移植 u-boot 1.1.6 到 S3C2440 (nand 启动)

2019-07-13 02:52发布

     移植参考了韦东山编写的《嵌入式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部分,由于我还不知道怎么进行移植,等以后弄明白了再贴上来。