diff options
Diffstat (limited to 'packages/linux/linux-ezx-2.6.21/patches/pxa-kbd.patch')
-rwxr-xr-x | packages/linux/linux-ezx-2.6.21/patches/pxa-kbd.patch | 534 |
1 files changed, 0 insertions, 534 deletions
diff --git a/packages/linux/linux-ezx-2.6.21/patches/pxa-kbd.patch b/packages/linux/linux-ezx-2.6.21/patches/pxa-kbd.patch deleted file mode 100755 index 425a5b984c..0000000000 --- a/packages/linux/linux-ezx-2.6.21/patches/pxa-kbd.patch +++ /dev/null @@ -1,534 +0,0 @@ -Index: linux-2.6.21/arch/arm/mach-pxa/generic.c -=================================================================== ---- linux-2.6.21.orig/arch/arm/mach-pxa/generic.c 2007-06-01 20:04:10.000000000 +0200 -+++ linux-2.6.21/arch/arm/mach-pxa/generic.c 2007-06-01 20:04:45.000000000 +0200 -@@ -42,6 +42,7 @@ - #include <asm/arch/mmc.h> - #include <asm/arch/irda.h> - #include <asm/arch/i2c.h> -+#include <asm/arch/kbd.h> - - #include "generic.h" - -@@ -430,6 +431,30 @@ - .id = -1, - }; - -+static struct resource pxa_kbd_resources[] = { -+ { -+ .start = IRQ_KEYPAD, -+ .end = IRQ_KEYPAD, -+ .flags = IORESOURCE_IRQ, -+ }, { -+ .start = 0x41500000, -+ .end = 0x4150004c, -+ .flags = IORESOURCE_MEM, -+ }, -+}; -+ -+static struct platform_device kbd_device = { -+ .name = "pxa-keyboard", -+ .id = -1, -+ .resource = pxa_kbd_resources, -+ .num_resources = ARRAY_SIZE(pxa_kbd_resources), -+}; -+ -+void __init pxa_set_kbd_info(struct pxakbd_platform_data *info) -+{ -+ kbd_device.dev.platform_data = info; -+} -+ - static struct platform_device *devices[] __initdata = { - &pxamci_device, - &udc_device, -@@ -444,6 +469,7 @@ - #endif - &i2s_device, - &pxartc_device, -+ &kbd_device, - }; - - static int __init pxa_init(void) -Index: linux-2.6.21/drivers/input/keyboard/Kconfig -=================================================================== ---- linux-2.6.21.orig/drivers/input/keyboard/Kconfig 2007-06-01 20:04:10.000000000 +0200 -+++ linux-2.6.21/drivers/input/keyboard/Kconfig 2007-06-01 20:04:45.000000000 +0200 -@@ -229,4 +229,11 @@ - To compile this driver as a module, choose M here: the - module will be called gpio-keys. - -+config KEYBOARD_PXA -+ tristate "Intel PXA keyboard support" -+ depends on ARCH_PXA -+ help -+ This add support for a driver of the Intel PXA2xx keyboard -+ controller. -+ - endif -Index: linux-2.6.21/drivers/input/keyboard/Makefile -=================================================================== ---- linux-2.6.21.orig/drivers/input/keyboard/Makefile 2007-06-01 20:04:10.000000000 +0200 -+++ linux-2.6.21/drivers/input/keyboard/Makefile 2007-06-01 20:04:45.000000000 +0200 -@@ -19,4 +19,4 @@ - obj-$(CONFIG_KEYBOARD_OMAP) += omap-keypad.o - obj-$(CONFIG_KEYBOARD_AAED2000) += aaed2000_kbd.o - obj-$(CONFIG_KEYBOARD_GPIO) += gpio_keys.o -- -+obj-$(CONFIG_KEYBOARD_PXA) += pxakbd.o -Index: linux-2.6.21/include/asm-arm/arch-pxa/kbd.h -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-2.6.21/include/asm-arm/arch-pxa/kbd.h 2007-06-01 20:04:45.000000000 +0200 -@@ -0,0 +1,28 @@ -+/* -+ * kbd_pxa.h -+ * -+ * Copyright (C) 2006 Harald Welte <laforge@openezx.org> -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ * -+ */ -+#ifndef _KBD_PXA_H_ -+#define _KBD_PXA_H_ -+ -+struct pxakbd_platform_data { -+ int (*init)(void); /* init gpio, etc. */ -+ unsigned int scan_interval; -+ struct { -+ unsigned int rows; -+ unsigned int cols; -+ unsigned char *keycode; -+ } matrix; -+ struct { -+ unsigned int num; -+ unsigned char *keycode; -+ } direct; -+}; -+ -+#endif -Index: linux-2.6.21/drivers/input/keyboard/pxakbd.c -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-2.6.21/drivers/input/keyboard/pxakbd.c 2007-06-02 10:41:13.000000000 +0200 -@@ -0,0 +1,403 @@ -+/* -+ * Driver for Motorola EZX phone "keyboard" -+ * -+ * (C) 2006 by Harald Welte <laforge@openezx.org> -+ * -+ * May, 2007 - Daniel Ribeiro <drwyrm@gmail.com> -+ * pm callbacks -+ */ -+ -+#include <linux/kernel.h> -+#include <linux/module.h> -+#include <linux/interrupt.h> -+#include <linux/input.h> -+#include <linux/spinlock.h> -+#include <linux/platform_device.h> -+ -+#include <asm/hardware.h> -+#include <asm/io.h> -+#include <asm/irq.h> -+ -+#include <asm/arch/kbd.h> -+#include <asm/arch/irqs.h> -+#include <asm/arch/pxa-regs.h> -+ -+#if 0 -+#define DEBUGP(x, args ...) printk(x, ## args) -+#else -+#define DEBUGP(x, args ...) -+#endif -+ -+/* per-keyboard private data structure */ -+struct pxakbd { -+ struct input_dev *input; -+ struct timer_list timer; -+ spinlock_t lock; -+ -+ struct resource *res; -+ unsigned int irq; -+ u_int32_t kpc; -+ u_int32_t kpkdi; -+ -+ struct pxakbd_platform_data *pd; -+}; -+ -+static int pxakbd_scan_direct(struct pxakbd *pxakbd) -+{ -+ u_int32_t kpdk; -+ unsigned int i; -+ int num_pressed = 0; -+ -+ kpdk = KPDK & 0x000000ff; -+ for (i = 0; i < pxakbd->pd->direct.num; i++) { -+ int pressed = 0; -+ -+ if (kpdk & (1 << i)) { -+ pressed = 1; -+ num_pressed++; -+ DEBUGP("pxakbd: pressed: direct %u\n", i); -+ } -+ if (pxakbd->pd->direct.keycode[i] != KEY_RESERVED) { -+ DEBUGP( "pxakbd: sending to input layer: keycode = %d, pressed = %d\n", pxakbd->pd->direct.keycode[i], pressed ); -+ input_report_key(pxakbd->input, pxakbd->pd->direct.keycode[i], -+ pressed); -+ } -+ } -+ return num_pressed; -+} -+ -+/* read the full 8x8 matrix from the PXA27x keypad controller */ -+static inline void __read_matrix(u_int8_t *matrix) -+{ -+ u_int32_t tmp; -+ u_int8_t row; -+ -+ /* Fill the matrix by rows */ -+ -+ tmp = KPASMKP0; -+ for (row=0; row<8; row++) { -+ /* zero the matrix on the first time, then keep ORing */ -+ matrix[row] = ((tmp >> row) & 1); -+ matrix[row] |= ((tmp >> (16 + row)) & 1) << 1; -+ } -+ -+ tmp = KPASMKP1; -+ for (row=0; row<8; row++) { -+ matrix[row] |= ((tmp >> row) & 1) << 2; -+ matrix[row] |= ((tmp >> (16 + row)) & 1) << 3; -+ } -+ -+ tmp = KPASMKP2; -+ for (row=0; row<8; row++) { -+ matrix[row] |= ((tmp >> row) & 1) << 4; -+ matrix[row] |= ((tmp >> (16 + row)) & 1) << 5; -+ } -+ -+ tmp = KPASMKP3; -+ for (row=0; row<8; row++) { -+ matrix[row] |= ((tmp >> row) & 1) << 6; -+ matrix[row] |= ((tmp >> (16 + row)) & 1) << 7; -+ } -+} -+ -+/* compare current matrix with last, generate 'diff' events */ -+static int __cmp_matrix_gen_events(struct pxakbd *pxakbd, u_int8_t *matrix) -+{ -+ unsigned int i; -+ int num_pressed = 0; -+ -+ /* iterate over the matrix */ -+ for (i = 0; i < pxakbd->pd->matrix.rows; i++) { -+ unsigned int j; -+ for (j = 0; j < pxakbd->pd->matrix.cols; j++) { -+ u_int32_t scancode = -+ (i * pxakbd->pd->matrix.cols) + j; -+ int pressed = matrix[i] & (1 << j); -+ -+ if (pressed) { -+ DEBUGP("pxakbd: pressed: %u/%u\n", i, j); -+ num_pressed++; -+ } -+ -+ input_report_key(pxakbd->input, -+ pxakbd->pd->matrix.keycode[scancode], pressed); -+ } -+ } -+ -+ return num_pressed; -+} -+ -+/* scan the matrix keypad */ -+static int pxakbd_scan_matrix(struct pxakbd *pxakbd) -+{ -+ int num_pressed; -+ u_int32_t kpas; -+ u_int8_t matrix[8]; -+ -+ kpas = KPAS; -+ -+ if ((kpas & KPAS_MUKP) == KPAS_MUKP_NONE) { -+ /* no keys pressed */ -+ memset(matrix, 0, sizeof(matrix)); -+ } else if ((kpas & KPAS_MUKP) == KPAS_MUKP_ONE) { -+ /* one key pressed */ -+ u_int8_t row = (kpas & KPAS_RP) >> 4; -+ u_int8_t col = kpas & KPAS_CP; -+ -+ if (row == 0x0f || col == 0x0f) { -+ printk(KERN_WARNING "pxakbd: col or row invalid!\n"); -+ return -1; -+ } -+ -+ /* clear the matrix and set the single pressed key */ -+ memset(matrix, 0, sizeof(matrix)); -+ matrix[row] |= (1 << col); -+ } else { -+ /* multiple keys pressed */ -+ __read_matrix(matrix); -+ } -+ -+ num_pressed = __cmp_matrix_gen_events(pxakbd, matrix); -+ -+ return num_pressed; -+} -+ -+static void pxakbd_timer_callback(unsigned long data) -+{ -+ unsigned long flags; -+ struct pxakbd *pxakbd = (struct pxakbd *) data; -+ unsigned int num_pressed; -+ -+ spin_lock_irqsave(&pxakbd->lock, flags); -+ -+ num_pressed = pxakbd_scan_direct(pxakbd); -+ num_pressed += pxakbd_scan_matrix(pxakbd); -+ -+ spin_unlock_irqrestore(&pxakbd->lock, flags); -+ -+ /* propagate events up the input stack */ -+ input_sync(pxakbd->input); -+} -+ -+static irqreturn_t pxakbd_interrupt(int irq, void *dummy) -+{ -+ struct pxakbd *pxakbd = dummy; -+ u_int32_t kpc; -+ int handled = 0; -+ int num_pressed = 0; -+ -+ /* read and clear interrupt */ -+ kpc = KPC; -+ -+ if (kpc & KPC_DI) { -+ num_pressed += pxakbd_scan_direct(pxakbd); -+ handled = 1; -+ } -+ -+ if (kpc & KPC_MI) { -+ while (KPAS & KPAS_SO) { -+ /* wait for scan to complete beforereading scan regs */ -+ cpu_relax(); -+ } -+ num_pressed += pxakbd_scan_matrix(pxakbd); -+ handled = 1; -+ } -+ -+ /* If any keys are currently pressed, we need to start the timer to detect -+ * key release. */ -+ if (num_pressed) -+ mod_timer(&pxakbd->timer, jiffies + pxakbd->pd->scan_interval); -+ -+ /* propagate events up the input stack */ -+ input_sync(pxakbd->input); -+ -+ return IRQ_RETVAL(handled); -+} -+ -+static int __init pxakbd_probe(struct platform_device *pdev) -+{ -+ struct pxakbd *pxakbd; -+ struct input_dev *input_dev; -+ struct resource *r; -+ int i; -+ int ret = -ENOMEM; -+ -+ int rows, cols, n_direct; -+ -+ if (!pdev->dev.platform_data) { -+ printk(KERN_ERR "pxakbd: platform data not set\n"); -+ ret = -ENODEV; -+ goto out; -+ } -+ -+ pxakbd = kzalloc(sizeof(*pxakbd), GFP_KERNEL); -+ if (!pxakbd) -+ goto out; -+ -+ input_dev = input_allocate_device(); -+ if (!input_dev) -+ goto out_pxa; -+ -+ spin_lock_init(&pxakbd->lock); -+ pxakbd->irq = platform_get_irq(pdev, 0); -+ r = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ if (!r || pxakbd->irq == NO_IRQ) { -+ printk(KERN_ERR "pxakbd: invalid resources\n"); -+ ret = -EBUSY; -+ goto out_idev; -+ } -+ -+ pxakbd->input = input_dev; -+ init_timer(&pxakbd->timer); -+ pxakbd->timer.function = pxakbd_timer_callback; -+ pxakbd->timer.data = (unsigned long) pxakbd; -+ pxakbd->pd = pdev->dev.platform_data; -+ pxakbd->res = r; -+ -+ rows = pxakbd->pd->matrix.rows; -+ cols = pxakbd->pd->matrix.cols; -+ n_direct = pxakbd->pd->direct.num; -+ -+ input_dev->name = "pxa-keyboard"; -+ input_dev->phys = "pxakbd/input0"; -+ input_dev->id.bustype = BUS_HOST; -+ input_dev->id.vendor = 0x0001; -+ input_dev->id.product = 0x0001; -+ input_dev->id.version = 0x0001; -+ input_dev->cdev.dev = &pdev->dev; -+ input_dev->private = pxakbd; -+ -+ input_dev->evbit[0] = BIT(EV_KEY)|BIT(EV_REP); -+ -+ input_dev->keycodesize = sizeof(unsigned char); -+ input_dev->keycodemax = (rows*cols)+n_direct; -+ input_dev->keycode = kmalloc(input_dev->keycodemax*input_dev->keycodesize, -+ GFP_KERNEL); -+ if (!input_dev->keycode){ -+ ret = -ENOMEM; -+ goto out_idev; -+ } -+ -+ memcpy(input_dev->keycode, pxakbd->pd->matrix.keycode, rows*cols); -+ -+ memcpy(input_dev->keycode+(rows*cols), -+ pxakbd->pd->direct.keycode, -+ n_direct); -+ -+ for (i = 0; i < rows*cols; i++) -+ set_bit(pxakbd->pd->matrix.keycode[i], input_dev->keybit); -+ -+ for (i = 0; i < n_direct; i++) -+ set_bit(pxakbd->pd->direct.keycode[i], input_dev->keybit); -+ -+ clear_bit(0, input_dev->keybit); -+ -+ if (request_irq(pxakbd->irq, pxakbd_interrupt, 0, "pxakbd", pxakbd)) { -+ printk(KERN_ERR "pxakbd: can't request irq %d\n", pxakbd->irq); -+ ret = -EBUSY; -+ goto out_idev; -+ } -+ -+ r = request_mem_region(r->start, 0x4c, "pxakbd"); -+ if (!r) { -+ printk(KERN_ERR "pxakbd: can't request memregion\n"); -+ ret = -EBUSY; -+ goto out_irq; -+ } -+ -+ /* set up gpio */ -+ pxakbd->pd->init(); -+ -+ /* set keypad control register */ -+ KPC = (KPC_ASACT | /* automatic scan on activity */ -+ KPC_ME | KPC_DE | /* matrix and direct keypad enabled */ -+ ((pxakbd->pd->matrix.cols-1)<<23) | /* columns */ -+ ((pxakbd->pd->matrix.rows-1)<<26) | /* rows */ -+ ((pxakbd->pd->direct.num-1)<<6) | /* direct keys */ -+ KPC_MS_ALL); /* scan all columns */ -+ -+ pxa_set_cken(CKEN19_KEYPAD, 1); -+ -+ KPC |= (KPC_DIE | KPC_MIE); /* enable matrix and direct keyboard */ -+ -+ KPKDI = 0x40; /* matrix key debounce interval: 0x40 */ -+ -+ platform_set_drvdata(pdev, pxakbd); -+ -+ return input_register_device(pxakbd->input); -+ -+out_drvdata: -+ platform_set_drvdata(pdev, NULL); -+out_mem: -+ release_resource(r); -+out_irq: -+ free_irq(pxakbd->irq, pxakbd); -+out_idev: -+ kfree(input_dev->keycode); -+ input_free_device(input_dev); -+out_pxa: -+ kfree(pxakbd); -+out: -+ return ret; -+} -+ -+static int pxakbd_remove(struct platform_device *pdev) -+{ -+ struct pxakbd *pxakbd = platform_get_drvdata(pdev); -+ -+ kfree(pxakbd->input->keycode); -+ input_unregister_device(pxakbd->input); -+ platform_set_drvdata(pdev, NULL); -+ release_resource(pxakbd->res); -+ free_irq(pxakbd->irq, pxakbd); -+ kfree(pxakbd); -+ -+ return 0; -+} -+ -+static int pxakbd_suspend(struct platform_device *pdev, pm_message_t state) -+{ -+ struct pxakbd *pxakbd = platform_get_drvdata(pdev); -+ -+ pxakbd->kpc = KPC; -+ pxakbd->kpkdi = KPKDI; -+ -+ return 0; -+} -+ -+static int pxakbd_resume(struct platform_device *pdev) -+{ -+ struct pxakbd *pxakbd = platform_get_drvdata(pdev); -+ -+ KPC = pxakbd->kpc; -+ KPKDI = pxakbd->kpkdi; -+ -+ return 0; -+} -+ -+static struct platform_driver pxakbd_driver = { -+ .probe = &pxakbd_probe, -+ .remove = &pxakbd_remove, -+ .suspend = &pxakbd_suspend, -+ .resume = &pxakbd_resume, -+ .driver = { -+ .name = "pxa-keyboard", -+ }, -+}; -+ -+static int __devinit pxakbd_init(void) -+{ -+ return platform_driver_register(&pxakbd_driver); -+} -+ -+static void __exit pxakbd_exit(void) -+{ -+ platform_driver_unregister(&pxakbd_driver); -+} -+ -+module_init(pxakbd_init); -+module_exit(pxakbd_exit); -+ -+MODULE_AUTHOR("Harald Welte <laforge@openezx.org>"); -+MODULE_DESCRIPTION("Driver for Intel PXA27x keypad controller"); -+MODULE_LICENSE("GPL"); -Index: linux-2.6.21/include/asm-arm/arch-pxa/pxa-regs.h -=================================================================== ---- linux-2.6.21.orig/include/asm-arm/arch-pxa/pxa-regs.h 2007-06-01 20:04:45.000000000 +0200 -+++ linux-2.6.21/include/asm-arm/arch-pxa/pxa-regs.h 2007-06-01 20:04:45.000000000 +0200 -@@ -2165,6 +2165,11 @@ - #define KPMK_MKP (0x1 << 31) - #define KPAS_SO (0x1 << 31) - #define KPASMKPx_SO (0x1 << 31) -+#define KPAS_RP (0x000000f0) -+#define KPAS_CP (0x0000000f) -+#define KPAS_MUKP (0x7c000000) -+#define KPAS_MUKP_ONE (0x04000000) -+#define KPAS_MUKP_NONE (0x00000000) - - /* - * UHC: USB Host Controller (OHCI-like) register definitions |