Re: [U-Boot-Users] NAND driver question

On Tuesday 29 January 2008, Craig Millen wrote:
I have been experiencing a few problems when using a NAND flash for storage in u-boot.
When I'm reading large files (7MB) from the NAND, periodically there will be a NAND ECC read error when using the following command:
=> nand read 400000 0 154000 NAND read: device 0 offset 0x0, size 0x154000 1392640 bytes read: ERROR.
After turning on debug, the problem is occurring in the nand_read_ecc function whereby the ecc check fails. After running it numerous times,
there seems to be no correlation between pages that fail and appears to be completely random. Has anyone else had these problems?
No. NAND blocks can fail and generate ECC errors. But your description doesn't really sound like this is a NAND chips related problem. Does this happen on multiple boards or just s single one? This looks more like a timing problem or something like this to me.
IIRC, then you had to change the 4xx NDFC driver to access the NAND via 8bit access, correct? I have used this driver on multiple 4xx boards and on all boards this driver can be used as is, meaning with 32bit access enabled. Perhaps you still have a problem with the interface to the NAND chips.
Yes, this is correct. I have never been able to get this line in ndfc.c:ndfc_read_buf to work:
*p++ = in_be32((u32 *)(base + NDFC_DATA));
It always gives me a Machine check exception (see below), so I have changed it to reading 4 bytes instead, which causes no problems.
NAND: Bus Fault @ 0x0ff89fa8, fixup 0x00000000 Machine Check Exception. Caused by (from msr): regs 0ff16c90 Data Read PLB Error NIP: 0FF89FA8 XER: 00000000 LR: 0FF6AC8C REGS: 0ff16c90 TRAP: 0200 DEAR: 0000000 0 MSR: 00021000 EE: 0 PR: 0 FP: 0 ME: 1 IR/DR: 00
GPR00: 00000000 0FF16D80 0000051B 0FFC7EBC 0FF17210 00000210 00000000 10D8C46D GPR08: 0FF628C0 90000000 03F940AA 01000000 42000024 00000000 0FFAB300 0FFA7D84 GPR16: 00000200 00000010 0FFA7D84 0FF17210 0FF17210 0000001F 00000010 00000200 GPR24: 00000001 0FFC7EBC 00000210 00000000 00000210 0FF16F38 0FFABB24 0FFAAD84 Call backtrace: 0FF16F38 0FF6AC68 0FF6CA88 0FF6D608 0FF6DA88 0FF6A9A4 0FF69444 0FF6247C 0FF5B6B0 machine check
From what I can see, there aren't that many things to setup for NAND though.
1. init.S: tlbentry(CFG_NAND_ADDR, SZ_4K, CFG_NAND_ADDR, 0, AC_R|AC_W|AC_X|SA_G|SA_I) (which I notice on the sequoia board, page_size is SZ_1K, and extended real page number (ERPN) is '1' both of wich I don't fully understand). 2. <board_config>.h where you setup its address and the AP/CR values all of which seem to be fairly common. #define CFG_NAND_ADDR 0xD0000000 /* NAND Flash */ /* Memory Bank 1 (NAND-FLASH) initialization */ #define CFG_EBC_PB1AP 0x018003c0 #define CFG_EBC_PB1CR (CFG_NAND_ADDR | 0x1c000)
3. Four long words in SEEPROM for boot option H Here are our settings and their descriptions:
SDR0_SDSTP0[ENG]: 1 : PLL's VCO is the source for PLL forward divisors SDR0_SDSTP0[SRC]: 0 : Feedback originates from PLLOUTA SDR0_SDSTP0[SEL]: 000 : Feedback selection is PLL output SDR0_SDSTP0[TUNE 5:7]: 101 : 10 <= M <= 22, 600MHz < VCO <= 900MHz = 85
SDR0_SDSTP0[TUNE 8:14]: 0111000 SDR0_SDSTP0[FBDV 15]: 0 : PLL feedback divisor =70
SDR0_SDSTP0[FBDV 16:19]: 1000 : PLL feedback divisor=8 SDR0_SDSTP0[FBDVA]: 0010 : PLL forward divisor A=2 =82
SDR0_SDSTP0[FBDVB]: 100 : PLL forward divisor B=4 SDR0_SDSTP0[PRBDV0]: 010 : PLL primary divisor B=2 SDR0_SDSTP0[OPBDV0]: 10 : OPB clock divisor 0=2 = 8A
------------------------------------------------------------------------ -------------------------------
SDR0_SDSTP1[LFBDV]: 000001 : PLL local feedback divisor SDR0_SDSTP1[PERDV0 0:1]: 01 : Peripheral clock divisor 0=2 = 05
SDR0_SDSTP1[PERDV0 2]: 0 : Peripheral clock divisor 0=2 SDR0_SDSTP1[MALDV0]: 10 : MAL clock divisor 0 = 2 SDR0_SDSTP1[PCIDV0]: 00 : Sync PCI clock divisor 0 = 4 SDR0_SDSTP1[PLLTIMER 0:2]: 111 : PLL locking timer = 47
SDR0_SDSTP1[PLLTIMER 3]: 1 : PLL locking timer SDR0_SDSTP1[RW]: 01 : EBC ROM width: 16-bit ***** should be 0b10 32-bit (Boot from NAND Flash) SDR0_SDSTP1[RL]: 00 : EBC ROM location: EBC ***** should be 0b10 NDFC SDR0_SDSTP1[PAE]: 0 : PCI internal arbiter: disabled SDR0_SDSTP1[PHCE]: 0 : PCI host configuration: disabled SDR0_SDSTP1[ZM 0]: 0 : ZMII mode: MII mode =a0
SDR0_SDSTP1[ZM 1]: 0 : ZMII mode: RMII mode 100 SDR0_SDSTP1[CTE]: 0 : CPU trace: disabled SDR0_SDSTP1[Nto1]: 0 : CPU/PLB ratio N/P: not N to 1 SDR0_SDSTP1[PAME]: 1 : PCI asynchronous mode: enabled SDR0_SDSTP1[RSV]: 0000 : Reserved = 10 ------------------------------------------------------------------------ -------------------------------
SDR0_SDSTP2[MEN]: 01 : Multiplex: EMAC ******** should be 0b10 for NDFC SDR0_SDSTP2[NE]: 0 : NDFC: ******** should be 0b1 for NDFC SDR0_SDSTP2[NBW]: 0 : NDFC boot width: 8-bit
SDR0_SDSTP2[NBP]: 000 : NDFC boot page selection =40
SDR0_SDSTP2[NBAC]: 00 : NDFC boot address selection cycle: ** should be 0b01 4 Addr. Cycles, 1 Col. + 3 Row (512 page size) SDR0_SDSTP2[NARE]: 0 : NDFC auto read : disabled *** should be 1 for NAND booting SDR0_SDSTP2[NRB]: 0 : NDFC Ready/Busy : Ready SDR0_SDSTP2[NDRSC 0:3]: 1000 : NDFC device reset counter *** have to figure out this value based on clock =08
SDR0_SDSTP2[NDRSC 4:11]: 0010 0011 : NDFC device reset counter =23
SDR0_SDSTP2[NDRSC 12:15]: 0101 : NDFC device reset counter = 16949 *** should be 1000 0010 0011 0110 = 33334 for 66MHz SDR0_SDSTP2[NCG0]: 0 : NDFC/EBC chip select gating CS0 : EBC *** should be 1 for NDFC SDR0_SDSTP2[NCG1]: 0 : NDFC/EBC chip select gating CS1 : EBC SDR0_SDSTP2[NCG2]: 0 : NDFC/EBC chip select gating CS2 : EBC SDR0_SDSTP2[NCG3]: 0 : NDFC/EBC chip select gating CS3 : EBC =50 ------------------------------------------------------------------------ ------------------------------- SDR0_SDSTP3[NCRDC]: 0000 1101 0000 0101 : NDFC device read count =0d05 SDR0_SDSTP3[RSVD]: 0000 0000 0000 0000 : reserved =0000
We have noticed however that when reading from the nand in u-boot, that the /CE line is never deasserted between page reads, but in the linux kernel user mode, it is. We have yet to figure out why this is.
There are only two other spots in the code that I can see where timing parameters for the NAND are set:
Ndfc.c: board_nand_init: out_be32((u32 *)(base + NDFC_BCFG0 + (cs << 2)), 0x80002222);
Ndfc.c: board_nand_select_device: out_be32((u32 *)(base + NDFC_CCR), 0x00000000 | (cs << 24));
I am curious to know why the numbers for the NDFC_BCFG0 register aren't a function of the clock frequency, instead are hard coded. What frequency is all of this based on?
Thanks, Craig

On Friday 01 February 2008, Craig Millen wrote:
IIRC, then you had to change the 4xx NDFC driver to access the NAND via 8bit access, correct? I have used this driver on multiple 4xx boards and on all boards this driver can be used as is, meaning with 32bit access enabled. Perhaps you still have a problem with the interface to the NAND chips.
Yes, this is correct. I have never been able to get this line in ndfc.c:ndfc_read_buf to work:
*p++ = in_be32((u32 *)(base + NDFC_DATA));
It always gives me a Machine check exception (see below), so I have changed it to reading 4 bytes instead, which causes no problems.
<snip>
From what I can see, there aren't that many things to setup for NAND though.
- init.S: tlbentry(CFG_NAND_ADDR, SZ_4K, CFG_NAND_ADDR, 0,
AC_R|AC_W|AC_X|SA_G|SA_I) (which I notice on the sequoia board, page_size is SZ_1K, and extended real page number (ERPN) is '1' both of wich I don't fully understand).
1k should be enough but this difference is definitely not our problem. And the 1 in ERPN must be used on 440EPx, since 440EPx has the EBC at 0x1.xxxx.xxxx, so above 4GB. This is not the case for the 440EP. So this difference is ok too.
I may have noted this before, but I suggest you move the CFG_NAND_ADDR to 0x90000000 as done on Bamboo, since 0xd0000000 is reserved for PCI memory on 440EP.
- <board_config>.h where you setup its address and the AP/CR values all
of which seem to be fairly common.
#define CFG_NAND_ADDR 0xD0000000 /* NAND Flash */ /* Memory Bank 1 (NAND-FLASH) initialization */ #define CFG_EBC_PB1AP 0x018003c0 #define CFG_EBC_PB1CR (CFG_NAND_ADDR | 0x1c000)
Looks good.
- Four long words in SEEPROM for boot option H
Here are our settings and their descriptions:
SDR0_SDSTP0[ENG]: 1 : PLL's VCO is the source for PLL forward divisors SDR0_SDSTP0[SRC]: 0 : Feedback originates from PLLOUTA SDR0_SDSTP0[SEL]: 000 : Feedback selection is PLL output SDR0_SDSTP0[TUNE 5:7]: 101 : 10 <= M <= 22, 600MHz < VCO <= 900MHz = 85
SDR0_SDSTP0[TUNE 8:14]: 0111000 SDR0_SDSTP0[FBDV 15]: 0 : PLL feedback divisor =70
SDR0_SDSTP0[FBDV 16:19]: 1000 : PLL feedback divisor=8 SDR0_SDSTP0[FBDVA]: 0010 : PLL forward divisor A=2 =82
SDR0_SDSTP0[FBDVB]: 100 : PLL forward divisor B=4 SDR0_SDSTP0[PRBDV0]: 010 : PLL primary divisor B=2 SDR0_SDSTP0[OPBDV0]: 10 : OPB clock divisor 0=2 = 8A
SDR0_SDSTP1[LFBDV]: 000001 : PLL local feedback divisor SDR0_SDSTP1[PERDV0 0:1]: 01 : Peripheral clock divisor 0=2 = 05
SDR0_SDSTP1[PERDV0 2]: 0 : Peripheral clock divisor 0=2 SDR0_SDSTP1[MALDV0]: 10 : MAL clock divisor 0 = 2 SDR0_SDSTP1[PCIDV0]: 00 : Sync PCI clock divisor 0 = 4 SDR0_SDSTP1[PLLTIMER 0:2]: 111 : PLL locking timer = 47
SDR0_SDSTP1[PLLTIMER 3]: 1 : PLL locking timer SDR0_SDSTP1[RW]: 01 : EBC ROM width: 16-bit ***** should be 0b10 32-bit (Boot from NAND Flash) SDR0_SDSTP1[RL]: 00 : EBC ROM location: EBC ***** should be 0b10 NDFC SDR0_SDSTP1[PAE]: 0 : PCI internal arbiter: disabled SDR0_SDSTP1[PHCE]: 0 : PCI host configuration: disabled SDR0_SDSTP1[ZM 0]: 0 : ZMII mode: MII mode =a0
SDR0_SDSTP1[ZM 1]: 0 : ZMII mode: RMII mode 100 SDR0_SDSTP1[CTE]: 0 : CPU trace: disabled SDR0_SDSTP1[Nto1]: 0 : CPU/PLB ratio N/P: not N to 1 SDR0_SDSTP1[PAME]: 1 : PCI asynchronous mode: enabled SDR0_SDSTP1[RSV]: 0000 : Reserved = 10
SDR0_SDSTP2[MEN]: 01 : Multiplex: EMAC ******** should be 0b10 for NDFC SDR0_SDSTP2[NE]: 0 : NDFC: ******** should be 0b1 for NDFC SDR0_SDSTP2[NBW]: 0 : NDFC boot width: 8-bit
SDR0_SDSTP2[NBP]: 000 : NDFC boot page selection =40
SDR0_SDSTP2[NBAC]: 00 : NDFC boot address selection cycle: ** should be 0b01 4 Addr. Cycles, 1 Col. + 3 Row (512 page size) SDR0_SDSTP2[NARE]: 0 : NDFC auto read : disabled *** should be 1 for NAND booting SDR0_SDSTP2[NRB]: 0 : NDFC Ready/Busy : Ready SDR0_SDSTP2[NDRSC 0:3]: 1000 : NDFC device reset counter *** have to figure out this value based on clock =08
SDR0_SDSTP2[NDRSC 4:11]: 0010 0011 : NDFC device reset counter =23
SDR0_SDSTP2[NDRSC 12:15]: 0101 : NDFC device reset counter = 16949 *** should be 1000 0010 0011 0110 = 33334 for 66MHz SDR0_SDSTP2[NCG0]: 0 : NDFC/EBC chip select gating CS0 : EBC *** should be 1 for NDFC SDR0_SDSTP2[NCG1]: 0 : NDFC/EBC chip select gating CS1 : EBC SDR0_SDSTP2[NCG2]: 0 : NDFC/EBC chip select gating CS2 : EBC SDR0_SDSTP2[NCG3]: 0 : NDFC/EBC chip select gating CS3 : EBC =50
SDR0_SDSTP3[NCRDC]: 0000 1101 0000 0101 : NDFC device read count =0d05 SDR0_SDSTP3[RSVD]: 0000 0000 0000 0000 : reserved =0000
How is SDR0_CUST0 configured. Please read is in a running system and send me the value. And how is the GPIO/multiplexing configured?
BTW: It would be much easier to help you here, if you board port was available in the official U-Boot repository. I suggest you submit this support soon.
We have noticed however that when reading from the nand in u-boot, that the /CE line is never deasserted between page reads, but in the linux kernel user mode, it is. We have yet to figure out why this is.
That's possible. Could be that the U-Boot NAND driver doesn't deassert the CE line.
There are only two other spots in the code that I can see where timing parameters for the NAND are set:
Ndfc.c: board_nand_init: out_be32((u32 *)(base + NDFC_BCFG0 + (cs << 2)), 0x80002222);
Ndfc.c: board_nand_select_device: out_be32((u32 *)(base + NDFC_CCR), 0x00000000 | (cs << 24));
I am curious to know why the numbers for the NDFC_BCFG0 register aren't a function of the clock frequency, instead are hard coded.
Right. This would be a good extension. Patches are always welcome. :)
What frequency is all of this based on?
EBC, since the NAND is connected to the EBC.
What frequency is your EBC clocked? Did you try lower access speeds, something like:
out_be32((u32 *)(base + NDFC_BCFG0 + (cs << 2)), 0x80007777);
And when you get this exception upon NAND access, did you even measure the NAND signals while doing this lword access? Do you see something on those signals at all on lword accesses?
Best regards, Stefan
===================================================================== DENX Software Engineering GmbH, MD: Wolfgang Denk & Detlev Zundel HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: +49-8142-66989-0 Fax: +49-8142-66989-80 Email: office@denx.de =====================================================================
participants (2)
-
Craig Millen
-
Stefan Roese