hc
2024-02-20 102a0743326a03cd1a1202ceda21e175b7d3575c
kernel/drivers/mtd/nand/raw/nand_timings.c
....@@ -1,27 +1,34 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * Copyright (C) 2014 Free Electrons
34 *
45 * Author: Boris BREZILLON <boris.brezillon@free-electrons.com>
5
- *
6
- * This program is free software; you can redistribute it and/or modify
7
- * it under the terms of the GNU General Public License version 2 as
8
- * published by the Free Software Foundation.
9
- *
106 */
117 #include <linux/kernel.h>
128 #include <linux/err.h>
139 #include <linux/export.h>
14
-#include <linux/mtd/rawnand.h>
10
+
11
+#include "internals.h"
1512
1613 #define ONFI_DYN_TIMING_MAX U16_MAX
1714
18
-static const struct nand_data_interface onfi_sdr_timings[] = {
15
+/*
16
+ * For non-ONFI chips we use the highest possible value for tPROG and tBERS.
17
+ * tR and tCCS will take the default values precised in the ONFI specification
18
+ * for timing mode 0, respectively 200us and 500ns.
19
+ *
20
+ * These four values are tweaked to be more accurate in the case of ONFI chips.
21
+ */
22
+static const struct nand_interface_config onfi_sdr_timings[] = {
1923 /* Mode 0 */
2024 {
2125 .type = NAND_SDR_IFACE,
26
+ .timings.mode = 0,
2227 .timings.sdr = {
2328 .tCCS_min = 500000,
2429 .tR_max = 200000000,
30
+ .tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
31
+ .tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
2532 .tADL_min = 400000,
2633 .tALH_min = 20000,
2734 .tALS_min = 50000,
....@@ -61,9 +68,12 @@
6168 /* Mode 1 */
6269 {
6370 .type = NAND_SDR_IFACE,
71
+ .timings.mode = 1,
6472 .timings.sdr = {
6573 .tCCS_min = 500000,
6674 .tR_max = 200000000,
75
+ .tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
76
+ .tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
6777 .tADL_min = 400000,
6878 .tALH_min = 10000,
6979 .tALS_min = 25000,
....@@ -103,9 +113,12 @@
103113 /* Mode 2 */
104114 {
105115 .type = NAND_SDR_IFACE,
116
+ .timings.mode = 2,
106117 .timings.sdr = {
107118 .tCCS_min = 500000,
108119 .tR_max = 200000000,
120
+ .tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
121
+ .tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
109122 .tADL_min = 400000,
110123 .tALH_min = 10000,
111124 .tALS_min = 15000,
....@@ -145,9 +158,12 @@
145158 /* Mode 3 */
146159 {
147160 .type = NAND_SDR_IFACE,
161
+ .timings.mode = 3,
148162 .timings.sdr = {
149163 .tCCS_min = 500000,
150164 .tR_max = 200000000,
165
+ .tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
166
+ .tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
151167 .tADL_min = 400000,
152168 .tALH_min = 5000,
153169 .tALS_min = 10000,
....@@ -187,9 +203,12 @@
187203 /* Mode 4 */
188204 {
189205 .type = NAND_SDR_IFACE,
206
+ .timings.mode = 4,
190207 .timings.sdr = {
191208 .tCCS_min = 500000,
192209 .tR_max = 200000000,
210
+ .tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
211
+ .tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
193212 .tADL_min = 400000,
194213 .tALH_min = 5000,
195214 .tALS_min = 10000,
....@@ -229,9 +248,12 @@
229248 /* Mode 5 */
230249 {
231250 .type = NAND_SDR_IFACE,
251
+ .timings.mode = 5,
232252 .timings.sdr = {
233253 .tCCS_min = 500000,
234254 .tR_max = 200000000,
255
+ .tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
256
+ .tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
235257 .tADL_min = 400000,
236258 .tALH_min = 5000,
237259 .tALS_min = 10000,
....@@ -270,37 +292,334 @@
270292 },
271293 };
272294
273
-/**
274
- * onfi_async_timing_mode_to_sdr_timings - [NAND Interface] Retrieve NAND
275
- * timings according to the given ONFI timing mode
276
- * @mode: ONFI timing mode
277
- */
278
-const struct nand_sdr_timings *onfi_async_timing_mode_to_sdr_timings(int mode)
279
-{
280
- if (mode < 0 || mode >= ARRAY_SIZE(onfi_sdr_timings))
281
- return ERR_PTR(-EINVAL);
295
+static const struct nand_interface_config onfi_nvddr_timings[] = {
296
+ /* Mode 0 */
297
+ {
298
+ .type = NAND_NVDDR_IFACE,
299
+ .timings.mode = 0,
300
+ .timings.nvddr = {
301
+ .tCCS_min = 500000,
302
+ .tR_max = 200000000,
303
+ .tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
304
+ .tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
305
+ .tAC_min = 3000,
306
+ .tAC_max = 25000,
307
+ .tADL_min = 400000,
308
+ .tCAD_min = 45000,
309
+ .tCAH_min = 10000,
310
+ .tCALH_min = 10000,
311
+ .tCALS_min = 10000,
312
+ .tCAS_min = 10000,
313
+ .tCEH_min = 20000,
314
+ .tCH_min = 10000,
315
+ .tCK_min = 50000,
316
+ .tCS_min = 35000,
317
+ .tDH_min = 5000,
318
+ .tDQSCK_min = 3000,
319
+ .tDQSCK_max = 25000,
320
+ .tDQSD_min = 0,
321
+ .tDQSD_max = 18000,
322
+ .tDQSHZ_max = 20000,
323
+ .tDQSQ_max = 5000,
324
+ .tDS_min = 5000,
325
+ .tDSC_min = 50000,
326
+ .tFEAT_max = 1000000,
327
+ .tITC_max = 1000000,
328
+ .tQHS_max = 6000,
329
+ .tRHW_min = 100000,
330
+ .tRR_min = 20000,
331
+ .tRST_max = 500000000,
332
+ .tWB_max = 100000,
333
+ .tWHR_min = 80000,
334
+ .tWRCK_min = 20000,
335
+ .tWW_min = 100000,
336
+ },
337
+ },
338
+ /* Mode 1 */
339
+ {
340
+ .type = NAND_NVDDR_IFACE,
341
+ .timings.mode = 1,
342
+ .timings.nvddr = {
343
+ .tCCS_min = 500000,
344
+ .tR_max = 200000000,
345
+ .tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
346
+ .tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
347
+ .tAC_min = 3000,
348
+ .tAC_max = 25000,
349
+ .tADL_min = 400000,
350
+ .tCAD_min = 45000,
351
+ .tCAH_min = 5000,
352
+ .tCALH_min = 5000,
353
+ .tCALS_min = 5000,
354
+ .tCAS_min = 5000,
355
+ .tCEH_min = 20000,
356
+ .tCH_min = 5000,
357
+ .tCK_min = 30000,
358
+ .tCS_min = 25000,
359
+ .tDH_min = 2500,
360
+ .tDQSCK_min = 3000,
361
+ .tDQSCK_max = 25000,
362
+ .tDQSD_min = 0,
363
+ .tDQSD_max = 18000,
364
+ .tDQSHZ_max = 20000,
365
+ .tDQSQ_max = 2500,
366
+ .tDS_min = 3000,
367
+ .tDSC_min = 30000,
368
+ .tFEAT_max = 1000000,
369
+ .tITC_max = 1000000,
370
+ .tQHS_max = 3000,
371
+ .tRHW_min = 100000,
372
+ .tRR_min = 20000,
373
+ .tRST_max = 500000000,
374
+ .tWB_max = 100000,
375
+ .tWHR_min = 80000,
376
+ .tWRCK_min = 20000,
377
+ .tWW_min = 100000,
378
+ },
379
+ },
380
+ /* Mode 2 */
381
+ {
382
+ .type = NAND_NVDDR_IFACE,
383
+ .timings.mode = 2,
384
+ .timings.nvddr = {
385
+ .tCCS_min = 500000,
386
+ .tR_max = 200000000,
387
+ .tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
388
+ .tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
389
+ .tAC_min = 3000,
390
+ .tAC_max = 25000,
391
+ .tADL_min = 400000,
392
+ .tCAD_min = 45000,
393
+ .tCAH_min = 4000,
394
+ .tCALH_min = 4000,
395
+ .tCALS_min = 4000,
396
+ .tCAS_min = 4000,
397
+ .tCEH_min = 20000,
398
+ .tCH_min = 4000,
399
+ .tCK_min = 20000,
400
+ .tCS_min = 15000,
401
+ .tDH_min = 1700,
402
+ .tDQSCK_min = 3000,
403
+ .tDQSCK_max = 25000,
404
+ .tDQSD_min = 0,
405
+ .tDQSD_max = 18000,
406
+ .tDQSHZ_max = 20000,
407
+ .tDQSQ_max = 1700,
408
+ .tDS_min = 2000,
409
+ .tDSC_min = 20000,
410
+ .tFEAT_max = 1000000,
411
+ .tITC_max = 1000000,
412
+ .tQHS_max = 2000,
413
+ .tRHW_min = 100000,
414
+ .tRR_min = 20000,
415
+ .tRST_max = 500000000,
416
+ .tWB_max = 100000,
417
+ .tWHR_min = 80000,
418
+ .tWRCK_min = 20000,
419
+ .tWW_min = 100000,
420
+ },
421
+ },
422
+ /* Mode 3 */
423
+ {
424
+ .type = NAND_NVDDR_IFACE,
425
+ .timings.mode = 3,
426
+ .timings.nvddr = {
427
+ .tCCS_min = 500000,
428
+ .tR_max = 200000000,
429
+ .tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
430
+ .tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
431
+ .tAC_min = 3000,
432
+ .tAC_max = 25000,
433
+ .tADL_min = 400000,
434
+ .tCAD_min = 45000,
435
+ .tCAH_min = 3000,
436
+ .tCALH_min = 3000,
437
+ .tCALS_min = 3000,
438
+ .tCAS_min = 3000,
439
+ .tCEH_min = 20000,
440
+ .tCH_min = 3000,
441
+ .tCK_min = 15000,
442
+ .tCS_min = 15000,
443
+ .tDH_min = 1300,
444
+ .tDQSCK_min = 3000,
445
+ .tDQSCK_max = 25000,
446
+ .tDQSD_min = 0,
447
+ .tDQSD_max = 18000,
448
+ .tDQSHZ_max = 20000,
449
+ .tDQSQ_max = 1300,
450
+ .tDS_min = 1500,
451
+ .tDSC_min = 15000,
452
+ .tFEAT_max = 1000000,
453
+ .tITC_max = 1000000,
454
+ .tQHS_max = 1500,
455
+ .tRHW_min = 100000,
456
+ .tRR_min = 20000,
457
+ .tRST_max = 500000000,
458
+ .tWB_max = 100000,
459
+ .tWHR_min = 80000,
460
+ .tWRCK_min = 20000,
461
+ .tWW_min = 100000,
462
+ },
463
+ },
464
+ /* Mode 4 */
465
+ {
466
+ .type = NAND_NVDDR_IFACE,
467
+ .timings.mode = 4,
468
+ .timings.nvddr = {
469
+ .tCCS_min = 500000,
470
+ .tR_max = 200000000,
471
+ .tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
472
+ .tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
473
+ .tAC_min = 3000,
474
+ .tAC_max = 25000,
475
+ .tADL_min = 400000,
476
+ .tCAD_min = 45000,
477
+ .tCAH_min = 2500,
478
+ .tCALH_min = 2500,
479
+ .tCALS_min = 2500,
480
+ .tCAS_min = 2500,
481
+ .tCEH_min = 20000,
482
+ .tCH_min = 2500,
483
+ .tCK_min = 12000,
484
+ .tCS_min = 15000,
485
+ .tDH_min = 1100,
486
+ .tDQSCK_min = 3000,
487
+ .tDQSCK_max = 25000,
488
+ .tDQSD_min = 0,
489
+ .tDQSD_max = 18000,
490
+ .tDQSHZ_max = 20000,
491
+ .tDQSQ_max = 1000,
492
+ .tDS_min = 1100,
493
+ .tDSC_min = 12000,
494
+ .tFEAT_max = 1000000,
495
+ .tITC_max = 1000000,
496
+ .tQHS_max = 1200,
497
+ .tRHW_min = 100000,
498
+ .tRR_min = 20000,
499
+ .tRST_max = 500000000,
500
+ .tWB_max = 100000,
501
+ .tWHR_min = 80000,
502
+ .tWRCK_min = 20000,
503
+ .tWW_min = 100000,
504
+ },
505
+ },
506
+ /* Mode 5 */
507
+ {
508
+ .type = NAND_NVDDR_IFACE,
509
+ .timings.mode = 5,
510
+ .timings.nvddr = {
511
+ .tCCS_min = 500000,
512
+ .tR_max = 200000000,
513
+ .tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
514
+ .tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
515
+ .tAC_min = 3000,
516
+ .tAC_max = 25000,
517
+ .tADL_min = 400000,
518
+ .tCAD_min = 45000,
519
+ .tCAH_min = 2000,
520
+ .tCALH_min = 2000,
521
+ .tCALS_min = 2000,
522
+ .tCAS_min = 2000,
523
+ .tCEH_min = 20000,
524
+ .tCH_min = 2000,
525
+ .tCK_min = 10000,
526
+ .tCS_min = 15000,
527
+ .tDH_min = 900,
528
+ .tDQSCK_min = 3000,
529
+ .tDQSCK_max = 25000,
530
+ .tDQSD_min = 0,
531
+ .tDQSD_max = 18000,
532
+ .tDQSHZ_max = 20000,
533
+ .tDQSQ_max = 850,
534
+ .tDS_min = 900,
535
+ .tDSC_min = 10000,
536
+ .tFEAT_max = 1000000,
537
+ .tITC_max = 1000000,
538
+ .tQHS_max = 1000,
539
+ .tRHW_min = 100000,
540
+ .tRR_min = 20000,
541
+ .tRST_max = 500000000,
542
+ .tWB_max = 100000,
543
+ .tWHR_min = 80000,
544
+ .tWRCK_min = 20000,
545
+ .tWW_min = 100000,
546
+ },
547
+ },
548
+};
282549
283
- return &onfi_sdr_timings[mode].timings.sdr;
550
+/* All NAND chips share the same reset data interface: SDR mode 0 */
551
+const struct nand_interface_config *nand_get_reset_interface_config(void)
552
+{
553
+ return &onfi_sdr_timings[0];
284554 }
285
-EXPORT_SYMBOL(onfi_async_timing_mode_to_sdr_timings);
286555
287556 /**
288
- * onfi_fill_data_interface - [NAND Interface] Initialize a data interface from
289
- * given ONFI mode
290
- * @mode: The ONFI timing mode
557
+ * onfi_find_closest_sdr_mode - Derive the closest ONFI SDR timing mode given a
558
+ * set of timings
559
+ * @spec_timings: the timings to challenge
291560 */
292
-int onfi_fill_data_interface(struct nand_chip *chip,
293
- enum nand_data_interface_type type,
294
- int timing_mode)
561
+unsigned int
562
+onfi_find_closest_sdr_mode(const struct nand_sdr_timings *spec_timings)
295563 {
296
- struct nand_data_interface *iface = &chip->data_interface;
564
+ const struct nand_sdr_timings *onfi_timings;
565
+ int mode;
566
+
567
+ for (mode = ARRAY_SIZE(onfi_sdr_timings) - 1; mode > 0; mode--) {
568
+ onfi_timings = &onfi_sdr_timings[mode].timings.sdr;
569
+
570
+ if (spec_timings->tCCS_min <= onfi_timings->tCCS_min &&
571
+ spec_timings->tADL_min <= onfi_timings->tADL_min &&
572
+ spec_timings->tALH_min <= onfi_timings->tALH_min &&
573
+ spec_timings->tALS_min <= onfi_timings->tALS_min &&
574
+ spec_timings->tAR_min <= onfi_timings->tAR_min &&
575
+ spec_timings->tCEH_min <= onfi_timings->tCEH_min &&
576
+ spec_timings->tCH_min <= onfi_timings->tCH_min &&
577
+ spec_timings->tCLH_min <= onfi_timings->tCLH_min &&
578
+ spec_timings->tCLR_min <= onfi_timings->tCLR_min &&
579
+ spec_timings->tCLS_min <= onfi_timings->tCLS_min &&
580
+ spec_timings->tCOH_min <= onfi_timings->tCOH_min &&
581
+ spec_timings->tCS_min <= onfi_timings->tCS_min &&
582
+ spec_timings->tDH_min <= onfi_timings->tDH_min &&
583
+ spec_timings->tDS_min <= onfi_timings->tDS_min &&
584
+ spec_timings->tIR_min <= onfi_timings->tIR_min &&
585
+ spec_timings->tRC_min <= onfi_timings->tRC_min &&
586
+ spec_timings->tREH_min <= onfi_timings->tREH_min &&
587
+ spec_timings->tRHOH_min <= onfi_timings->tRHOH_min &&
588
+ spec_timings->tRHW_min <= onfi_timings->tRHW_min &&
589
+ spec_timings->tRLOH_min <= onfi_timings->tRLOH_min &&
590
+ spec_timings->tRP_min <= onfi_timings->tRP_min &&
591
+ spec_timings->tRR_min <= onfi_timings->tRR_min &&
592
+ spec_timings->tWC_min <= onfi_timings->tWC_min &&
593
+ spec_timings->tWH_min <= onfi_timings->tWH_min &&
594
+ spec_timings->tWHR_min <= onfi_timings->tWHR_min &&
595
+ spec_timings->tWP_min <= onfi_timings->tWP_min &&
596
+ spec_timings->tWW_min <= onfi_timings->tWW_min)
597
+ return mode;
598
+ }
599
+
600
+ return 0;
601
+}
602
+
603
+/**
604
+ * onfi_fill_interface_config - Initialize an interface config from a given
605
+ * ONFI mode
606
+ * @chip: The NAND chip
607
+ * @iface: The interface configuration to fill
608
+ * @type: The interface type
609
+ * @timing_mode: The ONFI timing mode
610
+ */
611
+void onfi_fill_interface_config(struct nand_chip *chip,
612
+ struct nand_interface_config *iface,
613
+ enum nand_interface_type type,
614
+ unsigned int timing_mode)
615
+{
297616 struct onfi_params *onfi = chip->parameters.onfi;
298617
299
- if (type != NAND_SDR_IFACE)
300
- return -EINVAL;
618
+ if (WARN_ON(type != NAND_SDR_IFACE))
619
+ return;
301620
302
- if (timing_mode < 0 || timing_mode >= ARRAY_SIZE(onfi_sdr_timings))
303
- return -EINVAL;
621
+ if (WARN_ON(timing_mode >= ARRAY_SIZE(onfi_sdr_timings)))
622
+ return;
304623
305624 *iface = onfi_sdr_timings[timing_mode];
306625
....@@ -319,23 +638,5 @@
319638
320639 /* nanoseconds -> picoseconds */
321640 timings->tCCS_min = 1000UL * onfi->tCCS;
322
- } else {
323
- struct nand_sdr_timings *timings = &iface->timings.sdr;
324
- /*
325
- * For non-ONFI chips we use the highest possible value for
326
- * tPROG and tBERS. tR and tCCS will take the default values
327
- * precised in the ONFI specification for timing mode 0,
328
- * respectively 200us and 500ns.
329
- */
330
-
331
- /* microseconds -> picoseconds */
332
- timings->tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX;
333
- timings->tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX;
334
-
335
- timings->tR_max = 200000000;
336
- timings->tCCS_min = 500000;
337641 }
338
-
339
- return 0;
340642 }
341
-EXPORT_SYMBOL(onfi_fill_data_interface);