xref: /OK3568_Linux_fs/kernel/drivers/mtd/nand/spi/xtx.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (c) 2020 Rockchip Electronics Co., Ltd
4  *
5  * Authors:
6  *	Dingqiang Lin <jon.lin@rock-chips.com>
7  */
8 
9 #include <linux/device.h>
10 #include <linux/kernel.h>
11 #include <linux/mtd/spinand.h>
12 
13 #define SPINAND_MFR_XTX			0x0B
14 
15 static SPINAND_OP_VARIANTS(read_cache_variants,
16 		SPINAND_PAGE_READ_FROM_CACHE_X4_OP(0, 1, NULL, 0),
17 		SPINAND_PAGE_READ_FROM_CACHE_X2_OP(0, 1, NULL, 0),
18 		SPINAND_PAGE_READ_FROM_CACHE_OP(true, 0, 1, NULL, 0),
19 		SPINAND_PAGE_READ_FROM_CACHE_OP(false, 0, 1, NULL, 0));
20 
21 static SPINAND_OP_VARIANTS(write_cache_variants,
22 		SPINAND_PROG_LOAD_X4(true, 0, NULL, 0),
23 		SPINAND_PROG_LOAD(true, 0, NULL, 0));
24 
25 static SPINAND_OP_VARIANTS(update_cache_variants,
26 		SPINAND_PROG_LOAD_X4(false, 0, NULL, 0),
27 		SPINAND_PROG_LOAD(false, 0, NULL, 0));
28 
xt26g0xa_ooblayout_ecc(struct mtd_info * mtd,int section,struct mtd_oob_region * region)29 static int xt26g0xa_ooblayout_ecc(struct mtd_info *mtd, int section,
30 				  struct mtd_oob_region *region)
31 {
32 	if (section)
33 		return -ERANGE;
34 
35 	region->offset = 48;
36 	region->length = 16;
37 
38 	return 0;
39 }
40 
xt26g0xa_ooblayout_free(struct mtd_info * mtd,int section,struct mtd_oob_region * region)41 static int xt26g0xa_ooblayout_free(struct mtd_info *mtd, int section,
42 				   struct mtd_oob_region *region)
43 {
44 	if (section)
45 		return -ERANGE;
46 
47 	region->offset = 2;
48 	region->length = mtd->oobsize - 18;
49 
50 	return 0;
51 }
52 
53 static const struct mtd_ooblayout_ops xt26g0xa_ooblayout = {
54 	.ecc = xt26g0xa_ooblayout_ecc,
55 	.free = xt26g0xa_ooblayout_free,
56 };
57 
xt26g01b_ooblayout_ecc(struct mtd_info * mtd,int section,struct mtd_oob_region * region)58 static int xt26g01b_ooblayout_ecc(struct mtd_info *mtd, int section,
59 				  struct mtd_oob_region *region)
60 {
61 	return -ERANGE;
62 }
63 
xt26g01b_ooblayout_free(struct mtd_info * mtd,int section,struct mtd_oob_region * region)64 static int xt26g01b_ooblayout_free(struct mtd_info *mtd, int section,
65 				   struct mtd_oob_region *region)
66 {
67 	if (section)
68 		return -ERANGE;
69 
70 	region->offset = 2;
71 	region->length = mtd->oobsize - 2;
72 
73 	return 0;
74 }
75 
76 static const struct mtd_ooblayout_ops xt26g01b_ooblayout = {
77 	.ecc = xt26g01b_ooblayout_ecc,
78 	.free = xt26g01b_ooblayout_free,
79 };
80 
xt26g02b_ooblayout_ecc(struct mtd_info * mtd,int section,struct mtd_oob_region * region)81 static int xt26g02b_ooblayout_ecc(struct mtd_info *mtd, int section,
82 				  struct mtd_oob_region *region)
83 {
84 	if (section > 3)
85 		return -ERANGE;
86 
87 	region->offset = (16 * section) + 8;
88 	region->length = 8;
89 
90 	return 0;
91 }
92 
xt26g02b_ooblayout_free(struct mtd_info * mtd,int section,struct mtd_oob_region * region)93 static int xt26g02b_ooblayout_free(struct mtd_info *mtd, int section,
94 				   struct mtd_oob_region *region)
95 {
96 	if (section > 3)
97 		return -ERANGE;
98 
99 	region->offset = (16 * section) + 2;
100 	region->length = 6;
101 
102 	return 0;
103 }
104 
105 static const struct mtd_ooblayout_ops xt26g02b_ooblayout = {
106 	.ecc = xt26g02b_ooblayout_ecc,
107 	.free = xt26g02b_ooblayout_free,
108 };
109 
xt26g01c_ooblayout_ecc(struct mtd_info * mtd,int section,struct mtd_oob_region * region)110 static int xt26g01c_ooblayout_ecc(struct mtd_info *mtd, int section,
111 				  struct mtd_oob_region *region)
112 {
113 	if (section)
114 		return -ERANGE;
115 
116 	region->offset = mtd->oobsize / 2;
117 	region->length = mtd->oobsize / 2;
118 
119 	return 0;
120 }
121 
xt26g01c_ooblayout_free(struct mtd_info * mtd,int section,struct mtd_oob_region * region)122 static int xt26g01c_ooblayout_free(struct mtd_info *mtd, int section,
123 				   struct mtd_oob_region *region)
124 {
125 	if (section)
126 		return -ERANGE;
127 
128 	region->offset = 2;
129 	region->length = mtd->oobsize / 2 - 2;
130 
131 	return 0;
132 }
133 
134 static const struct mtd_ooblayout_ops xt26g01c_ooblayout = {
135 	.ecc = xt26g01c_ooblayout_ecc,
136 	.free = xt26g01c_ooblayout_free,
137 };
138 
139 /*
140  * ecc bits: 0xC0[2,5]
141  * [0x0000], No bit errors were detected;
142  * [0x0001, 0x0111], Bit errors were detected and corrected. Not
143  *	reach Flipping Bits;
144  * [0x1000], Multiple bit errors were detected and
145  *	not corrected.
146  * [0x1100], Bit error count equals the bit flip
147  *	detectionthreshold
148  * else, reserved
149  */
xt26g0xa_ecc_get_status(struct spinand_device * spinand,u8 status)150 static int xt26g0xa_ecc_get_status(struct spinand_device *spinand,
151 				   u8 status)
152 {
153 	u8 eccsr = (status & GENMASK(5, 2)) >> 2;
154 
155 	if (eccsr <= 7)
156 		return eccsr;
157 	else if (eccsr == 12)
158 		return 8;
159 	else
160 		return -EBADMSG;
161 }
162 
163 /*
164  * ecc bits: 0xC0[4,6]
165  * [0x0], No bit errors were detected;
166  * [0x001, 0x011], Bit errors were detected and corrected. Not
167  *	reach Flipping Bits;
168  * [0x100], Bit error count equals the bit flip
169  *	detectionthreshold
170  * [0x101, 0x110], Reserved;
171  * [0x111], Multiple bit errors were detected and
172  *	not corrected.
173  */
xt26g02b_ecc_get_status(struct spinand_device * spinand,u8 status)174 static int xt26g02b_ecc_get_status(struct spinand_device *spinand,
175 				   u8 status)
176 {
177 	u8 eccsr = (status & GENMASK(6, 4)) >> 4;
178 
179 	if (eccsr <= 4)
180 		return eccsr;
181 	else
182 		return -EBADMSG;
183 }
184 
185 /*
186  * ecc bits: 0xC0[4,7]
187  * [0b0000], No bit errors were detected;
188  * [0b0001, 0b0111], 1-7 Bit errors were detected and corrected. Not
189  *	reach Flipping Bits;
190  * [0b1000], 8 Bit errors were detected and corrected. Bit error count
191  *	equals the bit flip detectionthreshold;
192  * [0b1111], Bit errors greater than ECC capability(8 bits) and not corrected;
193  * others, Reserved.
194  */
xt26g01c_ecc_get_status(struct spinand_device * spinand,u8 status)195 static int xt26g01c_ecc_get_status(struct spinand_device *spinand,
196 				   u8 status)
197 {
198 	u8 eccsr = (status & GENMASK(7, 4)) >> 4;
199 
200 	if (eccsr <= 8)
201 		return eccsr;
202 	else
203 		return -EBADMSG;
204 }
205 
206 static const struct spinand_info xtx_spinand_table[] = {
207 	SPINAND_INFO("XT26G01A",
208 		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0xE1),
209 		     NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1),
210 		     NAND_ECCREQ(8, 512),
211 		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
212 					      &write_cache_variants,
213 					      &update_cache_variants),
214 		     SPINAND_HAS_QE_BIT,
215 		     SPINAND_ECCINFO(&xt26g0xa_ooblayout,
216 				     xt26g0xa_ecc_get_status)),
217 	SPINAND_INFO("XT26G02A",
218 		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0xE2),
219 		     NAND_MEMORG(1, 2048, 64, 64, 2048, 40, 1, 1, 1),
220 		     NAND_ECCREQ(8, 512),
221 		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
222 					      &write_cache_variants,
223 					      &update_cache_variants),
224 		     SPINAND_HAS_QE_BIT,
225 		     SPINAND_ECCINFO(&xt26g0xa_ooblayout,
226 				     xt26g0xa_ecc_get_status)),
227 	SPINAND_INFO("XT26G04A",
228 		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0xE3),
229 		     NAND_MEMORG(1, 2048, 64, 128, 2048, 80, 1, 1, 1),
230 		     NAND_ECCREQ(8, 512),
231 		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
232 					      &write_cache_variants,
233 					      &update_cache_variants),
234 		     SPINAND_HAS_QE_BIT,
235 		     SPINAND_ECCINFO(&xt26g0xa_ooblayout,
236 				     xt26g0xa_ecc_get_status)),
237 	SPINAND_INFO("XT26G01B",
238 		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0xF1),
239 		     NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1),
240 		     NAND_ECCREQ(8, 512),
241 		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
242 					      &write_cache_variants,
243 					      &update_cache_variants),
244 		     SPINAND_HAS_QE_BIT,
245 		     SPINAND_ECCINFO(&xt26g01b_ooblayout,
246 				     xt26g0xa_ecc_get_status)),
247 	SPINAND_INFO("XT26G02B",
248 		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0xF2),
249 		     NAND_MEMORG(1, 2048, 64, 64, 2048, 40, 1, 1, 1),
250 		     NAND_ECCREQ(4, 512),
251 		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
252 					      &write_cache_variants,
253 					      &update_cache_variants),
254 		     SPINAND_HAS_QE_BIT,
255 		     SPINAND_ECCINFO(&xt26g02b_ooblayout,
256 				     xt26g02b_ecc_get_status)),
257 	SPINAND_INFO("XT26G01C",
258 		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0x11),
259 		     NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),
260 		     NAND_ECCREQ(8, 512),
261 		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
262 					      &write_cache_variants,
263 					      &update_cache_variants),
264 		     SPINAND_HAS_QE_BIT,
265 		     SPINAND_ECCINFO(&xt26g01c_ooblayout,
266 				     xt26g01c_ecc_get_status)),
267 	SPINAND_INFO("XT26G02C",
268 		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0x12),
269 		     NAND_MEMORG(1, 2048, 64, 64, 2048, 40, 1, 1, 1),
270 		     NAND_ECCREQ(8, 512),
271 		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
272 					      &write_cache_variants,
273 					      &update_cache_variants),
274 		     SPINAND_HAS_QE_BIT,
275 		     SPINAND_ECCINFO(&xt26g0xa_ooblayout,
276 				     xt26g01c_ecc_get_status)),
277 	SPINAND_INFO("XT26G04C",
278 		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0x13),
279 		     NAND_MEMORG(1, 4096, 256, 64, 2048, 80, 1, 1, 1),
280 		     NAND_ECCREQ(8, 512),
281 		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
282 					      &write_cache_variants,
283 					      &update_cache_variants),
284 		     SPINAND_HAS_QE_BIT,
285 		     SPINAND_ECCINFO(&xt26g01c_ooblayout,
286 				     xt26g01c_ecc_get_status)),
287 	SPINAND_INFO("XT26G11C",
288 		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0x15),
289 		     NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),
290 		     NAND_ECCREQ(8, 512),
291 		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
292 					      &write_cache_variants,
293 					      &update_cache_variants),
294 		     SPINAND_HAS_QE_BIT,
295 		     SPINAND_ECCINFO(&xt26g01c_ooblayout,
296 				     xt26g01c_ecc_get_status)),
297 };
298 
299 static const struct spinand_manufacturer_ops xtx_spinand_manuf_ops = {
300 };
301 
302 const struct spinand_manufacturer xtx_spinand_manufacturer = {
303 	.id = SPINAND_MFR_XTX,
304 	.name = "xtx",
305 	.chips = xtx_spinand_table,
306 	.nchips = ARRAY_SIZE(xtx_spinand_table),
307 	.ops = &xtx_spinand_manuf_ops,
308 };
309