1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * Author:
4 * Chuanhong Guo <gch981213@gmail.com>
5 */
6
7 #include <linux/bitfield.h>
8 #include <linux/device.h>
9 #include <linux/kernel.h>
10 #include <linux/mtd/spinand.h>
11
12 #define SPINAND_MFR_GIGADEVICE 0xC8
13
14 #define GD5FXGQ4XA_STATUS_ECC_1_7_BITFLIPS (1 << 4)
15 #define GD5FXGQ4XA_STATUS_ECC_8_BITFLIPS (3 << 4)
16
17 #define GD5FXGQ5XE_STATUS_ECC_1_4_BITFLIPS (1 << 4)
18 #define GD5FXGQ5XE_STATUS_ECC_4_BITFLIPS (3 << 4)
19
20 #define GD5FXGQXXEXXG_REG_STATUS2 0xf0
21
22 #define GD5FXGQ4UXFXXG_STATUS_ECC_MASK (7 << 4)
23 #define GD5FXGQ4UXFXXG_STATUS_ECC_NO_BITFLIPS (0 << 4)
24 #define GD5FXGQ4UXFXXG_STATUS_ECC_1_3_BITFLIPS (1 << 4)
25 #define GD5FXGQ4UXFXXG_STATUS_ECC_UNCOR_ERROR (7 << 4)
26
27 /* Feature bit definitions */
28 #define GD_FEATURE_NR BIT(3) /* Normal Read(1=normal,0=continuous) */
29 #define GD_FEATURE_CRDC BIT(2) /* Continuous Read Dummy */
30
31 /* ECC status extraction helpers */
32 #define GD_ECCSR_LAST_PAGE(eccsr) FIELD_GET(GENMASK(3, 0), eccsr)
33 #define GD_ECCSR_ACCUMULATED(eccsr) FIELD_GET(GENMASK(7, 4), eccsr)
34
35 struct gigadevice_priv {
36 bool continuous_read;
37 };
38
39 static SPINAND_OP_VARIANTS(read_cache_variants,
40 SPINAND_PAGE_READ_FROM_CACHE_1S_4S_4S_OP(0, 1, NULL, 0, 0),
41 SPINAND_PAGE_READ_FROM_CACHE_1S_1S_4S_OP(0, 1, NULL, 0, 0),
42 SPINAND_PAGE_READ_FROM_CACHE_1S_2S_2S_OP(0, 1, NULL, 0, 0),
43 SPINAND_PAGE_READ_FROM_CACHE_1S_1S_2S_OP(0, 1, NULL, 0, 0),
44 SPINAND_PAGE_READ_FROM_CACHE_FAST_1S_1S_1S_OP(0, 1, NULL, 0, 0),
45 SPINAND_PAGE_READ_FROM_CACHE_1S_1S_1S_OP(0, 1, NULL, 0, 0));
46
47 static SPINAND_OP_VARIANTS(read_cache_variants_f,
48 SPINAND_PAGE_READ_FROM_CACHE_1S_4S_4S_OP(0, 1, NULL, 0, 0),
49 SPINAND_PAGE_READ_FROM_CACHE_3A_1S_1S_4S_OP(0, 1, NULL, 0, 0),
50 SPINAND_PAGE_READ_FROM_CACHE_1S_2S_2S_OP(0, 1, NULL, 0, 0),
51 SPINAND_PAGE_READ_FROM_CACHE_3A_1S_1S_2S_OP(0, 1, NULL, 0, 0),
52 SPINAND_PAGE_READ_FROM_CACHE_FAST_3A_1S_1S_1S_OP(0, 1, NULL, 0, 0),
53 SPINAND_PAGE_READ_FROM_CACHE_3A_1S_1S_1S_OP(0, 0, NULL, 0, 0));
54
55 static SPINAND_OP_VARIANTS(read_cache_variants_1gq5,
56 SPINAND_PAGE_READ_FROM_CACHE_1S_4S_4S_OP(0, 2, NULL, 0, 0),
57 SPINAND_PAGE_READ_FROM_CACHE_1S_1S_4S_OP(0, 1, NULL, 0, 0),
58 SPINAND_PAGE_READ_FROM_CACHE_1S_2S_2S_OP(0, 1, NULL, 0, 0),
59 SPINAND_PAGE_READ_FROM_CACHE_1S_1S_2S_OP(0, 1, NULL, 0, 0),
60 SPINAND_PAGE_READ_FROM_CACHE_FAST_1S_1S_1S_OP(0, 1, NULL, 0, 0),
61 SPINAND_PAGE_READ_FROM_CACHE_1S_1S_1S_OP(0, 1, NULL, 0, 0));
62
63 static SPINAND_OP_VARIANTS(read_cache_variants_2gq5,
64 SPINAND_PAGE_READ_FROM_CACHE_1S_4S_4S_OP(0, 4, NULL, 0, 0),
65 SPINAND_PAGE_READ_FROM_CACHE_1S_1S_4S_OP(0, 1, NULL, 0, 0),
66 SPINAND_PAGE_READ_FROM_CACHE_1S_2S_2S_OP(0, 2, NULL, 0, 0),
67 SPINAND_PAGE_READ_FROM_CACHE_1S_1S_2S_OP(0, 1, NULL, 0, 0),
68 SPINAND_PAGE_READ_FROM_CACHE_FAST_1S_1S_1S_OP(0, 1, NULL, 0, 0),
69 SPINAND_PAGE_READ_FROM_CACHE_1S_1S_1S_OP(0, 1, NULL, 0, 0));
70
71 static SPINAND_OP_VARIANTS(write_cache_variants,
72 SPINAND_PROG_LOAD_1S_1S_4S_OP(true, 0, NULL, 0),
73 SPINAND_PROG_LOAD_1S_1S_1S_OP(true, 0, NULL, 0));
74
75 static SPINAND_OP_VARIANTS(update_cache_variants,
76 SPINAND_PROG_LOAD_1S_1S_4S_OP(false, 0, NULL, 0),
77 SPINAND_PROG_LOAD_1S_1S_1S_OP(false, 0, NULL, 0));
78
gd5fxgm9_get_eccsr(struct spinand_device * spinand,u8 * eccsr)79 static int gd5fxgm9_get_eccsr(struct spinand_device *spinand, u8 *eccsr)
80 {
81 struct gigadevice_priv *priv = spinand->priv;
82 struct spi_mem_op op = SPI_MEM_OP(SPI_MEM_OP_CMD(0x7c, 1),
83 SPI_MEM_OP_NO_ADDR,
84 SPI_MEM_OP_DUMMY(1, 1),
85 SPI_MEM_OP_DATA_IN(1, eccsr, 1));
86 int ret;
87
88 ret = spi_mem_exec_op(spinand->spimem, &op);
89 if (ret)
90 return ret;
91
92 if (priv->continuous_read)
93 *eccsr = GD_ECCSR_ACCUMULATED(*eccsr);
94 else
95 *eccsr = GD_ECCSR_LAST_PAGE(*eccsr);
96
97 return 0;
98 }
99
gd5fxgm9_ecc_get_status(struct spinand_device * spinand,u8 status)100 static int gd5fxgm9_ecc_get_status(struct spinand_device *spinand, u8 status)
101 {
102 struct nand_device *nand = spinand_to_nand(spinand);
103 u8 eccsr;
104 int ret;
105
106 switch (status & STATUS_ECC_MASK) {
107 case STATUS_ECC_NO_BITFLIPS:
108 return 0;
109
110 case GD5FXGQ4XA_STATUS_ECC_1_7_BITFLIPS:
111 ret = gd5fxgm9_get_eccsr(spinand, spinand->scratchbuf);
112 if (ret)
113 return nanddev_get_ecc_conf(nand)->strength;
114
115 eccsr = *spinand->scratchbuf;
116 if (WARN_ON(!eccsr || eccsr > nanddev_get_ecc_conf(nand)->strength))
117 return nanddev_get_ecc_conf(nand)->strength;
118
119 return eccsr;
120
121 case GD5FXGQ4XA_STATUS_ECC_8_BITFLIPS:
122 return 8;
123
124 case STATUS_ECC_UNCOR_ERROR:
125 return -EBADMSG;
126
127 default:
128 return -EINVAL;
129 }
130 }
131
gd5fxgm9_set_continuous_read(struct spinand_device * spinand,bool enable)132 static int gd5fxgm9_set_continuous_read(struct spinand_device *spinand, bool enable)
133 {
134 struct gigadevice_priv *priv = spinand->priv;
135 int ret;
136
137 ret = spinand_upd_cfg(spinand, GD_FEATURE_NR,
138 enable ? 0 : GD_FEATURE_NR);
139 if (ret)
140 return ret;
141
142 priv->continuous_read = enable;
143
144 return 0;
145 }
146
gd5fxgq4xa_ooblayout_ecc(struct mtd_info * mtd,int section,struct mtd_oob_region * region)147 static int gd5fxgq4xa_ooblayout_ecc(struct mtd_info *mtd, int section,
148 struct mtd_oob_region *region)
149 {
150 if (section > 3)
151 return -ERANGE;
152
153 region->offset = (16 * section) + 8;
154 region->length = 8;
155
156 return 0;
157 }
158
gd5fxgq4xa_ooblayout_free(struct mtd_info * mtd,int section,struct mtd_oob_region * region)159 static int gd5fxgq4xa_ooblayout_free(struct mtd_info *mtd, int section,
160 struct mtd_oob_region *region)
161 {
162 if (section > 3)
163 return -ERANGE;
164
165 if (section) {
166 region->offset = 16 * section;
167 region->length = 8;
168 } else {
169 /* section 0 has one byte reserved for bad block mark */
170 region->offset = 1;
171 region->length = 7;
172 }
173 return 0;
174 }
175
176 static const struct mtd_ooblayout_ops gd5fxgq4xa_ooblayout = {
177 .ecc = gd5fxgq4xa_ooblayout_ecc,
178 .free = gd5fxgq4xa_ooblayout_free,
179 };
180
gd5fxgq4xa_ecc_get_status(struct spinand_device * spinand,u8 status)181 static int gd5fxgq4xa_ecc_get_status(struct spinand_device *spinand,
182 u8 status)
183 {
184 switch (status & STATUS_ECC_MASK) {
185 case STATUS_ECC_NO_BITFLIPS:
186 return 0;
187
188 case GD5FXGQ4XA_STATUS_ECC_1_7_BITFLIPS:
189 /* 1-7 bits are flipped. return the maximum. */
190 return 7;
191
192 case GD5FXGQ4XA_STATUS_ECC_8_BITFLIPS:
193 return 8;
194
195 case STATUS_ECC_UNCOR_ERROR:
196 return -EBADMSG;
197
198 default:
199 break;
200 }
201
202 return -EINVAL;
203 }
204
gd5fxgqx_variant2_ooblayout_ecc(struct mtd_info * mtd,int section,struct mtd_oob_region * region)205 static int gd5fxgqx_variant2_ooblayout_ecc(struct mtd_info *mtd, int section,
206 struct mtd_oob_region *region)
207 {
208 if (section)
209 return -ERANGE;
210
211 region->offset = 64;
212 region->length = 64;
213
214 return 0;
215 }
216
gd5fxgqx_variant2_ooblayout_free(struct mtd_info * mtd,int section,struct mtd_oob_region * region)217 static int gd5fxgqx_variant2_ooblayout_free(struct mtd_info *mtd, int section,
218 struct mtd_oob_region *region)
219 {
220 if (section)
221 return -ERANGE;
222
223 /* Reserve 1 bytes for the BBM. */
224 region->offset = 1;
225 region->length = 63;
226
227 return 0;
228 }
229
230 /* Valid for Q4/Q5 and Q6 (untested) devices */
231 static const struct mtd_ooblayout_ops gd5fxgqx_variant2_ooblayout = {
232 .ecc = gd5fxgqx_variant2_ooblayout_ecc,
233 .free = gd5fxgqx_variant2_ooblayout_free,
234 };
235
gd5fxgq4xc_ooblayout_256_ecc(struct mtd_info * mtd,int section,struct mtd_oob_region * oobregion)236 static int gd5fxgq4xc_ooblayout_256_ecc(struct mtd_info *mtd, int section,
237 struct mtd_oob_region *oobregion)
238 {
239 if (section)
240 return -ERANGE;
241
242 oobregion->offset = 128;
243 oobregion->length = 128;
244
245 return 0;
246 }
247
gd5fxgq4xc_ooblayout_256_free(struct mtd_info * mtd,int section,struct mtd_oob_region * oobregion)248 static int gd5fxgq4xc_ooblayout_256_free(struct mtd_info *mtd, int section,
249 struct mtd_oob_region *oobregion)
250 {
251 if (section)
252 return -ERANGE;
253
254 oobregion->offset = 1;
255 oobregion->length = 127;
256
257 return 0;
258 }
259
260 static const struct mtd_ooblayout_ops gd5fxgq4xc_oob_256_ops = {
261 .ecc = gd5fxgq4xc_ooblayout_256_ecc,
262 .free = gd5fxgq4xc_ooblayout_256_free,
263 };
264
gd5fxgq4uexxg_ecc_get_status(struct spinand_device * spinand,u8 status)265 static int gd5fxgq4uexxg_ecc_get_status(struct spinand_device *spinand,
266 u8 status)
267 {
268 u8 status2;
269 struct spi_mem_op op = SPINAND_OP(spinand, get_feature,
270 GD5FXGQXXEXXG_REG_STATUS2, spinand->scratchbuf);
271 int ret;
272
273 switch (status & STATUS_ECC_MASK) {
274 case STATUS_ECC_NO_BITFLIPS:
275 return 0;
276
277 case GD5FXGQ4XA_STATUS_ECC_1_7_BITFLIPS:
278 /*
279 * Read status2 register to determine a more fine grained
280 * bit error status
281 */
282 ret = spi_mem_exec_op(spinand->spimem, &op);
283 if (ret)
284 return ret;
285
286 /*
287 * 4 ... 7 bits are flipped (1..4 can't be detected, so
288 * report the maximum of 4 in this case
289 */
290 /* bits sorted this way (3...0): ECCS1,ECCS0,ECCSE1,ECCSE0 */
291 status2 = *(spinand->scratchbuf);
292 return ((status & STATUS_ECC_MASK) >> 2) |
293 ((status2 & STATUS_ECC_MASK) >> 4);
294
295 case GD5FXGQ4XA_STATUS_ECC_8_BITFLIPS:
296 return 8;
297
298 case STATUS_ECC_UNCOR_ERROR:
299 return -EBADMSG;
300
301 default:
302 break;
303 }
304
305 return -EINVAL;
306 }
307
gd5fxgq5xexxg_ecc_get_status(struct spinand_device * spinand,u8 status)308 static int gd5fxgq5xexxg_ecc_get_status(struct spinand_device *spinand,
309 u8 status)
310 {
311 u8 status2;
312 struct spi_mem_op op = SPINAND_OP(spinand, get_feature,
313 GD5FXGQXXEXXG_REG_STATUS2, spinand->scratchbuf);
314 int ret;
315
316 switch (status & STATUS_ECC_MASK) {
317 case STATUS_ECC_NO_BITFLIPS:
318 return 0;
319
320 case GD5FXGQ5XE_STATUS_ECC_1_4_BITFLIPS:
321 /*
322 * Read status2 register to determine a more fine grained
323 * bit error status
324 */
325 ret = spi_mem_exec_op(spinand->spimem, &op);
326 if (ret)
327 return ret;
328
329 /*
330 * 1 ... 4 bits are flipped (and corrected)
331 */
332 /* bits sorted this way (1...0): ECCSE1, ECCSE0 */
333 status2 = *(spinand->scratchbuf);
334 return ((status2 & STATUS_ECC_MASK) >> 4) + 1;
335
336 case STATUS_ECC_UNCOR_ERROR:
337 return -EBADMSG;
338
339 default:
340 break;
341 }
342
343 return -EINVAL;
344 }
345
gd5fxgq4ufxxg_ecc_get_status(struct spinand_device * spinand,u8 status)346 static int gd5fxgq4ufxxg_ecc_get_status(struct spinand_device *spinand,
347 u8 status)
348 {
349 switch (status & GD5FXGQ4UXFXXG_STATUS_ECC_MASK) {
350 case GD5FXGQ4UXFXXG_STATUS_ECC_NO_BITFLIPS:
351 return 0;
352
353 case GD5FXGQ4UXFXXG_STATUS_ECC_1_3_BITFLIPS:
354 return 3;
355
356 case GD5FXGQ4UXFXXG_STATUS_ECC_UNCOR_ERROR:
357 return -EBADMSG;
358
359 default: /* (2 << 4) through (6 << 4) are 4-8 corrected errors */
360 return ((status & GD5FXGQ4UXFXXG_STATUS_ECC_MASK) >> 4) + 2;
361 }
362
363 return -EINVAL;
364 }
365
366 static const struct spinand_info gigadevice_spinand_table[] = {
367 SPINAND_INFO("GD5F1GQ4xA",
368 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0xf1),
369 NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1),
370 NAND_ECCREQ(8, 512),
371 SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
372 &write_cache_variants,
373 &update_cache_variants),
374 SPINAND_HAS_QE_BIT,
375 SPINAND_ECCINFO(&gd5fxgq4xa_ooblayout,
376 gd5fxgq4xa_ecc_get_status)),
377 SPINAND_INFO("GD5F2GQ4xA",
378 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0xf2),
379 NAND_MEMORG(1, 2048, 64, 64, 2048, 40, 1, 1, 1),
380 NAND_ECCREQ(8, 512),
381 SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
382 &write_cache_variants,
383 &update_cache_variants),
384 SPINAND_HAS_QE_BIT,
385 SPINAND_ECCINFO(&gd5fxgq4xa_ooblayout,
386 gd5fxgq4xa_ecc_get_status)),
387 SPINAND_INFO("GD5F4GQ4xA",
388 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0xf4),
389 NAND_MEMORG(1, 2048, 64, 64, 4096, 80, 1, 1, 1),
390 NAND_ECCREQ(8, 512),
391 SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
392 &write_cache_variants,
393 &update_cache_variants),
394 SPINAND_HAS_QE_BIT,
395 SPINAND_ECCINFO(&gd5fxgq4xa_ooblayout,
396 gd5fxgq4xa_ecc_get_status)),
397 SPINAND_INFO("GD5F4GQ4RC",
398 SPINAND_ID(SPINAND_READID_METHOD_OPCODE, 0xa4, 0x68),
399 NAND_MEMORG(1, 4096, 256, 64, 2048, 40, 1, 1, 1),
400 NAND_ECCREQ(8, 512),
401 SPINAND_INFO_OP_VARIANTS(&read_cache_variants_f,
402 &write_cache_variants,
403 &update_cache_variants),
404 SPINAND_HAS_QE_BIT,
405 SPINAND_ECCINFO(&gd5fxgq4xc_oob_256_ops,
406 gd5fxgq4ufxxg_ecc_get_status)),
407 SPINAND_INFO("GD5F4GQ4UC",
408 SPINAND_ID(SPINAND_READID_METHOD_OPCODE, 0xb4, 0x68),
409 NAND_MEMORG(1, 4096, 256, 64, 2048, 40, 1, 1, 1),
410 NAND_ECCREQ(8, 512),
411 SPINAND_INFO_OP_VARIANTS(&read_cache_variants_f,
412 &write_cache_variants,
413 &update_cache_variants),
414 SPINAND_HAS_QE_BIT,
415 SPINAND_ECCINFO(&gd5fxgq4xc_oob_256_ops,
416 gd5fxgq4ufxxg_ecc_get_status)),
417 SPINAND_INFO("GD5F1GQ4UExxG",
418 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0xd1),
419 NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),
420 NAND_ECCREQ(8, 512),
421 SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
422 &write_cache_variants,
423 &update_cache_variants),
424 SPINAND_HAS_QE_BIT,
425 SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
426 gd5fxgq4uexxg_ecc_get_status)),
427 SPINAND_INFO("GD5F1GQ4RExxG",
428 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0xc1),
429 NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),
430 NAND_ECCREQ(8, 512),
431 SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
432 &write_cache_variants,
433 &update_cache_variants),
434 SPINAND_HAS_QE_BIT,
435 SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
436 gd5fxgq4uexxg_ecc_get_status)),
437 SPINAND_INFO("GD5F2GQ4UExxG",
438 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0xd2),
439 NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1),
440 NAND_ECCREQ(8, 512),
441 SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
442 &write_cache_variants,
443 &update_cache_variants),
444 SPINAND_HAS_QE_BIT,
445 SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
446 gd5fxgq4uexxg_ecc_get_status)),
447 SPINAND_INFO("GD5F2GQ4RExxG",
448 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0xc2),
449 NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1),
450 NAND_ECCREQ(8, 512),
451 SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
452 &write_cache_variants,
453 &update_cache_variants),
454 SPINAND_HAS_QE_BIT,
455 SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
456 gd5fxgq4uexxg_ecc_get_status)),
457 SPINAND_INFO("GD5F1GQ4UFxxG",
458 SPINAND_ID(SPINAND_READID_METHOD_OPCODE, 0xb1, 0x48),
459 NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),
460 NAND_ECCREQ(8, 512),
461 SPINAND_INFO_OP_VARIANTS(&read_cache_variants_f,
462 &write_cache_variants,
463 &update_cache_variants),
464 SPINAND_HAS_QE_BIT,
465 SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
466 gd5fxgq4ufxxg_ecc_get_status)),
467 SPINAND_INFO("GD5F1GQ5UExxG",
468 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x51),
469 NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),
470 NAND_ECCREQ(4, 512),
471 SPINAND_INFO_OP_VARIANTS(&read_cache_variants_1gq5,
472 &write_cache_variants,
473 &update_cache_variants),
474 SPINAND_HAS_QE_BIT,
475 SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
476 gd5fxgq5xexxg_ecc_get_status)),
477 SPINAND_INFO("GD5F1GQ5RExxG",
478 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x41),
479 NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),
480 NAND_ECCREQ(4, 512),
481 SPINAND_INFO_OP_VARIANTS(&read_cache_variants_1gq5,
482 &write_cache_variants,
483 &update_cache_variants),
484 SPINAND_HAS_QE_BIT,
485 SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
486 gd5fxgq5xexxg_ecc_get_status)),
487 SPINAND_INFO("GD5F2GQ5UExxG",
488 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x52),
489 NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1),
490 NAND_ECCREQ(4, 512),
491 SPINAND_INFO_OP_VARIANTS(&read_cache_variants_2gq5,
492 &write_cache_variants,
493 &update_cache_variants),
494 SPINAND_HAS_QE_BIT,
495 SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
496 gd5fxgq5xexxg_ecc_get_status)),
497 SPINAND_INFO("GD5F2GQ5RExxG",
498 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x42),
499 NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1),
500 NAND_ECCREQ(4, 512),
501 SPINAND_INFO_OP_VARIANTS(&read_cache_variants_2gq5,
502 &write_cache_variants,
503 &update_cache_variants),
504 SPINAND_HAS_QE_BIT,
505 SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
506 gd5fxgq5xexxg_ecc_get_status)),
507 SPINAND_INFO("GD5F4GQ6UExxG",
508 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x55),
509 NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 2, 1),
510 NAND_ECCREQ(4, 512),
511 SPINAND_INFO_OP_VARIANTS(&read_cache_variants_2gq5,
512 &write_cache_variants,
513 &update_cache_variants),
514 SPINAND_HAS_QE_BIT,
515 SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
516 gd5fxgq5xexxg_ecc_get_status)),
517 SPINAND_INFO("GD5F4GQ6RExxG",
518 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x45),
519 NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 2, 1),
520 NAND_ECCREQ(4, 512),
521 SPINAND_INFO_OP_VARIANTS(&read_cache_variants_2gq5,
522 &write_cache_variants,
523 &update_cache_variants),
524 SPINAND_HAS_QE_BIT,
525 SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
526 gd5fxgq5xexxg_ecc_get_status)),
527 SPINAND_INFO("GD5F1GM7UExxG",
528 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x91),
529 NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),
530 NAND_ECCREQ(8, 512),
531 SPINAND_INFO_OP_VARIANTS(&read_cache_variants_1gq5,
532 &write_cache_variants,
533 &update_cache_variants),
534 SPINAND_HAS_QE_BIT,
535 SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
536 gd5fxgq4uexxg_ecc_get_status)),
537 SPINAND_INFO("GD5F1GM7RExxG",
538 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x81),
539 NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),
540 NAND_ECCREQ(8, 512),
541 SPINAND_INFO_OP_VARIANTS(&read_cache_variants_1gq5,
542 &write_cache_variants,
543 &update_cache_variants),
544 SPINAND_HAS_QE_BIT,
545 SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
546 gd5fxgq4uexxg_ecc_get_status)),
547 SPINAND_INFO("GD5F2GM7UExxG",
548 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x92),
549 NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1),
550 NAND_ECCREQ(8, 512),
551 SPINAND_INFO_OP_VARIANTS(&read_cache_variants_1gq5,
552 &write_cache_variants,
553 &update_cache_variants),
554 SPINAND_HAS_QE_BIT,
555 SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
556 gd5fxgq4uexxg_ecc_get_status)),
557 SPINAND_INFO("GD5F2GM7RExxG",
558 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x82),
559 NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1),
560 NAND_ECCREQ(8, 512),
561 SPINAND_INFO_OP_VARIANTS(&read_cache_variants_1gq5,
562 &write_cache_variants,
563 &update_cache_variants),
564 SPINAND_HAS_QE_BIT,
565 SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
566 gd5fxgq4uexxg_ecc_get_status)),
567 SPINAND_INFO("GD5F4GM8UExxG",
568 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x95),
569 NAND_MEMORG(1, 2048, 128, 64, 4096, 80, 1, 1, 1),
570 NAND_ECCREQ(8, 512),
571 SPINAND_INFO_OP_VARIANTS(&read_cache_variants_1gq5,
572 &write_cache_variants,
573 &update_cache_variants),
574 SPINAND_HAS_QE_BIT,
575 SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
576 gd5fxgq4uexxg_ecc_get_status)),
577 SPINAND_INFO("GD5F4GM8RExxG",
578 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x85),
579 NAND_MEMORG(1, 2048, 128, 64, 4096, 80, 1, 1, 1),
580 NAND_ECCREQ(8, 512),
581 SPINAND_INFO_OP_VARIANTS(&read_cache_variants_1gq5,
582 &write_cache_variants,
583 &update_cache_variants),
584 SPINAND_HAS_QE_BIT,
585 SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
586 gd5fxgq4uexxg_ecc_get_status)),
587 SPINAND_INFO("GD5F2GQ5xExxH",
588 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x22),
589 NAND_MEMORG(1, 2048, 64, 64, 2048, 40, 1, 1, 1),
590 NAND_ECCREQ(4, 512),
591 SPINAND_INFO_OP_VARIANTS(&read_cache_variants_2gq5,
592 &write_cache_variants,
593 &update_cache_variants),
594 SPINAND_HAS_QE_BIT,
595 SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
596 gd5fxgq4uexxg_ecc_get_status)),
597 SPINAND_INFO("GD5F1GQ5RExxH",
598 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x21),
599 NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1),
600 NAND_ECCREQ(4, 512),
601 SPINAND_INFO_OP_VARIANTS(&read_cache_variants_1gq5,
602 &write_cache_variants,
603 &update_cache_variants),
604 SPINAND_HAS_QE_BIT,
605 SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
606 gd5fxgq4uexxg_ecc_get_status)),
607 SPINAND_INFO("GD5F1GQ4RExxH",
608 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xc9),
609 NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1),
610 NAND_ECCREQ(4, 512),
611 SPINAND_INFO_OP_VARIANTS(&read_cache_variants_1gq5,
612 &write_cache_variants,
613 &update_cache_variants),
614 SPINAND_HAS_QE_BIT,
615 SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
616 gd5fxgq4uexxg_ecc_get_status)),
617 SPINAND_INFO("GD5F1GM9UExxG",
618 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x91, 0x01),
619 NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),
620 NAND_ECCREQ(8, 512),
621 SPINAND_INFO_OP_VARIANTS(&read_cache_variants_1gq5,
622 &write_cache_variants,
623 &update_cache_variants),
624 SPINAND_HAS_QE_BIT,
625 SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
626 gd5fxgm9_ecc_get_status),
627 SPINAND_CONT_READ(gd5fxgm9_set_continuous_read)),
628 SPINAND_INFO("GD5F1GM9RExxG",
629 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x81, 0x01),
630 NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),
631 NAND_ECCREQ(8, 512),
632 SPINAND_INFO_OP_VARIANTS(&read_cache_variants_1gq5,
633 &write_cache_variants,
634 &update_cache_variants),
635 SPINAND_HAS_QE_BIT,
636 SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
637 gd5fxgm9_ecc_get_status),
638 SPINAND_CONT_READ(gd5fxgm9_set_continuous_read)),
639 };
640
gd5fxgm9_spinand_init(struct spinand_device * spinand)641 static int gd5fxgm9_spinand_init(struct spinand_device *spinand)
642 {
643 struct gigadevice_priv *priv;
644
645 priv = kzalloc_obj(*priv);
646 if (!priv)
647 return -ENOMEM;
648
649 spinand->priv = priv;
650
651 return 0;
652 }
653
gd5fxgm9_spinand_cleanup(struct spinand_device * spinand)654 static void gd5fxgm9_spinand_cleanup(struct spinand_device *spinand)
655 {
656 kfree(spinand->priv);
657 }
658
659 static const struct spinand_manufacturer_ops gigadevice_spinand_manuf_ops = {
660 .init = gd5fxgm9_spinand_init,
661 .cleanup = gd5fxgm9_spinand_cleanup,
662 };
663
664 const struct spinand_manufacturer gigadevice_spinand_manufacturer = {
665 .id = SPINAND_MFR_GIGADEVICE,
666 .name = "GigaDevice",
667 .chips = gigadevice_spinand_table,
668 .nchips = ARRAY_SIZE(gigadevice_spinand_table),
669 .ops = &gigadevice_spinand_manuf_ops,
670 };
671