[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