[PATCH 1/4] Input: rk805-pwrkey - enable the wakeup interrupt during system suspend
Jakob Unterwurzacher
jakobunt at gmail.com
Thu Oct 29 03:06:23 PDT 2026
From: Jakob Unterwurzacher <jakob.unterwurzacher at cherry.de>
The driver marks the device as wakeup capable, but never enables the
power key interrupt as a wakeup interrupt. As a consequence, the PMIC
interrupt line is masked during system suspend and the power key cannot
wake up the system, e.g. from suspend-to-ram on RK3588 with an RK806.
Enable the interrupt as wakeup interrupt in the suspend callback if the
device may wake up the system, and disable it again on resume.
This is done in the regular suspend phase on purpose, rather than with
dev_pm_set_wake_irq(), which arms the wakeup in the noirq phase: there,
enabling it updates the PMIC's interrupt registers through regmap-irq,
which fails when the PMIC is connected via SPI:
spi_master spi2: Failed to power device: -13
rk8xx-spi spi2.0: Failed to sync masks in 7a
Fixes: 5a35b85c2d92 ("Input: add power key driver for Rockchip RK805 PMIC")
---
drivers/input/misc/rk805-pwrkey.c | 42 ++++++++++++++++++++++++++++++++++++++-
1 file changed, 41 insertions(+), 1 deletion(-)
diff --git a/drivers/input/misc/rk805-pwrkey.c b/drivers/input/misc/rk805-pwrkey.c
index 76873aa005b41..9b64ec7463c62 100644
--- a/drivers/input/misc/rk805-pwrkey.c
+++ b/drivers/input/misc/rk805-pwrkey.c
@@ -15,6 +15,10 @@
#include <linux/module.h>
#include <linux/platform_device.h>
+struct rk805_pwrkey {
+ int irq;
+};
+
static irqreturn_t pwrkey_fall_irq(int irq, void *_pwr)
{
struct input_dev *pwr = _pwr;
@@ -37,10 +41,15 @@ static irqreturn_t pwrkey_rise_irq(int irq, void *_pwr)
static int rk805_pwrkey_probe(struct platform_device *pdev)
{
+ struct rk805_pwrkey *priv;
struct input_dev *pwr;
int fall_irq, rise_irq;
int err;
+ priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
pwr = devm_input_allocate_device(&pdev->dev);
if (!pwr) {
dev_err(&pdev->dev, "Can't allocate power button\n");
@@ -84,16 +93,47 @@ static int rk805_pwrkey_probe(struct platform_device *pdev)
return err;
}
- platform_set_drvdata(pdev, pwr);
+ priv->irq = fall_irq;
+ platform_set_drvdata(pdev, priv);
device_init_wakeup(&pdev->dev, true);
return 0;
}
+/*
+ * Arm the wakeup in the regular suspend phase rather than with
+ * dev_pm_set_wake_irq(), which does it in the noirq phase: enabling the
+ * wakeup updates the PMIC's interrupt registers, which is no longer
+ * possible once the bus to the PMIC (e.g. SPI on RK806) is suspended.
+ */
+static int rk805_pwrkey_suspend(struct device *dev)
+{
+ struct rk805_pwrkey *priv = dev_get_drvdata(dev);
+
+ if (device_may_wakeup(dev))
+ enable_irq_wake(priv->irq);
+
+ return 0;
+}
+
+static int rk805_pwrkey_resume(struct device *dev)
+{
+ struct rk805_pwrkey *priv = dev_get_drvdata(dev);
+
+ if (device_may_wakeup(dev))
+ disable_irq_wake(priv->irq);
+
+ return 0;
+}
+
+static DEFINE_SIMPLE_DEV_PM_OPS(rk805_pwrkey_pm_ops, rk805_pwrkey_suspend,
+ rk805_pwrkey_resume);
+
static struct platform_driver rk805_pwrkey_driver = {
.probe = rk805_pwrkey_probe,
.driver = {
.name = "rk805-pwrkey",
+ .pm = pm_sleep_ptr(&rk805_pwrkey_pm_ops),
},
};
module_platform_driver(rk805_pwrkey_driver);
--
2.47.3
More information about the linux-arm-kernel
mailing list