[PATCH 2/8] reboot-mode: add trigger op and request/list helpers

Balaji Selvanathan via U-Boot <[email protected]>
Newsgroups org.u-boot-project.lists.u-boot
Message-ID <20260811-b4-reset-edl-rebootmode-v1-2-2e15adc156a3@oss.qualcomm.com>
The reboot-mode framework so far only reads a value from a backing store
on boot (get/set) and maps it to an environment variable. Triggering a
reset into a specific mode on demand - e.g. rebooting a Qualcomm SoC into
EDL via a PSCI SYSTEM_RESET2 vendor reset - needs a different approach.

Add an trigger() op to struct reboot_mode_ops. It takes the
decoded magic cells for a mode and resets the system immediately; on
success it does not return. Backing-store drivers (nvmem, gpio, rtc)
leave it NULL and are unaffected.

Add two uclass helpers built on top of it:

  - reboot_mode_request(name) looks up a mode by name across all
    UCLASS_REBOOT_MODE devices and, if the owning device can trigger,
    resets into it. Returns -ENOENT if no triggerable mode matches.

  - reboot_mode_list() enumerates every triggerable mode registered with
    the framework, so a command can present the available modes to the
    user rather than hard-coding them.

Signed-off-by: Balaji Selvanathan <[email protected]>
---
 drivers/reboot-mode/reboot-mode-uclass.c | 48 ++++++++++++++++++++++++++++++++
 include/reboot-mode/reboot-mode.h        | 40 ++++++++++++++++++++++++++
 2 files changed, 88 insertions(+)

diff --git a/drivers/reboot-mode/reboot-mode-uclass.c b/drivers/reboot-mode/reboot-mode-uclass.c
index 80aabf54750..866a56ecb7b 100644
--- a/drivers/reboot-mode/reboot-mode-uclass.c
+++ b/drivers/reboot-mode/reboot-mode-uclass.c
@@ -54,6 +54,54 @@ int dm_reboot_mode_update(struct udevice *dev)
 	return 0;
 }
 
+int reboot_mode_request(const char *name)
+{
+	const struct reboot_mode_uclass_platdata *plat_data;
+	struct reboot_mode_ops *ops;
+	struct udevice *dev;
+	int i;
+
+	uclass_foreach_dev_probe(UCLASS_REBOOT_MODE, dev) {
+		ops = reboot_mode_get_ops(dev);
+		if (!ops || !ops->trigger)
+			continue;
+
+		plat_data = dev_get_uclass_plat(dev);
+		for (i = 0; i < plat_data->count; i++) {
+			if (strcmp(plat_data->modes[i].mode_name, name))
+				continue;
+
+			/* Does not return on success. */
+			return ops->trigger(dev, plat_data->modes[i].magic,
+					    plat_data->modes[i].count);
+		}
+	}
+
+	return -ENOENT;
+}
+
+int reboot_mode_list(void)
+{
+	const struct reboot_mode_uclass_platdata *plat_data;
+	struct reboot_mode_ops *ops;
+	struct udevice *dev;
+	int i;
+
+	printf("Available reset modes:\n");
+
+	uclass_foreach_dev_probe(UCLASS_REBOOT_MODE, dev) {
+		ops = reboot_mode_get_ops(dev);
+		if (!ops || !ops->trigger)
+			continue;
+
+		plat_data = dev_get_uclass_plat(dev);
+		for (i = 0; i < plat_data->count; i++)
+			printf("  %s\n", plat_data->modes[i].mode_name);
+	}
+
+	return 0;
+}
+
 int dm_reboot_mode_pre_probe(struct udevice *dev)
 {
 	struct reboot_mode_uclass_platdata *plat_data;
diff --git a/include/reboot-mode/reboot-mode.h b/include/reboot-mode/reboot-mode.h
index 54a8c09650e..67be5e4b3eb 100644
--- a/include/reboot-mode/reboot-mode.h
+++ b/include/reboot-mode/reboot-mode.h
@@ -46,6 +46,22 @@ struct reboot_mode_ops {
 	 * @rebootmode:	New reboot mode value to store
 	 */
 	int (*set)(struct udevice *dev, u32 rebootmode);
+
+	/**
+	 * trigger() - reset the system into the given mode now
+	 *
+	 * Unlike get()/set(), which persist a value for the next boot to
+	 * consume, trigger() performs the reset immediately. On success it
+	 * does not return. Drivers with a backing store (nvmem, gpio, rtc)
+	 * leave this NULL.
+	 *
+	 * @dev:	Device to trigger
+	 * @magic:	Array of @count 32-bit magic cells describing the mode
+	 * @count:	Number of valid cells in @magic (1 to
+	 *		REBOOT_MODE_MAX_MAGIC)
+	 * Return: does not return on success; -ve on error
+	 */
+	int (*trigger)(struct udevice *dev, const u32 *magic, int count);
 };
 
 /* Access the operations for a reboot mode device */
@@ -59,4 +75,28 @@ struct reboot_mode_ops {
  */
 int dm_reboot_mode_update(struct udevice *dev);
 
+/**
+ * reboot_mode_request() - reset the system into a named mode
+ *
+ * Search every UCLASS_REBOOT_MODE device for a mode named @name and, if the
+ * owning device supports triggering, reset into it. On success this does not
+ * return.
+ *
+ * @name:	Mode name (without the device tree "mode-" prefix)
+ * Return: does not return on success; -ENOENT if no device declares a
+ *	   triggerable mode called @name; other -ve on error
+ */
+int reboot_mode_request(const char *name);
+
+/**
+ * reboot_mode_list() - print all triggerable reboot modes
+ *
+ * Enumerate every UCLASS_REBOOT_MODE device and print the name of each mode
+ * that can be triggered (i.e. whose device implements the trigger op). Modes
+ * that only exist to be read from a backing store on boot are not listed.
+ *
+ * Return: 0 if OK, -ve on error
+ */
+int reboot_mode_list(void);
+
 #endif /* REBOOT_MODE_REBOOT_MODE_H__ */

-- 
2.34.1
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.