1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  *  Copyright (C) 2014 Free Electrons
4  *
5  *  Author: Boris BREZILLON <boris.brezillon@free-electrons.com>
6  */
7 #include <linux/kernel.h>
8 #include <linux/err.h>
9 #include <linux/export.h>
10 
11 #include "internals.h"
12 
13 #define ONFI_DYN_TIMING_MAX U16_MAX
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_fill_data_interface - [NAND Interface] Initialize a data interface from
272  * given ONFI mode
273  * @mode: The ONFI timing mode
274  */
275 int onfi_fill_data_interface(struct nand_chip *chip,
276 			     enum nand_data_interface_type type,
277 			     int timing_mode)
278 {
279 	struct nand_data_interface *iface = &chip->data_interface;
280 	struct onfi_params *onfi = chip->parameters.onfi;
281 
282 	if (type != NAND_SDR_IFACE)
283 		return -EINVAL;
284 
285 	if (timing_mode < 0 || timing_mode >= ARRAY_SIZE(onfi_sdr_timings))
286 		return -EINVAL;
287 
288 	*iface = onfi_sdr_timings[timing_mode];
289 
290 	/*
291 	 * Initialize timings that cannot be deduced from timing mode:
292 	 * tPROG, tBERS, tR and tCCS.
293 	 * These information are part of the ONFI parameter page.
294 	 */
295 	if (onfi) {
296 		struct nand_sdr_timings *timings = &iface->timings.sdr;
297 
298 		/* microseconds -> picoseconds */
299 		timings->tPROG_max = 1000000ULL * onfi->tPROG;
300 		timings->tBERS_max = 1000000ULL * onfi->tBERS;
301 		timings->tR_max = 1000000ULL * onfi->tR;
302 
303 		/* nanoseconds -> picoseconds */
304 		timings->tCCS_min = 1000UL * onfi->tCCS;
305 	} else {
306 		struct nand_sdr_timings *timings = &iface->timings.sdr;
307 		/*
308 		 * For non-ONFI chips we use the highest possible value for
309 		 * tPROG and tBERS. tR and tCCS will take the default values
310 		 * precised in the ONFI specification for timing mode 0,
311 		 * respectively 200us and 500ns.
312 		 */
313 
314 		/* microseconds -> picoseconds */
315 		timings->tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX;
316 		timings->tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX;
317 		timings->tR_max = 1000000ULL * 200000000ULL;
318 
319 		/* nanoseconds -> picoseconds */
320 		timings->tCCS_min = 1000UL * 500000;
321 	}
322 
323 	return 0;
324 }
325