aboutsummaryrefslogtreecommitdiff
path: root/arch/arm
diff options
context:
space:
mode:
authorNaveen Kumar Gaddipati <naveen.gaddipati@stericsson.com>2010-06-16 10:34:44 +0530
committerJohn Rigby <john.rigby@linaro.org>2010-09-02 22:45:44 -0600
commite8704ac96d42a4f3093dc253b7f2b44cf8c150e8 (patch)
tree059f5e17a3ba6265cf2001fab7d3e91b80b3ef2f /arch/arm
parent1b7470b38cbbc8ef57ead27b2362703fb139ab92 (diff)
ske_driver: support for internal keypad
Added the driver to support the internal keypad on ux500 platform ST-Ericsson Id:CR 256008 Signed-off-by: Naveen Kumar Gaddipati <naveen.gaddipati@stericsson.com> Signed-off-by: Mian Yousaf Kaukab <mian.yousaf.kaukab@stericsson.com> Change-Id: I8f776d4ff1e8ac4bc3ad0b629c1144b7e5daefb8 Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/2541 Reviewed-by: Jonas ABERG <jonas.aberg@stericsson.com>
Diffstat (limited to 'arch/arm')
-rwxr-xr-xarch/arm/mach-ux500/board-mop500.c6
-rwxr-xr-xarch/arm/mach-ux500/clock.c2
-rwxr-xr-xarch/arm/mach-ux500/devices.c232
-rwxr-xr-xarch/arm/mach-ux500/include/mach/devices.h1
-rwxr-xr-xarch/arm/mach-ux500/include/mach/irqs.h1
-rwxr-xr-xarch/arm/mach-ux500/include/mach/kpd.h60
6 files changed, 274 insertions, 28 deletions
diff --git a/arch/arm/mach-ux500/board-mop500.c b/arch/arm/mach-ux500/board-mop500.c
index 782a9801aa2..a52bc7e6231 100755
--- a/arch/arm/mach-ux500/board-mop500.c
+++ b/arch/arm/mach-ux500/board-mop500.c
@@ -124,6 +124,9 @@ static struct gpio_altfun_data gpio_altfun_table[] = {
__GPIO_ALT(GPIO_ALT_TP_SET_EXT_CLK, 228, 228, 0, NMK_GPIO_ALT_A,
"u8500_tp"),
#endif
+#ifdef CONFIG_KEYPAD_SKE
+ __GPIO_ALT(GPIO_ALT_KEYPAD, 153, 168, 0, NMK_GPIO_ALT_A, "ske-kp"),
+#endif
};
@@ -1309,6 +1312,9 @@ static struct platform_device *platform_board_devs[] __initdata = {
&ux500_hash1_device,
#endif
&u8500_leds_controller,
+#ifdef CONFIG_KEYPAD_SKE
+ &ske_keypad_device,
+#endif
};
static void __init mop500_platdata_init(void)
diff --git a/arch/arm/mach-ux500/clock.c b/arch/arm/mach-ux500/clock.c
index 056ecc26140..5ab9027368b 100755
--- a/arch/arm/mach-ux500/clock.c
+++ b/arch/arm/mach-ux500/clock.c
@@ -433,7 +433,7 @@ static struct clk_lookup u8500_common_clkregs[] = {
CLK(gpio2, "gpioblock2", NULL),
CLK(sdi5, "sdi5", NULL),
CLK(uart2, "uart2", NULL),
- CLK(ske, "ske", NULL),
+ CLK(ske, "ske-kp", NULL),
CLK(sdi2, "sdi2", NULL),
CLK(i2c0, "nmk-i2c.0", NULL),
CLK(fsmc, "fsmc", NULL),
diff --git a/arch/arm/mach-ux500/devices.c b/arch/arm/mach-ux500/devices.c
index 711b02b45be..aab9f3e6501 100755
--- a/arch/arm/mach-ux500/devices.c
+++ b/arch/arm/mach-ux500/devices.c
@@ -17,6 +17,7 @@
#include <linux/gpio.h>
#include <linux/usb/musb.h>
#include <linux/dma-mapping.h>
+#include <linux/input.h>
#include <asm/irq.h>
@@ -43,6 +44,7 @@
#include <mach/tc35892.h>
#include <mach/uart.h>
#include <mach/setup.h>
+#include <mach/kpd.h>
void __init u8500_register_device(struct platform_device *dev, void *data)
{
@@ -726,7 +728,237 @@ struct amba_device ux500_uart2_device = {
};
#endif
+#ifdef CONFIG_KEYPAD_SKE
+
+#define KEYPAD_DEBOUNCE_PERIOD_SKE 64
+#define ROW_PIN_I0 164
+#define ROW_PIN_I3 161
+#define ROW_PIN_I4 156
+#define ROW_PIN_I7 153
+#define COL_PIN_O0 168
+#define COL_PIN_O3 165
+#define COL_PIN_O4 160
+#define COL_PIN_O7 157
+
+/* ske_set_gpio_column - Disables Pull up
+ * @start: start column pin
+ * @end: end column pin
+ * This function disables the pull up for output pins
+*/
+int ske_set_gpio_column(int start, int end)
+{
+ int i;
+ int status = 0;
+
+ for (i = start; i <= end; i++) {
+ status = gpio_request(i, "ske");
+ if (status < 0) {
+ printk(KERN_ERR "%s: gpio request failed \n", __func__);
+ return status;
+ }
+ status = nmk_gpio_set_pull(i, NMK_GPIO_PULL_UP);
+ if (status < 0) {
+ printk(KERN_ERR "%s: gpio set pull failed \n", __func__);
+ return status;
+ }
+ gpio_free(i);
+ }
+ return status;
+}
+/* ske_set_gpio_row - enable the input pins
+ * @start: start row pin
+ * @end: end row pin
+ * This function enable the input pins
+*/
+int ske_set_gpio_row(int start, int end)
+{
+ int i = 0;
+ int status = 0;
+
+ for (i = start; i <= end; i++) {
+ status = gpio_request(i, "ske");
+ if (status < 0) {
+ printk(KERN_ERR "%s: gpio request failed \n", __func__);
+ return status;
+ }
+ status = gpio_direction_output(i, 1);
+ if (status < 0) {
+ printk(KERN_ERR "%s: gpio direction failed \n", __func__);
+ gpio_free(i);
+ return status;
+ }
+ gpio_set_value(i, 1);
+ gpio_free(i);
+ }
+ return status;
+}
+/**
+ * ske_kp_init - enable the gpio configuration
+ * @kp: keypad device data pointer
+ *
+ * This function is used to enable the gpio configuration for keypad
+ *
+ */
+static int ske_kp_init(struct keypad_t *kp)
+{
+ int ret;
+ ret = ske_set_gpio_row(ROW_PIN_I3, ROW_PIN_I0);
+ if (ret < 0)
+ goto err;
+ ret = ske_set_gpio_row(ROW_PIN_I7, ROW_PIN_I4);
+ if (ret < 0)
+ goto err;
+ ret = ske_set_gpio_column(COL_PIN_O3, COL_PIN_O0);
+ if (ret < 0)
+ goto err;
+ ret = ske_set_gpio_column(COL_PIN_O7, COL_PIN_O4);
+ if (ret < 0)
+ goto err;
+ ret = stm_gpio_altfuncenable(GPIO_ALT_KEYPAD);
+ if (ret)
+ goto err;
+ return 0;
+err:
+ printk(KERN_ERR "%s: failed \n", __func__);
+ return ret;
+}
+/**
+ * ske_kp_exit - disable the gpio configuration
+ * @kp: keypad device data pointer
+ *
+ * This function is used to disable the gpio configuration for keypad
+ *
+ */
+static int ske_kp_exit(struct keypad_t *kp)
+{
+ stm_gpio_altfuncdisable(GPIO_ALT_KEYPAD);
+ return 0;
+}
+
+/*
+ * Initializes the key scan table (lookup table) as per pre-defined the scan
+ * codes to be passed to upper layer with respective key codes
+ */
+u8 const kpd_lookup_tbl[MAX_KPROW][MAX_KPROW] = {
+ {
+ KEY_RESERVED,
+ KEY_RESERVED,
+ KEY_RESERVED,
+ KEY_RESERVED,
+ KEY_RESERVED,
+ KEY_MENU,
+ KEY_RESERVED,
+ KEY_RESERVED
+ },
+ {
+ KEY_RESERVED,
+ KEY_RESERVED,
+ KEY_RESERVED,
+ KEY_3,
+ KEY_RESERVED,
+ KEY_RESERVED,
+ KEY_RESERVED,
+ KEY_RESERVED
+ },
+ {
+ KEY_RESERVED,
+ KEY_RESERVED,
+ KEY_RESERVED,
+ KEY_RESERVED,
+ KEY_RESERVED,
+ KEY_END,
+ KEY_RESERVED,
+ KEY_RESERVED
+ },
+ {
+ KEY_RESERVED,
+ KEY_RESERVED,
+ KEY_7,
+ KEY_DOWN,
+ KEY_UP,
+ KEY_VOLUMEDOWN,
+ KEY_RESERVED,
+ KEY_RESERVED
+ },
+ {
+ KEY_RESERVED,
+ KEY_4,
+ KEY_VOLUMEUP,
+ KEY_LEFT,
+ KEY_RESERVED,
+ KEY_0,
+ KEY_RESERVED,
+ KEY_RESERVED
+ },
+ {
+ KEY_9,
+ KEY_RESERVED,
+ KEY_RIGHT,
+ KEY_RESERVED,
+ KEY_RESERVED,
+ KEY_1,
+ KEY_RESERVED,
+ KEY_RESERVED
+ },
+ {
+ KEY_RESERVED,
+ KEY_RESERVED,
+ KEY_BACK,
+ KEY_RESERVED,
+ KEY_SEND,
+ KEY_RESERVED,
+ KEY_RESERVED,
+ KEY_2
+ },
+ {
+ KEY_RESERVED,
+ KEY_RESERVED,
+ KEY_RESERVED,
+ KEY_RESERVED,
+ KEY_RESERVED,
+ KEY_RESERVED,
+ KEY_ENTER,
+ KEY_RESERVED
+ }
+};
+
+static struct keypad_device keypad_board = {
+ .init = ske_kp_init,
+ .exit = ske_kp_exit,
+ .kcode_tbl = (u8 *) kpd_lookup_tbl,
+ .krow = MAX_KPROW,
+ .kcol = MAX_KPCOL,
+ .debounce_period = KEYPAD_DEBOUNCE_PERIOD_SKE,
+ .irqtype = 0,
+ .int_status = KP_INT_DISABLED,
+ .int_line_behaviour = INT_LINE_NOTSET,
+};
+
+struct resource keypad_resources[] = {
+ [0] = {
+ .start = U8500_SKE_BASE,
+ .end = U8500_SKE_BASE + SZ_4K - 1,
+ .name = "ux500_ske_base",
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_SKE_KP,
+ .end = IRQ_SKE_KP,
+ .name = "ux500_ske_irq",
+ .flags = IORESOURCE_IRQ,
+ },
+};
+struct platform_device ske_keypad_device = {
+ .name = "ske-kp",
+ .id = -1,
+ .dev = {
+ .platform_data = &keypad_board,
+ },
+ .num_resources = ARRAY_SIZE(keypad_resources),
+ .resource = keypad_resources,
+};
+#endif
#if defined(CONFIG_U5500_MLOADER_HELPER)
struct platform_device mloader_helper_device = {
.name = "mloader_helper",
diff --git a/arch/arm/mach-ux500/include/mach/devices.h b/arch/arm/mach-ux500/include/mach/devices.h
index 73ddb146626..5acb60460f3 100755
--- a/arch/arm/mach-ux500/include/mach/devices.h
+++ b/arch/arm/mach-ux500/include/mach/devices.h
@@ -50,6 +50,7 @@ extern struct platform_device ux500_musb_device;
extern struct amba_device ux500_uart0_device;
extern struct amba_device ux500_uart1_device;
extern struct amba_device ux500_uart2_device;
+extern struct platform_device ske_keypad_device;
#ifdef CONFIG_U5500_MLOADER_HELPER
extern struct platform_device mloader_helper_device;
diff --git a/arch/arm/mach-ux500/include/mach/irqs.h b/arch/arm/mach-ux500/include/mach/irqs.h
index b883d013773..88e51d1c4da 100755
--- a/arch/arm/mach-ux500/include/mach/irqs.h
+++ b/arch/arm/mach-ux500/include/mach/irqs.h
@@ -51,6 +51,7 @@
#define IRQ_SDMMC1 (IRQ_SPI_START + 50)
#define IRQ_I2C4 (IRQ_SPI_START + 51)
#define IRQ_SSP1 (IRQ_SPI_START + 52)
+#define IRQ_SKE_KP (IRQ_SPI_START + 54)
#define IRQ_I2C2 (IRQ_SPI_START + 55)
#define IRQ_SDMMC3 (IRQ_SPI_START + 59)
#define IRQ_SDMMC0 (IRQ_SPI_START + 60)
diff --git a/arch/arm/mach-ux500/include/mach/kpd.h b/arch/arm/mach-ux500/include/mach/kpd.h
index 46177466078..ffff8eea193 100755
--- a/arch/arm/mach-ux500/include/mach/kpd.h
+++ b/arch/arm/mach-ux500/include/mach/kpd.h
@@ -14,12 +14,14 @@
#define CONFIG_AUTOSCAN_ENABLED 1
#endif
#include <mach/hardware.h>
+#include <linux/clk.h>
#define MAX_KPROW 8
#define MAX_KPCOL 8
+#define MAX_KEYS (MAX_KPROW * MAX_KPCOL)
/*keypad related Constants*/
-#define KEYPAD_RELEASE_PERIOD 11 /*110 Msec, repeate key scan time */
-#define KEYPAD_SCAN_PERIOD 4 /*40Msec for new keypress */
+#define KEYPAD_RELEASE_PERIOD 11 /*11 msec, repeate key scan time */
+#define KEYPAD_SCAN_PERIOD 4 /*4msec for new keypress */
#define KEYPAD_STATE_DEFAULT 0
#define KEYPAD_STATE_PRESSED 1
#define KEYPAD_STATE_PRESSACK 2
@@ -33,18 +35,18 @@ struct keypad_t;
* struct keypad_device - Device data structure for platform specific data
* @init: pointer to keypad init function
* @exit: pointer to keypad deinitialisation function
- * @autoscan_check: pointer to read autoscan status function, not used
+ * @autoscan_check: pointer to read autoscan status function
* currently
* @autoscan_disable: pointer to autoscan feature disable function,
* not used currently
* @autoscan_results: pointer to read autoscan results function
- * @autoscan_en: pointer to enable autoscan feature function, not used
+ * @autoscan_en: pointer to enable autoscan feature function
* currently
* @irqen: pointer to enable irq function
* @irqdis: pointer to disable irq function
* @kcode_tbl: lookup table for keycodes
* @krow: mask for available rows, value is 0xFF
- * @kcol: mask for available columns, value is 0xFF
+ * @kcol: mask for available columns, value is 0xFF
* @irqdis_int: pointer to disable irq function, to be called from ISR
* @debounce_period: platform specific debounce time, can be fine tuned later
* @irqtype: type of interrupt
@@ -54,47 +56,51 @@ struct keypad_t;
* @enable_wakeup: specifies if keypad event can wake up system from sleep
*/
struct keypad_device {
- int (*init)(struct keypad_t *kp);
- int (*exit)(struct keypad_t *kp);
- int (*autoscan_check)(void);
- void (*autoscan_disable)(void);
- int (*autoscan_results)(struct keypad_t *kp);
- void (*autoscan_en)(void);
- int (*irqen)(struct keypad_t *kp);
- int (*irqdis)(struct keypad_t *kp); /* normal disable */
- u8 *kcode_tbl;
- u8 krow;
- u8 kcol;
- int (*irqdis_int)(struct keypad_t *kp);
- /* func used wen disable in interrupt handler */
- u8 debounce_period;
- unsigned long irqtype;
- u8 irq; /*IRQ no*/
- u8 int_status;
- u8 int_line_behaviour;
- bool enable_wakeup;
+ int (*init)(struct keypad_t *kp);
+ int (*exit)(struct keypad_t *kp);
+ int (*autoscan_check)(void);
+ void (*autoscan_disable)(void);
+ int (*autoscan_results)(struct keypad_t *kp);
+ void (*autoscan_en)(void);
+ int (*irqen)(struct keypad_t *kp);
+ int (*irqdis)(struct keypad_t *kp);
+ u8 *kcode_tbl;
+ u8 krow;
+ u8 kcol;
+ int (*irqdis_int)(struct keypad_t *kp);
+ u8 debounce_period;
+ unsigned long irqtype;
+ u8 irq;
+ u8 int_status;
+ u8 int_line_behaviour;
+ bool enable_wakeup;
};
-
/**
* struct keypad_t - keypad data structure used internally by keypad driver
* @irq: irq no
* @mode: 0 for interrupt mode, 1 for polling mode
+ * @ske_regs: ske regsiters base address
+ * @cr_lock: spinlock variable
* @key_state: array for saving keystates
* @lockbits: used for synchronisation in ISR
* @inp_dev: pointer to input device object
- * @address_for_data: not used
* @kscan_work: work queue
* @board: keypad platform device
+ * @key_cnt: count the keys pressed
+ * @clk: clock structure pointer
*/
struct keypad_t {
int irq;
int mode;
+ void __iomem *ske_regs;
int key_state[MAX_KPROW][MAX_KPCOL];
unsigned long lockbits;
+ spinlock_t cr_lock;
struct input_dev *inp_dev;
- void *address_for_data;
struct delayed_work kscan_work;
struct keypad_device *board;
+ int key_cnt;
+ struct clk *clk;
};
/**
* enum kp_int_status - enum for INTR status