1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * Copyright (C) 2018 Stefan Roese <sr@denx.de>
4 *
5 * Derived from drivers/mtd/nand/spi/micron.c
6 * Copyright (c) 2016-2017 Micron Technology, Inc.
7 */
8
9 #ifndef __UBOOT__
10 #include <linux/device.h>
11 #include <linux/kernel.h>
12 #endif
13 #include <linux/mtd/spinand.h>
14
15 #define SPINAND_MFR_GIGADEVICE 0xC8
16
17 #define GD5FXGQ4XA_STATUS_ECC_1_7_BITFLIPS (1 << 4)
18 #define GD5FXGQ4XA_STATUS_ECC_8_BITFLIPS (3 << 4)
19
20 #define GD5FXGQ5XE_STATUS_ECC_1_4_BITFLIPS (1 << 4)
21 #define GD5FXGQ5XE_STATUS_ECC_4_BITFLIPS (3 << 4)
22
23 #define GD5FXGQXXEXXG_REG_STATUS2 0xf0
24
25 #define GD5FXGQ4UXFXXG_STATUS_ECC_MASK (7 << 4)
26 #define GD5FXGQ4UXFXXG_STATUS_ECC_NO_BITFLIPS (0 << 4)
27 #define GD5FXGQ4UXFXXG_STATUS_ECC_1_3_BITFLIPS (1 << 4)
28 #define GD5FXGQ4UXFXXG_STATUS_ECC_UNCOR_ERROR (7 << 4)
29
30 static SPINAND_OP_VARIANTS(read_cache_variants,
31 SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP(0, 1, NULL, 0),
32 SPINAND_PAGE_READ_FROM_CACHE_X4_OP(0, 1, NULL, 0),
33 SPINAND_PAGE_READ_FROM_CACHE_DUALIO_OP(0, 1, NULL, 0),
34 SPINAND_PAGE_READ_FROM_CACHE_X2_OP(0, 1, NULL, 0),
35 SPINAND_PAGE_READ_FROM_CACHE_OP(true, 0, 1, NULL, 0),
36 SPINAND_PAGE_READ_FROM_CACHE_OP(false, 0, 1, NULL, 0));
37
38 static SPINAND_OP_VARIANTS(read_cache_variants_f,
39 SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP(0, 1, NULL, 0),
40 SPINAND_PAGE_READ_FROM_CACHE_X4_OP_3A(0, 1, NULL, 0),
41 SPINAND_PAGE_READ_FROM_CACHE_DUALIO_OP(0, 1, NULL, 0),
42 SPINAND_PAGE_READ_FROM_CACHE_X2_OP_3A(0, 1, NULL, 0),
43 SPINAND_PAGE_READ_FROM_CACHE_OP_3A(true, 0, 1, NULL, 0),
44 SPINAND_PAGE_READ_FROM_CACHE_OP_3A(false, 0, 0, NULL, 0));
45
46 static SPINAND_OP_VARIANTS(read_cache_variants_1gq5,
47 SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP(0, 2, NULL, 0),
48 SPINAND_PAGE_READ_FROM_CACHE_X4_OP(0, 1, NULL, 0),
49 SPINAND_PAGE_READ_FROM_CACHE_DUALIO_OP(0, 1, NULL, 0),
50 SPINAND_PAGE_READ_FROM_CACHE_X2_OP(0, 1, NULL, 0),
51 SPINAND_PAGE_READ_FROM_CACHE_OP(true, 0, 1, NULL, 0),
52 SPINAND_PAGE_READ_FROM_CACHE_OP(false, 0, 1, NULL, 0));
53
54 static SPINAND_OP_VARIANTS(read_cache_variants_2gq5,
55 SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP(0, 4, NULL, 0),
56 SPINAND_PAGE_READ_FROM_CACHE_X4_OP(0, 1, NULL, 0),
57 SPINAND_PAGE_READ_FROM_CACHE_DUALIO_OP(0, 2, NULL, 0),
58 SPINAND_PAGE_READ_FROM_CACHE_X2_OP(0, 1, NULL, 0),
59 SPINAND_PAGE_READ_FROM_CACHE_OP(true, 0, 1, NULL, 0),
60 SPINAND_PAGE_READ_FROM_CACHE_OP(false, 0, 1, NULL, 0));
61
62 static SPINAND_OP_VARIANTS(write_cache_variants,
63 SPINAND_PROG_LOAD_X4(true, 0, NULL, 0),
64 SPINAND_PROG_LOAD(true, 0, NULL, 0));
65
66 static SPINAND_OP_VARIANTS(update_cache_variants,
67 SPINAND_PROG_LOAD_X4(false, 0, NULL, 0),
68 SPINAND_PROG_LOAD(false, 0, NULL, 0));
69
gd5fxgq4xa_ooblayout_ecc(struct mtd_info * mtd,int section,struct mtd_oob_region * region)70 static int gd5fxgq4xa_ooblayout_ecc(struct mtd_info *mtd, int section,
71 struct mtd_oob_region *region)
72 {
73 if (section > 3)
74 return -ERANGE;
75
76 region->offset = (16 * section) + 8;
77 region->length = 8;
78
79 return 0;
80 }
81
gd5fxgq4xa_ooblayout_free(struct mtd_info * mtd,int section,struct mtd_oob_region * region)82 static int gd5fxgq4xa_ooblayout_free(struct mtd_info *mtd, int section,
83 struct mtd_oob_region *region)
84 {
85 if (section > 3)
86 return -ERANGE;
87
88 if (section) {
89 region->offset = 16 * section;
90 region->length = 8;
91 } else {
92 /* section 0 has one byte reserved for bad block mark */
93 region->offset = 1;
94 region->length = 7;
95 }
96 return 0;
97 }
98
99 static const struct mtd_ooblayout_ops gd5fxgq4xa_ooblayout = {
100 .ecc = gd5fxgq4xa_ooblayout_ecc,
101 .rfree = gd5fxgq4xa_ooblayout_free,
102 };
103
gd5fxgq4xa_ecc_get_status(struct spinand_device * spinand,u8 status)104 static int gd5fxgq4xa_ecc_get_status(struct spinand_device *spinand,
105 u8 status)
106 {
107 switch (status & STATUS_ECC_MASK) {
108 case STATUS_ECC_NO_BITFLIPS:
109 return 0;
110
111 case GD5FXGQ4XA_STATUS_ECC_1_7_BITFLIPS:
112 /* 1-7 bits are flipped. return the maximum. */
113 return 7;
114
115 case GD5FXGQ4XA_STATUS_ECC_8_BITFLIPS:
116 return 8;
117
118 case STATUS_ECC_UNCOR_ERROR:
119 return -EBADMSG;
120
121 default:
122 break;
123 }
124
125 return -EINVAL;
126 }
127
gd5fxgqx_variant2_ooblayout_ecc(struct mtd_info * mtd,int section,struct mtd_oob_region * region)128 static int gd5fxgqx_variant2_ooblayout_ecc(struct mtd_info *mtd, int section,
129 struct mtd_oob_region *region)
130 {
131 if (section)
132 return -ERANGE;
133
134 region->offset = 64;
135 region->length = 64;
136
137 return 0;
138 }
139
gd5fxgqx_variant2_ooblayout_free(struct mtd_info * mtd,int section,struct mtd_oob_region * region)140 static int gd5fxgqx_variant2_ooblayout_free(struct mtd_info *mtd, int section,
141 struct mtd_oob_region *region)
142 {
143 if (section)
144 return -ERANGE;
145
146 /* Reserve 1 bytes for the BBM. */
147 region->offset = 1;
148 region->length = 63;
149
150 return 0;
151 }
152
153 /* Valid for Q4/Q5 and Q6 (untested) devices */
154 static const struct mtd_ooblayout_ops gd5fxgqx_variant2_ooblayout = {
155 .ecc = gd5fxgqx_variant2_ooblayout_ecc,
156 .rfree = gd5fxgqx_variant2_ooblayout_free,
157 };
158
gd5fxgq4xc_ooblayout_256_ecc(struct mtd_info * mtd,int section,struct mtd_oob_region * oobregion)159 static int gd5fxgq4xc_ooblayout_256_ecc(struct mtd_info *mtd, int section,
160 struct mtd_oob_region *oobregion)
161 {
162 if (section)
163 return -ERANGE;
164
165 oobregion->offset = 128;
166 oobregion->length = 128;
167
168 return 0;
169 }
170
gd5fxgq4xc_ooblayout_256_free(struct mtd_info * mtd,int section,struct mtd_oob_region * oobregion)171 static int gd5fxgq4xc_ooblayout_256_free(struct mtd_info *mtd, int section,
172 struct mtd_oob_region *oobregion)
173 {
174 if (section)
175 return -ERANGE;
176
177 oobregion->offset = 1;
178 oobregion->length = 127;
179
180 return 0;
181 }
182
183 static const struct mtd_ooblayout_ops gd5fxgq4xc_oob_256_ops = {
184 .ecc = gd5fxgq4xc_ooblayout_256_ecc,
185 .rfree = gd5fxgq4xc_ooblayout_256_free,
186 };
187
gd5fxgqx_variant3_ooblayout_ecc(struct mtd_info * mtd,int section,struct mtd_oob_region * region)188 static int gd5fxgqx_variant3_ooblayout_ecc(struct mtd_info *mtd, int section,
189 struct mtd_oob_region *region)
190 {
191 return -ERANGE;
192 }
193
gd5fxgqx_variant3_ooblayout_free(struct mtd_info * mtd,int section,struct mtd_oob_region * region)194 static int gd5fxgqx_variant3_ooblayout_free(struct mtd_info *mtd, int section,
195 struct mtd_oob_region *region)
196 {
197 if (section)
198 return -ERANGE;
199
200 /* Reserve 1 bytes for the BBM. */
201 region->offset = 1;
202 region->length = 63;
203
204 return 0;
205 }
206
207 static const struct mtd_ooblayout_ops gd5fxgqx_variant3_ooblayout = {
208 .ecc = gd5fxgqx_variant3_ooblayout_ecc,
209 .rfree = gd5fxgqx_variant3_ooblayout_free,
210 };
211
gd5fxgq4uexxg_ecc_get_status(struct spinand_device * spinand,u8 status)212 static int gd5fxgq4uexxg_ecc_get_status(struct spinand_device *spinand,
213 u8 status)
214 {
215 u8 status2;
216 struct spi_mem_op op = SPINAND_GET_FEATURE_OP(GD5FXGQXXEXXG_REG_STATUS2,
217 &status2);
218 int ret;
219
220 switch (status & STATUS_ECC_MASK) {
221 case STATUS_ECC_NO_BITFLIPS:
222 return 0;
223
224 case GD5FXGQ4XA_STATUS_ECC_1_7_BITFLIPS:
225 /*
226 * Read status2 register to determine a more fine grained
227 * bit error status
228 */
229 ret = spi_mem_exec_op(spinand->slave, &op);
230 if (ret)
231 return ret;
232
233 /*
234 * 4 ... 7 bits are flipped (1..4 can't be detected, so
235 * report the maximum of 4 in this case
236 */
237 /* bits sorted this way (3...0): ECCS1,ECCS0,ECCSE1,ECCSE0 */
238 return ((status & STATUS_ECC_MASK) >> 2) |
239 ((status2 & STATUS_ECC_MASK) >> 4);
240
241 case GD5FXGQ4XA_STATUS_ECC_8_BITFLIPS:
242 return 8;
243
244 case STATUS_ECC_UNCOR_ERROR:
245 return -EBADMSG;
246
247 default:
248 break;
249 }
250
251 return -EINVAL;
252 }
253
gd5fxgq5xexxg_ecc_get_status(struct spinand_device * spinand,u8 status)254 static int gd5fxgq5xexxg_ecc_get_status(struct spinand_device *spinand,
255 u8 status)
256 {
257 u8 status2;
258 struct spi_mem_op op = SPINAND_GET_FEATURE_OP(GD5FXGQXXEXXG_REG_STATUS2,
259 &status2);
260 int ret;
261
262 switch (status & STATUS_ECC_MASK) {
263 case STATUS_ECC_NO_BITFLIPS:
264 return 0;
265
266 case GD5FXGQ5XE_STATUS_ECC_1_4_BITFLIPS:
267 /*
268 * Read status2 register to determine a more fine grained
269 * bit error status
270 */
271 ret = spi_mem_exec_op(spinand->slave, &op);
272 if (ret)
273 return ret;
274
275 /*
276 * 1 ... 4 bits are flipped (and corrected)
277 */
278 /* bits sorted this way (1...0): ECCSE1, ECCSE0 */
279 return ((status2 & STATUS_ECC_MASK) >> 4) + 1;
280
281 case STATUS_ECC_UNCOR_ERROR:
282 return -EBADMSG;
283
284 default:
285 break;
286 }
287
288 return -EINVAL;
289 }
290
gd5fxgq4ufxxg_ecc_get_status(struct spinand_device * spinand,u8 status)291 static int gd5fxgq4ufxxg_ecc_get_status(struct spinand_device *spinand,
292 u8 status)
293 {
294 switch (status & GD5FXGQ4UXFXXG_STATUS_ECC_MASK) {
295 case GD5FXGQ4UXFXXG_STATUS_ECC_NO_BITFLIPS:
296 return 0;
297
298 case GD5FXGQ4UXFXXG_STATUS_ECC_1_3_BITFLIPS:
299 return 3;
300
301 case GD5FXGQ4UXFXXG_STATUS_ECC_UNCOR_ERROR:
302 return -EBADMSG;
303
304 default: /* (2 << 4) through (6 << 4) are 4-8 corrected errors */
305 return ((status & GD5FXGQ4UXFXXG_STATUS_ECC_MASK) >> 4) + 2;
306 }
307
308 return -EINVAL;
309 }
310
311 static const struct spinand_info gigadevice_spinand_table[] = {
312 SPINAND_INFO("GD5F1GQ4xA",
313 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0xf1),
314 NAND_MEMORG(1, 2048, 64, 64, 1024, 1, 1, 1),
315 NAND_ECCREQ(8, 512),
316 SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
317 &write_cache_variants,
318 &update_cache_variants),
319 SPINAND_HAS_QE_BIT,
320 SPINAND_ECCINFO(&gd5fxgq4xa_ooblayout,
321 gd5fxgq4xa_ecc_get_status)),
322 SPINAND_INFO("GD5F2GQ4xA",
323 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0xf2),
324 NAND_MEMORG(1, 2048, 64, 64, 2048, 1, 1, 1),
325 NAND_ECCREQ(8, 512),
326 SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
327 &write_cache_variants,
328 &update_cache_variants),
329 SPINAND_HAS_QE_BIT,
330 SPINAND_ECCINFO(&gd5fxgq4xa_ooblayout,
331 gd5fxgq4xa_ecc_get_status)),
332 SPINAND_INFO("GD5F4GQ4xA",
333 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0xf4),
334 NAND_MEMORG(1, 2048, 64, 64, 4096, 1, 1, 1),
335 NAND_ECCREQ(8, 512),
336 SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
337 &write_cache_variants,
338 &update_cache_variants),
339 SPINAND_HAS_QE_BIT,
340 SPINAND_ECCINFO(&gd5fxgq4xa_ooblayout,
341 gd5fxgq4xa_ecc_get_status)),
342 SPINAND_INFO("GD5F4GQ4RC",
343 SPINAND_ID(SPINAND_READID_METHOD_OPCODE, 0xa4, 0x68),
344 NAND_MEMORG(1, 4096, 256, 64, 2048, 1, 1, 1),
345 NAND_ECCREQ(8, 512),
346 SPINAND_INFO_OP_VARIANTS(&read_cache_variants_f,
347 &write_cache_variants,
348 &update_cache_variants),
349 SPINAND_HAS_QE_BIT,
350 SPINAND_ECCINFO(&gd5fxgq4xc_oob_256_ops,
351 gd5fxgq4ufxxg_ecc_get_status)),
352 SPINAND_INFO("GD5F4GQ4UC",
353 SPINAND_ID(SPINAND_READID_METHOD_OPCODE, 0xb4, 0x68),
354 NAND_MEMORG(1, 4096, 256, 64, 2048, 1, 1, 1),
355 NAND_ECCREQ(8, 512),
356 SPINAND_INFO_OP_VARIANTS(&read_cache_variants_f,
357 &write_cache_variants,
358 &update_cache_variants),
359 SPINAND_HAS_QE_BIT,
360 SPINAND_ECCINFO(&gd5fxgq4xc_oob_256_ops,
361 gd5fxgq4ufxxg_ecc_get_status)),
362 SPINAND_INFO("GD5F1GQ4UExxG",
363 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0xd1),
364 NAND_MEMORG(1, 2048, 128, 64, 1024, 1, 1, 1),
365 NAND_ECCREQ(8, 512),
366 SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
367 &write_cache_variants,
368 &update_cache_variants),
369 SPINAND_HAS_QE_BIT,
370 SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
371 gd5fxgq4uexxg_ecc_get_status)),
372 SPINAND_INFO("GD5F1GQ4RExxG",
373 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0xc1),
374 NAND_MEMORG(1, 2048, 128, 64, 1024, 1, 1, 1),
375 NAND_ECCREQ(8, 512),
376 SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
377 &write_cache_variants,
378 &update_cache_variants),
379 SPINAND_HAS_QE_BIT,
380 SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
381 gd5fxgq4uexxg_ecc_get_status)),
382 SPINAND_INFO("GD5F2GQ4UExxG",
383 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0xd2),
384 NAND_MEMORG(1, 2048, 128, 64, 2048, 1, 1, 1),
385 NAND_ECCREQ(8, 512),
386 SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
387 &write_cache_variants,
388 &update_cache_variants),
389 SPINAND_HAS_QE_BIT,
390 SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
391 gd5fxgq4uexxg_ecc_get_status)),
392 SPINAND_INFO("GD5F2GQ4RExxG",
393 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0xc2),
394 NAND_MEMORG(1, 2048, 128, 64, 2048, 1, 1, 1),
395 NAND_ECCREQ(8, 512),
396 SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
397 &write_cache_variants,
398 &update_cache_variants),
399 SPINAND_HAS_QE_BIT,
400 SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
401 gd5fxgq4uexxg_ecc_get_status)),
402 SPINAND_INFO("GD5F1GQ4UFxxG",
403 SPINAND_ID(SPINAND_READID_METHOD_OPCODE, 0xb1, 0x48),
404 NAND_MEMORG(1, 2048, 128, 64, 1024, 1, 1, 1),
405 NAND_ECCREQ(8, 512),
406 SPINAND_INFO_OP_VARIANTS(&read_cache_variants_f,
407 &write_cache_variants,
408 &update_cache_variants),
409 SPINAND_HAS_QE_BIT,
410 SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
411 gd5fxgq4ufxxg_ecc_get_status)),
412 SPINAND_INFO("GD5F1GQ5UExxG",
413 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x51),
414 NAND_MEMORG(1, 2048, 128, 64, 1024, 1, 1, 1),
415 NAND_ECCREQ(4, 512),
416 SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
417 &write_cache_variants,
418 &update_cache_variants),
419 SPINAND_HAS_QE_BIT,
420 SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
421 gd5fxgq5xexxg_ecc_get_status)),
422 SPINAND_INFO("GD5F1GQ5RExxG",
423 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x41),
424 NAND_MEMORG(1, 2048, 128, 64, 1024, 1, 1, 1),
425 NAND_ECCREQ(4, 512),
426 SPINAND_INFO_OP_VARIANTS(&read_cache_variants_1gq5,
427 &write_cache_variants,
428 &update_cache_variants),
429 SPINAND_HAS_QE_BIT,
430 SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
431 gd5fxgq5xexxg_ecc_get_status)),
432 SPINAND_INFO("GD5F2GQ5UExxG",
433 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x52),
434 NAND_MEMORG(1, 2048, 128, 64, 2048, 1, 1, 1),
435 NAND_ECCREQ(4, 512),
436 SPINAND_INFO_OP_VARIANTS(&read_cache_variants_2gq5,
437 &write_cache_variants,
438 &update_cache_variants),
439 SPINAND_HAS_QE_BIT,
440 SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
441 gd5fxgq5xexxg_ecc_get_status)),
442 SPINAND_INFO("GD5F2GQ5RExxG",
443 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x42),
444 NAND_MEMORG(1, 2048, 128, 64, 2048, 1, 1, 1),
445 NAND_ECCREQ(4, 512),
446 SPINAND_INFO_OP_VARIANTS(&read_cache_variants_2gq5,
447 &write_cache_variants,
448 &update_cache_variants),
449 SPINAND_HAS_QE_BIT,
450 SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
451 gd5fxgq5xexxg_ecc_get_status)),
452 SPINAND_INFO("GD5F4GQ6UExxG",
453 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x55),
454 NAND_MEMORG(1, 2048, 128, 64, 2048, 1, 2, 1),
455 NAND_ECCREQ(4, 512),
456 SPINAND_INFO_OP_VARIANTS(&read_cache_variants_2gq5,
457 &write_cache_variants,
458 &update_cache_variants),
459 SPINAND_HAS_QE_BIT,
460 SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
461 gd5fxgq5xexxg_ecc_get_status)),
462 SPINAND_INFO("GD5F4GQ6RExxG",
463 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x45),
464 NAND_MEMORG(1, 2048, 128, 64, 2048, 1, 2, 1),
465 NAND_ECCREQ(4, 512),
466 SPINAND_INFO_OP_VARIANTS(&read_cache_variants_2gq5,
467 &write_cache_variants,
468 &update_cache_variants),
469 SPINAND_HAS_QE_BIT,
470 SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
471 gd5fxgq5xexxg_ecc_get_status)),
472 SPINAND_INFO("GD5F1GM7UExxG",
473 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x91),
474 NAND_MEMORG(1, 2048, 128, 64, 1024, 1, 1, 1),
475 NAND_ECCREQ(8, 512),
476 SPINAND_INFO_OP_VARIANTS(&read_cache_variants_1gq5,
477 &write_cache_variants,
478 &update_cache_variants),
479 SPINAND_HAS_QE_BIT,
480 SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
481 gd5fxgq4uexxg_ecc_get_status)),
482 SPINAND_INFO("GD5F1GM7RExxG",
483 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x81),
484 NAND_MEMORG(1, 2048, 128, 64, 1024, 1, 1, 1),
485 NAND_ECCREQ(8, 512),
486 SPINAND_INFO_OP_VARIANTS(&read_cache_variants_1gq5,
487 &write_cache_variants,
488 &update_cache_variants),
489 SPINAND_HAS_QE_BIT,
490 SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
491 gd5fxgq4uexxg_ecc_get_status)),
492 SPINAND_INFO("GD5F2GM7UExxG",
493 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x92),
494 NAND_MEMORG(1, 2048, 128, 64, 2048, 1, 1, 1),
495 NAND_ECCREQ(8, 512),
496 SPINAND_INFO_OP_VARIANTS(&read_cache_variants_1gq5,
497 &write_cache_variants,
498 &update_cache_variants),
499 SPINAND_HAS_QE_BIT,
500 SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
501 gd5fxgq4uexxg_ecc_get_status)),
502 SPINAND_INFO("GD5F2GM7RExxG",
503 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x82),
504 NAND_MEMORG(1, 2048, 128, 64, 2048, 1, 1, 1),
505 NAND_ECCREQ(8, 512),
506 SPINAND_INFO_OP_VARIANTS(&read_cache_variants_1gq5,
507 &write_cache_variants,
508 &update_cache_variants),
509 SPINAND_HAS_QE_BIT,
510 SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
511 gd5fxgq4uexxg_ecc_get_status)),
512 SPINAND_INFO("GD5F4GM8UExxG",
513 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x95),
514 NAND_MEMORG(1, 2048, 128, 64, 4096, 1, 1, 1),
515 NAND_ECCREQ(8, 512),
516 SPINAND_INFO_OP_VARIANTS(&read_cache_variants_1gq5,
517 &write_cache_variants,
518 &update_cache_variants),
519 SPINAND_HAS_QE_BIT,
520 SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
521 gd5fxgq4uexxg_ecc_get_status)),
522 SPINAND_INFO("GD5F4GM8RExxG",
523 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x85),
524 NAND_MEMORG(1, 2048, 128, 64, 4096, 1, 1, 1),
525 NAND_ECCREQ(8, 512),
526 SPINAND_INFO_OP_VARIANTS(&read_cache_variants_1gq5,
527 &write_cache_variants,
528 &update_cache_variants),
529 SPINAND_HAS_QE_BIT,
530 SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
531 gd5fxgq4uexxg_ecc_get_status)),
532 SPINAND_INFO("GD5F1GQ4UExxH",
533 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0xd9),
534 NAND_MEMORG(1, 2048, 64, 64, 1024, 1, 1, 1),
535 NAND_ECCREQ(8, 512),
536 SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
537 &write_cache_variants,
538 &update_cache_variants),
539 SPINAND_HAS_QE_BIT,
540 SPINAND_ECCINFO(&gd5fxgqx_variant3_ooblayout,
541 gd5fxgq4xa_ecc_get_status)),
542 };
543
gigadevice_spinand_set_ds(struct spinand_device * spinand,u8 ds_io)544 static int gigadevice_spinand_set_ds(struct spinand_device *spinand, u8 ds_io)
545 {
546 struct spi_mem_op op = SPINAND_SET_FEATURE_OP(0xD0,
547 spinand->scratchbuf);
548
549 *spinand->scratchbuf = (ds_io & 0x3) << 5;
550 return spi_mem_exec_op(spinand->slave, &op);
551 }
552
gigadevice_spinand_init(struct spinand_device * spinand)553 static int gigadevice_spinand_init(struct spinand_device *spinand)
554 {
555 /* GD5F1GQ5UExxG */
556 if (spinand->id.data[1] == 0x51)
557 gigadevice_spinand_set_ds(spinand, 3);
558
559 return 0;
560 }
561
562 static const struct spinand_manufacturer_ops gigadevice_spinand_manuf_ops = {
563 .init = gigadevice_spinand_init,
564 };
565
566 const struct spinand_manufacturer gigadevice_spinand_manufacturer = {
567 .id = SPINAND_MFR_GIGADEVICE,
568 .name = "GigaDevice",
569 .chips = gigadevice_spinand_table,
570 .nchips = ARRAY_SIZE(gigadevice_spinand_table),
571 .ops = &gigadevice_spinand_manuf_ops,
572 };
573