diff options
Diffstat (limited to 'drivers/mmc/host/sdhci.c')
| -rw-r--r-- | drivers/mmc/host/sdhci.c | 79 |
1 files changed, 45 insertions, 34 deletions
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index c7851c0aabce..6f0bfc0c8c9c 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c | |||
| @@ -1618,7 +1618,7 @@ static int sdhci_do_3_3v_signal_voltage_switch(struct sdhci_host *host, | |||
| 1618 | sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2); | 1618 | sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2); |
| 1619 | 1619 | ||
| 1620 | if (host->vqmmc) { | 1620 | if (host->vqmmc) { |
| 1621 | ret = regulator_set_voltage(host->vqmmc, 3300000, 3300000); | 1621 | ret = regulator_set_voltage(host->vqmmc, 2700000, 3600000); |
| 1622 | if (ret) { | 1622 | if (ret) { |
| 1623 | pr_warning("%s: Switching to 3.3V signalling voltage " | 1623 | pr_warning("%s: Switching to 3.3V signalling voltage " |
| 1624 | " failed\n", mmc_hostname(host->mmc)); | 1624 | " failed\n", mmc_hostname(host->mmc)); |
| @@ -1662,7 +1662,7 @@ static int sdhci_do_1_8v_signal_voltage_switch(struct sdhci_host *host, | |||
| 1662 | */ | 1662 | */ |
| 1663 | if (host->vqmmc) | 1663 | if (host->vqmmc) |
| 1664 | ret = regulator_set_voltage(host->vqmmc, | 1664 | ret = regulator_set_voltage(host->vqmmc, |
| 1665 | 1800000, 1800000); | 1665 | 1700000, 1950000); |
| 1666 | else | 1666 | else |
| 1667 | ret = 0; | 1667 | ret = 0; |
| 1668 | 1668 | ||
| @@ -1994,30 +1994,11 @@ static void sdhci_enable_preset_value(struct mmc_host *mmc, bool enable) | |||
| 1994 | sdhci_runtime_pm_put(host); | 1994 | sdhci_runtime_pm_put(host); |
| 1995 | } | 1995 | } |
| 1996 | 1996 | ||
| 1997 | static const struct mmc_host_ops sdhci_ops = { | 1997 | static void sdhci_card_event(struct mmc_host *mmc) |
| 1998 | .request = sdhci_request, | ||
| 1999 | .set_ios = sdhci_set_ios, | ||
| 2000 | .get_ro = sdhci_get_ro, | ||
| 2001 | .hw_reset = sdhci_hw_reset, | ||
| 2002 | .enable_sdio_irq = sdhci_enable_sdio_irq, | ||
| 2003 | .start_signal_voltage_switch = sdhci_start_signal_voltage_switch, | ||
| 2004 | .execute_tuning = sdhci_execute_tuning, | ||
| 2005 | .enable_preset_value = sdhci_enable_preset_value, | ||
| 2006 | }; | ||
| 2007 | |||
| 2008 | /*****************************************************************************\ | ||
| 2009 | * * | ||
| 2010 | * Tasklets * | ||
| 2011 | * * | ||
| 2012 | \*****************************************************************************/ | ||
| 2013 | |||
| 2014 | static void sdhci_tasklet_card(unsigned long param) | ||
| 2015 | { | 1998 | { |
| 2016 | struct sdhci_host *host; | 1999 | struct sdhci_host *host = mmc_priv(mmc); |
| 2017 | unsigned long flags; | 2000 | unsigned long flags; |
| 2018 | 2001 | ||
| 2019 | host = (struct sdhci_host*)param; | ||
| 2020 | |||
| 2021 | spin_lock_irqsave(&host->lock, flags); | 2002 | spin_lock_irqsave(&host->lock, flags); |
| 2022 | 2003 | ||
| 2023 | /* Check host->mrq first in case we are runtime suspended */ | 2004 | /* Check host->mrq first in case we are runtime suspended */ |
| @@ -2036,6 +2017,31 @@ static void sdhci_tasklet_card(unsigned long param) | |||
| 2036 | } | 2017 | } |
| 2037 | 2018 | ||
| 2038 | spin_unlock_irqrestore(&host->lock, flags); | 2019 | spin_unlock_irqrestore(&host->lock, flags); |
| 2020 | } | ||
| 2021 | |||
| 2022 | static const struct mmc_host_ops sdhci_ops = { | ||
| 2023 | .request = sdhci_request, | ||
| 2024 | .set_ios = sdhci_set_ios, | ||
| 2025 | .get_ro = sdhci_get_ro, | ||
| 2026 | .hw_reset = sdhci_hw_reset, | ||
| 2027 | .enable_sdio_irq = sdhci_enable_sdio_irq, | ||
| 2028 | .start_signal_voltage_switch = sdhci_start_signal_voltage_switch, | ||
| 2029 | .execute_tuning = sdhci_execute_tuning, | ||
| 2030 | .enable_preset_value = sdhci_enable_preset_value, | ||
| 2031 | .card_event = sdhci_card_event, | ||
| 2032 | }; | ||
| 2033 | |||
| 2034 | /*****************************************************************************\ | ||
| 2035 | * * | ||
| 2036 | * Tasklets * | ||
| 2037 | * * | ||
| 2038 | \*****************************************************************************/ | ||
| 2039 | |||
| 2040 | static void sdhci_tasklet_card(unsigned long param) | ||
| 2041 | { | ||
| 2042 | struct sdhci_host *host = (struct sdhci_host*)param; | ||
| 2043 | |||
| 2044 | sdhci_card_event(host->mmc); | ||
| 2039 | 2045 | ||
| 2040 | mmc_detect_change(host->mmc, msecs_to_jiffies(200)); | 2046 | mmc_detect_change(host->mmc, msecs_to_jiffies(200)); |
| 2041 | } | 2047 | } |
| @@ -2282,6 +2288,8 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask) | |||
| 2282 | pr_err("%s: ADMA error\n", mmc_hostname(host->mmc)); | 2288 | pr_err("%s: ADMA error\n", mmc_hostname(host->mmc)); |
| 2283 | sdhci_show_adma_error(host); | 2289 | sdhci_show_adma_error(host); |
| 2284 | host->data->error = -EIO; | 2290 | host->data->error = -EIO; |
| 2291 | if (host->ops->adma_workaround) | ||
| 2292 | host->ops->adma_workaround(host, intmask); | ||
| 2285 | } | 2293 | } |
| 2286 | 2294 | ||
| 2287 | if (host->data->error) | 2295 | if (host->data->error) |
| @@ -2858,10 +2866,16 @@ int sdhci_add_host(struct sdhci_host *host) | |||
| 2858 | mmc_hostname(mmc)); | 2866 | mmc_hostname(mmc)); |
| 2859 | host->vqmmc = NULL; | 2867 | host->vqmmc = NULL; |
| 2860 | } | 2868 | } |
| 2861 | } | 2869 | } else { |
| 2862 | else if (regulator_is_supported_voltage(host->vqmmc, 1800000, 1800000)) | ||
| 2863 | regulator_enable(host->vqmmc); | 2870 | regulator_enable(host->vqmmc); |
| 2864 | else | 2871 | if (!regulator_is_supported_voltage(host->vqmmc, 1700000, |
| 2872 | 1950000)) | ||
| 2873 | caps[1] &= ~(SDHCI_SUPPORT_SDR104 | | ||
| 2874 | SDHCI_SUPPORT_SDR50 | | ||
| 2875 | SDHCI_SUPPORT_DDR50); | ||
| 2876 | } | ||
| 2877 | |||
| 2878 | if (host->quirks2 & SDHCI_QUIRK2_NO_1_8_V) | ||
| 2865 | caps[1] &= ~(SDHCI_SUPPORT_SDR104 | SDHCI_SUPPORT_SDR50 | | 2879 | caps[1] &= ~(SDHCI_SUPPORT_SDR104 | SDHCI_SUPPORT_SDR50 | |
| 2866 | SDHCI_SUPPORT_DDR50); | 2880 | SDHCI_SUPPORT_DDR50); |
| 2867 | 2881 | ||
| @@ -2919,21 +2933,18 @@ int sdhci_add_host(struct sdhci_host *host) | |||
| 2919 | mmc_hostname(mmc)); | 2933 | mmc_hostname(mmc)); |
| 2920 | host->vmmc = NULL; | 2934 | host->vmmc = NULL; |
| 2921 | } | 2935 | } |
| 2922 | } else | 2936 | } |
| 2923 | regulator_enable(host->vmmc); | ||
| 2924 | 2937 | ||
| 2925 | #ifdef CONFIG_REGULATOR | 2938 | #ifdef CONFIG_REGULATOR |
| 2926 | if (host->vmmc) { | 2939 | if (host->vmmc) { |
| 2927 | ret = regulator_is_supported_voltage(host->vmmc, 3300000, | 2940 | ret = regulator_is_supported_voltage(host->vmmc, 2700000, |
| 2928 | 3300000); | 2941 | 3600000); |
| 2929 | if ((ret <= 0) || (!(caps[0] & SDHCI_CAN_VDD_330))) | 2942 | if ((ret <= 0) || (!(caps[0] & SDHCI_CAN_VDD_330))) |
| 2930 | caps[0] &= ~SDHCI_CAN_VDD_330; | 2943 | caps[0] &= ~SDHCI_CAN_VDD_330; |
| 2931 | ret = regulator_is_supported_voltage(host->vmmc, 3000000, | ||
| 2932 | 3000000); | ||
| 2933 | if ((ret <= 0) || (!(caps[0] & SDHCI_CAN_VDD_300))) | 2944 | if ((ret <= 0) || (!(caps[0] & SDHCI_CAN_VDD_300))) |
| 2934 | caps[0] &= ~SDHCI_CAN_VDD_300; | 2945 | caps[0] &= ~SDHCI_CAN_VDD_300; |
| 2935 | ret = regulator_is_supported_voltage(host->vmmc, 1800000, | 2946 | ret = regulator_is_supported_voltage(host->vmmc, 1700000, |
| 2936 | 1800000); | 2947 | 1950000); |
| 2937 | if ((ret <= 0) || (!(caps[0] & SDHCI_CAN_VDD_180))) | 2948 | if ((ret <= 0) || (!(caps[0] & SDHCI_CAN_VDD_180))) |
| 2938 | caps[0] &= ~SDHCI_CAN_VDD_180; | 2949 | caps[0] &= ~SDHCI_CAN_VDD_180; |
| 2939 | } | 2950 | } |
