> -----Original Message----- > From: Linus Walleij <[email protected]> > Sent: Wednesday, September 11, 2024 12:11 AM > To: [email protected]; Dario Binacchi > <[email protected]>; Michael Trimarchi > <[email protected]>; Anand Gore > <[email protected]>; William Zhang > <[email protected]>; Kursad Oney > <[email protected]>; Philippe Reynes > <[email protected]> > Cc: Linus Walleij <[email protected]>; David Regan > <[email protected]>; Miquel Raynal <[email protected]> > Subject: [PATCH 7/7] mtd: rawnand: brcmnand: Add support for getting ecc > setting from strap > > From: William Zhang <[email protected]> > > Backport from the upstream Linux kernel > commit c2cf7e25eb2a3c915a420fb8ceed8912add7f36c > "mtd: rawnand: brcmnand: Add support for getting ecc setting from strap" > > Note: the upstream kernel introduces a new > bool brcmnand_get_sector_size_1k() function because the int > version in U-Boot has been removed in Linux. I kept the old > int-returning version that is already in U-Boot as we depend > on that in other code. > > BCMBCA broadband SoC based board design does not specify ecc setting in > dts but rather use the SoC NAND strap info to obtain the ecc strength > and spare area size setting. Add brcm,nand-ecc-use-strap dts propety for > this purpose and update driver to support this option. However these two > options can not be used at the same time. > > Signed-off-by: William Zhang <[email protected]> > Reviewed-by: David Regan <[email protected]> > Signed-off-by: Miquel Raynal <[email protected]> > Link: https://lore.kernel.org/linux-mtd/20240301173308.226004-1- > [email protected] > Signed-off-by: Linus Walleij <[email protected]> > --- > drivers/mtd/nand/raw/brcmnand/brcmnand.c | 70 > ++++++++++++++++++++++++++++++-- > 1 file changed, 66 insertions(+), 4 deletions(-) > > diff --git a/drivers/mtd/nand/raw/brcmnand/brcmnand.c > b/drivers/mtd/nand/raw/brcmnand/brcmnand.c > index 55d5d27438a8..1ffd6cfff98f 100644 > --- a/drivers/mtd/nand/raw/brcmnand/brcmnand.c > +++ b/drivers/mtd/nand/raw/brcmnand/brcmnand.c > @@ -980,6 +980,43 @@ static void brcmnand_set_sector_size_1k(struct > brcmnand_host *host, int val) > nand_writereg(ctrl, acc_control_offs, tmp); > } > > +static int brcmnand_get_spare_size(struct brcmnand_host *host) > +{ > + struct brcmnand_controller *ctrl = host->ctrl; > + u16 acc_control_offs = brcmnand_cs_offset(ctrl, host->cs, > + > BRCMNAND_CS_ACC_CONTROL); > + u32 acc = nand_readreg(ctrl, acc_control_offs); > + > + return (acc & brcmnand_spare_area_mask(ctrl)); > +} > + > +static void brcmnand_get_ecc_settings(struct brcmnand_host *host, > struct nand_chip *chip) > +{ > + struct brcmnand_controller *ctrl = host->ctrl; > + u16 acc_control_offs = brcmnand_cs_offset(ctrl, host->cs, > + > BRCMNAND_CS_ACC_CONTROL); > + bool sector_size_1k = brcmnand_get_sector_size_1k(host); > + int spare_area_size, ecc_level; > + u32 acc; > + > + spare_area_size = brcmnand_get_spare_size(host); > + acc = nand_readreg(ctrl, acc_control_offs); > + ecc_level = (acc & brcmnand_ecc_level_mask(ctrl)) >> ctrl- > >ecc_level_shift; > + if (sector_size_1k) > + chip->ecc.strength = ecc_level * 2; > + else if (spare_area_size == 16 && ecc_level == 15) > + chip->ecc.strength = 1; /* hamming */ > + else > + chip->ecc.strength = ecc_level; > + > + if (chip->ecc.size == 0) { > + if (sector_size_1k) > + chip->ecc.size = 1024; > + else > + chip->ecc.size = 512; > + } > +} > + > > /********************************************************** > ************* > * CS_NAND_SELECT > > ********************************************************** > *************/ > @@ -2323,12 +2360,33 @@ static int brcmnand_setup_dev(struct > brcmnand_host *host) > struct nand_memory_organization *memorg = > nanddev_get_memorg(nanddev); > struct brcmnand_controller *ctrl = host->ctrl; > struct brcmnand_cfg *cfg = &host->hwcfg; > - char msg[128]; > u32 offs, tmp, oob_sector; > + bool use_strap = false; > + char msg[128]; > int ret; > > memset(cfg, 0, sizeof(*cfg)); > > +#ifndef __UBOOT__ > + use_strap = of_property_read_bool(nand_get_flash_node(chip), > + "brcm,nand-ecc-use-strap"): > +#else > + ret = ofnode_read_bool(nand_get_flash_node(chip), use_strap = ofnode_read_bool(nand_get_flash_node(chip),
> + "brcm,nand-ecc-use-strap");
> +#endif /* __UBOOT__ */
> + /*
> + * Either nand-ecc-xxx or brcm,nand-ecc-use-strap can be set. Error
> out
> + * if both exist.
> + */
> + if (chip->ecc.strength && use_strap) {
> + dev_err(ctrl->dev,
> + "ECC strap and DT ECC configuration properties are
> mutually exclusive\n");
> + return -EINVAL;
> + }
> +
> + if (use_strap)
> + brcmnand_get_ecc_settings(host, chip);
> +
> #ifndef __UBOOT__
> ret = of_property_read_u32(nand_get_flash_node(chip),
> "brcm,nand-oob-sector-size",
> @@ -2338,10 +2396,14 @@ static int brcmnand_setup_dev(struct
> brcmnand_host *host)
> "brcm,nand-oob-sector-size",
> &oob_sector);
> #endif /* __UBOOT__ */
> +
> if (ret) {
> - /* Use detected size */
> - cfg->spare_area_size = mtd->oobsize /
> - (mtd->writesize >> FC_SHIFT);
> + if (use_strap)
> + cfg->spare_area_size =
> brcmnand_get_spare_size(host);
> + else
> + /* Use detected size */
> + cfg->spare_area_size = mtd->oobsize /
> + (mtd->writesize >> FC_SHIFT);
> } else {
> cfg->spare_area_size = oob_sector;
> }
>
> --
> 2.46.0
smime.p7s
Description: S/MIME Cryptographic Signature

