diff --git a/arch/arm/aarch64/src/arch_gic.c b/arch/arm/aarch64/src/arch_gic.c index 9e12cd4db915cd82c64ab7f8f55acd8310452626..fd01fe5f47356cd5c3ed4ab1496d5a44741169c2 100644 --- a/arch/arm/aarch64/src/arch_gic.c +++ b/arch/arm/aarch64/src/arch_gic.c @@ -282,7 +282,7 @@ bool arch_interrupt_is_interrupt_context(void) return current_iar != INTERRUPT_ID_INVALID; } -int arch_interrupt_init() +int arch_interrupt_init(void) { return FWK_SUCCESS; } diff --git a/arch/arm/arm-m/include/arch_nvic.h b/arch/arm/arm-m/include/arch_nvic.h index 89281121fbb108dc7500ad9416c66b0c55f5f004..42c3844bb934c83af4057653898671444d266291 100644 --- a/arch/arm/arm-m/include/arch_nvic.h +++ b/arch/arm/arm-m/include/arch_nvic.h @@ -20,6 +20,6 @@ * * \return Status code representing the result of the operation. */ -int arch_interrupt_init(); +int arch_interrupt_init(void); #endif /* ARCH_NVIC_H */ diff --git a/arch/arm/arm-m/src/arch_nvic.c b/arch/arm/arm-m/src/arch_nvic.c index 78fa45a61e4f04c4cf05c406f3a5d6171e96901b..8c9ac6f890067bf40e2811a6f95bf6ad2bb5f6f1 100644 --- a/arch/arm/arm-m/src/arch_nvic.c +++ b/arch/arm/arm-m/src/arch_nvic.c @@ -245,7 +245,7 @@ void arch_interrupt_irq_invalid(void) } #ifndef ARMV6M -int arch_interrupt_init() +int arch_interrupt_init(void) { uint32_t ictr_intlinesnum; uint32_t align_entries; @@ -327,7 +327,7 @@ int arch_interrupt_init() } #else -int arch_interrupt_init() +int arch_interrupt_init(void) { uint32_t ictr_intlinesnum; uint32_t irq; diff --git a/arch/arm/armv8-a/src/arch_gic.c b/arch/arm/armv8-a/src/arch_gic.c index 2243bd17e49c8bc9fd78b9ace84a7bcfde9b8675..d33c09f6e6c31730e142eb6805b130e8bea2baf8 100644 --- a/arch/arm/armv8-a/src/arch_gic.c +++ b/arch/arm/armv8-a/src/arch_gic.c @@ -574,7 +574,7 @@ bool arch_interrupt_is_interrupt_context(void) return true; } -int arch_interrupt_init() +int arch_interrupt_init(void) { /* * Allocate and initialize a table for the callback functions and their diff --git a/arch/none/host/src/arch_interrupt.c b/arch/none/host/src/arch_interrupt.c index 44570fffea2b43211ffe535fdf64275addd3b96c..b49d1f41d03768a5f6e3e21d06966e7b9564cf0c 100644 --- a/arch/none/host/src/arch_interrupt.c +++ b/arch/none/host/src/arch_interrupt.c @@ -94,7 +94,7 @@ bool arch_interrupt_is_interrupt_context(void) return false; } -int arch_interrupt_init() +int arch_interrupt_init(void) { return FWK_SUCCESS; } diff --git a/arch/none/optee/include/arch_main.h b/arch/none/optee/include/arch_main.h index a89f5bec075465b7845b009a4d3a0433c14edf1b..9e8d6772f01b12a71776115a95b7d692aa43a2d7 100644 --- a/arch/none/optee/include/arch_main.h +++ b/arch/none/optee/include/arch_main.h @@ -1,6 +1,7 @@ /* * Arm SCP/MCP Software - * Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved. + * Copyright (c) 2022-2025, Linaro Limited and Contributors. All rights + * reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -45,4 +46,23 @@ extern void scmi_process_mbx_smt(unsigned int id); extern void scmi_process_mbx_msg(unsigned int id, void *in_buf, size_t in_size, void *out_buf, size_t *out_size); +struct scpfw_config; +#ifdef CFG_SCMI_SCPFW_FROM_DT + +/*! + * \brief Configure resources directly from OPTEE. + * + */ +int scmi_configure(struct scpfw_config *cfg); + +#else + +static inline int scmi_configure(struct scpfw_config *cfg) +{ + (void)cfg; + return 0; +} + +#endif /* CFG_SCMI_SCPFW_FROM_DT */ + #endif /* ARCH_MAIN_H */ diff --git a/arch/none/optee/src/arch_interrupt.c b/arch/none/optee/src/arch_interrupt.c index 4fa0404c723245230e02588874ea6ded8c21195f..9e70416f639d611b39d5b068653e766d5920d8b1 100644 --- a/arch/none/optee/src/arch_interrupt.c +++ b/arch/none/optee/src/arch_interrupt.c @@ -96,7 +96,7 @@ bool arch_interrupt_is_interrupt_context(void) return false; } -int arch_interrupt_init() +int arch_interrupt_init(void) { return FWK_SUCCESS; } diff --git a/framework/include/fwk_arch.h b/framework/include/fwk_arch.h index 1522551724b34c7db50268d8adacc6da3202178f..79bd7639f65b510e7dd222b114dfa682095064f9 100644 --- a/framework/include/fwk_arch.h +++ b/framework/include/fwk_arch.h @@ -203,7 +203,7 @@ bool arch_interrupt_is_interrupt_context(void); * \retval ::FWK_E_PARAM One or more parameters were invalid. * \retval ::FWK_E_PANIC Unrecoverable initialization error. */ -int fwk_arch_init(); +int fwk_arch_init(void); /*! * \brief Stop the framework library. diff --git a/framework/include/fwk_interrupt.h b/framework/include/fwk_interrupt.h index 0c47c8aa803ba31d066b47374feeb7bfacb3c092..cdb740ce2430d4faf50e2e8aff5a7dab2bf53de9 100644 --- a/framework/include/fwk_interrupt.h +++ b/framework/include/fwk_interrupt.h @@ -82,7 +82,7 @@ inline static unsigned int fwk_interrupt_global_disable(void) return arch_interrupts_disable(); } -int fwk_arch_interrupt_init(); +int fwk_arch_interrupt_init(void); /*! * \brief Test whether an interrupt is enabled. * diff --git a/framework/src/fwk_arch.c b/framework/src/fwk_arch.c index a30c2107c36394e73b04dd2aa50a4d5ca64c8842..d2709177325aacdb4ee01ec2e513634049c1f8da 100644 --- a/framework/src/fwk_arch.c +++ b/framework/src/fwk_arch.c @@ -29,7 +29,7 @@ #include -int fwk_arch_init() +int fwk_arch_init(void) { int status; diff --git a/framework/src/fwk_interrupt.c b/framework/src/fwk_interrupt.c index eee73352a7fc9b27a6a4b799689af9863f16f4e7..812dd4c2f7605bc8f4a017958765720946f87bb7 100644 --- a/framework/src/fwk_interrupt.c +++ b/framework/src/fwk_interrupt.c @@ -16,7 +16,7 @@ #include -int fwk_arch_interrupt_init() +int fwk_arch_interrupt_init(void) { return arch_interrupt_init(); } diff --git a/framework/test/include/arch_interrupt.h b/framework/test/include/arch_interrupt.h index b298229c27d34dce22963e0bbf1774e67fd03775..58175ba439c3002fc13b942628ce06d052f8aef4 100644 --- a/framework/test/include/arch_interrupt.h +++ b/framework/test/include/arch_interrupt.h @@ -45,6 +45,6 @@ inline static void arch_suspend(void) { } -int arch_interrupt_init(); +int arch_interrupt_init(void); #endif /* ARCH_HELPERS_H */ diff --git a/product/optee/stm32mp2/fw/CMakeLists.txt b/product/optee/stm32mp2/fw/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..b2869f89dc99ed10332fad692ad19d26d1c6a907 --- /dev/null +++ b/product/optee/stm32mp2/fw/CMakeLists.txt @@ -0,0 +1,28 @@ +# +# Arm SCP/MCP Software +# Copyright (c) 2025, STMicroelectronics and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# +# Create the firmware target. +# +add_library(${SCP_FIRMWARE_TARGET}) + +# Include common optee modules in the module list +add_subdirectory("${CMAKE_CURRENT_LIST_DIR}/../../common/" + "${CMAKE_CURRENT_BINARY_DIR}/optee/module/") + +# 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_scmi.c") + +set(SCP_MODULE_PATHS ${SCP_MODULE_PATHS} PARENT_SCOPE) diff --git a/product/optee/stm32mp2/fw/Firmware.cmake b/product/optee/stm32mp2/fw/Firmware.cmake new file mode 100644 index 0000000000000000000000000000000000000000..d17f3b7e75417ce0a7ef31119662fa3f91aeba0e --- /dev/null +++ b/product/optee/stm32mp2/fw/Firmware.cmake @@ -0,0 +1,72 @@ +# +# Arm SCP/MCP Software +# Copyright (c) 2025, STMicroelectronics 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) + +# 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. + +if(CFG_SCPFW_MOD_OPTEE_MBX) +list(APPEND SCP_MODULES "optee-mbx") +endif(CFG_SCPFW_MOD_OPTEE_MBX) + +if(CFG_SCPFW_MOD_MSG_SMT) +list(APPEND SCP_MODULES "msg-smt") +endif(CFG_SCPFW_MOD_MSG_SMT) + +list(APPEND SCP_MODULES "scmi") + +if(CFG_SCPFW_MOD_OPTEE_CLOCK) +list(APPEND SCP_MODULES "optee-clock") +endif(CFG_SCPFW_MOD_OPTEE_CLOCK) + +if(CFG_SCPFW_MOD_CLOCK) +list(APPEND SCP_MODULES "clock") +endif(CFG_SCPFW_MOD_CLOCK) + +if(CFG_SCPFW_MOD_SCMI_CLOCK) +list(APPEND SCP_MODULES "scmi-clock") +endif(CFG_SCPFW_MOD_SCMI_CLOCK) + +if(CFG_SCPFW_MOD_OPTEE_RESET) +list(APPEND SCP_MODULES "optee-reset") +endif(CFG_SCPFW_MOD_OPTEE_RESET) + +if(CFG_SCPFW_MOD_RESET_DOMAIN) +list(APPEND SCP_MODULES "reset-domain") +endif(CFG_SCPFW_MOD_RESET_DOMAIN) + +if(CFG_SCPFW_MOD_SCMI_RESET_DOMAIN) +list(APPEND SCP_MODULES "scmi-reset-domain") +endif(CFG_SCPFW_MOD_SCMI_RESET_DOMAIN) + +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 0000000000000000000000000000000000000000..b4214d1f0265fa65599da2778ad1342dcf41d9e7 --- /dev/null +++ b/product/optee/stm32mp2/fw/Toolchain-GNU.cmake @@ -0,0 +1,22 @@ +# +# Arm SCP/MCP Software +# Copyright (c) 2025, STMicroelectronics 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_scmi.c b/product/optee/stm32mp2/fw/config_scmi.c new file mode 100644 index 0000000000000000000000000000000000000000..ddd3d9637848431e104f488e0e7ddafebec1f052 --- /dev/null +++ b/product/optee/stm32mp2/fw/config_scmi.c @@ -0,0 +1,544 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2025, STMicroelectronics and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +#ifdef CFG_SCPFW_MOD_OPTEE_CLOCK +# include +#endif +#ifdef CFG_SCPFW_MOD_OPTEE_RESET +# include +#endif +#ifdef CFG_SCPFW_MOD_MSG_SMT +# include +#endif +#ifdef CFG_SCPFW_MOD_RESET_DOMAIN +# include +#endif +#ifdef CFG_SCPFW_MOD_SCMI_CLOCK +# include +#endif +#ifdef CFG_SCPFW_MOD_SCMI_RESET_DOMAIN +# include +#endif + +#include +#include +#include + +#include +#include +#include + +/* 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 */ +#ifdef CFG_SCPFW_MOD_MSG_SMT +static struct fwk_element *msg_smt_elt; +static struct mod_msg_smt_channel_config *msg_smt_data; +#endif +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; +static struct mod_scmi_clock_agent_config *scmi_clk_agent_cfg; +#endif + +#ifdef CFG_SCPFW_MOD_CLOCK +/* + * Clocks and optee/clock, same number/indices. + * Elements and configuration data. + */ +static struct fwk_element *optee_clock_elt; +static struct mod_optee_clock_config *optee_clock_cfg; +static struct fwk_element *clock_elt; +static struct mod_clock_dev_config *clock_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 + +/* 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), +}; + +#ifdef CFG_SCPFW_MOD_MSG_SMT +/* 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), +}; +#endif + +/* 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 + +/* + * 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 + */ +struct scpfw_resource_counter { + size_t channel_count; + size_t clock_index; + size_t clock_count; + size_t reset_index; + size_t reset_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) +{ + for (size_t 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 (size_t j = 0; j < agent_cfg->channel_count; j++) { + struct scpfw_channel_config *channel_cfg = + agent_cfg->channel_config + j; + + /* Clocks for scmi_clock */ + scpfw_resource_counter.clock_count += channel_cfg->clock_count; + /* Reset for scmi_reset only */ + scpfw_resource_counter.reset_count += channel_cfg->reset_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 +} + +/* + * 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_clock_config *scmi_clock_config __maybe_unused; + size_t __maybe_unused scmi_agent_count; + + /* + * @cfg does not consider agent #0, + * that is the reserved platform/server agent. + */ + 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_clk_agent_cfg = + fwk_mm_calloc(scmi_agent_count, sizeof(*scmi_clk_agent_cfg)); + 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 +} + +enum mailbox_type { + MAILBOX_TYPE_MSG_SMT, + MAILBOX_TYPE_COUNT, +}; + +static enum mailbox_type module_idx_smt_table[SCMI_AGENT_ID_COUNT] = { + /* + * Agent NSEC0 is Cortex-A that communicates over OP-TEE's SCMI PTA + * and OP-TEE shared memory hence using MSG_SMT module. + */ + [SCMI_AGENT_ID_NSEC0] = MAILBOX_TYPE_MSG_SMT, +}; + +static void set_scmi_comm_resources(struct scpfw_config *cfg) +{ + unsigned int channel_index = 0; + unsigned int __maybe_unused msg_smt_index = 0; + size_t scmi_agent_count = cfg->agent_count; + + /* + * @cfg does not consider agent #0, + * that is the reserved platform/server agent. + */ + scmi_agent_table = + fwk_mm_calloc(scmi_agent_count + 1, sizeof(*scmi_agent_table)); + + scmi_service_elt = fwk_mm_calloc( + scpfw_resource_counter.channel_count + 1, sizeof(*scmi_service_elt)); + +#ifdef CFG_SCPFW_MOD_MSG_SMT + 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)); +#endif + + 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 = "ST", + .sub_vendor_identifier = "ST", + }; + + for (size_t i = 0; i < cfg->agent_count; i++) { + struct scpfw_agent_config *agent_cfg = cfg->agent_config + i; + size_t agent_index = agent_cfg->agent_id; + + scmi_agent_table[agent_index].type = SCMI_AGENT_TYPE_OSPM; + scmi_agent_table[agent_index].name = agent_cfg->name; + + for (size_t 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)); + + scmi_service_elt[channel_index].name = channel_cfg->name; + scmi_service_elt[channel_index].data = service_data; + + optee_mbx_elt[channel_index].name = channel_cfg->name; + optee_mbx_elt[channel_index].data = + (void *)(optee_mbx_data + channel_index); + + assert(agent_index < SCMI_AGENT_ID_COUNT); + + switch (module_idx_smt_table[agent_index]) { +#if defined(CFG_SCPFW_MOD_MSG_SMT) + case MAILBOX_TYPE_MSG_SMT: + *service_data = (struct mod_scmi_service_config){ + .transport_id = (fwk_id_t)FWK_ID_ELEMENT_INIT( + FWK_MODULE_IDX_MSG_SMT, msg_smt_index), + .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, + }; + + msg_smt_elt[msg_smt_index].name = channel_cfg->name; + msg_smt_elt[msg_smt_index].data = + (void *)(msg_smt_data + msg_smt_index); + + msg_smt_data[msg_smt_index] = + (struct mod_msg_smt_channel_config){ + .type = MOD_MSG_SMT_CHANNEL_TYPE_REQUESTER, + .mailbox_size = SCMI_SHMEM_SIZE, + .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_data[channel_index] = + (struct mod_optee_mbx_channel_config){ + .driver_id = (fwk_id_t)FWK_ID_ELEMENT_INIT( + FWK_MODULE_IDX_MSG_SMT, msg_smt_index), + .driver_api_id = (fwk_id_t)FWK_ID_API_INIT( + FWK_MODULE_IDX_MSG_SMT, + MOD_MSG_SMT_API_IDX_DRIVER_INPUT), + }; + msg_smt_index++; + break; +#endif + default: + panic("Incorrect SMT module_idx"); + } + + channel_index++; + } + } +}; + +static void set_resources(struct scpfw_config *cfg) +{ + for (size_t 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 (size_t 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].agent_config); + scmi_clk_agent_cfg[agent_index] = + (struct mod_scmi_clock_agent_config){ + .device_count = channel_cfg->clock_count, + .device_table = dev, + }; + scmi_clk_agent_tbl[agent_index].agent_config = + scmi_clk_agent_cfg + agent_index; + + /* Set clock and optee/clock elements and config data */ + for (size_t k = 0; k < channel_cfg->clock_count; k++) { + struct scmi_clock *clock_cfg = channel_cfg->clock + k; + struct mod_clock_dev_config cdata = { + .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), + .pd_source_id = FWK_ID_NONE, + }; + + 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); + + memcpy(clock_data + clock_index, &cdata, sizeof(cdata)); + + 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 (size_t 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 + } + } +} + +int scmi_configure(struct scpfw_config *cfg) +{ + count_resources(cfg); + allocate_global_resources(cfg); + set_scmi_comm_resources(cfg); + set_resources(cfg); + + return 0; +} diff --git a/product/optee/stm32mp2/include/fmw_io.h b/product/optee/stm32mp2/include/fmw_io.h new file mode 100644 index 0000000000000000000000000000000000000000..9ab54997120c7b838dd307643db022cb2b166071 --- /dev/null +++ b/product/optee/stm32mp2/include/fmw_io.h @@ -0,0 +1,17 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2025, STMicroelectronics and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef FMW_IO_H +#define FMW_IO_H + +#include +#include + +#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 0000000000000000000000000000000000000000..ede9c642e89ac031f9f5964f566e506280309e76 --- /dev/null +++ b/product/optee/stm32mp2/include/fmw_log.h @@ -0,0 +1,16 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2025, STMicroelectronics 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/scmi_agents.h b/product/optee/stm32mp2/include/scmi_agents.h new file mode 100644 index 0000000000000000000000000000000000000000..b8bbe43085f49d6b201ead703a45ce9ea4369671 --- /dev/null +++ b/product/optee/stm32mp2/include/scmi_agents.h @@ -0,0 +1,29 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2025, STMicroelectronics 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/sub-stm32mp2.mk b/product/optee/stm32mp2/sub-stm32mp2.mk new file mode 100644 index 0000000000000000000000000000000000000000..22895dec5dfc78a58e5eea7dc52e95285b18d903 --- /dev/null +++ b/product/optee/stm32mp2/sub-stm32mp2.mk @@ -0,0 +1,10 @@ +# +# Arm SCP/MCP Software +# Copyright (c) 2025, STMicroelectronics and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +incdirs_ext-y += $(scpfw-path)/product/optee/stm32mp2/include + +srcs-y += $(scpfw-path)/product/optee/stm32mp2/fw/config_scmi.c