移植u-boot-2012.04.01到JZ2440

開發環境:Ubuntu 12.04
開發板:JZ2440  256M NandFlash  64M SDRAM
交叉編譯器:arm-linux-gcc-4.3.2
u-boot:u-boot-2012.04.01  
 
 
 
 
 
 
 
 
  最近在學習BootLoader,移植u-boot-2012.04.01到JZ2440開發板,如今把移植過程記錄下來,一來梳理思路,二來方便之後更進一步學習。
 
1、  u-boot分析過程
    a、 初始化硬件:關看門狗、設置時鐘、設置SDRAM、初始化NAND FLASH
    b、若是bootloader比較大,要把它重定位到SDRAM
    c、把內核從NAND FLASH讀到SDRAM
    d、設置"要傳給內核的參數"
    e、跳轉執行內核
具體代碼分析
一、set the cpu to SVC32 mode
二、turn off the watchdog
三、mask all IRQs by setting all bits in the INTMR
四、設置時鐘比例
五、設置內存控制器
六、設置棧,調用C函數board_init_f
七、調用函數數組init_sequence裏的各個函數
    7.1 board_early_init_f : 設置系統時鐘、設置GPIO
......................................
八、重定位代碼
    8.1 從NOR FLASH把代碼複製到SDRAM
    8.2 程序的連接地址是0,訪問全局變量、靜態變量、調用函數時是使"基於0地址編譯獲得的地址",如今把程序複製到了SDRAM,須要修改代碼,把"基於0地址編譯獲得的地址"改成新地址。
    8.3 程序裏有些地址在連接時不能肯定,要到運行前才能肯定:fixabs
九、clear_bss
十、調用C函數board_init_r:第2階段的代碼
 
2、初始編譯
 一、  解壓 u-boot-2012.04.01.tar.bz2
tar xjf u-boot-2012.04.01.tar.bz2

進入解壓後文件目錄linux

cd u-boot-2012.04.01

二、在解壓後文件目錄下根據靠近的單板,配置數組

make smdk2410_config
make

這個時候編譯完成後是不能在JZ2440上正常運行架構

3、創建本身的單板,定製適合本身單板的bootloaderasync

一、新建一個單板ide

    cd board/samsung/
    cp smdk2410 smdk2440 -rf
     cd ../../include/configs/
    cp smdk2410.h smdk2440.h
修改boards.cfg
仿照2410,添加2440
smdk2410                     arm         arm920t     -                  samsung        s3c24x0

添加函數

smdk2440                     arm         arm920t     -                   samsung        s3c24x0

make , 燒寫調試學習

二、根據需求進一步配置測試

make menuconfig  

三、修改Makefile ,開頭指定架構和編譯器spa

 ARCH=arm
 CROSS_COMPILE=arm-linux-
四、修改uboot代碼,適合單板
  uboot裏先以60MHZ的時鐘計算參數來設置內存控制器,可是MPLL還未設置
  處理措施: 把MPLL的設置放到start.S裏,取消board_early_init_f裏對MPLL的設置
a、設置PLL的時鐘的函數在_main中的board_init_f中初始化函數列表中的  boad_early_init_f 中,設置MPLL倍頻值。它應該要在設置分頻係數和初始化內存控制器以前來設置。
作以下修改: 在smdk2410.c文件中找到設置MPLL部分的代碼,註釋掉。
    /* to reduce PLL lock time, adjust the LOCKTIME register */
         //writel(0xFFFFFF, &clk_power->locktime);

      /* configure MPLL */
         //writel((M_MDIV << 12) + (M_PDIV << 4) + M_SDIV,
           //     &clk_power->mpllcon);

而後在start.S中再設置MPLLdebug

 

#define S3C2440_MPLL_400MHZ     ((0x5c<<12)|(0x01<<4)|(0x01))
#if 0
    /* FCLK:HCLK:PCLK = 1:2:4 */
    /* default FCLK is 120 MHz ! */
    ldr    r0, =CLKDIVN
    mov    r1, #3
    str    r1, [r0]
  #else
        /* 2. 設置時鐘 400MHz */
        ldr r0, =0x4c000014
        //  mov r1, #0x03;            // FCLK:HCLK:PCLK=1:2:4, HDIVN=1,PDIVN=1
        mov r1, #0x05;            // FCLK:HCLK:PCLK=1:4:8
        str r1, [r0]
        /* 若是HDIVN非0,CPU的總線模式應該從「fast bus mode」變爲「asynchronous bus mode」 */
        mrc p15, 0, r1, c1, c0, 0       /* 讀出控制寄存器 */
        orr r1, r1, #0xc0000000         /* 設置爲「asynchronous bus mode」 */
        mcr p15, 0, r1, c1, c0, 0       /* 寫入控制寄存器 */
    
        #define S3C2440_MPLL_400MHZ     ((0x5c<<12)|(0x01<<4)|(0x01))
        /* MPLLCON = S3C2440_MPLL_200MHZ */
        ldr r0, =0x4c000004
        ldr r1, =S3C2440_MPLL_400MHZ
        str r1, [r0]
  
        /* 啓動ICACHE */
        mrc p15, 0, r0, c1, c0, 0   @ read control reg
        orr r0, r0, #(1<<12)
        mcr p15, 0, r0, c1, c0, 0   @ write it back
  #endif
View Code

 

關閉看門狗、關中斷

#define S3C2440_MPLL_400MHZ     ((0x5c<<12)|(0x01<<4)|(0x01))
#if 0
    /* FCLK:HCLK:PCLK = 1:2:4 */
    /* default FCLK is 120 MHz ! */
    ldr    r0, =CLKDIVN
    mov    r1, #3
    str    r1, [r0]
  #else
        /* 2. 設置時鐘 400MHz */
        ldr r0, =0x4c000014
        //  mov r1, #0x03;            // FCLK:HCLK:PCLK=1:2:4, HDIVN=1,PDIVN=1
        mov r1, #0x05;            // FCLK:HCLK:PCLK=1:4:8
        str r1, [r0]
        /* 若是HDIVN非0,CPU的總線模式應該從「fast bus mode」變爲「asynchronous bus mode」 */
        mrc p15, 0, r1, c1, c0, 0       /* 讀出控制寄存器 */
        orr r1, r1, #0xc0000000         /* 設置爲「asynchronous bus mode」 */
        mcr p15, 0, r1, c1, c0, 0       /* 寫入控制寄存器 */
    
        #define S3C2440_MPLL_400MHZ     ((0x5c<<12)|(0x01<<4)|(0x01))
        /* MPLLCON = S3C2440_MPLL_200MHZ */
        ldr r0, =0x4c000004
        ldr r1, =S3C2440_MPLL_400MHZ
        str r1, [r0]
  
        /* 啓動ICACHE */
        mrc p15, 0, r0, c1, c0, 0   @ read control reg
        orr r0, r0, #(1<<12)
        mcr p15, 0, r0, c1, c0, 0   @ write it back
  #endif
關閉看門狗、關中斷

#ifdef CONFIG_S3C24X0
    /* turn off the watchdog */

# if defined(CONFIG_S3C2400)
#  define pWTCON    0x15300000
#  define INTMSK    0x14400008    /* Interrupt-Controller base addresses */
#  define CLKDIVN    0x14800014    /* clock divisor register */
#else
#  define pWTCON    0x53000000
#  define INTMSK    0x4A000008    /* Interrupt-Controller base addresses */
#  define INTSUBMSK    0x4A00001C
#  define CLKDIVN    0x4C000014    /* clock divisor register */
# endif

    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, =0x3ff
    ldr    r0, =INTSUBMSK
    str    r1, [r0]
# endif
#endif
View Code
b、內存控制器的設置值改成以下
在/board/samsung/smdk2410/lowlevel_init.S文件中作一下修改
SMRDATA:
#if 0
    .word (0+(B1_BWSCON<<4)+(B2_BWSCON<<8)+(B3_BWSCON<<12)+(B4_BWSCON<<16)+(B5_BWSCON<<20)+(B6_BWSCON<<24)+(B7_BWSCON<<28))
    .word ((B0_Tacs<<13)+(B0_Tcos<<11)+(B0_Tacc<<8)+(B0_Tcoh<<6)+(B0_Tah<<4)+(B0_Tacp<<2)+(B0_PMC))
    .word ((B1_Tacs<<13)+(B1_Tcos<<11)+(B1_Tacc<<8)+(B1_Tcoh<<6)+(B1_Tah<<4)+(B1_Tacp<<2)+(B1_PMC))
    .word ((B2_Tacs<<13)+(B2_Tcos<<11)+(B2_Tacc<<8)+(B2_Tcoh<<6)+(B2_Tah<<4)+(B2_Tacp<<2)+(B2_PMC))
    .word ((B3_Tacs<<13)+(B3_Tcos<<11)+(B3_Tacc<<8)+(B3_Tcoh<<6)+(B3_Tah<<4)+(B3_Tacp<<2)+(B3_PMC))
    .word ((B4_Tacs<<13)+(B4_Tcos<<11)+(B4_Tacc<<8)+(B4_Tcoh<<6)+(B4_Tah<<4)+(B4_Tacp<<2)+(B4_PMC))
    .word ((B5_Tacs<<13)+(B5_Tcos<<11)+(B5_Tacc<<8)+(B5_Tcoh<<6)+(B5_Tah<<4)+(B5_Tacp<<2)+(B5_PMC))
    .word ((B6_MT<<15)+(B6_Trcd<<2)+(B6_SCAN))
    .word ((B7_MT<<15)+(B7_Trcd<<2)+(B7_SCAN))
    .word ((REFEN<<23)+(TREFMD<<22)+(Trp<<20)+(Trc<<18)+(Tchr<<16)+REFCNT)
    .word 0x32
    .word 0x30
    .word 0x30
#else

  .long 0x22011110     //BWSCON
  .long 0x00000700     //BANKCON0
  .long 0x00000700     //BANKCON1
  .long 0x00000700     //BANKCON2
  .long 0x00000700     //BANKCON3
  .long 0x00000700     //BANKCON4
  .long 0x00000700     //BANKCON5
  .long 0x00018005     //BANKCON6
  .long 0x00018005     //BANKCON7
  .long 0x008C04F4     //REFRESH
  .long 0x000000B1     //BANKSIZE
  .long 0x00000030     //MRSRB6
  .long 0x00000030     //MRSRB7

 #endif
View Code

c、設置串口波特率(get_HCLK函數),亂碼,查看串口波特率的設置,發如今get_HCLK裏沒有定義CONFIG_S3C2440宏

處理措施:在include/configs/smdk2440.h中
//#define CONFIG_S3C2410        /* specifically a SAMSUNG S3C2410 SoC */
//#define CONFIG_SMDK2410        /* on a SAMSUNG SMDK2410 Board */
#define CONFIG_S3C2440        /* specifically a SAMSUNG S3C2440 SoC */
#define CONFIG_SMDK2440        /* on a SAMSUNG SMDK2440 Board */
d、修改UBOOT支持NAND啓動,原來的代碼在連接時加了"-pie"選項, 使得u-boot.bin裏多了"*(.rel*)", "*(.dynsym)"
    使得程序很是大,不利於從NAND啓動(重定位以前的啓動代碼應該少於4K)
arch/arm/config.mk:75:LDFLAGS_u-boot += -pie 去掉這行
把init.c放入board/samsung/smdk2440目錄,修改Makefile,使init.c編譯進去
修改smdk2440.h ,修改CONFIG_SYS_TEXT_BASE爲0x33f80000
#define CONFIG_SYS_TEXT_BASE    0x33f00000
 
init.c
/* NAND FLASH控制器 */
#define NFCONF (*((volatile unsigned long *)0x4E000000))
#define NFCONT (*((volatile unsigned long *)0x4E000004))
#define NFCMMD (*((volatile unsigned char *)0x4E000008))
#define NFADDR (*((volatile unsigned char *)0x4E00000C))
#define NFDATA (*((volatile unsigned char *)0x4E000010))
#define NFSTAT (*((volatile unsigned char *)0x4E000020))

/* GPIO */
#define GPHCON              (*(volatile unsigned long *)0x56000070)
#define GPHUP               (*(volatile unsigned long *)0x56000078)

/* UART registers*/
#define ULCON0              (*(volatile unsigned long *)0x50000000)
#define UCON0               (*(volatile unsigned long *)0x50000004)
#define UFCON0              (*(volatile unsigned long *)0x50000008)
#define UMCON0              (*(volatile unsigned long *)0x5000000c)
#define UTRSTAT0            (*(volatile unsigned long *)0x50000010)
#define UTXH0               (*(volatile unsigned char *)0x50000020)
#define URXH0               (*(volatile unsigned char *)0x50000024)
#define UBRDIV0             (*(volatile unsigned long *)0x50000028)

#define TXD0READY   (1<<2)


void nand_read(unsigned int addr, unsigned char *buf, unsigned int len);


int isBootFromNorFlash(void)
{
    volatile int *p = (volatile int *)0;
    int val;

    val = *p;
    *p = 0x12345678;
    if (*p == 0x12345678)
    {
        /* 寫成功, 是nand啓動 */
        *p = val;
        return 0;
    }
    else
    {
        /* NOR不能像內存同樣寫 */
        return 1;
    }
}

void copy_code_to_sdram(unsigned char *src, unsigned char *dest, unsigned int len)
{    
    int i = 0;
    
    /* 若是是NOR啓動 */
    if (isBootFromNorFlash())
    {
        while (i < len)
        {
            dest[i] = src[i];
            i++;
        }
    }
    else
    {
        //nand_init();
        nand_read((unsigned int)src, dest, len);
    }
}

void clear_bss(void)
{
    extern int __bss_start, __bss_end;
    int *p = &__bss_start;
    
    for (; p < &__bss_end; p++)
        *p = 0;
}

void nand_init(void)
{
#define TACLS   0
#define TWRPH0  1
#define TWRPH1  0
    /* 設置時序 */
    NFCONF = (TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4);
    /* 使能NAND Flash控制器, 初始化ECC, 禁止片選 */
    NFCONT = (1<<4)|(1<<1)|(1<<0);    
}

void nand_select(void)
{
    NFCONT &= ~(1<<1);    
}

void nand_deselect(void)
{
    NFCONT |= (1<<1);    
}

void nand_cmd(unsigned char cmd)
{
    volatile int i;
    NFCMMD = cmd;
    for (i = 0; i < 10; i++);
}

void nand_addr(unsigned int addr)
{
    unsigned int col  = addr % 2048;
    unsigned int page = addr / 2048;
    volatile int i;

    NFADDR = col & 0xff;
    for (i = 0; i < 10; i++);
    NFADDR = (col >> 8) & 0xff;
    for (i = 0; i < 10; i++);
    
    NFADDR  = page & 0xff;
    for (i = 0; i < 10; i++);
    NFADDR  = (page >> 8) & 0xff;
    for (i = 0; i < 10; i++);
    NFADDR  = (page >> 16) & 0xff;
    for (i = 0; i < 10; i++);    
}

void nand_wait_ready(void)
{
    while (!(NFSTAT & 1));
}

unsigned char nand_data(void)
{
    return NFDATA;
}

void nand_read(unsigned int addr, unsigned char *buf, unsigned int len)
{
    int col = addr % 2048;
    int i = 0;
        
    /* 1. 選中 */
    nand_select();

    while (i < len)
    {
        /* 2. 發出讀命令00h */
        nand_cmd(0x00);

        /* 3. 發出地址(分5步發出) */
        nand_addr(addr);

        /* 4. 發出讀命令30h */
        nand_cmd(0x30);

        /* 5. 判斷狀態 */
        nand_wait_ready();

        /* 6. 讀數據 */
        for (; (col < 2048) && (i < len); col++)
        {
            buf[i] = nand_data();
            i++;
            addr++;
        }
        
        col = 0;
    }

    /* 7. 取消選中 */        
    nand_deselect();
}

#define PCLK            50000000    // init.c中的clock_init函數設置PCLK爲50MHz
#define UART_CLK        PCLK        //  UART0的時鐘源設爲PCLK
#define UART_BAUD_RATE  115200      // 波特率
#define UART_BRD        ((UART_CLK  / (UART_BAUD_RATE * 16)) - 1)

/*
 * 初始化UART0
 * 115200,8N1,無流控
 */
void uart0_init(void)
{
    GPHCON  |= 0xa0;    // GPH2,GPH3用做TXD0,RXD0
    GPHUP   = 0x0c;     // GPH2,GPH3內部上拉

    ULCON0  = 0x03;     // 8N1(8個數據位,無較驗,1箇中止位)
    UCON0   = 0x05;     // 查詢方式,UART時鐘源爲PCLK
    UFCON0  = 0x00;     // 不使用FIFO
    UMCON0  = 0x00;     // 不使用流控
    UBRDIV0 = UART_BRD; // 波特率爲115200
}

/*
 * 發送一個字符
 */
void putc(unsigned char c)
{
    /* 等待,直到發送緩衝區中的數據已經所有發送出去 */
    while (!(UTRSTAT0 & TXD0READY));
    
    /* 向UTXH0寄存器中寫入數據,UART即自動將它發送出去 */
    UTXH0 = c;
}

void puts(char *str)
{
    int i = 0;
    while (str[i])
    {
        putc(str[i]);
        i++;
    }
}

void puthex(unsigned int val)
{
    /* 0x1234abcd */
    int i;
    int j;
    
    puts("0x");

    for (i = 0; i < 8; i++)
    {
        j = (val >> ((7-i)*4)) & 0xf;
        if ((j >= 0) && (j <= 9))
            putc('0' + j);
        else
            putc('A' + j - 0xa);
        
    }
    
}
View Code
 
 修改start.S
    修改board_init_f, 把relocate_code去掉
    修改連接腳本: 把start.S, init.c, lowlevel.S等文件放在最前面,
    在./arch/arm/cpu/u-boot.lds文件中
修改成
board/samsung/smdk2440/libsmdk2440.o
e、代碼重定位
    修改board.c文件中的board_init_f函數以下
    /*
     * reserve memory for U-Boot code, data & bss
     * round down to next 4 kB limit
     */
    //addr -= gd->mon_len;
    //addr &= ~(4096 - 1);
    addr = CONFIG_SYS_TEXT_BASE;
    base_sp = addr_sp;
    //relocate_code(addr_sp, id, addr);
    return ( unsigned int )id;
    /* NOTREACHED - relocate_code() does not return */

f、支持NOR-FLASH: 在drivers\mtd\jedec_flash.c 加上新的型號, jedec_table[] 中增長一項匹配板子上的NOR-Flash廠商ID和設備ID

static const struct amd_flash_info jedec_table[] = {
#ifdef CONFIG_SYS_FLASH_LEGACY_256Kx8
    {
        .mfr_id        = (u16)SST_MANUFACT,
        .dev_id        = SST39LF020,
        .name        = "SST 39LF020",
        .uaddr        = {
            [0] = MTD_UADDR_0x5555_0x2AAA /* x8 */
        },
        .DevSize    = SIZE_256KiB,
        .CmdSet        = P_ID_AMD_STD,
        .NumEraseRegions= 1,
        .regions    = {
            ERASEINFO(0x01000,64),
        }
    },
#endif
#ifdef CONFIG_SYS_FLASH_LEGACY_512Kx8
    {
        .mfr_id        = (u16)AMD_MANUFACT,
        .dev_id        = AM29LV040B,
        .name        = "AMD AM29LV040B",
        .uaddr        = {
            [0] = MTD_UADDR_0x0555_0x02AA /* x8 */
        },
        .DevSize    = SIZE_512KiB,
        .CmdSet        = P_ID_AMD_STD,
        .NumEraseRegions= 1,
        .regions    = {
            ERASEINFO(0x10000,8),
        }
    },
    {
        .mfr_id        = (u16)SST_MANUFACT,
        .dev_id        = SST39LF040,
        .name        = "SST 39LF040",
        .uaddr        = {
            [0] = MTD_UADDR_0x5555_0x2AAA /* x8 */
        },
        .DevSize    = SIZE_512KiB,
        .CmdSet        = P_ID_AMD_STD,
        .NumEraseRegions= 1,
        .regions    = {
            ERASEINFO(0x01000,128),
        }
    },
    {
        .mfr_id        = (u16)STM_MANUFACT,
        .dev_id        = STM_ID_M29W040B,
        .name        = "ST Micro M29W040B",
        .uaddr        = {
            [0] = MTD_UADDR_0x0555_0x02AA /* x8 */
        },
        .DevSize    = SIZE_512KiB,
        .CmdSet        = P_ID_AMD_STD,
        .NumEraseRegions= 1,
        .regions    = {
            ERASEINFO(0x10000,8),
        }
    },
    {
        .mfr_id        = (u16)MX_MANUFACT,
        .dev_id        = MX29LV040,
        .name        = "MXIC MX29LV040",
        .uaddr        = {
            [0] = MTD_UADDR_0x0555_0x02AA /* x8 */
        },
        .DevSize    = SIZE_512KiB,
        .CmdSet        = P_ID_AMD_STD,
        .NumEraseRegions= 1,
        .regions    = {
            ERASEINFO(0x10000, 8),
        }
    },
    {
        .mfr_id        = (u16)WINB_MANUFACT,
        .dev_id        = W39L040A,
        .name        = "WINBOND W39L040A",
        .uaddr        = {
            [0] = MTD_UADDR_0x5555_0x2AAA /* x8 */
        },
        .DevSize    = SIZE_512KiB,
        .CmdSet        = P_ID_AMD_STD,
        .NumEraseRegions= 1,
        .regions    = {
            ERASEINFO(0x10000, 8),
        }
    },
    {
        .mfr_id        = (u16)AMIC_MANUFACT,
        .dev_id        = A29L040,
        .name        = "AMIC A29L040",
        .uaddr        = {
            [0] = MTD_UADDR_0x0555_0x02AA /* x8 */
        },
        .DevSize    = SIZE_512KiB,
        .CmdSet        = P_ID_AMD_STD,
        .NumEraseRegions= 1,
        .regions    = {
            ERASEINFO(0x10000, 8),
        }
    },
    {
        .mfr_id        = (u16)EON_MANUFACT,
        .dev_id        = EN29LV040A,
        .name        = "EON EN29LV040A",
        .uaddr        = {
            [0] = MTD_UADDR_0x0555_0x02AA /* x8 */
        },
        .DevSize    = SIZE_512KiB,
        .CmdSet        = P_ID_AMD_STD,
        .NumEraseRegions= 1,
        .regions    = {
            ERASEINFO(0x10000, 8),
        }
    },
#endif
#ifdef CONFIG_SYS_FLASH_LEGACY_512Kx16
    {
        .mfr_id        = (u16)AMD_MANUFACT,
        .dev_id        = AM29F400BB,
        .name        = "AMD AM29F400BB",
        .uaddr        = {
            [1] = MTD_UADDR_0x0555_0x02AA /* x16 */
        },
        .DevSize    = SIZE_512KiB,
        .CmdSet        = CFI_CMDSET_AMD_LEGACY,
        .NumEraseRegions= 4,
        .regions    = {
            ERASEINFO(0x04000, 1),
            ERASEINFO(0x02000, 2),
            ERASEINFO(0x08000, 1),
            ERASEINFO(0x10000, 7),
        }
    },
    {
        .mfr_id        = (u16)AMD_MANUFACT,
        .dev_id        = AM29LV400BB,
        .name        = "AMD AM29LV400BB",
        .uaddr        = {
            [1] = MTD_UADDR_0x0555_0x02AA /* x16 */
        },
        .DevSize    = SIZE_512KiB,
        .CmdSet        = CFI_CMDSET_AMD_LEGACY,
        .NumEraseRegions= 4,
        .regions    = {
            ERASEINFO(0x04000,1),
            ERASEINFO(0x02000,2),
            ERASEINFO(0x08000,1),
            ERASEINFO(0x10000,7),
        }
    },
    {
        .mfr_id        = (u16)AMD_MANUFACT,
        .dev_id        = AM29LV800BB,
        .name        = "AMD AM29LV800BB",
        .uaddr        = {
            [1] = MTD_UADDR_0x0555_0x02AA /* x16 */
        },
        .DevSize    = SIZE_1MiB,
        .CmdSet        = CFI_CMDSET_AMD_LEGACY,
        .NumEraseRegions= 4,
        .regions    = {
            ERASEINFO(0x04000, 1),
            ERASEINFO(0x02000, 2),
            ERASEINFO(0x08000, 1),
            ERASEINFO(0x10000, 15),
        }
    },
    {
        .mfr_id        = (u16)STM_MANUFACT,
        .dev_id        = STM29F400BB,
        .name        = "ST Micro M29F400BB",
        .uaddr        = {
            [1] = MTD_UADDR_0x0555_0x02AA /* x16 */
        },
        .DevSize        = SIZE_512KiB,
        .CmdSet            = CFI_CMDSET_AMD_LEGACY,
        .NumEraseRegions    = 4,
        .regions        = {
            ERASEINFO(0x04000, 1),
            ERASEINFO(0x02000, 2),
            ERASEINFO(0x08000, 1),
            ERASEINFO(0x10000, 7),
        }
    },
#endif

    //JZ2440
    {
        .mfr_id        = (u16)MX_MANUFACT,  
        .dev_id        = 0x2249,
        .name        = "MXIC MX29LV160DB",
        .uaddr        = {
            [1] = MTD_UADDR_0x0555_0x02AA /* x16 */
        },
        .DevSize    = SIZE_2MiB,
        .CmdSet        = P_ID_AMD_STD,
        .NumEraseRegions= 4,
        .regions    = {
            ERASEINFO(16*1024,1),
            ERASEINFO(8*1024,2),
            ERASEINFO(32*1024,1),
            ERASEINFO(64*1024,31),
        }
    }

};
View Code

 

在上面代碼中最後增長JZ2440的Nor flash
在smdk2440.h 中修改
#define CONFIG_SYS_MAX_FLASH_SECT    (128)

驗證是否支持Nor flash

flinfo : 查看flash信息,RO塊經過"protect off all"指令後擦寫。

    測試一下norflash可否正確讀寫,用如下u-boot命令:

    cp.b 0 30000000 80
    cmp.b 0 30000000 80 
    發現讀norflash沒有問題。再用如下幾條命令測試寫norflash:
    mw.b 30000000 12 3
    protect off all
    erase 0 ffff
    cp.b 30000000 0 3
    md.b 0 3
    發現也是121212;所以寫norflash成功,至此u-boot已經支持JZ2440開發板的norflash。
 
g、修改UBOOT支持NAND FLASH
修復了重定時留下來的BUG:SP要從新設置,在start.S文件中作以下修改
/* Set stackpointer in internal RAM to call board_init_f */

call_board_init_f:

    ldr    r0,=0x00000000
    bl    board_init_f

/* unsigned int的值存在r0,正好給board_init_r做爲參數用 */
    ldr r1,_TEXT_BASE
    ldr sp,base_sp
/* 調用第二階段的代碼 */
    bl board_init_r

.globl base_sp
base_sp:
    .long 0

啓動cache後就初始化nandflash

#ifndef CONFIG_SKIP_LOWLEVEL_INIT
    bl    cpu_init_crit
#endif
ldr sp, =(CONFIG_SYS_INIT_SP_ADDR)
bic sp, sp, #7 /* 8-byte alignment for ABI compliance */

bl nand_init_ll
修改:include/configs/smdk2440.h: #define CONFIG_CMD_NAND,把drivers\mtd\nand\s3c2410_nand.c複製爲s3c2440_nand.c
修改此文件裏代碼以下:將以s3c2410開頭函數名或變量名修改成以s3c2440開頭
static void s3c2440_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
{
    struct nand_chip *chip = mtd->priv;
    struct s3c2440_nand *nand = s3c2440_get_base_nand();
    if( ctrl&NAND_CLE)
    {
        /* 發命令 */
        writeb(cmd,&nand->nfcmd);
    }
    else if( ctrl&NAND_ALE)
    {
        /* 發地址 */
        writeb(cmd,&nand->nfaddr);
    }

}
int board_nand_init(struct nand_chip *nand)
{
    u_int32_t cfg;
    u_int8_t tacls, twrph0, twrph1;
    struct s3c24x0_clock_power *clk_power = s3c24x0_get_base_clock_power();
    struct s3c2440_nand *nand_reg = s3c2440_get_base_nand();

    debug("board_nand_init()\n");

    writel(readl(&clk_power->clkcon) | (1 << 4), &clk_power->clkcon);

    /* initialize hardware */
#if defined(CONFIG_S3C24XX_CUSTOM_NAND_TIMING)
    tacls  = CONFIG_S3C24XX_TACLS;
    twrph0 = CONFIG_S3C24XX_TWRPH0;
    twrph1 =  CONFIG_S3C24XX_TWRPH1;
#else
    tacls = 4;
    twrph0 = 8;
    twrph1 = 8;
#endif
#if 0
    cfg = S3C2410_NFCONF_EN;
    cfg |= S3C2410_NFCONF_TACLS(tacls - 1);
    cfg |= S3C2410_NFCONF_TWRPH0(twrph0 - 1);
    cfg |= S3C2410_NFCONF_TWRPH1(twrph1 - 1);
#endif
    /* 設置時序 */
    cfg = ((tacls-1)<<12)|((twrph0-1)<<8)|((twrph1-1)<<4);    
    writel(cfg, &nand_reg->nfconf);
    /* 使能NAND Flash控制器, 初始化ECC, 禁止片選 */
    writel((1<<4)|(1<<1)|(1<<0), &nand_reg->nfcont);

    /* initialize nand_chip data structure */
    nand->IO_ADDR_R = (void *)&nand_reg->nfdata;
    nand->IO_ADDR_W = (void *)&nand_reg->nfdata;

    nand->select_chip = s3c2440_nand_select;

    /* read_buf and write_buf are default */
    /* read_byte and write_byte are default */
#ifdef CONFIG_NAND_SPL
    nand->read_buf = nand_read_buf;
#endif

    /* hwcontrol always must be implemented */
    nand->cmd_ctrl = s3c2440_hwcontrol;

    nand->dev_ready = s3c2440_dev_ready;

#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_HW;
    nand->ecc.size = CONFIG_SYS_NAND_ECCSIZE;
    nand->ecc.bytes = CONFIG_SYS_NAND_ECCBYTES;
#else
    nand->ecc.mode = NAND_ECC_SOFT;
#endif

#ifdef CONFIG_S3C2410_NAND_BBT
    nand->options = NAND_USE_FLASH_BBT;
#else
    nand->options = 0;
#endif

    debug("end of nand_init\n");

    return 0;
}
View Code

 

h、支持DM9000網卡
啓動uboot,打印出Net: CS8900-0,而咱們的網卡是DM9000,因而在代碼中搜索「Net:」,定位到common/board_r.c的initr_net函數,一路追蹤eth_initialize, eth_common_init,一直到 board\samsung\smdk2440\smdk2440.c的board_eth_init函數,這裏是對CS8900進行了初始化,咱們要對DM9000進行初始化,經過查看drivers/net/Makefile,發現要包含dm9000x.c的文件,要定義CONFIG_DRIVER_DM9000這個宏,咱們也要註釋掉CONFIG_CS8900宏。同時查看dm9000x.c,裏面有一個dm9000_initialize函數,因而仿照cs8900來寫dm9000的初始化函數。
#ifdef CONFIG_CMD_NET
int board_eth_init(bd_t *bis)
{
    int rc = 0;
#ifdef CONFIG_CS8900
    rc = cs8900_initialize(0, CONFIG_CS8900_BASE);
#endif
#ifdef CONFIG_DRIVER_DM9000
    rc = dm9000_initialize(&bis);
#endif
    return rc;
}
#endif

配置文件smdk2440.h修改以下:

/*
 * Hardware drivers
 */

#if 0
#define CONFIG_CS8900        /* we have a CS8900 on-board */
#define CONFIG_CS8900_BASE    0x19000300
#define CONFIG_CS8900_BUS16    /* the Linux driver does accesses as shorts */
#else
#define CONFIG_DRIVER_DM9000
#define CONFIG_DM9000_BASE 0x20000000
#define DM9000_IO CONFIG_DM9000_BASE
#define DM9000_DATA CONFIG_DM9000_BASE + 4

#endif

設置CONFIG_ETHADDR宏,根據本身狀況配置

#define CONFIG_ETHADDR 00:0c:29:8d:73:b1

保存,編譯,燒寫,啓動Uboot,網卡正常啓動。

4、nand flash 分區
在smdk2440.h文件中,修改如下代碼
#if 0
#define CONFIG_ENV_ADDR            (CONFIG_SYS_FLASH_BASE + 0x070000)
#define CONFIG_ENV_IS_IN_FLASH
#define CONFIG_ENV_SIZE            0x10000
/* allow to overwrite serial and ethaddr */
#define CONFIG_ENV_OVERWRITE
#endif
#define CONFIG_ENV_IS_IN_NAND
#define CONFIG_ENV_OFFSET 0x00040000
#define CONFIG_ENV_SIZE 0x20000
#define CONFIG_ENV_RANGE CONFIG_ENV_SIZE

#define CONFIG_CMD_MTDPARTS
#define CONFIG_MTD_DEVICE
#define MTDIDS_DEFAULT        "nand0=jz2440-0" /* 哪個設備 */

#define MTDPARTS_DEFAULT    "mtdparts=jz2440-0:256k(bootloader),"    \
                        "128k(params),"        \
                        "4m(kernel),"    \
                        "-(rootfs)"        \

至此u-boot的移植基本完成。

相關文章
相關標籤/搜索