* [PATCH v2 0/2] Input: drv260x: restore configuration across power loss
@ 2026-08-27 23:16 Maurizio Casciano
2026-08-27 23:16 ` [PATCH v2 1/2] Input: drv260x: Restore configuration after device close Maurizio Casciano
2026-08-27 23:16 ` [PATCH v2 2/2] Input: drv260x: Fix suspend and resume sequencing Maurizio Casciano
0 siblings, 2 replies; 3+ messages in thread
From: Maurizio Casciano @ 2026-08-27 23:16 UTC (permalink / raw)
To: Dmitry Torokhov; +Cc: linux-input, linux-kernel, Maurizio Casciano
The DRV260x enable GPIO disables the I2C interface and resets volatile
configuration when lowered. Closing the input device or suspending the
system can therefore leave the controller unconfigured when it is used
again.
Restore the actuator configuration when the input device is reopened and
after system resume. Quiesce asynchronous force-feedback work during
suspend, restore a usable state if regulator shutdown fails, and keep the
firmware-selected actuator mode unchanged during playback.
Changes since v1:
- add a separate first patch restoring configuration after input close;
- stop overwriting the configured actuator mode during playback; and
- retain the suspend/resume sequencing fix while restoring all volatile
configuration after the enable GPIO is asserted.
The previously posted optional-vbat change is withdrawn, as requested by
Dmitry. The Yoga Book enable-GPIO mapping has also been removed from the
generic Input driver and is provided by board software nodes in the
separately posted platform/x86 v2 series.
Both patches pass strict checkpatch, W=1 and sparse v0.6.5-rc1. They were
tested on a Lenovo Yoga Book YB1-X91L with both DRV2604 devices. An
RTC-timed suspend-to-RAM and resume completed without rebooting, and both
force-feedback devices played effects afterwards without drv260x, I2C or
configuration-restore errors.
With Best Regards,
Maurizio Casciano
Maurizio Casciano (2):
Input: drv260x: Restore configuration after device close
Input: drv260x: Fix suspend and resume sequencing
drivers/input/misc/drv260x.c | 58 +++++++++++++++++++++++++++++-------
1 file changed, 48 insertions(+), 10 deletions(-)
base-commit: 9a29ee801f525bcad71fea021bfe2a030885c8df
--
2.53.0
^ permalink raw reply [flat|nested] 3+ messages in thread
* [PATCH v2 1/2] Input: drv260x: Restore configuration after device close
2026-08-27 23:16 [PATCH v2 0/2] Input: drv260x: restore configuration across power loss Maurizio Casciano
@ 2026-08-27 23:16 ` Maurizio Casciano
2026-08-27 23:16 ` [PATCH v2 2/2] Input: drv260x: Fix suspend and resume sequencing Maurizio Casciano
1 sibling, 0 replies; 3+ messages in thread
From: Maurizio Casciano @ 2026-08-27 23:16 UTC (permalink / raw)
To: Dmitry Torokhov
Cc: linux-input, linux-kernel, Maurizio Casciano, Sashiko AI review
The enable GPIO resets volatile device registers when it is lowered. The
input close callback lowers that GPIO, but the next open currently starts
playback without restoring the actuator configuration.
Raise the enable GPIO, observe the startup delay and reinitialize the
controller when the input device is opened. Keep the configured actuator
mode unchanged during playback so later initialization follows the mode
selected by firmware.
Reported-by: Sashiko AI review <sashiko-bot@kernel.org>
Link: https://lore.kernel.org/linux-input/20260827182855.DE8E91F000E9@smtp.kernel.org/
Signed-off-by: Maurizio Casciano <mauriziocasciano7@gmail.com>
---
drivers/input/misc/drv260x.c | 18 ++++++++++++++++--
1 file changed, 16 insertions(+), 2 deletions(-)
diff --git a/drivers/input/misc/drv260x.c b/drivers/input/misc/drv260x.c
index 6c5c4c53753b..f26a9052edd2 100644
--- a/drivers/input/misc/drv260x.c
+++ b/drivers/input/misc/drv260x.c
@@ -243,8 +243,6 @@ static int drv260x_haptics_play(struct input_dev *input, void *data,
{
struct drv260x_data *haptics = input_get_drvdata(input);
- haptics->mode = DRV260X_LRA_NO_CAL_MODE;
-
/* Scale u16 magnitude into u8 register value */
if (effect->u.rumble.strong_magnitude > 0)
haptics->magnitude = effect->u.rumble.strong_magnitude >> 8;
@@ -426,6 +424,21 @@ static int drv260x_init(struct drv260x_data *haptics)
return 0;
}
+static int drv260x_open(struct input_dev *input)
+{
+ struct drv260x_data *haptics = input_get_drvdata(input);
+ int error;
+
+ gpiod_set_value(haptics->enable_gpio, 1);
+ usleep_range(250, 500);
+
+ error = drv260x_init(haptics);
+ if (error)
+ gpiod_set_value(haptics->enable_gpio, 0);
+
+ return error;
+}
+
static const struct regmap_config drv260x_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
@@ -528,6 +541,7 @@ static int drv260x_probe(struct i2c_client *client)
}
haptics->input_dev->name = "drv260x:haptics";
+ haptics->input_dev->open = drv260x_open;
haptics->input_dev->close = drv260x_close;
input_set_drvdata(haptics->input_dev, haptics);
input_set_capability(haptics->input_dev, EV_FF, FF_RUMBLE);
--
2.53.0
^ permalink raw reply [flat|nested] 3+ messages in thread
* [PATCH v2 2/2] Input: drv260x: Fix suspend and resume sequencing
2026-08-27 23:16 [PATCH v2 0/2] Input: drv260x: restore configuration across power loss Maurizio Casciano
2026-08-27 23:16 ` [PATCH v2 1/2] Input: drv260x: Restore configuration after device close Maurizio Casciano
@ 2026-08-27 23:16 ` Maurizio Casciano
1 sibling, 0 replies; 3+ messages in thread
From: Maurizio Casciano @ 2026-08-27 23:16 UTC (permalink / raw)
To: Dmitry Torokhov; +Cc: linux-input, linux-kernel, Maurizio Casciano
Force-feedback playback is queued asynchronously, but system suspend
can cut the enable GPIO and vbat supply while the worker is pending.
Quiesce the worker and reject new playback requests after suspend
begins.
The enable pin also disables I2C and resets volatile configuration.
Raise it before communicating on resume, observe the startup delay,
and rerun device initialization. Restore the same state if regulator
shutdown aborts suspend.
Assisted-by: Codex:gpt-5.6-sol sparse
Signed-off-by: Maurizio Casciano <mauriziocasciano7@gmail.com>
---
drivers/input/misc/drv260x.c | 42 ++++++++++++++++++++++++++++--------
1 file changed, 33 insertions(+), 9 deletions(-)
diff --git a/drivers/input/misc/drv260x.c b/drivers/input/misc/drv260x.c
index f26a9052edd2..c64a86bc9bfd 100644
--- a/drivers/input/misc/drv260x.c
+++ b/drivers/input/misc/drv260x.c
@@ -181,6 +181,7 @@
* @work: Work item used to off load the enable/disable of the vibration
* @enable_gpio: Pointer to the gpio used for enable/disabling
* @regulator: Pointer to the regulator for the IC
+ * @suspended: Whether force-feedback work must remain quiesced
* @magnitude: Magnitude of the vibration event
* @mode: The operating mode of the IC (LRA_NO_CAL, ERM or LRA)
* @library: The vibration library to be used
@@ -194,6 +195,7 @@ struct drv260x_data {
struct work_struct work;
struct gpio_desc *enable_gpio;
struct regulator *regulator;
+ bool suspended;
u8 magnitude;
u32 mode;
u32 library;
@@ -215,6 +217,13 @@ static int drv260x_calculate_voltage(unsigned int voltage)
return (voltage * 255 / 5600);
}
+static void drv260x_set_suspended(struct drv260x_data *haptics,
+ bool suspended)
+{
+ scoped_guard(spinlock_irqsave, &haptics->input_dev->event_lock)
+ haptics->suspended = suspended;
+}
+
static void drv260x_worker(struct work_struct *work)
{
struct drv260x_data *haptics = container_of(work, struct drv260x_data, work);
@@ -243,6 +252,9 @@ static int drv260x_haptics_play(struct input_dev *input, void *data,
{
struct drv260x_data *haptics = input_get_drvdata(input);
+ if (haptics->suspended)
+ return 0;
+
/* Scale u16 magnitude into u8 register value */
if (effect->u.rumble.strong_magnitude > 0)
haptics->magnitude = effect->u.rumble.strong_magnitude >> 8;
@@ -583,17 +595,21 @@ static int drv260x_probe(struct i2c_client *client)
static int drv260x_suspend(struct device *dev)
{
struct drv260x_data *haptics = dev_get_drvdata(dev);
- int error;
+ int error, restore_error;
guard(mutex)(&haptics->input_dev->mutex);
if (input_device_enabled(haptics->input_dev)) {
+ drv260x_set_suspended(haptics, true);
+ cancel_work_sync(&haptics->work);
+
error = regmap_update_bits(haptics->regmap,
DRV260X_MODE,
DRV260X_STANDBY_MASK,
DRV260X_STANDBY);
if (error) {
dev_err(dev, "Failed to set standby mode\n");
+ drv260x_set_suspended(haptics, false);
return error;
}
@@ -602,9 +618,15 @@ static int drv260x_suspend(struct device *dev)
error = regulator_disable(haptics->regulator);
if (error) {
dev_err(dev, "Failed to disable regulator\n");
- regmap_update_bits(haptics->regmap,
- DRV260X_MODE,
- DRV260X_STANDBY_MASK, 0);
+
+ gpiod_set_value(haptics->enable_gpio, 1);
+ usleep_range(250, 500);
+ restore_error = drv260x_init(haptics);
+ if (restore_error)
+ dev_err(dev, "Failed to restore configuration: %d\n",
+ restore_error);
+
+ drv260x_set_suspended(haptics, false);
return error;
}
}
@@ -626,16 +648,18 @@ static int drv260x_resume(struct device *dev)
return error;
}
- error = regmap_update_bits(haptics->regmap,
- DRV260X_MODE,
- DRV260X_STANDBY_MASK, 0);
+ gpiod_set_value(haptics->enable_gpio, 1);
+ usleep_range(250, 500);
+
+ error = drv260x_init(haptics);
if (error) {
- dev_err(dev, "Failed to unset standby mode\n");
+ dev_err(dev, "Failed to restore configuration: %d\n", error);
+ gpiod_set_value(haptics->enable_gpio, 0);
regulator_disable(haptics->regulator);
return error;
}
- gpiod_set_value(haptics->enable_gpio, 1);
+ drv260x_set_suspended(haptics, false);
}
return 0;
--
2.53.0
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2026-08-27 23:16 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-08-27 23:16 [PATCH v2 0/2] Input: drv260x: restore configuration across power loss Maurizio Casciano
2026-08-27 23:16 ` [PATCH v2 1/2] Input: drv260x: Restore configuration after device close Maurizio Casciano
2026-08-27 23:16 ` [PATCH v2 2/2] Input: drv260x: Fix suspend and resume sequencing Maurizio Casciano
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®