aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAdrian Hunter <adrian.hunter@intel.com>2016-04-15 07:06:57 -0400
committerUlf Hansson <ulf.hansson@linaro.org>2016-04-18 05:22:53 -0400
commit6e1c7d6103fe7031035cec321307c6356809adf4 (patch)
treed0c2e4002b8c4ad7d882a1046aef4f3c72f2ea8d
parentc3b46c73264b03000d1e18b22f5caf63332547c9 (diff)
mmc: sdhci-acpi: Reduce Baytrail eMMC/SD/SDIO hangs
Baytrail eMMC/SD/SDIO host controllers have been known to hang. A change to a hardware setting has been found to reduce the occurrence of such hangs. This patch ensures the correct setting. This patch applies cleanly to v4.4+. It could go to earlier kernels also, so I will send backports to the stable list in due course. Signed-off-by: Adrian Hunter <adrian.hunter@intel.com> Cc: stable@vger.kernel.org # v4.4+ Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
-rw-r--r--drivers/mmc/host/Kconfig1
-rw-r--r--drivers/mmc/host/sdhci-acpi.c81
2 files changed, 82 insertions, 0 deletions
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
index 04feea8354cb..e657af0e95fa 100644
--- a/drivers/mmc/host/Kconfig
+++ b/drivers/mmc/host/Kconfig
@@ -97,6 +97,7 @@ config MMC_RICOH_MMC
97config MMC_SDHCI_ACPI 97config MMC_SDHCI_ACPI
98 tristate "SDHCI support for ACPI enumerated SDHCI controllers" 98 tristate "SDHCI support for ACPI enumerated SDHCI controllers"
99 depends on MMC_SDHCI && ACPI 99 depends on MMC_SDHCI && ACPI
100 select IOSF_MBI if X86
100 help 101 help
101 This selects support for ACPI enumerated SDHCI controllers, 102 This selects support for ACPI enumerated SDHCI controllers,
102 identified by ACPI Compatibility ID PNP0D40 or specific 103 identified by ACPI Compatibility ID PNP0D40 or specific
diff --git a/drivers/mmc/host/sdhci-acpi.c b/drivers/mmc/host/sdhci-acpi.c
index 6839e41c6d58..bed6a494f52c 100644
--- a/drivers/mmc/host/sdhci-acpi.c
+++ b/drivers/mmc/host/sdhci-acpi.c
@@ -41,6 +41,11 @@
41#include <linux/mmc/pm.h> 41#include <linux/mmc/pm.h>
42#include <linux/mmc/slot-gpio.h> 42#include <linux/mmc/slot-gpio.h>
43 43
44#ifdef CONFIG_X86
45#include <asm/cpu_device_id.h>
46#include <asm/iosf_mbi.h>
47#endif
48
44#include "sdhci.h" 49#include "sdhci.h"
45 50
46enum { 51enum {
@@ -116,6 +121,75 @@ static const struct sdhci_acpi_chip sdhci_acpi_chip_int = {
116 .ops = &sdhci_acpi_ops_int, 121 .ops = &sdhci_acpi_ops_int,
117}; 122};
118 123
124#ifdef CONFIG_X86
125
126static bool sdhci_acpi_byt(void)
127{
128 static const struct x86_cpu_id byt[] = {
129 { X86_VENDOR_INTEL, 6, 0x37 },
130 {}
131 };
132
133 return x86_match_cpu(byt);
134}
135
136#define BYT_IOSF_SCCEP 0x63
137#define BYT_IOSF_OCP_NETCTRL0 0x1078
138#define BYT_IOSF_OCP_TIMEOUT_BASE GENMASK(10, 8)
139
140static void sdhci_acpi_byt_setting(struct device *dev)
141{
142 u32 val = 0;
143
144 if (!sdhci_acpi_byt())
145 return;
146
147 if (iosf_mbi_read(BYT_IOSF_SCCEP, MBI_CR_READ, BYT_IOSF_OCP_NETCTRL0,
148 &val)) {
149 dev_err(dev, "%s read error\n", __func__);
150 return;
151 }
152
153 if (!(val & BYT_IOSF_OCP_TIMEOUT_BASE))
154 return;
155
156 val &= ~BYT_IOSF_OCP_TIMEOUT_BASE;
157
158 if (iosf_mbi_write(BYT_IOSF_SCCEP, MBI_CR_WRITE, BYT_IOSF_OCP_NETCTRL0,
159 val)) {
160 dev_err(dev, "%s write error\n", __func__);
161 return;
162 }
163
164 dev_dbg(dev, "%s completed\n", __func__);
165}
166
167static bool sdhci_acpi_byt_defer(struct device *dev)
168{
169 if (!sdhci_acpi_byt())
170 return false;
171
172 if (!iosf_mbi_available())
173 return true;
174
175 sdhci_acpi_byt_setting(dev);
176
177 return false;
178}
179
180#else
181
182static inline void sdhci_acpi_byt_setting(struct device *dev)
183{
184}
185
186static inline bool sdhci_acpi_byt_defer(struct device *dev)
187{
188 return false;
189}
190
191#endif
192
119static int bxt_get_cd(struct mmc_host *mmc) 193static int bxt_get_cd(struct mmc_host *mmc)
120{ 194{
121 int gpio_cd = mmc_gpio_get_cd(mmc); 195 int gpio_cd = mmc_gpio_get_cd(mmc);
@@ -322,6 +396,9 @@ static int sdhci_acpi_probe(struct platform_device *pdev)
322 if (acpi_bus_get_status(device) || !device->status.present) 396 if (acpi_bus_get_status(device) || !device->status.present)
323 return -ENODEV; 397 return -ENODEV;
324 398
399 if (sdhci_acpi_byt_defer(dev))
400 return -EPROBE_DEFER;
401
325 hid = acpi_device_hid(device); 402 hid = acpi_device_hid(device);
326 uid = device->pnp.unique_id; 403 uid = device->pnp.unique_id;
327 404
@@ -447,6 +524,8 @@ static int sdhci_acpi_resume(struct device *dev)
447{ 524{
448 struct sdhci_acpi_host *c = dev_get_drvdata(dev); 525 struct sdhci_acpi_host *c = dev_get_drvdata(dev);
449 526
527 sdhci_acpi_byt_setting(&c->pdev->dev);
528
450 return sdhci_resume_host(c->host); 529 return sdhci_resume_host(c->host);
451} 530}
452 531
@@ -470,6 +549,8 @@ static int sdhci_acpi_runtime_resume(struct device *dev)
470{ 549{
471 struct sdhci_acpi_host *c = dev_get_drvdata(dev); 550 struct sdhci_acpi_host *c = dev_get_drvdata(dev);
472 551
552 sdhci_acpi_byt_setting(&c->pdev->dev);
553
473 return sdhci_runtime_resume_host(c->host); 554 return sdhci_runtime_resume_host(c->host);
474} 555}
475 556