]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - drivers/mmc/host/sdhci.c
KARO: cleanup after merge of Freescale 3.10.17 stuff
[karo-tx-linux.git] / drivers / mmc / host / sdhci.c
index fd20e892439a27324f38d2fb3c5e54a80abb3e32..47055f3f01b8580e01ff147232d106bc14db3667 100644 (file)
@@ -205,9 +205,14 @@ static void sdhci_do_reset(struct sdhci_host *host, u8 mask)
 
        host->ops->reset(host, mask);
 
-       if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA)) {
-               if ((host->ops->enable_dma) && (mask & SDHCI_RESET_ALL))
-                       host->ops->enable_dma(host);
+       if (mask & SDHCI_RESET_ALL) {
+               if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA)) {
+                       if (host->ops->enable_dma)
+                               host->ops->enable_dma(host);
+               }
+
+               /* Resetting the controller clears many */
+               host->preset_enabled = false;
        }
 }
 
@@ -1083,24 +1088,23 @@ static void sdhci_finish_command(struct sdhci_host *host)
 
 static u16 sdhci_get_preset_value(struct sdhci_host *host)
 {
-       u16 ctrl, preset = 0;
-
-       ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
+       u16 preset = 0;
 
-       switch (ctrl & SDHCI_CTRL_UHS_MASK) {
-       case SDHCI_CTRL_UHS_SDR12:
+       switch (host->timing) {
+       case MMC_TIMING_UHS_SDR12:
                preset = sdhci_readw(host, SDHCI_PRESET_FOR_SDR12);
                break;
-       case SDHCI_CTRL_UHS_SDR25:
+       case MMC_TIMING_UHS_SDR25:
                preset = sdhci_readw(host, SDHCI_PRESET_FOR_SDR25);
                break;
-       case SDHCI_CTRL_UHS_SDR50:
+       case MMC_TIMING_UHS_SDR50:
                preset = sdhci_readw(host, SDHCI_PRESET_FOR_SDR50);
                break;
-       case SDHCI_CTRL_UHS_SDR104:
+       case MMC_TIMING_UHS_SDR104:
+       case MMC_TIMING_MMC_HS200:
                preset = sdhci_readw(host, SDHCI_PRESET_FOR_SDR104);
                break;
-       case SDHCI_CTRL_UHS_DDR50:
+       case MMC_TIMING_UHS_DDR50:
                preset = sdhci_readw(host, SDHCI_PRESET_FOR_DDR50);
                break;
        default:
@@ -1112,32 +1116,22 @@ static u16 sdhci_get_preset_value(struct sdhci_host *host)
        return preset;
 }
 
-static void sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
+void sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
 {
        int div = 0; /* Initialized for compiler warning */
        int real_div = div, clk_mul = 1;
        u16 clk = 0;
        unsigned long timeout;
 
-       if (clock && clock == host->clock)
-               return;
-
        host->mmc->actual_clock = 0;
 
-       if (host->ops->set_clock) {
-               host->ops->set_clock(host, clock);
-               if (host->quirks & SDHCI_QUIRK_NONSTANDARD_CLOCK)
-                       return;
-       }
-
        sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL);
 
        if (clock == 0)
-               goto out;
+               return;
 
        if (host->version >= SDHCI_SPEC_300) {
-               if (sdhci_readw(host, SDHCI_HOST_CONTROL2) &
-                       SDHCI_CTRL_PRESET_VAL_ENABLE) {
+               if (host->preset_enabled) {
                        u16 pre_val;
 
                        clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
@@ -1223,26 +1217,16 @@ clock_set:
 
        clk |= SDHCI_CLOCK_CARD_EN;
        sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
-
-out:
-       host->clock = clock;
-}
-
-static inline void sdhci_update_clock(struct sdhci_host *host)
-{
-       unsigned int clock;
-
-       clock = host->clock;
-       host->clock = 0;
-       sdhci_set_clock(host, clock);
 }
+EXPORT_SYMBOL_GPL(sdhci_set_clock);
 
-static int sdhci_set_power(struct sdhci_host *host, unsigned short power)
+static void sdhci_set_power(struct sdhci_host *host, unsigned char mode,
+                           unsigned short vdd)
 {
        u8 pwr = 0;
 
-       if (power != (unsigned short)-1) {
-               switch (1 << power) {
+       if (mode != MMC_POWER_OFF) {
+               switch (1 << vdd) {
                case MMC_VDD_165_195:
                        pwr = SDHCI_POWER_180;
                        break;
@@ -1260,7 +1244,7 @@ static int sdhci_set_power(struct sdhci_host *host, unsigned short power)
        }
 
        if (host->pwr == pwr)
-               return -1;
+               return;
 
        host->pwr = pwr;
 
@@ -1268,38 +1252,43 @@ static int sdhci_set_power(struct sdhci_host *host, unsigned short power)
                sdhci_writeb(host, 0, SDHCI_POWER_CONTROL);
                if (host->quirks2 & SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON)
                        sdhci_runtime_pm_bus_off(host);
-               return 0;
-       }
-
-       /*
-        * Spec says that we should clear the power reg before setting
-        * a new value. Some controllers don't seem to like this though.
-        */
-       if (!(host->quirks & SDHCI_QUIRK_SINGLE_POWER_WRITE))
-               sdhci_writeb(host, 0, SDHCI_POWER_CONTROL);
+               vdd = 0;
+       } else {
+               /*
+                * Spec says that we should clear the power reg before setting
+                * a new value. Some controllers don't seem to like this though.
+                */
+               if (!(host->quirks & SDHCI_QUIRK_SINGLE_POWER_WRITE))
+                       sdhci_writeb(host, 0, SDHCI_POWER_CONTROL);
 
-       /*
-        * At least the Marvell CaFe chip gets confused if we set the voltage
-        * and set turn on power at the same time, so set the voltage first.
-        */
-       if (host->quirks & SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER)
-               sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL);
+               /*
+                * At least the Marvell CaFe chip gets confused if we set the
+                * voltage and set turn on power at the same time, so set the
+                * voltage first.
+                */
+               if (host->quirks & SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER)
+                       sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL);
 
-       pwr |= SDHCI_POWER_ON;
+               pwr |= SDHCI_POWER_ON;
 
-       sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL);
+               sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL);
 
-       if (host->quirks2 & SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON)
-               sdhci_runtime_pm_bus_on(host);
+               if (host->quirks2 & SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON)
+                       sdhci_runtime_pm_bus_on(host);
 
-       /*
-        * Some controllers need an extra 10ms delay of 10ms before they
-        * can apply clock after applying power
-        */
-       if (host->quirks & SDHCI_QUIRK_DELAY_AFTER_POWER)
-               mdelay(10);
+               /*
+                * Some controllers need an extra 10ms delay of 10ms before
+                * they can apply clock after applying power
+                */
+               if (host->quirks & SDHCI_QUIRK_DELAY_AFTER_POWER)
+                       mdelay(10);
+       }
 
-       return power;
+       if (host->vmmc) {
+               spin_unlock_irq(&host->lock);
+               mmc_regulator_set_ocr(host->mmc, host->vmmc, vdd);
+               spin_lock_irq(&host->lock);
+       }
 }
 
 /*****************************************************************************\
@@ -1424,10 +1413,32 @@ void sdhci_set_bus_width(struct sdhci_host *host, int width)
 }
 EXPORT_SYMBOL_GPL(sdhci_set_bus_width);
 
+void sdhci_set_uhs_signaling(struct sdhci_host *host, unsigned timing)
+{
+       u16 ctrl_2;
+
+       ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2);
+       /* Select Bus Speed Mode for host */
+       ctrl_2 &= ~SDHCI_CTRL_UHS_MASK;
+       if ((timing == MMC_TIMING_MMC_HS200) ||
+           (timing == MMC_TIMING_UHS_SDR104))
+               ctrl_2 |= SDHCI_CTRL_UHS_SDR104;
+       else if (timing == MMC_TIMING_UHS_SDR12)
+               ctrl_2 |= SDHCI_CTRL_UHS_SDR12;
+       else if (timing == MMC_TIMING_UHS_SDR25)
+               ctrl_2 |= SDHCI_CTRL_UHS_SDR25;
+       else if (timing == MMC_TIMING_UHS_SDR50)
+               ctrl_2 |= SDHCI_CTRL_UHS_SDR50;
+       else if ((timing == MMC_TIMING_UHS_DDR50) ||
+                (timing == MMC_TIMING_MMC_DDR52))
+               ctrl_2 |= SDHCI_CTRL_UHS_DDR50;
+       sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2);
+}
+EXPORT_SYMBOL_GPL(sdhci_set_uhs_signaling);
+
 static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios)
 {
        unsigned long flags;
-       int vdd_bit = -1;
        u8 ctrl;
 
        spin_lock_irqsave(&host->lock, flags);
@@ -1453,19 +1464,13 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios)
                !(host->quirks2 & SDHCI_QUIRK2_PRESET_VALUE_BROKEN))
                sdhci_enable_preset_value(host, false);
 
-       sdhci_set_clock(host, ios->clock);
-
-       if (ios->power_mode == MMC_POWER_OFF)
-               vdd_bit = sdhci_set_power(host, -1);
-       else
-               vdd_bit = sdhci_set_power(host, ios->vdd);
-
-       if (host->vmmc && vdd_bit != -1) {
-               spin_unlock_irqrestore(&host->lock, flags);
-               mmc_regulator_set_ocr(host->mmc, host->vmmc, vdd_bit);
-               spin_lock_irqsave(&host->lock, flags);
+       if (!ios->clock || ios->clock != host->clock) {
+               host->ops->set_clock(host, ios->clock);
+               host->clock = ios->clock;
        }
 
+       sdhci_set_power(host, ios->power_mode, ios->vdd);
+
        if (host->ops->platform_send_init_74_clocks)
                host->ops->platform_send_init_74_clocks(host, ios->power_mode);
 
@@ -1492,13 +1497,13 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios)
                    (ios->timing == MMC_TIMING_UHS_SDR25))
                        ctrl |= SDHCI_CTRL_HISPD;
 
-               ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2);
-               if (!(ctrl_2 & SDHCI_CTRL_PRESET_VAL_ENABLE)) {
+               if (!host->preset_enabled) {
                        sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
                        /*
                         * We only need to set Driver Strength if the
                         * preset value enable is not set.
                         */
+                       ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2);
                        ctrl_2 &= ~SDHCI_CTRL_DRV_TYPE_MASK;
                        if (ios->drv_type == MMC_SET_DRIVER_TYPE_A)
                                ctrl_2 |= SDHCI_CTRL_DRV_TYPE_A;
@@ -1522,7 +1527,7 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios)
                        sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
 
                        /* Re-enable SD Clock */
-                       sdhci_update_clock(host);
+                       host->ops->set_clock(host, host->clock);
                }
 
 
@@ -1531,26 +1536,8 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios)
                clk &= ~SDHCI_CLOCK_CARD_EN;
                sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
 
-               if (host->ops->set_uhs_signaling)
-                       host->ops->set_uhs_signaling(host, ios->timing);
-               else {
-                       ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2);
-                       /* Select Bus Speed Mode for host */
-                       ctrl_2 &= ~SDHCI_CTRL_UHS_MASK;
-                       if ((ios->timing == MMC_TIMING_MMC_HS200) ||
-                           (ios->timing == MMC_TIMING_UHS_SDR104))
-                               ctrl_2 |= SDHCI_CTRL_UHS_SDR104;
-                       else if (ios->timing == MMC_TIMING_UHS_SDR12)
-                               ctrl_2 |= SDHCI_CTRL_UHS_SDR12;
-                       else if (ios->timing == MMC_TIMING_UHS_SDR25)
-                               ctrl_2 |= SDHCI_CTRL_UHS_SDR25;
-                       else if (ios->timing == MMC_TIMING_UHS_SDR50)
-                               ctrl_2 |= SDHCI_CTRL_UHS_SDR50;
-                       else if ((ios->timing == MMC_TIMING_UHS_DDR50) ||
-                                (ios->timing == MMC_TIMING_MMC_DDR52))
-                               ctrl_2 |= SDHCI_CTRL_UHS_DDR50;
-                       sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2);
-               }
+               host->ops->set_uhs_signaling(host, ios->timing);
+               host->timing = ios->timing;
 
                if (!(host->quirks2 & SDHCI_QUIRK2_PRESET_VALUE_BROKEN) &&
                                ((ios->timing == MMC_TIMING_UHS_SDR12) ||
@@ -1567,7 +1554,7 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios)
                }
 
                /* Re-enable SD Clock */
-               sdhci_update_clock(host);
+               host->ops->set_clock(host, host->clock);
        } else
                sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
 
@@ -1833,21 +1820,15 @@ static int sdhci_card_busy(struct mmc_host *mmc)
 
 static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)
 {
-       struct sdhci_host *host;
+       struct sdhci_host *host = mmc_priv(mmc);
        u16 ctrl;
        int tuning_loop_counter = MAX_TUNING_LOOP;
-       unsigned long timeout;
        int err = 0;
-       bool requires_tuning_nonuhs = false;
        unsigned long flags;
 
-       host = mmc_priv(mmc);
-
        sdhci_runtime_pm_get(host);
        spin_lock_irqsave(&host->lock, flags);
 
-       ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
-
        /*
         * The Host Controller needs tuning only in case of SDR104 mode
         * and for SDR50 mode when Use Tuning for SDR50 is set in the
@@ -1855,15 +1836,18 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)
         * If the Host Controller supports the HS200 mode then the
         * tuning function has to be executed.
         */
-       if (((ctrl & SDHCI_CTRL_UHS_MASK) == SDHCI_CTRL_UHS_SDR50) &&
-           (host->flags & SDHCI_SDR50_NEEDS_TUNING ||
-            host->flags & SDHCI_SDR104_NEEDS_TUNING))
-               requires_tuning_nonuhs = true;
-
-       if (((ctrl & SDHCI_CTRL_UHS_MASK) == SDHCI_CTRL_UHS_SDR104) ||
-           requires_tuning_nonuhs)
-               ctrl |= SDHCI_CTRL_EXEC_TUNING;
-       else {
+       switch (host->timing) {
+       case MMC_TIMING_MMC_HS200:
+       case MMC_TIMING_UHS_SDR104:
+               break;
+
+       case MMC_TIMING_UHS_SDR50:
+               if (host->flags & SDHCI_SDR50_NEEDS_TUNING ||
+                   host->flags & SDHCI_SDR104_NEEDS_TUNING)
+                       break;
+               /* FALLTHROUGH */
+
+       default:
                spin_unlock_irqrestore(&host->lock, flags);
                sdhci_runtime_pm_put(host);
                return 0;
@@ -1876,6 +1860,8 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)
                return err;
        }
 
+       ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
+       ctrl |= SDHCI_CTRL_EXEC_TUNING;
        sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
 
        /*
@@ -1895,14 +1881,10 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)
         * Issue CMD19 repeatedly till Execute Tuning is set to 0 or the number
         * of loops reaches 40 times or a timeout of 150ms occurs.
         */
-       timeout = 150;
        do {
                struct mmc_command cmd = {0};
                struct mmc_request mrq = {NULL};
 
-               if (!tuning_loop_counter && !timeout)
-                       break;
-
                cmd.opcode = opcode;
                cmd.arg = 0;
                cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
@@ -1910,6 +1892,9 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)
                cmd.data = NULL;
                cmd.error = 0;
 
+               if (tuning_loop_counter-- == 0)
+                       break;
+
                mrq.cmd = &cmd;
                host->mrq = &mrq;
 
@@ -1967,8 +1952,6 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)
                host->tuning_done = 0;
 
                ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
-               tuning_loop_counter--;
-               timeout--;
 
                /* eMMC spec does not require a delay between tuning cycles */
                if (opcode == MMC_SEND_TUNING_BLOCK)
@@ -1979,17 +1962,15 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)
         * The Host Driver has exhausted the maximum number of loops allowed,
         * so use fixed sampling frequency.
         */
-       if (!tuning_loop_counter || !timeout) {
+       if (tuning_loop_counter < 0) {
                ctrl &= ~SDHCI_CTRL_TUNED_CLK;
                sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
+       }
+       if (!(ctrl & SDHCI_CTRL_TUNED_CLK)) {
+               pr_info(DRIVER_NAME ": Tuning procedure"
+                       " failed, falling back to fixed sampling"
+                       " clock\n");
                err = -EIO;
-       } else {
-               if (!(ctrl & SDHCI_CTRL_TUNED_CLK)) {
-                       pr_info(DRIVER_NAME ": Tuning procedure"
-                               " failed, falling back to fixed sampling"
-                               " clock\n");
-                       err = -EIO;
-               }
        }
 
 out:
@@ -2035,26 +2016,30 @@ out:
 
 static void sdhci_enable_preset_value(struct sdhci_host *host, bool enable)
 {
-       u16 ctrl;
-
        /* Host Controller v3.00 defines preset value registers */
        if (host->version < SDHCI_SPEC_300)
                return;
 
-       ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
-
        /*
         * We only enable or disable Preset Value if they are not already
         * enabled or disabled respectively. Otherwise, we bail out.
         */
-       if (enable && !(ctrl & SDHCI_CTRL_PRESET_VAL_ENABLE)) {
-               ctrl |= SDHCI_CTRL_PRESET_VAL_ENABLE;
-               sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
-               host->flags |= SDHCI_PV_ENABLED;
-       } else if (!enable && (ctrl & SDHCI_CTRL_PRESET_VAL_ENABLE)) {
-               ctrl &= ~SDHCI_CTRL_PRESET_VAL_ENABLE;
+       if (host->preset_enabled != enable) {
+               u16 ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
+
+               if (enable)
+                       ctrl |= SDHCI_CTRL_PRESET_VAL_ENABLE;
+               else
+                       ctrl &= ~SDHCI_CTRL_PRESET_VAL_ENABLE;
+
                sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
-               host->flags &= ~SDHCI_PV_ENABLED;
+
+               if (enable)
+                       host->flags |= SDHCI_PV_ENABLED;
+               else
+                       host->flags &= ~SDHCI_PV_ENABLED;
+
+               host->preset_enabled = enable;
        }
 }
 
@@ -2141,7 +2126,7 @@ static void sdhci_tasklet_finish(unsigned long param)
                /* Some controllers need this kick or reset won't work here */
                if (host->quirks & SDHCI_QUIRK_CLOCK_BEFORE_RESET)
                        /* This is to force an update */
-                       sdhci_update_clock(host);
+                       host->ops->set_clock(host, host->clock);
 
                /* Spec says we should do both at the same time, but Ricoh
                   controllers do not like that. */
@@ -2560,9 +2545,6 @@ EXPORT_SYMBOL_GPL(sdhci_disable_irq_wakeups);
 
 int sdhci_suspend_host(struct sdhci_host *host)
 {
-       if (host->ops->platform_suspend)
-               host->ops->platform_suspend(host);
-
        sdhci_disable_card_detection(host);
 
        /* Disable tuning since we are suspending */
@@ -2619,9 +2601,6 @@ int sdhci_resume_host(struct sdhci_host *host)
 
        sdhci_enable_card_detection(host);
 
-       if (host->ops->platform_resume)
-               host->ops->platform_resume(host);
-
        /* Set the re-tuning expiration flag */
        if (host->flags & SDHCI_USING_RETUNING_TIMER)
                host->flags |= SDHCI_NEEDS_RETUNING;