summaryrefslogtreecommitdiff
path: root/drivers/mmc/core/host.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mmc/core/host.c')
-rw-r--r--drivers/mmc/core/host.c50
1 files changed, 31 insertions, 19 deletions
diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c
index 848b3453517e..aa4afba7ab1e 100644
--- a/drivers/mmc/core/host.c
+++ b/drivers/mmc/core/host.c
@@ -30,18 +30,16 @@
#include "host.h"
#include "slot-gpio.h"
#include "pwrseq.h"
+#include "sdio_ops.h"
#define cls_dev_to_mmc_host(d) container_of(d, struct mmc_host, class_dev)
static DEFINE_IDA(mmc_host_ida);
-static DEFINE_SPINLOCK(mmc_host_lock);
static void mmc_host_classdev_release(struct device *dev)
{
struct mmc_host *host = cls_dev_to_mmc_host(dev);
- spin_lock(&mmc_host_lock);
- ida_remove(&mmc_host_ida, host->index);
- spin_unlock(&mmc_host_lock);
+ ida_simple_remove(&mmc_host_ida, host->index);
kfree(host);
}
@@ -113,6 +111,12 @@ void mmc_retune_hold(struct mmc_host *host)
host->hold_retune += 1;
}
+void mmc_retune_hold_now(struct mmc_host *host)
+{
+ host->retune_now = 0;
+ host->hold_retune += 1;
+}
+
void mmc_retune_release(struct mmc_host *host)
{
if (host->hold_retune)
@@ -228,6 +232,8 @@ int mmc_of_parse(struct mmc_host *host)
/* Parse Card Detection */
if (device_property_read_bool(dev, "non-removable")) {
host->caps |= MMC_CAP_NONREMOVABLE;
+ if (device_property_read_bool(dev, "cd-post"))
+ host->caps2 |= MMC_CAP2_CD_POST;
} else {
cd_cap_invert = device_property_read_bool(dev, "cd-inverted");
@@ -299,6 +305,10 @@ int mmc_of_parse(struct mmc_host *host)
if (device_property_read_bool(dev, "wakeup-source") ||
device_property_read_bool(dev, "enable-sdio-wakeup")) /* legacy */
host->pm_caps |= MMC_PM_WAKE_SDIO_IRQ;
+ if (device_property_read_bool(dev, "pm-ignore-notify"))
+ host->pm_caps |= MMC_PM_IGNORE_PM_NOTIFY;
+ if (device_property_read_bool(dev, "mmc-ddr-3_3v"))
+ host->caps |= MMC_CAP_3_3V_DDR;
if (device_property_read_bool(dev, "mmc-ddr-1_8v"))
host->caps |= MMC_CAP_1_8V_DDR;
if (device_property_read_bool(dev, "mmc-ddr-1_2v"))
@@ -343,6 +353,7 @@ EXPORT_SYMBOL(mmc_of_parse);
struct mmc_host *mmc_alloc_host(int extra, struct device *dev)
{
int err;
+ int alias_id;
struct mmc_host *host;
host = kzalloc(sizeof(struct mmc_host) + extra, GFP_KERNEL);
@@ -351,27 +362,25 @@ struct mmc_host *mmc_alloc_host(int extra, struct device *dev)
/* scanning will be enabled when we're ready */
host->rescan_disable = 1;
+ host->parent = dev;
-again:
- if (!ida_pre_get(&mmc_host_ida, GFP_KERNEL)) {
+ alias_id = mmc_get_reserved_index(host);
+ if (alias_id >= 0)
+ err = ida_simple_get(&mmc_host_ida, alias_id,
+ alias_id + 1, GFP_KERNEL);
+ else
+ err = ida_simple_get(&mmc_host_ida,
+ mmc_first_nonreserved_index(),
+ 0, GFP_KERNEL);
+ if (err < 0) {
kfree(host);
return NULL;
}
- spin_lock(&mmc_host_lock);
- err = ida_get_new(&mmc_host_ida, &host->index);
- spin_unlock(&mmc_host_lock);
-
- if (err == -EAGAIN) {
- goto again;
- } else if (err) {
- kfree(host);
- return NULL;
- }
+ host->index = err;
dev_set_name(&host->class_dev, "mmc%d", host->index);
- host->parent = dev;
host->class_dev.parent = dev;
host->class_dev.class = &mmc_host_class;
device_initialize(&host->class_dev);
@@ -385,6 +394,7 @@ again:
spin_lock_init(&host->lock);
init_waitqueue_head(&host->wq);
INIT_DELAYED_WORK(&host->detect, mmc_rescan);
+ INIT_DELAYED_WORK(&host->sdio_irq_work, sdio_irq_work);
setup_timer(&host->retune_timer, mmc_retune_timer, (unsigned long)host);
/*
@@ -429,7 +439,8 @@ int mmc_add_host(struct mmc_host *host)
#endif
mmc_start_host(host);
- mmc_register_pm_notifier(host);
+ if (!(host->pm_caps& MMC_PM_IGNORE_PM_NOTIFY))
+ mmc_register_pm_notifier(host);
return 0;
}
@@ -446,7 +457,8 @@ EXPORT_SYMBOL(mmc_add_host);
*/
void mmc_remove_host(struct mmc_host *host)
{
- mmc_unregister_pm_notifier(host);
+ if (!(host->pm_caps& MMC_PM_IGNORE_PM_NOTIFY))
+ mmc_unregister_pm_notifier(host);
mmc_stop_host(host);
#ifdef CONFIG_DEBUG_FS