Commit 740a221e authored by Adrian Hunter's avatar Adrian Hunter Committed by Chris Ball

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: default avatarAdrian Hunter <adrian.hunter@intel.com>
Reviewed-by: default avatarLinus Walleij <linus.walleij@linaro.org>
Signed-off-by: default avatarChris Ball <chris@printf.net>
parent 26652671
...@@ -34,6 +34,7 @@ ...@@ -34,6 +34,7 @@
#include <linux/mmc/host.h> #include <linux/mmc/host.h>
#include <linux/mmc/mmc.h> #include <linux/mmc/mmc.h>
#include <linux/mmc/sd.h> #include <linux/mmc/sd.h>
#include <linux/mmc/slot-gpio.h>
#include "core.h" #include "core.h"
#include "bus.h" #include "bus.h"
...@@ -2471,6 +2472,7 @@ void mmc_start_host(struct mmc_host *host) ...@@ -2471,6 +2472,7 @@ void mmc_start_host(struct mmc_host *host)
mmc_power_off(host); mmc_power_off(host);
else else
mmc_power_up(host, host->ocr_avail); mmc_power_up(host, host->ocr_avail);
mmc_gpiod_request_cd_irq(host);
_mmc_detect_change(host, 0, false); _mmc_detect_change(host, 0, false);
} }
...@@ -2482,6 +2484,8 @@ void mmc_stop_host(struct mmc_host *host) ...@@ -2482,6 +2484,8 @@ void mmc_stop_host(struct mmc_host *host)
host->removed = 1; host->removed = 1;
spin_unlock_irqrestore(&host->lock, flags); spin_unlock_irqrestore(&host->lock, flags);
#endif #endif
if (host->slot.cd_irq >= 0)
disable_irq(host->slot.cd_irq);
host->rescan_disable = 1; host->rescan_disable = 1;
cancel_delayed_work_sync(&host->detect); cancel_delayed_work_sync(&host->detect);
......
...@@ -139,7 +139,7 @@ int mmc_gpio_request_ro(struct mmc_host *host, unsigned int gpio) ...@@ -139,7 +139,7 @@ int mmc_gpio_request_ro(struct mmc_host *host, unsigned int gpio)
} }
EXPORT_SYMBOL(mmc_gpio_request_ro); 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; struct mmc_gpio *ctx = host->slot.handler_priv;
int ret, irq; int ret, irq;
...@@ -171,6 +171,7 @@ static void mmc_gpiod_request_cd_irq(struct mmc_host *host) ...@@ -171,6 +171,7 @@ static void mmc_gpiod_request_cd_irq(struct mmc_host *host)
if (irq < 0) if (irq < 0)
host->caps |= MMC_CAP_NEEDS_POLL; host->caps |= MMC_CAP_NEEDS_POLL;
} }
EXPORT_SYMBOL(mmc_gpiod_request_cd_irq);
/** /**
* mmc_gpio_request_cd - request a gpio for card-detection * mmc_gpio_request_cd - request a gpio for card-detection
...@@ -276,3 +277,81 @@ void mmc_gpio_free_cd(struct mmc_host *host) ...@@ -276,3 +277,81 @@ void mmc_gpio_free_cd(struct mmc_host *host)
devm_gpio_free(&host->class_dev, gpio); devm_gpio_free(&host->class_dev, gpio);
} }
EXPORT_SYMBOL(mmc_gpio_free_cd); 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);
...@@ -22,4 +22,10 @@ int mmc_gpio_request_cd(struct mmc_host *host, unsigned int gpio, ...@@ -22,4 +22,10 @@ int mmc_gpio_request_cd(struct mmc_host *host, unsigned int gpio,
unsigned int debounce); unsigned int debounce);
void mmc_gpio_free_cd(struct mmc_host *host); 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 #endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment