@ -331,7 +331,7 @@ static inline int onenand_bufferram_offset(struct mtd_info *mtd, int area)
if ( ONENAND_CURRENT_BUFFERRAM ( this ) ) {
if ( area = = ONENAND_DATARAM )
return mtd - > oobblock ;
return mtd - > writesize ;
if ( area = = ONENAND_SPARERAM )
return mtd - > oobsize ;
}
@ -482,6 +482,30 @@ static int onenand_update_bufferram(struct mtd_info *mtd, loff_t addr,
}
/**
* onenand_invalidate_bufferram - [ GENERIC ] Invalidate BufferRAM information
* @ param mtd MTD data structure
* @ param addr start address to invalidate
* @ param len length to invalidate
*
* Invalidate BufferRAM information
*/
static void onenand_invalidate_bufferram ( struct mtd_info * mtd , loff_t addr ,
unsigned int len )
{
struct onenand_chip * this = mtd - > priv ;
int i ;
loff_t end_addr = addr + len ;
/* Invalidate BufferRAM */
for ( i = 0 ; i < MAX_BUFFERRAM ; i + + ) {
loff_t buf_addr = this - > bufferram [ i ] . block < < this - > erase_shift ;
if ( buf_addr > = addr & & buf_addr < end_addr )
this - > bufferram [ i ] . valid = 0 ;
}
}
/**
* onenand_get_device - [ GENERIC ] Get chip for selected access
* @ param mtd MTD device structure
* @ param new_state the state which is requested
@ -541,15 +565,15 @@ static int onenand_read_ecc(struct mtd_info *mtd, loff_t from, size_t len,
onenand_get_device ( mtd , FL_READING ) ;
while ( read < len ) {
thislen = min_t ( int , mtd - > oobblock , len - read ) ;
thislen = min_t ( int , mtd - > writesize , len - read ) ;
column = from & ( mtd - > oobblock - 1 ) ;
if ( column + thislen > mtd - > oobblock )
thislen = mtd - > oobblock - column ;
column = from & ( mtd - > writesize - 1 ) ;
if ( column + thislen > mtd - > writesize )
thislen = mtd - > writesize - column ;
if ( ! onenand_check_bufferram ( mtd , from ) ) {
this - > command ( mtd , ONENAND_CMD_READ , from ,
mtd - > oobblock ) ;
mtd - > writesize ) ;
ret = this - > wait ( mtd , FL_READING ) ;
/* First copy data and check return value for ECC handling */
onenand_update_bufferram ( mtd , from , 1 ) ;
@ -664,7 +688,7 @@ int onenand_read_oob(struct mtd_info *mtd, loff_t from, size_t len,
/* Read more? */
if ( read < len ) {
/* Page size */
from + = mtd - > oobblock ;
from + = mtd - > writesize ;
column = 0 ;
}
}
@ -691,7 +715,7 @@ static int onenand_verify_page(struct mtd_info *mtd, u_char * buf,
void __iomem * dataram0 , * dataram1 ;
int ret = 0 ;
this - > command ( mtd , ONENAND_CMD_READ , addr , mtd - > oobblock ) ;
this - > command ( mtd , ONENAND_CMD_READ , addr , mtd - > writesize ) ;
ret = this - > wait ( mtd , FL_READING ) ;
if ( ret )
@ -701,9 +725,9 @@ static int onenand_verify_page(struct mtd_info *mtd, u_char * buf,
/* Check, if the two dataram areas are same */
dataram0 = this - > base + ONENAND_DATARAM ;
dataram1 = dataram0 + mtd - > oobblock ;
dataram1 = dataram0 + mtd - > writesize ;
if ( memcmp ( dataram0 , dataram1 , mtd - > oobblock ) )
if ( memcmp ( dataram0 , dataram1 , mtd - > writesize ) )
return - EBADMSG ;
return 0 ;
@ -712,7 +736,7 @@ static int onenand_verify_page(struct mtd_info *mtd, u_char * buf,
# define onenand_verify_page(...) (0)
# endif
# define NOTALIGNED(x) ((x & (mtd->oobblock - 1)) != 0)
# define NOTALIGNED(x) ((x & (mtd->writesize - 1)) != 0)
/**
* onenand_write_ecc - [ MTD Interface ] OneNAND write with ECC
@ -760,15 +784,15 @@ static int onenand_write_ecc(struct mtd_info *mtd, loff_t to, size_t len,
/* Loop until all data write */
while ( written < len ) {
int thislen = min_t ( int , mtd - > oobblock , len - written ) ;
int thislen = min_t ( int , mtd - > writesize , len - written ) ;
this - > command ( mtd , ONENAND_CMD_BUFFERRAM , to , mtd - > oobblock ) ;
this - > command ( mtd , ONENAND_CMD_BUFFERRAM , to , mtd - > writesize ) ;
this - > write_bufferram ( mtd , ONENAND_DATARAM , buf , 0 , thislen ) ;
this - > write_bufferram ( mtd , ONENAND_SPARERAM , ffchars , 0 ,
mtd - > oobsize ) ;
this - > command ( mtd , ONENAND_CMD_PROG , to , mtd - > oobblock ) ;
this - > command ( mtd , ONENAND_CMD_PROG , to , mtd - > writesize ) ;
onenand_update_bufferram ( mtd , to , 1 ) ;
@ -893,6 +917,25 @@ int onenand_write_oob(struct mtd_info *mtd, loff_t to, size_t len,
}
/**
* onenand_block_isbad_nolock - [ GENERIC ] Check if a block is marked bad
* @ param mtd MTD device structure
* @ param ofs offset from device start
* @ param allowbbt 1 , if its allowed to access the bbt area
*
* Check , if the block is bad , Either by reading the bad block table or
* calling of the scan function .
*/
static int onenand_block_isbad_nolock ( struct mtd_info * mtd , loff_t ofs , int allowbbt )
{
struct onenand_chip * this = mtd - > priv ;
struct bbm_info * bbm = this - > bbm ;
/* Return info from the table */
return bbm - > isbad_bbt ( mtd , ofs , allowbbt ) ;
}
/**
* onenand_erase - [ MTD Interface ] erase block ( s )
* @ param mtd MTD device structure
* @ param instr erase instruction
@ -950,6 +993,8 @@ int onenand_erase(struct mtd_info *mtd, struct erase_info *instr)
this - > command ( mtd , ONENAND_CMD_ERASE , addr , block_size ) ;
onenand_invalidate_bufferram ( mtd , addr , block_size ) ;
ret = this - > wait ( mtd , FL_ERASING ) ;
/* Check, if it is write protected */
if ( ret ) {
@ -1005,30 +1050,45 @@ void onenand_sync(struct mtd_info *mtd)
* onenand_block_isbad - [ MTD Interface ] Check whether the block at the given offset is bad
* @ param mtd MTD device structure
* @ param ofs offset relative to mtd start
*
* Check whether the block is bad
*/
int onenand_block_isbad ( struct mtd_info * mtd , loff_t ofs )
{
/*
* TODO
* 1. Bad block table ( BBT )
* - > using NAND BBT to support JFFS2
* 2. Bad block management ( BBM )
* - > bad block replace scheme
*
* Currently we do nothing
*/
return 0 ;
int ret ;
/* Check for invalid offset */
if ( ofs > mtd - > size )
return - EINVAL ;
onenand_get_device ( mtd , FL_READING ) ;
ret = onenand_block_isbad_nolock ( mtd , ofs , 0 ) ;
onenand_release_device ( mtd ) ;
return ret ;
}
/**
* onenand_block_markbad - [ MTD Interface ] Mark the block at the given offset as bad
* @ param mtd MTD device structure
* @ param ofs offset relative to mtd start
*
* Mark the block as bad
*/
int onenand_block_markbad ( struct mtd_info * mtd , loff_t ofs )
{
/* see above */
return 0 ;
struct onenand_chip * this = mtd - > priv ;
int ret ;
ret = onenand_block_isbad ( mtd , ofs ) ;
if ( ret ) {
/* If it was bad already, return success and do nothing */
if ( ret > 0 )
return 0 ;
return ret ;
}
ret = this - > block_markbad ( mtd , ofs ) ;
return ret ;
}
/**
@ -1184,10 +1244,8 @@ static int onenand_probe(struct mtd_info *mtd)
/* Reset OneNAND to read default register values */
this - > write_word ( ONENAND_CMD_RESET , this - > base + ONENAND_BOOTRAM ) ;
{
int i ;
for ( i = 0 ; i < 10000 ; i + + ) ;
}
/* Wait reset */
this - > wait ( mtd , FL_RESETING ) ;
/* Read manufacturer and device IDs from Register */
maf_id = this - > read_word ( this - > base + ONENAND_REG_MANUFACTURER_ID ) ;
@ -1212,16 +1270,16 @@ static int onenand_probe(struct mtd_info *mtd)
/* OneNAND page size & block size */
/* The data buffer size is equal to page size */
mtd - > oobblock =
mtd - > writesize =
this - > read_word ( this - > base + ONENAND_REG_DATA_BUFFER_SIZE ) ;
mtd - > oobsize = mtd - > oobblock > > 5 ;
mtd - > oobsize = mtd - > writesize > > 5 ;
/* Pagers per block is always 64 in OneNAND */
mtd - > erasesize = mtd - > oobblock < < 6 ;
mtd - > erasesize = mtd - > writesize < < 6 ;
this - > erase_shift = ffs ( mtd - > erasesize ) - 1 ;
this - > page_shift = ffs ( mtd - > oobblock ) - 1 ;
this - > page_shift = ffs ( mtd - > writesize ) - 1 ;
this - > ppb_shift = ( this - > erase_shift - this - > page_shift ) ;
this - > page_mask = ( mtd - > erasesize / mtd - > oobblock ) - 1 ;
this - > page_mask = ( mtd - > erasesize / mtd - > writesize ) - 1 ;
/* REVIST: Multichip handling */
@ -1240,11 +1298,10 @@ static int onenand_probe(struct mtd_info *mtd)
this - > options | = ONENAND_CONT_LOCK ;
}
mtd - > flags = MTD_CAP_NANDFLASH ;
mtd - > erase = onenand_erase ;
mtd - > read = onenand_read ;
mtd - > write = onenand_write ;
mtd - > read_ecc = onenand_read_ecc ;
mtd - > write_ecc = onenand_write_ecc ;
mtd - > read_oob = onenand_read_oob ;
mtd - > write_oob = onenand_write_oob ;
mtd - > sync = onenand_sync ;