diff --git a/meta-digi-arm/dynamic-layers/stm-st-stm32mp/recipes-security/optee/files/fonts.tar.gz b/meta-digi-arm/dynamic-layers/stm-st-stm32mp/recipes-security/optee/files/fonts.tar.gz new file mode 100644 index 000000000..0a564c426 Binary files /dev/null and b/meta-digi-arm/dynamic-layers/stm-st-stm32mp/recipes-security/optee/files/fonts.tar.gz differ diff --git a/meta-digi-arm/dynamic-layers/stm-st-stm32mp/recipes-security/optee/optee-os-stm32mp2-common.inc b/meta-digi-arm/dynamic-layers/stm-st-stm32mp/recipes-security/optee/optee-os-stm32mp2-common.inc new file mode 100644 index 000000000..2ccdcf72d --- /dev/null +++ b/meta-digi-arm/dynamic-layers/stm-st-stm32mp/recipes-security/optee/optee-os-stm32mp2-common.inc @@ -0,0 +1,172 @@ +FILESEXTRAPATHS:prepend := "${THISDIR}/optee-os:" + +PACKAGE_ARCH = "${MACHINE_ARCH}" + +PROVIDES += "virtual/optee-os" +RPROVIDES:${PN} += "virtual/optee-os virtual/systemd-bootconf" + +CVE_PRODUCT = "op-tee:op-tee_os" + +############################################################# +#inherit external-dt scp-firmware + +# Enable use of scp-firmware shared folder +STAGING_SCPFW_DIR = "${TMPDIR}/work-shared/${MACHINE}/scp-firmware" + +do_compile[depends] += "scp-firmware:do_configure" + + +STAGING_EXTDT_DIR = "${TMPDIR}/work-shared/${MACHINE}/external-dt" +############################################################# + +B = "${WORKDIR}/build" +# Configure build dir for externalsrc class usage through devtool +EXTERNALSRC_BUILD:pn-${PN} = "${WORKDIR}/build" + +DEPENDS += "dtc-native" +DEPENDS += "python3-pycryptodomex-native" +DEPENDS += "python3-pyelftools-native" +DEPENDS += "libgcc python3-cryptography-native" +DEPENDS += "python3-pillow-native" + +inherit deploy python3native + +OPTEEMACHINE ?= "${MACHINE}" +OPTEEOUTPUTMACHINE ?= "${MACHINE}" + +# Default log level +ST_OPTEE_DEBUG_LOG_LEVEL ??= "2" + +# default core debug +ST_OPTEE_CORE_DEBUG ??= "y" +ST_OPTEE_CORE_DEBUG:stm32mp15common ?= "n" + +EXTRA_OEMAKE = "PLATFORM=${OPTEEMACHINE}" +EXTRA_OEMAKE += "CROSS_COMPILE_core=${HOST_PREFIX}" +EXTRA_OEMAKE += "CROSS_COMPILE_ta_arm64=${HOST_PREFIX}" +EXTRA_OEMAKE += "${@bb.utils.contains('TUNE_FEATURES', 'aarch64', 'ARCH=arm CFG_ARM64_core=y', 'ARCH=arm CFG_ARM32_core=y CROSS_COMPILE_ta_arm32=${HOST_PREFIX}', d)}" +EXTRA_OEMAKE += "NOWERROR=1" +EXTRA_OEMAKE += "LDFLAGS=" +# Set external-dt support +EXTRA_OEMAKE += "${@bb.utils.contains('EXTERNAL_DT_ENABLED', '1', 'CFG_EXT_DTS=${STAGING_EXTDT_DIR}/optee', '', d)}" +# Set scp-firmware support +EXTRA_OEMAKE += "CFG_SCP_FIRMWARE=${STAGING_SCPFW_DIR}" + +# debug and trace +EXTRA_OEMAKE += "${@bb.utils.contains('ST_OPTEE_DEBUG_TRACE', '1', 'CFG_TEE_CORE_LOG_LEVEL=${ST_OPTEE_DEBUG_LOG_LEVEL} CFG_TEE_CORE_DEBUG=${ST_OPTEE_CORE_DEBUG}', '', d)}" + +# OPTEE in sysram +EXTRA_OEMAKE:append:stm32mp15common = " ${@bb.utils.contains('ST_OPTEE_IN_SYSRAM', '1', 'CFG_STM32MP1_OPTEE_IN_SYSRAM=y', '', d)}" + +# SCP firmware +#EXTRA_OEMAKE_SCP_FIRMWARE ??= "" +EXTRA_OEMAKE_SCP_FIRMWARE:stm32mp15common ??= "" +EXTRA_OEMAKE_SCP_FIRMWARE:stm32mp13common ??= "${@bb.utils.contains('ENABLE_SCMI_SCPFW', '1', 'CFG_SCMI_SCPFW=y', 'CFG_SCMI_SCPFW=n', d)}" +EXTRA_OEMAKE_SCP_FIRMWARE:stm32mp25common ??= "CFG_SCMI_SCPFW=y" +EXTRA_OEMAKE += " ${EXTRA_OEMAKE_SCP_FIRMWARE}" + +OPTEE_ARCH:armv7a = "arm32" +OPTEE_ARCH:armv7ve = "arm32" +OPTEE_ARCH:aarch64 = "arm64" + +do_configure:prepend(){ + chmod 755 ${S}/scripts/bin_to_c.py +} + +do_compile() { + export CFLAGS="${CFLAGS} --sysroot=${STAGING_DIR_HOST}" + export OPENSSL_MODULES=${STAGING_LIBDIR_NATIVE}/ossl-modules/ + if [ -n "${OPTEE_CONF}" ]; then + for conf in ${OPTEE_CONF}; do + # Configure SOC switch + soc_extra="" + for soc in ${STM32MP_SOC_NAME}; do + if [ "$(echo ${conf} | grep -c ${soc})" -eq 1 ]; then + soc_extra="$(echo CFG_${soc} | awk '{print toupper($0)}')=y" + break + fi + done + + oe_runmake -C ${S} O=${B}/${conf} CFG_EMBED_DTB_SOURCE_FILE=${conf}.dts ${soc_extra} + done + else + oe_runmake -C ${S} O=${B}/out + fi +} + +do_install:stm32mp1common() { + #install TA devkit + install -d ${D}${includedir}/optee/export-user_ta/ + + if [ -n "${OPTEE_CONF}" ]; then + for conf in ${OPTEE_CONF}; do + for f in ${B}/${conf}/export-ta_${OPTEE_ARCH}/* ; do + cp -aRf $f ${D}${includedir}/optee/export-user_ta/ + done + done + fi +} +do_install:stm32mp2common() { + #install TA devkit + install -d ${D}${includedir}/optee/export-user_ta_arm32/ + install -d ${D}${includedir}/optee/export-user_ta_arm64/ + + if [ -n "${OPTEE_CONF}" ]; then + for conf in ${OPTEE_CONF}; do + if [ -d ${B}/${conf}/export-ta_arm32 ]; then + for f in ${B}/${conf}/export-ta_arm32/* ; do + cp -aRf $f ${D}${includedir}/optee/export-user_ta_arm32/ + done + fi + if [ -d ${B}/${conf}/export-ta_arm64 ]; then + for f in ${B}/${conf}/export-ta_arm64/* ; do + cp -aRf $f ${D}${includedir}/optee/export-user_ta_arm64/ + done + fi + done + fi +} + + +# Configure optee binaries +OPTEE_HEADER = "tee-header_v2" +OPTEE_PAGEABLE = "tee-pageable_v2" +OPTEE_PAGER = "tee-pager_v2" +OPTEE_SUFFIX = "bin" +# Output the ELF generated +ELF_DEBUG_ENABLE ?= "" +OPTEE_ELF = "tee" +OPTEE_ELF_SUFFIX = "elf" + +do_deploy[sstate-outputdirs] = "${DEPLOY_DIR_IMAGE}/optee" +do_deploy() { + install -d ${DEPLOYDIR}/debug + if [ -n "${OPTEE_CONF}" ]; then + for conf in ${OPTEE_CONF}; do + install -m 644 ${B}/${conf}/core/${OPTEE_HEADER}.${OPTEE_SUFFIX} ${DEPLOYDIR}/${OPTEE_HEADER}-${conf}.${OPTEE_SUFFIX} + install -m 644 ${B}/${conf}/core/${OPTEE_PAGER}.${OPTEE_SUFFIX} ${DEPLOYDIR}/${OPTEE_PAGER}-${conf}.${OPTEE_SUFFIX} + install -m 644 ${B}/${conf}/core/${OPTEE_PAGEABLE}.${OPTEE_SUFFIX} ${DEPLOYDIR}/${OPTEE_PAGEABLE}-${conf}.${OPTEE_SUFFIX} + if [ -n "${ELF_DEBUG_ENABLE}" ]; then + install -m 644 ${B}/${conf}/core/${OPTEE_ELF}.${OPTEE_ELF_SUFFIX} ${DEPLOYDIR}/debug/${OPTEE_ELF}-${conf}.${OPTEE_ELF_SUFFIX} + fi + done + else + install -m 644 ${B}/core/${OPTEE_HEADER}.${OPTEE_SUFFIX} ${DEPLOYDIR}/${OPTEE_HEADER}.${OPTEE_SUFFIX} + install -m 644 ${B}/core/${OPTEE_PAGER}.${OPTEE_SUFFIX} ${DEPLOYDIR}/${OPTEE_PAGER}.${OPTEE_SUFFIX} + install -m 644 ${B}/core/${OPTEE_PAGEABLE}.${OPTEE_SUFFIX} ${DEPLOYDIR}/${OPTEE_PAGEABLE}.${OPTEE_SUFFIX} + if [ -n "${ELF_DEBUG_ENABLE}" ]; then + install -m 644 ${B}/core/${OPTEE_ELF}.${OPTEE_ELF_SUFFIX} ${DEPLOYDIR}/debug/${OPTEE_ELF}.${OPTEE_ELF_SUFFIX} + fi + fi +} +addtask deploy before do_build after do_compile + +FILES:${PN} = "${nonarch_base_libdir}/firmware/" +FILES:${PN}-dev = "/usr/include/optee" + +INSANE_SKIP:${PN}-dev = "staticdev" + +INHIBIT_PACKAGE_STRIP = "1" +# --------------------------------------------------------------------- +# Avoid QA Issue: contains reference to TMPDIR [buildpaths] +INSANE_SKIP:${PN} += "buildpaths" diff --git a/meta-digi-arm/dynamic-layers/stm-st-stm32mp/recipes-security/optee/optee-os-stm32mp_%.bbappend b/meta-digi-arm/dynamic-layers/stm-st-stm32mp/recipes-security/optee/optee-os-stm32mp_3.16.0.bbappend similarity index 100% rename from meta-digi-arm/dynamic-layers/stm-st-stm32mp/recipes-security/optee/optee-os-stm32mp_%.bbappend rename to meta-digi-arm/dynamic-layers/stm-st-stm32mp/recipes-security/optee/optee-os-stm32mp_3.16.0.bbappend diff --git a/meta-digi-arm/dynamic-layers/stm-st-stm32mp/recipes-security/optee/optee-os-stm32mp_3.19.0.bb b/meta-digi-arm/dynamic-layers/stm-st-stm32mp/recipes-security/optee/optee-os-stm32mp_3.19.0.bb new file mode 100644 index 000000000..2fe62ea76 --- /dev/null +++ b/meta-digi-arm/dynamic-layers/stm-st-stm32mp/recipes-security/optee/optee-os-stm32mp_3.19.0.bb @@ -0,0 +1,62 @@ +SUMMARY = "OPTEE TA development kit for stm32mp" +LICENSE = "BSD-2-Clause & BSD-3-Clause" +LIC_FILES_CHKSUM = "file://LICENSE;md5=c1f21c4f72f372ef38a5a4aee55ec173" + +# Select internal or Github OPTEE repo +OPTEE_URI_STASH = "${DIGI_MTK_GIT}/emp/optee_os.git;protocol=ssh" +OPTEE_URI_GITHUB = "${DIGI_GITHUB_GIT}/optee_os.git;protocol=https" +OPTEE_GIT_URI ?= "${@oe.utils.conditional('DIGI_INTERNAL_GIT', '1' , '${OPTEE_URI_STASH}', '${OPTEE_URI_GITHUB}', d)}" + +SRCBRANCH = "3.19.0/stm/master" +SRCREV = "${AUTOREV}" + +SRC_URI = " \ + ${OPTEE_GIT_URI};branch=${SRCBRANCH};name=os \ + file://fonts.tar.gz;subdir=git;name=fonts \ +" + +SRC_URI[fonts.sha256sum] = "4941e8bb6d8ac377838e27b214bf43008c496a24a8f897e0b06433988cbd53b2" + +OPTEE_VERSION = "3.19.0" +OPTEE_SUBVERSION = "stm32mp" +OPTEE_RELEASE = "beta-r1" + +PV = "${OPTEE_VERSION}-${OPTEE_SUBVERSION}-${OPTEE_RELEASE}" + +ARCHIVER_ST_BRANCH = "${OPTEE_VERSION}-${OPTEE_SUBVERSION}" +ARCHIVER_ST_REVISION = "${PV}" +ARCHIVER_COMMUNITY_BRANCH = "master" +ARCHIVER_COMMUNITY_REVISION = "${OPTEE_VERSION}" + +S = "${WORKDIR}/git" + +OPTEEMACHINE ?= "stm32mp1" +OPTEEMACHINE:stm32mp1common = "stm32mp1" +OPTEEMACHINE:stm32mp2common = "stm32mp2" + +OPTEEOUTPUTMACHINE ?= "stm32mp1" +OPTEEOUTPUTMACHINE:stm32mp1common = "stm32mp1" +OPTEEOUTPUTMACHINE:stm32mp2common = "stm32mp2" + +# The package is empty but must be generated to avoid apt-get installation issue +ALLOW_EMPTY:${PN} = "1" + +require optee-os-stm32mp2-common.inc + +# Specific for revA board +EXTRA_OEMAKE_REVA:stm32mp25revabcommon:append = " CFG_STM32MP25x_REVA=y " +EXTRA_OEMAKE += " ${EXTRA_OEMAKE_REVA}" + +# --------------------------------- +# Configure archiver use +# --------------------------------- +include ${@oe.utils.ifelse(d.getVar('ST_ARCHIVER_ENABLE') == '1', 'optee-os-stm32mp-archiver.inc','')} + +# --------------------------------- +# Configure default preference to manage dynamic selection between tarball and github +# --------------------------------- +STM32MP_SOURCE_SELECTION ?= "tarball" + +DEFAULT_PREFERENCE = "${@bb.utils.contains('STM32MP_SOURCE_SELECTION', 'github', '-1', '1', d)}" + +COMPATIBLE_MACHINE = "(ccmp2)" diff --git a/meta-digi-arm/dynamic-layers/stm-st-stm32mp/recipes-security/scp-firmware/scp-firmware-archiver.inc b/meta-digi-arm/dynamic-layers/stm-st-stm32mp/recipes-security/scp-firmware/scp-firmware-archiver.inc new file mode 100644 index 000000000..c3a587bc1 --- /dev/null +++ b/meta-digi-arm/dynamic-layers/stm-st-stm32mp/recipes-security/scp-firmware/scp-firmware-archiver.inc @@ -0,0 +1,10 @@ +# +# Archiver Configuration +# +SRC_URI:append = " file://README.HOW_TO.txt " +COPYLEFT_LICENSE_INCLUDE:append = " BSD-3* " + +inherit archiver +ARCHIVER_MODE[src] = "original" + +inherit archiver_stm32mp_clean diff --git a/meta-digi-arm/dynamic-layers/stm-st-stm32mp/recipes-security/scp-firmware/scp-firmware.bb b/meta-digi-arm/dynamic-layers/stm-st-stm32mp/recipes-security/scp-firmware/scp-firmware.bb new file mode 100644 index 000000000..b78447ab6 --- /dev/null +++ b/meta-digi-arm/dynamic-layers/stm-st-stm32mp/recipes-security/scp-firmware/scp-firmware.bb @@ -0,0 +1,74 @@ +SUMMARY = "SCP Firmware for stm32mp" +LICENSE = "BSD-3-Clause" +LIC_FILES_CHKSUM = "file://${S}/license.md;md5=ef610a65bfb6d16f79778877cbfd45df" + +SRC_URI = "gitsm://github.com/ARM-software/SCP-firmware;protocol=https;nobranch=1" +SRCREV = "0c7236b1851d90124210a0414fd982dc55322c7c" + +SRC_URI += " \ + file://0001-2.12-stm32mp-r1.patch \ + file://0001-Correct-git-error.patch \ +" + +SCPFW_VERSION = "2.12" +SCPFW_SUBVERSION = "stm32mp" +SCPFW_RELEASE = "r1" + +PV = "${SCPFW_VERSION}-${SCPFW_SUBVERSION}-${SCPFW_RELEASE}" + +S = "${WORKDIR}/git" + +################################################################### +#inherit scp-firmware + +# Enable use of scp-firmware shared folder +STAGING_SCPFW_DIR = "${TMPDIR}/work-shared/${MACHINE}/scp-firmware" + +do_compile[depends] += "scp-firmware:do_configure" +################################################################### + +PACKAGE_ARCH = "${MACHINE_ARCH}" +COMPATIBLE_MACHINE = "(stm32mpcommon)" + +# Do not remove source code, even if rm_work is configured +RM_WORK_EXCLUDE += "${PN}" + +# ----------------------------------------------- +# Enable use of work-shared folder +# Make sure to move ${S} to STAGING_SCPFW_DIR. We can't just +# create the symlink in advance as the git fetcher can't cope with +# the symlink. +do_unpack[cleandirs] += "${S}" +do_unpack[cleandirs] += "${STAGING_SCPFW_DIR}" +do_clean[cleandirs] += "${S}" +do_clean[cleandirs] += "${STAGING_SCPFW_DIR}" +python do_symlink_scpfirmwaresrc() { + # Specific part to update devtool-source class + if bb.data.inherits_class('devtool-source', d): + # We don't want to move the source to STAGING_SCPFW_DIR here + if d.getVar('STAGING_SCPFW_DIR', d): + d.setVar('STAGING_SCPFW_DIR', '${S}') + + # Copy/Paste from kernel class with adaptation to SCPFW var + s = d.getVar("S") + if s[-1] == '/': + # drop trailing slash, so that os.symlink(scpscr, s) doesn't use s as directory name and fail + s=s[:-1] + scpscr = d.getVar("STAGING_SCPFW_DIR") + if s != scpscr: + bb.utils.mkdirhier(scpscr) + bb.utils.remove(scpscr, recurse=True) + if d.getVar("EXTERNALSRC"): + # With EXTERNALSRC S will not be wiped so we can symlink to it + os.symlink(s, scpscr) + else: + import shutil + shutil.move(s, scpscr) + os.symlink(scpscr, s) +} +addtask symlink_scpfirmwaresrc before do_patch do_configure after do_unpack + +# --------------------------------- +# Configure archiver use +# --------------------------------- +include ${@oe.utils.ifelse(d.getVar('ST_ARCHIVER_ENABLE') == '1', 'scp-firmware-archiver.inc','')} diff --git a/meta-digi-arm/dynamic-layers/stm-st-stm32mp/recipes-security/scp-firmware/scp-firmware/0001-2.12-stm32mp-r1.patch b/meta-digi-arm/dynamic-layers/stm-st-stm32mp/recipes-security/scp-firmware/scp-firmware/0001-2.12-stm32mp-r1.patch new file mode 100644 index 000000000..65c88f23a --- /dev/null +++ b/meta-digi-arm/dynamic-layers/stm-st-stm32mp/recipes-security/scp-firmware/scp-firmware/0001-2.12-stm32mp-r1.patch @@ -0,0 +1,5722 @@ +From 223bf375c59e78bd4791a3ae40eb9bdc6d361199 Mon Sep 17 00:00:00 2001 +From: Christophe Priouzeau +Date: Mon, 27 Nov 2023 09:44:21 +0100 +Subject: [PATCH] 2.12-stm32mp-r1 + +Signed-off-by: Christophe Priouzeau +--- + 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 ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#ifdef CFG_SCPFW_MOD_DVFS ++#include ++#endif ++#include ++#include ++#include ++#include ++#ifdef CFG_SCPFW_MOD_PSU ++#include ++#include ++#endif ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#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 */ ++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 +-#include +-#include +-#include +-#include +- +-#include +-#include +-#include +- +-#include +- +-#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 +-#include +-#include +-#include +-#include +-#include +- +-#include +-#include +-#include +-#include +- +-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 +-#include +-#include +-#include +- +-#include +-#include +-#include +-#include +- +-#include +-#include +-#include +- +-#include +-#include +-#include +- +-/* +- * 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 +-#include +-#include +- +-#include +-#include +-#include +- +-#include +-#include +-#include +-#include +-#include +- +-/* +- * 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 +-#include +-#include +-#include +- +-#include +-#include +-#include +-#include +-#include +- +-#include +-#include +-#include +- +-#include +-#include +-#include +-#include +- +-/* +- * 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 ++#include ++#include ++#include ++ ++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 ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++#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 +-#include +- +-#include +- +-/*! +- * \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 +-#include +-#include +-#include +- +-#include +-#include +-#include +- +-#include +- +-#include +-#include +-#include +- +-#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 +-#include +-#include +-#include +- +-#include +-#include +- +-#include +-#include +- +-#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 ++#include ++#include ++#include ++ ++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 ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++#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 ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#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 */ ++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 ++#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 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 ++#include ++#include ++#include ++ ++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 ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++#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 ++#include ++#include ++#include ++ ++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 ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++#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 + diff --git a/meta-digi-arm/dynamic-layers/stm-st-stm32mp/recipes-security/scp-firmware/scp-firmware/0001-Correct-git-error.patch b/meta-digi-arm/dynamic-layers/stm-st-stm32mp/recipes-security/scp-firmware/scp-firmware/0001-Correct-git-error.patch new file mode 100644 index 000000000..1943abcbb --- /dev/null +++ b/meta-digi-arm/dynamic-layers/stm-st-stm32mp/recipes-security/scp-firmware/scp-firmware/0001-Correct-git-error.patch @@ -0,0 +1,32 @@ +From 27dd5642469b49aa6a94d99d97bce793f2473053 Mon Sep 17 00:00:00 2001 +From: Christophe Priouzeau +Date: Tue, 28 Nov 2023 14:18:02 +0100 +Subject: [PATCH] Correct git error + +When there is no .git for scp firmware, the git describe command +return error: +fatal: not a git repository (or any parent up to mount point /mnt) +Stopping at filesystem boundary (GIT_DISCOVERY_ACROSS_FILESYSTEM not set). + +To correct this kind of error, we can redirect the error on a variable + +Signed-off-by: Christophe Priouzeau +--- + framework/CMakeLists.txt | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/framework/CMakeLists.txt b/framework/CMakeLists.txt +index 9b9bb229..9a9f0bd4 100644 +--- a/framework/CMakeLists.txt ++++ b/framework/CMakeLists.txt +@@ -197,6 +197,7 @@ if(GIT_FOUND) + COMMAND "${GIT_EXECUTABLE}" describe --tags --dirty --always + WORKING_DIRECTORY "${SCP_SOURCE_DIR}" + OUTPUT_VARIABLE SCP_DESCRIBE ++ ERROR_VARIABLE _errorOut + OUTPUT_STRIP_TRAILING_WHITESPACE) + endif() + +-- +2.34.1 + diff --git a/meta-digi-arm/dynamic-layers/stm-st-stm32mp/recipes-security/scp-firmware/scp-firmware/README.HOW_TO.txt b/meta-digi-arm/dynamic-layers/stm-st-stm32mp/recipes-security/scp-firmware/scp-firmware/README.HOW_TO.txt new file mode 100644 index 000000000..579be8b66 --- /dev/null +++ b/meta-digi-arm/dynamic-layers/stm-st-stm32mp/recipes-security/scp-firmware/scp-firmware/README.HOW_TO.txt @@ -0,0 +1,56 @@ +Sharing scp firmware +1. Prepare scp firmware source +2. Manage scp firmware source code with GIT +3. Configure scp firmware source code +4. Test scp firmware source code + +-------------------------------------- +1. Prepare scp-firmware source +-------------------------------------- +If not already done, extract the sources from Developer Package tarball, for example: + $ tar xf en.SOURCES-stm32mp1-*.tar.xz + +In the scp firmware source directory (sources/*/##BP##-##PR##), +you have one external dt tarball: + - ##BP##-##PR##.tar.xz + - 00*.patch + +If you would like to have a git management for the source code move to +to section 2 [Management of external dt source code with GIT]. + +Otherwise, to manage scp firmware source code without git, you must extract the +tarball now and apply the patch: + + $> tar xf ##BP##-##PR##.tar.xz + $> cd ##BP## + $> for p in `ls -1 ../*.patch`; do patch -p1 < $p; done + +You can now move to section 3 [Configure scp firmware source code]. + +------------------------------------- +2. Manage external dt source code with GIT +------------------------------------- +If you like to have a better management of change made on external dt source, you +have following solutions to use git. + +2.1 Create Git from tarball +--------------------------- + $ cd + $ test -d .git || git init . && git add . && git commit -m "new scp-firwmare" && git gc + $ git checkout -b WORKING + NB: this is the fastest way to get your scp firmware source code ready for development + +------------------------------- +3. Configure scp firmware source code +------------------------------- +To enable use of scp firmware source code for other component, you must set the +SCPFW_DIR variable to your shell environement: + + $> export SCPFW_DIR=$PWD/##BP## + +--------------------------- +4. Test scp firmware source code +--------------------------- +Nothing to do, scp-firmware is directly used by other component. + + #> echo "*** Nothing to test ***"