mmc: sdhci-pci: Fix BYT OCP setting
Some time ago, a fix was done for the sdhci-acpi driver, refer
commit 6e1c7d6103
("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: Adrian Hunter <adrian.hunter@intel.com>
Cc: stable@vger.kernel.org
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
This commit is contained in:
parent
3436821738
commit
0a49a619e7
|
@ -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 @@
|
||||||
#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 = {
|
||||||
.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)
|
||||||
|
|
||||||
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)
|
||||||
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 = {
|
||||||
};
|
};
|
||||||
|
|
||||||
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 = {
|
||||||
};
|
};
|
||||||
|
|
||||||
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 = {
|
||||||
};
|
};
|
||||||
|
|
||||||
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 |
|
||||||
|
|
Loading…
Reference in New Issue