]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blobdiff - drivers/mmc/host/sdhci.c
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next
[mirror_ubuntu-artful-kernel.git] / drivers / mmc / host / sdhci.c
index aaf535ad3a4f1551e69061d556e7cf7c0fe6589f..e010ea4eb6f5672ecc4d1f7e8cfac98856e6b243 100644 (file)
 #define DBG(f, x...) \
        pr_debug(DRIVER_NAME " [%s()]: " f, __func__,## x)
 
-#if defined(CONFIG_LEDS_CLASS) || (defined(CONFIG_LEDS_CLASS_MODULE) && \
-       defined(CONFIG_MMC_SDHCI_MODULE))
-#define SDHCI_USE_LEDS_CLASS
-#endif
-
 #define MAX_TUNING_LOOP 40
 
 static unsigned int debug_quirks = 0;
@@ -53,7 +48,7 @@ static void sdhci_finish_data(struct sdhci_host *);
 static void sdhci_finish_command(struct sdhci_host *);
 static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode);
 static void sdhci_enable_preset_value(struct sdhci_host *host, bool enable);
-static int sdhci_do_get_cd(struct sdhci_host *host);
+static int sdhci_get_cd(struct mmc_host *mmc);
 
 static void sdhci_dumpregs(struct sdhci_host *host)
 {
@@ -198,7 +193,7 @@ EXPORT_SYMBOL_GPL(sdhci_reset);
 static void sdhci_do_reset(struct sdhci_host *host, u8 mask)
 {
        if (host->quirks & SDHCI_QUIRK_NO_CARD_NO_RESET) {
-               if (!sdhci_do_get_cd(host))
+               if (!sdhci_get_cd(host->mmc))
                        return;
        }
 
@@ -246,7 +241,7 @@ static void sdhci_reinit(struct sdhci_host *host)
        sdhci_enable_card_detection(host);
 }
 
-static void sdhci_activate_led(struct sdhci_host *host)
+static void __sdhci_led_activate(struct sdhci_host *host)
 {
        u8 ctrl;
 
@@ -255,7 +250,7 @@ static void sdhci_activate_led(struct sdhci_host *host)
        sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
 }
 
-static void sdhci_deactivate_led(struct sdhci_host *host)
+static void __sdhci_led_deactivate(struct sdhci_host *host)
 {
        u8 ctrl;
 
@@ -264,9 +259,9 @@ static void sdhci_deactivate_led(struct sdhci_host *host)
        sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
 }
 
-#ifdef SDHCI_USE_LEDS_CLASS
+#if IS_REACHABLE(CONFIG_LEDS_CLASS)
 static void sdhci_led_control(struct led_classdev *led,
-       enum led_brightness brightness)
+                             enum led_brightness brightness)
 {
        struct sdhci_host *host = container_of(led, struct sdhci_host, led);
        unsigned long flags;
@@ -277,12 +272,62 @@ static void sdhci_led_control(struct led_classdev *led,
                goto out;
 
        if (brightness == LED_OFF)
-               sdhci_deactivate_led(host);
+               __sdhci_led_deactivate(host);
        else
-               sdhci_activate_led(host);
+               __sdhci_led_activate(host);
 out:
        spin_unlock_irqrestore(&host->lock, flags);
 }
+
+static int sdhci_led_register(struct sdhci_host *host)
+{
+       struct mmc_host *mmc = host->mmc;
+
+       snprintf(host->led_name, sizeof(host->led_name),
+                "%s::", mmc_hostname(mmc));
+
+       host->led.name = host->led_name;
+       host->led.brightness = LED_OFF;
+       host->led.default_trigger = mmc_hostname(mmc);
+       host->led.brightness_set = sdhci_led_control;
+
+       return led_classdev_register(mmc_dev(mmc), &host->led);
+}
+
+static void sdhci_led_unregister(struct sdhci_host *host)
+{
+       led_classdev_unregister(&host->led);
+}
+
+static inline void sdhci_led_activate(struct sdhci_host *host)
+{
+}
+
+static inline void sdhci_led_deactivate(struct sdhci_host *host)
+{
+}
+
+#else
+
+static inline int sdhci_led_register(struct sdhci_host *host)
+{
+       return 0;
+}
+
+static inline void sdhci_led_unregister(struct sdhci_host *host)
+{
+}
+
+static inline void sdhci_led_activate(struct sdhci_host *host)
+{
+       __sdhci_led_activate(host);
+}
+
+static inline void sdhci_led_deactivate(struct sdhci_host *host)
+{
+       __sdhci_led_deactivate(host);
+}
+
 #endif
 
 /*****************************************************************************\
@@ -1186,8 +1231,6 @@ void sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
        host->mmc->actual_clock = 0;
 
        sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL);
-       if (host->quirks2 & SDHCI_QUIRK2_NEED_DELAY_AFTER_INT_CLK_RST)
-               mdelay(1);
 
        if (clock == 0)
                return;
@@ -1332,9 +1375,7 @@ static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq)
 
        WARN_ON(host->mrq != NULL);
 
-#ifndef SDHCI_USE_LEDS_CLASS
-       sdhci_activate_led(host);
-#endif
+       sdhci_led_activate(host);
 
        /*
         * Ensure we don't send the STOP for non-SET_BLOCK_COUNTED
@@ -1409,11 +1450,11 @@ void sdhci_set_uhs_signaling(struct sdhci_host *host, unsigned timing)
 }
 EXPORT_SYMBOL_GPL(sdhci_set_uhs_signaling);
 
-static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios)
+static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 {
+       struct sdhci_host *host = mmc_priv(mmc);
        unsigned long flags;
        u8 ctrl;
-       struct mmc_host *mmc = host->mmc;
 
        spin_lock_irqsave(&host->lock, flags);
 
@@ -1567,16 +1608,10 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios)
        spin_unlock_irqrestore(&host->lock, flags);
 }
 
-static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
+static int sdhci_get_cd(struct mmc_host *mmc)
 {
        struct sdhci_host *host = mmc_priv(mmc);
-
-       sdhci_do_set_ios(host, ios);
-}
-
-static int sdhci_do_get_cd(struct sdhci_host *host)
-{
-       int gpio_cd = mmc_gpio_get_cd(host->mmc);
+       int gpio_cd = mmc_gpio_get_cd(mmc);
 
        if (host->flags & SDHCI_DEVICE_DEAD)
                return 0;
@@ -1600,13 +1635,6 @@ static int sdhci_do_get_cd(struct sdhci_host *host)
        return !!(sdhci_readl(host, SDHCI_PRESENT_STATE) & SDHCI_CARD_PRESENT);
 }
 
-static int sdhci_get_cd(struct mmc_host *mmc)
-{
-       struct sdhci_host *host = mmc_priv(mmc);
-
-       return sdhci_do_get_cd(host);
-}
-
 static int sdhci_check_ro(struct sdhci_host *host)
 {
        unsigned long flags;
@@ -1631,8 +1659,9 @@ static int sdhci_check_ro(struct sdhci_host *host)
 
 #define SAMPLE_COUNT   5
 
-static int sdhci_do_get_ro(struct sdhci_host *host)
+static int sdhci_get_ro(struct mmc_host *mmc)
 {
+       struct sdhci_host *host = mmc_priv(mmc);
        int i, ro_count;
 
        if (!(host->quirks & SDHCI_QUIRK_UNSTABLE_RO_DETECT))
@@ -1657,13 +1686,6 @@ static void sdhci_hw_reset(struct mmc_host *mmc)
                host->ops->hw_reset(host);
 }
 
-static int sdhci_get_ro(struct mmc_host *mmc)
-{
-       struct sdhci_host *host = mmc_priv(mmc);
-
-       return sdhci_do_get_ro(host);
-}
-
 static void sdhci_enable_sdio_irq_nolock(struct sdhci_host *host, int enable)
 {
        if (!(host->flags & SDHCI_DEVICE_DEAD)) {
@@ -1693,10 +1715,10 @@ static void sdhci_enable_sdio_irq(struct mmc_host *mmc, int enable)
        spin_unlock_irqrestore(&host->lock, flags);
 }
 
-static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host,
-                                               struct mmc_ios *ios)
+static int sdhci_start_signal_voltage_switch(struct mmc_host *mmc,
+                                            struct mmc_ios *ios)
 {
-       struct mmc_host *mmc = host->mmc;
+       struct sdhci_host *host = mmc_priv(mmc);
        u16 ctrl;
        int ret;
 
@@ -1784,17 +1806,6 @@ static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host,
        }
 }
 
-static int sdhci_start_signal_voltage_switch(struct mmc_host *mmc,
-       struct mmc_ios *ios)
-{
-       struct sdhci_host *host = mmc_priv(mmc);
-
-       if (host->version < SDHCI_SPEC_300)
-               return 0;
-
-       return sdhci_do_start_signal_voltage_switch(host, ios);
-}
-
 static int sdhci_card_busy(struct mmc_host *mmc)
 {
        struct sdhci_host *host = mmc_priv(mmc);
@@ -1863,8 +1874,7 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)
                break;
 
        case MMC_TIMING_UHS_SDR50:
-               if (host->flags & SDHCI_SDR50_NEEDS_TUNING ||
-                   host->flags & SDHCI_SDR104_NEEDS_TUNING)
+               if (host->flags & SDHCI_SDR50_NEEDS_TUNING)
                        break;
                /* FALLTHROUGH */
 
@@ -2086,7 +2096,7 @@ static void sdhci_card_event(struct mmc_host *mmc)
        if (host->ops->card_event)
                host->ops->card_event(host);
 
-       present = sdhci_do_get_cd(host);
+       present = sdhci_get_cd(host->mmc);
 
        spin_lock_irqsave(&host->lock, flags);
 
@@ -2195,9 +2205,7 @@ static void sdhci_tasklet_finish(unsigned long param)
        host->cmd = NULL;
        host->data = NULL;
 
-#ifndef SDHCI_USE_LEDS_CLASS
-       sdhci_deactivate_led(host);
-#endif
+       sdhci_led_deactivate(host);
 
        mmiowb();
        spin_unlock_irqrestore(&host->lock, flags);
@@ -2659,7 +2667,7 @@ int sdhci_resume_host(struct sdhci_host *host)
                sdhci_init(host, 0);
                host->pwr = 0;
                host->clock = 0;
-               sdhci_do_set_ios(host, &host->mmc->ios);
+               sdhci_set_ios(host->mmc, &host->mmc->ios);
        } else {
                sdhci_init(host, (host->mmc->pm_flags & MMC_PM_KEEP_POWER));
                mmiowb();
@@ -2721,8 +2729,8 @@ int sdhci_runtime_resume_host(struct sdhci_host *host)
        /* Force clock and power re-program */
        host->pwr = 0;
        host->clock = 0;
-       sdhci_do_start_signal_voltage_switch(host, &host->mmc->ios);
-       sdhci_do_set_ios(host, &host->mmc->ios);
+       sdhci_start_signal_voltage_switch(host->mmc, &host->mmc->ios);
+       sdhci_set_ios(host->mmc, &host->mmc->ios);
 
        if ((host_flags & SDHCI_PV_ENABLED) &&
                !(host->quirks2 & SDHCI_QUIRK2_PRESET_VALUE_BROKEN)) {
@@ -2967,7 +2975,8 @@ int sdhci_add_host(struct sdhci_host *host)
                if (!host->ops->get_max_clock) {
                        pr_err("%s: Hardware doesn't specify base clock frequency.\n",
                               mmc_hostname(mmc));
-                       return -ENODEV;
+                       ret = -ENODEV;
+                       goto undma;
                }
                host->max_clk = host->ops->get_max_clock(host);
        }
@@ -3004,7 +3013,7 @@ int sdhci_add_host(struct sdhci_host *host)
        } else
                mmc->f_min = host->max_clk / SDHCI_MAX_DIV_SPEC_200;
 
-       if (!mmc->f_max || (mmc->f_max && (mmc->f_max > max_clk)))
+       if (!mmc->f_max || mmc->f_max > max_clk)
                mmc->f_max = max_clk;
 
        if (!(host->quirks & SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK)) {
@@ -3017,7 +3026,8 @@ int sdhci_add_host(struct sdhci_host *host)
                        } else {
                                pr_err("%s: Hardware doesn't specify timeout clock frequency.\n",
                                        mmc_hostname(mmc));
-                               return -ENODEV;
+                               ret = -ENODEV;
+                               goto undma;
                        }
                }
 
@@ -3071,8 +3081,9 @@ int sdhci_add_host(struct sdhci_host *host)
                mmc->caps |= MMC_CAP_NEEDS_POLL;
 
        /* If there are external regulators, get them */
-       if (mmc_regulator_get_supply(mmc) == -EPROBE_DEFER)
-               return -EPROBE_DEFER;
+       ret = mmc_regulator_get_supply(mmc);
+       if (ret == -EPROBE_DEFER)
+               goto undma;
 
        /* If vqmmc regulator and no 1.8V signalling, then there's no UHS */
        if (!IS_ERR(mmc->supply.vqmmc)) {
@@ -3127,10 +3138,6 @@ int sdhci_add_host(struct sdhci_host *host)
        if (caps[1] & SDHCI_USE_SDR50_TUNING)
                host->flags |= SDHCI_SDR50_NEEDS_TUNING;
 
-       /* Does the host need tuning for SDR104 / HS200? */
-       if (mmc->caps2 & MMC_CAP2_HS200)
-               host->flags |= SDHCI_SDR104_NEEDS_TUNING;
-
        /* Driver Type(s) (A, C, D) supported by the host */
        if (caps[1] & SDHCI_DRIVER_TYPE_A)
                mmc->caps |= MMC_CAP_DRIVER_TYPE_A;
@@ -3229,7 +3236,8 @@ int sdhci_add_host(struct sdhci_host *host)
        if (mmc->ocr_avail == 0) {
                pr_err("%s: Hardware doesn't report any support voltages.\n",
                       mmc_hostname(mmc));
-               return -ENODEV;
+               ret = -ENODEV;
+               goto unreg;
        }
 
        spin_lock_init(&host->lock);
@@ -3313,25 +3321,18 @@ int sdhci_add_host(struct sdhci_host *host)
        sdhci_dumpregs(host);
 #endif
 
-#ifdef SDHCI_USE_LEDS_CLASS
-       snprintf(host->led_name, sizeof(host->led_name),
-               "%s::", mmc_hostname(mmc));
-       host->led.name = host->led_name;
-       host->led.brightness = LED_OFF;
-       host->led.default_trigger = mmc_hostname(mmc);
-       host->led.brightness_set = sdhci_led_control;
-
-       ret = led_classdev_register(mmc_dev(mmc), &host->led);
+       ret = sdhci_led_register(host);
        if (ret) {
                pr_err("%s: Failed to register LED device: %d\n",
                       mmc_hostname(mmc), ret);
-               goto reset;
+               goto unirq;
        }
-#endif
 
        mmiowb();
 
-       mmc_add_host(mmc);
+       ret = mmc_add_host(mmc);
+       if (ret)
+               goto unled;
 
        pr_info("%s: SDHCI controller on %s [%s] using %s\n",
                mmc_hostname(mmc), host->hw_name, dev_name(mmc_dev(mmc)),
@@ -3343,15 +3344,25 @@ int sdhci_add_host(struct sdhci_host *host)
 
        return 0;
 
-#ifdef SDHCI_USE_LEDS_CLASS
-reset:
+unled:
+       sdhci_led_unregister(host);
+unirq:
        sdhci_do_reset(host, SDHCI_RESET_ALL);
        sdhci_writel(host, 0, SDHCI_INT_ENABLE);
        sdhci_writel(host, 0, SDHCI_SIGNAL_ENABLE);
        free_irq(host->irq, host);
-#endif
 untasklet:
        tasklet_kill(&host->finish_tasklet);
+unreg:
+       if (!IS_ERR(mmc->supply.vqmmc))
+               regulator_disable(mmc->supply.vqmmc);
+undma:
+       if (host->align_buffer)
+               dma_free_coherent(mmc_dev(mmc), host->align_buffer_sz +
+                                 host->adma_table_sz, host->align_buffer,
+                                 host->align_addr);
+       host->adma_table = NULL;
+       host->align_buffer = NULL;
 
        return ret;
 }
@@ -3383,9 +3394,7 @@ void sdhci_remove_host(struct sdhci_host *host, int dead)
 
        mmc_remove_host(mmc);
 
-#ifdef SDHCI_USE_LEDS_CLASS
-       led_classdev_unregister(&host->led);
-#endif
+       sdhci_led_unregister(host);
 
        if (!dead)
                sdhci_do_reset(host, SDHCI_RESET_ALL);