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>
This commit is contained in:
parent
2665267133
commit
740a221ef0
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue