@ -1103,6 +1103,152 @@ static void mmc_set_bus_width(struct mmc *mmc, uint width)
mmc_set_ios ( mmc ) ;
}
static int sd_select_bus_freq_width ( struct mmc * mmc )
{
int err ;
struct mmc_cmd cmd ;
err = sd_change_freq ( mmc ) ;
if ( err )
return err ;
/* Restrict card's capabilities by what the host can do */
mmc - > card_caps & = mmc - > cfg - > host_caps ;
if ( mmc - > card_caps & MMC_MODE_4BIT ) {
cmd . cmdidx = MMC_CMD_APP_CMD ;
cmd . resp_type = MMC_RSP_R1 ;
cmd . cmdarg = mmc - > rca < < 16 ;
err = mmc_send_cmd ( mmc , & cmd , NULL ) ;
if ( err )
return err ;
cmd . cmdidx = SD_CMD_APP_SET_BUS_WIDTH ;
cmd . resp_type = MMC_RSP_R1 ;
cmd . cmdarg = 2 ;
err = mmc_send_cmd ( mmc , & cmd , NULL ) ;
if ( err )
return err ;
mmc_set_bus_width ( mmc , 4 ) ;
}
err = sd_read_ssr ( mmc ) ;
if ( err )
return err ;
if ( mmc - > card_caps & MMC_MODE_HS )
mmc - > tran_speed = 50000000 ;
else
mmc - > tran_speed = 25000000 ;
return 0 ;
}
static int mmc_select_bus_freq_width ( struct mmc * mmc , const u8 * ext_csd )
{
ALLOC_CACHE_ALIGN_BUFFER ( u8 , test_csd , MMC_MAX_BLOCK_LEN ) ;
/* An array of possible bus widths in order of preference */
static const unsigned int ext_csd_bits [ ] = {
EXT_CSD_DDR_BUS_WIDTH_8 ,
EXT_CSD_DDR_BUS_WIDTH_4 ,
EXT_CSD_BUS_WIDTH_8 ,
EXT_CSD_BUS_WIDTH_4 ,
EXT_CSD_BUS_WIDTH_1 ,
} ;
/* An array to map CSD bus widths to host cap bits */
static const unsigned int ext_to_hostcaps [ ] = {
[ EXT_CSD_DDR_BUS_WIDTH_4 ] =
MMC_MODE_DDR_52MHz | MMC_MODE_4BIT ,
[ EXT_CSD_DDR_BUS_WIDTH_8 ] =
MMC_MODE_DDR_52MHz | MMC_MODE_8BIT ,
[ EXT_CSD_BUS_WIDTH_4 ] = MMC_MODE_4BIT ,
[ EXT_CSD_BUS_WIDTH_8 ] = MMC_MODE_8BIT ,
} ;
/* An array to map chosen bus width to an integer */
static const unsigned int widths [ ] = {
8 , 4 , 8 , 4 , 1 ,
} ;
int err ;
int idx ;
err = mmc_change_freq ( mmc ) ;
if ( err )
return err ;
/* Restrict card's capabilities by what the host can do */
mmc - > card_caps & = mmc - > cfg - > host_caps ;
/* Only version 4 of MMC supports wider bus widths */
if ( mmc - > version < MMC_VERSION_4 )
return 0 ;
for ( idx = 0 ; idx < ARRAY_SIZE ( ext_csd_bits ) ; idx + + ) {
unsigned int extw = ext_csd_bits [ idx ] ;
unsigned int caps = ext_to_hostcaps [ extw ] ;
/*
* If the bus width is still not changed ,
* don ' t try to set the default again .
* Otherwise , recover from switch attempts
* by switching to 1 - bit bus width .
*/
if ( extw = = EXT_CSD_BUS_WIDTH_1 & &
mmc - > bus_width = = 1 ) {
err = 0 ;
break ;
}
/*
* Check to make sure the card and controller support
* these capabilities
*/
if ( ( mmc - > card_caps & caps ) ! = caps )
continue ;
err = mmc_switch ( mmc , EXT_CSD_CMD_SET_NORMAL ,
EXT_CSD_BUS_WIDTH , extw ) ;
if ( err )
continue ;
mmc - > ddr_mode = ( caps & MMC_MODE_DDR_52MHz ) ? 1 : 0 ;
mmc_set_bus_width ( mmc , widths [ idx ] ) ;
err = mmc_send_ext_csd ( mmc , test_csd ) ;
if ( err )
continue ;
/* Only compare read only fields */
if ( ext_csd [ EXT_CSD_PARTITIONING_SUPPORT ]
= = test_csd [ EXT_CSD_PARTITIONING_SUPPORT ] & &
ext_csd [ EXT_CSD_HC_WP_GRP_SIZE ]
= = test_csd [ EXT_CSD_HC_WP_GRP_SIZE ] & &
ext_csd [ EXT_CSD_REV ]
= = test_csd [ EXT_CSD_REV ] & &
ext_csd [ EXT_CSD_HC_ERASE_GRP_SIZE ]
= = test_csd [ EXT_CSD_HC_ERASE_GRP_SIZE ] & &
memcmp ( & ext_csd [ EXT_CSD_SEC_CNT ] ,
& test_csd [ EXT_CSD_SEC_CNT ] , 4 ) = = 0 )
break ;
err = - EBADMSG ;
}
if ( err )
return err ;
if ( mmc - > card_caps & MMC_MODE_HS ) {
if ( mmc - > card_caps & MMC_MODE_HS_52MHz )
mmc - > tran_speed = 52000000 ;
else
mmc - > tran_speed = 26000000 ;
}
return err ;
}
static int mmc_startup ( struct mmc * mmc )
{
int err , i ;
@ -1110,7 +1256,6 @@ static int mmc_startup(struct mmc *mmc)
u64 cmult , csize , capacity ;
struct mmc_cmd cmd ;
ALLOC_CACHE_ALIGN_BUFFER ( u8 , ext_csd , MMC_MAX_BLOCK_LEN ) ;
ALLOC_CACHE_ALIGN_BUFFER ( u8 , test_csd , MMC_MAX_BLOCK_LEN ) ;
bool has_parts = false ;
bool part_completed ;
struct blk_desc * bdesc ;
@ -1415,136 +1560,13 @@ static int mmc_startup(struct mmc *mmc)
return err ;
if ( IS_SD ( mmc ) )
err = sd_change_freq ( mmc ) ;
err = sd_select_bus_freq_width ( mmc ) ;
else
err = mmc_change_freq ( mmc ) ;
err = mmc_select_bus_freq_width ( mmc , ext_csd ) ;
if ( err )
return err ;
/* Restrict card's capabilities by what the host can do */
mmc - > card_caps & = mmc - > cfg - > host_caps ;
if ( IS_SD ( mmc ) ) {
if ( mmc - > card_caps & MMC_MODE_4BIT ) {
cmd . cmdidx = MMC_CMD_APP_CMD ;
cmd . resp_type = MMC_RSP_R1 ;
cmd . cmdarg = mmc - > rca < < 16 ;
err = mmc_send_cmd ( mmc , & cmd , NULL ) ;
if ( err )
return err ;
cmd . cmdidx = SD_CMD_APP_SET_BUS_WIDTH ;
cmd . resp_type = MMC_RSP_R1 ;
cmd . cmdarg = 2 ;
err = mmc_send_cmd ( mmc , & cmd , NULL ) ;
if ( err )
return err ;
mmc_set_bus_width ( mmc , 4 ) ;
}
err = sd_read_ssr ( mmc ) ;
if ( err )
return err ;
if ( mmc - > card_caps & MMC_MODE_HS )
mmc - > tran_speed = 50000000 ;
else
mmc - > tran_speed = 25000000 ;
} else if ( mmc - > version > = MMC_VERSION_4 ) {
/* Only version 4 of MMC supports wider bus widths */
int idx ;
/* An array of possible bus widths in order of preference */
static unsigned ext_csd_bits [ ] = {
EXT_CSD_DDR_BUS_WIDTH_8 ,
EXT_CSD_DDR_BUS_WIDTH_4 ,
EXT_CSD_BUS_WIDTH_8 ,
EXT_CSD_BUS_WIDTH_4 ,
EXT_CSD_BUS_WIDTH_1 ,
} ;
/* An array to map CSD bus widths to host cap bits */
static unsigned ext_to_hostcaps [ ] = {
[ EXT_CSD_DDR_BUS_WIDTH_4 ] =
MMC_MODE_DDR_52MHz | MMC_MODE_4BIT ,
[ EXT_CSD_DDR_BUS_WIDTH_8 ] =
MMC_MODE_DDR_52MHz | MMC_MODE_8BIT ,
[ EXT_CSD_BUS_WIDTH_4 ] = MMC_MODE_4BIT ,
[ EXT_CSD_BUS_WIDTH_8 ] = MMC_MODE_8BIT ,
} ;
/* An array to map chosen bus width to an integer */
static unsigned widths [ ] = {
8 , 4 , 8 , 4 , 1 ,
} ;
for ( idx = 0 ; idx < ARRAY_SIZE ( ext_csd_bits ) ; idx + + ) {
unsigned int extw = ext_csd_bits [ idx ] ;
unsigned int caps = ext_to_hostcaps [ extw ] ;
/*
* If the bus width is still not changed ,
* don ' t try to set the default again .
* Otherwise , recover from switch attempts
* by switching to 1 - bit bus width .
*/
if ( extw = = EXT_CSD_BUS_WIDTH_1 & &
mmc - > bus_width = = 1 ) {
err = 0 ;
break ;
}
/*
* Check to make sure the card and controller support
* these capabilities
*/
if ( ( mmc - > card_caps & caps ) ! = caps )
continue ;
err = mmc_switch ( mmc , EXT_CSD_CMD_SET_NORMAL ,
EXT_CSD_BUS_WIDTH , extw ) ;
if ( err )
continue ;
mmc - > ddr_mode = ( caps & MMC_MODE_DDR_52MHz ) ? 1 : 0 ;
mmc_set_bus_width ( mmc , widths [ idx ] ) ;
err = mmc_send_ext_csd ( mmc , test_csd ) ;
if ( err )
continue ;
/* Only compare read only fields */
if ( ext_csd [ EXT_CSD_PARTITIONING_SUPPORT ]
= = test_csd [ EXT_CSD_PARTITIONING_SUPPORT ] & &
ext_csd [ EXT_CSD_HC_WP_GRP_SIZE ]
= = test_csd [ EXT_CSD_HC_WP_GRP_SIZE ] & &
ext_csd [ EXT_CSD_REV ]
= = test_csd [ EXT_CSD_REV ] & &
ext_csd [ EXT_CSD_HC_ERASE_GRP_SIZE ]
= = test_csd [ EXT_CSD_HC_ERASE_GRP_SIZE ] & &
memcmp ( & ext_csd [ EXT_CSD_SEC_CNT ] ,
& test_csd [ EXT_CSD_SEC_CNT ] , 4 ) = = 0 )
break ;
else
err = - EBADMSG ;
}
if ( err )
return err ;
if ( mmc - > card_caps & MMC_MODE_HS ) {
if ( mmc - > card_caps & MMC_MODE_HS_52MHz )
mmc - > tran_speed = 52000000 ;
else
mmc - > tran_speed = 26000000 ;
}
}
mmc_set_clock ( mmc , mmc - > tran_speed ) ;
/* Fix the block length for DDR mode */