Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Copyright (c) 2018 exceet electronics GmbH
0004  * Copyright (c) 2018 Kontron Electronics GmbH
0005  *
0006  * Author: Frieder Schrempf <frieder.schrempf@kontron.de>
0007  */
0008 
0009 #include <linux/device.h>
0010 #include <linux/kernel.h>
0011 #include <linux/mtd/spinand.h>
0012 
0013 /* Kioxia is new name of Toshiba memory. */
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  * Backward compatibility for 1st generation Serial NAND devices
0033  * which don't support Quad Program Load operation.
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     /* 2 bytes reserved for BBM */
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          * Let's try to retrieve the real maximum number of bitflips
0089          * in order to avoid forcing the wear-leveling layer to move
0090          * data around if it's not necessary.
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     /* 3.3V 1Gb (1st generation) */
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     /* 3.3V 2Gb (1st generation) */
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     /* 3.3V 4Gb (1st generation) */
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     /* 1.8V 1Gb (1st generation) */
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     /* 1.8V 2Gb (1st generation) */
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     /* 1.8V 4Gb (1st generation) */
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      * 2nd generation serial nand has HOLD_D which is equivalent to
0179      * QE_BIT.
0180      */
0181     /* 3.3V 1Gb (2nd generation) */
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     /* 3.3V 2Gb (2nd generation) */
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     /* 3.3V 4Gb (2nd generation) */
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     /* 3.3V 8Gb (2nd generation) */
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     /* 1.8V 1Gb (2nd generation) */
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     /* 1.8V 2Gb (2nd generation) */
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     /* 1.8V 4Gb (2nd generation) */
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     /* 1.8V 8Gb (2nd generation) */
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 };