diff --git a/drivers/firmware/nrf_ironside/CMakeLists.txt b/drivers/firmware/nrf_ironside/CMakeLists.txt index 90320c62df5..8f31acfef00 100644 --- a/drivers/firmware/nrf_ironside/CMakeLists.txt +++ b/drivers/firmware/nrf_ironside/CMakeLists.txt @@ -4,3 +4,5 @@ zephyr_library() zephyr_library_sources_ifdef(CONFIG_NRF_IRONSIDE_CALL call.c) + +zephyr_library_sources_ifdef(CONFIG_NRF_IRONSIDE_CPUCONF_SERVICE cpuconf.c) diff --git a/drivers/firmware/nrf_ironside/Kconfig b/drivers/firmware/nrf_ironside/Kconfig index 20545669e92..86c94d3a2ad 100644 --- a/drivers/firmware/nrf_ironside/Kconfig +++ b/drivers/firmware/nrf_ironside/Kconfig @@ -26,3 +26,15 @@ config NRF_IRONSIDE_CALL_INIT_PRIORITY but higher than the priority of any feature that selects NRF_IRONSIDE_CALL. endif # NRF_IRONSIDE_CALL + +menu "Nordic IRONside services" + depends on SOC_NRF54H20_IRON + +config NRF_IRONSIDE_CPUCONF_SERVICE + bool "IRONside CPUCONF service" + depends on SOC_NRF54H20_CPUAPP + select NRF_IRONSIDE_CALL + help + Service used to boot local domain cores. + +endmenu diff --git a/drivers/firmware/nrf_ironside/cpuconf.c b/drivers/firmware/nrf_ironside/cpuconf.c new file mode 100644 index 00000000000..a8377ae0f93 --- /dev/null +++ b/drivers/firmware/nrf_ironside/cpuconf.c @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#include +#include + +#include +#include + +#define CPU_PARAMS_CPU_OFFSET (0) +#define CPU_PARAMS_CPU_MASK (0xF) +#define CPU_PARAMS_WAIT_BIT BIT(4) + +int ironside_cpuconf(NRF_PROCESSORID_Type cpu, const void *vector_table, bool cpu_wait, + const uint8_t *msg, size_t msg_size) +{ + int err; + struct ironside_call_buf *buf; + uint8_t *buf_msg; + + if (msg_size > IRONSIDE_CPUCONF_SERVICE_MSG_MAX_SIZE) { + return -IRONSIDE_CPUCONF_ERROR_MESSAGE_TOO_LARGE; + } + + buf = ironside_call_alloc(); + + buf->id = IRONSIDE_CALL_ID_CPUCONF_V0; + + buf->args[IRONSIDE_CPUCONF_SERVICE_CPU_PARAMS_IDX] = + (((uint32_t)cpu << CPU_PARAMS_CPU_OFFSET) & CPU_PARAMS_CPU_MASK) | + (cpu_wait ? CPU_PARAMS_WAIT_BIT : 0); + + buf->args[IRONSIDE_CPUCONF_SERVICE_VECTOR_TABLE_IDX] = (uint32_t)vector_table; + + buf_msg = (uint8_t *)&buf->args[IRONSIDE_CPUCONF_SERVICE_MSG_0]; + if (msg_size > 0) { + memcpy(buf_msg, msg, msg_size); + } + if (msg_size < IRONSIDE_CPUCONF_SERVICE_MSG_MAX_SIZE) { + memset(&buf_msg[msg_size], 0, IRONSIDE_CPUCONF_SERVICE_MSG_MAX_SIZE - msg_size); + } + + ironside_call_dispatch(buf); + + if (buf->status == IRONSIDE_CALL_STATUS_RSP_SUCCESS) { + err = buf->args[IRONSIDE_CPUCONF_SERVICE_RETCODE_IDX]; + } else { + err = buf->status; + } + + ironside_call_release(buf); + + return err; +} diff --git a/include/zephyr/drivers/firmware/nrf_ironside/cpuconf.h b/include/zephyr/drivers/firmware/nrf_ironside/cpuconf.h new file mode 100644 index 00000000000..e6f2150b6e2 --- /dev/null +++ b/include/zephyr/drivers/firmware/nrf_ironside/cpuconf.h @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_ZEPHYR_DRIVERS_FIRMWARE_NRF_IRONSIDE_CPUCONF_H_ +#define ZEPHYR_INCLUDE_ZEPHYR_DRIVERS_FIRMWARE_NRF_IRONSIDE_CPUCONF_H_ + +#include +#include +#include +#include +#include + +/** + * @name CPUCONF service error codes. + * @{ + */ + +/** An invalid or unsupported processor ID was specified. */ +#define IRONSIDE_CPUCONF_ERROR_WRONG_CPU (1) +/** The boot message is too large to fit in the buffer. */ +#define IRONSIDE_CPUCONF_ERROR_MESSAGE_TOO_LARGE (2) + +/** + * @} + */ + +#define IRONSIDE_CALL_ID_CPUCONF_V0 2 + +enum { + IRONSIDE_CPUCONF_SERVICE_CPU_PARAMS_IDX, + IRONSIDE_CPUCONF_SERVICE_VECTOR_TABLE_IDX, + IRONSIDE_CPUCONF_SERVICE_MSG_0, + IRONSIDE_CPUCONF_SERVICE_MSG_1, + IRONSIDE_CPUCONF_SERVICE_MSG_2, + IRONSIDE_CPUCONF_SERVICE_MSG_3, + /* The last enum value is reserved for the number of arguments */ + IRONSIDE_CPUCONF_NUM_ARGS +}; + +/* Maximum size of the CPUCONF message parameter. */ +#define IRONSIDE_CPUCONF_SERVICE_MSG_MAX_SIZE (4 * sizeof(uint32_t)) + +/* IDX 0 is re-used by the error return code and the 'cpu' parameter. */ +#define IRONSIDE_CPUCONF_SERVICE_RETCODE_IDX 0 + +BUILD_ASSERT(IRONSIDE_CPUCONF_NUM_ARGS <= NRF_IRONSIDE_CALL_NUM_ARGS); + +/** + * @brief Boot a local domain CPU + * + * @param cpu The CPU to be booted + * @param vector_table Pointer to the vector table used to boot the CPU. + * @param cpu_wait When this is true, the CPU will WAIT even if the CPU has clock. + * @param msg A message that can be placed in radiocore's boot report. + * @param msg_size Size of the message in bytes. + * + * @note cpu_wait is only intended to be enabled for debug purposes + * and it is only supported that a debugger resumes the CPU. + * + * @note the call always sends IRONSIDE_CPUCONF_SERVICE_MSG_MAX_SIZE message bytes. + * If the given msg_size is less than that, the remaining bytes are set to zero. + * + * @retval 0 on success or if the CPU has already booted. + * @retval Positive non-0 error status if reported by IRONside call. + * @retval -IRONSIDE_CPUCONF_ERROR_WRONG_CPU if cpu is unrecognized + * @retval -IRONSIDE_CPUCONF_ERROR_MESSAGE_TOO_LARGE if msg_size is greater than + * IRONSIDE_CPUCONF_SERVICE_MSG_MAX_SIZE. + */ +int ironside_cpuconf(NRF_PROCESSORID_Type cpu, const void *vector_table, bool cpu_wait, + const uint8_t *msg, size_t msg_size); + +#endif /* ZEPHYR_INCLUDE_ZEPHYR_DRIVERS_FIRMWARE_NRF_IRONSIDE_CPUCONF_H_ */