Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -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);
+80 −1
Original line number Diff line number Diff line
@@ -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);
+6 −0
Original line number Diff line number Diff line
@@ -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