U-BOOT1.2.0移植S3C2440成功

主要参考http://blog.chinaunix.net/u1/34474/showart.php?id=397315文章,tekkamna写的很详细,我就直接搬过来,记录如下:(本人在他的基础上修改了DM9000x的驱动,SDRAM的刷新参数,和网络控制芯片的基地址)交叉编译器用的是3.3.2版本。
 
   首先,U-Boot1.2.0还没有支持s3c2440,这次移植是用2410的文件稍作修改而成的。其实2440和2410的区别主要是2440的主频更高,增加了摄像头接口和AC‘97音频接口;寄存器方面,除了新增模块的寄存器外,移植所要注意的是NAND FlASH控制器的寄存器有较大的变化、芯片的时钟频率控制寄存器(芯片PLL的寄存器)有一定的变化。其他寄存器基本是兼容的。

一、在U-Boot中建立自己的开发板类型,并测试编译。
我为开发板取名叫: hongge2440


 

0 在工作目录下解压U-Boot。
$tar zxvf u-boot.git.tar.gz


 

1 进入U-Boot目录,修改Makefile
$cd u-boot.git/
$vi Makefile
#为hongge2440建立编译项

sbc2410x_config: unconfig
    @$(MKCONFIG) $(@:_config=) arm arm920t sbc2410x NULL s3c24x0


hongge2440_config    :    unconfig
        @$(MKCONFIG) $(@:_config=) arm arm920t hongge2440 hongge s3c24x0
各项的意思如下:
arm: CPU的架构(ARCH)
arm920t: CPU的类型(CPU),其对应于cpu/arm920t子目录。
hongge2440: 开发板的型号(BOARD),对应于board/hongge/hongge2440目录。
hongge: 开发者/或经销商(vender)。
s3c24x0: 片上系统(SOC)。
红色的字符是要做的修改:功能是屏蔽无用的语句。其实被屏蔽的语句是MII接口用的,放在这显然是错误的,无端的浪费了10秒钟。

至此,U-Boot的2440移植结束了,两张网卡要用哪张随你便。只要重新编译一下就好了。GOOD LUCK!


 

2 在/board子目录中建立自己的开发板hongge2440目录

由于我在上一步板子的
开发者/或经销商(vender)中填了 hongge ,所以开发板hongge2440目录一定要建在/board子目录中的hongge目录下 ,否则编译会出错。

$cd board
$mkdir hongge hongge/hongge2440
$cp -arf sbc2410x/*   hongge/hongge2440/
$cd hongge/hongge2440
$mv sbc2410x.c hongge.c

   还要记得修改自己的开发板hongge2440目录下的Makefile文件,不然编译时会出错:
COBJS    := hongge2440.o flash.o
$vi Makefile


 


3 在include/configs/中建立配置头文件
$cd http://www.cnblogs.com/..
$cp include/configs/sbc2410x.h include/configs/hongge2440.h


 


4 测试编译能否成功
$make hongge2440_config
Configuring for hongge2440 board...
(如果出现:
$ make hongge2440_config

Makefile:1927: *** 遗漏分隔符 。 停止。
请在U-boot的根目录下的Makefile的
        @$(MKCONFIG) $(@:_config=) arm arm920t hongge2440 hongge)
前加上“Tab”键)
$make


    我到这一步测试交叉编译成功!!


 


 


二、修改U-Boot中的文件,以匹配自己的板子
 1 修改/cpu/arm920t/start.S

    (0)修改寄存器地址定义
/* turn off the watchdog */
#if defined(CONFIG_S3C2400)
# define pWTCON        0x15300000
# define INTMSK        0x14400008    /* Interupt-Controller base addresses */
# define CLKDIVN    0x14800014    /* clock divisor register */
#elif defined(CONFIG_S3C2410)|| defined(CONFIG_S3C2440)
# define pWTCON        0x53000000
# define INTMSK        0x4A000008    /* Interupt-Controller base addresses */
# define INTSUBMSK    0x4A00001C
# define CLKDIVN    0x4C000014    /* clock divisor register */
#endif
   

  (1)修改中断禁止部分

#if defined(CONFIG_S3C2400) || defined(CONFIG_S3C2410) || defined(CONFIG_S3C2440)
    ldr     r0, =pWTCON
    mov     r1, #0x0
    str     r1, [r0]

    /*
     * mask all IRQs by setting all bits in the INTMR - default
     */
    mov    r1, #0xffffffff
    ldr    r0, =INTMSK
    str    r1, [r0]
# if defined(CONFIG_S3C2410)

    ldr    r1, =0x7ff   //根据2410芯片手册,
INTSUBMSK有11位可用,
                       //
vivi也是0x7ff,不知为什么U-Boot一直没改过来。
    ldr    r0, =INTSUBMSK
    str    r1, [r0]
# endif
# if  defined(CONFIG_S3C2440)
    ldr    r1, =0x7fff  
//根据2440芯片手册,INTSUBMSK有15位可用
    ldr    r0, =INTSUBMSK
    str    r1, [r0]
# endif


 


  (2)修改时钟设置(2440的主频可达533MHz,但是我设到533MHz时系统很不稳定,不知是不是SDRAM和总线配置的影响,所以现在先设到405MHz,以后在改进。)

   
    /* 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   tekkaman*/
    orr    r1, r1, #0xc0000000         /*Asynchronous  tekkaman*/
    mcr    p15, 0, r1, c1, c0, 0      /*write ctrl register tekkaman*/

#if defined(CONFIG_S3C2440)
    /*now, CPU clock is 405.00 Mhz   tekkaman*/
    mov    r1, #CLK_CTL_BASE    /* tekkaman*/
    mov    r2, #
MDIV_405                   /* mpll_405mhz    tekkaman*/
    add    r2, r2, #
PSDIV_405             /* mpll_405mhz    tekkaman*/
    str    r2, [r1, #0x04]               /* MPLLCON tekkaman */

#endif
#if defined(CONFIG_S3C2410)
    /*now, CPU clock is 202.8 Mhz   tekkaman*/
    mov    r1, #CLK_CTL_BASE    /* tekkaman*/
    mov    r2, #MDIV_200                   /* mpll_200mhz    tekkaman*/
    add    r2, r2, #PSDIV_200             /* mpll_200mhz    tekkaman*/
    str    r2, [r1, #0x04]               /* MPLLCON tekkaman */

#endif
#endif    /* CONFIG_S3C2400 || CONFIG_S3C2410|| CONFIG_S3C2440 */

    红色部分是我添加的,
利用vivi的代码,将其设为405.00MHz 并在前面加上:

#elif defined(CONFIG_S3C2410)
# define pWTCON        0x53000000
# define INTMSK        0x4A000008    /* Interupt-Controller base addresses */
# define INTSUBMSK    0x4A00001C
# define CLKDIVN    0x4C000014    /* clock divisor register */
#define CLK_CTL_BASE        0x4C000000  /* tekkaman */
#if defined(CONFIG_S3C2440)
#define MDIV_405       0x7f << 12   /* tekkaman */
#define PSDIV_405       0x21       /* tekkaman */
#endif
#if defined(CONFIG_S3C2410)
#define MDIV_200        0xa1 << 12   /* tekkaman */
#define PSDIV_200        0x31       /* tekkaman */
#endif
#endif


(3)将从Flash启动改成从NAND Flash启动。(特别注意:这和2410的程序有不同,不可混用!!!是拷贝vivi的代码。)
将以下UBoot的重定向语句段:
#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 */
替换成:

#ifdef CONFIG_S3C2440_NAND_BOOT   @tekkaman@@@@@@@@@@@@@@@@SSSSSSSSSSSSS
    @ 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

@ copy U-Boot to RAM
  ldr   r0, =TEXT_BASE
  mov     r1, #0x0
  mov r2, #0x20000
  bl    nand_read_ll
  tst    r0, #0x0
  beq  ok_nand_read

bad_nand_read:
loop2:    b     loop2          @ 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:
loop3:     b     loop3         @ infinite loop

#endif @ CONFIG_S3C2440_NAND_BOOT  @tekkaman@@@@@@@@@@@@@@@@@@EEEEEEEEE

在“ldr    pc, _start_armboot”之前加入:

    @  LED1 on u-boot stage 1 is ok!
    mov    r1, #GPIO_CTL_BASE
    add    r1, r1, #oGPIO_B
    ldr    r2,=0x155aa
    str    r2, [r1, #oGPIO_CON]
    mov    r2, #0xff
    str    r2, [r1, #oGPIO_UP]
    mov    r2, #0x1c0
    str    r2, [r1, #oGPIO_DAT]

修改目的:如果看到只有LED1亮了,说明UBoot的第一阶段已完成!
灯亮这段程序根据个人的板子不通要做相应的修改,不知道怎么修改就不
添加也行
在 “  _start_armboot:    .word start_armboot  ” 后加入:
   .align     2
DW_STACK_START:  .word  STACK_BASE+STACK_SIZE-4

board/hongge/hongge2440加入NAND Flash读函数文件,拷贝vivi中的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)
#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 GPDAT        __REGi(GPIO_CTL_BASE+oGPIO_F+oGPIO_DAT)

#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 BUSY 4
inline void wait_idle(void) {
    while(!(NFSTAT & BUSY));
    NFSTAT |= BUSY;
}

#define NAND_SECTOR_SIZE    512
#define NAND_BLOCK_MASK        (NAND_SECTOR_SIZE - 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) || (size & NAND_BLOCK_MASK)) {
        return -1;    /* invalid alignment */
    }

    NAND_CHIP_ENABLE;

    for(i=start_addr; i < (start_addr + size);) {
        /* READ0 */
        NAND_CLEAR_RB;        
        NFCMD = 0;

        /* Write Address */
        NFADDR = i & 0xff;
        NFADDR = (i >> 9) & 0xff;
        NFADDR = (i >> 17) & 0xff;
        NFADDR = (i >> 25) & 0xff;

        NAND_DETECT_RB;

        for(j=0; j < NAND_SECTOR_SIZE; j++, i++) {
            *buf = (NFDATA & 0xff);
            buf++;
        }
    }
    NAND_CHIP_DISABLE;
    return 0;
}

注意:s3c2410s3c2440Nand Flash控制器寄存器不同,不能混用!!

3 修改board/hongge/hongge2440/Makefile文件
......
OBJS := hongge2440.o  nand_read.o flash.o
......

4 修改include/configs/hongge.h文件,添加如下内容(注意:s3c2410s3c2440Nand Flash控制器寄存器不同,不能混用!!):
......
/*
 * Nandflash Boot
 */
#define CONFIG_S3C2440_NAND_BOOT 1
#define STACK_BASE    0x33f00000
#define STACK_SIZE    0x8000
//#define UBOOT_RAM_BASE    0x33f80000
/* NAND Flash Controller */
#define NAND_CTL_BASE        0x4E000000
#define bINT_CTL(Nb)        __REG(INT_CTL_BASE + (Nb))
/* Offset */
#define oNFCONF            0x00
#define oNFCONT            0x04
#define oNFCMD            0x08
#define oNFADDR            0x0c
#define oNFDATA            0x10
#define oNFSTAT            0x20
#define oNFECC            0x2c

/* GPIO */
#define GPIO_CTL_BASE        0x56000000
#define oGPIO_B            0x10
#define oGPIO_CON       0x0   /* R/W, Configures the pins of the port */
#define oGPIO_DAT        0x4    /* R/W,    Data register for port */
#define oGPIO_UP        0x8    /* R/W, Pull-up disable register */
#endif    /* __CONFIG_H */

5 修改board/tekkaman/hongge2440/lowlevel_init.S文件
   
依照开发板的内存区的配置情况, 修改board/hongge/hongge2440/lowlevel_init.S文件,我利用vivi源码里的信息做了如下更改:
......
/* REFRESH parameter */
#define REFEN             0x1    /* Refresh enable */
#define TREFMD             0x0    /* CBR(CAS before RAS)/Auto refresh */
#define Trp             0x0   
#define Trc             0x3    /* 7clk */
#define Tchr             0x2    /* 3clk */
#define REFCNT             1268    /*period=7.8125us,HCLK=100Mhz  (2048+1-7.8125*100)*/
......

6 修改/board/hongge/hongge2440/hongge2440.c
 
因为友善之臂SBC2440smdk2410GPIO连接有所不同,修改其对GPIOPLL的配置(请参阅友善之臂SBC2440的硬件说明和2440芯片手册)
......

#elif FCLK_SPEED==1        /* Fout = 405MHz */
//#define M_MDIV    0x5c
//#define M_PDIV    0x4
//#define M_SDIV    0x0
#define M_MDIV    0x7f
#define M_PDIV    0x2
#define M_SDIV    0x1
......
#elif USB_CLOCK==1
//#define U_M_MDIV    0x48
//#define U_M_PDIV    0x3
#define U_M_MDIV    0x38
#define U_M_PDIV    0x2
#define U_M_SDIV    0x2

......

/* set up the I/O ports */
gpio->GPACON = 0x007FFFFF;
//gpio->GPBCON = 0x00044556;
gpio->GPBCON = 0x00055556;

......
    /* arch number of S3C2440 -Board */
    gd->bd->bi_arch_number = MACH_TYPE_S3C2440 ;

/* adress of boot parameters */

gd->bd->bi_boot_params = 0x30000100;

icache_enable();

dcache_enable();

gpio->GPBDAT = 0x180; //tekkamanninja

//int board_init (void)设置完成后,LED1LED2会亮起!

return 0;

}

上面这段是直接搬tekkaman的,本人移植是没有修改这段,写上来是给大家需要的做个参考

7 为了实现NAND Flash的读写,再次修改/include/configs/hongge2440.h
(
请格外注意:如果编译时报错,在Linux下用KWrite等有高亮显示的文本编辑器看看文件的注释是不是为注释应有的颜色(KWrite中为灰色),如果不是,则将注释删除。因为#define后面的注释被认为是程序的一部分。建议注释和#define分行写)
......
/*
 * High Level Configuration Options
 * (easy to change)
 */
#define CONFIG_ARM920T        1    /* This is an ARM920T Core    */

//#define CONFIG_S3C2410      1 

//#define CONFIG_SBC2410X    1


#define    CONFIG_S3C2440        1    /* in a SAMSUNG S3C2440 SoC     */
#define CONFIG_hongge2440    1  /* on a SAMSUNG hongge2440 Board  */
......
/***********************************************************
 * Command definition
 ***********************************************************/
#define CONFIG_COMMANDS \
            (CONFIG_CMD_DFL     | \
            CFG_CMD_CACHE     | \
            CFG_CMD_NAND     | \
            CFG_CMD_NET     | \
            /*CFG_CMD_EEPROM |*/ \
            /*CFG_CMD_I2C     |*/ \
            /*CFG_CMD_USB     |*/ \
            CFG_CMD_PING | \
            CFG_CMD_ENV | \
            CFG_CMD_REGINFO  | \
            CFG_CMD_DATE     | \
            CFG_CMD_DHCP     | \
            CFG_CMD_ELF)

/* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */
#include <cmd_confdefs.h>
#define    CFG_LONGHELP               
/* undef to save memory        */

#define    CFG_PROMPT   "[HongGe2440]#"
/*Monitor Command Prompt  */
#define    CFG_CBSIZE        256       
/* Console I/O Buffer Size    */
......
#define    CFG_LOAD_ADDR      0x30008000  
 /* default load address    */

......
/* Timeout for Flash Write */

#define    CFG_ENV_IS_IN_NAND    1
#define CFG_ENV_OFFSET  0X20000
//#define ENV_IS_EMBEDDED 1
#define CFG_NAND_LEGACY

#define CFG_ENV_SIZE    0x10000  
/* Total Size of Environment Sector */
/*----------------------------------------------------------------------
 * NAND flash settings
 */
#if (CONFIG_COMMANDS & CFG_CMD_NAND)
#define CFG_NAND_BASE 0x4E000000
/* NandFlash
控制器在SFR区起始寄存器地址 */
#define CFG_MAX_NAND_DEVICE 1
 /*
支持的最在Nand Flash数据 */
#define SECTORSIZE 512
/* 1
页的大小 */
#define NAND_SECTOR_SIZE SECTORSIZE
#define NAND_BLOCK_MASK 511
/*
页掩码 */
#define ADDR_COLUMN 1
/*
一个字节的Column地址 */

#define ADDR_PAGE 3
/* 3
字节的页块地址!!!!!*/
#define ADDR_COLUMN_PAGE 4
/*
总共4字节的页块地址!!!!! */
#define NAND_ChipID_UNKNOWN 0x00
/*
未知芯片的ID */
#define NAND_MAX_FLOORS 1
#define NAND_MAX_CHIPS 1
/* Nand Flash
命令层底层接口函数 */
#define WRITE_NAND_COMMAND(d, adr) {rNFCMD = d;}

#define WRITE_NAND_ADDRESS(d, adr) {rNFADDR = d;}

#define WRITE_NAND(d, adr) {rNFDATA = d;}

#define READ_NAND(adr) (rNFDATA)

#define NAND_WAIT_READY(nand) {while(!(rNFSTAT&(1<<0)));}

#define NAND_DISABLE_CE(nand) {rNFCONT |= (1<<1);}

#define NAND_ENABLE_CE(nand) {rNFCONT &= ~(1<<1);}



#define WRITE_NAND_COMMANDW(d, adr) NF_CmdW(d)

/* the following functions are NOP's because S3C24X0 handles this in hardware */

#define NAND_CTL_CLRALE(nandptr)
#define NAND_CTL_SETALE(nandptr)
#define NAND_CTL_CLRCLE(nandptr)
#define NAND_CTL_SETCLE(nandptr)
/*
允许Nand Flash写校验 */
#define CONFIG_MTD_NAND_VERIFY_WRITE 1
......

#define rNFCONF (*(volatile unsigned int *)0x4e000000)

#define rNFCONT (*(volatile unsigned int *)0x4e000004)

#define rNFCMD (*(volatile unsigned char *)0x4e000008)

#define rNFADDR (*(volatile unsigned char *)0x4e00000c)

#define rNFDATA (*(volatile unsigned char *)0x4e000010)

#define rNFSTAT (*(volatile unsigned int *)0x4e000020)

#define rNFECC (*(volatile unsigned int *)0x4e00002c)

#endif    /* __CONFIG_H */

8、在个文件中添加“CONFIG_S3C2440”,使得原来s3c2410的代码可以编译进来。

1/include/common.h文件的第454行:

#if defined(CONFIG_S3C2400) || defined(CONFIG_S3C2410) || defined(CONFIG_LH7A40X) || defined(CONFIG_S3C2440)

2/include/s3c24x0.h文件的第859599110148404行:

#if defined(CONFIG_S3C2410) || defined (CONFIG_S3C2440)

3/cpu/arm920t/s3c24x0/interrupts.c文件的第33行:

#if defined(CONFIG_S3C2400) || defined (CONFIG_S3C2410) || defined (CONFIG_TRAB) || defined (CONFIG_S3C2440)

38行:#elif defined(CONFIG_S3C2410) || defined (CONFIG_S3C2440)

4/cpu/arm920t/s3c24x0/serial.c文件的第22行:

#if defined(CONFIG_S3C2400) || defined (CONFIG_S3C2410) || defined (CONFIG_TRAB) || defined (CONFIG_S3C2440)

26行:#elif defined(CONFIG_S3C2410) || defined (CONFIG_S3C2440)

void serial_setbrg (void)

{

         S3C24X0_UART * const uart = S3C24X0_GetBase_UART(UART_NR);

         int i;

         unsigned int reg = 0;

 

         /* value is calculated so : (int)(PCLK/16./baudrate) -1 */

         reg = get_PCLK() / (16 * gd->baudrate) - 1;

         /* FIFO enable, Tx/Rx FIFO clear */

         uart->UFCON = 0x00;

         uart->UMCON = 0x0;

         /* Normal,No parity,1 stop,8 bit */

         uart->ULCON = 0x3;

......

}

5/cpu/arm920t/s3c24x0/speed.c文件的第33行:

#if defined(CONFIG_S3C2400) || defined (CONFIG_S3C2410) || defined (CONFIG_TRAB) || defined (CONFIG_S3C2440)

37:#elif defined(CONFIG_S3C2410) || defined (CONFIG_S3C2440)

顺便修改源代码,以匹配s3c2440

static ulong get_PLLCLK(int pllreg)
{
   ......

    m = ((r & 0xFF000) >> 12) + 8;
    p = ((r & 0x003F0) >> 4) + 2;
    s = r & 0x3;
//tekkaman
#if defined(CONFIG_S3C2440)
   if (pllreg == MPLL)
    return((CONFIG_SYS_CLK_FREQ * m * 2) / (p << s));
    else if (pllreg == UPLL)
#endif
//tekkaman

    return((CONFIG_SYS_CLK_FREQ * m) / (p << s));
}

......

/* return FCLK frequency */

ulong get_FCLK(void)

{

    return(get_PLLCLK(MPLL));

}

 

/* return HCLK frequency */

ulong get_HCLK(void)

{

    S3C24X0_CLOCK_POWER * const clk_power = S3C24X0_GetBase_CLOCK_POWER();

 

      

              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());

                            }

}

......

6/cpu/arm920t/s3c24x0/usb_ohci.c文件的第45行:

#elif defined(CONFIG_S3C2410) || defined(CONFIG_S3C2440)

(i2c的文件还没修改,因为没用到)

7/rtc/s3c24x0_rtc.c文件的第35行:

#elif defined(CONFIG_S3C2410) || defined(CONFIG_S3C2440)

 

在个文件中添加“defined(CONFIG_hongge2440)”,使得原来SBC2410X的代码可以编译进来。

1/cpu/arm920t/s3c24x0/interrupts.c文件的第181行: 

    defined(CONFIG_VCMA9) || defined(CONFIG_hongge2440)

 

9、 include/linux/mtd/nand_ids.h的结构体nand_flash_ids加入

static struct nand_flash_dev nand_flash_ids[] = {

......
    {"Samsung KM29N16000",NAND_MFR_SAMSUNG, 0x64, 21, 1, 2, 0x1000, 0},
   
{"Samsung K9F1208U0B",  NAND_MFR_SAMSUNG, 0x76, 26, 0, 3, 0x4000, 0},
    {"Samsung unknown 4Mb", NAND_MFR_SAMSUNG, 0x6b, 22, 0, 2, 0x2000, 0},
......

};

 

 

10、修改/lib_arm中的board.c。

......

#include <common.h>
#include <command.h>
#include <malloc.h>
#include <devices.h>
#include <version.h>
#include <net.h>
#include <s3c2410.h>

 

......

 

static int display_banner (void)
{      

         S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();

         gpio->GPBDAT = 0x100;  //tekkamanninja

//在串口初始化和console初始化完成,串口输出信息之前,LED1LED2LED3会亮起!

    printf ("\n\n%s\n\n", version_string);
    debug ("U-Boot code: %08lX -> %08lX  BSS: -> %08lX\n",
           _armboot_start, _bss_start, _bss_end);
   
printf ("U-Boot code: %08lX -> %08lX  BSS: -> %08lX\n",    //tekkaman
        _armboot_start, _bss_start, _bss_end);      //tekkaman
#ifdef CONFIG_MODEM_SUPPORT
    debug ("Modem Support enabled\n");
#endif
#ifdef CONFIG_USE_IRQ
    debug ("IRQ Stack: %08lx\n", IRQ_STACK_START);
    debug ("FIQ Stack: %08lx\n", FIQ_STACK_START);
#endif

    return (0);
}

 

......

void start_armboot (void)

{

         init_fnc_t **init_fnc_ptr;

         char *s;

#ifndef CFG_NO_FLASH

         ulong size;

#endif

#if defined(CONFIG_VFD) || defined(CONFIG_LCD)

         unsigned long addr;

#endif

         S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();

......

         gpio->GPBDAT = 0x0;  //tekkamanninja

//在进入命令提示符之前,四个LED会同时亮起!

         /* main_loop() can return to retry autoboot, if so just run it again. */

         for (;;) {

                   main_loop ();

         }

 

         /* NOTREACHED - no way out of command loop except booting */

}

上面这段是本人移植的时候只加了个头文件也没有修改,搬过来是给需要的朋友做参考。


 

 

11、 修改common/env_nand.c

......
#ifdef CONFIG_INFERNO
#error CONFIG_INFERNO not supported yet
#endif

int nand_legacy_rw (struct nand_chip* nand, int cmd,
        size_t start, size_t len,
        size_t * retlen, u_char * buf);
extern struct nand_chip nand_dev_desc[CFG_MAX_NAND_DEVICE];
extern int nand_legacy_erase(struct nand_chip *nand, size_t ofs, size_t len, int clean);

/* info for NAND chips, defined in drivers/nand/nand.c */
extern nand_info_t nand_info[CFG_MAX_NAND_DEVICE];

......

#else /* ! CFG_ENV_OFFSET_REDUND */
int saveenv(void)
{
    ulong total;
    int ret = 0;

    puts ("Erasing Nand...");
    //if (nand_erase(&nand_info[0], CFG_ENV_OFFSET, CFG_ENV_SIZE))

if (nand_legacy_erase(nand_dev_desc + 0, CFG_ENV_OFFSET, CFG_ENV_SIZE, 0))
        return 1;


    puts ("Writing to Nand... ");
    total = CFG_ENV_SIZE;
    //ret = nand_write(&nand_info[0], CFG_ENV_OFFSET, &total, (u_char*)env_ptr);

ret = nand_legacy_rw(nand_dev_desc + 0,

0x00 | 0x02, CFG_ENV_OFFSET, CFG_ENV_SIZE,

&total, (u_char*)env_ptr);


    if (ret || total != CFG_ENV_SIZE)
        return 1;

    puts ("done\n");
    return ret;
......
#else /* ! CFG_ENV_OFFSET_REDUND */
/*
 * The legacy NAND code saved the environment in the first NAND device i.e.,
 * nand_dev_desc + 0. This is also the behaviour using the new NAND code.
 */
void env_relocate_spec (void)
{
#if !defined(ENV_IS_EMBEDDED)
    ulong total;
    int ret;

    total = CFG_ENV_SIZE;
    //ret = nand_read(&nand_info[0], CFG_ENV_OFFSET, &total, (u_char*)env_ptr);
    ret = nand_legacy_rw(nand_dev_desc + 0, 0x01 | 0x02, CFG_ENV_OFFSET, CFG_ENV_SIZE, &total, (u_char*)env_ptr);

......



12、 在/board/tekkaman/hongge2440/hongge2440.c文件的末尾添加对Nand Flash 的初始化函数(在后面Nand Flash的操作都要用到)

 

u-boot运行至第二阶段进入start_armboot()函数。其中nand_init()函数是对nand flash的最初初始化函数。Nand_init()函数在两个文件中实现。其调用与CFG_NAND_LEGACY宏有关,如果没有定义这个宏,系统调用 drivers/nand/nand.c中的nand_init();否则调用自己在board/hongge/hongge2440/hongge2440.c中的nand_init()函数。这里我选择第二种方式。

 

#if (CONFIG_COMMANDS & CFG_CMD_NAND)
typedef enum {
NFCE_LOW,
NFCE_HIGH
} NFCE_STATE;

static inline void NF_Conf(u16 conf)
{
S3C2410_NAND * const nand = S3C2410_GetBase_NAND();

nand->NFCONF = conf;
}

static inline void NF_Cont(u16 cont)

 

{

S3C2410_NAND * const nand = S3C2410_GetBase_NAND();

nand->NFCONT = cont;

}

static inline void NF_Cmd(u8 cmd)
{
S3C2410_NAND * const nand = S3C2410_GetBase_NAND();

nand->NFCMD = cmd;
}

static inline void NF_CmdW(u8 cmd)
{
NF_Cmd(cmd);
udelay(1);
}

static inline void NF_Addr(u8 addr)
{
S3C2410_NAND * const nand = S3C2410_GetBase_NAND();

nand->NFADDR = addr;
}

static inline void NF_SetCE(NFCE_STATE s)
{
S3C2410_NAND * const nand = S3C2410_GetBase_NAND();

switch (s) {
case NFCE_LOW:
nand->NFCONT &= ~(1<<1);
break;

case NFCE_HIGH:
nand->NFCONT |= (1<<1);
break;
}
}

static inline void NF_WaitRB(void)
{
S3C2410_NAND * const nand = S3C2410_GetBase_NAND();

while (!(nand->NFSTAT & (1<<0)));
}

static inline void NF_Write(u8 data)
{
S3C2410_NAND * const nand = S3C2410_GetBase_NAND();

nand->NFDATA = data;
}

static inline u8 NF_Read(void)
{
S3C2410_NAND * const nand = S3C2410_GetBase_NAND();

return(nand->NFDATA);
}

static inline void NF_Init_ECC(void)
{
S3C2410_NAND * const nand = S3C2410_GetBase_NAND();

nand->NFCONT |= (1<<4);
}

static inline u32 NF_Read_ECC(void)
{
S3C2410_NAND * const nand = S3C2410_GetBase_NAND();

return(nand->NFECC);
}

#endif


#if (CONFIG_COMMANDS & CFG_CMD_NAND)
extern ulong nand_probe(ulong physadr);


static inline void NF_Reset(void)
{
int i;

NF_SetCE(NFCE_LOW);
NF_Cmd(0xFF); /* reset command */
for(i = 0; i < 10; i++); /* tWB = 100ns. */
NF_WaitRB(); /* wait 200~500us; */
NF_SetCE(NFCE_HIGH);
}


static inline void NF_Init(void)
{
#if 0 /* a little bit too optimistic */
#define TACLS 0
#define TWRPH0 3
#define TWRPH1 0
#else
#define TACLS 0
#define TWRPH0 4
#define TWRPH1 2
#endif

       NF_Conf((TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4));

       NF_Cont((1<<6)|(1<<4)|(1<<1)|(1<<0));
/*nand->NFCONF = (1<<15)|(1<<14)|(1<<13)|(1<<12)|(1<<11)|(TACLS<<8)|(TWRPH0<<4)|(TWRPH1<<0); */
/* 1 1 1 1, 1 xxx, r xxx, r xxx */
/* En 512B 4step ECCR nFCE=H tACLS tWRPH0 tWRPH1 */

NF_Reset();
}

void
nand_init(void)
{
S3C2410_NAND * const nand = S3C2410_GetBase_NAND();

NF_Init();
#ifdef DEBUG
printf("NAND flash probing at 0x%.8lX\n", (ulong)nand);
#endif
printf ("%4lu MB\n", nand_probe((ulong)nand) >> 20);
}
#endif

 

 

12 在/include/s3c24x0.h中加入2440 的NAND FLASH 寄存器定义和CAMDIVN定义:

......

typedef struct {

         S3C24X0_REG32   LOCKTIME;

         S3C24X0_REG32   MPLLCON;

         S3C24X0_REG32   UPLLCON;

         S3C24X0_REG32   CLKCON;

         S3C24X0_REG32   CLKSLOW;

         S3C24X0_REG32   CLKDIVN;

         S3C24X0_REG32   CAMDIVN;

} /*__attribute__((__packed__))*/ S3C24X0_CLOCK_POWER;

......

#if defined(CONFIG_S3C2410)

/* NAND FLASH (see S3C2410 manual chapter 6) */

typedef struct {

         S3C24X0_REG32   NFCONF;

         S3C24X0_REG32   NFCMD;

         S3C24X0_REG32   NFADDR;

         S3C24X0_REG32   NFDATA;

         S3C24X0_REG32   NFSTAT;

         S3C24X0_REG32   NFECC;

} /*__attribute__((__packed__))*/ S3C2410_NAND;

#endif

#if defined (CONFIG_S3C2440)

/* NAND FLASH (see S3C2440 manual chapter 6) */

typedef struct {

         S3C24X0_REG32   NFCONF;

         S3C24X0_REG32   NFCONT;

         S3C24X0_REG32   NFCMD;

         S3C24X0_REG32   NFADDR;

         S3C24X0_REG32   NFDATA;

         S3C24X0_REG32   NFMECC0;

         S3C24X0_REG32   NFMECC1;

         S3C24X0_REG32   NFSECC;

         S3C24X0_REG32   NFSTAT;

         S3C24X0_REG32   NFESTAT0;

         S3C24X0_REG32   NFESTAT1;

         S3C24X0_REG32   NFECC;

} /*__attribute__((__packed__))*/ S3C2410_NAND;

#endif

 

 

三、交叉编译UBoot
UBoot的根目录下
$make
一阵English飘过~~~~~~~~~~~~~~~~~~~~~~~

本人按照上面的做了一遍,可以成功!!

四 网卡移植。

本人的板子使用的是DM9000A,下面的修改是这款芯片。如果使用DM9000请参考

DM9000网卡移植请看:http://blog.chinaunix.net/u1/34474/showart.php?id=401078 按照这边文章的内容接着继续下去即可。
由于UBOOT自带的dm9000x网卡驱动对dm9000a的支持有点小问题,所以本人把修改好的dm9000x驱动程序附上。(见附件)替换原来的驱动后,
在/include/configs/hongge2440.h文件中修改添加对DM9000A的支持,屏蔽CS8900:
/*
 * Hardware drivers
 */
//#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 */

#define CONFIG_DRIVER_DM9000  1
#define CONFIG_DM9000_BASE  0x20000300
#define DM9000_IO   CONFIG_DM9000_BASE
#define DM9000_DATA   (CONFIG_DM9000_BASE+16)
#define CONFIG_DM9000_USE_16BIT
   
    在这里
#define CONFIG_DM9000_BASE 的定义最为重要。不同的板子只要修改这个参数即可。DM9000在BANK4上所以定义为“0x20000300”。DM9000A在BANK4上所以定义为“0x20000000”。有的板子是在BANK1上,就为“0x08000000”。就是说DM9000A不用添加300的偏移,具体看网卡芯片的手册。DM9000_DATA   的地址如果CMD使用A2就是CONFIG_DM9000_BASE+4,我的板子是A4所以CONFIG_DM9000_BASE+16,一般的开发板都是A2,具体请看板子的电路图。

    这样定义完之后,就可以“make”,然后下载到板上运行。ping和tftp都可以实现。但是有些问题:

(1)网卡的MAC地址与你设置的不一样
(2)会有“could not establish link” 的提示,而且在显示MAC地址后很久后才响应。

这两个问题我认为是U-Boot的DM9000源码的BUG。追踪源码可以知道:这些都是发生在int eth_init(bd_t * bd)初始化时的错误。

    修正BUG(修改/drivers/dm9000x.c文件)

(1)
网卡MAC地址错误的解决方法:

/* Initilize dm9000 board
*/
int
eth_init(bd_t * bd)
{
    ......

    /* Set Node address */
/*    for (i = 0; i < 6; i++)
        ((u16 *) bd->bi_enetaddr)[i] = read_srom_word(i);
*/
//tekkamanninja   
    char *tmp = getenv ("ethaddr");
    char *end;

    for (i=0; i<6; i++) {
        bd->bi_enetaddr[i] = tmp ? simple_strtoul(tmp, &end, 16) : 0;
        if (tmp)
            tmp = (*end) ? end+1 : end;
    }
//tekkamanninja
    printf("MAC: %02x:%02x:%02x:%02x:%02x:%02x\n", bd->bi_enetaddr[0],
           bd->bi_enetaddr[1], bd->bi_enetaddr[2], bd->bi_enetaddr[3],
           bd->bi_enetaddr[4], bd->bi_enetaddr[5]);
......

红色的字符是要做的修改:功能是屏蔽原有获取MAC地址的语句,替换成从U-Boot的参数区读取数据并存到
bd->bi_enetaddr[i]中。

(2)“could not establish link” 提示和慢响应的解决方法:

/* Initilize dm9000 board
*/
int
eth_init(bd_t * bd)
{
    ......

    DM9000_iow(DM9000_RCR, RCR_DIS_LONG | RCR_DIS_CRC | RCR_RXEN);    /* RX enable */
    DM9000_iow(DM9000_IMR, IMR_PAR);    /* Enable TX/RX interrupt mask */

#if 0
    i = 0;
    while (!(phy_read(1) & 0x20)) {    /* autonegation complete bit */
        udelay(1000);
        i++;
        if (i == 10000) {
            printf("could not establish link\n");
            return 0;
        }
        printf(" link=%d\n",i);
    }
#endif
#if 0
    /* see what we've got */
    lnk = phy_read(17) >> 12;
    printf("operating at ");
    switch (lnk) {
    case 1:
        printf("10M half duplex ");
        break;
    case 2:
        printf("10M full duplex ");
        break;
    case 4:
        printf("100M half duplex ");
        break;
    case 8:
        printf("100M full duplex ");
        break;
    default:
        printf("unknown: %d ", lnk);
        break;
    }
    printf("mode\n");
#endif
printf("operating at 100M full duplex mode\n");
    return 0;
}
网卡驱动

posted on 2009-09-17 12:42  ( ⊙o⊙ )哇倪  阅读(2250)  评论(0编辑  收藏  举报

导航