File Index
Files and directories
Sign in
FILE

gigadevice.c

File preview with syntax highlighting.

linux-6.19.14/drivers/mtd/nand/spi/gigadevice.c C
  1// SPDX-License-Identifier: GPL-2.0
  2/*
  3 * Author:
  4 *	Chuanhong Guo <gch981213@gmail.com>
  5 */
  6
  7#include <linux/bitfield.h>
  8#include <linux/device.h>
  9#include <linux/kernel.h>
 10#include <linux/mtd/spinand.h>
 11
 12#define SPINAND_MFR_GIGADEVICE			0xC8
 13
 14#define GD5FXGQ4XA_STATUS_ECC_1_7_BITFLIPS	(1 << 4)
 15#define GD5FXGQ4XA_STATUS_ECC_8_BITFLIPS	(3 << 4)
 16
 17#define GD5FXGQ5XE_STATUS_ECC_1_4_BITFLIPS	(1 << 4)
 18#define GD5FXGQ5XE_STATUS_ECC_4_BITFLIPS	(3 << 4)
 19
 20#define GD5FXGQXXEXXG_REG_STATUS2		0xf0
 21
 22#define GD5FXGQ4UXFXXG_STATUS_ECC_MASK		(7 << 4)
 23#define GD5FXGQ4UXFXXG_STATUS_ECC_NO_BITFLIPS	(0 << 4)
 24#define GD5FXGQ4UXFXXG_STATUS_ECC_1_3_BITFLIPS	(1 << 4)
 25#define GD5FXGQ4UXFXXG_STATUS_ECC_UNCOR_ERROR	(7 << 4)
 26
 27/* Feature bit definitions */
 28#define GD_FEATURE_NR	BIT(3)	/* Normal Read(1=normal,0=continuous) */
 29#define GD_FEATURE_CRDC	BIT(2)	/* Continuous Read Dummy */
 30
 31/* ECC status extraction helpers */
 32#define GD_ECCSR_LAST_PAGE(eccsr)	FIELD_GET(GENMASK(3, 0), eccsr)
 33#define GD_ECCSR_ACCUMULATED(eccsr)	FIELD_GET(GENMASK(7, 4), eccsr)
 34
 35struct gigadevice_priv {
 36	bool continuous_read;
 37};
 38
 39static SPINAND_OP_VARIANTS(read_cache_variants,
 40		SPINAND_PAGE_READ_FROM_CACHE_1S_4S_4S_OP(0, 1, NULL, 0, 0),
 41		SPINAND_PAGE_READ_FROM_CACHE_1S_1S_4S_OP(0, 1, NULL, 0, 0),
 42		SPINAND_PAGE_READ_FROM_CACHE_1S_2S_2S_OP(0, 1, NULL, 0, 0),
 43		SPINAND_PAGE_READ_FROM_CACHE_1S_1S_2S_OP(0, 1, NULL, 0, 0),
 44		SPINAND_PAGE_READ_FROM_CACHE_FAST_1S_1S_1S_OP(0, 1, NULL, 0, 0),
 45		SPINAND_PAGE_READ_FROM_CACHE_1S_1S_1S_OP(0, 1, NULL, 0, 0));
 46
 47static SPINAND_OP_VARIANTS(read_cache_variants_f,
 48		SPINAND_PAGE_READ_FROM_CACHE_1S_4S_4S_OP(0, 1, NULL, 0, 0),
 49		SPINAND_PAGE_READ_FROM_CACHE_3A_1S_1S_4S_OP(0, 1, NULL, 0, 0),
 50		SPINAND_PAGE_READ_FROM_CACHE_1S_2S_2S_OP(0, 1, NULL, 0, 0),
 51		SPINAND_PAGE_READ_FROM_CACHE_3A_1S_1S_2S_OP(0, 1, NULL, 0, 0),
 52		SPINAND_PAGE_READ_FROM_CACHE_FAST_3A_1S_1S_1S_OP(0, 1, NULL, 0, 0),
 53		SPINAND_PAGE_READ_FROM_CACHE_3A_1S_1S_1S_OP(0, 0, NULL, 0, 0));
 54
 55static SPINAND_OP_VARIANTS(read_cache_variants_1gq5,
 56		SPINAND_PAGE_READ_FROM_CACHE_1S_4S_4S_OP(0, 2, NULL, 0, 0),
 57		SPINAND_PAGE_READ_FROM_CACHE_1S_1S_4S_OP(0, 1, NULL, 0, 0),
 58		SPINAND_PAGE_READ_FROM_CACHE_1S_2S_2S_OP(0, 1, NULL, 0, 0),
 59		SPINAND_PAGE_READ_FROM_CACHE_1S_1S_2S_OP(0, 1, NULL, 0, 0),
 60		SPINAND_PAGE_READ_FROM_CACHE_FAST_1S_1S_1S_OP(0, 1, NULL, 0, 0),
 61		SPINAND_PAGE_READ_FROM_CACHE_1S_1S_1S_OP(0, 1, NULL, 0, 0));
 62
 63static SPINAND_OP_VARIANTS(read_cache_variants_2gq5,
 64		SPINAND_PAGE_READ_FROM_CACHE_1S_4S_4S_OP(0, 4, NULL, 0, 0),
 65		SPINAND_PAGE_READ_FROM_CACHE_1S_1S_4S_OP(0, 1, NULL, 0, 0),
 66		SPINAND_PAGE_READ_FROM_CACHE_1S_2S_2S_OP(0, 2, NULL, 0, 0),
 67		SPINAND_PAGE_READ_FROM_CACHE_1S_1S_2S_OP(0, 1, NULL, 0, 0),
 68		SPINAND_PAGE_READ_FROM_CACHE_FAST_1S_1S_1S_OP(0, 1, NULL, 0, 0),
 69		SPINAND_PAGE_READ_FROM_CACHE_1S_1S_1S_OP(0, 1, NULL, 0, 0));
 70
 71static SPINAND_OP_VARIANTS(write_cache_variants,
 72		SPINAND_PROG_LOAD_1S_1S_4S_OP(true, 0, NULL, 0),
 73		SPINAND_PROG_LOAD_1S_1S_1S_OP(true, 0, NULL, 0));
 74
 75static SPINAND_OP_VARIANTS(update_cache_variants,
 76		SPINAND_PROG_LOAD_1S_1S_4S_OP(false, 0, NULL, 0),
 77		SPINAND_PROG_LOAD_1S_1S_1S_OP(false, 0, NULL, 0));
 78
 79static int gd5fxgm9_get_eccsr(struct spinand_device *spinand, u8 *eccsr)
 80{
 81	struct gigadevice_priv *priv = spinand->priv;
 82	struct spi_mem_op op = SPI_MEM_OP(SPI_MEM_OP_CMD(0x7c, 1),
 83					SPI_MEM_OP_NO_ADDR,
 84					SPI_MEM_OP_DUMMY(1, 1),
 85					SPI_MEM_OP_DATA_IN(1, eccsr, 1));
 86	int ret;
 87
 88	ret = spi_mem_exec_op(spinand->spimem, &op);
 89	if (ret)
 90		return ret;
 91
 92	if (priv->continuous_read)
 93		*eccsr = GD_ECCSR_ACCUMULATED(*eccsr);
 94	else
 95		*eccsr = GD_ECCSR_LAST_PAGE(*eccsr);
 96
 97	return 0;
 98}
 99
100static int gd5fxgm9_ecc_get_status(struct spinand_device *spinand, u8 status)
101{
102	struct nand_device *nand = spinand_to_nand(spinand);
103	u8 eccsr;
104	int ret;
105
106	switch (status & STATUS_ECC_MASK) {
107	case STATUS_ECC_NO_BITFLIPS:
108		return 0;
109
110	case GD5FXGQ4XA_STATUS_ECC_1_7_BITFLIPS:
111		ret = gd5fxgm9_get_eccsr(spinand, spinand->scratchbuf);
112		if (ret)
113			return nanddev_get_ecc_conf(nand)->strength;
114
115		eccsr = *spinand->scratchbuf;
116		if (WARN_ON(!eccsr || eccsr > nanddev_get_ecc_conf(nand)->strength))
117			return nanddev_get_ecc_conf(nand)->strength;
118
119		return eccsr;
120
121	case GD5FXGQ4XA_STATUS_ECC_8_BITFLIPS:
122		return 8;
123
124	case STATUS_ECC_UNCOR_ERROR:
125		return -EBADMSG;
126
127	default:
128		return -EINVAL;
129	}
130}
131
132static int gd5fxgm9_set_continuous_read(struct spinand_device *spinand, bool enable)
133{
134	struct gigadevice_priv *priv = spinand->priv;
135	int ret;
136
137	ret = spinand_upd_cfg(spinand, GD_FEATURE_NR,
138				enable ? 0 : GD_FEATURE_NR);
139	if (ret)
140		return ret;
141
142	priv->continuous_read = enable;
143
144	return 0;
145}
146
147static int gd5fxgq4xa_ooblayout_ecc(struct mtd_info *mtd, int section,
148				  struct mtd_oob_region *region)
149{
150	if (section > 3)
151		return -ERANGE;
152
153	region->offset = (16 * section) + 8;
154	region->length = 8;
155
156	return 0;
157}
158
159static int gd5fxgq4xa_ooblayout_free(struct mtd_info *mtd, int section,
160				   struct mtd_oob_region *region)
161{
162	if (section > 3)
163		return -ERANGE;
164
165	if (section) {
166		region->offset = 16 * section;
167		region->length = 8;
168	} else {
169		/* section 0 has one byte reserved for bad block mark */
170		region->offset = 1;
171		region->length = 7;
172	}
173	return 0;
174}
175
176static const struct mtd_ooblayout_ops gd5fxgq4xa_ooblayout = {
177	.ecc = gd5fxgq4xa_ooblayout_ecc,
178	.free = gd5fxgq4xa_ooblayout_free,
179};
180
181static int gd5fxgq4xa_ecc_get_status(struct spinand_device *spinand,
182					 u8 status)
183{
184	switch (status & STATUS_ECC_MASK) {
185	case STATUS_ECC_NO_BITFLIPS:
186		return 0;
187
188	case GD5FXGQ4XA_STATUS_ECC_1_7_BITFLIPS:
189		/* 1-7 bits are flipped. return the maximum. */
190		return 7;
191
192	case GD5FXGQ4XA_STATUS_ECC_8_BITFLIPS:
193		return 8;
194
195	case STATUS_ECC_UNCOR_ERROR:
196		return -EBADMSG;
197
198	default:
199		break;
200	}
201
202	return -EINVAL;
203}
204
205static int gd5fxgqx_variant2_ooblayout_ecc(struct mtd_info *mtd, int section,
206				       struct mtd_oob_region *region)
207{
208	if (section)
209		return -ERANGE;
210
211	region->offset = 64;
212	region->length = 64;
213
214	return 0;
215}
216
217static int gd5fxgqx_variant2_ooblayout_free(struct mtd_info *mtd, int section,
218					struct mtd_oob_region *region)
219{
220	if (section)
221		return -ERANGE;
222
223	/* Reserve 1 bytes for the BBM. */
224	region->offset = 1;
225	region->length = 63;
226
227	return 0;
228}
229
230/* Valid for Q4/Q5 and Q6 (untested) devices */
231static const struct mtd_ooblayout_ops gd5fxgqx_variant2_ooblayout = {
232	.ecc = gd5fxgqx_variant2_ooblayout_ecc,
233	.free = gd5fxgqx_variant2_ooblayout_free,
234};
235
236static int gd5fxgq4xc_ooblayout_256_ecc(struct mtd_info *mtd, int section,
237					struct mtd_oob_region *oobregion)
238{
239	if (section)
240		return -ERANGE;
241
242	oobregion->offset = 128;
243	oobregion->length = 128;
244
245	return 0;
246}
247
248static int gd5fxgq4xc_ooblayout_256_free(struct mtd_info *mtd, int section,
249					 struct mtd_oob_region *oobregion)
250{
251	if (section)
252		return -ERANGE;
253
254	oobregion->offset = 1;
255	oobregion->length = 127;
256
257	return 0;
258}
259
260static const struct mtd_ooblayout_ops gd5fxgq4xc_oob_256_ops = {
261	.ecc = gd5fxgq4xc_ooblayout_256_ecc,
262	.free = gd5fxgq4xc_ooblayout_256_free,
263};
264
265static int gd5fxgq4uexxg_ecc_get_status(struct spinand_device *spinand,
266					u8 status)
267{
268	u8 status2;
269	struct spi_mem_op op = SPINAND_GET_FEATURE_1S_1S_1S_OP(GD5FXGQXXEXXG_REG_STATUS2,
270						      spinand->scratchbuf);
271	int ret;
272
273	switch (status & STATUS_ECC_MASK) {
274	case STATUS_ECC_NO_BITFLIPS:
275		return 0;
276
277	case GD5FXGQ4XA_STATUS_ECC_1_7_BITFLIPS:
278		/*
279		 * Read status2 register to determine a more fine grained
280		 * bit error status
281		 */
282		ret = spi_mem_exec_op(spinand->spimem, &op);
283		if (ret)
284			return ret;
285
286		/*
287		 * 4 ... 7 bits are flipped (1..4 can't be detected, so
288		 * report the maximum of 4 in this case
289		 */
290		/* bits sorted this way (3...0): ECCS1,ECCS0,ECCSE1,ECCSE0 */
291		status2 = *(spinand->scratchbuf);
292		return ((status & STATUS_ECC_MASK) >> 2) |
293			((status2 & STATUS_ECC_MASK) >> 4);
294
295	case GD5FXGQ4XA_STATUS_ECC_8_BITFLIPS:
296		return 8;
297
298	case STATUS_ECC_UNCOR_ERROR:
299		return -EBADMSG;
300
301	default:
302		break;
303	}
304
305	return -EINVAL;
306}
307
308static int gd5fxgq5xexxg_ecc_get_status(struct spinand_device *spinand,
309					u8 status)
310{
311	u8 status2;
312	struct spi_mem_op op = SPINAND_GET_FEATURE_1S_1S_1S_OP(GD5FXGQXXEXXG_REG_STATUS2,
313						      spinand->scratchbuf);
314	int ret;
315
316	switch (status & STATUS_ECC_MASK) {
317	case STATUS_ECC_NO_BITFLIPS:
318		return 0;
319
320	case GD5FXGQ5XE_STATUS_ECC_1_4_BITFLIPS:
321		/*
322		 * Read status2 register to determine a more fine grained
323		 * bit error status
324		 */
325		ret = spi_mem_exec_op(spinand->spimem, &op);
326		if (ret)
327			return ret;
328
329		/*
330		 * 1 ... 4 bits are flipped (and corrected)
331		 */
332		/* bits sorted this way (1...0): ECCSE1, ECCSE0 */
333		status2 = *(spinand->scratchbuf);
334		return ((status2 & STATUS_ECC_MASK) >> 4) + 1;
335
336	case STATUS_ECC_UNCOR_ERROR:
337		return -EBADMSG;
338
339	default:
340		break;
341	}
342
343	return -EINVAL;
344}
345
346static int gd5fxgq4ufxxg_ecc_get_status(struct spinand_device *spinand,
347					u8 status)
348{
349	switch (status & GD5FXGQ4UXFXXG_STATUS_ECC_MASK) {
350	case GD5FXGQ4UXFXXG_STATUS_ECC_NO_BITFLIPS:
351		return 0;
352
353	case GD5FXGQ4UXFXXG_STATUS_ECC_1_3_BITFLIPS:
354		return 3;
355
356	case GD5FXGQ4UXFXXG_STATUS_ECC_UNCOR_ERROR:
357		return -EBADMSG;
358
359	default: /* (2 << 4) through (6 << 4) are 4-8 corrected errors */
360		return ((status & GD5FXGQ4UXFXXG_STATUS_ECC_MASK) >> 4) + 2;
361	}
362
363	return -EINVAL;
364}
365
366static const struct spinand_info gigadevice_spinand_table[] = {
367	SPINAND_INFO("GD5F1GQ4xA",
368		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0xf1),
369		     NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1),
370		     NAND_ECCREQ(8, 512),
371		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
372					      &write_cache_variants,
373					      &update_cache_variants),
374		     SPINAND_HAS_QE_BIT,
375		     SPINAND_ECCINFO(&gd5fxgq4xa_ooblayout,
376				     gd5fxgq4xa_ecc_get_status)),
377	SPINAND_INFO("GD5F2GQ4xA",
378		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0xf2),
379		     NAND_MEMORG(1, 2048, 64, 64, 2048, 40, 1, 1, 1),
380		     NAND_ECCREQ(8, 512),
381		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
382					      &write_cache_variants,
383					      &update_cache_variants),
384		     SPINAND_HAS_QE_BIT,
385		     SPINAND_ECCINFO(&gd5fxgq4xa_ooblayout,
386				     gd5fxgq4xa_ecc_get_status)),
387	SPINAND_INFO("GD5F4GQ4xA",
388		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0xf4),
389		     NAND_MEMORG(1, 2048, 64, 64, 4096, 80, 1, 1, 1),
390		     NAND_ECCREQ(8, 512),
391		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
392					      &write_cache_variants,
393					      &update_cache_variants),
394		     SPINAND_HAS_QE_BIT,
395		     SPINAND_ECCINFO(&gd5fxgq4xa_ooblayout,
396				     gd5fxgq4xa_ecc_get_status)),
397	SPINAND_INFO("GD5F4GQ4RC",
398		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE, 0xa4, 0x68),
399		     NAND_MEMORG(1, 4096, 256, 64, 2048, 40, 1, 1, 1),
400		     NAND_ECCREQ(8, 512),
401		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants_f,
402					      &write_cache_variants,
403					      &update_cache_variants),
404		     SPINAND_HAS_QE_BIT,
405		     SPINAND_ECCINFO(&gd5fxgq4xc_oob_256_ops,
406				     gd5fxgq4ufxxg_ecc_get_status)),
407	SPINAND_INFO("GD5F4GQ4UC",
408		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE, 0xb4, 0x68),
409		     NAND_MEMORG(1, 4096, 256, 64, 2048, 40, 1, 1, 1),
410		     NAND_ECCREQ(8, 512),
411		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants_f,
412					      &write_cache_variants,
413					      &update_cache_variants),
414		     SPINAND_HAS_QE_BIT,
415		     SPINAND_ECCINFO(&gd5fxgq4xc_oob_256_ops,
416				     gd5fxgq4ufxxg_ecc_get_status)),
417	SPINAND_INFO("GD5F1GQ4UExxG",
418		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0xd1),
419		     NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),
420		     NAND_ECCREQ(8, 512),
421		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
422					      &write_cache_variants,
423					      &update_cache_variants),
424		     SPINAND_HAS_QE_BIT,
425		     SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
426				     gd5fxgq4uexxg_ecc_get_status)),
427	SPINAND_INFO("GD5F1GQ4RExxG",
428		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0xc1),
429		     NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),
430		     NAND_ECCREQ(8, 512),
431		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
432					      &write_cache_variants,
433					      &update_cache_variants),
434		     SPINAND_HAS_QE_BIT,
435		     SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
436				     gd5fxgq4uexxg_ecc_get_status)),
437	SPINAND_INFO("GD5F2GQ4UExxG",
438		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0xd2),
439		     NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1),
440		     NAND_ECCREQ(8, 512),
441		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
442					      &write_cache_variants,
443					      &update_cache_variants),
444		     SPINAND_HAS_QE_BIT,
445		     SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
446				     gd5fxgq4uexxg_ecc_get_status)),
447	SPINAND_INFO("GD5F2GQ4RExxG",
448		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0xc2),
449		     NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1),
450		     NAND_ECCREQ(8, 512),
451		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
452					      &write_cache_variants,
453					      &update_cache_variants),
454		     SPINAND_HAS_QE_BIT,
455		     SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
456				     gd5fxgq4uexxg_ecc_get_status)),
457	SPINAND_INFO("GD5F1GQ4UFxxG",
458		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE, 0xb1, 0x48),
459		     NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),
460		     NAND_ECCREQ(8, 512),
461		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants_f,
462					      &write_cache_variants,
463					      &update_cache_variants),
464		     SPINAND_HAS_QE_BIT,
465		     SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
466				     gd5fxgq4ufxxg_ecc_get_status)),
467	SPINAND_INFO("GD5F1GQ5UExxG",
468		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x51),
469		     NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),
470		     NAND_ECCREQ(4, 512),
471		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants_1gq5,
472					      &write_cache_variants,
473					      &update_cache_variants),
474		     SPINAND_HAS_QE_BIT,
475		     SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
476				     gd5fxgq5xexxg_ecc_get_status)),
477	SPINAND_INFO("GD5F1GQ5RExxG",
478		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x41),
479		     NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),
480		     NAND_ECCREQ(4, 512),
481		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants_1gq5,
482					      &write_cache_variants,
483					      &update_cache_variants),
484		     SPINAND_HAS_QE_BIT,
485		     SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
486				     gd5fxgq5xexxg_ecc_get_status)),
487	SPINAND_INFO("GD5F2GQ5UExxG",
488		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x52),
489		     NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1),
490		     NAND_ECCREQ(4, 512),
491		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants_2gq5,
492					      &write_cache_variants,
493					      &update_cache_variants),
494		     SPINAND_HAS_QE_BIT,
495		     SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
496				     gd5fxgq5xexxg_ecc_get_status)),
497	SPINAND_INFO("GD5F2GQ5RExxG",
498		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x42),
499		     NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1),
500		     NAND_ECCREQ(4, 512),
501		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants_2gq5,
502					      &write_cache_variants,
503					      &update_cache_variants),
504		     SPINAND_HAS_QE_BIT,
505		     SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
506				     gd5fxgq5xexxg_ecc_get_status)),
507	SPINAND_INFO("GD5F4GQ6UExxG",
508		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x55),
509		     NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 2, 1),
510		     NAND_ECCREQ(4, 512),
511		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants_2gq5,
512					      &write_cache_variants,
513					      &update_cache_variants),
514		     SPINAND_HAS_QE_BIT,
515		     SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
516				     gd5fxgq5xexxg_ecc_get_status)),
517	SPINAND_INFO("GD5F4GQ6RExxG",
518		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x45),
519		     NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 2, 1),
520		     NAND_ECCREQ(4, 512),
521		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants_2gq5,
522					      &write_cache_variants,
523					      &update_cache_variants),
524		     SPINAND_HAS_QE_BIT,
525		     SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
526				     gd5fxgq5xexxg_ecc_get_status)),
527	SPINAND_INFO("GD5F1GM7UExxG",
528		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x91),
529		     NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),
530		     NAND_ECCREQ(8, 512),
531		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants_1gq5,
532					      &write_cache_variants,
533					      &update_cache_variants),
534		     SPINAND_HAS_QE_BIT,
535		     SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
536				     gd5fxgq4uexxg_ecc_get_status)),
537	SPINAND_INFO("GD5F1GM7RExxG",
538		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x81),
539		     NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),
540		     NAND_ECCREQ(8, 512),
541		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants_1gq5,
542					      &write_cache_variants,
543					      &update_cache_variants),
544		     SPINAND_HAS_QE_BIT,
545		     SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
546				     gd5fxgq4uexxg_ecc_get_status)),
547	SPINAND_INFO("GD5F2GM7UExxG",
548		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x92),
549		     NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1),
550		     NAND_ECCREQ(8, 512),
551		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants_1gq5,
552					      &write_cache_variants,
553					      &update_cache_variants),
554		     SPINAND_HAS_QE_BIT,
555		     SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
556				     gd5fxgq4uexxg_ecc_get_status)),
557	SPINAND_INFO("GD5F2GM7RExxG",
558		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x82),
559		     NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1),
560		     NAND_ECCREQ(8, 512),
561		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants_1gq5,
562					      &write_cache_variants,
563					      &update_cache_variants),
564		     SPINAND_HAS_QE_BIT,
565		     SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
566				     gd5fxgq4uexxg_ecc_get_status)),
567	SPINAND_INFO("GD5F4GM8UExxG",
568		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x95),
569		     NAND_MEMORG(1, 2048, 128, 64, 4096, 80, 1, 1, 1),
570		     NAND_ECCREQ(8, 512),
571		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants_1gq5,
572					      &write_cache_variants,
573					      &update_cache_variants),
574		     SPINAND_HAS_QE_BIT,
575		     SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
576				     gd5fxgq4uexxg_ecc_get_status)),
577	SPINAND_INFO("GD5F4GM8RExxG",
578		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x85),
579		     NAND_MEMORG(1, 2048, 128, 64, 4096, 80, 1, 1, 1),
580		     NAND_ECCREQ(8, 512),
581		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants_1gq5,
582					      &write_cache_variants,
583					      &update_cache_variants),
584		     SPINAND_HAS_QE_BIT,
585		     SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
586				     gd5fxgq4uexxg_ecc_get_status)),
587	SPINAND_INFO("GD5F2GQ5xExxH",
588		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x22),
589		     NAND_MEMORG(1, 2048, 64, 64, 2048, 40, 1, 1, 1),
590		     NAND_ECCREQ(4, 512),
591		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants_2gq5,
592					      &write_cache_variants,
593					      &update_cache_variants),
594		     SPINAND_HAS_QE_BIT,
595		     SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
596				     gd5fxgq4uexxg_ecc_get_status)),
597	SPINAND_INFO("GD5F1GQ5RExxH",
598		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x21),
599		     NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1),
600		     NAND_ECCREQ(4, 512),
601		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants_1gq5,
602					      &write_cache_variants,
603					      &update_cache_variants),
604		     SPINAND_HAS_QE_BIT,
605		     SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
606				     gd5fxgq4uexxg_ecc_get_status)),
607	SPINAND_INFO("GD5F1GQ4RExxH",
608		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xc9),
609		     NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1),
610		     NAND_ECCREQ(4, 512),
611		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants_1gq5,
612					      &write_cache_variants,
613					      &update_cache_variants),
614		     SPINAND_HAS_QE_BIT,
615		     SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
616				     gd5fxgq4uexxg_ecc_get_status)),
617	SPINAND_INFO("GD5F1GM9UExxG",
618		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x91, 0x01),
619		     NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),
620		     NAND_ECCREQ(8, 512),
621		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants_1gq5,
622					      &write_cache_variants,
623					      &update_cache_variants),
624		     SPINAND_HAS_QE_BIT,
625		     SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
626				     gd5fxgm9_ecc_get_status),
627			SPINAND_CONT_READ(gd5fxgm9_set_continuous_read)),
628	SPINAND_INFO("GD5F1GM9RExxG",
629		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x81, 0x01),
630		     NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),
631		     NAND_ECCREQ(8, 512),
632		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants_1gq5,
633					      &write_cache_variants,
634					      &update_cache_variants),
635		     SPINAND_HAS_QE_BIT,
636		     SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout,
637				     gd5fxgm9_ecc_get_status),
638			SPINAND_CONT_READ(gd5fxgm9_set_continuous_read)),
639};
640
641static int gd5fxgm9_spinand_init(struct spinand_device *spinand)
642{
643	struct gigadevice_priv *priv;
644
645	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
646	if (!priv)
647		return -ENOMEM;
648
649	spinand->priv =  priv;
650
651	return 0;
652}
653
654static void gd5fxgm9_spinand_cleanup(struct spinand_device *spinand)
655{
656	kfree(spinand->priv);
657}
658
659static const struct spinand_manufacturer_ops gigadevice_spinand_manuf_ops = {
660	.init = gd5fxgm9_spinand_init,
661	.cleanup = gd5fxgm9_spinand_cleanup,
662};
663
664const struct spinand_manufacturer gigadevice_spinand_manufacturer = {
665	.id = SPINAND_MFR_GIGADEVICE,
666	.name = "GigaDevice",
667	.chips = gigadevice_spinand_table,
668	.nchips = ARRAY_SIZE(gigadevice_spinand_table),
669	.ops = &gigadevice_spinand_manuf_ops,
670};
~/ Read-only file preview.