[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20211112143855.2678989-5-herve.codina@bootlin.com>
Date: Fri, 12 Nov 2021 15:38:55 +0100
From: Herve Codina <herve.codina@...tlin.com>
To: Miquel Raynal <miquel.raynal@...tlin.com>,
Richard Weinberger <richard@....at>,
Vignesh Raghavendra <vigneshr@...com>
Cc: linux-mtd@...ts.infradead.org, linux-kernel@...r.kernel.org,
Herve Codina <herve.codina@...tlin.com>,
Thomas Petazzoni <thomas.petazzoni@...tlin.com>
Subject: [PATCH 4/4] mtd: rawnand: fsmc: Fix timing computation
The timing setting were incorrect on some nands leading to a
fallback to mode 0 timing on some Micron nand or to incorrect
data reads on some Winbond NAND.
The timing computation did not take into account the following
constraint given in SPEAr3xx reference manual:
twait >= tCEA - tset*TCLK + TOUTDEL + TINDEL
This patch adds this constraint and fixes the issues on both
nands having the both nands working at mode 3 timing.
The change has no impact on slower timing mode such as mode 0.
Indeed, on mode 0 timing, computed values are the same with and
without the patch.
Signed-off-by: Herve Codina <herve.codina@...tlin.com>
---
drivers/mtd/nand/raw/fsmc_nand.c | 27 +++++++++++++++++++--------
1 file changed, 19 insertions(+), 8 deletions(-)
diff --git a/drivers/mtd/nand/raw/fsmc_nand.c b/drivers/mtd/nand/raw/fsmc_nand.c
index bff09219ce3a..a3aa66f30869 100644
--- a/drivers/mtd/nand/raw/fsmc_nand.c
+++ b/drivers/mtd/nand/raw/fsmc_nand.c
@@ -278,7 +278,7 @@ static int fsmc_calc_timings(struct fsmc_nand_data *host,
{
unsigned long hclk = clk_get_rate(host->clk);
unsigned long hclkn = NSEC_PER_SEC / hclk;
- u32 thiz, thold, twait, tset;
+ u32 thiz, thold, twait, tset, tmp;
if (sdrt->tRC_min < 30000)
return -EOPNOTSUPP;
@@ -310,13 +310,6 @@ static int fsmc_calc_timings(struct fsmc_nand_data *host,
else if (tims->thold > FSMC_THOLD_MASK)
tims->thold = FSMC_THOLD_MASK;
- twait = max(sdrt->tRP_min, sdrt->tWP_min);
- tims->twait = DIV_ROUND_UP(twait / 1000, hclkn) - 1;
- if (tims->twait == 0)
- tims->twait = 1;
- else if (tims->twait > FSMC_TWAIT_MASK)
- tims->twait = FSMC_TWAIT_MASK;
-
tset = max(sdrt->tCS_min - sdrt->tWP_min,
sdrt->tCEA_max - sdrt->tREA_max);
tims->tset = DIV_ROUND_UP(tset / 1000, hclkn) - 1;
@@ -325,6 +318,24 @@ static int fsmc_calc_timings(struct fsmc_nand_data *host,
else if (tims->tset > FSMC_TSET_MASK)
tims->tset = FSMC_TSET_MASK;
+ twait = max(sdrt->tRP_min, sdrt->tWP_min);
+
+ /* According to SPEAr300 Reference Manual (RM0082) which gives more
+ * information related to FSMSC timings than the SPEAr600 one (RM0305),
+ * twait >= tCEA - tset*TCLK + TOUTDEL + TINDEL
+ * With TOUTDEL = 7ns (Output delay from the flip-flops to the board)
+ * and TINDEL = 5ns (Input delay from the board to the flipflop)
+ */
+ tmp = sdrt->tCEA_max - (tims->tset + 1)*hclkn*1000 + 7000 + 5000;
+ if (twait < tmp)
+ twait = tmp;
+
+ tims->twait = DIV_ROUND_UP(twait / 1000, hclkn) - 1;
+ if (tims->twait == 0)
+ tims->twait = 1;
+ else if (tims->twait > FSMC_TWAIT_MASK)
+ tims->twait = FSMC_TWAIT_MASK;
+
return 0;
}
--
2.31.1
Powered by blists - more mailing lists