blob: f64b06a71dfa1e2f1713b5cfb3dd10842e9a91c6 [file] [log] [blame]
Thomas Gleixnerd2912cb2019-06-04 10:11:33 +02001// SPDX-License-Identifier: GPL-2.0-only
Boris BREZILLON974647e2014-07-11 09:49:42 +02002/*
3 * Copyright (C) 2014 Free Electrons
4 *
5 * Author: Boris BREZILLON <boris.brezillon@free-electrons.com>
Boris BREZILLON974647e2014-07-11 09:49:42 +02006 */
7#include <linux/kernel.h>
8#include <linux/err.h>
9#include <linux/export.h>
Boris Brezillon348d56a2018-09-07 00:38:48 +020010
11#include "internals.h"
Boris BREZILLON974647e2014-07-11 09:49:42 +020012
Miquel Raynal6a943382018-07-14 12:23:54 +020013#define ONFI_DYN_TIMING_MAX U16_MAX
14
Sascha Hauerb1dd3ca2016-09-15 10:32:47 +020015static const struct nand_data_interface onfi_sdr_timings[] = {
Boris BREZILLON974647e2014-07-11 09:49:42 +020016 /* Mode 0 */
17 {
Sascha Hauerb1dd3ca2016-09-15 10:32:47 +020018 .type = NAND_SDR_IFACE,
19 .timings.sdr = {
Boris Brezillon204e7ec2016-10-01 10:24:02 +020020 .tCCS_min = 500000,
21 .tR_max = 200000000,
Sascha Hauerb1dd3ca2016-09-15 10:32:47 +020022 .tADL_min = 400000,
23 .tALH_min = 20000,
24 .tALS_min = 50000,
25 .tAR_min = 25000,
26 .tCEA_max = 100000,
27 .tCEH_min = 20000,
28 .tCH_min = 20000,
29 .tCHZ_max = 100000,
30 .tCLH_min = 20000,
31 .tCLR_min = 20000,
32 .tCLS_min = 50000,
33 .tCOH_min = 0,
34 .tCS_min = 70000,
35 .tDH_min = 20000,
36 .tDS_min = 40000,
37 .tFEAT_max = 1000000,
38 .tIR_min = 10000,
39 .tITC_max = 1000000,
40 .tRC_min = 100000,
41 .tREA_max = 40000,
42 .tREH_min = 30000,
43 .tRHOH_min = 0,
44 .tRHW_min = 200000,
45 .tRHZ_max = 200000,
46 .tRLOH_min = 0,
47 .tRP_min = 50000,
48 .tRR_min = 40000,
49 .tRST_max = 250000000000ULL,
50 .tWB_max = 200000,
51 .tWC_min = 100000,
52 .tWH_min = 30000,
53 .tWHR_min = 120000,
54 .tWP_min = 50000,
55 .tWW_min = 100000,
56 },
Boris BREZILLON974647e2014-07-11 09:49:42 +020057 },
58 /* Mode 1 */
59 {
Sascha Hauerb1dd3ca2016-09-15 10:32:47 +020060 .type = NAND_SDR_IFACE,
61 .timings.sdr = {
Boris Brezillon204e7ec2016-10-01 10:24:02 +020062 .tCCS_min = 500000,
63 .tR_max = 200000000,
Sascha Hauerb1dd3ca2016-09-15 10:32:47 +020064 .tADL_min = 400000,
65 .tALH_min = 10000,
66 .tALS_min = 25000,
67 .tAR_min = 10000,
68 .tCEA_max = 45000,
69 .tCEH_min = 20000,
70 .tCH_min = 10000,
71 .tCHZ_max = 50000,
72 .tCLH_min = 10000,
73 .tCLR_min = 10000,
74 .tCLS_min = 25000,
75 .tCOH_min = 15000,
76 .tCS_min = 35000,
77 .tDH_min = 10000,
78 .tDS_min = 20000,
79 .tFEAT_max = 1000000,
80 .tIR_min = 0,
81 .tITC_max = 1000000,
82 .tRC_min = 50000,
83 .tREA_max = 30000,
84 .tREH_min = 15000,
85 .tRHOH_min = 15000,
86 .tRHW_min = 100000,
87 .tRHZ_max = 100000,
88 .tRLOH_min = 0,
89 .tRP_min = 25000,
90 .tRR_min = 20000,
91 .tRST_max = 500000000,
92 .tWB_max = 100000,
93 .tWC_min = 45000,
94 .tWH_min = 15000,
95 .tWHR_min = 80000,
96 .tWP_min = 25000,
97 .tWW_min = 100000,
98 },
Boris BREZILLON974647e2014-07-11 09:49:42 +020099 },
100 /* Mode 2 */
101 {
Sascha Hauerb1dd3ca2016-09-15 10:32:47 +0200102 .type = NAND_SDR_IFACE,
103 .timings.sdr = {
Boris Brezillon204e7ec2016-10-01 10:24:02 +0200104 .tCCS_min = 500000,
105 .tR_max = 200000000,
Sascha Hauerb1dd3ca2016-09-15 10:32:47 +0200106 .tADL_min = 400000,
107 .tALH_min = 10000,
108 .tALS_min = 15000,
109 .tAR_min = 10000,
110 .tCEA_max = 30000,
111 .tCEH_min = 20000,
112 .tCH_min = 10000,
113 .tCHZ_max = 50000,
114 .tCLH_min = 10000,
115 .tCLR_min = 10000,
116 .tCLS_min = 15000,
117 .tCOH_min = 15000,
118 .tCS_min = 25000,
119 .tDH_min = 5000,
120 .tDS_min = 15000,
121 .tFEAT_max = 1000000,
122 .tIR_min = 0,
123 .tITC_max = 1000000,
124 .tRC_min = 35000,
125 .tREA_max = 25000,
126 .tREH_min = 15000,
127 .tRHOH_min = 15000,
128 .tRHW_min = 100000,
129 .tRHZ_max = 100000,
130 .tRLOH_min = 0,
131 .tRR_min = 20000,
132 .tRST_max = 500000000,
133 .tWB_max = 100000,
134 .tRP_min = 17000,
135 .tWC_min = 35000,
136 .tWH_min = 15000,
137 .tWHR_min = 80000,
138 .tWP_min = 17000,
139 .tWW_min = 100000,
140 },
Boris BREZILLON974647e2014-07-11 09:49:42 +0200141 },
142 /* Mode 3 */
143 {
Sascha Hauerb1dd3ca2016-09-15 10:32:47 +0200144 .type = NAND_SDR_IFACE,
145 .timings.sdr = {
Boris Brezillon204e7ec2016-10-01 10:24:02 +0200146 .tCCS_min = 500000,
147 .tR_max = 200000000,
Sascha Hauerb1dd3ca2016-09-15 10:32:47 +0200148 .tADL_min = 400000,
149 .tALH_min = 5000,
150 .tALS_min = 10000,
151 .tAR_min = 10000,
152 .tCEA_max = 25000,
153 .tCEH_min = 20000,
154 .tCH_min = 5000,
155 .tCHZ_max = 50000,
156 .tCLH_min = 5000,
157 .tCLR_min = 10000,
158 .tCLS_min = 10000,
159 .tCOH_min = 15000,
160 .tCS_min = 25000,
161 .tDH_min = 5000,
162 .tDS_min = 10000,
163 .tFEAT_max = 1000000,
164 .tIR_min = 0,
165 .tITC_max = 1000000,
166 .tRC_min = 30000,
167 .tREA_max = 20000,
168 .tREH_min = 10000,
169 .tRHOH_min = 15000,
170 .tRHW_min = 100000,
171 .tRHZ_max = 100000,
172 .tRLOH_min = 0,
173 .tRP_min = 15000,
174 .tRR_min = 20000,
175 .tRST_max = 500000000,
176 .tWB_max = 100000,
177 .tWC_min = 30000,
178 .tWH_min = 10000,
179 .tWHR_min = 80000,
180 .tWP_min = 15000,
181 .tWW_min = 100000,
182 },
Boris BREZILLON974647e2014-07-11 09:49:42 +0200183 },
184 /* Mode 4 */
185 {
Sascha Hauerb1dd3ca2016-09-15 10:32:47 +0200186 .type = NAND_SDR_IFACE,
187 .timings.sdr = {
Boris Brezillon204e7ec2016-10-01 10:24:02 +0200188 .tCCS_min = 500000,
189 .tR_max = 200000000,
Sascha Hauerb1dd3ca2016-09-15 10:32:47 +0200190 .tADL_min = 400000,
191 .tALH_min = 5000,
192 .tALS_min = 10000,
193 .tAR_min = 10000,
194 .tCEA_max = 25000,
195 .tCEH_min = 20000,
196 .tCH_min = 5000,
197 .tCHZ_max = 30000,
198 .tCLH_min = 5000,
199 .tCLR_min = 10000,
200 .tCLS_min = 10000,
201 .tCOH_min = 15000,
202 .tCS_min = 20000,
203 .tDH_min = 5000,
204 .tDS_min = 10000,
205 .tFEAT_max = 1000000,
206 .tIR_min = 0,
207 .tITC_max = 1000000,
208 .tRC_min = 25000,
209 .tREA_max = 20000,
210 .tREH_min = 10000,
211 .tRHOH_min = 15000,
212 .tRHW_min = 100000,
213 .tRHZ_max = 100000,
214 .tRLOH_min = 5000,
215 .tRP_min = 12000,
216 .tRR_min = 20000,
217 .tRST_max = 500000000,
218 .tWB_max = 100000,
219 .tWC_min = 25000,
220 .tWH_min = 10000,
221 .tWHR_min = 80000,
222 .tWP_min = 12000,
223 .tWW_min = 100000,
224 },
Boris BREZILLON974647e2014-07-11 09:49:42 +0200225 },
226 /* Mode 5 */
227 {
Sascha Hauerb1dd3ca2016-09-15 10:32:47 +0200228 .type = NAND_SDR_IFACE,
229 .timings.sdr = {
Boris Brezillon204e7ec2016-10-01 10:24:02 +0200230 .tCCS_min = 500000,
231 .tR_max = 200000000,
Sascha Hauerb1dd3ca2016-09-15 10:32:47 +0200232 .tADL_min = 400000,
233 .tALH_min = 5000,
234 .tALS_min = 10000,
235 .tAR_min = 10000,
236 .tCEA_max = 25000,
237 .tCEH_min = 20000,
238 .tCH_min = 5000,
239 .tCHZ_max = 30000,
240 .tCLH_min = 5000,
241 .tCLR_min = 10000,
242 .tCLS_min = 10000,
243 .tCOH_min = 15000,
244 .tCS_min = 15000,
245 .tDH_min = 5000,
246 .tDS_min = 7000,
247 .tFEAT_max = 1000000,
248 .tIR_min = 0,
249 .tITC_max = 1000000,
250 .tRC_min = 20000,
251 .tREA_max = 16000,
252 .tREH_min = 7000,
253 .tRHOH_min = 15000,
254 .tRHW_min = 100000,
255 .tRHZ_max = 100000,
256 .tRLOH_min = 5000,
257 .tRP_min = 10000,
258 .tRR_min = 20000,
259 .tRST_max = 500000000,
260 .tWB_max = 100000,
261 .tWC_min = 20000,
262 .tWH_min = 7000,
263 .tWHR_min = 80000,
264 .tWP_min = 10000,
265 .tWW_min = 100000,
266 },
Boris BREZILLON974647e2014-07-11 09:49:42 +0200267 },
268};
269
270/**
Miquel Raynal17fa8042017-11-30 18:01:31 +0100271 * onfi_fill_data_interface - [NAND Interface] Initialize a data interface from
Sascha Hauerb88730a2016-09-15 10:32:48 +0200272 * given ONFI mode
Sascha Hauerb88730a2016-09-15 10:32:48 +0200273 * @mode: The ONFI timing mode
274 */
Miquel Raynal17fa8042017-11-30 18:01:31 +0100275int onfi_fill_data_interface(struct nand_chip *chip,
Sascha Hauerb88730a2016-09-15 10:32:48 +0200276 enum nand_data_interface_type type,
277 int timing_mode)
278{
Miquel Raynal17fa8042017-11-30 18:01:31 +0100279 struct nand_data_interface *iface = &chip->data_interface;
Miquel Raynal3d3fe3c2018-07-25 15:31:52 +0200280 struct onfi_params *onfi = chip->parameters.onfi;
Miquel Raynal17fa8042017-11-30 18:01:31 +0100281
Sascha Hauerb88730a2016-09-15 10:32:48 +0200282 if (type != NAND_SDR_IFACE)
283 return -EINVAL;
284
285 if (timing_mode < 0 || timing_mode >= ARRAY_SIZE(onfi_sdr_timings))
286 return -EINVAL;
287
288 *iface = onfi_sdr_timings[timing_mode];
289
290 /*
Boris Brezillon204e7ec2016-10-01 10:24:02 +0200291 * Initialize timings that cannot be deduced from timing mode:
Miquel Raynal6a943382018-07-14 12:23:54 +0200292 * tPROG, tBERS, tR and tCCS.
Sascha Hauerb88730a2016-09-15 10:32:48 +0200293 * These information are part of the ONFI parameter page.
294 */
Miquel Raynal3d3fe3c2018-07-25 15:31:52 +0200295 if (onfi) {
Boris Brezillon204e7ec2016-10-01 10:24:02 +0200296 struct nand_sdr_timings *timings = &iface->timings.sdr;
297
298 /* microseconds -> picoseconds */
Miquel Raynal3d3fe3c2018-07-25 15:31:52 +0200299 timings->tPROG_max = 1000000ULL * onfi->tPROG;
300 timings->tBERS_max = 1000000ULL * onfi->tBERS;
301 timings->tR_max = 1000000ULL * onfi->tR;
Boris Brezillon204e7ec2016-10-01 10:24:02 +0200302
303 /* nanoseconds -> picoseconds */
Miquel Raynal3d3fe3c2018-07-25 15:31:52 +0200304 timings->tCCS_min = 1000UL * onfi->tCCS;
Miquel Raynal6a943382018-07-14 12:23:54 +0200305 } else {
306 struct nand_sdr_timings *timings = &iface->timings.sdr;
307 /*
308 * For non-ONFI chips we use the highest possible value for
309 * tPROG and tBERS. tR and tCCS will take the default values
310 * precised in the ONFI specification for timing mode 0,
311 * respectively 200us and 500ns.
312 */
313
314 /* microseconds -> picoseconds */
315 timings->tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX;
316 timings->tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX;
317 timings->tR_max = 1000000ULL * 200000000ULL;
318
319 /* nanoseconds -> picoseconds */
320 timings->tCCS_min = 1000UL * 500000;
Boris Brezillon204e7ec2016-10-01 10:24:02 +0200321 }
Sascha Hauerb88730a2016-09-15 10:32:48 +0200322
323 return 0;
324}