7 NOR Flash(SSTVF1601) 支持
在u-boot中添加对Nor flash的支持比较简单,大多数Nor flash都支持CFI接口,而u-boot有对cfi flash的驱动支持。对于SSTVF1601,并不支持标准的CFI接口,所以得使用JEDEC接口。但jedec_flash.c中并没有SSTVF1601的配置信息,所以得手动添加上:
drivers/mtd/jedec_flash.c:
static const struct amd_flash_info jedec_table[] = {
…
#ifdef CONFIG_SYS_FLASH_LEGACY_1024Kx16
{
.mfr_id= (u16)SST_MANUFACT,
.dev_id = SST39VF1601,
.name = "SST 39VF1601",
.uaddr = {
[1] = MTD_UADDR_0x5555_0x2AAA /* x16 */
},
.DevSize = SIZE_2MiB,
.CmdSet = P_ID_AMD_STD,
.NumEraseRegions= 4,
.regions = {
ERASEINFO(0x1000,96),
ERASEINFO(0x1000,160),
ERASEINFO(0x1000,240),
ERASEINFO(0x1000,16),
}
},
#endif
};
修改micro2440.h:
/*-----------------------------------------------------------------------
* FLASH and environment organization
*/
#define CONFIG_SYS_FLASH_CFI
#define CONFIG_FLASH_CFI_DRIVER
#define CONFIG_FLASH_CFI_LEGACY
#define CONFIG_SYS_FLASH_LEGACY_1024Kx16
#define CONFIG_FLASH_SHOW_PROGRESS45
#define CONFIG_SYS_MAX_FLASH_BANKS1
#define CONFIG_SYS_FLASH_BANKS_LIST { CONFIG_SYS_FLASH_BASE }
#define CONFIG_SYS_MAX_FLASH_SECT(512)
#define CONFIG_ENV_ADDR(CONFIG_SYS_FLASH_BASE + 0x1f0000)
#define CONFIG_ENV_IS_IN_FLASH
#define CONFIG_ENV_SIZE0x10000
7 NAND Flash支持
u-boot的driver/mtd/nand下有s3c2410 nand控制器的驱动,并没有s3c2440的。但2410和2440的nand控制器差别并不大,我们可以在2410的基础上进行移植。具体代码可以在我的github(https://github.com/novawl/u-boot-v2010.4.1)下的drivers/mtd/nand/s3c2440_nand.c中查看。需要注意的是,hwcontrol函数中,当cmd不为命令时,得将IO_ADDR_W赋值为nfdata地址,不然数据将无法写入到nand flash中。
static void s3c2440_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
{
struct nand_chip *chip = mtd->priv;
struct s3c2440_nand *nand = s3c2440_get_base_nand();
debug("hwcontrol(): 0x%02x 0x%02x\n", cmd, ctrl);
if (ctrl & NAND_CTRL_CHANGE) {
ulong IO_ADDR_W = (ulong)nand;
if (!(ctrl & NAND_CLE))
IO_ADDR_W |= S3C2440_ADDR_NCLE;
if (!(ctrl & NAND_ALE))
IO_ADDR_W |= S3C2440_ADDR_NALE;
if (cmd == NAND_CMD_NONE)
IO_ADDR_W = &nand->nfdata;
chip->IO_ADDR_W = (void *)IO_ADDR_W;
if (ctrl & NAND_NCE)
writel(readl(&nand->nfcont) & ~S3C2440_NFCONT_nFCE, &nand->nfcont);
else
writel(readl(&nand->nfcont) | S3C2440_NFCONT_nFCE, &nand->nfcont);
}
if (cmd != NAND_CMD_NONE)
writeb(cmd, chip->IO_ADDR_W);
}
修改arch/arm/lib/board.c,当从Nor flash启动时才初始化nor flash,否则只初始化nand flash:
#if !defined(CONFIG_SYS_NO_FLASH)
static char *failed = "*** failed ***\n";
#ifdef CONFIG_MICRO2440
extern int BootFrmNORFlash(); /*在board/samsung/micro2440/nand.c中实现*/
#endif
#endif
void board_init_r(gd_t *id, ulong dest_addr)
…
#if !defined(CONFIG_SYS_NO_FLASH)
#ifdef CONFIG_MICRO2440
if (BootFrmNORFlash()) {
#endif
puts("Flash: ");
flash_size = flash_init();
if (flash_size > 0) {
# ifdef CONFIG_SYS_FLASH_CHECKSUM
char *s = getenv("flashchecksum");
print_size(flash_size, "");
/*
* Compute and print flash CRC if flashchecksum is set to 'y'
*
* NOTE: Maybe we should add some WATCHDOG_RESET()? XXX
*/
if (s && (*s == 'y')) {
printf(" CRC: %08X", crc32(0, (const unsigned char *) CONFIG_SYS_FLASH_BASE, flash_size));
}
putc('\n');
# else/* !CONFIG_SYS_FLASH_CHECKSUM */
print_size(flash_size, "\n");
# endif /* CONFIG_SYS_FLASH_CHECKSUM */
} else {
puts(failed);
hang();
}
#ifdef CONFIG_MICRO2440
}
#endif
#endif
#if defined(CONFIG_CMD_NAND)
puts("NAND: ");
nand_init();/* go init the NAND */
#endif
ECC校验:
s3c2410和s3c2440 Nand flash控制器ECC校验模块有很大差别,所以基于s3c2440_nand.c的ecc校验函数和s3c2410_nand.c有较大差别。下面是与ECC校验相关的三个函数的实现:
#ifdef CONFIG_S3C2440_NAND_HWECC
void s3c2440_nand_enable_hwecc(struct mtd_info *mtd, int mode)
{
struct s3c2440_nand *nand = s3c2440_get_base_nand();
debug("s3c2410_nand_enable_hwecc(%p, %d)\n", mtd, mode);
writel(readl(&nand->nfcont) | S3C2440_NFCONT_INITECC, &nand->nfcont);
}
static int s3c2440_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code)
{
struct s3c2440_nand *nand = s3c2440_get_base_nand();
unsigned long ecc = readl(&nand->nfecc0);
ecc_code[0] = ecc;
ecc_code[1] = ecc >> 8;
ecc_code[2] = ecc >> 16;
debug("s3c2410_nand_calculate_hwecc(%p,): 0x%02x 0x%02x 0x%02x\n", mtd , ecc_code[0], ecc_code[1], ecc_code[2]);
return 0;
}
static int s3c2440_nand_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *calc_ecc)
{
if (read_ecc[0] == calc_ecc[0] &&
read_ecc[1] == calc_ecc[1] &&
read_ecc[2] == calc_ecc[2])
return 0;
printf("s3c2440_nand_correct_data: not implemented\n");
return -1;
}
#endif
micro2440.h中与ECC相关的配置:
#define CONFIG_S3C2440_NAND_HWECC
#define CONFIG_SYS_NAND_ECCSIZE512
#define CONFIG_SYS_NAND_ECCBYTES3
还有一个需要注意的地方是新版的u-boot中s3c24x0.h中定义的struct s3c2440_nand结构体定义并不全面,并没有nfmecc0 和nfmecc1等寄存器的实现,这里需要添加上:
#ifdef CONFIG_S3C2440
/* NAND FLASH (see S3C2440 manual chapter 6) */
struct s3c2440_nand {
u32 nfconf;
u32 nfcont;
u32 nfcmd;
u32 nfaddr;
u32 nfdata;
u32 nfeccd0;
u32 nfeccd1;
u32 nfeccd;
u32 nfstat;
u32 nfstat0;
u32 nfstat1;
u32 nfecc0;
u32 nfecc1;
u32 nfecc;
};
#endif