public inbox for u-boot@lists.denx.de
 help / color / mirror / Atom feed
* [PATCH 0/4] firmware: scmi: add SCMI power domain protocol support
@ 2023-09-26  7:00 AKASHI Takahiro
  2023-09-26  7:00 ` [PATCH 1/4] firmware: scmi: add " AKASHI Takahiro
                   ` (3 more replies)
  0 siblings, 4 replies; 10+ messages in thread
From: AKASHI Takahiro @ 2023-09-26  7:00 UTC (permalink / raw)
  To: trini, sjg; +Cc: etienne.carriere, u-boot, AKASHI Takahiro

This patch series allows users to access SCMI power domain protocol
provided by SCMI server (platform). See SCMI specification document
v3.2 beta 2[1] for more details about SCMI power domain protocol.

The implementation consists of two layers:
- basic helper functions for SCMI power domain protocol
  in drivers/firmware/scmi/pwdom.c (patch#1)
- DM-compliant power domain driver, which utilizes the helper functions,
  in drivers/power/domain/scmi-power-domain.c (patch#2)

[1] https://developer.arm.com/documentation/den0056/e/?lang=en

DT bindings
===========
Standard bindings are applied, i.e.

scmi {
    ...
    pwrdom_scmi: protocol@11 {
        regs = <0x11>;
        #power-domain-cells = <1>;
    }
    ...
}

som-device {
    ...
    power-domains = <&pwrdom_scmi 2>;
}

Test
====
The patch series was tested on the following platform:
* sandbox ("ut dm scmi_power_domains")


Prerequisite:
=============
* This patch series is based on my "Base protocol support" patches[2]
  on v2023.10-rc4.

[2] https://lists.denx.de/pipermail/u-boot/2023-September/531623.html

Patches:
========
Patch#1: Add SCMI power domain protocol helpers
Patch#2: Add power domain driver
Patch#3-#4: Test related


Change history:
===============
RFC (Sep 26, 2023)
* initial release

AKASHI Takahiro (4):
  firmware: scmi: add power domain protocol support
  power: domain: add SCMI driver
  sandbox: add SCMI power domain protocol support for testing
  test: dm: add SCMI power domain protocol test

 arch/sandbox/dts/test.dts                    |   6 +
 arch/sandbox/include/asm/scmi_test.h         |  20 ++
 configs/sandbox_defconfig                    |   1 +
 drivers/firmware/scmi/Makefile               |   1 +
 drivers/firmware/scmi/pwdom.c                | 189 +++++++++++++
 drivers/firmware/scmi/sandbox-scmi_agent.c   | 265 ++++++++++++++++++-
 drivers/firmware/scmi/sandbox-scmi_devices.c |  10 +
 drivers/firmware/scmi/scmi_agent-uclass.c    |  11 +
 drivers/power/domain/Kconfig                 |   7 +
 drivers/power/domain/Makefile                |   1 +
 drivers/power/domain/scmi-power-domain.c     | 197 ++++++++++++++
 include/scmi_agent-uclass.h                  |   2 +
 include/scmi_protocols.h                     | 178 +++++++++++++
 test/dm/scmi.c                               | 107 +++++++-
 14 files changed, 993 insertions(+), 2 deletions(-)
 create mode 100644 drivers/firmware/scmi/pwdom.c
 create mode 100644 drivers/power/domain/scmi-power-domain.c

-- 
2.34.1


^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH 1/4] firmware: scmi: add power domain protocol support
  2023-09-26  7:00 [PATCH 0/4] firmware: scmi: add SCMI power domain protocol support AKASHI Takahiro
@ 2023-09-26  7:00 ` AKASHI Takahiro
  2023-09-26  7:00 ` [PATCH 2/4] power: domain: add SCMI driver AKASHI Takahiro
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 10+ messages in thread
From: AKASHI Takahiro @ 2023-09-26  7:00 UTC (permalink / raw)
  To: trini, sjg; +Cc: etienne.carriere, u-boot, AKASHI Takahiro

In this patch, added are helper functions to directly manipulate
SCMI power domain management protocol. DM compliant power domain
driver will be implemented on top of those interfaces in a succeeding
patch.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 drivers/firmware/scmi/Makefile |   1 +
 drivers/firmware/scmi/pwdom.c  | 189 +++++++++++++++++++++++++++++++++
 include/scmi_protocols.h       | 178 +++++++++++++++++++++++++++++++
 3 files changed, 368 insertions(+)
 create mode 100644 drivers/firmware/scmi/pwdom.c

diff --git a/drivers/firmware/scmi/Makefile b/drivers/firmware/scmi/Makefile
index 1a23d4981709..dae42863589a 100644
--- a/drivers/firmware/scmi/Makefile
+++ b/drivers/firmware/scmi/Makefile
@@ -4,4 +4,5 @@ obj-y	+= smt.o
 obj-$(CONFIG_SCMI_AGENT_SMCCC)		+= smccc_agent.o
 obj-$(CONFIG_SCMI_AGENT_MAILBOX)	+= mailbox_agent.o
 obj-$(CONFIG_SCMI_AGENT_OPTEE)	+= optee_agent.o
+obj-$(CONFIG_SCMI_POWER_DOMAIN)		+= pwdom.o
 obj-$(CONFIG_SANDBOX)		+= sandbox-scmi_agent.o sandbox-scmi_devices.o
diff --git a/drivers/firmware/scmi/pwdom.c b/drivers/firmware/scmi/pwdom.c
new file mode 100644
index 000000000000..61b4338663de
--- /dev/null
+++ b/drivers/firmware/scmi/pwdom.c
@@ -0,0 +1,189 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * SCMI Power domain management protocol
+ *
+ * Copyright (C) 2023 Linaro Limited
+ *		author: AKASHI Takahiro <takahiro.akashi@linaro.org>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <malloc.h>
+#include <scmi_agent.h>
+#include <scmi_protocols.h>
+#include <string.h>
+#include <asm/types.h>
+
+int scmi_pwd_protocol_attrs(struct udevice *dev, int *num_pwdoms,
+			    u64 *stats_addr, size_t *stats_len)
+{
+	struct scmi_pwd_protocol_attrs_out out;
+	struct scmi_msg msg = {
+		.protocol_id = SCMI_PROTOCOL_ID_POWER_DOMAIN,
+		.message_id = SCMI_PROTOCOL_ATTRIBUTES,
+		.out_msg = (u8 *)&out,
+		.out_msg_sz = sizeof(out),
+	};
+	int ret;
+
+	if (!dev || !num_pwdoms || !stats_addr || !stats_len)
+		return -EINVAL;
+
+	ret = devm_scmi_process_msg(dev, &msg);
+	if (ret)
+		return ret;
+	if (out.status)
+		return scmi_to_linux_errno(out.status);
+
+	*num_pwdoms = SCMI_PWD_PROTO_ATTRS_NUM_PWD(out.attributes);
+	*stats_addr = ((u64)out.stats_addr_high << 32) + out.stats_addr_low;
+	*stats_len = out.stats_len;
+
+	return 0;
+}
+
+int scmi_pwd_protocol_message_attrs(struct udevice *dev, s32 message_id,
+				    u32 *attributes)
+{
+	struct scmi_pwd_protocol_msg_attrs_out out;
+	struct scmi_msg msg = {
+		.protocol_id = SCMI_PROTOCOL_ID_POWER_DOMAIN,
+		.message_id = SCMI_PROTOCOL_MESSAGE_ATTRIBUTES,
+		.in_msg = (u8 *)&message_id,
+		.in_msg_sz = sizeof(message_id),
+		.out_msg = (u8 *)&out,
+		.out_msg_sz = sizeof(out),
+	};
+	int ret;
+
+	if (!dev || !attributes)
+		return -EINVAL;
+
+	ret = devm_scmi_process_msg(dev, &msg);
+	if (ret)
+		return ret;
+	if (out.status)
+		return scmi_to_linux_errno(out.status);
+
+	*attributes = out.attributes;
+
+	return 0;
+}
+
+int scmi_pwd_attrs(struct udevice *dev, u32 domain_id, u32 *attributes,
+		   u8 **name)
+{
+	struct scmi_pwd_attrs_out out;
+	struct scmi_msg msg = {
+		.protocol_id = SCMI_PROTOCOL_ID_POWER_DOMAIN,
+		.message_id = SCMI_PWD_ATTRIBUTES,
+		.in_msg = (u8 *)&domain_id,
+		.in_msg_sz = sizeof(domain_id),
+		.out_msg = (u8 *)&out,
+		.out_msg_sz = sizeof(out),
+	};
+	int ret;
+
+	if (!dev || !attributes || !name)
+		return -EINVAL;
+
+	ret = devm_scmi_process_msg(dev, &msg);
+	if (ret)
+		return ret;
+	if (out.status)
+		return scmi_to_linux_errno(out.status);
+
+	*name = strdup(out.name);
+	if (!*name)
+		return -ENOMEM;
+
+	*attributes = out.attributes;
+
+	return 0;
+}
+
+int scmi_pwd_state_set(struct udevice *dev, u32 flags, u32 domain_id,
+		       u32 pstate)
+{
+	struct scmi_pwd_state_set_in in;
+	s32 status;
+	struct scmi_msg msg = {
+		.protocol_id = SCMI_PROTOCOL_ID_POWER_DOMAIN,
+		.message_id = SCMI_PWD_STATE_SET,
+		.in_msg = (u8 *)&in,
+		.in_msg_sz = sizeof(in),
+		.out_msg = (u8 *)&status,
+		.out_msg_sz = sizeof(status),
+	};
+	int ret;
+
+	if (!dev)
+		return -EINVAL;
+
+	in.flags = flags;
+	in.domain_id = domain_id;
+	in.pstate = pstate;
+	ret = devm_scmi_process_msg(dev, &msg);
+	if (ret)
+		return ret;
+	if (status)
+		return scmi_to_linux_errno(status);
+
+	return 0;
+}
+
+int scmi_pwd_state_get(struct udevice *dev, u32 domain_id, u32 *pstate)
+{
+	struct scmi_pwd_state_get_out out;
+	struct scmi_msg msg = {
+		.protocol_id = SCMI_PROTOCOL_ID_POWER_DOMAIN,
+		.message_id = SCMI_PWD_STATE_GET,
+		.in_msg = (u8 *)&domain_id,
+		.in_msg_sz = sizeof(domain_id),
+		.out_msg = (u8 *)&out,
+		.out_msg_sz = sizeof(out),
+	};
+	int ret;
+
+	if (!dev || !pstate)
+		return -EINVAL;
+
+	ret = devm_scmi_process_msg(dev, &msg);
+	if (ret)
+		return ret;
+	if (out.status)
+		return scmi_to_linux_errno(out.status);
+
+	*pstate = out.pstate;
+
+	return 0;
+}
+
+int scmi_pwd_name_get(struct udevice *dev, u32 domain_id, u8 **name)
+{
+	struct scmi_pwd_name_get_out out;
+	struct scmi_msg msg = {
+		.protocol_id = SCMI_PROTOCOL_ID_POWER_DOMAIN,
+		.message_id = SCMI_PWD_NAME_GET,
+		.in_msg = (u8 *)&domain_id,
+		.in_msg_sz = sizeof(domain_id),
+		.out_msg = (u8 *)&out,
+		.out_msg_sz = sizeof(out),
+	};
+	int ret;
+
+	if (!dev || !name)
+		return -EINVAL;
+
+	ret = devm_scmi_process_msg(dev, &msg);
+	if (ret)
+		return ret;
+	if (out.status)
+		return scmi_to_linux_errno(out.status);
+
+	*name = strdup(out.extended_name);
+	if (!*name)
+		return -ENOMEM;
+
+	return 0;
+}
diff --git a/include/scmi_protocols.h b/include/scmi_protocols.h
index ee551b38deb4..9e0ba26f8632 100644
--- a/include/scmi_protocols.h
+++ b/include/scmi_protocols.h
@@ -400,6 +400,184 @@ int scmi_base_reset_agent_configuration(struct udevice *dev, u32 agent_id,
 int scmi_generic_protocol_version(struct udevice *dev,
 				  enum scmi_std_protocol id, u32 *version);
 
+/*
+ * SCMI Power Domain Management Protocol
+ */
+
+#define SCMI_PWD_PROTOCOL_VERSION 0x30000
+#define SCMI_PWD_PSTATE_TYPE_LOST BIT(30)
+#define SCMI_PWD_PSTATE_ID GENMASK(27, 0)
+
+enum scmi_power_domain_message_id {
+	SCMI_PWD_ATTRIBUTES = 0x3,
+	SCMI_PWD_STATE_SET = 0x4,
+	SCMI_PWD_STATE_GET = 0x5,
+	SCMI_PWD_STATE_NOTIFY = 0x6,
+	SCMI_PWD_STATE_CHANGE_REQUESTED_NOTIFY = 0x7,
+	SCMI_PWD_NAME_GET = 0x8,
+};
+
+/**
+ * struct scmi_pwd_protocol_attrs_out
+ * @status:		SCMI command status
+ * @attributes:		Protocol attributes
+ * @stats_addr_low:	Lower 32 bits of address of statistics memory region
+ * @stats_addr_high:	Higher 32 bits of address of statistics memory region
+ * @stats_len:		Length of statistics memory region
+ */
+struct scmi_pwd_protocol_attrs_out {
+	s32 status;
+	u32 attributes;
+	u32 stats_addr_low;
+	u32 stats_addr_high;
+	u32 stats_len;
+};
+
+#define SCMI_PWD_PROTO_ATTRS_NUM_PWD(attributes) ((attributes) & GENMASK(15, 0))
+
+/**
+ * struct scmi_pwd_protocol_msg_attrs_out
+ * @status:		SCMI command status
+ * @attributes:		Message-specific attributes
+ */
+struct scmi_pwd_protocol_msg_attrs_out {
+	s32 status;
+	u32 attributes;
+};
+
+#define SCMI_PWD_NAME_LENGTH_MAX 16
+
+/**
+ * struct scmi_pwd_attrs_out
+ * @status:	SCMI command status
+ * @attributes:	Power domain attributes
+ * @name:	Name of power domain
+ */
+struct scmi_pwd_attrs_out {
+	s32 status;
+	u32 attributes;
+	u8 name[SCMI_PWD_NAME_LENGTH_MAX];
+};
+
+#define SCMI_PWD_ATTR_PSTATE_CHANGE_NOTIFY	BIT(31)
+#define SCMI_PWD_ATTR_PSTATE_ASYNC		BIT(30)
+#define SCMI_PWD_ATTR_PSTATE_SYNC		BIT(29)
+#define SCMI_PWD_ATTR_PSTATE_CHANGE_RQ_NOTIFY	BIT(28)
+#define SCMI_PWD_ATTR_EXTENDED_NAME		BIT(27)
+
+/**
+ * struct scmi_pwd_state_set_in
+ * @flags:	Flags
+ * @domain_id:	Identifier of power domain
+ * @pstate:	Power state of the domain
+ */
+struct scmi_pwd_state_set_in {
+	u32 flags;
+	u32 domain_id;
+	u32 pstate;
+};
+
+#define SCMI_PWD_SET_FLAGS_ASYNC BIT(0)
+
+/**
+ * struct scmi_pwd_state_get_out
+ * @status:	SCMI command status
+ * @pstate:	Power state of the domain
+ */
+struct scmi_pwd_state_get_out {
+	s32 status;
+	u32 pstate;
+};
+
+#define SCMI_PWD_EXTENDED_NAME_MAX 64
+/**
+ * struct scmi_pwd_name_get_out
+ * @status:		SCMI command status
+ * @flags:		Parameter flags
+ * @extended_name:	Extended name of power domain
+ */
+struct scmi_pwd_name_get_out {
+	s32 status;
+	u32 flags;
+	u8 extended_name[SCMI_PWD_EXTENDED_NAME_MAX];
+};
+
+/**
+ * scmi_pwd_protocol_attrs - get protocol attributes
+ * @dev:	SCMI protocol device
+ * @num_pwdoms:	Number of power domains
+ * @stats_addr:	Address of statistics memory region
+ * @stats_len:	Length of statistics memory region
+ *
+ * Obtain the protocol attributes, the number of power domains and
+ * the information of statistics memory region.
+ *
+ * Return: 0 on success, error code on failure
+ */
+int scmi_pwd_protocol_attrs(struct udevice *dev, int *num_pwdoms,
+			    u64 *stats_addr, size_t *stats_len);
+/**
+ * scmi_pwd_protocol_message_attrs - get message-specific attributes
+ * @dev:		SCMI protocol device
+ * @message_id:		SCMI message ID
+ * @attributes:		Message-specific attributes
+ *
+ * Obtain the message-specific attributes in @attributes.
+ *
+ * Return: 0 on success, error code on failure
+ */
+int scmi_pwd_protocol_message_attrs(struct udevice *dev, s32 message_id,
+				    u32 *attributes);
+/**
+ * scmi_pwd_attrs - get power domain attributes
+ * @dev:	SCMI protocol device
+ * @domain_id:	Identifier of power domain
+ * @attributes:	Power domain attributes
+ * @name:	Name of power domain
+ *
+ * Obtain the attributes of the given power domain, @domain_id, in @attributes
+ * as well as its name in @name.
+ *
+ * Return: 0 on success, error code on failure
+ */
+int scmi_pwd_attrs(struct udevice *dev, u32 message_id, u32 *attributes,
+		   u8 **name);
+/**
+ * scmi_pwd_state_set - set power state
+ * @dev:	SCMI protocol device
+ * @flags:	Parameter flags
+ * @domain_id:	Identifier of power domain
+ * @pstate:	Power state
+ *
+ * Change the power state of the given power domain, @domain_id.
+ *
+ * Return: 0 on success, error code on failure
+ */
+int scmi_pwd_state_set(struct udevice *dev, u32 flags, u32 domain_id,
+		       u32 pstate);
+/**
+ * scmi_pwd_state_get - get power state
+ * @dev:	SCMI protocol device
+ * @domain_id:	Identifier of power domain
+ * @pstate:	Power state
+ *
+ * Obtain the power state of the given power domain, @domain_id.
+ *
+ * Return: 0 on success, error code on failure
+ */
+int scmi_pwd_state_get(struct udevice *dev, u32 domain_id, u32 *pstate);
+/**
+ * scmi_pwd_name_get - get extended name
+ * @dev:	SCMI protocol device
+ * @domain_id:	Identifier of power domain
+ * @name:	Extended name of the domain
+ *
+ * Obtain the extended name of the given power domain, @domain_id, in @name.
+ *
+ * Return: 0 on success, error code on failure
+ */
+int scmi_pwd_name_get(struct udevice *dev, u32 domain_id, u8 **name);
+
 /*
  * SCMI Clock Protocol
  */
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 2/4] power: domain: add SCMI driver
  2023-09-26  7:00 [PATCH 0/4] firmware: scmi: add SCMI power domain protocol support AKASHI Takahiro
  2023-09-26  7:00 ` [PATCH 1/4] firmware: scmi: add " AKASHI Takahiro
@ 2023-09-26  7:00 ` AKASHI Takahiro
  2023-09-26  7:00 ` [PATCH 3/4] sandbox: add SCMI power domain protocol support for testing AKASHI Takahiro
  2023-09-26  7:00 ` [PATCH 4/4] test: dm: add SCMI power domain protocol test AKASHI Takahiro
  3 siblings, 0 replies; 10+ messages in thread
From: AKASHI Takahiro @ 2023-09-26  7:00 UTC (permalink / raw)
  To: trini, sjg; +Cc: etienne.carriere, u-boot, AKASHI Takahiro

Add power domain driver based on SCMI power domain management protocol.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 drivers/firmware/scmi/scmi_agent-uclass.c |  11 ++
 drivers/power/domain/Kconfig              |   7 +
 drivers/power/domain/Makefile             |   1 +
 drivers/power/domain/scmi-power-domain.c  | 197 ++++++++++++++++++++++
 include/scmi_agent-uclass.h               |   2 +
 5 files changed, 218 insertions(+)
 create mode 100644 drivers/power/domain/scmi-power-domain.c

diff --git a/drivers/firmware/scmi/scmi_agent-uclass.c b/drivers/firmware/scmi/scmi_agent-uclass.c
index 6f585b96f740..0f1003e167e6 100644
--- a/drivers/firmware/scmi/scmi_agent-uclass.c
+++ b/drivers/firmware/scmi/scmi_agent-uclass.c
@@ -86,6 +86,9 @@ struct udevice *scmi_get_protocol(struct udevice *dev,
 	case SCMI_PROTOCOL_ID_BASE:
 		proto = priv->base_dev;
 		break;
+	case SCMI_PROTOCOL_ID_POWER_DOMAIN:
+		proto = priv->pwdom_dev;
+		break;
 	case SCMI_PROTOCOL_ID_CLOCK:
 		proto = priv->clock_dev;
 		break;
@@ -133,6 +136,9 @@ static int scmi_add_protocol(struct udevice *dev,
 	case SCMI_PROTOCOL_ID_BASE:
 		priv->base_dev = proto;
 		break;
+	case SCMI_PROTOCOL_ID_POWER_DOMAIN:
+		priv->pwdom_dev = proto;
+		break;
 	case SCMI_PROTOCOL_ID_CLOCK:
 		priv->clock_dev = proto;
 		break;
@@ -405,6 +411,11 @@ static int scmi_bind_protocols(struct udevice *dev)
 		drv = NULL;
 		name = ofnode_get_name(node);
 		switch (protocol_id) {
+		case SCMI_PROTOCOL_ID_POWER_DOMAIN:
+			if (CONFIG_IS_ENABLED(SCMI_POWER_DOMAIN) &&
+			    scmi_protocol_is_supported(dev, protocol_id))
+				drv = DM_DRIVER_GET(scmi_power_domain);
+			break;
 		case SCMI_PROTOCOL_ID_CLOCK:
 			if (CONFIG_IS_ENABLED(CLK_SCMI) &&
 			    scmi_protocol_is_supported(dev, protocol_id))
diff --git a/drivers/power/domain/Kconfig b/drivers/power/domain/Kconfig
index 411c210756a3..bd82d2f7044b 100644
--- a/drivers/power/domain/Kconfig
+++ b/drivers/power/domain/Kconfig
@@ -83,6 +83,13 @@ config SANDBOX_POWER_DOMAIN
 	  simply accepts requests to power on/off various HW modules without
 	  actually doing anything beyond a little error checking.
 
+config SCMI_POWER_DOMAIN
+	bool "Enable SCMI power domain driver"
+	depends on POWER_DOMAIN && SCMI_FIRMWARE
+	help
+	  Enable power domain implementation based on SCMI power domain
+	  management protocol.
+
 config TEGRA186_POWER_DOMAIN
 	bool "Enable Tegra186 BPMP-based power domain driver"
 	depends on TEGRA186_BPMP
diff --git a/drivers/power/domain/Makefile b/drivers/power/domain/Makefile
index aa5a4ba57cd8..2daab73eb758 100644
--- a/drivers/power/domain/Makefile
+++ b/drivers/power/domain/Makefile
@@ -15,6 +15,7 @@ obj-$(CONFIG_MESON_EE_POWER_DOMAIN) += meson-ee-pwrc.o
 obj-$(CONFIG_MESON_SECURE_POWER_DOMAIN) += meson-secure-pwrc.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
 obj-$(CONFIG_TEGRA186_POWER_DOMAIN) += tegra186-power-domain.o
 obj-$(CONFIG_TI_SCI_POWER_DOMAIN) += ti-sci-power-domain.o
 obj-$(CONFIG_TI_POWER_DOMAIN) += ti-power-domain.o
diff --git a/drivers/power/domain/scmi-power-domain.c b/drivers/power/domain/scmi-power-domain.c
new file mode 100644
index 000000000000..5ea9ff889231
--- /dev/null
+++ b/drivers/power/domain/scmi-power-domain.c
@@ -0,0 +1,197 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * SCMI Power domain driver
+ *
+ * Copyright (C) 2023 Linaro Limited
+ *              author: AKASHI Takahiro <takahiro.akashi@linaro.org>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <malloc.h>
+#include <power-domain.h>
+#include <power-domain-uclass.h>
+#include <scmi_agent.h>
+#include <scmi_protocols.h>
+#include <dm/device_compat.h>
+
+/**
+ * struct scmi_pwd_properties
+ * @attributes:	Power domain attributes
+ * @name:	Name of the domain
+ */
+struct scmi_pwd_properties {
+	u32 attributes;
+	u8 *name; /* not used now */
+};
+
+/**
+ * struct scmi_power_domain_priv
+ * @num_pwdoms:	Number of power domains
+ * @prop:	Pointer to domain's properties
+ * @stats_addr:	Address of statistics memory region
+ * @stats_len:	Length of statistics memory region
+ */
+struct scmi_power_domain_priv {
+	int num_pwdoms;
+	struct scmi_pwd_properties *prop;
+	u64 stats_addr;
+	size_t stats_len;
+};
+
+/**
+ * async_is_supported - check asynchronous transition
+ * @attributes:	Power domain attributes
+ *
+ * Determine if the power transition can be done asynchronously.
+ *
+ * Return: true if supported, false if not
+ */
+static bool async_is_supported(u32 attributes)
+{
+	if (attributes & SCMI_PWD_ATTR_PSTATE_ASYNC)
+		return true;
+
+	/* TODO: check attributes && SCMI_PWD_ATTR_PSTATE_SYNC */
+	return false;
+}
+
+/**
+ * scmi_power_domain_on - Enable the power domain
+ * @power_domain:	Power domain
+ *
+ * Turn on the power domain.
+ *
+ * Return: 0 on success, error code on failure
+ */
+static int scmi_power_domain_on(struct power_domain *power_domain)
+{
+	struct scmi_power_domain_priv *priv = dev_get_priv(power_domain->dev);
+	u32 flags, pstate;
+	int ret;
+
+	if (power_domain->id > priv->num_pwdoms)
+		return -EINVAL;
+
+	if (async_is_supported(priv->prop[power_domain->id].attributes))
+		flags = SCMI_PWD_SET_FLAGS_ASYNC;
+	else
+		flags = 0;
+
+	/* ON */
+	pstate = 0;
+
+	ret = scmi_pwd_state_set(power_domain->dev, flags, power_domain->id,
+				 pstate);
+	if (ret) {
+		dev_err(power_domain->dev, "failed to set the state on (%d)\n",
+			ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+/**
+ * scmi_power_domain_off - Disable the power domain
+ * @power_domain:	Power domain
+ *
+ * Turn off the power domain.
+ *
+ * Return: 0 on success, error code on failure
+ */
+static int scmi_power_domain_off(struct power_domain *power_domain)
+{
+	struct scmi_power_domain_priv *priv = dev_get_priv(power_domain->dev);
+	u32 flags, pstate;
+	int ret;
+
+	if (power_domain->id > priv->num_pwdoms)
+		return -EINVAL;
+
+	if (async_is_supported(priv->prop[power_domain->id].attributes))
+		flags = SCMI_PWD_SET_FLAGS_ASYNC;
+	else
+		flags = 0;
+
+	/* OFF */
+	pstate = SCMI_PWD_PSTATE_TYPE_LOST;
+
+	ret = scmi_pwd_state_set(power_domain->dev, flags, power_domain->id,
+				 pstate);
+	if (ret) {
+		dev_err(power_domain->dev, "failed to set the state off (%d)\n",
+			ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+/**
+ * scmi_power_domain_probe - Probe the power domain
+ * @dev:	Power domain device
+ *
+ * Probe the power domain and initialize the properties.
+ *
+ * Return: 0 on success, error code on failure
+ */
+static int scmi_power_domain_probe(struct udevice *dev)
+{
+	struct scmi_power_domain_priv *priv = dev_get_priv(dev);
+	u32 version;
+	int i, ret;
+
+	ret = devm_scmi_of_get_channel(dev);
+	if (ret) {
+		dev_err(dev, "failed to get channel (%d)\n", ret);
+		return ret;
+	}
+
+	ret = scmi_generic_protocol_version(dev, SCMI_PROTOCOL_ID_POWER_DOMAIN,
+					    &version);
+#if 0 /* TODO */
+	if (ret || version < SCMI_POWER_DOMAIN_PROTOCOL_VERSION) {
+		dev_err(dev, "protocol version doesn't match (%d)\n", version);
+		return -EINVAL;
+	}
+#endif
+
+	ret = scmi_pwd_protocol_attrs(dev, &priv->num_pwdoms, &priv->stats_addr,
+				      &priv->stats_len);
+	if (ret) {
+		dev_err(dev, "failed to get protocol attributes (%d)\n", ret);
+		return ret;
+	}
+
+	priv->prop = calloc(sizeof(*priv->prop), priv->num_pwdoms);
+	if (!priv->prop)
+		return -ENOMEM;
+
+	for (i = 0; i < priv->num_pwdoms; i++) {
+		ret = scmi_pwd_attrs(dev, i, &priv->prop[i].attributes,
+				     &priv->prop[i].name);
+		if (ret) {
+			dev_err(dev, "failed to get attributes pwd:%d (%d)\n",
+				i, ret);
+			/* TODO: clean up */
+
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+struct power_domain_ops scmi_power_domain_ops = {
+	.on = scmi_power_domain_on,
+	.off = scmi_power_domain_off,
+};
+
+U_BOOT_DRIVER(scmi_power_domain) = {
+	.name = "scmi_power_domain",
+	.id = UCLASS_POWER_DOMAIN,
+	.ops = &scmi_power_domain_ops,
+	.probe = scmi_power_domain_probe,
+	.priv_auto = sizeof(struct scmi_power_domain_priv),
+};
diff --git a/include/scmi_agent-uclass.h b/include/scmi_agent-uclass.h
index 35d96069645e..33e0e18c30d4 100644
--- a/include/scmi_agent-uclass.h
+++ b/include/scmi_agent-uclass.h
@@ -23,6 +23,7 @@ struct scmi_channel;
  * @agent_name:		Agent name
  * @agent_id:		Identifier of agent
  * @base_dev:		SCMI base protocol device
+ * @pwdom_dev:		SCMI power domain management protocol device
  * @clock_dev:		SCMI clock protocol device
  * @resetdom_dev:	SCMI reset domain protocol device
  * @voltagedom_dev:	SCMI voltage domain protocol device
@@ -38,6 +39,7 @@ struct scmi_agent_priv {
 	u8 *agent_name;
 	u32 agent_id;
 	struct udevice *base_dev;
+	struct udevice *pwdom_dev;
 	struct udevice *clock_dev;
 	struct udevice *resetdom_dev;
 	struct udevice *voltagedom_dev;
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 3/4] sandbox: add SCMI power domain protocol support for testing
  2023-09-26  7:00 [PATCH 0/4] firmware: scmi: add SCMI power domain protocol support AKASHI Takahiro
  2023-09-26  7:00 ` [PATCH 1/4] firmware: scmi: add " AKASHI Takahiro
  2023-09-26  7:00 ` [PATCH 2/4] power: domain: add SCMI driver AKASHI Takahiro
@ 2023-09-26  7:00 ` AKASHI Takahiro
  2023-10-02  1:17   ` Simon Glass
  2023-09-26  7:00 ` [PATCH 4/4] test: dm: add SCMI power domain protocol test AKASHI Takahiro
  3 siblings, 1 reply; 10+ messages in thread
From: AKASHI Takahiro @ 2023-09-26  7:00 UTC (permalink / raw)
  To: trini, sjg; +Cc: etienne.carriere, u-boot, AKASHI Takahiro

SCMI power domain management protocol is supported on sandbox
for test purpose. Add fake agent interfaces and associated
power domain devices.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 arch/sandbox/dts/test.dts                    |   6 +
 arch/sandbox/include/asm/scmi_test.h         |  20 ++
 configs/sandbox_defconfig                    |   1 +
 drivers/firmware/scmi/sandbox-scmi_agent.c   | 265 ++++++++++++++++++-
 drivers/firmware/scmi/sandbox-scmi_devices.c |  10 +
 5 files changed, 301 insertions(+), 1 deletion(-)

diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index 36de6a37cf6d..38fcf42cd23d 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -693,6 +693,11 @@
 			#address-cells = <1>;
 			#size-cells = <0>;
 
+			pwrdom_scmi: protocol@11 {
+				reg = <0x11>;
+				#power-domain-cells = <1>;
+			};
+
 			clk_scmi: protocol@14 {
 				reg = <0x14>;
 				#clock-cells = <1>;
@@ -1589,6 +1594,7 @@
 
 	sandbox_scmi {
 		compatible = "sandbox,scmi-devices";
+		power-domains = <&pwrdom_scmi 2>;
 		clocks = <&clk_scmi 2>, <&clk_scmi 0>;
 		resets = <&reset_scmi 3>;
 		regul0-supply = <&regul0_scmi>;
diff --git a/arch/sandbox/include/asm/scmi_test.h b/arch/sandbox/include/asm/scmi_test.h
index ccb0df6c148f..1b0f4464b98f 100644
--- a/arch/sandbox/include/asm/scmi_test.h
+++ b/arch/sandbox/include/asm/scmi_test.h
@@ -6,10 +6,21 @@
 #ifndef __SANDBOX_SCMI_TEST_H
 #define __SANDBOX_SCMI_TEST_H
 
+#include <power-domain.h>
+
 struct udevice;
 struct sandbox_scmi_agent;
 struct sandbox_scmi_service;
 
+/**
+ * struct sandbox_scmi_pwd
+ * @id:		Identifier of the power domain used in the SCMI protocol
+ */
+struct sandbox_scmi_pwd {
+	uint id;
+	u32 pstate;
+};
+
 /**
  * struct sandbox_scmi_clk - Simulated clock exposed by SCMI
  * @id:		Identifier of the clock used in the SCMI protocol
@@ -45,6 +56,8 @@ struct sandbox_scmi_voltd {
 
 /**
  * struct sandbox_scmi_agent - Simulated SCMI service seen by SCMI agent
+ * @pwdom_version: Implemented power domain protocol version
+ * @pwdom_count:   Simulated power domains array size
  * @clk:	Simulated clocks
  * @clk_count:	Simulated clocks array size
  * @reset:	Simulated reset domains
@@ -53,6 +66,9 @@ struct sandbox_scmi_voltd {
  * @voltd_count: Simulated voltage domains array size
  */
 struct sandbox_scmi_agent {
+	int pwdom_version;
+	struct sandbox_scmi_pwd *pwdom;
+	size_t pwdom_count;
 	struct sandbox_scmi_clk *clk;
 	size_t clk_count;
 	struct sandbox_scmi_reset *reset;
@@ -71,6 +87,8 @@ struct sandbox_scmi_service {
 
 /**
  * struct sandbox_scmi_devices - Reference to devices probed through SCMI
+ * @pwdom:		Array of power domains
+ * @pwdom_count:	Number of power domains probed
  * @clk:		Array the clock devices
  * @clk_count:		Number of clock devices probed
  * @reset:		Array the reset controller devices
@@ -79,6 +97,8 @@ struct sandbox_scmi_service {
  * @regul_count:	Number of regulator devices probed
  */
 struct sandbox_scmi_devices {
+	struct power_domain *pwdom;
+	size_t pwdom_count;
 	struct clk *clk;
 	size_t clk_count;
 	struct reset_ctl *reset;
diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
index 3906476bb4fc..b0a72e63f7da 100644
--- a/configs/sandbox_defconfig
+++ b/configs/sandbox_defconfig
@@ -241,6 +241,7 @@ CONFIG_PINCTRL_SANDBOX=y
 CONFIG_PINCTRL_SINGLE=y
 CONFIG_POWER_DOMAIN=y
 CONFIG_SANDBOX_POWER_DOMAIN=y
+CONFIG_SCMI_POWER_DOMAIN=y
 CONFIG_DM_PMIC=y
 CONFIG_PMIC_ACT8846=y
 CONFIG_DM_PMIC_PFUZE100=y
diff --git a/drivers/firmware/scmi/sandbox-scmi_agent.c b/drivers/firmware/scmi/sandbox-scmi_agent.c
index eb567dd900d7..9f5f497e0a6c 100644
--- a/drivers/firmware/scmi/sandbox-scmi_agent.c
+++ b/drivers/firmware/scmi/sandbox-scmi_agent.c
@@ -43,6 +43,8 @@
 #define SANDBOX_SCMI_AGENT_NAME "OSPM"
 #define SANDBOX_SCMI_PLATFORM_NAME "platform"
 
+#define SANDBOX_SCMI_PWD_PROTOCOL_VERSION SCMI_PWD_PROTOCOL_VERSION
+
 /**
  * struct sandbox_channel - Description of sandbox transport
  * @channel_id:		Channel identifier
@@ -64,6 +66,7 @@ struct scmi_channel {
 };
 
 static u8 protocols[] = {
+	SCMI_PROTOCOL_ID_POWER_DOMAIN,
 	SCMI_PROTOCOL_ID_CLOCK,
 	SCMI_PROTOCOL_ID_RESET_DOMAIN,
 	SCMI_PROTOCOL_ID_VOLTAGE_DOMAIN,
@@ -71,6 +74,12 @@ static u8 protocols[] = {
 
 #define NUM_PROTOCOLS ARRAY_SIZE(protocols)
 
+static struct sandbox_scmi_pwd scmi_pwdom[] = {
+	{ .id = 0 },
+	{ .id = 1 },
+	{ .id = 2 },
+};
+
 static struct sandbox_scmi_clk scmi_clk[] = {
 	{ .rate = 333 },
 	{ .rate = 200 },
@@ -458,6 +467,238 @@ static int sandbox_scmi_base_reset_agent_configuration(struct udevice *dev,
 	return 0;
 }
 
+/* Power Domain Management Protocol */
+
+/**
+ * sandbox_scmi_pwd_protocol_version - implement SCMI_PROTOCOL_VERSION
+ * @dev:	SCMI device
+ * @msg:	SCMI message
+ *
+ * Implement SCMI_PROTOCOL_VERSION command.
+ *
+ * Return:	0 on success, error code on failure
+ */
+static int sandbox_scmi_pwd_protocol_version(struct udevice *dev,
+					     struct scmi_msg *msg)
+{
+	struct scmi_protocol_version_out *out = NULL;
+
+	if (!msg->out_msg || msg->out_msg_sz < sizeof(*out))
+		return -EINVAL;
+
+	out = (struct scmi_protocol_version_out *)msg->out_msg;
+	out->version = SANDBOX_SCMI_PWD_PROTOCOL_VERSION;
+	out->status = SCMI_SUCCESS;
+
+	return 0;
+}
+
+/**
+ * sandbox_scmi_pwd_protocol_attribs - implement SCMI_PWD_PROTOCOL_ATTRS
+ * @dev:	SCMI device
+ * @msg:	SCMI message
+ *
+ * Implement SCMI_PWD_PROTOCOL_ATTRS command.
+ *
+ * Return:	0 on success, error code on failure
+ */
+static int sandbox_scmi_pwd_protocol_attribs(struct udevice *dev,
+					     struct scmi_msg *msg)
+{
+	struct scmi_pwd_protocol_attrs_out *out;
+
+	if (!msg->out_msg || msg->out_msg_sz < sizeof(*out))
+		return -EINVAL;
+
+	out = (struct scmi_pwd_protocol_attrs_out *)msg->out_msg;
+
+	out->attributes = ARRAY_SIZE(scmi_pwdom);
+	out->stats_addr_low = 0;
+	out->stats_addr_high = 0;
+	out->stats_len = 0;
+	out->status = SCMI_SUCCESS;
+
+	return 0;
+}
+
+/**
+ * sandbox_scmi_pwd_protocol_msg_attribs - implement
+					SCMI_PWD_PROTOCOL_MESSAGE_ATTRS
+ * @dev:	SCMI device
+ * @msg:	SCMI message
+ *
+ * Implement SCMI_PWD_PROTOCOL_MESSAGE_ATTRS command.
+ *
+ * Return:	0 on success, error code on failure
+ */
+static int sandbox_scmi_pwd_protocol_msg_attribs(struct udevice *dev,
+						 struct scmi_msg *msg)
+{
+	u32 message_id;
+	struct scmi_pwd_protocol_msg_attrs_out *out;
+
+	if (!msg->in_msg || msg->in_msg_sz < sizeof(message_id) ||
+	    !msg->out_msg || msg->out_msg_sz < sizeof(*out))
+		return -EINVAL;
+
+	message_id = *(u32 *)msg->in_msg;
+
+	out = (struct scmi_pwd_protocol_msg_attrs_out *)msg->out_msg;
+	if (message_id <= SCMI_PWD_STATE_GET ||
+	    message_id == SCMI_PWD_NAME_GET) {
+		out->attributes = 0;
+		out->status = SCMI_SUCCESS;
+	} else {
+		out->status = SCMI_NOT_FOUND;
+	}
+
+	return 0;
+}
+
+/**
+ * sandbox_scmi_pwd_attribs - implement SCMI_PWD_ATTRS
+ * @dev:	SCMI device
+ * @msg:	SCMI message
+ *
+ * Implement SCMI_PWD_ATTRS command.
+ *
+ * Return:	0 on success, error code on failure
+ */
+static int sandbox_scmi_pwd_attribs(struct udevice *dev, struct scmi_msg *msg)
+{
+	u32 domain_id;
+	struct scmi_pwd_attrs_out *out;
+
+	if (!msg->in_msg || msg->in_msg_sz < sizeof(domain_id) ||
+	    !msg->out_msg || msg->out_msg_sz < sizeof(*out))
+		return -EINVAL;
+
+	domain_id = *(u32 *)msg->in_msg;
+	out = (struct scmi_pwd_attrs_out *)msg->out_msg;
+
+	if (domain_id > ARRAY_SIZE(scmi_pwdom)) {
+		out->status = SCMI_NOT_FOUND;
+
+		return 0;
+	}
+
+	out->attributes =
+		SCMI_PWD_ATTR_PSTATE_SYNC | SCMI_PWD_ATTR_EXTENDED_NAME;
+	/* just 15-char + NULL */
+	snprintf(out->name, SCMI_PWD_NAME_LENGTH_MAX, "power-domain--%d",
+		 domain_id);
+	out->status = SCMI_SUCCESS;
+
+	return 0;
+}
+
+/**
+ * sandbox_scmi_pwd_state_set - implement SCMI_PWD_STATE_SET
+ * @dev:	SCMI device
+ * @msg:	SCMI message
+ *
+ * Implement SCMI_PWD_STATE_SET command.
+ *
+ * Return:	0 on success, error code on failure
+ */
+static int sandbox_scmi_pwd_state_set(struct udevice *dev, struct scmi_msg *msg)
+{
+	struct scmi_pwd_state_set_in *in;
+	s32 *status;
+
+	if (!msg->in_msg || msg->in_msg_sz < sizeof(in) ||
+	    !msg->out_msg || msg->out_msg_sz < sizeof(*status))
+		return -EINVAL;
+
+	in = (struct scmi_pwd_state_set_in *)msg->in_msg;
+	status = (s32 *)msg->out_msg;
+
+	if (in->domain_id > ARRAY_SIZE(scmi_pwdom)) {
+		*status = SCMI_NOT_FOUND;
+
+		return 0;
+	}
+
+	if ((in->flags & SCMI_PWD_SET_FLAGS_ASYNC) ||
+	    (in->pstate != SCMI_PWD_PSTATE_TYPE_LOST && in->pstate)) {
+		*status = SCMI_INVALID_PARAMETERS;
+
+		return 0;
+	}
+
+	scmi_pwdom[in->domain_id].pstate = in->pstate;
+	*status = SCMI_SUCCESS;
+
+	return 0;
+}
+
+/**
+ * sandbox_scmi_pwd_state_get - implement SCMI_PWD_STATE_GET
+ * @dev:	SCMI device
+ * @msg:	SCMI message
+ *
+ * Implement SCMI_PWD_STATE_GET command.
+ *
+ * Return:	0 on success, error code on failure
+ */
+static int sandbox_scmi_pwd_state_get(struct udevice *dev, struct scmi_msg *msg)
+{
+	u32 domain_id;
+	struct scmi_pwd_state_get_out *out;
+
+	if (!msg->in_msg || msg->in_msg_sz < sizeof(domain_id) ||
+	    !msg->out_msg || msg->out_msg_sz < sizeof(*out))
+		return -EINVAL;
+
+	domain_id = *(u32 *)msg->in_msg;
+	out = (struct scmi_pwd_state_get_out *)msg->out_msg;
+
+	if (domain_id > ARRAY_SIZE(scmi_pwdom)) {
+		out->status = SCMI_NOT_FOUND;
+
+		return 0;
+	}
+
+	out->pstate = scmi_pwdom[domain_id].pstate;
+	out->status = SCMI_SUCCESS;
+
+	return 0;
+}
+
+/**
+ * sandbox_scmi_pwd_name_get - implement SCMI_PWD_NAME_GET
+ * @dev:	SCMI device
+ * @msg:	SCMI message
+ *
+ * Implement SCMI_PWD_NAME_GET command.
+ *
+ * Return:	0 on success, error code on failure
+ */
+static int sandbox_scmi_pwd_name_get(struct udevice *dev, struct scmi_msg *msg)
+{
+	u32 domain_id;
+	struct scmi_pwd_name_get_out *out;
+
+	if (!msg->in_msg || msg->in_msg_sz < sizeof(domain_id) ||
+	    !msg->out_msg || msg->out_msg_sz < sizeof(*out))
+		return -EINVAL;
+
+	domain_id = *(u32 *)msg->in_msg;
+	out = (struct scmi_pwd_name_get_out *)msg->out_msg;
+
+	if (domain_id > ARRAY_SIZE(scmi_pwdom)) {
+		out->status = SCMI_NOT_FOUND;
+
+		return 0;
+	}
+
+	snprintf(out->extended_name, SCMI_PWD_EXTENDED_NAME_MAX,
+		 "power-domain--%d-extended", domain_id);
+	out->status = SCMI_SUCCESS;
+
+	return 0;
+}
+
 /* Clock Protocol */
 
 static int sandbox_scmi_clock_protocol_attribs(struct udevice *dev,
@@ -918,6 +1159,26 @@ static int sandbox_scmi_test_process_msg(struct udevice *dev,
 			break;
 		}
 		break;
+	case SCMI_PROTOCOL_ID_POWER_DOMAIN:
+		switch (msg->message_id) {
+		case SCMI_PROTOCOL_VERSION:
+			return sandbox_scmi_pwd_protocol_version(dev, msg);
+		case SCMI_PROTOCOL_ATTRIBUTES:
+			return sandbox_scmi_pwd_protocol_attribs(dev, msg);
+		case SCMI_PROTOCOL_MESSAGE_ATTRIBUTES:
+			return sandbox_scmi_pwd_protocol_msg_attribs(dev, msg);
+		case SCMI_PWD_ATTRIBUTES:
+			return sandbox_scmi_pwd_attribs(dev, msg);
+		case SCMI_PWD_STATE_SET:
+			return sandbox_scmi_pwd_state_set(dev, msg);
+		case SCMI_PWD_STATE_GET:
+			return sandbox_scmi_pwd_state_get(dev, msg);
+		case SCMI_PWD_NAME_GET:
+			return sandbox_scmi_pwd_name_get(dev, msg);
+		default:
+			break;
+		}
+		break;
 	case SCMI_PROTOCOL_ID_CLOCK:
 		switch (msg->message_id) {
 		case SCMI_PROTOCOL_ATTRIBUTES:
@@ -960,7 +1221,6 @@ static int sandbox_scmi_test_process_msg(struct udevice *dev,
 			break;
 		}
 		break;
-	case SCMI_PROTOCOL_ID_POWER_DOMAIN:
 	case SCMI_PROTOCOL_ID_SYSTEM:
 	case SCMI_PROTOCOL_ID_PERF:
 	case SCMI_PROTOCOL_ID_SENSOR:
@@ -993,6 +1253,9 @@ static int sandbox_scmi_test_probe(struct udevice *dev)
 	struct sandbox_scmi_agent *agent = dev_get_priv(dev);
 
 	*agent = (struct sandbox_scmi_agent){
+		.pwdom_version = SANDBOX_SCMI_PWD_PROTOCOL_VERSION,
+		.pwdom = scmi_pwdom,
+		.pwdom_count = ARRAY_SIZE(scmi_pwdom),
 		.clk = scmi_clk,
 		.clk_count = ARRAY_SIZE(scmi_clk),
 		.reset = scmi_reset,
diff --git a/drivers/firmware/scmi/sandbox-scmi_devices.c b/drivers/firmware/scmi/sandbox-scmi_devices.c
index 9baeb469ec0a..facb5b06ffb5 100644
--- a/drivers/firmware/scmi/sandbox-scmi_devices.c
+++ b/drivers/firmware/scmi/sandbox-scmi_devices.c
@@ -29,12 +29,14 @@
 
 /*
  * struct sandbox_scmi_device_priv - Storage for device handles used by test
+ * @pwdom:		Power domain device
  * @clk:		Array of clock instances used by tests
  * @reset_clt:		Array of the reset controller instances used by tests
  * @regulators:		Array of regulator device references used by the tests
  * @devices:		Resources exposed by sandbox_scmi_devices_ctx()
  */
 struct sandbox_scmi_device_priv {
+	struct power_domain pwdom;
 	struct clk clk[SCMI_TEST_DEVICES_CLK_COUNT];
 	struct reset_ctl reset_ctl[SCMI_TEST_DEVICES_RD_COUNT];
 	struct udevice *regulators[SCMI_TEST_DEVICES_VOLTD_COUNT];
@@ -77,6 +79,8 @@ static int sandbox_scmi_devices_probe(struct udevice *dev)
 	size_t n;
 
 	priv->devices = (struct sandbox_scmi_devices){
+		.pwdom = &priv->pwdom,
+		.pwdom_count = 1,
 		.clk = priv->clk,
 		.clk_count = SCMI_TEST_DEVICES_CLK_COUNT,
 		.reset = priv->reset_ctl,
@@ -85,6 +89,12 @@ static int sandbox_scmi_devices_probe(struct udevice *dev)
 		.regul_count = SCMI_TEST_DEVICES_VOLTD_COUNT,
 	};
 
+	ret = power_domain_get_by_index(dev, priv->devices.pwdom, 0);
+	if (ret) {
+		dev_err(dev, "%s: Failed on power domain\n", __func__);
+		return ret;
+	}
+
 	for (n = 0; n < SCMI_TEST_DEVICES_CLK_COUNT; n++) {
 		ret = clk_get_by_index(dev, n, priv->devices.clk + n);
 		if (ret) {
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 4/4] test: dm: add SCMI power domain protocol test
  2023-09-26  7:00 [PATCH 0/4] firmware: scmi: add SCMI power domain protocol support AKASHI Takahiro
                   ` (2 preceding siblings ...)
  2023-09-26  7:00 ` [PATCH 3/4] sandbox: add SCMI power domain protocol support for testing AKASHI Takahiro
@ 2023-09-26  7:00 ` AKASHI Takahiro
  2023-10-02  1:17   ` Simon Glass
  2023-10-14  1:20   ` Tom Rini
  3 siblings, 2 replies; 10+ messages in thread
From: AKASHI Takahiro @ 2023-09-26  7:00 UTC (permalink / raw)
  To: trini, sjg; +Cc: etienne.carriere, u-boot, AKASHI Takahiro

This ut has tests for the SCMI power domain protocol as well as DM
interfaces for power domain devices.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 test/dm/scmi.c | 107 ++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 106 insertions(+), 1 deletion(-)

diff --git a/test/dm/scmi.c b/test/dm/scmi.c
index 949e49bd2c35..c2625373d84e 100644
--- a/test/dm/scmi.c
+++ b/test/dm/scmi.c
@@ -15,6 +15,7 @@
 #include <common.h>
 #include <clk.h>
 #include <dm.h>
+#include <malloc.h>
 #include <reset.h>
 #include <scmi_agent.h>
 #include <scmi_agent-uclass.h>
@@ -223,7 +224,8 @@ static int dm_test_scmi_cmd(struct unit_test_state *uts)
 	ut_assert_nextline("  # of agents: 2");
 	ut_assert_nextline("      0: platform");
 	ut_assert_nextline("    > 1: OSPM");
-	ut_assert_nextline("  # of protocols: 3");
+	ut_assert_nextline("  # of protocols: 4");
+	ut_assert_nextline("      Power domain management");
 	ut_assert_nextline("      Clock management");
 	ut_assert_nextline("      Reset domain management");
 	ut_assert_nextline("      Voltage domain management");
@@ -259,6 +261,109 @@ static int dm_test_scmi_cmd(struct unit_test_state *uts)
 
 DM_TEST(dm_test_scmi_cmd, UT_TESTF_SCAN_FDT);
 
+static int dm_test_scmi_power_domains(struct unit_test_state *uts)
+{
+	struct sandbox_scmi_agent *agent;
+	struct sandbox_scmi_devices *scmi_devices;
+	struct udevice *agent_dev, *pwd, *dev;
+	u32 version, count, attributes, pstate;
+	u64 stats_addr;
+	size_t stats_len;
+	u8 *name;
+	int ret;
+
+	/* preparation */
+	ut_assertok(load_sandbox_scmi_test_devices(uts, &agent, &dev));
+	ut_assertnonnull(agent);
+	scmi_devices = sandbox_scmi_devices_ctx(dev);
+	ut_assertnonnull(scmi_devices);
+	ut_asserteq(2, scmi_devices->pwdom->id); /* in test.dts */
+
+	ut_assertok(uclass_get_device_by_name(UCLASS_SCMI_AGENT, "scmi",
+					      &agent_dev));
+	ut_assertnonnull(agent_dev);
+	pwd = scmi_get_protocol(agent_dev, SCMI_PROTOCOL_ID_POWER_DOMAIN);
+	ut_assertnonnull(pwd);
+
+	/*
+	 * SCMI Power domain management protocol interfaces
+	 */
+	/* version */
+	ret = scmi_generic_protocol_version(pwd, SCMI_PROTOCOL_ID_POWER_DOMAIN,
+					    &version);
+	ut_assertok(ret);
+	ut_asserteq(agent->pwdom_version, version);
+
+	/* protocol attributes */
+	ret = scmi_pwd_protocol_attrs(pwd, &count, &stats_addr, &stats_len);
+	ut_assertok(ret);
+	ut_asserteq(agent->pwdom_count, count);
+	ut_asserteq(0, stats_len);
+
+	/* protocol message attributes */
+	ret = scmi_pwd_protocol_message_attrs(pwd, SCMI_PWD_STATE_SET,
+					      &attributes);
+	ut_assertok(ret);
+	ret = scmi_pwd_protocol_message_attrs(pwd, SCMI_PWD_STATE_NOTIFY,
+					      &attributes);
+	ut_asserteq(-ENOENT, ret); /* the protocol not supported */
+
+	/* power domain attributes */
+	ret = scmi_pwd_attrs(pwd, 0, &attributes, &name);
+	ut_assertok(ret);
+	ut_asserteq_str("power-domain--0", name);
+	free(name);
+
+	ret = scmi_pwd_attrs(pwd, 10, &attributes, &name);
+	ut_asserteq(-ENOENT, ret); /* domain-10 doesn't exist */
+
+	/* power domain state set/get */
+	ret = scmi_pwd_state_set(pwd, 0, 0, 0);
+	ut_assertok(ret);
+	ret = scmi_pwd_state_get(pwd, 0, &pstate);
+	ut_assertok(ret);
+	ut_asserteq(0, pstate); /* ON */
+
+	ret = scmi_pwd_state_set(pwd, 0, 0, SCMI_PWD_PSTATE_TYPE_LOST);
+	ut_assertok(ret);
+	ret = scmi_pwd_state_get(pwd, 0, &pstate);
+	ut_assertok(ret);
+	ut_asserteq(SCMI_PWD_PSTATE_TYPE_LOST, pstate); /* OFF */
+
+	ret = scmi_pwd_state_set(pwd, 0, 10, 0);
+	ut_asserteq(-ENOENT, ret);
+
+	/* power domain name get */
+	ret = scmi_pwd_name_get(pwd, 0, &name);
+	ut_assertok(ret);
+	ut_asserteq_str("power-domain--0-extended", name);
+	free(name);
+
+	ret = scmi_pwd_name_get(pwd, 10, &name);
+	ut_asserteq(-ENOENT, ret); /* domain-10 doesn't exist */
+
+	/*
+	 * U-Boot driver model interfaces
+	 */
+	/* power_domain_on */
+	ret = power_domain_on(scmi_devices->pwdom);
+	ut_assertok(ret);
+	ret = scmi_pwd_state_get(pwd, scmi_devices->pwdom->id, &pstate);
+	ut_assertok(ret);
+	ut_asserteq(0, pstate); /* ON */
+
+	/* power_domain_off */
+	ret = power_domain_off(scmi_devices->pwdom);
+	ut_assertok(ret);
+	ret = scmi_pwd_state_get(pwd, scmi_devices->pwdom->id, &pstate);
+	ut_assertok(ret);
+	ut_asserteq(SCMI_PWD_PSTATE_TYPE_LOST, pstate); /* OFF */
+
+	return release_sandbox_scmi_test_devices(uts, dev);
+}
+
+DM_TEST(dm_test_scmi_power_domains, UT_TESTF_SCAN_FDT);
+
 static int dm_test_scmi_clocks(struct unit_test_state *uts)
 {
 	struct sandbox_scmi_agent *agent;
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [PATCH 3/4] sandbox: add SCMI power domain protocol support for testing
  2023-09-26  7:00 ` [PATCH 3/4] sandbox: add SCMI power domain protocol support for testing AKASHI Takahiro
@ 2023-10-02  1:17   ` Simon Glass
  2023-10-03  0:22     ` AKASHI Takahiro
  0 siblings, 1 reply; 10+ messages in thread
From: Simon Glass @ 2023-10-02  1:17 UTC (permalink / raw)
  To: AKASHI Takahiro; +Cc: trini, etienne.carriere, u-boot

Hi AKASHI,

On Tue, 26 Sept 2023 at 01:01, AKASHI Takahiro
<takahiro.akashi@linaro.org> wrote:
>
> SCMI power domain management protocol is supported on sandbox
> for test purpose. Add fake agent interfaces and associated
> power domain devices.
>
> Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
> ---
>  arch/sandbox/dts/test.dts                    |   6 +
>  arch/sandbox/include/asm/scmi_test.h         |  20 ++
>  configs/sandbox_defconfig                    |   1 +
>  drivers/firmware/scmi/sandbox-scmi_agent.c   | 265 ++++++++++++++++++-
>  drivers/firmware/scmi/sandbox-scmi_devices.c |  10 +
>  5 files changed, 301 insertions(+), 1 deletion(-)

Reviewed-by: Simon Glass <sjg@chromium.org>

nit below

>
> diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
> index 36de6a37cf6d..38fcf42cd23d 100644
> --- a/arch/sandbox/dts/test.dts
> +++ b/arch/sandbox/dts/test.dts
> @@ -693,6 +693,11 @@
>                         #address-cells = <1>;
>                         #size-cells = <0>;
>
> +                       pwrdom_scmi: protocol@11 {
> +                               reg = <0x11>;
> +                               #power-domain-cells = <1>;
> +                       };
> +
>                         clk_scmi: protocol@14 {
>                                 reg = <0x14>;
>                                 #clock-cells = <1>;
> @@ -1589,6 +1594,7 @@
>
>         sandbox_scmi {
>                 compatible = "sandbox,scmi-devices";
> +               power-domains = <&pwrdom_scmi 2>;
>                 clocks = <&clk_scmi 2>, <&clk_scmi 0>;
>                 resets = <&reset_scmi 3>;
>                 regul0-supply = <&regul0_scmi>;
> diff --git a/arch/sandbox/include/asm/scmi_test.h b/arch/sandbox/include/asm/scmi_test.h
> index ccb0df6c148f..1b0f4464b98f 100644
> --- a/arch/sandbox/include/asm/scmi_test.h
> +++ b/arch/sandbox/include/asm/scmi_test.h
> @@ -6,10 +6,21 @@
>  #ifndef __SANDBOX_SCMI_TEST_H
>  #define __SANDBOX_SCMI_TEST_H
>
> +#include <power-domain.h>
> +
>  struct udevice;
>  struct sandbox_scmi_agent;
>  struct sandbox_scmi_service;
>
> +/**
> + * struct sandbox_scmi_pwd
> + * @id:                Identifier of the power domain used in the SCMI protocol

@pstate ?

> + */
> +struct sandbox_scmi_pwd {
> +       uint id;
> +       u32 pstate;
> +};
> +
>  /**
>   * struct sandbox_scmi_clk - Simulated clock exposed by SCMI
>   * @id:                Identifier of the clock used in the SCMI protocol
> @@ -45,6 +56,8 @@ struct sandbox_scmi_voltd {
>

[..]

Regards,
Simon

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 4/4] test: dm: add SCMI power domain protocol test
  2023-09-26  7:00 ` [PATCH 4/4] test: dm: add SCMI power domain protocol test AKASHI Takahiro
@ 2023-10-02  1:17   ` Simon Glass
  2023-10-14  1:20   ` Tom Rini
  1 sibling, 0 replies; 10+ messages in thread
From: Simon Glass @ 2023-10-02  1:17 UTC (permalink / raw)
  To: AKASHI Takahiro; +Cc: trini, etienne.carriere, u-boot

On Tue, 26 Sept 2023 at 01:01, AKASHI Takahiro
<takahiro.akashi@linaro.org> wrote:
>
> This ut has tests for the SCMI power domain protocol as well as DM
> interfaces for power domain devices.
>
> Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
> ---
>  test/dm/scmi.c | 107 ++++++++++++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 106 insertions(+), 1 deletion(-)
>

Reviewed-by: Simon Glass <sjg@chromium.org>

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 3/4] sandbox: add SCMI power domain protocol support for testing
  2023-10-02  1:17   ` Simon Glass
@ 2023-10-03  0:22     ` AKASHI Takahiro
  0 siblings, 0 replies; 10+ messages in thread
From: AKASHI Takahiro @ 2023-10-03  0:22 UTC (permalink / raw)
  To: Simon Glass; +Cc: trini, etienne.carriere, u-boot

Hi Simon,

Thank you for the review.

On Sun, Oct 01, 2023 at 07:17:17PM -0600, Simon Glass wrote:
> Hi AKASHI,
> 
> On Tue, 26 Sept 2023 at 01:01, AKASHI Takahiro
> <takahiro.akashi@linaro.org> wrote:
> >
> > SCMI power domain management protocol is supported on sandbox
> > for test purpose. Add fake agent interfaces and associated
> > power domain devices.
> >
> > Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
> > ---
> >  arch/sandbox/dts/test.dts                    |   6 +
> >  arch/sandbox/include/asm/scmi_test.h         |  20 ++
> >  configs/sandbox_defconfig                    |   1 +
> >  drivers/firmware/scmi/sandbox-scmi_agent.c   | 265 ++++++++++++++++++-
> >  drivers/firmware/scmi/sandbox-scmi_devices.c |  10 +
> >  5 files changed, 301 insertions(+), 1 deletion(-)
> 
> Reviewed-by: Simon Glass <sjg@chromium.org>
> 
> nit below
> 
> >
> > diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
> > index 36de6a37cf6d..38fcf42cd23d 100644
> > --- a/arch/sandbox/dts/test.dts
> > +++ b/arch/sandbox/dts/test.dts
> > @@ -693,6 +693,11 @@
> >                         #address-cells = <1>;
> >                         #size-cells = <0>;
> >
> > +                       pwrdom_scmi: protocol@11 {
> > +                               reg = <0x11>;
> > +                               #power-domain-cells = <1>;
> > +                       };
> > +
> >                         clk_scmi: protocol@14 {
> >                                 reg = <0x14>;
> >                                 #clock-cells = <1>;
> > @@ -1589,6 +1594,7 @@
> >
> >         sandbox_scmi {
> >                 compatible = "sandbox,scmi-devices";
> > +               power-domains = <&pwrdom_scmi 2>;
> >                 clocks = <&clk_scmi 2>, <&clk_scmi 0>;
> >                 resets = <&reset_scmi 3>;
> >                 regul0-supply = <&regul0_scmi>;
> > diff --git a/arch/sandbox/include/asm/scmi_test.h b/arch/sandbox/include/asm/scmi_test.h
> > index ccb0df6c148f..1b0f4464b98f 100644
> > --- a/arch/sandbox/include/asm/scmi_test.h
> > +++ b/arch/sandbox/include/asm/scmi_test.h
> > @@ -6,10 +6,21 @@
> >  #ifndef __SANDBOX_SCMI_TEST_H
> >  #define __SANDBOX_SCMI_TEST_H
> >
> > +#include <power-domain.h>
> > +
> >  struct udevice;
> >  struct sandbox_scmi_agent;
> >  struct sandbox_scmi_service;
> >
> > +/**
> > + * struct sandbox_scmi_pwd
> > + * @id:                Identifier of the power domain used in the SCMI protocol
> 
> @pstate ?

Yes, I will add a comment.

-Takahiro Akashi


> > + */
> > +struct sandbox_scmi_pwd {
> > +       uint id;
> > +       u32 pstate;
> > +};
> > +
> >  /**
> >   * struct sandbox_scmi_clk - Simulated clock exposed by SCMI
> >   * @id:                Identifier of the clock used in the SCMI protocol
> > @@ -45,6 +56,8 @@ struct sandbox_scmi_voltd {
> >
> 
> [..]
> 
> Regards,
> Simon

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 4/4] test: dm: add SCMI power domain protocol test
  2023-09-26  7:00 ` [PATCH 4/4] test: dm: add SCMI power domain protocol test AKASHI Takahiro
  2023-10-02  1:17   ` Simon Glass
@ 2023-10-14  1:20   ` Tom Rini
  2023-10-16  1:59     ` AKASHI Takahiro
  1 sibling, 1 reply; 10+ messages in thread
From: Tom Rini @ 2023-10-14  1:20 UTC (permalink / raw)
  To: AKASHI Takahiro; +Cc: sjg, etienne.carriere, u-boot

[-- Attachment #1: Type: text/plain, Size: 537 bytes --]

On Tue, Sep 26, 2023 at 04:00:43PM +0900, AKASHI Takahiro wrote:

> This ut has tests for the SCMI power domain protocol as well as DM
> interfaces for power domain devices.
> 
> Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
> Reviewed-by: Simon Glass <sjg@chromium.org>
> ---
>  test/dm/scmi.c | 107 ++++++++++++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 106 insertions(+), 1 deletion(-)

With v6 of the required series there is no scmi command, so, how do we
test this support now?

-- 
Tom

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 659 bytes --]

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 4/4] test: dm: add SCMI power domain protocol test
  2023-10-14  1:20   ` Tom Rini
@ 2023-10-16  1:59     ` AKASHI Takahiro
  0 siblings, 0 replies; 10+ messages in thread
From: AKASHI Takahiro @ 2023-10-16  1:59 UTC (permalink / raw)
  To: Tom Rini; +Cc: sjg, etienne.carriere, u-boot

[-- Attachment #1: Type: text/plain, Size: 1188 bytes --]

Hi Tom,

On Fri, Oct 13, 2023 at 09:20:48PM -0400, Tom Rini wrote:
> On Tue, Sep 26, 2023 at 04:00:43PM +0900, AKASHI Takahiro wrote:
> 
> > This ut has tests for the SCMI power domain protocol as well as DM
> > interfaces for power domain devices.
> > 
> > Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
> > Reviewed-by: Simon Glass <sjg@chromium.org>
> > ---
> >  test/dm/scmi.c | 107 ++++++++++++++++++++++++++++++++++++++++++++++++-
> >  1 file changed, 106 insertions(+), 1 deletion(-)
> 
> With v6 of the required series there is no scmi command, so, how do we
> test this support now?

Well, "ut dm scmi_power_domains" does test the code at function level
(both for SCMI protocol APIs and DM's power_domain_*() interfaces).

That said, prior to v6, we needed to adjust the output from "smci info"
command and hence "ut dm scmi_cmd" test because it, more specifically base
protocol's DISCOVER_LIST_PROTOCOLS, tries to enumerate available protocols
including power domain protocol.

With v6, we can simply remove the first hunk in this commit.
I will submit a new version with this change.

Thanks,
-Takahiro Akashi

> 
> -- 
> Tom



[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2023-10-16  2:00 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-09-26  7:00 [PATCH 0/4] firmware: scmi: add SCMI power domain protocol support AKASHI Takahiro
2023-09-26  7:00 ` [PATCH 1/4] firmware: scmi: add " AKASHI Takahiro
2023-09-26  7:00 ` [PATCH 2/4] power: domain: add SCMI driver AKASHI Takahiro
2023-09-26  7:00 ` [PATCH 3/4] sandbox: add SCMI power domain protocol support for testing AKASHI Takahiro
2023-10-02  1:17   ` Simon Glass
2023-10-03  0:22     ` AKASHI Takahiro
2023-09-26  7:00 ` [PATCH 4/4] test: dm: add SCMI power domain protocol test AKASHI Takahiro
2023-10-02  1:17   ` Simon Glass
2023-10-14  1:20   ` Tom Rini
2023-10-16  1:59     ` AKASHI Takahiro

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox