diff options
Diffstat (limited to 'drivers/mmc/core/host.c')
-rw-r--r-- | drivers/mmc/core/host.c | 50 |
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 |