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的寄存器)有必定的變化。其餘寄存器基本是兼容的。

1、在U-Boot中創建本身的開發板類型,並測試編譯。
我爲開發板取名叫: hongge2440php


0 在工做目錄下解壓U-Boot。
$tar zxvf u-boot.git.tar.gz
linux


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)。

git


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 ../../..
$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


    我到這一步測試交叉編譯成功!!

編輯器




2、修改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
oop


(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控制器寄存器不一樣,不能混用!!this

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 */

八、在個文件中添加「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)

 

九、 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},
......

};

 

 

十、修改/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 */

}

上面這段是本人移植的時候只加了個頭文件也沒有修改,搬過來是給須要的朋友作參考。


十一、 修改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);

......



十二、 在/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

 

 

3、交叉編譯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;
}
文件: dm9000x.rar
大小: 5KB
下載: 下載

紅色的字符是要作的修改:功能是屏蔽無用的語句。 其實被屏蔽的語句是MII接口用的,放在這顯然是錯誤的,無故的浪費了10秒鐘。

至此,U-Boot的2440移植結束了,兩張網卡要用哪張隨你便。只要從新編譯一下就行了。GOOD LUCK!
相關文章
相關標籤/搜索