From: Charles Perry <charles.perry@microchip.com>
To: <u-boot@lists.denx.de>
Cc: Rahul Pathak <rahul@summations.net>,
Anup Patel <anup@brainfault.org>,
Charles Perry <charles.perry@microchip.com>,
Simon Glass <sjg@chromium.org>, Tom Rini <trini@konsulko.com>,
Mattijs Korpershoek <mkorpershoek@kernel.org>,
Marek Vasut <marek.vasut+renesas@mailbox.org>,
Heiko Schocher <hs@nabladev.com>,
Svyatoslav Ryhel <clamor95@gmail.com>,
"Markus Schneider-Pargmann (TI.com)" <msp@baylibre.com>,
Neil Armstrong <neil.armstrong@linaro.org>,
Lucien.Jheng <lucienzx159@gmail.com>,
"Martin Schwan" <m.schwan@phytec.de>,
Michal Simek <michal.simek@amd.com>, Peng Fan <peng.fan@nxp.com>,
Pieter Van Trappen <pieter.van.trappen@cern.ch>,
"Dinesh Maniyam" <dinesh.maniyam@altera.com>
Subject: [PATCH 7/7] firmware: rpmi: add a test and sandbox for device power
Date: Fri, 26 Jun 2026 13:15:48 -0700 [thread overview]
Message-ID: <20260626201613.1035208-8-charles.perry@microchip.com> (raw)
In-Reply-To: <20260626201613.1035208-1-charles.perry@microchip.com>
Add a simulation of the device power service group using code from
librpmi [1] and adapted.
[1]: https://github.com/riscv-software-src/librpmi/blob/3f3c4ca47339a8795432e260f17e1fc5091c9a3a/lib/rpmi_service_group_device_power.c
Signed-off-by: Charles Perry <charles.perry@microchip.com>
---
arch/sandbox/dts/test.dts | 11 ++
configs/sandbox_defconfig | 1 +
drivers/firmware/rpmi/Makefile | 2 +-
drivers/firmware/rpmi/rpmi-sandbox-power.c | 174 +++++++++++++++++++++
drivers/firmware/rpmi/rpmi-sandbox.c | 2 +
drivers/firmware/rpmi/rpmi-sandbox.h | 1 +
test/dm/rpmi.c | 21 +++
7 files changed, 211 insertions(+), 1 deletion(-)
create mode 100644 drivers/firmware/rpmi/rpmi-sandbox-power.c
diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index e5d6f398fb35..7e25053851f4 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -886,6 +886,12 @@
#clock-cells = <1>;
clocks = <&rpmi_clock 0>, <&rpmi_clock 1>, <&rpmi_clock 2>, <&rpmi_clock 3>;
};
+
+ rpmi_dpwr: rpmi-power-domain {
+ compatible = "riscv,rpmi-device-power";
+ mboxes = <&rpmi 0x9>;
+ #power-domain-cells = <1>;
+ };
};
fpga {
@@ -1927,6 +1933,11 @@
regul1-supply = <®ul1_scmi>;
};
+ rpmi-power-domain-test {
+ compatible = "sandbox,power-domain-test";
+ power-domains = <&rpmi_dpwr 1>;
+ };
+
pinctrl {
compatible = "sandbox,pinctrl";
diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
index f1637e1ff09c..59967bd2ee0f 100644
--- a/configs/sandbox_defconfig
+++ b/configs/sandbox_defconfig
@@ -289,6 +289,7 @@ CONFIG_PINCONF=y
CONFIG_PINCTRL_SANDBOX=y
CONFIG_PINCTRL_SINGLE=y
CONFIG_POWER_DOMAIN=y
+CONFIG_RPMI_POWER_DOMAIN=y
CONFIG_SANDBOX_POWER_DOMAIN=y
CONFIG_SCMI_POWER_DOMAIN=y
CONFIG_DM_PMIC=y
diff --git a/drivers/firmware/rpmi/Makefile b/drivers/firmware/rpmi/Makefile
index 150e98a72df9..c73ad92baec1 100644
--- a/drivers/firmware/rpmi/Makefile
+++ b/drivers/firmware/rpmi/Makefile
@@ -1,4 +1,4 @@
obj-y += rpmi-uclass.o
obj-$(CONFIG_RPMI_SBI_MPXY) += rpmi-sbi-mpxy.o
obj-$(CONFIG_RPMI_SHMEM) += rpmi-shmem.o
-obj-$(CONFIG_SANDBOX) += rpmi-sandbox.o rpmi-sandbox-clock.o
+obj-$(CONFIG_SANDBOX) += rpmi-sandbox.o rpmi-sandbox-clock.o rpmi-sandbox-power.o
diff --git a/drivers/firmware/rpmi/rpmi-sandbox-power.c b/drivers/firmware/rpmi/rpmi-sandbox-power.c
new file mode 100644
index 000000000000..aba0ecdda0a6
--- /dev/null
+++ b/drivers/firmware/rpmi/rpmi-sandbox-power.c
@@ -0,0 +1,174 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2024 Ventana Micro Systems Inc.
+ * Copyright (C) 2026 Microchip Technology Inc. All rights reserved.
+ */
+
+#define LOG_CATEGORY UCLASS_RPMI
+
+#include <asm/types.h>
+#include <asm/io.h>
+#include <asm/byteorder.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <rpmi.h>
+#include "rpmi-sandbox.h"
+
+struct rpmi_dpwr {
+ const char *name;
+ u32 trans_latency;
+ enum rpmi_dpwr_state state;
+};
+
+struct rpmi_dpwr dpwr_simulation[] = {
+ { "DPWR0", 0, RPMI_DPWR_STATE_ON },
+ { "DPWR1", 0, RPMI_DPWR_STATE_OFF },
+};
+
+static u32 dpwr_count = ARRAY_SIZE(dpwr_simulation);
+
+static struct rpmi_dpwr *rpmi_get_dpwr(u32 dpwrid)
+{
+ if (dpwrid >= ARRAY_SIZE(dpwr_simulation))
+ return NULL;
+
+ return &dpwr_simulation[dpwrid];
+}
+
+static enum rpmi_error_codes
+rpmi_dpwr_get_num_domains(struct rpmi_transport *trans, u16 request_datalen,
+ const u8 *request_data, u16 *response_datalen,
+ u8 *response_data)
+{
+ u32 *resp = (void *)response_data;
+
+ resp[1] = cpu_to_le32(dpwr_count);
+ resp[0] = cpu_to_le32((u32)RPMI_SUCCESS);
+
+ *response_datalen = 2 * sizeof(*resp);
+
+ return RPMI_SUCCESS;
+}
+
+static enum rpmi_error_codes
+rpmi_dpwr_get_attributes(struct rpmi_transport *trans, u16 request_datalen,
+ const u8 *request_data, u16 *response_datalen,
+ u8 *response_data)
+{
+ u16 resp_dlen = sizeof(u32);
+ u32 *resp = (void *)response_data;
+ struct rpmi_dpwr *dpwr;
+
+ u32 dpwrid = cpu_to_le32(((const u32 *)request_data)[0]);
+
+ dpwr = rpmi_get_dpwr(dpwrid);
+ if (!dpwr) {
+ resp[0] = cpu_to_le32((u32)RPMI_ERR_INVALID_PARAM);
+ goto done;
+ }
+
+ if (dpwr->name)
+ strlcpy((char *)&resp[3], dpwr->name, RPMI_DPWR_NAME_LEN);
+
+ resp[2] = cpu_to_le32(dpwr->trans_latency);
+ resp[1] = cpu_to_le32((u32)0x0);
+ resp[0] = cpu_to_le32((u32)RPMI_SUCCESS);
+
+ resp_dlen = 3 * sizeof(*resp) + RPMI_DPWR_NAME_LEN;
+
+done:
+ *response_datalen = resp_dlen;
+
+ return RPMI_SUCCESS;
+}
+
+static enum rpmi_error_codes rpmi_dpwr_get_state(struct rpmi_transport *trans,
+ u16 request_datalen,
+ const u8 *request_data,
+ u16 *response_datalen,
+ u8 *response_data)
+{
+ u16 resp_dlen = sizeof(u32);
+ u32 *resp = (void *)response_data;
+ u32 dpwr_state = 0;
+ struct rpmi_dpwr *dpwr;
+
+ u32 dpwrid = cpu_to_le32(((const u32 *)request_data)[0]);
+
+ dpwr = rpmi_get_dpwr(dpwrid);
+ if (!dpwr) {
+ resp[0] = cpu_to_le32((u32)RPMI_ERR_INVALID_PARAM);
+ goto done;
+ }
+
+ dpwr_state = dpwr->state;
+
+ resp[1] = cpu_to_le32((u32)dpwr_state);
+ resp[0] = cpu_to_le32((u32)RPMI_SUCCESS);
+
+ resp_dlen = 2 * sizeof(*resp);
+
+done:
+ *response_datalen = resp_dlen;
+ return RPMI_SUCCESS;
+}
+
+static enum rpmi_error_codes rpmi_dpwr_set_state(struct rpmi_transport *trans,
+ u16 request_datalen,
+ const u8 *request_data,
+ u16 *response_datalen,
+ u8 *response_data)
+{
+ u16 resp_dlen = sizeof(u32);
+ u32 *resp = (void *)response_data;
+ struct rpmi_dpwr *dpwr;
+
+ u32 dpwrid = cpu_to_le32(((const u32 *)request_data)[0]);
+ u32 dpwr_state = cpu_to_le32(((const u32 *)request_data)[1]);
+
+ dpwr = rpmi_get_dpwr(dpwrid);
+ if (!dpwr) {
+ resp[0] = cpu_to_le32((u32)RPMI_ERR_INVALID_PARAM);
+ goto done;
+ }
+
+ dpwr->state = dpwr_state;
+
+ resp[0] = cpu_to_le32((u32)RPMI_SUCCESS);
+
+ resp_dlen = sizeof(*resp);
+
+done:
+ *response_datalen = resp_dlen;
+ return RPMI_SUCCESS;
+}
+
+static struct rpmi_service rpmi_dpwr_services[RPMI_DPWR_SRV_ID_MAX] = {
+ [RPMI_DPWR_SRV_GET_NUM_DOMAINS] = {
+ .service_id = RPMI_DPWR_SRV_GET_NUM_DOMAINS,
+ .min_a2p_request_datalen = 0,
+ .process_a2p_request = rpmi_dpwr_get_num_domains,
+ },
+ [RPMI_DPWR_SRV_GET_ATTRIBUTES] = {
+ .service_id = RPMI_DPWR_SRV_GET_ATTRIBUTES,
+ .min_a2p_request_datalen = 4,
+ .process_a2p_request = rpmi_dpwr_get_attributes,
+ },
+ [RPMI_DPWR_SRV_SET_DPWR_STATE] = {
+ .service_id = RPMI_DPWR_SRV_SET_DPWR_STATE,
+ .min_a2p_request_datalen = 8,
+ .process_a2p_request = rpmi_dpwr_set_state,
+ },
+ [RPMI_DPWR_SRV_GET_DPWR_STATE] = {
+ .service_id = RPMI_DPWR_SRV_GET_DPWR_STATE,
+ .min_a2p_request_datalen = 4,
+ .process_a2p_request = rpmi_dpwr_get_state,
+ },
+};
+
+const struct rpmi_service_group rpmi_sandbox_dpwr_sg = {
+ .name = "dpwr",
+ .max_service_id = RPMI_DPWR_SRV_GET_DPWR_STATE,
+ .servicegroup_version = RPMI_MKVER(1, 0),
+ .services = rpmi_dpwr_services,
+};
diff --git a/drivers/firmware/rpmi/rpmi-sandbox.c b/drivers/firmware/rpmi/rpmi-sandbox.c
index 5597c27067eb..c34c61da5d9e 100644
--- a/drivers/firmware/rpmi/rpmi-sandbox.c
+++ b/drivers/firmware/rpmi/rpmi-sandbox.c
@@ -29,6 +29,8 @@ const struct rpmi_service_group *rpmi_sandbox_sg(u32 servicegroup_id)
switch (servicegroup_id) {
case RPMI_SRVGRP_CLOCK:
return &rpmi_sandbox_clock_sg;
+ case RPMI_SRVGRP_DEVICE_POWER:
+ return &rpmi_sandbox_dpwr_sg;
default:
return NULL;
}
diff --git a/drivers/firmware/rpmi/rpmi-sandbox.h b/drivers/firmware/rpmi/rpmi-sandbox.h
index 132d1e9e8be6..7dea5035929e 100644
--- a/drivers/firmware/rpmi/rpmi-sandbox.h
+++ b/drivers/firmware/rpmi/rpmi-sandbox.h
@@ -43,5 +43,6 @@ struct rpmi_service_group {
};
extern const struct rpmi_service_group rpmi_sandbox_clock_sg;
+extern const struct rpmi_service_group rpmi_sandbox_dpwr_sg;
#endif
diff --git a/test/dm/rpmi.c b/test/dm/rpmi.c
index 1ea29780a480..e886b9ab2da4 100644
--- a/test/dm/rpmi.c
+++ b/test/dm/rpmi.c
@@ -9,6 +9,7 @@
#include <stdio.h>
#include <dm/device-internal.h>
#include <dm/test.h>
+#include <asm/power-domain.h>
#include <test/ut.h>
static int dm_test_rpmi_clock(struct unit_test_state *uts)
@@ -46,3 +47,23 @@ static int dm_test_rpmi_clock(struct unit_test_state *uts)
return 0;
}
DM_TEST(dm_test_rpmi_clock, UTF_SCAN_FDT);
+
+static int dm_test_rpmi_dpwr(struct unit_test_state *uts)
+{
+ struct udevice *rpmi_dev, *dpwr_dev, *dpwr_consumer;
+
+ ut_assertok(uclass_get_device_by_name(UCLASS_RPMI, "rpmi", &rpmi_dev));
+
+ ut_assertok(uclass_get_device_by_name(UCLASS_POWER_DOMAIN,
+ "rpmi-power-domain", &dpwr_dev));
+
+ ut_assertok(uclass_get_device_by_name(
+ UCLASS_MISC, "rpmi-power-domain-test", &dpwr_consumer));
+
+ ut_assertok(sandbox_power_domain_test_get(dpwr_consumer));
+ ut_assertok(sandbox_power_domain_test_on(dpwr_consumer));
+ ut_assertok(sandbox_power_domain_test_off(dpwr_consumer));
+
+ return 0;
+}
+DM_TEST(dm_test_rpmi_dpwr, UTF_SCAN_FDT);
--
2.47.3
prev parent reply other threads:[~2026-06-26 21:21 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-06-26 20:15 [PATCH 0/7] Add support for RPMI to U-Boot Charles Perry
2026-06-26 20:15 ` [PATCH 1/7] firmware: add support for RPMI Charles Perry
2026-06-27 1:09 ` Yao Zi
2026-06-26 20:15 ` [PATCH 2/7] firmware: rpmi: add support for the SBI MPXY transport Charles Perry
2026-06-27 1:30 ` Yao Zi
2026-06-26 20:15 ` [PATCH 3/7] firmware: rpmi: add support for shared memory transport Charles Perry
2026-06-26 20:15 ` [PATCH 4/7] drivers: clk: add support for RPMI clocks Charles Perry
2026-06-27 1:47 ` Yao Zi
2026-06-26 20:15 ` [PATCH 5/7] drivers: power: add support for RPMI power domains Charles Perry
2026-06-26 20:15 ` [PATCH 6/7] firmware: rpmi: add a test and a sandbox driver Charles Perry
2026-06-26 20:15 ` Charles Perry [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260626201613.1035208-8-charles.perry@microchip.com \
--to=charles.perry@microchip.com \
--cc=anup@brainfault.org \
--cc=clamor95@gmail.com \
--cc=dinesh.maniyam@altera.com \
--cc=hs@nabladev.com \
--cc=lucienzx159@gmail.com \
--cc=m.schwan@phytec.de \
--cc=marek.vasut+renesas@mailbox.org \
--cc=michal.simek@amd.com \
--cc=mkorpershoek@kernel.org \
--cc=msp@baylibre.com \
--cc=neil.armstrong@linaro.org \
--cc=peng.fan@nxp.com \
--cc=pieter.van.trappen@cern.ch \
--cc=rahul@summations.net \
--cc=sjg@chromium.org \
--cc=trini@konsulko.com \
--cc=u-boot@lists.denx.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.