[PATCH 07/11] reboot-mode: pm8916-pon: add new driver

Sam Day via B4 Relay devnull+me.samcday.com at kernel.org
Sat Jun 6 10:47:38 CEST 2026


From: Sam Day <me at samcday.com>

The PM8916 provides a PON_SOFT_RB_SPARE register that survives across
reboots.

Signed-off-by: Sam Day <me at samcday.com>
---
 drivers/misc/pm8916_pon.c                    |  7 +++
 drivers/reboot-mode/Makefile                 |  1 +
 drivers/reboot-mode/reboot-mode-pm8916-pon.c | 88 ++++++++++++++++++++++++++++
 3 files changed, 96 insertions(+)

diff --git a/drivers/misc/pm8916_pon.c b/drivers/misc/pm8916_pon.c
index 4cd8921a08a..c889d2d4e6e 100644
--- a/drivers/misc/pm8916_pon.c
+++ b/drivers/misc/pm8916_pon.c
@@ -142,6 +142,13 @@ static int pm8916_pon_bind(struct udevice *dev)
 			dev_warn(dev, "failed to bind qcom_pwrkey: %d\n", ret);
 	}
 
+	if (CONFIG_IS_ENABLED(DM_REBOOT_MODE)) {
+		ret = device_bind_driver_to_node(dev, "pm8916_pon_reboot_mode",
+						 "reboot_mode", dev_ofnode(dev), NULL);
+		if (ret)
+			dev_warn(dev, "failed to bind reboot_mode: %d\n", ret);
+	}
+
 	return 0;
 }
 
diff --git a/drivers/reboot-mode/Makefile b/drivers/reboot-mode/Makefile
index 48c8ab7fe71..467334d010e 100644
--- a/drivers/reboot-mode/Makefile
+++ b/drivers/reboot-mode/Makefile
@@ -8,3 +8,4 @@ obj-$(CONFIG_DM_REBOOT_MODE) += reboot-mode-uclass.o
 obj-$(CONFIG_DM_REBOOT_MODE_GPIO) += reboot-mode-gpio.o
 obj-$(CONFIG_DM_REBOOT_MODE_RTC) += reboot-mode-rtc.o
 obj-$(CONFIG_REBOOT_MODE_NVMEM) += reboot-mode-nvmem.o
+obj-$(CONFIG_PM8916_PON) += reboot-mode-pm8916-pon.o
diff --git a/drivers/reboot-mode/reboot-mode-pm8916-pon.c b/drivers/reboot-mode/reboot-mode-pm8916-pon.c
new file mode 100644
index 00000000000..fa8d0ecaa77
--- /dev/null
+++ b/drivers/reboot-mode/reboot-mode-pm8916-pon.c
@@ -0,0 +1,88 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+#include <dm.h>
+#include <dm/device_compat.h>
+#include <dm/read.h>
+#include <fdtdec.h>
+#include <power/pmic.h>
+#include <reboot-mode/reboot-mode.h>
+
+#define PON_SOFT_RB_SPARE 0x8f
+
+#define GEN1_REASON_SHIFT 2
+
+struct pm8916_pon_reboot_mode_priv {
+	struct udevice *pmic;
+	phys_addr_t base;
+};
+
+static int pm8916_pon_reboot_mode_get(struct udevice *dev, u32 *rebootmode)
+{
+	struct pm8916_pon_reboot_mode_priv *priv = dev_get_priv(dev);
+	int reg;
+	uint mask = GENMASK(7, GEN1_REASON_SHIFT);
+
+	reg = pmic_reg_read(priv->pmic, priv->base + PON_SOFT_RB_SPARE);
+	if (reg < 0) {
+		dev_warn(dev, "Failed to read PON_SOFT_RB_SPARE: %d\n", reg);
+		return reg;
+	}
+
+	*rebootmode = (reg & mask) >> GEN1_REASON_SHIFT;
+
+	return 0;
+}
+
+static int pm8916_pon_reboot_mode_set(struct udevice *dev, u32 rebootmode)
+{
+	struct pm8916_pon_reboot_mode_priv *priv = dev_get_priv(dev);
+	uint mask = GENMASK(7, GEN1_REASON_SHIFT);
+	int ret;
+
+	ret = pmic_clrsetbits(priv->pmic, priv->base + PON_SOFT_RB_SPARE, mask,
+			      rebootmode << GEN1_REASON_SHIFT);
+	if (ret) {
+		dev_warn(dev, "Failed to write PON_SOFT_RB_SPARE: %d\n", ret);
+		return ret;
+	}
+	return 0;
+}
+
+static const struct reboot_mode_ops pm8916_pon_reboot_mode_ops = {
+	.get = pm8916_pon_reboot_mode_get,
+	.set = pm8916_pon_reboot_mode_set,
+};
+
+static int pm8916_pon_reboot_mode_probe(struct udevice *dev)
+{
+	struct pm8916_pon_reboot_mode_priv *priv = dev_get_priv(dev);
+	struct udevice *pon = dev_get_parent(dev);
+	fdt_addr_t base;
+
+	/* this driver only works as a child of pm8916_pon */
+	if (!pon || !pon->driver || strcmp(pon->driver->name, "pm8916_pon"))
+		return -EINVAL;
+
+	priv->pmic = dev_get_parent(pon);
+	if (!priv->pmic) {
+		dev_err(dev, "PMIC driver not found\n");
+		return -EINVAL;
+	}
+
+	base = dev_read_addr(pon);
+	if (base == FDT_ADDR_T_NONE) {
+		dev_err(dev, "missing PON reg base\n");
+		return -EINVAL;
+	}
+	priv->base = base;
+
+	return 0;
+}
+
+U_BOOT_DRIVER(pm8916_pon_reboot_mode) = {
+	.name = "pm8916_pon_reboot_mode",
+	.id = UCLASS_REBOOT_MODE,
+	.probe = pm8916_pon_reboot_mode_probe,
+	.ops = &pm8916_pon_reboot_mode_ops,
+	.priv_auto = sizeof(struct pm8916_pon_reboot_mode_priv),
+};

-- 
2.54.0




More information about the U-Boot mailing list