支持NAND Flash
首先在配置文件include/configs/myjz2440.h的宏CONFIG_COMMANDS中增加:
#define CFG_CMD_NAND 1 (大概在82行)
编译,出现nand.c的错误和警告
解决:在include/configs/myjz2440.h的最后面增加3个宏:
/*NAND flash settings*/
#define CFG_NAND_BASE?????? ?0????? //无实际意义:基地址,在board_nand_init中重新定义
#define CFG_MAX_NAND_DEVICE??? ?1?? //NAND Flash设备数目为1
#define NAND_MAX_CHIPS????????? 1?? //每个NAND设备由1个NADN芯片组成
修改配置文件后再编译,只有一个错误了“board_nand_init”函数未定义
?
board_nand_init需要自己编写,在cpu/arm920t/s3c24x0下新建nand_flash.c:
#include <common.h>
#if (CONFIG_COMMANDS & CFG_CMD_NAND) && !defined(CFG_NAND_LEGACY)
#include <s3c2410.h>
#include <nand.h>
DECLARE_GLOBAL_DATA_PTR;
#define S3C2410_NFSTAT_READY??? (1<<0)
#define S3C2410_NFCONF_nFCE???? (1<<11)
#define S3C2440_NFSTAT_READY??? (1<<0)
#define S3C2440_NFCONT_nFCE???? (1<<1)
/* select chip,for s3c2410 */
static void s3c2410_nand_select_chip(struct mtd_info *mtd,int chip)
{
??? S3C2410_NAND * const s3c2410nand = S3C2410_GetBase_NAND();
??? if (chip == -1) {
??????? s3c2410nand->NFCONF |= S3C2410_NFCONF_nFCE;
??? } else {
??????? s3c2410nand->NFCONF &= ~S3C2410_NFCONF_nFCE;
??? }
}
static void s3c2410_nand_hwcontrol(struct mtd_info *mtd,int cmd)
{
??? S3C2410_NAND * const s3c2410nand = S3C2410_GetBase_NAND();
??? struct nand_chip *chip = mtd->priv;
??? switch (cmd) {
??? case NAND_CTL_SETNCE:
??? case NAND_CTL_CLRNCE:
??????? printf("%s: called for NCEn",__FUNCTION__);
??????? break;
??? case NAND_CTL_SETCLE:
??????? chip->IO_ADDR_W = (void *)&s3c2410nand->NFCMD;
??????? break;
??? case NAND_CTL_SETALE:
??????? chip->IO_ADDR_W = (void *)&s3c2410nand->NFADDR;
??????? break;
??????? /* NAND_CTL_CLRCLE: */
??????? /* NAND_CTL_CLRALE: */
??? default:
??????? chip->IO_ADDR_W = (void *)&s3c2410nand->NFDATA;
??????? break;
??? }
}
static int s3c2410_nand_devready(struct mtd_info *mtd)
{
??? S3C2410_NAND * const s3c2410nand = S3C2410_GetBase_NAND();
??? return (s3c2410nand->NFSTAT & S3C2410_NFSTAT_READY);
}
/* select chip,for s3c2440 */
static void s3c2440_nand_select_chip(struct mtd_info *mtd,int chip)
{
??? S3C2440_NAND * const s3c2440nand = S3C2440_GetBase_NAND();
??? if (chip == -1) {
??????? s3c2440nand->NFCONT |= S3C2440_NFCONT_nFCE;
??? } else {
??????? s3c2440nand->NFCONT &= ~S3C2440_NFCONT_nFCE;
??? }
}
static void s3c2440_nand_hwcontrol(struct mtd_info *mtd,int cmd)
{
??? S3C2440_NAND * const s3c2440nand = S3C2440_GetBase_NAND();
??? struct nand_chip *chip = mtd->priv;
??? switch (cmd) {
??? case NAND_CTL_SETNCE:
??? case NAND_CTL_CLRNCE:
??????? printf("%s: called for NCEn",__FUNCTION__);
??????? break;
??? case NAND_CTL_SETCLE:
??????? chip->IO_ADDR_W = (void *)&s3c2440nand->NFCMD;
??????? break;
??? case NAND_CTL_SETALE:
??????? chip->IO_ADDR_W = (void *)&s3c2440nand->NFADDR;
??????? break;
??????? /* NAND_CTL_CLRCLE: */
??????? /* NAND_CTL_CLRALE: */
??? default:
??????? chip->IO_ADDR_W = (void *)&s3c2440nand->NFDATA;
??????? break;
??? }
}
static int s3c2440_nand_devready(struct mtd_info *mtd)
{
??? S3C2440_NAND * const s3c2440nand = S3C2440_GetBase_NAND();
??? return (s3c2440nand->NFSTAT & S3C2440_NFSTAT_READY);
}
static void s3c24x0_nand_inithw(void)
{
??? S3C2410_NAND * const s3c2410nand = S3C2410_GetBase_NAND();
??? S3C2440_NAND * const s3c2440nand = S3C2440_GetBase_NAND();
#define TACLS?? 0
#define TWRPH0? 4
#define TWRPH1? 2
??? if (gd->bd->bi_arch_number == MACH_TYPE_SMDK2410)
??? {
??????? /* Enable NAND flash controller,Initialize ECC,enable chip select,Set flash memory timing */
??????? s3c2410nand->NFCONF = (1<<15)|(1<<12)|(1<<11)|(TACLS<<8)|(TWRPH0<<4)|(TWRPH1<<0);
??? }
??? else
??? {
??????? /* Set flash memory timing */
??????? s3c2440nand->NFCONF = (TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4);
??????? /* Initialize ECC,NAND flash controller enable */
??????? s3c2440nand->NFCONT = (1<<4)|(0<<1)|(1<<0);
??? }
}
void board_nand_init(struct nand_chip *chip)
{
??? S3C2410_NAND * const s3c2410nand = S3C2410_GetBase_NAND();
??? S3C2440_NAND * const s3c2440nand = S3C2440_GetBase_NAND();
??? s3c24x0_nand_inithw();
??? if (gd->bd->bi_arch_number == MACH_TYPE_SMDK2410) {
??????? chip->IO_ADDR_R??? = (void *)&s3c2410nand->NFDATA;
??????? chip->IO_ADDR_W??? = (void *)&s3c2410nand->NFDATA;
??????? chip->hwcontrol??? = s3c2410_nand_hwcontrol;
??????? chip->dev_ready??? = s3c2410_nand_devready;
??????? chip->select_chip? = s3c2410_nand_select_chip;
??????? chip->options????? = 0;
??? } else {
??????? chip->IO_ADDR_R??? = (void *)&s3c2440nand->NFDATA;
??????? chip->IO_ADDR_W??? = (void *)&s3c2440nand->NFDATA;
??????? chip->hwcontrol??? = s3c2440_nand_hwcontrol;
??????? chip->dev_ready??? = s3c2440_nand_devready;
??????? chip->select_chip? = s3c2440_nand_select_chip;
??????? chip->options????? = 0;
??? }
??? chip->eccmode?????? = NAND_ECC_SOFT;
}
编写之前,需要针对S3C2440 NAND Flash定义一些数据结构和函数
在include/s3c24x0.h中增加S3C2440_NAND数据结构(168行)
/* 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 NFMECCD0;
??? S3C24X0_REG32 NFMECCD1;
??? S3C24X0_REG32 NFSECCD;
??? S3C24X0_REG32 NFSTAT;
??? S3C24X0_REG32 NFESTAT0;
??? S3C24X0_REG32 NFESTAT1;
??? S3C24X0_REG32 NFMECC0;
??? S3C24X0_REG32 NFMECC1;
??? S3C24X0_REG32 NFSECC;
??? S3C24X0_REG32 NFSBLK;
??? S3C24X0_REG32 NFEBLK;
} /*__attribute__((__packed__))*/ S3C2440_NAND;
?
在include/s3c2410.h中仿照S3C2410_GetBase_NAND函数(96行)
定义2440的函数:
static inline S3C2440_NAND * const S3C2440_GetBase_NAND(void)
{
??? return (S3C2440_NAND * const)S3C2410_NAND_BASE;
}
?
cpu/arm920t/s3c24x0/nand_flash.c中代码可以从Linux-2.6.13中/drivers/mtd/nand/s3c2410.c中移植过来的,代码见上。
?
修改cpu/arm920t/s3c24x0/Makefile:
COBJS? =? 加上一项nand_flash.o
?
编译后生成uboot镜像,但这里注意,现在还不支持NAND FLASH启动,只能烧到NOR FLASH中,后再用nand命令操作nand flash。要支持NAND FLASH启动,要修改cpu/arm920t/start.S,还要编写nand启动函数,这里先不考虑,复制现成的代码过来,以后再说。