[U-Boot] [PATCH resend V2 1/3] mtd: nand: mxs support oobsize bigger than 512

Tim Harvey tharvey at gateworks.com
Fri Jul 31 18:20:18 CEST 2015


On Tue, Jul 21, 2015 at 1:15 AM, Peng Fan <Peng.Fan at freescale.com> wrote:
> If ecc chunk data size is 512 and oobsize is bigger than 512, there is
> a chance that block_mark_bit_offset conflicts with bch ecc area.
>
> The following graph is modified from kernel gpmi-nand.c driver with
> each data block 512 bytes. We can see that Block Mark conflicts with
> ecc area from bch view. We can enlarge the ecc chunk size to avoid
> this problem to those oobsize which is larger than 512.
>
>    |                          P                                        |
>    |<----------------------------------------------------------------->|
>    |                                                                   |
>    |                                                (Block Mark)       |
>    |                      P'                             |           | |   |
>    |<--------------------------------------------------->|     D     | | O'|
>    |                                                     |<--------->| |<->|
>    V                                                     V           V V   V
>    +---+--------------+-+--------------+-+--------------+-+----------+-+---+
>    | M |   data       |E|   data       |E|   data       |E|   data   |E|   |
>    +---+--------------+-+--------------+-+--------------+-+----------+-+---+
>                                                         ^                  ^
>                                                         |         O        |
>                                                         |<---------------->|
>
>        P : the page size for BCH module.
>        E : The ECC strength.
>        G : the length of Galois Field.
>        N : The chunk count of per page.
>        M : the metasize of per page.
>        C : the ecc chunk size, aka the "data" above.
>        P': the nand chip's page size.
>        O : the nand chip's oob size.
>        O': the free oob.
>
> Signed-off-by: Peng Fan <Peng.Fan at freescale.com>
> Reviewed-by: Marek Vasut <marex at denx.de>
> ---
>
> Changes v2:
>  none
>
> Changes v1:
> The previous patch is https://patchwork.ozlabs.org/patch/422757/
> This version contains a minor change to the name from gf_len to galois_field.
> Also add Marek's Reviewed-by.
>
>  arch/arm/include/asm/imx-common/regs-bch.h |  2 ++
>  drivers/mtd/nand/mxs_nand.c                | 32 +++++++++++++++++++++---------
>  2 files changed, 25 insertions(+), 9 deletions(-)
>
> diff --git a/arch/arm/include/asm/imx-common/regs-bch.h b/arch/arm/include/asm/imx-common/regs-bch.h
> index a33d341..5c47783 100644
> --- a/arch/arm/include/asm/imx-common/regs-bch.h
> +++ b/arch/arm/include/asm/imx-common/regs-bch.h
> @@ -148,6 +148,7 @@ struct mxs_bch_regs {
>  #define        BCH_FLASHLAYOUT0_ECC0_ECC30                     (0xf << 12)
>  #define        BCH_FLASHLAYOUT0_ECC0_ECC32                     (0x10 << 12)
>  #define        BCH_FLASHLAYOUT0_GF13_0_GF14_1                  (1 << 10)
> +#define        BCH_FLASHLAYOUT0_GF13_0_GF14_1_OFFSET           10
>  #define        BCH_FLASHLAYOUT0_DATA0_SIZE_MASK                0xfff
>  #define        BCH_FLASHLAYOUT0_DATA0_SIZE_OFFSET              0
>
> @@ -178,6 +179,7 @@ struct mxs_bch_regs {
>  #define        BCH_FLASHLAYOUT1_ECCN_ECC30                     (0xf << 12)
>  #define        BCH_FLASHLAYOUT1_ECCN_ECC32                     (0x10 << 12)
>  #define        BCH_FLASHLAYOUT1_GF13_0_GF14_1                  (1 << 10)
> +#define        BCH_FLASHLAYOUT1_GF13_0_GF14_1_OFFSET           10
>  #define        BCH_FLASHLAYOUT1_DATAN_SIZE_MASK                0xfff
>  #define        BCH_FLASHLAYOUT1_DATAN_SIZE_OFFSET              0
>
> diff --git a/drivers/mtd/nand/mxs_nand.c b/drivers/mtd/nand/mxs_nand.c
> index 9c144a2..33ce817 100644
> --- a/drivers/mtd/nand/mxs_nand.c
> +++ b/drivers/mtd/nand/mxs_nand.c
> @@ -68,6 +68,8 @@ struct mxs_nand_info {
>  };
>
>  struct nand_ecclayout fake_ecc_layout;
> +static int chunk_data_size = MXS_NAND_CHUNK_DATA_CHUNK_SIZE;
> +static int galois_field = 13;
>
>  /*
>   * Cache management functions
> @@ -130,12 +132,12 @@ static void mxs_nand_return_dma_descs(struct mxs_nand_info *info)
>
>  static uint32_t mxs_nand_ecc_chunk_cnt(uint32_t page_data_size)
>  {
> -       return page_data_size / MXS_NAND_CHUNK_DATA_CHUNK_SIZE;
> +       return page_data_size / chunk_data_size;
>  }
>
>  static uint32_t mxs_nand_ecc_size_in_bits(uint32_t ecc_strength)
>  {
> -       return ecc_strength * MXS_NAND_BITS_PER_ECC_LEVEL;
> +       return ecc_strength * galois_field;
>  }
>
>  static uint32_t mxs_nand_aux_status_offset(void)
> @@ -157,8 +159,8 @@ static inline uint32_t mxs_nand_get_ecc_strength(uint32_t page_data_size,
>          *              (page oob size - meta data size) * (bits per byte)
>          */
>         ecc_strength = ((page_oob_size - MXS_NAND_METADATA_SIZE) * 8)
> -                       / (MXS_NAND_BITS_PER_ECC_LEVEL *
> -                               mxs_nand_ecc_chunk_cnt(page_data_size));
> +                       / (galois_field *
> +                          mxs_nand_ecc_chunk_cnt(page_data_size));
>
>         return round_down(ecc_strength, 2);
>  }
> @@ -173,7 +175,7 @@ static inline uint32_t mxs_nand_get_mark_offset(uint32_t page_data_size,
>         uint32_t block_mark_chunk_bit_offset;
>         uint32_t block_mark_bit_offset;
>
> -       chunk_data_size_in_bits = MXS_NAND_CHUNK_DATA_CHUNK_SIZE * 8;
> +       chunk_data_size_in_bits = chunk_data_size * 8;
>         chunk_ecc_size_in_bits  = mxs_nand_ecc_size_in_bits(ecc_strength);
>
>         chunk_total_size_in_bits =
> @@ -972,6 +974,16 @@ static int mxs_nand_scan_bbt(struct mtd_info *mtd)
>         struct mxs_bch_regs *bch_regs = (struct mxs_bch_regs *)MXS_BCH_BASE;
>         uint32_t tmp;
>
> +       if (mtd->oobsize > MXS_NAND_CHUNK_DATA_CHUNK_SIZE) {
> +               galois_field = 14;
> +               chunk_data_size = MXS_NAND_CHUNK_DATA_CHUNK_SIZE * 2;
> +       }
> +
> +       if (mtd->oobsize > chunk_data_size) {
> +               printf("Not support the NAND chips whose oob size is larger then %d bytes!\n", chunk_data_size);
> +               return -EINVAL;
> +       }
> +
>         /* Configure BCH and set NFC geometry */
>         mxs_reset_block(&bch_regs->hw_bch_ctrl_reg);
>
> @@ -981,16 +993,18 @@ static int mxs_nand_scan_bbt(struct mtd_info *mtd)
>         tmp |= MXS_NAND_METADATA_SIZE << BCH_FLASHLAYOUT0_META_SIZE_OFFSET;
>         tmp |= (mxs_nand_get_ecc_strength(mtd->writesize, mtd->oobsize) >> 1)
>                 << BCH_FLASHLAYOUT0_ECC0_OFFSET;
> -       tmp |= MXS_NAND_CHUNK_DATA_CHUNK_SIZE
> -               >> MXS_NAND_CHUNK_DATA_CHUNK_SIZE_SHIFT;
> +       tmp |= chunk_data_size >> MXS_NAND_CHUNK_DATA_CHUNK_SIZE_SHIFT;
> +       tmp |= (14 == galois_field ? 1 : 0) <<
> +               BCH_FLASHLAYOUT0_GF13_0_GF14_1_OFFSET;
>         writel(tmp, &bch_regs->hw_bch_flash0layout0);
>
>         tmp = (mtd->writesize + mtd->oobsize)
>                 << BCH_FLASHLAYOUT1_PAGE_SIZE_OFFSET;
>         tmp |= (mxs_nand_get_ecc_strength(mtd->writesize, mtd->oobsize) >> 1)
>                 << BCH_FLASHLAYOUT1_ECCN_OFFSET;
> -       tmp |= MXS_NAND_CHUNK_DATA_CHUNK_SIZE
> -               >> MXS_NAND_CHUNK_DATA_CHUNK_SIZE_SHIFT;
> +       tmp |= chunk_data_size >> MXS_NAND_CHUNK_DATA_CHUNK_SIZE_SHIFT;
> +       tmp |= (14 == galois_field ? 1 : 0) <<
> +               BCH_FLASHLAYOUT1_GF13_0_GF14_1_OFFSET;
>         writel(tmp, &bch_regs->hw_bch_flash0layout1);
>
>         /* Set *all* chip selects to use layout 0 */
> --
> 1.8.4
>

Tested on IMX6 with MT29F16G08 16Gb and MT29F2G08 2Gb NAND devices.

Tested-By: Tim Harvey <tharvey at gateworks.com>


More information about the U-Boot mailing list