Chinaunix首页 | 论坛 | 博客
  • 博客访问: 6682
  • 博文数量: 3
  • 博客积分: 120
  • 博客等级: 入伍新兵
  • 技术积分: 40
  • 用 户 组: 普通用户
  • 注册时间: 2010-08-07 14:29
文章分类
文章存档

2010年(3)

我的朋友
最近访客

分类: 嵌入式

2010-09-16 09:31:31

QQ2440开发板上的移植

u-boot-1.1.6.tar.bz2解压,得到文件夹u-boot-1.1.6

采用交叉编译器arm-linux-gcc 3.4.1

1阶段测试环境是否正确搭建

1)、在u-boot-1.1.6/board下找个与QQ2440相似的开发板,这里选smdk2410

2)、将u-boot-1.1.6/board/smdk2410目录复制到board目录下,并改名为QQ2440

3)、把smdk2410.c改名为QQ2440.c,修改Makefile中的 COBJS := QQ2440.o flash.o,保存。

4)、将u-boot-1.1.6/include/configs/smdk2410.h,复制到include/configs目录,并改名为QQ2440.h

6)、在u-boot-1.1.6/Makefile中添加

2440_config : unconfig

 @$(MKCONFIG) $(@:_config=) arm arm920t QQ2440 NULL s3c24x0

7)、打开超级终端,切换到u-boot-1.1.6目录,敲入命令

# make QQ2440_config

Configuring for 2440 board...

8)、之后就可以# make了,如正常编译通过,表明环境搭建好。

2阶段修改文件

接下来进入移植当中最为繁琐也最考验一个人耐心的阶段,修改文件。

(这里没有定义config_s3c2440,用的是config_s3c2410,但实际上是s3c2440的配置)

126行添加中断模式寄存器的定义:

# define INTMOD     0X4A000004  

146

# if defined(CONFIG_S3C2410)

       ldr   r1, =0x3ff   

       ldr   r0, =INTSUBMSK

       str    r1, [r0]

# endif

改为:

# if defined(CONFIG_S3C2410)

       ldr   r1, =0x7fff         /*15位的中断*/

       ldr   r0, =INTSUBMSK

       str    r1, [r0]

# endif

150行注释掉时钟设置(因为在下面我们调用子函数完成)

#if 0

       /* FCLK:HCLK:PCLK = 1:4:8 */

       /* default FCLK is 120 MHz ! */

       ldr   r0, =CLKDIVN

       mov r1, #3

       str    r1, [r0]

#endif

168行将堆栈设置提到前面以便后面C函数clock_init的调用。

       /* Set up the stack                                         */

stack_setup:

       ldr   r0, _TEXT_BASE         /* upper 128 KiB: relocated uboot   */

       sub  r0, r0, #CFG_MALLOC_LEN      /* malloc area                      */

       sub  r0, r0, #CFG_GBL_DATA_SIZE /* bdinfo                        */

       sub  sp, r0, #12             /* leave 3 words for abort-stack    */

    bl clock_init     /*初始化系统时钟,自己添加的函数*/

185行(因为堆栈在前面已经设置)

       beq     stack_setup

改为

       beq     clear_bss

190

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

改为:(CopyCode2Ram函数在board/QQ2440\boot_init下。boot_init文件自己添加)

#if 1

       bl  CopyCode2Ram      /* r0: source, r1: dest, r2: size */

#else

       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

208行注释掉堆栈设置

/* Set up the stack                                         */

/*stack_setup:*/

/*    ldr   r0, _TEXT_BASE           // upper 128 KiB: relocated uboot   */

/*    sub  r0, r0, #CFG_MALLOC_LEN      // malloc area                      */

/*    sub  r0, r0, #CFG_GBL_DATA_SIZE // bdinfo                        */

/* #ifdef CONFIG_USE_IRQ  */

/*    sub  r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ) */

/*  #endif  */

/*    sub  sp, r0, #12             //  leave 3 words for abort-stack    */

board/QQ2440/lowlevel.init.S

54行(bank1IDE,Nor Flash32位,nand Flash16位)

#define B1_BWSCON         (DW32)

改为:

#define B1_BWSCON         (DW16)

126行(修改存储器刷新计数值)

#define REFCNT    1113 /* period="15".6us, HCLK="60Mhz", (2048+1-15.6*60) */

改为:

#define REFCNT     0x4f4  /* period=7.8125us, HCLK=100Mhz, (2048+1-7.8125*100) */

include/congifs/QQ2440.h

74行添加(调用内核使用到)

#define CONFIG_SETUP_MEMORY_TAGS    1

#define CONFIG_CMDLINE_TAG          1

81行添加三条命令

#define CONFIG_COMMANDS \

                        (CONFIG_CMD_DFL  | \

                        CFG_CMD_CACHE    | \

/*************lihuistart********/\

                        CFG_CMD_PING     | \

                        CFG_CMD_JFFS2    | \

                        CFG_CMD_NAND     | \

/* End: *lihui************/ \

                        /*CFG_CMD_NAND   |*/ \

                        /*CFG_CMD_EEPROM |*/ \

                        /*CFG_CMD_I2C    |*/ \

                        /*CFG_CMD_USB    |*/ \

                        CFG_CMD_REGINFO  | \

                        CFG_CMD_DATE     | \

                        CFG_CMD_ELF)

98行修改网口配置

#define CONFIG_BOOTARGS         "root=ramfs devfs=mount console=ttySA0,9600" *

#define CONFIG_ETHADDR      08:00:3e:26:0a:5b *

#define CONFIG_NETMASK          255.255.255.0

#define CONFIG_IPADDR          10.0.0.110

#define CONFIG_SERVERIP             10.0.0.1

#define CONFIG_BOOTFILE      "elinos-lart" *

#define CONFIG_BOOTCOMMAND  "tftp; bootm"

/*****************************************lihui*****/

#define CONFIG_BOOTARGS  "noinitrd root=/dev/mtdblock2 init=/linuxrc console=ttySAC0"

#define CONFIG_ETHADDR          08:00:3e:26:0a:5b

#define CONFIG_NETMASK       255.255.255.0

#define CONFIG_IPADDR          192.168.1.17

#define CONFIG_SERVERIP             192.168.1.106

/*#define CONFIG_BOOTFILE   "elinos-lart" */

#define CONFIG_BOOTCOMMAND  "nboot 0x320000000 0x50000; bootm 0x32000000"

182行修改输出文字

#define    CFG_PROMPT             "sdmk2410#"  /* Monitor Command Prompt       */

改为:

#define    CFG_PROMPT             "QQ2440> "   /* Monitor Command Prompt       */

180行修改flash选择

#define CONFIG_AMD_LV400    1     /* uncomment this if you have a LV400 flash */

#if 0

#define CONFIG_AMD_LV800    1     /* uncomment this if you have a LV800 flash */

#endif

改为

#if 0

#define CONFIG_AMD_LV400    1     /* uncomment this if you have a LV400 flash */

#endif

#define CONFIG_AMD_LV800    1     /* uncomment this if you have a LV800 flash */

在最后添加Nand Flash设置

/*NAND flash settings */

#define CFG_NAND_BASE           0    //随便设

#define CFG_MAX_NAND_DEVICE     1  //设备数1

#define NAND_MAX_CHIPS          1   //片数1

board/QQ2440/QQ2440.c

23行有关时钟定义修改为:

#define S3C2440_MPLL_400MHZ     0x7f021

#define S3C2440_MPLL_200MHZ     ((0x5c<<12)|(0x01<<4)|(0x02))

#define S3C2440_MPLL_100MHZ     ((0x5c<<12)|(0x01<<4)|(0x03))

#define S3C2440_UPLL_48MHZ      ((0x38<<12)|(0x02<<4)|(0x02))

#define S3C2440_CLKDIV         0x05   /* FCLK:HCLK:PCLK = 1:4:8, UCLK = UPLL */

#define S3C2440_CLKDIV188       0x04    /* FCLK:HCLK:PCLK = 1:8:8 */

#define S3C2440_CAMDIVN188      ((0<<8)|(1<<9)) /* FCLK:HCLK:PCLK = 1:8:8 */

/* S3C2410: Mpll,Upll = (m * Fin) / (p * 2^s)

 * m = M (the value for divider M)+ 8, p = P (the value for divider P) + 2

 */

#define S3C2410_MPLL_200MHZ     ((0x5c<<12)|(0x04<<4)|(0x00))

#define S3C2410_UPLL_48MHZ      ((0x28<<12)|(0x01<<4)|(0x02))

#define S3C2410_CLKDIV          0x03    /* FCLK:HCLK:PCLK = 1:2:4 */

66行在board_init函数中注释掉原有的时钟配置

/* to reduce PLL lock time, adjust the LOCKTIME register */

/*    clk_power->LOCKTIME = 0xFFFFFF;*/

       /* configure MPLL */

/*    clk_power->MPLLCON = ((M_MDIV << 12) + (M_PDIV << 4) + M_SDIV);*/

       /* some delay between MPLL and UPLL */

/*    delay (4000);*/

       /* configure UPLL */

/*    clk_power->UPLLCON = ((U_M_MDIV << 12) + (U_M_PDIV << 4) + U_M_SDIV);*/

       /* some delay between MPLL and UPLL */

添加:

/* support both of S3C2410 and S3C2440, by */

    if ((gpio->GSTATUS1 == 0x32410000) || (gpio->GSTATUS1 == 0x32410002))

    {

        /* FCLK:HCLK:PCLK = 1:2:4 */

        clk_power->CLKDIVN = S3C2410_CLKDIV;

 

        /* change to asynchronous bus mod */

        __asm__(    "mrc    p15, 0, r1, c1, c0, 0\n"    /* read ctrl register   */ 

                    "orr    r1, r1, #0xc0000000\n"      /* Asynchronous         */ 

                    "mcr    p15, 0, r1, c1, c0, 0\n"    /* write ctrl register  */ 

                    :::"r1"

                    );

       

        /* to reduce PLL lock time, adjust the LOCKTIME register */

        clk_power->LOCKTIME = 0xFFFFFF;

 

        /* configure MPLL */

        clk_power->MPLLCON = S3C2410_MPLL_200MHZ;

 

        /* some delay between MPLL and UPLL */

        delay (4000);

 

        /* configure UPLL */

        clk_power->UPLLCON = S3C2410_UPLL_48MHZ;

 

        /* some delay between MPLL and UPLL */

        delay (8000);

       

        /* arch number of SMDK2410-Board */

        gd->bd->bi_arch_number = MACH_TYPE_SMDK2410;

    }

    else

    {

#if 1

        /* FCLK:HCLK:PCLK = 1:4:8 */

        clk_power->CLKDIVN = S3C2440_CLKDIV;

#else

        /* FCLK:HCLK:PCLK = 1:8:8 */

        clk_power->CLKDIVN = S3C2440_CLKDIV188;

        clk_power->CAMDIVN = S3C2440_CAMDIVN188;

#endif

 

        /* change to asynchronous bus mod */

        __asm__(    "mrc    p15, 0, r1, c1, c0, 0\n"    /* read ctrl register   */ 

                    "orr    r1, r1, #0xc0000000\n"      /* Asynchronous         */ 

                    "mcr    p15, 0, r1, c1, c0, 0\n"    /* write ctrl register  */ 

                    :::"r1"

                    );

 

        /* to reduce PLL lock time, adjust the LOCKTIME register */

        clk_power->LOCKTIME = 0xFFFFFF;

 

        /* configure MPLL */

        clk_power->MPLLCON = S3C2440_MPLL_400MHZ;

 

        /* some delay between MPLL and UPLL */

        delay (4000);

 

        /* configure UPLL */

        clk_power->UPLLCON = S3C2440_UPLL_48MHZ;

 

        /* some delay between MPLL and UPLL */

        delay (8000);

       

        /* arch number of QQ2440-Board */

        gd->bd->bi_arch_number = MACH_TYPE_S3C2440;

    }

include/s3c24x0.h

129行在结构体s3c24x0_clock_power中添加CAMDIVN(分频用)

typedef struct {

       S3C24X0_REG32  LOCKTIME;

       S3C24X0_REG32  MPLLCON;

       S3C24X0_REG32  UPLLCON;

       S3C24X0_REG32  CLKCON;

       S3C24X0_REG32  CLKSLOW;

       S3C24X0_REG32  CLKDIVN;

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

改为:

typedef struct {

       S3C24X0_REG32  LOCKTIME;

       S3C24X0_REG32  MPLLCON;

       S3C24X0_REG32  UPLLCON;

       S3C24X0_REG32  CLKCON;

       S3C24X0_REG32  CLKSLOW;

       S3C24X0_REG32  CLKDIVN;

    S3C24X0_REG32  CAMDIVN;    /* for s3c2440 */

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

170添加Nand结构体的定义

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

        S3C24X0_REG32  NFMECCD1;

        S3C24X0_REG32  NFSECCD;

       S3C24X0_REG32  NFSTAT;

        S3C24X0_REG32  NFESTAT0;

        S3C24X0_REG32  NFESTAT1;

        S3C24X0_REG32  NFMECC0;

        S3C24X0_REG32  NFMECC1;

        S3C24X0_REG32  NFSECC;

       S3C24X0_REG32  NFSBLK;

        S3C24X0_REG32  NFEBLK;

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

include/s3c2410.h

100行添加获取s3c2440_NAND基址的函数

/* for s3c2440*/

static inline S3C2440_NAND * const S3C2440_GetBase_NAND(void)

{

       return (S3C2440_NAND * const)S3C2410_NAND_BASE;

}

1)      cpu/arm920t/s3c24x0/speed.c

41行添加全局变量声明

DECLARE_GLOBAL_DATA_PTR;

70行注释掉

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

改为

  /* support both of S3C2410 and S3C2440 */

    if (gd->bd->bi_arch_number == MACH_TYPE_SMDK2410)

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

    else

        return((CONFIG_SYS_CLK_FREQ * m * 2) / (p << s));   /* S3C2440 */

87行添加s3c2440_clkdivn的配置定义

/* for s3c2440 */

#define S3C2440_CLKDIVN_PDIVN        (1<<0)

#define S3C2440_CLKDIVN_HDIVN_MASK   (3<<1)

#define S3C2440_CLKDIVN_HDIVN_1      (0<<1)

#define S3C2440_CLKDIVN_HDIVN_2      (1<<1)

#define S3C2440_CLKDIVN_HDIVN_4_8    (2<<1)

#define S3C2440_CLKDIVN_HDIVN_3_6    (3<<1)

#define S3C2440_CLKDIVN_UCLK         (1<<3)

 

#define S3C2440_CAMDIVN_CAMCLK_MASK  (0xf<<0)

#define S3C2440_CAMDIVN_CAMCLK_SEL   (1<<4)

#define S3C2440_CAMDIVN_HCLK3_HALF   (1<<8)

#define S3C2440_CAMDIVN_HCLK4_HALF   (1<<9)

#define S3C2440_CAMDIVN_DVSEN        (1<<12)

105行函数get_HCLK修改为:

ulong get_HCLK(void)

{

    S3C24X0_CLOCK_POWER * const clk_power = S3C24X0_GetBase_CLOCK_POWER();

/* support both of S3C2410 and S3C2440*/

 

    unsigned long clkdiv;

    unsigned long camdiv;

    int hdiv = 1;

 

    if (gd->bd->bi_arch_number == MACH_TYPE_SMDK2410)

        return((clk_power->CLKDIVN & 0x2) ? get_FCLK()/2 : get_FCLK());

    else

    {

        clkdiv = clk_power->CLKDIVN;

        camdiv = clk_power->CAMDIVN;

 

        /* work out clock scalings */

 

        switch (clkdiv & S3C2440_CLKDIVN_HDIVN_MASK) {

        case S3C2440_CLKDIVN_HDIVN_1:

            hdiv = 1;

            break;

 

        case S3C2440_CLKDIVN_HDIVN_2:

            hdiv = 2;

            break;

 

        case S3C2440_CLKDIVN_HDIVN_4_8:

            hdiv = (camdiv & S3C2440_CAMDIVN_HCLK4_HALF) ? 8 : 4;

            break;

 

        case S3C2440_CLKDIVN_HDIVN_3_6:

            hdiv = (camdiv & S3C2440_CAMDIVN_HCLK3_HALF) ? 6 : 3;

            break;

        }

 

        return get_FCLK() / hdiv;

    }

}

149get_PCLK函数修改为:

ulong get_PCLK(void)

{

    S3C24X0_CLOCK_POWER * const clk_power = S3C24X0_GetBase_CLOCK_POWER();

    unsigned long clkdiv;

    unsigned long camdiv;

    int hdiv = 1;

 

    /* support both of S3C2410 and S3C2440,*/

    if (gd->bd->bi_arch_number == MACH_TYPE_SMDK2410)

        return((clk_power->CLKDIVN & 0x1) ? get_HCLK()/2 : get_HCLK());

    else

    {  

        clkdiv = clk_power->CLKDIVN;

        camdiv = clk_power->CAMDIVN;

 

        /* work out clock scalings */

 

        switch (clkdiv & S3C2440_CLKDIVN_HDIVN_MASK) {

        case S3C2440_CLKDIVN_HDIVN_1:

            hdiv = 1;

            break;

 

        case S3C2440_CLKDIVN_HDIVN_2:

            hdiv = 2;

            break;

 

        case S3C2440_CLKDIVN_HDIVN_4_8:

            hdiv = (camdiv & S3C2440_CAMDIVN_HCLK4_HALF) ? 8 : 4;

            break;

 

        case S3C2440_CLKDIVN_HDIVN_3_6:

            hdiv = (camdiv & S3C2440_CAMDIVN_HCLK3_HALF) ? 6 : 3;

            break;

        }

 

        return get_FCLK() / hdiv / ((clkdiv & S3C2440_CLKDIVN_PDIVN)? 2:1);

    }       

}

下添加boot_init.c文件

修改当前目录下的Makefile中的 COBJS := QQ2440.o flash.o

COBJS := QQ2440.o flash.o boot_init.o

内容如下:

#include

#include

 

#define GSTATUS1        (*(volatile unsigned int *)0x560000B0)

#define BUSY            1

 

/* 供外部调用的函数 */

void nand_init_ll(void);

void nand_read_ll(unsigned char *buf, unsigned long start_addr, int size);

 

/* NAND Flash操作的总入口, 它们将调用S3C2410S3C2440的相应函数 */

static void nand_reset(void);

static void wait_idle(void);

static void nand_select_chip(void);

static void nand_deselect_chip(void);

static void write_cmd(int cmd);

static void write_addr(unsigned int addr);

static unsigned char read_data(void);

 

/* S3C2410NAND Flash处理函数 */

static void s3c2410_nand_reset(void);

static void s3c2410_wait_idle(void);

static void s3c2410_nand_select_chip(void);

static void s3c2410_nand_deselect_chip(void);

static void s3c2410_write_cmd(int cmd);

static void s3c2410_write_addr(unsigned int addr);

static unsigned char s3c2410_read_data(void);

 

/* S3C2440NAND Flash处理函数 */

static void s3c2440_nand_reset(void);

static void s3c2440_wait_idle(void);

static void s3c2440_nand_select_chip(void);

static void s3c2440_nand_deselect_chip(void);

static void s3c2440_write_cmd(int cmd);

static void s3c2440_write_addr(unsigned int addr);

static unsigned char s3c2440_read_data(void);

 

/* S3C2410NAND Flash操作函数 */

 

/* 复位 */

static void s3c2410_nand_reset(void)

{

    s3c2410_nand_select_chip();

    s3c2410_write_cmd(0xff);  // 复位命令

    s3c2410_wait_idle();

    s3c2410_nand_deselect_chip();

}

 

/* 等待NAND Flash就绪 */

static void s3c2410_wait_idle(void)

{

    int i;

       S3C2410_NAND * s3c2410nand = (S3C2410_NAND *)0x4e000000;

      

    volatile unsigned char *p = (volatile unsigned char *)&s3c2410nand->NFSTAT;

    while(!(*p & BUSY))

        for(i=0; i<10; i++);

}

 

/* 发出片选信号 */

static void s3c2410_nand_select_chip(void)

{

    int i;

       S3C2410_NAND * s3c2410nand = (S3C2410_NAND *)0x4e000000;

 

    s3c2410nand->NFCONF &= ~(1<<11);

    for(i=0; i<10; i++);   

}

 

/* 取消片选信号 */

static void s3c2410_nand_deselect_chip(void)

{

       S3C2410_NAND * s3c2410nand = (S3C2410_NAND *)0x4e000000;

 

    s3c2410nand->NFCONF |= (1<<11);

}

 

/* 发出命令 */

static void s3c2410_write_cmd(int cmd)

{

       S3C2410_NAND * s3c2410nand = (S3C2410_NAND *)0x4e000000;

 

    volatile unsigned char *p = (volatile unsigned char *)&s3c2410nand->NFCMD;

    *p = cmd;

}

 

/* 发出地址 */

static void s3c2410_write_addr(unsigned int addr)

{

    int i;

       S3C2410_NAND * s3c2410nand = (S3C2410_NAND *)0x4e000000;

    volatile unsigned char *p = (volatile unsigned char *)&s3c2410nand->NFADDR;

   

    *p = addr & 0xff;

    for(i=0; i<10; i++);

    *p = (addr >> 9) & 0xff;

    for(i=0; i<10; i++);

    *p = (addr >> 17) & 0xff;

    for(i=0; i<10; i++);

    *p = (addr >> 25) & 0xff;

    for(i=0; i<10; i++);

}

 

/* 读取数据 */

static unsigned char s3c2410_read_data(void)

{

       S3C2410_NAND * s3c2410nand = (S3C2410_NAND *)0x4e000000;

 

    volatile unsigned char *p = (volatile unsigned char *)&s3c2410nand->NFDATA;

    return *p;

}

 

/* S3C2440NAND Flash操作函数 */

 

/* 复位 */

static void s3c2440_nand_reset(void)

{

    s3c2440_nand_select_chip();

    s3c2440_write_cmd(0xff);  // 复位命令

    s3c2440_wait_idle();

    s3c2440_nand_deselect_chip();

}

 

/* 等待NAND Flash就绪 */

static void s3c2440_wait_idle(void)

{

    int i;

       S3C2440_NAND * s3c2440nand = (S3C2440_NAND *)0x4e000000;

    volatile unsigned char *p = (volatile unsigned char *)&s3c2440nand->NFSTAT;

 

    while(!(*p & BUSY))

        for(i=0; i<10; i++);

}

 

/* 发出片选信号 */

static void s3c2440_nand_select_chip(void)

{

    int i;

       S3C2440_NAND * s3c2440nand = (S3C2440_NAND *)0x4e000000;

 

    s3c2440nand->NFCONT &= ~(1<<1);

    for(i=0; i<10; i++);   

}

 

/* 取消片选信号 */

static void s3c2440_nand_deselect_chip(void)

{

       S3C2440_NAND * s3c2440nand = (S3C2440_NAND *)0x4e000000;

 

    s3c2440nand->NFCONT |= (1<<1);

}

 

/* 发出命令 */

static void s3c2440_write_cmd(int cmd)

{

       S3C2440_NAND * s3c2440nand = (S3C2440_NAND *)0x4e000000;

 

    volatile unsigned char *p = (volatile unsigned char *)&s3c2440nand->NFCMD;

    *p = cmd;

}

 

/* 发出地址 */

static void s3c2440_write_addr(unsigned int addr)

{

    int i;

       S3C2440_NAND * s3c2440nand = (S3C2440_NAND *)0x4e000000;

    volatile unsigned char *p = (volatile unsigned char *)&s3c2440nand->NFADDR;

   

    *p = addr & 0xff;

    for(i=0; i<10; i++);

    *p = (addr >> 9) & 0xff;

    for(i=0; i<10; i++);

    *p = (addr >> 17) & 0xff;

    for(i=0; i<10; i++);

    *p = (addr >> 25) & 0xff;

    for(i=0; i<10; i++);

}

 

/* 读取数据 */

static unsigned char s3c2440_read_data(void)

{

       S3C2440_NAND * s3c2440nand = (S3C2440_NAND *)0x4e000000;

    volatile unsigned char *p = (volatile unsigned char *)&s3c2440nand->NFDATA;

    return *p;

}

 

 

/* 在第一次使用NAND Flash前,复位一下NAND Flash */

static void nand_reset(void)

{

    /* 判断是S3C2410还是S3C2440 */

    if ((GSTATUS1 == 0x32410000) || (GSTATUS1 == 0x32410002))

       {

           s3c2410_nand_reset();

       }

       else

       {

           s3c2440_nand_reset();

       }

}

 

static void wait_idle(void)

{

    /* 判断是S3C2410还是S3C2440 */

    if ((GSTATUS1 == 0x32410000) || (GSTATUS1 == 0x32410002))

       {

           s3c2410_wait_idle();

       }

       else

       {

           s3c2440_wait_idle();

       }

}

 

static void nand_select_chip(void)

{

    int i;

      

    /* 判断是S3C2410还是S3C2440 */

    if ((GSTATUS1 == 0x32410000) || (GSTATUS1 == 0x32410002))

       {

           s3c2410_nand_select_chip();

       }

       else

       {

           s3c2440_nand_select_chip();

       }

      

    for(i=0; i<10; i++);

}

 

static void nand_deselect_chip(void)

{

    /* 判断是S3C2410还是S3C2440 */

    if ((GSTATUS1 == 0x32410000) || (GSTATUS1 == 0x32410002))

       {

           s3c2410_nand_deselect_chip();

       }

       else

       {

           s3c2440_nand_deselect_chip();

       }    

}

 

static void write_cmd(int cmd)

{

    /* 判断是S3C2410还是S3C2440 */

    if ((GSTATUS1 == 0x32410000) || (GSTATUS1 == 0x32410002))

       {

           s3c2410_write_cmd(cmd);

       }

       else

       {

           s3c2440_write_cmd(cmd);

       }    

}

static void write_addr(unsigned int addr)

{

    /* 判断是S3C2410还是S3C2440 */

    if ((GSTATUS1 == 0x32410000) || (GSTATUS1 == 0x32410002))

       {

           s3c2410_write_addr(addr);

       }

       else

       {

           s3c2440_write_addr(addr);

       }    

}

 

static unsigned char read_data(void)

{

    /* 判断是S3C2410还是S3C2440 */

    if ((GSTATUS1 == 0x32410000) || (GSTATUS1 == 0x32410002))

       {

           return s3c2410_read_data();

       }

       else

       {

           return s3c2440_read_data();

       }    

}

 

/* 初始化NAND Flash */

void nand_init_ll(void)

{

       S3C2410_NAND * s3c2410nand = (S3C2410_NAND *)0x4e000000;

       S3C2440_NAND * s3c2440nand = (S3C2440_NAND *)0x4e000000;

 

#define TACLS   0

#define TWRPH0  3

#define TWRPH1  0

 

    /* 判断是S3C2410还是S3C2440 */

    if ((GSTATUS1 == 0x32410000) || (GSTATUS1 == 0x32410002))

    {

              /* 使能NAND Flash控制器, 初始化ECC, 禁止片选, 设置时序 */

        s3c2410nand->NFCONF = (1<<15)|(1<<12)|(1<<11)|(TACLS<<8)|(TWRPH0<<4)|(TWRPH1<<0);

    }

    else

    {

              /* 设置时序 */

        s3c2440nand->NFCONF = (TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4);

        /* 使能NAND Flash控制器, 初始化ECC, 禁止片选 */

        s3c2440nand->NFCONT = (1<<4)|(1<<1)|(1<<0);

    }

 

       /* 复位NAND Flash */

       nand_reset();

}

 

 

#define NAND_SECTOR_SIZE    512

#define NAND_BLOCK_MASK     (NAND_SECTOR_SIZE - 1)

 

/* 读函数 */

void 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 ;    /* 地址或长度不对齐 */

    }

 

    /* 选中芯片 */

    nand_select_chip();

 

    for(i=start_addr; i < (start_addr + size);) {

      /* 发出READ0命令 */

      write_cmd(0);

 

      /* Write Address */

      write_addr(i);

      wait_idle();

 

      for(j=0; j < NAND_SECTOR_SIZE; j++, i++) {

          *buf = read_data();

          buf++;

      }

    }

 

    /* 取消片选信号 */

    nand_deselect_chip();

   

    return ;

}

 

int bBootFrmNORFlash(void)

{

    volatile unsigned int *pdw = (volatile unsigned int *)0;

    unsigned int dwVal;

   

    /*

     * 无论是从NOR Flash还是从NAND Flash启动,

     * 地址0处为指令"b  Reset", 机器码为0xEA00000B

     * 对于从NAND Flash启动的情况,其开始4KB的代码会复制到CPU内部4K内存中,

     * 对于从NOR Flash启动的情况,NOR Flash的开始地址即为0

     * 对于NOR Flash,必须通过一定的命令序列才能写数据,

     * 所以可以根据这点差别来分辨是从NAND Flash还是NOR Flash启动:

     * 向地址0写入一个数据,然后读出来,如果没有改变的话就是NOR Flash

     */

 

    dwVal = *pdw;      

    *pdw = 0x12345678;

    if (*pdw != 0x12345678)

    {

        return 1;

    }

    else

    {

        *pdw = dwVal;

        return 0;

    }

}

 

int CopyCode2Ram(unsigned long start_addr, unsigned char *buf, int size)

{

    unsigned int *pdwDest;

    unsigned int *pdwSrc;

    int i;

 

    if (bBootFrmNORFlash())

    {

        pdwDest = (unsigned int *)buf;

        pdwSrc  = (unsigned int *)start_addr;

        /* NOR Flash启动 */

        for (i = 0; i < size / 4; i++)

        {

            pdwDest[i] = pdwSrc[i];

        }

        return 0;

    }

    else

    {

        /* 初始化NAND Flash */

              nand_init_ll();

        /* NAND Flash启动 */

        nand_read_ll(buf, start_addr, (size + NAND_BLOCK_MASK)&~(NAND_BLOCK_MASK));

              return 0;

    }

}

 

static inline void delay (unsigned long loops)

{

    __asm__ volatile ("1:\n"

      "subs %0, %1, #1\n"

      "bne 1b":"=r" (loops):"0" (loops));

}

 

/* S3C2440: Mpll = (2*m * Fin) / (p * 2^s), UPLL = (m * Fin) / (p * 2^s)

 * m = M (the value for divider M)+ 8, p = P (the value for divider P) + 2

 */

#define S3C2440_MPLL_400MHZ     ((0x5c<<12)|(0x01<<4)|(0x01))

#define S3C2440_MPLL_200MHZ     ((0x5c<<12)|(0x01<<4)|(0x02))

#define S3C2440_MPLL_100MHZ     ((0x5c<<12)|(0x01<<4)|(0x03))

#define S3C2440_UPLL_48MHZ      ((0x38<<12)|(0x02<<4)|(0x02))

#define S3C2440_CLKDIV          0x05    /* FCLK:HCLK:PCLK = 1:4:8, UCLK = UPLL */

#define S3C2440_CLKDIV188       0x04    /* FCLK:HCLK:PCLK = 1:8:8 */

#define S3C2440_CAMDIVN188      ((0<<8)|(1<<9)) /* FCLK:HCLK:PCLK = 1:8:8 */

 

/* S3C2410: Mpll,Upll = (m * Fin) / (p * 2^s)

 * m = M (the value for divider M)+ 8, p = P (the value for divider P) + 2

 */

#define S3C2410_MPLL_200MHZ     ((0x5c<<12)|(0x04<<4)|(0x00))

#define S3C2410_UPLL_48MHZ      ((0x28<<12)|(0x01<<4)|(0x02))

#define S3C2410_CLKDIV          0x03    /* FCLK:HCLK:PCLK = 1:2:4 */

void clock_init(void)

{

       S3C24X0_CLOCK_POWER *clk_power = (S3C24X0_CLOCK_POWER *)0x4C000000;

 

    /* support both of S3C2410 and S3C2440, by */

    if ((GSTATUS1 == 0x32410000) || (GSTATUS1 == 0x32410002))

    {

        /* FCLK:HCLK:PCLK = 1:2:4 */

        clk_power->CLKDIVN = S3C2410_CLKDIV;

 

        /* change to asynchronous bus mod */

        __asm__(    "mrc    p15, 0, r1, c1, c0, 0\n"    /* read ctrl register   */ 

                    "orr    r1, r1, #0xc0000000\n"      /* Asynchronous         */ 

                    "mcr    p15, 0, r1, c1, c0, 0\n"    /* write ctrl register  */ 

                    :::"r1"

                    );

       

        /* to reduce PLL lock time, adjust the LOCKTIME register */

        clk_power->LOCKTIME = 0xFFFFFF;

 

        /* configure MPLL */

        clk_power->MPLLCON = S3C2410_MPLL_200MHZ;

 

        /* some delay between MPLL and UPLL */

        delay (4000);

 

        /* configure UPLL */

        clk_power->UPLLCON = S3C2410_UPLL_48MHZ;

 

        /* some delay between MPLL and UPLL */

        delay (8000);

    }

    else

    {

        /* FCLK:HCLK:PCLK = 1:4:8 */

        clk_power->CLKDIVN = S3C2440_CLKDIV;

 

        /* change to asynchronous bus mod */

        __asm__(    "mrc    p15, 0, r1, c1, c0, 0\n"    /* read ctrl register   */ 

                    "orr    r1, r1, #0xc0000000\n"      /* Asynchronous         */ 

                    "mcr    p15, 0, r1, c1, c0, 0\n"    /* write ctrl register  */ 

                    :::"r1"

                    );

 

        /* to reduce PLL lock time, adjust the LOCKTIME register */

        clk_power->LOCKTIME = 0xFFFFFF;

 

        /* configure MPLL */

        clk_power->MPLLCON = S3C2440_MPLL_400MHZ;

 

        /* some delay between MPLL and UPLL */

        delay (4000);

 

        /* configure UPLL */

        clk_power->UPLLCON = S3C2440_UPLL_48MHZ;

 

        /* some delay between MPLL and UPLL */

        delay (8000);

    }

}

cpu/arm920t/s3c24x0中添加nand_flash.c文件

在当前目录下的Makefile中的 COBJS 下添加上nand_flash.o

内容如下:

/*

 * Nand flash interface of s3c2410/s3c2440, by

 * Changed from drivers/mtd/nand/s3c2410.c of kernel 2.6.13

 */

 

#include

 

#if (CONFIG_COMMANDS & CFG_CMD_NAND) && !defined(CFG_NAND_LEGACY)

#include

#include

 

DECLARE_GLOBAL_DATA_PTR;

 

#define S3C2410_NFSTAT_READY    (1<<0)

#define S3C2410_NFCONF_nFCE     (1<<11)

 

#define S3C2440_NFSTAT_READY    (1<<0)

#define S3C2440_NFCONT_nFCE     (1<<1)

 

 

/* select chip, for s3c2410 */

static void s3c2410_nand_select_chip(struct mtd_info *mtd, int chip)

{

    S3C2410_NAND * const s3c2410nand = S3C2410_GetBase_NAND();

 

    if (chip == -1) {

        s3c2410nand->NFCONF |= S3C2410_NFCONF_nFCE;

    } else {

        s3c2410nand->NFCONF &= ~S3C2410_NFCONF_nFCE;

    }

}

 

/* command and control functions, for s3c2410

 *

 * Note, these all use tglx's method of changing the IO_ADDR_W field

 * to make the code simpler, and use the nand layer's code to issue the

 * command and address sequences via the proper IO ports.

 *

*/

static void s3c2410_nand_hwcontrol(struct mtd_info *mtd, int cmd)

{

    S3C2410_NAND * const s3c2410nand = S3C2410_GetBase_NAND();

    struct nand_chip *chip = mtd->priv;

 

    switch (cmd) {

    case NAND_CTL_SETNCE:

    case NAND_CTL_CLRNCE:

        printf("%s: called for NCE\n", __FUNCTION__);

        break;

 

    case NAND_CTL_SETCLE:

        chip->IO_ADDR_W = (void *)&s3c2410nand->NFCMD;

        break;

 

    case NAND_CTL_SETALE:

        chip->IO_ADDR_W = (void *)&s3c2410nand->NFADDR;

        break;

 

        /* NAND_CTL_CLRCLE: */

        /* NAND_CTL_CLRALE: */

    default:

        chip->IO_ADDR_W = (void *)&s3c2410nand->NFDATA;

        break;

    }

}

 

/* s3c2410_nand_devready()

 *

 * returns 0 if the nand is busy, 1 if it is ready

 */

static int s3c2410_nand_devready(struct mtd_info *mtd)

{

    S3C2410_NAND * const s3c2410nand = S3C2410_GetBase_NAND();

 

    return (s3c2410nand->NFSTAT & S3C2410_NFSTAT_READY);

}

 

 

/* select chip, for s3c2440 */

static void s3c2440_nand_select_chip(struct mtd_info *mtd, int chip)

{

    S3C2440_NAND * const s3c2440nand = S3C2440_GetBase_NAND();

 

    if (chip == -1) {

        s3c2440nand->NFCONT |= S3C2440_NFCONT_nFCE;

    } else {

        s3c2440nand->NFCONT &= ~S3C2440_NFCONT_nFCE;

    }

}

 

/* command and control functions */

static void s3c2440_nand_hwcontrol(struct mtd_info *mtd, int cmd)

{

    S3C2440_NAND * const s3c2440nand = S3C2440_GetBase_NAND();

    struct nand_chip *chip = mtd->priv;

 

    switch (cmd) {

    case NAND_CTL_SETNCE:

    case NAND_CTL_CLRNCE:

        printf("%s: called for NCE\n", __FUNCTION__);

        break;

 

    case NAND_CTL_SETCLE:

        chip->IO_ADDR_W = (void *)&s3c2440nand->NFCMD;

        break;

 

    case NAND_CTL_SETALE:

        chip->IO_ADDR_W = (void *)&s3c2440nand->NFADDR;

        break;

 

        /* NAND_CTL_CLRCLE: */

        /* NAND_CTL_CLRALE: */

    default:

        chip->IO_ADDR_W = (void *)&s3c2440nand->NFDATA;

        break;

    }

}

 

/* s3c2440_nand_devready()

 *

 * returns 0 if the nand is busy, 1 if it is ready

 */

static int s3c2440_nand_devready(struct mtd_info *mtd)

{

    S3C2440_NAND * const s3c2440nand = S3C2440_GetBase_NAND();

 

    return (s3c2440nand->NFSTAT & S3C2440_NFSTAT_READY);

}

 

/*

 * Nand flash hardware initialization:

 * Set the timing, enable NAND flash controller

 */

static void s3c24x0_nand_inithw(void)

{

    S3C2410_NAND * const s3c2410nand = S3C2410_GetBase_NAND();

    S3C2440_NAND * const s3c2440nand = S3C2440_GetBase_NAND();

 

#define TACLS   0

#define TWRPH0  4

#define TWRPH1  2

 

    if (gd->bd->bi_arch_number == MACH_TYPE_SMDK2410)

    {

        /* Enable NAND flash controller, Initialize ECC, enable chip select, Set flash memory timing */

        s3c2410nand->NFCONF = (1<<15)|(1<<12)|(1<<11)|(TACLS<<8)|(TWRPH0<<4)|(TWRPH1<<0);

    }

    else

    {

        /* Set flash memory timing */

        s3c2440nand->NFCONF = (TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4);

        /* Initialize ECC, enable chip select, NAND flash controller enable */

        s3c2440nand->NFCONT = (1<<4)|(0<<1)|(1<<0);

    }

}

 

/*

 * Called by drivers/nand/nand.c, initialize the interface of nand flash

 */

void board_nand_init(struct nand_chip *chip)

{

    S3C2410_NAND * const s3c2410nand = S3C2410_GetBase_NAND();

    S3C2440_NAND * const s3c2440nand = S3C2440_GetBase_NAND();

 

    s3c24x0_nand_inithw();

 

    if (gd->bd->bi_arch_number == MACH_TYPE_SMDK2410) {

        chip->IO_ADDR_R    = (void *)&s3c2410nand->NFDATA;

        chip->IO_ADDR_W    = (void *)&s3c2410nand->NFDATA;

        chip->hwcontrol    = s3c2410_nand_hwcontrol;

        chip->dev_ready    = s3c2410_nand_devready;

        chip->select_chip  = s3c2410_nand_select_chip;

        chip->options      = 0;

    } else {

        chip->IO_ADDR_R    = (void *)&s3c2440nand->NFDATA;

        chip->IO_ADDR_W    = (void *)&s3c2440nand->NFDATA;

        chip->hwcontrol    = s3c2440_nand_hwcontrol;

        chip->dev_ready    = s3c2440_nand_devready;

        chip->select_chip  = s3c2440_nand_select_chip;

        chip->options      = 0;

    }

 

    chip->eccmode       = NAND_ECC_SOFT;

}

 

#endif

board/QQ2440/u-boot.lds

36行添加(显示用)

Board/QQ2440/boot_init.o(.text)

第三阶段  编译文件

u-boot-1.1.6目录下

#make QQ2440_config

# make all

此时在u-boot-1.1.6目录下生成u-boot.bin文件

第四阶段  u-boot烧写到开发板

要烧写U-Boot,必须确定Nor Flash中的BIOSSupervivi2.0,把开发板设置为Nor lash启动,连接好串口和USB线,打开超级终端,打开电源,串口显示如图:

打开DNW,确认USB 连接正常 OK,点UsbPortTransmit/Restore,选择刚才所编译的u-boot.bin,下载和烧写很快就会结束。把QQ2440启动模式跳线改为Nand Flash启动,重新复位或者重启开机电源开关,在串口终端可以看到如图信息:

至此U-Boot已经编译并下载到开发板中运行了,这时你需要完全抛弃 Nor Flashsupervivi的那些功能命令,使用U-Boot本身的功能来下载和烧写内核,以及文件系统。

阅读(560) | 评论(0) | 转发(0) |
0

上一篇:U-Boot启动过程

下一篇:没有了

给主人留下些什么吧!~~