linux/drivers/mtd/nand/spi/toshiba.c
<<
>>
Prefs
   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_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 devices
  33 * 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, &mbf);
  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 >>= 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};
 270
 271static const struct spinand_manufacturer_ops toshiba_spinand_manuf_ops = {
 272};
 273
 274const struct spinand_manufacturer toshiba_spinand_manufacturer = {
 275        .id = SPINAND_MFR_TOSHIBA,
 276        .name = "Toshiba",
 277        .chips = toshiba_spinand_table,
 278        .nchips = ARRAY_SIZE(toshiba_spinand_table),
 279        .ops = &toshiba_spinand_manuf_ops,
 280};
 281