@ -16,28 +16,6 @@
# include <asm/arch/cpu.h>
# include <asm/arch/mmc.h>
struct sunxi_mmc_des {
u32 reserved1_1 : 1 ;
u32 dic : 1 ; /* disable interrupt on completion */
u32 last_des : 1 ; /* 1-this data buffer is the last buffer */
u32 first_des : 1 ; /* 1-data buffer is the first buffer,
0 - data buffer contained in the next
descriptor is 1 st buffer */
u32 des_chain : 1 ; /* 1-the 2nd address in the descriptor is the
next descriptor address */
u32 end_of_ring : 1 ; /* 1-last descriptor flag when using dual
data buffer in descriptor */
u32 reserved1_2 : 24 ;
u32 card_err_sum : 1 ; /* transfer error flag */
u32 own : 1 ; /* des owner:1-idma owns it, 0-host owns it */
# define SDXC_DES_NUM_SHIFT 16
# define SDXC_DES_BUFFER_MAX_LEN (1 << SDXC_DES_NUM_SHIFT)
u32 data_buf1_sz : 16 ;
u32 data_buf2_sz : 16 ;
u32 buf_addr_ptr1 ;
u32 buf_addr_ptr2 ;
} ;
struct sunxi_mmc_host {
unsigned mmc_no ;
uint32_t * mclkreg ;
@ -189,6 +167,7 @@ static int mmc_core_init(struct mmc *mmc)
/* Reset controller */
writel ( SUNXI_MMC_GCTRL_RESET , & mmchost - > reg - > gctrl ) ;
udelay ( 1000 ) ;
return 0 ;
}
@ -204,6 +183,9 @@ static int mmc_trans_data_by_cpu(struct mmc *mmc, struct mmc_data *data)
unsigned timeout_msecs = 2000 ;
unsigned * buff = ( unsigned int * ) ( reading ? data - > dest : data - > src ) ;
/* Always read / write data through the CPU */
setbits_le32 ( & mmchost - > reg - > gctrl , SUNXI_MMC_GCTRL_ACCESS_BY_AHB ) ;
for ( i = 0 ; i < ( byte_cnt > > 2 ) ; i + + ) {
while ( readl ( & mmchost - > reg - > status ) & status_bit ) {
if ( ! timeout_msecs - - )
@ -220,85 +202,6 @@ static int mmc_trans_data_by_cpu(struct mmc *mmc, struct mmc_data *data)
return 0 ;
}
static int mmc_trans_data_by_dma ( struct mmc * mmc , struct mmc_data * data )
{
struct sunxi_mmc_host * mmchost = mmc - > priv ;
unsigned byte_cnt = data - > blocksize * data - > blocks ;
unsigned char * buff ;
unsigned des_idx = 0 ;
unsigned buff_frag_num =
( byte_cnt + SDXC_DES_BUFFER_MAX_LEN - 1 ) > > SDXC_DES_NUM_SHIFT ;
unsigned remain ;
unsigned i , rval ;
ALLOC_CACHE_ALIGN_BUFFER ( struct sunxi_mmc_des , pdes , buff_frag_num ) ;
buff = data - > flags & MMC_DATA_READ ?
( unsigned char * ) data - > dest : ( unsigned char * ) data - > src ;
remain = byte_cnt & ( SDXC_DES_BUFFER_MAX_LEN - 1 ) ;
flush_cache ( ( unsigned long ) buff , ( unsigned long ) byte_cnt ) ;
for ( i = 0 ; i < buff_frag_num ; i + + , des_idx + + ) {
memset ( ( void * ) & pdes [ des_idx ] , 0 , sizeof ( struct sunxi_mmc_des ) ) ;
pdes [ des_idx ] . des_chain = 1 ;
pdes [ des_idx ] . own = 1 ;
pdes [ des_idx ] . dic = 1 ;
if ( buff_frag_num > 1 & & i ! = buff_frag_num - 1 )
pdes [ des_idx ] . data_buf1_sz = 0 ; /* 0 == max_len */
else
pdes [ des_idx ] . data_buf1_sz = remain ;
pdes [ des_idx ] . buf_addr_ptr1 =
( u32 ) buff + i * SDXC_DES_BUFFER_MAX_LEN ;
if ( i = = 0 )
pdes [ des_idx ] . first_des = 1 ;
if ( i = = buff_frag_num - 1 ) {
pdes [ des_idx ] . dic = 0 ;
pdes [ des_idx ] . last_des = 1 ;
pdes [ des_idx ] . end_of_ring = 1 ;
pdes [ des_idx ] . buf_addr_ptr2 = 0 ;
} else {
pdes [ des_idx ] . buf_addr_ptr2 = ( u32 ) & pdes [ des_idx + 1 ] ;
}
}
flush_cache ( ( unsigned long ) pdes ,
sizeof ( struct sunxi_mmc_des ) * ( des_idx + 1 ) ) ;
rval = readl ( & mmchost - > reg - > gctrl ) ;
/* Enable DMA */
writel ( rval | SUNXI_MMC_GCTRL_DMA_RESET | SUNXI_MMC_GCTRL_DMA_ENABLE ,
& mmchost - > reg - > gctrl ) ;
/* Reset iDMA */
writel ( SUNXI_MMC_IDMAC_RESET , & mmchost - > reg - > dmac ) ;
/* Enable iDMA */
writel ( SUNXI_MMC_IDMAC_FIXBURST | SUNXI_MMC_IDMAC_ENABLE ,
& mmchost - > reg - > dmac ) ;
rval = readl ( & mmchost - > reg - > idie ) &
~ ( SUNXI_MMC_IDIE_TXIRQ | SUNXI_MMC_IDIE_RXIRQ ) ;
if ( data - > flags & MMC_DATA_WRITE )
rval | = SUNXI_MMC_IDIE_TXIRQ ;
else
rval | = SUNXI_MMC_IDIE_RXIRQ ;
writel ( rval , & mmchost - > reg - > idie ) ;
writel ( ( u32 ) pdes , & mmchost - > reg - > dlba ) ;
writel ( ( 0x2 < < 28 ) | ( 0x7 < < 16 ) | ( 0x01 < < 3 ) ,
& mmchost - > reg - > ftrglevel ) ;
return 0 ;
}
static void mmc_enable_dma_accesses ( struct mmc * mmc , int dma )
{
struct sunxi_mmc_host * mmchost = mmc - > priv ;
unsigned int gctrl = readl ( & mmchost - > reg - > gctrl ) ;
if ( dma )
gctrl & = ~ SUNXI_MMC_GCTRL_ACCESS_BY_AHB ;
else
gctrl | = SUNXI_MMC_GCTRL_ACCESS_BY_AHB ;
writel ( gctrl , & mmchost - > reg - > gctrl ) ;
}
static int mmc_rint_wait ( struct mmc * mmc , unsigned int timeout_msecs ,
unsigned int done_bit , const char * what )
{
@ -327,7 +230,6 @@ static int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
unsigned int timeout_msecs ;
int error = 0 ;
unsigned int status = 0 ;
unsigned int usedma = 0 ;
unsigned int bytecnt = 0 ;
if ( mmchost - > fatal_err )
@ -378,20 +280,8 @@ static int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
bytecnt = data - > blocksize * data - > blocks ;
debug ( " trans data %d bytes \n " , bytecnt ) ;
# if defined(CONFIG_MMC_SUNXI_USE_DMA) && !defined(CONFIG_SPL_BUILD)
if ( bytecnt > 64 ) {
# else
if ( 0 ) {
# endif
usedma = 1 ;
mmc_enable_dma_accesses ( mmc , 1 ) ;
ret = mmc_trans_data_by_dma ( mmc , data ) ;
writel ( cmdval | cmd - > cmdidx , & mmchost - > reg - > cmd ) ;
} else {
mmc_enable_dma_accesses ( mmc , 0 ) ;
writel ( cmdval | cmd - > cmdidx , & mmchost - > reg - > cmd ) ;
ret = mmc_trans_data_by_cpu ( mmc , data ) ;
}
writel ( cmdval | cmd - > cmdidx , & mmchost - > reg - > cmd ) ;
ret = mmc_trans_data_by_cpu ( mmc , data ) ;
if ( ret ) {
error = readl ( & mmchost - > reg - > rint ) & \
SUNXI_MMC_RINT_INTERRUPT_ERROR_BIT ;
@ -405,7 +295,7 @@ static int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
goto out ;
if ( data ) {
timeout_msecs = usedma ? 120 * bytecnt : 120 ;
timeout_msecs = 120 ;
debug ( " cacl timeout %x msec \n " , timeout_msecs ) ;
error = mmc_rint_wait ( mmc , timeout_msecs ,
data - > blocks > 1 ?
@ -442,23 +332,6 @@ static int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
debug ( " mmc resp 0x%08x \n " , cmd - > response [ 0 ] ) ;
}
out :
if ( data & & usedma ) {
/* IDMASTAREG
* IDST [ 0 ] : idma tx int
* IDST [ 1 ] : idma rx int
* IDST [ 2 ] : idma fatal bus error
* IDST [ 4 ] : idma descriptor invalid
* IDST [ 5 ] : idma error summary
* IDST [ 8 ] : idma normal interrupt sumary
* IDST [ 9 ] : idma abnormal interrupt sumary
*/
status = readl ( & mmchost - > reg - > idst ) ;
writel ( status , & mmchost - > reg - > idst ) ;
writel ( 0 , & mmchost - > reg - > idie ) ;
writel ( 0 , & mmchost - > reg - > dmac ) ;
writel ( readl ( & mmchost - > reg - > gctrl ) & ~ SUNXI_MMC_GCTRL_DMA_ENABLE ,
& mmchost - > reg - > gctrl ) ;
}
if ( error < 0 ) {
writel ( SUNXI_MMC_GCTRL_RESET , & mmchost - > reg - > gctrl ) ;
mmc_update_clk ( mmc ) ;