@ -744,7 +744,7 @@ static void nand_command(struct mtd_info *mtd, unsigned int command,
/* Serially input address */
if ( column ! = - 1 ) {
/* Adjust columns for 16 bit buswidth */
if ( ( chip - > options & NAND_BUSWIDTH_16 ) & &
if ( chip - > options & NAND_BUSWIDTH_16 & &
! nand_opcode_8bits ( command ) )
column > > = 1 ;
chip - > cmd_ctrl ( mtd , column , ctrl ) ;
@ -837,7 +837,7 @@ static void nand_command_lp(struct mtd_info *mtd, unsigned int command,
/* Serially input address */
if ( column ! = - 1 ) {
/* Adjust columns for 16 bit buswidth */
if ( ( chip - > options & NAND_BUSWIDTH_16 ) & &
if ( chip - > options & NAND_BUSWIDTH_16 & &
! nand_opcode_8bits ( command ) )
column > > = 1 ;
chip - > cmd_ctrl ( mtd , column , ctrl ) ;
@ -1346,9 +1346,11 @@ static int nand_read_page_swecc(struct mtd_info *mtd, struct nand_chip *chip,
* @ data_offs : offset of requested data within the page
* @ readlen : data length
* @ bufpoi : buffer to store read data
* @ page : page number to read
*/
static int nand_read_subpage ( struct mtd_info * mtd , struct nand_chip * chip ,
uint32_t data_offs , uint32_t readlen , uint8_t * bufpoi )
uint32_t data_offs , uint32_t readlen , uint8_t * bufpoi ,
int page )
{
int start_step , end_step , num_steps ;
uint32_t * eccpos = chip - > ecc . layout - > eccpos ;
@ -1356,13 +1358,14 @@ 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 ;
int index ;
unsigned int max_bitflips = 0 ;
/* Column address within the page aligned to ECC size (256bytes) */
start_step = data_offs / chip - > ecc . size ;
end_step = ( data_offs + readlen - 1 ) / chip - > ecc . size ;
num_steps = end_step - start_step + 1 ;
index = start_step * chip - > ecc . bytes ;
/* Data size aligned to ECC ecc.size */
datafrag_len = num_steps * chip - > ecc . size ;
@ -1399,8 +1402,6 @@ static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip,
* Send the command to read the particular ECC bytes take care
* about buswidth alignment in read_buf .
*/
index = start_step * chip - > ecc . bytes ;
aligned_pos = eccpos [ index ] & ~ ( busw - 1 ) ;
aligned_len = eccfrag_len ;
if ( eccpos [ index ] & ( busw - 1 ) )
@ -1725,7 +1726,8 @@ read_retry:
else if ( ! aligned & & NAND_HAS_SUBPAGE_READ ( chip ) & &
! oob )
ret = chip - > ecc . read_subpage ( mtd , chip ,
col , bytes , bufpoi ) ;
col , bytes , bufpoi ,
page ) ;
else
ret = chip - > ecc . read_page ( mtd , chip , bufpoi ,
oob_required , page ) ;
@ -2189,7 +2191,7 @@ static int nand_write_page_raw_syndrome(struct mtd_info *mtd,
oob + = chip - > ecc . prepad ;
}
chip - > read _buf ( mtd , oob , eccbytes ) ;
chip - > w rit e_buf( mtd , oob , eccbytes ) ;
oob + = eccbytes ;
if ( chip - > ecc . postpad ) {
@ -3154,7 +3156,6 @@ static void nand_set_defaults(struct nand_chip *chip, int busw)
}
# ifdef CONFIG_SYS_NAND_ONFI_DETECTION
/* Sanitize ONFI strings so we can safely print them */
# ifndef __UBOOT__
static void sanitize_string ( uint8_t * s , size_t len )
@ -3189,6 +3190,7 @@ static u16 onfi_crc16(u16 crc, u8 const *p, size_t len)
return crc ;
}
# ifdef CONFIG_SYS_NAND_ONFI_DETECTION
/* Parse the Extended Parameter Page. */
static int nand_flash_detect_ext_param_page ( struct mtd_info * mtd ,
struct nand_chip * chip , struct nand_onfi_params * p )
@ -3304,15 +3306,6 @@ static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip,
chip - > read_byte ( mtd ) ! = ' F ' | | chip - > read_byte ( mtd ) ! = ' I ' )
return 0 ;
/*
* ONFI must be probed in 8 - bit mode or with NAND_BUSWIDTH_AUTO , not
* with NAND_BUSWIDTH_16
*/
if ( chip - > options & NAND_BUSWIDTH_16 ) {
pr_err ( " ONFI cannot be probed in 16-bit mode; aborting \n " ) ;
return 0 ;
}
chip - > cmdfunc ( mtd , NAND_CMD_PARAM , 0 , - 1 ) ;
for ( i = 0 ; i < 3 ; i + + ) {
for ( j = 0 ; j < sizeof ( * p ) ; j + + )
@ -3409,6 +3402,87 @@ static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip,
# endif
/*
* Check if the NAND chip is JEDEC compliant , returns 1 if it is , 0 otherwise .
*/
static int nand_flash_detect_jedec ( struct mtd_info * mtd , struct nand_chip * chip ,
int * busw )
{
struct nand_jedec_params * p = & chip - > jedec_params ;
struct jedec_ecc_info * ecc ;
int val ;
int i , j ;
/* Try JEDEC for unknown chip or LP */
chip - > cmdfunc ( mtd , NAND_CMD_READID , 0x40 , - 1 ) ;
if ( chip - > read_byte ( mtd ) ! = ' J ' | | chip - > read_byte ( mtd ) ! = ' E ' | |
chip - > read_byte ( mtd ) ! = ' D ' | | chip - > read_byte ( mtd ) ! = ' E ' | |
chip - > read_byte ( mtd ) ! = ' C ' )
return 0 ;
chip - > cmdfunc ( mtd , NAND_CMD_PARAM , 0x40 , - 1 ) ;
for ( i = 0 ; i < 3 ; i + + ) {
for ( j = 0 ; j < sizeof ( * p ) ; j + + )
( ( uint8_t * ) p ) [ j ] = chip - > read_byte ( mtd ) ;
if ( onfi_crc16 ( ONFI_CRC_BASE , ( uint8_t * ) p , 510 ) = =
le16_to_cpu ( p - > crc ) )
break ;
}
if ( i = = 3 ) {
pr_err ( " Could not find valid JEDEC parameter page; aborting \n " ) ;
return 0 ;
}
/* Check version */
val = le16_to_cpu ( p - > revision ) ;
if ( val & ( 1 < < 2 ) )
chip - > jedec_version = 10 ;
else if ( val & ( 1 < < 1 ) )
chip - > jedec_version = 1 ; /* vendor specific version */
if ( ! chip - > jedec_version ) {
pr_info ( " unsupported JEDEC version: %d \n " , val ) ;
return 0 ;
}
sanitize_string ( p - > manufacturer , sizeof ( p - > manufacturer ) ) ;
sanitize_string ( p - > model , sizeof ( p - > model ) ) ;
if ( ! mtd - > name )
mtd - > name = p - > model ;
mtd - > writesize = le32_to_cpu ( p - > byte_per_page ) ;
/* Please reference to the comment for nand_flash_detect_onfi. */
mtd - > erasesize = 1 < < ( fls ( le32_to_cpu ( p - > pages_per_block ) ) - 1 ) ;
mtd - > erasesize * = mtd - > writesize ;
mtd - > oobsize = le16_to_cpu ( p - > spare_bytes_per_page ) ;
/* Please reference to the comment for nand_flash_detect_onfi. */
chip - > chipsize = 1 < < ( fls ( le32_to_cpu ( p - > blocks_per_lun ) ) - 1 ) ;
chip - > chipsize * = ( uint64_t ) mtd - > erasesize * p - > lun_count ;
chip - > bits_per_cell = p - > bits_per_cell ;
if ( jedec_feature ( chip ) & JEDEC_FEATURE_16_BIT_BUS )
* busw = NAND_BUSWIDTH_16 ;
else
* busw = 0 ;
/* ECC info */
ecc = & p - > ecc_info [ 0 ] ;
if ( ecc - > codeword_size > = 9 ) {
chip - > ecc_strength_ds = ecc - > ecc_bits ;
chip - > ecc_step_ds = 1 < < ecc - > codeword_size ;
} else {
pr_warn ( " Invalid codeword size \n " ) ;
}
return 1 ;
}
/*
* nand_id_has_period - Check if an ID string has a given wraparound period
* @ id_data : the ID string
* @ arrlen : the length of the @ id_data array
@ -3718,10 +3792,10 @@ static bool find_full_id_nand(struct mtd_info *mtd, struct nand_chip *chip,
*/
static struct nand_flash_dev * nand_get_flash_type ( struct mtd_info * mtd ,
struct nand_chip * chip ,
int busw ,
int * maf_id , int * dev_id ,
struct nand_flash_dev * type )
{
int busw ;
int i , maf_idx ;
u8 id_data [ 8 ] ;
@ -3777,6 +3851,10 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
/* Check is chip is ONFI compliant */
if ( nand_flash_detect_onfi ( mtd , chip , & busw ) )
goto ident_done ;
/* Check if the chip is JEDEC compliant */
if ( nand_flash_detect_jedec ( mtd , chip , & busw ) )
goto ident_done ;
}
if ( ! type - > name )
@ -3856,12 +3934,29 @@ ident_done:
pr_info ( " device found, Manufacturer ID: 0x%02x, Chip ID: 0x%02x \n " ,
* maf_id , * dev_id ) ;
# ifdef CONFIG_SYS_NAND_ONFI_DETECTION
pr_info ( " %s %s \n " , nand_manuf_ids [ maf_idx ] . name ,
chip - > onfi_version ? chip - > onfi_params . model : type - > name ) ;
if ( chip - > onfi_version )
pr_info ( " %s %s \n " , nand_manuf_ids [ maf_idx ] . name ,
chip - > onfi_params . model ) ;
else if ( chip - > jedec_version )
pr_info ( " %s %s \n " , nand_manuf_ids [ maf_idx ] . name ,
chip - > jedec_params . model ) ;
else
pr_info ( " %s %s \n " , nand_manuf_ids [ maf_idx ] . name ,
type - > name ) ;
# else
pr_info ( " %s %s \n " , nand_manuf_ids [ maf_idx ] . name , type - > name ) ;
if ( chip - > jedec_version )
pr_info ( " %s %s \n " , nand_manuf_ids [ maf_idx ] . name ,
chip - > jedec_params . model ) ;
else
pr_info ( " %s %s \n " , nand_manuf_ids [ maf_idx ] . name ,
type - > name ) ;
pr_info ( " %s %s \n " , nand_manuf_ids [ maf_idx ] . name ,
type - > name ) ;
# endif
pr_info ( " %dMiB, %s, page size: %d, OOB size: %d \n " ,
( int ) ( chip - > chipsize > > 20 ) , nand_is_slc ( chip ) ? " SLC " : " MLC " ,
mtd - > writesize , mtd - > oobsize ) ;
@ -3882,18 +3977,16 @@ ident_done:
int nand_scan_ident ( struct mtd_info * mtd , int maxchips ,
struct nand_flash_dev * table )
{
int i , busw , nand_maf_id , nand_dev_id ;
int i , nand_maf_id , nand_dev_id ;
struct nand_chip * chip = mtd - > priv ;
struct nand_flash_dev * type ;
/* Get buswidth to select the correct functions */
busw = chip - > options & NAND_BUSWIDTH_16 ;
/* Set the default functions */
nand_set_defaults ( chip , busw ) ;
nand_set_defaults ( chip , chip - > options & NAND_BUSWIDTH_16 ) ;
/* Read the flash type */
type = nand_get_flash_type ( mtd , chip , busw ,
& nand_maf_id , & nand_dev_id , table ) ;
type = nand_get_flash_type ( mtd , chip , & nand_maf_id ,
& nand_dev_id , table ) ;
if ( IS_ERR ( type ) ) {
if ( ! ( chip - > options & NAND_SCAN_SILENT_NODEV ) )
@ -3947,15 +4040,30 @@ int nand_scan_tail(struct mtd_info *mtd)
int i ;
struct nand_chip * chip = mtd - > priv ;
struct nand_ecc_ctrl * ecc = & chip - > ecc ;
struct nand_buffers * nbuf ;
/* New bad blocks should be marked in OOB, flash-based BBT, or both */
BUG_ON ( ( chip - > bbt_options & NAND_BBT_NO_OOB_BBM ) & &
! ( chip - > bbt_options & NAND_BBT_USE_FLASH ) ) ;
if ( ! ( chip - > options & NAND_OWN_BUFFERS ) )
chip - > buffers = kmalloc ( sizeof ( * chip - > buffers ) , GFP_KERNEL ) ;
if ( ! chip - > buffers )
return - ENOMEM ;
if ( ! ( chip - > options & NAND_OWN_BUFFERS ) ) {
# ifndef __UBOOT__
nbuf = kzalloc ( sizeof ( * nbuf ) + mtd - > writesize
+ mtd - > oobsize * 3 , GFP_KERNEL ) ;
if ( ! nbuf )
return - ENOMEM ;
nbuf - > ecccalc = ( uint8_t * ) ( nbuf + 1 ) ;
nbuf - > ecccode = nbuf - > ecccalc + mtd - > oobsize ;
nbuf - > databuf = nbuf - > ecccode + mtd - > oobsize ;
# else
nbuf = kzalloc ( sizeof ( struct nand_buffers ) , GFP_KERNEL ) ;
# endif
chip - > buffers = nbuf ;
} else {
if ( ! chip - > buffers )
return - ENOMEM ;
}
/* Set the internal oob buffer location, just after the page data */
chip - > oob_poi = chip - > buffers - > databuf + mtd - > writesize ;
@ -4076,7 +4184,7 @@ int nand_scan_tail(struct mtd_info *mtd)
case NAND_ECC_SOFT_BCH :
if ( ! mtd_nand_has_bch ( ) ) {
pr_warn ( " CONFIG_MTD_ECC_BCH not enabled \n " ) ;
pr_warn ( " CONFIG_MTD_NAND_ ECC_BCH not enabled \n " ) ;
BUG ( ) ;
}
ecc - > calculate = nand_bch_calculate_ecc ;