5723 lines
194 KiB
Diff
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
|
|
|