Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

regulator: pca9450: Add restart handler

When restarting a CPU powered by the PCA9450 power management IC, it
is beneficial to use the PCA9450 to power cycle the CPU and all its
connected peripherals to start up in a known state. The PCA9450 features
a cold start procedure initiated by an I2C command.

Add a restart handler so that the PCA9450 is used to restart the CPU.
The restart handler sends command 0x14 to the SW_RST register,
initiating a cold reset (Power recycle all regulators except LDO1, LDO2
and CLK_32K_OUT)

As the PCA9450 is a PMIC specific for the i.MX8M family CPU, the restart
handler priority is set just slightly higher than imx2_wdt and the PSCI
restart handler. This makes sure this restart handler takes precedence.

Signed-off-by: Paul Geurts <paul.geurts@prodrive-technologies.com>
Link: https://patch.msgid.link/20250505115936.1946891-1-paul.geurts@prodrive-technologies.com
Signed-off-by: Mark Brown <broonie@kernel.org>

authored by

Paul Geurts and committed by
Mark Brown
6157e62b d5cc0984

+32
+27
drivers/regulator/pca9450-regulator.c
··· 9 9 #include <linux/i2c.h> 10 10 #include <linux/interrupt.h> 11 11 #include <linux/kernel.h> 12 + #include <linux/reboot.h> 12 13 #include <linux/module.h> 13 14 #include <linux/of.h> 14 15 #include <linux/platform_device.h> ··· 34 33 struct device *dev; 35 34 struct regmap *regmap; 36 35 struct gpio_desc *sd_vsel_gpio; 36 + struct notifier_block restart_nb; 37 37 enum pca9450_chip_type type; 38 38 unsigned int rcnt; 39 39 int irq; ··· 967 965 return IRQ_HANDLED; 968 966 } 969 967 968 + static int pca9450_i2c_restart_handler(struct notifier_block *nb, 969 + unsigned long action, void *data) 970 + { 971 + struct pca9450 *pca9450 = container_of(nb, struct pca9450, restart_nb); 972 + struct i2c_client *i2c = container_of(pca9450->dev, struct i2c_client, dev); 973 + 974 + dev_dbg(&i2c->dev, "Restarting device..\n"); 975 + if (i2c_smbus_write_byte_data(i2c, PCA9450_REG_SWRST, SW_RST_COMMAND) == 0) { 976 + /* tRESTART is 250ms, so 300 should be enough to make sure it happened */ 977 + mdelay(300); 978 + /* When we get here, the PMIC didn't power cycle for some reason. so warn.*/ 979 + dev_warn(&i2c->dev, "Device didn't respond to restart command\n"); 980 + } else { 981 + dev_err(&i2c->dev, "Restart command failed\n"); 982 + } 983 + 984 + return 0; 985 + } 986 + 970 987 static int pca9450_i2c_probe(struct i2c_client *i2c) 971 988 { 972 989 enum pca9450_chip_type type = (unsigned int)(uintptr_t) ··· 1127 1106 1128 1107 pca9450->sd_vsel_fixed_low = 1129 1108 of_property_read_bool(ldo5->dev.of_node, "nxp,sd-vsel-fixed-low"); 1109 + 1110 + pca9450->restart_nb.notifier_call = pca9450_i2c_restart_handler; 1111 + pca9450->restart_nb.priority = PCA9450_RESTART_HANDLER_PRIORITY; 1112 + 1113 + if (register_restart_handler(&pca9450->restart_nb)) 1114 + dev_warn(&i2c->dev, "Failed to register restart handler\n"); 1130 1115 1131 1116 dev_info(&i2c->dev, "%s probed.\n", 1132 1117 type == PCA9450_TYPE_PCA9450A ? "pca9450a" :
+5
include/linux/regulator/pca9450.h
··· 35 35 PCA9450_DVS_LEVEL_MAX, 36 36 }; 37 37 38 + #define PCA9450_RESTART_HANDLER_PRIORITY 130 39 + 38 40 #define PCA9450_BUCK1_VOLTAGE_NUM 0x80 39 41 #define PCA9450_BUCK2_VOLTAGE_NUM 0x80 40 42 #define PCA9450_BUCK3_VOLTAGE_NUM 0x80 ··· 236 234 #define I2C_LT_ON_STANDBY_RUN 0x01 237 235 #define I2C_LT_ON_RUN 0x02 238 236 #define I2C_LT_FORCE_ENABLE 0x03 237 + 238 + /* PCA9450_REG_SW_RST command */ 239 + #define SW_RST_COMMAND 0x14 239 240 240 241 #endif /* __LINUX_REG_PCA9450_H__ */