@ -37,15 +37,24 @@
*/
# include <common.h>
# include <dm.h>
# include <malloc.h>
# include <memalign.h>
# include <sdhci.h>
# include <mach/timer.h>
# include <asm/arch/msg.h>
# include <asm/arch/mbox.h>
# include <mach/sdhci.h>
# include <mach/timer.h>
/* 400KHz is max freq for card ID etc. Use that as min */
# define MIN_FREQ 400000
# define SDHCI_BUFFER 0x20
struct bcm2835_sdhci_plat {
struct mmc_config cfg ;
struct mmc mmc ;
} ;
struct bcm2835_sdhci_host {
struct sdhci_host host ;
uint twoticks_delay ;
@ -58,7 +67,7 @@ static inline struct bcm2835_sdhci_host *to_bcm(struct sdhci_host *host)
}
static inline void bcm2835_sdhci_raw_writel ( struct sdhci_host * host , u32 val ,
int reg )
int reg )
{
struct bcm2835_sdhci_host * bcm_host = to_bcm ( host ) ;
@ -153,16 +162,33 @@ static const struct sdhci_ops bcm2835_ops = {
. read_b = bcm2835_sdhci_readb ,
} ;
int bcm2835_sdhci_init ( u32 regbase , u32 emmc_freq )
static int bcm2835_sdhci_bind ( struct udevice * dev )
{
struct bcm2835_sdhci_host * bcm_host ;
struct sdhci_host * host ;
struct bcm2835_sdhci_plat * plat = dev_get_platdata ( dev ) ;
bcm_host = calloc ( 1 , sizeof ( * bcm_host ) ) ;
if ( ! bcm_host ) {
printf ( " sdhci_host calloc fail! \n " ) ;
return - ENOMEM ;
return sdhci_bind ( dev , & plat - > mmc , & plat - > cfg ) ;
}
static int bcm2835_sdhci_probe ( struct udevice * dev )
{
struct mmc_uclass_priv * upriv = dev_get_uclass_priv ( dev ) ;
struct bcm2835_sdhci_plat * plat = dev_get_platdata ( dev ) ;
struct bcm2835_sdhci_host * priv = dev_get_priv ( dev ) ;
struct sdhci_host * host = & priv - > host ;
fdt_addr_t base ;
int emmc_freq ;
int ret ;
base = dev_get_addr ( dev ) ;
if ( base = = FDT_ADDR_T_NONE )
return - EINVAL ;
ret = bcm2835_get_mmc_clock ( ) ;
if ( ret < 0 ) {
debug ( " %s: Failed to set MMC clock (err=%d) \n " , __func__ , ret ) ;
return ret ;
}
emmc_freq = ret ;
/*
* See the comments in bcm2835_sdhci_raw_writel ( ) .
@ -177,19 +203,42 @@ int bcm2835_sdhci_init(u32 regbase, u32 emmc_freq)
* Multiply by 1000000 to get uS per two ticks .
* + 1 for hack rounding .
*/
bcm_host - > twoticks_delay = ( ( 2 * 1000000 ) / MIN_FREQ ) + 1 ;
bcm_host - > last_write = 0 ;
priv - > twoticks_delay = ( ( 2 * 1000000 ) / MIN_FREQ ) + 1 ;
priv - > last_write = 0 ;
host = & bcm_host - > host ;
host - > name = " bcm2835_sdhci " ;
host - > ioaddr = ( void * ) ( unsigned long ) regbase ;
host - > name = dev - > name ;
host - > ioaddr = ( void * ) base ;
host - > quirks = SDHCI_QUIRK_BROKEN_VOLTAGE | SDHCI_QUIRK_BROKEN_R1B |
SDHCI_QUIRK_WAIT_SEND_CMD | SDHCI_QUIRK_NO_HISPD_BIT ;
host - > max_clk = emmc_freq ;
host - > voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195 ;
host - > ops = & bcm2835_ops ;
add_sdhci ( host , 0 , MIN_FREQ ) ;
ret = sdhci_setup_cfg ( & plat - > cfg , host , emmc_freq , MIN_FREQ ) ;
if ( ret ) {
debug ( " %s: Failed to setup SDHCI (err=%d) \n " , __func__ , ret ) ;
return ret ;
}
upriv - > mmc = & plat - > mmc ;
host - > mmc = & plat - > mmc ;
host - > mmc - > priv = host ;
return 0 ;
return sdhci_probe ( dev ) ;
}
static const struct udevice_id bcm2835_sdhci_match [ ] = {
{ . compatible = " brcm,bcm2835-sdhci " } ,
{ /* sentinel */ }
} ;
U_BOOT_DRIVER ( sdhci_cdns ) = {
. name = " sdhci-bcm2835 " ,
. id = UCLASS_MMC ,
. of_match = bcm2835_sdhci_match ,
. bind = bcm2835_sdhci_bind ,
. probe = bcm2835_sdhci_probe ,
. priv_auto_alloc_size = sizeof ( struct bcm2835_sdhci_host ) ,
. platdata_auto_alloc_size = sizeof ( struct bcm2835_sdhci_plat ) ,
. ops = & sdhci_ops ,
} ;