@ -763,6 +763,62 @@ static int pmecc_choose_ecc(struct atmel_nand_host *host,
}
# endif
# if defined(NO_GALOIS_TABLE_IN_ROM)
static uint16_t * pmecc_galois_table ;
static inline int deg ( unsigned int poly )
{
/* polynomial degree is the most-significant bit index */
return fls ( poly ) - 1 ;
}
static int build_gf_tables ( int mm , unsigned int poly ,
int16_t * index_of , int16_t * alpha_to )
{
unsigned int i , x = 1 ;
const unsigned int k = 1 < < deg ( poly ) ;
unsigned int nn = ( 1 < < mm ) - 1 ;
/* primitive polynomial must be of degree m */
if ( k ! = ( 1u < < mm ) )
return - EINVAL ;
for ( i = 0 ; i < nn ; i + + ) {
alpha_to [ i ] = x ;
index_of [ x ] = i ;
if ( i & & ( x = = 1 ) )
/* polynomial is not primitive (a^i=1 with 0<i<2^m-1) */
return - EINVAL ;
x < < = 1 ;
if ( x & k )
x ^ = poly ;
}
alpha_to [ nn ] = 1 ;
index_of [ 0 ] = 0 ;
return 0 ;
}
static uint16_t * create_lookup_table ( int sector_size )
{
int degree = ( sector_size = = 512 ) ?
PMECC_GF_DIMENSION_13 :
PMECC_GF_DIMENSION_14 ;
unsigned int poly = ( sector_size = = 512 ) ?
PMECC_GF_13_PRIMITIVE_POLY :
PMECC_GF_14_PRIMITIVE_POLY ;
int table_size = ( sector_size = = 512 ) ?
PMECC_INDEX_TABLE_SIZE_512 :
PMECC_INDEX_TABLE_SIZE_1024 ;
int16_t * addr = kzalloc ( 2 * table_size * sizeof ( uint16_t ) , GFP_KERNEL ) ;
if ( addr & & build_gf_tables ( degree , poly , addr , addr + table_size ) )
return NULL ;
return ( uint16_t * ) addr ;
}
# endif
static int atmel_pmecc_nand_init_params ( struct nand_chip * nand ,
struct mtd_info * mtd )
{
@ -810,11 +866,18 @@ static int atmel_pmecc_nand_init_params(struct nand_chip *nand,
sector_size = host - > pmecc_sector_size ;
/* TODO: need check whether cap & sector_size is validate */
# if defined(NO_GALOIS_TABLE_IN_ROM)
/*
* As pmecc_rom_base is the begin of the gallois field table , So the
* index offset just set as 0.
*/
host - > pmecc_index_table_offset = 0 ;
# else
if ( host - > pmecc_sector_size = = 512 )
host - > pmecc_index_table_offset = ATMEL_PMECC_INDEX_OFFSET_512 ;
else
host - > pmecc_index_table_offset = ATMEL_PMECC_INDEX_OFFSET_1024 ;
# endif
MTDDEBUG ( MTD_DEBUG_LEVEL1 ,
" Initialize PMECC params, cap: %d, sector: %d \n " ,
@ -823,7 +886,17 @@ static int atmel_pmecc_nand_init_params(struct nand_chip *nand,
host - > pmecc = ( struct pmecc_regs __iomem * ) ATMEL_BASE_PMECC ;
host - > pmerrloc = ( struct pmecc_errloc_regs __iomem * )
ATMEL_BASE_PMERRLOC ;
# if defined(NO_GALOIS_TABLE_IN_ROM)
pmecc_galois_table = create_lookup_table ( host - > pmecc_sector_size ) ;
if ( ! pmecc_galois_table ) {
dev_err ( host - > dev , " out of memory \n " ) ;
return - ENOMEM ;
}
host - > pmecc_rom_base = ( void __iomem * ) pmecc_galois_table ;
# else
host - > pmecc_rom_base = ( void __iomem * ) ATMEL_BASE_ROM ;
# endif
/* ECC is calculated for the whole page (1 step) */
nand - > ecc . size = mtd - > writesize ;