diff options
Diffstat (limited to 'drivers/mmc/host/sdhci-pci-core.c')
| -rw-r--r-- | drivers/mmc/host/sdhci-pci-core.c | 98 | 
1 files changed, 98 insertions, 0 deletions
diff --git a/drivers/mmc/host/sdhci-pci-core.c b/drivers/mmc/host/sdhci-pci-core.c index 99b0fec2836b..ab9e2b901094 100644 --- a/drivers/mmc/host/sdhci-pci-core.c +++ b/drivers/mmc/host/sdhci-pci-core.c @@ -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 | @@ -1576,6 +1672,8 @@ static const struct pci_device_id pci_ids[] = {  	SDHCI_PCI_DEVICE(INTEL, CNPH_SD,   intel_byt_sd),  	SDHCI_PCI_DEVICE(INTEL, ICP_EMMC,  intel_glk_emmc),  	SDHCI_PCI_DEVICE(INTEL, ICP_SD,    intel_byt_sd), +	SDHCI_PCI_DEVICE(INTEL, CML_EMMC,  intel_glk_emmc), +	SDHCI_PCI_DEVICE(INTEL, CML_SD,    intel_byt_sd),  	SDHCI_PCI_DEVICE(O2, 8120,     o2),  	SDHCI_PCI_DEVICE(O2, 8220,     o2),  	SDHCI_PCI_DEVICE(O2, 8221,     o2),  |