Message ID | 20240916-brcmnand-fixes-v2-1-08632f64c8ec@linaro.org |
---|---|
State | New |
Headers | show |
Series | mtd: nand: brcmnand: Backported fixes from Linux | expand |
> -----Original Message----- > From: Linus Walleij <linus.walleij@linaro.org> > Sent: Monday, September 16, 2024 2:59 AM > To: u-boot@lists.denx.de; Dario Binacchi > <dario.binacchi@amarulasolutions.com>; Michael Trimarchi > <michael@amarulasolutions.com>; Anand Gore > <anand.gore@broadcom.com>; William Zhang > <william.zhang@broadcom.com>; Kursad Oney > <kursad.oney@broadcom.com>; Philippe Reynes > <philippe.reynes@softathome.com> > Cc: Linus Walleij <linus.walleij@linaro.org>; Florian Fainelli > <florian.fainelli@broadcom.com>; Miquel Raynal > <miquel.raynal@bootlin.com> > Subject: [PATCH v2 1/7] mtd: rawnand: brcmnand: Fix ECC level field > setting for v7.2 controller > > From: William Zhang <william.zhang@broadcom.com> > > Backport from the Linux kernel > commit 2ec2839a9062db8a592525a3fdabd42dcd9a3a9b > "mtd: rawnand: brcmnand: Fix ECC level field setting for v7.2 controller" > > v7.2 controller has different ECC level field size and shift in the acc > control register than its predecessor and successor controller. It needs > to be set specifically. > > Signed-off-by: William Zhang <william.zhang@broadcom.com> > Reviewed-by: Florian Fainelli <florian.fainelli@broadcom.com> > Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com> > Link: https://lore.kernel.org/linux-mtd/20230706182909.79151-2- > william.zhang@broadcom.com > Signed-off-by: Linus Walleij <linus.walleij@linaro.org> > --- > drivers/mtd/nand/raw/brcmnand/brcmnand.c | 74 > ++++++++++++++++++-------------- > 1 file changed, 41 insertions(+), 33 deletions(-) > > diff --git a/drivers/mtd/nand/raw/brcmnand/brcmnand.c > b/drivers/mtd/nand/raw/brcmnand/brcmnand.c > index b1af3f717d43..700d1122639f 100644 > --- a/drivers/mtd/nand/raw/brcmnand/brcmnand.c > +++ b/drivers/mtd/nand/raw/brcmnand/brcmnand.c > @@ -218,6 +218,7 @@ struct brcmnand_controller { > const unsigned int *page_sizes; > unsigned int page_size_shift; > unsigned int max_oob; > + u32 ecc_level_shift; > u32 features; > > /* for low-power standby/resume only */ > @@ -544,6 +545,34 @@ enum { > INTFC_CTLR_READY = BIT(31), > }; > > +/********************************************************* > ************** > + * NAND ACC CONTROL bitfield > + * > + * Some bits have remained constant throughout hardware revision, while > + * others have shifted around. > + > ********************************************************** > *************/ > + > +/* Constant for all versions (where supported) */ > +enum { > + /* See BRCMNAND_HAS_CACHE_MODE */ > + ACC_CONTROL_CACHE_MODE = BIT(22), > + > + /* See BRCMNAND_HAS_PREFETCH */ > + ACC_CONTROL_PREFETCH = BIT(23), > + > + ACC_CONTROL_PAGE_HIT = BIT(24), > + ACC_CONTROL_WR_PREEMPT = BIT(25), > + ACC_CONTROL_PARTIAL_PAGE = BIT(26), > + ACC_CONTROL_RD_ERASED = BIT(27), > + ACC_CONTROL_FAST_PGM_RDIN = BIT(28), > + ACC_CONTROL_WR_ECC = BIT(30), > + ACC_CONTROL_RD_ECC = BIT(31), > +}; > + > +#define ACC_CONTROL_ECC_SHIFT 16 > +/* Only for v7.2 */ > +#define ACC_CONTROL_ECC_EXT_SHIFT 13 > + > static inline u32 nand_readreg(struct brcmnand_controller *ctrl, u32 > offs) > { > return brcmnand_readl(ctrl->nand_base + offs); > @@ -675,6 +704,12 @@ static int brcmnand_revision_init(struct > brcmnand_controller *ctrl) > #endif /* __UBOOT__ */ > ctrl->features |= BRCMNAND_HAS_WP; > > + /* v7.2 has different ecc level shift in the acc register */ > + if (ctrl->nand_version == 0x0702) > + ctrl->ecc_level_shift = ACC_CONTROL_ECC_EXT_SHIFT; > + else > + ctrl->ecc_level_shift = ACC_CONTROL_ECC_SHIFT; > + > return 0; > } > > @@ -844,30 +879,6 @@ static inline int brcmnand_cmd_shift(struct > brcmnand_controller *ctrl) > return 0; > } > > - > /********************************************************** > ************* > - * NAND ACC CONTROL bitfield > - * > - * Some bits have remained constant throughout hardware revision, while > - * others have shifted around. > - > ********************************************************** > *************/ > - > -/* Constant for all versions (where supported) */ > -enum { > - /* See BRCMNAND_HAS_CACHE_MODE */ > - ACC_CONTROL_CACHE_MODE = BIT(22), > - > - /* See BRCMNAND_HAS_PREFETCH */ > - ACC_CONTROL_PREFETCH = BIT(23), > - > - ACC_CONTROL_PAGE_HIT = BIT(24), > - ACC_CONTROL_WR_PREEMPT = BIT(25), > - ACC_CONTROL_PARTIAL_PAGE = BIT(26), > - ACC_CONTROL_RD_ERASED = BIT(27), > - ACC_CONTROL_FAST_PGM_RDIN = BIT(28), > - ACC_CONTROL_WR_ECC = BIT(30), > - ACC_CONTROL_RD_ECC = BIT(31), > -}; > - > static inline u32 brcmnand_spare_area_mask(struct brcmnand_controller > *ctrl) > { > if (ctrl->nand_version == 0x0702) > @@ -880,18 +891,15 @@ static inline u32 > brcmnand_spare_area_mask(struct brcmnand_controller *ctrl) > return GENMASK(4, 0); > } > > -#define NAND_ACC_CONTROL_ECC_SHIFT 16 > -#define NAND_ACC_CONTROL_ECC_EXT_SHIFT 13 > - > static inline u32 brcmnand_ecc_level_mask(struct brcmnand_controller > *ctrl) > { > u32 mask = (ctrl->nand_version >= 0x0600) ? 0x1f : 0x0f; > > - mask <<= NAND_ACC_CONTROL_ECC_SHIFT; > + mask <<= ACC_CONTROL_ECC_SHIFT; > > /* v7.2 includes additional ECC levels */ > - if (ctrl->nand_version >= 0x0702) > - mask |= 0x7 << NAND_ACC_CONTROL_ECC_EXT_SHIFT; > + if (ctrl->nand_version == 0x0702) > + mask |= 0x7 << ACC_CONTROL_ECC_EXT_SHIFT; > > return mask; > } > @@ -905,8 +913,8 @@ static void brcmnand_set_ecc_enabled(struct > brcmnand_host *host, int en) > > if (en) { > acc_control |= ecc_flags; /* enable RD/WR ECC */ > - acc_control |= host->hwcfg.ecc_level > - << NAND_ACC_CONTROL_ECC_SHIFT; > + acc_control &= ~brcmnand_ecc_level_mask(ctrl); > + acc_control |= host->hwcfg.ecc_level << ctrl->ecc_level_shift; > } else { > acc_control &= ~ecc_flags; /* disable RD/WR ECC */ > acc_control &= ~brcmnand_ecc_level_mask(ctrl); > @@ -2225,7 +2233,7 @@ static int brcmnand_set_cfg(struct > brcmnand_host *host, > tmp &= ~brcmnand_ecc_level_mask(ctrl); > tmp &= ~brcmnand_spare_area_mask(ctrl); > if (ctrl->nand_version >= 0x0302) { > - tmp |= cfg->ecc_level << NAND_ACC_CONTROL_ECC_SHIFT; > + tmp |= cfg->ecc_level << ctrl->ecc_level_shift; > tmp |= cfg->spare_area_size; > } > nand_writereg(ctrl, acc_control_offs, tmp); > > -- > 2.46.0 Reviewed-by: William Zhang <william.zhang@broadcom.com>
On Mon, Sep 16, 2024 at 11:58 AM Linus Walleij <linus.walleij@linaro.org> wrote: > > From: William Zhang <william.zhang@broadcom.com> > > Backport from the Linux kernel > commit 2ec2839a9062db8a592525a3fdabd42dcd9a3a9b > "mtd: rawnand: brcmnand: Fix ECC level field setting for v7.2 controller" > > v7.2 controller has different ECC level field size and shift in the acc > control register than its predecessor and successor controller. It needs > to be set specifically. > > Signed-off-by: William Zhang <william.zhang@broadcom.com> > Reviewed-by: Florian Fainelli <florian.fainelli@broadcom.com> > Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com> > Link: https://lore.kernel.org/linux-mtd/20230706182909.79151-2-william.zhang@broadcom.com > Signed-off-by: Linus Walleij <linus.walleij@linaro.org> > --- > drivers/mtd/nand/raw/brcmnand/brcmnand.c | 74 ++++++++++++++++++-------------- > 1 file changed, 41 insertions(+), 33 deletions(-) > > diff --git a/drivers/mtd/nand/raw/brcmnand/brcmnand.c b/drivers/mtd/nand/raw/brcmnand/brcmnand.c > index b1af3f717d43..700d1122639f 100644 > --- a/drivers/mtd/nand/raw/brcmnand/brcmnand.c > +++ b/drivers/mtd/nand/raw/brcmnand/brcmnand.c > @@ -218,6 +218,7 @@ struct brcmnand_controller { > const unsigned int *page_sizes; > unsigned int page_size_shift; > unsigned int max_oob; > + u32 ecc_level_shift; > u32 features; > > /* for low-power standby/resume only */ > @@ -544,6 +545,34 @@ enum { > INTFC_CTLR_READY = BIT(31), > }; > > +/*********************************************************************** > + * NAND ACC CONTROL bitfield > + * > + * Some bits have remained constant throughout hardware revision, while > + * others have shifted around. > + ***********************************************************************/ > + > +/* Constant for all versions (where supported) */ > +enum { > + /* See BRCMNAND_HAS_CACHE_MODE */ > + ACC_CONTROL_CACHE_MODE = BIT(22), > + > + /* See BRCMNAND_HAS_PREFETCH */ > + ACC_CONTROL_PREFETCH = BIT(23), > + > + ACC_CONTROL_PAGE_HIT = BIT(24), > + ACC_CONTROL_WR_PREEMPT = BIT(25), > + ACC_CONTROL_PARTIAL_PAGE = BIT(26), > + ACC_CONTROL_RD_ERASED = BIT(27), > + ACC_CONTROL_FAST_PGM_RDIN = BIT(28), > + ACC_CONTROL_WR_ECC = BIT(30), > + ACC_CONTROL_RD_ECC = BIT(31), > +}; > + > +#define ACC_CONTROL_ECC_SHIFT 16 > +/* Only for v7.2 */ > +#define ACC_CONTROL_ECC_EXT_SHIFT 13 > + > static inline u32 nand_readreg(struct brcmnand_controller *ctrl, u32 offs) > { > return brcmnand_readl(ctrl->nand_base + offs); > @@ -675,6 +704,12 @@ static int brcmnand_revision_init(struct brcmnand_controller *ctrl) > #endif /* __UBOOT__ */ > ctrl->features |= BRCMNAND_HAS_WP; > > + /* v7.2 has different ecc level shift in the acc register */ > + if (ctrl->nand_version == 0x0702) > + ctrl->ecc_level_shift = ACC_CONTROL_ECC_EXT_SHIFT; > + else > + ctrl->ecc_level_shift = ACC_CONTROL_ECC_SHIFT; > + > return 0; > } > > @@ -844,30 +879,6 @@ static inline int brcmnand_cmd_shift(struct brcmnand_controller *ctrl) > return 0; > } > > -/*********************************************************************** > - * NAND ACC CONTROL bitfield > - * > - * Some bits have remained constant throughout hardware revision, while > - * others have shifted around. > - ***********************************************************************/ > - > -/* Constant for all versions (where supported) */ > -enum { > - /* See BRCMNAND_HAS_CACHE_MODE */ > - ACC_CONTROL_CACHE_MODE = BIT(22), > - > - /* See BRCMNAND_HAS_PREFETCH */ > - ACC_CONTROL_PREFETCH = BIT(23), > - > - ACC_CONTROL_PAGE_HIT = BIT(24), > - ACC_CONTROL_WR_PREEMPT = BIT(25), > - ACC_CONTROL_PARTIAL_PAGE = BIT(26), > - ACC_CONTROL_RD_ERASED = BIT(27), > - ACC_CONTROL_FAST_PGM_RDIN = BIT(28), > - ACC_CONTROL_WR_ECC = BIT(30), > - ACC_CONTROL_RD_ECC = BIT(31), > -}; > - > static inline u32 brcmnand_spare_area_mask(struct brcmnand_controller *ctrl) > { > if (ctrl->nand_version == 0x0702) > @@ -880,18 +891,15 @@ static inline u32 brcmnand_spare_area_mask(struct brcmnand_controller *ctrl) > return GENMASK(4, 0); > } > > -#define NAND_ACC_CONTROL_ECC_SHIFT 16 > -#define NAND_ACC_CONTROL_ECC_EXT_SHIFT 13 > - > static inline u32 brcmnand_ecc_level_mask(struct brcmnand_controller *ctrl) > { > u32 mask = (ctrl->nand_version >= 0x0600) ? 0x1f : 0x0f; > > - mask <<= NAND_ACC_CONTROL_ECC_SHIFT; > + mask <<= ACC_CONTROL_ECC_SHIFT; > > /* v7.2 includes additional ECC levels */ > - if (ctrl->nand_version >= 0x0702) > - mask |= 0x7 << NAND_ACC_CONTROL_ECC_EXT_SHIFT; > + if (ctrl->nand_version == 0x0702) > + mask |= 0x7 << ACC_CONTROL_ECC_EXT_SHIFT; > > return mask; > } > @@ -905,8 +913,8 @@ static void brcmnand_set_ecc_enabled(struct brcmnand_host *host, int en) > > if (en) { > acc_control |= ecc_flags; /* enable RD/WR ECC */ > - acc_control |= host->hwcfg.ecc_level > - << NAND_ACC_CONTROL_ECC_SHIFT; > + acc_control &= ~brcmnand_ecc_level_mask(ctrl); > + acc_control |= host->hwcfg.ecc_level << ctrl->ecc_level_shift; > } else { > acc_control &= ~ecc_flags; /* disable RD/WR ECC */ > acc_control &= ~brcmnand_ecc_level_mask(ctrl); > @@ -2225,7 +2233,7 @@ static int brcmnand_set_cfg(struct brcmnand_host *host, > tmp &= ~brcmnand_ecc_level_mask(ctrl); > tmp &= ~brcmnand_spare_area_mask(ctrl); > if (ctrl->nand_version >= 0x0302) { > - tmp |= cfg->ecc_level << NAND_ACC_CONTROL_ECC_SHIFT; > + tmp |= cfg->ecc_level << ctrl->ecc_level_shift; > tmp |= cfg->spare_area_size; > } > nand_writereg(ctrl, acc_control_offs, tmp); > > -- > 2.46.0 > Acked-by; Michael Trimarchi <michael@amarulasolutions.com>
diff --git a/drivers/mtd/nand/raw/brcmnand/brcmnand.c b/drivers/mtd/nand/raw/brcmnand/brcmnand.c index b1af3f717d43..700d1122639f 100644 --- a/drivers/mtd/nand/raw/brcmnand/brcmnand.c +++ b/drivers/mtd/nand/raw/brcmnand/brcmnand.c @@ -218,6 +218,7 @@ struct brcmnand_controller { const unsigned int *page_sizes; unsigned int page_size_shift; unsigned int max_oob; + u32 ecc_level_shift; u32 features; /* for low-power standby/resume only */ @@ -544,6 +545,34 @@ enum { INTFC_CTLR_READY = BIT(31), }; +/*********************************************************************** + * NAND ACC CONTROL bitfield + * + * Some bits have remained constant throughout hardware revision, while + * others have shifted around. + ***********************************************************************/ + +/* Constant for all versions (where supported) */ +enum { + /* See BRCMNAND_HAS_CACHE_MODE */ + ACC_CONTROL_CACHE_MODE = BIT(22), + + /* See BRCMNAND_HAS_PREFETCH */ + ACC_CONTROL_PREFETCH = BIT(23), + + ACC_CONTROL_PAGE_HIT = BIT(24), + ACC_CONTROL_WR_PREEMPT = BIT(25), + ACC_CONTROL_PARTIAL_PAGE = BIT(26), + ACC_CONTROL_RD_ERASED = BIT(27), + ACC_CONTROL_FAST_PGM_RDIN = BIT(28), + ACC_CONTROL_WR_ECC = BIT(30), + ACC_CONTROL_RD_ECC = BIT(31), +}; + +#define ACC_CONTROL_ECC_SHIFT 16 +/* Only for v7.2 */ +#define ACC_CONTROL_ECC_EXT_SHIFT 13 + static inline u32 nand_readreg(struct brcmnand_controller *ctrl, u32 offs) { return brcmnand_readl(ctrl->nand_base + offs); @@ -675,6 +704,12 @@ static int brcmnand_revision_init(struct brcmnand_controller *ctrl) #endif /* __UBOOT__ */ ctrl->features |= BRCMNAND_HAS_WP; + /* v7.2 has different ecc level shift in the acc register */ + if (ctrl->nand_version == 0x0702) + ctrl->ecc_level_shift = ACC_CONTROL_ECC_EXT_SHIFT; + else + ctrl->ecc_level_shift = ACC_CONTROL_ECC_SHIFT; + return 0; } @@ -844,30 +879,6 @@ static inline int brcmnand_cmd_shift(struct brcmnand_controller *ctrl) return 0; } -/*********************************************************************** - * NAND ACC CONTROL bitfield - * - * Some bits have remained constant throughout hardware revision, while - * others have shifted around. - ***********************************************************************/ - -/* Constant for all versions (where supported) */ -enum { - /* See BRCMNAND_HAS_CACHE_MODE */ - ACC_CONTROL_CACHE_MODE = BIT(22), - - /* See BRCMNAND_HAS_PREFETCH */ - ACC_CONTROL_PREFETCH = BIT(23), - - ACC_CONTROL_PAGE_HIT = BIT(24), - ACC_CONTROL_WR_PREEMPT = BIT(25), - ACC_CONTROL_PARTIAL_PAGE = BIT(26), - ACC_CONTROL_RD_ERASED = BIT(27), - ACC_CONTROL_FAST_PGM_RDIN = BIT(28), - ACC_CONTROL_WR_ECC = BIT(30), - ACC_CONTROL_RD_ECC = BIT(31), -}; - static inline u32 brcmnand_spare_area_mask(struct brcmnand_controller *ctrl) { if (ctrl->nand_version == 0x0702) @@ -880,18 +891,15 @@ static inline u32 brcmnand_spare_area_mask(struct brcmnand_controller *ctrl) return GENMASK(4, 0); } -#define NAND_ACC_CONTROL_ECC_SHIFT 16 -#define NAND_ACC_CONTROL_ECC_EXT_SHIFT 13 - static inline u32 brcmnand_ecc_level_mask(struct brcmnand_controller *ctrl) { u32 mask = (ctrl->nand_version >= 0x0600) ? 0x1f : 0x0f; - mask <<= NAND_ACC_CONTROL_ECC_SHIFT; + mask <<= ACC_CONTROL_ECC_SHIFT; /* v7.2 includes additional ECC levels */ - if (ctrl->nand_version >= 0x0702) - mask |= 0x7 << NAND_ACC_CONTROL_ECC_EXT_SHIFT; + if (ctrl->nand_version == 0x0702) + mask |= 0x7 << ACC_CONTROL_ECC_EXT_SHIFT; return mask; } @@ -905,8 +913,8 @@ static void brcmnand_set_ecc_enabled(struct brcmnand_host *host, int en) if (en) { acc_control |= ecc_flags; /* enable RD/WR ECC */ - acc_control |= host->hwcfg.ecc_level - << NAND_ACC_CONTROL_ECC_SHIFT; + acc_control &= ~brcmnand_ecc_level_mask(ctrl); + acc_control |= host->hwcfg.ecc_level << ctrl->ecc_level_shift; } else { acc_control &= ~ecc_flags; /* disable RD/WR ECC */ acc_control &= ~brcmnand_ecc_level_mask(ctrl); @@ -2225,7 +2233,7 @@ static int brcmnand_set_cfg(struct brcmnand_host *host, tmp &= ~brcmnand_ecc_level_mask(ctrl); tmp &= ~brcmnand_spare_area_mask(ctrl); if (ctrl->nand_version >= 0x0302) { - tmp |= cfg->ecc_level << NAND_ACC_CONTROL_ECC_SHIFT; + tmp |= cfg->ecc_level << ctrl->ecc_level_shift; tmp |= cfg->spare_area_size; } nand_writereg(ctrl, acc_control_offs, tmp);