I am trying to get snvs-pwrkey to function on my custom hardware using a imx6Q to detect a power off request.
I modified my device tree and defconfig files to include the snvs-pwrkey driver, and I see it is instantiated and registered as a keyboard in dmesg.
However when I run evtest to test the keyboard I get no response from the keypress.
snvs-rtc is working fine, and I have another keyboard kpp working fine as well.
added to arch/arm/boot/dts/imx6qdl.dtsi
snvs_pwrkey: snvs-pwrkey@0x020cc000 {
compatible = "fsl,imx6sx-snvs-pwrkey";
reg = <0x020cc000 0x4000>;
interrupts = <0 4 IRQ_TYPE_LEVEL_HIGH>;
fsl,keycode = <116>; /* KEY_POWER */
fsl,wakeup;
};
added to arch/arm/boot/dts/imx6qdl-wandboard.dtsi
&snvs_pwrkey {
status = "okay";
};
Solved! Go to Solution.
Correct usage is:
snvs-pwrkey@0x020cc000 {
compatible = "fsl,imx6sx-snvs-pwrkey";
reg = <0x020cc000 0x4000>;
interrupts = <0 4 IRQ_TYPE_LEVEL_HIGH>;
fsl,keycode = <116>; /* KEY_POWER */
fsl,wakeup;
};
However, there is an issue with the driver.
The interrupt only triggers on the release of the key. The driver is looking for a change in the state of the key, but since the interrupt triggers on release the key value is always 0. Removing this check make the driver work fine.
I am using a quad processor, so I am not sure if this is different for the others.
Patch looks like this:
---
drivers/input/keyboard/snvs_pwrkey.c | 37 +++++++++++++++++++++---------------
1 file changed, 22 insertions(+), 15 deletions(-)
diff --git a/drivers/input/keyboard/snvs_pwrkey.c b/drivers/input/keyboard/snvs_pwrkey.c
index 1d6d62c..fa85b69 100644
--- a/drivers/input/keyboard/snvs_pwrkey.c
+++ b/drivers/input/keyboard/snvs_pwrkey.c
@@ -46,21 +46,28 @@ static void imx_imx_snvs_check_for_events(unsigned long data)
void __iomem *ioaddr = pdata->ioaddr;
u32 state;
- state = ((readl_relaxed(ioaddr + SNVS_HPSR_REG) & SNVS_HPSR_BTN) ?
- 1 : 0);
-
- /* only report new event if status changed */
- if (state ^ pdata->keystate) {
- pdata->keystate = state;
- input_event(input, EV_KEY, pdata->keycode, state);
- input_sync(input);
- }
-
- /* repeat check if pressed long */
- if (state) {
- mod_timer(&pdata->check_timer,
- jiffies + msecs_to_jiffies(60));
- }
+ //state = ((readl_relaxed(ioaddr + SNVS_HPSR_REG) & SNVS_HPSR_BTN) ? 1 : 0);
+
+ ///* only report new event if status changed */
+ //if (state ^ pdata->keystate) {
+ // pdata->keystate = state;
+ // input_event(input, EV_KEY, pdata->keycode, state);
+ // input_sync(input);
+ //}
+
+ ///* repeat check if pressed long */
+ //if (state) {
+ // mod_timer(&pdata->check_timer,
+ // jiffies + msecs_to_jiffies(60));
+ //}
+
+ /* interrupt only reports release of key so do not wait for state change */
+ state=1;
+ input_event(input, EV_KEY, pdata->keycode, state);
+ input_sync(input);
+ state=0;
+ input_event(input, EV_KEY, pdata->keycode, state);
+ input_sync(input);
}
static irqreturn_t imx_snvs_pwrkey_interrupt(int irq, void *dev_id)
--
1.9.1
I experienced the same issues with iMx6 dual. The bit 6 (BTN) in SNVS_HPSR_REG was not being set. Is there anyone from NXP can help identify the root cause ?
Correct usage is:
snvs-pwrkey@0x020cc000 {
compatible = "fsl,imx6sx-snvs-pwrkey";
reg = <0x020cc000 0x4000>;
interrupts = <0 4 IRQ_TYPE_LEVEL_HIGH>;
fsl,keycode = <116>; /* KEY_POWER */
fsl,wakeup;
};
However, there is an issue with the driver.
The interrupt only triggers on the release of the key. The driver is looking for a change in the state of the key, but since the interrupt triggers on release the key value is always 0. Removing this check make the driver work fine.
I am using a quad processor, so I am not sure if this is different for the others.
Patch looks like this:
---
drivers/input/keyboard/snvs_pwrkey.c | 37 +++++++++++++++++++++---------------
1 file changed, 22 insertions(+), 15 deletions(-)
diff --git a/drivers/input/keyboard/snvs_pwrkey.c b/drivers/input/keyboard/snvs_pwrkey.c
index 1d6d62c..fa85b69 100644
--- a/drivers/input/keyboard/snvs_pwrkey.c
+++ b/drivers/input/keyboard/snvs_pwrkey.c
@@ -46,21 +46,28 @@ static void imx_imx_snvs_check_for_events(unsigned long data)
void __iomem *ioaddr = pdata->ioaddr;
u32 state;
- state = ((readl_relaxed(ioaddr + SNVS_HPSR_REG) & SNVS_HPSR_BTN) ?
- 1 : 0);
-
- /* only report new event if status changed */
- if (state ^ pdata->keystate) {
- pdata->keystate = state;
- input_event(input, EV_KEY, pdata->keycode, state);
- input_sync(input);
- }
-
- /* repeat check if pressed long */
- if (state) {
- mod_timer(&pdata->check_timer,
- jiffies + msecs_to_jiffies(60));
- }
+ //state = ((readl_relaxed(ioaddr + SNVS_HPSR_REG) & SNVS_HPSR_BTN) ? 1 : 0);
+
+ ///* only report new event if status changed */
+ //if (state ^ pdata->keystate) {
+ // pdata->keystate = state;
+ // input_event(input, EV_KEY, pdata->keycode, state);
+ // input_sync(input);
+ //}
+
+ ///* repeat check if pressed long */
+ //if (state) {
+ // mod_timer(&pdata->check_timer,
+ // jiffies + msecs_to_jiffies(60));
+ //}
+
+ /* interrupt only reports release of key so do not wait for state change */
+ state=1;
+ input_event(input, EV_KEY, pdata->keycode, state);
+ input_sync(input);
+ state=0;
+ input_event(input, EV_KEY, pdata->keycode, state);
+ input_sync(input);
}
static irqreturn_t imx_snvs_pwrkey_interrupt(int irq, void *dev_id)
--
1.9.1
Hi Joe
one can look at linux documents in ..Documentation/devicetree/bindings/input/snvs-pwrkey.txt
[PATCH v2 2/3] document: devicetree: input: imx: i.mx snvs power device tree bindings -- Linux Input
Discussing the Linux ARM kernel
Best regards
igor
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------
Hi Igor,
Thanks for the response.
I looked at these documents and modified to match exactly:
snvs-pwrkey@0x020cc000 {
compatible = "fsl,imx6sx-snvs-pwrkey";
reg = <0x020cc000 0x4000>;
interrupts = <0 4 0x4>;
linux,keycode = <116>; /* KEY_POWER */
linux,wakeup;
};
However, I still get the same result.
Running evtest shows that the driver is loading, but it does not receive the keypress when the ON_OFF button is pressed.
If I press and hold the ON_OFF button, for 6 seconds or so, it shuts down the system as expected.
Thanks
Joe