@ -13,15 +13,18 @@
# include <common.h>
# include <malloc.h>
# include <mmc.h>
# include <dm.h>
# include <linux/errno.h>
# include <asm/io.h>
# include <linux/compat.h>
# include <linux/io.h>
# include <linux/sizes.h>
# include <asm/arch/rmobile.h>
# include <asm/arch/sh_sdhi.h>
# define DRIVER_NAME "sh-sdhi"
struct sh_sdhi_host {
unsigned long addr ;
void __iomem * addr ;
int ch ;
int bus_shift ;
unsigned long quirks ;
@ -50,11 +53,6 @@ static inline u16 sh_sdhi_readw(struct sh_sdhi_host *host, int reg)
return readw ( host - > addr + ( reg < < host - > bus_shift ) ) ;
}
static void * mmc_priv ( struct mmc * mmc )
{
return ( void * ) mmc - > priv ;
}
static void sh_sdhi_detect ( struct sh_sdhi_host * host )
{
sh_sdhi_writew ( host , SDHI_OPTION ,
@ -634,23 +632,17 @@ static int sh_sdhi_start_cmd(struct sh_sdhi_host *host,
return ret ;
}
static int sh_sdhi_send_cmd ( struct mmc * mmc , struct mmc_cmd * cmd ,
struct mmc_data * data )
static int sh_sdhi_send_cmd_common ( struct sh_sdhi_host * host ,
struct mmc_cmd * cmd , struct mmc_data * data )
{
struct sh_sdhi_host * host = mmc_priv ( mmc ) ;
int ret ;
host - > sd_error = 0 ;
ret = sh_sdhi_start_cmd ( host , data , cmd ) ;
return ret ;
return sh_sdhi_start_cmd ( host , data , cmd ) ;
}
static int sh_sdhi_set_ios ( struct mmc * mmc )
static int sh_sdhi_set_ios_common ( struct sh_sdhi_host * host , struct mmc * mmc )
{
int ret ;
struct sh_sdhi_host * host = mmc_priv ( mmc ) ;
ret = sh_sdhi_clock_control ( host , mmc - > clock ) ;
if ( ret )
@ -674,9 +666,8 @@ static int sh_sdhi_set_ios(struct mmc *mmc)
return 0 ;
}
static int sh_sdhi_initialize ( struct mmc * mmc )
static int sh_sdhi_initialize_common ( struct sh_sdhi_host * host )
{
struct sh_sdhi_host * host = mmc_priv ( mmc ) ;
int ret = sh_sdhi_sync_reset ( host ) ;
sh_sdhi_writew ( host , SDHI_PORTSEL , USE_1PORT ) ;
@ -692,6 +683,34 @@ static int sh_sdhi_initialize(struct mmc *mmc)
return ret ;
}
# ifndef CONFIG_DM_MMC
static void * mmc_priv ( struct mmc * mmc )
{
return ( void * ) mmc - > priv ;
}
static int sh_sdhi_send_cmd ( struct mmc * mmc , struct mmc_cmd * cmd ,
struct mmc_data * data )
{
struct sh_sdhi_host * host = mmc_priv ( mmc ) ;
return sh_sdhi_send_cmd_common ( host , cmd , data ) ;
}
static int sh_sdhi_set_ios ( struct mmc * mmc )
{
struct sh_sdhi_host * host = mmc_priv ( mmc ) ;
return sh_sdhi_set_ios_common ( host , mmc ) ;
}
static int sh_sdhi_initialize ( struct mmc * mmc )
{
struct sh_sdhi_host * host = mmc_priv ( mmc ) ;
return sh_sdhi_initialize_common ( host ) ;
}
static const struct mmc_ops sh_sdhi_ops = {
. send_cmd = sh_sdhi_send_cmd ,
. set_ios = sh_sdhi_set_ios ,
@ -743,7 +762,7 @@ int sh_sdhi_init(unsigned long addr, int ch, unsigned long quirks)
}
host - > ch = ch ;
host - > addr = addr ;
host - > addr = ( void __iomem * ) addr ;
host - > quirks = quirks ;
if ( host - > quirks & SH_SDHI_QUIRK_64BIT_BUF )
@ -757,3 +776,109 @@ error:
free ( host ) ;
return ret ;
}
# else
struct sh_sdhi_plat {
struct mmc_config cfg ;
struct mmc mmc ;
} ;
int sh_sdhi_dm_send_cmd ( struct udevice * dev , struct mmc_cmd * cmd ,
struct mmc_data * data )
{
struct sh_sdhi_host * host = dev_get_priv ( dev ) ;
return sh_sdhi_send_cmd_common ( host , cmd , data ) ;
}
int sh_sdhi_dm_set_ios ( struct udevice * dev )
{
struct sh_sdhi_host * host = dev_get_priv ( dev ) ;
struct mmc * mmc = mmc_get_mmc_dev ( dev ) ;
return sh_sdhi_set_ios_common ( host , mmc ) ;
}
static const struct dm_mmc_ops sh_sdhi_dm_ops = {
. send_cmd = sh_sdhi_dm_send_cmd ,
. set_ios = sh_sdhi_dm_set_ios ,
} ;
static int sh_sdhi_dm_bind ( struct udevice * dev )
{
struct sh_sdhi_plat * plat = dev_get_platdata ( dev ) ;
return mmc_bind ( dev , & plat - > mmc , & plat - > cfg ) ;
}
static int sh_sdhi_dm_probe ( struct udevice * dev )
{
struct sh_sdhi_plat * plat = dev_get_platdata ( dev ) ;
struct sh_sdhi_host * host = dev_get_priv ( dev ) ;
struct mmc_uclass_priv * upriv = dev_get_uclass_priv ( dev ) ;
const u32 quirks = dev_get_driver_data ( dev ) ;
fdt_addr_t base ;
base = devfdt_get_addr ( dev ) ;
if ( base = = FDT_ADDR_T_NONE )
return - EINVAL ;
host - > addr = devm_ioremap ( dev , base , SZ_2K ) ;
if ( ! host - > addr )
return - ENOMEM ;
host - > quirks = quirks ;
if ( host - > quirks & SH_SDHI_QUIRK_64BIT_BUF )
host - > bus_shift = 2 ;
else if ( host - > quirks & SH_SDHI_QUIRK_16BIT_BUF )
host - > bus_shift = 1 ;
plat - > cfg . name = dev - > name ;
plat - > cfg . host_caps = MMC_MODE_HS_52MHz | MMC_MODE_HS ;
switch ( fdtdec_get_int ( gd - > fdt_blob , dev_of_offset ( dev ) , " bus-width " ,
1 ) ) {
case 8 :
plat - > cfg . host_caps | = MMC_MODE_8BIT ;
break ;
case 4 :
plat - > cfg . host_caps | = MMC_MODE_4BIT ;
break ;
case 1 :
break ;
default :
dev_err ( dev , " Invalid \" bus-width \" value \n " ) ;
return - EINVAL ;
}
sh_sdhi_initialize_common ( host ) ;
plat - > cfg . voltages = MMC_VDD_165_195 | MMC_VDD_32_33 | MMC_VDD_33_34 ;
plat - > cfg . f_min = CLKDEV_INIT ;
plat - > cfg . f_max = CLKDEV_HS_DATA ;
plat - > cfg . b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT ;
upriv - > mmc = & plat - > mmc ;
return 0 ;
}
static const struct udevice_id sh_sdhi_sd_match [ ] = {
{ . compatible = " renesas,sdhi-r8a7795 " , . data = SH_SDHI_QUIRK_64BIT_BUF } ,
{ . compatible = " renesas,sdhi-r8a7796 " , . data = SH_SDHI_QUIRK_64BIT_BUF } ,
{ /* sentinel */ }
} ;
U_BOOT_DRIVER ( sh_sdhi_mmc ) = {
. name = " sh-sdhi-mmc " ,
. id = UCLASS_MMC ,
. of_match = sh_sdhi_sd_match ,
. bind = sh_sdhi_dm_bind ,
. probe = sh_sdhi_dm_probe ,
. priv_auto_alloc_size = sizeof ( struct sh_sdhi_host ) ,
. platdata_auto_alloc_size = sizeof ( struct sh_sdhi_plat ) ,
. ops = & sh_sdhi_dm_ops ,
} ;
# endif