[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20251223-arm-psci-system_reset2-vendor-reboots-v18-2-32fa9e76efc3@oss.qualcomm.com>
Date: Tue, 23 Dec 2025 22:37:33 +0530
From: Shivendra Pratap <shivendra.pratap@....qualcomm.com>
To: Lorenzo Pieralisi <lpieralisi@...nel.org>, Arnd Bergmann <arnd@...db.de>,
Bjorn Andersson <andersson@...nel.org>,
Sebastian Reichel <sre@...nel.org>, Rob Herring <robh@...nel.org>,
Sudeep Holla <sudeep.holla@....com>,
Souvik Chakravarty <Souvik.Chakravarty@....com>,
Krzysztof Kozlowski <krzk+dt@...nel.org>,
Andy Yan <andy.yan@...k-chips.com>,
Bartosz Golaszewski <brgl@...nel.org>
Cc: Florian Fainelli <florian.fainelli@...adcom.com>,
Krzysztof Kozlowski <krzk@...nel.org>,
Dmitry Baryshkov <dmitry.baryshkov@....qualcomm.com>,
Mukesh Ojha <mukesh.ojha@....qualcomm.com>,
Andre Draszik <andre.draszik@...aro.org>,
Kathiravan Thirumoorthy <kathiravan.thirumoorthy@....qualcomm.com>,
linux-pm@...r.kernel.org, linux-kernel@...r.kernel.org,
linux-arm-kernel@...ts.infradead.org, linux-arm-msm@...r.kernel.org,
Shivendra Pratap <shivendra.pratap@....qualcomm.com>,
Srinivas Kandagatla <srini@...nel.org>,
Umang Chheda <umang.chheda@....qualcomm.com>,
Nirmesh Kumar Singh <nirmesh.singh@....qualcomm.com>
Subject: [PATCH v18 02/10] power: reset: reboot-mode: Add support for 64
bit magic
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.
u64 magic
--------------------------------------------
| Higher 32 bit | Lower 32 bit |
| arg2 | arg1 |
--------------------------------------------
Update current reboot-mode drivers for 64-bit magic.
Reviewed-by: Umang Chheda <umang.chheda@....qualcomm.com>
Reviewed-by: Nirmesh Kumar Singh <nirmesh.singh@....qualcomm.com>
Signed-off-by: Shivendra Pratap <shivendra.pratap@....qualcomm.com>
---
drivers/power/reset/nvmem-reboot-mode.c | 10 ++++++----
drivers/power/reset/qcom-pon.c | 8 +++++---
drivers/power/reset/reboot-mode.c | 24 ++++++++++++++++++------
drivers/power/reset/syscon-reboot-mode.c | 8 +++++---
include/linux/reboot-mode.h | 6 +++++-
5 files changed, 39 insertions(+), 17 deletions(-)
diff --git a/drivers/power/reset/nvmem-reboot-mode.c b/drivers/power/reset/nvmem-reboot-mode.c
index 41530b70cfc48c2a83fbbd96f523d5816960a0d1..b3d21d39b0f732254c40103db1b51fb7045ce344 100644
--- a/drivers/power/reset/nvmem-reboot-mode.c
+++ b/drivers/power/reset/nvmem-reboot-mode.c
@@ -16,15 +16,17 @@ 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)
{
- int ret;
struct nvmem_reboot_mode *nvmem_rbm;
+ u32 magic_arg1;
+ int ret;
+ /* Use low 32 bits of magic for argument_1 */
+ magic_arg1 = FIELD_GET(GENMASK_ULL(31, 0), magic);
nvmem_rbm = container_of(reboot, struct nvmem_reboot_mode, reboot);
- ret = nvmem_cell_write(nvmem_rbm->cell, &magic, sizeof(magic));
+ ret = nvmem_cell_write(nvmem_rbm->cell, &magic_arg1, sizeof(magic_arg1));
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..ccce1673b2ec47d02524edd44811d4f528c243e8 100644
--- a/drivers/power/reset/qcom-pon.c
+++ b/drivers/power/reset/qcom-pon.c
@@ -27,17 +27,19 @@ 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;
int ret;
+ /* Use low 32 bits of magic for argument_1 */
+ magic_arg1 = FIELD_GET(GENMASK_ULL(31, 0), magic);
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 4b6ae4007c4f6fb7d51520b4be2bf3cb1dff518e..54adcda57e44edf2fd2cda0f752226f747aa72d7 100644
--- a/drivers/power/reset/reboot-mode.c
+++ b/drivers/power/reset/reboot-mode.c
@@ -17,12 +17,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;
@@ -54,7 +53,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);
@@ -77,7 +76,8 @@ 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_arg1;
+ u32 magic_arg2;
int ret;
INIT_LIST_HEAD(&reboot->head);
@@ -86,10 +86,13 @@ int reboot_mode_register(struct reboot_mode_driver *reboot)
if (strncmp(prop->name, PREFIX, len))
continue;
- if (of_property_read_u32(np, prop->name, &magic)) {
+ if (of_property_read_u32(np, prop->name, &magic_arg1)) {
pr_err("reboot mode %s without magic number\n", prop->name);
continue;
}
+ /* Default magic_arg2 to zero */
+ if (of_property_read_u32_index(np, prop->name, 1, &magic_arg2))
+ magic_arg2 = 0;
info = kzalloc(sizeof(*info), GFP_KERNEL);
if (!info) {
@@ -97,6 +100,15 @@ int reboot_mode_register(struct reboot_mode_driver *reboot)
goto error;
}
+ /**
+ * Format of u64 magic
+ *-------------------------------------------
+ *| Higher 32 bit | Lower 32 bit |
+ *| arg2 | arg1 |
+ *-------------------------------------------
+ */
+ info->magic = FIELD_PREP(GENMASK_ULL(63, 32), magic_arg2) |
+ FIELD_PREP(GENMASK_ULL(31, 0), magic_arg1);
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..eb7fc5b7d6a7ed8a833d4920991c4c40b5b13ca7 100644
--- a/drivers/power/reset/syscon-reboot-mode.c
+++ b/drivers/power/reset/syscon-reboot-mode.c
@@ -20,16 +20,18 @@ 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;
int ret;
+ /* Use low 32 bits of magic for argument_1 */
+ magic_arg1 = FIELD_GET(GENMASK_ULL(31, 0), magic);
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..a359dc0c6dede0ac5ce67190a00d46a7e7856707 100644
--- a/include/linux/reboot-mode.h
+++ b/include/linux/reboot-mode.h
@@ -2,10 +2,14 @@
#ifndef __REBOOT_MODE_H__
#define __REBOOT_MODE_H__
+#include <linux/bitfield.h>
+#include <linux/bits.h>
+#include <linux/types.h>
+
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
Powered by blists - more mailing lists