Custom Search

Re: [RESEND/PATCHv2] Input: omap-keypad: dynamically handle register offsets

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]


Hi Dmitry,

Gentle Ping on this..

~Sourav
On Wed, May 9, 2012 at 3:37 PM, Poddar, Sourav <sourav.poddar@xxxxxx> wrote:
> Hi Dmitry,
>
> On Wed, May 9, 2012 at 3:14 PM, Poddar, Sourav <sourav.poddar@xxxxxx> 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@xxxxxx>
>> 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@xxxxxxxxxxxxxxxxxxxx>
>> Signed-off-by: Felipe Balbi <balbi@xxxxxx>
>> Signed-off-by: G, Manjunath Kondaiah <manjugk@xxxxxx>
>> Signed-off-by: Sourav Poddar <sourav.poddar@xxxxxx>
>> Signed-off-by: Dmitry Torokhov <dtor@xxxxxxx>
>> ---
>>  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@xxxxxxxxx> wrote:
>>>> Hi Dmitry ,
>>>>
>>>>
>>>> On Wed, May 9, 2012 at 10:48 AM, Dmitry Torokhov
>>>> <dmitry.torokhov@xxxxxxxxx> 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@xxxxxx>
>>>
>>> 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@xxxxxx>
>>> Signed-off-by: G, Manjunath Kondaiah <manjugk@xxxxxx>
>>> Signed-off-by: Sourav Poddar <sourav.poddar@xxxxxx>
>>> Signed-off-by: Dmitry Torokhov <dtor@xxxxxxx>
>>> ---
>>>
>>>  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@xxxxxx>
> 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@xxxxxxxxxxxxxxxxxxxx>
> Signed-off-by: Felipe Balbi <balbi@xxxxxx>
> Signed-off-by: G, Manjunath Kondaiah <manjugk@xxxxxx>
> Signed-off-by: Sourav Poddar <sourav.poddar@xxxxxx>
> Signed-off-by: Dmitry Torokhov <dtor@xxxxxxx>
> ---
>  drivers/input/keyboard/Kconfig        |    4 +-
>  drivers/input/keyboard/omap4-keypad.c |  118 +++++++++++++++++++++++++-------
>  2 files changed, 94 insertions(+), 28 deletions(-)
>
> diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
> index f354813..33bbdee 100644
> --- a/drivers/input/keyboard/Kconfig
> +++ b/drivers/input/keyboard/Kconfig
> @@ -512,9 +512,9 @@ config KEYBOARD_OMAP
>          module will be called omap-keypad.
>
>  config KEYBOARD_OMAP4
> -       tristate "TI OMAP4 keypad support"
> +       tristate "TI OMAP4+ keypad support"
>        help
> -         Say Y here if you want to use the OMAP4 keypad.
> +         Say Y here if you want to use the OMAP4+ keypad.
>
>          To compile this driver as a module, choose M here: the
>          module will be called omap4-keypad.
> diff --git a/drivers/input/keyboard/omap4-keypad.c
> b/drivers/input/keyboard/omap4-keypad.c
> index e809ac0..28da0e4 100644
> --- a/drivers/input/keyboard/omap4-keypad.c
> +++ b/drivers/input/keyboard/omap4-keypad.c
> @@ -68,19 +68,52 @@
>
>  #define OMAP4_MASK_IRQSTATUSDISABLE    0xFFFF
>
> +enum {
> +       KBD_REVISION_OMAP4 = 0,
> +       KBD_REVISION_OMAP5,
> +};
> +
>  struct omap4_keypad {
>        struct input_dev *input;
>
>        void __iomem *base;
> -       int irq;
> +       unsigned int irq;
>
>        unsigned int rows;
>        unsigned int cols;
> +       u32 reg_offset;
> +       u32 irqreg_offset;
>        unsigned int row_shift;
>        unsigned char key_state[8];
>        unsigned short keymap[];
>  };
>
> +static int kbd_readl(struct omap4_keypad *keypad_data, u32 offset)
> +{
> +       return __raw_readl(keypad_data->base +
> +                               keypad_data->reg_offset + offset);
> +}
> +
> +static void kbd_writel(struct omap4_keypad *keypad_data, u32 offset, u32 value)
> +{
> +       __raw_writel(value,
> +                    keypad_data->base + keypad_data->reg_offset + offset);
> +}
> +
> +static int kbd_read_irqreg(struct omap4_keypad *keypad_data, u32 offset)
> +{
> +       return __raw_readl(keypad_data->base +
> +                               keypad_data->irqreg_offset + offset);
> +}
> +
> +static void kbd_write_irqreg(struct omap4_keypad *keypad_data,
> +                            u32 offset, u32 value)
> +{
> +       __raw_writel(value,
> +                    keypad_data->base + keypad_data->irqreg_offset + offset);
> +}
> +
> +
>  /* Interrupt handler */
>  static irqreturn_t omap4_keypad_interrupt(int irq, void *dev_id)
>  {
> @@ -91,12 +124,11 @@ static irqreturn_t omap4_keypad_interrupt(int
> irq, void *dev_id)
>        u32 *new_state = (u32 *) key_state;
>
>        /* Disable interrupts */
> -       __raw_writel(OMAP4_VAL_IRQDISABLE,
> -                    keypad_data->base + OMAP4_KBD_IRQENABLE);
> +       kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQENABLE,
> +                        OMAP4_VAL_IRQDISABLE);
>
> -       *new_state = __raw_readl(keypad_data->base + OMAP4_KBD_FULLCODE31_0);
> -       *(new_state + 1) = __raw_readl(keypad_data->base
> -                                               + OMAP4_KBD_FULLCODE63_32);
> +       *new_state = kbd_readl(keypad_data, OMAP4_KBD_FULLCODE31_0);
> +       *(new_state + 1) = kbd_readl(keypad_data, OMAP4_KBD_FULLCODE63_32);
>
>        for (row = 0; row < keypad_data->rows; row++) {
>                changed = key_state[row] ^ keypad_data->key_state[row];
> @@ -121,12 +153,13 @@ static irqreturn_t omap4_keypad_interrupt(int
> irq, void *dev_id)
>                sizeof(keypad_data->key_state));
>
>        /* clear pending interrupts */
> -       __raw_writel(__raw_readl(keypad_data->base + OMAP4_KBD_IRQSTATUS),
> -                       keypad_data->base + OMAP4_KBD_IRQSTATUS);
> +       kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS,
> +                        kbd_read_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS));
>
>        /* enable interrupts */
> -       __raw_writel(OMAP4_DEF_IRQENABLE_EVENTEN | OMAP4_DEF_IRQENABLE_LONGKEY,
> -                       keypad_data->base + OMAP4_KBD_IRQENABLE);
> +       kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQENABLE,
> +               OMAP4_DEF_IRQENABLE_EVENTEN |
> +                               OMAP4_DEF_IRQENABLE_LONGKEY);
>
>        return IRQ_HANDLED;
>  }
> @@ -139,16 +172,17 @@ static int omap4_keypad_open(struct input_dev *input)
>
>        disable_irq(keypad_data->irq);
>
> -       __raw_writel(OMAP4_VAL_FUNCTIONALCFG,
> -                       keypad_data->base + OMAP4_KBD_CTRL);
> -       __raw_writel(OMAP4_VAL_DEBOUNCINGTIME,
> -                       keypad_data->base + OMAP4_KBD_DEBOUNCINGTIME);
> -       __raw_writel(OMAP4_VAL_IRQDISABLE,
> -                       keypad_data->base + OMAP4_KBD_IRQSTATUS);
> -       __raw_writel(OMAP4_DEF_IRQENABLE_EVENTEN | OMAP4_DEF_IRQENABLE_LONGKEY,
> -                       keypad_data->base + OMAP4_KBD_IRQENABLE);
> -       __raw_writel(OMAP4_DEF_WUP_EVENT_ENA | OMAP4_DEF_WUP_LONG_KEY_ENA,
> -                       keypad_data->base + OMAP4_KBD_WAKEUPENABLE);
> +       kbd_writel(keypad_data, OMAP4_KBD_CTRL,
> +                       OMAP4_VAL_FUNCTIONALCFG);
> +       kbd_writel(keypad_data, OMAP4_KBD_DEBOUNCINGTIME,
> +                       OMAP4_VAL_DEBOUNCINGTIME);
> +       kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS,
> +                       OMAP4_VAL_IRQDISABLE);
> +       kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQENABLE,
> +                       OMAP4_DEF_IRQENABLE_EVENTEN |
> +                               OMAP4_DEF_IRQENABLE_LONGKEY);
> +       kbd_writel(keypad_data, OMAP4_KBD_WAKEUPENABLE,
> +                       OMAP4_DEF_WUP_EVENT_ENA | OMAP4_DEF_WUP_LONG_KEY_ENA);
>
>        enable_irq(keypad_data->irq);
>
> @@ -162,12 +196,12 @@ static void omap4_keypad_close(struct input_dev *input)
>        disable_irq(keypad_data->irq);
>
>        /* Disable interrupts */
> -       __raw_writel(OMAP4_VAL_IRQDISABLE,
> -                    keypad_data->base + OMAP4_KBD_IRQENABLE);
> +       kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQENABLE,
> +                        OMAP4_VAL_IRQDISABLE);
>
>        /* clear pending interrupts */
> -       __raw_writel(__raw_readl(keypad_data->base + OMAP4_KBD_IRQSTATUS),
> -                       keypad_data->base + OMAP4_KBD_IRQSTATUS);
> +       kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS,
> +                        kbd_read_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS));
>
>        enable_irq(keypad_data->irq);
>
> @@ -182,6 +216,7 @@ static int __devinit omap4_keypad_probe(struct
> platform_device *pdev)
>        struct resource *res;
>        resource_size_t size;
>        unsigned int row_shift, max_keys;
> +       int rev;
>        int irq;
>        int error;
>
> @@ -241,11 +276,40 @@ static int __devinit omap4_keypad_probe(struct
> platform_device *pdev)
>        keypad_data->rows = pdata->rows;
>        keypad_data->cols = pdata->cols;
>
> +       /*
> +       * Enable clocks for the keypad module so that we can read
> +       * revision register.
> +       */
> +       pm_runtime_enable(&pdev->dev);
> +       error = pm_runtime_get_sync(&pdev->dev);
> +       if (error) {
> +               dev_err(&pdev->dev, "pm_runtime_get_sync() failed\n");
> +               goto err_unmap;
> +       }
> +       rev = __raw_readl(keypad_data->base + OMAP4_KBD_REVISION);
> +       rev &= 0x03 << 30;
> +       rev >>= 30;
> +       switch (rev) {
> +       case KBD_REVISION_OMAP4:
> +               keypad_data->reg_offset = 0x00;
> +               keypad_data->irqreg_offset = 0x00;
> +               break;
> +       case KBD_REVISION_OMAP5:
> +               keypad_data->reg_offset = 0x10;
> +               keypad_data->irqreg_offset = 0x0c;
> +               break;
> +       default:
> +               dev_err(&pdev->dev,
> +                       "Keypad reports unsupported revision %d", rev);
> +               error = -EINVAL;
> +               goto err_pm_put_sync;
> +       }
> +
>        /* input device allocation */
>        keypad_data->input = input_dev = input_allocate_device();
>        if (!input_dev) {
>                error = -ENOMEM;
> -               goto err_unmap;
> +               goto err_pm_put_sync;
>        }
>
>        input_dev->name = pdev->name;
> @@ -280,7 +344,7 @@ static int __devinit omap4_keypad_probe(struct
> platform_device *pdev)
>                goto err_free_input;
>        }
>
> -       pm_runtime_enable(&pdev->dev);
> +       pm_runtime_put_sync(&pdev->dev);
>
>        error = input_register_device(keypad_data->input);
>        if (error < 0) {
> @@ -296,6 +360,8 @@ err_pm_disable:
>        free_irq(keypad_data->irq, keypad_data);
>  err_free_input:
>        input_free_device(input_dev);
> +err_pm_put_sync:
> +       pm_runtime_put_sync(&pdev->dev);
>  err_unmap:
>        iounmap(keypad_data->base);
>  err_release_mem:
> --
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Linux Media Devel]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Photo]     [Yosemite News]    [Yosemite Photos]    [Free Online Dating]     [Linux Kernel]     [Linux SCSI]     [XFree86]     [Linux Wireless Networking]     [Linux Omap]

  Powered by Linux