Re: [PATCH v20 02/10] power: reset: reboot-mode: Add support for 64 bit magic
From: Sebastian Reichel <hidden>
Date: 2026-03-11 09:22:51
Also in:
linux-arm-msm, linux-devicetree, linux-pm, lkml
Hi, On Wed, Mar 04, 2026 at 11:33:02PM +0530, Shivendra Pratap wrote:
Current reboot-mode supports a single 32-bit argument for any supported mode. Some reboot-mode based drivers may require passing two independent 32-bit arguments during a reboot sequence, for uses-cases, where a mode requires an additional argument. Such drivers may not be able to use the reboot-mode driver. For example, ARM PSCI vendor-specific resets, need two arguments for its operation – reset_type and cookie, to complete the reset operation. If a driver wants to implement this firmware-based reset, it cannot use reboot-mode framework. Introduce 64-bit magic values in reboot-mode driver to accommodate up-to two 32-bit arguments in below format. | Higher 32 bit | Lower 32 bit | | arg2 | arg1 | Update current reboot-mode drivers for 64-bit magic. Signed-off-by: Shivendra Pratap <redacted> ---
Reviewed-by: Sebastian Reichel <redacted> -- Sebastian
quoted hunk ↗ jump to hunk
drivers/power/reset/nvmem-reboot-mode.c | 8 ++++---- drivers/power/reset/qcom-pon.c | 6 +++--- drivers/power/reset/reboot-mode.c | 16 +++++++++------- drivers/power/reset/syscon-reboot-mode.c | 6 +++--- include/linux/reboot-mode.h | 15 ++++++++++++++- 5 files changed, 33 insertions(+), 18 deletions(-)diff --git a/drivers/power/reset/nvmem-reboot-mode.c b/drivers/power/reset/nvmem-reboot-mode.c index d260715fccf67f9f072bb56c5defbf885750650e..bd05d660490c686b43134f82f1eadd7665403d20 100644 --- a/drivers/power/reset/nvmem-reboot-mode.c +++ b/drivers/power/reset/nvmem-reboot-mode.c@@ -17,10 +17,10 @@ struct nvmem_reboot_mode { struct nvmem_cell *cell; }; -static int nvmem_reboot_mode_write(struct reboot_mode_driver *reboot, - unsigned int magic) +static int nvmem_reboot_mode_write(struct reboot_mode_driver *reboot, u64 magic) { struct nvmem_reboot_mode *nvmem_rbm; + u32 magic_arg1 = REBOOT_MODE_ARG1(magic); size_t buf_len; void *buf; int ret;@@ -32,10 +32,10 @@ static int nvmem_reboot_mode_write(struct reboot_mode_driver *reboot, return PTR_ERR(buf); kfree(buf); - if (buf_len > sizeof(magic)) + if (buf_len > sizeof(magic_arg1)) return -EINVAL; - ret = nvmem_cell_write(nvmem_rbm->cell, &magic, buf_len); + ret = nvmem_cell_write(nvmem_rbm->cell, &magic_arg1, buf_len); if (ret < 0) dev_err(reboot->dev, "update reboot mode bits failed\n");diff --git a/drivers/power/reset/qcom-pon.c b/drivers/power/reset/qcom-pon.c index 7e108982a582e8243c5c806bd4a793646b87189f..57b36e6186f80aff947fd7f5aae5ce280c65dc6b 100644 --- a/drivers/power/reset/qcom-pon.c +++ b/drivers/power/reset/qcom-pon.c@@ -27,17 +27,17 @@ struct qcom_pon { long reason_shift; }; -static int qcom_pon_reboot_mode_write(struct reboot_mode_driver *reboot, - unsigned int magic) +static int qcom_pon_reboot_mode_write(struct reboot_mode_driver *reboot, u64 magic) { struct qcom_pon *pon = container_of (reboot, struct qcom_pon, reboot_mode); + u32 magic_arg1 = REBOOT_MODE_ARG1(magic); int ret; ret = regmap_update_bits(pon->regmap, pon->baseaddr + PON_SOFT_RB_SPARE, GENMASK(7, pon->reason_shift), - magic << pon->reason_shift); + magic_arg1 << pon->reason_shift); if (ret < 0) dev_err(pon->dev, "update reboot mode bits failed\n");diff --git a/drivers/power/reset/reboot-mode.c b/drivers/power/reset/reboot-mode.c index d033043f5250a4de152a7786ef37e88a0ace3bbb..f5ab6eab210bcd9670441a4d2a301d9efdf2f322 100644 --- a/drivers/power/reset/reboot-mode.c +++ b/drivers/power/reset/reboot-mode.c@@ -19,12 +19,11 @@ struct mode_info { const char *mode; - u32 magic; + u64 magic; struct list_head list; }; -static unsigned int get_reboot_mode_magic(struct reboot_mode_driver *reboot, - const char *cmd) +static u64 get_reboot_mode_magic(struct reboot_mode_driver *reboot, const char *cmd) { const char *normal = "normal"; struct mode_info *info;@@ -56,7 +55,7 @@ static int reboot_mode_notify(struct notifier_block *this, unsigned long mode, void *cmd) { struct reboot_mode_driver *reboot; - unsigned int magic; + u64 magic; reboot = container_of(this, struct reboot_mode_driver, reboot_notifier); magic = get_reboot_mode_magic(reboot, cmd);@@ -78,7 +77,7 @@ int reboot_mode_register(struct reboot_mode_driver *reboot) struct property *prop; struct device_node *np = reboot->dev->of_node; size_t len = strlen(PREFIX); - u32 magic; + u32 magic[2] = {0}; int ret; INIT_LIST_HEAD(&reboot->head);@@ -87,7 +86,10 @@ int reboot_mode_register(struct reboot_mode_driver *reboot) if (strncmp(prop->name, PREFIX, len)) continue; - if (device_property_read_u32(reboot->dev, prop->name, &magic)) { + size_t count = device_property_count_u32(reboot->dev, prop->name); + + if (!count || count > ARRAY_SIZE(magic) || + device_property_read_u32_array(reboot->dev, prop->name, magic, count)) { pr_debug("reboot mode %s without magic number\n", prop->name); continue; }@@ -98,7 +100,7 @@ int reboot_mode_register(struct reboot_mode_driver *reboot) goto error; } - info->magic = magic; + info->magic = REBOOT_MODE_MAGIC(magic[0], magic[1]); info->mode = kstrdup_const(prop->name + len, GFP_KERNEL); if (!info->mode) { ret = -ENOMEM;diff --git a/drivers/power/reset/syscon-reboot-mode.c b/drivers/power/reset/syscon-reboot-mode.c index e0772c9f70f7a19cd8ec8a0b7fdbbaa7ba44afd0..9f4b18c5e46f6a8bf197773ceceb80b250f57541 100644 --- a/drivers/power/reset/syscon-reboot-mode.c +++ b/drivers/power/reset/syscon-reboot-mode.c@@ -20,16 +20,16 @@ struct syscon_reboot_mode { u32 mask; }; -static int syscon_reboot_mode_write(struct reboot_mode_driver *reboot, - unsigned int magic) +static int syscon_reboot_mode_write(struct reboot_mode_driver *reboot, u64 magic) { struct syscon_reboot_mode *syscon_rbm; + u32 magic_arg1 = REBOOT_MODE_ARG1(magic); int ret; syscon_rbm = container_of(reboot, struct syscon_reboot_mode, reboot); ret = regmap_update_bits(syscon_rbm->map, syscon_rbm->offset, - syscon_rbm->mask, magic); + syscon_rbm->mask, magic_arg1); if (ret < 0) dev_err(reboot->dev, "update reboot mode bits failed\n");diff --git a/include/linux/reboot-mode.h b/include/linux/reboot-mode.h index 4a2abb38d1d612ec0fdf05eb18c98b210f631b7f..2ce189fdfff4b396d7cc6f175b30016781ae4fe9 100644 --- a/include/linux/reboot-mode.h +++ b/include/linux/reboot-mode.h@@ -2,10 +2,23 @@ #ifndef __REBOOT_MODE_H__ #define __REBOOT_MODE_H__ +#include <linux/bitfield.h> +#include <linux/bits.h> +#include <linux/types.h> + +/* Construct 64-bit reboot magic: arg2 in upper 32 bits, arg1 in lower 32 */ +#define REBOOT_MODE_MAGIC(arg1, arg2) \ + (FIELD_PREP(GENMASK_ULL(31, 0), (arg1)) | \ + FIELD_PREP(GENMASK_ULL(63, 32), (arg2))) +/* Get 32 bit arg1 from 64 bit magic */ +#define REBOOT_MODE_ARG1(magic) FIELD_GET(GENMASK_ULL(31, 0), magic) +/* Get 32 bit arg2 from 64 bit magic */ +#define REBOOT_MODE_ARG2(magic) FIELD_GET(GENMASK_ULL(63, 32), magic) + struct reboot_mode_driver { struct device *dev; struct list_head head; - int (*write)(struct reboot_mode_driver *reboot, unsigned int magic); + int (*write)(struct reboot_mode_driver *reboot, u64 magic); struct notifier_block reboot_notifier; };-- 2.34.1
Attachments
- signature.asc [application/pgp-signature] 833 bytes