1
2
3
4
5
6
7
8
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
19static const struct nand_data_interface onfi_sdr_timings[] = {
20
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
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
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
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
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
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
276
277
278
279int 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
296
297
298
299 if (onfi) {
300 struct nand_sdr_timings *timings = &iface->timings.sdr;
301
302
303 timings->tPROG_max = 1000000ULL * onfi->tPROG;
304 timings->tBERS_max = 1000000ULL * onfi->tBERS;
305 timings->tR_max = 1000000ULL * onfi->tR;
306
307
308 timings->tCCS_min = 1000UL * onfi->tCCS;
309 } else {
310 struct nand_sdr_timings *timings = &iface->timings.sdr;
311
312
313
314
315
316
317
318
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
324 timings->tCCS_min = 1000UL * 500000;
325 }
326
327 return 0;
328}
329