@ -2415,15 +2415,134 @@ static void nand_set_defaults(struct nand_chip *chip, int busw)
chip - > controller = & chip - > hwcontrol ;
}
# ifdef CONFIG_SYS_NAND_ONFI_DETECTION
static u16 onfi_crc16 ( u16 crc , u8 const * p , size_t len )
{
int i ;
while ( len - - ) {
crc ^ = * p + + < < 8 ;
for ( i = 0 ; i < 8 ; i + + )
crc = ( crc < < 1 ) ^ ( ( crc & 0x8000 ) ? 0x8005 : 0 ) ;
}
return crc ;
}
/*
* Check if the NAND chip is ONFI compliant , returns 1 if it is , 0 otherwise
*/
static int nand_flash_detect_onfi ( struct mtd_info * mtd ,
struct nand_chip * chip ,
int * busw )
{
struct nand_onfi_params * p = & chip - > onfi_params ;
int i ;
int val ;
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 ' )
return 0 ;
printk ( KERN_INFO " ONFI flash detected \n " ) ;
chip - > cmdfunc ( mtd , NAND_CMD_PARAM , 0 , - 1 ) ;
for ( i = 0 ; i < 3 ; i + + ) {
chip - > read_buf ( mtd , ( uint8_t * ) p , sizeof ( * p ) ) ;
if ( onfi_crc16 ( ONFI_CRC_BASE , ( uint8_t * ) p , 254 ) = =
le16_to_cpu ( p - > crc ) ) {
printk ( KERN_INFO " ONFI param page %d valid \n " , i ) ;
break ;
}
}
if ( i = = 3 )
return 0 ;
/* check version */
val = le16_to_cpu ( p - > revision ) ;
if ( val = = 1 | | val > ( 1 < < 4 ) ) {
printk ( KERN_INFO " %s: unsupported ONFI "
" version: %d \n " , __func__ , val ) ;
return 0 ;
}
if ( val & ( 1 < < 4 ) )
chip - > onfi_version = 22 ;
else if ( val & ( 1 < < 3 ) )
chip - > onfi_version = 21 ;
else if ( val & ( 1 < < 2 ) )
chip - > onfi_version = 20 ;
else
chip - > onfi_version = 10 ;
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 ) ;
chip - > chipsize = le32_to_cpu ( p - > blocks_per_lun ) * mtd - > erasesize ;
* busw = 0 ;
if ( le16_to_cpu ( p - > features ) & 1 )
* busw = NAND_BUSWIDTH_16 ;
return 1 ;
}
# else
static inline int nand_flash_detect_onfi ( struct mtd_info * mtd ,
struct nand_chip * chip ,
int * busw )
{
return 0 ;
}
# 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
*/
static const struct nand_flash_dev * nand_get_flash_type ( struct mtd_info * mtd ,
struct nand_chip * chip ,
int busw , int * maf_id ,
int busw ,
int * maf_id , int * dev_id ,
const struct nand_flash_dev * type )
{
int dev_id , maf_idx ;
int ret , maf_idx ;
int tmp_id , tmp_manf ;
/* Select the device */
@ -2440,7 +2559,7 @@ static const struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
/* Read manufacturer and device IDs */
* maf_id = chip - > read_byte ( mtd ) ;
dev_id = chip - > read_byte ( mtd ) ;
* dev_id = chip - > read_byte ( mtd ) ;
/* Try again to make sure, as some systems the bus-hold or other
* interface concerns can cause random data which looks like a
@ -2455,10 +2574,10 @@ static const struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
tmp_manf = chip - > read_byte ( mtd ) ;
tmp_id = chip - > read_byte ( mtd ) ;
if ( tmp_manf ! = * maf_id | | tmp_id ! = dev_id ) {
if ( tmp_manf ! = * maf_id | | tmp_id ! = * 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 , tmp_manf , tmp_id ) ;
return ERR_PTR ( - ENODEV ) ;
}
@ -2466,16 +2585,16 @@ static const struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
type = nand_flash_ids ;
for ( ; type - > name ! = NULL ; type + + )
if ( dev_id = = type - > id )
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 )
* 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 ) ;
__func__ , * maf_id , * dev_id ) ;
return ERR_PTR ( - ENODEV ) ;
}
@ -2483,35 +2602,20 @@ static const struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
mtd - > name = type - > name ;
chip - > chipsize = ( uint64_t ) type - > chipsize < < 20 ;
chip - > onfi_version = 0 ;
/* 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 ;
ret = nand_flash_detect_onfi ( mtd , chip , & busw ) ;
if ( ! ret )
nand_flash_detect_non_onfi ( mtd , chip , type , & busw ) ;
} 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 chip options, preserve non chip based options */
chip - > options & = ~ NAND_CHIPOPTIONS_MSK ;
chip - > options | = type - > options & NAND_CHIPOPTIONS_MSK ;
/*
* Set chip as a default . Board drivers can override it , if necessary
*/
chip - > options | = NAND_NO_AUTOINCR ;
/* Try to identify manufacturer */
for ( maf_idx = 0 ; nand_manuf_ids [ maf_idx ] . id ! = 0x0 ; maf_idx + + ) {
@ -2526,7 +2630,7 @@ static const struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
if ( busw ! = ( chip - > options & NAND_BUSWIDTH_16 ) ) {
printk ( KERN_INFO " NAND device: Manufacturer ID: "
" 0x%02x, Chip ID: 0x%02x (%s %s) \n " , * maf_id ,
dev_id , nand_manuf_ids [ maf_idx ] . name , mtd - > name ) ;
* dev_id , nand_manuf_ids [ maf_idx ] . name , mtd - > name ) ;
printk ( KERN_WARNING " NAND bus width %d instead %d bit \n " ,
( chip - > options & NAND_BUSWIDTH_16 ) ? 16 : 8 ,
busw ? 16 : 8 ) ;
@ -2549,15 +2653,6 @@ static const struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
chip - > badblockpos = mtd - > writesize > 512 ?
NAND_LARGE_BADBLOCK_POS : NAND_SMALL_BADBLOCK_POS ;
/* Get chip options, preserve non chip based options */
chip - > options & = ~ NAND_CHIPOPTIONS_MSK ;
chip - > options | = type - > options & NAND_CHIPOPTIONS_MSK ;
/*
* Set chip as a default . Board drivers can override it , if necessary
*/
chip - > options | = NAND_NO_AUTOINCR ;
/* Check if chip is a not a samsung device. Do not clear the
* options for chips which are not having an extended id .
*/
@ -2575,7 +2670,7 @@ static const struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
chip - > cmdfunc = nand_command_lp ;
MTDDEBUG ( MTD_DEBUG_LEVEL0 , " NAND device: Manufacturer ID: "
" 0x%02x, Chip ID: 0x%02x (%s %s) \n " , * maf_id , dev_id ,
" 0x%02x, Chip ID: 0x%02x (%s %s) \n " , * maf_id , * dev_id ,
nand_manuf_ids [ maf_idx ] . name , type - > name ) ;
return type ;
@ -2595,7 +2690,7 @@ static const struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
int nand_scan_ident ( struct mtd_info * mtd , int maxchips ,
const struct nand_flash_dev * table )
{
int i , busw , nand_maf_id ;
int i , busw , nand_maf_id , nand_dev_id ;
struct nand_chip * chip = mtd - > priv ;
const struct nand_flash_dev * type ;
@ -2605,7 +2700,7 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips,
nand_set_defaults ( chip , busw ) ;
/* Read the flash type */
type = nand_get_flash_type ( mtd , chip , busw , & nand_maf_id , table ) ;
type = nand_get_flash_type ( mtd , chip , busw , & nand_maf_id , & nand_dev_id , table ) ;
if ( IS_ERR ( type ) ) {
# ifndef CONFIG_SYS_NAND_QUIET_TEST
@ -2624,7 +2719,7 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips,
chip - > cmdfunc ( mtd , NAND_CMD_READID , 0x00 , - 1 ) ;
/* Read manufacturer and device IDs */
if ( nand_maf_id ! = chip - > read_byte ( mtd ) | |
type - > id ! = chip - > read_byte ( mtd ) )
nand_dev_ id ! = chip - > read_byte ( mtd ) )
break ;
}
# ifdef DEBUG