mtd: rawnand: stm32_fmc2: avoid to lock the CPU bus
authorChristophe Kerello <christophe.kerello@st.com>
Mon, 16 Dec 2019 09:01:55 +0000 (10:01 +0100)
committerMiquel Raynal <miquel.raynal@bootlin.com>
Thu, 9 Jan 2020 19:03:41 +0000 (20:03 +0100)
We are currently using nand_soft_waitrdy to poll the status of the NAND
flash. FMC2 enables the wait feature bit (this feature is mandatory for
the sequencer mode). By enabling this feature, we can't poll the status
of the NAND flash, the read status command is stucked in FMC2 pipeline
until R/B# signal is high, and locks the CPU bus.
To avoid to lock the CPU bus, we poll FMC2 ISR register. This register
reports the status of the R/B# signal.

Fixes: 2cd457f328c1 ("mtd: rawnand: stm32_fmc2: add STM32 FMC2 NAND flash controller driver")
Signed-off-by: Christophe Kerello <christophe.kerello@st.com>
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
drivers/mtd/nand/raw/stm32_fmc2_nand.c

index 9e63800..3ba73f1 100644 (file)
@@ -37,6 +37,7 @@
 /* Max ECC buffer length */
 #define FMC2_MAX_ECC_BUF_LEN           (FMC2_BCHDSRS_LEN * FMC2_MAX_SG)
 
+#define FMC2_TIMEOUT_US                        1000
 #define FMC2_TIMEOUT_MS                        1000
 
 /* Timings */
@@ -53,6 +54,8 @@
 #define FMC2_PMEM                      0x88
 #define FMC2_PATT                      0x8c
 #define FMC2_HECCR                     0x94
+#define FMC2_ISR                       0x184
+#define FMC2_ICR                       0x188
 #define FMC2_CSQCR                     0x200
 #define FMC2_CSQCFGR1                  0x204
 #define FMC2_CSQCFGR2                  0x208
 #define FMC2_PATT_ATTHIZ(x)            (((x) & 0xff) << 24)
 #define FMC2_PATT_DEFAULT              0x0a0a0a0a
 
+/* Register: FMC2_ISR */
+#define FMC2_ISR_IHLF                  BIT(1)
+
+/* Register: FMC2_ICR */
+#define FMC2_ICR_CIHLF                 BIT(1)
+
 /* Register: FMC2_CSQCR */
 #define FMC2_CSQCR_CSQSTART            BIT(0)
 
@@ -1322,6 +1331,31 @@ static void stm32_fmc2_write_data(struct nand_chip *chip, const void *buf,
                stm32_fmc2_set_buswidth_16(fmc2, true);
 }
 
+static int stm32_fmc2_waitrdy(struct nand_chip *chip, unsigned long timeout_ms)
+{
+       struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
+       const struct nand_sdr_timings *timings;
+       u32 isr, sr;
+
+       /* Check if there is no pending requests to the NAND flash */
+       if (readl_relaxed_poll_timeout_atomic(fmc2->io_base + FMC2_SR, sr,
+                                             sr & FMC2_SR_NWRF, 1,
+                                             FMC2_TIMEOUT_US))
+               dev_warn(fmc2->dev, "Waitrdy timeout\n");
+
+       /* Wait tWB before R/B# signal is low */
+       timings = nand_get_sdr_timings(&chip->data_interface);
+       ndelay(PSEC_TO_NSEC(timings->tWB_max));
+
+       /* R/B# signal is low, clear high level flag */
+       writel_relaxed(FMC2_ICR_CIHLF, fmc2->io_base + FMC2_ICR);
+
+       /* Wait R/B# signal is high */
+       return readl_relaxed_poll_timeout_atomic(fmc2->io_base + FMC2_ISR,
+                                                isr, isr & FMC2_ISR_IHLF,
+                                                5, 1000 * timeout_ms);
+}
+
 static int stm32_fmc2_exec_op(struct nand_chip *chip,
                              const struct nand_operation *op,
                              bool check_only)
@@ -1366,8 +1400,8 @@ static int stm32_fmc2_exec_op(struct nand_chip *chip,
                        break;
 
                case NAND_OP_WAITRDY_INSTR:
-                       ret = nand_soft_waitrdy(chip,
-                                               instr->ctx.waitrdy.timeout_ms);
+                       ret = stm32_fmc2_waitrdy(chip,
+                                                instr->ctx.waitrdy.timeout_ms);
                        break;
                }
        }