@ -31,6 +31,9 @@
# include <asm/io.h>
# include <asm/arch/mmc_host_def.h>
/* If we fail after 1 second wait, something is really bad */
# define MAX_RETRY_MS 1000
static int mmc_read_data ( hsmmc_t * mmc_base , char * buf , unsigned int size ) ;
static int mmc_write_data ( hsmmc_t * mmc_base , const char * buf , unsigned int siz ) ;
static struct mmc hsmmc_dev [ 2 ] ;
@ -70,18 +73,29 @@ unsigned char mmc_board_init(hsmmc_t *mmc_base)
void mmc_init_stream ( hsmmc_t * mmc_base )
{
ulong start ;
writel ( readl ( & mmc_base - > con ) | INIT_INITSTREAM , & mmc_base - > con ) ;
writel ( MMC_CMD0 , & mmc_base - > cmd ) ;
while ( ! ( readl ( & mmc_base - > stat ) & CC_MASK ) )
;
start = get_timer ( 0 ) ;
while ( ! ( readl ( & mmc_base - > stat ) & CC_MASK ) ) {
if ( get_timer ( 0 ) - start > MAX_RETRY_MS ) {
printf ( " %s: timedout waiting for cc! \n " , __func__ ) ;
return ;
}
}
writel ( CC_MASK , & mmc_base - > stat )
;
writel ( MMC_CMD0 , & mmc_base - > cmd )
;
while ( ! ( readl ( & mmc_base - > stat ) & CC_MASK ) )
;
start = get_timer ( 0 ) ;
while ( ! ( readl ( & mmc_base - > stat ) & CC_MASK ) ) {
if ( get_timer ( 0 ) - start > MAX_RETRY_MS ) {
printf ( " %s: timedout waiting for cc2! \n " , __func__ ) ;
return ;
}
}
writel ( readl ( & mmc_base - > con ) & ~ INIT_INITSTREAM , & mmc_base - > con ) ;
}
@ -91,16 +105,28 @@ static int mmc_init_setup(struct mmc *mmc)
hsmmc_t * mmc_base = ( hsmmc_t * ) mmc - > priv ;
unsigned int reg_val ;
unsigned int dsor ;
ulong start ;
mmc_board_init ( mmc_base ) ;
writel ( readl ( & mmc_base - > sysconfig ) | MMC_SOFTRESET ,
& mmc_base - > sysconfig ) ;
while ( ( readl ( & mmc_base - > sysstatus ) & RESETDONE ) = = 0 )
;
start = get_timer ( 0 ) ;
while ( ( readl ( & mmc_base - > sysstatus ) & RESETDONE ) = = 0 ) {
if ( get_timer ( 0 ) - start > MAX_RETRY_MS ) {
printf ( " %s: timedout waiting for cc2! \n " , __func__ ) ;
return TIMEOUT ;
}
}
writel ( readl ( & mmc_base - > sysctl ) | SOFTRESETALL , & mmc_base - > sysctl ) ;
while ( ( readl ( & mmc_base - > sysctl ) & SOFTRESETALL ) ! = 0x0 )
;
start = get_timer ( 0 ) ;
while ( ( readl ( & mmc_base - > sysctl ) & SOFTRESETALL ) ! = 0x0 ) {
if ( get_timer ( 0 ) - start > MAX_RETRY_MS ) {
printf ( " %s: timedout waiting for softresetall! \n " ,
__func__ ) ;
return TIMEOUT ;
}
}
writel ( DTW_1_BITMODE | SDBP_PWROFF | SDVS_3V0 , & mmc_base - > hctl ) ;
writel ( readl ( & mmc_base - > capa ) | VS30_3V0SUP | VS18_1V8SUP ,
& mmc_base - > capa ) ;
@ -116,8 +142,13 @@ static int mmc_init_setup(struct mmc *mmc)
( ICE_STOP | DTO_15THDTO | CEN_DISABLE ) ) ;
mmc_reg_out ( & mmc_base - > sysctl , ICE_MASK | CLKD_MASK ,
( dsor < < CLKD_OFFSET ) | ICE_OSCILLATE ) ;
while ( ( readl ( & mmc_base - > sysctl ) & ICS_MASK ) = = ICS_NOTREADY )
;
start = get_timer ( 0 ) ;
while ( ( readl ( & mmc_base - > sysctl ) & ICS_MASK ) = = ICS_NOTREADY ) {
if ( get_timer ( 0 ) - start > MAX_RETRY_MS ) {
printf ( " %s: timedout waiting for ics! \n " , __func__ ) ;
return TIMEOUT ;
}
}
writel ( readl ( & mmc_base - > sysctl ) | CEN_ENABLE , & mmc_base - > sysctl ) ;
writel ( readl ( & mmc_base - > hctl ) | SDBP_PWRON , & mmc_base - > hctl ) ;
@ -137,14 +168,23 @@ static int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
{
hsmmc_t * mmc_base = ( hsmmc_t * ) mmc - > priv ;
unsigned int flags , mmc_stat ;
unsigned int retry = 0x100000 ;
ulong start ;
while ( ( readl ( & mmc_base - > pstate ) & DATI_MASK ) = = DATI_CMDDIS )
;
start = get_timer ( 0 ) ;
while ( ( readl ( & mmc_base - > pstate ) & DATI_MASK ) = = DATI_CMDDIS ) {
if ( get_timer ( 0 ) - start > MAX_RETRY_MS ) {
printf ( " %s: timedout waiting for cmddis! \n " , __func__ ) ;
return TIMEOUT ;
}
}
writel ( 0xFFFFFFFF , & mmc_base - > stat ) ;
while ( readl ( & mmc_base - > stat ) )
;
start = get_timer ( 0 ) ;
while ( readl ( & mmc_base - > stat ) ) {
if ( get_timer ( 0 ) - start > MAX_RETRY_MS ) {
printf ( " %s: timedout waiting for stat! \n " , __func__ ) ;
return TIMEOUT ;
}
}
/*
* CMDREG
* CMDIDX [ 13 : 8 ] : Command index
@ -200,15 +240,14 @@ static int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
writel ( cmd - > cmdarg , & mmc_base - > arg ) ;
writel ( ( cmd - > cmdidx < < 24 ) | flags , & mmc_base - > cmd ) ;
start = get_timer ( 0 ) ;
do {
mmc_stat = readl ( & mmc_base - > stat ) ;
retry - - ;
} while ( ( mmc_stat = = 0 ) & & ( retry > 0 ) ) ;
if ( retry = = 0 ) {
printf ( " %s : timeout: No status update \n " , __func__ ) ;
return TIMEOUT ;
}
if ( get_timer ( 0 ) - start > MAX_RETRY_MS ) {
printf ( " %s : timeout: No status update \n " , __func__ ) ;
return TIMEOUT ;
}
} while ( ! mmc_stat ) ;
if ( ( mmc_stat & IE_CTO ) ! = 0 )
return TIMEOUT ;
@ -253,8 +292,14 @@ static int mmc_read_data(hsmmc_t *mmc_base, char *buf, unsigned int size)
count / = 4 ;
while ( size ) {
ulong start = get_timer ( 0 ) ;
do {
mmc_stat = readl ( & mmc_base - > stat ) ;
if ( get_timer ( 0 ) - start > MAX_RETRY_MS ) {
printf ( " %s: timedout waiting for status! \n " ,
__func__ ) ;
return TIMEOUT ;
}
} while ( mmc_stat = = 0 ) ;
if ( ( mmc_stat & ERRI_MASK ) ! = 0 )
@ -298,8 +343,14 @@ static int mmc_write_data(hsmmc_t *mmc_base, const char *buf, unsigned int size)
count / = 4 ;
while ( size ) {
ulong start = get_timer ( 0 ) ;
do {
mmc_stat = readl ( & mmc_base - > stat ) ;
if ( get_timer ( 0 ) - start > MAX_RETRY_MS ) {
printf ( " %s: timedout waiting for status! \n " ,
__func__ ) ;
return TIMEOUT ;
}
} while ( mmc_stat = = 0 ) ;
if ( ( mmc_stat & ERRI_MASK ) ! = 0 )
@ -334,6 +385,7 @@ static void mmc_set_ios(struct mmc *mmc)
{
hsmmc_t * mmc_base = ( hsmmc_t * ) mmc - > priv ;
unsigned int dsor = 0 ;
ulong start ;
/* configue bus width */
switch ( mmc - > bus_width ) {
@ -372,8 +424,13 @@ static void mmc_set_ios(struct mmc *mmc)
mmc_reg_out ( & mmc_base - > sysctl , ICE_MASK | CLKD_MASK ,
( dsor < < CLKD_OFFSET ) | ICE_OSCILLATE ) ;
while ( ( readl ( & mmc_base - > sysctl ) & ICS_MASK ) = = ICS_NOTREADY )
;
start = get_timer ( 0 ) ;
while ( ( readl ( & mmc_base - > sysctl ) & ICS_MASK ) = = ICS_NOTREADY ) {
if ( get_timer ( 0 ) - start > MAX_RETRY_MS ) {
printf ( " %s: timedout waiting for ics! \n " , __func__ ) ;
return ;
}
}
writel ( readl ( & mmc_base - > sysctl ) | CEN_ENABLE , & mmc_base - > sysctl ) ;
}