分类: 嵌入式
2009-07-30 17:28:11
u-boot运行至第二阶段进入start_armboot()函数。其中nand_init()函数是对nand flash的最初初始化函数。Nand_init()函数在两个文件中实现。其调用与CFG_NAND_LEGACY宏有关,如果没有定义这个宏,系统调用 drivers/nand/nand.c中的nand_init();否则调用自己在board/Embest/edukit2410/edukit2410.c中的nand_init()函数。这里我选择第二种方式。
#if defined(CONFIG_CMD_NAND)
typedef enum {
NFCE_LOW,
NFCE_HIGH
} NFCE_STATE;
static inline void NF_Conf(u16 conf)
{
S
nand->NFCONF = conf;
}
static inline void NF_Cmd(u8 cmd)
{
S
nand->NFCMD = cmd;
}
static inline void NF_CmdW(u8 cmd)
{
NF_Cmd(cmd);
udelay(1);
}
static inline void NF_Addr(u8 addr)
{
S
nand->NFADDR = addr;
}
static inline void NF_WaitRB(void)
{
S
while (!(nand->NFSTAT & (1<<0)));
}
static inline void NF_Write(u8 data)
{
S
nand->NFDATA = data;
}
static inline u8 NF_Read(void)
{
S
return(nand->NFDATA);
}
static inline u32 NF_Read_ECC(void)
{
S
return(nand->NFECC);
}
static inline void NF_SetCE(NFCE_STATE s)
{
S
switch (s) {
case NFCE_LOW:
nand->NFCONF &= ~(1<<11);
break;
case NFCE_HIGH:
nand->NFCONF |= (1<<11);
break;
}
}
static inline void NF_Init_ECC(void)
{
S
nand->NFCONF |= (1<<12);
}
extern ulong nand_probe(ulong physadr);
static inline void NF_Reset(void)
{
int i;
NF_SetCE(NFCE_LOW);
NF_Cmd(0xFF); /* reset command */
for(i = 0; i < 10; i++); /* tWB = 100ns. */
NF_WaitRB(); /* wait 200~500us; */
NF_SetCE(NFCE_HIGH);
}
static inline void NF_Init(void)
{
#if 0
#define TACLS 0
#define TWRPH0 3
#define TWRPH1 0
#else
#define TACLS 0
#define TWRPH0 4
#define TWRPH1 2
#endif
#if defined(CONFIG_S
NF_Conf((TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4));
NF_Cont((1<<6)|(1<<4)|(1<<1)|(1<<0));
#else
NF_Conf((1<<15)|(0<<14)|(0<<13)|(1<<12)|(1<<11)|(TACLS<<8)|(TWRPH0<<4)|(TWRPH1<<0));
/*nand->NFCONF = (1<<15)|(1<<14)|(1<<13)|(1<<12)|(1<<11)|(TACLS<<8)|(TWRPH0<<4)|(TWRPH1<<0); */
/* 1 1 1 1, 1 xxx, r xxx, r xxx */
/* En 512B 4step ECCR nFCE=H tACLS tWRPH0 tWRPH1 */
#endif
NF_Reset();
}
void nand_init(void)
{
S
NF_Init();
#ifdef DEBUG
printf("NAND flash probing at 0x%.8lX\n", (ulong)nand);
#endif
printf ("%4lu MB\n", nand_probe((ulong)nand) >> 20);
}
#endif