Chinaunix首页 | 论坛 | 博客
  • 博客访问: 45940
  • 博文数量: 32
  • 博客积分: 427
  • 博客等级: 下士
  • 技术积分: 285
  • 用 户 组: 普通用户
  • 注册时间: 2011-03-20 00:40
文章分类

全部博文(32)

文章存档

2014年(8)

2012年(11)

2011年(13)

我的朋友

分类:

2011-11-05 18:54:24

原文地址:续uboot移植 作者:crazytyt

7 为了实现NAND Flash的读写,再次修改/include/configs/tekkaman2440.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    /* in a SAMSUNG S3C2410 SoC */

//#define CONFIG_SBC2410X        1    /* on a friendly-arm SBC-2410X Board */

#define CONFIG_S3C2440 1 /* in a SAMSUNG S3C2440 SoC */
#define CONFIG_tekkaman2440 1 /* on a SAMSUNG tekkaman2440 Board */
#define CONFIG_tekkaman2440_LED 1
/* Use the LED on Board */
......
/*
 * Command line configuration.
 */

#include <config_cmd_default.h>

#define CONFIG_CMD_ASKENV
#define CONFIG_CMD_CACHE
#define CONFIG_CMD_DATE
#define CONFIG_CMD_DHCP
#define CONFIG_CMD_ELF
#define CONFIG_CMD_PING
#define CONFIG_CMD_NAND
#define CONFIG_CMD_REGINFO

#define CONFIG_CMD_JFFS2

/* JFFS2 Support    080218  */

#define CONFIG_CMD_USB

/* USB Support  080218  */

#define CONFIG_CMD_FAT

/* FAT support  080218  */

......
#define CFG_LONGHELP
/* undef to save memory */
#define CFG_PROMPT "[Tekkaman2440]#"
/*Monitor Command Prompt */
#define CFG_CBSIZE 256
/* Console I/O Buffer Size */
......
#define CFG_LOAD_ADDR 0x30008000
 /* default load address */

......

/* timeout values are in ticks */
#define CFG_FLASH_ERASE_TOUT    (5*CFG_HZ) /* Timeout for Flash Erase */
#define CFG_FLASH_WRITE_TOUT    (5*CFG_HZ) /* Timeout for Flash Write */

#define CFG_ENV_IS_IN_NAND 1
#define CFG_ENV_OFFSET 0X30000
#define CFG_NAND_LEGACY

//#define    CFG_ENV_IS_IN_FLASH    1

#define CFG_ENV_SIZE        0x10000    /* Total Size of Environment Sector */

/*----------------------------------------------------------------------
 * NAND flash settings
 */

#if defined(CONFIG_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_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 WRITE_NAND_COMMAND(d, adr) {rNFCMD = d;}
#define WRITE_NAND_COMMANDW(d, adr)    NF_CmdW(d)

# if defined(CONFIG_S3C2440)
#define NAND_DISABLE_CE(nand) {rNFCONT |= (1<<1);}
#define NAND_ENABLE_CE(nand) {rNFCONT &= ~(1<<1);}
#endif
# if defined(CONFIG_S3C2410)
#define NAND_DISABLE_CE(nand) {rNFCONF |= (1<<11);}
#define NAND_ENABLE_CE(nand) {rNFCONF &= ~(1<<11);}
#endif

/* the following s 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
......
#endif /* __CONFIG_H */

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

(1)/include/common.h文件的第474行:

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

(2)/include/s3c24x0.h文件的第85、95、99、110、148、404行:
“#ifdef CONFIG_S3C2410”改为

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


顺便在其中加入2440 的NAND FLASH 寄存器定义(第160行附近)和CAMDIVN定义(第128行附近):

......
typedef struct {
         S3C24X0_REG32 LOCKTIME;
         S3C24X0_REG32 MPLLCON;
         S3C24X0_REG32 UPLLCON;
         S3C24X0_REG32 CLKCON;
         S3C24X0_REG32 CLKSLOW;
         S3C24X0_REG32 CLKDIVN;
#if defined (CONFIG_S3C2440)
         S3C24X0_REG32 CAMDIVN;
#endif
} /*__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)/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)

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

#elif defined(CONFIG_SBC2410X) || \
      defined(CONFIG_SMDK2410) || \
      defined(CONFIG_VCMA9) ||defined(CONFIG_tekkaman2440)

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

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

#if defined(CONFIG_S3C2440)
    if (clk_power->CLKDIVN & 0x6)
                            {
                            if ((clk_power->CLKDIVN & 0x6)==2) return(get_FCLK()/2);
                            if ((clk_power->CLKDIVN & 0x6)==6) return((clk_power->CAMDIVN & 0x100) ? get_FCLK()/6 : get_FCLK()/3);
                            if ((clk_power->CLKDIVN & 0x6)==4) return((clk_power->CAMDIVN & 0x200) ? get_FCLK()/8 : get_FCLK()/4);
             return(get_FCLK());
                            }
 
       else return(get_FCLK());
#else

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

}
......

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

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

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

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

(8)/cpu/arm920t/s3c24x0/usb.c文件的第31行:

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

(9)/cpu/arm920t/s3c24x0/i2c.c文件的第35行:

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

第66、85、142、150、174行:
将“#ifdef CONFIG_S3C2410”改为

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

(10)drivers/usb/usb_ohci.c文件的第68行附近:

#if defined(CONFIG_ARM920T) || \
    defined(CONFIG_S3C2400) || \
    defined(CONFIG_S3C2410) || \
    defined(CONFIG_S3C2440) || \
    defined(CONFIG_440EP) || \
    defined(CONFIG_PCI_OHCI) || \
    defined(CONFIG_MPC5200)

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

static struct nand_flash_dev nand_flash_ids[] = {
......
    {"Samsung K9F1208U0B", NAND_MFR_SAMSUNG, 0x76, 26, 0, 3, 0x4000, 0},
    {NULL,}
};

 修改include/linux/mtd/nand.h

/*
 * Constants for hardware specific CLE/ALE/NCE
*/

#if 0

/* Select the chip by setting nCE to low */
#define NAND_CTL_SETNCE        1
/* Deselect the chip by setting nCE to high */
#define NAND_CTL_CLRNCE        2
/* Select the command latch by setting CLE to high */
#define NAND_CTL_SETCLE        3
/* Deselect the command latch by setting CLE to low */
#define NAND_CTL_CLRCLE        4
/* Select the address latch by setting ALE to high */
#define NAND_CTL_SETALE        5
/* Deselect the address latch by setting ALE to low */
#define NAND_CTL_CLRALE        6
/* Set write protection by setting WP to high. Not used! */
#define NAND_CTL_SETWP        7
/* Clear write protection by setting WP to low. Not used! */
#define NAND_CTL_CLRWP        8
#endif

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)
{
# if defined(CONFIG_tekkaman2440_LED)     
    S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
         gpio->GPBDAT = 0x100;
//tekkamanninja

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

#endif
    printf ("\n\n%s\n\n", version_string);
    debug ("U-Boot code: %08lX -> %08lX BSS: -> %08lX\n",
           _armboot_start, _bss_start, _bss_end);
#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
# if defined(CONFIG_tekkaman2440_LED)     
         S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
#endif
......
# if defined(CONFIG_tekkaman2440_LED)     
         gpio->GPBDAT = 0x0;
//tekkamanninja

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

#endif
         /* 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/tekkaman2440/tekkaman2440.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/tekkaman/tekkaman2440/tekkaman2440.c中的nand_init()函数。这里我选择第二种方式。

#if defined(CONFIG_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_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_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 u32 NF_Read_ECC(void)
{
    S3C2410_NAND * const nand = S3C2410_GetBase_NAND();
    return(nand->NFECC);
}

#if defined(CONFIG_S3C2440)
static inline void NF_Cont(u16 cont)
{
    S3C2410_NAND * const nand = S3C2410_GetBase_NAND();
    nand->NFCONT = cont;
}

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_Init_ECC(void)
{
    S3C2410_NAND * const nand = S3C2410_GetBase_NAND();
    nand->NFCONT |= (1<<4);
}

#else
static inline void NF_SetCE(NFCE_STATE s)
{
    S3C2410_NAND * const nand = S3C2410_GetBase_NAND();
    switch (s) {
    case NFCE_LOW:
        nand->NFCONF &= ~(1<<11);
        break;
    case NFCE_HIGH:
        nand->NFCONF |= (1<<11);
        break;
    }
}

static inline void NF_Init_ECC(void)
{
    S3C2410_NAND * const nand = S3C2410_GetBase_NAND();
    nand->NFCONF |= (1<<12);
}
#endif

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
#define TACLS 0
#define TWRPH0 3
#define TWRPH1 0
#else
#define TACLS 0
#define TWRPH0 4
#define TWRPH1 2
#endif

#if defined(CONFIG_S3C2440)
    NF_Conf((TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4));
    NF_Cont((1<<6)|(1<<4)|(1<<1)|(1<<0));
#else
    NF_Conf((1<<15)|(0<<14)|(0<<13)|(1<<12)|(1<<11)|(TACLS<<8)|(TWRPH0<<4)|(TWRPH1<<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 */
#endif
    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

三、交叉编译U-Boot。
在U-Boot的根目录下
$make
一阵English飘过~~~~~~~~~~~~~~~~~~~~~~~
 

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

上一篇:AT91RM9200 Bootloader改写

下一篇:s3c2410 watchdog

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