xref: /linux/drivers/mtd/nand/raw/nand_timings.c (revision 40d269c000bda9fcd276a0412a9cebd3f6e344c5)
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  */
22 static 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 
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 };
549 
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];
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  */
561 unsigned int
562 onfi_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  */
608 unsigned int
609 onfi_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  */
652 static 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  */
688 static 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  */
728 void 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