[U-Boot] [PATCH v2 2/5] nand: mxs_nand: add API for switching different BCH layouts

Oleksandr Suvorov oleksandr.suvorov at toradex.com
Wed Oct 23 11:23:04 UTC 2019


On Mon, Oct 21, 2019 at 4:41 PM Igor Opaniuk <igor.opaniuk at gmail.com> wrote:
>
> From: Igor Opaniuk <igor.opaniuk at toradex.com>
>
> On i.MX7 in a sake of reducing the disturbances caused by a neighboring
> cells in the FCB page in the NAND chip, a randomizer is enabled when
> reading the FCB page by ROM bootloader.
>
> Add API for setting BCH to specific layout (and restoring it back) used by
> ROM bootloader to be able to burn it in a proper way to NAND using
> nandbcb command.
>
> Signed-off-by: Igor Opaniuk <igor.opaniuk at toradex.com>
> Signed-off-by: Anti Sullin <anti.sullin at artecdesign.ee>

Reviewed-by: Oleksandr Suvorov <oleksandr.suvorov at toradex.com>

> ---
>
>  drivers/mtd/nand/raw/mxs_nand.c | 116 ++++++++++++++++++++++++++++++++
>  include/mxs_nand.h              |  22 ++++++
>  2 files changed, 138 insertions(+)
>
> diff --git a/drivers/mtd/nand/raw/mxs_nand.c b/drivers/mtd/nand/raw/mxs_nand.c
> index a41b9620d0..ad7b644886 100644
> --- a/drivers/mtd/nand/raw/mxs_nand.c
> +++ b/drivers/mtd/nand/raw/mxs_nand.c
> @@ -740,6 +740,19 @@ static int mxs_nand_ecc_write_page(struct mtd_info *mtd,
>         d->cmd.pio_words[4] = (dma_addr_t)nand_info->data_buf;
>         d->cmd.pio_words[5] = (dma_addr_t)nand_info->oob_buf;
>
> +       if (is_mx7() && nand_info->en_randomizer) {
> +               d->cmd.pio_words[2] |= GPMI_ECCCTRL_RANDOMIZER_ENABLE |
> +                                      GPMI_ECCCTRL_RANDOMIZER_TYPE2;
> +               /*
> +                * Write NAND page number needed to be randomized
> +                * to GPMI_ECCCOUNT register.
> +                *
> +                * The value is between 0-255. For additional details
> +                * check 9.6.6.4 of i.MX7D Applications Processor reference
> +                */
> +               d->cmd.pio_words[3] |= (page % 255) << 16;
> +       }
> +
>         mxs_dma_desc_append(channel, d);
>
>         /* Flush caches */
> @@ -1003,6 +1016,10 @@ int mxs_nand_setup_ecc(struct mtd_info *mtd)
>         uint32_t tmp;
>         int ret;
>
> +       nand_info->en_randomizer = 0;
> +       nand_info->oobsize = mtd->oobsize;
> +       nand_info->writesize = mtd->writesize;
> +
>         ret = mxs_nand_set_geometry(mtd, geo);
>         if (ret)
>                 return ret;
> @@ -1020,6 +1037,7 @@ int mxs_nand_setup_ecc(struct mtd_info *mtd)
>         tmp |= (geo->gf_len == 14 ? 1 : 0) <<
>                 BCH_FLASHLAYOUT0_GF13_0_GF14_1_OFFSET;
>         writel(tmp, &bch_regs->hw_bch_flash0layout0);
> +       nand_info->bch_flash0layout0 = tmp;
>
>         tmp = (mtd->writesize + mtd->oobsize)
>                 << BCH_FLASHLAYOUT1_PAGE_SIZE_OFFSET;
> @@ -1028,6 +1046,7 @@ int mxs_nand_setup_ecc(struct mtd_info *mtd)
>         tmp |= (geo->gf_len == 14 ? 1 : 0) <<
>                 BCH_FLASHLAYOUT1_GF13_0_GF14_1_OFFSET;
>         writel(tmp, &bch_regs->hw_bch_flash0layout1);
> +       nand_info->bch_flash0layout1 = tmp;
>
>         /* Set *all* chip selects to use layout 0 */
>         writel(0, &bch_regs->hw_bch_layoutselect);
> @@ -1303,3 +1322,100 @@ err:
>         free(nand_info);
>  }
>  #endif
> +
> +/*
> + * Read NAND layout for FCB block generation.
> + */
> +void mxs_nand_get_layout(struct mtd_info *mtd, struct mxs_nand_layout *l)
> +{
> +       struct mxs_bch_regs *bch_regs = (struct mxs_bch_regs *)MXS_BCH_BASE;
> +       u32 tmp;
> +
> +       tmp = readl(&bch_regs->hw_bch_flash0layout0);
> +       l->nblocks = (tmp & BCH_FLASHLAYOUT0_NBLOCKS_MASK) >>
> +                       BCH_FLASHLAYOUT0_NBLOCKS_OFFSET;
> +       l->meta_size = (tmp & BCH_FLASHLAYOUT0_META_SIZE_MASK) >>
> +                       BCH_FLASHLAYOUT0_META_SIZE_OFFSET;
> +
> +       tmp = readl(&bch_regs->hw_bch_flash0layout1);
> +       l->data0_size = 4 * ((tmp & BCH_FLASHLAYOUT0_DATA0_SIZE_MASK) >>
> +                       BCH_FLASHLAYOUT0_DATA0_SIZE_OFFSET);
> +       l->ecc0 = (tmp & BCH_FLASHLAYOUT0_ECC0_MASK) >>
> +                       BCH_FLASHLAYOUT0_ECC0_OFFSET;
> +       l->datan_size = 4 * ((tmp & BCH_FLASHLAYOUT1_DATAN_SIZE_MASK) >>
> +                       BCH_FLASHLAYOUT1_DATAN_SIZE_OFFSET);
> +       l->eccn = (tmp & BCH_FLASHLAYOUT1_ECCN_MASK) >>
> +                       BCH_FLASHLAYOUT1_ECCN_OFFSET;
> +}
> +
> +/*
> + * Set BCH to specific layout used by ROM bootloader to read FCB.
> + */
> +void mxs_nand_mode_fcb(struct mtd_info *mtd)
> +{
> +       u32 tmp;
> +       struct mxs_bch_regs *bch_regs = (struct mxs_bch_regs *)MXS_BCH_BASE;
> +       struct nand_chip *nand = mtd_to_nand(mtd);
> +       struct mxs_nand_info *nand_info = nand_get_controller_data(nand);
> +
> +       nand_info->en_randomizer = 1;
> +
> +       mtd->writesize = 1024;
> +       mtd->oobsize = 1862 - 1024;
> +
> +       /* 8 ecc_chunks_*/
> +       tmp = 7 << BCH_FLASHLAYOUT0_NBLOCKS_OFFSET;
> +       /* 32 bytes for metadata */
> +       tmp |= 32 << BCH_FLASHLAYOUT0_META_SIZE_OFFSET;
> +       /* using ECC62 level to be performed */
> +       tmp |= 0x1F << BCH_FLASHLAYOUT0_ECC0_OFFSET;
> +       /* 0x20 * 4 bytes of the data0 block */
> +       tmp |= 0x20 << BCH_FLASHLAYOUT0_DATA0_SIZE_OFFSET;
> +       tmp |= 0 << BCH_FLASHLAYOUT0_GF13_0_GF14_1_OFFSET;
> +       writel(tmp, &bch_regs->hw_bch_flash0layout0);
> +
> +       /* 1024 for data + 838 for OOB */
> +       tmp = 1862 << BCH_FLASHLAYOUT1_PAGE_SIZE_OFFSET;
> +       /* using ECC62 level to be performed */
> +       tmp |= 0x1F << BCH_FLASHLAYOUT1_ECCN_OFFSET;
> +       /* 0x20 * 4 bytes of the data0 block */
> +       tmp |= 0x20 << BCH_FLASHLAYOUT1_DATAN_SIZE_OFFSET;
> +       tmp |= 0 << BCH_FLASHLAYOUT1_GF13_0_GF14_1_OFFSET;
> +       writel(tmp, &bch_regs->hw_bch_flash0layout1);
> +}
> +
> +/*
> + * Restore BCH to normal settings.
> + */
> +void mxs_nand_mode_normal(struct mtd_info *mtd)
> +{
> +       struct mxs_bch_regs *bch_regs = (struct mxs_bch_regs *)MXS_BCH_BASE;
> +       struct nand_chip *nand = mtd_to_nand(mtd);
> +       struct mxs_nand_info *nand_info = nand_get_controller_data(nand);
> +
> +       nand_info->en_randomizer = 0;
> +
> +       mtd->writesize = nand_info->writesize;
> +       mtd->oobsize = nand_info->oobsize;
> +
> +       writel(nand_info->bch_flash0layout0, &bch_regs->hw_bch_flash0layout0);
> +       writel(nand_info->bch_flash0layout1, &bch_regs->hw_bch_flash0layout1);
> +}
> +
> +uint32_t mxs_nand_mark_byte_offset(struct mtd_info *mtd)
> +{
> +       struct nand_chip *chip = mtd_to_nand(mtd);
> +       struct mxs_nand_info *nand_info = nand_get_controller_data(chip);
> +       struct bch_geometry *geo = &nand_info->bch_geometry;
> +
> +       return geo->block_mark_byte_offset;
> +}
> +
> +uint32_t mxs_nand_mark_bit_offset(struct mtd_info *mtd)
> +{
> +       struct nand_chip *chip = mtd_to_nand(mtd);
> +       struct mxs_nand_info *nand_info = nand_get_controller_data(chip);
> +       struct bch_geometry *geo = &nand_info->bch_geometry;
> +
> +       return geo->block_mark_bit_offset;
> +}
> diff --git a/include/mxs_nand.h b/include/mxs_nand.h
> index 4bd65cded9..ada20483d0 100644
> --- a/include/mxs_nand.h
> +++ b/include/mxs_nand.h
> @@ -66,8 +66,30 @@ struct mxs_nand_info {
>         /* DMA descriptors */
>         struct mxs_dma_desc     **desc;
>         uint32_t                desc_index;
> +
> +       /* Hardware BCH interface and randomizer */
> +       u32 en_randomizer;
> +       u32 writesize;
> +       u32 oobsize;
> +       u32 bch_flash0layout0;
> +       u32 bch_flash0layout1;
> +};
> +
> +struct mxs_nand_layout {
> +       u32 nblocks;
> +       u32 meta_size;
> +       u32 data0_size;
> +       u32 ecc0;
> +       u32 datan_size;
> +       u32 eccn;
>  };
>
>  int mxs_nand_init_ctrl(struct mxs_nand_info *nand_info);
>  int mxs_nand_init_spl(struct nand_chip *nand);
>  int mxs_nand_setup_ecc(struct mtd_info *mtd);
> +
> +void mxs_nand_mode_fcb(struct mtd_info *mtd);
> +void mxs_nand_mode_normal(struct mtd_info *mtd);
> +u32 mxs_nand_mark_byte_offset(struct mtd_info *mtd);
> +u32 mxs_nand_mark_bit_offset(struct mtd_info *mtd);
> +void mxs_nand_get_layout(struct mtd_info *mtd, struct mxs_nand_layout *l);
> --
> 2.17.1
>
> _______________________________________________
> U-Boot mailing list
> U-Boot at lists.denx.de
> https://lists.denx.de/listinfo/u-boot



-- 
Best regards
Oleksandr Suvorov

Toradex AG
Altsagenstrasse 5 | 6048 Horw/Luzern | Switzerland | T: +41 41 500
4800 (main line)


More information about the U-Boot mailing list