mbox series

[0/9] Improve support for AMD SPI controllers

Message ID 20210824104041.708945-1-tanureal@opensource.cirrus.com
Headers show
Series Improve support for AMD SPI controllers | expand

Message

Lucas tanure Aug. 24, 2021, 10:40 a.m. UTC
Add support for AMDI0062 and overcome the fact that the
controller can't hold the chip select activated between
transfers.

AMD SPI controller starts the SPI transfer by copying a
special byte called opcode into the bus, followed by the
TX register bytes from the FIFO into the bus.
If the RX register is not zero, it will copy RX bytes
from the bus to the FIFO.

Rules:
 - It must have an opcode set, which can be the first
byte from the writing part
 - The writing part of the FIFO always goes first
 - It's not full duplex, it writes TX bytes and then
reads RX bytes into the FIFO
 - Write and Read share the same FIFO. If the transfer
needs to write N bytes, it will only be able to read
(70 - N) bytes.
 - The chip select can only be activated during that
transaction. If a second transfer rely on the address
written during a previous transfer, it needs to write
an updated address, or it will fail, as the device in
the SPI bus will not understand a read without an
address as the chip select was not held between transfers.

So, when the regmap splits a write to an address or read from
an address into 2 separated transfers inside one message the
AMD SPI driver needs to merge them back into a single one.
Also it needs to be sure that the of bytes to read|write is
a little less so the address can fit into the FIFO.

Lucas Tanure (9):
  regmap: spi: Set regmap max raw r/w from max_transfer_size
  spi: core: Add flag for controllers that can't hold cs between
    transfers
  regmap: spi: SPI_CONTROLLER_CS_PER_TRANSFER affects max read/write
  spi: amd: Refactor code to use less spi_master_get_devdata
  spi: amd: Refactor amd_spi_busy_wait to use readl_poll_timeout
  spi: amd: Remove uneeded variable
  spi: amd: Check for idle bus before execute opcode
  spi: amd: Refactor to overcome 70 bytes per CS limitation
  spi: amd: Add support for latest platform

 drivers/base/regmap/regmap-spi.c |  44 +++-
 drivers/base/regmap/regmap.c     |   9 +
 drivers/spi/spi-amd.c            | 415 ++++++++++++++++++++-----------
 include/linux/regmap.h           |   2 +
 include/linux/spi/spi.h          |   1 +
 5 files changed, 315 insertions(+), 156 deletions(-)

Comments

Mark Brown Aug. 24, 2021, 4:42 p.m. UTC | #1
On Tue, Aug 24, 2021 at 11:40:33AM +0100, Lucas Tanure wrote:

> +	if (master->max_transfer_size) {
> +		bus = kmemdup(&regmap_spi, sizeof(*bus), GFP_KERNEL);

We shouldn't be peering into the controller structure, use
spi_max_transfer_size() instead.

> +		bus->max_raw_read = bus->max_raw_write = master->max_transfer_size(spi);

Just write two assignment statements, it's more legible all round.
Mark Brown Aug. 24, 2021, 4:49 p.m. UTC | #2
On Tue, Aug 24, 2021 at 11:40:39AM +0100, Lucas Tanure wrote:
> Check if the bus is not in use before starting the transfer
> Also wait after so the READ bytes in the FIFO are ready to
> be copied

This means that we will wait for read to be ready even for write only
operations, as opposed to potentially just absorbing the delay while the
CPU does other stuff.  If we need to wait prior to reading we should do
that in the relevant code.