]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
power: reset: tdx-ec-poweroff: fix restart
authorEmanuele Ghidoli <emanuele.ghidoli@toradex.com>
Fri, 30 Jan 2026 07:11:35 +0000 (08:11 +0100)
committerSebastian Reichel <sebastian.reichel@collabora.com>
Fri, 30 Jan 2026 19:39:37 +0000 (20:39 +0100)
During testing, restart occasionally failed on Toradex modules.

The issue was traced to an interaction between the EC-based reset/poweroff
handler and the PSCI restart handler. While the embedded controller is
resetting or powering off the module, the PSCI code may still be invoked,
triggering an I2C transaction to the PMIC. This can leave the PMIC I2C
in a frozen state.

Add a delay after issuing the EC reset or power-off command to give the
controller time to complete the operation and avoid falling back to another
restart/poweroff provider.

Also print an error message if sending the command to the embedded controller
fails.

Fixes: 18672fe12367 ("power: reset: add Toradex Embedded Controller")
Cc: stable@vger.kernel.org
Signed-off-by: Emanuele Ghidoli <emanuele.ghidoli@toradex.com>
Reviewed-by: Francesco Dolcini <francesco.dolcini@toradex.com>
Link: https://patch.msgid.link/20260130071208.1184239-1-ghidoliemanuele@gmail.com
Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
drivers/power/reset/tdx-ec-poweroff.c

index 3302a127fce522420396652a2a0c5cb9257a2fde..8040aa03d74d4fab615946820db1cddf928a8b9f 100644 (file)
@@ -8,7 +8,10 @@
  */
 
 #include <linux/array_size.h>
+#include <linux/bug.h>
+#include <linux/delay.h>
 #include <linux/device.h>
+#include <linux/dev_printk.h>
 #include <linux/err.h>
 #include <linux/i2c.h>
 #include <linux/mod_devicetable.h>
@@ -31,6 +34,8 @@
 
 #define EC_REG_MAX                      0xD0
 
+#define EC_CMD_TIMEOUT_MS              1000
+
 static const struct regmap_range volatile_ranges[] = {
        regmap_reg_range(EC_CMD_REG, EC_CMD_REG),
 };
@@ -75,6 +80,13 @@ static int tdx_ec_power_off(struct sys_off_data *data)
 
        err = tdx_ec_cmd(regmap, EC_CMD_POWEROFF);
 
+       if (err) {
+               dev_err(data->dev, "Failed to send power off command\n");
+       } else {
+               mdelay(EC_CMD_TIMEOUT_MS);
+               WARN_ONCE(1, "Unable to power off system\n");
+       }
+
        return err ? NOTIFY_BAD : NOTIFY_DONE;
 }
 
@@ -85,6 +97,13 @@ static int tdx_ec_restart(struct sys_off_data *data)
 
        err = tdx_ec_cmd(regmap, EC_CMD_RESET);
 
+       if (err) {
+               dev_err(data->dev, "Failed to send restart command\n");
+       } else {
+               mdelay(EC_CMD_TIMEOUT_MS);
+               WARN_ONCE(1, "Unable to restart system\n");
+       }
+
        return err ? NOTIFY_BAD : NOTIFY_DONE;
 }