Merge remote-tracking branches 'spi/topic/imx', 'spi/topic/loopback', 'spi/topic...
[sfrench/cifs-2.6.git] / drivers / mtd / nand / nand_timings.c
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 #include <linux/mtd/nand.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  */
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  */
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  */
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);