brintos

brintos / linux-shallow public Read only

0
0
Text · 7.9 KiB · 66a4255 Raw
264 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Author:4 * Felix Matouschek <felix@matouschek.org>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_XTX	0x0B13 14#define XT26G0XA_STATUS_ECC_MASK	GENMASK(5, 2)15#define XT26G0XA_STATUS_ECC_NO_DETECTED	(0 << 2)16#define XT26G0XA_STATUS_ECC_8_CORRECTED	(3 << 4)17#define XT26G0XA_STATUS_ECC_UNCOR_ERROR	(2 << 4)18 19#define XT26XXXD_STATUS_ECC3_ECC2_MASK	    GENMASK(7, 6)20#define XT26XXXD_STATUS_ECC_NO_DETECTED     (0)21#define XT26XXXD_STATUS_ECC_1_7_CORRECTED   (1)22#define XT26XXXD_STATUS_ECC_8_CORRECTED     (3)23#define XT26XXXD_STATUS_ECC_UNCOR_ERROR     (2)24 25static SPINAND_OP_VARIANTS(read_cache_variants,26		SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP(0, 1, NULL, 0),27		SPINAND_PAGE_READ_FROM_CACHE_X4_OP(0, 1, NULL, 0),28		SPINAND_PAGE_READ_FROM_CACHE_DUALIO_OP(0, 1, NULL, 0),29		SPINAND_PAGE_READ_FROM_CACHE_X2_OP(0, 1, NULL, 0),30		SPINAND_PAGE_READ_FROM_CACHE_OP(true, 0, 1, NULL, 0),31		SPINAND_PAGE_READ_FROM_CACHE_OP(false, 0, 1, NULL, 0));32 33static SPINAND_OP_VARIANTS(write_cache_variants,34		SPINAND_PROG_LOAD_X4(true, 0, NULL, 0),35		SPINAND_PROG_LOAD(true, 0, NULL, 0));36 37static SPINAND_OP_VARIANTS(update_cache_variants,38		SPINAND_PROG_LOAD_X4(false, 0, NULL, 0),39		SPINAND_PROG_LOAD(false, 0, NULL, 0));40 41static int xt26g0xa_ooblayout_ecc(struct mtd_info *mtd, int section,42				   struct mtd_oob_region *region)43{44	if (section)45		return -ERANGE;46 47	region->offset = 48;48	region->length = 16;49 50	return 0;51}52 53static int xt26g0xa_ooblayout_free(struct mtd_info *mtd, int section,54				   struct mtd_oob_region *region)55{56	if (section)57		return -ERANGE;58 59	region->offset = 1;60	region->length = 47;61 62	return 0;63}64 65static const struct mtd_ooblayout_ops xt26g0xa_ooblayout = {66	.ecc = xt26g0xa_ooblayout_ecc,67	.free = xt26g0xa_ooblayout_free,68};69 70static int xt26g0xa_ecc_get_status(struct spinand_device *spinand,71					 u8 status)72{73	status = status & XT26G0XA_STATUS_ECC_MASK;74 75	switch (status) {76	case XT26G0XA_STATUS_ECC_NO_DETECTED:77		return 0;78	case XT26G0XA_STATUS_ECC_8_CORRECTED:79		return 8;80	case XT26G0XA_STATUS_ECC_UNCOR_ERROR:81		return -EBADMSG;82	default:83		break;84	}85 86	/* At this point values greater than (2 << 4) are invalid  */87	if (status > XT26G0XA_STATUS_ECC_UNCOR_ERROR)88		return -EINVAL;89 90	/* (1 << 2) through (7 << 2) are 1-7 corrected errors */91	return status >> 2;92}93 94static int xt26xxxd_ooblayout_ecc(struct mtd_info *mtd, int section,95				  struct mtd_oob_region *region)96{97	if (section)98		return -ERANGE;99 100	region->offset = mtd->oobsize / 2;101	region->length = mtd->oobsize / 2;102 103	return 0;104}105 106static int xt26xxxd_ooblayout_free(struct mtd_info *mtd, int section,107				   struct mtd_oob_region *region)108{109	if (section)110		return -ERANGE;111 112	region->offset = 2;113	region->length = mtd->oobsize / 2 - 2;114 115	return 0;116}117 118static const struct mtd_ooblayout_ops xt26xxxd_ooblayout = {119	.ecc = xt26xxxd_ooblayout_ecc,120	.free = xt26xxxd_ooblayout_free,121};122 123static int xt26xxxd_ecc_get_status(struct spinand_device *spinand,124				   u8 status)125{126	switch (FIELD_GET(STATUS_ECC_MASK, status)) {127	case XT26XXXD_STATUS_ECC_NO_DETECTED:128		return 0;129	case XT26XXXD_STATUS_ECC_UNCOR_ERROR:130		return -EBADMSG;131	case XT26XXXD_STATUS_ECC_1_7_CORRECTED:132		return 4 + FIELD_GET(XT26XXXD_STATUS_ECC3_ECC2_MASK, status);133	case XT26XXXD_STATUS_ECC_8_CORRECTED:134		return 8;135	default:136		break;137	}138 139	return -EINVAL;140}141static const struct spinand_info xtx_spinand_table[] = {142	SPINAND_INFO("XT26G01A",143		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0xE1),144		     NAND_MEMORG(1, 2048, 64, 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		     SPINAND_HAS_QE_BIT,150		     SPINAND_ECCINFO(&xt26g0xa_ooblayout,151				     xt26g0xa_ecc_get_status)),152	SPINAND_INFO("XT26G02A",153		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0xE2),154		     NAND_MEMORG(1, 2048, 64, 64, 2048, 40, 1, 1, 1),155		     NAND_ECCREQ(8, 512),156		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,157					      &write_cache_variants,158					      &update_cache_variants),159		     SPINAND_HAS_QE_BIT,160		     SPINAND_ECCINFO(&xt26g0xa_ooblayout,161				     xt26g0xa_ecc_get_status)),162	SPINAND_INFO("XT26G04A",163		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0xE3),164		     NAND_MEMORG(1, 2048, 64, 128, 2048, 40, 1, 1, 1),165		     NAND_ECCREQ(8, 512),166		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,167					      &write_cache_variants,168					      &update_cache_variants),169		     SPINAND_HAS_QE_BIT,170		     SPINAND_ECCINFO(&xt26g0xa_ooblayout,171				     xt26g0xa_ecc_get_status)),172	SPINAND_INFO("XT26G01D",173		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0x31),174		     NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),175		     NAND_ECCREQ(8, 512),176		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,177					      &write_cache_variants,178					      &update_cache_variants),179		     0,180		     SPINAND_ECCINFO(&xt26xxxd_ooblayout,181				     xt26xxxd_ecc_get_status)),182	SPINAND_INFO("XT26G11D",183		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0x34),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_variants,188					      &update_cache_variants),189		     0,190		     SPINAND_ECCINFO(&xt26xxxd_ooblayout,191				     xt26xxxd_ecc_get_status)),192	SPINAND_INFO("XT26Q01D",193		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0x51),194		     NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),195		     NAND_ECCREQ(8, 512),196		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,197					      &write_cache_variants,198					      &update_cache_variants),199		     0,200		     SPINAND_ECCINFO(&xt26xxxd_ooblayout,201				     xt26xxxd_ecc_get_status)),202	SPINAND_INFO("XT26G02D",203		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0x32),204		     NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1),205		     NAND_ECCREQ(8, 512),206		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,207					      &write_cache_variants,208					      &update_cache_variants),209		     0,210		     SPINAND_ECCINFO(&xt26xxxd_ooblayout,211				     xt26xxxd_ecc_get_status)),212	SPINAND_INFO("XT26G12D",213		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0x35),214		     NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1),215		     NAND_ECCREQ(8, 512),216		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,217					      &write_cache_variants,218					      &update_cache_variants),219		     0,220		     SPINAND_ECCINFO(&xt26xxxd_ooblayout,221				     xt26xxxd_ecc_get_status)),222	SPINAND_INFO("XT26Q02D",223		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0x52),224		     NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1),225		     NAND_ECCREQ(8, 512),226		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,227					      &write_cache_variants,228					      &update_cache_variants),229		     0,230		     SPINAND_ECCINFO(&xt26xxxd_ooblayout,231				     xt26xxxd_ecc_get_status)),232	SPINAND_INFO("XT26G04D",233		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0x33),234		     NAND_MEMORG(1, 4096, 256, 64, 2048, 40, 1, 1, 1),235		     NAND_ECCREQ(8, 512),236		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,237					      &write_cache_variants,238					      &update_cache_variants),239		     0,240		     SPINAND_ECCINFO(&xt26xxxd_ooblayout,241				     xt26xxxd_ecc_get_status)),242	SPINAND_INFO("XT26Q04D",243		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0x53),244		     NAND_MEMORG(1, 4096, 256, 64, 2048, 40, 1, 1, 1),245		     NAND_ECCREQ(8, 512),246		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,247					      &write_cache_variants,248					      &update_cache_variants),249		     0,250		     SPINAND_ECCINFO(&xt26xxxd_ooblayout,251				     xt26xxxd_ecc_get_status)),252};253 254static const struct spinand_manufacturer_ops xtx_spinand_manuf_ops = {255};256 257const struct spinand_manufacturer xtx_spinand_manufacturer = {258	.id = SPINAND_MFR_XTX,259	.name = "XTX",260	.chips = xtx_spinand_table,261	.nchips = ARRAY_SIZE(xtx_spinand_table),262	.ops = &xtx_spinand_manuf_ops,263};264