[U-Boot-Users] NAND driver question

Craig Millen
2008-02-01T19:55:05Z

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