Commit 4fd4409c authored by Adrian Hunter's avatar Adrian Hunter Committed by Chris Ball

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: default avatarAdrian Hunter <adrian.hunter@intel.com>
Signed-off-by: default avatarChris Ball <chris@printf.net>
parent 740a221e
...@@ -31,7 +31,6 @@ ...@@ -31,7 +31,6 @@
#include <linux/bitops.h> #include <linux/bitops.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/gpio/consumer.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/acpi.h> #include <linux/acpi.h>
#include <linux/pm.h> #include <linux/pm.h>
...@@ -40,6 +39,7 @@ ...@@ -40,6 +39,7 @@
#include <linux/mmc/host.h> #include <linux/mmc/host.h>
#include <linux/mmc/pm.h> #include <linux/mmc/pm.h>
#include <linux/mmc/slot-gpio.h>
#include <linux/mmc/sdhci.h> #include <linux/mmc/sdhci.h>
#include "sdhci.h" #include "sdhci.h"
...@@ -47,6 +47,7 @@ ...@@ -47,6 +47,7 @@
enum { enum {
SDHCI_ACPI_SD_CD = BIT(0), SDHCI_ACPI_SD_CD = BIT(0),
SDHCI_ACPI_RUNTIME_PM = BIT(1), SDHCI_ACPI_RUNTIME_PM = BIT(1),
SDHCI_ACPI_SD_CD_OVERRIDE_LEVEL = BIT(2),
}; };
struct sdhci_acpi_chip { struct sdhci_acpi_chip {
...@@ -128,7 +129,8 @@ static const struct sdhci_acpi_slot sdhci_acpi_slot_int_sdio = { ...@@ -128,7 +129,8 @@ static const struct sdhci_acpi_slot sdhci_acpi_slot_int_sdio = {
}; };
static const struct sdhci_acpi_slot sdhci_acpi_slot_int_sd = { static const struct sdhci_acpi_slot sdhci_acpi_slot_int_sd = {
.flags = SDHCI_ACPI_SD_CD | SDHCI_ACPI_RUNTIME_PM, .flags = SDHCI_ACPI_SD_CD | SDHCI_ACPI_SD_CD_OVERRIDE_LEVEL |
SDHCI_ACPI_RUNTIME_PM,
.quirks2 = SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON, .quirks2 = SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON,
}; };
...@@ -192,59 +194,6 @@ static const struct sdhci_acpi_slot *sdhci_acpi_get_slot(acpi_handle handle, ...@@ -192,59 +194,6 @@ static const struct sdhci_acpi_slot *sdhci_acpi_get_slot(acpi_handle handle,
return slot; return slot;
} }
#ifdef CONFIG_PM_RUNTIME
static irqreturn_t sdhci_acpi_sd_cd(int irq, void *dev_id)
{
mmc_detect_change(dev_id, msecs_to_jiffies(200));
return IRQ_HANDLED;
}
static int sdhci_acpi_add_own_cd(struct device *dev, struct mmc_host *mmc)
{
struct gpio_desc *desc;
unsigned long flags;
int err, irq;
desc = devm_gpiod_get_index(dev, "sd_cd", 0);
if (IS_ERR(desc)) {
err = PTR_ERR(desc);
goto out;
}
err = gpiod_direction_input(desc);
if (err)
goto out_free;
irq = gpiod_to_irq(desc);
if (irq < 0) {
err = irq;
goto out_free;
}
flags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING;
err = devm_request_irq(dev, irq, sdhci_acpi_sd_cd, flags, "sd_cd", mmc);
if (err)
goto out_free;
return 0;
out_free:
devm_gpiod_put(dev, desc);
out:
dev_warn(dev, "failed to setup card detect wake up\n");
return err;
}
#else
static int sdhci_acpi_add_own_cd(struct device *dev, struct mmc_host *mmc)
{
return 0;
}
#endif
static int sdhci_acpi_probe(struct platform_device *pdev) static int sdhci_acpi_probe(struct platform_device *pdev)
{ {
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
...@@ -332,14 +281,18 @@ static int sdhci_acpi_probe(struct platform_device *pdev) ...@@ -332,14 +281,18 @@ static int sdhci_acpi_probe(struct platform_device *pdev)
host->mmc->caps2 |= MMC_CAP2_NO_PRESCAN_POWERUP; host->mmc->caps2 |= MMC_CAP2_NO_PRESCAN_POWERUP;
err = sdhci_add_host(host);
if (err)
goto err_free;
if (sdhci_acpi_flag(c, SDHCI_ACPI_SD_CD)) { if (sdhci_acpi_flag(c, SDHCI_ACPI_SD_CD)) {
if (sdhci_acpi_add_own_cd(dev, host->mmc)) bool v = sdhci_acpi_flag(c, SDHCI_ACPI_SD_CD_OVERRIDE_LEVEL);
if (mmc_gpiod_request_cd(host->mmc, NULL, 0, v, 0)) {
dev_warn(dev, "failed to setup card detect gpio\n");
c->use_runtime_pm = false; c->use_runtime_pm = false;
} }
}
err = sdhci_add_host(host);
if (err)
goto err_free;
if (c->use_runtime_pm) { if (c->use_runtime_pm) {
pm_runtime_set_active(dev); pm_runtime_set_active(dev);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment