xref: /linux/drivers/mtd/nand/raw/nand_timings.c (revision 353b7a55dcaf5fb8758e09ebe2ddf5f3adbac7c5)
1d2912cb1SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2974647eaSBoris BREZILLON /*
3974647eaSBoris BREZILLON  *  Copyright (C) 2014 Free Electrons
4974647eaSBoris BREZILLON  *
5974647eaSBoris BREZILLON  *  Author: Boris BREZILLON <boris.brezillon@free-electrons.com>
6974647eaSBoris BREZILLON  */
7974647eaSBoris BREZILLON #include <linux/kernel.h>
8974647eaSBoris BREZILLON #include <linux/err.h>
9974647eaSBoris BREZILLON #include <linux/export.h>
10348d56a8SBoris Brezillon 
11348d56a8SBoris Brezillon #include "internals.h"
12974647eaSBoris BREZILLON 
136a943386SMiquel Raynal #define ONFI_DYN_TIMING_MAX U16_MAX
146a943386SMiquel Raynal 
15d1bfe1e3SMiquel Raynal /*
16d1bfe1e3SMiquel Raynal  * For non-ONFI chips we use the highest possible value for tPROG and tBERS.
17d1bfe1e3SMiquel Raynal  * tR and tCCS will take the default values precised in the ONFI specification
18d1bfe1e3SMiquel Raynal  * for timing mode 0, respectively 200us and 500ns.
19d1bfe1e3SMiquel Raynal  *
20d1bfe1e3SMiquel Raynal  * These four values are tweaked to be more accurate in the case of ONFI chips.
21d1bfe1e3SMiquel Raynal  */
224c46667bSMiquel Raynal static const struct nand_interface_config onfi_sdr_timings[] = {
23974647eaSBoris BREZILLON 	/* Mode 0 */
24974647eaSBoris BREZILLON 	{
25b1dd3ca2SSascha Hauer 		.type = NAND_SDR_IFACE,
2683c411c2SMiquel Raynal 		.timings.mode = 0,
27b1dd3ca2SSascha Hauer 		.timings.sdr = {
28204e7ecdSBoris Brezillon 			.tCCS_min = 500000,
29204e7ecdSBoris Brezillon 			.tR_max = 200000000,
30d1bfe1e3SMiquel Raynal 			.tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
31d1bfe1e3SMiquel Raynal 			.tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
3274a332e7SBoris Brezillon 			.tADL_min = 400000,
33974647eaSBoris BREZILLON 			.tALH_min = 20000,
34974647eaSBoris BREZILLON 			.tALS_min = 50000,
35974647eaSBoris BREZILLON 			.tAR_min = 25000,
36974647eaSBoris BREZILLON 			.tCEA_max = 100000,
37974647eaSBoris BREZILLON 			.tCEH_min = 20000,
38974647eaSBoris BREZILLON 			.tCH_min = 20000,
39974647eaSBoris BREZILLON 			.tCHZ_max = 100000,
40974647eaSBoris BREZILLON 			.tCLH_min = 20000,
41974647eaSBoris BREZILLON 			.tCLR_min = 20000,
42974647eaSBoris BREZILLON 			.tCLS_min = 50000,
43974647eaSBoris BREZILLON 			.tCOH_min = 0,
44974647eaSBoris BREZILLON 			.tCS_min = 70000,
45974647eaSBoris BREZILLON 			.tDH_min = 20000,
46974647eaSBoris BREZILLON 			.tDS_min = 40000,
47974647eaSBoris BREZILLON 			.tFEAT_max = 1000000,
48974647eaSBoris BREZILLON 			.tIR_min = 10000,
49974647eaSBoris BREZILLON 			.tITC_max = 1000000,
50974647eaSBoris BREZILLON 			.tRC_min = 100000,
51974647eaSBoris BREZILLON 			.tREA_max = 40000,
52974647eaSBoris BREZILLON 			.tREH_min = 30000,
53974647eaSBoris BREZILLON 			.tRHOH_min = 0,
54974647eaSBoris BREZILLON 			.tRHW_min = 200000,
55974647eaSBoris BREZILLON 			.tRHZ_max = 200000,
56974647eaSBoris BREZILLON 			.tRLOH_min = 0,
57974647eaSBoris BREZILLON 			.tRP_min = 50000,
5857d419a4SBoris Brezillon 			.tRR_min = 40000,
59bd8898dbSGeert Uytterhoeven 			.tRST_max = 250000000000ULL,
60974647eaSBoris BREZILLON 			.tWB_max = 200000,
61974647eaSBoris BREZILLON 			.tWC_min = 100000,
62974647eaSBoris BREZILLON 			.tWH_min = 30000,
63974647eaSBoris BREZILLON 			.tWHR_min = 120000,
64974647eaSBoris BREZILLON 			.tWP_min = 50000,
65974647eaSBoris BREZILLON 			.tWW_min = 100000,
66974647eaSBoris BREZILLON 		},
67b1dd3ca2SSascha Hauer 	},
68974647eaSBoris BREZILLON 	/* Mode 1 */
69974647eaSBoris BREZILLON 	{
70b1dd3ca2SSascha Hauer 		.type = NAND_SDR_IFACE,
7183c411c2SMiquel Raynal 		.timings.mode = 1,
72b1dd3ca2SSascha Hauer 		.timings.sdr = {
73204e7ecdSBoris Brezillon 			.tCCS_min = 500000,
74204e7ecdSBoris Brezillon 			.tR_max = 200000000,
75d1bfe1e3SMiquel Raynal 			.tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
76d1bfe1e3SMiquel Raynal 			.tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
7774a332e7SBoris Brezillon 			.tADL_min = 400000,
78974647eaSBoris BREZILLON 			.tALH_min = 10000,
79974647eaSBoris BREZILLON 			.tALS_min = 25000,
80974647eaSBoris BREZILLON 			.tAR_min = 10000,
81974647eaSBoris BREZILLON 			.tCEA_max = 45000,
82974647eaSBoris BREZILLON 			.tCEH_min = 20000,
83974647eaSBoris BREZILLON 			.tCH_min = 10000,
84974647eaSBoris BREZILLON 			.tCHZ_max = 50000,
85974647eaSBoris BREZILLON 			.tCLH_min = 10000,
86974647eaSBoris BREZILLON 			.tCLR_min = 10000,
87974647eaSBoris BREZILLON 			.tCLS_min = 25000,
88974647eaSBoris BREZILLON 			.tCOH_min = 15000,
89974647eaSBoris BREZILLON 			.tCS_min = 35000,
90974647eaSBoris BREZILLON 			.tDH_min = 10000,
91974647eaSBoris BREZILLON 			.tDS_min = 20000,
92974647eaSBoris BREZILLON 			.tFEAT_max = 1000000,
93974647eaSBoris BREZILLON 			.tIR_min = 0,
94974647eaSBoris BREZILLON 			.tITC_max = 1000000,
95974647eaSBoris BREZILLON 			.tRC_min = 50000,
96974647eaSBoris BREZILLON 			.tREA_max = 30000,
97974647eaSBoris BREZILLON 			.tREH_min = 15000,
98974647eaSBoris BREZILLON 			.tRHOH_min = 15000,
99974647eaSBoris BREZILLON 			.tRHW_min = 100000,
100974647eaSBoris BREZILLON 			.tRHZ_max = 100000,
101974647eaSBoris BREZILLON 			.tRLOH_min = 0,
102974647eaSBoris BREZILLON 			.tRP_min = 25000,
103974647eaSBoris BREZILLON 			.tRR_min = 20000,
104974647eaSBoris BREZILLON 			.tRST_max = 500000000,
105974647eaSBoris BREZILLON 			.tWB_max = 100000,
106974647eaSBoris BREZILLON 			.tWC_min = 45000,
107974647eaSBoris BREZILLON 			.tWH_min = 15000,
108974647eaSBoris BREZILLON 			.tWHR_min = 80000,
109974647eaSBoris BREZILLON 			.tWP_min = 25000,
110974647eaSBoris BREZILLON 			.tWW_min = 100000,
111974647eaSBoris BREZILLON 		},
112b1dd3ca2SSascha Hauer 	},
113974647eaSBoris BREZILLON 	/* Mode 2 */
114974647eaSBoris BREZILLON 	{
115b1dd3ca2SSascha Hauer 		.type = NAND_SDR_IFACE,
11683c411c2SMiquel Raynal 		.timings.mode = 2,
117b1dd3ca2SSascha Hauer 		.timings.sdr = {
118204e7ecdSBoris Brezillon 			.tCCS_min = 500000,
119204e7ecdSBoris Brezillon 			.tR_max = 200000000,
120d1bfe1e3SMiquel Raynal 			.tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
121d1bfe1e3SMiquel Raynal 			.tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
12274a332e7SBoris Brezillon 			.tADL_min = 400000,
123974647eaSBoris BREZILLON 			.tALH_min = 10000,
124974647eaSBoris BREZILLON 			.tALS_min = 15000,
125974647eaSBoris BREZILLON 			.tAR_min = 10000,
126974647eaSBoris BREZILLON 			.tCEA_max = 30000,
127974647eaSBoris BREZILLON 			.tCEH_min = 20000,
128974647eaSBoris BREZILLON 			.tCH_min = 10000,
129974647eaSBoris BREZILLON 			.tCHZ_max = 50000,
130974647eaSBoris BREZILLON 			.tCLH_min = 10000,
131974647eaSBoris BREZILLON 			.tCLR_min = 10000,
132974647eaSBoris BREZILLON 			.tCLS_min = 15000,
133974647eaSBoris BREZILLON 			.tCOH_min = 15000,
134974647eaSBoris BREZILLON 			.tCS_min = 25000,
135974647eaSBoris BREZILLON 			.tDH_min = 5000,
136974647eaSBoris BREZILLON 			.tDS_min = 15000,
137974647eaSBoris BREZILLON 			.tFEAT_max = 1000000,
138974647eaSBoris BREZILLON 			.tIR_min = 0,
139974647eaSBoris BREZILLON 			.tITC_max = 1000000,
140974647eaSBoris BREZILLON 			.tRC_min = 35000,
141974647eaSBoris BREZILLON 			.tREA_max = 25000,
142974647eaSBoris BREZILLON 			.tREH_min = 15000,
143974647eaSBoris BREZILLON 			.tRHOH_min = 15000,
144974647eaSBoris BREZILLON 			.tRHW_min = 100000,
145974647eaSBoris BREZILLON 			.tRHZ_max = 100000,
146974647eaSBoris BREZILLON 			.tRLOH_min = 0,
147974647eaSBoris BREZILLON 			.tRR_min = 20000,
148974647eaSBoris BREZILLON 			.tRST_max = 500000000,
149974647eaSBoris BREZILLON 			.tWB_max = 100000,
150974647eaSBoris BREZILLON 			.tRP_min = 17000,
151974647eaSBoris BREZILLON 			.tWC_min = 35000,
152974647eaSBoris BREZILLON 			.tWH_min = 15000,
153974647eaSBoris BREZILLON 			.tWHR_min = 80000,
154974647eaSBoris BREZILLON 			.tWP_min = 17000,
155974647eaSBoris BREZILLON 			.tWW_min = 100000,
156974647eaSBoris BREZILLON 		},
157b1dd3ca2SSascha Hauer 	},
158974647eaSBoris BREZILLON 	/* Mode 3 */
159974647eaSBoris BREZILLON 	{
160b1dd3ca2SSascha Hauer 		.type = NAND_SDR_IFACE,
16183c411c2SMiquel Raynal 		.timings.mode = 3,
162b1dd3ca2SSascha Hauer 		.timings.sdr = {
163204e7ecdSBoris Brezillon 			.tCCS_min = 500000,
164204e7ecdSBoris Brezillon 			.tR_max = 200000000,
165d1bfe1e3SMiquel Raynal 			.tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
166d1bfe1e3SMiquel Raynal 			.tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
16774a332e7SBoris Brezillon 			.tADL_min = 400000,
168974647eaSBoris BREZILLON 			.tALH_min = 5000,
169974647eaSBoris BREZILLON 			.tALS_min = 10000,
170974647eaSBoris BREZILLON 			.tAR_min = 10000,
171974647eaSBoris BREZILLON 			.tCEA_max = 25000,
172974647eaSBoris BREZILLON 			.tCEH_min = 20000,
173974647eaSBoris BREZILLON 			.tCH_min = 5000,
174974647eaSBoris BREZILLON 			.tCHZ_max = 50000,
175974647eaSBoris BREZILLON 			.tCLH_min = 5000,
176974647eaSBoris BREZILLON 			.tCLR_min = 10000,
177974647eaSBoris BREZILLON 			.tCLS_min = 10000,
178974647eaSBoris BREZILLON 			.tCOH_min = 15000,
179974647eaSBoris BREZILLON 			.tCS_min = 25000,
180974647eaSBoris BREZILLON 			.tDH_min = 5000,
181974647eaSBoris BREZILLON 			.tDS_min = 10000,
182974647eaSBoris BREZILLON 			.tFEAT_max = 1000000,
183974647eaSBoris BREZILLON 			.tIR_min = 0,
184974647eaSBoris BREZILLON 			.tITC_max = 1000000,
185974647eaSBoris BREZILLON 			.tRC_min = 30000,
186974647eaSBoris BREZILLON 			.tREA_max = 20000,
187974647eaSBoris BREZILLON 			.tREH_min = 10000,
188974647eaSBoris BREZILLON 			.tRHOH_min = 15000,
189974647eaSBoris BREZILLON 			.tRHW_min = 100000,
190974647eaSBoris BREZILLON 			.tRHZ_max = 100000,
191974647eaSBoris BREZILLON 			.tRLOH_min = 0,
192974647eaSBoris BREZILLON 			.tRP_min = 15000,
193974647eaSBoris BREZILLON 			.tRR_min = 20000,
194974647eaSBoris BREZILLON 			.tRST_max = 500000000,
195974647eaSBoris BREZILLON 			.tWB_max = 100000,
196974647eaSBoris BREZILLON 			.tWC_min = 30000,
197974647eaSBoris BREZILLON 			.tWH_min = 10000,
198974647eaSBoris BREZILLON 			.tWHR_min = 80000,
199974647eaSBoris BREZILLON 			.tWP_min = 15000,
200974647eaSBoris BREZILLON 			.tWW_min = 100000,
201974647eaSBoris BREZILLON 		},
202b1dd3ca2SSascha Hauer 	},
203974647eaSBoris BREZILLON 	/* Mode 4 */
204974647eaSBoris BREZILLON 	{
205b1dd3ca2SSascha Hauer 		.type = NAND_SDR_IFACE,
20683c411c2SMiquel Raynal 		.timings.mode = 4,
207b1dd3ca2SSascha Hauer 		.timings.sdr = {
208204e7ecdSBoris Brezillon 			.tCCS_min = 500000,
209204e7ecdSBoris Brezillon 			.tR_max = 200000000,
210d1bfe1e3SMiquel Raynal 			.tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
211d1bfe1e3SMiquel Raynal 			.tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
21274a332e7SBoris Brezillon 			.tADL_min = 400000,
213974647eaSBoris BREZILLON 			.tALH_min = 5000,
214974647eaSBoris BREZILLON 			.tALS_min = 10000,
215974647eaSBoris BREZILLON 			.tAR_min = 10000,
216974647eaSBoris BREZILLON 			.tCEA_max = 25000,
217974647eaSBoris BREZILLON 			.tCEH_min = 20000,
218974647eaSBoris BREZILLON 			.tCH_min = 5000,
219974647eaSBoris BREZILLON 			.tCHZ_max = 30000,
220974647eaSBoris BREZILLON 			.tCLH_min = 5000,
221974647eaSBoris BREZILLON 			.tCLR_min = 10000,
222974647eaSBoris BREZILLON 			.tCLS_min = 10000,
223974647eaSBoris BREZILLON 			.tCOH_min = 15000,
224974647eaSBoris BREZILLON 			.tCS_min = 20000,
225974647eaSBoris BREZILLON 			.tDH_min = 5000,
226974647eaSBoris BREZILLON 			.tDS_min = 10000,
227974647eaSBoris BREZILLON 			.tFEAT_max = 1000000,
228974647eaSBoris BREZILLON 			.tIR_min = 0,
229974647eaSBoris BREZILLON 			.tITC_max = 1000000,
230974647eaSBoris BREZILLON 			.tRC_min = 25000,
231974647eaSBoris BREZILLON 			.tREA_max = 20000,
232974647eaSBoris BREZILLON 			.tREH_min = 10000,
233974647eaSBoris BREZILLON 			.tRHOH_min = 15000,
234974647eaSBoris BREZILLON 			.tRHW_min = 100000,
235974647eaSBoris BREZILLON 			.tRHZ_max = 100000,
236974647eaSBoris BREZILLON 			.tRLOH_min = 5000,
237974647eaSBoris BREZILLON 			.tRP_min = 12000,
238974647eaSBoris BREZILLON 			.tRR_min = 20000,
239974647eaSBoris BREZILLON 			.tRST_max = 500000000,
240974647eaSBoris BREZILLON 			.tWB_max = 100000,
241974647eaSBoris BREZILLON 			.tWC_min = 25000,
242974647eaSBoris BREZILLON 			.tWH_min = 10000,
243974647eaSBoris BREZILLON 			.tWHR_min = 80000,
244974647eaSBoris BREZILLON 			.tWP_min = 12000,
245974647eaSBoris BREZILLON 			.tWW_min = 100000,
246974647eaSBoris BREZILLON 		},
247b1dd3ca2SSascha Hauer 	},
248974647eaSBoris BREZILLON 	/* Mode 5 */
249974647eaSBoris BREZILLON 	{
250b1dd3ca2SSascha Hauer 		.type = NAND_SDR_IFACE,
25183c411c2SMiquel Raynal 		.timings.mode = 5,
252b1dd3ca2SSascha Hauer 		.timings.sdr = {
253204e7ecdSBoris Brezillon 			.tCCS_min = 500000,
254204e7ecdSBoris Brezillon 			.tR_max = 200000000,
255d1bfe1e3SMiquel Raynal 			.tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
256d1bfe1e3SMiquel Raynal 			.tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
25774a332e7SBoris Brezillon 			.tADL_min = 400000,
258974647eaSBoris BREZILLON 			.tALH_min = 5000,
259974647eaSBoris BREZILLON 			.tALS_min = 10000,
260974647eaSBoris BREZILLON 			.tAR_min = 10000,
261974647eaSBoris BREZILLON 			.tCEA_max = 25000,
262974647eaSBoris BREZILLON 			.tCEH_min = 20000,
263974647eaSBoris BREZILLON 			.tCH_min = 5000,
264974647eaSBoris BREZILLON 			.tCHZ_max = 30000,
265974647eaSBoris BREZILLON 			.tCLH_min = 5000,
266974647eaSBoris BREZILLON 			.tCLR_min = 10000,
267974647eaSBoris BREZILLON 			.tCLS_min = 10000,
268974647eaSBoris BREZILLON 			.tCOH_min = 15000,
269974647eaSBoris BREZILLON 			.tCS_min = 15000,
270974647eaSBoris BREZILLON 			.tDH_min = 5000,
271974647eaSBoris BREZILLON 			.tDS_min = 7000,
272974647eaSBoris BREZILLON 			.tFEAT_max = 1000000,
273974647eaSBoris BREZILLON 			.tIR_min = 0,
274974647eaSBoris BREZILLON 			.tITC_max = 1000000,
275974647eaSBoris BREZILLON 			.tRC_min = 20000,
276974647eaSBoris BREZILLON 			.tREA_max = 16000,
277974647eaSBoris BREZILLON 			.tREH_min = 7000,
278974647eaSBoris BREZILLON 			.tRHOH_min = 15000,
279974647eaSBoris BREZILLON 			.tRHW_min = 100000,
280974647eaSBoris BREZILLON 			.tRHZ_max = 100000,
281974647eaSBoris BREZILLON 			.tRLOH_min = 5000,
282974647eaSBoris BREZILLON 			.tRP_min = 10000,
283974647eaSBoris BREZILLON 			.tRR_min = 20000,
284974647eaSBoris BREZILLON 			.tRST_max = 500000000,
285974647eaSBoris BREZILLON 			.tWB_max = 100000,
286974647eaSBoris BREZILLON 			.tWC_min = 20000,
287974647eaSBoris BREZILLON 			.tWH_min = 7000,
288974647eaSBoris BREZILLON 			.tWHR_min = 80000,
289974647eaSBoris BREZILLON 			.tWP_min = 10000,
290974647eaSBoris BREZILLON 			.tWW_min = 100000,
291974647eaSBoris BREZILLON 		},
292b1dd3ca2SSascha Hauer 	},
293974647eaSBoris BREZILLON };
294974647eaSBoris BREZILLON 
2951666b815SMiquel Raynal static const struct nand_interface_config onfi_nvddr_timings[] = {
2961666b815SMiquel Raynal 	/* Mode 0 */
2971666b815SMiquel Raynal 	{
2981666b815SMiquel Raynal 		.type = NAND_NVDDR_IFACE,
2991666b815SMiquel Raynal 		.timings.mode = 0,
3001666b815SMiquel Raynal 		.timings.nvddr = {
3011666b815SMiquel Raynal 			.tCCS_min = 500000,
3021666b815SMiquel Raynal 			.tR_max = 200000000,
3031666b815SMiquel Raynal 			.tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
3041666b815SMiquel Raynal 			.tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
3051666b815SMiquel Raynal 			.tAC_min = 3000,
3061666b815SMiquel Raynal 			.tAC_max = 25000,
3071666b815SMiquel Raynal 			.tADL_min = 400000,
3081666b815SMiquel Raynal 			.tCAD_min = 45000,
3091666b815SMiquel Raynal 			.tCAH_min = 10000,
3101666b815SMiquel Raynal 			.tCALH_min = 10000,
3111666b815SMiquel Raynal 			.tCALS_min = 10000,
3121666b815SMiquel Raynal 			.tCAS_min = 10000,
3131666b815SMiquel Raynal 			.tCEH_min = 20000,
3141666b815SMiquel Raynal 			.tCH_min = 10000,
3151666b815SMiquel Raynal 			.tCK_min = 50000,
3161666b815SMiquel Raynal 			.tCS_min = 35000,
3171666b815SMiquel Raynal 			.tDH_min = 5000,
3181666b815SMiquel Raynal 			.tDQSCK_min = 3000,
3191666b815SMiquel Raynal 			.tDQSCK_max = 25000,
3201666b815SMiquel Raynal 			.tDQSD_min = 0,
3211666b815SMiquel Raynal 			.tDQSD_max = 18000,
3221666b815SMiquel Raynal 			.tDQSHZ_max = 20000,
3231666b815SMiquel Raynal 			.tDQSQ_max = 5000,
3241666b815SMiquel Raynal 			.tDS_min = 5000,
3251666b815SMiquel Raynal 			.tDSC_min = 50000,
3261666b815SMiquel Raynal 			.tFEAT_max = 1000000,
3271666b815SMiquel Raynal 			.tITC_max = 1000000,
3281666b815SMiquel Raynal 			.tQHS_max = 6000,
3291666b815SMiquel Raynal 			.tRHW_min = 100000,
3301666b815SMiquel Raynal 			.tRR_min = 20000,
3311666b815SMiquel Raynal 			.tRST_max = 500000000,
3321666b815SMiquel Raynal 			.tWB_max = 100000,
3331666b815SMiquel Raynal 			.tWHR_min = 80000,
3341666b815SMiquel Raynal 			.tWRCK_min = 20000,
3351666b815SMiquel Raynal 			.tWW_min = 100000,
3361666b815SMiquel Raynal 		},
3371666b815SMiquel Raynal 	},
3381666b815SMiquel Raynal 	/* Mode 1 */
3391666b815SMiquel Raynal 	{
3401666b815SMiquel Raynal 		.type = NAND_NVDDR_IFACE,
3411666b815SMiquel Raynal 		.timings.mode = 1,
3421666b815SMiquel Raynal 		.timings.nvddr = {
3431666b815SMiquel Raynal 			.tCCS_min = 500000,
3441666b815SMiquel Raynal 			.tR_max = 200000000,
3451666b815SMiquel Raynal 			.tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
3461666b815SMiquel Raynal 			.tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
3471666b815SMiquel Raynal 			.tAC_min = 3000,
3481666b815SMiquel Raynal 			.tAC_max = 25000,
3491666b815SMiquel Raynal 			.tADL_min = 400000,
3501666b815SMiquel Raynal 			.tCAD_min = 45000,
3511666b815SMiquel Raynal 			.tCAH_min = 5000,
3521666b815SMiquel Raynal 			.tCALH_min = 5000,
3531666b815SMiquel Raynal 			.tCALS_min = 5000,
3541666b815SMiquel Raynal 			.tCAS_min = 5000,
3551666b815SMiquel Raynal 			.tCEH_min = 20000,
3561666b815SMiquel Raynal 			.tCH_min = 5000,
3571666b815SMiquel Raynal 			.tCK_min = 30000,
3581666b815SMiquel Raynal 			.tCS_min = 25000,
3591666b815SMiquel Raynal 			.tDH_min = 2500,
3601666b815SMiquel Raynal 			.tDQSCK_min = 3000,
3611666b815SMiquel Raynal 			.tDQSCK_max = 25000,
3621666b815SMiquel Raynal 			.tDQSD_min = 0,
3631666b815SMiquel Raynal 			.tDQSD_max = 18000,
3641666b815SMiquel Raynal 			.tDQSHZ_max = 20000,
3651666b815SMiquel Raynal 			.tDQSQ_max = 2500,
3661666b815SMiquel Raynal 			.tDS_min = 3000,
3671666b815SMiquel Raynal 			.tDSC_min = 30000,
3681666b815SMiquel Raynal 			.tFEAT_max = 1000000,
3691666b815SMiquel Raynal 			.tITC_max = 1000000,
3701666b815SMiquel Raynal 			.tQHS_max = 3000,
3711666b815SMiquel Raynal 			.tRHW_min = 100000,
3721666b815SMiquel Raynal 			.tRR_min = 20000,
3731666b815SMiquel Raynal 			.tRST_max = 500000000,
3741666b815SMiquel Raynal 			.tWB_max = 100000,
3751666b815SMiquel Raynal 			.tWHR_min = 80000,
3761666b815SMiquel Raynal 			.tWRCK_min = 20000,
3771666b815SMiquel Raynal 			.tWW_min = 100000,
3781666b815SMiquel Raynal 		},
3791666b815SMiquel Raynal 	},
3801666b815SMiquel Raynal 	/* Mode 2 */
3811666b815SMiquel Raynal 	{
3821666b815SMiquel Raynal 		.type = NAND_NVDDR_IFACE,
3831666b815SMiquel Raynal 		.timings.mode = 2,
3841666b815SMiquel Raynal 		.timings.nvddr = {
3851666b815SMiquel Raynal 			.tCCS_min = 500000,
3861666b815SMiquel Raynal 			.tR_max = 200000000,
3871666b815SMiquel Raynal 			.tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
3881666b815SMiquel Raynal 			.tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
3891666b815SMiquel Raynal 			.tAC_min = 3000,
3901666b815SMiquel Raynal 			.tAC_max = 25000,
3911666b815SMiquel Raynal 			.tADL_min = 400000,
3921666b815SMiquel Raynal 			.tCAD_min = 45000,
3931666b815SMiquel Raynal 			.tCAH_min = 4000,
3941666b815SMiquel Raynal 			.tCALH_min = 4000,
3951666b815SMiquel Raynal 			.tCALS_min = 4000,
3961666b815SMiquel Raynal 			.tCAS_min = 4000,
3971666b815SMiquel Raynal 			.tCEH_min = 20000,
3981666b815SMiquel Raynal 			.tCH_min = 4000,
3991666b815SMiquel Raynal 			.tCK_min = 20000,
4001666b815SMiquel Raynal 			.tCS_min = 15000,
4011666b815SMiquel Raynal 			.tDH_min = 1700,
4021666b815SMiquel Raynal 			.tDQSCK_min = 3000,
4031666b815SMiquel Raynal 			.tDQSCK_max = 25000,
4041666b815SMiquel Raynal 			.tDQSD_min = 0,
4051666b815SMiquel Raynal 			.tDQSD_max = 18000,
4061666b815SMiquel Raynal 			.tDQSHZ_max = 20000,
4071666b815SMiquel Raynal 			.tDQSQ_max = 1700,
4081666b815SMiquel Raynal 			.tDS_min = 2000,
4091666b815SMiquel Raynal 			.tDSC_min = 20000,
4101666b815SMiquel Raynal 			.tFEAT_max = 1000000,
4111666b815SMiquel Raynal 			.tITC_max = 1000000,
4121666b815SMiquel Raynal 			.tQHS_max = 2000,
4131666b815SMiquel Raynal 			.tRHW_min = 100000,
4141666b815SMiquel Raynal 			.tRR_min = 20000,
4151666b815SMiquel Raynal 			.tRST_max = 500000000,
4161666b815SMiquel Raynal 			.tWB_max = 100000,
4171666b815SMiquel Raynal 			.tWHR_min = 80000,
4181666b815SMiquel Raynal 			.tWRCK_min = 20000,
4191666b815SMiquel Raynal 			.tWW_min = 100000,
4201666b815SMiquel Raynal 		},
4211666b815SMiquel Raynal 	},
4221666b815SMiquel Raynal 	/* Mode 3 */
4231666b815SMiquel Raynal 	{
4241666b815SMiquel Raynal 		.type = NAND_NVDDR_IFACE,
4251666b815SMiquel Raynal 		.timings.mode = 3,
4261666b815SMiquel Raynal 		.timings.nvddr = {
4271666b815SMiquel Raynal 			.tCCS_min = 500000,
4281666b815SMiquel Raynal 			.tR_max = 200000000,
4291666b815SMiquel Raynal 			.tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
4301666b815SMiquel Raynal 			.tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
4311666b815SMiquel Raynal 			.tAC_min = 3000,
4321666b815SMiquel Raynal 			.tAC_max = 25000,
4331666b815SMiquel Raynal 			.tADL_min = 400000,
4341666b815SMiquel Raynal 			.tCAD_min = 45000,
4351666b815SMiquel Raynal 			.tCAH_min = 3000,
4361666b815SMiquel Raynal 			.tCALH_min = 3000,
4371666b815SMiquel Raynal 			.tCALS_min = 3000,
4381666b815SMiquel Raynal 			.tCAS_min = 3000,
4391666b815SMiquel Raynal 			.tCEH_min = 20000,
4401666b815SMiquel Raynal 			.tCH_min = 3000,
4411666b815SMiquel Raynal 			.tCK_min = 15000,
4421666b815SMiquel Raynal 			.tCS_min = 15000,
4431666b815SMiquel Raynal 			.tDH_min = 1300,
4441666b815SMiquel Raynal 			.tDQSCK_min = 3000,
4451666b815SMiquel Raynal 			.tDQSCK_max = 25000,
4461666b815SMiquel Raynal 			.tDQSD_min = 0,
4471666b815SMiquel Raynal 			.tDQSD_max = 18000,
4481666b815SMiquel Raynal 			.tDQSHZ_max = 20000,
4491666b815SMiquel Raynal 			.tDQSQ_max = 1300,
4501666b815SMiquel Raynal 			.tDS_min = 1500,
4511666b815SMiquel Raynal 			.tDSC_min = 15000,
4521666b815SMiquel Raynal 			.tFEAT_max = 1000000,
4531666b815SMiquel Raynal 			.tITC_max = 1000000,
4541666b815SMiquel Raynal 			.tQHS_max = 1500,
4551666b815SMiquel Raynal 			.tRHW_min = 100000,
4561666b815SMiquel Raynal 			.tRR_min = 20000,
4571666b815SMiquel Raynal 			.tRST_max = 500000000,
4581666b815SMiquel Raynal 			.tWB_max = 100000,
4591666b815SMiquel Raynal 			.tWHR_min = 80000,
4601666b815SMiquel Raynal 			.tWRCK_min = 20000,
4611666b815SMiquel Raynal 			.tWW_min = 100000,
4621666b815SMiquel Raynal 		},
4631666b815SMiquel Raynal 	},
4641666b815SMiquel Raynal 	/* Mode 4 */
4651666b815SMiquel Raynal 	{
4661666b815SMiquel Raynal 		.type = NAND_NVDDR_IFACE,
4671666b815SMiquel Raynal 		.timings.mode = 4,
4681666b815SMiquel Raynal 		.timings.nvddr = {
4691666b815SMiquel Raynal 			.tCCS_min = 500000,
4701666b815SMiquel Raynal 			.tR_max = 200000000,
4711666b815SMiquel Raynal 			.tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
4721666b815SMiquel Raynal 			.tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
4731666b815SMiquel Raynal 			.tAC_min = 3000,
4741666b815SMiquel Raynal 			.tAC_max = 25000,
4751666b815SMiquel Raynal 			.tADL_min = 400000,
4761666b815SMiquel Raynal 			.tCAD_min = 45000,
4771666b815SMiquel Raynal 			.tCAH_min = 2500,
4781666b815SMiquel Raynal 			.tCALH_min = 2500,
4791666b815SMiquel Raynal 			.tCALS_min = 2500,
4801666b815SMiquel Raynal 			.tCAS_min = 2500,
4811666b815SMiquel Raynal 			.tCEH_min = 20000,
4821666b815SMiquel Raynal 			.tCH_min = 2500,
4831666b815SMiquel Raynal 			.tCK_min = 12000,
4841666b815SMiquel Raynal 			.tCS_min = 15000,
4851666b815SMiquel Raynal 			.tDH_min = 1100,
4861666b815SMiquel Raynal 			.tDQSCK_min = 3000,
4871666b815SMiquel Raynal 			.tDQSCK_max = 25000,
4881666b815SMiquel Raynal 			.tDQSD_min = 0,
4891666b815SMiquel Raynal 			.tDQSD_max = 18000,
4901666b815SMiquel Raynal 			.tDQSHZ_max = 20000,
4911666b815SMiquel Raynal 			.tDQSQ_max = 1000,
4921666b815SMiquel Raynal 			.tDS_min = 1100,
4931666b815SMiquel Raynal 			.tDSC_min = 12000,
4941666b815SMiquel Raynal 			.tFEAT_max = 1000000,
4951666b815SMiquel Raynal 			.tITC_max = 1000000,
4961666b815SMiquel Raynal 			.tQHS_max = 1200,
4971666b815SMiquel Raynal 			.tRHW_min = 100000,
4981666b815SMiquel Raynal 			.tRR_min = 20000,
4991666b815SMiquel Raynal 			.tRST_max = 500000000,
5001666b815SMiquel Raynal 			.tWB_max = 100000,
5011666b815SMiquel Raynal 			.tWHR_min = 80000,
5021666b815SMiquel Raynal 			.tWRCK_min = 20000,
5031666b815SMiquel Raynal 			.tWW_min = 100000,
5041666b815SMiquel Raynal 		},
5051666b815SMiquel Raynal 	},
5061666b815SMiquel Raynal 	/* Mode 5 */
5071666b815SMiquel Raynal 	{
5081666b815SMiquel Raynal 		.type = NAND_NVDDR_IFACE,
5091666b815SMiquel Raynal 		.timings.mode = 5,
5101666b815SMiquel Raynal 		.timings.nvddr = {
5111666b815SMiquel Raynal 			.tCCS_min = 500000,
5121666b815SMiquel Raynal 			.tR_max = 200000000,
5131666b815SMiquel Raynal 			.tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
5141666b815SMiquel Raynal 			.tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
5151666b815SMiquel Raynal 			.tAC_min = 3000,
5161666b815SMiquel Raynal 			.tAC_max = 25000,
5171666b815SMiquel Raynal 			.tADL_min = 400000,
5181666b815SMiquel Raynal 			.tCAD_min = 45000,
5191666b815SMiquel Raynal 			.tCAH_min = 2000,
5201666b815SMiquel Raynal 			.tCALH_min = 2000,
5211666b815SMiquel Raynal 			.tCALS_min = 2000,
5221666b815SMiquel Raynal 			.tCAS_min = 2000,
5231666b815SMiquel Raynal 			.tCEH_min = 20000,
5241666b815SMiquel Raynal 			.tCH_min = 2000,
5251666b815SMiquel Raynal 			.tCK_min = 10000,
5261666b815SMiquel Raynal 			.tCS_min = 15000,
5271666b815SMiquel Raynal 			.tDH_min = 900,
5281666b815SMiquel Raynal 			.tDQSCK_min = 3000,
5291666b815SMiquel Raynal 			.tDQSCK_max = 25000,
5301666b815SMiquel Raynal 			.tDQSD_min = 0,
5311666b815SMiquel Raynal 			.tDQSD_max = 18000,
5321666b815SMiquel Raynal 			.tDQSHZ_max = 20000,
5331666b815SMiquel Raynal 			.tDQSQ_max = 850,
5341666b815SMiquel Raynal 			.tDS_min = 900,
5351666b815SMiquel Raynal 			.tDSC_min = 10000,
5361666b815SMiquel Raynal 			.tFEAT_max = 1000000,
5371666b815SMiquel Raynal 			.tITC_max = 1000000,
5381666b815SMiquel Raynal 			.tQHS_max = 1000,
5391666b815SMiquel Raynal 			.tRHW_min = 100000,
5401666b815SMiquel Raynal 			.tRR_min = 20000,
5411666b815SMiquel Raynal 			.tRST_max = 500000000,
5421666b815SMiquel Raynal 			.tWB_max = 100000,
5431666b815SMiquel Raynal 			.tWHR_min = 80000,
5441666b815SMiquel Raynal 			.tWRCK_min = 20000,
5451666b815SMiquel Raynal 			.tWW_min = 100000,
5461666b815SMiquel Raynal 		},
5471666b815SMiquel Raynal 	},
5481666b815SMiquel Raynal };
5491666b815SMiquel Raynal 
55035b6bcc9SMiquel Raynal /* All NAND chips share the same reset data interface: SDR mode 0 */
55135b6bcc9SMiquel Raynal const struct nand_interface_config *nand_get_reset_interface_config(void)
55235b6bcc9SMiquel Raynal {
55335b6bcc9SMiquel Raynal 	return &onfi_sdr_timings[0];
55435b6bcc9SMiquel Raynal }
55535b6bcc9SMiquel Raynal 
556974647eaSBoris BREZILLON /**
55798d6979aSMiquel Raynal  * onfi_find_closest_sdr_mode - Derive the closest ONFI SDR timing mode given a
55898d6979aSMiquel Raynal  *                              set of timings
55998d6979aSMiquel Raynal  * @spec_timings: the timings to challenge
56098d6979aSMiquel Raynal  */
56198d6979aSMiquel Raynal unsigned int
56298d6979aSMiquel Raynal onfi_find_closest_sdr_mode(const struct nand_sdr_timings *spec_timings)
56398d6979aSMiquel Raynal {
56498d6979aSMiquel Raynal 	const struct nand_sdr_timings *onfi_timings;
56598d6979aSMiquel Raynal 	int mode;
56698d6979aSMiquel Raynal 
56798d6979aSMiquel Raynal 	for (mode = ARRAY_SIZE(onfi_sdr_timings) - 1; mode > 0; mode--) {
56898d6979aSMiquel Raynal 		onfi_timings = &onfi_sdr_timings[mode].timings.sdr;
56998d6979aSMiquel Raynal 
57098d6979aSMiquel Raynal 		if (spec_timings->tCCS_min <= onfi_timings->tCCS_min &&
57198d6979aSMiquel Raynal 		    spec_timings->tADL_min <= onfi_timings->tADL_min &&
57298d6979aSMiquel Raynal 		    spec_timings->tALH_min <= onfi_timings->tALH_min &&
57398d6979aSMiquel Raynal 		    spec_timings->tALS_min <= onfi_timings->tALS_min &&
57498d6979aSMiquel Raynal 		    spec_timings->tAR_min <= onfi_timings->tAR_min &&
57598d6979aSMiquel Raynal 		    spec_timings->tCEH_min <= onfi_timings->tCEH_min &&
57698d6979aSMiquel Raynal 		    spec_timings->tCH_min <= onfi_timings->tCH_min &&
57798d6979aSMiquel Raynal 		    spec_timings->tCLH_min <= onfi_timings->tCLH_min &&
57898d6979aSMiquel Raynal 		    spec_timings->tCLR_min <= onfi_timings->tCLR_min &&
57998d6979aSMiquel Raynal 		    spec_timings->tCLS_min <= onfi_timings->tCLS_min &&
58098d6979aSMiquel Raynal 		    spec_timings->tCOH_min <= onfi_timings->tCOH_min &&
58198d6979aSMiquel Raynal 		    spec_timings->tCS_min <= onfi_timings->tCS_min &&
58298d6979aSMiquel Raynal 		    spec_timings->tDH_min <= onfi_timings->tDH_min &&
58398d6979aSMiquel Raynal 		    spec_timings->tDS_min <= onfi_timings->tDS_min &&
58498d6979aSMiquel Raynal 		    spec_timings->tIR_min <= onfi_timings->tIR_min &&
58598d6979aSMiquel Raynal 		    spec_timings->tRC_min <= onfi_timings->tRC_min &&
58698d6979aSMiquel Raynal 		    spec_timings->tREH_min <= onfi_timings->tREH_min &&
58798d6979aSMiquel Raynal 		    spec_timings->tRHOH_min <= onfi_timings->tRHOH_min &&
58898d6979aSMiquel Raynal 		    spec_timings->tRHW_min <= onfi_timings->tRHW_min &&
58998d6979aSMiquel Raynal 		    spec_timings->tRLOH_min <= onfi_timings->tRLOH_min &&
59098d6979aSMiquel Raynal 		    spec_timings->tRP_min <= onfi_timings->tRP_min &&
59198d6979aSMiquel Raynal 		    spec_timings->tRR_min <= onfi_timings->tRR_min &&
59298d6979aSMiquel Raynal 		    spec_timings->tWC_min <= onfi_timings->tWC_min &&
59398d6979aSMiquel Raynal 		    spec_timings->tWH_min <= onfi_timings->tWH_min &&
59498d6979aSMiquel Raynal 		    spec_timings->tWHR_min <= onfi_timings->tWHR_min &&
59598d6979aSMiquel Raynal 		    spec_timings->tWP_min <= onfi_timings->tWP_min &&
59698d6979aSMiquel Raynal 		    spec_timings->tWW_min <= onfi_timings->tWW_min)
59798d6979aSMiquel Raynal 			return mode;
59898d6979aSMiquel Raynal 	}
59998d6979aSMiquel Raynal 
60098d6979aSMiquel Raynal 	return 0;
60198d6979aSMiquel Raynal }
60298d6979aSMiquel Raynal 
60398d6979aSMiquel Raynal /**
604*e32df79fSMiquel Raynal  * onfi_find_closest_nvddr_mode - Derive the closest ONFI NVDDR timing mode
605*e32df79fSMiquel Raynal  *                                given a set of timings
606*e32df79fSMiquel Raynal  * @spec_timings: the timings to challenge
607*e32df79fSMiquel Raynal  */
608*e32df79fSMiquel Raynal unsigned int
609*e32df79fSMiquel Raynal onfi_find_closest_nvddr_mode(const struct nand_nvddr_timings *spec_timings)
610*e32df79fSMiquel Raynal {
611*e32df79fSMiquel Raynal 	const struct nand_nvddr_timings *onfi_timings;
612*e32df79fSMiquel Raynal 	int mode;
613*e32df79fSMiquel Raynal 
614*e32df79fSMiquel Raynal 	for (mode = ARRAY_SIZE(onfi_nvddr_timings) - 1; mode > 0; mode--) {
615*e32df79fSMiquel Raynal 		onfi_timings = &onfi_nvddr_timings[mode].timings.nvddr;
616*e32df79fSMiquel Raynal 
617*e32df79fSMiquel Raynal 		if (spec_timings->tCCS_min <= onfi_timings->tCCS_min &&
618*e32df79fSMiquel Raynal 		    spec_timings->tAC_min <= onfi_timings->tAC_min &&
619*e32df79fSMiquel Raynal 		    spec_timings->tADL_min <= onfi_timings->tADL_min &&
620*e32df79fSMiquel Raynal 		    spec_timings->tCAD_min <= onfi_timings->tCAD_min &&
621*e32df79fSMiquel Raynal 		    spec_timings->tCAH_min <= onfi_timings->tCAH_min &&
622*e32df79fSMiquel Raynal 		    spec_timings->tCALH_min <= onfi_timings->tCALH_min &&
623*e32df79fSMiquel Raynal 		    spec_timings->tCALS_min <= onfi_timings->tCALS_min &&
624*e32df79fSMiquel Raynal 		    spec_timings->tCAS_min <= onfi_timings->tCAS_min &&
625*e32df79fSMiquel Raynal 		    spec_timings->tCEH_min <= onfi_timings->tCEH_min &&
626*e32df79fSMiquel Raynal 		    spec_timings->tCH_min <= onfi_timings->tCH_min &&
627*e32df79fSMiquel Raynal 		    spec_timings->tCK_min <= onfi_timings->tCK_min &&
628*e32df79fSMiquel Raynal 		    spec_timings->tCS_min <= onfi_timings->tCS_min &&
629*e32df79fSMiquel Raynal 		    spec_timings->tDH_min <= onfi_timings->tDH_min &&
630*e32df79fSMiquel Raynal 		    spec_timings->tDQSCK_min <= onfi_timings->tDQSCK_min &&
631*e32df79fSMiquel Raynal 		    spec_timings->tDQSD_min <= onfi_timings->tDQSD_min &&
632*e32df79fSMiquel Raynal 		    spec_timings->tDS_min <= onfi_timings->tDS_min &&
633*e32df79fSMiquel Raynal 		    spec_timings->tDSC_min <= onfi_timings->tDSC_min &&
634*e32df79fSMiquel Raynal 		    spec_timings->tRHW_min <= onfi_timings->tRHW_min &&
635*e32df79fSMiquel Raynal 		    spec_timings->tRR_min <= onfi_timings->tRR_min &&
636*e32df79fSMiquel Raynal 		    spec_timings->tWHR_min <= onfi_timings->tWHR_min &&
637*e32df79fSMiquel Raynal 		    spec_timings->tWRCK_min <= onfi_timings->tWRCK_min &&
638*e32df79fSMiquel Raynal 		    spec_timings->tWW_min <= onfi_timings->tWW_min)
639*e32df79fSMiquel Raynal 			return mode;
640*e32df79fSMiquel Raynal 	}
641*e32df79fSMiquel Raynal 
642*e32df79fSMiquel Raynal 	return 0;
643*e32df79fSMiquel Raynal }
644*e32df79fSMiquel Raynal 
645*e32df79fSMiquel Raynal /*
64694c8ce8eSMiquel Raynal  * onfi_fill_sdr_interface_config - Initialize a SDR interface config from a
64794c8ce8eSMiquel Raynal  *                                  given ONFI mode
648844cc464SMiquel Raynal  * @chip: The NAND chip
6494c46667bSMiquel Raynal  * @iface: The interface configuration to fill
650844cc464SMiquel Raynal  * @timing_mode: The ONFI timing mode
651b88730adSSascha Hauer  */
65294c8ce8eSMiquel Raynal static void onfi_fill_sdr_interface_config(struct nand_chip *chip,
6534c46667bSMiquel Raynal 					   struct nand_interface_config *iface,
654fcaab3b2SMiquel Raynal 					   unsigned int timing_mode)
655b88730adSSascha Hauer {
6563d3fe3c0SMiquel Raynal 	struct onfi_params *onfi = chip->parameters.onfi;
65717fa8044SMiquel Raynal 
65842a9ad05SMiquel Raynal 	if (WARN_ON(timing_mode >= ARRAY_SIZE(onfi_sdr_timings)))
65942a9ad05SMiquel Raynal 		return;
660b88730adSSascha Hauer 
661b88730adSSascha Hauer 	*iface = onfi_sdr_timings[timing_mode];
662b88730adSSascha Hauer 
663b88730adSSascha Hauer 	/*
664204e7ecdSBoris Brezillon 	 * Initialize timings that cannot be deduced from timing mode:
6656a943386SMiquel Raynal 	 * tPROG, tBERS, tR and tCCS.
666b88730adSSascha Hauer 	 * These information are part of the ONFI parameter page.
667b88730adSSascha Hauer 	 */
6683d3fe3c0SMiquel Raynal 	if (onfi) {
669204e7ecdSBoris Brezillon 		struct nand_sdr_timings *timings = &iface->timings.sdr;
670204e7ecdSBoris Brezillon 
671204e7ecdSBoris Brezillon 		/* microseconds -> picoseconds */
6723d3fe3c0SMiquel Raynal 		timings->tPROG_max = 1000000ULL * onfi->tPROG;
6733d3fe3c0SMiquel Raynal 		timings->tBERS_max = 1000000ULL * onfi->tBERS;
6743d3fe3c0SMiquel Raynal 		timings->tR_max = 1000000ULL * onfi->tR;
675204e7ecdSBoris Brezillon 
676204e7ecdSBoris Brezillon 		/* nanoseconds -> picoseconds */
6773d3fe3c0SMiquel Raynal 		timings->tCCS_min = 1000UL * onfi->tCCS;
678204e7ecdSBoris Brezillon 	}
679b88730adSSascha Hauer }
68094c8ce8eSMiquel Raynal 
68194c8ce8eSMiquel Raynal /**
68245606518SMiquel Raynal  * onfi_fill_nvddr_interface_config - Initialize a NVDDR interface config from a
68345606518SMiquel Raynal  *                                    given ONFI mode
68445606518SMiquel Raynal  * @chip: The NAND chip
68545606518SMiquel Raynal  * @iface: The interface configuration to fill
68645606518SMiquel Raynal  * @timing_mode: The ONFI timing mode
68745606518SMiquel Raynal  */
68845606518SMiquel Raynal static void onfi_fill_nvddr_interface_config(struct nand_chip *chip,
68945606518SMiquel Raynal 					     struct nand_interface_config *iface,
69045606518SMiquel Raynal 					     unsigned int timing_mode)
69145606518SMiquel Raynal {
69245606518SMiquel Raynal 	struct onfi_params *onfi = chip->parameters.onfi;
69345606518SMiquel Raynal 
69445606518SMiquel Raynal 	if (WARN_ON(timing_mode >= ARRAY_SIZE(onfi_nvddr_timings)))
69545606518SMiquel Raynal 		return;
69645606518SMiquel Raynal 
69745606518SMiquel Raynal 	*iface = onfi_nvddr_timings[timing_mode];
69845606518SMiquel Raynal 
69945606518SMiquel Raynal 	/*
70045606518SMiquel Raynal 	 * Initialize timings that cannot be deduced from timing mode:
70145606518SMiquel Raynal 	 * tPROG, tBERS, tR, tCCS and tCAD.
70245606518SMiquel Raynal 	 * These information are part of the ONFI parameter page.
70345606518SMiquel Raynal 	 */
70445606518SMiquel Raynal 	if (onfi) {
70545606518SMiquel Raynal 		struct nand_nvddr_timings *timings = &iface->timings.nvddr;
70645606518SMiquel Raynal 
70745606518SMiquel Raynal 		/* microseconds -> picoseconds */
70845606518SMiquel Raynal 		timings->tPROG_max = 1000000ULL * onfi->tPROG;
70945606518SMiquel Raynal 		timings->tBERS_max = 1000000ULL * onfi->tBERS;
71045606518SMiquel Raynal 		timings->tR_max = 1000000ULL * onfi->tR;
71145606518SMiquel Raynal 
71245606518SMiquel Raynal 		/* nanoseconds -> picoseconds */
71345606518SMiquel Raynal 		timings->tCCS_min = 1000UL * onfi->tCCS;
71445606518SMiquel Raynal 
71545606518SMiquel Raynal 		if (onfi->fast_tCAD)
71645606518SMiquel Raynal 			timings->tCAD_min = 25000;
71745606518SMiquel Raynal 	}
71845606518SMiquel Raynal }
71945606518SMiquel Raynal 
72045606518SMiquel Raynal /**
72194c8ce8eSMiquel Raynal  * onfi_fill_interface_config - Initialize an interface config from a given
72294c8ce8eSMiquel Raynal  *                              ONFI mode
72394c8ce8eSMiquel Raynal  * @chip: The NAND chip
72494c8ce8eSMiquel Raynal  * @iface: The interface configuration to fill
72594c8ce8eSMiquel Raynal  * @type: The interface type
72694c8ce8eSMiquel Raynal  * @timing_mode: The ONFI timing mode
72794c8ce8eSMiquel Raynal  */
72894c8ce8eSMiquel Raynal void onfi_fill_interface_config(struct nand_chip *chip,
72994c8ce8eSMiquel Raynal 				struct nand_interface_config *iface,
73094c8ce8eSMiquel Raynal 				enum nand_interface_type type,
73194c8ce8eSMiquel Raynal 				unsigned int timing_mode)
73294c8ce8eSMiquel Raynal {
73394c8ce8eSMiquel Raynal 	if (type == NAND_SDR_IFACE)
73494c8ce8eSMiquel Raynal 		return onfi_fill_sdr_interface_config(chip, iface, timing_mode);
73545606518SMiquel Raynal 	else
73645606518SMiquel Raynal 		return onfi_fill_nvddr_interface_config(chip, iface, timing_mode);
73794c8ce8eSMiquel Raynal }
738