blob: 8fee3f438c6818781a57519950963c720627f0dd [file] [log] [blame]
Kristofer Jonsson49bdee82020-04-06 13:21:21 +02001/*
2 * Copyright (c) 2019-2020 Arm Limited. All rights reserved.
3 *
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 */
Kristofer Jonsson49bdee82020-04-06 13:21:21 +020018#include "ethosu_device.h"
Kristofer Jonsson49bdee82020-04-06 13:21:21 +020019#include "ethosu_common.h"
Kristofer Jonsson125429a2020-08-20 16:52:23 +020020#include "ethosu_config.h"
Bhavik Patel790ef362020-06-03 10:05:28 +020021
Kristofer Jonsson49bdee82020-04-06 13:21:21 +020022#include <assert.h>
Bhavik Pateldae5be02020-06-18 15:25:15 +020023#include <stddef.h>
Kristofer Jonsson49bdee82020-04-06 13:21:21 +020024#include <stdio.h>
25
Kristofer Jonsson49bdee82020-04-06 13:21:21 +020026#define BASEP_OFFSET 4
27#define REG_OFFSET 4
28#define BYTES_1KB 1024
29
Kristofer Jonsson125429a2020-08-20 16:52:23 +020030#define ADDRESS_BITS 48
31#define ADDRESS_MASK ((1ull << ADDRESS_BITS) - 1)
32
Kristofer Jonsson49bdee82020-04-06 13:21:21 +020033#if defined(ARM_NPU_STUB)
34static uint32_t stream_length = 0;
35#endif
36
Bhavik Pateldae5be02020-06-18 15:25:15 +020037enum ethosu_error_codes ethosu_dev_init(struct ethosu_device *dev, const void *base_address)
Kristofer Jonsson49bdee82020-04-06 13:21:21 +020038{
Bhavik Pateldae5be02020-06-18 15:25:15 +020039#if !defined(ARM_NPU_STUB)
Kristofer Jonsson4dc73dc2020-10-16 12:33:47 +020040 dev->base_address = (volatile uint32_t *)base_address;
Kristofer Jonssonef387ea2020-08-25 16:32:21 +020041 ethosu_save_pmu_config(dev);
Bhavik Pateldae5be02020-06-18 15:25:15 +020042#else
43 UNUSED(dev);
44 UNUSED(base_address);
45#endif
Kristofer Jonsson49bdee82020-04-06 13:21:21 +020046 return ETHOSU_SUCCESS;
47}
48
Bhavik Pateldae5be02020-06-18 15:25:15 +020049enum ethosu_error_codes ethosu_get_id(struct ethosu_device *dev, struct ethosu_id *id)
Kristofer Jonsson49bdee82020-04-06 13:21:21 +020050{
51 struct id_r _id;
52
53#if !defined(ARM_NPU_STUB)
Bhavik Pateldae5be02020-06-18 15:25:15 +020054 _id.word = ethosu_read_reg(dev, NPU_REG_ID);
Kristofer Jonsson49bdee82020-04-06 13:21:21 +020055#else
Bhavik Pateldae5be02020-06-18 15:25:15 +020056 UNUSED(dev);
57
Kristofer Jonsson49bdee82020-04-06 13:21:21 +020058 _id.word = 0;
59 _id.arch_patch_rev = NNX_ARCH_VERSION_PATCH;
60 _id.arch_minor_rev = NNX_ARCH_VERSION_MINOR;
61 _id.arch_major_rev = NNX_ARCH_VERSION_MAJOR;
62#endif
63
64 id->version_status = _id.version_status;
65 id->version_minor = _id.version_minor;
66 id->version_major = _id.version_major;
67 id->product_major = _id.product_major;
68 id->arch_patch_rev = _id.arch_patch_rev;
69 id->arch_minor_rev = _id.arch_minor_rev;
70 id->arch_major_rev = _id.arch_major_rev;
71
72 return ETHOSU_SUCCESS;
73}
74
Bhavik Pateldae5be02020-06-18 15:25:15 +020075enum ethosu_error_codes ethosu_get_config(struct ethosu_device *dev, struct ethosu_config *config)
Kristofer Jonsson49bdee82020-04-06 13:21:21 +020076{
77 struct config_r cfg = {.word = 0};
78
79#if !defined(ARM_NPU_STUB)
Bhavik Pateldae5be02020-06-18 15:25:15 +020080 cfg.word = ethosu_read_reg(dev, NPU_REG_CONFIG);
81#else
82 UNUSED(dev);
Kristofer Jonsson49bdee82020-04-06 13:21:21 +020083#endif
84
85 config->macs_per_cc = cfg.macs_per_cc;
86 config->cmd_stream_version = cfg.cmd_stream_version;
87 config->shram_size = cfg.shram_size;
88
89 return ETHOSU_SUCCESS;
90}
91
Bhavik Pateldae5be02020-06-18 15:25:15 +020092enum ethosu_error_codes ethosu_run_command_stream(struct ethosu_device *dev,
93 const uint8_t *cmd_stream_ptr,
Kristofer Jonsson49bdee82020-04-06 13:21:21 +020094 uint32_t cms_length,
95 const uint64_t *base_addr,
96 int num_base_addr)
97{
Bhavik Patele645fed2020-06-12 14:46:47 +020098 enum ethosu_error_codes ret_code = ETHOSU_SUCCESS;
99
Kristofer Jonsson49bdee82020-04-06 13:21:21 +0200100#if !defined(ARM_NPU_STUB)
Kristofer Jonsson49bdee82020-04-06 13:21:21 +0200101 ASSERT(num_base_addr <= ETHOSU_DRIVER_BASEP_INDEXES);
102
Per Åstrandc6c1db12020-09-28 08:41:45 +0200103 uint64_t qbase = (uintptr_t)cmd_stream_ptr + BASE_POINTER_OFFSET;
Kristofer Jonsson125429a2020-08-20 16:52:23 +0200104 ASSERT(qbase <= ADDRESS_MASK);
105 LOG_DEBUG("QBASE=0x%016llx, QSIZE=%u, base_pointer_offset=0x%08x\n", qbase, cms_length, BASE_POINTER_OFFSET);
106 ethosu_write_reg(dev, NPU_REG_QBASE0, qbase & 0xffffffff);
107 ethosu_write_reg(dev, NPU_REG_QBASE1, qbase >> 32);
108 ethosu_write_reg(dev, NPU_REG_QSIZE, cms_length);
Kristofer Jonsson49bdee82020-04-06 13:21:21 +0200109
Kristofer Jonsson125429a2020-08-20 16:52:23 +0200110 for (int i = 0; i < num_base_addr; i++)
Kristofer Jonsson49bdee82020-04-06 13:21:21 +0200111 {
Kristofer Jonsson125429a2020-08-20 16:52:23 +0200112 uint64_t addr = base_addr[i] + BASE_POINTER_OFFSET;
113 ASSERT(addr <= ADDRESS_MASK);
114 LOG_DEBUG("BASEP%d=0x%016llx\n", i, addr);
115 ethosu_write_reg(dev, NPU_REG_BASEP0 + (2 * i) * BASEP_OFFSET, addr & 0xffffffff);
116 ethosu_write_reg(dev, NPU_REG_BASEP0 + (2 * i + 1) * BASEP_OFFSET, addr >> 32);
Kristofer Jonsson49bdee82020-04-06 13:21:21 +0200117 }
118
Bhavik Pateldae5be02020-06-18 15:25:15 +0200119 ret_code = ethosu_set_command_run(dev);
Kristofer Jonsson49bdee82020-04-06 13:21:21 +0200120#else
121 // NPU stubbed
Bhavik Pateldae5be02020-06-18 15:25:15 +0200122 UNUSED(dev);
Kristofer Jonsson49bdee82020-04-06 13:21:21 +0200123 stream_length = cms_length;
124 UNUSED(cmd_stream_ptr);
125 UNUSED(base_addr);
126 ASSERT(num_base_addr < ETHOSU_DRIVER_BASEP_INDEXES);
127#if defined(NDEBUG)
128 UNUSED(num_base_addr);
129#endif
130#endif
131
Bhavik Patele645fed2020-06-12 14:46:47 +0200132 return ret_code;
Kristofer Jonsson49bdee82020-04-06 13:21:21 +0200133}
134
Bhavik Pateldae5be02020-06-18 15:25:15 +0200135enum ethosu_error_codes ethosu_is_irq_raised(struct ethosu_device *dev, uint8_t *irq_raised)
Kristofer Jonsson49bdee82020-04-06 13:21:21 +0200136{
137#if !defined(ARM_NPU_STUB)
138 struct status_r status;
Bhavik Pateldae5be02020-06-18 15:25:15 +0200139 status.word = ethosu_read_reg(dev, NPU_REG_STATUS);
Kristofer Jonsson49bdee82020-04-06 13:21:21 +0200140 if (status.irq_raised == 1)
141 {
142 *irq_raised = 1;
143 }
144 else
145 {
146 *irq_raised = 0;
147 }
148#else
Bhavik Pateldae5be02020-06-18 15:25:15 +0200149 UNUSED(dev);
Kristofer Jonsson49bdee82020-04-06 13:21:21 +0200150 *irq_raised = 1;
151#endif
152 return ETHOSU_SUCCESS;
153}
154
Bhavik Pateldae5be02020-06-18 15:25:15 +0200155enum ethosu_error_codes ethosu_clear_irq_status(struct ethosu_device *dev)
Kristofer Jonsson49bdee82020-04-06 13:21:21 +0200156{
157#if !defined(ARM_NPU_STUB)
Bhavik Patele645fed2020-06-12 14:46:47 +0200158 struct cmd_r oldcmd;
Bhavik Pateldae5be02020-06-18 15:25:15 +0200159 oldcmd.word = ethosu_read_reg(dev, NPU_REG_CMD);
Bhavik Patele645fed2020-06-12 14:46:47 +0200160 struct cmd_r cmd;
Per Åstrand9716b5e2020-08-19 13:15:06 +0200161
Bhavik Patele645fed2020-06-12 14:46:47 +0200162 cmd.word = 0;
163 cmd.clear_irq = 1;
164 cmd.clock_q_enable = oldcmd.clock_q_enable;
165 cmd.power_q_enable = oldcmd.power_q_enable;
Bhavik Pateldae5be02020-06-18 15:25:15 +0200166 ethosu_write_reg(dev, NPU_REG_CMD, cmd.word);
Kristofer Jonsson49bdee82020-04-06 13:21:21 +0200167#else
Bhavik Pateldae5be02020-06-18 15:25:15 +0200168 UNUSED(dev);
Kristofer Jonsson49bdee82020-04-06 13:21:21 +0200169#endif
170 return ETHOSU_SUCCESS;
171}
172
Bhavik Patele645fed2020-06-12 14:46:47 +0200173// TODO Understand settings of privilege/security level and update API.
Bhavik Pateldae5be02020-06-18 15:25:15 +0200174enum ethosu_error_codes ethosu_soft_reset(struct ethosu_device *dev)
Kristofer Jonsson49bdee82020-04-06 13:21:21 +0200175{
176 enum ethosu_error_codes return_code = ETHOSU_SUCCESS;
177#if !defined(ARM_NPU_STUB)
178 struct reset_r reset;
179 struct prot_r prot;
180
181 reset.word = 0;
Bhavik Pateldae5be02020-06-18 15:25:15 +0200182 reset.pending_CPL = PRIVILEGE_LEVEL_USER; // TODO, how to get the host privilege level
Kristofer Jonsson49bdee82020-04-06 13:21:21 +0200183 reset.pending_CSL = SECURITY_LEVEL_NON_SECURE; // TODO, how to get Security level
184
Bhavik Pateldae5be02020-06-18 15:25:15 +0200185 prot.word = ethosu_read_reg(dev, NPU_REG_PROT);
Kristofer Jonsson49bdee82020-04-06 13:21:21 +0200186
187 if (prot.active_CPL < reset.pending_CPL && prot.active_CSL > reset.pending_CSL)
188 {
189 // Register access not permitted
190 return ETHOSU_GENERIC_FAILURE;
191 }
Kristofer Jonsson4dc73dc2020-10-16 12:33:47 +0200192
Kristofer Jonsson49bdee82020-04-06 13:21:21 +0200193 // Reset and set security level
Bhavik Pateldae5be02020-06-18 15:25:15 +0200194 ethosu_write_reg(dev, NPU_REG_RESET, reset.word);
Kristofer Jonsson49bdee82020-04-06 13:21:21 +0200195
Kristofer Jonsson4dc73dc2020-10-16 12:33:47 +0200196 // Wait for reset to complete
Bhavik Pateldae5be02020-06-18 15:25:15 +0200197 return_code = ethosu_wait_for_reset(dev);
Bhavik Patel5f8dad12020-09-30 09:06:52 +0200198
Kristofer Jonsson4dc73dc2020-10-16 12:33:47 +0200199 // Save the proto register
Bhavik Patel5f8dad12020-09-30 09:06:52 +0200200 dev->reset = ethosu_read_reg(dev, NPU_REG_PROT);
Kristofer Jonsson4dc73dc2020-10-16 12:33:47 +0200201
202 // Soft reset will clear the PMU configuration and counters. The shadow PMU counters
203 // are cleared by saving the PMU counters to ram, which will read back zeros.
204 // The PMU configuration will be restored in the invoke function after power save
205 // has been disabled.
206 ethosu_save_pmu_counters(dev);
Bhavik Pateldae5be02020-06-18 15:25:15 +0200207#else
208 UNUSED(dev);
Kristofer Jonsson49bdee82020-04-06 13:21:21 +0200209#endif
210
211 return return_code;
212}
213
Bhavik Pateldae5be02020-06-18 15:25:15 +0200214enum ethosu_error_codes ethosu_wait_for_reset(struct ethosu_device *dev)
Kristofer Jonsson49bdee82020-04-06 13:21:21 +0200215{
216#if !defined(ARM_NPU_STUB)
217 struct status_r status;
218
219 // Wait until reset status indicates that reset has been completed
220 for (int i = 0; i < 100000; i++)
221 {
Bhavik Pateldae5be02020-06-18 15:25:15 +0200222 status.word = ethosu_read_reg(dev, NPU_REG_STATUS);
Kristofer Jonsson49bdee82020-04-06 13:21:21 +0200223 if (0 == status.reset_status)
224 {
225 break;
226 }
227 }
228
229 if (1 == status.reset_status)
230 {
231 return ETHOSU_GENERIC_FAILURE;
232 }
Bhavik Pateldae5be02020-06-18 15:25:15 +0200233#else
234 UNUSED(dev);
Kristofer Jonsson49bdee82020-04-06 13:21:21 +0200235#endif
236
237 return ETHOSU_SUCCESS;
238}
239
Bhavik Pateldae5be02020-06-18 15:25:15 +0200240enum ethosu_error_codes ethosu_read_apb_reg(struct ethosu_device *dev,
241 uint32_t start_address,
242 uint16_t num_reg,
243 uint32_t *reg)
Kristofer Jonsson49bdee82020-04-06 13:21:21 +0200244{
245#if !defined(ARM_NPU_STUB)
246 uint32_t address = start_address;
247
Douglas Troha2e7e3b72020-05-14 20:28:31 +0200248 ASSERT((start_address + num_reg) < ID_REGISTERS_SIZE);
Kristofer Jonsson49bdee82020-04-06 13:21:21 +0200249
250 for (int i = 0; i < num_reg; i++)
251 {
Bhavik Pateldae5be02020-06-18 15:25:15 +0200252 reg[i] = ethosu_read_reg(dev, address);
Kristofer Jonsson49bdee82020-04-06 13:21:21 +0200253 address += REG_OFFSET;
254 }
255#else
256 // NPU stubbed
Bhavik Pateldae5be02020-06-18 15:25:15 +0200257 UNUSED(dev);
Kristofer Jonsson49bdee82020-04-06 13:21:21 +0200258 UNUSED(start_address);
259 UNUSED(num_reg);
260 UNUSED(reg);
261#endif
262
263 return ETHOSU_SUCCESS;
264}
265
Bhavik Pateldae5be02020-06-18 15:25:15 +0200266enum ethosu_error_codes ethosu_set_qconfig(struct ethosu_device *dev, enum ethosu_memory_type memory_type)
Kristofer Jonsson49bdee82020-04-06 13:21:21 +0200267{
268 if (memory_type > ETHOSU_AXI1_OUTSTANDING_COUNTER3)
269 {
270 return ETHOSU_INVALID_PARAM;
271 }
272#if !defined(ARM_NPU_STUB)
Bhavik Pateldae5be02020-06-18 15:25:15 +0200273 ethosu_write_reg(dev, NPU_REG_QCONFIG, memory_type);
Kristofer Jonsson49bdee82020-04-06 13:21:21 +0200274#else
275 // NPU stubbed
Bhavik Pateldae5be02020-06-18 15:25:15 +0200276 UNUSED(dev);
Kristofer Jonsson49bdee82020-04-06 13:21:21 +0200277 UNUSED(memory_type);
278#endif
279 return ETHOSU_SUCCESS;
280}
281
Bhavik Pateldae5be02020-06-18 15:25:15 +0200282enum ethosu_error_codes ethosu_set_regioncfg(struct ethosu_device *dev,
283 uint8_t region,
284 enum ethosu_memory_type memory_type)
Kristofer Jonsson49bdee82020-04-06 13:21:21 +0200285{
286 if (region > 7)
287 {
288 return ETHOSU_INVALID_PARAM;
289 }
290#if !defined(ARM_NPU_STUB)
291 struct regioncfg_r regioncfg;
Bhavik Pateldae5be02020-06-18 15:25:15 +0200292 regioncfg.word = ethosu_read_reg(dev, NPU_REG_REGIONCFG);
Kristofer Jonsson49bdee82020-04-06 13:21:21 +0200293 regioncfg.word &= ~(0x3 << (2 * region));
294 regioncfg.word |= (memory_type & 0x3) << (2 * region);
Bhavik Pateldae5be02020-06-18 15:25:15 +0200295 ethosu_write_reg(dev, NPU_REG_REGIONCFG, regioncfg.word);
Kristofer Jonsson125429a2020-08-20 16:52:23 +0200296 LOG_DEBUG("REGIONCFG%u=0x%08x\n", region, regioncfg.word);
Kristofer Jonsson49bdee82020-04-06 13:21:21 +0200297#else
298 // NPU stubbed
Bhavik Pateldae5be02020-06-18 15:25:15 +0200299 UNUSED(dev);
Kristofer Jonsson49bdee82020-04-06 13:21:21 +0200300 UNUSED(region);
301 UNUSED(memory_type);
302#endif
303 return ETHOSU_SUCCESS;
304}
305
Bhavik Pateldae5be02020-06-18 15:25:15 +0200306enum ethosu_error_codes ethosu_set_axi_limit0(struct ethosu_device *dev,
307 enum ethosu_axi_limit_beats max_beats,
Kristofer Jonsson49bdee82020-04-06 13:21:21 +0200308 enum ethosu_axi_limit_mem_type memtype,
309 uint8_t max_reads,
310 uint8_t max_writes)
311{
312#if !defined(ARM_NPU_STUB)
313 struct axi_limit0_r axi_limit0;
Per Åstrand9716b5e2020-08-19 13:15:06 +0200314 axi_limit0.word = 0;
Kristofer Jonsson49bdee82020-04-06 13:21:21 +0200315 axi_limit0.max_beats = max_beats;
316 axi_limit0.memtype = memtype;
317 axi_limit0.max_outstanding_read_m1 = max_reads - 1;
318 axi_limit0.max_outstanding_write_m1 = max_writes - 1;
319
Bhavik Pateldae5be02020-06-18 15:25:15 +0200320 ethosu_write_reg(dev, NPU_REG_AXI_LIMIT0, axi_limit0.word);
Kristofer Jonsson49bdee82020-04-06 13:21:21 +0200321#else
322 // NPU stubbed
Bhavik Pateldae5be02020-06-18 15:25:15 +0200323 UNUSED(dev);
Kristofer Jonsson49bdee82020-04-06 13:21:21 +0200324 UNUSED(max_beats);
325 UNUSED(memtype);
326 UNUSED(max_reads);
327 UNUSED(max_writes);
328#endif
329
330 return ETHOSU_SUCCESS;
331}
332
Bhavik Pateldae5be02020-06-18 15:25:15 +0200333enum ethosu_error_codes ethosu_set_axi_limit1(struct ethosu_device *dev,
334 enum ethosu_axi_limit_beats max_beats,
Kristofer Jonsson49bdee82020-04-06 13:21:21 +0200335 enum ethosu_axi_limit_mem_type memtype,
336 uint8_t max_reads,
337 uint8_t max_writes)
338{
339#if !defined(ARM_NPU_STUB)
340 struct axi_limit1_r axi_limit1;
Per Åstrand9716b5e2020-08-19 13:15:06 +0200341 axi_limit1.word = 0;
Kristofer Jonsson49bdee82020-04-06 13:21:21 +0200342 axi_limit1.max_beats = max_beats;
343 axi_limit1.memtype = memtype;
344 axi_limit1.max_outstanding_read_m1 = max_reads - 1;
345 axi_limit1.max_outstanding_write_m1 = max_writes - 1;
346
Bhavik Pateldae5be02020-06-18 15:25:15 +0200347 ethosu_write_reg(dev, NPU_REG_AXI_LIMIT1, axi_limit1.word);
Kristofer Jonsson49bdee82020-04-06 13:21:21 +0200348#else
349 // NPU stubbed
Bhavik Pateldae5be02020-06-18 15:25:15 +0200350 UNUSED(dev);
Kristofer Jonsson49bdee82020-04-06 13:21:21 +0200351 UNUSED(max_beats);
352 UNUSED(memtype);
353 UNUSED(max_reads);
354 UNUSED(max_writes);
355#endif
356
357 return ETHOSU_SUCCESS;
358}
359
Bhavik Pateldae5be02020-06-18 15:25:15 +0200360enum ethosu_error_codes ethosu_set_axi_limit2(struct ethosu_device *dev,
361 enum ethosu_axi_limit_beats max_beats,
Kristofer Jonsson49bdee82020-04-06 13:21:21 +0200362 enum ethosu_axi_limit_mem_type memtype,
363 uint8_t max_reads,
364 uint8_t max_writes)
365{
366#if !defined(ARM_NPU_STUB)
367 struct axi_limit2_r axi_limit2;
Per Åstrand9716b5e2020-08-19 13:15:06 +0200368 axi_limit2.word = 0;
Kristofer Jonsson49bdee82020-04-06 13:21:21 +0200369 axi_limit2.max_beats = max_beats;
370 axi_limit2.memtype = memtype;
371 axi_limit2.max_outstanding_read_m1 = max_reads - 1;
372 axi_limit2.max_outstanding_write_m1 = max_writes - 1;
373
Bhavik Pateldae5be02020-06-18 15:25:15 +0200374 ethosu_write_reg(dev, NPU_REG_AXI_LIMIT2, axi_limit2.word);
Kristofer Jonsson49bdee82020-04-06 13:21:21 +0200375#else
376 // NPU stubbed
Bhavik Pateldae5be02020-06-18 15:25:15 +0200377 UNUSED(dev);
Kristofer Jonsson49bdee82020-04-06 13:21:21 +0200378 UNUSED(max_beats);
379 UNUSED(memtype);
380 UNUSED(max_reads);
381 UNUSED(max_writes);
382#endif
383
384 return ETHOSU_SUCCESS;
385}
386
Bhavik Pateldae5be02020-06-18 15:25:15 +0200387enum ethosu_error_codes ethosu_set_axi_limit3(struct ethosu_device *dev,
388 enum ethosu_axi_limit_beats max_beats,
Kristofer Jonsson49bdee82020-04-06 13:21:21 +0200389 enum ethosu_axi_limit_mem_type memtype,
390 uint8_t max_reads,
391 uint8_t max_writes)
392{
393#if !defined(ARM_NPU_STUB)
394 struct axi_limit3_r axi_limit3;
Per Åstrand9716b5e2020-08-19 13:15:06 +0200395 axi_limit3.word = 0;
Kristofer Jonsson49bdee82020-04-06 13:21:21 +0200396 axi_limit3.max_beats = max_beats;
397 axi_limit3.memtype = memtype;
398 axi_limit3.max_outstanding_read_m1 = max_reads - 1;
399 axi_limit3.max_outstanding_write_m1 = max_writes - 1;
400
Bhavik Pateldae5be02020-06-18 15:25:15 +0200401 ethosu_write_reg(dev, NPU_REG_AXI_LIMIT3, axi_limit3.word);
Kristofer Jonsson49bdee82020-04-06 13:21:21 +0200402#else
403 // NPU stubbed
Bhavik Pateldae5be02020-06-18 15:25:15 +0200404 UNUSED(dev);
Kristofer Jonsson49bdee82020-04-06 13:21:21 +0200405 UNUSED(max_beats);
406 UNUSED(memtype);
407 UNUSED(max_reads);
408 UNUSED(max_writes);
409#endif
410
411 return ETHOSU_SUCCESS;
412}
413
Bhavik Pateldae5be02020-06-18 15:25:15 +0200414enum ethosu_error_codes ethosu_get_revision(struct ethosu_device *dev, uint32_t *revision)
Kristofer Jonsson49bdee82020-04-06 13:21:21 +0200415{
416#if !defined(ARM_NPU_STUB)
Bhavik Pateldae5be02020-06-18 15:25:15 +0200417 *revision = ethosu_read_reg(dev, NPU_REG_REVISION);
Kristofer Jonsson49bdee82020-04-06 13:21:21 +0200418#else
Bhavik Pateldae5be02020-06-18 15:25:15 +0200419 UNUSED(dev);
420 *revision = 0xDEADC0DE;
Kristofer Jonsson49bdee82020-04-06 13:21:21 +0200421#endif
422 return ETHOSU_SUCCESS;
423}
424
Bhavik Pateldae5be02020-06-18 15:25:15 +0200425enum ethosu_error_codes ethosu_get_qread(struct ethosu_device *dev, uint32_t *qread)
Kristofer Jonsson49bdee82020-04-06 13:21:21 +0200426{
427#if !defined(ARM_NPU_STUB)
Bhavik Pateldae5be02020-06-18 15:25:15 +0200428 *qread = ethosu_read_reg(dev, NPU_REG_QREAD);
Kristofer Jonsson49bdee82020-04-06 13:21:21 +0200429#else
Bhavik Pateldae5be02020-06-18 15:25:15 +0200430 UNUSED(dev);
431 *qread = stream_length;
Kristofer Jonsson49bdee82020-04-06 13:21:21 +0200432#endif
433 return ETHOSU_SUCCESS;
434}
435
Bhavik Pateldae5be02020-06-18 15:25:15 +0200436enum ethosu_error_codes ethosu_get_status_mask(struct ethosu_device *dev, uint16_t *status_mask)
Kristofer Jonsson49bdee82020-04-06 13:21:21 +0200437{
438#if !defined(ARM_NPU_STUB)
439 struct status_r status;
440
Bhavik Pateldae5be02020-06-18 15:25:15 +0200441 status.word = ethosu_read_reg(dev, NPU_REG_STATUS);
Kristofer Jonsson49bdee82020-04-06 13:21:21 +0200442 *status_mask = status.word & 0xFFFF;
443#else
Bhavik Pateldae5be02020-06-18 15:25:15 +0200444 UNUSED(dev);
445 *status_mask = 0x0000;
Kristofer Jonsson49bdee82020-04-06 13:21:21 +0200446#endif
447 return ETHOSU_SUCCESS;
448}
449
Bhavik Pateldae5be02020-06-18 15:25:15 +0200450enum ethosu_error_codes ethosu_get_irq_history_mask(struct ethosu_device *dev, uint16_t *irq_history_mask)
Kristofer Jonsson49bdee82020-04-06 13:21:21 +0200451{
452#if !defined(ARM_NPU_STUB)
453 struct status_r status;
454
Bhavik Pateldae5be02020-06-18 15:25:15 +0200455 status.word = ethosu_read_reg(dev, NPU_REG_STATUS);
Kristofer Jonsson49bdee82020-04-06 13:21:21 +0200456 *irq_history_mask = status.irq_history_mask;
457#else
Bhavik Pateldae5be02020-06-18 15:25:15 +0200458 UNUSED(dev);
Kristofer Jonsson49bdee82020-04-06 13:21:21 +0200459 *irq_history_mask = 0xffff;
460#endif
461 return ETHOSU_SUCCESS;
462}
463
Bhavik Pateldae5be02020-06-18 15:25:15 +0200464enum ethosu_error_codes ethosu_clear_irq_history_mask(struct ethosu_device *dev, uint16_t irq_history_clear_mask)
Kristofer Jonsson49bdee82020-04-06 13:21:21 +0200465{
466#if !defined(ARM_NPU_STUB)
Bhavik Patele645fed2020-06-12 14:46:47 +0200467 struct cmd_r oldcmd;
Bhavik Pateldae5be02020-06-18 15:25:15 +0200468 oldcmd.word = ethosu_read_reg(dev, NPU_REG_CMD);
Bhavik Patele645fed2020-06-12 14:46:47 +0200469
470 struct cmd_r cmd;
471 cmd.word = 0;
472 cmd.clock_q_enable = oldcmd.clock_q_enable;
473 cmd.power_q_enable = oldcmd.power_q_enable;
474 cmd.clear_irq_history = irq_history_clear_mask;
Bhavik Pateldae5be02020-06-18 15:25:15 +0200475 ethosu_write_reg(dev, NPU_REG_CMD, cmd.word);
Kristofer Jonsson49bdee82020-04-06 13:21:21 +0200476#else
Bhavik Pateldae5be02020-06-18 15:25:15 +0200477 UNUSED(dev);
Bhavik Patelbcb5aaa2020-05-12 10:09:41 +0200478 UNUSED(irq_history_clear_mask);
Kristofer Jonsson49bdee82020-04-06 13:21:21 +0200479#endif
480 return ETHOSU_SUCCESS;
481}
482
Bhavik Pateldae5be02020-06-18 15:25:15 +0200483enum ethosu_error_codes ethosu_set_command_run(struct ethosu_device *dev)
Kristofer Jonsson49bdee82020-04-06 13:21:21 +0200484{
485#if !defined(ARM_NPU_STUB)
Bhavik Patele645fed2020-06-12 14:46:47 +0200486 struct cmd_r oldcmd;
Bhavik Pateldae5be02020-06-18 15:25:15 +0200487 oldcmd.word = ethosu_read_reg(dev, NPU_REG_CMD);
Bhavik Patele645fed2020-06-12 14:46:47 +0200488
489 struct cmd_r cmd;
490 cmd.word = 0;
491 cmd.transition_to_running_state = 1;
492 cmd.clock_q_enable = oldcmd.clock_q_enable;
493 cmd.power_q_enable = oldcmd.power_q_enable;
Bhavik Pateldae5be02020-06-18 15:25:15 +0200494 ethosu_write_reg(dev, NPU_REG_CMD, cmd.word);
Kristofer Jonsson49bdee82020-04-06 13:21:21 +0200495#else
Bhavik Pateldae5be02020-06-18 15:25:15 +0200496 UNUSED(dev);
Kristofer Jonsson49bdee82020-04-06 13:21:21 +0200497#endif
498 return ETHOSU_SUCCESS;
499}
500
Bhavik Pateldae5be02020-06-18 15:25:15 +0200501enum ethosu_error_codes ethosu_get_shram_data(struct ethosu_device *dev, int section, uint32_t *shram_p)
Kristofer Jonsson49bdee82020-04-06 13:21:21 +0200502{
503#if !defined(ARM_NPU_STUB)
504 int i = 0;
505 uint32_t address = NPU_REG_SHARED_BUFFER0;
Bhavik Pateldae5be02020-06-18 15:25:15 +0200506 ethosu_write_reg(dev, NPU_REG_DEBUG_ADDRESS, section * BYTES_1KB);
Kristofer Jonsson49bdee82020-04-06 13:21:21 +0200507
508 while (address <= NPU_REG_SHARED_BUFFER255)
509 {
Bhavik Pateldae5be02020-06-18 15:25:15 +0200510 shram_p[i] = ethosu_read_reg(dev, address);
Kristofer Jonsson49bdee82020-04-06 13:21:21 +0200511 address += REG_OFFSET;
512 i++;
513 }
514#else
515 // NPU stubbed
Bhavik Pateldae5be02020-06-18 15:25:15 +0200516 UNUSED(dev);
Kristofer Jonsson49bdee82020-04-06 13:21:21 +0200517 UNUSED(section);
518 UNUSED(shram_p);
519#endif
520
521 return ETHOSU_SUCCESS;
522}
523
Bhavik Pateldae5be02020-06-18 15:25:15 +0200524enum ethosu_error_codes ethosu_set_clock_and_power(struct ethosu_device *dev,
525 enum ethosu_clock_q_request clock_q,
Kristofer Jonsson49bdee82020-04-06 13:21:21 +0200526 enum ethosu_power_q_request power_q)
527{
528#if !defined(ARM_NPU_STUB)
529 struct cmd_r cmd;
530 cmd.word = 0;
531 cmd.clock_q_enable = clock_q;
532 cmd.power_q_enable = power_q;
Bhavik Pateldae5be02020-06-18 15:25:15 +0200533 ethosu_write_reg(dev, NPU_REG_CMD, cmd.word);
Kristofer Jonsson49bdee82020-04-06 13:21:21 +0200534#else
Bhavik Pateldae5be02020-06-18 15:25:15 +0200535 UNUSED(dev);
Kristofer Jonsson49bdee82020-04-06 13:21:21 +0200536 UNUSED(clock_q);
537 UNUSED(power_q);
538#endif
539 return ETHOSU_SUCCESS;
540}
Bhavik Pateldae5be02020-06-18 15:25:15 +0200541
542uint32_t ethosu_read_reg(struct ethosu_device *dev, uint32_t address)
543{
544#if !defined(ARM_NPU_STUB)
Per Åstrandc8019012020-09-28 08:44:42 +0200545 ASSERT(dev->base_address != 0);
Kristofer Jonsson4dc73dc2020-10-16 12:33:47 +0200546 ASSERT(address % 4 == 0);
Bhavik Pateldae5be02020-06-18 15:25:15 +0200547
Kristofer Jonsson4dc73dc2020-10-16 12:33:47 +0200548 volatile uint32_t *reg = dev->base_address + address / sizeof(uint32_t);
Bhavik Pateldae5be02020-06-18 15:25:15 +0200549 return *reg;
550#else
551 UNUSED(dev);
552 UNUSED(address);
553
554 return 0;
555#endif
556}
557
558void ethosu_write_reg(struct ethosu_device *dev, uint32_t address, uint32_t value)
559{
560#if !defined(ARM_NPU_STUB)
Per Åstrandc8019012020-09-28 08:44:42 +0200561 ASSERT(dev->base_address != 0);
Kristofer Jonsson4dc73dc2020-10-16 12:33:47 +0200562 ASSERT(address % 4 == 0);
Bhavik Pateldae5be02020-06-18 15:25:15 +0200563
Kristofer Jonsson4dc73dc2020-10-16 12:33:47 +0200564 volatile uint32_t *reg = dev->base_address + address / sizeof(uint32_t);
Bhavik Pateldae5be02020-06-18 15:25:15 +0200565 *reg = value;
566#else
567 UNUSED(dev);
568 UNUSED(address);
569 UNUSED(value);
570#endif
571}
Bhavik Patel5da40922020-07-15 10:06:43 +0200572
Kristofer Jonsson4dc73dc2020-10-16 12:33:47 +0200573void ethosu_write_reg_shadow(struct ethosu_device *dev, uint32_t address, uint32_t value, uint32_t *shadow)
574{
575 ethosu_write_reg(dev, address, value);
576 *shadow = ethosu_read_reg(dev, address);
577}
578
Bhavik Patel5da40922020-07-15 10:06:43 +0200579enum ethosu_error_codes ethosu_save_pmu_config(struct ethosu_device *dev)
580{
581#if !defined(ARM_NPU_STUB)
Kristofer Jonssonef387ea2020-08-25 16:32:21 +0200582 // Save the PMU control register
583 dev->pmcr = ethosu_read_reg(dev, NPU_REG_PMCR);
584
585 // Save IRQ control
586 dev->pmint = ethosu_read_reg(dev, NPU_REG_PMINTSET);
587
588 // Save the enabled events mask
589 dev->pmcnten = ethosu_read_reg(dev, NPU_REG_PMCNTENSET);
590
591 // Save start and stop event
592 dev->pmccntr_cfg = ethosu_read_reg(dev, NPU_REG_PMCCNTR_CFG);
593
Kristofer Jonssonef387ea2020-08-25 16:32:21 +0200594 // Save the event settings and counters
Bhavik Patel5da40922020-07-15 10:06:43 +0200595 for (uint32_t i = 0; i < ETHOSU_PMU_NCOUNTERS; i++)
596 {
Kristofer Jonssonef387ea2020-08-25 16:32:21 +0200597 dev->pmu_evtypr[i] = ethosu_read_reg(dev, NPU_REG_PMEVTYPER0 + i * sizeof(uint32_t));
Bhavik Patel5da40922020-07-15 10:06:43 +0200598 }
599#else
600 UNUSED(dev);
601#endif
602
603 return ETHOSU_SUCCESS;
604}
605
606enum ethosu_error_codes ethosu_restore_pmu_config(struct ethosu_device *dev)
607{
608#if !defined(ARM_NPU_STUB)
Kristofer Jonssonef387ea2020-08-25 16:32:21 +0200609 // Restore PMU control register
610 ethosu_write_reg(dev, NPU_REG_PMCR, dev->pmcr);
611
612 // Restore IRQ control
613 ethosu_write_reg(dev, NPU_REG_PMINTSET, dev->pmint);
614
615 // Restore enabled event mask
616 ethosu_write_reg(dev, NPU_REG_PMCNTENSET, dev->pmcnten);
617
618 // Restore start and stop event
619 ethosu_write_reg(dev, NPU_REG_PMCCNTR_CFG, dev->pmccntr_cfg);
620
Kristofer Jonsson4dc73dc2020-10-16 12:33:47 +0200621 // Save the event settings and counters
Kristofer Jonssonef387ea2020-08-25 16:32:21 +0200622 for (uint32_t i = 0; i < ETHOSU_PMU_NCOUNTERS; i++)
Bhavik Patel5da40922020-07-15 10:06:43 +0200623 {
Kristofer Jonssonef387ea2020-08-25 16:32:21 +0200624 ethosu_write_reg(dev, NPU_REG_PMEVTYPER0 + i * sizeof(uint32_t), dev->pmu_evtypr[i]);
Bhavik Patel5da40922020-07-15 10:06:43 +0200625 }
626#else
627 UNUSED(dev);
628#endif
629
630 return ETHOSU_SUCCESS;
631}
Bhavik Patel5f8dad12020-09-30 09:06:52 +0200632
Kristofer Jonsson4dc73dc2020-10-16 12:33:47 +0200633enum ethosu_error_codes ethosu_save_pmu_counters(struct ethosu_device *dev)
634{
635#if !defined(ARM_NPU_STUB)
636 // Save the cycle counter
637 dev->pmccntr[0] = ethosu_read_reg(dev, NPU_REG_PMCCNTR_LO);
638 dev->pmccntr[1] = ethosu_read_reg(dev, NPU_REG_PMCCNTR_HI);
639
640 // Save the event settings and counters
641 for (uint32_t i = 0; i < ETHOSU_PMU_NCOUNTERS; i++)
642 {
643 dev->pmu_evcntr[i] = ethosu_read_reg(dev, NPU_REG_PMEVCNTR0 + i * sizeof(uint32_t));
644 }
645#else
646 UNUSED(dev);
647#endif
648
649 return ETHOSU_SUCCESS;
650}
651
Bhavik Patel5f8dad12020-09-30 09:06:52 +0200652bool ethosu_status_has_error(struct ethosu_device *dev)
653{
654 bool status_error = false;
655#if !defined(ARM_NPU_STUB)
656 struct status_r status;
657 status.word = ethosu_read_reg(dev, NPU_REG_STATUS);
658 status_error = ((1 == status.bus_status) || (1 == status.cmd_parse_error) || (1 == status.wd_fault) ||
659 (1 == status.ecc_fault));
660#else
661 UNUSED(dev);
662#endif
663 return status_error;
664}