> -----Original Message----- > From: Linus Walleij <linus.wall...@linaro.org> > Sent: Wednesday, September 11, 2024 12:11 AM > To: u-boot@lists.denx.de; Dario Binacchi > <dario.binac...@amarulasolutions.com>; Michael Trimarchi > <mich...@amarulasolutions.com>; Anand Gore > <anand.g...@broadcom.com>; William Zhang > <william.zh...@broadcom.com>; Kursad Oney > <kursad.o...@broadcom.com>; Philippe Reynes > <philippe.rey...@softathome.com> > Cc: Linus Walleij <linus.wall...@linaro.org>; David Regan > <dre...@broadcom.com>; Miquel Raynal <miquel.ray...@bootlin.com> > Subject: [PATCH 7/7] mtd: rawnand: brcmnand: Add support for getting ecc > setting from strap > > From: William Zhang <william.zh...@broadcom.com> > > 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 <william.zh...@broadcom.com> > Reviewed-by: David Regan <dre...@broadcom.com> > Signed-off-by: Miquel Raynal <miquel.ray...@bootlin.com> > Link: https://lore.kernel.org/linux-mtd/20240301173308.226004-1- > william.zh...@broadcom.com > Signed-off-by: Linus Walleij <linus.wall...@linaro.org> > --- > 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