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;

}