Home Home > GIT Browse
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2019-08-12 17:52:55 +0200
committerTakashi Iwai <tiwai@suse.de>2019-08-12 17:52:55 +0200
commit7d122eb0b769a1ed4069e14aad19ce8c032418d5 (patch)
tree440b02621615e9464b2018f7955cb95549a61824
parent0a671c1e4331a9d891a6bca70de2e781e26ce6b0 (diff)
mmc: sdhci-pci: Fix BYT OCP setting (bsc#1051510).
-rw-r--r--drivers/mmc/host/Kconfig1
-rw-r--r--drivers/mmc/host/sdhci-pci-core.c96
2 files changed, 97 insertions, 0 deletions
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
index 0318c1355290..8c889ca93deb 100644
--- a/drivers/mmc/host/Kconfig
+++ b/drivers/mmc/host/Kconfig
@@ -73,6 +73,7 @@ config MMC_SDHCI_PCI
tristate "SDHCI support on PCI bus"
depends on MMC_SDHCI && PCI
select MMC_CQHCI
+ select IOSF_MBI if X86
help
This selects the PCI Secure Digital Host Controller Interface.
Most controllers found today are PCI devices.
diff --git a/drivers/mmc/host/sdhci-pci-core.c b/drivers/mmc/host/sdhci-pci-core.c
index 84ff70b91fed..651b2a6166a6 100644
--- a/drivers/mmc/host/sdhci-pci-core.c
+++ b/drivers/mmc/host/sdhci-pci-core.c
@@ -30,6 +30,10 @@
#include <linux/mmc/sdhci-pci-data.h>
#include <linux/acpi.h>
+#ifdef CONFIG_X86
+#include <asm/iosf_mbi.h>
+#endif
+
#include "cqhci.h"
#include "sdhci.h"
@@ -456,6 +460,50 @@ static const struct sdhci_pci_fixes sdhci_intel_pch_sdio = {
.probe_slot = pch_hc_probe_slot,
};
+#ifdef CONFIG_X86
+
+#define BYT_IOSF_SCCEP 0x63
+#define BYT_IOSF_OCP_NETCTRL0 0x1078
+#define BYT_IOSF_OCP_TIMEOUT_BASE GENMASK(10, 8)
+
+static void byt_ocp_setting(struct pci_dev *pdev)
+{
+ u32 val = 0;
+
+ if (pdev->device != PCI_DEVICE_ID_INTEL_BYT_EMMC &&
+ pdev->device != PCI_DEVICE_ID_INTEL_BYT_SDIO &&
+ pdev->device != PCI_DEVICE_ID_INTEL_BYT_SD &&
+ pdev->device != PCI_DEVICE_ID_INTEL_BYT_EMMC2)
+ return;
+
+ if (iosf_mbi_read(BYT_IOSF_SCCEP, MBI_CR_READ, BYT_IOSF_OCP_NETCTRL0,
+ &val)) {
+ dev_err(&pdev->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, MBI_CR_WRITE, BYT_IOSF_OCP_NETCTRL0,
+ val)) {
+ dev_err(&pdev->dev, "%s write error\n", __func__);
+ return;
+ }
+
+ dev_dbg(&pdev->dev, "%s completed\n", __func__);
+}
+
+#else
+
+static inline void byt_ocp_setting(struct pci_dev *pdev)
+{
+}
+
+#endif
+
enum {
INTEL_DSM_FNS = 0,
INTEL_DSM_V18_SWITCH = 3,
@@ -696,6 +744,8 @@ static void byt_probe_slot(struct sdhci_pci_slot *slot)
byt_read_dsm(slot);
+ byt_ocp_setting(slot->chip->pdev);
+
ops->execute_tuning = intel_execute_tuning;
}
@@ -860,7 +910,35 @@ static int byt_sd_probe_slot(struct sdhci_pci_slot *slot)
return 0;
}
+#ifdef CONFIG_PM_SLEEP
+
+static int byt_resume(struct sdhci_pci_chip *chip)
+{
+ byt_ocp_setting(chip->pdev);
+
+ return sdhci_pci_resume_host(chip);
+}
+
+#endif
+
+#ifdef CONFIG_PM
+
+static int byt_runtime_resume(struct sdhci_pci_chip *chip)
+{
+ byt_ocp_setting(chip->pdev);
+
+ return sdhci_pci_runtime_resume_host(chip);
+}
+
+#endif
+
static const struct sdhci_pci_fixes sdhci_intel_byt_emmc = {
+#ifdef CONFIG_PM_SLEEP
+ .resume = byt_resume,
+#endif
+#ifdef CONFIG_PM
+ .runtime_resume = byt_runtime_resume,
+#endif
.allow_runtime_pm = true,
.probe_slot = byt_emmc_probe_slot,
.quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC,
@@ -892,6 +970,12 @@ static const struct sdhci_pci_fixes sdhci_intel_glk_emmc = {
};
static const struct sdhci_pci_fixes sdhci_ni_byt_sdio = {
+#ifdef CONFIG_PM_SLEEP
+ .resume = byt_resume,
+#endif
+#ifdef CONFIG_PM
+ .runtime_resume = byt_runtime_resume,
+#endif
.quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC,
.quirks2 = SDHCI_QUIRK2_HOST_OFF_CARD_ON |
SDHCI_QUIRK2_PRESET_VALUE_BROKEN,
@@ -902,6 +986,12 @@ static const struct sdhci_pci_fixes sdhci_ni_byt_sdio = {
};
static const struct sdhci_pci_fixes sdhci_intel_byt_sdio = {
+#ifdef CONFIG_PM_SLEEP
+ .resume = byt_resume,
+#endif
+#ifdef CONFIG_PM
+ .runtime_resume = byt_runtime_resume,
+#endif
.quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC,
.quirks2 = SDHCI_QUIRK2_HOST_OFF_CARD_ON |
SDHCI_QUIRK2_PRESET_VALUE_BROKEN,
@@ -912,6 +1002,12 @@ static const struct sdhci_pci_fixes sdhci_intel_byt_sdio = {
};
static const struct sdhci_pci_fixes sdhci_intel_byt_sd = {
+#ifdef CONFIG_PM_SLEEP
+ .resume = byt_resume,
+#endif
+#ifdef CONFIG_PM
+ .runtime_resume = byt_runtime_resume,
+#endif
.quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC,
.quirks2 = SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON |
SDHCI_QUIRK2_PRESET_VALUE_BROKEN |