[PATCH v1 2/2] Input: atmel_mxt_ts - support poweroff in suspend
Stefan Eichenberger
eichest at gmail.com
Thu Dec 7 03:13:00 PST 2023
From: Stefan Eichenberger <stefan.eichenberger at toradex.com>
Add a new device tree property to indicate that the device should be
powered off in suspend mode. We have a shared regulator that powers the
display, a USB hub and some other peripherals. The maxtouch doesn't
normally disable the regulator in suspend mode, so our extra peripherals
stay powered on. This is not desirable as it consumes more power. With
this patch we add the option to disable the regulator in suspend mode
for the maxtouch and accept the longer initialisation time.
Signed-off-by: Stefan Eichenberger <stefan.eichenberger at toradex.com>
---
drivers/input/touchscreen/atmel_mxt_ts.c | 72 ++++++++++++++++++------
1 file changed, 55 insertions(+), 17 deletions(-)
diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
index 20094b9899f0..7caa0d317d30 100644
--- a/drivers/input/touchscreen/atmel_mxt_ts.c
+++ b/drivers/input/touchscreen/atmel_mxt_ts.c
@@ -317,6 +317,7 @@ struct mxt_data {
struct gpio_desc *reset_gpio;
struct gpio_desc *wake_gpio;
bool use_retrigen_workaround;
+ bool poweroff_in_suspend;
/* Cached parameters from object table */
u16 T5_address;
@@ -2799,15 +2800,18 @@ static int mxt_configure_objects(struct mxt_data *data,
dev_warn(dev, "Error %d updating config\n", error);
}
- if (data->multitouch) {
- error = mxt_initialize_input_device(data);
- if (error)
- return error;
- } else {
- dev_warn(dev, "No touch object detected\n");
- }
+ /* If input device is not already registered */
+ if (!data->input_dev) {
+ if (data->multitouch) {
+ error = mxt_initialize_input_device(data);
+ if (error)
+ return error;
+ } else {
+ dev_warn(dev, "No touch object detected\n");
+ }
- mxt_debug_init(data);
+ mxt_debug_init(data);
+ }
return 0;
}
@@ -3328,6 +3332,8 @@ static int mxt_probe(struct i2c_client *client)
msleep(MXT_RESET_INVALID_CHG);
}
+ data->poweroff_in_suspend = device_property_read_bool(&client->dev,
+ "atmel,poweroff-in-suspend");
/*
* Controllers like mXT1386 have a dedicated WAKE line that could be
* connected to a GPIO or to I2C SCL pin, or permanently asserted low.
@@ -3390,12 +3396,21 @@ static int mxt_suspend(struct device *dev)
if (!input_dev)
return 0;
- mutex_lock(&input_dev->mutex);
+ if (!device_may_wakeup(dev) && data->poweroff_in_suspend) {
+ if (data->reset_gpio)
+ gpiod_set_value(data->reset_gpio, 1);
- if (input_device_enabled(input_dev))
- mxt_stop(data);
+ regulator_bulk_disable(ARRAY_SIZE(data->regulators),
+ data->regulators);
+ data->T44_address = 0;
+ } else {
+ mutex_lock(&input_dev->mutex);
+
+ if (input_device_enabled(input_dev))
+ mxt_stop(data);
- mutex_unlock(&input_dev->mutex);
+ mutex_unlock(&input_dev->mutex);
+ }
disable_irq(data->irq);
@@ -3411,14 +3426,37 @@ static int mxt_resume(struct device *dev)
if (!input_dev)
return 0;
- enable_irq(data->irq);
+ if (!device_may_wakeup(dev) && data->poweroff_in_suspend) {
+ int ret;
- mutex_lock(&input_dev->mutex);
+ ret = regulator_bulk_enable(ARRAY_SIZE(data->regulators),
+ data->regulators);
+ if (ret) {
+ dev_err(dev, "failed to enable regulators: %d\n",
+ ret);
+ return ret;
+ }
+ msleep(MXT_BACKUP_TIME);
- if (input_device_enabled(input_dev))
- mxt_start(data);
+ if (data->reset_gpio) {
+ /* Wait a while and then de-assert the RESET GPIO line */
+ msleep(MXT_RESET_GPIO_TIME);
+ gpiod_set_value(data->reset_gpio, 0);
+ msleep(MXT_RESET_INVALID_CHG);
+ }
- mutex_unlock(&input_dev->mutex);
+ /* This also enables the irq again */
+ mxt_initialize(data);
+ } else {
+ enable_irq(data->irq);
+
+ mutex_lock(&input_dev->mutex);
+
+ if (input_device_enabled(input_dev))
+ mxt_start(data);
+
+ mutex_unlock(&input_dev->mutex);
+ }
return 0;
}
--
2.40.1
More information about the linux-arm-kernel
mailing list