xref: /openbmc/linux/drivers/mtd/nand/spi/toshiba.c (revision 8544cda9)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (c) 2018 exceet electronics GmbH
4  * Copyright (c) 2018 Kontron Electronics GmbH
5  *
6  * Author: Frieder Schrempf <frieder.schrempf@kontron.de>
7  */
8 
9 #include <linux/device.h>
10 #include <linux/kernel.h>
11 #include <linux/mtd/spinand.h>
12 
13 /* Kioxia is new name of Toshiba memory. */
14 #define SPINAND_MFR_TOSHIBA		0x98
15 #define TOSH_STATUS_ECC_HAS_BITFLIPS_T	(3 << 4)
16 
17 static SPINAND_OP_VARIANTS(read_cache_variants,
18 		SPINAND_PAGE_READ_FROM_CACHE_X4_OP(0, 1, NULL, 0),
19 		SPINAND_PAGE_READ_FROM_CACHE_X2_OP(0, 1, NULL, 0),
20 		SPINAND_PAGE_READ_FROM_CACHE_OP(true, 0, 1, NULL, 0),
21 		SPINAND_PAGE_READ_FROM_CACHE_OP(false, 0, 1, NULL, 0));
22 
23 static SPINAND_OP_VARIANTS(write_cache_x4_variants,
24 		SPINAND_PROG_LOAD_X4(true, 0, NULL, 0),
25 		SPINAND_PROG_LOAD(true, 0, NULL, 0));
26 
27 static SPINAND_OP_VARIANTS(update_cache_x4_variants,
28 		SPINAND_PROG_LOAD_X4(false, 0, NULL, 0),
29 		SPINAND_PROG_LOAD(false, 0, NULL, 0));
30 
31 /*
32  * Backward compatibility for 1st generation Serial NAND devices
33  * which don't support Quad Program Load operation.
34  */
35 static SPINAND_OP_VARIANTS(write_cache_variants,
36 		SPINAND_PROG_LOAD(true, 0, NULL, 0));
37 
38 static SPINAND_OP_VARIANTS(update_cache_variants,
39 		SPINAND_PROG_LOAD(false, 0, NULL, 0));
40 
tx58cxgxsxraix_ooblayout_ecc(struct mtd_info * mtd,int section,struct mtd_oob_region * region)41 static int tx58cxgxsxraix_ooblayout_ecc(struct mtd_info *mtd, int section,
42 					struct mtd_oob_region *region)
43 {
44 	if (section > 0)
45 		return -ERANGE;
46 
47 	region->offset = mtd->oobsize / 2;
48 	region->length = mtd->oobsize / 2;
49 
50 	return 0;
51 }
52 
tx58cxgxsxraix_ooblayout_free(struct mtd_info * mtd,int section,struct mtd_oob_region * region)53 static int tx58cxgxsxraix_ooblayout_free(struct mtd_info *mtd, int section,
54 					 struct mtd_oob_region *region)
55 {
56 	if (section > 0)
57 		return -ERANGE;
58 
59 	/* 2 bytes reserved for BBM */
60 	region->offset = 2;
61 	region->length = (mtd->oobsize / 2) - 2;
62 
63 	return 0;
64 }
65 
66 static const struct mtd_ooblayout_ops tx58cxgxsxraix_ooblayout = {
67 	.ecc = tx58cxgxsxraix_ooblayout_ecc,
68 	.free = tx58cxgxsxraix_ooblayout_free,
69 };
70 
tx58cxgxsxraix_ecc_get_status(struct spinand_device * spinand,u8 status)71 static int tx58cxgxsxraix_ecc_get_status(struct spinand_device *spinand,
72 					 u8 status)
73 {
74 	struct nand_device *nand = spinand_to_nand(spinand);
75 	u8 mbf = 0;
76 	struct spi_mem_op op = SPINAND_GET_FEATURE_OP(0x30, spinand->scratchbuf);
77 
78 	switch (status & STATUS_ECC_MASK) {
79 	case STATUS_ECC_NO_BITFLIPS:
80 		return 0;
81 
82 	case STATUS_ECC_UNCOR_ERROR:
83 		return -EBADMSG;
84 
85 	case STATUS_ECC_HAS_BITFLIPS:
86 	case TOSH_STATUS_ECC_HAS_BITFLIPS_T:
87 		/*
88 		 * Let's try to retrieve the real maximum number of bitflips
89 		 * in order to avoid forcing the wear-leveling layer to move
90 		 * data around if it's not necessary.
91 		 */
92 		if (spi_mem_exec_op(spinand->spimem, &op))
93 			return nanddev_get_ecc_conf(nand)->strength;
94 
95 		mbf = *(spinand->scratchbuf) >> 4;
96 
97 		if (WARN_ON(mbf > nanddev_get_ecc_conf(nand)->strength || !mbf))
98 			return nanddev_get_ecc_conf(nand)->strength;
99 
100 		return mbf;
101 
102 	default:
103 		break;
104 	}
105 
106 	return -EINVAL;
107 }
108 
109 static const struct spinand_info toshiba_spinand_table[] = {
110 	/* 3.3V 1Gb (1st generation) */
111 	SPINAND_INFO("TC58CVG0S3HRAIG",
112 		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xC2),
113 		     NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),
114 		     NAND_ECCREQ(8, 512),
115 		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
116 					      &write_cache_variants,
117 					      &update_cache_variants),
118 		     0,
119 		     SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout,
120 				     tx58cxgxsxraix_ecc_get_status)),
121 	/* 3.3V 2Gb (1st generation) */
122 	SPINAND_INFO("TC58CVG1S3HRAIG",
123 		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xCB),
124 		     NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1),
125 		     NAND_ECCREQ(8, 512),
126 		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
127 					      &write_cache_variants,
128 					      &update_cache_variants),
129 		     0,
130 		     SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout,
131 				     tx58cxgxsxraix_ecc_get_status)),
132 	/* 3.3V 4Gb (1st generation) */
133 	SPINAND_INFO("TC58CVG2S0HRAIG",
134 		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xCD),
135 		     NAND_MEMORG(1, 4096, 256, 64, 2048, 40, 1, 1, 1),
136 		     NAND_ECCREQ(8, 512),
137 		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
138 					      &write_cache_variants,
139 					      &update_cache_variants),
140 		     0,
141 		     SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout,
142 				     tx58cxgxsxraix_ecc_get_status)),
143 	/* 1.8V 1Gb (1st generation) */
144 	SPINAND_INFO("TC58CYG0S3HRAIG",
145 		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xB2),
146 		     NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),
147 		     NAND_ECCREQ(8, 512),
148 		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
149 					      &write_cache_variants,
150 					      &update_cache_variants),
151 		     0,
152 		     SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout,
153 				     tx58cxgxsxraix_ecc_get_status)),
154 	/* 1.8V 2Gb (1st generation) */
155 	SPINAND_INFO("TC58CYG1S3HRAIG",
156 		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xBB),
157 		     NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1),
158 		     NAND_ECCREQ(8, 512),
159 		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
160 					      &write_cache_variants,
161 					      &update_cache_variants),
162 		     0,
163 		     SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout,
164 				     tx58cxgxsxraix_ecc_get_status)),
165 	/* 1.8V 4Gb (1st generation) */
166 	SPINAND_INFO("TC58CYG2S0HRAIG",
167 		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xBD),
168 		     NAND_MEMORG(1, 4096, 256, 64, 2048, 40, 1, 1, 1),
169 		     NAND_ECCREQ(8, 512),
170 		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
171 					      &write_cache_variants,
172 					      &update_cache_variants),
173 		     0,
174 		     SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout,
175 				     tx58cxgxsxraix_ecc_get_status)),
176 
177 	/*
178 	 * 2nd generation serial nand has HOLD_D which is equivalent to
179 	 * QE_BIT.
180 	 */
181 	/* 3.3V 1Gb (2nd generation) */
182 	SPINAND_INFO("TC58CVG0S3HRAIJ",
183 		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xE2),
184 		     NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),
185 		     NAND_ECCREQ(8, 512),
186 		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
187 					      &write_cache_x4_variants,
188 					      &update_cache_x4_variants),
189 		     SPINAND_HAS_QE_BIT,
190 		     SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout,
191 				     tx58cxgxsxraix_ecc_get_status)),
192 	/* 3.3V 2Gb (2nd generation) */
193 	SPINAND_INFO("TC58CVG1S3HRAIJ",
194 		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xEB),
195 		     NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1),
196 		     NAND_ECCREQ(8, 512),
197 		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
198 					      &write_cache_x4_variants,
199 					      &update_cache_x4_variants),
200 		     SPINAND_HAS_QE_BIT,
201 		     SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout,
202 				     tx58cxgxsxraix_ecc_get_status)),
203 	/* 3.3V 4Gb (2nd generation) */
204 	SPINAND_INFO("TC58CVG2S0HRAIJ",
205 		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xED),
206 		     NAND_MEMORG(1, 4096, 256, 64, 2048, 40, 1, 1, 1),
207 		     NAND_ECCREQ(8, 512),
208 		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
209 					      &write_cache_x4_variants,
210 					      &update_cache_x4_variants),
211 		     SPINAND_HAS_QE_BIT,
212 		     SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout,
213 				     tx58cxgxsxraix_ecc_get_status)),
214 	/* 3.3V 8Gb (2nd generation) */
215 	SPINAND_INFO("TH58CVG3S0HRAIJ",
216 		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xE4),
217 		     NAND_MEMORG(1, 4096, 256, 64, 4096, 80, 1, 1, 1),
218 		     NAND_ECCREQ(8, 512),
219 		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
220 					      &write_cache_x4_variants,
221 					      &update_cache_x4_variants),
222 		     SPINAND_HAS_QE_BIT,
223 		     SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout,
224 				     tx58cxgxsxraix_ecc_get_status)),
225 	/* 1.8V 1Gb (2nd generation) */
226 	SPINAND_INFO("TC58CYG0S3HRAIJ",
227 		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xD2),
228 		     NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),
229 		     NAND_ECCREQ(8, 512),
230 		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
231 					      &write_cache_x4_variants,
232 					      &update_cache_x4_variants),
233 		     SPINAND_HAS_QE_BIT,
234 		     SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout,
235 				     tx58cxgxsxraix_ecc_get_status)),
236 	/* 1.8V 2Gb (2nd generation) */
237 	SPINAND_INFO("TC58CYG1S3HRAIJ",
238 		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xDB),
239 		     NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1),
240 		     NAND_ECCREQ(8, 512),
241 		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
242 					      &write_cache_x4_variants,
243 					      &update_cache_x4_variants),
244 		     SPINAND_HAS_QE_BIT,
245 		     SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout,
246 				     tx58cxgxsxraix_ecc_get_status)),
247 	/* 1.8V 4Gb (2nd generation) */
248 	SPINAND_INFO("TC58CYG2S0HRAIJ",
249 		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xDD),
250 		     NAND_MEMORG(1, 4096, 256, 64, 2048, 40, 1, 1, 1),
251 		     NAND_ECCREQ(8, 512),
252 		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
253 					      &write_cache_x4_variants,
254 					      &update_cache_x4_variants),
255 		     SPINAND_HAS_QE_BIT,
256 		     SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout,
257 				     tx58cxgxsxraix_ecc_get_status)),
258 	/* 1.8V 8Gb (2nd generation) */
259 	SPINAND_INFO("TH58CYG3S0HRAIJ",
260 		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xD4),
261 		     NAND_MEMORG(1, 4096, 256, 64, 4096, 80, 1, 1, 1),
262 		     NAND_ECCREQ(8, 512),
263 		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
264 					      &write_cache_x4_variants,
265 					      &update_cache_x4_variants),
266 		     SPINAND_HAS_QE_BIT,
267 		     SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout,
268 				     tx58cxgxsxraix_ecc_get_status)),
269 	/* 1.8V 1Gb (1st generation) */
270 	SPINAND_INFO("TC58NYG0S3HBAI4",
271 		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xA1),
272 		     NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),
273 		     NAND_ECCREQ(8, 512),
274 		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
275 					      &write_cache_variants,
276 					      &update_cache_variants),
277 		     0,
278 		     SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout,
279 				     tx58cxgxsxraix_ecc_get_status)),
280 	/* 1.8V 4Gb (1st generation) */
281 	SPINAND_INFO("TH58NYG2S3HBAI4",
282 		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xAC),
283 		     NAND_MEMORG(1, 2048, 128, 64, 4096, 80, 1, 2, 1),
284 		     NAND_ECCREQ(8, 512),
285 		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
286 					      &write_cache_x4_variants,
287 					      &update_cache_x4_variants),
288 		     SPINAND_HAS_QE_BIT,
289 		     SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout,
290 				     tx58cxgxsxraix_ecc_get_status)),
291 	/* 1.8V 8Gb (1st generation) */
292 	SPINAND_INFO("TH58NYG3S0HBAI6",
293 		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xA3),
294 		     NAND_MEMORG(1, 4096, 256, 64, 4096, 80, 1, 1, 1),
295 		     NAND_ECCREQ(8, 512),
296 		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
297 					      &write_cache_x4_variants,
298 					      &update_cache_x4_variants),
299 		     SPINAND_HAS_QE_BIT,
300 		     SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout,
301 				     tx58cxgxsxraix_ecc_get_status)),
302 };
303 
304 static const struct spinand_manufacturer_ops toshiba_spinand_manuf_ops = {
305 };
306 
307 const struct spinand_manufacturer toshiba_spinand_manufacturer = {
308 	.id = SPINAND_MFR_TOSHIBA,
309 	.name = "Toshiba",
310 	.chips = toshiba_spinand_table,
311 	.nchips = ARRAY_SIZE(toshiba_spinand_table),
312 	.ops = &toshiba_spinand_manuf_ops,
313 };
314