blob: e314577a3aa0a4d8585d4dfe5afe8f3aebdc098f [file] [log] [blame]
Mikael Olsson7da66192021-02-12 17:30:22 +01001/*
Joshua Pimm6bc80672022-10-19 15:46:27 +01002 * Copyright (c) 2021-2023, Arm Limited. All rights reserved.
Mikael Olsson7da66192021-02-12 17:30:22 +01003 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#include <stdint.h>
8#include <stdbool.h>
9
10#include <common/debug.h>
11#include <common/runtime_svc.h>
12#include <drivers/arm/ethosn.h>
13#include <drivers/delay_timer.h>
14#include <lib/mmio.h>
Mikael Olsson3288b462022-08-15 17:12:58 +020015#include <lib/utils_def.h>
Mikael Olsson7da66192021-02-12 17:30:22 +010016#include <plat/arm/common/fconf_ethosn_getter.h>
17
Rajasekaran Kalidossf8a18b82022-11-16 17:16:44 +010018#include <platform_def.h>
19
Mikael Olssona7df0d62023-01-13 09:56:41 +010020#if ARM_ETHOSN_NPU_TZMP1
21#include "ethosn_big_fw.h"
22#endif
23
Laurent Carlier5205df22021-09-16 15:10:35 +010024/*
Mikael Olsson3288b462022-08-15 17:12:58 +020025 * Number of Arm(R) Ethos(TM)-N NPU (NPU) devices available
Laurent Carlier5205df22021-09-16 15:10:35 +010026 */
Mikael Olsson3288b462022-08-15 17:12:58 +020027#define ETHOSN_NUM_DEVICES \
28 FCONF_GET_PROPERTY(hw_config, ethosn_config, num_devices)
Mikael Olsson7da66192021-02-12 17:30:22 +010029
Mikael Olsson3288b462022-08-15 17:12:58 +020030#define ETHOSN_GET_DEVICE(dev_idx) \
31 FCONF_GET_PROPERTY(hw_config, ethosn_device, dev_idx)
Mikael Olsson7da66192021-02-12 17:30:22 +010032
33/* NPU core sec registry address */
34#define ETHOSN_CORE_SEC_REG(core_addr, reg_offset) \
35 (core_addr + reg_offset)
36
37/* Reset timeout in us */
38#define ETHOSN_RESET_TIMEOUT_US U(10 * 1000 * 1000)
39#define ETHOSN_RESET_WAIT_US U(1)
40
41#define SEC_DEL_REG U(0x0004)
42#define SEC_DEL_VAL U(0x81C)
43#define SEC_DEL_EXCC_MASK U(0x20)
44
45#define SEC_SECCTLR_REG U(0x0010)
Mikael Olssonbfd9da72023-01-11 10:36:22 +010046/* Set bit[10] = 1 to workaround erratum 2838783 */
47#define SEC_SECCTLR_VAL U(0x403)
Mikael Olsson7da66192021-02-12 17:30:22 +010048
Mikael Olsson7da66192021-02-12 17:30:22 +010049#define SEC_DEL_ADDR_EXT_REG U(0x201C)
50#define SEC_DEL_ADDR_EXT_VAL U(0x15)
51
52#define SEC_SYSCTRL0_REG U(0x0018)
Mikael Olsson47675f22022-11-04 15:01:02 +010053#define SEC_SYSCTRL0_SLEEPING U(1U << 4)
Mikael Olsson7da66192021-02-12 17:30:22 +010054#define SEC_SYSCTRL0_SOFT_RESET U(3U << 29)
55#define SEC_SYSCTRL0_HARD_RESET U(1U << 31)
56
Rajasekaran Kalidossf8a18b82022-11-16 17:16:44 +010057#define SEC_NSAID_REG_BASE U(0x3004)
58#define SEC_NSAID_OFFSET U(0x1000)
59
Mikael Olsson3288b462022-08-15 17:12:58 +020060#define SEC_MMUSID_REG_BASE U(0x3008)
61#define SEC_MMUSID_OFFSET U(0x1000)
62
Mikael Olssona7df0d62023-01-13 09:56:41 +010063#define SEC_NPU_ID_REG U(0xF000)
64#define SEC_NPU_ID_ARCH_VER_SHIFT U(0X10)
65
Rajasekaran Kalidossf8a18b82022-11-16 17:16:44 +010066#define INPUT_STREAM_INDEX U(0x6)
67#define INTERMEDIATE_STREAM_INDEX U(0x7)
68#define OUTPUT_STREAM_INDEX U(0x8)
69
Mikael Olssona7df0d62023-01-13 09:56:41 +010070#if ARM_ETHOSN_NPU_TZMP1
71CASSERT(ARM_ETHOSN_NPU_FW_IMAGE_BASE > 0U, assert_ethosn_invalid_fw_image_base);
72static const struct ethosn_big_fw *big_fw;
73#endif
74
Mikael Olsson3288b462022-08-15 17:12:58 +020075static bool ethosn_get_device_and_core(uintptr_t core_addr,
76 const struct ethosn_device_t **dev_match,
77 const struct ethosn_core_t **core_match)
Laurent Carlier5205df22021-09-16 15:10:35 +010078{
Mikael Olsson3288b462022-08-15 17:12:58 +020079 uint32_t dev_idx;
80 uint32_t core_idx;
81
82 for (dev_idx = 0U; dev_idx < ETHOSN_NUM_DEVICES; ++dev_idx) {
83 const struct ethosn_device_t *dev = ETHOSN_GET_DEVICE(dev_idx);
84
85 for (core_idx = 0U; core_idx < dev->num_cores; ++core_idx) {
86 const struct ethosn_core_t *core = &(dev->cores[core_idx]);
87
88 if (core->addr == core_addr) {
89 *dev_match = dev;
90 *core_match = core;
91 return true;
92 }
Laurent Carlier5205df22021-09-16 15:10:35 +010093 }
94 }
95
Mikael Olsson3288b462022-08-15 17:12:58 +020096 WARN("ETHOSN: Unknown core address given to SMC call.\n");
Laurent Carlier5205df22021-09-16 15:10:35 +010097 return false;
98}
99
Rajasekaran Kalidossf8a18b82022-11-16 17:16:44 +0100100#if ARM_ETHOSN_NPU_TZMP1
Mikael Olssona7df0d62023-01-13 09:56:41 +0100101static uint32_t ethosn_core_read_arch_version(uintptr_t core_addr)
102{
103 uint32_t npu_id = mmio_read_32(ETHOSN_CORE_SEC_REG(core_addr,
104 SEC_NPU_ID_REG));
105
106 return (npu_id >> SEC_NPU_ID_ARCH_VER_SHIFT);
107}
108
Rajasekaran Kalidossf8a18b82022-11-16 17:16:44 +0100109static void ethosn_configure_stream_nsaid(const struct ethosn_core_t *core,
110 bool is_protected)
111{
112 size_t i;
113 uint32_t streams[9] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
114
115 if (is_protected) {
116 streams[INPUT_STREAM_INDEX] = ARM_ETHOSN_NPU_PROT_DATA_NSAID;
117 streams[INTERMEDIATE_STREAM_INDEX] =
118 ARM_ETHOSN_NPU_PROT_DATA_NSAID;
119 streams[OUTPUT_STREAM_INDEX] = ARM_ETHOSN_NPU_PROT_DATA_NSAID;
120 }
121
122 for (i = 0U; i < ARRAY_SIZE(streams); ++i) {
123 const uintptr_t reg_addr = SEC_NSAID_REG_BASE +
124 (SEC_NSAID_OFFSET * i);
125 mmio_write_32(ETHOSN_CORE_SEC_REG(core->addr, reg_addr),
126 streams[i]);
127 }
128}
129#endif
130
Mikael Olsson3288b462022-08-15 17:12:58 +0200131static void ethosn_configure_smmu_streams(const struct ethosn_device_t *device,
132 const struct ethosn_core_t *core,
133 uint32_t asset_alloc_idx)
134{
135 const struct ethosn_main_allocator_t *main_alloc =
136 &(core->main_allocator);
137 const struct ethosn_asset_allocator_t *asset_alloc =
138 &(device->asset_allocators[asset_alloc_idx]);
139 const uint32_t streams[9] = {
140 main_alloc->firmware.stream_id,
141 main_alloc->working_data.stream_id,
142 asset_alloc->command_stream.stream_id,
143 0U, /* Not used*/
144 main_alloc->firmware.stream_id,
145 asset_alloc->weight_data.stream_id,
146 asset_alloc->buffer_data.stream_id,
147 asset_alloc->intermediate_data.stream_id,
148 asset_alloc->buffer_data.stream_id
149 };
150 size_t i;
151
152 for (i = 0U; i < ARRAY_SIZE(streams); ++i) {
153 const uintptr_t reg_addr = SEC_MMUSID_REG_BASE +
154 (SEC_MMUSID_OFFSET * i);
155 mmio_write_32(ETHOSN_CORE_SEC_REG(core->addr, reg_addr),
156 streams[i]);
157 }
158}
159
Mikael Olsson7da66192021-02-12 17:30:22 +0100160static void ethosn_delegate_to_ns(uintptr_t core_addr)
161{
162 mmio_setbits_32(ETHOSN_CORE_SEC_REG(core_addr, SEC_SECCTLR_REG),
163 SEC_SECCTLR_VAL);
164
165 mmio_setbits_32(ETHOSN_CORE_SEC_REG(core_addr, SEC_DEL_REG),
166 SEC_DEL_VAL);
167
Mikael Olsson7da66192021-02-12 17:30:22 +0100168 mmio_setbits_32(ETHOSN_CORE_SEC_REG(core_addr, SEC_DEL_ADDR_EXT_REG),
169 SEC_DEL_ADDR_EXT_VAL);
170}
171
Laurent Carlier5205df22021-09-16 15:10:35 +0100172static int ethosn_is_sec(uintptr_t core_addr)
Mikael Olsson7da66192021-02-12 17:30:22 +0100173{
Laurent Carlier5205df22021-09-16 15:10:35 +0100174 if ((mmio_read_32(ETHOSN_CORE_SEC_REG(core_addr, SEC_DEL_REG))
Mikael Olsson7da66192021-02-12 17:30:22 +0100175 & SEC_DEL_EXCC_MASK) != 0U) {
176 return 0;
177 }
178
179 return 1;
180}
181
Mikael Olsson47675f22022-11-04 15:01:02 +0100182static int ethosn_core_is_sleeping(uintptr_t core_addr)
183{
184 const uintptr_t sysctrl0_reg =
185 ETHOSN_CORE_SEC_REG(core_addr, SEC_SYSCTRL0_REG);
186 const uint32_t sleeping_mask = SEC_SYSCTRL0_SLEEPING;
187
188 return ((mmio_read_32(sysctrl0_reg) & sleeping_mask) == sleeping_mask);
189}
190
Mikael Olsson7da66192021-02-12 17:30:22 +0100191static bool ethosn_reset(uintptr_t core_addr, int hard_reset)
192{
193 unsigned int timeout;
194 const uintptr_t sysctrl0_reg =
195 ETHOSN_CORE_SEC_REG(core_addr, SEC_SYSCTRL0_REG);
196 const uint32_t reset_val = (hard_reset != 0) ? SEC_SYSCTRL0_HARD_RESET
197 : SEC_SYSCTRL0_SOFT_RESET;
198
199 mmio_write_32(sysctrl0_reg, reset_val);
200
201 /* Wait for reset to complete */
202 for (timeout = 0U; timeout < ETHOSN_RESET_TIMEOUT_US;
203 timeout += ETHOSN_RESET_WAIT_US) {
204
205 if ((mmio_read_32(sysctrl0_reg) & reset_val) == 0U) {
206 break;
207 }
208
209 udelay(ETHOSN_RESET_WAIT_US);
210 }
211
212 return timeout < ETHOSN_RESET_TIMEOUT_US;
213}
214
215uintptr_t ethosn_smc_handler(uint32_t smc_fid,
Laurent Carlier5205df22021-09-16 15:10:35 +0100216 u_register_t core_addr,
Mikael Olsson3288b462022-08-15 17:12:58 +0200217 u_register_t asset_alloc_idx,
Joshua Pimm6bc80672022-10-19 15:46:27 +0100218 u_register_t reset_type,
Rajasekaran Kalidossf8a18b82022-11-16 17:16:44 +0100219 u_register_t is_protected,
Mikael Olsson7da66192021-02-12 17:30:22 +0100220 void *cookie,
221 void *handle,
222 u_register_t flags)
223{
Mikael Olsson7da66192021-02-12 17:30:22 +0100224 int hard_reset = 0;
Mikael Olsson3288b462022-08-15 17:12:58 +0200225 const struct ethosn_device_t *device = NULL;
226 const struct ethosn_core_t *core = NULL;
Laurent Carlier5205df22021-09-16 15:10:35 +0100227 const uint32_t fid = smc_fid & FUNCID_NUM_MASK;
Mikael Olsson7da66192021-02-12 17:30:22 +0100228
229 /* Only SiP fast calls are expected */
230 if ((GET_SMC_TYPE(smc_fid) != SMC_TYPE_FAST) ||
231 (GET_SMC_OEN(smc_fid) != OEN_SIP_START)) {
232 SMC_RET1(handle, SMC_UNK);
233 }
234
235 /* Truncate parameters to 32-bits for SMC32 */
236 if (GET_SMC_CC(smc_fid) == SMC_32) {
Laurent Carlier5205df22021-09-16 15:10:35 +0100237 core_addr &= 0xFFFFFFFF;
Mikael Olsson3288b462022-08-15 17:12:58 +0200238 asset_alloc_idx &= 0xFFFFFFFF;
Joshua Pimm6bc80672022-10-19 15:46:27 +0100239 reset_type &= 0xFFFFFFFF;
Rajasekaran Kalidossf8a18b82022-11-16 17:16:44 +0100240 is_protected &= 0xFFFFFFFF;
Mikael Olsson7da66192021-02-12 17:30:22 +0100241 }
242
Mikael Olsson47675f22022-11-04 15:01:02 +0100243 if (!is_ethosn_fid(smc_fid) || (fid > ETHOSN_FNUM_IS_SLEEPING)) {
Mikael Olsson3288b462022-08-15 17:12:58 +0200244 WARN("ETHOSN: Unknown SMC call: 0x%x\n", smc_fid);
Mikael Olsson7da66192021-02-12 17:30:22 +0100245 SMC_RET1(handle, SMC_UNK);
246 }
247
Laurent Carlier5205df22021-09-16 15:10:35 +0100248 /* Commands that do not require a valid core address */
249 switch (fid) {
Mikael Olsson7da66192021-02-12 17:30:22 +0100250 case ETHOSN_FNUM_VERSION:
251 SMC_RET2(handle, ETHOSN_VERSION_MAJOR, ETHOSN_VERSION_MINOR);
Laurent Carlier5205df22021-09-16 15:10:35 +0100252 }
253
Mikael Olsson3288b462022-08-15 17:12:58 +0200254 if (!ethosn_get_device_and_core(core_addr, &device, &core)) {
Laurent Carlier5205df22021-09-16 15:10:35 +0100255 SMC_RET1(handle, ETHOSN_UNKNOWN_CORE_ADDRESS);
256 }
257
Mikael Olsson3288b462022-08-15 17:12:58 +0200258 /* Commands that require a valid core address */
Laurent Carlier5205df22021-09-16 15:10:35 +0100259 switch (fid) {
Mikael Olsson7da66192021-02-12 17:30:22 +0100260 case ETHOSN_FNUM_IS_SEC:
Mikael Olsson3288b462022-08-15 17:12:58 +0200261 SMC_RET1(handle, ethosn_is_sec(core->addr));
Mikael Olsson47675f22022-11-04 15:01:02 +0100262 case ETHOSN_FNUM_IS_SLEEPING:
263 SMC_RET1(handle, ethosn_core_is_sleeping(core->addr));
Mikael Olsson3288b462022-08-15 17:12:58 +0200264 }
265
266 if (!device->has_reserved_memory &&
267 asset_alloc_idx >= device->num_allocators) {
268 WARN("ETHOSN: Unknown asset allocator index given to SMC call.\n");
269 SMC_RET1(handle, ETHOSN_UNKNOWN_ALLOCATOR_IDX);
270 }
271
Joshua Pimm6bc80672022-10-19 15:46:27 +0100272 if (reset_type > ETHOSN_RESET_TYPE_HALT) {
273 WARN("ETHOSN: Invalid reset type given to SMC call.\n");
274 SMC_RET1(handle, ETHOSN_INVALID_PARAMETER);
275 }
276
277 /*
278 * Commands that require a valid device, reset type,
279 * core and asset allocator
280 */
Mikael Olsson3288b462022-08-15 17:12:58 +0200281 switch (fid) {
Mikael Olsson7da66192021-02-12 17:30:22 +0100282 case ETHOSN_FNUM_HARD_RESET:
283 hard_reset = 1;
284 /* Fallthrough */
285 case ETHOSN_FNUM_SOFT_RESET:
Mikael Olsson3288b462022-08-15 17:12:58 +0200286 if (!ethosn_reset(core->addr, hard_reset)) {
Mikael Olsson7da66192021-02-12 17:30:22 +0100287 SMC_RET1(handle, ETHOSN_FAILURE);
288 }
Mikael Olsson3288b462022-08-15 17:12:58 +0200289
Joshua Pimm6bc80672022-10-19 15:46:27 +0100290 if (reset_type == ETHOSN_RESET_TYPE_FULL) {
291 if (!device->has_reserved_memory) {
292 ethosn_configure_smmu_streams(device, core,
293 asset_alloc_idx);
Rajasekaran Kalidossf8a18b82022-11-16 17:16:44 +0100294
295 #if ARM_ETHOSN_NPU_TZMP1
296 ethosn_configure_stream_nsaid(core,
297 is_protected);
298 #endif
Joshua Pimm6bc80672022-10-19 15:46:27 +0100299 }
Mikael Olsson3288b462022-08-15 17:12:58 +0200300
Joshua Pimm6bc80672022-10-19 15:46:27 +0100301 ethosn_delegate_to_ns(core->addr);
302 }
Mikael Olsson7da66192021-02-12 17:30:22 +0100303 SMC_RET1(handle, ETHOSN_SUCCESS);
304 default:
Mikael Olsson3288b462022-08-15 17:12:58 +0200305 WARN("ETHOSN: Unimplemented SMC call: 0x%x\n", fid);
Mikael Olsson7da66192021-02-12 17:30:22 +0100306 SMC_RET1(handle, SMC_UNK);
307 }
308}
Mikael Olsson461bf7d2023-01-18 18:05:15 +0100309
310int ethosn_smc_setup(void)
311{
Mikael Olssona7df0d62023-01-13 09:56:41 +0100312#if ARM_ETHOSN_NPU_TZMP1
313 struct ethosn_device_t *dev;
314 uint32_t arch_ver;
315#endif
316
Mikael Olsson461bf7d2023-01-18 18:05:15 +0100317 if (ETHOSN_NUM_DEVICES == 0U) {
318 ERROR("ETHOSN: No NPU found\n");
319 return ETHOSN_FAILURE;
320 }
321
Mikael Olssona7df0d62023-01-13 09:56:41 +0100322#if ARM_ETHOSN_NPU_TZMP1
323
324 /* Only one NPU core is supported in the TZMP1 setup */
325 if ((ETHOSN_NUM_DEVICES != 1U) ||
326 (ETHOSN_GET_DEVICE(0U)->num_cores != 1U)) {
327 ERROR("ETHOSN: TZMP1 doesn't support multiple NPU cores\n");
328 return ETHOSN_FAILURE;
329 }
330
331 dev = ETHOSN_GET_DEVICE(0U);
332 arch_ver = ethosn_core_read_arch_version(dev->cores[0U].addr);
333 big_fw = (struct ethosn_big_fw *)ARM_ETHOSN_NPU_FW_IMAGE_BASE;
334
335 if (!ethosn_big_fw_verify_header(big_fw, arch_ver)) {
336 return ETHOSN_FAILURE;
337 }
338
339 NOTICE("ETHOSN: TZMP1 setup succeeded with firmware version %u.%u.%u\n",
340 big_fw->fw_ver_major, big_fw->fw_ver_minor,
341 big_fw->fw_ver_patch);
342#else
343 NOTICE("ETHOSN: Setup succeeded\n");
344#endif
345
Mikael Olsson461bf7d2023-01-18 18:05:15 +0100346 return 0;
347}