blob: e5901c4a52bbd5209b4545c6387cfde9260bf387 [file] [log] [blame]
From e9d1edae3f34367442cab71753a0d1e55cbc439b Mon Sep 17 00:00:00 2001
From: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
Date: Sun, 25 Dec 2011 21:36:02 +0100
Subject: 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>
(cherry picked from commit 349ab52446772a359bc7e7699cae3880d48fa5c9)
Conflicts:
drivers/mmc/core/Makefile
Signed-off-by: Simon Horman <horms@verge.net.au>
---
drivers/mmc/core/Makefile | 1 +
drivers/mmc/core/cd-gpio.c | 74 +++++++++++++++++++++++++++++++++++++++++++++
include/linux/mmc/cd-gpio.h | 19 ++++++++++++
3 files changed, 94 insertions(+)
create mode 100644 drivers/mmc/core/cd-gpio.c
create mode 100644 include/linux/mmc/cd-gpio.h
diff --git a/drivers/mmc/core/Makefile b/drivers/mmc/core/Makefile
index 6395019..274b67c 100644
--- a/drivers/mmc/core/Makefile
+++ b/drivers/mmc/core/Makefile
@@ -9,4 +9,5 @@ mmc_core-y := core.o bus.o host.o \
sdio_cis.o sdio_io.o sdio_irq.o \
quirks.o
+mmc_core-$(CONFIG_GPIOLIB) += cd-gpio.o
mmc_core-$(CONFIG_DEBUG_FS) += debugfs.o
diff --git a/drivers/mmc/core/cd-gpio.c b/drivers/mmc/core/cd-gpio.c
new file mode 100644
index 0000000..082202a
--- /dev/null
+++ b/drivers/mmc/core/cd-gpio.c
@@ -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);
diff --git a/include/linux/mmc/cd-gpio.h b/include/linux/mmc/cd-gpio.h
new file mode 100644
index 0000000..a8e4697
--- /dev/null
+++ b/include/linux/mmc/cd-gpio.h
@@ -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
--
1.7.10.2.565.gbd578b5