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