All of lore.kernel.org
 help / color / mirror / Atom feed
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>,
	Tom Rini <trini@konsulko.com>,
	Jaehoon Chung <jh80.chung@samsung.com>,
	Peng Fan <peng.fan@nxp.com>,
	"Neil Armstrong" <neil.armstrong@linaro.org>,
	Simon Glass <sjg@chromium.org>,
	"Kory Maincent" <kory.maincent@bootlin.com>,
	Kuan-Wei Chiu <visitorckw@gmail.com>,
	Raymond Mao <raymond.mao@riscstar.com>,
	Quentin Schulz <quentin.schulz@cherry.de>,
	Stefan Roese <stefan.roese@mailbox.org>,
	"Jerome Forissier" <jerome.forissier@arm.com>,
	Philip Molloy <philip.molloy@analog.com>,
	Tien Fong Chee <tien.fong.chee@altera.com>,
	"Casey Connolly" <casey.connolly@linaro.org>,
	Balaji Selvanathan <balaji.selvanathan@oss.qualcomm.com>,
	Alif Zakuan Yuslaimi <alif.zakuan.yuslaimi@altera.com>,
	Sumit Garg <sumit.garg@oss.qualcomm.com>,
	"Markus Schneider-Pargmann (TI.com)" <msp@baylibre.com>,
	Marek Vasut <marek.vasut@mailbox.org>,
	Aswin Murugan <aswin.murugan@oss.qualcomm.com>
Subject: [PATCH 5/7] drivers: power: add support for RPMI power domains
Date: Fri, 26 Jun 2026 13:15:46 -0700	[thread overview]
Message-ID: <20260626201613.1035208-6-charles.perry@microchip.com> (raw)
In-Reply-To: <20260626201613.1035208-1-charles.perry@microchip.com>

The RISC-V Platform Management Interface (RPMI) defines the device power
service group [1] that is used to control power domains. This is used to
implement a UCLASS_POWER_DOMAIN driver.

[1]: https://github.com/riscv-non-isa/riscv-rpmi (chapter 4.9)

Signed-off-by: Charles Perry <charles.perry@microchip.com>
---
 MAINTAINERS                              |   1 +
 drivers/power/domain/Kconfig             |   7 +
 drivers/power/domain/Makefile            |   1 +
 drivers/power/domain/rpmi-power-domain.c | 229 +++++++++++++++++++++++
 include/rpmi_proto.h                     |  18 ++
 5 files changed, 256 insertions(+)
 create mode 100644 drivers/power/domain/rpmi-power-domain.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 0bf6582ef493..d2b18d9b13db 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1694,6 +1694,7 @@ M:	Charles Perry <charles.perry@microchip.com>
 S:	Maintained
 F:	drivers/clk/clk_rpmi.c
 F:	drivers/firmware/rpmi/
+F:	drivers/power/domain/rpmi-power-domain.c
 F:	include/rpmi*
 
 SANDBOX
diff --git a/drivers/power/domain/Kconfig b/drivers/power/domain/Kconfig
index 4112b777371d..e8484b193cad 100644
--- a/drivers/power/domain/Kconfig
+++ b/drivers/power/domain/Kconfig
@@ -106,6 +106,13 @@ config RENESAS_R8A78000_POWER_DOMAIN
 	  and reset driver. The MDLC is responsible for managing both
 	  power domains and resets on R-Car R8A78000 X5H SoC.
 
+config RPMI_POWER_DOMAIN
+	bool "Enable the RPMI Power domain driver"
+	depends on POWER_DOMAIN && RPMI_FIRMWARE
+	help
+	  Enable this option if you want to support power domains managed by
+	  the RISC-V Platform Management Interface (RPMI) protocol.
+
 config SANDBOX_POWER_DOMAIN
 	bool "Enable the sandbox power domain test driver"
 	depends on POWER_DOMAIN && SANDBOX
diff --git a/drivers/power/domain/Makefile b/drivers/power/domain/Makefile
index 110153d5cf81..9c42160e18be 100644
--- a/drivers/power/domain/Makefile
+++ b/drivers/power/domain/Makefile
@@ -16,6 +16,7 @@ obj-$(CONFIG_MESON_GX_VPU_POWER_DOMAIN) += meson-gx-pwrc-vpu.o
 obj-$(CONFIG_MESON_EE_POWER_DOMAIN) += meson-ee-pwrc.o
 obj-$(CONFIG_MESON_SECURE_POWER_DOMAIN) += meson-secure-pwrc.o
 obj-$(CONFIG_RENESAS_R8A78000_POWER_DOMAIN) += renesas-r8a78000-power-domain.o
+obj-$(CONFIG_RPMI_POWER_DOMAIN) += rpmi-power-domain.o
 obj-$(CONFIG_SANDBOX_POWER_DOMAIN) += sandbox-power-domain.o
 obj-$(CONFIG_SANDBOX_POWER_DOMAIN) += sandbox-power-domain-test.o
 obj-$(CONFIG_SCMI_POWER_DOMAIN) += scmi-power-domain.o
diff --git a/drivers/power/domain/rpmi-power-domain.c b/drivers/power/domain/rpmi-power-domain.c
new file mode 100644
index 000000000000..f00ebab86686
--- /dev/null
+++ b/drivers/power/domain/rpmi-power-domain.c
@@ -0,0 +1,229 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2026 Microchip Technology Inc. All rights reserved.
+ */
+
+#include <dm.h>
+#include <malloc.h>
+#include <power-domain.h>
+#include <power-domain-uclass.h>
+#include <rpmi.h>
+#include <dm/device_compat.h>
+
+struct rpmi_get_num_pd_rx {
+	__le32 status;
+	__le32 num_pd;
+};
+
+struct rpmi_get_attrs_tx {
+	__le32 pd_id;
+};
+
+struct rpmi_get_attrs_rx {
+	__le32 status;
+	__le32 flags;
+	__le32 trans_latency;
+	char name[RPMI_DPWR_NAME_LEN];
+};
+
+struct rpmi_set_state_tx {
+	__le32 pd_id;
+	__le32 state;
+};
+
+struct rpmi_set_state_rx {
+	__le32 status;
+};
+
+struct rpmi_pd_def {
+	u32 transition_latency;
+	char name[RPMI_DPWR_NAME_LEN + 1];
+};
+
+struct rpmi_pd_priv {
+	struct rpmi_chan chan;
+	struct udevice *dev;
+	u32 num_pd;
+	struct rpmi_pd_def *defs;
+};
+
+static int rpmi_pd_get_attrs(struct rpmi_pd_priv *priv, u32 pd_id,
+			     struct rpmi_pd_def *def)
+{
+	struct rpmi_get_attrs_tx tx = {
+		.pd_id = cpu_to_le32(pd_id),
+	};
+	struct rpmi_get_attrs_rx rx;
+	int ret, status;
+
+	ret = rpmi_send_with_resp(&priv->chan, RPMI_DPWR_SRV_GET_ATTRIBUTES,
+				  &tx, sizeof(tx), &rx, sizeof(rx), NULL);
+	if (ret)
+		return ret;
+
+	status = le32_to_cpu(rx.status);
+	if (status)
+		return rpmi_to_linux_error(status);
+
+	def->transition_latency = le32_to_cpu(rx.trans_latency);
+	memcpy(def->name, rx.name, RPMI_DPWR_NAME_LEN);
+	def->name[RPMI_DPWR_NAME_LEN] = '\0';
+
+	return 0;
+}
+
+static int rpmi_pd_set_state(struct rpmi_pd_priv *priv, u32 pd_id, u32 state)
+{
+	struct rpmi_set_state_tx tx = {
+		.pd_id = cpu_to_le32(pd_id),
+		.state = cpu_to_le32(state),
+	};
+	struct rpmi_set_state_rx rx;
+	int ret, status;
+
+	ret = rpmi_send_with_resp(&priv->chan, RPMI_DPWR_SRV_SET_DPWR_STATE,
+				  &tx, sizeof(tx), &rx, sizeof(rx), NULL);
+
+	if (ret)
+		return ret;
+
+	status = le32_to_cpu(rx.status);
+	if (status)
+		return rpmi_to_linux_error(status);
+
+	return 0;
+}
+
+static int rpmi_power_domain_on(struct power_domain *power_domain)
+{
+	return rpmi_pd_set_state(dev_get_plat(power_domain->dev),
+				 power_domain->id, RPMI_DPWR_STATE_ON);
+}
+
+static int rpmi_power_domain_off(struct power_domain *power_domain)
+{
+	return rpmi_pd_set_state(dev_get_plat(power_domain->dev),
+				 power_domain->id, RPMI_DPWR_STATE_OFF);
+}
+
+static int rpmi_power_domain_xlate(struct power_domain *power_domain,
+				   struct ofnode_phandle_args *args)
+{
+	struct rpmi_pd_priv *priv = dev_get_plat(power_domain->dev);
+
+	if (args->args_count != 1)
+		return -EINVAL;
+
+	if (args->args[0] >= priv->num_pd)
+		return -EINVAL;
+
+	power_domain->id = args->args[0];
+
+	return 0;
+}
+
+static int rpmi_pd_get_num_domains(struct rpmi_pd_priv *priv)
+{
+	struct rpmi_get_num_pd_rx rx;
+	int ret, status;
+
+	ret = rpmi_send_with_resp(&priv->chan, RPMI_DPWR_SRV_GET_NUM_DOMAINS,
+				  NULL, 0, &rx, sizeof(rx), NULL);
+	if (ret)
+		return ret;
+
+	status = le32_to_cpu(rx.status);
+	if (status)
+		return rpmi_to_linux_error(status);
+
+	priv->num_pd = le32_to_cpu(rx.num_pd);
+
+	return 0;
+}
+
+static int rpmi_pd_probe(struct udevice *dev)
+{
+	struct rpmi_pd_priv *priv = (struct rpmi_pd_priv *)dev_get_plat(dev);
+	struct rpmi_chan *chan = &priv->chan;
+	int ret, i;
+
+	priv->dev = dev;
+
+	ret = rpmi_open(chan);
+	if (ret)
+		return ret;
+
+	ret = rpmi_check_versions(chan, RPMI_MKVER(1, 0),
+				  RPMI_SRVGRP_DEVICE_POWER, RPMI_MKVER(1, 0));
+	if (ret)
+		goto err_out;
+
+	ret = rpmi_pd_get_num_domains(priv);
+	if (ret)
+		goto err_out;
+
+	priv->defs = calloc(priv->num_pd, sizeof(struct rpmi_pd_def));
+	if (!priv->defs) {
+		ret = -ENOMEM;
+		goto err_out;
+	}
+
+	for (i = 0; i < priv->num_pd; i++) {
+		ret = rpmi_pd_get_attrs(priv, i, &priv->defs[i]);
+		if (ret)
+			goto err_out;
+	}
+
+	dev_dbg(dev, "num pd = %i\n", priv->num_pd);
+
+	return 0;
+
+err_out:
+	if (priv->defs)
+		free(priv->defs);
+	rpmi_close(chan);
+
+	return ret;
+}
+
+static int rpmi_pd_remove(struct udevice *dev)
+{
+	struct rpmi_pd_priv *priv = (struct rpmi_pd_priv *)dev_get_plat(dev);
+	struct rpmi_chan *chan = &priv->chan;
+
+	if (priv->defs)
+		free(priv->defs);
+	rpmi_close(chan);
+
+	return 0;
+}
+
+static int rpmi_pd_to_plat(struct udevice *dev)
+{
+	struct rpmi_pd_priv *priv = (struct rpmi_pd_priv *)dev_get_plat(dev);
+
+	return rpmi_get_by_index(dev, 0, &priv->chan);
+}
+
+static const struct power_domain_ops rpmi_pd_ops = {
+	.of_xlate = rpmi_power_domain_xlate,
+	.on = rpmi_power_domain_on,
+	.off = rpmi_power_domain_off,
+};
+
+static const struct udevice_id rpmi_pd_ids[] = {
+	{ .compatible = "riscv,rpmi-device-power" },
+	{}
+};
+
+U_BOOT_DRIVER(rpmi_pd) = {
+	.name = "rpmi-device-power",
+	.id = UCLASS_POWER_DOMAIN,
+	.of_match = rpmi_pd_ids,
+	.probe = rpmi_pd_probe,
+	.remove = rpmi_pd_remove,
+	.ops = &rpmi_pd_ops,
+	.of_to_plat = rpmi_pd_to_plat,
+	.plat_auto = sizeof(struct rpmi_pd_priv),
+	.flags = DM_FLAG_PRE_RELOC,
+};
diff --git a/include/rpmi_proto.h b/include/rpmi_proto.h
index dc0937ce7053..d2512617f75c 100644
--- a/include/rpmi_proto.h
+++ b/include/rpmi_proto.h
@@ -122,4 +122,22 @@ enum rpmi_clock_type {
 
 #define RPMI_CLOCK_RATE_INVALID		(-1ULL)
 
+/* RPMI Device_Power (DPWR) service IDs */
+enum rpmi_dpwr_service_id {
+	RPMI_DPWR_SRV_ENABLE_NOTIFICATION = 0x01,
+	RPMI_DPWR_SRV_GET_NUM_DOMAINS = 0x02,
+	RPMI_DPWR_SRV_GET_ATTRIBUTES = 0x03,
+	RPMI_DPWR_SRV_SET_DPWR_STATE = 0x04,
+	RPMI_DPWR_SRV_GET_DPWR_STATE = 0x05,
+	RPMI_DPWR_SRV_ID_MAX,
+};
+
+enum rpmi_dpwr_state {
+	RPMI_DPWR_STATE_INVALID = -1,
+	RPMI_DPWR_STATE_ON = 0,
+	RPMI_DPWR_STATE_OFF = 3,
+};
+
+#define RPMI_DPWR_NAME_LEN 16
+
 #endif
-- 
2.47.3


  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 ` Charles Perry [this message]
2026-06-26 20:15 ` [PATCH 6/7] firmware: rpmi: add a test and a sandbox driver Charles Perry
2026-06-26 20:15 ` [PATCH 7/7] firmware: rpmi: add a test and sandbox for device power Charles Perry

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-6-charles.perry@microchip.com \
    --to=charles.perry@microchip.com \
    --cc=alif.zakuan.yuslaimi@altera.com \
    --cc=anup@brainfault.org \
    --cc=aswin.murugan@oss.qualcomm.com \
    --cc=balaji.selvanathan@oss.qualcomm.com \
    --cc=casey.connolly@linaro.org \
    --cc=jerome.forissier@arm.com \
    --cc=jh80.chung@samsung.com \
    --cc=kory.maincent@bootlin.com \
    --cc=marek.vasut@mailbox.org \
    --cc=msp@baylibre.com \
    --cc=neil.armstrong@linaro.org \
    --cc=peng.fan@nxp.com \
    --cc=philip.molloy@analog.com \
    --cc=quentin.schulz@cherry.de \
    --cc=rahul@summations.net \
    --cc=raymond.mao@riscstar.com \
    --cc=sjg@chromium.org \
    --cc=stefan.roese@mailbox.org \
    --cc=sumit.garg@oss.qualcomm.com \
    --cc=tien.fong.chee@altera.com \
    --cc=trini@konsulko.com \
    --cc=u-boot@lists.denx.de \
    --cc=visitorckw@gmail.com \
    /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.