Commit 5ad567ffbaf208bd35bff4341906346c1a1d4574
Committed by
Dmitry Torokhov
1 parent
163d27706b
Exists in
master
and in
7 other branches
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); |