From: Syed Mohammed Khasim Date: Fri, 18 May 2007 15:38:45 +0000 (-0700) Subject: TWL4030 Keypad Driver X-Git-Tag: v2.6.22-omap1~143 X-Git-Url: http://pilppa.com/gitweb/?a=commitdiff_plain;h=2e60f0207fe633874b45597554652867f8dad55c;p=linux-2.6-omap-h63xx.git TWL4030 Keypad Driver Incorporated Review comments and have merged Nishanth's patch. This patch adds TWL4030 Keypad driver support for 2430 SDP. Signed-off-by: Syed Mohammed Khasim Signed-off-by: Tony Lindgren --- diff --git a/arch/arm/mach-omap2/board-2430sdp.c b/arch/arm/mach-omap2/board-2430sdp.c index 27806b966a1..7070b89d051 100644 --- a/arch/arm/mach-omap2/board-2430sdp.c +++ b/arch/arm/mach-omap2/board-2430sdp.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -34,6 +35,7 @@ #include #include #include +#include #include #include #include "prcm-regs.h" @@ -120,9 +122,64 @@ static struct platform_device sdp2430_smc91x_device = { .resource = sdp2430_smc91x_resources, }; +/* + * Key mapping for 2430 SDP board + */ + +static int sdp2430_keymap[] = { + KEY(0, 0, KEY_LEFT), + KEY(0, 1, KEY_RIGHT), + KEY(0, 2, KEY_A), + KEY(0, 3, KEY_B), + KEY(0, 4, KEY_C), + KEY(1, 0, KEY_DOWN), + KEY(1, 1, KEY_UP), + KEY(1, 2, KEY_E), + KEY(1, 3, KEY_F), + KEY(1, 4, KEY_G), + KEY(2, 0, KEY_ENTER), + KEY(2, 1, KEY_I), + KEY(2, 2, KEY_J), + KEY(2, 3, KEY_K), + KEY(2, 4, KEY_3), + KEY(3, 0, KEY_M), + KEY(3, 1, KEY_N), + KEY(3, 2, KEY_O), + KEY(3, 3, KEY_P), + KEY(3, 4, KEY_Q), + KEY(4, 0, KEY_R), + KEY(4, 1, KEY_4), + KEY(4, 2, KEY_T), + KEY(4, 3, KEY_U), + KEY(4, 4, KEY_D), + KEY(5, 0, KEY_V), + KEY(5, 1, KEY_W), + KEY(5, 2, KEY_L), + KEY(5, 3, KEY_S), + KEY(5, 4, KEY_H), + 0 +}; + +static struct omap_kp_platform_data sdp2430_kp_data = { + .rows = 5, + .cols = 6, + .keymap = sdp2430_keymap, + .keymapsize = ARRAY_SIZE(sdp2430_keymap), + .rep = 1, +}; + +static struct platform_device sdp2430_kp_device = { + .name = "omap_twl4030keypad", + .id = -1, + .dev = { + .platform_data = &sdp2430_kp_data, + }, +}; + static struct platform_device *sdp2430_devices[] __initdata = { &sdp2430_smc91x_device, &sdp2430_flash_device, + &sdp2430_kp_device, }; static struct tsc2046_platform_data tsc2046_config = { diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index 31200944161..f303b6e1270 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig @@ -214,6 +214,16 @@ config KEYBOARD_OMAP To compile this driver as a module, choose M here: the module will be called omap-keypad. +config KEYBOARD_TWL4030 + tristate "TI TWL4030 keypad support" + depends on TWL4030_CORE && MACH_OMAP_2430SDP + help + Say Y here if you want to use the OMAP TWL4030 keypad. + + To compile this driver as a module, choose M here: the + module will be called omap-twl4030keypad. This driver depends on + TWL4030 Core and TWL4030 GPIO I2C client driver + config OMAP_PS2 tristate "TI OMAP Innovator 1510 PS/2 keyboard & mouse support" depends on ARCH_OMAP15XX && MACH_OMAP_INNOVATOR diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile index 0e36829b243..4cad7f107fc 100644 --- a/drivers/input/keyboard/Makefile +++ b/drivers/input/keyboard/Makefile @@ -23,4 +23,4 @@ obj-$(CONFIG_KEYBOARD_PXA27x) += pxa27x_keyboard.o obj-$(CONFIG_KEYBOARD_AAED2000) += aaed2000_kbd.o obj-$(CONFIG_KEYBOARD_GPIO) += gpio_keys.o obj-$(CONFIG_KEYBOARD_TSC2301) += tsc2301_kp.o - +obj-$(CONFIG_KEYBOARD_TWL4030) += omap-twl4030keypad.o diff --git a/drivers/input/keyboard/omap-twl4030keypad.c b/drivers/input/keyboard/omap-twl4030keypad.c new file mode 100644 index 00000000000..b96e84f5f14 --- /dev/null +++ b/drivers/input/keyboard/omap-twl4030keypad.c @@ -0,0 +1,387 @@ +/* + * drivers/input/keyboard/omap-twl4030keypad.c + * + * Copyright (C) 2007 Texas Instruments, Inc. + * + * Code re-written for 2430SDP by: + * Syed Mohammed Khasim + * + * Initial Code: + * Manjunatha G K + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "twl4030-keypad.h" + +#define OMAP_TWL4030KP_LOG_LEVEL 0 + +#define KEY(col, row, val) (((col) << 28) | ((row) << 24) | (val)) +#define NUM_ROWS 5 +#define NUM_COLS 6 + +#define ROW_MASK ((1<dev.platform_data; + + /* Get the debug Device */ + dbg_dev = &(pdev->dev); + + if (!pdata->rows || !pdata->cols || !pdata->keymap) { + dev_err(dbg_dev, "No rows, cols or keymap from pdata\n"); + return -EINVAL; + } + + omap_twl4030kp = input_allocate_device(); + if (omap_twl4030kp == NULL) + return -ENOMEM; + + keymap = pdata->keymap; + + /* setup input device */ + set_bit(EV_KEY, omap_twl4030kp->evbit); + + /* Enable auto repeat feature of Linux input subsystem */ + set_bit(EV_REP, omap_twl4030kp->evbit); + + for (i = 0; keymap[i] != 0; i++) + set_bit(keymap[i] & 0x00ffffff, omap_twl4030kp->keybit); + + omap_twl4030kp->name = "omap_twl4030keypad"; + omap_twl4030kp->phys = "omap_twl4030keypad/input0"; + omap_twl4030kp->dev.parent = &pdev->dev; + + omap_twl4030kp->id.bustype = BUS_HOST; + omap_twl4030kp->id.vendor = 0x0001; + omap_twl4030kp->id.product = 0x0001; + omap_twl4030kp->id.version = 0x0003; + + omap_twl4030kp->keycode = keymap; + omap_twl4030kp->keycodesize = sizeof(unsigned int); + omap_twl4030kp->keycodemax = pdata->keymapsize; + + /* Get the debug Device to omap keypad device */ + dbg_dev = &(omap_twl4030kp->dev); + + ret = input_register_device(omap_twl4030kp); + if (ret < 0) { + dev_err(dbg_dev, "Unable to register twl4030 keypad device\n"); + goto err2; + } + + setup_timer(&kptimer,omap_kp_timer,(unsigned long) omap_twl4030kp); + + /* + * Since keypad driver uses I2C for reading + * twl4030 keypad registers, tasklets cannot + * be used. + */ + INIT_WORK(&timer_work, twl4030_timer_work); + + reg = KEYP_CTRL_REG_MASK_NOAUTORPT; + ret = twl4030_kpwrite_u8(TWL4030_MODULE_KEYPAD, reg, + REG_KEYP_CTRL_REG); + if (ret < 0) + goto err3; + + /* Set all events to Falling Edge detection */ + reg = KEYP_EDR_MASK; + ret = twl4030_kpwrite_u8(TWL4030_MODULE_KEYPAD, reg, REG_KEYP_EDR); + if (ret < 0) + goto err3; + + /* Set Pre Scalar Field PTV to 4 */ + reg = BIT_LK_PTV_REG_PTV_MASK & (BIT_PTV_REG_PTV4 << BIT_LK_PTV_REG_PTV); + + ret = twl4030_kpwrite_u8(TWL4030_MODULE_KEYPAD, reg, REG_LK_PTV_REG); + if (ret < 0) + goto err3; + + /* + * Set key debounce time to 10 ms using equation + * Tint = Tclk * (LOAD_TIM+1) * 2^(PTV+1) + * Where Tclk = 31.25 us ( since kbd_if_clk is 32KHz) + * PTV = 4 for all the operations. + */ + ret = twl4030_kpwrite_u8(TWL4030_MODULE_KEYPAD, 0x3f, + REG_KEY_DEB_REG); + if (ret < 0) + goto err3; + + /* Set SIH Ctrl register */ + reg = KEYP_SIH_CTRL_MASK; + ret = twl4030_kpwrite_u8(TWL4030_MODULE_KEYPAD, reg, + REG_KEYP_SIH_CTRL); + if (ret < 0) + goto err3; + + /* + * This ISR will always execute in kernel thread context because of + * the need to access the TWL4030 over the I2C bus. + */ + ret = request_irq(TWL4030_MODIRQ_KEYPAD, do_kp_irq, + IRQF_DISABLED, "TWL4030 Keypad", omap_twl4030kp); + if (ret < 0) { + dev_info(dbg_dev, "request_irq failed for irq no=%d\n", + TWL4030_MODIRQ_KEYPAD); + goto err3; + } else { + /* Enable keypad module interrupts now. */ + reg = KEYP_IMR1_UNMASK; + ret = twl4030_kpwrite_u8(TWL4030_MODULE_KEYPAD, reg, + REG_KEYP_IMR1); + if (ret < 0) { + /* mask all events - dont care abt result */ + (void)twl4030_kpwrite_u8(TWL4030_MODULE_KEYPAD, 0xff, + REG_KEYP_IMR1); + goto err4; + } + } + + /* Read initial state of keypad matrix. */ + ret = twl4030_i2c_read(TWL4030_MODULE_KEYPAD, kp_state, code_reg, + NUM_ROWS); + if (ret < 0) { + dev_warn(dbg_dev, "Could not read TWL4030 register %X - ret %d[%x]\n", + reg, ret, ret); + goto err4; + } + return (ret); +err4: + free_irq(TWL4030_MODIRQ_KEYPAD, NULL); +err3: + input_unregister_device(omap_twl4030kp); +err2: + input_free_device(omap_twl4030kp); + return -ENODEV; +} + +static int omap_kp_remove(struct platform_device *pdev) +{ + free_irq(TWL4030_MODIRQ_KEYPAD, NULL); + del_timer_sync(&kptimer); + + input_unregister_device(omap_twl4030kp); + return 0; +} + + +static struct platform_driver omap_kp_driver = { + .probe = omap_kp_probe, + .remove = omap_kp_remove, + .driver = { + .name = "omap_twl4030keypad", + }, +}; + +/* + * OMAP TWL4030 Keypad init + */ +static int __devinit omap_kp_init(void) +{ + return platform_driver_register(&omap_kp_driver); +} + +static void __exit omap_kp_exit(void) +{ + platform_driver_unregister(&omap_kp_driver); +} + +module_init(omap_kp_init); +module_exit(omap_kp_exit); +MODULE_AUTHOR("Texas Instruments"); +MODULE_DESCRIPTION("OMAP TWL4030 Keypad Driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/input/keyboard/twl4030-keypad.h b/drivers/input/keyboard/twl4030-keypad.h new file mode 100644 index 00000000000..642b851f03f --- /dev/null +++ b/drivers/input/keyboard/twl4030-keypad.h @@ -0,0 +1,76 @@ +/* + * drivers/input/keyboard/twl4030-keypad.h + * + * Copyright (C) 2006-2007 Texas Instruments, Inc. + * + * Intial Code: + * Syed Mohammed Khasim + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef __TWL4030_KEYPAD_H__ +#define __TWL4030_KEYPAD_H__ + +/* Register Definitions */ +#define REG_KEYP_CTRL_REG (0x0) +#define REG_KEY_DEB_REG (0x1) +#define REG_LK_PTV_REG (0x3) +#define REG_FULL_CODE_7_0 (0x9) +#define REG_KEYP_ISR1 (0x11) +#define REG_KEYP_IMR1 (0x12) +#define REG_KEYP_EDR (0x16) +#define REG_KEYP_SIH_CTRL (0x17) + +/* KEYP_CTRL_REG Fields */ +#define BIT_KEYP_CTRL_REG_SOFT_NRST_MASK (0x00000001) +#define BIT_KEYP_CTRL_REG_SOFTMODEN_MASK (0x00000002) +#define BIT_KEYP_CTRL_REG_LK_EN_MASK (0x00000004) +#define BIT_KEYP_CTRL_REG_TOE_EN_MASK (0x00000008) +#define BIT_KEYP_CTRL_REG_TOLE_EN_MASK (0x00000010) +#define BIT_KEYP_CTRL_REG_RP_EN_MASK (0x00000020) +#define BIT_KEYP_CTRL_REG_KBD_ON_MASK (0x00000040) + + +#define KEYP_CTRL_REG_MASK_NOAUTORPT BIT_KEYP_CTRL_REG_SOFT_NRST_MASK |\ + BIT_KEYP_CTRL_REG_SOFTMODEN_MASK |\ + BIT_KEYP_CTRL_REG_KBD_ON_MASK + +/* LK_PTV_REG Fields */ +#define BIT_LK_PTV_REG_PTV (0x005) +#define BIT_LK_PTV_REG_PTV_MASK (0x000000E0) +#define BIT_PTV_REG_PTV4 (0x4) + +/* KEYP_IMR1 Fields */ +#define KEYP_IMR1_MASK (0x0F) +#define KEYP_IMR1_UNMASK (0x00) + +/* KEYP_EDR Fields */ +#define BIT_KEYP_EDR_ITKPFALLING_MASK (0x00000001) +#define BIT_KEYP_EDR_ITKPRISING_MASK (0x00000002) +#define BIT_KEYP_EDR_ITLKFALLING_MASK (0x00000004) +#define BIT_KEYP_EDR_ITLKRISING_MASK (0x00000008) +#define BIT_KEYP_EDR_ITTOFALLING_MASK (0x00000010) +#define BIT_KEYP_EDR_ITTORISING_MASK (0x00000020) +#define BIT_KEYP_EDR_ITMISFALLING_MASK (0x00000040) +#define BIT_KEYP_EDR_ITMISRISING_MASK (0x00000080) + +#define KEYP_EDR_MASK BIT_KEYP_EDR_ITKPFALLING_MASK |\ + BIT_KEYP_EDR_ITLKFALLING_MASK |\ + BIT_KEYP_EDR_ITTOFALLING_MASK |\ + BIT_KEYP_EDR_ITMISFALLING_MASK +/* KEYP_SIH_CTRL Fields */ +#define KEYP_SIH_CTRL_MASK (0x04) + +#endif /* End of __TWL4030-KEYPAD_H__ */ diff --git a/include/asm-arm/arch-omap/board-2430sdp.h b/include/asm-arm/arch-omap/board-2430sdp.h index e9c65ce3cb1..8166aa5c84e 100644 --- a/include/asm-arm/arch-omap/board-2430sdp.h +++ b/include/asm-arm/arch-omap/board-2430sdp.h @@ -30,7 +30,7 @@ #define __ASM_ARCH_OMAP_2430SDP_H /* Placeholder for 2430SDP specific defines */ -#define OMAP24XX_ETHR_START 0x08000300 +#define OMAP24XX_ETHR_START 0x08000300 #define OMAP24XX_ETHR_GPIO_IRQ 149 #define SDP2430_CS0_BASE 0x04000000 @@ -39,6 +39,10 @@ /* TWL4030 Primary Interrupt Handler (PIH) interrupts */ #define IH_TWL4030_BASE IH_BOARD_BASE #define IH_TWL4030_END (IH_TWL4030_BASE+8) -#define NR_IRQS (IH_TWL4030_END) + +/* TWL4030 GPIO Interrupts */ +#define IH_TWL4030_GPIO_BASE (IH_TWL4030_END) +#define IH_TWL4030_GPIO_END (IH_TWL4030_BASE+18) +#define NR_IRQS (IH_TWL4030_GPIO_END) #endif /* __ASM_ARCH_OMAP_2430SDP_H */ diff --git a/include/asm-arm/arch-omap/twl4030.h b/include/asm-arm/arch-omap/twl4030.h index a603c10aec1..017dfd70243 100644 --- a/include/asm-arm/arch-omap/twl4030.h +++ b/include/asm-arm/arch-omap/twl4030.h @@ -72,6 +72,23 @@ #define TWL4030_VAUX3_DEV_GRP 0x1F #define TWL4030_VAUX3_DEDICATED 0x22 +/* TWL4030 GPIO interrupt definitions */ + +#define TWL4030_GPIO_MIN 0 +#define TWL4030_GPIO_MAX 18 +#define TWL4030_GPIO_MAX_CD 2 +#define TWL4030_GPIO_IRQ_NO(n) (IH_TWL4030_GPIO_BASE+n) +#define TWL4030_GPIO_IS_INPUT 1 +#define TWL4030_GPIO_IS_OUTPUT 0 +#define TWL4030_GPIO_IS_ENABLE 1 +#define TWL4030_GPIO_IS_DISABLE 0 +#define TWL4030_GPIO_PULL_UP 0 +#define TWL4030_GPIO_PULL_DOWN 1 +#define TWL4030_GPIO_PULL_NONE 2 +#define TWL4030_GPIO_EDGE_NONE 0 +#define TWL4030_GPIO_EDGE_RISING 1 +#define TWL4030_GPIO_EDGE_FALLING 2 + /* Functions to read and write from TWL4030 */ /*