diff options
author | Adrian Hunter <adrian.hunter@intel.com> | 2019-05-06 04:38:53 -0400 |
---|---|---|
committer | Ulf Hansson <ulf.hansson@linaro.org> | 2019-05-06 06:33:03 -0400 |
commit | 0a49a619e7e1aeb3f5f5511ca59314423c83dae2 (patch) | |
tree | 11a2beea28a357d5b6c0056ebf65730f98fb2b35 | |
parent | 343682173846c68f231929a5b84584ab7a845a0b (diff) |
mmc: sdhci-pci: Fix BYT OCP setting
Some time ago, a fix was done for the sdhci-acpi driver, refer
commit 6e1c7d6103fe ("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>
-rw-r--r-- | drivers/mmc/host/Kconfig | 1 | ||||
-rw-r--r-- | drivers/mmc/host/sdhci-pci-core.c | 96 |
2 files changed, 97 insertions, 0 deletions
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig index 1249cde7004d..0e86340536b6 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig | |||
@@ -92,6 +92,7 @@ config MMC_SDHCI_PCI | |||
92 | tristate "SDHCI support on PCI bus" | 92 | tristate "SDHCI support on PCI bus" |
93 | depends on MMC_SDHCI && PCI | 93 | depends on MMC_SDHCI && PCI |
94 | select MMC_CQHCI | 94 | select MMC_CQHCI |
95 | select IOSF_MBI if X86 | ||
95 | help | 96 | help |
96 | This selects the PCI Secure Digital Host Controller Interface. | 97 | This selects the PCI Secure Digital Host Controller Interface. |
97 | Most controllers found today are PCI devices. | 98 | 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 a3d7a9db76c5..ab9e2b901094 100644 --- a/drivers/mmc/host/sdhci-pci-core.c +++ b/drivers/mmc/host/sdhci-pci-core.c | |||
@@ -31,6 +31,10 @@ | |||
31 | #include <linux/mmc/sdhci-pci-data.h> | 31 | #include <linux/mmc/sdhci-pci-data.h> |
32 | #include <linux/acpi.h> | 32 | #include <linux/acpi.h> |
33 | 33 | ||
34 | #ifdef CONFIG_X86 | ||
35 | #include <asm/iosf_mbi.h> | ||
36 | #endif | ||
37 | |||
34 | #include "cqhci.h" | 38 | #include "cqhci.h" |
35 | 39 | ||
36 | #include "sdhci.h" | 40 | #include "sdhci.h" |
@@ -451,6 +455,50 @@ static const struct sdhci_pci_fixes sdhci_intel_pch_sdio = { | |||
451 | .probe_slot = pch_hc_probe_slot, | 455 | .probe_slot = pch_hc_probe_slot, |
452 | }; | 456 | }; |
453 | 457 | ||
458 | #ifdef CONFIG_X86 | ||
459 | |||
460 | #define BYT_IOSF_SCCEP 0x63 | ||
461 | #define BYT_IOSF_OCP_NETCTRL0 0x1078 | ||
462 | #define BYT_IOSF_OCP_TIMEOUT_BASE GENMASK(10, 8) | ||
463 | |||
464 | static void byt_ocp_setting(struct pci_dev *pdev) | ||
465 | { | ||
466 | u32 val = 0; | ||
467 | |||
468 | if (pdev->device != PCI_DEVICE_ID_INTEL_BYT_EMMC && | ||
469 | pdev->device != PCI_DEVICE_ID_INTEL_BYT_SDIO && | ||
470 | pdev->device != PCI_DEVICE_ID_INTEL_BYT_SD && | ||
471 | pdev->device != PCI_DEVICE_ID_INTEL_BYT_EMMC2) | ||
472 | return; | ||
473 | |||
474 | if (iosf_mbi_read(BYT_IOSF_SCCEP, MBI_CR_READ, BYT_IOSF_OCP_NETCTRL0, | ||
475 | &val)) { | ||
476 | dev_err(&pdev->dev, "%s read error\n", __func__); | ||
477 | return; | ||
478 | } | ||
479 | |||
480 | if (!(val & BYT_IOSF_OCP_TIMEOUT_BASE)) | ||
481 | return; | ||
482 | |||
483 | val &= ~BYT_IOSF_OCP_TIMEOUT_BASE; | ||
484 | |||
485 | if (iosf_mbi_write(BYT_IOSF_SCCEP, MBI_CR_WRITE, BYT_IOSF_OCP_NETCTRL0, | ||
486 | val)) { | ||
487 | dev_err(&pdev->dev, "%s write error\n", __func__); | ||
488 | return; | ||
489 | } | ||
490 | |||
491 | dev_dbg(&pdev->dev, "%s completed\n", __func__); | ||
492 | } | ||
493 | |||
494 | #else | ||
495 | |||
496 | static inline void byt_ocp_setting(struct pci_dev *pdev) | ||
497 | { | ||
498 | } | ||
499 | |||
500 | #endif | ||
501 | |||
454 | enum { | 502 | enum { |
455 | INTEL_DSM_FNS = 0, | 503 | INTEL_DSM_FNS = 0, |
456 | INTEL_DSM_V18_SWITCH = 3, | 504 | INTEL_DSM_V18_SWITCH = 3, |
@@ -715,6 +763,8 @@ static void byt_probe_slot(struct sdhci_pci_slot *slot) | |||
715 | 763 | ||
716 | byt_read_dsm(slot); | 764 | byt_read_dsm(slot); |
717 | 765 | ||
766 | byt_ocp_setting(slot->chip->pdev); | ||
767 | |||
718 | ops->execute_tuning = intel_execute_tuning; | 768 | ops->execute_tuning = intel_execute_tuning; |
719 | ops->start_signal_voltage_switch = intel_start_signal_voltage_switch; | 769 | ops->start_signal_voltage_switch = intel_start_signal_voltage_switch; |
720 | 770 | ||
@@ -938,7 +988,35 @@ static int byt_sd_probe_slot(struct sdhci_pci_slot *slot) | |||
938 | return 0; | 988 | return 0; |
939 | } | 989 | } |
940 | 990 | ||
991 | #ifdef CONFIG_PM_SLEEP | ||
992 | |||
993 | static int byt_resume(struct sdhci_pci_chip *chip) | ||
994 | { | ||
995 | byt_ocp_setting(chip->pdev); | ||
996 | |||
997 | return sdhci_pci_resume_host(chip); | ||
998 | } | ||
999 | |||
1000 | #endif | ||
1001 | |||
1002 | #ifdef CONFIG_PM | ||
1003 | |||
1004 | static int byt_runtime_resume(struct sdhci_pci_chip *chip) | ||
1005 | { | ||
1006 | byt_ocp_setting(chip->pdev); | ||
1007 | |||
1008 | return sdhci_pci_runtime_resume_host(chip); | ||
1009 | } | ||
1010 | |||
1011 | #endif | ||
1012 | |||
941 | static const struct sdhci_pci_fixes sdhci_intel_byt_emmc = { | 1013 | static const struct sdhci_pci_fixes sdhci_intel_byt_emmc = { |
1014 | #ifdef CONFIG_PM_SLEEP | ||
1015 | .resume = byt_resume, | ||
1016 | #endif | ||
1017 | #ifdef CONFIG_PM | ||
1018 | .runtime_resume = byt_runtime_resume, | ||
1019 | #endif | ||
942 | .allow_runtime_pm = true, | 1020 | .allow_runtime_pm = true, |
943 | .probe_slot = byt_emmc_probe_slot, | 1021 | .probe_slot = byt_emmc_probe_slot, |
944 | .quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC | | 1022 | .quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC | |
@@ -972,6 +1050,12 @@ static const struct sdhci_pci_fixes sdhci_intel_glk_emmc = { | |||
972 | }; | 1050 | }; |
973 | 1051 | ||
974 | static const struct sdhci_pci_fixes sdhci_ni_byt_sdio = { | 1052 | static const struct sdhci_pci_fixes sdhci_ni_byt_sdio = { |
1053 | #ifdef CONFIG_PM_SLEEP | ||
1054 | .resume = byt_resume, | ||
1055 | #endif | ||
1056 | #ifdef CONFIG_PM | ||
1057 | .runtime_resume = byt_runtime_resume, | ||
1058 | #endif | ||
975 | .quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC | | 1059 | .quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC | |
976 | SDHCI_QUIRK_NO_LED, | 1060 | SDHCI_QUIRK_NO_LED, |
977 | .quirks2 = SDHCI_QUIRK2_HOST_OFF_CARD_ON | | 1061 | .quirks2 = SDHCI_QUIRK2_HOST_OFF_CARD_ON | |
@@ -983,6 +1067,12 @@ static const struct sdhci_pci_fixes sdhci_ni_byt_sdio = { | |||
983 | }; | 1067 | }; |
984 | 1068 | ||
985 | static const struct sdhci_pci_fixes sdhci_intel_byt_sdio = { | 1069 | static const struct sdhci_pci_fixes sdhci_intel_byt_sdio = { |
1070 | #ifdef CONFIG_PM_SLEEP | ||
1071 | .resume = byt_resume, | ||
1072 | #endif | ||
1073 | #ifdef CONFIG_PM | ||
1074 | .runtime_resume = byt_runtime_resume, | ||
1075 | #endif | ||
986 | .quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC | | 1076 | .quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC | |
987 | SDHCI_QUIRK_NO_LED, | 1077 | SDHCI_QUIRK_NO_LED, |
988 | .quirks2 = SDHCI_QUIRK2_HOST_OFF_CARD_ON | | 1078 | .quirks2 = SDHCI_QUIRK2_HOST_OFF_CARD_ON | |
@@ -994,6 +1084,12 @@ static const struct sdhci_pci_fixes sdhci_intel_byt_sdio = { | |||
994 | }; | 1084 | }; |
995 | 1085 | ||
996 | static const struct sdhci_pci_fixes sdhci_intel_byt_sd = { | 1086 | static const struct sdhci_pci_fixes sdhci_intel_byt_sd = { |
1087 | #ifdef CONFIG_PM_SLEEP | ||
1088 | .resume = byt_resume, | ||
1089 | #endif | ||
1090 | #ifdef CONFIG_PM | ||
1091 | .runtime_resume = byt_runtime_resume, | ||
1092 | #endif | ||
997 | .quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC | | 1093 | .quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC | |
998 | SDHCI_QUIRK_NO_LED, | 1094 | SDHCI_QUIRK_NO_LED, |
999 | .quirks2 = SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON | | 1095 | .quirks2 = SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON | |