blob: cf3491055e271d841faad06fe02eae18e1de6613 [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
Laurent Carlier5205df22021-09-16 15:10:35 +010020/*
Mikael Olsson3288b462022-08-15 17:12:58 +020021 * Number of Arm(R) Ethos(TM)-N NPU (NPU) devices available
Laurent Carlier5205df22021-09-16 15:10:35 +010022 */
Mikael Olsson3288b462022-08-15 17:12:58 +020023#define ETHOSN_NUM_DEVICES \
24 FCONF_GET_PROPERTY(hw_config, ethosn_config, num_devices)
Mikael Olsson7da66192021-02-12 17:30:22 +010025
Mikael Olsson3288b462022-08-15 17:12:58 +020026#define ETHOSN_GET_DEVICE(dev_idx) \
27 FCONF_GET_PROPERTY(hw_config, ethosn_device, dev_idx)
Mikael Olsson7da66192021-02-12 17:30:22 +010028
29/* NPU core sec registry address */
30#define ETHOSN_CORE_SEC_REG(core_addr, reg_offset) \
31 (core_addr + reg_offset)
32
33/* Reset timeout in us */
34#define ETHOSN_RESET_TIMEOUT_US U(10 * 1000 * 1000)
35#define ETHOSN_RESET_WAIT_US U(1)
36
37#define SEC_DEL_REG U(0x0004)
38#define SEC_DEL_VAL U(0x81C)
39#define SEC_DEL_EXCC_MASK U(0x20)
40
41#define SEC_SECCTLR_REG U(0x0010)
Mikael Olssonbfd9da72023-01-11 10:36:22 +010042/* Set bit[10] = 1 to workaround erratum 2838783 */
43#define SEC_SECCTLR_VAL U(0x403)
Mikael Olsson7da66192021-02-12 17:30:22 +010044
Mikael Olsson7da66192021-02-12 17:30:22 +010045#define SEC_DEL_ADDR_EXT_REG U(0x201C)
46#define SEC_DEL_ADDR_EXT_VAL U(0x15)
47
48#define SEC_SYSCTRL0_REG U(0x0018)
Mikael Olsson47675f22022-11-04 15:01:02 +010049#define SEC_SYSCTRL0_SLEEPING U(1U << 4)
Mikael Olsson7da66192021-02-12 17:30:22 +010050#define SEC_SYSCTRL0_SOFT_RESET U(3U << 29)
51#define SEC_SYSCTRL0_HARD_RESET U(1U << 31)
52
Rajasekaran Kalidossf8a18b82022-11-16 17:16:44 +010053#define SEC_NSAID_REG_BASE U(0x3004)
54#define SEC_NSAID_OFFSET U(0x1000)
55
Mikael Olsson3288b462022-08-15 17:12:58 +020056#define SEC_MMUSID_REG_BASE U(0x3008)
57#define SEC_MMUSID_OFFSET U(0x1000)
58
Rajasekaran Kalidossf8a18b82022-11-16 17:16:44 +010059#define INPUT_STREAM_INDEX U(0x6)
60#define INTERMEDIATE_STREAM_INDEX U(0x7)
61#define OUTPUT_STREAM_INDEX U(0x8)
62
Mikael Olsson3288b462022-08-15 17:12:58 +020063static bool ethosn_get_device_and_core(uintptr_t core_addr,
64 const struct ethosn_device_t **dev_match,
65 const struct ethosn_core_t **core_match)
Laurent Carlier5205df22021-09-16 15:10:35 +010066{
Mikael Olsson3288b462022-08-15 17:12:58 +020067 uint32_t dev_idx;
68 uint32_t core_idx;
69
70 for (dev_idx = 0U; dev_idx < ETHOSN_NUM_DEVICES; ++dev_idx) {
71 const struct ethosn_device_t *dev = ETHOSN_GET_DEVICE(dev_idx);
72
73 for (core_idx = 0U; core_idx < dev->num_cores; ++core_idx) {
74 const struct ethosn_core_t *core = &(dev->cores[core_idx]);
75
76 if (core->addr == core_addr) {
77 *dev_match = dev;
78 *core_match = core;
79 return true;
80 }
Laurent Carlier5205df22021-09-16 15:10:35 +010081 }
82 }
83
Mikael Olsson3288b462022-08-15 17:12:58 +020084 WARN("ETHOSN: Unknown core address given to SMC call.\n");
Laurent Carlier5205df22021-09-16 15:10:35 +010085 return false;
86}
87
Rajasekaran Kalidossf8a18b82022-11-16 17:16:44 +010088#if ARM_ETHOSN_NPU_TZMP1
89static void ethosn_configure_stream_nsaid(const struct ethosn_core_t *core,
90 bool is_protected)
91{
92 size_t i;
93 uint32_t streams[9] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
94
95 if (is_protected) {
96 streams[INPUT_STREAM_INDEX] = ARM_ETHOSN_NPU_PROT_DATA_NSAID;
97 streams[INTERMEDIATE_STREAM_INDEX] =
98 ARM_ETHOSN_NPU_PROT_DATA_NSAID;
99 streams[OUTPUT_STREAM_INDEX] = ARM_ETHOSN_NPU_PROT_DATA_NSAID;
100 }
101
102 for (i = 0U; i < ARRAY_SIZE(streams); ++i) {
103 const uintptr_t reg_addr = SEC_NSAID_REG_BASE +
104 (SEC_NSAID_OFFSET * i);
105 mmio_write_32(ETHOSN_CORE_SEC_REG(core->addr, reg_addr),
106 streams[i]);
107 }
108}
109#endif
110
Mikael Olsson3288b462022-08-15 17:12:58 +0200111static void ethosn_configure_smmu_streams(const struct ethosn_device_t *device,
112 const struct ethosn_core_t *core,
113 uint32_t asset_alloc_idx)
114{
115 const struct ethosn_main_allocator_t *main_alloc =
116 &(core->main_allocator);
117 const struct ethosn_asset_allocator_t *asset_alloc =
118 &(device->asset_allocators[asset_alloc_idx]);
119 const uint32_t streams[9] = {
120 main_alloc->firmware.stream_id,
121 main_alloc->working_data.stream_id,
122 asset_alloc->command_stream.stream_id,
123 0U, /* Not used*/
124 main_alloc->firmware.stream_id,
125 asset_alloc->weight_data.stream_id,
126 asset_alloc->buffer_data.stream_id,
127 asset_alloc->intermediate_data.stream_id,
128 asset_alloc->buffer_data.stream_id
129 };
130 size_t i;
131
132 for (i = 0U; i < ARRAY_SIZE(streams); ++i) {
133 const uintptr_t reg_addr = SEC_MMUSID_REG_BASE +
134 (SEC_MMUSID_OFFSET * i);
135 mmio_write_32(ETHOSN_CORE_SEC_REG(core->addr, reg_addr),
136 streams[i]);
137 }
138}
139
Mikael Olsson7da66192021-02-12 17:30:22 +0100140static void ethosn_delegate_to_ns(uintptr_t core_addr)
141{
142 mmio_setbits_32(ETHOSN_CORE_SEC_REG(core_addr, SEC_SECCTLR_REG),
143 SEC_SECCTLR_VAL);
144
145 mmio_setbits_32(ETHOSN_CORE_SEC_REG(core_addr, SEC_DEL_REG),
146 SEC_DEL_VAL);
147
Mikael Olsson7da66192021-02-12 17:30:22 +0100148 mmio_setbits_32(ETHOSN_CORE_SEC_REG(core_addr, SEC_DEL_ADDR_EXT_REG),
149 SEC_DEL_ADDR_EXT_VAL);
150}
151
Laurent Carlier5205df22021-09-16 15:10:35 +0100152static int ethosn_is_sec(uintptr_t core_addr)
Mikael Olsson7da66192021-02-12 17:30:22 +0100153{
Laurent Carlier5205df22021-09-16 15:10:35 +0100154 if ((mmio_read_32(ETHOSN_CORE_SEC_REG(core_addr, SEC_DEL_REG))
Mikael Olsson7da66192021-02-12 17:30:22 +0100155 & SEC_DEL_EXCC_MASK) != 0U) {
156 return 0;
157 }
158
159 return 1;
160}
161
Mikael Olsson47675f22022-11-04 15:01:02 +0100162static int ethosn_core_is_sleeping(uintptr_t core_addr)
163{
164 const uintptr_t sysctrl0_reg =
165 ETHOSN_CORE_SEC_REG(core_addr, SEC_SYSCTRL0_REG);
166 const uint32_t sleeping_mask = SEC_SYSCTRL0_SLEEPING;
167
168 return ((mmio_read_32(sysctrl0_reg) & sleeping_mask) == sleeping_mask);
169}
170
Mikael Olsson7da66192021-02-12 17:30:22 +0100171static bool ethosn_reset(uintptr_t core_addr, int hard_reset)
172{
173 unsigned int timeout;
174 const uintptr_t sysctrl0_reg =
175 ETHOSN_CORE_SEC_REG(core_addr, SEC_SYSCTRL0_REG);
176 const uint32_t reset_val = (hard_reset != 0) ? SEC_SYSCTRL0_HARD_RESET
177 : SEC_SYSCTRL0_SOFT_RESET;
178
179 mmio_write_32(sysctrl0_reg, reset_val);
180
181 /* Wait for reset to complete */
182 for (timeout = 0U; timeout < ETHOSN_RESET_TIMEOUT_US;
183 timeout += ETHOSN_RESET_WAIT_US) {
184
185 if ((mmio_read_32(sysctrl0_reg) & reset_val) == 0U) {
186 break;
187 }
188
189 udelay(ETHOSN_RESET_WAIT_US);
190 }
191
192 return timeout < ETHOSN_RESET_TIMEOUT_US;
193}
194
195uintptr_t ethosn_smc_handler(uint32_t smc_fid,
Laurent Carlier5205df22021-09-16 15:10:35 +0100196 u_register_t core_addr,
Mikael Olsson3288b462022-08-15 17:12:58 +0200197 u_register_t asset_alloc_idx,
Joshua Pimm6bc80672022-10-19 15:46:27 +0100198 u_register_t reset_type,
Rajasekaran Kalidossf8a18b82022-11-16 17:16:44 +0100199 u_register_t is_protected,
Mikael Olsson7da66192021-02-12 17:30:22 +0100200 void *cookie,
201 void *handle,
202 u_register_t flags)
203{
Mikael Olsson7da66192021-02-12 17:30:22 +0100204 int hard_reset = 0;
Mikael Olsson3288b462022-08-15 17:12:58 +0200205 const struct ethosn_device_t *device = NULL;
206 const struct ethosn_core_t *core = NULL;
Laurent Carlier5205df22021-09-16 15:10:35 +0100207 const uint32_t fid = smc_fid & FUNCID_NUM_MASK;
Mikael Olsson7da66192021-02-12 17:30:22 +0100208
209 /* Only SiP fast calls are expected */
210 if ((GET_SMC_TYPE(smc_fid) != SMC_TYPE_FAST) ||
211 (GET_SMC_OEN(smc_fid) != OEN_SIP_START)) {
212 SMC_RET1(handle, SMC_UNK);
213 }
214
215 /* Truncate parameters to 32-bits for SMC32 */
216 if (GET_SMC_CC(smc_fid) == SMC_32) {
Laurent Carlier5205df22021-09-16 15:10:35 +0100217 core_addr &= 0xFFFFFFFF;
Mikael Olsson3288b462022-08-15 17:12:58 +0200218 asset_alloc_idx &= 0xFFFFFFFF;
Joshua Pimm6bc80672022-10-19 15:46:27 +0100219 reset_type &= 0xFFFFFFFF;
Rajasekaran Kalidossf8a18b82022-11-16 17:16:44 +0100220 is_protected &= 0xFFFFFFFF;
Mikael Olsson7da66192021-02-12 17:30:22 +0100221 }
222
Mikael Olsson47675f22022-11-04 15:01:02 +0100223 if (!is_ethosn_fid(smc_fid) || (fid > ETHOSN_FNUM_IS_SLEEPING)) {
Mikael Olsson3288b462022-08-15 17:12:58 +0200224 WARN("ETHOSN: Unknown SMC call: 0x%x\n", smc_fid);
Mikael Olsson7da66192021-02-12 17:30:22 +0100225 SMC_RET1(handle, SMC_UNK);
226 }
227
Laurent Carlier5205df22021-09-16 15:10:35 +0100228 /* Commands that do not require a valid core address */
229 switch (fid) {
Mikael Olsson7da66192021-02-12 17:30:22 +0100230 case ETHOSN_FNUM_VERSION:
231 SMC_RET2(handle, ETHOSN_VERSION_MAJOR, ETHOSN_VERSION_MINOR);
Laurent Carlier5205df22021-09-16 15:10:35 +0100232 }
233
Mikael Olsson3288b462022-08-15 17:12:58 +0200234 if (!ethosn_get_device_and_core(core_addr, &device, &core)) {
Laurent Carlier5205df22021-09-16 15:10:35 +0100235 SMC_RET1(handle, ETHOSN_UNKNOWN_CORE_ADDRESS);
236 }
237
Mikael Olsson3288b462022-08-15 17:12:58 +0200238 /* Commands that require a valid core address */
Laurent Carlier5205df22021-09-16 15:10:35 +0100239 switch (fid) {
Mikael Olsson7da66192021-02-12 17:30:22 +0100240 case ETHOSN_FNUM_IS_SEC:
Mikael Olsson3288b462022-08-15 17:12:58 +0200241 SMC_RET1(handle, ethosn_is_sec(core->addr));
Mikael Olsson47675f22022-11-04 15:01:02 +0100242 case ETHOSN_FNUM_IS_SLEEPING:
243 SMC_RET1(handle, ethosn_core_is_sleeping(core->addr));
Mikael Olsson3288b462022-08-15 17:12:58 +0200244 }
245
246 if (!device->has_reserved_memory &&
247 asset_alloc_idx >= device->num_allocators) {
248 WARN("ETHOSN: Unknown asset allocator index given to SMC call.\n");
249 SMC_RET1(handle, ETHOSN_UNKNOWN_ALLOCATOR_IDX);
250 }
251
Joshua Pimm6bc80672022-10-19 15:46:27 +0100252 if (reset_type > ETHOSN_RESET_TYPE_HALT) {
253 WARN("ETHOSN: Invalid reset type given to SMC call.\n");
254 SMC_RET1(handle, ETHOSN_INVALID_PARAMETER);
255 }
256
257 /*
258 * Commands that require a valid device, reset type,
259 * core and asset allocator
260 */
Mikael Olsson3288b462022-08-15 17:12:58 +0200261 switch (fid) {
Mikael Olsson7da66192021-02-12 17:30:22 +0100262 case ETHOSN_FNUM_HARD_RESET:
263 hard_reset = 1;
264 /* Fallthrough */
265 case ETHOSN_FNUM_SOFT_RESET:
Mikael Olsson3288b462022-08-15 17:12:58 +0200266 if (!ethosn_reset(core->addr, hard_reset)) {
Mikael Olsson7da66192021-02-12 17:30:22 +0100267 SMC_RET1(handle, ETHOSN_FAILURE);
268 }
Mikael Olsson3288b462022-08-15 17:12:58 +0200269
Joshua Pimm6bc80672022-10-19 15:46:27 +0100270 if (reset_type == ETHOSN_RESET_TYPE_FULL) {
271 if (!device->has_reserved_memory) {
272 ethosn_configure_smmu_streams(device, core,
273 asset_alloc_idx);
Rajasekaran Kalidossf8a18b82022-11-16 17:16:44 +0100274
275 #if ARM_ETHOSN_NPU_TZMP1
276 ethosn_configure_stream_nsaid(core,
277 is_protected);
278 #endif
Joshua Pimm6bc80672022-10-19 15:46:27 +0100279 }
Mikael Olsson3288b462022-08-15 17:12:58 +0200280
Joshua Pimm6bc80672022-10-19 15:46:27 +0100281 ethosn_delegate_to_ns(core->addr);
282 }
Mikael Olsson7da66192021-02-12 17:30:22 +0100283 SMC_RET1(handle, ETHOSN_SUCCESS);
284 default:
Mikael Olsson3288b462022-08-15 17:12:58 +0200285 WARN("ETHOSN: Unimplemented SMC call: 0x%x\n", fid);
Mikael Olsson7da66192021-02-12 17:30:22 +0100286 SMC_RET1(handle, SMC_UNK);
287 }
288}