读书人

U-boot移栽 (v2012.04.1 S3C2440平台)

发布时间: 2012-09-28 00:03:35 作者: rapoo

U-boot移植 (v2012.04.1 S3C2440平台) (三) Nor flash Nand flash 驱动支持

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

读书人网 >Flash

热点推荐