diff mbox series

[3/3] Input: da9063 - Add polling support

Message ID 20231211165708.161808-4-biju.das.jz@bp.renesas.com (mailing list archive)
State Superseded
Delegated to: Geert Uytterhoeven
Headers show
Series Add polling support for DA9063 onkey driver | expand

Commit Message

Biju Das Dec. 11, 2023, 4:57 p.m. UTC
On some platforms (eg: RZ/{G2UL,Five} SMARC EVK), there is no IRQ
populated by default. Add polling support.

While at it, doing some cleanups in da9063_poll_on().

Signed-off-by: Biju Das <biju.das.jz@bp.renesas.com>
---
 drivers/input/misc/da9063_onkey.c | 88 +++++++++++++++++++++++--------
 1 file changed, 66 insertions(+), 22 deletions(-)

Comments

Biju Das Dec. 11, 2023, 5:07 p.m. UTC | #1
Hi All,

> -----Original Message-----
> From: Biju Das <biju.das.jz@bp.renesas.com>
> Sent: Monday, December 11, 2023 4:57 PM
> Subject: [PATCH 3/3] Input: da9063 - Add polling support
> 
> On some platforms (eg: RZ/{G2UL,Five} SMARC EVK), there is no IRQ
> populated by default. Add polling support.
> 
> While at it, doing some cleanups in da9063_poll_on().
> 
> Signed-off-by: Biju Das <biju.das.jz@bp.renesas.com>
> ---
>  drivers/input/misc/da9063_onkey.c | 88 +++++++++++++++++++++++--------
>  1 file changed, 66 insertions(+), 22 deletions(-)
> 
> diff --git a/drivers/input/misc/da9063_onkey.c
> b/drivers/input/misc/da9063_onkey.c
> index 536220662b38..b9bb8c1cb758 100644
> --- a/drivers/input/misc/da9063_onkey.c
> +++ b/drivers/input/misc/da9063_onkey.c
> @@ -19,6 +19,8 @@
>  #include <linux/mfd/da9062/core.h>
>  #include <linux/mfd/da9062/registers.h>
> 
> +#define DA9062_KEY_THRESHOLD_MSEC	(200)
> +
>  struct da906x_chip_config {
>  	/* REGS */
>  	int onkey_status;
> @@ -42,6 +44,8 @@ struct da9063_onkey {
>  	const struct da906x_chip_config *config;
>  	char phys[32];
>  	bool key_power;
> +	unsigned int poll_interval;
> +	unsigned int key_threshold_release_time;
>  };
> 
>  static const struct da906x_chip_config da9063_regs = { @@ -86,15 +90,27
> @@ static void da9063_poll_on(struct work_struct *work)
>  	int error;
> 
>  	/* Poll to see when the pin is released */
> -	error = regmap_read(onkey->regmap,
> -			    config->onkey_status,
> -			    &val);
> +	error = regmap_read(onkey->regmap, config->onkey_status, &val);
>  	if (error) {
> -		dev_err(onkey->dev,
> -			"Failed to read ON status: %d\n", error);
> +		dev_err(onkey->dev, "Failed to read ON status: %d\n", error);
>  		goto err_poll;
>  	}
> 
> +	if (onkey->poll_interval &&
> +	    onkey->key_threshold_release_time <= DA9062_KEY_THRESHOLD_MSEC)
> {
> +		/* detect short press or long key press */
> +		if (!(val & config->onkey_nonkey_mask)) {
> +			input_report_key(onkey->input, KEY_POWER, 0);
> +			input_sync(onkey->input);
> +			onkey->key_threshold_release_time = 0;
> +			dev_dbg(onkey->dev, "KEY_POWER short press.\n");
> +		} else {
> +			schedule_delayed_work(&onkey->work,
> msecs_to_jiffies(50));
> +			onkey->key_threshold_release_time += 50;
> +		}
> +		return;
> +	}
> +
>  	if (!(val & config->onkey_nonkey_mask)) {
>  		error = regmap_update_bits(onkey->regmap,
>  					   config->onkey_pwr_signalling,
> @@ -177,6 +193,21 @@ static irqreturn_t da9063_onkey_irq_handler(int irq,
> void *data)
>  	return IRQ_HANDLED;
>  }
> 
> +static void da9063_onkey_polled_poll(struct input_dev *input) {
> +	struct da9063_onkey *onkey = input_get_drvdata(input);
> +	const struct da906x_chip_config *config = onkey->config;
> +	unsigned int val;
> +	int error;
> +
> +	error = regmap_read(onkey->regmap, config->onkey_status, &val);
> +	if (onkey->key_power && !error && (val & config->onkey_nonkey_mask))
> {
> +		input_report_key(onkey->input, KEY_POWER, 1);
> +		input_sync(onkey->input);
> +		schedule_delayed_work(&onkey->work, 0);
> +	}
> +}
> +
>  static int da9063_onkey_probe(struct platform_device *pdev)  {
>  	struct da9063_onkey *onkey;
> @@ -222,25 +253,38 @@ static int da9063_onkey_probe(struct platform_device
> *pdev)
>  		return dev_err_probe(&pdev->dev, error,
>  				     "Failed to add cancel poll action\n");
> 
> -	irq = platform_get_irq_byname(pdev, "ONKEY");
> -	if (irq < 0)
> +	irq = platform_get_irq_byname_optional(pdev, "ONKEY");
> +	if (irq != -ENXIO)
>  		return irq;

Oops, this check is wrong for IRQ case.

I will send v2, once I get feedback for this patch series.
It should be like [1]

[1]
 https://patchwork.kernel.org/project/linux-renesas-soc/patch/20231204130504.126787-2-biju.das.jz@bp.renesas.com/

Cheers,
Biju

> 
> -	error = devm_request_threaded_irq(&pdev->dev, irq,
> -					  NULL, da9063_onkey_irq_handler,
> -					  IRQF_TRIGGER_LOW | IRQF_ONESHOT,
> -					  "ONKEY", onkey);
> -	if (error)
> -		return dev_err_probe(&pdev->dev, error,
> -				     "Failed to request IRQ %d\n", irq);
> -
> -	error = dev_pm_set_wake_irq(&pdev->dev, irq);
> -	if (error)
> -		dev_warn(&pdev->dev,
> -			 "Failed to set IRQ %d as a wake IRQ: %d\n",
> -			 irq, error);
> -	else
> -		device_init_wakeup(&pdev->dev, true);
> +	if (irq >= 0) {
> +		error = devm_request_threaded_irq(&pdev->dev, irq,
> +						  NULL, da9063_onkey_irq_handler,
> +						  IRQF_TRIGGER_LOW | IRQF_ONESHOT,
> +						  "ONKEY", onkey);
> +		if (error)
> +			return dev_err_probe(&pdev->dev, error,
> +					     "Failed to request IRQ %d\n", irq);
> +
> +		error = dev_pm_set_wake_irq(&pdev->dev, irq);
> +		if (error)
> +			dev_warn(&pdev->dev,
> +				 "Failed to set IRQ %d as a wake IRQ: %d\n",
> +				 irq, error);
> +		else
> +			device_init_wakeup(&pdev->dev, true);
> +	} else {
> +		input_set_drvdata(onkey->input, onkey);
> +		device_property_read_u32(&pdev->dev, "poll-interval",
> +					 &onkey->poll_interval);
> +		error = input_setup_polling(onkey->input,
> +					    da9063_onkey_polled_poll);
> +		if (error)
> +			return dev_err_probe(&pdev->dev, error,
> +					     "unable to set up polling\n");
> +
> +		input_set_poll_interval(onkey->input, onkey->poll_interval);
> +	}
> 
>  	error = input_register_device(onkey->input);
>  	if (error)
> --
> 2.25.1
diff mbox series

Patch

diff --git a/drivers/input/misc/da9063_onkey.c b/drivers/input/misc/da9063_onkey.c
index 536220662b38..b9bb8c1cb758 100644
--- a/drivers/input/misc/da9063_onkey.c
+++ b/drivers/input/misc/da9063_onkey.c
@@ -19,6 +19,8 @@ 
 #include <linux/mfd/da9062/core.h>
 #include <linux/mfd/da9062/registers.h>
 
+#define DA9062_KEY_THRESHOLD_MSEC	(200)
+
 struct da906x_chip_config {
 	/* REGS */
 	int onkey_status;
@@ -42,6 +44,8 @@  struct da9063_onkey {
 	const struct da906x_chip_config *config;
 	char phys[32];
 	bool key_power;
+	unsigned int poll_interval;
+	unsigned int key_threshold_release_time;
 };
 
 static const struct da906x_chip_config da9063_regs = {
@@ -86,15 +90,27 @@  static void da9063_poll_on(struct work_struct *work)
 	int error;
 
 	/* Poll to see when the pin is released */
-	error = regmap_read(onkey->regmap,
-			    config->onkey_status,
-			    &val);
+	error = regmap_read(onkey->regmap, config->onkey_status, &val);
 	if (error) {
-		dev_err(onkey->dev,
-			"Failed to read ON status: %d\n", error);
+		dev_err(onkey->dev, "Failed to read ON status: %d\n", error);
 		goto err_poll;
 	}
 
+	if (onkey->poll_interval &&
+	    onkey->key_threshold_release_time <= DA9062_KEY_THRESHOLD_MSEC) {
+		/* detect short press or long key press */
+		if (!(val & config->onkey_nonkey_mask)) {
+			input_report_key(onkey->input, KEY_POWER, 0);
+			input_sync(onkey->input);
+			onkey->key_threshold_release_time = 0;
+			dev_dbg(onkey->dev, "KEY_POWER short press.\n");
+		} else {
+			schedule_delayed_work(&onkey->work, msecs_to_jiffies(50));
+			onkey->key_threshold_release_time += 50;
+		}
+		return;
+	}
+
 	if (!(val & config->onkey_nonkey_mask)) {
 		error = regmap_update_bits(onkey->regmap,
 					   config->onkey_pwr_signalling,
@@ -177,6 +193,21 @@  static irqreturn_t da9063_onkey_irq_handler(int irq, void *data)
 	return IRQ_HANDLED;
 }
 
+static void da9063_onkey_polled_poll(struct input_dev *input)
+{
+	struct da9063_onkey *onkey = input_get_drvdata(input);
+	const struct da906x_chip_config *config = onkey->config;
+	unsigned int val;
+	int error;
+
+	error = regmap_read(onkey->regmap, config->onkey_status, &val);
+	if (onkey->key_power && !error && (val & config->onkey_nonkey_mask)) {
+		input_report_key(onkey->input, KEY_POWER, 1);
+		input_sync(onkey->input);
+		schedule_delayed_work(&onkey->work, 0);
+	}
+}
+
 static int da9063_onkey_probe(struct platform_device *pdev)
 {
 	struct da9063_onkey *onkey;
@@ -222,25 +253,38 @@  static int da9063_onkey_probe(struct platform_device *pdev)
 		return dev_err_probe(&pdev->dev, error,
 				     "Failed to add cancel poll action\n");
 
-	irq = platform_get_irq_byname(pdev, "ONKEY");
-	if (irq < 0)
+	irq = platform_get_irq_byname_optional(pdev, "ONKEY");
+	if (irq != -ENXIO)
 		return irq;
 
-	error = devm_request_threaded_irq(&pdev->dev, irq,
-					  NULL, da9063_onkey_irq_handler,
-					  IRQF_TRIGGER_LOW | IRQF_ONESHOT,
-					  "ONKEY", onkey);
-	if (error)
-		return dev_err_probe(&pdev->dev, error,
-				     "Failed to request IRQ %d\n", irq);
-
-	error = dev_pm_set_wake_irq(&pdev->dev, irq);
-	if (error)
-		dev_warn(&pdev->dev,
-			 "Failed to set IRQ %d as a wake IRQ: %d\n",
-			 irq, error);
-	else
-		device_init_wakeup(&pdev->dev, true);
+	if (irq >= 0) {
+		error = devm_request_threaded_irq(&pdev->dev, irq,
+						  NULL, da9063_onkey_irq_handler,
+						  IRQF_TRIGGER_LOW | IRQF_ONESHOT,
+						  "ONKEY", onkey);
+		if (error)
+			return dev_err_probe(&pdev->dev, error,
+					     "Failed to request IRQ %d\n", irq);
+
+		error = dev_pm_set_wake_irq(&pdev->dev, irq);
+		if (error)
+			dev_warn(&pdev->dev,
+				 "Failed to set IRQ %d as a wake IRQ: %d\n",
+				 irq, error);
+		else
+			device_init_wakeup(&pdev->dev, true);
+	} else {
+		input_set_drvdata(onkey->input, onkey);
+		device_property_read_u32(&pdev->dev, "poll-interval",
+					 &onkey->poll_interval);
+		error = input_setup_polling(onkey->input,
+					    da9063_onkey_polled_poll);
+		if (error)
+			return dev_err_probe(&pdev->dev, error,
+					     "unable to set up polling\n");
+
+		input_set_poll_interval(onkey->input, onkey->poll_interval);
+	}
 
 	error = input_register_device(onkey->input);
 	if (error)