From: Benjamin Bara <benjamin.bara@xxxxxxxxxxx> The TPS658629-Q1 (unfortunately the only TPS6586x with public data sheet) provides a SOFT RST bit in the SUPPLYENE reg to request a (cold) reboot. Use it to implement and register a restart handler. Tested on a TPS658640. Signed-off-by: Benjamin Bara <benjamin.bara@xxxxxxxxxxx> --- drivers/mfd/tps6586x.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/drivers/mfd/tps6586x.c b/drivers/mfd/tps6586x.c index 4869155437cb..b46917231847 100644 --- a/drivers/mfd/tps6586x.c +++ b/drivers/mfd/tps6586x.c @@ -15,6 +15,7 @@ #include <linux/interrupt.h> #include <linux/irq.h> #include <linux/irqdomain.h> +#include <linux/irqflags.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/mutex.h> @@ -30,6 +31,7 @@ #include <linux/mfd/tps6586x.h> #define TPS6586X_SUPPLYENE 0x14 +#define SOFT_RST_BIT BIT(0) #define EXITSLREQ_BIT BIT(1) #define SLEEP_MODE_BIT BIT(3) @@ -470,6 +472,20 @@ static int tps6586x_power_off_handler(struct sys_off_data *data) return tps6586x_set_bits(tps6586x_dev, TPS6586X_SUPPLYENE, SLEEP_MODE_BIT); } +static int tps6586x_restart_handler(struct sys_off_data *data) +{ + unsigned long flags; + struct device *tps6586x_dev = (struct device *)data->cb_data; + + /* bring pmic into HARD REBOOT state, enforce atomic i2c xfer */ + local_irq_save(flags); + tps6586x_set_bits(tps6586x_dev, TPS6586X_SUPPLYENE, SOFT_RST_BIT); + local_irq_restore(flags); + + mdelay(500); + return 0; +} + static void tps6586x_print_version(struct i2c_client *client, int version) { const char *name; @@ -570,6 +586,13 @@ static int tps6586x_i2c_probe(struct i2c_client *client) dev_err(&client->dev, "register power off handler failed: %d\n", ret); goto err_add_devs; } + + ret = devm_register_restart_handler(&client->dev, &tps6586x_restart_handler, + &client->dev); + if (ret) { + dev_err(&client->dev, "register restart handler failed: %d\n", ret); + goto err_add_devs; + } } return 0; -- 2.34.1