Message ID | 20191021133859.23824-3-igor.opaniuk@gmail.com |
---|---|
State | Changes Requested |
Delegated to: | Stefano Babic |
Headers | show |
Series | imx: nandbcb: support for i.MX7 and bcb only updates | expand |
On Mon, Oct 21, 2019 at 4:41 PM Igor Opaniuk <igor.opaniuk@gmail.com> wrote: > > From: Igor Opaniuk <igor.opaniuk@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@toradex.com> > Signed-off-by: Anti Sullin <anti.sullin@artecdesign.ee> Reviewed-by: Oleksandr Suvorov <oleksandr.suvorov@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@lists.denx.de > https://lists.denx.de/listinfo/u-boot
On Mon, 2019-10-21 at 16:38 +0300, Igor Opaniuk wrote: > From: Igor Opaniuk <igor.opaniuk@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@toradex.com> > Signed-off-by: Anti Sullin <anti.sullin@artecdesign.ee> Tested-by: Max Krummenacher <max.krummenacher@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);
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);