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