Commit 5a1314fa authored by Ricardo Ribalda's avatar Ricardo Ribalda Committed by Mark Brown

spi: xilinx: Detect stall with Unknown commands

When the core is configured in C_SPI_MODE > 0, it integrates a
lookup table that automatically configures the core in dual or quad mode
based on the command (first byte on the tx fifo).

Unfortunately, that list mode_?_memoy_*.mif does not contain all the
supported commands by the flash.

Since 4.14 spi-nor automatically tries to probe the flash using SFDP
(command 0x5a), and that command is not part of the list_mode table.

Whit the right combination of C_SPI_MODE and C_SPI_MEMORY this leads
into a stall that can only be recovered with a soft rest.

This patch detects this kind of stall and returns -EIO to the caller on
those commands. spi-nor can handle this error properly:

m25p80 spi0.0: Detected stall. Check C_SPI_MODE and C_SPI_MEMORY. 0x21 0x2404
m25p80 spi0.0: SPI transfer failed: -5
spi_master spi0: failed to transfer one message from queue
m25p80 spi0.0: s25sl064p (8192 Kbytes)
Signed-off-by: default avatarRicardo Ribalda Delgado <ricardo.ribalda@gmail.com>
Signed-off-by: default avatarMark Brown <broonie@kernel.org>
Cc: stable@vger.kernel.org
parent abbdb5ce
...@@ -271,6 +271,7 @@ static int xilinx_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t) ...@@ -271,6 +271,7 @@ static int xilinx_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t)
while (remaining_words) { while (remaining_words) {
int n_words, tx_words, rx_words; int n_words, tx_words, rx_words;
u32 sr; u32 sr;
int stalled;
n_words = min(remaining_words, xspi->buffer_size); n_words = min(remaining_words, xspi->buffer_size);
...@@ -299,7 +300,17 @@ static int xilinx_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t) ...@@ -299,7 +300,17 @@ static int xilinx_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t)
/* Read out all the data from the Rx FIFO */ /* Read out all the data from the Rx FIFO */
rx_words = n_words; rx_words = n_words;
stalled = 10;
while (rx_words) { while (rx_words) {
if (rx_words == n_words && !(stalled--) &&
!(sr & XSPI_SR_TX_EMPTY_MASK) &&
(sr & XSPI_SR_RX_EMPTY_MASK)) {
dev_err(&spi->dev,
"Detected stall. Check C_SPI_MODE and C_SPI_MEMORY\n");
xspi_init_hw(xspi);
return -EIO;
}
if ((sr & XSPI_SR_TX_EMPTY_MASK) && (rx_words > 1)) { if ((sr & XSPI_SR_TX_EMPTY_MASK) && (rx_words > 1)) {
xilinx_spi_rx(xspi); xilinx_spi_rx(xspi);
rx_words--; rx_words--;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment