]> code.ossystems Code Review - openembedded-core.git/commitdiff
linux-rp-2.6.23: Keypad driver for Zylonite.
authorSamuel Ortiz <sameo@openedhand.com>
Tue, 19 Feb 2008 01:09:57 +0000 (01:09 +0000)
committerSamuel Ortiz <sameo@openedhand.com>
Tue, 19 Feb 2008 01:09:57 +0000 (01:09 +0000)
This is a backport from Eric Miao's patchset.

git-svn-id: https://svn.o-hand.com/repos/poky/trunk@3826 311d38ba-8fff-0310-9ca6-ca027cbcb966

meta/packages/linux/linux-rp-2.6.23/defconfig-zylonite
meta/packages/linux/linux-rp-2.6.23/zylonite_keypad-r0.patch [new file with mode: 0644]
meta/packages/linux/linux-rp_2.6.23.bb

index 14ea6c355f7f91d805124b2588a8f95445080270..4eb064b5ddfbcc4776b5b0eebe52c9651f2bd18a 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
 # Linux kernel version: 2.6.23
-# Tue Feb 12 18:04:14 2008
+# Mon Feb 18 01:42:46 2008
 #
 CONFIG_ARM=y
 CONFIG_SYS_SUPPORTS_APM_EMULATION=y
@@ -729,11 +729,13 @@ CONFIG_KEYBOARD_ATKBD=y
 # CONFIG_KEYBOARD_XTKBD is not set
 # CONFIG_KEYBOARD_NEWTON is not set
 # CONFIG_KEYBOARD_STOWAWAY is not set
+CONFIG_KEYBOARD_PXA27x=y
 # CONFIG_KEYBOARD_GPIO is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_INPUT_JOYSTICK is not set
 # CONFIG_INPUT_TABLET is not set
 CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_ZYLONITE=y
 # CONFIG_TOUCHSCREEN_FUJITSU is not set
 # CONFIG_TOUCHSCREEN_GUNZE is not set
 # CONFIG_TOUCHSCREEN_ELO is not set
diff --git a/meta/packages/linux/linux-rp-2.6.23/zylonite_keypad-r0.patch b/meta/packages/linux/linux-rp-2.6.23/zylonite_keypad-r0.patch
new file mode 100644 (file)
index 0000000..1889b38
--- /dev/null
@@ -0,0 +1,1187 @@
+Eric Miao's pxa keypad patchset backport.
+---
+ arch/arm/mach-pxa/devices.h                |    1 
+ arch/arm/mach-pxa/generic.c                |   31 +
+ arch/arm/mach-pxa/pxa27x.c                 |    2 
+ arch/arm/mach-pxa/pxa300.c                 |    6 
+ arch/arm/mach-pxa/pxa3xx.c                 |    1 
+ arch/arm/mach-pxa/zylonite.c               |   68 +++
+ drivers/input/keyboard/Kconfig             |    8 
+ drivers/input/keyboard/Makefile            |    2 
+ drivers/input/keyboard/pxa27x_keyboard.c   |  273 -------------
+ drivers/input/keyboard/pxa27x_keypad.c     |  575 +++++++++++++++++++++++++++++
+ include/asm-arm/arch-pxa/irqs.h            |    2 
+ include/asm-arm/arch-pxa/pxa27x_keyboard.h |   13 
+ include/asm-arm/arch-pxa/pxa27x_keypad.h   |   58 ++
+ 13 files changed, 745 insertions(+), 295 deletions(-)
+
+Index: linux-2.6.23-z-input/drivers/input/keyboard/Kconfig
+===================================================================
+--- linux-2.6.23-z-input.orig/drivers/input/keyboard/Kconfig   2008-02-18 01:43:28.000000000 +0100
++++ linux-2.6.23-z-input/drivers/input/keyboard/Kconfig        2008-02-18 01:43:28.000000000 +0100
+@@ -218,13 +218,13 @@
+         module will be called omap-keypad.
+ config KEYBOARD_PXA27x
+-      tristate "PXA27x keyboard support"
+-      depends on PXA27x
++      tristate "PXA27x/PXA3xx keypad support"
++      depends on PXA27x || PXA3xx
+       help
+-        Enable support for PXA27x matrix keyboard controller
++        Enable support for PXA27x/PXA3xx keypad controller
+         To compile this driver as a module, choose M here: the
+-        module will be called pxa27x_keyboard.
++        module will be called pxa27x_keypad.
+ config KEYBOARD_AAED2000
+       tristate "AAED-2000 keyboard"
+Index: linux-2.6.23-z-input/drivers/input/keyboard/Makefile
+===================================================================
+--- linux-2.6.23-z-input.orig/drivers/input/keyboard/Makefile  2008-02-18 01:43:28.000000000 +0100
++++ linux-2.6.23-z-input/drivers/input/keyboard/Makefile       2008-02-18 01:43:28.000000000 +0100
+@@ -18,7 +18,7 @@
+ obj-$(CONFIG_KEYBOARD_HIL)            += hil_kbd.o
+ obj-$(CONFIG_KEYBOARD_HIL_OLD)                += hilkbd.o
+ obj-$(CONFIG_KEYBOARD_OMAP)           += omap-keypad.o
+-obj-$(CONFIG_KEYBOARD_PXA27x)         += pxa27x_keyboard.o
++obj-$(CONFIG_KEYBOARD_PXA27x)         += pxa27x_keypad.o
+ obj-$(CONFIG_KEYBOARD_AAED2000)               += aaed2000_kbd.o
+ obj-$(CONFIG_KEYBOARD_GPIO)           += gpio_keys.o
+ obj-$(CONFIG_KEYBOARD_ASIC3)          += asic3_keys.o
+Index: linux-2.6.23-z-input/drivers/input/keyboard/pxa27x_keypad.c
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.23-z-input/drivers/input/keyboard/pxa27x_keypad.c        2008-02-19 01:40:04.000000000 +0100
+@@ -0,0 +1,575 @@
++/*
++ * linux/drivers/input/keyboard/pxa27x_keypad.c
++ *
++ * Driver for the pxa27x matrix keyboard controller.
++ *
++ * Created:   Feb 22, 2007
++ * Author:    Rodolfo Giometti <giometti@linux.it>
++ *
++ * Based on a previous implementations by Kevin O'Connor
++ * <kevin_at_koconnor.net> and Alex Osborne <bobofdoom@gmail.com> and
++ * on some suggestions by Nicolas Pitre <nico@cam.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.
++ */
++
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/interrupt.h>
++#include <linux/input.h>
++#include <linux/device.h>
++#include <linux/platform_device.h>
++#include <linux/clk.h>
++#include <linux/err.h>
++
++#include <asm/mach-types.h>
++#include <asm/mach/arch.h>
++#include <asm/mach/map.h>
++
++#include <asm/arch/hardware.h>
++#include <asm/arch/mfp.h>
++#include <asm/arch/pxa27x_keypad.h>
++
++#define BIT_MASK(nr)            (1UL << ((nr) % BITS_PER_LONG))
++
++/*
++ * Keypad Controller registers
++ */
++#define KPC             0x0000 /* Keypad Control register */
++#define KPDK            0x0008 /* Keypad Direct Key register */
++#define KPREC           0x0010 /* Keypad Rotary Encoder register */
++#define KPMK            0x0018 /* Keypad Matrix Key register */
++#define KPAS            0x0020 /* Keypad Automatic Scan register */
++
++/* Keypad Automatic Scan Multiple Key Presser register 0-3 */
++#define KPASMKP0        0x0028
++#define KPASMKP1        0x0030
++#define KPASMKP2        0x0038
++#define KPASMKP3        0x0040
++#define KPKDI           0x0048
++
++/* bit definitions */
++#define KPC_MKRN(n)   ((((n) - 1) & 0x7) << 26) /* matrix key row number */
++#define KPC_MKCN(n)   ((((n) - 1) & 0x7) << 23) /* matrix key column number */
++#define KPC_DKN(n)    ((((n) - 1) & 0x7) << 6)  /* direct key number */
++
++#define KPC_AS          (0x1 << 30)  /* Automatic Scan bit */
++#define KPC_ASACT       (0x1 << 29)  /* Automatic Scan on Activity */
++#define KPC_MI          (0x1 << 22)  /* Matrix interrupt bit */
++#define KPC_IMKP        (0x1 << 21)  /* Ignore Multiple Key Press */
++
++#define KPC_MS(n)     (0x1 << (13 + (n)))     /* Matrix scan line 'n' */
++#define KPC_MS_ALL      (0xff << 13)
++
++#define KPC_ME          (0x1 << 12)  /* Matrix Keypad Enable */
++#define KPC_MIE         (0x1 << 11)  /* Matrix Interrupt Enable */
++#define KPC_DK_DEB_SEL        (0x1 <<  9)  /* Direct Keypad Debounce Select */
++#define KPC_DI          (0x1 <<  5)  /* Direct key interrupt bit */
++#define KPC_RE_ZERO_DEB (0x1 <<  4)  /* Rotary Encoder Zero Debounce */
++#define KPC_REE1        (0x1 <<  3)  /* Rotary Encoder1 Enable */
++#define KPC_REE0        (0x1 <<  2)  /* Rotary Encoder0 Enable */
++#define KPC_DE          (0x1 <<  1)  /* Direct Keypad Enable */
++#define KPC_DIE         (0x1 <<  0)  /* Direct Keypad interrupt Enable */
++
++#define KPDK_DKP        (0x1 << 31)
++#define KPDK_DK(n)    ((n) & 0xff)
++
++#define KPREC_OF1       (0x1 << 31)
++#define kPREC_UF1       (0x1 << 30)
++#define KPREC_OF0       (0x1 << 15)
++#define KPREC_UF0       (0x1 << 14)
++
++#define KPREC_RECOUNT0(n)     ((n) & 0xff)
++#define KPREC_RECOUNT1(n)     (((n) >> 16) & 0xff)
++
++#define KPMK_MKP        (0x1 << 31)
++#define KPAS_SO         (0x1 << 31)
++#define KPASMKPx_SO     (0x1 << 31)
++
++#define KPAS_MUKP(n)  (((n) >> 26) & 0x1f)
++#define KPAS_RP(n)    (((n) >> 4) & 0xf)
++#define KPAS_CP(n)    ((n) & 0xf)
++
++#define KPASMKP_MKC_MASK      (0xff)
++
++#define keypad_readl(off)     __raw_readl(keypad->mmio_base + (off))
++#define keypad_writel(off, v) __raw_writel((v), keypad->mmio_base + (off))
++
++#define MAX_MATRIX_KEY_NUM    (8 * 8)
++
++struct pxa27x_keypad {
++      struct pxa27x_keypad_platform_data *pdata;
++
++      struct clk *clk;
++      struct input_dev *input_dev;
++      void __iomem *mmio_base;
++
++      /* matrix key code map */
++      unsigned int matrix_keycodes[MAX_MATRIX_KEY_NUM];
++
++      /* state row bits of each column scan */
++      uint32_t matrix_key_state[MAX_MATRIX_KEY_COLS];
++      uint32_t direct_key_state;
++
++      unsigned int direct_key_mask;
++
++      int rotary_rel_code[2];
++      int rotary_up_key[2];
++      int rotary_down_key[2];
++};
++
++static void pxa27x_keypad_build_keycode(struct pxa27x_keypad *keypad)
++{
++      struct pxa27x_keypad_platform_data *pdata = keypad->pdata;
++      struct input_dev *input_dev = keypad->input_dev;
++      unsigned int *key;
++      int i;
++
++      key = &pdata->matrix_key_map[0];
++      for (i = 0; i < pdata->matrix_key_map_size; i++, key++) {
++              int row = ((*key) >> 28) & 0xf;
++              int col = ((*key) >> 24) & 0xf;
++              int code = (*key) & 0xffffff;
++
++              keypad->matrix_keycodes[(row << 3) + col] = code;
++              set_bit(code, input_dev->keybit);
++      }
++
++      keypad->rotary_up_key[0] = pdata->rotary0_up_key;
++      keypad->rotary_up_key[1] = pdata->rotary1_up_key;
++      keypad->rotary_down_key[0] = pdata->rotary0_down_key;
++      keypad->rotary_down_key[1] = pdata->rotary1_down_key;
++      keypad->rotary_rel_code[0] = pdata->rotary0_rel_code;
++      keypad->rotary_rel_code[1] = pdata->rotary1_rel_code;
++
++      if (pdata->rotary0_up_key && pdata->rotary0_down_key) {
++              set_bit(pdata->rotary0_up_key, input_dev->keybit);
++              set_bit(pdata->rotary0_down_key, input_dev->keybit);
++      } else
++              set_bit(pdata->rotary0_rel_code, input_dev->relbit);
++
++      if (pdata->rotary1_up_key && pdata->rotary1_down_key) {
++              set_bit(pdata->rotary1_up_key, input_dev->keybit);
++              set_bit(pdata->rotary1_down_key, input_dev->keybit);
++      } else
++              set_bit(pdata->rotary1_rel_code, input_dev->relbit);
++}
++
++static inline unsigned int lookup_matrix_keycode(
++              struct pxa27x_keypad *keypad, int row, int col)
++{
++      return keypad->matrix_keycodes[(row << 3) + col];
++}
++
++static void pxa27x_keypad_scan_matrix(struct pxa27x_keypad *keypad)
++{
++      struct pxa27x_keypad_platform_data *pdata = keypad->pdata;
++      int row, col, num_keys_pressed = 0;
++      uint32_t new_state[MAX_MATRIX_KEY_COLS];
++      uint32_t kpas = keypad_readl(KPAS);
++
++      num_keys_pressed = KPAS_MUKP(kpas);
++
++      memset(new_state, 0, sizeof(new_state));
++
++      if (num_keys_pressed == 0)
++              goto scan;
++
++      if (num_keys_pressed == 1) {
++              col = KPAS_CP(kpas);
++              row = KPAS_RP(kpas);
++
++              /* if invalid row/col, treat as no key pressed */
++              if (col >= pdata->matrix_key_cols ||
++                  row >= pdata->matrix_key_rows)
++                      goto scan;
++
++              new_state[col] = (1 << row);
++              goto scan;
++      }
++
++      if (num_keys_pressed > 1) {
++              uint32_t kpasmkp0 = keypad_readl(KPASMKP0);
++              uint32_t kpasmkp1 = keypad_readl(KPASMKP1);
++              uint32_t kpasmkp2 = keypad_readl(KPASMKP2);
++              uint32_t kpasmkp3 = keypad_readl(KPASMKP3);
++
++              new_state[0] = kpasmkp0 & KPASMKP_MKC_MASK;
++              new_state[1] = (kpasmkp0 >> 16) & KPASMKP_MKC_MASK;
++              new_state[2] = kpasmkp1 & KPASMKP_MKC_MASK;
++              new_state[3] = (kpasmkp1 >> 16) & KPASMKP_MKC_MASK;
++              new_state[4] = kpasmkp2 & KPASMKP_MKC_MASK;
++              new_state[5] = (kpasmkp2 >> 16) & KPASMKP_MKC_MASK;
++              new_state[6] = kpasmkp3 & KPASMKP_MKC_MASK;
++              new_state[7] = (kpasmkp3 >> 16) & KPASMKP_MKC_MASK;
++      }
++scan:
++      for (col = 0; col < pdata->matrix_key_cols; col++) {
++              uint32_t bits_changed;
++
++              bits_changed = keypad->matrix_key_state[col] ^ new_state[col];
++              if (bits_changed == 0)
++                      continue;
++
++              for (row = 0; row < pdata->matrix_key_rows; row++) {
++                      if ((bits_changed & (1 << row)) == 0)
++                              continue;
++
++                      input_report_key(keypad->input_dev,
++                              lookup_matrix_keycode(keypad, row, col),
++                              new_state[col] & (1 << row));
++              }
++      }
++      input_sync(keypad->input_dev);
++      memcpy(keypad->matrix_key_state, new_state, sizeof(new_state));
++}
++
++#define DEFAULT_KPREC (0x007f007f)
++
++static inline int rotary_delta(uint32_t kprec)
++{
++      if (kprec & KPREC_OF0)
++              return (kprec & 0xff) + 0x7f;
++      else if (kprec & KPREC_UF0)
++              return (kprec & 0xff) - 0x7f - 0xff;
++      else
++              return (kprec & 0xff) - 0x7f;
++}
++
++static void report_rotary_event(struct pxa27x_keypad *keypad, int r, int delta)
++{
++      struct input_dev *dev = keypad->input_dev;
++
++      if (delta == 0)
++              return;
++
++      if (keypad->rotary_up_key[r] && keypad->rotary_down_key[r]) {
++              int keycode = (delta > 0) ? keypad->rotary_up_key[r] :
++                                          keypad->rotary_down_key[r];
++
++              /* simulate a press-n-release */
++              input_report_key(dev, keycode, 1);
++              input_sync(dev);
++              input_report_key(dev, keycode, 0);
++              input_sync(dev);
++      } else {
++              input_report_rel(dev, keypad->rotary_rel_code[r], delta);
++              input_sync(dev);
++      }
++}
++
++static void pxa27x_keypad_scan_rotary(struct pxa27x_keypad *keypad)
++{
++      struct pxa27x_keypad_platform_data *pdata = keypad->pdata;
++      uint32_t kprec;
++
++      /* read and reset to default count value */
++      kprec = keypad_readl(KPREC);
++      keypad_writel(KPREC, DEFAULT_KPREC);
++
++      if (pdata->enable_rotary0)
++              report_rotary_event(keypad, 0, rotary_delta(kprec));
++
++      if (pdata->enable_rotary1)
++              report_rotary_event(keypad, 1, rotary_delta(kprec >> 16));
++}
++
++static void pxa27x_keypad_scan_direct(struct pxa27x_keypad *keypad)
++{
++      struct pxa27x_keypad_platform_data *pdata = keypad->pdata;
++      unsigned int new_state;
++      uint32_t kpdk, bits_changed;
++      int i;
++
++      kpdk = keypad_readl(KPDK);
++
++      if (pdata->enable_rotary0 || pdata->enable_rotary1)
++              pxa27x_keypad_scan_rotary(keypad);
++
++      if (pdata->direct_key_map == NULL)
++              return;
++
++      new_state = KPDK_DK(kpdk) & keypad->direct_key_mask;
++      bits_changed = keypad->direct_key_state ^ new_state;
++
++      if (bits_changed == 0)
++              return;
++
++      for (i = 0; i < pdata->direct_key_num; i++) {
++              if (bits_changed & (1 << i))
++                      input_report_key(keypad->input_dev,
++                                      pdata->direct_key_map[i],
++                                      (new_state & (1 << i)));
++      }
++      input_sync(keypad->input_dev);
++      keypad->direct_key_state = new_state;
++}
++
++static irqreturn_t pxa27x_keypad_irq_handler(int irq, void *dev_id)
++{
++      struct pxa27x_keypad *keypad = dev_id;
++      unsigned long kpc = keypad_readl(KPC);
++
++      if (kpc & KPC_DI)
++              pxa27x_keypad_scan_direct(keypad);
++
++      if (kpc & KPC_MI)
++              pxa27x_keypad_scan_matrix(keypad);
++
++      return IRQ_HANDLED;
++}
++
++static void pxa27x_keypad_config(struct pxa27x_keypad *keypad)
++{
++      struct pxa27x_keypad_platform_data *pdata = keypad->pdata;
++      unsigned int mask = 0, direct_key_num = 0;
++      unsigned long kpc = 0;
++
++      /* enable matrix keys with automatic scan */
++      if (pdata->matrix_key_rows && pdata->matrix_key_cols) {
++              kpc |= KPC_ASACT | KPC_MIE | KPC_ME | KPC_MS_ALL;
++              kpc |= KPC_MKRN(pdata->matrix_key_rows) |
++                     KPC_MKCN(pdata->matrix_key_cols);
++      }
++
++      /* enable rotary key, debounce interval same as direct keys */
++      if (pdata->enable_rotary0) {
++              mask |= 0x03;
++              direct_key_num = 2;
++              kpc |= KPC_REE0;
++      }
++
++      if (pdata->enable_rotary1) {
++              mask |= 0x0c;
++              direct_key_num = 4;
++              kpc |= KPC_REE1;
++      }
++
++      if (pdata->direct_key_num > direct_key_num)
++              direct_key_num = pdata->direct_key_num;
++
++      keypad->direct_key_mask = ((2 << direct_key_num) - 1) & ~mask;
++
++      /* enable direct key */
++      if (direct_key_num)
++              kpc |= KPC_DE | KPC_DIE | KPC_DKN(direct_key_num);
++
++      keypad_writel(KPC, kpc | KPC_RE_ZERO_DEB);
++      keypad_writel(KPREC, DEFAULT_KPREC);
++      keypad_writel(KPKDI, pdata->debounce_interval);
++}
++
++static int pxa27x_keypad_open(struct input_dev *dev)
++{
++      struct pxa27x_keypad *keypad = input_get_drvdata(dev);
++
++      /* Enable unit clock */
++      clk_enable(keypad->clk);
++      pxa27x_keypad_config(keypad);
++
++      return 0;
++}
++
++static void pxa27x_keypad_close(struct input_dev *dev)
++{
++      struct pxa27x_keypad *keypad = input_get_drvdata(dev);
++
++      /* Disable clock unit */
++      clk_disable(keypad->clk);
++}
++
++#ifdef CONFIG_PM
++static int pxa27x_keypad_suspend(struct platform_device *pdev, pm_message_t state)
++{
++      struct pxa27x_keypad *keypad = platform_get_drvdata(pdev);
++
++      clk_disable(keypad->clk);
++      return 0;
++}
++
++static int pxa27x_keypad_resume(struct platform_device *pdev)
++{
++      struct pxa27x_keypad *keypad = platform_get_drvdata(pdev);
++      struct input_dev *input_dev = keypad->input_dev;
++
++      mutex_lock(&input_dev->mutex);
++
++      if (input_dev->users) {
++              /* Enable unit clock */
++              clk_enable(keypad->clk);
++              pxa27x_keypad_config(keypad);
++      }
++
++      mutex_unlock(&input_dev->mutex);
++
++      return 0;
++}
++#else
++#define pxa27x_keypad_suspend NULL
++#define pxa27x_keypad_resume  NULL
++#endif
++
++#define res_size(res) ((res)->end - (res)->start + 1)
++
++static int __devinit pxa27x_keypad_probe(struct platform_device *pdev)
++{
++      struct pxa27x_keypad *keypad;
++      struct input_dev *input_dev;
++      struct resource *res;
++      int irq, error;
++
++      keypad = kzalloc(sizeof(struct pxa27x_keypad), GFP_KERNEL);
++      if (keypad == NULL) {
++              dev_err(&pdev->dev, "failed to allocate driver data\n");
++              return -ENOMEM;
++      }
++
++      keypad->pdata = pdev->dev.platform_data;
++      if (keypad->pdata == NULL) {
++              dev_err(&pdev->dev, "no platform data defined\n");
++              error = -EINVAL;
++              goto failed_free;
++      }
++
++      irq = platform_get_irq(pdev, 0);
++      if (irq < 0) {
++              dev_err(&pdev->dev, "failed to get keypad irq\n");
++              error = -ENXIO;
++              goto failed_free;
++      }
++
++      res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++      if (res == NULL) {
++              dev_err(&pdev->dev, "failed to get I/O memory\n");
++              error = -ENXIO;
++              goto failed_free;
++      }
++
++      res = request_mem_region(res->start, res_size(res), pdev->name);
++      if (res == NULL) {
++              dev_err(&pdev->dev, "failed to request I/O memory\n");
++              error = -EBUSY;
++              goto failed_free;
++      }
++
++      keypad->mmio_base = ioremap(res->start, res_size(res));
++      if (keypad->mmio_base == NULL) {
++              dev_err(&pdev->dev, "failed to remap I/O memory\n");
++              error = -ENXIO;
++              goto failed_free_mem;
++      }
++
++      keypad->clk = clk_get(&pdev->dev, "KBDCLK");
++      if (IS_ERR(keypad->clk)) {
++              dev_err(&pdev->dev, "failed to get keypad clock\n");
++              error = PTR_ERR(keypad->clk);
++              goto failed_free_io;
++      }
++
++      /* Create and register the input driver. */
++      input_dev = input_allocate_device();
++      if (!input_dev) {
++              dev_err(&pdev->dev, "failed to allocate input device\n");
++              error = -ENOMEM;
++              goto failed_put_clk;
++      }
++
++      input_dev->name = pdev->name;
++      input_dev->id.bustype = BUS_HOST;
++      input_dev->open = pxa27x_keypad_open;
++      input_dev->close = pxa27x_keypad_close;
++      input_dev->dev.parent = &pdev->dev;
++
++      keypad->input_dev = input_dev;
++      input_set_drvdata(input_dev, keypad);
++
++      input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP) |
++              BIT_MASK(EV_REL);
++
++      pxa27x_keypad_build_keycode(keypad);
++      platform_set_drvdata(pdev, keypad);
++
++      error = request_irq(irq, pxa27x_keypad_irq_handler, IRQF_DISABLED,
++                          pdev->name, keypad);
++      if (error) {
++              dev_err(&pdev->dev, "failed to request IRQ\n");
++              goto failed_free_dev;
++      }
++
++      /* Register the input device */
++      error = input_register_device(input_dev);
++      if (error) {
++              dev_err(&pdev->dev, "failed to register input device\n");
++              goto failed_free_irq;
++      }
++
++      return 0;
++
++failed_free_irq:
++      free_irq(irq, pdev);
++      platform_set_drvdata(pdev, NULL);
++failed_free_dev:
++      input_free_device(input_dev);
++failed_put_clk:
++      clk_put(keypad->clk);
++failed_free_io:
++      iounmap(keypad->mmio_base);
++failed_free_mem:
++      release_mem_region(res->start, res_size(res));
++failed_free:
++      kfree(keypad);
++      return error;
++}
++
++static int __devexit pxa27x_keypad_remove(struct platform_device *pdev)
++{
++      struct pxa27x_keypad *keypad = platform_get_drvdata(pdev);
++      struct resource *res;
++
++      free_irq(platform_get_irq(pdev, 0), pdev);
++
++      clk_disable(keypad->clk);
++      clk_put(keypad->clk);
++
++      input_unregister_device(keypad->input_dev);
++      input_free_device(keypad->input_dev);
++
++      iounmap(keypad->mmio_base);
++
++      res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++      release_mem_region(res->start, res_size(res));
++
++      platform_set_drvdata(pdev, NULL);
++      kfree(keypad);
++      return 0;
++}
++
++static struct platform_driver pxa27x_keypad_driver = {
++      .probe          = pxa27x_keypad_probe,
++      .remove         = __devexit_p(pxa27x_keypad_remove),
++      .suspend        = pxa27x_keypad_suspend,
++      .resume         = pxa27x_keypad_resume,
++      .driver         = {
++              .name   = "pxa27x-keypad",
++      },
++};
++
++static int __init pxa27x_keypad_init(void)
++{
++      return platform_driver_register(&pxa27x_keypad_driver);
++}
++
++static void __exit pxa27x_keypad_exit(void)
++{
++      platform_driver_unregister(&pxa27x_keypad_driver);
++}
++
++module_init(pxa27x_keypad_init);
++module_exit(pxa27x_keypad_exit);
++
++MODULE_DESCRIPTION("PXA27x Keypad Controller Driver");
++MODULE_LICENSE("GPL");
+Index: linux-2.6.23-z-input/include/asm-arm/arch-pxa/pxa27x_keyboard.h
+===================================================================
+--- linux-2.6.23-z-input.orig/include/asm-arm/arch-pxa/pxa27x_keyboard.h       2007-10-09 22:31:38.000000000 +0200
++++ /dev/null  1970-01-01 00:00:00.000000000 +0000
+@@ -1,13 +0,0 @@
+-#define PXAKBD_MAXROW         8
+-#define PXAKBD_MAXCOL         8
+-
+-struct pxa27x_keyboard_platform_data {
+-      int nr_rows, nr_cols;
+-      int keycodes[PXAKBD_MAXROW][PXAKBD_MAXCOL];
+-      int gpio_modes[PXAKBD_MAXROW + PXAKBD_MAXCOL];
+-
+-#ifdef CONFIG_PM
+-      u32 reg_kpc;
+-      u32 reg_kprec;
+-#endif
+-};
+Index: linux-2.6.23-z-input/include/asm-arm/arch-pxa/pxa27x_keypad.h
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.23-z-input/include/asm-arm/arch-pxa/pxa27x_keypad.h      2008-02-18 01:43:28.000000000 +0100
+@@ -0,0 +1,58 @@
++#ifndef __ASM_ARCH_PXA27x_KEYPAD_H
++#define __ASM_ARCH_PXA27x_KEYPAD_H
++
++#include <linux/input.h>
++
++#define MAX_MATRIX_KEY_ROWS   (8)
++#define MAX_MATRIX_KEY_COLS   (8)
++
++/* pxa3xx keypad platform specific parameters
++ *
++ * NOTE:
++ * 1. direct_key_num indicates the number of keys in the direct keypad
++ *    _plus_ the number of rotary-encoder sensor inputs,  this can be
++ *    left as 0 if only rotary encoders are enabled,  the driver will
++ *    automatically calculate this
++ *
++ * 2. direct_key_map is the key code map for the direct keys, if rotary
++ *    encoder(s) are enabled, direct key 0/1(2/3) will be ignored
++ *
++ * 3. rotary can be either interpreted as a relative input event (e.g.
++ *    REL_WHEEL/REL_HWHEEL) or specific keys (e.g. UP/DOWN/LEFT/RIGHT)
++ *
++ * 4. matrix key and direct key will use the same debounce_interval by
++ *    default, which should be sufficient in most cases
++ */
++struct pxa27x_keypad_platform_data {
++
++      /* code map for the matrix keys */
++      unsigned int    matrix_key_rows;
++      unsigned int    matrix_key_cols;
++      unsigned int    *matrix_key_map;
++      int             matrix_key_map_size;
++
++      /* direct keys */
++      int             direct_key_num;
++      unsigned int    direct_key_map[8];
++
++      /* rotary encoders 0 */
++      int             enable_rotary0;
++      int             rotary0_rel_code;
++      int             rotary0_up_key;
++      int             rotary0_down_key;
++
++      /* rotary encoders 1 */
++      int             enable_rotary1;
++      int             rotary1_rel_code;
++      int             rotary1_up_key;
++      int             rotary1_down_key;
++
++      /* key debounce interval */
++      unsigned int    debounce_interval;
++};
++
++#define KEY(row, col, val)    (((row) << 28) | ((col) << 24) | (val))
++
++extern void pxa_set_keypad_info(struct pxa27x_keypad_platform_data *info);
++
++#endif /* __ASM_ARCH_PXA27x_KEYPAD_H */
+Index: linux-2.6.23-z-input/drivers/input/keyboard/pxa27x_keyboard.c
+===================================================================
+--- linux-2.6.23-z-input.orig/drivers/input/keyboard/pxa27x_keyboard.c 2008-02-18 01:43:28.000000000 +0100
++++ /dev/null  1970-01-01 00:00:00.000000000 +0000
+@@ -1,273 +0,0 @@
+-/*
+- * linux/drivers/input/keyboard/pxa27x_keyboard.c
+- *
+- * Driver for the pxa27x matrix keyboard controller.
+- *
+- * Created:   Feb 22, 2007
+- * Author:    Rodolfo Giometti <giometti@linux.it>
+- *
+- * Based on a previous implementations by Kevin O'Connor
+- * <kevin_at_koconnor.net> and Alex Osborne <bobofdoom@gmail.com> and
+- * on some suggestions by Nicolas Pitre <nico@cam.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.
+- */
+-
+-
+-#include <linux/kernel.h>
+-#include <linux/module.h>
+-#include <linux/init.h>
+-#include <linux/interrupt.h>
+-#include <linux/input.h>
+-#include <linux/device.h>
+-#include <linux/platform_device.h>
+-#include <linux/clk.h>
+-#include <linux/err.h>
+-
+-#include <asm/mach-types.h>
+-#include <asm/mach/arch.h>
+-#include <asm/mach/map.h>
+-
+-#include <asm/arch/hardware.h>
+-#include <asm/arch/pxa-regs.h>
+-#include <asm/arch/irqs.h>
+-#include <asm/arch/pxa27x_keyboard.h>
+-
+-#define DRIVER_NAME           "pxa27x-keyboard"
+-
+-#define KPASMKP(col)          (col/2 == 0 ? KPASMKP0 : \
+-                               col/2 == 1 ? KPASMKP1 : \
+-                               col/2 == 2 ? KPASMKP2 : KPASMKP3)
+-#define KPASMKPx_MKC(row, col)        (1 << (row + 16 * (col % 2)))
+-
+-static struct clk *pxakbd_clk;
+-
+-static irqreturn_t pxakbd_irq_handler(int irq, void *dev_id)
+-{
+-      struct platform_device *pdev = dev_id;
+-      struct pxa27x_keyboard_platform_data *pdata = pdev->dev.platform_data;
+-      struct input_dev *input_dev = platform_get_drvdata(pdev);
+-      unsigned long kpc = KPC;
+-      int p, row, col, rel;
+-
+-      if (kpc & KPC_DI) {
+-              unsigned long kpdk = KPDK;
+-
+-              if (!(kpdk & KPDK_DKP)) {
+-                      /* better luck next time */
+-              } else if (kpc & KPC_REE0) {
+-                      unsigned long kprec = KPREC;
+-                      KPREC = 0x7f;
+-
+-                      if (kprec & KPREC_OF0)
+-                              rel = (kprec & 0xff) + 0x7f;
+-                      else if (kprec & KPREC_UF0)
+-                              rel = (kprec & 0xff) - 0x7f - 0xff;
+-                      else
+-                              rel = (kprec & 0xff) - 0x7f;
+-
+-                      if (rel) {
+-                              input_report_rel(input_dev, REL_WHEEL, rel);
+-                              input_sync(input_dev);
+-                      }
+-              }
+-      }
+-
+-      if (kpc & KPC_MI) {
+-              /* report the status of every button */
+-              for (row = 0; row < pdata->nr_rows; row++) {
+-                      for (col = 0; col < pdata->nr_cols; col++) {
+-                              p = KPASMKP(col) & KPASMKPx_MKC(row, col) ?
+-                                      1 : 0;
+-                              pr_debug("keycode %x - pressed %x\n",
+-                                              pdata->keycodes[row][col], p);
+-                              input_report_key(input_dev,
+-                                              pdata->keycodes[row][col], p);
+-                      }
+-              }
+-              input_sync(input_dev);
+-      }
+-
+-      return IRQ_HANDLED;
+-}
+-
+-static int pxakbd_open(struct input_dev *dev)
+-{
+-      /* Set keypad control register */
+-      KPC |= (KPC_ASACT |
+-              KPC_MS_ALL |
+-              (2 << 6) | KPC_REE0 | KPC_DK_DEB_SEL |
+-              KPC_ME | KPC_MIE | KPC_DE | KPC_DIE);
+-
+-      KPC &= ~KPC_AS;         /* disable automatic scan */
+-      KPC &= ~KPC_IMKP;       /* do not ignore multiple keypresses */
+-
+-      /* Set rotary count to mid-point value */
+-      KPREC = 0x7F;
+-
+-      /* Enable unit clock */
+-      clk_enable(pxakbd_clk);
+-
+-      return 0;
+-}
+-
+-static void pxakbd_close(struct input_dev *dev)
+-{
+-      /* Disable clock unit */
+-      clk_disable(pxakbd_clk);
+-}
+-
+-#ifdef CONFIG_PM
+-static int pxakbd_suspend(struct platform_device *pdev, pm_message_t state)
+-{
+-      struct pxa27x_keyboard_platform_data *pdata = pdev->dev.platform_data;
+-
+-      /* Save controller status */
+-      pdata->reg_kpc = KPC;
+-      pdata->reg_kprec = KPREC;
+-
+-      return 0;
+-}
+-
+-static int pxakbd_resume(struct platform_device *pdev)
+-{
+-      struct pxa27x_keyboard_platform_data *pdata = pdev->dev.platform_data;
+-      struct input_dev *input_dev = platform_get_drvdata(pdev);
+-
+-      mutex_lock(&input_dev->mutex);
+-
+-      if (input_dev->users) {
+-              /* Restore controller status */
+-              KPC = pdata->reg_kpc;
+-              KPREC = pdata->reg_kprec;
+-
+-              /* Enable unit clock */
+-              clk_disable(pxakbd_clk);
+-              clk_enable(pxakbd_clk);
+-      }
+-
+-      mutex_unlock(&input_dev->mutex);
+-
+-      return 0;
+-}
+-#else
+-#define pxakbd_suspend        NULL
+-#define pxakbd_resume NULL
+-#endif
+-
+-static int __devinit pxakbd_probe(struct platform_device *pdev)
+-{
+-      struct pxa27x_keyboard_platform_data *pdata = pdev->dev.platform_data;
+-      struct input_dev *input_dev;
+-      int i, row, col, error;
+-
+-      pxakbd_clk = clk_get(&pdev->dev, "KBDCLK");
+-      if (IS_ERR(pxakbd_clk)) {
+-              error = PTR_ERR(pxakbd_clk);
+-              goto err_clk;
+-      }
+-
+-      /* Create and register the input driver. */
+-      input_dev = input_allocate_device();
+-      if (!input_dev) {
+-              printk(KERN_ERR "Cannot request keypad device\n");
+-              error = -ENOMEM;
+-              goto err_alloc;
+-      }
+-
+-      input_dev->name = DRIVER_NAME;
+-      input_dev->id.bustype = BUS_HOST;
+-      input_dev->open = pxakbd_open;
+-      input_dev->close = pxakbd_close;
+-      input_dev->dev.parent = &pdev->dev;
+-
+-      input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP) | BIT(EV_REL);
+-      input_dev->relbit[LONG(REL_WHEEL)] = BIT(REL_WHEEL);
+-      for (row = 0; row < pdata->nr_rows; row++) {
+-              for (col = 0; col < pdata->nr_cols; col++) {
+-                      int code = pdata->keycodes[row][col];
+-                      if (code > 0)
+-                              set_bit(code, input_dev->keybit);
+-              }
+-      }
+-
+-      error = request_irq(IRQ_KEYPAD, pxakbd_irq_handler, IRQF_DISABLED,
+-                          DRIVER_NAME, pdev);
+-      if (error) {
+-              printk(KERN_ERR "Cannot request keypad IRQ\n");
+-              goto err_free_dev;
+-      }
+-
+-      platform_set_drvdata(pdev, input_dev);
+-
+-      /* Register the input device */
+-      error = input_register_device(input_dev);
+-      if (error)
+-              goto err_free_irq;
+-
+-      /* Setup GPIOs. */
+-      for (i = 0; i < pdata->nr_rows + pdata->nr_cols; i++)
+-              pxa_gpio_mode(pdata->gpio_modes[i]);
+-
+-      /*
+-       * Store rows/cols info into keyboard registers.
+-       */
+-
+-      KPC |= (pdata->nr_rows - 1) << 26;
+-      KPC |= (pdata->nr_cols - 1) << 23;
+-
+-      for (col = 0; col < pdata->nr_cols; col++)
+-              KPC |= KPC_MS0 << col;
+-
+-      return 0;
+-
+- err_free_irq:
+-      platform_set_drvdata(pdev, NULL);
+-      free_irq(IRQ_KEYPAD, pdev);
+- err_free_dev:
+-      input_free_device(input_dev);
+- err_alloc:
+-      clk_put(pxakbd_clk);
+- err_clk:
+-      return error;
+-}
+-
+-static int __devexit pxakbd_remove(struct platform_device *pdev)
+-{
+-      struct input_dev *input_dev = platform_get_drvdata(pdev);
+-
+-      input_unregister_device(input_dev);
+-      free_irq(IRQ_KEYPAD, pdev);
+-      clk_put(pxakbd_clk);
+-      platform_set_drvdata(pdev, NULL);
+-
+-      return 0;
+-}
+-
+-static struct platform_driver pxakbd_driver = {
+-      .probe          = pxakbd_probe,
+-      .remove         = __devexit_p(pxakbd_remove),
+-      .suspend        = pxakbd_suspend,
+-      .resume         = pxakbd_resume,
+-      .driver         = {
+-              .name   = DRIVER_NAME,
+-      },
+-};
+-
+-static int __init 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_DESCRIPTION("PXA27x Matrix Keyboard Driver");
+-MODULE_LICENSE("GPL");
+Index: linux-2.6.23-z-input/arch/arm/mach-pxa/zylonite.c
+===================================================================
+--- linux-2.6.23-z-input.orig/arch/arm/mach-pxa/zylonite.c     2008-02-18 01:43:28.000000000 +0100
++++ linux-2.6.23-z-input/arch/arm/mach-pxa/zylonite.c  2008-02-19 01:31:33.000000000 +0100
+@@ -25,6 +25,7 @@
+ #include <asm/arch/gpio.h>
+ #include <asm/arch/pxafb.h>
+ #include <asm/arch/zylonite.h>
++#include <asm/arch/pxa27x_keypad.h>
+ #include "generic.h"
+@@ -173,6 +174,72 @@
+ static inline void zylonite_init_lcd(void) {}
+ #endif
++#if defined(CONFIG_KEYBOARD_PXA27x) || defined(CONFIG_KEYBOARD_PXA27x_MODULES)
++static unsigned int zylonite_matrix_key_map[] = {
++       /* KEY(row, col, key_code) */
++       KEY(0, 0, KEY_A), KEY(0, 1, KEY_B), KEY(0, 2, KEY_C), KEY(0, 5, KEY_D),
++       KEY(1, 0, KEY_E), KEY(1, 1, KEY_F), KEY(1, 2, KEY_G), KEY(1, 5, KEY_H),
++       KEY(2, 0, KEY_I), KEY(2, 1, KEY_J), KEY(2, 2, KEY_K), KEY(2, 5, KEY_L),
++       KEY(3, 0, KEY_M), KEY(3, 1, KEY_N), KEY(3, 2, KEY_O), KEY(3, 5, KEY_P),
++       KEY(5, 0, KEY_Q), KEY(5, 1, KEY_R), KEY(5, 2, KEY_S), KEY(5, 5, KEY_T),
++       KEY(6, 0, KEY_U), KEY(6, 1, KEY_V), KEY(6, 2, KEY_W), KEY(6, 5, KEY_X),
++       KEY(7, 1, KEY_Y), KEY(7, 2, KEY_Z),
++
++       KEY(4, 4, KEY_0), KEY(1, 3, KEY_1), KEY(4, 1, KEY_2), KEY(1, 4, KEY_3),
++       KEY(2, 3, KEY_4), KEY(4, 2, KEY_5), KEY(2, 4, KEY_6), KEY(3, 3, KEY_7),
++       KEY(4, 3, KEY_8), KEY(3, 4, KEY_9),
++
++       KEY(4, 5, KEY_SPACE),
++       KEY(5, 3, KEY_KPASTERISK),      /* * */
++       KEY(5, 4, KEY_KPDOT),           /* #" */
++
++       KEY(0, 7, KEY_UP),
++       KEY(1, 7, KEY_DOWN),
++       KEY(2, 7, KEY_LEFT),
++       KEY(3, 7, KEY_RIGHT),
++       KEY(2, 6, KEY_HOME),
++       KEY(3, 6, KEY_END),
++       KEY(6, 4, KEY_DELETE),
++       KEY(6, 6, KEY_BACK),
++       KEY(6, 3, KEY_CAPSLOCK),        /* KEY_LEFTSHIFT), */
++
++       KEY(4, 6, KEY_ENTER),           /* scroll push */
++       KEY(5, 7, KEY_ENTER),           /* keypad action */
++
++       KEY(0, 4, KEY_EMAIL),
++       KEY(5, 6, KEY_SEND),
++       KEY(4, 0, KEY_CALENDAR),
++       KEY(7, 6, KEY_RECORD),
++       KEY(6, 7, KEY_VOLUMEUP),
++       KEY(7, 7, KEY_VOLUMEDOWN),
++
++       KEY(0, 6, KEY_F22),     /* soft1 */
++       KEY(1, 6, KEY_F23),     /* soft2 */
++       KEY(0, 3, KEY_AUX),     /* contact */
++};
++
++static struct pxa27x_keypad_platform_data zylonite_keypad_info = {
++       .matrix_key_rows        = 8,
++       .matrix_key_cols        = 8,
++       .matrix_key_map         = zylonite_matrix_key_map,
++       .matrix_key_map_size    = ARRAY_SIZE(zylonite_matrix_key_map),
++
++       .enable_rotary0         = 1,
++       .rotary0_up_key         = KEY_UP,
++       .rotary0_down_key       = KEY_DOWN,
++
++       .debounce_interval      = 30,
++};
++
++static void __init zylonite_init_keypad(void)
++{
++       pxa_set_keypad_info(&zylonite_keypad_info);
++}
++#else
++static inline void zylonite_init_keypad(void) {}
++#endif
++
++
+ static void __init zylonite_init(void)
+ {
+       /* board-processor specific initialization */
+@@ -190,6 +257,7 @@
+       platform_device_register(&touch_device);
+       zylonite_init_lcd();
++      zylonite_init_keypad();
+ }
+ MACHINE_START(ZYLONITE, "PXA3xx Platform Development Kit (aka Zylonite)")
+Index: linux-2.6.23-z-input/arch/arm/mach-pxa/devices.h
+===================================================================
+--- linux-2.6.23-z-input.orig/arch/arm/mach-pxa/devices.h      2008-02-18 01:43:28.000000000 +0100
++++ linux-2.6.23-z-input/arch/arm/mach-pxa/devices.h   2008-02-18 01:43:28.000000000 +0100
+@@ -12,3 +12,4 @@
+ extern struct platform_device pxa27x_device_i2c_power;
+ extern struct platform_device pxa27x_device_ohci;
++extern struct platform_device pxa27x_device_keypad;
+Index: linux-2.6.23-z-input/arch/arm/mach-pxa/generic.c
+===================================================================
+--- linux-2.6.23-z-input.orig/arch/arm/mach-pxa/generic.c      2008-02-18 01:43:28.000000000 +0100
++++ linux-2.6.23-z-input/arch/arm/mach-pxa/generic.c   2008-02-18 01:43:28.000000000 +0100
+@@ -450,3 +450,34 @@
+       .name           = "sa1100-rtc",
+       .id             = -1,
+ };
++
++static struct resource pxa27x_resource_keypad[] = {
++       [0] = {
++               .start  = 0x41500000,
++               .end    = 0x4150004c,
++               .flags  = IORESOURCE_MEM,
++       },
++       [1] = {
++               .start  = IRQ_KEYPAD,
++               .end    = IRQ_KEYPAD,
++               .flags  = IORESOURCE_IRQ,
++       },
++};
++
++struct platform_device pxa27x_device_keypad = {
++       .name           = "pxa27x-keypad",
++       .id             = -1,
++       .resource       = pxa27x_resource_keypad,
++       .num_resources  = ARRAY_SIZE(pxa27x_resource_keypad),
++};
++
++void __init pxa_set_keypad_info(struct pxa27x_keypad_platform_data *info)
++{
++      int ret;
++
++      pxa27x_device_keypad.dev.platform_data = info;
++
++      ret = platform_device_register(&pxa27x_device_keypad);
++      if (ret)
++              dev_err(&pxa27x_device_keypad.dev, "unable to register device: %d\n", ret);
++}
+Index: linux-2.6.23-z-input/arch/arm/mach-pxa/pxa27x.c
+===================================================================
+--- linux-2.6.23-z-input.orig/arch/arm/mach-pxa/pxa27x.c       2008-02-18 01:43:28.000000000 +0100
++++ linux-2.6.23-z-input/arch/arm/mach-pxa/pxa27x.c    2008-02-18 01:43:28.000000000 +0100
+@@ -148,7 +148,7 @@
+       INIT_CKEN("USBCLK", USB,    48000000, 0, &pxa27x_device_ohci.dev),
+       INIT_CKEN("I2CCLK", PWRI2C, 13000000, 0, &pxa27x_device_i2c_power.dev),
+-      INIT_CKEN("KBDCLK", KEYPAD, 32768, 0, NULL),
++      INIT_CKEN("KBDCLK", KEYPAD, 32768, 0, &pxa27x_device_keypad.dev),
+       /*
+       INIT_CKEN("PWMCLK",  PWM0, 13000000, 0, NULL),
+Index: linux-2.6.23-z-input/arch/arm/mach-pxa/pxa3xx.c
+===================================================================
+--- linux-2.6.23-z-input.orig/arch/arm/mach-pxa/pxa3xx.c       2008-02-18 01:43:28.000000000 +0100
++++ linux-2.6.23-z-input/arch/arm/mach-pxa/pxa3xx.c    2008-02-19 01:32:40.000000000 +0100
+@@ -159,6 +159,7 @@
+ static struct clk pxa3xx_clks[] = {
+       INIT_CK("LCDCLK", LCD,    &clk_pxa3xx_hsio_ops, &pxa_device_fb.dev),
+       INIT_CK("CAMCLK", CAMERA, &clk_pxa3xx_hsio_ops, NULL),
++      INIT_CK("KBDCLK", KEYPAD, &clk_pxa3xx_hsio_ops, &pxa27x_device_keypad.dev),
+       INIT_CKEN("UARTCLK", FFUART, 14857000, 1, &pxa_device_ffuart.dev),
+       INIT_CKEN("UARTCLK", BTUART, 14857000, 1, &pxa_device_btuart.dev),
+Index: linux-2.6.23-z-input/include/asm-arm/arch-pxa/irqs.h
+===================================================================
+--- linux-2.6.23-z-input.orig/include/asm-arm/arch-pxa/irqs.h  2008-02-18 01:43:28.000000000 +0100
++++ linux-2.6.23-z-input/include/asm-arm/arch-pxa/irqs.h       2008-02-18 01:43:28.000000000 +0100
+@@ -13,7 +13,7 @@
+ #define PXA_IRQ(x)    (x)
+-#ifdef CONFIG_PXA27x
++#if defined(CONFIG_PXA27x) || defined(CONFIG_PXA3xx)
+ #define IRQ_SSP3      PXA_IRQ(0)      /* SSP3 service request */
+ #define IRQ_MSL               PXA_IRQ(1)      /* MSL Interface interrupt */
+ #define IRQ_USBH2     PXA_IRQ(2)      /* USB Host interrupt 1 (OHCI) */
+Index: linux-2.6.23-z-input/arch/arm/mach-pxa/pxa300.c
+===================================================================
+--- linux-2.6.23-z-input.orig/arch/arm/mach-pxa/pxa300.c       2008-02-19 01:33:58.000000000 +0100
++++ linux-2.6.23-z-input/arch/arm/mach-pxa/pxa300.c    2008-02-19 01:34:35.000000000 +0100
+@@ -23,8 +23,10 @@
+       MFP_ADDR_X(GPIO0,   GPIO2,   0x00b4),
+       MFP_ADDR_X(GPIO3,   GPIO26,  0x027c),
+-      MFP_ADDR_X(GPIO27,  GPIO127, 0x0400),
+-      MFP_ADDR_X(GPIO0_2, GPIO6_2, 0x02ec),
++      MFP_ADDR_X(GPIO27,  GPIO98,  0x0400),
++      MFP_ADDR_X(GPIO99,  GPIO127, 0x0600),
++      MFP_ADDR_X(GPIO0_2, GPIO1_2, 0x0674),
++      MFP_ADDR_X(GPIO2_2, GPIO6_2, 0x02dc),
+       MFP_ADDR(nBE0, 0x0204),
+       MFP_ADDR(nBE1, 0x0208),
index 32564a2f6647cca6138bbe1c06d8f689c4099dad..1b6a9ba78f7ef152f7f4e26808421061fafe2f87 100644 (file)
@@ -140,6 +140,7 @@ SRC_URI_append_zylonite ="\
        file://zylonite-boot.patch;patch=1 \
        file://zylonite_mtd-r0.patch;patch=1 \
        file://zylonite_touch-r0.patch;patch=1 \
+       file://zylonite_keypad-r0.patch;patch=1 \
        "
 
 S = "${WORKDIR}/linux-2.6.23"