]> git.proxmox.com Git - mirror_ubuntu-kernels.git/commitdiff
mmc: core: Fixup signal voltage switch
authorJohan Rudholm <johan.rudholm@stericsson.com>
Mon, 28 Jan 2013 14:08:28 +0000 (15:08 +0100)
committerChris Ball <cjb@laptop.org>
Sun, 24 Feb 2013 19:37:08 +0000 (14:37 -0500)
When switching SD and SDIO cards from 3.3V to 1.8V signal levels, the
clock should be gated for 5 ms during the step. After enabling the
clock, the host should wait for at least 1 ms before checking for
failure. Failure by the card to switch is indicated by dat[0:3] being
pulled low. The host should check for this condition and power-cycle
the card if failure is indicated.

Add a retry mechanism for the SDIO case.

If the voltage switch fails repeatedly, give up and continue the
initialization using the original voltage.

This patch places a couple of requirements on the host driver:

 1) mmc_set_ios with ios.clock = 0 must gate the clock
 2) mmc_power_off must actually cut the power to the card
 3) The card_busy host_ops member must be implemented

if these requirements are not fulfilled, the 1.8V signal voltage switch
will still be attempted but may not be successful.

Signed-off-by: Johan Rudholm <johan.rudholm@stericsson.com>
Signed-off-by: Kevin Liu <kliu5@marvell.com>
Acked-by: Ulf Hansson <ulf.hansson@linaro.org>
Tested-by: Wei WANG <wei_wang@realsil.com.cn>
Signed-off-by: Chris Ball <cjb@laptop.org>
drivers/mmc/core/core.c
drivers/mmc/core/sd.c
drivers/mmc/core/sdio.c

index bb794c7845971106963ef5686815dcf6ce7c2cc8..e41badbf9b501629a1cb444a0b99af8b4770f0af 100644 (file)
@@ -1340,6 +1340,7 @@ int mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage)
 {
        struct mmc_command cmd = {0};
        int err = 0;
+       u32 clock;
 
        BUG_ON(!host);
 
@@ -1347,20 +1348,82 @@ int mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage)
         * Send CMD11 only if the request is to switch the card to
         * 1.8V signalling.
         */
-       if (signal_voltage != MMC_SIGNAL_VOLTAGE_330) {
-               cmd.opcode = SD_SWITCH_VOLTAGE;
-               cmd.arg = 0;
-               cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
+       if (signal_voltage == MMC_SIGNAL_VOLTAGE_330)
+               return __mmc_set_signal_voltage(host, signal_voltage);
 
-               err = mmc_wait_for_cmd(host, &cmd, 0);
-               if (err)
-                       return err;
+       /*
+        * If we cannot switch voltages, return failure so the caller
+        * can continue without UHS mode
+        */
+       if (!host->ops->start_signal_voltage_switch)
+               return -EPERM;
+       if (!host->ops->card_busy)
+               pr_warning("%s: cannot verify signal voltage switch\n",
+                               mmc_hostname(host));
+
+       cmd.opcode = SD_SWITCH_VOLTAGE;
+       cmd.arg = 0;
+       cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
+
+       err = mmc_wait_for_cmd(host, &cmd, 0);
+       if (err)
+               return err;
 
-               if (!mmc_host_is_spi(host) && (cmd.resp[0] & R1_ERROR))
-                       return -EIO;
+       if (!mmc_host_is_spi(host) && (cmd.resp[0] & R1_ERROR))
+               return -EIO;
+
+       mmc_host_clk_hold(host);
+       /*
+        * The card should drive cmd and dat[0:3] low immediately
+        * after the response of cmd11, but wait 1 ms to be sure
+        */
+       mmc_delay(1);
+       if (host->ops->card_busy && !host->ops->card_busy(host)) {
+               err = -EAGAIN;
+               goto power_cycle;
        }
+       /*
+        * During a signal voltage level switch, the clock must be gated
+        * for 5 ms according to the SD spec
+        */
+       clock = host->ios.clock;
+       host->ios.clock = 0;
+       mmc_set_ios(host);
 
-       return __mmc_set_signal_voltage(host, signal_voltage);
+       if (__mmc_set_signal_voltage(host, signal_voltage)) {
+               /*
+                * Voltages may not have been switched, but we've already
+                * sent CMD11, so a power cycle is required anyway
+                */
+               err = -EAGAIN;
+               goto power_cycle;
+       }
+
+       /* Keep clock gated for at least 5 ms */
+       mmc_delay(5);
+       host->ios.clock = clock;
+       mmc_set_ios(host);
+
+       /* Wait for at least 1 ms according to spec */
+       mmc_delay(1);
+
+       /*
+        * Failure to switch is indicated by the card holding
+        * dat[0:3] low
+        */
+       if (host->ops->card_busy && host->ops->card_busy(host))
+               err = -EAGAIN;
+
+power_cycle:
+       if (err) {
+               pr_debug("%s: Signal voltage switch failed, "
+                       "power cycling card\n", mmc_hostname(host));
+               mmc_power_cycle(host);
+       }
+
+       mmc_host_clk_release(host);
+
+       return err;
 }
 
 /*
index 9a59fcd55a75f636ce103f9dd6f9b5cb4b67027e..03134b1e563cc81d1ee300305ad60e07b08dc0c3 100644 (file)
@@ -712,6 +712,14 @@ int mmc_sd_get_cid(struct mmc_host *host, u32 ocr, u32 *cid, u32 *rocr)
 {
        int err;
        u32 max_current;
+       int retries = 10;
+
+try_again:
+       if (!retries) {
+               ocr &= ~SD_OCR_S18R;
+               pr_warning("%s: Skipping voltage switch\n",
+                       mmc_hostname(host));
+       }
 
        /*
         * Since we're changing the OCR value, we seem to
@@ -733,9 +741,10 @@ int mmc_sd_get_cid(struct mmc_host *host, u32 ocr, u32 *cid, u32 *rocr)
 
        /*
         * If the host supports one of UHS-I modes, request the card
-        * to switch to 1.8V signaling level.
+        * to switch to 1.8V signaling level. If the card has failed
+        * repeatedly to switch however, skip this.
         */
-       if (mmc_host_uhs(host))
+       if (retries && mmc_host_uhs(host))
                ocr |= SD_OCR_S18R;
 
        /*
@@ -746,7 +755,6 @@ int mmc_sd_get_cid(struct mmc_host *host, u32 ocr, u32 *cid, u32 *rocr)
        if (max_current > 150)
                ocr |= SD_OCR_XPC;
 
-try_again:
        err = mmc_send_app_op_cond(host, ocr, rocr);
        if (err)
                return err;
@@ -758,8 +766,11 @@ try_again:
        if (!mmc_host_is_spi(host) && rocr &&
           ((*rocr & 0x41000000) == 0x41000000)) {
                err = mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180);
-               if (err) {
-                       ocr &= ~SD_OCR_S18R;
+               if (err == -EAGAIN) {
+                       retries--;
+                       goto try_again;
+               } else if (err) {
+                       retries = 0;
                        goto try_again;
                }
        }
index 1a726aef211d7f45600e874d6572bb8744497350..aa0719a4dfd16c28f2f1ee03adf5f170016e4cdc 100644 (file)
@@ -584,10 +584,19 @@ static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr,
 {
        struct mmc_card *card;
        int err;
+       int retries = 10;
 
        BUG_ON(!host);
        WARN_ON(!host->claimed);
 
+try_again:
+       if (!retries) {
+               pr_warning("%s: Skipping voltage switch\n",
+                               mmc_hostname(host));
+               ocr &= ~R4_18V_PRESENT;
+               host->ocr &= ~R4_18V_PRESENT;
+       }
+
        /*
         * Inform the card of the voltage
         */
@@ -646,9 +655,16 @@ static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr,
         * systems that claim 1.8v signalling in fact do not support
         * it.
         */
-       if ((ocr & R4_18V_PRESENT) && mmc_host_uhs(host)) {
+       if (!powered_resume && (ocr & R4_18V_PRESENT) && mmc_host_uhs(host)) {
                err = mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180);
-               if (err) {
+               if (err == -EAGAIN) {
+                       sdio_reset(host);
+                       mmc_go_idle(host);
+                       mmc_send_if_cond(host, host->ocr_avail);
+                       mmc_remove_card(card);
+                       retries--;
+                       goto try_again;
+               } else if (err) {
                        ocr &= ~R4_18V_PRESENT;
                        host->ocr &= ~R4_18V_PRESENT;
                }