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