1、修改include/configs/smdk2440.h
(1)加入支持YAFFS的配置
/* YAFFS */
#define ENABLE_CMD_NAND_YAFFS 1
#define ENABLE_CMD_NAND_YAFFS_SKIPFB 1
2、修改common/cmd_nand.c文件
(1)在do_nand函数中的读写操作中加入yaffs的选项
if (!s || !strcmp(s, ".jffs2") ||
!strcmp(s, ".e") || !strcmp(s, ".i")) {
if (read)
ret = nand_read_skip_bad(nand, off, &size,
(u_char *)addr);
else
ret = nand_write_skip_bad(nand, off, &size,
(u_char *)addr);
/**************************YAFFS***********************************/
#if defined(ENABLE_CMD_NAND_YAFFS)
}else if ( s != NULL && (!strcmp(s, ".yaffs") || !strcmp(s, ".yaffs2"))){
if(read) {
printf("nand read.yaffs[2] is not provide temporarily!");
} else {
nand->rw_oob = 1;
#if defined(ENABLE_CMD_NAND_YAFFS_SKIPFB)
nand->skipfirstblk = 1;
#else
nand->skipfirstblk = 0;
#endif
ret = nand_write_skip_bad(nand,off,&size,(u_char *)addr);
#if defined(ENABLE_CMD_NAND_YAFFS_SKIPFB)
nand->skipfirstblk = 0;
#endif
nand->rw_oob = 0;
}
#endif
/**************************************************************/
} else if (!strcmp(s, ".oob")) {
/* out-of-band data */
mtd_oob_ops_t ops = {
.oobbuf = (u8 *)addr,
.ooblen = size,
.mode = MTD_OOB_RAW
};
if (read)
ret = nand->read_oob(nand, off, &ops);
else
ret = nand->write_oob(nand, off, &ops);
} else {
printf("Unknown nand command suffix '%s'.\n", s);
return 1;
}
(2)在U_BOOT_CMD中加入yaffs的选项
#if defined(ENABLE_CMD_NAND_YAFFS)
"nand read[.yaffs[2]] is not provide temporarily!\n"
"nand write[.yaffs[2]] addr off size - write the 'size' byte yaffs image starting\n"
" at offset 'off' from memory address 'addr' (.yaffs2 for 2048 + 16 NAND)\n"
#endif
3、修改include/linux/mtd/mtd.h
(1)在mtd_info结构体中加入nand驱动中用到的两个变量
struct mtd_info {
u_char rw_oob;
u_char skipfirstblk;
u_char type;
4、修改drivers/mtd/nand/nand_util.c
(1)在nand_write_skip_bad()函数中添加对OOB操作的支持
size_t len_incl_bad;
u_char *p_buffer = buffer;
/********************************************************/
#if defined(ENABLE_CMD_NAND_YAFFS)
if(nand->rw_oob==1) {
size_t oobsize = nand->oobsize;
size_t datasize = nand->writesize;
int datapages = 0;
if (((*length)%(nand->oobsize+nand->writesize)) != 0) {
printf("Attempt to write error length data!\n");
return -EINVAL;
}
datapages = *length/(datasize+oobsize);
*length = datapages*datasize;
left_to_write = *length;
}
#endif
/*****************************************************/
……
if ((offset + len_incl_bad) > nand->size) {
printf ("Attempt to write outside the flash area\n");
return -EINVAL;
}
/*******************************************************/
#if !defined(ENABLE_CMD_NAND_YAFFS)
if (len_incl_bad == *length) {
rval = nand_write (nand, offset, length, buffer);
if (rval != 0)
printf ("NAND write to offset %llx failed %d\n",
offset, rval);
return rval;
}
#endif
/********************************************************/
while (left_to_write > 0) {
size_t block_offset = offset & (nand->erasesize - 1);
size_t write_size;
……
/********************************************************/
#if defined(ENABLE_CMD_NAND_YAFFS)
if(nand->skipfirstblk == 1) {
nand->skipfirstblk = 0;
printf("Skip the first good block %llx\n",offset & ~(nand->erasesize - 1));
offset += nand->erasesize - block_offset;
continue;
}
#endif
/******************************************************/
if(left_to_write < (nand->erasesize - block_offset))
write_size = left_to_write;
else
write_size = nand->erasesize - block_offset;
printf("\rWriting at 0x%08lx -- ",offset);
……
left_to_write -= write_size;
offset+= write_size;
/***************************************************/
//p_buffer += write_size;
#if defined(ENABLE_CMD_NAND_YAFFS)
if(nand->rw_oob==1) {
p_buffer += write_size+(write_size/nand->writesize*nand->oobsize);
} else {
p_buffer += write_size;
}
#else
p_buffer += write_size;
#endif
/************************************************/
}
return0;
}
5、修改drivers/mtd/nand/nand_base.c
(1)在nand_write函数中加入OOB
static int nand_write(struct mtd_info *mtd, loff_t to, size_t len,
size_t *retlen, const uint8_t *buf)
{
structnand_chip *chip = mtd->priv;
intret;
/***************************************************************/
#if defined(ENABLE_CMD_NAND_YAFFS)
int oldopsmode = 0;
u_char data_buffer[len] ,oob_buffer[len/(mtd->writesize)*mtd->oobsize];
if(mtd->rw_oob==1) {
size_t oobsize = mtd->oobsize;
size_t datasize = mtd->writesize;
int i = 0;
uint8_t oobtemp[oobsize];
int datapages = 0;
datapages = len/(datasize);
for(i=0;i<(datapages);i++) {
memcpy((void *)(data_buffer+i*datasize),(void *)(buf+datasize*i+i*oobsize),datasize);
memcpy((void *)(oob_buffer+i*oobsize),(void *)(buf+datasize*(i+1)+i*oobsize),oobsize);
}
}
#endif
/**************************************************************/
/* Do not allow reads past end of device */
if ((to + len) > mtd->size)
return -EINVAL;
if (!len)
return 0;
nand_get_device(chip, mtd, FL_WRITING);
chip->ops.len = len;
/***********************************************************/
//chip->ops.datbuf = (uint8_t *)buf;
//chip->ops.oobbuf = NULL;
if(mtd->rw_oob!=1) {
chip->ops.datbuf = (uint8_t *)buf;
}else{
chip->ops.datbuf = (uint8_t *)data_buffer;
}
#if defined(ENABLE_CMD_NAND_YAFFS)
if(mtd->rw_oob!=1) {
chip->ops.oobbuf = NULL;
} else {
chip->ops.oobbuf = (uint8_t *)oob_buffer;
chip->ops.ooblen = mtd->oobsize;
oldopsmode = chip->ops.mode;
chip->ops.mode = MTD_OOB_RAW;
}
#else
chip->ops.oobbuf = NULL;
#endif
/*********************************************************/
ret = nand_do_write_ops(mtd, to, &chip->ops);
*retlen = chip->ops.retlen;
nand_release_device(mtd);
/*******************************************************/
#if defined(ENABLE_CMD_NAND_YAFFS)
chip->ops.mode = oldopsmode;
#endif
/******************************************************/
return ret;
}