diff options
Diffstat (limited to 'drivers/mtd/nand/raw/stm32_fmc2_nand.c')
-rw-r--r-- | drivers/mtd/nand/raw/stm32_fmc2_nand.c | 53 |
1 files changed, 45 insertions, 8 deletions
diff --git a/drivers/mtd/nand/raw/stm32_fmc2_nand.c b/drivers/mtd/nand/raw/stm32_fmc2_nand.c index 76609b908b5e..e02985c2bf9f 100644 --- a/drivers/mtd/nand/raw/stm32_fmc2_nand.c +++ b/drivers/mtd/nand/raw/stm32_fmc2_nand.c @@ -37,6 +37,9 @@ /* 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 */ #define FMC2_THIZ 1 #define FMC2_TIO 8000 @@ -51,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 @@ -116,6 +121,12 @@ #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) @@ -530,7 +541,8 @@ static int stm32_fmc2_ham_calculate(struct nand_chip *chip, const u8 *data, int ret; ret = readl_relaxed_poll_timeout(fmc2->io_base + FMC2_SR, - sr, sr & FMC2_SR_NWRF, 10, 1000); + sr, sr & FMC2_SR_NWRF, 10, + FMC2_TIMEOUT_MS); if (ret) { dev_err(fmc2->dev, "ham timeout\n"); return ret; @@ -611,7 +623,7 @@ static int stm32_fmc2_bch_calculate(struct nand_chip *chip, const u8 *data, /* Wait until the BCH code is ready */ if (!wait_for_completion_timeout(&fmc2->complete, - msecs_to_jiffies(1000))) { + msecs_to_jiffies(FMC2_TIMEOUT_MS))) { dev_err(fmc2->dev, "bch timeout\n"); stm32_fmc2_disable_bch_irq(fmc2); return -ETIMEDOUT; @@ -696,7 +708,7 @@ static int stm32_fmc2_bch_correct(struct nand_chip *chip, u8 *dat, /* Wait until the decoding error is ready */ if (!wait_for_completion_timeout(&fmc2->complete, - msecs_to_jiffies(1000))) { + msecs_to_jiffies(FMC2_TIMEOUT_MS))) { dev_err(fmc2->dev, "bch timeout\n"); stm32_fmc2_disable_bch_irq(fmc2); return -ETIMEDOUT; @@ -969,7 +981,7 @@ static int stm32_fmc2_xfer(struct nand_chip *chip, const u8 *buf, /* Wait end of sequencer transfer */ if (!wait_for_completion_timeout(&fmc2->complete, - msecs_to_jiffies(1000))) { + msecs_to_jiffies(FMC2_TIMEOUT_MS))) { dev_err(fmc2->dev, "seq timeout\n"); stm32_fmc2_disable_seq_irq(fmc2); dmaengine_terminate_all(dma_ch); @@ -981,7 +993,7 @@ static int stm32_fmc2_xfer(struct nand_chip *chip, const u8 *buf, /* Wait DMA data transfer completion */ if (!wait_for_completion_timeout(&fmc2->dma_data_complete, - msecs_to_jiffies(100))) { + msecs_to_jiffies(FMC2_TIMEOUT_MS))) { dev_err(fmc2->dev, "data DMA timeout\n"); dmaengine_terminate_all(dma_ch); ret = -ETIMEDOUT; @@ -990,7 +1002,7 @@ static int stm32_fmc2_xfer(struct nand_chip *chip, const u8 *buf, /* Wait DMA ECC transfer completion */ if (!write_data && !raw) { if (!wait_for_completion_timeout(&fmc2->dma_ecc_complete, - msecs_to_jiffies(100))) { + msecs_to_jiffies(FMC2_TIMEOUT_MS))) { dev_err(fmc2->dev, "ECC DMA timeout\n"); dmaengine_terminate_all(fmc2->dma_ecc_ch); ret = -ETIMEDOUT; @@ -1319,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) @@ -1363,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; } } |