@ -115,6 +115,35 @@ static int nand_do_write_oob(struct mtd_info *mtd, loff_t to,
static int nand_wait ( struct mtd_info * mtd , struct nand_chip * this ) ;
static int check_offs_len ( struct mtd_info * mtd ,
loff_t ofs , uint64_t len )
{
struct nand_chip * chip = mtd - > priv ;
int ret = 0 ;
/* Start address must align on block boundary */
if ( ofs & ( ( 1 < < chip - > phys_erase_shift ) - 1 ) ) {
MTDDEBUG ( MTD_DEBUG_LEVEL0 , " %s: Unaligned address \n " , __func__ ) ;
ret = - EINVAL ;
}
/* Length must align on block boundary */
if ( len & ( ( 1 < < chip - > phys_erase_shift ) - 1 ) ) {
MTDDEBUG ( MTD_DEBUG_LEVEL0 , " %s: Length not block aligned \n " ,
__func__ ) ;
ret = - EINVAL ;
}
/* Do not allow past end of device */
if ( ofs + len > mtd - > size ) {
MTDDEBUG ( MTD_DEBUG_LEVEL0 , " %s: Past end of device \n " ,
__func__ ) ;
ret = - EINVAL ;
}
return ret ;
}
/**
* nand_release_device - [ GENERIC ] release chip
* @ mtd : MTD device structure
@ -123,8 +152,10 @@ static int nand_wait(struct mtd_info *mtd, struct nand_chip *this);
*/
static void nand_release_device ( struct mtd_info * mtd )
{
struct nand_chip * this = mtd - > priv ;
this - > select_chip ( mtd , - 1 ) ; /* De-select the NAND device */
struct nand_chip * chip = mtd - > priv ;
/* De-select the NAND device */
chip - > select_chip ( mtd , - 1 ) ;
}
/**
@ -316,6 +347,9 @@ static int nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip)
struct nand_chip * chip = mtd - > priv ;
u16 bad ;
if ( chip - > options & NAND_BBT_SCANLASTPAGE )
ofs + = mtd - > erasesize - mtd - > writesize ;
page = ( int ) ( ofs > > chip - > page_shift ) & chip - > pagemask ;
if ( getchip ) {
@ -333,14 +367,18 @@ static int nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip)
bad = cpu_to_le16 ( chip - > read_word ( mtd ) ) ;
if ( chip - > badblockpos & 0x1 )
bad > > = 8 ;
if ( ( bad & 0xFF ) ! = 0xff )
res = 1 ;
else
bad & = 0xFF ;
} else {
chip - > cmdfunc ( mtd , NAND_CMD_READOOB , chip - > badblockpos , page ) ;
if ( chip - > read_byte ( mtd ) ! = 0xff )
res = 1 ;
bad = chip - > read_byte ( mtd ) ;
}
if ( likely ( chip - > badblockbits = = 8 ) )
res = bad ! = 0xFF ;
else
res = hweight8 ( bad ) < chip - > badblockbits ;
if ( getchip )
nand_release_device ( mtd ) ;
@ -359,7 +397,10 @@ static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs)
{
struct nand_chip * chip = mtd - > priv ;
uint8_t buf [ 2 ] = { 0 , 0 } ;
int block , ret ;
int block , ret , i = 0 ;
if ( chip - > options & NAND_BBT_SCANLASTPAGE )
ofs + = mtd - > erasesize - mtd - > writesize ;
/* Get block number */
block = ( int ) ( ofs > > chip - > bbt_erase_shift ) ;
@ -370,17 +411,31 @@ static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs)
if ( chip - > options & NAND_USE_FLASH_BBT )
ret = nand_update_bbt ( mtd , ofs ) ;
else {
/* We write two bytes, so we dont have to mess with 16 bit
* access
*/
nand_get_device ( chip , mtd , FL_WRITING ) ;
ofs + = mtd - > oobsize ;
chip - > ops . len = chip - > ops . ooblen = 2 ;
chip - > ops . datbuf = NULL ;
chip - > ops . oobbuf = buf ;
chip - > ops . ooboffs = chip - > badblockpos & ~ 0x01 ;
ret = nand_do_write_oob ( mtd , ofs , & chip - > ops ) ;
/* Write to first two pages and to byte 1 and 6 if necessary.
* If we write to more than one location , the first error
* encountered quits the procedure . We write two bytes per
* location , so we dont have to mess with 16 bit access .
*/
do {
chip - > ops . len = chip - > ops . ooblen = 2 ;
chip - > ops . datbuf = NULL ;
chip - > ops . oobbuf = buf ;
chip - > ops . ooboffs = chip - > badblockpos & ~ 0x01 ;
ret = nand_do_write_oob ( mtd , ofs , & chip - > ops ) ;
if ( ! ret & & ( chip - > options & NAND_BBT_SCANBYTE1AND6 ) ) {
chip - > ops . ooboffs = NAND_SMALL_BADBLOCK_POS
& ~ 0x01 ;
ret = nand_do_write_oob ( mtd , ofs , & chip - > ops ) ;
}
i + + ;
ofs + = mtd - > writesize ;
} while ( ! ret & & ( chip - > options & NAND_BBT_SCAN2NDPAGE ) & &
i < 2 ) ;
nand_release_device ( mtd ) ;
}
if ( ! ret )
@ -399,6 +454,11 @@ static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs)
static int nand_check_wp ( struct mtd_info * mtd )
{
struct nand_chip * chip = mtd - > priv ;
/* broken xD cards report WP despite being writable */
if ( chip - > options & NAND_BROKEN_XD )
return 0 ;
/* Check the WP bit */
chip - > cmdfunc ( mtd , NAND_CMD_STATUS , - 1 , - 1 ) ;
return ( chip - > read_byte ( mtd ) & NAND_STATUS_WP ) ? 0 : 1 ;
@ -419,11 +479,6 @@ static int nand_block_checkbad(struct mtd_info *mtd, loff_t ofs, int getchip,
{
struct nand_chip * chip = mtd - > priv ;
if ( ! ( chip - > options & NAND_BBT_SCANNED ) ) {
chip - > options | = NAND_BBT_SCANNED ;
chip - > scan_bbt ( mtd ) ;
}
if ( ! chip - > bbt )
return chip - > block_bad ( mtd , ofs , getchip ) ;
@ -686,9 +741,10 @@ static void nand_command_lp(struct mtd_info *mtd, unsigned int command,
*
* Get the device and lock it for exclusive access
*/
static int nand_get_device ( struct nand_chip * this , struct mtd_info * mtd , int new_state )
static int
nand_get_device ( struct nand_chip * chip , struct mtd_info * mtd , int new_state )
{
this - > state = new_state ;
chip - > state = new_state ;
return 0 ;
}
@ -701,10 +757,10 @@ static int nand_get_device (struct nand_chip *this, struct mtd_info *mtd, int ne
* Erase can take up to 400 ms and program up to 20 ms according to
* general NAND and SmartMedia specs
*/
static int nand_wait ( struct mtd_info * mtd , struct nand_chip * this )
static int nand_wait ( struct mtd_info * mtd , struct nand_chip * chip )
{
unsigned long timeo ;
int state = this - > state ;
int state = chip - > state ;
u32 time_start ;
if ( state = = FL_ERASING )
@ -712,10 +768,10 @@ static int nand_wait(struct mtd_info *mtd, struct nand_chip *this)
else
timeo = ( CONFIG_SYS_HZ * 20 ) / 1000 ;
if ( ( state = = FL_ERASING ) & & ( this - > options & NAND_IS_AND ) )
this - > cmdfunc ( mtd , NAND_CMD_STATUS_MULTI , - 1 , - 1 ) ;
if ( ( state = = FL_ERASING ) & & ( chip - > options & NAND_IS_AND ) )
chip - > cmdfunc ( mtd , NAND_CMD_STATUS_MULTI , - 1 , - 1 ) ;
else
this - > cmdfunc ( mtd , NAND_CMD_STATUS , - 1 , - 1 ) ;
chip - > cmdfunc ( mtd , NAND_CMD_STATUS , - 1 , - 1 ) ;
time_start = get_timer ( 0 ) ;
@ -725,11 +781,11 @@ static int nand_wait(struct mtd_info *mtd, struct nand_chip *this)
return 0x01 ;
}
if ( this - > dev_ready ) {
if ( this - > dev_ready ( mtd ) )
if ( chip - > dev_ready ) {
if ( chip - > dev_ready ( mtd ) )
break ;
} else {
if ( this - > read_byte ( mtd ) & NAND_STATUS_READY )
if ( chip - > read_byte ( mtd ) & NAND_STATUS_READY )
break ;
}
}
@ -739,7 +795,7 @@ static int nand_wait(struct mtd_info *mtd, struct nand_chip *this)
;
# endif /* PPCHAMELON_NAND_TIMER_HACK */
return this - > read_byte ( mtd ) ;
return ( int ) chip - > read_byte ( mtd ) ;
}
/**
@ -860,6 +916,7 @@ static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip,
int data_col_addr , i , gaps = 0 ;
int datafrag_len , eccfrag_len , aligned_len , aligned_pos ;
int busw = ( chip - > options & NAND_BUSWIDTH_16 ) ? 2 : 1 ;
int index = 0 ;
/* Column address wihin the page aligned to ECC size (256bytes). */
start_step = data_offs / chip - > ecc . size ;
@ -898,26 +955,30 @@ static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip,
} else {
/* send the command to read the particular ecc bytes */
/* take care about buswidth alignment in read_buf */
aligned_pos = eccpos [ start_step * chip - > ecc . bytes ] & ~ ( busw - 1 ) ;
index = start_step * chip - > ecc . bytes ;
aligned_pos = eccpos [ index ] & ~ ( busw - 1 ) ;
aligned_len = eccfrag_len ;
if ( eccpos [ start_step * chip - > ecc . bytes ] & ( busw - 1 ) )
if ( eccpos [ index ] & ( busw - 1 ) )
aligned_len + + ;
if ( eccpos [ ( start_step + num_steps ) * chip - > ecc . bytes ] & ( busw - 1 ) )
if ( eccpos [ index + ( num_steps * chip - > ecc . bytes ) ] & ( busw - 1 ) )
aligned_len + + ;
chip - > cmdfunc ( mtd , NAND_CMD_RNDOUT , mtd - > writesize + aligned_pos , - 1 ) ;
chip - > cmdfunc ( mtd , NAND_CMD_RNDOUT ,
mtd - > writesize + aligned_pos , - 1 ) ;
chip - > read_buf ( mtd , & chip - > oob_poi [ aligned_pos ] , aligned_len ) ;
}
for ( i = 0 ; i < eccfrag_len ; i + + )
chip - > buffers - > ecccode [ i ] = chip - > oob_poi [ eccpos [ i + start_step * chip - > ecc . bytes ] ] ;
chip - > buffers - > ecccode [ i ] = chip - > oob_poi [ eccpos [ i + index ] ] ;
p = bufpoi + data_col_addr ;
for ( i = 0 ; i < eccfrag_len ; i + = chip - > ecc . bytes , p + = chip - > ecc . size ) {
int stat ;
stat = chip - > ecc . correct ( mtd , p , & chip - > buffers - > ecccode [ i ] , & chip - > buffers - > ecccalc [ i ] ) ;
if ( stat = = - 1 )
stat = chip - > ecc . correct ( mtd , p ,
& chip - > buffers - > ecccode [ i ] , & chip - > buffers - > ecccalc [ i ] ) ;
if ( stat < 0 )
mtd - > ecc_stats . failed + + ;
else
mtd - > ecc_stats . corrected + = stat ;
@ -1142,6 +1203,9 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
int ret = 0 ;
uint32_t readlen = ops - > len ;
uint32_t oobreadlen = ops - > ooblen ;
uint32_t max_oobsize = ops - > mode = = MTD_OOB_AUTO ?
mtd - > oobavail : mtd - > oobsize ;
uint8_t * bufpoi , * oob , * buf ;
stats = mtd - > ecc_stats ;
@ -1187,7 +1251,8 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
/* Transfer not aligned data */
if ( ! aligned ) {
if ( ! NAND_SUBPAGE_READ ( chip ) & & ! oob )
if ( ! NAND_SUBPAGE_READ ( chip ) & & ! oob & &
! ( mtd - > ecc_stats . failed - stats . failed ) )
chip - > pagebuf = realpage ;
memcpy ( buf , chip - > buffers - > databuf + col , bytes ) ;
}
@ -1195,18 +1260,14 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
buf + = bytes ;
if ( unlikely ( oob ) ) {
/* Raw mode does data:oob:data:oob */
if ( ops - > mode ! = MTD_OOB_RAW ) {
int toread = min ( oobreadlen ,
chip - > ecc . layout - > oobavail ) ;
if ( toread ) {
oob = nand_transfer_oob ( chip ,
oob , ops , toread ) ;
oobreadlen - = toread ;
}
} else
buf = nand_transfer_oob ( chip ,
buf , ops , mtd - > oobsize ) ;
int toread = min ( oobreadlen , max_oobsize ) ;
if ( toread ) {
oob = nand_transfer_oob ( chip ,
oob , ops , toread ) ;
oobreadlen - = toread ;
}
}
if ( ! ( chip - > options & NAND_NO_READRDY ) ) {
@ -1793,13 +1854,12 @@ static int nand_write_page(struct mtd_info *mtd, struct nand_chip *chip,
* nand_fill_oob - [ Internal ] Transfer client buffer to oob
* @ chip : nand chip structure
* @ oob : oob data buffer
* @ len : oob data write length
* @ ops : oob ops structure
*/
static uint8_t * nand_fill_oob ( struct nand_chip * chip , uint8_t * oob ,
struct mtd_oob_ops * ops )
static uint8_t * nand_fill_oob ( struct nand_chip * chip , uint8_t * oob , size_t len ,
struct mtd_oob_ops * ops )
{
size_t len = ops - > ooblen ;
switch ( ops - > mode ) {
case MTD_OOB_PLACE :
@ -1838,7 +1898,7 @@ static uint8_t *nand_fill_oob(struct nand_chip *chip, uint8_t *oob,
return NULL ;
}
# define NOTALIGNED(x) (x & (chip->subpagesize - 1)) != 0
# define NOTALIGNED(x) (( x & (chip->subpagesize - 1)) != 0)
/**
* nand_do_write_ops - [ Internal ] NAND write with ECC
@ -1854,6 +1914,11 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to,
int chipnr , realpage , page , blockmask , column ;
struct nand_chip * chip = mtd - > priv ;
uint32_t writelen = ops - > len ;
uint32_t oobwritelen = ops - > ooblen ;
uint32_t oobmaxlen = ops - > mode = = MTD_OOB_AUTO ?
mtd - > oobavail : mtd - > oobsize ;
uint8_t * oob = ops - > oobbuf ;
uint8_t * buf = ops - > datbuf ;
int ret , subpage ;
@ -1890,6 +1955,10 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to,
if ( likely ( ! oob ) )
memset ( chip - > oob_poi , 0xff , mtd - > oobsize ) ;
/* Don't allow multipage oob writes with offset */
if ( oob & & ops - > ooboffs & & ( ops - > ooboffs + ops - > ooblen > oobmaxlen ) )
return - EINVAL ;
while ( 1 ) {
WATCHDOG_RESET ( ) ;
@ -1907,8 +1976,11 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to,
wbuf = chip - > buffers - > databuf ;
}
if ( unlikely ( oob ) )
oob = nand_fill_oob ( chip , oob , ops ) ;
if ( unlikely ( oob ) ) {
size_t len = min ( oobwritelen , oobmaxlen ) ;
oob = nand_fill_oob ( chip , oob , len , ops ) ;
oobwritelen - = len ;
}
ret = chip - > write_page ( mtd , chip , wbuf , page , cached ,
( ops - > mode = = MTD_OOB_RAW ) ) ;
@ -2043,7 +2115,7 @@ static int nand_do_write_oob(struct mtd_info *mtd, loff_t to,
chip - > pagebuf = - 1 ;
memset ( chip - > oob_poi , 0xff , mtd - > oobsize ) ;
nand_fill_oob ( chip , ops - > oobbuf , ops ) ;
nand_fill_oob ( chip , ops - > oobbuf , ops - > ooblen , ops ) ;
status = chip - > ecc . write_oob ( mtd , chip , page & chip - > pagemask ) ;
memset ( chip - > oob_poi , 0xff , mtd - > oobsize ) ;
@ -2166,27 +2238,10 @@ int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr,
__func__ , ( unsigned long long ) instr - > addr ,
( unsigned long long ) instr - > len ) ;
/* Start address must align on block boundary */
if ( instr - > addr & ( ( 1 < < chip - > phys_erase_shift ) - 1 ) ) {
MTDDEBUG ( MTD_DEBUG_LEVEL0 , " nand_erase: Unaligned address \n " ) ;
if ( check_offs_len ( mtd , instr - > addr , instr - > len ) )
return - EINVAL ;
}
/* Length must align on block boundary */
if ( instr - > len & ( ( 1 < < chip - > phys_erase_shift ) - 1 ) ) {
MTDDEBUG ( MTD_DEBUG_LEVEL0 ,
" nand_erase: Length not block aligned \n " ) ;
return - EINVAL ;
}
/* Do not allow erase past end of device */
if ( ( instr - > len + instr - > addr ) > mtd - > size ) {
MTDDEBUG ( MTD_DEBUG_LEVEL0 ,
" nand_erase: Erase past end of device \n " ) ;
return - EINVAL ;
}
instr - > fail_addr = 0xffffffff ;
instr - > fail_addr = MTD_FAIL_ADDR_UNKNOWN ;
/* Grab the lock and see if the device is available */
nand_get_device ( chip , mtd , FL_ERASING ) ;
@ -2371,7 +2426,8 @@ static int nand_block_markbad(struct mtd_info *mtd, loff_t ofs)
struct nand_chip * chip = mtd - > priv ;
int ret ;
if ( ( ret = nand_block_isbad ( mtd , ofs ) ) ) {
ret = nand_block_isbad ( mtd , ofs ) ;
if ( ret ) {
/* If it was bad already, return success and do nothing. */
if ( ret > 0 )
return 0 ;
@ -2444,6 +2500,7 @@ static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip,
int i ;
int val ;
/* try ONFI for unknow chip or LP */
chip - > cmdfunc ( mtd , NAND_CMD_READID , 0x20 , - 1 ) ;
if ( chip - > read_byte ( mtd ) ! = ' O ' | | chip - > read_byte ( mtd ) ! = ' N ' | |
chip - > read_byte ( mtd ) ! = ' F ' | | chip - > read_byte ( mtd ) ! = ' I ' )
@ -2486,7 +2543,6 @@ static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip,
if ( ! mtd - > name )
mtd - > name = p - > model ;
mtd - > writesize = le32_to_cpu ( p - > byte_per_page ) ;
mtd - > erasesize = le32_to_cpu ( p - > pages_per_block ) * mtd - > writesize ;
mtd - > oobsize = le16_to_cpu ( p - > spare_bytes_per_page ) ;
@ -2495,6 +2551,10 @@ static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip,
if ( le16_to_cpu ( p - > features ) & 1 )
* busw = NAND_BUSWIDTH_16 ;
chip - > options & = ~ NAND_CHIPOPTIONS_MSK ;
chip - > options | = ( NAND_NO_READRDY |
NAND_NO_AUTOINCR ) & NAND_CHIPOPTIONS_MSK ;
return 1 ;
}
# else
@ -2506,41 +2566,6 @@ static inline int nand_flash_detect_onfi(struct mtd_info *mtd,
}
# endif
static void nand_flash_detect_non_onfi ( struct mtd_info * mtd ,
struct nand_chip * chip ,
const struct nand_flash_dev * type ,
int * busw )
{
/* Newer devices have all the information in additional id bytes */
if ( ! type - > pagesize ) {
int extid ;
/* The 3rd id byte holds MLC / multichip data */
chip - > cellinfo = chip - > read_byte ( mtd ) ;
/* The 4th id byte is the important one */
extid = chip - > read_byte ( mtd ) ;
/* Calc pagesize */
mtd - > writesize = 1024 < < ( extid & 0x3 ) ;
extid > > = 2 ;
/* Calc oobsize */
mtd - > oobsize = ( 8 < < ( extid & 0x01 ) ) * ( mtd - > writesize > > 9 ) ;
extid > > = 2 ;
/* Calc blocksize. Blocksize is multiples of 64KiB */
mtd - > erasesize = ( 64 * 1024 ) < < ( extid & 0x03 ) ;
extid > > = 2 ;
/* Get buswidth information */
* busw = ( extid & 0x01 ) ? NAND_BUSWIDTH_16 : 0 ;
} else {
/*
* Old devices have chip data hardcoded in the device id table
*/
mtd - > erasesize = type - > erasesize ;
mtd - > writesize = type - > pagesize ;
mtd - > oobsize = mtd - > writesize / 32 ;
* busw = type - > options & NAND_BUSWIDTH_16 ;
}
}
/*
* Get the flash and manufacturer id and lookup if the type is supported
*/
@ -2550,8 +2575,9 @@ static const struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
int * maf_id , int * dev_id ,
const struct nand_flash_dev * type )
{
int ret , maf_idx ;
int tmp_id , tmp_manf ;
int i , maf_idx ;
u8 id_data [ 8 ] ;
int ret ;
/* Select the device */
chip - > select_chip ( mtd , 0 ) ;
@ -2577,15 +2603,13 @@ static const struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
chip - > cmdfunc ( mtd , NAND_CMD_READID , 0x00 , - 1 ) ;
/* Read manufacturer and device IDs */
tmp_manf = chip - > read_byte ( mtd ) ;
tmp_id = chip - > read_byte ( mtd ) ;
for ( i = 0 ; i < 2 ; i + + )
id_data [ i ] = chip - > read_byte ( mtd ) ;
if ( tmp_manf ! = * maf_id | | tmp_id ! = * dev_id ) {
if ( id_data [ 0 ] ! = * maf_id | | id_data [ 1 ] ! = * dev_id ) {
printk ( KERN_INFO " %s: second ID read did not match "
" %02x,%02x against %02x,%02x \n " , __func__ ,
* maf_id , * dev_id , tmp_manf , tmp_id ) ;
* maf_id , * dev_id , id_data [ 0 ] , id_data [ 1 ] ) ;
return ERR_PTR ( - ENODEV ) ;
}
@ -2596,30 +2620,121 @@ static const struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
if ( * dev_id = = type - > id )
break ;
if ( ! type - > name ) {
/* supress warning if there is no nand */
if ( * maf_id ! = 0x00 & & * maf_id ! = 0xff & &
* dev_id ! = 0x00 & & * dev_id ! = 0xff )
printk ( KERN_INFO " %s: unknown NAND device: "
" Manufacturer ID: 0x%02x, Chip ID: 0x%02x \n " ,
__func__ , * maf_id , * dev_id ) ;
return ERR_PTR ( - ENODEV ) ;
chip - > onfi_version = 0 ;
if ( ! type - > name | | ! type - > pagesize ) {
/* Check is chip is ONFI compliant */
ret = nand_flash_detect_onfi ( mtd , chip , & busw ) ;
if ( ret )
goto ident_done ;
}
chip - > cmdfunc ( mtd , NAND_CMD_READID , 0x00 , - 1 ) ;
/* Read entire ID string */
for ( i = 0 ; i < 8 ; i + + )
id_data [ i ] = chip - > read_byte ( mtd ) ;
if ( ! type - > name )
return ERR_PTR ( - ENODEV ) ;
if ( ! mtd - > name )
mtd - > name = type - > name ;
chip - > chipsize = ( uint64_t ) type - > chipsize < < 20 ;
chip - > onfi_version = 0 ;
ret = nand_flash_detect_onfi ( mtd , chip , & busw ) ;
if ( ! ret )
nand_flash_detect_non_onfi ( mtd , chip , type , & busw ) ;
if ( ! type - > pagesize & & chip - > init_size ) {
/* set the pagesize, oobsize, erasesize by the driver*/
busw = chip - > init_size ( mtd , chip , id_data ) ;
} else if ( ! type - > pagesize ) {
int extid ;
/* The 3rd id byte holds MLC / multichip data */
chip - > cellinfo = id_data [ 2 ] ;
/* The 4th id byte is the important one */
extid = id_data [ 3 ] ;
/*
* Field definitions are in the following datasheets :
* Old style ( 4 , 5 byte ID ) : Samsung K9GAG08U0M ( p .32 )
* New style ( 6 byte ID ) : Samsung K9GBG08U0M ( p .40 )
*
* Check for wraparound + Samsung ID + nonzero 6 th byte
* to decide what to do .
*/
if ( id_data [ 0 ] = = id_data [ 6 ] & & id_data [ 1 ] = = id_data [ 7 ] & &
id_data [ 0 ] = = NAND_MFR_SAMSUNG & &
( chip - > cellinfo & NAND_CI_CELLTYPE_MSK ) & &
id_data [ 5 ] ! = 0x00 ) {
/* Calc pagesize */
mtd - > writesize = 2048 < < ( extid & 0x03 ) ;
extid > > = 2 ;
/* Calc oobsize */
switch ( extid & 0x03 ) {
case 1 :
mtd - > oobsize = 128 ;
break ;
case 2 :
mtd - > oobsize = 218 ;
break ;
case 3 :
mtd - > oobsize = 400 ;
break ;
default :
mtd - > oobsize = 436 ;
break ;
}
extid > > = 2 ;
/* Calc blocksize */
mtd - > erasesize = ( 128 * 1024 ) < <
( ( ( extid > > 1 ) & 0x04 ) | ( extid & 0x03 ) ) ;
busw = 0 ;
} else {
/* Calc pagesize */
mtd - > writesize = 1024 < < ( extid & 0x03 ) ;
extid > > = 2 ;
/* Calc oobsize */
mtd - > oobsize = ( 8 < < ( extid & 0x01 ) ) *
( mtd - > writesize > > 9 ) ;
extid > > = 2 ;
/* Calc blocksize. Blocksize is multiples of 64KiB */
mtd - > erasesize = ( 64 * 1024 ) < < ( extid & 0x03 ) ;
extid > > = 2 ;
/* Get buswidth information */
busw = ( extid & 0x01 ) ? NAND_BUSWIDTH_16 : 0 ;
}
} else {
/*
* Old devices have chip data hardcoded in the device id table
*/
mtd - > erasesize = type - > erasesize ;
mtd - > writesize = type - > pagesize ;
mtd - > oobsize = mtd - > writesize / 32 ;
busw = type - > options & NAND_BUSWIDTH_16 ;
/*
* Check for Spansion / AMD ID + repeating 5 th , 6 th byte since
* some Spansion chips have erasesize that conflicts with size
* listed in nand_ids table
* Data sheet ( 5 byte ID ) : Spansion S30ML - P ORNAND ( p .39 )
*/
if ( * maf_id = = NAND_MFR_AMD & & id_data [ 4 ] ! = 0x00 & &
id_data [ 5 ] = = 0x00 & & id_data [ 6 ] = = 0x00 & &
id_data [ 7 ] = = 0x00 & & mtd - > writesize = = 512 ) {
mtd - > erasesize = 128 * 1024 ;
mtd - > erasesize < < = ( ( id_data [ 3 ] & 0x03 ) < < 1 ) ;
}
}
/* Get chip options, preserve non chip based options */
chip - > options & = ~ NAND_CHIPOPTIONS_MSK ;
chip - > options | = type - > options & NAND_CHIPOPTIONS_MSK ;
/* Check if chip is a not a samsung device. Do not clear the
* options for chips which are not having an extended id .
*/
if ( * maf_id ! = NAND_MFR_SAMSUNG & & ! type - > pagesize )
chip - > options & = ~ NAND_SAMSUNG_LP_OPTIONS ;
ident_done :
/*
* Set chip as a default . Board drivers can override it , if necessary
*/
@ -2654,18 +2769,48 @@ static const struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
ffs ( mtd - > erasesize ) - 1 ;
if ( chip - > chipsize & 0xffffffff )
chip - > chip_shift = ffs ( ( unsigned ) chip - > chipsize ) - 1 ;
else
chip - > chip_shift = ffs ( ( unsigned ) ( chip - > chipsize > > 32 ) ) + 31 ;
else {
chip - > chip_shift = ffs ( ( unsigned ) ( chip - > chipsize > > 32 ) ) ;
chip - > chip_shift + = 32 - 1 ;
}
chip - > badblockbits = 8 ;
/* Set the bad block position */
chip - > badblockpos = mtd - > writesize > 512 ?
NAND_LARGE_BADBLOCK_POS : NAND_SMALL_BADBLOCK_POS ;
if ( mtd - > writesize > 512 | | ( busw & NAND_BUSWIDTH_16 ) )
chip - > badblockpos = NAND_LARGE_BADBLOCK_POS ;
else
chip - > badblockpos = NAND_SMALL_BADBLOCK_POS ;
/* Check if chip is a not a samsung device. Do not clear the
* options for chips which are not having an extended id .
/*
* Bad block marker is stored in the last page of each block
* on Samsung and Hynix MLC devices ; stored in first two pages
* of each block on Micron devices with 2 KiB pages and on
* SLC Samsung , Hynix , Toshiba and AMD / Spansion . All others scan
* only the first page .
*/
if ( * maf_id ! = NAND_MFR_SAMSUNG & & ! type - > pagesize )
chip - > options & = ~ NAND_SAMSUNG_LP_OPTIONS ;
if ( ( chip - > cellinfo & NAND_CI_CELLTYPE_MSK ) & &
( * maf_id = = NAND_MFR_SAMSUNG | |
* maf_id = = NAND_MFR_HYNIX ) )
chip - > options | = NAND_BBT_SCANLASTPAGE ;
else if ( ( ! ( chip - > cellinfo & NAND_CI_CELLTYPE_MSK ) & &
( * maf_id = = NAND_MFR_SAMSUNG | |
* maf_id = = NAND_MFR_HYNIX | |
* maf_id = = NAND_MFR_TOSHIBA | |
* maf_id = = NAND_MFR_AMD ) ) | |
( mtd - > writesize = = 2048 & &
* maf_id = = NAND_MFR_MICRON ) )
chip - > options | = NAND_BBT_SCAN2NDPAGE ;
/*
* Numonyx / ST 2 K pages , x8 bus use BOTH byte 1 and 6
*/
if ( ! ( busw & NAND_BUSWIDTH_16 ) & &
* maf_id = = NAND_MFR_STMICRO & &
mtd - > writesize = = 2048 ) {
chip - > options | = NAND_BBT_SCANBYTE1AND6 ;
chip - > badblockpos = 0 ;
}
/* Check for AND chips with 4 page planes */
if ( chip - > options & NAND_4PAGE_ARRAY )
@ -2677,9 +2822,15 @@ static const struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
if ( mtd - > writesize > 512 & & chip - > cmdfunc = = nand_command )
chip - > cmdfunc = nand_command_lp ;
/* TODO onfi flash name */
MTDDEBUG ( MTD_DEBUG_LEVEL0 , " NAND device: Manufacturer ID: "
" 0x%02x, Chip ID: 0x%02x (%s %s) \n " , * maf_id , * dev_id ,
nand_manuf_ids [ maf_idx ] . name , type - > name ) ;
" 0x%02x, Chip ID: 0x%02x (%s %s) \n " , * maf_id , * dev_id ,
nand_manuf_ids [ maf_idx ] . name ,
# ifdef CONFIG_SYS_NAND_ONFI_DETECTION
chip - > onfi_version ? chip - > onfi_params . model : type - > name ) ;
# else
type - > name ) ;
# endif
return type ;
}
@ -2865,7 +3016,8 @@ int nand_scan_tail(struct mtd_info *mtd)
chip - > ecc . write_page_raw = nand_write_page_raw ;
chip - > ecc . read_oob = nand_read_oob_std ;
chip - > ecc . write_oob = nand_write_oob_std ;
chip - > ecc . size = 256 ;
if ( ! chip - > ecc . size )
chip - > ecc . size = 256 ;
chip - > ecc . bytes = 3 ;
break ;
@ -2973,7 +3125,8 @@ int nand_scan_tail(struct mtd_info *mtd)
/* Fill in remaining MTD driver data */
mtd - > type = MTD_NANDFLASH ;
mtd - > flags = MTD_CAP_NANDFLASH ;
mtd - > flags = ( chip - > options & NAND_ROM ) ? MTD_CAP_ROM :
MTD_CAP_NANDFLASH ;
mtd - > erase = nand_erase ;
mtd - > point = NULL ;
mtd - > unpoint = NULL ;
@ -2992,9 +3145,10 @@ int nand_scan_tail(struct mtd_info *mtd)
/* Check, if we should skip the bad block table scan */
if ( chip - > options & NAND_SKIP_BBTSCAN )
chip - > options | = NAND_BBT_SCANNED ;
return 0 ;
return 0 ;
/* Build bad block table */
return chip - > scan_bbt ( mtd ) ;
}
/**
@ -3039,4 +3193,9 @@ void nand_release(struct mtd_info *mtd)
kfree ( chip - > bbt ) ;
if ( ! ( chip - > options & NAND_OWN_BUFFERS ) )
kfree ( chip - > buffers ) ;
/* Free bad block descriptor memory */
if ( chip - > badblock_pattern & & chip - > badblock_pattern - > options
& NAND_BBT_DYNAMICSTRUCT )
kfree ( chip - > badblock_pattern ) ;
}