blob: aec2027f2b6a8e953f566bd9f215b26f5d5dee62 [file] [log] [blame]
Jonny Svärd136810f2021-10-13 16:04:26 +02001/*
Jonny Svärdd1750ec2022-01-04 10:59:16 +01002 * Copyright (c) 2019-2022 Arm Limited. All rights reserved.
Jonny Svärd136810f2021-10-13 16:04:26 +02003 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Licensed under the Apache License, Version 2.0 (the License); you may
7 * not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an AS IS BASIS, WITHOUT
14 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
Jonny Svärdd1750ec2022-01-04 10:59:16 +010018
Kristofer Jonsson96703322022-11-04 15:54:32 +010019/******************************************************************************
20 * Includes
21 ******************************************************************************/
22
Jonny Svärd136810f2021-10-13 16:04:26 +020023#include "ethosu_interface.h"
24
Jonny Svärd136810f2021-10-13 16:04:26 +020025#include "ethosu_device.h"
26#include "ethosu_log.h"
27
Kristofer Jonsson1c0e7ae2022-05-12 11:35:33 +020028#ifdef ETHOSU55
29#include "ethosu_config_u55.h"
30#else
31#include "ethosu_config_u65.h"
32#endif
33
Jonny Svärd136810f2021-10-13 16:04:26 +020034#include <assert.h>
35#include <inttypes.h>
36#include <stdbool.h>
37#include <stddef.h>
38#include <stdio.h>
39#include <stdlib.h>
40
Kristofer Jonsson96703322022-11-04 15:54:32 +010041/******************************************************************************
42 * Defines
43 ******************************************************************************/
44
Jonny Svärdd1750ec2022-01-04 10:59:16 +010045#define ETHOSU_PRODUCT_U55 0
46#define ETHOSU_PRODUCT_U65 1
47
Jonny Svärd136810f2021-10-13 16:04:26 +020048#define BASEP_OFFSET 4
49
50#ifdef ETHOSU65
51#define ADDRESS_BITS 40
52#else
53#define ADDRESS_BITS 32
54#endif
55
56#define ADDRESS_MASK ((1ull << ADDRESS_BITS) - 1)
57
58#define NPU_CMD_PWR_CLK_MASK (0xC)
59
Kristofer Jonsson96703322022-11-04 15:54:32 +010060/******************************************************************************
61 * Functions
62 ******************************************************************************/
63
64uint64_t __attribute__((weak)) ethosu_address_remap(uint64_t address, int index)
65{
66 (void)(index);
67 return address;
68}
69
Jonny Svärd136810f2021-10-13 16:04:26 +020070struct ethosu_device *ethosu_dev_init(const void *base_address, uint32_t secure_enable, uint32_t privilege_enable)
71{
72 struct ethosu_device *dev = malloc(sizeof(struct ethosu_device));
73 if (!dev)
74 {
Kristofer Jonsson089a3472021-11-12 12:52:07 +010075 LOG_ERR("Failed to allocate memory for Ethos-U device");
Jonny Svärd136810f2021-10-13 16:04:26 +020076 return NULL;
77 }
78
79 dev->reg = (volatile struct NPU_REG *)base_address;
80 dev->secure = secure_enable;
81 dev->privileged = privilege_enable;
82
Jonny Svärdd1750ec2022-01-04 10:59:16 +010083#ifdef ETHOSU55
84 if (dev->reg->CONFIG.product != ETHOSU_PRODUCT_U55)
85#else
86 if (dev->reg->CONFIG.product != ETHOSU_PRODUCT_U65)
87#endif
88 {
89 LOG_ERR("Failed to initialize device. Driver has not been compiled for this product");
90 goto err;
91 }
92
Jonny Svärd136810f2021-10-13 16:04:26 +020093 // Make sure the NPU is in a known state
94 if (ethosu_dev_soft_reset(dev) != ETHOSU_SUCCESS)
95 {
Jonny Svärdd1750ec2022-01-04 10:59:16 +010096 goto err;
Jonny Svärd136810f2021-10-13 16:04:26 +020097 }
98
99 return dev;
Jonny Svärdd1750ec2022-01-04 10:59:16 +0100100
101err:
102 free(dev);
103 return NULL;
Jonny Svärd136810f2021-10-13 16:04:26 +0200104}
105
106void ethosu_dev_deinit(struct ethosu_device *dev)
107{
108 free(dev);
109}
110
111enum ethosu_error_codes ethosu_dev_axi_init(struct ethosu_device *dev)
112{
113 struct regioncfg_r rcfg = {0};
114 struct axi_limit0_r l0 = {0};
115 struct axi_limit1_r l1 = {0};
116 struct axi_limit2_r l2 = {0};
117 struct axi_limit3_r l3 = {0};
118
119 dev->reg->QCONFIG.word = NPU_QCONFIG;
120
121 rcfg.region0 = NPU_REGIONCFG_0;
122 rcfg.region1 = NPU_REGIONCFG_1;
123 rcfg.region2 = NPU_REGIONCFG_2;
124 rcfg.region3 = NPU_REGIONCFG_3;
125 rcfg.region4 = NPU_REGIONCFG_4;
126 rcfg.region5 = NPU_REGIONCFG_5;
127 rcfg.region6 = NPU_REGIONCFG_6;
128 rcfg.region7 = NPU_REGIONCFG_7;
129 dev->reg->REGIONCFG.word = rcfg.word;
130
131 l0.max_beats = AXI_LIMIT0_MAX_BEATS_BYTES;
132 l0.memtype = AXI_LIMIT0_MEM_TYPE;
133 l0.max_outstanding_read_m1 = AXI_LIMIT0_MAX_OUTSTANDING_READS - 1;
134 l0.max_outstanding_write_m1 = AXI_LIMIT0_MAX_OUTSTANDING_WRITES - 1;
135
136 l1.max_beats = AXI_LIMIT1_MAX_BEATS_BYTES;
137 l1.memtype = AXI_LIMIT1_MEM_TYPE;
138 l1.max_outstanding_read_m1 = AXI_LIMIT1_MAX_OUTSTANDING_READS - 1;
139 l1.max_outstanding_write_m1 = AXI_LIMIT1_MAX_OUTSTANDING_WRITES - 1;
140
141 l2.max_beats = AXI_LIMIT2_MAX_BEATS_BYTES;
142 l2.memtype = AXI_LIMIT2_MEM_TYPE;
143 l2.max_outstanding_read_m1 = AXI_LIMIT2_MAX_OUTSTANDING_READS - 1;
144 l2.max_outstanding_write_m1 = AXI_LIMIT2_MAX_OUTSTANDING_WRITES - 1;
145
146 l3.max_beats = AXI_LIMIT3_MAX_BEATS_BYTES;
147 l3.memtype = AXI_LIMIT3_MEM_TYPE;
148 l3.max_outstanding_read_m1 = AXI_LIMIT3_MAX_OUTSTANDING_READS - 1;
149 l3.max_outstanding_write_m1 = AXI_LIMIT3_MAX_OUTSTANDING_WRITES - 1;
150
151 dev->reg->AXI_LIMIT0.word = l0.word;
152 dev->reg->AXI_LIMIT1.word = l1.word;
153 dev->reg->AXI_LIMIT2.word = l2.word;
154 dev->reg->AXI_LIMIT3.word = l3.word;
155
156 return ETHOSU_SUCCESS;
157}
158
Jonny Svärd1a3bb922022-02-25 16:28:21 +0100159void ethosu_dev_run_command_stream(struct ethosu_device *dev,
160 const uint8_t *cmd_stream_ptr,
161 uint32_t cms_length,
162 const uint64_t *base_addr,
163 int num_base_addr)
Jonny Svärd136810f2021-10-13 16:04:26 +0200164{
165 assert(num_base_addr <= NPU_REG_BASEP_ARRLEN);
166
167 struct cmd_r cmd;
Kristofer Jonsson96703322022-11-04 15:54:32 +0100168 uint64_t qbase = ethosu_address_remap((uintptr_t)cmd_stream_ptr, -1);
Jonny Svärd136810f2021-10-13 16:04:26 +0200169 assert(qbase <= ADDRESS_MASK);
Kristofer Jonsson96703322022-11-04 15:54:32 +0100170 LOG_DEBUG("QBASE=0x%016llx, QSIZE=%u, cmd_stream_ptr=%p", qbase, cms_length, cmd_stream_ptr);
Jonny Svärd136810f2021-10-13 16:04:26 +0200171
172 dev->reg->QBASE.word[0] = qbase & 0xffffffff;
173#ifdef ETHOSU65
174 dev->reg->QBASE.word[1] = qbase >> 32;
175#endif
176 dev->reg->QSIZE.word = cms_length;
177
178 for (int i = 0; i < num_base_addr; i++)
179 {
Kristofer Jonsson96703322022-11-04 15:54:32 +0100180 uint64_t addr = ethosu_address_remap(base_addr[i], i);
Jonny Svärd136810f2021-10-13 16:04:26 +0200181 assert(addr <= ADDRESS_MASK);
Kristofer Jonsson089a3472021-11-12 12:52:07 +0100182 LOG_DEBUG("BASEP%d=0x%016llx", i, addr);
Jonny Svärd136810f2021-10-13 16:04:26 +0200183 dev->reg->BASEP[i].word[0] = addr & 0xffffffff;
184#ifdef ETHOSU65
185 dev->reg->BASEP[i].word[1] = addr >> 32;
186#endif
187 }
188
189 cmd.word = dev->reg->CMD.word & NPU_CMD_PWR_CLK_MASK;
190 cmd.transition_to_running_state = 1;
191
192 dev->reg->CMD.word = cmd.word;
Kristofer Jonsson089a3472021-11-12 12:52:07 +0100193 LOG_DEBUG("CMD=0x%08x", cmd.word);
Jonny Svärd1a3bb922022-02-25 16:28:21 +0100194}
Jonny Svärd136810f2021-10-13 16:04:26 +0200195
Jonny Svärd1a3bb922022-02-25 16:28:21 +0100196void ethosu_dev_print_err_status(struct ethosu_device *dev)
197{
198 LOG_ERR("NPU status=0x%08" PRIx32 ", qread=%" PRIu32 ", cmd_end_reached=%d",
199 dev->reg->STATUS.word,
200 dev->reg->QREAD.word,
201 dev->reg->STATUS.cmd_end_reached);
Jonny Svärd136810f2021-10-13 16:04:26 +0200202}
203
204bool ethosu_dev_handle_interrupt(struct ethosu_device *dev)
205{
206 struct cmd_r cmd;
207
208 // Clear interrupt
209 cmd.word = dev->reg->CMD.word & NPU_CMD_PWR_CLK_MASK;
210 cmd.clear_irq = 1;
211 dev->reg->CMD.word = cmd.word;
212
213 // If a fault has occured, the NPU needs to be reset
214 if (dev->reg->STATUS.bus_status || dev->reg->STATUS.cmd_parse_error || dev->reg->STATUS.wd_fault ||
Jonny Svärd6d5b0832021-11-30 14:54:07 +0100215 dev->reg->STATUS.ecc_fault || !dev->reg->STATUS.cmd_end_reached)
Jonny Svärd136810f2021-10-13 16:04:26 +0200216 {
Jonny Svärd136810f2021-10-13 16:04:26 +0200217 return false;
218 }
219
Jonny Svärd6d5b0832021-11-30 14:54:07 +0100220 return true;
Jonny Svärd136810f2021-10-13 16:04:26 +0200221}
222
223bool ethosu_dev_verify_access_state(struct ethosu_device *dev)
224{
225 if (dev->reg->PROT.active_CSL != (dev->secure ? SECURITY_LEVEL_SECURE : SECURITY_LEVEL_NON_SECURE) ||
226 dev->reg->PROT.active_CPL != (dev->privileged ? PRIVILEGE_LEVEL_PRIVILEGED : PRIVILEGE_LEVEL_USER))
227 {
228 return false;
229 }
230 return true;
231}
232
233enum ethosu_error_codes ethosu_dev_soft_reset(struct ethosu_device *dev)
234{
Jonny Svärd301399d2022-04-26 18:31:24 +0200235 // Note that after a soft-reset, the NPU is unconditionally
236 // powered until the next CMD gets written.
237
Jonny Svärd136810f2021-10-13 16:04:26 +0200238 struct reset_r reset;
239
240 reset.word = 0;
241 reset.pending_CPL = dev->privileged ? PRIVILEGE_LEVEL_PRIVILEGED : PRIVILEGE_LEVEL_USER;
242 reset.pending_CSL = dev->secure ? SECURITY_LEVEL_SECURE : SECURITY_LEVEL_NON_SECURE;
243
244 // Reset and set security level
Kristofer Jonsson089a3472021-11-12 12:52:07 +0100245 LOG_INFO("Soft reset NPU");
Jonny Svärd136810f2021-10-13 16:04:26 +0200246 dev->reg->RESET.word = reset.word;
247
248 // Wait until reset status indicates that reset has been completed
249 for (int i = 0; i < 100000 && dev->reg->STATUS.reset_status != 0; i++)
250 {
251 }
252
253 if (dev->reg->STATUS.reset_status != 0)
254 {
Kristofer Jonsson089a3472021-11-12 12:52:07 +0100255 LOG_ERR("Soft reset timed out");
Jonny Svärd136810f2021-10-13 16:04:26 +0200256 return ETHOSU_GENERIC_FAILURE;
257 }
258
259 // Verify that NPU has switched security state and privilege level
260 if (ethosu_dev_verify_access_state(dev) != true)
261 {
Kristofer Jonsson089a3472021-11-12 12:52:07 +0100262 LOG_ERR("Failed to switch security state and privilege level");
Jonny Svärd136810f2021-10-13 16:04:26 +0200263 return ETHOSU_GENERIC_FAILURE;
264 }
265
266 // Reinitialize AXI settings
267 ethosu_dev_axi_init(dev);
268
269 return ETHOSU_SUCCESS;
270}
271
272void ethosu_dev_get_hw_info(struct ethosu_device *dev, struct ethosu_hw_info *hwinfo)
273{
274 struct config_r cfg;
275 struct id_r id;
276
277 cfg.word = dev->reg->CONFIG.word;
278 id.word = dev->reg->ID.word;
279
280 hwinfo->cfg.cmd_stream_version = cfg.cmd_stream_version;
281 hwinfo->cfg.custom_dma = cfg.custom_dma;
282 hwinfo->cfg.macs_per_cc = cfg.macs_per_cc;
283
284 hwinfo->version.arch_major_rev = id.arch_major_rev;
285 hwinfo->version.arch_minor_rev = id.arch_minor_rev;
286 hwinfo->version.arch_patch_rev = id.arch_patch_rev;
287 hwinfo->version.product_major = id.product_major;
288 hwinfo->version.version_major = id.version_major;
289 hwinfo->version.version_minor = id.version_minor;
290 hwinfo->version.version_status = id.version_status;
291}
292
293enum ethosu_error_codes ethosu_dev_set_clock_and_power(struct ethosu_device *dev,
294 enum ethosu_clock_q_request clock_q,
295 enum ethosu_power_q_request power_q)
296{
297 struct cmd_r cmd = {0};
298 cmd.word = dev->reg->CMD.word & NPU_CMD_PWR_CLK_MASK;
299
300 if (power_q != ETHOSU_POWER_Q_UNCHANGED)
301 {
302 cmd.power_q_enable = power_q == ETHOSU_POWER_Q_ENABLE ? 1 : 0;
303 }
304 if (clock_q != ETHOSU_CLOCK_Q_UNCHANGED)
305 {
306 cmd.clock_q_enable = clock_q == ETHOSU_CLOCK_Q_ENABLE ? 1 : 0;
307 }
308
309 dev->reg->CMD.word = cmd.word;
Kristofer Jonsson089a3472021-11-12 12:52:07 +0100310 LOG_DEBUG("CMD=0x%08x", cmd.word);
Jonny Svärd136810f2021-10-13 16:04:26 +0200311
312 return ETHOSU_SUCCESS;
313}
314
315bool ethosu_dev_verify_optimizer_config(struct ethosu_device *dev, uint32_t cfg_in, uint32_t id_in)
316{
317 struct config_r *opt_cfg = (struct config_r *)&cfg_in;
318 struct config_r hw_cfg;
319 struct id_r *opt_id = (struct id_r *)&id_in;
320 struct id_r hw_id;
321 bool ret = true;
322
323 hw_cfg.word = dev->reg->CONFIG.word;
324 hw_id.word = dev->reg->ID.word;
325
Jonny Svärdd1750ec2022-01-04 10:59:16 +0100326 LOG_INFO("Optimizer config. product=%d, cmd_stream_version=%d, macs_per_cc=%d, shram_size=%d, custom_dma=%d",
327 opt_cfg->product,
Jonny Svärd136810f2021-10-13 16:04:26 +0200328 opt_cfg->cmd_stream_version,
329 opt_cfg->macs_per_cc,
330 opt_cfg->shram_size,
331 opt_cfg->custom_dma);
Jonny Svärdd1750ec2022-01-04 10:59:16 +0100332 LOG_INFO("Optimizer config. arch version: %d.%d.%d",
Jonny Svärd136810f2021-10-13 16:04:26 +0200333 opt_id->arch_major_rev,
334 opt_id->arch_minor_rev,
335 opt_id->arch_patch_rev);
Jonny Svärdd1750ec2022-01-04 10:59:16 +0100336 LOG_INFO("Ethos-U config. product=%d, cmd_stream_version=%d, macs_per_cc=%d, shram_size=%d, custom_dma=%d",
337 hw_cfg.product,
Jonny Svärd136810f2021-10-13 16:04:26 +0200338 hw_cfg.cmd_stream_version,
339 hw_cfg.macs_per_cc,
340 hw_cfg.shram_size,
341 hw_cfg.custom_dma);
Jonny Svärdd1750ec2022-01-04 10:59:16 +0100342 LOG_INFO("Ethos-U. arch version=%d.%d.%d", hw_id.arch_major_rev, hw_id.arch_minor_rev, hw_id.arch_patch_rev);
Jonny Svärd136810f2021-10-13 16:04:26 +0200343
344 if (opt_cfg->word != hw_cfg.word)
345 {
Jonny Svärdd1750ec2022-01-04 10:59:16 +0100346 if (hw_cfg.product != opt_cfg->product)
347 {
348 LOG_ERR("NPU config mismatch. npu.product=%d, optimizer.product=%d", hw_cfg.product, opt_cfg->product);
349 ret = false;
350 }
351
Jonny Svärd136810f2021-10-13 16:04:26 +0200352 if (hw_cfg.macs_per_cc != opt_cfg->macs_per_cc)
353 {
Kristofer Jonsson1975b8d2021-11-26 16:15:44 +0100354 LOG_ERR("NPU config mismatch. npu.macs_per_cc=%d, optimizer.macs_per_cc=%d",
Jonny Svärd136810f2021-10-13 16:04:26 +0200355 hw_cfg.macs_per_cc,
356 opt_cfg->macs_per_cc);
357 ret = false;
358 }
359
Jonny Svärd136810f2021-10-13 16:04:26 +0200360 if (hw_cfg.cmd_stream_version != opt_cfg->cmd_stream_version)
361 {
Kristofer Jonsson1975b8d2021-11-26 16:15:44 +0100362 LOG_ERR("NPU config mismatch. npu.cmd_stream_version=%d, optimizer.cmd_stream_version=%d",
Jonny Svärd136810f2021-10-13 16:04:26 +0200363 hw_cfg.cmd_stream_version,
364 opt_cfg->cmd_stream_version);
365 ret = false;
366 }
367
368 if (!hw_cfg.custom_dma && opt_cfg->custom_dma)
369 {
Kristofer Jonsson1975b8d2021-11-26 16:15:44 +0100370 LOG_ERR("NPU config mismatch. npu.custom_dma=%d, optimizer.custom_dma=%d",
Jonny Svärd136810f2021-10-13 16:04:26 +0200371 hw_cfg.custom_dma,
372 opt_cfg->custom_dma);
373 ret = false;
374 }
375 }
376
377 if ((hw_id.arch_major_rev != opt_id->arch_major_rev) || (hw_id.arch_minor_rev < opt_id->arch_minor_rev))
378 {
Kristofer Jonsson1975b8d2021-11-26 16:15:44 +0100379 LOG_ERR("NPU arch mismatch. npu.arch=%d.%d.%d, optimizer.arch=%d.%d.%d",
Jonny Svärd136810f2021-10-13 16:04:26 +0200380 hw_id.arch_major_rev,
381 hw_id.arch_minor_rev,
382 hw_id.arch_patch_rev,
383 opt_id->arch_major_rev,
384 opt_id->arch_minor_rev,
385 opt_id->arch_patch_rev);
386 ret = false;
387 }
388
389 return ret;
390}