File Index
Files and directories
Sign in
FILE

toshiba.c

File preview with syntax highlighting.

linux-6.19.14/drivers/mtd/nand/spi/toshiba.c C
  1// SPDX-License-Identifier: GPL-2.0
  2/*
  3 * Copyright (c) 2018 exceet electronics GmbH
  4 * Copyright (c) 2018 Kontron Electronics GmbH
  5 *
  6 * Author: Frieder Schrempf <frieder.schrempf@kontron.de>
  7 */
  8
  9#include <linux/device.h>
 10#include <linux/kernel.h>
 11#include <linux/mtd/spinand.h>
 12
 13/* Kioxia is new name of Toshiba memory. */
 14#define SPINAND_MFR_TOSHIBA		0x98
 15#define TOSH_STATUS_ECC_HAS_BITFLIPS_T	(3 << 4)
 16
 17static SPINAND_OP_VARIANTS(read_cache_variants,
 18		SPINAND_PAGE_READ_FROM_CACHE_1S_1S_4S_OP(0, 1, NULL, 0, 0),
 19		SPINAND_PAGE_READ_FROM_CACHE_1S_1S_2S_OP(0, 1, NULL, 0, 0),
 20		SPINAND_PAGE_READ_FROM_CACHE_FAST_1S_1S_1S_OP(0, 1, NULL, 0, 0),
 21		SPINAND_PAGE_READ_FROM_CACHE_1S_1S_1S_OP(0, 1, NULL, 0, 0));
 22
 23static SPINAND_OP_VARIANTS(write_cache_x4_variants,
 24		SPINAND_PROG_LOAD_1S_1S_4S_OP(true, 0, NULL, 0),
 25		SPINAND_PROG_LOAD_1S_1S_1S_OP(true, 0, NULL, 0));
 26
 27static SPINAND_OP_VARIANTS(update_cache_x4_variants,
 28		SPINAND_PROG_LOAD_1S_1S_4S_OP(false, 0, NULL, 0),
 29		SPINAND_PROG_LOAD_1S_1S_1S_OP(false, 0, NULL, 0));
 30
 31/*
 32 * Backward compatibility for 1st generation Serial NAND devices
 33 * which don't support Quad Program Load operation.
 34 */
 35static SPINAND_OP_VARIANTS(write_cache_variants,
 36		SPINAND_PROG_LOAD_1S_1S_1S_OP(true, 0, NULL, 0));
 37
 38static SPINAND_OP_VARIANTS(update_cache_variants,
 39		SPINAND_PROG_LOAD_1S_1S_1S_OP(false, 0, NULL, 0));
 40
 41static int tx58cxgxsxraix_ooblayout_ecc(struct mtd_info *mtd, int section,
 42					struct mtd_oob_region *region)
 43{
 44	if (section > 0)
 45		return -ERANGE;
 46
 47	region->offset = mtd->oobsize / 2;
 48	region->length = mtd->oobsize / 2;
 49
 50	return 0;
 51}
 52
 53static int tx58cxgxsxraix_ooblayout_free(struct mtd_info *mtd, int section,
 54					 struct mtd_oob_region *region)
 55{
 56	if (section > 0)
 57		return -ERANGE;
 58
 59	/* 2 bytes reserved for BBM */
 60	region->offset = 2;
 61	region->length = (mtd->oobsize / 2) - 2;
 62
 63	return 0;
 64}
 65
 66static const struct mtd_ooblayout_ops tx58cxgxsxraix_ooblayout = {
 67	.ecc = tx58cxgxsxraix_ooblayout_ecc,
 68	.free = tx58cxgxsxraix_ooblayout_free,
 69};
 70
 71static int tx58cxgxsxraix_ecc_get_status(struct spinand_device *spinand,
 72					 u8 status)
 73{
 74	struct nand_device *nand = spinand_to_nand(spinand);
 75	u8 mbf = 0;
 76	struct spi_mem_op op = SPINAND_GET_FEATURE_1S_1S_1S_OP(0x30, spinand->scratchbuf);
 77
 78	switch (status & STATUS_ECC_MASK) {
 79	case STATUS_ECC_NO_BITFLIPS:
 80		return 0;
 81
 82	case STATUS_ECC_UNCOR_ERROR:
 83		return -EBADMSG;
 84
 85	case STATUS_ECC_HAS_BITFLIPS:
 86	case TOSH_STATUS_ECC_HAS_BITFLIPS_T:
 87		/*
 88		 * Let's try to retrieve the real maximum number of bitflips
 89		 * in order to avoid forcing the wear-leveling layer to move
 90		 * data around if it's not necessary.
 91		 */
 92		if (spi_mem_exec_op(spinand->spimem, &op))
 93			return nanddev_get_ecc_conf(nand)->strength;
 94
 95		mbf = *(spinand->scratchbuf) >> 4;
 96
 97		if (WARN_ON(mbf > nanddev_get_ecc_conf(nand)->strength || !mbf))
 98			return nanddev_get_ecc_conf(nand)->strength;
 99
100		return mbf;
101
102	default:
103		break;
104	}
105
106	return -EINVAL;
107}
108
109static const struct spinand_info toshiba_spinand_table[] = {
110	/* 3.3V 1Gb (1st generation) */
111	SPINAND_INFO("TC58CVG0S3HRAIG",
112		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xC2),
113		     NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),
114		     NAND_ECCREQ(8, 512),
115		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
116					      &write_cache_variants,
117					      &update_cache_variants),
118		     0,
119		     SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout,
120				     tx58cxgxsxraix_ecc_get_status)),
121	/* 3.3V 2Gb (1st generation) */
122	SPINAND_INFO("TC58CVG1S3HRAIG",
123		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xCB),
124		     NAND_MEMORG(1, 2048, 128, 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(&tx58cxgxsxraix_ooblayout,
131				     tx58cxgxsxraix_ecc_get_status)),
132	/* 3.3V 4Gb (1st generation) */
133	SPINAND_INFO("TC58CVG2S0HRAIG",
134		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xCD),
135		     NAND_MEMORG(1, 4096, 256, 64, 2048, 40, 1, 1, 1),
136		     NAND_ECCREQ(8, 512),
137		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
138					      &write_cache_variants,
139					      &update_cache_variants),
140		     0,
141		     SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout,
142				     tx58cxgxsxraix_ecc_get_status)),
143	/* 1.8V 1Gb (1st generation) */
144	SPINAND_INFO("TC58CYG0S3HRAIG",
145		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xB2),
146		     NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),
147		     NAND_ECCREQ(8, 512),
148		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
149					      &write_cache_variants,
150					      &update_cache_variants),
151		     0,
152		     SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout,
153				     tx58cxgxsxraix_ecc_get_status)),
154	/* 1.8V 2Gb (1st generation) */
155	SPINAND_INFO("TC58CYG1S3HRAIG",
156		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xBB),
157		     NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1),
158		     NAND_ECCREQ(8, 512),
159		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
160					      &write_cache_variants,
161					      &update_cache_variants),
162		     0,
163		     SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout,
164				     tx58cxgxsxraix_ecc_get_status)),
165	/* 1.8V 4Gb (1st generation) */
166	SPINAND_INFO("TC58CYG2S0HRAIG",
167		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xBD),
168		     NAND_MEMORG(1, 4096, 256, 64, 2048, 40, 1, 1, 1),
169		     NAND_ECCREQ(8, 512),
170		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
171					      &write_cache_variants,
172					      &update_cache_variants),
173		     0,
174		     SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout,
175				     tx58cxgxsxraix_ecc_get_status)),
176
177	/*
178	 * 2nd generation serial nand has HOLD_D which is equivalent to
179	 * QE_BIT.
180	 */
181	/* 3.3V 1Gb (2nd generation) */
182	SPINAND_INFO("TC58CVG0S3HRAIJ",
183		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xE2),
184		     NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),
185		     NAND_ECCREQ(8, 512),
186		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
187					      &write_cache_x4_variants,
188					      &update_cache_x4_variants),
189		     SPINAND_HAS_QE_BIT,
190		     SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout,
191				     tx58cxgxsxraix_ecc_get_status)),
192	/* 3.3V 2Gb (2nd generation) */
193	SPINAND_INFO("TC58CVG1S3HRAIJ",
194		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xEB),
195		     NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1),
196		     NAND_ECCREQ(8, 512),
197		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
198					      &write_cache_x4_variants,
199					      &update_cache_x4_variants),
200		     SPINAND_HAS_QE_BIT,
201		     SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout,
202				     tx58cxgxsxraix_ecc_get_status)),
203	/* 3.3V 4Gb (2nd generation) */
204	SPINAND_INFO("TC58CVG2S0HRAIJ",
205		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xED),
206		     NAND_MEMORG(1, 4096, 256, 64, 2048, 40, 1, 1, 1),
207		     NAND_ECCREQ(8, 512),
208		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
209					      &write_cache_x4_variants,
210					      &update_cache_x4_variants),
211		     SPINAND_HAS_QE_BIT,
212		     SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout,
213				     tx58cxgxsxraix_ecc_get_status)),
214	/* 3.3V 8Gb (2nd generation) */
215	SPINAND_INFO("TH58CVG3S0HRAIJ",
216		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xE4),
217		     NAND_MEMORG(1, 4096, 256, 64, 4096, 80, 1, 1, 1),
218		     NAND_ECCREQ(8, 512),
219		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
220					      &write_cache_x4_variants,
221					      &update_cache_x4_variants),
222		     SPINAND_HAS_QE_BIT,
223		     SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout,
224				     tx58cxgxsxraix_ecc_get_status)),
225	/* 1.8V 1Gb (2nd generation) */
226	SPINAND_INFO("TC58CYG0S3HRAIJ",
227		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xD2),
228		     NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),
229		     NAND_ECCREQ(8, 512),
230		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
231					      &write_cache_x4_variants,
232					      &update_cache_x4_variants),
233		     SPINAND_HAS_QE_BIT,
234		     SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout,
235				     tx58cxgxsxraix_ecc_get_status)),
236	/* 1.8V 2Gb (2nd generation) */
237	SPINAND_INFO("TC58CYG1S3HRAIJ",
238		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xDB),
239		     NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1),
240		     NAND_ECCREQ(8, 512),
241		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
242					      &write_cache_x4_variants,
243					      &update_cache_x4_variants),
244		     SPINAND_HAS_QE_BIT,
245		     SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout,
246				     tx58cxgxsxraix_ecc_get_status)),
247	/* 1.8V 4Gb (2nd generation) */
248	SPINAND_INFO("TC58CYG2S0HRAIJ",
249		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xDD),
250		     NAND_MEMORG(1, 4096, 256, 64, 2048, 40, 1, 1, 1),
251		     NAND_ECCREQ(8, 512),
252		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
253					      &write_cache_x4_variants,
254					      &update_cache_x4_variants),
255		     SPINAND_HAS_QE_BIT,
256		     SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout,
257				     tx58cxgxsxraix_ecc_get_status)),
258	/* 1.8V 8Gb (2nd generation) */
259	SPINAND_INFO("TH58CYG3S0HRAIJ",
260		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xD4),
261		     NAND_MEMORG(1, 4096, 256, 64, 4096, 80, 1, 1, 1),
262		     NAND_ECCREQ(8, 512),
263		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
264					      &write_cache_x4_variants,
265					      &update_cache_x4_variants),
266		     SPINAND_HAS_QE_BIT,
267		     SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout,
268				     tx58cxgxsxraix_ecc_get_status)),
269	/* 1.8V 1Gb (1st generation) */
270	SPINAND_INFO("TC58NYG0S3HBAI4",
271		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xA1),
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		     0,
278		     SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout,
279				     tx58cxgxsxraix_ecc_get_status)),
280	/* 1.8V 4Gb (1st generation) */
281	SPINAND_INFO("TH58NYG2S3HBAI4",
282		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xAC),
283		     NAND_MEMORG(1, 2048, 128, 64, 4096, 80, 1, 2, 1),
284		     NAND_ECCREQ(8, 512),
285		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
286					      &write_cache_x4_variants,
287					      &update_cache_x4_variants),
288		     SPINAND_HAS_QE_BIT,
289		     SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout,
290				     tx58cxgxsxraix_ecc_get_status)),
291	/* 1.8V 8Gb (1st generation) */
292	SPINAND_INFO("TH58NYG3S0HBAI6",
293		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xA3),
294		     NAND_MEMORG(1, 4096, 256, 64, 4096, 80, 1, 1, 1),
295		     NAND_ECCREQ(8, 512),
296		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
297					      &write_cache_x4_variants,
298					      &update_cache_x4_variants),
299		     SPINAND_HAS_QE_BIT,
300		     SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout,
301				     tx58cxgxsxraix_ecc_get_status)),
302};
303
304static const struct spinand_manufacturer_ops toshiba_spinand_manuf_ops = {
305};
306
307const struct spinand_manufacturer toshiba_spinand_manufacturer = {
308	.id = SPINAND_MFR_TOSHIBA,
309	.name = "Toshiba",
310	.chips = toshiba_spinand_table,
311	.nchips = ARRAY_SIZE(toshiba_spinand_table),
312	.ops = &toshiba_spinand_manuf_ops,
313};
~/ Read-only file preview.