@ -124,6 +124,7 @@ static int mmc_write_data(struct hsmmc *mmc_base, const char *buf,
unsigned int siz ) ;
static void omap_hsmmc_start_clock ( struct hsmmc * mmc_base ) ;
static void omap_hsmmc_stop_clock ( struct hsmmc * mmc_base ) ;
static void mmc_reset_controller_fsm ( struct hsmmc * mmc_base , u32 bit ) ;
static inline struct omap_hsmmc_data * omap_hsmmc_get_data ( struct mmc * mmc )
{
@ -355,6 +356,124 @@ static void omap_hsmmc_set_capabilities(struct mmc *mmc)
writel ( val , & mmc_base - > capa ) ;
}
# ifdef MMC_SUPPORTS_TUNING
static void omap_hsmmc_disable_tuning ( struct mmc * mmc )
{
struct hsmmc * mmc_base ;
struct omap_hsmmc_data * priv = omap_hsmmc_get_data ( mmc ) ;
u32 val ;
mmc_base = priv - > base_addr ;
val = readl ( & mmc_base - > ac12 ) ;
val & = ~ ( AC12_SCLK_SEL ) ;
writel ( val , & mmc_base - > ac12 ) ;
val = readl ( & mmc_base - > dll ) ;
val & = ~ ( DLL_FORCE_VALUE | DLL_SWT ) ;
writel ( val , & mmc_base - > dll ) ;
}
static void omap_hsmmc_set_dll ( struct mmc * mmc , int count )
{
int i ;
struct hsmmc * mmc_base ;
struct omap_hsmmc_data * priv = omap_hsmmc_get_data ( mmc ) ;
u32 val ;
mmc_base = priv - > base_addr ;
val = readl ( & mmc_base - > dll ) ;
val | = DLL_FORCE_VALUE ;
val & = ~ ( DLL_FORCE_SR_C_MASK < < DLL_FORCE_SR_C_SHIFT ) ;
val | = ( count < < DLL_FORCE_SR_C_SHIFT ) ;
writel ( val , & mmc_base - > dll ) ;
val | = DLL_CALIB ;
writel ( val , & mmc_base - > dll ) ;
for ( i = 0 ; i < 1000 ; i + + ) {
if ( readl ( & mmc_base - > dll ) & DLL_CALIB )
break ;
}
val & = ~ DLL_CALIB ;
writel ( val , & mmc_base - > dll ) ;
}
static int omap_hsmmc_execute_tuning ( struct udevice * dev , uint opcode )
{
struct omap_hsmmc_data * priv = dev_get_priv ( dev ) ;
struct mmc_uclass_priv * upriv = dev_get_uclass_priv ( dev ) ;
struct mmc * mmc = upriv - > mmc ;
struct hsmmc * mmc_base ;
u32 val ;
u8 cur_match , prev_match = 0 ;
int ret ;
u32 phase_delay = 0 ;
u32 start_window = 0 , max_window = 0 ;
u32 length = 0 , max_len = 0 ;
mmc_base = priv - > base_addr ;
val = readl ( & mmc_base - > capa2 ) ;
/* clock tuning is not needed for upto 52MHz */
if ( ! ( ( mmc - > selected_mode = = MMC_HS_200 ) | |
( mmc - > selected_mode = = UHS_SDR104 ) | |
( ( mmc - > selected_mode = = UHS_SDR50 ) & & ( val & CAPA2_TSDR50 ) ) ) )
return 0 ;
val = readl ( & mmc_base - > dll ) ;
val | = DLL_SWT ;
writel ( val , & mmc_base - > dll ) ;
while ( phase_delay < = MAX_PHASE_DELAY ) {
omap_hsmmc_set_dll ( mmc , phase_delay ) ;
cur_match = ! mmc_send_tuning ( mmc , opcode , NULL ) ;
if ( cur_match ) {
if ( prev_match ) {
length + + ;
} else {
start_window = phase_delay ;
length = 1 ;
}
}
if ( length > max_len ) {
max_window = start_window ;
max_len = length ;
}
prev_match = cur_match ;
phase_delay + = 4 ;
}
if ( ! max_len ) {
ret = - EIO ;
goto tuning_error ;
}
val = readl ( & mmc_base - > ac12 ) ;
if ( ! ( val & AC12_SCLK_SEL ) ) {
ret = - EIO ;
goto tuning_error ;
}
phase_delay = max_window + 4 * ( ( 3 * max_len ) > > 2 ) ;
omap_hsmmc_set_dll ( mmc , phase_delay ) ;
mmc_reset_controller_fsm ( mmc_base , SYSCTL_SRD ) ;
mmc_reset_controller_fsm ( mmc_base , SYSCTL_SRC ) ;
return 0 ;
tuning_error :
omap_hsmmc_disable_tuning ( mmc ) ;
mmc_reset_controller_fsm ( mmc_base , SYSCTL_SRD ) ;
mmc_reset_controller_fsm ( mmc_base , SYSCTL_SRC ) ;
return ret ;
}
# endif
# endif
static int omap_hsmmc_init_setup ( struct mmc * mmc )
@ -1050,6 +1169,9 @@ static const struct dm_mmc_ops omap_hsmmc_ops = {
. get_cd = omap_hsmmc_getcd ,
. get_wp = omap_hsmmc_getwp ,
# endif
# ifdef MMC_SUPPORTS_TUNING
. execute_tuning = omap_hsmmc_execute_tuning ,
# endif
} ;
# else
static const struct mmc_ops omap_hsmmc_ops = {