drivers: firmware: nrf_ironside: add IRONside CPUCONF service

Add an IPC service API for booting local domain cores.

Signed-off-by: Sebastian Bøe <sebastian.boe@nordicsemi.no>
Signed-off-by: Jonathan Nilsen <jonathan.nilsen@nordicsemi.no>
This commit is contained in:
Sebastian Bøe 2025-05-01 11:49:18 +02:00 committed by Benjamin Cabé
commit 14a47cbe05
4 changed files with 147 additions and 0 deletions

View file

@ -4,3 +4,5 @@
zephyr_library() zephyr_library()
zephyr_library_sources_ifdef(CONFIG_NRF_IRONSIDE_CALL call.c) zephyr_library_sources_ifdef(CONFIG_NRF_IRONSIDE_CALL call.c)
zephyr_library_sources_ifdef(CONFIG_NRF_IRONSIDE_CPUCONF_SERVICE cpuconf.c)

View file

@ -26,3 +26,15 @@ config NRF_IRONSIDE_CALL_INIT_PRIORITY
but higher than the priority of any feature that selects NRF_IRONSIDE_CALL. but higher than the priority of any feature that selects NRF_IRONSIDE_CALL.
endif # 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

View file

@ -0,0 +1,59 @@
/*
* Copyright (c) 2025 Nordic Semiconductor ASA
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdint.h>
#include <stdbool.h>
#include <zephyr/sys/util.h>
#include <zephyr/kernel.h>
#include <zephyr/drivers/firmware/nrf_ironside/call.h>
#include <zephyr/drivers/firmware/nrf_ironside/cpuconf.h>
#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;
}

View file

@ -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 <stdbool.h>
#include <stddef.h>
#include <zephyr/drivers/firmware/nrf_ironside/call.h>
#include <zephyr/toolchain/common.h>
#include <nrf.h>
/**
* @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_ */