summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/mmc/dw_mmc.c15
-rw-r--r--include/dwmmc.h4
2 files changed, 17 insertions, 2 deletions
diff --git a/drivers/mmc/dw_mmc.c b/drivers/mmc/dw_mmc.c
index 1aa992c352c..94b6641c44c 100644
--- a/drivers/mmc/dw_mmc.c
+++ b/drivers/mmc/dw_mmc.c
@@ -419,6 +419,10 @@ static int dwmci_send_cmd_common(struct dwmci_host *host, struct mmc_cmd *cmd,
if (cmd->resp_type & MMC_RSP_CRC)
flags |= DWMCI_CMD_CHECK_CRC;
+ host->volt_switching = (cmd->cmdidx == SD_CMD_SWITCH_UHS18V);
+ if (host->volt_switching)
+ flags |= DWMCI_CMD_VOLT_SWITCH;
+
flags |= cmd->cmdidx | DWMCI_CMD_START | DWMCI_CMD_USE_HOLD_REG;
debug("Sending CMD%d\n", cmd->cmdidx);
@@ -427,6 +431,10 @@ static int dwmci_send_cmd_common(struct dwmci_host *host, struct mmc_cmd *cmd,
for (i = 0; i < retry; i++) {
mask = dwmci_readl(host, DWMCI_RINTSTS);
+ if (host->volt_switching && (mask & DWMCI_INTMSK_VOLTSW)) {
+ dwmci_writel(host, DWMCI_RINTSTS, DWMCI_INTMSK_VOLTSW);
+ break;
+ }
if (mask & DWMCI_INTMSK_CDONE) {
if (!data)
dwmci_writel(host, DWMCI_RINTSTS, mask);
@@ -508,12 +516,15 @@ static int dwmci_control_clken(struct dwmci_host *host, bool on)
const u32 val = on ? DWMCI_CLKEN_ENABLE | DWMCI_CLKEN_LOW_PWR : 0;
const u32 cmd_only_clk = DWMCI_CMD_PRV_DAT_WAIT | DWMCI_CMD_UPD_CLK;
int i, timeout = 10000;
- u32 mask;
+ u32 flags, mask;
dwmci_writel(host, DWMCI_CLKENA, val);
/* Inform CIU */
- dwmci_writel(host, DWMCI_CMD, DWMCI_CMD_START | cmd_only_clk);
+ flags = DWMCI_CMD_START | cmd_only_clk;
+ if (host->volt_switching)
+ flags |= DWMCI_CMD_VOLT_SWITCH;
+ dwmci_writel(host, DWMCI_CMD, flags);
for (i = 0; i < timeout; i++) {
mask = dwmci_readl(host, DWMCI_RINTSTS);
diff --git a/include/dwmmc.h b/include/dwmmc.h
index 639a2d28e78..47e3220985e 100644
--- a/include/dwmmc.h
+++ b/include/dwmmc.h
@@ -72,6 +72,7 @@
#define DWMCI_INTMSK_RTO BIT(8)
#define DWMCI_INTMSK_DRTO BIT(9)
#define DWMCI_INTMSK_HTO BIT(10)
+#define DWMCI_INTMSK_VOLTSW BIT(10) /* overlap! */
#define DWMCI_INTMSK_FRUN BIT(11)
#define DWMCI_INTMSK_HLE BIT(12)
#define DWMCI_INTMSK_SBE BIT(13)
@@ -104,6 +105,7 @@
#define DWMCI_CMD_ABORT_STOP BIT(14)
#define DWMCI_CMD_PRV_DAT_WAIT BIT(13)
#define DWMCI_CMD_UPD_CLK BIT(21)
+#define DWMCI_CMD_VOLT_SWITCH BIT(28)
#define DWMCI_CMD_USE_HOLD_REG BIT(29)
#define DWMCI_CMD_START BIT(31)
@@ -190,6 +192,7 @@ struct dwmci_idmac_regs {
* @cfg: Internal MMC configuration, for !CONFIG_BLK cases
* @fifo_mode: Use FIFO mode (not DMA) to read and write data
* @dma_64bit_address: Whether DMA supports 64-bit address mode or not
+ * @volt_switching: Whether SD voltage switching is in process or not
* @regs: Registers that can vary for different DW MMC block versions
*/
struct dwmci_host {
@@ -229,6 +232,7 @@ struct dwmci_host {
bool fifo_mode;
bool dma_64bit_address;
+ bool volt_switching;
const struct dwmci_idmac_regs *regs;
};