aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input/keyboard/omap4-keypad.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/input/keyboard/omap4-keypad.c')
-rw-r--r--drivers/input/keyboard/omap4-keypad.c95
1 files changed, 71 insertions, 24 deletions
diff --git a/drivers/input/keyboard/omap4-keypad.c b/drivers/input/keyboard/omap4-keypad.c
index f4aa53a1fd69..30acfd49fa6c 100644
--- a/drivers/input/keyboard/omap4-keypad.c
+++ b/drivers/input/keyboard/omap4-keypad.c
@@ -53,21 +53,17 @@
53#define OMAP4_KBD_FULLCODE63_32 0x48 53#define OMAP4_KBD_FULLCODE63_32 0x48
54 54
55/* OMAP4 bit definitions */ 55/* OMAP4 bit definitions */
56#define OMAP4_DEF_IRQENABLE_EVENTEN (1 << 0) 56#define OMAP4_DEF_IRQENABLE_EVENTEN BIT(0)
57#define OMAP4_DEF_IRQENABLE_LONGKEY (1 << 1) 57#define OMAP4_DEF_IRQENABLE_LONGKEY BIT(1)
58#define OMAP4_DEF_IRQENABLE_TIMEOUTEN (1 << 2) 58#define OMAP4_DEF_WUP_EVENT_ENA BIT(0)
59#define OMAP4_DEF_WUP_EVENT_ENA (1 << 0) 59#define OMAP4_DEF_WUP_LONG_KEY_ENA BIT(1)
60#define OMAP4_DEF_WUP_LONG_KEY_ENA (1 << 1) 60#define OMAP4_DEF_CTRL_NOSOFTMODE BIT(1)
61#define OMAP4_DEF_CTRL_NOSOFTMODE (1 << 1) 61#define OMAP4_DEF_CTRL_PTV_SHIFT 2
62#define OMAP4_DEF_CTRLPTVVALUE (1 << 2)
63#define OMAP4_DEF_CTRLPTV (1 << 1)
64 62
65/* OMAP4 values */ 63/* OMAP4 values */
66#define OMAP4_VAL_IRQDISABLE 0x00 64#define OMAP4_VAL_IRQDISABLE 0x0
67#define OMAP4_VAL_DEBOUNCINGTIME 0x07 65#define OMAP4_VAL_DEBOUNCINGTIME 0x7
68#define OMAP4_VAL_FUNCTIONALCFG 0x1E 66#define OMAP4_VAL_PVT 0x7
69
70#define OMAP4_MASK_IRQSTATUSDISABLE 0xFFFF
71 67
72enum { 68enum {
73 KBD_REVISION_OMAP4 = 0, 69 KBD_REVISION_OMAP4 = 0,
@@ -78,6 +74,7 @@ struct omap4_keypad {
78 struct input_dev *input; 74 struct input_dev *input;
79 75
80 void __iomem *base; 76 void __iomem *base;
77 bool irq_wake_enabled;
81 unsigned int irq; 78 unsigned int irq;
82 79
83 unsigned int rows; 80 unsigned int rows;
@@ -116,8 +113,22 @@ static void kbd_write_irqreg(struct omap4_keypad *keypad_data,
116} 113}
117 114
118 115
119/* Interrupt handler */ 116/* Interrupt handlers */
120static irqreturn_t omap4_keypad_interrupt(int irq, void *dev_id) 117static irqreturn_t omap4_keypad_irq_handler(int irq, void *dev_id)
118{
119 struct omap4_keypad *keypad_data = dev_id;
120
121 if (kbd_read_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS)) {
122 /* Disable interrupts */
123 kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQENABLE,
124 OMAP4_VAL_IRQDISABLE);
125 return IRQ_WAKE_THREAD;
126 }
127
128 return IRQ_NONE;
129}
130
131static irqreturn_t omap4_keypad_irq_thread_fn(int irq, void *dev_id)
121{ 132{
122 struct omap4_keypad *keypad_data = dev_id; 133 struct omap4_keypad *keypad_data = dev_id;
123 struct input_dev *input_dev = keypad_data->input; 134 struct input_dev *input_dev = keypad_data->input;
@@ -125,10 +136,6 @@ static irqreturn_t omap4_keypad_interrupt(int irq, void *dev_id)
125 unsigned int col, row, code, changed; 136 unsigned int col, row, code, changed;
126 u32 *new_state = (u32 *) key_state; 137 u32 *new_state = (u32 *) key_state;
127 138
128 /* Disable interrupts */
129 kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQENABLE,
130 OMAP4_VAL_IRQDISABLE);
131
132 *new_state = kbd_readl(keypad_data, OMAP4_KBD_FULLCODE31_0); 139 *new_state = kbd_readl(keypad_data, OMAP4_KBD_FULLCODE31_0);
133 *(new_state + 1) = kbd_readl(keypad_data, OMAP4_KBD_FULLCODE63_32); 140 *(new_state + 1) = kbd_readl(keypad_data, OMAP4_KBD_FULLCODE63_32);
134 141
@@ -175,11 +182,13 @@ static int omap4_keypad_open(struct input_dev *input)
175 disable_irq(keypad_data->irq); 182 disable_irq(keypad_data->irq);
176 183
177 kbd_writel(keypad_data, OMAP4_KBD_CTRL, 184 kbd_writel(keypad_data, OMAP4_KBD_CTRL,
178 OMAP4_VAL_FUNCTIONALCFG); 185 OMAP4_DEF_CTRL_NOSOFTMODE |
186 (OMAP4_VAL_PVT << OMAP4_DEF_CTRL_PTV_SHIFT));
179 kbd_writel(keypad_data, OMAP4_KBD_DEBOUNCINGTIME, 187 kbd_writel(keypad_data, OMAP4_KBD_DEBOUNCINGTIME,
180 OMAP4_VAL_DEBOUNCINGTIME); 188 OMAP4_VAL_DEBOUNCINGTIME);
189 /* clear pending interrupts */
181 kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS, 190 kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS,
182 OMAP4_VAL_IRQDISABLE); 191 kbd_read_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS));
183 kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQENABLE, 192 kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQENABLE,
184 OMAP4_DEF_IRQENABLE_EVENTEN | 193 OMAP4_DEF_IRQENABLE_EVENTEN |
185 OMAP4_DEF_IRQENABLE_LONGKEY); 194 OMAP4_DEF_IRQENABLE_LONGKEY);
@@ -363,14 +372,15 @@ static int omap4_keypad_probe(struct platform_device *pdev)
363 goto err_free_keymap; 372 goto err_free_keymap;
364 } 373 }
365 374
366 error = request_irq(keypad_data->irq, omap4_keypad_interrupt, 375 error = request_threaded_irq(keypad_data->irq, omap4_keypad_irq_handler,
367 IRQF_TRIGGER_RISING, 376 omap4_keypad_irq_thread_fn, 0,
368 "omap4-keypad", keypad_data); 377 "omap4-keypad", keypad_data);
369 if (error) { 378 if (error) {
370 dev_err(&pdev->dev, "failed to register interrupt\n"); 379 dev_err(&pdev->dev, "failed to register interrupt\n");
371 goto err_free_input; 380 goto err_free_input;
372 } 381 }
373 382
383 device_init_wakeup(&pdev->dev, true);
374 pm_runtime_put_sync(&pdev->dev); 384 pm_runtime_put_sync(&pdev->dev);
375 385
376 error = input_register_device(keypad_data->input); 386 error = input_register_device(keypad_data->input);
@@ -384,6 +394,7 @@ static int omap4_keypad_probe(struct platform_device *pdev)
384 394
385err_pm_disable: 395err_pm_disable:
386 pm_runtime_disable(&pdev->dev); 396 pm_runtime_disable(&pdev->dev);
397 device_init_wakeup(&pdev->dev, false);
387 free_irq(keypad_data->irq, keypad_data); 398 free_irq(keypad_data->irq, keypad_data);
388err_free_keymap: 399err_free_keymap:
389 kfree(keypad_data->keymap); 400 kfree(keypad_data->keymap);
@@ -409,6 +420,8 @@ static int omap4_keypad_remove(struct platform_device *pdev)
409 420
410 pm_runtime_disable(&pdev->dev); 421 pm_runtime_disable(&pdev->dev);
411 422
423 device_init_wakeup(&pdev->dev, false);
424
412 input_unregister_device(keypad_data->input); 425 input_unregister_device(keypad_data->input);
413 426
414 iounmap(keypad_data->base); 427 iounmap(keypad_data->base);
@@ -430,12 +443,46 @@ static const struct of_device_id omap_keypad_dt_match[] = {
430MODULE_DEVICE_TABLE(of, omap_keypad_dt_match); 443MODULE_DEVICE_TABLE(of, omap_keypad_dt_match);
431#endif 444#endif
432 445
446#ifdef CONFIG_PM_SLEEP
447static int omap4_keypad_suspend(struct device *dev)
448{
449 struct platform_device *pdev = to_platform_device(dev);
450 struct omap4_keypad *keypad_data = platform_get_drvdata(pdev);
451 int error;
452
453 if (device_may_wakeup(&pdev->dev)) {
454 error = enable_irq_wake(keypad_data->irq);
455 if (!error)
456 keypad_data->irq_wake_enabled = true;
457 }
458
459 return 0;
460}
461
462static int omap4_keypad_resume(struct device *dev)
463{
464 struct platform_device *pdev = to_platform_device(dev);
465 struct omap4_keypad *keypad_data = platform_get_drvdata(pdev);
466
467 if (device_may_wakeup(&pdev->dev) && keypad_data->irq_wake_enabled) {
468 disable_irq_wake(keypad_data->irq);
469 keypad_data->irq_wake_enabled = false;
470 }
471
472 return 0;
473}
474#endif
475
476static SIMPLE_DEV_PM_OPS(omap4_keypad_pm_ops,
477 omap4_keypad_suspend, omap4_keypad_resume);
478
433static struct platform_driver omap4_keypad_driver = { 479static struct platform_driver omap4_keypad_driver = {
434 .probe = omap4_keypad_probe, 480 .probe = omap4_keypad_probe,
435 .remove = omap4_keypad_remove, 481 .remove = omap4_keypad_remove,
436 .driver = { 482 .driver = {
437 .name = "omap4-keypad", 483 .name = "omap4-keypad",
438 .owner = THIS_MODULE, 484 .owner = THIS_MODULE,
485 .pm = &omap4_keypad_pm_ops,
439 .of_match_table = of_match_ptr(omap_keypad_dt_match), 486 .of_match_table = of_match_ptr(omap_keypad_dt_match),
440 }, 487 },
441}; 488};