* [PATCH v2 0/4] snvs_pwrkey - code improvements and add report event
@ 2026-06-04 6:56 Joy Zou
2026-06-04 6:56 ` [PATCH v2 1/4] Input: snvs_pwrkey - make use of dev_err_probe() Joy Zou
` (3 more replies)
0 siblings, 4 replies; 7+ messages in thread
From: Joy Zou @ 2026-06-04 6:56 UTC (permalink / raw)
To: Dmitry Torokhov, Frank Li, Peng Fan, Jacky Bai, Ye Li
Cc: imx, linux-input, linux-kernel, Joy Zou
This patch series improves the snvs_pwrkey driver with better code quality
and add report press event.
The main improvements include:
1. Clean up the code by using local device pointers and dev_err_probe() for
better readability and easier debugging.
2. Fix potential event loss during system suspend by reporting key press events
directly in the interrupt handler.
To: Dmitry Torokhov <dmitry.torokhov@gmail.com>
To: Frank Li <Frank.Li@nxp.com>
To: Peng Fan <peng.fan@nxp.com>
To: Jacky Bai <ping.bai@nxp.com>
To: Ye Li <ye.li@nxp.com>
Cc: imx@lists.linux.dev
Cc: linux-input@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Joy Zou <joy.zou@nxp.com>
---
Changes in v2:
- Drop dev_err_probe() change for platform_get_irq() per AI review comments.
- Add new patch #2 replace hardcoding -EINVAL with original error code per
AI review comments.
- Use dev instead of &pdev->dev for devm_input_allocate_device(), which was
missed in patch v1 per AI review comments.
- Add a boolean variable suspended and PM callback functions to replace
the use of the is_suspended field per AI review comments.
- Move event report handle to else branch in suspended state, since the
pdata->minor_rev == 0 branch has no debounce detection per AI review
comments.
- Modify patch #3 and #4 commit message.
- Add Reviewed-by tag for patch #1.
- Link to v1: https://lore.kernel.org/r/20260326-pwrkey-cleanup-v1-0-d85d7c0bf275@nxp.com
---
Joy Zou (4):
Input: snvs_pwrkey - make use of dev_err_probe()
Input: snvs_pwrkey - replace hardcoding -EINVAL with original error code
Input: snvs_pwrkey - use local device pointer to simple code
Input: snvs_pwrkey - report press event in interrupt handler
drivers/input/keyboard/snvs_pwrkey.c | 102 ++++++++++++++++++++++-------------
1 file changed, 64 insertions(+), 38 deletions(-)
---
base-commit: f7af91adc230aa99e23330ecf85bc9badd9780ad
change-id: 20260326-pwrkey-cleanup-99d3de61ed6d
Best regards,
--
Joy Zou <joy.zou@nxp.com>
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH v2 1/4] Input: snvs_pwrkey - make use of dev_err_probe()
2026-06-04 6:56 [PATCH v2 0/4] snvs_pwrkey - code improvements and add report event Joy Zou
@ 2026-06-04 6:56 ` Joy Zou
2026-06-04 6:56 ` [PATCH v2 2/4] Input: snvs_pwrkey - replace hardcoding -EINVAL with original error code Joy Zou
` (2 subsequent siblings)
3 siblings, 0 replies; 7+ messages in thread
From: Joy Zou @ 2026-06-04 6:56 UTC (permalink / raw)
To: Dmitry Torokhov, Frank Li, Peng Fan, Jacky Bai, Ye Li
Cc: imx, linux-input, linux-kernel, Joy Zou
Add dev_err_probe() at return path of probe() to support users to
identify issues easier.
Reviewed-by: Frank Li <Frank.Li@nxp.com>
Signed-off-by: Joy Zou <joy.zou@nxp.com>
---
Changes in v2:
1. Drop dev_err_probe() change for platform_get_irq() per AI review comments.
2. Add Reviewed-by tag.
---
drivers/input/keyboard/snvs_pwrkey.c | 38 +++++++++++++-----------------------
1 file changed, 14 insertions(+), 24 deletions(-)
diff --git a/drivers/input/keyboard/snvs_pwrkey.c b/drivers/input/keyboard/snvs_pwrkey.c
index 954055aaf6e29527f22f8129fd47ca17722e2bc9..748196fcce75ba7192b1ee5fc516bdf4a9ae074d 100644
--- a/drivers/input/keyboard/snvs_pwrkey.c
+++ b/drivers/input/keyboard/snvs_pwrkey.c
@@ -124,17 +124,15 @@ static int imx_snvs_pwrkey_probe(struct platform_device *pdev)
/* Get SNVS register Page */
np = pdev->dev.of_node;
if (!np)
- return -ENODEV;
+ return dev_err_probe(&pdev->dev, -ENODEV, "Device tree node not found\n");
pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata)
return -ENOMEM;
pdata->snvs = syscon_regmap_lookup_by_phandle(np, "regmap");
- if (IS_ERR(pdata->snvs)) {
- dev_err(&pdev->dev, "Can't get snvs syscon\n");
- return PTR_ERR(pdata->snvs);
- }
+ if (IS_ERR(pdata->snvs))
+ return dev_err_probe(&pdev->dev, PTR_ERR(pdata->snvs), "Can't get snvs syscon\n");
if (of_property_read_u32(np, "linux,keycode", &pdata->keycode)) {
pdata->keycode = KEY_POWER;
@@ -142,10 +140,9 @@ static int imx_snvs_pwrkey_probe(struct platform_device *pdev)
}
clk = devm_clk_get_optional_enabled(&pdev->dev, NULL);
- if (IS_ERR(clk)) {
- dev_err(&pdev->dev, "Failed to get snvs clock (%pe)\n", clk);
- return PTR_ERR(clk);
- }
+ if (IS_ERR(clk))
+ return dev_err_probe(&pdev->dev, PTR_ERR(clk),
+ "Failed to get snvs clock (%pe)\n", clk);
pdata->wakeup = of_property_read_bool(np, "wakeup-source");
@@ -165,9 +162,8 @@ static int imx_snvs_pwrkey_probe(struct platform_device *pdev)
bpt = (val / 5) - 1;
break;
default:
- dev_err(&pdev->dev,
- "power-off-time-sec %d out of range\n", val);
- return -EINVAL;
+ return dev_err_probe(&pdev->dev, -EINVAL,
+ "power-off-time-sec %d out of range\n", val);
}
regmap_update_bits(pdata->snvs, SNVS_LPCR_REG, SNVS_LPCR_BPT_MASK,
@@ -198,10 +194,8 @@ static int imx_snvs_pwrkey_probe(struct platform_device *pdev)
/* input customer action to cancel release timer */
error = devm_add_action(&pdev->dev, imx_snvs_pwrkey_act, pdata);
- if (error) {
- dev_err(&pdev->dev, "failed to register remove action\n");
- return error;
- }
+ if (error)
+ return dev_err_probe(&pdev->dev, error, "failed to register remove action\n");
pdata->input = input;
platform_set_drvdata(pdev, pdata);
@@ -209,16 +203,12 @@ static int imx_snvs_pwrkey_probe(struct platform_device *pdev)
error = devm_request_irq(&pdev->dev, pdata->irq,
imx_snvs_pwrkey_interrupt,
0, pdev->name, pdev);
- if (error) {
- dev_err(&pdev->dev, "interrupt not available.\n");
- return error;
- }
+ if (error)
+ return dev_err_probe(&pdev->dev, error, "interrupt not available.\n");
error = input_register_device(input);
- if (error < 0) {
- dev_err(&pdev->dev, "failed to register input device\n");
- return error;
- }
+ if (error < 0)
+ return dev_err_probe(&pdev->dev, error, "failed to register input device\n");
device_init_wakeup(&pdev->dev, pdata->wakeup);
error = dev_pm_set_wake_irq(&pdev->dev, pdata->irq);
--
2.50.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH v2 2/4] Input: snvs_pwrkey - replace hardcoding -EINVAL with original error code
2026-06-04 6:56 [PATCH v2 0/4] snvs_pwrkey - code improvements and add report event Joy Zou
2026-06-04 6:56 ` [PATCH v2 1/4] Input: snvs_pwrkey - make use of dev_err_probe() Joy Zou
@ 2026-06-04 6:56 ` Joy Zou
2026-06-04 6:56 ` [PATCH v2 3/4] Input: snvs_pwrkey - use local device pointer to simple code Joy Zou
2026-06-04 6:56 ` [PATCH v2 4/4] Input: snvs_pwrkey - report press event in interrupt handler Joy Zou
3 siblings, 0 replies; 7+ messages in thread
From: Joy Zou @ 2026-06-04 6:56 UTC (permalink / raw)
To: Dmitry Torokhov, Frank Li, Peng Fan, Jacky Bai, Ye Li
Cc: imx, linux-input, linux-kernel, Joy Zou
Hardcoding -EINVAL discards the actual error code, which breaks probe
deferral (-EPROBE_DEFER) and loses critical diagnostic information
needed for proper kernel error handling.
Signed-off-by: Joy Zou <joy.zou@nxp.com>
---
drivers/input/keyboard/snvs_pwrkey.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/input/keyboard/snvs_pwrkey.c b/drivers/input/keyboard/snvs_pwrkey.c
index 748196fcce75ba7192b1ee5fc516bdf4a9ae074d..a291812e6d22ea963568cced5b889bad00658526 100644
--- a/drivers/input/keyboard/snvs_pwrkey.c
+++ b/drivers/input/keyboard/snvs_pwrkey.c
@@ -148,7 +148,7 @@ static int imx_snvs_pwrkey_probe(struct platform_device *pdev)
pdata->irq = platform_get_irq(pdev, 0);
if (pdata->irq < 0)
- return -EINVAL;
+ return pdata->irq;
error = of_property_read_u32(np, "power-off-time-sec", &val);
if (!error) {
--
2.50.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH v2 3/4] Input: snvs_pwrkey - use local device pointer to simple code
2026-06-04 6:56 [PATCH v2 0/4] snvs_pwrkey - code improvements and add report event Joy Zou
2026-06-04 6:56 ` [PATCH v2 1/4] Input: snvs_pwrkey - make use of dev_err_probe() Joy Zou
2026-06-04 6:56 ` [PATCH v2 2/4] Input: snvs_pwrkey - replace hardcoding -EINVAL with original error code Joy Zou
@ 2026-06-04 6:56 ` Joy Zou
2026-06-04 6:56 ` [PATCH v2 4/4] Input: snvs_pwrkey - report press event in interrupt handler Joy Zou
3 siblings, 0 replies; 7+ messages in thread
From: Joy Zou @ 2026-06-04 6:56 UTC (permalink / raw)
To: Dmitry Torokhov, Frank Li, Peng Fan, Jacky Bai, Ye Li
Cc: imx, linux-input, linux-kernel, Joy Zou
Use local struct device pointer to avoid reference the platform_device
pointer every time.
No functional change.
Signed-off-by: Joy Zou <joy.zou@nxp.com>
---
Changes for v2:
1. Use dev instead of &pdev->dev for devm_input_allocate_device(),
which was missed in patch v1 per AI review comments.
2. Modify commit message.
---
drivers/input/keyboard/snvs_pwrkey.c | 41 ++++++++++++++++++------------------
1 file changed, 21 insertions(+), 20 deletions(-)
diff --git a/drivers/input/keyboard/snvs_pwrkey.c b/drivers/input/keyboard/snvs_pwrkey.c
index a291812e6d22ea963568cced5b889bad00658526..4a1d04898482669894e9978014b62e4e9774b4e4 100644
--- a/drivers/input/keyboard/snvs_pwrkey.c
+++ b/drivers/input/keyboard/snvs_pwrkey.c
@@ -112,6 +112,7 @@ static void imx_snvs_pwrkey_act(void *pdata)
static int imx_snvs_pwrkey_probe(struct platform_device *pdev)
{
+ struct device *dev = &pdev->dev;
struct pwrkey_drv_data *pdata;
struct input_dev *input;
struct device_node *np;
@@ -122,26 +123,26 @@ static int imx_snvs_pwrkey_probe(struct platform_device *pdev)
u32 vid;
/* Get SNVS register Page */
- np = pdev->dev.of_node;
+ np = dev->of_node;
if (!np)
- return dev_err_probe(&pdev->dev, -ENODEV, "Device tree node not found\n");
+ return dev_err_probe(dev, -ENODEV, "Device tree node not found\n");
- pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
+ pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata)
return -ENOMEM;
pdata->snvs = syscon_regmap_lookup_by_phandle(np, "regmap");
if (IS_ERR(pdata->snvs))
- return dev_err_probe(&pdev->dev, PTR_ERR(pdata->snvs), "Can't get snvs syscon\n");
+ return dev_err_probe(dev, PTR_ERR(pdata->snvs), "Can't get snvs syscon\n");
if (of_property_read_u32(np, "linux,keycode", &pdata->keycode)) {
pdata->keycode = KEY_POWER;
- dev_warn(&pdev->dev, "KEY_POWER without setting in dts\n");
+ dev_warn(dev, "KEY_POWER without setting in dts\n");
}
- clk = devm_clk_get_optional_enabled(&pdev->dev, NULL);
+ clk = devm_clk_get_optional_enabled(dev, NULL);
if (IS_ERR(clk))
- return dev_err_probe(&pdev->dev, PTR_ERR(clk),
+ return dev_err_probe(dev, PTR_ERR(clk),
"Failed to get snvs clock (%pe)\n", clk);
pdata->wakeup = of_property_read_bool(np, "wakeup-source");
@@ -162,7 +163,7 @@ static int imx_snvs_pwrkey_probe(struct platform_device *pdev)
bpt = (val / 5) - 1;
break;
default:
- return dev_err_probe(&pdev->dev, -EINVAL,
+ return dev_err_probe(dev, -EINVAL,
"power-off-time-sec %d out of range\n", val);
}
@@ -180,9 +181,9 @@ static int imx_snvs_pwrkey_probe(struct platform_device *pdev)
timer_setup(&pdata->check_timer, imx_imx_snvs_check_for_events, 0);
- input = devm_input_allocate_device(&pdev->dev);
+ input = devm_input_allocate_device(dev);
if (!input) {
- dev_err(&pdev->dev, "failed to allocate the input device\n");
+ dev_err(dev, "failed to allocate the input device\n");
return -ENOMEM;
}
@@ -193,27 +194,27 @@ static int imx_snvs_pwrkey_probe(struct platform_device *pdev)
input_set_capability(input, EV_KEY, pdata->keycode);
/* input customer action to cancel release timer */
- error = devm_add_action(&pdev->dev, imx_snvs_pwrkey_act, pdata);
+ error = devm_add_action(dev, imx_snvs_pwrkey_act, pdata);
if (error)
- return dev_err_probe(&pdev->dev, error, "failed to register remove action\n");
+ return dev_err_probe(dev, error, "failed to register remove action\n");
pdata->input = input;
platform_set_drvdata(pdev, pdata);
- error = devm_request_irq(&pdev->dev, pdata->irq,
- imx_snvs_pwrkey_interrupt,
- 0, pdev->name, pdev);
+ error = devm_request_irq(dev, pdata->irq,
+ imx_snvs_pwrkey_interrupt,
+ 0, pdev->name, pdev);
if (error)
- return dev_err_probe(&pdev->dev, error, "interrupt not available.\n");
+ return dev_err_probe(dev, error, "interrupt not available.\n");
error = input_register_device(input);
if (error < 0)
- return dev_err_probe(&pdev->dev, error, "failed to register input device\n");
+ return dev_err_probe(dev, error, "failed to register input device\n");
- device_init_wakeup(&pdev->dev, pdata->wakeup);
- error = dev_pm_set_wake_irq(&pdev->dev, pdata->irq);
+ device_init_wakeup(dev, pdata->wakeup);
+ error = dev_pm_set_wake_irq(dev, pdata->irq);
if (error)
- dev_err(&pdev->dev, "irq wake enable failed.\n");
+ dev_err(dev, "irq wake enable failed.\n");
return 0;
}
--
2.50.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH v2 4/4] Input: snvs_pwrkey - report press event in interrupt handler
2026-06-04 6:56 [PATCH v2 0/4] snvs_pwrkey - code improvements and add report event Joy Zou
` (2 preceding siblings ...)
2026-06-04 6:56 ` [PATCH v2 3/4] Input: snvs_pwrkey - use local device pointer to simple code Joy Zou
@ 2026-06-04 6:56 ` Joy Zou
2026-06-05 6:59 ` Bough Chen
3 siblings, 1 reply; 7+ messages in thread
From: Joy Zou @ 2026-06-04 6:56 UTC (permalink / raw)
To: Dmitry Torokhov, Frank Li, Peng Fan, Jacky Bai, Ye Li
Cc: imx, linux-input, linux-kernel, Joy Zou
The driver implements debounce protection using a timer-based mechanism:
when a key interrupt occurs, a timer is scheduled to verify the key state
after DEBOUNCE_TIME before reporting the event. This works well during
normal operation.
However, key press events can be lost during system resume on platforms
like i.MX8MQ-EVK because:
1. During the no_irq resume phase, PCIe driver restoration can take up to
200ms with IRQs disabled.
2. The power key interrupt remains pending during the no_irq phase.
3. If the key is released before IRQs are re-enabled, the timer eventually
runs but sees the key as released and skips reporting the event.
Report key press events directly in interrupt handler to prevent event
loss during system suspend. This is safe because:
1. Only one event is reported per suspend cycle.
2. Normal operation retains the existing timer-based debounce mechanism.
Signed-off-by: Joy Zou <joy.zou@nxp.com>
---
Changes for v2:
1. Add a boolean variable suspended and PM callback functions to replace
the use of the is_suspended field per AI review comments.
2. Move event report handle to else branch in suspended state, since the
pdata->minor_rev == 0 branch has no debounce detection per AI review
comments.
3. Modify the commit message.
---
drivers/input/keyboard/snvs_pwrkey.c | 35 +++++++++++++++++++++++++++++++++++
1 file changed, 35 insertions(+)
diff --git a/drivers/input/keyboard/snvs_pwrkey.c b/drivers/input/keyboard/snvs_pwrkey.c
index 4a1d04898482669894e9978014b62e4e9774b4e4..f212a6b26185d13e1af62728e7b2add5010adc5a 100644
--- a/drivers/input/keyboard/snvs_pwrkey.c
+++ b/drivers/input/keyboard/snvs_pwrkey.c
@@ -39,6 +39,7 @@ struct pwrkey_drv_data {
int keycode;
int keystate; /* 1:pressed */
int wakeup;
+ bool suspended; /* Track suspend state */
struct timer_list check_timer;
struct input_dev *input;
u8 minor_rev;
@@ -92,6 +93,15 @@ static irqreturn_t imx_snvs_pwrkey_interrupt(int irq, void *dev_id)
input_sync(input);
pm_relax(input->dev.parent);
} else {
+ /*
+ * Report key press events directly in interrupt handler to prevent event
+ * loss during system suspend.
+ */
+ if (pdata->suspended) {
+ pdata->keystate = 1;
+ input_report_key(input, pdata->keycode, 1);
+ input_sync(input);
+ }
mod_timer(&pdata->check_timer,
jiffies + msecs_to_jiffies(DEBOUNCE_TIME));
}
@@ -219,6 +229,30 @@ static int imx_snvs_pwrkey_probe(struct platform_device *pdev)
return 0;
}
+static int __maybe_unused imx_snvs_pwrkey_suspend(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct pwrkey_drv_data *pdata = platform_get_drvdata(pdev);
+
+ pdata->suspended = true;
+
+ return 0;
+}
+
+static int __maybe_unused imx_snvs_pwrkey_resume(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct pwrkey_drv_data *pdata = platform_get_drvdata(pdev);
+
+ pdata->suspended = false;
+
+ return 0;
+}
+
+static SIMPLE_DEV_PM_OPS(imx_snvs_pwrkey_pm_ops,
+ imx_snvs_pwrkey_suspend,
+ imx_snvs_pwrkey_resume);
+
static const struct of_device_id imx_snvs_pwrkey_ids[] = {
{ .compatible = "fsl,sec-v4.0-pwrkey" },
{ /* sentinel */ }
@@ -229,6 +263,7 @@ static struct platform_driver imx_snvs_pwrkey_driver = {
.driver = {
.name = "snvs_pwrkey",
.of_match_table = imx_snvs_pwrkey_ids,
+ .pm = &imx_snvs_pwrkey_pm_ops,
},
.probe = imx_snvs_pwrkey_probe,
};
--
2.50.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH v2 4/4] Input: snvs_pwrkey - report press event in interrupt handler
2026-06-04 6:56 ` [PATCH v2 4/4] Input: snvs_pwrkey - report press event in interrupt handler Joy Zou
@ 2026-06-05 6:59 ` Bough Chen
2026-06-15 3:52 ` Joy Zou
0 siblings, 1 reply; 7+ messages in thread
From: Bough Chen @ 2026-06-05 6:59 UTC (permalink / raw)
To: Joy Zou
Cc: Dmitry Torokhov, Frank Li, Peng Fan, Jacky Bai, Ye Li, imx,
linux-input, linux-kernel
On Thu, Jun 04, 2026 at 02:56:24PM +0800, Joy Zou wrote:
> The driver implements debounce protection using a timer-based mechanism:
> when a key interrupt occurs, a timer is scheduled to verify the key state
> after DEBOUNCE_TIME before reporting the event. This works well during
> normal operation.
>
> However, key press events can be lost during system resume on platforms
> like i.MX8MQ-EVK because:
> 1. During the no_irq resume phase, PCIe driver restoration can take up to
> 200ms with IRQs disabled.
> 2. The power key interrupt remains pending during the no_irq phase.
> 3. If the key is released before IRQs are re-enabled, the timer eventually
> runs but sees the key as released and skips reporting the event.
>
> Report key press events directly in interrupt handler to prevent event
> loss during system suspend. This is safe because:
>
> 1. Only one event is reported per suspend cycle.
> 2. Normal operation retains the existing timer-based debounce mechanism.
>
> Signed-off-by: Joy Zou <joy.zou@nxp.com>
> ---
> Changes for v2:
> 1. Add a boolean variable suspended and PM callback functions to replace
> the use of the is_suspended field per AI review comments.
> 2. Move event report handle to else branch in suspended state, since the
> pdata->minor_rev == 0 branch has no debounce detection per AI review
> comments.
> 3. Modify the commit message.
> ---
> drivers/input/keyboard/snvs_pwrkey.c | 35 +++++++++++++++++++++++++++++++++++
> 1 file changed, 35 insertions(+)
>
> diff --git a/drivers/input/keyboard/snvs_pwrkey.c b/drivers/input/keyboard/snvs_pwrkey.c
> index 4a1d04898482669894e9978014b62e4e9774b4e4..f212a6b26185d13e1af62728e7b2add5010adc5a 100644
> --- a/drivers/input/keyboard/snvs_pwrkey.c
> +++ b/drivers/input/keyboard/snvs_pwrkey.c
> @@ -39,6 +39,7 @@ struct pwrkey_drv_data {
> int keycode;
> int keystate; /* 1:pressed */
> int wakeup;
> + bool suspended; /* Track suspend state */
> struct timer_list check_timer;
> struct input_dev *input;
> u8 minor_rev;
> @@ -92,6 +93,15 @@ static irqreturn_t imx_snvs_pwrkey_interrupt(int irq, void *dev_id)
> input_sync(input);
> pm_relax(input->dev.parent);
> } else {
> + /*
> + * Report key press events directly in interrupt handler to prevent event
> + * loss during system suspend.
> + */
> + if (pdata->suspended) {
Here, pdata->suspended should not be safe for SMP system, maybe to use atomic_read() to make the code more stronger.
> + pdata->keystate = 1;
> + input_report_key(input, pdata->keycode, 1);
> + input_sync(input);
> + }
> mod_timer(&pdata->check_timer,
> jiffies + msecs_to_jiffies(DEBOUNCE_TIME));
Here already report the key when pdata->suspend == true, seems do not need to trigger the timer again.
Is it more reasonable to change like this?
if (atomic_read(&pdata->suspended)) {
...
} else {
mode_timer()
}
> }
> @@ -219,6 +229,30 @@ static int imx_snvs_pwrkey_probe(struct platform_device *pdev)
> return 0;
> }
>
> +static int __maybe_unused imx_snvs_pwrkey_suspend(struct device *dev)
> +{
> + struct platform_device *pdev = to_platform_device(dev);
> + struct pwrkey_drv_data *pdata = platform_get_drvdata(pdev);
> +
> + pdata->suspended = true;
> +
atomic_set(&pdata->suspended, 1)
> + return 0;
> +}
> +
> +static int __maybe_unused imx_snvs_pwrkey_resume(struct device *dev)
> +{
> + struct platform_device *pdev = to_platform_device(dev);
> + struct pwrkey_drv_data *pdata = platform_get_drvdata(pdev);
> +
> + pdata->suspended = false;
> +
atomic_set(&pdata->suspended, 0);
Regards
Haibo Chen
> + return 0;
> +}
> +
> +static SIMPLE_DEV_PM_OPS(imx_snvs_pwrkey_pm_ops,
> + imx_snvs_pwrkey_suspend,
> + imx_snvs_pwrkey_resume);
> +
> static const struct of_device_id imx_snvs_pwrkey_ids[] = {
> { .compatible = "fsl,sec-v4.0-pwrkey" },
> { /* sentinel */ }
> @@ -229,6 +263,7 @@ static struct platform_driver imx_snvs_pwrkey_driver = {
> .driver = {
> .name = "snvs_pwrkey",
> .of_match_table = imx_snvs_pwrkey_ids,
> + .pm = &imx_snvs_pwrkey_pm_ops,
> },
> .probe = imx_snvs_pwrkey_probe,
> };
>
> --
> 2.50.1
>
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v2 4/4] Input: snvs_pwrkey - report press event in interrupt handler
2026-06-05 6:59 ` Bough Chen
@ 2026-06-15 3:52 ` Joy Zou
0 siblings, 0 replies; 7+ messages in thread
From: Joy Zou @ 2026-06-15 3:52 UTC (permalink / raw)
To: Bough Chen
Cc: Joy Zou, Dmitry Torokhov, Frank Li, Peng Fan, Jacky Bai, Ye Li,
imx, linux-input, linux-kernel
On Fri, Jun 05, 2026 at 02:59:13PM +0800, Bough Chen wrote:
> On Thu, Jun 04, 2026 at 02:56:24PM +0800, Joy Zou wrote:
> > The driver implements debounce protection using a timer-based mechanism:
> > when a key interrupt occurs, a timer is scheduled to verify the key state
> > after DEBOUNCE_TIME before reporting the event. This works well during
> > normal operation.
> >
> > However, key press events can be lost during system resume on platforms
> > like i.MX8MQ-EVK because:
> > 1. During the no_irq resume phase, PCIe driver restoration can take up to
> > 200ms with IRQs disabled.
> > 2. The power key interrupt remains pending during the no_irq phase.
> > 3. If the key is released before IRQs are re-enabled, the timer eventually
> > runs but sees the key as released and skips reporting the event.
> >
> > Report key press events directly in interrupt handler to prevent event
> > loss during system suspend. This is safe because:
> >
> > 1. Only one event is reported per suspend cycle.
> > 2. Normal operation retains the existing timer-based debounce mechanism.
> >
> > Signed-off-by: Joy Zou <joy.zou@nxp.com>
> > ---
> > Changes for v2:
> > 1. Add a boolean variable suspended and PM callback functions to replace
> > the use of the is_suspended field per AI review comments.
> > 2. Move event report handle to else branch in suspended state, since the
> > pdata->minor_rev == 0 branch has no debounce detection per AI review
> > comments.
> > 3. Modify the commit message.
> > ---
> > drivers/input/keyboard/snvs_pwrkey.c | 35 +++++++++++++++++++++++++++++++++++
> > 1 file changed, 35 insertions(+)
> >
> > diff --git a/drivers/input/keyboard/snvs_pwrkey.c b/drivers/input/keyboard/snvs_pwrkey.c
> > index 4a1d04898482669894e9978014b62e4e9774b4e4..f212a6b26185d13e1af62728e7b2add5010adc5a 100644
> > --- a/drivers/input/keyboard/snvs_pwrkey.c
> > +++ b/drivers/input/keyboard/snvs_pwrkey.c
> > @@ -39,6 +39,7 @@ struct pwrkey_drv_data {
> > int keycode;
> > int keystate; /* 1:pressed */
> > int wakeup;
> > + bool suspended; /* Track suspend state */
> > struct timer_list check_timer;
> > struct input_dev *input;
> > u8 minor_rev;
> > @@ -92,6 +93,15 @@ static irqreturn_t imx_snvs_pwrkey_interrupt(int irq, void *dev_id)
> > input_sync(input);
> > pm_relax(input->dev.parent);
> > } else {
> > + /*
> > + * Report key press events directly in interrupt handler to prevent event
> > + * loss during system suspend.
> > + */
> > + if (pdata->suspended) {
>
> Here, pdata->suspended should not be safe for SMP system, maybe to use atomic_read() to make the code more stronger.
Thanks for your comments! You're right that pdata->suspended needs protection.
However, AI review found there are the pdata->keystate that also need protection.
Instead of using atomic operations for individual fields, I think it would be
more maintainable to use a single lock to protect all related fields consistently.
>
> > + pdata->keystate = 1;
> > + input_report_key(input, pdata->keycode, 1);
> > + input_sync(input);
> > + }
> > mod_timer(&pdata->check_timer,
> > jiffies + msecs_to_jiffies(DEBOUNCE_TIME));
>
> Here already report the key when pdata->suspend == true, seems do not need to trigger the timer again.
> Is it more reasonable to change like this?
> if (atomic_read(&pdata->suspended)) {
> ...
> } else {
> mode_timer()
> }
Have checked the interrupt handler only report directly press event, still need
to report release event in timer callback. So can't use the way.
BR
Joy Zou
>
> > }
> > @@ -219,6 +229,30 @@ static int imx_snvs_pwrkey_probe(struct platform_device *pdev)
> > return 0;
> > }
> >
> > +static int __maybe_unused imx_snvs_pwrkey_suspend(struct device *dev)
> > +{
> > + struct platform_device *pdev = to_platform_device(dev);
> > + struct pwrkey_drv_data *pdata = platform_get_drvdata(pdev);
> > +
> > + pdata->suspended = true;
> > +
>
> atomic_set(&pdata->suspended, 1)
>
> > + return 0;
> > +}
> > +
> > +static int __maybe_unused imx_snvs_pwrkey_resume(struct device *dev)
> > +{
> > + struct platform_device *pdev = to_platform_device(dev);
> > + struct pwrkey_drv_data *pdata = platform_get_drvdata(pdev);
> > +
> > + pdata->suspended = false;
> > +
>
> atomic_set(&pdata->suspended, 0);
>
> Regards
> Haibo Chen
> > + return 0;
> > +}
> > +
> > +static SIMPLE_DEV_PM_OPS(imx_snvs_pwrkey_pm_ops,
> > + imx_snvs_pwrkey_suspend,
> > + imx_snvs_pwrkey_resume);
> > +
> > static const struct of_device_id imx_snvs_pwrkey_ids[] = {
> > { .compatible = "fsl,sec-v4.0-pwrkey" },
> > { /* sentinel */ }
> > @@ -229,6 +263,7 @@ static struct platform_driver imx_snvs_pwrkey_driver = {
> > .driver = {
> > .name = "snvs_pwrkey",
> > .of_match_table = imx_snvs_pwrkey_ids,
> > + .pm = &imx_snvs_pwrkey_pm_ops,
> > },
> > .probe = imx_snvs_pwrkey_probe,
> > };
> >
> > --
> > 2.50.1
> >
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2026-06-15 3:49 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-06-04 6:56 [PATCH v2 0/4] snvs_pwrkey - code improvements and add report event Joy Zou
2026-06-04 6:56 ` [PATCH v2 1/4] Input: snvs_pwrkey - make use of dev_err_probe() Joy Zou
2026-06-04 6:56 ` [PATCH v2 2/4] Input: snvs_pwrkey - replace hardcoding -EINVAL with original error code Joy Zou
2026-06-04 6:56 ` [PATCH v2 3/4] Input: snvs_pwrkey - use local device pointer to simple code Joy Zou
2026-06-04 6:56 ` [PATCH v2 4/4] Input: snvs_pwrkey - report press event in interrupt handler Joy Zou
2026-06-05 6:59 ` Bough Chen
2026-06-15 3:52 ` Joy Zou
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox