Skip to content

Commit 9472335

Browse files
hcodinamiquelraynal
authored andcommitted
mtd: rawnand: fsmc: Fix timing computation
Under certain circumstances, the timing settings calculated by the FSMC NAND controller driver were inaccurate. These settings led to incorrect data reads or fallback to timing mode 0 depending on the NAND chip used. The timing computation did not take into account the following constraint given in SPEAr3xx reference manual: twait >= tCEA - (tset * TCLK) + TOUTDEL + TINDEL Enhance the timings calculation by taking into account this additional constraint. This change has no impact on slow timing modes such as mode 0. Indeed, on mode 0, computed values are the same with and without the patch. NANDs which previously stayed in mode 0 because of fallback to mode 0 can now work at higher speeds and NANDs which were not working at all because of the corrupted data work at high speeds without troubles. Overall improvement on a Micron/MT29F1G08 (flash_speed tool): mode0 mode3 eraseblock write speed 3220 KiB/s 4511 KiB/s eraseblock read speed 4491 KiB/s 7529 KiB/s Fixes: d9fb079 ("mtd: nand: fsmc: add support for SDR timings") Signed-off-by: Herve Codina <[email protected]> Signed-off-by: Miquel Raynal <[email protected]> Link: https://lore.kernel.org/linux-mtd/[email protected]
1 parent a4ca0c4 commit 9472335

File tree

1 file changed

+24
-8
lines changed

1 file changed

+24
-8
lines changed

drivers/mtd/nand/raw/fsmc_nand.c

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,14 @@
9494

9595
#define FSMC_BUSY_WAIT_TIMEOUT (1 * HZ)
9696

97+
/*
98+
* According to SPEAr300 Reference Manual (RM0082)
99+
* TOUDEL = 7ns (Output delay from the flip-flops to the board)
100+
* TINDEL = 5ns (Input delay from the board to the flipflop)
101+
*/
102+
#define TOUTDEL 7000
103+
#define TINDEL 5000
104+
97105
struct fsmc_nand_timings {
98106
u8 tclr;
99107
u8 tar;
@@ -278,7 +286,7 @@ static int fsmc_calc_timings(struct fsmc_nand_data *host,
278286
{
279287
unsigned long hclk = clk_get_rate(host->clk);
280288
unsigned long hclkn = NSEC_PER_SEC / hclk;
281-
u32 thiz, thold, twait, tset;
289+
u32 thiz, thold, twait, tset, twait_min;
282290

283291
if (sdrt->tRC_min < 30000)
284292
return -EOPNOTSUPP;
@@ -310,13 +318,6 @@ static int fsmc_calc_timings(struct fsmc_nand_data *host,
310318
else if (tims->thold > FSMC_THOLD_MASK)
311319
tims->thold = FSMC_THOLD_MASK;
312320

313-
twait = max(sdrt->tRP_min, sdrt->tWP_min);
314-
tims->twait = DIV_ROUND_UP(twait / 1000, hclkn) - 1;
315-
if (tims->twait == 0)
316-
tims->twait = 1;
317-
else if (tims->twait > FSMC_TWAIT_MASK)
318-
tims->twait = FSMC_TWAIT_MASK;
319-
320321
tset = max(sdrt->tCS_min - sdrt->tWP_min,
321322
sdrt->tCEA_max - sdrt->tREA_max);
322323
tims->tset = DIV_ROUND_UP(tset / 1000, hclkn) - 1;
@@ -325,6 +326,21 @@ static int fsmc_calc_timings(struct fsmc_nand_data *host,
325326
else if (tims->tset > FSMC_TSET_MASK)
326327
tims->tset = FSMC_TSET_MASK;
327328

329+
/*
330+
* According to SPEAr300 Reference Manual (RM0082) which gives more
331+
* information related to FSMSC timings than the SPEAr600 one (RM0305),
332+
* twait >= tCEA - (tset * TCLK) + TOUTDEL + TINDEL
333+
*/
334+
twait_min = sdrt->tCEA_max - ((tims->tset + 1) * hclkn * 1000)
335+
+ TOUTDEL + TINDEL;
336+
twait = max3(sdrt->tRP_min, sdrt->tWP_min, twait_min);
337+
338+
tims->twait = DIV_ROUND_UP(twait / 1000, hclkn) - 1;
339+
if (tims->twait == 0)
340+
tims->twait = 1;
341+
else if (tims->twait > FSMC_TWAIT_MASK)
342+
tims->twait = FSMC_TWAIT_MASK;
343+
328344
return 0;
329345
}
330346

0 commit comments

Comments
 (0)