[PATCH 2/2] Input: Touchscreen: tsc200x - delegate wakeup IRQ management to I2C core

phucduc.bui@gmail.com posted 2 patches 1 month ago
[PATCH 2/2] Input: Touchscreen: tsc200x - delegate wakeup IRQ management to I2C core
Posted by phucduc.bui@gmail.com 1 month ago
From: bui duc phuc <phucduc.bui@gmail.com>

The tsc200x driver supports both I2C (tsc2004) and SPI (tsc2005)
 interfaces.
Currently, the driver attempts to manually manage the wakeup interrupt by
calling enable_irq_wake() and disable_irq_wake() during suspend and resume.

However, for I2C devices, the I2C core already automatically handles the
wakeup source initialization and IRQ management if the "wakeup-source"
property is present in the device tree. Manually managing it again in the
driver is redundant and can lead to unbalanced IRQ wake reference counts.

Clean up the wakeup IRQ handling by checking the bus type:
- For I2C (BUS_I2C): Rely entirely on the I2C core for wakeup management.
- For SPI (BUS_SPI): Explicitly call device_init_wakeup() in probe and
  manually manage enable/disable_irq_wake() during suspend/resume.

The ts->wake_irq_enabled flag is also updated accordingly to ensure the
driver accurately tracks the wakeup state across both buses.

Note: This patch is based on code analysis of the I2C subsystem and
has not been verified on actual hardware yet.

Signed-off-by: bui duc phuc <phucduc.bui@gmail.com>
---
 drivers/input/touchscreen/tsc200x-core.c | 18 +++++++++++++-----
 1 file changed, 13 insertions(+), 5 deletions(-)

diff --git a/drivers/input/touchscreen/tsc200x-core.c b/drivers/input/touchscreen/tsc200x-core.c
index eba53613b005..d14d967845c8 100644
--- a/drivers/input/touchscreen/tsc200x-core.c
+++ b/drivers/input/touchscreen/tsc200x-core.c
@@ -465,6 +465,7 @@ int tsc200x_probe(struct device *dev, int irq, const struct input_id *tsc_id,
 	ts->idev = input_dev;
 	ts->regmap = regmap;
 	ts->tsc200x_cmd = tsc200x_cmd;
+	ts->bustype = tsc_id->bustype;
 
 	error = device_property_read_u32(dev, "ti,x-plate-ohms", &x_plate_ohm);
 	ts->x_plate_ohm = error ? TSC200X_DEF_RESISTOR : x_plate_ohm;
@@ -547,8 +548,9 @@ int tsc200x_probe(struct device *dev, int irq, const struct input_id *tsc_id,
 		return error;
 	}
 
-	device_init_wakeup(dev,
-			   device_property_read_bool(dev, "wakeup-source"));
+	if (ts->bustype == BUS_SPI)
+		device_init_wakeup(dev,
+				 device_property_read_bool(dev, "wakeup-source"));
 
 	return 0;
 }
@@ -565,8 +567,13 @@ static int tsc200x_suspend(struct device *dev)
 
 	ts->suspended = true;
 
-	if (device_may_wakeup(dev))
-		ts->wake_irq_enabled = enable_irq_wake(ts->irq) == 0;
+	if (device_may_wakeup(dev)) {
+		if (ts->bustype == BUS_SPI)
+			ts->wake_irq_enabled = enable_irq_wake(ts->irq) == 0;
+		else
+			ts->wake_irq_enabled = true;
+	} else
+		ts->wake_irq_enabled = false;
 
 	return 0;
 }
@@ -578,7 +585,8 @@ static int tsc200x_resume(struct device *dev)
 	guard(mutex)(&ts->mutex);
 
 	if (ts->wake_irq_enabled) {
-		disable_irq_wake(ts->irq);
+		if (ts->bustype == BUS_SPI)
+			disable_irq_wake(ts->irq);
 		ts->wake_irq_enabled = false;
 	}
 
-- 
2.43.0
Re: [PATCH 2/2] Input: Touchscreen: tsc200x - delegate wakeup IRQ management to I2C core
Posted by Dmitry Torokhov 4 weeks, 1 day ago
On Mon, Mar 09, 2026 at 06:00:44PM +0700, phucduc.bui@gmail.com wrote:
> From: bui duc phuc <phucduc.bui@gmail.com>
> 
> The tsc200x driver supports both I2C (tsc2004) and SPI (tsc2005)
>  interfaces.
> Currently, the driver attempts to manually manage the wakeup interrupt by
> calling enable_irq_wake() and disable_irq_wake() during suspend and resume.
> 
> However, for I2C devices, the I2C core already automatically handles the
> wakeup source initialization and IRQ management if the "wakeup-source"
> property is present in the device tree. Manually managing it again in the
> driver is redundant and can lead to unbalanced IRQ wake reference counts.
> 
> Clean up the wakeup IRQ handling by checking the bus type:
> - For I2C (BUS_I2C): Rely entirely on the I2C core for wakeup management.
> - For SPI (BUS_SPI): Explicitly call device_init_wakeup() in probe and
>   manually manage enable/disable_irq_wake() during suspend/resume.
> 
> The ts->wake_irq_enabled flag is also updated accordingly to ensure the
> driver accurately tracks the wakeup state across both buses.
> 
> Note: This patch is based on code analysis of the I2C subsystem and
> has not been verified on actual hardware yet.
> 
> Signed-off-by: bui duc phuc <phucduc.bui@gmail.com>
> ---
>  drivers/input/touchscreen/tsc200x-core.c | 18 +++++++++++++-----
>  1 file changed, 13 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/input/touchscreen/tsc200x-core.c b/drivers/input/touchscreen/tsc200x-core.c
> index eba53613b005..d14d967845c8 100644
> --- a/drivers/input/touchscreen/tsc200x-core.c
> +++ b/drivers/input/touchscreen/tsc200x-core.c
> @@ -465,6 +465,7 @@ int tsc200x_probe(struct device *dev, int irq, const struct input_id *tsc_id,
>  	ts->idev = input_dev;
>  	ts->regmap = regmap;
>  	ts->tsc200x_cmd = tsc200x_cmd;
> +	ts->bustype = tsc_id->bustype;
>  
>  	error = device_property_read_u32(dev, "ti,x-plate-ohms", &x_plate_ohm);
>  	ts->x_plate_ohm = error ? TSC200X_DEF_RESISTOR : x_plate_ohm;
> @@ -547,8 +548,9 @@ int tsc200x_probe(struct device *dev, int irq, const struct input_id *tsc_id,
>  		return error;
>  	}
>  
> -	device_init_wakeup(dev,
> -			   device_property_read_bool(dev, "wakeup-source"));
> +	if (ts->bustype == BUS_SPI)
> +		device_init_wakeup(dev,
> +				 device_property_read_bool(dev, "wakeup-source"));
>  
>  	return 0;
>  }
> @@ -565,8 +567,13 @@ static int tsc200x_suspend(struct device *dev)
>  
>  	ts->suspended = true;
>  
> -	if (device_may_wakeup(dev))
> -		ts->wake_irq_enabled = enable_irq_wake(ts->irq) == 0;
> +	if (device_may_wakeup(dev)) {
> +		if (ts->bustype == BUS_SPI)
> +			ts->wake_irq_enabled = enable_irq_wake(ts->irq) == 0;
> +		else
> +			ts->wake_irq_enabled = true;
> +	} else
> +		ts->wake_irq_enabled = false;

Sorry, but this just makes it all worse. There is no downside from
letting the driver to control wakeup if it wants to, so I'd rather leave
it as it was, at least for now.

Thanks.

-- 
Dmitry
[PATCH 2/2] Input: Touchscreen: tsc200x - delegate wakeup IRQ
Posted by phucduc.bui@gmail.com 4 weeks, 1 day ago
Hi Dmitry,

> Sorry, but this just makes it all worse. There is no downside from
> letting the driver to control wakeup if it wants to, so I'd rather leave
> it as it was, at least for now.

Thanks you for your reply

I was thinking that the code might be simplified by removing
ts->wake_irq_enabled.

In resume(), we could just check device_may_wakeup(dev) before calling
disable_irq_wake(ts->irq). From what I can see, wake_irq_enabled is only
used there, so it seems redundant.

I don't have the hardware to test this right now, so I didn't try the
change myself.

Do you think it would make sense to remove this field?

Best regards,
Phuc