Linux Audio

Check our new training course

Loading...
v5.9
  1// SPDX-License-Identifier: GPL-2.0
  2/*
  3 * Copyright (c) 2018 Macronix
  4 *
  5 * Author: Boris Brezillon <boris.brezillon@bootlin.com>
  6 */
  7
  8#include <linux/device.h>
  9#include <linux/kernel.h>
 10#include <linux/mtd/spinand.h>
 11
 12#define SPINAND_MFR_MACRONIX		0xC2
 13#define MACRONIX_ECCSR_MASK		0x0F
 14
 15static 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
 21static SPINAND_OP_VARIANTS(write_cache_variants,
 22		SPINAND_PROG_LOAD_X4(true, 0, NULL, 0),
 23		SPINAND_PROG_LOAD(true, 0, NULL, 0));
 24
 25static SPINAND_OP_VARIANTS(update_cache_variants,
 26		SPINAND_PROG_LOAD_X4(false, 0, NULL, 0),
 27		SPINAND_PROG_LOAD(false, 0, NULL, 0));
 28
 29static int mx35lfxge4ab_ooblayout_ecc(struct mtd_info *mtd, int section,
 30				      struct mtd_oob_region *region)
 31{
 32	return -ERANGE;
 33}
 34
 35static int mx35lfxge4ab_ooblayout_free(struct mtd_info *mtd, int section,
 36				       struct mtd_oob_region *region)
 37{
 38	if (section)
 39		return -ERANGE;
 40
 41	region->offset = 2;
 42	region->length = mtd->oobsize - 2;
 43
 44	return 0;
 45}
 46
 47static const struct mtd_ooblayout_ops mx35lfxge4ab_ooblayout = {
 48	.ecc = mx35lfxge4ab_ooblayout_ecc,
 49	.free = mx35lfxge4ab_ooblayout_free,
 50};
 51
 52static int mx35lf1ge4ab_get_eccsr(struct spinand_device *spinand, u8 *eccsr)
 53{
 54	struct spi_mem_op op = SPI_MEM_OP(SPI_MEM_OP_CMD(0x7c, 1),
 55					  SPI_MEM_OP_NO_ADDR,
 56					  SPI_MEM_OP_DUMMY(1, 1),
 57					  SPI_MEM_OP_DATA_IN(1, eccsr, 1));
 58
 59	int ret = spi_mem_exec_op(spinand->spimem, &op);
 60	if (ret)
 61		return ret;
 62
 63	*eccsr &= MACRONIX_ECCSR_MASK;
 64	return 0;
 65}
 66
 67static int mx35lf1ge4ab_ecc_get_status(struct spinand_device *spinand,
 68				       u8 status)
 69{
 70	struct nand_device *nand = spinand_to_nand(spinand);
 71	u8 eccsr;
 72
 73	switch (status & STATUS_ECC_MASK) {
 74	case STATUS_ECC_NO_BITFLIPS:
 75		return 0;
 76
 77	case STATUS_ECC_UNCOR_ERROR:
 78		return -EBADMSG;
 79
 80	case STATUS_ECC_HAS_BITFLIPS:
 81		/*
 82		 * Let's try to retrieve the real maximum number of bitflips
 83		 * in order to avoid forcing the wear-leveling layer to move
 84		 * data around if it's not necessary.
 85		 */
 86		if (mx35lf1ge4ab_get_eccsr(spinand, &eccsr))
 87			return nand->eccreq.strength;
 88
 89		if (WARN_ON(eccsr > nand->eccreq.strength || !eccsr))
 90			return nand->eccreq.strength;
 
 91
 92		return eccsr;
 93
 94	default:
 95		break;
 96	}
 97
 98	return -EINVAL;
 99}
100
101static const struct spinand_info macronix_spinand_table[] = {
102	SPINAND_INFO("MX35LF1GE4AB",
103		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x12),
104		     NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1),
105		     NAND_ECCREQ(4, 512),
106		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
107					      &write_cache_variants,
108					      &update_cache_variants),
109		     SPINAND_HAS_QE_BIT,
110		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
111				     mx35lf1ge4ab_ecc_get_status)),
112	SPINAND_INFO("MX35LF2GE4AB",
113		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x22),
114		     NAND_MEMORG(1, 2048, 64, 64, 2048, 40, 2, 1, 1),
115		     NAND_ECCREQ(4, 512),
116		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
117					      &write_cache_variants,
118					      &update_cache_variants),
119		     SPINAND_HAS_QE_BIT,
120		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout, NULL)),
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
121};
122
123static const struct spinand_manufacturer_ops macronix_spinand_manuf_ops = {
124};
125
126const struct spinand_manufacturer macronix_spinand_manufacturer = {
127	.id = SPINAND_MFR_MACRONIX,
128	.name = "Macronix",
129	.chips = macronix_spinand_table,
130	.nchips = ARRAY_SIZE(macronix_spinand_table),
131	.ops = &macronix_spinand_manuf_ops,
132};
v5.14.15
  1// SPDX-License-Identifier: GPL-2.0
  2/*
  3 * Copyright (c) 2018 Macronix
  4 *
  5 * Author: Boris Brezillon <boris.brezillon@bootlin.com>
  6 */
  7
  8#include <linux/device.h>
  9#include <linux/kernel.h>
 10#include <linux/mtd/spinand.h>
 11
 12#define SPINAND_MFR_MACRONIX		0xC2
 13#define MACRONIX_ECCSR_MASK		0x0F
 14
 15static 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
 21static SPINAND_OP_VARIANTS(write_cache_variants,
 22		SPINAND_PROG_LOAD_X4(true, 0, NULL, 0),
 23		SPINAND_PROG_LOAD(true, 0, NULL, 0));
 24
 25static SPINAND_OP_VARIANTS(update_cache_variants,
 26		SPINAND_PROG_LOAD_X4(false, 0, NULL, 0),
 27		SPINAND_PROG_LOAD(false, 0, NULL, 0));
 28
 29static int mx35lfxge4ab_ooblayout_ecc(struct mtd_info *mtd, int section,
 30				      struct mtd_oob_region *region)
 31{
 32	return -ERANGE;
 33}
 34
 35static int mx35lfxge4ab_ooblayout_free(struct mtd_info *mtd, int section,
 36				       struct mtd_oob_region *region)
 37{
 38	if (section)
 39		return -ERANGE;
 40
 41	region->offset = 2;
 42	region->length = mtd->oobsize - 2;
 43
 44	return 0;
 45}
 46
 47static const struct mtd_ooblayout_ops mx35lfxge4ab_ooblayout = {
 48	.ecc = mx35lfxge4ab_ooblayout_ecc,
 49	.free = mx35lfxge4ab_ooblayout_free,
 50};
 51
 52static int mx35lf1ge4ab_get_eccsr(struct spinand_device *spinand, u8 *eccsr)
 53{
 54	struct spi_mem_op op = SPI_MEM_OP(SPI_MEM_OP_CMD(0x7c, 1),
 55					  SPI_MEM_OP_NO_ADDR,
 56					  SPI_MEM_OP_DUMMY(1, 1),
 57					  SPI_MEM_OP_DATA_IN(1, eccsr, 1));
 58
 59	int ret = spi_mem_exec_op(spinand->spimem, &op);
 60	if (ret)
 61		return ret;
 62
 63	*eccsr &= MACRONIX_ECCSR_MASK;
 64	return 0;
 65}
 66
 67static int mx35lf1ge4ab_ecc_get_status(struct spinand_device *spinand,
 68				       u8 status)
 69{
 70	struct nand_device *nand = spinand_to_nand(spinand);
 71	u8 eccsr;
 72
 73	switch (status & STATUS_ECC_MASK) {
 74	case STATUS_ECC_NO_BITFLIPS:
 75		return 0;
 76
 77	case STATUS_ECC_UNCOR_ERROR:
 78		return -EBADMSG;
 79
 80	case STATUS_ECC_HAS_BITFLIPS:
 81		/*
 82		 * Let's try to retrieve the real maximum number of bitflips
 83		 * in order to avoid forcing the wear-leveling layer to move
 84		 * data around if it's not necessary.
 85		 */
 86		if (mx35lf1ge4ab_get_eccsr(spinand, &eccsr))
 87			return nanddev_get_ecc_conf(nand)->strength;
 88
 89		if (WARN_ON(eccsr > nanddev_get_ecc_conf(nand)->strength ||
 90			    !eccsr))
 91			return nanddev_get_ecc_conf(nand)->strength;
 92
 93		return eccsr;
 94
 95	default:
 96		break;
 97	}
 98
 99	return -EINVAL;
100}
101
102static const struct spinand_info macronix_spinand_table[] = {
103	SPINAND_INFO("MX35LF1GE4AB",
104		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x12),
105		     NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1),
106		     NAND_ECCREQ(4, 512),
107		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
108					      &write_cache_variants,
109					      &update_cache_variants),
110		     SPINAND_HAS_QE_BIT,
111		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
112				     mx35lf1ge4ab_ecc_get_status)),
113	SPINAND_INFO("MX35LF2GE4AB",
114		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x22),
115		     NAND_MEMORG(1, 2048, 64, 64, 2048, 40, 2, 1, 1),
116		     NAND_ECCREQ(4, 512),
117		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
118					      &write_cache_variants,
119					      &update_cache_variants),
120		     SPINAND_HAS_QE_BIT,
121		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout, NULL)),
122	SPINAND_INFO("MX35LF2GE4AD",
123		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x26),
124		     NAND_MEMORG(1, 2048, 64, 64, 2048, 40, 1, 1, 1),
125		     NAND_ECCREQ(8, 512),
126		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
127					      &write_cache_variants,
128					      &update_cache_variants),
129		     0,
130		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
131				     mx35lf1ge4ab_ecc_get_status)),
132	SPINAND_INFO("MX35LF4GE4AD",
133		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x37),
134		     NAND_MEMORG(1, 4096, 128, 64, 2048, 40, 1, 1, 1),
135		     NAND_ECCREQ(8, 512),
136		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
137					      &write_cache_variants,
138					      &update_cache_variants),
139		     0,
140		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
141				     mx35lf1ge4ab_ecc_get_status)),
142	SPINAND_INFO("MX35LF1G24AD",
143		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x14),
144		     NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),
145		     NAND_ECCREQ(8, 512),
146		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
147					      &write_cache_variants,
148					      &update_cache_variants),
149		     0,
150		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout, NULL)),
151	SPINAND_INFO("MX35LF2G24AD",
152		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x24),
153		     NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1),
154		     NAND_ECCREQ(8, 512),
155		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
156					      &write_cache_variants,
157					      &update_cache_variants),
158		     0,
159		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout, NULL)),
160	SPINAND_INFO("MX35LF4G24AD",
161		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x35),
162		     NAND_MEMORG(1, 4096, 256, 64, 2048, 40, 2, 1, 1),
163		     NAND_ECCREQ(8, 512),
164		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
165					      &write_cache_variants,
166					      &update_cache_variants),
167		     0,
168		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout, NULL)),
169	SPINAND_INFO("MX31LF1GE4BC",
170		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x1e),
171		     NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1),
172		     NAND_ECCREQ(8, 512),
173		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
174					      &write_cache_variants,
175					      &update_cache_variants),
176		     0 /*SPINAND_HAS_QE_BIT*/,
177		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
178				     mx35lf1ge4ab_ecc_get_status)),
179	SPINAND_INFO("MX31UF1GE4BC",
180		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x9e),
181		     NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1),
182		     NAND_ECCREQ(8, 512),
183		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
184					      &write_cache_variants,
185					      &update_cache_variants),
186		     0 /*SPINAND_HAS_QE_BIT*/,
187		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
188				     mx35lf1ge4ab_ecc_get_status)),
189
190	SPINAND_INFO("MX35LF2G14AC",
191		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x20),
192		     NAND_MEMORG(1, 2048, 64, 64, 2048, 40, 2, 1, 1),
193		     NAND_ECCREQ(4, 512),
194		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
195					      &write_cache_variants,
196					      &update_cache_variants),
197		     SPINAND_HAS_QE_BIT,
198		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
199				     mx35lf1ge4ab_ecc_get_status)),
200	SPINAND_INFO("MX35UF4G24AD",
201		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xb5),
202		     NAND_MEMORG(1, 4096, 256, 64, 2048, 40, 2, 1, 1),
203		     NAND_ECCREQ(8, 512),
204		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
205					      &write_cache_variants,
206					      &update_cache_variants),
207		     SPINAND_HAS_QE_BIT,
208		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
209				     mx35lf1ge4ab_ecc_get_status)),
210	SPINAND_INFO("MX35UF4GE4AD",
211		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xb7),
212		     NAND_MEMORG(1, 4096, 256, 64, 2048, 40, 1, 1, 1),
213		     NAND_ECCREQ(8, 512),
214		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
215					      &write_cache_variants,
216					      &update_cache_variants),
217		     SPINAND_HAS_QE_BIT,
218		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
219				     mx35lf1ge4ab_ecc_get_status)),
220	SPINAND_INFO("MX35UF2G14AC",
221		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xa0),
222		     NAND_MEMORG(1, 2048, 64, 64, 2048, 40, 2, 1, 1),
223		     NAND_ECCREQ(4, 512),
224		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
225					      &write_cache_variants,
226					      &update_cache_variants),
227		     SPINAND_HAS_QE_BIT,
228		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
229				     mx35lf1ge4ab_ecc_get_status)),
230	SPINAND_INFO("MX35UF2G24AD",
231		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xa4),
232		     NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 2, 1, 1),
233		     NAND_ECCREQ(8, 512),
234		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
235					      &write_cache_variants,
236					      &update_cache_variants),
237		     SPINAND_HAS_QE_BIT,
238		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
239				     mx35lf1ge4ab_ecc_get_status)),
240	SPINAND_INFO("MX35UF2GE4AD",
241		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xa6),
242		     NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1),
243		     NAND_ECCREQ(8, 512),
244		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
245					      &write_cache_variants,
246					      &update_cache_variants),
247		     SPINAND_HAS_QE_BIT,
248		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
249				     mx35lf1ge4ab_ecc_get_status)),
250	SPINAND_INFO("MX35UF2GE4AC",
251		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xa2),
252		     NAND_MEMORG(1, 2048, 64, 64, 2048, 40, 1, 1, 1),
253		     NAND_ECCREQ(4, 512),
254		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
255					      &write_cache_variants,
256					      &update_cache_variants),
257		     SPINAND_HAS_QE_BIT,
258		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
259				     mx35lf1ge4ab_ecc_get_status)),
260	SPINAND_INFO("MX35UF1G14AC",
261		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x90),
262		     NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1),
263		     NAND_ECCREQ(4, 512),
264		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
265					      &write_cache_variants,
266					      &update_cache_variants),
267		     SPINAND_HAS_QE_BIT,
268		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
269				     mx35lf1ge4ab_ecc_get_status)),
270	SPINAND_INFO("MX35UF1G24AD",
271		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x94),
272		     NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),
273		     NAND_ECCREQ(8, 512),
274		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
275					      &write_cache_variants,
276					      &update_cache_variants),
277		     SPINAND_HAS_QE_BIT,
278		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
279				     mx35lf1ge4ab_ecc_get_status)),
280	SPINAND_INFO("MX35UF1GE4AD",
281		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x96),
282		     NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),
283		     NAND_ECCREQ(8, 512),
284		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
285					      &write_cache_variants,
286					      &update_cache_variants),
287		     SPINAND_HAS_QE_BIT,
288		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
289				     mx35lf1ge4ab_ecc_get_status)),
290	SPINAND_INFO("MX35UF1GE4AC",
291		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x92),
292		     NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1),
293		     NAND_ECCREQ(4, 512),
294		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
295					      &write_cache_variants,
296					      &update_cache_variants),
297		     SPINAND_HAS_QE_BIT,
298		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
299				     mx35lf1ge4ab_ecc_get_status)),
300
301};
302
303static const struct spinand_manufacturer_ops macronix_spinand_manuf_ops = {
304};
305
306const struct spinand_manufacturer macronix_spinand_manufacturer = {
307	.id = SPINAND_MFR_MACRONIX,
308	.name = "Macronix",
309	.chips = macronix_spinand_table,
310	.nchips = ARRAY_SIZE(macronix_spinand_table),
311	.ops = &macronix_spinand_manuf_ops,
312};