Unlike most other power button drivers, this driver unconditionally
enables its wakeup IRQ. It should be using device_may_wakeup() to
respect the userspace configuration of wakeup sources.
Because the AXP20x MFD device uses regmap-irq, the AXP20x PEK IRQs are
nested off of regmap-irq's threaded interrupt handler. The device core
ignores such interrupts, so to actually disable wakeup, we must
explicitly disable all non-wakeup interrupts during suspend.
Signed-off-by: Samuel Holland <samuel@xxxxxxxxxxxx>
---
drivers/input/misc/axp20x-pek.c | 42 ++++++++++++++++++++++++++++++++-
1 file changed, 41 insertions(+), 1 deletion(-)
diff --git a/drivers/input/misc/axp20x-pek.c b/drivers/input/misc/axp20x-pek.c
index 7d0ee5bececb..38cd4a4aeb65 100644
--- a/drivers/input/misc/axp20x-pek.c
+++ b/drivers/input/misc/axp20x-pek.c
@@ -280,7 +280,7 @@ static int axp20x_pek_probe_input_device(struct axp20x_pek *axp20x_pek,
}
if (axp20x_pek->axp20x->variant == AXP288_ID)
- enable_irq_wake(axp20x_pek->irq_dbr);
+ device_init_wakeup(&pdev->dev, true);
return 0;
}
@@ -352,6 +352,45 @@ static int axp20x_pek_probe(struct platform_device *pdev)
return 0;
}
+#if CONFIG_PM_SLEEP
+static int axp20x_pek_suspend(struct device *dev)
+{
+ struct axp20x_pek *axp20x_pek = dev_get_drvdata(dev);
+
+ /*
+ * Nested threaded interrupts are not automatically
+ * disabled, so we must do it explicitly.
+ */
+ if (device_may_wakeup(dev)) {
+ enable_irq_wake(axp20x_pek->irq_dbf);
+ enable_irq_wake(axp20x_pek->irq_dbr);
+ } else {
+ disable_irq(axp20x_pek->irq_dbf);
+ disable_irq(axp20x_pek->irq_dbr);
+ }
+
+ return 0;
+}
+
+static int axp20x_pek_resume(struct device *dev)
+{
+ struct axp20x_pek *axp20x_pek = dev_get_drvdata(dev);
+
+ if (device_may_wakeup(dev)) {
+ disable_irq_wake(axp20x_pek->irq_dbf);
+ disable_irq_wake(axp20x_pek->irq_dbr);
+ } else {
+ enable_irq(axp20x_pek->irq_dbf);
+ enable_irq(axp20x_pek->irq_dbr);
+ }
+
+ return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(axp20x_pek_pm_ops, axp20x_pek_suspend,
+ axp20x_pek_resume);
+
static const struct platform_device_id axp_pek_id_match[] = {
{
.name = "axp20x-pek",
@@ -371,6 +410,7 @@ static struct platform_driver axp20x_pek_driver = {
.driver = {
.name = "axp20x-pek",
.dev_groups = axp20x_groups,
+ .pm = &axp20x_pek_pm_ops,
},
};
module_platform_driver(axp20x_pek_driver);