blob: bea3062d71d6f9e9220798173e47fed6f556d39e [file] [log] [blame]
Boris BREZILLON974647e2014-07-11 09:49:42 +02001/*
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>
Boris Brezillon348d56a2018-09-07 00:38:48 +020014
15#include "internals.h"
Boris BREZILLON974647e2014-07-11 09:49:42 +020016
Miquel Raynal6a943382018-07-14 12:23:54 +020017#define ONFI_DYN_TIMING_MAX U16_MAX
18
Sascha Hauerb1dd3ca2016-09-15 10:32:47 +020019static const struct nand_data_interface onfi_sdr_timings[] = {
Boris BREZILLON974647e2014-07-11 09:49:42 +020020 /* Mode 0 */
21 {
Sascha Hauerb1dd3ca2016-09-15 10:32:47 +020022 .type = NAND_SDR_IFACE,
23 .timings.sdr = {
Boris Brezillon204e7ec2016-10-01 10:24:02 +020024 .tCCS_min = 500000,
25 .tR_max = 200000000,
Sascha Hauerb1dd3ca2016-09-15 10:32:47 +020026 .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 },
Boris BREZILLON974647e2014-07-11 09:49:42 +020061 },
62 /* Mode 1 */
63 {
Sascha Hauerb1dd3ca2016-09-15 10:32:47 +020064 .type = NAND_SDR_IFACE,
65 .timings.sdr = {
Boris Brezillon204e7ec2016-10-01 10:24:02 +020066 .tCCS_min = 500000,
67 .tR_max = 200000000,
Sascha Hauerb1dd3ca2016-09-15 10:32:47 +020068 .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 },
Boris BREZILLON974647e2014-07-11 09:49:42 +0200103 },
104 /* Mode 2 */
105 {
Sascha Hauerb1dd3ca2016-09-15 10:32:47 +0200106 .type = NAND_SDR_IFACE,
107 .timings.sdr = {
Boris Brezillon204e7ec2016-10-01 10:24:02 +0200108 .tCCS_min = 500000,
109 .tR_max = 200000000,
Sascha Hauerb1dd3ca2016-09-15 10:32:47 +0200110 .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 },
Boris BREZILLON974647e2014-07-11 09:49:42 +0200145 },
146 /* Mode 3 */
147 {
Sascha Hauerb1dd3ca2016-09-15 10:32:47 +0200148 .type = NAND_SDR_IFACE,
149 .timings.sdr = {
Boris Brezillon204e7ec2016-10-01 10:24:02 +0200150 .tCCS_min = 500000,
151 .tR_max = 200000000,
Sascha Hauerb1dd3ca2016-09-15 10:32:47 +0200152 .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 },
Boris BREZILLON974647e2014-07-11 09:49:42 +0200187 },
188 /* Mode 4 */
189 {
Sascha Hauerb1dd3ca2016-09-15 10:32:47 +0200190 .type = NAND_SDR_IFACE,
191 .timings.sdr = {
Boris Brezillon204e7ec2016-10-01 10:24:02 +0200192 .tCCS_min = 500000,
193 .tR_max = 200000000,
Sascha Hauerb1dd3ca2016-09-15 10:32:47 +0200194 .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 },
Boris BREZILLON974647e2014-07-11 09:49:42 +0200229 },
230 /* Mode 5 */
231 {
Sascha Hauerb1dd3ca2016-09-15 10:32:47 +0200232 .type = NAND_SDR_IFACE,
233 .timings.sdr = {
Boris Brezillon204e7ec2016-10-01 10:24:02 +0200234 .tCCS_min = 500000,
235 .tR_max = 200000000,
Sascha Hauerb1dd3ca2016-09-15 10:32:47 +0200236 .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 },
Boris BREZILLON974647e2014-07-11 09:49:42 +0200271 },
272};
273
274/**
Miquel Raynal17fa8042017-11-30 18:01:31 +0100275 * onfi_fill_data_interface - [NAND Interface] Initialize a data interface from
Sascha Hauerb88730a2016-09-15 10:32:48 +0200276 * given ONFI mode
Sascha Hauerb88730a2016-09-15 10:32:48 +0200277 * @mode: The ONFI timing mode
278 */
Miquel Raynal17fa8042017-11-30 18:01:31 +0100279int onfi_fill_data_interface(struct nand_chip *chip,
Sascha Hauerb88730a2016-09-15 10:32:48 +0200280 enum nand_data_interface_type type,
281 int timing_mode)
282{
Miquel Raynal17fa8042017-11-30 18:01:31 +0100283 struct nand_data_interface *iface = &chip->data_interface;
Miquel Raynal3d3fe3c2018-07-25 15:31:52 +0200284 struct onfi_params *onfi = chip->parameters.onfi;
Miquel Raynal17fa8042017-11-30 18:01:31 +0100285
Sascha Hauerb88730a2016-09-15 10:32:48 +0200286 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 /*
Boris Brezillon204e7ec2016-10-01 10:24:02 +0200295 * Initialize timings that cannot be deduced from timing mode:
Miquel Raynal6a943382018-07-14 12:23:54 +0200296 * tPROG, tBERS, tR and tCCS.
Sascha Hauerb88730a2016-09-15 10:32:48 +0200297 * These information are part of the ONFI parameter page.
298 */
Miquel Raynal3d3fe3c2018-07-25 15:31:52 +0200299 if (onfi) {
Boris Brezillon204e7ec2016-10-01 10:24:02 +0200300 struct nand_sdr_timings *timings = &iface->timings.sdr;
301
302 /* microseconds -> picoseconds */
Miquel Raynal3d3fe3c2018-07-25 15:31:52 +0200303 timings->tPROG_max = 1000000ULL * onfi->tPROG;
304 timings->tBERS_max = 1000000ULL * onfi->tBERS;
305 timings->tR_max = 1000000ULL * onfi->tR;
Boris Brezillon204e7ec2016-10-01 10:24:02 +0200306
307 /* nanoseconds -> picoseconds */
Miquel Raynal3d3fe3c2018-07-25 15:31:52 +0200308 timings->tCCS_min = 1000UL * onfi->tCCS;
Miquel Raynal6a943382018-07-14 12:23:54 +0200309 } else {
310 struct nand_sdr_timings *timings = &iface->timings.sdr;
311 /*
312 * For non-ONFI chips we use the highest possible value for
313 * tPROG and tBERS. tR and tCCS will take the default values
314 * precised in the ONFI specification for timing mode 0,
315 * respectively 200us and 500ns.
316 */
317
318 /* microseconds -> picoseconds */
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 /* nanoseconds -> picoseconds */
324 timings->tCCS_min = 1000UL * 500000;
Boris Brezillon204e7ec2016-10-01 10:24:02 +0200325 }
Sascha Hauerb88730a2016-09-15 10:32:48 +0200326
327 return 0;
328}