Message ID | 20230606231252.94838-12-william.zhang@broadcom.com |
---|---|
State | Changes Requested |
Delegated to: | Miquel Raynal |
Headers | show |
Series | mtd: rawnand: brcmnand: driver and doc updates | expand |
Hi William, william.zhang@broadcom.com wrote on Tue, 6 Jun 2023 16:12:51 -0700: > 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. > > The generic nand ecc settings still take precedence over this flag. For > example, if nand-ecc-strength is set in the dts, the driver ignores the > strap setting and falls back to original behavior. This makes sure that > the existing BCMBCA board dts still works the old way even the strap > flag is set in the BCMBCA chip dtsi. > > Signed-off-by: William Zhang <william.zhang@broadcom.com> > --- > > drivers/mtd/nand/raw/brcmnand/brcmnand.c | 72 +++++++++++++++++++++--- > 1 file changed, 64 insertions(+), 8 deletions(-) > > diff --git a/drivers/mtd/nand/raw/brcmnand/brcmnand.c b/drivers/mtd/nand/raw/brcmnand/brcmnand.c > index 656be4d73016..8c7cea36ac71 100644 > --- a/drivers/mtd/nand/raw/brcmnand/brcmnand.c > +++ b/drivers/mtd/nand/raw/brcmnand/brcmnand.c > @@ -1076,6 +1076,38 @@ 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 int brcmnand_get_ecc_strength(struct brcmnand_host *host) > +{ > + struct brcmnand_controller *ctrl = host->ctrl; > + u16 acc_control_offs = brcmnand_cs_offset(ctrl, host->cs, > + BRCMNAND_CS_ACC_CONTROL); > + int sector_size_1k = brcmnand_get_sector_size_1k(host); > + int spare_area_size, ecc_level, ecc_strength; > + 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)) >> brcmnand_ecc_level_shift(ctrl); > + if (sector_size_1k) > + ecc_strength = ecc_level<<1; ? If you mean "x2" then let the compiler do that. > + else if (spare_area_size == 16 && ecc_level == 15) > + ecc_strength = 1; /* hamming */ > + else > + ecc_strength = ecc_level; > + > + return ecc_strength; > +} > + > /*********************************************************************** > * CS_NAND_SELECT > ***********************************************************************/ > @@ -2656,19 +2688,43 @@ static int brcmnand_setup_dev(struct brcmnand_host *host) > nanddev_get_ecc_requirements(&chip->base); > struct brcmnand_controller *ctrl = host->ctrl; > struct brcmnand_cfg *cfg = &host->hwcfg; > - char msg[128]; > + struct device_node *np = nand_get_flash_node(chip); > u32 offs, tmp, oob_sector; > - int ret; > + int ret, sector_size_1k = 0; > + bool use_strap = false; > + char msg[128]; > > memset(cfg, 0, sizeof(*cfg)); > + use_strap = of_property_read_bool(np, "brcm,nand-ecc-use-strap"); > + > + /* > + * Set ECC size and strength based on hw configuration from strap > + * if device tree does not specify them and use strap property is set > + * If ecc strength is set in dts, don't use strap setting. > + */ > + if (chip->ecc.strength) > + use_strap = 0; > + > + if (use_strap) { > + chip->ecc.strength = brcmnand_get_ecc_strength(host); > + sector_size_1k = brcmnand_get_sector_size_1k(host); > + if (chip->ecc.size == 0) { > + if (sector_size_1k < 0) > + chip->ecc.size = 512; > + else > + chip->ecc.size = 512<<sector_size_1k; Please run checkpatch.pl --strict > + } > + } > > - ret = of_property_read_u32(nand_get_flash_node(chip), > - "brcm,nand-oob-sector-size", > - &oob_sector); > + ret = of_property_read_u32(np, "brcm,nand-oob-sector-size", > + &oob_sector); > 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; > } Thanks, Miquèl
diff --git a/drivers/mtd/nand/raw/brcmnand/brcmnand.c b/drivers/mtd/nand/raw/brcmnand/brcmnand.c index 656be4d73016..8c7cea36ac71 100644 --- a/drivers/mtd/nand/raw/brcmnand/brcmnand.c +++ b/drivers/mtd/nand/raw/brcmnand/brcmnand.c @@ -1076,6 +1076,38 @@ 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 int brcmnand_get_ecc_strength(struct brcmnand_host *host) +{ + struct brcmnand_controller *ctrl = host->ctrl; + u16 acc_control_offs = brcmnand_cs_offset(ctrl, host->cs, + BRCMNAND_CS_ACC_CONTROL); + int sector_size_1k = brcmnand_get_sector_size_1k(host); + int spare_area_size, ecc_level, ecc_strength; + 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)) >> brcmnand_ecc_level_shift(ctrl); + if (sector_size_1k) + ecc_strength = ecc_level<<1; + else if (spare_area_size == 16 && ecc_level == 15) + ecc_strength = 1; /* hamming */ + else + ecc_strength = ecc_level; + + return ecc_strength; +} + /*********************************************************************** * CS_NAND_SELECT ***********************************************************************/ @@ -2656,19 +2688,43 @@ static int brcmnand_setup_dev(struct brcmnand_host *host) nanddev_get_ecc_requirements(&chip->base); struct brcmnand_controller *ctrl = host->ctrl; struct brcmnand_cfg *cfg = &host->hwcfg; - char msg[128]; + struct device_node *np = nand_get_flash_node(chip); u32 offs, tmp, oob_sector; - int ret; + int ret, sector_size_1k = 0; + bool use_strap = false; + char msg[128]; memset(cfg, 0, sizeof(*cfg)); + use_strap = of_property_read_bool(np, "brcm,nand-ecc-use-strap"); + + /* + * Set ECC size and strength based on hw configuration from strap + * if device tree does not specify them and use strap property is set + * If ecc strength is set in dts, don't use strap setting. + */ + if (chip->ecc.strength) + use_strap = 0; + + if (use_strap) { + chip->ecc.strength = brcmnand_get_ecc_strength(host); + sector_size_1k = brcmnand_get_sector_size_1k(host); + if (chip->ecc.size == 0) { + if (sector_size_1k < 0) + chip->ecc.size = 512; + else + chip->ecc.size = 512<<sector_size_1k; + } + } - ret = of_property_read_u32(nand_get_flash_node(chip), - "brcm,nand-oob-sector-size", - &oob_sector); + ret = of_property_read_u32(np, "brcm,nand-oob-sector-size", + &oob_sector); 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; }
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. The generic nand ecc settings still take precedence over this flag. For example, if nand-ecc-strength is set in the dts, the driver ignores the strap setting and falls back to original behavior. This makes sure that the existing BCMBCA board dts still works the old way even the strap flag is set in the BCMBCA chip dtsi. Signed-off-by: William Zhang <william.zhang@broadcom.com> --- drivers/mtd/nand/raw/brcmnand/brcmnand.c | 72 +++++++++++++++++++++--- 1 file changed, 64 insertions(+), 8 deletions(-)