From mboxrd@z Thu Jan 1 00:00:00 1970 From: Peng Fan Date: Tue, 20 Jan 2015 14:35:58 +0800 Subject: [U-Boot] [PATCH 2/2] mtd:mxs:nand support oobsize bigger than 512 In-Reply-To: <1418963953-1623-2-git-send-email-Peng.Fan@freescale.com> References: <1418963953-1623-1-git-send-email-Peng.Fan@freescale.com> <1418963953-1623-2-git-send-email-Peng.Fan@freescale.com> Message-ID: <54BDF74E.5030509@freescale.com> List-Id: MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit To: u-boot@lists.denx.de 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 > --- > 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.