[PATCH v3 3/9] Input: elan_i2c - Wait for initialization after enabling regulator supply

From: Chen-Yu Tsai

Date: Tue Jul 21 2026 - 03:59:19 EST


Elan trackpad controllers require some delay after enabling power to
the controller for the hardware and firmware to initialize:

- 2ms for hardware initialization
- 100ms for firmware initialization

Until then, the hardware will not respond to I2C transfers. This was
observed on the MT8173 Chromebooks after the regulator supply for the
trackpad was changed to "not always on".

Switch to the new regulator_enable_and_wait(). This makes sure that
enough time has passed since the regulator was first enabled, satisfying
the power sequencing delay requirement. This allows the delay to be
skipped if the regulator supply was already enabled by some other part
of the kernel, such as the I2C OF component prober.

Fixes: 6696777c6506 ("Input: add driver for Elan I2C/SMbus touchpad")
Signed-off-by: Chen-Yu Tsai <wenst@xxxxxxxxxxxx>
---
Changes since v2:
- Switched to new regulator_enable_and_wait() API

Changes since v1:
- Delay only if the regulator was previously disabled / turned off
- Link to v1
https://lore.kernel.org/all/20241001093815.2481899-1-wenst@xxxxxxxxxxxx/
---
drivers/input/mouse/elan_i2c_core.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/drivers/input/mouse/elan_i2c_core.c b/drivers/input/mouse/elan_i2c_core.c
index 9f024a435dbf..77885930bf9e 100644
--- a/drivers/input/mouse/elan_i2c_core.c
+++ b/drivers/input/mouse/elan_i2c_core.c
@@ -36,6 +36,7 @@
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/string_choices.h>
+#include <linux/time.h>
#include <linux/uaccess.h>
#include <linux/unaligned.h>

@@ -47,6 +48,8 @@
#define ETP_FWIDTH_REDUCE 90
#define ETP_FINGER_WIDTH 15
#define ETP_RETRY_COUNT 3
+/* H/W init 2 ms + F/W init 100 ms w/ round up */
+#define ETP_POWER_ON_DELAY_US (110 * USEC_PER_MSEC)

/* quirks to control the device */
#define ETP_QUIRK_QUICK_WAKEUP BIT(0)
@@ -1250,7 +1253,7 @@ static int elan_probe(struct i2c_client *client)
if (IS_ERR(data->vcc))
return dev_err_probe(dev, PTR_ERR(data->vcc), "Failed to get 'vcc' regulator\n");

- error = regulator_enable(data->vcc);
+ error = regulator_enable_and_wait(data->vcc, ETP_POWER_ON_DELAY_US);
if (error) {
dev_err(dev, "Failed to enable regulator: %d\n", error);
return error;
@@ -1406,7 +1409,7 @@ static int elan_resume(struct device *dev)
int error;

if (!device_may_wakeup(dev)) {
- error = regulator_enable(data->vcc);
+ error = regulator_enable_and_wait(data->vcc, ETP_POWER_ON_DELAY_US);
if (error) {
dev_err(dev, "error %d enabling regulator\n", error);
goto err;
--
2.55.0.229.g6434b31f56-goog