drivers/mmc/core/slot-gpio.c

Source file repositories/reference/linux-study-clean/drivers/mmc/core/slot-gpio.c

File Facts

System
Linux kernel
Corpus path
drivers/mmc/core/slot-gpio.c
Extension
.c
Size
6991 bytes
Lines
285
Domain
Driver Families
Bucket
drivers/mmc
Inferred role
Driver Families: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct mmc_gpio {
	struct gpio_desc *ro_gpio;
	struct gpio_desc *cd_gpio;
	irq_handler_t cd_gpio_isr;
	char *ro_label;
	char *cd_label;
	u32 cd_debounce_delay_ms;
	int cd_irq;
};

static irqreturn_t mmc_gpio_cd_irqt(int irq, void *dev_id)
{
	/* Schedule a card detection after a debounce timeout */
	struct mmc_host *host = dev_id;
	struct mmc_gpio *ctx = host->slot.handler_priv;

	host->trigger_card_event = true;
	mmc_detect_change(host, msecs_to_jiffies(ctx->cd_debounce_delay_ms));

	return IRQ_HANDLED;
}

int mmc_gpio_alloc(struct mmc_host *host)
{
	const char *devname = dev_name(host->parent);
	struct mmc_gpio *ctx;

	ctx = devm_kzalloc(host->parent, sizeof(*ctx), GFP_KERNEL);
	if (!ctx)
		return -ENOMEM;

	ctx->cd_debounce_delay_ms = 200;
	ctx->cd_label = devm_kasprintf(host->parent, GFP_KERNEL, "%s cd", devname);
	if (!ctx->cd_label)
		return -ENOMEM;
	ctx->ro_label = devm_kasprintf(host->parent, GFP_KERNEL, "%s ro", devname);
	if (!ctx->ro_label)
		return -ENOMEM;
	ctx->cd_irq = -EINVAL;
	host->slot.handler_priv = ctx;
	host->slot.cd_irq = -EINVAL;

	return 0;
}

void mmc_gpio_set_cd_irq(struct mmc_host *host, int irq)
{
	struct mmc_gpio *ctx = host->slot.handler_priv;

	if (!ctx || irq < 0)
		return;

	ctx->cd_irq = irq;
}
EXPORT_SYMBOL(mmc_gpio_set_cd_irq);

int mmc_gpio_get_ro(struct mmc_host *host)
{
	struct mmc_gpio *ctx = host->slot.handler_priv;
	int cansleep;

	if (!ctx || !ctx->ro_gpio)
		return -ENOSYS;

	cansleep = gpiod_cansleep(ctx->ro_gpio);
	return cansleep ?
		gpiod_get_value_cansleep(ctx->ro_gpio) :
		gpiod_get_value(ctx->ro_gpio);
}
EXPORT_SYMBOL(mmc_gpio_get_ro);

int mmc_gpio_get_cd(struct mmc_host *host)
{
	struct mmc_gpio *ctx = host->slot.handler_priv;
	int cansleep;

	if (!ctx || !ctx->cd_gpio)
		return -ENOSYS;

	cansleep = gpiod_cansleep(ctx->cd_gpio);
	return cansleep ?
		gpiod_get_value_cansleep(ctx->cd_gpio) :
		gpiod_get_value(ctx->cd_gpio);
}
EXPORT_SYMBOL(mmc_gpio_get_cd);

void mmc_gpiod_request_cd_irq(struct mmc_host *host)
{
	struct mmc_gpio *ctx = host->slot.handler_priv;
	int irq = -EINVAL;

Annotation

Implementation Notes