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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox