1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * Copyright (C) 2014 Free Electrons
4 *
5 * Author: Boris BREZILLON <boris.brezillon@free-electrons.com>
6 */
7#include <linux/kernel.h>
8#include <linux/err.h>
9#include <linux/export.h>
10
11#include "internals.h"
12
13#define ONFI_DYN_TIMING_MAX U16_MAX
14
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 */
22static const struct nand_interface_config onfi_sdr_timings[] = {
23 /* Mode 0 */
24 {
25 .type = NAND_SDR_IFACE,
26 .timings.mode = 0,
27 .timings.sdr = {
28 .tCCS_min = 500000,
29 .tR_max = 200000000,
30 .tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
31 .tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
32 .tADL_min = 400000,
33 .tALH_min = 20000,
34 .tALS_min = 50000,
35 .tAR_min = 25000,
36 .tCEA_max = 100000,
37 .tCEH_min = 20000,
38 .tCH_min = 20000,
39 .tCHZ_max = 100000,
40 .tCLH_min = 20000,
41 .tCLR_min = 20000,
42 .tCLS_min = 50000,
43 .tCOH_min = 0,
44 .tCS_min = 70000,
45 .tDH_min = 20000,
46 .tDS_min = 40000,
47 .tFEAT_max = 1000000,
48 .tIR_min = 10000,
49 .tITC_max = 1000000,
50 .tRC_min = 100000,
51 .tREA_max = 40000,
52 .tREH_min = 30000,
53 .tRHOH_min = 0,
54 .tRHW_min = 200000,
55 .tRHZ_max = 200000,
56 .tRLOH_min = 0,
57 .tRP_min = 50000,
58 .tRR_min = 40000,
59 .tRST_max = 250000000000ULL,
60 .tWB_max = 200000,
61 .tWC_min = 100000,
62 .tWH_min = 30000,
63 .tWHR_min = 120000,
64 .tWP_min = 50000,
65 .tWW_min = 100000,
66 },
67 },
68 /* Mode 1 */
69 {
70 .type = NAND_SDR_IFACE,
71 .timings.mode = 1,
72 .timings.sdr = {
73 .tCCS_min = 500000,
74 .tR_max = 200000000,
75 .tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
76 .tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
77 .tADL_min = 400000,
78 .tALH_min = 10000,
79 .tALS_min = 25000,
80 .tAR_min = 10000,
81 .tCEA_max = 45000,
82 .tCEH_min = 20000,
83 .tCH_min = 10000,
84 .tCHZ_max = 50000,
85 .tCLH_min = 10000,
86 .tCLR_min = 10000,
87 .tCLS_min = 25000,
88 .tCOH_min = 15000,
89 .tCS_min = 35000,
90 .tDH_min = 10000,
91 .tDS_min = 20000,
92 .tFEAT_max = 1000000,
93 .tIR_min = 0,
94 .tITC_max = 1000000,
95 .tRC_min = 50000,
96 .tREA_max = 30000,
97 .tREH_min = 15000,
98 .tRHOH_min = 15000,
99 .tRHW_min = 100000,
100 .tRHZ_max = 100000,
101 .tRLOH_min = 0,
102 .tRP_min = 25000,
103 .tRR_min = 20000,
104 .tRST_max = 500000000,
105 .tWB_max = 100000,
106 .tWC_min = 45000,
107 .tWH_min = 15000,
108 .tWHR_min = 80000,
109 .tWP_min = 25000,
110 .tWW_min = 100000,
111 },
112 },
113 /* Mode 2 */
114 {
115 .type = NAND_SDR_IFACE,
116 .timings.mode = 2,
117 .timings.sdr = {
118 .tCCS_min = 500000,
119 .tR_max = 200000000,
120 .tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
121 .tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
122 .tADL_min = 400000,
123 .tALH_min = 10000,
124 .tALS_min = 15000,
125 .tAR_min = 10000,
126 .tCEA_max = 30000,
127 .tCEH_min = 20000,
128 .tCH_min = 10000,
129 .tCHZ_max = 50000,
130 .tCLH_min = 10000,
131 .tCLR_min = 10000,
132 .tCLS_min = 15000,
133 .tCOH_min = 15000,
134 .tCS_min = 25000,
135 .tDH_min = 5000,
136 .tDS_min = 15000,
137 .tFEAT_max = 1000000,
138 .tIR_min = 0,
139 .tITC_max = 1000000,
140 .tRC_min = 35000,
141 .tREA_max = 25000,
142 .tREH_min = 15000,
143 .tRHOH_min = 15000,
144 .tRHW_min = 100000,
145 .tRHZ_max = 100000,
146 .tRLOH_min = 0,
147 .tRR_min = 20000,
148 .tRST_max = 500000000,
149 .tWB_max = 100000,
150 .tRP_min = 17000,
151 .tWC_min = 35000,
152 .tWH_min = 15000,
153 .tWHR_min = 80000,
154 .tWP_min = 17000,
155 .tWW_min = 100000,
156 },
157 },
158 /* Mode 3 */
159 {
160 .type = NAND_SDR_IFACE,
161 .timings.mode = 3,
162 .timings.sdr = {
163 .tCCS_min = 500000,
164 .tR_max = 200000000,
165 .tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
166 .tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
167 .tADL_min = 400000,
168 .tALH_min = 5000,
169 .tALS_min = 10000,
170 .tAR_min = 10000,
171 .tCEA_max = 25000,
172 .tCEH_min = 20000,
173 .tCH_min = 5000,
174 .tCHZ_max = 50000,
175 .tCLH_min = 5000,
176 .tCLR_min = 10000,
177 .tCLS_min = 10000,
178 .tCOH_min = 15000,
179 .tCS_min = 25000,
180 .tDH_min = 5000,
181 .tDS_min = 10000,
182 .tFEAT_max = 1000000,
183 .tIR_min = 0,
184 .tITC_max = 1000000,
185 .tRC_min = 30000,
186 .tREA_max = 20000,
187 .tREH_min = 10000,
188 .tRHOH_min = 15000,
189 .tRHW_min = 100000,
190 .tRHZ_max = 100000,
191 .tRLOH_min = 0,
192 .tRP_min = 15000,
193 .tRR_min = 20000,
194 .tRST_max = 500000000,
195 .tWB_max = 100000,
196 .tWC_min = 30000,
197 .tWH_min = 10000,
198 .tWHR_min = 80000,
199 .tWP_min = 15000,
200 .tWW_min = 100000,
201 },
202 },
203 /* Mode 4 */
204 {
205 .type = NAND_SDR_IFACE,
206 .timings.mode = 4,
207 .timings.sdr = {
208 .tCCS_min = 500000,
209 .tR_max = 200000000,
210 .tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
211 .tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
212 .tADL_min = 400000,
213 .tALH_min = 5000,
214 .tALS_min = 10000,
215 .tAR_min = 10000,
216 .tCEA_max = 25000,
217 .tCEH_min = 20000,
218 .tCH_min = 5000,
219 .tCHZ_max = 30000,
220 .tCLH_min = 5000,
221 .tCLR_min = 10000,
222 .tCLS_min = 10000,
223 .tCOH_min = 15000,
224 .tCS_min = 20000,
225 .tDH_min = 5000,
226 .tDS_min = 10000,
227 .tFEAT_max = 1000000,
228 .tIR_min = 0,
229 .tITC_max = 1000000,
230 .tRC_min = 25000,
231 .tREA_max = 20000,
232 .tREH_min = 10000,
233 .tRHOH_min = 15000,
234 .tRHW_min = 100000,
235 .tRHZ_max = 100000,
236 .tRLOH_min = 5000,
237 .tRP_min = 12000,
238 .tRR_min = 20000,
239 .tRST_max = 500000000,
240 .tWB_max = 100000,
241 .tWC_min = 25000,
242 .tWH_min = 10000,
243 .tWHR_min = 80000,
244 .tWP_min = 12000,
245 .tWW_min = 100000,
246 },
247 },
248 /* Mode 5 */
249 {
250 .type = NAND_SDR_IFACE,
251 .timings.mode = 5,
252 .timings.sdr = {
253 .tCCS_min = 500000,
254 .tR_max = 200000000,
255 .tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
256 .tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
257 .tADL_min = 400000,
258 .tALH_min = 5000,
259 .tALS_min = 10000,
260 .tAR_min = 10000,
261 .tCEA_max = 25000,
262 .tCEH_min = 20000,
263 .tCH_min = 5000,
264 .tCHZ_max = 30000,
265 .tCLH_min = 5000,
266 .tCLR_min = 10000,
267 .tCLS_min = 10000,
268 .tCOH_min = 15000,
269 .tCS_min = 15000,
270 .tDH_min = 5000,
271 .tDS_min = 7000,
272 .tFEAT_max = 1000000,
273 .tIR_min = 0,
274 .tITC_max = 1000000,
275 .tRC_min = 20000,
276 .tREA_max = 16000,
277 .tREH_min = 7000,
278 .tRHOH_min = 15000,
279 .tRHW_min = 100000,
280 .tRHZ_max = 100000,
281 .tRLOH_min = 5000,
282 .tRP_min = 10000,
283 .tRR_min = 20000,
284 .tRST_max = 500000000,
285 .tWB_max = 100000,
286 .tWC_min = 20000,
287 .tWH_min = 7000,
288 .tWHR_min = 80000,
289 .tWP_min = 10000,
290 .tWW_min = 100000,
291 },
292 },
293};
294
295static 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};
549
550/* All NAND chips share the same reset data interface: SDR mode 0 */
551const struct nand_interface_config *nand_get_reset_interface_config(void)
552{
553 return &onfi_sdr_timings[0];
554}
555
556/**
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
560 */
561unsigned int
562onfi_find_closest_sdr_mode(const struct nand_sdr_timings *spec_timings)
563{
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_find_closest_nvddr_mode - Derive the closest ONFI NVDDR timing mode
605 * given a set of timings
606 * @spec_timings: the timings to challenge
607 */
608unsigned int
609onfi_find_closest_nvddr_mode(const struct nand_nvddr_timings *spec_timings)
610{
611 const struct nand_nvddr_timings *onfi_timings;
612 int mode;
613
614 for (mode = ARRAY_SIZE(onfi_nvddr_timings) - 1; mode > 0; mode--) {
615 onfi_timings = &onfi_nvddr_timings[mode].timings.nvddr;
616
617 if (spec_timings->tCCS_min <= onfi_timings->tCCS_min &&
618 spec_timings->tAC_min <= onfi_timings->tAC_min &&
619 spec_timings->tADL_min <= onfi_timings->tADL_min &&
620 spec_timings->tCAD_min <= onfi_timings->tCAD_min &&
621 spec_timings->tCAH_min <= onfi_timings->tCAH_min &&
622 spec_timings->tCALH_min <= onfi_timings->tCALH_min &&
623 spec_timings->tCALS_min <= onfi_timings->tCALS_min &&
624 spec_timings->tCAS_min <= onfi_timings->tCAS_min &&
625 spec_timings->tCEH_min <= onfi_timings->tCEH_min &&
626 spec_timings->tCH_min <= onfi_timings->tCH_min &&
627 spec_timings->tCK_min <= onfi_timings->tCK_min &&
628 spec_timings->tCS_min <= onfi_timings->tCS_min &&
629 spec_timings->tDH_min <= onfi_timings->tDH_min &&
630 spec_timings->tDQSCK_min <= onfi_timings->tDQSCK_min &&
631 spec_timings->tDQSD_min <= onfi_timings->tDQSD_min &&
632 spec_timings->tDS_min <= onfi_timings->tDS_min &&
633 spec_timings->tDSC_min <= onfi_timings->tDSC_min &&
634 spec_timings->tRHW_min <= onfi_timings->tRHW_min &&
635 spec_timings->tRR_min <= onfi_timings->tRR_min &&
636 spec_timings->tWHR_min <= onfi_timings->tWHR_min &&
637 spec_timings->tWRCK_min <= onfi_timings->tWRCK_min &&
638 spec_timings->tWW_min <= onfi_timings->tWW_min)
639 return mode;
640 }
641
642 return 0;
643}
644
645/*
646 * onfi_fill_sdr_interface_config - Initialize a SDR interface config from a
647 * given ONFI mode
648 * @chip: The NAND chip
649 * @iface: The interface configuration to fill
650 * @timing_mode: The ONFI timing mode
651 */
652static void onfi_fill_sdr_interface_config(struct nand_chip *chip,
653 struct nand_interface_config *iface,
654 unsigned int timing_mode)
655{
656 struct onfi_params *onfi = chip->parameters.onfi;
657
658 if (WARN_ON(timing_mode >= ARRAY_SIZE(onfi_sdr_timings)))
659 return;
660
661 *iface = onfi_sdr_timings[timing_mode];
662
663 /*
664 * Initialize timings that cannot be deduced from timing mode:
665 * tPROG, tBERS, tR and tCCS.
666 * These information are part of the ONFI parameter page.
667 */
668 if (onfi) {
669 struct nand_sdr_timings *timings = &iface->timings.sdr;
670
671 /* microseconds -> picoseconds */
672 timings->tPROG_max = 1000000ULL * onfi->tPROG;
673 timings->tBERS_max = 1000000ULL * onfi->tBERS;
674 timings->tR_max = 1000000ULL * onfi->tR;
675
676 /* nanoseconds -> picoseconds */
677 timings->tCCS_min = 1000UL * onfi->tCCS;
678 }
679}
680
681/**
682 * onfi_fill_nvddr_interface_config - Initialize a NVDDR interface config from a
683 * given ONFI mode
684 * @chip: The NAND chip
685 * @iface: The interface configuration to fill
686 * @timing_mode: The ONFI timing mode
687 */
688static void onfi_fill_nvddr_interface_config(struct nand_chip *chip,
689 struct nand_interface_config *iface,
690 unsigned int timing_mode)
691{
692 struct onfi_params *onfi = chip->parameters.onfi;
693
694 if (WARN_ON(timing_mode >= ARRAY_SIZE(onfi_nvddr_timings)))
695 return;
696
697 *iface = onfi_nvddr_timings[timing_mode];
698
699 /*
700 * Initialize timings that cannot be deduced from timing mode:
701 * tPROG, tBERS, tR, tCCS and tCAD.
702 * These information are part of the ONFI parameter page.
703 */
704 if (onfi) {
705 struct nand_nvddr_timings *timings = &iface->timings.nvddr;
706
707 /* microseconds -> picoseconds */
708 timings->tPROG_max = 1000000ULL * onfi->tPROG;
709 timings->tBERS_max = 1000000ULL * onfi->tBERS;
710 timings->tR_max = 1000000ULL * onfi->tR;
711
712 /* nanoseconds -> picoseconds */
713 timings->tCCS_min = 1000UL * onfi->tCCS;
714
715 if (onfi->fast_tCAD)
716 timings->tCAD_min = 25000;
717 }
718}
719
720/**
721 * onfi_fill_interface_config - Initialize an interface config from a given
722 * ONFI mode
723 * @chip: The NAND chip
724 * @iface: The interface configuration to fill
725 * @type: The interface type
726 * @timing_mode: The ONFI timing mode
727 */
728void onfi_fill_interface_config(struct nand_chip *chip,
729 struct nand_interface_config *iface,
730 enum nand_interface_type type,
731 unsigned int timing_mode)
732{
733 if (type == NAND_SDR_IFACE)
734 return onfi_fill_sdr_interface_config(chip, iface, timing_mode);
735 else
736 return onfi_fill_nvddr_interface_config(chip, iface, timing_mode);
737}
738

source code of linux/drivers/mtd/nand/raw/nand_timings.c