mmc: core: hold SD Clock before CMD11 during Signal
Voltage Switch Procedure This patch is to fix an issue found on mb86s7x platforms. [symptom] There are some UHS-1 SD memory cards sometimes cannot be detected correctly, e.g., Transcend 600x SDXC 64GB UHS-1 memory card. During Signal Voltage Switch Procedure, failure to switch is indicated by the card holding DAT[3:0] low. [analysis] According to SD Host Controller Simplified Specification Version 3.00 chapter 3.6.1, the Signal Voltage Switch Procedure should be: (1) Check S18A; (2) Issue CMD11; (3) Check CMD 11 response; (4) Stop providing SD clock; (5) Check DAT[3:0] should be 0000b; (6) Set 1.8V Signal Enable; (7) Wait 5ms; (8) Check 1.8V Signal Enable; (9) Provide SD Clock; (10) Wait 1ms; (11) Check DAT[3:0] should be 1111b; (12) error handling With CONFIG_MMC_CLKGATE=y, sometimes there is one more gating/un-gating SD clock between (2) and (3). In this case, some UHS-1 SD cards will hold DAT[3:0] 0000b at (11) and thus fails Signal Voltage Switch Procedure. [solution] By mmc_host_clk_hold() before CMD11, the additional gating/un-gating SD clock between (2) and (3) can be prevented and thus no failure at (11). It has been verified with many UHS-1 SD cards on mb86s7x platforms and works correctly. Signed-off-by: Vincent Yang <Vincent.Yang@tw.fujitsu.com> Reviewed-by: Johan Rudholm <jrudholm@gmail.com> Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
This commit is contained in:
parent
e34d467c51
commit
c6eb588028
1 changed files with 8 additions and 5 deletions
|
@ -1447,18 +1447,20 @@ int mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage, u32 ocr)
|
||||||
pr_warn("%s: cannot verify signal voltage switch\n",
|
pr_warn("%s: cannot verify signal voltage switch\n",
|
||||||
mmc_hostname(host));
|
mmc_hostname(host));
|
||||||
|
|
||||||
|
mmc_host_clk_hold(host);
|
||||||
|
|
||||||
cmd.opcode = SD_SWITCH_VOLTAGE;
|
cmd.opcode = SD_SWITCH_VOLTAGE;
|
||||||
cmd.arg = 0;
|
cmd.arg = 0;
|
||||||
cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
|
cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
|
||||||
|
|
||||||
err = mmc_wait_for_cmd(host, &cmd, 0);
|
err = mmc_wait_for_cmd(host, &cmd, 0);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
goto err_command;
|
||||||
|
|
||||||
if (!mmc_host_is_spi(host) && (cmd.resp[0] & R1_ERROR))
|
if (!mmc_host_is_spi(host) && (cmd.resp[0] & R1_ERROR)) {
|
||||||
return -EIO;
|
err = -EIO;
|
||||||
|
goto err_command;
|
||||||
mmc_host_clk_hold(host);
|
}
|
||||||
/*
|
/*
|
||||||
* The card should drive cmd and dat[0:3] low immediately
|
* The card should drive cmd and dat[0:3] low immediately
|
||||||
* after the response of cmd11, but wait 1 ms to be sure
|
* after the response of cmd11, but wait 1 ms to be sure
|
||||||
|
@ -1507,6 +1509,7 @@ int mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage, u32 ocr)
|
||||||
mmc_power_cycle(host, ocr);
|
mmc_power_cycle(host, ocr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err_command:
|
||||||
mmc_host_clk_release(host);
|
mmc_host_clk_release(host);
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
|
|
Loading…
Reference in a new issue