Skip to content

Commit f77621c

Browse files
Poddar, Souravdtor
authored andcommitted
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>
1 parent 1a49a0a commit f77621c

File tree

2 files changed

+94
-28
lines changed

2 files changed

+94
-28
lines changed

drivers/input/keyboard/Kconfig

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -522,9 +522,9 @@ config KEYBOARD_OMAP
522522
module will be called omap-keypad.
523523

524524
config KEYBOARD_OMAP4
525-
tristate "TI OMAP4 keypad support"
525+
tristate "TI OMAP4+ keypad support"
526526
help
527-
Say Y here if you want to use the OMAP4 keypad.
527+
Say Y here if you want to use the OMAP4+ keypad.
528528

529529
To compile this driver as a module, choose M here: the
530530
module will be called omap4-keypad.

drivers/input/keyboard/omap4-keypad.c

Lines changed: 92 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -68,19 +68,52 @@
6868

6969
#define OMAP4_MASK_IRQSTATUSDISABLE 0xFFFF
7070

71+
enum {
72+
KBD_REVISION_OMAP4 = 0,
73+
KBD_REVISION_OMAP5,
74+
};
75+
7176
struct omap4_keypad {
7277
struct input_dev *input;
7378

7479
void __iomem *base;
75-
int irq;
80+
unsigned int irq;
7681

7782
unsigned int rows;
7883
unsigned int cols;
84+
u32 reg_offset;
85+
u32 irqreg_offset;
7986
unsigned int row_shift;
8087
unsigned char key_state[8];
8188
unsigned short keymap[];
8289
};
8390

91+
static int kbd_readl(struct omap4_keypad *keypad_data, u32 offset)
92+
{
93+
return __raw_readl(keypad_data->base +
94+
keypad_data->reg_offset + offset);
95+
}
96+
97+
static void kbd_writel(struct omap4_keypad *keypad_data, u32 offset, u32 value)
98+
{
99+
__raw_writel(value,
100+
keypad_data->base + keypad_data->reg_offset + offset);
101+
}
102+
103+
static int kbd_read_irqreg(struct omap4_keypad *keypad_data, u32 offset)
104+
{
105+
return __raw_readl(keypad_data->base +
106+
keypad_data->irqreg_offset + offset);
107+
}
108+
109+
static void kbd_write_irqreg(struct omap4_keypad *keypad_data,
110+
u32 offset, u32 value)
111+
{
112+
__raw_writel(value,
113+
keypad_data->base + keypad_data->irqreg_offset + offset);
114+
}
115+
116+
84117
/* Interrupt handler */
85118
static irqreturn_t omap4_keypad_interrupt(int irq, void *dev_id)
86119
{
@@ -91,12 +124,11 @@ static irqreturn_t omap4_keypad_interrupt(int irq, void *dev_id)
91124
u32 *new_state = (u32 *) key_state;
92125

93126
/* Disable interrupts */
94-
__raw_writel(OMAP4_VAL_IRQDISABLE,
95-
keypad_data->base + OMAP4_KBD_IRQENABLE);
127+
kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQENABLE,
128+
OMAP4_VAL_IRQDISABLE);
96129

97-
*new_state = __raw_readl(keypad_data->base + OMAP4_KBD_FULLCODE31_0);
98-
*(new_state + 1) = __raw_readl(keypad_data->base
99-
+ OMAP4_KBD_FULLCODE63_32);
130+
*new_state = kbd_readl(keypad_data, OMAP4_KBD_FULLCODE31_0);
131+
*(new_state + 1) = kbd_readl(keypad_data, OMAP4_KBD_FULLCODE63_32);
100132

101133
for (row = 0; row < keypad_data->rows; row++) {
102134
changed = key_state[row] ^ keypad_data->key_state[row];
@@ -121,12 +153,13 @@ static irqreturn_t omap4_keypad_interrupt(int irq, void *dev_id)
121153
sizeof(keypad_data->key_state));
122154

123155
/* clear pending interrupts */
124-
__raw_writel(__raw_readl(keypad_data->base + OMAP4_KBD_IRQSTATUS),
125-
keypad_data->base + OMAP4_KBD_IRQSTATUS);
156+
kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS,
157+
kbd_read_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS));
126158

127159
/* enable interrupts */
128-
__raw_writel(OMAP4_DEF_IRQENABLE_EVENTEN | OMAP4_DEF_IRQENABLE_LONGKEY,
129-
keypad_data->base + OMAP4_KBD_IRQENABLE);
160+
kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQENABLE,
161+
OMAP4_DEF_IRQENABLE_EVENTEN |
162+
OMAP4_DEF_IRQENABLE_LONGKEY);
130163

131164
return IRQ_HANDLED;
132165
}
@@ -139,16 +172,17 @@ static int omap4_keypad_open(struct input_dev *input)
139172

140173
disable_irq(keypad_data->irq);
141174

142-
__raw_writel(OMAP4_VAL_FUNCTIONALCFG,
143-
keypad_data->base + OMAP4_KBD_CTRL);
144-
__raw_writel(OMAP4_VAL_DEBOUNCINGTIME,
145-
keypad_data->base + OMAP4_KBD_DEBOUNCINGTIME);
146-
__raw_writel(OMAP4_VAL_IRQDISABLE,
147-
keypad_data->base + OMAP4_KBD_IRQSTATUS);
148-
__raw_writel(OMAP4_DEF_IRQENABLE_EVENTEN | OMAP4_DEF_IRQENABLE_LONGKEY,
149-
keypad_data->base + OMAP4_KBD_IRQENABLE);
150-
__raw_writel(OMAP4_DEF_WUP_EVENT_ENA | OMAP4_DEF_WUP_LONG_KEY_ENA,
151-
keypad_data->base + OMAP4_KBD_WAKEUPENABLE);
175+
kbd_writel(keypad_data, OMAP4_KBD_CTRL,
176+
OMAP4_VAL_FUNCTIONALCFG);
177+
kbd_writel(keypad_data, OMAP4_KBD_DEBOUNCINGTIME,
178+
OMAP4_VAL_DEBOUNCINGTIME);
179+
kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS,
180+
OMAP4_VAL_IRQDISABLE);
181+
kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQENABLE,
182+
OMAP4_DEF_IRQENABLE_EVENTEN |
183+
OMAP4_DEF_IRQENABLE_LONGKEY);
184+
kbd_writel(keypad_data, OMAP4_KBD_WAKEUPENABLE,
185+
OMAP4_DEF_WUP_EVENT_ENA | OMAP4_DEF_WUP_LONG_KEY_ENA);
152186

153187
enable_irq(keypad_data->irq);
154188

@@ -162,12 +196,12 @@ static void omap4_keypad_close(struct input_dev *input)
162196
disable_irq(keypad_data->irq);
163197

164198
/* Disable interrupts */
165-
__raw_writel(OMAP4_VAL_IRQDISABLE,
166-
keypad_data->base + OMAP4_KBD_IRQENABLE);
199+
kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQENABLE,
200+
OMAP4_VAL_IRQDISABLE);
167201

168202
/* clear pending interrupts */
169-
__raw_writel(__raw_readl(keypad_data->base + OMAP4_KBD_IRQSTATUS),
170-
keypad_data->base + OMAP4_KBD_IRQSTATUS);
203+
kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS,
204+
kbd_read_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS));
171205

172206
enable_irq(keypad_data->irq);
173207

@@ -182,6 +216,7 @@ static int __devinit omap4_keypad_probe(struct platform_device *pdev)
182216
struct resource *res;
183217
resource_size_t size;
184218
unsigned int row_shift, max_keys;
219+
int rev;
185220
int irq;
186221
int error;
187222

@@ -241,11 +276,40 @@ static int __devinit omap4_keypad_probe(struct platform_device *pdev)
241276
keypad_data->rows = pdata->rows;
242277
keypad_data->cols = pdata->cols;
243278

279+
/*
280+
* Enable clocks for the keypad module so that we can read
281+
* revision register.
282+
*/
283+
pm_runtime_enable(&pdev->dev);
284+
error = pm_runtime_get_sync(&pdev->dev);
285+
if (error) {
286+
dev_err(&pdev->dev, "pm_runtime_get_sync() failed\n");
287+
goto err_unmap;
288+
}
289+
rev = __raw_readl(keypad_data->base + OMAP4_KBD_REVISION);
290+
rev &= 0x03 << 30;
291+
rev >>= 30;
292+
switch (rev) {
293+
case KBD_REVISION_OMAP4:
294+
keypad_data->reg_offset = 0x00;
295+
keypad_data->irqreg_offset = 0x00;
296+
break;
297+
case KBD_REVISION_OMAP5:
298+
keypad_data->reg_offset = 0x10;
299+
keypad_data->irqreg_offset = 0x0c;
300+
break;
301+
default:
302+
dev_err(&pdev->dev,
303+
"Keypad reports unsupported revision %d", rev);
304+
error = -EINVAL;
305+
goto err_pm_put_sync;
306+
}
307+
244308
/* input device allocation */
245309
keypad_data->input = input_dev = input_allocate_device();
246310
if (!input_dev) {
247311
error = -ENOMEM;
248-
goto err_unmap;
312+
goto err_pm_put_sync;
249313
}
250314

251315
input_dev->name = pdev->name;
@@ -280,7 +344,7 @@ static int __devinit omap4_keypad_probe(struct platform_device *pdev)
280344
goto err_free_input;
281345
}
282346

283-
pm_runtime_enable(&pdev->dev);
347+
pm_runtime_put_sync(&pdev->dev);
284348

285349
error = input_register_device(keypad_data->input);
286350
if (error < 0) {
@@ -296,6 +360,8 @@ static int __devinit omap4_keypad_probe(struct platform_device *pdev)
296360
free_irq(keypad_data->irq, keypad_data);
297361
err_free_input:
298362
input_free_device(input_dev);
363+
err_pm_put_sync:
364+
pm_runtime_put_sync(&pdev->dev);
299365
err_unmap:
300366
iounmap(keypad_data->base);
301367
err_release_mem:

0 commit comments

Comments
 (0)