MAX77663 PMIC has embedded poweroff function used by some
device to initiane device power off. Implement it as sysreset
driver.

Signed-off-by: Svyatoslav Ryhel <clamo...@gmail.com>
---
 drivers/power/pmic/max77663.c        | 12 ++++++-
 drivers/sysreset/Kconfig             |  7 ++++
 drivers/sysreset/Makefile            |  1 +
 drivers/sysreset/sysreset_max77663.c | 53 ++++++++++++++++++++++++++++
 include/power/max77663.h             |  5 +++
 5 files changed, 77 insertions(+), 1 deletion(-)
 create mode 100644 drivers/sysreset/sysreset_max77663.c

diff --git a/drivers/power/pmic/max77663.c b/drivers/power/pmic/max77663.c
index 4070235d3c..e333c8dcf5 100644
--- a/drivers/power/pmic/max77663.c
+++ b/drivers/power/pmic/max77663.c
@@ -9,6 +9,7 @@
 #include <dm.h>
 #include <i2c.h>
 #include <log.h>
+#include <dm/lists.h>
 #include <power/pmic.h>
 #include <power/regulator.h>
 #include <power/max77663.h>
@@ -49,7 +50,16 @@ static int max77663_read(struct udevice *dev, uint reg, 
uint8_t *buff, int len)
 static int max77663_bind(struct udevice *dev)
 {
        ofnode regulators_node;
-       int children;
+       int children, ret;
+
+       if (IS_ENABLED(CONFIG_SYSRESET_MAX77663)) {
+               ret = device_bind_driver(dev, MAX77663_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 eab556c349..bc35896101 100644
--- a/drivers/sysreset/Kconfig
+++ b/drivers/sysreset/Kconfig
@@ -74,6 +74,13 @@ config SYSRESET_GPIO
          example on Microblaze where reset logic can be controlled via GPIO
          pin which triggers cpu reset.
 
+config SYSRESET_MAX77663
+       bool "Enable support for MAX77663 PMIC System Reset"
+       depends on DM_PMIC_MAX77663
+       select SYSRESET_CMD_POWEROFF if CMD_POWEROFF
+       help
+         Enable system power management functions found in MAX77663 PMIC.
+
 config SYSRESET_MICROBLAZE
        bool "Enable support for Microblaze soft reset"
        depends on MICROBLAZE
diff --git a/drivers/sysreset/Makefile b/drivers/sysreset/Makefile
index a9ac123754..c31f51c581 100644
--- a/drivers/sysreset/Makefile
+++ b/drivers/sysreset/Makefile
@@ -9,6 +9,7 @@ obj-$(CONFIG_ARCH_STI) += sysreset_sti.o
 obj-$(CONFIG_SANDBOX) += sysreset_sandbox.o
 obj-$(CONFIG_POWEROFF_GPIO) += poweroff_gpio.o
 obj-$(CONFIG_SYSRESET_GPIO) += sysreset_gpio.o
+obj-$(CONFIG_$(SPL_TPL_)SYSRESET_MAX77663) += sysreset_max77663.o
 obj-$(CONFIG_SYSRESET_MPC83XX) += sysreset_mpc83xx.o
 obj-$(CONFIG_SYSRESET_MICROBLAZE) += sysreset_microblaze.o
 obj-$(CONFIG_SYSRESET_OCTEON) += sysreset_octeon.o
diff --git a/drivers/sysreset/sysreset_max77663.c 
b/drivers/sysreset/sysreset_max77663.c
new file mode 100644
index 0000000000..4a2a2275df
--- /dev/null
+++ b/drivers/sysreset/sysreset_max77663.c
@@ -0,0 +1,53 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ *  Copyright(C) 2023 Svyatoslav Ryhel <clamo...@gmail.com>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <i2c.h>
+#include <errno.h>
+#include <sysreset.h>
+#include <power/pmic.h>
+#include <power/max77663.h>
+
+static int max77663_sysreset_request(struct udevice *dev,
+                                    enum sysreset_t type)
+{
+       int val;
+
+       val = pmic_reg_read(dev->parent, MAX77663_REG_ONOFF_CFG1);
+       if (val < 0)
+               return val;
+
+       /* clear both bits */
+       val &= ~ONOFF_SFT_RST;
+       val &= ~ONOFF_PWR_OFF;
+
+       switch (type) {
+       case SYSRESET_POWER:
+               /* MAX77663: SFT_RST > ONOFF_CFG1 */
+               pmic_reg_write(dev->parent, MAX77663_REG_ONOFF_CFG1,
+                              val | ONOFF_SFT_RST);
+               break;
+       case SYSRESET_POWER_OFF:
+               /* MAX77663: PWR_OFF > ONOFF_CFG1 */
+               pmic_reg_write(dev->parent, MAX77663_REG_ONOFF_CFG1,
+                              val | ONOFF_PWR_OFF);
+               break;
+       default:
+               return -EPROTONOSUPPORT;
+       }
+
+       return -EINPROGRESS;
+}
+
+static struct sysreset_ops max77663_sysreset = {
+       .request = max77663_sysreset_request,
+};
+
+U_BOOT_DRIVER(sysreset_max77663) = {
+       .id     = UCLASS_SYSRESET,
+       .name   = MAX77663_RST_DRIVER,
+       .ops    = &max77663_sysreset,
+};
diff --git a/include/power/max77663.h b/include/power/max77663.h
index 0f764bcbcc..b3ae3dabf4 100644
--- a/include/power/max77663.h
+++ b/include/power/max77663.h
@@ -12,6 +12,7 @@
 /* Drivers name */
 #define MAX77663_LDO_DRIVER            "max77663_ldo"
 #define MAX77663_SD_DRIVER             "max77663_sd"
+#define MAX77663_RST_DRIVER            "max77663_rst"
 
 /* Step-Down (SD) Regulator calculations */
 #define SD_STATUS_MASK                 0x30
@@ -39,4 +40,8 @@
 
 #define LDO_VOLT_BASE                  800000
 
+#define MAX77663_REG_ONOFF_CFG1                0x41
+#define   ONOFF_SFT_RST                        BIT(7)
+#define   ONOFF_PWR_OFF                        BIT(1)
+
 #endif /* _MAX77663_H_ */
-- 
2.39.2

Reply via email to