Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -92,6 +92,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.
+96 −0
Original line number Diff line number Diff line
@@ -31,6 +31,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"
@@ -451,6 +455,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,
@@ -715,6 +763,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;
	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;
}

#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 |
@@ -972,6 +1050,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 |
			  SDHCI_QUIRK_NO_LED,
	.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 = {
#ifdef CONFIG_PM_SLEEP
	.resume		= byt_resume,
#endif
#ifdef CONFIG_PM
	.runtime_resume	= byt_runtime_resume,
#endif
	.quirks		= SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC |
			  SDHCI_QUIRK_NO_LED,
	.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 = {
#ifdef CONFIG_PM_SLEEP
	.resume		= byt_resume,
#endif
#ifdef CONFIG_PM
	.runtime_resume	= byt_runtime_resume,
#endif
	.quirks		= SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC |
			  SDHCI_QUIRK_NO_LED,
	.quirks2	= SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON |