X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=drivers%2Fmmc%2Fcore%2Fhost.c;h=0268217e447faf6c63295592a5cb06414572df7e;hb=2ae05321496aa27767bc33a5cc19451b3db67919;hp=fcf7829c759e200baa7ef5f9cd456c18dd83ac48;hpb=334ca3ed18ded942e0220719f70b80eb20fa48ec;p=firefly-linux-kernel-4.4.55.git diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c index fcf7829c759e..0268217e447f 100644 --- a/drivers/mmc/core/host.c +++ b/drivers/mmc/core/host.c @@ -32,8 +32,6 @@ #include "slot-gpio.h" #include "pwrseq.h" -#define cls_dev_to_mmc_host(d) container_of(d, struct mmc_host, class_dev) - static DEFINE_IDR(mmc_host_idr); static DEFINE_SPINLOCK(mmc_host_lock); @@ -161,12 +159,23 @@ int mmc_of_parse(struct mmc_host *host) int ret; bool cd_cap_invert, cd_gpio_invert = false; bool ro_cap_invert, ro_gpio_invert = false; + enum of_gpio_flags pwrseq_flags; + int pwrseq_gpio; if (!host->parent || !host->parent->of_node) return 0; np = host->parent->of_node; + pwrseq_gpio = of_get_named_gpio_flags(np, "pwrseq-gpio", 0, &pwrseq_flags); + if ( gpio_is_valid(pwrseq_gpio) ) { + ret = devm_gpio_request_one(&host->class_dev, pwrseq_gpio, (pwrseq_flags & OF_GPIO_ACTIVE_LOW) ? GPIOF_OUT_INIT_LOW : GPIOF_OUT_INIT_HIGH, "sdpwr-gpio"); + if (ret != 0) { + dev_err(&host->class_dev, "request sdcard pwrseq gpio error\n"); + return -EIO; + } + }; + /* "bus-width" is translated to MMC_CAP_*_BIT_DATA flags */ if (of_property_read_u32(np, "bus-width", &bus_width) < 0) { dev_dbg(host->parent, @@ -289,6 +298,15 @@ int mmc_of_parse(struct mmc_host *host) host->caps2 |= MMC_CAP2_HS400_1_8V | MMC_CAP2_HS200_1_8V_SDR; if (of_property_read_bool(np, "mmc-hs400-1_2v")) host->caps2 |= MMC_CAP2_HS400_1_2V | MMC_CAP2_HS200_1_2V_SDR; + if (of_property_read_bool(np, "mmc-hs400-enhanced-strobe")) + host->caps2 |= MMC_CAP2_HS400_ES; + + if (of_property_read_bool(np, "supports-sd")) + host->restrict_caps |= RESTRICT_CARD_TYPE_SD; + if (of_property_read_bool(np, "supports-sdio")) + host->restrict_caps |= RESTRICT_CARD_TYPE_SDIO; + if (of_property_read_bool(np, "supports-emmc")) + host->restrict_caps |= RESTRICT_CARD_TYPE_EMMC; host->dsr_req = !of_property_read_u32(np, "dsr", &host->dsr); if (host->dsr_req && (host->dsr & ~0xffff)) { @@ -377,6 +395,7 @@ EXPORT_SYMBOL(mmc_alloc_host); * prepared to start servicing requests before this function * completes. */ +struct mmc_host *primary_sdio_host; int mmc_add_host(struct mmc_host *host) { int err; @@ -394,10 +413,17 @@ int mmc_add_host(struct mmc_host *host) mmc_add_host_debugfs(host); #endif +#ifdef CONFIG_BLOCK + mmc_latency_hist_sysfs_init(host); +#endif + mmc_start_host(host); if (!(host->pm_flags & MMC_PM_IGNORE_PM_NOTIFY)) register_pm_notifier(&host->pm_notify); + if (host->restrict_caps & RESTRICT_CARD_TYPE_SDIO) + primary_sdio_host = host; + return 0; } @@ -422,6 +448,10 @@ void mmc_remove_host(struct mmc_host *host) mmc_remove_host_debugfs(host); #endif +#ifdef CONFIG_BLOCK + mmc_latency_hist_sysfs_exit(host); +#endif + device_del(&host->class_dev); led_trigger_unregister_simple(host->led); @@ -442,3 +472,45 @@ void mmc_free_host(struct mmc_host *host) } EXPORT_SYMBOL(mmc_free_host); + +/** + * mmc_host_rescan - triger software rescan flow + * @host: mmc host + * + * rescan slot attach in the assigned host. + * If @host is NULL, default rescan primary_sdio_host + * saved by mmc_add_host(). + * OR, rescan host from argument. + * + */ +int mmc_host_rescan(struct mmc_host *host, int val, int is_cap_sdio_irq) +{ + if (NULL != primary_sdio_host) { + if (!host) + host = primary_sdio_host; + else + pr_info("%s: mmc_host_rescan pass in host from argument!\n", + mmc_hostname(host)); + } else { + pr_err("sdio: host isn't initialization successfully.\n"); + return -ENOMEDIUM; + } + + pr_info("%s:mmc host rescan start!\n", mmc_hostname(host)); + + /* 0: oob 1:cap-sdio-irq */ + if (is_cap_sdio_irq == 1) { + host->caps |= MMC_CAP_SDIO_IRQ; + } else if (is_cap_sdio_irq == 0) { + host->caps &= ~MMC_CAP_SDIO_IRQ; + } else { + dev_err(&host->class_dev, "sdio: host doesn't identify oob or sdio_irq mode!\n"); + return -ENOMEDIUM; + } + + if (!(host->caps & MMC_CAP_NONREMOVABLE) && host->ops->set_sdio_status) + host->ops->set_sdio_status(host, val); + + return 0; +} +EXPORT_SYMBOL(mmc_host_rescan);