[PATCH v3 1/2] power: pmic: pca9450: Add support for system reset

Primoz Fiser primoz.fiser at norik.com
Thu Aug 28 13:24:04 CEST 2025


The family of PCA9450 PMICs have the ability to perform system resets.
Restarting via PMIC is preferred method of restarting the system as all
the peripherals are brought to a know state after a power-cycle. The
PCA9450 features a cold restart procedure which is initiated by an I2C
command 0x14 to the SW_RST register.

Support in Linux for restarting via PCA9450 PMIC has been added by
Linux commit 6157e62b07d9 ("regulator: pca9450: Add restart handler").

Now add support for it also in the U-Boot via sysreset framework.

Signed-off-by: Primoz Fiser <primoz.fiser at norik.com>
Reviewed-by: Paul Geurts <paul.geurts at prodrive-technologies.com>
---
Changes in v3:
- rebase custodians/u-boot-mmc branch: next 
- add Reviewed-by: tags

Link to v2: https://lore.kernel.org/all/20250814094741.4177431-1-primoz.fiser@norik.com/

 drivers/power/pmic/pca9450.c | 44 ++++++++++++++++++++++++++++++++++++
 include/power/pca9450.h      |  2 ++
 2 files changed, 46 insertions(+)

diff --git a/drivers/power/pmic/pca9450.c b/drivers/power/pmic/pca9450.c
index 0e3d14abf154..8b98c2239e13 100644
--- a/drivers/power/pmic/pca9450.c
+++ b/drivers/power/pmic/pca9450.c
@@ -6,13 +6,17 @@
 #include <fdtdec.h>
 #include <errno.h>
 #include <dm.h>
+#include <dm/device_compat.h>
+#include <dm/lists.h>
 #include <i2c.h>
 #include <log.h>
 #include <asm/global_data.h>
+#include <linux/delay.h>
 #include <linux/printk.h>
 #include <power/pmic.h>
 #include <power/regulator.h>
 #include <power/pca9450.h>
+#include <sysreset.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -79,6 +83,15 @@ static int pca9450_bind(struct udevice *dev)
 static int pca9450_probe(struct udevice *dev)
 {
 	unsigned int reset_ctrl;
+	int ret;
+
+	if (CONFIG_IS_ENABLED(SYSRESET)) {
+		ret = device_bind_driver_to_node(dev, "pca9450_sysreset",
+						 "pca9450_sysreset",
+						 dev_ofnode(dev), NULL);
+		if (ret)
+			return ret;
+	}
 
 	if (ofnode_read_bool(dev_ofnode(dev), "nxp,wdog_b-warm-reset"))
 		reset_ctrl = PCA9450_PMIC_RESET_WDOG_B_CFG_WARM;
@@ -112,3 +125,34 @@ U_BOOT_DRIVER(pmic_pca9450) = {
 	.probe = pca9450_probe,
 	.ops = &pca9450_ops,
 };
+
+#ifdef CONFIG_SYSRESET
+static int pca9450_sysreset_request(struct udevice *dev, enum sysreset_t type)
+{
+	u8 cmd = PCA9450_SW_RST_COLD_RST;
+
+	if (type != SYSRESET_COLD)
+		return -EPROTONOSUPPORT;
+
+	if (pmic_write(dev->parent, PCA9450_SW_RST, &cmd, 1)) {
+		dev_err(dev, "reset command failed\n");
+	} else {
+		/* tRESTART is 250ms, delay 300ms just to be sure */
+		mdelay(300);
+		/* Should not get here, warn if we do */
+		dev_warn(dev, "didn't respond to reset command\n");
+	}
+
+	return -EINPROGRESS;
+}
+
+static struct sysreset_ops pca9450_sysreset_ops = {
+	.request	= pca9450_sysreset_request,
+};
+
+U_BOOT_DRIVER(pca9450_sysreset) = {
+	.name		= "pca9450_sysreset",
+	.id		= UCLASS_SYSRESET,
+	.ops		= &pca9450_sysreset_ops,
+};
+#endif /* CONFIG_SYSRESET */
diff --git a/include/power/pca9450.h b/include/power/pca9450.h
index e5ab09fb8c83..9119ef793b1f 100644
--- a/include/power/pca9450.h
+++ b/include/power/pca9450.h
@@ -75,4 +75,6 @@ enum {
 #define PCA9450_PMIC_RESET_WDOG_B_CFG_WARM		0x40
 #define PCA9450_PMIC_RESET_WDOG_B_CFG_COLD_LDO12	0x80
 
+#define PCA9450_SW_RST_COLD_RST		0x14
+
 #endif
-- 
2.34.1



More information about the U-Boot mailing list