From 8c36d2366775e14171daf1defda791ea1fefe138 Mon Sep 17 00:00:00 2001 From: Ondrej Jirman Date: Thu, 16 Sep 2021 16:00:15 +0200 Subject: [PATCH 290/478] mfd: rk808: Add support for restart via PMIC Implemented by pgwipeout. See: https://discord.com/channels/463237927984693259/811213663150407691/881541707961876511 Signed-off-by: Ondrej Jirman --- drivers/mfd/rk808.c | 48 +++++++++++++++++++++++++++++++++++++++ include/linux/mfd/rk808.h | 2 ++ 2 files changed, 50 insertions(+) diff --git a/drivers/mfd/rk808.c b/drivers/mfd/rk808.c index b181fe401330..b608264f52d2 100644 --- a/drivers/mfd/rk808.c +++ b/drivers/mfd/rk808.c @@ -19,6 +19,7 @@ #include #include #include +#include struct rk808_reg_data { int addr; @@ -533,6 +534,7 @@ static void rk808_pm_power_off(void) int ret; unsigned int reg, bit; struct rk808 *rk808 = i2c_get_clientdata(rk808_i2c_client); + dev_err(&rk808_i2c_client->dev, "poweroff device!\n"); switch (rk808->variant) { case RK805_ID: @@ -552,6 +554,7 @@ static void rk808_pm_power_off(void) bit = DEV_OFF; break; default: + dev_err(&rk808_i2c_client->dev, "poweroff device not supported!\n"); return; } ret = regmap_update_bits(rk808->regmap, reg, bit, bit); @@ -559,6 +562,44 @@ static void rk808_pm_power_off(void) dev_err(&rk808_i2c_client->dev, "Failed to shutdown device!\n"); } +static int rk808_restart_notify(struct notifier_block *this, unsigned long mode, void *cmd) +{ + int ret; + unsigned int reg, bit; + struct rk808 *rk808 = i2c_get_clientdata(rk808_i2c_client); + + switch (rk808->variant) { + case RK805_ID: + reg = RK805_DEV_CTRL_REG; + bit = DEV_OFF_RST; + break; + case RK808_ID: + reg = RK808_DEVCTRL_REG, + bit = DEV_OFF; + break; + case RK818_ID: + reg = RK818_DEVCTRL_REG; + bit = DEV_OFF_RST; + break; + case RK817_ID: + reg = RK817_SYS_CFG(3); + bit = DEV_RST; + break; + default: + return NOTIFY_DONE; + } + ret = regmap_update_bits(rk808->regmap, reg, bit, bit); + if (ret) + dev_err(&rk808_i2c_client->dev, "Failed to restart device!\n"); + + return NOTIFY_DONE; +} + +static struct notifier_block rk808_restart_handler = { + .notifier_call = rk808_restart_notify, + .priority = 255, +}; + static void rk8xx_shutdown(struct i2c_client *client) { struct rk808 *rk808 = i2c_get_clientdata(client); @@ -727,6 +768,13 @@ static int rk808_probe(struct i2c_client *client, if (of_property_read_bool(np, "rockchip,system-power-controller")) { rk808_i2c_client = client; pm_power_off = rk808_pm_power_off; + rk808->nb = &rk808_restart_handler; + + dev_warn(&client->dev, "register restart handler\n"); + + ret = register_restart_handler(rk808->nb); + if (ret) + dev_err(&client->dev, "failed to register restart handler, %d\n", ret); } return 0; diff --git a/include/linux/mfd/rk808.h b/include/linux/mfd/rk808.h index a96e6d43ca06..5dfe0c4ceab1 100644 --- a/include/linux/mfd/rk808.h +++ b/include/linux/mfd/rk808.h @@ -373,6 +373,7 @@ enum rk805_reg { #define SWITCH2_EN BIT(6) #define SWITCH1_EN BIT(5) #define DEV_OFF_RST BIT(3) +#define DEV_RST BIT(2) #define DEV_OFF BIT(0) #define RTC_STOP BIT(0) @@ -701,5 +702,6 @@ struct rk808 { long variant; const struct regmap_config *regmap_cfg; const struct regmap_irq_chip *regmap_irq_chip; + struct notifier_block *nb; }; #endif /* __LINUX_REGULATOR_RK808_H */ -- 2.35.3