All of lore.kernel.org
 help / color / mirror / Atom feed
From: Ben Gardiner <bengardiner@nanometrics.ca>
To: Kevin Hilman <khilman@deeprootsystems.com>,
	davinci-linux-open-source@linux.davincidsp.com,
	linux-input@vger.kernel.org,
	Dmitry Torokhov <dmitry.torokhov@gmail.com>
Cc: linux-kernel@vger.kernel.org,
	Chris Cordahi <christophercordahi@nanometrics.ca>,
	Paul Mundt <lethal@linux-sh.org>, Sekhar Nori <nsekhar@ti.com>,
	Gabor Juhos <juhosg@openwrt.org>,
	Dmitry Torokhov <dmitry.torokhov@gmail.com>,
	Mike Frysinger <vapier@gentoo.org>
Subject: [PATCH v5 1/5] [WIP] input: add input driver for polled GPIO buttons
Date: Wed, 24 Nov 2010 16:59:30 -0500	[thread overview]
Message-ID: <91c06463c8c2afb543c8a22350d2ddd8bf2ef71f.1290635422.git.bengardiner@nanometrics.ca> (raw)
In-Reply-To: <cover.1290635422.git.bengardiner@nanometrics.ca>

From: Gabor Juhos <juhosg@openwrt.org>

The existing gpio-keys driver can be usable only for GPIO lines with
interrupt support. Several devices have buttons connected to a GPIO
line which is not capable to generate interrupts. This patch adds a
new input driver using the generic GPIO layer and the input-polldev
to support such buttons.

(WIP: this version has incorporated into it the changes I suggested in review
of the original patch by Gabor Junos. I am posting it as part of the da850-evm
series in the hopes that the final version produced by Gabor can be
substituted in its place when the time is right. I don't mean to imply that
this version of the patch should be integrated in the final series)

Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Cc: Mike Frysinger <vapier@gentoo.org>
Cc: linux-input@vger.kernel.org
Signed-off-by: Ben Gardiner <bengardiner@nanometrics.ca>
---
 drivers/input/keyboard/Kconfig            |   16 ++
 drivers/input/keyboard/Makefile           |    2 +
 drivers/input/keyboard/gpio_keys_polled.c |  240 +++++++++++++++++++++++++++++
 include/linux/gpio_keys_polled.h          |   26 +++
 4 files changed, 284 insertions(+), 0 deletions(-)
 create mode 100644 drivers/input/keyboard/gpio_keys_polled.c
 create mode 100644 include/linux/gpio_keys_polled.h

diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
index b8c51b9..9648ff4 100644
--- a/drivers/input/keyboard/Kconfig
+++ b/drivers/input/keyboard/Kconfig
@@ -485,4 +485,20 @@ config KEYBOARD_W90P910
 	  To compile this driver as a module, choose M here: the
 	  module will be called w90p910_keypad.
 
+config KEYBOARD_GPIO_POLLED
+	tristate "Polled GPIO buttons"
+	depends on GENERIC_GPIO
+	select INPUT_POLLDEV
+	help
+	  This driver implements support for buttons connected
+	  to GPIO pins of various CPUs (and some other chips).
+
+	  Say Y here if your device has buttons connected
+	  directly to such GPIO pins.  Your board-specific
+	  setup logic must also provide a platform device,
+	  with configuration data saying which GPIOs are used.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called gpio-buttons.
+
 endif
diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile
index a34452e..e6da817 100644
--- a/drivers/input/keyboard/Makefile
+++ b/drivers/input/keyboard/Makefile
@@ -44,3 +44,5 @@ obj-$(CONFIG_KEYBOARD_TNETV107X)	+= tnetv107x-keypad.o
 obj-$(CONFIG_KEYBOARD_TWL4030)		+= twl4030_keypad.o
 obj-$(CONFIG_KEYBOARD_XTKBD)		+= xtkbd.o
 obj-$(CONFIG_KEYBOARD_W90P910)		+= w90p910_keypad.o
+obj-$(CONFIG_KEYBOARD_GPIO_POLLED)	+= gpio_keys_polled.o
+
diff --git a/drivers/input/keyboard/gpio_keys_polled.c b/drivers/input/keyboard/gpio_keys_polled.c
new file mode 100644
index 0000000..390ed93
--- /dev/null
+++ b/drivers/input/keyboard/gpio_keys_polled.c
@@ -0,0 +1,240 @@
+/*
+ *  Driver for buttons on GPIO lines not capable of generating interrupts
+ *
+ *  Copyright (C) 2007-2010 Gabor Juhos <juhosg@openwrt.org>
+ *  Copyright (C) 2010 Nuno Goncalves <nunojpg@gmail.com>
+ *
+ *  This file was based on: /drivers/input/misc/cobalt_btns.c
+ *	Copyright (C) 2007 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *
+ *  also was based on: /drivers/input/keyboard/gpio_keys.c
+ *	Copyright 2005 Phil Blundell
+ *
+ *  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/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/input.h>
+#include <linux/input-polldev.h>
+#include <linux/ioport.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+#include <linux/gpio_keys_polled.h>
+
+#define DRV_NAME	"gpio-keys-polled"
+
+struct gpio_keys_button_data {
+	int last_state;
+	int count;
+	int can_sleep;
+};
+
+struct gpio_keys_polled_dev {
+	struct input_polled_dev *poll_dev;
+	struct gpio_keys_polled_platform_data *pdata;
+	struct gpio_keys_button_data *data;
+};
+
+static void gpio_keys_polled_check_state(struct input_dev *input,
+				      struct gpio_keys_button *button,
+				      struct gpio_keys_button_data *bdata)
+{
+	int state;
+
+	if (bdata->can_sleep)
+		state = !!gpio_get_value_cansleep(button->gpio);
+	else
+		state = !!gpio_get_value(button->gpio);
+
+	if (state != bdata->last_state) {
+		unsigned int type = button->type ?: EV_KEY;
+
+		input_event(input, type, button->code,
+			    !!(state ^ button->active_low));
+		input_sync(input);
+		bdata->count = 0;
+		bdata->last_state = state;
+	}
+}
+
+static void gpio_keys_polled_poll(struct input_polled_dev *dev)
+{
+	struct gpio_keys_polled_dev *bdev = dev->private;
+	struct gpio_keys_polled_platform_data *pdata = bdev->pdata;
+	struct input_dev *input = dev->input;
+	int i, threshold;
+
+	for (i = 0; i < bdev->pdata->nbuttons; i++) {
+		struct gpio_keys_button *button = &pdata->buttons[i];
+		struct gpio_keys_button_data *bdata = &bdev->data[i];
+
+		threshold = round_up(button->debounce_interval,
+				pdata->poll_interval) /
+				pdata->poll_interval;
+		if (bdata->count < threshold)
+			bdata->count++;
+		else
+			gpio_keys_polled_check_state(input, button, bdata);
+
+	}
+}
+
+static int __devinit gpio_keys_polled_probe(struct platform_device *pdev)
+{
+	struct gpio_keys_polled_platform_data *pdata = pdev->dev.platform_data;
+	struct device *dev = &pdev->dev;
+	struct gpio_keys_polled_dev *bdev;
+	struct input_polled_dev *poll_dev;
+	struct input_dev *input;
+	int error;
+	int i;
+
+	if (!pdata)
+		return -ENXIO;
+
+	bdev = kzalloc(sizeof(struct gpio_keys_polled_dev) +
+		       pdata->nbuttons * sizeof(struct gpio_keys_button_data),
+		       GFP_KERNEL);
+	if (!bdev) {
+		dev_err(dev, "no memory for private data\n");
+		return -ENOMEM;
+	}
+
+	bdev->data = (struct gpio_keys_button_data *) &bdev[1];
+
+	poll_dev = input_allocate_polled_device();
+	if (!poll_dev) {
+		dev_err(dev, "no memory for polled device\n");
+		error = -ENOMEM;
+		goto err_free_bdev;
+	}
+
+	poll_dev->private = bdev;
+	poll_dev->poll = gpio_keys_polled_poll;
+	poll_dev->poll_interval = pdata->poll_interval;
+
+	input = poll_dev->input;
+
+	input->evbit[0] = BIT(EV_KEY);
+	input->name = pdev->name;
+	input->phys = DRV_NAME"/input0";
+	input->dev.parent = &pdev->dev;
+
+	input->id.bustype = BUS_HOST;
+	input->id.vendor = 0x0001;
+	input->id.product = 0x0001;
+	input->id.version = 0x0100;
+
+	for (i = 0; i < pdata->nbuttons; i++) {
+		struct gpio_keys_button *button = &pdata->buttons[i];
+		unsigned int gpio = button->gpio;
+		unsigned int type = button->type ?: EV_KEY;
+
+		if (button->wakeup) {
+			dev_err(dev, DRV_NAME " does not support wakeup\n");
+			goto err_free_gpio;
+		}
+
+		error = gpio_request(gpio,
+				     button->desc ? button->desc : DRV_NAME);
+		if (error) {
+			dev_err(dev, "unable to claim gpio %u, err=%d\n",
+				gpio, error);
+			goto err_free_gpio;
+		}
+
+		error = gpio_direction_input(gpio);
+		if (error) {
+			dev_err(dev,
+				"unable to set direction on gpio %u, err=%d\n",
+				gpio, error);
+			goto err_free_gpio;
+		}
+
+		bdev->data[i].can_sleep = gpio_cansleep(gpio);
+		bdev->data[i].last_state = -1;
+
+		input_set_capability(input, type, button->code);
+	}
+
+	bdev->poll_dev = poll_dev;
+	bdev->pdata = pdata;
+	platform_set_drvdata(pdev, bdev);
+
+	error = input_register_polled_device(poll_dev);
+	if (error) {
+		dev_err(dev, "unable to register polled device, err=%d\n",
+			error);
+		goto err_free_gpio;
+	}
+
+	/* report initial state of the buttons */
+	for (i = 0; i < pdata->nbuttons; i++)
+		gpio_keys_polled_check_state(input, &pdata->buttons[i],
+					 &bdev->data[i]);
+
+	return 0;
+
+err_free_gpio:
+	for (i = i - 1; i >= 0; i--)
+		gpio_free(pdata->buttons[i].gpio);
+
+	input_free_polled_device(poll_dev);
+
+err_free_bdev:
+	kfree(bdev);
+
+	platform_set_drvdata(pdev, NULL);
+	return error;
+}
+
+static int __devexit gpio_keys_polled_remove(struct platform_device *pdev)
+{
+	struct gpio_keys_polled_dev *bdev = platform_get_drvdata(pdev);
+	struct gpio_keys_polled_platform_data *pdata = bdev->pdata;
+	int i;
+
+	input_unregister_polled_device(bdev->poll_dev);
+
+	for (i = 0; i < pdata->nbuttons; i++)
+		gpio_free(pdata->buttons[i].gpio);
+
+	input_free_polled_device(bdev->poll_dev);
+
+	kfree(bdev);
+	platform_set_drvdata(pdev, NULL);
+
+	return 0;
+}
+
+static struct platform_driver gpio_keys_polled_driver = {
+	.probe	= gpio_keys_polled_probe,
+	.remove	= __devexit_p(gpio_keys_polled_remove),
+	.driver	= {
+		.name	= DRV_NAME,
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int __init gpio_keys_polled_init(void)
+{
+	return platform_driver_register(&gpio_keys_polled_driver);
+}
+
+static void __exit gpio_keys_polled_exit(void)
+{
+	platform_driver_unregister(&gpio_keys_polled_driver);
+}
+
+module_init(gpio_keys_polled_init);
+module_exit(gpio_keys_polled_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Gabor Juhos <juhosg@openwrt.org>");
+MODULE_DESCRIPTION("Polled GPIO Buttons driver");
diff --git a/include/linux/gpio_keys_polled.h b/include/linux/gpio_keys_polled.h
new file mode 100644
index 0000000..bf7f94a
--- /dev/null
+++ b/include/linux/gpio_keys_polled.h
@@ -0,0 +1,26 @@
+/*
+ *  Definitions for the GPIO buttons interface driver
+ *
+ *  Copyright (C) 2007-2010 Gabor Juhos <juhosg@openwrt.org>
+ *
+ *  This file was based on: /include/linux/gpio_keys.h
+ *	The original gpio_keys.h seems not to have a license.
+ *
+ *  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 _GPIO_BUTTONS_H_
+#define _GPIO_BUTTONS_H_
+
+#include <linux/gpio_keys.h>
+
+struct gpio_keys_polled_platform_data {
+	struct gpio_keys_button *buttons;
+	int	nbuttons;		/* number of buttons */
+	int	poll_interval;		/* polling interval in msecs*/
+};
+
+#endif /* _GPIO_BUTTONS_H_ */
-- 
1.7.0.4


WARNING: multiple messages have this Message-ID (diff)
From: Ben Gardiner <bengardiner@nanometrics.ca>
To: Kevin Hilman <khilman@deeprootsystems.com>,
	davinci-linux-open-source@linux.davincidsp.com,
	linux-input@vger.kernel.org
Cc: linux-kernel@vger.kernel.org,
	Chris Cordahi <christophercordahi@nanometrics.ca>,
	Paul Mundt <lethal@linux-sh.org>, Sekhar Nori <nsekhar@ti.com>,
	Gabor Juhos <juhosg@openwrt.org>,
	Dmitry Torokhov <dmitry.torokhov@gmail.com>,
	Mike Frysinger <vapier@gentoo.org>
Subject: [PATCH v5 1/5] [WIP] input: add input driver for polled GPIO buttons
Date: Wed, 24 Nov 2010 16:59:30 -0500	[thread overview]
Message-ID: <91c06463c8c2afb543c8a22350d2ddd8bf2ef71f.1290635422.git.bengardiner@nanometrics.ca> (raw)
In-Reply-To: <cover.1290635422.git.bengardiner@nanometrics.ca>

From: Gabor Juhos <juhosg@openwrt.org>

The existing gpio-keys driver can be usable only for GPIO lines with
interrupt support. Several devices have buttons connected to a GPIO
line which is not capable to generate interrupts. This patch adds a
new input driver using the generic GPIO layer and the input-polldev
to support such buttons.

(WIP: this version has incorporated into it the changes I suggested in review
of the original patch by Gabor Junos. I am posting it as part of the da850-evm
series in the hopes that the final version produced by Gabor can be
substituted in its place when the time is right. I don't mean to imply that
this version of the patch should be integrated in the final series)

Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Cc: Mike Frysinger <vapier@gentoo.org>
Cc: linux-input@vger.kernel.org
Signed-off-by: Ben Gardiner <bengardiner@nanometrics.ca>
---
 drivers/input/keyboard/Kconfig            |   16 ++
 drivers/input/keyboard/Makefile           |    2 +
 drivers/input/keyboard/gpio_keys_polled.c |  240 +++++++++++++++++++++++++++++
 include/linux/gpio_keys_polled.h          |   26 +++
 4 files changed, 284 insertions(+), 0 deletions(-)
 create mode 100644 drivers/input/keyboard/gpio_keys_polled.c
 create mode 100644 include/linux/gpio_keys_polled.h

diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
index b8c51b9..9648ff4 100644
--- a/drivers/input/keyboard/Kconfig
+++ b/drivers/input/keyboard/Kconfig
@@ -485,4 +485,20 @@ config KEYBOARD_W90P910
 	  To compile this driver as a module, choose M here: the
 	  module will be called w90p910_keypad.
 
+config KEYBOARD_GPIO_POLLED
+	tristate "Polled GPIO buttons"
+	depends on GENERIC_GPIO
+	select INPUT_POLLDEV
+	help
+	  This driver implements support for buttons connected
+	  to GPIO pins of various CPUs (and some other chips).
+
+	  Say Y here if your device has buttons connected
+	  directly to such GPIO pins.  Your board-specific
+	  setup logic must also provide a platform device,
+	  with configuration data saying which GPIOs are used.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called gpio-buttons.
+
 endif
diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile
index a34452e..e6da817 100644
--- a/drivers/input/keyboard/Makefile
+++ b/drivers/input/keyboard/Makefile
@@ -44,3 +44,5 @@ obj-$(CONFIG_KEYBOARD_TNETV107X)	+= tnetv107x-keypad.o
 obj-$(CONFIG_KEYBOARD_TWL4030)		+= twl4030_keypad.o
 obj-$(CONFIG_KEYBOARD_XTKBD)		+= xtkbd.o
 obj-$(CONFIG_KEYBOARD_W90P910)		+= w90p910_keypad.o
+obj-$(CONFIG_KEYBOARD_GPIO_POLLED)	+= gpio_keys_polled.o
+
diff --git a/drivers/input/keyboard/gpio_keys_polled.c b/drivers/input/keyboard/gpio_keys_polled.c
new file mode 100644
index 0000000..390ed93
--- /dev/null
+++ b/drivers/input/keyboard/gpio_keys_polled.c
@@ -0,0 +1,240 @@
+/*
+ *  Driver for buttons on GPIO lines not capable of generating interrupts
+ *
+ *  Copyright (C) 2007-2010 Gabor Juhos <juhosg@openwrt.org>
+ *  Copyright (C) 2010 Nuno Goncalves <nunojpg@gmail.com>
+ *
+ *  This file was based on: /drivers/input/misc/cobalt_btns.c
+ *	Copyright (C) 2007 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *
+ *  also was based on: /drivers/input/keyboard/gpio_keys.c
+ *	Copyright 2005 Phil Blundell
+ *
+ *  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/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/input.h>
+#include <linux/input-polldev.h>
+#include <linux/ioport.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+#include <linux/gpio_keys_polled.h>
+
+#define DRV_NAME	"gpio-keys-polled"
+
+struct gpio_keys_button_data {
+	int last_state;
+	int count;
+	int can_sleep;
+};
+
+struct gpio_keys_polled_dev {
+	struct input_polled_dev *poll_dev;
+	struct gpio_keys_polled_platform_data *pdata;
+	struct gpio_keys_button_data *data;
+};
+
+static void gpio_keys_polled_check_state(struct input_dev *input,
+				      struct gpio_keys_button *button,
+				      struct gpio_keys_button_data *bdata)
+{
+	int state;
+
+	if (bdata->can_sleep)
+		state = !!gpio_get_value_cansleep(button->gpio);
+	else
+		state = !!gpio_get_value(button->gpio);
+
+	if (state != bdata->last_state) {
+		unsigned int type = button->type ?: EV_KEY;
+
+		input_event(input, type, button->code,
+			    !!(state ^ button->active_low));
+		input_sync(input);
+		bdata->count = 0;
+		bdata->last_state = state;
+	}
+}
+
+static void gpio_keys_polled_poll(struct input_polled_dev *dev)
+{
+	struct gpio_keys_polled_dev *bdev = dev->private;
+	struct gpio_keys_polled_platform_data *pdata = bdev->pdata;
+	struct input_dev *input = dev->input;
+	int i, threshold;
+
+	for (i = 0; i < bdev->pdata->nbuttons; i++) {
+		struct gpio_keys_button *button = &pdata->buttons[i];
+		struct gpio_keys_button_data *bdata = &bdev->data[i];
+
+		threshold = round_up(button->debounce_interval,
+				pdata->poll_interval) /
+				pdata->poll_interval;
+		if (bdata->count < threshold)
+			bdata->count++;
+		else
+			gpio_keys_polled_check_state(input, button, bdata);
+
+	}
+}
+
+static int __devinit gpio_keys_polled_probe(struct platform_device *pdev)
+{
+	struct gpio_keys_polled_platform_data *pdata = pdev->dev.platform_data;
+	struct device *dev = &pdev->dev;
+	struct gpio_keys_polled_dev *bdev;
+	struct input_polled_dev *poll_dev;
+	struct input_dev *input;
+	int error;
+	int i;
+
+	if (!pdata)
+		return -ENXIO;
+
+	bdev = kzalloc(sizeof(struct gpio_keys_polled_dev) +
+		       pdata->nbuttons * sizeof(struct gpio_keys_button_data),
+		       GFP_KERNEL);
+	if (!bdev) {
+		dev_err(dev, "no memory for private data\n");
+		return -ENOMEM;
+	}
+
+	bdev->data = (struct gpio_keys_button_data *) &bdev[1];
+
+	poll_dev = input_allocate_polled_device();
+	if (!poll_dev) {
+		dev_err(dev, "no memory for polled device\n");
+		error = -ENOMEM;
+		goto err_free_bdev;
+	}
+
+	poll_dev->private = bdev;
+	poll_dev->poll = gpio_keys_polled_poll;
+	poll_dev->poll_interval = pdata->poll_interval;
+
+	input = poll_dev->input;
+
+	input->evbit[0] = BIT(EV_KEY);
+	input->name = pdev->name;
+	input->phys = DRV_NAME"/input0";
+	input->dev.parent = &pdev->dev;
+
+	input->id.bustype = BUS_HOST;
+	input->id.vendor = 0x0001;
+	input->id.product = 0x0001;
+	input->id.version = 0x0100;
+
+	for (i = 0; i < pdata->nbuttons; i++) {
+		struct gpio_keys_button *button = &pdata->buttons[i];
+		unsigned int gpio = button->gpio;
+		unsigned int type = button->type ?: EV_KEY;
+
+		if (button->wakeup) {
+			dev_err(dev, DRV_NAME " does not support wakeup\n");
+			goto err_free_gpio;
+		}
+
+		error = gpio_request(gpio,
+				     button->desc ? button->desc : DRV_NAME);
+		if (error) {
+			dev_err(dev, "unable to claim gpio %u, err=%d\n",
+				gpio, error);
+			goto err_free_gpio;
+		}
+
+		error = gpio_direction_input(gpio);
+		if (error) {
+			dev_err(dev,
+				"unable to set direction on gpio %u, err=%d\n",
+				gpio, error);
+			goto err_free_gpio;
+		}
+
+		bdev->data[i].can_sleep = gpio_cansleep(gpio);
+		bdev->data[i].last_state = -1;
+
+		input_set_capability(input, type, button->code);
+	}
+
+	bdev->poll_dev = poll_dev;
+	bdev->pdata = pdata;
+	platform_set_drvdata(pdev, bdev);
+
+	error = input_register_polled_device(poll_dev);
+	if (error) {
+		dev_err(dev, "unable to register polled device, err=%d\n",
+			error);
+		goto err_free_gpio;
+	}
+
+	/* report initial state of the buttons */
+	for (i = 0; i < pdata->nbuttons; i++)
+		gpio_keys_polled_check_state(input, &pdata->buttons[i],
+					 &bdev->data[i]);
+
+	return 0;
+
+err_free_gpio:
+	for (i = i - 1; i >= 0; i--)
+		gpio_free(pdata->buttons[i].gpio);
+
+	input_free_polled_device(poll_dev);
+
+err_free_bdev:
+	kfree(bdev);
+
+	platform_set_drvdata(pdev, NULL);
+	return error;
+}
+
+static int __devexit gpio_keys_polled_remove(struct platform_device *pdev)
+{
+	struct gpio_keys_polled_dev *bdev = platform_get_drvdata(pdev);
+	struct gpio_keys_polled_platform_data *pdata = bdev->pdata;
+	int i;
+
+	input_unregister_polled_device(bdev->poll_dev);
+
+	for (i = 0; i < pdata->nbuttons; i++)
+		gpio_free(pdata->buttons[i].gpio);
+
+	input_free_polled_device(bdev->poll_dev);
+
+	kfree(bdev);
+	platform_set_drvdata(pdev, NULL);
+
+	return 0;
+}
+
+static struct platform_driver gpio_keys_polled_driver = {
+	.probe	= gpio_keys_polled_probe,
+	.remove	= __devexit_p(gpio_keys_polled_remove),
+	.driver	= {
+		.name	= DRV_NAME,
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int __init gpio_keys_polled_init(void)
+{
+	return platform_driver_register(&gpio_keys_polled_driver);
+}
+
+static void __exit gpio_keys_polled_exit(void)
+{
+	platform_driver_unregister(&gpio_keys_polled_driver);
+}
+
+module_init(gpio_keys_polled_init);
+module_exit(gpio_keys_polled_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Gabor Juhos <juhosg@openwrt.org>");
+MODULE_DESCRIPTION("Polled GPIO Buttons driver");
diff --git a/include/linux/gpio_keys_polled.h b/include/linux/gpio_keys_polled.h
new file mode 100644
index 0000000..bf7f94a
--- /dev/null
+++ b/include/linux/gpio_keys_polled.h
@@ -0,0 +1,26 @@
+/*
+ *  Definitions for the GPIO buttons interface driver
+ *
+ *  Copyright (C) 2007-2010 Gabor Juhos <juhosg@openwrt.org>
+ *
+ *  This file was based on: /include/linux/gpio_keys.h
+ *	The original gpio_keys.h seems not to have a license.
+ *
+ *  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 _GPIO_BUTTONS_H_
+#define _GPIO_BUTTONS_H_
+
+#include <linux/gpio_keys.h>
+
+struct gpio_keys_polled_platform_data {
+	struct gpio_keys_button *buttons;
+	int	nbuttons;		/* number of buttons */
+	int	poll_interval;		/* polling interval in msecs*/
+};
+
+#endif /* _GPIO_BUTTONS_H_ */
-- 
1.7.0.4

  reply	other threads:[~2010-11-24 21:59 UTC|newest]

Thread overview: 104+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <cover.1289835508.git.bengardiner@nanometrics.ca>
     [not found] ` <8891d088e9a16122c780f737b1b1ec35f9517c36.1289835508.git.bengardiner@nanometrics.ca>
2010-11-16  9:36   ` [PATCH 1/4] input: gpio_keys: polling mode support Paul Mundt
2010-11-16 18:28     ` Ben Gardiner
2010-11-16 19:39 ` [PATCH v2 0/4] da850-evm: add gpio-{keys,leds} for UI and BB expanders Ben Gardiner
2010-11-16 19:39   ` [PATCH v2 0/4] da850-evm: add gpio-{keys, leds} " Ben Gardiner
2010-11-16 19:39   ` [PATCH v2 1/4] input: gpio_keys: polling mode support Ben Gardiner
2010-11-16 19:39   ` [PATCH v2 2/4] da850-evm: add UI Expander pushbuttons Ben Gardiner
2010-11-19  9:58     ` Nori, Sekhar
2010-11-19  9:58       ` Nori, Sekhar
2010-11-19 15:38       ` Ben Gardiner
2010-11-19 15:38         ` Ben Gardiner
2010-11-22 11:49         ` Nori, Sekhar
2010-11-22 11:49           ` Nori, Sekhar
2010-11-22 13:50           ` Ben Gardiner
2010-11-22 13:50             ` Ben Gardiner
2010-11-23 12:38             ` Nori, Sekhar
2010-11-23 12:38               ` Nori, Sekhar
2010-11-23 13:29               ` Ben Gardiner
2010-11-23 13:29                 ` Ben Gardiner
2010-11-23 15:48               ` Kevin Hilman
2010-11-23 15:48                 ` Kevin Hilman
2010-11-23 17:58                 ` Ben Gardiner
2010-11-23 17:58                   ` Ben Gardiner
2010-11-24  6:09                 ` Paul Mundt
2010-11-24  6:09                   ` Paul Mundt
2010-11-24 17:17                   ` Ben Gardiner
2010-11-24 17:17                     ` Ben Gardiner
2010-11-16 19:39   ` [PATCH v2 3/4] da850-evm: extract defines for SEL{A,B,C} pins in UI expander Ben Gardiner
2010-11-16 19:39     ` [PATCH v2 3/4] da850-evm: extract defines for SEL{A, B, C} " Ben Gardiner
2010-11-19 11:19     ` Nori, Sekhar
2010-11-19 11:19       ` Nori, Sekhar
2010-11-19 15:38       ` Ben Gardiner
2010-11-19 15:38         ` Ben Gardiner
2010-11-16 19:39   ` [PATCH v2 4/4] da850-evm: add baseboard UI expander buttons, switches and LEDs Ben Gardiner
2010-11-19 12:14     ` Nori, Sekhar
2010-11-19 12:14       ` Nori, Sekhar
2010-11-19 15:40       ` Ben Gardiner
2010-11-19 15:40         ` Ben Gardiner
2010-11-19 17:02         ` Dmitry Torokhov
2010-11-19 17:02           ` Dmitry Torokhov
2010-11-19 17:15           ` Ben Gardiner
2010-11-19 17:15             ` Ben Gardiner
2010-11-22 12:00         ` Nori, Sekhar
2010-11-22 12:00           ` Nori, Sekhar
2010-11-22 14:15           ` Ben Gardiner
2010-11-22 14:15             ` Ben Gardiner
2010-11-23 12:42             ` Nori, Sekhar
2010-11-23 12:42               ` Nori, Sekhar
2010-11-23 13:32               ` Ben Gardiner
2010-11-23 13:32                 ` Ben Gardiner
2010-11-19 21:37   ` [PATCH v3 0/4] da850-evm: add gpio-{keys,leds} for UI and BB expanders Ben Gardiner
2010-11-19 21:37     ` [PATCH v3 1/4] input: gpio_keys: polling mode support Ben Gardiner
2010-11-19 21:37     ` [PATCH v3 2/4] da850-evm: add UI Expander pushbuttons Ben Gardiner
2010-11-19 21:37     ` [PATCH v3 3/4] da850-evm: extract defines for SEL{A,B,C} pins in UI expander Ben Gardiner
2010-11-19 21:41       ` [PATCH v3 3/4] da850-evm: extract defines for SEL{A, B, C} " Victor Rodriguez
2010-11-19 21:41         ` Victor Rodriguez
2010-11-19 22:25         ` Ben Gardiner
2010-11-19 22:25           ` Ben Gardiner
2010-11-19 21:37     ` [PATCH v3 4/4] da850-evm: add baseboard GPIO expander buttons, switches and LEDs Ben Gardiner
2010-11-23 19:40     ` [PATCH v4 0/5] da850-evm: add gpio-{keys,leds} for UI and BB expanders Ben Gardiner
2010-11-23 19:40       ` [PATCH v4 1/5] input: gpio_keys: polling mode support Ben Gardiner
2010-11-23 19:40         ` Ben Gardiner
2010-11-23 19:40       ` [PATCH v4 2/5] da850-evm: add UI Expander pushbuttons Ben Gardiner
2010-11-23 19:40         ` Ben Gardiner
2010-11-24 13:16         ` Nori, Sekhar
2010-11-24 13:16           ` Nori, Sekhar
2010-11-24 17:16           ` Ben Gardiner
2010-11-24 17:16             ` Ben Gardiner
2010-11-23 19:40       ` [PATCH v4 3/5] da850-evm: extract defines for SEL{A,B,C} pins in UI expander Ben Gardiner
2010-11-23 19:40       ` [PATCH v4 4/5] da850-evm: add baseboard GPIO expander buttons, switches and LEDs Ben Gardiner
2010-11-23 19:41       ` [PATCH v4 5/5] da850-evm: KEYBOARD_GPIO and INPUT_POLLDEV Kconfig conditionals Ben Gardiner
2010-11-23 19:41         ` Ben Gardiner
2010-11-24 21:59       ` [PATCH v5 0/5] da850-evm: add gpio-{keys,leds} for UI and BB expanders Ben Gardiner
2010-11-24 21:59         ` Ben Gardiner [this message]
2010-11-24 21:59           ` [PATCH v5 1/5] [WIP] input: add input driver for polled GPIO buttons Ben Gardiner
2010-11-24 21:59         ` [PATCH v5 2/5] da850-evm: add UI Expander pushbuttons Ben Gardiner
2010-11-24 21:59           ` Ben Gardiner
2010-11-24 21:59         ` [PATCH v5 3/5] da850-evm: extract defines for SEL{A,B,C} pins in UI expander Ben Gardiner
2010-11-24 21:59         ` [PATCH v5 4/5] da850-evm: add baseboard GPIO expander buttons, switches and LEDs Ben Gardiner
2010-11-24 21:59         ` [PATCH v5 5/5] da850-evm: KEYBOARD_GPIO_POLLED Kconfig conditional Ben Gardiner
2010-11-24 21:59           ` Ben Gardiner
2010-12-09 21:51         ` [PATCH v6 0/5] da850-evm: add gpio-{keys,leds} for UI and BB expanders Ben Gardiner
2010-12-09 21:51           ` [PATCH v6 1/5] Input: add input driver for polled GPIO buttons Ben Gardiner
2010-12-09 21:51             ` Ben Gardiner
2010-12-10 15:50             ` Kevin Hilman
2010-12-09 21:51           ` [PATCH v6 2/5] da850-evm: add UI Expander pushbuttons Ben Gardiner
2010-12-09 21:51             ` Ben Gardiner
2010-12-09 21:51           ` [PATCH v6 3/5] da850-evm: extract defines for SEL{A,B,C} pins in UI expander Ben Gardiner
2010-12-09 21:51           ` [PATCH v6 4/5] da850-evm: add baseboard GPIO expander buttons, switches and LEDs Ben Gardiner
2010-12-09 21:51           ` [PATCH v6 5/5] da850-evm: KEYBOARD_GPIO_POLLED Kconfig conditional Ben Gardiner
2010-12-09 21:51             ` Ben Gardiner
2010-12-10 16:16           ` [PATCH v6 0/5] da850-evm: add gpio-{keys,leds} for UI and BB expanders Kevin Hilman
2010-12-10 16:33             ` Ben Gardiner
2010-12-10 16:33               ` Ben Gardiner
2010-12-11  0:04               ` Kevin Hilman
2010-12-11  0:04                 ` Kevin Hilman
2010-12-13 17:02               ` Ben Gardiner
2010-12-13 17:02                 ` Ben Gardiner
2010-12-13 21:53                 ` Kevin Hilman
2010-12-13 21:53                   ` [PATCH v6 0/5] da850-evm: add gpio-{keys, leds} " Kevin Hilman
2010-12-14  4:31                   ` [PATCH v6 0/5] da850-evm: add gpio-{keys,leds} " Ben Gardiner
2010-12-14  4:31                     ` Ben Gardiner
2010-12-14 16:17                   ` Ben Gardiner
2010-12-14 17:10                     ` Kevin Hilman
2010-12-17 15:15                       ` Ben Gardiner

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=91c06463c8c2afb543c8a22350d2ddd8bf2ef71f.1290635422.git.bengardiner@nanometrics.ca \
    --to=bengardiner@nanometrics.ca \
    --cc=christophercordahi@nanometrics.ca \
    --cc=davinci-linux-open-source@linux.davincidsp.com \
    --cc=dmitry.torokhov@gmail.com \
    --cc=juhosg@openwrt.org \
    --cc=khilman@deeprootsystems.com \
    --cc=lethal@linux-sh.org \
    --cc=linux-input@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=nsekhar@ti.com \
    --cc=vapier@gentoo.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.