Merge tag 'lsk-v4.4-16.07-android'
[firefly-linux-kernel-4.4.55.git] / drivers / mmc / core / host.c
index da950c44204d27d6db8cd5a2d56b6b3e88e27c09..a346775929c8644d0b8e3745684df78cc5e78a1b 100644 (file)
@@ -289,6 +289,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 +386,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;
@@ -395,7 +405,11 @@ int mmc_add_host(struct mmc_host *host)
 #endif
 
        mmc_start_host(host);
-       register_pm_notifier(&host->pm_notify);
+       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;
 }
@@ -412,7 +426,9 @@ EXPORT_SYMBOL(mmc_add_host);
  */
 void mmc_remove_host(struct mmc_host *host)
 {
-       unregister_pm_notifier(&host->pm_notify);
+       if (!(host->pm_flags & MMC_PM_IGNORE_PM_NOTIFY))
+               unregister_pm_notifier(&host->pm_notify);
+
        mmc_stop_host(host);
 
 #ifdef CONFIG_DEBUG_FS
@@ -439,3 +455,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);