mmc: omap_hsmmc: add support to set default io voltage

"ti,dual-volt" is used in linux kernel to set the voltage capabilities.
For host controller dt nodes that doesn't have "ti,dual-volt",
it's assumed 1.8v is the io voltage. This is not always true (like in
the case of beagle-x15 where the io lines are connected to 3.3v).
Hence if "no-1-8-v" property is set, io voltage will be set to 3v.

Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
Signed-off-by: Jean-Jacques Hiblot <jjhiblot@ti.com>
This commit is contained in:
Kishon Vijay Abraham I 2018-01-30 16:01:32 +01:00 committed by Jaehoon Chung
parent 48a2f11443
commit b594481709
2 changed files with 77 additions and 2 deletions

View file

@ -65,6 +65,7 @@ struct omap_hsmmc_plat {
struct hsmmc *base_addr;
struct mmc mmc;
bool cd_inverted;
u32 controller_flags;
};
/*
@ -124,8 +125,10 @@ struct omap_hsmmc_plat {
#define DTW_8_BITMODE (0x1 << 5) /* CON[DW8]*/
#define SDBP_PWROFF (0x0 << 8)
#define SDBP_PWRON (0x1 << 8)
#define SDVS_MASK (0x7 << 9)
#define SDVS_1V8 (0x5 << 9)
#define SDVS_3V0 (0x6 << 9)
#define SDVS_3V3 (0x7 << 9)
#define DMA_SELECT (0x2 << 3)
#define ICE_MASK (0x1 << 0)
#define ICE_STOP (0x0 << 0)
@ -159,8 +162,13 @@ struct omap_hsmmc_plat {
#define IE_CERR (0x01 << 28)
#define IE_BADA (0x01 << 29)
#define VS30_3V0SUP (1 << 25)
#define VS18_1V8SUP (1 << 26)
#define VS33_3V3SUP BIT(24)
#define VS30_3V0SUP BIT(25)
#define VS18_1V8SUP BIT(26)
#define IOV_3V3 3300000
#define IOV_3V0 3000000
#define IOV_1V8 1800000
/* Driver definitions */
#define MMCSD_SECTOR_SIZE 512

View file

@ -73,6 +73,9 @@ struct omap_hsmmc_data {
int cd_gpio;
int wp_gpio;
#endif
#endif
#if CONFIG_IS_ENABLED(DM_MMC)
uint iov;
#endif
u8 controller_flags;
#ifndef CONFIG_OMAP34XX
@ -111,6 +114,8 @@ struct omap_hsmmc_adma_desc {
* that the bandwidth is always above 3MB/s).
*/
#define DMA_TIMEOUT_PER_MB 333
#define OMAP_HSMMC_SUPPORTS_DUAL_VOLT BIT(0)
#define OMAP_HSMMC_NO_1_8_V BIT(1)
#define OMAP_HSMMC_USE_ADMA BIT(2)
static int mmc_read_data(struct hsmmc *mmc_base, char *buf, unsigned int size);
@ -252,6 +257,58 @@ void mmc_init_stream(struct hsmmc *mmc_base)
writel(readl(&mmc_base->con) & ~INIT_INITSTREAM, &mmc_base->con);
}
#if CONFIG_IS_ENABLED(DM_MMC)
static void omap_hsmmc_conf_bus_power(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->hctl) & ~SDVS_MASK;
switch (priv->iov) {
case IOV_3V3:
val |= SDVS_3V3;
break;
case IOV_3V0:
val |= SDVS_3V0;
break;
case IOV_1V8:
val |= SDVS_1V8;
break;
}
writel(val, &mmc_base->hctl);
}
static void omap_hsmmc_set_capabilities(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->capa);
if (priv->controller_flags & OMAP_HSMMC_SUPPORTS_DUAL_VOLT) {
val |= (VS30_3V0SUP | VS18_1V8SUP);
priv->iov = IOV_3V0;
} else if (priv->controller_flags & OMAP_HSMMC_NO_1_8_V) {
val |= VS30_3V0SUP;
val &= ~VS18_1V8SUP;
priv->iov = IOV_3V0;
} else {
val |= VS18_1V8SUP;
val &= ~VS30_3V0SUP;
priv->iov = IOV_1V8;
}
writel(val, &mmc_base->capa);
}
#endif
static int omap_hsmmc_init_setup(struct mmc *mmc)
{
struct omap_hsmmc_data *priv = omap_hsmmc_get_data(mmc);
@ -286,9 +343,15 @@ static int omap_hsmmc_init_setup(struct mmc *mmc)
if (reg_val & MADMA_EN)
priv->controller_flags |= OMAP_HSMMC_USE_ADMA;
#endif
#if CONFIG_IS_ENABLED(DM_MMC)
omap_hsmmc_set_capabilities(mmc);
omap_hsmmc_conf_bus_power(mmc);
#else
writel(DTW_1_BITMODE | SDBP_PWROFF | SDVS_3V0, &mmc_base->hctl);
writel(readl(&mmc_base->capa) | VS30_3V0SUP | VS18_1V8SUP,
&mmc_base->capa);
#endif
reg_val = readl(&mmc_base->con) & RESERVED_MASK;
@ -1071,6 +1134,10 @@ static int omap_hsmmc_ofdata_to_platdata(struct udevice *dev)
cfg->f_max = fdtdec_get_int(fdt, node, "max-frequency", 52000000);
cfg->voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195;
cfg->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
if (fdtdec_get_bool(fdt, node, "ti,dual-volt"))
plat->controller_flags |= OMAP_HSMMC_SUPPORTS_DUAL_VOLT;
if (fdtdec_get_bool(fdt, node, "no-1-8-v"))
plat->controller_flags |= OMAP_HSMMC_NO_1_8_V;
#ifdef OMAP_HSMMC_USE_GPIO
plat->cd_inverted = fdtdec_get_bool(fdt, node, "cd-inverted");