aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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);