mmc: add a generic GPIO card-detect helper
This patch adds a primitive helper to support card hotplug detection on platforms, where a GPIO, capable of producing interrupts, is used for detection of card-insertion and -removal events. Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> Signed-off-by: Chris Ball <cjb@laptop.org>
This commit is contained in:
parent
b67e198073
commit
349ab52446
|
@ -7,6 +7,6 @@ mmc_core-y := core.o bus.o host.o \
|
|||
mmc.o mmc_ops.o sd.o sd_ops.o \
|
||||
sdio.o sdio_ops.o sdio_bus.o \
|
||||
sdio_cis.o sdio_io.o sdio_irq.o \
|
||||
quirks.o
|
||||
quirks.o cd-gpio.o
|
||||
|
||||
mmc_core-$(CONFIG_DEBUG_FS) += debugfs.o
|
||||
|
|
74
drivers/mmc/core/cd-gpio.c
Normal file
74
drivers/mmc/core/cd-gpio.c
Normal file
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* Generic GPIO card-detect helper
|
||||
*
|
||||
* Copyright (C) 2011, Guennadi Liakhovetski <g.liakhovetski@gmx.de>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <linux/err.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/mmc/host.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
struct mmc_cd_gpio {
|
||||
unsigned int gpio;
|
||||
char label[0];
|
||||
};
|
||||
|
||||
static irqreturn_t mmc_cd_gpio_irqt(int irq, void *dev_id)
|
||||
{
|
||||
/* Schedule a card detection after a debounce timeout */
|
||||
mmc_detect_change(dev_id, msecs_to_jiffies(100));
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
int mmc_cd_gpio_request(struct mmc_host *host, unsigned int gpio,
|
||||
unsigned int irq, unsigned long flags)
|
||||
{
|
||||
size_t len = strlen(dev_name(host->parent)) + 4;
|
||||
struct mmc_cd_gpio *cd = kmalloc(sizeof(*cd) + len, GFP_KERNEL);
|
||||
int ret;
|
||||
|
||||
if (!cd)
|
||||
return -ENOMEM;
|
||||
|
||||
snprintf(cd->label, len, "%s cd", dev_name(host->parent));
|
||||
|
||||
ret = gpio_request_one(gpio, GPIOF_DIR_IN, cd->label);
|
||||
if (ret < 0)
|
||||
goto egpioreq;
|
||||
|
||||
ret = request_threaded_irq(irq, NULL, mmc_cd_gpio_irqt,
|
||||
flags, cd->label, host);
|
||||
if (ret < 0)
|
||||
goto eirqreq;
|
||||
|
||||
cd->gpio = gpio;
|
||||
host->hotplug.irq = irq;
|
||||
host->hotplug.handler_priv = cd;
|
||||
|
||||
return 0;
|
||||
|
||||
eirqreq:
|
||||
gpio_free(gpio);
|
||||
egpioreq:
|
||||
kfree(cd);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(mmc_cd_gpio_request);
|
||||
|
||||
void mmc_cd_gpio_free(struct mmc_host *host)
|
||||
{
|
||||
struct mmc_cd_gpio *cd = host->hotplug.handler_priv;
|
||||
|
||||
free_irq(host->hotplug.irq, host);
|
||||
gpio_free(cd->gpio);
|
||||
kfree(cd);
|
||||
}
|
||||
EXPORT_SYMBOL(mmc_cd_gpio_free);
|
19
include/linux/mmc/cd-gpio.h
Normal file
19
include/linux/mmc/cd-gpio.h
Normal file
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
* Generic GPIO card-detect helper header
|
||||
*
|
||||
* Copyright (C) 2011, Guennadi Liakhovetski <g.liakhovetski@gmx.de>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#ifndef MMC_CD_GPIO_H
|
||||
#define MMC_CD_GPIO_H
|
||||
|
||||
struct mmc_host;
|
||||
int mmc_cd_gpio_request(struct mmc_host *host, unsigned int gpio,
|
||||
unsigned int irq, unsigned long flags);
|
||||
void mmc_cd_gpio_free(struct mmc_host *host);
|
||||
|
||||
#endif
|
Loading…
Reference in a new issue