Commit c6eb5880 authored by Vincent Yang's avatar Vincent Yang Committed by Ulf Hansson

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: default avatarVincent Yang <Vincent.Yang@tw.fujitsu.com>
Reviewed-by: default avatarJohan Rudholm <jrudholm@gmail.com>
Signed-off-by: default avatarUlf Hansson <ulf.hansson@linaro.org>
parent e34d467c
...@@ -1447,18 +1447,20 @@ int mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage, u32 ocr) ...@@ -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))
return -EIO;
mmc_host_clk_hold(host); if (!mmc_host_is_spi(host) && (cmd.resp[0] & R1_ERROR)) {
err = -EIO;
goto err_command;
}
/* /*
* 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) ...@@ -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;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment