一、先实现可从nand flash启动
1.在u-boot-1.2.0/Makefile中
diff -urNu-boot-1.2.0.orig/Makefile u-boot-1.2.0/Makefile
---u-boot-1.2.0.orig/Makefile 2007-01-0707:13:11.000000000 +0800
+++u-boot-1.2.0/Makefile 2007-09-1912:09:20.000000000 +0800
@@ -125,7+125,7 @@
CROSS_COMPILE = powerpc-linux-
endif
ifeq ($(ARCH),arm)
-CROSS_COMPILE = arm-linux-
+CROSS_COMPILE =/usr/local/arm/arm-2007q1/bin/arm-none-linux-gnueabi-
endif
这是需要修改的第一段代码
其实就是把/u-boot-1.2.0/Makefile程序第125行改了,其实就是设定交叉编译器,这段代码是很好的学习材料
这就是一个补丁的制作过程
diff:以u-boot-1.2.0/Makefile为目标文件,以u-boot-1.2.0.orig/Makefile为源文件
2.在u-boot-1.2.0/board/smdk2410/中
Makefile
diff -urN u-boot-1.2.0.orig/board/smdk2410/Makefileu-boot-1.2.0/board/smdk2410/Makefile
---u-boot-1.2.0.orig/board/smdk2410/Makefile 2007-01-0707:13:11.000000000 +0800
+++u-boot-1.2.0/board/smdk2410/Makefile 2007-09-1912:22:24.000000000 +0800
@@ -25,7 +25,7 @@
LIB = $(obj)lib$(BOARD).a
-COBJS := smdk2410.o flash.o
+COBJS := smdk2410.o flash.onand_read.o
SOBJS :=lowlevel_init.o
SRCS := $(SOBJS:.o=.S)$(COBJS:.o=.c)
lowlevel_init.S
diff -urNu-boot-1.2.0.orig/board/smdk2410/lowlevel_init.Su-boot-1.2.0/board/smdk2410/lowlevel_init.S
---u-boot-1.2.0.orig/board/smdk2410/lowlevel_init.S 2007-01-0707:13:11.000000000 +0800
+++u-boot-1.2.0/board/smdk2410/lowlevel_init.S 2007-09-1912:22:08.000000000 +0800
@@ -123,7 +123,7 @@
#define Trp 0x0
#define Trc 0x3
#define Tchr 0x2
-#define REFCNT 1113
+#defineREFCNT 1268
_TEXT_BASE:
新建文件nand_read.c
diff -urNu-boot-1.2.0.orig/board/smdk2410/nand_read.cu-boot-1.2.0/board/smdk2410/nand_read.c
---u-boot-1.2.0.orig/board/smdk2410/nand_read.c 1970-01-0108:00:00.000000000 +0800
+++u-boot-1.2.0/board/smdk2410/nand_read.c 2007-09-1912:24:13.000000000 +0800
@@ -0,0 +1,77 @@
+
+
+#include<config.h>
+
+#ifdef CONFIG_S3C2410_NAND_BOOT
+
+#define __REGb(x) (*(volatile unsigned char*)(x))
+#define __REGi(x) (*(volatile unsigned int*)(x))
+#defineNF_BASE 0x4e000000
+#define NFCONF __REGi(NF_BASE +0x0)
+#define NFCMD __REGb(NF_BASE +0x4)
+#define NFADDR __REGb(NF_BASE +0x8)
+#define NFDATA __REGb(NF_BASE +0xc)
+#define NFSTAT __REGb(NF_BASE +0x10)
+
+#define BUSY 1
+inline void wait_idle(void) {
+ inti;
+
+ while(!(NFSTAT & BUSY))
+ for(i=0; i<10; i++);
+}
+
+#define NAND_SECTOR_SIZE 512
+#defineNAND_BLOCK_MASK (NAND_SECTOR_SIZE- 1)
+
+
+int
+nand_read_ll(unsigned char *buf, unsigned long start_addr, intsize)
+{
+ int i,j;
+
+ if((start_addr & NAND_BLOCK_MASK) || (size& NAND_BLOCK_MASK)) {
+ return -1;
+ }
+
+
+ NFCONF&= ~0x800;
+ for(i=0;i<10; i++);
+
+ for(i=start_addr; i < (start_addr + size);) {
+
+ NFCMD = 0;
+
+
+ NFADDR = i & 0xff;
+ NFADDR = (i >> 9) &0xff;
+ NFADDR = (i >> 17) &0xff;
+ NFADDR = (i >> 25) &0xff;
+
+ wait_idle();
+
+ for(j=0; j < NAND_SECTOR_SIZE; j++, i++) {
+ *buf = (NFDATA & 0xff);
+ buf++;
+ }
+ }
+
+
+ NFCONF |=0x800;
+
+ return0;
+}
+
+#endif
smdk2410.c
diff -urN u-boot-1.2.0.orig/board/smdk2410/smdk2410.cu-boot-1.2.0/board/smdk2410/smdk2410.c
---u-boot-1.2.0.orig/board/smdk2410/smdk2410.c 2007-01-0707:13:11.000000000 +0800
+++u-boot-1.2.0/board/smdk2410/smdk2410.c 2007-09-1912:21:39.000000000 +0800
@@ -36,10 +36,10 @@
#define M_MDIV 0xC3
#define M_PDIV 0x4
#define M_SDIV 0x1
-#elif FCLK_SPEED==1
-#define M_MDIV 0xA1
-#define M_PDIV 0x3
-#define M_SDIV 0x1
+#elifFCLK_SPEED==1
+#define M_MDIV 0x5C
+#define M_PDIV 0x4
+#defineM_SDIV 0x0
#endif
#define USB_CLOCK 1
@@ -87,7 +87,7 @@
gpio->GPACON =0x007FFFFF;
- gpio->GPBCON = 0x00044555;
+ gpio->GPBCON =0x000055A;
gpio->GPBUP= 0x000007FF;
gpio->GPCCON =0xAAAAAAAA;
gpio->GPCUP =0x0000FFFF;
@@ -99,7 +99,7 @@
gpio->GPFUP =0x000000FF;
gpio->GPGCON =0xFF95FFBA;
gpio->GPGUP =0x0000FFFF;
- gpio->GPHCON = 0x002AFAAA;
+ gpio->GPHCON =0x0016FAAA;
gpio->GPHUP= 0x000007FF;
3.在u-boot-1.2.0/cpu/arm920t中
start.S(第一层汇编程序入口)
diff -urN u-boot-1.2.0.orig/cpu/arm920t/start.Su-boot-1.2.0/cpu/arm920t/start.S
---u-boot-1.2.0.orig/cpu/arm920t/start.S 2007-01-0707:13:11.000000000 +0800
+++ u-boot-1.2.0/cpu/arm920t/start.S 2007-09-1912:37:00.000000000 +0800
@@ -27,7 +27,7 @@
#include<config.h>
#include<version.h>
-
+#include<s3c2410.h>
ldr r0,=INTSUBMSK
str r1,[r0]
# endif
@@ -161,6 +161,7 @@
#endif
#ifndef CONFIG_SKIP_RELOCATE_UBOOT
+#ifndefCONFIG_S3C2410_NAND_BOOT
relocate:
adr r0,_start
ldr r1,_TEXT_BASE
@@ -177,8 +178,67 @@
stmia r1!,{r3-r10}
cmp r0,r2
ble copy_loop
+#else
+relocate:
+copy_myself:
+ @ reset NAND
+ mov r1,#S3C2410_NAND_BASE
+ ldr r2,=0xf830 @ initial valueenable
+ str r2, [r1, #oNFCONF]
+ ldr r2, [r1, #oNFCONF]
+ bic r2, r2,#0x800 @ enable chip
+ str r2, [r1, #oNFCONF]
+ mov r2,#0xff @ RESET command
+ strb r2, [r1, #oNFCMD]
+ mov r3,#0 @wait
+1: add r3, r3, #0x1
+ cmp r3, #0xa
+ blt 1b
+2: ldr r2, [r1,#oNFSTAT] @ wait ready
+ tst r2, #0x1
+ beq 2b
+ ldr r2, [r1, #oNFCONF]
+ orr r2, r2,#0x800 @ disable chip
+ str r2, [r1, #oNFCONF]
+
+
+ ldr r0,_TEXT_BASE
+ sub r0, r0,#CFG_MALLOC_LEN
+ sub r0, r0,#CFG_GBL_DATA_SIZE
+#ifdef CONFIG_USE_IRQ
+ sub r0, r0,#(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)
+#endif
+ sub sp, r0,#12
+
+ @ copy u-boot to RAM
+ ldr r0, _TEXT_BASE
+ mov r1, #0x0
+ mov r2, #CFG_UBOOT_SIZE
+ bl nand_read_ll
+
+ tst r0, #0x0
+ beq ok_nand_read
+
+ok_nand_read:
+ @ verify
+ mov r0, #0
+ ldr r1, _TEXT_BASE
+ mov r2,#0x400 @ 4 bytes * 1024 = 4K-bytes
+go_next:
+ ldr r3, [r0], #4
+ ldr r4, [r1], #4
+ teq r3, r4
+ bne notmatch
+ subs r2, r2, #4
+ beq done_nand_read
+ bne go_next
+notmatch:
+1: b 1b
+done_nand_read:
+#endif
#endif
+#ifndefCONFIG_S3C2410_NAND_BOOT
stack_setup:
ldr r0,_TEXT_BASE
@@ -188,6 +248,7 @@
sub r0, r0,#(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)
#endif
sub sp, r0,#12
+#endif
clear_bss:
ldr r0,_bss_start
4.在u-boot-1.2.0/include/Configs/smdk2410.h中
diff -urN u-boot-1.2.0.orig/include/configs/smdk2410.hu-boot-1.2.0/include/configs/smdk2410.h
---u-boot-1.2.0.orig/include/configs/smdk2410.h 2007-01-0707:13:11.000000000 +0800
+++u-boot-1.2.0/include/configs/smdk2410.h 2007-09-1912:42:45.000000000 +0800
@@ -82,6 +82,8 @@
/
/
/
+ CFG_CMD_NET | /
+ CFG_CMD_PING |/
CFG_CMD_REGINFO | /
CFG_CMD_DATE | /
CFG_CMD_ELF)
@@ -91,10 +93,10 @@
#define CONFIG_BOOTDELAY 3
-
+#defineCONFIG_ETHADDR 08:00:3e:26:0a:5b
#defineCONFIG_NETMASK 255.255.255.0
-#defineCONFIG_IPADDR 10.0.0.110
-#defineCONFIG_SERVERIP 10.0.0.1
+#defineCONFIG_IPADDR 192.168.1.110
+#defineCONFIG_SERVERIP 192.168.1.216
@@ -108,7 +110,7 @@
* Miscellaneous configurable options
*/
#define CFG_LONGHELP
-#define CFG_PROMPT "SMDK2410# "
+#define CFG_PROMPT "U-boot#"
#define CFG_CBSIZE 256
#define CFG_PBSIZE(CFG_CBSIZE+sizeof(CFG_PROMPT)+16)
#define CFG_MAXARGS 16
@@ -178,4 +180,8 @@
#define CFG_ENV_IS_IN_FLASH 1
#defineCFG_ENV_SIZE 0x10000
+
+#define CONFIG_S3C2410_NAND_BOOT
+#defineCFG_UBOOT_SIZE 0x20000
+
#endif
5.在u-boot-1.2.0/include/s3c2410.h
diff -urN u-boot-1.2.0.orig/include/s3c2410.hu-boot-1.2.0/include/s3c2410.h
--- u-boot-1.2.0.orig/include/s3c2410.h 2007-01-0707:13:11.000000000 +0800
+++ u-boot-1.2.0/include/s3c2410.h 2007-09-1912:38:31.000000000 +0800
@@ -38,12 +38,6 @@
#defineS3C2410_ECCSIZE 512
#define S3C2410_ECCBYTES 3
-typedef enum {
- S3C24X0_UART0,
- S3C24X0_UART1,
- S3C24X0_UART2
-} S3C24X0_UARTS_NR;
-
#defineS3C24X0_MEMCTL_BASE 0x48000000
#defineS3C24X0_USB_HOST_BASE 0x49000000
@@ -64,10 +58,23 @@
#defineS3C24X0_SPI_BASE 0x59000000
#defineS3C2410_SDI_BASE 0x5A000000
+#defineoNFCONF 0x00
+#defineoNFCMD 0x04
+#defineoNFADDR 0x08
+#defineoNFDATA 0x0C
+#defineoNFSTAT 0x10
+#defineoNFECC 0x14
+
+#ifndef __ASSEMBLER__
#include<s3c24x0.h>
+typedef enum {
+ S3C24X0_UART0,
+ S3C24X0_UART1,
+ S3C24X0_UART2
+} S3C24X0_UARTS_NR;
static inline S3C24X0_MEMCTL * constS3C24X0_GetBase_MEMCTL(void)
{
@@ -224,4 +231,7 @@
rINTPND;/
}
+
+#endif
+
#endif
二、再实现支持nand flash 读写的部分(可以去掉2440的部分):
U-Boot 1.1.6中对NANDFlash的支持有新旧两套代码,新代码在drivers/nand目录下,旧代码在drivers/nand_legacy目录下。文档doc/README.nand对这两套代码有所说明:使用旧代码需要定义更多的宏,而新代码移植自Linux内核2.6.12,它更加智能,可以自动识别更多型号的NANDFlash。目前之所以还保留旧的代码,是因为两个目标板NETTA、NETTA_ISDN使用JFFS文件系统,它们还依赖于旧代码。当相关功能移植到新代码之后,旧的代码将从U-Boot中去除。
要让U-Boot支持NAND Flash,首先在配置文件include/configs/100ask24x0.h的宏CONFIG_COMMANDS中增加CFG_CMD_NAND,如下:
#define CONFIG_COMMANDS /
(CONFIG_CMD_DFL | /
CFG_CMD_CACHE | /
CFG_CMD_PING | /
CFG_CMD_NAND| /
……
然后选择使用哪套代码:在配置文件中定义宏CFG_NAND_LEGACY则使用旧代码,否则使用新代码。
使用旧代码时,需要实现drivers/nand_legacy/nand_legacy.c中使用到的各种宏,比如:
#define NAND_WAIT_READY(nand)/* 等待Nand Flash的状态为“就绪”,代码依赖于具体的开发板 */
#define WRITE_NAND_COMMAND(d, adr)/* 写NAND Flash命令,代码依赖于具体的开发板 */
本书使用新代码,下面讲述移植过程。
代码的移植没有现成的文档,可以在配置文件include/configs/100ask24x0.h的宏CONFIG_COMMANDS中增加CFG_CMD_NAND后,就编译代码,然后一个一个地解决出现的错误。编译结果中出现的错误和警告如下:
nand.h:412: error: `NAND_MAX_CHIPS' undeclared here (not in a function)
nand.c:35: error: `CFG_MAX_NAND_DEVICE' undeclared here (not in a function)
nand.c:38: error: `CFG_NAND_BASE' undeclared here (not in a function)
nand.c:35: error: storage size of `nand_info' isn't known
nand.c:37: error: storage size of `nand_chip' isn't known
nand.c:38: error: storage size of `base_address' isn't known
nand.c:37: warning: 'nand_chip' defined but not used
nand.c:38: warning: 'base_address' defined but not used
在配置文件include/configs/100ask24x0.h中增加如下3个宏就可以解决上述错误。在Flash的驱动程序中,设备是逻辑上的概念,表示一组相同结构、访问函数相同的Flash芯片。在本书所用开发板中,只有一个NAND Flash芯片,所以设备数为1,芯片数也为1。
#define CFG_NAND_BASE 0/* 无实际意义:基地址,这在board_nand_init中重新指定 */
#define CFG_MAX_NAND_DEVICE 1/* NAND Flash“设备”的数目为1 */
#define NAND_MAX_CHIPS 1/* 每个NAND Flash“设备”由1个NAND Flash“芯片”组成 */
修改配置文件后再次编译,现在只有一个错误了,“board_nand_init函数未定义”:
nand.c:50: undefined reference to `board_nand_init'
调用board_nand_init函数的过程为:NANDFlash的初始化入口函数是nand_init,它在lib_arm/board.c的start_armboot函数中被调用;nand_init函数在drivers/nand/nand.c中实现,它调用相同文件中的nand_init_chip函数;nand_init_chip函数首先调用board_nand_init函数来初始化NAND Flash设备,最后才是统一的识别过程。
从board_nand_init函数的名称就可以知道它是平台/开发板相关的函数,需要自己编写。本书在cpu/arm920t/s3c24x0目录下新建一个文件nand_flash.c,在里面针对S3C2410、S3C2440实现了统一的board_nand_init函数。
在编写board_nand_init函数的之前,需要针对S3C2410、S3C2440 NAND Flash控制器的不同定义一些数据结构和函数:
(1)在include/s3c24x0.h文件中增加S3C2440_NAND数据结构。
/* NAND FLASH (see S3C2440 manual chapter 6, www.100ask.net) */
typedef struct {
S3C24X0_REG32 NFCONF;
S3C24X0_REG32 NFCONT;
S3C24X0_REG32 NFCMD;
S3C24X0_REG32 NFADDR;
S3C24X0_REG32 NFDATA;
S3C24X0_REG32 NFMECCD0;
S3C24X0_REG32 NFMECCD1;
S3C24X0_REG32 NFSECCD;
S3C24X0_REG32 NFSTAT;
S3C24X0_REG32 NFESTAT0;
S3C24X0_REG32 NFESTAT1;
S3C24X0_REG32 NFMECC0;
S3C24X0_REG32 NFMECC1;
S3C24X0_REG32 NFSECC;
S3C24X0_REG32 NFSBLK;
S3C24X0_REG32 NFEBLK;
} /*__attribute__((__packed__))*/ S3C2440_NAND;
(2)在include/s3c2410.h文件中仿照S3C2410_GetBase_NAND函数定义S3C2440_GetBase_NAND函数。
/* for s3c2440, www.100ask.net */
static inline S3C2440_NAND * const S3C2440_GetBase_NAND(void)
{
return (S3C2440_NAND * const)S3C2410_NAND_BASE;
}
既然新的NANDFlash代码是从Linux内核2.6.12中移植来的,那么cpu/arm920t/s3c24x0/nand_flash.c文件也可以仿照内核中,对S3C2410、S3C2440的NANDFlash进行初始化的drivers/mtd/nand/s3c2410.c文件来编写。为了方便阅读,先把cpu/arm920t/s3c24x0/nand_flash.c文件的代码全部列出来,再讲解:
01 /*
02 * s3c2410/s3c2440的NAND Flash控制器接口, www.100ask.net
03 * 修改自Linux内核2.6.13文件drivers/mtd/nand/s3c2410.c
04 */
05
06 #include <common.h>
07
08 #if (CONFIG_COMMANDS & CFG_CMD_NAND) && !defined(CFG_NAND_LEGACY)
09 #include <s3c2410.h>
10 #include <nand.h>
11
12 DECLARE_GLOBAL_DATA_PTR;
13
14 #define S3C2410_NFSTAT_READY (1<<0)
15 #define S3C2410_NFCONF_nFCE (1<<11)
16
17 #define S3C2440_NFSTAT_READY (1<<0)
18 #define S3C2440_NFCONT_nFCE (1<<1)
19
20
21 /* S3C2410:NAND Flash的片选函数 */
22 static void s3c2410_nand_select_chip(struct mtd_info *mtd, int chip)
23 {
24 S3C2410_NAND * const s3c2410nand = S3C2410_GetBase_NAND();
25
26 if (chip == -1) {
27 s3c2410nand->NFCONF |= S3C2410_NFCONF_nFCE;/* 禁止片选信号 */
28 } else {
29 s3c2410nand->NFCONF &= ~S3C2410_NFCONF_nFCE;/* 使能片选信号 */
30 }
31 }
32
33 /* S3C2410:命令和控制函数
34 *
35 * 注意,这个函数仅仅根据各种命令来修改“写地址”IO_ADDR_W 的值(这称为tglx方法),
36 * 这种方法使得平台/开发板相关的代码很简单。
37 * 真正发出命令是在上一层NAND Flash的统一的驱动中实现,
38 * 它首先调用这个函数修改“写地址”,然后才分别发出控制、地址、数据序列。
39 */
40 static void s3c2410_nand_hwcontrol(struct mtd_info *mtd, int cmd)
41 {
42 S3C2410_NAND * const s3c2410nand = S3C2410_GetBase_NAND();
43 struct nand_chip *chip = mtd->priv;
44
45 switch (cmd) {
46 case NAND_CTL_SETNCE:
47 case NAND_CTL_CLRNCE:
48 printf("%s: called for NCE/n", __FUNCTION__);
49 break;
50
51 case NAND_CTL_SETCLE:
52 chip->IO_ADDR_W = (void *)&s3c2410nand->NFCMD;
53 break;
54
55 case NAND_CTL_SETALE:
56 chip->IO_ADDR_W = (void *)&s3c2410nand->NFADDR;
57 break;
58
59 /* NAND_CTL_CLRCLE: */
60 /* NAND_CTL_CLRALE: */
61 default:
62 chip->IO_ADDR_W = (void *)&s3c2410nand->NFDATA;
63 break;
64 }
65 }
66
67 /* S3C2410:查询NAND Flash状态
68 *
69 * 返回值:0 – 忙, 1 – 就绪
70 */
71 static int s3c2410_nand_devready(struct mtd_info *mtd)
72 {
73 S3C2410_NAND * const s3c2410nand = S3C2410_GetBase_NAND();
74
75 return (s3c2410nand->NFSTAT & S3C2410_NFSTAT_READY);
76 }
77
78
79 /* S3C2440:NAND Flash的片选函数 */
80 static void s3c2440_nand_select_chip(struct mtd_info *mtd, int chip)
81 {
82 S3C2440_NAND * const s3c2440nand = S3C2440_GetBase_NAND();
83
84 if (chip == -1) {
85 s3c2440nand->NFCONT |= S3C2440_NFCONT_nFCE;/* 禁止片选信号 */
86 } else {
87 s3c2440nand->NFCONT &= ~S3C2440_NFCONT_nFCE;/* 使能片选信号 */
88 }
89 }
90
91 /* S3C2440:命令和控制函数,与s3c2410_nand_hwcontrol函数类似 */
92 static void s3c2440_nand_hwcontrol(struct mtd_info *mtd, int cmd)
93 {
94 S3C2440_NAND * const s3c2440nand = S3C2440_GetBase_NAND();
95 struct nand_chip *chip = mtd->priv;
96
97 switch (cmd) {
98 case NAND_CTL_SETNCE:
99 case NAND_CTL_CLRNCE:
100 printf("%s: called for NCE/n", __FUNCTION__);
101 break;
102
103 case NAND_CTL_SETCLE:
104 chip->IO_ADDR_W = (void *)&s3c2440nand->NFCMD;
105 break;
106
107 case NAND_CTL_SETALE:
108 chip->IO_ADDR_W = (void *)&s3c2440nand->NFADDR;
109 break;
110
111 /* NAND_CTL_CLRCLE: */
112 /* NAND_CTL_CLRALE: */
113 default:
114 chip->IO_ADDR_W = (void *)&s3c2440nand->NFDATA;
115 break;
116 }
117 }
118
119 /* S3C2440:查询NAND Flash状态
120 *
121 * 返回值:0 – 忙, 1 – 就绪
122 */
123 static int s3c2440_nand_devready(struct mtd_info *mtd)
124 {
125 S3C2440_NAND * const s3c2440nand = S3C2440_GetBase_NAND();
126
127 return (s3c2440nand->NFSTAT & S3C2440_NFSTAT_READY);
128 }
129
130 /*
131 * Nand flash硬件初始化:
132 * 设置NAND Flash的时序, 使能NAND Flash控制器
133 */
134 static void s3c24x0_nand_inithw(void)
135 {
136 S3C2410_NAND * const s3c2410nand = S3C2410_GetBase_NAND();
137 S3C2440_NAND * const s3c2440nand = S3C2440_GetBase_NAND();
138
139 #define TACLS 0
140 #define TWRPH0 4
141 #define TWRPH1 2
142
143 if (gd->bd->bi_arch_number == MACH_TYPE_SMDK2410)
144 {
145 /* 使能NAND Flash控制器,初始化ECC,使能片选信号,设置时序 */
146 s3c2410nand->NFCONF = (1<<15)|(1<<12)|(1<<11)|(TACLS<<8)|(TWRPH0<<4)|(TWRPH1<<0);
147 }
148 else
149 {
150 /* 设置时序 */
151 s3c2440nand->NFCONF = (TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4);
152 /* 初始化ECC,使能NAND Flash控制器,使能片选信号 */
153 s3c2440nand->NFCONT = (1<<4)|(0<<1)|(1<<0);
154 }
155 }
156
157 /*
158 * 被drivers/nand/nand.c调用, 初始化NAND Flash硬件,初始化访问接口函数
159 */
160 void board_nand_init(struct nand_chip *chip)
161 {
162 S3C2410_NAND * const s3c2410nand = S3C2410_GetBase_NAND();
163 S3C2440_NAND * const s3c2440nand = S3C2440_GetBase_NAND();
164
165 s3c24x0_nand_inithw();/* Nand flash硬件初始化 */
166
167 if (gd->bd->bi_arch_number == MACH_TYPE_SMDK2410) {
168 chip->IO_ADDR_R = (void *)&s3c2410nand->NFDATA;
169 chip->IO_ADDR_W = (void *)&s3c2410nand->NFDATA;
170 chip->hwcontrol = s3c2410_nand_hwcontrol;
171 chip->dev_ready = s3c2410_nand_devready;
172 chip->select_chip = s3c2410_nand_select_chip;
173 chip->options = 0;/* 设置位宽等,位宽为8 */
174 } else {
175 chip->IO_ADDR_R = (void *)&s3c2440nand->NFDATA;
176 chip->IO_ADDR_W = (void *)&s3c2440nand->NFDATA;
177 chip->hwcontrol = s3c2440_nand_hwcontrol;
178 chip->dev_ready = s3c2440_nand_devready;
179 chip->select_chip = s3c2440_nand_select_chip;
180 chip->options = 0;/* 设置位宽等,位宽为8 */
181 }
182
183 chip->eccmode = NAND_ECC_SOFT;/* ECC较验方式:软件ECC */
184 }
185
186 #endif
文件中分别针对S3C2410、S3C2440实现了NAND Flash最底层访问函数,并进行了一些硬件的设置(比如时序、使能NANDFlash控制器等)。新的代码对NANDFlash的封装做得很好,只要向上提供底层初始化函数board_nand_init来设置好平台/开发板相关的初始化、提供底层接口即可。
最后,只要将新建的nand_flash.c文件编入U-Boot中就可以擦除、读写NAND Flash了。如下修改cpu/arm920t/s3c24x0/Makefile文件即可:
COBJS = i2c.o interrupts.o serial.o speed.o /
usb_ohci.o
改为:
COBJS = i2c.o interrupts.o serial.o speed.o /
usb_ohci.o nand_flash.o
现在,可以使用新编译的u-boot.bin烧写内核映像到NAND Flash去了,请参考15.2.6。