[PATCH] Add Cobalt button interface driver support

STALE6900d

11 messages, 3 authors, 2007-09-18 · open the first message on its own page

[PATCH] Add Cobalt button interface driver support

From: Yoichi Yuasa <hidden>
Date: 2007-02-16 04:11:27

Hi,

This patch adds support for the back panel buttons on Cobalt server.
It's tested on the Cobalt Qube2.

Yoichi

Signed-off-by: Yoichi Yuasa <redacted>

diff -pruN -X mips/Documentation/dontdiff mips-orig/drivers/input/misc/Kconfig mips/drivers/input/misc/Kconfig
--- mips-orig/drivers/input/misc/Kconfig	2007-02-14 15:35:30.566862000 +0900
+++ mips/drivers/input/misc/Kconfig	2007-02-15 17:20:28.721985250 +0900
@@ -89,4 +89,10 @@ config HP_SDC_RTC
 	  Say Y here if you want to support the built-in real time clock
 	  of the HP SDC controller.
 
+config INPUT_COBALT_BTNS
+	tristate "Cobalt button interface"       
+	depends on MIPS_COBALT
+	help
+	  Say Y here if you want to support MIPS Cobalt button interface.
+
 endif
diff -pruN -X mips/Documentation/dontdiff mips-orig/drivers/input/misc/Makefile mips/drivers/input/misc/Makefile
--- mips-orig/drivers/input/misc/Makefile	2007-02-14 15:35:30.566862000 +0900
+++ mips/drivers/input/misc/Makefile	2007-02-15 11:55:30.856042500 +0900
@@ -12,3 +12,4 @@ obj-$(CONFIG_INPUT_WISTRON_BTNS)	+= wist
 obj-$(CONFIG_INPUT_ATLAS_BTNS)		+= atlas_btns.o
 obj-$(CONFIG_HP_SDC_RTC)		+= hp_sdc_rtc.o
 obj-$(CONFIG_INPUT_IXP4XX_BEEPER)	+= ixp4xx-beeper.o
+obj-$(CONFIG_INPUT_COBALT_BTNS)		+= cobalt_btns.o
diff -pruN -X mips/Documentation/dontdiff mips-orig/drivers/input/misc/cobalt_btns.c mips/drivers/input/misc/cobalt_btns.c
--- mips-orig/drivers/input/misc/cobalt_btns.c	1970-01-01 09:00:00.000000000 +0900
+++ mips/drivers/input/misc/cobalt_btns.c	2007-02-15 17:17:31.550912750 +0900
@@ -0,0 +1,199 @@
+/*
+ *  Cobalt button interface driver.
+ *
+ *  Copyright (C) 2007  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+#include <linux/init.h>
+#include <linux/input.h>
+#include <linux/ioport.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/jiffies.h>
+#include <linux/timer.h>
+
+#include <asm/param.h>
+
+#define BUTTONS_POLL_FREQUENCY	30
+#define BUTTONS_COUNT_THRESHOLD	3
+#define BUTTONS_STATUS_MASK	0xfe000000
+
+struct buttons_dev {
+	struct input_dev *input;
+	void __iomem *reg;
+};
+
+struct buttons_map {
+	uint32_t	mask;
+	int		keycode;
+	int		count;
+};
+
+static struct buttons_map buttons_map[] = {
+	{ 0x02000000, KEY_RESTART, },
+	{ 0x04000000, KEY_LEFT, },
+	{ 0x08000000, KEY_UP, },
+	{ 0x10000000, KEY_DOWN, },
+	{ 0x20000000, KEY_RIGHT, },
+	{ 0x40000000, KEY_ENTER, },
+	{ 0x80000000, KEY_SELECT, },
+};
+
+static struct resource cobalt_buttons_resource = {
+	.start	= 0x1d000000,
+	.end	= 0x1d000003,
+	.flags	= IORESOURCE_MEM,
+};
+
+static struct platform_device cobalt_buttons_device = {
+	.name		= "Cobalt buttons",
+	.num_resources	= 1,
+	.resource	= &cobalt_buttons_resource,
+};
+
+static struct timer_list buttons_timer;
+
+static void handle_buttons(unsigned long data)
+{
+	struct buttons_map *button = buttons_map;
+	struct buttons_dev *bdev;
+	uint32_t status;
+	int i;
+
+	bdev = (struct buttons_dev *)data;
+	status = readl(bdev->reg);
+	status = ~status & BUTTONS_STATUS_MASK;
+
+	for (i = 0; i < ARRAY_SIZE(buttons_map); i++) {
+		if (status & button->mask) {
+			button->count++;
+		} else {
+			if (button->count >= BUTTONS_COUNT_THRESHOLD) {
+				input_report_key(bdev->input, button->keycode, 0);
+				input_sync(bdev->input);
+			}
+			button->count = 0;
+		}
+
+		if (button->count == BUTTONS_COUNT_THRESHOLD) {
+			input_report_key(bdev->input, button->keycode, 1);
+			input_sync(bdev->input);
+		}
+
+		button++;
+	}
+
+	mod_timer(&buttons_timer, jiffies + HZ / BUTTONS_POLL_FREQUENCY);
+}
+
+static int __init cobalt_buttons_probe(struct platform_device *pdev)
+{
+	struct buttons_dev *bdev;
+	struct input_dev *input;
+	struct resource *res;
+	int retval, i;
+
+	bdev = kzalloc(sizeof(struct buttons_dev), GFP_KERNEL);
+	if (!bdev)
+		return -ENOMEM;
+
+	input = input_allocate_device();
+	if (!input) {
+		kfree(bdev);
+		return -ENOMEM;
+	}
+
+	input->name = "Cobalt buttons";
+	input->phys = "cobalt/input0";
+	input->id.bustype = BUS_HOST;
+	input->cdev.dev = &pdev->dev;
+
+	input->evbit[0] = BIT(EV_KEY);
+	for (i = 0; i < ARRAY_SIZE(buttons_map); i++) {
+		set_bit(buttons_map[i].keycode, input->keybit);
+		buttons_map[i].count = 0;
+	}
+
+	retval = input_register_device(input);
+	if (retval < 0) {
+		input_free_device(input);
+		kfree(bdev);
+		return retval;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		input_unregister_device(input);
+		kfree(bdev);
+		return -EBUSY;
+	}
+
+	bdev->input = input;
+	bdev->reg = ioremap(res->start, res->end - res->start + 1);
+	dev_set_drvdata(&pdev->dev, bdev);
+
+	setup_timer(&buttons_timer, handle_buttons, (unsigned long)bdev);
+	mod_timer(&buttons_timer, jiffies + HZ / BUTTONS_POLL_FREQUENCY);
+
+	return retval;
+}
+
+static int __devexit cobalt_buttons_remove(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct buttons_dev *bdev = dev_get_drvdata(dev);
+
+	del_timer(&buttons_timer);
+	input_unregister_device(bdev->input);
+	iounmap(bdev->reg);
+	kfree(bdev);
+	dev_set_drvdata(dev, NULL);
+
+	return 0;
+}
+
+static struct platform_driver cobalt_buttons_driver = {
+	.probe	= cobalt_buttons_probe,
+	.remove	= __devexit_p(cobalt_buttons_remove),
+	.driver	= {
+		.name	= "Cobalt buttons",
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int __init cobalt_buttons_init(void)
+{
+	int retval;
+
+	retval = platform_device_register(&cobalt_buttons_device);
+	if (retval < 0)
+		return retval;
+
+	retval = platform_driver_register(&cobalt_buttons_driver);
+	if (retval < 0)
+		platform_device_unregister(&cobalt_buttons_device);
+
+	return retval;
+}
+
+static void __exit cobalt_buttons_exit(void)
+{
+	platform_driver_unregister(&cobalt_buttons_driver);
+	platform_device_unregister(&cobalt_buttons_device);
+}
+
+module_init(cobalt_buttons_init);
+module_exit(cobalt_buttons_exit);

Re: [PATCH] Add Cobalt button interface driver support

From: Dmitry Torokhov <hidden>
Date: 2007-02-16 04:09:47

On Thursday 15 February 2007 22:36, Yoichi Yuasa wrote:
Hi,

This patch adds support for the back panel buttons on Cobalt server.
It's tested on the Cobalt Qube2.
Hi,

Thank you for your patch. Couple of comments:
+
+		button++;
+	}
+
+	mod_timer(&buttons_timer, jiffies + HZ / BUTTONS_POLL_FREQUENCY);
May I suggest using msecs_to_jiffies() to avoid direct computations on HZ?
+
+	bdev->input = input;
+	bdev->reg = ioremap(res->start, res->end - res->start + 1);
+	dev_set_drvdata(&pdev->dev, bdev);
+
+	setup_timer(&buttons_timer, handle_buttons, (unsigned long)bdev);
+	mod_timer(&buttons_timer, jiffies + HZ / BUTTONS_POLL_FREQUENCY);
Please implement cobalt_buttons_open() and cobalt_buttons_close() methods
and start/stop timer from there - there is no point in polling hardware
if noone is listening to the events.
+
+	return retval;
+}
+
+static int __devexit cobalt_buttons_remove(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct buttons_dev *bdev = dev_get_drvdata(dev);
+
+	del_timer(&buttons_timer);
del_timer_sync? Is there any possibility it may run SMP?
+
+static void __exit cobalt_buttons_exit(void)
+{
+	platform_driver_unregister(&cobalt_buttons_driver);
You are not allowed to unregister statically allocated devices -
if there are references left and your module goes away then
these references become invalid and kernel goes boom.

Please convert to platform_device_alloc/platform_device_add.

Is there a point of moving platform device creation code into
platform-specific code? Is there a possibility of this driver
being used elsewhere?
+	platform_device_unregister(&cobalt_buttons_device);
+}
+
+module_init(cobalt_buttons_init);
+module_exit(cobalt_buttons_exit);
-- 
Dmitry

Re: [PATCH] Add Cobalt button interface driver support

From: Yoichi Yuasa <hidden>
Date: 2007-02-16 08:15:29

Hi,

Thank you for your comments.

On Thu, 15 Feb 2007 23:09:43 -0500
Dmitry Torokhov [off-list ref] wrote:
On Thursday 15 February 2007 22:36, Yoichi Yuasa wrote:
quoted
Hi,

This patch adds support for the back panel buttons on Cobalt server.
It's tested on the Cobalt Qube2.
Hi,

Thank you for your patch. Couple of comments:
quoted
+
+		button++;
+	}
+
+	mod_timer(&buttons_timer, jiffies + HZ / BUTTONS_POLL_FREQUENCY);
May I suggest using msecs_to_jiffies() to avoid direct computations on HZ?
OK, I updated it.
quoted
+
+	bdev->input = input;
+	bdev->reg = ioremap(res->start, res->end - res->start + 1);
+	dev_set_drvdata(&pdev->dev, bdev);
+
+	setup_timer(&buttons_timer, handle_buttons, (unsigned long)bdev);
+	mod_timer(&buttons_timer, jiffies + HZ / BUTTONS_POLL_FREQUENCY);
Please implement cobalt_buttons_open() and cobalt_buttons_close() methods
and start/stop timer from there - there is no point in polling hardware
if noone is listening to the events.
I updated it too.
quoted
+static int __devexit cobalt_buttons_remove(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct buttons_dev *bdev = dev_get_drvdata(dev);
+
+	del_timer(&buttons_timer);
del_timer_sync? Is there any possibility it may run SMP?
Cobalt server doesn't support SMP. but there is no problem.
I updated it.
quoted
+static void __exit cobalt_buttons_exit(void)
+{
+	platform_driver_unregister(&cobalt_buttons_driver);
You are not allowed to unregister statically allocated devices -
if there are references left and your module goes away then
these references become invalid and kernel goes boom.

Please convert to platform_device_alloc/platform_device_add.
I updated it.
Is there a point of moving platform device creation code into
platform-specific code? Is there a possibility of this driver
being used elsewhere?
No it isn't. 

Yoichi

Signed-off-by: Yoichi Yuasa <redacted>

diff -pruN -X mips/Documentation/dontdiff mips-orig/drivers/input/misc/Kconfig mips/drivers/input/misc/Kconfig
--- mips-orig/drivers/input/misc/Kconfig	2007-02-14 15:35:30.566862000 +0900
+++ mips/drivers/input/misc/Kconfig	2007-02-15 17:20:28.721985250 +0900
@@ -89,4 +89,10 @@ config HP_SDC_RTC
 	  Say Y here if you want to support the built-in real time clock
 	  of the HP SDC controller.
 
+config INPUT_COBALT_BTNS
+	tristate "Cobalt button interface"       
+	depends on MIPS_COBALT
+	help
+	  Say Y here if you want to support MIPS Cobalt button interface.
+
 endif
diff -pruN -X mips/Documentation/dontdiff mips-orig/drivers/input/misc/Makefile mips/drivers/input/misc/Makefile
--- mips-orig/drivers/input/misc/Makefile	2007-02-14 15:35:30.566862000 +0900
+++ mips/drivers/input/misc/Makefile	2007-02-15 11:55:30.856042500 +0900
@@ -12,3 +12,4 @@ obj-$(CONFIG_INPUT_WISTRON_BTNS)	+= wist
 obj-$(CONFIG_INPUT_ATLAS_BTNS)		+= atlas_btns.o
 obj-$(CONFIG_HP_SDC_RTC)		+= hp_sdc_rtc.o
 obj-$(CONFIG_INPUT_IXP4XX_BEEPER)	+= ixp4xx-beeper.o
+obj-$(CONFIG_INPUT_COBALT_BTNS)		+= cobalt_btns.o
diff -pruN -X mips/Documentation/dontdiff mips-orig/drivers/input/misc/cobalt_btns.c mips/drivers/input/misc/cobalt_btns.c
--- mips-orig/drivers/input/misc/cobalt_btns.c	1970-01-01 09:00:00.000000000 +0900
+++ mips/drivers/input/misc/cobalt_btns.c	2007-02-16 16:09:48.857365000 +0900
@@ -0,0 +1,233 @@
+/*
+ *  Cobalt button interface driver.
+ *
+ *  Copyright (C) 2007  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+#include <linux/init.h>
+#include <linux/input.h>
+#include <linux/ioport.h>
+#include <linux/miscdevice.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/jiffies.h>
+#include <linux/timer.h>
+
+#include <asm/param.h>
+
+#define BUTTONS_POLL_INTERVAL	30	/* msec */
+#define BUTTONS_COUNT_THRESHOLD	3
+#define BUTTONS_STATUS_MASK	0xfe000000
+
+struct buttons_dev {
+	struct input_dev *input;
+	void __iomem *reg;
+};
+
+struct buttons_map {
+	uint32_t	mask;
+	int		keycode;
+	int		count;
+};
+
+static struct buttons_map buttons_map[] = {
+	{ 0x02000000, KEY_RESTART, },
+	{ 0x04000000, KEY_LEFT, },
+	{ 0x08000000, KEY_UP, },
+	{ 0x10000000, KEY_DOWN, },
+	{ 0x20000000, KEY_RIGHT, },
+	{ 0x40000000, KEY_ENTER, },
+	{ 0x80000000, KEY_SELECT, },
+};
+
+static struct resource cobalt_buttons_resource __initdata = {
+	.start	= 0x1d000000,
+	.end	= 0x1d000003,
+	.flags	= IORESOURCE_MEM,
+};
+
+static struct platform_device *cobalt_buttons_device;
+
+static struct timer_list buttons_timer;
+
+static void handle_buttons(unsigned long data)
+{
+	struct buttons_map *button = buttons_map;
+	struct buttons_dev *bdev;
+	uint32_t status;
+	int i;
+
+	bdev = (struct buttons_dev *)data;
+	status = readl(bdev->reg);
+	status = ~status & BUTTONS_STATUS_MASK;
+
+	for (i = 0; i < ARRAY_SIZE(buttons_map); i++) {
+		if (status & button->mask) {
+			button->count++;
+		} else {
+			if (button->count >= BUTTONS_COUNT_THRESHOLD) {
+				input_report_key(bdev->input, button->keycode, 0);
+				input_sync(bdev->input);
+			}
+			button->count = 0;
+		}
+
+		if (button->count == BUTTONS_COUNT_THRESHOLD) {
+			input_report_key(bdev->input, button->keycode, 1);
+			input_sync(bdev->input);
+		}
+
+		button++;
+	}
+
+	mod_timer(&buttons_timer, jiffies + msecs_to_jiffies(BUTTONS_POLL_INTERVAL));
+}
+
+static int cobalt_buttons_open(struct inode *inode, struct file *file)
+{
+	buttons_timer.expires = jiffies + msecs_to_jiffies(BUTTONS_POLL_INTERVAL);
+	add_timer(&buttons_timer);
+
+	return nonseekable_open(inode, file);
+
+}
+
+static int cobalt_buttons_release(struct inode *inode, struct file *file)
+{
+	return del_timer_sync(&buttons_timer);
+}
+
+static const struct file_operations cobalt_buttons_fops = {
+	.owner		= THIS_MODULE,
+	.open		= cobalt_buttons_open,
+	.release	= cobalt_buttons_release,
+	.llseek		= no_llseek,
+};
+
+static struct miscdevice cobalt_buttons_miscdevice = {
+	.minor	= MISC_DYNAMIC_MINOR,
+	.name	= "Cobalt buttons",
+	.fops	= &cobalt_buttons_fops,
+};
+
+static int __init cobalt_buttons_probe(struct platform_device *pdev)
+{
+	struct buttons_dev *bdev;
+	struct input_dev *input;
+	struct resource *res;
+	int retval, i;
+
+	bdev = kzalloc(sizeof(struct buttons_dev), GFP_KERNEL);
+	if (!bdev)
+		return -ENOMEM;
+
+	input = input_allocate_device();
+	if (!input) {
+		kfree(bdev);
+		return -ENOMEM;
+	}
+
+	input->name = "Cobalt buttons";
+	input->phys = "cobalt/input0";
+	input->id.bustype = BUS_HOST;
+	input->cdev.dev = &pdev->dev;
+
+	input->evbit[0] = BIT(EV_KEY);
+	for (i = 0; i < ARRAY_SIZE(buttons_map); i++) {
+		set_bit(buttons_map[i].keycode, input->keybit);
+		buttons_map[i].count = 0;
+	}
+
+	retval = input_register_device(input);
+	if (retval < 0) {
+		input_free_device(input);
+		kfree(bdev);
+		return retval;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		input_unregister_device(input);
+		kfree(bdev);
+		return -EBUSY;
+	}
+
+	bdev->input = input;
+	bdev->reg = ioremap(res->start, res->end - res->start + 1);
+	dev_set_drvdata(&pdev->dev, bdev);
+
+	setup_timer(&buttons_timer, handle_buttons, (unsigned long)bdev);
+
+	retval = misc_register(&cobalt_buttons_miscdevice);
+	if (retval < 0) {
+		del_timer_sync(&buttons_timer);
+		iounmap(bdev->reg);
+		input_unregister_device(input);
+		kfree(bdev);
+	}
+
+	return retval;
+}
+
+static int __devexit cobalt_buttons_remove(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct buttons_dev *bdev = dev_get_drvdata(dev);
+
+	misc_deregister(&cobalt_buttons_miscdevice);
+	input_unregister_device(bdev->input);
+	iounmap(bdev->reg);
+	kfree(bdev);
+	dev_set_drvdata(dev, NULL);
+
+	return 0;
+}
+
+static struct platform_driver cobalt_buttons_driver = {
+	.probe	= cobalt_buttons_probe,
+	.remove	= __devexit_p(cobalt_buttons_remove),
+	.driver	= {
+		.name	= "Cobalt buttons",
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int __init cobalt_buttons_init(void)
+{
+	int retval;
+
+	cobalt_buttons_device = platform_device_register_simple("Cobalt buttons", -1,
+	                                                        &cobalt_buttons_resource, 1);
+	if (IS_ERR(cobalt_buttons_device)) {
+		retval = PTR_ERR(cobalt_buttons_device);
+		return retval;
+	}
+
+	retval = platform_driver_register(&cobalt_buttons_driver);
+	if (retval < 0)
+		platform_device_unregister(cobalt_buttons_device);
+
+	return retval;
+}
+
+static void __exit cobalt_buttons_exit(void)
+{
+	platform_driver_unregister(&cobalt_buttons_driver);
+	platform_device_unregister(cobalt_buttons_device);
+}
+
+module_init(cobalt_buttons_init);
+module_exit(cobalt_buttons_exit);

Re: [PATCH] Add Cobalt button interface driver support

From: "Dmitry Torokhov" <dmitry.torokhov@gmail.com>
Date: 2007-02-16 15:15:15

On 2/16/07, Yoichi Yuasa [off-list ref] wrote:
+
+static int cobalt_buttons_open(struct inode *inode, struct file *file)
+{
+       buttons_timer.expires = jiffies + msecs_to_jiffies(BUTTONS_POLL_INTERVAL);
+       add_timer(&buttons_timer);
+
+       return nonseekable_open(inode, file);
+
+}
Hi,

I am sorry, I was not clear enough - when I was talking about adding
cobalt_buttons_open/close I was not asking you to add a misc device to
the driver. I was talking about setting up open() and close() methods
in input_dev structure. These methods are called by input core when
first (or last) user opens or closes one of input interfaces, such as
/dev/input/eventX, /dev/input/jsX, etc and so it is naturally to
start/stop polling device from these functions.

Does this make sense?

-- 
Dmitry

Re: [PATCH] Add Cobalt button interface driver support

From: Yoichi Yuasa <hidden>
Date: 2007-02-16 16:22:58

On Fri, 16 Feb 2007 10:15:11 -0500
"Dmitry Torokhov" [off-list ref] wrote:
On 2/16/07, Yoichi Yuasa [off-list ref] wrote:
quoted
+
+static int cobalt_buttons_open(struct inode *inode, struct file *file)
+{
+       buttons_timer.expires = jiffies + msecs_to_jiffies(BUTTONS_POLL_INTERVAL);
+       add_timer(&buttons_timer);
+
+       return nonseekable_open(inode, file);
+
+}
Hi,

I am sorry, I was not clear enough - when I was talking about adding
cobalt_buttons_open/close I was not asking you to add a misc device to
the driver. I was talking about setting up open() and close() methods
in input_dev structure. These methods are called by input core when
first (or last) user opens or closes one of input interfaces, such as
/dev/input/eventX, /dev/input/jsX, etc and so it is naturally to
start/stop polling device from these functions.

Does this make sense?
make sense.
updated my patch.

Yoichi

Signed-off-by: Yoichi Yuasa <redacted>

diff -pruN -X cobalt-buttons/Documentation/dontdiff cobalt-buttons-orig/drivers/input/misc/Kconfig cobalt-buttons/drivers/input/misc/Kconfig
--- cobalt-buttons-orig/drivers/input/misc/Kconfig	2007-02-14 15:35:30.566862000 +0900
+++ cobalt-buttons/drivers/input/misc/Kconfig	2007-02-15 17:20:28.721985250 +0900
@@ -89,4 +89,10 @@ config HP_SDC_RTC
 	  Say Y here if you want to support the built-in real time clock
 	  of the HP SDC controller.
 
+config INPUT_COBALT_BTNS
+	tristate "Cobalt button interface"       
+	depends on MIPS_COBALT
+	help
+	  Say Y here if you want to support MIPS Cobalt button interface.
+
 endif
diff -pruN -X cobalt-buttons/Documentation/dontdiff cobalt-buttons-orig/drivers/input/misc/Makefile cobalt-buttons/drivers/input/misc/Makefile
--- cobalt-buttons-orig/drivers/input/misc/Makefile	2007-02-14 15:35:30.566862000 +0900
+++ cobalt-buttons/drivers/input/misc/Makefile	2007-02-15 11:55:30.856042500 +0900
@@ -12,3 +12,4 @@ obj-$(CONFIG_INPUT_WISTRON_BTNS)	+= wist
 obj-$(CONFIG_INPUT_ATLAS_BTNS)		+= atlas_btns.o
 obj-$(CONFIG_HP_SDC_RTC)		+= hp_sdc_rtc.o
 obj-$(CONFIG_INPUT_IXP4XX_BEEPER)	+= ixp4xx-beeper.o
+obj-$(CONFIG_INPUT_COBALT_BTNS)		+= cobalt_btns.o
diff -pruN -X cobalt-buttons/Documentation/dontdiff cobalt-buttons-orig/drivers/input/misc/cobalt_btns.c cobalt-buttons/drivers/input/misc/cobalt_btns.c
--- cobalt-buttons-orig/drivers/input/misc/cobalt_btns.c	1970-01-01 09:00:00.000000000 +0900
+++ cobalt-buttons/drivers/input/misc/cobalt_btns.c	2007-02-17 01:14:33.079876500 +0900
@@ -0,0 +1,211 @@
+/*
+ *  Cobalt button interface driver.
+ *
+ *  Copyright (C) 2007  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+#include <linux/init.h>
+#include <linux/input.h>
+#include <linux/ioport.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/jiffies.h>
+#include <linux/timer.h>
+
+#define BUTTONS_POLL_INTERVAL	30	/* msec */
+#define BUTTONS_COUNT_THRESHOLD	3
+#define BUTTONS_STATUS_MASK	0xfe000000
+
+struct buttons_dev {
+	struct input_dev *input;
+	void __iomem *reg;
+};
+
+struct buttons_map {
+	uint32_t	mask;
+	int		keycode;
+	int		count;
+};
+
+static struct buttons_map buttons_map[] = {
+	{ 0x02000000, KEY_RESTART, },
+	{ 0x04000000, KEY_LEFT, },
+	{ 0x08000000, KEY_UP, },
+	{ 0x10000000, KEY_DOWN, },
+	{ 0x20000000, KEY_RIGHT, },
+	{ 0x40000000, KEY_ENTER, },
+	{ 0x80000000, KEY_SELECT, },
+};
+
+static struct resource cobalt_buttons_resource __initdata = {
+	.start	= 0x1d000000,
+	.end	= 0x1d000003,
+	.flags	= IORESOURCE_MEM,
+};
+
+static struct platform_device *cobalt_buttons_device;
+
+static struct timer_list buttons_timer;
+
+static void handle_buttons(unsigned long data)
+{
+	struct buttons_map *button = buttons_map;
+	struct buttons_dev *bdev;
+	uint32_t status;
+	int i;
+
+	bdev = (struct buttons_dev *)data;
+	status = readl(bdev->reg);
+	status = ~status & BUTTONS_STATUS_MASK;
+
+	for (i = 0; i < ARRAY_SIZE(buttons_map); i++) {
+		if (status & button->mask) {
+			button->count++;
+		} else {
+			if (button->count >= BUTTONS_COUNT_THRESHOLD) {
+				input_report_key(bdev->input, button->keycode, 0);
+				input_sync(bdev->input);
+			}
+			button->count = 0;
+		}
+
+		if (button->count == BUTTONS_COUNT_THRESHOLD) {
+			input_report_key(bdev->input, button->keycode, 1);
+			input_sync(bdev->input);
+		}
+
+		button++;
+	}
+
+	mod_timer(&buttons_timer, jiffies + msecs_to_jiffies(BUTTONS_POLL_INTERVAL));
+}
+
+static int cobalt_buttons_open(struct input_dev *dev)
+{
+	buttons_timer.expires = jiffies + msecs_to_jiffies(BUTTONS_POLL_INTERVAL);
+	add_timer(&buttons_timer);
+
+	return 0;
+}
+
+static void cobalt_buttons_close(struct input_dev *dev)
+{
+	del_timer_sync(&buttons_timer);
+}
+
+static int __init cobalt_buttons_probe(struct platform_device *pdev)
+{
+	struct buttons_dev *bdev;
+	struct input_dev *input;
+	struct resource *res;
+	int retval, i;
+
+	bdev = kzalloc(sizeof(struct buttons_dev), GFP_KERNEL);
+	if (!bdev)
+		return -ENOMEM;
+
+	input = input_allocate_device();
+	if (!input) {
+		kfree(bdev);
+		return -ENOMEM;
+	}
+
+	input->name = "Cobalt buttons";
+	input->phys = "cobalt/input0";
+	input->id.bustype = BUS_HOST;
+	input->cdev.dev = &pdev->dev;
+	input->open = cobalt_buttons_open;
+	input->close = cobalt_buttons_close;
+
+	input->evbit[0] = BIT(EV_KEY);
+	for (i = 0; i < ARRAY_SIZE(buttons_map); i++) {
+		set_bit(buttons_map[i].keycode, input->keybit);
+		buttons_map[i].count = 0;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		input_free_device(input);
+		kfree(bdev);
+		return -EBUSY;
+	}
+
+	bdev->input = input;
+	bdev->reg = ioremap(res->start, res->end - res->start + 1);
+	dev_set_drvdata(&pdev->dev, bdev);
+
+	setup_timer(&buttons_timer, handle_buttons, (unsigned long)bdev);
+
+	retval = input_register_device(input);
+	if (retval < 0) {
+		del_timer_sync(&buttons_timer);
+		dev_set_drvdata(&pdev->dev, NULL);
+		iounmap(bdev->reg);
+		input_free_device(input);
+		kfree(bdev);
+	}
+
+	return retval;
+}
+
+static int __devexit cobalt_buttons_remove(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct buttons_dev *bdev = dev_get_drvdata(dev);
+
+	input_unregister_device(bdev->input);
+	iounmap(bdev->reg);
+	kfree(bdev);
+	dev_set_drvdata(dev, NULL);
+
+	return 0;
+}
+
+static struct platform_driver cobalt_buttons_driver = {
+	.probe	= cobalt_buttons_probe,
+	.remove	= __devexit_p(cobalt_buttons_remove),
+	.driver	= {
+		.name	= "Cobalt buttons",
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int __init cobalt_buttons_init(void)
+{
+	int retval;
+
+	cobalt_buttons_device = platform_device_register_simple("Cobalt buttons", -1,
+	                                                        &cobalt_buttons_resource, 1);
+	if (IS_ERR(cobalt_buttons_device)) {
+		retval = PTR_ERR(cobalt_buttons_device);
+		return retval;
+	}
+
+	retval = platform_driver_register(&cobalt_buttons_driver);
+	if (retval < 0)
+		platform_device_unregister(cobalt_buttons_device);
+
+	return retval;
+}
+
+static void __exit cobalt_buttons_exit(void)
+{
+	platform_driver_unregister(&cobalt_buttons_driver);
+	platform_device_unregister(cobalt_buttons_device);
+}
+
+module_init(cobalt_buttons_init);
+module_exit(cobalt_buttons_exit);

Re: [PATCH] Add Cobalt button interface driver support

From: Dmitry Torokhov <hidden>
Date: 2007-04-04 04:02:01

Hi Yoichi,

Could you please try the patch below? It moves platform device creation
code into cobalt arch code to belletr follow driver model.

Thank you!

-- 
Dmitry

Input: cobalt buttons - separate device and driver registration

Create platform device for cobalt buttons as part of arch setup.
This makes the driver follow current driver model more closely.

Signed-off-by: Dmitry Torokhov <redacted>
---

 arch/mips/cobalt/Makefile        |    2 -
 arch/mips/cobalt/buttons.c       |   54 +++++++++++++++++++++++++++++++++++++++
 drivers/input/misc/cobalt_btns.c |   24 -----------------
 3 files changed, 56 insertions(+), 24 deletions(-)

Index: work/arch/mips/cobalt/Makefile
===================================================================
--- work.orig/arch/mips/cobalt/Makefile
+++ work/arch/mips/cobalt/Makefile
@@ -2,7 +2,7 @@
 # Makefile for the Cobalt micro systems family specific parts of the kernel
 #
 
-obj-y	 := irq.o reset.o setup.o
+obj-y	 := irq.o reset.o setup.o buttons.o
 
 obj-$(CONFIG_EARLY_PRINTK)	+= console.o
 obj-$(CONFIG_MTD_PHYSMAP)	+= mtd.o
Index: work/arch/mips/cobalt/buttons.c
===================================================================
--- /dev/null
+++ work/arch/mips/cobalt/buttons.c
@@ -0,0 +1,54 @@
+/*
+ *  Cobalt buttons platform device.
+ *
+ *  Copyright (C) 2007  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <linux/platform_device.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+
+static struct resource cobalt_buttons_resource __initdata = {
+	.start	= 0x1d000000,
+	.end	= 0x1d000003,
+	.flags	= IORESOURCE_MEM,
+};
+
+static __init int cobalt_add_buttons(void)
+{
+	struct platform_device *pd;
+	int error;
+
+	pd = platform_device_alloc("Cobalt buttons", -1);
+	if (!pd)
+		return -ENOMEM;
+
+	error = platform_device_add_resources(pd, &cobalt_buttons_resource, 1);
+	if (error)
+		goto err_free_device;
+
+	error = platform_device_add(pd);
+	if (error)
+		goto err_free_device;
+
+	return 0;
+
+ err_free_device:
+	platform_device_put(pd);
+	return error;
+}
+device_initcall(cobalt_add_buttons);
Index: work/drivers/input/misc/cobalt_btns.c
===================================================================
--- work.orig/drivers/input/misc/cobalt_btns.c
+++ work/drivers/input/misc/cobalt_btns.c
@@ -50,14 +50,6 @@ static struct buttons_map buttons_map[] 
 	{ 0x80000000, KEY_SELECT, },
 };
 
-static struct resource cobalt_buttons_resource __initdata = {
-	.start	= 0x1d000000,
-	.end	= 0x1d000003,
-	.flags	= IORESOURCE_MEM,
-};
-
-static struct platform_device *cobalt_buttons_device;
-
 static struct timer_list buttons_timer;
 
 static void handle_buttons(unsigned long data)
@@ -183,26 +175,12 @@ static struct platform_driver cobalt_but
 
 static int __init cobalt_buttons_init(void)
 {
-	int retval;
-
-	cobalt_buttons_device = platform_device_register_simple("Cobalt buttons", -1,
-	                                                        &cobalt_buttons_resource, 1);
-	if (IS_ERR(cobalt_buttons_device)) {
-		retval = PTR_ERR(cobalt_buttons_device);
-		return retval;
-	}
-
-	retval = platform_driver_register(&cobalt_buttons_driver);
-	if (retval < 0)
-		platform_device_unregister(cobalt_buttons_device);
-
-	return retval;
+	return platform_driver_register(&cobalt_buttons_driver);
 }
 
 static void __exit cobalt_buttons_exit(void)
 {
 	platform_driver_unregister(&cobalt_buttons_driver);
-	platform_device_unregister(cobalt_buttons_device);
 }
 
 module_init(cobalt_buttons_init);

Re: [PATCH] Add Cobalt button interface driver support

From: Yoichi Yuasa <hidden>
Date: 2007-04-05 05:02:55

Hi Dmitry,

On Wed, 4 Apr 2007 00:01:41 -0400
Dmitry Torokhov [off-list ref] wrote:
Hi Yoichi,

Could you please try the patch below? It moves platform device creation
code into cobalt arch code to belletr follow driver model.
It works fine.

Acked-by: Yoichi Yuasa <redacted>

Yoichi

Re: [PATCH] Add Cobalt button interface driver support

From: Dmitry Torokhov <hidden>
Date: 2007-04-25 05:34:33

Hi Yoichi,

On Thursday 05 April 2007 01:02, Yoichi Yuasa wrote:
Hi Dmitry,

On Wed, 4 Apr 2007 00:01:41 -0400
Dmitry Torokhov [off-list ref] wrote:
quoted
Hi Yoichi,

Could you please try the patch below? It moves platform device creation
code into cobalt arch code to belletr follow driver model.
It works fine.
Coudl you please try couple more patches, please? I wrote a generic
stub for polled (as opposed to interrupt-driven) input devices and
converting existing drivers to use it. Cobalt buttons seem to be
a good candidate...
  
Thank you in advance.

-- 
Dmitry

Re: [PATCH] Add Cobalt button interface driver support

From: Yoichi Yuasa <hidden>
Date: 2007-04-26 06:40:25

Hi Dmitry,

On Wed, 25 Apr 2007 01:34:33 -0400
Dmitry Torokhov [off-list ref] wrote:
Hi Yoichi,

On Thursday 05 April 2007 01:02, Yoichi Yuasa wrote:
quoted
Hi Dmitry,

On Wed, 4 Apr 2007 00:01:41 -0400
Dmitry Torokhov [off-list ref] wrote:
quoted
Hi Yoichi,

Could you please try the patch below? It moves platform device creation
code into cobalt arch code to belletr follow driver model.
It works fine.
Coudl you please try couple more patches, please? I wrote a generic
stub for polled (as opposed to interrupt-driven) input devices and
converting existing drivers to use it. Cobalt buttons seem to be
a good candidate...
Looks good to me and works fine.

Acked-by: Yoichi Yuasa <redacted>

Thanks for your great work,

Yoichi

Re: [PATCH] Add Cobalt button interface driver support

From: "Dmitry Torokhov" <dmitry.torokhov@gmail.com>
Date: 2007-04-26 12:29:25

On 4/26/07, Yoichi Yuasa [off-list ref] wrote:
Dmitry Torokhov [off-list ref] wrote:
quoted
Coudl you please try couple more patches, please? I wrote a generic
stub for polled (as opposed to interrupt-driven) input devices and
converting existing drivers to use it. Cobalt buttons seem to be
a good candidate...
Looks good to me and works fine.

Acked-by: Yoichi Yuasa <redacted>
Thank you for testing/review.

-- 
Dmitry

Re: [PATCH] Add Cobalt button interface driver support

From: Dmitry Torokhov <hidden>
Date: 2007-09-18 04:59:39

Hi Yoichi,

I tried adding loadable keymap support to the cobalt buttons driver so
that users can adjust keycodes if they are not satisfied with the default
selection. I would like to ask you to give this patch a spin when you
have a minute to spare as I do not own the hardware and terefore is unable
to test the patch myself.

The easies way to test I believe with the keyfuzz utility:

	http://0pointer.de/lennart/projects/keyfuzz/

Cobalt_btns uses 0-7 range of "scancodes".

Thank you in advance.

-- 
Dmitry

Input: cobalt_btns - add support for loadable keymaps

Signed-off-by: Dmitry Torokhov <redacted>
---
 drivers/input/misc/cobalt_btns.c |   73 +++++++++++++++++++--------------------
 1 file changed, 36 insertions(+), 37 deletions(-)

Index: linux/drivers/input/misc/cobalt_btns.c
===================================================================
--- linux.orig/drivers/input/misc/cobalt_btns.c
+++ linux/drivers/input/misc/cobalt_btns.c
@@ -27,55 +27,48 @@
 #define BUTTONS_COUNT_THRESHOLD	3
 #define BUTTONS_STATUS_MASK	0xfe000000
 
+static const unsigned short cobalt_map[] = {
+	KEY_RESERVED,
+	KEY_RESTART,
+	KEY_LEFT,
+	KEY_UP,
+	KEY_DOWN,
+	KEY_RIGHT,
+	KEY_ENTER,
+	KEY_SELECT
+};
+
 struct buttons_dev {
 	struct input_polled_dev *poll_dev;
+	unsigned short keymap[ARRAY_SIZE(cobalt_map)];
+	int count[ARRAY_SIZE(cobalt_map)];
 	void __iomem *reg;
 };
 
-struct buttons_map {
-	uint32_t mask;
-	int keycode;
-	int count;
-};
-
-static struct buttons_map buttons_map[] = {
-	{ 0x02000000, KEY_RESTART, },
-	{ 0x04000000, KEY_LEFT, },
-	{ 0x08000000, KEY_UP, },
-	{ 0x10000000, KEY_DOWN, },
-	{ 0x20000000, KEY_RIGHT, },
-	{ 0x40000000, KEY_ENTER, },
-	{ 0x80000000, KEY_SELECT, },
-};
-
 static void handle_buttons(struct input_polled_dev *dev)
 {
-	struct buttons_map *button = buttons_map;
 	struct buttons_dev *bdev = dev->private;
 	struct input_dev *input = dev->input;
 	uint32_t status;
 	int i;
 
-	status = readl(bdev->reg);
-	status = ~status & BUTTONS_STATUS_MASK;
+	status = ~readl(bdev->reg) >> 24;
 
-	for (i = 0; i < ARRAY_SIZE(buttons_map); i++) {
-		if (status & button->mask) {
-			button->count++;
+	for (i = 0; i < ARRAY_SIZE(bdev->keymap); i++) {
+		if (status & (1UL << i)) {
+			if (++bdev->count[i] == BUTTONS_COUNT_THRESHOLD) {
+				input_event(input, EV_MSC, MSC_SCAN, i);
+				input_report_key(input, bdev->keymap[i], 1);
+				input_sync(input);
+			}
 		} else {
-			if (button->count >= BUTTONS_COUNT_THRESHOLD) {
-				input_report_key(input, button->keycode, 0);
+			if (bdev->count[i] >= BUTTONS_COUNT_THRESHOLD) {
+				input_event(input, EV_MSC, MSC_SCAN, i);
+				input_report_key(input, bdev->keymap[i], 0);
 				input_sync(input);
 			}
-			button->count = 0;
-		}
-
-		if (button->count == BUTTONS_COUNT_THRESHOLD) {
-			input_report_key(input, button->keycode, 1);
-			input_sync(input);
+			bdev->count[i] = 0;
 		}
-
-		button++;
 	}
 }
 
@@ -94,6 +87,8 @@ static int __devinit cobalt_buttons_prob
 		goto err_free_mem;
 	}
 
+	memcpy(bdev->keymap, cobalt_map, sizeof(bdev->keymap));
+
 	poll_dev->private = bdev;
 	poll_dev->poll = handle_buttons;
 	poll_dev->poll_interval = BUTTONS_POLL_INTERVAL;
@@ -104,11 +99,15 @@ static int __devinit cobalt_buttons_prob
 	input->id.bustype = BUS_HOST;
 	input->cdev.dev = &pdev->dev;
 
-	input->evbit[0] = BIT(EV_KEY);
-	for (i = 0; i < ARRAY_SIZE(buttons_map); i++) {
-		set_bit(buttons_map[i].keycode, input->keybit);
-		buttons_map[i].count = 0;
-	}
+	input->keycode = pdev->keymap;
+	input->keycodemax = ARRAY_SIZE(pdev->keymap);
+	input->keycodesize = sizeof(unsigned short);
+
+	input_set_capability(input, EV_MSC, MSC_SCAN);
+	__set_bit(EV_KEY, input->evbit);
+	for (i = 0; i < ARRAY_SIZE(buttons_map); i++)
+		__set_bit(input->keycode[i], input->keybit);
+	__clear_bit(KEY_RESERVED, input->keybit);
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!res) {
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help