[PATCH 2/3] Input: add TWL603x power button

akemnade@kernel.org posted 3 patches 3 months, 3 weeks ago
There is a newer version of this series
[PATCH 2/3] Input: add TWL603x power button
Posted by akemnade@kernel.org 3 months, 3 weeks ago
From: Andreas Kemnade <andreas@kemnade.info>

Like the TWL4030, these PMICs also have a power button feature, so add
a driver for it.

Signed-off-by: Andreas Kemnade <andreas@kemnade.info>
---
 drivers/input/misc/Kconfig             |  10 +++
 drivers/input/misc/Makefile            |   1 +
 drivers/input/misc/twl6030-pwrbutton.c | 111 +++++++++++++++++++++++++++++++++
 3 files changed, 122 insertions(+)

diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
index cc2558630797e..5e2d1a5116502 100644
--- a/drivers/input/misc/Kconfig
+++ b/drivers/input/misc/Kconfig
@@ -569,6 +569,16 @@ config INPUT_TWL4030_VIBRA
 	  To compile this driver as a module, choose M here. The module will
 	  be called twl4030_vibra.
 
+config INPUT_TWL6030_PWRBUTTON
+	tristate "TWL6030 Power button Driver"
+	depends on TWL4030_CORE
+	help
+	  Say Y here if you want to enable power key reporting via the
+	  TWL6030 family of chips.
+
+	  To compile this driver as a module, choose M here. The module will
+	  be called twl4030_pwrbutton.
+
 config INPUT_TWL6040_VIBRA
 	tristate "Support for TWL6040 Vibrator"
 	depends on TWL6040_CORE
diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile
index f5ebfa9d99831..596c013261f44 100644
--- a/drivers/input/misc/Makefile
+++ b/drivers/input/misc/Makefile
@@ -88,6 +88,7 @@ obj-$(CONFIG_INPUT_TPS65219_PWRBUTTON)	+= tps65219-pwrbutton.o
 obj-$(CONFIG_INPUT_TPS6594_PWRBUTTON)	+= tps6594-pwrbutton.o
 obj-$(CONFIG_INPUT_TWL4030_PWRBUTTON)	+= twl4030-pwrbutton.o
 obj-$(CONFIG_INPUT_TWL4030_VIBRA)	+= twl4030-vibra.o
+obj-$(CONFIG_INPUT_TWL6030_PWRBUTTON)	+= twl6030-pwrbutton.o
 obj-$(CONFIG_INPUT_TWL6040_VIBRA)	+= twl6040-vibra.o
 obj-$(CONFIG_INPUT_UINPUT)		+= uinput.o
 obj-$(CONFIG_INPUT_WISTRON_BTNS)	+= wistron_btns.o
diff --git a/drivers/input/misc/twl6030-pwrbutton.c b/drivers/input/misc/twl6030-pwrbutton.c
new file mode 100644
index 0000000000000..fb3d8dcc9088a
--- /dev/null
+++ b/drivers/input/misc/twl6030-pwrbutton.c
@@ -0,0 +1,111 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/**
+ * TWL603x power button input driver
+ *
+ * Copyright (C) 2024 Andreas Kemnade <andreas@kemnade.info>
+ *
+ * based on older 6030 driver found in a v3.0 vendor kernel
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/input.h>
+#include <linux/bits.h>
+#include <linux/interrupt.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/mfd/twl.h>
+
+#define PWR_PWRON_IRQ BIT(0)
+
+#define STS_HW_CONDITIONS 0x2
+
+static irqreturn_t powerbutton_irq(int irq, void *_pwr)
+{
+	struct input_dev *pwr = _pwr;
+	int err;
+	u8 value;
+
+	err = twl_i2c_read_u8(TWL_MODULE_PM_MASTER, &value, STS_HW_CONDITIONS);
+	if (err)
+		return IRQ_HANDLED;
+
+	pm_wakeup_event(pwr->dev.parent, 0);
+	input_report_key(pwr, KEY_POWER, value & PWR_PWRON_IRQ);
+	input_sync(pwr);
+
+	return IRQ_HANDLED;
+}
+
+static int twl6030_pwrbutton_probe(struct platform_device *pdev)
+{
+	struct input_dev *pwr;
+	int irq = platform_get_irq(pdev, 0);
+	int err;
+
+	pwr = devm_input_allocate_device(&pdev->dev);
+	if (!pwr) {
+		dev_err(&pdev->dev, "Can't allocate power button\n");
+		return -ENOMEM;
+	}
+
+	input_set_capability(pwr, EV_KEY, KEY_POWER);
+	pwr->name = "twl6030_pwrbutton";
+	pwr->phys = "twl6030_pwrbutton/input0";
+	pwr->dev.parent = &pdev->dev;
+
+	err = devm_request_threaded_irq(&pdev->dev, irq, NULL, powerbutton_irq,
+			IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING |
+			IRQF_ONESHOT,
+			"twl6030_pwrbutton", pwr);
+	if (err < 0) {
+		dev_err(&pdev->dev, "Can't get IRQ for pwrbutton: %d\n", err);
+		return err;
+	}
+
+	err = input_register_device(pwr);
+	if (err) {
+		dev_err(&pdev->dev, "Can't register power button: %d\n", err);
+		return err;
+	}
+
+	err = twl6030_interrupt_unmask(0x01, REG_INT_MSK_LINE_A);
+	if (err < 0)
+		return err;
+
+	err = twl6030_interrupt_unmask(0x01, REG_INT_MSK_STS_A);
+	if (err < 0)
+		return err;
+
+	device_init_wakeup(&pdev->dev, true);
+
+	return 0;
+}
+
+static void twl6030_pwrbutton_remove(struct platform_device *pdev)
+{
+	twl6030_interrupt_mask(0x01, REG_INT_MSK_LINE_A);
+	twl6030_interrupt_mask(0x01, REG_INT_MSK_STS_A);
+}
+
+static const struct of_device_id twl6030_pwrbutton_dt_match_table[] = {
+	{ .compatible = "ti,twl6030-pwrbutton" },
+	{},
+};
+MODULE_DEVICE_TABLE(of, twl6030_pwrbutton_dt_match_table);
+
+static struct platform_driver twl6030_pwrbutton_driver = {
+	.probe		= twl6030_pwrbutton_probe,
+	.remove		= twl6030_pwrbutton_remove,
+	.driver		= {
+		.name	= "twl6030_pwrbutton",
+		.of_match_table = of_match_ptr(twl6030_pwrbutton_dt_match_table),
+	},
+};
+module_platform_driver(twl6030_pwrbutton_driver);
+
+MODULE_ALIAS("platform:twl6030_pwrbutton");
+MODULE_DESCRIPTION("Phoenix Power Button");
+MODULE_LICENSE("GPL");

-- 
2.47.3
Re: [PATCH 2/3] Input: add TWL603x power button
Posted by Dmitry Torokhov 3 months, 2 weeks ago
On Mon, Oct 20, 2025 at 02:31:59PM +0200, akemnade@kernel.org wrote:
> From: Andreas Kemnade <andreas@kemnade.info>
> 
> Like the TWL4030, these PMICs also have a power button feature, so add
> a driver for it.

Could it be integrated into twl4030-pwrbutton.c? I think the differences
can be accounted for via a "chip" structure attached to a compatible...

Thanks.

-- 
Dmitry
Re: [PATCH 2/3] Input: add TWL603x power button
Posted by Andreas Kemnade 3 months, 2 weeks ago
On Tue, 21 Oct 2025 10:58:35 -0700
Dmitry Torokhov <dmitry.torokhov@gmail.com> wrote:

> On Mon, Oct 20, 2025 at 02:31:59PM +0200, akemnade@kernel.org wrote:
> > From: Andreas Kemnade <andreas@kemnade.info>
> > 
> > Like the TWL4030, these PMICs also have a power button feature, so add
> > a driver for it.  
> 
> Could it be integrated into twl4030-pwrbutton.c? I think the differences
> can be accounted for via a "chip" structure attached to a compatible...
> 
So what is different:
- different register (but same bit)
- some custom irq stuff for 603x (so if (is_603x) needed)
- different name for the button (can be neglected I think) 

Besides of adding a chip structure  we can do it the same way
as rtc-twl.c is doing: using twl_class_is_xxxx() which derives
its return from the parents compatible. It is simplier, but
I think the chip structure does not hurt much either.

Regards,
Andreas
Re: [PATCH 2/3] Input: add TWL603x power button
Posted by Dmitry Torokhov 3 months, 2 weeks ago
On Wed, Oct 22, 2025 at 02:44:22PM +0200, Andreas Kemnade wrote:
> On Tue, 21 Oct 2025 10:58:35 -0700
> Dmitry Torokhov <dmitry.torokhov@gmail.com> wrote:
> 
> > On Mon, Oct 20, 2025 at 02:31:59PM +0200, akemnade@kernel.org wrote:
> > > From: Andreas Kemnade <andreas@kemnade.info>
> > > 
> > > Like the TWL4030, these PMICs also have a power button feature, so add
> > > a driver for it.  
> > 
> > Could it be integrated into twl4030-pwrbutton.c? I think the differences
> > can be accounted for via a "chip" structure attached to a compatible...
> > 
> So what is different:
> - different register (but same bit)
> - some custom irq stuff for 603x (so if (is_603x) needed)

Right, why do we need to unmask the interrupt by hand for 6030? I'd
expect this handled in the core, when we request the interrupt, not in
the button driver..in the core, when we request the interrupt, not in
the button driver...

Thanks.

-- 
Dmitry
Re: [PATCH 2/3] Input: add TWL603x power button
Posted by Andreas Kemnade 3 months, 2 weeks ago
On Wed, 22 Oct 2025 11:48:59 -0700
Dmitry Torokhov <dmitry.torokhov@gmail.com> wrote:

> On Wed, Oct 22, 2025 at 02:44:22PM +0200, Andreas Kemnade wrote:
> > On Tue, 21 Oct 2025 10:58:35 -0700
> > Dmitry Torokhov <dmitry.torokhov@gmail.com> wrote:
> >   
> > > On Mon, Oct 20, 2025 at 02:31:59PM +0200, akemnade@kernel.org wrote:  
> > > > From: Andreas Kemnade <andreas@kemnade.info>
> > > > 
> > > > Like the TWL4030, these PMICs also have a power button feature, so add
> > > > a driver for it.    
> > > 
> > > Could it be integrated into twl4030-pwrbutton.c? I think the differences
> > > can be accounted for via a "chip" structure attached to a compatible...
> > >   
> > So what is different:
> > - different register (but same bit)
> > - some custom irq stuff for 603x (so if (is_603x) needed)  
> 
> Right, why do we need to unmask the interrupt by hand for 6030? I'd
> expect this handled in the core, when we request the interrupt, not in
> the button driver..in the core, when we request the interrupt, not in
> the button driver...
> 
Short answer: irqchip ops do not provide mask/unmask for 6030.

Why... Interrupts are merged. There are 3 irq registers for the whole chip
and some of these 24bits are merged to provide one interrupt per submodule.
Apparently these custom calls are there to enable the merged interrupts
individually or multiple together. That is at least my theory I derived
from my archeology session.

The thing is implemented differently for the twl4030, there you have multiple
irqs per module.

But why two calls here? With one of them the interrupt pad of the pmic reacts
to the interrupt, with the other call, the irq status register does.

So can it all be implemented differently? Probably yes, but things
need to be done carefully or with one cross-subsystem patch changing
everything in lockstep. This somehow itches me for several reasons.

Regards,
Andreas
Re: [PATCH 2/3] Input: add TWL603x power button
Posted by Krzysztof Kozlowski 3 months, 2 weeks ago
On 20/10/2025 14:31, akemnade@kernel.org wrote:
> +static const struct of_device_id twl6030_pwrbutton_dt_match_table[] = {
> +	{ .compatible = "ti,twl6030-pwrbutton" },
> +	{},
> +};
> +MODULE_DEVICE_TABLE(of, twl6030_pwrbutton_dt_match_table);
> +
> +static struct platform_driver twl6030_pwrbutton_driver = {
> +	.probe		= twl6030_pwrbutton_probe,
> +	.remove		= twl6030_pwrbutton_remove,
> +	.driver		= {
> +		.name	= "twl6030_pwrbutton",
> +		.of_match_table = of_match_ptr(twl6030_pwrbutton_dt_match_table),

Drop of match ptr, you have a warning here.

> +	},
> +};
> +module_platform_driver(twl6030_pwrbutton_driver);
> +
> +MODULE_ALIAS("platform:twl6030_pwrbutton");

You should not need MODULE_ALIAS() in normal cases. If you need it,
usually it means your device ID table is wrong (e.g. misses either
entries or MODULE_DEVICE_TABLE()). MODULE_ALIAS() is not a substitute
for incomplete ID table.


> +MODULE_DESCRIPTION("Phoenix Power Button");
> +MODULE_LICENSE("GPL");
> 


Best regards,
Krzysztof