brintos

brintos / linux-shallow public Read only

0
0
Text · 10.7 KiB · bbbcaa8 Raw
314 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Copyright (c) 2018 exceet electronics GmbH4 * Copyright (c) 2018 Kontron Electronics GmbH5 *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		0x9815#define TOSH_STATUS_ECC_HAS_BITFLIPS_T	(3 << 4)16 17static SPINAND_OP_VARIANTS(read_cache_variants,18		SPINAND_PAGE_READ_FROM_CACHE_X4_OP(0, 1, NULL, 0),19		SPINAND_PAGE_READ_FROM_CACHE_X2_OP(0, 1, NULL, 0),20		SPINAND_PAGE_READ_FROM_CACHE_OP(true, 0, 1, NULL, 0),21		SPINAND_PAGE_READ_FROM_CACHE_OP(false, 0, 1, NULL, 0));22 23static SPINAND_OP_VARIANTS(write_cache_x4_variants,24		SPINAND_PROG_LOAD_X4(true, 0, NULL, 0),25		SPINAND_PROG_LOAD(true, 0, NULL, 0));26 27static SPINAND_OP_VARIANTS(update_cache_x4_variants,28		SPINAND_PROG_LOAD_X4(false, 0, NULL, 0),29		SPINAND_PROG_LOAD(false, 0, NULL, 0));30 31/*32 * Backward compatibility for 1st generation Serial NAND devices33 * which don't support Quad Program Load operation.34 */35static SPINAND_OP_VARIANTS(write_cache_variants,36		SPINAND_PROG_LOAD(true, 0, NULL, 0));37 38static SPINAND_OP_VARIANTS(update_cache_variants,39		SPINAND_PROG_LOAD(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_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 bitflips89		 * in order to avoid forcing the wear-leveling layer to move90		 * 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 to179	 * 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};314