移植参考了韦东山编写的《嵌入式linux应用开发完全手册》,这真是一本不错的书!本次移植中因为想从nand
启动,就没有修改nor flash的部分.
步骤1.我的开发板取名为s3c2440明,建立与开发板对应的目录和文件,由于s3c2440和smdk2410很相似,就直接复制一份.
learnboy@debian:~/project/arm/u-boot-1.1.6$ cp -av board/smdk2410/ board/s3c2440
“board/smdk2410/” -> “board/s3c2440”
“board/smdk2410/smdk2410.c” -> “board/s3c2440/smdk2410.c”
“board/smdk2410/Makefile” -> “board/s3c2440/Makefile”
“board/smdk2410/config.mk” -> “board/s3c2440/config.mk”
“board/smdk2410/lowlevel_init.S” -> “board/s3c2440/lowlevel_init.S”
“board/smdk2410/u-boot.lds” -> “board/s3c2440/u-boot.lds”
“board/smdk2410/flash.c” -> “board/s3c2440/flash.c”
将 smdk2410.c改为s3c2440.c,
learnboy@debian:~/project/arm/u-boot-1.1.6$ mv board/s3c2440/smdk2410.c board/s3c2440/s3c2440.c
接下来在include/configs目录下建立配置文件s3c2440.h,直接复制就行
learnboy@debian:~/project/arm/u-boot-1.1.6$ cp include/configs/smdk2410.h include/configs/s3c2440.h
修改Makefile文件,在顶层Makefile中1881行处添加如下两行
s3c2440_config: unconfig
@$(MKCONFIG) $(@:_CONFIG=) arm arm920t s3c2440 NULL s3c24x0
修改board/s3c2440目录下的Makefile的28行由
COBJS := smdk2410.o flash.o
改为
COBJS := s3c2440.o flash.o
步骤2: 针对自己的开发板修改start.s,加入下列内容:
121 #if defined(CONFIG_s3c2440)
122 /*先定义出一些寄存器*/
123 # define pWTCON 0x53000000 /*看门狗寄存器地址*/
124 # define INTMSK 0x4A000008 /* Interupt-Controller base addresses */
125 # define INTSUBMSK 0x4A00001C
126 # define CLKDIVN 0x4C000014 /* clock divisor register */
/*确定分频比 为1:4:8,参照S3C2440A 的datasheet*/
127 # define CLKDIVN_val 5
128
129 #define LOCKTIME 0x4c000000
130 #define MPLLCON 0x4c000004
131 #define UPLLCON 0x4c000008
132 #define MPLLCON_val ((0x7f << 12)|(0x2 << 4)|(0x1))
133 #define UPLLCON_val ((0x3c << 12)|(0x4 << 4)|(0x2))
... ...
/*关闭看门狗*/
140 ldr r0, =pWTCON
141 mov r1, #0x0
142 str r1, [r0]
143
144 /*
145 * mask all IRQs by setting all bits in the INTMR - default
146 */
147 mov r1, #0xffffffff
148 ldr r0, =INTMSK
149 str r1, [r0]
150 /*设置分频比*/
151 /* FCLK:HCLK:PCLK = 1:4:8 */
152 /* default FCLK is 12 MHz ! */
153
154 ldr r0, =CLKDIVN
155 mov r1, #CLKDIVN_val
156 str r1, [r0]
... ...
162
163
164 ldr r1,=0x7fff
165 ldr r0,=INTSUBMSK
166 str r1,[r0]
167
168
169 /*Clock asynchronous mode */
170 mrc p15, 0, r1, c1, c0, 0
171 orr r1, r1, #0xc000000
172 mcr p15, 0, r1, c1, c0, 0
173
174 ldr r0, =MPLLCON
175 ldr r1, =MPLLCON_val
176 str r1,[r0]
177
178 ldr r0, =UPLLCON
179 ldr r1, =UPLLCON_val
180 str r1,[r0]
181
182 #endif
... ...
/*将flash 启动改为从 nand 启动*/
214 #ifdef CONFIG_s3c2440_NAND_BOOT
215
216 @ reset NAND
217 mov r1, #NAND_CTL_BASE
218 ldr r2, =( ( 7 << 12 ) | ( 7 << 8 ) | ( 7 << 4 ) | ( 0 << 0 ))
219 str r2, [r1, #oNFCONF]
220 ldr r2, [r1, #oNFCONF]
221
222 ldr r2, =( 1 << 4 ) | ( 0 << 1 ) | ( 1 << 0 )
223 str r2, [r1, #oNFCONT]
224 ldr r2, [r1, #oNFCONT]
225
226 ldr r2, =(0x6) @ RnB clear
227 str r2, [r1, #oNFSTAT]
228 ldr r2, [r1, #oNFSTAT]
229
230 mov r2, #0xff @ RESET command
231 strb r2, [r1, #oNFCMD]
232 mov r3, #0 @wait
233 nand1:
234 add r3, r3, #0x1
235 cmp r3, #0xa
236 blt nand1
237 nand2:
238 ldr r2, [r1, #oNFSTAT] @ wait ready
239 tst r2, #0x4
240 beq nand2
241
242
243 ldr r2, [r1, #oNFCONT]
244 orr r2, r2, #0x2 @Flash Memory Chip Disable
245 str r2, [r1, #oNFCONT]
246
247 @ get read to call C s ( for nand_read() )
248 ldr sp, DW_STACK_START @ setup stack pointer
249 mov fp, #0 @ no previous, so fp = 0
250
251 @ copy U-boot to RAM
252
253 ldr r0, =TEXT_BASE
254 mov r1, #0x0
255 mov r2, #0x30000
256 bl nand_read_ll /*nand_read_ll 函数代码在vivi中有,可以直接复制过来*/
257 tst r0, #0x0
258 beq ok_nand_read
259 bad_nand_read:
260 loop2: b loop2 @infinate loop
261
262 ok_nand_read:
263 @ verify
264 mov r0, #0
265 ldr r1, =TEXT_BASE
266 mov r2, #0x400 @ 4 bytes * 1024 = 4K bytes
267
268 go_next:
269 ldr r3, [r0], #4
270 ldr r4, [r1], #4
271 teq r3, r4
272 bne notmatch
273 subs r2, r2, #4
274 beq stack_setup
275 bne go_next
276 notmatch:
277 loop3: b loop3 @ infinite loop
278
279 #endif
/* 代码搬移完成后,让四个LED灯亮,表示此前的步骤都已经成功完成 */
326 #if defined(CONFIG_s3c2440)
327
328 @ LED1 on u-boot stage 1 is
329
330 mov r1, #GPIO_CTL_BASE
331 add r1, r1, #oGPIO_F
332 ldr r2, =0x5500
333 str r2, [r1,#oGPIO_CON]
334 mov r2, #0xff
335 str r2,[r1, #oGPIO_UP]
336 mov r2, #0x0f
337 str r2,[r1,#oGPIO_DAT]
338
339 #endif
340 /*跳到第二阶段C函数入口 */
341 ldr pc, _start_armboot
342
343 _start_armboot: .word start_armboot
344 .align 2
345 DW_STACK_START: .word STACK _BASE+STACK_SIZE-4
步骤3:拷贝vivi中的nand_read.c 文件到board/s3c2440文件夹下。代码如下:
/*
2 * vivi/s3c2410/nand_read.c: Simple NAND read functions for booting from NAND
3 *
4 * Copyright (C) 2002 MIZI Research, Inc.
5 *
6 * Author: Hwang, Chideok
7 * Date : $Date: 2004/02/04 06:22:24 $
8 *
9 * $Revision: 1.1.1.1 $
10 * $Id: param.c,v 1.9 2002/07/11 06:17:20 nandy Exp
11 *
12 * History
13 *
14 * 2002-05-xx: Hwang, Chideok
15 *
16 * 2002-05-xx: Chan Gyun Jeong
17 *
18 * 2002-08-10: Yong-iL Joh
19 *
20 */
21
22 #include
23
24 #define __REGb(x) (*(volatile unsigned char *)(x))
25 #define __REGi(x) (*(volatile unsigned int *)(x))
26 #define NF_BASE 0x4e000000
27
28 #if defined(CONFIG_s3c2440)
29
30 #define NFCONF __REGi(NF_BASE + 0x0)
31 #define NFCONT __REGi(NF_BASE + 0x4)
32 #define NFCMD __REGb(NF_BASE + 0x8)
33 #define NFADDR __REGb(NF_BASE + 0xC)
34 #define NFDATA __REGb(NF_BASE + 0x10)
35 #define NFSTAT __REGb(NF_BASE + 0x20)
36
37 //#define GPDAT __REGi(GPIO_CTL_BASE+oGPIO_F+oGPIO_DAT)
38
39 #define NAND_CHIP_ENABLE (NFCONT &= ~(1<<1))
40 #define NAND_CHIP_DISABLE (NFCONT |= (1<<1))
41 #define NAND_CLEAR_RB (NFSTAT |= (1<<2))
42 #define NAND_DETECT_RB { while(! (NFSTAT&(1<<2)) );}
43
44 #define BUSY 4
45 inline void wait_idle(void) {
46 while(!(NFSTAT & BUSY));
47 NFSTAT |= BUSY;
48 }
49
50 #define NAND_SECTOR_SIZE 512
51 #define NAND_BLOCK_MASK (NAND_SECTOR_SIZE - 1)
52
53 /* low level nand read function */
54 int
55 nand_read_ll(unsigned char *buf, unsigned long start_addr, int size)
56 {
57 int i, j;
58
59 if ((start_addr & NAND_BLOCK_MASK) || (size & NAND_BLOCK_MASK)) {
60 return -1; /* invalid alignment */
61 }
62
63 NAND_CHIP_ENABLE;
64
65 for(i=start_addr; i < (start_addr + size);) {
66
67 /* READ0 */
68 NAND_CLEAR_RB;
69 NFCMD = 0;
70
71 /* Write Address */
72 NFADDR = i & 0xff;
73 NFADDR = (i >> 9) & 0xff;
74 NFADDR = (i >> 17) & 0xff;
75 NFADDR = (i >> 25) & 0xff;
76
77 /*is nand flash ready ?*/
78 NAND_DETECT_RB;
79
80 /*ready a page data into buf*/
81 for(j=0; j < NAND_SECTOR_SIZE; j++, i++) {
82 *buf = (NFDATA & 0xff);
83 buf++;
84 }
85 }
86 NAND_CHIP_DISABLE;
87 return 0;
88 }
89 #endif
完了顺便修改board/s3c2440/Makefile 文件,增加nand_read.o
28 COBJS := s3c2440.o nand_read.o flash.o
步骤4:修改开发板对应的配置文件include/configs/s3c2440.h
为了支持nand命令,支持网络和ping命令,在CONFIG_COMMANDS 中增加几项
78 #define CONFIG_COMMANDS /
79 (CONFIG_CMD_DFL | /
80 CFG_CMD_CACHE | /
81 CFG_CMD_NAND | / /*支持nand命令*/
82 CFG_CMD_NET | / /*支持网络*/
83 CFG_CMD_ENV | / /*环境变量*/
84 /*CFG_CMD_EEPROM |*/ /
85 /*CFG_CMD_I2C |*/ /
86 /*CFG_CMD_USB |*/ /
87 CFG_CMD_PING | / /*ping 命令*/
88 CFG_CMD_REGINFO | /
89 CFG_CMD_DATE | /
90 CFG_CMD_ELF)
去掉 网卡物理地址的注释
94 /*#define CONFIG_ETHADDR 08:00:3e:26:0a:5b */
#define CONFIG_ETHADDR 08:00:3e:26:0a:5b
增加nand 相关的一些宏
95 #define CFG_NAND_BASE 0x4e000000
96 #define CFG_MAX_NAND_DEVICE 1
97 #define NAND_MAX_CHIPS 1
98
99 #define CONFIG_SETUP_MEMORY_TAGS 1
100 #define CONFIG_CMDLINE_TAG 1
注释掉
191 //#define CFG_ENV_IS_IN_FLASH 1
添加 nand
192 #define CFG_ENV_IS_IN_NAND 1
194 #define CFG_ENV_OFFSET 0x30000 /*u-boot.bin space */
195 #define CFG_ENV_SIZE 0x10000 /* Total Size of Environment Sector
/*定义堆栈的基址和大小*/
201 #define STACK_BASE 0x33f00000
202 #define STACK_SIZE 0x8000
203 /*define UBoot_RAM_BASE 0x33f00000*/
204 #define NAND_CTL_BASE 0x4e000000 /*nand 控制寄存器的基址*/
205 #define bINT_CTL(Nb) __REG(INT_CTL_BASE + (Nb) )
206
207
208 #if defined(CONFIG_s3c2440)
209 #define CONFIG_s3c2440_NAND_BOOT 1 /*定义从nand flash 启动*/
210
211 #define oNFCONF 0x00
212 #define oNFCONT 0x04
213 #define oNFCMD 0x08
214 #define oNFADDR 0x0c
215 #define oNFDATA 0x10
216 #define oNFSTAT 0x20
217 #define oNFECC 0x2c
218 #define rNFCONF (*(volatile unsigned int *)0x4e000000)
219 #define rNFCONT (*(volatile unsigned int *)0x4e000004)
220 #define rNFCMD (*(volatile unsigned char*)0x4e000008)
221 #define rNFADDR (*(volatile unsigned char*)0x4e00000c)
222 #define rNFDATA (*(volatile unsigned char*)0x4e000010)
223 #define rNFSTAT (*(volatile unsigned int *)0x4e000020)
224 #define rNFECC (*(volatile unsigned int *)0x4e00002c)
225
226 /*GPIO*/
227 #define GPIO_CTL_BASE 0x56000000
228 #define oGPIO_F 0x50 /*FOR LED*/
229 #define oGPIO_CON 0x0
230 #define oGPIO_DAT 0x4
231 #define oGPIO_UP 0x8
232
233 #endif
步骤5:修改 board/s3c2440/lowlevel_init.S
参照 s3c2440A的数据手册修改以下参数
123 #define Trp 0x0 /* 2clk */
124 #define Trc 0x1 /* 5clk */
125 #define Tchr 0x2 /* 3clk */
126 #define REFCNT 0x4f4 /*preiod=7.8125us, HCLK = 100 MHz ( 2048+1-7.8125*100) */
步骤6:修改board/s3c2440/s3c2440.c中的 GPIO 和PLL设置
33 #define CLKDIV 0x05 /*FCLK:HCLK:PCLK= 1:4:8*/
34
35 #define FCLK_SPEED 1
36
37 #if FCLK_SPEED==1 /* Fout = 405MHz, Fin = 12MHz for Audio */
38 #define M_MDIV 0x7f
39 #define M_PDIV 0x2
40 #define M_SDIV 0x1
41 #elif FCLK_SPEED==0 /* Fout = 202.8MHz */
42 #define M_MDIV 0xA1
43 #define M_PDIV 0x3
44 #define M_SDIV 0x1
45 #endif
47 #define USB_CLOCK 1
48
49 #if USB_CLOCK==0
50 #define U_M_MDIV 0xA1
51 #define U_M_PDIV 0x3
52 #define U_M_SDIV 0x1
53 #elif USB_CLOCK==1
54 #define U_M_MDIV 0x38
55 #define U_M_PDIV 0x2
56 #define U_M_SDIV 0x2
57 #endif
接下来修改board_init函数,填充数据机构
70 int board_init (void)
71 {
72 S3C24X0_CLOCK_POWER * const clk_power = S3C24X0_GetBase_CLOCK_POWER ();
73 S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
74
75 clk_power->CLKDIVN=CLKDIV; /*分频比*/
76
77 /* to reduce PLL lock time, adjust the LOCKTIME register */
78 clk_power->LOCKTIME = 0xFFFFFFFF; /*锁定时间*/
79
80 /* configure MPLL */
81 clk_power->MPLLCON = ((M_MDIV << 12) + (M_PDIV << 4) + M_SDIV);
82
83 /* some delay between MPLL and UPLL */
84 delay (4000);
85
86 /* configure UPLL */
87 clk_power->UPLLCON = ((U_M_MDIV << 12) + (U_M_PDIV << 4) + U_M_SDIV );
88
89 /* some delay between MPLL and UPLL */
90 delay (8000);
91
92 /* set up the I/O ports */
93
94 /*for led */
95 gpio->GPFCON = 0x5500; /*添加LED*/
96
97 gpio->GPACON = 0x007FFFFF;
98 gpio->GPBCON = 0x00044555;
99 gpio->GPBUP = 0x000007FF;
100 gpio->GPCCON = 0xAAAAAAAA;
101 gpio->GPCUP = 0x0000FFFF;
102 gpio->GPDCON = 0xAAAAAAAA;
103 gpio->GPDUP = 0x0000FFFF;
104 gpio->GPECON = 0xAAAAAAAA;
105 gpio->GPEUP = 0x0000FFFF;
106 gpio->GPFCON = 0x000055AA;
107 gpio->GPFUP = 0x000000FF;
108 gpio->GPGCON = 0xFF95FFBA;
109 gpio->GPGUP = 0x0000FFFF;
110 gpio->GPHCON = 0x002AFAAA;
111 gpio->GPHUP = 0x000007FF;
112
113 /* arch number of s3c2440-Board */
114 gd->bd->bi_arch_number = MACH_TYPE_S3C2440; /*指明机器类型*/
115
116 /* adress of boot parameters */
117 gd->bd->bi_boot_params = 0x30000100;
118
119 icache_enable();
120 dcache_enable();
121
122 gpio->GPFDAT = 0xbf; /*该阶段完成后点亮LED3*/
123
124 return 0;
125 }
步骤7:在include/common.h中加入s3c2440的配置,使2410的代码能够编译进来。
449 #if defined(CONFIG_S3C2400) || defined(CONFIG_S3C2410) || defined(CONFIG_L H7A40X) || defined(CONFIG_s3c2440)
450 ulong get_FCLK (void);
451 ulong get_HCLK (void);
452 ulong get_PCLK (void);
453 ulong get_UCLK (void);
454 #endif
步骤8:修改获取系统时钟的函数,在文件cpu/arm920t/s3c24x0/speed.c中定义
先添加预编译指令
33 #if defined(CONFIG_S3C2400) || defined (CONFIG_S3C2410) || defined (CONFIG_TRAB)|| defined(CONFI G_s3c2440)
37 #elif defined(CONFIG_S3C2410)|| defined(CONFIG_s3c2440)
38 #include
39 #endif
再定义一些宏
44 DECLARE_GLOBAL_DATA_PTR;
45
46 #define CLK_PDIVN (1<<0)
47 #define CLK_HDIVN_MASK (3<<1)
48 #define CLK_HDIVN_1 (0<<1)
49 #define CLK_HDIVN_2 (1<<1)
50 #define CLK_HDIVN_4_8 (2<<1)
51 #define CLK_HDIVN_3_6 (3<<1)
52 #define CLK_UCLK (1<<3)
53
54 #define CAMDIVN_CAMCLK_MASK (0xf<<0)
55 #define CAMDIVN_CAMCLK_SEL (1<<4)
56 #define CAMDIVN_HCLK3_HALF (1<<8)
57 #define CAMDIVN_HCLK4_HALF (1<<9)
58 #define CAMDIVN_DVS_EN (1<<12)
根据 s3c2440数据手册,分别修改get_PLLCLK(),get_HCLK()和get_PCLK()函数
70 static ulong get_PLLCLK(int pllreg)
71 {
72 S3C24X0_CLOCK_POWER * const clk_power = S3C24X0_GetBase_CLOCK_POWER();
73 ulong r, m, p, s;
74
75 if (pllreg == MPLL)
76 r = clk_power->MPLLCON;
77 else if (pllreg == UPLL)
78 r = clk_power->UPLLCON;
79 else
80 hang();
81
82 m = ((r & 0xFF000) >> 12) + 8;
83 p = ((r & 0x003F0) >> 4) + 2;
84 s = r & 0x3;
85
86 if(gd->bd->bi_arch_number == MACH_TYPE_S3C2440)
87 return((CONFIG_SYS_CLK_FREQ * m * 2) / (p << s));
88 }
97 ulong get_HCLK(void)
98 {
99 S3C24X0_CLOCK_POWER * const clk_power = S3C24X0_GetBase_CLOCK_POWER();
100
101 unsigned long clkdiv;
102 unsigned long camdiv;
103 int hdiv = 1;
104
105 if(gd->bd->bi_arch_number == MACH_TYPE_S3C2440) {
106
107 clkdiv = clk_power->CLKDIVN;
108 camdiv = clk_power->CAMDIVN;
109
110 switch (clkdiv & CLK_HDIVN_MASK) {
111
112 case CLK_HDIVN_1:
113 hdiv = 1;
114 break;
115 case CLK_HDIVN_2:
116 hdiv = 2;
117 break;
118 case CLK_HDIVN_4_8:
119 hdiv = (camdiv & CAMDIVN_HCLK4_HALF)?8:4;
120 break;
121 case CLK_HDIVN_3_6:
122 hdiv = (camdiv & CAMDIVN_HCLK3_HALF)?6:3;
123 break;
124 }
125
126 return get_FCLK() / hdiv;
127 }
128
129 }
134 /* return PCLK frequency */
135 ulong get_PCLK(void)
136 {
137 S3C24X0_CLOCK_POWER * const clk_power = S3C24X0_GetBase_CLOCK_POWER();
138
139 unsigned long clkdiv;
140 unsigned long camdiv;
141 int hdiv = 1;
142
143 if(gd->bd->bi_arch_number == MACH_TYPE_S3C2440) {
144
145 clkdiv = clk_power->CLKDIVN;
146 camdiv = clk_power->CAMDIVN;
147
148 switch (clkdiv & CLK_HDIVN_MASK) {
149
150 case CLK_HDIVN_1:
151 hdiv = 1;
152 break;
153 case CLK_HDIVN_2:
154 hdiv = 2;
155 break;
156 case CLK_HDIVN_4_8:
157 hdiv = (camdiv & CAMDIVN_HCLK4_HALF)?8:4;
158 break;
159 case CLK_HDIVN_3_6:
160 hdiv = (camdiv & CAMDIVN_HCLK3_HALF)?6:3;
161 break;
162 }
163
164 return get_FCLK() / hdiv / ((clkdiv & CLK_PDIVN)?2:1);
165
166 }
167
168 }
步骤9:修改include/s3c24x0.h文件,增加S3C2440_NAND数据结构,添加nand 初始化函数,让u-boot支持nand擦写。
170 typedef struct {
171 S3C24X0_REG32 NFCONF;
172 S3C24X0_REG32 NFCONT;
173 S3C24X0_REG32 NFCMD;
174 S3C24X0_REG32 NFADDR;
175 S3C24X0_REG32 NFDATA;
176 S3C24X0_REG32 NFMECCD0;
177 S3C24X0_REG32 NFMECCD1;
178 S3C24X0_REG32 NFSECCD;
179 S3C24X0_REG32 NFSTAT;
180 S3C24X0_REG32 NFESTAT0;
181 S3C24X0_REG32 NFESTAT1;
182 S3C24X0_REG32 NFMECC0;
183 S3C24X0_REG32 NFMECC1;
184 S3C24X0_REG32 NFSECC;
185 S3C24X0_REG32 NFSBLK;
186 S3C24X0_REG32 NFEBLK;
187 } /*__attribute__((__packed__))*/ s3c2440_NAND;
再在include/s3c2410.h中仿照s3C2410_GetBase_NAND定义s3C2440_GetBase_NAND.
100 /*for s3c2440 */
101 static inline s3c2440_NAND * const s3c2440_GetBase_NAND(void)
102 {
103 return (s3c2440_NAND * const)S3C2410_NAND_BASE;
104 }
采用u-boot中的新的那套nand 支持,手动编写s3c2440 nand的初始化函数,在cpu/arm920t/s3c24x0/nand_flash.c中进行实现
1 #include
2
3 #if(CONFIG_COMMANDS & CFG_CMD_NAND) && !defined(CFG_NAND_LEGACY)
4 #include
5 #include
6
7 DECLARE_GLOBAL_DATA_PTR;
8
9 #define s3c2440_NFSTAT_READY (1<<0)
10 #define s3c2440_NFCONT_nFCE (1<<1)
11
12 /*chip select */
13 static void s3c2440_nand_select_chip(struct mtd_info *mtd,int chip) {
14
15 s3c2440_NAND *const s3c2440_nand = s3c2440_GetBase_NAND();
16
17 if(chip == -1) {
18 s3c2440_nand->NFCONT |=s3c2440_NFCONT_nFCE;
19 }
20 else {
21 s3c2440_nand->NFCONT &=~s3c2440_NFCONT_nFCE;
22 }
23 }
24
25 /*command and control */
26 static void s3c2440_nand_hwcontrol(struct mtd_info *mtd,int cmd) {
27
28 s3c2440_NAND *const s3c2440_nand = s3c2440_GetBase_NAND();
29 struct nand_chip *chip = mtd->priv;
30
31 switch (cmd) {
32
33 case NAND_CTL_SETNCE:
34 case NAND_CTL_CLRNCE:
35 printf("%s:called for NCE/n",__FUNCTION__);
36 break;
37 case NAND_CTL_SETCLE:
38 chip->IO_ADDR_W = (void *) &s3c2440_nand->NFCMD;
39 break;
40 case NAND_CTL_SETALE:
41 chip->IO_ADDR_W = (void *) &s3c2440_nand->NFADDR;
42 break;
43 /*NAND_CTL_CLRCLE*/
44 /*NAND_CTL_CLRALE*/
45
46 default:
47 chip->IO_ADDR_W = (void *) &s3c2440_nand->NFDATA;
48 break;
49 }
50 }
51
52 /*inspect NAND status : 0 busy,1 free*/
53 static int s3c2440_nand_devready(struct mtd_info *mtd) {
54
55 s3c2440_NAND * const s3c2440_nand = s3c2440_GetBase_NAND();
56
57 return (s3c2440_nand->NFSTAT & s3c2440_NFSTAT_READY);
58 59
60 /*set NAND time seq */
61 static void s3c24x0_nand_inithw(void) {
62
63 s3c2440_NAND *const s3c2440_nand = s3c2440_GetBase_NAND();
64
65 #define TACLS 0
66 #define TWRPH0 4
67 #define TWRPH1 2
68
69 if (gd->bd->bi_arch_number == MACH_TYPE_S3C2440) {
70
71 s3c2440_nand->NFCONF = (TACLS << 12) | (TWRPH0 << 8) | (TWRPH1 << 4);
72 s3c2440_nand->NFCONT = (1<< 4) | (0<<1) | (1<<0);
73 }
74 }
75
76 /*invoke by drivers/nand/nand.c,initialize nand hardware */
77 void board_nand_init(struct nand_chip *chip) {
78
79 s3c2440_NAND *const s3c2440_nand = s3c2440_GetBase_NAND();
80 s3c24x0_nand_inithw();
81
82 if (gd->bd->bi_arch_number == MACH_TYPE_S3C2440) {
83
84 chip->IO_ADDR_R = (void *)&s3c2440_nand->NFDATA;
85 chip->IO_ADDR_W = (void *)&s3c2440_nand->NFDATA;
86 chip->hwcontrol = s3c2440_nand_hwcontrol;
}
87 chip->dev_ready = s3c2440_nand_devready;
88 chip->select_chip = s3c2440_nand_select_chip;
89 chip->options = 0;
90 }
91 chip->eccmode = NAND_ECC_SOFT;
92 }
93 #endif
最后修改 cpu/arm920t/s3c24x0/Makefile 文件,增加 新建的nand_flash.c
28 COBJS = i2c.o interrupts.o serial.o speed.o /
29 usb_ohci.o nand_flash.o
至此,u-boot 已经可以支持nand 擦写了。
步骤10:增加yaffs文件烧写。
在nand 命令处理函数do_nand中增加write.yaffs 的支持。修改common/cmd_nand.c 文件:
在354行以后增加如下的代码
354 } else if( s !=NULL && !strcmp(s,".yaffs")){ /*add ysffs */
355 if (read) { /*read*/
356
357 nand_read_options_t opts;
358 memset(&opts,0,sizeof(opts));
359 opts.buffer = (u_char *)addr;
360 opts.length = size;
361 opts.offset = off;
362 opts.readoob = 1;
363 opts.quiet = quiet;
364 ret = nand_read_opts(nand,&opts);
365 }
366 else{ /*write*/
367
368 nand_write_options_t opts;
369 memset(&opts,0,sizeof(opts));
370 opts.buffer = (u_char *)addr;
371 opts.length = size;
372 opts.offset = off;
373 /* opts.forceyaffs = 1; */
374 opts.noecc = 1;
375
376 opts.writeoob = 1;
377 opts.blockalign = 1;
378 opts.quiet = quiet;
379 opts.skipfirstblk = 1;
380 ret = nand_write_opts(nand,&opts);
381 }
382 }
再在U-BOOT_CMD中增加 nand write.yaffs 的使用说明
487 U_BOOT_CMD(nand, 5, 1, do_nand,
488 "nand - NAND sub-system/n",
489 "info - show available NAND devices/n"
490 "nand device [dev] - show or set current device/n"
491 "nand read[.jffs2] - addr off|partition size/n"
492 "nand write[.jffs2] - addr off|partiton size - read/write `size' bytes starting/n"
493 " at offset `off' to/from memory address `addr'/n"
494 "nand write[.yaffs] - addr off|partiton size - read/write 'size' bytes starting/n"
495 " at offset 'off' to/from memory address 'addr'/n"
496 "nand erase [clean] [off size] - erase `size' bytes from/n"
497 " offset `off' (entire device if not specified)/n"
498 "nand bad - show bad blocks/n"
499 "nand dump[.oob] off - dump page/n"
500 "nand scrub - really clean NAND erasing bad blocks (UNSAFE)/n"
501 "nand markbad off - mark bad block at offset (UNSAFE)/n"
502 "nand biterr off - make a bit error at offset (UNSAFE)/n"
503 "nand lock [tight] [status] - bring nand to lock state or display locked pages/n"
504 "nand unlock [offset] [size] - unlock section/n");
修改include/nand.h,增加skipfirstblk成员。
68 struct nand_write_options {
69 u_char *buffer; /* memory block containing image to write */
70 ulong length; /* number of bytes to write */
71 ulong offset; /* start address in NAND */
72 int quiet; /* don't display progress messages */
73 int autoplace; /* if true use auto oob layout */
74 int forcejffs2; /* force jffs2 oob layout */
75 int forceyaffs; /* force yaffs oob layout */
76 int noecc; /* write without ecc */
77 int writeoob; /* image contains oob data */
78 int pad; /* pad to page size */
79 int blockalign; /* 1|2|4 set multiple of eraseblocks
80 * to align to */
81 int skipfirstblk; /*skip the first block*/
82 };
最后修改nand_write_opts函数,增加对skipfirstblk成员的支持,它在drivers/nand/nand_util.c文件中
在
430 /* skip the first block when write yaffs images */
431
432 if(skipfirstblk) {
433 mtdoffset +=erasesize_blockalign;
434 skipfirstblk = 0;
435 continue;
436 }
为了防止烧写 yaffs 系统时,打印出ECC校验警告,将dirvers/nand/nand_base.c中的nand_write_page函数中打印警告
的语句注释掉
911 /* printk (KERN_WARNING "Writing data without ECC to NAND-FLASH is not recommended /n"); */
总结:以上步骤肯定有错误和不足之处,希望网友发现后能给我指出来。在移植时我参考了很多牛人的博客,虽然有点粗糙,但是还可以用了。至于NOR flash部分,由于我还不知道怎么进行移植,等以后弄明白了再贴上来。