xref: /OK3568_Linux_fs/kernel/drivers/mtd/nand/raw/nand_timings.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  *  Copyright (C) 2014 Free Electrons
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  *  Author: Boris BREZILLON <boris.brezillon@free-electrons.com>
6*4882a593Smuzhiyun  */
7*4882a593Smuzhiyun #include <linux/kernel.h>
8*4882a593Smuzhiyun #include <linux/err.h>
9*4882a593Smuzhiyun #include <linux/export.h>
10*4882a593Smuzhiyun 
11*4882a593Smuzhiyun #include "internals.h"
12*4882a593Smuzhiyun 
13*4882a593Smuzhiyun #define ONFI_DYN_TIMING_MAX U16_MAX
14*4882a593Smuzhiyun 
15*4882a593Smuzhiyun /*
16*4882a593Smuzhiyun  * For non-ONFI chips we use the highest possible value for tPROG and tBERS.
17*4882a593Smuzhiyun  * tR and tCCS will take the default values precised in the ONFI specification
18*4882a593Smuzhiyun  * for timing mode 0, respectively 200us and 500ns.
19*4882a593Smuzhiyun  *
20*4882a593Smuzhiyun  * These four values are tweaked to be more accurate in the case of ONFI chips.
21*4882a593Smuzhiyun  */
22*4882a593Smuzhiyun static const struct nand_interface_config onfi_sdr_timings[] = {
23*4882a593Smuzhiyun 	/* Mode 0 */
24*4882a593Smuzhiyun 	{
25*4882a593Smuzhiyun 		.type = NAND_SDR_IFACE,
26*4882a593Smuzhiyun 		.timings.mode = 0,
27*4882a593Smuzhiyun 		.timings.sdr = {
28*4882a593Smuzhiyun 			.tCCS_min = 500000,
29*4882a593Smuzhiyun 			.tR_max = 200000000,
30*4882a593Smuzhiyun 			.tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
31*4882a593Smuzhiyun 			.tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
32*4882a593Smuzhiyun 			.tADL_min = 400000,
33*4882a593Smuzhiyun 			.tALH_min = 20000,
34*4882a593Smuzhiyun 			.tALS_min = 50000,
35*4882a593Smuzhiyun 			.tAR_min = 25000,
36*4882a593Smuzhiyun 			.tCEA_max = 100000,
37*4882a593Smuzhiyun 			.tCEH_min = 20000,
38*4882a593Smuzhiyun 			.tCH_min = 20000,
39*4882a593Smuzhiyun 			.tCHZ_max = 100000,
40*4882a593Smuzhiyun 			.tCLH_min = 20000,
41*4882a593Smuzhiyun 			.tCLR_min = 20000,
42*4882a593Smuzhiyun 			.tCLS_min = 50000,
43*4882a593Smuzhiyun 			.tCOH_min = 0,
44*4882a593Smuzhiyun 			.tCS_min = 70000,
45*4882a593Smuzhiyun 			.tDH_min = 20000,
46*4882a593Smuzhiyun 			.tDS_min = 40000,
47*4882a593Smuzhiyun 			.tFEAT_max = 1000000,
48*4882a593Smuzhiyun 			.tIR_min = 10000,
49*4882a593Smuzhiyun 			.tITC_max = 1000000,
50*4882a593Smuzhiyun 			.tRC_min = 100000,
51*4882a593Smuzhiyun 			.tREA_max = 40000,
52*4882a593Smuzhiyun 			.tREH_min = 30000,
53*4882a593Smuzhiyun 			.tRHOH_min = 0,
54*4882a593Smuzhiyun 			.tRHW_min = 200000,
55*4882a593Smuzhiyun 			.tRHZ_max = 200000,
56*4882a593Smuzhiyun 			.tRLOH_min = 0,
57*4882a593Smuzhiyun 			.tRP_min = 50000,
58*4882a593Smuzhiyun 			.tRR_min = 40000,
59*4882a593Smuzhiyun 			.tRST_max = 250000000000ULL,
60*4882a593Smuzhiyun 			.tWB_max = 200000,
61*4882a593Smuzhiyun 			.tWC_min = 100000,
62*4882a593Smuzhiyun 			.tWH_min = 30000,
63*4882a593Smuzhiyun 			.tWHR_min = 120000,
64*4882a593Smuzhiyun 			.tWP_min = 50000,
65*4882a593Smuzhiyun 			.tWW_min = 100000,
66*4882a593Smuzhiyun 		},
67*4882a593Smuzhiyun 	},
68*4882a593Smuzhiyun 	/* Mode 1 */
69*4882a593Smuzhiyun 	{
70*4882a593Smuzhiyun 		.type = NAND_SDR_IFACE,
71*4882a593Smuzhiyun 		.timings.mode = 1,
72*4882a593Smuzhiyun 		.timings.sdr = {
73*4882a593Smuzhiyun 			.tCCS_min = 500000,
74*4882a593Smuzhiyun 			.tR_max = 200000000,
75*4882a593Smuzhiyun 			.tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
76*4882a593Smuzhiyun 			.tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
77*4882a593Smuzhiyun 			.tADL_min = 400000,
78*4882a593Smuzhiyun 			.tALH_min = 10000,
79*4882a593Smuzhiyun 			.tALS_min = 25000,
80*4882a593Smuzhiyun 			.tAR_min = 10000,
81*4882a593Smuzhiyun 			.tCEA_max = 45000,
82*4882a593Smuzhiyun 			.tCEH_min = 20000,
83*4882a593Smuzhiyun 			.tCH_min = 10000,
84*4882a593Smuzhiyun 			.tCHZ_max = 50000,
85*4882a593Smuzhiyun 			.tCLH_min = 10000,
86*4882a593Smuzhiyun 			.tCLR_min = 10000,
87*4882a593Smuzhiyun 			.tCLS_min = 25000,
88*4882a593Smuzhiyun 			.tCOH_min = 15000,
89*4882a593Smuzhiyun 			.tCS_min = 35000,
90*4882a593Smuzhiyun 			.tDH_min = 10000,
91*4882a593Smuzhiyun 			.tDS_min = 20000,
92*4882a593Smuzhiyun 			.tFEAT_max = 1000000,
93*4882a593Smuzhiyun 			.tIR_min = 0,
94*4882a593Smuzhiyun 			.tITC_max = 1000000,
95*4882a593Smuzhiyun 			.tRC_min = 50000,
96*4882a593Smuzhiyun 			.tREA_max = 30000,
97*4882a593Smuzhiyun 			.tREH_min = 15000,
98*4882a593Smuzhiyun 			.tRHOH_min = 15000,
99*4882a593Smuzhiyun 			.tRHW_min = 100000,
100*4882a593Smuzhiyun 			.tRHZ_max = 100000,
101*4882a593Smuzhiyun 			.tRLOH_min = 0,
102*4882a593Smuzhiyun 			.tRP_min = 25000,
103*4882a593Smuzhiyun 			.tRR_min = 20000,
104*4882a593Smuzhiyun 			.tRST_max = 500000000,
105*4882a593Smuzhiyun 			.tWB_max = 100000,
106*4882a593Smuzhiyun 			.tWC_min = 45000,
107*4882a593Smuzhiyun 			.tWH_min = 15000,
108*4882a593Smuzhiyun 			.tWHR_min = 80000,
109*4882a593Smuzhiyun 			.tWP_min = 25000,
110*4882a593Smuzhiyun 			.tWW_min = 100000,
111*4882a593Smuzhiyun 		},
112*4882a593Smuzhiyun 	},
113*4882a593Smuzhiyun 	/* Mode 2 */
114*4882a593Smuzhiyun 	{
115*4882a593Smuzhiyun 		.type = NAND_SDR_IFACE,
116*4882a593Smuzhiyun 		.timings.mode = 2,
117*4882a593Smuzhiyun 		.timings.sdr = {
118*4882a593Smuzhiyun 			.tCCS_min = 500000,
119*4882a593Smuzhiyun 			.tR_max = 200000000,
120*4882a593Smuzhiyun 			.tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
121*4882a593Smuzhiyun 			.tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
122*4882a593Smuzhiyun 			.tADL_min = 400000,
123*4882a593Smuzhiyun 			.tALH_min = 10000,
124*4882a593Smuzhiyun 			.tALS_min = 15000,
125*4882a593Smuzhiyun 			.tAR_min = 10000,
126*4882a593Smuzhiyun 			.tCEA_max = 30000,
127*4882a593Smuzhiyun 			.tCEH_min = 20000,
128*4882a593Smuzhiyun 			.tCH_min = 10000,
129*4882a593Smuzhiyun 			.tCHZ_max = 50000,
130*4882a593Smuzhiyun 			.tCLH_min = 10000,
131*4882a593Smuzhiyun 			.tCLR_min = 10000,
132*4882a593Smuzhiyun 			.tCLS_min = 15000,
133*4882a593Smuzhiyun 			.tCOH_min = 15000,
134*4882a593Smuzhiyun 			.tCS_min = 25000,
135*4882a593Smuzhiyun 			.tDH_min = 5000,
136*4882a593Smuzhiyun 			.tDS_min = 15000,
137*4882a593Smuzhiyun 			.tFEAT_max = 1000000,
138*4882a593Smuzhiyun 			.tIR_min = 0,
139*4882a593Smuzhiyun 			.tITC_max = 1000000,
140*4882a593Smuzhiyun 			.tRC_min = 35000,
141*4882a593Smuzhiyun 			.tREA_max = 25000,
142*4882a593Smuzhiyun 			.tREH_min = 15000,
143*4882a593Smuzhiyun 			.tRHOH_min = 15000,
144*4882a593Smuzhiyun 			.tRHW_min = 100000,
145*4882a593Smuzhiyun 			.tRHZ_max = 100000,
146*4882a593Smuzhiyun 			.tRLOH_min = 0,
147*4882a593Smuzhiyun 			.tRR_min = 20000,
148*4882a593Smuzhiyun 			.tRST_max = 500000000,
149*4882a593Smuzhiyun 			.tWB_max = 100000,
150*4882a593Smuzhiyun 			.tRP_min = 17000,
151*4882a593Smuzhiyun 			.tWC_min = 35000,
152*4882a593Smuzhiyun 			.tWH_min = 15000,
153*4882a593Smuzhiyun 			.tWHR_min = 80000,
154*4882a593Smuzhiyun 			.tWP_min = 17000,
155*4882a593Smuzhiyun 			.tWW_min = 100000,
156*4882a593Smuzhiyun 		},
157*4882a593Smuzhiyun 	},
158*4882a593Smuzhiyun 	/* Mode 3 */
159*4882a593Smuzhiyun 	{
160*4882a593Smuzhiyun 		.type = NAND_SDR_IFACE,
161*4882a593Smuzhiyun 		.timings.mode = 3,
162*4882a593Smuzhiyun 		.timings.sdr = {
163*4882a593Smuzhiyun 			.tCCS_min = 500000,
164*4882a593Smuzhiyun 			.tR_max = 200000000,
165*4882a593Smuzhiyun 			.tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
166*4882a593Smuzhiyun 			.tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
167*4882a593Smuzhiyun 			.tADL_min = 400000,
168*4882a593Smuzhiyun 			.tALH_min = 5000,
169*4882a593Smuzhiyun 			.tALS_min = 10000,
170*4882a593Smuzhiyun 			.tAR_min = 10000,
171*4882a593Smuzhiyun 			.tCEA_max = 25000,
172*4882a593Smuzhiyun 			.tCEH_min = 20000,
173*4882a593Smuzhiyun 			.tCH_min = 5000,
174*4882a593Smuzhiyun 			.tCHZ_max = 50000,
175*4882a593Smuzhiyun 			.tCLH_min = 5000,
176*4882a593Smuzhiyun 			.tCLR_min = 10000,
177*4882a593Smuzhiyun 			.tCLS_min = 10000,
178*4882a593Smuzhiyun 			.tCOH_min = 15000,
179*4882a593Smuzhiyun 			.tCS_min = 25000,
180*4882a593Smuzhiyun 			.tDH_min = 5000,
181*4882a593Smuzhiyun 			.tDS_min = 10000,
182*4882a593Smuzhiyun 			.tFEAT_max = 1000000,
183*4882a593Smuzhiyun 			.tIR_min = 0,
184*4882a593Smuzhiyun 			.tITC_max = 1000000,
185*4882a593Smuzhiyun 			.tRC_min = 30000,
186*4882a593Smuzhiyun 			.tREA_max = 20000,
187*4882a593Smuzhiyun 			.tREH_min = 10000,
188*4882a593Smuzhiyun 			.tRHOH_min = 15000,
189*4882a593Smuzhiyun 			.tRHW_min = 100000,
190*4882a593Smuzhiyun 			.tRHZ_max = 100000,
191*4882a593Smuzhiyun 			.tRLOH_min = 0,
192*4882a593Smuzhiyun 			.tRP_min = 15000,
193*4882a593Smuzhiyun 			.tRR_min = 20000,
194*4882a593Smuzhiyun 			.tRST_max = 500000000,
195*4882a593Smuzhiyun 			.tWB_max = 100000,
196*4882a593Smuzhiyun 			.tWC_min = 30000,
197*4882a593Smuzhiyun 			.tWH_min = 10000,
198*4882a593Smuzhiyun 			.tWHR_min = 80000,
199*4882a593Smuzhiyun 			.tWP_min = 15000,
200*4882a593Smuzhiyun 			.tWW_min = 100000,
201*4882a593Smuzhiyun 		},
202*4882a593Smuzhiyun 	},
203*4882a593Smuzhiyun 	/* Mode 4 */
204*4882a593Smuzhiyun 	{
205*4882a593Smuzhiyun 		.type = NAND_SDR_IFACE,
206*4882a593Smuzhiyun 		.timings.mode = 4,
207*4882a593Smuzhiyun 		.timings.sdr = {
208*4882a593Smuzhiyun 			.tCCS_min = 500000,
209*4882a593Smuzhiyun 			.tR_max = 200000000,
210*4882a593Smuzhiyun 			.tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
211*4882a593Smuzhiyun 			.tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
212*4882a593Smuzhiyun 			.tADL_min = 400000,
213*4882a593Smuzhiyun 			.tALH_min = 5000,
214*4882a593Smuzhiyun 			.tALS_min = 10000,
215*4882a593Smuzhiyun 			.tAR_min = 10000,
216*4882a593Smuzhiyun 			.tCEA_max = 25000,
217*4882a593Smuzhiyun 			.tCEH_min = 20000,
218*4882a593Smuzhiyun 			.tCH_min = 5000,
219*4882a593Smuzhiyun 			.tCHZ_max = 30000,
220*4882a593Smuzhiyun 			.tCLH_min = 5000,
221*4882a593Smuzhiyun 			.tCLR_min = 10000,
222*4882a593Smuzhiyun 			.tCLS_min = 10000,
223*4882a593Smuzhiyun 			.tCOH_min = 15000,
224*4882a593Smuzhiyun 			.tCS_min = 20000,
225*4882a593Smuzhiyun 			.tDH_min = 5000,
226*4882a593Smuzhiyun 			.tDS_min = 10000,
227*4882a593Smuzhiyun 			.tFEAT_max = 1000000,
228*4882a593Smuzhiyun 			.tIR_min = 0,
229*4882a593Smuzhiyun 			.tITC_max = 1000000,
230*4882a593Smuzhiyun 			.tRC_min = 25000,
231*4882a593Smuzhiyun 			.tREA_max = 20000,
232*4882a593Smuzhiyun 			.tREH_min = 10000,
233*4882a593Smuzhiyun 			.tRHOH_min = 15000,
234*4882a593Smuzhiyun 			.tRHW_min = 100000,
235*4882a593Smuzhiyun 			.tRHZ_max = 100000,
236*4882a593Smuzhiyun 			.tRLOH_min = 5000,
237*4882a593Smuzhiyun 			.tRP_min = 12000,
238*4882a593Smuzhiyun 			.tRR_min = 20000,
239*4882a593Smuzhiyun 			.tRST_max = 500000000,
240*4882a593Smuzhiyun 			.tWB_max = 100000,
241*4882a593Smuzhiyun 			.tWC_min = 25000,
242*4882a593Smuzhiyun 			.tWH_min = 10000,
243*4882a593Smuzhiyun 			.tWHR_min = 80000,
244*4882a593Smuzhiyun 			.tWP_min = 12000,
245*4882a593Smuzhiyun 			.tWW_min = 100000,
246*4882a593Smuzhiyun 		},
247*4882a593Smuzhiyun 	},
248*4882a593Smuzhiyun 	/* Mode 5 */
249*4882a593Smuzhiyun 	{
250*4882a593Smuzhiyun 		.type = NAND_SDR_IFACE,
251*4882a593Smuzhiyun 		.timings.mode = 5,
252*4882a593Smuzhiyun 		.timings.sdr = {
253*4882a593Smuzhiyun 			.tCCS_min = 500000,
254*4882a593Smuzhiyun 			.tR_max = 200000000,
255*4882a593Smuzhiyun 			.tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
256*4882a593Smuzhiyun 			.tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
257*4882a593Smuzhiyun 			.tADL_min = 400000,
258*4882a593Smuzhiyun 			.tALH_min = 5000,
259*4882a593Smuzhiyun 			.tALS_min = 10000,
260*4882a593Smuzhiyun 			.tAR_min = 10000,
261*4882a593Smuzhiyun 			.tCEA_max = 25000,
262*4882a593Smuzhiyun 			.tCEH_min = 20000,
263*4882a593Smuzhiyun 			.tCH_min = 5000,
264*4882a593Smuzhiyun 			.tCHZ_max = 30000,
265*4882a593Smuzhiyun 			.tCLH_min = 5000,
266*4882a593Smuzhiyun 			.tCLR_min = 10000,
267*4882a593Smuzhiyun 			.tCLS_min = 10000,
268*4882a593Smuzhiyun 			.tCOH_min = 15000,
269*4882a593Smuzhiyun 			.tCS_min = 15000,
270*4882a593Smuzhiyun 			.tDH_min = 5000,
271*4882a593Smuzhiyun 			.tDS_min = 7000,
272*4882a593Smuzhiyun 			.tFEAT_max = 1000000,
273*4882a593Smuzhiyun 			.tIR_min = 0,
274*4882a593Smuzhiyun 			.tITC_max = 1000000,
275*4882a593Smuzhiyun 			.tRC_min = 20000,
276*4882a593Smuzhiyun 			.tREA_max = 16000,
277*4882a593Smuzhiyun 			.tREH_min = 7000,
278*4882a593Smuzhiyun 			.tRHOH_min = 15000,
279*4882a593Smuzhiyun 			.tRHW_min = 100000,
280*4882a593Smuzhiyun 			.tRHZ_max = 100000,
281*4882a593Smuzhiyun 			.tRLOH_min = 5000,
282*4882a593Smuzhiyun 			.tRP_min = 10000,
283*4882a593Smuzhiyun 			.tRR_min = 20000,
284*4882a593Smuzhiyun 			.tRST_max = 500000000,
285*4882a593Smuzhiyun 			.tWB_max = 100000,
286*4882a593Smuzhiyun 			.tWC_min = 20000,
287*4882a593Smuzhiyun 			.tWH_min = 7000,
288*4882a593Smuzhiyun 			.tWHR_min = 80000,
289*4882a593Smuzhiyun 			.tWP_min = 10000,
290*4882a593Smuzhiyun 			.tWW_min = 100000,
291*4882a593Smuzhiyun 		},
292*4882a593Smuzhiyun 	},
293*4882a593Smuzhiyun };
294*4882a593Smuzhiyun 
295*4882a593Smuzhiyun static const struct nand_interface_config onfi_nvddr_timings[] = {
296*4882a593Smuzhiyun 	/* Mode 0 */
297*4882a593Smuzhiyun 	{
298*4882a593Smuzhiyun 		.type = NAND_NVDDR_IFACE,
299*4882a593Smuzhiyun 		.timings.mode = 0,
300*4882a593Smuzhiyun 		.timings.nvddr = {
301*4882a593Smuzhiyun 			.tCCS_min = 500000,
302*4882a593Smuzhiyun 			.tR_max = 200000000,
303*4882a593Smuzhiyun 			.tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
304*4882a593Smuzhiyun 			.tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
305*4882a593Smuzhiyun 			.tAC_min = 3000,
306*4882a593Smuzhiyun 			.tAC_max = 25000,
307*4882a593Smuzhiyun 			.tADL_min = 400000,
308*4882a593Smuzhiyun 			.tCAD_min = 45000,
309*4882a593Smuzhiyun 			.tCAH_min = 10000,
310*4882a593Smuzhiyun 			.tCALH_min = 10000,
311*4882a593Smuzhiyun 			.tCALS_min = 10000,
312*4882a593Smuzhiyun 			.tCAS_min = 10000,
313*4882a593Smuzhiyun 			.tCEH_min = 20000,
314*4882a593Smuzhiyun 			.tCH_min = 10000,
315*4882a593Smuzhiyun 			.tCK_min = 50000,
316*4882a593Smuzhiyun 			.tCS_min = 35000,
317*4882a593Smuzhiyun 			.tDH_min = 5000,
318*4882a593Smuzhiyun 			.tDQSCK_min = 3000,
319*4882a593Smuzhiyun 			.tDQSCK_max = 25000,
320*4882a593Smuzhiyun 			.tDQSD_min = 0,
321*4882a593Smuzhiyun 			.tDQSD_max = 18000,
322*4882a593Smuzhiyun 			.tDQSHZ_max = 20000,
323*4882a593Smuzhiyun 			.tDQSQ_max = 5000,
324*4882a593Smuzhiyun 			.tDS_min = 5000,
325*4882a593Smuzhiyun 			.tDSC_min = 50000,
326*4882a593Smuzhiyun 			.tFEAT_max = 1000000,
327*4882a593Smuzhiyun 			.tITC_max = 1000000,
328*4882a593Smuzhiyun 			.tQHS_max = 6000,
329*4882a593Smuzhiyun 			.tRHW_min = 100000,
330*4882a593Smuzhiyun 			.tRR_min = 20000,
331*4882a593Smuzhiyun 			.tRST_max = 500000000,
332*4882a593Smuzhiyun 			.tWB_max = 100000,
333*4882a593Smuzhiyun 			.tWHR_min = 80000,
334*4882a593Smuzhiyun 			.tWRCK_min = 20000,
335*4882a593Smuzhiyun 			.tWW_min = 100000,
336*4882a593Smuzhiyun 		},
337*4882a593Smuzhiyun 	},
338*4882a593Smuzhiyun 	/* Mode 1 */
339*4882a593Smuzhiyun 	{
340*4882a593Smuzhiyun 		.type = NAND_NVDDR_IFACE,
341*4882a593Smuzhiyun 		.timings.mode = 1,
342*4882a593Smuzhiyun 		.timings.nvddr = {
343*4882a593Smuzhiyun 			.tCCS_min = 500000,
344*4882a593Smuzhiyun 			.tR_max = 200000000,
345*4882a593Smuzhiyun 			.tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
346*4882a593Smuzhiyun 			.tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
347*4882a593Smuzhiyun 			.tAC_min = 3000,
348*4882a593Smuzhiyun 			.tAC_max = 25000,
349*4882a593Smuzhiyun 			.tADL_min = 400000,
350*4882a593Smuzhiyun 			.tCAD_min = 45000,
351*4882a593Smuzhiyun 			.tCAH_min = 5000,
352*4882a593Smuzhiyun 			.tCALH_min = 5000,
353*4882a593Smuzhiyun 			.tCALS_min = 5000,
354*4882a593Smuzhiyun 			.tCAS_min = 5000,
355*4882a593Smuzhiyun 			.tCEH_min = 20000,
356*4882a593Smuzhiyun 			.tCH_min = 5000,
357*4882a593Smuzhiyun 			.tCK_min = 30000,
358*4882a593Smuzhiyun 			.tCS_min = 25000,
359*4882a593Smuzhiyun 			.tDH_min = 2500,
360*4882a593Smuzhiyun 			.tDQSCK_min = 3000,
361*4882a593Smuzhiyun 			.tDQSCK_max = 25000,
362*4882a593Smuzhiyun 			.tDQSD_min = 0,
363*4882a593Smuzhiyun 			.tDQSD_max = 18000,
364*4882a593Smuzhiyun 			.tDQSHZ_max = 20000,
365*4882a593Smuzhiyun 			.tDQSQ_max = 2500,
366*4882a593Smuzhiyun 			.tDS_min = 3000,
367*4882a593Smuzhiyun 			.tDSC_min = 30000,
368*4882a593Smuzhiyun 			.tFEAT_max = 1000000,
369*4882a593Smuzhiyun 			.tITC_max = 1000000,
370*4882a593Smuzhiyun 			.tQHS_max = 3000,
371*4882a593Smuzhiyun 			.tRHW_min = 100000,
372*4882a593Smuzhiyun 			.tRR_min = 20000,
373*4882a593Smuzhiyun 			.tRST_max = 500000000,
374*4882a593Smuzhiyun 			.tWB_max = 100000,
375*4882a593Smuzhiyun 			.tWHR_min = 80000,
376*4882a593Smuzhiyun 			.tWRCK_min = 20000,
377*4882a593Smuzhiyun 			.tWW_min = 100000,
378*4882a593Smuzhiyun 		},
379*4882a593Smuzhiyun 	},
380*4882a593Smuzhiyun 	/* Mode 2 */
381*4882a593Smuzhiyun 	{
382*4882a593Smuzhiyun 		.type = NAND_NVDDR_IFACE,
383*4882a593Smuzhiyun 		.timings.mode = 2,
384*4882a593Smuzhiyun 		.timings.nvddr = {
385*4882a593Smuzhiyun 			.tCCS_min = 500000,
386*4882a593Smuzhiyun 			.tR_max = 200000000,
387*4882a593Smuzhiyun 			.tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
388*4882a593Smuzhiyun 			.tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
389*4882a593Smuzhiyun 			.tAC_min = 3000,
390*4882a593Smuzhiyun 			.tAC_max = 25000,
391*4882a593Smuzhiyun 			.tADL_min = 400000,
392*4882a593Smuzhiyun 			.tCAD_min = 45000,
393*4882a593Smuzhiyun 			.tCAH_min = 4000,
394*4882a593Smuzhiyun 			.tCALH_min = 4000,
395*4882a593Smuzhiyun 			.tCALS_min = 4000,
396*4882a593Smuzhiyun 			.tCAS_min = 4000,
397*4882a593Smuzhiyun 			.tCEH_min = 20000,
398*4882a593Smuzhiyun 			.tCH_min = 4000,
399*4882a593Smuzhiyun 			.tCK_min = 20000,
400*4882a593Smuzhiyun 			.tCS_min = 15000,
401*4882a593Smuzhiyun 			.tDH_min = 1700,
402*4882a593Smuzhiyun 			.tDQSCK_min = 3000,
403*4882a593Smuzhiyun 			.tDQSCK_max = 25000,
404*4882a593Smuzhiyun 			.tDQSD_min = 0,
405*4882a593Smuzhiyun 			.tDQSD_max = 18000,
406*4882a593Smuzhiyun 			.tDQSHZ_max = 20000,
407*4882a593Smuzhiyun 			.tDQSQ_max = 1700,
408*4882a593Smuzhiyun 			.tDS_min = 2000,
409*4882a593Smuzhiyun 			.tDSC_min = 20000,
410*4882a593Smuzhiyun 			.tFEAT_max = 1000000,
411*4882a593Smuzhiyun 			.tITC_max = 1000000,
412*4882a593Smuzhiyun 			.tQHS_max = 2000,
413*4882a593Smuzhiyun 			.tRHW_min = 100000,
414*4882a593Smuzhiyun 			.tRR_min = 20000,
415*4882a593Smuzhiyun 			.tRST_max = 500000000,
416*4882a593Smuzhiyun 			.tWB_max = 100000,
417*4882a593Smuzhiyun 			.tWHR_min = 80000,
418*4882a593Smuzhiyun 			.tWRCK_min = 20000,
419*4882a593Smuzhiyun 			.tWW_min = 100000,
420*4882a593Smuzhiyun 		},
421*4882a593Smuzhiyun 	},
422*4882a593Smuzhiyun 	/* Mode 3 */
423*4882a593Smuzhiyun 	{
424*4882a593Smuzhiyun 		.type = NAND_NVDDR_IFACE,
425*4882a593Smuzhiyun 		.timings.mode = 3,
426*4882a593Smuzhiyun 		.timings.nvddr = {
427*4882a593Smuzhiyun 			.tCCS_min = 500000,
428*4882a593Smuzhiyun 			.tR_max = 200000000,
429*4882a593Smuzhiyun 			.tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
430*4882a593Smuzhiyun 			.tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
431*4882a593Smuzhiyun 			.tAC_min = 3000,
432*4882a593Smuzhiyun 			.tAC_max = 25000,
433*4882a593Smuzhiyun 			.tADL_min = 400000,
434*4882a593Smuzhiyun 			.tCAD_min = 45000,
435*4882a593Smuzhiyun 			.tCAH_min = 3000,
436*4882a593Smuzhiyun 			.tCALH_min = 3000,
437*4882a593Smuzhiyun 			.tCALS_min = 3000,
438*4882a593Smuzhiyun 			.tCAS_min = 3000,
439*4882a593Smuzhiyun 			.tCEH_min = 20000,
440*4882a593Smuzhiyun 			.tCH_min = 3000,
441*4882a593Smuzhiyun 			.tCK_min = 15000,
442*4882a593Smuzhiyun 			.tCS_min = 15000,
443*4882a593Smuzhiyun 			.tDH_min = 1300,
444*4882a593Smuzhiyun 			.tDQSCK_min = 3000,
445*4882a593Smuzhiyun 			.tDQSCK_max = 25000,
446*4882a593Smuzhiyun 			.tDQSD_min = 0,
447*4882a593Smuzhiyun 			.tDQSD_max = 18000,
448*4882a593Smuzhiyun 			.tDQSHZ_max = 20000,
449*4882a593Smuzhiyun 			.tDQSQ_max = 1300,
450*4882a593Smuzhiyun 			.tDS_min = 1500,
451*4882a593Smuzhiyun 			.tDSC_min = 15000,
452*4882a593Smuzhiyun 			.tFEAT_max = 1000000,
453*4882a593Smuzhiyun 			.tITC_max = 1000000,
454*4882a593Smuzhiyun 			.tQHS_max = 1500,
455*4882a593Smuzhiyun 			.tRHW_min = 100000,
456*4882a593Smuzhiyun 			.tRR_min = 20000,
457*4882a593Smuzhiyun 			.tRST_max = 500000000,
458*4882a593Smuzhiyun 			.tWB_max = 100000,
459*4882a593Smuzhiyun 			.tWHR_min = 80000,
460*4882a593Smuzhiyun 			.tWRCK_min = 20000,
461*4882a593Smuzhiyun 			.tWW_min = 100000,
462*4882a593Smuzhiyun 		},
463*4882a593Smuzhiyun 	},
464*4882a593Smuzhiyun 	/* Mode 4 */
465*4882a593Smuzhiyun 	{
466*4882a593Smuzhiyun 		.type = NAND_NVDDR_IFACE,
467*4882a593Smuzhiyun 		.timings.mode = 4,
468*4882a593Smuzhiyun 		.timings.nvddr = {
469*4882a593Smuzhiyun 			.tCCS_min = 500000,
470*4882a593Smuzhiyun 			.tR_max = 200000000,
471*4882a593Smuzhiyun 			.tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
472*4882a593Smuzhiyun 			.tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
473*4882a593Smuzhiyun 			.tAC_min = 3000,
474*4882a593Smuzhiyun 			.tAC_max = 25000,
475*4882a593Smuzhiyun 			.tADL_min = 400000,
476*4882a593Smuzhiyun 			.tCAD_min = 45000,
477*4882a593Smuzhiyun 			.tCAH_min = 2500,
478*4882a593Smuzhiyun 			.tCALH_min = 2500,
479*4882a593Smuzhiyun 			.tCALS_min = 2500,
480*4882a593Smuzhiyun 			.tCAS_min = 2500,
481*4882a593Smuzhiyun 			.tCEH_min = 20000,
482*4882a593Smuzhiyun 			.tCH_min = 2500,
483*4882a593Smuzhiyun 			.tCK_min = 12000,
484*4882a593Smuzhiyun 			.tCS_min = 15000,
485*4882a593Smuzhiyun 			.tDH_min = 1100,
486*4882a593Smuzhiyun 			.tDQSCK_min = 3000,
487*4882a593Smuzhiyun 			.tDQSCK_max = 25000,
488*4882a593Smuzhiyun 			.tDQSD_min = 0,
489*4882a593Smuzhiyun 			.tDQSD_max = 18000,
490*4882a593Smuzhiyun 			.tDQSHZ_max = 20000,
491*4882a593Smuzhiyun 			.tDQSQ_max = 1000,
492*4882a593Smuzhiyun 			.tDS_min = 1100,
493*4882a593Smuzhiyun 			.tDSC_min = 12000,
494*4882a593Smuzhiyun 			.tFEAT_max = 1000000,
495*4882a593Smuzhiyun 			.tITC_max = 1000000,
496*4882a593Smuzhiyun 			.tQHS_max = 1200,
497*4882a593Smuzhiyun 			.tRHW_min = 100000,
498*4882a593Smuzhiyun 			.tRR_min = 20000,
499*4882a593Smuzhiyun 			.tRST_max = 500000000,
500*4882a593Smuzhiyun 			.tWB_max = 100000,
501*4882a593Smuzhiyun 			.tWHR_min = 80000,
502*4882a593Smuzhiyun 			.tWRCK_min = 20000,
503*4882a593Smuzhiyun 			.tWW_min = 100000,
504*4882a593Smuzhiyun 		},
505*4882a593Smuzhiyun 	},
506*4882a593Smuzhiyun 	/* Mode 5 */
507*4882a593Smuzhiyun 	{
508*4882a593Smuzhiyun 		.type = NAND_NVDDR_IFACE,
509*4882a593Smuzhiyun 		.timings.mode = 5,
510*4882a593Smuzhiyun 		.timings.nvddr = {
511*4882a593Smuzhiyun 			.tCCS_min = 500000,
512*4882a593Smuzhiyun 			.tR_max = 200000000,
513*4882a593Smuzhiyun 			.tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
514*4882a593Smuzhiyun 			.tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
515*4882a593Smuzhiyun 			.tAC_min = 3000,
516*4882a593Smuzhiyun 			.tAC_max = 25000,
517*4882a593Smuzhiyun 			.tADL_min = 400000,
518*4882a593Smuzhiyun 			.tCAD_min = 45000,
519*4882a593Smuzhiyun 			.tCAH_min = 2000,
520*4882a593Smuzhiyun 			.tCALH_min = 2000,
521*4882a593Smuzhiyun 			.tCALS_min = 2000,
522*4882a593Smuzhiyun 			.tCAS_min = 2000,
523*4882a593Smuzhiyun 			.tCEH_min = 20000,
524*4882a593Smuzhiyun 			.tCH_min = 2000,
525*4882a593Smuzhiyun 			.tCK_min = 10000,
526*4882a593Smuzhiyun 			.tCS_min = 15000,
527*4882a593Smuzhiyun 			.tDH_min = 900,
528*4882a593Smuzhiyun 			.tDQSCK_min = 3000,
529*4882a593Smuzhiyun 			.tDQSCK_max = 25000,
530*4882a593Smuzhiyun 			.tDQSD_min = 0,
531*4882a593Smuzhiyun 			.tDQSD_max = 18000,
532*4882a593Smuzhiyun 			.tDQSHZ_max = 20000,
533*4882a593Smuzhiyun 			.tDQSQ_max = 850,
534*4882a593Smuzhiyun 			.tDS_min = 900,
535*4882a593Smuzhiyun 			.tDSC_min = 10000,
536*4882a593Smuzhiyun 			.tFEAT_max = 1000000,
537*4882a593Smuzhiyun 			.tITC_max = 1000000,
538*4882a593Smuzhiyun 			.tQHS_max = 1000,
539*4882a593Smuzhiyun 			.tRHW_min = 100000,
540*4882a593Smuzhiyun 			.tRR_min = 20000,
541*4882a593Smuzhiyun 			.tRST_max = 500000000,
542*4882a593Smuzhiyun 			.tWB_max = 100000,
543*4882a593Smuzhiyun 			.tWHR_min = 80000,
544*4882a593Smuzhiyun 			.tWRCK_min = 20000,
545*4882a593Smuzhiyun 			.tWW_min = 100000,
546*4882a593Smuzhiyun 		},
547*4882a593Smuzhiyun 	},
548*4882a593Smuzhiyun };
549*4882a593Smuzhiyun 
550*4882a593Smuzhiyun /* All NAND chips share the same reset data interface: SDR mode 0 */
nand_get_reset_interface_config(void)551*4882a593Smuzhiyun const struct nand_interface_config *nand_get_reset_interface_config(void)
552*4882a593Smuzhiyun {
553*4882a593Smuzhiyun 	return &onfi_sdr_timings[0];
554*4882a593Smuzhiyun }
555*4882a593Smuzhiyun 
556*4882a593Smuzhiyun /**
557*4882a593Smuzhiyun  * onfi_find_closest_sdr_mode - Derive the closest ONFI SDR timing mode given a
558*4882a593Smuzhiyun  *                              set of timings
559*4882a593Smuzhiyun  * @spec_timings: the timings to challenge
560*4882a593Smuzhiyun  */
561*4882a593Smuzhiyun unsigned int
onfi_find_closest_sdr_mode(const struct nand_sdr_timings * spec_timings)562*4882a593Smuzhiyun onfi_find_closest_sdr_mode(const struct nand_sdr_timings *spec_timings)
563*4882a593Smuzhiyun {
564*4882a593Smuzhiyun 	const struct nand_sdr_timings *onfi_timings;
565*4882a593Smuzhiyun 	int mode;
566*4882a593Smuzhiyun 
567*4882a593Smuzhiyun 	for (mode = ARRAY_SIZE(onfi_sdr_timings) - 1; mode > 0; mode--) {
568*4882a593Smuzhiyun 		onfi_timings = &onfi_sdr_timings[mode].timings.sdr;
569*4882a593Smuzhiyun 
570*4882a593Smuzhiyun 		if (spec_timings->tCCS_min <= onfi_timings->tCCS_min &&
571*4882a593Smuzhiyun 		    spec_timings->tADL_min <= onfi_timings->tADL_min &&
572*4882a593Smuzhiyun 		    spec_timings->tALH_min <= onfi_timings->tALH_min &&
573*4882a593Smuzhiyun 		    spec_timings->tALS_min <= onfi_timings->tALS_min &&
574*4882a593Smuzhiyun 		    spec_timings->tAR_min <= onfi_timings->tAR_min &&
575*4882a593Smuzhiyun 		    spec_timings->tCEH_min <= onfi_timings->tCEH_min &&
576*4882a593Smuzhiyun 		    spec_timings->tCH_min <= onfi_timings->tCH_min &&
577*4882a593Smuzhiyun 		    spec_timings->tCLH_min <= onfi_timings->tCLH_min &&
578*4882a593Smuzhiyun 		    spec_timings->tCLR_min <= onfi_timings->tCLR_min &&
579*4882a593Smuzhiyun 		    spec_timings->tCLS_min <= onfi_timings->tCLS_min &&
580*4882a593Smuzhiyun 		    spec_timings->tCOH_min <= onfi_timings->tCOH_min &&
581*4882a593Smuzhiyun 		    spec_timings->tCS_min <= onfi_timings->tCS_min &&
582*4882a593Smuzhiyun 		    spec_timings->tDH_min <= onfi_timings->tDH_min &&
583*4882a593Smuzhiyun 		    spec_timings->tDS_min <= onfi_timings->tDS_min &&
584*4882a593Smuzhiyun 		    spec_timings->tIR_min <= onfi_timings->tIR_min &&
585*4882a593Smuzhiyun 		    spec_timings->tRC_min <= onfi_timings->tRC_min &&
586*4882a593Smuzhiyun 		    spec_timings->tREH_min <= onfi_timings->tREH_min &&
587*4882a593Smuzhiyun 		    spec_timings->tRHOH_min <= onfi_timings->tRHOH_min &&
588*4882a593Smuzhiyun 		    spec_timings->tRHW_min <= onfi_timings->tRHW_min &&
589*4882a593Smuzhiyun 		    spec_timings->tRLOH_min <= onfi_timings->tRLOH_min &&
590*4882a593Smuzhiyun 		    spec_timings->tRP_min <= onfi_timings->tRP_min &&
591*4882a593Smuzhiyun 		    spec_timings->tRR_min <= onfi_timings->tRR_min &&
592*4882a593Smuzhiyun 		    spec_timings->tWC_min <= onfi_timings->tWC_min &&
593*4882a593Smuzhiyun 		    spec_timings->tWH_min <= onfi_timings->tWH_min &&
594*4882a593Smuzhiyun 		    spec_timings->tWHR_min <= onfi_timings->tWHR_min &&
595*4882a593Smuzhiyun 		    spec_timings->tWP_min <= onfi_timings->tWP_min &&
596*4882a593Smuzhiyun 		    spec_timings->tWW_min <= onfi_timings->tWW_min)
597*4882a593Smuzhiyun 			return mode;
598*4882a593Smuzhiyun 	}
599*4882a593Smuzhiyun 
600*4882a593Smuzhiyun 	return 0;
601*4882a593Smuzhiyun }
602*4882a593Smuzhiyun 
603*4882a593Smuzhiyun /**
604*4882a593Smuzhiyun  * onfi_fill_interface_config - Initialize an interface config from a given
605*4882a593Smuzhiyun  *                              ONFI mode
606*4882a593Smuzhiyun  * @chip: The NAND chip
607*4882a593Smuzhiyun  * @iface: The interface configuration to fill
608*4882a593Smuzhiyun  * @type: The interface type
609*4882a593Smuzhiyun  * @timing_mode: The ONFI timing mode
610*4882a593Smuzhiyun  */
onfi_fill_interface_config(struct nand_chip * chip,struct nand_interface_config * iface,enum nand_interface_type type,unsigned int timing_mode)611*4882a593Smuzhiyun void onfi_fill_interface_config(struct nand_chip *chip,
612*4882a593Smuzhiyun 				struct nand_interface_config *iface,
613*4882a593Smuzhiyun 				enum nand_interface_type type,
614*4882a593Smuzhiyun 				unsigned int timing_mode)
615*4882a593Smuzhiyun {
616*4882a593Smuzhiyun 	struct onfi_params *onfi = chip->parameters.onfi;
617*4882a593Smuzhiyun 
618*4882a593Smuzhiyun 	if (WARN_ON(type != NAND_SDR_IFACE))
619*4882a593Smuzhiyun 		return;
620*4882a593Smuzhiyun 
621*4882a593Smuzhiyun 	if (WARN_ON(timing_mode >= ARRAY_SIZE(onfi_sdr_timings)))
622*4882a593Smuzhiyun 		return;
623*4882a593Smuzhiyun 
624*4882a593Smuzhiyun 	*iface = onfi_sdr_timings[timing_mode];
625*4882a593Smuzhiyun 
626*4882a593Smuzhiyun 	/*
627*4882a593Smuzhiyun 	 * Initialize timings that cannot be deduced from timing mode:
628*4882a593Smuzhiyun 	 * tPROG, tBERS, tR and tCCS.
629*4882a593Smuzhiyun 	 * These information are part of the ONFI parameter page.
630*4882a593Smuzhiyun 	 */
631*4882a593Smuzhiyun 	if (onfi) {
632*4882a593Smuzhiyun 		struct nand_sdr_timings *timings = &iface->timings.sdr;
633*4882a593Smuzhiyun 
634*4882a593Smuzhiyun 		/* microseconds -> picoseconds */
635*4882a593Smuzhiyun 		timings->tPROG_max = 1000000ULL * onfi->tPROG;
636*4882a593Smuzhiyun 		timings->tBERS_max = 1000000ULL * onfi->tBERS;
637*4882a593Smuzhiyun 		timings->tR_max = 1000000ULL * onfi->tR;
638*4882a593Smuzhiyun 
639*4882a593Smuzhiyun 		/* nanoseconds -> picoseconds */
640*4882a593Smuzhiyun 		timings->tCCS_min = 1000UL * onfi->tCCS;
641*4882a593Smuzhiyun 	}
642*4882a593Smuzhiyun }
643