diff options
author | Adrian Hunter <adrian.hunter@intel.com> | 2014-03-10 13:02:41 (GMT) |
---|---|---|
committer | Chris Ball <chris@printf.net> | 2014-03-17 13:12:00 (GMT) |
commit | 740a221ef0e579dc7c675cf6b90f5313509788f7 (patch) | |
tree | 7e31940925f1e6e4b7876c9a1f96a17eef20b401 /drivers/mmc/core | |
parent | 26652671338a443fd33cf47b50658dd8b095d54a (diff) | |
download | linux-740a221ef0e579dc7c675cf6b90f5313509788f7.tar.xz |
mmc: slot-gpio: Add GPIO descriptor based CD GPIO API
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>
Diffstat (limited to 'drivers/mmc/core')
-rw-r--r-- | drivers/mmc/core/core.c | 4 | ||||
-rw-r--r-- | drivers/mmc/core/slot-gpio.c | 81 |
2 files changed, 84 insertions, 1 deletions
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index dc7a5fb..acbc3f2 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -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); diff --git a/drivers/mmc/core/slot-gpio.c b/drivers/mmc/core/slot-gpio.c index 47fa07e..f7650b8 100644 --- a/drivers/mmc/core/slot-gpio.c +++ b/drivers/mmc/core/slot-gpio.c @@ -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); |