diff mbox series

[v2,4/4] input: misc: rt5120: Add power key support

Message ID 1655892104-10874-5-git-send-email-u0084500@gmail.com (mailing list archive)
State Superseded
Headers show
Series Add Richtek RT5120 PMIC support | expand

Commit Message

ChiYuan Huang June 22, 2022, 10:01 a.m. UTC
From: ChiYuan Huang <cy_huang@richtek.com>

Add RT5120 PMIC power key support.

Signed-off-by: ChiYuan Huang <cy_huang@richtek.com>
---
 drivers/input/misc/Kconfig         |   9 +++
 drivers/input/misc/Makefile        |   1 +
 drivers/input/misc/rt5120-pwrkey.c | 115 +++++++++++++++++++++++++++++++++++++
 3 files changed, 125 insertions(+)
 create mode 100644 drivers/input/misc/rt5120-pwrkey.c

Comments

Dmitry Torokhov July 9, 2022, 4:53 a.m. UTC | #1
Hi ChiYuan,

On Wed, Jun 22, 2022 at 06:01:44PM +0800, cy_huang wrote:
> +
> +	is_pressed = !(stat & RT5120_PWRKEYSTAT_MASK);
> +
> +	if ((is_pressed && irq == priv->press_irq) ||
> +	    (!is_pressed  && irq == priv->release_irq)) {
> +		input_report_key(priv->input, KEY_POWER, is_pressed);
> +		input_sync(priv->input);
> +	}
> +

What is the reason for checking both the status and interrupt? Can we
simply say:


	input_report_key(priv->input, KEY_POWER,
			 !(stat & RT5120_PWRKEYSTAT_MASK));
	input_sync(priv->input);

?

Thanks.
ChiYuan Huang July 11, 2022, 3:43 a.m. UTC | #2
Dmitry Torokhov <dmitry.torokhov@gmail.com> 於 2022年7月9日 週六 中午12:53寫道:
>
> Hi ChiYuan,
>
> On Wed, Jun 22, 2022 at 06:01:44PM +0800, cy_huang wrote:
> > +
> > +     is_pressed = !(stat & RT5120_PWRKEYSTAT_MASK);
> > +
> > +     if ((is_pressed && irq == priv->press_irq) ||
> > +         (!is_pressed  && irq == priv->release_irq)) {
> > +             input_report_key(priv->input, KEY_POWER, is_pressed);
> > +             input_sync(priv->input);
> > +     }
> > +
>
> What is the reason for checking both the status and interrupt? Can we
> simply say:
>
Just to make sure 'press/release' to matche the current state.
In the IC design, it already guarantee press/release interrupt with 50
millisecond debounce time.
But if irq is delayed handling, press and release irq will all be checked.
Although irq is one by one, but in that case, pwrkey button up will be
reported twice.
I'm not sure whether this case exists or not.
>
>         input_report_key(priv->input, KEY_POWER,
>                          !(stat & RT5120_PWRKEYSTAT_MASK));
>         input_sync(priv->input);
>
> ?
>
Yes, but how about the above comment? Is that case 'don't care'?
> Thanks.
>
> --
> Dmitry
diff mbox series

Patch

diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
index a18ab73..0b976f8 100644
--- a/drivers/input/misc/Kconfig
+++ b/drivers/input/misc/Kconfig
@@ -891,6 +891,15 @@  config INPUT_SC27XX_VIBRA
 	  To compile this driver as a module, choose M here. The module will
 	  be called sc27xx_vibra.
 
+config INPUT_RT5120_PWRKEY
+	tristate "RT5120 PMIC power key support"
+	depends on MFD_RT5120
+	help
+	  This enables support for RT5120 PMIC power key driver.
+
+	  To compile this driver as a module, choose M here. the module will
+	  be called rt5120-pwerkey.
+
 config INPUT_STPMIC1_ONKEY
 	tristate "STPMIC1 PMIC Onkey support"
 	depends on MFD_STPMIC1
diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile
index 28dfc44..d1fb00e 100644
--- a/drivers/input/misc/Makefile
+++ b/drivers/input/misc/Makefile
@@ -69,6 +69,7 @@  obj-$(CONFIG_INPUT_RAVE_SP_PWRBUTTON)	+= rave-sp-pwrbutton.o
 obj-$(CONFIG_INPUT_RB532_BUTTON)	+= rb532_button.o
 obj-$(CONFIG_INPUT_REGULATOR_HAPTIC)	+= regulator-haptic.o
 obj-$(CONFIG_INPUT_RETU_PWRBUTTON)	+= retu-pwrbutton.o
+obj-$(CONFIG_INPUT_RT5120_PWRKEY)	+= rt5120-pwrkey.o
 obj-$(CONFIG_INPUT_AXP20X_PEK)		+= axp20x-pek.o
 obj-$(CONFIG_INPUT_GPIO_ROTARY_ENCODER)	+= rotary_encoder.o
 obj-$(CONFIG_INPUT_RK805_PWRKEY)	+= rk805-pwrkey.o
diff --git a/drivers/input/misc/rt5120-pwrkey.c b/drivers/input/misc/rt5120-pwrkey.c
new file mode 100644
index 00000000..42bd2f3
--- /dev/null
+++ b/drivers/input/misc/rt5120-pwrkey.c
@@ -0,0 +1,115 @@ 
+// SPDX-License-Identifier: GPL-2.0+
+
+#include <linux/bits.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mod_devicetable.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+#define RT5120_REG_INTSTAT	0x1E
+#define RT5120_PWRKEYSTAT_MASK	BIT(7)
+
+struct rt5120_priv {
+	struct regmap *regmap;
+	struct input_dev *input;
+	int press_irq;
+	int release_irq;
+};
+
+static irqreturn_t rt5120_pwrkey_handler(int irq, void *devid)
+{
+	struct rt5120_priv *priv = devid;
+	unsigned int stat;
+	bool is_pressed;
+	int ret;
+
+	ret = regmap_read(priv->regmap, RT5120_REG_INTSTAT, &stat);
+	if (ret)
+		return IRQ_NONE;
+
+	is_pressed = !(stat & RT5120_PWRKEYSTAT_MASK);
+
+	if ((is_pressed && irq == priv->press_irq) ||
+	    (!is_pressed  && irq == priv->release_irq)) {
+		input_report_key(priv->input, KEY_POWER, is_pressed);
+		input_sync(priv->input);
+	}
+
+	return IRQ_HANDLED;
+}
+
+static int rt5120_pwrkey_probe(struct platform_device *pdev)
+{
+	struct rt5120_priv *priv;
+	int ret;
+
+	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	priv->regmap = dev_get_regmap(pdev->dev.parent, NULL);
+	if (!priv->regmap) {
+		dev_err(&pdev->dev, "Failed to init regmap\n");
+		return -ENODEV;
+	}
+
+	priv->press_irq = platform_get_irq_byname(pdev, "pwrkey-press");
+	if (priv->press_irq < 0)
+		return priv->press_irq;
+
+	priv->release_irq = platform_get_irq_byname(pdev, "pwrkey-release");
+	if (priv->release_irq < 0)
+		return priv->release_irq;
+
+	/* Make input device be device resource managed */
+	priv->input = devm_input_allocate_device(&pdev->dev);
+	if (!priv->input) {
+		dev_err(&pdev->dev, "Failed to allocate input device\n");
+		return -ENOMEM;
+	}
+
+	priv->input->name = "rt5120_pwrkey";
+	priv->input->phys = "rt5120_pwrkey/input0";
+	priv->input->id.bustype = BUS_I2C;
+	input_set_capability(priv->input, EV_KEY, KEY_POWER);
+
+	ret = input_register_device(priv->input);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to register input device\n");
+		return ret;
+	}
+
+	ret = devm_request_threaded_irq(&pdev->dev, priv->press_irq, NULL,
+					rt5120_pwrkey_handler, 0,
+					"pwrkey-press", priv);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to register pwrkey press irq\n");
+		return ret;
+	}
+
+	return devm_request_threaded_irq(&pdev->dev, priv->release_irq, NULL,
+					 rt5120_pwrkey_handler, 0,
+					 "pwrkey-release", priv);
+}
+
+static const struct of_device_id r5120_pwrkey_match_table[] = {
+	{ .compatible = "richtek,rt5120-pwrkey", },
+	{}
+};
+MODULE_DEVICE_TABLE(of, r5120_pwrkey_match_table);
+
+static struct platform_driver rt5120_pwrkey_driver = {
+	.driver = {
+		.name = "rt5120-pwrkey",
+		.of_match_table = r5120_pwrkey_match_table,
+	},
+	.probe = rt5120_pwrkey_probe,
+};
+module_platform_driver(rt5120_pwrkey_driver);
+
+MODULE_AUTHOR("ChiYuan Huang <cy_huang@richtek.com>");
+MODULE_DESCRIPTION("Richtek RT5120 power key driver");
+MODULE_LICENSE("GPL v2");