1 /*
2 * Copyright (c) 2024 Nordic Semiconductor ASA
3 * SPDX-License-Identifier: Apache-2.0
4 */
5
6 #define DT_DRV_COMPAT nordic_nrf_vpr_coprocessor
7
8 #include <string.h>
9
10 #include <zephyr/devicetree.h>
11 #include <zephyr/init.h>
12 #include <zephyr/logging/log.h>
13 #include <zephyr/sys/util.h>
14 #include <zephyr/toolchain.h>
15
16 #include <hal/nrf_vpr.h>
17 #if defined(CONFIG_SOC_NRF54L_CPUAPP_COMMON) && !defined(CONFIG_TRUSTED_EXECUTION_NONSECURE)
18 #include <hal/nrf_spu.h>
19 #endif
20
21 LOG_MODULE_REGISTER(nordic_vpr_launcher, CONFIG_NORDIC_VPR_LAUNCHER_LOG_LEVEL);
22
23 struct nordic_vpr_launcher_config {
24 NRF_VPR_Type *vpr;
25 uintptr_t exec_addr;
26 #if DT_ANY_INST_HAS_PROP_STATUS_OKAY(source_memory)
27 uintptr_t src_addr;
28 size_t size;
29 #endif
30 };
31
nordic_vpr_launcher_init(const struct device * dev)32 static int nordic_vpr_launcher_init(const struct device *dev)
33 {
34 const struct nordic_vpr_launcher_config *config = dev->config;
35
36 #if DT_ANY_INST_HAS_PROP_STATUS_OKAY(source_memory)
37 if (config->size > 0U) {
38 LOG_DBG("Loading VPR (%p) from %p to %p (%zu bytes)", config->vpr,
39 (void *)config->src_addr, (void *)config->exec_addr, config->size);
40 memcpy((void *)config->exec_addr, (void *)config->src_addr, config->size);
41 }
42 #endif
43
44 #if defined(CONFIG_SOC_NRF54L_CPUAPP_COMMON) && !defined(CONFIG_TRUSTED_EXECUTION_NONSECURE)
45 nrf_spu_periph_perm_secattr_set(NRF_SPU00, nrf_address_slave_get((uint32_t)config->vpr),
46 true);
47 #endif
48 LOG_DBG("Launching VPR (%p) from %p", config->vpr, (void *)config->exec_addr);
49 nrf_vpr_initpc_set(config->vpr, config->exec_addr);
50 nrf_vpr_cpurun_set(config->vpr, true);
51
52 return 0;
53 }
54
55 /* obtain VPR address either from memory or partition */
56 #define VPR_ADDR(node_id) \
57 (DT_REG_ADDR(node_id) + \
58 COND_CODE_0(DT_FIXED_PARTITION_EXISTS(node_id), (0), (DT_REG_ADDR(DT_GPARENT(node_id)))))
59
60 #define NORDIC_VPR_LAUNCHER_DEFINE(inst) \
61 IF_ENABLED(DT_INST_NODE_HAS_PROP(inst, source_memory), \
62 (BUILD_ASSERT((DT_REG_SIZE(DT_INST_PHANDLE(inst, execution_memory)) <= \
63 DT_REG_SIZE(DT_INST_PHANDLE(inst, source_memory))), \
64 "Execution memory exceeds source memory size");)) \
65 \
66 static const struct nordic_vpr_launcher_config config##inst = { \
67 .vpr = (NRF_VPR_Type *)DT_INST_REG_ADDR(inst), \
68 .exec_addr = VPR_ADDR(DT_INST_PHANDLE(inst, execution_memory)), \
69 IF_ENABLED(DT_INST_NODE_HAS_PROP(inst, source_memory), \
70 (.src_addr = VPR_ADDR(DT_INST_PHANDLE(inst, source_memory)), \
71 .size = DT_REG_SIZE(DT_INST_PHANDLE(inst, execution_memory)),))}; \
72 \
73 DEVICE_DT_INST_DEFINE(inst, nordic_vpr_launcher_init, NULL, NULL, &config##inst, \
74 POST_KERNEL, CONFIG_NORDIC_VPR_LAUNCHER_INIT_PRIORITY, NULL);
75
76 DT_INST_FOREACH_STATUS_OKAY(NORDIC_VPR_LAUNCHER_DEFINE)
77