Skip to content

Commit

Permalink
spi: armada-3700: Fix failing commands with quad-SPI
Browse files Browse the repository at this point in the history
A3700 SPI controller datasheet states that only the first line (IO0) is
used to receive and send instructions, addresses and dummy bytes,
unless for addresses during an RX operation in a quad SPI configuration
(see p.821 of the Armada-3720-DB datasheet). Otherwise, some commands
such as SPI NOR commands like READ_FROM_CACHE_DUAL_IO(0xeb) and
READ_FROM_CACHE_DUAL_IO(0xbb) will fail because these commands must send
address bytes through the four pins. Data transfer always use the four
bytes with this setup.

Thus, in quad SPI configuration, the A3700_SPI_ADDR_PIN bit must be set
only in this case to inform the controller that it must use the number
of pins indicated in the {A3700_SPI_DATA_PIN1,A3700_SPI_DATA_PIN0} field
during the address cycles of an RX operation.

Suggested-by: Ken Ma <make@marvell.com>
Signed-off-by: Miquel Raynal <miquel.raynal@free-electrons.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
Cc: stable@vger.kernel.org
  • Loading branch information
Miquel Raynal authored and Mark Brown committed Sep 13, 2017
1 parent ecb478b commit 747e1f6
Showing 1 changed file with 5 additions and 2 deletions.
7 changes: 5 additions & 2 deletions drivers/spi/spi-armada-3700.c
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ static void a3700_spi_deactivate_cs(struct a3700_spi *a3700_spi,
}

static int a3700_spi_pin_mode_set(struct a3700_spi *a3700_spi,
unsigned int pin_mode)
unsigned int pin_mode, bool receiving)
{
u32 val;

Expand All @@ -177,6 +177,9 @@ static int a3700_spi_pin_mode_set(struct a3700_spi *a3700_spi,
break;
case SPI_NBITS_QUAD:
val |= A3700_SPI_DATA_PIN1;
/* RX during address reception uses 4-pin */
if (receiving)
val |= A3700_SPI_ADDR_PIN;
break;
default:
dev_err(&a3700_spi->master->dev, "wrong pin mode %u", pin_mode);
Expand Down Expand Up @@ -653,7 +656,7 @@ static int a3700_spi_transfer_one(struct spi_master *master,
else if (xfer->rx_buf)
nbits = xfer->rx_nbits;

a3700_spi_pin_mode_set(a3700_spi, nbits);
a3700_spi_pin_mode_set(a3700_spi, nbits, xfer->rx_buf ? true : false);

if (xfer->rx_buf) {
/* Set read data length */
Expand Down

0 comments on commit 747e1f6

Please sign in to comment.