xref: /linux/drivers/mtd/nand/raw/nand_timings.c (revision e9f0878c4b2004ac19581274c1ae4c61ae3ca70e)
1 /*
2  *  Copyright (C) 2014 Free Electrons
3  *
4  *  Author: Boris BREZILLON <boris.brezillon@free-electrons.com>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation.
9  *
10  */
11 #include <linux/kernel.h>
12 #include <linux/err.h>
13 #include <linux/export.h>
14 #include <linux/mtd/rawnand.h>
15 
16 #define ONFI_DYN_TIMING_MAX U16_MAX
17 
18 static const struct nand_data_interface onfi_sdr_timings[] = {
19 	/* Mode 0 */
20 	{
21 		.type = NAND_SDR_IFACE,
22 		.timings.sdr = {
23 			.tCCS_min = 500000,
24 			.tR_max = 200000000,
25 			.tADL_min = 400000,
26 			.tALH_min = 20000,
27 			.tALS_min = 50000,
28 			.tAR_min = 25000,
29 			.tCEA_max = 100000,
30 			.tCEH_min = 20000,
31 			.tCH_min = 20000,
32 			.tCHZ_max = 100000,
33 			.tCLH_min = 20000,
34 			.tCLR_min = 20000,
35 			.tCLS_min = 50000,
36 			.tCOH_min = 0,
37 			.tCS_min = 70000,
38 			.tDH_min = 20000,
39 			.tDS_min = 40000,
40 			.tFEAT_max = 1000000,
41 			.tIR_min = 10000,
42 			.tITC_max = 1000000,
43 			.tRC_min = 100000,
44 			.tREA_max = 40000,
45 			.tREH_min = 30000,
46 			.tRHOH_min = 0,
47 			.tRHW_min = 200000,
48 			.tRHZ_max = 200000,
49 			.tRLOH_min = 0,
50 			.tRP_min = 50000,
51 			.tRR_min = 40000,
52 			.tRST_max = 250000000000ULL,
53 			.tWB_max = 200000,
54 			.tWC_min = 100000,
55 			.tWH_min = 30000,
56 			.tWHR_min = 120000,
57 			.tWP_min = 50000,
58 			.tWW_min = 100000,
59 		},
60 	},
61 	/* Mode 1 */
62 	{
63 		.type = NAND_SDR_IFACE,
64 		.timings.sdr = {
65 			.tCCS_min = 500000,
66 			.tR_max = 200000000,
67 			.tADL_min = 400000,
68 			.tALH_min = 10000,
69 			.tALS_min = 25000,
70 			.tAR_min = 10000,
71 			.tCEA_max = 45000,
72 			.tCEH_min = 20000,
73 			.tCH_min = 10000,
74 			.tCHZ_max = 50000,
75 			.tCLH_min = 10000,
76 			.tCLR_min = 10000,
77 			.tCLS_min = 25000,
78 			.tCOH_min = 15000,
79 			.tCS_min = 35000,
80 			.tDH_min = 10000,
81 			.tDS_min = 20000,
82 			.tFEAT_max = 1000000,
83 			.tIR_min = 0,
84 			.tITC_max = 1000000,
85 			.tRC_min = 50000,
86 			.tREA_max = 30000,
87 			.tREH_min = 15000,
88 			.tRHOH_min = 15000,
89 			.tRHW_min = 100000,
90 			.tRHZ_max = 100000,
91 			.tRLOH_min = 0,
92 			.tRP_min = 25000,
93 			.tRR_min = 20000,
94 			.tRST_max = 500000000,
95 			.tWB_max = 100000,
96 			.tWC_min = 45000,
97 			.tWH_min = 15000,
98 			.tWHR_min = 80000,
99 			.tWP_min = 25000,
100 			.tWW_min = 100000,
101 		},
102 	},
103 	/* Mode 2 */
104 	{
105 		.type = NAND_SDR_IFACE,
106 		.timings.sdr = {
107 			.tCCS_min = 500000,
108 			.tR_max = 200000000,
109 			.tADL_min = 400000,
110 			.tALH_min = 10000,
111 			.tALS_min = 15000,
112 			.tAR_min = 10000,
113 			.tCEA_max = 30000,
114 			.tCEH_min = 20000,
115 			.tCH_min = 10000,
116 			.tCHZ_max = 50000,
117 			.tCLH_min = 10000,
118 			.tCLR_min = 10000,
119 			.tCLS_min = 15000,
120 			.tCOH_min = 15000,
121 			.tCS_min = 25000,
122 			.tDH_min = 5000,
123 			.tDS_min = 15000,
124 			.tFEAT_max = 1000000,
125 			.tIR_min = 0,
126 			.tITC_max = 1000000,
127 			.tRC_min = 35000,
128 			.tREA_max = 25000,
129 			.tREH_min = 15000,
130 			.tRHOH_min = 15000,
131 			.tRHW_min = 100000,
132 			.tRHZ_max = 100000,
133 			.tRLOH_min = 0,
134 			.tRR_min = 20000,
135 			.tRST_max = 500000000,
136 			.tWB_max = 100000,
137 			.tRP_min = 17000,
138 			.tWC_min = 35000,
139 			.tWH_min = 15000,
140 			.tWHR_min = 80000,
141 			.tWP_min = 17000,
142 			.tWW_min = 100000,
143 		},
144 	},
145 	/* Mode 3 */
146 	{
147 		.type = NAND_SDR_IFACE,
148 		.timings.sdr = {
149 			.tCCS_min = 500000,
150 			.tR_max = 200000000,
151 			.tADL_min = 400000,
152 			.tALH_min = 5000,
153 			.tALS_min = 10000,
154 			.tAR_min = 10000,
155 			.tCEA_max = 25000,
156 			.tCEH_min = 20000,
157 			.tCH_min = 5000,
158 			.tCHZ_max = 50000,
159 			.tCLH_min = 5000,
160 			.tCLR_min = 10000,
161 			.tCLS_min = 10000,
162 			.tCOH_min = 15000,
163 			.tCS_min = 25000,
164 			.tDH_min = 5000,
165 			.tDS_min = 10000,
166 			.tFEAT_max = 1000000,
167 			.tIR_min = 0,
168 			.tITC_max = 1000000,
169 			.tRC_min = 30000,
170 			.tREA_max = 20000,
171 			.tREH_min = 10000,
172 			.tRHOH_min = 15000,
173 			.tRHW_min = 100000,
174 			.tRHZ_max = 100000,
175 			.tRLOH_min = 0,
176 			.tRP_min = 15000,
177 			.tRR_min = 20000,
178 			.tRST_max = 500000000,
179 			.tWB_max = 100000,
180 			.tWC_min = 30000,
181 			.tWH_min = 10000,
182 			.tWHR_min = 80000,
183 			.tWP_min = 15000,
184 			.tWW_min = 100000,
185 		},
186 	},
187 	/* Mode 4 */
188 	{
189 		.type = NAND_SDR_IFACE,
190 		.timings.sdr = {
191 			.tCCS_min = 500000,
192 			.tR_max = 200000000,
193 			.tADL_min = 400000,
194 			.tALH_min = 5000,
195 			.tALS_min = 10000,
196 			.tAR_min = 10000,
197 			.tCEA_max = 25000,
198 			.tCEH_min = 20000,
199 			.tCH_min = 5000,
200 			.tCHZ_max = 30000,
201 			.tCLH_min = 5000,
202 			.tCLR_min = 10000,
203 			.tCLS_min = 10000,
204 			.tCOH_min = 15000,
205 			.tCS_min = 20000,
206 			.tDH_min = 5000,
207 			.tDS_min = 10000,
208 			.tFEAT_max = 1000000,
209 			.tIR_min = 0,
210 			.tITC_max = 1000000,
211 			.tRC_min = 25000,
212 			.tREA_max = 20000,
213 			.tREH_min = 10000,
214 			.tRHOH_min = 15000,
215 			.tRHW_min = 100000,
216 			.tRHZ_max = 100000,
217 			.tRLOH_min = 5000,
218 			.tRP_min = 12000,
219 			.tRR_min = 20000,
220 			.tRST_max = 500000000,
221 			.tWB_max = 100000,
222 			.tWC_min = 25000,
223 			.tWH_min = 10000,
224 			.tWHR_min = 80000,
225 			.tWP_min = 12000,
226 			.tWW_min = 100000,
227 		},
228 	},
229 	/* Mode 5 */
230 	{
231 		.type = NAND_SDR_IFACE,
232 		.timings.sdr = {
233 			.tCCS_min = 500000,
234 			.tR_max = 200000000,
235 			.tADL_min = 400000,
236 			.tALH_min = 5000,
237 			.tALS_min = 10000,
238 			.tAR_min = 10000,
239 			.tCEA_max = 25000,
240 			.tCEH_min = 20000,
241 			.tCH_min = 5000,
242 			.tCHZ_max = 30000,
243 			.tCLH_min = 5000,
244 			.tCLR_min = 10000,
245 			.tCLS_min = 10000,
246 			.tCOH_min = 15000,
247 			.tCS_min = 15000,
248 			.tDH_min = 5000,
249 			.tDS_min = 7000,
250 			.tFEAT_max = 1000000,
251 			.tIR_min = 0,
252 			.tITC_max = 1000000,
253 			.tRC_min = 20000,
254 			.tREA_max = 16000,
255 			.tREH_min = 7000,
256 			.tRHOH_min = 15000,
257 			.tRHW_min = 100000,
258 			.tRHZ_max = 100000,
259 			.tRLOH_min = 5000,
260 			.tRP_min = 10000,
261 			.tRR_min = 20000,
262 			.tRST_max = 500000000,
263 			.tWB_max = 100000,
264 			.tWC_min = 20000,
265 			.tWH_min = 7000,
266 			.tWHR_min = 80000,
267 			.tWP_min = 10000,
268 			.tWW_min = 100000,
269 		},
270 	},
271 };
272 
273 /**
274  * onfi_async_timing_mode_to_sdr_timings - [NAND Interface] Retrieve NAND
275  * timings according to the given ONFI timing mode
276  * @mode: ONFI timing mode
277  */
278 const struct nand_sdr_timings *onfi_async_timing_mode_to_sdr_timings(int mode)
279 {
280 	if (mode < 0 || mode >= ARRAY_SIZE(onfi_sdr_timings))
281 		return ERR_PTR(-EINVAL);
282 
283 	return &onfi_sdr_timings[mode].timings.sdr;
284 }
285 EXPORT_SYMBOL(onfi_async_timing_mode_to_sdr_timings);
286 
287 /**
288  * onfi_fill_data_interface - [NAND Interface] Initialize a data interface from
289  * given ONFI mode
290  * @mode: The ONFI timing mode
291  */
292 int onfi_fill_data_interface(struct nand_chip *chip,
293 			     enum nand_data_interface_type type,
294 			     int timing_mode)
295 {
296 	struct nand_data_interface *iface = &chip->data_interface;
297 	struct onfi_params *onfi = chip->parameters.onfi;
298 
299 	if (type != NAND_SDR_IFACE)
300 		return -EINVAL;
301 
302 	if (timing_mode < 0 || timing_mode >= ARRAY_SIZE(onfi_sdr_timings))
303 		return -EINVAL;
304 
305 	*iface = onfi_sdr_timings[timing_mode];
306 
307 	/*
308 	 * Initialize timings that cannot be deduced from timing mode:
309 	 * tPROG, tBERS, tR and tCCS.
310 	 * These information are part of the ONFI parameter page.
311 	 */
312 	if (onfi) {
313 		struct nand_sdr_timings *timings = &iface->timings.sdr;
314 
315 		/* microseconds -> picoseconds */
316 		timings->tPROG_max = 1000000ULL * onfi->tPROG;
317 		timings->tBERS_max = 1000000ULL * onfi->tBERS;
318 		timings->tR_max = 1000000ULL * onfi->tR;
319 
320 		/* nanoseconds -> picoseconds */
321 		timings->tCCS_min = 1000UL * onfi->tCCS;
322 	} else {
323 		struct nand_sdr_timings *timings = &iface->timings.sdr;
324 		/*
325 		 * For non-ONFI chips we use the highest possible value for
326 		 * tPROG and tBERS. tR and tCCS will take the default values
327 		 * precised in the ONFI specification for timing mode 0,
328 		 * respectively 200us and 500ns.
329 		 */
330 
331 		/* microseconds -> picoseconds */
332 		timings->tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX;
333 		timings->tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX;
334 		timings->tR_max = 1000000ULL * 200000000ULL;
335 
336 		/* nanoseconds -> picoseconds */
337 		timings->tCCS_min = 1000UL * 500000;
338 	}
339 
340 	return 0;
341 }
342 EXPORT_SYMBOL(onfi_fill_data_interface);
343