hc
2024-05-10 61598093bbdd283a7edc367d900f223070ead8d2
kernel/drivers/mtd/nand/spi/micron.c
....@@ -18,7 +18,17 @@
1818 #define MICRON_STATUS_ECC_4TO6_BITFLIPS (3 << 4)
1919 #define MICRON_STATUS_ECC_7TO8_BITFLIPS (5 << 4)
2020
21
-static SPINAND_OP_VARIANTS(read_cache_variants,
21
+#define MICRON_CFG_CR BIT(0)
22
+
23
+/*
24
+ * As per datasheet, die selection is done by the 6th bit of Die
25
+ * Select Register (Address 0xD0).
26
+ */
27
+#define MICRON_DIE_SELECT_REG 0xD0
28
+
29
+#define MICRON_SELECT_DIE(x) ((x) << 6)
30
+
31
+static SPINAND_OP_VARIANTS(quadio_read_cache_variants,
2232 SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP(0, 2, NULL, 0),
2333 SPINAND_PAGE_READ_FROM_CACHE_X4_OP(0, 1, NULL, 0),
2434 SPINAND_PAGE_READ_FROM_CACHE_DUALIO_OP(0, 1, NULL, 0),
....@@ -26,46 +36,114 @@
2636 SPINAND_PAGE_READ_FROM_CACHE_OP(true, 0, 1, NULL, 0),
2737 SPINAND_PAGE_READ_FROM_CACHE_OP(false, 0, 1, NULL, 0));
2838
29
-static SPINAND_OP_VARIANTS(write_cache_variants,
39
+static SPINAND_OP_VARIANTS(x4_write_cache_variants,
3040 SPINAND_PROG_LOAD_X4(true, 0, NULL, 0),
3141 SPINAND_PROG_LOAD(true, 0, NULL, 0));
3242
33
-static SPINAND_OP_VARIANTS(update_cache_variants,
43
+static SPINAND_OP_VARIANTS(x4_update_cache_variants,
3444 SPINAND_PROG_LOAD_X4(false, 0, NULL, 0),
3545 SPINAND_PROG_LOAD(false, 0, NULL, 0));
3646
37
-static int mt29f2g01abagd_ooblayout_ecc(struct mtd_info *mtd, int section,
38
- struct mtd_oob_region *region)
47
+/* Micron MT29F2G01AAAED Device */
48
+static SPINAND_OP_VARIANTS(x4_read_cache_variants,
49
+ SPINAND_PAGE_READ_FROM_CACHE_X4_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(x1_write_cache_variants,
55
+ SPINAND_PROG_LOAD(true, 0, NULL, 0));
56
+
57
+static SPINAND_OP_VARIANTS(x1_update_cache_variants,
58
+ SPINAND_PROG_LOAD(false, 0, NULL, 0));
59
+
60
+static int micron_8_ooblayout_ecc(struct mtd_info *mtd, int section,
61
+ struct mtd_oob_region *region)
3962 {
4063 if (section)
4164 return -ERANGE;
4265
43
- region->offset = 64;
44
- region->length = 64;
66
+ region->offset = mtd->oobsize / 2;
67
+ region->length = mtd->oobsize / 2;
4568
4669 return 0;
4770 }
4871
49
-static int mt29f2g01abagd_ooblayout_free(struct mtd_info *mtd, int section,
50
- struct mtd_oob_region *region)
72
+static int micron_8_ooblayout_free(struct mtd_info *mtd, int section,
73
+ struct mtd_oob_region *region)
5174 {
5275 if (section)
5376 return -ERANGE;
5477
5578 /* Reserve 2 bytes for the BBM. */
5679 region->offset = 2;
57
- region->length = 62;
80
+ region->length = (mtd->oobsize / 2) - 2;
5881
5982 return 0;
6083 }
6184
62
-static const struct mtd_ooblayout_ops mt29f2g01abagd_ooblayout = {
63
- .ecc = mt29f2g01abagd_ooblayout_ecc,
64
- .free = mt29f2g01abagd_ooblayout_free,
85
+static const struct mtd_ooblayout_ops micron_8_ooblayout = {
86
+ .ecc = micron_8_ooblayout_ecc,
87
+ .free = micron_8_ooblayout_free,
6588 };
6689
67
-static int mt29f2g01abagd_ecc_get_status(struct spinand_device *spinand,
68
- u8 status)
90
+static int micron_4_ooblayout_ecc(struct mtd_info *mtd, int section,
91
+ struct mtd_oob_region *region)
92
+{
93
+ struct spinand_device *spinand = mtd_to_spinand(mtd);
94
+
95
+ if (section >= spinand->base.memorg.pagesize /
96
+ mtd->ecc_step_size)
97
+ return -ERANGE;
98
+
99
+ region->offset = (section * 16) + 8;
100
+ region->length = 8;
101
+
102
+ return 0;
103
+}
104
+
105
+static int micron_4_ooblayout_free(struct mtd_info *mtd, int section,
106
+ struct mtd_oob_region *region)
107
+{
108
+ struct spinand_device *spinand = mtd_to_spinand(mtd);
109
+
110
+ if (section >= spinand->base.memorg.pagesize /
111
+ mtd->ecc_step_size)
112
+ return -ERANGE;
113
+
114
+ if (section) {
115
+ region->offset = 16 * section;
116
+ region->length = 8;
117
+ } else {
118
+ /* section 0 has two bytes reserved for the BBM */
119
+ region->offset = 2;
120
+ region->length = 6;
121
+ }
122
+
123
+ return 0;
124
+}
125
+
126
+static const struct mtd_ooblayout_ops micron_4_ooblayout = {
127
+ .ecc = micron_4_ooblayout_ecc,
128
+ .free = micron_4_ooblayout_free,
129
+};
130
+
131
+static int micron_select_target(struct spinand_device *spinand,
132
+ unsigned int target)
133
+{
134
+ struct spi_mem_op op = SPINAND_SET_FEATURE_OP(MICRON_DIE_SELECT_REG,
135
+ spinand->scratchbuf);
136
+
137
+ if (target > 1)
138
+ return -EINVAL;
139
+
140
+ *spinand->scratchbuf = MICRON_SELECT_DIE(target);
141
+
142
+ return spi_mem_exec_op(spinand->spimem, &op);
143
+}
144
+
145
+static int micron_8_ecc_get_status(struct spinand_device *spinand,
146
+ u8 status)
69147 {
70148 switch (status & MICRON_STATUS_ECC_MASK) {
71149 case STATUS_ECC_NO_BITFLIPS:
....@@ -91,43 +169,141 @@
91169 }
92170
93171 static const struct spinand_info micron_spinand_table[] = {
94
- SPINAND_INFO("MT29F2G01ABAGD", 0x24,
95
- NAND_MEMORG(1, 2048, 128, 64, 2048, 2, 1, 1),
172
+ /* M79A 2Gb 3.3V */
173
+ SPINAND_INFO("MT29F2G01ABAGD",
174
+ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x24),
175
+ NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 2, 1, 1),
96176 NAND_ECCREQ(8, 512),
97
- SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
98
- &write_cache_variants,
99
- &update_cache_variants),
177
+ SPINAND_INFO_OP_VARIANTS(&quadio_read_cache_variants,
178
+ &x4_write_cache_variants,
179
+ &x4_update_cache_variants),
100180 0,
101
- SPINAND_ECCINFO(&mt29f2g01abagd_ooblayout,
102
- mt29f2g01abagd_ecc_get_status)),
181
+ SPINAND_ECCINFO(&micron_8_ooblayout,
182
+ micron_8_ecc_get_status)),
183
+ /* M79A 2Gb 1.8V */
184
+ SPINAND_INFO("MT29F2G01ABBGD",
185
+ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x25),
186
+ NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 2, 1, 1),
187
+ NAND_ECCREQ(8, 512),
188
+ SPINAND_INFO_OP_VARIANTS(&quadio_read_cache_variants,
189
+ &x4_write_cache_variants,
190
+ &x4_update_cache_variants),
191
+ 0,
192
+ SPINAND_ECCINFO(&micron_8_ooblayout,
193
+ micron_8_ecc_get_status)),
194
+ /* M78A 1Gb 3.3V */
195
+ SPINAND_INFO("MT29F1G01ABAFD",
196
+ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x14),
197
+ NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),
198
+ NAND_ECCREQ(8, 512),
199
+ SPINAND_INFO_OP_VARIANTS(&quadio_read_cache_variants,
200
+ &x4_write_cache_variants,
201
+ &x4_update_cache_variants),
202
+ 0,
203
+ SPINAND_ECCINFO(&micron_8_ooblayout,
204
+ micron_8_ecc_get_status)),
205
+ /* M78A 1Gb 1.8V */
206
+ SPINAND_INFO("MT29F1G01ABAFD",
207
+ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x15),
208
+ NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),
209
+ NAND_ECCREQ(8, 512),
210
+ SPINAND_INFO_OP_VARIANTS(&quadio_read_cache_variants,
211
+ &x4_write_cache_variants,
212
+ &x4_update_cache_variants),
213
+ 0,
214
+ SPINAND_ECCINFO(&micron_8_ooblayout,
215
+ micron_8_ecc_get_status)),
216
+ /* M79A 4Gb 3.3V */
217
+ SPINAND_INFO("MT29F4G01ADAGD",
218
+ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x36),
219
+ NAND_MEMORG(1, 2048, 128, 64, 2048, 80, 2, 1, 2),
220
+ NAND_ECCREQ(8, 512),
221
+ SPINAND_INFO_OP_VARIANTS(&quadio_read_cache_variants,
222
+ &x4_write_cache_variants,
223
+ &x4_update_cache_variants),
224
+ 0,
225
+ SPINAND_ECCINFO(&micron_8_ooblayout,
226
+ micron_8_ecc_get_status),
227
+ SPINAND_SELECT_TARGET(micron_select_target)),
228
+ /* M70A 4Gb 3.3V */
229
+ SPINAND_INFO("MT29F4G01ABAFD",
230
+ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x34),
231
+ NAND_MEMORG(1, 4096, 256, 64, 2048, 40, 1, 1, 1),
232
+ NAND_ECCREQ(8, 512),
233
+ SPINAND_INFO_OP_VARIANTS(&quadio_read_cache_variants,
234
+ &x4_write_cache_variants,
235
+ &x4_update_cache_variants),
236
+ SPINAND_HAS_CR_FEAT_BIT,
237
+ SPINAND_ECCINFO(&micron_8_ooblayout,
238
+ micron_8_ecc_get_status)),
239
+ /* M70A 4Gb 1.8V */
240
+ SPINAND_INFO("MT29F4G01ABBFD",
241
+ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x35),
242
+ NAND_MEMORG(1, 4096, 256, 64, 2048, 40, 1, 1, 1),
243
+ NAND_ECCREQ(8, 512),
244
+ SPINAND_INFO_OP_VARIANTS(&quadio_read_cache_variants,
245
+ &x4_write_cache_variants,
246
+ &x4_update_cache_variants),
247
+ SPINAND_HAS_CR_FEAT_BIT,
248
+ SPINAND_ECCINFO(&micron_8_ooblayout,
249
+ micron_8_ecc_get_status)),
250
+ /* M70A 8Gb 3.3V */
251
+ SPINAND_INFO("MT29F8G01ADAFD",
252
+ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x46),
253
+ NAND_MEMORG(1, 4096, 256, 64, 2048, 40, 1, 1, 2),
254
+ NAND_ECCREQ(8, 512),
255
+ SPINAND_INFO_OP_VARIANTS(&quadio_read_cache_variants,
256
+ &x4_write_cache_variants,
257
+ &x4_update_cache_variants),
258
+ SPINAND_HAS_CR_FEAT_BIT,
259
+ SPINAND_ECCINFO(&micron_8_ooblayout,
260
+ micron_8_ecc_get_status),
261
+ SPINAND_SELECT_TARGET(micron_select_target)),
262
+ /* M70A 8Gb 1.8V */
263
+ SPINAND_INFO("MT29F8G01ADBFD",
264
+ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x47),
265
+ NAND_MEMORG(1, 4096, 256, 64, 2048, 40, 1, 1, 2),
266
+ NAND_ECCREQ(8, 512),
267
+ SPINAND_INFO_OP_VARIANTS(&quadio_read_cache_variants,
268
+ &x4_write_cache_variants,
269
+ &x4_update_cache_variants),
270
+ SPINAND_HAS_CR_FEAT_BIT,
271
+ SPINAND_ECCINFO(&micron_8_ooblayout,
272
+ micron_8_ecc_get_status),
273
+ SPINAND_SELECT_TARGET(micron_select_target)),
274
+ /* M69A 2Gb 3.3V */
275
+ SPINAND_INFO("MT29F2G01AAAED",
276
+ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x9F),
277
+ NAND_MEMORG(1, 2048, 64, 64, 2048, 80, 2, 1, 1),
278
+ NAND_ECCREQ(4, 512),
279
+ SPINAND_INFO_OP_VARIANTS(&x4_read_cache_variants,
280
+ &x1_write_cache_variants,
281
+ &x1_update_cache_variants),
282
+ 0,
283
+ SPINAND_ECCINFO(&micron_4_ooblayout, NULL)),
103284 };
104285
105
-static int micron_spinand_detect(struct spinand_device *spinand)
286
+static int micron_spinand_init(struct spinand_device *spinand)
106287 {
107
- u8 *id = spinand->id.data;
108
- int ret;
109
-
110288 /*
111
- * Micron SPI NAND read ID need a dummy byte,
112
- * so the first byte in raw_id is dummy.
289
+ * M70A device series enable Continuous Read feature at Power-up,
290
+ * which is not supported. Disable this bit to avoid any possible
291
+ * failure.
113292 */
114
- if (id[1] != SPINAND_MFR_MICRON)
115
- return 0;
293
+ if (spinand->flags & SPINAND_HAS_CR_FEAT_BIT)
294
+ return spinand_upd_cfg(spinand, MICRON_CFG_CR, 0);
116295
117
- ret = spinand_match_and_init(spinand, micron_spinand_table,
118
- ARRAY_SIZE(micron_spinand_table), id[2]);
119
- if (ret)
120
- return ret;
121
-
122
- return 1;
296
+ return 0;
123297 }
124298
125299 static const struct spinand_manufacturer_ops micron_spinand_manuf_ops = {
126
- .detect = micron_spinand_detect,
300
+ .init = micron_spinand_init,
127301 };
128302
129303 const struct spinand_manufacturer micron_spinand_manufacturer = {
130304 .id = SPINAND_MFR_MICRON,
131305 .name = "Micron",
306
+ .chips = micron_spinand_table,
307
+ .nchips = ARRAY_SIZE(micron_spinand_table),
132308 .ops = &micron_spinand_manuf_ops,
133309 };