@ -340,6 +340,115 @@ static int omap_calculate_ecc(struct mtd_info *mtd, const uint8_t *dat,
return 0 ;
}
# ifdef CONFIG_NAND_OMAP_GPMC_PREFETCH
# define PREFETCH_CONFIG1_CS_SHIFT 24
# define PREFETCH_FIFOTHRESHOLD_MAX 0x40
# define PREFETCH_FIFOTHRESHOLD(val) ((val) << 8)
# define PREFETCH_STATUS_COUNT(val) (val & 0x00003fff)
# define PREFETCH_STATUS_FIFO_CNT(val) ((val >> 24) & 0x7F)
# define ENABLE_PREFETCH (1 << 7)
/**
* omap_prefetch_enable - configures and starts prefetch transfer
* @ fifo_th : fifo threshold to be used for read / write
* @ count : number of bytes to be transferred
* @ is_write : prefetch read ( 0 ) or write post ( 1 ) mode
* @ cs : chip select to use
*/
static int omap_prefetch_enable ( int fifo_th , unsigned int count , int is_write , int cs )
{
uint32_t val ;
if ( fifo_th > PREFETCH_FIFOTHRESHOLD_MAX )
return - EINVAL ;
if ( readl ( & gpmc_cfg - > prefetch_control ) )
return - EBUSY ;
/* Set the amount of bytes to be prefetched */
writel ( count , & gpmc_cfg - > prefetch_config2 ) ;
val = ( cs < < PREFETCH_CONFIG1_CS_SHIFT ) | ( is_write & 1 ) |
PREFETCH_FIFOTHRESHOLD ( fifo_th ) | ENABLE_PREFETCH ;
writel ( val , & gpmc_cfg - > prefetch_config1 ) ;
/* Start the prefetch engine */
writel ( 1 , & gpmc_cfg - > prefetch_control ) ;
return 0 ;
}
/**
* omap_prefetch_reset - disables and stops the prefetch engine
*/
static void omap_prefetch_reset ( void )
{
writel ( 0 , & gpmc_cfg - > prefetch_control ) ;
writel ( 0 , & gpmc_cfg - > prefetch_config1 ) ;
}
static int __read_prefetch_aligned ( struct nand_chip * chip , uint32_t * buf , int len )
{
int ret ;
uint32_t cnt ;
struct omap_nand_info * info = chip - > priv ;
ret = omap_prefetch_enable ( PREFETCH_FIFOTHRESHOLD_MAX , len , 0 , info - > cs ) ;
if ( ret < 0 )
return ret ;
do {
int i ;
cnt = readl ( & gpmc_cfg - > prefetch_status ) ;
cnt = PREFETCH_STATUS_FIFO_CNT ( cnt ) ;
for ( i = 0 ; i < cnt / 4 ; i + + ) {
* buf + + = readl ( CONFIG_SYS_NAND_BASE ) ;
len - = 4 ;
}
} while ( len ) ;
omap_prefetch_reset ( ) ;
return 0 ;
}
static void omap_nand_read_prefetch8 ( struct mtd_info * mtd , uint8_t * buf , int len )
{
int ret ;
uint32_t head , tail ;
struct nand_chip * chip = mtd - > priv ;
/*
* If the destination buffer is unaligned , start with reading
* the overlap byte - wise .
*/
head = ( ( uint32_t ) buf ) % 4 ;
if ( head ) {
nand_read_buf ( mtd , buf , head ) ;
buf + = head ;
len - = head ;
}
/*
* Only transfer multiples of 4 bytes in a pre - fetched fashion .
* If there ' s a residue , care for it byte - wise afterwards .
*/
tail = len % 4 ;
ret = __read_prefetch_aligned ( chip , ( uint32_t * ) buf , len - tail ) ;
if ( ret < 0 ) {
/* fallback in case the prefetch engine is busy */
nand_read_buf ( mtd , buf , len ) ;
} else if ( tail ) {
buf + = len - tail ;
nand_read_buf ( mtd , buf , tail ) ;
}
}
# endif /* CONFIG_NAND_OMAP_GPMC_PREFETCH */
# ifdef CONFIG_NAND_OMAP_ELM
/*
* omap_reverse_list - re - orders list elements in reverse order [ internal ]
@ -452,115 +561,6 @@ static int omap_correct_data_bch(struct mtd_info *mtd, uint8_t *dat,
return ( err ) ? err : error_count ;
}
# ifdef CONFIG_NAND_OMAP_GPMC_PREFETCH
# define PREFETCH_CONFIG1_CS_SHIFT 24
# define PREFETCH_FIFOTHRESHOLD_MAX 0x40
# define PREFETCH_FIFOTHRESHOLD(val) ((val) << 8)
# define PREFETCH_STATUS_COUNT(val) (val & 0x00003fff)
# define PREFETCH_STATUS_FIFO_CNT(val) ((val >> 24) & 0x7F)
# define ENABLE_PREFETCH (1 << 7)
/**
* omap_prefetch_enable - configures and starts prefetch transfer
* @ fifo_th : fifo threshold to be used for read / write
* @ count : number of bytes to be transferred
* @ is_write : prefetch read ( 0 ) or write post ( 1 ) mode
* @ cs : chip select to use
*/
static int omap_prefetch_enable ( int fifo_th , unsigned int count , int is_write , int cs )
{
uint32_t val ;
if ( fifo_th > PREFETCH_FIFOTHRESHOLD_MAX )
return - EINVAL ;
if ( readl ( & gpmc_cfg - > prefetch_control ) )
return - EBUSY ;
/* Set the amount of bytes to be prefetched */
writel ( count , & gpmc_cfg - > prefetch_config2 ) ;
val = ( cs < < PREFETCH_CONFIG1_CS_SHIFT ) | ( is_write & 1 ) |
PREFETCH_FIFOTHRESHOLD ( fifo_th ) | ENABLE_PREFETCH ;
writel ( val , & gpmc_cfg - > prefetch_config1 ) ;
/* Start the prefetch engine */
writel ( 1 , & gpmc_cfg - > prefetch_control ) ;
return 0 ;
}
/**
* omap_prefetch_reset - disables and stops the prefetch engine
*/
static void omap_prefetch_reset ( void )
{
writel ( 0 , & gpmc_cfg - > prefetch_control ) ;
writel ( 0 , & gpmc_cfg - > prefetch_config1 ) ;
}
static int __read_prefetch_aligned ( struct nand_chip * chip , uint32_t * buf , int len )
{
int ret ;
uint32_t cnt ;
struct omap_nand_info * info = chip - > priv ;
ret = omap_prefetch_enable ( PREFETCH_FIFOTHRESHOLD_MAX , len , 0 , info - > cs ) ;
if ( ret < 0 )
return ret ;
do {
int i ;
cnt = readl ( & gpmc_cfg - > prefetch_status ) ;
cnt = PREFETCH_STATUS_FIFO_CNT ( cnt ) ;
for ( i = 0 ; i < cnt / 4 ; i + + ) {
* buf + + = readl ( CONFIG_SYS_NAND_BASE ) ;
len - = 4 ;
}
} while ( len ) ;
omap_prefetch_reset ( ) ;
return 0 ;
}
static void omap_nand_read_prefetch8 ( struct mtd_info * mtd , uint8_t * buf , int len )
{
int ret ;
uint32_t head , tail ;
struct nand_chip * chip = mtd - > priv ;
/*
* If the destination buffer is unaligned , start with reading
* the overlap byte - wise .
*/
head = ( ( uint32_t ) buf ) % 4 ;
if ( head ) {
nand_read_buf ( mtd , buf , head ) ;
buf + = head ;
len - = head ;
}
/*
* Only transfer multiples of 4 bytes in a pre - fetched fashion .
* If there ' s a residue , care for it byte - wise afterwards .
*/
tail = len % 4 ;
ret = __read_prefetch_aligned ( chip , ( uint32_t * ) buf , len - tail ) ;
if ( ret < 0 ) {
/* fallback in case the prefetch engine is busy */
nand_read_buf ( mtd , buf , len ) ;
} else if ( tail ) {
buf + = len - tail ;
nand_read_buf ( mtd , buf , tail ) ;
}
}
# endif /* CONFIG_NAND_OMAP_GPMC_PREFETCH */
/**
* omap_read_page_bch - hardware ecc based page read function
* @ mtd : mtd info structure