From 8b8a00eaf47719ee04338eff9cd94b0408779d9d Mon Sep 17 00:00:00 2001 From: Svyatoslav Ryhel Date: Tue, 24 Oct 2023 10:49:07 +0300 Subject: [PATCH] sysreset: implement TPS65910 sysreset functions TPS65910/TPS65911 PMICs have embedded power control functions used by some device to initiane device power off. Implement it as sysreset driver. Signed-off-by: Svyatoslav Ryhel --- drivers/power/pmic/pmic_tps65910_dm.c | 12 +++++- drivers/sysreset/Kconfig | 8 ++++ drivers/sysreset/Makefile | 1 + drivers/sysreset/sysreset_tps65910.c | 54 +++++++++++++++++++++++++++ include/power/tps65910_pmic.h | 7 ++++ 5 files changed, 81 insertions(+), 1 deletion(-) create mode 100644 drivers/sysreset/sysreset_tps65910.c diff --git a/drivers/power/pmic/pmic_tps65910_dm.c b/drivers/power/pmic/pmic_tps65910_dm.c index 0a4911cef6..ecf836eb0e 100644 --- a/drivers/power/pmic/pmic_tps65910_dm.c +++ b/drivers/power/pmic/pmic_tps65910_dm.c @@ -5,6 +5,7 @@ #include #include +#include #include #include #include @@ -59,7 +60,16 @@ static int pmic_tps65910_bind(struct udevice *dev) const struct pmic_child_info *tps6591x_children_info = (struct pmic_child_info *)dev_get_driver_data(dev); ofnode regulators_node; - int children; + int children, ret; + + if (IS_ENABLED(CONFIG_SYSRESET_TPS65910)) { + ret = device_bind_driver(dev, TPS65910_RST_DRIVER, + "sysreset", NULL); + if (ret) { + log_err("cannot bind SYSRESET (ret = %d)\n", ret); + return ret; + } + } regulators_node = dev_read_subnode(dev, "regulators"); if (!ofnode_valid(regulators_node)) { diff --git a/drivers/sysreset/Kconfig b/drivers/sysreset/Kconfig index cdb4ae2bb1..659170d156 100644 --- a/drivers/sysreset/Kconfig +++ b/drivers/sysreset/Kconfig @@ -157,6 +157,14 @@ config SYSRESET_TI_SCI This enables the system reset driver support over TI System Control Interface available on some new TI's SoCs. +config SYSRESET_TPS65910 + bool "Enable support for TPS65910/TPS65911 PMIC System Reset" + depends on DM_PMIC_TPS65910 + select SYSRESET_CMD_POWEROFF if CMD_POWEROFF + help + Enable system power management functions found in TPS65910/TPS65911 + PMICs. + config SYSRESET_TPS80031 bool "Enable support for TPS80031/TPS80032 PMIC System Reset" depends on DM_PMIC_TPS80031 diff --git a/drivers/sysreset/Makefile b/drivers/sysreset/Makefile index f62db899da..0d96a204a9 100644 --- a/drivers/sysreset/Makefile +++ b/drivers/sysreset/Makefile @@ -19,6 +19,7 @@ obj-$(CONFIG_SYSRESET_SOCFPGA) += sysreset_socfpga.o obj-$(CONFIG_SYSRESET_SOCFPGA_SOC64) += sysreset_socfpga_soc64.o obj-$(CONFIG_SYSRESET_TEGRA) += sysreset_tegra.o obj-$(CONFIG_SYSRESET_TI_SCI) += sysreset-ti-sci.o +obj-$(CONFIG_$(SPL_TPL_)SYSRESET_TPS65910) += sysreset_tps65910.o obj-$(CONFIG_$(SPL_TPL_)SYSRESET_TPS80031) += sysreset_tps80031.o obj-$(CONFIG_SYSRESET_SYSCON) += sysreset_syscon.o obj-$(CONFIG_SYSRESET_WATCHDOG) += sysreset_watchdog.o diff --git a/drivers/sysreset/sysreset_tps65910.c b/drivers/sysreset/sysreset_tps65910.c new file mode 100644 index 0000000000..98da56661c --- /dev/null +++ b/drivers/sysreset/sysreset_tps65910.c @@ -0,0 +1,54 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright(C) 2023 Svyatoslav Ryhel + */ + +#include +#include +#include +#include +#include +#include + +static int tps65910_sysreset_request(struct udevice *dev, + enum sysreset_t type) +{ + int val; + + val = pmic_reg_read(dev->parent, TPS65910_REG_DEVICE_CTRL); + if (val < 0) + return val; + + /* define power-off to be sequential */ + val |= PWR_OFF_SEQ; + pmic_reg_write(dev->parent, TPS65910_REG_DEVICE_CTRL, val); + + val &= ~DEV_ON; + + switch (type) { + case SYSRESET_POWER: + /* TPS65910: DEV_OFF_RST > DEVICE_CTRL */ + pmic_reg_write(dev->parent, TPS65910_REG_DEVICE_CTRL, + val | DEV_OFF_RST); + break; + case SYSRESET_POWER_OFF: + /* TPS65910: DEV_OFF > DEVICE_CTRL */ + pmic_reg_write(dev->parent, TPS65910_REG_DEVICE_CTRL, + val | DEV_OFF); + break; + default: + return -EPROTONOSUPPORT; + } + + return -EINPROGRESS; +} + +static struct sysreset_ops tps65910_sysreset = { + .request = tps65910_sysreset_request, +}; + +U_BOOT_DRIVER(sysreset_tps65910) = { + .id = UCLASS_SYSRESET, + .name = TPS65910_RST_DRIVER, + .ops = &tps65910_sysreset, +}; diff --git a/include/power/tps65910_pmic.h b/include/power/tps65910_pmic.h index 7d6545abdf..2026ec2f42 100644 --- a/include/power/tps65910_pmic.h +++ b/include/power/tps65910_pmic.h @@ -17,6 +17,12 @@ #define TPS65910_SUPPLY_STATE_OFF 0x0 #define TPS65910_SUPPLY_STATE_ON 0x1 +/* TPS65910 DEVICE_CTRL bits */ +#define PWR_OFF_SEQ BIT(7) +#define DEV_OFF_RST BIT(3) +#define DEV_ON BIT(2) +#define DEV_OFF BIT(0) + /* i2c registers */ enum { TPS65910_REG_RTC_SEC = 0x00, @@ -125,6 +131,7 @@ struct tps65910_regulator_pdata { #define TPS65910_BUCK_DRIVER "tps65910_buck" #define TPS65910_BOOST_DRIVER "tps65910_boost" #define TPS65910_LDO_DRIVER "tps65910_ldo" +#define TPS65910_RST_DRIVER "tps65910_rst" /* tps65911 i2c registers */ enum { -- 2.39.5