Skip to content

Commit 6157e62

Browse files
paulgeurtsbroonie
authored andcommitted
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>
1 parent d5cc098 commit 6157e62

File tree

2 files changed

+32
-0
lines changed

2 files changed

+32
-0
lines changed

drivers/regulator/pca9450-regulator.c

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include <linux/i2c.h>
1010
#include <linux/interrupt.h>
1111
#include <linux/kernel.h>
12+
#include <linux/reboot.h>
1213
#include <linux/module.h>
1314
#include <linux/of.h>
1415
#include <linux/platform_device.h>
@@ -33,6 +34,7 @@ struct pca9450 {
3334
struct device *dev;
3435
struct regmap *regmap;
3536
struct gpio_desc *sd_vsel_gpio;
37+
struct notifier_block restart_nb;
3638
enum pca9450_chip_type type;
3739
unsigned int rcnt;
3840
int irq;
@@ -965,6 +967,25 @@ static irqreturn_t pca9450_irq_handler(int irq, void *data)
965967
return IRQ_HANDLED;
966968
}
967969

970+
static int pca9450_i2c_restart_handler(struct notifier_block *nb,
971+
unsigned long action, void *data)
972+
{
973+
struct pca9450 *pca9450 = container_of(nb, struct pca9450, restart_nb);
974+
struct i2c_client *i2c = container_of(pca9450->dev, struct i2c_client, dev);
975+
976+
dev_dbg(&i2c->dev, "Restarting device..\n");
977+
if (i2c_smbus_write_byte_data(i2c, PCA9450_REG_SWRST, SW_RST_COMMAND) == 0) {
978+
/* tRESTART is 250ms, so 300 should be enough to make sure it happened */
979+
mdelay(300);
980+
/* When we get here, the PMIC didn't power cycle for some reason. so warn.*/
981+
dev_warn(&i2c->dev, "Device didn't respond to restart command\n");
982+
} else {
983+
dev_err(&i2c->dev, "Restart command failed\n");
984+
}
985+
986+
return 0;
987+
}
988+
968989
static int pca9450_i2c_probe(struct i2c_client *i2c)
969990
{
970991
enum pca9450_chip_type type = (unsigned int)(uintptr_t)
@@ -1107,6 +1128,12 @@ static int pca9450_i2c_probe(struct i2c_client *i2c)
11071128
pca9450->sd_vsel_fixed_low =
11081129
of_property_read_bool(ldo5->dev.of_node, "nxp,sd-vsel-fixed-low");
11091130

1131+
pca9450->restart_nb.notifier_call = pca9450_i2c_restart_handler;
1132+
pca9450->restart_nb.priority = PCA9450_RESTART_HANDLER_PRIORITY;
1133+
1134+
if (register_restart_handler(&pca9450->restart_nb))
1135+
dev_warn(&i2c->dev, "Failed to register restart handler\n");
1136+
11101137
dev_info(&i2c->dev, "%s probed.\n",
11111138
type == PCA9450_TYPE_PCA9450A ? "pca9450a" :
11121139
(type == PCA9450_TYPE_PCA9451A ? "pca9451a" : "pca9450bc"));

include/linux/regulator/pca9450.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ enum {
3535
PCA9450_DVS_LEVEL_MAX,
3636
};
3737

38+
#define PCA9450_RESTART_HANDLER_PRIORITY 130
39+
3840
#define PCA9450_BUCK1_VOLTAGE_NUM 0x80
3941
#define PCA9450_BUCK2_VOLTAGE_NUM 0x80
4042
#define PCA9450_BUCK3_VOLTAGE_NUM 0x80
@@ -235,4 +237,7 @@ enum {
235237
#define I2C_LT_ON_RUN 0x02
236238
#define I2C_LT_FORCE_ENABLE 0x03
237239

240+
/* PCA9450_REG_SW_RST command */
241+
#define SW_RST_COMMAND 0x14
242+
238243
#endif /* __LINUX_REG_PCA9450_H__ */

0 commit comments

Comments
 (0)