#include <common.h> #include <s3c2440.h> #define BUSY??????????? 1 #ifdef?NAND_LARGEPAGE #define NAND_SECTOR_SIZE 2048 #else #define NAND_SECTOR_SIZE 512 #endif #define NAND_BLOCK_MASK (NAND_SECTOR_SIZE - 1) /* 供外部调用的函数 */ void nand_init_ll(void); void nand_read_ll(unsigned char *buf,unsigned long start_addr,int size); /* S3C2440的NAND Flash处理函数 */ static void nand_reset(void); static void wait_idle(void); static void nand_select_chip(void); static void nand_deselect_chip(void); static void write_cmd(int cmd); static void write_addr(unsigned int addr); static unsigned char read_data(void); /* S3C2440的NAND Flash操作函数 */ /* 复位 */ static void nand_reset(void) { ??? nand_select_chip(); ??? write_cmd(0xff);? // 复位命令 ??? wait_idle(); ??? nand_deselect_chip(); } /* 等待NAND Flash就绪 */ static void wait_idle(void) { ? int i; ?S3C2440_NAND * s3c2440nand = (S3C2440_NAND *)0x4e000000; ?volatile unsigned char *p = (volatile unsigned char *)&s3c2440nand->NFSTAT; ?while(!(*p & BUSY)) ?for(i=0; i<10; i++); } /* 发出片选信号 */ static void nand_select_chip(void) { ?int i; ?S3C2440_NAND * s3c2440nand = (S3C2440_NAND *)0x4e000000; ?s3c2440nand->NFCONT &= ~(1<<1); ?for(i=0; i<10; i++);???? } /* 取消片选信号 */ static void nand_deselect_chip(void) { ?S3C2440_NAND * s3c2440nand = (S3C2440_NAND *)0x4e000000; ??? s3c2440nand->NFCONT |= (1<<1); } /* 发出命令 */ static void write_cmd(int cmd) { ?S3C2440_NAND * s3c2440nand = (S3C2440_NAND *)0x4e000000; ??? volatile unsigned char *p = (volatile unsigned char *)&s3c2440nand->NFCMD; ??? *p = cmd; } /* 发出地址 Nand进行寻址的部分*/ static void write_addr(unsigned int addr) { ? int i; ?S3C2440_NAND * s3c2440nand = (S3C2440_NAND *)0x4e000000; ?volatile unsigned char *p = (volatile unsigned char *)&s3c2440nand->NFADDR; #ifndef?NAND_LARGEPAGE???? ?*p = addr & 0xff; ?for(i=0; i<10; i++); ?*p = (addr >> 9) & 0xff; ?for(i=0; i<10; i++); ?*p = (addr >> 17) & 0xff; ?for(i=0; i<10; i++); ?*p = (addr >> 25) & 0xff; ?for(i=0; i<10; i++); #else ?int col,page; ?col = addr & NAND_BLOCK_MASK; ?page = addr / NAND_SECTOR_SIZE; ?*p = col & 0xff;???/* Column Address A0~A7 */ ?for(i=0; i<10; i++);?? ?*p = (col >> 8) & 0x0f;??/* Column Address A8~A11 */ ?for(i=0; i<10; i++); ?*p = page & 0xff;???/* Row Address A12~A19 */ ?for(i=0; i<10; i++); ?*p = (page >> 8) & 0xff;?/* Row Address A20~A27 */ ?for(i=0; i<10; i++); ?*p = (page >> 16) & 0x03;?/* Row Address A28~A29 */ ?for(i=0; i<10; i++); #endif } /* 读取数据 */ static unsigned char read_data(void) { ?S3C2440_NAND * s3c2440nand = (S3C2440_NAND *)0x4e000000; ?volatile unsigned char *p = (volatile unsigned char *)&s3c2440nand->NFDATA; ?return *p; } /* 初始化NAND Flash */ void nand_init_ll(void) { ?S3C2440_NAND * s3c2440nand = (S3C2440_NAND *)0x4e000000; #define TACLS?? 0 #define TWRPH0? 3 #define TWRPH1? 0 ?/* 设置时序 */ ?s3c2440nand->NFCONF = (TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4); ?/* 使能NAND Flash控制器,初始化ECC,禁止片选 */ ?s3c2440nand->NFCONT = (1<<4)|(1<<1)|(1<<0); ?/* 复位NAND Flash */ ?nand_reset(); } /* 读函数 */ void nand_read_ll(unsigned char *buf,int size) { ??? int i,j; ??? if ((start_addr & NAND_BLOCK_MASK) || (size & NAND_BLOCK_MASK)) { ??????? return ;????/* 地址或长度不对齐 */ ??? } ????/* 选中芯片 */ ??? nand_select_chip(); ??? for(i=start_addr; i < (start_addr + size);) { ??????/* 发出READ0命令 */ ????? write_cmd(0); ??????/* Write Address */ ????? write_addr(i); #ifdef NAND_LARGEPAGE ?write_cmd(0x30); #endif ????? wait_idle(); ????? for(j=0; j < NAND_SECTOR_SIZE; j++,i++) { ????????? *buf = read_data(); ????????? buf++; ????? } ??? } ????/* 取消片选信号 */ ??? nand_deselect_chip(); ??? return ; } int bBootFrmNORFlash(void)???/* 取OM0、1的值,判断开发板是从NorFlash还是NandFlash启动 */ { ??volatile unsigned int *bwsCON = (volatile unsigned int *)0x48000000; ??unsigned int bwsVal; ??bwsVal = *bwsCON; ??bwsVal &= 0x06; ??if (bwsVal==0){ ???return 0; ??} ??else?{ ???return 1; ??} } int CopyCode2Ram(unsigned long start_addr,unsigned char *buf,int size) { ??? unsigned int *pdwDest; ??? unsigned int *pdwSrc; ??? int i; ??? if (bBootFrmNORFlash()) ??? { ????? pdwDest = (unsigned int *)buf; ????? pdwSrc? = (unsigned int *)start_addr; ????? /* 从 NOR Flash启动 */ ????? for (i = 0; i < size / 4; i++) ????? { ??????? pdwDest[i] = pdwSrc[i]; ????? } ??? } ??? else ??? { ????? /* 初始化NAND Flash */ ???nand_init_ll(); ????? /* 从 NAND Flash启动 */ ????? nand_read_ll(buf,start_addr,(size + NAND_BLOCK_MASK)&~(NAND_BLOCK_MASK)); ??? } ?return 0; } |