微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > 嵌入式Linux之我行——u-boot-2009.08在2440上的移植详解(三)

嵌入式Linux之我行——u-boot-2009.08在2440上的移植详解(三)

时间:11-20 来源:互联网 点击:

Linux内核的MTD架构,删除了以前传统的执行方法,使移植没有以前那样复杂了,实现Nand的操作和基本命令都直接在drivers/mtd/nand目录下(在doc/README.nand中讲得很清楚)。下面我们结合代码来分析一下u-boot在第二阶段的执行流程:

1.lib_arm/board.c文件中的start_armboot函数调用了drivers/mtd/nand/nand.c文件中的nand_init函数,如下:
#if defined(CONFIG_CMD_NAND)//可以看到CONFIG_CMD_NAND宏决定了Nand的初始化
puts ("NAND: ");
nand_init();
#endif

2.nand_init调用了同文件下的nand_init_chip函数;
3.nand_init_chip函数调用drivers/mtd/nand/s3c2410_nand.c文件下的board_nand_init函数,然后再调用drivers/mtd/nand/nand_base.c函数中的nand_scan函数;
4.nand_scan函数调用了同文件下的nand_scan_ident函数等。


因为2440和2410对nand控制器的操作有很大的不同,所以s3c2410_nand.c下对nand操作的函数就是我们做移植需要实现的部分了,他与具体的Nand Flash硬件密切相关。为了区别与2410,这里我们就重新建立一个s3c2440_nand.c文件,在这里面来实现对nand的操作,代码如下:

#gedit drivers/mtd/nand/s3c2440_nand.c//新建s3c2440_nand.c文件

#include

#if 0
#define DEBUGN printf
#else
#define DEBUGN(x, args ...) {}
#endif

#include
#include
#include

#define __REGb(x) (*(volatile unsigned char *)(x))
#define __REGi(x) (*(volatile unsigned int *)(x))

#define NF_BASE 0x4e000000//Nand配置寄存器基地址
#define NFCONF __REGi(NF_BASE + 0x0)//偏移后还是得到配置寄存器基地址
#define NFCONT __REGi(NF_BASE + 0x4)//偏移后得到Nand控制寄存器基地址
#define NFCMD __REGb(NF_BASE + 0x8)//偏移后得到Nand指令寄存器基地址
#define NFADDR __REGb(NF_BASE + 0xc)//偏移后得到Nand地址寄存器基地址
#define NFDATA __REGb(NF_BASE + 0x10)//偏移后得到Nand数据寄存器基地址
#define NFMECCD0 __REGi(NF_BASE + 0x14)//偏移后得到Nand主数据区域ECC0寄存器基地址
#define NFMECCD1 __REGi(NF_BASE + 0x18)//偏移后得到Nand主数据区域ECC1寄存器基地址
#define NFSECCD __REGi(NF_BASE + 0x1C)//偏移后得到Nand空闲区域ECC寄存器基地址
#define NFSTAT __REGb(NF_BASE + 0x20)//偏移后得到Nand状态寄存器基地址
#define NFSTAT0 __REGi(NF_BASE + 0x24)//偏移后得到Nand ECC0状态寄存器基地址
#define NFSTAT1 __REGi(NF_BASE + 0x28)//偏移后得到Nand ECC1状态寄存器基地址
#define NFMECC0 __REGi(NF_BASE + 0x2C)//偏移后得到Nand主数据区域ECC0状态寄存器基地址
#define NFMECC1 __REGi(NF_BASE + 0x30)//偏移后得到Nand主数据区域ECC1状态寄存器基地址
#define NFSECC __REGi(NF_BASE + 0x34)//偏移后得到Nand空闲区域ECC状态寄存器基地址
#define NFSBLK __REGi(NF_BASE + 0x38)//偏移后得到Nand块开始地址
#define NFEBLK __REGi(NF_BASE + 0x3c)//偏移后得到Nand块结束地址

#define S3C2440_NFCONT_nCE (1<1)
#define S3C2440_ADDR_NALE 0x0c
#define S3C2440_ADDR_NCLE 0x08

ulong IO_ADDR_W = NF_BASE;

static void s3c2440_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
{
struct nand_chip *chip = mtd->priv;

DEBUGN("hwcontrol(): 0xx 0xx\n", cmd, ctrl);

if (ctrl & NAND_CTRL_CHANGE) {
IO_ADDR_W = NF_BASE;

if (!(ctrl & NAND_CLE))//要写的是地址
IO_ADDR_W |= S3C2440_ADDR_NALE;
if (!(ctrl & NAND_ALE))//要写的是命令
IO_ADDR_W |= S3C2440_ADDR_NCLE;

if (ctrl & NAND_NCE)
NFCONT &= ~S3C2440_NFCONT_nCE;//使能nand flash
else
NFCONT |= S3C2440_NFCONT_nCE;//禁止nand flash
}

if (cmd != NAND_CMD_NONE)
writeb(cmd,(void *)IO_ADDR_W);
}

static int s3c2440_dev_ready(struct mtd_info *mtd)
{
DEBUGN("dev_ready\n");
return (NFSTAT & 0x01);
}

int board_nand_init(struct nand_chip *nand)
{
u_int32_t cfg;
u_int8_t tacls, twrph0, twrph1;
S3C24X0_CLOCK_POWER * const clk_power = S3C24X0_GetBase_CLOCK_POWER();

DEBUGN("board_nand_init()\n");

clk_power->CLKCON |= (1 < 4);

twrph0 = 4; twrph1 = 2; tacls = 0;

cfg = (tacls<12)|(twrph0<8)|(twrph1<4);
NFCONF = cfg;

cfg = (1<6)|(1<4)|(0<1)|(1<0);
NFCONT = cfg;


nand->IO_ADDR_R = nand->IO_ADDR_W = (void *)0x4e000010;



nand->cmd_ctrl = s3c2440_hwcontrol;

nand->dev_ready = s3c2440_dev_ready;

return 0;
}

其次,在

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top