From 060aaad1a1bfee60f2a16651e5c81336a77e2576 Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Tue, 22 Jun 2010 14:47:40 +0530 Subject: [PATCH 17/38] mmci: support card detection interrupts If an IRQ can be requested on the card detected GPIO, use it instead of polling. Acked-by: Linus Walleij Signed-off-by: Rabin Vincent --- drivers/mmc/host/mmci.c | 24 +++++++++++++++++++++++- drivers/mmc/host/mmci.h | 1 + 2 files changed, 24 insertions(+), 1 deletions(-) diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c index 9a9aeac..29d37be 100644 --- a/drivers/mmc/host/mmci.c +++ b/drivers/mmc/host/mmci.c @@ -585,6 +585,15 @@ static int mmci_get_cd(struct mmc_host *mmc) return status; } +static irqreturn_t mmci_cd_irq(int irq, void *dev_id) +{ + struct mmci_host *host = dev_id; + + mmc_detect_change(host->mmc, msecs_to_jiffies(500)); + + return IRQ_HANDLED; +} + static const struct mmc_host_ops mmci_ops = { .request = mmci_request, .set_ios = mmci_set_ios, @@ -621,6 +630,7 @@ static int __devinit mmci_probe(struct amba_device *dev, struct amba_id *id) host->gpio_wp = -ENOSYS; host->gpio_cd = -ENOSYS; + host->gpio_cd_irq = -1; host->hw_designer = amba_manf(dev); host->hw_revision = amba_rev(dev); @@ -700,7 +710,6 @@ static int __devinit mmci_probe(struct amba_device *dev, struct amba_id *id) if (host->vcc == NULL) mmc->ocr_avail = plat->ocr_mask; mmc->caps = plat->capabilities; - mmc->caps |= MMC_CAP_NEEDS_POLL; /* * We can do SGIO @@ -745,6 +754,12 @@ static int __devinit mmci_probe(struct amba_device *dev, struct amba_id *id) host->gpio_cd = plat->gpio_cd; else if (ret != -ENOSYS) goto err_gpio_cd; + + ret = request_any_context_irq(gpio_to_irq(plat->gpio_cd), + mmci_cd_irq, 0, + DRIVER_NAME " (cd)", host); + if (ret >= 0) + host->gpio_cd_irq = gpio_to_irq(plat->gpio_cd); } if (gpio_is_valid(plat->gpio_wp)) { ret = gpio_request(plat->gpio_wp, DRIVER_NAME " (wp)"); @@ -756,6 +771,9 @@ static int __devinit mmci_probe(struct amba_device *dev, struct amba_id *id) goto err_gpio_wp; } + if (host->gpio_cd_irq < 0) + mmc->caps |= MMC_CAP_NEEDS_POLL; + ret = request_irq(dev->irq[0], mmci_irq, IRQF_SHARED, DRIVER_NAME " (cmd)", host); if (ret) goto unmap; @@ -782,6 +800,8 @@ static int __devinit mmci_probe(struct amba_device *dev, struct amba_id *id) if (host->gpio_wp != -ENOSYS) gpio_free(host->gpio_wp); err_gpio_wp: + if (host->gpio_cd_irq >= 0) + free_irq(host->gpio_cd_irq, host); if (host->gpio_cd != -ENOSYS) gpio_free(host->gpio_cd); err_gpio_cd: @@ -820,6 +840,8 @@ static int __devexit mmci_remove(struct amba_device *dev) if (host->gpio_wp != -ENOSYS) gpio_free(host->gpio_wp); + if (host->gpio_cd_irq >= 0) + free_irq(host->gpio_cd_irq, host); if (host->gpio_cd != -ENOSYS) gpio_free(host->gpio_cd); diff --git a/drivers/mmc/host/mmci.h b/drivers/mmc/host/mmci.h index 68970cf..0a11ddc 100644 --- a/drivers/mmc/host/mmci.h +++ b/drivers/mmc/host/mmci.h @@ -154,6 +154,7 @@ struct mmci_host { struct clk *clk; int gpio_cd; int gpio_wp; + int gpio_cd_irq; unsigned int data_xfered; -- 1.6.3.3