blob: 13658540618a5a57831c514a3e61d0de39371e38 [file] [log] [blame]
developer937e1212023-08-11 19:47:10 +08001Index: linux-5.4.246/drivers/mtd/nand/spi/gigadevice.c
2===================================================================
3--- linux-5.4.246.orig/drivers/mtd/nand/spi/gigadevice.c
4+++ linux-5.4.246/drivers/mtd/nand/spi/gigadevice.c
5@@ -13,7 +13,10 @@
6 #define GD5FXGQ4XA_STATUS_ECC_1_7_BITFLIPS (1 << 4)
7 #define GD5FXGQ4XA_STATUS_ECC_8_BITFLIPS (3 << 4)
8
9-#define GD5FXGQ4UEXXG_REG_STATUS2 0xf0
10+#define GD5FXGQ5XE_STATUS_ECC_1_4_BITFLIPS (1 << 4)
11+#define GD5FXGQ5XE_STATUS_ECC_4_BITFLIPS (3 << 4)
12+
13+#define GD5FXGQXXEXXG_REG_STATUS2 0xf0
14
15 #define GD5FXGQ4UXFXXG_STATUS_ECC_MASK (7 << 4)
16 #define GD5FXGQ4UXFXXG_STATUS_ECC_NO_BITFLIPS (0 << 4)
17@@ -36,6 +39,22 @@ static SPINAND_OP_VARIANTS(read_cache_va
18 SPINAND_PAGE_READ_FROM_CACHE_OP_3A(true, 0, 1, NULL, 0),
19 SPINAND_PAGE_READ_FROM_CACHE_OP_3A(false, 0, 0, NULL, 0));
20
21+static SPINAND_OP_VARIANTS(read_cache_variants_1gq5,
22+ SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP(0, 2, NULL, 0),
23+ SPINAND_PAGE_READ_FROM_CACHE_X4_OP(0, 1, NULL, 0),
24+ SPINAND_PAGE_READ_FROM_CACHE_DUALIO_OP(0, 1, NULL, 0),
25+ SPINAND_PAGE_READ_FROM_CACHE_X2_OP(0, 1, NULL, 0),
26+ SPINAND_PAGE_READ_FROM_CACHE_OP(true, 0, 1, NULL, 0),
27+ SPINAND_PAGE_READ_FROM_CACHE_OP(false, 0, 1, NULL, 0));
28+
29+static SPINAND_OP_VARIANTS(read_cache_variants_2gq5,
30+ SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP(0, 4, NULL, 0),
31+ SPINAND_PAGE_READ_FROM_CACHE_X4_OP(0, 1, NULL, 0),
32+ SPINAND_PAGE_READ_FROM_CACHE_DUALIO_OP(0, 2, NULL, 0),
33+ SPINAND_PAGE_READ_FROM_CACHE_X2_OP(0, 1, NULL, 0),
34+ SPINAND_PAGE_READ_FROM_CACHE_OP(true, 0, 1, NULL, 0),
35+ SPINAND_PAGE_READ_FROM_CACHE_OP(false, 0, 1, NULL, 0));
36+
37 static SPINAND_OP_VARIANTS(write_cache_variants,
38 SPINAND_PROG_LOAD_X4(true, 0, NULL, 0),
39 SPINAND_PROG_LOAD(true, 0, NULL, 0));
40@@ -102,7 +121,7 @@ static int gd5fxgq4xa_ecc_get_status(str
41 return -EINVAL;
42 }
43
44-static int gd5fxgq4_variant2_ooblayout_ecc(struct mtd_info *mtd, int section,
45+static int gd5fxgqx_variant2_ooblayout_ecc(struct mtd_info *mtd, int section,
46 struct mtd_oob_region *region)
47 {
48 if (section)
49@@ -114,7 +133,7 @@ static int gd5fxgq4_variant2_ooblayout_e
50 return 0;
51 }
52
53-static int gd5fxgq4_variant2_ooblayout_free(struct mtd_info *mtd, int section,
54+static int gd5fxgqx_variant2_ooblayout_free(struct mtd_info *mtd, int section,
55 struct mtd_oob_region *region)
56 {
57 if (section)
58@@ -127,16 +146,46 @@ static int gd5fxgq4_variant2_ooblayout_f
59 return 0;
60 }
61
62-static const struct mtd_ooblayout_ops gd5fxgq4_variant2_ooblayout = {
63- .ecc = gd5fxgq4_variant2_ooblayout_ecc,
64- .free = gd5fxgq4_variant2_ooblayout_free,
65+/* Valid for Q4/Q5 and Q6 (untested) devices */
66+static const struct mtd_ooblayout_ops gd5fxgqx_variant2_ooblayout = {
67+ .ecc = gd5fxgqx_variant2_ooblayout_ecc,
68+ .free = gd5fxgqx_variant2_ooblayout_free,
69+};
70+
71+static int gd5fxgq4xc_ooblayout_256_ecc(struct mtd_info *mtd, int section,
72+ struct mtd_oob_region *oobregion)
73+{
74+ if (section)
75+ return -ERANGE;
76+
77+ oobregion->offset = 128;
78+ oobregion->length = 128;
79+
80+ return 0;
81+}
82+
83+static int gd5fxgq4xc_ooblayout_256_free(struct mtd_info *mtd, int section,
84+ struct mtd_oob_region *oobregion)
85+{
86+ if (section)
87+ return -ERANGE;
88+
89+ oobregion->offset = 1;
90+ oobregion->length = 127;
91+
92+ return 0;
93+}
94+
95+static const struct mtd_ooblayout_ops gd5fxgq4xc_oob_256_ops = {
96+ .ecc = gd5fxgq4xc_ooblayout_256_ecc,
97+ .free = gd5fxgq4xc_ooblayout_256_free,
98 };
99
100 static int gd5fxgq4uexxg_ecc_get_status(struct spinand_device *spinand,
101 u8 status)
102 {
103 u8 status2;
104- struct spi_mem_op op = SPINAND_GET_FEATURE_OP(GD5FXGQ4UEXXG_REG_STATUS2,
105+ struct spi_mem_op op = SPINAND_GET_FEATURE_OP(GD5FXGQXXEXXG_REG_STATUS2,
106 &status2);
107 int ret;
108
109@@ -174,6 +223,43 @@ static int gd5fxgq4uexxg_ecc_get_status(
110 return -EINVAL;
111 }
112
113+static int gd5fxgq5xexxg_ecc_get_status(struct spinand_device *spinand,
114+ u8 status)
115+{
116+ u8 status2;
117+ struct spi_mem_op op = SPINAND_GET_FEATURE_OP(GD5FXGQXXEXXG_REG_STATUS2,
118+ &status2);
119+ int ret;
120+
121+ switch (status & STATUS_ECC_MASK) {
122+ case STATUS_ECC_NO_BITFLIPS:
123+ return 0;
124+
125+ case GD5FXGQ5XE_STATUS_ECC_1_4_BITFLIPS:
126+ /*
127+ * Read status2 register to determine a more fine grained
128+ * bit error status
129+ */
130+ ret = spi_mem_exec_op(spinand->spimem, &op);
131+ if (ret)
132+ return ret;
133+
134+ /*
135+ * 1 ... 4 bits are flipped (and corrected)
136+ */
137+ /* bits sorted this way (1...0): ECCSE1, ECCSE0 */
138+ return ((status2 & STATUS_ECC_MASK) >> 4) + 1;
139+
140+ case STATUS_ECC_UNCOR_ERROR:
141+ return -EBADMSG;
142+
143+ default:
144+ break;
145+ }
146+
147+ return -EINVAL;
148+}
149+
150 static int gd5fxgq4ufxxg_ecc_get_status(struct spinand_device *spinand,
151 u8 status)
152 {
153@@ -195,7 +281,8 @@ static int gd5fxgq4ufxxg_ecc_get_status(
154 }
155
156 static const struct spinand_info gigadevice_spinand_table[] = {
157- SPINAND_INFO("GD5F1GQ4xA", 0xF1,
158+ SPINAND_INFO("GD5F1GQ4xA",
159+ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0xf1),
160 NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1),
161 NAND_ECCREQ(8, 512),
162 SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
163@@ -204,7 +291,8 @@ static const struct spinand_info gigadev
164 SPINAND_HAS_QE_BIT,
165 SPINAND_ECCINFO(&gd5fxgq4xa_ooblayout,
166 gd5fxgq4xa_ecc_get_status)),
167- SPINAND_INFO("GD5F2GQ4xA", 0xF2,
168+ SPINAND_INFO("GD5F2GQ4xA",
169+ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0xf2),
170 NAND_MEMORG(1, 2048, 64, 64, 2048, 40, 1, 1, 1),
171 NAND_ECCREQ(8, 512),
172 SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
173@@ -213,7 +301,8 @@ static const struct spinand_info gigadev
174 SPINAND_HAS_QE_BIT,
175 SPINAND_ECCINFO(&gd5fxgq4xa_ooblayout,
176 gd5fxgq4xa_ecc_get_status)),
177- SPINAND_INFO("GD5F4GQ4xA", 0xF4,
178+ SPINAND_INFO("GD5F4GQ4xA",
179+ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0xf4),
180 NAND_MEMORG(1, 2048, 64, 64, 4096, 80, 1, 1, 1),
181 NAND_ECCREQ(8, 512),
182 SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
183@@ -222,59 +311,205 @@ static const struct spinand_info gigadev
184 SPINAND_HAS_QE_BIT,
185 SPINAND_ECCINFO(&gd5fxgq4xa_ooblayout,
186 gd5fxgq4xa_ecc_get_status)),
187- SPINAND_INFO("GD5F1GQ4UExxG", 0xd1,
188+ SPINAND_INFO("GD5F4GQ4RC",
189+ SPINAND_ID(SPINAND_READID_METHOD_OPCODE, 0xa4, 0x68),
190+ NAND_MEMORG(1, 4096, 256, 64, 2048, 40, 1, 1, 1),
191+ NAND_ECCREQ(8, 512),
192+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants_f,
193+ &write_cache_variants,
194+ &update_cache_variants),
195+ SPINAND_HAS_QE_BIT,
196+ SPINAND_ECCINFO(&gd5fxgq4xc_oob_256_ops,
197+ gd5fxgq4ufxxg_ecc_get_status)),
198+ SPINAND_INFO("GD5F4GQ4UC",
199+ SPINAND_ID(SPINAND_READID_METHOD_OPCODE, 0xb4, 0x68),
200+ NAND_MEMORG(1, 4096, 256, 64, 2048, 40, 1, 1, 1),
201+ NAND_ECCREQ(8, 512),
202+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants_f,
203+ &write_cache_variants,
204+ &update_cache_variants),
205+ SPINAND_HAS_QE_BIT,
206+ SPINAND_ECCINFO(&gd5fxgq4xc_oob_256_ops,
207+ gd5fxgq4ufxxg_ecc_get_status)),
208+ SPINAND_INFO("GD5F1GQ4UExxG",
209+ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0xd1),
210+ NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),
211+ NAND_ECCREQ(8, 512),
212+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
213+ &write_cache_variants,
214+ &update_cache_variants),
215+ SPINAND_HAS_QE_BIT,
216+ SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
217+ gd5fxgq4uexxg_ecc_get_status)),
218+ SPINAND_INFO("GD5F1GQ4RExxG",
219+ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0xc1),
220 NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),
221 NAND_ECCREQ(8, 512),
222 SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
223 &write_cache_variants,
224 &update_cache_variants),
225 SPINAND_HAS_QE_BIT,
226- SPINAND_ECCINFO(&gd5fxgq4_variant2_ooblayout,
227+ SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
228+ gd5fxgq4uexxg_ecc_get_status)),
229+ SPINAND_INFO("GD5F2GQ4UExxG",
230+ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0xd2),
231+ NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1),
232+ NAND_ECCREQ(8, 512),
233+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
234+ &write_cache_variants,
235+ &update_cache_variants),
236+ SPINAND_HAS_QE_BIT,
237+ SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
238 gd5fxgq4uexxg_ecc_get_status)),
239- SPINAND_INFO("GD5F1GQ4UFxxG", 0xb148,
240+ SPINAND_INFO("GD5F2GQ4RExxG",
241+ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0xc2),
242+ NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1),
243+ NAND_ECCREQ(8, 512),
244+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
245+ &write_cache_variants,
246+ &update_cache_variants),
247+ SPINAND_HAS_QE_BIT,
248+ SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
249+ gd5fxgq4uexxg_ecc_get_status)),
250+ SPINAND_INFO("GD5F1GQ4UFxxG",
251+ SPINAND_ID(SPINAND_READID_METHOD_OPCODE, 0xb1, 0x48),
252 NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),
253 NAND_ECCREQ(8, 512),
254 SPINAND_INFO_OP_VARIANTS(&read_cache_variants_f,
255 &write_cache_variants,
256 &update_cache_variants),
257 SPINAND_HAS_QE_BIT,
258- SPINAND_ECCINFO(&gd5fxgq4_variant2_ooblayout,
259+ SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
260 gd5fxgq4ufxxg_ecc_get_status)),
261+ SPINAND_INFO("GD5F1GQ5UExxG",
262+ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x51),
263+ NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),
264+ NAND_ECCREQ(4, 512),
265+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants_1gq5,
266+ &write_cache_variants,
267+ &update_cache_variants),
268+ SPINAND_HAS_QE_BIT,
269+ SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
270+ gd5fxgq5xexxg_ecc_get_status)),
271+ SPINAND_INFO("GD5F1GQ5RExxG",
272+ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x41),
273+ NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),
274+ NAND_ECCREQ(4, 512),
275+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants_1gq5,
276+ &write_cache_variants,
277+ &update_cache_variants),
278+ SPINAND_HAS_QE_BIT,
279+ SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
280+ gd5fxgq5xexxg_ecc_get_status)),
281+ SPINAND_INFO("GD5F2GQ5UExxG",
282+ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x52),
283+ NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1),
284+ NAND_ECCREQ(4, 512),
285+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants_2gq5,
286+ &write_cache_variants,
287+ &update_cache_variants),
288+ SPINAND_HAS_QE_BIT,
289+ SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
290+ gd5fxgq5xexxg_ecc_get_status)),
291+ SPINAND_INFO("GD5F2GQ5RExxG",
292+ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x42),
293+ NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1),
294+ NAND_ECCREQ(4, 512),
295+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants_2gq5,
296+ &write_cache_variants,
297+ &update_cache_variants),
298+ SPINAND_HAS_QE_BIT,
299+ SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
300+ gd5fxgq5xexxg_ecc_get_status)),
301+ SPINAND_INFO("GD5F4GQ6UExxG",
302+ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x55),
303+ NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 2, 1),
304+ NAND_ECCREQ(4, 512),
305+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants_2gq5,
306+ &write_cache_variants,
307+ &update_cache_variants),
308+ SPINAND_HAS_QE_BIT,
309+ SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
310+ gd5fxgq5xexxg_ecc_get_status)),
311+ SPINAND_INFO("GD5F4GQ6RExxG",
312+ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x45),
313+ NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 2, 1),
314+ NAND_ECCREQ(4, 512),
315+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants_2gq5,
316+ &write_cache_variants,
317+ &update_cache_variants),
318+ SPINAND_HAS_QE_BIT,
319+ SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
320+ gd5fxgq5xexxg_ecc_get_status)),
321+ SPINAND_INFO("GD5F1GM7UExxG",
322+ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x91),
323+ NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),
324+ NAND_ECCREQ(8, 512),
325+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants_1gq5,
326+ &write_cache_variants,
327+ &update_cache_variants),
328+ SPINAND_HAS_QE_BIT,
329+ SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
330+ gd5fxgq4uexxg_ecc_get_status)),
331+ SPINAND_INFO("GD5F1GM7RExxG",
332+ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x81),
333+ NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),
334+ NAND_ECCREQ(8, 512),
335+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants_1gq5,
336+ &write_cache_variants,
337+ &update_cache_variants),
338+ SPINAND_HAS_QE_BIT,
339+ SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
340+ gd5fxgq4uexxg_ecc_get_status)),
341+ SPINAND_INFO("GD5F2GM7UExxG",
342+ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x92),
343+ NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1),
344+ NAND_ECCREQ(8, 512),
345+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants_1gq5,
346+ &write_cache_variants,
347+ &update_cache_variants),
348+ SPINAND_HAS_QE_BIT,
349+ SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
350+ gd5fxgq4uexxg_ecc_get_status)),
351+ SPINAND_INFO("GD5F2GM7RExxG",
352+ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x82),
353+ NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1),
354+ NAND_ECCREQ(8, 512),
355+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants_1gq5,
356+ &write_cache_variants,
357+ &update_cache_variants),
358+ SPINAND_HAS_QE_BIT,
359+ SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
360+ gd5fxgq4uexxg_ecc_get_status)),
361+ SPINAND_INFO("GD5F4GM8UExxG",
362+ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x95),
363+ NAND_MEMORG(1, 2048, 128, 64, 4096, 80, 1, 1, 1),
364+ NAND_ECCREQ(8, 512),
365+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants_1gq5,
366+ &write_cache_variants,
367+ &update_cache_variants),
368+ SPINAND_HAS_QE_BIT,
369+ SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
370+ gd5fxgq4uexxg_ecc_get_status)),
371+ SPINAND_INFO("GD5F4GM8RExxG",
372+ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x85),
373+ NAND_MEMORG(1, 2048, 128, 64, 4096, 80, 1, 1, 1),
374+ NAND_ECCREQ(8, 512),
375+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants_1gq5,
376+ &write_cache_variants,
377+ &update_cache_variants),
378+ SPINAND_HAS_QE_BIT,
379+ SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
380+ gd5fxgq4uexxg_ecc_get_status)),
381 };
382
383-static int gigadevice_spinand_detect(struct spinand_device *spinand)
384-{
385- u8 *id = spinand->id.data;
386- u16 did;
387- int ret;
388-
389- /*
390- * Earlier GDF5-series devices (A,E) return [0][MID][DID]
391- * Later (F) devices return [MID][DID1][DID2]
392- */
393-
394- if (id[0] == SPINAND_MFR_GIGADEVICE)
395- did = (id[1] << 8) + id[2];
396- else if (id[0] == 0 && id[1] == SPINAND_MFR_GIGADEVICE)
397- did = id[2];
398- else
399- return 0;
400-
401- ret = spinand_match_and_init(spinand, gigadevice_spinand_table,
402- ARRAY_SIZE(gigadevice_spinand_table),
403- did);
404- if (ret)
405- return ret;
406-
407- return 1;
408-}
409-
410 static const struct spinand_manufacturer_ops gigadevice_spinand_manuf_ops = {
411- .detect = gigadevice_spinand_detect,
412 };
413
414 const struct spinand_manufacturer gigadevice_spinand_manufacturer = {
415 .id = SPINAND_MFR_GIGADEVICE,
416 .name = "GigaDevice",
417+ .chips = gigadevice_spinand_table,
418+ .nchips = ARRAY_SIZE(gigadevice_spinand_table),
419 .ops = &gigadevice_spinand_manuf_ops,
420 };