mmc: slot-gpio: Add GPIO descriptor based CD GPIO API
authorAdrian Hunter <adrian.hunter@intel.com>
Mon, 10 Mar 2014 13:02:41 +0000 (15:02 +0200)
committerChris Ball <chris@printf.net>
Mon, 17 Mar 2014 13:12:00 +0000 (09:12 -0400)
Add functions to request a CD GPIO using the GPIO descriptor API.
Note that the new request function is paired with mmc_gpiod_free_cd()
not mmc_gpio_free_cd().  Note also that it must be called prior to
mmc_add_host() otherwise the caller must also call
mmc_gpiod_request_cd_irq().

Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Chris Ball <chris@printf.net>
drivers/mmc/core/core.c
drivers/mmc/core/slot-gpio.c
include/linux/mmc/slot-gpio.h

index dc7a5fb81a5ce914c9ee1622fb41f14050848fe1..acbc3f2aaaf9e3adff743de7081e1e6508b6b03c 100644 (file)
@@ -34,6 +34,7 @@
 #include <linux/mmc/host.h>
 #include <linux/mmc/mmc.h>
 #include <linux/mmc/sd.h>
+#include <linux/mmc/slot-gpio.h>
 
 #include "core.h"
 #include "bus.h"
@@ -2471,6 +2472,7 @@ void mmc_start_host(struct mmc_host *host)
                mmc_power_off(host);
        else
                mmc_power_up(host, host->ocr_avail);
+       mmc_gpiod_request_cd_irq(host);
        _mmc_detect_change(host, 0, false);
 }
 
@@ -2482,6 +2484,8 @@ void mmc_stop_host(struct mmc_host *host)
        host->removed = 1;
        spin_unlock_irqrestore(&host->lock, flags);
 #endif
+       if (host->slot.cd_irq >= 0)
+               disable_irq(host->slot.cd_irq);
 
        host->rescan_disable = 1;
        cancel_delayed_work_sync(&host->detect);
index 47fa07e3604dca6a129a2474cb0e7325c21bac8a..f7650b899e3d426fbce08e8b636784adf0d0cdf0 100644 (file)
@@ -139,7 +139,7 @@ int mmc_gpio_request_ro(struct mmc_host *host, unsigned int gpio)
 }
 EXPORT_SYMBOL(mmc_gpio_request_ro);
 
-static void mmc_gpiod_request_cd_irq(struct mmc_host *host)
+void mmc_gpiod_request_cd_irq(struct mmc_host *host)
 {
        struct mmc_gpio *ctx = host->slot.handler_priv;
        int ret, irq;
@@ -171,6 +171,7 @@ static void mmc_gpiod_request_cd_irq(struct mmc_host *host)
        if (irq < 0)
                host->caps |= MMC_CAP_NEEDS_POLL;
 }
+EXPORT_SYMBOL(mmc_gpiod_request_cd_irq);
 
 /**
  * mmc_gpio_request_cd - request a gpio for card-detection
@@ -276,3 +277,81 @@ void mmc_gpio_free_cd(struct mmc_host *host)
        devm_gpio_free(&host->class_dev, gpio);
 }
 EXPORT_SYMBOL(mmc_gpio_free_cd);
+
+/**
+ * mmc_gpiod_request_cd - request a gpio descriptor for card-detection
+ * @host: mmc host
+ * @con_id: function within the GPIO consumer
+ * @idx: index of the GPIO to obtain in the consumer
+ * @override_active_level: ignore %GPIO_ACTIVE_LOW flag
+ * @debounce: debounce time in microseconds
+ *
+ * Use this function in place of mmc_gpio_request_cd() to use the GPIO
+ * descriptor API.  Note that it is paired with mmc_gpiod_free_cd() not
+ * mmc_gpio_free_cd().  Note also that it must be called prior to mmc_add_host()
+ * otherwise the caller must also call mmc_gpiod_request_cd_irq().
+ *
+ * Returns zero on success, else an error.
+ */
+int mmc_gpiod_request_cd(struct mmc_host *host, const char *con_id,
+                        unsigned int idx, bool override_active_level,
+                        unsigned int debounce)
+{
+       struct mmc_gpio *ctx;
+       struct gpio_desc *desc;
+       int ret;
+
+       ret = mmc_gpio_alloc(host);
+       if (ret < 0)
+               return ret;
+
+       ctx = host->slot.handler_priv;
+
+       if (!con_id)
+               con_id = ctx->cd_label;
+
+       desc = devm_gpiod_get_index(host->parent, con_id, idx);
+       if (IS_ERR(desc))
+               return PTR_ERR(desc);
+
+       ret = gpiod_direction_input(desc);
+       if (ret < 0)
+               return ret;
+
+       if (debounce) {
+               ret = gpiod_set_debounce(desc, debounce);
+               if (ret < 0)
+                       return ret;
+       }
+
+       ctx->override_cd_active_level = override_active_level;
+       ctx->cd_gpio = desc;
+
+       return 0;
+}
+EXPORT_SYMBOL(mmc_gpiod_request_cd);
+
+/**
+ * mmc_gpiod_free_cd - free the card-detection gpio descriptor
+ * @host: mmc host
+ *
+ * It's provided only for cases that client drivers need to manually free
+ * up the card-detection gpio requested by mmc_gpiod_request_cd().
+ */
+void mmc_gpiod_free_cd(struct mmc_host *host)
+{
+       struct mmc_gpio *ctx = host->slot.handler_priv;
+
+       if (!ctx || !ctx->cd_gpio)
+               return;
+
+       if (host->slot.cd_irq >= 0) {
+               devm_free_irq(&host->class_dev, host->slot.cd_irq, host);
+               host->slot.cd_irq = -EINVAL;
+       }
+
+       devm_gpiod_put(&host->class_dev, ctx->cd_gpio);
+
+       ctx->cd_gpio = NULL;
+}
+EXPORT_SYMBOL(mmc_gpiod_free_cd);
index b0c73e4cacea1484fe4790a49514cb004e0af024..d2433381e8286573cda47c579660562196644c83 100644 (file)
@@ -22,4 +22,10 @@ int mmc_gpio_request_cd(struct mmc_host *host, unsigned int gpio,
                        unsigned int debounce);
 void mmc_gpio_free_cd(struct mmc_host *host);
 
+int mmc_gpiod_request_cd(struct mmc_host *host, const char *con_id,
+                        unsigned int idx, bool override_active_level,
+                        unsigned int debounce);
+void mmc_gpiod_free_cd(struct mmc_host *host);
+void mmc_gpiod_request_cd_irq(struct mmc_host *host);
+
 #endif