aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc
diff options
context:
space:
mode:
authorRabin Vincent <rabin.vincent@stericsson.com>2010-08-09 12:55:48 +0100
committerRussell King <rmk+kernel@arm.linux.org.uk>2010-09-23 15:01:59 +0100
commit148b8b39c156424da22693d26adcb69800faf95e (patch)
treecf3c1f37a69d81cfb04e968cb7911371ddf9ed80 /drivers/mmc
parentARM: 6310/1: mmci: support different FIFO sizes (diff)
downloadlinux-dev-148b8b39c156424da22693d26adcb69800faf95e.tar.xz
linux-dev-148b8b39c156424da22693d26adcb69800faf95e.zip
ARM: 6308/1: 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 <linus.walleij@stericsson.com> Signed-off-by: Rabin Vincent <rabin.vincent@stericsson.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'drivers/mmc')
-rw-r--r--drivers/mmc/host/mmci.c24
-rw-r--r--drivers/mmc/host/mmci.h1
2 files changed, 24 insertions, 1 deletions
diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c
index 1932e9cc8f52..a922a0028836 100644
--- a/drivers/mmc/host/mmci.c
+++ b/drivers/mmc/host/mmci.c
@@ -601,6 +601,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,
@@ -637,6 +646,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);
@@ -716,7 +726,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
@@ -761,6 +770,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)");
@@ -772,6 +787,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;
@@ -798,6 +816,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:
@@ -836,6 +856,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 4e18f5403f48..c7d373c7aec9 100644
--- a/drivers/mmc/host/mmci.h
+++ b/drivers/mmc/host/mmci.h
@@ -147,6 +147,7 @@ struct mmci_host {
struct clk *clk;
int gpio_cd;
int gpio_wp;
+ int gpio_cd_irq;
unsigned int data_xfered;