@ -665,6 +665,99 @@ static void atmel_pmecc_core_init(struct mtd_info *mtd)
pmecc_writel ( host - > pmecc , ctrl , PMECC_CTRL_ENABLE ) ;
}
# ifdef CONFIG_SYS_NAND_ONFI_DETECTION
/*
* get_onfi_ecc_param - Get ECC requirement from ONFI parameters
* @ ecc_bits : store the ONFI ECC correct bits capbility
* @ sector_size : in how many bytes that ONFI require to correct @ ecc_bits
*
* Returns - 1 if ONFI parameters is not supported . In this case @ ecc_bits ,
* @ sector_size are initialize to 0.
* Return 0 if success to get the ECC requirement .
*/
static int get_onfi_ecc_param ( struct nand_chip * chip ,
int * ecc_bits , int * sector_size )
{
* ecc_bits = * sector_size = 0 ;
if ( chip - > onfi_params . ecc_bits = = 0xff )
/* TODO: the sector_size and ecc_bits need to be find in
* extended ecc parameter , currently we don ' t support it .
*/
return - 1 ;
* ecc_bits = chip - > onfi_params . ecc_bits ;
/* The default sector size (ecc codeword size) is 512 */
* sector_size = 512 ;
return 0 ;
}
/*
* pmecc_choose_ecc - Get ecc requirement from ONFI parameters . If
* pmecc_corr_cap or pmecc_sector_size is 0 , then set it as
* ONFI ECC parameters .
* @ host : point to an atmel_nand_host structure .
* if host - > pmecc_corr_cap is 0 then set it as the ONFI ecc_bits .
* if host - > pmecc_sector_size is 0 then set it as the ONFI sector_size .
* @ chip : point to an nand_chip structure .
* @ cap : store the ONFI ECC correct bits capbility
* @ sector_size : in how many bytes that ONFI require to correct @ ecc_bits
*
* Return 0 if success . otherwise return the error code .
*/
static int pmecc_choose_ecc ( struct atmel_nand_host * host ,
struct nand_chip * chip ,
int * cap , int * sector_size )
{
/* Get ECC requirement from ONFI parameters */
* cap = * sector_size = 0 ;
if ( chip - > onfi_version ) {
if ( ! get_onfi_ecc_param ( chip , cap , sector_size ) ) {
MTDDEBUG ( MTD_DEBUG_LEVEL1 , " ONFI params, minimum required ECC: %d bits in %d bytes \n " ,
* cap , * sector_size ) ;
} else {
dev_info ( host - > dev , " NAND chip ECC reqirement is in Extended ONFI parameter, we don't support yet. \n " ) ;
}
} else {
dev_info ( host - > dev , " NAND chip is not ONFI compliant, assume ecc_bits is 2 in 512 bytes " ) ;
}
if ( * cap = = 0 & & * sector_size = = 0 ) {
/* Non-ONFI compliant or use extended ONFI parameters */
* cap = 2 ;
* sector_size = 512 ;
}
/* If head file doesn't specify then use the one in ONFI parameters */
if ( host - > pmecc_corr_cap = = 0 ) {
/* use the most fitable ecc bits (the near bigger one ) */
if ( * cap < = 2 )
host - > pmecc_corr_cap = 2 ;
else if ( * cap < = 4 )
host - > pmecc_corr_cap = 4 ;
else if ( * cap < = 8 )
host - > pmecc_corr_cap = 8 ;
else if ( * cap < = 12 )
host - > pmecc_corr_cap = 12 ;
else if ( * cap < = 24 )
host - > pmecc_corr_cap = 24 ;
else
return - EINVAL ;
}
if ( host - > pmecc_sector_size = = 0 ) {
/* use the most fitable sector size (the near smaller one ) */
if ( * sector_size > = 1024 )
host - > pmecc_sector_size = 1024 ;
else if ( * sector_size > = 512 )
host - > pmecc_sector_size = 512 ;
else
return - EINVAL ;
}
return 0 ;
}
# endif
static int atmel_pmecc_nand_init_params ( struct nand_chip * nand ,
struct mtd_info * mtd )
{
@ -678,8 +771,41 @@ static int atmel_pmecc_nand_init_params(struct nand_chip *nand,
nand - > ecc . correct = NULL ;
nand - > ecc . hwctl = NULL ;
cap = host - > pmecc_corr_cap = CONFIG_PMECC_CAP ;
sector_size = host - > pmecc_sector_size = CONFIG_PMECC_SECTOR_SIZE ;
# ifdef CONFIG_SYS_NAND_ONFI_DETECTION
host - > pmecc_corr_cap = host - > pmecc_sector_size = 0 ;
# ifdef CONFIG_PMECC_CAP
host - > pmecc_corr_cap = CONFIG_PMECC_CAP ;
# endif
# ifdef CONFIG_PMECC_SECTOR_SIZE
host - > pmecc_sector_size = CONFIG_PMECC_SECTOR_SIZE ;
# endif
/* Get ECC requirement of ONFI parameters. And if CONFIG_PMECC_CAP or
* CONFIG_PMECC_SECTOR_SIZE not defined , then use ecc_bits , sector_size
* from ONFI .
*/
if ( pmecc_choose_ecc ( host , nand , & cap , & sector_size ) ) {
dev_err ( host - > dev , " The NAND flash's ECC requirement(ecc_bits: %d, sector_size: %d) are not support! " ,
cap , sector_size ) ;
return - EINVAL ;
}
if ( cap > host - > pmecc_corr_cap )
dev_info ( host - > dev , " WARNING: Using different ecc correct bits(%d bit) from Nand ONFI ECC reqirement (%d bit). \n " ,
host - > pmecc_corr_cap , cap ) ;
if ( sector_size < host - > pmecc_sector_size )
dev_info ( host - > dev , " WARNING: Using different ecc correct sector size (%d bytes) from Nand ONFI ECC reqirement (%d bytes). \n " ,
host - > pmecc_sector_size , sector_size ) ;
# else /* CONFIG_SYS_NAND_ONFI_DETECTION */
host - > pmecc_corr_cap = CONFIG_PMECC_CAP ;
host - > pmecc_sector_size = CONFIG_PMECC_SECTOR_SIZE ;
# endif
cap = host - > pmecc_corr_cap ;
sector_size = host - > pmecc_sector_size ;
/* TODO: need check whether cap & sector_size is validate */
if ( host - > pmecc_sector_size = = 512 )
host - > pmecc_index_table_offset = ATMEL_PMECC_INDEX_OFFSET_512 ;
else