Messages in this thread | | | Date | Wed, 15 Sep 2021 10:13:12 +0200 | Subject | Re: [PATCH v2] mtd: spinand: Add support for Etron EM73D044VCx | From | Frieder Schrempf <> |
| |
Hi Bert,
On 08.09.21 22:16, Bert Vermeulen wrote: > This adds a new vendor Etron, and support for a 2Gb chip. > > The datasheet is available at > https://eur04.safelinks.protection.outlook.com/?url=https%3A%2F%2Fwww.etron.com%2Fcn%2Fproducts%2FEM73%255B8%255DC%255BD_E_F%255DVC%2520SPI%2520NAND%2520Flash_Promotion_Rev%25201_00A.pdf&data=04%7C01%7Cfrieder.schrempf%40kontron.de%7C871fa2a364d8484bbc0d08d97305f2f4%7C8c9d3c973fd941c8a2b1646f3942daf1%7C0%7C0%7C637667293724201439%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&sdata=SeopP6Mvu1CHj6eB22XlO78NGnMc3hCFzM%2F5jKmJZxU%3D&reserved=0 > > Signed-off-by: Bert Vermeulen <bert@biot.com> > --- > v2: > - Made ooblayout_free/_ecc depend on chip-specific parameters, instead of > hardcoded to this 2Gb chip only > - Fixed manufacturer ordering > - Fixed minor formatting issues as reported > - Removed debug comment > > drivers/mtd/nand/spi/Makefile | 2 +- > drivers/mtd/nand/spi/core.c | 1 + > drivers/mtd/nand/spi/etron.c | 104 ++++++++++++++++++++++++++++++++++ > include/linux/mtd/spinand.h | 1 + > 4 files changed, 107 insertions(+), 1 deletion(-) > create mode 100644 drivers/mtd/nand/spi/etron.c > > diff --git a/drivers/mtd/nand/spi/Makefile b/drivers/mtd/nand/spi/Makefile > index 9662b9c1d5a9..cc3c4e046ea9 100644 > --- a/drivers/mtd/nand/spi/Makefile > +++ b/drivers/mtd/nand/spi/Makefile > @@ -1,3 +1,3 @@ > # SPDX-License-Identifier: GPL-2.0 > -spinand-objs := core.o gigadevice.o macronix.o micron.o paragon.o toshiba.o winbond.o > +spinand-objs := core.o etron.o gigadevice.o macronix.o micron.o paragon.o toshiba.o winbond.o > obj-$(CONFIG_MTD_SPI_NAND) += spinand.o > diff --git a/drivers/mtd/nand/spi/core.c b/drivers/mtd/nand/spi/core.c > index 446ba8d43fbc..2cbf25b8caa2 100644 > --- a/drivers/mtd/nand/spi/core.c > +++ b/drivers/mtd/nand/spi/core.c > @@ -894,6 +894,7 @@ static const struct nand_ops spinand_ops = { > }; > > static const struct spinand_manufacturer *spinand_manufacturers[] = { > + &etron_spinand_manufacturer, > &gigadevice_spinand_manufacturer, > ¯onix_spinand_manufacturer, > µn_spinand_manufacturer, > diff --git a/drivers/mtd/nand/spi/etron.c b/drivers/mtd/nand/spi/etron.c > new file mode 100644 > index 000000000000..1a92b9cf3043 > --- /dev/null > +++ b/drivers/mtd/nand/spi/etron.c > @@ -0,0 +1,104 @@ > +// SPDX-License-Identifier: GPL-2.0 > + > +#include <linux/device.h> > +#include <linux/kernel.h> > +#include <linux/mtd/spinand.h> > + > +#define SPINAND_MFR_ETRON 0xd5 > + > +static SPINAND_OP_VARIANTS(read_cache_variants, > + SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP(0, 1, NULL, 0), > + SPINAND_PAGE_READ_FROM_CACHE_X4_OP(0, 1, NULL, 0), > + SPINAND_PAGE_READ_FROM_CACHE_DUALIO_OP(0, 1, NULL, 0), > + SPINAND_PAGE_READ_FROM_CACHE_X2_OP(0, 1, NULL, 0), > + SPINAND_PAGE_READ_FROM_CACHE_OP(true, 0, 1, NULL, 0), > + SPINAND_PAGE_READ_FROM_CACHE_OP(false, 0, 1, NULL, 0)); > + > +static SPINAND_OP_VARIANTS(write_cache_variants, > + SPINAND_PROG_LOAD_X4(true, 0, NULL, 0), > + SPINAND_PROG_LOAD(true, 0, NULL, 0)); > + > +static SPINAND_OP_VARIANTS(update_cache_variants, > + SPINAND_PROG_LOAD_X4(false, 0, NULL, 0), > + SPINAND_PROG_LOAD(false, 0, NULL, 0)); > + > +static int etron_oob_spare(struct mtd_info *mtd) > +{ > + if (mtd->size < 0x10000000) > + return mtd->oobsize / 2; > + else > + return mtd->oobsize / 2 + mtd->oobsize / 16; > +} > + > +static int etron_ooblayout_ecc(struct mtd_info *mtd, int section, > + struct mtd_oob_region *oobregion) > +{ > + if (section) > + return -ERANGE; > + > + oobregion->offset = etron_oob_spare(mtd); > + oobregion->length = mtd->oobsize - oobregion->offset; > + > + return 0; > +} > + > +static int etron_ooblayout_free(struct mtd_info *mtd, int section, > + struct mtd_oob_region *oobregion) > +{ > + if (section) > + return -ERANGE; > + > + oobregion->offset = 2; > + oobregion->length = etron_oob_spare(mtd) - 2; > + > + return 0; > +} > + > +static const struct mtd_ooblayout_ops etron_ooblayout = { > + .ecc = etron_ooblayout_ecc, > + .free = etron_ooblayout_free, > +}; > + > +static int etron_ecc_get_status(struct spinand_device *spinand, u8 status) > +{ > + switch (status & STATUS_ECC_MASK) { > + case STATUS_ECC_NO_BITFLIPS: > + return 0; > + > + case STATUS_ECC_HAS_BITFLIPS: > + /* Between 1-7 bitflips were corrected */ > + return 7; > + > + case STATUS_ECC_MASK:
I'm not sure if using STATUS_ECC_MASK here to check for the 0b11 pattern is really a good idea. I'd rather introduce a vendor-specific define for this as other drivers do (see toshiba.c, paragon.c or gigadevice.c). As this seems to be a common pattern among vendors we could also think about introducing a new common flag like STATUS_ECC_HAS_MAX_BITFLIPS or something like that and use this instead.
> + /* Maximum bitflips were corrected */ > + return 8; > + > + case STATUS_ECC_UNCOR_ERROR: > + return -EBADMSG; > + } > + > + return -EINVAL; > +} > + > +static const struct spinand_info etron_spinand_table[] = { > + SPINAND_INFO("EM73D044VCx", > + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0x1f),
According to the datasheet, the device id of the EM73D044VCL is 0x2e and not 0x1f. Am I missing something?
Best regards Frieder
> + NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1), > + NAND_ECCREQ(8, 512), > + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, > + &write_cache_variants, > + &update_cache_variants), > + SPINAND_HAS_QE_BIT, > + SPINAND_ECCINFO(&etron_ooblayout, etron_ecc_get_status)), > +}; > + > +static const struct spinand_manufacturer_ops etron_spinand_manuf_ops = { > +}; > + > +const struct spinand_manufacturer etron_spinand_manufacturer = { > + .id = SPINAND_MFR_ETRON, > + .name = "Etron", > + .chips = etron_spinand_table, > + .nchips = ARRAY_SIZE(etron_spinand_table), > + .ops = &etron_spinand_manuf_ops, > +}; > diff --git a/include/linux/mtd/spinand.h b/include/linux/mtd/spinand.h > index 6988956b8492..d7c0a0439652 100644 > --- a/include/linux/mtd/spinand.h > +++ b/include/linux/mtd/spinand.h > @@ -260,6 +260,7 @@ struct spinand_manufacturer { > }; > > /* SPI NAND manufacturers */ > +extern const struct spinand_manufacturer etron_spinand_manufacturer; > extern const struct spinand_manufacturer gigadevice_spinand_manufacturer; > extern const struct spinand_manufacturer macronix_spinand_manufacturer; > extern const struct spinand_manufacturer micron_spinand_manufacturer; >
| |