mirror of
https://source.denx.de/u-boot/u-boot.git
synced 2026-05-05 12:46:14 +02:00
mmc: dw_mmc: add voltage switch command flag
During a voltage switch command (CMD11, opcode: SD_CMD_SWITCH_UHS18V), certain hosts tend to stop responding to subsequent commands. This is addressed by introducing an additional command flag, DWMCI_CMD_VOLT_SWITCH. The associated interrupt bit is defined as DWMCI_INTMSK_VOLTSW. This is set high when a voltage switch is issued, this needs to be waited for and set to low. Implement the same in the timeout loop. Do note that since DWMCI_INTMSK_VOLTSW shares the same bit as DWMCI_INTMSK_HTO (bit 10), the interrupt bit needs to be polled for only if the volt switch command is issued. DWMCI_CMD_VOLT_SWITCH also needs to be set for subsequent clken commands after the volt switch. To ensure this, add a boolean member in the host private struct (herein named volt_switching), which informs if the last command issued was for volt switching or not. Signed-off-by: Kaustabh Chakraborty <kauschluss@disroot.org> Signed-off-by: Peng Fan <peng.fan@nxp.com>
This commit is contained in:
parent
ae46019592
commit
e6b66e9f33
@ -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);
|
||||
|
||||
@ -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;
|
||||
};
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user