u-boot-2009.11移植(适用于TQ2440和MINI2440)第四篇:完善目标板外设驱动(Nand flash和Dm9000配置)

时间:2022-03-09 19:34:00

注意:红色标记为修改的地方

4.1 Nand Flash相关代码的修改

在U-boot 启动的第一阶段,初始化了Nand Flash 控制器。但到第二阶段start_armboot函数还是会再次初始化Nand Flash 控制器。因为第二阶段和第一阶段的代码基本是独立的,第一阶段的代码基本只起到代码重定位的作用,到了第二阶段才是真正U-boot 的开始,以前的初始化过程还会重做一遍,比如始化Nand Flash 控制器、CPU 频率等。

因为S3C2440 和S3C2410 之间的很大差别就是:S3C2410 的Nand Flash 控制器只支持512B+16B 的Nand Flash,而S3C2440 还支持2KB+64B 的大容量Nand Flash。所以在Nand Flash 控制器上寄存器和控制流程上的差别很明显,底层驱动代码的修改也是必须的。具体的差别还是需要对比芯片数据手册的,下面是关于Nand Flash 底层驱动代码的修改:

打开/drivers/mtd/nand/s3c2410_nand.c文件

#include<s3c2410.h>                        

#include <asm/io.h>

 

#define NF_BASE     0x4e000000

 

#if defined(CONFIG_S3C2410)

#define S3C2410_NFCONF_EN          (1<<15)

#define S3C2410_NFCONF_512BYTE     (1<<14)

#define S3C2410_NFCONF_4STEP       (1<<13)

#define S3C2410_NFCONF_INITECC     (1<<12)

#define S3C2410_NFCONF_nFCE        (1<<11)

#define S3C2410_NFCONF_TACLS(x)    ((x)<<8)

#define S3C2410_NFCONF_TWRPH0(x)   ((x)<<4)

#define S3C2410_NFCONF_TWRPH1(x)   ((x)<<0)

 

#define S3C2410_ADDR_NALE 4

#define S3C2410_ADDR_NCLE 8

#endif

 

#if defined(CONFIG_S3C2440)

#define S3C2410_NFCONT_EN          (1<<0)

#define S3C2410_NFCONT_INITECC     (1<<4)

#define S3C2410_NFCONT_nFCE        (1<<1)

#define S3C2410_NFCONT_MAINECCLOCK(1<<5)

#define S3C2410_NFCONF_TACLS(x)    ((x)<<12)

#define S3C2410_NFCONF_TWRPH0(x)   ((x)<<8)

#define S3C2410_NFCONF_TWRPH1(x)   ((x)<<4)

 

#define S3C2410_ADDR_NALE 0x08

#define S3C2410_ADDR_NCLE 0x0c

#endif

ulong IO_ADDR_W = NF_BASE;

 

static void s3c2410_hwcontrol(struct mtd_info *mtd,int cmd, unsigned int ctrl)

{

//  structnand_chip *chip = mtd->priv;

    structs3c2410_nand *nand = s3c2410_get_base_nand();

 

    debugX(1,"hwcontrol(): 0x%02x 0x%02x\n", cmd, ctrl);

 

    if (ctrl& NAND_CTRL_CHANGE) {

//      ulongIO_ADDR_W = (ulong)nand;

IO_ADDR_W = (ulong)nand;

 

        if(!(ctrl & NAND_CLE))

            IO_ADDR_W|= S3C2410_ADDR_NCLE;

        if(!(ctrl & NAND_ALE))

            IO_ADDR_W|= S3C2410_ADDR_NALE;

 

//      chip->IO_ADDR_W= (void *)IO_ADDR_W;

 

#if defined(CONFIG_S3C2410)

        if (ctrl& NAND_NCE)

            writel(readl(&nand->NFCONF)& ~S3C2410_NFCONF_nFCE,

                   &nand->NFCONF);

        else

            writel(readl(&nand->NFCONF)| S3C2410_NFCONF_nFCE,

                   &nand->NFCONF);

    }

#endif

#if defined(CONFIG_S3C2440)

        if(ctrl & NAND_NCE)

            writel(readl(&nand->NFCONT)& ~S3C2410_NFCONT_nFCE,

                   &nand->NFCONT);

        else

            writel(readl(&nand->NFCONT)| S3C2410_NFCONT_nFCE,

                   &nand->NFCONT);

    }

#endif

 

    if (cmd !=NAND_CMD_NONE)

//     writeb(cmd, chip->IO_ADDR_W);

        writeb(cmd, (void *)IO_ADDR_W);

}

……….

void s3c2410_nand_enable_hwecc(struct mtd_info *mtd,int mode)

{

    structs3c2410_nand *nand = s3c2410_get_base_nand();

    debugX(1,"s3c2410_nand_enable_hwecc(%p, %d)\n", mtd, mode);

#if defined(CONFIG_S3C2410)

    writel(readl(&nand->NFCONF)| S3C2410_NFCONF_INITECC, &nand->NFCONF);

#endif

 

#if defined(CONFIG_S3C2440)

    writel(readl(&nand->NFCONT)| S3C2410_NFCONT_INITECC, &nand->NFCONT);

#endif

}

 

………..

int board_nand_init(struct nand_chip *nand)

{

…………

debugX(1, "board_nand_init()\n");

 

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

#if defined(CONFIG_S3C2410)

    /* initializehardware */

    twrph0 = 3;

    twrph1 = 0;

    tacls = 0;

 

    cfg = S3C2410_NFCONF_EN;

    cfg |=S3C2410_NFCONF_TACLS(tacls - 1);

    cfg |=S3C2410_NFCONF_TWRPH0(twrph0 - 1);

    cfg |=S3C2410_NFCONF_TWRPH1(twrph1 - 1);

    writel(cfg,&nand_reg->NFCONF);

 

    /* initializenand_chip data structure */

    nand->IO_ADDR_R= nand->IO_ADDR_W = (void *)&nand_reg->NFDATA;

#endif

#if defined(CONFIG_S3C2440)

    twrph0= 4;

    twrph1= 2;

    tacls= 0;

 

    cfg= 0;

    cfg|= S3C2410_NFCONF_TACLS(tacls - 1);

    cfg|= S3C2410_NFCONF_TWRPH0(twrph0 - 1);

    cfg|= S3C2410_NFCONF_TWRPH1(twrph1 - 1);

    writel(cfg,&nand_reg->NFCONF);

 

    cfg=(0<<13)|(0<<12)|(0<<10)|(0<<9)|(0<<8)|(0<<6)|(0<<5)|(1<<4)|(0<<1)|(1<<0);

    writel(cfg,&nand_reg->NFCONT);

/* initialize nand_chip data structure */

    nand->IO_ADDR_R= nand->IO_ADDR_W = (void *)&nand_reg->NFDATA;

#endif

/* read_buf and write_buf are default */

    /* read_byteand write_byte are default */


4.2 修改网络相关代码

以前的U-boot 对于网络延时部分有问题,需要修改许多地方。但是现在的U-boot 网络部分已经基本不需要怎么修改了,只有在DM9000 的驱动和NFS 的TIMEOUT 参数上需要稍微修改一下:

对于 DM9000 的驱动,只是屏蔽了一点代码:

打开/drivers/net/dm9000x.c文件

static int dm9000_init(struct eth_device *dev, bd_t*bd)

{

……………

while (!(phy_read(1) & 0x20)) { /* autonegation complete bit */

        udelay(1000);

        i++;

        if (i == 1000) {

//          printf("couldnot establish link\n");

//          return0;

            break;

        }

    }

 

    /* see whatwe've got */

    lnk = phy_read(17) >> 12;

 

对于 NFS,增加了延时,否则会出现“*** ERROR: Cannot mount”的错误

打开net/nfs.c文件           

#define HASHES_PER_LINE 65  /* Number of "loading" hashes per line  */

#define NFS_RETRY_COUNT 30

#define NFS_TIMEOUT (10*2000UL)

 

static int fs_mounted = 0;

static unsigned long rpc_id = 0;