+#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT)
+static int omap_hsmmc_wait_dat0(struct udevice *dev, int state, int timeout)
+{
+ int ret = -ETIMEDOUT;
+ u32 con;
+ bool dat0_high;
+ bool target_dat0_high = !!state;
+ struct omap_hsmmc_data *priv = dev_get_priv(dev);
+ struct hsmmc *mmc_base = priv->base_addr;
+
+ con = readl(&mmc_base->con);
+ writel(con | CON_CLKEXTFREE | CON_PADEN, &mmc_base->con);
+
+ timeout = DIV_ROUND_UP(timeout, 10); /* check every 10 us. */
+ while (timeout--) {
+ dat0_high = !!(readl(&mmc_base->pstate) & PSTATE_DLEV_DAT0);
+ if (dat0_high == target_dat0_high) {
+ ret = 0;
+ break;
+ }
+ udelay(10);
+ }
+ writel(con, &mmc_base->con);
+
+ return ret;
+}
+#endif
+
+#if CONFIG_IS_ENABLED(MMC_IO_VOLTAGE)
+#if CONFIG_IS_ENABLED(DM_REGULATOR)
+static int omap_hsmmc_set_io_regulator(struct mmc *mmc, int mV)
+{
+ int ret = 0;
+ int uV = mV * 1000;
+
+ struct omap_hsmmc_data *priv = omap_hsmmc_get_data(mmc);
+
+ if (!mmc->vqmmc_supply)
+ return 0;
+
+ /* Disable PBIAS */
+ ret = regulator_set_enable(priv->pbias_supply, false);
+ if (ret && ret != -ENOSYS)
+ return ret;
+
+ /* Turn off IO voltage */
+ ret = regulator_set_enable(mmc->vqmmc_supply, false);
+ if (ret && ret != -ENOSYS)
+ return ret;
+ /* Program a new IO voltage value */
+ ret = regulator_set_value(mmc->vqmmc_supply, uV);
+ if (ret)
+ return ret;
+ /* Turn on IO voltage */
+ ret = regulator_set_enable(mmc->vqmmc_supply, true);
+ if (ret && ret != -ENOSYS)
+ return ret;
+
+ /* Program PBIAS voltage*/
+ ret = regulator_set_value(priv->pbias_supply, uV);
+ if (ret && ret != -ENOSYS)
+ return ret;
+ /* Enable PBIAS */
+ ret = regulator_set_enable(priv->pbias_supply, true);
+ if (ret && ret != -ENOSYS)
+ return ret;
+
+ return 0;
+}
+#endif
+
+static int omap_hsmmc_set_signal_voltage(struct mmc *mmc)
+{
+ struct omap_hsmmc_data *priv = omap_hsmmc_get_data(mmc);
+ struct hsmmc *mmc_base = priv->base_addr;
+ int mv = mmc_voltage_to_mv(mmc->signal_voltage);
+ u32 capa_mask;
+ __maybe_unused u8 palmas_ldo_volt;
+ u32 val;
+
+ if (mv < 0)
+ return -EINVAL;
+
+ if (mmc->signal_voltage == MMC_SIGNAL_VOLTAGE_330) {
+ /* Use 3.0V rather than 3.3V */
+ mv = 3000;
+ capa_mask = VS30_3V0SUP;
+ palmas_ldo_volt = LDO_VOLT_3V0;
+ } else if (mmc->signal_voltage == MMC_SIGNAL_VOLTAGE_180) {
+ capa_mask = VS18_1V8SUP;
+ palmas_ldo_volt = LDO_VOLT_1V8;
+ } else {
+ return -EOPNOTSUPP;
+ }
+
+ val = readl(&mmc_base->capa);
+ if (!(val & capa_mask))
+ return -EOPNOTSUPP;
+
+ priv->signal_voltage = mmc->signal_voltage;
+
+ omap_hsmmc_conf_bus_power(mmc, mmc->signal_voltage);
+
+#if CONFIG_IS_ENABLED(DM_REGULATOR)
+ return omap_hsmmc_set_io_regulator(mmc, mv);
+#elif (defined(CONFIG_OMAP54XX) || defined(CONFIG_OMAP44XX)) && \
+ defined(CONFIG_PALMAS_POWER)
+ if (mmc_get_blk_desc(mmc)->devnum == 0)
+ vmmc_pbias_config(palmas_ldo_volt);
+ return 0;
+#else
+ return 0;
+#endif
+}
+#endif
+
+static uint32_t omap_hsmmc_set_capabilities(struct mmc *mmc)