diff options
Diffstat (limited to 'drivers/mmc/core/core.c')
-rw-r--r-- | drivers/mmc/core/core.c | 94 |
1 files changed, 89 insertions, 5 deletions
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 75db30e6dcf..46086342289 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/log2.h> | 23 | #include <linux/log2.h> |
24 | #include <linux/regulator/consumer.h> | 24 | #include <linux/regulator/consumer.h> |
25 | #include <linux/pm_runtime.h> | 25 | #include <linux/pm_runtime.h> |
26 | #include <linux/wakelock.h> | ||
26 | 27 | ||
27 | #include <linux/mmc/card.h> | 28 | #include <linux/mmc/card.h> |
28 | #include <linux/mmc/host.h> | 29 | #include <linux/mmc/host.h> |
@@ -1121,6 +1122,36 @@ static inline void mmc_bus_put(struct mmc_host *host) | |||
1121 | spin_unlock_irqrestore(&host->lock, flags); | 1122 | spin_unlock_irqrestore(&host->lock, flags); |
1122 | } | 1123 | } |
1123 | 1124 | ||
1125 | int mmc_resume_bus(struct mmc_host *host) | ||
1126 | { | ||
1127 | unsigned long flags; | ||
1128 | |||
1129 | if (!mmc_bus_needs_resume(host)) | ||
1130 | return -EINVAL; | ||
1131 | |||
1132 | printk("%s: Starting deferred resume\n", mmc_hostname(host)); | ||
1133 | spin_lock_irqsave(&host->lock, flags); | ||
1134 | host->bus_resume_flags &= ~MMC_BUSRESUME_NEEDS_RESUME; | ||
1135 | host->rescan_disable = 0; | ||
1136 | spin_unlock_irqrestore(&host->lock, flags); | ||
1137 | |||
1138 | mmc_bus_get(host); | ||
1139 | if (host->bus_ops && !host->bus_dead) { | ||
1140 | mmc_power_up(host); | ||
1141 | BUG_ON(!host->bus_ops->resume); | ||
1142 | host->bus_ops->resume(host); | ||
1143 | } | ||
1144 | |||
1145 | if (host->bus_ops->detect && !host->bus_dead) | ||
1146 | host->bus_ops->detect(host); | ||
1147 | |||
1148 | mmc_bus_put(host); | ||
1149 | printk("%s: Deferred resume completed\n", mmc_hostname(host)); | ||
1150 | return 0; | ||
1151 | } | ||
1152 | |||
1153 | EXPORT_SYMBOL(mmc_resume_bus); | ||
1154 | |||
1124 | /* | 1155 | /* |
1125 | * Assign a mmc bus handler to a host. Only one bus handler may control a | 1156 | * Assign a mmc bus handler to a host. Only one bus handler may control a |
1126 | * host at any given time. | 1157 | * host at any given time. |
@@ -1186,6 +1217,7 @@ void mmc_detect_change(struct mmc_host *host, unsigned long delay) | |||
1186 | spin_unlock_irqrestore(&host->lock, flags); | 1217 | spin_unlock_irqrestore(&host->lock, flags); |
1187 | #endif | 1218 | #endif |
1188 | 1219 | ||
1220 | wake_lock(&host->detect_wake_lock); | ||
1189 | mmc_schedule_delayed_work(&host->detect, delay); | 1221 | mmc_schedule_delayed_work(&host->detect, delay); |
1190 | } | 1222 | } |
1191 | 1223 | ||
@@ -1592,6 +1624,7 @@ void mmc_rescan(struct work_struct *work) | |||
1592 | struct mmc_host *host = | 1624 | struct mmc_host *host = |
1593 | container_of(work, struct mmc_host, detect.work); | 1625 | container_of(work, struct mmc_host, detect.work); |
1594 | int i; | 1626 | int i; |
1627 | bool extend_wakelock = false; | ||
1595 | 1628 | ||
1596 | if (host->rescan_disable) | 1629 | if (host->rescan_disable) |
1597 | return; | 1630 | return; |
@@ -1606,6 +1639,12 @@ void mmc_rescan(struct work_struct *work) | |||
1606 | && !(host->caps & MMC_CAP_NONREMOVABLE)) | 1639 | && !(host->caps & MMC_CAP_NONREMOVABLE)) |
1607 | host->bus_ops->detect(host); | 1640 | host->bus_ops->detect(host); |
1608 | 1641 | ||
1642 | /* If the card was removed the bus will be marked | ||
1643 | * as dead - extend the wakelock so userspace | ||
1644 | * can respond */ | ||
1645 | if (host->bus_dead) | ||
1646 | extend_wakelock = 1; | ||
1647 | |||
1609 | /* | 1648 | /* |
1610 | * Let mmc_bus_put() free the bus/bus_ops if we've found that | 1649 | * Let mmc_bus_put() free the bus/bus_ops if we've found that |
1611 | * the card is no longer present. | 1650 | * the card is no longer present. |
@@ -1630,16 +1669,24 @@ void mmc_rescan(struct work_struct *work) | |||
1630 | 1669 | ||
1631 | mmc_claim_host(host); | 1670 | mmc_claim_host(host); |
1632 | for (i = 0; i < ARRAY_SIZE(freqs); i++) { | 1671 | for (i = 0; i < ARRAY_SIZE(freqs); i++) { |
1633 | if (!mmc_rescan_try_freq(host, max(freqs[i], host->f_min))) | 1672 | if (!mmc_rescan_try_freq(host, max(freqs[i], host->f_min))) { |
1673 | extend_wakelock = true; | ||
1634 | break; | 1674 | break; |
1675 | } | ||
1635 | if (freqs[i] <= host->f_min) | 1676 | if (freqs[i] <= host->f_min) |
1636 | break; | 1677 | break; |
1637 | } | 1678 | } |
1638 | mmc_release_host(host); | 1679 | mmc_release_host(host); |
1639 | 1680 | ||
1640 | out: | 1681 | out: |
1641 | if (host->caps & MMC_CAP_NEEDS_POLL) | 1682 | if (extend_wakelock) |
1683 | wake_lock_timeout(&host->detect_wake_lock, HZ / 2); | ||
1684 | else | ||
1685 | wake_unlock(&host->detect_wake_lock); | ||
1686 | if (host->caps & MMC_CAP_NEEDS_POLL) { | ||
1687 | wake_lock(&host->detect_wake_lock); | ||
1642 | mmc_schedule_delayed_work(&host->detect, HZ); | 1688 | mmc_schedule_delayed_work(&host->detect, HZ); |
1689 | } | ||
1643 | } | 1690 | } |
1644 | 1691 | ||
1645 | void mmc_start_host(struct mmc_host *host) | 1692 | void mmc_start_host(struct mmc_host *host) |
@@ -1659,7 +1706,8 @@ void mmc_stop_host(struct mmc_host *host) | |||
1659 | 1706 | ||
1660 | if (host->caps & MMC_CAP_DISABLE) | 1707 | if (host->caps & MMC_CAP_DISABLE) |
1661 | cancel_delayed_work(&host->disable); | 1708 | cancel_delayed_work(&host->disable); |
1662 | cancel_delayed_work_sync(&host->detect); | 1709 | if (cancel_delayed_work_sync(&host->detect)) |
1710 | wake_unlock(&host->detect_wake_lock); | ||
1663 | mmc_flush_scheduled_work(); | 1711 | mmc_flush_scheduled_work(); |
1664 | 1712 | ||
1665 | /* clear pm flags now and let card drivers set them as needed */ | 1713 | /* clear pm flags now and let card drivers set them as needed */ |
@@ -1776,9 +1824,13 @@ int mmc_suspend_host(struct mmc_host *host) | |||
1776 | { | 1824 | { |
1777 | int err = 0; | 1825 | int err = 0; |
1778 | 1826 | ||
1827 | if (mmc_bus_needs_resume(host)) | ||
1828 | return 0; | ||
1829 | |||
1779 | if (host->caps & MMC_CAP_DISABLE) | 1830 | if (host->caps & MMC_CAP_DISABLE) |
1780 | cancel_delayed_work(&host->disable); | 1831 | cancel_delayed_work(&host->disable); |
1781 | cancel_delayed_work(&host->detect); | 1832 | if (cancel_delayed_work(&host->detect)) |
1833 | wake_unlock(&host->detect_wake_lock); | ||
1782 | mmc_flush_scheduled_work(); | 1834 | mmc_flush_scheduled_work(); |
1783 | 1835 | ||
1784 | mmc_bus_get(host); | 1836 | mmc_bus_get(host); |
@@ -1799,6 +1851,7 @@ int mmc_suspend_host(struct mmc_host *host) | |||
1799 | host->pm_flags = 0; | 1851 | host->pm_flags = 0; |
1800 | err = 0; | 1852 | err = 0; |
1801 | } | 1853 | } |
1854 | flush_delayed_work(&host->disable); | ||
1802 | } | 1855 | } |
1803 | mmc_bus_put(host); | 1856 | mmc_bus_put(host); |
1804 | 1857 | ||
@@ -1819,6 +1872,12 @@ int mmc_resume_host(struct mmc_host *host) | |||
1819 | int err = 0; | 1872 | int err = 0; |
1820 | 1873 | ||
1821 | mmc_bus_get(host); | 1874 | mmc_bus_get(host); |
1875 | if (mmc_bus_manual_resume(host)) { | ||
1876 | host->bus_resume_flags |= MMC_BUSRESUME_NEEDS_RESUME; | ||
1877 | mmc_bus_put(host); | ||
1878 | return 0; | ||
1879 | } | ||
1880 | |||
1822 | if (host->bus_ops && !host->bus_dead) { | 1881 | if (host->bus_ops && !host->bus_dead) { |
1823 | if (!mmc_card_keep_power(host)) { | 1882 | if (!mmc_card_keep_power(host)) { |
1824 | mmc_power_up(host); | 1883 | mmc_power_up(host); |
@@ -1869,9 +1928,14 @@ int mmc_pm_notify(struct notifier_block *notify_block, | |||
1869 | case PM_SUSPEND_PREPARE: | 1928 | case PM_SUSPEND_PREPARE: |
1870 | 1929 | ||
1871 | spin_lock_irqsave(&host->lock, flags); | 1930 | spin_lock_irqsave(&host->lock, flags); |
1931 | if (mmc_bus_needs_resume(host)) { | ||
1932 | spin_unlock_irqrestore(&host->lock, flags); | ||
1933 | break; | ||
1934 | } | ||
1872 | host->rescan_disable = 1; | 1935 | host->rescan_disable = 1; |
1873 | spin_unlock_irqrestore(&host->lock, flags); | 1936 | spin_unlock_irqrestore(&host->lock, flags); |
1874 | cancel_delayed_work_sync(&host->detect); | 1937 | if (cancel_delayed_work_sync(&host->detect)) |
1938 | wake_unlock(&host->detect_wake_lock); | ||
1875 | 1939 | ||
1876 | if (!host->bus_ops || host->bus_ops->suspend) | 1940 | if (!host->bus_ops || host->bus_ops->suspend) |
1877 | break; | 1941 | break; |
@@ -1892,6 +1956,10 @@ int mmc_pm_notify(struct notifier_block *notify_block, | |||
1892 | case PM_POST_RESTORE: | 1956 | case PM_POST_RESTORE: |
1893 | 1957 | ||
1894 | spin_lock_irqsave(&host->lock, flags); | 1958 | spin_lock_irqsave(&host->lock, flags); |
1959 | if (mmc_bus_manual_resume(host)) { | ||
1960 | spin_unlock_irqrestore(&host->lock, flags); | ||
1961 | break; | ||
1962 | } | ||
1895 | host->rescan_disable = 0; | 1963 | host->rescan_disable = 0; |
1896 | spin_unlock_irqrestore(&host->lock, flags); | 1964 | spin_unlock_irqrestore(&host->lock, flags); |
1897 | mmc_detect_change(host, 0); | 1965 | mmc_detect_change(host, 0); |
@@ -1902,6 +1970,22 @@ int mmc_pm_notify(struct notifier_block *notify_block, | |||
1902 | } | 1970 | } |
1903 | #endif | 1971 | #endif |
1904 | 1972 | ||
1973 | #ifdef CONFIG_MMC_EMBEDDED_SDIO | ||
1974 | void mmc_set_embedded_sdio_data(struct mmc_host *host, | ||
1975 | struct sdio_cis *cis, | ||
1976 | struct sdio_cccr *cccr, | ||
1977 | struct sdio_embedded_func *funcs, | ||
1978 | int num_funcs) | ||
1979 | { | ||
1980 | host->embedded_sdio_data.cis = cis; | ||
1981 | host->embedded_sdio_data.cccr = cccr; | ||
1982 | host->embedded_sdio_data.funcs = funcs; | ||
1983 | host->embedded_sdio_data.num_funcs = num_funcs; | ||
1984 | } | ||
1985 | |||
1986 | EXPORT_SYMBOL(mmc_set_embedded_sdio_data); | ||
1987 | #endif | ||
1988 | |||
1905 | static int __init mmc_init(void) | 1989 | static int __init mmc_init(void) |
1906 | { | 1990 | { |
1907 | int ret; | 1991 | int ret; |