0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/device.h>
0010 #include <linux/kernel.h>
0011 #include <linux/mtd/spinand.h>
0012
0013
0014 #define SPINAND_MFR_TOSHIBA 0x98
0015 #define TOSH_STATUS_ECC_HAS_BITFLIPS_T (3 << 4)
0016
0017 static SPINAND_OP_VARIANTS(read_cache_variants,
0018 SPINAND_PAGE_READ_FROM_CACHE_X4_OP(0, 1, NULL, 0),
0019 SPINAND_PAGE_READ_FROM_CACHE_X2_OP(0, 1, NULL, 0),
0020 SPINAND_PAGE_READ_FROM_CACHE_OP(true, 0, 1, NULL, 0),
0021 SPINAND_PAGE_READ_FROM_CACHE_OP(false, 0, 1, NULL, 0));
0022
0023 static SPINAND_OP_VARIANTS(write_cache_x4_variants,
0024 SPINAND_PROG_LOAD_X4(true, 0, NULL, 0),
0025 SPINAND_PROG_LOAD(true, 0, NULL, 0));
0026
0027 static SPINAND_OP_VARIANTS(update_cache_x4_variants,
0028 SPINAND_PROG_LOAD_X4(false, 0, NULL, 0),
0029 SPINAND_PROG_LOAD(false, 0, NULL, 0));
0030
0031
0032
0033
0034
0035 static SPINAND_OP_VARIANTS(write_cache_variants,
0036 SPINAND_PROG_LOAD(true, 0, NULL, 0));
0037
0038 static SPINAND_OP_VARIANTS(update_cache_variants,
0039 SPINAND_PROG_LOAD(false, 0, NULL, 0));
0040
0041 static int tx58cxgxsxraix_ooblayout_ecc(struct mtd_info *mtd, int section,
0042 struct mtd_oob_region *region)
0043 {
0044 if (section > 0)
0045 return -ERANGE;
0046
0047 region->offset = mtd->oobsize / 2;
0048 region->length = mtd->oobsize / 2;
0049
0050 return 0;
0051 }
0052
0053 static int tx58cxgxsxraix_ooblayout_free(struct mtd_info *mtd, int section,
0054 struct mtd_oob_region *region)
0055 {
0056 if (section > 0)
0057 return -ERANGE;
0058
0059
0060 region->offset = 2;
0061 region->length = (mtd->oobsize / 2) - 2;
0062
0063 return 0;
0064 }
0065
0066 static const struct mtd_ooblayout_ops tx58cxgxsxraix_ooblayout = {
0067 .ecc = tx58cxgxsxraix_ooblayout_ecc,
0068 .free = tx58cxgxsxraix_ooblayout_free,
0069 };
0070
0071 static int tx58cxgxsxraix_ecc_get_status(struct spinand_device *spinand,
0072 u8 status)
0073 {
0074 struct nand_device *nand = spinand_to_nand(spinand);
0075 u8 mbf = 0;
0076 struct spi_mem_op op = SPINAND_GET_FEATURE_OP(0x30, &mbf);
0077
0078 switch (status & STATUS_ECC_MASK) {
0079 case STATUS_ECC_NO_BITFLIPS:
0080 return 0;
0081
0082 case STATUS_ECC_UNCOR_ERROR:
0083 return -EBADMSG;
0084
0085 case STATUS_ECC_HAS_BITFLIPS:
0086 case TOSH_STATUS_ECC_HAS_BITFLIPS_T:
0087
0088
0089
0090
0091
0092 if (spi_mem_exec_op(spinand->spimem, &op))
0093 return nanddev_get_ecc_conf(nand)->strength;
0094
0095 mbf >>= 4;
0096
0097 if (WARN_ON(mbf > nanddev_get_ecc_conf(nand)->strength || !mbf))
0098 return nanddev_get_ecc_conf(nand)->strength;
0099
0100 return mbf;
0101
0102 default:
0103 break;
0104 }
0105
0106 return -EINVAL;
0107 }
0108
0109 static const struct spinand_info toshiba_spinand_table[] = {
0110
0111 SPINAND_INFO("TC58CVG0S3HRAIG",
0112 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xC2),
0113 NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),
0114 NAND_ECCREQ(8, 512),
0115 SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
0116 &write_cache_variants,
0117 &update_cache_variants),
0118 0,
0119 SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout,
0120 tx58cxgxsxraix_ecc_get_status)),
0121
0122 SPINAND_INFO("TC58CVG1S3HRAIG",
0123 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xCB),
0124 NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1),
0125 NAND_ECCREQ(8, 512),
0126 SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
0127 &write_cache_variants,
0128 &update_cache_variants),
0129 0,
0130 SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout,
0131 tx58cxgxsxraix_ecc_get_status)),
0132
0133 SPINAND_INFO("TC58CVG2S0HRAIG",
0134 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xCD),
0135 NAND_MEMORG(1, 4096, 256, 64, 2048, 40, 1, 1, 1),
0136 NAND_ECCREQ(8, 512),
0137 SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
0138 &write_cache_variants,
0139 &update_cache_variants),
0140 0,
0141 SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout,
0142 tx58cxgxsxraix_ecc_get_status)),
0143
0144 SPINAND_INFO("TC58CYG0S3HRAIG",
0145 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xB2),
0146 NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),
0147 NAND_ECCREQ(8, 512),
0148 SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
0149 &write_cache_variants,
0150 &update_cache_variants),
0151 0,
0152 SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout,
0153 tx58cxgxsxraix_ecc_get_status)),
0154
0155 SPINAND_INFO("TC58CYG1S3HRAIG",
0156 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xBB),
0157 NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1),
0158 NAND_ECCREQ(8, 512),
0159 SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
0160 &write_cache_variants,
0161 &update_cache_variants),
0162 0,
0163 SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout,
0164 tx58cxgxsxraix_ecc_get_status)),
0165
0166 SPINAND_INFO("TC58CYG2S0HRAIG",
0167 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xBD),
0168 NAND_MEMORG(1, 4096, 256, 64, 2048, 40, 1, 1, 1),
0169 NAND_ECCREQ(8, 512),
0170 SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
0171 &write_cache_variants,
0172 &update_cache_variants),
0173 0,
0174 SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout,
0175 tx58cxgxsxraix_ecc_get_status)),
0176
0177
0178
0179
0180
0181
0182 SPINAND_INFO("TC58CVG0S3HRAIJ",
0183 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xE2),
0184 NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),
0185 NAND_ECCREQ(8, 512),
0186 SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
0187 &write_cache_x4_variants,
0188 &update_cache_x4_variants),
0189 SPINAND_HAS_QE_BIT,
0190 SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout,
0191 tx58cxgxsxraix_ecc_get_status)),
0192
0193 SPINAND_INFO("TC58CVG1S3HRAIJ",
0194 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xEB),
0195 NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1),
0196 NAND_ECCREQ(8, 512),
0197 SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
0198 &write_cache_x4_variants,
0199 &update_cache_x4_variants),
0200 SPINAND_HAS_QE_BIT,
0201 SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout,
0202 tx58cxgxsxraix_ecc_get_status)),
0203
0204 SPINAND_INFO("TC58CVG2S0HRAIJ",
0205 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xED),
0206 NAND_MEMORG(1, 4096, 256, 64, 2048, 40, 1, 1, 1),
0207 NAND_ECCREQ(8, 512),
0208 SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
0209 &write_cache_x4_variants,
0210 &update_cache_x4_variants),
0211 SPINAND_HAS_QE_BIT,
0212 SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout,
0213 tx58cxgxsxraix_ecc_get_status)),
0214
0215 SPINAND_INFO("TH58CVG3S0HRAIJ",
0216 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xE4),
0217 NAND_MEMORG(1, 4096, 256, 64, 4096, 80, 1, 1, 1),
0218 NAND_ECCREQ(8, 512),
0219 SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
0220 &write_cache_x4_variants,
0221 &update_cache_x4_variants),
0222 SPINAND_HAS_QE_BIT,
0223 SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout,
0224 tx58cxgxsxraix_ecc_get_status)),
0225
0226 SPINAND_INFO("TC58CYG0S3HRAIJ",
0227 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xD2),
0228 NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),
0229 NAND_ECCREQ(8, 512),
0230 SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
0231 &write_cache_x4_variants,
0232 &update_cache_x4_variants),
0233 SPINAND_HAS_QE_BIT,
0234 SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout,
0235 tx58cxgxsxraix_ecc_get_status)),
0236
0237 SPINAND_INFO("TC58CYG1S3HRAIJ",
0238 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xDB),
0239 NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1),
0240 NAND_ECCREQ(8, 512),
0241 SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
0242 &write_cache_x4_variants,
0243 &update_cache_x4_variants),
0244 SPINAND_HAS_QE_BIT,
0245 SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout,
0246 tx58cxgxsxraix_ecc_get_status)),
0247
0248 SPINAND_INFO("TC58CYG2S0HRAIJ",
0249 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xDD),
0250 NAND_MEMORG(1, 4096, 256, 64, 2048, 40, 1, 1, 1),
0251 NAND_ECCREQ(8, 512),
0252 SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
0253 &write_cache_x4_variants,
0254 &update_cache_x4_variants),
0255 SPINAND_HAS_QE_BIT,
0256 SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout,
0257 tx58cxgxsxraix_ecc_get_status)),
0258
0259 SPINAND_INFO("TH58CYG3S0HRAIJ",
0260 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xD4),
0261 NAND_MEMORG(1, 4096, 256, 64, 4096, 80, 1, 1, 1),
0262 NAND_ECCREQ(8, 512),
0263 SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
0264 &write_cache_x4_variants,
0265 &update_cache_x4_variants),
0266 SPINAND_HAS_QE_BIT,
0267 SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout,
0268 tx58cxgxsxraix_ecc_get_status)),
0269 };
0270
0271 static const struct spinand_manufacturer_ops toshiba_spinand_manuf_ops = {
0272 };
0273
0274 const struct spinand_manufacturer toshiba_spinand_manufacturer = {
0275 .id = SPINAND_MFR_TOSHIBA,
0276 .name = "Toshiba",
0277 .chips = toshiba_spinand_table,
0278 .nchips = ARRAY_SIZE(toshiba_spinand_table),
0279 .ops = &toshiba_spinand_manuf_ops,
0280 };