diff --git a/CMakeLists.txt b/CMakeLists.txt index 4edb25aa9b1d42c519d30bf44e701c3677b7c3ee..1f4de7bccf2af59c1171cc5042b362e8a22dbb79 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -151,7 +151,7 @@ endif() cmake_dependent_option( CMAKE_INTERPROCEDURAL_OPTIMIZATION "Enable interprocedural optimization?" - TRUE "SCP_IPO_SUPPORTED" FALSE) + TRUE "SCP_IPO_SUPPORTED;SCP_ENABLE_IPO" FALSE) # # Export a `compile_commands.json` file for generators that support it. @@ -331,10 +331,28 @@ include(CMakeDependentOption) # Common build options +if(SCP_ARCHITECTURE STREQUAL "zephyr") + set(SCP_ENABLE_SUB_SYSTEM_MODE_INIT TRUE) + set(SCP_ENABLE_CMSIS_INIT TRUE) +endif() + +if(SCP_ARCHITECTURE STREQUAL "optee") + set(SCP_ENABLE_SUB_SYSTEM_MODE_INIT TRUE) +endif() + +if(SCP_ARCHITECTURE STREQUAL "none") + set(SCP_ENABLE_SUB_SYSTEM_MODE_INIT TRUE) +endif() + set(SCP_ENABLE_OVERRIDE_FIRMWARE_NAME ${SCP_ENABLE_OVERRIDE_FIRMWARE_NAME_INIT} CACHE STRING "Override firmware binary name") +cmake_dependent_option( + SCP_ENABLE_CMSIS "Enable the CMSIS RTOS support?" + "${SCP_ENABLE_CMSIS_INIT}" + "DEFINED SCP_ENABLE_CMSIS_INIT" "${SCP_ENABLE_CMSIS}") + cmake_dependent_option( SCP_ENABLE_SUB_SYSTEM_MODE "Enable the execution as a sub-system?" "${SCP_ENABLE_SUB_SYSTEM_MODE_INIT}" @@ -538,6 +556,10 @@ if(SCP_FIRMWARE) string(APPEND scp_defines "$$") string(APPEND scp_defines "$$") + list(APPEND scp_libraries "$") + list(APPEND scp_libraries "$") + list(APPEND scp_libraries "$") + foreach(module IN LISTS SCP_MODULE_TARGETS) string(APPEND scp_sources "$$") string(APPEND scp_sources "$$") @@ -547,6 +569,8 @@ if(SCP_FIRMWARE) string(APPEND scp_defines "$$") string(APPEND scp_defines "$$") + + list(APPEND scp_libraries "$") endforeach() set(scp_sources $) @@ -561,6 +585,18 @@ if(SCP_FIRMWARE) add_subdirectory("doc" EXCLUDE_FROM_ALL) endif() + +set(SCP_FIRMWARE_LIB "${SCP_FIRMWARE_TARGET}-all") + +# merged libraries is only built when `make ${SCP_FIRMWARE_LIB}` is issued +add_custom_target(${SCP_FIRMWARE_LIB} + # COMMAND/COMMENT must be upper case + COMMAND ${CMAKE_AR} rcT $/lib${SCP_FIRMWARE_LIB}.a ${scp_libraries} + COMMENT " Merging all libraries in a single lib${SCP_FIRMWARE_LIB}.a" +) + +add_dependencies(${SCP_FIRMWARE_LIB} ${SCP_FIRMWARE_TARGET}) + # # Set up global inclusions and exclusions for source file quality assurance # tools. This is intended to filter in external directories (e.g. out-of-tree diff --git a/arch/CMakeLists.txt b/arch/CMakeLists.txt index 13a846dfcb4611c9a0214b7fcdb19279d51ee0e2..a99a77d028560dd28e03586b2ff99b968a2536d6 100644 --- a/arch/CMakeLists.txt +++ b/arch/CMakeLists.txt @@ -8,6 +8,8 @@ list(APPEND SCP_ARCHITECTURE_PATHS "${CMAKE_CURRENT_SOURCE_DIR}/arm/arm-m") list(APPEND SCP_ARCHITECTURE_PATHS "${CMAKE_CURRENT_SOURCE_DIR}/arm/armv8-a") list(APPEND SCP_ARCHITECTURE_PATHS "${CMAKE_CURRENT_SOURCE_DIR}/none/host") +list(APPEND SCP_ARCHITECTURE_PATHS "${CMAKE_CURRENT_SOURCE_DIR}/none/optee") +list(APPEND SCP_ARCHITECTURE_PATHS "${CMAKE_CURRENT_SOURCE_DIR}/none/zephyr") set(SCP_ARCHITECTURE_ "${SCP_ARCHITECTURE}") diff --git a/arch/none/host/include/arch_main.h b/arch/none/host/include/arch_main.h new file mode 100644 index 0000000000000000000000000000000000000000..51768a10eed0c0aab44fc2b5be388973f4488e4b --- /dev/null +++ b/arch/none/host/include/arch_main.h @@ -0,0 +1,24 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2021-2022, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef ARCH_MAIN_H +#define ARCH_MAIN_H + +/*! + * \brief Initialize the architecture. + * + */ +int scmi_arch_init(void); + +/*! + * \brief Stop the architecture. + * + */ +int scmi_arch_deinit(void); + + +#endif /* ARCH_MAIN_H */ diff --git a/arch/none/host/src/arch_interrupt.c b/arch/none/host/src/arch_interrupt.c index 64aee4df362f5f6ddc06960cb8208f43e2ebc1fc..362bf19b2d35615e9f2c13f8b1370bdb675e0cf5 100644 --- a/arch/none/host/src/arch_interrupt.c +++ b/arch/none/host/src/arch_interrupt.c @@ -14,6 +14,8 @@ #include #include +#include + static int global_enable(void) { return FWK_E_SUPPORT; diff --git a/arch/none/host/src/arch_main.c b/arch/none/host/src/arch_main.c index c17b325966cc60cca91440c8ee9cc1b535a58d0d..d3b5b7fad8937a8e4c3e5b57f0676266cffc2b83 100644 --- a/arch/none/host/src/arch_main.c +++ b/arch/none/host/src/arch_main.c @@ -1,37 +1,33 @@ /* * Arm SCP/MCP Software - * Copyright (c) 2015-2021, Arm Limited and Contributors. All rights reserved. + * Copyright (c) 2015-2022, Arm Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ #include -#include #include +#include #include -#include -#include - -/* - * Catches early failures in the initialization. - */ -static noreturn void panic(void) -{ - printf("Panic!\n"); - exit(1); -} - -static const struct fwk_arch_init_driver arch_init_driver = { +static const struct fwk_arch_init_driver scmi_init_driver = { .interrupt = arch_interrupt_init, }; -int main(void) +/* SCMI server init/deinit wrapper */ +int scmi_arch_init(void) { int status; - status = fwk_arch_init(&arch_init_driver); - if (status != FWK_SUCCESS) - panic(); + status = fwk_arch_init(&scmi_init_driver); + + fwk_log_flush(); + + return status; +} + +int scmi_arch_deinit(void) +{ + return fwk_arch_deinit(); } diff --git a/arch/none/optee/Architecture.cmake b/arch/none/optee/Architecture.cmake new file mode 100644 index 0000000000000000000000000000000000000000..9a325b81611134874a07c0e8e2f007aea0ee6792 --- /dev/null +++ b/arch/none/optee/Architecture.cmake @@ -0,0 +1,9 @@ +# +# Arm SCP/MCP Software +# Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +set(SCP_ARCHITECTURE "optee") +set(SCP_ARCHITECTURE_TARGET "arch-optee") diff --git a/arch/none/optee/CMakeLists.txt b/arch/none/optee/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..b274771a0d869292ec5b21fa77c7a858971b49cd --- /dev/null +++ b/arch/none/optee/CMakeLists.txt @@ -0,0 +1,32 @@ +# +# Arm SCP/MCP Software +# Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +add_library(arch-optee) + +if(NOT CFG_NUM_THREADS) + message(FATAL_ERROR + "Insufficient firmware metadata provided.\n" + "For optee arch, you must set CFG_NUM_THREADS") +endif() + +if(NOT SCP_OPTEE_DIR) + message(FATAL_ERROR + "Insufficient firmware metadata provided.\n" + "For optee arch, you must set SCP_OPTEE_DIR") +endif() + +target_compile_definitions(arch-optee PUBLIC -DCFG_NUM_THREADS=${CFG_NUM_THREADS}) + +target_include_directories(arch-optee + PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include") + +target_link_libraries(arch-optee + PUBLIC module-optee-mhu) + +target_sources( + arch-optee PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/src/arch_interrupt.c" + "${CMAKE_CURRENT_SOURCE_DIR}/src/arch_main.c") diff --git a/arch/none/optee/include/arch_helpers.h b/arch/none/optee/include/arch_helpers.h new file mode 100644 index 0000000000000000000000000000000000000000..ab3526fa714ab0d92c37c57d0f7c7b7daba4aeb9 --- /dev/null +++ b/arch/none/optee/include/arch_helpers.h @@ -0,0 +1,36 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef ARCH_HELPERS_H +#define ARCH_HELPERS_H + +/*! + * \brief Enables global CPU interrupts. (stub) + * + */ +inline static void arch_interrupts_enable(unsigned int not_used) +{ +} + +/*! + * \brief Disables global CPU interrupts. (stub) + * + */ +inline static unsigned int arch_interrupts_disable(void) +{ + return 0; +} + +/*! + * \brief Suspend execution of current CPU. + * + */ +inline static void arch_suspend(void) +{ +} + +#endif /* ARCH_HELPERS_H */ diff --git a/arch/none/optee/include/arch_interrupt.h b/arch/none/optee/include/arch_interrupt.h new file mode 100644 index 0000000000000000000000000000000000000000..372a60fef8c15eb96cac678b7e71210620b48365 --- /dev/null +++ b/arch/none/optee/include/arch_interrupt.h @@ -0,0 +1,25 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2020-2022, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef ARCH_INTERRUPT_H +#define ARCH_INTERRUPT_H + +#include + +/*! + * \brief Initialize the architecture interrupt management component. + * + * \param[out] Pointer to the interrupt driver. + * + * \retval ::FWK_E_PANIC The operation failed. + * \retval ::FWK_SUCCESS The operation succeeded. + * + * \return Status code representing the result of the operation. + */ +int arch_interrupt_init(const struct fwk_arch_interrupt_driver **driver); + +#endif /* ARCH_INTERRUPT_H */ diff --git a/arch/none/optee/include/arch_main.h b/arch/none/optee/include/arch_main.h new file mode 100644 index 0000000000000000000000000000000000000000..17c3ca5ae342260614ef39ae08e74b7f2cf0512c --- /dev/null +++ b/arch/none/optee/include/arch_main.h @@ -0,0 +1,48 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef ARCH_MAIN_H +#define ARCH_MAIN_H + +#include +#include +#include + +/*! + * \brief Initialize the architecture. + * + */ +int scmi_arch_init(void); + +/*! + * \brief Stop the architecture. + * + */ +int scmi_arch_deinit(void); + +/*! + * \brief Get number of channels. + * + */ +extern int scmi_get_devices_count(void); + +/*! + * \brief Get the id of a channel. + * + */ +extern int scmi_get_device(unsigned int id); + +/*! + * \brief Add new event to process on the channel id. + * + */ +extern void scmi_process_mhu_smt(unsigned int id); + +extern void scmi_process_mhu_msg(unsigned int id, void *in_buf, size_t in_size, + void *out_buf, size_t *out_size); + +#endif /* ARCH_MAIN_H */ diff --git a/arch/none/optee/src/arch_interrupt.c b/arch/none/optee/src/arch_interrupt.c new file mode 100644 index 0000000000000000000000000000000000000000..64aee4df362f5f6ddc06960cb8208f43e2ebc1fc --- /dev/null +++ b/arch/none/optee/src/arch_interrupt.c @@ -0,0 +1,120 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2015-2022, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Description: + * Interrupt management. + */ + +#include +#include + +#include +#include + +static int global_enable(void) +{ + return FWK_E_SUPPORT; +} + +static int global_disable(void) +{ + return FWK_E_SUPPORT; +} + +static int is_enabled(unsigned int interrupt, bool *state) +{ + return FWK_E_SUPPORT; +} + +static int enable(unsigned int interrupt) +{ + return FWK_E_SUPPORT; +} + +static int disable(unsigned int interrupt) +{ + return FWK_E_SUPPORT; +} + +static int is_pending(unsigned int interrupt, bool *state) +{ + return FWK_E_SUPPORT; +} + +static int set_pending(unsigned int interrupt) +{ + return FWK_E_SUPPORT; +} + +static int clear_pending(unsigned int interrupt) +{ + return FWK_E_SUPPORT; +} + +static int set_isr_irq(unsigned int interrupt, void (*isr)(void)) +{ + return FWK_E_SUPPORT; +} + +static int set_isr_irq_param( + unsigned int interrupt, + void (*isr)(uintptr_t param), + uintptr_t parameter) +{ + return FWK_E_SUPPORT; +} + +static int set_isr_nmi(void (*isr)(void)) +{ + return FWK_E_SUPPORT; +} + +static int set_isr_nmi_param(void (*isr)(uintptr_t param), uintptr_t parameter) +{ + return FWK_E_SUPPORT; +} + +static int set_isr_fault(void (*isr)(void)) +{ + return FWK_E_SUPPORT; +} + +static int get_current(unsigned int *interrupt) +{ + return FWK_E_SUPPORT; +} + +static bool is_interrupt_context(void) +{ + return false; +} + +static const struct fwk_arch_interrupt_driver driver = { + .global_enable = global_enable, + .global_disable = global_disable, + .is_enabled = is_enabled, + .enable = enable, + .disable = disable, + .is_pending = is_pending, + .set_pending = set_pending, + .clear_pending = clear_pending, + .set_isr_irq = set_isr_irq, + .set_isr_irq_param = set_isr_irq_param, + .set_isr_nmi = set_isr_nmi, + .set_isr_nmi_param = set_isr_nmi_param, + .set_isr_fault = set_isr_fault, + .get_current = get_current, + .is_interrupt_context = is_interrupt_context, +}; + +int arch_interrupt_init(const struct fwk_arch_interrupt_driver **_driver) +{ + if (_driver == NULL) + return FWK_E_PARAM; + + *_driver = &driver; + return FWK_SUCCESS; +} diff --git a/arch/none/optee/src/arch_main.c b/arch/none/optee/src/arch_main.c new file mode 100644 index 0000000000000000000000000000000000000000..192199eb57c94d11ac349cb7517ab745d2cdbd0f --- /dev/null +++ b/arch/none/optee/src/arch_main.c @@ -0,0 +1,120 @@ +/* + * 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 + +extern short int thread_get_id(void); + +static struct __fwk_ctx *thread_ctx[CFG_NUM_THREADS]; + +struct __fwk_ctx *arch_get_execution_ctx(void) +{ + return thread_ctx[thread_get_id()]; +} + +void arch_set_execution_ctx(struct __fwk_ctx *ctx) +{ + thread_ctx[thread_get_id()] = ctx; +} + +#include + +static const struct fwk_arch_init_driver scmi_init_driver = { + .interrupt = arch_interrupt_init, +}; + +int scmi_arch_init(void) +{ + fwk_id_t none_id = FWK_ID_NONE_INIT; + int status; + + fwk_set_ctx(none_id); + + status = fwk_arch_init(&scmi_init_driver); + + fwk_log_flush(); + + return status; +} + +int scmi_arch_deinit(void) +{ + return fwk_arch_deinit(); +} + +int scmi_get_devices_count(void) +{ + return optee_mhu_get_devices_count(); +} + +int scmi_get_device(unsigned int id) +{ + fwk_id_t device_id; + + device_id = optee_mhu_get_device(id); + + if (fwk_id_is_type(device_id, FWK_ID_TYPE_NONE)) { + return -1; + } + + return (int)device_id.value; +} + +void scmi_process_mhu_smt(unsigned int fwk_id) +{ +#if BUILD_HAS_MOD_OPTEE_SMT + fwk_id_t device_id; + + device_id.value = fwk_id; + + fwk_set_ctx(device_id); + + optee_mhu_signal_smt_message(device_id); + + fwk_process_event_queue(); + + fwk_log_flush(); +#endif +} + +void scmi_process_mhu_msg(unsigned int fwk_id, void *in_buf, size_t in_size, + void *out_buf, size_t *out_size) +{ +#if BUILD_HAS_MOD_MSG_SMT + fwk_id_t device_id; + + device_id.value = fwk_id; + + fwk_set_ctx(device_id); + + optee_mhu_signal_msg_message(device_id, in_buf, in_size, out_buf, out_size); + + fwk_process_event_queue(); + + fwk_log_flush(); +#endif +} + +void *aligned_alloc(size_t alignment, size_t size) +{ + return memalign(alignment, size); +} diff --git a/arch/none/zephyr/Architecture.cmake b/arch/none/zephyr/Architecture.cmake new file mode 100644 index 0000000000000000000000000000000000000000..b9c15e471fd56bddc39430100d99fb652b794432 --- /dev/null +++ b/arch/none/zephyr/Architecture.cmake @@ -0,0 +1,9 @@ +# +# Arm SCP/MCP Software +# Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +set(SCP_ARCHITECTURE "zephyr") +set(SCP_ARCHITECTURE_TARGET "arch-zephyr") diff --git a/arch/none/zephyr/CMakeLists.txt b/arch/none/zephyr/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..020b428df14a33368cd252507112321d677f85e9 --- /dev/null +++ b/arch/none/zephyr/CMakeLists.txt @@ -0,0 +1,19 @@ +# +# Arm SCP/MCP Software +# Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +add_library(arch-zephyr) + +target_include_directories(arch-zephyr + PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include") + +# cmake-lint: disable=E1122 + +target_sources( + arch-zephyr PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/src/arch_interrupt.c" + "${CMAKE_CURRENT_SOURCE_DIR}/src/arch_main.c") + +target_link_libraries(arch-zephyr PRIVATE zephyr) diff --git a/arch/none/zephyr/include/arch_helpers.h b/arch/none/zephyr/include/arch_helpers.h new file mode 100644 index 0000000000000000000000000000000000000000..c69889adfd8fa79396621e6c6344534b6711e01f --- /dev/null +++ b/arch/none/zephyr/include/arch_helpers.h @@ -0,0 +1,39 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef ARCH_HELPERS_H +#define ARCH_HELPERS_H + +#include + +/*! + * \brief Enables global CPU interrupts. (stub) + * + */ +inline static void arch_interrupts_enable(unsigned int flags) +{ + zephyr_irq_unlock(flags); +} + +/*! + * \brief Disables global CPU interrupts. (stub) + * + */ +inline static unsigned int arch_interrupts_disable(void) +{ + return zephyr_irq_lock(); +} + +/*! + * \brief Suspend execution of current CPU. + * + */ +inline static void arch_suspend(void) +{ +} + +#endif /* ARCH_HELPERS_H */ diff --git a/arch/none/zephyr/include/arch_interrupt.h b/arch/none/zephyr/include/arch_interrupt.h new file mode 100644 index 0000000000000000000000000000000000000000..8fca6bf1e266e064f30a1df8347db5e56e254ede --- /dev/null +++ b/arch/none/zephyr/include/arch_interrupt.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 ARCH_INTERRUPT_H +#define ARCH_INTERRUPT_H + +#include + +/*! + * \brief Initialize the architecture interrupt management component. + * + * \param[out] Pointer to the interrupt driver. + * + * \retval ::FWK_E_PANIC The operation failed. + * \retval ::FWK_SUCCESS The operation succeeded. + * + * \return Status code representing the result of the operation. + */ +int arch_interrupt_init(const struct fwk_arch_interrupt_driver **driver); + +void zephyr_irq_unlock(unsigned int flags); + +unsigned int zephyr_irq_lock(void); + +#endif /* ARCH_INTERRUPT_H */ diff --git a/arch/none/zephyr/include/arch_main.h b/arch/none/zephyr/include/arch_main.h new file mode 100644 index 0000000000000000000000000000000000000000..1422e1673e0d7c2e63d0e1d83676eecb5909006f --- /dev/null +++ b/arch/none/zephyr/include/arch_main.h @@ -0,0 +1,24 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef ARCH_MAIN_H +#define ARCH_MAIN_H + +/*! + * \brief Initialize the architecture. + * + */ +int scmi_arch_init(void); + +/*! + * \brief Stop the architecture. + * + */ +int scmi_arch_deinit(void); + + +#endif /* ARCH_MAIN_H */ diff --git a/arch/none/zephyr/src/arch_interrupt.c b/arch/none/zephyr/src/arch_interrupt.c new file mode 100644 index 0000000000000000000000000000000000000000..da52016b495ffc21887f361398e2122dcf8407a1 --- /dev/null +++ b/arch/none/zephyr/src/arch_interrupt.c @@ -0,0 +1,137 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Description: + * Interrupt management. + */ + +#include +#include + +#include +#include + +#include +#include + +static int global_enable(void) +{ + return FWK_E_SUPPORT; +} + +static int global_disable(void) +{ + return FWK_E_SUPPORT; +} + +static int is_enabled(unsigned int interrupt, bool *state) +{ + return FWK_E_SUPPORT; +} + +static int enable(unsigned int interrupt) +{ + return FWK_E_SUPPORT; +} + +static int disable(unsigned int interrupt) +{ + return FWK_E_SUPPORT; +} + +static int is_pending(unsigned int interrupt, bool *state) +{ + return FWK_E_SUPPORT; +} + +static int set_pending(unsigned int interrupt) +{ + return FWK_E_SUPPORT; +} + +static int clear_pending(unsigned int interrupt) +{ + return FWK_E_SUPPORT; +} + +static int set_isr_irq(unsigned int interrupt, void (*isr)(void)) +{ + return FWK_E_SUPPORT; +} + +static int set_isr_irq_param( + unsigned int interrupt, + void (*isr)(uintptr_t param), + uintptr_t parameter) +{ + return FWK_E_SUPPORT; +} + +static int set_isr_nmi(void (*isr)(void)) +{ + return FWK_E_SUPPORT; +} + +static int set_isr_nmi_param(void (*isr)(uintptr_t param), uintptr_t parameter) +{ + return FWK_E_SUPPORT; +} + +static int set_isr_fault(void (*isr)(void)) +{ + return FWK_E_SUPPORT; +} + +static int get_current(unsigned int *interrupt) +{ + return FWK_E_SUPPORT; +} + +static bool is_interrupt_context(void) +{ + if (k_is_in_isr()) { + return true; + } + + return false; +} + +void zephyr_irq_unlock(unsigned int flags) +{ + irq_unlock(flags); +} + +unsigned int zephyr_irq_lock(void) +{ + return irq_lock(); +} + +static const struct fwk_arch_interrupt_driver driver = { + .global_enable = global_enable, + .global_disable = global_disable, + .is_enabled = is_enabled, + .enable = enable, + .disable = disable, + .is_pending = is_pending, + .set_pending = set_pending, + .clear_pending = clear_pending, + .set_isr_irq = set_isr_irq, + .set_isr_irq_param = set_isr_irq_param, + .set_isr_nmi = set_isr_nmi, + .set_isr_nmi_param = set_isr_nmi_param, + .set_isr_fault = set_isr_fault, + .get_current = get_current, + .is_interrupt_context = is_interrupt_context, +}; + +int arch_interrupt_init(const struct fwk_arch_interrupt_driver **_driver) +{ + if (_driver == NULL) + return FWK_E_PARAM; + + *_driver = &driver; + return FWK_SUCCESS; +} diff --git a/arch/none/zephyr/src/arch_main.c b/arch/none/zephyr/src/arch_main.c new file mode 100644 index 0000000000000000000000000000000000000000..95b5cae1a37729d3b11fa422bc892eff8b1e3a83 --- /dev/null +++ b/arch/none/zephyr/src/arch_main.c @@ -0,0 +1,33 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include + +static const struct fwk_arch_init_driver scmi_init_driver = { + .interrupt = arch_interrupt_init, +}; + +/* SCMI server init/deinit wrapper */ +int scmi_arch_init(void) +{ + int status; + + status = fwk_arch_init(&scmi_init_driver); + + fwk_log_flush(); + + return status; +} + +int scmi_arch_deinit(void) +{ + return fwk_arch_deinit(); +} diff --git a/framework/CMakeLists.txt b/framework/CMakeLists.txt index 9bb45403963cc2059d9d3837816b9c7c9f7fe18b..33d1cd5970096f6c0f96afd2045d19c4a0382abe 100644 --- a/framework/CMakeLists.txt +++ b/framework/CMakeLists.txt @@ -40,6 +40,9 @@ target_sources( "${CMAKE_CURRENT_SOURCE_DIR}/src/stdlib.c" "${CMAKE_CURRENT_SOURCE_DIR}/src/fwk_core.c") +if(SCP_ENABLE_CMSIS) + target_compile_definitions(framework PUBLIC "BUILD_HAS_CMSIS") +endif() if(SCP_ENABLE_SUB_SYSTEM_MODE) target_compile_definitions(framework PUBLIC "BUILD_HAS_SUB_SYSTEM_MODE") @@ -240,3 +243,5 @@ if(SCP_ENABLE_DEBUGGER) endif() target_link_libraries(framework INTERFACE ${SCP_ARCHITECTURE_TARGET}) + +target_link_libraries(framework INTERFACE ${SCP_FIRMWARE_TARGET}) diff --git a/framework/include/fwk_core.h b/framework/include/fwk_core.h index bbda379cda3e664585f09d1aafec0cd5154e22f8..bc9910062d59d84b80b273da6018829fe6e2f6bb 100644 --- a/framework/include/fwk_core.h +++ b/framework/include/fwk_core.h @@ -147,6 +147,22 @@ int fwk_is_delayed_response_list_empty(fwk_id_t id, bool *is_empty); */ int fwk_get_first_delayed_response(fwk_id_t id, struct fwk_event *event); +/*! + * \brief Set the execution context to be used. An specific execution context + * can be associated to an element. + * + * \details When there are several transport channels that operate on + * unrelated resources, we can used dedicated execution context (event list ...) + * in order to parallelize the requests. + * + * \param[in] id Identifier of the module or element to use for the execution + * context. + * + * \retval ::FWK_SUCCESS The execution context has been set. + * \return Status code representing the result of the operation. + */ +void fwk_set_ctx(fwk_id_t id); + /*! * \} */ diff --git a/framework/include/fwk_status.h b/framework/include/fwk_status.h index d8585f31a9801a74d27583e7dd25aee8d696a907..59acde26fc0f0555f49ef70a556028cc9bd9b42a 100644 --- a/framework/include/fwk_status.h +++ b/framework/include/fwk_status.h @@ -1,6 +1,6 @@ /* * Arm SCP/MCP Software - * Copyright (c) 2015-2021, Arm Limited and Contributors. All rights reserved. + * Copyright (c) 2015-2022, Arm Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause * @@ -21,6 +21,9 @@ * \{ */ +/*! Success, need to init an execution context */ +#define FWK_INIT_CTX 2 + /*! Success, request is pending */ #define FWK_PENDING 1 diff --git a/framework/include/internal/fwk_context.h b/framework/include/internal/fwk_context.h index 722851c99cc9393dda85e3e3c3258dd2f886dd16..11c0b3a841a42262da78ab89910f32fc5c308213 100644 --- a/framework/include/internal/fwk_context.h +++ b/framework/include/internal/fwk_context.h @@ -49,4 +49,19 @@ struct __fwk_ctx { */ struct __fwk_ctx *__fwk_get_ctx(void); +/* + * \brief Init an execution context. + */ +int __fwk_init_execution_ctx(fwk_id_t element_id, size_t event_count); + +/* + * \brief architecture specific get of the current execution context. + */ +struct __fwk_ctx *arch_get_execution_ctx(void); + +/* + * \brief architecture specific set of the current execution context. + */ +void arch_set_execution_ctx(struct __fwk_ctx *ctx); + #endif /* FWK_INTERNAL_CONTEXT_H */ diff --git a/framework/include/internal/fwk_core.h b/framework/include/internal/fwk_core.h index ca580cd10a95b000120fffff1777fb017438710b..84ad8b512fdcbdbf26b6cdcb34d63d14ac8478cb 100644 --- a/framework/include/internal/fwk_core.h +++ b/framework/include/internal/fwk_core.h @@ -11,18 +11,21 @@ #include #include #include - +#include #include +extern struct __fwk_ctx global_ctx; + /* * \brief Initialize the core framework component. * * \param event_count The maximum number of events in all queues at all time. + * \param ctx the framexork context to intialize. * * \retval ::FWK_SUCCESS The core framework component was initialized. * \retval ::FWK_E_NOMEM Insufficient memory available for event queues. */ -int __fwk_init(size_t event_count); +int __fwk_init(size_t event_count, struct __fwk_ctx *ctx); /* * \brief Loop forever, processing events raised by modules and interrupt diff --git a/framework/include/internal/fwk_module.h b/framework/include/internal/fwk_module.h index 2c941b9e553b14e1071af961a67764b54f8001e0..4947299815426033df5c8a4a6b1906cdeaed5a45 100644 --- a/framework/include/internal/fwk_module.h +++ b/framework/include/internal/fwk_module.h @@ -41,6 +41,9 @@ struct fwk_module_context { /* Table of element contexts */ struct fwk_element_ctx *element_ctx_table; + /* Module execution context */ + struct __fwk_ctx *ctx; + #ifdef BUILD_HAS_NOTIFICATION /* * Table of notification subscription lists. One list per type of @@ -66,6 +69,9 @@ struct fwk_element_ctx { /* Number of sub-elements */ size_t sub_element_count; + /* Element execution context */ + struct __fwk_ctx *ctx; + #ifdef BUILD_HAS_NOTIFICATION /* * Table of notification subscription lists. One list per type of diff --git a/framework/src/fwk_core.c b/framework/src/fwk_core.c index 2ba8b97cf2d82516f3f8a1d1308b10168522f4d8..595d6b9ed221d37c14417e981d4d7a3cfd2e8efb 100644 --- a/framework/src/fwk_core.c +++ b/framework/src/fwk_core.c @@ -29,11 +29,64 @@ #include #include -static struct __fwk_ctx ctx; +struct __fwk_ctx global_ctx; static const char err_msg_line[] = "[FWK] Error %d in %s @%d"; static const char err_msg_func[] = "[FWK] Error %d in %s"; +struct __fwk_ctx * __attribute__((__weak__)) arch_get_execution_ctx(void) +{ + return &global_ctx; +} + +void __attribute__((__weak__)) arch_set_execution_ctx(struct __fwk_ctx *ctx) +{ + return; +} + +struct __fwk_ctx *__fwk_get_ctx(void) +{ + return arch_get_execution_ctx(); +} + + +void fwk_set_ctx(fwk_id_t id) +{ + struct __fwk_ctx *tmp = NULL; + + /* Find a module execution context */ + if (fwk_id_is_type(id, FWK_ID_TYPE_MODULE)) { + tmp = fwk_module_get_ctx(id)->ctx; + } + + /* Find an element or sub-element execution context */ + if (!tmp && + (fwk_id_is_type(id, FWK_ID_TYPE_ELEMENT) || + fwk_id_is_type(id, FWK_ID_TYPE_SUB_ELEMENT))) { + tmp = fwk_module_get_element_ctx(id)->ctx; + } + + /* Use global execution context if nothing else */ + if (!tmp) + tmp = &global_ctx; + + /* Save execution context */ + arch_set_execution_ctx(tmp); +} + +int __fwk_init_execution_ctx(fwk_id_t element_id, size_t event_count) +{ + struct fwk_element_ctx *element_ctx; + + element_ctx = fwk_module_get_element_ctx(element_id); + element_ctx->ctx = fwk_mm_calloc(1, sizeof(struct __fwk_ctx)); + + if (element_ctx->ctx == NULL) + return FWK_E_NOMEM; + + return __fwk_init(event_count, element_ctx->ctx); +} + enum interrupt_states { UNKNOWN_STATE = 0, INTERRUPT_STATE = 1, @@ -61,13 +114,16 @@ static struct fwk_event *duplicate_event( enum fwk_event_type event_type) { struct fwk_event *allocated_event = NULL; + struct __fwk_ctx *ctx; unsigned int flags; fwk_assert(event != NULL); + ctx = __fwk_get_ctx(); + flags = fwk_interrupt_global_disable(); allocated_event = FWK_LIST_GET( - fwk_list_pop_head(&ctx.free_event_queue), struct fwk_event, slist_node); + fwk_list_pop_head(&ctx->free_event_queue), struct fwk_event, slist_node); (void)fwk_interrupt_global_enable(flags); if (allocated_event == NULL) { @@ -94,7 +150,7 @@ static struct fwk_event *duplicate_event( return allocated_event; } -static int put_event( +static int put_event(struct __fwk_ctx *ctx, void *event, enum interrupt_states intr_state, enum fwk_event_type event_type) @@ -132,7 +188,7 @@ static int put_event( } if (std_event != NULL) { - allocated_event->cookie = ctx.event_cookie_counter++; + allocated_event->cookie = ctx->event_cookie_counter++; std_event->cookie = allocated_event->cookie; } @@ -144,9 +200,9 @@ static int put_event( } } if (intr_state == NOT_INTERRUPT_STATE) { - fwk_list_push_tail(&ctx.event_queue, &allocated_event->slist_node); + fwk_list_push_tail(&ctx->event_queue, &allocated_event->slist_node); } else { - fwk_list_push_tail(&ctx.isr_event_queue, &allocated_event->slist_node); + fwk_list_push_tail(&ctx->isr_event_queue, &allocated_event->slist_node); } #if FWK_LOG_LEVEL <= FWK_LOG_LEVEL_TRACE @@ -161,16 +217,17 @@ static int put_event( return FWK_SUCCESS; } -static void free_event(struct fwk_event *event) +static void free_event(struct __fwk_ctx *ctx, + struct fwk_event *event) { unsigned int flags; flags = fwk_interrupt_global_disable(); - fwk_list_push_tail(&ctx.free_event_queue, &event->slist_node); + fwk_list_push_tail(&ctx->free_event_queue, &event->slist_node); (void)fwk_interrupt_global_enable(flags); } -static void process_next_event(void) +static void process_next_event(struct __fwk_ctx *ctx) { int status; struct fwk_event *event, *allocated_event, async_response_event; @@ -178,8 +235,8 @@ static void process_next_event(void) int (*process_event)( const struct fwk_event *event, struct fwk_event *resp_event); - ctx.current_event = event = FWK_LIST_GET( - fwk_list_pop_head(&ctx.event_queue), struct fwk_event, slist_node); + ctx->current_event = event = FWK_LIST_GET( + fwk_list_pop_head(&ctx->event_queue), struct fwk_event, slist_node); #if FWK_LOG_LEVEL <= FWK_LOG_LEVEL_TRACE FWK_LOG_TRACE( @@ -209,7 +266,7 @@ static void process_next_event(void) async_response_event.is_response = true; async_response_event.response_requested = false; if (!async_response_event.is_delayed_response) { - (void)put_event( + (void)put_event(ctx, &async_response_event, UNKNOWN_STATE, FWK_EVENT_TYPE_STD); } else { allocated_event = @@ -233,19 +290,19 @@ static void process_next_event(void) } } - ctx.current_event = NULL; - free_event(event); + ctx->current_event = NULL; + free_event(ctx, event); return; } -static bool process_isr(void) +static bool process_isr(struct __fwk_ctx *ctx) { struct fwk_event *isr_event; unsigned int flags; flags = fwk_interrupt_global_disable(); isr_event = FWK_LIST_GET( - fwk_list_pop_head(&ctx.isr_event_queue), struct fwk_event, slist_node); + fwk_list_pop_head(&ctx->isr_event_queue), struct fwk_event, slist_node); (void)fwk_interrupt_global_enable(flags); if (isr_event == NULL) { @@ -260,7 +317,7 @@ static bool process_isr(void) FWK_ID_STR(isr_event->target_id)); #endif - fwk_list_push_tail(&ctx.event_queue, &isr_event->slist_node); + fwk_list_push_tail(&ctx->event_queue, &isr_event->slist_node); return true; } @@ -269,34 +326,38 @@ static bool process_isr(void) * Private interface functions */ -int __fwk_init(size_t event_count) +int __fwk_init(size_t event_count, struct __fwk_ctx *ctx) { struct fwk_event *event_table, *event; event_table = fwk_mm_calloc(event_count, sizeof(struct fwk_event)); /* All the event structures are free to be used. */ - fwk_list_init(&ctx.free_event_queue); - fwk_list_init(&ctx.event_queue); - fwk_list_init(&ctx.isr_event_queue); + fwk_list_init(&ctx->free_event_queue); + fwk_list_init(&ctx->event_queue); + fwk_list_init(&ctx->isr_event_queue); for (event = event_table; event < (event_table + event_count); event++) { - fwk_list_push_tail(&ctx.free_event_queue, &event->slist_node); + fwk_list_push_tail(&ctx->free_event_queue, &event->slist_node); } - ctx.initialized = true; + ctx->initialized = true; return FWK_SUCCESS; } void fwk_process_event_queue(void) { + struct __fwk_ctx *ctx; + + ctx = __fwk_get_ctx(); + for (;;) { - while (!fwk_list_is_empty(&ctx.event_queue)) { - process_next_event(); + while (!fwk_list_is_empty(&ctx->event_queue)) { + process_next_event(ctx); } - if (!process_isr()) { + if (!process_isr(ctx)) { break; } } @@ -311,23 +372,26 @@ noreturn void __fwk_run_main_loop(void) } } -struct __fwk_ctx *__fwk_get_ctx(void) -{ - return &ctx; -} - const struct fwk_event *__fwk_get_current_event(void) { - return ctx.current_event; + struct __fwk_ctx *ctx; + + ctx = __fwk_get_ctx(); + + return ctx->current_event; } #ifdef BUILD_HAS_NOTIFICATION int __fwk_put_notification(struct fwk_event *event) { + struct __fwk_ctx *ctx; + + ctx = __fwk_get_ctx(); + event->is_response = false; event->is_notification = true; - return put_event(event, UNKNOWN_STATE, FWK_EVENT_TYPE_STD); + return put_event(ctx, event, UNKNOWN_STATE, FWK_EVENT_TYPE_STD); } #endif @@ -338,10 +402,12 @@ int __fwk_put_notification(struct fwk_event *event) int __fwk_put_event(struct fwk_event *event) { int status = FWK_E_PARAM; + struct __fwk_ctx *ctx; enum interrupt_states intr_state; + ctx = __fwk_get_ctx(); #ifdef BUILD_MODE_DEBUG - if (!ctx.initialized) { + if (!ctx->initialized) { status = FWK_E_INIT; goto error; } @@ -357,8 +423,8 @@ int __fwk_put_event(struct fwk_event *event) intr_state = NOT_INTERRUPT_STATE; } - if ((intr_state == NOT_INTERRUPT_STATE) && (ctx.current_event != NULL)) { - event->source_id = ctx.current_event->target_id; + if ((intr_state == NOT_INTERRUPT_STATE) && (ctx->current_event != NULL)) { + event->source_id = ctx->current_event->target_id; } else if ( !fwk_id_type_is_valid(event->source_id) || !fwk_module_is_valid_entity_id(event->source_id)) { @@ -400,7 +466,7 @@ int __fwk_put_event(struct fwk_event *event) } #endif - return put_event(event, intr_state, FWK_EVENT_TYPE_STD); + return put_event(ctx, event, intr_state, FWK_EVENT_TYPE_STD); error: FWK_LOG_CRIT(err_msg_func, status, __func__); @@ -410,10 +476,13 @@ error: int __fwk_put_event_light(struct fwk_event_light *event) { int status = FWK_E_PARAM; + struct __fwk_ctx *ctx; enum interrupt_states intr_state; + ctx = __fwk_get_ctx(); + #ifdef BUILD_MODE_DEBUG - if (!ctx.initialized) { + if (!ctx->initialized) { status = FWK_E_INIT; goto error; } @@ -429,8 +498,8 @@ int __fwk_put_event_light(struct fwk_event_light *event) intr_state = NOT_INTERRUPT_STATE; } - if ((intr_state == NOT_INTERRUPT_STATE) && (ctx.current_event != NULL)) { - event->source_id = ctx.current_event->target_id; + if ((intr_state == NOT_INTERRUPT_STATE) && (ctx->current_event != NULL)) { + event->source_id = ctx->current_event->target_id; } else if ( !fwk_id_type_is_valid(event->source_id) || !fwk_module_is_valid_entity_id(event->source_id)) { @@ -451,7 +520,7 @@ int __fwk_put_event_light(struct fwk_event_light *event) } #endif - return put_event(event, intr_state, FWK_EVENT_TYPE_LIGHT); + return put_event(ctx, event, intr_state, FWK_EVENT_TYPE_LIGHT); error: FWK_LOG_CRIT(err_msg_func, status, __func__); diff --git a/framework/src/fwk_module.c b/framework/src/fwk_module.c index 8649ac243bdbc536c5a94a37d7eb017a7512149d..a3b3c6764b83312a62364ba9690709bdf55d886b 100644 --- a/framework/src/fwk_module.c +++ b/framework/src/fwk_module.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include @@ -98,6 +99,7 @@ static void fwk_module_init_element_ctx( .state = FWK_MODULE_STATE_UNINITIALIZED, .desc = element, .sub_element_count = element->sub_element_count, + .ctx = NULL, }; fwk_list_init(&ctx->delayed_response_list); @@ -199,6 +201,11 @@ static void fwk_module_init_elements(struct fwk_module_context *ctx) status = desc->element_init( element_id, element->sub_element_count, element->data); + + if (status == FWK_INIT_CTX) { + status = __fwk_init_execution_ctx(element_id, FWK_MODULE_EVENT_COUNT); + } + if (status != FWK_SUCCESS) { fwk_trap(); } @@ -420,7 +427,7 @@ int fwk_module_start(void) CLI_DEBUGGER(); - status = __fwk_init(FWK_MODULE_EVENT_COUNT); + status = __fwk_init(FWK_MODULE_EVENT_COUNT, &global_ctx); if (status != FWK_SUCCESS) { return status; } diff --git a/framework/test/test_fwk_core.c b/framework/test/test_fwk_core.c index 81bba301a7c91961c760a5b34917fb5163dcaded..b91f7d0fd9ad778ee0265c4fe57bfc862e25161c 100644 --- a/framework/test/test_fwk_core.c +++ b/framework/test/test_fwk_core.c @@ -153,7 +153,7 @@ static void test___fwk_init(void) fwk_mm_calloc_return_val = true; /* Insert 2 events in the list */ - result = __fwk_init(event_count); + result = __fwk_init(event_count, &global_ctx); assert(result == FWK_SUCCESS); assert( ctx->free_event_queue.head == @@ -204,7 +204,7 @@ static void test___fwk_run_main_loop(void) .id = FWK_ID_NOTIFICATION(0x5, 0x9), }; - result = __fwk_init(1); + result = __fwk_init(1, &global_ctx); assert(result == FWK_SUCCESS); free_event_queue_break = true; allocated_event = FWK_LIST_GET( @@ -358,7 +358,7 @@ static void test_fwk_put_event(void) result = fwk_put_event(&event2); assert(result == FWK_E_INIT); - result = __fwk_init(2); + result = __fwk_init(2, &global_ctx); assert(result == FWK_SUCCESS); /* Invalid entity ID */ @@ -425,7 +425,7 @@ static void test_fwk_put_event_light(void) result = fwk_put_event(&event2); assert(result == FWK_E_INIT); - result = __fwk_init(2); + result = __fwk_init(2, &global_ctx); assert(result == FWK_SUCCESS); /* Invalid entity ID */ @@ -493,7 +493,7 @@ static void test___fwk_put_notification(void) .response_requested = false, }; - result = __fwk_init(2); + result = __fwk_init(2, &global_ctx); assert(result == FWK_SUCCESS); result = __fwk_put_notification(&event1); diff --git a/module/CMakeLists.txt b/module/CMakeLists.txt index aaff739b648120b340285f8fec03f41869c5c8e7..aec8259044c60314e5b94a4ae296b4c23096598f 100644 --- a/module/CMakeLists.txt +++ b/module/CMakeLists.txt @@ -76,6 +76,16 @@ list(APPEND SCP_MODULE_PATHS "${CMAKE_CURRENT_SOURCE_DIR}/mpmm") list(APPEND SCP_MODULE_PATHS "${CMAKE_CURRENT_SOURCE_DIR}/thermal_mgmt") list(APPEND SCP_MODULE_PATHS "${CMAKE_CURRENT_SOURCE_DIR}/scmi_sensor_req") list(APPEND SCP_MODULE_PATHS "${CMAKE_CURRENT_SOURCE_DIR}/sp805") +list(APPEND SCP_MODULE_PATHS "${CMAKE_CURRENT_SOURCE_DIR}/optee/mhu") +list(APPEND SCP_MODULE_PATHS "${CMAKE_CURRENT_SOURCE_DIR}/optee/smt") +list(APPEND SCP_MODULE_PATHS "${CMAKE_CURRENT_SOURCE_DIR}/msg_smt") +list(APPEND SCP_MODULE_PATHS "${CMAKE_CURRENT_SOURCE_DIR}/optee/console") +list(APPEND SCP_MODULE_PATHS "${CMAKE_CURRENT_SOURCE_DIR}/optee/clock") +list(APPEND SCP_MODULE_PATHS "${CMAKE_CURRENT_SOURCE_DIR}/optee/reset") +list(APPEND SCP_MODULE_PATHS "${CMAKE_CURRENT_SOURCE_DIR}/input_mhu") +list(APPEND SCP_MODULE_PATHS "${CMAKE_CURRENT_SOURCE_DIR}/host_console") +list(APPEND SCP_MODULE_PATHS "${CMAKE_CURRENT_SOURCE_DIR}/vhost_mhu") +list(APPEND SCP_MODULE_PATHS "${CMAKE_CURRENT_SOURCE_DIR}/vring_mhu") foreach(source_dir IN LISTS SCP_MODULE_PATHS) unset(SCP_MODULE) diff --git a/module/host_console/CMakeLists.txt b/module/host_console/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..f78181ac05761866d1465abc5ca70eef007326aa --- /dev/null +++ b/module/host_console/CMakeLists.txt @@ -0,0 +1,11 @@ +# +# Arm SCP/MCP Software +# Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +add_library(${SCP_MODULE_TARGET} SCP_MODULE) + +target_sources(${SCP_MODULE_TARGET} + PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/src/mod_host_console.c") diff --git a/module/host_console/Module.cmake b/module/host_console/Module.cmake new file mode 100644 index 0000000000000000000000000000000000000000..74f35337bbda2df95a120d4ae40b6eb299e30184 --- /dev/null +++ b/module/host_console/Module.cmake @@ -0,0 +1,9 @@ +# +# Arm SCP/MCP Software +# Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +set(SCP_MODULE "host-console") +set(SCP_MODULE_TARGET "module-host-console") diff --git a/module/host_console/src/mod_host_console.c b/module/host_console/src/mod_host_console.c new file mode 100644 index 0000000000000000000000000000000000000000..ef6da88ad33aa1c90558646f2a40972aca136e87 --- /dev/null +++ b/module/host_console/src/mod_host_console.c @@ -0,0 +1,86 @@ +/* + * 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 + +static int mod_console_init( + fwk_id_t module_id, + unsigned int element_count, + const void *data) +{ + return FWK_SUCCESS; +} + +static int mod_console_element_init( + fwk_id_t element_id, + unsigned int unused, + const void *data) +{ + return FWK_SUCCESS; +} + + +static int mod_console_io_open(const struct fwk_io_stream *stream) +{ + return FWK_SUCCESS; +} + +static int mod_console_io_getch( + const struct fwk_io_stream *restrict stream, + char *restrict ch) +{ + *ch = 'A'; + + return FWK_SUCCESS; +} + +static int mod_console_io_putch(const struct fwk_io_stream *stream, char ch) +{ + putchar(ch); + return FWK_SUCCESS; +} + +static int mod_console_close(const struct fwk_io_stream *stream) +{ + return FWK_SUCCESS; +} + +const struct fwk_module module_host_console = { + .type = FWK_MODULE_TYPE_DRIVER, + + .init = mod_console_init, + .element_init = mod_console_element_init, + + .adapter = + (struct fwk_io_adapter){ + .open = mod_console_io_open, + .getch = mod_console_io_getch, + .putch = mod_console_io_putch, + .close = mod_console_close, + }, +}; + +struct fwk_module_config config_host_console = { + .elements = FWK_MODULE_STATIC_ELEMENTS({ + [0] = { + .name = "printf", + .data = (void *)1 + }, + [1] = { 0 }, + }), +}; diff --git a/module/input_mhu/CMakeLists.txt b/module/input_mhu/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..693efb13741e7c132093238af83d510dccc5a52a --- /dev/null +++ b/module/input_mhu/CMakeLists.txt @@ -0,0 +1,22 @@ +# +# Arm SCP/MCP Software +# Copyright (c) 2022, 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") + +if(SCP_ARCHITECTURE_TARGET STREQUAL "arch-none") + find_package(PkgConfig REQUIRED) + pkg_check_modules(deps REQUIRED IMPORTED_TARGET glib-2.0) + target_link_libraries(${SCP_MODULE_TARGET} PRIVATE PkgConfig::deps) +endif() + +target_link_libraries(${SCP_MODULE_TARGET} PRIVATE module-msg-smt) + +target_sources(${SCP_MODULE_TARGET} + PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/src/mod_input_mhu.c") diff --git a/module/input_mhu/Module.cmake b/module/input_mhu/Module.cmake new file mode 100644 index 0000000000000000000000000000000000000000..8c1aa6e8041f525a6c11963bbd9062c4397d32c6 --- /dev/null +++ b/module/input_mhu/Module.cmake @@ -0,0 +1,9 @@ +# +# Arm SCP/MCP Software +# Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +set(SCP_MODULE "input-mhu") +set(SCP_MODULE_TARGET "module-input-mhu") diff --git a/module/input_mhu/include/mod_input_mhu.h b/module/input_mhu/include/mod_input_mhu.h new file mode 100644 index 0000000000000000000000000000000000000000..7ba1ac8ce82e899785e62b83323c1e80504fa5f3 --- /dev/null +++ b/module/input_mhu/include/mod_input_mhu.h @@ -0,0 +1,25 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Description: + * OP-TEE mailbox buffer layer + */ + +#ifndef MOD_VHOST_MHU_H +#define MOD_VHOST_MHU_H + +/*! + * \brief Channel config. + */ +struct mod_input_mhu_channel_config { + /*! Identifier of the driver */ + fwk_id_t driver_id; + + /*! Identifier of the driver API to bind to */ + fwk_id_t driver_api_id; +}; + +#endif /* MOD_OPTEE_MHU_H */ diff --git a/module/input_mhu/src/mod_input_mhu.c b/module/input_mhu/src/mod_input_mhu.c new file mode 100644 index 0000000000000000000000000000000000000000..02383da25e402d91de8964bb9fa4bece6049dde3 --- /dev/null +++ b/module/input_mhu/src/mod_input_mhu.c @@ -0,0 +1,449 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Description: + * Message Handling Unit (MHU) Device Driver. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +struct __attribute((packed)) mod_virtio_smt_memory { + uint32_t message_header; + uint32_t payload[]; +}; + +struct virt_msg { + char out_buf[128]; + int out_len; + char in_buf[128]; + int in_len; +}; + +struct mhu_smt_channel { + fwk_id_t id; + struct mod_msg_smt_driver_input_api *api; + + /* input message */ + struct virt_msg *msg; +}; + +/* MHU device context */ +struct mhu_device_ctx { + /* Channel configuration data */ + struct mod_input_mhu_channel_config *config; + + /* Number of slots (represented by sub-elements) */ + unsigned int slot_count; + + /* Table of SMT channels bound to the device */ + struct mhu_smt_channel *smt_channel_table; + +}; + +/* MHU context */ +struct mhu_ctx { + /* Table of device contexts */ + struct mhu_device_ctx *device_ctx_table; + + /* Number of devices in the device context table*/ + unsigned int device_count; +}; + +static struct mhu_ctx mhu_ctx; + +/* + * Input host helpers + */ + +static int kbd_simple_msg(int proto, int msg, int token, struct mod_virtio_smt_memory *memory) +{ + + memory->message_header = token << 18 | proto << 10 | msg; + return sizeof(memory->message_header); + +} + +static int kbd_simple_one(int proto, int msg, int token, int param0, struct mod_virtio_smt_memory *memory) +{ + int length; + + memory->message_header = token << 18 | proto << 10 | msg; + length = sizeof(memory->message_header); + memory->payload[0] = param0; + length += sizeof(memory->payload[0]); + + return length; + +} + +static int kbd_simple_two(int proto, int msg, int token, int param0, int param1, struct mod_virtio_smt_memory *memory) +{ + int length; + + memory->message_header = token << 18 | proto << 10 | msg; + length = sizeof(memory->message_header); + memory->payload[0] = param0; + length += sizeof(memory->payload[0]); + memory->payload[1] = param1; + length += sizeof(memory->payload[1]); + + return length; +} + +static int kbd_sensor_trip(int proto, int msg, int token, int param0, int param1, struct mod_virtio_smt_memory *memory) +{ + int length; + + memory->message_header = token << 18 | proto << 10 | msg; + length = sizeof(memory->message_header); + memory->payload[0] = param0; + length += sizeof(memory->payload[0]); + memory->payload[1] = 0x0 << 4 | 0x3; + length += sizeof(memory->payload[1]); + memory->payload[2] = (uint32_t)param1; + length += sizeof(memory->payload[2]); + memory->payload[3] = 0; + length += sizeof(memory->payload[3]); + + return length; +} + +static int kbd_set_message(char *str, struct mod_virtio_smt_memory *memory) +{ + int i; + unsigned int level; + + if (!strcmp(str,"version\n")) { + return kbd_simple_msg(0x10, 0x0, 0xAA, memory); + } else if (!strcmp(str,"base attributes\n")) { + return kbd_simple_msg(0x10, 0x1, 0xAA, memory); + } else if (!strcmp(str,"vendor\n")) { + return kbd_simple_msg(0x10, 0x3, 0xAA, memory); + } else if (!strcmp(str,"sub vendor\n")) { + return kbd_simple_msg(0x10, 0x4, 0xAA, memory); + } else if (!strcmp(str,"implementation\n")) { + return kbd_simple_msg(0x10, 0x5, 0xAA, memory); + } else if (!strcmp(str,"list\n")) { + return kbd_simple_one(0x10, 0x6, 0xAA, 0, memory); + } else if (!strcmp(str,"agent\n")) { + return kbd_simple_one(0x10, 0x6, 0xAA, 1, memory); + } else if (!strcmp(str,"clock version\n")) { + return kbd_simple_msg(0x14, 0x0, 0xCC, memory); + } else if (!strcmp(str,"clock attributes\n")) { + return kbd_simple_msg(0x14, 0x1, 0xCC, memory); + } else if (!strncmp(str,"clock attribute", 15 )) { + sscanf(str, "clock attribute %d", &i); + return kbd_simple_one(0x14, 0x3, 0xCC, i, memory); + } else if (!strncmp(str,"clock enable", 12 )) { + sscanf(str, "clock enable %d", &i); + return kbd_simple_two(0x14, 0x7, 0xcc, i, 1, memory); + } else if (!strncmp(str,"clock disable", 12 )) { + sscanf(str, "clock disable %d", &i); + return kbd_simple_two(0x14, 0x7, 0xcc, i, 0, memory); + } else if (!strcmp(str,"power version\n")) { + return kbd_simple_msg(0x11, 0x0, 0xBB, memory); + } else if (!strcmp(str,"power attributes\n")) { + return kbd_simple_msg(0x11, 0x1, 0xBB, memory); + } else if (!strncmp(str,"power attribute", 15 )) { + sscanf(str, "power attribute %d", &i); + return kbd_simple_one(0x11, 0x3, 0xBB, i, memory); + return 0; + } else if (!strncmp(str,"power enable", 12 )) { + sscanf(str, "power enable %d", &i); + return kbd_simple_two(0x11, 0x4, 0xBB, i, 1, memory); + } else if (!strncmp(str,"power disable", 12 )) { + sscanf(str, "power disable %d", &i); + return kbd_simple_two(0x11, 0x4, 0xBB, i, 0, memory); + } else if (!strncmp(str,"power notify", 12 )) { + sscanf(str, "power notify %d", &i); + return kbd_simple_two(0x11, 0x6, 0xBB, i, 1, memory); + } else if (!strcmp(str,"perf version\n")) { + return kbd_simple_msg(0x13, 0x0, 0xBB, memory); + } else if (!strcmp(str,"perf attributes\n")) { + return kbd_simple_msg(0x13, 0x1, 0xBB, memory); + } else if (!strncmp(str,"perf msg attributes", 19 )) { + sscanf(str, "perf msg attributes %d", &i); + return kbd_simple_one(0x13, 0x2, 0xBB, i, memory); + } else if (!strncmp(str,"perf domain attributes", 22 )) { + sscanf(str, "perf domain attributes %d", &i); + return kbd_simple_one(0x13, 0x3, 0xBB, i, memory); + } else if (!strncmp(str,"perf describe levels", 20 )) { + sscanf(str, "perf describe levels %d %u", &i, &level); + return kbd_simple_two(0x13, 0x4, 0xBB, i, level, memory); + } else if (!strncmp(str,"perf set", 8 )) { + sscanf(str, "perf set %d %u", &i, &level); + return kbd_simple_two(0x13, 0x7, 0xBB, i, level, memory); + } else if (!strncmp(str,"perf get", 8 )) { + sscanf(str, "perf get %d", &i); + return kbd_simple_one(0x13, 0x8, 0xBB, i, memory); + } else if (!strncmp(str,"perf notify level", 17 )) { + sscanf(str, "perf notify level %d", &i); + return kbd_simple_two(0x11, 0xA, 0xBB, i, 1, memory); + } else if (!strcmp(str,"sensor version\n")) { + return kbd_simple_msg(0x15, 0x0, 0xFF, memory); + } else if (!strcmp(str,"sensor attributes\n")) { + return kbd_simple_msg(0x15, 0x1, 0xFF, memory); + } else if (!strncmp(str,"sensor msg attributes", 21 )) { + sscanf(str, "sensor msg attributes %d", &i); + return kbd_simple_one(0x15, 0x2, 0xFF, i, memory); + } else if (!strncmp(str,"sensor description", 18 )) { + sscanf(str, "sensor description %d", &i); + return kbd_simple_one(0x15, 0x3, 0xFF, i, memory); + } else if (!strncmp(str,"sensor get", 10 )) { + sscanf(str, "sensor get %d", &i); + return kbd_simple_two(0x15, 0x6, 0xFF, i, 0, memory); + } else if (!strncmp(str,"sensor notify", 13 )) { + sscanf(str, "sensor notify %d", &i); + return kbd_simple_two(0x15, 0x4, 0xFF, i, 1, memory); + } else if (!strncmp(str,"sensor trip", 11 )) { + sscanf(str, "sensor trip %d %u", &i, &level); + return kbd_sensor_trip(0x15, 0x5, 0xFF, i, level, memory); + } + + return -1; +} + +void input_signal_message(struct mhu_device_ctx *device_ctx, unsigned int channel_idx, struct virt_msg *msg ) +{ + struct mhu_smt_channel *smt_channel; + + smt_channel = &device_ctx->smt_channel_table[channel_idx]; + smt_channel->msg = msg; + + smt_channel->api->signal_message(smt_channel->id, + msg->out_buf, + msg->out_len, + msg->in_buf, + msg->in_len); + + fwk_process_event_queue(); + + fwk_log_flush(); +} + +static gboolean input_handle_request( GIOChannel *channel, GIOCondition cond, gpointer data) +{ + gchar *str_return; + gsize length, terminator_pos; + GError *error = NULL; + struct virt_msg msg; + + if (g_io_channel_read_line( channel, &str_return, &length, &terminator_pos, &error) == G_IO_STATUS_ERROR) + g_warning("Something went wrong"); + + if (length == 0) + return TRUE; + + if (error != NULL) { + g_warning("Something went wrong"); + exit(1); + } + + msg.out_len = kbd_set_message(str_return, (struct mod_virtio_smt_memory *) &msg.out_buf); + msg.in_len = 128; + + if (msg.out_len > 0) + /* Input keyboard emulates 1st channel request */ + input_signal_message(&mhu_ctx.device_ctx_table[0], 0, &msg); + + g_free( str_return ); + return TRUE; +} + +static int input_init_channels(struct mhu_device_ctx *device_ctx) +{ + GError *error = NULL; + GIOChannel *channel = g_io_channel_unix_new( STDIN_FILENO ); + g_io_add_watch( channel, G_IO_IN, input_handle_request, NULL ); + g_io_channel_set_flags(channel, G_IO_FLAG_NONBLOCK, &error); + if (error != NULL) { + g_warning("Something went wrong"); + exit(1); + } + return FWK_SUCCESS; +} + +/* + * Mailbox module driver API + */ + +/* + * Provide a notify interface to the Mailbox driver + */ +static int raise_queue_notify(fwk_id_t channel_id, size_t size) +{ + /* There should be a message in the mailbox */ + return FWK_SUCCESS; +} + +const struct mod_msg_smt_driver_ouput_api vhost_mod_smt_driver_api = { + .raise_notification = raise_queue_notify, +}; + +/* + * Framework handlers + */ + +static int vhost_init(fwk_id_t module_id, unsigned int device_count, + const void *data) +{ + + if (device_count == 0) + return FWK_E_PARAM; + + mhu_ctx.device_ctx_table = fwk_mm_calloc(device_count, + sizeof(*mhu_ctx.device_ctx_table)); + if (mhu_ctx.device_ctx_table == NULL) + return FWK_E_NOMEM; + + mhu_ctx.device_count = device_count; + + return FWK_SUCCESS; +} + +static int vhost_device_init(fwk_id_t device_id, unsigned int slot_count, + const void *data) +{ + unsigned int slot; + size_t elt_idx = fwk_id_get_element_idx(device_id); + struct mhu_device_ctx *device_ctx = &mhu_ctx.device_ctx_table[elt_idx]; + struct mhu_smt_channel *smt_channel; + + device_ctx->config = (struct mod_input_mhu_channel_config*)data; + + device_ctx->smt_channel_table = fwk_mm_calloc(slot_count, + sizeof(device_ctx->smt_channel_table[0])); + + device_ctx->slot_count = slot_count; + + for (slot = 0; slot < device_ctx->slot_count; slot++) { + smt_channel = &device_ctx->smt_channel_table[slot]; + + smt_channel->id.value = 0; + } + + /* TBF: Use PENDING to request the creation of a context */ + return FWK_SUCCESS; +} + +static int vhost_bind(fwk_id_t id, unsigned int round) +{ + int status; + unsigned int slot; + struct mhu_device_ctx *device_ctx; + struct mhu_smt_channel *smt_channel; + + if (fwk_id_is_type(id, FWK_ID_TYPE_MODULE)) { + return FWK_SUCCESS; + } + + if (round == 1) { + + device_ctx = &mhu_ctx.device_ctx_table[fwk_id_get_element_idx(id)]; + + for (slot = 0; slot < device_ctx->slot_count; slot++) { + smt_channel = &device_ctx->smt_channel_table[slot]; + + if (smt_channel->id.value == 0) + continue; + + status = fwk_module_bind(smt_channel->id, + device_ctx->config->driver_api_id, + &smt_channel->api); + + if (status != FWK_SUCCESS) + return status; + } + } + + return FWK_SUCCESS; +} + +static int vhost_process_bind_request(fwk_id_t source_id, + fwk_id_t target_id, + fwk_id_t api_id, + const void **api) +{ + size_t elt_idx; + unsigned int slot; + struct mhu_device_ctx *device_ctx; + struct mhu_smt_channel *smt_channel; + + if (!fwk_id_is_type(target_id, FWK_ID_TYPE_SUB_ELEMENT)) + return FWK_E_ACCESS; + + if (fwk_id_get_api_idx(api_id) != 0) + return FWK_E_PARAM; + + elt_idx = fwk_id_get_element_idx(target_id); + if (elt_idx >= mhu_ctx.device_count) + return FWK_E_PARAM; + + device_ctx = &mhu_ctx.device_ctx_table[elt_idx]; + + slot = fwk_id_get_sub_element_idx(target_id); + if (slot >= device_ctx->slot_count) + return FWK_E_PARAM; + + smt_channel = &device_ctx->smt_channel_table[slot]; + + smt_channel->id = source_id; + *api = &vhost_mod_smt_driver_api; + + return FWK_SUCCESS; +} + +static int vhost_start(fwk_id_t id) +{ + + size_t elt_idx; + struct mhu_device_ctx *device_ctx; + + if (fwk_id_is_type(id, FWK_ID_TYPE_MODULE)) { + return FWK_SUCCESS; + } + + elt_idx = fwk_id_get_element_idx(id); + device_ctx = &mhu_ctx.device_ctx_table[elt_idx]; + + input_init_channels(device_ctx); + + return FWK_SUCCESS; +} + +/* OPTEE_MHU module definition */ +const struct fwk_module module_input_mhu = { + .type = FWK_MODULE_TYPE_DRIVER, + .api_count = 1, + .init = vhost_init, + .element_init = vhost_device_init, + .bind = vhost_bind, + .start = vhost_start, + .process_bind_request = vhost_process_bind_request, +}; diff --git a/module/msg_smt/CMakeLists.txt b/module/msg_smt/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..df2b57155591e762a520345428d0937c32b55993 --- /dev/null +++ b/module/msg_smt/CMakeLists.txt @@ -0,0 +1,16 @@ +# +# Arm SCP/MCP Software +# Copyright (c) 2022, 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") + +target_sources(${SCP_MODULE_TARGET} + PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/src/mod_msg_smt.c") + +target_link_libraries(${SCP_MODULE_TARGET} PRIVATE module-scmi) diff --git a/module/msg_smt/Module.cmake b/module/msg_smt/Module.cmake new file mode 100644 index 0000000000000000000000000000000000000000..a7066cb73444bcde1f86ebf7883cba828aca496d --- /dev/null +++ b/module/msg_smt/Module.cmake @@ -0,0 +1,9 @@ +# +# Arm SCP/MCP Software +# Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +set(SCP_MODULE "msg-smt") +set(SCP_MODULE_TARGET "module-msg-smt") diff --git a/module/msg_smt/include/mod_msg_smt.h b/module/msg_smt/include/mod_msg_smt.h new file mode 100644 index 0000000000000000000000000000000000000000..2fc08d549263be7f3a1872ae6910ff35cb123cec --- /dev/null +++ b/module/msg_smt/include/mod_msg_smt.h @@ -0,0 +1,100 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Description: + * msg buffer device driver. + */ + +#ifndef MOD_MSG_SMT_H +#define MOD_MSG_SMT_H + +#include +#include +#include + +/*! + * @} + */ + +/*! + * \brief Channel type + * + * \details Defines the role of an entity in a channel + */ +enum mod_msg_smt_channel_type { + /*! Requester channel */ + MOD_MSG_SMT_CHANNEL_TYPE_REQUESTER, + + /*! Completer channel */ + MOD_MSG_SMT_CHANNEL_TYPE_COMPLETER, + + /*! Channel type count */ + MOD_MSG_SMT_CHANNEL_TYPE_COUNT, +}; + +/*! + * \brief Channel config. + */ +struct mod_msg_smt_channel_config { + /*! Channel role (requester or completer) */ + enum mod_msg_smt_channel_type type; + + /*! Shared mailbox size in bytes */ + size_t mailbox_size; + + /*! Identifier of the driver */ + fwk_id_t driver_id; + + /*! Identifier of the driver API to bind to */ + fwk_id_t driver_api_id; +}; + +/*! + * \brief Driver input API (Implemented by SMT) + * + * \details Interface used for driver -> SMT communication. + */ +struct mod_msg_smt_driver_input_api { + /*! + * \brief Signal an incoming message in the mailbox + * + * \param device_id Channel identifier + * + * \retval FWK_SUCCESS The operation succeeded. + * \return One of the standard error codes for implementation-defined + * errors. + */ + int (*signal_message)(fwk_id_t channel_id, void *msg_in, size_t in_len, void *msg_out, size_t out_len); +}; + +/*! + * \brief Driver output API (Implemented by MHU) + * + * \details Interface used for SMT -> driver communication. + */ +struct mod_msg_smt_driver_ouput_api { + /*! + * \brief Signal an incoming message in the mailbox + * + * \param device_id Channel identifier + * + * \retval FWK_SUCCESS The operation succeeded. + * \return One of the standard error codes for implementation-defined + * errors. + */ + int (*raise_notification)(fwk_id_t channel_id, size_t size); +}; + +/*! + * \brief Type of the interfaces exposed by the power domain module. + */ +enum mod_msg_smt_api_idx { + MOD_MSG_SMT_API_IDX_SCMI_TRANSPORT, + MOD_MSG_SMT_API_IDX_DRIVER_INPUT, + MOD_MSG_SMT_API_IDX_COUNT, +}; + +#endif /* MOD_MSG_SMT_H */ diff --git a/module/msg_smt/src/mod_msg_smt.c b/module/msg_smt/src/mod_msg_smt.c new file mode 100644 index 0000000000000000000000000000000000000000..6b8ff4a7b9b65000092cf1f05b9efce3d47a4354 --- /dev/null +++ b/module/msg_smt/src/mod_msg_smt.c @@ -0,0 +1,477 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Description: + * msg buffer device driver. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct __attribute((packed)) mod_msg_smt_memory { + uint32_t message_header; + uint32_t payload[]; +}; + +struct smt_channel_ctx { + /* Channel identifier */ + fwk_id_t id; + + /* Channel configuration data */ + struct mod_msg_smt_channel_config *config; + + /* Channel read and write cache memory areas */ + struct mod_msg_smt_memory *in; + struct mod_msg_smt_memory *out; + size_t in_len; + size_t out_len; + + /* Message processing in progrees flag */ + volatile bool locked; + + /* Maximum payload size of the channel */ + size_t max_payload_size; + + /* Driver entity identifier */ + fwk_id_t driver_id; + + /* SCMI module service bound to the channel */ + fwk_id_t scmi_service_id; + + /* Driver API */ + struct mod_msg_smt_driver_ouput_api *driver_api; + + /* SCMI service API */ + struct mod_scmi_from_transport_api *scmi_api; + + /* Flag indicating the mailbox is ready */ + bool msg_smt_mailbox_ready; +}; + +struct smt_ctx { + /* Table of channel contexts */ + struct smt_channel_ctx *channel_ctx_table; + + /* Number of channels */ + unsigned int channel_count; +}; + +static struct smt_ctx smt_ctx; + +/* + * SCMI Transport API + */ +static int smt_get_secure(fwk_id_t channel_id, bool *secure) +{ + if (secure == NULL) { + assert(false); + return FWK_E_PARAM; + } + + /* No msg mailbox is considered secure */ + *secure = 0; + + return FWK_SUCCESS; +} + +static int smt_get_max_payload_size(fwk_id_t channel_id, size_t *size) +{ + struct smt_channel_ctx *channel_ctx; + + if (size == NULL) { + assert(false); + return FWK_E_PARAM; + } + + channel_ctx = + &smt_ctx.channel_ctx_table[fwk_id_get_element_idx(channel_id)]; + + *size = channel_ctx->max_payload_size; + + return FWK_SUCCESS; +} + +static int smt_get_message_header(fwk_id_t channel_id, uint32_t *header) +{ + struct smt_channel_ctx *channel_ctx; + + if (header == NULL) { + assert(false); + return FWK_E_PARAM; + } + + channel_ctx = + &smt_ctx.channel_ctx_table[fwk_id_get_element_idx(channel_id)]; + + if (!channel_ctx->locked) + return FWK_E_ACCESS; + + *header = channel_ctx->in->message_header; + + return FWK_SUCCESS; +} + +static int smt_get_payload(fwk_id_t channel_id, + const void **payload, + size_t *size) +{ + struct smt_channel_ctx *channel_ctx; + + if (payload == NULL) { + assert(false); + return FWK_E_PARAM; + } + + channel_ctx = + &smt_ctx.channel_ctx_table[fwk_id_get_element_idx(channel_id)]; + + if (!channel_ctx->locked) + return FWK_E_ACCESS; + + *payload = channel_ctx->in->payload; + + if (size != NULL) { + *size = channel_ctx->in_len - + sizeof(channel_ctx->in->message_header); + } + + return FWK_SUCCESS; +} + +static int smt_write_payload(fwk_id_t channel_id, + size_t offset, + const void *payload, + size_t size) +{ + struct smt_channel_ctx *channel_ctx; + + channel_ctx = + &smt_ctx.channel_ctx_table[fwk_id_get_element_idx(channel_id)]; + + if ((payload == NULL) || + (offset > channel_ctx->max_payload_size) || + (size > channel_ctx->max_payload_size) || + ((offset + size) > channel_ctx->max_payload_size)) { + + assert(false); + return FWK_E_PARAM; + } + + if (!channel_ctx->locked) + return FWK_E_ACCESS; + + memcpy(((uint8_t*)channel_ctx->out->payload) + offset, payload, size); + + return FWK_SUCCESS; +} + +static int smt_respond(fwk_id_t channel_id, const void *payload, size_t size) +{ + struct smt_channel_ctx *channel_ctx; + struct mod_msg_smt_memory *memory; + + channel_ctx = &smt_ctx.channel_ctx_table[fwk_id_get_element_idx(channel_id)]; + memory = ((struct mod_msg_smt_memory *) channel_ctx->out); + + /* Copy the payload from either the write buffer or the payload parameter */ + if (payload) { + memcpy(memory->payload, payload, size); + } + + channel_ctx->locked = false; + + channel_ctx->out_len = sizeof(memory->message_header) + size; + + channel_ctx->driver_api->raise_notification(channel_ctx->driver_id, channel_ctx->out_len); + + return FWK_SUCCESS; +} + +static int smt_transmit(fwk_id_t channel_id, uint32_t message_header, + const void *payload, size_t size, bool request_ack_by_interrupt) +{ + struct smt_channel_ctx *channel_ctx; + struct mod_msg_smt_memory *memory; + + if (payload == NULL) { + return FWK_E_DATA; + } + + channel_ctx = &smt_ctx.channel_ctx_table[fwk_id_get_element_idx(channel_id)]; + memory = ((struct mod_msg_smt_memory *) channel_ctx->out); + + if (!channel_ctx->locked) { + return FWK_SUCCESS; + } + + memory->message_header = message_header; + + /* Copy the payload */ + memcpy(memory->payload, payload, size); + + channel_ctx->out_len = sizeof(memory->message_header) + size; + + /* Release the channel */ + channel_ctx->locked = false; + + /* Notify the agent */ + channel_ctx->driver_api->raise_notification(channel_ctx->driver_id, channel_ctx->out_len); + + return FWK_SUCCESS; +} + +static const struct mod_scmi_to_transport_api smt_mod_scmi_to_transport_api = { + .get_secure = smt_get_secure, + .get_max_payload_size = smt_get_max_payload_size, + .get_message_header = smt_get_message_header, + .get_payload = smt_get_payload, + .write_payload = smt_write_payload, + .respond = smt_respond, + .transmit = smt_transmit, +}; + +/* + * Driver handler API + */ +static int smt_requester_handler(struct smt_channel_ctx *channel_ctx) +{ + int status; + + /* Commit to sending a response */ + channel_ctx->locked = true; + + /* Prepare answer and copy message header (Payload not copied) */ + channel_ctx->out->message_header = channel_ctx->in->message_header; + + /* Let SCMI handle the message */ + status = + channel_ctx->scmi_api->signal_message(channel_ctx->scmi_service_id); + if (status != FWK_SUCCESS) { + return FWK_E_HANDLER; + } + + return FWK_SUCCESS; +} + +static int smt_completer_handler(struct smt_channel_ctx *channel_ctx) +{ + /* Commit to sending a response */ + channel_ctx->locked = true; + + return FWK_SUCCESS; +} + +int msg_signal_message(fwk_id_t channel_id, void *msg_in, size_t in_len, void *msg_out, size_t out_len) +{ + struct smt_channel_ctx *channel_ctx; + + channel_ctx = + &smt_ctx.channel_ctx_table[fwk_id_get_element_idx(channel_id)]; + + if (!channel_ctx->msg_smt_mailbox_ready) { + /* Discard any message in the mailbox when not ready */ + FWK_LOG_ERR("[MSG_SMT] Message not valid\n"); + + return FWK_SUCCESS; + } + + /* Check if we are already processing */ + if (channel_ctx->locked) { + return FWK_E_STATE; + } + + /* Save input/output buffers */ + channel_ctx->in = (struct mod_msg_smt_memory *)msg_in ; + channel_ctx->in_len = in_len; + channel_ctx->out = (struct mod_msg_smt_memory *)msg_out; + channel_ctx->out_len = out_len; + + switch (channel_ctx->config->type) { + case MOD_MSG_SMT_CHANNEL_TYPE_REQUESTER: + return smt_requester_handler(channel_ctx); + case MOD_MSG_SMT_CHANNEL_TYPE_COMPLETER: + return smt_completer_handler(channel_ctx); + default: + /* Invalid config */ + assert(false); + break; + } + + return FWK_SUCCESS; +} + +static const struct mod_msg_smt_driver_input_api driver_input_api = { + .signal_message = msg_signal_message, +}; + +/* + * Framework API + */ +static int msg_init(fwk_id_t module_id, unsigned int element_count, + const void *data) +{ + + if (element_count == 0) { + return FWK_E_PARAM; + } + + smt_ctx.channel_ctx_table = fwk_mm_calloc(element_count, + sizeof(*smt_ctx.channel_ctx_table)); + if (smt_ctx.channel_ctx_table == NULL) { + return FWK_E_NOMEM; + } + + smt_ctx.channel_count = element_count; + + return FWK_SUCCESS; +} + +static int msg_channel_init(fwk_id_t channel_id, unsigned int slot_count, + const void *data) +{ + size_t elt_idx = fwk_id_get_element_idx(channel_id); + struct smt_channel_ctx *channel_ctx = &smt_ctx.channel_ctx_table[elt_idx]; + + channel_ctx->config = (struct mod_msg_smt_channel_config*)data; + + /* Validate channel config */ + if (channel_ctx->config->type >= MOD_MSG_SMT_CHANNEL_TYPE_COUNT) { + assert(false); + return FWK_E_DATA; + } + + channel_ctx->in = NULL; + channel_ctx->in_len = 0; + channel_ctx->out = NULL; + channel_ctx->out_len = 0; + + channel_ctx->max_payload_size = channel_ctx->config->mailbox_size - + sizeof(struct mod_msg_smt_memory); + + channel_ctx->msg_smt_mailbox_ready = true; + + return FWK_SUCCESS; +} + +static int msg_bind(fwk_id_t id, unsigned int round) +{ + int status; + struct smt_channel_ctx *channel_ctx; + + if (fwk_id_is_type(id, FWK_ID_TYPE_MODULE)) { + return FWK_SUCCESS; + } + + channel_ctx = &smt_ctx.channel_ctx_table[fwk_id_get_element_idx(id)]; + + if (round == 0) { + + status = fwk_module_bind(channel_ctx->config->driver_id, + channel_ctx->config->driver_api_id, + &channel_ctx->driver_api); + if (status != FWK_SUCCESS) { + return status; + } + + channel_ctx->driver_id = channel_ctx->config->driver_id; + + } else if (round == 1) { + + status = fwk_module_bind(channel_ctx->scmi_service_id, + FWK_ID_API(FWK_MODULE_IDX_SCMI, MOD_SCMI_API_IDX_TRANSPORT), + &channel_ctx->scmi_api); + if (status != FWK_SUCCESS) { + return status; + } + } + + return FWK_SUCCESS; +} + +static int msg_process_bind_request(fwk_id_t source_id, + fwk_id_t target_id, + fwk_id_t api_id, + const void **api) +{ + struct smt_channel_ctx *channel_ctx = NULL; + size_t elt_idx; + + /* Only bind to a channel (not the whole module) */ + if (!fwk_id_is_type(target_id, FWK_ID_TYPE_ELEMENT)) { + return FWK_E_ACCESS; + } + + elt_idx = fwk_id_get_element_idx(target_id); + if (elt_idx >= smt_ctx.channel_count) { + return FWK_E_ACCESS; + } + + channel_ctx = &smt_ctx.channel_ctx_table[elt_idx]; + + switch (fwk_id_get_api_idx(api_id)) { + case MOD_MSG_SMT_API_IDX_DRIVER_INPUT: + /* Driver input API */ + + /* + * Make sure that the element that is trying to bind to us is the + * same element that we previously bound to. + * + * NOTE: We bound to an element but a sub-element should be binding + * back to us. This means we cannot use fwk_id_is_equal() because + * the ids have different types. For now we compare the indicies + * manually. + */ + if (fwk_id_get_module_idx(channel_ctx->driver_id) == + fwk_id_get_module_idx(source_id) && + fwk_id_get_element_idx(channel_ctx->driver_id) == + fwk_id_get_element_idx(source_id)) { + *api = &driver_input_api; + } else { + /* A module that we did not bind to is trying to bind to us */ + assert(false); + return FWK_E_ACCESS; + } + break; + + case MOD_MSG_SMT_API_IDX_SCMI_TRANSPORT: + /* SCMI transport API */ + *api = &smt_mod_scmi_to_transport_api; + channel_ctx->scmi_service_id = source_id; + break; + + default: + /* Invalid API */ + assert(false); + return FWK_E_PARAM; + } + + return FWK_SUCCESS; +} + +static int msg_start(fwk_id_t id) +{ + return FWK_SUCCESS; +} + +const struct fwk_module module_msg_smt = { + .type = FWK_MODULE_TYPE_SERVICE, + .api_count = MOD_MSG_SMT_API_IDX_COUNT, + .init = msg_init, + .element_init = msg_channel_init, + .bind = msg_bind, + .start = msg_start, + .process_bind_request = msg_process_bind_request, +}; diff --git a/module/optee/clock/CMakeLists.txt b/module/optee/clock/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..3525e92cb7e20ab69eae91dfd54c15c4c1ff9215 --- /dev/null +++ b/module/optee/clock/CMakeLists.txt @@ -0,0 +1,17 @@ +# +# Arm SCP/MCP Software +# Copyright (c) 2022, 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") + +target_sources(${SCP_MODULE_TARGET} + PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/src/mod_optee_clock.c") + +target_link_libraries(${SCP_MODULE_TARGET} + PRIVATE module-clock) diff --git a/module/optee/clock/Module.cmake b/module/optee/clock/Module.cmake new file mode 100644 index 0000000000000000000000000000000000000000..202c98e229c2f3da2ca9fc7d9f8f0217caa02b05 --- /dev/null +++ b/module/optee/clock/Module.cmake @@ -0,0 +1,9 @@ +# +# Arm SCP/MCP Software +# Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +set(SCP_MODULE "optee-clock") +set(SCP_MODULE_TARGET "module-optee-clock") diff --git a/module/optee/clock/include/mod_optee_clock.h b/module/optee/clock/include/mod_optee_clock.h new file mode 100644 index 0000000000000000000000000000000000000000..03570045be1a5182ff628f9065c531f389254bef --- /dev/null +++ b/module/optee/clock/include/mod_optee_clock.h @@ -0,0 +1,31 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MOD_OPTEE_CLOCK_H +#define MOD_OPTEE_CLOCK_H + +#include +#include + +#include + +#include +#include + +/*! + * \brief Platform clocks configuration. + */ +struct mod_optee_clock_config { + /*! Clock name */ + const char *name; + /*! Optee clock reference */ + struct clk *clk; + /*! default state of the clock */ + bool default_enabled; +}; + +#endif /* MOD_OPTEE_CLOCK_H */ diff --git a/module/optee/clock/src/mod_optee_clock.c b/module/optee/clock/src/mod_optee_clock.c new file mode 100644 index 0000000000000000000000000000000000000000..a5693919c0266cfeb34d988e46e4fb3edc2bcecd --- /dev/null +++ b/module/optee/clock/src/mod_optee_clock.c @@ -0,0 +1,349 @@ +/* + * 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 + +/* OP-TEE clock device context */ +struct optee_clock_dev_ctx { + struct clk *clk; + bool enabled; +}; + +/* OP-TEE clock module context */ +struct optee_clock_module_ctx { + struct optee_clock_dev_ctx *dev_ctx; + unsigned int dev_count; +}; + +static struct optee_clock_module_ctx module_ctx; + +static struct optee_clock_dev_ctx *elt_id_to_ctx(fwk_id_t dev_id) +{ + if (!fwk_module_is_valid_element_id(dev_id)) { + return NULL; + } + + return module_ctx.dev_ctx + fwk_id_get_element_idx(dev_id); +} + +static bool is_exposed(struct optee_clock_dev_ctx *ctx) +{ + return ctx->clk != NULL; +} + +/* + * Clock driver API functions + */ +static int get_rate(fwk_id_t dev_id, uint64_t *rate) +{ + struct optee_clock_dev_ctx *ctx = elt_id_to_ctx(dev_id); + + if ((ctx == NULL) || (rate == NULL)) { + return FWK_E_PARAM; + } + + if (!is_exposed(ctx)) { + *rate = 0; + return FWK_SUCCESS; + } + + *rate = clk_get_rate(ctx->clk); + + FMSG("SCMI optee_clock (%u/\"%s\"): clk_get_rate() = %"PRIu64, + fwk_id_get_element_idx(dev_id), clk_get_name(ctx->clk), *rate); + + return FWK_SUCCESS; +} + +static int set_state(fwk_id_t dev_id, enum mod_clock_state state) +{ + struct optee_clock_dev_ctx *ctx = elt_id_to_ctx(dev_id); + + if (ctx == NULL) { + return FWK_E_PARAM; + } + + switch (state) { + case MOD_CLOCK_STATE_STOPPED: + case MOD_CLOCK_STATE_RUNNING: + break; + default: + return FWK_E_PARAM; + } + + if (!is_exposed(ctx)) { + if (state == MOD_CLOCK_STATE_STOPPED) { + return FWK_SUCCESS; + } else { + return FWK_E_ACCESS; + } + } + + if (state == MOD_CLOCK_STATE_STOPPED) { + if (ctx->enabled) { + FMSG("SCMI optee_clock (%u/\"%s\") disable", + fwk_id_get_element_idx(dev_id), clk_get_name(ctx->clk)); + + clk_disable(ctx->clk); + ctx->enabled = false; + } else { + FMSG("SCMI optee_clock (%u/\"%s\") is already OFF", + fwk_id_get_element_idx(dev_id), clk_get_name(ctx->clk)); + } + } else { + if (!ctx->enabled) { + FMSG("SCMI optee_clock (%u/\"%s\") enable", + fwk_id_get_element_idx(dev_id), clk_get_name(ctx->clk)); + + clk_enable(ctx->clk); + ctx->enabled = true; + } else { + FMSG("SCMI optee_clock (%u/\"%s\") is already ON", + fwk_id_get_element_idx(dev_id), clk_get_name(ctx->clk)); + } + } + + return FWK_SUCCESS; +} + +static int get_state(fwk_id_t dev_id, enum mod_clock_state *state) +{ + struct optee_clock_dev_ctx *ctx = elt_id_to_ctx(dev_id); + + if ((ctx == NULL) || (state == NULL)) { + return FWK_E_PARAM; + } + + if (!is_exposed(ctx)) { + *state = MOD_CLOCK_STATE_STOPPED; + return FWK_SUCCESS; + } + + if (ctx->enabled) { + *state = MOD_CLOCK_STATE_RUNNING; + } else { + *state = MOD_CLOCK_STATE_STOPPED; + } + + FMSG("SCMI optee_clock (%u/\"%s\") is %s", + fwk_id_get_element_idx(dev_id), clk_get_name(ctx->clk), + *state == MOD_CLOCK_STATE_STOPPED ? "off" : "on"); + + return FWK_SUCCESS; +} + +static int get_range(fwk_id_t dev_id, struct mod_clock_range *range) +{ + struct optee_clock_dev_ctx *ctx = elt_id_to_ctx(dev_id); + unsigned long rate; + size_t rate_count; + size_t rate_idx; + TEE_Result res; + + if ((ctx == NULL) || (range == NULL)) { + return FWK_E_PARAM; + } + + range->rate_type = MOD_CLOCK_RATE_TYPE_DISCRETE; + + if (!is_exposed(ctx)) { + range->min = 0; + range->max = 0; + range->rate_count = 1; + + return FWK_SUCCESS; + } + + 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; + + return FWK_SUCCESS; + } + + range->rate_type = MOD_CLOCK_RATE_TYPE_DISCRETE; + range->rate_count = rate_count; + range->min = UINT64_MAX; + range->max = 0; + + for (rate_idx = 0; rate_idx < rate_count; rate_idx++) { + size_t count = 1; + + res = clk_get_rates_array(ctx->clk, rate_idx, &rate, &count); + assert(!res && count == 1); + + if (rate > range->max) { + range->max = rate; + } else if (rate < range->min) { + range->min = rate; + } + } + + return FWK_SUCCESS; +} + +static int set_rate(fwk_id_t dev_id, uint64_t rate, + enum mod_clock_round_mode round_mode) +{ + struct optee_clock_dev_ctx *ctx = elt_id_to_ctx(dev_id); + TEE_Result res; + + if (ctx == NULL) { + return FWK_E_PARAM; + } + + if (!is_exposed(ctx)) { + return FWK_E_ACCESS; + } + + res = clk_set_rate(ctx->clk, rate); + if (res == TEE_ERROR_NOT_SUPPORTED) { + return FWK_E_SUPPORT; + } + + FMSG("SCMI optee_clock (%u/\"%s\"): rate = %"PRIu64, + fwk_id_get_element_idx(dev_id), clk_get_name(ctx->clk), rate); + + return FWK_SUCCESS; +} + +static int get_rate_from_index(fwk_id_t dev_id, + unsigned int rate_index, uint64_t *rate) +{ + struct optee_clock_dev_ctx *ctx = elt_id_to_ctx(dev_id); + unsigned long rate_ul; + size_t rate_count; + TEE_Result res; + + if ((ctx == NULL) || (rate == NULL)) { + return FWK_E_PARAM; + } + + if (!is_exposed(ctx)) { + *rate = 0; + return FWK_SUCCESS; + } + + res = clk_get_rates_array(ctx->clk, 0, NULL, &rate_count); + if (res == TEE_ERROR_NOT_SUPPORTED) { + if (rate_index > 0) { + return FWK_E_PARAM; + } + + *rate = clk_get_rate(ctx->clk); + return FWK_SUCCESS; + } + + if (rate_index > rate_count) { + return FWK_E_PARAM; + } + + rate_count = 1; + res = clk_get_rates_array(ctx->clk, rate_index, &rate_ul, &rate_count); + assert(!res && rate_count == 1); + *rate = rate_ul; + + FMSG("SCMI optee_clock (%u/\"%s\"): rate(index %u) = %lu", + fwk_id_get_element_idx(dev_id), clk_get_name(ctx->clk), rate_index, + rate_ul); + + return FWK_SUCCESS; +} + +static int stub_process_power_transition(fwk_id_t dev_id, unsigned int state) +{ + return FWK_E_SUPPORT; +} + +static int stub_pending_power_transition(fwk_id_t dev_id, + unsigned int current_state, + unsigned int next_state) +{ + return FWK_E_SUPPORT; +} + +static const struct mod_clock_drv_api api_optee_clock = { + .get_rate = get_rate, + .set_state = set_state, + .get_state = get_state, + .get_range = get_range, + .get_rate_from_index = get_rate_from_index, + .set_rate = set_rate, + /* Not supported */ + .process_power_transition = stub_process_power_transition, + .process_pending_power_transition = stub_pending_power_transition, +}; + +/* + * Framework handler functions + */ + +static int optee_clock_init(fwk_id_t module_id, unsigned int count, + const void *data) +{ + if (count == 0) { + return FWK_SUCCESS; + } + + module_ctx.dev_count = count; + module_ctx.dev_ctx = fwk_mm_calloc(count, sizeof(*module_ctx.dev_ctx)); + + return FWK_SUCCESS; +} + +static int optee_clock_element_init(fwk_id_t element_id, unsigned int dev_count, + const void *data) +{ + struct optee_clock_dev_ctx *ctx = elt_id_to_ctx(element_id); + const struct mod_optee_clock_config *config = data; + TEE_Result res; + + ctx->clk = config->clk; + if (ctx->clk) { + ctx->enabled = config->default_enabled; + + if (ctx->enabled) { + res = clk_enable(ctx->clk); + if (res) { + return FWK_E_DEVICE; + } + } + } + + return FWK_SUCCESS; +} + +static int optee_clock_process_bind_request(fwk_id_t requester_id, fwk_id_t id, + fwk_id_t api_type, const void **api) +{ + *api = &api_optee_clock; + + return FWK_SUCCESS; +} + +const struct fwk_module module_optee_clock = { + .type = FWK_MODULE_TYPE_DRIVER, + .api_count = 1, + .event_count = 0, + .init = optee_clock_init, + .element_init = optee_clock_element_init, + .process_bind_request = optee_clock_process_bind_request, +}; diff --git a/module/optee/console/CMakeLists.txt b/module/optee/console/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..aebb7cc797667174980696bc8e0719154e04ce18 --- /dev/null +++ b/module/optee/console/CMakeLists.txt @@ -0,0 +1,23 @@ +# +# Arm SCP/MCP Software +# Copyright (c) 2022, 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") +# These include directories are relative to SCP-firmware submodule position in +# optee-os tree +# Those includes are needed for mutex definitnion that is used in optee_smt +# notification +target_include_directories(${SCP_MODULE_TARGET} + PUBLIC "${SCP_OPTEE_DIR}/core/arch/arm/include/" + "${SCP_OPTEE_DIR}/core/include/" + "${SCP_OPTEE_DIR}/lib/libutils/ext/include/" + "${SCP_OPTEE_DIR}/lib/libutee/include/") + +target_sources(${SCP_MODULE_TARGET} + PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/src/mod_optee_console.c") diff --git a/module/optee/console/Module.cmake b/module/optee/console/Module.cmake new file mode 100644 index 0000000000000000000000000000000000000000..d64eda60140ed161a70ba7a1baa567b63d92c572 --- /dev/null +++ b/module/optee/console/Module.cmake @@ -0,0 +1,9 @@ +# +# Arm SCP/MCP Software +# Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +set(SCP_MODULE "optee-console") +set(SCP_MODULE_TARGET "module-optee-console") diff --git a/module/optee/console/src/mod_optee_console.c b/module/optee/console/src/mod_optee_console.c new file mode 100644 index 0000000000000000000000000000000000000000..2d229bfb2ae2ad1bb65f3e7c931a03e110632e5e --- /dev/null +++ b/module/optee/console/src/mod_optee_console.c @@ -0,0 +1,86 @@ +/* + * 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 + +static int mod_console_init( + fwk_id_t module_id, + unsigned int element_count, + const void *data) +{ + return FWK_SUCCESS; +} + +static int mod_console_element_init( + fwk_id_t element_id, + unsigned int unused, + const void *data) +{ + return FWK_SUCCESS; +} + + +static int mod_console_io_open(const struct fwk_io_stream *stream) +{ + return FWK_SUCCESS; +} + +static int mod_console_io_getch( + const struct fwk_io_stream *restrict stream, + char *restrict ch) +{ + *ch = 'A'; + + return FWK_SUCCESS; +} + +static int mod_console_io_putch(const struct fwk_io_stream *stream, char ch) +{ + console_putc(ch); + return FWK_SUCCESS; +} + +static int mod_console_close(const struct fwk_io_stream *stream) +{ + return FWK_SUCCESS; +} + +const struct fwk_module module_optee_console = { + .type = FWK_MODULE_TYPE_DRIVER, + + .init = mod_console_init, + .element_init = mod_console_element_init, + + .adapter = + (struct fwk_io_adapter){ + .open = mod_console_io_open, + .getch = mod_console_io_getch, + .putch = mod_console_io_putch, + .close = mod_console_close, + }, +}; + +struct fwk_module_config config_optee_console = { + .elements = FWK_MODULE_STATIC_ELEMENTS({ + [0] = { + .name = "printf", + .data = (void *)1 + }, + [1] = { 0 }, + }), +}; diff --git a/module/optee/mhu/CMakeLists.txt b/module/optee/mhu/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..fb6c8d01718c55c2a58c923a8bc476f5b63936b6 --- /dev/null +++ b/module/optee/mhu/CMakeLists.txt @@ -0,0 +1,29 @@ +# +# Arm SCP/MCP Software +# Copyright (c) 2022, 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") + +# These include directories are relative to SCP-firmware submodule position in +# optee-os tree +# Those includes are needed for mutex defifitnion that is used in optee_smt +# notification +target_include_directories(${SCP_MODULE_TARGET} + PUBLIC "${SCP_OPTEE_DIR}/core/arch/arm/include/" + "${SCP_OPTEE_DIR}/core/include/" + "${SCP_OPTEE_DIR}/lib/libutils/ext/include/" + "${SCP_OPTEE_DIR}/lib/libutee/include/") + +target_link_libraries(${SCP_MODULE_TARGET} + PRIVATE module-optee-smt + module-msg-smt + module-scmi) + +target_sources(${SCP_MODULE_TARGET} + PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/src/mod_optee_mhu.c") diff --git a/module/optee/mhu/Module.cmake b/module/optee/mhu/Module.cmake new file mode 100644 index 0000000000000000000000000000000000000000..a0b180e3e5d2f2abc6429a39efc0b1ff5dabeb12 --- /dev/null +++ b/module/optee/mhu/Module.cmake @@ -0,0 +1,9 @@ +# +# Arm SCP/MCP Software +# Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +set(SCP_MODULE "optee-mhu") +set(SCP_MODULE_TARGET "module-optee-mhu") diff --git a/module/optee/mhu/include/mod_optee_mhu.h b/module/optee/mhu/include/mod_optee_mhu.h new file mode 100644 index 0000000000000000000000000000000000000000..3ad7dabb6cc337a32907b8bfaba3c47bbd912c94 --- /dev/null +++ b/module/optee/mhu/include/mod_optee_mhu.h @@ -0,0 +1,65 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Description: + * OP-TEE mailbox buffer layer + */ + +#ifndef MOD_OPTEE_MHU_H +#define MOD_OPTEE_MHU_H + +/* OPTEE_MHU currently uses a static shared memory buffer size */ +#define OPTEE_MHU_SHMEM_SIZE 128 + +/*! + * \brief Channel type + * + * \details Defines the role of an entity in a channel + */ +enum mod_optee_mhu_channel_type { + /*! Requester channel */ + MOD_OPTEE_MHU_CHANNEL_TYPE_REQUESTER, + + /*! Completer channel */ + MOD_OPTEE_MHU_CHANNEL_TYPE_COMPLETER, + + /*! Channel type count */ + MOD_OPTEE_MHU_CHANNEL_TYPE_COUNT, +}; + +/*! + * \brief Channel config. + */ +struct mod_optee_mhu_channel_config { + /*! Channel role (requester or completer) */ + enum mod_optee_mhu_channel_type type; + + /*! Identifier of the driver */ + fwk_id_t driver_id; + + /*! Identifier of the driver API to bind to */ + fwk_id_t driver_api_id; +}; + +/*! + * \brief Interface to exchange message with OP-TEE + */ + +/* Return number of MHU device registered in the paltform */ +int optee_mhu_get_devices_count(void); + +/* Retrun framwork ID related to MHU device identifed by @id */ +fwk_id_t optee_mhu_get_device(unsigned int id); + +/* Signal an incoming SCMI message in SMT device memory mailbox */ +void optee_mhu_signal_smt_message(fwk_id_t device_id); + +/* Signal an incoming SCMI message in a MSG OP-TEE shared memory mailbox */ +void optee_mhu_signal_msg_message(fwk_id_t device_id, + void *in_buf, size_t in_size, + void *out_buf, size_t *out_size); + +#endif /* MOD_OPTEE_MHU_H */ diff --git a/module/optee/mhu/src/mod_optee_mhu.c b/module/optee/mhu/src/mod_optee_mhu.c new file mode 100644 index 0000000000000000000000000000000000000000..a48e290b293f95a5b2f56992e1387e5efaffd31f --- /dev/null +++ b/module/optee/mhu/src/mod_optee_mhu.c @@ -0,0 +1,298 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Description: + * Message Handling Unit (MHU) Device Driver. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +/* MHU device context */ +struct mhu_device_ctx { + /* Channel configuration data */ + struct mod_optee_mhu_channel_config *config; + + fwk_id_t shmem_id; + + union { + struct mod_optee_smt_driver_input_api *smt; + struct mod_msg_smt_driver_input_api *msg; + } shmem_api; + + size_t *shm_out_size; + + struct mutex lock; +}; + +/* MHU context */ +struct mhu_ctx { + /* Table of device contexts */ + struct mhu_device_ctx *device_ctx_table; + + /* Number of devices in the device context table*/ + unsigned int device_count; +}; + +static struct mhu_ctx mhu_ctx; + +#if BUILD_HAS_MOD_OPTEE_SMT +void optee_mhu_signal_smt_message(fwk_id_t device_id) +{ + struct mhu_device_ctx *device_ctx; + unsigned int device_idx = fwk_id_get_element_idx(device_id); + + if (device_idx < mhu_ctx.device_count) { + fwk_assert(fwk_id_get_module_idx(device_ctx->shmem_id) == + FWK_MODULE_IDX_OPTEE_SMT); + + device_ctx = &mhu_ctx.device_ctx_table[device_idx]; + + /* Lock the channel until the message has been processed */ + if (device_ctx->config->type == MOD_OPTEE_MHU_CHANNEL_TYPE_REQUESTER) { + mutex_lock(&device_ctx->lock); + } + + device_ctx->shmem_api.smt->signal_message(device_ctx->shmem_id); + + if (device_ctx->config->type == MOD_OPTEE_MHU_CHANNEL_TYPE_COMPLETER) { + /* Wait until notification is ready */ + mutex_lock(&device_ctx->lock); + } + } else { + fwk_unexpected(); + } +} +#endif + +#if BUILD_HAS_MOD_MSG_SMT +void optee_mhu_signal_msg_message(fwk_id_t device_id, void *in_buf, + size_t in_size, void *out_buf, + size_t *out_size) +{ + struct mhu_device_ctx *device_ctx; + unsigned int device_idx = fwk_id_get_element_idx(device_id); + + if (device_idx < mhu_ctx.device_count) { + device_ctx = &mhu_ctx.device_ctx_table[device_idx]; + + fwk_assert(fwk_id_get_module_idx(device_ctx->shmem_id) == + FWK_MODULE_IDX_MSG_SMT); + + + /* Lock the channel until the message has been processed */ + if (device_ctx->config->type == MOD_OPTEE_MHU_CHANNEL_TYPE_REQUESTER) { + mutex_lock(&device_ctx->lock); + } + + device_ctx->shm_out_size = out_size; + device_ctx->shmem_api.msg->signal_message(device_ctx->shmem_id, + in_buf, in_size, + out_buf, *out_size); + + if (device_ctx->config->type == MOD_OPTEE_MHU_CHANNEL_TYPE_COMPLETER) { + /* Wait until notification is ready */ + mutex_lock(&device_ctx->lock); + } + } else { + fwk_unexpected(); + } +} +#endif + +int optee_mhu_get_devices_count(void) +{ + return mhu_ctx.device_count; +} + +fwk_id_t optee_mhu_get_device(unsigned int id) +{ + if (id >= mhu_ctx.device_count) + return (fwk_id_t)FWK_ID_NONE_INIT; + + return (fwk_id_t)FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_OPTEE_MHU, id); +} + +/* + * Mailbox module driver API + */ + +/* + * Provide a raise interrupt interface to the Mailbox driver + */ +static int raise_smt_interrupt(fwk_id_t channel_id) +{ + size_t idx = fwk_id_get_element_idx(channel_id); + struct mhu_device_ctx *channel_ctx = &mhu_ctx.device_ctx_table[idx]; + + /* Release the channel as the message has been processed */ + mutex_unlock(&channel_ctx->lock); + + /* There should be a message in the mailbox */ + return FWK_SUCCESS; +} + +const struct mod_optee_smt_driver_api mhu_smt_api = { + .raise_interrupt = raise_smt_interrupt, +}; + +static int raise_shm_notification(fwk_id_t channel_id, size_t size) +{ + size_t idx = fwk_id_get_element_idx(channel_id); + struct mhu_device_ctx *channel_ctx = &mhu_ctx.device_ctx_table[idx]; + + *channel_ctx->shm_out_size = size; + + /* Release the channel as the message has been processed */ + mutex_unlock(&channel_ctx->lock); + + return FWK_SUCCESS; +} + +const struct mod_msg_smt_driver_ouput_api mhu_shm_api = { + .raise_notification = raise_shm_notification, +}; + +/* + * Framework handlers + */ + +static int mhu_init(fwk_id_t module_id, unsigned int device_count, + const void *data) +{ + + if (device_count == 0) + return FWK_E_PARAM; + + mhu_ctx.device_ctx_table = fwk_mm_calloc(device_count, + sizeof(*mhu_ctx.device_ctx_table)); + if (mhu_ctx.device_ctx_table == NULL) { + return FWK_E_NOMEM; + } + + mhu_ctx.device_count = device_count; + + return FWK_SUCCESS; +} + +static int mhu_device_init(fwk_id_t device_id, unsigned int slot_count, + const void *data) +{ + size_t elt_idx = fwk_id_get_element_idx(device_id); + struct mhu_device_ctx *device_ctx = &mhu_ctx.device_ctx_table[elt_idx]; + + device_ctx->config = (struct mod_optee_mhu_channel_config*)data; + + /* Validate channel config */ + if (device_ctx->config->type >= MOD_OPTEE_MHU_CHANNEL_TYPE_COUNT) { + assert(false); + return FWK_E_DATA; + } + + mutex_init(&device_ctx->lock); + if (device_ctx->config->type == MOD_OPTEE_MHU_CHANNEL_TYPE_COMPLETER) { + /* lock the notification message */ + mutex_lock(&device_ctx->lock); + } + + /* + * Request the creation of an execution context for the device so we can + * paralellize unrelated request. + */ + return FWK_INIT_CTX; +} + +static int mhu_bind(fwk_id_t id, unsigned int round) +{ + int status; + struct mhu_device_ctx *device_ctx; + + if (fwk_id_is_type(id, FWK_ID_TYPE_MODULE)) { + return FWK_SUCCESS; + } + + if (round == 1) { + device_ctx = &mhu_ctx.device_ctx_table[fwk_id_get_element_idx(id)]; + + status = fwk_module_bind(device_ctx->config->driver_id, + device_ctx->config->driver_api_id, + &device_ctx->shmem_api); + if (status != FWK_SUCCESS) { + return status; + } + + device_ctx->shmem_id = device_ctx->config->driver_id; + } + + return FWK_SUCCESS; +} + +static int mhu_process_bind_request(fwk_id_t source_id, + fwk_id_t target_id, + fwk_id_t api_id, + const void **api) +{ + size_t elt_idx; + + if (!fwk_id_is_type(target_id, FWK_ID_TYPE_ELEMENT)) { + return FWK_E_ACCESS; + } + + if (fwk_id_get_api_idx(api_id) != 0) { + return FWK_E_PARAM; + } + + elt_idx = fwk_id_get_element_idx(target_id); + if (elt_idx >= mhu_ctx.device_count) { + return FWK_E_PARAM; + } + + switch (fwk_id_get_module_idx(source_id)) { +#if BUILD_HAS_MOD_OPTEE_SMT + case FWK_MODULE_IDX_OPTEE_SMT: + *api = &mhu_smt_api; + break; +#endif +#if BUILD_HAS_MOD_MSG_SMT + case FWK_MODULE_IDX_MSG_SMT: + *api = &mhu_shm_api; + break; +#endif + default: + return FWK_E_PANIC; + } + + return FWK_SUCCESS; +} + +static int mhu_start(fwk_id_t id) +{ + return FWK_SUCCESS; +} + +/* OPTEE_MHU module definition */ +const struct fwk_module module_optee_mhu = { + .type = FWK_MODULE_TYPE_DRIVER, + .api_count = 1, + .init = mhu_init, + .element_init = mhu_device_init, + .bind = mhu_bind, + .start = mhu_start, + .process_bind_request = mhu_process_bind_request, +}; diff --git a/module/optee/reset/CMakeLists.txt b/module/optee/reset/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..112fd5c280e28eeb2a9e09216cb6d4b9fe1964be --- /dev/null +++ b/module/optee/reset/CMakeLists.txt @@ -0,0 +1,17 @@ +# +# Arm SCP/MCP Software +# Copyright (c) 2022, 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") + +target_sources(${SCP_MODULE_TARGET} + PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/src/mod_optee_reset.c") + +target_link_libraries(${SCP_MODULE_TARGET} + PRIVATE module-reset-domain) diff --git a/module/optee/reset/Module.cmake b/module/optee/reset/Module.cmake new file mode 100644 index 0000000000000000000000000000000000000000..1699fb332db9915e31168bbf164bbfb337920e86 --- /dev/null +++ b/module/optee/reset/Module.cmake @@ -0,0 +1,9 @@ +# +# Arm SCP/MCP Software +# Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +set(SCP_MODULE "optee-reset") +set(SCP_MODULE_TARGET "module-optee-reset") diff --git a/module/optee/reset/include/mod_optee_reset.h b/module/optee/reset/include/mod_optee_reset.h new file mode 100644 index 0000000000000000000000000000000000000000..10f962083073b39899c9c8a1e3c51e9bbb5c21b2 --- /dev/null +++ b/module/optee/reset/include/mod_optee_reset.h @@ -0,0 +1,21 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MOD_OPTEE_RESET_H +#define MOD_OPTEE_RESET_H + +/*! + * \brief Platform reset domain configuration. + */ +struct mod_optee_reset_dev_config { + /*! Optee reset reference */ + struct rstctrl *rstctrl; + /*! Reset line name */ + const char *name; +}; + +#endif /* MOD_OPTEE_RESET_H */ diff --git a/module/optee/reset/src/mod_optee_reset.c b/module/optee/reset/src/mod_optee_reset.c new file mode 100644 index 0000000000000000000000000000000000000000..14f23adbce465fb12a0d39ae95bacee27d1b6403 --- /dev/null +++ b/module/optee/reset/src/mod_optee_reset.c @@ -0,0 +1,156 @@ +/* + * 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 + +#define TIMEOUT_US_1MS 1000 + +/* Device context */ +struct optee_reset_dev_ctx { + struct rstctrl *rstctrl; +}; + +/* Module context */ +struct optee_reset_ctx { + struct optee_reset_dev_ctx *dev_ctx_table; + unsigned int dev_count; +}; + +static struct optee_reset_ctx module_ctx; + +static bool is_exposed(struct optee_reset_dev_ctx *ctx) +{ + return ctx->rstctrl != NULL; +} + +/* + * Driver API functions + */ +static int reset_set_state(fwk_id_t dev_id, enum mod_reset_domain_mode mode, + uint32_t reset_state, uintptr_t cookie) +{ + struct optee_reset_dev_ctx *ctx = NULL; + int status = FWK_SUCCESS; + + 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 (!is_exposed(ctx)) { + return FWK_E_ACCESS; + } + + /* Whatever the reset_state set, we consider a unique context loss mode */ + if (reset_state) + DMSG("Override requested SCMI reset state %#"PRIx32, reset_state); + + switch (mode) { + case MOD_RESET_DOMAIN_MODE_EXPLICIT_ASSERT: + FMSG("SCMI reset %u: assert(%s)", + fwk_id_get_element_idx(dev_id), rstctrl_name(ctx->rstctrl)); + + if (rstctrl_assert(ctx->rstctrl)) { + status = FWK_E_DEVICE; + } + break; + case MOD_RESET_DOMAIN_MODE_EXPLICIT_DEASSERT: + FMSG("SCMI reset %u: deassert(%s)", + fwk_id_get_element_idx(dev_id), rstctrl_name(ctx->rstctrl)); + + if (rstctrl_deassert(ctx->rstctrl)) { + status = FWK_E_DEVICE; + } + break; + case MOD_RESET_DOMAIN_AUTO_RESET: + FMSG("SCMI reset %u: cycle(%s)", + fwk_id_get_element_idx(dev_id), rstctrl_name(ctx->rstctrl)); + + if (rstctrl_assert_to(ctx->rstctrl, TIMEOUT_US_1MS)) { + status = FWK_E_TIMEOUT; + } + if (rstctrl_deassert_to(ctx->rstctrl, TIMEOUT_US_1MS)) { + status = FWK_E_TIMEOUT; + } + break; + default: + return FWK_E_PARAM; + } + + return status; +} + +static const struct mod_reset_domain_drv_api api_optee_reset = { + .set_reset_state = reset_set_state, +}; + +/* + * Framework handler functions + */ + +static int optee_reset_init(fwk_id_t module_id, unsigned int element_count, + const void *data) +{ + module_ctx.dev_count = element_count; + + if (element_count == 0) { + return FWK_SUCCESS; + } + + module_ctx.dev_ctx_table = fwk_mm_calloc(element_count, + sizeof(struct optee_reset_dev_ctx)); + + return FWK_SUCCESS; +} + +static int optee_reset_element_init(fwk_id_t element_id, + unsigned int unused __unused, + const void *data) +{ + struct optee_reset_dev_ctx *ctx = NULL; + const struct mod_optee_reset_dev_config *config = NULL; + + 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)]; + config = (const struct mod_optee_reset_dev_config *)data; + + ctx->rstctrl = config->rstctrl; + + return FWK_SUCCESS; +} + +static int optee_reset_process_bind_request(fwk_id_t requester_id, fwk_id_t id, + fwk_id_t api_type, const void **api) +{ + *api = &api_optee_reset; + + return FWK_SUCCESS; +} + +const struct fwk_module module_optee_reset = { + .type = FWK_MODULE_TYPE_DRIVER, + .api_count = 1, + .init = optee_reset_init, + .element_init = optee_reset_element_init, + .process_bind_request = optee_reset_process_bind_request, +}; diff --git a/module/optee/smt/CMakeLists.txt b/module/optee/smt/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..3b7d2374a8b406106c57c02c266502a42fbe7ee4 --- /dev/null +++ b/module/optee/smt/CMakeLists.txt @@ -0,0 +1,16 @@ +# +# Arm SCP/MCP Software +# Copyright (c) 2022, 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") + +target_sources(${SCP_MODULE_TARGET} + PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/src/mod_optee_smt.c") + +target_link_libraries(${SCP_MODULE_TARGET} PRIVATE module-scmi) diff --git a/module/optee/smt/Module.cmake b/module/optee/smt/Module.cmake new file mode 100644 index 0000000000000000000000000000000000000000..46f7c1c2a08e9bc3616a0ffa27ed6f8587677143 --- /dev/null +++ b/module/optee/smt/Module.cmake @@ -0,0 +1,9 @@ +# +# Arm SCP/MCP Software +# Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +set(SCP_MODULE "optee-smt") +set(SCP_MODULE_TARGET "module-optee-smt") diff --git a/module/optee/smt/include/internal/optee_smt.h b/module/optee/smt/include/internal/optee_smt.h new file mode 100644 index 0000000000000000000000000000000000000000..6ee18dde0827db2d63713bfdb761db9be55f2b22 --- /dev/null +++ b/module/optee/smt/include/internal/optee_smt.h @@ -0,0 +1,43 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef INTERNAL_OPTEE_SMT_H +#define INTERNAL_OPTEE_SMT_H + +#include + +struct __attribute((packed)) mod_optee_smt_memory { + uint32_t reserved0; + uint32_t status; + uint64_t reserved1; + uint32_t flags; + uint32_t length; /* message_header + payload */ + uint32_t message_header; + uint32_t payload[]; +}; + +#define MOD_OPTEE_SMT_MAX_CHANNELS 8 + +#define MOD_OPTEE_SMT_MAILBOX_STATUS_FREE_POS 0 +#define MOD_OPTEE_SMT_MAILBOX_STATUS_FREE_MASK \ + (UINT32_C(0x1) << MOD_OPTEE_SMT_MAILBOX_STATUS_FREE_POS) + +#define MOD_OPTEE_SMT_MAILBOX_STATUS_ERROR_POS 1 +#define MOD_OPTEE_SMT_MAILBOX_STATUS_ERROR_MASK \ + (UINT32_C(0x1) << MOD_OPTEE_SMT_MAILBOX_STATUS_ERROR_POS) + +#define MOD_OPTEE_SMT_MAILBOX_FLAGS_IENABLED_POS 0 +#define MOD_OPTEE_SMT_MAILBOX_FLAGS_IENABLED_MASK \ + (UINT32_C(0x1) << MOD_OPTEE_SMT_MAILBOX_FLAGS_IENABLED_POS) + +#define MOD_OPTEE_SMT_MIN_PAYLOAD_SIZE \ + sizeof(((struct mod_optee_smt_memory *)NULL)->payload[0]) + +#define MOD_OPTEE_SMT_MIN_MAILBOX_SIZE \ + (sizeof(struct mod_optee_smt_memory) + MOD_OPTEE_SMT_MIN_PAYLOAD_SIZE) + +#endif /* INTERNAL_OPTEE_SMT_H */ diff --git a/module/optee/smt/include/mod_optee_smt.h b/module/optee/smt/include/mod_optee_smt.h new file mode 100644 index 0000000000000000000000000000000000000000..26dcd9eb734bb4e91ae6eede634a1272ef72059f --- /dev/null +++ b/module/optee/smt/include/mod_optee_smt.h @@ -0,0 +1,122 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MOD_OPTEE_SMT_H +#define MOD_OPTEE_SMT_H + +#include +#include + +#include +#include + +/*! + * \name Channel policies + * + * \details These policies define attributes that affect how the channel is + * treated by the SMT component. + * + * \{ + */ + +/*! No policies */ +#define MOD_SMT_POLICY_NONE 0 + +/*! This channel is secure */ +#define MOD_SMT_POLICY_SECURE (1U << 0) + +/*! The mailbox for this channel requires initialization */ +#define MOD_SMT_POLICY_INIT_MAILBOX (1U << 1) + +/*! + * \} + */ + +/*! + * \brief Channel type + * + * \details Defines the role of an entity in a channel + */ +enum mod_optee_smt_channel_type { + /*! Requester channel */ + MOD_OPTEE_SMT_CHANNEL_TYPE_REQUESTER, + + /*! Completer channel */ + MOD_OPTEE_SMT_CHANNEL_TYPE_COMPLETER, + + /*! Channel type count */ + MOD_OPTEE_SMT_CHANNEL_TYPE_COUNT, +}; + +/*! + * \brief Channel config. + */ +struct mod_optee_smt_channel_config { + /*! Channel role (requester or completer) */ + enum mod_optee_smt_channel_type type; + + /*! Channel policies */ + uint32_t policies; + + /*! Shared mailbox address */ + uintptr_t mailbox_address; + + /*! Shared mailbox size in bytes */ + size_t mailbox_size; + + /*! Identifier of the driver */ + fwk_id_t driver_id; + + /*! Identifier of the driver API to bind to */ + fwk_id_t driver_api_id; +}; + +/*! + * \brief Driver API + */ +struct mod_optee_smt_driver_api { + /*! + * \brief Raise an interrupt on the receiver + * + * \param device_id Device identifier + * + * \retval ::FWK_SUCCESS The operation succeeded + * \retval ::FWK_E_PARAM The device_id parameter is invalid + * \return One of the standard error codes for implementation-defined + * errors + */ + int (*raise_interrupt)(fwk_id_t device_id); +}; + +/*! + * \brief Driver input API (Implemented by SMT) + * + * \details Interface used for driver -> SMT communication. + */ +struct mod_optee_smt_driver_input_api { + /*! + * \brief Signal an incoming message in the mailbox + * + * \param device_id Channel identifier + * + * \retval ::FWK_SUCCESS The operation succeeded. + * \return One of the standard error codes for implementation-defined + * errors. + */ + int (*signal_message)(fwk_id_t channel_id); +}; + +/*! + * \brief Type of the interfaces exposed by the power domain module. + */ +enum mod_optee_smt_api_idx { + MOD_OPTEE_SMT_API_IDX_DRIVER_INPUT, + MOD_OPTEE_SMT_API_IDX_SCMI_TRANSPORT, + MOD_OPTEE_SMT_API_IDX_COUNT, +}; + +#endif /* MOD_OPTEE_SMT_H */ diff --git a/module/optee/smt/src/mod_optee_smt.c b/module/optee/smt/src/mod_optee_smt.c new file mode 100644 index 0000000000000000000000000000000000000000..35cc3234422e84a445e0e17281794a879a16bd9b --- /dev/null +++ b/module/optee/smt/src/mod_optee_smt.c @@ -0,0 +1,546 @@ +/* + * 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 + +struct smt_channel_ctx { + /* Channel identifier */ + fwk_id_t id; + + /* Channel configuration data */ + struct mod_optee_smt_channel_config *config; + + /* Channel mailbox virtual address */ + uintptr_t mailbox_va; + + /* Channel read and write cache memory areas */ + struct mod_optee_smt_memory *in, *out; + + /* Message processing in progrees flag */ + volatile bool locked; + + /* Maximum payload size of the channel */ + size_t max_payload_size; + + /* Driver entity identifier */ + fwk_id_t driver_id; + + /* SCMI module service bound to the channel */ + fwk_id_t scmi_service_id; + + /* Driver API */ + struct mod_optee_smt_driver_api *driver_api; + + /* SCMI service API */ + struct mod_scmi_from_transport_api *scmi_api; + + /* Flag indicating the mailbox is ready */ + bool optee_smt_mailbox_ready; +}; + +struct mod_smt_ctx { + /* Table of channel contexts */ + struct smt_channel_ctx *channel_ctx_table; + + /* Number of channels */ + unsigned int channel_count; +}; + +static struct mod_smt_ctx smt_ctx; + +/* + * SCMI Transport API + */ +static int smt_get_secure(fwk_id_t channel_id, bool *secure) +{ + struct smt_channel_ctx *channel_ctx; + + if (secure == NULL) { + fwk_unexpected(); + return FWK_E_PARAM; + } + + channel_ctx = + &smt_ctx.channel_ctx_table[fwk_id_get_element_idx(channel_id)]; + + *secure = + ((channel_ctx->config->policies & MOD_SMT_POLICY_SECURE) != + (uint32_t)0); + + return FWK_SUCCESS; +} + +static int smt_get_max_payload_size(fwk_id_t channel_id, size_t *size) +{ + struct smt_channel_ctx *channel_ctx; + + if (size == NULL) { + fwk_unexpected(); + return FWK_E_PARAM; + } + + channel_ctx = + &smt_ctx.channel_ctx_table[fwk_id_get_element_idx(channel_id)]; + + *size = channel_ctx->max_payload_size; + + return FWK_SUCCESS; +} + +static int smt_get_message_header(fwk_id_t channel_id, uint32_t *header) +{ + struct smt_channel_ctx *channel_ctx; + + if (header == NULL) { + fwk_unexpected(); + return FWK_E_PARAM; + } + + channel_ctx = + &smt_ctx.channel_ctx_table[fwk_id_get_element_idx(channel_id)]; + + if (!channel_ctx->locked) { + return FWK_E_ACCESS; + } + + *header = channel_ctx->in->message_header; + + return FWK_SUCCESS; +} + +static int smt_get_payload(fwk_id_t channel_id, + const void **payload, + size_t *size) +{ + struct smt_channel_ctx *channel_ctx; + + if (payload == NULL) { + fwk_unexpected(); + return FWK_E_PARAM; + } + + channel_ctx = + &smt_ctx.channel_ctx_table[fwk_id_get_element_idx(channel_id)]; + + if (!channel_ctx->locked) { + return FWK_E_ACCESS; + } + + *payload = channel_ctx->in->payload; + + if (size != NULL) { + *size = channel_ctx->in->length - + sizeof(channel_ctx->in->message_header); + } + + return FWK_SUCCESS; +} + +static int smt_write_payload(fwk_id_t channel_id, + size_t offset, + const void *payload, + size_t size) +{ + struct smt_channel_ctx *channel_ctx; + + channel_ctx = + &smt_ctx.channel_ctx_table[fwk_id_get_element_idx(channel_id)]; + + if ((payload == NULL) || + (offset > channel_ctx->max_payload_size) || + (size > channel_ctx->max_payload_size) || + ((offset + size) > channel_ctx->max_payload_size)) { + fwk_unexpected(); + return FWK_E_PARAM; + } + + if (!channel_ctx->locked) { + return FWK_E_ACCESS; + } + + fwk_str_memcpy( + ((uint8_t *)channel_ctx->out->payload) + offset, payload, size); + + return FWK_SUCCESS; +} + +static int smt_respond(fwk_id_t channel_id, const void *payload, size_t size) +{ + struct smt_channel_ctx *channel_ctx; + struct mod_optee_smt_memory *memory; + + channel_ctx = &smt_ctx.channel_ctx_table[fwk_id_get_element_idx(channel_id)]; + memory = (struct mod_optee_smt_memory *)channel_ctx->mailbox_va; + + /* Copy the header from the write buffer */ + *memory = *channel_ctx->out; + + /* Copy the payload from either the write buffer or the payload parameter */ + fwk_str_memcpy( + memory->payload, + (payload == NULL ? channel_ctx->out->payload : payload), + size); + + channel_ctx->locked = false; + + memory->length = sizeof(memory->message_header) + size; + memory->status |= MOD_OPTEE_SMT_MAILBOX_STATUS_FREE_MASK; + + channel_ctx->driver_api->raise_interrupt(channel_ctx->driver_id); + + return FWK_SUCCESS; +} + +static int smt_transmit(fwk_id_t channel_id, uint32_t message_header, + const void *payload, size_t size, bool request_ack_by_interrupt) +{ + struct smt_channel_ctx *channel_ctx; + struct mod_optee_smt_memory *memory; + + if (payload == NULL) { + return FWK_E_DATA; + } + + channel_ctx = &smt_ctx.channel_ctx_table[fwk_id_get_element_idx(channel_id)]; + memory = (struct mod_optee_smt_memory *)channel_ctx->mailbox_va; + + if (!channel_ctx->locked) { + return FWK_SUCCESS; + } + + memory->message_header = message_header; + + /* + * we do not want the agent to send an interrupt when it receives + * the message. + */ + memory->flags = 0; + + /* Copy the payload */ + fwk_str_memcpy(memory->payload, payload, size); + + memory->length = sizeof(memory->message_header) + size; + memory->status &= ~MOD_OPTEE_SMT_MAILBOX_STATUS_FREE_MASK; + + /* Release the channel */ + channel_ctx->locked = false; + + /* Notify the agent */ + channel_ctx->driver_api->raise_interrupt(channel_ctx->driver_id); + + return FWK_SUCCESS; +} + +static const struct mod_scmi_to_transport_api smt_mod_scmi_to_transport_api = { + .get_secure = smt_get_secure, + .get_max_payload_size = smt_get_max_payload_size, + .get_message_header = smt_get_message_header, + .get_payload = smt_get_payload, + .write_payload = smt_write_payload, + .respond = smt_respond, + .transmit = smt_transmit, +}; + +/* + * Driver handler API + */ +static int smt_requester_handler(struct smt_channel_ctx *channel_ctx) +{ + struct mod_optee_smt_memory *memory; + struct mod_optee_smt_memory *in; + struct mod_optee_smt_memory *out; + size_t payload_size; + int status; + + /* Commit to sending a response */ + channel_ctx->locked = true; + + memory = (struct mod_optee_smt_memory *)channel_ctx->mailbox_va; + + in = channel_ctx->in; + out = channel_ctx->out; + + /* Mirror mailbox contents in read and write buffers (Payload not copied) */ + *in = *memory; + *out = *memory; + + /* Ensure error bit is not set */ + out->status &= ~MOD_OPTEE_SMT_MAILBOX_STATUS_ERROR_MASK; + + /* + * Verify: + * 1. The length is at least as large as the message header + * 2. The length, minus the size of the message header, is less than or + * equal to the maximum payload size + * + * Note: the payload size is permitted to be of size zero. + */ + if ((in->length < sizeof(in->message_header)) || + ((in->length - sizeof(in->message_header)) + > channel_ctx->max_payload_size)) { + + out->status |= MOD_OPTEE_SMT_MAILBOX_STATUS_ERROR_MASK; + return smt_respond(channel_ctx->id, + &(int32_t){ SCMI_PROTOCOL_ERROR }, + sizeof(int32_t)); + } + + /* Copy payload from shared memory to read buffer */ + payload_size = in->length - sizeof(in->message_header); + fwk_str_memcpy(in->payload, memory->payload, payload_size); + + /* Let SCMI handle the message */ + status = + channel_ctx->scmi_api->signal_message(channel_ctx->scmi_service_id); + if (status != FWK_SUCCESS) { + return FWK_E_HANDLER; + } + + return FWK_SUCCESS; +} + +static int smt_completer_handler(struct smt_channel_ctx *channel_ctx) +{ + /* Commit to sending a response */ + channel_ctx->locked = true; + + return FWK_SUCCESS; +} + +static int smt_signal_message(fwk_id_t channel_id) +{ + struct smt_channel_ctx *channel_ctx; + + channel_ctx = + &smt_ctx.channel_ctx_table[fwk_id_get_element_idx(channel_id)]; + + if (!channel_ctx->optee_smt_mailbox_ready) { + /* Discard any message in the mailbox when not ready */ + FWK_LOG_ERR("[OPTEE_SMT] Message not valid\n"); + + return FWK_SUCCESS; + } + + /* Check if we are already processing */ + if (channel_ctx->locked) { + return FWK_E_STATE; + } + + switch (channel_ctx->config->type) { + case MOD_OPTEE_SMT_CHANNEL_TYPE_COMPLETER: + return smt_completer_handler(channel_ctx); + case MOD_OPTEE_SMT_CHANNEL_TYPE_REQUESTER: + return smt_requester_handler(channel_ctx); + default: + /* Invalid config */ + fwk_unexpected(); + break; + } + + return FWK_SUCCESS; +} + +static const struct mod_optee_smt_driver_input_api driver_input_api = { + .signal_message = smt_signal_message, +}; + +/* + * Framework API + */ +static int mailbox_init(fwk_id_t module_id, unsigned int element_count, + const void *data) +{ + + if (element_count == 0) { + return FWK_E_PARAM; + } + + smt_ctx.channel_ctx_table = + fwk_mm_calloc(element_count, sizeof(*smt_ctx.channel_ctx_table)); + + if (smt_ctx.channel_ctx_table == NULL) { + return FWK_E_NOMEM; + } + + smt_ctx.channel_count = element_count; + + return FWK_SUCCESS; +} + +static int mailbox_channel_init(fwk_id_t channel_id, unsigned int slot_count, + const void *data) +{ + size_t elt_idx = fwk_id_get_element_idx(channel_id); + struct smt_channel_ctx *channel_ctx = &smt_ctx.channel_ctx_table[elt_idx]; + struct mod_optee_smt_channel_config *config; + struct mod_optee_smt_memory *memory; + + config = (struct mod_optee_smt_channel_config*)data; + + /* Validate channel config */ + if ((config->type >= MOD_OPTEE_SMT_CHANNEL_TYPE_COUNT) || + (config->mailbox_address == 0) || (config->mailbox_size == 0)) { + fwk_unexpected(); + return FWK_E_DATA; + } + + channel_ctx->mailbox_va = smt_phys_to_virt(config->mailbox_address, + config->mailbox_size, + config->policies & + MOD_SMT_POLICY_SECURE); + if (channel_ctx->mailbox_va == 0) { + fwk_unexpected(); + return FWK_E_DATA; + } + + channel_ctx->id = channel_id; + channel_ctx->in = fwk_mm_alloc(1, config->mailbox_size); + channel_ctx->out = fwk_mm_alloc(1, config->mailbox_size); + + channel_ctx->max_payload_size = config->mailbox_size - + sizeof(struct mod_optee_smt_memory); + + memory = (struct mod_optee_smt_memory *)channel_ctx->mailbox_va; + memory->status = MOD_OPTEE_SMT_MAILBOX_STATUS_FREE_MASK; + + channel_ctx->config = config; + channel_ctx->optee_smt_mailbox_ready = true; + + return FWK_SUCCESS; +} + +static int mailbox_smt_bind(fwk_id_t id, unsigned int round) +{ + int status; + struct smt_channel_ctx *channel_ctx; + + if (fwk_id_is_type(id, FWK_ID_TYPE_MODULE)) { + return FWK_SUCCESS; + } + + channel_ctx = &smt_ctx.channel_ctx_table[fwk_id_get_element_idx(id)]; + + if (round == 0) { + + status = fwk_module_bind(channel_ctx->config->driver_id, + channel_ctx->config->driver_api_id, + &channel_ctx->driver_api); + if (status != FWK_SUCCESS) { + return status; + } + + channel_ctx->driver_id = channel_ctx->config->driver_id; + + } else if (round == 1) { + + status = fwk_module_bind(channel_ctx->scmi_service_id, + FWK_ID_API(FWK_MODULE_IDX_SCMI, + MOD_SCMI_API_IDX_TRANSPORT), + &channel_ctx->scmi_api); + if (status != FWK_SUCCESS) { + return status; + } + } + + return FWK_SUCCESS; +} + +static int mailbox_smt_process_bind_request(fwk_id_t source_id, + fwk_id_t target_id, + fwk_id_t api_id, + const void **api) +{ + struct smt_channel_ctx *channel_ctx = NULL; + size_t elt_idx; + + /* Only bind to a channel (not the whole module) */ + if (!fwk_id_is_type(target_id, FWK_ID_TYPE_ELEMENT)) { + /* Tried to bind to something other than a specific channel */ + fwk_unexpected(); + return FWK_E_PARAM; + } + + elt_idx = fwk_id_get_element_idx(target_id); + if (elt_idx >= smt_ctx.channel_count) { + return FWK_E_ACCESS; + } + + channel_ctx = &smt_ctx.channel_ctx_table[elt_idx]; + + switch (fwk_id_get_api_idx(api_id)) { + case MOD_OPTEE_SMT_API_IDX_DRIVER_INPUT: + /* Driver input API */ + + /* + * Make sure that the element that is trying to bind to us is the + * same element that we previously bound to. + * + * NOTE: We bound to an element but a sub-element should be binding + * back to us. This means we cannot use fwk_id_is_equal() because + * the ids have different types. For now we compare the indicies + * manually. + */ + if (fwk_id_get_module_idx(channel_ctx->driver_id) == + fwk_id_get_module_idx(source_id) && + fwk_id_get_element_idx(channel_ctx->driver_id) == + fwk_id_get_element_idx(source_id)) { + + /* Ids are equal */ + *api = &driver_input_api; + } else { + /* A module that we did not bind to is trying to bind to us */ + fwk_unexpected(); + return FWK_E_ACCESS; + } + break; + + case MOD_OPTEE_SMT_API_IDX_SCMI_TRANSPORT: + /* SCMI transport API */ + *api = &smt_mod_scmi_to_transport_api; + channel_ctx->scmi_service_id = source_id; + break; + + default: + /* Invalid API */ + fwk_unexpected(); + return FWK_E_PARAM; + } + + return FWK_SUCCESS; +} + +static int mailbox_start(fwk_id_t id) +{ + return FWK_SUCCESS; +} + +const struct fwk_module module_optee_smt = { + .type = FWK_MODULE_TYPE_SERVICE, + .api_count = MOD_OPTEE_SMT_API_IDX_COUNT, + .init = mailbox_init, + .element_init = mailbox_channel_init, + .bind = mailbox_smt_bind, + .start = mailbox_start, + .process_bind_request = mailbox_smt_process_bind_request, +}; diff --git a/module/vhost_mhu/CMakeLists.txt b/module/vhost_mhu/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..82d2673760c05f3bf04a351c70dfc0d5dfd62270 --- /dev/null +++ b/module/vhost_mhu/CMakeLists.txt @@ -0,0 +1,34 @@ +# +# Arm SCP/MCP Software +# Copyright (c) 2022, 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") + + +if(SCP_ARCHITECTURE_TARGET STREQUAL "arch-none") + find_package(PkgConfig REQUIRED) + pkg_check_modules(deps REQUIRED IMPORTED_TARGET glib-2.0 gio-unix-2.0) + target_link_libraries(${SCP_MODULE_TARGET} PRIVATE PkgConfig::deps) + + target_include_directories(${SCP_MODULE_TARGET} + PRIVATE "/home/vingu/Tools/Dev/qemu/") + + add_library( lib-vhost-user STATIC IMPORTED ) + set_target_properties( lib-vhost-user PROPERTIES IMPORTED_LOCATION /usr/local/lib/libvhost-user.a) + target_link_libraries(${SCP_MODULE_TARGET} PRIVATE lib-vhost-user) + + add_library( lib-vhost-user-glib STATIC IMPORTED ) + set_target_properties( lib-vhost-user-glib PROPERTIES IMPORTED_LOCATION /usr/local/lib/libvhost-user-glib.a) + target_link_libraries(${SCP_MODULE_TARGET} PRIVATE lib-vhost-user-glib) +endif() + +target_link_libraries(${SCP_MODULE_TARGET} PRIVATE module-msg-smt) + +target_sources(${SCP_MODULE_TARGET} + PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/src/mod_vhost_mhu.c") diff --git a/module/vhost_mhu/Module.cmake b/module/vhost_mhu/Module.cmake new file mode 100644 index 0000000000000000000000000000000000000000..96c6bcb71e1de0f9e906d7062d9683363bb5893a --- /dev/null +++ b/module/vhost_mhu/Module.cmake @@ -0,0 +1,9 @@ +# +# Arm SCP/MCP Software +# Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +set(SCP_MODULE "vhost-mhu") +set(SCP_MODULE_TARGET "module-vhost-mhu") diff --git a/module/vhost_mhu/include/mod_vhost_mhu.h b/module/vhost_mhu/include/mod_vhost_mhu.h new file mode 100644 index 0000000000000000000000000000000000000000..a9dc18ee18a1e67b7f9b9fea4eb3a7024c89b088 --- /dev/null +++ b/module/vhost_mhu/include/mod_vhost_mhu.h @@ -0,0 +1,28 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Description: + * vhost user based transport channel Device Driver. + */ + +#ifndef MOD_VHOST_MHU_H +#define MOD_VHOST_MHU_H + +/*! + * \brief Channel config. + */ +struct mod_vhost_mhu_channel_config { + /*! Identifier of the driver */ + fwk_id_t driver_id; + + /*! Identifier of the driver API to bind to */ + fwk_id_t driver_api_id; + + /*! Socket path for vhost user device protocol */ + const char *socket_path; +}; + +#endif /* MOD_OPTEE_MHU_H */ diff --git a/module/vhost_mhu/src/mod_vhost_mhu.c b/module/vhost_mhu/src/mod_vhost_mhu.c new file mode 100644 index 0000000000000000000000000000000000000000..599025be1e7f8997ad6f17afc0251f48133505d4 --- /dev/null +++ b/module/vhost_mhu/src/mod_vhost_mhu.c @@ -0,0 +1,468 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Description: + * vhost user based transport channel Device Driver. + */ + +#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 "subprojects/libvhost-user/libvhost-user-glib.h" +#include "subprojects/libvhost-user/libvhost-user.h" + +struct iovec { + void *iov_base; + size_t iov_len; +}; + +struct mhu_smt_channel { + fwk_id_t id; + struct mod_msg_smt_driver_input_api *api; + + /* vhost user message */ + VuVirtqElement *elem; +}; + +/* MHU device context */ +struct mhu_device_ctx { + /* Vhost user inteface */ + VugDev dev; + GSocket *socket; + GThread *thread; + + /* Channel configuration data */ + struct mod_vhost_mhu_channel_config *config; + + /* Number of slots (represented by sub-elements) */ + unsigned int slot_count; + + /* Table of SMT channels bound to the device */ + struct mhu_smt_channel *smt_channel_table; +}; + +/* MHU context */ +struct mhu_ctx { + /* Table of device contexts */ + struct mhu_device_ctx *device_ctx_table; + + /* Number of devices in the device context table*/ + unsigned int device_count; +}; + +static struct mhu_ctx mhu_ctx; + +/* + * Virtio vhost helpers + */ +/* Device implements some SCMI notifications, or delayed responses. */ +#define VIRTIO_SCMI_F_P2A_CHANNELS 0 + +/* Definitions from virtio-scmi specifications */ +#define VHOST_USER_SCMI_MAX_QUEUES 2 + +/* vhost-user-scmi definitions */ +#ifndef container_of +#define container_of(ptr, type, member) ({ \ + const typeof(((type *) 0)->member) *__mptr = (ptr); \ + (type *) ((char *) __mptr - offsetof(type, member));}) +#endif + +static uint64_t vscmi_get_features(VuDev *dev) +{ + uint64_t features = 1ull << VIRTIO_SCMI_F_P2A_CHANNELS; + + return features; +} + +static void vscmi_set_features(VuDev *dev, uint64_t features) +{ + if (features) { + g_autoptr(GString) s = g_string_new("Requested un-handled feature"); + g_string_append_printf(s, " 0x%" PRIx64 "", features); + g_debug("%s: %s", __func__, s->str); + } +} + +void vhost_signal_message(struct mhu_device_ctx *device_ctx, unsigned int channel_idx, VuVirtqElement *elem) +{ + struct mhu_smt_channel *smt_channel; + + smt_channel = &device_ctx->smt_channel_table[channel_idx]; + smt_channel->elem = elem; + + smt_channel->api->signal_message(smt_channel->id, + elem->out_sg[0].iov_base, + elem->out_sg[0].iov_len, + elem->in_sg[0].iov_base, + elem->in_sg[0].iov_len); + + fwk_process_event_queue(); + + fwk_log_flush(); +} + +static void vscmi_handle_request_ctrl(VuDev *dev, int qidx) +{ + struct mhu_device_ctx *device_ctx = container_of(dev, struct mhu_device_ctx, dev.parent); + + VuVirtq *vq = vu_get_queue(dev, qidx); + + for (;;) { + VuVirtqElement *elem; + + elem = vu_queue_pop(dev, vq, sizeof(VuVirtqElement)); + if (!elem) { + break; + } + + g_debug("%s: %s:%d got queue (in %d, out %d)", __func__, device_ctx->config->socket_path, qidx, elem->in_num, + elem->out_num); + + vhost_signal_message(device_ctx, qidx, elem); + } +} + +void vscmi_host_user_notification(VuDev *dev, VuVirtqElement *elem, int qidx, size_t in_hdr_len) +{ + VuVirtq *vq = vu_get_queue(dev, qidx); + + vu_queue_push(dev, vq, elem, in_hdr_len); + + vu_queue_notify(dev, vq); +} + +static void +vscmi_queue_set_started(VuDev *dev, int qidx, bool started) +{ + VuVirtq *vq = vu_get_queue(dev, qidx); + + g_debug("%s: idx %d started %d", __func__, qidx, started); + + vu_set_queue_handler(dev, vq, started ? vscmi_handle_request_ctrl : NULL); +} + +static void vscmi_panic(VuDev *dev, const char *msg) +{ + g_critical("%s\n", msg); + exit(EXIT_FAILURE); +} + +static int vscmi_init_channels(struct mhu_device_ctx *device_ctx); + +static gpointer server_wait_vm_thread(gpointer data) +{ + struct mhu_device_ctx *device_ctx = (struct mhu_device_ctx *)data; + + vscmi_init_channels(device_ctx); + + return NULL; +} + +static void vscmi_destroy_channels(struct mhu_device_ctx *device_ctx); + +/* + * vi2c_process_msg: process messages of vhost-user interface + * + * Any that are not handled here are processed by the libvhost library + * itself. + */ +static int vscmi_process_msg(VuDev *dev, VhostUserMsg *msg, int *do_reply) +{ + struct mhu_device_ctx *device_ctx = container_of(dev, struct mhu_device_ctx, dev.parent); + + if (msg->request == VHOST_USER_NONE) { + g_debug("%s VHOST_USER_NONE", __func__); + + vscmi_destroy_channels(device_ctx); + device_ctx->thread = g_thread_new (device_ctx->config->socket_path, server_wait_vm_thread, device_ctx); + + return 1; + } + + return 0; +} + +static const VuDevIface vuiface = { + .set_features = vscmi_set_features, + .get_features = vscmi_get_features, + .queue_set_started = vscmi_queue_set_started, + .process_msg = vscmi_process_msg, +}; + +static int vscmi_init_channels(struct mhu_device_ctx *device_ctx) +{ + GError *error = NULL; + const gchar *socket_path = (const gchar *) device_ctx->config->socket_path; + + /* + * Now create a vhost-user socket that we will receive messages + * on. Once we have our handler set up we can enter the glib main + * loop. + */ + if (!device_ctx->config->socket_path) { + return 0; + } + + g_autoptr(GSocketAddress) addr = g_unix_socket_address_new(socket_path); + g_autoptr(GSocket) bind_socket = g_socket_new(G_SOCKET_FAMILY_UNIX, G_SOCKET_TYPE_STREAM, + G_SOCKET_PROTOCOL_DEFAULT, &error); + + if (!g_socket_bind(bind_socket, addr, false, &error)) { + g_printerr("Failed to bind to socket at %s (%s).\n", + socket_path, error->message); + return FWK_E_DEVICE; + } + + if (!g_socket_listen(bind_socket, &error)) { + g_printerr("Failed to listen on socket %s (%s).\n", + socket_path, error->message); + return FWK_E_DEVICE; + } + + g_message("awaiting connection to %s", socket_path); + device_ctx->socket = g_socket_accept(bind_socket, NULL, &error); + if (!device_ctx->socket) { + g_printerr("Failed to accept on socket %s (%s).\n", + socket_path, error->message); + return FWK_E_DEVICE; + } + + if (!vug_init(&device_ctx->dev, VHOST_USER_SCMI_MAX_QUEUES, g_socket_get_fd(device_ctx->socket), + vscmi_panic, &vuiface)) { + g_printerr("Failed to initialize libvhost-user-glib.\n"); + return FWK_E_DEVICE; + } + + return FWK_SUCCESS; +} + +static void vscmi_destroy_channels(struct mhu_device_ctx *device_ctx) +{ + if (device_ctx->socket != NULL) { + vug_deinit(&device_ctx->dev); + g_socket_close(device_ctx->socket, NULL); + g_object_unref(device_ctx->socket); + device_ctx->socket = NULL; + } + + unlink(device_ctx->config->socket_path); +} + +/* + * Mailbox module driver API + */ + +/* + * Provide a notify interface to the Mailbox driver + */ +static int raise_queue_notify(fwk_id_t channel_id, size_t size) +{ + size_t elt_idx = fwk_id_get_element_idx(channel_id); + struct mhu_device_ctx *device_ctx = &mhu_ctx.device_ctx_table[elt_idx]; + size_t chnl_idx = fwk_id_get_sub_element_idx(channel_id); + struct mhu_smt_channel *smt_channel = &device_ctx->smt_channel_table[chnl_idx]; + + vscmi_host_user_notification(&device_ctx->dev.parent, smt_channel->elem, chnl_idx, size); + + /* There should be a message in the mailbox */ + return FWK_SUCCESS; +} + +const struct mod_msg_smt_driver_ouput_api vhost_mod_smt_driver_api = { + .raise_notification = raise_queue_notify, +}; + +/* + * Framework handlers + */ + +static int vhost_init(fwk_id_t module_id, unsigned int device_count, + const void *data) +{ + if (device_count == 0) { + return FWK_E_PARAM; + } + + mhu_ctx.device_ctx_table = fwk_mm_calloc(device_count, + sizeof(*mhu_ctx.device_ctx_table)); + if (mhu_ctx.device_ctx_table == NULL) { + return FWK_E_NOMEM; + } + + mhu_ctx.device_count = device_count; + + return FWK_SUCCESS; +} + +static int vhost_device_init(fwk_id_t device_id, unsigned int slot_count, + const void *data) +{ + unsigned int slot; + size_t elt_idx = fwk_id_get_element_idx(device_id); + struct mhu_device_ctx *device_ctx = &mhu_ctx.device_ctx_table[elt_idx]; + struct mhu_smt_channel *smt_channel; + + device_ctx->config = (struct mod_vhost_mhu_channel_config*)data; + + device_ctx->smt_channel_table = fwk_mm_calloc(slot_count, + sizeof(device_ctx->smt_channel_table[0])); + + device_ctx->slot_count = slot_count; + + for (slot = 0; slot < device_ctx->slot_count; slot++) { + smt_channel = &device_ctx->smt_channel_table[slot]; + + smt_channel->id.value = 0; + } + + device_ctx->socket = NULL; + + return FWK_SUCCESS; +} + +static int vhost_bind(fwk_id_t id, unsigned int round) +{ + int status; + unsigned int slot; + struct mhu_device_ctx *device_ctx; + struct mhu_smt_channel *smt_channel; + + if (fwk_id_is_type(id, FWK_ID_TYPE_MODULE)) { + return FWK_SUCCESS; + } + + if (round == 1) { + + device_ctx = &mhu_ctx.device_ctx_table[fwk_id_get_element_idx(id)]; + + for (slot = 0; slot < device_ctx->slot_count; slot++) { + smt_channel = &device_ctx->smt_channel_table[slot]; + + if (smt_channel->id.value == 0) { + continue; + } + + status = fwk_module_bind(smt_channel->id, + device_ctx->config->driver_api_id, + &smt_channel->api); + + if (status != FWK_SUCCESS) { + return status; + } + } + } + + return FWK_SUCCESS; +} + +static int vhost_process_bind_request(fwk_id_t source_id, + fwk_id_t target_id, + fwk_id_t api_id, + const void **api) +{ + size_t elt_idx; + unsigned int slot; + struct mhu_device_ctx *device_ctx; + struct mhu_smt_channel *smt_channel; + + if (!fwk_id_is_type(target_id, FWK_ID_TYPE_SUB_ELEMENT)) { + return FWK_E_ACCESS; + } + + if (fwk_id_get_api_idx(api_id) != 0) { + return FWK_E_PARAM; + } + + elt_idx = fwk_id_get_element_idx(target_id); + if (elt_idx >= mhu_ctx.device_count) { + return FWK_E_PARAM; + } + + device_ctx = &mhu_ctx.device_ctx_table[elt_idx]; + + slot = fwk_id_get_sub_element_idx(target_id); + if (slot >= device_ctx->slot_count) { + return FWK_E_PARAM; + } + + smt_channel = &device_ctx->smt_channel_table[slot]; + + smt_channel->id = source_id; + *api = &vhost_mod_smt_driver_api; + + return FWK_SUCCESS; +} + +static int vhost_start(fwk_id_t id) +{ + size_t elt_idx; + struct mhu_device_ctx *device_ctx; + + if (fwk_id_is_type(id, FWK_ID_TYPE_MODULE)) { + return FWK_SUCCESS; + } + + elt_idx = fwk_id_get_element_idx(id); + device_ctx = &mhu_ctx.device_ctx_table[elt_idx]; + + device_ctx->thread = g_thread_new(device_ctx->config->socket_path, server_wait_vm_thread, device_ctx); + + return FWK_SUCCESS; +} + +static int vhost_stop(fwk_id_t id) +{ + size_t elt_idx; + struct mhu_device_ctx *device_ctx; + + if (fwk_id_is_type(id, FWK_ID_TYPE_MODULE)) { + return FWK_SUCCESS; + } + + elt_idx = fwk_id_get_element_idx(id); + device_ctx = &mhu_ctx.device_ctx_table[elt_idx]; + + vscmi_destroy_channels(device_ctx); + + return FWK_SUCCESS; +} + +/* OPTEE_MHU module definition */ +const struct fwk_module module_vhost_mhu = { + .type = FWK_MODULE_TYPE_DRIVER, + .api_count = 1, + .init = vhost_init, + .element_init = vhost_device_init, + .bind = vhost_bind, + .start = vhost_start, + .stop = vhost_stop, + .process_bind_request = vhost_process_bind_request, +}; diff --git a/module/vring_mhu/CMakeLists.txt b/module/vring_mhu/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..a44b7b0e99d10876a0942cfaa19fff0a00829206 --- /dev/null +++ b/module/vring_mhu/CMakeLists.txt @@ -0,0 +1,22 @@ +# +# Arm SCP/MCP Software +# Copyright (c) 2022, 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") + +target_sources(${SCP_MODULE_TARGET} + PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/src/mod_vring_mhu.c") + +target_link_libraries(${SCP_MODULE_TARGET} PRIVATE module-msg-smt + module-scmi) + +if(SCP_ENABLE_CMSIS) + target_link_libraries(${SCP_MODULE_TARGET} PUBLIC zephyr) + target_link_libraries(${SCP_MODULE_TARGET} PRIVATE CMSIS) +endif() diff --git a/module/vring_mhu/Module.cmake b/module/vring_mhu/Module.cmake new file mode 100644 index 0000000000000000000000000000000000000000..8e87baa50d53b06b244afb3338085bd6de3999ac --- /dev/null +++ b/module/vring_mhu/Module.cmake @@ -0,0 +1,9 @@ +# +# Arm SCP/MCP Software +# Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +set(SCP_MODULE "vring-mhu") +set(SCP_MODULE_TARGET "module-vring-mhu") diff --git a/module/vring_mhu/include/mod_vring_mhu.h b/module/vring_mhu/include/mod_vring_mhu.h new file mode 100644 index 0000000000000000000000000000000000000000..0a6ba3994a8aa8575a164f415635191729a40852 --- /dev/null +++ b/module/vring_mhu/include/mod_vring_mhu.h @@ -0,0 +1,28 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Description: + * virtio based transport channel device driver. + */ + +#ifndef MOD_VRING_MHU_H +#define MOD_VRING_MHU_H + +/*! + * \brief Channel config. + */ +struct mod_vring_mhu_channel_config { + /*! Identifier of the driver */ + fwk_id_t driver_id; + + /*! Identifier of the driver API to bind to */ + fwk_id_t driver_api_id; + + /*! DT node label of the virtio-mmio device */ + const char *device_label; +}; + +#endif /* MOD_OPTEE_MHU_H */ diff --git a/module/vring_mhu/src/mod_vring_mhu.c b/module/vring_mhu/src/mod_vring_mhu.c new file mode 100644 index 0000000000000000000000000000000000000000..59a73fc84dd416c012962e6c69bcf52ff3ea9a01 --- /dev/null +++ b/module/vring_mhu/src/mod_vring_mhu.c @@ -0,0 +1,524 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Description: + * virtio based transport channel device driver. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#ifdef BUILD_HAS_CMSIS +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Device implements SCMI notifications, or delayed responses. */ +#define VIRTIO_SCMI_F_P2A_CHANNELS 0 + +/* Device implements 1 request virtqueue and 1 optional notification virtqueue */ +#define VIRTIO_SCMI_VQ_REQ 0 +#define VIRTIO_SCMI_VQ_NOTIF 1 +#define VIRTIO_SCMI_VQ_MAX_CNT 2 + +/* A typical virtio_scmi request is made of 1 request buffer and 1 response buffer */ +/* Response/Notification buffer idx */ +#define VIRTIO_SCMI_OUT_MSG 0 +/* Request buffer idx */ +#define VIRTIO_SCMI_IN_MSG 1 +#define VIRTIO_SCMI_REQ_MAX_CNT 2 + +#define VIRTIO_SCMI_MAX_DATA 128 + +struct mhu_smt_channel { + struct virtqueue *vq; + /* virtio user message */ + struct virtio_buf virtiobuf; + /* vring user buffer */ + struct virtqueue_buf vqbufs[VIRTIO_SCMI_REQ_MAX_CNT]; + volatile bool locked; + fwk_id_t id; + struct mod_msg_smt_driver_input_api *api; +}; + +/* MHU device context */ +struct mhu_device_ctx { + /* vring interface */ + const struct device *virtio; + + /* Channel configuration data */ + struct mod_vring_mhu_channel_config *config; + + /* Number of slots (represented by sub-elements) */ + unsigned int slot_count; + + /* Table of SMT channels bound to the device */ + struct mhu_smt_channel *smt_channel_table; +}; + +/* MHU context */ +struct mhu_ctx { + /* Table of device contexts */ + struct mhu_device_ctx *device_ctx_table; + + /* Number of devices in the device context table*/ + unsigned int device_count; + +#ifdef BUILD_HAS_CMSIS +#define SIGNAL_ISR_EVENT 0x01 + /* + * Identifier given by the underlying OS to the thread created by the + * module or element. + */ + osThreadId_t os_thread_id; +#endif +}; + +static struct mhu_ctx mhu_ctx; + +/* + * Mailbox module driver API + */ + +/* + * Provide a notify interface to the Mailbox driver + */ +static int vring_get_next_req(const struct device *dev, struct mhu_smt_channel *smt_channel) +{ + struct virtqueue_buf *elem = smt_channel->vqbufs; + int ret; + + ret = virtio_pop(dev, smt_channel->vq, &smt_channel->virtiobuf); + + if (!ret) { + /* No new request */ + return 0; + } + + /* Start processing a request on the channel/virtqueue */ + smt_channel->locked = true; + + /* signal to virtio scmi message module that a new request is ready to be processed */ + smt_channel->api->signal_message(smt_channel->id, + elem[VIRTIO_SCMI_IN_MSG].buf, + elem[VIRTIO_SCMI_IN_MSG].len, + elem[VIRTIO_SCMI_OUT_MSG].buf, + elem[VIRTIO_SCMI_OUT_MSG].len); + + return 1; +} + +static void vring_put_prev_req(const struct device *dev, struct mhu_smt_channel *smt_channel, size_t size) +{ + struct virtqueue_buf *elem = smt_channel->vqbufs; + + /* 1st buffer is the answer to other side */ + elem[VIRTIO_SCMI_OUT_MSG].len = size; + + /* + * 2nd buffer is to receive the request from other side. + * When we owns the bus, we provisionned this buffer for the other side and must + * init the lenght to default size. + * + * This is not used by notification channel. + */ + elem[VIRTIO_SCMI_IN_MSG].len = VIRTIO_SCMI_MAX_DATA; + + virtio_push(dev, smt_channel->vq, &smt_channel->virtiobuf); +} + +static int raise_queue_notify(fwk_id_t channel_id, size_t size) +{ + size_t elt_idx = fwk_id_get_element_idx(channel_id); + struct mhu_device_ctx *device_ctx = &mhu_ctx.device_ctx_table[elt_idx]; + size_t chnl_idx = fwk_id_get_sub_element_idx(channel_id); + struct mhu_smt_channel *smt_channel = &device_ctx->smt_channel_table[chnl_idx]; + + /* put current request */ + vring_put_prev_req(device_ctx->virtio, smt_channel, size); + + /* check if a request is pending */ + if (vring_get_next_req(device_ctx->virtio, smt_channel)) { + return FWK_SUCCESS; + } + + /* No pending request */ + smt_channel->locked = false; + + return FWK_SUCCESS; +} + +const struct mod_msg_smt_driver_ouput_api vring_mod_smt_driver_api = { + .raise_notification = raise_queue_notify, +}; + +static void vring_virtio_state(const struct device *dev, void *user_data, int state) +{ + struct mhu_device_ctx *device_ctx = user_data; + struct mhu_smt_channel *smt_channel; + unsigned int slot; + + if (!state) { + /* + * Connection with client has been lost. The ongoing requests are + * meaningless and should not be sent back to client once done. + * Buffer descriptor index is used to send back the request to the + * client. Reset it to discard the request. + */ + for (slot = 0; slot < device_ctx->slot_count; slot++) { + smt_channel = &device_ctx->smt_channel_table[slot]; + + smt_channel->virtiobuf.index = (unsigned int)(-1); + } + } +} + +/* + * Virtio vring helpers + */ + +#ifndef container_of +#define container_of(ptr, type, member) ({ \ + const typeof(((type *) 0)->member) *__mptr = (ptr); \ + (type *) ((char *) __mptr - offsetof(type, member));}) +#endif + +static void vring_virtio_cb(struct virtqueue *vq) +{ + struct virtio_mmio_data *driver_data = container_of(vq->vq_dev, struct virtio_mmio_data, device); + struct mhu_device_ctx *device_ctx = driver_data->user_data; + struct mhu_smt_channel *smt_channel = &device_ctx->smt_channel_table[vq->vq_queue_index]; + uint32_t flags; + + if (!(smt_channel->locked) && + !(vring_get_next_req(device_ctx->virtio, smt_channel))) { + return; + } + +#ifdef BUILD_HAS_CMSIS + /* + * A notification is about to be raised + * + * Either SCMI server is already processing a request + * Or there is a new pending request + * + * Make sure to wakeup the SCMI server. + * + * This can generate spurious iteration of main thread loop but no + * spurious wakeup and it will ensure that it never misses a + * new request. + */ + flags = osThreadFlagsSet(mhu_ctx.os_thread_id, SIGNAL_ISR_EVENT); + if ((int32_t)flags < 0) { + FWK_LOG_CRIT("[VRING] ThreadSetFlag error %d in %s", FWK_E_OS, __func__); + return; + } +#endif +} + +static const char *scmi_vio_vqueue_names[] = { "request", "notification" }; + +static virtio_callback_t vring_vio_complete_callbacks[] = { + vring_virtio_cb, + vring_virtio_cb +}; + +struct __attribute((packed)) mod_virtio_smt_memory { + uint32_t message_header; + uint32_t payload[]; +}; + +int vring_init_channel(struct mhu_device_ctx *device_ctx, unsigned int slot_count) +{ + struct mhu_smt_channel *smt_channel; + struct virtqueue *vqs[VIRTIO_SCMI_VQ_MAX_CNT]; + const struct device *virtio; + int ret, size, i; + + if (device_ctx->config->device_label == NULL) { + return FWK_SUCCESS; + } + + device_ctx->virtio = NULL; + virtio = device_get_binding(device_ctx->config->device_label); + if (!virtio) { + FWK_LOG_ERR("[VRING] Device driver %s not found\n",device_ctx->config->device_label); + return FWK_E_DEVICE; + } + + /* Can't have more than 2 virtqueues for virtio SCMI */ + if (slot_count > VIRTIO_SCMI_VQ_MAX_CNT) { + return FWK_E_PARAM; + } + + /* Set notification feature if there are 2 channels */ + if (slot_count == VIRTIO_SCMI_VQ_MAX_CNT) { + virtio_set_device_features(virtio, 1 << VIRTIO_SCMI_F_P2A_CHANNELS); + } + + /* Get virqueues if any */ + ret = virtio_get_vqs(virtio, slot_count, vqs, vring_vio_complete_callbacks, + scmi_vio_vqueue_names); + if (ret) { + return FWK_E_DEVICE; + } + + size = virtio_max_data_size_get(virtio); + /* set virtqeue on each channel */ + for (i = 0; i < slot_count; i++) { + /* Save vqs */ + smt_channel = &device_ctx->smt_channel_table[i]; + smt_channel->vq = vqs[i]; + + /* preallocate buffers : only necessary for mmio driver */ + smt_channel->vqbufs[VIRTIO_SCMI_OUT_MSG].buf = virtio_get_buffer(virtio, smt_channel->vq, VIRTIO_SCMI_OUT_MSG); + smt_channel->vqbufs[VIRTIO_SCMI_OUT_MSG].len = size; + + /* set virtiobuf */ + smt_channel->virtiobuf.out_num = 1; + smt_channel->virtiobuf.buffers = smt_channel->vqbufs; + + if (i == VIRTIO_SCMI_VQ_REQ) { + /* + * 1st channel receives request and needs both in and out buffers + * 2nd channel only sends notification and needs out buffer only + */ + smt_channel->virtiobuf.in_num = 1; + /* preallocated buffers : only necessary for mmio driver */ + smt_channel->vqbufs[VIRTIO_SCMI_IN_MSG].buf = virtio_get_buffer(virtio, smt_channel->vq, VIRTIO_SCMI_IN_MSG); + smt_channel->vqbufs[VIRTIO_SCMI_IN_MSG].len = size; + + if (smt_channel->vqbufs[VIRTIO_SCMI_IN_MSG].buf != NULL) + /* + * When we owns of the link, buffer is not null and it needs to + * provision the virtqueue to receive request + */ + virtio_push(virtio, smt_channel->vq, &smt_channel->virtiobuf); + } + } + + /* Save device */ + device_ctx->virtio = virtio; + + /* Save device ctx */ + virtio_set_callback(virtio, vring_virtio_state, (void *)device_ctx); + + /* Ready to process request */ + virtio_set_enabled(virtio, 1); + + return FWK_SUCCESS; +} + +/* + * Framework handlers + */ + +static int vring_module_init(fwk_id_t module_id, unsigned int device_count, + const void *data) +{ + if (device_count == 0) { + return FWK_E_PARAM; + } + + mhu_ctx.device_ctx_table = fwk_mm_calloc(device_count, + sizeof(*mhu_ctx.device_ctx_table)); + if (mhu_ctx.device_ctx_table == NULL) { + return FWK_E_NOMEM; + } + + mhu_ctx.device_count = device_count; + + return FWK_SUCCESS; +} + +static int vring_device_init(fwk_id_t device_id, unsigned int slot_count, + const void *data) +{ + unsigned int slot; + size_t elt_idx = fwk_id_get_element_idx(device_id); + struct mhu_device_ctx *device_ctx = &mhu_ctx.device_ctx_table[elt_idx]; + struct mhu_smt_channel *smt_channel; + + device_ctx->config = (struct mod_vring_mhu_channel_config*)data; + + device_ctx->smt_channel_table = fwk_mm_calloc(slot_count, + sizeof(device_ctx->smt_channel_table[0])); + + device_ctx->slot_count = slot_count; + + for (slot = 0; slot < device_ctx->slot_count; slot++) { + smt_channel = &device_ctx->smt_channel_table[slot]; + + smt_channel->id.value = 0; + smt_channel->locked = false; + } + + vring_init_channel(device_ctx, slot_count); + + return FWK_SUCCESS; +} + +static int vring_bind(fwk_id_t id, unsigned int round) +{ + int status; + unsigned int slot; + struct mhu_device_ctx *device_ctx; + struct mhu_smt_channel *smt_channel; + + if (fwk_id_is_type(id, FWK_ID_TYPE_MODULE)) { + return FWK_SUCCESS; + } + + if (round == 1) { + + device_ctx = &mhu_ctx.device_ctx_table[fwk_id_get_element_idx(id)]; + + for (slot = 0; slot < device_ctx->slot_count; slot++) { + smt_channel = &device_ctx->smt_channel_table[slot]; + + if (smt_channel->id.value == 0) { + continue; + } + + status = fwk_module_bind(smt_channel->id, + device_ctx->config->driver_api_id, + &smt_channel->api); + + if (status != FWK_SUCCESS) { + return status; + } + } + } + + return FWK_SUCCESS; +} + +static int vring_process_bind_request(fwk_id_t source_id, + fwk_id_t target_id, + fwk_id_t api_id, + const void **api) +{ + size_t elt_idx; + unsigned int slot; + struct mhu_device_ctx *device_ctx; + struct mhu_smt_channel *smt_channel; + + if (!fwk_id_is_type(target_id, FWK_ID_TYPE_SUB_ELEMENT)) { + return FWK_E_ACCESS; + } + + if (fwk_id_get_api_idx(api_id) != 0) { + return FWK_E_PARAM; + } + + elt_idx = fwk_id_get_element_idx(target_id); + if (elt_idx >= mhu_ctx.device_count) { + return FWK_E_PARAM; + } + + device_ctx = &mhu_ctx.device_ctx_table[elt_idx]; + + slot = fwk_id_get_sub_element_idx(target_id); + if (slot >= device_ctx->slot_count) { + return FWK_E_PARAM; + } + + smt_channel = &device_ctx->smt_channel_table[slot]; + + smt_channel->id = source_id; + *api = &vring_mod_smt_driver_api; + + return FWK_SUCCESS; +} + +#ifdef BUILD_HAS_CMSIS +static void vring_thread_function(void *arg) +{ + uint32_t flags, signals = SIGNAL_ISR_EVENT; + + for (;;) { + flags = osThreadFlagsWait(signals, osFlagsWaitAny, osWaitForever); + + if (!(flags & signals)) { + continue; + } + + fwk_process_event_queue(); + + fwk_log_flush(); + } +} + +#ifndef FMW_STACK_SIZE +# define FMW_STACK_SIZE 1536 +#endif + +int vring_thread_create(struct mhu_ctx *module_ctx) +{ + osThreadAttr_t thread_attr = { + .stack_size = FMW_STACK_SIZE, + }; + + module_ctx->os_thread_id = + osThreadNew(vring_thread_function, module_ctx, &thread_attr); + + if (module_ctx->os_thread_id == NULL) { + FWK_LOG_CRIT("[VRING] Thread Create error %d in %s", FWK_E_OS, __func__); + return FWK_E_OS; + } + + return FWK_SUCCESS; +} + +#else +int vring_thread_create(struct mhu_ctx *module_ctx) +{ + return FWK_SUCCESS; +} +#endif + +static int vring_start(fwk_id_t id) +{ + vring_thread_create(&mhu_ctx); + return FWK_SUCCESS; +} + +/* OPTEE_MHU module definition */ +const struct fwk_module module_vring_mhu = { + .type = FWK_MODULE_TYPE_DRIVER, + .api_count = 1, + .init = vring_module_init, + .element_init = vring_device_init, + .bind = vring_bind, + .start = vring_start, + .process_bind_request = vring_process_bind_request, +}; diff --git a/product/host-input/fw/CMakeLists.txt b/product/host-input/fw/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..f045afaf4d20b07e3db14b20f073f3e5dfa190d8 --- /dev/null +++ b/product/host-input/fw/CMakeLists.txt @@ -0,0 +1,41 @@ +# +# 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_executable(${SCP_FIRMWARE_TARGET}) + +find_package(PkgConfig REQUIRED) +pkg_check_modules(deps REQUIRED IMPORTED_TARGET glib-2.0) +target_link_libraries(${SCP_FIRMWARE_TARGET} PRIVATE PkgConfig::deps) + +# 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_mhu_smt.c" + "${CMAKE_CURRENT_SOURCE_DIR}/config_scmi.c" + "${CMAKE_CURRENT_SOURCE_DIR}/config_mock_clock.c" + "${CMAKE_CURRENT_SOURCE_DIR}/config_vpll.c" + "${CMAKE_CURRENT_SOURCE_DIR}/config_clock.c" + "${CMAKE_CURRENT_SOURCE_DIR}/config_scmi_clock.c" + "${CMAKE_CURRENT_SOURCE_DIR}/config_ppu_v0.c" + "${CMAKE_CURRENT_SOURCE_DIR}/config_power_domain.c" + "${CMAKE_CURRENT_SOURCE_DIR}/config_scmi_power_domain.c" + "${CMAKE_CURRENT_SOURCE_DIR}/config_mock_psu.c" + "${CMAKE_CURRENT_SOURCE_DIR}/config_psu.c" + "${CMAKE_CURRENT_SOURCE_DIR}/config_dvfs.c" + "${CMAKE_CURRENT_SOURCE_DIR}/config_scmi_perf.c" + "${CMAKE_CURRENT_SOURCE_DIR}/config_sensor.c" + "${CMAKE_CURRENT_SOURCE_DIR}/config_host.c") diff --git a/product/host-input/fw/Firmware.cmake b/product/host-input/fw/Firmware.cmake new file mode 100644 index 0000000000000000000000000000000000000000..cbcdd5e7dbab6fc87a61ea0835ce611df59b1181 --- /dev/null +++ b/product/host-input/fw/Firmware.cmake @@ -0,0 +1,55 @@ +# +# 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 "host-input") + +set(SCP_FIRMWARE_TARGET "host-input") + +set(SCP_ARCHITECTURE "none") + +#set(SCP_GENERATE_FLAT_BINARY_INIT TRUE) + +set(SCP_ENABLE_NOTIFICATIONS_INIT TRUE) + +set(SCP_ENABLE_SCMI_NOTIFICATIONS_INIT TRUE) + +set(SCP_ENABLE_SCMI_SENSOR_EVENTS_INIT TRUE) + +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/vppu") + +# 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 "input-mhu") +list(APPEND SCP_MODULES "msg-smt") +list(APPEND SCP_MODULES "scmi") +list(APPEND SCP_MODULES "mock-clock") +list(APPEND SCP_MODULES "system-pll") +list(APPEND SCP_MODULES "clock") +list(APPEND SCP_MODULES "scmi-clock") +list(APPEND SCP_MODULES "vppu") +list(APPEND SCP_MODULES "power-domain") +list(APPEND SCP_MODULES "scmi-power-domain") +list(APPEND SCP_MODULES "mock-psu") +list(APPEND SCP_MODULES "psu") +list(APPEND SCP_MODULES "dvfs") +list(APPEND SCP_MODULES "scmi-perf") +list(APPEND SCP_MODULES "reg-sensor") +list(APPEND SCP_MODULES "sensor") +list(APPEND SCP_MODULES "scmi-sensor") +list(APPEND SCP_MODULES "host-console") diff --git a/product/host-input/fw/clock_devices.h b/product/host-input/fw/clock_devices.h new file mode 100644 index 0000000000000000000000000000000000000000..df71204a250dac02a845a116f079fe2262a85b2f --- /dev/null +++ b/product/host-input/fw/clock_devices.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 CLOCK_DEVICES_H +#define CLOCK_DEVICES_H + +/*! + * \brief Clock device indexes. + */ +enum clock_dev_idx { + CLOCK_DEV_IDX_BIG, + CLOCK_DEV_IDX_LITTLE, + CLOCK_DEV_IDX_GPU, + CLOCK_DEV_IDX_VPU, + CLOCK_DEV_IDX_DPU, + CLOCK_DEV_IDX_PIXEL_0, + CLOCK_DEV_IDX_PIXEL_1, + CLOCK_DEV_IDX_MOCK_0, + CLOCK_DEV_IDX_MOCK_1, + CLOCK_DEV_IDX_MOCK_2, + CLOCK_DEV_IDX_MOCK_3, + CLOCK_DEV_IDX_COUNT +}; + +#endif /* CLOCK_DEVICES_H */ diff --git a/product/host-input/fw/config_clock.c b/product/host-input/fw/config_clock.c new file mode 100644 index 0000000000000000000000000000000000000000..103fbb09639be361554a42729df0c0f2b4696790 --- /dev/null +++ b/product/host-input/fw/config_clock.c @@ -0,0 +1,127 @@ +/* + * 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 "clock_devices.h" + +static struct fwk_element clock_dev_desc_table[] = { + [CLOCK_DEV_IDX_BIG] = { + .name = "CPU_GROUP_BIG", + .data = &((struct mod_clock_dev_config) { + .driver_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_SYSTEM_PLL, 0), + .api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_SYSTEM_PLL, + MOD_SYSTEM_PLL_API_TYPE_DEFAULT), + }), + }, + [CLOCK_DEV_IDX_LITTLE] = { + .name = "CPU_GROUP_LITTLE", + .data = &((struct mod_clock_dev_config) { + .driver_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_SYSTEM_PLL, 1), + .api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_SYSTEM_PLL, + MOD_SYSTEM_PLL_API_TYPE_DEFAULT), + }), + }, + [CLOCK_DEV_IDX_GPU] = { + .name = "GPU", + .data = &((struct mod_clock_dev_config) { + .driver_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_SYSTEM_PLL, 2), + .api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_SYSTEM_PLL, + MOD_SYSTEM_PLL_API_TYPE_DEFAULT), + }), + }, + [CLOCK_DEV_IDX_VPU] = { + .name = "VPU", + .data = &((struct mod_clock_dev_config) { + .driver_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_SYSTEM_PLL, 3), + .api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_SYSTEM_PLL, + MOD_SYSTEM_PLL_API_TYPE_DEFAULT), + }), + }, + [CLOCK_DEV_IDX_DPU] = { + .name = "DPU", + .data = &((struct mod_clock_dev_config) { + .driver_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_SYSTEM_PLL, 4), + .api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_SYSTEM_PLL, + MOD_SYSTEM_PLL_API_TYPE_DEFAULT), + }), + }, + [CLOCK_DEV_IDX_PIXEL_0] = { + .name = "PIXEL_0", + .data = &((struct mod_clock_dev_config) { + .driver_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_SYSTEM_PLL, 5), + .api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_SYSTEM_PLL, + MOD_SYSTEM_PLL_API_TYPE_DEFAULT), + }), + }, + [CLOCK_DEV_IDX_PIXEL_1] = { + .name = "PIXEL_1", + .data = &((struct mod_clock_dev_config) { + .driver_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_SYSTEM_PLL, 6), + .api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_SYSTEM_PLL, + MOD_SYSTEM_PLL_API_TYPE_DEFAULT), + }), + }, + [CLOCK_DEV_IDX_MOCK_0] = { + .name = "CLOCK_0", + .data = &((struct mod_clock_dev_config) { + .driver_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_MOCK_CLOCK, 0), + .api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_MOCK_CLOCK, + MOD_MOCK_CLOCK_API_TYPE_DRIVER), + }), + }, + [CLOCK_DEV_IDX_MOCK_1] = { + .name = "CLOCK_1", + .data = &((struct mod_clock_dev_config) { + .driver_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_MOCK_CLOCK, 1), + .api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_MOCK_CLOCK, + MOD_MOCK_CLOCK_API_TYPE_DRIVER), + }), + }, + [CLOCK_DEV_IDX_MOCK_2] = { + .name = "CLOCK_2", + .data = &((struct mod_clock_dev_config) { + .driver_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_MOCK_CLOCK, 2), + .api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_MOCK_CLOCK, + MOD_MOCK_CLOCK_API_TYPE_DRIVER), + }), + }, + [CLOCK_DEV_IDX_MOCK_3] = { + .name = "CLOCK_3", + .data = &((struct mod_clock_dev_config) { + .driver_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_MOCK_CLOCK, 3), + .api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_MOCK_CLOCK, + MOD_MOCK_CLOCK_API_TYPE_DRIVER), + }), + }, + [CLOCK_DEV_IDX_COUNT] = { 0 }, /* Termination description. */ +}; + +static const struct fwk_element *clock_get_dev_desc_table(fwk_id_t module_id) +{ + unsigned int i; + struct mod_clock_dev_config *dev_config; + + /* Configure all clocks to respond to changes in SYSTOP power state */ + for (i = 0; i < CLOCK_DEV_IDX_COUNT; i++) { + dev_config = + (struct mod_clock_dev_config *)clock_dev_desc_table[i].data; + dev_config->pd_source_id = FWK_ID_NONE; + } + return clock_dev_desc_table; +} + +struct fwk_module_config config_clock = { + .data = &((struct mod_clock_config){ + .pd_transition_notification_id = FWK_ID_NONE_INIT, + .pd_pre_transition_notification_id = FWK_ID_NONE_INIT, + }), + .elements = FWK_MODULE_DYNAMIC_ELEMENTS(clock_get_dev_desc_table), +}; diff --git a/product/host-input/fw/config_dvfs.c b/product/host-input/fw/config_dvfs.c new file mode 100644 index 0000000000000000000000000000000000000000..12867173043e0b4071db8040944b9f79ae852f86 --- /dev/null +++ b/product/host-input/fw/config_dvfs.c @@ -0,0 +1,152 @@ +/* + * 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 "config_dvfs.h" + +static const struct mod_dvfs_domain_config cpu_group_little = { + .psu_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_PSU, 0), + .clock_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_CLOCK, 0), + .latency = 1200, + .sustained_idx = 2, + .opps = (struct mod_dvfs_opp[]) { + { + .level = 665 * 1000UL, + .frequency = 665 * 1000UL, + .voltage = 100, + .power = 665*100*100/10000, + }, + { + .level = 998 * 1000UL, + .frequency = 998 * 1000UL, + .voltage = 110, + .power = 998*110*110/10000, + }, + { + .level = 1330 * 1000UL, + .frequency = 1330 * 1000UL, + .voltage = 120, + .power = 1330*120*120/10000, + }, + { + .level = 1463 * 1000UL, + .frequency = 1463 * 1000UL, + .voltage = 130, + .power = 1463*130*130/10000, + }, + { + .level = 1596 * 1000UL, + .frequency = 1596 * 1000UL, + .voltage = 140, + .power = 1596*140*140/10000, + }, + { 0 } + } +}; + +static const struct mod_dvfs_domain_config cpu_group_big = { + .psu_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_PSU, 1), + .clock_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_CLOCK, 1), + .latency = 1200, + .sustained_idx = 2, + .opps = (struct mod_dvfs_opp[]) { + { + .level = 1313 * 1000UL, + .frequency = 1313 * 1000UL , + .voltage = 100, + .power = 1313, + }, + { + .level = 1531 * 1000UL, + .frequency = 1531 * 1000UL, + .voltage = 200, + .power = 1531, + }, + { + .level = 1750 * 1000UL, + .frequency = 1750 * 1000UL, + .voltage = 300, + .power = 1750, + }, + { + .level = 2100 * 1000UL, + .frequency = 2100 * 1000UL, + .voltage = 400, + .power = 2100, + }, + { + .level = 2450 * 1000UL, + .frequency = 2450 * 1000UL, + .voltage = 500, + .power = 2450, + }, + { 0 } + } +}; + +static const struct mod_dvfs_domain_config gpu = { + .psu_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_PSU, 2), + .clock_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_CLOCK, 2), + .latency = 1200, + .sustained_idx = 4, + .opps = (struct mod_dvfs_opp[]) { + { + .level = 450 * 1000UL, + .frequency = 450 * 1000UL, + .voltage = 100, + }, + { + .level = 487500, + .frequency = 487500, + .voltage = 200, + }, + { + .level = 525 * 1000UL, + .frequency = 525 * 1000UL, + .voltage = 300, + }, + { + .level = 562500 * 1000UL, + .frequency = 562500, + .voltage = 400, + }, + { + .level = 600 * 1000UL, + .frequency = 600 * 1000UL, + .voltage = 500, + }, + { 0 } + } +}; + +static const struct fwk_element element_table[] = { + [DVFS_ELEMENT_IDX_LITTLE] = { + .name = "CPU_GROUP_LITTLE", + .data = &cpu_group_little, + }, + [DVFS_ELEMENT_IDX_BIG] = { + .name = "CPU_GROUP_BIG", + .data = &cpu_group_big, + }, + [DVFS_ELEMENT_IDX_GPU] = { + .name = "GPU", + .data = &gpu, + }, + { 0 } +}; + +static const struct fwk_element *dvfs_get_element_table(fwk_id_t module_id) +{ + return element_table; +} + +struct fwk_module_config config_dvfs = { + .elements = FWK_MODULE_DYNAMIC_ELEMENTS(dvfs_get_element_table), +}; diff --git a/product/host-input/fw/config_dvfs.h b/product/host-input/fw/config_dvfs.h new file mode 100644 index 0000000000000000000000000000000000000000..2913c1060d92e9dc24b84420144d50c55ec6c1f3 --- /dev/null +++ b/product/host-input/fw/config_dvfs.h @@ -0,0 +1,18 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CONFIG_DVFS_H +#define CONFIG_DVFS_H + +enum dvfs_element_idx { + DVFS_ELEMENT_IDX_LITTLE, + DVFS_ELEMENT_IDX_BIG, + DVFS_ELEMENT_IDX_GPU, + DVFS_ELEMENT_IDX_COUNT +}; + +#endif /* CONFIG_DVFS_H */ diff --git a/product/host-input/fw/config_host.c b/product/host-input/fw/config_host.c new file mode 100644 index 0000000000000000000000000000000000000000..0df4b32349c7dab3e2f75622d1f2a7651b4890ef --- /dev/null +++ b/product/host-input/fw/config_host.c @@ -0,0 +1,85 @@ +/* + * 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 + +/* Glib helpers */ + +typedef struct { + GMainLoop *loop; +} VuScmi; + +VuScmi scmi = {0}; + +static gboolean verbose; + +static GOptionEntry options[] = { + { "verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose, "Be more verbose in output", NULL}, + { NULL } +}; + +static gboolean hangup(gpointer user_data) +{ + GMainLoop *loop = (GMainLoop *) user_data; + g_info("%s: caught hangup/quit signal, quitting main loop", __func__); + g_main_loop_quit(loop); + return true; +} + +/* Main loop */ + +int main(int argc, char *argv[]) +{ + GError *error = NULL; + GOptionContext *context; + + context = g_option_context_new("host-user emulation of SCMI device"); + g_option_context_add_main_entries(context, options, "host-user-scmi"); + if (!g_option_context_parse(context, &argc, &argv, &error)) + { + g_printerr("option parsing failed: %s\n", error->message); + exit(1); + } + + if (verbose) { + g_log_set_handler(NULL, G_LOG_LEVEL_MASK, g_log_default_handler, NULL); + g_setenv("G_MESSAGES_DEBUG", "all", true); + } else { + g_log_set_handler(NULL, + G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_ERROR, + g_log_default_handler, NULL); + } + + /* + * Create the main loop first so all the various sources can be + * added. SCMI server can add it's GSource watches. + */ + scmi.loop = g_main_loop_new(NULL, FALSE); + + /* Catch exit signals */ + g_unix_signal_add(SIGHUP, hangup, scmi.loop); + g_unix_signal_add(SIGINT, hangup, scmi.loop); + g_unix_signal_add(SIGTERM, hangup, scmi.loop); + + /* Initialize scmi server */ + scmi_arch_init(); + + /* Enter main loop */ + g_message("entering main loop, awaiting messages"); + g_main_loop_run(scmi.loop); + g_message("finished main loop, cleaning up"); + + /* Stop scmi server */ + scmi_arch_deinit(); + + /* Stop main loop and exit */ + g_main_loop_unref(scmi.loop); +} diff --git a/product/host-input/fw/config_mhu_smt.c b/product/host-input/fw/config_mhu_smt.c new file mode 100644 index 0000000000000000000000000000000000000000..02a1c362dbb9c36fbd45f937d70c0f88398b3ce8 --- /dev/null +++ b/product/host-input/fw/config_mhu_smt.c @@ -0,0 +1,109 @@ +/* + * 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 + +static const struct fwk_element mhu_element_table[] = { + [SCMI_CHANNEL_DEVICE_IDX_PSCI] = { + .name = "virqueue for PSCI", + .sub_element_count = 1, + .data = &((struct mod_input_mhu_channel_config) { + .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_MSG_SMT, + MOD_MSG_SMT_API_IDX_DRIVER_INPUT), + }) + }, + [SCMI_CHANNEL_DEVICE_IDX_OSPM_0] = { + .name = "virqueue for OSPM #0", + .sub_element_count = 2, + .data = &((struct mod_input_mhu_channel_config) { + .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_MSG_SMT, + MOD_MSG_SMT_API_IDX_DRIVER_INPUT), + }) + }, + [SCMI_CHANNEL_DEVICE_IDX_OSPM_1] = { + .name = "virqueue for OSPM #1", + .sub_element_count = 2, + .data = &((struct mod_input_mhu_channel_config) { + .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_MSG_SMT, + MOD_MSG_SMT_API_IDX_DRIVER_INPUT), + }) + }, + [SCMI_CHANNEL_DEVICE_IDX_COUNT] = { 0 }, +}; + +static const struct fwk_element *mhu_get_element_table(fwk_id_t module_id) +{ + return (const struct fwk_element *)mhu_element_table; +} + +struct fwk_module_config config_input_mhu = { + .elements = FWK_MODULE_DYNAMIC_ELEMENTS(mhu_get_element_table), +}; + +static struct fwk_element smt_element_table[] = { + [SCMI_SERVICE_IDX_PSCI] = { + .name = "PSCI", + .data = &((struct mod_msg_smt_channel_config) { + .type = MOD_MSG_SMT_CHANNEL_TYPE_REQUESTER, + .driver_id = FWK_ID_SUB_ELEMENT_INIT(FWK_MODULE_IDX_INPUT_MHU, + SCMI_CHANNEL_DEVICE_IDX_PSCI, 0), + .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_INPUT_MHU, 0), + }) + }, + [SCMI_SERVICE_IDX_OSPM_0] = { + .name = "OSPM0", + .data = &((struct mod_msg_smt_channel_config) { + .type = MOD_MSG_SMT_CHANNEL_TYPE_REQUESTER, + .driver_id = FWK_ID_SUB_ELEMENT_INIT(FWK_MODULE_IDX_INPUT_MHU, + SCMI_CHANNEL_DEVICE_IDX_OSPM_0, 0), + .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_INPUT_MHU, 0), + }) + }, + [SCMI_SERVICE_IDX_OSPM_1] = { + .name = "OSPM1", + .data = &((struct mod_msg_smt_channel_config) { + .type = MOD_MSG_SMT_CHANNEL_TYPE_REQUESTER, + .driver_id = FWK_ID_SUB_ELEMENT_INIT(FWK_MODULE_IDX_INPUT_MHU, + SCMI_CHANNEL_DEVICE_IDX_OSPM_1, 0), + .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_INPUT_MHU, 0), + }) + }, +#ifdef BUILD_HAS_SCMI_NOTIFICATIONS + [SCMI_SERVICE_IDX_OSPM_0_P2A] = { + .name = "OSPM0 P2A", + .data = &((struct mod_msg_smt_channel_config) { + .type = MOD_MSG_SMT_CHANNEL_TYPE_COMPLETER, + .driver_id = FWK_ID_SUB_ELEMENT_INIT(FWK_MODULE_IDX_INPUT_MHU, + SCMI_CHANNEL_DEVICE_IDX_OSPM_0, 1), + .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_INPUT_MHU, 0), + }) + }, + [SCMI_SERVICE_IDX_OSPM_1_P2A] = { + .name = "OSPM1 P2A", + .data = &((struct mod_msg_smt_channel_config) { + .type = MOD_MSG_SMT_CHANNEL_TYPE_COMPLETER, + .driver_id = FWK_ID_SUB_ELEMENT_INIT(FWK_MODULE_IDX_INPUT_MHU, + SCMI_CHANNEL_DEVICE_IDX_OSPM_1, 1), + .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_INPUT_MHU, 0), + }) + }, +#endif + [SCMI_SERVICE_IDX_COUNT] = { 0 }, +}; + +static const struct fwk_element *smt_get_element_table(fwk_id_t module_id) +{ + return (const struct fwk_element *)smt_element_table; +} + +struct fwk_module_config config_msg_smt = { + .elements = FWK_MODULE_DYNAMIC_ELEMENTS(smt_get_element_table), +}; diff --git a/product/host-input/fw/config_mock_clock.c b/product/host-input/fw/config_mock_clock.c new file mode 100644 index 0000000000000000000000000000000000000000..5b64c9585051ffb4d07ef4da9ca0b5123f79337a --- /dev/null +++ b/product/host-input/fw/config_mock_clock.c @@ -0,0 +1,78 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include "config_mock_clock.h" + + +static const struct mod_mock_clock_rate clk0_rate_table[] = { + { .rate = 1536000 }, { .rate = 2116800 }, { .rate = 2304000 }, + { .rate = 4233600 }, { .rate = 4608000 }, { .rate = 8467200 }, + { .rate = 9216000 }, +}; + +static const struct mod_mock_clock_rate clk1_rate_table[] = { + { .rate = 2116800 }, +}; + +static const struct mod_mock_clock_rate clk2_rate_table[] = { + { .rate = 2304000 }, +}; + +static const struct mod_mock_clock_rate clk3_rate_table[] = { + { .rate = 4233600 }, +}; + +static const struct fwk_element element_table[] = { + [MOD_MOCK_CLOCK_ELEMENT_IDX_0] = + { + .name = "MOCK_CLK0", + .data = &(const struct mod_mock_clock_element_cfg){ + .rate_table = clk0_rate_table, + .rate_count = FWK_ARRAY_SIZE(clk0_rate_table), + .default_rate = 1536000, + }, + }, + [MOD_MOCK_CLOCK_ELEMENT_IDX_1] = + { + .name = "MOCK_CLK1", + .data = &(const struct mod_mock_clock_element_cfg){ + .rate_table = clk1_rate_table, + .rate_count = FWK_ARRAY_SIZE(clk1_rate_table), + .default_rate = 2116800, + }, + }, + [MOD_MOCK_CLOCK_ELEMENT_IDX_2] = + { + .name = "MOCK_CLK2", + .data = &(const struct mod_mock_clock_element_cfg){ + .rate_table = clk2_rate_table, + .rate_count = FWK_ARRAY_SIZE(clk2_rate_table), + .default_rate = 2304000, + }, + }, + [MOD_MOCK_CLOCK_ELEMENT_IDX_3] = + { + .name = "MOCK_CLK3", + .data = &(const struct mod_mock_clock_element_cfg){ + .rate_table = clk3_rate_table, + .rate_count = FWK_ARRAY_SIZE(clk3_rate_table), + .default_rate = 4233600, + }, + }, + [MOD_MOCK_CLOCK_ELEMENT_IDX_COUNT] = { 0 }, /* Termination description. */ +}; + +static const struct fwk_element *get_element_table(fwk_id_t module_id) +{ + return element_table; +} + +struct fwk_module_config config_mock_clock = { + .elements = FWK_MODULE_DYNAMIC_ELEMENTS(get_element_table), +}; diff --git a/product/host-input/fw/config_mock_clock.h b/product/host-input/fw/config_mock_clock.h new file mode 100644 index 0000000000000000000000000000000000000000..114f0e00f59d17b9d8fa5177237dadbdec790ceb --- /dev/null +++ b/product/host-input/fw/config_mock_clock.h @@ -0,0 +1,20 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CONFIG_MOCK_CLOCK_H +#define CONFIG_MOCK_CLOCK_H + +/* Mock clock element indices for Juno */ +enum mod_mock_clock_element_idx { + MOD_MOCK_CLOCK_ELEMENT_IDX_0, + MOD_MOCK_CLOCK_ELEMENT_IDX_1, + MOD_MOCK_CLOCK_ELEMENT_IDX_2, + MOD_MOCK_CLOCK_ELEMENT_IDX_3, + MOD_MOCK_CLOCK_ELEMENT_IDX_COUNT, +}; + +#endif /* CONFIG_MOCK_CLOCK_H */ diff --git a/product/host-input/fw/config_mock_psu.c b/product/host-input/fw/config_mock_psu.c new file mode 100644 index 0000000000000000000000000000000000000000..efdc94cbb4e733046ee5b542efae7085f402023e --- /dev/null +++ b/product/host-input/fw/config_mock_psu.c @@ -0,0 +1,55 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include "config_mock_psu.h" + +static const struct fwk_element element_table[] = { + [CONFIG_MOCK_PSU_ELEMENT_IDX_CPU_GROUP_LITTLE] = { + .name = "CPU_GROUP_LITTLE", + .data = &(const struct mod_mock_psu_element_cfg) { + .default_enabled = true, + .default_voltage = 100, + .async_alarm_id = FWK_ID_NONE_INIT, + }, + }, + [CONFIG_MOCK_PSU_ELEMENT_IDX_CPU_GROUP_BIG] = { + .name = "CPU_GROUP_BIG", + .data = &(const struct mod_mock_psu_element_cfg) { + .default_enabled = true, + .default_voltage = 100, + .async_alarm_id = FWK_ID_NONE_INIT, + }, + }, + [CONFIG_MOCK_PSU_ELEMENT_IDX_GPU] = { + .name = "GPU", + .data = &(const struct mod_mock_psu_element_cfg) { + .default_enabled = true, + .default_voltage = 100, + .async_alarm_id = FWK_ID_NONE_INIT, + }, + }, + [CONFIG_MOCK_PSU_ELEMENT_IDX_VPU] = { + .name = "VPU", + .data = &(const struct mod_mock_psu_element_cfg) { + .default_enabled = true, + .default_voltage = 100, + .async_alarm_id = FWK_ID_NONE_INIT, + }, + }, + { 0 } +}; + +static const struct fwk_element *get_element_table(fwk_id_t module_id) +{ + return element_table; +} + +struct fwk_module_config config_mock_psu = { + .elements = FWK_MODULE_DYNAMIC_ELEMENTS(get_element_table), +}; diff --git a/product/host-input/fw/config_mock_psu.h b/product/host-input/fw/config_mock_psu.h new file mode 100644 index 0000000000000000000000000000000000000000..74476bb4585bcae08e85f86fcb538bab8d213fc3 --- /dev/null +++ b/product/host-input/fw/config_mock_psu.h @@ -0,0 +1,19 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CONFIG_MOCK_PSU_H +#define CONFIG_MOCK_PSU_H + +enum config_mock_psu_element_idx { + CONFIG_MOCK_PSU_ELEMENT_IDX_CPU_GROUP_LITTLE, + CONFIG_MOCK_PSU_ELEMENT_IDX_CPU_GROUP_BIG, + CONFIG_MOCK_PSU_ELEMENT_IDX_GPU, + CONFIG_MOCK_PSU_ELEMENT_IDX_VPU, + CONFIG_MOCK_PSU_ELEMENT_IDX_COUNT, +}; + +#endif /* CONFIG_MOCK_PSU_H */ diff --git a/product/host-input/fw/config_power_domain.c b/product/host-input/fw/config_power_domain.c new file mode 100644 index 0000000000000000000000000000000000000000..eb5abb64bf4dd9e70cb4f0eb126cdb6d747e74d3 --- /dev/null +++ b/product/host-input/fw/config_power_domain.c @@ -0,0 +1,153 @@ +/* + * 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 "config_power_domain.h" +#include "config_ppu_v0.h" + +/* + * Mask of the allowed states for the top level power domains + * (but the cluster power domains) depending on the system states. + */ +static const uint32_t toplevel_allowed_state_mask_table[] = { + [MOD_PD_STATE_OFF] = MOD_PD_STATE_OFF_MASK, + [MOD_PD_STATE_ON] = MOD_PD_STATE_OFF_MASK | MOD_PD_STATE_ON_MASK, +}; + +/* + * Mask of the allowed states for the cluster power domain depending on the + * system states. + * + * While the clusters may reach a SLEEP state, SLEEP does not appear in this + * table. This is because the PPU driver backing the clusters will not accept a + * manual SLEEP request, but will transition to it automatically when possible. + */ +static const uint32_t cluster_pd_allowed_state_mask_table[] = { + [MOD_PD_STATE_OFF] = MOD_PD_STATE_OFF_MASK, + [MOD_PD_STATE_ON] = MOD_PD_STATE_OFF_MASK | MOD_PD_STATE_ON_MASK, +}; + +/* Mask of the allowed states for a core depending on the cluster states. */ +static const uint32_t core_pd_allowed_state_mask_table[] = { + [MOD_PD_STATE_OFF] = MOD_PD_STATE_OFF_MASK, + [MOD_PD_STATE_ON] = MOD_PD_STATE_OFF_MASK | MOD_PD_STATE_ON_MASK | + MOD_PD_STATE_SLEEP_MASK, + [MOD_PD_STATE_SLEEP] = MOD_PD_STATE_OFF_MASK | MOD_PD_STATE_SLEEP_MASK, +}; + +/* Power module specific configuration data (none) */ +static const struct mod_power_domain_config fvp_power_domain_config = { 0 }; + +static struct fwk_element fvp_power_domain_static_element_table[] = { + [CONFIG_POWER_DOMAIN_SYSTOP_CHILD_DBGTOP] = { + .name = "DBGTOP", + .data = &((struct mod_power_domain_element_config) { + .attributes.pd_type = MOD_PD_TYPE_DEVICE_DEBUG, + .driver_id = FWK_ID_ELEMENT_INIT( + FWK_MODULE_IDX_VPPU, PPU_V0_ELEMENT_IDX_DBGTOP), + .api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_VPPU, 0), + .allowed_state_mask_table = toplevel_allowed_state_mask_table, + .allowed_state_mask_table_size = + FWK_ARRAY_SIZE(toplevel_allowed_state_mask_table) + }), + }, + [CONFIG_POWER_DOMAIN_SYSTOP_CHILD_DPU0TOP] = { + .name = "DPU0TOP", + .data = &((struct mod_power_domain_element_config) { + .attributes.pd_type = MOD_PD_TYPE_DEVICE, + .driver_id = FWK_ID_ELEMENT_INIT( + FWK_MODULE_IDX_VPPU, PPU_V0_ELEMENT_IDX_DPU0TOP), + .api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_VPPU, 0), + .allowed_state_mask_table = toplevel_allowed_state_mask_table, + .allowed_state_mask_table_size = + FWK_ARRAY_SIZE(toplevel_allowed_state_mask_table) + }), + }, + [CONFIG_POWER_DOMAIN_SYSTOP_CHILD_DPU1TOP] = { + .name = "DPU1TOP", + .data = &((struct mod_power_domain_element_config) { + .attributes.pd_type = MOD_PD_TYPE_DEVICE, + .driver_id = FWK_ID_ELEMENT_INIT( + FWK_MODULE_IDX_VPPU, PPU_V0_ELEMENT_IDX_DPU1TOP), + .api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_VPPU, 0), + .allowed_state_mask_table = toplevel_allowed_state_mask_table, + .allowed_state_mask_table_size = + FWK_ARRAY_SIZE(toplevel_allowed_state_mask_table) + }), + }, + [CONFIG_POWER_DOMAIN_SYSTOP_CHILD_GPUTOP] = { + .name = "GPUTOP", + .data = &((struct mod_power_domain_element_config) { + .attributes.pd_type = MOD_PD_TYPE_DEVICE, + .driver_id = FWK_ID_ELEMENT_INIT( + FWK_MODULE_IDX_VPPU, PPU_V0_ELEMENT_IDX_GPUTOP), + .api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_VPPU, 0), + .allowed_state_mask_table = toplevel_allowed_state_mask_table, + .allowed_state_mask_table_size = + FWK_ARRAY_SIZE(toplevel_allowed_state_mask_table) + }), + }, + [CONFIG_POWER_DOMAIN_SYSTOP_CHILD_VPUTOP] = { + .name = "VPUTOP", + .data = &((struct mod_power_domain_element_config) { + .attributes.pd_type = MOD_PD_TYPE_DEVICE, + .driver_id = FWK_ID_ELEMENT_INIT( + FWK_MODULE_IDX_VPPU, PPU_V0_ELEMENT_IDX_VPUTOP), + .api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_VPPU, 0), + .allowed_state_mask_table = toplevel_allowed_state_mask_table, + .allowed_state_mask_table_size = + FWK_ARRAY_SIZE(toplevel_allowed_state_mask_table) + }), + }, + [CONFIG_POWER_DOMAIN_SYSTOP_CHILD_COUNT] = { + .name = "SYSTOP", + .data = &((struct mod_power_domain_element_config) { + .parent_idx = UINT32_MAX, + .attributes.pd_type = MOD_PD_TYPE_DEVICE, + .driver_id = FWK_ID_ELEMENT_INIT( + FWK_MODULE_IDX_VPPU, PPU_V0_ELEMENT_IDX_SYSTEM), + .api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_VPPU, 0), + .allowed_state_mask_table = toplevel_allowed_state_mask_table, + .allowed_state_mask_table_size = + FWK_ARRAY_SIZE(toplevel_allowed_state_mask_table) + }), + }, +}; + +/* + * Function definitions with internal linkage + */ +static const struct fwk_element *fvp_power_domain_get_element_table + (fwk_id_t module_id) +{ + const struct fwk_element *element_table; + + element_table = create_power_domain_element_table( + 4, + 2, + FWK_MODULE_IDX_VPPU, + 0, + core_pd_allowed_state_mask_table, + FWK_ARRAY_SIZE(core_pd_allowed_state_mask_table), + cluster_pd_allowed_state_mask_table, + FWK_ARRAY_SIZE(cluster_pd_allowed_state_mask_table), + fvp_power_domain_static_element_table, + FWK_ARRAY_SIZE(fvp_power_domain_static_element_table)); + + return element_table; +} + +/* + * Power module configuration data + */ +struct fwk_module_config config_power_domain = { + .data = &fvp_power_domain_config, + .elements = FWK_MODULE_DYNAMIC_ELEMENTS(fvp_power_domain_get_element_table), +}; diff --git a/product/host-input/fw/config_power_domain.h b/product/host-input/fw/config_power_domain.h new file mode 100644 index 0000000000000000000000000000000000000000..d3a1d91430b89ed48e11bd0e3d2d56e69534cd9f --- /dev/null +++ b/product/host-input/fw/config_power_domain.h @@ -0,0 +1,20 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CONFIG_POWER_DOMAIN_H +#define CONFIG_POWER_DOMAIN_H + +enum systop_child_index { + CONFIG_POWER_DOMAIN_SYSTOP_CHILD_DBGTOP, + CONFIG_POWER_DOMAIN_SYSTOP_CHILD_DPU0TOP, + CONFIG_POWER_DOMAIN_SYSTOP_CHILD_DPU1TOP, + CONFIG_POWER_DOMAIN_SYSTOP_CHILD_GPUTOP, + CONFIG_POWER_DOMAIN_SYSTOP_CHILD_VPUTOP, + CONFIG_POWER_DOMAIN_SYSTOP_CHILD_COUNT +}; + +#endif /* CONFIG_POWER_DOMAIN_H */ diff --git a/product/host-input/fw/config_ppu_v0.c b/product/host-input/fw/config_ppu_v0.c new file mode 100644 index 0000000000000000000000000000000000000000..6ad6117db7d926b4d87207274dc35197d859d00b --- /dev/null +++ b/product/host-input/fw/config_ppu_v0.c @@ -0,0 +1,156 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include "config_ppu_v0.h" + +uint32_t vppu_regdbg[16]; +uint32_t vppu_regdpu0[16]; +uint32_t vppu_regdpu1[16]; +uint32_t vppu_reggpu[16]; +uint32_t vppu_regvpu[16]; +uint32_t vppu_regsys0[16]; +uint32_t vppu_regsys1[16]; +uint32_t vppu_regcluster[16]; +uint32_t vppu_regsys[16]; + +static struct fwk_element host_ppu_v0_element_table[] = { + [PPU_V0_ELEMENT_IDX_CPU0] = { + .name = "CPU0", + .data = &((struct mod_ppu_v0_pd_config) { + .pd_type = MOD_PD_TYPE_DEVICE, + .ppu.reg_base = (uintptr_t)vppu_regcluster, + .ppu.irq = PPU_SYS1_IRQ + }), + }, + [PPU_V0_ELEMENT_IDX_CPU1] = { + .name = "CPU1", + .data = &((struct mod_ppu_v0_pd_config) { + .pd_type = MOD_PD_TYPE_DEVICE, + .ppu.reg_base = (uintptr_t)vppu_regcluster, + .ppu.irq = PPU_SYS1_IRQ + }), + }, + [PPU_V0_ELEMENT_IDX_CPU2] = { + .name = "CPU2", + .data = &((struct mod_ppu_v0_pd_config) { + .pd_type = MOD_PD_TYPE_DEVICE, + .ppu.reg_base = (uintptr_t)vppu_regcluster, + .ppu.irq = PPU_SYS1_IRQ + }), + }, + [PPU_V0_ELEMENT_IDX_CPU3] = { + .name = "CPU3", + .data = &((struct mod_ppu_v0_pd_config) { + .pd_type = MOD_PD_TYPE_DEVICE, + .ppu.reg_base = (uintptr_t)vppu_regcluster, + .ppu.irq = PPU_SYS1_IRQ + }), + }, + [PPU_V0_ELEMENT_IDX_CLUSTER0] = { + .name = "CLUSTER0", + .data = &((struct mod_ppu_v0_pd_config) { + .pd_type = MOD_PD_TYPE_DEVICE, + .ppu.reg_base = (uintptr_t)vppu_regcluster, + .ppu.irq = PPU_SYS1_IRQ + }), + }, + [PPU_V0_ELEMENT_IDX_CLUSTER1] = { + .name = "CLUSTER1", + .data = &((struct mod_ppu_v0_pd_config) { + .pd_type = MOD_PD_TYPE_DEVICE, + .ppu.reg_base = (uintptr_t)vppu_regcluster, + .ppu.irq = PPU_SYS1_IRQ + }), + }, + [PPU_V0_ELEMENT_IDX_DBGTOP] = { + .name = "DBGTOP", + .data = &((struct mod_ppu_v0_pd_config) { + .pd_type = MOD_PD_TYPE_DEVICE_DEBUG, + .ppu.reg_base = (uintptr_t)vppu_regdbg, + .ppu.irq = PPU_DEBUG_IRQ + }), + }, + [PPU_V0_ELEMENT_IDX_DPU0TOP] = { + .name = "DPU0TOP", + .data = &((struct mod_ppu_v0_pd_config) { + .pd_type = MOD_PD_TYPE_DEVICE, + .ppu.reg_base = (uintptr_t)vppu_regdpu0, + .ppu.irq = PPU_DPU0_IRQ, + .default_power_on = true, + }), + }, + [PPU_V0_ELEMENT_IDX_DPU1TOP] = { + .name = "DPU1TOP", + .data = &((struct mod_ppu_v0_pd_config) { + .pd_type = MOD_PD_TYPE_DEVICE, + .ppu.reg_base = (uintptr_t)vppu_regdpu1, + .ppu.irq = PPU_DPU1_IRQ, + .default_power_on = true, + }), + }, + [PPU_V0_ELEMENT_IDX_GPUTOP] = { + .name = "GPUTOP", + .data = &((struct mod_ppu_v0_pd_config) { + .pd_type = MOD_PD_TYPE_DEVICE, + .ppu.reg_base = (uintptr_t)vppu_reggpu, + .ppu.irq = PPU_GPU_IRQ, + .default_power_on = true, + }), + }, + [PPU_V0_ELEMENT_IDX_VPUTOP] = { + .name = "VPUTOP", + .data = &((struct mod_ppu_v0_pd_config) { + .pd_type = MOD_PD_TYPE_DEVICE, + .ppu.reg_base = (uintptr_t)vppu_regvpu, + .ppu.irq = PPU_VPU_IRQ, + .default_power_on = true, + }), + }, + [PPU_V0_ELEMENT_IDX_SYS0] = { + .name = "SYS0", + .data = &((struct mod_ppu_v0_pd_config) { + .pd_type = MOD_PD_TYPE_SYSTEM, + .ppu.reg_base = (uintptr_t)vppu_regsys0, + .ppu.irq = PPU_SYS0_IRQ + }), + }, + [PPU_V0_ELEMENT_IDX_SYS1] = { + .name = "SYS1", + .data = &((struct mod_ppu_v0_pd_config) { + .pd_type = MOD_PD_TYPE_SYSTEM, + .ppu.reg_base = (uintptr_t)vppu_regsys1, + .ppu.irq = PPU_SYS1_IRQ + }), + }, + [PPU_V0_ELEMENT_IDX_SYSTEM] = { + .name = "SYSTEM", + .data = &((struct mod_ppu_v0_pd_config) { + .pd_type = MOD_PD_TYPE_DEVICE, + .ppu.reg_base = (uintptr_t)vppu_regsys, + .ppu.irq = PPU_SYS1_IRQ, + .default_power_on = true, + }), + }, + [PPU_V0_ELEMENT_IDX_COUNT] = { 0 }, /* Termination entry */ +}; + + +static const struct fwk_element *host_ppu_v0_get_element_table + (fwk_id_t module_id) +{ + return host_ppu_v0_element_table; +} + +/* + * Power module configuration data + */ +struct fwk_module_config config_vppu = { + .elements = FWK_MODULE_DYNAMIC_ELEMENTS(host_ppu_v0_get_element_table), +}; diff --git a/product/host-input/fw/config_ppu_v0.h b/product/host-input/fw/config_ppu_v0.h new file mode 100644 index 0000000000000000000000000000000000000000..3f70a1d6add58144f89f81f69236da7398efba4c --- /dev/null +++ b/product/host-input/fw/config_ppu_v0.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 CONFIG_PPU_V0_H +#define CONFIG_PPU_V0_H + +enum ppu_v0_element_idx { + PPU_V0_ELEMENT_IDX_CPU0, + PPU_V0_ELEMENT_IDX_CPU1, + PPU_V0_ELEMENT_IDX_CPU2, + PPU_V0_ELEMENT_IDX_CPU3, + PPU_V0_ELEMENT_IDX_CLUSTER0, + PPU_V0_ELEMENT_IDX_CLUSTER1, + PPU_V0_ELEMENT_IDX_DBGTOP, + PPU_V0_ELEMENT_IDX_DPU0TOP, + PPU_V0_ELEMENT_IDX_DPU1TOP, + PPU_V0_ELEMENT_IDX_GPUTOP, + PPU_V0_ELEMENT_IDX_VPUTOP, + PPU_V0_ELEMENT_IDX_SYS0, + PPU_V0_ELEMENT_IDX_SYS1, + PPU_V0_ELEMENT_IDX_SYSTEM, + PPU_V0_ELEMENT_IDX_COUNT +}; + +#endif /* CONFIG_PPU_V0_H */ diff --git a/product/host-input/fw/config_psu.c b/product/host-input/fw/config_psu.c new file mode 100644 index 0000000000000000000000000000000000000000..6ad0595cbc23de700e7f50dae6393643f608fbd1 --- /dev/null +++ b/product/host-input/fw/config_psu.c @@ -0,0 +1,56 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + +static const struct fwk_element element_table[] = { + { + .name = "CPU_GROUP_LITTLE", + .data = &(const struct mod_psu_element_cfg) { + .driver_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_MOCK_PSU, 0), + .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_MOCK_PSU, + MOD_MOCK_PSU_API_IDX_DRIVER) + }, + }, + { + .name = "CPU_GROUP_BIG", + .data = &(const struct mod_psu_element_cfg) { + .driver_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_MOCK_PSU, 1), + .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_MOCK_PSU, + MOD_MOCK_PSU_API_IDX_DRIVER) + }, + }, + { + .name = "GPU", + .data = &(const struct mod_psu_element_cfg) { + .driver_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_MOCK_PSU, 2), + .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_MOCK_PSU, + MOD_MOCK_PSU_API_IDX_DRIVER) + }, + }, + { + .name = "VPU", + .data = &(const struct mod_psu_element_cfg) { + .driver_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_MOCK_PSU, 3), + .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_MOCK_PSU, + MOD_MOCK_PSU_API_IDX_DRIVER) + }, + }, + { 0 } +}; + +static const struct fwk_element *psu_get_element_table(fwk_id_t module_id) +{ + return element_table; +} + +struct fwk_module_config config_psu = { + .elements = FWK_MODULE_DYNAMIC_ELEMENTS(psu_get_element_table), +}; diff --git a/product/host-input/fw/config_reg_sensor.h b/product/host-input/fw/config_reg_sensor.h new file mode 100644 index 0000000000000000000000000000000000000000..60359a6aa527fde82ea2f05068c67e20b8d528f1 --- /dev/null +++ b/product/host-input/fw/config_reg_sensor.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 CONFIG_SENSOR_H +#define CONFIG_SENSOR_H + +enum SENSOR_DEVICES { + SENSOR_DEV_SOC_TEMP, + SENSOR_DEV_DDR_TEMP, + SENSOR_DEV_COUNT, +}; + +#endif /* CONFIG_PPU_V0_H */ diff --git a/product/host-input/fw/config_scmi.c b/product/host-input/fw/config_scmi.c new file mode 100644 index 0000000000000000000000000000000000000000..bb2ea9d9110469689ee60a00f33ecb059c55882c --- /dev/null +++ b/product/host-input/fw/config_scmi.c @@ -0,0 +1,122 @@ +/* + * 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 + +static const struct fwk_element service_table[] = { + [SCMI_SERVICE_IDX_PSCI] = { + .name = "agent PSCI", + .data = &((struct mod_scmi_service_config) { + .transport_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_MSG_SMT, + SCMI_SERVICE_IDX_PSCI), + .transport_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_MSG_SMT, + MOD_MSG_SMT_API_IDX_SCMI_TRANSPORT), + .scmi_agent_id = SCMI_AGENT_ID_PSCI, + .transport_notification_init_id = FWK_ID_NONE_INIT, + .scmi_p2a_id = FWK_ID_NONE_INIT, + }), + }, + [SCMI_SERVICE_IDX_OSPM_0] = { + .name = "agent OSPM0", + .data = &((struct mod_scmi_service_config) { + .transport_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_MSG_SMT, + SCMI_SERVICE_IDX_OSPM_0), + .transport_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_MSG_SMT, + MOD_MSG_SMT_API_IDX_SCMI_TRANSPORT), + .scmi_agent_id = SCMI_AGENT_ID_OSPM, + .transport_notification_init_id = FWK_ID_NONE_INIT, +#ifdef BUILD_HAS_SCMI_NOTIFICATIONS + .scmi_p2a_id = FWK_ID_ELEMENT_INIT( + FWK_MODULE_IDX_SCMI, + SCMI_SERVICE_IDX_OSPM_0_P2A), +#else + .scmi_p2a_id = FWK_ID_NONE_INIT, +#endif + }), + }, + [SCMI_SERVICE_IDX_OSPM_1] = { + .name = "agent OSPM1", + .data = &((struct mod_scmi_service_config) { + .transport_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_MSG_SMT, + SCMI_SERVICE_IDX_OSPM_1), + .transport_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_MSG_SMT, + MOD_MSG_SMT_API_IDX_SCMI_TRANSPORT), + .scmi_agent_id = SCMI_AGENT_ID_PERF, + .transport_notification_init_id = FWK_ID_NONE_INIT, +#ifdef BUILD_HAS_SCMI_NOTIFICATIONS + .scmi_p2a_id = FWK_ID_ELEMENT_INIT( + FWK_MODULE_IDX_SCMI, + SCMI_SERVICE_IDX_OSPM_1_P2A), +#else + .scmi_p2a_id = FWK_ID_NONE_INIT, +#endif + }), + }, +#ifdef BUILD_HAS_SCMI_NOTIFICATIONS + [SCMI_SERVICE_IDX_OSPM_0_P2A] = { + .name = "agent OSPM0 P2A", + .data = &((struct mod_scmi_service_config) { + .transport_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_MSG_SMT, + SCMI_SERVICE_IDX_OSPM_0_P2A), + .transport_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_MSG_SMT, + MOD_MSG_SMT_API_IDX_SCMI_TRANSPORT), + .scmi_agent_id = SCMI_AGENT_ID_OSPM, + .transport_notification_init_id = FWK_ID_NONE_INIT, + .scmi_p2a_id = FWK_ID_NONE_INIT, + }), + }, + [SCMI_SERVICE_IDX_OSPM_1_P2A] = { + .name = "agent OSPM1 P2A", + .data = &((struct mod_scmi_service_config) { + .transport_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_MSG_SMT, + SCMI_SERVICE_IDX_OSPM_1_P2A), + .transport_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_MSG_SMT, + MOD_MSG_SMT_API_IDX_SCMI_TRANSPORT), + .scmi_agent_id = SCMI_AGENT_ID_OSPM, + .transport_notification_init_id = FWK_ID_NONE_INIT, + .scmi_p2a_id = FWK_ID_NONE_INIT, + }), + }, +#endif + [SCMI_SERVICE_IDX_COUNT] = { 0 } +}; + +static const struct fwk_element *get_service_table(fwk_id_t module_id) +{ + return service_table; +} + +static const struct mod_scmi_agent agent_table[] = { + [SCMI_AGENT_ID_OSPM] = { + .type = SCMI_AGENT_TYPE_OSPM, + .name = "OSPM", + }, + [SCMI_AGENT_ID_PSCI] = { + .type = SCMI_AGENT_TYPE_PSCI, + .name = "PSCI", + }, + [SCMI_AGENT_ID_PERF] = { + .type = SCMI_AGENT_TYPE_OSPM, + .name = "PERF", + }, +}; + +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_service_table), +}; diff --git a/product/host-input/fw/config_scmi_clock.c b/product/host-input/fw/config_scmi_clock.c new file mode 100644 index 0000000000000000000000000000000000000000..d2eb353badacb3f6dcf28796389114df6de2c26d --- /dev/null +++ b/product/host-input/fw/config_scmi_clock.c @@ -0,0 +1,98 @@ +/* + * 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 "clock_devices.h" + +static const struct mod_scmi_clock_device agent_device_table_ospm[] = { + { + /* MOCK_0 */ + .element_id = + FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_CLOCK, CLOCK_DEV_IDX_MOCK_0), + }, + { + /* MOCK_1 */ + .element_id = + FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_CLOCK, CLOCK_DEV_IDX_MOCK_1), + }, + { + /* VPU */ + .element_id = + FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_CLOCK, CLOCK_DEV_IDX_VPU), + }, + { + /* MOCK_3 */ + .element_id = + FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_CLOCK, CLOCK_DEV_IDX_MOCK_3), + }, + { + /* DPU */ + .element_id = + FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_CLOCK, CLOCK_DEV_IDX_DPU), + }, + { + /* PIXEL_0 */ + .element_id = + FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_CLOCK, CLOCK_DEV_IDX_PIXEL_0), + }, + { + /* PIXEL_1 */ + .element_id = + FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_CLOCK, CLOCK_DEV_IDX_PIXEL_1), + }, +}; + +static const struct mod_scmi_clock_device agent_device_table_perf[] = { + { + /* MOCK_0 */ + .element_id = + FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_CLOCK, CLOCK_DEV_IDX_MOCK_0), + }, + { + /* MOCK_2 */ + .element_id = + FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_CLOCK, CLOCK_DEV_IDX_MOCK_2), + }, + { + /* MOCK_3 */ + .element_id = + FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_CLOCK, CLOCK_DEV_IDX_MOCK_3), + }, + { + /* PIXEL_0 */ + .element_id = + FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_CLOCK, CLOCK_DEV_IDX_PIXEL_0), + }, + { + /* PIXEL_1 */ + .element_id = + FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_CLOCK, CLOCK_DEV_IDX_PIXEL_1), + }, +}; + +static const struct mod_scmi_clock_agent agent_table[SCMI_AGENT_ID_COUNT] = { + [SCMI_AGENT_ID_OSPM] = { + .device_table = agent_device_table_ospm, + .device_count = FWK_ARRAY_SIZE(agent_device_table_ospm), + }, + [SCMI_AGENT_ID_PSCI] = { 0 /* No access */ }, + [SCMI_AGENT_ID_PERF] = { + .device_table = agent_device_table_perf, + .device_count = FWK_ARRAY_SIZE(agent_device_table_perf), + }, +}; + +struct fwk_module_config config_scmi_clock = { + .data = &((struct mod_scmi_clock_config) { + .max_pending_transactions = 0, + .agent_table = agent_table, + .agent_count = FWK_ARRAY_SIZE(agent_table), + }), +}; diff --git a/product/host-input/fw/config_scmi_perf.c b/product/host-input/fw/config_scmi_perf.c new file mode 100644 index 0000000000000000000000000000000000000000..63ca90e7b4d620ac7cbdbd4e9207d37a81b751be --- /dev/null +++ b/product/host-input/fw/config_scmi_perf.c @@ -0,0 +1,31 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include "config_dvfs.h" + +static const struct mod_scmi_perf_domain_config domains[] = { + [DVFS_ELEMENT_IDX_LITTLE] = { + .fast_channels_addr_scp = 0x0, + }, + [DVFS_ELEMENT_IDX_BIG] = { + .fast_channels_addr_scp = 0x0, + }, + [DVFS_ELEMENT_IDX_GPU] = { + .fast_channels_addr_scp = 0x0, + }, +}; + +struct fwk_module_config config_scmi_perf = { + .data = &((struct mod_scmi_perf_config) { + .domains = &domains, + .perf_doms_count = FWK_ARRAY_SIZE(domains), + .fast_channels_alarm_id = FWK_ID_NONE_INIT, + }), +}; diff --git a/product/host-input/fw/config_scmi_power_domain.c b/product/host-input/fw/config_scmi_power_domain.c new file mode 100644 index 0000000000000000000000000000000000000000..0740409915e723032ae4852d7c97b20bd6018b28 --- /dev/null +++ b/product/host-input/fw/config_scmi_power_domain.c @@ -0,0 +1,11 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +/* No elements, no module configuration data */ +struct fwk_module_config config_scmi_power_domain = { 0 }; diff --git a/product/host-input/fw/config_sensor.c b/product/host-input/fw/config_sensor.c new file mode 100644 index 0000000000000000000000000000000000000000..20826868113ed5e5d3e217c9db21e050e6437072 --- /dev/null +++ b/product/host-input/fw/config_sensor.c @@ -0,0 +1,100 @@ +/* + * 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 "config_reg_sensor.h" + +uint64_t soc_temp[3] = {25000, 25000, 25000}; +uint64_t ddr_temp[1] = {25000}; +/* + * Register Sensor driver config + */ +static struct mod_sensor_info info_soc_temperature = { + .type = MOD_SENSOR_TYPE_DEGREES_C, + .update_interval = 0, + .update_interval_multiplier = 0, + .unit_multiplier = -3, +}; + +static const struct fwk_element reg_sensor_element_table[] = { + [SENSOR_DEV_SOC_TEMP] = { + .name = "Soc Temperature", + .data = &((struct mod_reg_sensor_dev_config) { + .reg = (uintptr_t)(soc_temp), + .info = &info_soc_temperature, + }), + }, + [SENSOR_DEV_DDR_TEMP] = { + .name = "DDR Temperature", + .data = &((struct mod_reg_sensor_dev_config) { + .reg = (uintptr_t)(ddr_temp), + .info = &info_soc_temperature, + }), + }, + [SENSOR_DEV_COUNT] = { 0 }, +}; + +static const struct fwk_element *get_reg_sensor_element_table(fwk_id_t id) +{ + return reg_sensor_element_table; +} + +struct fwk_module_config config_reg_sensor = { + .elements = FWK_MODULE_DYNAMIC_ELEMENTS(get_reg_sensor_element_table), +}; + +/* + * Sensor module config + */ +static const struct fwk_element sensor_element_table[] = { + [0] = { + .name = "Soc Temperature", + .data = &((const struct mod_sensor_dev_config) { + .driver_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_REG_SENSOR, + SENSOR_DEV_SOC_TEMP), + .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_REG_SENSOR, 0), + .trip_point = { + .count = 2, + } + }), + }, + [1] = { + .name = "DDR Temperature", + .data = &((const struct mod_sensor_dev_config) { + .driver_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_REG_SENSOR, + SENSOR_DEV_DDR_TEMP), + .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_REG_SENSOR, 0), + .trip_point = { + .count = 2, + } + }), + }, + [2] = { 0 }, +}; + +static const struct fwk_element *get_sensor_element_table(fwk_id_t module_id) +{ + return sensor_element_table; +} +static const struct mod_sensor_config sensor_config = { +#ifdef BUILD_HAS_SCMI_NOTIFICATIONS + .notification_id = FWK_ID_MODULE_INIT(FWK_MODULE_IDX_SCMI_SENSOR), + .trip_point_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_SCMI_SENSOR, + SCMI_SENSOR_API_IDX_TRIP_POINT), +#else + .notification_id = FWK_ID_NONE_INIT +#endif +}; + +struct fwk_module_config config_sensor = { + .elements = FWK_MODULE_DYNAMIC_ELEMENTS(get_sensor_element_table), + .data = &sensor_config, +}; diff --git a/product/host-input/fw/config_vpll.c b/product/host-input/fw/config_vpll.c new file mode 100644 index 0000000000000000000000000000000000000000..78874a888bb8633437c5bec1995be26f8b284e03 --- /dev/null +++ b/product/host-input/fw/config_vpll.c @@ -0,0 +1,108 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +uint32_t ctrl_reg[7]; + +static const struct fwk_element system_pll_element_table[] = { + { + .name = "CPU_PLL_0", + .data = &((struct mod_system_pll_dev_config) { + .control_reg = &ctrl_reg[0], + .lock_flag_mask = PLL_STATUS1_CPUPLLLOCK(0, 0), + .initial_rate = 1330 * FWK_MHZ, + .min_rate = MOD_SYSTEM_PLL_MIN_RATE, + .max_rate = MOD_SYSTEM_PLL_MAX_RATE, + .min_step = MOD_SYSTEM_PLL_MIN_INTERVAL, + .defer_initialization = false, + }), + }, + { + .name = "CPU_PLL_1", + .data = &((struct mod_system_pll_dev_config) { + .control_reg = &ctrl_reg[1], + .lock_flag_mask = PLL_STATUS1_CPUPLLLOCK(0, 1), + .initial_rate = 1750 * FWK_MHZ, + .min_rate = MOD_SYSTEM_PLL_MIN_RATE, + .max_rate = MOD_SYSTEM_PLL_MAX_RATE, + .min_step = MOD_SYSTEM_PLL_MIN_INTERVAL, + .defer_initialization = false, + }), + }, + { + .name = "GPU_PLL", + .data = &((struct mod_system_pll_dev_config) { + .control_reg = &ctrl_reg[2], + .lock_flag_mask = PLL_STATUS0_GPUPLLLOCK, + .initial_rate = 600 * FWK_MHZ, + .min_rate = MOD_SYSTEM_PLL_MIN_RATE, + .max_rate = MOD_SYSTEM_PLL_MAX_RATE, + .min_step = MOD_SYSTEM_PLL_MIN_INTERVAL, + .defer_initialization = false, + }), + }, + { + .name = "DPU_PLL", + .data = &((struct mod_system_pll_dev_config) { + .control_reg = &ctrl_reg[3], + .lock_flag_mask = PLL_STATUS0_DISPLAYPLLLOCK, + .initial_rate = 260 * FWK_MHZ, + .min_rate = MOD_SYSTEM_PLL_MIN_RATE, + .max_rate = MOD_SYSTEM_PLL_MAX_RATE, + .min_step = MOD_SYSTEM_PLL_MIN_INTERVAL, + .defer_initialization = false, + }), + }, + { + .name = "VPU_PLL", + .data = &((struct mod_system_pll_dev_config) { + .control_reg = &ctrl_reg[4], + .lock_flag_mask = PLL_STATUS0_VIDEOPLLLOCK, + .initial_rate = 600 * FWK_MHZ, + .min_rate = MOD_SYSTEM_PLL_MIN_RATE, + .max_rate = MOD_SYSTEM_PLL_MAX_RATE, + .min_step = MOD_SYSTEM_PLL_MIN_INTERVAL, + .defer_initialization = false, + }), + }, + { + .name = "PIX0_PLL", + .data = &((struct mod_system_pll_dev_config) { + .control_reg = &ctrl_reg[5], + .initial_rate = 594 * FWK_MHZ, + .min_rate = 12500 * FWK_KHZ, + .max_rate = 594 * FWK_MHZ, + .min_step = 250 * FWK_KHZ, + .defer_initialization = false, + }), + }, + { + .name = "PIX1_PLL", + .data = &((struct mod_system_pll_dev_config) { + .control_reg = &ctrl_reg[6], + .initial_rate = 594 * FWK_MHZ, + .min_rate = 12500 * FWK_KHZ, + .max_rate = 594 * FWK_MHZ, + .min_step = 250 * FWK_KHZ, + .defer_initialization = false, + }), + }, + { 0 }, /* Termination description. */ +}; + +static const struct fwk_element *system_pll_get_element_table + (fwk_id_t module_id) +{ + return system_pll_element_table; +} + +struct fwk_module_config config_system_pll = { + .elements = FWK_MODULE_DYNAMIC_ELEMENTS(system_pll_get_element_table), +}; diff --git a/product/host-input/include/fake_irq.h b/product/host-input/include/fake_irq.h new file mode 100644 index 0000000000000000000000000000000000000000..75e53e5d8b5b56880e34f50a51e99a639c45b043 --- /dev/null +++ b/product/host-input/include/fake_irq.h @@ -0,0 +1,178 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SGM775_IRQ_H +#define SGM775_IRQ_H + +#include + +#define WDOG_IRQ FWK_INTERRUPT_NMI /* SCP Watchdog (SP805) */ + +enum sgm775_irq { + TIM32KHZ_IRQ = 0, /* 32KHz Physical Timer */ + CDBG_PWR_UP_REQ_IRQ = 1, /* Coresight Debug Power Request */ + CSYS_PWR_UP_REQ_IRQ = 2, /* Coresight System Power Request */ + CDBG_RST_REQ_IRQ = 3, /* Coresight Debug Reset Request */ + GIC_EXT_WAKEUP_IRQ = 4, /* External GIC Wakeup Request */ + RESERVED5_IRQ = 5, /* Reserved */ + RESERVED6_IRQ = 6, /* Reserved */ + RESERVED7_IRQ = 7, /* Reserved */ + RESERVED8_IRQ = 8, /* Reserved */ + RESERVED9_IRQ = 9, /* Reserved */ + RESERVED10_IRQ = 10, /* Reserved */ + RESERVED11_IRQ = 11, /* Reserved */ + RESERVED12_IRQ = 12, /* Reserved */ + RESERVED13_IRQ = 13, /* Reserved */ + RESERVED14_IRQ = 14, /* Reserved */ + RESERVED15_IRQ = 15, /* Reserved */ + SOC_WAKEUP0_IRQ = 16, /* SoC Expansion Wakeup */ + SOC_WAKEUP1_IRQ = 17, /* SoC Expansion Wakeup */ + SOC_WAKEUP2_IRQ = 18, /* SoC Expansion Wakeup */ + SOC_WAKEUP3_IRQ = 19, /* SoC Expansion Wakeup */ + SOC_WAKEUP4_IRQ = 20, /* SoC Expansion Wakeup */ + SOC_WAKEUP5_IRQ = 21, /* SoC Expansion Wakeup */ + SOC_WAKEUP6_IRQ = 22, /* SoC Expansion Wakeup */ + SOC_WAKEUP7_IRQ = 23, /* SoC Expansion Wakeup */ + SOC_WAKEUP8_IRQ = 24, /* SoC Expansion Wakeup */ + SOC_WAKEUP9_IRQ = 25, /* SoC Expansion Wakeup */ + SOC_WAKEUP10_IRQ = 26, /* SoC Expansion Wakeup */ + SOC_WAKEUP11_IRQ = 27, /* SoC Expansion Wakeup */ + SOC_WAKEUP12_IRQ = 28, /* SoC Expansion Wakeup */ + SOC_WAKEUP13_IRQ = 29, /* SoC Expansion Wakeup */ + SOC_WAKEUP14_IRQ = 30, /* SoC Expansion Wakeup */ + SOC_WAKEUP15_IRQ = 31, /* SoC Expansion Wakeup */ + PPU_SCP_IRQ = 32, /* SCP Power Policy Unit */ + TIMREFCLK_IRQ = 33, /* REFCLK Physical Timer */ + MHU_HIGH_PRIO_IRQ = 34, /* MHU High Priority */ + MHU_LOW_PRIO_IRQ = 35, /* MHU Low Priority */ + MHU_SECURE_IRQ = 36, /* MHU Secure */ + CTI_TRIGGER0_IRQ = 37, /* SCP CTI Trigger */ + CTI_TRIGGER1_IRQ = 38, /* SCP CTI Trigger */ + GIC_ERROR_ECC_IRQ = 39, /* GIC Error (ECC Fatal) */ + GIC_ERROR_AXIM_IRQ = 40, /* GIC Error (AXIM) */ + DMC_RESERVED0_IRQ = 41, /* DMC, Reserved */ + DMC_0_ERROR_ECC_IRQ = 42, /* DMC0 Combined ECC Error */ + DMC_0_ERROR_ACCESS_IRQ = 43, /* DMC0 Combined Misc Access Error */ + DMC_RESERVED1_IRQ = 44, /* DMC, Reserved */ + DMC_RESERVED2_IRQ = 45, /* DMC, Reserved */ + DMC_1_ERROR_ECC_IRQ = 46, /* DMC1 Combined ECC Error */ + DMC_1_ERROR_ACCESS_IRQ = 47, /* DMC1 Combined Misc Access Error */ + DMC_RESERVED3_IRQ = 48, /* DMC, Reserved */ + DMC_RESERVED4_IRQ = 49, /* DMC, Reserved */ + DMC_2_ERROR_ECC_IRQ = 50, /* DMC2 Combined ECC Error */ + DMC_2_ERROR_ACCESS_IRQ = 51, /* DMC2 Combined Misc Access Error */ + DMC_RESERVED5_IRQ = 52, /* DMC, Reserved */ + DMC_RESERVED6_IRQ = 53, /* DMC, Reserved */ + DMC_3_ERROR_ECC_IRQ = 54, /* DMC3 Combined ECC Error */ + DMC_3_ERROR_ACCESS_IRQ = 55, /* DMC3 Combined Misc Access Error */ + DMC_RESERVED7_IRQ = 56, /* DMC, Reserved */ + RESERVED57_IRQ = 57, /* Reserved */ + RESERVED58_IRQ = 58, /* Reserved */ + RESERVED59_IRQ = 59, /* Reserved */ + RESERVED60_IRQ = 60, /* Reserved */ + RESERVED61_IRQ = 61, /* Reserved */ + RESERVED62_IRQ = 62, /* Reserved */ + RESERVED63_IRQ = 63, /* Reserved */ + PPU_CLUS0CORE0_IRQ = 64, /* Cluster 0 Core 0 Power Policy Unit */ + PPU_CLUS0CORE1_IRQ = 65, /* Cluster 0 Core 1 Power Policy Unit */ + PPU_CLUS0CORE2_IRQ = 66, /* Cluster 0 Core 2 Power Policy Unit */ + PPU_CLUS0CORE3_IRQ = 67, /* Cluster 0 Core 3 Power Policy Unit */ + PPU_CLUS0_IRQ = 68, /* Cluster 0 Power Policy Unit */ + PPU_CLUS1CORE0_IRQ = 69, /* Cluster 1 Core 0 Power Policy Unit */ + PPU_CLUS1CORE1_IRQ = 70, /* Cluster 1 Core 1 Power Policy Unit */ + PPU_CLUS1CORE2_IRQ = 71, /* Cluster 1 Core 2 Power Policy Unit */ + PPU_CLUS1CORE3_IRQ = 72, /* Cluster 1 Core 3 Power Policy Unit */ + PPU_CLUS1_IRQ = 73, /* Cluster 1 Power Policy Unit */ + PPU_SYS0_IRQ = 74, /* System Power Policy Unit 0 */ + PPU_SYS1_IRQ = 75, /* System Power Policy Unit 1 */ + PPU_GPU_IRQ = 76, /* GPU Power Policy Unit */ + PPU_VPU_IRQ = 77, /* Video Power Policy Unit */ + RESERVED78_IRQ = 78, /* Reserved */ + PPU_DPU0_IRQ = 79, /* Display Power Policy Unit 0 */ + PPU_DPU1_IRQ = 80, /* Display Power Policy Unit 1 */ + PPU_DEBUG_IRQ = 81, /* DBGSYS Power Policy Unit */ + RESERVED82_IRQ = 82, /* Reserved */ + RESERVED83_IRQ = 83, /* Reserved */ + RESERVED84_IRQ = 84, /* Reserved */ + RESERVED85_IRQ = 85, /* Reserved */ + RESERVED86_IRQ = 86, /* Reserved */ + RESERVED87_IRQ = 87, /* Reserved */ + RESERVED88_IRQ = 88, /* Reserved */ + RESERVED89_IRQ = 89, /* Reserved */ + PPU_CLUS0CORE4_IRQ = 90, /* Cluster 0 Core 4 Power Policy Unit */ + PPU_CLUS0CORE5_IRQ = 91, /* Cluster 0 Core 5 Power Policy Unit */ + PPU_CLUS0CORE6_IRQ = 92, /* Cluster 0 Core 6 Power Policy Unit */ + PPU_CLUS0CORE7_IRQ = 93, /* Cluster 0 Core 7 Power Policy Unit */ + PPU_CLUS1CORE4_IRQ = 94, /* Cluster 1 Core 4 Power Policy Unit */ + PPU_CLUS1CORE5_IRQ = 95, /* Cluster 1 Core 5 Power Policy Unit */ + PPU_CLUS1CORE6_IRQ = 96, /* Cluster 1 Core 6 Power Policy Unit */ + PPU_CLUS1CORE7_IRQ = 97, /* Cluster 1 Core 7 Power Policy Unit */ + PLL_CLUS0_LOCK_IRQ = 98, /* Cluster 0 CPU PLL Lock */ + PLL_CLUS1_LOCK_IRQ = 99, /* Cluster 1 CPU PLL Lock */ + PLL_GPU_LOCK_IRQ = 100, /* GPU PLL Lock */ + PLL_VPU_LOCK_IRQ = 101, /* Video PLL Lock */ + PLL_SYS_LOCK_IRQ = 102, /* System PLL Lock */ + PLL_DPU_LOCK_IRQ = 103, /* Display PLL Lock */ + PLL_CLUS0CORE0_IRQ = 104, /* Cluster 0 PLL0 Lock */ + PLL_CLUS0CORE1_IRQ = 105, /* Cluster 0 PLL1 Lock */ + PLL_CLUS0CORE2_IRQ = 106, /* Cluster 0 PLL2 Lock */ + PLL_CLUS0CORE3_IRQ = 107, /* Cluster 0 PLL3 Lock */ + PLL_CLUS0CORE4_IRQ = 108, /* Cluster 0 PLL4 Lock */ + PLL_CLUS0CORE5_IRQ = 109, /* Cluster 0 PLL5 Lock */ + PLL_CLUS0CORE6_IRQ = 110, /* Cluster 0 PLL6 Lock */ + PLL_CLUS0CORE7_IRQ = 111, /* Cluster 0 PLL7 Lock */ + PLL_CLUS1CORE0_IRQ = 112, /* Cluster 1 PLL0 Lock */ + PLL_CLUS1CORE1_IRQ = 113, /* Cluster 1 PLL1 Lock */ + PLL_CLUS1CORE2_IRQ = 114, /* Cluster 1 PLL2 Lock */ + PLL_CLUS1CORE3_IRQ = 115, /* Cluster 1 PLL3 Lock */ + PLL_CLUS1CORE4_IRQ = 116, /* Cluster 1 PLL4 Lock */ + PLL_CLUS1CORE5_IRQ = 117, /* Cluster 1 PLL5 Lock */ + PLL_CLUS1CORE6_IRQ = 118, /* Cluster 1 PLL6 Lock */ + PLL_CLUS1CORE7_IRQ = 119, /* Cluster 1 PLL7 Lock */ + RESERVED120_IRQ = 120, /* Reserved */ + RESERVED121_IRQ = 121, /* Reserved */ + RESERVED122_IRQ = 122, /* Reserved */ + RESERVED123_IRQ = 123, /* Reserved */ + RESERVED124_IRQ = 124, /* Reserved */ + RESERVED125_IRQ = 125, /* Reserved */ + RESERVED126_IRQ = 126, /* Reserved */ + RESERVED127_IRQ = 127, /* Reserved */ + SCP_EXT_INTR0_IRQ = 128, /* SCP Customer Extension */ + SCP_EXT_INTR1_IRQ = 129, /* SCP Customer Extension */ + SCP_EXT_INTR2_IRQ = 130, /* SCP Customer Extension */ + SCP_EXT_INTR3_IRQ = 131, /* SCP Customer Extension */ + SCP_EXT_INTR4_IRQ = 132, /* SCP Customer Extension */ + SCP_EXT_INTR5_IRQ = 133, /* SCP Customer Extension */ + SCP_EXT_INTR6_IRQ = 134, /* SCP Customer Extension */ + SCP_EXT_INTR7_IRQ = 135, /* SCP Customer Extension */ + SCP_EXT_INTR8_IRQ = 136, /* SCP Customer Extension */ + SCP_EXT_INTR9_IRQ = 137, /* SCP Customer Extension */ + SCP_EXT_INTR10_IRQ = 138, /* SCP Customer Extension */ + SCP_EXT_INTR11_IRQ = 139, /* SCP Customer Extension */ + SCP_EXT_INTR12_IRQ = 140, /* SCP Customer Extension */ + SCP_EXT_INTR13_IRQ = 141, /* SCP Customer Extension */ + SCP_EXT_INTR14_IRQ = 142, /* SCP Customer Extension */ + SCP_EXT_INTR15_IRQ = 143, /* SCP Customer Extension */ + SCP_EXT_INTR16_IRQ = 144, /* SCP Customer Extension */ + SCP_EXT_INTR17_IRQ = 145, /* SCP Customer Extension */ + SCP_EXT_INTR18_IRQ = 146, /* SCP Customer Extension */ + SCP_EXT_INTR19_IRQ = 147, /* SCP Customer Extension */ + SCP_EXT_INTR20_IRQ = 148, /* SCP Customer Extension */ + SCP_EXT_INTR21_IRQ = 149, /* SCP Customer Extension */ + SCP_EXT_INTR22_IRQ = 150, /* SCP Customer Extension */ + SCP_EXT_INTR23_IRQ = 151, /* SCP Customer Extension */ + SCP_EXT_INTR24_IRQ = 152, /* SCP Customer Extension */ + SCP_EXT_INTR25_IRQ = 153, /* SCP Customer Extension */ + SCP_EXT_INTR26_IRQ = 154, /* SCP Customer Extension */ + SCP_EXT_INTR27_IRQ = 155, /* SCP Customer Extension */ + SCP_EXT_INTR28_IRQ = 156, /* SCP Customer Extension */ + SCP_EXT_INTR29_IRQ = 157, /* SCP Customer Extension */ + SCP_EXT_INTR30_IRQ = 158, /* SCP Customer Extension */ + SCP_EXT_INTR31_IRQ = 159, /* SCP Customer Extension */ +}; + +#endif /* SGM775_IRQ_H */ diff --git a/product/host-input/include/fake_mmap.h b/product/host-input/include/fake_mmap.h new file mode 100644 index 0000000000000000000000000000000000000000..c3643fc6ccccc2c41d311ec594c5b245e0554179 --- /dev/null +++ b/product/host-input/include/fake_mmap.h @@ -0,0 +1,101 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SGM775_MMAP_H +#define SGM775_MMAP_H + +#include + +/* + * Top-level base addresses + */ +#define EXPANSION0_BASE UINT32_C(0x40000000) +#define PERIPHERAL_BASE UINT32_C(0x44000000) +#define POWER_PERIPHERAL_BASE UINT32_C(0x50000000) +#define SYS0_BASE UINT32_C(0x60000000) +#define SYS1_BASE UINT32_C(0xA0000000) +#define PPB_INTERNAL_BASE UINT32_C(0xE0000000) +#define PPB_EXTERNAL_BASE UINT32_C(0xE0040000) +#define EXPANSION1_BASE UINT32_C(0xE0100000) + +/* + * Peripherals + */ +#define REFCLK_CNTCTL_BASE (PERIPHERAL_BASE + 0x0000) +#define REFCLK_CNTBASE0_BASE (PERIPHERAL_BASE + 0x1000) +#define WDOG_BASE (PERIPHERAL_BASE + 0x6000) +#define S32K_CNTCONTROL_BASE (PERIPHERAL_BASE + 0x7000) +#define S32K_CNTCTL_BASE (PERIPHERAL_BASE + 0x8000) +#define S32K_CNTBASE0_BASE (PERIPHERAL_BASE + 0x9000) +#define CS_CNTCONTROL_BASE (PERIPHERAL_BASE + 0xA000) + +/* + * Power control peripherals + */ +#define PIK_SCP_BASE (POWER_PERIPHERAL_BASE + 0x00000) +#define PIK_DEBUG_BASE (POWER_PERIPHERAL_BASE + 0x20000) +#define SENSOR_DEBUG_BASE (POWER_PERIPHERAL_BASE + 0x30000) +#define PIK_SYSTEM_BASE (POWER_PERIPHERAL_BASE + 0x40000) +#define SENSOR_SYSTEM_BASE (POWER_PERIPHERAL_BASE + 0x50000) +#define PIK_CLUS0_BASE (POWER_PERIPHERAL_BASE + 0x60000) +#define SENSOR_CLUS0_BASE (POWER_PERIPHERAL_BASE + 0x70000) +#define PIK_CLUS1_BASE (POWER_PERIPHERAL_BASE + 0x80000) +#define SENSOR_CLUS1_BASE (POWER_PERIPHERAL_BASE + 0x90000) +#define PIK_GPU_BASE (POWER_PERIPHERAL_BASE + 0xA0000) +#define SENSOR_GPU_BASE (POWER_PERIPHERAL_BASE + 0xB0000) +#define PIK_VPU_BASE (POWER_PERIPHERAL_BASE + 0xC0000) +#define SENSOR_VPU_BASE (POWER_PERIPHERAL_BASE + 0xD0000) +#define PIK_DPU_BASE (POWER_PERIPHERAL_BASE + 0xE0000) +#define SENSOR_DPU_BASE (POWER_PERIPHERAL_BASE + 0xF0000) + +/* + * PPU base address + */ +#define PPU_SCP_BASE (PIK_SCP_BASE + 0x1000) +#define PPU_SYS0_BASE (PIK_SYSTEM_BASE + 0x1000) +#define PPU_SYS1_BASE (PIK_SYSTEM_BASE + 0x2000) +#define PPU_DEBUG_BASE (PIK_DEBUG_BASE + 0x1000) +#define PPU_CLUS0CORE0_BASE (PIK_CLUS0_BASE + 0x2000) +#define PPU_CLUS0CORE1_BASE (PIK_CLUS0_BASE + 0x3000) +#define PPU_CLUS0CORE2_BASE (PIK_CLUS0_BASE + 0x4000) +#define PPU_CLUS0CORE3_BASE (PIK_CLUS0_BASE + 0x5000) +#define PPU_CLUS0CORE4_BASE (PIK_CLUS0_BASE + 0x6000) +#define PPU_CLUS0CORE5_BASE (PIK_CLUS0_BASE + 0x7000) +#define PPU_CLUS0CORE6_BASE (PIK_CLUS0_BASE + 0x8000) +#define PPU_CLUS0CORE7_BASE (PIK_CLUS0_BASE + 0x9000) +#define PPU_CLUS0_BASE (PIK_CLUS0_BASE + 0x1000) +#define PPU_CLUS1CORE0_BASE (PIK_CLUS1_BASE + 0x2000) +#define PPU_CLUS1CORE1_BASE (PIK_CLUS1_BASE + 0x3000) +#define PPU_CLUS1CORE2_BASE (PIK_CLUS1_BASE + 0x4000) +#define PPU_CLUS1CORE3_BASE (PIK_CLUS1_BASE + 0x5000) +#define PPU_CLUS1_BASE (PIK_CLUS1_BASE + 0x1000) +#define PPU_GPU_BASE (PIK_GPU_BASE + 0x1000) +#define PPU_VPU_BASE (PIK_VPU_BASE + 0x1000) +#define PPU_DPU0_BASE (PIK_DPU_BASE + 0x2000) +#define PPU_DPU1_BASE (PIK_DPU_BASE + 0x3000) + +/* + * System access port 1 + */ +#define TRUSTED_RAM_BASE (SYS1_BASE + 0x04000000) +#define NONTRUSTED_RAM_BASE (SYS1_BASE + 0x06000000) +#define SSC_BASE (SYS1_BASE + 0x2A420000) +#define REFCLK_CNTCONTROL_BASE (SYS1_BASE + 0x2A430000) +#define MHU_BASE (SYS1_BASE + 0x2B1F0000) + +/* + * Base addresses of MHU devices + */ + +#define MHU_SCP_INTR_L_BASE (MHU_BASE) +#define MHU_SCP_INTR_H_BASE (MHU_BASE + 0x0020) +#define MHU_CPU_INTR_L_BASE (MHU_BASE + 0x0100) +#define MHU_CPU_INTR_H_BASE (MHU_BASE + 0x0120) +#define MHU_SCP_INTR_S_BASE (MHU_BASE + 0x0200) +#define MHU_CPU_INTR_S_BASE (MHU_BASE + 0x0300) + +#endif /* SGM775_MMAP_H */ diff --git a/product/host-input/include/fake_pik.h b/product/host-input/include/fake_pik.h new file mode 100644 index 0000000000000000000000000000000000000000..f0d78e1a5ee02247274aae3ccb150702deec4184 --- /dev/null +++ b/product/host-input/include/fake_pik.h @@ -0,0 +1,13 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef FAKE_PIK_H +#define FAKE_PIK_H + +#include + +#endif /* SGM775_PIK_H */ diff --git a/product/host-input/include/fake_pik_scp.h b/product/host-input/include/fake_pik_scp.h new file mode 100644 index 0000000000000000000000000000000000000000..458ca3755e71fb9a440508b0e42e904d9573ab00 --- /dev/null +++ b/product/host-input/include/fake_pik_scp.h @@ -0,0 +1,63 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef FAKE_PIK_SCP_H +#define FAKE_PIK_SCP_H + +#include +#include + +/*! + * \brief SCP PIK register definitions + */ +struct pik_scp_reg { + uint32_t RESERVED0[4]; + FWK_RW uint32_t RESET_SYNDROME; + FWK_RW uint32_t WIC_CTRL; + FWK_R uint32_t WIC_STATUS; + uint8_t RESERVED1[0xA00 - 0x1C]; + FWK_R uint32_t CLKFORCE_STATUS; + FWK_RW uint32_t CLKFORCE_SET; + FWK_RW uint32_t CLKFORCE_CLR; + uint32_t RESERVED2; + FWK_R uint32_t PLL_STATUS0; + FWK_R uint32_t PLL_STATUS1; + uint8_t RESERVED3[0xFC0 - 0xA18]; + FWK_R uint32_t PIK_CONFIG; + uint32_t RESERVED4[3]; + FWK_R uint32_t PID4; + FWK_R uint32_t PID5; + FWK_R uint32_t PID6; + FWK_R uint32_t PID7; + FWK_R uint32_t PID0; + FWK_R uint32_t PID1; + FWK_R uint32_t PID2; + FWK_R uint32_t PID3; + FWK_R uint32_t ID0; + FWK_R uint32_t ID1; + FWK_R uint32_t ID2; + FWK_R uint32_t ID3; +}; + +#define PLL_STATUS0_REFCLK UINT32_C(0x00000001) +#define PLL_STATUS0_BCPUPLLLOCK UINT32_C(0x00000002) +#define PLL_STATUS0_LCPUPLLLOCK UINT32_C(0x00000004) +#define PLL_STATUS0_GPUPLLLOCK UINT32_C(0x00000008) +#define PLL_STATUS0_VIDEOPLLLOCK UINT32_C(0x00000010) +#define PLL_STATUS0_SYSPLLLOCK UINT32_C(0x00000020) +#define PLL_STATUS0_DISPLAYPLLLOCK UINT32_C(0x00000040) + +#define PLL_STATUS1_CPUPLLLOCK(CPU, PLL) \ + ((uint32_t)((1 << (PLL)) << ((CPU) * 8))) + +#define RESET_SYNDROME_PORESET UINT32_C(0x01) +#define RESET_SYNDROME_WDOGRESET_SCP UINT32_C(0x02) +#define RESET_SYNDROME_WDOGRESET_SYS UINT32_C(0x04) +#define RESET_SYNDROME_SYSRESETREQ UINT32_C(0x08) +#define RESET_SYNDROME_SCPM3LOCKUP UINT32_C(0x10) + +#endif /* FAKE_PIK_SCP_H */ diff --git a/product/host-input/include/fmw_io.h b/product/host-input/include/fmw_io.h new file mode 100644 index 0000000000000000000000000000000000000000..878f8eb7dd6dbfffde25a204e6a1e9f1e8d54101 --- /dev/null +++ b/product/host-input/include/fmw_io.h @@ -0,0 +1,18 @@ +/* + * 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_HOST_CONSOLE, 0) + +#endif /* FMW_IO_H */ diff --git a/product/host-input/include/fmw_log.h b/product/host-input/include/fmw_log.h new file mode 100644 index 0000000000000000000000000000000000000000..4e0bdd0ee4f2eb0b4f153112af3bd61e0599ebe4 --- /dev/null +++ b/product/host-input/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/host-input/include/scmi_agents.h b/product/host-input/include/scmi_agents.h new file mode 100644 index 0000000000000000000000000000000000000000..fe8b1202d8a676a4c7d3affaecfe3289f5d6e23d --- /dev/null +++ b/product/host-input/include/scmi_agents.h @@ -0,0 +1,38 @@ +/* + * 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 { + /* 0 is reserved for the platform */ + SCMI_AGENT_ID_OSPM = 1, + SCMI_AGENT_ID_PSCI, + SCMI_AGENT_ID_PERF, + SCMI_AGENT_ID_COUNT, +}; + +enum scmi_service_idx { + SCMI_SERVICE_IDX_PSCI, + SCMI_SERVICE_IDX_OSPM_0, + SCMI_SERVICE_IDX_OSPM_1, +#ifdef BUILD_HAS_SCMI_NOTIFICATIONS + SCMI_SERVICE_IDX_OSPM_0_P2A, + SCMI_SERVICE_IDX_OSPM_1_P2A, +#endif + SCMI_SERVICE_IDX_COUNT, +}; + +enum scmi_channel_device_idx { + // TODO: change this: current code support device#0 only + SCMI_CHANNEL_DEVICE_IDX_OSPM_0, + SCMI_CHANNEL_DEVICE_IDX_OSPM_1, + SCMI_CHANNEL_DEVICE_IDX_PSCI, + SCMI_CHANNEL_DEVICE_IDX_COUNT +}; + +#endif /* SCMI_AGENTS_H */ diff --git a/product/host-input/module/vppu/CMakeLists.txt b/product/host-input/module/vppu/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..c950cbd169b908d168db3b16a61bb6330c7a3a1d --- /dev/null +++ b/product/host-input/module/vppu/CMakeLists.txt @@ -0,0 +1,21 @@ +# +# Arm SCP/MCP Software +# Copyright (c) 2022, 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") + +target_sources( + ${SCP_MODULE_TARGET} PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/src/mod_ppu_v0.c" + "${CMAKE_CURRENT_SOURCE_DIR}/src/ppu_v0.c") + +target_link_libraries(${SCP_MODULE_TARGET} PRIVATE module-power-domain) + +if("system-power" IN_LIST SCP_MODULES) + target_link_libraries(${SCP_MODULE_TARGET} PRIVATE module-system-power) +endif() diff --git a/product/host-input/module/vppu/Module.cmake b/product/host-input/module/vppu/Module.cmake new file mode 100644 index 0000000000000000000000000000000000000000..558e7c273e6ea3e7691cf2a9f46d93d2a1caaf96 --- /dev/null +++ b/product/host-input/module/vppu/Module.cmake @@ -0,0 +1,9 @@ +# +# Arm SCP/MCP Software +# Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +set(SCP_MODULE "vppu") +set(SCP_MODULE_TARGET "module-vppu") diff --git a/product/host-input/module/vppu/include/mod_ppu_v0.h b/product/host-input/module/vppu/include/mod_ppu_v0.h new file mode 100644 index 0000000000000000000000000000000000000000..981562300741c866dcc45523eda4cd1027531df0 --- /dev/null +++ b/product/host-input/module/vppu/include/mod_ppu_v0.h @@ -0,0 +1,63 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Description: + * Virtual PPU v0 driver module + */ + +#ifndef MOD_PPU_V0_H +#define MOD_PPU_V0_H + +#include +#include +#include + +/*! + * \addtogroup GroupModules Modules + * @{ + */ + +/*! + * \defgroup GroupModulePPUv0 PPUv0 Driver + * @{ + */ + +/*! + * \brief Power domain PPU descriptor. + */ +struct mod_ppu_v0 { + /*! Base address of the PPU registers */ + uintptr_t reg_base; + + /*! PPU's IRQ number */ + unsigned int irq; +}; + +/*! + * \brief Configuration data of a power domain of the PPU_V0 driver module. + */ +struct mod_ppu_v0_pd_config { + /*! Power domain type */ + enum mod_pd_type pd_type; + + /*! PPU descriptor */ + struct mod_ppu_v0 ppu; + + /*! + * Flag indicating if this domain should be powered on during element init. + */ + bool default_power_on; +}; + +/*! + * @} + */ + +/*! + * @} + */ + +#endif /* MOD_PPU_V0_H */ diff --git a/product/host-input/module/vppu/src/mod_ppu_v0.c b/product/host-input/module/vppu/src/mod_ppu_v0.c new file mode 100644 index 0000000000000000000000000000000000000000..038a3760acf236f2543eb9aa03588a90901c6a90 --- /dev/null +++ b/product/host-input/module/vppu/src/mod_ppu_v0.c @@ -0,0 +1,306 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Description: + * Power State Management PPU v0 driver. + */ + +#include +#include +#include +#include +#include +#include +#include +#if BUILD_HAS_MOD_SYSTEM_POWER +#include +#endif +#include "ppu_v0.h" + +/* Power domain context */ +struct ppu_v0_pd_ctx { + /* Power domain configuration data */ + const struct mod_ppu_v0_pd_config *config; + + /* PPU registers */ + struct ppu_v0_reg *ppu; + + /* Identifier of the entity bound to the power domain driver API */ + fwk_id_t bound_id; + + /* Power module driver input API */ + struct mod_pd_driver_input_api *pd_driver_input_api; +}; + +/* Module context */ +struct ppu_v0_ctx { + /* Table of the power domain contexts */ + struct ppu_v0_pd_ctx *pd_ctx_table; +}; + +/* + * Internal variables + */ + +static struct ppu_v0_ctx ppu_v0_ctx; + +#define MODE_UNSUPPORTED ~0U +static const uint8_t ppu_mode_to_power_state[] = { + [PPU_V0_MODE_ON] = (uint8_t)MOD_PD_STATE_ON, + [PPU_V0_MODE_FUNC_RET] = (uint8_t)MOD_PD_STATE_ON, + [PPU_V0_MODE_MEM_OFF] = (uint8_t)MODE_UNSUPPORTED, + [PPU_V0_MODE_FULL_RET] = (uint8_t)MOD_PD_STATE_ON, + [PPU_V0_MODE_LOGIC_RET] = (uint8_t)MODE_UNSUPPORTED, + [PPU_V0_MODE_MEM_RET] = (uint8_t)MOD_PD_STATE_ON, + [PPU_V0_MODE_OFF] = (uint8_t)MOD_PD_STATE_OFF, + [PPU_V0_MODE_WARM_RESET] = (uint8_t)MODE_UNSUPPORTED, +}; + +/* + * Power domain driver interface + */ + +/* Driver functions not specific to any type of power domain. */ +static int get_state(struct ppu_v0_reg *ppu, unsigned int *state) +{ + enum ppu_v0_mode ppu_mode; + + /* Ensure ppu_mode_to_power_state has an entry for each PPU state */ + static_assert(FWK_ARRAY_SIZE(ppu_mode_to_power_state) == PPU_V0_MODE_COUNT, + "[MOD_PPU_V0] ppu_mode_to_power_state size error"); + + ppu_v0_get_power_mode(ppu, &ppu_mode); + assert(ppu_mode < PPU_V0_MODE_COUNT); + + *state = ppu_mode_to_power_state[ppu_mode]; + if (*state == MODE_UNSUPPORTED) { + FWK_LOG_ERR("[PD] Unexpected PPU mode (%i).\n", ppu_mode); + + return FWK_E_DEVICE; + } + + return FWK_SUCCESS; +} + +static int pd_init(struct ppu_v0_pd_ctx *pd_ctx) +{ + ppu_v0_init(pd_ctx->ppu); + + return FWK_SUCCESS; +} + +static int pd_set_state(fwk_id_t pd_id, unsigned int state) +{ + int status; + struct ppu_v0_pd_ctx *pd_ctx; + + pd_ctx = ppu_v0_ctx.pd_ctx_table + fwk_id_get_element_idx(pd_id); + + fwk_assert(pd_ctx->pd_driver_input_api != NULL); + + switch (state) { + case MOD_PD_STATE_ON: + ppu_v0_set_power_mode(pd_ctx->ppu, PPU_V0_MODE_ON); + status = pd_ctx->pd_driver_input_api->report_power_state_transition( + pd_ctx->bound_id, MOD_PD_STATE_ON); + assert(status == FWK_SUCCESS); + break; + + case MOD_PD_STATE_OFF: + ppu_v0_set_power_mode(pd_ctx->ppu, PPU_V0_MODE_OFF); + status = pd_ctx->pd_driver_input_api->report_power_state_transition( + pd_ctx->bound_id, MOD_PD_STATE_OFF); + assert(status == FWK_SUCCESS); + break; + + default: + FWK_LOG_ERR("[PD] Requested power state (%i) is not supported.\n", state); + return FWK_E_PARAM; + } + + if (status != FWK_SUCCESS) + return FWK_E_PANIC; + + return FWK_SUCCESS; +} + +static int pd_get_state(fwk_id_t pd_id, unsigned int *state) +{ + struct ppu_v0_pd_ctx *pd_ctx; + + pd_ctx = ppu_v0_ctx.pd_ctx_table + fwk_id_get_element_idx(pd_id); + + return get_state(pd_ctx->ppu, state); +} + +static int pd_reset(fwk_id_t pd_id) +{ + int status; + struct ppu_v0_pd_ctx *pd_ctx; + + pd_ctx = ppu_v0_ctx.pd_ctx_table + fwk_id_get_element_idx(pd_id); + + /* Model does not support warm reset at the moment. Using OFF instead. */ + status = ppu_v0_set_power_mode(pd_ctx->ppu, PPU_V0_MODE_OFF); + if (status == FWK_SUCCESS) + status = ppu_v0_set_power_mode(pd_ctx->ppu, PPU_V0_MODE_ON); + + return status; +} + +static int ppu_v0_prepare_core_for_system_suspend(fwk_id_t core_pd_id) +{ + return FWK_SUCCESS; +} + + +static const struct mod_pd_driver_api pd_driver = { + .set_state = pd_set_state, + .get_state = pd_get_state, + .reset = pd_reset, + .prepare_core_for_system_suspend = ppu_v0_prepare_core_for_system_suspend, +}; + +/* + * Framework handlers + */ + +static int ppu_v0_mod_init(fwk_id_t module_id, unsigned int pd_count, + const void *unused) +{ + ppu_v0_ctx.pd_ctx_table = fwk_mm_calloc(pd_count, + sizeof(struct ppu_v0_pd_ctx)); + if (ppu_v0_ctx.pd_ctx_table == NULL) + return FWK_E_NOMEM; + + return FWK_SUCCESS; +} + +static int ppu_v0_pd_init(fwk_id_t pd_id, unsigned int unused, const void *data) +{ + const struct mod_ppu_v0_pd_config *config = data; + struct ppu_v0_pd_ctx *pd_ctx; + int status; + + if (config->pd_type >= MOD_PD_TYPE_COUNT) + return FWK_E_DATA; + + pd_ctx = ppu_v0_ctx.pd_ctx_table + fwk_id_get_element_idx(pd_id); + pd_ctx->config = config; + pd_ctx->ppu = (struct ppu_v0_reg *)(config->ppu.reg_base); + pd_ctx->bound_id = FWK_ID_NONE; + + switch (config->pd_type) { + case MOD_PD_TYPE_DEVICE: + case MOD_PD_TYPE_DEVICE_DEBUG: + case MOD_PD_TYPE_SYSTEM: + status = pd_init(pd_ctx); + if (status != FWK_SUCCESS) + return status; + + if (config->default_power_on) + return ppu_v0_set_power_mode(pd_ctx->ppu, PPU_V0_MODE_ON); + + return FWK_SUCCESS; + + default: + return FWK_E_SUPPORT; + } +} + +static int ppu_v0_bind(fwk_id_t id, unsigned int round) +{ + struct ppu_v0_pd_ctx *pd_ctx; + + /* Nothing to do during the first round of calls where the power module + will bind to the power domains of this module. */ + if (round == 0) + return FWK_SUCCESS; + + /* In the case of the module, nothing to do */ + if (fwk_module_is_valid_module_id(id)) { + return FWK_SUCCESS; + } + + pd_ctx = ppu_v0_ctx.pd_ctx_table + fwk_id_get_element_idx(id); + + if (fwk_id_is_equal(pd_ctx->bound_id, FWK_ID_NONE)) + return FWK_SUCCESS; + + switch (fwk_id_get_module_idx(pd_ctx->bound_id)) { + #if BUILD_HAS_MOD_POWER_DOMAIN + case FWK_MODULE_IDX_POWER_DOMAIN: + return fwk_module_bind(pd_ctx->bound_id, + mod_pd_api_id_driver_input, + &pd_ctx->pd_driver_input_api); + break; + #endif + + #if BUILD_HAS_MOD_SYSTEM_POWER + case FWK_MODULE_IDX_SYSTEM_POWER: + return fwk_module_bind(pd_ctx->bound_id, + mod_system_power_api_id_pd_driver_input, + &pd_ctx->pd_driver_input_api); + break; + #endif + + default: + assert(false); + return FWK_E_SUPPORT; + } +} + +static int ppu_v0_process_bind_request(fwk_id_t source_id, + fwk_id_t target_id, fwk_id_t not_used, + const void **api) +{ + struct ppu_v0_pd_ctx *pd_ctx; + + pd_ctx = ppu_v0_ctx.pd_ctx_table + fwk_id_get_element_idx(target_id); + + switch (pd_ctx->config->pd_type) { + case MOD_PD_TYPE_SYSTEM: + if (!fwk_id_is_equal(pd_ctx->bound_id, FWK_ID_NONE)) { + assert(false); + return FWK_E_ACCESS; + } + /* Fallthrough */ + + case MOD_PD_TYPE_DEVICE: + case MOD_PD_TYPE_DEVICE_DEBUG: + #if BUILD_HAS_MOD_POWER_DOMAIN + if (fwk_id_get_module_idx(source_id) == FWK_MODULE_IDX_POWER_DOMAIN) { + pd_ctx->bound_id = source_id; + *api = &pd_driver; + break; + } + #endif + #if BUILD_HAS_MOD_SYSTEM_POWER + if (fwk_id_get_module_idx(source_id) == FWK_MODULE_IDX_SYSTEM_POWER) { + pd_ctx->bound_id = source_id; + *api = &pd_driver; + break; + } + #endif + assert(false); + return FWK_E_ACCESS; + + default: + (void)pd_driver; + return FWK_E_SUPPORT; + } + + return FWK_SUCCESS; +} + +const struct fwk_module module_vppu = { + .type = FWK_MODULE_TYPE_DRIVER, + .api_count = 1, + .init = ppu_v0_mod_init, + .element_init = ppu_v0_pd_init, + .bind = ppu_v0_bind, + .process_bind_request = ppu_v0_process_bind_request, +}; diff --git a/product/host-input/module/vppu/src/ppu_v0.c b/product/host-input/module/vppu/src/ppu_v0.c new file mode 100644 index 0000000000000000000000000000000000000000..5a19777a436df95fa8d8d1772d8d17715a594098 --- /dev/null +++ b/product/host-input/module/vppu/src/ppu_v0.c @@ -0,0 +1,65 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include "ppu_v0.h" + +void ppu_v0_init(struct ppu_v0_reg *ppu) +{ + assert(ppu != NULL); + + /* Set mode as masked to all input edge interrupts */ + ppu->IESR = 0; + + /* Mask all interrupts */ + ppu->IMR = PPU_V0_IMR_MASK; + + /* Acknowledge any interrupt left pending */ + ppu->ISR = PPU_V0_ISR_MASK; +} + +int ppu_v0_request_power_mode(struct ppu_v0_reg *ppu, enum ppu_v0_mode mode) +{ + uint32_t power_policy; + assert(ppu != NULL); + assert(mode < PPU_V0_MODE_COUNT); + + power_policy = ppu->POWER_POLICY & + ~(PPU_V0_PPR_POLICY | PPU_V0_PPR_DYNAMIC_EN); + ppu->POWER_POLICY = power_policy | mode; + ppu->POWER_STATUS = power_policy | mode; + + return FWK_SUCCESS; +} + +int ppu_v0_set_power_mode(struct ppu_v0_reg *ppu, enum ppu_v0_mode mode) +{ + int status; + assert(ppu != NULL); + + status = ppu_v0_request_power_mode(ppu, mode); + if (status != FWK_SUCCESS) + return status; + + while ((ppu->POWER_STATUS & (PPU_V0_PSR_POWSTAT | PPU_V0_PSR_DYNAMIC)) + != mode) + continue; + + return FWK_SUCCESS; +} + +int ppu_v0_get_power_mode(struct ppu_v0_reg *ppu, enum ppu_v0_mode *mode) +{ + assert(ppu != NULL); + assert(mode != NULL); + + *mode = (enum ppu_v0_mode)(ppu->POWER_STATUS & PPU_V0_PSR_POWSTAT); + + return FWK_SUCCESS; +} diff --git a/product/host-input/module/vppu/src/ppu_v0.h b/product/host-input/module/vppu/src/ppu_v0.h new file mode 100644 index 0000000000000000000000000000000000000000..fc7fe26b40f2883fdf49fa44f636711942b5bc6f --- /dev/null +++ b/product/host-input/module/vppu/src/ppu_v0.h @@ -0,0 +1,144 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PPU_V0_H +#define PPU_V0_H + +/*! + * \cond + * @{ + */ + +#include +#include +#include + +struct ppu_v0_reg { + FWK_RW uint32_t POWER_POLICY; + FWK_RW uint32_t POWER_STATUS; + FWK_R uint32_t STATIC_CFG_STATUS; + FWK_R uint32_t DEV_IF_IP_CUR_STATUS; + FWK_R uint32_t MISC_IP_CUR_STATUS; + FWK_R uint32_t STORED_STATUS; + FWK_W uint32_t OFF_MEM_RET_UNLOCK; + uint32_t RESERVED0; + FWK_RW uint32_t POWER_CFG; + uint32_t RESERVED1[3]; + FWK_RW uint32_t IMR; + FWK_RW uint32_t ISR; + FWK_RW uint32_t IESR; + uint32_t RESERVED2[5]; + FWK_RW uint32_t FUNC_RET_RAM_CFG; + FWK_RW uint32_t FULL_RET_RAM_CFG; + FWK_RW uint32_t MEM_RET_RAM_CFG; + uint32_t RESERVED3; + FWK_RW uint32_t MODE_ENTRY_DELAY_TIME_0; + FWK_RW uint32_t MODE_ENTRY_DELAY_TIME_1; + uint32_t RESERVED4[2]; + FWK_RW uint32_t DEV_CONTROL_DELAY_CFG_0; + FWK_RW uint32_t DEV_CONTROL_DELAY_CFG_1; + uint8_t RESERVED5[0xFC8 - 0x78]; + FWK_R uint32_t IMPLEMENTATION_ID; + FWK_R uint32_t ARCHITECTURE_ID; + FWK_R uint32_t PID4; + FWK_R uint32_t PID5; + FWK_R uint32_t PID6; + FWK_R uint32_t PID7; + FWK_R uint32_t PID0; + FWK_R uint32_t PID1; + FWK_R uint32_t PID2; + FWK_R uint32_t PID3; + FWK_R uint32_t CID0; + FWK_R uint32_t CID1; + FWK_R uint32_t CID2; + FWK_R uint32_t CID3; +}; + +enum ppu_v0_mode { + PPU_V0_MODE_OFF = 0, + PPU_V0_MODE_MEM_RET = 1, + PPU_V0_MODE_LOGIC_RET = 2, + PPU_V0_MODE_FULL_RET = 3, + PPU_V0_MODE_MEM_OFF = 4, + PPU_V0_MODE_FUNC_RET = 5, + PPU_V0_MODE_ON = 6, + PPU_V0_MODE_WARM_RESET = 7, + PPU_V0_MODE_COUNT, +}; + +/* + * Bit definitions for PPR + */ +#define PPU_V0_PPR_POLICY UINT32_C(0x00000007) +#define PPU_V0_PPR_DYNAMIC_EN UINT32_C(0x00000100) +#define PPU_V0_PPR_EMULATED_EN UINT32_C(0x00000200) +#define PPU_V0_PPR_OFF_LOCK_EN UINT32_C(0x00001000) + +/* + * Bit definitions for PSR + */ +#define PPU_V0_PSR_EMULATED UINT32_C(0x00000200) +#define PPU_V0_PSR_DYNAMIC UINT32_C(0x00000100) +#define PPU_V0_PSR_POWSTAT UINT32_C(0x00000007) + +/* + * Bit definitions for IMR + */ +#define PPU_V0_IMR_MASK UINT32_C(0x010000FF) +#define PPU_V0_IMR_STA_POLICY_TRN UINT32_C(0x00000001) +#define PPU_V0_IMR_STA_ACCEPT UINT32_C(0x00000002) +#define PPU_V0_IMR_STA_DENY UINT32_C(0x00000004) +#define PPU_V0_IMR_DYN_ACCEPT UINT32_C(0x00000008) +#define PPU_V0_IMR_DYN_DENY UINT32_C(0x00000010) +#define PPU_V0_IMR_EMU_ACCEPT UINT32_C(0x00000020) +#define PPU_V0_IMR_EMU_DENY UINT32_C(0x00000040) +#define PPU_V0_IMR_UNSPT_POLICY UINT32_C(0x00000080) +#define PPU_V0_IMR_DYN_POLICY_MIN UINT32_C(0x01000000) + +/* + * Bit definitions for ISR + */ +#define PPU_V0_ISR_MASK UINT32_C(0x01FF01FF) +#define PPU_V0_ISR_STA_POLICY_TRN UINT32_C(0x00000001) +#define PPU_V0_ISR_STA_ACCEPT UINT32_C(0x00000002) +#define PPU_V0_ISR_STA_DENY UINT32_C(0x00000004) +#define PPU_V0_ISR_DYN_ACCEPT UINT32_C(0x00000008) +#define PPU_V0_ISR_DYN_DENY UINT32_C(0x00000010) +#define PPU_V0_ISR_EMU_ACCEPT UINT32_C(0x00000020) +#define PPU_V0_ISR_EMU_DENY UINT32_C(0x00000040) +#define PPU_V0_ISR_UNSPT_POLICY UINT32_C(0x00000080) +#define PPU_V0_ISR_DBGEMUPWRDWN_EDGE UINT32_C(0x00000100) +#define PPU_V0_ISR_ACTIVE_EDGE UINT32_C(0x00FF0000) +#define PPU_V0_ISR_ACTIVE_EDGE_ACTIVE0 UINT32_C(0x00010000) +#define PPU_V0_ISR_ACTIVE_EDGE_ACTIVE1 UINT32_C(0x00020000) +#define PPU_V0_ISR_ACTIVE_EDGE_ACTIVE2 UINT32_C(0x00040000) +#define PPU_V0_ISR_ACTIVE_EDGE_ACTIVE3 UINT32_C(0x00080000) +#define PPU_V0_ISR_ACTIVE_EDGE_ACTIVE4 UINT32_C(0x00100000) +#define PPU_V0_ISR_ACTIVE_EDGE_ACTIVE5 UINT32_C(0x00200000) +#define PPU_V0_ISR_ACTIVE_EDGE_ACTIVE6 UINT32_C(0x00400000) +#define PPU_V0_ISR_ACTIVE_EDGE_ACTIVE7 UINT32_C(0x00800000) +#define PPU_V0_ISR_DYN_POLICY_MIN UINT32_C(0x01000000) + +/* + * Bit definitions for ARCHITECTURE_ID + */ +#define PPU_V0_ARCHITECTURE_ID UINT32_C(0x00000000) + +/* + * Interface + */ +void ppu_v0_init(struct ppu_v0_reg *ppu); +int ppu_v0_request_power_mode(struct ppu_v0_reg *ppu, enum ppu_v0_mode mode); +int ppu_v0_set_power_mode(struct ppu_v0_reg *ppu, enum ppu_v0_mode mode); +int ppu_v0_get_power_mode(struct ppu_v0_reg *ppu, enum ppu_v0_mode *mode); + +/*! + * \endcond + * @} + */ + +#endif /* PPU_V0_H */ diff --git a/product/host/fw/CMakeLists.txt b/product/host/fw/CMakeLists.txt index 42fe4ec908783a5b83267d1359ced1e17a6a80a1..ab986ef5a837638b8af6a43ec09e0de82aecbdb6 100644 --- a/product/host/fw/CMakeLists.txt +++ b/product/host/fw/CMakeLists.txt @@ -1,6 +1,6 @@ # # Arm SCP/MCP Software -# Copyright (c) 2021, Arm Limited and Contributors. All rights reserved. +# Copyright (c) 2021-2022, Arm Limited and Contributors. All rights reserved. # # SPDX-License-Identifier: BSD-3-Clause # @@ -8,4 +8,5 @@ add_executable(host) target_include_directories(host PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}") -target_sources(host PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/config_stdio.c") +target_sources(host PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/config_stdio.c" + "${CMAKE_CURRENT_SOURCE_DIR}/config_host.c") diff --git a/product/host/fw/config_host.c b/product/host/fw/config_host.c new file mode 100644 index 0000000000000000000000000000000000000000..84070edba11e3abc014fd7638c0e1869e772106d --- /dev/null +++ b/product/host/fw/config_host.c @@ -0,0 +1,41 @@ +/* + * 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 + +/* + * Catches early failures in the initialization. + */ +static noreturn void panic(void) +{ + printf("Panic!\n"); + exit(1); +} + +/* Main loop */ + +int main(int argc, char *argv[]) +{ + int status; + + /* Initialize scmi server */ + status = scmi_arch_init(); + if (status != FWK_SUCCESS) + panic(); + + for (;;) { + fwk_process_event_queue(); + (void)fwk_log_unbuffer(); + fwk_arch_suspend(); + } +} diff --git a/product/host/fw/firmware.mk b/product/host/fw/firmware.mk index 143a9556e504de6d2319c9e70239146726f659d1..c17c6758b9982c52b96b40aec913864dd0be9ad2 100644 --- a/product/host/fw/firmware.mk +++ b/product/host/fw/firmware.mk @@ -1,6 +1,6 @@ # # Arm SCP/MCP Software -# Copyright (c) 2015-2021, Arm Limited and Contributors. All rights reserved. +# Copyright (c) 2015-2022, Arm Limited and Contributors. All rights reserved. # # SPDX-License-Identifier: BSD-3-Clause # @@ -13,6 +13,8 @@ BS_FIRMWARE_HAS_NOTIFICATION := yes BS_FIRMWARE_MODULES := stdio -BS_FIRMWARE_SOURCES := config_stdio.c +BS_FIRMWARE_SOURCES := config_stdio.c \ + config_host.c + include $(BS_DIR)/firmware.mk diff --git a/product/optee-fvp/fw/CMakeLists.txt b/product/optee-fvp/fw/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..7cbb86c5fd10a907b4bded6e6a38b2150df92c6a --- /dev/null +++ b/product/optee-fvp/fw/CMakeLists.txt @@ -0,0 +1,36 @@ +# +# 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_mhu_smt.c" + "${CMAKE_CURRENT_SOURCE_DIR}/config_scmi.c" + "${CMAKE_CURRENT_SOURCE_DIR}/config_mock_clock.c" + "${CMAKE_CURRENT_SOURCE_DIR}/config_vpll.c" + "${CMAKE_CURRENT_SOURCE_DIR}/config_clock.c" + "${CMAKE_CURRENT_SOURCE_DIR}/config_scmi_clock.c" + "${CMAKE_CURRENT_SOURCE_DIR}/config_ppu_v0.c" + "${CMAKE_CURRENT_SOURCE_DIR}/config_power_domain.c" + "${CMAKE_CURRENT_SOURCE_DIR}/config_scmi_power_domain.c" + "${CMAKE_CURRENT_SOURCE_DIR}/config_mock_psu.c" + "${CMAKE_CURRENT_SOURCE_DIR}/config_psu.c" + "${CMAKE_CURRENT_SOURCE_DIR}/config_dvfs.c" + "${CMAKE_CURRENT_SOURCE_DIR}/config_scmi_perf.c" + "${CMAKE_CURRENT_SOURCE_DIR}/config_sensor.c") diff --git a/product/optee-fvp/fw/Firmware.cmake b/product/optee-fvp/fw/Firmware.cmake new file mode 100644 index 0000000000000000000000000000000000000000..4afad18bdf0dc6e34123e8a689ead88741c422eb --- /dev/null +++ b/product/optee-fvp/fw/Firmware.cmake @@ -0,0 +1,59 @@ +# +# 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_GENERATE_FLAT_BINARY_INIT FALSE) + +set(SCP_ENABLE_NOTIFICATIONS_INIT TRUE) + +set(SCP_ENABLE_SCMI_NOTIFICATIONS_INIT TRUE) + +set(SCP_ENABLE_SCMI_SENSOR_EVENTS_INIT TRUE) + +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/vppu") + +# 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-mhu") +list(APPEND SCP_MODULES "msg-smt") +list(APPEND SCP_MODULES "scmi") +list(APPEND SCP_MODULES "mock-clock") +list(APPEND SCP_MODULES "system-pll") +list(APPEND SCP_MODULES "clock") +list(APPEND SCP_MODULES "scmi-clock") +list(APPEND SCP_MODULES "vppu") +list(APPEND SCP_MODULES "power-domain") +list(APPEND SCP_MODULES "scmi-power-domain") +list(APPEND SCP_MODULES "mock-psu") +list(APPEND SCP_MODULES "psu") +list(APPEND SCP_MODULES "dvfs") +list(APPEND SCP_MODULES "scmi-perf") +list(APPEND SCP_MODULES "reg-sensor") +list(APPEND SCP_MODULES "sensor") +list(APPEND SCP_MODULES "scmi-sensor") +list(APPEND SCP_MODULES "optee-console") diff --git a/product/optee-fvp/fw/Toolchain-GNU.cmake b/product/optee-fvp/fw/Toolchain-GNU.cmake new file mode 100644 index 0000000000000000000000000000000000000000..bc85fad45b7e89a418f349c5d5ce2048fbe9e000 --- /dev/null +++ b/product/optee-fvp/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-fvp/fw/clock_devices.h b/product/optee-fvp/fw/clock_devices.h new file mode 100644 index 0000000000000000000000000000000000000000..df71204a250dac02a845a116f079fe2262a85b2f --- /dev/null +++ b/product/optee-fvp/fw/clock_devices.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 CLOCK_DEVICES_H +#define CLOCK_DEVICES_H + +/*! + * \brief Clock device indexes. + */ +enum clock_dev_idx { + CLOCK_DEV_IDX_BIG, + CLOCK_DEV_IDX_LITTLE, + CLOCK_DEV_IDX_GPU, + CLOCK_DEV_IDX_VPU, + CLOCK_DEV_IDX_DPU, + CLOCK_DEV_IDX_PIXEL_0, + CLOCK_DEV_IDX_PIXEL_1, + CLOCK_DEV_IDX_MOCK_0, + CLOCK_DEV_IDX_MOCK_1, + CLOCK_DEV_IDX_MOCK_2, + CLOCK_DEV_IDX_MOCK_3, + CLOCK_DEV_IDX_COUNT +}; + +#endif /* CLOCK_DEVICES_H */ diff --git a/product/optee-fvp/fw/config_clock.c b/product/optee-fvp/fw/config_clock.c new file mode 100644 index 0000000000000000000000000000000000000000..103fbb09639be361554a42729df0c0f2b4696790 --- /dev/null +++ b/product/optee-fvp/fw/config_clock.c @@ -0,0 +1,127 @@ +/* + * 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 "clock_devices.h" + +static struct fwk_element clock_dev_desc_table[] = { + [CLOCK_DEV_IDX_BIG] = { + .name = "CPU_GROUP_BIG", + .data = &((struct mod_clock_dev_config) { + .driver_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_SYSTEM_PLL, 0), + .api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_SYSTEM_PLL, + MOD_SYSTEM_PLL_API_TYPE_DEFAULT), + }), + }, + [CLOCK_DEV_IDX_LITTLE] = { + .name = "CPU_GROUP_LITTLE", + .data = &((struct mod_clock_dev_config) { + .driver_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_SYSTEM_PLL, 1), + .api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_SYSTEM_PLL, + MOD_SYSTEM_PLL_API_TYPE_DEFAULT), + }), + }, + [CLOCK_DEV_IDX_GPU] = { + .name = "GPU", + .data = &((struct mod_clock_dev_config) { + .driver_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_SYSTEM_PLL, 2), + .api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_SYSTEM_PLL, + MOD_SYSTEM_PLL_API_TYPE_DEFAULT), + }), + }, + [CLOCK_DEV_IDX_VPU] = { + .name = "VPU", + .data = &((struct mod_clock_dev_config) { + .driver_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_SYSTEM_PLL, 3), + .api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_SYSTEM_PLL, + MOD_SYSTEM_PLL_API_TYPE_DEFAULT), + }), + }, + [CLOCK_DEV_IDX_DPU] = { + .name = "DPU", + .data = &((struct mod_clock_dev_config) { + .driver_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_SYSTEM_PLL, 4), + .api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_SYSTEM_PLL, + MOD_SYSTEM_PLL_API_TYPE_DEFAULT), + }), + }, + [CLOCK_DEV_IDX_PIXEL_0] = { + .name = "PIXEL_0", + .data = &((struct mod_clock_dev_config) { + .driver_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_SYSTEM_PLL, 5), + .api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_SYSTEM_PLL, + MOD_SYSTEM_PLL_API_TYPE_DEFAULT), + }), + }, + [CLOCK_DEV_IDX_PIXEL_1] = { + .name = "PIXEL_1", + .data = &((struct mod_clock_dev_config) { + .driver_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_SYSTEM_PLL, 6), + .api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_SYSTEM_PLL, + MOD_SYSTEM_PLL_API_TYPE_DEFAULT), + }), + }, + [CLOCK_DEV_IDX_MOCK_0] = { + .name = "CLOCK_0", + .data = &((struct mod_clock_dev_config) { + .driver_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_MOCK_CLOCK, 0), + .api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_MOCK_CLOCK, + MOD_MOCK_CLOCK_API_TYPE_DRIVER), + }), + }, + [CLOCK_DEV_IDX_MOCK_1] = { + .name = "CLOCK_1", + .data = &((struct mod_clock_dev_config) { + .driver_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_MOCK_CLOCK, 1), + .api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_MOCK_CLOCK, + MOD_MOCK_CLOCK_API_TYPE_DRIVER), + }), + }, + [CLOCK_DEV_IDX_MOCK_2] = { + .name = "CLOCK_2", + .data = &((struct mod_clock_dev_config) { + .driver_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_MOCK_CLOCK, 2), + .api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_MOCK_CLOCK, + MOD_MOCK_CLOCK_API_TYPE_DRIVER), + }), + }, + [CLOCK_DEV_IDX_MOCK_3] = { + .name = "CLOCK_3", + .data = &((struct mod_clock_dev_config) { + .driver_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_MOCK_CLOCK, 3), + .api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_MOCK_CLOCK, + MOD_MOCK_CLOCK_API_TYPE_DRIVER), + }), + }, + [CLOCK_DEV_IDX_COUNT] = { 0 }, /* Termination description. */ +}; + +static const struct fwk_element *clock_get_dev_desc_table(fwk_id_t module_id) +{ + unsigned int i; + struct mod_clock_dev_config *dev_config; + + /* Configure all clocks to respond to changes in SYSTOP power state */ + for (i = 0; i < CLOCK_DEV_IDX_COUNT; i++) { + dev_config = + (struct mod_clock_dev_config *)clock_dev_desc_table[i].data; + dev_config->pd_source_id = FWK_ID_NONE; + } + return clock_dev_desc_table; +} + +struct fwk_module_config config_clock = { + .data = &((struct mod_clock_config){ + .pd_transition_notification_id = FWK_ID_NONE_INIT, + .pd_pre_transition_notification_id = FWK_ID_NONE_INIT, + }), + .elements = FWK_MODULE_DYNAMIC_ELEMENTS(clock_get_dev_desc_table), +}; diff --git a/product/optee-fvp/fw/config_dvfs.c b/product/optee-fvp/fw/config_dvfs.c new file mode 100644 index 0000000000000000000000000000000000000000..12867173043e0b4071db8040944b9f79ae852f86 --- /dev/null +++ b/product/optee-fvp/fw/config_dvfs.c @@ -0,0 +1,152 @@ +/* + * 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 "config_dvfs.h" + +static const struct mod_dvfs_domain_config cpu_group_little = { + .psu_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_PSU, 0), + .clock_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_CLOCK, 0), + .latency = 1200, + .sustained_idx = 2, + .opps = (struct mod_dvfs_opp[]) { + { + .level = 665 * 1000UL, + .frequency = 665 * 1000UL, + .voltage = 100, + .power = 665*100*100/10000, + }, + { + .level = 998 * 1000UL, + .frequency = 998 * 1000UL, + .voltage = 110, + .power = 998*110*110/10000, + }, + { + .level = 1330 * 1000UL, + .frequency = 1330 * 1000UL, + .voltage = 120, + .power = 1330*120*120/10000, + }, + { + .level = 1463 * 1000UL, + .frequency = 1463 * 1000UL, + .voltage = 130, + .power = 1463*130*130/10000, + }, + { + .level = 1596 * 1000UL, + .frequency = 1596 * 1000UL, + .voltage = 140, + .power = 1596*140*140/10000, + }, + { 0 } + } +}; + +static const struct mod_dvfs_domain_config cpu_group_big = { + .psu_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_PSU, 1), + .clock_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_CLOCK, 1), + .latency = 1200, + .sustained_idx = 2, + .opps = (struct mod_dvfs_opp[]) { + { + .level = 1313 * 1000UL, + .frequency = 1313 * 1000UL , + .voltage = 100, + .power = 1313, + }, + { + .level = 1531 * 1000UL, + .frequency = 1531 * 1000UL, + .voltage = 200, + .power = 1531, + }, + { + .level = 1750 * 1000UL, + .frequency = 1750 * 1000UL, + .voltage = 300, + .power = 1750, + }, + { + .level = 2100 * 1000UL, + .frequency = 2100 * 1000UL, + .voltage = 400, + .power = 2100, + }, + { + .level = 2450 * 1000UL, + .frequency = 2450 * 1000UL, + .voltage = 500, + .power = 2450, + }, + { 0 } + } +}; + +static const struct mod_dvfs_domain_config gpu = { + .psu_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_PSU, 2), + .clock_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_CLOCK, 2), + .latency = 1200, + .sustained_idx = 4, + .opps = (struct mod_dvfs_opp[]) { + { + .level = 450 * 1000UL, + .frequency = 450 * 1000UL, + .voltage = 100, + }, + { + .level = 487500, + .frequency = 487500, + .voltage = 200, + }, + { + .level = 525 * 1000UL, + .frequency = 525 * 1000UL, + .voltage = 300, + }, + { + .level = 562500 * 1000UL, + .frequency = 562500, + .voltage = 400, + }, + { + .level = 600 * 1000UL, + .frequency = 600 * 1000UL, + .voltage = 500, + }, + { 0 } + } +}; + +static const struct fwk_element element_table[] = { + [DVFS_ELEMENT_IDX_LITTLE] = { + .name = "CPU_GROUP_LITTLE", + .data = &cpu_group_little, + }, + [DVFS_ELEMENT_IDX_BIG] = { + .name = "CPU_GROUP_BIG", + .data = &cpu_group_big, + }, + [DVFS_ELEMENT_IDX_GPU] = { + .name = "GPU", + .data = &gpu, + }, + { 0 } +}; + +static const struct fwk_element *dvfs_get_element_table(fwk_id_t module_id) +{ + return element_table; +} + +struct fwk_module_config config_dvfs = { + .elements = FWK_MODULE_DYNAMIC_ELEMENTS(dvfs_get_element_table), +}; diff --git a/product/optee-fvp/fw/config_dvfs.h b/product/optee-fvp/fw/config_dvfs.h new file mode 100644 index 0000000000000000000000000000000000000000..2913c1060d92e9dc24b84420144d50c55ec6c1f3 --- /dev/null +++ b/product/optee-fvp/fw/config_dvfs.h @@ -0,0 +1,18 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CONFIG_DVFS_H +#define CONFIG_DVFS_H + +enum dvfs_element_idx { + DVFS_ELEMENT_IDX_LITTLE, + DVFS_ELEMENT_IDX_BIG, + DVFS_ELEMENT_IDX_GPU, + DVFS_ELEMENT_IDX_COUNT +}; + +#endif /* CONFIG_DVFS_H */ diff --git a/product/optee-fvp/fw/config_mhu_smt.c b/product/optee-fvp/fw/config_mhu_smt.c new file mode 100644 index 0000000000000000000000000000000000000000..e1a0f98707b1821c97a017e43357e96b4aca920c --- /dev/null +++ b/product/optee-fvp/fw/config_mhu_smt.c @@ -0,0 +1,138 @@ +/* + * 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 + + +static const struct fwk_element mhu_element_table[] = { + [SCMI_CHANNEL_DEVICE_IDX_PSCI] = { + .name = "OP-TEE for PSCI", + .data = &((struct mod_optee_mhu_channel_config) { + .type = MOD_OPTEE_MHU_CHANNEL_TYPE_REQUESTER, + .driver_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_MSG_SMT, + SCMI_SERVICE_IDX_PSCI), + .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_MSG_SMT, + MOD_MSG_SMT_API_IDX_DRIVER_INPUT), + }) + }, + [SCMI_CHANNEL_DEVICE_IDX_OSPM_0] = { + .name = "OP-TEE for OSPM #0", + .data = &((struct mod_optee_mhu_channel_config) { + .type = MOD_OPTEE_MHU_CHANNEL_TYPE_REQUESTER, + .driver_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_MSG_SMT, + SCMI_SERVICE_IDX_OSPM_0), + .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_MSG_SMT, + MOD_MSG_SMT_API_IDX_DRIVER_INPUT), + }) + }, + [SCMI_CHANNEL_DEVICE_IDX_OSPM_1] = { + .name = "OP-TEE for OSPM #1", + .data = &((struct mod_optee_mhu_channel_config) { + .type = MOD_OPTEE_MHU_CHANNEL_TYPE_REQUESTER, + .driver_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_MSG_SMT, + SCMI_SERVICE_IDX_OSPM_1), + .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_MSG_SMT, + MOD_MSG_SMT_API_IDX_DRIVER_INPUT), + }) + }, +#ifdef BUILD_HAS_SCMI_NOTIFICATIONS + [SCMI_CHANNEL_DEVICE_IDX_OSPM_0_P2A] = { + .name = "OP-TEE for OSPM #0 P2A", + .data = &((struct mod_optee_mhu_channel_config) { + .type = MOD_OPTEE_MHU_CHANNEL_TYPE_COMPLETER, + .driver_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_MSG_SMT, + SCMI_SERVICE_IDX_OSPM_0_P2A), + .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_MSG_SMT, + MOD_MSG_SMT_API_IDX_DRIVER_INPUT), + }) + }, + [SCMI_CHANNEL_DEVICE_IDX_OSPM_1_P2A] = { + .name = "OP-TEE for OSPM #1 P2A", + .data = &((struct mod_optee_mhu_channel_config) { + .type = MOD_OPTEE_MHU_CHANNEL_TYPE_COMPLETER, + .driver_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_MSG_SMT, + SCMI_SERVICE_IDX_OSPM_1_P2A), + .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_MSG_SMT, + MOD_MSG_SMT_API_IDX_DRIVER_INPUT), + }) + }, +#endif + [SCMI_CHANNEL_DEVICE_IDX_COUNT] = { 0 }, +}; + +static const struct fwk_element *mhu_get_element_table(fwk_id_t module_id) +{ + return (const struct fwk_element *)mhu_element_table; +} + +struct fwk_module_config config_optee_mhu = { + .elements = FWK_MODULE_DYNAMIC_ELEMENTS(mhu_get_element_table), +}; + +static struct fwk_element smt_element_table[] = { + [SCMI_SERVICE_IDX_PSCI] = { + .name = "PSCI", + .data = &((struct mod_msg_smt_channel_config) { + .type = MOD_MSG_SMT_CHANNEL_TYPE_REQUESTER, + .driver_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_OPTEE_MHU, + SCMI_CHANNEL_DEVICE_IDX_PSCI), + .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_OPTEE_MHU, 0), + }) + }, + [SCMI_SERVICE_IDX_OSPM_0] = { + .name = "OSPM0", + .data = &((struct mod_msg_smt_channel_config) { + .type = MOD_MSG_SMT_CHANNEL_TYPE_REQUESTER, + .driver_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_OPTEE_MHU, + SCMI_CHANNEL_DEVICE_IDX_OSPM_0), + .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_OPTEE_MHU, 0), + }) + }, + [SCMI_SERVICE_IDX_OSPM_1] = { + .name = "OSPM1", + .data = &((struct mod_msg_smt_channel_config) { + .type = MOD_MSG_SMT_CHANNEL_TYPE_REQUESTER, + .driver_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_OPTEE_MHU, + SCMI_CHANNEL_DEVICE_IDX_OSPM_1), + .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_OPTEE_MHU, 0), + }) + }, +#ifdef BUILD_HAS_SCMI_NOTIFICATIONS + [SCMI_SERVICE_IDX_OSPM_0_P2A] = { + .name = "OSPM0 P2A", + .data = &((struct mod_msg_smt_channel_config) { + .type = MOD_MSG_SMT_CHANNEL_TYPE_COMPLETER, + .driver_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_OPTEE_MHU, + SCMI_CHANNEL_DEVICE_IDX_OSPM_0_P2A), + .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_OPTEE_MHU, 0), + }) + }, + [SCMI_SERVICE_IDX_OSPM_1_P2A] = { + .name = "OSPM1 P2A", + .data = &((struct mod_msg_smt_channel_config) { + .type = MOD_MSG_SMT_CHANNEL_TYPE_COMPLETER, + .driver_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_OPTEE_MHU, + SCMI_CHANNEL_DEVICE_IDX_OSPM_1_P2A), + .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_OPTEE_MHU, 0), + }) + }, +#endif + [SCMI_SERVICE_IDX_COUNT] = { 0 }, +}; + +static const struct fwk_element *smt_get_element_table(fwk_id_t module_id) +{ + return (const struct fwk_element *)smt_element_table; +} + +struct fwk_module_config config_msg_smt = { + .elements = FWK_MODULE_DYNAMIC_ELEMENTS(smt_get_element_table), +}; diff --git a/product/optee-fvp/fw/config_mock_clock.c b/product/optee-fvp/fw/config_mock_clock.c new file mode 100644 index 0000000000000000000000000000000000000000..5b64c9585051ffb4d07ef4da9ca0b5123f79337a --- /dev/null +++ b/product/optee-fvp/fw/config_mock_clock.c @@ -0,0 +1,78 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include "config_mock_clock.h" + + +static const struct mod_mock_clock_rate clk0_rate_table[] = { + { .rate = 1536000 }, { .rate = 2116800 }, { .rate = 2304000 }, + { .rate = 4233600 }, { .rate = 4608000 }, { .rate = 8467200 }, + { .rate = 9216000 }, +}; + +static const struct mod_mock_clock_rate clk1_rate_table[] = { + { .rate = 2116800 }, +}; + +static const struct mod_mock_clock_rate clk2_rate_table[] = { + { .rate = 2304000 }, +}; + +static const struct mod_mock_clock_rate clk3_rate_table[] = { + { .rate = 4233600 }, +}; + +static const struct fwk_element element_table[] = { + [MOD_MOCK_CLOCK_ELEMENT_IDX_0] = + { + .name = "MOCK_CLK0", + .data = &(const struct mod_mock_clock_element_cfg){ + .rate_table = clk0_rate_table, + .rate_count = FWK_ARRAY_SIZE(clk0_rate_table), + .default_rate = 1536000, + }, + }, + [MOD_MOCK_CLOCK_ELEMENT_IDX_1] = + { + .name = "MOCK_CLK1", + .data = &(const struct mod_mock_clock_element_cfg){ + .rate_table = clk1_rate_table, + .rate_count = FWK_ARRAY_SIZE(clk1_rate_table), + .default_rate = 2116800, + }, + }, + [MOD_MOCK_CLOCK_ELEMENT_IDX_2] = + { + .name = "MOCK_CLK2", + .data = &(const struct mod_mock_clock_element_cfg){ + .rate_table = clk2_rate_table, + .rate_count = FWK_ARRAY_SIZE(clk2_rate_table), + .default_rate = 2304000, + }, + }, + [MOD_MOCK_CLOCK_ELEMENT_IDX_3] = + { + .name = "MOCK_CLK3", + .data = &(const struct mod_mock_clock_element_cfg){ + .rate_table = clk3_rate_table, + .rate_count = FWK_ARRAY_SIZE(clk3_rate_table), + .default_rate = 4233600, + }, + }, + [MOD_MOCK_CLOCK_ELEMENT_IDX_COUNT] = { 0 }, /* Termination description. */ +}; + +static const struct fwk_element *get_element_table(fwk_id_t module_id) +{ + return element_table; +} + +struct fwk_module_config config_mock_clock = { + .elements = FWK_MODULE_DYNAMIC_ELEMENTS(get_element_table), +}; diff --git a/product/optee-fvp/fw/config_mock_clock.h b/product/optee-fvp/fw/config_mock_clock.h new file mode 100644 index 0000000000000000000000000000000000000000..114f0e00f59d17b9d8fa5177237dadbdec790ceb --- /dev/null +++ b/product/optee-fvp/fw/config_mock_clock.h @@ -0,0 +1,20 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CONFIG_MOCK_CLOCK_H +#define CONFIG_MOCK_CLOCK_H + +/* Mock clock element indices for Juno */ +enum mod_mock_clock_element_idx { + MOD_MOCK_CLOCK_ELEMENT_IDX_0, + MOD_MOCK_CLOCK_ELEMENT_IDX_1, + MOD_MOCK_CLOCK_ELEMENT_IDX_2, + MOD_MOCK_CLOCK_ELEMENT_IDX_3, + MOD_MOCK_CLOCK_ELEMENT_IDX_COUNT, +}; + +#endif /* CONFIG_MOCK_CLOCK_H */ diff --git a/product/optee-fvp/fw/config_mock_psu.c b/product/optee-fvp/fw/config_mock_psu.c new file mode 100644 index 0000000000000000000000000000000000000000..efdc94cbb4e733046ee5b542efae7085f402023e --- /dev/null +++ b/product/optee-fvp/fw/config_mock_psu.c @@ -0,0 +1,55 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include "config_mock_psu.h" + +static const struct fwk_element element_table[] = { + [CONFIG_MOCK_PSU_ELEMENT_IDX_CPU_GROUP_LITTLE] = { + .name = "CPU_GROUP_LITTLE", + .data = &(const struct mod_mock_psu_element_cfg) { + .default_enabled = true, + .default_voltage = 100, + .async_alarm_id = FWK_ID_NONE_INIT, + }, + }, + [CONFIG_MOCK_PSU_ELEMENT_IDX_CPU_GROUP_BIG] = { + .name = "CPU_GROUP_BIG", + .data = &(const struct mod_mock_psu_element_cfg) { + .default_enabled = true, + .default_voltage = 100, + .async_alarm_id = FWK_ID_NONE_INIT, + }, + }, + [CONFIG_MOCK_PSU_ELEMENT_IDX_GPU] = { + .name = "GPU", + .data = &(const struct mod_mock_psu_element_cfg) { + .default_enabled = true, + .default_voltage = 100, + .async_alarm_id = FWK_ID_NONE_INIT, + }, + }, + [CONFIG_MOCK_PSU_ELEMENT_IDX_VPU] = { + .name = "VPU", + .data = &(const struct mod_mock_psu_element_cfg) { + .default_enabled = true, + .default_voltage = 100, + .async_alarm_id = FWK_ID_NONE_INIT, + }, + }, + { 0 } +}; + +static const struct fwk_element *get_element_table(fwk_id_t module_id) +{ + return element_table; +} + +struct fwk_module_config config_mock_psu = { + .elements = FWK_MODULE_DYNAMIC_ELEMENTS(get_element_table), +}; diff --git a/product/optee-fvp/fw/config_mock_psu.h b/product/optee-fvp/fw/config_mock_psu.h new file mode 100644 index 0000000000000000000000000000000000000000..74476bb4585bcae08e85f86fcb538bab8d213fc3 --- /dev/null +++ b/product/optee-fvp/fw/config_mock_psu.h @@ -0,0 +1,19 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CONFIG_MOCK_PSU_H +#define CONFIG_MOCK_PSU_H + +enum config_mock_psu_element_idx { + CONFIG_MOCK_PSU_ELEMENT_IDX_CPU_GROUP_LITTLE, + CONFIG_MOCK_PSU_ELEMENT_IDX_CPU_GROUP_BIG, + CONFIG_MOCK_PSU_ELEMENT_IDX_GPU, + CONFIG_MOCK_PSU_ELEMENT_IDX_VPU, + CONFIG_MOCK_PSU_ELEMENT_IDX_COUNT, +}; + +#endif /* CONFIG_MOCK_PSU_H */ diff --git a/product/optee-fvp/fw/config_power_domain.c b/product/optee-fvp/fw/config_power_domain.c new file mode 100644 index 0000000000000000000000000000000000000000..eb5abb64bf4dd9e70cb4f0eb126cdb6d747e74d3 --- /dev/null +++ b/product/optee-fvp/fw/config_power_domain.c @@ -0,0 +1,153 @@ +/* + * 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 "config_power_domain.h" +#include "config_ppu_v0.h" + +/* + * Mask of the allowed states for the top level power domains + * (but the cluster power domains) depending on the system states. + */ +static const uint32_t toplevel_allowed_state_mask_table[] = { + [MOD_PD_STATE_OFF] = MOD_PD_STATE_OFF_MASK, + [MOD_PD_STATE_ON] = MOD_PD_STATE_OFF_MASK | MOD_PD_STATE_ON_MASK, +}; + +/* + * Mask of the allowed states for the cluster power domain depending on the + * system states. + * + * While the clusters may reach a SLEEP state, SLEEP does not appear in this + * table. This is because the PPU driver backing the clusters will not accept a + * manual SLEEP request, but will transition to it automatically when possible. + */ +static const uint32_t cluster_pd_allowed_state_mask_table[] = { + [MOD_PD_STATE_OFF] = MOD_PD_STATE_OFF_MASK, + [MOD_PD_STATE_ON] = MOD_PD_STATE_OFF_MASK | MOD_PD_STATE_ON_MASK, +}; + +/* Mask of the allowed states for a core depending on the cluster states. */ +static const uint32_t core_pd_allowed_state_mask_table[] = { + [MOD_PD_STATE_OFF] = MOD_PD_STATE_OFF_MASK, + [MOD_PD_STATE_ON] = MOD_PD_STATE_OFF_MASK | MOD_PD_STATE_ON_MASK | + MOD_PD_STATE_SLEEP_MASK, + [MOD_PD_STATE_SLEEP] = MOD_PD_STATE_OFF_MASK | MOD_PD_STATE_SLEEP_MASK, +}; + +/* Power module specific configuration data (none) */ +static const struct mod_power_domain_config fvp_power_domain_config = { 0 }; + +static struct fwk_element fvp_power_domain_static_element_table[] = { + [CONFIG_POWER_DOMAIN_SYSTOP_CHILD_DBGTOP] = { + .name = "DBGTOP", + .data = &((struct mod_power_domain_element_config) { + .attributes.pd_type = MOD_PD_TYPE_DEVICE_DEBUG, + .driver_id = FWK_ID_ELEMENT_INIT( + FWK_MODULE_IDX_VPPU, PPU_V0_ELEMENT_IDX_DBGTOP), + .api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_VPPU, 0), + .allowed_state_mask_table = toplevel_allowed_state_mask_table, + .allowed_state_mask_table_size = + FWK_ARRAY_SIZE(toplevel_allowed_state_mask_table) + }), + }, + [CONFIG_POWER_DOMAIN_SYSTOP_CHILD_DPU0TOP] = { + .name = "DPU0TOP", + .data = &((struct mod_power_domain_element_config) { + .attributes.pd_type = MOD_PD_TYPE_DEVICE, + .driver_id = FWK_ID_ELEMENT_INIT( + FWK_MODULE_IDX_VPPU, PPU_V0_ELEMENT_IDX_DPU0TOP), + .api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_VPPU, 0), + .allowed_state_mask_table = toplevel_allowed_state_mask_table, + .allowed_state_mask_table_size = + FWK_ARRAY_SIZE(toplevel_allowed_state_mask_table) + }), + }, + [CONFIG_POWER_DOMAIN_SYSTOP_CHILD_DPU1TOP] = { + .name = "DPU1TOP", + .data = &((struct mod_power_domain_element_config) { + .attributes.pd_type = MOD_PD_TYPE_DEVICE, + .driver_id = FWK_ID_ELEMENT_INIT( + FWK_MODULE_IDX_VPPU, PPU_V0_ELEMENT_IDX_DPU1TOP), + .api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_VPPU, 0), + .allowed_state_mask_table = toplevel_allowed_state_mask_table, + .allowed_state_mask_table_size = + FWK_ARRAY_SIZE(toplevel_allowed_state_mask_table) + }), + }, + [CONFIG_POWER_DOMAIN_SYSTOP_CHILD_GPUTOP] = { + .name = "GPUTOP", + .data = &((struct mod_power_domain_element_config) { + .attributes.pd_type = MOD_PD_TYPE_DEVICE, + .driver_id = FWK_ID_ELEMENT_INIT( + FWK_MODULE_IDX_VPPU, PPU_V0_ELEMENT_IDX_GPUTOP), + .api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_VPPU, 0), + .allowed_state_mask_table = toplevel_allowed_state_mask_table, + .allowed_state_mask_table_size = + FWK_ARRAY_SIZE(toplevel_allowed_state_mask_table) + }), + }, + [CONFIG_POWER_DOMAIN_SYSTOP_CHILD_VPUTOP] = { + .name = "VPUTOP", + .data = &((struct mod_power_domain_element_config) { + .attributes.pd_type = MOD_PD_TYPE_DEVICE, + .driver_id = FWK_ID_ELEMENT_INIT( + FWK_MODULE_IDX_VPPU, PPU_V0_ELEMENT_IDX_VPUTOP), + .api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_VPPU, 0), + .allowed_state_mask_table = toplevel_allowed_state_mask_table, + .allowed_state_mask_table_size = + FWK_ARRAY_SIZE(toplevel_allowed_state_mask_table) + }), + }, + [CONFIG_POWER_DOMAIN_SYSTOP_CHILD_COUNT] = { + .name = "SYSTOP", + .data = &((struct mod_power_domain_element_config) { + .parent_idx = UINT32_MAX, + .attributes.pd_type = MOD_PD_TYPE_DEVICE, + .driver_id = FWK_ID_ELEMENT_INIT( + FWK_MODULE_IDX_VPPU, PPU_V0_ELEMENT_IDX_SYSTEM), + .api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_VPPU, 0), + .allowed_state_mask_table = toplevel_allowed_state_mask_table, + .allowed_state_mask_table_size = + FWK_ARRAY_SIZE(toplevel_allowed_state_mask_table) + }), + }, +}; + +/* + * Function definitions with internal linkage + */ +static const struct fwk_element *fvp_power_domain_get_element_table + (fwk_id_t module_id) +{ + const struct fwk_element *element_table; + + element_table = create_power_domain_element_table( + 4, + 2, + FWK_MODULE_IDX_VPPU, + 0, + core_pd_allowed_state_mask_table, + FWK_ARRAY_SIZE(core_pd_allowed_state_mask_table), + cluster_pd_allowed_state_mask_table, + FWK_ARRAY_SIZE(cluster_pd_allowed_state_mask_table), + fvp_power_domain_static_element_table, + FWK_ARRAY_SIZE(fvp_power_domain_static_element_table)); + + return element_table; +} + +/* + * Power module configuration data + */ +struct fwk_module_config config_power_domain = { + .data = &fvp_power_domain_config, + .elements = FWK_MODULE_DYNAMIC_ELEMENTS(fvp_power_domain_get_element_table), +}; diff --git a/product/optee-fvp/fw/config_power_domain.h b/product/optee-fvp/fw/config_power_domain.h new file mode 100644 index 0000000000000000000000000000000000000000..d3a1d91430b89ed48e11bd0e3d2d56e69534cd9f --- /dev/null +++ b/product/optee-fvp/fw/config_power_domain.h @@ -0,0 +1,20 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CONFIG_POWER_DOMAIN_H +#define CONFIG_POWER_DOMAIN_H + +enum systop_child_index { + CONFIG_POWER_DOMAIN_SYSTOP_CHILD_DBGTOP, + CONFIG_POWER_DOMAIN_SYSTOP_CHILD_DPU0TOP, + CONFIG_POWER_DOMAIN_SYSTOP_CHILD_DPU1TOP, + CONFIG_POWER_DOMAIN_SYSTOP_CHILD_GPUTOP, + CONFIG_POWER_DOMAIN_SYSTOP_CHILD_VPUTOP, + CONFIG_POWER_DOMAIN_SYSTOP_CHILD_COUNT +}; + +#endif /* CONFIG_POWER_DOMAIN_H */ diff --git a/product/optee-fvp/fw/config_ppu_v0.c b/product/optee-fvp/fw/config_ppu_v0.c new file mode 100644 index 0000000000000000000000000000000000000000..6ad6117db7d926b4d87207274dc35197d859d00b --- /dev/null +++ b/product/optee-fvp/fw/config_ppu_v0.c @@ -0,0 +1,156 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include "config_ppu_v0.h" + +uint32_t vppu_regdbg[16]; +uint32_t vppu_regdpu0[16]; +uint32_t vppu_regdpu1[16]; +uint32_t vppu_reggpu[16]; +uint32_t vppu_regvpu[16]; +uint32_t vppu_regsys0[16]; +uint32_t vppu_regsys1[16]; +uint32_t vppu_regcluster[16]; +uint32_t vppu_regsys[16]; + +static struct fwk_element host_ppu_v0_element_table[] = { + [PPU_V0_ELEMENT_IDX_CPU0] = { + .name = "CPU0", + .data = &((struct mod_ppu_v0_pd_config) { + .pd_type = MOD_PD_TYPE_DEVICE, + .ppu.reg_base = (uintptr_t)vppu_regcluster, + .ppu.irq = PPU_SYS1_IRQ + }), + }, + [PPU_V0_ELEMENT_IDX_CPU1] = { + .name = "CPU1", + .data = &((struct mod_ppu_v0_pd_config) { + .pd_type = MOD_PD_TYPE_DEVICE, + .ppu.reg_base = (uintptr_t)vppu_regcluster, + .ppu.irq = PPU_SYS1_IRQ + }), + }, + [PPU_V0_ELEMENT_IDX_CPU2] = { + .name = "CPU2", + .data = &((struct mod_ppu_v0_pd_config) { + .pd_type = MOD_PD_TYPE_DEVICE, + .ppu.reg_base = (uintptr_t)vppu_regcluster, + .ppu.irq = PPU_SYS1_IRQ + }), + }, + [PPU_V0_ELEMENT_IDX_CPU3] = { + .name = "CPU3", + .data = &((struct mod_ppu_v0_pd_config) { + .pd_type = MOD_PD_TYPE_DEVICE, + .ppu.reg_base = (uintptr_t)vppu_regcluster, + .ppu.irq = PPU_SYS1_IRQ + }), + }, + [PPU_V0_ELEMENT_IDX_CLUSTER0] = { + .name = "CLUSTER0", + .data = &((struct mod_ppu_v0_pd_config) { + .pd_type = MOD_PD_TYPE_DEVICE, + .ppu.reg_base = (uintptr_t)vppu_regcluster, + .ppu.irq = PPU_SYS1_IRQ + }), + }, + [PPU_V0_ELEMENT_IDX_CLUSTER1] = { + .name = "CLUSTER1", + .data = &((struct mod_ppu_v0_pd_config) { + .pd_type = MOD_PD_TYPE_DEVICE, + .ppu.reg_base = (uintptr_t)vppu_regcluster, + .ppu.irq = PPU_SYS1_IRQ + }), + }, + [PPU_V0_ELEMENT_IDX_DBGTOP] = { + .name = "DBGTOP", + .data = &((struct mod_ppu_v0_pd_config) { + .pd_type = MOD_PD_TYPE_DEVICE_DEBUG, + .ppu.reg_base = (uintptr_t)vppu_regdbg, + .ppu.irq = PPU_DEBUG_IRQ + }), + }, + [PPU_V0_ELEMENT_IDX_DPU0TOP] = { + .name = "DPU0TOP", + .data = &((struct mod_ppu_v0_pd_config) { + .pd_type = MOD_PD_TYPE_DEVICE, + .ppu.reg_base = (uintptr_t)vppu_regdpu0, + .ppu.irq = PPU_DPU0_IRQ, + .default_power_on = true, + }), + }, + [PPU_V0_ELEMENT_IDX_DPU1TOP] = { + .name = "DPU1TOP", + .data = &((struct mod_ppu_v0_pd_config) { + .pd_type = MOD_PD_TYPE_DEVICE, + .ppu.reg_base = (uintptr_t)vppu_regdpu1, + .ppu.irq = PPU_DPU1_IRQ, + .default_power_on = true, + }), + }, + [PPU_V0_ELEMENT_IDX_GPUTOP] = { + .name = "GPUTOP", + .data = &((struct mod_ppu_v0_pd_config) { + .pd_type = MOD_PD_TYPE_DEVICE, + .ppu.reg_base = (uintptr_t)vppu_reggpu, + .ppu.irq = PPU_GPU_IRQ, + .default_power_on = true, + }), + }, + [PPU_V0_ELEMENT_IDX_VPUTOP] = { + .name = "VPUTOP", + .data = &((struct mod_ppu_v0_pd_config) { + .pd_type = MOD_PD_TYPE_DEVICE, + .ppu.reg_base = (uintptr_t)vppu_regvpu, + .ppu.irq = PPU_VPU_IRQ, + .default_power_on = true, + }), + }, + [PPU_V0_ELEMENT_IDX_SYS0] = { + .name = "SYS0", + .data = &((struct mod_ppu_v0_pd_config) { + .pd_type = MOD_PD_TYPE_SYSTEM, + .ppu.reg_base = (uintptr_t)vppu_regsys0, + .ppu.irq = PPU_SYS0_IRQ + }), + }, + [PPU_V0_ELEMENT_IDX_SYS1] = { + .name = "SYS1", + .data = &((struct mod_ppu_v0_pd_config) { + .pd_type = MOD_PD_TYPE_SYSTEM, + .ppu.reg_base = (uintptr_t)vppu_regsys1, + .ppu.irq = PPU_SYS1_IRQ + }), + }, + [PPU_V0_ELEMENT_IDX_SYSTEM] = { + .name = "SYSTEM", + .data = &((struct mod_ppu_v0_pd_config) { + .pd_type = MOD_PD_TYPE_DEVICE, + .ppu.reg_base = (uintptr_t)vppu_regsys, + .ppu.irq = PPU_SYS1_IRQ, + .default_power_on = true, + }), + }, + [PPU_V0_ELEMENT_IDX_COUNT] = { 0 }, /* Termination entry */ +}; + + +static const struct fwk_element *host_ppu_v0_get_element_table + (fwk_id_t module_id) +{ + return host_ppu_v0_element_table; +} + +/* + * Power module configuration data + */ +struct fwk_module_config config_vppu = { + .elements = FWK_MODULE_DYNAMIC_ELEMENTS(host_ppu_v0_get_element_table), +}; diff --git a/product/optee-fvp/fw/config_ppu_v0.h b/product/optee-fvp/fw/config_ppu_v0.h new file mode 100644 index 0000000000000000000000000000000000000000..3f70a1d6add58144f89f81f69236da7398efba4c --- /dev/null +++ b/product/optee-fvp/fw/config_ppu_v0.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 CONFIG_PPU_V0_H +#define CONFIG_PPU_V0_H + +enum ppu_v0_element_idx { + PPU_V0_ELEMENT_IDX_CPU0, + PPU_V0_ELEMENT_IDX_CPU1, + PPU_V0_ELEMENT_IDX_CPU2, + PPU_V0_ELEMENT_IDX_CPU3, + PPU_V0_ELEMENT_IDX_CLUSTER0, + PPU_V0_ELEMENT_IDX_CLUSTER1, + PPU_V0_ELEMENT_IDX_DBGTOP, + PPU_V0_ELEMENT_IDX_DPU0TOP, + PPU_V0_ELEMENT_IDX_DPU1TOP, + PPU_V0_ELEMENT_IDX_GPUTOP, + PPU_V0_ELEMENT_IDX_VPUTOP, + PPU_V0_ELEMENT_IDX_SYS0, + PPU_V0_ELEMENT_IDX_SYS1, + PPU_V0_ELEMENT_IDX_SYSTEM, + PPU_V0_ELEMENT_IDX_COUNT +}; + +#endif /* CONFIG_PPU_V0_H */ diff --git a/product/optee-fvp/fw/config_psu.c b/product/optee-fvp/fw/config_psu.c new file mode 100644 index 0000000000000000000000000000000000000000..6ad0595cbc23de700e7f50dae6393643f608fbd1 --- /dev/null +++ b/product/optee-fvp/fw/config_psu.c @@ -0,0 +1,56 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + +static const struct fwk_element element_table[] = { + { + .name = "CPU_GROUP_LITTLE", + .data = &(const struct mod_psu_element_cfg) { + .driver_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_MOCK_PSU, 0), + .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_MOCK_PSU, + MOD_MOCK_PSU_API_IDX_DRIVER) + }, + }, + { + .name = "CPU_GROUP_BIG", + .data = &(const struct mod_psu_element_cfg) { + .driver_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_MOCK_PSU, 1), + .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_MOCK_PSU, + MOD_MOCK_PSU_API_IDX_DRIVER) + }, + }, + { + .name = "GPU", + .data = &(const struct mod_psu_element_cfg) { + .driver_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_MOCK_PSU, 2), + .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_MOCK_PSU, + MOD_MOCK_PSU_API_IDX_DRIVER) + }, + }, + { + .name = "VPU", + .data = &(const struct mod_psu_element_cfg) { + .driver_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_MOCK_PSU, 3), + .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_MOCK_PSU, + MOD_MOCK_PSU_API_IDX_DRIVER) + }, + }, + { 0 } +}; + +static const struct fwk_element *psu_get_element_table(fwk_id_t module_id) +{ + return element_table; +} + +struct fwk_module_config config_psu = { + .elements = FWK_MODULE_DYNAMIC_ELEMENTS(psu_get_element_table), +}; diff --git a/product/optee-fvp/fw/config_reg_sensor.h b/product/optee-fvp/fw/config_reg_sensor.h new file mode 100644 index 0000000000000000000000000000000000000000..60359a6aa527fde82ea2f05068c67e20b8d528f1 --- /dev/null +++ b/product/optee-fvp/fw/config_reg_sensor.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 CONFIG_SENSOR_H +#define CONFIG_SENSOR_H + +enum SENSOR_DEVICES { + SENSOR_DEV_SOC_TEMP, + SENSOR_DEV_DDR_TEMP, + SENSOR_DEV_COUNT, +}; + +#endif /* CONFIG_PPU_V0_H */ diff --git a/product/optee-fvp/fw/config_scmi.c b/product/optee-fvp/fw/config_scmi.c new file mode 100644 index 0000000000000000000000000000000000000000..bb2ea9d9110469689ee60a00f33ecb059c55882c --- /dev/null +++ b/product/optee-fvp/fw/config_scmi.c @@ -0,0 +1,122 @@ +/* + * 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 + +static const struct fwk_element service_table[] = { + [SCMI_SERVICE_IDX_PSCI] = { + .name = "agent PSCI", + .data = &((struct mod_scmi_service_config) { + .transport_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_MSG_SMT, + SCMI_SERVICE_IDX_PSCI), + .transport_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_MSG_SMT, + MOD_MSG_SMT_API_IDX_SCMI_TRANSPORT), + .scmi_agent_id = SCMI_AGENT_ID_PSCI, + .transport_notification_init_id = FWK_ID_NONE_INIT, + .scmi_p2a_id = FWK_ID_NONE_INIT, + }), + }, + [SCMI_SERVICE_IDX_OSPM_0] = { + .name = "agent OSPM0", + .data = &((struct mod_scmi_service_config) { + .transport_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_MSG_SMT, + SCMI_SERVICE_IDX_OSPM_0), + .transport_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_MSG_SMT, + MOD_MSG_SMT_API_IDX_SCMI_TRANSPORT), + .scmi_agent_id = SCMI_AGENT_ID_OSPM, + .transport_notification_init_id = FWK_ID_NONE_INIT, +#ifdef BUILD_HAS_SCMI_NOTIFICATIONS + .scmi_p2a_id = FWK_ID_ELEMENT_INIT( + FWK_MODULE_IDX_SCMI, + SCMI_SERVICE_IDX_OSPM_0_P2A), +#else + .scmi_p2a_id = FWK_ID_NONE_INIT, +#endif + }), + }, + [SCMI_SERVICE_IDX_OSPM_1] = { + .name = "agent OSPM1", + .data = &((struct mod_scmi_service_config) { + .transport_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_MSG_SMT, + SCMI_SERVICE_IDX_OSPM_1), + .transport_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_MSG_SMT, + MOD_MSG_SMT_API_IDX_SCMI_TRANSPORT), + .scmi_agent_id = SCMI_AGENT_ID_PERF, + .transport_notification_init_id = FWK_ID_NONE_INIT, +#ifdef BUILD_HAS_SCMI_NOTIFICATIONS + .scmi_p2a_id = FWK_ID_ELEMENT_INIT( + FWK_MODULE_IDX_SCMI, + SCMI_SERVICE_IDX_OSPM_1_P2A), +#else + .scmi_p2a_id = FWK_ID_NONE_INIT, +#endif + }), + }, +#ifdef BUILD_HAS_SCMI_NOTIFICATIONS + [SCMI_SERVICE_IDX_OSPM_0_P2A] = { + .name = "agent OSPM0 P2A", + .data = &((struct mod_scmi_service_config) { + .transport_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_MSG_SMT, + SCMI_SERVICE_IDX_OSPM_0_P2A), + .transport_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_MSG_SMT, + MOD_MSG_SMT_API_IDX_SCMI_TRANSPORT), + .scmi_agent_id = SCMI_AGENT_ID_OSPM, + .transport_notification_init_id = FWK_ID_NONE_INIT, + .scmi_p2a_id = FWK_ID_NONE_INIT, + }), + }, + [SCMI_SERVICE_IDX_OSPM_1_P2A] = { + .name = "agent OSPM1 P2A", + .data = &((struct mod_scmi_service_config) { + .transport_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_MSG_SMT, + SCMI_SERVICE_IDX_OSPM_1_P2A), + .transport_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_MSG_SMT, + MOD_MSG_SMT_API_IDX_SCMI_TRANSPORT), + .scmi_agent_id = SCMI_AGENT_ID_OSPM, + .transport_notification_init_id = FWK_ID_NONE_INIT, + .scmi_p2a_id = FWK_ID_NONE_INIT, + }), + }, +#endif + [SCMI_SERVICE_IDX_COUNT] = { 0 } +}; + +static const struct fwk_element *get_service_table(fwk_id_t module_id) +{ + return service_table; +} + +static const struct mod_scmi_agent agent_table[] = { + [SCMI_AGENT_ID_OSPM] = { + .type = SCMI_AGENT_TYPE_OSPM, + .name = "OSPM", + }, + [SCMI_AGENT_ID_PSCI] = { + .type = SCMI_AGENT_TYPE_PSCI, + .name = "PSCI", + }, + [SCMI_AGENT_ID_PERF] = { + .type = SCMI_AGENT_TYPE_OSPM, + .name = "PERF", + }, +}; + +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_service_table), +}; diff --git a/product/optee-fvp/fw/config_scmi_clock.c b/product/optee-fvp/fw/config_scmi_clock.c new file mode 100644 index 0000000000000000000000000000000000000000..d2eb353badacb3f6dcf28796389114df6de2c26d --- /dev/null +++ b/product/optee-fvp/fw/config_scmi_clock.c @@ -0,0 +1,98 @@ +/* + * 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 "clock_devices.h" + +static const struct mod_scmi_clock_device agent_device_table_ospm[] = { + { + /* MOCK_0 */ + .element_id = + FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_CLOCK, CLOCK_DEV_IDX_MOCK_0), + }, + { + /* MOCK_1 */ + .element_id = + FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_CLOCK, CLOCK_DEV_IDX_MOCK_1), + }, + { + /* VPU */ + .element_id = + FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_CLOCK, CLOCK_DEV_IDX_VPU), + }, + { + /* MOCK_3 */ + .element_id = + FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_CLOCK, CLOCK_DEV_IDX_MOCK_3), + }, + { + /* DPU */ + .element_id = + FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_CLOCK, CLOCK_DEV_IDX_DPU), + }, + { + /* PIXEL_0 */ + .element_id = + FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_CLOCK, CLOCK_DEV_IDX_PIXEL_0), + }, + { + /* PIXEL_1 */ + .element_id = + FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_CLOCK, CLOCK_DEV_IDX_PIXEL_1), + }, +}; + +static const struct mod_scmi_clock_device agent_device_table_perf[] = { + { + /* MOCK_0 */ + .element_id = + FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_CLOCK, CLOCK_DEV_IDX_MOCK_0), + }, + { + /* MOCK_2 */ + .element_id = + FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_CLOCK, CLOCK_DEV_IDX_MOCK_2), + }, + { + /* MOCK_3 */ + .element_id = + FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_CLOCK, CLOCK_DEV_IDX_MOCK_3), + }, + { + /* PIXEL_0 */ + .element_id = + FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_CLOCK, CLOCK_DEV_IDX_PIXEL_0), + }, + { + /* PIXEL_1 */ + .element_id = + FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_CLOCK, CLOCK_DEV_IDX_PIXEL_1), + }, +}; + +static const struct mod_scmi_clock_agent agent_table[SCMI_AGENT_ID_COUNT] = { + [SCMI_AGENT_ID_OSPM] = { + .device_table = agent_device_table_ospm, + .device_count = FWK_ARRAY_SIZE(agent_device_table_ospm), + }, + [SCMI_AGENT_ID_PSCI] = { 0 /* No access */ }, + [SCMI_AGENT_ID_PERF] = { + .device_table = agent_device_table_perf, + .device_count = FWK_ARRAY_SIZE(agent_device_table_perf), + }, +}; + +struct fwk_module_config config_scmi_clock = { + .data = &((struct mod_scmi_clock_config) { + .max_pending_transactions = 0, + .agent_table = agent_table, + .agent_count = FWK_ARRAY_SIZE(agent_table), + }), +}; diff --git a/product/optee-fvp/fw/config_scmi_perf.c b/product/optee-fvp/fw/config_scmi_perf.c new file mode 100644 index 0000000000000000000000000000000000000000..63ca90e7b4d620ac7cbdbd4e9207d37a81b751be --- /dev/null +++ b/product/optee-fvp/fw/config_scmi_perf.c @@ -0,0 +1,31 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include "config_dvfs.h" + +static const struct mod_scmi_perf_domain_config domains[] = { + [DVFS_ELEMENT_IDX_LITTLE] = { + .fast_channels_addr_scp = 0x0, + }, + [DVFS_ELEMENT_IDX_BIG] = { + .fast_channels_addr_scp = 0x0, + }, + [DVFS_ELEMENT_IDX_GPU] = { + .fast_channels_addr_scp = 0x0, + }, +}; + +struct fwk_module_config config_scmi_perf = { + .data = &((struct mod_scmi_perf_config) { + .domains = &domains, + .perf_doms_count = FWK_ARRAY_SIZE(domains), + .fast_channels_alarm_id = FWK_ID_NONE_INIT, + }), +}; diff --git a/product/optee-fvp/fw/config_scmi_power_domain.c b/product/optee-fvp/fw/config_scmi_power_domain.c new file mode 100644 index 0000000000000000000000000000000000000000..0740409915e723032ae4852d7c97b20bd6018b28 --- /dev/null +++ b/product/optee-fvp/fw/config_scmi_power_domain.c @@ -0,0 +1,11 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +/* No elements, no module configuration data */ +struct fwk_module_config config_scmi_power_domain = { 0 }; diff --git a/product/optee-fvp/fw/config_sensor.c b/product/optee-fvp/fw/config_sensor.c new file mode 100644 index 0000000000000000000000000000000000000000..20826868113ed5e5d3e217c9db21e050e6437072 --- /dev/null +++ b/product/optee-fvp/fw/config_sensor.c @@ -0,0 +1,100 @@ +/* + * 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 "config_reg_sensor.h" + +uint64_t soc_temp[3] = {25000, 25000, 25000}; +uint64_t ddr_temp[1] = {25000}; +/* + * Register Sensor driver config + */ +static struct mod_sensor_info info_soc_temperature = { + .type = MOD_SENSOR_TYPE_DEGREES_C, + .update_interval = 0, + .update_interval_multiplier = 0, + .unit_multiplier = -3, +}; + +static const struct fwk_element reg_sensor_element_table[] = { + [SENSOR_DEV_SOC_TEMP] = { + .name = "Soc Temperature", + .data = &((struct mod_reg_sensor_dev_config) { + .reg = (uintptr_t)(soc_temp), + .info = &info_soc_temperature, + }), + }, + [SENSOR_DEV_DDR_TEMP] = { + .name = "DDR Temperature", + .data = &((struct mod_reg_sensor_dev_config) { + .reg = (uintptr_t)(ddr_temp), + .info = &info_soc_temperature, + }), + }, + [SENSOR_DEV_COUNT] = { 0 }, +}; + +static const struct fwk_element *get_reg_sensor_element_table(fwk_id_t id) +{ + return reg_sensor_element_table; +} + +struct fwk_module_config config_reg_sensor = { + .elements = FWK_MODULE_DYNAMIC_ELEMENTS(get_reg_sensor_element_table), +}; + +/* + * Sensor module config + */ +static const struct fwk_element sensor_element_table[] = { + [0] = { + .name = "Soc Temperature", + .data = &((const struct mod_sensor_dev_config) { + .driver_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_REG_SENSOR, + SENSOR_DEV_SOC_TEMP), + .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_REG_SENSOR, 0), + .trip_point = { + .count = 2, + } + }), + }, + [1] = { + .name = "DDR Temperature", + .data = &((const struct mod_sensor_dev_config) { + .driver_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_REG_SENSOR, + SENSOR_DEV_DDR_TEMP), + .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_REG_SENSOR, 0), + .trip_point = { + .count = 2, + } + }), + }, + [2] = { 0 }, +}; + +static const struct fwk_element *get_sensor_element_table(fwk_id_t module_id) +{ + return sensor_element_table; +} +static const struct mod_sensor_config sensor_config = { +#ifdef BUILD_HAS_SCMI_NOTIFICATIONS + .notification_id = FWK_ID_MODULE_INIT(FWK_MODULE_IDX_SCMI_SENSOR), + .trip_point_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_SCMI_SENSOR, + SCMI_SENSOR_API_IDX_TRIP_POINT), +#else + .notification_id = FWK_ID_NONE_INIT +#endif +}; + +struct fwk_module_config config_sensor = { + .elements = FWK_MODULE_DYNAMIC_ELEMENTS(get_sensor_element_table), + .data = &sensor_config, +}; diff --git a/product/optee-fvp/fw/config_vpll.c b/product/optee-fvp/fw/config_vpll.c new file mode 100644 index 0000000000000000000000000000000000000000..78874a888bb8633437c5bec1995be26f8b284e03 --- /dev/null +++ b/product/optee-fvp/fw/config_vpll.c @@ -0,0 +1,108 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +uint32_t ctrl_reg[7]; + +static const struct fwk_element system_pll_element_table[] = { + { + .name = "CPU_PLL_0", + .data = &((struct mod_system_pll_dev_config) { + .control_reg = &ctrl_reg[0], + .lock_flag_mask = PLL_STATUS1_CPUPLLLOCK(0, 0), + .initial_rate = 1330 * FWK_MHZ, + .min_rate = MOD_SYSTEM_PLL_MIN_RATE, + .max_rate = MOD_SYSTEM_PLL_MAX_RATE, + .min_step = MOD_SYSTEM_PLL_MIN_INTERVAL, + .defer_initialization = false, + }), + }, + { + .name = "CPU_PLL_1", + .data = &((struct mod_system_pll_dev_config) { + .control_reg = &ctrl_reg[1], + .lock_flag_mask = PLL_STATUS1_CPUPLLLOCK(0, 1), + .initial_rate = 1750 * FWK_MHZ, + .min_rate = MOD_SYSTEM_PLL_MIN_RATE, + .max_rate = MOD_SYSTEM_PLL_MAX_RATE, + .min_step = MOD_SYSTEM_PLL_MIN_INTERVAL, + .defer_initialization = false, + }), + }, + { + .name = "GPU_PLL", + .data = &((struct mod_system_pll_dev_config) { + .control_reg = &ctrl_reg[2], + .lock_flag_mask = PLL_STATUS0_GPUPLLLOCK, + .initial_rate = 600 * FWK_MHZ, + .min_rate = MOD_SYSTEM_PLL_MIN_RATE, + .max_rate = MOD_SYSTEM_PLL_MAX_RATE, + .min_step = MOD_SYSTEM_PLL_MIN_INTERVAL, + .defer_initialization = false, + }), + }, + { + .name = "DPU_PLL", + .data = &((struct mod_system_pll_dev_config) { + .control_reg = &ctrl_reg[3], + .lock_flag_mask = PLL_STATUS0_DISPLAYPLLLOCK, + .initial_rate = 260 * FWK_MHZ, + .min_rate = MOD_SYSTEM_PLL_MIN_RATE, + .max_rate = MOD_SYSTEM_PLL_MAX_RATE, + .min_step = MOD_SYSTEM_PLL_MIN_INTERVAL, + .defer_initialization = false, + }), + }, + { + .name = "VPU_PLL", + .data = &((struct mod_system_pll_dev_config) { + .control_reg = &ctrl_reg[4], + .lock_flag_mask = PLL_STATUS0_VIDEOPLLLOCK, + .initial_rate = 600 * FWK_MHZ, + .min_rate = MOD_SYSTEM_PLL_MIN_RATE, + .max_rate = MOD_SYSTEM_PLL_MAX_RATE, + .min_step = MOD_SYSTEM_PLL_MIN_INTERVAL, + .defer_initialization = false, + }), + }, + { + .name = "PIX0_PLL", + .data = &((struct mod_system_pll_dev_config) { + .control_reg = &ctrl_reg[5], + .initial_rate = 594 * FWK_MHZ, + .min_rate = 12500 * FWK_KHZ, + .max_rate = 594 * FWK_MHZ, + .min_step = 250 * FWK_KHZ, + .defer_initialization = false, + }), + }, + { + .name = "PIX1_PLL", + .data = &((struct mod_system_pll_dev_config) { + .control_reg = &ctrl_reg[6], + .initial_rate = 594 * FWK_MHZ, + .min_rate = 12500 * FWK_KHZ, + .max_rate = 594 * FWK_MHZ, + .min_step = 250 * FWK_KHZ, + .defer_initialization = false, + }), + }, + { 0 }, /* Termination description. */ +}; + +static const struct fwk_element *system_pll_get_element_table + (fwk_id_t module_id) +{ + return system_pll_element_table; +} + +struct fwk_module_config config_system_pll = { + .elements = FWK_MODULE_DYNAMIC_ELEMENTS(system_pll_get_element_table), +}; diff --git a/product/optee-fvp/include/fake_irq.h b/product/optee-fvp/include/fake_irq.h new file mode 100644 index 0000000000000000000000000000000000000000..75e53e5d8b5b56880e34f50a51e99a639c45b043 --- /dev/null +++ b/product/optee-fvp/include/fake_irq.h @@ -0,0 +1,178 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SGM775_IRQ_H +#define SGM775_IRQ_H + +#include + +#define WDOG_IRQ FWK_INTERRUPT_NMI /* SCP Watchdog (SP805) */ + +enum sgm775_irq { + TIM32KHZ_IRQ = 0, /* 32KHz Physical Timer */ + CDBG_PWR_UP_REQ_IRQ = 1, /* Coresight Debug Power Request */ + CSYS_PWR_UP_REQ_IRQ = 2, /* Coresight System Power Request */ + CDBG_RST_REQ_IRQ = 3, /* Coresight Debug Reset Request */ + GIC_EXT_WAKEUP_IRQ = 4, /* External GIC Wakeup Request */ + RESERVED5_IRQ = 5, /* Reserved */ + RESERVED6_IRQ = 6, /* Reserved */ + RESERVED7_IRQ = 7, /* Reserved */ + RESERVED8_IRQ = 8, /* Reserved */ + RESERVED9_IRQ = 9, /* Reserved */ + RESERVED10_IRQ = 10, /* Reserved */ + RESERVED11_IRQ = 11, /* Reserved */ + RESERVED12_IRQ = 12, /* Reserved */ + RESERVED13_IRQ = 13, /* Reserved */ + RESERVED14_IRQ = 14, /* Reserved */ + RESERVED15_IRQ = 15, /* Reserved */ + SOC_WAKEUP0_IRQ = 16, /* SoC Expansion Wakeup */ + SOC_WAKEUP1_IRQ = 17, /* SoC Expansion Wakeup */ + SOC_WAKEUP2_IRQ = 18, /* SoC Expansion Wakeup */ + SOC_WAKEUP3_IRQ = 19, /* SoC Expansion Wakeup */ + SOC_WAKEUP4_IRQ = 20, /* SoC Expansion Wakeup */ + SOC_WAKEUP5_IRQ = 21, /* SoC Expansion Wakeup */ + SOC_WAKEUP6_IRQ = 22, /* SoC Expansion Wakeup */ + SOC_WAKEUP7_IRQ = 23, /* SoC Expansion Wakeup */ + SOC_WAKEUP8_IRQ = 24, /* SoC Expansion Wakeup */ + SOC_WAKEUP9_IRQ = 25, /* SoC Expansion Wakeup */ + SOC_WAKEUP10_IRQ = 26, /* SoC Expansion Wakeup */ + SOC_WAKEUP11_IRQ = 27, /* SoC Expansion Wakeup */ + SOC_WAKEUP12_IRQ = 28, /* SoC Expansion Wakeup */ + SOC_WAKEUP13_IRQ = 29, /* SoC Expansion Wakeup */ + SOC_WAKEUP14_IRQ = 30, /* SoC Expansion Wakeup */ + SOC_WAKEUP15_IRQ = 31, /* SoC Expansion Wakeup */ + PPU_SCP_IRQ = 32, /* SCP Power Policy Unit */ + TIMREFCLK_IRQ = 33, /* REFCLK Physical Timer */ + MHU_HIGH_PRIO_IRQ = 34, /* MHU High Priority */ + MHU_LOW_PRIO_IRQ = 35, /* MHU Low Priority */ + MHU_SECURE_IRQ = 36, /* MHU Secure */ + CTI_TRIGGER0_IRQ = 37, /* SCP CTI Trigger */ + CTI_TRIGGER1_IRQ = 38, /* SCP CTI Trigger */ + GIC_ERROR_ECC_IRQ = 39, /* GIC Error (ECC Fatal) */ + GIC_ERROR_AXIM_IRQ = 40, /* GIC Error (AXIM) */ + DMC_RESERVED0_IRQ = 41, /* DMC, Reserved */ + DMC_0_ERROR_ECC_IRQ = 42, /* DMC0 Combined ECC Error */ + DMC_0_ERROR_ACCESS_IRQ = 43, /* DMC0 Combined Misc Access Error */ + DMC_RESERVED1_IRQ = 44, /* DMC, Reserved */ + DMC_RESERVED2_IRQ = 45, /* DMC, Reserved */ + DMC_1_ERROR_ECC_IRQ = 46, /* DMC1 Combined ECC Error */ + DMC_1_ERROR_ACCESS_IRQ = 47, /* DMC1 Combined Misc Access Error */ + DMC_RESERVED3_IRQ = 48, /* DMC, Reserved */ + DMC_RESERVED4_IRQ = 49, /* DMC, Reserved */ + DMC_2_ERROR_ECC_IRQ = 50, /* DMC2 Combined ECC Error */ + DMC_2_ERROR_ACCESS_IRQ = 51, /* DMC2 Combined Misc Access Error */ + DMC_RESERVED5_IRQ = 52, /* DMC, Reserved */ + DMC_RESERVED6_IRQ = 53, /* DMC, Reserved */ + DMC_3_ERROR_ECC_IRQ = 54, /* DMC3 Combined ECC Error */ + DMC_3_ERROR_ACCESS_IRQ = 55, /* DMC3 Combined Misc Access Error */ + DMC_RESERVED7_IRQ = 56, /* DMC, Reserved */ + RESERVED57_IRQ = 57, /* Reserved */ + RESERVED58_IRQ = 58, /* Reserved */ + RESERVED59_IRQ = 59, /* Reserved */ + RESERVED60_IRQ = 60, /* Reserved */ + RESERVED61_IRQ = 61, /* Reserved */ + RESERVED62_IRQ = 62, /* Reserved */ + RESERVED63_IRQ = 63, /* Reserved */ + PPU_CLUS0CORE0_IRQ = 64, /* Cluster 0 Core 0 Power Policy Unit */ + PPU_CLUS0CORE1_IRQ = 65, /* Cluster 0 Core 1 Power Policy Unit */ + PPU_CLUS0CORE2_IRQ = 66, /* Cluster 0 Core 2 Power Policy Unit */ + PPU_CLUS0CORE3_IRQ = 67, /* Cluster 0 Core 3 Power Policy Unit */ + PPU_CLUS0_IRQ = 68, /* Cluster 0 Power Policy Unit */ + PPU_CLUS1CORE0_IRQ = 69, /* Cluster 1 Core 0 Power Policy Unit */ + PPU_CLUS1CORE1_IRQ = 70, /* Cluster 1 Core 1 Power Policy Unit */ + PPU_CLUS1CORE2_IRQ = 71, /* Cluster 1 Core 2 Power Policy Unit */ + PPU_CLUS1CORE3_IRQ = 72, /* Cluster 1 Core 3 Power Policy Unit */ + PPU_CLUS1_IRQ = 73, /* Cluster 1 Power Policy Unit */ + PPU_SYS0_IRQ = 74, /* System Power Policy Unit 0 */ + PPU_SYS1_IRQ = 75, /* System Power Policy Unit 1 */ + PPU_GPU_IRQ = 76, /* GPU Power Policy Unit */ + PPU_VPU_IRQ = 77, /* Video Power Policy Unit */ + RESERVED78_IRQ = 78, /* Reserved */ + PPU_DPU0_IRQ = 79, /* Display Power Policy Unit 0 */ + PPU_DPU1_IRQ = 80, /* Display Power Policy Unit 1 */ + PPU_DEBUG_IRQ = 81, /* DBGSYS Power Policy Unit */ + RESERVED82_IRQ = 82, /* Reserved */ + RESERVED83_IRQ = 83, /* Reserved */ + RESERVED84_IRQ = 84, /* Reserved */ + RESERVED85_IRQ = 85, /* Reserved */ + RESERVED86_IRQ = 86, /* Reserved */ + RESERVED87_IRQ = 87, /* Reserved */ + RESERVED88_IRQ = 88, /* Reserved */ + RESERVED89_IRQ = 89, /* Reserved */ + PPU_CLUS0CORE4_IRQ = 90, /* Cluster 0 Core 4 Power Policy Unit */ + PPU_CLUS0CORE5_IRQ = 91, /* Cluster 0 Core 5 Power Policy Unit */ + PPU_CLUS0CORE6_IRQ = 92, /* Cluster 0 Core 6 Power Policy Unit */ + PPU_CLUS0CORE7_IRQ = 93, /* Cluster 0 Core 7 Power Policy Unit */ + PPU_CLUS1CORE4_IRQ = 94, /* Cluster 1 Core 4 Power Policy Unit */ + PPU_CLUS1CORE5_IRQ = 95, /* Cluster 1 Core 5 Power Policy Unit */ + PPU_CLUS1CORE6_IRQ = 96, /* Cluster 1 Core 6 Power Policy Unit */ + PPU_CLUS1CORE7_IRQ = 97, /* Cluster 1 Core 7 Power Policy Unit */ + PLL_CLUS0_LOCK_IRQ = 98, /* Cluster 0 CPU PLL Lock */ + PLL_CLUS1_LOCK_IRQ = 99, /* Cluster 1 CPU PLL Lock */ + PLL_GPU_LOCK_IRQ = 100, /* GPU PLL Lock */ + PLL_VPU_LOCK_IRQ = 101, /* Video PLL Lock */ + PLL_SYS_LOCK_IRQ = 102, /* System PLL Lock */ + PLL_DPU_LOCK_IRQ = 103, /* Display PLL Lock */ + PLL_CLUS0CORE0_IRQ = 104, /* Cluster 0 PLL0 Lock */ + PLL_CLUS0CORE1_IRQ = 105, /* Cluster 0 PLL1 Lock */ + PLL_CLUS0CORE2_IRQ = 106, /* Cluster 0 PLL2 Lock */ + PLL_CLUS0CORE3_IRQ = 107, /* Cluster 0 PLL3 Lock */ + PLL_CLUS0CORE4_IRQ = 108, /* Cluster 0 PLL4 Lock */ + PLL_CLUS0CORE5_IRQ = 109, /* Cluster 0 PLL5 Lock */ + PLL_CLUS0CORE6_IRQ = 110, /* Cluster 0 PLL6 Lock */ + PLL_CLUS0CORE7_IRQ = 111, /* Cluster 0 PLL7 Lock */ + PLL_CLUS1CORE0_IRQ = 112, /* Cluster 1 PLL0 Lock */ + PLL_CLUS1CORE1_IRQ = 113, /* Cluster 1 PLL1 Lock */ + PLL_CLUS1CORE2_IRQ = 114, /* Cluster 1 PLL2 Lock */ + PLL_CLUS1CORE3_IRQ = 115, /* Cluster 1 PLL3 Lock */ + PLL_CLUS1CORE4_IRQ = 116, /* Cluster 1 PLL4 Lock */ + PLL_CLUS1CORE5_IRQ = 117, /* Cluster 1 PLL5 Lock */ + PLL_CLUS1CORE6_IRQ = 118, /* Cluster 1 PLL6 Lock */ + PLL_CLUS1CORE7_IRQ = 119, /* Cluster 1 PLL7 Lock */ + RESERVED120_IRQ = 120, /* Reserved */ + RESERVED121_IRQ = 121, /* Reserved */ + RESERVED122_IRQ = 122, /* Reserved */ + RESERVED123_IRQ = 123, /* Reserved */ + RESERVED124_IRQ = 124, /* Reserved */ + RESERVED125_IRQ = 125, /* Reserved */ + RESERVED126_IRQ = 126, /* Reserved */ + RESERVED127_IRQ = 127, /* Reserved */ + SCP_EXT_INTR0_IRQ = 128, /* SCP Customer Extension */ + SCP_EXT_INTR1_IRQ = 129, /* SCP Customer Extension */ + SCP_EXT_INTR2_IRQ = 130, /* SCP Customer Extension */ + SCP_EXT_INTR3_IRQ = 131, /* SCP Customer Extension */ + SCP_EXT_INTR4_IRQ = 132, /* SCP Customer Extension */ + SCP_EXT_INTR5_IRQ = 133, /* SCP Customer Extension */ + SCP_EXT_INTR6_IRQ = 134, /* SCP Customer Extension */ + SCP_EXT_INTR7_IRQ = 135, /* SCP Customer Extension */ + SCP_EXT_INTR8_IRQ = 136, /* SCP Customer Extension */ + SCP_EXT_INTR9_IRQ = 137, /* SCP Customer Extension */ + SCP_EXT_INTR10_IRQ = 138, /* SCP Customer Extension */ + SCP_EXT_INTR11_IRQ = 139, /* SCP Customer Extension */ + SCP_EXT_INTR12_IRQ = 140, /* SCP Customer Extension */ + SCP_EXT_INTR13_IRQ = 141, /* SCP Customer Extension */ + SCP_EXT_INTR14_IRQ = 142, /* SCP Customer Extension */ + SCP_EXT_INTR15_IRQ = 143, /* SCP Customer Extension */ + SCP_EXT_INTR16_IRQ = 144, /* SCP Customer Extension */ + SCP_EXT_INTR17_IRQ = 145, /* SCP Customer Extension */ + SCP_EXT_INTR18_IRQ = 146, /* SCP Customer Extension */ + SCP_EXT_INTR19_IRQ = 147, /* SCP Customer Extension */ + SCP_EXT_INTR20_IRQ = 148, /* SCP Customer Extension */ + SCP_EXT_INTR21_IRQ = 149, /* SCP Customer Extension */ + SCP_EXT_INTR22_IRQ = 150, /* SCP Customer Extension */ + SCP_EXT_INTR23_IRQ = 151, /* SCP Customer Extension */ + SCP_EXT_INTR24_IRQ = 152, /* SCP Customer Extension */ + SCP_EXT_INTR25_IRQ = 153, /* SCP Customer Extension */ + SCP_EXT_INTR26_IRQ = 154, /* SCP Customer Extension */ + SCP_EXT_INTR27_IRQ = 155, /* SCP Customer Extension */ + SCP_EXT_INTR28_IRQ = 156, /* SCP Customer Extension */ + SCP_EXT_INTR29_IRQ = 157, /* SCP Customer Extension */ + SCP_EXT_INTR30_IRQ = 158, /* SCP Customer Extension */ + SCP_EXT_INTR31_IRQ = 159, /* SCP Customer Extension */ +}; + +#endif /* SGM775_IRQ_H */ diff --git a/product/optee-fvp/include/fake_mmap.h b/product/optee-fvp/include/fake_mmap.h new file mode 100644 index 0000000000000000000000000000000000000000..c3643fc6ccccc2c41d311ec594c5b245e0554179 --- /dev/null +++ b/product/optee-fvp/include/fake_mmap.h @@ -0,0 +1,101 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SGM775_MMAP_H +#define SGM775_MMAP_H + +#include + +/* + * Top-level base addresses + */ +#define EXPANSION0_BASE UINT32_C(0x40000000) +#define PERIPHERAL_BASE UINT32_C(0x44000000) +#define POWER_PERIPHERAL_BASE UINT32_C(0x50000000) +#define SYS0_BASE UINT32_C(0x60000000) +#define SYS1_BASE UINT32_C(0xA0000000) +#define PPB_INTERNAL_BASE UINT32_C(0xE0000000) +#define PPB_EXTERNAL_BASE UINT32_C(0xE0040000) +#define EXPANSION1_BASE UINT32_C(0xE0100000) + +/* + * Peripherals + */ +#define REFCLK_CNTCTL_BASE (PERIPHERAL_BASE + 0x0000) +#define REFCLK_CNTBASE0_BASE (PERIPHERAL_BASE + 0x1000) +#define WDOG_BASE (PERIPHERAL_BASE + 0x6000) +#define S32K_CNTCONTROL_BASE (PERIPHERAL_BASE + 0x7000) +#define S32K_CNTCTL_BASE (PERIPHERAL_BASE + 0x8000) +#define S32K_CNTBASE0_BASE (PERIPHERAL_BASE + 0x9000) +#define CS_CNTCONTROL_BASE (PERIPHERAL_BASE + 0xA000) + +/* + * Power control peripherals + */ +#define PIK_SCP_BASE (POWER_PERIPHERAL_BASE + 0x00000) +#define PIK_DEBUG_BASE (POWER_PERIPHERAL_BASE + 0x20000) +#define SENSOR_DEBUG_BASE (POWER_PERIPHERAL_BASE + 0x30000) +#define PIK_SYSTEM_BASE (POWER_PERIPHERAL_BASE + 0x40000) +#define SENSOR_SYSTEM_BASE (POWER_PERIPHERAL_BASE + 0x50000) +#define PIK_CLUS0_BASE (POWER_PERIPHERAL_BASE + 0x60000) +#define SENSOR_CLUS0_BASE (POWER_PERIPHERAL_BASE + 0x70000) +#define PIK_CLUS1_BASE (POWER_PERIPHERAL_BASE + 0x80000) +#define SENSOR_CLUS1_BASE (POWER_PERIPHERAL_BASE + 0x90000) +#define PIK_GPU_BASE (POWER_PERIPHERAL_BASE + 0xA0000) +#define SENSOR_GPU_BASE (POWER_PERIPHERAL_BASE + 0xB0000) +#define PIK_VPU_BASE (POWER_PERIPHERAL_BASE + 0xC0000) +#define SENSOR_VPU_BASE (POWER_PERIPHERAL_BASE + 0xD0000) +#define PIK_DPU_BASE (POWER_PERIPHERAL_BASE + 0xE0000) +#define SENSOR_DPU_BASE (POWER_PERIPHERAL_BASE + 0xF0000) + +/* + * PPU base address + */ +#define PPU_SCP_BASE (PIK_SCP_BASE + 0x1000) +#define PPU_SYS0_BASE (PIK_SYSTEM_BASE + 0x1000) +#define PPU_SYS1_BASE (PIK_SYSTEM_BASE + 0x2000) +#define PPU_DEBUG_BASE (PIK_DEBUG_BASE + 0x1000) +#define PPU_CLUS0CORE0_BASE (PIK_CLUS0_BASE + 0x2000) +#define PPU_CLUS0CORE1_BASE (PIK_CLUS0_BASE + 0x3000) +#define PPU_CLUS0CORE2_BASE (PIK_CLUS0_BASE + 0x4000) +#define PPU_CLUS0CORE3_BASE (PIK_CLUS0_BASE + 0x5000) +#define PPU_CLUS0CORE4_BASE (PIK_CLUS0_BASE + 0x6000) +#define PPU_CLUS0CORE5_BASE (PIK_CLUS0_BASE + 0x7000) +#define PPU_CLUS0CORE6_BASE (PIK_CLUS0_BASE + 0x8000) +#define PPU_CLUS0CORE7_BASE (PIK_CLUS0_BASE + 0x9000) +#define PPU_CLUS0_BASE (PIK_CLUS0_BASE + 0x1000) +#define PPU_CLUS1CORE0_BASE (PIK_CLUS1_BASE + 0x2000) +#define PPU_CLUS1CORE1_BASE (PIK_CLUS1_BASE + 0x3000) +#define PPU_CLUS1CORE2_BASE (PIK_CLUS1_BASE + 0x4000) +#define PPU_CLUS1CORE3_BASE (PIK_CLUS1_BASE + 0x5000) +#define PPU_CLUS1_BASE (PIK_CLUS1_BASE + 0x1000) +#define PPU_GPU_BASE (PIK_GPU_BASE + 0x1000) +#define PPU_VPU_BASE (PIK_VPU_BASE + 0x1000) +#define PPU_DPU0_BASE (PIK_DPU_BASE + 0x2000) +#define PPU_DPU1_BASE (PIK_DPU_BASE + 0x3000) + +/* + * System access port 1 + */ +#define TRUSTED_RAM_BASE (SYS1_BASE + 0x04000000) +#define NONTRUSTED_RAM_BASE (SYS1_BASE + 0x06000000) +#define SSC_BASE (SYS1_BASE + 0x2A420000) +#define REFCLK_CNTCONTROL_BASE (SYS1_BASE + 0x2A430000) +#define MHU_BASE (SYS1_BASE + 0x2B1F0000) + +/* + * Base addresses of MHU devices + */ + +#define MHU_SCP_INTR_L_BASE (MHU_BASE) +#define MHU_SCP_INTR_H_BASE (MHU_BASE + 0x0020) +#define MHU_CPU_INTR_L_BASE (MHU_BASE + 0x0100) +#define MHU_CPU_INTR_H_BASE (MHU_BASE + 0x0120) +#define MHU_SCP_INTR_S_BASE (MHU_BASE + 0x0200) +#define MHU_CPU_INTR_S_BASE (MHU_BASE + 0x0300) + +#endif /* SGM775_MMAP_H */ diff --git a/product/optee-fvp/include/fake_pik.h b/product/optee-fvp/include/fake_pik.h new file mode 100644 index 0000000000000000000000000000000000000000..f0d78e1a5ee02247274aae3ccb150702deec4184 --- /dev/null +++ b/product/optee-fvp/include/fake_pik.h @@ -0,0 +1,13 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef FAKE_PIK_H +#define FAKE_PIK_H + +#include + +#endif /* SGM775_PIK_H */ diff --git a/product/optee-fvp/include/fake_pik_scp.h b/product/optee-fvp/include/fake_pik_scp.h new file mode 100644 index 0000000000000000000000000000000000000000..458ca3755e71fb9a440508b0e42e904d9573ab00 --- /dev/null +++ b/product/optee-fvp/include/fake_pik_scp.h @@ -0,0 +1,63 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef FAKE_PIK_SCP_H +#define FAKE_PIK_SCP_H + +#include +#include + +/*! + * \brief SCP PIK register definitions + */ +struct pik_scp_reg { + uint32_t RESERVED0[4]; + FWK_RW uint32_t RESET_SYNDROME; + FWK_RW uint32_t WIC_CTRL; + FWK_R uint32_t WIC_STATUS; + uint8_t RESERVED1[0xA00 - 0x1C]; + FWK_R uint32_t CLKFORCE_STATUS; + FWK_RW uint32_t CLKFORCE_SET; + FWK_RW uint32_t CLKFORCE_CLR; + uint32_t RESERVED2; + FWK_R uint32_t PLL_STATUS0; + FWK_R uint32_t PLL_STATUS1; + uint8_t RESERVED3[0xFC0 - 0xA18]; + FWK_R uint32_t PIK_CONFIG; + uint32_t RESERVED4[3]; + FWK_R uint32_t PID4; + FWK_R uint32_t PID5; + FWK_R uint32_t PID6; + FWK_R uint32_t PID7; + FWK_R uint32_t PID0; + FWK_R uint32_t PID1; + FWK_R uint32_t PID2; + FWK_R uint32_t PID3; + FWK_R uint32_t ID0; + FWK_R uint32_t ID1; + FWK_R uint32_t ID2; + FWK_R uint32_t ID3; +}; + +#define PLL_STATUS0_REFCLK UINT32_C(0x00000001) +#define PLL_STATUS0_BCPUPLLLOCK UINT32_C(0x00000002) +#define PLL_STATUS0_LCPUPLLLOCK UINT32_C(0x00000004) +#define PLL_STATUS0_GPUPLLLOCK UINT32_C(0x00000008) +#define PLL_STATUS0_VIDEOPLLLOCK UINT32_C(0x00000010) +#define PLL_STATUS0_SYSPLLLOCK UINT32_C(0x00000020) +#define PLL_STATUS0_DISPLAYPLLLOCK UINT32_C(0x00000040) + +#define PLL_STATUS1_CPUPLLLOCK(CPU, PLL) \ + ((uint32_t)((1 << (PLL)) << ((CPU) * 8))) + +#define RESET_SYNDROME_PORESET UINT32_C(0x01) +#define RESET_SYNDROME_WDOGRESET_SCP UINT32_C(0x02) +#define RESET_SYNDROME_WDOGRESET_SYS UINT32_C(0x04) +#define RESET_SYNDROME_SYSRESETREQ UINT32_C(0x08) +#define RESET_SYNDROME_SCPM3LOCKUP UINT32_C(0x10) + +#endif /* FAKE_PIK_SCP_H */ diff --git a/product/optee-fvp/include/fmw_io.h b/product/optee-fvp/include/fmw_io.h new file mode 100644 index 0000000000000000000000000000000000000000..a5bc6226cea5c0cdefad05ef62c6505315488235 --- /dev/null +++ b/product/optee-fvp/include/fmw_io.h @@ -0,0 +1,18 @@ +/* + * 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-fvp/include/fmw_log.h b/product/optee-fvp/include/fmw_log.h new file mode 100644 index 0000000000000000000000000000000000000000..4e0bdd0ee4f2eb0b4f153112af3bd61e0599ebe4 --- /dev/null +++ b/product/optee-fvp/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-fvp/include/scmi_agents.h b/product/optee-fvp/include/scmi_agents.h new file mode 100644 index 0000000000000000000000000000000000000000..ab5580fb515aaee84998ed0751499b8b31d38800 --- /dev/null +++ b/product/optee-fvp/include/scmi_agents.h @@ -0,0 +1,44 @@ +/* + * 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 { + /* 0 is reserved for the platform */ + SCMI_AGENT_ID_OSPM = 1, + SCMI_AGENT_ID_PSCI, + SCMI_AGENT_ID_PERF, + SCMI_AGENT_ID_COUNT, +}; + +enum scmi_service_idx { + SCMI_SERVICE_IDX_PSCI, + SCMI_SERVICE_IDX_OSPM_0, + SCMI_SERVICE_IDX_OSPM_1, +#ifdef BUILD_HAS_SCMI_NOTIFICATIONS + SCMI_SERVICE_IDX_OSPM_0_P2A, + SCMI_SERVICE_IDX_OSPM_1_P2A, +#endif + SCMI_SERVICE_IDX_COUNT, +}; + +enum scmi_channel_device_idx { + // TODO: change this: current code support device#0 only + SCMI_CHANNEL_DEVICE_IDX_PSCI, + SCMI_CHANNEL_DEVICE_IDX_OSPM_0, + SCMI_CHANNEL_DEVICE_IDX_OSPM_1, +#ifdef BUILD_HAS_SCMI_NOTIFICATIONS + SCMI_CHANNEL_DEVICE_IDX_OSPM_0_P2A, +#endif +#ifdef BUILD_HAS_SCMI_NOTIFICATIONS + SCMI_CHANNEL_DEVICE_IDX_OSPM_1_P2A, +#endif + SCMI_CHANNEL_DEVICE_IDX_COUNT +}; + +#endif /* SCMI_AGENTS_H */ diff --git a/product/optee-fvp/module/vppu/CMakeLists.txt b/product/optee-fvp/module/vppu/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..c950cbd169b908d168db3b16a61bb6330c7a3a1d --- /dev/null +++ b/product/optee-fvp/module/vppu/CMakeLists.txt @@ -0,0 +1,21 @@ +# +# Arm SCP/MCP Software +# Copyright (c) 2022, 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") + +target_sources( + ${SCP_MODULE_TARGET} PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/src/mod_ppu_v0.c" + "${CMAKE_CURRENT_SOURCE_DIR}/src/ppu_v0.c") + +target_link_libraries(${SCP_MODULE_TARGET} PRIVATE module-power-domain) + +if("system-power" IN_LIST SCP_MODULES) + target_link_libraries(${SCP_MODULE_TARGET} PRIVATE module-system-power) +endif() diff --git a/product/optee-fvp/module/vppu/Module.cmake b/product/optee-fvp/module/vppu/Module.cmake new file mode 100644 index 0000000000000000000000000000000000000000..558e7c273e6ea3e7691cf2a9f46d93d2a1caaf96 --- /dev/null +++ b/product/optee-fvp/module/vppu/Module.cmake @@ -0,0 +1,9 @@ +# +# Arm SCP/MCP Software +# Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +set(SCP_MODULE "vppu") +set(SCP_MODULE_TARGET "module-vppu") diff --git a/product/optee-fvp/module/vppu/include/mod_ppu_v0.h b/product/optee-fvp/module/vppu/include/mod_ppu_v0.h new file mode 100644 index 0000000000000000000000000000000000000000..981562300741c866dcc45523eda4cd1027531df0 --- /dev/null +++ b/product/optee-fvp/module/vppu/include/mod_ppu_v0.h @@ -0,0 +1,63 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Description: + * Virtual PPU v0 driver module + */ + +#ifndef MOD_PPU_V0_H +#define MOD_PPU_V0_H + +#include +#include +#include + +/*! + * \addtogroup GroupModules Modules + * @{ + */ + +/*! + * \defgroup GroupModulePPUv0 PPUv0 Driver + * @{ + */ + +/*! + * \brief Power domain PPU descriptor. + */ +struct mod_ppu_v0 { + /*! Base address of the PPU registers */ + uintptr_t reg_base; + + /*! PPU's IRQ number */ + unsigned int irq; +}; + +/*! + * \brief Configuration data of a power domain of the PPU_V0 driver module. + */ +struct mod_ppu_v0_pd_config { + /*! Power domain type */ + enum mod_pd_type pd_type; + + /*! PPU descriptor */ + struct mod_ppu_v0 ppu; + + /*! + * Flag indicating if this domain should be powered on during element init. + */ + bool default_power_on; +}; + +/*! + * @} + */ + +/*! + * @} + */ + +#endif /* MOD_PPU_V0_H */ diff --git a/product/optee-fvp/module/vppu/src/mod_ppu_v0.c b/product/optee-fvp/module/vppu/src/mod_ppu_v0.c new file mode 100644 index 0000000000000000000000000000000000000000..038a3760acf236f2543eb9aa03588a90901c6a90 --- /dev/null +++ b/product/optee-fvp/module/vppu/src/mod_ppu_v0.c @@ -0,0 +1,306 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Description: + * Power State Management PPU v0 driver. + */ + +#include +#include +#include +#include +#include +#include +#include +#if BUILD_HAS_MOD_SYSTEM_POWER +#include +#endif +#include "ppu_v0.h" + +/* Power domain context */ +struct ppu_v0_pd_ctx { + /* Power domain configuration data */ + const struct mod_ppu_v0_pd_config *config; + + /* PPU registers */ + struct ppu_v0_reg *ppu; + + /* Identifier of the entity bound to the power domain driver API */ + fwk_id_t bound_id; + + /* Power module driver input API */ + struct mod_pd_driver_input_api *pd_driver_input_api; +}; + +/* Module context */ +struct ppu_v0_ctx { + /* Table of the power domain contexts */ + struct ppu_v0_pd_ctx *pd_ctx_table; +}; + +/* + * Internal variables + */ + +static struct ppu_v0_ctx ppu_v0_ctx; + +#define MODE_UNSUPPORTED ~0U +static const uint8_t ppu_mode_to_power_state[] = { + [PPU_V0_MODE_ON] = (uint8_t)MOD_PD_STATE_ON, + [PPU_V0_MODE_FUNC_RET] = (uint8_t)MOD_PD_STATE_ON, + [PPU_V0_MODE_MEM_OFF] = (uint8_t)MODE_UNSUPPORTED, + [PPU_V0_MODE_FULL_RET] = (uint8_t)MOD_PD_STATE_ON, + [PPU_V0_MODE_LOGIC_RET] = (uint8_t)MODE_UNSUPPORTED, + [PPU_V0_MODE_MEM_RET] = (uint8_t)MOD_PD_STATE_ON, + [PPU_V0_MODE_OFF] = (uint8_t)MOD_PD_STATE_OFF, + [PPU_V0_MODE_WARM_RESET] = (uint8_t)MODE_UNSUPPORTED, +}; + +/* + * Power domain driver interface + */ + +/* Driver functions not specific to any type of power domain. */ +static int get_state(struct ppu_v0_reg *ppu, unsigned int *state) +{ + enum ppu_v0_mode ppu_mode; + + /* Ensure ppu_mode_to_power_state has an entry for each PPU state */ + static_assert(FWK_ARRAY_SIZE(ppu_mode_to_power_state) == PPU_V0_MODE_COUNT, + "[MOD_PPU_V0] ppu_mode_to_power_state size error"); + + ppu_v0_get_power_mode(ppu, &ppu_mode); + assert(ppu_mode < PPU_V0_MODE_COUNT); + + *state = ppu_mode_to_power_state[ppu_mode]; + if (*state == MODE_UNSUPPORTED) { + FWK_LOG_ERR("[PD] Unexpected PPU mode (%i).\n", ppu_mode); + + return FWK_E_DEVICE; + } + + return FWK_SUCCESS; +} + +static int pd_init(struct ppu_v0_pd_ctx *pd_ctx) +{ + ppu_v0_init(pd_ctx->ppu); + + return FWK_SUCCESS; +} + +static int pd_set_state(fwk_id_t pd_id, unsigned int state) +{ + int status; + struct ppu_v0_pd_ctx *pd_ctx; + + pd_ctx = ppu_v0_ctx.pd_ctx_table + fwk_id_get_element_idx(pd_id); + + fwk_assert(pd_ctx->pd_driver_input_api != NULL); + + switch (state) { + case MOD_PD_STATE_ON: + ppu_v0_set_power_mode(pd_ctx->ppu, PPU_V0_MODE_ON); + status = pd_ctx->pd_driver_input_api->report_power_state_transition( + pd_ctx->bound_id, MOD_PD_STATE_ON); + assert(status == FWK_SUCCESS); + break; + + case MOD_PD_STATE_OFF: + ppu_v0_set_power_mode(pd_ctx->ppu, PPU_V0_MODE_OFF); + status = pd_ctx->pd_driver_input_api->report_power_state_transition( + pd_ctx->bound_id, MOD_PD_STATE_OFF); + assert(status == FWK_SUCCESS); + break; + + default: + FWK_LOG_ERR("[PD] Requested power state (%i) is not supported.\n", state); + return FWK_E_PARAM; + } + + if (status != FWK_SUCCESS) + return FWK_E_PANIC; + + return FWK_SUCCESS; +} + +static int pd_get_state(fwk_id_t pd_id, unsigned int *state) +{ + struct ppu_v0_pd_ctx *pd_ctx; + + pd_ctx = ppu_v0_ctx.pd_ctx_table + fwk_id_get_element_idx(pd_id); + + return get_state(pd_ctx->ppu, state); +} + +static int pd_reset(fwk_id_t pd_id) +{ + int status; + struct ppu_v0_pd_ctx *pd_ctx; + + pd_ctx = ppu_v0_ctx.pd_ctx_table + fwk_id_get_element_idx(pd_id); + + /* Model does not support warm reset at the moment. Using OFF instead. */ + status = ppu_v0_set_power_mode(pd_ctx->ppu, PPU_V0_MODE_OFF); + if (status == FWK_SUCCESS) + status = ppu_v0_set_power_mode(pd_ctx->ppu, PPU_V0_MODE_ON); + + return status; +} + +static int ppu_v0_prepare_core_for_system_suspend(fwk_id_t core_pd_id) +{ + return FWK_SUCCESS; +} + + +static const struct mod_pd_driver_api pd_driver = { + .set_state = pd_set_state, + .get_state = pd_get_state, + .reset = pd_reset, + .prepare_core_for_system_suspend = ppu_v0_prepare_core_for_system_suspend, +}; + +/* + * Framework handlers + */ + +static int ppu_v0_mod_init(fwk_id_t module_id, unsigned int pd_count, + const void *unused) +{ + ppu_v0_ctx.pd_ctx_table = fwk_mm_calloc(pd_count, + sizeof(struct ppu_v0_pd_ctx)); + if (ppu_v0_ctx.pd_ctx_table == NULL) + return FWK_E_NOMEM; + + return FWK_SUCCESS; +} + +static int ppu_v0_pd_init(fwk_id_t pd_id, unsigned int unused, const void *data) +{ + const struct mod_ppu_v0_pd_config *config = data; + struct ppu_v0_pd_ctx *pd_ctx; + int status; + + if (config->pd_type >= MOD_PD_TYPE_COUNT) + return FWK_E_DATA; + + pd_ctx = ppu_v0_ctx.pd_ctx_table + fwk_id_get_element_idx(pd_id); + pd_ctx->config = config; + pd_ctx->ppu = (struct ppu_v0_reg *)(config->ppu.reg_base); + pd_ctx->bound_id = FWK_ID_NONE; + + switch (config->pd_type) { + case MOD_PD_TYPE_DEVICE: + case MOD_PD_TYPE_DEVICE_DEBUG: + case MOD_PD_TYPE_SYSTEM: + status = pd_init(pd_ctx); + if (status != FWK_SUCCESS) + return status; + + if (config->default_power_on) + return ppu_v0_set_power_mode(pd_ctx->ppu, PPU_V0_MODE_ON); + + return FWK_SUCCESS; + + default: + return FWK_E_SUPPORT; + } +} + +static int ppu_v0_bind(fwk_id_t id, unsigned int round) +{ + struct ppu_v0_pd_ctx *pd_ctx; + + /* Nothing to do during the first round of calls where the power module + will bind to the power domains of this module. */ + if (round == 0) + return FWK_SUCCESS; + + /* In the case of the module, nothing to do */ + if (fwk_module_is_valid_module_id(id)) { + return FWK_SUCCESS; + } + + pd_ctx = ppu_v0_ctx.pd_ctx_table + fwk_id_get_element_idx(id); + + if (fwk_id_is_equal(pd_ctx->bound_id, FWK_ID_NONE)) + return FWK_SUCCESS; + + switch (fwk_id_get_module_idx(pd_ctx->bound_id)) { + #if BUILD_HAS_MOD_POWER_DOMAIN + case FWK_MODULE_IDX_POWER_DOMAIN: + return fwk_module_bind(pd_ctx->bound_id, + mod_pd_api_id_driver_input, + &pd_ctx->pd_driver_input_api); + break; + #endif + + #if BUILD_HAS_MOD_SYSTEM_POWER + case FWK_MODULE_IDX_SYSTEM_POWER: + return fwk_module_bind(pd_ctx->bound_id, + mod_system_power_api_id_pd_driver_input, + &pd_ctx->pd_driver_input_api); + break; + #endif + + default: + assert(false); + return FWK_E_SUPPORT; + } +} + +static int ppu_v0_process_bind_request(fwk_id_t source_id, + fwk_id_t target_id, fwk_id_t not_used, + const void **api) +{ + struct ppu_v0_pd_ctx *pd_ctx; + + pd_ctx = ppu_v0_ctx.pd_ctx_table + fwk_id_get_element_idx(target_id); + + switch (pd_ctx->config->pd_type) { + case MOD_PD_TYPE_SYSTEM: + if (!fwk_id_is_equal(pd_ctx->bound_id, FWK_ID_NONE)) { + assert(false); + return FWK_E_ACCESS; + } + /* Fallthrough */ + + case MOD_PD_TYPE_DEVICE: + case MOD_PD_TYPE_DEVICE_DEBUG: + #if BUILD_HAS_MOD_POWER_DOMAIN + if (fwk_id_get_module_idx(source_id) == FWK_MODULE_IDX_POWER_DOMAIN) { + pd_ctx->bound_id = source_id; + *api = &pd_driver; + break; + } + #endif + #if BUILD_HAS_MOD_SYSTEM_POWER + if (fwk_id_get_module_idx(source_id) == FWK_MODULE_IDX_SYSTEM_POWER) { + pd_ctx->bound_id = source_id; + *api = &pd_driver; + break; + } + #endif + assert(false); + return FWK_E_ACCESS; + + default: + (void)pd_driver; + return FWK_E_SUPPORT; + } + + return FWK_SUCCESS; +} + +const struct fwk_module module_vppu = { + .type = FWK_MODULE_TYPE_DRIVER, + .api_count = 1, + .init = ppu_v0_mod_init, + .element_init = ppu_v0_pd_init, + .bind = ppu_v0_bind, + .process_bind_request = ppu_v0_process_bind_request, +}; diff --git a/product/optee-fvp/module/vppu/src/ppu_v0.c b/product/optee-fvp/module/vppu/src/ppu_v0.c new file mode 100644 index 0000000000000000000000000000000000000000..5a19777a436df95fa8d8d1772d8d17715a594098 --- /dev/null +++ b/product/optee-fvp/module/vppu/src/ppu_v0.c @@ -0,0 +1,65 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include "ppu_v0.h" + +void ppu_v0_init(struct ppu_v0_reg *ppu) +{ + assert(ppu != NULL); + + /* Set mode as masked to all input edge interrupts */ + ppu->IESR = 0; + + /* Mask all interrupts */ + ppu->IMR = PPU_V0_IMR_MASK; + + /* Acknowledge any interrupt left pending */ + ppu->ISR = PPU_V0_ISR_MASK; +} + +int ppu_v0_request_power_mode(struct ppu_v0_reg *ppu, enum ppu_v0_mode mode) +{ + uint32_t power_policy; + assert(ppu != NULL); + assert(mode < PPU_V0_MODE_COUNT); + + power_policy = ppu->POWER_POLICY & + ~(PPU_V0_PPR_POLICY | PPU_V0_PPR_DYNAMIC_EN); + ppu->POWER_POLICY = power_policy | mode; + ppu->POWER_STATUS = power_policy | mode; + + return FWK_SUCCESS; +} + +int ppu_v0_set_power_mode(struct ppu_v0_reg *ppu, enum ppu_v0_mode mode) +{ + int status; + assert(ppu != NULL); + + status = ppu_v0_request_power_mode(ppu, mode); + if (status != FWK_SUCCESS) + return status; + + while ((ppu->POWER_STATUS & (PPU_V0_PSR_POWSTAT | PPU_V0_PSR_DYNAMIC)) + != mode) + continue; + + return FWK_SUCCESS; +} + +int ppu_v0_get_power_mode(struct ppu_v0_reg *ppu, enum ppu_v0_mode *mode) +{ + assert(ppu != NULL); + assert(mode != NULL); + + *mode = (enum ppu_v0_mode)(ppu->POWER_STATUS & PPU_V0_PSR_POWSTAT); + + return FWK_SUCCESS; +} diff --git a/product/optee-fvp/module/vppu/src/ppu_v0.h b/product/optee-fvp/module/vppu/src/ppu_v0.h new file mode 100644 index 0000000000000000000000000000000000000000..fc7fe26b40f2883fdf49fa44f636711942b5bc6f --- /dev/null +++ b/product/optee-fvp/module/vppu/src/ppu_v0.h @@ -0,0 +1,144 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PPU_V0_H +#define PPU_V0_H + +/*! + * \cond + * @{ + */ + +#include +#include +#include + +struct ppu_v0_reg { + FWK_RW uint32_t POWER_POLICY; + FWK_RW uint32_t POWER_STATUS; + FWK_R uint32_t STATIC_CFG_STATUS; + FWK_R uint32_t DEV_IF_IP_CUR_STATUS; + FWK_R uint32_t MISC_IP_CUR_STATUS; + FWK_R uint32_t STORED_STATUS; + FWK_W uint32_t OFF_MEM_RET_UNLOCK; + uint32_t RESERVED0; + FWK_RW uint32_t POWER_CFG; + uint32_t RESERVED1[3]; + FWK_RW uint32_t IMR; + FWK_RW uint32_t ISR; + FWK_RW uint32_t IESR; + uint32_t RESERVED2[5]; + FWK_RW uint32_t FUNC_RET_RAM_CFG; + FWK_RW uint32_t FULL_RET_RAM_CFG; + FWK_RW uint32_t MEM_RET_RAM_CFG; + uint32_t RESERVED3; + FWK_RW uint32_t MODE_ENTRY_DELAY_TIME_0; + FWK_RW uint32_t MODE_ENTRY_DELAY_TIME_1; + uint32_t RESERVED4[2]; + FWK_RW uint32_t DEV_CONTROL_DELAY_CFG_0; + FWK_RW uint32_t DEV_CONTROL_DELAY_CFG_1; + uint8_t RESERVED5[0xFC8 - 0x78]; + FWK_R uint32_t IMPLEMENTATION_ID; + FWK_R uint32_t ARCHITECTURE_ID; + FWK_R uint32_t PID4; + FWK_R uint32_t PID5; + FWK_R uint32_t PID6; + FWK_R uint32_t PID7; + FWK_R uint32_t PID0; + FWK_R uint32_t PID1; + FWK_R uint32_t PID2; + FWK_R uint32_t PID3; + FWK_R uint32_t CID0; + FWK_R uint32_t CID1; + FWK_R uint32_t CID2; + FWK_R uint32_t CID3; +}; + +enum ppu_v0_mode { + PPU_V0_MODE_OFF = 0, + PPU_V0_MODE_MEM_RET = 1, + PPU_V0_MODE_LOGIC_RET = 2, + PPU_V0_MODE_FULL_RET = 3, + PPU_V0_MODE_MEM_OFF = 4, + PPU_V0_MODE_FUNC_RET = 5, + PPU_V0_MODE_ON = 6, + PPU_V0_MODE_WARM_RESET = 7, + PPU_V0_MODE_COUNT, +}; + +/* + * Bit definitions for PPR + */ +#define PPU_V0_PPR_POLICY UINT32_C(0x00000007) +#define PPU_V0_PPR_DYNAMIC_EN UINT32_C(0x00000100) +#define PPU_V0_PPR_EMULATED_EN UINT32_C(0x00000200) +#define PPU_V0_PPR_OFF_LOCK_EN UINT32_C(0x00001000) + +/* + * Bit definitions for PSR + */ +#define PPU_V0_PSR_EMULATED UINT32_C(0x00000200) +#define PPU_V0_PSR_DYNAMIC UINT32_C(0x00000100) +#define PPU_V0_PSR_POWSTAT UINT32_C(0x00000007) + +/* + * Bit definitions for IMR + */ +#define PPU_V0_IMR_MASK UINT32_C(0x010000FF) +#define PPU_V0_IMR_STA_POLICY_TRN UINT32_C(0x00000001) +#define PPU_V0_IMR_STA_ACCEPT UINT32_C(0x00000002) +#define PPU_V0_IMR_STA_DENY UINT32_C(0x00000004) +#define PPU_V0_IMR_DYN_ACCEPT UINT32_C(0x00000008) +#define PPU_V0_IMR_DYN_DENY UINT32_C(0x00000010) +#define PPU_V0_IMR_EMU_ACCEPT UINT32_C(0x00000020) +#define PPU_V0_IMR_EMU_DENY UINT32_C(0x00000040) +#define PPU_V0_IMR_UNSPT_POLICY UINT32_C(0x00000080) +#define PPU_V0_IMR_DYN_POLICY_MIN UINT32_C(0x01000000) + +/* + * Bit definitions for ISR + */ +#define PPU_V0_ISR_MASK UINT32_C(0x01FF01FF) +#define PPU_V0_ISR_STA_POLICY_TRN UINT32_C(0x00000001) +#define PPU_V0_ISR_STA_ACCEPT UINT32_C(0x00000002) +#define PPU_V0_ISR_STA_DENY UINT32_C(0x00000004) +#define PPU_V0_ISR_DYN_ACCEPT UINT32_C(0x00000008) +#define PPU_V0_ISR_DYN_DENY UINT32_C(0x00000010) +#define PPU_V0_ISR_EMU_ACCEPT UINT32_C(0x00000020) +#define PPU_V0_ISR_EMU_DENY UINT32_C(0x00000040) +#define PPU_V0_ISR_UNSPT_POLICY UINT32_C(0x00000080) +#define PPU_V0_ISR_DBGEMUPWRDWN_EDGE UINT32_C(0x00000100) +#define PPU_V0_ISR_ACTIVE_EDGE UINT32_C(0x00FF0000) +#define PPU_V0_ISR_ACTIVE_EDGE_ACTIVE0 UINT32_C(0x00010000) +#define PPU_V0_ISR_ACTIVE_EDGE_ACTIVE1 UINT32_C(0x00020000) +#define PPU_V0_ISR_ACTIVE_EDGE_ACTIVE2 UINT32_C(0x00040000) +#define PPU_V0_ISR_ACTIVE_EDGE_ACTIVE3 UINT32_C(0x00080000) +#define PPU_V0_ISR_ACTIVE_EDGE_ACTIVE4 UINT32_C(0x00100000) +#define PPU_V0_ISR_ACTIVE_EDGE_ACTIVE5 UINT32_C(0x00200000) +#define PPU_V0_ISR_ACTIVE_EDGE_ACTIVE6 UINT32_C(0x00400000) +#define PPU_V0_ISR_ACTIVE_EDGE_ACTIVE7 UINT32_C(0x00800000) +#define PPU_V0_ISR_DYN_POLICY_MIN UINT32_C(0x01000000) + +/* + * Bit definitions for ARCHITECTURE_ID + */ +#define PPU_V0_ARCHITECTURE_ID UINT32_C(0x00000000) + +/* + * Interface + */ +void ppu_v0_init(struct ppu_v0_reg *ppu); +int ppu_v0_request_power_mode(struct ppu_v0_reg *ppu, enum ppu_v0_mode mode); +int ppu_v0_set_power_mode(struct ppu_v0_reg *ppu, enum ppu_v0_mode mode); +int ppu_v0_get_power_mode(struct ppu_v0_reg *ppu, enum ppu_v0_mode *mode); + +/*! + * \endcond + * @} + */ + +#endif /* PPU_V0_H */ diff --git a/product/optee-stm32mp1/fw/CMakeLists.txt b/product/optee-stm32mp1/fw/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..f39e0f3482b336cd720551de8eb8f75a2292d1ea --- /dev/null +++ b/product/optee-stm32mp1/fw/CMakeLists.txt @@ -0,0 +1,27 @@ +# +# 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_mhu_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") diff --git a/product/optee-stm32mp1/fw/Firmware.cmake b/product/optee-stm32mp1/fw/Firmware.cmake new file mode 100644 index 0000000000000000000000000000000000000000..8f15840560cae1880bd156d2b8d598d1de9e3be2 --- /dev/null +++ b/product/optee-stm32mp1/fw/Firmware.cmake @@ -0,0 +1,59 @@ +# +# 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_LOG_LEVEL "TRACE") + +#set(SCP_GENERATE_FLAT_BINARY_INIT FALSE) + +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_pmic_regu") +list(PREPEND SCP_MODULE_PATHS "${CMAKE_CURRENT_LIST_DIR}/../module/stm32_pwr_regu") + +# 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-mhu") +list(APPEND SCP_MODULES "optee-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-pmic-regu") +list(APPEND SCP_MODULES "stm32-pwr-regu") +list(APPEND SCP_MODULES "voltage-domain") +list(APPEND SCP_MODULES "scmi-voltage-domain") +list(APPEND SCP_MODULES "optee-console") diff --git a/product/optee-stm32mp1/fw/Toolchain-GNU.cmake b/product/optee-stm32mp1/fw/Toolchain-GNU.cmake new file mode 100644 index 0000000000000000000000000000000000000000..bc85fad45b7e89a418f349c5d5ce2048fbe9e000 --- /dev/null +++ b/product/optee-stm32mp1/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-stm32mp1/fw/config_mhu_smt.c b/product/optee-stm32mp1/fw/config_mhu_smt.c new file mode 100644 index 0000000000000000000000000000000000000000..1de2244ff62bb6250d486f5b293391a0873d2da9 --- /dev/null +++ b/product/optee-stm32mp1/fw/config_mhu_smt.c @@ -0,0 +1,70 @@ +/* + * 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 + +#define OSPM0_SMT_MAILBOX_PA 0x2ffff000 +#define OSPM0_SMT_MAILBOX_SIZE SCMI_SHMEM_SIZE + +static const struct fwk_element mhu_element_table[] = { + [SCMI_CHANNEL_DEVICE_IDX_NS0] = { + .name = "SCMI non-secure to OP-TEE channel 0", + .data = &((struct mod_optee_mhu_channel_config){ + .type = MOD_OPTEE_MHU_CHANNEL_TYPE_REQUESTER, + .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 *mhu_get_element_table(fwk_id_t module_id) +{ + return (const struct fwk_element *)mhu_element_table; +} + +struct fwk_module_config config_optee_mhu = { + .elements = FWK_MODULE_DYNAMIC_ELEMENTS(mhu_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_MHU, + SCMI_CHANNEL_DEVICE_IDX_NS0), + .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_OPTEE_MHU, 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 new file mode 100644 index 0000000000000000000000000000000000000000..4f3442cc621b1a552667c3d0ad6518f3036daca2 --- /dev/null +++ b/product/optee-stm32mp1/fw/config_scmi.c @@ -0,0 +1,55 @@ +/* + * 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 new file mode 100644 index 0000000000000000000000000000000000000000..77091e8712cafcb921ad7effa35d5513ad4db282 --- /dev/null +++ b/product/optee-stm32mp1/fw/config_scmi_clocks.c @@ -0,0 +1,254 @@ +/* + * 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_SCMI0_HSE, + CLK_IDX_SCMI0_HSI, + CLK_IDX_SCMI0_CSI, + CLK_IDX_SCMI0_LSE, + CLK_IDX_SCMI0_LSI, + CLK_IDX_SCMI0_PLL2_Q, + CLK_IDX_SCMI0_PLL2_R, + CLK_IDX_SCMI0_MPU, + CLK_IDX_SCMI0_AXI, + CLK_IDX_SCMI0_BSEC, + CLK_IDX_SCMI0_CRYP1, + CLK_IDX_SCMI0_GPIOZ, + CLK_IDX_SCMI0_HASH1, + CLK_IDX_SCMI0_I2C4, + CLK_IDX_SCMI0_I2C6, + CLK_IDX_SCMI0_IWDG1, + CLK_IDX_SCMI0_RNG1, + CLK_IDX_SCMI0_RTC, + CLK_IDX_SCMI0_RTCAPB, + CLK_IDX_SCMI0_SPI6, + CLK_IDX_SCMI0_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_SCMI0_HSE, CK_HSE, "ck_hse", true), + STM32_CLOCK_CFG(CLK_IDX_SCMI0_HSI, CK_HSI, "ck_hsi", true), + STM32_CLOCK_CFG(CLK_IDX_SCMI0_CSI, CK_CSI, "ck_csi", true), + STM32_CLOCK_CFG(CLK_IDX_SCMI0_LSE, CK_LSE, "ck_lse", true), + STM32_CLOCK_CFG(CLK_IDX_SCMI0_LSI, CK_LSI, "ck_lsi", true), + STM32_CLOCK_CFG(CLK_IDX_SCMI0_PLL2_Q, PLL2_Q, "pll2_q", true), + STM32_CLOCK_CFG(CLK_IDX_SCMI0_PLL2_R, PLL2_R, "pll2_r", true), + STM32_CLOCK_CFG(CLK_IDX_SCMI0_MPU, CK_MCU, "ck_mpu", true), + STM32_CLOCK_CFG(CLK_IDX_SCMI0_AXI, CK_AXI, "ck_axi", true), + STM32_CLOCK_CFG(CLK_IDX_SCMI0_BSEC, BSEC, "bsec", false), + STM32_CLOCK_CFG(CLK_IDX_SCMI0_CRYP1, CRYP1, "cryp1", false), + STM32_CLOCK_CFG(CLK_IDX_SCMI0_GPIOZ, GPIOZ, "gpioz", false), + STM32_CLOCK_CFG(CLK_IDX_SCMI0_HASH1, HASH1, "hash1", false), + STM32_CLOCK_CFG(CLK_IDX_SCMI0_I2C4, I2C4_K, "i2c4_k", false), + STM32_CLOCK_CFG(CLK_IDX_SCMI0_I2C6, I2C6_K, "i2c6_k", false), + STM32_CLOCK_CFG(CLK_IDX_SCMI0_IWDG1, IWDG1, "iwdg1", false), + STM32_CLOCK_CFG(CLK_IDX_SCMI0_RNG1, RNG1_K, "rng1_k", true), + STM32_CLOCK_CFG(CLK_IDX_SCMI0_RTC, RTC, "ck_rtc", true), + STM32_CLOCK_CFG(CLK_IDX_SCMI0_RTCAPB, RTCAPB, "rtcapb", true), + STM32_CLOCK_CFG(CLK_IDX_SCMI0_SPI6, SPI6_K, "spi6_k", false), + STM32_CLOCK_CFG(CLK_IDX_SCMI0_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_SCMI0_HSE] = SCMI_CLOCK_ELT_ID(CLK_IDX_SCMI0_HSE), + [CK_SCMI0_HSI] = SCMI_CLOCK_ELT_ID(CLK_IDX_SCMI0_HSI), + [CK_SCMI0_CSI] = SCMI_CLOCK_ELT_ID(CLK_IDX_SCMI0_CSI), + [CK_SCMI0_LSE] = SCMI_CLOCK_ELT_ID(CLK_IDX_SCMI0_LSE), + [CK_SCMI0_LSI] = SCMI_CLOCK_ELT_ID(CLK_IDX_SCMI0_LSI), + [CK_SCMI0_PLL2_Q] = SCMI_CLOCK_ELT_ID(CLK_IDX_SCMI0_PLL2_Q), + [CK_SCMI0_PLL2_R] = SCMI_CLOCK_ELT_ID(CLK_IDX_SCMI0_PLL2_R), + [CK_SCMI0_MPU] = SCMI_CLOCK_ELT_ID(CLK_IDX_SCMI0_MPU), + [CK_SCMI0_AXI] = SCMI_CLOCK_ELT_ID(CLK_IDX_SCMI0_AXI), + [CK_SCMI0_BSEC] = SCMI_CLOCK_ELT_ID(CLK_IDX_SCMI0_BSEC), + [CK_SCMI0_CRYP1] = SCMI_CLOCK_ELT_ID(CLK_IDX_SCMI0_CRYP1), + [CK_SCMI0_GPIOZ] = SCMI_CLOCK_ELT_ID(CLK_IDX_SCMI0_GPIOZ), + [CK_SCMI0_HASH1] = SCMI_CLOCK_ELT_ID(CLK_IDX_SCMI0_HASH1), + [CK_SCMI0_I2C4] = SCMI_CLOCK_ELT_ID(CLK_IDX_SCMI0_I2C4), + [CK_SCMI0_I2C6] = SCMI_CLOCK_ELT_ID(CLK_IDX_SCMI0_I2C6), + [CK_SCMI0_IWDG1] = SCMI_CLOCK_ELT_ID(CLK_IDX_SCMI0_IWDG1), + [CK_SCMI0_RNG1] = SCMI_CLOCK_ELT_ID(CLK_IDX_SCMI0_RNG1), + [CK_SCMI0_RTC] = SCMI_CLOCK_ELT_ID(CLK_IDX_SCMI0_RTC), + [CK_SCMI0_RTCAPB] = SCMI_CLOCK_ELT_ID(CLK_IDX_SCMI0_RTCAPB), + [CK_SCMI0_SPI6] = SCMI_CLOCK_ELT_ID(CLK_IDX_SCMI0_SPI6), + [CK_SCMI0_USART1] = SCMI_CLOCK_ELT_ID(CLK_IDX_SCMI0_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 SCMI0 */ + CLOCK_ELT(CLK_IDX_SCMI0_HSE), + CLOCK_ELT(CLK_IDX_SCMI0_HSI), + CLOCK_ELT(CLK_IDX_SCMI0_CSI), + CLOCK_ELT(CLK_IDX_SCMI0_LSE), + CLOCK_ELT(CLK_IDX_SCMI0_LSI), + CLOCK_ELT(CLK_IDX_SCMI0_PLL2_Q), + CLOCK_ELT(CLK_IDX_SCMI0_PLL2_R), + CLOCK_ELT(CLK_IDX_SCMI0_MPU), + CLOCK_ELT(CLK_IDX_SCMI0_AXI), + CLOCK_ELT(CLK_IDX_SCMI0_BSEC), + CLOCK_ELT(CLK_IDX_SCMI0_CRYP1), + CLOCK_ELT(CLK_IDX_SCMI0_GPIOZ), + CLOCK_ELT(CLK_IDX_SCMI0_HASH1), + CLOCK_ELT(CLK_IDX_SCMI0_I2C4), + CLOCK_ELT(CLK_IDX_SCMI0_I2C6), + CLOCK_ELT(CLK_IDX_SCMI0_IWDG1), + CLOCK_ELT(CLK_IDX_SCMI0_RNG1), + CLOCK_ELT(CLK_IDX_SCMI0_RTC), + CLOCK_ELT(CLK_IDX_SCMI0_RTCAPB), + CLOCK_ELT(CLK_IDX_SCMI0_SPI6), + CLOCK_ELT(CLK_IDX_SCMI0_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 SCMI0 */ + OPTEE_CLOCK_ELT(CLK_IDX_SCMI0_HSE), + OPTEE_CLOCK_ELT(CLK_IDX_SCMI0_HSI), + OPTEE_CLOCK_ELT(CLK_IDX_SCMI0_CSI), + OPTEE_CLOCK_ELT(CLK_IDX_SCMI0_LSE), + OPTEE_CLOCK_ELT(CLK_IDX_SCMI0_LSI), + OPTEE_CLOCK_ELT(CLK_IDX_SCMI0_PLL2_Q), + OPTEE_CLOCK_ELT(CLK_IDX_SCMI0_PLL2_R), + OPTEE_CLOCK_ELT(CLK_IDX_SCMI0_MPU), + OPTEE_CLOCK_ELT(CLK_IDX_SCMI0_AXI), + OPTEE_CLOCK_ELT(CLK_IDX_SCMI0_BSEC), + OPTEE_CLOCK_ELT(CLK_IDX_SCMI0_CRYP1), + OPTEE_CLOCK_ELT(CLK_IDX_SCMI0_GPIOZ), + OPTEE_CLOCK_ELT(CLK_IDX_SCMI0_HASH1), + OPTEE_CLOCK_ELT(CLK_IDX_SCMI0_I2C4), + OPTEE_CLOCK_ELT(CLK_IDX_SCMI0_I2C6), + OPTEE_CLOCK_ELT(CLK_IDX_SCMI0_IWDG1), + OPTEE_CLOCK_ELT(CLK_IDX_SCMI0_RNG1), + OPTEE_CLOCK_ELT(CLK_IDX_SCMI0_RTC), + OPTEE_CLOCK_ELT(CLK_IDX_SCMI0_RTCAPB), + OPTEE_CLOCK_ELT(CLK_IDX_SCMI0_SPI6), + OPTEE_CLOCK_ELT(CLK_IDX_SCMI0_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 new file mode 100644 index 0000000000000000000000000000000000000000..7d127b8b096f4a743c034aa8a7343b07d369acb2 --- /dev/null +++ b/product/optee-stm32mp1/fw/config_scmi_reset_domains.c @@ -0,0 +1,206 @@ +/* + * 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. + * As only agent SCMI0 exposes reset domains, it currently happens + * that the index values are also the domain IDs exposed through SCMI. + */ +enum resetd_elt_idx { + /* Reset domain exposed to agent SCMI0 */ + RESETD_IDX_SCMI0_SPI6, + RESETD_IDX_SCMI0_I2C4, + RESETD_IDX_SCMI0_I2C6, + RESETD_IDX_SCMI0_USART1, + RESETD_IDX_SCMI0_STGEN, + RESETD_IDX_SCMI0_GPIOZ, + RESETD_IDX_SCMI0_CRYP1, + RESETD_IDX_SCMI0_HASH1, + RESETD_IDX_SCMI0_RNG1, + RESETD_IDX_SCMI0_MDMA, + RESETD_IDX_SCMI0_MCU, + RESETD_IDX_SCMI0_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_SCMI0_SPI6, SPI6_R, "spi6"), + STM32_RESET_CFG(RESETD_IDX_SCMI0_I2C4, I2C4_R, "i2c4"), + STM32_RESET_CFG(RESETD_IDX_SCMI0_I2C6, I2C6_R, "i2c6"), + STM32_RESET_CFG(RESETD_IDX_SCMI0_USART1, USART1_R, "usart1"), + STM32_RESET_CFG(RESETD_IDX_SCMI0_STGEN, STGEN_R, "stgen"), + STM32_RESET_CFG(RESETD_IDX_SCMI0_GPIOZ, GPIOZ_R, "gpioz"), + STM32_RESET_CFG(RESETD_IDX_SCMI0_CRYP1, CRYP1_R, "cryp1"), + STM32_RESET_CFG(RESETD_IDX_SCMI0_HASH1, HASH1_R, "hash1"), + STM32_RESET_CFG(RESETD_IDX_SCMI0_RNG1, RNG1_R, "rng1"), + STM32_RESET_CFG(RESETD_IDX_SCMI0_MDMA, MDMA_R, "mdma"), + STM32_RESET_CFG(RESETD_IDX_SCMI0_MCU, MCU_R, "mcu"), + STM32_RESET_CFG(RESETD_IDX_SCMI0_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_SCMI0_SPI6] = SCMI_RESETD_ELT_ID(RESETD_IDX_SCMI0_SPI6), + [RST_SCMI0_I2C4] = SCMI_RESETD_ELT_ID(RESETD_IDX_SCMI0_I2C4), + [RST_SCMI0_I2C6] = SCMI_RESETD_ELT_ID(RESETD_IDX_SCMI0_I2C6), + [RST_SCMI0_USART1] = SCMI_RESETD_ELT_ID(RESETD_IDX_SCMI0_USART1), + [RST_SCMI0_STGEN] = SCMI_RESETD_ELT_ID(RESETD_IDX_SCMI0_STGEN), + [RST_SCMI0_GPIOZ] = SCMI_RESETD_ELT_ID(RESETD_IDX_SCMI0_GPIOZ), + [RST_SCMI0_CRYP1] = SCMI_RESETD_ELT_ID(RESETD_IDX_SCMI0_CRYP1), + [RST_SCMI0_HASH1] = SCMI_RESETD_ELT_ID(RESETD_IDX_SCMI0_HASH1), + [RST_SCMI0_RNG1] = SCMI_RESETD_ELT_ID(RESETD_IDX_SCMI0_RNG1), + [RST_SCMI0_MDMA] = SCMI_RESETD_ELT_ID(RESETD_IDX_SCMI0_MDMA), + [RST_SCMI0_MCU] = SCMI_RESETD_ELT_ID(RESETD_IDX_SCMI0_MCU), + [RST_SCMI0_MCU_HOLD_BOOT] = SCMI_RESETD_ELT_ID(RESETD_IDX_SCMI0_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 SCMI0 */ + RESETD_ELT(RESETD_IDX_SCMI0_SPI6), + RESETD_ELT(RESETD_IDX_SCMI0_I2C4), + RESETD_ELT(RESETD_IDX_SCMI0_I2C6), + RESETD_ELT(RESETD_IDX_SCMI0_USART1), + RESETD_ELT(RESETD_IDX_SCMI0_STGEN), + RESETD_ELT(RESETD_IDX_SCMI0_GPIOZ), + RESETD_ELT(RESETD_IDX_SCMI0_CRYP1), + RESETD_ELT(RESETD_IDX_SCMI0_HASH1), + RESETD_ELT(RESETD_IDX_SCMI0_RNG1), + RESETD_ELT(RESETD_IDX_SCMI0_MDMA), + RESETD_ELT(RESETD_IDX_SCMI0_MCU), + RESETD_ELT(RESETD_IDX_SCMI0_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 SCMI0 */ + OPTEE_RESET_ELT(RESETD_IDX_SCMI0_SPI6), + OPTEE_RESET_ELT(RESETD_IDX_SCMI0_I2C4), + OPTEE_RESET_ELT(RESETD_IDX_SCMI0_I2C6), + OPTEE_RESET_ELT(RESETD_IDX_SCMI0_USART1), + OPTEE_RESET_ELT(RESETD_IDX_SCMI0_STGEN), + OPTEE_RESET_ELT(RESETD_IDX_SCMI0_GPIOZ), + OPTEE_RESET_ELT(RESETD_IDX_SCMI0_CRYP1), + OPTEE_RESET_ELT(RESETD_IDX_SCMI0_HASH1), + OPTEE_RESET_ELT(RESETD_IDX_SCMI0_RNG1), + OPTEE_RESET_ELT(RESETD_IDX_SCMI0_MDMA), + OPTEE_RESET_ELT(RESETD_IDX_SCMI0_MCU), + OPTEE_RESET_ELT(RESETD_IDX_SCMI0_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 new file mode 100644 index 0000000000000000000000000000000000000000..9290184b1f44bb7881e33effc6f0fac76bcdab02 --- /dev/null +++ b/product/optee-stm32mp1/fw/config_scmi_voltage_domains.c @@ -0,0 +1,262 @@ +/* + * 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 are 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 SCMI0 */ + VOLTD_IDX_SCMI0_REG11, + VOLTD_IDX_SCMI0_REG18, + VOLTD_IDX_SCMI0_USB33, + VOLTD_IDX_SCMI0_STPMIC1_BUCK1, + VOLTD_IDX_SCMI0_STPMIC1_BUCK2, + VOLTD_IDX_SCMI0_STPMIC1_BUCK3, + VOLTD_IDX_SCMI0_STPMIC1_BUCK4, + VOLTD_IDX_SCMI0_STPMIC1_LDO1, + VOLTD_IDX_SCMI0_STPMIC1_LDO2, + VOLTD_IDX_SCMI0_STPMIC1_LDO3, + VOLTD_IDX_SCMI0_STPMIC1_LDO4, + VOLTD_IDX_SCMI0_STPMIC1_LDO5, + VOLTD_IDX_SCMI0_STPMIC1_LDO6, + VOLTD_IDX_SCMI0_STPMIC1_VREFDDR, + VOLTD_IDX_SCMI0_STPMIC1_BOOST, + VOLTD_IDX_SCMI0_STPMIC1_PWR_SW1, + VOLTD_IDX_SCMI0_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 scmi0_voltd_device[] = { + SCMI_VOLTD_ELT_ID(VOLTD_SCMI0_REG11), + SCMI_VOLTD_ELT_ID(VOLTD_SCMI0_REG18), + SCMI_VOLTD_ELT_ID(VOLTD_SCMI0_USB33), + SCMI_VOLTD_ELT_ID(VOLTD_SCMI0_STPMIC1_BUCK1), + SCMI_VOLTD_ELT_ID(VOLTD_SCMI0_STPMIC1_BUCK2), + SCMI_VOLTD_ELT_ID(VOLTD_SCMI0_STPMIC1_BUCK3), + SCMI_VOLTD_ELT_ID(VOLTD_SCMI0_STPMIC1_BUCK4), + SCMI_VOLTD_ELT_ID(VOLTD_SCMI0_STPMIC1_LDO1), + SCMI_VOLTD_ELT_ID(VOLTD_SCMI0_STPMIC1_LDO2), + SCMI_VOLTD_ELT_ID(VOLTD_SCMI0_STPMIC1_LDO3), + SCMI_VOLTD_ELT_ID(VOLTD_SCMI0_STPMIC1_LDO4), + SCMI_VOLTD_ELT_ID(VOLTD_SCMI0_STPMIC1_LDO5), + SCMI_VOLTD_ELT_ID(VOLTD_SCMI0_STPMIC1_LDO6), + SCMI_VOLTD_ELT_ID(VOLTD_SCMI0_STPMIC1_VREFDDR), + SCMI_VOLTD_ELT_ID(VOLTD_SCMI0_STPMIC1_BOOST), + SCMI_VOLTD_ELT_ID(VOLTD_SCMI0_STPMIC1_PWR_SW1), + SCMI_VOLTD_ELT_ID(VOLTD_SCMI0_STPMIC1_PWR_SW2), +}; + +static const struct mod_scmi_voltd_agent voltd_agent_table[SCMI_AGENT_ID_COUNT] = { + [SCMI_AGENT_ID_NSEC0] = { + .device_table = scmi0_voltd_device, + .domain_count = FWK_ARRAY_SIZE(scmi0_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 descripbes 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_SCMI0_REG11] = VOLTD_STM32_PWR_ELT_ID(STM32_PWR_REG11), + [VOLTD_IDX_SCMI0_REG18] = VOLTD_STM32_PWR_ELT_ID(STM32_PWR_REG18), + [VOLTD_IDX_SCMI0_USB33] = VOLTD_STM32_PWR_ELT_ID(STM32_PWR_USB33), + [VOLTD_IDX_SCMI0_STPMIC1_BUCK1] = VOLTD_STM32_PMIC_ELT_ID(STPMIC1_REGU_BUCK1), + [VOLTD_IDX_SCMI0_STPMIC1_BUCK2] = VOLTD_STM32_PMIC_ELT_ID(STPMIC1_REGU_BUCK2), + [VOLTD_IDX_SCMI0_STPMIC1_BUCK3] = VOLTD_STM32_PMIC_ELT_ID(STPMIC1_REGU_BUCK3), + [VOLTD_IDX_SCMI0_STPMIC1_BUCK4] = VOLTD_STM32_PMIC_ELT_ID(STPMIC1_REGU_BUCK4), + [VOLTD_IDX_SCMI0_STPMIC1_LDO1] = VOLTD_STM32_PMIC_ELT_ID(STPMIC1_REGU_LDO1), + [VOLTD_IDX_SCMI0_STPMIC1_LDO2] = VOLTD_STM32_PMIC_ELT_ID(STPMIC1_REGU_LDO2), + [VOLTD_IDX_SCMI0_STPMIC1_LDO3] = VOLTD_STM32_PMIC_ELT_ID(STPMIC1_REGU_LDO3), + [VOLTD_IDX_SCMI0_STPMIC1_LDO4] = VOLTD_STM32_PMIC_ELT_ID(STPMIC1_REGU_LDO4), + [VOLTD_IDX_SCMI0_STPMIC1_LDO5] = VOLTD_STM32_PMIC_ELT_ID(STPMIC1_REGU_LDO5), + [VOLTD_IDX_SCMI0_STPMIC1_LDO6] = VOLTD_STM32_PMIC_ELT_ID(STPMIC1_REGU_LDO6), + [VOLTD_IDX_SCMI0_STPMIC1_VREFDDR] = VOLTD_STM32_PMIC_ELT_ID(STPMIC1_REGU_VREFDDR), + [VOLTD_IDX_SCMI0_STPMIC1_BOOST] = VOLTD_STM32_PMIC_ELT_ID(STPMIC1_REGU_BOOST), + [VOLTD_IDX_SCMI0_STPMIC1_PWR_SW1] = VOLTD_STM32_PMIC_ELT_ID(STPMIC1_REGU_PWR_SW1), + [VOLTD_IDX_SCMI0_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/include/fmw_log.h b/product/optee-stm32mp1/include/fmw_log.h new file mode 100644 index 0000000000000000000000000000000000000000..4e0bdd0ee4f2eb0b4f153112af3bd61e0599ebe4 --- /dev/null +++ b/product/optee-stm32mp1/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-stm32mp1/include/scmi_agents.h b/product/optee-stm32mp1/include/scmi_agents.h new file mode 100644 index 0000000000000000000000000000000000000000..13d29618a2f6e665f654a6ba9609a4d8c5054fd1 --- /dev/null +++ b/product/optee-stm32mp1/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-stm32mp1/module/stm32_pmic_regu/CMakeLists.txt b/product/optee-stm32mp1/module/stm32_pmic_regu/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..9262ecceb3cad63e6f6c42efe32222d6e703c649 --- /dev/null +++ b/product/optee-stm32mp1/module/stm32_pmic_regu/CMakeLists.txt @@ -0,0 +1,18 @@ +# +# Arm SCP/MCP Software +# Copyright (c) 2022, 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-stm32mp1") + +target_sources( + ${SCP_MODULE_TARGET} PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/src/mod_stm32_pmic_regu.c") + +target_link_libraries(${SCP_MODULE_TARGET} + PUBLIC module-scmi module-voltage-domain) diff --git a/product/optee-stm32mp1/module/stm32_pmic_regu/Module.cmake b/product/optee-stm32mp1/module/stm32_pmic_regu/Module.cmake new file mode 100644 index 0000000000000000000000000000000000000000..51bfae5b11ac7700a4ef25ffc8a9a251eb27a94f --- /dev/null +++ b/product/optee-stm32mp1/module/stm32_pmic_regu/Module.cmake @@ -0,0 +1,9 @@ +# +# 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 new file mode 100644 index 0000000000000000000000000000000000000000..120f13514db2386761b75c5b3553071f26f8c1e0 --- /dev/null +++ b/product/optee-stm32mp1/module/stm32_pmic_regu/include/mod_stm32_pmic_regu.h @@ -0,0 +1,24 @@ +/* + * 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 new file mode 100644 index 0000000000000000000000000000000000000000..650373da37ff8e6771d174511f473f16607d3831 --- /dev/null +++ b/product/optee-stm32mp1/module/stm32_pmic_regu/src/mod_stm32_pmic_regu.c @@ -0,0 +1,331 @@ +/* + * 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 + +/* 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; + + FMSG("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(); + + FMSG("%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; + + 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; + } + + *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; + } + + FMSG("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; + + ctx = module_ctx.dev_ctx_table + fwk_id_get_element_idx(dev_id); + + 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; + } + + 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; + } + + FMSG("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; + + 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; + } + + *level_uv = get_regu_voltage(ctx->regu_id); + + FMSG("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; + + 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->read_only) { + return FWK_E_ACCESS; + } + + FMSG("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; + + *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; + + 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; + } + + 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); + + FMSG("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; + + 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; + } + + 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; + + FMSG("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_level = pmic_regu_get_level, + .set_level = pmic_regu_set_level, + .set_config = pmic_regu_set_config, + .get_config = pmic_regu_get_config, + .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/CMakeLists.txt b/product/optee-stm32mp1/module/stm32_pwr_regu/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..ebba549f046ba9f1ba0ca4fc5ab3adf798b4b789 --- /dev/null +++ b/product/optee-stm32mp1/module/stm32_pwr_regu/CMakeLists.txt @@ -0,0 +1,17 @@ +# +# Arm SCP/MCP Software +# Copyright (c) 2022, 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-stm32mp1") + +target_sources( + ${SCP_MODULE_TARGET} PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/src/mod_stm32_pwr_regu.c") + +target_link_libraries(${SCP_MODULE_TARGET} PUBLIC module-voltage-domain) diff --git a/product/optee-stm32mp1/module/stm32_pwr_regu/Module.cmake b/product/optee-stm32mp1/module/stm32_pwr_regu/Module.cmake new file mode 100644 index 0000000000000000000000000000000000000000..b8c5be8dbc7638322a7b4c963b742612dac8b4c3 --- /dev/null +++ b/product/optee-stm32mp1/module/stm32_pwr_regu/Module.cmake @@ -0,0 +1,9 @@ +# +# 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 new file mode 100644 index 0000000000000000000000000000000000000000..567ab18e4a7fa776cd174c6d579e004d96ec903a --- /dev/null +++ b/product/optee-stm32mp1/module/stm32_pwr_regu/include/mod_stm32_pwr_regu.h @@ -0,0 +1,19 @@ +/* + * 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 new file mode 100644 index 0000000000000000000000000000000000000000..fe5b6292da1bec6f1d9baa4da735f6049802f7c4 --- /dev/null +++ b/product/optee-stm32mp1/module/stm32_pwr_regu/src/mod_stm32_pwr_regu.c @@ -0,0 +1,265 @@ +/* + * 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 + +/* 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; + + 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 (!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; + } + + FMSG("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; + + ctx = module_ctx.dev_ctx_table + fwk_id_get_element_idx(dev_id); + + 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; + } + + 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); + + FMSG("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; + + 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 (!nsec_can_access_pwr_regu(ctx->pwr_id)) { + return FWK_E_ACCESS; + } + + *level_uv = pwr_regu_level(ctx->pwr_id); + + FMSG("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; + + 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 (!nsec_can_access_pwr_regu(ctx->pwr_id)) { + return FWK_E_ACCESS; + } + + FMSG("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; + + 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 (!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; + + FMSG("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; + + 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 (!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); + + FMSG("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_level = pwr_regu_get_level, + .set_level = pwr_regu_set_level, + .set_config = pwr_regu_set_config, + .get_config = pwr_regu_get_config, + .get_info = pwr_regu_get_info, + .get_level_from_index = pwr_regu_level_from_index, + /* Not supported */ +}; + +/* + * 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/vhost-user/fw/CMakeLists.txt b/product/vhost-user/fw/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..f045afaf4d20b07e3db14b20f073f3e5dfa190d8 --- /dev/null +++ b/product/vhost-user/fw/CMakeLists.txt @@ -0,0 +1,41 @@ +# +# 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_executable(${SCP_FIRMWARE_TARGET}) + +find_package(PkgConfig REQUIRED) +pkg_check_modules(deps REQUIRED IMPORTED_TARGET glib-2.0) +target_link_libraries(${SCP_FIRMWARE_TARGET} PRIVATE PkgConfig::deps) + +# 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_mhu_smt.c" + "${CMAKE_CURRENT_SOURCE_DIR}/config_scmi.c" + "${CMAKE_CURRENT_SOURCE_DIR}/config_mock_clock.c" + "${CMAKE_CURRENT_SOURCE_DIR}/config_vpll.c" + "${CMAKE_CURRENT_SOURCE_DIR}/config_clock.c" + "${CMAKE_CURRENT_SOURCE_DIR}/config_scmi_clock.c" + "${CMAKE_CURRENT_SOURCE_DIR}/config_ppu_v0.c" + "${CMAKE_CURRENT_SOURCE_DIR}/config_power_domain.c" + "${CMAKE_CURRENT_SOURCE_DIR}/config_scmi_power_domain.c" + "${CMAKE_CURRENT_SOURCE_DIR}/config_mock_psu.c" + "${CMAKE_CURRENT_SOURCE_DIR}/config_psu.c" + "${CMAKE_CURRENT_SOURCE_DIR}/config_dvfs.c" + "${CMAKE_CURRENT_SOURCE_DIR}/config_scmi_perf.c" + "${CMAKE_CURRENT_SOURCE_DIR}/config_sensor.c" + "${CMAKE_CURRENT_SOURCE_DIR}/config_host.c") diff --git a/product/vhost-user/fw/Firmware.cmake b/product/vhost-user/fw/Firmware.cmake new file mode 100644 index 0000000000000000000000000000000000000000..7cb305d1a7bf0a2fd4ff4eba336447752c65472b --- /dev/null +++ b/product/vhost-user/fw/Firmware.cmake @@ -0,0 +1,55 @@ +# +# 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 "vhost-user") + +set(SCP_FIRMWARE_TARGET "vhost-user") + +#set(SCP_GENERATE_FLAT_BINARY_INIT TRUE) + +set(SCP_ENABLE_NOTIFICATIONS_INIT TRUE) + +set(SCP_ENABLE_SCMI_NOTIFICATIONS_INIT TRUE) + +set(SCP_ENABLE_SCMI_SENSOR_EVENTS_INIT TRUE) + +set(SCP_ENABLE_FAST_CHANNELS_INIT FALSE) + +#set(SCP_ENABLE_SCMI_RESET_INIT TRUE) + +set(SCP_ENABLE_IPO_INIT FALSE) + +set(SCP_ARCHITECTURE "none") + +list(PREPEND SCP_MODULE_PATHS "${CMAKE_CURRENT_LIST_DIR}/../module/vppu") + +# 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 "vhost-mhu") +list(APPEND SCP_MODULES "msg-smt") +list(APPEND SCP_MODULES "scmi") +list(APPEND SCP_MODULES "mock-clock") +list(APPEND SCP_MODULES "system-pll") +list(APPEND SCP_MODULES "clock") +list(APPEND SCP_MODULES "scmi-clock") +list(APPEND SCP_MODULES "vppu") +list(APPEND SCP_MODULES "power-domain") +list(APPEND SCP_MODULES "scmi-power-domain") +list(APPEND SCP_MODULES "mock-psu") +list(APPEND SCP_MODULES "psu") +list(APPEND SCP_MODULES "dvfs") +list(APPEND SCP_MODULES "scmi-perf") +list(APPEND SCP_MODULES "reg-sensor") +list(APPEND SCP_MODULES "sensor") +list(APPEND SCP_MODULES "scmi-sensor") +list(APPEND SCP_MODULES "host-console") diff --git a/product/vhost-user/fw/clock_devices.h b/product/vhost-user/fw/clock_devices.h new file mode 100644 index 0000000000000000000000000000000000000000..df71204a250dac02a845a116f079fe2262a85b2f --- /dev/null +++ b/product/vhost-user/fw/clock_devices.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 CLOCK_DEVICES_H +#define CLOCK_DEVICES_H + +/*! + * \brief Clock device indexes. + */ +enum clock_dev_idx { + CLOCK_DEV_IDX_BIG, + CLOCK_DEV_IDX_LITTLE, + CLOCK_DEV_IDX_GPU, + CLOCK_DEV_IDX_VPU, + CLOCK_DEV_IDX_DPU, + CLOCK_DEV_IDX_PIXEL_0, + CLOCK_DEV_IDX_PIXEL_1, + CLOCK_DEV_IDX_MOCK_0, + CLOCK_DEV_IDX_MOCK_1, + CLOCK_DEV_IDX_MOCK_2, + CLOCK_DEV_IDX_MOCK_3, + CLOCK_DEV_IDX_COUNT +}; + +#endif /* CLOCK_DEVICES_H */ diff --git a/product/vhost-user/fw/config_clock.c b/product/vhost-user/fw/config_clock.c new file mode 100644 index 0000000000000000000000000000000000000000..103fbb09639be361554a42729df0c0f2b4696790 --- /dev/null +++ b/product/vhost-user/fw/config_clock.c @@ -0,0 +1,127 @@ +/* + * 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 "clock_devices.h" + +static struct fwk_element clock_dev_desc_table[] = { + [CLOCK_DEV_IDX_BIG] = { + .name = "CPU_GROUP_BIG", + .data = &((struct mod_clock_dev_config) { + .driver_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_SYSTEM_PLL, 0), + .api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_SYSTEM_PLL, + MOD_SYSTEM_PLL_API_TYPE_DEFAULT), + }), + }, + [CLOCK_DEV_IDX_LITTLE] = { + .name = "CPU_GROUP_LITTLE", + .data = &((struct mod_clock_dev_config) { + .driver_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_SYSTEM_PLL, 1), + .api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_SYSTEM_PLL, + MOD_SYSTEM_PLL_API_TYPE_DEFAULT), + }), + }, + [CLOCK_DEV_IDX_GPU] = { + .name = "GPU", + .data = &((struct mod_clock_dev_config) { + .driver_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_SYSTEM_PLL, 2), + .api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_SYSTEM_PLL, + MOD_SYSTEM_PLL_API_TYPE_DEFAULT), + }), + }, + [CLOCK_DEV_IDX_VPU] = { + .name = "VPU", + .data = &((struct mod_clock_dev_config) { + .driver_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_SYSTEM_PLL, 3), + .api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_SYSTEM_PLL, + MOD_SYSTEM_PLL_API_TYPE_DEFAULT), + }), + }, + [CLOCK_DEV_IDX_DPU] = { + .name = "DPU", + .data = &((struct mod_clock_dev_config) { + .driver_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_SYSTEM_PLL, 4), + .api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_SYSTEM_PLL, + MOD_SYSTEM_PLL_API_TYPE_DEFAULT), + }), + }, + [CLOCK_DEV_IDX_PIXEL_0] = { + .name = "PIXEL_0", + .data = &((struct mod_clock_dev_config) { + .driver_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_SYSTEM_PLL, 5), + .api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_SYSTEM_PLL, + MOD_SYSTEM_PLL_API_TYPE_DEFAULT), + }), + }, + [CLOCK_DEV_IDX_PIXEL_1] = { + .name = "PIXEL_1", + .data = &((struct mod_clock_dev_config) { + .driver_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_SYSTEM_PLL, 6), + .api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_SYSTEM_PLL, + MOD_SYSTEM_PLL_API_TYPE_DEFAULT), + }), + }, + [CLOCK_DEV_IDX_MOCK_0] = { + .name = "CLOCK_0", + .data = &((struct mod_clock_dev_config) { + .driver_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_MOCK_CLOCK, 0), + .api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_MOCK_CLOCK, + MOD_MOCK_CLOCK_API_TYPE_DRIVER), + }), + }, + [CLOCK_DEV_IDX_MOCK_1] = { + .name = "CLOCK_1", + .data = &((struct mod_clock_dev_config) { + .driver_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_MOCK_CLOCK, 1), + .api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_MOCK_CLOCK, + MOD_MOCK_CLOCK_API_TYPE_DRIVER), + }), + }, + [CLOCK_DEV_IDX_MOCK_2] = { + .name = "CLOCK_2", + .data = &((struct mod_clock_dev_config) { + .driver_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_MOCK_CLOCK, 2), + .api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_MOCK_CLOCK, + MOD_MOCK_CLOCK_API_TYPE_DRIVER), + }), + }, + [CLOCK_DEV_IDX_MOCK_3] = { + .name = "CLOCK_3", + .data = &((struct mod_clock_dev_config) { + .driver_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_MOCK_CLOCK, 3), + .api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_MOCK_CLOCK, + MOD_MOCK_CLOCK_API_TYPE_DRIVER), + }), + }, + [CLOCK_DEV_IDX_COUNT] = { 0 }, /* Termination description. */ +}; + +static const struct fwk_element *clock_get_dev_desc_table(fwk_id_t module_id) +{ + unsigned int i; + struct mod_clock_dev_config *dev_config; + + /* Configure all clocks to respond to changes in SYSTOP power state */ + for (i = 0; i < CLOCK_DEV_IDX_COUNT; i++) { + dev_config = + (struct mod_clock_dev_config *)clock_dev_desc_table[i].data; + dev_config->pd_source_id = FWK_ID_NONE; + } + return clock_dev_desc_table; +} + +struct fwk_module_config config_clock = { + .data = &((struct mod_clock_config){ + .pd_transition_notification_id = FWK_ID_NONE_INIT, + .pd_pre_transition_notification_id = FWK_ID_NONE_INIT, + }), + .elements = FWK_MODULE_DYNAMIC_ELEMENTS(clock_get_dev_desc_table), +}; diff --git a/product/vhost-user/fw/config_dvfs.c b/product/vhost-user/fw/config_dvfs.c new file mode 100644 index 0000000000000000000000000000000000000000..12867173043e0b4071db8040944b9f79ae852f86 --- /dev/null +++ b/product/vhost-user/fw/config_dvfs.c @@ -0,0 +1,152 @@ +/* + * 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 "config_dvfs.h" + +static const struct mod_dvfs_domain_config cpu_group_little = { + .psu_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_PSU, 0), + .clock_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_CLOCK, 0), + .latency = 1200, + .sustained_idx = 2, + .opps = (struct mod_dvfs_opp[]) { + { + .level = 665 * 1000UL, + .frequency = 665 * 1000UL, + .voltage = 100, + .power = 665*100*100/10000, + }, + { + .level = 998 * 1000UL, + .frequency = 998 * 1000UL, + .voltage = 110, + .power = 998*110*110/10000, + }, + { + .level = 1330 * 1000UL, + .frequency = 1330 * 1000UL, + .voltage = 120, + .power = 1330*120*120/10000, + }, + { + .level = 1463 * 1000UL, + .frequency = 1463 * 1000UL, + .voltage = 130, + .power = 1463*130*130/10000, + }, + { + .level = 1596 * 1000UL, + .frequency = 1596 * 1000UL, + .voltage = 140, + .power = 1596*140*140/10000, + }, + { 0 } + } +}; + +static const struct mod_dvfs_domain_config cpu_group_big = { + .psu_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_PSU, 1), + .clock_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_CLOCK, 1), + .latency = 1200, + .sustained_idx = 2, + .opps = (struct mod_dvfs_opp[]) { + { + .level = 1313 * 1000UL, + .frequency = 1313 * 1000UL , + .voltage = 100, + .power = 1313, + }, + { + .level = 1531 * 1000UL, + .frequency = 1531 * 1000UL, + .voltage = 200, + .power = 1531, + }, + { + .level = 1750 * 1000UL, + .frequency = 1750 * 1000UL, + .voltage = 300, + .power = 1750, + }, + { + .level = 2100 * 1000UL, + .frequency = 2100 * 1000UL, + .voltage = 400, + .power = 2100, + }, + { + .level = 2450 * 1000UL, + .frequency = 2450 * 1000UL, + .voltage = 500, + .power = 2450, + }, + { 0 } + } +}; + +static const struct mod_dvfs_domain_config gpu = { + .psu_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_PSU, 2), + .clock_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_CLOCK, 2), + .latency = 1200, + .sustained_idx = 4, + .opps = (struct mod_dvfs_opp[]) { + { + .level = 450 * 1000UL, + .frequency = 450 * 1000UL, + .voltage = 100, + }, + { + .level = 487500, + .frequency = 487500, + .voltage = 200, + }, + { + .level = 525 * 1000UL, + .frequency = 525 * 1000UL, + .voltage = 300, + }, + { + .level = 562500 * 1000UL, + .frequency = 562500, + .voltage = 400, + }, + { + .level = 600 * 1000UL, + .frequency = 600 * 1000UL, + .voltage = 500, + }, + { 0 } + } +}; + +static const struct fwk_element element_table[] = { + [DVFS_ELEMENT_IDX_LITTLE] = { + .name = "CPU_GROUP_LITTLE", + .data = &cpu_group_little, + }, + [DVFS_ELEMENT_IDX_BIG] = { + .name = "CPU_GROUP_BIG", + .data = &cpu_group_big, + }, + [DVFS_ELEMENT_IDX_GPU] = { + .name = "GPU", + .data = &gpu, + }, + { 0 } +}; + +static const struct fwk_element *dvfs_get_element_table(fwk_id_t module_id) +{ + return element_table; +} + +struct fwk_module_config config_dvfs = { + .elements = FWK_MODULE_DYNAMIC_ELEMENTS(dvfs_get_element_table), +}; diff --git a/product/vhost-user/fw/config_dvfs.h b/product/vhost-user/fw/config_dvfs.h new file mode 100644 index 0000000000000000000000000000000000000000..2913c1060d92e9dc24b84420144d50c55ec6c1f3 --- /dev/null +++ b/product/vhost-user/fw/config_dvfs.h @@ -0,0 +1,18 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CONFIG_DVFS_H +#define CONFIG_DVFS_H + +enum dvfs_element_idx { + DVFS_ELEMENT_IDX_LITTLE, + DVFS_ELEMENT_IDX_BIG, + DVFS_ELEMENT_IDX_GPU, + DVFS_ELEMENT_IDX_COUNT +}; + +#endif /* CONFIG_DVFS_H */ diff --git a/product/vhost-user/fw/config_host.c b/product/vhost-user/fw/config_host.c new file mode 100644 index 0000000000000000000000000000000000000000..0df4b32349c7dab3e2f75622d1f2a7651b4890ef --- /dev/null +++ b/product/vhost-user/fw/config_host.c @@ -0,0 +1,85 @@ +/* + * 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 + +/* Glib helpers */ + +typedef struct { + GMainLoop *loop; +} VuScmi; + +VuScmi scmi = {0}; + +static gboolean verbose; + +static GOptionEntry options[] = { + { "verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose, "Be more verbose in output", NULL}, + { NULL } +}; + +static gboolean hangup(gpointer user_data) +{ + GMainLoop *loop = (GMainLoop *) user_data; + g_info("%s: caught hangup/quit signal, quitting main loop", __func__); + g_main_loop_quit(loop); + return true; +} + +/* Main loop */ + +int main(int argc, char *argv[]) +{ + GError *error = NULL; + GOptionContext *context; + + context = g_option_context_new("host-user emulation of SCMI device"); + g_option_context_add_main_entries(context, options, "host-user-scmi"); + if (!g_option_context_parse(context, &argc, &argv, &error)) + { + g_printerr("option parsing failed: %s\n", error->message); + exit(1); + } + + if (verbose) { + g_log_set_handler(NULL, G_LOG_LEVEL_MASK, g_log_default_handler, NULL); + g_setenv("G_MESSAGES_DEBUG", "all", true); + } else { + g_log_set_handler(NULL, + G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_ERROR, + g_log_default_handler, NULL); + } + + /* + * Create the main loop first so all the various sources can be + * added. SCMI server can add it's GSource watches. + */ + scmi.loop = g_main_loop_new(NULL, FALSE); + + /* Catch exit signals */ + g_unix_signal_add(SIGHUP, hangup, scmi.loop); + g_unix_signal_add(SIGINT, hangup, scmi.loop); + g_unix_signal_add(SIGTERM, hangup, scmi.loop); + + /* Initialize scmi server */ + scmi_arch_init(); + + /* Enter main loop */ + g_message("entering main loop, awaiting messages"); + g_main_loop_run(scmi.loop); + g_message("finished main loop, cleaning up"); + + /* Stop scmi server */ + scmi_arch_deinit(); + + /* Stop main loop and exit */ + g_main_loop_unref(scmi.loop); +} diff --git a/product/vhost-user/fw/config_mhu_smt.c b/product/vhost-user/fw/config_mhu_smt.c new file mode 100644 index 0000000000000000000000000000000000000000..d3bee3b41ca741bea8ffcd3d54efecf83a0177ee --- /dev/null +++ b/product/vhost-user/fw/config_mhu_smt.c @@ -0,0 +1,111 @@ +/* + * 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 + +static const struct fwk_element mhu_element_table[] = { + [SCMI_CHANNEL_DEVICE_IDX_PSCI] = { + .name = "virqueue for PSCI", + .sub_element_count = 1, + .data = &((struct mod_vhost_mhu_channel_config) { + .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_MSG_SMT, + MOD_MSG_SMT_API_IDX_DRIVER_INPUT), + }) + }, + [SCMI_CHANNEL_DEVICE_IDX_OSPM_0] = { + .name = "virqueue for OSPM #0", + .sub_element_count = 2, + .data = &((struct mod_vhost_mhu_channel_config) { + .socket_path ="vscmi-guest0.sock", + .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_MSG_SMT, + MOD_MSG_SMT_API_IDX_DRIVER_INPUT), + }) + }, + [SCMI_CHANNEL_DEVICE_IDX_OSPM_1] = { + .name = "virqueue for OSPM #1", + .sub_element_count = 2, + .data = &((struct mod_vhost_mhu_channel_config) { + .socket_path ="vscmi-guest1.sock", + .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_MSG_SMT, + MOD_MSG_SMT_API_IDX_DRIVER_INPUT), + }) + }, + [SCMI_CHANNEL_DEVICE_IDX_COUNT] = { 0 }, +}; + +static const struct fwk_element *mhu_get_element_table(fwk_id_t module_id) +{ + return (const struct fwk_element *)mhu_element_table; +} + +struct fwk_module_config config_vhost_mhu = { + .elements = FWK_MODULE_DYNAMIC_ELEMENTS(mhu_get_element_table), +}; + +static struct fwk_element smt_element_table[] = { + [SCMI_SERVICE_IDX_PSCI] = { + .name = "PSCI", + .data = &((struct mod_msg_smt_channel_config) { + .type = MOD_MSG_SMT_CHANNEL_TYPE_REQUESTER, + .driver_id = FWK_ID_SUB_ELEMENT_INIT(FWK_MODULE_IDX_VHOST_MHU, + SCMI_CHANNEL_DEVICE_IDX_PSCI, 0), + .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_VHOST_MHU, 0), + }) + }, + [SCMI_SERVICE_IDX_OSPM_0] = { + .name = "OSPM0", + .data = &((struct mod_msg_smt_channel_config) { + .type = MOD_MSG_SMT_CHANNEL_TYPE_REQUESTER, + .driver_id = FWK_ID_SUB_ELEMENT_INIT(FWK_MODULE_IDX_VHOST_MHU, + SCMI_CHANNEL_DEVICE_IDX_OSPM_0, 0), + .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_VHOST_MHU, 0), + }) + }, + [SCMI_SERVICE_IDX_OSPM_1] = { + .name = "OSPM1", + .data = &((struct mod_msg_smt_channel_config) { + .type = MOD_MSG_SMT_CHANNEL_TYPE_REQUESTER, + .driver_id = FWK_ID_SUB_ELEMENT_INIT(FWK_MODULE_IDX_VHOST_MHU, + SCMI_CHANNEL_DEVICE_IDX_OSPM_1, 0), + .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_VHOST_MHU, 0), + }) + }, +#ifdef BUILD_HAS_SCMI_NOTIFICATIONS + [SCMI_SERVICE_IDX_OSPM_0_P2A] = { + .name = "OSPM0 P2A", + .data = &((struct mod_msg_smt_channel_config) { + .type = MOD_MSG_SMT_CHANNEL_TYPE_COMPLETER, + .driver_id = FWK_ID_SUB_ELEMENT_INIT(FWK_MODULE_IDX_VHOST_MHU, + SCMI_CHANNEL_DEVICE_IDX_OSPM_0, 1), + .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_VHOST_MHU, 0), + }) + }, + [SCMI_SERVICE_IDX_OSPM_1_P2A] = { + .name = "OSPM1 P2A", + .data = &((struct mod_msg_smt_channel_config) { + .type = MOD_MSG_SMT_CHANNEL_TYPE_COMPLETER, + .driver_id = FWK_ID_SUB_ELEMENT_INIT(FWK_MODULE_IDX_VHOST_MHU, + SCMI_CHANNEL_DEVICE_IDX_OSPM_1, 1), + .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_VHOST_MHU, 0), + }) + }, +#endif + [SCMI_SERVICE_IDX_COUNT] = { 0 }, +}; + +static const struct fwk_element *smt_get_element_table(fwk_id_t module_id) +{ + return (const struct fwk_element *)smt_element_table; +} + +struct fwk_module_config config_msg_smt = { + .elements = FWK_MODULE_DYNAMIC_ELEMENTS(smt_get_element_table), +}; diff --git a/product/vhost-user/fw/config_mock_clock.c b/product/vhost-user/fw/config_mock_clock.c new file mode 100644 index 0000000000000000000000000000000000000000..5b64c9585051ffb4d07ef4da9ca0b5123f79337a --- /dev/null +++ b/product/vhost-user/fw/config_mock_clock.c @@ -0,0 +1,78 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include "config_mock_clock.h" + + +static const struct mod_mock_clock_rate clk0_rate_table[] = { + { .rate = 1536000 }, { .rate = 2116800 }, { .rate = 2304000 }, + { .rate = 4233600 }, { .rate = 4608000 }, { .rate = 8467200 }, + { .rate = 9216000 }, +}; + +static const struct mod_mock_clock_rate clk1_rate_table[] = { + { .rate = 2116800 }, +}; + +static const struct mod_mock_clock_rate clk2_rate_table[] = { + { .rate = 2304000 }, +}; + +static const struct mod_mock_clock_rate clk3_rate_table[] = { + { .rate = 4233600 }, +}; + +static const struct fwk_element element_table[] = { + [MOD_MOCK_CLOCK_ELEMENT_IDX_0] = + { + .name = "MOCK_CLK0", + .data = &(const struct mod_mock_clock_element_cfg){ + .rate_table = clk0_rate_table, + .rate_count = FWK_ARRAY_SIZE(clk0_rate_table), + .default_rate = 1536000, + }, + }, + [MOD_MOCK_CLOCK_ELEMENT_IDX_1] = + { + .name = "MOCK_CLK1", + .data = &(const struct mod_mock_clock_element_cfg){ + .rate_table = clk1_rate_table, + .rate_count = FWK_ARRAY_SIZE(clk1_rate_table), + .default_rate = 2116800, + }, + }, + [MOD_MOCK_CLOCK_ELEMENT_IDX_2] = + { + .name = "MOCK_CLK2", + .data = &(const struct mod_mock_clock_element_cfg){ + .rate_table = clk2_rate_table, + .rate_count = FWK_ARRAY_SIZE(clk2_rate_table), + .default_rate = 2304000, + }, + }, + [MOD_MOCK_CLOCK_ELEMENT_IDX_3] = + { + .name = "MOCK_CLK3", + .data = &(const struct mod_mock_clock_element_cfg){ + .rate_table = clk3_rate_table, + .rate_count = FWK_ARRAY_SIZE(clk3_rate_table), + .default_rate = 4233600, + }, + }, + [MOD_MOCK_CLOCK_ELEMENT_IDX_COUNT] = { 0 }, /* Termination description. */ +}; + +static const struct fwk_element *get_element_table(fwk_id_t module_id) +{ + return element_table; +} + +struct fwk_module_config config_mock_clock = { + .elements = FWK_MODULE_DYNAMIC_ELEMENTS(get_element_table), +}; diff --git a/product/vhost-user/fw/config_mock_clock.h b/product/vhost-user/fw/config_mock_clock.h new file mode 100644 index 0000000000000000000000000000000000000000..114f0e00f59d17b9d8fa5177237dadbdec790ceb --- /dev/null +++ b/product/vhost-user/fw/config_mock_clock.h @@ -0,0 +1,20 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CONFIG_MOCK_CLOCK_H +#define CONFIG_MOCK_CLOCK_H + +/* Mock clock element indices for Juno */ +enum mod_mock_clock_element_idx { + MOD_MOCK_CLOCK_ELEMENT_IDX_0, + MOD_MOCK_CLOCK_ELEMENT_IDX_1, + MOD_MOCK_CLOCK_ELEMENT_IDX_2, + MOD_MOCK_CLOCK_ELEMENT_IDX_3, + MOD_MOCK_CLOCK_ELEMENT_IDX_COUNT, +}; + +#endif /* CONFIG_MOCK_CLOCK_H */ diff --git a/product/vhost-user/fw/config_mock_psu.c b/product/vhost-user/fw/config_mock_psu.c new file mode 100644 index 0000000000000000000000000000000000000000..efdc94cbb4e733046ee5b542efae7085f402023e --- /dev/null +++ b/product/vhost-user/fw/config_mock_psu.c @@ -0,0 +1,55 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include "config_mock_psu.h" + +static const struct fwk_element element_table[] = { + [CONFIG_MOCK_PSU_ELEMENT_IDX_CPU_GROUP_LITTLE] = { + .name = "CPU_GROUP_LITTLE", + .data = &(const struct mod_mock_psu_element_cfg) { + .default_enabled = true, + .default_voltage = 100, + .async_alarm_id = FWK_ID_NONE_INIT, + }, + }, + [CONFIG_MOCK_PSU_ELEMENT_IDX_CPU_GROUP_BIG] = { + .name = "CPU_GROUP_BIG", + .data = &(const struct mod_mock_psu_element_cfg) { + .default_enabled = true, + .default_voltage = 100, + .async_alarm_id = FWK_ID_NONE_INIT, + }, + }, + [CONFIG_MOCK_PSU_ELEMENT_IDX_GPU] = { + .name = "GPU", + .data = &(const struct mod_mock_psu_element_cfg) { + .default_enabled = true, + .default_voltage = 100, + .async_alarm_id = FWK_ID_NONE_INIT, + }, + }, + [CONFIG_MOCK_PSU_ELEMENT_IDX_VPU] = { + .name = "VPU", + .data = &(const struct mod_mock_psu_element_cfg) { + .default_enabled = true, + .default_voltage = 100, + .async_alarm_id = FWK_ID_NONE_INIT, + }, + }, + { 0 } +}; + +static const struct fwk_element *get_element_table(fwk_id_t module_id) +{ + return element_table; +} + +struct fwk_module_config config_mock_psu = { + .elements = FWK_MODULE_DYNAMIC_ELEMENTS(get_element_table), +}; diff --git a/product/vhost-user/fw/config_mock_psu.h b/product/vhost-user/fw/config_mock_psu.h new file mode 100644 index 0000000000000000000000000000000000000000..74476bb4585bcae08e85f86fcb538bab8d213fc3 --- /dev/null +++ b/product/vhost-user/fw/config_mock_psu.h @@ -0,0 +1,19 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CONFIG_MOCK_PSU_H +#define CONFIG_MOCK_PSU_H + +enum config_mock_psu_element_idx { + CONFIG_MOCK_PSU_ELEMENT_IDX_CPU_GROUP_LITTLE, + CONFIG_MOCK_PSU_ELEMENT_IDX_CPU_GROUP_BIG, + CONFIG_MOCK_PSU_ELEMENT_IDX_GPU, + CONFIG_MOCK_PSU_ELEMENT_IDX_VPU, + CONFIG_MOCK_PSU_ELEMENT_IDX_COUNT, +}; + +#endif /* CONFIG_MOCK_PSU_H */ diff --git a/product/vhost-user/fw/config_power_domain.c b/product/vhost-user/fw/config_power_domain.c new file mode 100644 index 0000000000000000000000000000000000000000..eb5abb64bf4dd9e70cb4f0eb126cdb6d747e74d3 --- /dev/null +++ b/product/vhost-user/fw/config_power_domain.c @@ -0,0 +1,153 @@ +/* + * 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 "config_power_domain.h" +#include "config_ppu_v0.h" + +/* + * Mask of the allowed states for the top level power domains + * (but the cluster power domains) depending on the system states. + */ +static const uint32_t toplevel_allowed_state_mask_table[] = { + [MOD_PD_STATE_OFF] = MOD_PD_STATE_OFF_MASK, + [MOD_PD_STATE_ON] = MOD_PD_STATE_OFF_MASK | MOD_PD_STATE_ON_MASK, +}; + +/* + * Mask of the allowed states for the cluster power domain depending on the + * system states. + * + * While the clusters may reach a SLEEP state, SLEEP does not appear in this + * table. This is because the PPU driver backing the clusters will not accept a + * manual SLEEP request, but will transition to it automatically when possible. + */ +static const uint32_t cluster_pd_allowed_state_mask_table[] = { + [MOD_PD_STATE_OFF] = MOD_PD_STATE_OFF_MASK, + [MOD_PD_STATE_ON] = MOD_PD_STATE_OFF_MASK | MOD_PD_STATE_ON_MASK, +}; + +/* Mask of the allowed states for a core depending on the cluster states. */ +static const uint32_t core_pd_allowed_state_mask_table[] = { + [MOD_PD_STATE_OFF] = MOD_PD_STATE_OFF_MASK, + [MOD_PD_STATE_ON] = MOD_PD_STATE_OFF_MASK | MOD_PD_STATE_ON_MASK | + MOD_PD_STATE_SLEEP_MASK, + [MOD_PD_STATE_SLEEP] = MOD_PD_STATE_OFF_MASK | MOD_PD_STATE_SLEEP_MASK, +}; + +/* Power module specific configuration data (none) */ +static const struct mod_power_domain_config fvp_power_domain_config = { 0 }; + +static struct fwk_element fvp_power_domain_static_element_table[] = { + [CONFIG_POWER_DOMAIN_SYSTOP_CHILD_DBGTOP] = { + .name = "DBGTOP", + .data = &((struct mod_power_domain_element_config) { + .attributes.pd_type = MOD_PD_TYPE_DEVICE_DEBUG, + .driver_id = FWK_ID_ELEMENT_INIT( + FWK_MODULE_IDX_VPPU, PPU_V0_ELEMENT_IDX_DBGTOP), + .api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_VPPU, 0), + .allowed_state_mask_table = toplevel_allowed_state_mask_table, + .allowed_state_mask_table_size = + FWK_ARRAY_SIZE(toplevel_allowed_state_mask_table) + }), + }, + [CONFIG_POWER_DOMAIN_SYSTOP_CHILD_DPU0TOP] = { + .name = "DPU0TOP", + .data = &((struct mod_power_domain_element_config) { + .attributes.pd_type = MOD_PD_TYPE_DEVICE, + .driver_id = FWK_ID_ELEMENT_INIT( + FWK_MODULE_IDX_VPPU, PPU_V0_ELEMENT_IDX_DPU0TOP), + .api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_VPPU, 0), + .allowed_state_mask_table = toplevel_allowed_state_mask_table, + .allowed_state_mask_table_size = + FWK_ARRAY_SIZE(toplevel_allowed_state_mask_table) + }), + }, + [CONFIG_POWER_DOMAIN_SYSTOP_CHILD_DPU1TOP] = { + .name = "DPU1TOP", + .data = &((struct mod_power_domain_element_config) { + .attributes.pd_type = MOD_PD_TYPE_DEVICE, + .driver_id = FWK_ID_ELEMENT_INIT( + FWK_MODULE_IDX_VPPU, PPU_V0_ELEMENT_IDX_DPU1TOP), + .api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_VPPU, 0), + .allowed_state_mask_table = toplevel_allowed_state_mask_table, + .allowed_state_mask_table_size = + FWK_ARRAY_SIZE(toplevel_allowed_state_mask_table) + }), + }, + [CONFIG_POWER_DOMAIN_SYSTOP_CHILD_GPUTOP] = { + .name = "GPUTOP", + .data = &((struct mod_power_domain_element_config) { + .attributes.pd_type = MOD_PD_TYPE_DEVICE, + .driver_id = FWK_ID_ELEMENT_INIT( + FWK_MODULE_IDX_VPPU, PPU_V0_ELEMENT_IDX_GPUTOP), + .api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_VPPU, 0), + .allowed_state_mask_table = toplevel_allowed_state_mask_table, + .allowed_state_mask_table_size = + FWK_ARRAY_SIZE(toplevel_allowed_state_mask_table) + }), + }, + [CONFIG_POWER_DOMAIN_SYSTOP_CHILD_VPUTOP] = { + .name = "VPUTOP", + .data = &((struct mod_power_domain_element_config) { + .attributes.pd_type = MOD_PD_TYPE_DEVICE, + .driver_id = FWK_ID_ELEMENT_INIT( + FWK_MODULE_IDX_VPPU, PPU_V0_ELEMENT_IDX_VPUTOP), + .api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_VPPU, 0), + .allowed_state_mask_table = toplevel_allowed_state_mask_table, + .allowed_state_mask_table_size = + FWK_ARRAY_SIZE(toplevel_allowed_state_mask_table) + }), + }, + [CONFIG_POWER_DOMAIN_SYSTOP_CHILD_COUNT] = { + .name = "SYSTOP", + .data = &((struct mod_power_domain_element_config) { + .parent_idx = UINT32_MAX, + .attributes.pd_type = MOD_PD_TYPE_DEVICE, + .driver_id = FWK_ID_ELEMENT_INIT( + FWK_MODULE_IDX_VPPU, PPU_V0_ELEMENT_IDX_SYSTEM), + .api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_VPPU, 0), + .allowed_state_mask_table = toplevel_allowed_state_mask_table, + .allowed_state_mask_table_size = + FWK_ARRAY_SIZE(toplevel_allowed_state_mask_table) + }), + }, +}; + +/* + * Function definitions with internal linkage + */ +static const struct fwk_element *fvp_power_domain_get_element_table + (fwk_id_t module_id) +{ + const struct fwk_element *element_table; + + element_table = create_power_domain_element_table( + 4, + 2, + FWK_MODULE_IDX_VPPU, + 0, + core_pd_allowed_state_mask_table, + FWK_ARRAY_SIZE(core_pd_allowed_state_mask_table), + cluster_pd_allowed_state_mask_table, + FWK_ARRAY_SIZE(cluster_pd_allowed_state_mask_table), + fvp_power_domain_static_element_table, + FWK_ARRAY_SIZE(fvp_power_domain_static_element_table)); + + return element_table; +} + +/* + * Power module configuration data + */ +struct fwk_module_config config_power_domain = { + .data = &fvp_power_domain_config, + .elements = FWK_MODULE_DYNAMIC_ELEMENTS(fvp_power_domain_get_element_table), +}; diff --git a/product/vhost-user/fw/config_power_domain.h b/product/vhost-user/fw/config_power_domain.h new file mode 100644 index 0000000000000000000000000000000000000000..d3a1d91430b89ed48e11bd0e3d2d56e69534cd9f --- /dev/null +++ b/product/vhost-user/fw/config_power_domain.h @@ -0,0 +1,20 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CONFIG_POWER_DOMAIN_H +#define CONFIG_POWER_DOMAIN_H + +enum systop_child_index { + CONFIG_POWER_DOMAIN_SYSTOP_CHILD_DBGTOP, + CONFIG_POWER_DOMAIN_SYSTOP_CHILD_DPU0TOP, + CONFIG_POWER_DOMAIN_SYSTOP_CHILD_DPU1TOP, + CONFIG_POWER_DOMAIN_SYSTOP_CHILD_GPUTOP, + CONFIG_POWER_DOMAIN_SYSTOP_CHILD_VPUTOP, + CONFIG_POWER_DOMAIN_SYSTOP_CHILD_COUNT +}; + +#endif /* CONFIG_POWER_DOMAIN_H */ diff --git a/product/vhost-user/fw/config_ppu_v0.c b/product/vhost-user/fw/config_ppu_v0.c new file mode 100644 index 0000000000000000000000000000000000000000..6ad6117db7d926b4d87207274dc35197d859d00b --- /dev/null +++ b/product/vhost-user/fw/config_ppu_v0.c @@ -0,0 +1,156 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include "config_ppu_v0.h" + +uint32_t vppu_regdbg[16]; +uint32_t vppu_regdpu0[16]; +uint32_t vppu_regdpu1[16]; +uint32_t vppu_reggpu[16]; +uint32_t vppu_regvpu[16]; +uint32_t vppu_regsys0[16]; +uint32_t vppu_regsys1[16]; +uint32_t vppu_regcluster[16]; +uint32_t vppu_regsys[16]; + +static struct fwk_element host_ppu_v0_element_table[] = { + [PPU_V0_ELEMENT_IDX_CPU0] = { + .name = "CPU0", + .data = &((struct mod_ppu_v0_pd_config) { + .pd_type = MOD_PD_TYPE_DEVICE, + .ppu.reg_base = (uintptr_t)vppu_regcluster, + .ppu.irq = PPU_SYS1_IRQ + }), + }, + [PPU_V0_ELEMENT_IDX_CPU1] = { + .name = "CPU1", + .data = &((struct mod_ppu_v0_pd_config) { + .pd_type = MOD_PD_TYPE_DEVICE, + .ppu.reg_base = (uintptr_t)vppu_regcluster, + .ppu.irq = PPU_SYS1_IRQ + }), + }, + [PPU_V0_ELEMENT_IDX_CPU2] = { + .name = "CPU2", + .data = &((struct mod_ppu_v0_pd_config) { + .pd_type = MOD_PD_TYPE_DEVICE, + .ppu.reg_base = (uintptr_t)vppu_regcluster, + .ppu.irq = PPU_SYS1_IRQ + }), + }, + [PPU_V0_ELEMENT_IDX_CPU3] = { + .name = "CPU3", + .data = &((struct mod_ppu_v0_pd_config) { + .pd_type = MOD_PD_TYPE_DEVICE, + .ppu.reg_base = (uintptr_t)vppu_regcluster, + .ppu.irq = PPU_SYS1_IRQ + }), + }, + [PPU_V0_ELEMENT_IDX_CLUSTER0] = { + .name = "CLUSTER0", + .data = &((struct mod_ppu_v0_pd_config) { + .pd_type = MOD_PD_TYPE_DEVICE, + .ppu.reg_base = (uintptr_t)vppu_regcluster, + .ppu.irq = PPU_SYS1_IRQ + }), + }, + [PPU_V0_ELEMENT_IDX_CLUSTER1] = { + .name = "CLUSTER1", + .data = &((struct mod_ppu_v0_pd_config) { + .pd_type = MOD_PD_TYPE_DEVICE, + .ppu.reg_base = (uintptr_t)vppu_regcluster, + .ppu.irq = PPU_SYS1_IRQ + }), + }, + [PPU_V0_ELEMENT_IDX_DBGTOP] = { + .name = "DBGTOP", + .data = &((struct mod_ppu_v0_pd_config) { + .pd_type = MOD_PD_TYPE_DEVICE_DEBUG, + .ppu.reg_base = (uintptr_t)vppu_regdbg, + .ppu.irq = PPU_DEBUG_IRQ + }), + }, + [PPU_V0_ELEMENT_IDX_DPU0TOP] = { + .name = "DPU0TOP", + .data = &((struct mod_ppu_v0_pd_config) { + .pd_type = MOD_PD_TYPE_DEVICE, + .ppu.reg_base = (uintptr_t)vppu_regdpu0, + .ppu.irq = PPU_DPU0_IRQ, + .default_power_on = true, + }), + }, + [PPU_V0_ELEMENT_IDX_DPU1TOP] = { + .name = "DPU1TOP", + .data = &((struct mod_ppu_v0_pd_config) { + .pd_type = MOD_PD_TYPE_DEVICE, + .ppu.reg_base = (uintptr_t)vppu_regdpu1, + .ppu.irq = PPU_DPU1_IRQ, + .default_power_on = true, + }), + }, + [PPU_V0_ELEMENT_IDX_GPUTOP] = { + .name = "GPUTOP", + .data = &((struct mod_ppu_v0_pd_config) { + .pd_type = MOD_PD_TYPE_DEVICE, + .ppu.reg_base = (uintptr_t)vppu_reggpu, + .ppu.irq = PPU_GPU_IRQ, + .default_power_on = true, + }), + }, + [PPU_V0_ELEMENT_IDX_VPUTOP] = { + .name = "VPUTOP", + .data = &((struct mod_ppu_v0_pd_config) { + .pd_type = MOD_PD_TYPE_DEVICE, + .ppu.reg_base = (uintptr_t)vppu_regvpu, + .ppu.irq = PPU_VPU_IRQ, + .default_power_on = true, + }), + }, + [PPU_V0_ELEMENT_IDX_SYS0] = { + .name = "SYS0", + .data = &((struct mod_ppu_v0_pd_config) { + .pd_type = MOD_PD_TYPE_SYSTEM, + .ppu.reg_base = (uintptr_t)vppu_regsys0, + .ppu.irq = PPU_SYS0_IRQ + }), + }, + [PPU_V0_ELEMENT_IDX_SYS1] = { + .name = "SYS1", + .data = &((struct mod_ppu_v0_pd_config) { + .pd_type = MOD_PD_TYPE_SYSTEM, + .ppu.reg_base = (uintptr_t)vppu_regsys1, + .ppu.irq = PPU_SYS1_IRQ + }), + }, + [PPU_V0_ELEMENT_IDX_SYSTEM] = { + .name = "SYSTEM", + .data = &((struct mod_ppu_v0_pd_config) { + .pd_type = MOD_PD_TYPE_DEVICE, + .ppu.reg_base = (uintptr_t)vppu_regsys, + .ppu.irq = PPU_SYS1_IRQ, + .default_power_on = true, + }), + }, + [PPU_V0_ELEMENT_IDX_COUNT] = { 0 }, /* Termination entry */ +}; + + +static const struct fwk_element *host_ppu_v0_get_element_table + (fwk_id_t module_id) +{ + return host_ppu_v0_element_table; +} + +/* + * Power module configuration data + */ +struct fwk_module_config config_vppu = { + .elements = FWK_MODULE_DYNAMIC_ELEMENTS(host_ppu_v0_get_element_table), +}; diff --git a/product/vhost-user/fw/config_ppu_v0.h b/product/vhost-user/fw/config_ppu_v0.h new file mode 100644 index 0000000000000000000000000000000000000000..3f70a1d6add58144f89f81f69236da7398efba4c --- /dev/null +++ b/product/vhost-user/fw/config_ppu_v0.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 CONFIG_PPU_V0_H +#define CONFIG_PPU_V0_H + +enum ppu_v0_element_idx { + PPU_V0_ELEMENT_IDX_CPU0, + PPU_V0_ELEMENT_IDX_CPU1, + PPU_V0_ELEMENT_IDX_CPU2, + PPU_V0_ELEMENT_IDX_CPU3, + PPU_V0_ELEMENT_IDX_CLUSTER0, + PPU_V0_ELEMENT_IDX_CLUSTER1, + PPU_V0_ELEMENT_IDX_DBGTOP, + PPU_V0_ELEMENT_IDX_DPU0TOP, + PPU_V0_ELEMENT_IDX_DPU1TOP, + PPU_V0_ELEMENT_IDX_GPUTOP, + PPU_V0_ELEMENT_IDX_VPUTOP, + PPU_V0_ELEMENT_IDX_SYS0, + PPU_V0_ELEMENT_IDX_SYS1, + PPU_V0_ELEMENT_IDX_SYSTEM, + PPU_V0_ELEMENT_IDX_COUNT +}; + +#endif /* CONFIG_PPU_V0_H */ diff --git a/product/vhost-user/fw/config_psu.c b/product/vhost-user/fw/config_psu.c new file mode 100644 index 0000000000000000000000000000000000000000..6ad0595cbc23de700e7f50dae6393643f608fbd1 --- /dev/null +++ b/product/vhost-user/fw/config_psu.c @@ -0,0 +1,56 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + +static const struct fwk_element element_table[] = { + { + .name = "CPU_GROUP_LITTLE", + .data = &(const struct mod_psu_element_cfg) { + .driver_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_MOCK_PSU, 0), + .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_MOCK_PSU, + MOD_MOCK_PSU_API_IDX_DRIVER) + }, + }, + { + .name = "CPU_GROUP_BIG", + .data = &(const struct mod_psu_element_cfg) { + .driver_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_MOCK_PSU, 1), + .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_MOCK_PSU, + MOD_MOCK_PSU_API_IDX_DRIVER) + }, + }, + { + .name = "GPU", + .data = &(const struct mod_psu_element_cfg) { + .driver_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_MOCK_PSU, 2), + .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_MOCK_PSU, + MOD_MOCK_PSU_API_IDX_DRIVER) + }, + }, + { + .name = "VPU", + .data = &(const struct mod_psu_element_cfg) { + .driver_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_MOCK_PSU, 3), + .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_MOCK_PSU, + MOD_MOCK_PSU_API_IDX_DRIVER) + }, + }, + { 0 } +}; + +static const struct fwk_element *psu_get_element_table(fwk_id_t module_id) +{ + return element_table; +} + +struct fwk_module_config config_psu = { + .elements = FWK_MODULE_DYNAMIC_ELEMENTS(psu_get_element_table), +}; diff --git a/product/vhost-user/fw/config_reg_sensor.h b/product/vhost-user/fw/config_reg_sensor.h new file mode 100644 index 0000000000000000000000000000000000000000..60359a6aa527fde82ea2f05068c67e20b8d528f1 --- /dev/null +++ b/product/vhost-user/fw/config_reg_sensor.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 CONFIG_SENSOR_H +#define CONFIG_SENSOR_H + +enum SENSOR_DEVICES { + SENSOR_DEV_SOC_TEMP, + SENSOR_DEV_DDR_TEMP, + SENSOR_DEV_COUNT, +}; + +#endif /* CONFIG_PPU_V0_H */ diff --git a/product/vhost-user/fw/config_scmi.c b/product/vhost-user/fw/config_scmi.c new file mode 100644 index 0000000000000000000000000000000000000000..bb2ea9d9110469689ee60a00f33ecb059c55882c --- /dev/null +++ b/product/vhost-user/fw/config_scmi.c @@ -0,0 +1,122 @@ +/* + * 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 + +static const struct fwk_element service_table[] = { + [SCMI_SERVICE_IDX_PSCI] = { + .name = "agent PSCI", + .data = &((struct mod_scmi_service_config) { + .transport_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_MSG_SMT, + SCMI_SERVICE_IDX_PSCI), + .transport_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_MSG_SMT, + MOD_MSG_SMT_API_IDX_SCMI_TRANSPORT), + .scmi_agent_id = SCMI_AGENT_ID_PSCI, + .transport_notification_init_id = FWK_ID_NONE_INIT, + .scmi_p2a_id = FWK_ID_NONE_INIT, + }), + }, + [SCMI_SERVICE_IDX_OSPM_0] = { + .name = "agent OSPM0", + .data = &((struct mod_scmi_service_config) { + .transport_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_MSG_SMT, + SCMI_SERVICE_IDX_OSPM_0), + .transport_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_MSG_SMT, + MOD_MSG_SMT_API_IDX_SCMI_TRANSPORT), + .scmi_agent_id = SCMI_AGENT_ID_OSPM, + .transport_notification_init_id = FWK_ID_NONE_INIT, +#ifdef BUILD_HAS_SCMI_NOTIFICATIONS + .scmi_p2a_id = FWK_ID_ELEMENT_INIT( + FWK_MODULE_IDX_SCMI, + SCMI_SERVICE_IDX_OSPM_0_P2A), +#else + .scmi_p2a_id = FWK_ID_NONE_INIT, +#endif + }), + }, + [SCMI_SERVICE_IDX_OSPM_1] = { + .name = "agent OSPM1", + .data = &((struct mod_scmi_service_config) { + .transport_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_MSG_SMT, + SCMI_SERVICE_IDX_OSPM_1), + .transport_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_MSG_SMT, + MOD_MSG_SMT_API_IDX_SCMI_TRANSPORT), + .scmi_agent_id = SCMI_AGENT_ID_PERF, + .transport_notification_init_id = FWK_ID_NONE_INIT, +#ifdef BUILD_HAS_SCMI_NOTIFICATIONS + .scmi_p2a_id = FWK_ID_ELEMENT_INIT( + FWK_MODULE_IDX_SCMI, + SCMI_SERVICE_IDX_OSPM_1_P2A), +#else + .scmi_p2a_id = FWK_ID_NONE_INIT, +#endif + }), + }, +#ifdef BUILD_HAS_SCMI_NOTIFICATIONS + [SCMI_SERVICE_IDX_OSPM_0_P2A] = { + .name = "agent OSPM0 P2A", + .data = &((struct mod_scmi_service_config) { + .transport_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_MSG_SMT, + SCMI_SERVICE_IDX_OSPM_0_P2A), + .transport_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_MSG_SMT, + MOD_MSG_SMT_API_IDX_SCMI_TRANSPORT), + .scmi_agent_id = SCMI_AGENT_ID_OSPM, + .transport_notification_init_id = FWK_ID_NONE_INIT, + .scmi_p2a_id = FWK_ID_NONE_INIT, + }), + }, + [SCMI_SERVICE_IDX_OSPM_1_P2A] = { + .name = "agent OSPM1 P2A", + .data = &((struct mod_scmi_service_config) { + .transport_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_MSG_SMT, + SCMI_SERVICE_IDX_OSPM_1_P2A), + .transport_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_MSG_SMT, + MOD_MSG_SMT_API_IDX_SCMI_TRANSPORT), + .scmi_agent_id = SCMI_AGENT_ID_OSPM, + .transport_notification_init_id = FWK_ID_NONE_INIT, + .scmi_p2a_id = FWK_ID_NONE_INIT, + }), + }, +#endif + [SCMI_SERVICE_IDX_COUNT] = { 0 } +}; + +static const struct fwk_element *get_service_table(fwk_id_t module_id) +{ + return service_table; +} + +static const struct mod_scmi_agent agent_table[] = { + [SCMI_AGENT_ID_OSPM] = { + .type = SCMI_AGENT_TYPE_OSPM, + .name = "OSPM", + }, + [SCMI_AGENT_ID_PSCI] = { + .type = SCMI_AGENT_TYPE_PSCI, + .name = "PSCI", + }, + [SCMI_AGENT_ID_PERF] = { + .type = SCMI_AGENT_TYPE_OSPM, + .name = "PERF", + }, +}; + +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_service_table), +}; diff --git a/product/vhost-user/fw/config_scmi_clock.c b/product/vhost-user/fw/config_scmi_clock.c new file mode 100644 index 0000000000000000000000000000000000000000..d2eb353badacb3f6dcf28796389114df6de2c26d --- /dev/null +++ b/product/vhost-user/fw/config_scmi_clock.c @@ -0,0 +1,98 @@ +/* + * 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 "clock_devices.h" + +static const struct mod_scmi_clock_device agent_device_table_ospm[] = { + { + /* MOCK_0 */ + .element_id = + FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_CLOCK, CLOCK_DEV_IDX_MOCK_0), + }, + { + /* MOCK_1 */ + .element_id = + FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_CLOCK, CLOCK_DEV_IDX_MOCK_1), + }, + { + /* VPU */ + .element_id = + FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_CLOCK, CLOCK_DEV_IDX_VPU), + }, + { + /* MOCK_3 */ + .element_id = + FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_CLOCK, CLOCK_DEV_IDX_MOCK_3), + }, + { + /* DPU */ + .element_id = + FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_CLOCK, CLOCK_DEV_IDX_DPU), + }, + { + /* PIXEL_0 */ + .element_id = + FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_CLOCK, CLOCK_DEV_IDX_PIXEL_0), + }, + { + /* PIXEL_1 */ + .element_id = + FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_CLOCK, CLOCK_DEV_IDX_PIXEL_1), + }, +}; + +static const struct mod_scmi_clock_device agent_device_table_perf[] = { + { + /* MOCK_0 */ + .element_id = + FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_CLOCK, CLOCK_DEV_IDX_MOCK_0), + }, + { + /* MOCK_2 */ + .element_id = + FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_CLOCK, CLOCK_DEV_IDX_MOCK_2), + }, + { + /* MOCK_3 */ + .element_id = + FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_CLOCK, CLOCK_DEV_IDX_MOCK_3), + }, + { + /* PIXEL_0 */ + .element_id = + FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_CLOCK, CLOCK_DEV_IDX_PIXEL_0), + }, + { + /* PIXEL_1 */ + .element_id = + FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_CLOCK, CLOCK_DEV_IDX_PIXEL_1), + }, +}; + +static const struct mod_scmi_clock_agent agent_table[SCMI_AGENT_ID_COUNT] = { + [SCMI_AGENT_ID_OSPM] = { + .device_table = agent_device_table_ospm, + .device_count = FWK_ARRAY_SIZE(agent_device_table_ospm), + }, + [SCMI_AGENT_ID_PSCI] = { 0 /* No access */ }, + [SCMI_AGENT_ID_PERF] = { + .device_table = agent_device_table_perf, + .device_count = FWK_ARRAY_SIZE(agent_device_table_perf), + }, +}; + +struct fwk_module_config config_scmi_clock = { + .data = &((struct mod_scmi_clock_config) { + .max_pending_transactions = 0, + .agent_table = agent_table, + .agent_count = FWK_ARRAY_SIZE(agent_table), + }), +}; diff --git a/product/vhost-user/fw/config_scmi_perf.c b/product/vhost-user/fw/config_scmi_perf.c new file mode 100644 index 0000000000000000000000000000000000000000..63ca90e7b4d620ac7cbdbd4e9207d37a81b751be --- /dev/null +++ b/product/vhost-user/fw/config_scmi_perf.c @@ -0,0 +1,31 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include "config_dvfs.h" + +static const struct mod_scmi_perf_domain_config domains[] = { + [DVFS_ELEMENT_IDX_LITTLE] = { + .fast_channels_addr_scp = 0x0, + }, + [DVFS_ELEMENT_IDX_BIG] = { + .fast_channels_addr_scp = 0x0, + }, + [DVFS_ELEMENT_IDX_GPU] = { + .fast_channels_addr_scp = 0x0, + }, +}; + +struct fwk_module_config config_scmi_perf = { + .data = &((struct mod_scmi_perf_config) { + .domains = &domains, + .perf_doms_count = FWK_ARRAY_SIZE(domains), + .fast_channels_alarm_id = FWK_ID_NONE_INIT, + }), +}; diff --git a/product/vhost-user/fw/config_scmi_power_domain.c b/product/vhost-user/fw/config_scmi_power_domain.c new file mode 100644 index 0000000000000000000000000000000000000000..0740409915e723032ae4852d7c97b20bd6018b28 --- /dev/null +++ b/product/vhost-user/fw/config_scmi_power_domain.c @@ -0,0 +1,11 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +/* No elements, no module configuration data */ +struct fwk_module_config config_scmi_power_domain = { 0 }; diff --git a/product/vhost-user/fw/config_sensor.c b/product/vhost-user/fw/config_sensor.c new file mode 100644 index 0000000000000000000000000000000000000000..20826868113ed5e5d3e217c9db21e050e6437072 --- /dev/null +++ b/product/vhost-user/fw/config_sensor.c @@ -0,0 +1,100 @@ +/* + * 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 "config_reg_sensor.h" + +uint64_t soc_temp[3] = {25000, 25000, 25000}; +uint64_t ddr_temp[1] = {25000}; +/* + * Register Sensor driver config + */ +static struct mod_sensor_info info_soc_temperature = { + .type = MOD_SENSOR_TYPE_DEGREES_C, + .update_interval = 0, + .update_interval_multiplier = 0, + .unit_multiplier = -3, +}; + +static const struct fwk_element reg_sensor_element_table[] = { + [SENSOR_DEV_SOC_TEMP] = { + .name = "Soc Temperature", + .data = &((struct mod_reg_sensor_dev_config) { + .reg = (uintptr_t)(soc_temp), + .info = &info_soc_temperature, + }), + }, + [SENSOR_DEV_DDR_TEMP] = { + .name = "DDR Temperature", + .data = &((struct mod_reg_sensor_dev_config) { + .reg = (uintptr_t)(ddr_temp), + .info = &info_soc_temperature, + }), + }, + [SENSOR_DEV_COUNT] = { 0 }, +}; + +static const struct fwk_element *get_reg_sensor_element_table(fwk_id_t id) +{ + return reg_sensor_element_table; +} + +struct fwk_module_config config_reg_sensor = { + .elements = FWK_MODULE_DYNAMIC_ELEMENTS(get_reg_sensor_element_table), +}; + +/* + * Sensor module config + */ +static const struct fwk_element sensor_element_table[] = { + [0] = { + .name = "Soc Temperature", + .data = &((const struct mod_sensor_dev_config) { + .driver_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_REG_SENSOR, + SENSOR_DEV_SOC_TEMP), + .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_REG_SENSOR, 0), + .trip_point = { + .count = 2, + } + }), + }, + [1] = { + .name = "DDR Temperature", + .data = &((const struct mod_sensor_dev_config) { + .driver_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_REG_SENSOR, + SENSOR_DEV_DDR_TEMP), + .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_REG_SENSOR, 0), + .trip_point = { + .count = 2, + } + }), + }, + [2] = { 0 }, +}; + +static const struct fwk_element *get_sensor_element_table(fwk_id_t module_id) +{ + return sensor_element_table; +} +static const struct mod_sensor_config sensor_config = { +#ifdef BUILD_HAS_SCMI_NOTIFICATIONS + .notification_id = FWK_ID_MODULE_INIT(FWK_MODULE_IDX_SCMI_SENSOR), + .trip_point_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_SCMI_SENSOR, + SCMI_SENSOR_API_IDX_TRIP_POINT), +#else + .notification_id = FWK_ID_NONE_INIT +#endif +}; + +struct fwk_module_config config_sensor = { + .elements = FWK_MODULE_DYNAMIC_ELEMENTS(get_sensor_element_table), + .data = &sensor_config, +}; diff --git a/product/vhost-user/fw/config_vpll.c b/product/vhost-user/fw/config_vpll.c new file mode 100644 index 0000000000000000000000000000000000000000..78874a888bb8633437c5bec1995be26f8b284e03 --- /dev/null +++ b/product/vhost-user/fw/config_vpll.c @@ -0,0 +1,108 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +uint32_t ctrl_reg[7]; + +static const struct fwk_element system_pll_element_table[] = { + { + .name = "CPU_PLL_0", + .data = &((struct mod_system_pll_dev_config) { + .control_reg = &ctrl_reg[0], + .lock_flag_mask = PLL_STATUS1_CPUPLLLOCK(0, 0), + .initial_rate = 1330 * FWK_MHZ, + .min_rate = MOD_SYSTEM_PLL_MIN_RATE, + .max_rate = MOD_SYSTEM_PLL_MAX_RATE, + .min_step = MOD_SYSTEM_PLL_MIN_INTERVAL, + .defer_initialization = false, + }), + }, + { + .name = "CPU_PLL_1", + .data = &((struct mod_system_pll_dev_config) { + .control_reg = &ctrl_reg[1], + .lock_flag_mask = PLL_STATUS1_CPUPLLLOCK(0, 1), + .initial_rate = 1750 * FWK_MHZ, + .min_rate = MOD_SYSTEM_PLL_MIN_RATE, + .max_rate = MOD_SYSTEM_PLL_MAX_RATE, + .min_step = MOD_SYSTEM_PLL_MIN_INTERVAL, + .defer_initialization = false, + }), + }, + { + .name = "GPU_PLL", + .data = &((struct mod_system_pll_dev_config) { + .control_reg = &ctrl_reg[2], + .lock_flag_mask = PLL_STATUS0_GPUPLLLOCK, + .initial_rate = 600 * FWK_MHZ, + .min_rate = MOD_SYSTEM_PLL_MIN_RATE, + .max_rate = MOD_SYSTEM_PLL_MAX_RATE, + .min_step = MOD_SYSTEM_PLL_MIN_INTERVAL, + .defer_initialization = false, + }), + }, + { + .name = "DPU_PLL", + .data = &((struct mod_system_pll_dev_config) { + .control_reg = &ctrl_reg[3], + .lock_flag_mask = PLL_STATUS0_DISPLAYPLLLOCK, + .initial_rate = 260 * FWK_MHZ, + .min_rate = MOD_SYSTEM_PLL_MIN_RATE, + .max_rate = MOD_SYSTEM_PLL_MAX_RATE, + .min_step = MOD_SYSTEM_PLL_MIN_INTERVAL, + .defer_initialization = false, + }), + }, + { + .name = "VPU_PLL", + .data = &((struct mod_system_pll_dev_config) { + .control_reg = &ctrl_reg[4], + .lock_flag_mask = PLL_STATUS0_VIDEOPLLLOCK, + .initial_rate = 600 * FWK_MHZ, + .min_rate = MOD_SYSTEM_PLL_MIN_RATE, + .max_rate = MOD_SYSTEM_PLL_MAX_RATE, + .min_step = MOD_SYSTEM_PLL_MIN_INTERVAL, + .defer_initialization = false, + }), + }, + { + .name = "PIX0_PLL", + .data = &((struct mod_system_pll_dev_config) { + .control_reg = &ctrl_reg[5], + .initial_rate = 594 * FWK_MHZ, + .min_rate = 12500 * FWK_KHZ, + .max_rate = 594 * FWK_MHZ, + .min_step = 250 * FWK_KHZ, + .defer_initialization = false, + }), + }, + { + .name = "PIX1_PLL", + .data = &((struct mod_system_pll_dev_config) { + .control_reg = &ctrl_reg[6], + .initial_rate = 594 * FWK_MHZ, + .min_rate = 12500 * FWK_KHZ, + .max_rate = 594 * FWK_MHZ, + .min_step = 250 * FWK_KHZ, + .defer_initialization = false, + }), + }, + { 0 }, /* Termination description. */ +}; + +static const struct fwk_element *system_pll_get_element_table + (fwk_id_t module_id) +{ + return system_pll_element_table; +} + +struct fwk_module_config config_system_pll = { + .elements = FWK_MODULE_DYNAMIC_ELEMENTS(system_pll_get_element_table), +}; diff --git a/product/vhost-user/include/fake_irq.h b/product/vhost-user/include/fake_irq.h new file mode 100644 index 0000000000000000000000000000000000000000..75e53e5d8b5b56880e34f50a51e99a639c45b043 --- /dev/null +++ b/product/vhost-user/include/fake_irq.h @@ -0,0 +1,178 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SGM775_IRQ_H +#define SGM775_IRQ_H + +#include + +#define WDOG_IRQ FWK_INTERRUPT_NMI /* SCP Watchdog (SP805) */ + +enum sgm775_irq { + TIM32KHZ_IRQ = 0, /* 32KHz Physical Timer */ + CDBG_PWR_UP_REQ_IRQ = 1, /* Coresight Debug Power Request */ + CSYS_PWR_UP_REQ_IRQ = 2, /* Coresight System Power Request */ + CDBG_RST_REQ_IRQ = 3, /* Coresight Debug Reset Request */ + GIC_EXT_WAKEUP_IRQ = 4, /* External GIC Wakeup Request */ + RESERVED5_IRQ = 5, /* Reserved */ + RESERVED6_IRQ = 6, /* Reserved */ + RESERVED7_IRQ = 7, /* Reserved */ + RESERVED8_IRQ = 8, /* Reserved */ + RESERVED9_IRQ = 9, /* Reserved */ + RESERVED10_IRQ = 10, /* Reserved */ + RESERVED11_IRQ = 11, /* Reserved */ + RESERVED12_IRQ = 12, /* Reserved */ + RESERVED13_IRQ = 13, /* Reserved */ + RESERVED14_IRQ = 14, /* Reserved */ + RESERVED15_IRQ = 15, /* Reserved */ + SOC_WAKEUP0_IRQ = 16, /* SoC Expansion Wakeup */ + SOC_WAKEUP1_IRQ = 17, /* SoC Expansion Wakeup */ + SOC_WAKEUP2_IRQ = 18, /* SoC Expansion Wakeup */ + SOC_WAKEUP3_IRQ = 19, /* SoC Expansion Wakeup */ + SOC_WAKEUP4_IRQ = 20, /* SoC Expansion Wakeup */ + SOC_WAKEUP5_IRQ = 21, /* SoC Expansion Wakeup */ + SOC_WAKEUP6_IRQ = 22, /* SoC Expansion Wakeup */ + SOC_WAKEUP7_IRQ = 23, /* SoC Expansion Wakeup */ + SOC_WAKEUP8_IRQ = 24, /* SoC Expansion Wakeup */ + SOC_WAKEUP9_IRQ = 25, /* SoC Expansion Wakeup */ + SOC_WAKEUP10_IRQ = 26, /* SoC Expansion Wakeup */ + SOC_WAKEUP11_IRQ = 27, /* SoC Expansion Wakeup */ + SOC_WAKEUP12_IRQ = 28, /* SoC Expansion Wakeup */ + SOC_WAKEUP13_IRQ = 29, /* SoC Expansion Wakeup */ + SOC_WAKEUP14_IRQ = 30, /* SoC Expansion Wakeup */ + SOC_WAKEUP15_IRQ = 31, /* SoC Expansion Wakeup */ + PPU_SCP_IRQ = 32, /* SCP Power Policy Unit */ + TIMREFCLK_IRQ = 33, /* REFCLK Physical Timer */ + MHU_HIGH_PRIO_IRQ = 34, /* MHU High Priority */ + MHU_LOW_PRIO_IRQ = 35, /* MHU Low Priority */ + MHU_SECURE_IRQ = 36, /* MHU Secure */ + CTI_TRIGGER0_IRQ = 37, /* SCP CTI Trigger */ + CTI_TRIGGER1_IRQ = 38, /* SCP CTI Trigger */ + GIC_ERROR_ECC_IRQ = 39, /* GIC Error (ECC Fatal) */ + GIC_ERROR_AXIM_IRQ = 40, /* GIC Error (AXIM) */ + DMC_RESERVED0_IRQ = 41, /* DMC, Reserved */ + DMC_0_ERROR_ECC_IRQ = 42, /* DMC0 Combined ECC Error */ + DMC_0_ERROR_ACCESS_IRQ = 43, /* DMC0 Combined Misc Access Error */ + DMC_RESERVED1_IRQ = 44, /* DMC, Reserved */ + DMC_RESERVED2_IRQ = 45, /* DMC, Reserved */ + DMC_1_ERROR_ECC_IRQ = 46, /* DMC1 Combined ECC Error */ + DMC_1_ERROR_ACCESS_IRQ = 47, /* DMC1 Combined Misc Access Error */ + DMC_RESERVED3_IRQ = 48, /* DMC, Reserved */ + DMC_RESERVED4_IRQ = 49, /* DMC, Reserved */ + DMC_2_ERROR_ECC_IRQ = 50, /* DMC2 Combined ECC Error */ + DMC_2_ERROR_ACCESS_IRQ = 51, /* DMC2 Combined Misc Access Error */ + DMC_RESERVED5_IRQ = 52, /* DMC, Reserved */ + DMC_RESERVED6_IRQ = 53, /* DMC, Reserved */ + DMC_3_ERROR_ECC_IRQ = 54, /* DMC3 Combined ECC Error */ + DMC_3_ERROR_ACCESS_IRQ = 55, /* DMC3 Combined Misc Access Error */ + DMC_RESERVED7_IRQ = 56, /* DMC, Reserved */ + RESERVED57_IRQ = 57, /* Reserved */ + RESERVED58_IRQ = 58, /* Reserved */ + RESERVED59_IRQ = 59, /* Reserved */ + RESERVED60_IRQ = 60, /* Reserved */ + RESERVED61_IRQ = 61, /* Reserved */ + RESERVED62_IRQ = 62, /* Reserved */ + RESERVED63_IRQ = 63, /* Reserved */ + PPU_CLUS0CORE0_IRQ = 64, /* Cluster 0 Core 0 Power Policy Unit */ + PPU_CLUS0CORE1_IRQ = 65, /* Cluster 0 Core 1 Power Policy Unit */ + PPU_CLUS0CORE2_IRQ = 66, /* Cluster 0 Core 2 Power Policy Unit */ + PPU_CLUS0CORE3_IRQ = 67, /* Cluster 0 Core 3 Power Policy Unit */ + PPU_CLUS0_IRQ = 68, /* Cluster 0 Power Policy Unit */ + PPU_CLUS1CORE0_IRQ = 69, /* Cluster 1 Core 0 Power Policy Unit */ + PPU_CLUS1CORE1_IRQ = 70, /* Cluster 1 Core 1 Power Policy Unit */ + PPU_CLUS1CORE2_IRQ = 71, /* Cluster 1 Core 2 Power Policy Unit */ + PPU_CLUS1CORE3_IRQ = 72, /* Cluster 1 Core 3 Power Policy Unit */ + PPU_CLUS1_IRQ = 73, /* Cluster 1 Power Policy Unit */ + PPU_SYS0_IRQ = 74, /* System Power Policy Unit 0 */ + PPU_SYS1_IRQ = 75, /* System Power Policy Unit 1 */ + PPU_GPU_IRQ = 76, /* GPU Power Policy Unit */ + PPU_VPU_IRQ = 77, /* Video Power Policy Unit */ + RESERVED78_IRQ = 78, /* Reserved */ + PPU_DPU0_IRQ = 79, /* Display Power Policy Unit 0 */ + PPU_DPU1_IRQ = 80, /* Display Power Policy Unit 1 */ + PPU_DEBUG_IRQ = 81, /* DBGSYS Power Policy Unit */ + RESERVED82_IRQ = 82, /* Reserved */ + RESERVED83_IRQ = 83, /* Reserved */ + RESERVED84_IRQ = 84, /* Reserved */ + RESERVED85_IRQ = 85, /* Reserved */ + RESERVED86_IRQ = 86, /* Reserved */ + RESERVED87_IRQ = 87, /* Reserved */ + RESERVED88_IRQ = 88, /* Reserved */ + RESERVED89_IRQ = 89, /* Reserved */ + PPU_CLUS0CORE4_IRQ = 90, /* Cluster 0 Core 4 Power Policy Unit */ + PPU_CLUS0CORE5_IRQ = 91, /* Cluster 0 Core 5 Power Policy Unit */ + PPU_CLUS0CORE6_IRQ = 92, /* Cluster 0 Core 6 Power Policy Unit */ + PPU_CLUS0CORE7_IRQ = 93, /* Cluster 0 Core 7 Power Policy Unit */ + PPU_CLUS1CORE4_IRQ = 94, /* Cluster 1 Core 4 Power Policy Unit */ + PPU_CLUS1CORE5_IRQ = 95, /* Cluster 1 Core 5 Power Policy Unit */ + PPU_CLUS1CORE6_IRQ = 96, /* Cluster 1 Core 6 Power Policy Unit */ + PPU_CLUS1CORE7_IRQ = 97, /* Cluster 1 Core 7 Power Policy Unit */ + PLL_CLUS0_LOCK_IRQ = 98, /* Cluster 0 CPU PLL Lock */ + PLL_CLUS1_LOCK_IRQ = 99, /* Cluster 1 CPU PLL Lock */ + PLL_GPU_LOCK_IRQ = 100, /* GPU PLL Lock */ + PLL_VPU_LOCK_IRQ = 101, /* Video PLL Lock */ + PLL_SYS_LOCK_IRQ = 102, /* System PLL Lock */ + PLL_DPU_LOCK_IRQ = 103, /* Display PLL Lock */ + PLL_CLUS0CORE0_IRQ = 104, /* Cluster 0 PLL0 Lock */ + PLL_CLUS0CORE1_IRQ = 105, /* Cluster 0 PLL1 Lock */ + PLL_CLUS0CORE2_IRQ = 106, /* Cluster 0 PLL2 Lock */ + PLL_CLUS0CORE3_IRQ = 107, /* Cluster 0 PLL3 Lock */ + PLL_CLUS0CORE4_IRQ = 108, /* Cluster 0 PLL4 Lock */ + PLL_CLUS0CORE5_IRQ = 109, /* Cluster 0 PLL5 Lock */ + PLL_CLUS0CORE6_IRQ = 110, /* Cluster 0 PLL6 Lock */ + PLL_CLUS0CORE7_IRQ = 111, /* Cluster 0 PLL7 Lock */ + PLL_CLUS1CORE0_IRQ = 112, /* Cluster 1 PLL0 Lock */ + PLL_CLUS1CORE1_IRQ = 113, /* Cluster 1 PLL1 Lock */ + PLL_CLUS1CORE2_IRQ = 114, /* Cluster 1 PLL2 Lock */ + PLL_CLUS1CORE3_IRQ = 115, /* Cluster 1 PLL3 Lock */ + PLL_CLUS1CORE4_IRQ = 116, /* Cluster 1 PLL4 Lock */ + PLL_CLUS1CORE5_IRQ = 117, /* Cluster 1 PLL5 Lock */ + PLL_CLUS1CORE6_IRQ = 118, /* Cluster 1 PLL6 Lock */ + PLL_CLUS1CORE7_IRQ = 119, /* Cluster 1 PLL7 Lock */ + RESERVED120_IRQ = 120, /* Reserved */ + RESERVED121_IRQ = 121, /* Reserved */ + RESERVED122_IRQ = 122, /* Reserved */ + RESERVED123_IRQ = 123, /* Reserved */ + RESERVED124_IRQ = 124, /* Reserved */ + RESERVED125_IRQ = 125, /* Reserved */ + RESERVED126_IRQ = 126, /* Reserved */ + RESERVED127_IRQ = 127, /* Reserved */ + SCP_EXT_INTR0_IRQ = 128, /* SCP Customer Extension */ + SCP_EXT_INTR1_IRQ = 129, /* SCP Customer Extension */ + SCP_EXT_INTR2_IRQ = 130, /* SCP Customer Extension */ + SCP_EXT_INTR3_IRQ = 131, /* SCP Customer Extension */ + SCP_EXT_INTR4_IRQ = 132, /* SCP Customer Extension */ + SCP_EXT_INTR5_IRQ = 133, /* SCP Customer Extension */ + SCP_EXT_INTR6_IRQ = 134, /* SCP Customer Extension */ + SCP_EXT_INTR7_IRQ = 135, /* SCP Customer Extension */ + SCP_EXT_INTR8_IRQ = 136, /* SCP Customer Extension */ + SCP_EXT_INTR9_IRQ = 137, /* SCP Customer Extension */ + SCP_EXT_INTR10_IRQ = 138, /* SCP Customer Extension */ + SCP_EXT_INTR11_IRQ = 139, /* SCP Customer Extension */ + SCP_EXT_INTR12_IRQ = 140, /* SCP Customer Extension */ + SCP_EXT_INTR13_IRQ = 141, /* SCP Customer Extension */ + SCP_EXT_INTR14_IRQ = 142, /* SCP Customer Extension */ + SCP_EXT_INTR15_IRQ = 143, /* SCP Customer Extension */ + SCP_EXT_INTR16_IRQ = 144, /* SCP Customer Extension */ + SCP_EXT_INTR17_IRQ = 145, /* SCP Customer Extension */ + SCP_EXT_INTR18_IRQ = 146, /* SCP Customer Extension */ + SCP_EXT_INTR19_IRQ = 147, /* SCP Customer Extension */ + SCP_EXT_INTR20_IRQ = 148, /* SCP Customer Extension */ + SCP_EXT_INTR21_IRQ = 149, /* SCP Customer Extension */ + SCP_EXT_INTR22_IRQ = 150, /* SCP Customer Extension */ + SCP_EXT_INTR23_IRQ = 151, /* SCP Customer Extension */ + SCP_EXT_INTR24_IRQ = 152, /* SCP Customer Extension */ + SCP_EXT_INTR25_IRQ = 153, /* SCP Customer Extension */ + SCP_EXT_INTR26_IRQ = 154, /* SCP Customer Extension */ + SCP_EXT_INTR27_IRQ = 155, /* SCP Customer Extension */ + SCP_EXT_INTR28_IRQ = 156, /* SCP Customer Extension */ + SCP_EXT_INTR29_IRQ = 157, /* SCP Customer Extension */ + SCP_EXT_INTR30_IRQ = 158, /* SCP Customer Extension */ + SCP_EXT_INTR31_IRQ = 159, /* SCP Customer Extension */ +}; + +#endif /* SGM775_IRQ_H */ diff --git a/product/vhost-user/include/fake_mmap.h b/product/vhost-user/include/fake_mmap.h new file mode 100644 index 0000000000000000000000000000000000000000..c3643fc6ccccc2c41d311ec594c5b245e0554179 --- /dev/null +++ b/product/vhost-user/include/fake_mmap.h @@ -0,0 +1,101 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SGM775_MMAP_H +#define SGM775_MMAP_H + +#include + +/* + * Top-level base addresses + */ +#define EXPANSION0_BASE UINT32_C(0x40000000) +#define PERIPHERAL_BASE UINT32_C(0x44000000) +#define POWER_PERIPHERAL_BASE UINT32_C(0x50000000) +#define SYS0_BASE UINT32_C(0x60000000) +#define SYS1_BASE UINT32_C(0xA0000000) +#define PPB_INTERNAL_BASE UINT32_C(0xE0000000) +#define PPB_EXTERNAL_BASE UINT32_C(0xE0040000) +#define EXPANSION1_BASE UINT32_C(0xE0100000) + +/* + * Peripherals + */ +#define REFCLK_CNTCTL_BASE (PERIPHERAL_BASE + 0x0000) +#define REFCLK_CNTBASE0_BASE (PERIPHERAL_BASE + 0x1000) +#define WDOG_BASE (PERIPHERAL_BASE + 0x6000) +#define S32K_CNTCONTROL_BASE (PERIPHERAL_BASE + 0x7000) +#define S32K_CNTCTL_BASE (PERIPHERAL_BASE + 0x8000) +#define S32K_CNTBASE0_BASE (PERIPHERAL_BASE + 0x9000) +#define CS_CNTCONTROL_BASE (PERIPHERAL_BASE + 0xA000) + +/* + * Power control peripherals + */ +#define PIK_SCP_BASE (POWER_PERIPHERAL_BASE + 0x00000) +#define PIK_DEBUG_BASE (POWER_PERIPHERAL_BASE + 0x20000) +#define SENSOR_DEBUG_BASE (POWER_PERIPHERAL_BASE + 0x30000) +#define PIK_SYSTEM_BASE (POWER_PERIPHERAL_BASE + 0x40000) +#define SENSOR_SYSTEM_BASE (POWER_PERIPHERAL_BASE + 0x50000) +#define PIK_CLUS0_BASE (POWER_PERIPHERAL_BASE + 0x60000) +#define SENSOR_CLUS0_BASE (POWER_PERIPHERAL_BASE + 0x70000) +#define PIK_CLUS1_BASE (POWER_PERIPHERAL_BASE + 0x80000) +#define SENSOR_CLUS1_BASE (POWER_PERIPHERAL_BASE + 0x90000) +#define PIK_GPU_BASE (POWER_PERIPHERAL_BASE + 0xA0000) +#define SENSOR_GPU_BASE (POWER_PERIPHERAL_BASE + 0xB0000) +#define PIK_VPU_BASE (POWER_PERIPHERAL_BASE + 0xC0000) +#define SENSOR_VPU_BASE (POWER_PERIPHERAL_BASE + 0xD0000) +#define PIK_DPU_BASE (POWER_PERIPHERAL_BASE + 0xE0000) +#define SENSOR_DPU_BASE (POWER_PERIPHERAL_BASE + 0xF0000) + +/* + * PPU base address + */ +#define PPU_SCP_BASE (PIK_SCP_BASE + 0x1000) +#define PPU_SYS0_BASE (PIK_SYSTEM_BASE + 0x1000) +#define PPU_SYS1_BASE (PIK_SYSTEM_BASE + 0x2000) +#define PPU_DEBUG_BASE (PIK_DEBUG_BASE + 0x1000) +#define PPU_CLUS0CORE0_BASE (PIK_CLUS0_BASE + 0x2000) +#define PPU_CLUS0CORE1_BASE (PIK_CLUS0_BASE + 0x3000) +#define PPU_CLUS0CORE2_BASE (PIK_CLUS0_BASE + 0x4000) +#define PPU_CLUS0CORE3_BASE (PIK_CLUS0_BASE + 0x5000) +#define PPU_CLUS0CORE4_BASE (PIK_CLUS0_BASE + 0x6000) +#define PPU_CLUS0CORE5_BASE (PIK_CLUS0_BASE + 0x7000) +#define PPU_CLUS0CORE6_BASE (PIK_CLUS0_BASE + 0x8000) +#define PPU_CLUS0CORE7_BASE (PIK_CLUS0_BASE + 0x9000) +#define PPU_CLUS0_BASE (PIK_CLUS0_BASE + 0x1000) +#define PPU_CLUS1CORE0_BASE (PIK_CLUS1_BASE + 0x2000) +#define PPU_CLUS1CORE1_BASE (PIK_CLUS1_BASE + 0x3000) +#define PPU_CLUS1CORE2_BASE (PIK_CLUS1_BASE + 0x4000) +#define PPU_CLUS1CORE3_BASE (PIK_CLUS1_BASE + 0x5000) +#define PPU_CLUS1_BASE (PIK_CLUS1_BASE + 0x1000) +#define PPU_GPU_BASE (PIK_GPU_BASE + 0x1000) +#define PPU_VPU_BASE (PIK_VPU_BASE + 0x1000) +#define PPU_DPU0_BASE (PIK_DPU_BASE + 0x2000) +#define PPU_DPU1_BASE (PIK_DPU_BASE + 0x3000) + +/* + * System access port 1 + */ +#define TRUSTED_RAM_BASE (SYS1_BASE + 0x04000000) +#define NONTRUSTED_RAM_BASE (SYS1_BASE + 0x06000000) +#define SSC_BASE (SYS1_BASE + 0x2A420000) +#define REFCLK_CNTCONTROL_BASE (SYS1_BASE + 0x2A430000) +#define MHU_BASE (SYS1_BASE + 0x2B1F0000) + +/* + * Base addresses of MHU devices + */ + +#define MHU_SCP_INTR_L_BASE (MHU_BASE) +#define MHU_SCP_INTR_H_BASE (MHU_BASE + 0x0020) +#define MHU_CPU_INTR_L_BASE (MHU_BASE + 0x0100) +#define MHU_CPU_INTR_H_BASE (MHU_BASE + 0x0120) +#define MHU_SCP_INTR_S_BASE (MHU_BASE + 0x0200) +#define MHU_CPU_INTR_S_BASE (MHU_BASE + 0x0300) + +#endif /* SGM775_MMAP_H */ diff --git a/product/vhost-user/include/fake_pik.h b/product/vhost-user/include/fake_pik.h new file mode 100644 index 0000000000000000000000000000000000000000..f0d78e1a5ee02247274aae3ccb150702deec4184 --- /dev/null +++ b/product/vhost-user/include/fake_pik.h @@ -0,0 +1,13 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef FAKE_PIK_H +#define FAKE_PIK_H + +#include + +#endif /* SGM775_PIK_H */ diff --git a/product/vhost-user/include/fake_pik_scp.h b/product/vhost-user/include/fake_pik_scp.h new file mode 100644 index 0000000000000000000000000000000000000000..458ca3755e71fb9a440508b0e42e904d9573ab00 --- /dev/null +++ b/product/vhost-user/include/fake_pik_scp.h @@ -0,0 +1,63 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef FAKE_PIK_SCP_H +#define FAKE_PIK_SCP_H + +#include +#include + +/*! + * \brief SCP PIK register definitions + */ +struct pik_scp_reg { + uint32_t RESERVED0[4]; + FWK_RW uint32_t RESET_SYNDROME; + FWK_RW uint32_t WIC_CTRL; + FWK_R uint32_t WIC_STATUS; + uint8_t RESERVED1[0xA00 - 0x1C]; + FWK_R uint32_t CLKFORCE_STATUS; + FWK_RW uint32_t CLKFORCE_SET; + FWK_RW uint32_t CLKFORCE_CLR; + uint32_t RESERVED2; + FWK_R uint32_t PLL_STATUS0; + FWK_R uint32_t PLL_STATUS1; + uint8_t RESERVED3[0xFC0 - 0xA18]; + FWK_R uint32_t PIK_CONFIG; + uint32_t RESERVED4[3]; + FWK_R uint32_t PID4; + FWK_R uint32_t PID5; + FWK_R uint32_t PID6; + FWK_R uint32_t PID7; + FWK_R uint32_t PID0; + FWK_R uint32_t PID1; + FWK_R uint32_t PID2; + FWK_R uint32_t PID3; + FWK_R uint32_t ID0; + FWK_R uint32_t ID1; + FWK_R uint32_t ID2; + FWK_R uint32_t ID3; +}; + +#define PLL_STATUS0_REFCLK UINT32_C(0x00000001) +#define PLL_STATUS0_BCPUPLLLOCK UINT32_C(0x00000002) +#define PLL_STATUS0_LCPUPLLLOCK UINT32_C(0x00000004) +#define PLL_STATUS0_GPUPLLLOCK UINT32_C(0x00000008) +#define PLL_STATUS0_VIDEOPLLLOCK UINT32_C(0x00000010) +#define PLL_STATUS0_SYSPLLLOCK UINT32_C(0x00000020) +#define PLL_STATUS0_DISPLAYPLLLOCK UINT32_C(0x00000040) + +#define PLL_STATUS1_CPUPLLLOCK(CPU, PLL) \ + ((uint32_t)((1 << (PLL)) << ((CPU) * 8))) + +#define RESET_SYNDROME_PORESET UINT32_C(0x01) +#define RESET_SYNDROME_WDOGRESET_SCP UINT32_C(0x02) +#define RESET_SYNDROME_WDOGRESET_SYS UINT32_C(0x04) +#define RESET_SYNDROME_SYSRESETREQ UINT32_C(0x08) +#define RESET_SYNDROME_SCPM3LOCKUP UINT32_C(0x10) + +#endif /* FAKE_PIK_SCP_H */ diff --git a/product/vhost-user/include/fmw_io.h b/product/vhost-user/include/fmw_io.h new file mode 100644 index 0000000000000000000000000000000000000000..878f8eb7dd6dbfffde25a204e6a1e9f1e8d54101 --- /dev/null +++ b/product/vhost-user/include/fmw_io.h @@ -0,0 +1,18 @@ +/* + * 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_HOST_CONSOLE, 0) + +#endif /* FMW_IO_H */ diff --git a/product/vhost-user/include/fmw_log.h b/product/vhost-user/include/fmw_log.h new file mode 100644 index 0000000000000000000000000000000000000000..4e0bdd0ee4f2eb0b4f153112af3bd61e0599ebe4 --- /dev/null +++ b/product/vhost-user/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/vhost-user/include/scmi_agents.h b/product/vhost-user/include/scmi_agents.h new file mode 100644 index 0000000000000000000000000000000000000000..fe8b1202d8a676a4c7d3affaecfe3289f5d6e23d --- /dev/null +++ b/product/vhost-user/include/scmi_agents.h @@ -0,0 +1,38 @@ +/* + * 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 { + /* 0 is reserved for the platform */ + SCMI_AGENT_ID_OSPM = 1, + SCMI_AGENT_ID_PSCI, + SCMI_AGENT_ID_PERF, + SCMI_AGENT_ID_COUNT, +}; + +enum scmi_service_idx { + SCMI_SERVICE_IDX_PSCI, + SCMI_SERVICE_IDX_OSPM_0, + SCMI_SERVICE_IDX_OSPM_1, +#ifdef BUILD_HAS_SCMI_NOTIFICATIONS + SCMI_SERVICE_IDX_OSPM_0_P2A, + SCMI_SERVICE_IDX_OSPM_1_P2A, +#endif + SCMI_SERVICE_IDX_COUNT, +}; + +enum scmi_channel_device_idx { + // TODO: change this: current code support device#0 only + SCMI_CHANNEL_DEVICE_IDX_OSPM_0, + SCMI_CHANNEL_DEVICE_IDX_OSPM_1, + SCMI_CHANNEL_DEVICE_IDX_PSCI, + SCMI_CHANNEL_DEVICE_IDX_COUNT +}; + +#endif /* SCMI_AGENTS_H */ diff --git a/product/vhost-user/module/vppu/CMakeLists.txt b/product/vhost-user/module/vppu/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..c950cbd169b908d168db3b16a61bb6330c7a3a1d --- /dev/null +++ b/product/vhost-user/module/vppu/CMakeLists.txt @@ -0,0 +1,21 @@ +# +# Arm SCP/MCP Software +# Copyright (c) 2022, 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") + +target_sources( + ${SCP_MODULE_TARGET} PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/src/mod_ppu_v0.c" + "${CMAKE_CURRENT_SOURCE_DIR}/src/ppu_v0.c") + +target_link_libraries(${SCP_MODULE_TARGET} PRIVATE module-power-domain) + +if("system-power" IN_LIST SCP_MODULES) + target_link_libraries(${SCP_MODULE_TARGET} PRIVATE module-system-power) +endif() diff --git a/product/vhost-user/module/vppu/Module.cmake b/product/vhost-user/module/vppu/Module.cmake new file mode 100644 index 0000000000000000000000000000000000000000..558e7c273e6ea3e7691cf2a9f46d93d2a1caaf96 --- /dev/null +++ b/product/vhost-user/module/vppu/Module.cmake @@ -0,0 +1,9 @@ +# +# Arm SCP/MCP Software +# Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +set(SCP_MODULE "vppu") +set(SCP_MODULE_TARGET "module-vppu") diff --git a/product/vhost-user/module/vppu/include/mod_ppu_v0.h b/product/vhost-user/module/vppu/include/mod_ppu_v0.h new file mode 100644 index 0000000000000000000000000000000000000000..981562300741c866dcc45523eda4cd1027531df0 --- /dev/null +++ b/product/vhost-user/module/vppu/include/mod_ppu_v0.h @@ -0,0 +1,63 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Description: + * Virtual PPU v0 driver module + */ + +#ifndef MOD_PPU_V0_H +#define MOD_PPU_V0_H + +#include +#include +#include + +/*! + * \addtogroup GroupModules Modules + * @{ + */ + +/*! + * \defgroup GroupModulePPUv0 PPUv0 Driver + * @{ + */ + +/*! + * \brief Power domain PPU descriptor. + */ +struct mod_ppu_v0 { + /*! Base address of the PPU registers */ + uintptr_t reg_base; + + /*! PPU's IRQ number */ + unsigned int irq; +}; + +/*! + * \brief Configuration data of a power domain of the PPU_V0 driver module. + */ +struct mod_ppu_v0_pd_config { + /*! Power domain type */ + enum mod_pd_type pd_type; + + /*! PPU descriptor */ + struct mod_ppu_v0 ppu; + + /*! + * Flag indicating if this domain should be powered on during element init. + */ + bool default_power_on; +}; + +/*! + * @} + */ + +/*! + * @} + */ + +#endif /* MOD_PPU_V0_H */ diff --git a/product/vhost-user/module/vppu/src/mod_ppu_v0.c b/product/vhost-user/module/vppu/src/mod_ppu_v0.c new file mode 100644 index 0000000000000000000000000000000000000000..038a3760acf236f2543eb9aa03588a90901c6a90 --- /dev/null +++ b/product/vhost-user/module/vppu/src/mod_ppu_v0.c @@ -0,0 +1,306 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Description: + * Power State Management PPU v0 driver. + */ + +#include +#include +#include +#include +#include +#include +#include +#if BUILD_HAS_MOD_SYSTEM_POWER +#include +#endif +#include "ppu_v0.h" + +/* Power domain context */ +struct ppu_v0_pd_ctx { + /* Power domain configuration data */ + const struct mod_ppu_v0_pd_config *config; + + /* PPU registers */ + struct ppu_v0_reg *ppu; + + /* Identifier of the entity bound to the power domain driver API */ + fwk_id_t bound_id; + + /* Power module driver input API */ + struct mod_pd_driver_input_api *pd_driver_input_api; +}; + +/* Module context */ +struct ppu_v0_ctx { + /* Table of the power domain contexts */ + struct ppu_v0_pd_ctx *pd_ctx_table; +}; + +/* + * Internal variables + */ + +static struct ppu_v0_ctx ppu_v0_ctx; + +#define MODE_UNSUPPORTED ~0U +static const uint8_t ppu_mode_to_power_state[] = { + [PPU_V0_MODE_ON] = (uint8_t)MOD_PD_STATE_ON, + [PPU_V0_MODE_FUNC_RET] = (uint8_t)MOD_PD_STATE_ON, + [PPU_V0_MODE_MEM_OFF] = (uint8_t)MODE_UNSUPPORTED, + [PPU_V0_MODE_FULL_RET] = (uint8_t)MOD_PD_STATE_ON, + [PPU_V0_MODE_LOGIC_RET] = (uint8_t)MODE_UNSUPPORTED, + [PPU_V0_MODE_MEM_RET] = (uint8_t)MOD_PD_STATE_ON, + [PPU_V0_MODE_OFF] = (uint8_t)MOD_PD_STATE_OFF, + [PPU_V0_MODE_WARM_RESET] = (uint8_t)MODE_UNSUPPORTED, +}; + +/* + * Power domain driver interface + */ + +/* Driver functions not specific to any type of power domain. */ +static int get_state(struct ppu_v0_reg *ppu, unsigned int *state) +{ + enum ppu_v0_mode ppu_mode; + + /* Ensure ppu_mode_to_power_state has an entry for each PPU state */ + static_assert(FWK_ARRAY_SIZE(ppu_mode_to_power_state) == PPU_V0_MODE_COUNT, + "[MOD_PPU_V0] ppu_mode_to_power_state size error"); + + ppu_v0_get_power_mode(ppu, &ppu_mode); + assert(ppu_mode < PPU_V0_MODE_COUNT); + + *state = ppu_mode_to_power_state[ppu_mode]; + if (*state == MODE_UNSUPPORTED) { + FWK_LOG_ERR("[PD] Unexpected PPU mode (%i).\n", ppu_mode); + + return FWK_E_DEVICE; + } + + return FWK_SUCCESS; +} + +static int pd_init(struct ppu_v0_pd_ctx *pd_ctx) +{ + ppu_v0_init(pd_ctx->ppu); + + return FWK_SUCCESS; +} + +static int pd_set_state(fwk_id_t pd_id, unsigned int state) +{ + int status; + struct ppu_v0_pd_ctx *pd_ctx; + + pd_ctx = ppu_v0_ctx.pd_ctx_table + fwk_id_get_element_idx(pd_id); + + fwk_assert(pd_ctx->pd_driver_input_api != NULL); + + switch (state) { + case MOD_PD_STATE_ON: + ppu_v0_set_power_mode(pd_ctx->ppu, PPU_V0_MODE_ON); + status = pd_ctx->pd_driver_input_api->report_power_state_transition( + pd_ctx->bound_id, MOD_PD_STATE_ON); + assert(status == FWK_SUCCESS); + break; + + case MOD_PD_STATE_OFF: + ppu_v0_set_power_mode(pd_ctx->ppu, PPU_V0_MODE_OFF); + status = pd_ctx->pd_driver_input_api->report_power_state_transition( + pd_ctx->bound_id, MOD_PD_STATE_OFF); + assert(status == FWK_SUCCESS); + break; + + default: + FWK_LOG_ERR("[PD] Requested power state (%i) is not supported.\n", state); + return FWK_E_PARAM; + } + + if (status != FWK_SUCCESS) + return FWK_E_PANIC; + + return FWK_SUCCESS; +} + +static int pd_get_state(fwk_id_t pd_id, unsigned int *state) +{ + struct ppu_v0_pd_ctx *pd_ctx; + + pd_ctx = ppu_v0_ctx.pd_ctx_table + fwk_id_get_element_idx(pd_id); + + return get_state(pd_ctx->ppu, state); +} + +static int pd_reset(fwk_id_t pd_id) +{ + int status; + struct ppu_v0_pd_ctx *pd_ctx; + + pd_ctx = ppu_v0_ctx.pd_ctx_table + fwk_id_get_element_idx(pd_id); + + /* Model does not support warm reset at the moment. Using OFF instead. */ + status = ppu_v0_set_power_mode(pd_ctx->ppu, PPU_V0_MODE_OFF); + if (status == FWK_SUCCESS) + status = ppu_v0_set_power_mode(pd_ctx->ppu, PPU_V0_MODE_ON); + + return status; +} + +static int ppu_v0_prepare_core_for_system_suspend(fwk_id_t core_pd_id) +{ + return FWK_SUCCESS; +} + + +static const struct mod_pd_driver_api pd_driver = { + .set_state = pd_set_state, + .get_state = pd_get_state, + .reset = pd_reset, + .prepare_core_for_system_suspend = ppu_v0_prepare_core_for_system_suspend, +}; + +/* + * Framework handlers + */ + +static int ppu_v0_mod_init(fwk_id_t module_id, unsigned int pd_count, + const void *unused) +{ + ppu_v0_ctx.pd_ctx_table = fwk_mm_calloc(pd_count, + sizeof(struct ppu_v0_pd_ctx)); + if (ppu_v0_ctx.pd_ctx_table == NULL) + return FWK_E_NOMEM; + + return FWK_SUCCESS; +} + +static int ppu_v0_pd_init(fwk_id_t pd_id, unsigned int unused, const void *data) +{ + const struct mod_ppu_v0_pd_config *config = data; + struct ppu_v0_pd_ctx *pd_ctx; + int status; + + if (config->pd_type >= MOD_PD_TYPE_COUNT) + return FWK_E_DATA; + + pd_ctx = ppu_v0_ctx.pd_ctx_table + fwk_id_get_element_idx(pd_id); + pd_ctx->config = config; + pd_ctx->ppu = (struct ppu_v0_reg *)(config->ppu.reg_base); + pd_ctx->bound_id = FWK_ID_NONE; + + switch (config->pd_type) { + case MOD_PD_TYPE_DEVICE: + case MOD_PD_TYPE_DEVICE_DEBUG: + case MOD_PD_TYPE_SYSTEM: + status = pd_init(pd_ctx); + if (status != FWK_SUCCESS) + return status; + + if (config->default_power_on) + return ppu_v0_set_power_mode(pd_ctx->ppu, PPU_V0_MODE_ON); + + return FWK_SUCCESS; + + default: + return FWK_E_SUPPORT; + } +} + +static int ppu_v0_bind(fwk_id_t id, unsigned int round) +{ + struct ppu_v0_pd_ctx *pd_ctx; + + /* Nothing to do during the first round of calls where the power module + will bind to the power domains of this module. */ + if (round == 0) + return FWK_SUCCESS; + + /* In the case of the module, nothing to do */ + if (fwk_module_is_valid_module_id(id)) { + return FWK_SUCCESS; + } + + pd_ctx = ppu_v0_ctx.pd_ctx_table + fwk_id_get_element_idx(id); + + if (fwk_id_is_equal(pd_ctx->bound_id, FWK_ID_NONE)) + return FWK_SUCCESS; + + switch (fwk_id_get_module_idx(pd_ctx->bound_id)) { + #if BUILD_HAS_MOD_POWER_DOMAIN + case FWK_MODULE_IDX_POWER_DOMAIN: + return fwk_module_bind(pd_ctx->bound_id, + mod_pd_api_id_driver_input, + &pd_ctx->pd_driver_input_api); + break; + #endif + + #if BUILD_HAS_MOD_SYSTEM_POWER + case FWK_MODULE_IDX_SYSTEM_POWER: + return fwk_module_bind(pd_ctx->bound_id, + mod_system_power_api_id_pd_driver_input, + &pd_ctx->pd_driver_input_api); + break; + #endif + + default: + assert(false); + return FWK_E_SUPPORT; + } +} + +static int ppu_v0_process_bind_request(fwk_id_t source_id, + fwk_id_t target_id, fwk_id_t not_used, + const void **api) +{ + struct ppu_v0_pd_ctx *pd_ctx; + + pd_ctx = ppu_v0_ctx.pd_ctx_table + fwk_id_get_element_idx(target_id); + + switch (pd_ctx->config->pd_type) { + case MOD_PD_TYPE_SYSTEM: + if (!fwk_id_is_equal(pd_ctx->bound_id, FWK_ID_NONE)) { + assert(false); + return FWK_E_ACCESS; + } + /* Fallthrough */ + + case MOD_PD_TYPE_DEVICE: + case MOD_PD_TYPE_DEVICE_DEBUG: + #if BUILD_HAS_MOD_POWER_DOMAIN + if (fwk_id_get_module_idx(source_id) == FWK_MODULE_IDX_POWER_DOMAIN) { + pd_ctx->bound_id = source_id; + *api = &pd_driver; + break; + } + #endif + #if BUILD_HAS_MOD_SYSTEM_POWER + if (fwk_id_get_module_idx(source_id) == FWK_MODULE_IDX_SYSTEM_POWER) { + pd_ctx->bound_id = source_id; + *api = &pd_driver; + break; + } + #endif + assert(false); + return FWK_E_ACCESS; + + default: + (void)pd_driver; + return FWK_E_SUPPORT; + } + + return FWK_SUCCESS; +} + +const struct fwk_module module_vppu = { + .type = FWK_MODULE_TYPE_DRIVER, + .api_count = 1, + .init = ppu_v0_mod_init, + .element_init = ppu_v0_pd_init, + .bind = ppu_v0_bind, + .process_bind_request = ppu_v0_process_bind_request, +}; diff --git a/product/vhost-user/module/vppu/src/ppu_v0.c b/product/vhost-user/module/vppu/src/ppu_v0.c new file mode 100644 index 0000000000000000000000000000000000000000..5a19777a436df95fa8d8d1772d8d17715a594098 --- /dev/null +++ b/product/vhost-user/module/vppu/src/ppu_v0.c @@ -0,0 +1,65 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include "ppu_v0.h" + +void ppu_v0_init(struct ppu_v0_reg *ppu) +{ + assert(ppu != NULL); + + /* Set mode as masked to all input edge interrupts */ + ppu->IESR = 0; + + /* Mask all interrupts */ + ppu->IMR = PPU_V0_IMR_MASK; + + /* Acknowledge any interrupt left pending */ + ppu->ISR = PPU_V0_ISR_MASK; +} + +int ppu_v0_request_power_mode(struct ppu_v0_reg *ppu, enum ppu_v0_mode mode) +{ + uint32_t power_policy; + assert(ppu != NULL); + assert(mode < PPU_V0_MODE_COUNT); + + power_policy = ppu->POWER_POLICY & + ~(PPU_V0_PPR_POLICY | PPU_V0_PPR_DYNAMIC_EN); + ppu->POWER_POLICY = power_policy | mode; + ppu->POWER_STATUS = power_policy | mode; + + return FWK_SUCCESS; +} + +int ppu_v0_set_power_mode(struct ppu_v0_reg *ppu, enum ppu_v0_mode mode) +{ + int status; + assert(ppu != NULL); + + status = ppu_v0_request_power_mode(ppu, mode); + if (status != FWK_SUCCESS) + return status; + + while ((ppu->POWER_STATUS & (PPU_V0_PSR_POWSTAT | PPU_V0_PSR_DYNAMIC)) + != mode) + continue; + + return FWK_SUCCESS; +} + +int ppu_v0_get_power_mode(struct ppu_v0_reg *ppu, enum ppu_v0_mode *mode) +{ + assert(ppu != NULL); + assert(mode != NULL); + + *mode = (enum ppu_v0_mode)(ppu->POWER_STATUS & PPU_V0_PSR_POWSTAT); + + return FWK_SUCCESS; +} diff --git a/product/vhost-user/module/vppu/src/ppu_v0.h b/product/vhost-user/module/vppu/src/ppu_v0.h new file mode 100644 index 0000000000000000000000000000000000000000..fc7fe26b40f2883fdf49fa44f636711942b5bc6f --- /dev/null +++ b/product/vhost-user/module/vppu/src/ppu_v0.h @@ -0,0 +1,144 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PPU_V0_H +#define PPU_V0_H + +/*! + * \cond + * @{ + */ + +#include +#include +#include + +struct ppu_v0_reg { + FWK_RW uint32_t POWER_POLICY; + FWK_RW uint32_t POWER_STATUS; + FWK_R uint32_t STATIC_CFG_STATUS; + FWK_R uint32_t DEV_IF_IP_CUR_STATUS; + FWK_R uint32_t MISC_IP_CUR_STATUS; + FWK_R uint32_t STORED_STATUS; + FWK_W uint32_t OFF_MEM_RET_UNLOCK; + uint32_t RESERVED0; + FWK_RW uint32_t POWER_CFG; + uint32_t RESERVED1[3]; + FWK_RW uint32_t IMR; + FWK_RW uint32_t ISR; + FWK_RW uint32_t IESR; + uint32_t RESERVED2[5]; + FWK_RW uint32_t FUNC_RET_RAM_CFG; + FWK_RW uint32_t FULL_RET_RAM_CFG; + FWK_RW uint32_t MEM_RET_RAM_CFG; + uint32_t RESERVED3; + FWK_RW uint32_t MODE_ENTRY_DELAY_TIME_0; + FWK_RW uint32_t MODE_ENTRY_DELAY_TIME_1; + uint32_t RESERVED4[2]; + FWK_RW uint32_t DEV_CONTROL_DELAY_CFG_0; + FWK_RW uint32_t DEV_CONTROL_DELAY_CFG_1; + uint8_t RESERVED5[0xFC8 - 0x78]; + FWK_R uint32_t IMPLEMENTATION_ID; + FWK_R uint32_t ARCHITECTURE_ID; + FWK_R uint32_t PID4; + FWK_R uint32_t PID5; + FWK_R uint32_t PID6; + FWK_R uint32_t PID7; + FWK_R uint32_t PID0; + FWK_R uint32_t PID1; + FWK_R uint32_t PID2; + FWK_R uint32_t PID3; + FWK_R uint32_t CID0; + FWK_R uint32_t CID1; + FWK_R uint32_t CID2; + FWK_R uint32_t CID3; +}; + +enum ppu_v0_mode { + PPU_V0_MODE_OFF = 0, + PPU_V0_MODE_MEM_RET = 1, + PPU_V0_MODE_LOGIC_RET = 2, + PPU_V0_MODE_FULL_RET = 3, + PPU_V0_MODE_MEM_OFF = 4, + PPU_V0_MODE_FUNC_RET = 5, + PPU_V0_MODE_ON = 6, + PPU_V0_MODE_WARM_RESET = 7, + PPU_V0_MODE_COUNT, +}; + +/* + * Bit definitions for PPR + */ +#define PPU_V0_PPR_POLICY UINT32_C(0x00000007) +#define PPU_V0_PPR_DYNAMIC_EN UINT32_C(0x00000100) +#define PPU_V0_PPR_EMULATED_EN UINT32_C(0x00000200) +#define PPU_V0_PPR_OFF_LOCK_EN UINT32_C(0x00001000) + +/* + * Bit definitions for PSR + */ +#define PPU_V0_PSR_EMULATED UINT32_C(0x00000200) +#define PPU_V0_PSR_DYNAMIC UINT32_C(0x00000100) +#define PPU_V0_PSR_POWSTAT UINT32_C(0x00000007) + +/* + * Bit definitions for IMR + */ +#define PPU_V0_IMR_MASK UINT32_C(0x010000FF) +#define PPU_V0_IMR_STA_POLICY_TRN UINT32_C(0x00000001) +#define PPU_V0_IMR_STA_ACCEPT UINT32_C(0x00000002) +#define PPU_V0_IMR_STA_DENY UINT32_C(0x00000004) +#define PPU_V0_IMR_DYN_ACCEPT UINT32_C(0x00000008) +#define PPU_V0_IMR_DYN_DENY UINT32_C(0x00000010) +#define PPU_V0_IMR_EMU_ACCEPT UINT32_C(0x00000020) +#define PPU_V0_IMR_EMU_DENY UINT32_C(0x00000040) +#define PPU_V0_IMR_UNSPT_POLICY UINT32_C(0x00000080) +#define PPU_V0_IMR_DYN_POLICY_MIN UINT32_C(0x01000000) + +/* + * Bit definitions for ISR + */ +#define PPU_V0_ISR_MASK UINT32_C(0x01FF01FF) +#define PPU_V0_ISR_STA_POLICY_TRN UINT32_C(0x00000001) +#define PPU_V0_ISR_STA_ACCEPT UINT32_C(0x00000002) +#define PPU_V0_ISR_STA_DENY UINT32_C(0x00000004) +#define PPU_V0_ISR_DYN_ACCEPT UINT32_C(0x00000008) +#define PPU_V0_ISR_DYN_DENY UINT32_C(0x00000010) +#define PPU_V0_ISR_EMU_ACCEPT UINT32_C(0x00000020) +#define PPU_V0_ISR_EMU_DENY UINT32_C(0x00000040) +#define PPU_V0_ISR_UNSPT_POLICY UINT32_C(0x00000080) +#define PPU_V0_ISR_DBGEMUPWRDWN_EDGE UINT32_C(0x00000100) +#define PPU_V0_ISR_ACTIVE_EDGE UINT32_C(0x00FF0000) +#define PPU_V0_ISR_ACTIVE_EDGE_ACTIVE0 UINT32_C(0x00010000) +#define PPU_V0_ISR_ACTIVE_EDGE_ACTIVE1 UINT32_C(0x00020000) +#define PPU_V0_ISR_ACTIVE_EDGE_ACTIVE2 UINT32_C(0x00040000) +#define PPU_V0_ISR_ACTIVE_EDGE_ACTIVE3 UINT32_C(0x00080000) +#define PPU_V0_ISR_ACTIVE_EDGE_ACTIVE4 UINT32_C(0x00100000) +#define PPU_V0_ISR_ACTIVE_EDGE_ACTIVE5 UINT32_C(0x00200000) +#define PPU_V0_ISR_ACTIVE_EDGE_ACTIVE6 UINT32_C(0x00400000) +#define PPU_V0_ISR_ACTIVE_EDGE_ACTIVE7 UINT32_C(0x00800000) +#define PPU_V0_ISR_DYN_POLICY_MIN UINT32_C(0x01000000) + +/* + * Bit definitions for ARCHITECTURE_ID + */ +#define PPU_V0_ARCHITECTURE_ID UINT32_C(0x00000000) + +/* + * Interface + */ +void ppu_v0_init(struct ppu_v0_reg *ppu); +int ppu_v0_request_power_mode(struct ppu_v0_reg *ppu, enum ppu_v0_mode mode); +int ppu_v0_set_power_mode(struct ppu_v0_reg *ppu, enum ppu_v0_mode mode); +int ppu_v0_get_power_mode(struct ppu_v0_reg *ppu, enum ppu_v0_mode *mode); + +/*! + * \endcond + * @} + */ + +#endif /* PPU_V0_H */ diff --git a/product/virtio-zephyr/fw/CMakeLists.txt b/product/virtio-zephyr/fw/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..7cbb86c5fd10a907b4bded6e6a38b2150df92c6a --- /dev/null +++ b/product/virtio-zephyr/fw/CMakeLists.txt @@ -0,0 +1,36 @@ +# +# 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_mhu_smt.c" + "${CMAKE_CURRENT_SOURCE_DIR}/config_scmi.c" + "${CMAKE_CURRENT_SOURCE_DIR}/config_mock_clock.c" + "${CMAKE_CURRENT_SOURCE_DIR}/config_vpll.c" + "${CMAKE_CURRENT_SOURCE_DIR}/config_clock.c" + "${CMAKE_CURRENT_SOURCE_DIR}/config_scmi_clock.c" + "${CMAKE_CURRENT_SOURCE_DIR}/config_ppu_v0.c" + "${CMAKE_CURRENT_SOURCE_DIR}/config_power_domain.c" + "${CMAKE_CURRENT_SOURCE_DIR}/config_scmi_power_domain.c" + "${CMAKE_CURRENT_SOURCE_DIR}/config_mock_psu.c" + "${CMAKE_CURRENT_SOURCE_DIR}/config_psu.c" + "${CMAKE_CURRENT_SOURCE_DIR}/config_dvfs.c" + "${CMAKE_CURRENT_SOURCE_DIR}/config_scmi_perf.c" + "${CMAKE_CURRENT_SOURCE_DIR}/config_sensor.c") diff --git a/product/virtio-zephyr/fw/Firmware.cmake b/product/virtio-zephyr/fw/Firmware.cmake new file mode 100644 index 0000000000000000000000000000000000000000..f113a722b4b3395149eb7e00534a5cc2474ab35c --- /dev/null +++ b/product/virtio-zephyr/fw/Firmware.cmake @@ -0,0 +1,56 @@ +# +# 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 "zephyr-scmi") + +set(SCP_FIRMWARE_TARGET "zephyr-scmi") + +set(SCP_TOOLCHAIN_INIT "GNU") + +set(SCP_ARCHITECTURE "zephyr") + +#set(SCP_GENERATE_FLAT_BINARY_INIT FALSE) + +set(SCP_ENABLE_NOTIFICATIONS_INIT TRUE) + +set(SCP_ENABLE_SCMI_NOTIFICATIONS_INIT TRUE) + +set(SCP_ENABLE_SCMI_SENSOR_EVENTS_INIT TRUE) + +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/vppu") + +# 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 "vring-mhu") +list(APPEND SCP_MODULES "msg-smt") +list(APPEND SCP_MODULES "scmi") +list(APPEND SCP_MODULES "mock-clock") +list(APPEND SCP_MODULES "system-pll") +list(APPEND SCP_MODULES "clock") +list(APPEND SCP_MODULES "scmi-clock") +list(APPEND SCP_MODULES "vppu") +list(APPEND SCP_MODULES "power-domain") +list(APPEND SCP_MODULES "scmi-power-domain") +list(APPEND SCP_MODULES "mock-psu") +list(APPEND SCP_MODULES "psu") +list(APPEND SCP_MODULES "dvfs") +list(APPEND SCP_MODULES "scmi-perf") +list(APPEND SCP_MODULES "reg-sensor") +list(APPEND SCP_MODULES "sensor") +list(APPEND SCP_MODULES "scmi-sensor") diff --git a/product/virtio-zephyr/fw/Toolchain-GNU.cmake b/product/virtio-zephyr/fw/Toolchain-GNU.cmake new file mode 100644 index 0000000000000000000000000000000000000000..b2100cf6923f6aa89f77058eb809188d817d135e --- /dev/null +++ b/product/virtio-zephyr/fw/Toolchain-GNU.cmake @@ -0,0 +1,18 @@ +# +# 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 "cortex-m3") +set(CMAKE_TOOLCHAIN_PREFIX "arm-zephyr-eabi-") + +set(CMAKE_ASM_COMPILER_TARGET "arm-zephyr-eabi") +set(CMAKE_C_COMPILER_TARGET "arm-zephyr-eabi") +set(CMAKE_CXX_COMPILER_TARGET "arm-zephyr-eabi") + +include( + "${CMAKE_CURRENT_LIST_DIR}/../../../cmake/Toolchain/GNU-Baremetal.cmake") diff --git a/product/virtio-zephyr/fw/clock_devices.h b/product/virtio-zephyr/fw/clock_devices.h new file mode 100644 index 0000000000000000000000000000000000000000..df71204a250dac02a845a116f079fe2262a85b2f --- /dev/null +++ b/product/virtio-zephyr/fw/clock_devices.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 CLOCK_DEVICES_H +#define CLOCK_DEVICES_H + +/*! + * \brief Clock device indexes. + */ +enum clock_dev_idx { + CLOCK_DEV_IDX_BIG, + CLOCK_DEV_IDX_LITTLE, + CLOCK_DEV_IDX_GPU, + CLOCK_DEV_IDX_VPU, + CLOCK_DEV_IDX_DPU, + CLOCK_DEV_IDX_PIXEL_0, + CLOCK_DEV_IDX_PIXEL_1, + CLOCK_DEV_IDX_MOCK_0, + CLOCK_DEV_IDX_MOCK_1, + CLOCK_DEV_IDX_MOCK_2, + CLOCK_DEV_IDX_MOCK_3, + CLOCK_DEV_IDX_COUNT +}; + +#endif /* CLOCK_DEVICES_H */ diff --git a/product/virtio-zephyr/fw/config_clock.c b/product/virtio-zephyr/fw/config_clock.c new file mode 100644 index 0000000000000000000000000000000000000000..103fbb09639be361554a42729df0c0f2b4696790 --- /dev/null +++ b/product/virtio-zephyr/fw/config_clock.c @@ -0,0 +1,127 @@ +/* + * 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 "clock_devices.h" + +static struct fwk_element clock_dev_desc_table[] = { + [CLOCK_DEV_IDX_BIG] = { + .name = "CPU_GROUP_BIG", + .data = &((struct mod_clock_dev_config) { + .driver_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_SYSTEM_PLL, 0), + .api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_SYSTEM_PLL, + MOD_SYSTEM_PLL_API_TYPE_DEFAULT), + }), + }, + [CLOCK_DEV_IDX_LITTLE] = { + .name = "CPU_GROUP_LITTLE", + .data = &((struct mod_clock_dev_config) { + .driver_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_SYSTEM_PLL, 1), + .api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_SYSTEM_PLL, + MOD_SYSTEM_PLL_API_TYPE_DEFAULT), + }), + }, + [CLOCK_DEV_IDX_GPU] = { + .name = "GPU", + .data = &((struct mod_clock_dev_config) { + .driver_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_SYSTEM_PLL, 2), + .api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_SYSTEM_PLL, + MOD_SYSTEM_PLL_API_TYPE_DEFAULT), + }), + }, + [CLOCK_DEV_IDX_VPU] = { + .name = "VPU", + .data = &((struct mod_clock_dev_config) { + .driver_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_SYSTEM_PLL, 3), + .api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_SYSTEM_PLL, + MOD_SYSTEM_PLL_API_TYPE_DEFAULT), + }), + }, + [CLOCK_DEV_IDX_DPU] = { + .name = "DPU", + .data = &((struct mod_clock_dev_config) { + .driver_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_SYSTEM_PLL, 4), + .api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_SYSTEM_PLL, + MOD_SYSTEM_PLL_API_TYPE_DEFAULT), + }), + }, + [CLOCK_DEV_IDX_PIXEL_0] = { + .name = "PIXEL_0", + .data = &((struct mod_clock_dev_config) { + .driver_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_SYSTEM_PLL, 5), + .api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_SYSTEM_PLL, + MOD_SYSTEM_PLL_API_TYPE_DEFAULT), + }), + }, + [CLOCK_DEV_IDX_PIXEL_1] = { + .name = "PIXEL_1", + .data = &((struct mod_clock_dev_config) { + .driver_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_SYSTEM_PLL, 6), + .api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_SYSTEM_PLL, + MOD_SYSTEM_PLL_API_TYPE_DEFAULT), + }), + }, + [CLOCK_DEV_IDX_MOCK_0] = { + .name = "CLOCK_0", + .data = &((struct mod_clock_dev_config) { + .driver_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_MOCK_CLOCK, 0), + .api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_MOCK_CLOCK, + MOD_MOCK_CLOCK_API_TYPE_DRIVER), + }), + }, + [CLOCK_DEV_IDX_MOCK_1] = { + .name = "CLOCK_1", + .data = &((struct mod_clock_dev_config) { + .driver_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_MOCK_CLOCK, 1), + .api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_MOCK_CLOCK, + MOD_MOCK_CLOCK_API_TYPE_DRIVER), + }), + }, + [CLOCK_DEV_IDX_MOCK_2] = { + .name = "CLOCK_2", + .data = &((struct mod_clock_dev_config) { + .driver_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_MOCK_CLOCK, 2), + .api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_MOCK_CLOCK, + MOD_MOCK_CLOCK_API_TYPE_DRIVER), + }), + }, + [CLOCK_DEV_IDX_MOCK_3] = { + .name = "CLOCK_3", + .data = &((struct mod_clock_dev_config) { + .driver_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_MOCK_CLOCK, 3), + .api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_MOCK_CLOCK, + MOD_MOCK_CLOCK_API_TYPE_DRIVER), + }), + }, + [CLOCK_DEV_IDX_COUNT] = { 0 }, /* Termination description. */ +}; + +static const struct fwk_element *clock_get_dev_desc_table(fwk_id_t module_id) +{ + unsigned int i; + struct mod_clock_dev_config *dev_config; + + /* Configure all clocks to respond to changes in SYSTOP power state */ + for (i = 0; i < CLOCK_DEV_IDX_COUNT; i++) { + dev_config = + (struct mod_clock_dev_config *)clock_dev_desc_table[i].data; + dev_config->pd_source_id = FWK_ID_NONE; + } + return clock_dev_desc_table; +} + +struct fwk_module_config config_clock = { + .data = &((struct mod_clock_config){ + .pd_transition_notification_id = FWK_ID_NONE_INIT, + .pd_pre_transition_notification_id = FWK_ID_NONE_INIT, + }), + .elements = FWK_MODULE_DYNAMIC_ELEMENTS(clock_get_dev_desc_table), +}; diff --git a/product/virtio-zephyr/fw/config_dvfs.c b/product/virtio-zephyr/fw/config_dvfs.c new file mode 100644 index 0000000000000000000000000000000000000000..12867173043e0b4071db8040944b9f79ae852f86 --- /dev/null +++ b/product/virtio-zephyr/fw/config_dvfs.c @@ -0,0 +1,152 @@ +/* + * 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 "config_dvfs.h" + +static const struct mod_dvfs_domain_config cpu_group_little = { + .psu_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_PSU, 0), + .clock_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_CLOCK, 0), + .latency = 1200, + .sustained_idx = 2, + .opps = (struct mod_dvfs_opp[]) { + { + .level = 665 * 1000UL, + .frequency = 665 * 1000UL, + .voltage = 100, + .power = 665*100*100/10000, + }, + { + .level = 998 * 1000UL, + .frequency = 998 * 1000UL, + .voltage = 110, + .power = 998*110*110/10000, + }, + { + .level = 1330 * 1000UL, + .frequency = 1330 * 1000UL, + .voltage = 120, + .power = 1330*120*120/10000, + }, + { + .level = 1463 * 1000UL, + .frequency = 1463 * 1000UL, + .voltage = 130, + .power = 1463*130*130/10000, + }, + { + .level = 1596 * 1000UL, + .frequency = 1596 * 1000UL, + .voltage = 140, + .power = 1596*140*140/10000, + }, + { 0 } + } +}; + +static const struct mod_dvfs_domain_config cpu_group_big = { + .psu_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_PSU, 1), + .clock_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_CLOCK, 1), + .latency = 1200, + .sustained_idx = 2, + .opps = (struct mod_dvfs_opp[]) { + { + .level = 1313 * 1000UL, + .frequency = 1313 * 1000UL , + .voltage = 100, + .power = 1313, + }, + { + .level = 1531 * 1000UL, + .frequency = 1531 * 1000UL, + .voltage = 200, + .power = 1531, + }, + { + .level = 1750 * 1000UL, + .frequency = 1750 * 1000UL, + .voltage = 300, + .power = 1750, + }, + { + .level = 2100 * 1000UL, + .frequency = 2100 * 1000UL, + .voltage = 400, + .power = 2100, + }, + { + .level = 2450 * 1000UL, + .frequency = 2450 * 1000UL, + .voltage = 500, + .power = 2450, + }, + { 0 } + } +}; + +static const struct mod_dvfs_domain_config gpu = { + .psu_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_PSU, 2), + .clock_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_CLOCK, 2), + .latency = 1200, + .sustained_idx = 4, + .opps = (struct mod_dvfs_opp[]) { + { + .level = 450 * 1000UL, + .frequency = 450 * 1000UL, + .voltage = 100, + }, + { + .level = 487500, + .frequency = 487500, + .voltage = 200, + }, + { + .level = 525 * 1000UL, + .frequency = 525 * 1000UL, + .voltage = 300, + }, + { + .level = 562500 * 1000UL, + .frequency = 562500, + .voltage = 400, + }, + { + .level = 600 * 1000UL, + .frequency = 600 * 1000UL, + .voltage = 500, + }, + { 0 } + } +}; + +static const struct fwk_element element_table[] = { + [DVFS_ELEMENT_IDX_LITTLE] = { + .name = "CPU_GROUP_LITTLE", + .data = &cpu_group_little, + }, + [DVFS_ELEMENT_IDX_BIG] = { + .name = "CPU_GROUP_BIG", + .data = &cpu_group_big, + }, + [DVFS_ELEMENT_IDX_GPU] = { + .name = "GPU", + .data = &gpu, + }, + { 0 } +}; + +static const struct fwk_element *dvfs_get_element_table(fwk_id_t module_id) +{ + return element_table; +} + +struct fwk_module_config config_dvfs = { + .elements = FWK_MODULE_DYNAMIC_ELEMENTS(dvfs_get_element_table), +}; diff --git a/product/virtio-zephyr/fw/config_dvfs.h b/product/virtio-zephyr/fw/config_dvfs.h new file mode 100644 index 0000000000000000000000000000000000000000..2913c1060d92e9dc24b84420144d50c55ec6c1f3 --- /dev/null +++ b/product/virtio-zephyr/fw/config_dvfs.h @@ -0,0 +1,18 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CONFIG_DVFS_H +#define CONFIG_DVFS_H + +enum dvfs_element_idx { + DVFS_ELEMENT_IDX_LITTLE, + DVFS_ELEMENT_IDX_BIG, + DVFS_ELEMENT_IDX_GPU, + DVFS_ELEMENT_IDX_COUNT +}; + +#endif /* CONFIG_DVFS_H */ diff --git a/product/virtio-zephyr/fw/config_mhu_smt.c b/product/virtio-zephyr/fw/config_mhu_smt.c new file mode 100644 index 0000000000000000000000000000000000000000..755855d6e7452003f4716685b47cbb8ba26ba5f3 --- /dev/null +++ b/product/virtio-zephyr/fw/config_mhu_smt.c @@ -0,0 +1,116 @@ +/* + * 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 + +static const struct fwk_element mhu_element_table[] = { + [SCMI_CHANNEL_DEVICE_IDX_PSCI] = { + .name = "virqueue for PSCI", + .sub_element_count = 1, + .data = &((struct mod_vring_mhu_channel_config) { + .device_label = NULL, + .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_MSG_SMT, + MOD_MSG_SMT_API_IDX_DRIVER_INPUT), + }) + }, + [SCMI_CHANNEL_DEVICE_IDX_OSPM_0] = { + .name = "virqueue for OSPM #0", + .sub_element_count = 2, + .data = &((struct mod_vring_mhu_channel_config) { + .device_label = DT_LABEL(DT_INST(0, virtio_mmio)), + .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_MSG_SMT, + MOD_MSG_SMT_API_IDX_DRIVER_INPUT), + }) + }, + [SCMI_CHANNEL_DEVICE_IDX_OSPM_1] = { + .name = "virqueue for OSPM #1", + .sub_element_count = 2, + .data = &((struct mod_vring_mhu_channel_config) { + .device_label = DT_LABEL(DT_INST(1, virtio_mmio)), + .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_MSG_SMT, + MOD_MSG_SMT_API_IDX_DRIVER_INPUT), + }) + }, + [SCMI_CHANNEL_DEVICE_IDX_COUNT] = { 0 }, +}; + +static const struct fwk_element *mhu_get_element_table(fwk_id_t module_id) +{ + return (const struct fwk_element *)mhu_element_table; +} + +struct fwk_module_config config_vring_mhu = { + .elements = FWK_MODULE_DYNAMIC_ELEMENTS(mhu_get_element_table), +}; + +static struct fwk_element smt_element_table[] = { + [SCMI_SERVICE_IDX_PSCI] = { + .name = "PSCI", + .data = &((struct mod_msg_smt_channel_config) { + .type = MOD_MSG_SMT_CHANNEL_TYPE_REQUESTER, + .driver_id = FWK_ID_SUB_ELEMENT_INIT(FWK_MODULE_IDX_VRING_MHU, + SCMI_CHANNEL_DEVICE_IDX_PSCI, 0), + .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_VRING_MHU, 0), + }) + }, + [SCMI_SERVICE_IDX_OSPM_0] = { + .name = "OSPM0", + .data = &((struct mod_msg_smt_channel_config) { + .type = MOD_MSG_SMT_CHANNEL_TYPE_REQUESTER, + .driver_id = FWK_ID_SUB_ELEMENT_INIT(FWK_MODULE_IDX_VRING_MHU, + SCMI_CHANNEL_DEVICE_IDX_OSPM_0, 0), + .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_VRING_MHU, 0), + }) + }, + [SCMI_SERVICE_IDX_OSPM_1] = { + .name = "OSPM1", + .data = &((struct mod_msg_smt_channel_config) { + .type = MOD_MSG_SMT_CHANNEL_TYPE_REQUESTER, + .driver_id = FWK_ID_SUB_ELEMENT_INIT(FWK_MODULE_IDX_VRING_MHU, + SCMI_CHANNEL_DEVICE_IDX_OSPM_1, 0), + .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_VRING_MHU, 0), + }) + }, +#ifdef BUILD_HAS_SCMI_NOTIFICATIONS + [SCMI_SERVICE_IDX_OSPM_0_P2A] = { + .name = "OSPM0 P2A", + .data = &((struct mod_msg_smt_channel_config) { + .type = MOD_MSG_SMT_CHANNEL_TYPE_COMPLETER, + .driver_id = FWK_ID_SUB_ELEMENT_INIT(FWK_MODULE_IDX_VRING_MHU, + SCMI_CHANNEL_DEVICE_IDX_OSPM_0, 1), + .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_VRING_MHU, 0), + }) + }, + [SCMI_SERVICE_IDX_OSPM_1_P2A] = { + .name = "OSPM1 P2A", + .data = &((struct mod_msg_smt_channel_config) { + .type = MOD_MSG_SMT_CHANNEL_TYPE_COMPLETER, + .driver_id = FWK_ID_SUB_ELEMENT_INIT(FWK_MODULE_IDX_VRING_MHU, + SCMI_CHANNEL_DEVICE_IDX_OSPM_1, 1), + .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_VRING_MHU, 0), + }) + }, +#endif + [SCMI_SERVICE_IDX_COUNT] = { 0 }, +}; + +static const struct fwk_element *smt_get_element_table(fwk_id_t module_id) +{ + return (const struct fwk_element *)smt_element_table; +} + +struct fwk_module_config config_msg_smt = { + .elements = FWK_MODULE_DYNAMIC_ELEMENTS(smt_get_element_table), +}; diff --git a/product/virtio-zephyr/fw/config_mock_clock.c b/product/virtio-zephyr/fw/config_mock_clock.c new file mode 100644 index 0000000000000000000000000000000000000000..5b64c9585051ffb4d07ef4da9ca0b5123f79337a --- /dev/null +++ b/product/virtio-zephyr/fw/config_mock_clock.c @@ -0,0 +1,78 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include "config_mock_clock.h" + + +static const struct mod_mock_clock_rate clk0_rate_table[] = { + { .rate = 1536000 }, { .rate = 2116800 }, { .rate = 2304000 }, + { .rate = 4233600 }, { .rate = 4608000 }, { .rate = 8467200 }, + { .rate = 9216000 }, +}; + +static const struct mod_mock_clock_rate clk1_rate_table[] = { + { .rate = 2116800 }, +}; + +static const struct mod_mock_clock_rate clk2_rate_table[] = { + { .rate = 2304000 }, +}; + +static const struct mod_mock_clock_rate clk3_rate_table[] = { + { .rate = 4233600 }, +}; + +static const struct fwk_element element_table[] = { + [MOD_MOCK_CLOCK_ELEMENT_IDX_0] = + { + .name = "MOCK_CLK0", + .data = &(const struct mod_mock_clock_element_cfg){ + .rate_table = clk0_rate_table, + .rate_count = FWK_ARRAY_SIZE(clk0_rate_table), + .default_rate = 1536000, + }, + }, + [MOD_MOCK_CLOCK_ELEMENT_IDX_1] = + { + .name = "MOCK_CLK1", + .data = &(const struct mod_mock_clock_element_cfg){ + .rate_table = clk1_rate_table, + .rate_count = FWK_ARRAY_SIZE(clk1_rate_table), + .default_rate = 2116800, + }, + }, + [MOD_MOCK_CLOCK_ELEMENT_IDX_2] = + { + .name = "MOCK_CLK2", + .data = &(const struct mod_mock_clock_element_cfg){ + .rate_table = clk2_rate_table, + .rate_count = FWK_ARRAY_SIZE(clk2_rate_table), + .default_rate = 2304000, + }, + }, + [MOD_MOCK_CLOCK_ELEMENT_IDX_3] = + { + .name = "MOCK_CLK3", + .data = &(const struct mod_mock_clock_element_cfg){ + .rate_table = clk3_rate_table, + .rate_count = FWK_ARRAY_SIZE(clk3_rate_table), + .default_rate = 4233600, + }, + }, + [MOD_MOCK_CLOCK_ELEMENT_IDX_COUNT] = { 0 }, /* Termination description. */ +}; + +static const struct fwk_element *get_element_table(fwk_id_t module_id) +{ + return element_table; +} + +struct fwk_module_config config_mock_clock = { + .elements = FWK_MODULE_DYNAMIC_ELEMENTS(get_element_table), +}; diff --git a/product/virtio-zephyr/fw/config_mock_clock.h b/product/virtio-zephyr/fw/config_mock_clock.h new file mode 100644 index 0000000000000000000000000000000000000000..114f0e00f59d17b9d8fa5177237dadbdec790ceb --- /dev/null +++ b/product/virtio-zephyr/fw/config_mock_clock.h @@ -0,0 +1,20 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CONFIG_MOCK_CLOCK_H +#define CONFIG_MOCK_CLOCK_H + +/* Mock clock element indices for Juno */ +enum mod_mock_clock_element_idx { + MOD_MOCK_CLOCK_ELEMENT_IDX_0, + MOD_MOCK_CLOCK_ELEMENT_IDX_1, + MOD_MOCK_CLOCK_ELEMENT_IDX_2, + MOD_MOCK_CLOCK_ELEMENT_IDX_3, + MOD_MOCK_CLOCK_ELEMENT_IDX_COUNT, +}; + +#endif /* CONFIG_MOCK_CLOCK_H */ diff --git a/product/virtio-zephyr/fw/config_mock_psu.c b/product/virtio-zephyr/fw/config_mock_psu.c new file mode 100644 index 0000000000000000000000000000000000000000..efdc94cbb4e733046ee5b542efae7085f402023e --- /dev/null +++ b/product/virtio-zephyr/fw/config_mock_psu.c @@ -0,0 +1,55 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include "config_mock_psu.h" + +static const struct fwk_element element_table[] = { + [CONFIG_MOCK_PSU_ELEMENT_IDX_CPU_GROUP_LITTLE] = { + .name = "CPU_GROUP_LITTLE", + .data = &(const struct mod_mock_psu_element_cfg) { + .default_enabled = true, + .default_voltage = 100, + .async_alarm_id = FWK_ID_NONE_INIT, + }, + }, + [CONFIG_MOCK_PSU_ELEMENT_IDX_CPU_GROUP_BIG] = { + .name = "CPU_GROUP_BIG", + .data = &(const struct mod_mock_psu_element_cfg) { + .default_enabled = true, + .default_voltage = 100, + .async_alarm_id = FWK_ID_NONE_INIT, + }, + }, + [CONFIG_MOCK_PSU_ELEMENT_IDX_GPU] = { + .name = "GPU", + .data = &(const struct mod_mock_psu_element_cfg) { + .default_enabled = true, + .default_voltage = 100, + .async_alarm_id = FWK_ID_NONE_INIT, + }, + }, + [CONFIG_MOCK_PSU_ELEMENT_IDX_VPU] = { + .name = "VPU", + .data = &(const struct mod_mock_psu_element_cfg) { + .default_enabled = true, + .default_voltage = 100, + .async_alarm_id = FWK_ID_NONE_INIT, + }, + }, + { 0 } +}; + +static const struct fwk_element *get_element_table(fwk_id_t module_id) +{ + return element_table; +} + +struct fwk_module_config config_mock_psu = { + .elements = FWK_MODULE_DYNAMIC_ELEMENTS(get_element_table), +}; diff --git a/product/virtio-zephyr/fw/config_mock_psu.h b/product/virtio-zephyr/fw/config_mock_psu.h new file mode 100644 index 0000000000000000000000000000000000000000..74476bb4585bcae08e85f86fcb538bab8d213fc3 --- /dev/null +++ b/product/virtio-zephyr/fw/config_mock_psu.h @@ -0,0 +1,19 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CONFIG_MOCK_PSU_H +#define CONFIG_MOCK_PSU_H + +enum config_mock_psu_element_idx { + CONFIG_MOCK_PSU_ELEMENT_IDX_CPU_GROUP_LITTLE, + CONFIG_MOCK_PSU_ELEMENT_IDX_CPU_GROUP_BIG, + CONFIG_MOCK_PSU_ELEMENT_IDX_GPU, + CONFIG_MOCK_PSU_ELEMENT_IDX_VPU, + CONFIG_MOCK_PSU_ELEMENT_IDX_COUNT, +}; + +#endif /* CONFIG_MOCK_PSU_H */ diff --git a/product/virtio-zephyr/fw/config_power_domain.c b/product/virtio-zephyr/fw/config_power_domain.c new file mode 100644 index 0000000000000000000000000000000000000000..eb5abb64bf4dd9e70cb4f0eb126cdb6d747e74d3 --- /dev/null +++ b/product/virtio-zephyr/fw/config_power_domain.c @@ -0,0 +1,153 @@ +/* + * 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 "config_power_domain.h" +#include "config_ppu_v0.h" + +/* + * Mask of the allowed states for the top level power domains + * (but the cluster power domains) depending on the system states. + */ +static const uint32_t toplevel_allowed_state_mask_table[] = { + [MOD_PD_STATE_OFF] = MOD_PD_STATE_OFF_MASK, + [MOD_PD_STATE_ON] = MOD_PD_STATE_OFF_MASK | MOD_PD_STATE_ON_MASK, +}; + +/* + * Mask of the allowed states for the cluster power domain depending on the + * system states. + * + * While the clusters may reach a SLEEP state, SLEEP does not appear in this + * table. This is because the PPU driver backing the clusters will not accept a + * manual SLEEP request, but will transition to it automatically when possible. + */ +static const uint32_t cluster_pd_allowed_state_mask_table[] = { + [MOD_PD_STATE_OFF] = MOD_PD_STATE_OFF_MASK, + [MOD_PD_STATE_ON] = MOD_PD_STATE_OFF_MASK | MOD_PD_STATE_ON_MASK, +}; + +/* Mask of the allowed states for a core depending on the cluster states. */ +static const uint32_t core_pd_allowed_state_mask_table[] = { + [MOD_PD_STATE_OFF] = MOD_PD_STATE_OFF_MASK, + [MOD_PD_STATE_ON] = MOD_PD_STATE_OFF_MASK | MOD_PD_STATE_ON_MASK | + MOD_PD_STATE_SLEEP_MASK, + [MOD_PD_STATE_SLEEP] = MOD_PD_STATE_OFF_MASK | MOD_PD_STATE_SLEEP_MASK, +}; + +/* Power module specific configuration data (none) */ +static const struct mod_power_domain_config fvp_power_domain_config = { 0 }; + +static struct fwk_element fvp_power_domain_static_element_table[] = { + [CONFIG_POWER_DOMAIN_SYSTOP_CHILD_DBGTOP] = { + .name = "DBGTOP", + .data = &((struct mod_power_domain_element_config) { + .attributes.pd_type = MOD_PD_TYPE_DEVICE_DEBUG, + .driver_id = FWK_ID_ELEMENT_INIT( + FWK_MODULE_IDX_VPPU, PPU_V0_ELEMENT_IDX_DBGTOP), + .api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_VPPU, 0), + .allowed_state_mask_table = toplevel_allowed_state_mask_table, + .allowed_state_mask_table_size = + FWK_ARRAY_SIZE(toplevel_allowed_state_mask_table) + }), + }, + [CONFIG_POWER_DOMAIN_SYSTOP_CHILD_DPU0TOP] = { + .name = "DPU0TOP", + .data = &((struct mod_power_domain_element_config) { + .attributes.pd_type = MOD_PD_TYPE_DEVICE, + .driver_id = FWK_ID_ELEMENT_INIT( + FWK_MODULE_IDX_VPPU, PPU_V0_ELEMENT_IDX_DPU0TOP), + .api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_VPPU, 0), + .allowed_state_mask_table = toplevel_allowed_state_mask_table, + .allowed_state_mask_table_size = + FWK_ARRAY_SIZE(toplevel_allowed_state_mask_table) + }), + }, + [CONFIG_POWER_DOMAIN_SYSTOP_CHILD_DPU1TOP] = { + .name = "DPU1TOP", + .data = &((struct mod_power_domain_element_config) { + .attributes.pd_type = MOD_PD_TYPE_DEVICE, + .driver_id = FWK_ID_ELEMENT_INIT( + FWK_MODULE_IDX_VPPU, PPU_V0_ELEMENT_IDX_DPU1TOP), + .api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_VPPU, 0), + .allowed_state_mask_table = toplevel_allowed_state_mask_table, + .allowed_state_mask_table_size = + FWK_ARRAY_SIZE(toplevel_allowed_state_mask_table) + }), + }, + [CONFIG_POWER_DOMAIN_SYSTOP_CHILD_GPUTOP] = { + .name = "GPUTOP", + .data = &((struct mod_power_domain_element_config) { + .attributes.pd_type = MOD_PD_TYPE_DEVICE, + .driver_id = FWK_ID_ELEMENT_INIT( + FWK_MODULE_IDX_VPPU, PPU_V0_ELEMENT_IDX_GPUTOP), + .api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_VPPU, 0), + .allowed_state_mask_table = toplevel_allowed_state_mask_table, + .allowed_state_mask_table_size = + FWK_ARRAY_SIZE(toplevel_allowed_state_mask_table) + }), + }, + [CONFIG_POWER_DOMAIN_SYSTOP_CHILD_VPUTOP] = { + .name = "VPUTOP", + .data = &((struct mod_power_domain_element_config) { + .attributes.pd_type = MOD_PD_TYPE_DEVICE, + .driver_id = FWK_ID_ELEMENT_INIT( + FWK_MODULE_IDX_VPPU, PPU_V0_ELEMENT_IDX_VPUTOP), + .api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_VPPU, 0), + .allowed_state_mask_table = toplevel_allowed_state_mask_table, + .allowed_state_mask_table_size = + FWK_ARRAY_SIZE(toplevel_allowed_state_mask_table) + }), + }, + [CONFIG_POWER_DOMAIN_SYSTOP_CHILD_COUNT] = { + .name = "SYSTOP", + .data = &((struct mod_power_domain_element_config) { + .parent_idx = UINT32_MAX, + .attributes.pd_type = MOD_PD_TYPE_DEVICE, + .driver_id = FWK_ID_ELEMENT_INIT( + FWK_MODULE_IDX_VPPU, PPU_V0_ELEMENT_IDX_SYSTEM), + .api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_VPPU, 0), + .allowed_state_mask_table = toplevel_allowed_state_mask_table, + .allowed_state_mask_table_size = + FWK_ARRAY_SIZE(toplevel_allowed_state_mask_table) + }), + }, +}; + +/* + * Function definitions with internal linkage + */ +static const struct fwk_element *fvp_power_domain_get_element_table + (fwk_id_t module_id) +{ + const struct fwk_element *element_table; + + element_table = create_power_domain_element_table( + 4, + 2, + FWK_MODULE_IDX_VPPU, + 0, + core_pd_allowed_state_mask_table, + FWK_ARRAY_SIZE(core_pd_allowed_state_mask_table), + cluster_pd_allowed_state_mask_table, + FWK_ARRAY_SIZE(cluster_pd_allowed_state_mask_table), + fvp_power_domain_static_element_table, + FWK_ARRAY_SIZE(fvp_power_domain_static_element_table)); + + return element_table; +} + +/* + * Power module configuration data + */ +struct fwk_module_config config_power_domain = { + .data = &fvp_power_domain_config, + .elements = FWK_MODULE_DYNAMIC_ELEMENTS(fvp_power_domain_get_element_table), +}; diff --git a/product/virtio-zephyr/fw/config_power_domain.h b/product/virtio-zephyr/fw/config_power_domain.h new file mode 100644 index 0000000000000000000000000000000000000000..d3a1d91430b89ed48e11bd0e3d2d56e69534cd9f --- /dev/null +++ b/product/virtio-zephyr/fw/config_power_domain.h @@ -0,0 +1,20 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CONFIG_POWER_DOMAIN_H +#define CONFIG_POWER_DOMAIN_H + +enum systop_child_index { + CONFIG_POWER_DOMAIN_SYSTOP_CHILD_DBGTOP, + CONFIG_POWER_DOMAIN_SYSTOP_CHILD_DPU0TOP, + CONFIG_POWER_DOMAIN_SYSTOP_CHILD_DPU1TOP, + CONFIG_POWER_DOMAIN_SYSTOP_CHILD_GPUTOP, + CONFIG_POWER_DOMAIN_SYSTOP_CHILD_VPUTOP, + CONFIG_POWER_DOMAIN_SYSTOP_CHILD_COUNT +}; + +#endif /* CONFIG_POWER_DOMAIN_H */ diff --git a/product/virtio-zephyr/fw/config_ppu_v0.c b/product/virtio-zephyr/fw/config_ppu_v0.c new file mode 100644 index 0000000000000000000000000000000000000000..6ad6117db7d926b4d87207274dc35197d859d00b --- /dev/null +++ b/product/virtio-zephyr/fw/config_ppu_v0.c @@ -0,0 +1,156 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include "config_ppu_v0.h" + +uint32_t vppu_regdbg[16]; +uint32_t vppu_regdpu0[16]; +uint32_t vppu_regdpu1[16]; +uint32_t vppu_reggpu[16]; +uint32_t vppu_regvpu[16]; +uint32_t vppu_regsys0[16]; +uint32_t vppu_regsys1[16]; +uint32_t vppu_regcluster[16]; +uint32_t vppu_regsys[16]; + +static struct fwk_element host_ppu_v0_element_table[] = { + [PPU_V0_ELEMENT_IDX_CPU0] = { + .name = "CPU0", + .data = &((struct mod_ppu_v0_pd_config) { + .pd_type = MOD_PD_TYPE_DEVICE, + .ppu.reg_base = (uintptr_t)vppu_regcluster, + .ppu.irq = PPU_SYS1_IRQ + }), + }, + [PPU_V0_ELEMENT_IDX_CPU1] = { + .name = "CPU1", + .data = &((struct mod_ppu_v0_pd_config) { + .pd_type = MOD_PD_TYPE_DEVICE, + .ppu.reg_base = (uintptr_t)vppu_regcluster, + .ppu.irq = PPU_SYS1_IRQ + }), + }, + [PPU_V0_ELEMENT_IDX_CPU2] = { + .name = "CPU2", + .data = &((struct mod_ppu_v0_pd_config) { + .pd_type = MOD_PD_TYPE_DEVICE, + .ppu.reg_base = (uintptr_t)vppu_regcluster, + .ppu.irq = PPU_SYS1_IRQ + }), + }, + [PPU_V0_ELEMENT_IDX_CPU3] = { + .name = "CPU3", + .data = &((struct mod_ppu_v0_pd_config) { + .pd_type = MOD_PD_TYPE_DEVICE, + .ppu.reg_base = (uintptr_t)vppu_regcluster, + .ppu.irq = PPU_SYS1_IRQ + }), + }, + [PPU_V0_ELEMENT_IDX_CLUSTER0] = { + .name = "CLUSTER0", + .data = &((struct mod_ppu_v0_pd_config) { + .pd_type = MOD_PD_TYPE_DEVICE, + .ppu.reg_base = (uintptr_t)vppu_regcluster, + .ppu.irq = PPU_SYS1_IRQ + }), + }, + [PPU_V0_ELEMENT_IDX_CLUSTER1] = { + .name = "CLUSTER1", + .data = &((struct mod_ppu_v0_pd_config) { + .pd_type = MOD_PD_TYPE_DEVICE, + .ppu.reg_base = (uintptr_t)vppu_regcluster, + .ppu.irq = PPU_SYS1_IRQ + }), + }, + [PPU_V0_ELEMENT_IDX_DBGTOP] = { + .name = "DBGTOP", + .data = &((struct mod_ppu_v0_pd_config) { + .pd_type = MOD_PD_TYPE_DEVICE_DEBUG, + .ppu.reg_base = (uintptr_t)vppu_regdbg, + .ppu.irq = PPU_DEBUG_IRQ + }), + }, + [PPU_V0_ELEMENT_IDX_DPU0TOP] = { + .name = "DPU0TOP", + .data = &((struct mod_ppu_v0_pd_config) { + .pd_type = MOD_PD_TYPE_DEVICE, + .ppu.reg_base = (uintptr_t)vppu_regdpu0, + .ppu.irq = PPU_DPU0_IRQ, + .default_power_on = true, + }), + }, + [PPU_V0_ELEMENT_IDX_DPU1TOP] = { + .name = "DPU1TOP", + .data = &((struct mod_ppu_v0_pd_config) { + .pd_type = MOD_PD_TYPE_DEVICE, + .ppu.reg_base = (uintptr_t)vppu_regdpu1, + .ppu.irq = PPU_DPU1_IRQ, + .default_power_on = true, + }), + }, + [PPU_V0_ELEMENT_IDX_GPUTOP] = { + .name = "GPUTOP", + .data = &((struct mod_ppu_v0_pd_config) { + .pd_type = MOD_PD_TYPE_DEVICE, + .ppu.reg_base = (uintptr_t)vppu_reggpu, + .ppu.irq = PPU_GPU_IRQ, + .default_power_on = true, + }), + }, + [PPU_V0_ELEMENT_IDX_VPUTOP] = { + .name = "VPUTOP", + .data = &((struct mod_ppu_v0_pd_config) { + .pd_type = MOD_PD_TYPE_DEVICE, + .ppu.reg_base = (uintptr_t)vppu_regvpu, + .ppu.irq = PPU_VPU_IRQ, + .default_power_on = true, + }), + }, + [PPU_V0_ELEMENT_IDX_SYS0] = { + .name = "SYS0", + .data = &((struct mod_ppu_v0_pd_config) { + .pd_type = MOD_PD_TYPE_SYSTEM, + .ppu.reg_base = (uintptr_t)vppu_regsys0, + .ppu.irq = PPU_SYS0_IRQ + }), + }, + [PPU_V0_ELEMENT_IDX_SYS1] = { + .name = "SYS1", + .data = &((struct mod_ppu_v0_pd_config) { + .pd_type = MOD_PD_TYPE_SYSTEM, + .ppu.reg_base = (uintptr_t)vppu_regsys1, + .ppu.irq = PPU_SYS1_IRQ + }), + }, + [PPU_V0_ELEMENT_IDX_SYSTEM] = { + .name = "SYSTEM", + .data = &((struct mod_ppu_v0_pd_config) { + .pd_type = MOD_PD_TYPE_DEVICE, + .ppu.reg_base = (uintptr_t)vppu_regsys, + .ppu.irq = PPU_SYS1_IRQ, + .default_power_on = true, + }), + }, + [PPU_V0_ELEMENT_IDX_COUNT] = { 0 }, /* Termination entry */ +}; + + +static const struct fwk_element *host_ppu_v0_get_element_table + (fwk_id_t module_id) +{ + return host_ppu_v0_element_table; +} + +/* + * Power module configuration data + */ +struct fwk_module_config config_vppu = { + .elements = FWK_MODULE_DYNAMIC_ELEMENTS(host_ppu_v0_get_element_table), +}; diff --git a/product/virtio-zephyr/fw/config_ppu_v0.h b/product/virtio-zephyr/fw/config_ppu_v0.h new file mode 100644 index 0000000000000000000000000000000000000000..3f70a1d6add58144f89f81f69236da7398efba4c --- /dev/null +++ b/product/virtio-zephyr/fw/config_ppu_v0.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 CONFIG_PPU_V0_H +#define CONFIG_PPU_V0_H + +enum ppu_v0_element_idx { + PPU_V0_ELEMENT_IDX_CPU0, + PPU_V0_ELEMENT_IDX_CPU1, + PPU_V0_ELEMENT_IDX_CPU2, + PPU_V0_ELEMENT_IDX_CPU3, + PPU_V0_ELEMENT_IDX_CLUSTER0, + PPU_V0_ELEMENT_IDX_CLUSTER1, + PPU_V0_ELEMENT_IDX_DBGTOP, + PPU_V0_ELEMENT_IDX_DPU0TOP, + PPU_V0_ELEMENT_IDX_DPU1TOP, + PPU_V0_ELEMENT_IDX_GPUTOP, + PPU_V0_ELEMENT_IDX_VPUTOP, + PPU_V0_ELEMENT_IDX_SYS0, + PPU_V0_ELEMENT_IDX_SYS1, + PPU_V0_ELEMENT_IDX_SYSTEM, + PPU_V0_ELEMENT_IDX_COUNT +}; + +#endif /* CONFIG_PPU_V0_H */ diff --git a/product/virtio-zephyr/fw/config_psu.c b/product/virtio-zephyr/fw/config_psu.c new file mode 100644 index 0000000000000000000000000000000000000000..6ad0595cbc23de700e7f50dae6393643f608fbd1 --- /dev/null +++ b/product/virtio-zephyr/fw/config_psu.c @@ -0,0 +1,56 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + +static const struct fwk_element element_table[] = { + { + .name = "CPU_GROUP_LITTLE", + .data = &(const struct mod_psu_element_cfg) { + .driver_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_MOCK_PSU, 0), + .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_MOCK_PSU, + MOD_MOCK_PSU_API_IDX_DRIVER) + }, + }, + { + .name = "CPU_GROUP_BIG", + .data = &(const struct mod_psu_element_cfg) { + .driver_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_MOCK_PSU, 1), + .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_MOCK_PSU, + MOD_MOCK_PSU_API_IDX_DRIVER) + }, + }, + { + .name = "GPU", + .data = &(const struct mod_psu_element_cfg) { + .driver_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_MOCK_PSU, 2), + .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_MOCK_PSU, + MOD_MOCK_PSU_API_IDX_DRIVER) + }, + }, + { + .name = "VPU", + .data = &(const struct mod_psu_element_cfg) { + .driver_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_MOCK_PSU, 3), + .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_MOCK_PSU, + MOD_MOCK_PSU_API_IDX_DRIVER) + }, + }, + { 0 } +}; + +static const struct fwk_element *psu_get_element_table(fwk_id_t module_id) +{ + return element_table; +} + +struct fwk_module_config config_psu = { + .elements = FWK_MODULE_DYNAMIC_ELEMENTS(psu_get_element_table), +}; diff --git a/product/virtio-zephyr/fw/config_reg_sensor.h b/product/virtio-zephyr/fw/config_reg_sensor.h new file mode 100644 index 0000000000000000000000000000000000000000..60359a6aa527fde82ea2f05068c67e20b8d528f1 --- /dev/null +++ b/product/virtio-zephyr/fw/config_reg_sensor.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 CONFIG_SENSOR_H +#define CONFIG_SENSOR_H + +enum SENSOR_DEVICES { + SENSOR_DEV_SOC_TEMP, + SENSOR_DEV_DDR_TEMP, + SENSOR_DEV_COUNT, +}; + +#endif /* CONFIG_PPU_V0_H */ diff --git a/product/virtio-zephyr/fw/config_scmi.c b/product/virtio-zephyr/fw/config_scmi.c new file mode 100644 index 0000000000000000000000000000000000000000..bb2ea9d9110469689ee60a00f33ecb059c55882c --- /dev/null +++ b/product/virtio-zephyr/fw/config_scmi.c @@ -0,0 +1,122 @@ +/* + * 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 + +static const struct fwk_element service_table[] = { + [SCMI_SERVICE_IDX_PSCI] = { + .name = "agent PSCI", + .data = &((struct mod_scmi_service_config) { + .transport_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_MSG_SMT, + SCMI_SERVICE_IDX_PSCI), + .transport_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_MSG_SMT, + MOD_MSG_SMT_API_IDX_SCMI_TRANSPORT), + .scmi_agent_id = SCMI_AGENT_ID_PSCI, + .transport_notification_init_id = FWK_ID_NONE_INIT, + .scmi_p2a_id = FWK_ID_NONE_INIT, + }), + }, + [SCMI_SERVICE_IDX_OSPM_0] = { + .name = "agent OSPM0", + .data = &((struct mod_scmi_service_config) { + .transport_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_MSG_SMT, + SCMI_SERVICE_IDX_OSPM_0), + .transport_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_MSG_SMT, + MOD_MSG_SMT_API_IDX_SCMI_TRANSPORT), + .scmi_agent_id = SCMI_AGENT_ID_OSPM, + .transport_notification_init_id = FWK_ID_NONE_INIT, +#ifdef BUILD_HAS_SCMI_NOTIFICATIONS + .scmi_p2a_id = FWK_ID_ELEMENT_INIT( + FWK_MODULE_IDX_SCMI, + SCMI_SERVICE_IDX_OSPM_0_P2A), +#else + .scmi_p2a_id = FWK_ID_NONE_INIT, +#endif + }), + }, + [SCMI_SERVICE_IDX_OSPM_1] = { + .name = "agent OSPM1", + .data = &((struct mod_scmi_service_config) { + .transport_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_MSG_SMT, + SCMI_SERVICE_IDX_OSPM_1), + .transport_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_MSG_SMT, + MOD_MSG_SMT_API_IDX_SCMI_TRANSPORT), + .scmi_agent_id = SCMI_AGENT_ID_PERF, + .transport_notification_init_id = FWK_ID_NONE_INIT, +#ifdef BUILD_HAS_SCMI_NOTIFICATIONS + .scmi_p2a_id = FWK_ID_ELEMENT_INIT( + FWK_MODULE_IDX_SCMI, + SCMI_SERVICE_IDX_OSPM_1_P2A), +#else + .scmi_p2a_id = FWK_ID_NONE_INIT, +#endif + }), + }, +#ifdef BUILD_HAS_SCMI_NOTIFICATIONS + [SCMI_SERVICE_IDX_OSPM_0_P2A] = { + .name = "agent OSPM0 P2A", + .data = &((struct mod_scmi_service_config) { + .transport_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_MSG_SMT, + SCMI_SERVICE_IDX_OSPM_0_P2A), + .transport_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_MSG_SMT, + MOD_MSG_SMT_API_IDX_SCMI_TRANSPORT), + .scmi_agent_id = SCMI_AGENT_ID_OSPM, + .transport_notification_init_id = FWK_ID_NONE_INIT, + .scmi_p2a_id = FWK_ID_NONE_INIT, + }), + }, + [SCMI_SERVICE_IDX_OSPM_1_P2A] = { + .name = "agent OSPM1 P2A", + .data = &((struct mod_scmi_service_config) { + .transport_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_MSG_SMT, + SCMI_SERVICE_IDX_OSPM_1_P2A), + .transport_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_MSG_SMT, + MOD_MSG_SMT_API_IDX_SCMI_TRANSPORT), + .scmi_agent_id = SCMI_AGENT_ID_OSPM, + .transport_notification_init_id = FWK_ID_NONE_INIT, + .scmi_p2a_id = FWK_ID_NONE_INIT, + }), + }, +#endif + [SCMI_SERVICE_IDX_COUNT] = { 0 } +}; + +static const struct fwk_element *get_service_table(fwk_id_t module_id) +{ + return service_table; +} + +static const struct mod_scmi_agent agent_table[] = { + [SCMI_AGENT_ID_OSPM] = { + .type = SCMI_AGENT_TYPE_OSPM, + .name = "OSPM", + }, + [SCMI_AGENT_ID_PSCI] = { + .type = SCMI_AGENT_TYPE_PSCI, + .name = "PSCI", + }, + [SCMI_AGENT_ID_PERF] = { + .type = SCMI_AGENT_TYPE_OSPM, + .name = "PERF", + }, +}; + +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_service_table), +}; diff --git a/product/virtio-zephyr/fw/config_scmi_clock.c b/product/virtio-zephyr/fw/config_scmi_clock.c new file mode 100644 index 0000000000000000000000000000000000000000..d2eb353badacb3f6dcf28796389114df6de2c26d --- /dev/null +++ b/product/virtio-zephyr/fw/config_scmi_clock.c @@ -0,0 +1,98 @@ +/* + * 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 "clock_devices.h" + +static const struct mod_scmi_clock_device agent_device_table_ospm[] = { + { + /* MOCK_0 */ + .element_id = + FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_CLOCK, CLOCK_DEV_IDX_MOCK_0), + }, + { + /* MOCK_1 */ + .element_id = + FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_CLOCK, CLOCK_DEV_IDX_MOCK_1), + }, + { + /* VPU */ + .element_id = + FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_CLOCK, CLOCK_DEV_IDX_VPU), + }, + { + /* MOCK_3 */ + .element_id = + FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_CLOCK, CLOCK_DEV_IDX_MOCK_3), + }, + { + /* DPU */ + .element_id = + FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_CLOCK, CLOCK_DEV_IDX_DPU), + }, + { + /* PIXEL_0 */ + .element_id = + FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_CLOCK, CLOCK_DEV_IDX_PIXEL_0), + }, + { + /* PIXEL_1 */ + .element_id = + FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_CLOCK, CLOCK_DEV_IDX_PIXEL_1), + }, +}; + +static const struct mod_scmi_clock_device agent_device_table_perf[] = { + { + /* MOCK_0 */ + .element_id = + FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_CLOCK, CLOCK_DEV_IDX_MOCK_0), + }, + { + /* MOCK_2 */ + .element_id = + FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_CLOCK, CLOCK_DEV_IDX_MOCK_2), + }, + { + /* MOCK_3 */ + .element_id = + FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_CLOCK, CLOCK_DEV_IDX_MOCK_3), + }, + { + /* PIXEL_0 */ + .element_id = + FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_CLOCK, CLOCK_DEV_IDX_PIXEL_0), + }, + { + /* PIXEL_1 */ + .element_id = + FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_CLOCK, CLOCK_DEV_IDX_PIXEL_1), + }, +}; + +static const struct mod_scmi_clock_agent agent_table[SCMI_AGENT_ID_COUNT] = { + [SCMI_AGENT_ID_OSPM] = { + .device_table = agent_device_table_ospm, + .device_count = FWK_ARRAY_SIZE(agent_device_table_ospm), + }, + [SCMI_AGENT_ID_PSCI] = { 0 /* No access */ }, + [SCMI_AGENT_ID_PERF] = { + .device_table = agent_device_table_perf, + .device_count = FWK_ARRAY_SIZE(agent_device_table_perf), + }, +}; + +struct fwk_module_config config_scmi_clock = { + .data = &((struct mod_scmi_clock_config) { + .max_pending_transactions = 0, + .agent_table = agent_table, + .agent_count = FWK_ARRAY_SIZE(agent_table), + }), +}; diff --git a/product/virtio-zephyr/fw/config_scmi_perf.c b/product/virtio-zephyr/fw/config_scmi_perf.c new file mode 100644 index 0000000000000000000000000000000000000000..63ca90e7b4d620ac7cbdbd4e9207d37a81b751be --- /dev/null +++ b/product/virtio-zephyr/fw/config_scmi_perf.c @@ -0,0 +1,31 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include "config_dvfs.h" + +static const struct mod_scmi_perf_domain_config domains[] = { + [DVFS_ELEMENT_IDX_LITTLE] = { + .fast_channels_addr_scp = 0x0, + }, + [DVFS_ELEMENT_IDX_BIG] = { + .fast_channels_addr_scp = 0x0, + }, + [DVFS_ELEMENT_IDX_GPU] = { + .fast_channels_addr_scp = 0x0, + }, +}; + +struct fwk_module_config config_scmi_perf = { + .data = &((struct mod_scmi_perf_config) { + .domains = &domains, + .perf_doms_count = FWK_ARRAY_SIZE(domains), + .fast_channels_alarm_id = FWK_ID_NONE_INIT, + }), +}; diff --git a/product/virtio-zephyr/fw/config_scmi_power_domain.c b/product/virtio-zephyr/fw/config_scmi_power_domain.c new file mode 100644 index 0000000000000000000000000000000000000000..0740409915e723032ae4852d7c97b20bd6018b28 --- /dev/null +++ b/product/virtio-zephyr/fw/config_scmi_power_domain.c @@ -0,0 +1,11 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +/* No elements, no module configuration data */ +struct fwk_module_config config_scmi_power_domain = { 0 }; diff --git a/product/virtio-zephyr/fw/config_sensor.c b/product/virtio-zephyr/fw/config_sensor.c new file mode 100644 index 0000000000000000000000000000000000000000..20826868113ed5e5d3e217c9db21e050e6437072 --- /dev/null +++ b/product/virtio-zephyr/fw/config_sensor.c @@ -0,0 +1,100 @@ +/* + * 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 "config_reg_sensor.h" + +uint64_t soc_temp[3] = {25000, 25000, 25000}; +uint64_t ddr_temp[1] = {25000}; +/* + * Register Sensor driver config + */ +static struct mod_sensor_info info_soc_temperature = { + .type = MOD_SENSOR_TYPE_DEGREES_C, + .update_interval = 0, + .update_interval_multiplier = 0, + .unit_multiplier = -3, +}; + +static const struct fwk_element reg_sensor_element_table[] = { + [SENSOR_DEV_SOC_TEMP] = { + .name = "Soc Temperature", + .data = &((struct mod_reg_sensor_dev_config) { + .reg = (uintptr_t)(soc_temp), + .info = &info_soc_temperature, + }), + }, + [SENSOR_DEV_DDR_TEMP] = { + .name = "DDR Temperature", + .data = &((struct mod_reg_sensor_dev_config) { + .reg = (uintptr_t)(ddr_temp), + .info = &info_soc_temperature, + }), + }, + [SENSOR_DEV_COUNT] = { 0 }, +}; + +static const struct fwk_element *get_reg_sensor_element_table(fwk_id_t id) +{ + return reg_sensor_element_table; +} + +struct fwk_module_config config_reg_sensor = { + .elements = FWK_MODULE_DYNAMIC_ELEMENTS(get_reg_sensor_element_table), +}; + +/* + * Sensor module config + */ +static const struct fwk_element sensor_element_table[] = { + [0] = { + .name = "Soc Temperature", + .data = &((const struct mod_sensor_dev_config) { + .driver_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_REG_SENSOR, + SENSOR_DEV_SOC_TEMP), + .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_REG_SENSOR, 0), + .trip_point = { + .count = 2, + } + }), + }, + [1] = { + .name = "DDR Temperature", + .data = &((const struct mod_sensor_dev_config) { + .driver_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_REG_SENSOR, + SENSOR_DEV_DDR_TEMP), + .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_REG_SENSOR, 0), + .trip_point = { + .count = 2, + } + }), + }, + [2] = { 0 }, +}; + +static const struct fwk_element *get_sensor_element_table(fwk_id_t module_id) +{ + return sensor_element_table; +} +static const struct mod_sensor_config sensor_config = { +#ifdef BUILD_HAS_SCMI_NOTIFICATIONS + .notification_id = FWK_ID_MODULE_INIT(FWK_MODULE_IDX_SCMI_SENSOR), + .trip_point_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_SCMI_SENSOR, + SCMI_SENSOR_API_IDX_TRIP_POINT), +#else + .notification_id = FWK_ID_NONE_INIT +#endif +}; + +struct fwk_module_config config_sensor = { + .elements = FWK_MODULE_DYNAMIC_ELEMENTS(get_sensor_element_table), + .data = &sensor_config, +}; diff --git a/product/virtio-zephyr/fw/config_vpll.c b/product/virtio-zephyr/fw/config_vpll.c new file mode 100644 index 0000000000000000000000000000000000000000..78874a888bb8633437c5bec1995be26f8b284e03 --- /dev/null +++ b/product/virtio-zephyr/fw/config_vpll.c @@ -0,0 +1,108 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +uint32_t ctrl_reg[7]; + +static const struct fwk_element system_pll_element_table[] = { + { + .name = "CPU_PLL_0", + .data = &((struct mod_system_pll_dev_config) { + .control_reg = &ctrl_reg[0], + .lock_flag_mask = PLL_STATUS1_CPUPLLLOCK(0, 0), + .initial_rate = 1330 * FWK_MHZ, + .min_rate = MOD_SYSTEM_PLL_MIN_RATE, + .max_rate = MOD_SYSTEM_PLL_MAX_RATE, + .min_step = MOD_SYSTEM_PLL_MIN_INTERVAL, + .defer_initialization = false, + }), + }, + { + .name = "CPU_PLL_1", + .data = &((struct mod_system_pll_dev_config) { + .control_reg = &ctrl_reg[1], + .lock_flag_mask = PLL_STATUS1_CPUPLLLOCK(0, 1), + .initial_rate = 1750 * FWK_MHZ, + .min_rate = MOD_SYSTEM_PLL_MIN_RATE, + .max_rate = MOD_SYSTEM_PLL_MAX_RATE, + .min_step = MOD_SYSTEM_PLL_MIN_INTERVAL, + .defer_initialization = false, + }), + }, + { + .name = "GPU_PLL", + .data = &((struct mod_system_pll_dev_config) { + .control_reg = &ctrl_reg[2], + .lock_flag_mask = PLL_STATUS0_GPUPLLLOCK, + .initial_rate = 600 * FWK_MHZ, + .min_rate = MOD_SYSTEM_PLL_MIN_RATE, + .max_rate = MOD_SYSTEM_PLL_MAX_RATE, + .min_step = MOD_SYSTEM_PLL_MIN_INTERVAL, + .defer_initialization = false, + }), + }, + { + .name = "DPU_PLL", + .data = &((struct mod_system_pll_dev_config) { + .control_reg = &ctrl_reg[3], + .lock_flag_mask = PLL_STATUS0_DISPLAYPLLLOCK, + .initial_rate = 260 * FWK_MHZ, + .min_rate = MOD_SYSTEM_PLL_MIN_RATE, + .max_rate = MOD_SYSTEM_PLL_MAX_RATE, + .min_step = MOD_SYSTEM_PLL_MIN_INTERVAL, + .defer_initialization = false, + }), + }, + { + .name = "VPU_PLL", + .data = &((struct mod_system_pll_dev_config) { + .control_reg = &ctrl_reg[4], + .lock_flag_mask = PLL_STATUS0_VIDEOPLLLOCK, + .initial_rate = 600 * FWK_MHZ, + .min_rate = MOD_SYSTEM_PLL_MIN_RATE, + .max_rate = MOD_SYSTEM_PLL_MAX_RATE, + .min_step = MOD_SYSTEM_PLL_MIN_INTERVAL, + .defer_initialization = false, + }), + }, + { + .name = "PIX0_PLL", + .data = &((struct mod_system_pll_dev_config) { + .control_reg = &ctrl_reg[5], + .initial_rate = 594 * FWK_MHZ, + .min_rate = 12500 * FWK_KHZ, + .max_rate = 594 * FWK_MHZ, + .min_step = 250 * FWK_KHZ, + .defer_initialization = false, + }), + }, + { + .name = "PIX1_PLL", + .data = &((struct mod_system_pll_dev_config) { + .control_reg = &ctrl_reg[6], + .initial_rate = 594 * FWK_MHZ, + .min_rate = 12500 * FWK_KHZ, + .max_rate = 594 * FWK_MHZ, + .min_step = 250 * FWK_KHZ, + .defer_initialization = false, + }), + }, + { 0 }, /* Termination description. */ +}; + +static const struct fwk_element *system_pll_get_element_table + (fwk_id_t module_id) +{ + return system_pll_element_table; +} + +struct fwk_module_config config_system_pll = { + .elements = FWK_MODULE_DYNAMIC_ELEMENTS(system_pll_get_element_table), +}; diff --git a/product/virtio-zephyr/include/fake_irq.h b/product/virtio-zephyr/include/fake_irq.h new file mode 100644 index 0000000000000000000000000000000000000000..75e53e5d8b5b56880e34f50a51e99a639c45b043 --- /dev/null +++ b/product/virtio-zephyr/include/fake_irq.h @@ -0,0 +1,178 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SGM775_IRQ_H +#define SGM775_IRQ_H + +#include + +#define WDOG_IRQ FWK_INTERRUPT_NMI /* SCP Watchdog (SP805) */ + +enum sgm775_irq { + TIM32KHZ_IRQ = 0, /* 32KHz Physical Timer */ + CDBG_PWR_UP_REQ_IRQ = 1, /* Coresight Debug Power Request */ + CSYS_PWR_UP_REQ_IRQ = 2, /* Coresight System Power Request */ + CDBG_RST_REQ_IRQ = 3, /* Coresight Debug Reset Request */ + GIC_EXT_WAKEUP_IRQ = 4, /* External GIC Wakeup Request */ + RESERVED5_IRQ = 5, /* Reserved */ + RESERVED6_IRQ = 6, /* Reserved */ + RESERVED7_IRQ = 7, /* Reserved */ + RESERVED8_IRQ = 8, /* Reserved */ + RESERVED9_IRQ = 9, /* Reserved */ + RESERVED10_IRQ = 10, /* Reserved */ + RESERVED11_IRQ = 11, /* Reserved */ + RESERVED12_IRQ = 12, /* Reserved */ + RESERVED13_IRQ = 13, /* Reserved */ + RESERVED14_IRQ = 14, /* Reserved */ + RESERVED15_IRQ = 15, /* Reserved */ + SOC_WAKEUP0_IRQ = 16, /* SoC Expansion Wakeup */ + SOC_WAKEUP1_IRQ = 17, /* SoC Expansion Wakeup */ + SOC_WAKEUP2_IRQ = 18, /* SoC Expansion Wakeup */ + SOC_WAKEUP3_IRQ = 19, /* SoC Expansion Wakeup */ + SOC_WAKEUP4_IRQ = 20, /* SoC Expansion Wakeup */ + SOC_WAKEUP5_IRQ = 21, /* SoC Expansion Wakeup */ + SOC_WAKEUP6_IRQ = 22, /* SoC Expansion Wakeup */ + SOC_WAKEUP7_IRQ = 23, /* SoC Expansion Wakeup */ + SOC_WAKEUP8_IRQ = 24, /* SoC Expansion Wakeup */ + SOC_WAKEUP9_IRQ = 25, /* SoC Expansion Wakeup */ + SOC_WAKEUP10_IRQ = 26, /* SoC Expansion Wakeup */ + SOC_WAKEUP11_IRQ = 27, /* SoC Expansion Wakeup */ + SOC_WAKEUP12_IRQ = 28, /* SoC Expansion Wakeup */ + SOC_WAKEUP13_IRQ = 29, /* SoC Expansion Wakeup */ + SOC_WAKEUP14_IRQ = 30, /* SoC Expansion Wakeup */ + SOC_WAKEUP15_IRQ = 31, /* SoC Expansion Wakeup */ + PPU_SCP_IRQ = 32, /* SCP Power Policy Unit */ + TIMREFCLK_IRQ = 33, /* REFCLK Physical Timer */ + MHU_HIGH_PRIO_IRQ = 34, /* MHU High Priority */ + MHU_LOW_PRIO_IRQ = 35, /* MHU Low Priority */ + MHU_SECURE_IRQ = 36, /* MHU Secure */ + CTI_TRIGGER0_IRQ = 37, /* SCP CTI Trigger */ + CTI_TRIGGER1_IRQ = 38, /* SCP CTI Trigger */ + GIC_ERROR_ECC_IRQ = 39, /* GIC Error (ECC Fatal) */ + GIC_ERROR_AXIM_IRQ = 40, /* GIC Error (AXIM) */ + DMC_RESERVED0_IRQ = 41, /* DMC, Reserved */ + DMC_0_ERROR_ECC_IRQ = 42, /* DMC0 Combined ECC Error */ + DMC_0_ERROR_ACCESS_IRQ = 43, /* DMC0 Combined Misc Access Error */ + DMC_RESERVED1_IRQ = 44, /* DMC, Reserved */ + DMC_RESERVED2_IRQ = 45, /* DMC, Reserved */ + DMC_1_ERROR_ECC_IRQ = 46, /* DMC1 Combined ECC Error */ + DMC_1_ERROR_ACCESS_IRQ = 47, /* DMC1 Combined Misc Access Error */ + DMC_RESERVED3_IRQ = 48, /* DMC, Reserved */ + DMC_RESERVED4_IRQ = 49, /* DMC, Reserved */ + DMC_2_ERROR_ECC_IRQ = 50, /* DMC2 Combined ECC Error */ + DMC_2_ERROR_ACCESS_IRQ = 51, /* DMC2 Combined Misc Access Error */ + DMC_RESERVED5_IRQ = 52, /* DMC, Reserved */ + DMC_RESERVED6_IRQ = 53, /* DMC, Reserved */ + DMC_3_ERROR_ECC_IRQ = 54, /* DMC3 Combined ECC Error */ + DMC_3_ERROR_ACCESS_IRQ = 55, /* DMC3 Combined Misc Access Error */ + DMC_RESERVED7_IRQ = 56, /* DMC, Reserved */ + RESERVED57_IRQ = 57, /* Reserved */ + RESERVED58_IRQ = 58, /* Reserved */ + RESERVED59_IRQ = 59, /* Reserved */ + RESERVED60_IRQ = 60, /* Reserved */ + RESERVED61_IRQ = 61, /* Reserved */ + RESERVED62_IRQ = 62, /* Reserved */ + RESERVED63_IRQ = 63, /* Reserved */ + PPU_CLUS0CORE0_IRQ = 64, /* Cluster 0 Core 0 Power Policy Unit */ + PPU_CLUS0CORE1_IRQ = 65, /* Cluster 0 Core 1 Power Policy Unit */ + PPU_CLUS0CORE2_IRQ = 66, /* Cluster 0 Core 2 Power Policy Unit */ + PPU_CLUS0CORE3_IRQ = 67, /* Cluster 0 Core 3 Power Policy Unit */ + PPU_CLUS0_IRQ = 68, /* Cluster 0 Power Policy Unit */ + PPU_CLUS1CORE0_IRQ = 69, /* Cluster 1 Core 0 Power Policy Unit */ + PPU_CLUS1CORE1_IRQ = 70, /* Cluster 1 Core 1 Power Policy Unit */ + PPU_CLUS1CORE2_IRQ = 71, /* Cluster 1 Core 2 Power Policy Unit */ + PPU_CLUS1CORE3_IRQ = 72, /* Cluster 1 Core 3 Power Policy Unit */ + PPU_CLUS1_IRQ = 73, /* Cluster 1 Power Policy Unit */ + PPU_SYS0_IRQ = 74, /* System Power Policy Unit 0 */ + PPU_SYS1_IRQ = 75, /* System Power Policy Unit 1 */ + PPU_GPU_IRQ = 76, /* GPU Power Policy Unit */ + PPU_VPU_IRQ = 77, /* Video Power Policy Unit */ + RESERVED78_IRQ = 78, /* Reserved */ + PPU_DPU0_IRQ = 79, /* Display Power Policy Unit 0 */ + PPU_DPU1_IRQ = 80, /* Display Power Policy Unit 1 */ + PPU_DEBUG_IRQ = 81, /* DBGSYS Power Policy Unit */ + RESERVED82_IRQ = 82, /* Reserved */ + RESERVED83_IRQ = 83, /* Reserved */ + RESERVED84_IRQ = 84, /* Reserved */ + RESERVED85_IRQ = 85, /* Reserved */ + RESERVED86_IRQ = 86, /* Reserved */ + RESERVED87_IRQ = 87, /* Reserved */ + RESERVED88_IRQ = 88, /* Reserved */ + RESERVED89_IRQ = 89, /* Reserved */ + PPU_CLUS0CORE4_IRQ = 90, /* Cluster 0 Core 4 Power Policy Unit */ + PPU_CLUS0CORE5_IRQ = 91, /* Cluster 0 Core 5 Power Policy Unit */ + PPU_CLUS0CORE6_IRQ = 92, /* Cluster 0 Core 6 Power Policy Unit */ + PPU_CLUS0CORE7_IRQ = 93, /* Cluster 0 Core 7 Power Policy Unit */ + PPU_CLUS1CORE4_IRQ = 94, /* Cluster 1 Core 4 Power Policy Unit */ + PPU_CLUS1CORE5_IRQ = 95, /* Cluster 1 Core 5 Power Policy Unit */ + PPU_CLUS1CORE6_IRQ = 96, /* Cluster 1 Core 6 Power Policy Unit */ + PPU_CLUS1CORE7_IRQ = 97, /* Cluster 1 Core 7 Power Policy Unit */ + PLL_CLUS0_LOCK_IRQ = 98, /* Cluster 0 CPU PLL Lock */ + PLL_CLUS1_LOCK_IRQ = 99, /* Cluster 1 CPU PLL Lock */ + PLL_GPU_LOCK_IRQ = 100, /* GPU PLL Lock */ + PLL_VPU_LOCK_IRQ = 101, /* Video PLL Lock */ + PLL_SYS_LOCK_IRQ = 102, /* System PLL Lock */ + PLL_DPU_LOCK_IRQ = 103, /* Display PLL Lock */ + PLL_CLUS0CORE0_IRQ = 104, /* Cluster 0 PLL0 Lock */ + PLL_CLUS0CORE1_IRQ = 105, /* Cluster 0 PLL1 Lock */ + PLL_CLUS0CORE2_IRQ = 106, /* Cluster 0 PLL2 Lock */ + PLL_CLUS0CORE3_IRQ = 107, /* Cluster 0 PLL3 Lock */ + PLL_CLUS0CORE4_IRQ = 108, /* Cluster 0 PLL4 Lock */ + PLL_CLUS0CORE5_IRQ = 109, /* Cluster 0 PLL5 Lock */ + PLL_CLUS0CORE6_IRQ = 110, /* Cluster 0 PLL6 Lock */ + PLL_CLUS0CORE7_IRQ = 111, /* Cluster 0 PLL7 Lock */ + PLL_CLUS1CORE0_IRQ = 112, /* Cluster 1 PLL0 Lock */ + PLL_CLUS1CORE1_IRQ = 113, /* Cluster 1 PLL1 Lock */ + PLL_CLUS1CORE2_IRQ = 114, /* Cluster 1 PLL2 Lock */ + PLL_CLUS1CORE3_IRQ = 115, /* Cluster 1 PLL3 Lock */ + PLL_CLUS1CORE4_IRQ = 116, /* Cluster 1 PLL4 Lock */ + PLL_CLUS1CORE5_IRQ = 117, /* Cluster 1 PLL5 Lock */ + PLL_CLUS1CORE6_IRQ = 118, /* Cluster 1 PLL6 Lock */ + PLL_CLUS1CORE7_IRQ = 119, /* Cluster 1 PLL7 Lock */ + RESERVED120_IRQ = 120, /* Reserved */ + RESERVED121_IRQ = 121, /* Reserved */ + RESERVED122_IRQ = 122, /* Reserved */ + RESERVED123_IRQ = 123, /* Reserved */ + RESERVED124_IRQ = 124, /* Reserved */ + RESERVED125_IRQ = 125, /* Reserved */ + RESERVED126_IRQ = 126, /* Reserved */ + RESERVED127_IRQ = 127, /* Reserved */ + SCP_EXT_INTR0_IRQ = 128, /* SCP Customer Extension */ + SCP_EXT_INTR1_IRQ = 129, /* SCP Customer Extension */ + SCP_EXT_INTR2_IRQ = 130, /* SCP Customer Extension */ + SCP_EXT_INTR3_IRQ = 131, /* SCP Customer Extension */ + SCP_EXT_INTR4_IRQ = 132, /* SCP Customer Extension */ + SCP_EXT_INTR5_IRQ = 133, /* SCP Customer Extension */ + SCP_EXT_INTR6_IRQ = 134, /* SCP Customer Extension */ + SCP_EXT_INTR7_IRQ = 135, /* SCP Customer Extension */ + SCP_EXT_INTR8_IRQ = 136, /* SCP Customer Extension */ + SCP_EXT_INTR9_IRQ = 137, /* SCP Customer Extension */ + SCP_EXT_INTR10_IRQ = 138, /* SCP Customer Extension */ + SCP_EXT_INTR11_IRQ = 139, /* SCP Customer Extension */ + SCP_EXT_INTR12_IRQ = 140, /* SCP Customer Extension */ + SCP_EXT_INTR13_IRQ = 141, /* SCP Customer Extension */ + SCP_EXT_INTR14_IRQ = 142, /* SCP Customer Extension */ + SCP_EXT_INTR15_IRQ = 143, /* SCP Customer Extension */ + SCP_EXT_INTR16_IRQ = 144, /* SCP Customer Extension */ + SCP_EXT_INTR17_IRQ = 145, /* SCP Customer Extension */ + SCP_EXT_INTR18_IRQ = 146, /* SCP Customer Extension */ + SCP_EXT_INTR19_IRQ = 147, /* SCP Customer Extension */ + SCP_EXT_INTR20_IRQ = 148, /* SCP Customer Extension */ + SCP_EXT_INTR21_IRQ = 149, /* SCP Customer Extension */ + SCP_EXT_INTR22_IRQ = 150, /* SCP Customer Extension */ + SCP_EXT_INTR23_IRQ = 151, /* SCP Customer Extension */ + SCP_EXT_INTR24_IRQ = 152, /* SCP Customer Extension */ + SCP_EXT_INTR25_IRQ = 153, /* SCP Customer Extension */ + SCP_EXT_INTR26_IRQ = 154, /* SCP Customer Extension */ + SCP_EXT_INTR27_IRQ = 155, /* SCP Customer Extension */ + SCP_EXT_INTR28_IRQ = 156, /* SCP Customer Extension */ + SCP_EXT_INTR29_IRQ = 157, /* SCP Customer Extension */ + SCP_EXT_INTR30_IRQ = 158, /* SCP Customer Extension */ + SCP_EXT_INTR31_IRQ = 159, /* SCP Customer Extension */ +}; + +#endif /* SGM775_IRQ_H */ diff --git a/product/virtio-zephyr/include/fake_mmap.h b/product/virtio-zephyr/include/fake_mmap.h new file mode 100644 index 0000000000000000000000000000000000000000..c3643fc6ccccc2c41d311ec594c5b245e0554179 --- /dev/null +++ b/product/virtio-zephyr/include/fake_mmap.h @@ -0,0 +1,101 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SGM775_MMAP_H +#define SGM775_MMAP_H + +#include + +/* + * Top-level base addresses + */ +#define EXPANSION0_BASE UINT32_C(0x40000000) +#define PERIPHERAL_BASE UINT32_C(0x44000000) +#define POWER_PERIPHERAL_BASE UINT32_C(0x50000000) +#define SYS0_BASE UINT32_C(0x60000000) +#define SYS1_BASE UINT32_C(0xA0000000) +#define PPB_INTERNAL_BASE UINT32_C(0xE0000000) +#define PPB_EXTERNAL_BASE UINT32_C(0xE0040000) +#define EXPANSION1_BASE UINT32_C(0xE0100000) + +/* + * Peripherals + */ +#define REFCLK_CNTCTL_BASE (PERIPHERAL_BASE + 0x0000) +#define REFCLK_CNTBASE0_BASE (PERIPHERAL_BASE + 0x1000) +#define WDOG_BASE (PERIPHERAL_BASE + 0x6000) +#define S32K_CNTCONTROL_BASE (PERIPHERAL_BASE + 0x7000) +#define S32K_CNTCTL_BASE (PERIPHERAL_BASE + 0x8000) +#define S32K_CNTBASE0_BASE (PERIPHERAL_BASE + 0x9000) +#define CS_CNTCONTROL_BASE (PERIPHERAL_BASE + 0xA000) + +/* + * Power control peripherals + */ +#define PIK_SCP_BASE (POWER_PERIPHERAL_BASE + 0x00000) +#define PIK_DEBUG_BASE (POWER_PERIPHERAL_BASE + 0x20000) +#define SENSOR_DEBUG_BASE (POWER_PERIPHERAL_BASE + 0x30000) +#define PIK_SYSTEM_BASE (POWER_PERIPHERAL_BASE + 0x40000) +#define SENSOR_SYSTEM_BASE (POWER_PERIPHERAL_BASE + 0x50000) +#define PIK_CLUS0_BASE (POWER_PERIPHERAL_BASE + 0x60000) +#define SENSOR_CLUS0_BASE (POWER_PERIPHERAL_BASE + 0x70000) +#define PIK_CLUS1_BASE (POWER_PERIPHERAL_BASE + 0x80000) +#define SENSOR_CLUS1_BASE (POWER_PERIPHERAL_BASE + 0x90000) +#define PIK_GPU_BASE (POWER_PERIPHERAL_BASE + 0xA0000) +#define SENSOR_GPU_BASE (POWER_PERIPHERAL_BASE + 0xB0000) +#define PIK_VPU_BASE (POWER_PERIPHERAL_BASE + 0xC0000) +#define SENSOR_VPU_BASE (POWER_PERIPHERAL_BASE + 0xD0000) +#define PIK_DPU_BASE (POWER_PERIPHERAL_BASE + 0xE0000) +#define SENSOR_DPU_BASE (POWER_PERIPHERAL_BASE + 0xF0000) + +/* + * PPU base address + */ +#define PPU_SCP_BASE (PIK_SCP_BASE + 0x1000) +#define PPU_SYS0_BASE (PIK_SYSTEM_BASE + 0x1000) +#define PPU_SYS1_BASE (PIK_SYSTEM_BASE + 0x2000) +#define PPU_DEBUG_BASE (PIK_DEBUG_BASE + 0x1000) +#define PPU_CLUS0CORE0_BASE (PIK_CLUS0_BASE + 0x2000) +#define PPU_CLUS0CORE1_BASE (PIK_CLUS0_BASE + 0x3000) +#define PPU_CLUS0CORE2_BASE (PIK_CLUS0_BASE + 0x4000) +#define PPU_CLUS0CORE3_BASE (PIK_CLUS0_BASE + 0x5000) +#define PPU_CLUS0CORE4_BASE (PIK_CLUS0_BASE + 0x6000) +#define PPU_CLUS0CORE5_BASE (PIK_CLUS0_BASE + 0x7000) +#define PPU_CLUS0CORE6_BASE (PIK_CLUS0_BASE + 0x8000) +#define PPU_CLUS0CORE7_BASE (PIK_CLUS0_BASE + 0x9000) +#define PPU_CLUS0_BASE (PIK_CLUS0_BASE + 0x1000) +#define PPU_CLUS1CORE0_BASE (PIK_CLUS1_BASE + 0x2000) +#define PPU_CLUS1CORE1_BASE (PIK_CLUS1_BASE + 0x3000) +#define PPU_CLUS1CORE2_BASE (PIK_CLUS1_BASE + 0x4000) +#define PPU_CLUS1CORE3_BASE (PIK_CLUS1_BASE + 0x5000) +#define PPU_CLUS1_BASE (PIK_CLUS1_BASE + 0x1000) +#define PPU_GPU_BASE (PIK_GPU_BASE + 0x1000) +#define PPU_VPU_BASE (PIK_VPU_BASE + 0x1000) +#define PPU_DPU0_BASE (PIK_DPU_BASE + 0x2000) +#define PPU_DPU1_BASE (PIK_DPU_BASE + 0x3000) + +/* + * System access port 1 + */ +#define TRUSTED_RAM_BASE (SYS1_BASE + 0x04000000) +#define NONTRUSTED_RAM_BASE (SYS1_BASE + 0x06000000) +#define SSC_BASE (SYS1_BASE + 0x2A420000) +#define REFCLK_CNTCONTROL_BASE (SYS1_BASE + 0x2A430000) +#define MHU_BASE (SYS1_BASE + 0x2B1F0000) + +/* + * Base addresses of MHU devices + */ + +#define MHU_SCP_INTR_L_BASE (MHU_BASE) +#define MHU_SCP_INTR_H_BASE (MHU_BASE + 0x0020) +#define MHU_CPU_INTR_L_BASE (MHU_BASE + 0x0100) +#define MHU_CPU_INTR_H_BASE (MHU_BASE + 0x0120) +#define MHU_SCP_INTR_S_BASE (MHU_BASE + 0x0200) +#define MHU_CPU_INTR_S_BASE (MHU_BASE + 0x0300) + +#endif /* SGM775_MMAP_H */ diff --git a/product/virtio-zephyr/include/fake_pik.h b/product/virtio-zephyr/include/fake_pik.h new file mode 100644 index 0000000000000000000000000000000000000000..f0d78e1a5ee02247274aae3ccb150702deec4184 --- /dev/null +++ b/product/virtio-zephyr/include/fake_pik.h @@ -0,0 +1,13 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef FAKE_PIK_H +#define FAKE_PIK_H + +#include + +#endif /* SGM775_PIK_H */ diff --git a/product/virtio-zephyr/include/fake_pik_scp.h b/product/virtio-zephyr/include/fake_pik_scp.h new file mode 100644 index 0000000000000000000000000000000000000000..458ca3755e71fb9a440508b0e42e904d9573ab00 --- /dev/null +++ b/product/virtio-zephyr/include/fake_pik_scp.h @@ -0,0 +1,63 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef FAKE_PIK_SCP_H +#define FAKE_PIK_SCP_H + +#include +#include + +/*! + * \brief SCP PIK register definitions + */ +struct pik_scp_reg { + uint32_t RESERVED0[4]; + FWK_RW uint32_t RESET_SYNDROME; + FWK_RW uint32_t WIC_CTRL; + FWK_R uint32_t WIC_STATUS; + uint8_t RESERVED1[0xA00 - 0x1C]; + FWK_R uint32_t CLKFORCE_STATUS; + FWK_RW uint32_t CLKFORCE_SET; + FWK_RW uint32_t CLKFORCE_CLR; + uint32_t RESERVED2; + FWK_R uint32_t PLL_STATUS0; + FWK_R uint32_t PLL_STATUS1; + uint8_t RESERVED3[0xFC0 - 0xA18]; + FWK_R uint32_t PIK_CONFIG; + uint32_t RESERVED4[3]; + FWK_R uint32_t PID4; + FWK_R uint32_t PID5; + FWK_R uint32_t PID6; + FWK_R uint32_t PID7; + FWK_R uint32_t PID0; + FWK_R uint32_t PID1; + FWK_R uint32_t PID2; + FWK_R uint32_t PID3; + FWK_R uint32_t ID0; + FWK_R uint32_t ID1; + FWK_R uint32_t ID2; + FWK_R uint32_t ID3; +}; + +#define PLL_STATUS0_REFCLK UINT32_C(0x00000001) +#define PLL_STATUS0_BCPUPLLLOCK UINT32_C(0x00000002) +#define PLL_STATUS0_LCPUPLLLOCK UINT32_C(0x00000004) +#define PLL_STATUS0_GPUPLLLOCK UINT32_C(0x00000008) +#define PLL_STATUS0_VIDEOPLLLOCK UINT32_C(0x00000010) +#define PLL_STATUS0_SYSPLLLOCK UINT32_C(0x00000020) +#define PLL_STATUS0_DISPLAYPLLLOCK UINT32_C(0x00000040) + +#define PLL_STATUS1_CPUPLLLOCK(CPU, PLL) \ + ((uint32_t)((1 << (PLL)) << ((CPU) * 8))) + +#define RESET_SYNDROME_PORESET UINT32_C(0x01) +#define RESET_SYNDROME_WDOGRESET_SCP UINT32_C(0x02) +#define RESET_SYNDROME_WDOGRESET_SYS UINT32_C(0x04) +#define RESET_SYNDROME_SYSRESETREQ UINT32_C(0x08) +#define RESET_SYNDROME_SCPM3LOCKUP UINT32_C(0x10) + +#endif /* FAKE_PIK_SCP_H */ diff --git a/product/virtio-zephyr/include/fmw_io.h b/product/virtio-zephyr/include/fmw_io.h new file mode 100644 index 0000000000000000000000000000000000000000..48e5fc9336c3c931ddf7b47ec7b7696be4dae5a8 --- /dev/null +++ b/product/virtio-zephyr/include/fmw_io.h @@ -0,0 +1,18 @@ +/* + * 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_NONE + +#endif /* FMW_IO_H */ diff --git a/product/virtio-zephyr/include/fmw_log.h b/product/virtio-zephyr/include/fmw_log.h new file mode 100644 index 0000000000000000000000000000000000000000..4e0bdd0ee4f2eb0b4f153112af3bd61e0599ebe4 --- /dev/null +++ b/product/virtio-zephyr/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/virtio-zephyr/include/scmi_agents.h b/product/virtio-zephyr/include/scmi_agents.h new file mode 100644 index 0000000000000000000000000000000000000000..fe8b1202d8a676a4c7d3affaecfe3289f5d6e23d --- /dev/null +++ b/product/virtio-zephyr/include/scmi_agents.h @@ -0,0 +1,38 @@ +/* + * 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 { + /* 0 is reserved for the platform */ + SCMI_AGENT_ID_OSPM = 1, + SCMI_AGENT_ID_PSCI, + SCMI_AGENT_ID_PERF, + SCMI_AGENT_ID_COUNT, +}; + +enum scmi_service_idx { + SCMI_SERVICE_IDX_PSCI, + SCMI_SERVICE_IDX_OSPM_0, + SCMI_SERVICE_IDX_OSPM_1, +#ifdef BUILD_HAS_SCMI_NOTIFICATIONS + SCMI_SERVICE_IDX_OSPM_0_P2A, + SCMI_SERVICE_IDX_OSPM_1_P2A, +#endif + SCMI_SERVICE_IDX_COUNT, +}; + +enum scmi_channel_device_idx { + // TODO: change this: current code support device#0 only + SCMI_CHANNEL_DEVICE_IDX_OSPM_0, + SCMI_CHANNEL_DEVICE_IDX_OSPM_1, + SCMI_CHANNEL_DEVICE_IDX_PSCI, + SCMI_CHANNEL_DEVICE_IDX_COUNT +}; + +#endif /* SCMI_AGENTS_H */ diff --git a/product/virtio-zephyr/module/vppu/CMakeLists.txt b/product/virtio-zephyr/module/vppu/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..c950cbd169b908d168db3b16a61bb6330c7a3a1d --- /dev/null +++ b/product/virtio-zephyr/module/vppu/CMakeLists.txt @@ -0,0 +1,21 @@ +# +# Arm SCP/MCP Software +# Copyright (c) 2022, 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") + +target_sources( + ${SCP_MODULE_TARGET} PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/src/mod_ppu_v0.c" + "${CMAKE_CURRENT_SOURCE_DIR}/src/ppu_v0.c") + +target_link_libraries(${SCP_MODULE_TARGET} PRIVATE module-power-domain) + +if("system-power" IN_LIST SCP_MODULES) + target_link_libraries(${SCP_MODULE_TARGET} PRIVATE module-system-power) +endif() diff --git a/product/virtio-zephyr/module/vppu/Module.cmake b/product/virtio-zephyr/module/vppu/Module.cmake new file mode 100644 index 0000000000000000000000000000000000000000..558e7c273e6ea3e7691cf2a9f46d93d2a1caaf96 --- /dev/null +++ b/product/virtio-zephyr/module/vppu/Module.cmake @@ -0,0 +1,9 @@ +# +# Arm SCP/MCP Software +# Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +set(SCP_MODULE "vppu") +set(SCP_MODULE_TARGET "module-vppu") diff --git a/product/virtio-zephyr/module/vppu/include/mod_ppu_v0.h b/product/virtio-zephyr/module/vppu/include/mod_ppu_v0.h new file mode 100644 index 0000000000000000000000000000000000000000..981562300741c866dcc45523eda4cd1027531df0 --- /dev/null +++ b/product/virtio-zephyr/module/vppu/include/mod_ppu_v0.h @@ -0,0 +1,63 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Description: + * Virtual PPU v0 driver module + */ + +#ifndef MOD_PPU_V0_H +#define MOD_PPU_V0_H + +#include +#include +#include + +/*! + * \addtogroup GroupModules Modules + * @{ + */ + +/*! + * \defgroup GroupModulePPUv0 PPUv0 Driver + * @{ + */ + +/*! + * \brief Power domain PPU descriptor. + */ +struct mod_ppu_v0 { + /*! Base address of the PPU registers */ + uintptr_t reg_base; + + /*! PPU's IRQ number */ + unsigned int irq; +}; + +/*! + * \brief Configuration data of a power domain of the PPU_V0 driver module. + */ +struct mod_ppu_v0_pd_config { + /*! Power domain type */ + enum mod_pd_type pd_type; + + /*! PPU descriptor */ + struct mod_ppu_v0 ppu; + + /*! + * Flag indicating if this domain should be powered on during element init. + */ + bool default_power_on; +}; + +/*! + * @} + */ + +/*! + * @} + */ + +#endif /* MOD_PPU_V0_H */ diff --git a/product/virtio-zephyr/module/vppu/src/mod_ppu_v0.c b/product/virtio-zephyr/module/vppu/src/mod_ppu_v0.c new file mode 100644 index 0000000000000000000000000000000000000000..038a3760acf236f2543eb9aa03588a90901c6a90 --- /dev/null +++ b/product/virtio-zephyr/module/vppu/src/mod_ppu_v0.c @@ -0,0 +1,306 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Description: + * Power State Management PPU v0 driver. + */ + +#include +#include +#include +#include +#include +#include +#include +#if BUILD_HAS_MOD_SYSTEM_POWER +#include +#endif +#include "ppu_v0.h" + +/* Power domain context */ +struct ppu_v0_pd_ctx { + /* Power domain configuration data */ + const struct mod_ppu_v0_pd_config *config; + + /* PPU registers */ + struct ppu_v0_reg *ppu; + + /* Identifier of the entity bound to the power domain driver API */ + fwk_id_t bound_id; + + /* Power module driver input API */ + struct mod_pd_driver_input_api *pd_driver_input_api; +}; + +/* Module context */ +struct ppu_v0_ctx { + /* Table of the power domain contexts */ + struct ppu_v0_pd_ctx *pd_ctx_table; +}; + +/* + * Internal variables + */ + +static struct ppu_v0_ctx ppu_v0_ctx; + +#define MODE_UNSUPPORTED ~0U +static const uint8_t ppu_mode_to_power_state[] = { + [PPU_V0_MODE_ON] = (uint8_t)MOD_PD_STATE_ON, + [PPU_V0_MODE_FUNC_RET] = (uint8_t)MOD_PD_STATE_ON, + [PPU_V0_MODE_MEM_OFF] = (uint8_t)MODE_UNSUPPORTED, + [PPU_V0_MODE_FULL_RET] = (uint8_t)MOD_PD_STATE_ON, + [PPU_V0_MODE_LOGIC_RET] = (uint8_t)MODE_UNSUPPORTED, + [PPU_V0_MODE_MEM_RET] = (uint8_t)MOD_PD_STATE_ON, + [PPU_V0_MODE_OFF] = (uint8_t)MOD_PD_STATE_OFF, + [PPU_V0_MODE_WARM_RESET] = (uint8_t)MODE_UNSUPPORTED, +}; + +/* + * Power domain driver interface + */ + +/* Driver functions not specific to any type of power domain. */ +static int get_state(struct ppu_v0_reg *ppu, unsigned int *state) +{ + enum ppu_v0_mode ppu_mode; + + /* Ensure ppu_mode_to_power_state has an entry for each PPU state */ + static_assert(FWK_ARRAY_SIZE(ppu_mode_to_power_state) == PPU_V0_MODE_COUNT, + "[MOD_PPU_V0] ppu_mode_to_power_state size error"); + + ppu_v0_get_power_mode(ppu, &ppu_mode); + assert(ppu_mode < PPU_V0_MODE_COUNT); + + *state = ppu_mode_to_power_state[ppu_mode]; + if (*state == MODE_UNSUPPORTED) { + FWK_LOG_ERR("[PD] Unexpected PPU mode (%i).\n", ppu_mode); + + return FWK_E_DEVICE; + } + + return FWK_SUCCESS; +} + +static int pd_init(struct ppu_v0_pd_ctx *pd_ctx) +{ + ppu_v0_init(pd_ctx->ppu); + + return FWK_SUCCESS; +} + +static int pd_set_state(fwk_id_t pd_id, unsigned int state) +{ + int status; + struct ppu_v0_pd_ctx *pd_ctx; + + pd_ctx = ppu_v0_ctx.pd_ctx_table + fwk_id_get_element_idx(pd_id); + + fwk_assert(pd_ctx->pd_driver_input_api != NULL); + + switch (state) { + case MOD_PD_STATE_ON: + ppu_v0_set_power_mode(pd_ctx->ppu, PPU_V0_MODE_ON); + status = pd_ctx->pd_driver_input_api->report_power_state_transition( + pd_ctx->bound_id, MOD_PD_STATE_ON); + assert(status == FWK_SUCCESS); + break; + + case MOD_PD_STATE_OFF: + ppu_v0_set_power_mode(pd_ctx->ppu, PPU_V0_MODE_OFF); + status = pd_ctx->pd_driver_input_api->report_power_state_transition( + pd_ctx->bound_id, MOD_PD_STATE_OFF); + assert(status == FWK_SUCCESS); + break; + + default: + FWK_LOG_ERR("[PD] Requested power state (%i) is not supported.\n", state); + return FWK_E_PARAM; + } + + if (status != FWK_SUCCESS) + return FWK_E_PANIC; + + return FWK_SUCCESS; +} + +static int pd_get_state(fwk_id_t pd_id, unsigned int *state) +{ + struct ppu_v0_pd_ctx *pd_ctx; + + pd_ctx = ppu_v0_ctx.pd_ctx_table + fwk_id_get_element_idx(pd_id); + + return get_state(pd_ctx->ppu, state); +} + +static int pd_reset(fwk_id_t pd_id) +{ + int status; + struct ppu_v0_pd_ctx *pd_ctx; + + pd_ctx = ppu_v0_ctx.pd_ctx_table + fwk_id_get_element_idx(pd_id); + + /* Model does not support warm reset at the moment. Using OFF instead. */ + status = ppu_v0_set_power_mode(pd_ctx->ppu, PPU_V0_MODE_OFF); + if (status == FWK_SUCCESS) + status = ppu_v0_set_power_mode(pd_ctx->ppu, PPU_V0_MODE_ON); + + return status; +} + +static int ppu_v0_prepare_core_for_system_suspend(fwk_id_t core_pd_id) +{ + return FWK_SUCCESS; +} + + +static const struct mod_pd_driver_api pd_driver = { + .set_state = pd_set_state, + .get_state = pd_get_state, + .reset = pd_reset, + .prepare_core_for_system_suspend = ppu_v0_prepare_core_for_system_suspend, +}; + +/* + * Framework handlers + */ + +static int ppu_v0_mod_init(fwk_id_t module_id, unsigned int pd_count, + const void *unused) +{ + ppu_v0_ctx.pd_ctx_table = fwk_mm_calloc(pd_count, + sizeof(struct ppu_v0_pd_ctx)); + if (ppu_v0_ctx.pd_ctx_table == NULL) + return FWK_E_NOMEM; + + return FWK_SUCCESS; +} + +static int ppu_v0_pd_init(fwk_id_t pd_id, unsigned int unused, const void *data) +{ + const struct mod_ppu_v0_pd_config *config = data; + struct ppu_v0_pd_ctx *pd_ctx; + int status; + + if (config->pd_type >= MOD_PD_TYPE_COUNT) + return FWK_E_DATA; + + pd_ctx = ppu_v0_ctx.pd_ctx_table + fwk_id_get_element_idx(pd_id); + pd_ctx->config = config; + pd_ctx->ppu = (struct ppu_v0_reg *)(config->ppu.reg_base); + pd_ctx->bound_id = FWK_ID_NONE; + + switch (config->pd_type) { + case MOD_PD_TYPE_DEVICE: + case MOD_PD_TYPE_DEVICE_DEBUG: + case MOD_PD_TYPE_SYSTEM: + status = pd_init(pd_ctx); + if (status != FWK_SUCCESS) + return status; + + if (config->default_power_on) + return ppu_v0_set_power_mode(pd_ctx->ppu, PPU_V0_MODE_ON); + + return FWK_SUCCESS; + + default: + return FWK_E_SUPPORT; + } +} + +static int ppu_v0_bind(fwk_id_t id, unsigned int round) +{ + struct ppu_v0_pd_ctx *pd_ctx; + + /* Nothing to do during the first round of calls where the power module + will bind to the power domains of this module. */ + if (round == 0) + return FWK_SUCCESS; + + /* In the case of the module, nothing to do */ + if (fwk_module_is_valid_module_id(id)) { + return FWK_SUCCESS; + } + + pd_ctx = ppu_v0_ctx.pd_ctx_table + fwk_id_get_element_idx(id); + + if (fwk_id_is_equal(pd_ctx->bound_id, FWK_ID_NONE)) + return FWK_SUCCESS; + + switch (fwk_id_get_module_idx(pd_ctx->bound_id)) { + #if BUILD_HAS_MOD_POWER_DOMAIN + case FWK_MODULE_IDX_POWER_DOMAIN: + return fwk_module_bind(pd_ctx->bound_id, + mod_pd_api_id_driver_input, + &pd_ctx->pd_driver_input_api); + break; + #endif + + #if BUILD_HAS_MOD_SYSTEM_POWER + case FWK_MODULE_IDX_SYSTEM_POWER: + return fwk_module_bind(pd_ctx->bound_id, + mod_system_power_api_id_pd_driver_input, + &pd_ctx->pd_driver_input_api); + break; + #endif + + default: + assert(false); + return FWK_E_SUPPORT; + } +} + +static int ppu_v0_process_bind_request(fwk_id_t source_id, + fwk_id_t target_id, fwk_id_t not_used, + const void **api) +{ + struct ppu_v0_pd_ctx *pd_ctx; + + pd_ctx = ppu_v0_ctx.pd_ctx_table + fwk_id_get_element_idx(target_id); + + switch (pd_ctx->config->pd_type) { + case MOD_PD_TYPE_SYSTEM: + if (!fwk_id_is_equal(pd_ctx->bound_id, FWK_ID_NONE)) { + assert(false); + return FWK_E_ACCESS; + } + /* Fallthrough */ + + case MOD_PD_TYPE_DEVICE: + case MOD_PD_TYPE_DEVICE_DEBUG: + #if BUILD_HAS_MOD_POWER_DOMAIN + if (fwk_id_get_module_idx(source_id) == FWK_MODULE_IDX_POWER_DOMAIN) { + pd_ctx->bound_id = source_id; + *api = &pd_driver; + break; + } + #endif + #if BUILD_HAS_MOD_SYSTEM_POWER + if (fwk_id_get_module_idx(source_id) == FWK_MODULE_IDX_SYSTEM_POWER) { + pd_ctx->bound_id = source_id; + *api = &pd_driver; + break; + } + #endif + assert(false); + return FWK_E_ACCESS; + + default: + (void)pd_driver; + return FWK_E_SUPPORT; + } + + return FWK_SUCCESS; +} + +const struct fwk_module module_vppu = { + .type = FWK_MODULE_TYPE_DRIVER, + .api_count = 1, + .init = ppu_v0_mod_init, + .element_init = ppu_v0_pd_init, + .bind = ppu_v0_bind, + .process_bind_request = ppu_v0_process_bind_request, +}; diff --git a/product/virtio-zephyr/module/vppu/src/ppu_v0.c b/product/virtio-zephyr/module/vppu/src/ppu_v0.c new file mode 100644 index 0000000000000000000000000000000000000000..5a19777a436df95fa8d8d1772d8d17715a594098 --- /dev/null +++ b/product/virtio-zephyr/module/vppu/src/ppu_v0.c @@ -0,0 +1,65 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include "ppu_v0.h" + +void ppu_v0_init(struct ppu_v0_reg *ppu) +{ + assert(ppu != NULL); + + /* Set mode as masked to all input edge interrupts */ + ppu->IESR = 0; + + /* Mask all interrupts */ + ppu->IMR = PPU_V0_IMR_MASK; + + /* Acknowledge any interrupt left pending */ + ppu->ISR = PPU_V0_ISR_MASK; +} + +int ppu_v0_request_power_mode(struct ppu_v0_reg *ppu, enum ppu_v0_mode mode) +{ + uint32_t power_policy; + assert(ppu != NULL); + assert(mode < PPU_V0_MODE_COUNT); + + power_policy = ppu->POWER_POLICY & + ~(PPU_V0_PPR_POLICY | PPU_V0_PPR_DYNAMIC_EN); + ppu->POWER_POLICY = power_policy | mode; + ppu->POWER_STATUS = power_policy | mode; + + return FWK_SUCCESS; +} + +int ppu_v0_set_power_mode(struct ppu_v0_reg *ppu, enum ppu_v0_mode mode) +{ + int status; + assert(ppu != NULL); + + status = ppu_v0_request_power_mode(ppu, mode); + if (status != FWK_SUCCESS) + return status; + + while ((ppu->POWER_STATUS & (PPU_V0_PSR_POWSTAT | PPU_V0_PSR_DYNAMIC)) + != mode) + continue; + + return FWK_SUCCESS; +} + +int ppu_v0_get_power_mode(struct ppu_v0_reg *ppu, enum ppu_v0_mode *mode) +{ + assert(ppu != NULL); + assert(mode != NULL); + + *mode = (enum ppu_v0_mode)(ppu->POWER_STATUS & PPU_V0_PSR_POWSTAT); + + return FWK_SUCCESS; +} diff --git a/product/virtio-zephyr/module/vppu/src/ppu_v0.h b/product/virtio-zephyr/module/vppu/src/ppu_v0.h new file mode 100644 index 0000000000000000000000000000000000000000..fc7fe26b40f2883fdf49fa44f636711942b5bc6f --- /dev/null +++ b/product/virtio-zephyr/module/vppu/src/ppu_v0.h @@ -0,0 +1,144 @@ +/* + * Arm SCP/MCP Software + * Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PPU_V0_H +#define PPU_V0_H + +/*! + * \cond + * @{ + */ + +#include +#include +#include + +struct ppu_v0_reg { + FWK_RW uint32_t POWER_POLICY; + FWK_RW uint32_t POWER_STATUS; + FWK_R uint32_t STATIC_CFG_STATUS; + FWK_R uint32_t DEV_IF_IP_CUR_STATUS; + FWK_R uint32_t MISC_IP_CUR_STATUS; + FWK_R uint32_t STORED_STATUS; + FWK_W uint32_t OFF_MEM_RET_UNLOCK; + uint32_t RESERVED0; + FWK_RW uint32_t POWER_CFG; + uint32_t RESERVED1[3]; + FWK_RW uint32_t IMR; + FWK_RW uint32_t ISR; + FWK_RW uint32_t IESR; + uint32_t RESERVED2[5]; + FWK_RW uint32_t FUNC_RET_RAM_CFG; + FWK_RW uint32_t FULL_RET_RAM_CFG; + FWK_RW uint32_t MEM_RET_RAM_CFG; + uint32_t RESERVED3; + FWK_RW uint32_t MODE_ENTRY_DELAY_TIME_0; + FWK_RW uint32_t MODE_ENTRY_DELAY_TIME_1; + uint32_t RESERVED4[2]; + FWK_RW uint32_t DEV_CONTROL_DELAY_CFG_0; + FWK_RW uint32_t DEV_CONTROL_DELAY_CFG_1; + uint8_t RESERVED5[0xFC8 - 0x78]; + FWK_R uint32_t IMPLEMENTATION_ID; + FWK_R uint32_t ARCHITECTURE_ID; + FWK_R uint32_t PID4; + FWK_R uint32_t PID5; + FWK_R uint32_t PID6; + FWK_R uint32_t PID7; + FWK_R uint32_t PID0; + FWK_R uint32_t PID1; + FWK_R uint32_t PID2; + FWK_R uint32_t PID3; + FWK_R uint32_t CID0; + FWK_R uint32_t CID1; + FWK_R uint32_t CID2; + FWK_R uint32_t CID3; +}; + +enum ppu_v0_mode { + PPU_V0_MODE_OFF = 0, + PPU_V0_MODE_MEM_RET = 1, + PPU_V0_MODE_LOGIC_RET = 2, + PPU_V0_MODE_FULL_RET = 3, + PPU_V0_MODE_MEM_OFF = 4, + PPU_V0_MODE_FUNC_RET = 5, + PPU_V0_MODE_ON = 6, + PPU_V0_MODE_WARM_RESET = 7, + PPU_V0_MODE_COUNT, +}; + +/* + * Bit definitions for PPR + */ +#define PPU_V0_PPR_POLICY UINT32_C(0x00000007) +#define PPU_V0_PPR_DYNAMIC_EN UINT32_C(0x00000100) +#define PPU_V0_PPR_EMULATED_EN UINT32_C(0x00000200) +#define PPU_V0_PPR_OFF_LOCK_EN UINT32_C(0x00001000) + +/* + * Bit definitions for PSR + */ +#define PPU_V0_PSR_EMULATED UINT32_C(0x00000200) +#define PPU_V0_PSR_DYNAMIC UINT32_C(0x00000100) +#define PPU_V0_PSR_POWSTAT UINT32_C(0x00000007) + +/* + * Bit definitions for IMR + */ +#define PPU_V0_IMR_MASK UINT32_C(0x010000FF) +#define PPU_V0_IMR_STA_POLICY_TRN UINT32_C(0x00000001) +#define PPU_V0_IMR_STA_ACCEPT UINT32_C(0x00000002) +#define PPU_V0_IMR_STA_DENY UINT32_C(0x00000004) +#define PPU_V0_IMR_DYN_ACCEPT UINT32_C(0x00000008) +#define PPU_V0_IMR_DYN_DENY UINT32_C(0x00000010) +#define PPU_V0_IMR_EMU_ACCEPT UINT32_C(0x00000020) +#define PPU_V0_IMR_EMU_DENY UINT32_C(0x00000040) +#define PPU_V0_IMR_UNSPT_POLICY UINT32_C(0x00000080) +#define PPU_V0_IMR_DYN_POLICY_MIN UINT32_C(0x01000000) + +/* + * Bit definitions for ISR + */ +#define PPU_V0_ISR_MASK UINT32_C(0x01FF01FF) +#define PPU_V0_ISR_STA_POLICY_TRN UINT32_C(0x00000001) +#define PPU_V0_ISR_STA_ACCEPT UINT32_C(0x00000002) +#define PPU_V0_ISR_STA_DENY UINT32_C(0x00000004) +#define PPU_V0_ISR_DYN_ACCEPT UINT32_C(0x00000008) +#define PPU_V0_ISR_DYN_DENY UINT32_C(0x00000010) +#define PPU_V0_ISR_EMU_ACCEPT UINT32_C(0x00000020) +#define PPU_V0_ISR_EMU_DENY UINT32_C(0x00000040) +#define PPU_V0_ISR_UNSPT_POLICY UINT32_C(0x00000080) +#define PPU_V0_ISR_DBGEMUPWRDWN_EDGE UINT32_C(0x00000100) +#define PPU_V0_ISR_ACTIVE_EDGE UINT32_C(0x00FF0000) +#define PPU_V0_ISR_ACTIVE_EDGE_ACTIVE0 UINT32_C(0x00010000) +#define PPU_V0_ISR_ACTIVE_EDGE_ACTIVE1 UINT32_C(0x00020000) +#define PPU_V0_ISR_ACTIVE_EDGE_ACTIVE2 UINT32_C(0x00040000) +#define PPU_V0_ISR_ACTIVE_EDGE_ACTIVE3 UINT32_C(0x00080000) +#define PPU_V0_ISR_ACTIVE_EDGE_ACTIVE4 UINT32_C(0x00100000) +#define PPU_V0_ISR_ACTIVE_EDGE_ACTIVE5 UINT32_C(0x00200000) +#define PPU_V0_ISR_ACTIVE_EDGE_ACTIVE6 UINT32_C(0x00400000) +#define PPU_V0_ISR_ACTIVE_EDGE_ACTIVE7 UINT32_C(0x00800000) +#define PPU_V0_ISR_DYN_POLICY_MIN UINT32_C(0x01000000) + +/* + * Bit definitions for ARCHITECTURE_ID + */ +#define PPU_V0_ARCHITECTURE_ID UINT32_C(0x00000000) + +/* + * Interface + */ +void ppu_v0_init(struct ppu_v0_reg *ppu); +int ppu_v0_request_power_mode(struct ppu_v0_reg *ppu, enum ppu_v0_mode mode); +int ppu_v0_set_power_mode(struct ppu_v0_reg *ppu, enum ppu_v0_mode mode); +int ppu_v0_get_power_mode(struct ppu_v0_reg *ppu, enum ppu_v0_mode *mode); + +/*! + * \endcond + * @} + */ + +#endif /* PPU_V0_H */ diff --git a/tools/check_copyright.py b/tools/check_copyright.py index dd148118f0124e5697aacbe851440182e7e53082..2125c2ea16b748bdd92a9c095477184c6e0e84fc 100755 --- a/tools/check_copyright.py +++ b/tools/check_copyright.py @@ -62,9 +62,9 @@ FILE_TYPES = [ # Supported comment styles (Python regex) # COMMENT_PATTERN = '^(( \\*)|(;)|(\\#))' -COMPANY_PATTERN = '(Arm|Renesas)' +COMPANY_PATTERN = '(Arm|Renesas|Linaro)' COMPANY_FULL_NAME_PATTERN = \ - '(Arm Limited and Contributors|Renesas Electronics Corporation)' + '(Arm Limited and Contributors|Renesas Electronics Corporation|Linaro Limited and Contributors)' # # git command using diff-filter to include Added (A), Copied (C), Modified (M), diff --git a/tools/cppcheck_suppress_list.txt b/tools/cppcheck_suppress_list.txt index ddde2008df774e2218351f119e529925aae04937..d2f2a8bfdf97a5cf9fe798716b10292f5189979d 100755 --- a/tools/cppcheck_suppress_list.txt +++ b/tools/cppcheck_suppress_list.txt @@ -96,7 +96,7 @@ zerodivcond:*product/juno/module/juno_cdcel937/src/mod_juno_cdcel937.c:414 syntaxError:*arch/arm/armv8-a/include/arch_system.h:19 // Cppcheck is not able to parse returned boolean values inside if conditions -internalAstError:*framework/src/fwk_core.c:295 +internalAstError:*framework/src/fwk_core.c:356 // These assignments are used for testing constArgument:*framework/test/test_fwk_macros.c