xref: /linux/drivers/mtd/nand/spi/winbond.c (revision 3f75bfff44be0646580fe4efda45d646f9c1693b)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (c) 2017 exceet electronics GmbH
4  *
5  * Authors:
6  *	Frieder Schrempf <frieder.schrempf@exceet.de>
7  *	Boris Brezillon <boris.brezillon@bootlin.com>
8  */
9 
10 #include <linux/device.h>
11 #include <linux/kernel.h>
12 #include <linux/mtd/spinand.h>
13 #include <linux/units.h>
14 
15 #define SPINAND_MFR_WINBOND		0xEF
16 
17 #define WINBOND_CFG_BUF_READ		BIT(3)
18 
19 #define W25N04KV_STATUS_ECC_5_8_BITFLIPS	(3 << 4)
20 
21 /*
22  * "X2" in the core is equivalent to "dual output" in the datasheets,
23  * "X4" in the core is equivalent to "quad output" in the datasheets.
24  */
25 
26 static SPINAND_OP_VARIANTS(read_cache_octal_variants,
27 		SPINAND_PAGE_READ_FROM_CACHE_1S_1D_8D_OP(0, 2, NULL, 0, 105 * HZ_PER_MHZ),
28 		SPINAND_PAGE_READ_FROM_CACHE_1S_8S_8S_OP(0, 16, NULL, 0, 162 * HZ_PER_MHZ),
29 		SPINAND_PAGE_READ_FROM_CACHE_1S_1S_8S_OP(0, 1, NULL, 0, 133 * HZ_PER_MHZ),
30 		SPINAND_PAGE_READ_FROM_CACHE_FAST_1S_1S_1S_OP(0, 1, NULL, 0),
31 		SPINAND_PAGE_READ_FROM_CACHE_1S_1S_1S_OP(0, 1, NULL, 0));
32 
33 static SPINAND_OP_VARIANTS(write_cache_octal_variants,
34 		SPINAND_PROG_LOAD_1S_8S_8S_OP(true, 0, NULL, 0),
35 		SPINAND_PROG_LOAD_1S_1S_8S_OP(0, NULL, 0),
36 		SPINAND_PROG_LOAD_1S_1S_1S_OP(true, 0, NULL, 0));
37 
38 static SPINAND_OP_VARIANTS(update_cache_octal_variants,
39 		SPINAND_PROG_LOAD_1S_8S_8S_OP(false, 0, NULL, 0),
40 		SPINAND_PROG_LOAD_1S_1S_1S_OP(false, 0, NULL, 0));
41 
42 static SPINAND_OP_VARIANTS(read_cache_dual_quad_dtr_variants,
43 		SPINAND_PAGE_READ_FROM_CACHE_1S_4D_4D_OP(0, 8, NULL, 0, 80 * HZ_PER_MHZ),
44 		SPINAND_PAGE_READ_FROM_CACHE_1S_1D_4D_OP(0, 2, NULL, 0, 80 * HZ_PER_MHZ),
45 		SPINAND_PAGE_READ_FROM_CACHE_1S_4S_4S_OP(0, 2, NULL, 0, 104 * HZ_PER_MHZ),
46 		SPINAND_PAGE_READ_FROM_CACHE_1S_1S_4S_OP(0, 1, NULL, 0),
47 		SPINAND_PAGE_READ_FROM_CACHE_1S_2D_2D_OP(0, 4, NULL, 0, 80 * HZ_PER_MHZ),
48 		SPINAND_PAGE_READ_FROM_CACHE_1S_1D_2D_OP(0, 2, NULL, 0, 80 * HZ_PER_MHZ),
49 		SPINAND_PAGE_READ_FROM_CACHE_1S_2S_2S_OP(0, 1, NULL, 0, 104 * HZ_PER_MHZ),
50 		SPINAND_PAGE_READ_FROM_CACHE_1S_1S_2S_OP(0, 1, NULL, 0),
51 		SPINAND_PAGE_READ_FROM_CACHE_1S_1D_1D_OP(0, 2, NULL, 0, 80 * HZ_PER_MHZ),
52 		SPINAND_PAGE_READ_FROM_CACHE_FAST_1S_1S_1S_OP(0, 1, NULL, 0),
53 		SPINAND_PAGE_READ_FROM_CACHE_1S_1S_1S_OP(0, 1, NULL, 0, 54 * HZ_PER_MHZ));
54 
55 static SPINAND_OP_VARIANTS(read_cache_variants,
56 		SPINAND_PAGE_READ_FROM_CACHE_1S_4S_4S_OP(0, 2, NULL, 0),
57 		SPINAND_PAGE_READ_FROM_CACHE_1S_1S_4S_OP(0, 1, NULL, 0),
58 		SPINAND_PAGE_READ_FROM_CACHE_1S_2S_2S_OP(0, 1, NULL, 0),
59 		SPINAND_PAGE_READ_FROM_CACHE_1S_1S_2S_OP(0, 1, NULL, 0),
60 		SPINAND_PAGE_READ_FROM_CACHE_FAST_1S_1S_1S_OP(0, 1, NULL, 0),
61 		SPINAND_PAGE_READ_FROM_CACHE_1S_1S_1S_OP(0, 1, NULL, 0));
62 
63 static SPINAND_OP_VARIANTS(write_cache_variants,
64 		SPINAND_PROG_LOAD_1S_1S_4S_OP(true, 0, NULL, 0),
65 		SPINAND_PROG_LOAD_1S_1S_1S_OP(true, 0, NULL, 0));
66 
67 static SPINAND_OP_VARIANTS(update_cache_variants,
68 		SPINAND_PROG_LOAD_1S_1S_4S_OP(false, 0, NULL, 0),
69 		SPINAND_PROG_LOAD_1S_1S_1S_OP(false, 0, NULL, 0));
70 
w25m02gv_ooblayout_ecc(struct mtd_info * mtd,int section,struct mtd_oob_region * region)71 static int w25m02gv_ooblayout_ecc(struct mtd_info *mtd, int section,
72 				  struct mtd_oob_region *region)
73 {
74 	if (section > 3)
75 		return -ERANGE;
76 
77 	region->offset = (16 * section) + 8;
78 	region->length = 8;
79 
80 	return 0;
81 }
82 
w25m02gv_ooblayout_free(struct mtd_info * mtd,int section,struct mtd_oob_region * region)83 static int w25m02gv_ooblayout_free(struct mtd_info *mtd, int section,
84 				   struct mtd_oob_region *region)
85 {
86 	if (section > 3)
87 		return -ERANGE;
88 
89 	region->offset = (16 * section) + 2;
90 	region->length = 6;
91 
92 	return 0;
93 }
94 
95 static const struct mtd_ooblayout_ops w25m02gv_ooblayout = {
96 	.ecc = w25m02gv_ooblayout_ecc,
97 	.free = w25m02gv_ooblayout_free,
98 };
99 
w25m02gv_select_target(struct spinand_device * spinand,unsigned int target)100 static int w25m02gv_select_target(struct spinand_device *spinand,
101 				  unsigned int target)
102 {
103 	struct spi_mem_op op = SPI_MEM_OP(SPI_MEM_OP_CMD(0xc2, 1),
104 					  SPI_MEM_OP_NO_ADDR,
105 					  SPI_MEM_OP_NO_DUMMY,
106 					  SPI_MEM_OP_DATA_OUT(1,
107 							spinand->scratchbuf,
108 							1));
109 
110 	*spinand->scratchbuf = target;
111 	return spi_mem_exec_op(spinand->spimem, &op);
112 }
113 
w25n01kv_ooblayout_ecc(struct mtd_info * mtd,int section,struct mtd_oob_region * region)114 static int w25n01kv_ooblayout_ecc(struct mtd_info *mtd, int section,
115 				  struct mtd_oob_region *region)
116 {
117 	if (section > 3)
118 		return -ERANGE;
119 
120 	region->offset = 64 + (8 * section);
121 	region->length = 7;
122 
123 	return 0;
124 }
125 
w25n02kv_ooblayout_ecc(struct mtd_info * mtd,int section,struct mtd_oob_region * region)126 static int w25n02kv_ooblayout_ecc(struct mtd_info *mtd, int section,
127 				  struct mtd_oob_region *region)
128 {
129 	if (section > 3)
130 		return -ERANGE;
131 
132 	region->offset = 64 + (16 * section);
133 	region->length = 13;
134 
135 	return 0;
136 }
137 
w25n02kv_ooblayout_free(struct mtd_info * mtd,int section,struct mtd_oob_region * region)138 static int w25n02kv_ooblayout_free(struct mtd_info *mtd, int section,
139 				   struct mtd_oob_region *region)
140 {
141 	if (section > 3)
142 		return -ERANGE;
143 
144 	region->offset = (16 * section) + 2;
145 	region->length = 14;
146 
147 	return 0;
148 }
149 
150 static const struct mtd_ooblayout_ops w25n01kv_ooblayout = {
151 	.ecc = w25n01kv_ooblayout_ecc,
152 	.free = w25n02kv_ooblayout_free,
153 };
154 
155 static const struct mtd_ooblayout_ops w25n02kv_ooblayout = {
156 	.ecc = w25n02kv_ooblayout_ecc,
157 	.free = w25n02kv_ooblayout_free,
158 };
159 
w35n01jw_ooblayout_ecc(struct mtd_info * mtd,int section,struct mtd_oob_region * region)160 static int w35n01jw_ooblayout_ecc(struct mtd_info *mtd, int section,
161 				  struct mtd_oob_region *region)
162 {
163 	if (section > 7)
164 		return -ERANGE;
165 
166 	region->offset = (16 * section) + 12;
167 	region->length = 4;
168 
169 	return 0;
170 }
171 
w35n01jw_ooblayout_free(struct mtd_info * mtd,int section,struct mtd_oob_region * region)172 static int w35n01jw_ooblayout_free(struct mtd_info *mtd, int section,
173 				   struct mtd_oob_region *region)
174 {
175 	if (section > 7)
176 		return -ERANGE;
177 
178 	region->offset = 16 * section;
179 	region->length = 12;
180 
181 	/* Extract BBM */
182 	if (!section) {
183 		region->offset += 2;
184 		region->length -= 2;
185 	}
186 
187 	return 0;
188 }
189 
190 static const struct mtd_ooblayout_ops w35n01jw_ooblayout = {
191 	.ecc = w35n01jw_ooblayout_ecc,
192 	.free = w35n01jw_ooblayout_free,
193 };
194 
w25n02kv_ecc_get_status(struct spinand_device * spinand,u8 status)195 static int w25n02kv_ecc_get_status(struct spinand_device *spinand,
196 				   u8 status)
197 {
198 	struct nand_device *nand = spinand_to_nand(spinand);
199 	u8 mbf = 0;
200 	struct spi_mem_op op = SPINAND_GET_FEATURE_1S_1S_1S_OP(0x30, spinand->scratchbuf);
201 
202 	switch (status & STATUS_ECC_MASK) {
203 	case STATUS_ECC_NO_BITFLIPS:
204 		return 0;
205 
206 	case STATUS_ECC_UNCOR_ERROR:
207 		return -EBADMSG;
208 
209 	case STATUS_ECC_HAS_BITFLIPS:
210 	case W25N04KV_STATUS_ECC_5_8_BITFLIPS:
211 		/*
212 		 * Let's try to retrieve the real maximum number of bitflips
213 		 * in order to avoid forcing the wear-leveling layer to move
214 		 * data around if it's not necessary.
215 		 */
216 		if (spi_mem_exec_op(spinand->spimem, &op))
217 			return nanddev_get_ecc_conf(nand)->strength;
218 
219 		mbf = *(spinand->scratchbuf) >> 4;
220 
221 		if (WARN_ON(mbf > nanddev_get_ecc_conf(nand)->strength || !mbf))
222 			return nanddev_get_ecc_conf(nand)->strength;
223 
224 		return mbf;
225 
226 	default:
227 		break;
228 	}
229 
230 	return -EINVAL;
231 }
232 
233 static const struct spinand_info winbond_spinand_table[] = {
234 	/* 512M-bit densities */
235 	SPINAND_INFO("W25N512GW", /* 1.8V */
236 		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xba, 0x20),
237 		     NAND_MEMORG(1, 2048, 64, 64, 512, 10, 1, 1, 1),
238 		     NAND_ECCREQ(1, 512),
239 		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
240 					      &write_cache_variants,
241 					      &update_cache_variants),
242 		     0,
243 		     SPINAND_ECCINFO(&w25m02gv_ooblayout, NULL)),
244 	/* 1G-bit densities */
245 	SPINAND_INFO("W25N01GV", /* 3.3V */
246 		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xaa, 0x21),
247 		     NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1),
248 		     NAND_ECCREQ(1, 512),
249 		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
250 					      &write_cache_variants,
251 					      &update_cache_variants),
252 		     0,
253 		     SPINAND_ECCINFO(&w25m02gv_ooblayout, NULL)),
254 	SPINAND_INFO("W25N01GW", /* 1.8V */
255 		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xba, 0x21),
256 		     NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1),
257 		     NAND_ECCREQ(1, 512),
258 		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
259 					      &write_cache_variants,
260 					      &update_cache_variants),
261 		     0,
262 		     SPINAND_ECCINFO(&w25m02gv_ooblayout, NULL)),
263 	SPINAND_INFO("W25N01JW", /* high-speed 1.8V */
264 		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xbc, 0x21),
265 		     NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1),
266 		     NAND_ECCREQ(1, 512),
267 		     SPINAND_INFO_OP_VARIANTS(&read_cache_dual_quad_dtr_variants,
268 					      &write_cache_variants,
269 					      &update_cache_variants),
270 		     0,
271 		     SPINAND_ECCINFO(&w25m02gv_ooblayout, NULL)),
272 	SPINAND_INFO("W25N01KV", /* 3.3V */
273 		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xae, 0x21),
274 		     NAND_MEMORG(1, 2048, 96, 64, 1024, 20, 1, 1, 1),
275 		     NAND_ECCREQ(4, 512),
276 		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
277 					      &write_cache_variants,
278 					      &update_cache_variants),
279 		     0,
280 		     SPINAND_ECCINFO(&w25n01kv_ooblayout, w25n02kv_ecc_get_status)),
281 	SPINAND_INFO("W35N01JW", /* 1.8V */
282 		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xdc, 0x21),
283 		     NAND_MEMORG(1, 4096, 128, 64, 512, 10, 1, 1, 1),
284 		     NAND_ECCREQ(1, 512),
285 		     SPINAND_INFO_OP_VARIANTS(&read_cache_octal_variants,
286 					      &write_cache_octal_variants,
287 					      &update_cache_octal_variants),
288 		     0,
289 		     SPINAND_ECCINFO(&w35n01jw_ooblayout, NULL)),
290 	SPINAND_INFO("W35N02JW", /* 1.8V */
291 		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xdf, 0x22),
292 		     NAND_MEMORG(1, 4096, 128, 64, 512, 10, 1, 2, 1),
293 		     NAND_ECCREQ(1, 512),
294 		     SPINAND_INFO_OP_VARIANTS(&read_cache_octal_variants,
295 					      &write_cache_octal_variants,
296 					      &update_cache_octal_variants),
297 		     0,
298 		     SPINAND_ECCINFO(&w35n01jw_ooblayout, NULL)),
299 	SPINAND_INFO("W35N04JW", /* 1.8V */
300 		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xdf, 0x23),
301 		     NAND_MEMORG(1, 4096, 128, 64, 512, 10, 1, 4, 1),
302 		     NAND_ECCREQ(1, 512),
303 		     SPINAND_INFO_OP_VARIANTS(&read_cache_octal_variants,
304 					      &write_cache_octal_variants,
305 					      &update_cache_octal_variants),
306 		     0,
307 		     SPINAND_ECCINFO(&w35n01jw_ooblayout, NULL)),
308 	/* 2G-bit densities */
309 	SPINAND_INFO("W25M02GV", /* 2x1G-bit 3.3V */
310 		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xab, 0x21),
311 		     NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 2),
312 		     NAND_ECCREQ(1, 512),
313 		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
314 					      &write_cache_variants,
315 					      &update_cache_variants),
316 		     0,
317 		     SPINAND_ECCINFO(&w25m02gv_ooblayout, NULL),
318 		     SPINAND_SELECT_TARGET(w25m02gv_select_target)),
319 	SPINAND_INFO("W25N02JW", /* high-speed 1.8V */
320 		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xbf, 0x22),
321 		     NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 2, 1),
322 		     NAND_ECCREQ(1, 512),
323 		     SPINAND_INFO_OP_VARIANTS(&read_cache_dual_quad_dtr_variants,
324 					      &write_cache_variants,
325 					      &update_cache_variants),
326 		     0,
327 		     SPINAND_ECCINFO(&w25m02gv_ooblayout, NULL)),
328 	SPINAND_INFO("W25N02KV", /* 3.3V */
329 		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xaa, 0x22),
330 		     NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1),
331 		     NAND_ECCREQ(8, 512),
332 		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
333 					      &write_cache_variants,
334 					      &update_cache_variants),
335 		     0,
336 		     SPINAND_ECCINFO(&w25n02kv_ooblayout, w25n02kv_ecc_get_status)),
337 	SPINAND_INFO("W25N02KW", /* 1.8V */
338 		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xba, 0x22),
339 		     NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1),
340 		     NAND_ECCREQ(8, 512),
341 		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
342 					      &write_cache_variants,
343 					      &update_cache_variants),
344 		     0,
345 		     SPINAND_ECCINFO(&w25n02kv_ooblayout, w25n02kv_ecc_get_status)),
346 	/* 4G-bit densities */
347 	SPINAND_INFO("W25N04KV", /* 3.3V */
348 		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xaa, 0x23),
349 		     NAND_MEMORG(1, 2048, 128, 64, 4096, 40, 2, 1, 1),
350 		     NAND_ECCREQ(8, 512),
351 		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
352 					      &write_cache_variants,
353 					      &update_cache_variants),
354 		     0,
355 		     SPINAND_ECCINFO(&w25n02kv_ooblayout, w25n02kv_ecc_get_status)),
356 	SPINAND_INFO("W25N04KW", /* 1.8V */
357 		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xba, 0x23),
358 		     NAND_MEMORG(1, 2048, 128, 64, 4096, 40, 1, 1, 1),
359 		     NAND_ECCREQ(8, 512),
360 		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
361 					      &write_cache_variants,
362 					      &update_cache_variants),
363 		     0,
364 		     SPINAND_ECCINFO(&w25n02kv_ooblayout, w25n02kv_ecc_get_status)),
365 };
366 
winbond_spinand_init(struct spinand_device * spinand)367 static int winbond_spinand_init(struct spinand_device *spinand)
368 {
369 	struct nand_device *nand = spinand_to_nand(spinand);
370 	unsigned int i;
371 
372 	/*
373 	 * Make sure all dies are in buffer read mode and not continuous read
374 	 * mode.
375 	 */
376 	for (i = 0; i < nand->memorg.ntargets; i++) {
377 		spinand_select_target(spinand, i);
378 		spinand_upd_cfg(spinand, WINBOND_CFG_BUF_READ,
379 				WINBOND_CFG_BUF_READ);
380 	}
381 
382 	return 0;
383 }
384 
385 static const struct spinand_manufacturer_ops winbond_spinand_manuf_ops = {
386 	.init = winbond_spinand_init,
387 };
388 
389 const struct spinand_manufacturer winbond_spinand_manufacturer = {
390 	.id = SPINAND_MFR_WINBOND,
391 	.name = "Winbond",
392 	.chips = winbond_spinand_table,
393 	.nchips = ARRAY_SIZE(winbond_spinand_table),
394 	.ops = &winbond_spinand_manuf_ops,
395 };
396