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
17#define GD5FXGQ4XA_STATUS_ECC_1_7_BITFLIPS	(1 << 4)
18#define GD5FXGQ4XA_STATUS_ECC_8_BITFLIPS	(3 << 4)
19
20#define GD5FXGQ5XE_STATUS_ECC_1_4_BITFLIPS	(1 << 4)
21#define GD5FXGQ5XE_STATUS_ECC_4_BITFLIPS	(3 << 4)
22
23#define GD5FXGQXXEXXG_REG_STATUS2		0xf0
24
25#define GD5FXGQ4UXFXXG_STATUS_ECC_MASK		(7 << 4)
26#define GD5FXGQ4UXFXXG_STATUS_ECC_NO_BITFLIPS	(0 << 4)
27#define GD5FXGQ4UXFXXG_STATUS_ECC_1_3_BITFLIPS	(1 << 4)
28#define GD5FXGQ4UXFXXG_STATUS_ECC_UNCOR_ERROR	(7 << 4)
29
30static SPINAND_OP_VARIANTS(read_cache_variants,
31		SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP(0, 1, NULL, 0),
32		SPINAND_PAGE_READ_FROM_CACHE_X4_OP(0, 1, NULL, 0),
33		SPINAND_PAGE_READ_FROM_CACHE_DUALIO_OP(0, 1, NULL, 0),
34		SPINAND_PAGE_READ_FROM_CACHE_X2_OP(0, 1, NULL, 0),
35		SPINAND_PAGE_READ_FROM_CACHE_OP(true, 0, 1, NULL, 0),
36		SPINAND_PAGE_READ_FROM_CACHE_OP(false, 0, 1, NULL, 0));
37
38static SPINAND_OP_VARIANTS(read_cache_variants_f,
39		SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP(0, 1, NULL, 0),
40		SPINAND_PAGE_READ_FROM_CACHE_X4_OP_3A(0, 1, NULL, 0),
41		SPINAND_PAGE_READ_FROM_CACHE_DUALIO_OP(0, 1, NULL, 0),
42		SPINAND_PAGE_READ_FROM_CACHE_X2_OP_3A(0, 1, NULL, 0),
43		SPINAND_PAGE_READ_FROM_CACHE_OP_3A(true, 0, 1, NULL, 0),
44		SPINAND_PAGE_READ_FROM_CACHE_OP_3A(false, 0, 0, NULL, 0));
45
46static SPINAND_OP_VARIANTS(write_cache_variants,
47		SPINAND_PROG_LOAD_X4(true, 0, NULL, 0),
48		SPINAND_PROG_LOAD(true, 0, NULL, 0));
49
50static SPINAND_OP_VARIANTS(update_cache_variants,
51		SPINAND_PROG_LOAD_X4(false, 0, NULL, 0),
52		SPINAND_PROG_LOAD(false, 0, NULL, 0));
53
54static int gd5fxgq4xa_ooblayout_ecc(struct mtd_info *mtd, int section,
55				  struct mtd_oob_region *region)
56{
57	if (section > 3)
58		return -ERANGE;
59
60	region->offset = (16 * section) + 8;
61	region->length = 8;
62
63	return 0;
64}
65
66static int gd5fxgq4xa_ooblayout_free(struct mtd_info *mtd, int section,
67				   struct mtd_oob_region *region)
68{
69	if (section > 3)
70		return -ERANGE;
71
72	if (section) {
73		region->offset = 16 * section;
74		region->length = 8;
75	} else {
76		/* section 0 has one byte reserved for bad block mark */
77		region->offset = 1;
78		region->length = 7;
79	}
80	return 0;
81}
82
83static const struct mtd_ooblayout_ops gd5fxgq4xa_ooblayout = {
84	.ecc = gd5fxgq4xa_ooblayout_ecc,
85	.rfree = gd5fxgq4xa_ooblayout_free,
86};
87
88static int gd5fxgq4xa_ecc_get_status(struct spinand_device *spinand,
89					 u8 status)
90{
91	switch (status & STATUS_ECC_MASK) {
92	case STATUS_ECC_NO_BITFLIPS:
93		return 0;
94
95	case GD5FXGQ4XA_STATUS_ECC_1_7_BITFLIPS:
96		/* 1-7 bits are flipped. return the maximum. */
97		return 7;
98
99	case GD5FXGQ4XA_STATUS_ECC_8_BITFLIPS:
100		return 8;
101
102	case STATUS_ECC_UNCOR_ERROR:
103		return -EBADMSG;
104
105	default:
106		break;
107	}
108
109	return -EINVAL;
110}
111
112static int gd5fxgqx_variant2_ooblayout_ecc(struct mtd_info *mtd, int section,
113				       struct mtd_oob_region *region)
114{
115	if (section)
116		return -ERANGE;
117
118	region->offset = 64;
119	region->length = 64;
120
121	return 0;
122}
123
124static int gd5fxgqx_variant2_ooblayout_free(struct mtd_info *mtd, int section,
125					struct mtd_oob_region *region)
126{
127	if (section)
128		return -ERANGE;
129
130	/* Reserve 1 bytes for the BBM. */
131	region->offset = 1;
132	region->length = 63;
133
134	return 0;
135}
136
137/* Valid for Q4/Q5 and Q6 (untested) devices */
138static const struct mtd_ooblayout_ops gd5fxgqx_variant2_ooblayout = {
139	.ecc = gd5fxgqx_variant2_ooblayout_ecc,
140	.rfree = gd5fxgqx_variant2_ooblayout_free,
141};
142
143static int gd5fxgq4xc_ooblayout_256_ecc(struct mtd_info *mtd, int section,
144					struct mtd_oob_region *oobregion)
145{
146	if (section)
147		return -ERANGE;
148
149	oobregion->offset = 128;
150	oobregion->length = 128;
151
152	return 0;
153}
154
155static int gd5fxgq4xc_ooblayout_256_free(struct mtd_info *mtd, int section,
156					 struct mtd_oob_region *oobregion)
157{
158	if (section)
159		return -ERANGE;
160
161	oobregion->offset = 1;
162	oobregion->length = 127;
163
164	return 0;
165}
166
167static const struct mtd_ooblayout_ops gd5fxgq4xc_oob_256_ops = {
168	.ecc = gd5fxgq4xc_ooblayout_256_ecc,
169	.rfree = gd5fxgq4xc_ooblayout_256_free,
170};
171
172static int gd5fxgq4uexxg_ecc_get_status(struct spinand_device *spinand,
173					u8 status)
174{
175	u8 status2;
176	struct spi_mem_op op = SPINAND_GET_FEATURE_OP(GD5FXGQXXEXXG_REG_STATUS2,
177						      &status2);
178	int ret;
179
180	switch (status & STATUS_ECC_MASK) {
181	case STATUS_ECC_NO_BITFLIPS:
182		return 0;
183
184	case GD5FXGQ4XA_STATUS_ECC_1_7_BITFLIPS:
185		/*
186		 * Read status2 register to determine a more fine grained
187		 * bit error status
188		 */
189		ret = spi_mem_exec_op(spinand->slave, &op);
190		if (ret)
191			return ret;
192
193		/*
194		 * 4 ... 7 bits are flipped (1..4 can't be detected, so
195		 * report the maximum of 4 in this case
196		 */
197		/* bits sorted this way (3...0): ECCS1,ECCS0,ECCSE1,ECCSE0 */
198		return ((status & STATUS_ECC_MASK) >> 2) |
199			((status2 & STATUS_ECC_MASK) >> 4);
200
201	case GD5FXGQ4XA_STATUS_ECC_8_BITFLIPS:
202		return 8;
203
204	case STATUS_ECC_UNCOR_ERROR:
205		return -EBADMSG;
206
207	default:
208		break;
209	}
210
211	return -EINVAL;
212}
213
214static int gd5fxgq5xexxg_ecc_get_status(struct spinand_device *spinand,
215					u8 status)
216{
217	u8 status2;
218	struct spi_mem_op op = SPINAND_GET_FEATURE_OP(GD5FXGQXXEXXG_REG_STATUS2,
219						      &status2);
220	int ret;
221
222	switch (status & STATUS_ECC_MASK) {
223	case STATUS_ECC_NO_BITFLIPS:
224		return 0;
225
226	case GD5FXGQ5XE_STATUS_ECC_1_4_BITFLIPS:
227		/*
228		 * Read status2 register to determine a more fine grained
229		 * bit error status
230		 */
231		ret = spi_mem_exec_op(spinand->slave, &op);
232		if (ret)
233			return ret;
234
235		/*
236		 * 1 ... 4 bits are flipped (and corrected)
237		 */
238		/* bits sorted this way (1...0): ECCSE1, ECCSE0 */
239		return ((status2 & STATUS_ECC_MASK) >> 4) + 1;
240
241	case STATUS_ECC_UNCOR_ERROR:
242		return -EBADMSG;
243
244	default:
245		break;
246	}
247
248	return -EINVAL;
249}
250
251static int gd5fxgq4ufxxg_ecc_get_status(struct spinand_device *spinand,
252					u8 status)
253{
254	switch (status & GD5FXGQ4UXFXXG_STATUS_ECC_MASK) {
255	case GD5FXGQ4UXFXXG_STATUS_ECC_NO_BITFLIPS:
256		return 0;
257
258	case GD5FXGQ4UXFXXG_STATUS_ECC_1_3_BITFLIPS:
259		return 3;
260
261	case GD5FXGQ4UXFXXG_STATUS_ECC_UNCOR_ERROR:
262		return -EBADMSG;
263
264	default: /* (2 << 4) through (6 << 4) are 4-8 corrected errors */
265		return ((status & GD5FXGQ4UXFXXG_STATUS_ECC_MASK) >> 4) + 2;
266	}
267
268	return -EINVAL;
269}
270
271static const struct spinand_info gigadevice_spinand_table[] = {
272	SPINAND_INFO("GD5F1GQ4xA",
273		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0xf1),
274		     NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1),
275		     NAND_ECCREQ(8, 512),
276		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
277					      &write_cache_variants,
278					      &update_cache_variants),
279		     SPINAND_HAS_QE_BIT,
280		     SPINAND_ECCINFO(&gd5fxgq4xa_ooblayout,
281				     gd5fxgq4xa_ecc_get_status)),
282	SPINAND_INFO("GD5F2GQ4xA",
283		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0xf2),
284		     NAND_MEMORG(1, 2048, 64, 64, 2048, 40, 1, 1, 1),
285		     NAND_ECCREQ(8, 512),
286		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
287					      &write_cache_variants,
288					      &update_cache_variants),
289		     SPINAND_HAS_QE_BIT,
290		     SPINAND_ECCINFO(&gd5fxgq4xa_ooblayout,
291				     gd5fxgq4xa_ecc_get_status)),
292	SPINAND_INFO("GD5F4GQ4xA",
293		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0xf4),
294		     NAND_MEMORG(1, 2048, 64, 64, 4096, 80, 1, 1, 1),
295		     NAND_ECCREQ(8, 512),
296		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
297					      &write_cache_variants,
298					      &update_cache_variants),
299		     SPINAND_HAS_QE_BIT,
300		     SPINAND_ECCINFO(&gd5fxgq4xa_ooblayout,
301				     gd5fxgq4xa_ecc_get_status)),
302	SPINAND_INFO("GD5F4GQ4RC",
303		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE, 0xa4, 0x68),
304		     NAND_MEMORG(1, 4096, 256, 64, 2048, 40, 1, 1, 1),
305		     NAND_ECCREQ(8, 512),
306		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants_f,
307					      &write_cache_variants,
308					      &update_cache_variants),
309		     SPINAND_HAS_QE_BIT,
310		     SPINAND_ECCINFO(&gd5fxgq4xc_oob_256_ops,
311				     gd5fxgq4ufxxg_ecc_get_status)),
312	SPINAND_INFO("GD5F4GQ4UC",
313		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE, 0xb4, 0x68),
314		     NAND_MEMORG(1, 4096, 256, 64, 2048, 40, 1, 1, 1),
315		     NAND_ECCREQ(8, 512),
316		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants_f,
317					      &write_cache_variants,
318					      &update_cache_variants),
319		     SPINAND_HAS_QE_BIT,
320		     SPINAND_ECCINFO(&gd5fxgq4xc_oob_256_ops,
321				     gd5fxgq4ufxxg_ecc_get_status)),
322	SPINAND_INFO("GD5F1GQ4UExxG",
323		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0xd1),
324		     NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),
325		     NAND_ECCREQ(8, 512),
326		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
327					      &write_cache_variants,
328					      &update_cache_variants),
329		     SPINAND_HAS_QE_BIT,
330		     SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
331				     gd5fxgq4uexxg_ecc_get_status)),
332	SPINAND_INFO("GD5F1GQ4UFxxG",
333		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE, 0xb1, 0x48),
334		     NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),
335		     NAND_ECCREQ(8, 512),
336		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants_f,
337					      &write_cache_variants,
338					      &update_cache_variants),
339		     SPINAND_HAS_QE_BIT,
340		     SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
341				     gd5fxgq4ufxxg_ecc_get_status)),
342	SPINAND_INFO("GD5F1GQ5UExxG",
343		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x51),
344		     NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),
345		     NAND_ECCREQ(4, 512),
346		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
347					      &write_cache_variants,
348					      &update_cache_variants),
349		     SPINAND_HAS_QE_BIT,
350		     SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
351				     gd5fxgq5xexxg_ecc_get_status)),
352};
353
354static const struct spinand_manufacturer_ops gigadevice_spinand_manuf_ops = {
355};
356
357const struct spinand_manufacturer gigadevice_spinand_manufacturer = {
358	.id = SPINAND_MFR_GIGADEVICE,
359	.name = "GigaDevice",
360	.chips = gigadevice_spinand_table,
361	.nchips = ARRAY_SIZE(gigadevice_spinand_table),
362	.ops = &gigadevice_spinand_manuf_ops,
363};
364