@ -32,13 +32,33 @@
DECLARE_GLOBAL_DATA_PTR ;
struct mmc_host mmc_host [ CONFIG_SYS_MMC_MAX_DEVICE ] ;
struct tegra_mmc_priv {
struct tegra_mmc * reg ;
int id ; /* device id/number, 0-3 */
int enabled ; /* 1 to enable, 0 to disable */
int width ; /* Bus Width, 1, 4 or 8 */
# ifdef CONFIG_TEGRA186
struct reset_ctl reset_ctl ;
struct clk clk ;
# else
enum periph_id mmc_id ; /* Peripheral ID: PERIPH_ID_... */
# endif
struct gpio_desc cd_gpio ; /* Change Detect GPIO */
struct gpio_desc pwr_gpio ; /* Power GPIO */
struct gpio_desc wp_gpio ; /* Write Protect GPIO */
unsigned int version ; /* SDHCI spec. version */
unsigned int clock ; /* Current clock (MHz) */
struct mmc_config cfg ; /* mmc configuration */
} ;
struct tegra_mmc_priv mmc_host [ CONFIG_SYS_MMC_MAX_DEVICE ] ;
# if !CONFIG_IS_ENABLED(OF_CONTROL)
# error "Please enable device tree support to use this driver"
# endif
static void mmc_set_power ( struct mmc_host * host , unsigned short power )
static void tegra_mmc_set_power ( struct tegra_mmc_priv * priv ,
unsigned short power )
{
u8 pwr = 0 ;
debug ( " %s: power = %x \n " , __func__ , power ) ;
@ -61,17 +81,18 @@ static void mmc_set_power(struct mmc_host *host, unsigned short power)
debug ( " %s: pwr = %X \n " , __func__ , pwr ) ;
/* Set the bus voltage first (if any) */
writeb ( pwr , & host - > reg - > pwrcon ) ;
writeb ( pwr , & priv - > reg - > pwrcon ) ;
if ( pwr = = 0 )
return ;
/* Now enable bus power */
pwr | = TEGRA_MMC_PWRCTL_SD_BUS_POWER ;
writeb ( pwr , & host - > reg - > pwrcon ) ;
writeb ( pwr , & priv - > reg - > pwrcon ) ;
}
static void mmc_prepare_data ( struct mmc_host * host , struct mmc_data * data ,
struct bounce_buffer * bbstate )
static void tegra_mmc_prepare_data ( struct tegra_mmc_priv * priv ,
struct mmc_data * data ,
struct bounce_buffer * bbstate )
{
unsigned char ctrl ;
@ -80,7 +101,7 @@ static void mmc_prepare_data(struct mmc_host *host, struct mmc_data *data,
bbstate - > bounce_buffer , bbstate - > user_buffer , data - > blocks ,
data - > blocksize ) ;
writel ( ( u32 ) ( unsigned long ) bbstate - > bounce_buffer , & host - > reg - > sysad ) ;
writel ( ( u32 ) ( unsigned long ) bbstate - > bounce_buffer , & priv - > reg - > sysad ) ;
/*
* DMASEL [ 4 : 3 ]
* 00 = Selects SDMA
@ -88,17 +109,18 @@ static void mmc_prepare_data(struct mmc_host *host, struct mmc_data *data,
* 10 = Selects 32 - bit Address ADMA2
* 11 = Selects 64 - bit Address ADMA2
*/
ctrl = readb ( & host - > reg - > hostctl ) ;
ctrl = readb ( & priv - > reg - > hostctl ) ;
ctrl & = ~ TEGRA_MMC_HOSTCTL_DMASEL_MASK ;
ctrl | = TEGRA_MMC_HOSTCTL_DMASEL_SDMA ;
writeb ( ctrl , & host - > reg - > hostctl ) ;
writeb ( ctrl , & priv - > reg - > hostctl ) ;
/* We do not handle DMA boundaries, so set it to max (512 KiB) */
writew ( ( 7 < < 12 ) | ( data - > blocksize & 0xFFF ) , & host - > reg - > blksize ) ;
writew ( data - > blocks , & host - > reg - > blkcnt ) ;
writew ( ( 7 < < 12 ) | ( data - > blocksize & 0xFFF ) , & priv - > reg - > blksize ) ;
writew ( data - > blocks , & priv - > reg - > blkcnt ) ;
}
static void mmc_set_transfer_mode ( struct mmc_host * host , struct mmc_data * data )
static void tegra_mmc_set_transfer_mode ( struct tegra_mmc_priv * priv ,
struct mmc_data * data )
{
unsigned short mode ;
debug ( " mmc_set_transfer_mode called \n " ) ;
@ -121,13 +143,13 @@ static void mmc_set_transfer_mode(struct mmc_host *host, struct mmc_data *data)
if ( data - > flags & MMC_DATA_READ )
mode | = TEGRA_MMC_TRNMOD_DATA_XFER_DIR_SEL_READ ;
writew ( mode , & host - > reg - > trnmod ) ;
writew ( mode , & priv - > reg - > trnmod ) ;
}
static int mmc_wait_inhibit ( struct mmc_host * host ,
struct mmc_cmd * cmd ,
struct mmc_data * data ,
unsigned int timeout )
static int tegra_ mmc_wait_inhibit( struct tegra_mmc_priv * priv ,
struct mmc_cmd * cmd ,
struct mmc_data * data ,
unsigned int timeout )
{
/*
* PRNSTS
@ -143,7 +165,7 @@ static int mmc_wait_inhibit(struct mmc_host *host,
if ( ( data = = NULL ) & & ( cmd - > resp_type & MMC_RSP_BUSY ) )
mask | = TEGRA_MMC_PRNSTS_CMD_INHIBIT_DAT ;
while ( readl ( & host - > reg - > prnsts ) & mask ) {
while ( readl ( & priv - > reg - > prnsts ) & mask ) {
if ( timeout = = 0 ) {
printf ( " %s: timeout error \n " , __func__ ) ;
return - 1 ;
@ -155,29 +177,30 @@ static int mmc_wait_inhibit(struct mmc_host *host,
return 0 ;
}
static int mmc_send_cmd_bounced ( struct mmc * mmc , struct mmc_cmd * cmd ,
struct mmc_data * data , struct bounce_buffer * bbstate )
static int tegra_mmc_send_cmd_bounced ( struct mmc * mmc , struct mmc_cmd * cmd ,
struct mmc_data * data ,
struct bounce_buffer * bbstate )
{
struct mmc_host * host = mmc - > priv ;
struct tegra_mmc_priv * priv = mmc - > priv ;
int flags , i ;
int result ;
unsigned int mask = 0 ;
unsigned int retry = 0x100000 ;
debug ( " mmc_send_cmd called \n " ) ;
result = mmc_wait_inhibit ( host , cmd , data , 10 /* ms */ ) ;
result = tegra_ mmc_wait_inhibit( priv , cmd , data , 10 /* ms */ ) ;
if ( result < 0 )
return result ;
if ( data )
mmc_prepare_data ( host , data , bbstate ) ;
tegra_ mmc_prepare_data( priv , data , bbstate ) ;
debug ( " cmd->arg: %08x \n " , cmd - > cmdarg ) ;
writel ( cmd - > cmdarg , & host - > reg - > argument ) ;
writel ( cmd - > cmdarg , & priv - > reg - > argument ) ;
if ( data )
mmc_set_transfer_mode ( host , data ) ;
tegra_ mmc_set_transfer_mode( priv , data ) ;
if ( ( cmd - > resp_type & MMC_RSP_136 ) & & ( cmd - > resp_type & MMC_RSP_BUSY ) )
return - 1 ;
@ -212,33 +235,33 @@ static int mmc_send_cmd_bounced(struct mmc *mmc, struct mmc_cmd *cmd,
debug ( " cmd: %d \n " , cmd - > cmdidx ) ;
writew ( ( cmd - > cmdidx < < 8 ) | flags , & host - > reg - > cmdreg ) ;
writew ( ( cmd - > cmdidx < < 8 ) | flags , & priv - > reg - > cmdreg ) ;
for ( i = 0 ; i < retry ; i + + ) {
mask = readl ( & host - > reg - > norintsts ) ;
mask = readl ( & priv - > reg - > norintsts ) ;
/* Command Complete */
if ( mask & TEGRA_MMC_NORINTSTS_CMD_COMPLETE ) {
if ( ! data )
writel ( mask , & host - > reg - > norintsts ) ;
writel ( mask , & priv - > reg - > norintsts ) ;
break ;
}
}
if ( i = = retry ) {
printf ( " %s: waiting for status update \n " , __func__ ) ;
writel ( mask , & host - > reg - > norintsts ) ;
writel ( mask , & priv - > reg - > norintsts ) ;
return - ETIMEDOUT ;
}
if ( mask & TEGRA_MMC_NORINTSTS_CMD_TIMEOUT ) {
/* Timeout Error */
debug ( " timeout: %08x cmd %d \n " , mask , cmd - > cmdidx ) ;
writel ( mask , & host - > reg - > norintsts ) ;
writel ( mask , & priv - > reg - > norintsts ) ;
return - ETIMEDOUT ;
} else if ( mask & TEGRA_MMC_NORINTSTS_ERR_INTERRUPT ) {
/* Error Interrupt */
debug ( " error: %08x cmd %d \n " , mask , cmd - > cmdidx ) ;
writel ( mask , & host - > reg - > norintsts ) ;
writel ( mask , & priv - > reg - > norintsts ) ;
return - 1 ;
}
@ -246,8 +269,8 @@ static int mmc_send_cmd_bounced(struct mmc *mmc, struct mmc_cmd *cmd,
if ( cmd - > resp_type & MMC_RSP_136 ) {
/* CRC is stripped so we need to do some shifting. */
for ( i = 0 ; i < 4 ; i + + ) {
unsigned long offset =
( unsigned long ) ( & host - > reg - > rspreg3 - i ) ;
unsigned long offset = ( unsigned long )
( & priv - > reg - > rspreg3 - i ) ;
cmd - > response [ i ] = readl ( offset ) < < 8 ;
if ( i ! = 3 ) {
@ -260,21 +283,21 @@ static int mmc_send_cmd_bounced(struct mmc *mmc, struct mmc_cmd *cmd,
} else if ( cmd - > resp_type & MMC_RSP_BUSY ) {
for ( i = 0 ; i < retry ; i + + ) {
/* PRNTDATA[23:20] : DAT[3:0] Line Signal */
if ( readl ( & host - > reg - > prnsts )
if ( readl ( & priv - > reg - > prnsts )
& ( 1 < < 20 ) ) /* DAT[0] */
break ;
}
if ( i = = retry ) {
printf ( " %s: card is still busy \n " , __func__ ) ;
writel ( mask , & host - > reg - > norintsts ) ;
writel ( mask , & priv - > reg - > norintsts ) ;
return - ETIMEDOUT ;
}
cmd - > response [ 0 ] = readl ( & host - > reg - > rspreg0 ) ;
cmd - > response [ 0 ] = readl ( & priv - > reg - > rspreg0 ) ;
debug ( " cmd->resp[0]: %08x \n " , cmd - > response [ 0 ] ) ;
} else {
cmd - > response [ 0 ] = readl ( & host - > reg - > rspreg0 ) ;
cmd - > response [ 0 ] = readl ( & priv - > reg - > rspreg0 ) ;
debug ( " cmd->resp[0]: %08x \n " , cmd - > response [ 0 ] ) ;
}
}
@ -283,11 +306,11 @@ static int mmc_send_cmd_bounced(struct mmc *mmc, struct mmc_cmd *cmd,
unsigned long start = get_timer ( 0 ) ;
while ( 1 ) {
mask = readl ( & host - > reg - > norintsts ) ;
mask = readl ( & priv - > reg - > norintsts ) ;
if ( mask & TEGRA_MMC_NORINTSTS_ERR_INTERRUPT ) {
/* Error Interrupt */
writel ( mask , & host - > reg - > norintsts ) ;
writel ( mask , & priv - > reg - > norintsts ) ;
printf ( " %s: error during transfer: 0x%08x \n " ,
__func__ , mask ) ;
return - 1 ;
@ -296,31 +319,31 @@ static int mmc_send_cmd_bounced(struct mmc *mmc, struct mmc_cmd *cmd,
* DMA Interrupt , restart the transfer where
* it was interrupted .
*/
unsigned int address = readl ( & host - > reg - > sysad ) ;
unsigned int address = readl ( & priv - > reg - > sysad ) ;
debug ( " DMA end \n " ) ;
writel ( TEGRA_MMC_NORINTSTS_DMA_INTERRUPT ,
& host - > reg - > norintsts ) ;
writel ( address , & host - > reg - > sysad ) ;
& priv - > reg - > norintsts ) ;
writel ( address , & priv - > reg - > sysad ) ;
} else if ( mask & TEGRA_MMC_NORINTSTS_XFER_COMPLETE ) {
/* Transfer Complete */
debug ( " r/w is done \n " ) ;
break ;
} else if ( get_timer ( start ) > 8000UL ) {
writel ( mask , & host - > reg - > norintsts ) ;
writel ( mask , & priv - > reg - > norintsts ) ;
printf ( " %s: MMC Timeout \n "
" Interrupt status 0x%08x \n "
" Interrupt status enable 0x%08x \n "
" Interrupt signal enable 0x%08x \n "
" Present status 0x%08x \n " ,
__func__ , mask ,
readl ( & host - > reg - > norintstsen ) ,
readl ( & host - > reg - > norintsigen ) ,
readl ( & host - > reg - > prnsts ) ) ;
readl ( & priv - > reg - > norintstsen ) ,
readl ( & priv - > reg - > norintsigen ) ,
readl ( & priv - > reg - > prnsts ) ) ;
return - 1 ;
}
}
writel ( mask , & host - > reg - > norintsts ) ;
writel ( mask , & priv - > reg - > norintsts ) ;
}
udelay ( 1000 ) ;
@ -328,7 +351,7 @@ static int mmc_send_cmd_bounced(struct mmc *mmc, struct mmc_cmd *cmd,
}
static int tegra_mmc_send_cmd ( struct mmc * mmc , struct mmc_cmd * cmd ,
struct mmc_data * data )
struct mmc_data * data )
{
void * buf ;
unsigned int bbflags ;
@ -349,7 +372,7 @@ static int tegra_mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
bounce_buffer_start ( & bbstate , buf , len , bbflags ) ;
}
ret = mmc_send_cmd_bounced ( mmc , cmd , data , & bbstate ) ;
ret = tegra_ mmc_send_cmd_bounced( mmc , cmd , data , & bbstate ) ;
if ( data )
bounce_buffer_stop ( & bbstate ) ;
@ -357,7 +380,7 @@ static int tegra_mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
return ret ;
}
static void mmc_change_clock ( struct mmc_host * host , uint clock )
static void tegra_ mmc_change_clock( struct tegra_mmc_priv * priv , uint clock )
{
int div ;
unsigned short clk ;
@ -372,16 +395,16 @@ static void mmc_change_clock(struct mmc_host *host, uint clock)
goto out ;
# ifdef CONFIG_TEGRA186
{
ulong rate = clk_set_rate ( & host - > clk , clock ) ;
ulong rate = clk_set_rate ( & priv - > clk , clock ) ;
div = ( rate + clock - 1 ) / clock ;
}
# else
clock_adjust_periph_pll_div ( host - > mmc_id , CLOCK_ID_PERIPH , clock ,
clock_adjust_periph_pll_div ( priv - > mmc_id , CLOCK_ID_PERIPH , clock ,
& div ) ;
# endif
debug ( " div = %d \n " , div ) ;
writew ( 0 , & host - > reg - > clkcon ) ;
writew ( 0 , & priv - > reg - > clkcon ) ;
/*
* CLKCON
@ -393,11 +416,11 @@ static void mmc_change_clock(struct mmc_host *host, uint clock)
div > > = 1 ;
clk = ( ( div < < TEGRA_MMC_CLKCON_SDCLK_FREQ_SEL_SHIFT ) |
TEGRA_MMC_CLKCON_INTERNAL_CLOCK_ENABLE ) ;
writew ( clk , & host - > reg - > clkcon ) ;
writew ( clk , & priv - > reg - > clkcon ) ;
/* Wait max 10 ms */
timeout = 10 ;
while ( ! ( readw ( & host - > reg - > clkcon ) &
while ( ! ( readw ( & priv - > reg - > clkcon ) &
TEGRA_MMC_CLKCON_INTERNAL_CLOCK_STABLE ) ) {
if ( timeout = = 0 ) {
printf ( " %s: timeout error \n " , __func__ ) ;
@ -408,26 +431,26 @@ static void mmc_change_clock(struct mmc_host *host, uint clock)
}
clk | = TEGRA_MMC_CLKCON_SD_CLOCK_ENABLE ;
writew ( clk , & host - > reg - > clkcon ) ;
writew ( clk , & priv - > reg - > clkcon ) ;
debug ( " mmc_change_clock: clkcon = %08X \n " , clk ) ;
out :
host - > clock = clock ;
priv - > clock = clock ;
}
static void tegra_mmc_set_ios ( struct mmc * mmc )
{
struct mmc_host * host = mmc - > priv ;
struct tegra_mmc_priv * priv = mmc - > priv ;
unsigned char ctrl ;
debug ( " mmc_set_ios called \n " ) ;
debug ( " bus_width: %x, clock: %d \n " , mmc - > bus_width , mmc - > clock ) ;
/* Change clock first */
mmc_change_clock ( host , mmc - > clock ) ;
tegra_ mmc_change_clock( priv , mmc - > clock ) ;
ctrl = readb ( & host - > reg - > hostctl ) ;
ctrl = readb ( & priv - > reg - > hostctl ) ;
/*
* WIDE8 [ 5 ]
@ -444,38 +467,38 @@ static void tegra_mmc_set_ios(struct mmc *mmc)
else
ctrl & = ~ ( 1 < < 1 ) ;
writeb ( ctrl , & host - > reg - > hostctl ) ;
writeb ( ctrl , & priv - > reg - > hostctl ) ;
debug ( " mmc_set_ios: hostctl = %08X \n " , ctrl ) ;
}
static void pad_init_mmc ( struct mmc_host * host )
static void tegra_mmc_ pad_init( struct tegra_mmc_priv * priv )
{
# if defined(CONFIG_TEGRA30)
u32 val ;
debug ( " %s: sdmmc address = %08x \n " , __func__ , ( unsigned int ) host - > reg ) ;
debug ( " %s: sdmmc address = %08x \n " , __func__ , ( unsigned int ) priv - > reg ) ;
/* Set the pad drive strength for SDMMC1 or 3 only */
if ( host - > reg ! = ( void * ) 0x78000000 & &
host - > reg ! = ( void * ) 0x78000400 ) {
if ( priv - > reg ! = ( void * ) 0x78000000 & &
priv - > reg ! = ( void * ) 0x78000400 ) {
debug ( " %s: settings are only valid for SDMMC1/SDMMC3! \n " ,
__func__ ) ;
return ;
}
val = readl ( & host - > reg - > sdmemcmppadctl ) ;
val = readl ( & priv - > reg - > sdmemcmppadctl ) ;
val & = 0xFFFFFFF0 ;
val | = MEMCOMP_PADCTRL_VREF ;
writel ( val , & host - > reg - > sdmemcmppadctl ) ;
writel ( val , & priv - > reg - > sdmemcmppadctl ) ;
val = readl ( & host - > reg - > autocalcfg ) ;
val = readl ( & priv - > reg - > autocalcfg ) ;
val & = 0xFFFF0000 ;
val | = AUTO_CAL_PU_OFFSET | AUTO_CAL_PD_OFFSET | AUTO_CAL_ENABLED ;
writel ( val , & host - > reg - > autocalcfg ) ;
writel ( val , & priv - > reg - > autocalcfg ) ;
# endif
}
static void mmc_reset ( struct mmc_host * host , struct mmc * mmc )
static void tegra_ mmc_reset( struct tegra_mmc_priv * priv , struct mmc * mmc )
{
unsigned int timeout ;
debug ( " mmc_reset called \n " ) ;
@ -485,15 +508,15 @@ static void mmc_reset(struct mmc_host *host, struct mmc *mmc)
* 1 = reset
* 0 = work
*/
writeb ( TEGRA_MMC_SWRST_SW_RESET_FOR_ALL , & host - > reg - > swrst ) ;
writeb ( TEGRA_MMC_SWRST_SW_RESET_FOR_ALL , & priv - > reg - > swrst ) ;
host - > clock = 0 ;
priv - > clock = 0 ;
/* Wait max 100 ms */
timeout = 100 ;
/* hw clears the bit when it's done */
while ( readb ( & host - > reg - > swrst ) & TEGRA_MMC_SWRST_SW_RESET_FOR_ALL ) {
while ( readb ( & priv - > reg - > swrst ) & TEGRA_MMC_SWRST_SW_RESET_FOR_ALL ) {
if ( timeout = = 0 ) {
printf ( " %s: timeout error \n " , __func__ ) ;
return ;
@ -503,30 +526,30 @@ static void mmc_reset(struct mmc_host *host, struct mmc *mmc)
}
/* Set SD bus voltage & enable bus power */
mmc_set_power ( host , fls ( mmc - > cfg - > voltages ) - 1 ) ;
tegra_ mmc_set_power( priv , fls ( mmc - > cfg - > voltages ) - 1 ) ;
debug ( " %s: power control = %02X, host control = %02X \n " , __func__ ,
readb ( & host - > reg - > pwrcon ) , readb ( & host - > reg - > hostctl ) ) ;
readb ( & priv - > reg - > pwrcon ) , readb ( & priv - > reg - > hostctl ) ) ;
/* Make sure SDIO pads are set up */
pad_init_mmc ( host ) ;
tegra_mmc_pad_init ( priv ) ;
}
static int tegra_mmc_core_init ( struct mmc * mmc )
{
struct mmc_host * host = mmc - > priv ;
struct tegra_mmc_priv * priv = mmc - > priv ;
unsigned int mask ;
debug ( " mmc_core_init called \n " ) ;
mmc_reset ( host , mmc ) ;
tegra_ mmc_reset( priv , mmc ) ;
host - > version = readw ( & host - > reg - > hcver ) ;
debug ( " host version = %x \n " , host - > version ) ;
priv - > version = readw ( & priv - > reg - > hcver ) ;
debug ( " host version = %x \n " , priv - > version ) ;
/* mask all */
writel ( 0xffffffff , & host - > reg - > norintstsen ) ;
writel ( 0xffffffff , & host - > reg - > norintsigen ) ;
writel ( 0xffffffff , & priv - > reg - > norintstsen ) ;
writel ( 0xffffffff , & priv - > reg - > norintsigen ) ;
writeb ( 0xe , & host - > reg - > timeoutcon ) ; /* TMCLK * 2^27 */
writeb ( 0xe , & priv - > reg - > timeoutcon ) ; /* TMCLK * 2^27 */
/*
* NORMAL Interrupt Status Enable Register init
* [ 5 ] ENSTABUFRDRDY : Buffer Read Ready Status Enable
@ -535,35 +558,35 @@ static int tegra_mmc_core_init(struct mmc *mmc)
* [ 1 ] ENSTASTANSCMPLT : Transfre Complete Status Enable
* [ 0 ] ENSTACMDCMPLT : Command Complete Status Enable
*/
mask = readl ( & host - > reg - > norintstsen ) ;
mask = readl ( & priv - > reg - > norintstsen ) ;
mask & = ~ ( 0xffff ) ;
mask | = ( TEGRA_MMC_NORINTSTSEN_CMD_COMPLETE |
TEGRA_MMC_NORINTSTSEN_XFER_COMPLETE |
TEGRA_MMC_NORINTSTSEN_DMA_INTERRUPT |
TEGRA_MMC_NORINTSTSEN_BUFFER_WRITE_READY |
TEGRA_MMC_NORINTSTSEN_BUFFER_READ_READY ) ;
writel ( mask , & host - > reg - > norintstsen ) ;
writel ( mask , & priv - > reg - > norintstsen ) ;
/*
* NORMAL Interrupt Signal Enable Register init
* [ 1 ] ENSTACMDCMPLT : Transfer Complete Signal Enable
*/
mask = readl ( & host - > reg - > norintsigen ) ;
mask = readl ( & priv - > reg - > norintsigen ) ;
mask & = ~ ( 0xffff ) ;
mask | = TEGRA_MMC_NORINTSIGEN_XFER_COMPLETE ;
writel ( mask , & host - > reg - > norintsigen ) ;
writel ( mask , & priv - > reg - > norintsigen ) ;
return 0 ;
}
static int tegra_mmc_getcd ( struct mmc * mmc )
{
struct mmc_host * host = mmc - > priv ;
struct tegra_mmc_priv * priv = mmc - > priv ;
debug ( " tegra_mmc_getcd called \n " ) ;
if ( dm_gpio_is_valid ( & host - > cd_gpio ) )
return dm_gpio_get_value ( & host - > cd_gpio ) ;
if ( dm_gpio_is_valid ( & priv - > cd_gpio ) )
return dm_gpio_get_value ( & priv - > cd_gpio ) ;
return 1 ;
}
@ -577,55 +600,55 @@ static const struct mmc_ops tegra_mmc_ops = {
static int do_mmc_init ( int dev_index , bool removable )
{
struct mmc_host * host ;
struct tegra_mmc_priv * priv ;
struct mmc * mmc ;
# ifdef CONFIG_TEGRA186
int ret ;
# endif
/* DT should have been read & host config filled in */
host = & mmc_host [ dev_index ] ;
if ( ! host - > enabled )
priv = & mmc_host [ dev_index ] ;
if ( ! priv - > enabled )
return - 1 ;
debug ( " do_mmc_init: index %d, bus width %d pwr_gpio %d cd_gpio %d \n " ,
dev_index , host - > width , gpio_get_number ( & host - > pwr_gpio ) ,
gpio_get_number ( & host - > cd_gpio ) ) ;
dev_index , priv - > width , gpio_get_number ( & priv - > pwr_gpio ) ,
gpio_get_number ( & priv - > cd_gpio ) ) ;
host - > clock = 0 ;
priv - > clock = 0 ;
# ifdef CONFIG_TEGRA186
ret = reset_assert ( & host - > reset_ctl ) ;
ret = reset_assert ( & priv - > reset_ctl ) ;
if ( ret )
return ret ;
ret = clk_enable ( & host - > clk ) ;
ret = clk_enable ( & priv - > clk ) ;
if ( ret )
return ret ;
ret = clk_set_rate ( & host - > clk , 20000000 ) ;
ret = clk_set_rate ( & priv - > clk , 20000000 ) ;
if ( IS_ERR_VALUE ( ret ) )
return ret ;
ret = reset_deassert ( & host - > reset_ctl ) ;
ret = reset_deassert ( & priv - > reset_ctl ) ;
if ( ret )
return ret ;
# else
clock_start_periph_pll ( host - > mmc_id , CLOCK_ID_PERIPH , 20000000 ) ;
clock_start_periph_pll ( priv - > mmc_id , CLOCK_ID_PERIPH , 20000000 ) ;
# endif
if ( dm_gpio_is_valid ( & host - > pwr_gpio ) )
dm_gpio_set_value ( & host - > pwr_gpio , 1 ) ;
if ( dm_gpio_is_valid ( & priv - > pwr_gpio ) )
dm_gpio_set_value ( & priv - > pwr_gpio , 1 ) ;
memset ( & host - > cfg , 0 , sizeof ( host - > cfg ) ) ;
memset ( & priv - > cfg , 0 , sizeof ( priv - > cfg ) ) ;
host - > cfg . name = " Tegra SD/MMC " ;
host - > cfg . ops = & tegra_mmc_ops ;
priv - > cfg . name = " Tegra SD/MMC " ;
priv - > cfg . ops = & tegra_mmc_ops ;
host - > cfg . voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195 ;
host - > cfg . host_caps = 0 ;
if ( host - > width = = 8 )
host - > cfg . host_caps | = MMC_MODE_8BIT ;
if ( host - > width > = 4 )
host - > cfg . host_caps | = MMC_MODE_4BIT ;
host - > cfg . host_caps | = MMC_MODE_HS_52MHz | MMC_MODE_HS ;
priv - > cfg . voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195 ;
priv - > cfg . host_caps = 0 ;
if ( priv - > width = = 8 )
priv - > cfg . host_caps | = MMC_MODE_8BIT ;
if ( priv - > width > = 4 )
priv - > cfg . host_caps | = MMC_MODE_4BIT ;
priv - > cfg . host_caps | = MMC_MODE_HS_52MHz | MMC_MODE_HS ;
/*
* min freq is for card identification , and is the highest
@ -633,12 +656,12 @@ static int do_mmc_init(int dev_index, bool removable)
* max freq is highest HS eMMC clock as per the SD / MMC spec
* ( actually 52 MHz )
*/
host - > cfg . f_min = 375000 ;
host - > cfg . f_max = 48000000 ;
priv - > cfg . f_min = 375000 ;
priv - > cfg . f_max = 48000000 ;
host - > cfg . b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT ;
priv - > cfg . b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT ;
mmc = mmc_create ( & host - > cfg , host ) ;
mmc = mmc_create ( & priv - > cfg , priv ) ;
mmc - > block_dev . removable = removable ;
if ( mmc = = NULL )
return - 1 ;
@ -651,17 +674,17 @@ static int do_mmc_init(int dev_index, bool removable)
*
* @ param blob fdt blob
* @ param node Device index ( 0 - 3 )
* @ param host Structure to fill in ( reg , width , mmc_id )
* @ param priv Structure to fill in ( reg , width , mmc_id )
*/
static int mmc_get_config ( const void * blob , int node , struct mmc_host * host ,
bool * removablep )
static int mmc_get_config ( const void * blob , int node ,
struct tegra_mmc_priv * priv , bool * removablep )
{
debug ( " %s: node = %d \n " , __func__ , node ) ;
host - > enabled = fdtdec_get_is_enabled ( blob , node ) ;
priv - > enabled = fdtdec_get_is_enabled ( blob , node ) ;
host - > reg = ( struct tegra_mmc * ) fdtdec_get_addr ( blob , node , " reg " ) ;
if ( ( fdt_addr_t ) host - > reg = = FDT_ADDR_T_NONE ) {
priv - > reg = ( struct tegra_mmc * ) fdtdec_get_addr ( blob , node , " reg " ) ;
if ( ( fdt_addr_t ) priv - > reg = = FDT_ADDR_T_NONE ) {
debug ( " %s: no sdmmc base reg info found \n " , __func__ ) ;
return - FDT_ERR_NOTFOUND ;
}
@ -675,20 +698,20 @@ static int mmc_get_config(const void *blob, int node, struct mmc_host *host,
struct udevice dev ;
int ret ;
dev . of_offset = node ;
ret = reset_get_by_name ( & dev , " sdhci " , & host - > reset_ctl ) ;
ret = reset_get_by_name ( & dev , " sdhci " , & priv - > reset_ctl ) ;
if ( ret ) {
debug ( " reset_get_by_name() failed: %d \n " , ret ) ;
return ret ;
}
ret = clk_get_by_index ( & dev , 0 , & host - > clk ) ;
ret = clk_get_by_index ( & dev , 0 , & priv - > clk ) ;
if ( ret ) {
debug ( " clk_get_by_index() failed: %d \n " , ret ) ;
return ret ;
}
}
# else
host - > mmc_id = clock_decode_periph_id ( blob , node ) ;
if ( host - > mmc_id = = PERIPH_ID_NONE ) {
priv - > mmc_id = clock_decode_periph_id ( blob , node ) ;
if ( priv - > mmc_id = = PERIPH_ID_NONE ) {
debug ( " %s: could not decode periph id \n " , __func__ ) ;
return - FDT_ERR_NOTFOUND ;
}
@ -698,23 +721,23 @@ static int mmc_get_config(const void *blob, int node, struct mmc_host *host,
* NOTE : mmc - > bus_width is determined by mmc . c dynamically .
* TBD : Override it with this value ?
*/
host - > width = fdtdec_get_int ( blob , node , " bus-width " , 0 ) ;
if ( ! host - > width )
priv - > width = fdtdec_get_int ( blob , node , " bus-width " , 0 ) ;
if ( ! priv - > width )
debug ( " %s: no sdmmc width found \n " , __func__ ) ;
/* These GPIOs are optional */
gpio_request_by_name_nodev ( blob , node , " cd-gpios " , 0 , & host - > cd_gpio ,
gpio_request_by_name_nodev ( blob , node , " cd-gpios " , 0 , & priv - > cd_gpio ,
GPIOD_IS_IN ) ;
gpio_request_by_name_nodev ( blob , node , " wp-gpios " , 0 , & host - > wp_gpio ,
gpio_request_by_name_nodev ( blob , node , " wp-gpios " , 0 , & priv - > wp_gpio ,
GPIOD_IS_IN ) ;
gpio_request_by_name_nodev ( blob , node , " power-gpios " , 0 ,
& host - > pwr_gpio , GPIOD_IS_OUT ) ;
& priv - > pwr_gpio , GPIOD_IS_OUT ) ;
* removablep = ! fdtdec_get_bool ( blob , node , " non-removable " ) ;
debug ( " %s: found controller at %p, width = %d, periph_id = %d \n " ,
__func__ , host - > reg , host - > width ,
__func__ , priv - > reg , priv - > width ,
# ifndef CONFIG_TEGRA186
host - > mmc_id
priv - > mmc_id
# else
- 1
# endif
@ -732,7 +755,7 @@ static int mmc_get_config(const void *blob, int node, struct mmc_host *host,
*/
static int process_nodes ( const void * blob , int node_list [ ] , int count )
{
struct mmc_host * host ;
struct tegra_mmc_priv * priv ;
bool removable ;
int i , node ;
@ -744,10 +767,10 @@ static int process_nodes(const void *blob, int node_list[], int count)
if ( node < = 0 )
continue ;
host = & mmc_host [ i ] ;
host - > id = i ;
priv = & mmc_host [ i ] ;
priv - > id = i ;
if ( mmc_get_config ( blob , node , host , & removable ) ) {
if ( mmc_get_config ( blob , node , priv , & removable ) ) {
printf ( " %s: failed to decode dev %d \n " , __func__ , i ) ;
return - 1 ;
}