Commit 0a49a619 authored by Adrian Hunter's avatar Adrian Hunter Committed by Ulf Hansson

mmc: sdhci-pci: Fix BYT OCP setting

Some time ago, a fix was done for the sdhci-acpi driver, refer
commit 6e1c7d61 ("mmc: sdhci-acpi: Reduce Baytrail eMMC/SD/SDIO
hangs"). The same issue was not expected to affect the sdhci-pci driver,
but there have been reports to the contrary, so make the same hardware
setting change.

This patch applies to v5.0+ but before that backports will be required.
Signed-off-by: default avatarAdrian Hunter <adrian.hunter@intel.com>
Cc: stable@vger.kernel.org
Signed-off-by: default avatarUlf Hansson <ulf.hansson@linaro.org>
parent 34368217
...@@ -92,6 +92,7 @@ config MMC_SDHCI_PCI ...@@ -92,6 +92,7 @@ config MMC_SDHCI_PCI
tristate "SDHCI support on PCI bus" tristate "SDHCI support on PCI bus"
depends on MMC_SDHCI && PCI depends on MMC_SDHCI && PCI
select MMC_CQHCI select MMC_CQHCI
select IOSF_MBI if X86
help help
This selects the PCI Secure Digital Host Controller Interface. This selects the PCI Secure Digital Host Controller Interface.
Most controllers found today are PCI devices. Most controllers found today are PCI devices.
......
...@@ -31,6 +31,10 @@ ...@@ -31,6 +31,10 @@
#include <linux/mmc/sdhci-pci-data.h> #include <linux/mmc/sdhci-pci-data.h>
#include <linux/acpi.h> #include <linux/acpi.h>
#ifdef CONFIG_X86
#include <asm/iosf_mbi.h>
#endif
#include "cqhci.h" #include "cqhci.h"
#include "sdhci.h" #include "sdhci.h"
...@@ -451,6 +455,50 @@ static const struct sdhci_pci_fixes sdhci_intel_pch_sdio = { ...@@ -451,6 +455,50 @@ static const struct sdhci_pci_fixes sdhci_intel_pch_sdio = {
.probe_slot = pch_hc_probe_slot, .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 { enum {
INTEL_DSM_FNS = 0, INTEL_DSM_FNS = 0,
INTEL_DSM_V18_SWITCH = 3, INTEL_DSM_V18_SWITCH = 3,
...@@ -715,6 +763,8 @@ static void byt_probe_slot(struct sdhci_pci_slot *slot) ...@@ -715,6 +763,8 @@ static void byt_probe_slot(struct sdhci_pci_slot *slot)
byt_read_dsm(slot); byt_read_dsm(slot);
byt_ocp_setting(slot->chip->pdev);
ops->execute_tuning = intel_execute_tuning; ops->execute_tuning = intel_execute_tuning;
ops->start_signal_voltage_switch = intel_start_signal_voltage_switch; ops->start_signal_voltage_switch = intel_start_signal_voltage_switch;
...@@ -938,7 +988,35 @@ static int byt_sd_probe_slot(struct sdhci_pci_slot *slot) ...@@ -938,7 +988,35 @@ static int byt_sd_probe_slot(struct sdhci_pci_slot *slot)
return 0; 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 = { 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, .allow_runtime_pm = true,
.probe_slot = byt_emmc_probe_slot, .probe_slot = byt_emmc_probe_slot,
.quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC | .quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC |
...@@ -972,6 +1050,12 @@ static const struct sdhci_pci_fixes sdhci_intel_glk_emmc = { ...@@ -972,6 +1050,12 @@ static const struct sdhci_pci_fixes sdhci_intel_glk_emmc = {
}; };
static const struct sdhci_pci_fixes sdhci_ni_byt_sdio = { 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 | .quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC |
SDHCI_QUIRK_NO_LED, SDHCI_QUIRK_NO_LED,
.quirks2 = SDHCI_QUIRK2_HOST_OFF_CARD_ON | .quirks2 = SDHCI_QUIRK2_HOST_OFF_CARD_ON |
...@@ -983,6 +1067,12 @@ static const struct sdhci_pci_fixes sdhci_ni_byt_sdio = { ...@@ -983,6 +1067,12 @@ static const struct sdhci_pci_fixes sdhci_ni_byt_sdio = {
}; };
static const struct sdhci_pci_fixes sdhci_intel_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 | .quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC |
SDHCI_QUIRK_NO_LED, SDHCI_QUIRK_NO_LED,
.quirks2 = SDHCI_QUIRK2_HOST_OFF_CARD_ON | .quirks2 = SDHCI_QUIRK2_HOST_OFF_CARD_ON |
...@@ -994,6 +1084,12 @@ static const struct sdhci_pci_fixes sdhci_intel_byt_sdio = { ...@@ -994,6 +1084,12 @@ static const struct sdhci_pci_fixes sdhci_intel_byt_sdio = {
}; };
static const struct sdhci_pci_fixes sdhci_intel_byt_sd = { 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 | .quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC |
SDHCI_QUIRK_NO_LED, SDHCI_QUIRK_NO_LED,
.quirks2 = SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON | .quirks2 = SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON |
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment