From cac8c821059639b015586abf61623c62cc549a13 Mon Sep 17 00:00:00 2001 From: Tudor Ambarus Date: Mon, 7 Dec 2020 15:59:56 +0200 Subject: spi: atmel-quadspi: Fix AHB memory accesses Following error was seen when mounting a 16MByte ubifs: UBIFS error (ubi0:0 pid 1893): check_lpt_type.constprop.6: invalid type (15) in LPT node type QSPI_IFR.TFRTYP was not set correctly. When data transfer is enabled and one wants to access the serial memory through AHB in order to: - read in the serial memory, but not a memory data, for example a JEDEC-ID, QSPI_IFR.TFRTYP must be written to '0' (both sama5d2 and sam9x60). - read in the serial memory, and particularly a memory data, TFRTYP must be written to '1' (both sama5d2 and sam9x60). - write in the serial memory, but not a memory data, for example writing the configuration or the QSPI_SR, TFRTYP must be written to '2' for sama5d2 and to '0' for sam9x60. - write in the serial memory in particular to program a memory data, TFRTYP must be written to '3' for sama5d2 and to '1' for sam9x60. Fix the setting of the QSPI_IFR.TFRTYP field. Fixes: 2d30ac5ed633 ("mtd: spi-nor: atmel-quadspi: Use spi-mem interface for atmel-quadspi driver") Cc: # v5.0+ Reported-by: Tom Burkart Signed-off-by: Tudor Ambarus Link: https://lore.kernel.org/r/20201207135959.154124-2-tudor.ambarus@microchip.com Signed-off-by: Mark Brown --- drivers/spi/atmel-quadspi.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'drivers/spi/atmel-quadspi.c') diff --git a/drivers/spi/atmel-quadspi.c b/drivers/spi/atmel-quadspi.c index 8c009c175f2c..67ef98822366 100644 --- a/drivers/spi/atmel-quadspi.c +++ b/drivers/spi/atmel-quadspi.c @@ -365,10 +365,14 @@ static int atmel_qspi_set_cfg(struct atmel_qspi *aq, if (dummy_cycles) ifr |= QSPI_IFR_NBDUM(dummy_cycles); - /* Set data enable */ - if (op->data.nbytes) + /* Set data enable and data transfer type. */ + if (op->data.nbytes) { ifr |= QSPI_IFR_DATAEN; + if (op->addr.nbytes) + ifr |= QSPI_IFR_TFRTYP_MEM; + } + /* * If the QSPI controller is set in regular SPI mode, set it in * Serial Memory Mode (SMM). @@ -393,7 +397,7 @@ static int atmel_qspi_set_cfg(struct atmel_qspi *aq, atmel_qspi_write(icr, aq, QSPI_WICR); atmel_qspi_write(ifr, aq, QSPI_IFR); } else { - if (op->data.dir == SPI_MEM_DATA_OUT) + if (op->data.nbytes && op->data.dir == SPI_MEM_DATA_OUT) ifr |= QSPI_IFR_SAMA5D2_WRITE_TRSFR; /* Set QSPI Instruction Frame registers */ -- cgit From a6ff3a784ff9975dc77676827a2f448203511d19 Mon Sep 17 00:00:00 2001 From: Tudor Ambarus Date: Mon, 7 Dec 2020 15:59:57 +0200 Subject: spi: atmel-quadspi: Drop superfluous set of QSPI_IFR_APBTFRTYP_READ That bit describes the APB transfer type. We are writing serial memory registers via AHB acesses, that bit does not make sense in the current context. Signed-off-by: Tudor Ambarus Link: https://lore.kernel.org/r/20201207135959.154124-3-tudor.ambarus@microchip.com Signed-off-by: Mark Brown --- drivers/spi/atmel-quadspi.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers/spi/atmel-quadspi.c') diff --git a/drivers/spi/atmel-quadspi.c b/drivers/spi/atmel-quadspi.c index 67ef98822366..7fb302e4063d 100644 --- a/drivers/spi/atmel-quadspi.c +++ b/drivers/spi/atmel-quadspi.c @@ -386,9 +386,6 @@ static int atmel_qspi_set_cfg(struct atmel_qspi *aq, (void)atmel_qspi_read(aq, QSPI_SR); if (aq->caps->has_ricr) { - if (!op->addr.nbytes && op->data.dir == SPI_MEM_DATA_IN) - ifr |= QSPI_IFR_APBTFRTYP_READ; - /* Set QSPI Instruction Frame registers */ atmel_qspi_write(iar, aq, QSPI_IAR); if (op->data.dir == SPI_MEM_DATA_IN) -- cgit From d00364b6a60475cd75fd07e847ad6f955952638b Mon Sep 17 00:00:00 2001 From: Tudor Ambarus Date: Mon, 7 Dec 2020 15:59:58 +0200 Subject: spi: atmel-quadspi: Write QSPI_IAR only when needed The address must be written in QSPI_IAR only when we have a instruction frame with address but no data. Signed-off-by: Tudor Ambarus Link: https://lore.kernel.org/r/20201207135959.154124-4-tudor.ambarus@microchip.com Signed-off-by: Mark Brown --- drivers/spi/atmel-quadspi.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/spi/atmel-quadspi.c') diff --git a/drivers/spi/atmel-quadspi.c b/drivers/spi/atmel-quadspi.c index 7fb302e4063d..3a978ee8b70f 100644 --- a/drivers/spi/atmel-quadspi.c +++ b/drivers/spi/atmel-quadspi.c @@ -385,9 +385,11 @@ static int atmel_qspi_set_cfg(struct atmel_qspi *aq, /* Clear pending interrupts */ (void)atmel_qspi_read(aq, QSPI_SR); - if (aq->caps->has_ricr) { - /* Set QSPI Instruction Frame registers */ + /* Set QSPI Instruction Frame registers. */ + if (op->addr.nbytes && !op->data.nbytes) atmel_qspi_write(iar, aq, QSPI_IAR); + + if (aq->caps->has_ricr) { if (op->data.dir == SPI_MEM_DATA_IN) atmel_qspi_write(icr, aq, QSPI_RICR); else @@ -397,8 +399,6 @@ static int atmel_qspi_set_cfg(struct atmel_qspi *aq, if (op->data.nbytes && op->data.dir == SPI_MEM_DATA_OUT) ifr |= QSPI_IFR_SAMA5D2_WRITE_TRSFR; - /* Set QSPI Instruction Frame registers */ - atmel_qspi_write(iar, aq, QSPI_IAR); atmel_qspi_write(icr, aq, QSPI_ICR); atmel_qspi_write(ifr, aq, QSPI_IFR); } -- cgit From c066efb07d1e8b801ea9d0727119958c9904e63d Mon Sep 17 00:00:00 2001 From: Tudor Ambarus Date: Mon, 7 Dec 2020 15:59:59 +0200 Subject: spi: atmel-quadspi: Move common code outside of if else QSPI_IFR is set as the last QSPI Instruction Frame register regardless of the sama5d2 or sam9x60 version of the IP. Move the writing of QSPI_IFR outside of the IP specific code. Signed-off-by: Tudor Ambarus Link: https://lore.kernel.org/r/20201207135959.154124-5-tudor.ambarus@microchip.com Signed-off-by: Mark Brown --- drivers/spi/atmel-quadspi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/spi/atmel-quadspi.c') diff --git a/drivers/spi/atmel-quadspi.c b/drivers/spi/atmel-quadspi.c index 3a978ee8b70f..f56640d63982 100644 --- a/drivers/spi/atmel-quadspi.c +++ b/drivers/spi/atmel-quadspi.c @@ -394,15 +394,15 @@ static int atmel_qspi_set_cfg(struct atmel_qspi *aq, atmel_qspi_write(icr, aq, QSPI_RICR); else atmel_qspi_write(icr, aq, QSPI_WICR); - atmel_qspi_write(ifr, aq, QSPI_IFR); } else { if (op->data.nbytes && op->data.dir == SPI_MEM_DATA_OUT) ifr |= QSPI_IFR_SAMA5D2_WRITE_TRSFR; atmel_qspi_write(icr, aq, QSPI_ICR); - atmel_qspi_write(ifr, aq, QSPI_IFR); } + atmel_qspi_write(ifr, aq, QSPI_IFR); + return 0; } -- cgit