U-BOOT-1.1.6移植分享之实现nand自启动

来源:互联网 发布:数字新闻 数据新闻 编辑:程序博客网 时间:2024/04/30 11:02

背景:当初在移植u-boot时,在nand启动那里卡死了好久。由于我的ARM9开发板为mini2440,nandflash的芯片容量为256MB,与网上参考的文章nand容量不同,所以必须对源代码进行修改。当初偶尔看到这篇文章,照着步骤一步一步做下去,成功实现了nand启动,现在贴出来,希望能帮到有需要的人。

 

移植过程并非那么顺利,但是坚持下去,一切都会明朗
--------------------------------step1-----------------------------------

1
smdk2440建立编译项
 
打开uboot根目录下的Makefile,添加以下项
  root@shi:/home/shi/work_linux/uboot/u-boot-1.1.6/gedit Makefile
  smdk2440_config :       unconfig
        @$(MKCONFIG) $(@:_config=) arm arm920t smdk2440 NULL s3c24x0
   
说明:    
    arm: CPU
的架构(ARCH)
    arm920t: CPU
的类型(CPU),其对应于cpu/arm920t子目录
    smdk2440: 开发
板的型号(BOARD),对应于board/smdk2440/目录
    NULL:
开发者/或经销商(vender)
    s3c24x0:
片上系统(SOC)
2
设置交叉编译环境变量
    ifeq ($(ARCH),arm)
        CROSS_COMPILE =/usr/local/arm/3.3.2/bin/arm-linux-
    endif
3
/board子目录中建立自己的开发板smdk2440目录 并复制smdk2410目录下的所有文件到smdk2440目录
root@shi:/home/shi/work_linux/uboot/u-boot-1.1.6/board# mkdir smdk2440
root@shi:/home/shi/work_linux/uboot/u-boot-1.1.6/board# cp -arf smdk2410/* smdk2440
root@shi:/home/shi/work_linux/uboot/u-boot-1.1.6/board# cd smdk2440
root@shi:/home/shi/work_linux/uboot/u-boot-1.1.6/board/smdk2440# ls
config.mk  flash.c  lowlevel_init.S  Makefile  smdk2410.c  u-boot.lds
 
smdk2410.c替换成smdk2440.c
root@shi:/home/shi/work_linux/uboot/u-boot-1.1.6/board/smdk2440# mv smdk2410.c smdk2440.c
root@shi:/home/shi/work_linux/uboot/u-boot-1.1.6/board/smdk2440# ls
config.mk  flash.c  lowlevel_init.S  Makefile  smdk2440.c  u-boot.lds
root@shi:/home/shi/work_linux/uboot/u-boot-1.1.6/board/smdk2440#
 
修改该目录下的Makefile文件,加入smdk2440.c的编译项
COBJS    := smdk2440.o flash.o
4
include/configs/中建立配置头文件
root@shi:/home/shi/work_linux/uboot/u-boot-1.1.6/include/configs# cp smdk2410.h smdk2440.h
测试编译是否成功
硬件浮点和软件浮点的问题
如果编译环境和u-boot的版本搭配不合适的话会出现以下错误:
arm-linux-ld: ERROR: /usr/local/arm/3.3.2/lib/gcc-lib/arm-linux/3.3.2/libgcc.a(_udivdi3.oS) uses hardware FP, whereas u-boot uses software FP
文件格式无法识别: failed to merge target specific data of file /usr/local/arm/3.3.2/lib/gcc-lib/arm-linux/3.3.2/libgcc.a(_udivdi3.oS)
arm-linux-ld: ERROR: /usr/local/arm/3.3.2/lib/gcc-lib/arm-linux/3.3.2/libgcc.a(_clz.oS) uses hardware FP, whereas u-boot uses software FP
文件格式无法识别: failed to merge target specific data of file /usr/local/arm/3.3.2/lib/gcc-lib/arm-linux/3.3.2/libgcc.a(_clz.oS)
make: *** [u-boot]
错误 1
原因是u-boot使用的是软浮点,而交叉编译arm-linux-gcc是硬件浮点。

解决办法:去掉"cpu/arm920t/config.mk"文件中的 -msoft-float
root@shi:/home/shi/work_linux/uboot/u-boot-1.1.6# make smdk2440_config
Configuring for smdk2440 board...
root@shi:/home/shi/work_linux/uboot/u-boot-1.1.6# make
完成之后,如果没有错误会在该目录下生成 u-boot u-boot.srec  u-boot u-boot.bin
如果希望生成u-boot的反汇编文件,那么在根目录下打开Makefileh查找u-boot.bin
239ALL = $(obj)u-boot.srec $(obj)u-boot.bin $(obj)System.map $(U_BOOT_NAND)
修改为: ALL = $(obj)u-boot.srec $(obj)u-boot.bin $(obj)u-boot.dis $(obj)System.map $(U_BOOT_NAND)
-------------------------------step2---------------------------------------
5
清除编译生成的文件
root@shi:/home/shi/work_linux/uboot/u-boot-1.1.6# make distclean
6
修改/cpu/arm920t/start.S
 
找到程序的入口点,reset:
    /*
     * set the cpu to SVC32 mode
     */
    mrs    r0,cpsr
    bic    r0,r0,#0x1f
    orr    r0,r0,#0xd3
    msr    cpsr,r0
 
在下面添加开发板的LED测试代码,以方便观看u-boot的运行
//
测试开发板的LED
#if 1  
//LED
分别由S3C2440PB5678口来控制
#define GPBCON 0x56000010
#define GPBDAT 0x56000014
#define GPBUP  0x56000018    
  //
以下对寄存器的操作参照S3C2440DataSheet进行操作
    ldr r0, =GPBUP
    ldr r1, =0x7FF    //
即:二进制11111111111,关闭PB口上拉
    str r1, [r0]
    ldr r0, =GPBCON   //
配置PB5678为输出口,对应PBCON寄存器的第10-17
    ldr r1, =0x154FD  //
即:二进制010101010011111101
    str r1, [r0]
    ldr r0, =GPBDAT
    ldr r1, =0x1C0    //
即:二进制111000000PB5设为低电平,678为高电平
    str r1, [r0]      //
点亮开发板上的LED1
#endif
接下来要关闭看门狗、初始化系统时钟
代码修改如下:
#if defined(CONFIG_S3C2400) || defined(CONFIG_S3C2410) || defined(CONFIG_S3C2440)
#if defined(CONFIG_S3C2400)
# define pWTCON        0x15300000
# define INTMSK        0x14400008    /* Interupt-Controller base addresses */
# define CLKDIVN    0x14800014    /* clock divisor register */
#else
# define pWTCON        0x53000000
# define INTMSK        0x4A000008    /* Interupt-Controller base addresses */
# define INTSUBMSK    0x4A00001C
# define CLKDIVN    0x4C000014    /* clock divisor register */
#endif
#define CLK_CTL_BASE 0x4C000000
#define MDIV_405 0x7f << 12
#define PSDIV_405 0x21
#define UPLL_MDIV_48 0x38 << 12
#define UPLL_PSDIV_48 0x22
#define MDIV_200 0xa1 << 12
#define PSDIV_200 0x31
    ldr     r0, =pWTCON
    str     r1, [r0]
    /*mask all IRQs by setting all bits in the INTMR – default*/
    mov    r1, #0xffffffff
    str    r1, [r0]
# if defined(CONFIG_S3C2410)
    ldr    r1, =0x7ff
    ldr    r0, =INTSUBMSK
    str    r1, [r0]
# endif
#if defined(CONFIG_S3C2440)
    ldr r1, =0x7fff                 /*
根据2440芯片手册,INTSUBMSK15位可用*/
    ldr r0, =INTSUBMSK
    str r1, [r0]
#endif
#if defined(CONFIG_S3C2440)
    /* FCLK:HCLK:PCLK = 1:4:8 */
    ldr r0, =CLKDIVN
    mov r1, #5
    str r1, [r0]
    
    mrc p15, 0, r1, c1, c0, 0 /*read ctrl register */
    orr r1, r1, #0xc0000000 /*Asynchronous */
    mcr p15, 0, r1, c1, c0, 0 /*write ctrl register */
    /*now, CPU clock is 405.00 Mhz */
    mov r1, #CLK_CTL_BASE
    mov r2, #UPLL_MDIV_48    /*UPLL */
    add r2, r2, #UPLL_PSDIV_48
    str r2, [r1, #0x08]  /*write UPLL first,48MHz */
    mov r2, #MDIV_405 /* mpll_405mhz */
    add r2, r2, #PSDIV_405 /* mpll_405mhz h*/
    str r2, [r1, #0x04] /* MPLLCON hugerat */
#else
    /* FCLK:HCLK:PCLK = 1:2:4 */
    /* default FCLK is 120 MHz ! */
    ldr    r0, =CLKDIVN
    mov    r1, #3
    str    r1, [r0]

   
    mrc    p15, 0, r1, c1, c0, 0   
    orr    r1, r1, #0xc0000000   
    mcr    p15, 0, r1, c1, c0, 0    /*write ctrl register */
   
   
    mov    r1, #CLK_CTL_BASE   
    mov    r2, #MDIV_200   
    add    r2, r2, #PSDIV_200   
    str    r2, [r1, #0x04]
#endif   
#endif    /*CONFIG_S3C2400 || CONFIG_S3C2410 || CONFIG_S3C2440*/
-----------------------------------------------------------------
接下来为了观看u-boot的运行,添加一段LED的程序,此时点亮LED2,关闭其它LED
   //
点亮LED2
    ldr r0, =GPBDAT
    ldr r1, =0x1A0    //
即:二进制110100000PB6设为低电平,578为高电平
    str r1, [r0]      ////
点亮开发板上的LED2
8
时钟部分还需要在board/smdk2440/smdk2440.c中和cpu/arm920t/s3c24x0/speed.c中修改
 
首先 smdk2440.c中作如下修改
#define FCLK_SPEED 1
#if FCLK_SPEED==0        /* Fout = 203MHz, Fin = 12MHz for Audio */
#define M_MDIV    0xC3
#define M_PDIV    0x4
#define M_SDIV    0x1
#elif FCLK_SPEED==1        /* Fout = 202.8MHz */
#if defined(CONFIG_S3C2410)
/* Fout = 202.8MHz */
#define M_MDIV    0xA1
#define M_PDIV    0x3
#define M_SDIV    0x1
#endif
#if defined(CONFIG_S3C2440)
/* Fout = 405MHz */
#define M_MDIV 0x7f       
#define M_PDIV 0x2
#define M_SDIV 0x1
#endif
/*#define M_MDIV    0xA1
#define M_PDIV    0x3
#define M_SDIV    0x1*/
/*------------------------*/
#endif
#define USB_CLOCK 1
#if USB_CLOCK==0
#define U_M_MDIV    0xA1
#define U_M_PDIV    0x3
#define U_M_SDIV    0x1
#elif USB_CLOCK==1
#if defined(CONFIG_S3C2410)
#define U_M_MDIV    0x48
#define U_M_PDIV    0x3
#endif
#if defined(CONFIG_S3C2440)
#define U_M_MDIV 0x38
#define U_M_PDIV 0x2
#endif
/*#define U_M_MDIV    0x48
#define U_M_PDIV    0x3*/
#define U_M_SDIV    0x2
#endif
speed.c中作如下更改

static ulong get_PLLCLK(int pllreg)
{
    S3C24X0_CLOCK_POWER * const clk_power = S3C24X0_GetBase_CLOCK_POWER();
    ulong r, m, p, s;

    if (pllreg == MPLL)
    r = clk_power->MPLLCON;
    else if (pllreg == UPLL)
    r = clk_power->UPLLCON;
    else
    hang();

    m = ((r & 0xFF000) >> 12) + 8;
    p = ((r & 0x003F0) >> 4) + 2;
    s = r & 0x3;
#if defined(CONFIG_S3C2440) //
依据手册
    if (pllreg == MPLL)
     return((CONFIG_SYS_CLK_FREQ * m * 2) / (p << s));
    else if (pllreg == UPLL)
#endif
    return((CONFIG_SYS_CLK_FREQ * m) / (p << s));
}
并修改
ulong get_HCLK(void)
{
    S3C24X0_CLOCK_POWER * const clk_power = S3C24X0_GetBase_CLOCK_POWER();
#if defined(CONFIG_S3C2440)//
依据手册
    if (clk_power->CLKDIVN & 0x6)
                {
                if ((clk_power->CLKDIVN & 0x6)==2) return(get_FCLK()/2);
                if ((clk_power->CLKDIVN & 0x6)==6) return((clk_power->CAMDIVN & 0x100) ? get_FCLK()/6 : get_FCLK()/3);
                if ((clk_power->CLKDIVN & 0x6)==4) return((clk_power->CAMDIVN & 0x200) ? get_FCLK()/8 : get_FCLK()/4);
                return(get_FCLK());
                }
    else    return(get_FCLK());
#else
    return((clk_power->CLKDIVN & 0x2) ? get_FCLK()/2 : get_FCLK());
#endif
}

-------------------------------------------------
编译,保证无错误再往下进行
------------------------------------------------
9
还是回到start.S
#ifndef CONFIG_SKIP_LOWLEVEL_INIT
    bl    cpu_init_crit
#endif
以上代码使程序跳转到cpu_init_critcpu_init_crit中程序还要跳转到
lowlevel_init
执行,该函数在board/smdk2440/lowlevel_init.S中,用于对SDRAM的初始化,在该文件中需要修改SDRAM的刷新参数
#define B1_BWSCON          (DW16)
#define B3_BWSCON          (DW16)
#define B4_BWSCON        (DW16 + WAIT + UBLB)
#define B3_Tcos                0x0
#define B3_Tcoh             0x0
#define B3_Tacp             0x0
#define B4_Tcos             0x3
#define B4_Tcoh             0x1
#define B4_Tah             0x3
#define B4_Tacp             0x3
#define B6_Trcd              0x2
#define B7_Trcd             0x2
#define REFCNT             1259
SDRAM
初始化完成后再加一段LED测试的程序,以方便观察u-boot的运行打开start.S
#ifndef CONFIG_SKIP_LOWLEVEL_INIT
    bl    cpu_init_crit
  #endif
后面加:
//
点亮LED3
    ldr r0, =GPBDAT
    ldr r1, =0x160    //
即:二进制101100000PB7设为低电平,568为高电平
    str r1, [r0]      ////
点亮开发板上的LED3
10
继续,加入NANDFLASH启动代码
需要屏蔽掉以下代码搬移部分
#if 0
#ifndef CONFIG_SKIP_RELOCATE_UBOOT
relocate:                /* relocate U-Boot to RAM        */
    adr    r0, _start        /* r0 <- current position of code   */
    ldr    r1, _TEXT_BASE        /* test if we run from flash or RAM */
    cmp     r0, r1                  /* don't reloc during debug         */
    beq     stack_setup

    ldr    r2, _armboot_start
    ldr    r3, _bss_start
    sub    r2, r3, r2        /* r2 <- size of armboot            */
    add    r2, r0, r2        /* r2 <- source end address         */

copy_loop:
    ldmia    r0!, {r3-r10}        /* copy from source address [r0]    */
    stmia    r1!, {r3-r10}        /* copy to   target address [r1]    */
    cmp    r0, r2            /* until source end addreee [r2]    */
    ble    copy_loop
#endif    /* CONFIG_SKIP_RELOCATE_UBOOT */
#endif
添加以下代码:
/***************** NAND_BOOT *************************************************/
#define LENGTH_UBOOT  0x40000
#define NAND_CTL_BASE 0x4E000000

#ifdef CONFIG_S3C2440
/* Offset */
#define oNFCONF 0x00
#define oNFCONT 0x04
#define oNFCMD  0x08
#define oNFSTAT 0x20

    @ reset NAND
    mov    r1, #NAND_CTL_BASE
    ldr    r2, =( (7<<12)|(7<<8)|(7<<4)|(0<<0) )
    str    r2, [r1, #oNFCONF]
    ldr    r2, [r1, #oNFCONF]
   
    ldr    r2, =( (1<<4)|(0<<1)|(1<<0) )    @ Active low CE Control
    str    r2, [r1, #oNFCONT]
    ldr    r2, [r1, #oNFCONT]
   
    ldr    r2, =(0x6)                @ RnB Clear
    str    r2, [r1, #oNFSTAT]
    ldr    r2, [r1, #oNFSTAT]
   
    mov    r2, #0xff                @ RESET command
    strb    r2, [r1, #oNFCMD]
   
    mov    r3, #0    @ wait
nand1:
    add    r3, r3, #0x1
    cmp    r3, #0xa
    blt    nand1

nand2:
    ldr    r2, [r1, #oNFSTAT]            @ wait ready
    tst    r2, #0x4
    beq    nand2   
   
    ldr    r2, [r1, #oNFCONT]
    orr    r2, r2, #0x2    @ Flash Memory Chip Disable
    str    r2, [r1, #oNFCONT]
   
    @ get read to call C functions (for nand_read())

    ldr    sp, DW_STACK_START            @ setup stack pointer
    mov    fp, #0                    @ no previous frame, so fp=0


/***************** NAND_FLASH_PAGE_SIZE_2K ***********************************/
nand_page_2k:
    ldr    r0, =TEXT_BASE
    mov    r1, #0x0
    mov    r2, #LENGTH_UBOOT
    bl    nand_read_ll
    tst    r0, #0x0
    beq    ok_nand_read

bad_nand_read_2k:
    mov     r0, #0x60   
    bl    test_led_on
loop2k:
    b    loop2k            @ infinite loop

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    stack_setup
    bne    go_next

notmatch:
    mov     r0, #0x20   
    bl    test_led_on
loop3:
    b    loop3    @ infinite loop
#endif
ldr    pc, _start_armboot后添加 定义堆栈地址和宽度
#define STACK_BASE 0x33f00000
#define STACK_SIZE 0x10000
_start_armboot:    .word start_armboot后面添加
.align    2
DW_STACK_START:    .word    STACK_BASE+STACK_SIZE-4
11 NANDFLASH
启动代码有了,但还没有实现里面所调用的相关 nand_read_ll操作函数,因此需要在board/smdk2440/目录下建立nand_read.c文件,以实现nand_read_ll函数
 
进入到board/smdk2440/目录下,root@shi:/home/shi/work_linux/uboot/u-boot-1.1.6/board/smdk2440# gedit nand_read.c
 
输入以下代码并保存
#include <config.h>
#define __REGb(x) (*(volatile unsigned char *)(x))
#define __REGi(x) (*(volatile unsigned int *)(x))
#define NF_BASE 0x4e000000
#define NFCONF __REGi(NF_BASE + 0x0)
#if defined(CONFIG_S3C2440)
#define NFCONT __REGi(NF_BASE + 0x4)
#define NFCMD __REGb(NF_BASE + 0x8)
#define NFADDR __REGb(NF_BASE + 0xC)
#define NFDATA __REGb(NF_BASE + 0x10)
#define NFSTAT __REGb(NF_BASE + 0x20)
#define NAND_CHIP_ENABLE (NFCONT &= ~(1<<1))
#define NAND_CHIP_DISABLE (NFCONT |= (1<<1))
#define NAND_CLEAR_RB (NFSTAT |= (1<<2))
#define NAND_DETECT_RB { while(! (NFSTAT&(1<<2)));}
#define NAND_SECTOR_SIZE_2K 2048
#define NAND_BLOCK_MASK_2K (NAND_SECTOR_SIZE_2K - 1)

/* low level nand read function */
int nand_read_ll(unsigned char *buf, unsigned long start_addr, int size)
{
    int i, j;
   
    if ((start_addr & NAND_BLOCK_MASK_2K) || (size & NAND_BLOCK_MASK_2K)) {
    return -1;    /* invalid alignment */
    }
    NAND_CHIP_ENABLE;   
    for(i=start_addr; i < (start_addr + size); i += NAND_SECTOR_SIZE_2K) {
    /* READ0 */
        NAND_CLEAR_RB;   
        NFCMD = 0;   
   
        /* Write Address */
        NFADDR = 0;
        NFADDR = 0;
        NFADDR = (i >> 11) & 0xff;
        NFADDR = (i >> 19) & 0xff;
        NFADDR = (i >> 27) & 0xff;

        NFCMD = 0x30;
        NAND_DETECT_RB;
   
        for(j=0; j < NAND_SECTOR_SIZE_2K; j++) {
            *buf = (NFDATA & 0xff);
            buf++;
            }
    }
    NAND_CHIP_DISABLE;   
    return 0;
}
#endif

并在该目录下的Makefile文件中加入nand_read.c的编译项,COBJS    := smdk2440.o flash.o nand_read.o
打开该目录下的u-boot.lds,添加以下代码,防止编译器将nand_read编译到4K之后
.text      :
    {
      cpu/arm920t/start.o    (.text)
      board/smdk2440/lowlevel_init.o (.text)
      board/smdk2440/nand_read.o  (.text)
      *(.text)
    }
12
接下来添加nandflash的有关操作支持
 
cpu/arm920t/s3c24x0中建立文件s3c2440_nand.c
 
并添加如下代码:
#include <common.h>
#if 0
#define DEBUGN    printf
#else
#define DEBUGN(x, args ...) {}
#endif
#if defined(CONFIG_CMD_NAND)

#if !defined(CONFIG_NAND_LEGACY)
#include <nand.h>
#include <s3c2410.h>
#include <asm/io.h>

#define __REGb(x)    (*(volatile unsigned char *)(x))
#define __REGi(x)    (*(volatile unsigned int *)(x))
#if defined(CONFIG_S3C2410)
#define    NF_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 NFECC0        __REGb(NF_BASE + 0x14)
#define NFECC1        __REGb(NF_BASE + 0x15)
#define NFECC2        __REGb(NF_BASE + 0x16)
#else

#if defined(CONFIG_S3C2440)
#define    NF_BASE        0x4e000000
#define    NFCONF        __REGi(NF_BASE + 0x0)
#define    NFCONT        __REGi(NF_BASE + 0x4)
#define    NFCMD        __REGb(NF_BASE + 0x8)
#define    NFADDR        __REGb(NF_BASE + 0xc)
#define    NFDATA        __REGb(NF_BASE + 0x10)
#define     NFMECCD0    __REGi(NF_BASE + 0x14)
#define     NFMECCD1    __REGi(NF_BASE + 0x18)
#define     NFSECCD    __REGi(NF_BASE + 0x1C)
#define    NFSTAT        __REGb(NF_BASE + 0x20)
#define    NFSTAT0    __REGi(NF_BASE + 0x24)
#define    NFSTAT1    __REGi(NF_BASE + 0x28)
#define    NFMECC0    __REGi(NF_BASE + 0x2C)
#define    NFMECC1    __REGi(NF_BASE + 0x30)
#define    NFSECC        __REGi(NF_BASE + 0x34)

#define    NFSBLK        __REGi(NF_BASE + 0x38)
#define    NFEBLK        __REGi(NF_BASE + 0x3c)
#define S3C2440_NFCONT_nCE    (1<<1)
#define S3C2440_ADDR_NALE 0x0c
 
#define S3C2440_ADDR_NCLE 0x08
#endif
#endif
#define S3C2410_NFCONF_EN          (1<<15)
#define S3C2410_NFCONF_512BYTE     (1<<14)
#define S3C2410_NFCONF_4STEP       (1<<13)
#define S3C2410_NFCONF_INITECC     (1<<12)
#define S3C2410_NFCONF_nFCE        (1<<11)
#define S3C2410_NFCONF_TACLS(x)    ((x)<<8)
#define S3C2410_NFCONF_TWRPH0(x)   ((x)<<4)
#define S3C2410_NFCONF_TWRPH1(x)   ((x)<<0)
#define S3C2410_ADDR_NALE 4
#define S3C2410_ADDR_NCLE 8
ulong IO_ADDR_W = NF_BASE; //by hugerat,phase3
static void s3c2410_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
{
    struct nand_chip *chip = mtd->priv;
    DEBUGN("hwcontrol(): 0x%02x 0x%02x/n", cmd, ctrl);
#if defined(CONFIG_S3C2410)

    if (ctrl & NAND_CTRL_CHANGE) {
        //ulong IO_ADDR_W = NF_BASE; by hugerat.phase3
        IO_ADDR_W = NF_BASE;
        if (!(ctrl & NAND_CLE))
            IO_ADDR_W |= S3C2410_ADDR_NCLE;
        if (!(ctrl & NAND_ALE))
            IO_ADDR_W |= S3C2410_ADDR_NALE;
        //chip->IO_ADDR_W = (void *)IO_ADDR_W; //by hugerat,phase3
        if (ctrl & NAND_NCE)
            NFCONF &= ~S3C2410_NFCONF_nFCE;
        else
            NFCONF |= S3C2410_NFCONF_nFCE;
    }
    if (cmd != NAND_CMD_NONE)
        //writeb(cmd, chip->IO_ADDR_W);
        writeb(cmd,(void *)IO_ADDR_W);
#endif
#if defined(CONFIG_S3C2440)
    if (ctrl & NAND_CTRL_CHANGE) {
        IO_ADDR_W = NF_BASE; //by hugerat,phase3
        if (!(ctrl & NAND_CLE))
            {
            IO_ADDR_W |= S3C2440_ADDR_NALE;}
        if (!(ctrl & NAND_ALE))
            {
            IO_ADDR_W |= S3C2440_ADDR_NCLE;}
        //chip->IO_ADDR_W = (void *)IO_ADDR_W;
        if (ctrl & NAND_NCE)  
            {NFCONT &= ~S3C2440_NFCONT_nCE;
            //DEBUGN("NFCONT is 0x%x ",NFCONT);
            //DEBUGN("nand Enable ");
            }
        else
            {NFCONT |= S3C2440_NFCONT_nCE; 
            //DEBUGN("nand disable ");
            }
    }
    if (cmd != NAND_CMD_NONE)
        writeb(cmd,(void *)IO_ADDR_W);
        //writeb(cmd, chip->IO_ADDR_W);
#endif
}
static int s3c2410_dev_ready(struct mtd_info *mtd)
{
    DEBUGN("dev_ready/n");
    return (NFSTAT & 0x01);
}
#ifdef CONFIG_S3C2410_NAND_HWECC
void s3c2410_nand_enable_hwecc(struct mtd_info *mtd, int mode)
{
    DEBUGN("s3c2410_nand_enable_hwecc(%p, %d)/n", mtd, mode);
    NFCONF |= S3C2410_NFCONF_INITECC;
}
static int s3c2410_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
                      u_char *ecc_code)

{
    ecc_code[0] = NFECC0;
    ecc_code[1] = NFECC1;
    ecc_code[2] = NFECC2;
    DEBUGN("s3c2410_nand_calculate_hwecc(%p,): 0x%02x 0x%02x 0x%02x/n",
        mtd , ecc_code[0], ecc_code[1], ecc_code[2]);
    return 0;
}
static int s3c2410_nand_correct_data(struct mtd_info *mtd, u_char *dat,
                     u_char *read_ecc, u_char *calc_ecc)
{
    if (read_ecc[0] == calc_ecc[0] &&
        read_ecc[1] == calc_ecc[1] &&
        read_ecc[2] == calc_ecc[2])
        return 0;
    printf("s3c2410_nand_correct_data: not implemented/n");
    return -1;
}
#endif
int board_nand_init(struct nand_chip *nand)
{
    u_int32_t cfg;
    u_int8_t tacls, twrph0, twrph1;
    S3C24X0_CLOCK_POWER * const clk_power = S3C24X0_GetBase_CLOCK_POWER();   
    DEBUGN("board_nand_init()/n");
    clk_power->CLKCON |= (1 << 4);
#if defined(CONFIG_S3C2410)
    DEBUGN("CONFIG_S3C2410/n");
    /* initialize hardware */
    twrph0 = 3; twrph1 = 0; tacls = 0;
    cfg = S3C2410_NFCONF_EN;
    cfg |= S3C2410_NFCONF_TACLS(tacls - 1);
    cfg |= S3C2410_NFCONF_TWRPH0(twrph0 - 1);
    cfg |= S3C2410_NFCONF_TWRPH1(twrph1 - 1);
    NFCONF = cfg;
    /* initialize nand_chip data structure */
    nand->IO_ADDR_R = nand->IO_ADDR_W = (void *)0x4e00000c;
    nand->cmd_ctrl = s3c2410_hwcontrol;
    nand->dev_ready = s3c2410_dev_ready;

#else

#if defined(CONFIG_S3C2440)

    DEBUGN("CONFIG_S3C2440/n");

        twrph0 = 4; twrph1 = 2; tacls = 0;

    cfg = (tacls<<12)|(twrph0<<8)|(twrph1<<4);

    NFCONF = cfg;

    DEBUGN("cfg is %x/n",cfg);

    DEBUGN("NFCONF is %lx/n",NFCONF);

    cfg = (1<<6)|(1<<4)|(0<<1)|(1<<0);

    NFCONT = cfg;

    DEBUGN("cfg is %lx/n",cfg);

    DEBUGN("NFCONT is %x/n",NFCONT);

/* initialize nand_chip data structure */

    nand->IO_ADDR_R = nand->IO_ADDR_W = (void *)0x4e000010;
    nand->cmd_ctrl = s3c2410_hwcontrol;
    nand->dev_ready = s3c2410_dev_ready;

#endif

#endif
#ifdef CONFIG_S3C2410_NAND_HWECC

    nand->ecc.hwctl = s3c2410_nand_enable_hwecc;

    nand->ecc.calculate = s3c2410_nand_calculate_ecc;

    nand->ecc.correct = s3c2410_nand_correct_data;

    nand->ecc.mode = NAND_ECC_HW3_512;

#else
    nand->ecc.mode = NAND_ECC_SOFT;

#endif
#ifdef CONFIG_S3C2410_NAND_BBT

    nand->options = NAND_USE_FLASH_BBT;

#else
    nand->options = 0;
#endif

    DEBUGN("end of nand_init/n");
    return 0;

}
#else

 #error "U-Boot legacy NAND support not available for S3C2410"

#endif

#endif
并在该目录下的Makefile文件中添加s3c2440_nand.c的编译项
COBJS    = i2c.o interrupts.o serial.o speed.o /

      usb_ohci.o s3c2440_nand.o
-------------------------
13
最后需要加入CONFIG_S3C2440的宏定义,以便修改的代码能编译进去
 
include/configs/smdk2440.h文件中
修改
//#define    CONFIG_S3C2410        1    /* in a SAMSUNG S3C2410 SoC     */

//#define CONFIG_SMDK2410        1    /* on a SAMSUNG SMDK2410 Board  */
#define    CONFIG_S3C2440        1    /* in a SAMSUNG S3C2410 SoC     */

#define CONFIG_smdk2440        1    /* on a SAMSUNG SMDK2410 Board  *
屏蔽掉CS8900的网卡驱动2440板卡上的是DM9000
//#define CONFIG_DRIVER_CS8900    1    /* we have a CS8900 on-board */

//#define CS8900_BASE        0x19000300

//#define CS8900_BUS16        1 /* the Linux driver does accesses as shorts */
添加DM9000的驱动
#define CONFIG_DRIVER_DM9000    1

#define CONFIG_DM9000_USE_16BIT     1

#define CONFIG_DM9000_BASE        0x20000300

#define DM9000_IO            0x20000300 

#define DM9000_DATA            0x20000304
添加
# if defined(CONFIG_S3C2440)

#define CONFIG_S3C2440_NAND_BOOT 1

#endif
修改
#define    CFG_PROMPT        "SMDK2440 # "    /* Monitor Command Prompt    */
修改include/common.h   449
#if defined(CONFIG_S3C2400) || defined(CONFIG_S3C2410) || defined(CONFIG_LH7A40X) || defined(CONFIG_S3C2440)
修改include/s3c24x0.h
将里面所有的#ifdef CONFIG_S3C2410
修改为:
#if defined(CONFIG_S3C2410) || defined(CONFIG_S3C2440)
cpu/arm920t/s3c24x0/interrupt.c中添加 defined (CONFIG_S3C2440)的项
#elif defined(CONFIG_SBC2410X) || /

      defined(CONFIG_SMDK2410) || /

      defined(CONFIG_VCMA9)    || /

      defined(CONFIG_smdk2440)
cpu/arm920t/s3c24x0/serial.c 添加defined (CONFIG_S3C2440)的项
cpu/arm920t/s3c24x0/speed.c中添加defined (CONFIG_S3C2440)的项
rtc/s3c24x0_rtc.c中添加defined (CONFIG_S3C2440)的项
测试编译,将u-boot.bin烧录到NANDFLASH,成功!!!!
串口输出信息:
U-Boot 1.1.6 (Jan 12 2010 - 21:28:15)
DRAM:  64 MB
Flash: 512 kB
*** Warning - bad CRC, using default environment
In:    serial
Out:   serial
Err:   serial
SMDK2440 #
一开始出现乱码,是时钟设置有误,后来在speed.c添加了代码
ulong get_HCLK(void)
{
    S3C24X0_CLOCK_POWER * const clk_power = S3C24X0_GetBase_CLOCK_POWER();
#if defined(CONFIG_S3C2440)
    if (clk_power->CLKDIVN & 0x6)
                {
                if ((clk_power->CLKDIVN & 0x6)==2) return(get_FCLK()/2);
                if ((clk_power->CLKDIVN & 0x6)==6) return((clk_power->CAMDIVN & 0x100) ? get_FCLK()/6 : get_FCLK()/3);
                if ((clk_power->CLKDIVN & 0x6)==4) return((clk_power->CAMDIVN & 0x200) ? get_FCLK()/8 : get_FCLK()/4);
                return(get_FCLK());
                }
    else    return(get_FCLK());
#else
    return((clk_power->CLKDIVN & 0x2) ? get_FCLK()/2 : get_FCLK());
#endif
}

输出一切正常
u-boot
第一阶段的移植到此,总结一下,继续前行:

移植的过程并不会一帆风顺,需要耐性和坚定不移的心,希望学习ARM+LINUX的技术达人可以加进我的开源社区QQ群:93751599

原创粉丝点击