#define MEM_SYS_CFG (*((volatile unsigned long *)0x7E00F120)) //Configure memory subsystem
#define NFCONF (*((volatile unsigned long *)0x70200000)) //nand flash Configuration register
#define NFCONT (*((volatile unsigned long *)0x70200004)) //nand flash Control register
#define NFCMMD (*((volatile unsigned long *)0x70200008)) //nand flash Command register
#define NFADDR (*((volatile unsigned long *)0x7020000C)) //nand flash Address register
#define NFDATA (*((volatile unsigned char *)0x70200010)) //nand flash Data register
#define NFSTAT (*((volatile unsigned long *)0x70200028)) //nand flash Status register
#define TACLS 0
#define TWRPH0 1
#define TWRPH1 0
void nand_select(void)
{
NFCONT &= ~(1<<1); //Force Xm0CSn2 to low(Enable chip select)
}
void nand_deselect(void)
{
NFCONT |= (1<<1); //Force Xm0CSn2 to High(Disable chip select)
}
void nand_cmd(unsigned char cmd)
{
NFCMMD = cmd; //set nand flash command value
}
void nand_addr(unsigned char addr)
{
NFADDR = addr; //set nand flash address value
}
unsigned char nand_get_data(void)
{
return NFDATA; //get nand flash data value
}
void wait_ready(void)
{
while ((NFSTAT & 0x1) == 0); //wait till nand flash is ready
}
//reset nand flash
void nand_reset(void)
{
/* 选中 */
nand_select();
/* 发出0xff命令 */
nand_cmd(0xff);
/* 等待就绪 */
wait_ready();
/* 取消选中 */
nand_deselect();
}
//initialize nand flash
void nand_init(void)
{
/* 让xm0csn2用作nand flash cs0 片选引脚 */
MEM_SYS_CFG &= ~(1<<1);
/* 设置时间参数 */
NFCONF &= ~((1<<30) | (7<<12) | (7<<8) | (7<<4));
NFCONF |= ((TACLS<<12) | (TWRPH0<<8) | (TWRPH1<<4));
/* 使能nand flash controller */
NFCONT |= 1;
nand_reset();
}
//because I can't find data sheet of K9GAG08U0A, so I can only refer to data sheet of K9GAG08U0D
//some details are different but the theories are the same
//refer to "K9GAG08X0D Array Organization" in the K9GAG08U0D manual
void nand_send_addr(unsigned int addr)
{
nand_addr(addr & 0xff); /* a0~a7 */
nand_addr((addr >> 8) & 0x7); /* 程序的角度: a8~a10 */
nand_addr((addr >> 11) & 0xff); /* 程序的角度: a11~a18 */
nand_addr((addr >> 19) & 0xff); /* 程序的角度: a19~a26 */
nand_addr((addr >> 27) & 0xff); /* 程序的角度: a27~ */
}
//copy [len] bytes from [nand_start] on nand flash to [ddr_start] on sdram
int nand_read(unsigned int nand_start, unsigned int ddr_start, unsigned int len)
{
unsigned int addr = nand_start;
int i, count = 0;
unsigned char *dest = (unsigned char *)ddr_start;
/* 选中芯片 */
nand_select();
while (count < len)
{
/* 发出命令0x00 */
nand_cmd(0x00);
/* 发出地址 */
nand_send_addr(addr);
/* 发出命令0x30 */
nand_cmd(0x30);
/* 等待就绪 */
wait_ready();
/* 读数据 */
for (i = 0; i < 2048 && count < len; i++)
{
dest[count++] = nand_get_data();
}
addr += 2048;
}
/* 取消片选 */
nand_deselect();
return 0;
}
//the whole process to copy [len] bytes from [nand_start] on nand flash to [ddr_start] on sdram
int copy2ddr(unsigned int nand_start, unsigned int ddr_start, unsigned int len)
{
int ret;
/* 初始化nand flash controller */
nand_init();
/* 读nand flash */
ret = nand_read(nand_start, ddr_start, len);
return ret;
}
阅读(1081) | 评论(0) | 转发(0) |