mmc: sdhci-spear: use generic card detection gpio support
authorRussell King <rmk+kernel@arm.linux.org.uk>
Fri, 28 Feb 2014 21:32:49 +0000 (21:32 +0000)
committerChris Ball <chris@printf.net>
Tue, 4 Mar 2014 21:28:47 +0000 (16:28 -0500)
sdhci has support for using GPIOs for card detection.  If we have a
GPIO specified, we can use that directly, without needing our own
interrupt handler.

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Signed-off-by: Chris Ball <chris@printf.net>
drivers/mmc/host/sdhci-spear.c

index 676df4623057ab4e794a3115d7415f9dde98c0bd..0316dec3f0060e5ad7a8d83a35421018e210811c 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/slab.h>
 #include <linux/mmc/host.h>
 #include <linux/mmc/sdhci-spear.h>
+#include <linux/mmc/slot-gpio.h>
 #include <linux/io.h>
 #include "sdhci.h"
 
@@ -40,28 +41,6 @@ static const struct sdhci_ops sdhci_pltfm_ops = {
        /* Nothing to do for now. */
 };
 
-/* gpio card detection interrupt handler */
-static irqreturn_t sdhci_gpio_irq(int irq, void *dev_id)
-{
-       struct platform_device *pdev = dev_id;
-       struct sdhci_host *host = platform_get_drvdata(pdev);
-       struct spear_sdhci *sdhci = dev_get_platdata(&pdev->dev);
-       unsigned long gpio_irq_type;
-       int val;
-
-       val = gpio_get_value(sdhci->data->card_int_gpio);
-
-       /* val == 1 -> card removed, val == 0 -> card inserted */
-       /* if card removed - set irq for low level, else vice versa */
-       gpio_irq_type = val ? IRQF_TRIGGER_LOW : IRQF_TRIGGER_HIGH;
-       irq_set_irq_type(irq, gpio_irq_type);
-
-       /* inform sdhci driver about card insertion/removal */
-       tasklet_schedule(&host->card_tasklet);
-
-       return IRQ_HANDLED;
-}
-
 #ifdef CONFIG_OF
 static struct sdhci_plat_data *sdhci_probe_config_dt(struct platform_device *pdev)
 {
@@ -152,6 +131,22 @@ static int sdhci_probe(struct platform_device *pdev)
                sdhci->data = dev_get_platdata(&pdev->dev);
        }
 
+       /*
+        * It is optional to use GPIOs for sdhci card detection. If
+        * sdhci->data is NULL, then use original sdhci lines otherwise
+        * GPIO lines. We use the built-in GPIO support for this.
+        */
+       if (sdhci->data && sdhci->data->card_int_gpio >= 0) {
+               ret = mmc_gpio_request_cd(host->mmc,
+                                         sdhci->data->card_int_gpio, 0);
+               if (ret < 0) {
+                       dev_dbg(&pdev->dev,
+                               "failed to request card-detect gpio%d\n",
+                               sdhci->data->card_int_gpio);
+                       goto disable_clk;
+               }
+       }
+
        ret = sdhci_add_host(host);
        if (ret) {
                dev_dbg(&pdev->dev, "error adding host\n");
@@ -160,48 +155,8 @@ static int sdhci_probe(struct platform_device *pdev)
 
        platform_set_drvdata(pdev, host);
 
-       /*
-        * It is optional to use GPIOs for sdhci Power control & sdhci card
-        * interrupt detection. If sdhci->data is NULL, then use original sdhci
-        * lines otherwise GPIO lines.
-        * If GPIO is selected for power control, then power should be disabled
-        * after card removal and should be enabled when card insertion
-        * interrupt occurs
-        */
-       if (!sdhci->data)
-               return 0;
-
-       if (sdhci->data->card_int_gpio >= 0) {
-               ret = devm_gpio_request(&pdev->dev, sdhci->data->card_int_gpio,
-                               "sdhci");
-               if (ret < 0) {
-                       dev_dbg(&pdev->dev, "gpio request fail: %d\n",
-                                       sdhci->data->card_int_gpio);
-                       goto set_drvdata;
-               }
-
-               ret = gpio_direction_input(sdhci->data->card_int_gpio);
-               if (ret) {
-                       dev_dbg(&pdev->dev, "gpio set direction fail: %d\n",
-                                       sdhci->data->card_int_gpio);
-                       goto set_drvdata;
-               }
-               ret = devm_request_irq(&pdev->dev,
-                               gpio_to_irq(sdhci->data->card_int_gpio),
-                               sdhci_gpio_irq, IRQF_TRIGGER_LOW,
-                               mmc_hostname(host->mmc), pdev);
-               if (ret) {
-                       dev_dbg(&pdev->dev, "gpio request irq fail: %d\n",
-                                       sdhci->data->card_int_gpio);
-                       goto set_drvdata;
-               }
-
-       }
-
        return 0;
 
-set_drvdata:
-       sdhci_remove_host(host, 1);
 disable_clk:
        clk_disable_unprepare(sdhci->clk);
 err_host: