Re: [U-Boot] [PATCH v1 9/9] arm: dts: imx7: colibri: add raw NAND support

2018-06-27 Thread Han Xu


On 04/20/2018 10:53 AM, Stefan Agner wrote:
> From: Stefan Agner 
> 
> Signed-off-by: Stefan Agner 
> ---
> 
>   arch/arm/dts/imx7-colibri.dts | 28 
>   1 file changed, 28 insertions(+)
> 
> diff --git a/arch/arm/dts/imx7-colibri.dts b/arch/arm/dts/imx7-colibri.dts
> index f6c21052ae..a3b5618b45 100644
> --- a/arch/arm/dts/imx7-colibri.dts
> +++ b/arch/arm/dts/imx7-colibri.dts
> @@ -17,6 +17,15 @@
>   };
>   };
>   
> +&gpmi {
> + pinctrl-names = "default";
> + pinctrl-0 = <&pinctrl_gpmi_nand>;
> + fsl,use-minimum-ecc;


enable minimum ecc may cause no backward compatible since previous 
implementation use oob space for ecc as much as possible. May consider 
mention this in docs and don't enable it by default?


> + nand-on-flash-bbt;
> + nand-ecc-mode = "hw";
> + status = "okay";
> +};
> +
>   &i2c1 {
>   pinctrl-names = "default", "gpio";
>   pinctrl-0 = <&pinctrl_i2c1>;
> @@ -49,6 +58,25 @@
>   };
>   
>   &iomuxc {
> + pinctrl_gpmi_nand: gpmi-nand-grp {
> + fsl,pins = <
> + MX7D_PAD_SD3_CLK__NAND_CLE  0x71
> + MX7D_PAD_SD3_CMD__NAND_ALE  0x71
> + MX7D_PAD_SAI1_TX_BCLK__NAND_CE0_B   0x71
> + MX7D_PAD_SAI1_TX_DATA__NAND_READY_B 0x74
> + MX7D_PAD_SD3_STROBE__NAND_RE_B  0x71
> + MX7D_PAD_SD3_RESET_B__NAND_WE_B 0x71
> + MX7D_PAD_SD3_DATA0__NAND_DATA00 0x71
> + MX7D_PAD_SD3_DATA1__NAND_DATA01 0x71
> + MX7D_PAD_SD3_DATA2__NAND_DATA02 0x71
> + MX7D_PAD_SD3_DATA3__NAND_DATA03 0x71
> + MX7D_PAD_SD3_DATA4__NAND_DATA04 0x71
> + MX7D_PAD_SD3_DATA5__NAND_DATA05 0x71
> + MX7D_PAD_SD3_DATA6__NAND_DATA06 0x71
> + MX7D_PAD_SD3_DATA7__NAND_DATA07 0x71
> + >;
> + };
> +
>   pinctrl_i2c4: i2c4-grp {
>   fsl,pins = <
>   MX7D_PAD_ENET1_RGMII_TD3__I2C4_SDA  0x407f
> 
___
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot


Re: [EXT] [PATCH] mtd: mxs_nand: default to legacy bch and rename to modern bch option

2022-03-17 Thread Han Xu
On Thu, Mar 17, 2022 at 8:27 AM Frieder Schrempf <
frieder.schre...@kontron.de> wrote:

> Hi Stefano,
>
> this old patch was delegated to you in patchwork. If you're not the
> correct maintainer to address, please let me know. As the NAND layer
> seems to be unmaintained at the moment, I'm not sure whom to ask.
>
> This patch fixes a regression that was introduced by 616f03dabacb ("
> mtd: gpmi: change the BCH layout setting for large oob NAND") which
> alters the BCH layout in a way that doesn't match with the
> implementation in the Linux kernel.
>
> This causes failures when loading an UBI image in U-Boot that was
> flashed by Linux or vice versa (see [1]).
>
> There has been an approach to fix this through an optional devicetree
> property in 51cdf83eea ("mtd: gpmi: provide the option to use legacy bch
> geometry"), but this is not acceptable. The "legacy" BCH layout
> compatible with Linux should be used by default.
>
> The approach to upstream the "new" layout to the kernel [2] seems to be
> stalled and even if it would succeed, it would break systems that use an
> old U-Boot and a new kernel, which is again not really acceptable in my
> opinion.


Hi Frieder,

I am not in office this week. I will send another patch set to change in
both kernel and u-boot to fix the compatible issue.


>
> For the reasons above I would like to ask U-Boot maintainers to pick up
> this patch.
>
> Thanks
> Frieder
>
> [1] https://lists.denx.de/pipermail/u-boot/2022-March/477828.html
> [2]
>
> https://patchwork.ozlabs.org/project/linux-mtd/patch/20210522205136.19465-2-han...@nxp.com/
>
> Am 20.05.21 um 11:09 schrieb Sean Nyekjaer:
> > On 13/05/2021 22.02, han.xu wrote:
> >> On 21/05/11 07:08AM, Sean Nyekjaer wrote:
> >>> Caution: EXT Email
> >>>
> >>> On 11/05/2021 04.49, han.xu wrote:
> >>>> On 21/05/10 12:00PM, Sean Nyekjaer wrote:
> >>>>> Caution: EXT Email
> >>>>>
> >>>>> Linux kernel defaults to use legacy bch setting, this was creating a
> >>>>> mismatch between U-boot and Linux default settings.
> >>>> Kernel uses the NAND chip specified minimum ecc strength and steps by
> default
> >>>> not the legacy bch setting, unless users enable it in DT file.
> >>>>
> >>>
> >>> Hi,
> >>>
> >>> Adding, mtd-list and Miquel
> >>>
> >>> With u-boot dtb:
> >>> &gpmi {
> >>> pinctrl-names = "default";
> >>> pinctrl-0 = <&pinctrl_gpmi_nand1>;
> >>> compatible = "fsl,imx7d-gpmi-nand";
> >>> nand-on-flash-bbt;
> >>> status = "okay";
> >>> };
> >>>
> >>> With linux dtb (mainline 5.10):
> >>> &gpmi {
> >>> pinctrl-names = "default";
> >>> pinctrl-0 = <&pinctrl_gpmi_nand1>;
> >>> nand-on-flash-bbt;
> >>> status = "okay";
> >>> };
> >>>
> >>> U-boot prior to commit 51cdf83eea selected 18 bit ECC, after that
> commit it selects 8 bits.
> >>> With legacy option it selects 18.
> >>> Linux is selecting 18 bits ;) So now we have a mismatch.
> >>>
> >>> I have been searching for the legacy option in the mainline kernel
> can't find it ;)
> >>> Please show me where it is (is it in the NXP fork?)
> >>
> >> You are right, it's only fixed in NXP fork, with kernel driver
> modification. We
> >> prefer the current u-boot bch geometry, so I will send out a kernel
> patch to
> >> make them align.
> >>
> > Any progress on this?
> >
> > I see your patch in:
> >
> https://eur04.safelinks.protection.outlook.com/?url=https%3A%2F%2Fsource.codeaurora.org%2Fexternal%2Fimx%2Flinux-imx%2Fcommit%2Fdrivers%2Fmtd%2Fnand%2Fraw%2Fgpmi-nand%3Fh%3Dimx_5.4.70_2.3.0%26id%3Dae980dccc6189956fab047958ad0a70ec4951439&data=04%7C01%7Cfrieder.schrempf%40kontron.de%7C275b7f11361e4fd3eb7e08d91b6f0e45%7C8c9d3c973fd941c8a2b1646f3942daf1%7C0%7C0%7C637570986066857865%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&sdata=L4xAN9HDl68dmA%2FX6nnP%2Buqh6CUKTQZJeFWja5EvmPI%3D&reserved=0
> >
> > But I can't find the option for selecting legacy mode in the
> devicetree...
> >
> > /Sean
>
> __
> Linux MTD discussion mailing list
> http://lists.infradead.org/mailman/listinfo/linux-mtd/
>
-- 
Sincerely,

Han XU


[PATCH] spi: nxp_fspi: reset the FLSHxCR1 registers

2023-09-13 Thread Han Xu
Reset the FLSHxCR1 registers to default value. ROM may set the register
value and it affects the SPI NAND normal functions.

Signed-off-by: Han Xu 
---
 drivers/spi/nxp_fspi.c | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/drivers/spi/nxp_fspi.c b/drivers/spi/nxp_fspi.c
index 579d6bac9b..5db27f9ae2 100644
--- a/drivers/spi/nxp_fspi.c
+++ b/drivers/spi/nxp_fspi.c
@@ -927,6 +927,13 @@ static int nxp_fspi_default_setup(struct nxp_fspi *f)
fspi_writel(f, FSPI_AHBCR_PREF_EN | FSPI_AHBCR_RDADDROPT,
base + FSPI_AHBCR);
 
+   /* Reset the flashx control1 registers */
+   reg = FSPI_FLSHXCR1_TCSH(0x3) | FSPI_FLSHXCR1_TCSS(0x3);
+   fspi_writel(f, reg, base + FSPI_FLSHA1CR1);
+   fspi_writel(f, reg, base + FSPI_FLSHA2CR1);
+   fspi_writel(f, reg, base + FSPI_FLSHB1CR1);
+   fspi_writel(f, reg, base + FSPI_FLSHB2CR1);
+
/* AHB Read - Set lut sequence ID for all CS. */
fspi_writel(f, SEQID_LUT, base + FSPI_FLSHA1CR2);
fspi_writel(f, SEQID_LUT, base + FSPI_FLSHA2CR2);
-- 
2.34.1



RE: [PATCH V2 2/4] mtd: nand: mxs_nand_spl: Fix bad block skipping

2022-04-27 Thread Han Xu



> -Original Message-
> From: Michael Trimarchi 
> Sent: Wednesday, April 27, 2022 12:50 AM
> To: Han Xu ; U-Boot-Denx 
> Cc: Ye Li ; Stefano Babic ; Miquel Raynal
> ; Fabio Estevam ; Dario
> Binacchi ; Sean Anderson
> ; linux-ker...@amarulasolutions.com; Jagan Teki
> ; Ariel D'Alessandro
> ; Fabio Estevam 
> Subject: [PATCH V2 2/4] mtd: nand: mxs_nand_spl: Fix bad block skipping
> 
> The specific implementation was having bug. Those bugs are since the beginning
> of the implementation. Some manufactures can receive this bug in their SPL 
> code.
> This bug start to be more visible on architecture that has complicated boot
> process like imx8mn. Older version of uboot has the same problem only if the
> bad block appear in correspoding of befine of u-boot image. In order to adjust
> the function we scan from the first block. The logic is not changed to have a
> simple way to fix without get regression.
> 
> The problematic part of old code was in this part:
> 
> while (is_badblock(mtd, offs, 1)) {
>page = page + nand_page_per_block;
>   /* Check i we've reached the end of flash. */
>   if (page >= mtd->size >> chip->page_shift) {
>   free(page_buf);
>   return -ENOMEM;
>  }
> }
> 
> Even we fix it adding increment of the offset of one erase block size we 
> don't fix
> the problem, because the first erase block where the image start is not 
> checked.

Could you please describe more details about your test? Thanks.

> The code was tested on an imx8mn where the boot rom api was not able to skip
> it. Apart of that other architecure are using this code and all boards that 
> has
> nand as boot device can be affected
> 
> Cc: Han Xu 
> Cc: Fabio Estevam 
> Signed-off-by: Michael Trimarchi 
> ---
> V1->V2:
>   - Adjust the commit message
>   - Add Cc Han Xu and Fabio
>   - fix size >= 0 to > 0
> ---
>  drivers/mtd/nand/raw/mxs_nand_spl.c | 90 -
>  1 file changed, 49 insertions(+), 41 deletions(-)
> 
> diff --git a/drivers/mtd/nand/raw/mxs_nand_spl.c
> b/drivers/mtd/nand/raw/mxs_nand_spl.c
> index 59a67ee414..2bfb181007 100644
> --- a/drivers/mtd/nand/raw/mxs_nand_spl.c
> +++ b/drivers/mtd/nand/raw/mxs_nand_spl.c
> @@ -218,14 +218,14 @@ void nand_init(void)
>   mxs_nand_setup_ecc(mtd);
>  }
> 
> -int nand_spl_load_image(uint32_t offs, unsigned int size, void *buf)
> +int nand_spl_load_image(uint32_t offs, unsigned int size, void *dst)
>  {
> - struct nand_chip *chip;
> - unsigned int page;
> + unsigned int sz;
> + unsigned int block, lastblock;
> + unsigned int page, page_offset;
>   unsigned int nand_page_per_block;
> - unsigned int sz = 0;
> + struct nand_chip *chip;
>   u8 *page_buf = NULL;
> - u32 page_off;
> 
>   chip = mtd_to_nand(mtd);
>   if (!chip->numchips)
> @@ -235,47 +235,42 @@ int nand_spl_load_image(uint32_t offs, unsigned int
> size, void *buf)
>   if (!page_buf)
>   return -ENOMEM;
> 
> - page = offs >> chip->page_shift;
> - page_off = offs & (mtd->writesize - 1);
> + /* offs has to be aligned to a page address! */
> + block = offs / mtd->erasesize;
> + lastblock = (offs + size - 1) / mtd->erasesize;
> + page = (offs % mtd->erasesize) / mtd->writesize;
> + page_offset = offs % mtd->writesize;
>   nand_page_per_block = mtd->erasesize / mtd->writesize;
> 
> - debug("%s offset:0x%08x len:%d page:%x\n", __func__, offs, size, page);
> -
> - while (size) {
> - if (mxs_read_page_ecc(mtd, page_buf, page) < 0)
> - return -1;
> -
> - if (size > (mtd->writesize - page_off))
> - sz = (mtd->writesize - page_off);
> - else
> - sz = size;
> -
> - memcpy(buf, page_buf + page_off, sz);
> -
> - offs += mtd->writesize;
> - page++;
> - buf += (mtd->writesize - page_off);
> - page_off = 0;
> - size -= sz;
> -
> - /*
> -  * Check if we have crossed a block boundary, and if so
> -  * check for bad block.
> -  */
> - if (!(page % nand_page_per_block)) {
> - /*
> -  * Yes, new block. See if this block is good. If not,
> -  * loop until we find a good block.
> -  */
> - while (i

Re: [PATCH V2 2/4] mtd: nand: mxs_nand_spl: Fix bad block skipping

2022-05-02 Thread Han Xu
On 22/05/01 08:36AM, Michael Nazzareno Trimarchi wrote:
> Dear Han and Fabio
> 
> On Thu, Apr 28, 2022 at 7:01 AM Michael Nazzareno Trimarchi
>  wrote:
> >
> > Hi
> >
> > On Thu, Apr 28, 2022 at 2:27 AM Han Xu  wrote:
> > >
> > >
> > >
> > > > -Original Message-
> > > > From: Michael Trimarchi 
> > > > Sent: Wednesday, April 27, 2022 12:50 AM
> > > > To: Han Xu ; U-Boot-Denx 
> > > > Cc: Ye Li ; Stefano Babic ; Miquel Raynal
> > > > ; Fabio Estevam ; Dario
> > > > Binacchi ; Sean Anderson
> > > > ; linux-ker...@amarulasolutions.com; Jagan Teki
> > > > ; Ariel D'Alessandro
> > > > ; Fabio Estevam 
> > > > Subject: [PATCH V2 2/4] mtd: nand: mxs_nand_spl: Fix bad block skipping
> > > >
> > > > The specific implementation was having bug. Those bugs are since the 
> > > > beginning
> > > > of the implementation. Some manufactures can receive this bug in their 
> > > > SPL code.
> > > > This bug start to be more visible on architecture that has complicated 
> > > > boot
> > > > process like imx8mn. Older version of uboot has the same problem only 
> > > > if the
> > > > bad block appear in correspoding of befine of u-boot image. In order to 
> > > > adjust
> > > > the function we scan from the first block. The logic is not changed to 
> > > > have a
> > > > simple way to fix without get regression.
> > > >
> > > > The problematic part of old code was in this part:
> > > >
> > > > while (is_badblock(mtd, offs, 1)) {
> > > >page = page + nand_page_per_block;
> > > >   /* Check i we've reached the end of flash. */
> > > >   if (page >= mtd->size >> chip->page_shift) {
> > > >   free(page_buf);
> > > >   return -ENOMEM;
> > > >  }
> > > > }
> > > >
> > > > Even we fix it adding increment of the offset of one erase block size 
> > > > we don't fix
> > > > the problem, because the first erase block where the image start is not 
> > > > checked.
> > >
> > > Could you please describe more details about your test? Thanks.
> >
> > Suppose you have a badblock on 5 or 6. Let's start to have only 6
> > and you write uboot from 5 and let's the uboot be enough big to cover 5, 6, 
> > 7, 8
> >
> >
> > Case 1)
> > When you write the block 6 the code will skip it as bad during
> > programming. THe image of uboot (or flash.bin) will
> > be on 5 7 8 9, because the 6 is skipped. The while loop on spl will
> > read (from raw offset the 5) and then he will found the
> > bad block on next erase block in the while loop and will exists at the
> > end of the flash because the test
> > is done on the offset and not on the page that is not incremented
> >
> > Case 2)
> >
> > Now same example but let's suppose to have block 5 bad. So you write
> > your image and it will start
> > from a raw offset 5 but it will be written starting from 6. The spl
> > loader will fail because it will not skip
> > the first block and then will fail anyway to read the image. The patch
> > try to fix the above behavior
> >
> > Case 3) can be any combination
> >
> 
> Do I need to resend v3?
> 
> Michael

It's not about the v3. I need to discuss some details with ROM team but
unfortunately they are all in vacation till May 5th. I will respond after the
discussion.

> 
> > Michael
> >
> >
> >
> > >
> > > > The code was tested on an imx8mn where the boot rom api was not able to 
> > > > skip
> > > > it. Apart of that other architecure are using this code and all boards 
> > > > that has
> > > > nand as boot device can be affected
> > > >
> > > > Cc: Han Xu 
> > > > Cc: Fabio Estevam 
> > > > Signed-off-by: Michael Trimarchi 
> > > > ---
> > > > V1->V2:
> > > >   - Adjust the commit message
> > > >   - Add Cc Han Xu and Fabio
> > > >   - fix size >= 0 to > 0
> > > > ---
> > > >  drivers/mtd/nand/raw/mxs_nand_spl.c | 90 -
> > > >  1 file changed, 49 insertions(+), 41 deletions(-)
> > > >
> > > > 

Re: [PATCH V2 1/4] nand: raw: mxs_nand: Fix specific hook registration

2022-05-06 Thread Han Xu
On 22/04/27 07:50AM, Michael Trimarchi wrote:
> Move the hook after nand_scan_tail is called. The hook must be replaced
> to the mxs specific one but those must to be assignment later in the
> probe function.
> 
> With this fix markbad is working again. Before this change:
> 
> nand markbad 0xDEC00
> NXS NAND: Writing OOB isn't supported
> NXS NAND: Writing OOB isn't supported
> block 0x000dec00 NOT marked as bad! ERROR 0
> 
> Cc: Han Xu 
> Cc: Fabio Estevam 
> Signed-off-by: Michael Trimarchi 

Acked-by: Han Xu 

> ---
> V1->V2:
>   - Adjust the commit message
>   - Add Cc Han Xu and Fabio
> ---
>  drivers/mtd/nand/raw/mxs_nand.c | 32 
>  1 file changed, 16 insertions(+), 16 deletions(-)
> 
> diff --git a/drivers/mtd/nand/raw/mxs_nand.c b/drivers/mtd/nand/raw/mxs_nand.c
> index ee5d7fde9c..53f24b9c4b 100644
> --- a/drivers/mtd/nand/raw/mxs_nand.c
> +++ b/drivers/mtd/nand/raw/mxs_nand.c
> @@ -1246,22 +1246,6 @@ int mxs_nand_setup_ecc(struct mtd_info *mtd)
>   /* Enable BCH complete interrupt */
>   writel(BCH_CTRL_COMPLETE_IRQ_EN, &bch_regs->hw_bch_ctrl_set);
>  
> - /* Hook some operations at the MTD level. */
> - if (mtd->_read_oob != mxs_nand_hook_read_oob) {
> - nand_info->hooked_read_oob = mtd->_read_oob;
> - mtd->_read_oob = mxs_nand_hook_read_oob;
> - }
> -
> - if (mtd->_write_oob != mxs_nand_hook_write_oob) {
> - nand_info->hooked_write_oob = mtd->_write_oob;
> - mtd->_write_oob = mxs_nand_hook_write_oob;
> - }
> -
> - if (mtd->_block_markbad != mxs_nand_hook_block_markbad) {
> - nand_info->hooked_block_markbad = mtd->_block_markbad;
> - mtd->_block_markbad = mxs_nand_hook_block_markbad;
> - }
> -
>   return 0;
>  }
>  
> @@ -1467,6 +1451,22 @@ int mxs_nand_init_ctrl(struct mxs_nand_info *nand_info)
>   if (err)
>   goto err_free_buffers;
>  
> + /* Hook some operations at the MTD level. */
> + if (mtd->_read_oob != mxs_nand_hook_read_oob) {
> + nand_info->hooked_read_oob = mtd->_read_oob;
> + mtd->_read_oob = mxs_nand_hook_read_oob;
> + }
> +
> + if (mtd->_write_oob != mxs_nand_hook_write_oob) {
> + nand_info->hooked_write_oob = mtd->_write_oob;
> + mtd->_write_oob = mxs_nand_hook_write_oob;
> + }
> +
> + if (mtd->_block_markbad != mxs_nand_hook_block_markbad) {
> + nand_info->hooked_block_markbad = mtd->_block_markbad;
> + mtd->_block_markbad = mxs_nand_hook_block_markbad;
> + }
> +
>   err = nand_register(0, mtd);
>   if (err)
>   goto err_free_buffers;
> -- 
> 2.25.1
> 


Re: [PATCH V2 2/4] mtd: nand: mxs_nand_spl: Fix bad block skipping

2022-05-06 Thread Han Xu
On 22/04/27 07:50AM, Michael Trimarchi wrote:
> The specific implementation was having bug. Those bugs are since
> the beginning of the implementation. Some manufactures can receive
> this bug in their SPL code. This bug start to be more visible on
> architecture that has complicated boot process like imx8mn. Older
> version of uboot has the same problem only if the bad block
> appear in correspoding of befine of u-boot image. In order to
> adjust the function we scan from the first block. The logic
> is not changed to have a simple way to fix without get regression.
> 
> The problematic part of old code was in this part:
> 
> while (is_badblock(mtd, offs, 1)) {
>page = page + nand_page_per_block;
>   /* Check i we've reached the end of flash. */
>   if (page >= mtd->size >> chip->page_shift) {
>   free(page_buf);
>   return -ENOMEM;
>  }
> }
> 
> Even we fix it adding increment of the offset of one erase block size
> we don't fix the problem, because the first erase block where the
> image start is not checked. The code was tested on an imx8mn where
> the boot rom api was not able to skip it. Apart of that other
> architecure are using this code and all boards that has nand as boot
> device can be affected
> 
> Cc: Han Xu 
> Cc: Fabio Estevam 
> Signed-off-by: Michael Trimarchi 

Acked-by: Han Xu 

> ---
> V1->V2:
>   - Adjust the commit message
>   - Add Cc Han Xu and Fabio
>   - fix size >= 0 to > 0
> ---
>  drivers/mtd/nand/raw/mxs_nand_spl.c | 90 -
>  1 file changed, 49 insertions(+), 41 deletions(-)
> 
> diff --git a/drivers/mtd/nand/raw/mxs_nand_spl.c 
> b/drivers/mtd/nand/raw/mxs_nand_spl.c
> index 59a67ee414..2bfb181007 100644
> --- a/drivers/mtd/nand/raw/mxs_nand_spl.c
> +++ b/drivers/mtd/nand/raw/mxs_nand_spl.c
> @@ -218,14 +218,14 @@ void nand_init(void)
>   mxs_nand_setup_ecc(mtd);
>  }
>  
> -int nand_spl_load_image(uint32_t offs, unsigned int size, void *buf)
> +int nand_spl_load_image(uint32_t offs, unsigned int size, void *dst)
>  {
> - struct nand_chip *chip;
> - unsigned int page;
> + unsigned int sz;
> + unsigned int block, lastblock;
> + unsigned int page, page_offset;
>   unsigned int nand_page_per_block;
> - unsigned int sz = 0;
> + struct nand_chip *chip;
>   u8 *page_buf = NULL;
> - u32 page_off;
>  
>   chip = mtd_to_nand(mtd);
>   if (!chip->numchips)
> @@ -235,47 +235,42 @@ int nand_spl_load_image(uint32_t offs, unsigned int 
> size, void *buf)
>   if (!page_buf)
>   return -ENOMEM;
>  
> - page = offs >> chip->page_shift;
> - page_off = offs & (mtd->writesize - 1);
> + /* offs has to be aligned to a page address! */
> + block = offs / mtd->erasesize;
> + lastblock = (offs + size - 1) / mtd->erasesize;
> + page = (offs % mtd->erasesize) / mtd->writesize;
> + page_offset = offs % mtd->writesize;
>   nand_page_per_block = mtd->erasesize / mtd->writesize;
>  
> - debug("%s offset:0x%08x len:%d page:%x\n", __func__, offs, size, page);
> -
> - while (size) {
> - if (mxs_read_page_ecc(mtd, page_buf, page) < 0)
> - return -1;
> -
> - if (size > (mtd->writesize - page_off))
> - sz = (mtd->writesize - page_off);
> - else
> - sz = size;
> -
> - memcpy(buf, page_buf + page_off, sz);
> -
> - offs += mtd->writesize;
> - page++;
> - buf += (mtd->writesize - page_off);
> - page_off = 0;
> - size -= sz;
> -
> - /*
> -  * Check if we have crossed a block boundary, and if so
> -  * check for bad block.
> -  */
> - if (!(page % nand_page_per_block)) {
> - /*
> -  * Yes, new block. See if this block is good. If not,
> -  * loop until we find a good block.
> -  */
> - while (is_badblock(mtd, offs, 1)) {
> - page = page + nand_page_per_block;
> - /* Check i we've reached the end of flash. */
> - if (page >= mtd->size >> chip->page_shift) {
> + while (block <= lastblock && size > 0) {
> + if (!is_badblock(mtd, mtd->erasesize * block, 1)) {
> + /* Skip bad blocks */
> + 

Re: [PATCH V2 3/4] arm: mach-imx: cmd_nandbcb fix bad block handling

2022-05-06 Thread Han Xu
On 22/04/27 07:50AM, Michael Trimarchi wrote:
> The badblock should be skipped properly in reading and writing.
> Fix the logic. The bcb struct is written, skipping the bad block,
> so we need to read using the same logic. This was tested create
> bad block in the area and then flash it and read it back.
> 
> Cc: Han Xu 
> Cc: Fabio Estevam 
> Signed-off-by: Michael Trimarchi 

Acked-by: Han Xu 

> ---
> V1->V2:
>   - Adjust the commit message
>   - Add Cc Han Xu and Fabio
>   - move out from RFC
> ---
>  arch/arm/mach-imx/cmd_nandbcb.c | 21 +++--
>  1 file changed, 7 insertions(+), 14 deletions(-)
> 
> diff --git a/arch/arm/mach-imx/cmd_nandbcb.c b/arch/arm/mach-imx/cmd_nandbcb.c
> index f119e9f88d..c54f52b343 100644
> --- a/arch/arm/mach-imx/cmd_nandbcb.c
> +++ b/arch/arm/mach-imx/cmd_nandbcb.c
> @@ -506,10 +506,6 @@ static int read_fcb(struct boot_config *boot_cfg, struct 
> fcb_block *fcb,
>   int ret = 0;
>  
>   mtd = boot_cfg->mtd;
> - if (mtd_block_isbad(mtd, off)) {
> - printf("Block %d is bad, skipped\n", (int)CONV_TO_BLOCKS(off));
> - return 1;
> - }
>  
>   fcb_raw_page = kzalloc(mtd->writesize + mtd->oobsize, GFP_KERNEL);
>   if (!fcb_raw_page) {
> @@ -530,7 +526,7 @@ static int read_fcb(struct boot_config *boot_cfg, struct 
> fcb_block *fcb,
>   else if (plat_config.misc_flags & FCB_ENCODE_BCH_40b)
>   mxs_nand_mode_fcb_40bit(mtd);
>  
> - ret = nand_read(mtd, off, &size, (u_char *)fcb);
> + ret = nand_read_skip_bad(mtd, off, &size, NULL, mtd->size, 
> (u_char *)fcb);
>  
>   /* switch BCH back */
>   mxs_nand_mode_normal(mtd);
> @@ -617,6 +613,7 @@ static int write_fcb(struct boot_config *boot_cfg, struct 
> fcb_block *fcb)
>   for (i = 0; i < g_boot_search_count; i++) {
>   if (mtd_block_isbad(mtd, off)) {
>   printf("Block %d is bad, skipped\n", i);
> + off += mtd->erasesize;
>   continue;
>   }
>  
> @@ -676,20 +673,15 @@ static int read_dbbt(struct boot_config *boot_cfg, 
> struct dbbt_block *dbbt,
> void *dbbt_data_page, loff_t off)
>  {
>   size_t size;
> + size_t actual_size;
>   struct mtd_info *mtd;
>   loff_t to;
>   int ret;
>  
>   mtd = boot_cfg->mtd;
>  
> - if (mtd_block_isbad(mtd, off)) {
> - printf("Block %d is bad, skipped\n",
> -(int)CONV_TO_BLOCKS(off));
> - return 1;
> - }
> -
>   size = sizeof(struct dbbt_block);
> - ret = nand_read(mtd, off, &size, (u_char *)dbbt);
> + ret = nand_read_skip_bad(mtd, off, &size, &actual_size, mtd->size, 
> (u_char *)dbbt);
>   printf("NAND DBBT read from 0x%llx offset 0x%zx read: %s\n",
>  off, size, ret ? "ERROR" : "OK");
>   if (ret)
> @@ -697,9 +689,9 @@ static int read_dbbt(struct boot_config *boot_cfg, struct 
> dbbt_block *dbbt,
>  
>   /* dbbtpages == 0 if no bad blocks */
>   if (dbbt->dbbtpages > 0) {
> - to = off + 4 * mtd->writesize;
> + to = off + 4 * mtd->writesize + actual_size - size;
>   size = mtd->writesize;
> - ret = nand_read(mtd, to, &size, dbbt_data_page);
> + ret = nand_read_skip_bad(mtd, to, &size, NULL, mtd->size, 
> dbbt_data_page);
>   printf("DBBT data read from 0x%llx offset 0x%zx read: %s\n",
>  to, size, ret ? "ERROR" : "OK");
>  
> @@ -729,6 +721,7 @@ static int write_dbbt(struct boot_config *boot_cfg, 
> struct dbbt_block *dbbt,
>   if (mtd_block_isbad(mtd, off)) {
>   printf("Block %d is bad, skipped\n",
>  (int)(i + CONV_TO_BLOCKS(off)));
> + off += mtd->erasesize;
>   continue;
>   }
>  
> -- 
> 2.25.1
> 


Re: [PATCH 4/4] spl: spl_nand: Fix bad block handling in fitImage

2022-05-06 Thread Han Xu
On 22/04/27 07:50AM, Michael Trimarchi wrote:
> If the fitImage has some bad block in fit image area, the
> offset must be recalulcated. This should be done always.
> After implementing it in mxs now is possible to call the function
> even for that platform.
> 
> Cc: Fabio Estevam 
> Signed-off-by: Michael Trimarchi 

Acked-by: Han Xu 

> ---
> V1->V2:
>   - move out from RFC
> ---
>  common/spl/spl_nand.c | 5 +
>  1 file changed, 1 insertion(+), 4 deletions(-)
> 
> diff --git a/common/spl/spl_nand.c b/common/spl/spl_nand.c
> index fc61b447a5..82a10ffa63 100644
> --- a/common/spl/spl_nand.c
> +++ b/common/spl/spl_nand.c
> @@ -43,15 +43,12 @@ static ulong spl_nand_fit_read(struct spl_load_info 
> *load, ulong offs,
>  ulong size, void *dst)
>  {
>   int err;
> -#ifdef CONFIG_SYS_NAND_BLOCK_SIZE
>   ulong sector;
>  
>   sector = *(int *)load->priv;
> - offs = sector + nand_spl_adjust_offset(sector, offs - sector);
> -#else
>   offs *= load->bl_len;
>   size *= load->bl_len;
> -#endif
> + offs = sector + nand_spl_adjust_offset(sector, offs - sector);
>   err = nand_spl_load_image(offs, size, dst);
>   if (err)
>   return 0;
> -- 
> 2.25.1
> 


[PATCH] mtd: gpmi: fix the gpmi bch setting unalignment issue

2022-03-21 Thread Han Xu
The code change fixed the kernel gpmi bch setting not aligned with
u-boot settings issue. It still uses the legacy bch geometry as the
default option. If users need to choose the minimum ecc strength that
NAND chips required, it can be enabled by either adding DT flag
"fsl,use-minimum-ecc" or CONFIG_NAND_MXS_USE_MINIMUM_ECC in configs.

Fixes: 51cdf83eea mtd: gpmi: provide the option to use legacy bch geometry
Signed-off-by: Han Xu 
---
 drivers/mtd/nand/raw/mxs_nand.c | 71 -
 1 file changed, 62 insertions(+), 9 deletions(-)

diff --git a/drivers/mtd/nand/raw/mxs_nand.c b/drivers/mtd/nand/raw/mxs_nand.c
index 748056a43e..ee5d7fde9c 100644
--- a/drivers/mtd/nand/raw/mxs_nand.c
+++ b/drivers/mtd/nand/raw/mxs_nand.c
@@ -195,6 +195,7 @@ static inline int mxs_nand_legacy_calc_ecc_layout(struct 
bch_geometry *geo,
struct nand_chip *chip = mtd_to_nand(mtd);
struct mxs_nand_info *nand_info = nand_get_controller_data(chip);
unsigned int block_mark_bit_offset;
+   int corr, ds_corr;
 
/* The default for the length of Galois Field. */
geo->gf_len = 13;
@@ -225,6 +226,17 @@ static inline int mxs_nand_legacy_calc_ecc_layout(struct 
bch_geometry *geo,
geo->ecc_strength = min(round_down(geo->ecc_strength, 2),
nand_info->max_ecc_strength_supported);
 
+   /* check ecc strength, same as nand_ecc_is_strong_enough() did*/
+   if (chip->ecc_step_ds) {
+   corr = mtd->writesize * geo->ecc_strength /
+  geo->ecc_chunkn_size;
+   ds_corr = mtd->writesize * chip->ecc_strength_ds /
+  chip->ecc_step_ds;
+   if (corr < ds_corr ||
+   geo->ecc_strength < chip->ecc_strength_ds)
+   return -EINVAL;
+   }
+
block_mark_bit_offset = mtd->writesize * 8 -
(geo->ecc_strength * geo->gf_len * (geo->ecc_chunk_count - 1)
+ MXS_NAND_METADATA_SIZE * 8);
@@ -,6 +1123,7 @@ static int mxs_nand_set_geometry(struct mtd_info *mtd, 
struct bch_geometry *geo)
struct nand_chip *chip = mtd_to_nand(mtd);
struct nand_chip *nand = mtd_to_nand(mtd);
struct mxs_nand_info *nand_info = nand_get_controller_data(nand);
+   int err;
 
if (chip->ecc_strength_ds > nand_info->max_ecc_strength_supported) {
printf("unsupported NAND chip, minimum ecc required %d\n"
@@ -1118,19 +1131,57 @@ static int mxs_nand_set_geometry(struct mtd_info *mtd, 
struct bch_geometry *geo)
return -EINVAL;
}
 
-   if ((!(chip->ecc_strength_ds > 0 && chip->ecc_step_ds > 0) &&
-mtd->oobsize < 1024) || nand_info->legacy_bch_geometry) {
-   dev_warn(mtd->dev, "use legacy bch geometry\n");
-   return mxs_nand_legacy_calc_ecc_layout(geo, mtd);
+   /* use the legacy bch setting by default */
+   if ((!nand_info->use_minimum_ecc && mtd->oobsize < 1024) ||
+   !(chip->ecc_strength_ds > 0 && chip->ecc_step_ds > 0)) {
+   dev_dbg(mtd->dev, "use legacy bch geometry\n");
+   err = mxs_nand_legacy_calc_ecc_layout(geo, mtd);
+   if (!err)
+   return 0;
}
 
-   if (mtd->oobsize > 1024 || chip->ecc_step_ds < mtd->oobsize)
-   return mxs_nand_calc_ecc_for_large_oob(geo, mtd);
+   /* for large oob nand */
+   if (mtd->oobsize > 1024) {
+   dev_dbg(mtd->dev, "use large oob bch geometry\n");
+   err = mxs_nand_calc_ecc_for_large_oob(geo, mtd);
+   if (!err)
+   return 0;
+   }
 
-   return mxs_nand_calc_ecc_layout_by_info(geo, mtd,
-   chip->ecc_strength_ds, chip->ecc_step_ds);
+   /* otherwise use the minimum ecc nand chips required */
+   dev_dbg(mtd->dev, "use minimum ecc bch geometry\n");
+   err = mxs_nand_calc_ecc_layout_by_info(geo, mtd, chip->ecc_strength_ds,
+  chip->ecc_step_ds);
 
-   return 0;
+   if (err)
+   dev_err(mtd->dev, "none of the bch geometry setting works\n");
+
+   return err;
+}
+
+void mxs_nand_dump_geo(struct mtd_info *mtd)
+{
+   struct nand_chip *nand = mtd_to_nand(mtd);
+   struct mxs_nand_info *nand_info = nand_get_controller_data(nand);
+   struct bch_geometry *geo = &nand_info->bch_geometry;
+
+   dev_dbg(mtd->dev, "BCH Geometry :\n"
+   "GF Length\t\t: %u\n"
+   "ECC Strength\t\t: %u\n"
+   "ECC for Meta\t\t: %u\n"
+   &qu

Re: [PATCH] mtd: gpmi: fix the gpmi bch setting unalignment issue

2022-03-23 Thread Han Xu
On 22/03/22 12:34PM, Tim Harvey wrote:
> On Mon, Mar 21, 2022 at 1:37 PM Han Xu  wrote:
> >
> > The code change fixed the kernel gpmi bch setting not aligned with
> > u-boot settings issue. It still uses the legacy bch geometry as the
> > default option. If users need to choose the minimum ecc strength that
> > NAND chips required, it can be enabled by either adding DT flag
> > "fsl,use-minimum-ecc" or CONFIG_NAND_MXS_USE_MINIMUM_ECC in configs.
> >
> > Fixes: 51cdf83eea mtd: gpmi: provide the option to use legacy bch geometry
> > Signed-off-by: Han Xu 
> > ---
> >  drivers/mtd/nand/raw/mxs_nand.c | 71 -
> >  1 file changed, 62 insertions(+), 9 deletions(-)
> >
> > diff --git a/drivers/mtd/nand/raw/mxs_nand.c 
> > b/drivers/mtd/nand/raw/mxs_nand.c
> > index 748056a43e..ee5d7fde9c 100644
> > --- a/drivers/mtd/nand/raw/mxs_nand.c
> > +++ b/drivers/mtd/nand/raw/mxs_nand.c
> > @@ -195,6 +195,7 @@ static inline int 
> > mxs_nand_legacy_calc_ecc_layout(struct bch_geometry *geo,
> > struct nand_chip *chip = mtd_to_nand(mtd);
> > struct mxs_nand_info *nand_info = nand_get_controller_data(chip);
> > unsigned int block_mark_bit_offset;
> > +   int corr, ds_corr;
> >
> > /* The default for the length of Galois Field. */
> > geo->gf_len = 13;
> > @@ -225,6 +226,17 @@ static inline int 
> > mxs_nand_legacy_calc_ecc_layout(struct bch_geometry *geo,
> > geo->ecc_strength = min(round_down(geo->ecc_strength, 2),
> > nand_info->max_ecc_strength_supported);
> >
> > +   /* check ecc strength, same as nand_ecc_is_strong_enough() did*/
> > +   if (chip->ecc_step_ds) {
> > +   corr = mtd->writesize * geo->ecc_strength /
> > +  geo->ecc_chunkn_size;
> > +   ds_corr = mtd->writesize * chip->ecc_strength_ds /
> > +  chip->ecc_step_ds;
> > +   if (corr < ds_corr ||
> > +   geo->ecc_strength < chip->ecc_strength_ds)
> > +   return -EINVAL;
> > +   }
> > +
> > block_mark_bit_offset = mtd->writesize * 8 -
> > (geo->ecc_strength * geo->gf_len * (geo->ecc_chunk_count - 
> > 1)
> > + MXS_NAND_METADATA_SIZE * 8);
> > @@ -,6 +1123,7 @@ static int mxs_nand_set_geometry(struct mtd_info 
> > *mtd, struct bch_geometry *geo)
> > struct nand_chip *chip = mtd_to_nand(mtd);
> > struct nand_chip *nand = mtd_to_nand(mtd);
> > struct mxs_nand_info *nand_info = nand_get_controller_data(nand);
> > +   int err;
> >
> > if (chip->ecc_strength_ds > nand_info->max_ecc_strength_supported) {
> > printf("unsupported NAND chip, minimum ecc required %d\n"
> > @@ -1118,19 +1131,57 @@ static int mxs_nand_set_geometry(struct mtd_info 
> > *mtd, struct bch_geometry *geo)
> > return -EINVAL;
> > }
> >
> > -   if ((!(chip->ecc_strength_ds > 0 && chip->ecc_step_ds > 0) &&
> > -mtd->oobsize < 1024) || nand_info->legacy_bch_geometry) {
> > -   dev_warn(mtd->dev, "use legacy bch geometry\n");
> > -   return mxs_nand_legacy_calc_ecc_layout(geo, mtd);
> > +   /* use the legacy bch setting by default */
> > +   if ((!nand_info->use_minimum_ecc && mtd->oobsize < 1024) ||
> > +   !(chip->ecc_strength_ds > 0 && chip->ecc_step_ds > 0)) {
> > +   dev_dbg(mtd->dev, "use legacy bch geometry\n");
> > +   err = mxs_nand_legacy_calc_ecc_layout(geo, mtd);
> > +   if (!err)
> > +   return 0;
> > }
> >
> > -   if (mtd->oobsize > 1024 || chip->ecc_step_ds < mtd->oobsize)
> > -   return mxs_nand_calc_ecc_for_large_oob(geo, mtd);
> > +   /* for large oob nand */
> > +   if (mtd->oobsize > 1024) {
> > +   dev_dbg(mtd->dev, "use large oob bch geometry\n");
> > +   err = mxs_nand_calc_ecc_for_large_oob(geo, mtd);
> > +   if (!err)
> > +   return 0;
> > +   }
> >
> > -   return mxs_nand_calc_ecc_layout_by_info(geo, mtd,
> > -   chip->ecc_strength_ds, ch

[PATCH v2] mtd: gpmi: fix the bch setting backward compatible issue

2022-03-23 Thread Han Xu
Previous u-boot code changed the default bch setting behavior and caused
backward compatible issue. This fix choose the legacy bch geometry back
again as the default option. If the minimum ecc strength that NAND chips
required need to be chosen, it can be enabled by either adding DT flag
"fsl,use-minimum-ecc" or CONFIG_NAND_MXS_USE_MINIMUM_ECC in configs. The
unused flag "fsl,legacy-bch-geometry" get removed.

Fixes: 51cdf83eea mtd: gpmi: provide the option to use legacy bch geometry
Fixes: 616f03daba mtd: gpmi: change the BCH layout setting for large oob NAND
Tested-by: Tim Harvey 
Signed-off-by: Han Xu 

Changes in v2:
-- change the commit log about backward compatible issue is in u-boot
-- removed the unused flag
-- add fixes and test tag
---
 drivers/mtd/nand/raw/mxs_nand.c| 71 ++
 drivers/mtd/nand/raw/mxs_nand_dt.c |  2 -
 include/mxs_nand.h |  2 -
 3 files changed, 62 insertions(+), 13 deletions(-)

diff --git a/drivers/mtd/nand/raw/mxs_nand.c b/drivers/mtd/nand/raw/mxs_nand.c
index 748056a43e..ee5d7fde9c 100644
--- a/drivers/mtd/nand/raw/mxs_nand.c
+++ b/drivers/mtd/nand/raw/mxs_nand.c
@@ -195,6 +195,7 @@ static inline int mxs_nand_legacy_calc_ecc_layout(struct 
bch_geometry *geo,
struct nand_chip *chip = mtd_to_nand(mtd);
struct mxs_nand_info *nand_info = nand_get_controller_data(chip);
unsigned int block_mark_bit_offset;
+   int corr, ds_corr;
 
/* The default for the length of Galois Field. */
geo->gf_len = 13;
@@ -225,6 +226,17 @@ static inline int mxs_nand_legacy_calc_ecc_layout(struct 
bch_geometry *geo,
geo->ecc_strength = min(round_down(geo->ecc_strength, 2),
nand_info->max_ecc_strength_supported);
 
+   /* check ecc strength, same as nand_ecc_is_strong_enough() did*/
+   if (chip->ecc_step_ds) {
+   corr = mtd->writesize * geo->ecc_strength /
+  geo->ecc_chunkn_size;
+   ds_corr = mtd->writesize * chip->ecc_strength_ds /
+  chip->ecc_step_ds;
+   if (corr < ds_corr ||
+   geo->ecc_strength < chip->ecc_strength_ds)
+   return -EINVAL;
+   }
+
block_mark_bit_offset = mtd->writesize * 8 -
(geo->ecc_strength * geo->gf_len * (geo->ecc_chunk_count - 1)
+ MXS_NAND_METADATA_SIZE * 8);
@@ -,6 +1123,7 @@ static int mxs_nand_set_geometry(struct mtd_info *mtd, 
struct bch_geometry *geo)
struct nand_chip *chip = mtd_to_nand(mtd);
struct nand_chip *nand = mtd_to_nand(mtd);
struct mxs_nand_info *nand_info = nand_get_controller_data(nand);
+   int err;
 
if (chip->ecc_strength_ds > nand_info->max_ecc_strength_supported) {
printf("unsupported NAND chip, minimum ecc required %d\n"
@@ -1118,19 +1131,57 @@ static int mxs_nand_set_geometry(struct mtd_info *mtd, 
struct bch_geometry *geo)
return -EINVAL;
}
 
-   if ((!(chip->ecc_strength_ds > 0 && chip->ecc_step_ds > 0) &&
-mtd->oobsize < 1024) || nand_info->legacy_bch_geometry) {
-   dev_warn(mtd->dev, "use legacy bch geometry\n");
-   return mxs_nand_legacy_calc_ecc_layout(geo, mtd);
+   /* use the legacy bch setting by default */
+   if ((!nand_info->use_minimum_ecc && mtd->oobsize < 1024) ||
+   !(chip->ecc_strength_ds > 0 && chip->ecc_step_ds > 0)) {
+   dev_dbg(mtd->dev, "use legacy bch geometry\n");
+   err = mxs_nand_legacy_calc_ecc_layout(geo, mtd);
+   if (!err)
+   return 0;
}
 
-   if (mtd->oobsize > 1024 || chip->ecc_step_ds < mtd->oobsize)
-   return mxs_nand_calc_ecc_for_large_oob(geo, mtd);
+   /* for large oob nand */
+   if (mtd->oobsize > 1024) {
+   dev_dbg(mtd->dev, "use large oob bch geometry\n");
+   err = mxs_nand_calc_ecc_for_large_oob(geo, mtd);
+   if (!err)
+   return 0;
+   }
 
-   return mxs_nand_calc_ecc_layout_by_info(geo, mtd,
-   chip->ecc_strength_ds, chip->ecc_step_ds);
+   /* otherwise use the minimum ecc nand chips required */
+   dev_dbg(mtd->dev, "use minimum ecc bch geometry\n");
+   err = mxs_nand_calc_ecc_layout_by_info(geo, mtd, chip->ecc_strength_ds,
+  chip->ecc_step_ds);
 
-   return 0;
+   if (err)
+   dev_err(mtd->dev, "none of the bch geometry setting works\n");
+
+   return err;
+}
+
+void mxs_nand_dump_geo(struct mtd_info *mtd)
+{
+

[PATCH v3] mtd: gpmi: fix the bch setting backward compatible issue

2022-03-24 Thread Han Xu
Previous u-boot code changed the default bch setting behavior and caused
backward compatible issue. This fix choose the legacy bch geometry back
again as the default option. If the minimum ecc strength that NAND chips
required need to be chosen, it can be enabled by either adding DT flag
"fsl,use-minimum-ecc" or CONFIG_NAND_MXS_USE_MINIMUM_ECC in configs. The
unused flag "fsl,legacy-bch-geometry" get removed.

Fixes: 51cdf83eea (mtd: gpmi: provide the option to use legacy bch geometry)
Fixes: 616f03daba (mtd: gpmi: change the BCH layout setting for large
oob NAND)
Tested-by: Tim Harvey 
Tested-by: Sean Nyekjaer 
Signed-off-by: Han Xu 

---
Changes in v2:
 - change the commit log about backward compatible issue is in u-boot
 - removed the unused flag
 - add fixes and test tag

Changes in v3:
 - fix the fixes syntax
 - fix the change log syntax
 - add more test tag
---
 drivers/mtd/nand/raw/mxs_nand.c| 71 ++
 drivers/mtd/nand/raw/mxs_nand_dt.c |  2 -
 include/mxs_nand.h |  2 -
 3 files changed, 62 insertions(+), 13 deletions(-)

diff --git a/drivers/mtd/nand/raw/mxs_nand.c b/drivers/mtd/nand/raw/mxs_nand.c
index 748056a43e..ee5d7fde9c 100644
--- a/drivers/mtd/nand/raw/mxs_nand.c
+++ b/drivers/mtd/nand/raw/mxs_nand.c
@@ -195,6 +195,7 @@ static inline int mxs_nand_legacy_calc_ecc_layout(struct 
bch_geometry *geo,
struct nand_chip *chip = mtd_to_nand(mtd);
struct mxs_nand_info *nand_info = nand_get_controller_data(chip);
unsigned int block_mark_bit_offset;
+   int corr, ds_corr;
 
/* The default for the length of Galois Field. */
geo->gf_len = 13;
@@ -225,6 +226,17 @@ static inline int mxs_nand_legacy_calc_ecc_layout(struct 
bch_geometry *geo,
geo->ecc_strength = min(round_down(geo->ecc_strength, 2),
nand_info->max_ecc_strength_supported);
 
+   /* check ecc strength, same as nand_ecc_is_strong_enough() did*/
+   if (chip->ecc_step_ds) {
+   corr = mtd->writesize * geo->ecc_strength /
+  geo->ecc_chunkn_size;
+   ds_corr = mtd->writesize * chip->ecc_strength_ds /
+  chip->ecc_step_ds;
+   if (corr < ds_corr ||
+   geo->ecc_strength < chip->ecc_strength_ds)
+   return -EINVAL;
+   }
+
block_mark_bit_offset = mtd->writesize * 8 -
(geo->ecc_strength * geo->gf_len * (geo->ecc_chunk_count - 1)
+ MXS_NAND_METADATA_SIZE * 8);
@@ -,6 +1123,7 @@ static int mxs_nand_set_geometry(struct mtd_info *mtd, 
struct bch_geometry *geo)
struct nand_chip *chip = mtd_to_nand(mtd);
struct nand_chip *nand = mtd_to_nand(mtd);
struct mxs_nand_info *nand_info = nand_get_controller_data(nand);
+   int err;
 
if (chip->ecc_strength_ds > nand_info->max_ecc_strength_supported) {
printf("unsupported NAND chip, minimum ecc required %d\n"
@@ -1118,19 +1131,57 @@ static int mxs_nand_set_geometry(struct mtd_info *mtd, 
struct bch_geometry *geo)
return -EINVAL;
}
 
-   if ((!(chip->ecc_strength_ds > 0 && chip->ecc_step_ds > 0) &&
-mtd->oobsize < 1024) || nand_info->legacy_bch_geometry) {
-   dev_warn(mtd->dev, "use legacy bch geometry\n");
-   return mxs_nand_legacy_calc_ecc_layout(geo, mtd);
+   /* use the legacy bch setting by default */
+   if ((!nand_info->use_minimum_ecc && mtd->oobsize < 1024) ||
+   !(chip->ecc_strength_ds > 0 && chip->ecc_step_ds > 0)) {
+   dev_dbg(mtd->dev, "use legacy bch geometry\n");
+   err = mxs_nand_legacy_calc_ecc_layout(geo, mtd);
+   if (!err)
+   return 0;
}
 
-   if (mtd->oobsize > 1024 || chip->ecc_step_ds < mtd->oobsize)
-   return mxs_nand_calc_ecc_for_large_oob(geo, mtd);
+   /* for large oob nand */
+   if (mtd->oobsize > 1024) {
+   dev_dbg(mtd->dev, "use large oob bch geometry\n");
+   err = mxs_nand_calc_ecc_for_large_oob(geo, mtd);
+   if (!err)
+   return 0;
+   }
 
-   return mxs_nand_calc_ecc_layout_by_info(geo, mtd,
-   chip->ecc_strength_ds, chip->ecc_step_ds);
+   /* otherwise use the minimum ecc nand chips required */
+   dev_dbg(mtd->dev, "use minimum ecc bch geometry\n");
+   err = mxs_nand_calc_ecc_layout_by_info(geo, mtd, chip->ecc_strength_ds,
+  chip->ecc_step_ds);
 
-   return 0;
+   if (err)
+   dev_err(mtd->dev, "none of the bc

[PATCH v4] mtd: gpmi: fix the bch setting backward compatible issue

2022-03-25 Thread Han Xu
Previous u-boot code changed the default bch setting behavior and caused
backward compatible issue. This fix choose the legacy bch geometry back
again as the default option. If the minimum ecc strength that NAND chips
required need to be chosen, it can be enabled by either adding DT flag
"fsl,use-minimum-ecc" or CONFIG_NAND_MXS_USE_MINIMUM_ECC in configs. The
unused flag "fsl,legacy-bch-geometry" get removed.

Fixes: 51cdf83eea (mtd: gpmi: provide the option to use legacy bch geometry)
Fixes: 616f03daba (mtd: gpmi: change the BCH layout setting for large oob NAND)
Tested-by: Tim Harvey 
Tested-by: Sean Nyekjaer 
Signed-off-by: Han Xu 

---
Changes in v2:
 - change the commit log about backward compatible issue is in u-boot
 - removed the unused flag
 - add fixes and test tag

Changes in v3:
 - fix the fixes syntax
 - fix the change log syntax
 - add more test tag

Changes in v4:
 - change the fix tag to single line
---
 drivers/mtd/nand/raw/mxs_nand.c| 71 ++
 drivers/mtd/nand/raw/mxs_nand_dt.c |  2 -
 include/mxs_nand.h |  2 -
 3 files changed, 62 insertions(+), 13 deletions(-)

diff --git a/drivers/mtd/nand/raw/mxs_nand.c b/drivers/mtd/nand/raw/mxs_nand.c
index 748056a43e..ee5d7fde9c 100644
--- a/drivers/mtd/nand/raw/mxs_nand.c
+++ b/drivers/mtd/nand/raw/mxs_nand.c
@@ -195,6 +195,7 @@ static inline int mxs_nand_legacy_calc_ecc_layout(struct 
bch_geometry *geo,
struct nand_chip *chip = mtd_to_nand(mtd);
struct mxs_nand_info *nand_info = nand_get_controller_data(chip);
unsigned int block_mark_bit_offset;
+   int corr, ds_corr;
 
/* The default for the length of Galois Field. */
geo->gf_len = 13;
@@ -225,6 +226,17 @@ static inline int mxs_nand_legacy_calc_ecc_layout(struct 
bch_geometry *geo,
geo->ecc_strength = min(round_down(geo->ecc_strength, 2),
nand_info->max_ecc_strength_supported);
 
+   /* check ecc strength, same as nand_ecc_is_strong_enough() did*/
+   if (chip->ecc_step_ds) {
+   corr = mtd->writesize * geo->ecc_strength /
+  geo->ecc_chunkn_size;
+   ds_corr = mtd->writesize * chip->ecc_strength_ds /
+  chip->ecc_step_ds;
+   if (corr < ds_corr ||
+   geo->ecc_strength < chip->ecc_strength_ds)
+   return -EINVAL;
+   }
+
block_mark_bit_offset = mtd->writesize * 8 -
(geo->ecc_strength * geo->gf_len * (geo->ecc_chunk_count - 1)
+ MXS_NAND_METADATA_SIZE * 8);
@@ -,6 +1123,7 @@ static int mxs_nand_set_geometry(struct mtd_info *mtd, 
struct bch_geometry *geo)
struct nand_chip *chip = mtd_to_nand(mtd);
struct nand_chip *nand = mtd_to_nand(mtd);
struct mxs_nand_info *nand_info = nand_get_controller_data(nand);
+   int err;
 
if (chip->ecc_strength_ds > nand_info->max_ecc_strength_supported) {
printf("unsupported NAND chip, minimum ecc required %d\n"
@@ -1118,19 +1131,57 @@ static int mxs_nand_set_geometry(struct mtd_info *mtd, 
struct bch_geometry *geo)
return -EINVAL;
}
 
-   if ((!(chip->ecc_strength_ds > 0 && chip->ecc_step_ds > 0) &&
-mtd->oobsize < 1024) || nand_info->legacy_bch_geometry) {
-   dev_warn(mtd->dev, "use legacy bch geometry\n");
-   return mxs_nand_legacy_calc_ecc_layout(geo, mtd);
+   /* use the legacy bch setting by default */
+   if ((!nand_info->use_minimum_ecc && mtd->oobsize < 1024) ||
+   !(chip->ecc_strength_ds > 0 && chip->ecc_step_ds > 0)) {
+   dev_dbg(mtd->dev, "use legacy bch geometry\n");
+   err = mxs_nand_legacy_calc_ecc_layout(geo, mtd);
+   if (!err)
+   return 0;
}
 
-   if (mtd->oobsize > 1024 || chip->ecc_step_ds < mtd->oobsize)
-   return mxs_nand_calc_ecc_for_large_oob(geo, mtd);
+   /* for large oob nand */
+   if (mtd->oobsize > 1024) {
+   dev_dbg(mtd->dev, "use large oob bch geometry\n");
+   err = mxs_nand_calc_ecc_for_large_oob(geo, mtd);
+   if (!err)
+   return 0;
+   }
 
-   return mxs_nand_calc_ecc_layout_by_info(geo, mtd,
-   chip->ecc_strength_ds, chip->ecc_step_ds);
+   /* otherwise use the minimum ecc nand chips required */
+   dev_dbg(mtd->dev, "use minimum ecc bch geometry\n");
+   err = mxs_nand_calc_ecc_layout_by_info(geo, mtd, chip->ecc_strength_ds,
+  chip->ecc_step_ds);
 
-   return 0;
+