* [RESEND/PATCHv2] Input: omap-keypad: dynamically handle register offsets
@ 2012-04-26 5:54 Sourav Poddar
2012-05-08 17:26 ` Poddar, Sourav
2012-05-09 5:18 ` Dmitry Torokhov
0 siblings, 2 replies; 11+ messages in thread
From: Sourav Poddar @ 2012-04-26 5:54 UTC (permalink / raw)
To: dmitry.torokhov, dtor, linux-input, linux-omap; +Cc: sourav.poddar, balbi, akpm
From: G, Manjunath Kondaiah <manjugk@ti.com>
Keypad controller register offsets are different for omap4
and omap5. Handle these offsets through static mapping and
assign these mappings during run time.
Tested on omap4430 sdp with 3.4-rc3.
Tested on omap5430evm with 3.1-custom kernel.
Cc: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Felipe Balbi <balbi@ti.com>
Signed-off-by: G, Manjunath Kondaiah <manjugk@ti.com>
Signed-off-by: Sourav Poddar <sourav.poddar@ti.com>
---
Changes since v1:
- Fix Felipe's comment about getting rid
of one argument from irqstatus/irqenable api
- Fix Dmitry's comment:
- get rid of revision check in readl/writel
- Relace ENODEV with proper macro.
- Use switch statement
drivers/input/keyboard/Kconfig | 6 +-
drivers/input/keyboard/omap4-keypad.c | 115 ++++++++++++++++++++++++++-------
2 files changed, 95 insertions(+), 26 deletions(-)
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
index f354813..9a0e1a9 100644
--- a/drivers/input/keyboard/Kconfig
+++ b/drivers/input/keyboard/Kconfig
@@ -511,10 +511,10 @@ config KEYBOARD_OMAP
To compile this driver as a module, choose M here: the
module will be called omap-keypad.
-config KEYBOARD_OMAP4
- tristate "TI OMAP4 keypad support"
+config KEYBOARD_OMAP4+
+ tristate "TI OMAP4+ keypad support"
help
- Say Y here if you want to use the OMAP4 keypad.
+ Say Y here if you want to use the OMAP4+ keypad.
To compile this driver as a module, choose M here: the
module will be called omap4-keypad.
diff --git a/drivers/input/keyboard/omap4-keypad.c b/drivers/input/keyboard/omap4-keypad.c
index e809ac0..8e46563 100644
--- a/drivers/input/keyboard/omap4-keypad.c
+++ b/drivers/input/keyboard/omap4-keypad.c
@@ -68,6 +68,11 @@
#define OMAP4_MASK_IRQSTATUSDISABLE 0xFFFF
+enum {
+ KBD_REVISION_OMAP4 = 0,
+ KBD_REVISION_OMAP5,
+};
+
struct omap4_keypad {
struct input_dev *input;
@@ -76,11 +81,61 @@ struct omap4_keypad {
unsigned int rows;
unsigned int cols;
+ unsigned int revision;
+ u32 irqstatus;
+ u32 irqenable;
+ u32 reg_offset;
unsigned int row_shift;
unsigned char key_state[8];
unsigned short keymap[];
};
+static int kbd_read_irqstatus(struct omap4_keypad *keypad_data, u32 offset)
+{
+ return __raw_readl(keypad_data->base + offset);
+}
+
+static int kbd_write_irqstatus(struct omap4_keypad *keypad_data,
+ u32 value)
+{
+ return __raw_writel(value, keypad_data->base + keypad_data->irqstatus);
+}
+
+static int kbd_write_irqenable(struct omap4_keypad *keypad_data,
+ u32 value)
+{
+ return __raw_writel(value, keypad_data->base + keypad_data->irqenable);
+}
+
+static int kbd_readl(struct omap4_keypad *keypad_data, u32 offset)
+{
+ return __raw_readl(keypad_data->base +
+ keypad_data->reg_offset + offset);
+}
+
+static void kbd_writel(struct omap4_keypad *keypad_data, u32 offset, u32 value)
+{
+ __raw_writel(value, keypad_data->base +
+ keypad_data->reg_offset + offset);
+}
+
+static int kbd_read_revision(struct omap4_keypad *keypad_data, u32 offset)
+{
+ int reg;
+ reg = __raw_readl(keypad_data->base + offset);
+ reg &= 0x03 << 30;
+ reg >>= 30;
+
+ switch (reg) {
+ case 1:
+ return KBD_REVISION_OMAP5;
+ case 0:
+ return KBD_REVISION_OMAP4;
+ default:
+ return -EINVAL;
+ }
+}
+
/* Interrupt handler */
static irqreturn_t omap4_keypad_interrupt(int irq, void *dev_id)
{
@@ -91,12 +146,10 @@ static irqreturn_t omap4_keypad_interrupt(int irq, void *dev_id)
u32 *new_state = (u32 *) key_state;
/* Disable interrupts */
- __raw_writel(OMAP4_VAL_IRQDISABLE,
- keypad_data->base + OMAP4_KBD_IRQENABLE);
+ kbd_write_irqenable(keypad_data, OMAP4_VAL_IRQDISABLE);
- *new_state = __raw_readl(keypad_data->base + OMAP4_KBD_FULLCODE31_0);
- *(new_state + 1) = __raw_readl(keypad_data->base
- + OMAP4_KBD_FULLCODE63_32);
+ *new_state = kbd_readl(keypad_data, OMAP4_KBD_FULLCODE31_0);
+ *(new_state + 1) = kbd_readl(keypad_data, OMAP4_KBD_FULLCODE63_32);
for (row = 0; row < keypad_data->rows; row++) {
changed = key_state[row] ^ keypad_data->key_state[row];
@@ -121,12 +174,12 @@ static irqreturn_t omap4_keypad_interrupt(int irq, void *dev_id)
sizeof(keypad_data->key_state));
/* clear pending interrupts */
- __raw_writel(__raw_readl(keypad_data->base + OMAP4_KBD_IRQSTATUS),
- keypad_data->base + OMAP4_KBD_IRQSTATUS);
+ kbd_write_irqstatus(keypad_data,
+ kbd_read_irqstatus(keypad_data, keypad_data->irqstatus));
/* enable interrupts */
- __raw_writel(OMAP4_DEF_IRQENABLE_EVENTEN | OMAP4_DEF_IRQENABLE_LONGKEY,
- keypad_data->base + OMAP4_KBD_IRQENABLE);
+ kbd_write_irqenable(keypad_data, OMAP4_DEF_IRQENABLE_EVENTEN |
+ OMAP4_DEF_IRQENABLE_LONGKEY);
return IRQ_HANDLED;
}
@@ -139,16 +192,33 @@ static int omap4_keypad_open(struct input_dev *input)
disable_irq(keypad_data->irq);
- __raw_writel(OMAP4_VAL_FUNCTIONALCFG,
- keypad_data->base + OMAP4_KBD_CTRL);
- __raw_writel(OMAP4_VAL_DEBOUNCINGTIME,
- keypad_data->base + OMAP4_KBD_DEBOUNCINGTIME);
- __raw_writel(OMAP4_VAL_IRQDISABLE,
- keypad_data->base + OMAP4_KBD_IRQSTATUS);
- __raw_writel(OMAP4_DEF_IRQENABLE_EVENTEN | OMAP4_DEF_IRQENABLE_LONGKEY,
- keypad_data->base + OMAP4_KBD_IRQENABLE);
- __raw_writel(OMAP4_DEF_WUP_EVENT_ENA | OMAP4_DEF_WUP_LONG_KEY_ENA,
- keypad_data->base + OMAP4_KBD_WAKEUPENABLE);
+ keypad_data->revision = kbd_read_revision(keypad_data,
+ OMAP4_KBD_REVISION);
+ switch (keypad_data->revision) {
+ case 1:
+ keypad_data->irqstatus = OMAP4_KBD_IRQSTATUS + 0x0c;
+ keypad_data->irqenable = OMAP4_KBD_IRQENABLE + 0x0c;
+ keypad_data->reg_offset = 0x10;
+ break;
+ case 0:
+ keypad_data->irqstatus = OMAP4_KBD_IRQSTATUS;
+ keypad_data->irqenable = OMAP4_KBD_IRQENABLE;
+ keypad_data->reg_offset = 0x00;
+ break;
+ default:
+ pr_err("Omap keypad not found\n");
+ return -ENODEV;
+ }
+
+ kbd_writel(keypad_data, OMAP4_KBD_CTRL,
+ OMAP4_VAL_FUNCTIONALCFG);
+ kbd_writel(keypad_data, OMAP4_KBD_DEBOUNCINGTIME,
+ OMAP4_VAL_DEBOUNCINGTIME);
+ kbd_write_irqstatus(keypad_data, OMAP4_VAL_IRQDISABLE);
+ kbd_write_irqenable(keypad_data, OMAP4_DEF_IRQENABLE_EVENTEN |
+ OMAP4_DEF_IRQENABLE_LONGKEY);
+ kbd_writel(keypad_data, OMAP4_KBD_WAKEUPENABLE,
+ OMAP4_DEF_WUP_EVENT_ENA | OMAP4_DEF_WUP_LONG_KEY_ENA);
enable_irq(keypad_data->irq);
@@ -162,12 +232,11 @@ static void omap4_keypad_close(struct input_dev *input)
disable_irq(keypad_data->irq);
/* Disable interrupts */
- __raw_writel(OMAP4_VAL_IRQDISABLE,
- keypad_data->base + OMAP4_KBD_IRQENABLE);
+ kbd_write_irqenable(keypad_data, OMAP4_VAL_IRQDISABLE);
/* clear pending interrupts */
- __raw_writel(__raw_readl(keypad_data->base + OMAP4_KBD_IRQSTATUS),
- keypad_data->base + OMAP4_KBD_IRQSTATUS);
+ kbd_write_irqstatus(keypad_data,
+ kbd_read_irqstatus(keypad_data, keypad_data->irqstatus));
enable_irq(keypad_data->irq);
--
1.7.1
^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [RESEND/PATCHv2] Input: omap-keypad: dynamically handle register offsets
2012-04-26 5:54 [RESEND/PATCHv2] Input: omap-keypad: dynamically handle register offsets Sourav Poddar
@ 2012-05-08 17:26 ` Poddar, Sourav
2012-05-09 5:18 ` Dmitry Torokhov
1 sibling, 0 replies; 11+ messages in thread
From: Poddar, Sourav @ 2012-05-08 17:26 UTC (permalink / raw)
To: dmitry.torokhov, dtor, linux-input, linux-omap, akpm; +Cc: sourav.poddar, balbi
Gentle ping on this.. any comments?
~Sourav
On Thu, Apr 26, 2012 at 11:24 AM, Sourav Poddar <sourav.poddar@ti.com> wrote:
> From: G, Manjunath Kondaiah <manjugk@ti.com>
>
> Keypad controller register offsets are different for omap4
> and omap5. Handle these offsets through static mapping and
> assign these mappings during run time.
>
> Tested on omap4430 sdp with 3.4-rc3.
> Tested on omap5430evm with 3.1-custom kernel.
>
> Cc: Andrew Morton <akpm@linux-foundation.org>
> Signed-off-by: Felipe Balbi <balbi@ti.com>
> Signed-off-by: G, Manjunath Kondaiah <manjugk@ti.com>
> Signed-off-by: Sourav Poddar <sourav.poddar@ti.com>
> ---
> Changes since v1:
> - Fix Felipe's comment about getting rid
> of one argument from irqstatus/irqenable api
> - Fix Dmitry's comment:
> - get rid of revision check in readl/writel
> - Relace ENODEV with proper macro.
> - Use switch statement
> drivers/input/keyboard/Kconfig | 6 +-
> drivers/input/keyboard/omap4-keypad.c | 115 ++++++++++++++++++++++++++-------
> 2 files changed, 95 insertions(+), 26 deletions(-)
>
> diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
> index f354813..9a0e1a9 100644
> --- a/drivers/input/keyboard/Kconfig
> +++ b/drivers/input/keyboard/Kconfig
> @@ -511,10 +511,10 @@ config KEYBOARD_OMAP
> To compile this driver as a module, choose M here: the
> module will be called omap-keypad.
>
> -config KEYBOARD_OMAP4
> - tristate "TI OMAP4 keypad support"
> +config KEYBOARD_OMAP4+
> + tristate "TI OMAP4+ keypad support"
> help
> - Say Y here if you want to use the OMAP4 keypad.
> + Say Y here if you want to use the OMAP4+ keypad.
>
> To compile this driver as a module, choose M here: the
> module will be called omap4-keypad.
> diff --git a/drivers/input/keyboard/omap4-keypad.c b/drivers/input/keyboard/omap4-keypad.c
> index e809ac0..8e46563 100644
> --- a/drivers/input/keyboard/omap4-keypad.c
> +++ b/drivers/input/keyboard/omap4-keypad.c
> @@ -68,6 +68,11 @@
>
> #define OMAP4_MASK_IRQSTATUSDISABLE 0xFFFF
>
> +enum {
> + KBD_REVISION_OMAP4 = 0,
> + KBD_REVISION_OMAP5,
> +};
> +
> struct omap4_keypad {
> struct input_dev *input;
>
> @@ -76,11 +81,61 @@ struct omap4_keypad {
>
> unsigned int rows;
> unsigned int cols;
> + unsigned int revision;
> + u32 irqstatus;
> + u32 irqenable;
> + u32 reg_offset;
> unsigned int row_shift;
> unsigned char key_state[8];
> unsigned short keymap[];
> };
>
> +static int kbd_read_irqstatus(struct omap4_keypad *keypad_data, u32 offset)
> +{
> + return __raw_readl(keypad_data->base + offset);
> +}
> +
> +static int kbd_write_irqstatus(struct omap4_keypad *keypad_data,
> + u32 value)
> +{
> + return __raw_writel(value, keypad_data->base + keypad_data->irqstatus);
> +}
> +
> +static int kbd_write_irqenable(struct omap4_keypad *keypad_data,
> + u32 value)
> +{
> + return __raw_writel(value, keypad_data->base + keypad_data->irqenable);
> +}
> +
> +static int kbd_readl(struct omap4_keypad *keypad_data, u32 offset)
> +{
> + return __raw_readl(keypad_data->base +
> + keypad_data->reg_offset + offset);
> +}
> +
> +static void kbd_writel(struct omap4_keypad *keypad_data, u32 offset, u32 value)
> +{
> + __raw_writel(value, keypad_data->base +
> + keypad_data->reg_offset + offset);
> +}
> +
> +static int kbd_read_revision(struct omap4_keypad *keypad_data, u32 offset)
> +{
> + int reg;
> + reg = __raw_readl(keypad_data->base + offset);
> + reg &= 0x03 << 30;
> + reg >>= 30;
> +
> + switch (reg) {
> + case 1:
> + return KBD_REVISION_OMAP5;
> + case 0:
> + return KBD_REVISION_OMAP4;
> + default:
> + return -EINVAL;
> + }
> +}
> +
> /* Interrupt handler */
> static irqreturn_t omap4_keypad_interrupt(int irq, void *dev_id)
> {
> @@ -91,12 +146,10 @@ static irqreturn_t omap4_keypad_interrupt(int irq, void *dev_id)
> u32 *new_state = (u32 *) key_state;
>
> /* Disable interrupts */
> - __raw_writel(OMAP4_VAL_IRQDISABLE,
> - keypad_data->base + OMAP4_KBD_IRQENABLE);
> + kbd_write_irqenable(keypad_data, OMAP4_VAL_IRQDISABLE);
>
> - *new_state = __raw_readl(keypad_data->base + OMAP4_KBD_FULLCODE31_0);
> - *(new_state + 1) = __raw_readl(keypad_data->base
> - + OMAP4_KBD_FULLCODE63_32);
> + *new_state = kbd_readl(keypad_data, OMAP4_KBD_FULLCODE31_0);
> + *(new_state + 1) = kbd_readl(keypad_data, OMAP4_KBD_FULLCODE63_32);
>
> for (row = 0; row < keypad_data->rows; row++) {
> changed = key_state[row] ^ keypad_data->key_state[row];
> @@ -121,12 +174,12 @@ static irqreturn_t omap4_keypad_interrupt(int irq, void *dev_id)
> sizeof(keypad_data->key_state));
>
> /* clear pending interrupts */
> - __raw_writel(__raw_readl(keypad_data->base + OMAP4_KBD_IRQSTATUS),
> - keypad_data->base + OMAP4_KBD_IRQSTATUS);
> + kbd_write_irqstatus(keypad_data,
> + kbd_read_irqstatus(keypad_data, keypad_data->irqstatus));
>
> /* enable interrupts */
> - __raw_writel(OMAP4_DEF_IRQENABLE_EVENTEN | OMAP4_DEF_IRQENABLE_LONGKEY,
> - keypad_data->base + OMAP4_KBD_IRQENABLE);
> + kbd_write_irqenable(keypad_data, OMAP4_DEF_IRQENABLE_EVENTEN |
> + OMAP4_DEF_IRQENABLE_LONGKEY);
>
> return IRQ_HANDLED;
> }
> @@ -139,16 +192,33 @@ static int omap4_keypad_open(struct input_dev *input)
>
> disable_irq(keypad_data->irq);
>
> - __raw_writel(OMAP4_VAL_FUNCTIONALCFG,
> - keypad_data->base + OMAP4_KBD_CTRL);
> - __raw_writel(OMAP4_VAL_DEBOUNCINGTIME,
> - keypad_data->base + OMAP4_KBD_DEBOUNCINGTIME);
> - __raw_writel(OMAP4_VAL_IRQDISABLE,
> - keypad_data->base + OMAP4_KBD_IRQSTATUS);
> - __raw_writel(OMAP4_DEF_IRQENABLE_EVENTEN | OMAP4_DEF_IRQENABLE_LONGKEY,
> - keypad_data->base + OMAP4_KBD_IRQENABLE);
> - __raw_writel(OMAP4_DEF_WUP_EVENT_ENA | OMAP4_DEF_WUP_LONG_KEY_ENA,
> - keypad_data->base + OMAP4_KBD_WAKEUPENABLE);
> + keypad_data->revision = kbd_read_revision(keypad_data,
> + OMAP4_KBD_REVISION);
> + switch (keypad_data->revision) {
> + case 1:
> + keypad_data->irqstatus = OMAP4_KBD_IRQSTATUS + 0x0c;
> + keypad_data->irqenable = OMAP4_KBD_IRQENABLE + 0x0c;
> + keypad_data->reg_offset = 0x10;
> + break;
> + case 0:
> + keypad_data->irqstatus = OMAP4_KBD_IRQSTATUS;
> + keypad_data->irqenable = OMAP4_KBD_IRQENABLE;
> + keypad_data->reg_offset = 0x00;
> + break;
> + default:
> + pr_err("Omap keypad not found\n");
> + return -ENODEV;
> + }
> +
> + kbd_writel(keypad_data, OMAP4_KBD_CTRL,
> + OMAP4_VAL_FUNCTIONALCFG);
> + kbd_writel(keypad_data, OMAP4_KBD_DEBOUNCINGTIME,
> + OMAP4_VAL_DEBOUNCINGTIME);
> + kbd_write_irqstatus(keypad_data, OMAP4_VAL_IRQDISABLE);
> + kbd_write_irqenable(keypad_data, OMAP4_DEF_IRQENABLE_EVENTEN |
> + OMAP4_DEF_IRQENABLE_LONGKEY);
> + kbd_writel(keypad_data, OMAP4_KBD_WAKEUPENABLE,
> + OMAP4_DEF_WUP_EVENT_ENA | OMAP4_DEF_WUP_LONG_KEY_ENA);
>
> enable_irq(keypad_data->irq);
>
> @@ -162,12 +232,11 @@ static void omap4_keypad_close(struct input_dev *input)
> disable_irq(keypad_data->irq);
>
> /* Disable interrupts */
> - __raw_writel(OMAP4_VAL_IRQDISABLE,
> - keypad_data->base + OMAP4_KBD_IRQENABLE);
> + kbd_write_irqenable(keypad_data, OMAP4_VAL_IRQDISABLE);
>
> /* clear pending interrupts */
> - __raw_writel(__raw_readl(keypad_data->base + OMAP4_KBD_IRQSTATUS),
> - keypad_data->base + OMAP4_KBD_IRQSTATUS);
> + kbd_write_irqstatus(keypad_data,
> + kbd_read_irqstatus(keypad_data, keypad_data->irqstatus));
>
> enable_irq(keypad_data->irq);
>
> --
> 1.7.1
>
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [RESEND/PATCHv2] Input: omap-keypad: dynamically handle register offsets
2012-04-26 5:54 [RESEND/PATCHv2] Input: omap-keypad: dynamically handle register offsets Sourav Poddar
2012-05-08 17:26 ` Poddar, Sourav
@ 2012-05-09 5:18 ` Dmitry Torokhov
2012-05-09 6:54 ` Poddar, Sourav
1 sibling, 1 reply; 11+ messages in thread
From: Dmitry Torokhov @ 2012-05-09 5:18 UTC (permalink / raw)
To: Sourav Poddar; +Cc: linux-input, linux-omap, balbi, akpm
Ho Sourav,
On Thu, Apr 26, 2012 at 11:24:37AM +0530, Sourav Poddar wrote:
>
> -config KEYBOARD_OMAP4
> - tristate "TI OMAP4 keypad support"
> +config KEYBOARD_OMAP4+
I think this works purely by accident - '+' sign getting dropped by
parser...
> @@ -139,16 +192,33 @@ static int omap4_keypad_open(struct input_dev *input)
>
> disable_irq(keypad_data->irq);
>
> - __raw_writel(OMAP4_VAL_FUNCTIONALCFG,
> - keypad_data->base + OMAP4_KBD_CTRL);
> - __raw_writel(OMAP4_VAL_DEBOUNCINGTIME,
> - keypad_data->base + OMAP4_KBD_DEBOUNCINGTIME);
> - __raw_writel(OMAP4_VAL_IRQDISABLE,
> - keypad_data->base + OMAP4_KBD_IRQSTATUS);
> - __raw_writel(OMAP4_DEF_IRQENABLE_EVENTEN | OMAP4_DEF_IRQENABLE_LONGKEY,
> - keypad_data->base + OMAP4_KBD_IRQENABLE);
> - __raw_writel(OMAP4_DEF_WUP_EVENT_ENA | OMAP4_DEF_WUP_LONG_KEY_ENA,
> - keypad_data->base + OMAP4_KBD_WAKEUPENABLE);
> + keypad_data->revision = kbd_read_revision(keypad_data,
> + OMAP4_KBD_REVISION);
> + switch (keypad_data->revision) {
> + case 1:
> + keypad_data->irqstatus = OMAP4_KBD_IRQSTATUS + 0x0c;
> + keypad_data->irqenable = OMAP4_KBD_IRQENABLE + 0x0c;
> + keypad_data->reg_offset = 0x10;
> + break;
This should be done in probe().
Could you please tell me if the version of the patch below works for
you?
Thanks.
--
Dmitry
Input: omap-keypad - dynamically handle register offsets
From: G, Manjunath Kondaiah <manjugk@ti.com>
Keypad controller register offsets are different for omap4
and omap5. Handle these offsets through static mapping and
assign these mappings during run time.
Tested on omap4430 sdp with 3.4-rc3.
Tested on omap5430evm with 3.1-custom kernel.
Signed-off-by: Felipe Balbi <balbi@ti.com>
Signed-off-by: G, Manjunath Kondaiah <manjugk@ti.com>
Signed-off-by: Sourav Poddar <sourav.poddar@ti.com>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
---
drivers/input/keyboard/Kconfig | 4 +
drivers/input/keyboard/omap4-keypad.c | 102 +++++++++++++++++++++++++--------
2 files changed, 80 insertions(+), 26 deletions(-)
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
index 20a3753..84ee155 100644
--- a/drivers/input/keyboard/Kconfig
+++ b/drivers/input/keyboard/Kconfig
@@ -531,9 +531,9 @@ config KEYBOARD_OMAP
module will be called omap-keypad.
config KEYBOARD_OMAP4
- tristate "TI OMAP4 keypad support"
+ tristate "TI OMAP4+ keypad support"
help
- Say Y here if you want to use the OMAP4 keypad.
+ Say Y here if you want to use the OMAP4+ keypad.
To compile this driver as a module, choose M here: the
module will be called omap4-keypad.
diff --git a/drivers/input/keyboard/omap4-keypad.c b/drivers/input/keyboard/omap4-keypad.c
index e809ac0..ddd5c9e 100644
--- a/drivers/input/keyboard/omap4-keypad.c
+++ b/drivers/input/keyboard/omap4-keypad.c
@@ -68,19 +68,52 @@
#define OMAP4_MASK_IRQSTATUSDISABLE 0xFFFF
+enum {
+ KBD_REVISION_OMAP4 = 0,
+ KBD_REVISION_OMAP5,
+};
+
struct omap4_keypad {
struct input_dev *input;
void __iomem *base;
- int irq;
+ unsigned int irq;
unsigned int rows;
unsigned int cols;
+ u32 reg_offset;
+ u32 irqreg_offset;
unsigned int row_shift;
unsigned char key_state[8];
unsigned short keymap[];
};
+static int kbd_readl(struct omap4_keypad *keypad_data, u32 offset)
+{
+ return __raw_readl(keypad_data->base +
+ keypad_data->reg_offset + offset);
+}
+
+static void kbd_writel(struct omap4_keypad *keypad_data, u32 offset, u32 value)
+{
+ __raw_writel(value,
+ keypad_data->base + keypad_data->reg_offset + offset);
+}
+
+static int kbd_read_irqreg(struct omap4_keypad *keypad_data, u32 offset)
+{
+ return __raw_readl(keypad_data->base +
+ keypad_data->irqreg_offset + offset);
+}
+
+static void kbd_write_irqreg(struct omap4_keypad *keypad_data,
+ u32 offset, u32 value)
+{
+ __raw_writel(value,
+ keypad_data->base + keypad_data->irqreg_offset + offset);
+}
+
+
/* Interrupt handler */
static irqreturn_t omap4_keypad_interrupt(int irq, void *dev_id)
{
@@ -91,12 +124,11 @@ static irqreturn_t omap4_keypad_interrupt(int irq, void *dev_id)
u32 *new_state = (u32 *) key_state;
/* Disable interrupts */
- __raw_writel(OMAP4_VAL_IRQDISABLE,
- keypad_data->base + OMAP4_KBD_IRQENABLE);
+ kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQENABLE,
+ OMAP4_VAL_IRQDISABLE);
- *new_state = __raw_readl(keypad_data->base + OMAP4_KBD_FULLCODE31_0);
- *(new_state + 1) = __raw_readl(keypad_data->base
- + OMAP4_KBD_FULLCODE63_32);
+ *new_state = kbd_readl(keypad_data, OMAP4_KBD_FULLCODE31_0);
+ *(new_state + 1) = kbd_readl(keypad_data, OMAP4_KBD_FULLCODE63_32);
for (row = 0; row < keypad_data->rows; row++) {
changed = key_state[row] ^ keypad_data->key_state[row];
@@ -121,12 +153,13 @@ static irqreturn_t omap4_keypad_interrupt(int irq, void *dev_id)
sizeof(keypad_data->key_state));
/* clear pending interrupts */
- __raw_writel(__raw_readl(keypad_data->base + OMAP4_KBD_IRQSTATUS),
- keypad_data->base + OMAP4_KBD_IRQSTATUS);
+ kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS,
+ kbd_read_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS));
/* enable interrupts */
- __raw_writel(OMAP4_DEF_IRQENABLE_EVENTEN | OMAP4_DEF_IRQENABLE_LONGKEY,
- keypad_data->base + OMAP4_KBD_IRQENABLE);
+ kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQENABLE,
+ OMAP4_DEF_IRQENABLE_EVENTEN |
+ OMAP4_DEF_IRQENABLE_LONGKEY);
return IRQ_HANDLED;
}
@@ -139,16 +172,17 @@ static int omap4_keypad_open(struct input_dev *input)
disable_irq(keypad_data->irq);
- __raw_writel(OMAP4_VAL_FUNCTIONALCFG,
- keypad_data->base + OMAP4_KBD_CTRL);
- __raw_writel(OMAP4_VAL_DEBOUNCINGTIME,
- keypad_data->base + OMAP4_KBD_DEBOUNCINGTIME);
- __raw_writel(OMAP4_VAL_IRQDISABLE,
- keypad_data->base + OMAP4_KBD_IRQSTATUS);
- __raw_writel(OMAP4_DEF_IRQENABLE_EVENTEN | OMAP4_DEF_IRQENABLE_LONGKEY,
- keypad_data->base + OMAP4_KBD_IRQENABLE);
- __raw_writel(OMAP4_DEF_WUP_EVENT_ENA | OMAP4_DEF_WUP_LONG_KEY_ENA,
- keypad_data->base + OMAP4_KBD_WAKEUPENABLE);
+ kbd_writel(keypad_data, OMAP4_KBD_CTRL,
+ OMAP4_VAL_FUNCTIONALCFG);
+ kbd_writel(keypad_data, OMAP4_KBD_DEBOUNCINGTIME,
+ OMAP4_VAL_DEBOUNCINGTIME);
+ kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS,
+ OMAP4_VAL_IRQDISABLE);
+ kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQENABLE,
+ OMAP4_DEF_IRQENABLE_EVENTEN |
+ OMAP4_DEF_IRQENABLE_LONGKEY);
+ kbd_writel(keypad_data, OMAP4_KBD_WAKEUPENABLE,
+ OMAP4_DEF_WUP_EVENT_ENA | OMAP4_DEF_WUP_LONG_KEY_ENA);
enable_irq(keypad_data->irq);
@@ -162,12 +196,12 @@ static void omap4_keypad_close(struct input_dev *input)
disable_irq(keypad_data->irq);
/* Disable interrupts */
- __raw_writel(OMAP4_VAL_IRQDISABLE,
- keypad_data->base + OMAP4_KBD_IRQENABLE);
+ kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQENABLE,
+ OMAP4_VAL_IRQDISABLE);
/* clear pending interrupts */
- __raw_writel(__raw_readl(keypad_data->base + OMAP4_KBD_IRQSTATUS),
- keypad_data->base + OMAP4_KBD_IRQSTATUS);
+ kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS,
+ kbd_read_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS));
enable_irq(keypad_data->irq);
@@ -182,6 +216,7 @@ static int __devinit omap4_keypad_probe(struct platform_device *pdev)
struct resource *res;
resource_size_t size;
unsigned int row_shift, max_keys;
+ int rev;
int irq;
int error;
@@ -241,6 +276,25 @@ static int __devinit omap4_keypad_probe(struct platform_device *pdev)
keypad_data->rows = pdata->rows;
keypad_data->cols = pdata->cols;
+ rev = __raw_readl(keypad_data->base + OMAP4_KBD_REVISION);
+ rev &= 0x03 << 30;
+ rev >>= 30;
+ switch (rev) {
+ case KBD_REVISION_OMAP4:
+ keypad_data->reg_offset = 0x00;
+ keypad_data->irqreg_offset = 0x00;
+ break;
+ case KBD_REVISION_OMAP5:
+ keypad_data->reg_offset = 0x10;
+ keypad_data->irqreg_offset = 0x0c;
+ break;
+ default:
+ dev_err(&pdev->dev,
+ "Keypad reports unsupported revision %d", rev);
+ error = -EINVAL;
+ goto err_unmap;
+ }
+
/* input device allocation */
keypad_data->input = input_dev = input_allocate_device();
if (!input_dev) {
^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [RESEND/PATCHv2] Input: omap-keypad: dynamically handle register offsets
2012-05-09 5:18 ` Dmitry Torokhov
@ 2012-05-09 6:54 ` Poddar, Sourav
2012-05-09 7:07 ` Poddar, Sourav
2012-05-09 7:45 ` Dmitry Torokhov
0 siblings, 2 replies; 11+ messages in thread
From: Poddar, Sourav @ 2012-05-09 6:54 UTC (permalink / raw)
To: Dmitry Torokhov; +Cc: linux-input, linux-omap, balbi, akpm
Hi Dmitry ,
On Wed, May 9, 2012 at 10:48 AM, Dmitry Torokhov
<dmitry.torokhov@gmail.com> wrote:
> Ho Sourav,
>
> On Thu, Apr 26, 2012 at 11:24:37AM +0530, Sourav Poddar wrote:
>>
>> -config KEYBOARD_OMAP4
>> - tristate "TI OMAP4 keypad support"
>> +config KEYBOARD_OMAP4+
>
> I think this works purely by accident - '+' sign getting dropped by
> parser...
>
>> @@ -139,16 +192,33 @@ static int omap4_keypad_open(struct input_dev *input)
>>
>> disable_irq(keypad_data->irq);
>>
>> - __raw_writel(OMAP4_VAL_FUNCTIONALCFG,
>> - keypad_data->base + OMAP4_KBD_CTRL);
>> - __raw_writel(OMAP4_VAL_DEBOUNCINGTIME,
>> - keypad_data->base + OMAP4_KBD_DEBOUNCINGTIME);
>> - __raw_writel(OMAP4_VAL_IRQDISABLE,
>> - keypad_data->base + OMAP4_KBD_IRQSTATUS);
>> - __raw_writel(OMAP4_DEF_IRQENABLE_EVENTEN | OMAP4_DEF_IRQENABLE_LONGKEY,
>> - keypad_data->base + OMAP4_KBD_IRQENABLE);
>> - __raw_writel(OMAP4_DEF_WUP_EVENT_ENA | OMAP4_DEF_WUP_LONG_KEY_ENA,
>> - keypad_data->base + OMAP4_KBD_WAKEUPENABLE);
>> + keypad_data->revision = kbd_read_revision(keypad_data,
>> + OMAP4_KBD_REVISION);
>> + switch (keypad_data->revision) {
>> + case 1:
>> + keypad_data->irqstatus = OMAP4_KBD_IRQSTATUS + 0x0c;
>> + keypad_data->irqenable = OMAP4_KBD_IRQENABLE + 0x0c;
>> + keypad_data->reg_offset = 0x10;
>> + break;
>
> This should be done in probe().
>
Dont we then require "pm_runtime_put_sync" in probe, since we are trying
to read the keypad revision register.?
> Could you please tell me if the version of the patch below works for
> you?
>
I just quickly tested this patch and saw the following kernel carsh.
[ 1.571838] Bad mode in data abort handler detected
[ 1.576934] Internal error: Oops - bad mode: 0 [#1] SMP ARM
[ 1.582763] Modules linked in:
[ 1.585937] CPU: 0 Not tainted (3.4.0-rc5-dirty #11)
[ 1.591522] PC is at __key.13633+0x3f39df40/0x8
[ 1.596252] LR is at omap4_keypad_probe+0x1cc/0x3dc
[ 1.601348] pc : [<ffff0018>] lr : [<c0466ffc>] psr: 40000092
[ 1.601348] sp : df831e68 ip : fc31c000 fp : 00000040
[ 1.613311] r10: c2460000 r9 : 00000080 r8 : 00000003
[ 1.618774] r7 : de36e880 r6 : df966008 r5 : df965480 r4 : c2422bc0
[ 1.625579] r3 : 60000013 r2 : 00000000 r1 : 00000000 r0 : 0000001e
[ 1.632385] Flags: nZcv IRQs off FIQs on Mode IRQ_32 ISA ARM
Segment kernel
[ 1.640106] Control: 10c53c7d Table: 8000404a DAC: 00000017
[ 1.646118] Process swapper/0 (pid: 1, stack limit = 0xdf8302f8)
[ 1.652374] Stack: (0xdf831e68 to 0xdf832000)
[ 1.656921] 1e60: 0000001e 00000000 00000000
60000013 c2422bc0 df965480
[ 1.665466] 1e80: df966008 de36e880 00000003 00000080 c2460000
00000040 fc31c000 df831e68
[ 1.674011] 1ea0: c0466ffc ffff0018 40000092 ffffffff 00000000
c008b744 df967590 00000098
[ 1.682556] 1ec0: df96603c df966008 c0c49dd8 df96603c c06f2a00
0000008e c06687f0 c0643fcc
[ 1.691070] 1ee0: 00000000 c02b8748 c02b8730 c02b72c4 df966008
c06f2a00 df96603c 00000000
[ 1.699615] 1f00: 0000008e c02b74d8 c06f2a00 df831f18 c02b7444
c02b5b2c df8402a8 df968e90
[ 1.708160] 1f20: 00000000 c06f2a00 c06e5e28 de395bc0 00000000
c02b625c c0575768 c024d028
[ 1.716705] 1f40: df830000 c06f2a00 00000000 00000000 0000008e
c06687f0 c0643fcc c02b7ac4
[ 1.725219] 1f60: df830000 00000007 c06fdc00 00000000 0000008e
c0008630 00000001 c1058170
[ 1.733764] 1f80: c05f8500 c0643fcc 00000001 60000013 00000001
c05716e0 00000006 00000006
[ 1.742309] 1fa0: 60000013 c064dbb0 00000007 c06fdc00 c061e20c
0000008e c06687f0 c064dbb8
[ 1.750854] 1fc0: 00000000 c061e374 00000006 00000006 c061e20c
00000000 00000000 c061e28c
[ 1.759399] 1fe0: c00152b8 00000013 00000000 00000000 00000000
c00152b8 ffffffff 00000000
[ 1.767944] [<c0466ffc>] (omap4_keypad_probe+0x1cc/0x3dc) from
[<df831e68>] (0xdf831e68)
[ 1.776397] Code: e59ff410 ea0000bb ea00009a ea0000fa (ea000078)
[ 1.782775] ------------[ cut here ]------------
[ 1.787628] WARNING: at arch/arm/mach-omap2/omap_l3_noc.c:113
l3_interrupt_handler+0x17c/0x1b4()
[ 1.796783] L3 custom error: MASTER:MPU TARGET:L4CFG
[ 1.801971] Modules linked in:
[ 1.805175] [<c001bba4>] (unwind_backtrace+0x0/0xf4) from
[<c003f9f0>] (warn_slowpath_common+0x4c/0x64)
[ 1.815002] [<c003f9f0>] (warn_slowpath_common+0x4c/0x64) from
[<c003fa9c>] (warn_slowpath_fmt+0x30/0x40)
[ 1.825012] [<c003fa9c>] (warn_slowpath_fmt+0x30/0x40) from
[<c00341ac>] (l3_interrupt_handler+0x17c/0x1b4)
[ 1.835205] [<c00341ac>] (l3_interrupt_handler+0x17c/0x1b4) from
[<c009d88c>] (handle_irq_event_percpu+0x64/0x24c)
[ 1.846008] [<c009d88c>] (handle_irq_event_percpu+0x64/0x24c) from
[<c009dab0>] (handle_irq_event+0x3c/0x5c)
[ 1.856292] [<c009dab0>] (handle_irq_event+0x3c/0x5c) from
[<c00a05f4>] (handle_fasteoi_irq+0x98/0x13c)
[ 1.866088] [<c00a05f4>] (handle_fasteoi_irq+0x98/0x13c) from
[<c009d330>] (generic_handle_irq+0x34/0x44)
[ 1.876098] [<c009d330>] (generic_handle_irq+0x34/0x44) from
[<c00151cc>] (handle_IRQ+0x4c/0xac)
[ 1.885284] [<c00151cc>] (handle_IRQ+0x4c/0xac) from [<c0008480>]
(gic_handle_irq+0x2c/0x60)
[ 1.894073] [<c0008480>] (gic_handle_irq+0x2c/0x60) from
[<c04713a4>] (__irq_svc+0x44/0x60)
[ 1.902801] Exception stack(0xdf831ce8 to 0xdf831d30)
[ 1.908081] 1ce0: c06df3c8 0000000a 00000001
00000000 00000282 00000000
[ 1.916625] 1d00: df830000 c066e080 00000000 c070ffc0 ffff001a
ffff001c df831d10 df831d30
[ 1.925170] 1d20: c0047390 c0047394 60000013 ffffffff
[ 1.930450] [<c04713a4>] (__irq_svc+0x44/0x60) from [<c0047394>]
(__do_softirq+0x64/0x214)
[ 1.939086] [<c0047394>] (__do_softirq+0x64/0x214) from
[<c0047720>] (irq_exit+0x90/0x98)
[ 1.947631] [<c0047720>] (irq_exit+0x90/0x98) from [<c00151d0>]
(handle_IRQ+0x50/0xac)
[ 1.955902] [<c00151d0>] (handle_IRQ+0x50/0xac) from [<c0008480>]
(gic_handle_irq+0x2c/0x60)
[ 1.964691] [<c0008480>] (gic_handle_irq+0x2c/0x60) from
[<c04713a4>] (__irq_svc+0x44/0x60)
[ 1.973419] Exception stack(0xdf831da0 to 0xdf831de8)
[ 1.978668] 1da0: c06df3c8 00000000 df831dd8 00000000 c068ffa0
df831e68 00000001 00000001
[ 1.987213] 1dc0: df831e2f 00000000 ffff001a ffff001c ffffffff
df831de8 c0471138 c047113c
[ 1.995758] 1de0: 60000013 ffffffff
[ 1.999420] [<c04713a4>] (__irq_svc+0x44/0x60) from [<c047113c>]
(_raw_spin_unlock_irq+0x28/0x2c)
[ 2.008697] [<c047113c>] (_raw_spin_unlock_irq+0x28/0x2c) from
[<c001857c>] (die+0xe0/0x324)
[ 2.017486] [<c001857c>] (die+0xe0/0x324) from [<c00187fc>]
(bad_mode+0x3c/0x60)
[ 2.025207] [<c00187fc>] (bad_mode+0x3c/0x60) from [<c0466ffc>]
(omap4_keypad_probe+0x1cc/0x3dc)
[ 2.034393] [<c0466ffc>] (omap4_keypad_probe+0x1cc/0x3dc) from
[<df831e68>] (0xdf831e68)
[ 2.042877] ---[ end trace 2dead3f602d0a977 ]---
[ 2.047760] ---[ end trace 2dead3f602d0a978 ]---
[ 2.052642] Kernel panic - not syncing: Attempted to kill init!
exitcode=0x0000000b
Looking more into this.
~Sourav
> Thanks.
>
> --
> Dmitry
>
>
> Input: omap-keypad - dynamically handle register offsets
>
> From: G, Manjunath Kondaiah <manjugk@ti.com>
>
> Keypad controller register offsets are different for omap4
> and omap5. Handle these offsets through static mapping and
> assign these mappings during run time.
>
> Tested on omap4430 sdp with 3.4-rc3.
> Tested on omap5430evm with 3.1-custom kernel.
>
> Signed-off-by: Felipe Balbi <balbi@ti.com>
> Signed-off-by: G, Manjunath Kondaiah <manjugk@ti.com>
> Signed-off-by: Sourav Poddar <sourav.poddar@ti.com>
> Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
> ---
>
> drivers/input/keyboard/Kconfig | 4 +
> drivers/input/keyboard/omap4-keypad.c | 102 +++++++++++++++++++++++++--------
> 2 files changed, 80 insertions(+), 26 deletions(-)
>
>
> diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
> index 20a3753..84ee155 100644
> --- a/drivers/input/keyboard/Kconfig
> +++ b/drivers/input/keyboard/Kconfig
> @@ -531,9 +531,9 @@ config KEYBOARD_OMAP
> module will be called omap-keypad.
>
> config KEYBOARD_OMAP4
> - tristate "TI OMAP4 keypad support"
> + tristate "TI OMAP4+ keypad support"
> help
> - Say Y here if you want to use the OMAP4 keypad.
> + Say Y here if you want to use the OMAP4+ keypad.
>
> To compile this driver as a module, choose M here: the
> module will be called omap4-keypad.
> diff --git a/drivers/input/keyboard/omap4-keypad.c b/drivers/input/keyboard/omap4-keypad.c
> index e809ac0..ddd5c9e 100644
> --- a/drivers/input/keyboard/omap4-keypad.c
> +++ b/drivers/input/keyboard/omap4-keypad.c
> @@ -68,19 +68,52 @@
>
> #define OMAP4_MASK_IRQSTATUSDISABLE 0xFFFF
>
> +enum {
> + KBD_REVISION_OMAP4 = 0,
> + KBD_REVISION_OMAP5,
> +};
> +
> struct omap4_keypad {
> struct input_dev *input;
>
> void __iomem *base;
> - int irq;
> + unsigned int irq;
>
> unsigned int rows;
> unsigned int cols;
> + u32 reg_offset;
> + u32 irqreg_offset;
> unsigned int row_shift;
> unsigned char key_state[8];
> unsigned short keymap[];
> };
>
> +static int kbd_readl(struct omap4_keypad *keypad_data, u32 offset)
> +{
> + return __raw_readl(keypad_data->base +
> + keypad_data->reg_offset + offset);
> +}
> +
> +static void kbd_writel(struct omap4_keypad *keypad_data, u32 offset, u32 value)
> +{
> + __raw_writel(value,
> + keypad_data->base + keypad_data->reg_offset + offset);
> +}
> +
> +static int kbd_read_irqreg(struct omap4_keypad *keypad_data, u32 offset)
> +{
> + return __raw_readl(keypad_data->base +
> + keypad_data->irqreg_offset + offset);
> +}
> +
> +static void kbd_write_irqreg(struct omap4_keypad *keypad_data,
> + u32 offset, u32 value)
> +{
> + __raw_writel(value,
> + keypad_data->base + keypad_data->irqreg_offset + offset);
> +}
> +
> +
> /* Interrupt handler */
> static irqreturn_t omap4_keypad_interrupt(int irq, void *dev_id)
> {
> @@ -91,12 +124,11 @@ static irqreturn_t omap4_keypad_interrupt(int irq, void *dev_id)
> u32 *new_state = (u32 *) key_state;
>
> /* Disable interrupts */
> - __raw_writel(OMAP4_VAL_IRQDISABLE,
> - keypad_data->base + OMAP4_KBD_IRQENABLE);
> + kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQENABLE,
> + OMAP4_VAL_IRQDISABLE);
>
> - *new_state = __raw_readl(keypad_data->base + OMAP4_KBD_FULLCODE31_0);
> - *(new_state + 1) = __raw_readl(keypad_data->base
> - + OMAP4_KBD_FULLCODE63_32);
> + *new_state = kbd_readl(keypad_data, OMAP4_KBD_FULLCODE31_0);
> + *(new_state + 1) = kbd_readl(keypad_data, OMAP4_KBD_FULLCODE63_32);
>
> for (row = 0; row < keypad_data->rows; row++) {
> changed = key_state[row] ^ keypad_data->key_state[row];
> @@ -121,12 +153,13 @@ static irqreturn_t omap4_keypad_interrupt(int irq, void *dev_id)
> sizeof(keypad_data->key_state));
>
> /* clear pending interrupts */
> - __raw_writel(__raw_readl(keypad_data->base + OMAP4_KBD_IRQSTATUS),
> - keypad_data->base + OMAP4_KBD_IRQSTATUS);
> + kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS,
> + kbd_read_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS));
>
> /* enable interrupts */
> - __raw_writel(OMAP4_DEF_IRQENABLE_EVENTEN | OMAP4_DEF_IRQENABLE_LONGKEY,
> - keypad_data->base + OMAP4_KBD_IRQENABLE);
> + kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQENABLE,
> + OMAP4_DEF_IRQENABLE_EVENTEN |
> + OMAP4_DEF_IRQENABLE_LONGKEY);
>
> return IRQ_HANDLED;
> }
> @@ -139,16 +172,17 @@ static int omap4_keypad_open(struct input_dev *input)
>
> disable_irq(keypad_data->irq);
>
> - __raw_writel(OMAP4_VAL_FUNCTIONALCFG,
> - keypad_data->base + OMAP4_KBD_CTRL);
> - __raw_writel(OMAP4_VAL_DEBOUNCINGTIME,
> - keypad_data->base + OMAP4_KBD_DEBOUNCINGTIME);
> - __raw_writel(OMAP4_VAL_IRQDISABLE,
> - keypad_data->base + OMAP4_KBD_IRQSTATUS);
> - __raw_writel(OMAP4_DEF_IRQENABLE_EVENTEN | OMAP4_DEF_IRQENABLE_LONGKEY,
> - keypad_data->base + OMAP4_KBD_IRQENABLE);
> - __raw_writel(OMAP4_DEF_WUP_EVENT_ENA | OMAP4_DEF_WUP_LONG_KEY_ENA,
> - keypad_data->base + OMAP4_KBD_WAKEUPENABLE);
> + kbd_writel(keypad_data, OMAP4_KBD_CTRL,
> + OMAP4_VAL_FUNCTIONALCFG);
> + kbd_writel(keypad_data, OMAP4_KBD_DEBOUNCINGTIME,
> + OMAP4_VAL_DEBOUNCINGTIME);
> + kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS,
> + OMAP4_VAL_IRQDISABLE);
> + kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQENABLE,
> + OMAP4_DEF_IRQENABLE_EVENTEN |
> + OMAP4_DEF_IRQENABLE_LONGKEY);
> + kbd_writel(keypad_data, OMAP4_KBD_WAKEUPENABLE,
> + OMAP4_DEF_WUP_EVENT_ENA | OMAP4_DEF_WUP_LONG_KEY_ENA);
>
> enable_irq(keypad_data->irq);
>
> @@ -162,12 +196,12 @@ static void omap4_keypad_close(struct input_dev *input)
> disable_irq(keypad_data->irq);
>
> /* Disable interrupts */
> - __raw_writel(OMAP4_VAL_IRQDISABLE,
> - keypad_data->base + OMAP4_KBD_IRQENABLE);
> + kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQENABLE,
> + OMAP4_VAL_IRQDISABLE);
>
> /* clear pending interrupts */
> - __raw_writel(__raw_readl(keypad_data->base + OMAP4_KBD_IRQSTATUS),
> - keypad_data->base + OMAP4_KBD_IRQSTATUS);
> + kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS,
> + kbd_read_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS));
>
> enable_irq(keypad_data->irq);
>
> @@ -182,6 +216,7 @@ static int __devinit omap4_keypad_probe(struct platform_device *pdev)
> struct resource *res;
> resource_size_t size;
> unsigned int row_shift, max_keys;
> + int rev;
> int irq;
> int error;
>
> @@ -241,6 +276,25 @@ static int __devinit omap4_keypad_probe(struct platform_device *pdev)
> keypad_data->rows = pdata->rows;
> keypad_data->cols = pdata->cols;
>
> + rev = __raw_readl(keypad_data->base + OMAP4_KBD_REVISION);
> + rev &= 0x03 << 30;
> + rev >>= 30;
> + switch (rev) {
> + case KBD_REVISION_OMAP4:
> + keypad_data->reg_offset = 0x00;
> + keypad_data->irqreg_offset = 0x00;
> + break;
> + case KBD_REVISION_OMAP5:
> + keypad_data->reg_offset = 0x10;
> + keypad_data->irqreg_offset = 0x0c;
> + break;
> + default:
> + dev_err(&pdev->dev,
> + "Keypad reports unsupported revision %d", rev);
> + error = -EINVAL;
> + goto err_unmap;
> + }
> +
> /* input device allocation */
> keypad_data->input = input_dev = input_allocate_device();
> if (!input_dev) {
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [RESEND/PATCHv2] Input: omap-keypad: dynamically handle register offsets
2012-05-09 6:54 ` Poddar, Sourav
@ 2012-05-09 7:07 ` Poddar, Sourav
2012-05-09 7:45 ` Dmitry Torokhov
1 sibling, 0 replies; 11+ messages in thread
From: Poddar, Sourav @ 2012-05-09 7:07 UTC (permalink / raw)
To: Dmitry Torokhov; +Cc: linux-input, linux-omap, balbi, akpm
On Wed, May 9, 2012 at 12:24 PM, Poddar, Sourav <sourav.poddar@ti.com> wrote:
> Hi Dmitry ,
>
>
> On Wed, May 9, 2012 at 10:48 AM, Dmitry Torokhov
> <dmitry.torokhov@gmail.com> wrote:
>> Ho Sourav,
>>
>> On Thu, Apr 26, 2012 at 11:24:37AM +0530, Sourav Poddar wrote:
>>>
>>> -config KEYBOARD_OMAP4
>>> - tristate "TI OMAP4 keypad support"
>>> +config KEYBOARD_OMAP4+
>>
>> I think this works purely by accident - '+' sign getting dropped by
>> parser...
>>
>>> @@ -139,16 +192,33 @@ static int omap4_keypad_open(struct input_dev *input)
>>>
>>> disable_irq(keypad_data->irq);
>>>
>>> - __raw_writel(OMAP4_VAL_FUNCTIONALCFG,
>>> - keypad_data->base + OMAP4_KBD_CTRL);
>>> - __raw_writel(OMAP4_VAL_DEBOUNCINGTIME,
>>> - keypad_data->base + OMAP4_KBD_DEBOUNCINGTIME);
>>> - __raw_writel(OMAP4_VAL_IRQDISABLE,
>>> - keypad_data->base + OMAP4_KBD_IRQSTATUS);
>>> - __raw_writel(OMAP4_DEF_IRQENABLE_EVENTEN | OMAP4_DEF_IRQENABLE_LONGKEY,
>>> - keypad_data->base + OMAP4_KBD_IRQENABLE);
>>> - __raw_writel(OMAP4_DEF_WUP_EVENT_ENA | OMAP4_DEF_WUP_LONG_KEY_ENA,
>>> - keypad_data->base + OMAP4_KBD_WAKEUPENABLE);
>>> + keypad_data->revision = kbd_read_revision(keypad_data,
>>> + OMAP4_KBD_REVISION);
>>> + switch (keypad_data->revision) {
>>> + case 1:
>>> + keypad_data->irqstatus = OMAP4_KBD_IRQSTATUS + 0x0c;
>>> + keypad_data->irqenable = OMAP4_KBD_IRQENABLE + 0x0c;
>>> + keypad_data->reg_offset = 0x10;
>>> + break;
>>
>> This should be done in probe().
>>
> Dont we then require "pm_runtime_put_sync" in probe, since we are trying
> to read the keypad revision register.?
Sorry for the typo, I meant "pm_runtime_get_sync".
>> Could you please tell me if the version of the patch below works for
>> you?
>>
>
> I just quickly tested this patch and saw the following kernel carsh.
>
> [ 1.571838] Bad mode in data abort handler detected
> [ 1.576934] Internal error: Oops - bad mode: 0 [#1] SMP ARM
> [ 1.582763] Modules linked in:
> [ 1.585937] CPU: 0 Not tainted (3.4.0-rc5-dirty #11)
> [ 1.591522] PC is at __key.13633+0x3f39df40/0x8
> [ 1.596252] LR is at omap4_keypad_probe+0x1cc/0x3dc
> [ 1.601348] pc : [<ffff0018>] lr : [<c0466ffc>] psr: 40000092
> [ 1.601348] sp : df831e68 ip : fc31c000 fp : 00000040
> [ 1.613311] r10: c2460000 r9 : 00000080 r8 : 00000003
> [ 1.618774] r7 : de36e880 r6 : df966008 r5 : df965480 r4 : c2422bc0
> [ 1.625579] r3 : 60000013 r2 : 00000000 r1 : 00000000 r0 : 0000001e
> [ 1.632385] Flags: nZcv IRQs off FIQs on Mode IRQ_32 ISA ARM
> Segment kernel
> [ 1.640106] Control: 10c53c7d Table: 8000404a DAC: 00000017
> [ 1.646118] Process swapper/0 (pid: 1, stack limit = 0xdf8302f8)
> [ 1.652374] Stack: (0xdf831e68 to 0xdf832000)
> [ 1.656921] 1e60: 0000001e 00000000 00000000
> 60000013 c2422bc0 df965480
> [ 1.665466] 1e80: df966008 de36e880 00000003 00000080 c2460000
> 00000040 fc31c000 df831e68
> [ 1.674011] 1ea0: c0466ffc ffff0018 40000092 ffffffff 00000000
> c008b744 df967590 00000098
> [ 1.682556] 1ec0: df96603c df966008 c0c49dd8 df96603c c06f2a00
> 0000008e c06687f0 c0643fcc
> [ 1.691070] 1ee0: 00000000 c02b8748 c02b8730 c02b72c4 df966008
> c06f2a00 df96603c 00000000
> [ 1.699615] 1f00: 0000008e c02b74d8 c06f2a00 df831f18 c02b7444
> c02b5b2c df8402a8 df968e90
> [ 1.708160] 1f20: 00000000 c06f2a00 c06e5e28 de395bc0 00000000
> c02b625c c0575768 c024d028
> [ 1.716705] 1f40: df830000 c06f2a00 00000000 00000000 0000008e
> c06687f0 c0643fcc c02b7ac4
> [ 1.725219] 1f60: df830000 00000007 c06fdc00 00000000 0000008e
> c0008630 00000001 c1058170
> [ 1.733764] 1f80: c05f8500 c0643fcc 00000001 60000013 00000001
> c05716e0 00000006 00000006
> [ 1.742309] 1fa0: 60000013 c064dbb0 00000007 c06fdc00 c061e20c
> 0000008e c06687f0 c064dbb8
> [ 1.750854] 1fc0: 00000000 c061e374 00000006 00000006 c061e20c
> 00000000 00000000 c061e28c
> [ 1.759399] 1fe0: c00152b8 00000013 00000000 00000000 00000000
> c00152b8 ffffffff 00000000
> [ 1.767944] [<c0466ffc>] (omap4_keypad_probe+0x1cc/0x3dc) from
> [<df831e68>] (0xdf831e68)
> [ 1.776397] Code: e59ff410 ea0000bb ea00009a ea0000fa (ea000078)
> [ 1.782775] ------------[ cut here ]------------
> [ 1.787628] WARNING: at arch/arm/mach-omap2/omap_l3_noc.c:113
> l3_interrupt_handler+0x17c/0x1b4()
> [ 1.796783] L3 custom error: MASTER:MPU TARGET:L4CFG
> [ 1.801971] Modules linked in:
> [ 1.805175] [<c001bba4>] (unwind_backtrace+0x0/0xf4) from
> [<c003f9f0>] (warn_slowpath_common+0x4c/0x64)
> [ 1.815002] [<c003f9f0>] (warn_slowpath_common+0x4c/0x64) from
> [<c003fa9c>] (warn_slowpath_fmt+0x30/0x40)
> [ 1.825012] [<c003fa9c>] (warn_slowpath_fmt+0x30/0x40) from
> [<c00341ac>] (l3_interrupt_handler+0x17c/0x1b4)
> [ 1.835205] [<c00341ac>] (l3_interrupt_handler+0x17c/0x1b4) from
> [<c009d88c>] (handle_irq_event_percpu+0x64/0x24c)
> [ 1.846008] [<c009d88c>] (handle_irq_event_percpu+0x64/0x24c) from
> [<c009dab0>] (handle_irq_event+0x3c/0x5c)
> [ 1.856292] [<c009dab0>] (handle_irq_event+0x3c/0x5c) from
> [<c00a05f4>] (handle_fasteoi_irq+0x98/0x13c)
> [ 1.866088] [<c00a05f4>] (handle_fasteoi_irq+0x98/0x13c) from
> [<c009d330>] (generic_handle_irq+0x34/0x44)
> [ 1.876098] [<c009d330>] (generic_handle_irq+0x34/0x44) from
> [<c00151cc>] (handle_IRQ+0x4c/0xac)
> [ 1.885284] [<c00151cc>] (handle_IRQ+0x4c/0xac) from [<c0008480>]
> (gic_handle_irq+0x2c/0x60)
> [ 1.894073] [<c0008480>] (gic_handle_irq+0x2c/0x60) from
> [<c04713a4>] (__irq_svc+0x44/0x60)
> [ 1.902801] Exception stack(0xdf831ce8 to 0xdf831d30)
> [ 1.908081] 1ce0: c06df3c8 0000000a 00000001
> 00000000 00000282 00000000
> [ 1.916625] 1d00: df830000 c066e080 00000000 c070ffc0 ffff001a
> ffff001c df831d10 df831d30
> [ 1.925170] 1d20: c0047390 c0047394 60000013 ffffffff
> [ 1.930450] [<c04713a4>] (__irq_svc+0x44/0x60) from [<c0047394>]
> (__do_softirq+0x64/0x214)
> [ 1.939086] [<c0047394>] (__do_softirq+0x64/0x214) from
> [<c0047720>] (irq_exit+0x90/0x98)
> [ 1.947631] [<c0047720>] (irq_exit+0x90/0x98) from [<c00151d0>]
> (handle_IRQ+0x50/0xac)
> [ 1.955902] [<c00151d0>] (handle_IRQ+0x50/0xac) from [<c0008480>]
> (gic_handle_irq+0x2c/0x60)
> [ 1.964691] [<c0008480>] (gic_handle_irq+0x2c/0x60) from
> [<c04713a4>] (__irq_svc+0x44/0x60)
> [ 1.973419] Exception stack(0xdf831da0 to 0xdf831de8)
> [ 1.978668] 1da0: c06df3c8 00000000 df831dd8 00000000 c068ffa0
> df831e68 00000001 00000001
> [ 1.987213] 1dc0: df831e2f 00000000 ffff001a ffff001c ffffffff
> df831de8 c0471138 c047113c
> [ 1.995758] 1de0: 60000013 ffffffff
> [ 1.999420] [<c04713a4>] (__irq_svc+0x44/0x60) from [<c047113c>]
> (_raw_spin_unlock_irq+0x28/0x2c)
> [ 2.008697] [<c047113c>] (_raw_spin_unlock_irq+0x28/0x2c) from
> [<c001857c>] (die+0xe0/0x324)
> [ 2.017486] [<c001857c>] (die+0xe0/0x324) from [<c00187fc>]
> (bad_mode+0x3c/0x60)
> [ 2.025207] [<c00187fc>] (bad_mode+0x3c/0x60) from [<c0466ffc>]
> (omap4_keypad_probe+0x1cc/0x3dc)
> [ 2.034393] [<c0466ffc>] (omap4_keypad_probe+0x1cc/0x3dc) from
> [<df831e68>] (0xdf831e68)
> [ 2.042877] ---[ end trace 2dead3f602d0a977 ]---
> [ 2.047760] ---[ end trace 2dead3f602d0a978 ]---
> [ 2.052642] Kernel panic - not syncing: Attempted to kill init!
> exitcode=0x0000000b
>
> Looking more into this.
>
>
> ~Sourav
>
>
>
>> Thanks.
>>
>> --
>> Dmitry
>>
>>
>> Input: omap-keypad - dynamically handle register offsets
>>
>> From: G, Manjunath Kondaiah <manjugk@ti.com>
>>
>> Keypad controller register offsets are different for omap4
>> and omap5. Handle these offsets through static mapping and
>> assign these mappings during run time.
>>
>> Tested on omap4430 sdp with 3.4-rc3.
>> Tested on omap5430evm with 3.1-custom kernel.
>>
>> Signed-off-by: Felipe Balbi <balbi@ti.com>
>> Signed-off-by: G, Manjunath Kondaiah <manjugk@ti.com>
>> Signed-off-by: Sourav Poddar <sourav.poddar@ti.com>
>> Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
>> ---
>>
>> drivers/input/keyboard/Kconfig | 4 +
>> drivers/input/keyboard/omap4-keypad.c | 102 +++++++++++++++++++++++++--------
>> 2 files changed, 80 insertions(+), 26 deletions(-)
>>
>>
>> diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
>> index 20a3753..84ee155 100644
>> --- a/drivers/input/keyboard/Kconfig
>> +++ b/drivers/input/keyboard/Kconfig
>> @@ -531,9 +531,9 @@ config KEYBOARD_OMAP
>> module will be called omap-keypad.
>>
>> config KEYBOARD_OMAP4
>> - tristate "TI OMAP4 keypad support"
>> + tristate "TI OMAP4+ keypad support"
>> help
>> - Say Y here if you want to use the OMAP4 keypad.
>> + Say Y here if you want to use the OMAP4+ keypad.
>>
>> To compile this driver as a module, choose M here: the
>> module will be called omap4-keypad.
>> diff --git a/drivers/input/keyboard/omap4-keypad.c b/drivers/input/keyboard/omap4-keypad.c
>> index e809ac0..ddd5c9e 100644
>> --- a/drivers/input/keyboard/omap4-keypad.c
>> +++ b/drivers/input/keyboard/omap4-keypad.c
>> @@ -68,19 +68,52 @@
>>
>> #define OMAP4_MASK_IRQSTATUSDISABLE 0xFFFF
>>
>> +enum {
>> + KBD_REVISION_OMAP4 = 0,
>> + KBD_REVISION_OMAP5,
>> +};
>> +
>> struct omap4_keypad {
>> struct input_dev *input;
>>
>> void __iomem *base;
>> - int irq;
>> + unsigned int irq;
>>
>> unsigned int rows;
>> unsigned int cols;
>> + u32 reg_offset;
>> + u32 irqreg_offset;
>> unsigned int row_shift;
>> unsigned char key_state[8];
>> unsigned short keymap[];
>> };
>>
>> +static int kbd_readl(struct omap4_keypad *keypad_data, u32 offset)
>> +{
>> + return __raw_readl(keypad_data->base +
>> + keypad_data->reg_offset + offset);
>> +}
>> +
>> +static void kbd_writel(struct omap4_keypad *keypad_data, u32 offset, u32 value)
>> +{
>> + __raw_writel(value,
>> + keypad_data->base + keypad_data->reg_offset + offset);
>> +}
>> +
>> +static int kbd_read_irqreg(struct omap4_keypad *keypad_data, u32 offset)
>> +{
>> + return __raw_readl(keypad_data->base +
>> + keypad_data->irqreg_offset + offset);
>> +}
>> +
>> +static void kbd_write_irqreg(struct omap4_keypad *keypad_data,
>> + u32 offset, u32 value)
>> +{
>> + __raw_writel(value,
>> + keypad_data->base + keypad_data->irqreg_offset + offset);
>> +}
>> +
>> +
>> /* Interrupt handler */
>> static irqreturn_t omap4_keypad_interrupt(int irq, void *dev_id)
>> {
>> @@ -91,12 +124,11 @@ static irqreturn_t omap4_keypad_interrupt(int irq, void *dev_id)
>> u32 *new_state = (u32 *) key_state;
>>
>> /* Disable interrupts */
>> - __raw_writel(OMAP4_VAL_IRQDISABLE,
>> - keypad_data->base + OMAP4_KBD_IRQENABLE);
>> + kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQENABLE,
>> + OMAP4_VAL_IRQDISABLE);
>>
>> - *new_state = __raw_readl(keypad_data->base + OMAP4_KBD_FULLCODE31_0);
>> - *(new_state + 1) = __raw_readl(keypad_data->base
>> - + OMAP4_KBD_FULLCODE63_32);
>> + *new_state = kbd_readl(keypad_data, OMAP4_KBD_FULLCODE31_0);
>> + *(new_state + 1) = kbd_readl(keypad_data, OMAP4_KBD_FULLCODE63_32);
>>
>> for (row = 0; row < keypad_data->rows; row++) {
>> changed = key_state[row] ^ keypad_data->key_state[row];
>> @@ -121,12 +153,13 @@ static irqreturn_t omap4_keypad_interrupt(int irq, void *dev_id)
>> sizeof(keypad_data->key_state));
>>
>> /* clear pending interrupts */
>> - __raw_writel(__raw_readl(keypad_data->base + OMAP4_KBD_IRQSTATUS),
>> - keypad_data->base + OMAP4_KBD_IRQSTATUS);
>> + kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS,
>> + kbd_read_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS));
>>
>> /* enable interrupts */
>> - __raw_writel(OMAP4_DEF_IRQENABLE_EVENTEN | OMAP4_DEF_IRQENABLE_LONGKEY,
>> - keypad_data->base + OMAP4_KBD_IRQENABLE);
>> + kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQENABLE,
>> + OMAP4_DEF_IRQENABLE_EVENTEN |
>> + OMAP4_DEF_IRQENABLE_LONGKEY);
>>
>> return IRQ_HANDLED;
>> }
>> @@ -139,16 +172,17 @@ static int omap4_keypad_open(struct input_dev *input)
>>
>> disable_irq(keypad_data->irq);
>>
>> - __raw_writel(OMAP4_VAL_FUNCTIONALCFG,
>> - keypad_data->base + OMAP4_KBD_CTRL);
>> - __raw_writel(OMAP4_VAL_DEBOUNCINGTIME,
>> - keypad_data->base + OMAP4_KBD_DEBOUNCINGTIME);
>> - __raw_writel(OMAP4_VAL_IRQDISABLE,
>> - keypad_data->base + OMAP4_KBD_IRQSTATUS);
>> - __raw_writel(OMAP4_DEF_IRQENABLE_EVENTEN | OMAP4_DEF_IRQENABLE_LONGKEY,
>> - keypad_data->base + OMAP4_KBD_IRQENABLE);
>> - __raw_writel(OMAP4_DEF_WUP_EVENT_ENA | OMAP4_DEF_WUP_LONG_KEY_ENA,
>> - keypad_data->base + OMAP4_KBD_WAKEUPENABLE);
>> + kbd_writel(keypad_data, OMAP4_KBD_CTRL,
>> + OMAP4_VAL_FUNCTIONALCFG);
>> + kbd_writel(keypad_data, OMAP4_KBD_DEBOUNCINGTIME,
>> + OMAP4_VAL_DEBOUNCINGTIME);
>> + kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS,
>> + OMAP4_VAL_IRQDISABLE);
>> + kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQENABLE,
>> + OMAP4_DEF_IRQENABLE_EVENTEN |
>> + OMAP4_DEF_IRQENABLE_LONGKEY);
>> + kbd_writel(keypad_data, OMAP4_KBD_WAKEUPENABLE,
>> + OMAP4_DEF_WUP_EVENT_ENA | OMAP4_DEF_WUP_LONG_KEY_ENA);
>>
>> enable_irq(keypad_data->irq);
>>
>> @@ -162,12 +196,12 @@ static void omap4_keypad_close(struct input_dev *input)
>> disable_irq(keypad_data->irq);
>>
>> /* Disable interrupts */
>> - __raw_writel(OMAP4_VAL_IRQDISABLE,
>> - keypad_data->base + OMAP4_KBD_IRQENABLE);
>> + kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQENABLE,
>> + OMAP4_VAL_IRQDISABLE);
>>
>> /* clear pending interrupts */
>> - __raw_writel(__raw_readl(keypad_data->base + OMAP4_KBD_IRQSTATUS),
>> - keypad_data->base + OMAP4_KBD_IRQSTATUS);
>> + kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS,
>> + kbd_read_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS));
>>
>> enable_irq(keypad_data->irq);
>>
>> @@ -182,6 +216,7 @@ static int __devinit omap4_keypad_probe(struct platform_device *pdev)
>> struct resource *res;
>> resource_size_t size;
>> unsigned int row_shift, max_keys;
>> + int rev;
>> int irq;
>> int error;
>>
>> @@ -241,6 +276,25 @@ static int __devinit omap4_keypad_probe(struct platform_device *pdev)
>> keypad_data->rows = pdata->rows;
>> keypad_data->cols = pdata->cols;
>>
>> + rev = __raw_readl(keypad_data->base + OMAP4_KBD_REVISION);
>> + rev &= 0x03 << 30;
>> + rev >>= 30;
>> + switch (rev) {
>> + case KBD_REVISION_OMAP4:
>> + keypad_data->reg_offset = 0x00;
>> + keypad_data->irqreg_offset = 0x00;
>> + break;
>> + case KBD_REVISION_OMAP5:
>> + keypad_data->reg_offset = 0x10;
>> + keypad_data->irqreg_offset = 0x0c;
>> + break;
>> + default:
>> + dev_err(&pdev->dev,
>> + "Keypad reports unsupported revision %d", rev);
>> + error = -EINVAL;
>> + goto err_unmap;
>> + }
>> +
>> /* input device allocation */
>> keypad_data->input = input_dev = input_allocate_device();
>> if (!input_dev) {
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [RESEND/PATCHv2] Input: omap-keypad: dynamically handle register offsets
2012-05-09 6:54 ` Poddar, Sourav
2012-05-09 7:07 ` Poddar, Sourav
@ 2012-05-09 7:45 ` Dmitry Torokhov
2012-05-09 9:44 ` Poddar, Sourav
1 sibling, 1 reply; 11+ messages in thread
From: Dmitry Torokhov @ 2012-05-09 7:45 UTC (permalink / raw)
To: Poddar, Sourav; +Cc: linux-input, linux-omap, balbi, akpm
> Hi Dmitry ,
>
>
> On Wed, May 9, 2012 at 10:48 AM, Dmitry Torokhov
> <dmitry.torokhov@gmail.com> wrote:
> > Ho Sourav,
> >
> > On Thu, Apr 26, 2012 at 11:24:37AM +0530, Sourav Poddar wrote:
> >>
> >> -config KEYBOARD_OMAP4
> >> - tristate "TI OMAP4 keypad support"
> >> +config KEYBOARD_OMAP4+
> >
> > I think this works purely by accident - '+' sign getting dropped by
> > parser...
> >
> >> @@ -139,16 +192,33 @@ static int omap4_keypad_open(struct input_dev *input)
> >>
> >> disable_irq(keypad_data->irq);
> >>
> >> - __raw_writel(OMAP4_VAL_FUNCTIONALCFG,
> >> - keypad_data->base + OMAP4_KBD_CTRL);
> >> - __raw_writel(OMAP4_VAL_DEBOUNCINGTIME,
> >> - keypad_data->base + OMAP4_KBD_DEBOUNCINGTIME);
> >> - __raw_writel(OMAP4_VAL_IRQDISABLE,
> >> - keypad_data->base + OMAP4_KBD_IRQSTATUS);
> >> - __raw_writel(OMAP4_DEF_IRQENABLE_EVENTEN | OMAP4_DEF_IRQENABLE_LONGKEY,
> >> - keypad_data->base + OMAP4_KBD_IRQENABLE);
> >> - __raw_writel(OMAP4_DEF_WUP_EVENT_ENA | OMAP4_DEF_WUP_LONG_KEY_ENA,
> >> - keypad_data->base + OMAP4_KBD_WAKEUPENABLE);
> >> + keypad_data->revision = kbd_read_revision(keypad_data,
> >> + OMAP4_KBD_REVISION);
> >> + switch (keypad_data->revision) {
> >> + case 1:
> >> + keypad_data->irqstatus = OMAP4_KBD_IRQSTATUS + 0x0c;
> >> + keypad_data->irqenable = OMAP4_KBD_IRQENABLE + 0x0c;
> >> + keypad_data->reg_offset = 0x10;
> >> + break;
> >
> > This should be done in probe().
> >
> Dont we then require "pm_runtime_put_sync" in probe, since we are trying
> to read the keypad revision register.?
Ah, indeed, but I think not pm_runtime_get_sync() but
pm_runtime_set_active().
Not sure if this will fix the crash...
--
Dmitry
Input: omap-keypad - dynamically handle register offsets
From: G, Manjunath Kondaiah <manjugk@ti.com>
Keypad controller register offsets are different for omap4
and omap5. Handle these offsets through static mapping and
assign these mappings during run time.
Tested on omap4430 sdp with 3.4-rc3.
Tested on omap5430evm with 3.1-custom kernel.
Signed-off-by: Felipe Balbi <balbi@ti.com>
Signed-off-by: G, Manjunath Kondaiah <manjugk@ti.com>
Signed-off-by: Sourav Poddar <sourav.poddar@ti.com>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
---
drivers/input/keyboard/Kconfig | 4 +
drivers/input/keyboard/omap4-keypad.c | 117 ++++++++++++++++++++++++++-------
2 files changed, 94 insertions(+), 27 deletions(-)
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
index 20a3753..84ee155 100644
--- a/drivers/input/keyboard/Kconfig
+++ b/drivers/input/keyboard/Kconfig
@@ -531,9 +531,9 @@ config KEYBOARD_OMAP
module will be called omap-keypad.
config KEYBOARD_OMAP4
- tristate "TI OMAP4 keypad support"
+ tristate "TI OMAP4+ keypad support"
help
- Say Y here if you want to use the OMAP4 keypad.
+ Say Y here if you want to use the OMAP4+ keypad.
To compile this driver as a module, choose M here: the
module will be called omap4-keypad.
diff --git a/drivers/input/keyboard/omap4-keypad.c b/drivers/input/keyboard/omap4-keypad.c
index e809ac0..c9fd0df 100644
--- a/drivers/input/keyboard/omap4-keypad.c
+++ b/drivers/input/keyboard/omap4-keypad.c
@@ -68,19 +68,52 @@
#define OMAP4_MASK_IRQSTATUSDISABLE 0xFFFF
+enum {
+ KBD_REVISION_OMAP4 = 0,
+ KBD_REVISION_OMAP5,
+};
+
struct omap4_keypad {
struct input_dev *input;
void __iomem *base;
- int irq;
+ unsigned int irq;
unsigned int rows;
unsigned int cols;
+ u32 reg_offset;
+ u32 irqreg_offset;
unsigned int row_shift;
unsigned char key_state[8];
unsigned short keymap[];
};
+static int kbd_readl(struct omap4_keypad *keypad_data, u32 offset)
+{
+ return __raw_readl(keypad_data->base +
+ keypad_data->reg_offset + offset);
+}
+
+static void kbd_writel(struct omap4_keypad *keypad_data, u32 offset, u32 value)
+{
+ __raw_writel(value,
+ keypad_data->base + keypad_data->reg_offset + offset);
+}
+
+static int kbd_read_irqreg(struct omap4_keypad *keypad_data, u32 offset)
+{
+ return __raw_readl(keypad_data->base +
+ keypad_data->irqreg_offset + offset);
+}
+
+static void kbd_write_irqreg(struct omap4_keypad *keypad_data,
+ u32 offset, u32 value)
+{
+ __raw_writel(value,
+ keypad_data->base + keypad_data->irqreg_offset + offset);
+}
+
+
/* Interrupt handler */
static irqreturn_t omap4_keypad_interrupt(int irq, void *dev_id)
{
@@ -91,12 +124,11 @@ static irqreturn_t omap4_keypad_interrupt(int irq, void *dev_id)
u32 *new_state = (u32 *) key_state;
/* Disable interrupts */
- __raw_writel(OMAP4_VAL_IRQDISABLE,
- keypad_data->base + OMAP4_KBD_IRQENABLE);
+ kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQENABLE,
+ OMAP4_VAL_IRQDISABLE);
- *new_state = __raw_readl(keypad_data->base + OMAP4_KBD_FULLCODE31_0);
- *(new_state + 1) = __raw_readl(keypad_data->base
- + OMAP4_KBD_FULLCODE63_32);
+ *new_state = kbd_readl(keypad_data, OMAP4_KBD_FULLCODE31_0);
+ *(new_state + 1) = kbd_readl(keypad_data, OMAP4_KBD_FULLCODE63_32);
for (row = 0; row < keypad_data->rows; row++) {
changed = key_state[row] ^ keypad_data->key_state[row];
@@ -121,12 +153,13 @@ static irqreturn_t omap4_keypad_interrupt(int irq, void *dev_id)
sizeof(keypad_data->key_state));
/* clear pending interrupts */
- __raw_writel(__raw_readl(keypad_data->base + OMAP4_KBD_IRQSTATUS),
- keypad_data->base + OMAP4_KBD_IRQSTATUS);
+ kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS,
+ kbd_read_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS));
/* enable interrupts */
- __raw_writel(OMAP4_DEF_IRQENABLE_EVENTEN | OMAP4_DEF_IRQENABLE_LONGKEY,
- keypad_data->base + OMAP4_KBD_IRQENABLE);
+ kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQENABLE,
+ OMAP4_DEF_IRQENABLE_EVENTEN |
+ OMAP4_DEF_IRQENABLE_LONGKEY);
return IRQ_HANDLED;
}
@@ -139,16 +172,17 @@ static int omap4_keypad_open(struct input_dev *input)
disable_irq(keypad_data->irq);
- __raw_writel(OMAP4_VAL_FUNCTIONALCFG,
- keypad_data->base + OMAP4_KBD_CTRL);
- __raw_writel(OMAP4_VAL_DEBOUNCINGTIME,
- keypad_data->base + OMAP4_KBD_DEBOUNCINGTIME);
- __raw_writel(OMAP4_VAL_IRQDISABLE,
- keypad_data->base + OMAP4_KBD_IRQSTATUS);
- __raw_writel(OMAP4_DEF_IRQENABLE_EVENTEN | OMAP4_DEF_IRQENABLE_LONGKEY,
- keypad_data->base + OMAP4_KBD_IRQENABLE);
- __raw_writel(OMAP4_DEF_WUP_EVENT_ENA | OMAP4_DEF_WUP_LONG_KEY_ENA,
- keypad_data->base + OMAP4_KBD_WAKEUPENABLE);
+ kbd_writel(keypad_data, OMAP4_KBD_CTRL,
+ OMAP4_VAL_FUNCTIONALCFG);
+ kbd_writel(keypad_data, OMAP4_KBD_DEBOUNCINGTIME,
+ OMAP4_VAL_DEBOUNCINGTIME);
+ kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS,
+ OMAP4_VAL_IRQDISABLE);
+ kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQENABLE,
+ OMAP4_DEF_IRQENABLE_EVENTEN |
+ OMAP4_DEF_IRQENABLE_LONGKEY);
+ kbd_writel(keypad_data, OMAP4_KBD_WAKEUPENABLE,
+ OMAP4_DEF_WUP_EVENT_ENA | OMAP4_DEF_WUP_LONG_KEY_ENA);
enable_irq(keypad_data->irq);
@@ -162,12 +196,12 @@ static void omap4_keypad_close(struct input_dev *input)
disable_irq(keypad_data->irq);
/* Disable interrupts */
- __raw_writel(OMAP4_VAL_IRQDISABLE,
- keypad_data->base + OMAP4_KBD_IRQENABLE);
+ kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQENABLE,
+ OMAP4_VAL_IRQDISABLE);
/* clear pending interrupts */
- __raw_writel(__raw_readl(keypad_data->base + OMAP4_KBD_IRQSTATUS),
- keypad_data->base + OMAP4_KBD_IRQSTATUS);
+ kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS,
+ kbd_read_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS));
enable_irq(keypad_data->irq);
@@ -182,6 +216,7 @@ static int __devinit omap4_keypad_probe(struct platform_device *pdev)
struct resource *res;
resource_size_t size;
unsigned int row_shift, max_keys;
+ int rev;
int irq;
int error;
@@ -241,11 +276,40 @@ static int __devinit omap4_keypad_probe(struct platform_device *pdev)
keypad_data->rows = pdata->rows;
keypad_data->cols = pdata->cols;
+ /*
+ * Mark device as active (and wake up its parent) so we can read
+ * revision register.
+ */
+ error = pm_runtime_set_active(&pdev->dev);
+ if (error) {
+ dev_err(&pdev->dev, "pm_runtime_set_active() failed\n");
+ goto err_unmap;
+ }
+
+ rev = __raw_readl(keypad_data->base + OMAP4_KBD_REVISION);
+ rev &= 0x03 << 30;
+ rev >>= 30;
+ switch (rev) {
+ case KBD_REVISION_OMAP4:
+ keypad_data->reg_offset = 0x00;
+ keypad_data->irqreg_offset = 0x00;
+ break;
+ case KBD_REVISION_OMAP5:
+ keypad_data->reg_offset = 0x10;
+ keypad_data->irqreg_offset = 0x0c;
+ break;
+ default:
+ dev_err(&pdev->dev,
+ "Keypad reports unsupported revision %d", rev);
+ error = -EINVAL;
+ goto err_pm_suspended;
+ }
+
/* input device allocation */
keypad_data->input = input_dev = input_allocate_device();
if (!input_dev) {
error = -ENOMEM;
- goto err_unmap;
+ goto err_pm_suspended;
}
input_dev->name = pdev->name;
@@ -281,6 +345,7 @@ static int __devinit omap4_keypad_probe(struct platform_device *pdev)
}
pm_runtime_enable(&pdev->dev);
+ pm_runtime_put_sync(&pdev->dev);
error = input_register_device(keypad_data->input);
if (error < 0) {
@@ -296,6 +361,8 @@ err_pm_disable:
free_irq(keypad_data->irq, keypad_data);
err_free_input:
input_free_device(input_dev);
+err_pm_suspended:
+ pm_runtime_set_suspended(&pdev->dev);
err_unmap:
iounmap(keypad_data->base);
err_release_mem:
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [RESEND/PATCHv2] Input: omap-keypad: dynamically handle register offsets
2012-05-09 7:45 ` Dmitry Torokhov
@ 2012-05-09 9:44 ` Poddar, Sourav
2012-05-09 10:07 ` Poddar, Sourav
0 siblings, 1 reply; 11+ messages in thread
From: Poddar, Sourav @ 2012-05-09 9:44 UTC (permalink / raw)
To: Dmitry Torokhov; +Cc: linux-input, linux-omap, balbi, akpm
[-- Attachment #1: Type: text/plain, Size: 20224 bytes --]
Hi Dmitry,
I did some minor fixes to the patch which you suggested above and
the keypad is functional now.
Changes:
- Move "pm_runtime_enable" before using "pm_runtime_get_sync".
Sending the patch inlined..(also attached).
From: G, Manjunath Kondaiah <manjugk@ti.com>
Date: Mon, 10 Oct 2011 20:52:05 +0530
Subject: [PATCH] Input: omap-keypad: dynamically handle register offsets
Keypad controller register offsets are different for omap4
and omap5. Handle these offsets through static mapping and
assign these mappings during run time.
Tested on omap4430 sdp with 3.4-rc3.
Tested on omap5430evm with 3.1-custom kernel.
Cc: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Felipe Balbi <balbi@ti.com>
Signed-off-by: G, Manjunath Kondaiah <manjugk@ti.com>
Signed-off-by: Sourav Poddar <sourav.poddar@ti.com>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
---
drivers/input/keyboard/Kconfig | 4 +-
drivers/input/keyboard/omap4-keypad.c | 120 +++++++++++++++++++++++++-------
2 files changed, 95 insertions(+), 29 deletions(-)
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
index f354813..33bbdee 100644
--- a/drivers/input/keyboard/Kconfig
+++ b/drivers/input/keyboard/Kconfig
@@ -512,9 +512,9 @@ config KEYBOARD_OMAP
module will be called omap-keypad.
config KEYBOARD_OMAP4
- tristate "TI OMAP4 keypad support"
+ tristate "TI OMAP4+ keypad support"
help
- Say Y here if you want to use the OMAP4 keypad.
+ Say Y here if you want to use the OMAP4+ keypad.
To compile this driver as a module, choose M here: the
module will be called omap4-keypad.
diff --git a/drivers/input/keyboard/omap4-keypad.c
b/drivers/input/keyboard/omap4-keypad.c
index e809ac0..d7102e8 100644
--- a/drivers/input/keyboard/omap4-keypad.c
+++ b/drivers/input/keyboard/omap4-keypad.c
@@ -68,19 +68,52 @@
#define OMAP4_MASK_IRQSTATUSDISABLE 0xFFFF
+enum {
+ KBD_REVISION_OMAP4 = 0,
+ KBD_REVISION_OMAP5,
+};
+
struct omap4_keypad {
struct input_dev *input;
void __iomem *base;
- int irq;
+ unsigned int irq;
unsigned int rows;
unsigned int cols;
+ u32 reg_offset;
+ u32 irqreg_offset;
unsigned int row_shift;
unsigned char key_state[8];
unsigned short keymap[];
};
+static int kbd_readl(struct omap4_keypad *keypad_data, u32 offset)
+{
+ return __raw_readl(keypad_data->base +
+ keypad_data->reg_offset + offset);
+}
+
+static void kbd_writel(struct omap4_keypad *keypad_data, u32 offset, u32 value)
+{
+ __raw_writel(value,
+ keypad_data->base + keypad_data->reg_offset + offset);
+}
+
+static int kbd_read_irqreg(struct omap4_keypad *keypad_data, u32 offset)
+{
+ return __raw_readl(keypad_data->base +
+ keypad_data->irqreg_offset + offset);
+}
+
+static void kbd_write_irqreg(struct omap4_keypad *keypad_data,
+ u32 offset, u32 value)
+{
+ __raw_writel(value,
+ keypad_data->base + keypad_data->irqreg_offset + offset);
+}
+
+
/* Interrupt handler */
static irqreturn_t omap4_keypad_interrupt(int irq, void *dev_id)
{
@@ -91,12 +124,11 @@ static irqreturn_t omap4_keypad_interrupt(int
irq, void *dev_id)
u32 *new_state = (u32 *) key_state;
/* Disable interrupts */
- __raw_writel(OMAP4_VAL_IRQDISABLE,
- keypad_data->base + OMAP4_KBD_IRQENABLE);
+ kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQENABLE,
+ OMAP4_VAL_IRQDISABLE);
- *new_state = __raw_readl(keypad_data->base + OMAP4_KBD_FULLCODE31_0);
- *(new_state + 1) = __raw_readl(keypad_data->base
- + OMAP4_KBD_FULLCODE63_32);
+ *new_state = kbd_readl(keypad_data, OMAP4_KBD_FULLCODE31_0);
+ *(new_state + 1) = kbd_readl(keypad_data, OMAP4_KBD_FULLCODE63_32);
for (row = 0; row < keypad_data->rows; row++) {
changed = key_state[row] ^ keypad_data->key_state[row];
@@ -121,12 +153,13 @@ static irqreturn_t omap4_keypad_interrupt(int
irq, void *dev_id)
sizeof(keypad_data->key_state));
/* clear pending interrupts */
- __raw_writel(__raw_readl(keypad_data->base + OMAP4_KBD_IRQSTATUS),
- keypad_data->base + OMAP4_KBD_IRQSTATUS);
+ kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS,
+ kbd_read_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS));
/* enable interrupts */
- __raw_writel(OMAP4_DEF_IRQENABLE_EVENTEN | OMAP4_DEF_IRQENABLE_LONGKEY,
- keypad_data->base + OMAP4_KBD_IRQENABLE);
+ kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQENABLE,
+ OMAP4_DEF_IRQENABLE_EVENTEN |
+ OMAP4_DEF_IRQENABLE_LONGKEY);
return IRQ_HANDLED;
}
@@ -139,16 +172,17 @@ static int omap4_keypad_open(struct input_dev *input)
disable_irq(keypad_data->irq);
- __raw_writel(OMAP4_VAL_FUNCTIONALCFG,
- keypad_data->base + OMAP4_KBD_CTRL);
- __raw_writel(OMAP4_VAL_DEBOUNCINGTIME,
- keypad_data->base + OMAP4_KBD_DEBOUNCINGTIME);
- __raw_writel(OMAP4_VAL_IRQDISABLE,
- keypad_data->base + OMAP4_KBD_IRQSTATUS);
- __raw_writel(OMAP4_DEF_IRQENABLE_EVENTEN | OMAP4_DEF_IRQENABLE_LONGKEY,
- keypad_data->base + OMAP4_KBD_IRQENABLE);
- __raw_writel(OMAP4_DEF_WUP_EVENT_ENA | OMAP4_DEF_WUP_LONG_KEY_ENA,
- keypad_data->base + OMAP4_KBD_WAKEUPENABLE);
+ kbd_writel(keypad_data, OMAP4_KBD_CTRL,
+ OMAP4_VAL_FUNCTIONALCFG);
+ kbd_writel(keypad_data, OMAP4_KBD_DEBOUNCINGTIME,
+ OMAP4_VAL_DEBOUNCINGTIME);
+ kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS,
+ OMAP4_VAL_IRQDISABLE);
+ kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQENABLE,
+ OMAP4_DEF_IRQENABLE_EVENTEN |
+ OMAP4_DEF_IRQENABLE_LONGKEY);
+ kbd_writel(keypad_data, OMAP4_KBD_WAKEUPENABLE,
+ OMAP4_DEF_WUP_EVENT_ENA | OMAP4_DEF_WUP_LONG_KEY_ENA);
enable_irq(keypad_data->irq);
@@ -162,12 +196,12 @@ static void omap4_keypad_close(struct input_dev *input)
disable_irq(keypad_data->irq);
/* Disable interrupts */
- __raw_writel(OMAP4_VAL_IRQDISABLE,
- keypad_data->base + OMAP4_KBD_IRQENABLE);
+ kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQENABLE,
+ OMAP4_VAL_IRQDISABLE);
/* clear pending interrupts */
- __raw_writel(__raw_readl(keypad_data->base + OMAP4_KBD_IRQSTATUS),
- keypad_data->base + OMAP4_KBD_IRQSTATUS);
+ kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS,
+ kbd_read_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS));
enable_irq(keypad_data->irq);
@@ -182,6 +216,7 @@ static int __devinit omap4_keypad_probe(struct
platform_device *pdev)
struct resource *res;
resource_size_t size;
unsigned int row_shift, max_keys;
+ int rev;
int irq;
int error;
@@ -241,11 +276,40 @@ static int __devinit omap4_keypad_probe(struct
platform_device *pdev)
keypad_data->rows = pdata->rows;
keypad_data->cols = pdata->cols;
+ /*
+ * Enable clocks for the keypad module so that we can read
+ * revision register.
+ */
+ pm_runtime_enable(&pdev->dev);
+ error = pm_runtime_get_sync(&pdev->dev);
+ if (error) {
+ dev_err(&pdev->dev, "pm_runtime_get_sync() failed\n");
+ goto err_unmap;
+ }
+ rev = __raw_readl(keypad_data->base + OMAP4_KBD_REVISION);
+ rev &= 0x03 << 30;
+ rev >>= 30;
+ switch (rev) {
+ case KBD_REVISION_OMAP4:
+ keypad_data->reg_offset = 0x00;
+ keypad_data->irqreg_offset = 0x00;
+ break;
+ case KBD_REVISION_OMAP5:
+ keypad_data->reg_offset = 0x10;
+ keypad_data->irqreg_offset = 0x0c;
+ break;
+ default:
+ dev_err(&pdev->dev,
+ "Keypad reports unsupported revision %d", rev);
+ error = -EINVAL;
+ goto err_pm_put_sync;
+ }
+
/* input device allocation */
keypad_data->input = input_dev = input_allocate_device();
if (!input_dev) {
error = -ENOMEM;
- goto err_unmap;
+ goto err_pm_put_sync;
}
input_dev->name = pdev->name;
@@ -273,14 +337,14 @@ static int __devinit omap4_keypad_probe(struct
platform_device *pdev)
input_dev->keycode, input_dev->keybit);
error = request_irq(keypad_data->irq, omap4_keypad_interrupt,
- IRQF_TRIGGER_RISING,
+ IRQF_DISABLED | IRQF_TRIGGER_RISING,
"omap4-keypad", keypad_data);
if (error) {
dev_err(&pdev->dev, "failed to register interrupt\n");
goto err_free_input;
}
- pm_runtime_enable(&pdev->dev);
+ pm_runtime_put_sync(&pdev->dev);
error = input_register_device(keypad_data->input);
if (error < 0) {
@@ -296,6 +360,8 @@ err_pm_disable:
free_irq(keypad_data->irq, keypad_data);
err_free_input:
input_free_device(input_dev);
+err_pm_put_sync:
+ pm_runtime_put_sync(&pdev->dev);
err_unmap:
iounmap(keypad_data->base);
err_release_mem:
~Sourav
On Wed, May 9, 2012 at 1:15 PM, Dmitry Torokhov
<dmitry.torokhov@gmail.com> wrote:
>> Hi Dmitry ,
>>
>>
>> On Wed, May 9, 2012 at 10:48 AM, Dmitry Torokhov
>> <dmitry.torokhov@gmail.com> wrote:
>> > Ho Sourav,
>> >
>> > On Thu, Apr 26, 2012 at 11:24:37AM +0530, Sourav Poddar wrote:
>> >>
>> >> -config KEYBOARD_OMAP4
>> >> - tristate "TI OMAP4 keypad support"
>> >> +config KEYBOARD_OMAP4+
>> >
>> > I think this works purely by accident - '+' sign getting dropped by
>> > parser...
>> >
>> >> @@ -139,16 +192,33 @@ static int omap4_keypad_open(struct input_dev *input)
>> >>
>> >> disable_irq(keypad_data->irq);
>> >>
>> >> - __raw_writel(OMAP4_VAL_FUNCTIONALCFG,
>> >> - keypad_data->base + OMAP4_KBD_CTRL);
>> >> - __raw_writel(OMAP4_VAL_DEBOUNCINGTIME,
>> >> - keypad_data->base + OMAP4_KBD_DEBOUNCINGTIME);
>> >> - __raw_writel(OMAP4_VAL_IRQDISABLE,
>> >> - keypad_data->base + OMAP4_KBD_IRQSTATUS);
>> >> - __raw_writel(OMAP4_DEF_IRQENABLE_EVENTEN | OMAP4_DEF_IRQENABLE_LONGKEY,
>> >> - keypad_data->base + OMAP4_KBD_IRQENABLE);
>> >> - __raw_writel(OMAP4_DEF_WUP_EVENT_ENA | OMAP4_DEF_WUP_LONG_KEY_ENA,
>> >> - keypad_data->base + OMAP4_KBD_WAKEUPENABLE);
>> >> + keypad_data->revision = kbd_read_revision(keypad_data,
>> >> + OMAP4_KBD_REVISION);
>> >> + switch (keypad_data->revision) {
>> >> + case 1:
>> >> + keypad_data->irqstatus = OMAP4_KBD_IRQSTATUS + 0x0c;
>> >> + keypad_data->irqenable = OMAP4_KBD_IRQENABLE + 0x0c;
>> >> + keypad_data->reg_offset = 0x10;
>> >> + break;
>> >
>> > This should be done in probe().
>> >
>> Dont we then require "pm_runtime_put_sync" in probe, since we are trying
>> to read the keypad revision register.?
>
> Ah, indeed, but I think not pm_runtime_get_sync() but
> pm_runtime_set_active().
>
> Not sure if this will fix the crash...
>
> --
> Dmitry
>
>
> Input: omap-keypad - dynamically handle register offsets
>
> From: G, Manjunath Kondaiah <manjugk@ti.com>
>
> Keypad controller register offsets are different for omap4
> and omap5. Handle these offsets through static mapping and
> assign these mappings during run time.
>
> Tested on omap4430 sdp with 3.4-rc3.
> Tested on omap5430evm with 3.1-custom kernel.
>
> Signed-off-by: Felipe Balbi <balbi@ti.com>
> Signed-off-by: G, Manjunath Kondaiah <manjugk@ti.com>
> Signed-off-by: Sourav Poddar <sourav.poddar@ti.com>
> Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
> ---
>
> drivers/input/keyboard/Kconfig | 4 +
> drivers/input/keyboard/omap4-keypad.c | 117 ++++++++++++++++++++++++++-------
> 2 files changed, 94 insertions(+), 27 deletions(-)
>
>
> diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
> index 20a3753..84ee155 100644
> --- a/drivers/input/keyboard/Kconfig
> +++ b/drivers/input/keyboard/Kconfig
> @@ -531,9 +531,9 @@ config KEYBOARD_OMAP
> module will be called omap-keypad.
>
> config KEYBOARD_OMAP4
> - tristate "TI OMAP4 keypad support"
> + tristate "TI OMAP4+ keypad support"
> help
> - Say Y here if you want to use the OMAP4 keypad.
> + Say Y here if you want to use the OMAP4+ keypad.
>
> To compile this driver as a module, choose M here: the
> module will be called omap4-keypad.
> diff --git a/drivers/input/keyboard/omap4-keypad.c b/drivers/input/keyboard/omap4-keypad.c
> index e809ac0..c9fd0df 100644
> --- a/drivers/input/keyboard/omap4-keypad.c
> +++ b/drivers/input/keyboard/omap4-keypad.c
> @@ -68,19 +68,52 @@
>
> #define OMAP4_MASK_IRQSTATUSDISABLE 0xFFFF
>
> +enum {
> + KBD_REVISION_OMAP4 = 0,
> + KBD_REVISION_OMAP5,
> +};
> +
> struct omap4_keypad {
> struct input_dev *input;
>
> void __iomem *base;
> - int irq;
> + unsigned int irq;
>
> unsigned int rows;
> unsigned int cols;
> + u32 reg_offset;
> + u32 irqreg_offset;
> unsigned int row_shift;
> unsigned char key_state[8];
> unsigned short keymap[];
> };
>
> +static int kbd_readl(struct omap4_keypad *keypad_data, u32 offset)
> +{
> + return __raw_readl(keypad_data->base +
> + keypad_data->reg_offset + offset);
> +}
> +
> +static void kbd_writel(struct omap4_keypad *keypad_data, u32 offset, u32 value)
> +{
> + __raw_writel(value,
> + keypad_data->base + keypad_data->reg_offset + offset);
> +}
> +
> +static int kbd_read_irqreg(struct omap4_keypad *keypad_data, u32 offset)
> +{
> + return __raw_readl(keypad_data->base +
> + keypad_data->irqreg_offset + offset);
> +}
> +
> +static void kbd_write_irqreg(struct omap4_keypad *keypad_data,
> + u32 offset, u32 value)
> +{
> + __raw_writel(value,
> + keypad_data->base + keypad_data->irqreg_offset + offset);
> +}
> +
> +
> /* Interrupt handler */
> static irqreturn_t omap4_keypad_interrupt(int irq, void *dev_id)
> {
> @@ -91,12 +124,11 @@ static irqreturn_t omap4_keypad_interrupt(int irq, void *dev_id)
> u32 *new_state = (u32 *) key_state;
>
> /* Disable interrupts */
> - __raw_writel(OMAP4_VAL_IRQDISABLE,
> - keypad_data->base + OMAP4_KBD_IRQENABLE);
> + kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQENABLE,
> + OMAP4_VAL_IRQDISABLE);
>
> - *new_state = __raw_readl(keypad_data->base + OMAP4_KBD_FULLCODE31_0);
> - *(new_state + 1) = __raw_readl(keypad_data->base
> - + OMAP4_KBD_FULLCODE63_32);
> + *new_state = kbd_readl(keypad_data, OMAP4_KBD_FULLCODE31_0);
> + *(new_state + 1) = kbd_readl(keypad_data, OMAP4_KBD_FULLCODE63_32);
>
> for (row = 0; row < keypad_data->rows; row++) {
> changed = key_state[row] ^ keypad_data->key_state[row];
> @@ -121,12 +153,13 @@ static irqreturn_t omap4_keypad_interrupt(int irq, void *dev_id)
> sizeof(keypad_data->key_state));
>
> /* clear pending interrupts */
> - __raw_writel(__raw_readl(keypad_data->base + OMAP4_KBD_IRQSTATUS),
> - keypad_data->base + OMAP4_KBD_IRQSTATUS);
> + kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS,
> + kbd_read_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS));
>
> /* enable interrupts */
> - __raw_writel(OMAP4_DEF_IRQENABLE_EVENTEN | OMAP4_DEF_IRQENABLE_LONGKEY,
> - keypad_data->base + OMAP4_KBD_IRQENABLE);
> + kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQENABLE,
> + OMAP4_DEF_IRQENABLE_EVENTEN |
> + OMAP4_DEF_IRQENABLE_LONGKEY);
>
> return IRQ_HANDLED;
> }
> @@ -139,16 +172,17 @@ static int omap4_keypad_open(struct input_dev *input)
>
> disable_irq(keypad_data->irq);
>
> - __raw_writel(OMAP4_VAL_FUNCTIONALCFG,
> - keypad_data->base + OMAP4_KBD_CTRL);
> - __raw_writel(OMAP4_VAL_DEBOUNCINGTIME,
> - keypad_data->base + OMAP4_KBD_DEBOUNCINGTIME);
> - __raw_writel(OMAP4_VAL_IRQDISABLE,
> - keypad_data->base + OMAP4_KBD_IRQSTATUS);
> - __raw_writel(OMAP4_DEF_IRQENABLE_EVENTEN | OMAP4_DEF_IRQENABLE_LONGKEY,
> - keypad_data->base + OMAP4_KBD_IRQENABLE);
> - __raw_writel(OMAP4_DEF_WUP_EVENT_ENA | OMAP4_DEF_WUP_LONG_KEY_ENA,
> - keypad_data->base + OMAP4_KBD_WAKEUPENABLE);
> + kbd_writel(keypad_data, OMAP4_KBD_CTRL,
> + OMAP4_VAL_FUNCTIONALCFG);
> + kbd_writel(keypad_data, OMAP4_KBD_DEBOUNCINGTIME,
> + OMAP4_VAL_DEBOUNCINGTIME);
> + kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS,
> + OMAP4_VAL_IRQDISABLE);
> + kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQENABLE,
> + OMAP4_DEF_IRQENABLE_EVENTEN |
> + OMAP4_DEF_IRQENABLE_LONGKEY);
> + kbd_writel(keypad_data, OMAP4_KBD_WAKEUPENABLE,
> + OMAP4_DEF_WUP_EVENT_ENA | OMAP4_DEF_WUP_LONG_KEY_ENA);
>
> enable_irq(keypad_data->irq);
>
> @@ -162,12 +196,12 @@ static void omap4_keypad_close(struct input_dev *input)
> disable_irq(keypad_data->irq);
>
> /* Disable interrupts */
> - __raw_writel(OMAP4_VAL_IRQDISABLE,
> - keypad_data->base + OMAP4_KBD_IRQENABLE);
> + kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQENABLE,
> + OMAP4_VAL_IRQDISABLE);
>
> /* clear pending interrupts */
> - __raw_writel(__raw_readl(keypad_data->base + OMAP4_KBD_IRQSTATUS),
> - keypad_data->base + OMAP4_KBD_IRQSTATUS);
> + kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS,
> + kbd_read_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS));
>
> enable_irq(keypad_data->irq);
>
> @@ -182,6 +216,7 @@ static int __devinit omap4_keypad_probe(struct platform_device *pdev)
> struct resource *res;
> resource_size_t size;
> unsigned int row_shift, max_keys;
> + int rev;
> int irq;
> int error;
>
> @@ -241,11 +276,40 @@ static int __devinit omap4_keypad_probe(struct platform_device *pdev)
> keypad_data->rows = pdata->rows;
> keypad_data->cols = pdata->cols;
>
> + /*
> + * Mark device as active (and wake up its parent) so we can read
> + * revision register.
> + */
> + error = pm_runtime_set_active(&pdev->dev);
> + if (error) {
> + dev_err(&pdev->dev, "pm_runtime_set_active() failed\n");
> + goto err_unmap;
> + }
> +
> + rev = __raw_readl(keypad_data->base + OMAP4_KBD_REVISION);
> + rev &= 0x03 << 30;
> + rev >>= 30;
> + switch (rev) {
> + case KBD_REVISION_OMAP4:
> + keypad_data->reg_offset = 0x00;
> + keypad_data->irqreg_offset = 0x00;
> + break;
> + case KBD_REVISION_OMAP5:
> + keypad_data->reg_offset = 0x10;
> + keypad_data->irqreg_offset = 0x0c;
> + break;
> + default:
> + dev_err(&pdev->dev,
> + "Keypad reports unsupported revision %d", rev);
> + error = -EINVAL;
> + goto err_pm_suspended;
> + }
> +
> /* input device allocation */
> keypad_data->input = input_dev = input_allocate_device();
> if (!input_dev) {
> error = -ENOMEM;
> - goto err_unmap;
> + goto err_pm_suspended;
> }
>
> input_dev->name = pdev->name;
> @@ -281,6 +345,7 @@ static int __devinit omap4_keypad_probe(struct platform_device *pdev)
> }
>
> pm_runtime_enable(&pdev->dev);
> + pm_runtime_put_sync(&pdev->dev);
>
> error = input_register_device(keypad_data->input);
> if (error < 0) {
> @@ -296,6 +361,8 @@ err_pm_disable:
> free_irq(keypad_data->irq, keypad_data);
> err_free_input:
> input_free_device(input_dev);
> +err_pm_suspended:
> + pm_runtime_set_suspended(&pdev->dev);
> err_unmap:
> iounmap(keypad_data->base);
> err_release_mem:
[-- Attachment #2: 0001-Input-omap-keypad-dynamically-handle-register-offset.patch --]
[-- Type: text/x-diff, Size: 8125 bytes --]
From ec4ebfe4f0a11182a578369421b57adcb4c3a79d Mon Sep 17 00:00:00 2001
From: G, Manjunath Kondaiah <manjugk@ti.com>
Date: Mon, 10 Oct 2011 20:52:05 +0530
Subject: [PATCH] Input: omap-keypad: dynamically handle register offsets
Keypad controller register offsets are different for omap4
and omap5. Handle these offsets through static mapping and
assign these mappings during run time.
Tested on omap4430 sdp with 3.4-rc3.
Tested on omap5430evm with 3.1-custom kernel.
Cc: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Felipe Balbi <balbi@ti.com>
Signed-off-by: G, Manjunath Kondaiah <manjugk@ti.com>
Signed-off-by: Sourav Poddar <sourav.poddar@ti.com>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
---
drivers/input/keyboard/Kconfig | 4 +-
drivers/input/keyboard/omap4-keypad.c | 120 +++++++++++++++++++++++++-------
2 files changed, 95 insertions(+), 29 deletions(-)
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
index f354813..33bbdee 100644
--- a/drivers/input/keyboard/Kconfig
+++ b/drivers/input/keyboard/Kconfig
@@ -512,9 +512,9 @@ config KEYBOARD_OMAP
module will be called omap-keypad.
config KEYBOARD_OMAP4
- tristate "TI OMAP4 keypad support"
+ tristate "TI OMAP4+ keypad support"
help
- Say Y here if you want to use the OMAP4 keypad.
+ Say Y here if you want to use the OMAP4+ keypad.
To compile this driver as a module, choose M here: the
module will be called omap4-keypad.
diff --git a/drivers/input/keyboard/omap4-keypad.c b/drivers/input/keyboard/omap4-keypad.c
index e809ac0..d7102e8 100644
--- a/drivers/input/keyboard/omap4-keypad.c
+++ b/drivers/input/keyboard/omap4-keypad.c
@@ -68,19 +68,52 @@
#define OMAP4_MASK_IRQSTATUSDISABLE 0xFFFF
+enum {
+ KBD_REVISION_OMAP4 = 0,
+ KBD_REVISION_OMAP5,
+};
+
struct omap4_keypad {
struct input_dev *input;
void __iomem *base;
- int irq;
+ unsigned int irq;
unsigned int rows;
unsigned int cols;
+ u32 reg_offset;
+ u32 irqreg_offset;
unsigned int row_shift;
unsigned char key_state[8];
unsigned short keymap[];
};
+static int kbd_readl(struct omap4_keypad *keypad_data, u32 offset)
+{
+ return __raw_readl(keypad_data->base +
+ keypad_data->reg_offset + offset);
+}
+
+static void kbd_writel(struct omap4_keypad *keypad_data, u32 offset, u32 value)
+{
+ __raw_writel(value,
+ keypad_data->base + keypad_data->reg_offset + offset);
+}
+
+static int kbd_read_irqreg(struct omap4_keypad *keypad_data, u32 offset)
+{
+ return __raw_readl(keypad_data->base +
+ keypad_data->irqreg_offset + offset);
+}
+
+static void kbd_write_irqreg(struct omap4_keypad *keypad_data,
+ u32 offset, u32 value)
+{
+ __raw_writel(value,
+ keypad_data->base + keypad_data->irqreg_offset + offset);
+}
+
+
/* Interrupt handler */
static irqreturn_t omap4_keypad_interrupt(int irq, void *dev_id)
{
@@ -91,12 +124,11 @@ static irqreturn_t omap4_keypad_interrupt(int irq, void *dev_id)
u32 *new_state = (u32 *) key_state;
/* Disable interrupts */
- __raw_writel(OMAP4_VAL_IRQDISABLE,
- keypad_data->base + OMAP4_KBD_IRQENABLE);
+ kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQENABLE,
+ OMAP4_VAL_IRQDISABLE);
- *new_state = __raw_readl(keypad_data->base + OMAP4_KBD_FULLCODE31_0);
- *(new_state + 1) = __raw_readl(keypad_data->base
- + OMAP4_KBD_FULLCODE63_32);
+ *new_state = kbd_readl(keypad_data, OMAP4_KBD_FULLCODE31_0);
+ *(new_state + 1) = kbd_readl(keypad_data, OMAP4_KBD_FULLCODE63_32);
for (row = 0; row < keypad_data->rows; row++) {
changed = key_state[row] ^ keypad_data->key_state[row];
@@ -121,12 +153,13 @@ static irqreturn_t omap4_keypad_interrupt(int irq, void *dev_id)
sizeof(keypad_data->key_state));
/* clear pending interrupts */
- __raw_writel(__raw_readl(keypad_data->base + OMAP4_KBD_IRQSTATUS),
- keypad_data->base + OMAP4_KBD_IRQSTATUS);
+ kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS,
+ kbd_read_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS));
/* enable interrupts */
- __raw_writel(OMAP4_DEF_IRQENABLE_EVENTEN | OMAP4_DEF_IRQENABLE_LONGKEY,
- keypad_data->base + OMAP4_KBD_IRQENABLE);
+ kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQENABLE,
+ OMAP4_DEF_IRQENABLE_EVENTEN |
+ OMAP4_DEF_IRQENABLE_LONGKEY);
return IRQ_HANDLED;
}
@@ -139,16 +172,17 @@ static int omap4_keypad_open(struct input_dev *input)
disable_irq(keypad_data->irq);
- __raw_writel(OMAP4_VAL_FUNCTIONALCFG,
- keypad_data->base + OMAP4_KBD_CTRL);
- __raw_writel(OMAP4_VAL_DEBOUNCINGTIME,
- keypad_data->base + OMAP4_KBD_DEBOUNCINGTIME);
- __raw_writel(OMAP4_VAL_IRQDISABLE,
- keypad_data->base + OMAP4_KBD_IRQSTATUS);
- __raw_writel(OMAP4_DEF_IRQENABLE_EVENTEN | OMAP4_DEF_IRQENABLE_LONGKEY,
- keypad_data->base + OMAP4_KBD_IRQENABLE);
- __raw_writel(OMAP4_DEF_WUP_EVENT_ENA | OMAP4_DEF_WUP_LONG_KEY_ENA,
- keypad_data->base + OMAP4_KBD_WAKEUPENABLE);
+ kbd_writel(keypad_data, OMAP4_KBD_CTRL,
+ OMAP4_VAL_FUNCTIONALCFG);
+ kbd_writel(keypad_data, OMAP4_KBD_DEBOUNCINGTIME,
+ OMAP4_VAL_DEBOUNCINGTIME);
+ kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS,
+ OMAP4_VAL_IRQDISABLE);
+ kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQENABLE,
+ OMAP4_DEF_IRQENABLE_EVENTEN |
+ OMAP4_DEF_IRQENABLE_LONGKEY);
+ kbd_writel(keypad_data, OMAP4_KBD_WAKEUPENABLE,
+ OMAP4_DEF_WUP_EVENT_ENA | OMAP4_DEF_WUP_LONG_KEY_ENA);
enable_irq(keypad_data->irq);
@@ -162,12 +196,12 @@ static void omap4_keypad_close(struct input_dev *input)
disable_irq(keypad_data->irq);
/* Disable interrupts */
- __raw_writel(OMAP4_VAL_IRQDISABLE,
- keypad_data->base + OMAP4_KBD_IRQENABLE);
+ kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQENABLE,
+ OMAP4_VAL_IRQDISABLE);
/* clear pending interrupts */
- __raw_writel(__raw_readl(keypad_data->base + OMAP4_KBD_IRQSTATUS),
- keypad_data->base + OMAP4_KBD_IRQSTATUS);
+ kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS,
+ kbd_read_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS));
enable_irq(keypad_data->irq);
@@ -182,6 +216,7 @@ static int __devinit omap4_keypad_probe(struct platform_device *pdev)
struct resource *res;
resource_size_t size;
unsigned int row_shift, max_keys;
+ int rev;
int irq;
int error;
@@ -241,11 +276,40 @@ static int __devinit omap4_keypad_probe(struct platform_device *pdev)
keypad_data->rows = pdata->rows;
keypad_data->cols = pdata->cols;
+ /*
+ * Enable clocks for the keypad module so that we can read
+ * revision register.
+ */
+ pm_runtime_enable(&pdev->dev);
+ error = pm_runtime_get_sync(&pdev->dev);
+ if (error) {
+ dev_err(&pdev->dev, "pm_runtime_get_sync() failed\n");
+ goto err_unmap;
+ }
+ rev = __raw_readl(keypad_data->base + OMAP4_KBD_REVISION);
+ rev &= 0x03 << 30;
+ rev >>= 30;
+ switch (rev) {
+ case KBD_REVISION_OMAP4:
+ keypad_data->reg_offset = 0x00;
+ keypad_data->irqreg_offset = 0x00;
+ break;
+ case KBD_REVISION_OMAP5:
+ keypad_data->reg_offset = 0x10;
+ keypad_data->irqreg_offset = 0x0c;
+ break;
+ default:
+ dev_err(&pdev->dev,
+ "Keypad reports unsupported revision %d", rev);
+ error = -EINVAL;
+ goto err_pm_put_sync;
+ }
+
/* input device allocation */
keypad_data->input = input_dev = input_allocate_device();
if (!input_dev) {
error = -ENOMEM;
- goto err_unmap;
+ goto err_pm_put_sync;
}
input_dev->name = pdev->name;
@@ -273,14 +337,14 @@ static int __devinit omap4_keypad_probe(struct platform_device *pdev)
input_dev->keycode, input_dev->keybit);
error = request_irq(keypad_data->irq, omap4_keypad_interrupt,
- IRQF_TRIGGER_RISING,
+ IRQF_DISABLED | IRQF_TRIGGER_RISING,
"omap4-keypad", keypad_data);
if (error) {
dev_err(&pdev->dev, "failed to register interrupt\n");
goto err_free_input;
}
- pm_runtime_enable(&pdev->dev);
+ pm_runtime_put_sync(&pdev->dev);
error = input_register_device(keypad_data->input);
if (error < 0) {
@@ -296,6 +360,8 @@ err_pm_disable:
free_irq(keypad_data->irq, keypad_data);
err_free_input:
input_free_device(input_dev);
+err_pm_put_sync:
+ pm_runtime_put_sync(&pdev->dev);
err_unmap:
iounmap(keypad_data->base);
err_release_mem:
--
1.7.1
^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [RESEND/PATCHv2] Input: omap-keypad: dynamically handle register offsets
2012-05-09 9:44 ` Poddar, Sourav
@ 2012-05-09 10:07 ` Poddar, Sourav
2012-05-17 13:31 ` Poddar, Sourav
0 siblings, 1 reply; 11+ messages in thread
From: Poddar, Sourav @ 2012-05-09 10:07 UTC (permalink / raw)
To: Dmitry Torokhov; +Cc: linux-input, linux-omap, balbi, akpm
[-- Attachment #1: Type: text/plain, Size: 30662 bytes --]
Hi Dmitry,
On Wed, May 9, 2012 at 3:14 PM, Poddar, Sourav <sourav.poddar@ti.com> wrote:
> Hi Dmitry,
>
> I did some minor fixes to the patch which you suggested above and
> the keypad is functional now.
>
> Changes:
> - Move "pm_runtime_enable" before using "pm_runtime_get_sync".
>
> Sending the patch inlined..(also attached).
>
> From: G, Manjunath Kondaiah <manjugk@ti.com>
> Date: Mon, 10 Oct 2011 20:52:05 +0530
> Subject: [PATCH] Input: omap-keypad: dynamically handle register offsets
>
> Keypad controller register offsets are different for omap4
> and omap5. Handle these offsets through static mapping and
> assign these mappings during run time.
>
> Tested on omap4430 sdp with 3.4-rc3.
> Tested on omap5430evm with 3.1-custom kernel.
>
> Cc: Andrew Morton <akpm@linux-foundation.org>
> Signed-off-by: Felipe Balbi <balbi@ti.com>
> Signed-off-by: G, Manjunath Kondaiah <manjugk@ti.com>
> Signed-off-by: Sourav Poddar <sourav.poddar@ti.com>
> Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
> ---
> drivers/input/keyboard/Kconfig | 4 +-
> drivers/input/keyboard/omap4-keypad.c | 120 +++++++++++++++++++++++++-------
> 2 files changed, 95 insertions(+), 29 deletions(-)
>
> diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
> index f354813..33bbdee 100644
> --- a/drivers/input/keyboard/Kconfig
> +++ b/drivers/input/keyboard/Kconfig
> @@ -512,9 +512,9 @@ config KEYBOARD_OMAP
> module will be called omap-keypad.
>
> config KEYBOARD_OMAP4
> - tristate "TI OMAP4 keypad support"
> + tristate "TI OMAP4+ keypad support"
> help
> - Say Y here if you want to use the OMAP4 keypad.
> + Say Y here if you want to use the OMAP4+ keypad.
>
> To compile this driver as a module, choose M here: the
> module will be called omap4-keypad.
> diff --git a/drivers/input/keyboard/omap4-keypad.c
> b/drivers/input/keyboard/omap4-keypad.c
> index e809ac0..d7102e8 100644
> --- a/drivers/input/keyboard/omap4-keypad.c
> +++ b/drivers/input/keyboard/omap4-keypad.c
> @@ -68,19 +68,52 @@
>
> #define OMAP4_MASK_IRQSTATUSDISABLE 0xFFFF
>
> +enum {
> + KBD_REVISION_OMAP4 = 0,
> + KBD_REVISION_OMAP5,
> +};
> +
> struct omap4_keypad {
> struct input_dev *input;
>
> void __iomem *base;
> - int irq;
> + unsigned int irq;
>
> unsigned int rows;
> unsigned int cols;
> + u32 reg_offset;
> + u32 irqreg_offset;
> unsigned int row_shift;
> unsigned char key_state[8];
> unsigned short keymap[];
> };
>
> +static int kbd_readl(struct omap4_keypad *keypad_data, u32 offset)
> +{
> + return __raw_readl(keypad_data->base +
> + keypad_data->reg_offset + offset);
> +}
> +
> +static void kbd_writel(struct omap4_keypad *keypad_data, u32 offset, u32 value)
> +{
> + __raw_writel(value,
> + keypad_data->base + keypad_data->reg_offset + offset);
> +}
> +
> +static int kbd_read_irqreg(struct omap4_keypad *keypad_data, u32 offset)
> +{
> + return __raw_readl(keypad_data->base +
> + keypad_data->irqreg_offset + offset);
> +}
> +
> +static void kbd_write_irqreg(struct omap4_keypad *keypad_data,
> + u32 offset, u32 value)
> +{
> + __raw_writel(value,
> + keypad_data->base + keypad_data->irqreg_offset + offset);
> +}
> +
> +
> /* Interrupt handler */
> static irqreturn_t omap4_keypad_interrupt(int irq, void *dev_id)
> {
> @@ -91,12 +124,11 @@ static irqreturn_t omap4_keypad_interrupt(int
> irq, void *dev_id)
> u32 *new_state = (u32 *) key_state;
>
> /* Disable interrupts */
> - __raw_writel(OMAP4_VAL_IRQDISABLE,
> - keypad_data->base + OMAP4_KBD_IRQENABLE);
> + kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQENABLE,
> + OMAP4_VAL_IRQDISABLE);
>
> - *new_state = __raw_readl(keypad_data->base + OMAP4_KBD_FULLCODE31_0);
> - *(new_state + 1) = __raw_readl(keypad_data->base
> - + OMAP4_KBD_FULLCODE63_32);
> + *new_state = kbd_readl(keypad_data, OMAP4_KBD_FULLCODE31_0);
> + *(new_state + 1) = kbd_readl(keypad_data, OMAP4_KBD_FULLCODE63_32);
>
> for (row = 0; row < keypad_data->rows; row++) {
> changed = key_state[row] ^ keypad_data->key_state[row];
> @@ -121,12 +153,13 @@ static irqreturn_t omap4_keypad_interrupt(int
> irq, void *dev_id)
> sizeof(keypad_data->key_state));
>
> /* clear pending interrupts */
> - __raw_writel(__raw_readl(keypad_data->base + OMAP4_KBD_IRQSTATUS),
> - keypad_data->base + OMAP4_KBD_IRQSTATUS);
> + kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS,
> + kbd_read_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS));
>
> /* enable interrupts */
> - __raw_writel(OMAP4_DEF_IRQENABLE_EVENTEN | OMAP4_DEF_IRQENABLE_LONGKEY,
> - keypad_data->base + OMAP4_KBD_IRQENABLE);
> + kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQENABLE,
> + OMAP4_DEF_IRQENABLE_EVENTEN |
> + OMAP4_DEF_IRQENABLE_LONGKEY);
>
> return IRQ_HANDLED;
> }
> @@ -139,16 +172,17 @@ static int omap4_keypad_open(struct input_dev *input)
>
> disable_irq(keypad_data->irq);
>
> - __raw_writel(OMAP4_VAL_FUNCTIONALCFG,
> - keypad_data->base + OMAP4_KBD_CTRL);
> - __raw_writel(OMAP4_VAL_DEBOUNCINGTIME,
> - keypad_data->base + OMAP4_KBD_DEBOUNCINGTIME);
> - __raw_writel(OMAP4_VAL_IRQDISABLE,
> - keypad_data->base + OMAP4_KBD_IRQSTATUS);
> - __raw_writel(OMAP4_DEF_IRQENABLE_EVENTEN | OMAP4_DEF_IRQENABLE_LONGKEY,
> - keypad_data->base + OMAP4_KBD_IRQENABLE);
> - __raw_writel(OMAP4_DEF_WUP_EVENT_ENA | OMAP4_DEF_WUP_LONG_KEY_ENA,
> - keypad_data->base + OMAP4_KBD_WAKEUPENABLE);
> + kbd_writel(keypad_data, OMAP4_KBD_CTRL,
> + OMAP4_VAL_FUNCTIONALCFG);
> + kbd_writel(keypad_data, OMAP4_KBD_DEBOUNCINGTIME,
> + OMAP4_VAL_DEBOUNCINGTIME);
> + kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS,
> + OMAP4_VAL_IRQDISABLE);
> + kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQENABLE,
> + OMAP4_DEF_IRQENABLE_EVENTEN |
> + OMAP4_DEF_IRQENABLE_LONGKEY);
> + kbd_writel(keypad_data, OMAP4_KBD_WAKEUPENABLE,
> + OMAP4_DEF_WUP_EVENT_ENA | OMAP4_DEF_WUP_LONG_KEY_ENA);
>
> enable_irq(keypad_data->irq);
>
> @@ -162,12 +196,12 @@ static void omap4_keypad_close(struct input_dev *input)
> disable_irq(keypad_data->irq);
>
> /* Disable interrupts */
> - __raw_writel(OMAP4_VAL_IRQDISABLE,
> - keypad_data->base + OMAP4_KBD_IRQENABLE);
> + kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQENABLE,
> + OMAP4_VAL_IRQDISABLE);
>
> /* clear pending interrupts */
> - __raw_writel(__raw_readl(keypad_data->base + OMAP4_KBD_IRQSTATUS),
> - keypad_data->base + OMAP4_KBD_IRQSTATUS);
> + kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS,
> + kbd_read_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS));
>
> enable_irq(keypad_data->irq);
>
> @@ -182,6 +216,7 @@ static int __devinit omap4_keypad_probe(struct
> platform_device *pdev)
> struct resource *res;
> resource_size_t size;
> unsigned int row_shift, max_keys;
> + int rev;
> int irq;
> int error;
>
> @@ -241,11 +276,40 @@ static int __devinit omap4_keypad_probe(struct
> platform_device *pdev)
> keypad_data->rows = pdata->rows;
> keypad_data->cols = pdata->cols;
>
> + /*
> + * Enable clocks for the keypad module so that we can read
> + * revision register.
> + */
> + pm_runtime_enable(&pdev->dev);
> + error = pm_runtime_get_sync(&pdev->dev);
> + if (error) {
> + dev_err(&pdev->dev, "pm_runtime_get_sync() failed\n");
> + goto err_unmap;
> + }
> + rev = __raw_readl(keypad_data->base + OMAP4_KBD_REVISION);
> + rev &= 0x03 << 30;
> + rev >>= 30;
> + switch (rev) {
> + case KBD_REVISION_OMAP4:
> + keypad_data->reg_offset = 0x00;
> + keypad_data->irqreg_offset = 0x00;
> + break;
> + case KBD_REVISION_OMAP5:
> + keypad_data->reg_offset = 0x10;
> + keypad_data->irqreg_offset = 0x0c;
> + break;
> + default:
> + dev_err(&pdev->dev,
> + "Keypad reports unsupported revision %d", rev);
> + error = -EINVAL;
> + goto err_pm_put_sync;
> + }
> +
> /* input device allocation */
> keypad_data->input = input_dev = input_allocate_device();
> if (!input_dev) {
> error = -ENOMEM;
> - goto err_unmap;
> + goto err_pm_put_sync;
> }
>
> input_dev->name = pdev->name;
> @@ -273,14 +337,14 @@ static int __devinit omap4_keypad_probe(struct
> platform_device *pdev)
> input_dev->keycode, input_dev->keybit);
>
> error = request_irq(keypad_data->irq, omap4_keypad_interrupt,
> - IRQF_TRIGGER_RISING,
> + IRQF_DISABLED | IRQF_TRIGGER_RISING,
Sorry, " IRQF_DISABLED" got included by mistake.
Removing this stray change and sending it again.
> "omap4-keypad", keypad_data);
> if (error) {
> dev_err(&pdev->dev, "failed to register interrupt\n");
> goto err_free_input;
> }
>
> - pm_runtime_enable(&pdev->dev);
> + pm_runtime_put_sync(&pdev->dev);
>
> error = input_register_device(keypad_data->input);
> if (error < 0) {
> @@ -296,6 +360,8 @@ err_pm_disable:
> free_irq(keypad_data->irq, keypad_data);
> err_free_input:
> input_free_device(input_dev);
> +err_pm_put_sync:
> + pm_runtime_put_sync(&pdev->dev);
> err_unmap:
> iounmap(keypad_data->base);
> err_release_mem:
>
>
> ~Sourav
>
> On Wed, May 9, 2012 at 1:15 PM, Dmitry Torokhov
> <dmitry.torokhov@gmail.com> wrote:
>>> Hi Dmitry ,
>>>
>>>
>>> On Wed, May 9, 2012 at 10:48 AM, Dmitry Torokhov
>>> <dmitry.torokhov@gmail.com> wrote:
>>> > Ho Sourav,
>>> >
>>> > On Thu, Apr 26, 2012 at 11:24:37AM +0530, Sourav Poddar wrote:
>>> >>
>>> >> -config KEYBOARD_OMAP4
>>> >> - tristate "TI OMAP4 keypad support"
>>> >> +config KEYBOARD_OMAP4+
>>> >
>>> > I think this works purely by accident - '+' sign getting dropped by
>>> > parser...
>>> >
>>> >> @@ -139,16 +192,33 @@ static int omap4_keypad_open(struct input_dev *input)
>>> >>
>>> >> disable_irq(keypad_data->irq);
>>> >>
>>> >> - __raw_writel(OMAP4_VAL_FUNCTIONALCFG,
>>> >> - keypad_data->base + OMAP4_KBD_CTRL);
>>> >> - __raw_writel(OMAP4_VAL_DEBOUNCINGTIME,
>>> >> - keypad_data->base + OMAP4_KBD_DEBOUNCINGTIME);
>>> >> - __raw_writel(OMAP4_VAL_IRQDISABLE,
>>> >> - keypad_data->base + OMAP4_KBD_IRQSTATUS);
>>> >> - __raw_writel(OMAP4_DEF_IRQENABLE_EVENTEN | OMAP4_DEF_IRQENABLE_LONGKEY,
>>> >> - keypad_data->base + OMAP4_KBD_IRQENABLE);
>>> >> - __raw_writel(OMAP4_DEF_WUP_EVENT_ENA | OMAP4_DEF_WUP_LONG_KEY_ENA,
>>> >> - keypad_data->base + OMAP4_KBD_WAKEUPENABLE);
>>> >> + keypad_data->revision = kbd_read_revision(keypad_data,
>>> >> + OMAP4_KBD_REVISION);
>>> >> + switch (keypad_data->revision) {
>>> >> + case 1:
>>> >> + keypad_data->irqstatus = OMAP4_KBD_IRQSTATUS + 0x0c;
>>> >> + keypad_data->irqenable = OMAP4_KBD_IRQENABLE + 0x0c;
>>> >> + keypad_data->reg_offset = 0x10;
>>> >> + break;
>>> >
>>> > This should be done in probe().
>>> >
>>> Dont we then require "pm_runtime_put_sync" in probe, since we are trying
>>> to read the keypad revision register.?
>>
>> Ah, indeed, but I think not pm_runtime_get_sync() but
>> pm_runtime_set_active().
>>
>> Not sure if this will fix the crash...
>>
>> --
>> Dmitry
>>
>>
>> Input: omap-keypad - dynamically handle register offsets
>>
>> From: G, Manjunath Kondaiah <manjugk@ti.com>
>>
>> Keypad controller register offsets are different for omap4
>> and omap5. Handle these offsets through static mapping and
>> assign these mappings during run time.
>>
>> Tested on omap4430 sdp with 3.4-rc3.
>> Tested on omap5430evm with 3.1-custom kernel.
>>
>> Signed-off-by: Felipe Balbi <balbi@ti.com>
>> Signed-off-by: G, Manjunath Kondaiah <manjugk@ti.com>
>> Signed-off-by: Sourav Poddar <sourav.poddar@ti.com>
>> Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
>> ---
>>
>> drivers/input/keyboard/Kconfig | 4 +
>> drivers/input/keyboard/omap4-keypad.c | 117 ++++++++++++++++++++++++++-------
>> 2 files changed, 94 insertions(+), 27 deletions(-)
>>
>>
>> diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
>> index 20a3753..84ee155 100644
>> --- a/drivers/input/keyboard/Kconfig
>> +++ b/drivers/input/keyboard/Kconfig
>> @@ -531,9 +531,9 @@ config KEYBOARD_OMAP
>> module will be called omap-keypad.
>>
>> config KEYBOARD_OMAP4
>> - tristate "TI OMAP4 keypad support"
>> + tristate "TI OMAP4+ keypad support"
>> help
>> - Say Y here if you want to use the OMAP4 keypad.
>> + Say Y here if you want to use the OMAP4+ keypad.
>>
>> To compile this driver as a module, choose M here: the
>> module will be called omap4-keypad.
>> diff --git a/drivers/input/keyboard/omap4-keypad.c b/drivers/input/keyboard/omap4-keypad.c
>> index e809ac0..c9fd0df 100644
>> --- a/drivers/input/keyboard/omap4-keypad.c
>> +++ b/drivers/input/keyboard/omap4-keypad.c
>> @@ -68,19 +68,52 @@
>>
>> #define OMAP4_MASK_IRQSTATUSDISABLE 0xFFFF
>>
>> +enum {
>> + KBD_REVISION_OMAP4 = 0,
>> + KBD_REVISION_OMAP5,
>> +};
>> +
>> struct omap4_keypad {
>> struct input_dev *input;
>>
>> void __iomem *base;
>> - int irq;
>> + unsigned int irq;
>>
>> unsigned int rows;
>> unsigned int cols;
>> + u32 reg_offset;
>> + u32 irqreg_offset;
>> unsigned int row_shift;
>> unsigned char key_state[8];
>> unsigned short keymap[];
>> };
>>
>> +static int kbd_readl(struct omap4_keypad *keypad_data, u32 offset)
>> +{
>> + return __raw_readl(keypad_data->base +
>> + keypad_data->reg_offset + offset);
>> +}
>> +
>> +static void kbd_writel(struct omap4_keypad *keypad_data, u32 offset, u32 value)
>> +{
>> + __raw_writel(value,
>> + keypad_data->base + keypad_data->reg_offset + offset);
>> +}
>> +
>> +static int kbd_read_irqreg(struct omap4_keypad *keypad_data, u32 offset)
>> +{
>> + return __raw_readl(keypad_data->base +
>> + keypad_data->irqreg_offset + offset);
>> +}
>> +
>> +static void kbd_write_irqreg(struct omap4_keypad *keypad_data,
>> + u32 offset, u32 value)
>> +{
>> + __raw_writel(value,
>> + keypad_data->base + keypad_data->irqreg_offset + offset);
>> +}
>> +
>> +
>> /* Interrupt handler */
>> static irqreturn_t omap4_keypad_interrupt(int irq, void *dev_id)
>> {
>> @@ -91,12 +124,11 @@ static irqreturn_t omap4_keypad_interrupt(int irq, void *dev_id)
>> u32 *new_state = (u32 *) key_state;
>>
>> /* Disable interrupts */
>> - __raw_writel(OMAP4_VAL_IRQDISABLE,
>> - keypad_data->base + OMAP4_KBD_IRQENABLE);
>> + kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQENABLE,
>> + OMAP4_VAL_IRQDISABLE);
>>
>> - *new_state = __raw_readl(keypad_data->base + OMAP4_KBD_FULLCODE31_0);
>> - *(new_state + 1) = __raw_readl(keypad_data->base
>> - + OMAP4_KBD_FULLCODE63_32);
>> + *new_state = kbd_readl(keypad_data, OMAP4_KBD_FULLCODE31_0);
>> + *(new_state + 1) = kbd_readl(keypad_data, OMAP4_KBD_FULLCODE63_32);
>>
>> for (row = 0; row < keypad_data->rows; row++) {
>> changed = key_state[row] ^ keypad_data->key_state[row];
>> @@ -121,12 +153,13 @@ static irqreturn_t omap4_keypad_interrupt(int irq, void *dev_id)
>> sizeof(keypad_data->key_state));
>>
>> /* clear pending interrupts */
>> - __raw_writel(__raw_readl(keypad_data->base + OMAP4_KBD_IRQSTATUS),
>> - keypad_data->base + OMAP4_KBD_IRQSTATUS);
>> + kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS,
>> + kbd_read_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS));
>>
>> /* enable interrupts */
>> - __raw_writel(OMAP4_DEF_IRQENABLE_EVENTEN | OMAP4_DEF_IRQENABLE_LONGKEY,
>> - keypad_data->base + OMAP4_KBD_IRQENABLE);
>> + kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQENABLE,
>> + OMAP4_DEF_IRQENABLE_EVENTEN |
>> + OMAP4_DEF_IRQENABLE_LONGKEY);
>>
>> return IRQ_HANDLED;
>> }
>> @@ -139,16 +172,17 @@ static int omap4_keypad_open(struct input_dev *input)
>>
>> disable_irq(keypad_data->irq);
>>
>> - __raw_writel(OMAP4_VAL_FUNCTIONALCFG,
>> - keypad_data->base + OMAP4_KBD_CTRL);
>> - __raw_writel(OMAP4_VAL_DEBOUNCINGTIME,
>> - keypad_data->base + OMAP4_KBD_DEBOUNCINGTIME);
>> - __raw_writel(OMAP4_VAL_IRQDISABLE,
>> - keypad_data->base + OMAP4_KBD_IRQSTATUS);
>> - __raw_writel(OMAP4_DEF_IRQENABLE_EVENTEN | OMAP4_DEF_IRQENABLE_LONGKEY,
>> - keypad_data->base + OMAP4_KBD_IRQENABLE);
>> - __raw_writel(OMAP4_DEF_WUP_EVENT_ENA | OMAP4_DEF_WUP_LONG_KEY_ENA,
>> - keypad_data->base + OMAP4_KBD_WAKEUPENABLE);
>> + kbd_writel(keypad_data, OMAP4_KBD_CTRL,
>> + OMAP4_VAL_FUNCTIONALCFG);
>> + kbd_writel(keypad_data, OMAP4_KBD_DEBOUNCINGTIME,
>> + OMAP4_VAL_DEBOUNCINGTIME);
>> + kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS,
>> + OMAP4_VAL_IRQDISABLE);
>> + kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQENABLE,
>> + OMAP4_DEF_IRQENABLE_EVENTEN |
>> + OMAP4_DEF_IRQENABLE_LONGKEY);
>> + kbd_writel(keypad_data, OMAP4_KBD_WAKEUPENABLE,
>> + OMAP4_DEF_WUP_EVENT_ENA | OMAP4_DEF_WUP_LONG_KEY_ENA);
>>
>> enable_irq(keypad_data->irq);
>>
>> @@ -162,12 +196,12 @@ static void omap4_keypad_close(struct input_dev *input)
>> disable_irq(keypad_data->irq);
>>
>> /* Disable interrupts */
>> - __raw_writel(OMAP4_VAL_IRQDISABLE,
>> - keypad_data->base + OMAP4_KBD_IRQENABLE);
>> + kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQENABLE,
>> + OMAP4_VAL_IRQDISABLE);
>>
>> /* clear pending interrupts */
>> - __raw_writel(__raw_readl(keypad_data->base + OMAP4_KBD_IRQSTATUS),
>> - keypad_data->base + OMAP4_KBD_IRQSTATUS);
>> + kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS,
>> + kbd_read_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS));
>>
>> enable_irq(keypad_data->irq);
>>
>> @@ -182,6 +216,7 @@ static int __devinit omap4_keypad_probe(struct platform_device *pdev)
>> struct resource *res;
>> resource_size_t size;
>> unsigned int row_shift, max_keys;
>> + int rev;
>> int irq;
>> int error;
>>
>> @@ -241,11 +276,40 @@ static int __devinit omap4_keypad_probe(struct platform_device *pdev)
>> keypad_data->rows = pdata->rows;
>> keypad_data->cols = pdata->cols;
>>
>> + /*
>> + * Mark device as active (and wake up its parent) so we can read
>> + * revision register.
>> + */
>> + error = pm_runtime_set_active(&pdev->dev);
>> + if (error) {
>> + dev_err(&pdev->dev, "pm_runtime_set_active() failed\n");
>> + goto err_unmap;
>> + }
>> +
>> + rev = __raw_readl(keypad_data->base + OMAP4_KBD_REVISION);
>> + rev &= 0x03 << 30;
>> + rev >>= 30;
>> + switch (rev) {
>> + case KBD_REVISION_OMAP4:
>> + keypad_data->reg_offset = 0x00;
>> + keypad_data->irqreg_offset = 0x00;
>> + break;
>> + case KBD_REVISION_OMAP5:
>> + keypad_data->reg_offset = 0x10;
>> + keypad_data->irqreg_offset = 0x0c;
>> + break;
>> + default:
>> + dev_err(&pdev->dev,
>> + "Keypad reports unsupported revision %d", rev);
>> + error = -EINVAL;
>> + goto err_pm_suspended;
>> + }
>> +
>> /* input device allocation */
>> keypad_data->input = input_dev = input_allocate_device();
>> if (!input_dev) {
>> error = -ENOMEM;
>> - goto err_unmap;
>> + goto err_pm_suspended;
>> }
>>
>> input_dev->name = pdev->name;
>> @@ -281,6 +345,7 @@ static int __devinit omap4_keypad_probe(struct platform_device *pdev)
>> }
>>
>> pm_runtime_enable(&pdev->dev);
>> + pm_runtime_put_sync(&pdev->dev);
>>
>> error = input_register_device(keypad_data->input);
>> if (error < 0) {
>> @@ -296,6 +361,8 @@ err_pm_disable:
>> free_irq(keypad_data->irq, keypad_data);
>> err_free_input:
>> input_free_device(input_dev);
>> +err_pm_suspended:
>> + pm_runtime_set_suspended(&pdev->dev);
>> err_unmap:
>> iounmap(keypad_data->base);
>> err_release_mem:
From: G, Manjunath Kondaiah <manjugk@ti.com>
Date: Mon, 10 Oct 2011 20:52:05 +0530
Subject: [PATCH] Input: omap-keypad: dynamically handle register offsets
Keypad controller register offsets are different for omap4
and omap5. Handle these offsets through static mapping and
assign these mappings during run time.
Tested on omap4430 sdp with 3.4-rc3.
Tested on omap5430evm with 3.1-custom kernel.
Cc: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Felipe Balbi <balbi@ti.com>
Signed-off-by: G, Manjunath Kondaiah <manjugk@ti.com>
Signed-off-by: Sourav Poddar <sourav.poddar@ti.com>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
---
drivers/input/keyboard/Kconfig | 4 +-
drivers/input/keyboard/omap4-keypad.c | 118 +++++++++++++++++++++++++-------
2 files changed, 94 insertions(+), 28 deletions(-)
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
index f354813..33bbdee 100644
--- a/drivers/input/keyboard/Kconfig
+++ b/drivers/input/keyboard/Kconfig
@@ -512,9 +512,9 @@ config KEYBOARD_OMAP
module will be called omap-keypad.
config KEYBOARD_OMAP4
- tristate "TI OMAP4 keypad support"
+ tristate "TI OMAP4+ keypad support"
help
- Say Y here if you want to use the OMAP4 keypad.
+ Say Y here if you want to use the OMAP4+ keypad.
To compile this driver as a module, choose M here: the
module will be called omap4-keypad.
diff --git a/drivers/input/keyboard/omap4-keypad.c
b/drivers/input/keyboard/omap4-keypad.c
index e809ac0..28da0e4 100644
--- a/drivers/input/keyboard/omap4-keypad.c
+++ b/drivers/input/keyboard/omap4-keypad.c
@@ -68,19 +68,52 @@
#define OMAP4_MASK_IRQSTATUSDISABLE 0xFFFF
+enum {
+ KBD_REVISION_OMAP4 = 0,
+ KBD_REVISION_OMAP5,
+};
+
struct omap4_keypad {
struct input_dev *input;
void __iomem *base;
- int irq;
+ unsigned int irq;
unsigned int rows;
unsigned int cols;
+ u32 reg_offset;
+ u32 irqreg_offset;
unsigned int row_shift;
unsigned char key_state[8];
unsigned short keymap[];
};
+static int kbd_readl(struct omap4_keypad *keypad_data, u32 offset)
+{
+ return __raw_readl(keypad_data->base +
+ keypad_data->reg_offset + offset);
+}
+
+static void kbd_writel(struct omap4_keypad *keypad_data, u32 offset, u32 value)
+{
+ __raw_writel(value,
+ keypad_data->base + keypad_data->reg_offset + offset);
+}
+
+static int kbd_read_irqreg(struct omap4_keypad *keypad_data, u32 offset)
+{
+ return __raw_readl(keypad_data->base +
+ keypad_data->irqreg_offset + offset);
+}
+
+static void kbd_write_irqreg(struct omap4_keypad *keypad_data,
+ u32 offset, u32 value)
+{
+ __raw_writel(value,
+ keypad_data->base + keypad_data->irqreg_offset + offset);
+}
+
+
/* Interrupt handler */
static irqreturn_t omap4_keypad_interrupt(int irq, void *dev_id)
{
@@ -91,12 +124,11 @@ static irqreturn_t omap4_keypad_interrupt(int
irq, void *dev_id)
u32 *new_state = (u32 *) key_state;
/* Disable interrupts */
- __raw_writel(OMAP4_VAL_IRQDISABLE,
- keypad_data->base + OMAP4_KBD_IRQENABLE);
+ kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQENABLE,
+ OMAP4_VAL_IRQDISABLE);
- *new_state = __raw_readl(keypad_data->base + OMAP4_KBD_FULLCODE31_0);
- *(new_state + 1) = __raw_readl(keypad_data->base
- + OMAP4_KBD_FULLCODE63_32);
+ *new_state = kbd_readl(keypad_data, OMAP4_KBD_FULLCODE31_0);
+ *(new_state + 1) = kbd_readl(keypad_data, OMAP4_KBD_FULLCODE63_32);
for (row = 0; row < keypad_data->rows; row++) {
changed = key_state[row] ^ keypad_data->key_state[row];
@@ -121,12 +153,13 @@ static irqreturn_t omap4_keypad_interrupt(int
irq, void *dev_id)
sizeof(keypad_data->key_state));
/* clear pending interrupts */
- __raw_writel(__raw_readl(keypad_data->base + OMAP4_KBD_IRQSTATUS),
- keypad_data->base + OMAP4_KBD_IRQSTATUS);
+ kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS,
+ kbd_read_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS));
/* enable interrupts */
- __raw_writel(OMAP4_DEF_IRQENABLE_EVENTEN | OMAP4_DEF_IRQENABLE_LONGKEY,
- keypad_data->base + OMAP4_KBD_IRQENABLE);
+ kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQENABLE,
+ OMAP4_DEF_IRQENABLE_EVENTEN |
+ OMAP4_DEF_IRQENABLE_LONGKEY);
return IRQ_HANDLED;
}
@@ -139,16 +172,17 @@ static int omap4_keypad_open(struct input_dev *input)
disable_irq(keypad_data->irq);
- __raw_writel(OMAP4_VAL_FUNCTIONALCFG,
- keypad_data->base + OMAP4_KBD_CTRL);
- __raw_writel(OMAP4_VAL_DEBOUNCINGTIME,
- keypad_data->base + OMAP4_KBD_DEBOUNCINGTIME);
- __raw_writel(OMAP4_VAL_IRQDISABLE,
- keypad_data->base + OMAP4_KBD_IRQSTATUS);
- __raw_writel(OMAP4_DEF_IRQENABLE_EVENTEN | OMAP4_DEF_IRQENABLE_LONGKEY,
- keypad_data->base + OMAP4_KBD_IRQENABLE);
- __raw_writel(OMAP4_DEF_WUP_EVENT_ENA | OMAP4_DEF_WUP_LONG_KEY_ENA,
- keypad_data->base + OMAP4_KBD_WAKEUPENABLE);
+ kbd_writel(keypad_data, OMAP4_KBD_CTRL,
+ OMAP4_VAL_FUNCTIONALCFG);
+ kbd_writel(keypad_data, OMAP4_KBD_DEBOUNCINGTIME,
+ OMAP4_VAL_DEBOUNCINGTIME);
+ kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS,
+ OMAP4_VAL_IRQDISABLE);
+ kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQENABLE,
+ OMAP4_DEF_IRQENABLE_EVENTEN |
+ OMAP4_DEF_IRQENABLE_LONGKEY);
+ kbd_writel(keypad_data, OMAP4_KBD_WAKEUPENABLE,
+ OMAP4_DEF_WUP_EVENT_ENA | OMAP4_DEF_WUP_LONG_KEY_ENA);
enable_irq(keypad_data->irq);
@@ -162,12 +196,12 @@ static void omap4_keypad_close(struct input_dev *input)
disable_irq(keypad_data->irq);
/* Disable interrupts */
- __raw_writel(OMAP4_VAL_IRQDISABLE,
- keypad_data->base + OMAP4_KBD_IRQENABLE);
+ kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQENABLE,
+ OMAP4_VAL_IRQDISABLE);
/* clear pending interrupts */
- __raw_writel(__raw_readl(keypad_data->base + OMAP4_KBD_IRQSTATUS),
- keypad_data->base + OMAP4_KBD_IRQSTATUS);
+ kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS,
+ kbd_read_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS));
enable_irq(keypad_data->irq);
@@ -182,6 +216,7 @@ static int __devinit omap4_keypad_probe(struct
platform_device *pdev)
struct resource *res;
resource_size_t size;
unsigned int row_shift, max_keys;
+ int rev;
int irq;
int error;
@@ -241,11 +276,40 @@ static int __devinit omap4_keypad_probe(struct
platform_device *pdev)
keypad_data->rows = pdata->rows;
keypad_data->cols = pdata->cols;
+ /*
+ * Enable clocks for the keypad module so that we can read
+ * revision register.
+ */
+ pm_runtime_enable(&pdev->dev);
+ error = pm_runtime_get_sync(&pdev->dev);
+ if (error) {
+ dev_err(&pdev->dev, "pm_runtime_get_sync() failed\n");
+ goto err_unmap;
+ }
+ rev = __raw_readl(keypad_data->base + OMAP4_KBD_REVISION);
+ rev &= 0x03 << 30;
+ rev >>= 30;
+ switch (rev) {
+ case KBD_REVISION_OMAP4:
+ keypad_data->reg_offset = 0x00;
+ keypad_data->irqreg_offset = 0x00;
+ break;
+ case KBD_REVISION_OMAP5:
+ keypad_data->reg_offset = 0x10;
+ keypad_data->irqreg_offset = 0x0c;
+ break;
+ default:
+ dev_err(&pdev->dev,
+ "Keypad reports unsupported revision %d", rev);
+ error = -EINVAL;
+ goto err_pm_put_sync;
+ }
+
/* input device allocation */
keypad_data->input = input_dev = input_allocate_device();
if (!input_dev) {
error = -ENOMEM;
- goto err_unmap;
+ goto err_pm_put_sync;
}
input_dev->name = pdev->name;
@@ -280,7 +344,7 @@ static int __devinit omap4_keypad_probe(struct
platform_device *pdev)
goto err_free_input;
}
- pm_runtime_enable(&pdev->dev);
+ pm_runtime_put_sync(&pdev->dev);
error = input_register_device(keypad_data->input);
if (error < 0) {
@@ -296,6 +360,8 @@ err_pm_disable:
free_irq(keypad_data->irq, keypad_data);
err_free_input:
input_free_device(input_dev);
+err_pm_put_sync:
+ pm_runtime_put_sync(&pdev->dev);
err_unmap:
iounmap(keypad_data->base);
err_release_mem:
--
[-- Attachment #2: 0001-Input-omap-keypad-dynamically-handle-register-offset.patch --]
[-- Type: text/x-diff, Size: 7826 bytes --]
From e163a570b8ee81c22c5a71bb092c205f146fee49 Mon Sep 17 00:00:00 2001
From: G, Manjunath Kondaiah <manjugk@ti.com>
Date: Mon, 10 Oct 2011 20:52:05 +0530
Subject: [PATCH] Input: omap-keypad: dynamically handle register offsets
Keypad controller register offsets are different for omap4
and omap5. Handle these offsets through static mapping and
assign these mappings during run time.
Tested on omap4430 sdp with 3.4-rc3.
Tested on omap5430evm with 3.1-custom kernel.
Cc: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Felipe Balbi <balbi@ti.com>
Signed-off-by: G, Manjunath Kondaiah <manjugk@ti.com>
Signed-off-by: Sourav Poddar <sourav.poddar@ti.com>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
---
drivers/input/keyboard/Kconfig | 4 +-
drivers/input/keyboard/omap4-keypad.c | 118 +++++++++++++++++++++++++-------
2 files changed, 94 insertions(+), 28 deletions(-)
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
index f354813..33bbdee 100644
--- a/drivers/input/keyboard/Kconfig
+++ b/drivers/input/keyboard/Kconfig
@@ -512,9 +512,9 @@ config KEYBOARD_OMAP
module will be called omap-keypad.
config KEYBOARD_OMAP4
- tristate "TI OMAP4 keypad support"
+ tristate "TI OMAP4+ keypad support"
help
- Say Y here if you want to use the OMAP4 keypad.
+ Say Y here if you want to use the OMAP4+ keypad.
To compile this driver as a module, choose M here: the
module will be called omap4-keypad.
diff --git a/drivers/input/keyboard/omap4-keypad.c b/drivers/input/keyboard/omap4-keypad.c
index e809ac0..28da0e4 100644
--- a/drivers/input/keyboard/omap4-keypad.c
+++ b/drivers/input/keyboard/omap4-keypad.c
@@ -68,19 +68,52 @@
#define OMAP4_MASK_IRQSTATUSDISABLE 0xFFFF
+enum {
+ KBD_REVISION_OMAP4 = 0,
+ KBD_REVISION_OMAP5,
+};
+
struct omap4_keypad {
struct input_dev *input;
void __iomem *base;
- int irq;
+ unsigned int irq;
unsigned int rows;
unsigned int cols;
+ u32 reg_offset;
+ u32 irqreg_offset;
unsigned int row_shift;
unsigned char key_state[8];
unsigned short keymap[];
};
+static int kbd_readl(struct omap4_keypad *keypad_data, u32 offset)
+{
+ return __raw_readl(keypad_data->base +
+ keypad_data->reg_offset + offset);
+}
+
+static void kbd_writel(struct omap4_keypad *keypad_data, u32 offset, u32 value)
+{
+ __raw_writel(value,
+ keypad_data->base + keypad_data->reg_offset + offset);
+}
+
+static int kbd_read_irqreg(struct omap4_keypad *keypad_data, u32 offset)
+{
+ return __raw_readl(keypad_data->base +
+ keypad_data->irqreg_offset + offset);
+}
+
+static void kbd_write_irqreg(struct omap4_keypad *keypad_data,
+ u32 offset, u32 value)
+{
+ __raw_writel(value,
+ keypad_data->base + keypad_data->irqreg_offset + offset);
+}
+
+
/* Interrupt handler */
static irqreturn_t omap4_keypad_interrupt(int irq, void *dev_id)
{
@@ -91,12 +124,11 @@ static irqreturn_t omap4_keypad_interrupt(int irq, void *dev_id)
u32 *new_state = (u32 *) key_state;
/* Disable interrupts */
- __raw_writel(OMAP4_VAL_IRQDISABLE,
- keypad_data->base + OMAP4_KBD_IRQENABLE);
+ kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQENABLE,
+ OMAP4_VAL_IRQDISABLE);
- *new_state = __raw_readl(keypad_data->base + OMAP4_KBD_FULLCODE31_0);
- *(new_state + 1) = __raw_readl(keypad_data->base
- + OMAP4_KBD_FULLCODE63_32);
+ *new_state = kbd_readl(keypad_data, OMAP4_KBD_FULLCODE31_0);
+ *(new_state + 1) = kbd_readl(keypad_data, OMAP4_KBD_FULLCODE63_32);
for (row = 0; row < keypad_data->rows; row++) {
changed = key_state[row] ^ keypad_data->key_state[row];
@@ -121,12 +153,13 @@ static irqreturn_t omap4_keypad_interrupt(int irq, void *dev_id)
sizeof(keypad_data->key_state));
/* clear pending interrupts */
- __raw_writel(__raw_readl(keypad_data->base + OMAP4_KBD_IRQSTATUS),
- keypad_data->base + OMAP4_KBD_IRQSTATUS);
+ kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS,
+ kbd_read_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS));
/* enable interrupts */
- __raw_writel(OMAP4_DEF_IRQENABLE_EVENTEN | OMAP4_DEF_IRQENABLE_LONGKEY,
- keypad_data->base + OMAP4_KBD_IRQENABLE);
+ kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQENABLE,
+ OMAP4_DEF_IRQENABLE_EVENTEN |
+ OMAP4_DEF_IRQENABLE_LONGKEY);
return IRQ_HANDLED;
}
@@ -139,16 +172,17 @@ static int omap4_keypad_open(struct input_dev *input)
disable_irq(keypad_data->irq);
- __raw_writel(OMAP4_VAL_FUNCTIONALCFG,
- keypad_data->base + OMAP4_KBD_CTRL);
- __raw_writel(OMAP4_VAL_DEBOUNCINGTIME,
- keypad_data->base + OMAP4_KBD_DEBOUNCINGTIME);
- __raw_writel(OMAP4_VAL_IRQDISABLE,
- keypad_data->base + OMAP4_KBD_IRQSTATUS);
- __raw_writel(OMAP4_DEF_IRQENABLE_EVENTEN | OMAP4_DEF_IRQENABLE_LONGKEY,
- keypad_data->base + OMAP4_KBD_IRQENABLE);
- __raw_writel(OMAP4_DEF_WUP_EVENT_ENA | OMAP4_DEF_WUP_LONG_KEY_ENA,
- keypad_data->base + OMAP4_KBD_WAKEUPENABLE);
+ kbd_writel(keypad_data, OMAP4_KBD_CTRL,
+ OMAP4_VAL_FUNCTIONALCFG);
+ kbd_writel(keypad_data, OMAP4_KBD_DEBOUNCINGTIME,
+ OMAP4_VAL_DEBOUNCINGTIME);
+ kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS,
+ OMAP4_VAL_IRQDISABLE);
+ kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQENABLE,
+ OMAP4_DEF_IRQENABLE_EVENTEN |
+ OMAP4_DEF_IRQENABLE_LONGKEY);
+ kbd_writel(keypad_data, OMAP4_KBD_WAKEUPENABLE,
+ OMAP4_DEF_WUP_EVENT_ENA | OMAP4_DEF_WUP_LONG_KEY_ENA);
enable_irq(keypad_data->irq);
@@ -162,12 +196,12 @@ static void omap4_keypad_close(struct input_dev *input)
disable_irq(keypad_data->irq);
/* Disable interrupts */
- __raw_writel(OMAP4_VAL_IRQDISABLE,
- keypad_data->base + OMAP4_KBD_IRQENABLE);
+ kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQENABLE,
+ OMAP4_VAL_IRQDISABLE);
/* clear pending interrupts */
- __raw_writel(__raw_readl(keypad_data->base + OMAP4_KBD_IRQSTATUS),
- keypad_data->base + OMAP4_KBD_IRQSTATUS);
+ kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS,
+ kbd_read_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS));
enable_irq(keypad_data->irq);
@@ -182,6 +216,7 @@ static int __devinit omap4_keypad_probe(struct platform_device *pdev)
struct resource *res;
resource_size_t size;
unsigned int row_shift, max_keys;
+ int rev;
int irq;
int error;
@@ -241,11 +276,40 @@ static int __devinit omap4_keypad_probe(struct platform_device *pdev)
keypad_data->rows = pdata->rows;
keypad_data->cols = pdata->cols;
+ /*
+ * Enable clocks for the keypad module so that we can read
+ * revision register.
+ */
+ pm_runtime_enable(&pdev->dev);
+ error = pm_runtime_get_sync(&pdev->dev);
+ if (error) {
+ dev_err(&pdev->dev, "pm_runtime_get_sync() failed\n");
+ goto err_unmap;
+ }
+ rev = __raw_readl(keypad_data->base + OMAP4_KBD_REVISION);
+ rev &= 0x03 << 30;
+ rev >>= 30;
+ switch (rev) {
+ case KBD_REVISION_OMAP4:
+ keypad_data->reg_offset = 0x00;
+ keypad_data->irqreg_offset = 0x00;
+ break;
+ case KBD_REVISION_OMAP5:
+ keypad_data->reg_offset = 0x10;
+ keypad_data->irqreg_offset = 0x0c;
+ break;
+ default:
+ dev_err(&pdev->dev,
+ "Keypad reports unsupported revision %d", rev);
+ error = -EINVAL;
+ goto err_pm_put_sync;
+ }
+
/* input device allocation */
keypad_data->input = input_dev = input_allocate_device();
if (!input_dev) {
error = -ENOMEM;
- goto err_unmap;
+ goto err_pm_put_sync;
}
input_dev->name = pdev->name;
@@ -280,7 +344,7 @@ static int __devinit omap4_keypad_probe(struct platform_device *pdev)
goto err_free_input;
}
- pm_runtime_enable(&pdev->dev);
+ pm_runtime_put_sync(&pdev->dev);
error = input_register_device(keypad_data->input);
if (error < 0) {
@@ -296,6 +360,8 @@ err_pm_disable:
free_irq(keypad_data->irq, keypad_data);
err_free_input:
input_free_device(input_dev);
+err_pm_put_sync:
+ pm_runtime_put_sync(&pdev->dev);
err_unmap:
iounmap(keypad_data->base);
err_release_mem:
--
1.7.1
^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [RESEND/PATCHv2] Input: omap-keypad: dynamically handle register offsets
2012-05-09 10:07 ` Poddar, Sourav
@ 2012-05-17 13:31 ` Poddar, Sourav
2012-05-17 15:25 ` Dmitry Torokhov
0 siblings, 1 reply; 11+ messages in thread
From: Poddar, Sourav @ 2012-05-17 13:31 UTC (permalink / raw)
To: Dmitry Torokhov; +Cc: linux-input, linux-omap, balbi, akpm
Hi Dmitry,
Gentle Ping on this..
~Sourav
On Wed, May 9, 2012 at 3:37 PM, Poddar, Sourav <sourav.poddar@ti.com> wrote:
> Hi Dmitry,
>
> On Wed, May 9, 2012 at 3:14 PM, Poddar, Sourav <sourav.poddar@ti.com> wrote:
>> Hi Dmitry,
>>
>> I did some minor fixes to the patch which you suggested above and
>> the keypad is functional now.
>>
>> Changes:
>> - Move "pm_runtime_enable" before using "pm_runtime_get_sync".
>>
>> Sending the patch inlined..(also attached).
>>
>> From: G, Manjunath Kondaiah <manjugk@ti.com>
>> Date: Mon, 10 Oct 2011 20:52:05 +0530
>> Subject: [PATCH] Input: omap-keypad: dynamically handle register offsets
>>
>> Keypad controller register offsets are different for omap4
>> and omap5. Handle these offsets through static mapping and
>> assign these mappings during run time.
>>
>> Tested on omap4430 sdp with 3.4-rc3.
>> Tested on omap5430evm with 3.1-custom kernel.
>>
>> Cc: Andrew Morton <akpm@linux-foundation.org>
>> Signed-off-by: Felipe Balbi <balbi@ti.com>
>> Signed-off-by: G, Manjunath Kondaiah <manjugk@ti.com>
>> Signed-off-by: Sourav Poddar <sourav.poddar@ti.com>
>> Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
>> ---
>> drivers/input/keyboard/Kconfig | 4 +-
>> drivers/input/keyboard/omap4-keypad.c | 120 +++++++++++++++++++++++++-------
>> 2 files changed, 95 insertions(+), 29 deletions(-)
>>
>> diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
>> index f354813..33bbdee 100644
>> --- a/drivers/input/keyboard/Kconfig
>> +++ b/drivers/input/keyboard/Kconfig
>> @@ -512,9 +512,9 @@ config KEYBOARD_OMAP
>> module will be called omap-keypad.
>>
>> config KEYBOARD_OMAP4
>> - tristate "TI OMAP4 keypad support"
>> + tristate "TI OMAP4+ keypad support"
>> help
>> - Say Y here if you want to use the OMAP4 keypad.
>> + Say Y here if you want to use the OMAP4+ keypad.
>>
>> To compile this driver as a module, choose M here: the
>> module will be called omap4-keypad.
>> diff --git a/drivers/input/keyboard/omap4-keypad.c
>> b/drivers/input/keyboard/omap4-keypad.c
>> index e809ac0..d7102e8 100644
>> --- a/drivers/input/keyboard/omap4-keypad.c
>> +++ b/drivers/input/keyboard/omap4-keypad.c
>> @@ -68,19 +68,52 @@
>>
>> #define OMAP4_MASK_IRQSTATUSDISABLE 0xFFFF
>>
>> +enum {
>> + KBD_REVISION_OMAP4 = 0,
>> + KBD_REVISION_OMAP5,
>> +};
>> +
>> struct omap4_keypad {
>> struct input_dev *input;
>>
>> void __iomem *base;
>> - int irq;
>> + unsigned int irq;
>>
>> unsigned int rows;
>> unsigned int cols;
>> + u32 reg_offset;
>> + u32 irqreg_offset;
>> unsigned int row_shift;
>> unsigned char key_state[8];
>> unsigned short keymap[];
>> };
>>
>> +static int kbd_readl(struct omap4_keypad *keypad_data, u32 offset)
>> +{
>> + return __raw_readl(keypad_data->base +
>> + keypad_data->reg_offset + offset);
>> +}
>> +
>> +static void kbd_writel(struct omap4_keypad *keypad_data, u32 offset, u32 value)
>> +{
>> + __raw_writel(value,
>> + keypad_data->base + keypad_data->reg_offset + offset);
>> +}
>> +
>> +static int kbd_read_irqreg(struct omap4_keypad *keypad_data, u32 offset)
>> +{
>> + return __raw_readl(keypad_data->base +
>> + keypad_data->irqreg_offset + offset);
>> +}
>> +
>> +static void kbd_write_irqreg(struct omap4_keypad *keypad_data,
>> + u32 offset, u32 value)
>> +{
>> + __raw_writel(value,
>> + keypad_data->base + keypad_data->irqreg_offset + offset);
>> +}
>> +
>> +
>> /* Interrupt handler */
>> static irqreturn_t omap4_keypad_interrupt(int irq, void *dev_id)
>> {
>> @@ -91,12 +124,11 @@ static irqreturn_t omap4_keypad_interrupt(int
>> irq, void *dev_id)
>> u32 *new_state = (u32 *) key_state;
>>
>> /* Disable interrupts */
>> - __raw_writel(OMAP4_VAL_IRQDISABLE,
>> - keypad_data->base + OMAP4_KBD_IRQENABLE);
>> + kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQENABLE,
>> + OMAP4_VAL_IRQDISABLE);
>>
>> - *new_state = __raw_readl(keypad_data->base + OMAP4_KBD_FULLCODE31_0);
>> - *(new_state + 1) = __raw_readl(keypad_data->base
>> - + OMAP4_KBD_FULLCODE63_32);
>> + *new_state = kbd_readl(keypad_data, OMAP4_KBD_FULLCODE31_0);
>> + *(new_state + 1) = kbd_readl(keypad_data, OMAP4_KBD_FULLCODE63_32);
>>
>> for (row = 0; row < keypad_data->rows; row++) {
>> changed = key_state[row] ^ keypad_data->key_state[row];
>> @@ -121,12 +153,13 @@ static irqreturn_t omap4_keypad_interrupt(int
>> irq, void *dev_id)
>> sizeof(keypad_data->key_state));
>>
>> /* clear pending interrupts */
>> - __raw_writel(__raw_readl(keypad_data->base + OMAP4_KBD_IRQSTATUS),
>> - keypad_data->base + OMAP4_KBD_IRQSTATUS);
>> + kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS,
>> + kbd_read_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS));
>>
>> /* enable interrupts */
>> - __raw_writel(OMAP4_DEF_IRQENABLE_EVENTEN | OMAP4_DEF_IRQENABLE_LONGKEY,
>> - keypad_data->base + OMAP4_KBD_IRQENABLE);
>> + kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQENABLE,
>> + OMAP4_DEF_IRQENABLE_EVENTEN |
>> + OMAP4_DEF_IRQENABLE_LONGKEY);
>>
>> return IRQ_HANDLED;
>> }
>> @@ -139,16 +172,17 @@ static int omap4_keypad_open(struct input_dev *input)
>>
>> disable_irq(keypad_data->irq);
>>
>> - __raw_writel(OMAP4_VAL_FUNCTIONALCFG,
>> - keypad_data->base + OMAP4_KBD_CTRL);
>> - __raw_writel(OMAP4_VAL_DEBOUNCINGTIME,
>> - keypad_data->base + OMAP4_KBD_DEBOUNCINGTIME);
>> - __raw_writel(OMAP4_VAL_IRQDISABLE,
>> - keypad_data->base + OMAP4_KBD_IRQSTATUS);
>> - __raw_writel(OMAP4_DEF_IRQENABLE_EVENTEN | OMAP4_DEF_IRQENABLE_LONGKEY,
>> - keypad_data->base + OMAP4_KBD_IRQENABLE);
>> - __raw_writel(OMAP4_DEF_WUP_EVENT_ENA | OMAP4_DEF_WUP_LONG_KEY_ENA,
>> - keypad_data->base + OMAP4_KBD_WAKEUPENABLE);
>> + kbd_writel(keypad_data, OMAP4_KBD_CTRL,
>> + OMAP4_VAL_FUNCTIONALCFG);
>> + kbd_writel(keypad_data, OMAP4_KBD_DEBOUNCINGTIME,
>> + OMAP4_VAL_DEBOUNCINGTIME);
>> + kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS,
>> + OMAP4_VAL_IRQDISABLE);
>> + kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQENABLE,
>> + OMAP4_DEF_IRQENABLE_EVENTEN |
>> + OMAP4_DEF_IRQENABLE_LONGKEY);
>> + kbd_writel(keypad_data, OMAP4_KBD_WAKEUPENABLE,
>> + OMAP4_DEF_WUP_EVENT_ENA | OMAP4_DEF_WUP_LONG_KEY_ENA);
>>
>> enable_irq(keypad_data->irq);
>>
>> @@ -162,12 +196,12 @@ static void omap4_keypad_close(struct input_dev *input)
>> disable_irq(keypad_data->irq);
>>
>> /* Disable interrupts */
>> - __raw_writel(OMAP4_VAL_IRQDISABLE,
>> - keypad_data->base + OMAP4_KBD_IRQENABLE);
>> + kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQENABLE,
>> + OMAP4_VAL_IRQDISABLE);
>>
>> /* clear pending interrupts */
>> - __raw_writel(__raw_readl(keypad_data->base + OMAP4_KBD_IRQSTATUS),
>> - keypad_data->base + OMAP4_KBD_IRQSTATUS);
>> + kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS,
>> + kbd_read_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS));
>>
>> enable_irq(keypad_data->irq);
>>
>> @@ -182,6 +216,7 @@ static int __devinit omap4_keypad_probe(struct
>> platform_device *pdev)
>> struct resource *res;
>> resource_size_t size;
>> unsigned int row_shift, max_keys;
>> + int rev;
>> int irq;
>> int error;
>>
>> @@ -241,11 +276,40 @@ static int __devinit omap4_keypad_probe(struct
>> platform_device *pdev)
>> keypad_data->rows = pdata->rows;
>> keypad_data->cols = pdata->cols;
>>
>> + /*
>> + * Enable clocks for the keypad module so that we can read
>> + * revision register.
>> + */
>> + pm_runtime_enable(&pdev->dev);
>> + error = pm_runtime_get_sync(&pdev->dev);
>> + if (error) {
>> + dev_err(&pdev->dev, "pm_runtime_get_sync() failed\n");
>> + goto err_unmap;
>> + }
>> + rev = __raw_readl(keypad_data->base + OMAP4_KBD_REVISION);
>> + rev &= 0x03 << 30;
>> + rev >>= 30;
>> + switch (rev) {
>> + case KBD_REVISION_OMAP4:
>> + keypad_data->reg_offset = 0x00;
>> + keypad_data->irqreg_offset = 0x00;
>> + break;
>> + case KBD_REVISION_OMAP5:
>> + keypad_data->reg_offset = 0x10;
>> + keypad_data->irqreg_offset = 0x0c;
>> + break;
>> + default:
>> + dev_err(&pdev->dev,
>> + "Keypad reports unsupported revision %d", rev);
>> + error = -EINVAL;
>> + goto err_pm_put_sync;
>> + }
>> +
>> /* input device allocation */
>> keypad_data->input = input_dev = input_allocate_device();
>> if (!input_dev) {
>> error = -ENOMEM;
>> - goto err_unmap;
>> + goto err_pm_put_sync;
>> }
>>
>> input_dev->name = pdev->name;
>> @@ -273,14 +337,14 @@ static int __devinit omap4_keypad_probe(struct
>> platform_device *pdev)
>> input_dev->keycode, input_dev->keybit);
>>
>> error = request_irq(keypad_data->irq, omap4_keypad_interrupt,
>> - IRQF_TRIGGER_RISING,
>> + IRQF_DISABLED | IRQF_TRIGGER_RISING,
> Sorry, " IRQF_DISABLED" got included by mistake.
> Removing this stray change and sending it again.
>
>> "omap4-keypad", keypad_data);
>> if (error) {
>> dev_err(&pdev->dev, "failed to register interrupt\n");
>> goto err_free_input;
>> }
>>
>> - pm_runtime_enable(&pdev->dev);
>> + pm_runtime_put_sync(&pdev->dev);
>>
>> error = input_register_device(keypad_data->input);
>> if (error < 0) {
>> @@ -296,6 +360,8 @@ err_pm_disable:
>> free_irq(keypad_data->irq, keypad_data);
>> err_free_input:
>> input_free_device(input_dev);
>> +err_pm_put_sync:
>> + pm_runtime_put_sync(&pdev->dev);
>> err_unmap:
>> iounmap(keypad_data->base);
>> err_release_mem:
>>
>>
>> ~Sourav
>>
>> On Wed, May 9, 2012 at 1:15 PM, Dmitry Torokhov
>> <dmitry.torokhov@gmail.com> wrote:
>>>> Hi Dmitry ,
>>>>
>>>>
>>>> On Wed, May 9, 2012 at 10:48 AM, Dmitry Torokhov
>>>> <dmitry.torokhov@gmail.com> wrote:
>>>> > Ho Sourav,
>>>> >
>>>> > On Thu, Apr 26, 2012 at 11:24:37AM +0530, Sourav Poddar wrote:
>>>> >>
>>>> >> -config KEYBOARD_OMAP4
>>>> >> - tristate "TI OMAP4 keypad support"
>>>> >> +config KEYBOARD_OMAP4+
>>>> >
>>>> > I think this works purely by accident - '+' sign getting dropped by
>>>> > parser...
>>>> >
>>>> >> @@ -139,16 +192,33 @@ static int omap4_keypad_open(struct input_dev *input)
>>>> >>
>>>> >> disable_irq(keypad_data->irq);
>>>> >>
>>>> >> - __raw_writel(OMAP4_VAL_FUNCTIONALCFG,
>>>> >> - keypad_data->base + OMAP4_KBD_CTRL);
>>>> >> - __raw_writel(OMAP4_VAL_DEBOUNCINGTIME,
>>>> >> - keypad_data->base + OMAP4_KBD_DEBOUNCINGTIME);
>>>> >> - __raw_writel(OMAP4_VAL_IRQDISABLE,
>>>> >> - keypad_data->base + OMAP4_KBD_IRQSTATUS);
>>>> >> - __raw_writel(OMAP4_DEF_IRQENABLE_EVENTEN | OMAP4_DEF_IRQENABLE_LONGKEY,
>>>> >> - keypad_data->base + OMAP4_KBD_IRQENABLE);
>>>> >> - __raw_writel(OMAP4_DEF_WUP_EVENT_ENA | OMAP4_DEF_WUP_LONG_KEY_ENA,
>>>> >> - keypad_data->base + OMAP4_KBD_WAKEUPENABLE);
>>>> >> + keypad_data->revision = kbd_read_revision(keypad_data,
>>>> >> + OMAP4_KBD_REVISION);
>>>> >> + switch (keypad_data->revision) {
>>>> >> + case 1:
>>>> >> + keypad_data->irqstatus = OMAP4_KBD_IRQSTATUS + 0x0c;
>>>> >> + keypad_data->irqenable = OMAP4_KBD_IRQENABLE + 0x0c;
>>>> >> + keypad_data->reg_offset = 0x10;
>>>> >> + break;
>>>> >
>>>> > This should be done in probe().
>>>> >
>>>> Dont we then require "pm_runtime_put_sync" in probe, since we are trying
>>>> to read the keypad revision register.?
>>>
>>> Ah, indeed, but I think not pm_runtime_get_sync() but
>>> pm_runtime_set_active().
>>>
>>> Not sure if this will fix the crash...
>>>
>>> --
>>> Dmitry
>>>
>>>
>>> Input: omap-keypad - dynamically handle register offsets
>>>
>>> From: G, Manjunath Kondaiah <manjugk@ti.com>
>>>
>>> Keypad controller register offsets are different for omap4
>>> and omap5. Handle these offsets through static mapping and
>>> assign these mappings during run time.
>>>
>>> Tested on omap4430 sdp with 3.4-rc3.
>>> Tested on omap5430evm with 3.1-custom kernel.
>>>
>>> Signed-off-by: Felipe Balbi <balbi@ti.com>
>>> Signed-off-by: G, Manjunath Kondaiah <manjugk@ti.com>
>>> Signed-off-by: Sourav Poddar <sourav.poddar@ti.com>
>>> Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
>>> ---
>>>
>>> drivers/input/keyboard/Kconfig | 4 +
>>> drivers/input/keyboard/omap4-keypad.c | 117 ++++++++++++++++++++++++++-------
>>> 2 files changed, 94 insertions(+), 27 deletions(-)
>>>
>>>
>>> diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
>>> index 20a3753..84ee155 100644
>>> --- a/drivers/input/keyboard/Kconfig
>>> +++ b/drivers/input/keyboard/Kconfig
>>> @@ -531,9 +531,9 @@ config KEYBOARD_OMAP
>>> module will be called omap-keypad.
>>>
>>> config KEYBOARD_OMAP4
>>> - tristate "TI OMAP4 keypad support"
>>> + tristate "TI OMAP4+ keypad support"
>>> help
>>> - Say Y here if you want to use the OMAP4 keypad.
>>> + Say Y here if you want to use the OMAP4+ keypad.
>>>
>>> To compile this driver as a module, choose M here: the
>>> module will be called omap4-keypad.
>>> diff --git a/drivers/input/keyboard/omap4-keypad.c b/drivers/input/keyboard/omap4-keypad.c
>>> index e809ac0..c9fd0df 100644
>>> --- a/drivers/input/keyboard/omap4-keypad.c
>>> +++ b/drivers/input/keyboard/omap4-keypad.c
>>> @@ -68,19 +68,52 @@
>>>
>>> #define OMAP4_MASK_IRQSTATUSDISABLE 0xFFFF
>>>
>>> +enum {
>>> + KBD_REVISION_OMAP4 = 0,
>>> + KBD_REVISION_OMAP5,
>>> +};
>>> +
>>> struct omap4_keypad {
>>> struct input_dev *input;
>>>
>>> void __iomem *base;
>>> - int irq;
>>> + unsigned int irq;
>>>
>>> unsigned int rows;
>>> unsigned int cols;
>>> + u32 reg_offset;
>>> + u32 irqreg_offset;
>>> unsigned int row_shift;
>>> unsigned char key_state[8];
>>> unsigned short keymap[];
>>> };
>>>
>>> +static int kbd_readl(struct omap4_keypad *keypad_data, u32 offset)
>>> +{
>>> + return __raw_readl(keypad_data->base +
>>> + keypad_data->reg_offset + offset);
>>> +}
>>> +
>>> +static void kbd_writel(struct omap4_keypad *keypad_data, u32 offset, u32 value)
>>> +{
>>> + __raw_writel(value,
>>> + keypad_data->base + keypad_data->reg_offset + offset);
>>> +}
>>> +
>>> +static int kbd_read_irqreg(struct omap4_keypad *keypad_data, u32 offset)
>>> +{
>>> + return __raw_readl(keypad_data->base +
>>> + keypad_data->irqreg_offset + offset);
>>> +}
>>> +
>>> +static void kbd_write_irqreg(struct omap4_keypad *keypad_data,
>>> + u32 offset, u32 value)
>>> +{
>>> + __raw_writel(value,
>>> + keypad_data->base + keypad_data->irqreg_offset + offset);
>>> +}
>>> +
>>> +
>>> /* Interrupt handler */
>>> static irqreturn_t omap4_keypad_interrupt(int irq, void *dev_id)
>>> {
>>> @@ -91,12 +124,11 @@ static irqreturn_t omap4_keypad_interrupt(int irq, void *dev_id)
>>> u32 *new_state = (u32 *) key_state;
>>>
>>> /* Disable interrupts */
>>> - __raw_writel(OMAP4_VAL_IRQDISABLE,
>>> - keypad_data->base + OMAP4_KBD_IRQENABLE);
>>> + kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQENABLE,
>>> + OMAP4_VAL_IRQDISABLE);
>>>
>>> - *new_state = __raw_readl(keypad_data->base + OMAP4_KBD_FULLCODE31_0);
>>> - *(new_state + 1) = __raw_readl(keypad_data->base
>>> - + OMAP4_KBD_FULLCODE63_32);
>>> + *new_state = kbd_readl(keypad_data, OMAP4_KBD_FULLCODE31_0);
>>> + *(new_state + 1) = kbd_readl(keypad_data, OMAP4_KBD_FULLCODE63_32);
>>>
>>> for (row = 0; row < keypad_data->rows; row++) {
>>> changed = key_state[row] ^ keypad_data->key_state[row];
>>> @@ -121,12 +153,13 @@ static irqreturn_t omap4_keypad_interrupt(int irq, void *dev_id)
>>> sizeof(keypad_data->key_state));
>>>
>>> /* clear pending interrupts */
>>> - __raw_writel(__raw_readl(keypad_data->base + OMAP4_KBD_IRQSTATUS),
>>> - keypad_data->base + OMAP4_KBD_IRQSTATUS);
>>> + kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS,
>>> + kbd_read_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS));
>>>
>>> /* enable interrupts */
>>> - __raw_writel(OMAP4_DEF_IRQENABLE_EVENTEN | OMAP4_DEF_IRQENABLE_LONGKEY,
>>> - keypad_data->base + OMAP4_KBD_IRQENABLE);
>>> + kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQENABLE,
>>> + OMAP4_DEF_IRQENABLE_EVENTEN |
>>> + OMAP4_DEF_IRQENABLE_LONGKEY);
>>>
>>> return IRQ_HANDLED;
>>> }
>>> @@ -139,16 +172,17 @@ static int omap4_keypad_open(struct input_dev *input)
>>>
>>> disable_irq(keypad_data->irq);
>>>
>>> - __raw_writel(OMAP4_VAL_FUNCTIONALCFG,
>>> - keypad_data->base + OMAP4_KBD_CTRL);
>>> - __raw_writel(OMAP4_VAL_DEBOUNCINGTIME,
>>> - keypad_data->base + OMAP4_KBD_DEBOUNCINGTIME);
>>> - __raw_writel(OMAP4_VAL_IRQDISABLE,
>>> - keypad_data->base + OMAP4_KBD_IRQSTATUS);
>>> - __raw_writel(OMAP4_DEF_IRQENABLE_EVENTEN | OMAP4_DEF_IRQENABLE_LONGKEY,
>>> - keypad_data->base + OMAP4_KBD_IRQENABLE);
>>> - __raw_writel(OMAP4_DEF_WUP_EVENT_ENA | OMAP4_DEF_WUP_LONG_KEY_ENA,
>>> - keypad_data->base + OMAP4_KBD_WAKEUPENABLE);
>>> + kbd_writel(keypad_data, OMAP4_KBD_CTRL,
>>> + OMAP4_VAL_FUNCTIONALCFG);
>>> + kbd_writel(keypad_data, OMAP4_KBD_DEBOUNCINGTIME,
>>> + OMAP4_VAL_DEBOUNCINGTIME);
>>> + kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS,
>>> + OMAP4_VAL_IRQDISABLE);
>>> + kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQENABLE,
>>> + OMAP4_DEF_IRQENABLE_EVENTEN |
>>> + OMAP4_DEF_IRQENABLE_LONGKEY);
>>> + kbd_writel(keypad_data, OMAP4_KBD_WAKEUPENABLE,
>>> + OMAP4_DEF_WUP_EVENT_ENA | OMAP4_DEF_WUP_LONG_KEY_ENA);
>>>
>>> enable_irq(keypad_data->irq);
>>>
>>> @@ -162,12 +196,12 @@ static void omap4_keypad_close(struct input_dev *input)
>>> disable_irq(keypad_data->irq);
>>>
>>> /* Disable interrupts */
>>> - __raw_writel(OMAP4_VAL_IRQDISABLE,
>>> - keypad_data->base + OMAP4_KBD_IRQENABLE);
>>> + kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQENABLE,
>>> + OMAP4_VAL_IRQDISABLE);
>>>
>>> /* clear pending interrupts */
>>> - __raw_writel(__raw_readl(keypad_data->base + OMAP4_KBD_IRQSTATUS),
>>> - keypad_data->base + OMAP4_KBD_IRQSTATUS);
>>> + kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS,
>>> + kbd_read_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS));
>>>
>>> enable_irq(keypad_data->irq);
>>>
>>> @@ -182,6 +216,7 @@ static int __devinit omap4_keypad_probe(struct platform_device *pdev)
>>> struct resource *res;
>>> resource_size_t size;
>>> unsigned int row_shift, max_keys;
>>> + int rev;
>>> int irq;
>>> int error;
>>>
>>> @@ -241,11 +276,40 @@ static int __devinit omap4_keypad_probe(struct platform_device *pdev)
>>> keypad_data->rows = pdata->rows;
>>> keypad_data->cols = pdata->cols;
>>>
>>> + /*
>>> + * Mark device as active (and wake up its parent) so we can read
>>> + * revision register.
>>> + */
>>> + error = pm_runtime_set_active(&pdev->dev);
>>> + if (error) {
>>> + dev_err(&pdev->dev, "pm_runtime_set_active() failed\n");
>>> + goto err_unmap;
>>> + }
>>> +
>>> + rev = __raw_readl(keypad_data->base + OMAP4_KBD_REVISION);
>>> + rev &= 0x03 << 30;
>>> + rev >>= 30;
>>> + switch (rev) {
>>> + case KBD_REVISION_OMAP4:
>>> + keypad_data->reg_offset = 0x00;
>>> + keypad_data->irqreg_offset = 0x00;
>>> + break;
>>> + case KBD_REVISION_OMAP5:
>>> + keypad_data->reg_offset = 0x10;
>>> + keypad_data->irqreg_offset = 0x0c;
>>> + break;
>>> + default:
>>> + dev_err(&pdev->dev,
>>> + "Keypad reports unsupported revision %d", rev);
>>> + error = -EINVAL;
>>> + goto err_pm_suspended;
>>> + }
>>> +
>>> /* input device allocation */
>>> keypad_data->input = input_dev = input_allocate_device();
>>> if (!input_dev) {
>>> error = -ENOMEM;
>>> - goto err_unmap;
>>> + goto err_pm_suspended;
>>> }
>>>
>>> input_dev->name = pdev->name;
>>> @@ -281,6 +345,7 @@ static int __devinit omap4_keypad_probe(struct platform_device *pdev)
>>> }
>>>
>>> pm_runtime_enable(&pdev->dev);
>>> + pm_runtime_put_sync(&pdev->dev);
>>>
>>> error = input_register_device(keypad_data->input);
>>> if (error < 0) {
>>> @@ -296,6 +361,8 @@ err_pm_disable:
>>> free_irq(keypad_data->irq, keypad_data);
>>> err_free_input:
>>> input_free_device(input_dev);
>>> +err_pm_suspended:
>>> + pm_runtime_set_suspended(&pdev->dev);
>>> err_unmap:
>>> iounmap(keypad_data->base);
>>> err_release_mem:
>
> From: G, Manjunath Kondaiah <manjugk@ti.com>
> Date: Mon, 10 Oct 2011 20:52:05 +0530
> Subject: [PATCH] Input: omap-keypad: dynamically handle register offsets
>
> Keypad controller register offsets are different for omap4
> and omap5. Handle these offsets through static mapping and
> assign these mappings during run time.
>
> Tested on omap4430 sdp with 3.4-rc3.
> Tested on omap5430evm with 3.1-custom kernel.
>
> Cc: Andrew Morton <akpm@linux-foundation.org>
> Signed-off-by: Felipe Balbi <balbi@ti.com>
> Signed-off-by: G, Manjunath Kondaiah <manjugk@ti.com>
> Signed-off-by: Sourav Poddar <sourav.poddar@ti.com>
> Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
> ---
> drivers/input/keyboard/Kconfig | 4 +-
> drivers/input/keyboard/omap4-keypad.c | 118 +++++++++++++++++++++++++-------
> 2 files changed, 94 insertions(+), 28 deletions(-)
>
> diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
> index f354813..33bbdee 100644
> --- a/drivers/input/keyboard/Kconfig
> +++ b/drivers/input/keyboard/Kconfig
> @@ -512,9 +512,9 @@ config KEYBOARD_OMAP
> module will be called omap-keypad.
>
> config KEYBOARD_OMAP4
> - tristate "TI OMAP4 keypad support"
> + tristate "TI OMAP4+ keypad support"
> help
> - Say Y here if you want to use the OMAP4 keypad.
> + Say Y here if you want to use the OMAP4+ keypad.
>
> To compile this driver as a module, choose M here: the
> module will be called omap4-keypad.
> diff --git a/drivers/input/keyboard/omap4-keypad.c
> b/drivers/input/keyboard/omap4-keypad.c
> index e809ac0..28da0e4 100644
> --- a/drivers/input/keyboard/omap4-keypad.c
> +++ b/drivers/input/keyboard/omap4-keypad.c
> @@ -68,19 +68,52 @@
>
> #define OMAP4_MASK_IRQSTATUSDISABLE 0xFFFF
>
> +enum {
> + KBD_REVISION_OMAP4 = 0,
> + KBD_REVISION_OMAP5,
> +};
> +
> struct omap4_keypad {
> struct input_dev *input;
>
> void __iomem *base;
> - int irq;
> + unsigned int irq;
>
> unsigned int rows;
> unsigned int cols;
> + u32 reg_offset;
> + u32 irqreg_offset;
> unsigned int row_shift;
> unsigned char key_state[8];
> unsigned short keymap[];
> };
>
> +static int kbd_readl(struct omap4_keypad *keypad_data, u32 offset)
> +{
> + return __raw_readl(keypad_data->base +
> + keypad_data->reg_offset + offset);
> +}
> +
> +static void kbd_writel(struct omap4_keypad *keypad_data, u32 offset, u32 value)
> +{
> + __raw_writel(value,
> + keypad_data->base + keypad_data->reg_offset + offset);
> +}
> +
> +static int kbd_read_irqreg(struct omap4_keypad *keypad_data, u32 offset)
> +{
> + return __raw_readl(keypad_data->base +
> + keypad_data->irqreg_offset + offset);
> +}
> +
> +static void kbd_write_irqreg(struct omap4_keypad *keypad_data,
> + u32 offset, u32 value)
> +{
> + __raw_writel(value,
> + keypad_data->base + keypad_data->irqreg_offset + offset);
> +}
> +
> +
> /* Interrupt handler */
> static irqreturn_t omap4_keypad_interrupt(int irq, void *dev_id)
> {
> @@ -91,12 +124,11 @@ static irqreturn_t omap4_keypad_interrupt(int
> irq, void *dev_id)
> u32 *new_state = (u32 *) key_state;
>
> /* Disable interrupts */
> - __raw_writel(OMAP4_VAL_IRQDISABLE,
> - keypad_data->base + OMAP4_KBD_IRQENABLE);
> + kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQENABLE,
> + OMAP4_VAL_IRQDISABLE);
>
> - *new_state = __raw_readl(keypad_data->base + OMAP4_KBD_FULLCODE31_0);
> - *(new_state + 1) = __raw_readl(keypad_data->base
> - + OMAP4_KBD_FULLCODE63_32);
> + *new_state = kbd_readl(keypad_data, OMAP4_KBD_FULLCODE31_0);
> + *(new_state + 1) = kbd_readl(keypad_data, OMAP4_KBD_FULLCODE63_32);
>
> for (row = 0; row < keypad_data->rows; row++) {
> changed = key_state[row] ^ keypad_data->key_state[row];
> @@ -121,12 +153,13 @@ static irqreturn_t omap4_keypad_interrupt(int
> irq, void *dev_id)
> sizeof(keypad_data->key_state));
>
> /* clear pending interrupts */
> - __raw_writel(__raw_readl(keypad_data->base + OMAP4_KBD_IRQSTATUS),
> - keypad_data->base + OMAP4_KBD_IRQSTATUS);
> + kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS,
> + kbd_read_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS));
>
> /* enable interrupts */
> - __raw_writel(OMAP4_DEF_IRQENABLE_EVENTEN | OMAP4_DEF_IRQENABLE_LONGKEY,
> - keypad_data->base + OMAP4_KBD_IRQENABLE);
> + kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQENABLE,
> + OMAP4_DEF_IRQENABLE_EVENTEN |
> + OMAP4_DEF_IRQENABLE_LONGKEY);
>
> return IRQ_HANDLED;
> }
> @@ -139,16 +172,17 @@ static int omap4_keypad_open(struct input_dev *input)
>
> disable_irq(keypad_data->irq);
>
> - __raw_writel(OMAP4_VAL_FUNCTIONALCFG,
> - keypad_data->base + OMAP4_KBD_CTRL);
> - __raw_writel(OMAP4_VAL_DEBOUNCINGTIME,
> - keypad_data->base + OMAP4_KBD_DEBOUNCINGTIME);
> - __raw_writel(OMAP4_VAL_IRQDISABLE,
> - keypad_data->base + OMAP4_KBD_IRQSTATUS);
> - __raw_writel(OMAP4_DEF_IRQENABLE_EVENTEN | OMAP4_DEF_IRQENABLE_LONGKEY,
> - keypad_data->base + OMAP4_KBD_IRQENABLE);
> - __raw_writel(OMAP4_DEF_WUP_EVENT_ENA | OMAP4_DEF_WUP_LONG_KEY_ENA,
> - keypad_data->base + OMAP4_KBD_WAKEUPENABLE);
> + kbd_writel(keypad_data, OMAP4_KBD_CTRL,
> + OMAP4_VAL_FUNCTIONALCFG);
> + kbd_writel(keypad_data, OMAP4_KBD_DEBOUNCINGTIME,
> + OMAP4_VAL_DEBOUNCINGTIME);
> + kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS,
> + OMAP4_VAL_IRQDISABLE);
> + kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQENABLE,
> + OMAP4_DEF_IRQENABLE_EVENTEN |
> + OMAP4_DEF_IRQENABLE_LONGKEY);
> + kbd_writel(keypad_data, OMAP4_KBD_WAKEUPENABLE,
> + OMAP4_DEF_WUP_EVENT_ENA | OMAP4_DEF_WUP_LONG_KEY_ENA);
>
> enable_irq(keypad_data->irq);
>
> @@ -162,12 +196,12 @@ static void omap4_keypad_close(struct input_dev *input)
> disable_irq(keypad_data->irq);
>
> /* Disable interrupts */
> - __raw_writel(OMAP4_VAL_IRQDISABLE,
> - keypad_data->base + OMAP4_KBD_IRQENABLE);
> + kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQENABLE,
> + OMAP4_VAL_IRQDISABLE);
>
> /* clear pending interrupts */
> - __raw_writel(__raw_readl(keypad_data->base + OMAP4_KBD_IRQSTATUS),
> - keypad_data->base + OMAP4_KBD_IRQSTATUS);
> + kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS,
> + kbd_read_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS));
>
> enable_irq(keypad_data->irq);
>
> @@ -182,6 +216,7 @@ static int __devinit omap4_keypad_probe(struct
> platform_device *pdev)
> struct resource *res;
> resource_size_t size;
> unsigned int row_shift, max_keys;
> + int rev;
> int irq;
> int error;
>
> @@ -241,11 +276,40 @@ static int __devinit omap4_keypad_probe(struct
> platform_device *pdev)
> keypad_data->rows = pdata->rows;
> keypad_data->cols = pdata->cols;
>
> + /*
> + * Enable clocks for the keypad module so that we can read
> + * revision register.
> + */
> + pm_runtime_enable(&pdev->dev);
> + error = pm_runtime_get_sync(&pdev->dev);
> + if (error) {
> + dev_err(&pdev->dev, "pm_runtime_get_sync() failed\n");
> + goto err_unmap;
> + }
> + rev = __raw_readl(keypad_data->base + OMAP4_KBD_REVISION);
> + rev &= 0x03 << 30;
> + rev >>= 30;
> + switch (rev) {
> + case KBD_REVISION_OMAP4:
> + keypad_data->reg_offset = 0x00;
> + keypad_data->irqreg_offset = 0x00;
> + break;
> + case KBD_REVISION_OMAP5:
> + keypad_data->reg_offset = 0x10;
> + keypad_data->irqreg_offset = 0x0c;
> + break;
> + default:
> + dev_err(&pdev->dev,
> + "Keypad reports unsupported revision %d", rev);
> + error = -EINVAL;
> + goto err_pm_put_sync;
> + }
> +
> /* input device allocation */
> keypad_data->input = input_dev = input_allocate_device();
> if (!input_dev) {
> error = -ENOMEM;
> - goto err_unmap;
> + goto err_pm_put_sync;
> }
>
> input_dev->name = pdev->name;
> @@ -280,7 +344,7 @@ static int __devinit omap4_keypad_probe(struct
> platform_device *pdev)
> goto err_free_input;
> }
>
> - pm_runtime_enable(&pdev->dev);
> + pm_runtime_put_sync(&pdev->dev);
>
> error = input_register_device(keypad_data->input);
> if (error < 0) {
> @@ -296,6 +360,8 @@ err_pm_disable:
> free_irq(keypad_data->irq, keypad_data);
> err_free_input:
> input_free_device(input_dev);
> +err_pm_put_sync:
> + pm_runtime_put_sync(&pdev->dev);
> err_unmap:
> iounmap(keypad_data->base);
> err_release_mem:
> --
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [RESEND/PATCHv2] Input: omap-keypad: dynamically handle register offsets
2012-05-17 13:31 ` Poddar, Sourav
@ 2012-05-17 15:25 ` Dmitry Torokhov
2012-05-18 4:34 ` Poddar, Sourav
0 siblings, 1 reply; 11+ messages in thread
From: Dmitry Torokhov @ 2012-05-17 15:25 UTC (permalink / raw)
To: Poddar, Sourav; +Cc: linux-input, linux-omap, balbi, akpm
Hi Sourav,
On Thu, May 17, 2012 at 07:01:49PM +0530, Poddar, Sourav wrote:
> Hi Dmitry,
>
> Gentle Ping on this..
The patch has been committed to my 'next' branch for 3.5 on 05/11/12:
http://git.kernel.org/?p=linux/kernel/git/dtor/input.git;a=commit;h=f77621cc640a7c50b3d8c5254ecc5d91eaa99d0d
Thanks.
--
Dmitry
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [RESEND/PATCHv2] Input: omap-keypad: dynamically handle register offsets
2012-05-17 15:25 ` Dmitry Torokhov
@ 2012-05-18 4:34 ` Poddar, Sourav
0 siblings, 0 replies; 11+ messages in thread
From: Poddar, Sourav @ 2012-05-18 4:34 UTC (permalink / raw)
To: Dmitry Torokhov; +Cc: linux-input, linux-omap, balbi, akpm
On Thu, May 17, 2012 at 8:55 PM, Dmitry Torokhov
<dmitry.torokhov@gmail.com> wrote:
> Hi Sourav,
>
> On Thu, May 17, 2012 at 07:01:49PM +0530, Poddar, Sourav wrote:
>> Hi Dmitry,
>>
>> Gentle Ping on this..
>
> The patch has been committed to my 'next' branch for 3.5 on 05/11/12:
>
Thanks.
> http://git.kernel.org/?p=linux/kernel/git/dtor/input.git;a=commit;h=f77621cc640a7c50b3d8c5254ecc5d91eaa99d0d
>
> Thanks.
>
> --
> Dmitry
^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2012-05-18 4:34 UTC | newest]
Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-04-26 5:54 [RESEND/PATCHv2] Input: omap-keypad: dynamically handle register offsets Sourav Poddar
2012-05-08 17:26 ` Poddar, Sourav
2012-05-09 5:18 ` Dmitry Torokhov
2012-05-09 6:54 ` Poddar, Sourav
2012-05-09 7:07 ` Poddar, Sourav
2012-05-09 7:45 ` Dmitry Torokhov
2012-05-09 9:44 ` Poddar, Sourav
2012-05-09 10:07 ` Poddar, Sourav
2012-05-17 13:31 ` Poddar, Sourav
2012-05-17 15:25 ` Dmitry Torokhov
2012-05-18 4:34 ` Poddar, Sourav
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).