aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAdrian Hunter <adrian.hunter@intel.com>2014-03-10 09:02:42 -0400
committerChris Ball <chris@printf.net>2014-03-17 09:12:39 -0400
commit4fd4409c81e2c756a5cfbedc598c48d6a3ed3fd5 (patch)
tree432f23975640efe5b925f9d3df1c556b22873eee
parent740a221ef0e579dc7c675cf6b90f5313509788f7 (diff)
mmc: sdhci-acpi: Fix broken card detect for ACPI HID 80860F14
Some 80860F14 devices do not support card detect and must rely completely on GPIO. Presently the card detect GPIO is used only to wake-up from runtime suspend. Change to using mmc_gpioid_request_cd() which will cause the SDHCI driver to prefer the GPIO to the host controller's native card detect. Signed-off-by: Adrian Hunter <adrian.hunter@intel.com> Signed-off-by: Chris Ball <chris@printf.net>
-rw-r--r--drivers/mmc/host/sdhci-acpi.c77
1 files changed, 15 insertions, 62 deletions
diff --git a/drivers/mmc/host/sdhci-acpi.c b/drivers/mmc/host/sdhci-acpi.c
index 9ce17f6e4014..98c7420c5f75 100644
--- a/drivers/mmc/host/sdhci-acpi.c
+++ b/drivers/mmc/host/sdhci-acpi.c
@@ -31,7 +31,6 @@
31#include <linux/bitops.h> 31#include <linux/bitops.h>
32#include <linux/types.h> 32#include <linux/types.h>
33#include <linux/err.h> 33#include <linux/err.h>
34#include <linux/gpio/consumer.h>
35#include <linux/interrupt.h> 34#include <linux/interrupt.h>
36#include <linux/acpi.h> 35#include <linux/acpi.h>
37#include <linux/pm.h> 36#include <linux/pm.h>
@@ -40,13 +39,15 @@
40 39
41#include <linux/mmc/host.h> 40#include <linux/mmc/host.h>
42#include <linux/mmc/pm.h> 41#include <linux/mmc/pm.h>
42#include <linux/mmc/slot-gpio.h>
43#include <linux/mmc/sdhci.h> 43#include <linux/mmc/sdhci.h>
44 44
45#include "sdhci.h" 45#include "sdhci.h"
46 46
47enum { 47enum {
48 SDHCI_ACPI_SD_CD = BIT(0), 48 SDHCI_ACPI_SD_CD = BIT(0),
49 SDHCI_ACPI_RUNTIME_PM = BIT(1), 49 SDHCI_ACPI_RUNTIME_PM = BIT(1),
50 SDHCI_ACPI_SD_CD_OVERRIDE_LEVEL = BIT(2),
50}; 51};
51 52
52struct sdhci_acpi_chip { 53struct sdhci_acpi_chip {
@@ -128,7 +129,8 @@ static const struct sdhci_acpi_slot sdhci_acpi_slot_int_sdio = {
128}; 129};
129 130
130static const struct sdhci_acpi_slot sdhci_acpi_slot_int_sd = { 131static const struct sdhci_acpi_slot sdhci_acpi_slot_int_sd = {
131 .flags = SDHCI_ACPI_SD_CD | SDHCI_ACPI_RUNTIME_PM, 132 .flags = SDHCI_ACPI_SD_CD | SDHCI_ACPI_SD_CD_OVERRIDE_LEVEL |
133 SDHCI_ACPI_RUNTIME_PM,
132 .quirks2 = SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON, 134 .quirks2 = SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON,
133}; 135};
134 136
@@ -192,59 +194,6 @@ static const struct sdhci_acpi_slot *sdhci_acpi_get_slot(acpi_handle handle,
192 return slot; 194 return slot;
193} 195}
194 196
195#ifdef CONFIG_PM_RUNTIME
196
197static irqreturn_t sdhci_acpi_sd_cd(int irq, void *dev_id)
198{
199 mmc_detect_change(dev_id, msecs_to_jiffies(200));
200 return IRQ_HANDLED;
201}
202
203static int sdhci_acpi_add_own_cd(struct device *dev, struct mmc_host *mmc)
204{
205 struct gpio_desc *desc;
206 unsigned long flags;
207 int err, irq;
208
209 desc = devm_gpiod_get_index(dev, "sd_cd", 0);
210 if (IS_ERR(desc)) {
211 err = PTR_ERR(desc);
212 goto out;
213 }
214
215 err = gpiod_direction_input(desc);
216 if (err)
217 goto out_free;
218
219 irq = gpiod_to_irq(desc);
220 if (irq < 0) {
221 err = irq;
222 goto out_free;
223 }
224
225 flags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING;
226 err = devm_request_irq(dev, irq, sdhci_acpi_sd_cd, flags, "sd_cd", mmc);
227 if (err)
228 goto out_free;
229
230 return 0;
231
232out_free:
233 devm_gpiod_put(dev, desc);
234out:
235 dev_warn(dev, "failed to setup card detect wake up\n");
236 return err;
237}
238
239#else
240
241static int sdhci_acpi_add_own_cd(struct device *dev, struct mmc_host *mmc)
242{
243 return 0;
244}
245
246#endif
247
248static int sdhci_acpi_probe(struct platform_device *pdev) 197static int sdhci_acpi_probe(struct platform_device *pdev)
249{ 198{
250 struct device *dev = &pdev->dev; 199 struct device *dev = &pdev->dev;
@@ -332,15 +281,19 @@ static int sdhci_acpi_probe(struct platform_device *pdev)
332 281
333 host->mmc->caps2 |= MMC_CAP2_NO_PRESCAN_POWERUP; 282 host->mmc->caps2 |= MMC_CAP2_NO_PRESCAN_POWERUP;
334 283
335 err = sdhci_add_host(host);
336 if (err)
337 goto err_free;
338
339 if (sdhci_acpi_flag(c, SDHCI_ACPI_SD_CD)) { 284 if (sdhci_acpi_flag(c, SDHCI_ACPI_SD_CD)) {
340 if (sdhci_acpi_add_own_cd(dev, host->mmc)) 285 bool v = sdhci_acpi_flag(c, SDHCI_ACPI_SD_CD_OVERRIDE_LEVEL);
286
287 if (mmc_gpiod_request_cd(host->mmc, NULL, 0, v, 0)) {
288 dev_warn(dev, "failed to setup card detect gpio\n");
341 c->use_runtime_pm = false; 289 c->use_runtime_pm = false;
290 }
342 } 291 }
343 292
293 err = sdhci_add_host(host);
294 if (err)
295 goto err_free;
296
344 if (c->use_runtime_pm) { 297 if (c->use_runtime_pm) {
345 pm_runtime_set_active(dev); 298 pm_runtime_set_active(dev);
346 pm_suspend_ignore_children(dev, 1); 299 pm_suspend_ignore_children(dev, 1);