分类:
2011-08-09 11:41:19
1.2.7 Nand Flash 驱动
首先,要说明一下 CFG_NAND_LEGACY 的使用。在u-boot的 drivers/mtd/下有两个目录,分别是nand和nand_legacy。在nand目录下的是nand的初始化函数和nand的操作读写函数,是使用linux的mtd构架。此目录下的文件,只有在定义了CFG_CMD_NAND宏和没有定义CFG_NAND_LEGACY宏的情况下才会被编译。在nand_leagcy目录下的文件也是是实现nand相关操作命令,如read,write等命令的功能,但不是使用linux的mtd构架。此目录下的文件,只有在定义了CFG_CMD_NAND和定义了CFG_NAND_LEGACY宏的情况下才会定义。此目录下的文件u-boot已不推荐使用。在本移植过程中采用不定义CFG_NAND_LEGACY的方式。
(1)修改/cpu/arm920t/s3c24x0/nand.c
先加入S3C2440 NAND flash控制器的地址定义,修改后如下:
#define __REGb(x) (*(volatile unsigned char *)(x))
#define __REGi(x) (*(volatile unsigned int *)(x))
#if defined(CONFIG_S3C2410)
#define NF_BASE 0x4e000000
#define NFCONF __REGi(NF_BASE + 0x0)
#define NFCMD __REGb(NF_BASE + 0x4)
……
#define NFECC0 __REGb(NF_BASE + 0x14)
#define NFECC1 __REGb(NF_BASE + 0x15)
#define NFECC2 __REGb(NF_BASE + 0x16)
#else
#if defined(CONFIG_S3C2440)
#define NF_BASE 0x4e000000
#define NFCONF __REGi(NF_BASE + 0x0)
#define NFCONT __REGi(NF_BASE + 0x4)
#define NFCMD __REGb(NF_BASE + 0x8)
#define NFADDR __REGb(NF_BASE + 0xc)
#define NFDATA __REGb(NF_BASE + 0x10)
#define NFMECCD0 __REGi(NF_BASE + 0x14)
#define NFMECCD1 __REGi(NF_BASE + 0x18)
#define NFSECCD __REGi(NF_BASE + 0x1C)
#define NFSTAT __REGb(NF_BASE + 0x20)
#define NFSTAT0 __REGi(NF_BASE + 0x24)
#define NFSTAT1 __REGi(NF_BASE + 0x28)
#define NFMECC0 __REGi(NF_BASE + 0x2C)
#define NFMECC1 __REGi(NF_BASE + 0x30)
#define NFSECC __REGi(NF_BASE + 0x34)
#define NFSBLK __REGi(NF_BASE + 0x38)
#define NFEBLK __REGi(NF_BASE + 0x3c)
#define S3C2440_NFCONT_nCE (1<<1)
#define S3C2440_ADDR_NALE 0x0c
#define S3C2440_ADDR_NCLE 0x08
#endif
#endif
#define S3C2410_NFCONF_512BYTE (1<<14)
u-boot.2008.10自带的S3C2410的s3c2410_hwcontrol函数有错。在此函数中,把chip->IO_ADDR_W值改写了,导致在写数据时出现错误。解决方法是使用一全局变量代替 chip->IO_ADDR_W。在 s3c2410_hwcontrol 函数上一行定义这个全局变量,然后修改 s3c2410_hwcontrol 函数,让它支持 S3C2440,修改后如下:
#define S3C2410_ADDR_NCLE 8
ulong IO_ADDR_W = NF_BASE;
static void s3c2410_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
{
struct nand_chip *chip = mtd->priv;
DEBUGN("hwcontrol(): 0x%02x 0x%02x\n", cmd, ctrl);
#if defined(CONFIG_S3C2410)
if (ctrl & NAND_CTRL_CHANGE) {
//ulong IO_ADDR_W = NF_BASE;
IO_ADDR_W = NF_BASE;
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 (ctrl & NAND_NCE)
NFCONF &= ~S3C2410_NFCONF_nFCE;
……
}
if (cmd != NAND_CMD_NONE)
//writeb(cmd, chip->IO_ADDR_W);
writeb(cmd,(void *)IO_ADDR_W);
#endif
#if defined(CONFIG_S3C2440)
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;}
//chip->IO_ADDR_W = (void *)IO_ADDR_W;
if (ctrl & NAND_NCE)
{NFCONT &= ~S3C2440_NFCONT_nCE; //使能nand flash
//DEBUGN("NFCONT is 0x%x ",NFCONT);
//DEBUGN("nand Enable ");
}
else
{NFCONT |= S3C2440_NFCONT_nCE; //禁止nand flash
//DEBUGN("nand disable ");
}
}
if (cmd != NAND_CMD_NONE)
writeb(cmd,(void *)IO_ADDR_W);
//writeb(cmd, chip->IO_ADDR_W);
#endif
}
修改board_nand_init 函数如下:
DEBUGN("board_nand_init()\n");
clk_power->CLKCON |= (1 << 4);
#if defined(CONFIG_S3C2410)
DEBUGN("CONFIG_S3C2410\n");
/* initialize hardware */
twrph0 = 3; twrph1 = 0; tacls = 0;
……
nand->cmd_ctrl = s3c2410_hwcontrol;
nand->dev_ready = s3c2410_dev_ready;
#else
#if defined(CONFIG_S3C2440)
DEBUGN("CONFIG_S3C2440\n");
twrph0 = 4; twrph1 = 2; tacls = 0;
cfg = (tacls<<12)|(twrph0<<8)|(twrph1<<4);
NFCONF = cfg;
//DEBUGN("cfg is %x\n",cfg);
//DEBUGN("NFCONF is %lx\n",NFCONF);
cfg = (1<<6)|(1<<4)|(0<<1)|(1<<0);
NFCONT = cfg;
//DEBUGN("cfg is %lx\n",cfg);
//DEBUGN("NFCONT is %x\n",NFCONT);
/* initialize nand_chip data structure */
nand->IO_ADDR_R = nand->IO_ADDR_W = (void *)0x4e000010;
/* read_buf and write_buf are default */
/* read_byte and write_byte are default */
/* hwcontrol always must be implemented */
nand->cmd_ctrl = s3c2410_hwcontrol;
nand->dev_ready = s3c2410_dev_ready;
#endif
#endif
#ifdef CONFIG_S3C2410_NAND_HWECC
1.2.8 修改u-boot-2008.10/cpu/arm920t/s3c24x0/interrupts.c 文件
(1)在有S3C2410的宏定义开关里加入对S3C2440的支持:
#include
#if defined(CONFIG_S3C2400) || defined (CONFIG_S3C2410) || defined (CONFIG_TRAB) || defined (CONFIG_S3C2440)
#include
#if defined(CONFIG_S3C2400)
#include
#elif defined(CONFIG_S3C2410) || defined(CONFIG_S3C2440)
#include
#endif
(2)加入对mini2440的支持:
#elif defined(CONFIG_SBC2410X) || \
defined(CONFIG_SMDK2410) || \
defined(CONFIG_VCMA9) || \
defined(CONFIG_mini2440)
tbclk = CFG_HZ;
#else
# error "tbclk not configured"
1.2.9 修改 cpu\arm920t\s3c24x0\speed.c ,修改根据时钟寄存器来计算时钟的方法。
(1)头文件对S3C2440的支持:
#include
#if defined(CONFIG_S3C2400) || defined (CONFIG_S3C2410) || defined (CONFIG_TRAB) || defined (CONFIG_S3C2440)
#include
#if defined(CONFIG_S3C2400)
#include
#elif defined(CONFIG_S3C2410) || defined(CONFIG_S3C2440)
#include
#endif
(2)由于S3C2410和S3C2440的MPLL、UPLL计算公式不一样,所以get_PLLCLK函数也需要修改:
m = ((r & 0xFF000) >> 12) + 8;
p = ((r & 0x003F0) >> 4) + 2;
s = r & 0x3;
#if defined(CONFIG_S3C2440)
if (pllreg == MPLL)
return((CONFIG_SYS_CLK_FREQ * m * 2) / (p << s));
else if (pllreg == UPLL)
#endif
return((CONFIG_SYS_CLK_FREQ * m ) / (p << s));
(3) 由于S3C2410和S3C2440的设置方法也不一样,所以get_HCLK函数也需要修改:
ulong get_HCLK(void)
{
S3C24X0_CLOCK_POWER * const clk_power = S3C24X0_GetBase_CLOCK_POWER();
#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
//return((clk_power->CLKDIVN & 0x2) ? get_FCLK()/2 : get_FCLK());
}
/* return PCLK frequency */
1.2.10 修改u-boot-2008.10/drivers/usb/usb_ohci.c ,添加对2440的支持
defined(CONFIG_S3C2400) || \
defined(CONFIG_S3C2410) || \
defined(CONFIG_S3C2440) || \
defined(CONFIG_S3C6400) || \
defined(CONFIG_440EP) || \
defined(CONFIG_PCI_OHCI) || \
defined(CONFIG_MPC5200) || \
defined(CFG_OHCI_USE_NPS)
# define OHCI_USE_NPS /* force NoPowerSwitching mode */
#endif
1.2.11 添加mini2440的机器ID
在u-boot-2008.10/include/asm-arm/mach-types.h文件中添加(需要和内核的ID保持一致):
#define MACH_TYPE_IMX27IPCAM 1871
#define MACH_TYPE_NEMOC 1872
#define MACH_TYPE_GENEVA 1873
#define MACH_TYPE_mini2440 782