/* Extended status bits for the STM32 variants */
 #define MCI_STM32_BUSYD0       BIT(20)
 #define MCI_STM32_BUSYD0END    BIT(21)
+#define MCI_STM32_VSWEND       BIT(25)
 
 #define MMCICLEAR              0x038
 #define MCI_CMDCRCFAILCLR      (1 << 0)
 #define MCI_ST_SDIOITC         (1 << 22)
 #define MCI_ST_CEATAENDC       (1 << 23)
 #define MCI_ST_BUSYENDC                (1 << 24)
+/* Extended clear bits for the STM32 variants */
+#define MCI_STM32_VSWENDC      BIT(25)
+#define MCI_STM32_CKSTOPC      BIT(26)
 
 #define MMCIMASK0              0x03c
 #define MCI_CMDCRCFAILMASK     (1 << 0)
 
 #define DLYB_CFGR_UNIT_MAX     127
 
 #define DLYB_LNG_TIMEOUT_US    1000
+#define SDMMC_VSWEND_TIMEOUT_US 10000
 
 struct sdmmc_lli_desc {
        u32 idmalar;
        struct mmc_ios ios = host->mmc->ios;
        struct sdmmc_dlyb *dlyb = host->variant_priv;
 
+       /* adds OF options */
        pwr = host->pwr_reg_add;
 
        sdmmc_dlyb_input_ck(dlyb);
                writel(MCI_IRQENABLE | host->variant->start_err,
                       host->base + MMCIMASK0);
 
+               /* preserves voltage switch bits */
+               pwr |= host->pwr_reg & (MCI_STM32_VSWITCHEN |
+                                       MCI_STM32_VSWITCH);
+
                /*
                 * After a power-cycle state, we must set the SDMMC in
                 * Power-off. The SDMMC_D[7:0], SDMMC_CMD and SDMMC_CK are
        return sdmmc_dlyb_phase_tuning(host, opcode);
 }
 
+static void sdmmc_pre_sig_volt_vswitch(struct mmci_host *host)
+{
+       /* clear the voltage switch completion flag */
+       writel_relaxed(MCI_STM32_VSWENDC, host->base + MMCICLEAR);
+       /* enable Voltage switch procedure */
+       mmci_write_pwrreg(host, host->pwr_reg | MCI_STM32_VSWITCHEN);
+}
+
+static int sdmmc_post_sig_volt_switch(struct mmci_host *host,
+                                     struct mmc_ios *ios)
+{
+       unsigned long flags;
+       u32 status;
+       int ret = 0;
+
+       if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_180) {
+               spin_lock_irqsave(&host->lock, flags);
+               mmci_write_pwrreg(host, host->pwr_reg | MCI_STM32_VSWITCH);
+               spin_unlock_irqrestore(&host->lock, flags);
+
+               /* wait voltage switch completion while 10ms */
+               ret = readl_relaxed_poll_timeout(host->base + MMCISTATUS,
+                                                status,
+                                                (status & MCI_STM32_VSWEND),
+                                                10, SDMMC_VSWEND_TIMEOUT_US);
+
+               writel_relaxed(MCI_STM32_VSWENDC | MCI_STM32_CKSTOPC,
+                              host->base + MMCICLEAR);
+               mmci_write_pwrreg(host, host->pwr_reg &
+                                 ~(MCI_STM32_VSWITCHEN | MCI_STM32_VSWITCH));
+       }
+
+       return ret;
+}
+
 static struct mmci_host_ops sdmmc_variant_ops = {
        .validate_data = sdmmc_idma_validate_data,
        .prep_data = sdmmc_idma_prep_data,
        .set_clkreg = mmci_sdmmc_set_clkreg,
        .set_pwrreg = mmci_sdmmc_set_pwrreg,
        .busy_complete = sdmmc_busy_complete,
+       .pre_sig_volt_switch = sdmmc_pre_sig_volt_vswitch,
+       .post_sig_volt_switch = sdmmc_post_sig_volt_switch,
 };
 
 void sdmmc_variant_init(struct mmci_host *host)