xref: /rk3399_rockchip-uboot/drivers/mtd/nand/spi/gigadevice.c (revision 4e0fa9f6a6afd1c4db979a3d2e9f1e67d6e1f06f)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (C) 2018 Stefan Roese <sr@denx.de>
4  *
5  * Derived from drivers/mtd/nand/spi/micron.c
6  *   Copyright (c) 2016-2017 Micron Technology, Inc.
7  */
8 
9 #ifndef __UBOOT__
10 #include <linux/device.h>
11 #include <linux/kernel.h>
12 #endif
13 #include <linux/mtd/spinand.h>
14 
15 #define SPINAND_MFR_GIGADEVICE			0xC8
16 #define GD5FXGQ4XA_STATUS_ECC_BELOW_BITFLIPS	(1 << 4)
17 #define GD5FXGQ4XA_STATUS_ECC_MAX_BITFLIPS	(3 << 4)
18 
19 #define GD5FXGQ4XEXXG_REG_STATUS2		0xf0
20 
21 static SPINAND_OP_VARIANTS(read_cache_variants,
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(write_cache_variants,
30 		SPINAND_PROG_LOAD_X4(true, 0, NULL, 0),
31 		SPINAND_PROG_LOAD(true, 0, NULL, 0));
32 
33 static SPINAND_OP_VARIANTS(update_cache_variants,
34 		SPINAND_PROG_LOAD_X4(false, 0, NULL, 0),
35 		SPINAND_PROG_LOAD(false, 0, NULL, 0));
36 
37 static int gd5fxgq4xexxg_ooblayout_ecc(struct mtd_info *mtd, int section,
38 				       struct mtd_oob_region *region)
39 {
40 	if (section)
41 		return -ERANGE;
42 
43 	region->offset = 64;
44 	region->length = 64;
45 
46 	return 0;
47 }
48 
49 static int gd5fxgq4xexxg_ooblayout_free(struct mtd_info *mtd, int section,
50 					struct mtd_oob_region *region)
51 {
52 	if (section)
53 		return -ERANGE;
54 
55 	/* Reserve 1 bytes for the BBM. */
56 	region->offset = 1;
57 	region->length = 63;
58 
59 	return 0;
60 }
61 
62 static int gd5f1gq4xexxg_ecc_get_status(struct spinand_device *spinand,
63 					u8 status)
64 {
65 	u8 status2;
66 	struct spi_mem_op op = SPINAND_GET_FEATURE_OP(GD5FXGQ4XEXXG_REG_STATUS2,
67 						      &status2);
68 	int ret;
69 
70 	switch (status & STATUS_ECC_MASK) {
71 	case STATUS_ECC_NO_BITFLIPS:
72 		return 0;
73 
74 	case GD5FXGQ4XA_STATUS_ECC_BELOW_BITFLIPS:
75 		/*
76 		 * Read status2 register to determine a more fine grained
77 		 * bit error status
78 		 */
79 		ret = spi_mem_exec_op(spinand->slave, &op);
80 		if (ret)
81 			return ret;
82 
83 		/*
84 		 * 4 ... 7 bits are flipped (1..4 can't be detected, so
85 		 * report the maximum of 4 in this case
86 		 */
87 		/* bits sorted this way (3...0): ECCS1,ECCS0,ECCSE1,ECCSE0 */
88 		return ((status & STATUS_ECC_MASK) >> 2) |
89 			((status2 & STATUS_ECC_MASK) >> 4);
90 
91 	case GD5FXGQ4XA_STATUS_ECC_MAX_BITFLIPS:
92 		return 8;
93 
94 	case STATUS_ECC_UNCOR_ERROR:
95 		return -EBADMSG;
96 
97 	default:
98 		break;
99 	}
100 
101 	return -EINVAL;
102 }
103 
104 static int gd5fxgq5xexxg_ecc_get_status(struct spinand_device *spinand,
105 					u8 status)
106 {
107 	u8 status2;
108 	struct spi_mem_op op = SPINAND_GET_FEATURE_OP(GD5FXGQ4XEXXG_REG_STATUS2,
109 						      &status2);
110 	int ret;
111 
112 	switch (status & STATUS_ECC_MASK) {
113 	case STATUS_ECC_NO_BITFLIPS:
114 		return 0;
115 
116 	case GD5FXGQ4XA_STATUS_ECC_BELOW_BITFLIPS:
117 		/*
118 		 * Read status2 register to determine a more fine grained
119 		 * bit error status
120 		 */
121 		ret = spi_mem_exec_op(spinand->slave, &op);
122 		if (ret)
123 			return ret;
124 
125 		/*
126 		 * 1 ... 4 bits are flipped (1..4 can't be detected, so
127 		 * report the maximum of 4 in this case
128 		 */
129 		/* bits sorted this way (3...0): ECCS1,ECCS0,ECCSE1,ECCSE0 */
130 		return (((status & STATUS_ECC_MASK) >> 2) |
131 			((status2 & STATUS_ECC_MASK) >> 4)) - 3;
132 
133 	case GD5FXGQ4XA_STATUS_ECC_MAX_BITFLIPS:
134 		return -EBADMSG;
135 
136 	case STATUS_ECC_UNCOR_ERROR:
137 		return -EBADMSG;
138 
139 	default:
140 		break;
141 	}
142 
143 	return -EINVAL;
144 }
145 
146 static const struct mtd_ooblayout_ops gd5fxgq4xexxg_ooblayout = {
147 	.ecc = gd5fxgq4xexxg_ooblayout_ecc,
148 	.rfree = gd5fxgq4xexxg_ooblayout_free,
149 };
150 
151 static int gd5fxgq4xexxh_ooblayout_ecc(struct mtd_info *mtd, int section,
152 				       struct mtd_oob_region *region)
153 {
154 	return -ERANGE;
155 }
156 
157 static int gd5fxgq4xexxh_ooblayout_free(struct mtd_info *mtd, int section,
158 					struct mtd_oob_region *region)
159 {
160 	if (section)
161 		return -ERANGE;
162 
163 	/* Reserve 1 bytes for the BBM. */
164 	region->offset = 1;
165 	region->length = 63;
166 
167 	return 0;
168 }
169 
170 static const struct mtd_ooblayout_ops gd5fxgq4xexxh_ooblayout = {
171 	.ecc = gd5fxgq4xexxh_ooblayout_ecc,
172 	.rfree = gd5fxgq4xexxh_ooblayout_free,
173 };
174 
175 static const struct spinand_info gigadevice_spinand_table[] = {
176 	SPINAND_INFO("GD5F1GQ4UExxG",
177 		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0xd1),
178 		     NAND_MEMORG(1, 2048, 128, 64, 1024, 1, 1, 1),
179 		     NAND_ECCREQ(8, 512),
180 		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
181 					      &write_cache_variants,
182 					      &update_cache_variants),
183 		     SPINAND_HAS_QE_BIT,
184 		     SPINAND_ECCINFO(&gd5fxgq4xexxg_ooblayout,
185 				     gd5f1gq4xexxg_ecc_get_status)),
186 	SPINAND_INFO("GD5F1GQ5UExxG",
187 		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0x51),
188 		     NAND_MEMORG(1, 2048, 128, 64, 1024, 1, 1, 1),
189 		     NAND_ECCREQ(4, 512),
190 		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
191 					      &write_cache_variants,
192 					      &update_cache_variants),
193 		     SPINAND_HAS_QE_BIT,
194 		     SPINAND_ECCINFO(&gd5fxgq4xexxg_ooblayout,
195 				     gd5fxgq5xexxg_ecc_get_status)),
196 	SPINAND_INFO("GD5F2GQ5UExxG",
197 		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0x52),
198 		     NAND_MEMORG(1, 2048, 128, 64, 2048, 1, 1, 1),
199 		     NAND_ECCREQ(4, 512),
200 		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
201 					      &write_cache_variants,
202 					      &update_cache_variants),
203 		     SPINAND_HAS_QE_BIT,
204 		     SPINAND_ECCINFO(&gd5fxgq4xexxg_ooblayout,
205 				     gd5fxgq5xexxg_ecc_get_status)),
206 	SPINAND_INFO("GD5F2GQ4UBxxG",
207 		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0xd2),
208 		     NAND_MEMORG(1, 2048, 128, 64, 2048, 1, 1, 1),
209 		     NAND_ECCREQ(8, 512),
210 		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
211 					      &write_cache_variants,
212 					      &update_cache_variants),
213 		     SPINAND_HAS_QE_BIT,
214 		     SPINAND_ECCINFO(&gd5fxgq4xexxg_ooblayout,
215 				     gd5f1gq4xexxg_ecc_get_status)),
216 	SPINAND_INFO("GD5F4GQ6UExxG",
217 		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0x55),
218 		     NAND_MEMORG(1, 2048, 128, 64, 4096, 1, 1, 1),
219 		     NAND_ECCREQ(4, 512),
220 		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
221 					      &write_cache_variants,
222 					      &update_cache_variants),
223 		     SPINAND_HAS_QE_BIT,
224 		     SPINAND_ECCINFO(&gd5fxgq4xexxg_ooblayout,
225 				     gd5fxgq5xexxg_ecc_get_status)),
226 	SPINAND_INFO("GD5F1GQ4UExxH",
227 		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0xd9),
228 		     NAND_MEMORG(1, 2048, 64, 64, 1024, 1, 1, 1),
229 		     NAND_ECCREQ(8, 512),
230 		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
231 					      &write_cache_variants,
232 					      &update_cache_variants),
233 		     SPINAND_HAS_QE_BIT,
234 		     SPINAND_ECCINFO(&gd5fxgq4xexxh_ooblayout,
235 				     gd5f1gq4xexxg_ecc_get_status)),
236 	SPINAND_INFO("GD5F1GQ5RExxG",
237 		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0x41),
238 		     NAND_MEMORG(1, 2048, 128, 64, 1024, 1, 1, 1),
239 		     NAND_ECCREQ(4, 512),
240 		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
241 					      &write_cache_variants,
242 					      &update_cache_variants),
243 		     SPINAND_HAS_QE_BIT,
244 		     SPINAND_ECCINFO(&gd5fxgq4xexxg_ooblayout,
245 				     gd5fxgq5xexxg_ecc_get_status)),
246 	SPINAND_INFO("GD5F2GQ5RExxG",
247 		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0x42),
248 		     NAND_MEMORG(1, 2048, 128, 64, 2048, 1, 1, 1),
249 		     NAND_ECCREQ(4, 512),
250 		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
251 					      &write_cache_variants,
252 					      &update_cache_variants),
253 		     SPINAND_HAS_QE_BIT,
254 		     SPINAND_ECCINFO(&gd5fxgq4xexxg_ooblayout,
255 				     gd5fxgq5xexxg_ecc_get_status)),
256 	SPINAND_INFO("GD5F2GM7RxG",
257 		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0x82),
258 		     NAND_MEMORG(1, 2048, 128, 64, 2048, 1, 1, 1),
259 		     NAND_ECCREQ(8, 512),
260 		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
261 					      &write_cache_variants,
262 					      &update_cache_variants),
263 		     SPINAND_HAS_QE_BIT,
264 		     SPINAND_ECCINFO(&gd5fxgq4xexxg_ooblayout,
265 				     gd5f1gq4xexxg_ecc_get_status)),
266 	SPINAND_INFO("GD5F2GM7UxG",
267 		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0x92),
268 		     NAND_MEMORG(1, 2048, 128, 64, 2048, 1, 1, 1),
269 		     NAND_ECCREQ(8, 512),
270 		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
271 					      &write_cache_variants,
272 					      &update_cache_variants),
273 		     SPINAND_HAS_QE_BIT,
274 		     SPINAND_ECCINFO(&gd5fxgq4xexxg_ooblayout,
275 				     gd5f1gq4xexxg_ecc_get_status)),
276 };
277 
278 static const struct spinand_manufacturer_ops gigadevice_spinand_manuf_ops = {
279 };
280 
281 const struct spinand_manufacturer gigadevice_spinand_manufacturer = {
282 	.id = SPINAND_MFR_GIGADEVICE,
283 	.name = "GigaDevice",
284 	.chips = gigadevice_spinand_table,
285 	.nchips = ARRAY_SIZE(gigadevice_spinand_table),
286 	.ops = &gigadevice_spinand_manuf_ops,
287 };
288