[U-Boot] [PATCH 2/2] mtd:mxs:nand support oobsize bigger than 512
Peng Fan
B51431 at freescale.com
Tue Jan 20 07:35:58 CET 2015
Hi Marek,
And this one.
On 12/19/2014 12:39 PM, Peng Fan 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>
> ---
> arch/arm/include/asm/imx-common/regs-bch.h | 2 ++
> drivers/mtd/nand/mxs_nand.c | 33 ++++++++++++++++++++++--------
> 2 files changed, 27 insertions(+), 8 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 a45fcf9..0db9eb3 100644
> --- a/drivers/mtd/nand/mxs_nand.c
> +++ b/drivers/mtd/nand/mxs_nand.c
> @@ -29,6 +29,7 @@
>
> #define MXS_NAND_DMA_DESCRIPTOR_COUNT 4
>
> +#define MXS_NAND_MAX_CHUNK_DATA_CHUNK_SIZE 1024
> #define MXS_NAND_CHUNK_DATA_CHUNK_SIZE 512
> #if defined(CONFIG_MX6)
> #define MXS_NAND_CHUNK_DATA_CHUNK_SIZE_SHIFT 2
> @@ -68,6 +69,8 @@ struct mxs_nand_info {
> };
>
> struct nand_ecclayout fake_ecc_layout;
> +static int chunk_data_size = MXS_NAND_CHUNK_DATA_CHUNK_SIZE;
> +static int gf_len = 13;
>
> /*
> * Cache management functions
> @@ -130,12 +133,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 * 13;
> + return ecc_strength * gf_len;
> }
>
> static uint32_t mxs_nand_aux_status_offset(void)
> @@ -149,7 +152,7 @@ static inline uint32_t mxs_nand_get_ecc_strength(uint32_t page_data_size,
> int ecc_strength;
>
> ecc_strength = ((page_oob_size - MXS_NAND_METADATA_SIZE) * 8)
> - / (13 * mxs_nand_ecc_chunk_cnt(page_data_size));
> + / (gf_len * mxs_nand_ecc_chunk_cnt(page_data_size));
>
> return round_down(ecc_strength, 2);
> }
> @@ -164,7 +167,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 =
> @@ -963,6 +966,20 @@ 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_MAX_CHUNK_DATA_CHUNK_SIZE) {
> + printf("We do not support the NAND device whose oob size is larger then %d bytes!\n", MXS_NAND_MAX_CHUNK_DATA_CHUNK_SIZE);
> + return -EINVAL;
> + }
> +
> + /*
> + * If oobsize bigger than 512, galois filed should be 14, ecc chunk
> + * data size should be 1024 but not 512.
> + */
> + if (mtd->oobsize > MXS_NAND_CHUNK_DATA_CHUNK_SIZE) {
> + gf_len = 14;
> + chunk_data_size = MXS_NAND_MAX_CHUNK_DATA_CHUNK_SIZE;
> + }
> +
> /* Configure BCH and set NFC geometry */
> mxs_reset_block(&bch_regs->hw_bch_ctrl_reg);
>
> @@ -972,16 +989,16 @@ 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 == gf_len ? 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 == gf_len ? 1 : 0) << BCH_FLASHLAYOUT1_GF13_0_GF14_1_OFFSET;
> writel(tmp, &bch_regs->hw_bch_flash0layout1);
>
> /* Set *all* chip selects to use layout 0 */
Thanks,
Peng.
More information about the U-Boot
mailing list