2010-08-31 18:05:27 -06:00
|
|
|
/*
|
|
|
|
* OMAP4 Keypad Driver
|
|
|
|
*
|
|
|
|
* Copyright (C) 2010 Texas Instruments
|
|
|
|
*
|
|
|
|
* Author: Abraham Arce <x0066660@ti.com>
|
|
|
|
* Initial Code: Syed Rafiuddin <rafiuddin.syed@ti.com>
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <linux/module.h>
|
|
|
|
#include <linux/init.h>
|
|
|
|
#include <linux/interrupt.h>
|
|
|
|
#include <linux/platform_device.h>
|
|
|
|
#include <linux/errno.h>
|
|
|
|
#include <linux/io.h>
|
2012-07-13 01:10:47 -06:00
|
|
|
#include <linux/of.h>
|
2010-08-31 18:05:27 -06:00
|
|
|
#include <linux/input.h>
|
|
|
|
#include <linux/slab.h>
|
2011-02-22 23:25:59 -07:00
|
|
|
#include <linux/pm_runtime.h>
|
2010-08-31 18:05:27 -06:00
|
|
|
|
2012-03-16 23:47:48 -06:00
|
|
|
#include <linux/platform_data/omap4-keypad.h>
|
2010-08-31 18:05:27 -06:00
|
|
|
|
|
|
|
/* OMAP4 registers */
|
|
|
|
#define OMAP4_KBD_REVISION 0x00
|
|
|
|
#define OMAP4_KBD_SYSCONFIG 0x10
|
|
|
|
#define OMAP4_KBD_SYSSTATUS 0x14
|
|
|
|
#define OMAP4_KBD_IRQSTATUS 0x18
|
|
|
|
#define OMAP4_KBD_IRQENABLE 0x1C
|
|
|
|
#define OMAP4_KBD_WAKEUPENABLE 0x20
|
|
|
|
#define OMAP4_KBD_PENDING 0x24
|
|
|
|
#define OMAP4_KBD_CTRL 0x28
|
|
|
|
#define OMAP4_KBD_DEBOUNCINGTIME 0x2C
|
|
|
|
#define OMAP4_KBD_LONGKEYTIME 0x30
|
|
|
|
#define OMAP4_KBD_TIMEOUT 0x34
|
|
|
|
#define OMAP4_KBD_STATEMACHINE 0x38
|
|
|
|
#define OMAP4_KBD_ROWINPUTS 0x3C
|
|
|
|
#define OMAP4_KBD_COLUMNOUTPUTS 0x40
|
|
|
|
#define OMAP4_KBD_FULLCODE31_0 0x44
|
|
|
|
#define OMAP4_KBD_FULLCODE63_32 0x48
|
|
|
|
|
|
|
|
/* OMAP4 bit definitions */
|
|
|
|
#define OMAP4_DEF_IRQENABLE_EVENTEN (1 << 0)
|
|
|
|
#define OMAP4_DEF_IRQENABLE_LONGKEY (1 << 1)
|
|
|
|
#define OMAP4_DEF_IRQENABLE_TIMEOUTEN (1 << 2)
|
2010-09-30 00:38:01 -06:00
|
|
|
#define OMAP4_DEF_WUP_EVENT_ENA (1 << 0)
|
|
|
|
#define OMAP4_DEF_WUP_LONG_KEY_ENA (1 << 1)
|
2010-08-31 18:05:27 -06:00
|
|
|
#define OMAP4_DEF_CTRL_NOSOFTMODE (1 << 1)
|
|
|
|
#define OMAP4_DEF_CTRLPTVVALUE (1 << 2)
|
|
|
|
#define OMAP4_DEF_CTRLPTV (1 << 1)
|
|
|
|
|
|
|
|
/* OMAP4 values */
|
2010-09-30 00:36:48 -06:00
|
|
|
#define OMAP4_VAL_IRQDISABLE 0x00
|
2010-08-31 18:05:27 -06:00
|
|
|
#define OMAP4_VAL_DEBOUNCINGTIME 0x07
|
|
|
|
#define OMAP4_VAL_FUNCTIONALCFG 0x1E
|
|
|
|
|
|
|
|
#define OMAP4_MASK_IRQSTATUSDISABLE 0xFFFF
|
|
|
|
|
Input: omap-keypad - dynamically handle register offsets
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>
2012-05-10 23:32:00 -06:00
|
|
|
enum {
|
|
|
|
KBD_REVISION_OMAP4 = 0,
|
|
|
|
KBD_REVISION_OMAP5,
|
|
|
|
};
|
|
|
|
|
2010-08-31 18:05:27 -06:00
|
|
|
struct omap4_keypad {
|
|
|
|
struct input_dev *input;
|
|
|
|
|
|
|
|
void __iomem *base;
|
Input: omap-keypad - dynamically handle register offsets
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>
2012-05-10 23:32:00 -06:00
|
|
|
unsigned int irq;
|
2010-08-31 18:05:27 -06:00
|
|
|
|
|
|
|
unsigned int rows;
|
|
|
|
unsigned int cols;
|
Input: omap-keypad - dynamically handle register offsets
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>
2012-05-10 23:32:00 -06:00
|
|
|
u32 reg_offset;
|
|
|
|
u32 irqreg_offset;
|
2010-08-31 18:05:27 -06:00
|
|
|
unsigned int row_shift;
|
2012-07-13 01:10:47 -06:00
|
|
|
bool no_autorepeat;
|
2010-08-31 18:05:27 -06:00
|
|
|
unsigned char key_state[8];
|
2012-07-13 01:10:47 -06:00
|
|
|
unsigned short *keymap;
|
2010-08-31 18:05:27 -06:00
|
|
|
};
|
|
|
|
|
Input: omap-keypad - dynamically handle register offsets
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>
2012-05-10 23:32:00 -06:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-08-31 18:05:27 -06:00
|
|
|
/* Interrupt handler */
|
|
|
|
static irqreturn_t omap4_keypad_interrupt(int irq, void *dev_id)
|
|
|
|
{
|
|
|
|
struct omap4_keypad *keypad_data = dev_id;
|
|
|
|
struct input_dev *input_dev = keypad_data->input;
|
|
|
|
unsigned char key_state[ARRAY_SIZE(keypad_data->key_state)];
|
|
|
|
unsigned int col, row, code, changed;
|
|
|
|
u32 *new_state = (u32 *) key_state;
|
|
|
|
|
|
|
|
/* Disable interrupts */
|
Input: omap-keypad - dynamically handle register offsets
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>
2012-05-10 23:32:00 -06:00
|
|
|
kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQENABLE,
|
|
|
|
OMAP4_VAL_IRQDISABLE);
|
2010-08-31 18:05:27 -06:00
|
|
|
|
Input: omap-keypad - dynamically handle register offsets
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>
2012-05-10 23:32:00 -06:00
|
|
|
*new_state = kbd_readl(keypad_data, OMAP4_KBD_FULLCODE31_0);
|
|
|
|
*(new_state + 1) = kbd_readl(keypad_data, OMAP4_KBD_FULLCODE63_32);
|
2010-08-31 18:05:27 -06:00
|
|
|
|
|
|
|
for (row = 0; row < keypad_data->rows; row++) {
|
|
|
|
changed = key_state[row] ^ keypad_data->key_state[row];
|
|
|
|
if (!changed)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
for (col = 0; col < keypad_data->cols; col++) {
|
|
|
|
if (changed & (1 << col)) {
|
|
|
|
code = MATRIX_SCAN_CODE(row, col,
|
|
|
|
keypad_data->row_shift);
|
|
|
|
input_event(input_dev, EV_MSC, MSC_SCAN, code);
|
|
|
|
input_report_key(input_dev,
|
|
|
|
keypad_data->keymap[code],
|
|
|
|
key_state[row] & (1 << col));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
input_sync(input_dev);
|
|
|
|
|
|
|
|
memcpy(keypad_data->key_state, key_state,
|
|
|
|
sizeof(keypad_data->key_state));
|
|
|
|
|
|
|
|
/* clear pending interrupts */
|
Input: omap-keypad - dynamically handle register offsets
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>
2012-05-10 23:32:00 -06:00
|
|
|
kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS,
|
|
|
|
kbd_read_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS));
|
2010-08-31 18:05:27 -06:00
|
|
|
|
|
|
|
/* enable interrupts */
|
Input: omap-keypad - dynamically handle register offsets
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>
2012-05-10 23:32:00 -06:00
|
|
|
kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQENABLE,
|
|
|
|
OMAP4_DEF_IRQENABLE_EVENTEN |
|
|
|
|
OMAP4_DEF_IRQENABLE_LONGKEY);
|
2010-08-31 18:05:27 -06:00
|
|
|
|
|
|
|
return IRQ_HANDLED;
|
|
|
|
}
|
|
|
|
|
2011-02-22 23:25:59 -07:00
|
|
|
static int omap4_keypad_open(struct input_dev *input)
|
|
|
|
{
|
|
|
|
struct omap4_keypad *keypad_data = input_get_drvdata(input);
|
|
|
|
|
|
|
|
pm_runtime_get_sync(input->dev.parent);
|
|
|
|
|
|
|
|
disable_irq(keypad_data->irq);
|
|
|
|
|
Input: omap-keypad - dynamically handle register offsets
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>
2012-05-10 23:32:00 -06:00
|
|
|
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);
|
2011-02-22 23:25:59 -07:00
|
|
|
|
|
|
|
enable_irq(keypad_data->irq);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void omap4_keypad_close(struct input_dev *input)
|
|
|
|
{
|
|
|
|
struct omap4_keypad *keypad_data = input_get_drvdata(input);
|
|
|
|
|
|
|
|
disable_irq(keypad_data->irq);
|
|
|
|
|
|
|
|
/* Disable interrupts */
|
Input: omap-keypad - dynamically handle register offsets
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>
2012-05-10 23:32:00 -06:00
|
|
|
kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQENABLE,
|
|
|
|
OMAP4_VAL_IRQDISABLE);
|
2011-02-22 23:25:59 -07:00
|
|
|
|
|
|
|
/* clear pending interrupts */
|
Input: omap-keypad - dynamically handle register offsets
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>
2012-05-10 23:32:00 -06:00
|
|
|
kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS,
|
|
|
|
kbd_read_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS));
|
2011-02-22 23:25:59 -07:00
|
|
|
|
|
|
|
enable_irq(keypad_data->irq);
|
|
|
|
|
|
|
|
pm_runtime_put_sync(input->dev.parent);
|
|
|
|
}
|
|
|
|
|
2012-07-13 01:10:47 -06:00
|
|
|
#ifdef CONFIG_OF
|
2012-11-23 22:38:25 -07:00
|
|
|
static int omap4_keypad_parse_dt(struct device *dev,
|
|
|
|
struct omap4_keypad *keypad_data)
|
2012-07-13 01:10:47 -06:00
|
|
|
{
|
|
|
|
struct device_node *np = dev->of_node;
|
2013-02-25 15:08:40 -07:00
|
|
|
int err;
|
2012-07-13 01:10:47 -06:00
|
|
|
|
2013-02-25 15:08:40 -07:00
|
|
|
err = matrix_keypad_parse_of_params(dev, &keypad_data->rows,
|
|
|
|
&keypad_data->cols);
|
|
|
|
if (err)
|
|
|
|
return err;
|
2012-07-13 01:10:47 -06:00
|
|
|
|
|
|
|
if (of_get_property(np, "linux,input-no-autorepeat", NULL))
|
|
|
|
keypad_data->no_autorepeat = true;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
static inline int omap4_keypad_parse_dt(struct device *dev,
|
|
|
|
struct omap4_keypad *keypad_data)
|
|
|
|
{
|
|
|
|
return -ENOSYS;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2012-11-23 22:38:25 -07:00
|
|
|
static int omap4_keypad_probe(struct platform_device *pdev)
|
2010-08-31 18:05:27 -06:00
|
|
|
{
|
2012-07-13 01:10:47 -06:00
|
|
|
const struct omap4_keypad_platform_data *pdata =
|
|
|
|
dev_get_platdata(&pdev->dev);
|
|
|
|
const struct matrix_keymap_data *keymap_data =
|
|
|
|
pdata ? pdata->keymap_data : NULL;
|
2010-08-31 18:05:27 -06:00
|
|
|
struct omap4_keypad *keypad_data;
|
|
|
|
struct input_dev *input_dev;
|
2010-09-30 00:35:57 -06:00
|
|
|
struct resource *res;
|
2012-07-13 01:10:47 -06:00
|
|
|
unsigned int max_keys;
|
Input: omap-keypad - dynamically handle register offsets
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>
2012-05-10 23:32:00 -06:00
|
|
|
int rev;
|
2010-09-30 00:35:57 -06:00
|
|
|
int irq;
|
2010-08-31 18:05:27 -06:00
|
|
|
int error;
|
|
|
|
|
2010-09-30 00:35:57 -06:00
|
|
|
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
|
|
|
if (!res) {
|
2010-08-31 18:05:27 -06:00
|
|
|
dev_err(&pdev->dev, "no base address specified\n");
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
2010-09-30 00:35:57 -06:00
|
|
|
irq = platform_get_irq(pdev, 0);
|
|
|
|
if (!irq) {
|
2010-08-31 18:05:27 -06:00
|
|
|
dev_err(&pdev->dev, "no keyboard irq assigned\n");
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
2012-07-13 01:10:47 -06:00
|
|
|
keypad_data = kzalloc(sizeof(struct omap4_keypad), GFP_KERNEL);
|
2010-08-31 18:05:27 -06:00
|
|
|
if (!keypad_data) {
|
|
|
|
dev_err(&pdev->dev, "keypad_data memory allocation failed\n");
|
|
|
|
return -ENOMEM;
|
|
|
|
}
|
|
|
|
|
2012-07-13 01:10:47 -06:00
|
|
|
keypad_data->irq = irq;
|
|
|
|
|
|
|
|
if (pdata) {
|
|
|
|
keypad_data->rows = pdata->rows;
|
|
|
|
keypad_data->cols = pdata->cols;
|
|
|
|
} else {
|
|
|
|
error = omap4_keypad_parse_dt(&pdev->dev, keypad_data);
|
|
|
|
if (error)
|
|
|
|
return error;
|
|
|
|
}
|
2010-09-30 00:35:57 -06:00
|
|
|
|
2012-07-13 01:10:47 -06:00
|
|
|
res = request_mem_region(res->start, resource_size(res), pdev->name);
|
2010-09-30 00:35:57 -06:00
|
|
|
if (!res) {
|
|
|
|
dev_err(&pdev->dev, "can't request mem region\n");
|
|
|
|
error = -EBUSY;
|
|
|
|
goto err_free_keypad;
|
|
|
|
}
|
2010-08-31 18:05:27 -06:00
|
|
|
|
2010-09-30 00:35:57 -06:00
|
|
|
keypad_data->base = ioremap(res->start, resource_size(res));
|
|
|
|
if (!keypad_data->base) {
|
|
|
|
dev_err(&pdev->dev, "can't ioremap mem resource\n");
|
|
|
|
error = -ENOMEM;
|
|
|
|
goto err_release_mem;
|
|
|
|
}
|
|
|
|
|
2010-08-31 18:05:27 -06:00
|
|
|
|
Input: omap-keypad - dynamically handle register offsets
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>
2012-05-10 23:32:00 -06:00
|
|
|
/*
|
2012-07-13 01:10:47 -06:00
|
|
|
* Enable clocks for the keypad module so that we can read
|
|
|
|
* revision register.
|
|
|
|
*/
|
Input: omap-keypad - dynamically handle register offsets
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>
2012-05-10 23:32:00 -06:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2010-08-31 18:05:27 -06:00
|
|
|
/* input device allocation */
|
|
|
|
keypad_data->input = input_dev = input_allocate_device();
|
|
|
|
if (!input_dev) {
|
|
|
|
error = -ENOMEM;
|
Input: omap-keypad - dynamically handle register offsets
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>
2012-05-10 23:32:00 -06:00
|
|
|
goto err_pm_put_sync;
|
2010-08-31 18:05:27 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
input_dev->name = pdev->name;
|
|
|
|
input_dev->dev.parent = &pdev->dev;
|
|
|
|
input_dev->id.bustype = BUS_HOST;
|
|
|
|
input_dev->id.vendor = 0x0001;
|
|
|
|
input_dev->id.product = 0x0001;
|
|
|
|
input_dev->id.version = 0x0001;
|
|
|
|
|
2011-02-22 23:25:59 -07:00
|
|
|
input_dev->open = omap4_keypad_open;
|
|
|
|
input_dev->close = omap4_keypad_close;
|
|
|
|
|
2012-07-13 01:10:47 -06:00
|
|
|
input_set_capability(input_dev, EV_MSC, MSC_SCAN);
|
|
|
|
if (!keypad_data->no_autorepeat)
|
|
|
|
__set_bit(EV_REP, input_dev->evbit);
|
|
|
|
|
|
|
|
input_set_drvdata(input_dev, keypad_data);
|
|
|
|
|
|
|
|
keypad_data->row_shift = get_count_order(keypad_data->cols);
|
|
|
|
max_keys = keypad_data->rows << keypad_data->row_shift;
|
|
|
|
keypad_data->keymap = kzalloc(max_keys * sizeof(keypad_data->keymap[0]),
|
|
|
|
GFP_KERNEL);
|
|
|
|
if (!keypad_data->keymap) {
|
|
|
|
dev_err(&pdev->dev, "Not enough memory for keymap\n");
|
|
|
|
error = -ENOMEM;
|
|
|
|
goto err_free_input;
|
|
|
|
}
|
|
|
|
|
|
|
|
error = matrix_keypad_build_keymap(keymap_data, NULL,
|
|
|
|
keypad_data->rows, keypad_data->cols,
|
2012-05-10 23:37:08 -06:00
|
|
|
keypad_data->keymap, input_dev);
|
|
|
|
if (error) {
|
|
|
|
dev_err(&pdev->dev, "failed to build keymap\n");
|
2012-07-13 01:10:47 -06:00
|
|
|
goto err_free_keymap;
|
2012-05-10 23:37:08 -06:00
|
|
|
}
|
2010-08-31 18:05:27 -06:00
|
|
|
|
|
|
|
error = request_irq(keypad_data->irq, omap4_keypad_interrupt,
|
2010-09-30 00:37:04 -06:00
|
|
|
IRQF_TRIGGER_RISING,
|
2010-08-31 18:05:27 -06:00
|
|
|
"omap4-keypad", keypad_data);
|
|
|
|
if (error) {
|
|
|
|
dev_err(&pdev->dev, "failed to register interrupt\n");
|
|
|
|
goto err_free_input;
|
|
|
|
}
|
|
|
|
|
Input: omap-keypad - dynamically handle register offsets
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>
2012-05-10 23:32:00 -06:00
|
|
|
pm_runtime_put_sync(&pdev->dev);
|
2011-02-22 23:25:59 -07:00
|
|
|
|
2010-08-31 18:05:27 -06:00
|
|
|
error = input_register_device(keypad_data->input);
|
|
|
|
if (error < 0) {
|
|
|
|
dev_err(&pdev->dev, "failed to register input device\n");
|
2011-02-22 23:25:59 -07:00
|
|
|
goto err_pm_disable;
|
2010-08-31 18:05:27 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
platform_set_drvdata(pdev, keypad_data);
|
|
|
|
return 0;
|
|
|
|
|
2011-02-22 23:25:59 -07:00
|
|
|
err_pm_disable:
|
|
|
|
pm_runtime_disable(&pdev->dev);
|
2010-08-31 18:05:27 -06:00
|
|
|
free_irq(keypad_data->irq, keypad_data);
|
2012-07-13 01:10:47 -06:00
|
|
|
err_free_keymap:
|
|
|
|
kfree(keypad_data->keymap);
|
2010-08-31 18:05:27 -06:00
|
|
|
err_free_input:
|
|
|
|
input_free_device(input_dev);
|
Input: omap-keypad - dynamically handle register offsets
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>
2012-05-10 23:32:00 -06:00
|
|
|
err_pm_put_sync:
|
|
|
|
pm_runtime_put_sync(&pdev->dev);
|
2010-09-30 00:35:57 -06:00
|
|
|
err_unmap:
|
|
|
|
iounmap(keypad_data->base);
|
|
|
|
err_release_mem:
|
2012-07-13 01:10:47 -06:00
|
|
|
release_mem_region(res->start, resource_size(res));
|
2010-08-31 18:05:27 -06:00
|
|
|
err_free_keypad:
|
|
|
|
kfree(keypad_data);
|
|
|
|
return error;
|
|
|
|
}
|
|
|
|
|
2012-11-23 22:50:47 -07:00
|
|
|
static int omap4_keypad_remove(struct platform_device *pdev)
|
2010-08-31 18:05:27 -06:00
|
|
|
{
|
|
|
|
struct omap4_keypad *keypad_data = platform_get_drvdata(pdev);
|
2010-09-30 00:35:57 -06:00
|
|
|
struct resource *res;
|
2010-08-31 18:05:27 -06:00
|
|
|
|
|
|
|
free_irq(keypad_data->irq, keypad_data);
|
2011-02-22 23:25:59 -07:00
|
|
|
|
|
|
|
pm_runtime_disable(&pdev->dev);
|
|
|
|
|
2010-08-31 18:05:27 -06:00
|
|
|
input_unregister_device(keypad_data->input);
|
2010-09-30 00:35:57 -06:00
|
|
|
|
|
|
|
iounmap(keypad_data->base);
|
|
|
|
|
|
|
|
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
|
|
|
release_mem_region(res->start, resource_size(res));
|
|
|
|
|
2012-07-13 01:10:47 -06:00
|
|
|
kfree(keypad_data->keymap);
|
2010-08-31 18:05:27 -06:00
|
|
|
kfree(keypad_data);
|
2012-07-13 01:10:47 -06:00
|
|
|
|
2010-08-31 18:05:27 -06:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2012-07-13 01:10:47 -06:00
|
|
|
#ifdef CONFIG_OF
|
|
|
|
static const struct of_device_id omap_keypad_dt_match[] = {
|
|
|
|
{ .compatible = "ti,omap4-keypad" },
|
|
|
|
{},
|
|
|
|
};
|
|
|
|
MODULE_DEVICE_TABLE(of, omap_keypad_dt_match);
|
|
|
|
#endif
|
|
|
|
|
2010-08-31 18:05:27 -06:00
|
|
|
static struct platform_driver omap4_keypad_driver = {
|
|
|
|
.probe = omap4_keypad_probe,
|
2012-11-23 22:27:39 -07:00
|
|
|
.remove = omap4_keypad_remove,
|
2010-08-31 18:05:27 -06:00
|
|
|
.driver = {
|
|
|
|
.name = "omap4-keypad",
|
|
|
|
.owner = THIS_MODULE,
|
2012-07-13 01:10:47 -06:00
|
|
|
.of_match_table = of_match_ptr(omap_keypad_dt_match),
|
2010-08-31 18:05:27 -06:00
|
|
|
},
|
|
|
|
};
|
2011-11-29 12:08:39 -07:00
|
|
|
module_platform_driver(omap4_keypad_driver);
|
2010-08-31 18:05:27 -06:00
|
|
|
|
|
|
|
MODULE_AUTHOR("Texas Instruments");
|
|
|
|
MODULE_DESCRIPTION("OMAP4 Keypad Driver");
|
|
|
|
MODULE_LICENSE("GPL");
|
|
|
|
MODULE_ALIAS("platform:omap4-keypad");
|