i.MX28: BCH error in L2.6.35_1.1.0_130130

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

i.MX28: BCH error in L2.6.35_1.1.0_130130

4,894 Views
PeterChan
NXP Employee
NXP Employee

In case you have the NAND driver enabled in Linux BSP release L2.6.35_1.1.0_130130 and experience BCH timeout error on i.MX28, please try this patch.

--- a/drivers/mtd/nand/gpmi-nfc/gpmi-nfc-hal-v1.c

+++ b/drivers/mtd/nand/gpmi-nfc/gpmi-nfc-hal-v1.c

@@ -46,8 +46,15 @@ static int init(struct gpmi_nfc_data *this)

        clk_enable(resources->clock);

        /* Reset the GPMI block. */

-

-       mxs_reset_block(resources->gpmi_regs + HW_GPMI_CTRL0, false);

+   /*

+    * Reset the BCH block. Notice that we pass in true for the just_enable

+    * flag. This is because the soft reset for the version 0 BCH block

+    * doesn't work and the version 1 BCH block is similar enough that we

+    * suspect the same (though this has not been officially tested). If you

+    * try to soft reset a version 0 BCH block, it becomes unusable until

+    * the next hard reset.

+    */

+       mxs_reset_block(resources->gpmi_regs + HW_GPMI_CTRL0, true);

        /* Choose NAND mode. */

        __raw_writel(BM_GPMI_CTRL1_GPMI_MODE,

@@ -108,7 +115,15 @@ static int set_geometry(struct gpmi_nfc_data *this)

        clk_enable(resources->clock);

        /* reset the BCH */

-       mxs_reset_block(resources->bch_regs, false);

+   /*

+    * Reset the BCH block. Notice that we pass in true for the just_enable

+    * flag. This is because the soft reset for the version 0 BCH block

+    * doesn't work and the version 1 BCH block is similar enough that we

+    * suspect the same (though this has not been officially tested). If you

+    * try to soft reset a version 0 BCH block, it becomes unusable until

+    * the next hard reset.

+    */

+       mxs_reset_block(resources->bch_regs, true);

        /* Configure layout 0. */

Labels (1)
0 Kudos
Reply
35 Replies

1,172 Views
PeterChan
NXP Employee
NXP Employee

Hi Thomas,

My NAND boot up stress test at GPMI 96MHz has been running for over 24 hours or nearly 3000 boot up and not yet any error has been observed. Please let me know if you need further input from us.

Thanks,

Peter

0 Kudos
Reply

1,172 Views
ThomasBandelier
Contributor II

Hi Peter,

Thanks for feedback

I would need additional confirmation from you

It looks like the default setup uses XTAL as gpmi_ref

in our design , pll.0 is used byt doing the following:

/* turn on gpmi frac: pll.0 is ref_gpmi's parent*/

    REG_CLR(REGS_CLKCTRL_BASE, HW_CLKCTRL_FRAC1,

        BM_CLKCTRL_FRAC1_CLKGATEGPMI |

        BM_CLKCTRL_FRAC1_PIXFRAC);

    REG_SET(REGS_CLKCTRL_BASE, HW_CLKCTRL_FRAC1, 18<<16); /* 480 MHz for ref_gpmi*/

    /* Clear bypass bit: ref_gpmi becomes clk_gpmi's parent*/

    REG_CLR(REGS_CLKCTRL_BASE, HW_CLKCTRL_CLKSEQ,

           BM_CLKCTRL_CLKSEQ_BYPASS_GPMI);

Can you confirm this is the right way to configure gpmi_ref ? Thanks.

Thomas

0 Kudos
Reply

1,172 Views
PeterChan
NXP Employee
NXP Employee

Hi Thomas,

After writing the GPMI clock divider value, you need to poll the BUSY bit to wait for the new divider value effective in the clock domains. Below is my code to change the GPMI clock to 96 MHz.

    /* source path from ref_xtal */

    REG_SET(REGS_CLKCTRL_BASE, HW_CLKCTRL_CLKSEQ,

        BM_CLKCTRL_CLKSEQ_BYPASS_GPMI);

    /* Set GPMIFRAC = 18 */

    REG_WR( REGS_CLKCTRL_BASE, HW_CLKCTRL_FRAC1,

        REG_RD(REGS_CLKCTRL_BASE, HW_CLKCTRL_FRAC1) &

        (~(BM_CLKCTRL_FRAC1_CLKGATEGPMI)) );

    REG_WR( REGS_CLKCTRL_BASE, HW_CLKCTRL_FRAC1,

        (REG_RD(REGS_CLKCTRL_BASE, HW_CLKCTRL_FRAC1) &

        (~(BM_CLKCTRL_FRAC1_GPMIFRAC))) |

        (18 << BP_CLKCTRL_FRAC1_GPMIFRAC) );

    /* Set GPMI DIV = 5 */

    REG_WR( REGS_CLKCTRL_BASE, HW_CLKCTRL_GPMI,

        REG_RD(REGS_CLKCTRL_BASE, HW_CLKCTRL_GPMI) &

        (~(BM_CLKCTRL_GPMI_CLKGATE)) );

    while( REG_RD(REGS_CLKCTRL_BASE, HW_CLKCTRL_GPMI) & BM_CLKCTRL_GPMI_BUSY);

    REG_WR( REGS_CLKCTRL_BASE, HW_CLKCTRL_GPMI,

        (REG_RD(REGS_CLKCTRL_BASE, HW_CLKCTRL_GPMI) &

        (~(BM_CLKCTRL_GPMI_DIV))) |

        (5 << BP_CLKCTRL_GPMI_DIV) );

    while( REG_RD(REGS_CLKCTRL_BASE, HW_CLKCTRL_GPMI) & BM_CLKCTRL_GPMI_BUSY);


    REG_WR( REGS_CLKCTRL_BASE, HW_CLKCTRL_GPMI,

        REG_RD(REGS_CLKCTRL_BASE, HW_CLKCTRL_GPMI) &

        (~(BM_CLKCTRL_GPMI_DIV_FRAC_EN)) );

    while( REG_RD(REGS_CLKCTRL_BASE, HW_CLKCTRL_GPMI) & BM_CLKCTRL_GPMI_BUSY);

    /* source path is ref_gpmi GPMI = 480 * (18/18) / 5 = 96 MHz */

    REG_CLR(REGS_CLKCTRL_BASE, HW_CLKCTRL_CLKSEQ,

        BM_CLKCTRL_CLKSEQ_BYPASS_GPMI);

Thanks,

Peter

0 Kudos
Reply

1,172 Views
ThomasBandelier
Contributor II

Thanks Peter ! I will try this.

My question came because I observed that I had different results given the clock source used:

- XTAL @24Mhz: issue not reproduced

- PLL.0 divided to 24 MHz: issue reproduced.

TEsting is ongoing, will let you know.

Thomas

0 Kudos
Reply

1,172 Views
ThomasBandelier
Contributor II

Hi

I did the follwoign tests:

24MHz obtained by dividing pll.0: no error

40 Mhz obtained by dividing pll.0: DMA error reproduced

Peter, can you share tour u-boot code? I think we are not aligned

Note that I 'm using relaxed timings for our NAND (the default timings coded in u-boot 2009.08, manuf id 0xC, prod id 0xF1)

thanks

0 Kudos
Reply

1,172 Views
PeterChan
NXP Employee
NXP Employee

Hi Thomas,

My EVK has been running for 2 more days (or 5000 times) but still no BCH error or boot failure found. Here are my changes in clean L2.6.35_1.1.0_130130 u-boot for 96MHz GPMI clock. My boot environment is

bootdelay=3

baudrate=115200

ipaddr=192.168.1.103

serverip=192.168.1.101

netmask=255.255.255.0

bootfile="uImage"

loadaddr=0x42000000

nfsroot=/home/notroot/nfs/rootfs

bootargs_nfs=setenv bootargs ${bootargs} root=/dev/nfs ip=dhcp nfsroot=${serverip}:${nfsroot},v3,tcp fec_mac=${ethaddr}

bootcmd_net=run bootargs_nfs; dhcp; bootm

ethact=FEC0

bootcmd_mmc=run bootargs_mmc; mmc read 0 ${loadaddr} 0x100 0x2000; bootm

bootargs_mmc=setenv bootargs ${bootargs} root=/dev/mmcblk0p3 rw rootwait ip=none gpmi noinitrd

bootargs_nand=setenv bootargs ${bootargs} ubi.mtd=2 root=ubi0:rootfs0 rootfstype=ubifs rw rootwait ip=none gpmi noinitrd

bootcmd_nand=run bootargs_nand; nand read ${loadaddr} 0x1400000 0x300000; bootm

bootargs=console=ttyAM0,115200

bootcmd=run bootcmd_nand

stdin=serial

stdout=serial

stderr=serial

Thanks,

Peter

0 Kudos
Reply

1,172 Views
ThomasBandelier
Contributor II

Hi Peter,

I'm coming back with interesting results.

It seems the following is needed:

- during u-boot NAND driver init:

reset GPMI with just_enable to FALSE

reset BCH with just enable to TRUE

- during set_geometry:

reset BCH with just enable to TRUE

GPMI can be totally soft-reset during init

BCH must never be totally soft-reset

BCH must be enabled right after GPMI during init.

I did not try to remove the additional BCH enablement in init, as my current code is working.

Could you please acknowledge this sequence ?

from <init>:

mxs_dma_init();

    /* Reset the GPMI block. */

    i = 0;

    do {

   error = gpmi_reset_block((void *)CONFIG_GPMI_REG_BASE, 0);
   i++;

    } while (error != 0 && i < 10);

    //try just enable

    gpmi_reset_block((void *)CONFIG_BCH_REG_BASE + HW_BCH_CTRL, 1);

    /* Choose NAND mode. */

    REG_CLR(CONFIG_GPMI_REG_BASE, HW_GPMI_CTRL1,

   BM_GPMI_CTRL1_GPMI_MODE);

from <set_geometry>

page_size= mtd->writesize + mtd->oobsize;

    /*

     * Reset the BCH block. Notice that we pass in true for the just_enable

     * flag. This is because the soft reset for the version 0 BCH block

     * doesn't work and the version 1 BCH block is similar enough that we

     * suspect the same (though this has not been officially tested). If you

     * try to soft reset a version 0 BCH block, it becomes unusable until

     * the next hard reset.

     */

    gpmi_reset_block((void *)CONFIG_BCH_REG_BASE + HW_BCH_CTRL, 1);

    /* Configure layout 0. */

    writel(BF_BCH_FLASH0LAYOUT0_NBLOCKS(block_count) |
   BF_BCH_FLASH0LAYOUT0_META_SIZE(metadata_size) |
   BF_BCH_FLASH0LAYOUT0_ECC0(ecc_strength)   |
   BF_BCH_FLASH0LAYOUT0_DATA0_SIZE(block_size),
   CONFIG_BCH_REG_BASE + HW_BCH_FLASH0LAYOUT0);

Thanks,

Thomas

0 Kudos
Reply

1,172 Views
PeterChan
NXP Employee
NXP Employee

Hi Thomas,

Please see my comment about the u-boot NAND driver init sequence.

"GPMI can be totally soft-reset during init"

- agree.

"BCH must never be totally soft-reset.

- Errata 2847 is only applicable to i.MX233. i.MX28 should not have this issue. I have validated the BCH soft reset (but only on 1 board) in my previous boot up stress test. Have you ever tried the BSP sequence (GPMI soft reset with just_enable to FALSE, followed by BCH soft reset with just enabled to FALSE)? Does it also work on your side?

"BCH must be enabled right after GPMI during init"

- agree. BCH is always enabled after GPMI

Thanks,

Peter

0 Kudos
Reply

1,172 Views
ThomasBandelier
Contributor II

Hi Peter,

Regarding the BCH soft-reset I'm almost sure this issue is valid for i.MX28

On my side, the only way I can get both the BCH timeout and corrupted PEBs issues gone is when I DON'T soft reset BCH

Thomas

0 Kudos
Reply

1,172 Views
ThomasBandelier
Contributor II

Additional comment: Note this is very board-dependant. You should try with different boards to increase testing diversity IMO.

Thomas

0 Kudos
Reply

1,172 Views
PeterChan
NXP Employee
NXP Employee

I run the boot up test again using your sequence (GPMI soft reset, BCH just enabled). My EVK board also does not show any boot up issue after 3600+ times. I will get another EVK board and test both sequences again.

I don't see any harm to let the BCH just enable. If this sequence works on all your boards, please keep this.

0 Kudos
Reply

1,172 Views
PeterChan
NXP Employee
NXP Employee

I have tried the both sequences, {GPMI soft reset BCH just enabled} and {GPMI soft reset BCH soft reset}, on 3 i.MX28 EVKs but none of them shows any boot error.

Since no boot error is found in {GPMI soft reset BCH just enabled} sequence in both of our testings, I think this sequence can also be used in i.MX28.

0 Kudos
Reply

1,182 Views
ThomasBandelier
Contributor II

Hi Peter,

Thanks for feedback. I will double check if our code is doing the GPMI source clock change correctly as you mention and come back to you

BR


Thomas

0 Kudos
Reply

1,182 Views
ThomasBandelier
Contributor II

Hi Peter,

In our u-boot code, the difference is that  the GPMI bypass bit is cleared before setting the GPMI divider. I would like to try your recommandation (setting it after) but I'm concerned that if it just doesn't work, my board won't be able to boot at all.

So: have you unitary-tested it ?

0 Kudos
Reply

1,182 Views
ThomasBandelier
Contributor II

Hi Peter,

We are using L2.6.35 1_1_0 on iMX28. the original patch comes from a bug on imx28 as well so this should not be a surprise.

we backported the patch from gpmi-lib to the right file (where GPMI is reset) in this BSP

> may I say that setting "just_enable" to true can resolve all NAND startup issues?

No, it's the contrary in our case. If set to true, we will have DMA timeouts.

if set to false, DMA timeouts go away but we have startup issues 1 time over 100.

If we use the patch I pointed (additional BCH reset) we don't have any problmes.

Thomas

0 Kudos
Reply