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
16static const struct nand_sdr_timings onfi_sdr_timings[] = {
17	/* Mode 0 */
18	{
19		.tADL_min = 200000,
20		.tALH_min = 20000,
21		.tALS_min = 50000,
22		.tAR_min = 25000,
23		.tCEA_max = 100000,
24		.tCEH_min = 20000,
25		.tCH_min = 20000,
26		.tCHZ_max = 100000,
27		.tCLH_min = 20000,
28		.tCLR_min = 20000,
29		.tCLS_min = 50000,
30		.tCOH_min = 0,
31		.tCS_min = 70000,
32		.tDH_min = 20000,
33		.tDS_min = 40000,
34		.tFEAT_max = 1000000,
35		.tIR_min = 10000,
36		.tITC_max = 1000000,
37		.tRC_min = 100000,
38		.tREA_max = 40000,
39		.tREH_min = 30000,
40		.tRHOH_min = 0,
41		.tRHW_min = 200000,
42		.tRHZ_max = 200000,
43		.tRLOH_min = 0,
44		.tRP_min = 50000,
45		.tRST_max = 250000000000ULL,
46		.tWB_max = 200000,
47		.tRR_min = 40000,
48		.tWC_min = 100000,
49		.tWH_min = 30000,
50		.tWHR_min = 120000,
51		.tWP_min = 50000,
52		.tWW_min = 100000,
53	},
54	/* Mode 1 */
55	{
56		.tADL_min = 100000,
57		.tALH_min = 10000,
58		.tALS_min = 25000,
59		.tAR_min = 10000,
60		.tCEA_max = 45000,
61		.tCEH_min = 20000,
62		.tCH_min = 10000,
63		.tCHZ_max = 50000,
64		.tCLH_min = 10000,
65		.tCLR_min = 10000,
66		.tCLS_min = 25000,
67		.tCOH_min = 15000,
68		.tCS_min = 35000,
69		.tDH_min = 10000,
70		.tDS_min = 20000,
71		.tFEAT_max = 1000000,
72		.tIR_min = 0,
73		.tITC_max = 1000000,
74		.tRC_min = 50000,
75		.tREA_max = 30000,
76		.tREH_min = 15000,
77		.tRHOH_min = 15000,
78		.tRHW_min = 100000,
79		.tRHZ_max = 100000,
80		.tRLOH_min = 0,
81		.tRP_min = 25000,
82		.tRR_min = 20000,
83		.tRST_max = 500000000,
84		.tWB_max = 100000,
85		.tWC_min = 45000,
86		.tWH_min = 15000,
87		.tWHR_min = 80000,
88		.tWP_min = 25000,
89		.tWW_min = 100000,
90	},
91	/* Mode 2 */
92	{
93		.tADL_min = 100000,
94		.tALH_min = 10000,
95		.tALS_min = 15000,
96		.tAR_min = 10000,
97		.tCEA_max = 30000,
98		.tCEH_min = 20000,
99		.tCH_min = 10000,
100		.tCHZ_max = 50000,
101		.tCLH_min = 10000,
102		.tCLR_min = 10000,
103		.tCLS_min = 15000,
104		.tCOH_min = 15000,
105		.tCS_min = 25000,
106		.tDH_min = 5000,
107		.tDS_min = 15000,
108		.tFEAT_max = 1000000,
109		.tIR_min = 0,
110		.tITC_max = 1000000,
111		.tRC_min = 35000,
112		.tREA_max = 25000,
113		.tREH_min = 15000,
114		.tRHOH_min = 15000,
115		.tRHW_min = 100000,
116		.tRHZ_max = 100000,
117		.tRLOH_min = 0,
118		.tRR_min = 20000,
119		.tRST_max = 500000000,
120		.tWB_max = 100000,
121		.tRP_min = 17000,
122		.tWC_min = 35000,
123		.tWH_min = 15000,
124		.tWHR_min = 80000,
125		.tWP_min = 17000,
126		.tWW_min = 100000,
127	},
128	/* Mode 3 */
129	{
130		.tADL_min = 100000,
131		.tALH_min = 5000,
132		.tALS_min = 10000,
133		.tAR_min = 10000,
134		.tCEA_max = 25000,
135		.tCEH_min = 20000,
136		.tCH_min = 5000,
137		.tCHZ_max = 50000,
138		.tCLH_min = 5000,
139		.tCLR_min = 10000,
140		.tCLS_min = 10000,
141		.tCOH_min = 15000,
142		.tCS_min = 25000,
143		.tDH_min = 5000,
144		.tDS_min = 10000,
145		.tFEAT_max = 1000000,
146		.tIR_min = 0,
147		.tITC_max = 1000000,
148		.tRC_min = 30000,
149		.tREA_max = 20000,
150		.tREH_min = 10000,
151		.tRHOH_min = 15000,
152		.tRHW_min = 100000,
153		.tRHZ_max = 100000,
154		.tRLOH_min = 0,
155		.tRP_min = 15000,
156		.tRR_min = 20000,
157		.tRST_max = 500000000,
158		.tWB_max = 100000,
159		.tWC_min = 30000,
160		.tWH_min = 10000,
161		.tWHR_min = 80000,
162		.tWP_min = 15000,
163		.tWW_min = 100000,
164	},
165	/* Mode 4 */
166	{
167		.tADL_min = 70000,
168		.tALH_min = 5000,
169		.tALS_min = 10000,
170		.tAR_min = 10000,
171		.tCEA_max = 25000,
172		.tCEH_min = 20000,
173		.tCH_min = 5000,
174		.tCHZ_max = 30000,
175		.tCLH_min = 5000,
176		.tCLR_min = 10000,
177		.tCLS_min = 10000,
178		.tCOH_min = 15000,
179		.tCS_min = 20000,
180		.tDH_min = 5000,
181		.tDS_min = 10000,
182		.tFEAT_max = 1000000,
183		.tIR_min = 0,
184		.tITC_max = 1000000,
185		.tRC_min = 25000,
186		.tREA_max = 20000,
187		.tREH_min = 10000,
188		.tRHOH_min = 15000,
189		.tRHW_min = 100000,
190		.tRHZ_max = 100000,
191		.tRLOH_min = 5000,
192		.tRP_min = 12000,
193		.tRR_min = 20000,
194		.tRST_max = 500000000,
195		.tWB_max = 100000,
196		.tWC_min = 25000,
197		.tWH_min = 10000,
198		.tWHR_min = 80000,
199		.tWP_min = 12000,
200		.tWW_min = 100000,
201	},
202	/* Mode 5 */
203	{
204		.tADL_min = 70000,
205		.tALH_min = 5000,
206		.tALS_min = 10000,
207		.tAR_min = 10000,
208		.tCEA_max = 25000,
209		.tCEH_min = 20000,
210		.tCH_min = 5000,
211		.tCHZ_max = 30000,
212		.tCLH_min = 5000,
213		.tCLR_min = 10000,
214		.tCLS_min = 10000,
215		.tCOH_min = 15000,
216		.tCS_min = 15000,
217		.tDH_min = 5000,
218		.tDS_min = 7000,
219		.tFEAT_max = 1000000,
220		.tIR_min = 0,
221		.tITC_max = 1000000,
222		.tRC_min = 20000,
223		.tREA_max = 16000,
224		.tREH_min = 7000,
225		.tRHOH_min = 15000,
226		.tRHW_min = 100000,
227		.tRHZ_max = 100000,
228		.tRLOH_min = 5000,
229		.tRP_min = 10000,
230		.tRR_min = 20000,
231		.tRST_max = 500000000,
232		.tWB_max = 100000,
233		.tWC_min = 20000,
234		.tWH_min = 7000,
235		.tWHR_min = 80000,
236		.tWP_min = 10000,
237		.tWW_min = 100000,
238	},
239};
240
241/**
242 * onfi_async_timing_mode_to_sdr_timings - [NAND Interface] Retrieve NAND
243 * timings according to the given ONFI timing mode
244 * @mode: ONFI timing mode
245 */
246const struct nand_sdr_timings *onfi_async_timing_mode_to_sdr_timings(int mode)
247{
248	if (mode < 0 || mode >= ARRAY_SIZE(onfi_sdr_timings))
249		return ERR_PTR(-EINVAL);
250
251	return &onfi_sdr_timings[mode];
252}
253EXPORT_SYMBOL(onfi_async_timing_mode_to_sdr_timings);
254