meta-digi/meta-digi-arm/dynamic-layers/stm-st-stm32mp/recipes-security/scp-firmware/scp-firmware/0001-2.12-stm32mp-r1.patch

5723 lines
194 KiB
Diff

From 223bf375c59e78bd4791a3ae40eb9bdc6d361199 Mon Sep 17 00:00:00 2001
From: Christophe Priouzeau <christophe.priouzeau@foss.st.com>
Date: Mon, 27 Nov 2023 09:44:21 +0100
Subject: [PATCH] 2.12-stm32mp-r1
Signed-off-by: Christophe Priouzeau <christophe.priouzeau@foss.st.com>
---
framework/include/fwk_dlist.h | 4 +-
framework/include/fwk_slist.h | 4 +-
framework/src/fwk_dlist.c | 6 +-
module/clock/include/mod_clock.h | 60 +-
module/clock/src/mod_clock.c | 33 +
module/optee/clock/src/mod_optee_clock.c | 81 +-
.../include/mod_resource_perms.h | 6 +
module/scmi/include/mod_scmi_std.h | 7 +-
.../scmi_clock/include/internal/scmi_clock.h | 71 ++
module/scmi_clock/src/mod_scmi_clock.c | 245 ++++++
.../include/mod_voltage_domain.h | 4 +-
product/optee-stm32mp1/fw/CMakeLists.txt | 7 +-
product/optee-stm32mp1/fw/Firmware.cmake | 15 +-
product/optee-stm32mp1/fw/config_all.c | 797 ++++++++++++++++++
product/optee-stm32mp1/fw/config_mbx_smt.c | 68 --
product/optee-stm32mp1/fw/config_scmi.c | 55 --
.../optee-stm32mp1/fw/config_scmi_clocks.c | 254 ------
.../fw/config_scmi_reset_domains.c | 204 -----
.../fw/config_scmi_voltage_domains.c | 262 ------
.../CMakeLists.txt | 6 +-
.../module/psu_optee_regulator/Module.cmake | 9 +
.../include/mod_psu_optee_regulator.h | 25 +
.../src/mod_psu_optee_regulator.c | 190 +++++
.../module/stm32_pmic_regu/Module.cmake | 9 -
.../include/mod_stm32_pmic_regu.h | 24 -
.../stm32_pmic_regu/src/mod_stm32_pmic_regu.c | 367 --------
.../module/stm32_pwr_regu/Module.cmake | 9 -
.../include/mod_stm32_pwr_regu.h | 19 -
.../stm32_pwr_regu/src/mod_stm32_pwr_regu.c | 293 -------
.../CMakeLists.txt | 9 +-
.../module/stm32_regu_consumer/Module.cmake | 9 +
.../include/mod_stm32_regu_consumer.h | 37 +
.../src/mod_stm32_regu_consumer.c | 343 ++++++++
product/optee-stm32mp2/fw/CMakeLists.txt | 24 +
product/optee-stm32mp2/fw/Firmware.cmake | 57 ++
product/optee-stm32mp2/fw/Toolchain-GNU.cmake | 22 +
product/optee-stm32mp2/fw/config_all.c | 793 +++++++++++++++++
product/optee-stm32mp2/include/fmw_io.h | 17 +
product/optee-stm32mp2/include/fmw_log.h | 16 +
.../optee-stm32mp2/include/gnu/stubs-soft.h | 0
product/optee-stm32mp2/include/scmi_agents.h | 29 +
.../module/psu_optee_regulator/CMakeLists.txt | 17 +
.../module/psu_optee_regulator/Module.cmake | 9 +
.../include/mod_psu_optee_regulator.h | 25 +
.../src/mod_psu_optee_regulator.c | 190 +++++
.../module/stm32_regu_consumer/CMakeLists.txt | 17 +
.../module/stm32_regu_consumer/Module.cmake | 9 +
.../include/mod_stm32_regu_consumer.h | 37 +
.../src/mod_stm32_regu_consumer.c | 345 ++++++++
49 files changed, 3540 insertions(+), 1599 deletions(-)
create mode 100644 product/optee-stm32mp1/fw/config_all.c
delete mode 100644 product/optee-stm32mp1/fw/config_mbx_smt.c
delete mode 100644 product/optee-stm32mp1/fw/config_scmi.c
delete mode 100644 product/optee-stm32mp1/fw/config_scmi_clocks.c
delete mode 100644 product/optee-stm32mp1/fw/config_scmi_reset_domains.c
delete mode 100644 product/optee-stm32mp1/fw/config_scmi_voltage_domains.c
rename product/optee-stm32mp1/module/{stm32_pwr_regu => psu_optee_regulator}/CMakeLists.txt (80%)
create mode 100644 product/optee-stm32mp1/module/psu_optee_regulator/Module.cmake
create mode 100644 product/optee-stm32mp1/module/psu_optee_regulator/include/mod_psu_optee_regulator.h
create mode 100644 product/optee-stm32mp1/module/psu_optee_regulator/src/mod_psu_optee_regulator.c
delete mode 100644 product/optee-stm32mp1/module/stm32_pmic_regu/Module.cmake
delete mode 100644 product/optee-stm32mp1/module/stm32_pmic_regu/include/mod_stm32_pmic_regu.h
delete mode 100644 product/optee-stm32mp1/module/stm32_pmic_regu/src/mod_stm32_pmic_regu.c
delete mode 100644 product/optee-stm32mp1/module/stm32_pwr_regu/Module.cmake
delete mode 100644 product/optee-stm32mp1/module/stm32_pwr_regu/include/mod_stm32_pwr_regu.h
delete mode 100644 product/optee-stm32mp1/module/stm32_pwr_regu/src/mod_stm32_pwr_regu.c
rename product/optee-stm32mp1/module/{stm32_pmic_regu => stm32_regu_consumer}/CMakeLists.txt (64%)
create mode 100644 product/optee-stm32mp1/module/stm32_regu_consumer/Module.cmake
create mode 100644 product/optee-stm32mp1/module/stm32_regu_consumer/include/mod_stm32_regu_consumer.h
create mode 100644 product/optee-stm32mp1/module/stm32_regu_consumer/src/mod_stm32_regu_consumer.c
create mode 100644 product/optee-stm32mp2/fw/CMakeLists.txt
create mode 100644 product/optee-stm32mp2/fw/Firmware.cmake
create mode 100644 product/optee-stm32mp2/fw/Toolchain-GNU.cmake
create mode 100644 product/optee-stm32mp2/fw/config_all.c
create mode 100644 product/optee-stm32mp2/include/fmw_io.h
create mode 100644 product/optee-stm32mp2/include/fmw_log.h
create mode 100644 product/optee-stm32mp2/include/gnu/stubs-soft.h
create mode 100644 product/optee-stm32mp2/include/scmi_agents.h
create mode 100644 product/optee-stm32mp2/module/psu_optee_regulator/CMakeLists.txt
create mode 100644 product/optee-stm32mp2/module/psu_optee_regulator/Module.cmake
create mode 100644 product/optee-stm32mp2/module/psu_optee_regulator/include/mod_psu_optee_regulator.h
create mode 100644 product/optee-stm32mp2/module/psu_optee_regulator/src/mod_psu_optee_regulator.c
create mode 100644 product/optee-stm32mp2/module/stm32_regu_consumer/CMakeLists.txt
create mode 100644 product/optee-stm32mp2/module/stm32_regu_consumer/Module.cmake
create mode 100644 product/optee-stm32mp2/module/stm32_regu_consumer/include/mod_stm32_regu_consumer.h
create mode 100644 product/optee-stm32mp2/module/stm32_regu_consumer/src/mod_stm32_regu_consumer.c
diff --git a/framework/include/fwk_dlist.h b/framework/include/fwk_dlist.h
index fc560b4e..ffe2dc56 100644
--- a/framework/include/fwk_dlist.h
+++ b/framework/include/fwk_dlist.h
@@ -1,6 +1,6 @@
/*
* Arm SCP/MCP Software
- * Copyright (c) 2015-2021, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2023, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*
@@ -92,7 +92,7 @@ struct fwk_dlist_node *__fwk_dlist_pop_head(struct fwk_dlist *list) FWK_LEAF
* See fwk_list_remove(list, node) for the public interface.
*/
void __fwk_dlist_remove(struct fwk_dlist *list, struct fwk_dlist_node *node)
- FWK_LEAF FWK_NOTHROW FWK_NONNULL(1) FWK_NONNULL(2) FWK_UNTOUCHED(1)
+ FWK_LEAF FWK_NOTHROW FWK_NONNULL(1) FWK_NONNULL(2) FWK_READ_ONLY1(1)
FWK_READ_WRITE1(2);
/*
diff --git a/framework/include/fwk_slist.h b/framework/include/fwk_slist.h
index df690999..42830d20 100644
--- a/framework/include/fwk_slist.h
+++ b/framework/include/fwk_slist.h
@@ -1,6 +1,6 @@
/*
* Arm SCP/MCP Software
- * Copyright (c) 2015-2021, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2023, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*
@@ -116,7 +116,7 @@ struct fwk_slist_node *__fwk_slist_pop_head(struct fwk_slist *list) FWK_LEAF
struct fwk_slist_node *__fwk_slist_next(
const struct fwk_slist *list,
const struct fwk_slist_node *node) FWK_PURE FWK_LEAF FWK_NOTHROW
- FWK_NONNULL(1) FWK_NONNULL(2) FWK_UNTOUCHED(1) FWK_READ_ONLY1(2);
+ FWK_NONNULL(1) FWK_NONNULL(2) FWK_READ_ONLY1(1) FWK_READ_ONLY1(2);
/*
* Remove a node from a singly-linked list.
diff --git a/framework/src/fwk_dlist.c b/framework/src/fwk_dlist.c
index 6fcfd08b..e8c1ba62 100644
--- a/framework/src/fwk_dlist.c
+++ b/framework/src/fwk_dlist.c
@@ -1,6 +1,6 @@
/*
* Arm SCP/MCP Software
- * Copyright (c) 2015-2021, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2023, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*
@@ -73,7 +73,7 @@ void __fwk_dlist_remove(
fwk_assert(node->prev != NULL);
fwk_assert(node->next != NULL);
- assert(__fwk_slist_contains(
+ fwk_assert(__fwk_slist_contains(
(struct fwk_slist *)list,
(struct fwk_slist_node *)node));
@@ -104,7 +104,7 @@ void __fwk_dlist_insert(
fwk_assert(node->prev != NULL);
fwk_assert(node->next != NULL);
- assert(__fwk_slist_contains(
+ fwk_assert(__fwk_slist_contains(
(struct fwk_slist *)list,
(struct fwk_slist_node *)node));
diff --git a/module/clock/include/mod_clock.h b/module/clock/include/mod_clock.h
index 4d6f6ead..38bf0400 100644
--- a/module/clock/include/mod_clock.h
+++ b/module/clock/include/mod_clock.h
@@ -175,10 +175,10 @@ struct mod_clock_config {
*/
struct mod_clock_dev_config {
/*! Reference to the device element within the associated driver module */
- const fwk_id_t driver_id;
+ fwk_id_t driver_id;
/*! Reference to the API provided by the device driver module */
- const fwk_id_t api_id;
+ fwk_id_t api_id;
/*!
* \brief Reference to the element or module that is the source of the
@@ -424,6 +424,34 @@ struct mod_clock_drv_api {
fwk_id_t clock_id,
uint64_t in_rate,
uint64_t *out_rate);
+
+ /*!
+ * \brief Get the clock duty cycle.
+ *
+ * \param clock_id Clock device identifier.
+ *
+ * \param[out] num Numerator of the clock duty cycle.
+ *
+ * \param[out] den Denominator of the clock duty cycle.
+ *
+ * \retval ::FWK_SUCCESS The operation succeeded.
+ * \return One of the standard framework error codes.
+ */
+ int (*get_duty_cycle)(fwk_id_t clock_id, uint32_t *num, uint32_t *den);
+
+ /*!
+ * \brief Get the rounded rate the clock supports for requested input @rate
+ *
+ * \param clock_id Clock device identifier.
+ *
+ * \param[int] rate Requested rate in Hertz.
+ *
+ * \param[out] rounded_rate Output rounded rate supported.
+ *
+ * \retval ::FWK_SUCCESS The operation succeeded.
+ * \return One of the standard framework error codes.
+ */
+ int (*round_rate)(fwk_id_t clock_id, uint64_t rate, uint64_t *rounded_rate);
};
/*!
@@ -538,6 +566,34 @@ struct mod_clock_api {
* \return One of the standard framework error codes.
*/
int (*get_info)(fwk_id_t clock_id, struct mod_clock_info *info);
+
+ /*!
+ * \brief Get the clock duty cycle.
+ *
+ * \param clock_id Clock device identifier.
+ *
+ * \param[out] num Numerator of the clock duty cycle.
+ *
+ * \param[out] den Denominator of the clock duty cycle.
+ *
+ * \retval ::FWK_SUCCESS The operation succeeded.
+ * \return One of the standard framework error codes.
+ */
+ int (*get_duty_cycle)(fwk_id_t clock_id, uint32_t *num, uint32_t *den);
+
+ /*!
+ * \brief Get the rounded rate the clock supports for requested input @rate
+ *
+ * \param clock_id Clock device identifier.
+ *
+ * \param[int] rate Requested rate in Hertz.
+ *
+ * \param[out] rounded_rate Output rounded rate supported.
+ *
+ * \retval ::FWK_SUCCESS The operation succeeded.
+ * \return One of the standard framework error codes.
+ */
+ int (*round_rate)(fwk_id_t clock_id, uint64_t rate, uint64_t *rounded_rate);
};
/*!
diff --git a/module/clock/src/mod_clock.c b/module/clock/src/mod_clock.c
index 15a1b331..f4b27b24 100644
--- a/module/clock/src/mod_clock.c
+++ b/module/clock/src/mod_clock.c
@@ -345,6 +345,37 @@ static int clock_get_info(fwk_id_t clock_id, struct mod_clock_info *info)
return FWK_SUCCESS;
}
+static int clock_get_duty_cycle(fwk_id_t clock_id, uint32_t *num, uint32_t *den)
+{
+ struct clock_dev_ctx *ctx;
+
+ clock_get_ctx(clock_id, &ctx);
+
+ if (!ctx->api->get_duty_cycle) {
+ return FWK_E_SUPPORT;
+ }
+
+ return ctx->api->get_duty_cycle(ctx->config->driver_id, num, den);
+}
+
+static int clock_round_rate(fwk_id_t clock_id, uint64_t rate,
+ uint64_t *rounded_rate)
+{
+ struct clock_dev_ctx *ctx;
+
+ clock_get_ctx(clock_id, &ctx);
+
+ if (rounded_rate == NULL) {
+ return FWK_E_PARAM;
+ }
+
+ if (!ctx->api->round_rate) {
+ return FWK_E_SUPPORT;
+ }
+
+ return ctx->api->round_rate(ctx->config->driver_id, rate, rounded_rate);
+}
+
static const struct mod_clock_api clock_api = {
.set_rate = clock_set_rate,
.get_rate = clock_get_rate,
@@ -352,6 +383,8 @@ static const struct mod_clock_api clock_api = {
.set_state = clock_set_state,
.get_state = clock_get_state,
.get_info = clock_get_info,
+ .get_duty_cycle = clock_get_duty_cycle,
+ .round_rate = clock_round_rate,
};
/*
diff --git a/module/optee/clock/src/mod_optee_clock.c b/module/optee/clock/src/mod_optee_clock.c
index 0ccaade7..36d9fa9d 100644
--- a/module/optee/clock/src/mod_optee_clock.c
+++ b/module/optee/clock/src/mod_optee_clock.c
@@ -179,9 +179,8 @@ static int get_range(fwk_id_t dev_id, struct mod_clock_range *range)
return FWK_E_PARAM;
}
- range->rate_type = MOD_CLOCK_RATE_TYPE_DISCRETE;
-
if (!is_exposed(ctx)) {
+ range->rate_type = MOD_CLOCK_RATE_TYPE_DISCRETE;
range->min = 0;
range->max = 0;
range->rate_count = 1;
@@ -191,9 +190,23 @@ static int get_range(fwk_id_t dev_id, struct mod_clock_range *range)
res = clk_get_rates_array(ctx->clk, 0, NULL, &rate_count);
if (res == TEE_ERROR_NOT_SUPPORTED) {
- range->min = clk_get_rate(ctx->clk);
- range->max = range->min;
- range->rate_count = 1;
+ unsigned long max = 0;
+ unsigned long min = 0;
+ unsigned long step = 0;
+
+ res = clk_get_rates_steps(ctx->clk, &min, &max, &step);
+
+ if (res == TEE_ERROR_NOT_SUPPORTED) {
+ range->rate_type = MOD_CLOCK_RATE_TYPE_DISCRETE;
+ range->min = clk_get_rate(ctx->clk);
+ range->max = range->min;
+ range->rate_count = 1;
+ }
+
+ range->rate_type = MOD_CLOCK_RATE_TYPE_CONTINUOUS;
+ range->min = min;
+ range->max = max;
+ range->step = step;
return FWK_SUCCESS;
}
@@ -293,6 +306,62 @@ static int get_rate_from_index(fwk_id_t dev_id,
return FWK_SUCCESS;
}
+static int get_duty_cycle(fwk_id_t dev_id, uint32_t *num, uint32_t *den)
+{
+ struct optee_clock_dev_ctx *ctx = elt_id_to_ctx(dev_id);
+ struct clk_duty duty = { 0 };
+ TEE_Result res;
+
+ if (ctx == NULL) {
+ return FWK_E_PARAM;
+ }
+
+ if (!is_exposed(ctx)) {
+ /* Return a dummy value to prevent an error trace */
+ *num = 1;
+ *den = 2;
+ return FWK_SUCCESS;
+ }
+
+ res = clk_get_duty_cycle(ctx->clk, &duty);
+
+ FWK_LOG_DEBUG(
+ MOD_NAME "SCMI optee_clock (%u/\"%s\"): %" PRIx32,
+ fwk_id_get_element_idx(dev_id),
+ clk_get_name(ctx->clk),
+ res);
+
+ if (res == TEE_ERROR_NOT_SUPPORTED) {
+ /* Assume a 50% duty cycle */
+ duty = (struct clk_duty){ .num = 1, .den = 2 };
+ } else if (res != TEE_SUCCESS) {
+ return FWK_E_DEVICE;
+ }
+
+ *num = duty.num;
+ *den = duty.den;
+
+ return FWK_SUCCESS;
+}
+
+static int get_rounded_rate(fwk_id_t dev_id, uint64_t rate,
+ uint64_t *rounded_rate)
+{
+ struct optee_clock_dev_ctx *ctx = elt_id_to_ctx(dev_id);
+
+ if (ctx == NULL) {
+ return FWK_E_PARAM;
+ }
+
+ if (!is_exposed(ctx)) {
+ return FWK_E_SUPPORT;
+ }
+
+ *rounded_rate = (uint64_t)clk_round_rate(ctx->clk, (unsigned long)rate);
+
+ return FWK_SUCCESS;
+}
+
static int stub_process_power_transition(fwk_id_t dev_id, unsigned int state)
{
return FWK_E_SUPPORT;
@@ -312,6 +381,8 @@ static const struct mod_clock_drv_api api_optee_clock = {
.get_range = get_range,
.get_rate_from_index = get_rate_from_index,
.set_rate = set_rate,
+ .get_duty_cycle = get_duty_cycle,
+ .round_rate = get_rounded_rate,
/* Not supported */
.process_power_transition = stub_process_power_transition,
.process_pending_power_transition = stub_pending_power_transition,
diff --git a/module/resource_perms/include/mod_resource_perms.h b/module/resource_perms/include/mod_resource_perms.h
index 99d2f3d0..78da6799 100644
--- a/module/resource_perms/include/mod_resource_perms.h
+++ b/module/resource_perms/include/mod_resource_perms.h
@@ -187,6 +187,12 @@ enum mod_res_clock_permissions_idx {
MOD_SCMI_CLOCK_RATE_GET - MOD_RES_PERMS_CLOCK_PERMS_OFFSET,
MOD_RES_PERMS_SCMI_CLOCK_CONFIG_SET_IDX =
MOD_SCMI_CLOCK_CONFIG_SET - MOD_RES_PERMS_CLOCK_PERMS_OFFSET,
+ MOD_RES_PERMS_SCMI_CLOCK_NAME_GET_IDX =
+ MOD_SCMI_CLOCK_NAME_GET - MOD_RES_PERMS_CLOCK_PERMS_OFFSET,
+ MOD_RES_PERMS_SCMI_CLOCK_RATE_NOTIFY_IDX =
+ MOD_SCMI_CLOCK_RATE_NOTIFY - MOD_RES_PERMS_CLOCK_PERMS_OFFSET,
+ MOD_RES_PERMS_SCMI_CLOCK_CHANGE_REQUESTED_NOTIFY_IDX =
+ MOD_SCMI_CLOCK_CHANGE_REQUESTED_NOTIFY - MOD_RES_PERMS_CLOCK_PERMS_OFFSET,
};
/*!
diff --git a/module/scmi/include/mod_scmi_std.h b/module/scmi/include/mod_scmi_std.h
index d212c687..1724406b 100644
--- a/module/scmi/include/mod_scmi_std.h
+++ b/module/scmi/include/mod_scmi_std.h
@@ -161,7 +161,12 @@ enum scmi_clock_command_id {
MOD_SCMI_CLOCK_RATE_SET = 0x005,
MOD_SCMI_CLOCK_RATE_GET = 0x006,
MOD_SCMI_CLOCK_CONFIG_SET = 0x007,
- MOD_SCMI_CLOCK_COMMAND_COUNT,
+ MOD_SCMI_CLOCK_NAME_GET = 0x008,
+ MOD_SCMI_CLOCK_RATE_NOTIFY = 0x009,
+ MOD_SCMI_CLOCK_RATE_CHANGE_REQUESTED_NOTIFY = 0x00A,
+ MOD_SCMI_CLOCK_DUTY_CYCLE_GET = 0x00B,
+ MOD_SCMI_CLOCK_ROUND_RATE_GET = 0x00C,
+ MOD_SCMI_CLOCK_COMMAND_COUNT
};
/*!
diff --git a/module/scmi_clock/include/internal/scmi_clock.h b/module/scmi_clock/include/internal/scmi_clock.h
index f3b51e5b..7671e0e8 100644
--- a/module/scmi_clock/include/internal/scmi_clock.h
+++ b/module/scmi_clock/include/internal/scmi_clock.h
@@ -244,4 +244,75 @@ struct scmi_clock_describe_rates_p2a {
struct scmi_clock_rate rates[];
};
+/*
+ * Clock get name (extended 64byte name)
+ */
+
+struct scmi_clock_name_get_a2p {
+ uint32_t clock_id;
+};
+
+#define SCMI_CLOCK_EXTTENDED_NAME_LENGTH_MAX 64
+
+struct scmi_clock_name_get_p2a {
+ int32_t status;
+ uint32_t flags;
+ char clock_name[SCMI_CLOCK_EXTTENDED_NAME_LENGTH_MAX];
+};
+
+/*
+ * Clock notify on clock rate change
+ */
+
+struct scmi_clock_rate_notify_a2p {
+ uint32_t clock_id;
+ uint32_t notify_enable;
+};
+
+struct scmi_clock_rate_notify_p2a {
+ int32_t status;
+};
+
+/*
+ * Clock notify on clock rate change requests
+ */
+
+struct scmi_clock_rate_change_request_notify_a2p {
+ uint32_t clock_id;
+ uint32_t notify_enable;
+};
+
+struct scmi_clock_rate_change_request_notify_p2a {
+ int32_t status;
+};
+
+/*
+ * Clock get duty cycle
+ */
+
+struct scmi_clock_duty_cycle_get_a2p {
+ uint32_t clock_id;
+};
+
+struct scmi_clock_duty_cycle_get_p2a {
+ int32_t status;
+ uint32_t numerator;
+ uint32_t denominator;
+};
+
+/*
+ * Clock get round rate
+ */
+
+struct scmi_clock_round_rate_get_a2p {
+ uint32_t flags;
+ uint32_t clock_id;
+ uint32_t rate[2];
+};
+
+struct scmi_clock_round_rate_get_p2a {
+ int32_t status;
+ uint32_t rate[2];
+};
+
#endif /* INTERNAL_SCMI_CLOCK_H */
diff --git a/module/scmi_clock/src/mod_scmi_clock.c b/module/scmi_clock/src/mod_scmi_clock.c
index 59a1fb14..5999e03f 100644
--- a/module/scmi_clock/src/mod_scmi_clock.c
+++ b/module/scmi_clock/src/mod_scmi_clock.c
@@ -128,6 +128,16 @@ static int scmi_clock_config_set_handler(fwk_id_t service_id,
const uint32_t *payload);
static int scmi_clock_describe_rates_handler(fwk_id_t service_id,
const uint32_t *payload);
+static int scmi_clock_name_get_handler(fwk_id_t service_id,
+ const uint32_t *payload);
+static int scmi_clock_rate_notify_handler(fwk_id_t service_id,
+ const uint32_t *payload);
+static int scmi_clock_rate_change_request_notify_handler(fwk_id_t service_id,
+ const uint32_t *payload);
+static int scmi_clock_duty_cycle_get_handler(fwk_id_t service_id,
+ const uint32_t *payload);
+static int scmi_clock_round_rate_get_handler(fwk_id_t service_id,
+ const uint32_t *payload);
/*
* Internal variables.
@@ -146,6 +156,11 @@ static int (*const handler_table[MOD_SCMI_CLOCK_COMMAND_COUNT])(
[MOD_SCMI_CLOCK_RATE_SET] = scmi_clock_rate_set_handler,
[MOD_SCMI_CLOCK_CONFIG_SET] = scmi_clock_config_set_handler,
[MOD_SCMI_CLOCK_DESCRIBE_RATES] = scmi_clock_describe_rates_handler,
+ [MOD_SCMI_CLOCK_NAME_GET] = scmi_clock_name_get_handler,
+ [MOD_SCMI_CLOCK_RATE_NOTIFY] = scmi_clock_rate_notify_handler,
+ [MOD_SCMI_CLOCK_RATE_CHANGE_REQUESTED_NOTIFY] = scmi_clock_rate_change_request_notify_handler,
+ [MOD_SCMI_CLOCK_DUTY_CYCLE_GET] = scmi_clock_duty_cycle_get_handler,
+ [MOD_SCMI_CLOCK_ROUND_RATE_GET] = scmi_clock_round_rate_get_handler,
};
static const unsigned int payload_size_table[MOD_SCMI_CLOCK_COMMAND_COUNT] = {
@@ -163,6 +178,16 @@ static const unsigned int payload_size_table[MOD_SCMI_CLOCK_COMMAND_COUNT] = {
(unsigned int)sizeof(struct scmi_clock_config_set_a2p),
[MOD_SCMI_CLOCK_DESCRIBE_RATES] =
(unsigned int)sizeof(struct scmi_clock_describe_rates_a2p),
+ [MOD_SCMI_CLOCK_NAME_GET] =
+ (unsigned int)sizeof(struct scmi_clock_describe_rates_a2p),
+ [MOD_SCMI_CLOCK_RATE_NOTIFY] =
+ (unsigned int)sizeof(struct scmi_clock_rate_notify_a2p),
+ [MOD_SCMI_CLOCK_RATE_CHANGE_REQUESTED_NOTIFY] =
+ (unsigned int)sizeof(struct scmi_clock_rate_change_request_notify_a2p),
+ [MOD_SCMI_CLOCK_DUTY_CYCLE_GET] =
+ (unsigned int)sizeof(struct scmi_clock_duty_cycle_get_a2p),
+ [MOD_SCMI_CLOCK_ROUND_RATE_GET] =
+ (unsigned int)sizeof(struct scmi_clock_round_rate_get_a2p),
};
/*
@@ -1368,6 +1393,226 @@ exit:
return status;
}
+static int scmi_clock_name_get_handler(fwk_id_t service_id,
+ const uint32_t *payload)
+{
+ int status, respond_status;
+ const struct mod_scmi_clock_device *clock_device;
+ size_t response_size;
+ const struct scmi_clock_name_get_a2p *parameters;
+ struct scmi_clock_name_get_p2a return_values = {
+ .status = (int32_t)SCMI_GENERIC_ERROR
+ };
+
+ parameters = (const struct scmi_clock_name_get_a2p*)payload;
+
+ status = scmi_clock_get_clock_device_entry(
+ service_id, parameters->clock_id, &clock_device);
+ if (status != FWK_SUCCESS) {
+ return_values.status = (int32_t)SCMI_NOT_FOUND;
+ goto exit;
+ }
+
+#ifdef BUILD_HAS_MOD_RESOURCE_PERMS
+ status = scmi_clock_permissions_handler(
+ parameters->clock_id,
+ service_id,
+ (unsigned int)MOD_SCMI_CLOCK_NAME_GET);
+ if (status != FWK_SUCCESS) {
+ return_values.status = (int32_t)SCMI_DENIED;
+ goto exit;
+ }
+#endif
+
+ fwk_str_strncpy(
+ return_values.clock_name,
+ fwk_module_get_element_name(clock_device->element_id),
+ sizeof(return_values.clock_name) - 1);
+
+ return_values.status = (int32_t)SCMI_SUCCESS;
+ response_size = sizeof(return_values);
+ return FWK_SUCCESS;
+
+exit:
+ response_size = sizeof(return_values.status);
+ respond_status = scmi_clock_ctx.scmi_api->respond(
+ service_id, &return_values, response_size);
+ if (respond_status != FWK_SUCCESS) {
+ FWK_LOG_DEBUG("[SCMI-CLK] %s @%d", __func__, __LINE__);
+ }
+
+ return status;
+}
+
+static int scmi_clock_rate_notify_handler(fwk_id_t service_id,
+ const uint32_t *payload)
+{
+ struct scmi_clock_rate_notify_p2a return_values = {
+ .status = (int32_t)SCMI_NOT_SUPPORTED,
+ };
+ int respond_status;
+
+ respond_status = scmi_clock_ctx.scmi_api->respond(
+ service_id,
+ &return_values,
+ sizeof(return_values.status));
+
+ if (respond_status != FWK_SUCCESS) {
+ FWK_LOG_DEBUG("[SCMI-CLK] %s @%d", __func__, __LINE__);
+ }
+
+ return FWK_SUCCESS;
+}
+
+static int scmi_clock_rate_change_request_notify_handler(fwk_id_t service_id,
+ const uint32_t *payload)
+{
+ struct scmi_clock_rate_change_request_notify_p2a return_values = {
+ .status = (int32_t)SCMI_NOT_SUPPORTED,
+ };
+ int respond_status;
+
+ respond_status = scmi_clock_ctx.scmi_api->respond(
+ service_id,
+ &return_values,
+ sizeof(return_values.status));
+
+ if (respond_status != FWK_SUCCESS) {
+ FWK_LOG_DEBUG("[SCMI-CLK] %s @%d", __func__, __LINE__);
+ }
+
+ return FWK_SUCCESS;
+}
+
+static int scmi_clock_duty_cycle_get_handler(fwk_id_t service_id,
+ const uint32_t *payload)
+
+{
+ const struct scmi_clock_duty_cycle_get_a2p *parameters;
+ struct scmi_clock_duty_cycle_get_p2a return_values = {
+ .status = (int32_t)SCMI_SUCCESS
+ };
+ const struct mod_scmi_clock_device *clock_device;
+ unsigned int agent_id;
+ size_t response_size;
+ int status;
+
+ parameters = (const struct scmi_clock_duty_cycle_get_a2p*)payload;
+
+ status = scmi_clock_get_clock_device_entry(
+ service_id, parameters->clock_id, &clock_device);
+ if (status != FWK_SUCCESS) {
+ return_values.status = (int32_t)SCMI_NOT_FOUND;
+ goto exit;
+ }
+
+#ifdef BUILD_HAS_MOD_RESOURCE_PERMS
+ /* Test SET_RATE permission until we have a DUTY_CYCLE permission flag */
+ status = scmi_clock_permissions_handler(
+ parameters->clock_id,
+ service_id,
+ (unsigned int)MOD_SCMI_CLOCK_RATE_SET);
+ if (status != FWK_SUCCESS) {
+ return_values.status = (int32_t)SCMI_DENIED;
+ goto exit;
+ }
+#endif
+
+ status = scmi_clock_ctx.scmi_api->get_agent_id(service_id, &agent_id);
+ if (status != FWK_SUCCESS) {
+ goto exit;
+ }
+
+ status = scmi_clock_ctx.clock_api->get_duty_cycle(clock_device->element_id,
+ &return_values.numerator,
+ &return_values.denominator);
+
+ if (status == FWK_E_SUPPORT) {
+ return_values.status = (int32_t)SCMI_NOT_SUPPORTED;
+ } else if (status != FWK_SUCCESS) {
+ return_values.status = (int32_t)SCMI_GENERIC_ERROR;
+ }
+
+exit:
+ response_size = (return_values.status == SCMI_SUCCESS) ?
+ sizeof(return_values) : sizeof(return_values.status);
+ return scmi_clock_ctx.scmi_api->respond(
+ service_id, &return_values, response_size);
+}
+
+/*
+ * Use clock set rate with round nearest flag support to
+ * get rounded value.
+ */
+static int scmi_clock_round_rate_get_handler(fwk_id_t service_id,
+ const uint32_t *payload)
+{
+ const struct scmi_clock_round_rate_get_a2p *parameters;
+ struct scmi_clock_round_rate_get_p2a return_values = {
+ .status = (int32_t)SCMI_SUCCESS,
+ };
+ const struct mod_scmi_clock_device *clock_device;
+ unsigned long input_rate;
+ uint64_t output_rate;
+ size_t response_size;
+ int status;
+
+ parameters = (const struct scmi_clock_round_rate_get_a2p*)payload;
+
+ status = scmi_clock_get_clock_device_entry(
+ service_id,
+ parameters->clock_id,
+ &clock_device);
+
+ if (status != FWK_SUCCESS) {
+ return_values.status = (int32_t)SCMI_NOT_FOUND;
+ goto exit;
+ }
+
+#ifdef BUILD_HAS_MOD_RESOURCE_PERMS
+ status = scmi_clock_permissions_handler(
+ parameters->clock_id,
+ service_id,
+ (unsigned int)MOD_SCMI_CLOCK_RATE_SET);
+ if (status != FWK_SUCCESS) {
+ return_values.status = (int32_t)SCMI_DENIED;
+ goto exit;
+ }
+#endif
+
+ if ((parameters->flags & SCMI_CLOCK_RATE_SET_ASYNC_MASK) != 0) {
+ /* Support for async clock set commands not yet implemented */
+ return_values.status = (int32_t)SCMI_NOT_SUPPORTED;
+ goto exit;
+ }
+
+ input_rate = parameters->rate[0];
+ if (parameters->rate[1]) {
+ return_values.status = (int32_t)SCMI_INVALID_PARAMETERS;
+ goto exit;
+ }
+
+ status = scmi_clock_ctx.clock_api->round_rate(clock_device->element_id,
+ input_rate, &output_rate);
+ if (status == FWK_E_SUPPORT) {
+ return_values.status = (int32_t)SCMI_NOT_SUPPORTED;
+ } else if (status != FWK_SUCCESS) {
+ return_values.status = (int32_t)SCMI_GENERIC_ERROR;
+ } else {
+ return_values.rate[0] = (uint32_t)output_rate;
+ return_values.rate[1] = 0;
+ return_values.status = (int32_t)SCMI_SUCCESS;
+ }
+
+exit:
+
+
+ response_size = (return_values.status == SCMI_SUCCESS) ?
+ sizeof(return_values) : sizeof(return_values.status);
+ return scmi_clock_ctx.scmi_api->respond(
+ service_id, &return_values, response_size);
+}
+
/*
* SCMI module -> SCMI clock module interface
*/
diff --git a/module/voltage_domain/include/mod_voltage_domain.h b/module/voltage_domain/include/mod_voltage_domain.h
index 85b09606..cd0c21f1 100644
--- a/module/voltage_domain/include/mod_voltage_domain.h
+++ b/module/voltage_domain/include/mod_voltage_domain.h
@@ -78,10 +78,10 @@ enum mod_voltd_voltage_level_type {
*/
struct mod_voltd_dev_config {
/*! Reference to the device element within the associated driver module */
- const fwk_id_t driver_id;
+ fwk_id_t driver_id;
/*! Reference to the API provided by the device driver module */
- const fwk_id_t api_id;
+ fwk_id_t api_id;
};
/*!
diff --git a/product/optee-stm32mp1/fw/CMakeLists.txt b/product/optee-stm32mp1/fw/CMakeLists.txt
index c3a47b21..8674a1eb 100644
--- a/product/optee-stm32mp1/fw/CMakeLists.txt
+++ b/product/optee-stm32mp1/fw/CMakeLists.txt
@@ -20,8 +20,5 @@ target_include_directories(
target_sources(
${SCP_FIRMWARE_TARGET}
- PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/config_mbx_smt.c"
- "${CMAKE_CURRENT_SOURCE_DIR}/config_scmi.c"
- "${CMAKE_CURRENT_SOURCE_DIR}/config_scmi_clocks.c"
- "${CMAKE_CURRENT_SOURCE_DIR}/config_scmi_reset_domains.c"
- "${CMAKE_CURRENT_SOURCE_DIR}/config_scmi_voltage_domains.c")
+ PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/config_all.c"
+)
diff --git a/product/optee-stm32mp1/fw/Firmware.cmake b/product/optee-stm32mp1/fw/Firmware.cmake
index b0d55b83..0b84f335 100644
--- a/product/optee-stm32mp1/fw/Firmware.cmake
+++ b/product/optee-stm32mp1/fw/Firmware.cmake
@@ -31,15 +31,15 @@ set(SCP_ENABLE_SCMI_RESET_INIT TRUE)
set(SCP_ENABLE_IPO_INIT FALSE)
-list(PREPEND SCP_MODULE_PATHS "${CMAKE_CURRENT_LIST_DIR}/../module/stm32_pmic_regu")
-list(PREPEND SCP_MODULE_PATHS "${CMAKE_CURRENT_LIST_DIR}/../module/stm32_pwr_regu")
+list(PREPEND SCP_MODULE_PATHS "${CMAKE_CURRENT_LIST_DIR}/../module/stm32_regu_consumer")
+list(PREPEND SCP_MODULE_PATHS "${CMAKE_CURRENT_LIST_DIR}/../module/psu_optee_regulator")
# The order of the modules in the following list is the order in which the
# modules are initialized, bound, started during the pre-runtime phase.
# any change in the order will cause firmware initialization errors.
list(APPEND SCP_MODULES "optee-mbx")
-list(APPEND SCP_MODULES "optee-smt")
+list(APPEND SCP_MODULES "msg-smt")
list(APPEND SCP_MODULES "scmi")
list(APPEND SCP_MODULES "optee-clock")
list(APPEND SCP_MODULES "clock")
@@ -47,8 +47,13 @@ list(APPEND SCP_MODULES "scmi-clock")
list(APPEND SCP_MODULES "optee-reset")
list(APPEND SCP_MODULES "reset-domain")
list(APPEND SCP_MODULES "scmi-reset-domain")
-list(APPEND SCP_MODULES "stm32-pmic-regu")
-list(APPEND SCP_MODULES "stm32-pwr-regu")
+list(APPEND SCP_MODULES "stm32-regu-consumer")
list(APPEND SCP_MODULES "voltage-domain")
list(APPEND SCP_MODULES "scmi-voltage-domain")
+if (CFG_STM32MP13)
+ list(APPEND SCP_MODULES "psu-optee-regulator")
+ list(APPEND SCP_MODULES "psu")
+ list(APPEND SCP_MODULES "dvfs")
+ list(APPEND SCP_MODULES "scmi-perf")
+endif (CFG_STM32MP13)
list(APPEND SCP_MODULES "optee-console")
diff --git a/product/optee-stm32mp1/fw/config_all.c b/product/optee-stm32mp1/fw/config_all.c
new file mode 100644
index 00000000..afff9283
--- /dev/null
+++ b/product/optee-stm32mp1/fw/config_all.c
@@ -0,0 +1,797 @@
+/*
+ * Arm SCP/MCP Software
+ * Copyright (c) 2022-2023, Linaro Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <fwk_assert.h>
+#include <fwk_element.h>
+#include <fwk_id.h>
+#include <fwk_mm.h>
+#include <fwk_module.h>
+#include <fwk_module_idx.h>
+
+#include <mod_clock.h>
+#ifdef CFG_SCPFW_MOD_DVFS
+#include <mod_dvfs.h>
+#endif
+#include <mod_msg_smt.h>
+#include <mod_optee_clock.h>
+#include <mod_optee_mbx.h>
+#include <mod_optee_reset.h>
+#ifdef CFG_SCPFW_MOD_PSU
+#include <mod_psu.h>
+#include <mod_psu_optee_regulator.h>
+#endif
+#include <mod_reset_domain.h>
+#include <mod_scmi.h>
+#include <mod_scmi_clock.h>
+#include <mod_scmi_perf.h>
+#include <mod_scmi_reset_domain.h>
+#include <mod_scmi_voltage_domain.h>
+#include <mod_stm32_regu_consumer.h>
+#include <mod_voltage_domain.h>
+#include <scmi_agents.h>
+
+#include <assert.h>
+#include <stddef.h>
+#include <stdint.h>
+
+#include <drivers/regulator.h>
+#include <drivers/stm32mp_dt_bindings.h>
+#include <kernel/panic.h>
+#include <scmi_agent_configuration.h>
+#include <stm32_util.h>
+#include <util.h>
+
+/* SCMI agent and services (channels) */
+static struct mod_scmi_agent *scmi_agent_table;
+static struct mod_scmi_config scmi_data;
+static struct fwk_element *scmi_service_elt;
+
+/* SCMI channel mailbox/shmem */
+static struct fwk_element *msg_smt_elt;
+static struct mod_msg_smt_channel_config *msg_smt_data;
+static struct fwk_element *optee_mbx_elt;
+static struct mod_optee_mbx_channel_config *optee_mbx_data;
+
+#ifdef CFG_SCPFW_MOD_SCMI_CLOCK
+/* SCMI clock generic */
+static struct mod_scmi_clock_agent *scmi_clk_agent_tbl;
+#endif
+
+#ifdef CFG_SCPFW_MOD_CLOCK
+/* Clocks and optee/clock, same number/indices. Elements and configuration data */
+static struct fwk_element *optee_clock_elt; /* Optee/clock elements */
+static struct mod_optee_clock_config *optee_clock_cfg; /* Config data for optee/clock elements */
+static struct fwk_element *clock_elt; /* Clock elements */
+static struct mod_clock_dev_config *clock_data; /* Config data for clock elements */
+#endif
+
+#ifdef CFG_SCPFW_MOD_DVFS
+/* 1 DVFS (elt & data) per DVFS exposed */
+static struct mod_dvfs_domain_config *dvfs_data;
+static struct fwk_element *dvfs_elt;
+/* A unique scmi_perf instance refers to perf domains data (DVFS instance) */
+static struct mod_scmi_perf_domain_config *scmi_perf_domain_data;
+struct fwk_module_config config_scmi_perf;
+
+/* PSU and optee/psu-regu, used with DVFS. Elements and configuration data */
+static struct fwk_element *psu_optee_regu_elt;
+static struct mod_psu_optee_regulator_dev_config *psu_optee_regu_data;
+static struct fwk_element *psu_elt;
+static struct mod_psu_element_cfg *psu_data;
+#endif
+
+#ifdef CFG_SCPFW_MOD_RESET_DOMAIN
+/* SCMI reset domains and optee reset controller */
+static struct mod_scmi_reset_domain_agent *scmi_reset_agent_tbl;
+static struct fwk_element *optee_reset_elt;
+static struct mod_optee_reset_dev_config *optee_reset_data;
+static struct fwk_element *reset_elt;
+static struct mod_reset_domain_dev_config *reset_data;
+#endif
+
+#ifdef CFG_SCPFW_MOD_VOLTAGE_DOMAIN
+/* SCMI voltage domains and optee regulators */
+static struct mod_scmi_voltd_agent *scmi_voltd_agent_tbl;
+static struct fwk_element *optee_regu_elt;
+static struct mod_stm32_regu_consumer_dev_config *optee_regu_data;
+static struct fwk_element *voltd_elt;
+static struct mod_voltd_dev_config *voltd_data;
+#endif
+
+/* Config data for scmi module */
+static const struct fwk_element *get_scmi_service_table(fwk_id_t module_id)
+{
+ return scmi_service_elt; /* scmi_service_elt filled during initialization */
+}
+
+struct fwk_module_config config_scmi = {
+ .data = (void *)&scmi_data, /* scmi_data filled during initialization */
+ .elements = FWK_MODULE_DYNAMIC_ELEMENTS(get_scmi_service_table),
+};
+
+/* Config data for optee_mbx module */
+static const struct fwk_element *optee_mbx_get_element_table(fwk_id_t module_id)
+{
+ return (const struct fwk_element *)optee_mbx_elt;
+}
+
+struct fwk_module_config config_optee_mbx = {
+ .elements = FWK_MODULE_DYNAMIC_ELEMENTS(optee_mbx_get_element_table),
+};
+
+/* Config data for msg_smt module */
+static const struct fwk_element *msg_smt_get_element_table(fwk_id_t module_id)
+{
+ fwk_assert(fwk_id_get_module_idx(module_id) == FWK_MODULE_IDX_MSG_SMT);
+ return (const struct fwk_element *)msg_smt_elt;
+}
+
+struct fwk_module_config config_msg_smt = {
+ .elements = FWK_MODULE_DYNAMIC_ELEMENTS(msg_smt_get_element_table),
+};
+
+/* Config data for scmi_clock, clock and optee_clock modules */
+#ifdef CFG_SCPFW_MOD_SCMI_CLOCK
+struct fwk_module_config config_scmi_clock = {
+ .data = &((struct mod_scmi_clock_config){
+ .agent_table = NULL, /* Allocated during initialization */
+ .agent_count = 0, /* Set during initialization */
+ }),
+};
+#endif
+
+#ifdef CFG_SCPFW_MOD_CLOCK
+static const struct fwk_element *clock_get_element_table(fwk_id_t module_id)
+{
+ fwk_assert(fwk_id_get_module_idx(module_id) == FWK_MODULE_IDX_CLOCK);
+ return (const struct fwk_element *)clock_elt;
+}
+
+struct fwk_module_config config_clock = {
+ .elements = FWK_MODULE_DYNAMIC_ELEMENTS(clock_get_element_table),
+};
+
+static const struct fwk_element *optee_clock_get_element_table(fwk_id_t module_id)
+{
+ fwk_assert(fwk_id_get_module_idx(module_id) == FWK_MODULE_IDX_OPTEE_CLOCK);
+ return (const struct fwk_element *)optee_clock_elt;
+}
+
+struct fwk_module_config config_optee_clock = {
+ .elements = FWK_MODULE_DYNAMIC_ELEMENTS(optee_clock_get_element_table),
+};
+#endif
+
+/* Config data for scmi_reset_domain, reset_domain and optee_reset modules */
+#ifdef CFG_SCPFW_MOD_RESET_DOMAIN
+struct fwk_module_config config_scmi_reset_domain = {
+ .data = &((struct mod_scmi_reset_domain_config){
+ .agent_table = NULL, /* Allocated during initialization */
+ .agent_count = 0, /* Set during initialization */
+ }),
+};
+
+static const struct fwk_element *reset_get_element_table(fwk_id_t module_id)
+{
+ fwk_assert(fwk_id_get_module_idx(module_id) == FWK_MODULE_IDX_RESET_DOMAIN);
+ return (const struct fwk_element *)reset_elt;
+}
+
+struct fwk_module_config config_reset_domain = {
+ .elements = FWK_MODULE_DYNAMIC_ELEMENTS(reset_get_element_table),
+};
+
+static const struct fwk_element *optee_reset_get_element_table(fwk_id_t module_id)
+{
+ fwk_assert(fwk_id_get_module_idx(module_id) == FWK_MODULE_IDX_OPTEE_RESET);
+ return (const struct fwk_element *)optee_reset_elt;
+}
+
+struct fwk_module_config config_optee_reset = {
+ .elements = FWK_MODULE_DYNAMIC_ELEMENTS(optee_reset_get_element_table),
+};
+#endif
+
+#ifdef CFG_SCPFW_MOD_VOLTAGE_DOMAIN
+/* Config data for scmi_voltage_domain, voltage_domain and optee_regu modules */
+struct fwk_module_config config_scmi_voltage_domain = {
+ .data = &((struct mod_scmi_voltd_config){
+ .agent_table = NULL, /* Allocated during initialization */
+ .agent_count = 0, /* Set during initialization */
+ }),
+};
+
+static const struct fwk_element *voltd_get_element_table(fwk_id_t module_id)
+{
+ fwk_assert(fwk_id_get_module_idx(module_id) == FWK_MODULE_IDX_VOLTAGE_DOMAIN);
+ return (const struct fwk_element *)voltd_elt;
+}
+
+struct fwk_module_config config_voltage_domain = {
+ .elements = FWK_MODULE_DYNAMIC_ELEMENTS(voltd_get_element_table),
+};
+
+static const struct fwk_element *stm32_regu_consumer_get_element_table(fwk_id_t module_id)
+{
+ fwk_assert(fwk_id_get_module_idx(module_id) == FWK_MODULE_IDX_STM32_REGU_CONSUMER);
+ return (const struct fwk_element *)optee_regu_elt;
+}
+
+struct fwk_module_config config_stm32_regu_consumer = {
+ .elements = FWK_MODULE_DYNAMIC_ELEMENTS(stm32_regu_consumer_get_element_table),
+};
+#endif
+
+#ifdef CFG_SCPFW_MOD_DVFS
+/* Config data for scmi_perf and dvfs module */
+struct fwk_module_config config_scmi_perf = {
+ .data = &((struct mod_scmi_perf_config){
+ .domains = NULL, /* Allocated during initialization */
+ .perf_doms_count = 0, /* Set during initialization */
+ .fast_channels_alarm_id = FWK_ID_NONE_INIT,
+#ifdef BUILD_HAS_MOD_STATISTICS
+ .stats_enabled = true,
+#endif
+ }),
+};
+
+static const struct fwk_element *dvfs_get_element_table(fwk_id_t module_id)
+{
+ fwk_assert(fwk_id_get_module_idx(module_id) == FWK_MODULE_IDX_DVFS);
+ return (const struct fwk_element *)dvfs_elt;
+}
+
+struct fwk_module_config config_dvfs = {
+ .elements = FWK_MODULE_DYNAMIC_ELEMENTS(dvfs_get_element_table),
+};
+
+/* Config data for psu and optee/psu module */
+static const struct fwk_element *psu_get_element_table(fwk_id_t module_id)
+{
+ fwk_assert(fwk_id_get_module_idx(module_id) == FWK_MODULE_IDX_PSU);
+ return (const struct fwk_element *)psu_elt;
+}
+
+struct fwk_module_config config_psu = {
+ .elements = FWK_MODULE_DYNAMIC_ELEMENTS(psu_get_element_table),
+};
+
+static const struct fwk_element *psu_optee_regu_get_element_table(fwk_id_t module_id)
+{
+ fwk_assert(fwk_id_get_module_idx(module_id) == FWK_MODULE_IDX_PSU_OPTEE_REGULATOR);
+ return (const struct fwk_element *)psu_optee_regu_elt ;
+}
+
+struct fwk_module_config config_psu_optee_regulator = {
+ .elements = FWK_MODULE_DYNAMIC_ELEMENTS(psu_optee_regu_get_element_table),
+};
+#endif
+
+/*
+ * Indices state when applying agents configuration
+ * @channel_count: Number of channels (mailbox/shmem links) used
+ * @clock_index: Current index for clock and optee/clock (same indices)
+ * @clock_count: Number of clocks (also number of optee/clocks)
+ * @reset_index: Current index for reset controller and optee/reset
+ * @reset_count: Number of reset controller (optee/reset) instances
+ * @regu_index: Current index for voltd and optee/regulator
+ * @regu_count: Number of voltd (optee/regulator) instances
+ * @psu_index: Current index for PSU and optee/PSU instances
+ * @psu_count: Number of PSU (optee/PSU) instances
+ * @dvfs_index: Current index for DVFS instance
+ * @dvfs_count: Number of DVFS instances
+ */
+struct scpfw_resource_counter {
+ size_t channel_count;
+ size_t clock_index;
+ size_t clock_count;
+ size_t reset_index;
+ size_t reset_count;
+ size_t regu_index;
+ size_t regu_count;
+ size_t psu_index;
+ size_t psu_count;
+ size_t dvfs_index;
+ size_t dvfs_count;
+} scpfw_resource_counter;
+
+/*
+ * Count once for all the several instances and allocate global resources.
+ * Global resources are clock, optee/clock, reset, optee/reset, regu,
+ * optee/regu, psu, optee/psu, dvfs, perfd, ...;
+ */
+static void count_resources(struct scpfw_config *cfg)
+{
+ size_t i, j;
+
+ for (i = 0; i < cfg->agent_count; i++) {
+ struct scpfw_agent_config *agent_cfg = cfg->agent_config + i;
+
+ scpfw_resource_counter.channel_count += agent_cfg->channel_count;
+
+ for (j = 0; j < agent_cfg->channel_count; j++) {
+ struct scpfw_channel_config *channel_cfg = agent_cfg->channel_config + j;
+
+ /* Clocks for scmi_clock and for DVFS */
+ scpfw_resource_counter.clock_count += channel_cfg->clock_count;
+ scpfw_resource_counter.clock_count += channel_cfg->perfd_count;
+ /* Reset for smci_reset only */
+ scpfw_resource_counter.reset_count += channel_cfg->reset_count;
+ /* Regulators for smci_voltage_domain only */
+ scpfw_resource_counter.regu_count += channel_cfg->voltd_count;
+ /* DVFS and PSU DVFS only */
+ scpfw_resource_counter.dvfs_count += channel_cfg->perfd_count;
+ scpfw_resource_counter.psu_count += channel_cfg->perfd_count;
+ }
+ }
+
+#ifndef CFG_SCPFW_MOD_CLOCK
+ fwk_assert(!scpfw_resource_counter.clock_count);
+#endif
+#ifndef CFG_SCPFW_MOD_RESET_DOMAIN
+ fwk_assert(!scpfw_resource_counter.reset_count);
+#endif
+#ifndef CFG_SCPFW_MOD_VOLTAGE_DOMAIN
+ fwk_assert(!scpfw_resource_counter.regu_count);
+#endif
+#ifndef CFG_SCPFW_MOD_DVFS
+ fwk_assert(!scpfw_resource_counter.dvfs_count);
+#endif
+#ifndef CFG_SCPFW_MOD_PSU
+ fwk_assert(!scpfw_resource_counter.psu_count);
+#endif
+}
+
+/*
+ * Allocate all tables that may be needed. An optimized implementation would
+ * allocate a single piece of memory and set the pointers accordingly.
+ * */
+static void allocate_global_resources(struct scpfw_config *cfg)
+{
+ struct mod_scmi_reset_domain_config *scmi_reset_config __maybe_unused;
+ struct mod_scmi_voltd_config *scmi_voltd_config __maybe_unused;
+ struct mod_scmi_clock_config *scmi_clock_config __maybe_unused;
+ /* @cfg does not consider agent #0 this the reserved platform/server agent */
+ size_t __maybe_unused scmi_agent_count = cfg->agent_count + 1;
+
+#ifdef CFG_SCPFW_MOD_SCMI_CLOCK
+ /* SCMI clock domains resources */
+ scmi_clk_agent_tbl = fwk_mm_calloc(scmi_agent_count,
+ sizeof(*scmi_clk_agent_tbl));
+ scmi_clock_config = (void *)config_scmi_clock.data;
+ scmi_clock_config->agent_table = scmi_clk_agent_tbl;
+ scmi_clock_config->agent_count = scmi_agent_count;
+#endif
+
+#ifdef CFG_SCPFW_MOD_CLOCK
+ /* Clock domains resources */
+ optee_clock_cfg = fwk_mm_calloc(scpfw_resource_counter.clock_count,
+ sizeof(*optee_clock_cfg));
+ optee_clock_elt = fwk_mm_calloc(scpfw_resource_counter.clock_count + 1,
+ sizeof(*optee_clock_elt));
+
+ clock_data = fwk_mm_calloc(scpfw_resource_counter.clock_count,
+ sizeof(*clock_data));
+ clock_elt = fwk_mm_calloc(scpfw_resource_counter.clock_count + 1,
+ sizeof(*clock_elt));
+#endif
+
+#ifdef CFG_SCPFW_MOD_RESET_DOMAIN
+ /* SCMI reset domains resources */
+ scmi_reset_agent_tbl = fwk_mm_calloc(scmi_agent_count,
+ sizeof(*scmi_reset_agent_tbl));
+ scmi_reset_config = (void *)config_scmi_reset_domain.data;
+ scmi_reset_config->agent_table = scmi_reset_agent_tbl;
+ scmi_reset_config->agent_count = scmi_agent_count;
+
+ optee_reset_data = fwk_mm_calloc(scpfw_resource_counter.reset_count,
+ sizeof(*optee_reset_data));
+ optee_reset_elt = fwk_mm_calloc(scpfw_resource_counter.reset_count + 1,
+ sizeof(*optee_reset_elt));
+
+ reset_data = fwk_mm_calloc(scpfw_resource_counter.reset_count,
+ sizeof(*reset_data));
+ reset_elt = fwk_mm_calloc(scpfw_resource_counter.reset_count + 1,
+ sizeof(*reset_elt));
+#endif
+
+#ifdef CFG_SCPFW_MOD_DVFS
+ /* PSU and related optee PSU regulator resources */
+ psu_optee_regu_elt = fwk_mm_calloc(scpfw_resource_counter.dvfs_count + 1,
+ sizeof(*psu_optee_regu_elt));
+ psu_optee_regu_data = fwk_mm_calloc(scpfw_resource_counter.dvfs_count,
+ sizeof(*psu_optee_regu_data));
+
+ psu_elt = fwk_mm_calloc(scpfw_resource_counter.psu_count + 1,
+ sizeof(*psu_elt));
+ psu_data = fwk_mm_calloc(scpfw_resource_counter.psu_count,
+ sizeof(*psu_data));
+
+ /* DVFS and SCMI performance management resources */
+ dvfs_elt = fwk_mm_calloc(scpfw_resource_counter.dvfs_count + 1,
+ sizeof(*dvfs_elt));
+ dvfs_data = fwk_mm_calloc(scpfw_resource_counter.dvfs_count,
+ sizeof(*dvfs_data));
+
+ scmi_perf_domain_data = fwk_mm_calloc(scpfw_resource_counter.dvfs_count,
+ sizeof(*scmi_perf_domain_data));
+#endif
+
+#ifdef CFG_SCPFW_MOD_VOLTAGE_DOMAIN
+ /* SCMI voltage domains resources */
+ scmi_voltd_agent_tbl = fwk_mm_calloc(scmi_agent_count,
+ sizeof(*scmi_voltd_agent_tbl));
+ scmi_voltd_config = (void *)config_scmi_voltage_domain.data;
+ scmi_voltd_config->agent_table = scmi_voltd_agent_tbl;
+ scmi_voltd_config->agent_count = scmi_agent_count;
+
+ optee_regu_data = fwk_mm_calloc(scpfw_resource_counter.regu_count,
+ sizeof(*optee_regu_data));
+ optee_regu_elt = fwk_mm_calloc(scpfw_resource_counter.regu_count + 1,
+ sizeof(*optee_regu_elt));
+
+ voltd_data = fwk_mm_calloc(scpfw_resource_counter.regu_count,
+ sizeof(*voltd_data));
+ voltd_elt = fwk_mm_calloc(scpfw_resource_counter.regu_count + 1,
+ sizeof(*voltd_elt));
+#endif
+}
+
+static void set_scmi_comm_resources(struct scpfw_config *cfg)
+{
+ unsigned int channel_index;
+ size_t i, j;
+ /* @cfg does not consider agent #0 this the reserved platform/server agent */
+ size_t scmi_agent_count = cfg->agent_count + 1;
+
+ scmi_agent_table = fwk_mm_calloc(scmi_agent_count,
+ sizeof(*scmi_agent_table));
+
+ scmi_service_elt = fwk_mm_calloc(scpfw_resource_counter.channel_count + 1,
+ sizeof(*scmi_service_elt));
+
+ msg_smt_elt = fwk_mm_calloc(scpfw_resource_counter.channel_count + 1,
+ sizeof(*msg_smt_elt));
+ msg_smt_data = fwk_mm_calloc(scpfw_resource_counter.channel_count,
+ sizeof(*msg_smt_data));
+
+ optee_mbx_elt = fwk_mm_calloc(scpfw_resource_counter.channel_count + 1,
+ sizeof(*optee_mbx_elt));
+ optee_mbx_data = fwk_mm_calloc(scpfw_resource_counter.channel_count,
+ sizeof(*optee_mbx_data));
+
+ /* Set now the uniqnue scmi module instance configuration data */
+ scmi_data = (struct mod_scmi_config){
+ .agent_table = scmi_agent_table,
+ .agent_count = scmi_agent_count,
+ .protocol_count_max = 9,
+ .vendor_identifier = "STMicroelectronics",
+ .sub_vendor_identifier = "STMicroelectronics",
+ };
+
+ channel_index = 0;
+
+ for (i = 0; i < cfg->agent_count; i++) {
+ struct scpfw_agent_config *agent_cfg = cfg->agent_config + i;
+ size_t agent_index = i + 1;
+
+ scmi_agent_table[agent_index].type = SCMI_AGENT_TYPE_OSPM;
+ scmi_agent_table[agent_index].name = agent_cfg->name;
+
+ for (j = 0; j < agent_cfg->channel_count; j++) {
+ struct scpfw_channel_config *channel_cfg = agent_cfg->channel_config + j;
+ struct mod_scmi_service_config *service_data;
+
+ service_data = fwk_mm_calloc(1, sizeof(*service_data));
+ *service_data = (struct mod_scmi_service_config){
+ .transport_id = (fwk_id_t)FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_MSG_SMT, 0),
+ .transport_api_id = (fwk_id_t)FWK_ID_API_INIT(FWK_MODULE_IDX_MSG_SMT,
+ MOD_MSG_SMT_API_IDX_SCMI_TRANSPORT),
+ .scmi_agent_id = agent_cfg->agent_id,
+ .scmi_p2a_id = FWK_ID_NONE_INIT,
+ };
+
+ /* Currently expect 1 agent with ID SCMI_AGENT_ID_NSEC0 (1) */
+ fwk_assert(service_data->scmi_agent_id == SCMI_AGENT_ID_NSEC0);
+
+ scmi_service_elt[channel_index].name = channel_cfg->name;
+ scmi_service_elt[channel_index].data = service_data;
+
+ msg_smt_elt[channel_index].name = channel_cfg->name;
+ msg_smt_elt[channel_index].data = (void *)(msg_smt_data + channel_index);
+
+ msg_smt_data[channel_index] = (struct mod_msg_smt_channel_config){
+ .type = MOD_MSG_SMT_CHANNEL_TYPE_REQUESTER,
+ .mailbox_size = 128,
+ .driver_id = (fwk_id_t)FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_OPTEE_MBX,
+ channel_index),
+ .driver_api_id = (fwk_id_t)FWK_ID_API_INIT(FWK_MODULE_IDX_OPTEE_MBX, 0),
+ };
+
+ optee_mbx_elt[channel_index].name = channel_cfg->name;
+ optee_mbx_elt[channel_index].data = (void *)(optee_mbx_data + channel_index);
+
+ optee_mbx_data[channel_index] = (struct mod_optee_mbx_channel_config){
+ .driver_id = (fwk_id_t)FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_MSG_SMT, channel_index),
+ .driver_api_id = (fwk_id_t)FWK_ID_API_INIT(FWK_MODULE_IDX_MSG_SMT,
+ MOD_MSG_SMT_API_IDX_DRIVER_INPUT),
+ };
+
+ channel_index++;
+ }
+ }
+};
+
+static void set_resources(struct scpfw_config *cfg)
+{
+ size_t i, j, k, l __maybe_unused;
+
+ for (i = 0; i < cfg->agent_count; i++) {
+ struct scpfw_agent_config *agent_cfg = cfg->agent_config + i;
+ size_t agent_index = i + 1;
+
+ if (agent_index != agent_cfg->agent_id) {
+ panic("scpfw config expects agent ID is agent index");
+ }
+
+ for (j = 0; j < agent_cfg->channel_count; j++) {
+ struct scpfw_channel_config *channel_cfg = agent_cfg->channel_config + j;
+
+#ifdef CFG_SCPFW_MOD_SCMI_CLOCK
+ /* Add first SCMI clock. We will add later the clocks used for DVFS */
+ if (channel_cfg->clock_count) {
+ size_t clock_index = scpfw_resource_counter.clock_index;
+ struct mod_scmi_clock_device *dev = NULL;
+
+ /* Set SCMI clocks array for the SCMI agent */
+ dev = fwk_mm_calloc(channel_cfg->clock_count,
+ sizeof(struct mod_scmi_clock_device));
+
+ fwk_assert(!scmi_clk_agent_tbl[agent_index].device_table);
+ scmi_clk_agent_tbl[agent_index].device_count = channel_cfg->clock_count;
+ scmi_clk_agent_tbl[agent_index].device_table = dev;
+
+ /* Set clock and optee/clock elements and config data */
+ for (k = 0; k < channel_cfg->clock_count; k++) {
+ struct scmi_clock *clock_cfg = channel_cfg->clock + k;
+
+ dev[k].element_id =
+ (fwk_id_t)FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_CLOCK, clock_index);
+
+ optee_clock_cfg[clock_index].clk = clock_cfg->clk;
+ optee_clock_cfg[clock_index].default_enabled = clock_cfg->enabled;
+
+ optee_clock_elt[clock_index].name = clock_cfg->name;
+ optee_clock_elt[clock_index].data = (void *)(optee_clock_cfg + clock_index);
+
+ clock_data[clock_index] = (struct mod_clock_dev_config){
+ .driver_id = (fwk_id_t)FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_OPTEE_CLOCK,
+ clock_index),
+ .api_id = (fwk_id_t)FWK_ID_API_INIT(FWK_MODULE_IDX_OPTEE_CLOCK,
+ 0),
+ };
+
+ clock_elt[clock_index].name = clock_cfg->name;
+ clock_elt[clock_index].data = (void *)(clock_data + clock_index);
+
+ clock_index++;
+ }
+
+ scpfw_resource_counter.clock_index = clock_index;
+ }
+#endif
+
+#ifdef CFG_SCPFW_MOD_RESET_DOMAIN
+ if (channel_cfg->reset_count) {
+ struct mod_scmi_reset_domain_device *dev = NULL;
+ size_t reset_index = scpfw_resource_counter.reset_index;
+
+ /* Set SCMI reset domains array for the SCMI agent */
+ dev = fwk_mm_calloc(channel_cfg->reset_count, sizeof(*dev));
+
+ fwk_assert(!scmi_reset_agent_tbl[agent_index].device_table);
+ scmi_reset_agent_tbl[agent_index].agent_domain_count = channel_cfg->reset_count;
+ scmi_reset_agent_tbl[agent_index].device_table = dev;
+
+ /* Set reset_domain and optee/reset elements and config data */
+ for (k = 0; k < channel_cfg->reset_count; k++) {
+ struct scmi_reset *reset_cfg = channel_cfg->reset + k;
+
+ dev[k].element_id =
+ (fwk_id_t)FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_RESET_DOMAIN,
+ reset_index);
+
+ optee_reset_data[reset_index].rstctrl = reset_cfg->rstctrl;
+
+ optee_reset_elt[reset_index].name = reset_cfg->name;
+ optee_reset_elt[reset_index].data =
+ (void *)(optee_reset_data + reset_index);
+
+ reset_data[reset_index] = (struct mod_reset_domain_dev_config){
+ .driver_id =
+ (fwk_id_t)FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_OPTEE_RESET,
+ reset_index),
+ .driver_api_id =
+ (fwk_id_t)FWK_ID_API_INIT(FWK_MODULE_IDX_OPTEE_RESET, 0),
+ .modes = MOD_RESET_DOMAIN_AUTO_RESET |
+ MOD_RESET_DOMAIN_MODE_EXPLICIT_ASSERT |
+ MOD_RESET_DOMAIN_MODE_EXPLICIT_DEASSERT,
+ };
+
+ reset_elt[reset_index].name = reset_cfg->name;
+ reset_elt[reset_index].data = (void *)(reset_data + reset_index);
+
+ reset_index++;
+ }
+
+ scpfw_resource_counter.reset_index = reset_index;
+ }
+#endif
+
+#ifdef CFG_SCPFW_MOD_VOLTAGE_DOMAIN
+ if (channel_cfg->voltd_count) {
+ size_t regu_index = scpfw_resource_counter.regu_index;
+ struct mod_scmi_voltd_device *dev = NULL;
+
+ /* Set SCMI voltage domains array for the SCMI agent */
+ dev = fwk_mm_calloc(channel_cfg->voltd_count,
+ sizeof(struct mod_scmi_voltd_device));
+
+ fwk_assert(!scmi_voltd_agent_tbl[agent_index].device_table);
+ scmi_voltd_agent_tbl[agent_index].domain_count = channel_cfg->voltd_count;
+ scmi_voltd_agent_tbl[agent_index].device_table = dev;
+
+ /* Set voltage_domain and optee/regu elements and config data */
+ for (k = 0; k < channel_cfg->voltd_count; k++) {
+ struct scmi_voltd *voltd_cfg = channel_cfg->voltd + k;
+ static const char reserved[] = "reserved";
+ const char *name = NULL;
+
+ if (voltd_cfg->rdev) {
+ name = voltd_cfg->rdev->reg_name;
+ } else {
+ name = reserved;
+ }
+
+ dev[regu_index].element_id =
+ (fwk_id_t)FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_VOLTAGE_DOMAIN, k);
+
+ optee_regu_elt[regu_index].name = name;
+ optee_regu_elt[regu_index].data = (void *)(optee_regu_data + regu_index);
+ optee_regu_data[regu_index].rdev = voltd_cfg->rdev;
+ optee_regu_data[regu_index].default_enabled = voltd_cfg->enabled;
+
+ voltd_data[regu_index].driver_id =
+ (fwk_id_t)FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_STM32_REGU_CONSUMER,
+ regu_index);
+ voltd_data[regu_index].api_id =
+ (fwk_id_t)FWK_ID_API_INIT(FWK_MODULE_IDX_STM32_REGU_CONSUMER, 0);
+
+ voltd_elt[regu_index].name = name;
+ voltd_elt[regu_index].data = (void *)(voltd_data + regu_index);
+ regu_index++;
+ }
+
+ scpfw_resource_counter.regu_index = regu_index;
+ }
+#endif
+
+#ifdef CFG_SCPFW_MOD_DVFS
+ if (channel_cfg->perfd_count) {
+ size_t clock_index = scpfw_resource_counter.clock_index;
+ size_t psu_index = scpfw_resource_counter.psu_index;
+ size_t dvfs_index = scpfw_resource_counter.dvfs_index;
+
+ for (k = 0; k < channel_cfg->perfd_count; k++) {
+ struct mod_scmi_perf_config *scmi_perf_data = NULL;
+ struct scmi_perfd *perfd_cfg = channel_cfg->perfd + k;
+
+ /*
+ * DVFS with SCMI performance management domains
+ * 1 initial scmi_perf instance defines the number of DVFS's
+ * For each DVFS instance:
+ * - 1 instance (elt/config) of dvfs, psu, optee/psu, clock, optee/clock
+ * Clocks and optee/clocks are already allocated but not yet set.
+ */
+
+ /* scmi_perf: data defines the DVFS domains indices */
+ scmi_perf_domain_data[dvfs_index] = (struct mod_scmi_perf_domain_config){ };
+
+ scmi_perf_data = (void *)config_scmi_perf.data;
+
+ scmi_perf_data[dvfs_index].domains = (void *)scmi_perf_domain_data;
+ scmi_perf_data[dvfs_index].perf_doms_count = scpfw_resource_counter.dvfs_count;
+ scmi_perf_data[dvfs_index].fast_channels_alarm_id = (fwk_id_t)FWK_ID_NONE_INIT;
+#ifdef BUILD_HAS_MOD_STATISTICS
+ scmi_perf_data[dvfs_index].stats_enabled = true;
+#endif
+
+ /* dvfs instances: 1 instance per expose DVFS service */
+ dvfs_data[dvfs_index].psu_id =
+ (fwk_id_t)FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_PSU, psu_index);
+ dvfs_data[dvfs_index].clock_id =
+ (fwk_id_t)FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_CLOCK, clock_index);
+ dvfs_data[dvfs_index].latency = 0; /* not set, used for async access */
+ dvfs_data[dvfs_index].opps =
+ fwk_mm_calloc(perfd_cfg->dvfs_opp_count,
+ sizeof(struct mod_dvfs_opp));
+
+ for (l = 0; l < perfd_cfg->dvfs_opp_count; l++) {
+ uint64_t power = 0;
+
+ /* Quick estimation of power consumpsion */
+ power = perfd_cfg->dvfs_opp_khz[l];
+ power *= perfd_cfg->dvfs_opp_mv[l];
+ power *= perfd_cfg->dvfs_opp_mv[l];
+ power /= 100 * 1000 * 1000;
+
+ dvfs_data[dvfs_index].opps[l] = (struct mod_dvfs_opp){
+ .level = perfd_cfg->dvfs_opp_khz[l] * 1000UL,
+ .frequency = perfd_cfg->dvfs_opp_khz[l],
+ .voltage = perfd_cfg->dvfs_opp_mv[l],
+ .power = (uint32_t)power,
+ };
+ }
+
+ dvfs_elt[dvfs_index].name = perfd_cfg->name;
+ dvfs_elt[dvfs_index].data = (void *)(dvfs_data + dvfs_index);
+
+ /* Module psu_optee module (elements and configuration data) */
+ psu_optee_regu_elt[psu_index].name = perfd_cfg->rdev->reg_name;
+ psu_optee_regu_elt[psu_index].sub_element_count = scpfw_resource_counter.psu_count;
+ psu_optee_regu_elt[psu_index].data = (void *)(psu_optee_regu_data + psu_index);
+
+ psu_optee_regu_data[psu_index].rdev = perfd_cfg->rdev;
+
+ /* Module psu (elements and configuration data) */
+ psu_elt[psu_index].name = perfd_cfg->rdev->reg_name;
+ psu_elt[psu_index].data = (void *)(psu_data + psu_index);
+ psu_data[psu_index].driver_id =
+ (fwk_id_t)FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_PSU_OPTEE_REGULATOR, psu_index);
+ psu_data[psu_index].driver_api_id =
+ (fwk_id_t)FWK_ID_API_INIT(FWK_MODULE_IDX_PSU_OPTEE_REGULATOR, 0);
+
+ /* Module clock and optee_clock */
+ fwk_assert(!clock_elt[clock_index].data);
+
+ clock_elt[clock_index].name = perfd_cfg->clk->name;
+ clock_elt[clock_index].data = (void *)(clock_data + clock_index);
+
+ clock_data[clock_index] = (struct mod_clock_dev_config){
+ .driver_id = (fwk_id_t)FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_OPTEE_CLOCK,
+ clock_index),
+ .api_id = (fwk_id_t)FWK_ID_API_INIT(FWK_MODULE_IDX_OPTEE_CLOCK,
+ 0),
+ };
+
+ optee_clock_cfg[clock_index].clk = perfd_cfg->clk;
+ optee_clock_cfg[clock_index].default_enabled = false;
+
+ optee_clock_elt[clock_index].name = perfd_cfg->clk->name;
+ optee_clock_elt[clock_index].data = (void *)(optee_clock_cfg + clock_index);
+
+ clock_index++;
+ psu_index++;
+ dvfs_index++;
+ }
+
+ scpfw_resource_counter.clock_index = clock_index;
+ scpfw_resource_counter.psu_index = psu_index;
+ scpfw_resource_counter.dvfs_index = dvfs_index;
+ }
+#endif
+ }
+ }
+}
+
+void scpfw_configure(struct scpfw_config *cfg)
+{
+ count_resources(cfg);
+ allocate_global_resources(cfg);
+ set_scmi_comm_resources(cfg);
+ set_resources(cfg);
+}
diff --git a/product/optee-stm32mp1/fw/config_mbx_smt.c b/product/optee-stm32mp1/fw/config_mbx_smt.c
deleted file mode 100644
index 21d606d7..00000000
--- a/product/optee-stm32mp1/fw/config_mbx_smt.c
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Arm SCP/MCP Software
- * Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#include <arch_main.h>
-#include <fwk_element.h>
-#include <fwk_id.h>
-#include <fwk_module.h>
-#include <fwk_module_idx.h>
-
-#include <mod_optee_mbx.h>
-#include <mod_optee_smt.h>
-#include <scmi_agents.h>
-
-#include <stdint.h>
-
-#define OSPM0_SMT_MAILBOX_PA 0x2ffff000
-#define OSPM0_SMT_MAILBOX_SIZE SCMI_SHMEM_SIZE
-
-static const struct fwk_element mbx_element_table[] = {
- [SCMI_CHANNEL_DEVICE_IDX_NS0] = {
- .name = "SCMI non-secure to OP-TEE channel 0",
- .data = &((struct mod_optee_mbx_channel_config){
- .driver_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_OPTEE_SMT, 0),
- .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_OPTEE_SMT,
- MOD_OPTEE_SMT_API_IDX_DRIVER_INPUT)
- })
- },
- [SCMI_CHANNEL_DEVICE_IDX_COUNT] = { 0 },
-};
-
-static const struct fwk_element *mbx_get_element_table(fwk_id_t module_id)
-{
- return (const struct fwk_element *)mbx_element_table;
-}
-
-struct fwk_module_config config_optee_mbx = {
- .elements = FWK_MODULE_DYNAMIC_ELEMENTS(mbx_get_element_table),
-};
-
-static struct fwk_element smt_elt_table[] = {
- [0] = {
- .name = "OSPM0",
- .data = &((struct mod_optee_smt_channel_config) {
- .type = MOD_OPTEE_SMT_CHANNEL_TYPE_REQUESTER,
- .mailbox_address = OSPM0_SMT_MAILBOX_PA,
- .mailbox_size = OSPM0_SMT_MAILBOX_SIZE,
- .driver_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_OPTEE_MBX,
- SCMI_CHANNEL_DEVICE_IDX_NS0),
- .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_OPTEE_MBX, 0),
- })
- },
- [1] = { 0 },
-};
-
-static const struct fwk_element *smt_get_element_table(fwk_id_t module_id)
-{
- fwk_assert(fwk_id_get_module_idx(module_id) == FWK_MODULE_IDX_OPTEE_SMT);
-
- return (const struct fwk_element *)smt_elt_table;
-}
-
-struct fwk_module_config config_optee_smt = {
- .elements = FWK_MODULE_DYNAMIC_ELEMENTS(smt_get_element_table),
-};
diff --git a/product/optee-stm32mp1/fw/config_scmi.c b/product/optee-stm32mp1/fw/config_scmi.c
deleted file mode 100644
index 4f3442cc..00000000
--- a/product/optee-stm32mp1/fw/config_scmi.c
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Arm SCP/MCP Software
- * Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#include <fwk_element.h>
-#include <fwk_id.h>
-#include <fwk_macros.h>
-#include <fwk_log.h>
-#include <fwk_module.h>
-#include <fwk_module_idx.h>
-
-#include <internal/scmi.h>
-#include <mod_optee_smt.h>
-#include <mod_scmi.h>
-#include <scmi_agents.h>
-
-static const struct fwk_element service_table[] = {
- [SCMI_SERVICE_IDX_NS_CHANNEL0] = {
- .name = "service-0",
- .data = &((struct mod_scmi_service_config) {
- .transport_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_OPTEE_SMT, 0),
- .transport_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_OPTEE_SMT,
- MOD_OPTEE_SMT_API_IDX_SCMI_TRANSPORT),
- .scmi_agent_id = SCMI_AGENT_ID_NSEC0,
- .scmi_p2a_id = FWK_ID_NONE_INIT,
- }),
- },
- [SCMI_SERVICE_IDX_COUNT] = { 0 }
-};
-
-static const struct fwk_element *get_scmi_service_table(fwk_id_t module_id)
-{
- return service_table;
-}
-
-static const struct mod_scmi_agent agent_table[] = {
- [SCMI_AGENT_ID_NSEC0] = {
- .type = SCMI_AGENT_TYPE_OSPM,
- .name = "OSPM0",
- },
-};
-
-struct fwk_module_config config_scmi = {
- .data = &((struct mod_scmi_config) {
- .protocol_count_max = 9,
- .agent_count = FWK_ARRAY_SIZE(agent_table) - 1,
- .agent_table = agent_table,
- .vendor_identifier = "Linaro",
- .sub_vendor_identifier = "PMWG",
- }),
- .elements = FWK_MODULE_DYNAMIC_ELEMENTS(get_scmi_service_table),
-};
diff --git a/product/optee-stm32mp1/fw/config_scmi_clocks.c b/product/optee-stm32mp1/fw/config_scmi_clocks.c
deleted file mode 100644
index 478ae588..00000000
--- a/product/optee-stm32mp1/fw/config_scmi_clocks.c
+++ /dev/null
@@ -1,254 +0,0 @@
-/*
- * Arm SCP/MCP Software
- * Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#include <fwk_element.h>
-#include <fwk_id.h>
-#include <fwk_module.h>
-#include <fwk_module_idx.h>
-
-#include <mod_clock.h>
-#include <mod_optee_clock.h>
-#include <mod_scmi_clock.h>
-#include <scmi_agents.h>
-
-#include <assert.h>
-#include <stddef.h>
-#include <stdint.h>
-
-#include <dt-bindings/clock/stm32mp1-clks.h>
-#include <stm32_util.h>
-#include <util.h>
-
-/*
- * Indices of clock elements exposed through a SCMI agent.
- * As all exposed SCMI clocks relate to a single backend dirver
- * these indices are used as indices for fwk elements for modules
- * CLOCK and STM32_CLOCK. Note these are not the clock ID values
- * exposed through SCMI.
- */
-enum clock_elt_idx {
- /* Clocks exposed to agent SCMI */
- CLK_IDX_SCMI_HSE,
- CLK_IDX_SCMI_HSI,
- CLK_IDX_SCMI_CSI,
- CLK_IDX_SCMI_LSE,
- CLK_IDX_SCMI_LSI,
- CLK_IDX_SCMI_PLL2_Q,
- CLK_IDX_SCMI_PLL2_R,
- CLK_IDX_SCMI_MPU,
- CLK_IDX_SCMI_AXI,
- CLK_IDX_SCMI_BSEC,
- CLK_IDX_SCMI_CRYP1,
- CLK_IDX_SCMI_GPIOZ,
- CLK_IDX_SCMI_HASH1,
- CLK_IDX_SCMI_I2C4,
- CLK_IDX_SCMI_I2C6,
- CLK_IDX_SCMI_IWDG1,
- CLK_IDX_SCMI_RNG1,
- CLK_IDX_SCMI_RTC,
- CLK_IDX_SCMI_RTCAPB,
- CLK_IDX_SCMI_SPI6,
- CLK_IDX_SCMI_USART1,
- /* Count indices */
- CLK_IDX_COUNT
-};
-
-struct mod_stm32_clock_dev_config {
- const char *name;
- unsigned long rcc_clk_id;
- bool default_enabled;
-};
-
-/*
- * stm32_clock_cfg - Common configuration for exposed SCMI clocks
- *
- * Clock name defined here is used for all CLOCK and STM32_CLOCK
- * fwk elements names.
- */
-#define STM32_CLOCK_CFG(_idx, _rcc_clk_id, _name, _default_enabled) \
- [(_idx)] = { \
- .rcc_clk_id = (_rcc_clk_id), \
- .name = (_name), \
- .default_enabled = (_default_enabled), \
- }
-
-static const struct mod_stm32_clock_dev_config stm32_clock_cfg[] = {
- STM32_CLOCK_CFG(CLK_IDX_SCMI_HSE, CK_HSE, "ck_hse", true),
- STM32_CLOCK_CFG(CLK_IDX_SCMI_HSI, CK_HSI, "ck_hsi", true),
- STM32_CLOCK_CFG(CLK_IDX_SCMI_CSI, CK_CSI, "ck_csi", true),
- STM32_CLOCK_CFG(CLK_IDX_SCMI_LSE, CK_LSE, "ck_lse", true),
- STM32_CLOCK_CFG(CLK_IDX_SCMI_LSI, CK_LSI, "ck_lsi", true),
- STM32_CLOCK_CFG(CLK_IDX_SCMI_PLL2_Q, PLL2_Q, "pll2_q", true),
- STM32_CLOCK_CFG(CLK_IDX_SCMI_PLL2_R, PLL2_R, "pll2_r", true),
- STM32_CLOCK_CFG(CLK_IDX_SCMI_MPU, CK_MCU, "ck_mpu", true),
- STM32_CLOCK_CFG(CLK_IDX_SCMI_AXI, CK_AXI, "ck_axi", true),
- STM32_CLOCK_CFG(CLK_IDX_SCMI_BSEC, BSEC, "bsec", false),
- STM32_CLOCK_CFG(CLK_IDX_SCMI_CRYP1, CRYP1, "cryp1", false),
- STM32_CLOCK_CFG(CLK_IDX_SCMI_GPIOZ, GPIOZ, "gpioz", false),
- STM32_CLOCK_CFG(CLK_IDX_SCMI_HASH1, HASH1, "hash1", false),
- STM32_CLOCK_CFG(CLK_IDX_SCMI_I2C4, I2C4_K, "i2c4_k", false),
- STM32_CLOCK_CFG(CLK_IDX_SCMI_I2C6, I2C6_K, "i2c6_k", false),
- STM32_CLOCK_CFG(CLK_IDX_SCMI_IWDG1, IWDG1, "iwdg1", false),
- STM32_CLOCK_CFG(CLK_IDX_SCMI_RNG1, RNG1_K, "rng1_k", true),
- STM32_CLOCK_CFG(CLK_IDX_SCMI_RTC, RTC, "ck_rtc", true),
- STM32_CLOCK_CFG(CLK_IDX_SCMI_RTCAPB, RTCAPB, "rtcapb", true),
- STM32_CLOCK_CFG(CLK_IDX_SCMI_SPI6, SPI6_K, "spi6_k", false),
- STM32_CLOCK_CFG(CLK_IDX_SCMI_USART1, USART1_K, "usart1_k", false),
-};
-
-/*
- * Bindgins between SCMI clock_id value and clock module element in fwk
- */
-#define SCMI_CLOCK_ELT_ID(_idx) \
- { .element_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_CLOCK, (_idx)) }
-
-static struct mod_scmi_clock_device scmi_clock_device[] = {
- [CK_SCMI_HSE] = SCMI_CLOCK_ELT_ID(CLK_IDX_SCMI_HSE),
- [CK_SCMI_HSI] = SCMI_CLOCK_ELT_ID(CLK_IDX_SCMI_HSI),
- [CK_SCMI_CSI] = SCMI_CLOCK_ELT_ID(CLK_IDX_SCMI_CSI),
- [CK_SCMI_LSE] = SCMI_CLOCK_ELT_ID(CLK_IDX_SCMI_LSE),
- [CK_SCMI_LSI] = SCMI_CLOCK_ELT_ID(CLK_IDX_SCMI_LSI),
- [CK_SCMI_PLL2_Q] = SCMI_CLOCK_ELT_ID(CLK_IDX_SCMI_PLL2_Q),
- [CK_SCMI_PLL2_R] = SCMI_CLOCK_ELT_ID(CLK_IDX_SCMI_PLL2_R),
- [CK_SCMI_MPU] = SCMI_CLOCK_ELT_ID(CLK_IDX_SCMI_MPU),
- [CK_SCMI_AXI] = SCMI_CLOCK_ELT_ID(CLK_IDX_SCMI_AXI),
- [CK_SCMI_BSEC] = SCMI_CLOCK_ELT_ID(CLK_IDX_SCMI_BSEC),
- [CK_SCMI_CRYP1] = SCMI_CLOCK_ELT_ID(CLK_IDX_SCMI_CRYP1),
- [CK_SCMI_GPIOZ] = SCMI_CLOCK_ELT_ID(CLK_IDX_SCMI_GPIOZ),
- [CK_SCMI_HASH1] = SCMI_CLOCK_ELT_ID(CLK_IDX_SCMI_HASH1),
- [CK_SCMI_I2C4] = SCMI_CLOCK_ELT_ID(CLK_IDX_SCMI_I2C4),
- [CK_SCMI_I2C6] = SCMI_CLOCK_ELT_ID(CLK_IDX_SCMI_I2C6),
- [CK_SCMI_IWDG1] = SCMI_CLOCK_ELT_ID(CLK_IDX_SCMI_IWDG1),
- [CK_SCMI_RNG1] = SCMI_CLOCK_ELT_ID(CLK_IDX_SCMI_RNG1),
- [CK_SCMI_RTC] = SCMI_CLOCK_ELT_ID(CLK_IDX_SCMI_RTC),
- [CK_SCMI_RTCAPB] = SCMI_CLOCK_ELT_ID(CLK_IDX_SCMI_RTCAPB),
- [CK_SCMI_SPI6] = SCMI_CLOCK_ELT_ID(CLK_IDX_SCMI_SPI6),
- [CK_SCMI_USART1] = SCMI_CLOCK_ELT_ID(CLK_IDX_SCMI_USART1),
-};
-
-/* Agents and clocks references */
-static const struct mod_scmi_clock_agent clk_agent_tbl[SCMI_AGENT_ID_COUNT] = {
- [SCMI_AGENT_ID_NSEC0] = {
- .device_table = (void *)scmi_clock_device,
- .device_count = FWK_ARRAY_SIZE(scmi_clock_device),
- },
-};
-
-/* Exported configuration data for module SCMI_CLOCK */
-struct fwk_module_config config_scmi_clock = {
- .data = &((struct mod_scmi_clock_config){
- .agent_table = clk_agent_tbl,
- .agent_count = FWK_ARRAY_SIZE(clk_agent_tbl),
- }),
-};
-
-/*
- * Clock backend driver configuration
- * STM32_CLOCK element index is the related CLOCK element index.
- */
-#define CLOCK_DATA(_idx) ((struct mod_clock_dev_config){ \
- .driver_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_OPTEE_CLOCK, \
- (_idx)), \
- .api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_OPTEE_CLOCK, 0), \
- })
-
-#define CLOCK_ELT(_idx) [(_idx)] = { \
- .name = stm32_clock_cfg[(_idx)].name, \
- .data = &CLOCK_DATA((_idx)), \
- }
-
-/* Element names are the clock names exposed by the SCMI service */
-static struct fwk_element clock_elt[] = {
- /* Clocks exposed to agent SCMI */
- CLOCK_ELT(CLK_IDX_SCMI_HSE),
- CLOCK_ELT(CLK_IDX_SCMI_HSI),
- CLOCK_ELT(CLK_IDX_SCMI_CSI),
- CLOCK_ELT(CLK_IDX_SCMI_LSE),
- CLOCK_ELT(CLK_IDX_SCMI_LSI),
- CLOCK_ELT(CLK_IDX_SCMI_PLL2_Q),
- CLOCK_ELT(CLK_IDX_SCMI_PLL2_R),
- CLOCK_ELT(CLK_IDX_SCMI_MPU),
- CLOCK_ELT(CLK_IDX_SCMI_AXI),
- CLOCK_ELT(CLK_IDX_SCMI_BSEC),
- CLOCK_ELT(CLK_IDX_SCMI_CRYP1),
- CLOCK_ELT(CLK_IDX_SCMI_GPIOZ),
- CLOCK_ELT(CLK_IDX_SCMI_HASH1),
- CLOCK_ELT(CLK_IDX_SCMI_I2C4),
- CLOCK_ELT(CLK_IDX_SCMI_I2C6),
- CLOCK_ELT(CLK_IDX_SCMI_IWDG1),
- CLOCK_ELT(CLK_IDX_SCMI_RNG1),
- CLOCK_ELT(CLK_IDX_SCMI_RTC),
- CLOCK_ELT(CLK_IDX_SCMI_RTCAPB),
- CLOCK_ELT(CLK_IDX_SCMI_SPI6),
- CLOCK_ELT(CLK_IDX_SCMI_USART1),
- /* Termination entry */
- [CLK_IDX_COUNT] = { 0 }
-};
-
-static_assert(FWK_ARRAY_SIZE(clock_elt) == CLK_IDX_COUNT + 1,
- "Invalid range for CLOCK and STM32_CLOCK indices");
-
-/* Exported configuration data for module VOLTAGE_DOMAIN */
-const struct fwk_module_config config_clock = {
- .elements = FWK_MODULE_STATIC_ELEMENTS_PTR(clock_elt),
-};
-
-#define CLOCK_COUNT FWK_ARRAY_SIZE(stm32_clock_cfg)
-static struct mod_optee_clock_config optee_clock_cfg[CLOCK_COUNT];
-
-#define OPTEE_CLOCK_ELT(_idx) \
- [(_idx)] = { \
- .name = stm32_clock_cfg[(_idx)].name, \
- .data = &optee_clock_cfg[(_idx)], \
- }
-
-static const struct fwk_element optee_clock_elt[] = {
- /* Clocks exposed to agent SCMI */
- OPTEE_CLOCK_ELT(CLK_IDX_SCMI_HSE),
- OPTEE_CLOCK_ELT(CLK_IDX_SCMI_HSI),
- OPTEE_CLOCK_ELT(CLK_IDX_SCMI_CSI),
- OPTEE_CLOCK_ELT(CLK_IDX_SCMI_LSE),
- OPTEE_CLOCK_ELT(CLK_IDX_SCMI_LSI),
- OPTEE_CLOCK_ELT(CLK_IDX_SCMI_PLL2_Q),
- OPTEE_CLOCK_ELT(CLK_IDX_SCMI_PLL2_R),
- OPTEE_CLOCK_ELT(CLK_IDX_SCMI_MPU),
- OPTEE_CLOCK_ELT(CLK_IDX_SCMI_AXI),
- OPTEE_CLOCK_ELT(CLK_IDX_SCMI_BSEC),
- OPTEE_CLOCK_ELT(CLK_IDX_SCMI_CRYP1),
- OPTEE_CLOCK_ELT(CLK_IDX_SCMI_GPIOZ),
- OPTEE_CLOCK_ELT(CLK_IDX_SCMI_HASH1),
- OPTEE_CLOCK_ELT(CLK_IDX_SCMI_I2C4),
- OPTEE_CLOCK_ELT(CLK_IDX_SCMI_I2C6),
- OPTEE_CLOCK_ELT(CLK_IDX_SCMI_IWDG1),
- OPTEE_CLOCK_ELT(CLK_IDX_SCMI_RNG1),
- OPTEE_CLOCK_ELT(CLK_IDX_SCMI_RTC),
- OPTEE_CLOCK_ELT(CLK_IDX_SCMI_RTCAPB),
- OPTEE_CLOCK_ELT(CLK_IDX_SCMI_SPI6),
- OPTEE_CLOCK_ELT(CLK_IDX_SCMI_USART1),
- /* Termination entry */
- [CLK_IDX_COUNT] = { 0 }
-};
-
-static_assert(FWK_ARRAY_SIZE(optee_clock_elt) == CLK_IDX_COUNT + 1,
- "Invalid range for CLOCK and STM32_CLOCK indices");
-
-static const struct fwk_element *optee_clock_get_elt_table(fwk_id_t module_id)
-{
- size_t n;
-
- for (n = 0; n < FWK_ARRAY_SIZE(optee_clock_cfg); n++) {
- optee_clock_cfg[n].clk =
- stm32mp_rcc_clock_id_to_clk(stm32_clock_cfg[n].rcc_clk_id);
- optee_clock_cfg[n].default_enabled = stm32_clock_cfg[n].default_enabled;
- }
-
- return optee_clock_elt;
-}
-
-struct fwk_module_config config_optee_clock = {
- .elements = FWK_MODULE_DYNAMIC_ELEMENTS(optee_clock_get_elt_table),
-};
diff --git a/product/optee-stm32mp1/fw/config_scmi_reset_domains.c b/product/optee-stm32mp1/fw/config_scmi_reset_domains.c
deleted file mode 100644
index bb9794d6..00000000
--- a/product/optee-stm32mp1/fw/config_scmi_reset_domains.c
+++ /dev/null
@@ -1,204 +0,0 @@
-/*
- * Arm SCP/MCP Software
- * Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#include <fwk_macros.h>
-#include <fwk_module.h>
-#include <fwk_module_idx.h>
-
-#include <mod_reset_domain.h>
-#include <mod_scmi_reset_domain.h>
-#include <mod_optee_reset.h>
-
-#include <assert.h>
-#include <dt-bindings/reset/stm32mp1-resets.h>
-#include <scmi_agents.h>
-#include <stm32_util.h>
-#include <util.h>
-
-/*
- * Indices of reset domain elements exposed through a SCMI agent.
- * As all exposed SCMI reset domains relate to a single backend dirver
- * these indices are used as indices for fwk elements for modules
- * RESET_DOMAIN and STM32_RESET.
- */
-enum resetd_elt_idx {
- /* Reset domain exposed to agent SCMI */
- RESETD_IDX_SCMI_SPI6,
- RESETD_IDX_SCMI_I2C4,
- RESETD_IDX_SCMI_I2C6,
- RESETD_IDX_SCMI_USART1,
- RESETD_IDX_SCMI_STGEN,
- RESETD_IDX_SCMI_GPIOZ,
- RESETD_IDX_SCMI_CRYP1,
- RESETD_IDX_SCMI_HASH1,
- RESETD_IDX_SCMI_RNG1,
- RESETD_IDX_SCMI_MDMA,
- RESETD_IDX_SCMI_MCU,
- RESETD_IDX_SCMI_MCU_HOLD_BOOT,
- RESETD_IDX_COUNT
-};
-
-struct mod_stm32_reset_dev_config {
- const char *name;
- unsigned long rcc_rst_id;
-};
-
-/*
- * stm32_resetd_cfg - Common configuration for exposed SCMI reset domains
- *
- * Domain names defined here are used for all RESET_DOMAIN and STM32_RESET
- * fwk elements names.
- */
-#define STM32_RESET_CFG(_idx, _rcc_rst_id, _name) \
- [(_idx)] = { .rcc_rst_id = (_rcc_rst_id), .name = (_name) }
-
-static const struct mod_stm32_reset_dev_config stm32_resetd_cfg[] = {
- STM32_RESET_CFG(RESETD_IDX_SCMI_SPI6, SPI6_R, "spi6"),
- STM32_RESET_CFG(RESETD_IDX_SCMI_I2C4, I2C4_R, "i2c4"),
- STM32_RESET_CFG(RESETD_IDX_SCMI_I2C6, I2C6_R, "i2c6"),
- STM32_RESET_CFG(RESETD_IDX_SCMI_USART1, USART1_R, "usart1"),
- STM32_RESET_CFG(RESETD_IDX_SCMI_STGEN, STGEN_R, "stgen"),
- STM32_RESET_CFG(RESETD_IDX_SCMI_GPIOZ, GPIOZ_R, "gpioz"),
- STM32_RESET_CFG(RESETD_IDX_SCMI_CRYP1, CRYP1_R, "cryp1"),
- STM32_RESET_CFG(RESETD_IDX_SCMI_HASH1, HASH1_R, "hash1"),
- STM32_RESET_CFG(RESETD_IDX_SCMI_RNG1, RNG1_R, "rng1"),
- STM32_RESET_CFG(RESETD_IDX_SCMI_MDMA, MDMA_R, "mdma"),
- STM32_RESET_CFG(RESETD_IDX_SCMI_MCU, MCU_R, "mcu"),
- STM32_RESET_CFG(RESETD_IDX_SCMI_MCU_HOLD_BOOT, MCU_HOLD_BOOT_R, "mcu-hold-boot"),
-};
-
-/*
- * Bindgins between SCMI domain_id value and reset domain module element in fwk
- */
-#define SCMI_RESETD_ELT_ID(_idx) \
- { .element_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_RESET_DOMAIN, (_idx)) }
-
-static const struct mod_scmi_reset_domain_device scmi_resetd_device[] = {
- [RST_SCMI_SPI6] = SCMI_RESETD_ELT_ID(RESETD_IDX_SCMI_SPI6),
- [RST_SCMI_I2C4] = SCMI_RESETD_ELT_ID(RESETD_IDX_SCMI_I2C4),
- [RST_SCMI_I2C6] = SCMI_RESETD_ELT_ID(RESETD_IDX_SCMI_I2C6),
- [RST_SCMI_USART1] = SCMI_RESETD_ELT_ID(RESETD_IDX_SCMI_USART1),
- [RST_SCMI_STGEN] = SCMI_RESETD_ELT_ID(RESETD_IDX_SCMI_STGEN),
- [RST_SCMI_GPIOZ] = SCMI_RESETD_ELT_ID(RESETD_IDX_SCMI_GPIOZ),
- [RST_SCMI_CRYP1] = SCMI_RESETD_ELT_ID(RESETD_IDX_SCMI_CRYP1),
- [RST_SCMI_HASH1] = SCMI_RESETD_ELT_ID(RESETD_IDX_SCMI_HASH1),
- [RST_SCMI_RNG1] = SCMI_RESETD_ELT_ID(RESETD_IDX_SCMI_RNG1),
- [RST_SCMI_MDMA] = SCMI_RESETD_ELT_ID(RESETD_IDX_SCMI_MDMA),
- [RST_SCMI_MCU] = SCMI_RESETD_ELT_ID(RESETD_IDX_SCMI_MCU),
- [RST_SCMI_MCU_HOLD_BOOT] = SCMI_RESETD_ELT_ID(RESETD_IDX_SCMI_MCU_HOLD_BOOT),
-};
-
-/* Agents andreset domains references */
-static const struct mod_scmi_reset_domain_agent resetd_agent_table[SCMI_AGENT_ID_COUNT] = {
- [SCMI_AGENT_ID_NSEC0] = {
- .device_table = (void *)scmi_resetd_device,
- .agent_domain_count = FWK_ARRAY_SIZE(scmi_resetd_device),
- },
-};
-
-/* Exported configuration data for module SCMI_RESET_DOMAIN */
-struct fwk_module_config config_scmi_reset_domain = {
- .data = &((struct mod_scmi_reset_domain_config){
- .agent_table = resetd_agent_table,
- .agent_count = FWK_ARRAY_SIZE(resetd_agent_table),
- }),
-};
-
-/*
- * Reset controller backend driver configuration
- * STM32_RESET element index is the related RESET_DOMAIN element index.
- */
-#define RESETD_DATA(_idx) ((struct mod_reset_domain_dev_config){ \
- .driver_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_OPTEE_RESET, (_idx)), \
- .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_OPTEE_RESET, 0), \
- .modes = MOD_RESET_DOMAIN_AUTO_RESET | \
- MOD_RESET_DOMAIN_MODE_EXPLICIT_ASSERT | \
- MOD_RESET_DOMAIN_MODE_EXPLICIT_DEASSERT, \
- .capabilities = 0, /* No notif, no async */ \
- })
-
-
-#define RESETD_ELT(_idx) [(_idx)] = { \
- .name = stm32_resetd_cfg[(_idx)].name, \
- .data = &RESETD_DATA((_idx)), \
- }
-
-/* Element names are the reset domain names exposed by the SCMI service */
-static const struct fwk_element resetd_elt[] = {
- /* Reset domains exposed to agent SCMI */
- RESETD_ELT(RESETD_IDX_SCMI_SPI6),
- RESETD_ELT(RESETD_IDX_SCMI_I2C4),
- RESETD_ELT(RESETD_IDX_SCMI_I2C6),
- RESETD_ELT(RESETD_IDX_SCMI_USART1),
- RESETD_ELT(RESETD_IDX_SCMI_STGEN),
- RESETD_ELT(RESETD_IDX_SCMI_GPIOZ),
- RESETD_ELT(RESETD_IDX_SCMI_CRYP1),
- RESETD_ELT(RESETD_IDX_SCMI_HASH1),
- RESETD_ELT(RESETD_IDX_SCMI_RNG1),
- RESETD_ELT(RESETD_IDX_SCMI_MDMA),
- RESETD_ELT(RESETD_IDX_SCMI_MCU),
- RESETD_ELT(RESETD_IDX_SCMI_MCU_HOLD_BOOT),
- /* Termination entry */
- [RESETD_IDX_COUNT] = { 0 }
-};
-
-static_assert(FWK_ARRAY_SIZE(resetd_elt) == RESETD_IDX_COUNT + 1,
- "Invalid range for RESET_DOMAIN and STM32_RESET indices");
-
-/* Exported configuration data for module VOLTAGE_DOMAIN */
-const struct fwk_module_config config_reset_domain = {
- .elements = FWK_MODULE_STATIC_ELEMENTS_PTR(resetd_elt),
-};
-
-/*
- * Configuration for module OPTEE_RESET
- */
-#define RESET_COUNT FWK_ARRAY_SIZE(stm32_resetd_cfg)
-static struct mod_optee_reset_dev_config optee_reset_cfg[RESET_COUNT];
-
-#define OPTEE_RESET_ELT(_idx) \
- [(_idx)] = { \
- .name = stm32_resetd_cfg[(_idx)].name, \
- .data = &optee_reset_cfg[(_idx)], \
- }
-
-static const struct fwk_element optee_reset_elt[] = {
- /* Reset domaines exposed to agent SCMI */
- OPTEE_RESET_ELT(RESETD_IDX_SCMI_SPI6),
- OPTEE_RESET_ELT(RESETD_IDX_SCMI_I2C4),
- OPTEE_RESET_ELT(RESETD_IDX_SCMI_I2C6),
- OPTEE_RESET_ELT(RESETD_IDX_SCMI_USART1),
- OPTEE_RESET_ELT(RESETD_IDX_SCMI_STGEN),
- OPTEE_RESET_ELT(RESETD_IDX_SCMI_GPIOZ),
- OPTEE_RESET_ELT(RESETD_IDX_SCMI_CRYP1),
- OPTEE_RESET_ELT(RESETD_IDX_SCMI_HASH1),
- OPTEE_RESET_ELT(RESETD_IDX_SCMI_RNG1),
- OPTEE_RESET_ELT(RESETD_IDX_SCMI_MDMA),
- OPTEE_RESET_ELT(RESETD_IDX_SCMI_MCU),
- OPTEE_RESET_ELT(RESETD_IDX_SCMI_MCU_HOLD_BOOT),
- /* Termination entry */
- [RESETD_IDX_COUNT] = { 0 }
-};
-
-static_assert(FWK_ARRAY_SIZE(optee_reset_elt) == RESETD_IDX_COUNT + 1,
- "Invalid range for RESET and OPTEE_RESET indices");
-
-static const struct fwk_element *optee_reset_get_elt_table(fwk_id_t module_id)
-{
- size_t n;
-
- for (n = 0; n < FWK_ARRAY_SIZE(optee_reset_cfg); n++) {
- optee_reset_cfg[n].rstctrl =
- stm32mp_rcc_reset_id_to_rstctrl(stm32_resetd_cfg[n].rcc_rst_id);
- }
-
- return optee_reset_elt;
-}
-
-struct fwk_module_config config_optee_reset = {
- .elements = FWK_MODULE_DYNAMIC_ELEMENTS(optee_reset_get_elt_table),
-};
diff --git a/product/optee-stm32mp1/fw/config_scmi_voltage_domains.c b/product/optee-stm32mp1/fw/config_scmi_voltage_domains.c
deleted file mode 100644
index 54270128..00000000
--- a/product/optee-stm32mp1/fw/config_scmi_voltage_domains.c
+++ /dev/null
@@ -1,262 +0,0 @@
-/*
- * Arm SCP/MCP Software
- * Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#include <fwk_element.h>
-#include <fwk_id.h>
-#include <fwk_module.h>
-#include <fwk_module_idx.h>
-
-#include <mod_voltage_domain.h>
-#include <mod_scmi_voltage_domain.h>
-#include <mod_stm32_pmic_regu.h>
-#include <mod_stm32_pwr_regu.h>
-#include <scmi_agents.h>
-
-#include <assert.h>
-#include <stddef.h>
-#include <stdint.h>
-
-#include <compiler.h>
-#include <drivers/stm32mp1_pwr.h>
-#include <dt-bindings/regulator/st,stm32mp15-regulator.h>
-#include <util.h>
-
-/*
- * stm32_pwr_cfg - Configuration data for PWR regulators exposed thru SCMI
- *
- * These configation data is referenced in the fwk config data of
- * fwk modules VOLTAGE_DOMAIN and STM32_PMIC_REGU.
- */
-enum stm32_pwr_regu {
- STM32_PWR_REG11,
- STM32_PWR_REG18,
- STM32_PWR_USB33,
-};
-
-static const struct mod_stm32_pwr_regu_dev_config stm32_pwr_cfg[] = {
- [STM32_PWR_REG11] = { .pwr_id = PWR_REG11, .regu_name = "reg11" },
- [STM32_PWR_REG18] = { .pwr_id = PWR_REG18, .regu_name = "reg18" },
- [STM32_PWR_USB33] = { .pwr_id = PWR_USB33, .regu_name = "usb33" },
-};
-
-/*
- * stm32_pmic_cfg - Configuration data for PMIC regulators exposed thru SCMI
- *
- * These configation data are referenced in the fwk config data of
- * fwk modules VOLTAGE_DOMAIN and STM32_PMIC_REGU.
- * @regu_name is used both in PMIC regulator driver API and as SCMI
- * voltage domain name.
- */
-enum stpmic1_regu {
- STPMIC1_REGU_BUCK1,
- STPMIC1_REGU_BUCK2,
- STPMIC1_REGU_BUCK3,
- STPMIC1_REGU_BUCK4,
- STPMIC1_REGU_LDO1,
- STPMIC1_REGU_LDO2,
- STPMIC1_REGU_LDO3,
- STPMIC1_REGU_LDO4,
- STPMIC1_REGU_LDO5,
- STPMIC1_REGU_LDO6,
- STPMIC1_REGU_VREFDDR,
- STPMIC1_REGU_BOOST,
- STPMIC1_REGU_PWR_SW1,
- STPMIC1_REGU_PWR_SW2,
-};
-
-static const struct mod_stm32_pmic_regu_dev_config stm32_pmic_cfg[] = {
- [STPMIC1_REGU_BUCK1] = { .regu_name = "buck1" },
- [STPMIC1_REGU_BUCK2] = { .regu_name = "buck2", .read_only = true },
- [STPMIC1_REGU_BUCK3] = { .regu_name = "buck3" },
- [STPMIC1_REGU_BUCK4] = { .regu_name = "buck4" },
- [STPMIC1_REGU_LDO1] = { .regu_name = "ldo1" },
- [STPMIC1_REGU_LDO2] = { .regu_name = "ldo2" },
- [STPMIC1_REGU_LDO3] = { .regu_name = "ldo3", .read_only = true },
- [STPMIC1_REGU_LDO4] = { .regu_name = "ldo4" },
- [STPMIC1_REGU_LDO5] = { .regu_name = "ldo5" },
- [STPMIC1_REGU_LDO6] = { .regu_name = "ldo6" },
- [STPMIC1_REGU_VREFDDR] = { .regu_name = "vref_ddr", .read_only = true },
- [STPMIC1_REGU_BOOST] = { .regu_name = "boost" },
- [STPMIC1_REGU_PWR_SW1] = { .regu_name = "pwr_sw1" },
- [STPMIC1_REGU_PWR_SW2] = { .regu_name = "pwr_sw2" },
-};
-
-/*
- * Indices of voltage domain module elements exposed through a SCMI agent.
- */
-enum voltd_elt_idx {
- /* Voltage domains exposed to agent SCMI */
- VOLTD_IDX_SCMI_REG11,
- VOLTD_IDX_SCMI_REG18,
- VOLTD_IDX_SCMI_USB33,
- VOLTD_IDX_SCMI_STPMIC1_BUCK1,
- VOLTD_IDX_SCMI_STPMIC1_BUCK2,
- VOLTD_IDX_SCMI_STPMIC1_BUCK3,
- VOLTD_IDX_SCMI_STPMIC1_BUCK4,
- VOLTD_IDX_SCMI_STPMIC1_LDO1,
- VOLTD_IDX_SCMI_STPMIC1_LDO2,
- VOLTD_IDX_SCMI_STPMIC1_LDO3,
- VOLTD_IDX_SCMI_STPMIC1_LDO4,
- VOLTD_IDX_SCMI_STPMIC1_LDO5,
- VOLTD_IDX_SCMI_STPMIC1_LDO6,
- VOLTD_IDX_SCMI_STPMIC1_VREFDDR,
- VOLTD_IDX_SCMI_STPMIC1_BOOST,
- VOLTD_IDX_SCMI_STPMIC1_PWR_SW1,
- VOLTD_IDX_SCMI_STPMIC1_PWR_SW2,
- VOLTD_IDX_COUNT
-};
-
-/*
- * SCMI Voltage Domain driver configuration
- */
-#define SCMI_VOLTD_ELT_ID(_idx) \
- { .element_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_VOLTAGE_DOMAIN, (_idx)) }
-
-static struct mod_scmi_voltd_device scmi_voltd_device[] = {
- SCMI_VOLTD_ELT_ID(VOLTD_SCMI_REG11),
- SCMI_VOLTD_ELT_ID(VOLTD_SCMI_REG18),
- SCMI_VOLTD_ELT_ID(VOLTD_SCMI_USB33),
- SCMI_VOLTD_ELT_ID(VOLTD_SCMI_STPMIC1_BUCK1),
- SCMI_VOLTD_ELT_ID(VOLTD_SCMI_STPMIC1_BUCK2),
- SCMI_VOLTD_ELT_ID(VOLTD_SCMI_STPMIC1_BUCK3),
- SCMI_VOLTD_ELT_ID(VOLTD_SCMI_STPMIC1_BUCK4),
- SCMI_VOLTD_ELT_ID(VOLTD_SCMI_STPMIC1_LDO1),
- SCMI_VOLTD_ELT_ID(VOLTD_SCMI_STPMIC1_LDO2),
- SCMI_VOLTD_ELT_ID(VOLTD_SCMI_STPMIC1_LDO3),
- SCMI_VOLTD_ELT_ID(VOLTD_SCMI_STPMIC1_LDO4),
- SCMI_VOLTD_ELT_ID(VOLTD_SCMI_STPMIC1_LDO5),
- SCMI_VOLTD_ELT_ID(VOLTD_SCMI_STPMIC1_LDO6),
- SCMI_VOLTD_ELT_ID(VOLTD_SCMI_STPMIC1_VREFDDR),
- SCMI_VOLTD_ELT_ID(VOLTD_SCMI_STPMIC1_BOOST),
- SCMI_VOLTD_ELT_ID(VOLTD_SCMI_STPMIC1_PWR_SW1),
- SCMI_VOLTD_ELT_ID(VOLTD_SCMI_STPMIC1_PWR_SW2),
-};
-
-static const struct mod_scmi_voltd_agent voltd_agent_table[SCMI_AGENT_ID_COUNT] = {
- [SCMI_AGENT_ID_NSEC0] = {
- .device_table = scmi_voltd_device,
- .domain_count = FWK_ARRAY_SIZE(scmi_voltd_device),
- },
-};
-
-/* Exported configuration data for module SCMI_VOLTAGE_DOMAIN */
-const struct fwk_module_config config_scmi_voltage_domain = {
- .data = &((struct mod_scmi_voltd_config){
- .agent_table = voltd_agent_table,
- .agent_count = FWK_ARRAY_SIZE(voltd_agent_table),
- }),
-};
-
-/*
- * Voltage Domain driver configuration describes STM32_PWR_REGU elements
- * and STM32_PMIC_REGU elements.
- */
-#define VOLTD_STM32_PWR_DATA(_idx) \
- ((struct mod_voltd_dev_config){ \
- .driver_id = \
- FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_STM32_PWR_REGU, (_idx)), \
- .api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_STM32_PWR_REGU, 0), \
- })
-
-#define VOLTD_STM32_PWR_ELT_ID(_idx) \
- { \
- .name = stm32_pwr_cfg[(_idx)].regu_name, \
- .data = &VOLTD_STM32_PWR_DATA(_idx), \
- }
-
-#define VOLTD_STM32_PMIC_DATA(_idx) \
- ((struct mod_voltd_dev_config){ \
- .driver_id = \
- FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_STM32_PMIC_REGU, (_idx)), \
- .api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_STM32_PMIC_REGU, 0), \
- })
-
-#define VOLTD_STM32_PMIC_ELT_ID(_dev_idx) \
- { \
- .name = stm32_pmic_cfg[(_dev_idx)].regu_name, \
- .data = &VOLTD_STM32_PMIC_DATA(_dev_idx), \
- }
-
-/* Elements names are the voltage domain names exposed by the SCMI service */
-static const struct fwk_element voltd_elt[] = {
- [VOLTD_IDX_SCMI_REG11] = VOLTD_STM32_PWR_ELT_ID(STM32_PWR_REG11),
- [VOLTD_IDX_SCMI_REG18] = VOLTD_STM32_PWR_ELT_ID(STM32_PWR_REG18),
- [VOLTD_IDX_SCMI_USB33] = VOLTD_STM32_PWR_ELT_ID(STM32_PWR_USB33),
- [VOLTD_IDX_SCMI_STPMIC1_BUCK1] = VOLTD_STM32_PMIC_ELT_ID(STPMIC1_REGU_BUCK1),
- [VOLTD_IDX_SCMI_STPMIC1_BUCK2] = VOLTD_STM32_PMIC_ELT_ID(STPMIC1_REGU_BUCK2),
- [VOLTD_IDX_SCMI_STPMIC1_BUCK3] = VOLTD_STM32_PMIC_ELT_ID(STPMIC1_REGU_BUCK3),
- [VOLTD_IDX_SCMI_STPMIC1_BUCK4] = VOLTD_STM32_PMIC_ELT_ID(STPMIC1_REGU_BUCK4),
- [VOLTD_IDX_SCMI_STPMIC1_LDO1] = VOLTD_STM32_PMIC_ELT_ID(STPMIC1_REGU_LDO1),
- [VOLTD_IDX_SCMI_STPMIC1_LDO2] = VOLTD_STM32_PMIC_ELT_ID(STPMIC1_REGU_LDO2),
- [VOLTD_IDX_SCMI_STPMIC1_LDO3] = VOLTD_STM32_PMIC_ELT_ID(STPMIC1_REGU_LDO3),
- [VOLTD_IDX_SCMI_STPMIC1_LDO4] = VOLTD_STM32_PMIC_ELT_ID(STPMIC1_REGU_LDO4),
- [VOLTD_IDX_SCMI_STPMIC1_LDO5] = VOLTD_STM32_PMIC_ELT_ID(STPMIC1_REGU_LDO5),
- [VOLTD_IDX_SCMI_STPMIC1_LDO6] = VOLTD_STM32_PMIC_ELT_ID(STPMIC1_REGU_LDO6),
- [VOLTD_IDX_SCMI_STPMIC1_VREFDDR] = VOLTD_STM32_PMIC_ELT_ID(STPMIC1_REGU_VREFDDR),
- [VOLTD_IDX_SCMI_STPMIC1_BOOST] = VOLTD_STM32_PMIC_ELT_ID(STPMIC1_REGU_BOOST),
- [VOLTD_IDX_SCMI_STPMIC1_PWR_SW1] = VOLTD_STM32_PMIC_ELT_ID(STPMIC1_REGU_PWR_SW1),
- [VOLTD_IDX_SCMI_STPMIC1_PWR_SW2] = VOLTD_STM32_PMIC_ELT_ID(STPMIC1_REGU_PWR_SW2),
- [VOLTD_IDX_COUNT] = { 0 } /* Termination entry */
-};
-
-/* Exported configuration data for module VOLTAGE_DOMAIN */
-const struct fwk_module_config config_voltage_domain = {
- .elements = FWK_MODULE_STATIC_ELEMENTS_PTR(voltd_elt),
-};
-
-/*
- * STM32 PWR driver configuration
- */
-#define STM32_PWR_ELT(_dev_idx) \
- [(_dev_idx)] = { \
- .name = stm32_pwr_cfg[(_dev_idx)].regu_name, \
- .data = &stm32_pwr_cfg[(_dev_idx)], \
- }
-
-static const struct fwk_element stm32_pwr_elt[] = {
- STM32_PWR_ELT(STM32_PWR_REG11),
- STM32_PWR_ELT(STM32_PWR_REG18),
- STM32_PWR_ELT(STM32_PWR_USB33),
- { 0 } /* Termination entry */
-};
-
-/* Exported configuration data for module STM32_PWR_REGU */
-const struct fwk_module_config config_stm32_pwr_regu = {
- .elements = FWK_MODULE_STATIC_ELEMENTS_PTR(stm32_pwr_elt),
-};
-
-/*
- * STM32 PMIC regulator driver configuration
- */
-#define STM32_PMIC_ELT(_dev_idx) \
- [(_dev_idx)] = { \
- .name = stm32_pmic_cfg[(_dev_idx)].regu_name, \
- .data = &stm32_pmic_cfg[(_dev_idx)], \
- }
-
-static const struct fwk_element stm32_pmic_elt[] = {
- STM32_PMIC_ELT(STPMIC1_REGU_BUCK1),
- STM32_PMIC_ELT(STPMIC1_REGU_BUCK2),
- STM32_PMIC_ELT(STPMIC1_REGU_BUCK3),
- STM32_PMIC_ELT(STPMIC1_REGU_BUCK4),
- STM32_PMIC_ELT(STPMIC1_REGU_LDO1),
- STM32_PMIC_ELT(STPMIC1_REGU_LDO2),
- STM32_PMIC_ELT(STPMIC1_REGU_LDO3),
- STM32_PMIC_ELT(STPMIC1_REGU_LDO4),
- STM32_PMIC_ELT(STPMIC1_REGU_LDO5),
- STM32_PMIC_ELT(STPMIC1_REGU_LDO6),
- STM32_PMIC_ELT(STPMIC1_REGU_VREFDDR),
- STM32_PMIC_ELT(STPMIC1_REGU_BOOST),
- STM32_PMIC_ELT(STPMIC1_REGU_PWR_SW1),
- STM32_PMIC_ELT(STPMIC1_REGU_PWR_SW2),
- { 0 } /* Termination entry */
-};
-
-/* Exported configuration data for module STM32_PMIC_REGU */
-const struct fwk_module_config config_stm32_pmic_regu = {
- .elements = FWK_MODULE_STATIC_ELEMENTS_PTR(stm32_pmic_elt),
-};
diff --git a/product/optee-stm32mp1/module/stm32_pwr_regu/CMakeLists.txt b/product/optee-stm32mp1/module/psu_optee_regulator/CMakeLists.txt
similarity index 80%
rename from product/optee-stm32mp1/module/stm32_pwr_regu/CMakeLists.txt
rename to product/optee-stm32mp1/module/psu_optee_regulator/CMakeLists.txt
index 7471acc6..77af63f2 100644
--- a/product/optee-stm32mp1/module/stm32_pwr_regu/CMakeLists.txt
+++ b/product/optee-stm32mp1/module/psu_optee_regulator/CMakeLists.txt
@@ -1,6 +1,6 @@
#
# Arm SCP/MCP Software
-# Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved.
+# Copyright (c) 2023, Linaro Limited and Contributors. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
@@ -9,9 +9,9 @@ add_library(${SCP_MODULE_TARGET} SCP_MODULE)
target_include_directories(${SCP_MODULE_TARGET}
PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include"
- "${SCP_OPTEE_DIR}/core/arch/arm/plat-stm32mp1")
+ "${SCP_OPTEE_DIR}/core/arch/arm/plat-stm32mp2")
target_sources(
- ${SCP_MODULE_TARGET} PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/src/mod_stm32_pwr_regu.c")
+ ${SCP_MODULE_TARGET} PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/src/mod_psu_optee_regulator.c")
target_link_libraries(${SCP_MODULE_TARGET} PUBLIC module-voltage-domain)
diff --git a/product/optee-stm32mp1/module/psu_optee_regulator/Module.cmake b/product/optee-stm32mp1/module/psu_optee_regulator/Module.cmake
new file mode 100644
index 00000000..26dc706e
--- /dev/null
+++ b/product/optee-stm32mp1/module/psu_optee_regulator/Module.cmake
@@ -0,0 +1,9 @@
+#
+# Arm SCP/MCP Software
+# Copyright (c) 2023, Linaro Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+set(SCP_MODULE "psu-optee-regulator")
+set(SCP_MODULE_TARGET "psu-optee-regulator")
diff --git a/product/optee-stm32mp1/module/psu_optee_regulator/include/mod_psu_optee_regulator.h b/product/optee-stm32mp1/module/psu_optee_regulator/include/mod_psu_optee_regulator.h
new file mode 100644
index 00000000..789c9591
--- /dev/null
+++ b/product/optee-stm32mp1/module/psu_optee_regulator/include/mod_psu_optee_regulator.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2023, STMicroelectronics
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MOD_PSU_OPTEE_REGULATOR_H
+#define MOD_PSU_OPTEE_REGULATOR_H
+
+#include <fwk_element.h>
+#include <fwk_macros.h>
+#include <stdint.h>
+#include <stdbool.h>
+
+struct rdev;
+
+/*!
+ * \brief Platform regulator configuration.
+ */
+struct mod_psu_optee_regulator_dev_config {
+ struct rdev *rdev;
+};
+
+#endif /* MOD_PSU_OPTEE_REGULATOR_H */
diff --git a/product/optee-stm32mp1/module/psu_optee_regulator/src/mod_psu_optee_regulator.c b/product/optee-stm32mp1/module/psu_optee_regulator/src/mod_psu_optee_regulator.c
new file mode 100644
index 00000000..73a82b45
--- /dev/null
+++ b/product/optee-stm32mp1/module/psu_optee_regulator/src/mod_psu_optee_regulator.c
@@ -0,0 +1,190 @@
+/*
+ * Copyright (c) 2017-2019, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2022, STMicroelectronics
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stddef.h>
+
+#include <fwk_log.h>
+#include <fwk_macros.h>
+#include <fwk_mm.h>
+#include <fwk_module.h>
+#include <mod_psu.h>
+#include <mod_psu_optee_regulator.h>
+#include <mod_scmi_std.h>
+
+#include <assert.h>
+#include <config.h>
+#include <drivers/regulator.h>
+#include <io.h>
+#include <trace.h>
+
+#define DEBUG_MSG(...) FMSG(__VA_ARGS__)
+
+/* Module context */
+struct psu_optee_regulator_ctx {
+ struct mod_psu_optee_regulator_dev_config *config;
+ unsigned int dev_count;
+};
+
+/* A single instance handles all voltage regulators abstracted by regulator.h */
+static struct psu_optee_regulator_ctx module_ctx;
+
+static char __maybe_unused *regulator_name(struct rdev *rdev)
+{
+ if (rdev)
+ return (char *)rdev->reg_name;
+
+ return NULL;
+}
+
+static struct rdev *get_regulator(fwk_id_t id)
+{
+ unsigned int elt_index;
+
+ elt_index = fwk_id_get_element_idx(id);
+ if (elt_index >= module_ctx.dev_count)
+ return NULL;
+
+ return module_ctx.config[elt_index].rdev;
+}
+
+/*
+ * Driver functions for the PSU API
+ */
+static int psu_optee_regulator_set_enabled(fwk_id_t id, bool enabled)
+{
+ TEE_Result res = TEE_ERROR_GENERIC;
+ struct rdev *regulator;
+
+ regulator = get_regulator(id);
+ if (!regulator) {
+ return FWK_E_PARAM;
+ }
+
+ DEBUG_MSG("PSU set %s %s", regulator_name(regulator),
+ enabled ? "ON" : "OFF");
+
+ if (enabled) {
+ res = regulator_enable(regulator);
+ } else {
+ res = regulator_disable(regulator);
+ }
+
+ if (res) {
+ return FWK_E_HANDLER;
+ } else {
+ return FWK_SUCCESS;
+ }
+}
+
+static int psu_optee_regulator_get_enabled(fwk_id_t id, bool *enabled)
+{
+ struct rdev *regulator;
+
+ regulator = get_regulator(id);
+ if (!regulator || (enabled == NULL)) {
+ return FWK_E_PARAM;
+ }
+
+ *enabled = regulator_is_enabled((const struct rdev *)regulator);
+ DEBUG_MSG("PSU get %s state: %s", regulator_name(regulator),
+ enabled ? "ON" : "OFF");
+
+ return FWK_SUCCESS;
+}
+
+static int psu_optee_regulator_set_voltage(fwk_id_t id, uint32_t voltage)
+{
+ TEE_Result res = TEE_ERROR_GENERIC;
+ struct rdev *regulator;
+ uint16_t level_mv = voltage;
+
+ regulator = get_regulator(id);
+ if (!regulator) {
+ return FWK_E_PARAM;
+ }
+
+ DEBUG_MSG("PSU set regulator %s level: %"PRIu32"mV",
+ regulator_name(regulator), (uint32_t)level_mv);
+
+ res = regulator_set_voltage(regulator, level_mv);
+
+ if (res) {
+ return FWK_E_HANDLER;
+ } else {
+
+ return FWK_SUCCESS;
+ }
+}
+
+static int psu_optee_regulator_get_voltage(fwk_id_t id, uint32_t *voltage)
+{
+ TEE_Result res = TEE_ERROR_GENERIC;
+ struct rdev *regulator;
+ uint16_t level_mv;
+
+ regulator = get_regulator(id);
+ if (!regulator || (voltage == NULL)) {
+ return FWK_E_PARAM;
+ }
+
+ res = regulator_get_voltage(regulator, &level_mv);
+
+ DEBUG_MSG("PSU get regulator %s level: %"PRIu32"mV (res %#"PRIx32")",
+ regulator_name(regulator), (uint32_t)level_mv, res);
+
+ if (res) {
+ return FWK_E_HANDLER;
+ }
+
+ *voltage = level_mv;
+
+ return FWK_SUCCESS;
+}
+
+static struct mod_psu_driver_api psu_driver_api = {
+ .set_enabled = psu_optee_regulator_set_enabled,
+ .get_enabled = psu_optee_regulator_get_enabled,
+ .set_voltage = psu_optee_regulator_set_voltage,
+ .get_voltage = psu_optee_regulator_get_voltage,
+};
+
+static int psu_optee_regulator_init(fwk_id_t module_id,
+ unsigned int element_count,
+ const void *data)
+{
+ return FWK_SUCCESS;
+}
+
+static int psu_optee_regulator_element_init(fwk_id_t element_id,
+ unsigned int sub_element_count,
+ const void *data)
+{
+ fwk_assert(data != NULL);
+
+ module_ctx.config = (struct mod_psu_optee_regulator_dev_config *)data;
+ module_ctx.dev_count = sub_element_count;
+
+ return FWK_SUCCESS;
+}
+
+static int psu_optee_regulator_process_bind_request(fwk_id_t source_id,
+ fwk_id_t target_id,
+ fwk_id_t api_id,
+ const void **api)
+{
+ *api = &psu_driver_api;
+
+ return FWK_SUCCESS;
+}
+
+const struct fwk_module module_psu_optee_regulator = {
+ .api_count = 1,
+ .type = FWK_MODULE_TYPE_DRIVER,
+ .init = psu_optee_regulator_init,
+ .element_init = psu_optee_regulator_element_init,
+ .process_bind_request = psu_optee_regulator_process_bind_request,
+};
diff --git a/product/optee-stm32mp1/module/stm32_pmic_regu/Module.cmake b/product/optee-stm32mp1/module/stm32_pmic_regu/Module.cmake
deleted file mode 100644
index 51bfae5b..00000000
--- a/product/optee-stm32mp1/module/stm32_pmic_regu/Module.cmake
+++ /dev/null
@@ -1,9 +0,0 @@
-#
-# Arm SCP/MCP Software
-# Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved.
-#
-# SPDX-License-Identifier: BSD-3-Clause
-#
-
-set(SCP_MODULE "stm32-pmic-regu")
-set(SCP_MODULE_TARGET "module-stm32-pmic-regu")
diff --git a/product/optee-stm32mp1/module/stm32_pmic_regu/include/mod_stm32_pmic_regu.h b/product/optee-stm32mp1/module/stm32_pmic_regu/include/mod_stm32_pmic_regu.h
deleted file mode 100644
index 120f1351..00000000
--- a/product/optee-stm32mp1/module/stm32_pmic_regu/include/mod_stm32_pmic_regu.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Arm SCP/MCP Software
- * Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#ifndef MOD_STPMIC1_REGU_H
-#define MOD_STPMIC1_REGU_H
-
-#include <fwk_element.h>
-#include <fwk_macros.h>
-
-#include <stdint.h>
-
-/*!
- * \brief Platform regulator configuration.
- */
-struct mod_stm32_pmic_regu_dev_config {
- const char *regu_name;
- bool read_only;
-};
-
-#endif /* MOD_STPMIC1_REGU_H */
diff --git a/product/optee-stm32mp1/module/stm32_pmic_regu/src/mod_stm32_pmic_regu.c b/product/optee-stm32mp1/module/stm32_pmic_regu/src/mod_stm32_pmic_regu.c
deleted file mode 100644
index b22702b6..00000000
--- a/product/optee-stm32mp1/module/stm32_pmic_regu/src/mod_stm32_pmic_regu.c
+++ /dev/null
@@ -1,367 +0,0 @@
-/*
- * Arm SCP/MCP Software
- * Copyright (c) 2022-2023, Linaro Limited and Contributors. All rights
- * reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- *
- * Description:
- * Interface SCP-firmare VOLTD instances with OP-TEE stm32mp1
- * PMIC regulator driver for voltage regulator controller from
- * an external PMIC access with a I2C bus using OP-TEE resources.
- *
- * The OP-TEE drvier is accessed by API function named like
- * stpmic1_regulator_*(). They execute in a threaded interruptible,
- * and rescheduable context.
- */
-#include <fwk_macros.h>
-#include <fwk_mm.h>
-#include <fwk_module.h>
-#include <fwk_log.h>
-
-#include <mod_scmi_std.h>
-#include <mod_stm32_pmic_regu.h>
-#include <mod_voltage_domain.h>
-
-#include <stddef.h>
-
-#include <drivers/stm32mp1_pmic.h>
-#include <drivers/stpmic1_regulator.h>
-#include <stm32_util.h>
-
-#define MOD_NAME "[STM32 PMIC] "
-
-/* Device context */
-struct stm32_pmic_regu_dev_ctx {
- const char *regu_id; /* Both name and backend regu ID */
- bool read_only;
-};
-
-/* Module context */
-struct stm32_pmic_regu_ctx {
- struct stm32_pmic_regu_dev_ctx *dev_ctx_table;
- unsigned int dev_count;
-};
-
-static struct stm32_pmic_regu_ctx module_ctx;
-
-static int32_t get_regu_voltage(const char *regu_id)
-{
- unsigned long level_uv = 0;
-
- stm32mp_get_pmic();
- level_uv = stpmic1_regulator_voltage_get(regu_id) * 1000;
- stm32mp_put_pmic();
-
- return (int32_t)level_uv;
-}
-
-static int32_t set_regu_voltage(const char *regu_id, int32_t level_uv)
-{
- int rc = 0;
- unsigned int level_mv = level_uv / 1000;
-
- FWK_LOG_DEBUG(
- MOD_NAME "Set STPMIC1 regulator %s level to %dmV",
- regu_id,
- level_uv / 1000);
-
- fwk_assert(level_mv < UINT16_MAX);
-
- stm32mp_get_pmic();
- rc = stpmic1_regulator_voltage_set(regu_id, level_mv);
- stm32mp_put_pmic();
-
- return rc ? SCMI_GENERIC_ERROR : SCMI_SUCCESS;
-}
-
-static bool regu_is_enable(const char *regu_id)
-{
- bool rc = false;
-
- stm32mp_get_pmic();
- rc = stpmic1_is_regulator_enabled(regu_id);
- stm32mp_put_pmic();
-
- return rc;
-}
-
-static int32_t set_regu_state(const char *regu_id, bool enable)
-{
- int rc = 0;
-
- stm32mp_get_pmic();
-
- FWK_LOG_DEBUG(
- MOD_NAME "%sable STPMIC1 %s (was %s)",
- enable ? "En" : "Dis",
- regu_id,
- stpmic1_is_regulator_enabled(regu_id) ? "on" : "off");
-
- if (enable) {
- rc = stpmic1_regulator_enable(regu_id);
- } else {
- rc = stpmic1_regulator_disable(regu_id);
- }
-
- stm32mp_put_pmic();
-
- return rc ? SCMI_GENERIC_ERROR : SCMI_SUCCESS;
-}
-
-/*
- * Voltage domain driver API functions
- */
-static int pmic_regu_get_config(fwk_id_t dev_id, uint8_t *mode_type,
- uint8_t *mode_id)
-{
- struct stm32_pmic_regu_dev_ctx *ctx;
-
- if (!fwk_module_is_valid_element_id(dev_id) ||
- mode_id == NULL || mode_type == NULL) {
- return FWK_E_PARAM;
- }
-
- ctx = module_ctx.dev_ctx_table + fwk_id_get_element_idx(dev_id);
-
- *mode_type = MOD_VOLTD_MODE_TYPE_ARCH;
-
- if (regu_is_enable(ctx->regu_id)) {
- *mode_id = MOD_VOLTD_MODE_ID_ON;
- } else {
- *mode_id = MOD_VOLTD_MODE_ID_OFF;
- }
-
- FWK_LOG_DEBUG(
- MOD_NAME "SCMI voltd %u: get config PMIC %s: %s",
- fwk_id_get_element_idx(dev_id),
- ctx->regu_id,
- *mode_id == MOD_VOLTD_MODE_ID_ON ? "on" : "off");
-
- return FWK_SUCCESS;
-}
-
-static int pmic_regu_set_config(fwk_id_t dev_id, uint8_t mode_type,
- uint8_t mode_id)
-{
- struct stm32_pmic_regu_dev_ctx *ctx = NULL;
-
- if (!fwk_module_is_valid_element_id(dev_id) ||
- mode_type != MOD_VOLTD_MODE_TYPE_ARCH ||
- (mode_id == MOD_VOLTD_MODE_ID_ON && mode_id == MOD_VOLTD_MODE_ID_OFF)) {
- return FWK_E_PARAM;
- }
-
- ctx = module_ctx.dev_ctx_table + fwk_id_get_element_idx(dev_id);
-
- if (ctx->read_only) {
- return FWK_E_ACCESS;
- }
-
- if (set_regu_state(ctx->regu_id, mode_id == MOD_VOLTD_MODE_ID_ON)) {
- return FWK_E_DEVICE;
- }
-
- FWK_LOG_DEBUG(
- MOD_NAME "SCMI voltd %u: set config PMIC %s to %s",
- fwk_id_get_element_idx(dev_id),
- ctx->regu_id,
- mode_id == MOD_VOLTD_MODE_ID_ON ? "on" : "off");
-
- return FWK_SUCCESS;
-}
-
-static int pmic_regu_get_level(fwk_id_t dev_id, int *level_uv)
-{
- struct stm32_pmic_regu_dev_ctx *ctx = NULL;
-
- if (!fwk_module_is_valid_element_id(dev_id) || level_uv == NULL) {
- return FWK_E_PARAM;
- }
-
- ctx = module_ctx.dev_ctx_table + fwk_id_get_element_idx(dev_id);
-
- *level_uv = get_regu_voltage(ctx->regu_id);
-
- FWK_LOG_DEBUG(
- MOD_NAME "SCMI voltd %u: get level PMIC %s = %d",
- fwk_id_get_element_idx(dev_id),
- ctx->regu_id,
- *level_uv);
-
- return FWK_SUCCESS;
-}
-
-static int pmic_regu_set_level(fwk_id_t dev_id, int level_uv)
-{
- struct stm32_pmic_regu_dev_ctx *ctx = NULL;
-
- if (!fwk_module_is_valid_element_id(dev_id)) {
- return FWK_E_PARAM;
- }
-
- ctx = module_ctx.dev_ctx_table + fwk_id_get_element_idx(dev_id);
-
- if (ctx->read_only) {
- return FWK_E_ACCESS;
- }
-
- FWK_LOG_DEBUG(
- MOD_NAME "SCMI voltd %u: set level PMIC %s to %d",
- fwk_id_get_element_idx(dev_id),
- ctx->regu_id,
- level_uv);
-
- if (set_regu_voltage(ctx->regu_id, level_uv)) {
- return FWK_E_DEVICE;
- }
-
- return FWK_SUCCESS;
-}
-
-static void find_bound_uv(const uint16_t *levels, size_t count,
- int32_t *min, int32_t *max)
-{
- size_t n = 0;
-
- fwk_assert((count == 0 || levels != NULL) && min != NULL && max != NULL);
-
- *min = INT32_MAX;
- *max = INT32_MIN;
-
- for (n = 0; n < count; n++) {
- if (*min > levels[n]) {
- *min = levels[n];
- }
- if (*max < levels[n]) {
- *max = levels[n];
- }
- }
-
- /* Convert from mV to uV */
- *min *= 1000;
- *max *= 1000;
-}
-
-static int pmic_regu_get_info(fwk_id_t dev_id, struct mod_voltd_info *info)
-{
- struct stm32_pmic_regu_dev_ctx *ctx = NULL;
- const uint16_t *levels = NULL;
- size_t full_count = 0;
-
- if (!fwk_module_is_valid_element_id(dev_id) || info == NULL) {
- return FWK_E_PARAM;
- }
-
- ctx = module_ctx.dev_ctx_table + fwk_id_get_element_idx(dev_id);
-
- stpmic1_regulator_levels_mv(ctx->regu_id, &levels, &full_count);
-
- memset(info, 0, sizeof(*info));
- info->name = ctx->regu_id;
- info->level_range.level_type = MOD_VOLTD_VOLTAGE_LEVEL_DISCRETE;
- info->level_range.level_count = full_count;
- find_bound_uv(levels, full_count,
- &info->level_range.min_uv, &info->level_range.max_uv);
-
- FWK_LOG_DEBUG(
- MOD_NAME "SCMI voltd %u: get_info PMIC %s, range [%d %d]",
- fwk_id_get_element_idx(dev_id),
- ctx->regu_id,
- info->level_range.min_uv,
- info->level_range.max_uv);
-
- return FWK_SUCCESS;
-}
-
-static int pmic_regu_level_from_index(fwk_id_t dev_id, unsigned int index,
- int32_t *level_uv)
-{
- struct stm32_pmic_regu_dev_ctx *ctx = NULL;
- const uint16_t *levels = NULL;
- size_t full_count = 0;
-
- if (!fwk_module_is_valid_element_id(dev_id) || level_uv == NULL) {
- return FWK_E_PARAM;
- }
-
- ctx = module_ctx.dev_ctx_table + fwk_id_get_element_idx(dev_id);
-
- stpmic1_regulator_levels_mv(ctx->regu_id, &levels, &full_count);
- if (index >= full_count) {
- return FWK_E_RANGE;
- }
-
- *level_uv = (int32_t)levels[index] * 1000;
-
- FWK_LOG_DEBUG(
- MOD_NAME "SCMI voltd %u: get level PMIC %s = %d",
- fwk_id_get_element_idx(dev_id),
- ctx->regu_id,
- *level_uv);
-
- return FWK_SUCCESS;
-}
-
-static const struct mod_voltd_drv_api api_stm32_pmic_regu = {
- .get_config = pmic_regu_get_config,
- .set_config = pmic_regu_set_config,
- .get_level = pmic_regu_get_level,
- .set_level = pmic_regu_set_level,
- .get_info = pmic_regu_get_info,
- .get_level_from_index = pmic_regu_level_from_index,
-};
-
-/*
- * Framework handler functions
- */
-
-static int stm32_pmic_regu_init(fwk_id_t module_id, unsigned int element_count,
- const void *data)
-{
- module_ctx.dev_count = element_count;
-
- if (element_count) {
- module_ctx.dev_ctx_table =
- fwk_mm_calloc(element_count, sizeof(*module_ctx.dev_ctx_table));
- }
-
- return FWK_SUCCESS;
-}
-
-static int stm32_pmic_regu_element_init(fwk_id_t element_id,
- unsigned int unused,
- const void *data)
-{
- struct stm32_pmic_regu_dev_ctx *ctx = NULL;
- const struct mod_stm32_pmic_regu_dev_config *dev_config = data;
-
- if (!fwk_module_is_valid_element_id(element_id)) {
- return FWK_E_PARAM;
- }
-
- ctx = module_ctx.dev_ctx_table + fwk_id_get_element_idx(element_id);
-
- ctx->regu_id = dev_config->regu_name;
- ctx->read_only = dev_config->read_only;
-
- return FWK_SUCCESS;
-}
-
-static int stm32_pmic_regu_process_bind_request(fwk_id_t requester_id,
- fwk_id_t target_id,
- fwk_id_t api_type,
- const void **api)
-{
- *api = &api_stm32_pmic_regu;
-
- return FWK_SUCCESS;
-}
-
-const struct fwk_module module_stm32_pmic_regu = {
- .type = FWK_MODULE_TYPE_DRIVER,
- .api_count = 1,
- .init = stm32_pmic_regu_init,
- .element_init = stm32_pmic_regu_element_init,
- .process_bind_request = stm32_pmic_regu_process_bind_request,
-};
diff --git a/product/optee-stm32mp1/module/stm32_pwr_regu/Module.cmake b/product/optee-stm32mp1/module/stm32_pwr_regu/Module.cmake
deleted file mode 100644
index b8c5be8d..00000000
--- a/product/optee-stm32mp1/module/stm32_pwr_regu/Module.cmake
+++ /dev/null
@@ -1,9 +0,0 @@
-#
-# Arm SCP/MCP Software
-# Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved.
-#
-# SPDX-License-Identifier: BSD-3-Clause
-#
-
-set(SCP_MODULE "stm32-pwr-regu")
-set(SCP_MODULE_TARGET "module-stm32-pwr-regu")
diff --git a/product/optee-stm32mp1/module/stm32_pwr_regu/include/mod_stm32_pwr_regu.h b/product/optee-stm32mp1/module/stm32_pwr_regu/include/mod_stm32_pwr_regu.h
deleted file mode 100644
index 567ab18e..00000000
--- a/product/optee-stm32mp1/module/stm32_pwr_regu/include/mod_stm32_pwr_regu.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Arm SCP/MCP Software
- * Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#ifndef MOD_STM32_PWR_REGU_H
-#define MOD_STM32_PWR_REGU_H
-
-/*!
- * \brief Platform clocks configuration.
- */
-struct mod_stm32_pwr_regu_dev_config {
- unsigned long pwr_id;
- const char *regu_name;
-};
-
-#endif /* MOD_STM32_PWR_REGU_H */
diff --git a/product/optee-stm32mp1/module/stm32_pwr_regu/src/mod_stm32_pwr_regu.c b/product/optee-stm32mp1/module/stm32_pwr_regu/src/mod_stm32_pwr_regu.c
deleted file mode 100644
index 65c02f43..00000000
--- a/product/optee-stm32mp1/module/stm32_pwr_regu/src/mod_stm32_pwr_regu.c
+++ /dev/null
@@ -1,293 +0,0 @@
-/*
- * Arm SCP/MCP Software
- * Copyright (c) 2022-2023, Linaro Limited and Contributors. All rights
- * reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- *
- * Description:
- * Interface SCP-firmare VOLTD instances with OP-TEE stm32mp1
- * PWR regulator driver for SoC voltage regulator controller by
- * OP-TEE for this platform.
- *
- * The OP-TEE drvier is accessed by API function named
- * stm32mp1_regultor_*(). They execute in a threaded interruptible,
- * and rescheduable context.
- */
-
-#include <fwk_macros.h>
-#include <fwk_mm.h>
-#include <fwk_module.h>
-#include <fwk_log.h>
-
-#include <mod_voltage_domain.h>
-#include <mod_stm32_pwr_regu.h>
-
-#include <drivers/stm32mp1_pwr.h>
-#include <stm32_util.h>
-
-#define MOD_NAME "[STM32 PWR] "
-
-/* Device context */
-struct stm32_pwr_regu_dev_ctx {
- enum pwr_regulator pwr_id;
- const char *name;
-};
-
-/* Module context */
-struct stm32_pwr_regu_ctx {
- struct stm32_pwr_regu_dev_ctx *dev_ctx_table;
- unsigned int dev_count;
-};
-
-static struct stm32_pwr_regu_ctx module_ctx;
-
-static bool nsec_can_access_pwr_regu(enum pwr_regulator pwr_id)
-{
- /* Currently allow non-secure world to access all PWR regulators */
- return true;
-}
-
-static int32_t pwr_regu_level(enum pwr_regulator pwr_id)
-{
- return (int32_t)stm32mp1_pwr_regulator_mv(pwr_id) * 1000;
-}
-
-/*
- * Voltage domain driver API functions
- */
-static int pwr_regu_get_config(fwk_id_t dev_id, uint8_t *mode_type,
- uint8_t *mode_id)
-{
- struct stm32_pwr_regu_dev_ctx *ctx;
-
- if (!fwk_module_is_valid_element_id(dev_id) ||
- mode_type == NULL || mode_id == NULL) {
- return FWK_E_PARAM;
- }
-
- ctx = module_ctx.dev_ctx_table + fwk_id_get_element_idx(dev_id);
-
- if (!nsec_can_access_pwr_regu(ctx->pwr_id)) {
- return FWK_E_ACCESS;
- }
-
- *mode_type = MOD_VOLTD_MODE_TYPE_ARCH;
-
- if (stm32mp1_pwr_regulator_is_enabled(ctx->pwr_id)) {
- *mode_id = MOD_VOLTD_MODE_ID_ON;
- } else {
- *mode_id = MOD_VOLTD_MODE_ID_OFF;
- }
-
- FWK_LOG_DEBUG(
- MOD_NAME "SCMI voltd %u: get_config PWR#%u = %s",
- fwk_id_get_element_idx(dev_id),
- ctx->pwr_id,
- *mode_id == MOD_VOLTD_MODE_ID_ON ? "on" : "off");
-
- return FWK_SUCCESS;
-}
-
-static int pwr_regu_set_config(fwk_id_t dev_id, uint8_t mode_type,
- uint8_t mode_id)
-{
- struct stm32_pwr_regu_dev_ctx *ctx = NULL;
-
- if (!fwk_module_is_valid_element_id(dev_id) ||
- mode_type != MOD_VOLTD_MODE_TYPE_ARCH ||
- (mode_id == MOD_VOLTD_MODE_ID_ON && mode_id == MOD_VOLTD_MODE_ID_OFF)) {
- return FWK_E_PARAM;
- }
-
- ctx = module_ctx.dev_ctx_table + fwk_id_get_element_idx(dev_id);
-
- if (!nsec_can_access_pwr_regu(ctx->pwr_id)) {
- return FWK_E_ACCESS;
- }
-
- stm32mp1_pwr_regulator_set_state(ctx->pwr_id,
- mode_id == MOD_VOLTD_MODE_ID_ON);
-
- FWK_LOG_DEBUG(
- MOD_NAME "SCMI voltd %u: set_config PWR#%u %s",
- fwk_id_get_element_idx(dev_id),
- ctx->pwr_id,
- mode_id == MOD_VOLTD_MODE_ID_ON ? "on" : "off");
-
- return FWK_SUCCESS;
-}
-
-static int pwr_regu_get_level(fwk_id_t dev_id, int *level_uv)
-{
- struct stm32_pwr_regu_dev_ctx *ctx = NULL;
-
- if (!fwk_module_is_valid_element_id(dev_id) || level_uv == NULL) {
- return FWK_E_PARAM;
- }
-
- ctx = module_ctx.dev_ctx_table + fwk_id_get_element_idx(dev_id);
-
- if (!nsec_can_access_pwr_regu(ctx->pwr_id)) {
- return FWK_E_ACCESS;
- }
-
- *level_uv = pwr_regu_level(ctx->pwr_id);
-
- FWK_LOG_DEBUG(
- MOD_NAME "SCMI voltd %u: get_level PWR#%u = %d",
- fwk_id_get_element_idx(dev_id),
- ctx->pwr_id,
- *level_uv);
-
- return FWK_SUCCESS;
-}
-
-static int pwr_regu_set_level(fwk_id_t dev_id, int level_uv)
-{
- struct stm32_pwr_regu_dev_ctx *ctx = NULL;
-
- if (!fwk_module_is_valid_element_id(dev_id)) {
- return FWK_E_PARAM;
- }
-
- ctx = module_ctx.dev_ctx_table + fwk_id_get_element_idx(dev_id);
-
- if (!nsec_can_access_pwr_regu(ctx->pwr_id)) {
- return FWK_E_ACCESS;
- }
-
- FWK_LOG_DEBUG(
- MOD_NAME "SCMI voltd %u: set_level PWR#%u to %d",
- fwk_id_get_element_idx(dev_id),
- ctx->pwr_id,
- level_uv);
-
- if (level_uv != pwr_regu_level(ctx->pwr_id)) {
- return FWK_E_RANGE;
- }
-
- return FWK_SUCCESS;
-}
-
-static int pwr_regu_get_info(fwk_id_t dev_id, struct mod_voltd_info *info)
-{
- struct stm32_pwr_regu_dev_ctx *ctx = NULL;
-
- if (!fwk_module_is_valid_element_id(dev_id) || info == NULL) {
- return FWK_E_PARAM;
- }
-
- ctx = module_ctx.dev_ctx_table + fwk_id_get_element_idx(dev_id);
-
- if (!nsec_can_access_pwr_regu(ctx->pwr_id)) {
- return FWK_E_ACCESS;
- }
-
- memset(info, 0, sizeof(*info));
- info->level_range.level_type = MOD_VOLTD_VOLTAGE_LEVEL_DISCRETE;
- info->level_range.min_uv = pwr_regu_level(ctx->pwr_id);
- info->level_range.max_uv = info->level_range.min_uv;
- info->level_range.level_count = 1;
- info->name = ctx->name;
-
- FWK_LOG_DEBUG(
- MOD_NAME "SCMI voltd %u: get_info PWR#%u",
- fwk_id_get_element_idx(dev_id),
- ctx->pwr_id);
-
- return FWK_SUCCESS;
-}
-
-static int pwr_regu_level_from_index(fwk_id_t dev_id, unsigned int index,
- int32_t *level_uv)
-{
- struct stm32_pwr_regu_dev_ctx *ctx = NULL;
-
- if (!fwk_module_is_valid_element_id(dev_id) || level_uv == NULL) {
- return FWK_E_PARAM;
- }
-
- ctx = module_ctx.dev_ctx_table + fwk_id_get_element_idx(dev_id);
-
- if (!nsec_can_access_pwr_regu(ctx->pwr_id)) {
- return FWK_E_ACCESS;
- }
-
- if (index > 0) {
- return FWK_E_RANGE;
- }
-
- *level_uv = pwr_regu_level(ctx->pwr_id);
-
- FWK_LOG_DEBUG(
- MOD_NAME "SCMI voltd %u: get_level_from_index PWR#%u = %" PRId32,
- fwk_id_get_element_idx(dev_id),
- ctx->pwr_id,
- *level_uv);
-
- return FWK_SUCCESS;
-}
-
-static const struct mod_voltd_drv_api api_stm32_pwr_regu = {
- .get_config = pwr_regu_get_config,
- .set_config = pwr_regu_set_config,
- .get_level = pwr_regu_get_level,
- .set_level = pwr_regu_set_level,
- .get_info = pwr_regu_get_info,
- .get_level_from_index = pwr_regu_level_from_index,
-};
-
-/*
- * Framework handler functions
- */
-
-static int stm32_pwr_regu_init(fwk_id_t module_id, unsigned int element_count,
- const void *data)
-{
- module_ctx.dev_count = element_count;
-
- if (element_count) {
- module_ctx.dev_ctx_table =
- fwk_mm_calloc(element_count, sizeof(*module_ctx.dev_ctx_table));
- }
-
- return FWK_SUCCESS;
-}
-
-static int stm32_pwr_regu_element_init(fwk_id_t element_id,
- unsigned int unused,
- const void *data)
-{
- struct stm32_pwr_regu_dev_ctx *ctx = NULL;
- const struct mod_stm32_pwr_regu_dev_config *dev_config = data;
-
- if (!fwk_module_is_valid_element_id(element_id)) {
- return FWK_E_PARAM;
- }
-
- ctx = module_ctx.dev_ctx_table + fwk_id_get_element_idx(element_id);
-
- ctx->pwr_id = dev_config->pwr_id;
- ctx->name = dev_config->regu_name;
-
- return FWK_SUCCESS;
-}
-
-static int stm32_pwr_regu_process_bind_request(fwk_id_t requester_id,
- fwk_id_t target_id,
- fwk_id_t api_type,
- const void **api)
-{
- *api = &api_stm32_pwr_regu;
-
- return FWK_SUCCESS;
-}
-
-const struct fwk_module module_stm32_pwr_regu = {
- .type = FWK_MODULE_TYPE_DRIVER,
- .api_count = 1,
- .init = stm32_pwr_regu_init,
- .element_init = stm32_pwr_regu_element_init,
- .process_bind_request = stm32_pwr_regu_process_bind_request,
-};
diff --git a/product/optee-stm32mp1/module/stm32_pmic_regu/CMakeLists.txt b/product/optee-stm32mp1/module/stm32_regu_consumer/CMakeLists.txt
similarity index 64%
rename from product/optee-stm32mp1/module/stm32_pmic_regu/CMakeLists.txt
rename to product/optee-stm32mp1/module/stm32_regu_consumer/CMakeLists.txt
index e93bb764..adf79cfc 100644
--- a/product/optee-stm32mp1/module/stm32_pmic_regu/CMakeLists.txt
+++ b/product/optee-stm32mp1/module/stm32_regu_consumer/CMakeLists.txt
@@ -1,6 +1,6 @@
#
# Arm SCP/MCP Software
-# Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved.
+# Copyright (c) 2023, Linaro Limited and Contributors. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
@@ -9,10 +9,9 @@ add_library(${SCP_MODULE_TARGET} SCP_MODULE)
target_include_directories(${SCP_MODULE_TARGET}
PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include"
- "${SCP_OPTEE_DIR}/core/arch/arm/plat-stm32mp1")
+ "${SCP_OPTEE_DIR}/core/arch/arm/plat-stm32mp2")
target_sources(
- ${SCP_MODULE_TARGET} PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/src/mod_stm32_pmic_regu.c")
+ ${SCP_MODULE_TARGET} PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/src/mod_stm32_regu_consumer.c")
-target_link_libraries(${SCP_MODULE_TARGET}
- PUBLIC module-scmi module-voltage-domain)
+target_link_libraries(${SCP_MODULE_TARGET} PUBLIC module-voltage-domain)
diff --git a/product/optee-stm32mp1/module/stm32_regu_consumer/Module.cmake b/product/optee-stm32mp1/module/stm32_regu_consumer/Module.cmake
new file mode 100644
index 00000000..dc988ed3
--- /dev/null
+++ b/product/optee-stm32mp1/module/stm32_regu_consumer/Module.cmake
@@ -0,0 +1,9 @@
+#
+# Arm SCP/MCP Software
+# Copyright (c) 2023, Linaro Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+set(SCP_MODULE "stm32-regu-consumer")
+set(SCP_MODULE_TARGET "module-stm32-regu-consumer")
diff --git a/product/optee-stm32mp1/module/stm32_regu_consumer/include/mod_stm32_regu_consumer.h b/product/optee-stm32mp1/module/stm32_regu_consumer/include/mod_stm32_regu_consumer.h
new file mode 100644
index 00000000..6671eab3
--- /dev/null
+++ b/product/optee-stm32mp1/module/stm32_regu_consumer/include/mod_stm32_regu_consumer.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2022, STMicroelectronics
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MOD_STM32_REGU_CONSUMER_H
+#define MOD_STM32_REGU_CONSUMER_H
+
+#include <fwk_element.h>
+#include <fwk_macros.h>
+#include <stdint.h>
+#include <stdbool.h>
+
+struct scmi_server_regu_channel;
+struct rdev;
+
+/*!
+ * \brief Platform regulator configuration.
+ */
+struct mod_stm32_regu_consumer_dev_config {
+ struct rdev *rdev;
+ bool default_enabled;
+};
+
+/*
+ * Build SCMI server resource tables for the voltage domains exposed
+ * by platform.
+ *
+ * @plat - reference to platform data
+ * @plat_count - Number of elements in platform data
+ */
+void scmi_server_build_optee_regu_config(struct scmi_server_regu_channel *plat,
+ size_t plat_count);
+
+#endif /* MOD_STM32_REGU_CONSUMER_H */
diff --git a/product/optee-stm32mp1/module/stm32_regu_consumer/src/mod_stm32_regu_consumer.c b/product/optee-stm32mp1/module/stm32_regu_consumer/src/mod_stm32_regu_consumer.c
new file mode 100644
index 00000000..76955728
--- /dev/null
+++ b/product/optee-stm32mp1/module/stm32_regu_consumer/src/mod_stm32_regu_consumer.c
@@ -0,0 +1,343 @@
+/*
+ * Copyright (c) 2017-2019, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2022, STMicroelectronics
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stddef.h>
+
+#include <fwk_log.h>
+#include <fwk_macros.h>
+#include <fwk_mm.h>
+#include <fwk_module.h>
+#include <mod_scmi_std.h>
+#include <mod_stm32_regu_consumer.h>
+#include <mod_voltage_domain.h>
+
+#include <assert.h>
+#include <drivers/regulator.h>
+#include <scmi_regulator_consumer.h>
+#include <trace.h>
+
+#define DEBUG_MSG(...) FMSG(__VA_ARGS__)
+
+/* Device context */
+struct stm32_regu_consumer_dev_ctx {
+ struct rdev *rdev;
+ bool enabled;
+};
+
+/* Module context */
+struct stm32_regu_consumer_ctx {
+ struct stm32_regu_consumer_dev_ctx *dev_ctx_table;
+ unsigned int dev_count;
+};
+
+/* A single instance handles all voltage regulators abstracted by regulator.h */
+static struct stm32_regu_consumer_ctx module_ctx;
+
+static char *regu_name(struct rdev *rdev)
+{
+ if (rdev)
+ return (char *)rdev->reg_name;
+
+ return NULL;
+}
+
+static int find_ctx(fwk_id_t dev_id,
+ struct stm32_regu_consumer_dev_ctx **out_ctx)
+{
+ struct stm32_regu_consumer_dev_ctx *ctx;
+
+ ctx = module_ctx.dev_ctx_table + fwk_id_get_element_idx(dev_id);
+
+ if (!fwk_module_is_valid_element_id(dev_id))
+ return FWK_E_PARAM;
+
+ if (!ctx->rdev)
+ return FWK_E_ACCESS;
+
+ *out_ctx = ctx;
+
+ return FWK_SUCCESS;
+}
+
+static int stm32_regu_consumer_get_config(fwk_id_t dev_id, uint8_t *mode_type,
+ uint8_t *mode_id)
+{
+ struct stm32_regu_consumer_dev_ctx *ctx;
+ int ret;
+
+ ret = find_ctx(dev_id, &ctx);
+ if (ret)
+ return ret;
+
+ *mode_type = MOD_VOLTD_MODE_TYPE_ARCH;
+
+ if (ctx->enabled)
+ *mode_id = MOD_VOLTD_MODE_ID_ON;
+ else
+ *mode_id = MOD_VOLTD_MODE_ID_OFF;
+
+ DEBUG_MSG("SCMI voltd %u: get config PMIC %s = %#"PRIx8", %#"PRIx8,
+ fwk_id_get_element_idx(dev_id), regu_name(ctx->rdev), *mode_type,
+ *mode_id);
+
+ return FWK_SUCCESS;
+}
+
+static int stm32_regu_consumer_set_config(fwk_id_t dev_id, uint8_t mode_type,
+ uint8_t mode_id)
+{
+ struct stm32_regu_consumer_dev_ctx *ctx;
+ int ret;
+
+ ret = find_ctx(dev_id, &ctx);
+ if (ret)
+ return ret;
+
+ if (mode_type != MOD_VOLTD_MODE_TYPE_ARCH) {
+ return FWK_E_PARAM;
+ }
+
+ switch (mode_id) {
+ case MOD_VOLTD_MODE_ID_ON:
+ if (!ctx->enabled) {
+ if (regulator_enable(ctx->rdev))
+ return FWK_E_DEVICE;
+
+ ctx->enabled = true;
+ }
+ break;
+
+ case MOD_VOLTD_MODE_ID_OFF:
+ if (ctx->enabled) {
+ if (regulator_disable(ctx->rdev))
+ return FWK_E_DEVICE;
+
+ ctx->enabled = false;
+ }
+ break;
+
+ default:
+ return FWK_E_PARAM;
+ }
+
+ DEBUG_MSG("SCMI voltd %u: set config PMIC %s to type %#"PRIx8" / mode %#"PRIx8,
+ fwk_id_get_element_idx(dev_id), regu_name(ctx->rdev), mode_type,
+ mode_id);
+
+ return FWK_SUCCESS;
+}
+
+static int stm32_regu_consumer_get_level(fwk_id_t dev_id, int *level_uv)
+{
+ struct stm32_regu_consumer_dev_ctx *ctx;
+ uint16_t level_mv;
+ int ret;
+
+ ret = find_ctx(dev_id, &ctx);
+ if (ret)
+ return ret;
+
+ if (regulator_get_voltage(ctx->rdev, &level_mv))
+ return FWK_E_PANIC;
+
+ *level_uv = (int)level_mv * 1000;
+
+ DEBUG_MSG("SCMI voltd %u: get level PMIC %s = %d",
+ fwk_id_get_element_idx(dev_id), regu_name(ctx->rdev), *level_uv);
+
+ return FWK_SUCCESS;
+}
+
+static int stm32_regu_consumer_set_level(fwk_id_t dev_id, int level_uv)
+{
+ struct stm32_regu_consumer_dev_ctx *ctx = NULL;
+ int ret = FWK_E_PANIC;
+
+ if (level_uv / 1000 > UINT16_MAX) {
+ FWK_LOG_ERR("Volatge level too high (mV shall fit in 16 bits)");
+ return FWK_E_PARAM;
+ }
+
+ ret = find_ctx(dev_id, &ctx);
+ if (ret)
+ return ret;
+
+ if (regulator_set_voltage(ctx->rdev, level_uv / 1000))
+ return FWK_E_DEVICE;
+
+ DEBUG_MSG("SCMI voltd %u: set level PMIC %s to %d",
+ fwk_id_get_element_idx(dev_id), regu_name(ctx->rdev), level_uv);
+
+ return FWK_SUCCESS;
+}
+
+static void find_bound_uv(const uint16_t *levels, size_t count,
+ int32_t *min, int32_t *max)
+{
+ size_t n = 0;
+
+ *min = INT32_MAX;
+ *max = INT32_MIN;
+
+ for (n = 0; n < count; n++) {
+ if (*min > levels[n])
+ *min = levels[n];
+ if (*max < levels[n])
+ *max = levels[n];
+ }
+
+ /* Convert from mV to uV */
+ *min *= 1000;
+ *max *= 1000;
+}
+
+static int stm32_regu_consumer_get_info(fwk_id_t dev_id,
+ struct mod_voltd_info *info)
+{
+ struct stm32_regu_consumer_dev_ctx *ctx;
+ uint16_t *levels;
+ size_t full_count;
+ int ret;
+
+ ret = find_ctx(dev_id, &ctx);
+ if (ret == FWK_E_ACCESS) {
+ static const char reserved[] = "reserved";
+
+ memset(info, 0, sizeof(*info));
+ info->name = reserved;
+ info->level_range.level_type = MOD_VOLTD_VOLTAGE_LEVEL_DISCRETE;
+ info->level_range.level_count = 1;
+ info->level_range.min_uv = 0;
+ info->level_range.max_uv = 0;
+
+ return FWK_SUCCESS;
+ } else if (ret != FWK_SUCCESS) {
+ return ret;
+ }
+
+ if (regulator_list_voltages(ctx->rdev, &levels, &full_count)) {
+ return FWK_E_SUPPORT;
+ }
+
+ memset(info, 0, sizeof(*info));
+ info->name = regu_name(ctx->rdev);
+ info->level_range.level_type = MOD_VOLTD_VOLTAGE_LEVEL_DISCRETE;
+ info->level_range.level_count = full_count;
+ find_bound_uv(levels, full_count,
+ &info->level_range.min_uv, &info->level_range.max_uv);
+
+ DEBUG_MSG("SCMI voltd %u: get_info PMIC %s, range [%d %d]",
+ fwk_id_get_element_idx(dev_id), regu_name(ctx->rdev),
+ info->level_range.min_uv, info->level_range.max_uv);
+
+ return FWK_SUCCESS;
+}
+
+static int stm32_regu_consumer_level_from_index(fwk_id_t dev_id,
+ unsigned int index,
+ int32_t *level_uv)
+{
+ struct stm32_regu_consumer_dev_ctx *ctx;
+ uint16_t *levels;
+ size_t full_count;
+ int ret;
+
+ ret = find_ctx(dev_id, &ctx);
+ if (ret == FWK_E_ACCESS) {
+ if (index > 0) {
+ return FWK_E_RANGE;
+ }
+ *level_uv = 0;
+
+ return FWK_SUCCESS;
+ } else if (ret != FWK_SUCCESS) {
+ return ret;
+ }
+
+ if (regulator_list_voltages(ctx->rdev, &levels, &full_count)) {
+ return FWK_E_SUPPORT;
+ }
+
+ if (index >= full_count)
+ return FWK_E_RANGE;
+
+ *level_uv = (int32_t)levels[index] * 1000;
+
+ DEBUG_MSG("SCMI voltd %u: get level PMIC %s = %"PRId32,
+ fwk_id_get_element_idx(dev_id), regu_name(ctx->rdev), *level_uv);
+
+ return FWK_SUCCESS;
+}
+
+static const struct mod_voltd_drv_api api_optee_regu = {
+ .get_level = stm32_regu_consumer_get_level,
+ .set_level = stm32_regu_consumer_set_level,
+ .set_config = stm32_regu_consumer_set_config,
+ .get_config = stm32_regu_consumer_get_config,
+ .get_info = stm32_regu_consumer_get_info,
+ .get_level_from_index = stm32_regu_consumer_level_from_index,
+};
+
+/*
+ * Framework handler functions
+ */
+
+static int stm32_regu_consumer_init(fwk_id_t module_id,
+ unsigned int element_count,
+ const void *data)
+{
+ module_ctx.dev_count = element_count;
+
+ if (element_count)
+ module_ctx.dev_ctx_table =
+ fwk_mm_calloc(element_count, sizeof(*module_ctx.dev_ctx_table));
+
+ return FWK_SUCCESS;
+}
+
+static int stm32_regu_consumer_element_init(fwk_id_t element_id,
+ unsigned int unused,
+ const void *data)
+{
+ const struct mod_stm32_regu_consumer_dev_config *dev_config = data;
+ struct stm32_regu_consumer_dev_ctx *ctx;
+
+ if (!fwk_module_is_valid_element_id(element_id))
+ return FWK_E_PANIC;
+
+ ctx = module_ctx.dev_ctx_table + fwk_id_get_element_idx(element_id);
+
+ ctx->rdev = dev_config->rdev;
+ ctx->enabled = dev_config->default_enabled;
+
+ if (ctx->enabled) {
+ if (!ctx->rdev)
+ return FWK_E_PARAM;
+ if (regulator_enable(ctx->rdev))
+ return FWK_E_DEVICE;
+ }
+
+ return FWK_SUCCESS;
+}
+
+static int stm32_regu_consumer_process_bind_request(fwk_id_t requester_id,
+ fwk_id_t target_id,
+ fwk_id_t api_type,
+ const void **api)
+{
+ *api = &api_optee_regu;
+
+ return FWK_SUCCESS;
+}
+
+const struct fwk_module module_stm32_regu_consumer = {
+ .type = FWK_MODULE_TYPE_DRIVER,
+ .api_count = 1,
+ .init = stm32_regu_consumer_init,
+ .element_init = stm32_regu_consumer_element_init,
+ .process_bind_request = stm32_regu_consumer_process_bind_request,
+};
diff --git a/product/optee-stm32mp2/fw/CMakeLists.txt b/product/optee-stm32mp2/fw/CMakeLists.txt
new file mode 100644
index 00000000..8674a1eb
--- /dev/null
+++ b/product/optee-stm32mp2/fw/CMakeLists.txt
@@ -0,0 +1,24 @@
+#
+# Arm SCP/MCP Software
+# Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+#
+# Create the firmware target.
+#
+
+add_library(${SCP_FIRMWARE_TARGET})
+
+# cmake-lint: disable=E1122
+
+target_include_directories(
+ ${SCP_FIRMWARE_TARGET}
+ PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/../include"
+ "${CMAKE_CURRENT_SOURCE_DIR}")
+
+target_sources(
+ ${SCP_FIRMWARE_TARGET}
+ PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/config_all.c"
+)
diff --git a/product/optee-stm32mp2/fw/Firmware.cmake b/product/optee-stm32mp2/fw/Firmware.cmake
new file mode 100644
index 00000000..0e5b0665
--- /dev/null
+++ b/product/optee-stm32mp2/fw/Firmware.cmake
@@ -0,0 +1,57 @@
+#
+# Arm SCP/MCP Software
+# Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+#
+# Configure the build system.
+#
+
+set(SCP_FIRMWARE "scmi-fw")
+
+set(SCP_FIRMWARE_TARGET "scmi-fw")
+
+set(SCP_TOOLCHAIN_INIT "GNU")
+
+set(SCP_ARCHITECTURE "optee")
+
+set(CMAKE_BUILD_TYPE "Release")
+
+set(SCP_ENABLE_NOTIFICATIONS_INIT FALSE)
+
+set(SCP_ENABLE_SCMI_NOTIFICATIONS_INIT FALSE)
+
+set(SCP_ENABLE_SCMI_SENSOR_EVENTS_INIT FALSE)
+
+set(SCP_ENABLE_FAST_CHANNELS_INIT FALSE)
+
+set(SCP_ENABLE_SCMI_RESET_INIT TRUE)
+
+set(SCP_ENABLE_IPO_INIT FALSE)
+
+list(PREPEND SCP_MODULE_PATHS "${CMAKE_CURRENT_LIST_DIR}/../module/stm32_regu_consumer")
+list(PREPEND SCP_MODULE_PATHS "${CMAKE_CURRENT_LIST_DIR}/../module/psu_optee_regulator")
+
+# The order of the modules in the following list is the order in which the
+# modules are initialized, bound, started during the pre-runtime phase.
+# any change in the order will cause firmware initialization errors.
+
+list(APPEND SCP_MODULES "optee-mbx")
+list(APPEND SCP_MODULES "msg-smt")
+list(APPEND SCP_MODULES "scmi")
+list(APPEND SCP_MODULES "optee-clock")
+list(APPEND SCP_MODULES "clock")
+list(APPEND SCP_MODULES "scmi-clock")
+list(APPEND SCP_MODULES "optee-reset")
+list(APPEND SCP_MODULES "reset-domain")
+list(APPEND SCP_MODULES "scmi-reset-domain")
+list(APPEND SCP_MODULES "stm32-regu-consumer")
+list(APPEND SCP_MODULES "voltage-domain")
+list(APPEND SCP_MODULES "scmi-voltage-domain")
+list(APPEND SCP_MODULES "psu-optee-regulator")
+list(APPEND SCP_MODULES "psu")
+list(APPEND SCP_MODULES "dvfs")
+list(APPEND SCP_MODULES "scmi-perf")
+list(APPEND SCP_MODULES "optee-console")
diff --git a/product/optee-stm32mp2/fw/Toolchain-GNU.cmake b/product/optee-stm32mp2/fw/Toolchain-GNU.cmake
new file mode 100644
index 00000000..ab5d91f2
--- /dev/null
+++ b/product/optee-stm32mp2/fw/Toolchain-GNU.cmake
@@ -0,0 +1,22 @@
+#
+# Arm SCP/MCP Software
+# Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+include_guard()
+
+set(CMAKE_SYSTEM_PROCESSOR "optee")
+set(CMAKE_TOOLCHAIN_PREFIX ${CFG_CROSS_COMPILE})
+
+set(CMAKE_ASM_COMPILER_TARGET ${CFG_CROSS_COMPILE})
+set(CMAKE_C_COMPILER_TARGET ${CFG_CROSS_COMPILE})
+set(CMAKE_CXX_COMPILER_TARGET ${CFG_CROSS_COMPILE})
+
+include(
+ "${CMAKE_CURRENT_LIST_DIR}/../../../cmake/Toolchain/GNU-Baremetal.cmake")
+
+foreach(language IN ITEMS ASM C CXX)
+ string(APPEND CMAKE_${language}_FLAGS_INIT ${CFG_CFLAGS_OPTEE})
+endforeach()
diff --git a/product/optee-stm32mp2/fw/config_all.c b/product/optee-stm32mp2/fw/config_all.c
new file mode 100644
index 00000000..3aa24d76
--- /dev/null
+++ b/product/optee-stm32mp2/fw/config_all.c
@@ -0,0 +1,793 @@
+/*
+ * Arm SCP/MCP Software
+ * Copyright (c) 2022-2023, Linaro Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <fwk_assert.h>
+#include <fwk_element.h>
+#include <fwk_id.h>
+#include <fwk_mm.h>
+#include <fwk_module.h>
+#include <fwk_module_idx.h>
+
+#include <mod_clock.h>
+#include <mod_dvfs.h>
+#include <mod_msg_smt.h>
+#include <mod_optee_clock.h>
+#include <mod_optee_mbx.h>
+#include <mod_optee_reset.h>
+#include <mod_psu.h>
+#include <mod_psu_optee_regulator.h>
+#include <mod_reset_domain.h>
+#include <mod_scmi.h>
+#include <mod_scmi_clock.h>
+#include <mod_scmi_perf.h>
+#include <mod_scmi_reset_domain.h>
+#include <mod_scmi_voltage_domain.h>
+#include <mod_stm32_regu_consumer.h>
+#include <mod_voltage_domain.h>
+#include <scmi_agents.h>
+
+#include <assert.h>
+#include <stddef.h>
+#include <stdint.h>
+
+#include <drivers/regulator.h>
+#include <drivers/stm32mp_dt_bindings.h>
+#include <kernel/panic.h>
+#include <scmi_agent_configuration.h>
+#include <stm32_util.h>
+#include <util.h>
+
+/* SCMI agent and services (channels) */
+static struct mod_scmi_agent *scmi_agent_table;
+static struct mod_scmi_config scmi_data;
+static struct fwk_element *scmi_service_elt;
+
+/* SCMI channel mailbox/shmem */
+static struct fwk_element *msg_smt_elt;
+static struct mod_msg_smt_channel_config *msg_smt_data;
+static struct fwk_element *optee_mbx_elt;
+static struct mod_optee_mbx_channel_config *optee_mbx_data;
+
+#ifdef CFG_SCPFW_MOD_SCMI_CLOCK
+/* SCMI clock generic */
+static struct mod_scmi_clock_agent *scmi_clk_agent_tbl;
+#endif
+
+#ifdef CFG_SCPFW_MOD_CLOCK
+/* Clocks and optee/clock, same number/indices. Elements and configuration data */
+static struct fwk_element *optee_clock_elt; /* Optee/clock elements */
+static struct mod_optee_clock_config *optee_clock_cfg; /* Config data for optee/clock elements */
+static struct fwk_element *clock_elt; /* Clock elements */
+static struct mod_clock_dev_config *clock_data; /* Config data for clock elements */
+#endif
+
+#ifdef CFG_SCPFW_MOD_DVFS
+/* 1 DVFS (elt & data) per DVFS exposed */
+static struct mod_dvfs_domain_config *dvfs_data;
+static struct fwk_element *dvfs_elt;
+/* A unique scmi_perf instance refers to perf domains data (DVFS instance) */
+static struct mod_scmi_perf_domain_config *scmi_perf_domain_data;
+struct fwk_module_config config_scmi_perf;
+
+/* PSU and optee/psu-regu, used with DVFS. Elements and configuration data */
+static struct fwk_element *psu_optee_regu_elt;
+static struct mod_psu_optee_regulator_dev_config *psu_optee_regu_data;
+static struct fwk_element *psu_elt;
+static struct mod_psu_element_cfg *psu_data;
+#endif
+
+#ifdef CFG_SCPFW_MOD_RESET_DOMAIN
+/* SCMI reset domains and optee reset controller */
+static struct mod_scmi_reset_domain_agent *scmi_reset_agent_tbl;
+static struct fwk_element *optee_reset_elt;
+static struct mod_optee_reset_dev_config *optee_reset_data;
+static struct fwk_element *reset_elt;
+static struct mod_reset_domain_dev_config *reset_data;
+#endif
+
+#ifdef CFG_SCPFW_MOD_VOLTAGE_DOMAIN
+/* SCMI voltage domains and optee regulators */
+static struct mod_scmi_voltd_agent *scmi_voltd_agent_tbl;
+static struct fwk_element *optee_regu_elt;
+static struct mod_stm32_regu_consumer_dev_config *optee_regu_data;
+static struct fwk_element *voltd_elt;
+static struct mod_voltd_dev_config *voltd_data;
+#endif
+
+/* Config data for scmi module */
+static const struct fwk_element *get_scmi_service_table(fwk_id_t module_id)
+{
+ return scmi_service_elt; /* scmi_service_elt filled during initialization */
+}
+
+struct fwk_module_config config_scmi = {
+ .data = (void *)&scmi_data, /* scmi_data filled during initialization */
+ .elements = FWK_MODULE_DYNAMIC_ELEMENTS(get_scmi_service_table),
+};
+
+/* Config data for optee_mbx module */
+static const struct fwk_element *optee_mbx_get_element_table(fwk_id_t module_id)
+{
+ return (const struct fwk_element *)optee_mbx_elt;
+}
+
+struct fwk_module_config config_optee_mbx = {
+ .elements = FWK_MODULE_DYNAMIC_ELEMENTS(optee_mbx_get_element_table),
+};
+
+/* Config data for msg_smt module */
+static const struct fwk_element *msg_smt_get_element_table(fwk_id_t module_id)
+{
+ fwk_assert(fwk_id_get_module_idx(module_id) == FWK_MODULE_IDX_MSG_SMT);
+ return (const struct fwk_element *)msg_smt_elt;
+}
+
+struct fwk_module_config config_msg_smt = {
+ .elements = FWK_MODULE_DYNAMIC_ELEMENTS(msg_smt_get_element_table),
+};
+
+/* Config data for scmi_clock, clock and optee_clock modules */
+#ifdef CFG_SCPFW_MOD_SCMI_CLOCK
+struct fwk_module_config config_scmi_clock = {
+ .data = &((struct mod_scmi_clock_config){
+ .agent_table = NULL, /* Allocated during initialization */
+ .agent_count = 0, /* Set during initialization */
+ }),
+};
+#endif
+
+#ifdef CFG_SCPFW_MOD_CLOCK
+static const struct fwk_element *clock_get_element_table(fwk_id_t module_id)
+{
+ fwk_assert(fwk_id_get_module_idx(module_id) == FWK_MODULE_IDX_CLOCK);
+ return (const struct fwk_element *)clock_elt;
+}
+
+struct fwk_module_config config_clock = {
+ .elements = FWK_MODULE_DYNAMIC_ELEMENTS(clock_get_element_table),
+};
+
+static const struct fwk_element *optee_clock_get_element_table(fwk_id_t module_id)
+{
+ fwk_assert(fwk_id_get_module_idx(module_id) == FWK_MODULE_IDX_OPTEE_CLOCK);
+ return (const struct fwk_element *)optee_clock_elt;
+}
+
+struct fwk_module_config config_optee_clock = {
+ .elements = FWK_MODULE_DYNAMIC_ELEMENTS(optee_clock_get_element_table),
+};
+#endif
+
+/* Config data for scmi_reset_domain, reset_domain and optee_reset modules */
+#ifdef CFG_SCPFW_MOD_RESET_DOMAIN
+struct fwk_module_config config_scmi_reset_domain = {
+ .data = &((struct mod_scmi_reset_domain_config){
+ .agent_table = NULL, /* Allocated during initialization */
+ .agent_count = 0, /* Set during initialization */
+ }),
+};
+
+static const struct fwk_element *reset_get_element_table(fwk_id_t module_id)
+{
+ fwk_assert(fwk_id_get_module_idx(module_id) == FWK_MODULE_IDX_RESET_DOMAIN);
+ return (const struct fwk_element *)reset_elt;
+}
+
+struct fwk_module_config config_reset_domain = {
+ .elements = FWK_MODULE_DYNAMIC_ELEMENTS(reset_get_element_table),
+};
+
+static const struct fwk_element *optee_reset_get_element_table(fwk_id_t module_id)
+{
+ fwk_assert(fwk_id_get_module_idx(module_id) == FWK_MODULE_IDX_OPTEE_RESET);
+ return (const struct fwk_element *)optee_reset_elt;
+}
+
+struct fwk_module_config config_optee_reset = {
+ .elements = FWK_MODULE_DYNAMIC_ELEMENTS(optee_reset_get_element_table),
+};
+#endif
+
+#ifdef CFG_SCPFW_MOD_VOLTAGE_DOMAIN
+/* Config data for scmi_voltage_domain, voltage_domain and optee_regu modules */
+struct fwk_module_config config_scmi_voltage_domain = {
+ .data = &((struct mod_scmi_voltd_config){
+ .agent_table = NULL, /* Allocated during initialization */
+ .agent_count = 0, /* Set during initialization */
+ }),
+};
+
+static const struct fwk_element *voltd_get_element_table(fwk_id_t module_id)
+{
+ fwk_assert(fwk_id_get_module_idx(module_id) == FWK_MODULE_IDX_VOLTAGE_DOMAIN);
+ return (const struct fwk_element *)voltd_elt;
+}
+
+struct fwk_module_config config_voltage_domain = {
+ .elements = FWK_MODULE_DYNAMIC_ELEMENTS(voltd_get_element_table),
+};
+
+static const struct fwk_element *stm32_regu_consumer_get_element_table(fwk_id_t module_id)
+{
+ fwk_assert(fwk_id_get_module_idx(module_id) == FWK_MODULE_IDX_STM32_REGU_CONSUMER);
+ return (const struct fwk_element *)optee_regu_elt;
+}
+
+struct fwk_module_config config_stm32_regu_consumer = {
+ .elements = FWK_MODULE_DYNAMIC_ELEMENTS(stm32_regu_consumer_get_element_table),
+};
+#endif
+
+#ifdef CFG_SCPFW_MOD_DVFS
+/* Config data for scmi_perf and dvfs module */
+struct fwk_module_config config_scmi_perf = {
+ .data = &((struct mod_scmi_perf_config){
+ .domains = NULL, /* Allocated during initialization */
+ .perf_doms_count = 0, /* Set during initialization */
+ .fast_channels_alarm_id = FWK_ID_NONE_INIT,
+#ifdef BUILD_HAS_MOD_STATISTICS
+ .stats_enabled = true,
+#endif
+ }),
+};
+
+static const struct fwk_element *dvfs_get_element_table(fwk_id_t module_id)
+{
+ fwk_assert(fwk_id_get_module_idx(module_id) == FWK_MODULE_IDX_DVFS);
+ return (const struct fwk_element *)dvfs_elt;
+}
+
+struct fwk_module_config config_dvfs = {
+ .elements = FWK_MODULE_DYNAMIC_ELEMENTS(dvfs_get_element_table),
+};
+
+/* Config data for psu and optee/psu module */
+static const struct fwk_element *psu_get_element_table(fwk_id_t module_id)
+{
+ fwk_assert(fwk_id_get_module_idx(module_id) == FWK_MODULE_IDX_PSU);
+ return (const struct fwk_element *)psu_elt;
+}
+
+struct fwk_module_config config_psu = {
+ .elements = FWK_MODULE_DYNAMIC_ELEMENTS(psu_get_element_table),
+};
+
+static const struct fwk_element *psu_optee_regu_get_element_table(fwk_id_t module_id)
+{
+ fwk_assert(fwk_id_get_module_idx(module_id) == FWK_MODULE_IDX_PSU_OPTEE_REGULATOR);
+ return (const struct fwk_element *)psu_optee_regu_elt ;
+}
+
+struct fwk_module_config config_psu_optee_regulator = {
+ .elements = FWK_MODULE_DYNAMIC_ELEMENTS(psu_optee_regu_get_element_table),
+};
+#endif
+
+/*
+ * Indices state when applying agents configuration
+ * @channel_count: Number of channels (mailbox/shmem links) used
+ * @clock_index: Current index for clock and optee/clock (same indices)
+ * @clock_count: Number of clocks (also number of optee/clocks)
+ * @reset_index: Current index for reset controller and optee/reset
+ * @reset_count: Number of reset controller (optee/reset) instances
+ * @regu_index: Current index for voltd and optee/regulator
+ * @regu_count: Number of voltd (optee/regulator) instances
+ * @psu_index: Current index for PSU and optee/PSU instances
+ * @psu_count: Number of PSU (optee/PSU) instances
+ * @dvfs_index: Current index for DVFS instance
+ * @dvfs_count: Number of DVFS instances
+ */
+struct scpfw_resource_counter {
+ size_t channel_count;
+ size_t clock_index;
+ size_t clock_count;
+ size_t reset_index;
+ size_t reset_count;
+ size_t regu_index;
+ size_t regu_count;
+ size_t psu_index;
+ size_t psu_count;
+ size_t dvfs_index;
+ size_t dvfs_count;
+} scpfw_resource_counter;
+
+/*
+ * Count once for all the several instances and allocate global resources.
+ * Global resources are clock, optee/clock, reset, optee/reset, regu,
+ * optee/regu, psu, optee/psu, dvfs, perfd, ...;
+ */
+static void count_resources(struct scpfw_config *cfg)
+{
+ size_t i, j;
+
+ for (i = 0; i < cfg->agent_count; i++) {
+ struct scpfw_agent_config *agent_cfg = cfg->agent_config + i;
+
+ scpfw_resource_counter.channel_count += agent_cfg->channel_count;
+
+ for (j = 0; j < agent_cfg->channel_count; j++) {
+ struct scpfw_channel_config *channel_cfg = agent_cfg->channel_config + j;
+
+ /* Clocks for scmi_clock and for DVFS */
+ scpfw_resource_counter.clock_count += channel_cfg->clock_count;
+ scpfw_resource_counter.clock_count += channel_cfg->perfd_count;
+ /* Reset for smci_reset only */
+ scpfw_resource_counter.reset_count += channel_cfg->reset_count;
+ /* Regulators for smci_voltage_domain only */
+ scpfw_resource_counter.regu_count += channel_cfg->voltd_count;
+ /* DVFS and PSU DVFS only */
+ scpfw_resource_counter.dvfs_count += channel_cfg->perfd_count;
+ scpfw_resource_counter.psu_count += channel_cfg->perfd_count;
+ }
+ }
+
+#ifndef CFG_SCPFW_MOD_CLOCK
+ fwk_assert(!scpfw_resource_counter.clock_count);
+#endif
+#ifndef CFG_SCPFW_MOD_RESET_DOMAIN
+ fwk_assert(!scpfw_resource_counter.reset_count);
+#endif
+#ifndef CFG_SCPFW_MOD_VOLTAGE_DOMAIN
+ fwk_assert(!scpfw_resource_counter.regu_count);
+#endif
+#ifndef CFG_SCPFW_MOD_DVFS
+ fwk_assert(!scpfw_resource_counter.dvfs_count);
+#endif
+#ifndef CFG_SCPFW_MOD_PSU
+ fwk_assert(!scpfw_resource_counter.psu_count);
+#endif
+}
+
+/*
+ * Allocate all tables that may be needed. An optimized implementation would
+ * allocate a single piece of memory and set the pointers accordingly.
+ * */
+static void allocate_global_resources(struct scpfw_config *cfg)
+{
+ struct mod_scmi_reset_domain_config *scmi_reset_config __maybe_unused;
+ struct mod_scmi_voltd_config *scmi_voltd_config __maybe_unused;
+ struct mod_scmi_clock_config *scmi_clock_config __maybe_unused;
+ /* @cfg does not consider agent #0 this the reserved platform/server agent */
+ size_t __maybe_unused scmi_agent_count = cfg->agent_count + 1;
+
+#ifdef CFG_SCPFW_MOD_SCMI_CLOCK
+ /* SCMI clock domains resources */
+ scmi_clk_agent_tbl = fwk_mm_calloc(scmi_agent_count,
+ sizeof(*scmi_clk_agent_tbl));
+ scmi_clock_config = (void *)config_scmi_clock.data;
+ scmi_clock_config->agent_table = scmi_clk_agent_tbl;
+ scmi_clock_config->agent_count = scmi_agent_count;
+#endif
+
+#ifdef CFG_SCPFW_MOD_CLOCK
+ /* Clock domains resources */
+ optee_clock_cfg = fwk_mm_calloc(scpfw_resource_counter.clock_count,
+ sizeof(*optee_clock_cfg));
+ optee_clock_elt = fwk_mm_calloc(scpfw_resource_counter.clock_count + 1,
+ sizeof(*optee_clock_elt));
+
+ clock_data = fwk_mm_calloc(scpfw_resource_counter.clock_count,
+ sizeof(*clock_data));
+ clock_elt = fwk_mm_calloc(scpfw_resource_counter.clock_count + 1,
+ sizeof(*clock_elt));
+#endif
+
+#ifdef CFG_SCPFW_MOD_RESET_DOMAIN
+ /* SCMI reset domains resources */
+ scmi_reset_agent_tbl = fwk_mm_calloc(scmi_agent_count,
+ sizeof(*scmi_reset_agent_tbl));
+ scmi_reset_config = (void *)config_scmi_reset_domain.data;
+ scmi_reset_config->agent_table = scmi_reset_agent_tbl;
+ scmi_reset_config->agent_count = scmi_agent_count;
+
+ optee_reset_data = fwk_mm_calloc(scpfw_resource_counter.reset_count,
+ sizeof(*optee_reset_data));
+ optee_reset_elt = fwk_mm_calloc(scpfw_resource_counter.reset_count + 1,
+ sizeof(*optee_reset_elt));
+
+ reset_data = fwk_mm_calloc(scpfw_resource_counter.reset_count,
+ sizeof(*reset_data));
+ reset_elt = fwk_mm_calloc(scpfw_resource_counter.reset_count + 1,
+ sizeof(*reset_elt));
+#endif
+
+#ifdef CFG_SCPFW_MOD_DVFS
+ /* PSU and related optee PSU regulator resources */
+ psu_optee_regu_elt = fwk_mm_calloc(scpfw_resource_counter.dvfs_count + 1,
+ sizeof(*psu_optee_regu_elt));
+ psu_optee_regu_data = fwk_mm_calloc(scpfw_resource_counter.dvfs_count,
+ sizeof(*psu_optee_regu_data));
+
+ psu_elt = fwk_mm_calloc(scpfw_resource_counter.psu_count + 1,
+ sizeof(*psu_elt));
+ psu_data = fwk_mm_calloc(scpfw_resource_counter.psu_count,
+ sizeof(*psu_data));
+
+ /* DVFS and SCMI performance management resources */
+ dvfs_elt = fwk_mm_calloc(scpfw_resource_counter.dvfs_count + 1,
+ sizeof(*dvfs_elt));
+ dvfs_data = fwk_mm_calloc(scpfw_resource_counter.dvfs_count,
+ sizeof(*dvfs_data));
+
+ scmi_perf_domain_data = fwk_mm_calloc(scpfw_resource_counter.dvfs_count,
+ sizeof(*scmi_perf_domain_data));
+#endif
+
+#ifdef CFG_SCPFW_MOD_VOLTAGE_DOMAIN
+ /* SCMI voltage domains resources */
+ scmi_voltd_agent_tbl = fwk_mm_calloc(scmi_agent_count,
+ sizeof(*scmi_voltd_agent_tbl));
+ scmi_voltd_config = (void *)config_scmi_voltage_domain.data;
+ scmi_voltd_config->agent_table = scmi_voltd_agent_tbl;
+ scmi_voltd_config->agent_count = scmi_agent_count;
+
+ optee_regu_data = fwk_mm_calloc(scpfw_resource_counter.regu_count,
+ sizeof(*optee_regu_data));
+ optee_regu_elt = fwk_mm_calloc(scpfw_resource_counter.regu_count + 1,
+ sizeof(*optee_regu_elt));
+
+ voltd_data = fwk_mm_calloc(scpfw_resource_counter.regu_count,
+ sizeof(*voltd_data));
+ voltd_elt = fwk_mm_calloc(scpfw_resource_counter.regu_count + 1,
+ sizeof(*voltd_elt));
+#endif
+}
+
+static void set_scmi_comm_resources(struct scpfw_config *cfg)
+{
+ unsigned int channel_index;
+ size_t i, j;
+ /* @cfg does not consider agent #0 this the reserved platform/server agent */
+ size_t scmi_agent_count = cfg->agent_count + 1;
+
+ scmi_agent_table = fwk_mm_calloc(scmi_agent_count,
+ sizeof(*scmi_agent_table));
+
+ scmi_service_elt = fwk_mm_calloc(scpfw_resource_counter.channel_count + 1,
+ sizeof(*scmi_service_elt));
+
+ msg_smt_elt = fwk_mm_calloc(scpfw_resource_counter.channel_count + 1,
+ sizeof(*msg_smt_elt));
+ msg_smt_data = fwk_mm_calloc(scpfw_resource_counter.channel_count,
+ sizeof(*msg_smt_data));
+
+ optee_mbx_elt = fwk_mm_calloc(scpfw_resource_counter.channel_count + 1,
+ sizeof(*optee_mbx_elt));
+ optee_mbx_data = fwk_mm_calloc(scpfw_resource_counter.channel_count,
+ sizeof(*optee_mbx_data));
+
+ /* Set now the uniqnue scmi module instance configuration data */
+ scmi_data = (struct mod_scmi_config){
+ .agent_table = scmi_agent_table,
+ .agent_count = scmi_agent_count,
+ .protocol_count_max = 9,
+ .vendor_identifier = "STMicroelectronics",
+ .sub_vendor_identifier = "STMicroelectronics",
+ };
+
+ channel_index = 0;
+
+ for (i = 0; i < cfg->agent_count; i++) {
+ struct scpfw_agent_config *agent_cfg = cfg->agent_config + i;
+ size_t agent_index = i + 1;
+
+ scmi_agent_table[agent_index].type = SCMI_AGENT_TYPE_OSPM;
+ scmi_agent_table[agent_index].name = agent_cfg->name;
+
+ for (j = 0; j < agent_cfg->channel_count; j++) {
+ struct scpfw_channel_config *channel_cfg = agent_cfg->channel_config + j;
+ struct mod_scmi_service_config *service_data;
+
+ service_data = fwk_mm_calloc(1, sizeof(*service_data));
+ *service_data = (struct mod_scmi_service_config){
+ .transport_id = (fwk_id_t)FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_MSG_SMT, 0),
+ .transport_api_id = (fwk_id_t)FWK_ID_API_INIT(FWK_MODULE_IDX_MSG_SMT,
+ MOD_MSG_SMT_API_IDX_SCMI_TRANSPORT),
+ .scmi_agent_id = agent_cfg->agent_id,
+ .scmi_p2a_id = FWK_ID_NONE_INIT,
+ };
+
+ /* Currently expect 1 agent with ID SCMI_AGENT_ID_NSEC0 (1) */
+ fwk_assert(service_data->scmi_agent_id == SCMI_AGENT_ID_NSEC0);
+
+ scmi_service_elt[channel_index].name = channel_cfg->name;
+ scmi_service_elt[channel_index].data = service_data;
+
+ msg_smt_elt[channel_index].name = channel_cfg->name;
+ msg_smt_elt[channel_index].data = (void *)(msg_smt_data + channel_index);
+
+ msg_smt_data[channel_index] = (struct mod_msg_smt_channel_config){
+ .type = MOD_MSG_SMT_CHANNEL_TYPE_REQUESTER,
+ .mailbox_size = 128,
+ .driver_id = (fwk_id_t)FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_OPTEE_MBX,
+ channel_index),
+ .driver_api_id = (fwk_id_t)FWK_ID_API_INIT(FWK_MODULE_IDX_OPTEE_MBX, 0),
+ };
+
+ optee_mbx_elt[channel_index].name = channel_cfg->name;
+ optee_mbx_elt[channel_index].data = (void *)(optee_mbx_data + channel_index);
+
+ optee_mbx_data[channel_index] = (struct mod_optee_mbx_channel_config){
+ .driver_id = (fwk_id_t)FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_MSG_SMT, channel_index),
+ .driver_api_id = (fwk_id_t)FWK_ID_API_INIT(FWK_MODULE_IDX_MSG_SMT,
+ MOD_MSG_SMT_API_IDX_DRIVER_INPUT),
+ };
+
+ channel_index++;
+ }
+ }
+};
+
+static void set_resources(struct scpfw_config *cfg)
+{
+ size_t i, j, k, l;
+
+ for (i = 0; i < cfg->agent_count; i++) {
+ struct scpfw_agent_config *agent_cfg = cfg->agent_config + i;
+ size_t agent_index = i + 1;
+
+ if (agent_index != agent_cfg->agent_id) {
+ panic("scpfw config expects agent ID is agent index");
+ }
+
+ for (j = 0; j < agent_cfg->channel_count; j++) {
+ struct scpfw_channel_config *channel_cfg = agent_cfg->channel_config + j;
+
+#ifdef CFG_SCPFW_MOD_SCMI_CLOCK
+ /* Add first SCMI clock. We will add later the clocks used for DVFS */
+ if (channel_cfg->clock_count) {
+ size_t clock_index = scpfw_resource_counter.clock_index;
+ struct mod_scmi_clock_device *dev = NULL;
+
+ /* Set SCMI clocks array for the SCMI agent */
+ dev = fwk_mm_calloc(channel_cfg->clock_count,
+ sizeof(struct mod_scmi_clock_device));
+
+ fwk_assert(!scmi_clk_agent_tbl[agent_index].device_table);
+ scmi_clk_agent_tbl[agent_index].device_count = channel_cfg->clock_count;
+ scmi_clk_agent_tbl[agent_index].device_table = dev;
+
+ /* Set clock and optee/clock elements and config data */
+ for (k = 0; k < channel_cfg->clock_count; k++) {
+ struct scmi_clock *clock_cfg = channel_cfg->clock + k;
+
+ dev[k].element_id =
+ (fwk_id_t)FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_CLOCK, clock_index);
+
+ optee_clock_cfg[clock_index].clk = clock_cfg->clk;
+ optee_clock_cfg[clock_index].default_enabled = clock_cfg->enabled;
+
+ optee_clock_elt[clock_index].name = clock_cfg->name;
+ optee_clock_elt[clock_index].data = (void *)(optee_clock_cfg + clock_index);
+
+ clock_data[clock_index] = (struct mod_clock_dev_config){
+ .driver_id = (fwk_id_t)FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_OPTEE_CLOCK,
+ clock_index),
+ .api_id = (fwk_id_t)FWK_ID_API_INIT(FWK_MODULE_IDX_OPTEE_CLOCK,
+ 0),
+ };
+
+ clock_elt[clock_index].name = clock_cfg->name;
+ clock_elt[clock_index].data = (void *)(clock_data + clock_index);
+
+ clock_index++;
+ }
+
+ scpfw_resource_counter.clock_index = clock_index;
+ }
+#endif
+
+#ifdef CFG_SCPFW_MOD_RESET_DOMAIN
+ if (channel_cfg->reset_count) {
+ struct mod_scmi_reset_domain_device *dev = NULL;
+ size_t reset_index = scpfw_resource_counter.reset_index;
+
+ /* Set SCMI reset domains array for the SCMI agent */
+ dev = fwk_mm_calloc(channel_cfg->reset_count, sizeof(*dev));
+
+ fwk_assert(!scmi_reset_agent_tbl[agent_index].device_table);
+ scmi_reset_agent_tbl[agent_index].agent_domain_count = channel_cfg->reset_count;
+ scmi_reset_agent_tbl[agent_index].device_table = dev;
+
+ /* Set reset_domain and optee/reset elements and config data */
+ for (k = 0; k < channel_cfg->reset_count; k++) {
+ struct scmi_reset *reset_cfg = channel_cfg->reset + k;
+
+ dev[k].element_id =
+ (fwk_id_t)FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_RESET_DOMAIN,
+ reset_index);
+
+ optee_reset_data[reset_index].rstctrl = reset_cfg->rstctrl;
+
+ optee_reset_elt[reset_index].name = reset_cfg->name;
+ optee_reset_elt[reset_index].data =
+ (void *)(optee_reset_data + reset_index);
+
+ reset_data[reset_index] = (struct mod_reset_domain_dev_config){
+ .driver_id =
+ (fwk_id_t)FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_OPTEE_RESET,
+ reset_index),
+ .driver_api_id =
+ (fwk_id_t)FWK_ID_API_INIT(FWK_MODULE_IDX_OPTEE_RESET, 0),
+ .modes = MOD_RESET_DOMAIN_AUTO_RESET |
+ MOD_RESET_DOMAIN_MODE_EXPLICIT_ASSERT |
+ MOD_RESET_DOMAIN_MODE_EXPLICIT_DEASSERT,
+ };
+
+ reset_elt[reset_index].name = reset_cfg->name;
+ reset_elt[reset_index].data = (void *)(reset_data + reset_index);
+
+ reset_index++;
+ }
+
+ scpfw_resource_counter.reset_index = reset_index;
+ }
+#endif
+
+#ifdef CFG_SCPFW_MOD_VOLTAGE_DOMAIN
+ if (channel_cfg->voltd_count) {
+ size_t regu_index = scpfw_resource_counter.regu_index;
+ struct mod_scmi_voltd_device *dev = NULL;
+
+ /* Set SCMI voltage domains array for the SCMI agent */
+ dev = fwk_mm_calloc(channel_cfg->voltd_count,
+ sizeof(struct mod_scmi_voltd_device));
+
+ fwk_assert(!scmi_voltd_agent_tbl[agent_index].device_table);
+ scmi_voltd_agent_tbl[agent_index].domain_count = channel_cfg->voltd_count;
+ scmi_voltd_agent_tbl[agent_index].device_table = dev;
+
+ /* Set voltage_domain and optee/regu elements and config data */
+ for (k = 0; k < channel_cfg->voltd_count; k++) {
+ struct scmi_voltd *voltd_cfg = channel_cfg->voltd + k;
+ static const char reserved[] = "reserved";
+ const char *name = NULL;
+
+ if (voltd_cfg->rdev) {
+ name = voltd_cfg->rdev->reg_name;
+ } else {
+ name = reserved;
+ }
+
+ dev[regu_index].element_id =
+ (fwk_id_t)FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_VOLTAGE_DOMAIN, k);
+
+ optee_regu_elt[regu_index].name = name;
+ optee_regu_elt[regu_index].data = (void *)(optee_regu_data + regu_index);
+ optee_regu_data[regu_index].rdev = voltd_cfg->rdev;
+ optee_regu_data[regu_index].default_enabled = voltd_cfg->enabled;
+
+ voltd_data[regu_index].driver_id =
+ (fwk_id_t)FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_STM32_REGU_CONSUMER,
+ regu_index);
+ voltd_data[regu_index].api_id =
+ (fwk_id_t)FWK_ID_API_INIT(FWK_MODULE_IDX_STM32_REGU_CONSUMER, 0);
+
+ voltd_elt[regu_index].name = name;
+ voltd_elt[regu_index].data = (void *)(voltd_data + regu_index);
+ regu_index++;
+ }
+
+ scpfw_resource_counter.regu_index = regu_index;
+ }
+#endif
+
+#ifdef CFG_SCPFW_MOD_DVFS
+ if (channel_cfg->perfd_count) {
+ size_t clock_index = scpfw_resource_counter.clock_index;
+ size_t psu_index = scpfw_resource_counter.psu_index;
+ size_t dvfs_index = scpfw_resource_counter.dvfs_index;
+
+ for (k = 0; k < channel_cfg->perfd_count; k++) {
+ struct mod_scmi_perf_config *scmi_perf_data = NULL;
+ struct scmi_perfd *perfd_cfg = channel_cfg->perfd + k;
+
+ /*
+ * DVFS with SCMI performance management domains
+ * 1 initial scmi_perf instance defines the number of DVFS's
+ * For each DVFS instance:
+ * - 1 instance (elt/config) of dvfs, psu, optee/psu, clock, optee/clock
+ * Clocks and optee/clocks are already allocated but not yet set.
+ */
+
+ /* scmi_perf: data defines the DVFS domains indices */
+ scmi_perf_domain_data[dvfs_index] = (struct mod_scmi_perf_domain_config){ };
+
+ scmi_perf_data = (void *)config_scmi_perf.data;
+
+ scmi_perf_data[dvfs_index].domains = (void *)scmi_perf_domain_data;
+ scmi_perf_data[dvfs_index].perf_doms_count = scpfw_resource_counter.dvfs_count;
+ scmi_perf_data[dvfs_index].fast_channels_alarm_id = (fwk_id_t)FWK_ID_NONE_INIT;
+#ifdef BUILD_HAS_MOD_STATISTICS
+ scmi_perf_data[dvfs_index].stats_enabled = true;
+#endif
+
+ /* dvfs instances: 1 instance per expose DVFS service */
+ dvfs_data[dvfs_index].psu_id =
+ (fwk_id_t)FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_PSU, psu_index);
+ dvfs_data[dvfs_index].clock_id =
+ (fwk_id_t)FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_CLOCK, clock_index);
+ dvfs_data[dvfs_index].latency = 0; /* not set, used for async access */
+ dvfs_data[dvfs_index].opps =
+ fwk_mm_calloc(perfd_cfg->dvfs_opp_count,
+ sizeof(struct mod_dvfs_opp));
+
+ for (l = 0; l < perfd_cfg->dvfs_opp_count; l++) {
+ uint64_t power = 0;
+
+ /* Quick estimation of power consumpsion */
+ power = perfd_cfg->dvfs_opp_khz[l];
+ power *= perfd_cfg->dvfs_opp_mv[l];
+ power *= perfd_cfg->dvfs_opp_mv[l];
+ power /= 100 * 1000 * 1000;
+
+ dvfs_data[dvfs_index].opps[l] = (struct mod_dvfs_opp){
+ .level = perfd_cfg->dvfs_opp_khz[l] * 1000UL,
+ .frequency = perfd_cfg->dvfs_opp_khz[l],
+ .voltage = perfd_cfg->dvfs_opp_mv[l],
+ .power = (uint32_t)power,
+ };
+ }
+
+ dvfs_elt[dvfs_index].name = perfd_cfg->name;
+ dvfs_elt[dvfs_index].data = (void *)(dvfs_data + dvfs_index);
+
+ /* Module psu_optee module (elements and configuration data) */
+ psu_optee_regu_elt[psu_index].name = perfd_cfg->rdev->reg_name;
+ psu_optee_regu_elt[psu_index].sub_element_count = scpfw_resource_counter.psu_count;
+ psu_optee_regu_elt[psu_index].data = (void *)(psu_optee_regu_data + psu_index);
+
+ psu_optee_regu_data[psu_index].rdev = perfd_cfg->rdev;
+
+ /* Module psu (elements and configuration data) */
+ psu_elt[psu_index].name = perfd_cfg->rdev->reg_name;
+ psu_elt[psu_index].data = (void *)(psu_data + psu_index);
+ psu_data[psu_index].driver_id =
+ (fwk_id_t)FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_PSU_OPTEE_REGULATOR, psu_index);
+ psu_data[psu_index].driver_api_id =
+ (fwk_id_t)FWK_ID_API_INIT(FWK_MODULE_IDX_PSU_OPTEE_REGULATOR, 0);
+
+ /* Module clock and optee_clock */
+ fwk_assert(!clock_elt[clock_index].data);
+
+ clock_elt[clock_index].name = perfd_cfg->clk->name;
+ clock_elt[clock_index].data = (void *)(clock_data + clock_index);
+
+ clock_data[clock_index] = (struct mod_clock_dev_config){
+ .driver_id = (fwk_id_t)FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_OPTEE_CLOCK,
+ clock_index),
+ .api_id = (fwk_id_t)FWK_ID_API_INIT(FWK_MODULE_IDX_OPTEE_CLOCK,
+ 0),
+ };
+
+ optee_clock_cfg[clock_index].clk = perfd_cfg->clk;
+ optee_clock_cfg[clock_index].default_enabled = false;
+
+ optee_clock_elt[clock_index].name = perfd_cfg->clk->name;
+ optee_clock_elt[clock_index].data = (void *)(optee_clock_cfg + clock_index);
+
+ clock_index++;
+ psu_index++;
+ dvfs_index++;
+ }
+
+ scpfw_resource_counter.clock_index = clock_index;
+ scpfw_resource_counter.psu_index = psu_index;
+ scpfw_resource_counter.dvfs_index = dvfs_index;
+ }
+#endif
+ }
+ }
+}
+
+void scpfw_configure(struct scpfw_config *cfg)
+{
+ count_resources(cfg);
+ allocate_global_resources(cfg);
+ set_scmi_comm_resources(cfg);
+ set_resources(cfg);
+}
diff --git a/product/optee-stm32mp2/include/fmw_io.h b/product/optee-stm32mp2/include/fmw_io.h
new file mode 100644
index 00000000..8e53e139
--- /dev/null
+++ b/product/optee-stm32mp2/include/fmw_io.h
@@ -0,0 +1,17 @@
+/*
+ * Arm SCP/MCP Software
+ * Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef FMW_IO_H
+#define FMW_IO_H
+
+#include <fwk_id.h>
+#include <fwk_module_idx.h>
+
+#define FMW_IO_STDIN_ID FWK_ID_NONE
+#define FMW_IO_STDOUT_ID FWK_ID_ELEMENT(FWK_MODULE_IDX_OPTEE_CONSOLE, 0)
+
+#endif /* FMW_IO_H */
diff --git a/product/optee-stm32mp2/include/fmw_log.h b/product/optee-stm32mp2/include/fmw_log.h
new file mode 100644
index 00000000..4e0bdd0e
--- /dev/null
+++ b/product/optee-stm32mp2/include/fmw_log.h
@@ -0,0 +1,16 @@
+/*
+ * Arm SCP/MCP Software
+ * Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef FMW_LOG_H
+#define FMW_LOG_H
+
+/*
+ * Disable log buffering by setting buffer size to 0.
+ */
+#define FMW_LOG_BUFFER_SIZE 0
+
+#endif /* FMW_LOG_H */
diff --git a/product/optee-stm32mp2/include/gnu/stubs-soft.h b/product/optee-stm32mp2/include/gnu/stubs-soft.h
new file mode 100644
index 00000000..e69de29b
diff --git a/product/optee-stm32mp2/include/scmi_agents.h b/product/optee-stm32mp2/include/scmi_agents.h
new file mode 100644
index 00000000..13d29618
--- /dev/null
+++ b/product/optee-stm32mp2/include/scmi_agents.h
@@ -0,0 +1,29 @@
+/*
+ * Arm SCP/MCP Software
+ * Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SCMI_AGENTS_H
+#define SCMI_AGENTS_H
+
+enum scmi_agent_id {
+ SCMI_AGENT_ID_RSV = 0, /* 0 is reserved for the platform */
+ SCMI_AGENT_ID_NSEC0,
+ SCMI_AGENT_ID_COUNT
+};
+
+enum scmi_service_idx {
+ SCMI_SERVICE_IDX_NS_CHANNEL0 = 0,
+ SCMI_SERVICE_IDX_COUNT
+};
+
+enum scmi_channel_device_idx {
+ SCMI_CHANNEL_DEVICE_IDX_NS0 = 0,
+ SCMI_CHANNEL_DEVICE_IDX_COUNT
+};
+
+#define SCMI_SHMEM_SIZE 128
+
+#endif /* SCMI_AGENTS_H */
diff --git a/product/optee-stm32mp2/module/psu_optee_regulator/CMakeLists.txt b/product/optee-stm32mp2/module/psu_optee_regulator/CMakeLists.txt
new file mode 100644
index 00000000..77af63f2
--- /dev/null
+++ b/product/optee-stm32mp2/module/psu_optee_regulator/CMakeLists.txt
@@ -0,0 +1,17 @@
+#
+# Arm SCP/MCP Software
+# Copyright (c) 2023, Linaro Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+add_library(${SCP_MODULE_TARGET} SCP_MODULE)
+
+target_include_directories(${SCP_MODULE_TARGET}
+ PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include"
+ "${SCP_OPTEE_DIR}/core/arch/arm/plat-stm32mp2")
+
+target_sources(
+ ${SCP_MODULE_TARGET} PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/src/mod_psu_optee_regulator.c")
+
+target_link_libraries(${SCP_MODULE_TARGET} PUBLIC module-voltage-domain)
diff --git a/product/optee-stm32mp2/module/psu_optee_regulator/Module.cmake b/product/optee-stm32mp2/module/psu_optee_regulator/Module.cmake
new file mode 100644
index 00000000..26dc706e
--- /dev/null
+++ b/product/optee-stm32mp2/module/psu_optee_regulator/Module.cmake
@@ -0,0 +1,9 @@
+#
+# Arm SCP/MCP Software
+# Copyright (c) 2023, Linaro Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+set(SCP_MODULE "psu-optee-regulator")
+set(SCP_MODULE_TARGET "psu-optee-regulator")
diff --git a/product/optee-stm32mp2/module/psu_optee_regulator/include/mod_psu_optee_regulator.h b/product/optee-stm32mp2/module/psu_optee_regulator/include/mod_psu_optee_regulator.h
new file mode 100644
index 00000000..5b0347c7
--- /dev/null
+++ b/product/optee-stm32mp2/module/psu_optee_regulator/include/mod_psu_optee_regulator.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2023, STMicroelectronics
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MOD_PSU_OPTEE_REGULATOR_H
+#define MOD_PSU_OPTEE_REGULATOR_H
+
+#include <fwk_element.h>
+#include <fwk_macros.h>
+#include <stdint.h>
+#include <stdbool.h>
+
+struct rdev;
+
+/*!
+ * \brief Platform regulator configuration.
+ */
+struct mod_psu_optee_regulator_dev_config {
+ struct rdev *rdev;
+};
+
+#endif /* MOD_PSU_OPTEE_REGULATOR_H */
diff --git a/product/optee-stm32mp2/module/psu_optee_regulator/src/mod_psu_optee_regulator.c b/product/optee-stm32mp2/module/psu_optee_regulator/src/mod_psu_optee_regulator.c
new file mode 100644
index 00000000..f1e8c444
--- /dev/null
+++ b/product/optee-stm32mp2/module/psu_optee_regulator/src/mod_psu_optee_regulator.c
@@ -0,0 +1,190 @@
+/*
+ * Copyright (c) 2017-2019, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2022, STMicroelectronics
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stddef.h>
+
+#include <fwk_log.h>
+#include <fwk_macros.h>
+#include <fwk_mm.h>
+#include <fwk_module.h>
+#include <mod_psu.h>
+#include <mod_psu_optee_regulator.h>
+#include <mod_scmi_std.h>
+
+#include <assert.h>
+#include <config.h>
+#include <drivers/regulator.h>
+#include <io.h>
+#include <trace.h>
+
+#define DEBUG_MSG(...) FMSG(__VA_ARGS__)
+
+/* Module context */
+struct psu_optee_regulator_ctx {
+ struct mod_psu_optee_regulator_dev_config *config;
+ unsigned int dev_count;
+};
+
+/* A single instance handles all voltage regulators abstracted by regulator.h */
+static struct psu_optee_regulator_ctx module_ctx;
+
+static char __maybe_unused *regulator_name(struct rdev *rdev)
+{
+ if (rdev)
+ return (char *)rdev->reg_name;
+
+ return NULL;
+}
+
+static struct rdev *get_regulator(fwk_id_t id)
+{
+ unsigned int elt_index;
+
+ elt_index = fwk_id_get_element_idx(id);
+ if (elt_index >= module_ctx.dev_count)
+ return NULL;
+
+ return module_ctx.config[elt_index].rdev;
+}
+
+/*
+ * Driver functions for the PSU API
+ */
+static int psu_optee_regulator_set_enabled(fwk_id_t id, bool enabled)
+{
+ TEE_Result res = TEE_ERROR_GENERIC;
+ struct rdev *regulator;
+
+ regulator = get_regulator(id);
+ if (!regulator) {
+ return FWK_E_PARAM;
+ }
+
+ DEBUG_MSG("PSU set %s %s", regulator_name(regulator),
+ enabled ? "ON" : "OFF");
+
+ if (enabled) {
+ res = regulator_enable(regulator);
+ } else {
+ res = regulator_disable(regulator);
+ }
+
+ if (res) {
+ return FWK_E_HANDLER;
+ } else {
+ return FWK_SUCCESS;
+ }
+}
+
+static int psu_optee_regulator_get_enabled(fwk_id_t id, bool *enabled)
+{
+ struct rdev *regulator;
+
+ regulator = get_regulator(id);
+ if (!regulator || (enabled == NULL)) {
+ return FWK_E_PARAM;
+ }
+
+ *enabled = regulator_is_enabled((const struct rdev *)regulator);
+ DEBUG_MSG("PSU get %s state: %s", regulator_name(regulator),
+ enabled ? "ON" : "OFF");
+
+ return FWK_SUCCESS;
+}
+
+static int psu_optee_regulator_set_voltage(fwk_id_t id, uint32_t voltage)
+{
+ TEE_Result res = TEE_ERROR_GENERIC;
+ struct rdev *regulator;
+ uint16_t level_mv = voltage;
+
+ regulator = get_regulator(id);
+ if (!regulator) {
+ return FWK_E_PARAM;
+ }
+
+ DEBUG_MSG("PSU set regulator %s level: %"PRIu32"mV",
+ regulator_name(regulator), (uint32_t)level_mv);
+
+ res = regulator_set_voltage(regulator, level_mv);
+
+ if (res) {
+ return FWK_E_HANDLER;
+ } else {
+
+ return FWK_SUCCESS;
+ }
+}
+
+static int psu_optee_regulator_get_voltage(fwk_id_t id, uint32_t *voltage)
+{
+ TEE_Result res = TEE_ERROR_GENERIC;
+ struct rdev *regulator;
+ uint16_t level_mv;
+
+ regulator = get_regulator(id);
+ if (!regulator || (voltage == NULL)) {
+ return FWK_E_PARAM;
+ }
+
+ res = regulator_get_voltage(regulator, &level_mv);
+
+ DEBUG_MSG("PSU get regulator %s level: %"PRIu32"mV (res %#"PRIx32")",
+ regulator_name(regulator), (uint32_t)level_mv, res);
+
+ if (res) {
+ return FWK_E_HANDLER;
+ }
+
+ *voltage = level_mv;
+
+ return FWK_SUCCESS;
+}
+
+static struct mod_psu_driver_api psu_driver_api = {
+ .set_enabled = psu_optee_regulator_set_enabled,
+ .get_enabled = psu_optee_regulator_get_enabled,
+ .set_voltage = psu_optee_regulator_set_voltage,
+ .get_voltage = psu_optee_regulator_get_voltage,
+};
+
+static int psu_optee_regulator_init(fwk_id_t module_id,
+ unsigned int element_count,
+ const void *data)
+{
+ return FWK_SUCCESS;
+}
+
+static int psu_optee_regulator_element_init(fwk_id_t element_id,
+ unsigned int sub_element_count,
+ const void *data)
+{
+ fwk_assert(data != NULL);
+
+ module_ctx.config = (struct mod_psu_optee_regulator_dev_config *)data;
+ module_ctx.dev_count = sub_element_count;
+
+ return FWK_SUCCESS;
+}
+
+static int psu_optee_regulator_process_bind_request(fwk_id_t source_id,
+ fwk_id_t target_id,
+ fwk_id_t api_id,
+ const void **api)
+{
+ *api = &psu_driver_api;
+
+ return FWK_SUCCESS;
+}
+
+const struct fwk_module module_psu_optee_regulator = {
+ .api_count = 1,
+ .type = FWK_MODULE_TYPE_DRIVER,
+ .init = psu_optee_regulator_init,
+ .element_init = psu_optee_regulator_element_init,
+ .process_bind_request = psu_optee_regulator_process_bind_request,
+};
diff --git a/product/optee-stm32mp2/module/stm32_regu_consumer/CMakeLists.txt b/product/optee-stm32mp2/module/stm32_regu_consumer/CMakeLists.txt
new file mode 100644
index 00000000..adf79cfc
--- /dev/null
+++ b/product/optee-stm32mp2/module/stm32_regu_consumer/CMakeLists.txt
@@ -0,0 +1,17 @@
+#
+# Arm SCP/MCP Software
+# Copyright (c) 2023, Linaro Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+add_library(${SCP_MODULE_TARGET} SCP_MODULE)
+
+target_include_directories(${SCP_MODULE_TARGET}
+ PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include"
+ "${SCP_OPTEE_DIR}/core/arch/arm/plat-stm32mp2")
+
+target_sources(
+ ${SCP_MODULE_TARGET} PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/src/mod_stm32_regu_consumer.c")
+
+target_link_libraries(${SCP_MODULE_TARGET} PUBLIC module-voltage-domain)
diff --git a/product/optee-stm32mp2/module/stm32_regu_consumer/Module.cmake b/product/optee-stm32mp2/module/stm32_regu_consumer/Module.cmake
new file mode 100644
index 00000000..dc988ed3
--- /dev/null
+++ b/product/optee-stm32mp2/module/stm32_regu_consumer/Module.cmake
@@ -0,0 +1,9 @@
+#
+# Arm SCP/MCP Software
+# Copyright (c) 2023, Linaro Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+set(SCP_MODULE "stm32-regu-consumer")
+set(SCP_MODULE_TARGET "module-stm32-regu-consumer")
diff --git a/product/optee-stm32mp2/module/stm32_regu_consumer/include/mod_stm32_regu_consumer.h b/product/optee-stm32mp2/module/stm32_regu_consumer/include/mod_stm32_regu_consumer.h
new file mode 100644
index 00000000..d3f3358e
--- /dev/null
+++ b/product/optee-stm32mp2/module/stm32_regu_consumer/include/mod_stm32_regu_consumer.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2022, STMicroelectronics
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MOD_STM32_REGU_CONSUMER_H
+#define MOD_STM32_REGU_CONSUMER_H
+
+#include <fwk_element.h>
+#include <fwk_macros.h>
+#include <stdint.h>
+#include <stdbool.h>
+
+struct scmi_server_regu_channel;
+struct rdev;
+
+/*!
+ * \brief Platform regulator configuration.
+ */
+struct mod_stm32_regu_consumer_dev_config {
+ struct rdev *rdev;
+ bool default_enabled;
+};
+
+/*
+ * Build SCMI server resource tables for the voltage domains exposed
+ * by platform.
+ *
+ * @plat - reference to platform data
+ * @plat_count - Number of elements in platform data
+ */
+void scmi_server_build_optee_regu_config(struct scmi_server_regu_channel *plat,
+ size_t plat_count);
+
+#endif /* MOD_STM32_REGU_CONSUMER_H */
diff --git a/product/optee-stm32mp2/module/stm32_regu_consumer/src/mod_stm32_regu_consumer.c b/product/optee-stm32mp2/module/stm32_regu_consumer/src/mod_stm32_regu_consumer.c
new file mode 100644
index 00000000..2a344d90
--- /dev/null
+++ b/product/optee-stm32mp2/module/stm32_regu_consumer/src/mod_stm32_regu_consumer.c
@@ -0,0 +1,345 @@
+/*
+ * Copyright (c) 2017-2019, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2022, STMicroelectronics
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stddef.h>
+
+#include <fwk_log.h>
+#include <fwk_macros.h>
+#include <fwk_mm.h>
+#include <fwk_module.h>
+#include <mod_scmi_std.h>
+#include <mod_stm32_regu_consumer.h>
+#include <mod_voltage_domain.h>
+
+#include <assert.h>
+#include <drivers/regulator.h>
+#include <scmi_regulator_consumer.h>
+#include <trace.h>
+
+#define DEBUG_MSG(...) FMSG(__VA_ARGS__)
+
+/* Device context */
+struct stm32_regu_consumer_dev_ctx {
+ struct rdev *rdev;
+ bool enabled;
+};
+
+/* Module context */
+struct stm32_regu_consumer_ctx {
+ struct stm32_regu_consumer_dev_ctx *dev_ctx_table;
+ unsigned int dev_count;
+};
+
+/* A single instance handles all voltage regulators abstracted by regulator.h */
+static struct stm32_regu_consumer_ctx module_ctx;
+
+static char *regu_name(struct rdev *rdev)
+{
+ if (rdev)
+ return (char *)rdev->reg_name;
+
+ return NULL;
+}
+
+static int find_ctx(fwk_id_t dev_id,
+ struct stm32_regu_consumer_dev_ctx **out_ctx)
+{
+ struct stm32_regu_consumer_dev_ctx *ctx;
+
+ ctx = module_ctx.dev_ctx_table + fwk_id_get_element_idx(dev_id);
+
+ if (!fwk_module_is_valid_element_id(dev_id))
+ return FWK_E_PARAM;
+
+ if (!ctx->rdev)
+ return FWK_E_ACCESS;
+
+ *out_ctx = ctx;
+
+ return FWK_SUCCESS;
+}
+
+static int stm32_regu_consumer_get_config(fwk_id_t dev_id, uint8_t *mode_type,
+ uint8_t *mode_id)
+{
+ struct stm32_regu_consumer_dev_ctx *ctx;
+ int ret;
+
+ ret = find_ctx(dev_id, &ctx);
+ if (ret)
+ return ret;
+
+ *mode_type = MOD_VOLTD_MODE_TYPE_ARCH;
+
+ if (ctx->enabled)
+ *mode_id = MOD_VOLTD_MODE_ID_ON;
+ else
+ *mode_id = MOD_VOLTD_MODE_ID_OFF;
+
+ DEBUG_MSG("SCMI voltd %u: get config PMIC %s = %#"PRIx8", %#"PRIx8,
+ fwk_id_get_element_idx(dev_id), regu_name(ctx->rdev), *mode_type,
+ *mode_id);
+
+ return FWK_SUCCESS;
+}
+
+static int stm32_regu_consumer_set_config(fwk_id_t dev_id, uint8_t mode_type,
+ uint8_t mode_id)
+{
+ struct stm32_regu_consumer_dev_ctx *ctx;
+ int ret;
+
+ ret = find_ctx(dev_id, &ctx);
+ if (ret)
+ return ret;
+
+ if (mode_type != MOD_VOLTD_MODE_TYPE_ARCH) {
+ return FWK_E_PARAM;
+ }
+
+ switch (mode_id) {
+ case MOD_VOLTD_MODE_ID_ON:
+ if (!ctx->enabled) {
+ if (regulator_enable(ctx->rdev))
+ return FWK_E_DEVICE;
+
+ ctx->enabled = true;
+ }
+ break;
+
+ case MOD_VOLTD_MODE_ID_OFF:
+ if (ctx->enabled) {
+ if (regulator_disable(ctx->rdev))
+ return FWK_E_DEVICE;
+
+ ctx->enabled = false;
+ }
+ break;
+
+ default:
+ return FWK_E_PARAM;
+ }
+
+ DEBUG_MSG("SCMI voltd %u: set config PMIC %s to type %#"PRIx8" / mode %#"PRIx8,
+ fwk_id_get_element_idx(dev_id), regu_name(ctx->rdev), mode_type,
+ mode_id);
+
+ return FWK_SUCCESS;
+}
+
+static int stm32_regu_consumer_get_level(fwk_id_t dev_id, int *level_uv)
+{
+ struct stm32_regu_consumer_dev_ctx *ctx;
+ uint16_t level_mv;
+ int ret;
+
+ ret = find_ctx(dev_id, &ctx);
+ if (ret)
+ return ret;
+
+ if (regulator_get_voltage(ctx->rdev, &level_mv))
+ return FWK_E_PANIC;
+
+ *level_uv = (int)level_mv * 1000;
+
+ DEBUG_MSG("SCMI voltd %u: get level PMIC %s = %d",
+ fwk_id_get_element_idx(dev_id), regu_name(ctx->rdev), *level_uv);
+
+ return FWK_SUCCESS;
+}
+
+static int stm32_regu_consumer_set_level(fwk_id_t dev_id, int level_uv)
+{
+ struct stm32_regu_consumer_dev_ctx *ctx = NULL;
+ int ret = FWK_E_PANIC;
+
+ if (level_uv / 1000 > UINT16_MAX) {
+ FWK_LOG_ERR("Volatge level too high (mV shall fit in 16 bits)");
+ return FWK_E_PARAM;
+ }
+
+ ret = find_ctx(dev_id, &ctx);
+ if (ret)
+ return ret;
+
+ if (regulator_set_voltage(ctx->rdev, level_uv / 1000))
+ return FWK_E_DEVICE;
+
+ DEBUG_MSG("SCMI voltd %u: set level PMIC %s to %d",
+ fwk_id_get_element_idx(dev_id), regu_name(ctx->rdev), level_uv);
+
+ return FWK_SUCCESS;
+}
+
+static void find_bound_uv(const uint16_t *levels, size_t count,
+ int32_t *min, int32_t *max)
+{
+ size_t n = 0;
+
+ *min = INT32_MAX;
+ *max = INT32_MIN;
+
+ for (n = 0; n < count; n++) {
+ if (*min > levels[n]) {
+ *min = levels[n];
+ }
+ if (*max < levels[n]) {
+ *max = levels[n];
+ }
+ }
+
+ /* Convert from mV to uV */
+ *min *= 1000;
+ *max *= 1000;
+}
+
+static int stm32_regu_consumer_get_info(fwk_id_t dev_id,
+ struct mod_voltd_info *info)
+{
+ struct stm32_regu_consumer_dev_ctx *ctx;
+ uint16_t *levels;
+ size_t full_count;
+ int ret;
+
+ ret = find_ctx(dev_id, &ctx);
+ if (ret == FWK_E_ACCESS) {
+ static const char reserved[] = "reserved";
+
+ memset(info, 0, sizeof(*info));
+ info->name = reserved;
+ info->level_range.level_type = MOD_VOLTD_VOLTAGE_LEVEL_DISCRETE;
+ info->level_range.level_count = 1;
+ info->level_range.min_uv = 0;
+ info->level_range.max_uv = 0;
+
+ return FWK_SUCCESS;
+ } else if (ret != FWK_SUCCESS) {
+ return ret;
+ }
+
+ if (regulator_list_voltages(ctx->rdev, &levels, &full_count)) {
+ return FWK_E_SUPPORT;
+ }
+
+ memset(info, 0, sizeof(*info));
+ info->name = regu_name(ctx->rdev);
+ info->level_range.level_type = MOD_VOLTD_VOLTAGE_LEVEL_DISCRETE;
+ info->level_range.level_count = full_count;
+ find_bound_uv(levels, full_count,
+ &info->level_range.min_uv, &info->level_range.max_uv);
+
+ DEBUG_MSG("SCMI voltd %u: get_info PMIC %s, range [%d %d]",
+ fwk_id_get_element_idx(dev_id), regu_name(ctx->rdev),
+ info->level_range.min_uv, info->level_range.max_uv);
+
+ return FWK_SUCCESS;
+}
+
+static int stm32_regu_consumer_level_from_index(fwk_id_t dev_id,
+ unsigned int index,
+ int32_t *level_uv)
+{
+ struct stm32_regu_consumer_dev_ctx *ctx;
+ uint16_t *levels;
+ size_t full_count;
+ int ret;
+
+ ret = find_ctx(dev_id, &ctx);
+ if (ret == FWK_E_ACCESS) {
+ if (index > 0) {
+ return FWK_E_RANGE;
+ }
+ *level_uv = 0;
+
+ return FWK_SUCCESS;
+ } else if (ret != FWK_SUCCESS) {
+ return ret;
+ }
+
+ if (regulator_list_voltages(ctx->rdev, &levels, &full_count)) {
+ return FWK_E_SUPPORT;
+ }
+
+ if (index >= full_count)
+ return FWK_E_RANGE;
+
+ *level_uv = (int32_t)levels[index] * 1000;
+
+ DEBUG_MSG("SCMI voltd %u: get level PMIC %s = %"PRId32,
+ fwk_id_get_element_idx(dev_id), regu_name(ctx->rdev), *level_uv);
+
+ return FWK_SUCCESS;
+}
+
+static const struct mod_voltd_drv_api api_optee_regu = {
+ .get_level = stm32_regu_consumer_get_level,
+ .set_level = stm32_regu_consumer_set_level,
+ .set_config = stm32_regu_consumer_set_config,
+ .get_config = stm32_regu_consumer_get_config,
+ .get_info = stm32_regu_consumer_get_info,
+ .get_level_from_index = stm32_regu_consumer_level_from_index,
+};
+
+/*
+ * Framework handler functions
+ */
+
+static int stm32_regu_consumer_init(fwk_id_t module_id,
+ unsigned int element_count,
+ const void *data)
+{
+ module_ctx.dev_count = element_count;
+
+ if (element_count)
+ module_ctx.dev_ctx_table =
+ fwk_mm_calloc(element_count, sizeof(*module_ctx.dev_ctx_table));
+
+ return FWK_SUCCESS;
+}
+
+static int stm32_regu_consumer_element_init(fwk_id_t element_id,
+ unsigned int unused,
+ const void *data)
+{
+ const struct mod_stm32_regu_consumer_dev_config *dev_config = data;
+ struct stm32_regu_consumer_dev_ctx *ctx;
+
+ if (!fwk_module_is_valid_element_id(element_id))
+ return FWK_E_PANIC;
+
+ ctx = module_ctx.dev_ctx_table + fwk_id_get_element_idx(element_id);
+
+ ctx->rdev = dev_config->rdev;
+ ctx->enabled = dev_config->default_enabled;
+
+ if (ctx->enabled) {
+ if (!ctx->rdev)
+ return FWK_E_PARAM;
+ if (regulator_enable(ctx->rdev))
+ return FWK_E_DEVICE;
+ }
+
+ return FWK_SUCCESS;
+}
+
+static int stm32_regu_consumer_process_bind_request(fwk_id_t requester_id,
+ fwk_id_t target_id,
+ fwk_id_t api_type,
+ const void **api)
+{
+ *api = &api_optee_regu;
+
+ return FWK_SUCCESS;
+}
+
+const struct fwk_module module_stm32_regu_consumer = {
+ .type = FWK_MODULE_TYPE_DRIVER,
+ .api_count = 1,
+ .init = stm32_regu_consumer_init,
+ .element_init = stm32_regu_consumer_element_init,
+ .process_bind_request = stm32_regu_consumer_process_bind_request,
+};
--
2.34.1