Commit 5ad567ffbaf208bd35bff4341906346c1a1d4574

Authored by Abraham Arce
Committed by Dmitry Torokhov
1 parent 163d27706b

Input: omap4-keypad - wire up runtime PM handling

Enable Runtime PM functionality in OMAP4 driver based on the following
assumptions:

- keyboard controller in wakeup domain so it is always on and power
  impact is minimal;
- in OMAP4 the device control is at module/device level and ick/fclk
  level control is difficult so cutting of clocks will prevent
  interrupts.

Signed-off-by: Abraham Arce <x0066660@ti.com>
Signed-off-by: Shubhrajyoti D <shubhrajyoti@ti.com>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>

Showing 1 changed file with 55 additions and 19 deletions Side-by-side Diff

drivers/input/keyboard/omap4-keypad.c
... ... @@ -29,6 +29,7 @@
29 29 #include <linux/io.h>
30 30 #include <linux/input.h>
31 31 #include <linux/slab.h>
  32 +#include <linux/pm_runtime.h>
32 33  
33 34 #include <plat/omap4-keypad.h>
34 35  
... ... @@ -80,20 +81,6 @@
80 81 unsigned short keymap[];
81 82 };
82 83  
83   -static void __devinit omap4_keypad_config(struct omap4_keypad *keypad_data)
84   -{
85   - __raw_writel(OMAP4_VAL_FUNCTIONALCFG,
86   - keypad_data->base + OMAP4_KBD_CTRL);
87   - __raw_writel(OMAP4_VAL_DEBOUNCINGTIME,
88   - keypad_data->base + OMAP4_KBD_DEBOUNCINGTIME);
89   - __raw_writel(OMAP4_VAL_IRQDISABLE,
90   - keypad_data->base + OMAP4_KBD_IRQSTATUS);
91   - __raw_writel(OMAP4_DEF_IRQENABLE_EVENTEN | OMAP4_DEF_IRQENABLE_LONGKEY,
92   - keypad_data->base + OMAP4_KBD_IRQENABLE);
93   - __raw_writel(OMAP4_DEF_WUP_EVENT_ENA | OMAP4_DEF_WUP_LONG_KEY_ENA,
94   - keypad_data->base + OMAP4_KBD_WAKEUPENABLE);
95   -}
96   -
97 84 /* Interrupt handler */
98 85 static irqreturn_t omap4_keypad_interrupt(int irq, void *dev_id)
99 86 {
... ... @@ -144,6 +131,49 @@
144 131 return IRQ_HANDLED;
145 132 }
146 133  
  134 +static int omap4_keypad_open(struct input_dev *input)
  135 +{
  136 + struct omap4_keypad *keypad_data = input_get_drvdata(input);
  137 +
  138 + pm_runtime_get_sync(input->dev.parent);
  139 +
  140 + disable_irq(keypad_data->irq);
  141 +
  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);
  152 +
  153 + enable_irq(keypad_data->irq);
  154 +
  155 + return 0;
  156 +}
  157 +
  158 +static void omap4_keypad_close(struct input_dev *input)
  159 +{
  160 + struct omap4_keypad *keypad_data = input_get_drvdata(input);
  161 +
  162 + disable_irq(keypad_data->irq);
  163 +
  164 + /* Disable interrupts */
  165 + __raw_writel(OMAP4_VAL_IRQDISABLE,
  166 + keypad_data->base + OMAP4_KBD_IRQENABLE);
  167 +
  168 + /* clear pending interrupts */
  169 + __raw_writel(__raw_readl(keypad_data->base + OMAP4_KBD_IRQSTATUS),
  170 + keypad_data->base + OMAP4_KBD_IRQSTATUS);
  171 +
  172 + enable_irq(keypad_data->irq);
  173 +
  174 + pm_runtime_put_sync(input->dev.parent);
  175 +}
  176 +
147 177 static int __devinit omap4_keypad_probe(struct platform_device *pdev)
148 178 {
149 179 const struct omap4_keypad_platform_data *pdata;
... ... @@ -225,6 +255,9 @@
225 255 input_dev->id.product = 0x0001;
226 256 input_dev->id.version = 0x0001;
227 257  
  258 + input_dev->open = omap4_keypad_open;
  259 + input_dev->close = omap4_keypad_close;
  260 +
228 261 input_dev->keycode = keypad_data->keymap;
229 262 input_dev->keycodesize = sizeof(keypad_data->keymap[0]);
230 263 input_dev->keycodemax = max_keys;
... ... @@ -239,8 +272,6 @@
239 272 matrix_keypad_build_keymap(pdata->keymap_data, row_shift,
240 273 input_dev->keycode, input_dev->keybit);
241 274  
242   - omap4_keypad_config(keypad_data);
243   -
244 275 error = request_irq(keypad_data->irq, omap4_keypad_interrupt,
245 276 IRQF_TRIGGER_RISING,
246 277 "omap4-keypad", keypad_data);
247 278  
248 279  
249 280  
... ... @@ -249,17 +280,19 @@
249 280 goto err_free_input;
250 281 }
251 282  
  283 + pm_runtime_enable(&pdev->dev);
  284 +
252 285 error = input_register_device(keypad_data->input);
253 286 if (error < 0) {
254 287 dev_err(&pdev->dev, "failed to register input device\n");
255   - goto err_free_irq;
  288 + goto err_pm_disable;
256 289 }
257 290  
258   -
259 291 platform_set_drvdata(pdev, keypad_data);
260 292 return 0;
261 293  
262   -err_free_irq:
  294 +err_pm_disable:
  295 + pm_runtime_disable(&pdev->dev);
263 296 free_irq(keypad_data->irq, keypad_data);
264 297 err_free_input:
265 298 input_free_device(input_dev);
... ... @@ -278,6 +311,9 @@
278 311 struct resource *res;
279 312  
280 313 free_irq(keypad_data->irq, keypad_data);
  314 +
  315 + pm_runtime_disable(&pdev->dev);
  316 +
281 317 input_unregister_device(keypad_data->input);
282 318  
283 319 iounmap(keypad_data->base);