* [PATCH] Add Cobalt button interface driver support @ 2007-02-16 3:36 Yoichi Yuasa 2007-02-16 4:09 ` Dmitry Torokhov 0 siblings, 1 reply; 11+ messages in thread From: Yoichi Yuasa @ 2007-02-16 3:36 UTC (permalink / raw) To: dmitry.torokhov; +Cc: yoichi_yuasa, linux-input, Linux Kernel Mailing List 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 <yoichi_yuasa@tripeaks.co.jp> 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); ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH] Add Cobalt button interface driver support 2007-02-16 3:36 [PATCH] Add Cobalt button interface driver support Yoichi Yuasa @ 2007-02-16 4:09 ` Dmitry Torokhov 2007-02-16 8:15 ` Yoichi Yuasa 0 siblings, 1 reply; 11+ messages in thread From: Dmitry Torokhov @ 2007-02-16 4:09 UTC (permalink / raw) To: Yoichi Yuasa; +Cc: linux-input, Linux Kernel Mailing List 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 ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH] Add Cobalt button interface driver support 2007-02-16 4:09 ` Dmitry Torokhov @ 2007-02-16 8:15 ` Yoichi Yuasa 2007-02-16 15:15 ` Dmitry Torokhov 0 siblings, 1 reply; 11+ messages in thread From: Yoichi Yuasa @ 2007-02-16 8:15 UTC (permalink / raw) To: Dmitry Torokhov; +Cc: yoichi_yuasa, linux-input, linux-kernel Hi, Thank you for your comments. On Thu, 15 Feb 2007 23:09:43 -0500 Dmitry Torokhov <dtor@insightbb.com> wrote: > 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? OK, I updated it. > > + > > + 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. > > +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. > > +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 <yoichi_yuasa@tripeaks.co.jp> 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); ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH] Add Cobalt button interface driver support 2007-02-16 8:15 ` Yoichi Yuasa @ 2007-02-16 15:15 ` Dmitry Torokhov 2007-02-16 16:22 ` Yoichi Yuasa 0 siblings, 1 reply; 11+ messages in thread From: Dmitry Torokhov @ 2007-02-16 15:15 UTC (permalink / raw) To: Yoichi Yuasa; +Cc: linux-input, linux-kernel On 2/16/07, Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> 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 ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH] Add Cobalt button interface driver support 2007-02-16 15:15 ` Dmitry Torokhov @ 2007-02-16 16:22 ` Yoichi Yuasa 2007-04-04 4:01 ` Dmitry Torokhov 0 siblings, 1 reply; 11+ messages in thread From: Yoichi Yuasa @ 2007-02-16 16:22 UTC (permalink / raw) To: Dmitry Torokhov; +Cc: yoichi_yuasa, linux-input, linux-kernel On Fri, 16 Feb 2007 10:15:11 -0500 "Dmitry Torokhov" <dmitry.torokhov@gmail.com> wrote: > On 2/16/07, Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> 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? make sense. updated my patch. Yoichi Signed-off-by: Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> 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); ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH] Add Cobalt button interface driver support 2007-02-16 16:22 ` Yoichi Yuasa @ 2007-04-04 4:01 ` Dmitry Torokhov 2007-04-05 5:02 ` Yoichi Yuasa 0 siblings, 1 reply; 11+ messages in thread From: Dmitry Torokhov @ 2007-04-04 4:01 UTC (permalink / raw) To: Yoichi Yuasa; +Cc: linux-input, linux-kernel 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 <dtor@mail.ru> --- 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); ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH] Add Cobalt button interface driver support 2007-04-04 4:01 ` Dmitry Torokhov @ 2007-04-05 5:02 ` Yoichi Yuasa 2007-04-25 5:34 ` Dmitry Torokhov 0 siblings, 1 reply; 11+ messages in thread From: Yoichi Yuasa @ 2007-04-05 5:02 UTC (permalink / raw) To: Dmitry Torokhov; +Cc: yoichi_yuasa, linux-input, linux-kernel Hi Dmitry, On Wed, 4 Apr 2007 00:01:41 -0400 Dmitry Torokhov <dtor@insightbb.com> 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 <yoichi_yuasa@tripeaks.co.jp> Yoichi ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH] Add Cobalt button interface driver support 2007-04-05 5:02 ` Yoichi Yuasa @ 2007-04-25 5:34 ` Dmitry Torokhov 2007-04-26 6:40 ` Yoichi Yuasa 0 siblings, 1 reply; 11+ messages in thread From: Dmitry Torokhov @ 2007-04-25 5:34 UTC (permalink / raw) To: Yoichi Yuasa; +Cc: linux-input [-- Attachment #1: Type: text/plain, Size: 606 bytes --] 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 <dtor@insightbb.com> 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. > 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 [-- Attachment #2: polled-button.patch --] [-- Type: text/x-diff, Size: 7867 bytes --] Subject: XXX Signed-off-by: Dmitry Torokhov <dtor@mail.ru> --- drivers/input/misc/Kconfig | 11 ++ drivers/input/misc/Makefile | 1 drivers/input/misc/input-polldev.c | 171 +++++++++++++++++++++++++++++++++++++ include/linux/input-polldev.h | 46 +++++++++ 4 files changed, 229 insertions(+) Index: work/drivers/input/misc/Kconfig =================================================================== --- work.orig/drivers/input/misc/Kconfig +++ work/drivers/input/misc/Kconfig @@ -90,6 +90,17 @@ config INPUT_UINPUT To compile this driver as a module, choose M here: the module will be called uinput. +config INPUT_POLLDEV + tristate "Polled input device skeleton" + help + Say Y here if you are using a driver for an input + device that periodically polls hardware state. This + option is only useful for out-of-tree drivers since + in-tree drivers select it automatically. + + To compile this driver as a module, choose M here: the + module will be called input-polldev. + config HP_SDC_RTC tristate "HP SDC Real Time Clock" depends on GSC || HP300 Index: work/drivers/input/misc/Makefile =================================================================== --- work.orig/drivers/input/misc/Makefile +++ work/drivers/input/misc/Makefile @@ -4,6 +4,7 @@ # Each configuration option enables a list of files. +obj-$(CONFIG_INPUT_POLLDEV) += input-polldev.o obj-$(CONFIG_INPUT_SPARCSPKR) += sparcspkr.o obj-$(CONFIG_INPUT_PCSPKR) += pcspkr.o obj-$(CONFIG_INPUT_M68K_BEEP) += m68kspkr.o Index: work/drivers/input/misc/input-polldev.c =================================================================== --- /dev/null +++ work/drivers/input/misc/input-polldev.c @@ -0,0 +1,171 @@ +/* + * Generic implementation of a polled input device + + * Copyright (c) 2007 Dmitry Torokhov + * + * 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/jiffies.h> +#include <linux/mutex.h> +#include <linux/input-polldev.h> + +static DEFINE_MUTEX(polldev_mutex); +static int polldev_users; +static struct workqueue_struct *polldev_wq; + +static int input_polldev_start_workqueue(void) +{ + int retval; + + retval = mutex_lock_interruptible(&polldev_mutex); + if (retval) + return retval; + + if (!polldev_users) { + polldev_wq = create_singlethread_workqueue("ipolldevd"); + if (!polldev_wq) { + printk(KERN_ERR "input-polldev: failed to create " + "ipolldevd workqueue\n"); + retval = -ENOMEM; + goto out; + } + } + + polldev_users++; + + out: + mutex_unlock(&polldev_mutex); + return retval; +} + +static void input_polldev_stop_workqueue(void) +{ + mutex_lock(&polldev_mutex); + + if (!--polldev_users) + destroy_workqueue(polldev_wq); + + mutex_unlock(&polldev_mutex); +} + +static void input_polled_device_work(struct work_struct *work) +{ + struct input_polled_dev *dev = + container_of(work, struct input_polled_dev, work.work); + + dev->poll(dev); + queue_delayed_work(polldev_wq, &dev->work, + msecs_to_jiffies(dev->poll_interval)); +} + +static int input_open_polled_device(struct input_dev *input) +{ + struct input_polled_dev *dev = input->private; + int error; + + error = input_polldev_start_workqueue(); + if (error) + return error; + + if (dev->flush) + dev->flush(dev); + + queue_delayed_work(polldev_wq, &dev->work, + msecs_to_jiffies(dev->poll_interval)); + + return 0; +} + +static void input_close_polled_device(struct input_dev *input) +{ + struct input_polled_dev *dev = input->private; + + cancel_rearming_delayed_workqueue(polldev_wq, &dev->work); + input_polldev_stop_workqueue(); +} + +/** + * input_allocate_polled_device - allocated memory polled device + * + * The function allocates memory for a polled device and also + * for an input device associated with this polled device. + */ +struct input_polled_dev *input_allocate_polled_device(void) +{ + struct input_polled_dev *dev; + + dev = kzalloc(sizeof(struct input_polled_dev), GFP_KERNEL); + if (!dev) + return NULL; + + dev->input = input_allocate_device(); + if (!dev->input) { + kfree(dev); + return NULL; + } + + return dev; +} +EXPORT_SYMBOL(input_allocate_polled_device); + +/** + * input_free_polled_device - free memory allocated for polled device + * @dev: device to free + * + * The function frees memory allocated for pollign device and drops + * reference to the associated input device (if present). + */ +void input_free_polled_device(struct input_polled_dev *dev) +{ + if (dev) { + input_free_device(dev->input); + kfree(dev); + } +} +EXPORT_SYMBOL(input_free_polled_device); + +/** + * input_register_polled_device - register polled device + * @dev: device to register + * + * The function registers previously initialized polled input device + * with input layer. The device should be allocated with call to + * input_allocate_polled_device(). Callers should also set up poll() + * method and set up capabilities (id, name, phys, bits) of the + * corresponing input_dev structure. + */ +int input_register_polled_device(struct input_polled_dev *dev) +{ + struct input_dev *input = dev->input; + + INIT_DELAYED_WORK(&dev->work, input_polled_device_work); + if (!dev->poll_interval) + dev->poll_interval = 500; + input->private = dev; + input->open = input_open_polled_device; + input->close = input_close_polled_device; + + return input_register_device(input); +} +EXPORT_SYMBOL(input_register_polled_device); + +/** + * input_unregister_polled_device - unregister polled device + * @dev: device to unregister + * + * The function unregisters previously registered polled input + * device from input layer. Polling is stopped and device is + * ready to be freed with call to input_free_polled_device(). + * Callers should not attempt to access dev->input pointer + * after calling this function. + */ +void input_unregister_polled_device(struct input_polled_dev *dev) +{ + input_unregister_device(dev->input); + dev->input = NULL; +} +EXPORT_SYMBOL(input_unregister_polled_device); + Index: work/include/linux/input-polldev.h =================================================================== --- /dev/null +++ work/include/linux/input-polldev.h @@ -0,0 +1,46 @@ +#ifndef _INPUT_POLLDEV_H +#define _INPUT_POLLDEV_H + +/* + * Copyright (c) 2007 Dmitry Torokhov + * + * 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/input.h> +#include <linux/workqueue.h> + +/** + * struct input_polled_dev - simple polled input device + * @private: private driver data + * @flush: driver-supplied method that flushes device's state upon + * opening (optional) + * @poll: driver-supplied method that polls the device and posts + * input events (mandatory). + * @poll_interval: specifies how often the poll() method shoudl be called. + * @input: input device structire associated with the polled device. + * Must be properly initialized by the driver (id, name, phys, bits). + * + * Polled input device provides a skeleton for supporting simple input + * devices that do not raise interrupts but have to be periodically + * scanned to detect changes in their state. + */ +struct input_polled_dev { + void *private; + + void (*flush)(struct input_polled_dev *dev); + void (*poll)(struct input_polled_dev *dev); + unsigned int poll_interval; /* msec */ + + struct input_dev *input; + struct delayed_work work; +}; + +struct input_polled_dev *input_allocate_polled_device(void); +void input_free_polled_device(struct input_polled_dev *dev); +int input_register_polled_device(struct input_polled_dev *dev); +void input_unregister_polled_device(struct input_polled_dev *dev); + +#endif [-- Attachment #3: cobalt-to-polldev.patch --] [-- Type: text/x-diff, Size: 4866 bytes --] Subject: XXX Input: cobalt_btns - convert to use polldev library Signed-off-by: Dmitry Torokhov <dtor@mail.ru> --- drivers/input/misc/Kconfig | 1 drivers/input/misc/cobalt_btns.c | 59 ++++++++++++++------------------------- 2 files changed, 23 insertions(+), 37 deletions(-) Index: work/drivers/input/misc/cobalt_btns.c =================================================================== --- work.orig/drivers/input/misc/cobalt_btns.c +++ work/drivers/input/misc/cobalt_btns.c @@ -18,19 +18,17 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include <linux/init.h> -#include <linux/input.h> +#include <linux/input-polldev.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; + struct input_polled_dev *poll_dev; void __iomem *reg; }; @@ -50,16 +48,14 @@ static struct buttons_map buttons_map[] { 0x80000000, KEY_SELECT, }, }; -static struct timer_list buttons_timer; - -static void handle_buttons(unsigned long data) +static void handle_buttons(struct input_polled_dev *dev) { struct buttons_map *button = buttons_map; - struct buttons_dev *bdev; + struct buttons_dev *bdev = dev->private; + struct input_dev *input = dev->input; uint32_t status; int i; - bdev = (struct buttons_dev *)data; status = readl(bdev->reg); status = ~status & BUTTONS_STATUS_MASK; @@ -68,55 +64,45 @@ static void handle_buttons(unsigned long button->count++; } else { if (button->count >= BUTTONS_COUNT_THRESHOLD) { - input_report_key(bdev->input, button->keycode, 0); - input_sync(bdev->input); + input_report_key(input, button->keycode, 0); + input_sync(input); } button->count = 0; } if (button->count == BUTTONS_COUNT_THRESHOLD) { - input_report_key(bdev->input, button->keycode, 1); - input_sync(bdev->input); + input_report_key(input, button->keycode, 1); + input_sync(input); } button++; } - - mod_timer(&buttons_timer, jiffies + msecs_to_jiffies(BUTTONS_POLL_INTERVAL)); -} - -static int cobalt_buttons_open(struct input_dev *dev) -{ - mod_timer(&buttons_timer, jiffies + msecs_to_jiffies(BUTTONS_POLL_INTERVAL)); - - return 0; -} - -static void cobalt_buttons_close(struct input_dev *dev) -{ - del_timer_sync(&buttons_timer); } static int __devinit cobalt_buttons_probe(struct platform_device *pdev) { struct buttons_dev *bdev; + struct input_polled_dev *poll_dev; struct input_dev *input; struct resource *res; int error, i; bdev = kzalloc(sizeof(struct buttons_dev), GFP_KERNEL); - input = input_allocate_device(); - if (!bdev || !input) { + poll_dev = input_allocate_polled_device(); + if (!bdev || !poll_dev) { error = -ENOMEM; goto err_free_mem; } + poll_dev->private = bdev; + poll_dev->poll = handle_buttons; + poll_dev->poll_interval = BUTTONS_POLL_INTERVAL; + + input = poll_dev->input; 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++) { @@ -130,13 +116,11 @@ static int __devinit cobalt_buttons_prob goto err_free_mem; } - bdev->input = input; + bdev->poll_dev = poll_dev; 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); - - error = input_register_device(input); + error = input_register_polled_device(poll_dev); if (error) goto err_iounmap; @@ -145,7 +129,7 @@ static int __devinit cobalt_buttons_prob err_iounmap: iounmap(bdev->reg); err_free_mem: - input_free_device(input); + input_free_polled_device(poll_dev); kfree(bdev); dev_set_drvdata(&pdev->dev, NULL); return error; @@ -156,7 +140,8 @@ static int __devexit cobalt_buttons_remo struct device *dev = &pdev->dev; struct buttons_dev *bdev = dev_get_drvdata(dev); - input_unregister_device(bdev->input); + input_unregister_polled_device(bdev->poll_dev); + input_free_polled_device(bdev->poll_dev); iounmap(bdev->reg); kfree(bdev); dev_set_drvdata(dev, NULL); Index: work/drivers/input/misc/Kconfig =================================================================== --- work.orig/drivers/input/misc/Kconfig +++ work/drivers/input/misc/Kconfig @@ -43,6 +43,7 @@ config INPUT_M68K_BEEP config INPUT_COBALT_BTNS tristate "Cobalt button interface" depends on MIPS_COBALT + select INPUT_POLLDEV help Say Y here if you want to support MIPS Cobalt button interface. ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH] Add Cobalt button interface driver support 2007-04-25 5:34 ` Dmitry Torokhov @ 2007-04-26 6:40 ` Yoichi Yuasa 2007-04-26 12:29 ` Dmitry Torokhov 2007-09-18 4:59 ` Dmitry Torokhov 0 siblings, 2 replies; 11+ messages in thread From: Yoichi Yuasa @ 2007-04-26 6:40 UTC (permalink / raw) To: Dmitry Torokhov; +Cc: yoichi_yuasa, linux-input Hi Dmitry, On Wed, 25 Apr 2007 01:34:33 -0400 Dmitry Torokhov <dtor@insightbb.com> wrote: > 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 <dtor@insightbb.com> 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. > > > > 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 <yoichi_yuasa@tripeaks.co.jp> Thanks for your great work, Yoichi ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH] Add Cobalt button interface driver support 2007-04-26 6:40 ` Yoichi Yuasa @ 2007-04-26 12:29 ` Dmitry Torokhov 2007-09-18 4:59 ` Dmitry Torokhov 1 sibling, 0 replies; 11+ messages in thread From: Dmitry Torokhov @ 2007-04-26 12:29 UTC (permalink / raw) To: Yoichi Yuasa; +Cc: linux-input On 4/26/07, Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> wrote: > Dmitry Torokhov <dtor@insightbb.com> wrote: > > > > 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 <yoichi_yuasa@tripeaks.co.jp> > Thank you for testing/review. -- Dmitry ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH] Add Cobalt button interface driver support 2007-04-26 6:40 ` Yoichi Yuasa 2007-04-26 12:29 ` Dmitry Torokhov @ 2007-09-18 4:59 ` Dmitry Torokhov 1 sibling, 0 replies; 11+ messages in thread From: Dmitry Torokhov @ 2007-09-18 4:59 UTC (permalink / raw) To: Yoichi Yuasa; +Cc: linux-input 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 <dtor@mail.ru> --- 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) { ^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2007-09-18 4:59 UTC | newest] Thread overview: 11+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2007-02-16 3:36 [PATCH] Add Cobalt button interface driver support Yoichi Yuasa 2007-02-16 4:09 ` Dmitry Torokhov 2007-02-16 8:15 ` Yoichi Yuasa 2007-02-16 15:15 ` Dmitry Torokhov 2007-02-16 16:22 ` Yoichi Yuasa 2007-04-04 4:01 ` Dmitry Torokhov 2007-04-05 5:02 ` Yoichi Yuasa 2007-04-25 5:34 ` Dmitry Torokhov 2007-04-26 6:40 ` Yoichi Yuasa 2007-04-26 12:29 ` Dmitry Torokhov 2007-09-18 4:59 ` Dmitry Torokhov
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).