U-boot-2009 08移植(五)uboot架構中NAND Flash驅動修改
分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow
也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!
分析了一下Uboot中Nandflash的驅動,u-boot-2009.08使用的是和Linux核心一樣的MTD(記憶體技術裝置)架構。在Uboot下對Nand的支援體現在命令列下實現對nand flash的操作,為:nand info,nand device,nand read,nand write,nand erease,nand bad。用到的主要資料結構有:struct nand_flash_dev,struct nand_chip。前者包括主要的晶片型號,儲存容量,裝置ID,I/O匯流排寬度等資訊;後者是具體對nand flash進行操作時用到的資訊。
u-boot啟動到第二個階段後,在/cpu/arm920t/board.c這個檔案中start_armboot函式裡,有下面的程式碼:
#if defined(CONFIG_CMD_NAND)
puts ("NAND: ");
nand_init(); /* go init the NAND */
#endif
所以,我們只要定義了CONFIG_CMD_NAND這個巨集,就會開始nand初始化。通過用Source Insight來做程式碼分析來一步步地檢視函式執行過程,得出下面的nand執行流程:
1./cpu/arm920t/board.c檔案中的start_armboot函式呼叫/drivers/mtd/nand/nand.c檔案中的nand_init函式;
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.s3c2410_nand.c就是我們做移植需要實現的檔案,是與具體的硬體密切相關的。
5.nand_scan函式會呼叫同文件下的nand_scan_ident等函式。
從這裡我們得知,我們要把nand移植到2440上,就要修改s3c2410_nand.c這個檔案!因為對nand flash的操作,實際上就是對nand控制器的操作,而2440的nand控制器和2410相比,有很大的不同!我們的修改工作量主要也是在這裡。在這裡我就在原始檔上修改了。
首先在include/configs/fl2440.h中相應位置增加必要的巨集定義:
#define CONFIG_CMD_NAND
/* NAND flash settings */
#if defined(CONFIG_CMD_NAND)
#define CONFIG_SYS_NAND_BASE 0x4E000000
#define CONFIG_SYS_MAX_NAND_DEVICE 1
#define CONFIG_MTD_NAND_VERIFY_WRITE 1
#define NAND_SAMSUNG_LP_OPTIONS 1 /*注意,這個定義很重要,因為我們用的是大塊nand!! */
#undef CONFIG_ENV_IS_IN_FLASH
#define CONFIG_ENV_IS_IN_NAND 1 /* 環境變數的儲存位置 */
#endif
修改/drivers/mtd/nand/Makefile,在其中新增:
COBJS-y += s3c2410_nand.o
COBJS-$(CONFIG_NAND_S3C2440) += s3c2410_nand.o
#if 0
#define NFCONF __REGi(NF_BASE + 0x0)
#define NFCMD __REGb(NF_BASE + 0x4)
#define NFADDR __REGb(NF_BASE + 0x8)
#define NFDATA __REGb(NF_BASE + 0xc)
#define NFSTAT __REGb(NF_BASE + 0x10)
#define NFECC0 __REGb(NF_BASE + 0x14)
#define NFECC1 __REGb(NF_BASE + 0x15)
#define NFECC2 __REGb(NF_BASE + 0x16)
#endif
#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 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
uboot程式碼中的NAND Flash的讀寫驅動中存在一些錯誤,需要進行修改後才能完成,主要修改drivers/mtd/nand/s3c2410_nand.c檔案,首先修改27行如下:
修改s3c2410_hwcontrol函式 ,這個函式用來控制傳送命令還是地址。board_nand_init函式。
首先宣告一個全域性變數 ulong IO_ADDR_W = NF_BASE;
#ifdef CONFIG_S3C2410_NAND_HWECC //這個巨集沒有定義,所以我們不用關心ECC之類的。
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 (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 defined(CONFIG_S3C2440)
if (ctrl & NAND_NCE)
NFCONT&= ~S3C2410_NFCONT_nFCE; //原始碼中是NFCONF,S3C2410_NFCONF_nFCE
else
NFCONT|=S3C2410_NFCONT_nFCE; //原始碼中是NFCONF,S3C2410_NFCONF_nFCE
#endif
}
if (cmd != NAND_CMD_NONE)
// writeb(cmd, chip->IO_ADDR_W);
writeb(cmd, (void *)IO_ADDR_W);
}
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);
/* initialize hardware */
twrph0 = 0; twrph1 = 4; tacls = 2;
cfg = 0;
cfg |= S3C2410_NFCONF_TACLS(tacls - 1);
cfg |= S3C2410_NFCONF_TWRPH0(twrph0 - 1);
cfg |= S3C2410_NFCONF_TWRPH1(twrph1 - 1);
NFCONF = cfg;
cfg = (0<<13)|(0<<12)|(0<<10)|(0<<9)|(0<<8)|(0<<6)|(0<<5)|(1<<4)|(0<<1)|(1<<0);
NFCONT = cfg;
* initialize nand_chip data structure */
nand->IO_ADDR_R = nand->IO_ADDR_W = (void *)0x4e000010; //NFSTAT 的地址是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;
/*以下是校驗碼的設定,可以不用設定*/
#ifdef CONFIG_S3C2410_NAND_HWECC
nand->ecc.hwctl = s3c2410_nand_enable_hwecc;
nand->ecc.calculate = s3c2410_nand_calculate_ecc;
nand->ecc.correct = s3c2410_nand_correct_data;
nand->ecc.mode = NAND_ECC_HW3_512;
#else
nand->ecc.mode = NAND_ECC_SOFT;
#endif
ifdef CONFIG_S3C2410_NAND_BBT
nand->options = NAND_USE_FLASH_BBT;
#else
nand->options = 0;
#endif
DEBUGN("end of nand_init\n");
return 0;
}
參考地址:http://blog.csdn.net/yanghao23/article/details/7700699