Upgrade to 4.4.50-rt62
[kvmfornfv.git] / kernel / drivers / mmc / host / sdhci-acpi.c
index a5cda92..5a05bf4 100644 (file)
 #include <linux/mmc/pm.h>
 #include <linux/mmc/slot-gpio.h>
 
+#ifdef CONFIG_X86
+#include <asm/cpu_device_id.h>
+#include <asm/iosf_mbi.h>
+#endif
+
 #include "sdhci.h"
 
 enum {
@@ -146,6 +151,75 @@ static const struct sdhci_acpi_chip sdhci_acpi_chip_int = {
        .ops = &sdhci_acpi_ops_int,
 };
 
+#ifdef CONFIG_X86
+
+static bool sdhci_acpi_byt(void)
+{
+       static const struct x86_cpu_id byt[] = {
+               { X86_VENDOR_INTEL, 6, 0x37 },
+               {}
+       };
+
+       return x86_match_cpu(byt);
+}
+
+#define BYT_IOSF_SCCEP                 0x63
+#define BYT_IOSF_OCP_NETCTRL0          0x1078
+#define BYT_IOSF_OCP_TIMEOUT_BASE      GENMASK(10, 8)
+
+static void sdhci_acpi_byt_setting(struct device *dev)
+{
+       u32 val = 0;
+
+       if (!sdhci_acpi_byt())
+               return;
+
+       if (iosf_mbi_read(BYT_IOSF_SCCEP, 0x06, BYT_IOSF_OCP_NETCTRL0,
+                         &val)) {
+               dev_err(dev, "%s read error\n", __func__);
+               return;
+       }
+
+       if (!(val & BYT_IOSF_OCP_TIMEOUT_BASE))
+               return;
+
+       val &= ~BYT_IOSF_OCP_TIMEOUT_BASE;
+
+       if (iosf_mbi_write(BYT_IOSF_SCCEP, 0x07, BYT_IOSF_OCP_NETCTRL0,
+                          val)) {
+               dev_err(dev, "%s write error\n", __func__);
+               return;
+       }
+
+       dev_dbg(dev, "%s completed\n", __func__);
+}
+
+static bool sdhci_acpi_byt_defer(struct device *dev)
+{
+       if (!sdhci_acpi_byt())
+               return false;
+
+       if (!iosf_mbi_available())
+               return true;
+
+       sdhci_acpi_byt_setting(dev);
+
+       return false;
+}
+
+#else
+
+static inline void sdhci_acpi_byt_setting(struct device *dev)
+{
+}
+
+static inline bool sdhci_acpi_byt_defer(struct device *dev)
+{
+       return false;
+}
+
+#endif
+
 static int bxt_get_cd(struct mmc_host *mmc)
 {
        int gpio_cd = mmc_gpio_get_cd(mmc);
@@ -233,7 +307,7 @@ static const struct sdhci_acpi_slot sdhci_acpi_slot_int_emmc = {
        .chip    = &sdhci_acpi_chip_int,
        .caps    = MMC_CAP_8_BIT_DATA | MMC_CAP_NONREMOVABLE |
                   MMC_CAP_HW_RESET | MMC_CAP_1_8V_DDR |
-                  MMC_CAP_BUS_WIDTH_TEST | MMC_CAP_WAIT_WHILE_BUSY,
+                  MMC_CAP_WAIT_WHILE_BUSY,
        .caps2   = MMC_CAP2_HC_ERASE_SZ,
        .flags   = SDHCI_ACPI_RUNTIME_PM,
        .quirks  = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC,
@@ -248,7 +322,7 @@ static const struct sdhci_acpi_slot sdhci_acpi_slot_int_sdio = {
                   SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC,
        .quirks2 = SDHCI_QUIRK2_HOST_OFF_CARD_ON,
        .caps    = MMC_CAP_NONREMOVABLE | MMC_CAP_POWER_OFF_CARD |
-                  MMC_CAP_BUS_WIDTH_TEST | MMC_CAP_WAIT_WHILE_BUSY,
+                  MMC_CAP_WAIT_WHILE_BUSY,
        .flags   = SDHCI_ACPI_RUNTIME_PM,
        .pm_caps = MMC_PM_KEEP_POWER,
        .probe_slot     = sdhci_acpi_sdio_probe_slot,
@@ -260,7 +334,7 @@ static const struct sdhci_acpi_slot sdhci_acpi_slot_int_sd = {
        .quirks  = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC,
        .quirks2 = SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON |
                   SDHCI_QUIRK2_STOP_WITH_TC,
-       .caps    = MMC_CAP_BUS_WIDTH_TEST | MMC_CAP_WAIT_WHILE_BUSY,
+       .caps    = MMC_CAP_WAIT_WHILE_BUSY,
        .probe_slot     = sdhci_acpi_sd_probe_slot,
 };
 
@@ -337,6 +411,9 @@ static int sdhci_acpi_probe(struct platform_device *pdev)
        if (acpi_bus_get_status(device) || !device->status.present)
                return -ENODEV;
 
+       if (sdhci_acpi_byt_defer(dev))
+               return -EPROBE_DEFER;
+
        hid = acpi_device_hid(device);
        uid = device->pnp.unique_id;
 
@@ -460,6 +537,8 @@ static int sdhci_acpi_resume(struct device *dev)
 {
        struct sdhci_acpi_host *c = dev_get_drvdata(dev);
 
+       sdhci_acpi_byt_setting(&c->pdev->dev);
+
        return sdhci_resume_host(c->host);
 }
 
@@ -483,6 +562,8 @@ static int sdhci_acpi_runtime_resume(struct device *dev)
 {
        struct sdhci_acpi_host *c = dev_get_drvdata(dev);
 
+       sdhci_acpi_byt_setting(&c->pdev->dev);
+
        return sdhci_runtime_resume_host(c->host);
 }