|
@@ -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");
|