Index: linux-2.6.15-rc1/arch/arm/mach-pxa/Makefile =================================================================== --- linux-2.6.15-rc1.orig/arch/arm/mach-pxa/Makefile 2005-11-19 23:13:40.000000000 +0000 +++ linux-2.6.15-rc1/arch/arm/mach-pxa/Makefile 2005-11-19 23:13:41.000000000 +0000 @@ -31,6 +31,7 @@ # Misc features obj-$(CONFIG_PM) += pm.o sleep.o +obj-$(CONFIG_PXA_KEYS) += pxa_keys.o obj-$(CONFIG_PXA_SSP) += ssp.o ifeq ($(CONFIG_PXA27x),y) Index: linux-2.6.15-rc1/arch/arm/mach-pxa/Kconfig =================================================================== --- linux-2.6.15-rc1.orig/arch/arm/mach-pxa/Kconfig 2005-11-19 23:13:40.000000000 +0000 +++ linux-2.6.15-rc1/arch/arm/mach-pxa/Kconfig 2005-11-19 23:13:41.000000000 +0000 @@ -112,6 +112,10 @@ help Select code specific to PXA27x variants +config PXA_KEYS + tristate "PXA25x/27x simple keyboard driver" + depends on (PXA25x || PXA27x) && INPUT + config IWMMXT bool help Index: linux-2.6.15-rc1/arch/arm/mach-pxa/pxa_keys.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.6.15-rc1/arch/arm/mach-pxa/pxa_keys.c 2005-11-19 23:32:30.000000000 +0000 @@ -0,0 +1,157 @@ +/* + * Driver interface for keys on PXA25x GPIO lines + * + * 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 +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +static irqreturn_t +pxa_keys_isr (int irq, void *dev_id, struct pt_regs *regs) +{ + int i; + struct pxa_keys_platform_data *k = dev_id; + + if (k->suspended) + return IRQ_HANDLED; + + for (i = 0; i < k->nbuttons; i++) { + int gpio = k->buttons[i].gpio; + if (irq == IRQ_GPIO(gpio)) { + int state = ((GPLR(gpio) & GPIO_bit(gpio)) ? 1 : 0) + ^ ((k->buttons[i].flags & PXAKEY_ACTIVE_LOW) != 0); + input_report_key (&k->input, k->buttons[i].keycode, state); + if ((k->buttons[i].flags & PXAKEY_PWR_KEY) + && time_after(jiffies, k->suspend_jiffies + HZ)) { + input_event(&k->input, EV_PWR, k->buttons[i].keycode, state); + k->suspend_jiffies=jiffies; + } + + } + } + + return IRQ_HANDLED; +} + +#ifdef CONFIG_PM +static int pxa_keys_suspend(struct platform_device *pdev, pm_message_t state) +{ + struct pxa_keys_platform_data *k = platform_get_drvdata(pdev); + k->suspended = 1; + return 0; +} + +static int pxa_keys_resume(struct platform_device *pdev) +{ + struct pxa_keys_platform_data *k = platform_get_drvdata(pdev); + + /* Upon resume, ignore the suspend key for a short while */ + k->suspend_jiffies=jiffies; + k->suspended = 0; + return 0; +} +#else +#define pxa_keys_suspend NULL +#define pxa_keys_resume NULL +#endif + +static int +pxa_keys_probe (struct platform_device *pdev) +{ + struct pxa_keys_platform_data *k; + int i; + + k = pdev->dev.platform_data; + platform_set_drvdata(pdev, k); + + init_input_dev (&k->input); + + k->input.evbit[0] = BIT(EV_KEY) | BIT(EV_PWR) | BIT(EV_REP); + for (i = 0; i < k->nbuttons; i++) { + int code = k->buttons[i].keycode; + int irq = IRQ_GPIO (k->buttons[i].gpio); + int result; + + set_irq_type (irq, IRQT_BOTHEDGE); + result = request_irq (irq, pxa_keys_isr, SA_SAMPLE_RANDOM, + "pxa_keys", k); + if (result == 0) + set_bit (code, k->input.keybit); + else + printk("pxa_keys: unable to claim irq %d; error %d\n", irq, result); + } + + k->input.name = pdev->name; + k->input.private = k; + + k->suspend_jiffies=jiffies; + k->suspended=0; + + input_register_device (&k->input); + + return 0; +} + +static int +pxa_keys_remove (struct platform_device *pdev) +{ + struct pxa_keys_platform_data *k = pdev->dev.platform_data; + int i; + + for (i = 0; i < k->nbuttons; i++) { + int irq = IRQ_GPIO (k->buttons[i].gpio); + free_irq (irq, k); + } + + input_unregister_device (&k->input); + + return 0; +} + +struct platform_driver pxa_keys_device_driver = { + .probe = pxa_keys_probe, + .remove = pxa_keys_remove, + .suspend = pxa_keys_suspend, + .resume = pxa_keys_resume, + .driver = { + .name = "pxa2xx-keys", + }, +}; + +static int pxa_keys_init (void) +{ + return platform_driver_register(&pxa_keys_device_driver); +} + +static void pxa_keys_cleanup (void) +{ + platform_driver_unregister(&pxa_keys_device_driver); +} + +module_init (pxa_keys_init); +module_exit (pxa_keys_cleanup); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Phil Blundell "); +MODULE_DESCRIPTION("Keyboard driver for PXA25x/PXA27x GPIOs"); Index: linux-2.6.15-rc1/include/asm-arm/arch-pxa/pxa_keys.h =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.6.15-rc1/include/asm-arm/arch-pxa/pxa_keys.h 2005-11-19 23:13:41.000000000 +0000 @@ -0,0 +1,17 @@ +#include + +struct pxa_keys_button { + int keycode; + int gpio; + unsigned long flags; +}; +#define PXAKEY_ACTIVE_LOW (1 << 0) /* Key is Active Low */ +#define PXAKEY_PWR_KEY (1 << 1) /* Key is a Power Key */ + +struct pxa_keys_platform_data { + struct pxa_keys_button *buttons; + int nbuttons; + struct input_dev input; + unsigned int suspended; + unsigned long suspend_jiffies; +};