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