444 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Copyright (c) 2018 Macronix4 *5 * Author: Boris Brezillon <boris.brezillon@bootlin.com>6 */7 8#include <linux/bitfield.h>9#include <linux/device.h>10#include <linux/kernel.h>11#include <linux/mtd/spinand.h>12 13#define SPINAND_MFR_MACRONIX 0xC214#define MACRONIX_ECCSR_BF_LAST_PAGE(eccsr) FIELD_GET(GENMASK(3, 0), eccsr)15#define MACRONIX_ECCSR_BF_ACCUMULATED_PAGES(eccsr) FIELD_GET(GENMASK(7, 4), eccsr)16#define MACRONIX_CFG_CONT_READ BIT(2)17 18#define STATUS_ECC_HAS_BITFLIPS_THRESHOLD (3 << 4)19 20/* Bitflip theshold configuration register */21#define REG_CFG_BFT 0x1022#define CFG_BFT(x) FIELD_PREP(GENMASK(7, 4), (x))23 24struct macronix_priv {25 bool cont_read;26};27 28static SPINAND_OP_VARIANTS(read_cache_variants,29 SPINAND_PAGE_READ_FROM_CACHE_X4_OP(0, 1, NULL, 0),30 SPINAND_PAGE_READ_FROM_CACHE_X2_OP(0, 1, NULL, 0),31 SPINAND_PAGE_READ_FROM_CACHE_OP(true, 0, 1, NULL, 0),32 SPINAND_PAGE_READ_FROM_CACHE_OP(false, 0, 1, NULL, 0));33 34static SPINAND_OP_VARIANTS(write_cache_variants,35 SPINAND_PROG_LOAD_X4(true, 0, NULL, 0),36 SPINAND_PROG_LOAD(false, 0, NULL, 0));37 38static SPINAND_OP_VARIANTS(update_cache_variants,39 SPINAND_PROG_LOAD_X4(false, 0, NULL, 0),40 SPINAND_PROG_LOAD(false, 0, NULL, 0));41 42static int mx35lfxge4ab_ooblayout_ecc(struct mtd_info *mtd, int section,43 struct mtd_oob_region *region)44{45 return -ERANGE;46}47 48static int mx35lfxge4ab_ooblayout_free(struct mtd_info *mtd, int section,49 struct mtd_oob_region *region)50{51 if (section)52 return -ERANGE;53 54 region->offset = 2;55 region->length = mtd->oobsize - 2;56 57 return 0;58}59 60static const struct mtd_ooblayout_ops mx35lfxge4ab_ooblayout = {61 .ecc = mx35lfxge4ab_ooblayout_ecc,62 .free = mx35lfxge4ab_ooblayout_free,63};64 65static int macronix_get_eccsr(struct spinand_device *spinand, u8 *eccsr)66{67 struct macronix_priv *priv = spinand->priv;68 struct spi_mem_op op = SPI_MEM_OP(SPI_MEM_OP_CMD(0x7c, 1),69 SPI_MEM_OP_NO_ADDR,70 SPI_MEM_OP_DUMMY(1, 1),71 SPI_MEM_OP_DATA_IN(1, eccsr, 1));72 73 int ret = spi_mem_exec_op(spinand->spimem, &op);74 if (ret)75 return ret;76 77 /*78 * ECCSR exposes the number of bitflips for the last read page in bits [3:0].79 * Continuous read compatible chips also expose the maximum number of80 * bitflips for the whole (continuous) read operation in bits [7:4].81 */82 if (!priv->cont_read)83 *eccsr = MACRONIX_ECCSR_BF_LAST_PAGE(*eccsr);84 else85 *eccsr = MACRONIX_ECCSR_BF_ACCUMULATED_PAGES(*eccsr);86 87 return 0;88}89 90static int macronix_ecc_get_status(struct spinand_device *spinand,91 u8 status)92{93 struct nand_device *nand = spinand_to_nand(spinand);94 u8 eccsr;95 96 switch (status & STATUS_ECC_MASK) {97 case STATUS_ECC_NO_BITFLIPS:98 return 0;99 100 case STATUS_ECC_UNCOR_ERROR:101 return -EBADMSG;102 103 case STATUS_ECC_HAS_BITFLIPS:104 /*105 * Let's try to retrieve the real maximum number of bitflips106 * in order to avoid forcing the wear-leveling layer to move107 * data around if it's not necessary.108 */109 if (macronix_get_eccsr(spinand, spinand->scratchbuf))110 return nanddev_get_ecc_conf(nand)->strength;111 112 eccsr = *spinand->scratchbuf;113 if (WARN_ON(eccsr > nanddev_get_ecc_conf(nand)->strength || !eccsr))114 return nanddev_get_ecc_conf(nand)->strength;115 116 return eccsr;117 default:118 break;119 }120 121 return -EINVAL;122}123 124static int macronix_set_cont_read(struct spinand_device *spinand, bool enable)125{126 struct macronix_priv *priv = spinand->priv;127 int ret;128 129 ret = spinand_upd_cfg(spinand, MACRONIX_CFG_CONT_READ,130 enable ? MACRONIX_CFG_CONT_READ : 0);131 if (ret)132 return ret;133 134 priv->cont_read = enable;135 136 return 0;137}138 139static const struct spinand_info macronix_spinand_table[] = {140 SPINAND_INFO("MX35LF1GE4AB",141 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x12),142 NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1),143 NAND_ECCREQ(4, 512),144 SPINAND_INFO_OP_VARIANTS(&read_cache_variants,145 &write_cache_variants,146 &update_cache_variants),147 SPINAND_HAS_QE_BIT,148 SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,149 macronix_ecc_get_status)),150 SPINAND_INFO("MX35LF2GE4AB",151 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x22),152 NAND_MEMORG(1, 2048, 64, 64, 2048, 40, 2, 1, 1),153 NAND_ECCREQ(4, 512),154 SPINAND_INFO_OP_VARIANTS(&read_cache_variants,155 &write_cache_variants,156 &update_cache_variants),157 SPINAND_HAS_QE_BIT |158 SPINAND_HAS_PROG_PLANE_SELECT_BIT |159 SPINAND_HAS_READ_PLANE_SELECT_BIT,160 SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout, NULL)),161 SPINAND_INFO("MX35LF2GE4AD",162 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x26, 0x03),163 NAND_MEMORG(1, 2048, 64, 64, 2048, 40, 1, 1, 1),164 NAND_ECCREQ(8, 512),165 SPINAND_INFO_OP_VARIANTS(&read_cache_variants,166 &write_cache_variants,167 &update_cache_variants),168 SPINAND_HAS_QE_BIT,169 SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,170 macronix_ecc_get_status),171 SPINAND_CONT_READ(macronix_set_cont_read)),172 SPINAND_INFO("MX35LF4GE4AD",173 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x37, 0x03),174 NAND_MEMORG(1, 4096, 128, 64, 2048, 40, 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 SPINAND_HAS_QE_BIT,180 SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,181 macronix_ecc_get_status),182 SPINAND_CONT_READ(macronix_set_cont_read)),183 SPINAND_INFO("MX35LF1G24AD",184 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x14, 0x03),185 NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),186 NAND_ECCREQ(8, 512),187 SPINAND_INFO_OP_VARIANTS(&read_cache_variants,188 &write_cache_variants,189 &update_cache_variants),190 SPINAND_HAS_QE_BIT,191 SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout, NULL)),192 SPINAND_INFO("MX35LF2G24AD",193 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x24, 0x03),194 NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 2, 1, 1),195 NAND_ECCREQ(8, 512),196 SPINAND_INFO_OP_VARIANTS(&read_cache_variants,197 &write_cache_variants,198 &update_cache_variants),199 SPINAND_HAS_QE_BIT |200 SPINAND_HAS_PROG_PLANE_SELECT_BIT,201 SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout, NULL)),202 SPINAND_INFO("MX35LF2G24AD-Z4I8",203 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x64, 0x03),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 SPINAND_HAS_QE_BIT,210 SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout, NULL)),211 SPINAND_INFO("MX35LF4G24AD",212 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x35, 0x03),213 NAND_MEMORG(1, 4096, 256, 64, 2048, 40, 2, 1, 1),214 NAND_ECCREQ(8, 512),215 SPINAND_INFO_OP_VARIANTS(&read_cache_variants,216 &write_cache_variants,217 &update_cache_variants),218 SPINAND_HAS_QE_BIT |219 SPINAND_HAS_PROG_PLANE_SELECT_BIT,220 SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout, NULL)),221 SPINAND_INFO("MX35LF4G24AD-Z4I8",222 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x75, 0x03),223 NAND_MEMORG(1, 4096, 256, 64, 2048, 40, 1, 1, 1),224 NAND_ECCREQ(8, 512),225 SPINAND_INFO_OP_VARIANTS(&read_cache_variants,226 &write_cache_variants,227 &update_cache_variants),228 SPINAND_HAS_QE_BIT,229 SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout, NULL)),230 SPINAND_INFO("MX31LF1GE4BC",231 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x1e),232 NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1),233 NAND_ECCREQ(8, 512),234 SPINAND_INFO_OP_VARIANTS(&read_cache_variants,235 &write_cache_variants,236 &update_cache_variants),237 SPINAND_HAS_QE_BIT,238 SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,239 macronix_ecc_get_status)),240 SPINAND_INFO("MX31UF1GE4BC",241 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x9e),242 NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1),243 NAND_ECCREQ(8, 512),244 SPINAND_INFO_OP_VARIANTS(&read_cache_variants,245 &write_cache_variants,246 &update_cache_variants),247 SPINAND_HAS_QE_BIT,248 SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,249 macronix_ecc_get_status)),250 251 SPINAND_INFO("MX35LF2G14AC",252 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x20),253 NAND_MEMORG(1, 2048, 64, 64, 2048, 40, 2, 1, 1),254 NAND_ECCREQ(4, 512),255 SPINAND_INFO_OP_VARIANTS(&read_cache_variants,256 &write_cache_variants,257 &update_cache_variants),258 SPINAND_HAS_QE_BIT |259 SPINAND_HAS_PROG_PLANE_SELECT_BIT |260 SPINAND_HAS_READ_PLANE_SELECT_BIT,261 SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,262 macronix_ecc_get_status)),263 SPINAND_INFO("MX35UF4G24AD",264 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xb5, 0x03),265 NAND_MEMORG(1, 4096, 256, 64, 2048, 40, 2, 1, 1),266 NAND_ECCREQ(8, 512),267 SPINAND_INFO_OP_VARIANTS(&read_cache_variants,268 &write_cache_variants,269 &update_cache_variants),270 SPINAND_HAS_QE_BIT |271 SPINAND_HAS_PROG_PLANE_SELECT_BIT,272 SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,273 macronix_ecc_get_status)),274 SPINAND_INFO("MX35UF4G24AD-Z4I8",275 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xf5, 0x03),276 NAND_MEMORG(1, 4096, 256, 64, 2048, 40, 1, 1, 1),277 NAND_ECCREQ(8, 512),278 SPINAND_INFO_OP_VARIANTS(&read_cache_variants,279 &write_cache_variants,280 &update_cache_variants),281 SPINAND_HAS_QE_BIT,282 SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,283 macronix_ecc_get_status)),284 SPINAND_INFO("MX35UF4GE4AD",285 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xb7, 0x03),286 NAND_MEMORG(1, 4096, 256, 64, 2048, 40, 1, 1, 1),287 NAND_ECCREQ(8, 512),288 SPINAND_INFO_OP_VARIANTS(&read_cache_variants,289 &write_cache_variants,290 &update_cache_variants),291 SPINAND_HAS_QE_BIT,292 SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,293 macronix_ecc_get_status),294 SPINAND_CONT_READ(macronix_set_cont_read)),295 SPINAND_INFO("MX35UF2G14AC",296 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xa0),297 NAND_MEMORG(1, 2048, 64, 64, 2048, 40, 2, 1, 1),298 NAND_ECCREQ(4, 512),299 SPINAND_INFO_OP_VARIANTS(&read_cache_variants,300 &write_cache_variants,301 &update_cache_variants),302 SPINAND_HAS_QE_BIT |303 SPINAND_HAS_PROG_PLANE_SELECT_BIT |304 SPINAND_HAS_READ_PLANE_SELECT_BIT,305 SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,306 macronix_ecc_get_status)),307 SPINAND_INFO("MX35UF2G24AD",308 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xa4, 0x03),309 NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 2, 1, 1),310 NAND_ECCREQ(8, 512),311 SPINAND_INFO_OP_VARIANTS(&read_cache_variants,312 &write_cache_variants,313 &update_cache_variants),314 SPINAND_HAS_QE_BIT |315 SPINAND_HAS_PROG_PLANE_SELECT_BIT,316 SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,317 macronix_ecc_get_status)),318 SPINAND_INFO("MX35UF2G24AD-Z4I8",319 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xe4, 0x03),320 NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1),321 NAND_ECCREQ(8, 512),322 SPINAND_INFO_OP_VARIANTS(&read_cache_variants,323 &write_cache_variants,324 &update_cache_variants),325 SPINAND_HAS_QE_BIT,326 SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,327 macronix_ecc_get_status)),328 SPINAND_INFO("MX35UF2GE4AD",329 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xa6, 0x03),330 NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1),331 NAND_ECCREQ(8, 512),332 SPINAND_INFO_OP_VARIANTS(&read_cache_variants,333 &write_cache_variants,334 &update_cache_variants),335 SPINAND_HAS_QE_BIT,336 SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,337 macronix_ecc_get_status),338 SPINAND_CONT_READ(macronix_set_cont_read)),339 SPINAND_INFO("MX35UF2GE4AC",340 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xa2, 0x01),341 NAND_MEMORG(1, 2048, 64, 64, 2048, 40, 1, 1, 1),342 NAND_ECCREQ(4, 512),343 SPINAND_INFO_OP_VARIANTS(&read_cache_variants,344 &write_cache_variants,345 &update_cache_variants),346 SPINAND_HAS_QE_BIT,347 SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,348 macronix_ecc_get_status),349 SPINAND_CONT_READ(macronix_set_cont_read)),350 SPINAND_INFO("MX35UF1G14AC",351 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x90),352 NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1),353 NAND_ECCREQ(4, 512),354 SPINAND_INFO_OP_VARIANTS(&read_cache_variants,355 &write_cache_variants,356 &update_cache_variants),357 SPINAND_HAS_QE_BIT,358 SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,359 macronix_ecc_get_status)),360 SPINAND_INFO("MX35UF1G24AD",361 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x94, 0x03),362 NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),363 NAND_ECCREQ(8, 512),364 SPINAND_INFO_OP_VARIANTS(&read_cache_variants,365 &write_cache_variants,366 &update_cache_variants),367 SPINAND_HAS_QE_BIT,368 SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,369 macronix_ecc_get_status)),370 SPINAND_INFO("MX35UF1GE4AD",371 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x96, 0x03),372 NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),373 NAND_ECCREQ(8, 512),374 SPINAND_INFO_OP_VARIANTS(&read_cache_variants,375 &write_cache_variants,376 &update_cache_variants),377 SPINAND_HAS_QE_BIT,378 SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,379 macronix_ecc_get_status),380 SPINAND_CONT_READ(macronix_set_cont_read)),381 SPINAND_INFO("MX35UF1GE4AC",382 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x92, 0x01),383 NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1),384 NAND_ECCREQ(4, 512),385 SPINAND_INFO_OP_VARIANTS(&read_cache_variants,386 &write_cache_variants,387 &update_cache_variants),388 SPINAND_HAS_QE_BIT,389 SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,390 macronix_ecc_get_status),391 SPINAND_CONT_READ(macronix_set_cont_read)),392 SPINAND_INFO("MX31LF2GE4BC",393 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x2e),394 NAND_MEMORG(1, 2048, 64, 64, 2048, 40, 1, 1, 1),395 NAND_ECCREQ(8, 512),396 SPINAND_INFO_OP_VARIANTS(&read_cache_variants,397 &write_cache_variants,398 &update_cache_variants),399 SPINAND_HAS_QE_BIT,400 SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,401 macronix_ecc_get_status)),402 SPINAND_INFO("MX3UF2GE4BC",403 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xae),404 NAND_MEMORG(1, 2048, 64, 64, 2048, 40, 1, 1, 1),405 NAND_ECCREQ(8, 512),406 SPINAND_INFO_OP_VARIANTS(&read_cache_variants,407 &write_cache_variants,408 &update_cache_variants),409 SPINAND_HAS_QE_BIT,410 SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,411 macronix_ecc_get_status)),412};413 414static int macronix_spinand_init(struct spinand_device *spinand)415{416 struct macronix_priv *priv;417 418 priv = kzalloc(sizeof(*priv), GFP_KERNEL);419 if (!priv)420 return -ENOMEM;421 422 spinand->priv = priv;423 424 return 0;425}426 427static void macronix_spinand_cleanup(struct spinand_device *spinand)428{429 kfree(spinand->priv);430}431 432static const struct spinand_manufacturer_ops macronix_spinand_manuf_ops = {433 .init = macronix_spinand_init,434 .cleanup = macronix_spinand_cleanup,435};436 437const struct spinand_manufacturer macronix_spinand_manufacturer = {438 .id = SPINAND_MFR_MACRONIX,439 .name = "Macronix",440 .chips = macronix_spinand_table,441 .nchips = ARRAY_SIZE(macronix_spinand_table),442 .ops = ¯onix_spinand_manuf_ops,443};444