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
},
.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:
#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();
#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, "");
if (s && (*s == 'y')) {
printf(" CRC: %08X", crc32(0, (const unsigned char *) CONFIG_SYS_FLASH_BASE, flash_size));
}
putc('\n');
# else
print_size(flash_size, "\n");
# endif
} else {
puts(failed);
hang();
}
#ifdef CONFIG_MICRO2440
}
#endif
#endif
#if defined(CONFIG_CMD_NAND)
puts("NAND: ");
nand_init();
#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
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