[resend v2 15/19] drivers: mtd: nand: base: Add support for Hardware ECC for check bad block

Michael Nazzareno Trimarchi michael at amarulasolutions.com
Thu Dec 12 19:38:25 CET 2024


Hi

On Thu, Dec 5, 2024 at 10:24 AM <dinesh.maniyam at intel.com> wrote:
>
> From: Dinesh Maniyam <dinesh.maniyam at intel.com>
>
> Leverage linux code to support hardware ECC interface
> to verify nand bad block.
>
> Signed-off-by: Dinesh Maniyam <dinesh.maniyam at intel.com>
>
> ---
> v2:
> - remove the "this patch is to" commit phrases
> ---
> ---
>  drivers/mtd/nand/raw/nand_base.c | 71 +++++++++++++++++++++-----------
>  include/linux/mtd/rawnand.h      | 13 ++++++
>  2 files changed, 60 insertions(+), 24 deletions(-)
>
> diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
> index 4401bdcdb9..9b1b2d1f85 100644
> --- a/drivers/mtd/nand/raw/nand_base.c
> +++ b/drivers/mtd/nand/raw/nand_base.c
> @@ -9,6 +9,8 @@
>   *  Copyright (C) 2000 Steven J. Hill (sjhill at realitydiluted.com)
>   *               2002-2006 Thomas Gleixner (tglx at linutronix.de)
>   *
> + *  Copyright (C) 2024 Intel Corporation <www.intel.com>
> + *

Drop it. I don't think that because you add a function here, you can
add any copyright

>   *  Credits:
>   *     David Woodhouse for adding multichip support
>   *
> @@ -306,6 +308,35 @@ void nand_read_buf16(struct mtd_info *mtd, uint8_t *buf, int len)
>         ioread16_rep(chip->IO_ADDR_R, p, len >> 1);
>  }
>
> +/*
> + * nand_bbm_get_next_page - Get the next page for bad block markers
> + * @chip: The NAND chip
> + * @page: First page to start checking for bad block marker usage
> + *
> + * Returns an integer that corresponds to the page offset within a block, for
> + * a page that is used to store bad block markers. If no more pages are
> + * available, -EINVAL is returned.
> + */
> +int nand_bbm_get_next_page(struct nand_chip *chip, int page)
> +{
> +       struct mtd_info *mtd = nand_to_mtd(chip);
> +       int last_page = ((mtd->erasesize - mtd->writesize) >>
> +                        chip->page_shift) & chip->pagemask;
> +       unsigned int bbm_flags = NAND_BBM_FIRSTPAGE | NAND_BBM_SECONDPAGE
> +               | NAND_BBM_LASTPAGE;
> +
> +       if (page == 0 && !(chip->options & bbm_flags))
> +               return 0;
> +       if (page == 0 && chip->options & NAND_BBM_FIRSTPAGE)
> +               return 0;
> +       if (page <= 1 && chip->options & NAND_BBM_SECONDPAGE)
> +               return 1;
> +       if (page <= last_page && chip->options & NAND_BBM_LASTPAGE)
> +               return last_page;
> +
> +       return -EINVAL;
> +}
> +
>  /**
>   * nand_block_bad - [DEFAULT] Read bad block marker from the chip
>   * @mtd: MTD device structure
> @@ -315,40 +346,32 @@ void nand_read_buf16(struct mtd_info *mtd, uint8_t *buf, int len)
>   */
>  static int nand_block_bad(struct mtd_info *mtd, loff_t ofs)
>  {
> -       int page, res = 0, i = 0;
>         struct nand_chip *chip = mtd_to_nand(mtd);
> -       u16 bad;
> +       int first_page, page_offset;
> +       int res;
> +       u8 bad;
>
> -       if (chip->bbt_options & NAND_BBT_SCANLASTPAGE)
> -               ofs += mtd->erasesize - mtd->writesize;
> +       first_page = (int)(ofs >> chip->page_shift) & chip->pagemask;
> +       page_offset = nand_bbm_get_next_page(chip, 0);
>
> -       page = (int)(ofs >> chip->page_shift) & chip->pagemask;
> +       while (page_offset >= 0) {
> +               res = chip->ecc.read_oob(mtd, chip, first_page + page_offset);
> +               if (res < 0)
> +                       return res;
>
> -       do {
> -               if (chip->options & NAND_BUSWIDTH_16) {
> -                       chip->cmdfunc(mtd, NAND_CMD_READOOB,
> -                                       chip->badblockpos & 0xFE, page);
> -                       bad = cpu_to_le16(chip->read_word(mtd));
> -                       if (chip->badblockpos & 0x1)
> -                               bad >>= 8;
> -                       else
> -                               bad &= 0xFF;
> -               } else {
> -                       chip->cmdfunc(mtd, NAND_CMD_READOOB, chip->badblockpos,
> -                                       page);
> -                       bad = chip->read_byte(mtd);
> -               }
> +               bad = chip->oob_poi[chip->badblockpos];
>
>                 if (likely(chip->badblockbits == 8))
>                         res = bad != 0xFF;
>                 else
>                         res = hweight8(bad) < chip->badblockbits;
> -               ofs += mtd->writesize;
> -               page = (int)(ofs >> chip->page_shift) & chip->pagemask;
> -               i++;
> -       } while (!res && i < 2 && (chip->bbt_options & NAND_BBT_SCAN2NDPAGE));
> +               if (res)
> +                       return res;
>
> -       return res;
> +               page_offset = nand_bbm_get_next_page(chip, page_offset + 1);
> +       }
> +
> +       return 0;
>  }
>
>  /**
> diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h
> index 14f93dab0a..35eb3b5678 100644
> --- a/include/linux/mtd/rawnand.h
> +++ b/include/linux/mtd/rawnand.h
> @@ -4,6 +4,8 @@
>   *                        Steven J. Hill <sjhill at realitydiluted.com>
>   *                       Thomas Gleixner <tglx at linutronix.de>
>   *
> + *  Copyright (C) 2024 Intel Corporation <www.intel.com>
> + *

Drop here

>   * Info:
>   *     Contains standard defines and IDs for NAND flash devices
>   *
> @@ -131,6 +133,17 @@ void nand_wait_ready(struct mtd_info *mtd);
>
>  #define NAND_DATA_IFACE_CHECK_ONLY     -1
>
> +/*
> + * There are different places where the manufacturer stores the factory bad
> + * block markers.
> + *
> + * Position within the block: Each of these pages needs to be checked for a
> + * bad block marking pattern.
> + */
> +#define NAND_BBM_FIRSTPAGE     BIT(24)
> +#define NAND_BBM_SECONDPAGE    BIT(25)
> +#define NAND_BBM_LASTPAGE      BIT(26)
> +
>  /*
>   * Constants for ECC_MODES
>   */
> --
> 2.19.0
>
Reviewed-by: Michael Trimarchi <michael at amarulasolutions.com>

-- 
Michael Nazzareno Trimarchi
Co-Founder & Chief Executive Officer
M. +39 347 913 2170
michael at amarulasolutions.com
__________________________________

Amarula Solutions BV
Joop Geesinkweg 125, 1114 AB, Amsterdam, NL
T. +31 (0)85 111 9172
info at amarulasolutions.com
www.amarulasolutions.com


More information about the U-Boot mailing list