blob: d6360f48816a182c2c2c3338bd445eb99d2fd608 [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"
Bhavik Patel790ef362020-06-03 10:05:28 +020020
Kristofer Jonsson49bdee82020-04-06 13:21:21 +020021#include <assert.h>
Bhavik Patel790ef362020-06-03 10:05:28 +020022#include <stdbool.h>
23#include <stddef.h>
Kristofer Jonsson49bdee82020-04-06 13:21:21 +020024#include <stdio.h>
25
26#define MASK_0_31_BITS 0xFFFFFFFF
27#define MASK_32_47_BITS 0xFFFF00000000
Bhavik Patel790ef362020-06-03 10:05:28 +020028#define MASK_16_BYTE_ALIGN 0xF
Kristofer Jonsson49bdee82020-04-06 13:21:21 +020029#define BASEP_OFFSET 4
30#define REG_OFFSET 4
31#define BYTES_1KB 1024
32
33#if defined(ARM_NPU_STUB)
34static uint32_t stream_length = 0;
35#endif
36
37enum ethosu_error_codes ethosu_dev_init(void)
38{
39 return ETHOSU_SUCCESS;
40}
41
42enum ethosu_error_codes ethosu_get_id(struct ethosu_id *id)
43{
44 struct id_r _id;
45
46#if !defined(ARM_NPU_STUB)
47 _id.word = read_reg(NPU_REG_ID);
48#else
49 _id.word = 0;
50 _id.arch_patch_rev = NNX_ARCH_VERSION_PATCH;
51 _id.arch_minor_rev = NNX_ARCH_VERSION_MINOR;
52 _id.arch_major_rev = NNX_ARCH_VERSION_MAJOR;
53#endif
54
55 id->version_status = _id.version_status;
56 id->version_minor = _id.version_minor;
57 id->version_major = _id.version_major;
58 id->product_major = _id.product_major;
59 id->arch_patch_rev = _id.arch_patch_rev;
60 id->arch_minor_rev = _id.arch_minor_rev;
61 id->arch_major_rev = _id.arch_major_rev;
62
63 return ETHOSU_SUCCESS;
64}
65
66enum ethosu_error_codes ethosu_get_config(struct ethosu_config *config)
67{
68 struct config_r cfg = {.word = 0};
69
70#if !defined(ARM_NPU_STUB)
71 cfg.word = read_reg(NPU_REG_CONFIG);
72#endif
73
74 config->macs_per_cc = cfg.macs_per_cc;
75 config->cmd_stream_version = cfg.cmd_stream_version;
76 config->shram_size = cfg.shram_size;
77
78 return ETHOSU_SUCCESS;
79}
80
81enum ethosu_error_codes ethosu_run_command_stream(const uint8_t *cmd_stream_ptr,
82 uint32_t cms_length,
83 const uint64_t *base_addr,
84 int num_base_addr)
85{
86#if !defined(ARM_NPU_STUB)
87 uint32_t qbase0;
88 uint32_t qbase1;
89 uint32_t qsize;
90 uint32_t *reg_basep;
91 int num_base_reg;
92
93 ASSERT(num_base_addr <= ETHOSU_DRIVER_BASEP_INDEXES);
94
Bhavik Patel790ef362020-06-03 10:05:28 +020095 if (0 != ((ptrdiff_t)cmd_stream_ptr & MASK_16_BYTE_ALIGN))
96 {
97 LOG_ERR("Error: Command stream addr %p not aligned to 16 bytes\n", cmd_stream_ptr);
98 return ETHOSU_INVALID_PARAM;
99 }
100
101 bool base_addr_invalid = false;
102 for (int i = 0; i < num_base_addr; i++)
103 {
104 if (0 != (base_addr[i] & MASK_16_BYTE_ALIGN))
105 {
106 LOG_ERR("Error: Base addr %d: %p not aligned to 16 bytes\n", i, (void *)(base_addr[i]));
107 base_addr_invalid = true;
108 }
109 }
110 if (base_addr_invalid)
111 {
112 return ETHOSU_INVALID_PARAM;
113 }
114
Kristofer Jonsson49bdee82020-04-06 13:21:21 +0200115 qbase0 = ((uint64_t)cmd_stream_ptr) & MASK_0_31_BITS;
116 qbase1 = (((uint64_t)cmd_stream_ptr) & MASK_32_47_BITS) >> 32;
117 qsize = cms_length;
118 num_base_reg = num_base_addr * 2;
119 reg_basep = (uint32_t *)base_addr;
120
121 for (int i = 0; i < num_base_reg; i++)
122 {
123 write_reg(NPU_REG_BASEP0 + (i * BASEP_OFFSET), reg_basep[i]);
124 }
125
126 write_reg(NPU_REG_QBASE0, qbase0);
127 write_reg(NPU_REG_QBASE1, qbase1);
128 write_reg(NPU_REG_QSIZE, qsize);
129 write_reg(NPU_REG_CMD, 1);
130#else
131 // NPU stubbed
132 stream_length = cms_length;
133 UNUSED(cmd_stream_ptr);
134 UNUSED(base_addr);
135 ASSERT(num_base_addr < ETHOSU_DRIVER_BASEP_INDEXES);
136#if defined(NDEBUG)
137 UNUSED(num_base_addr);
138#endif
139#endif
140
141 return ETHOSU_SUCCESS;
142}
143
144enum ethosu_error_codes ethosu_is_irq_raised(uint8_t *irq_raised)
145{
146#if !defined(ARM_NPU_STUB)
147 struct status_r status;
148 status.word = read_reg(NPU_REG_STATUS);
149 if (status.irq_raised == 1)
150 {
151 *irq_raised = 1;
152 }
153 else
154 {
155 *irq_raised = 0;
156 }
157#else
158 *irq_raised = 1;
159#endif
160 return ETHOSU_SUCCESS;
161}
162
163enum ethosu_error_codes ethosu_clear_irq_status(void)
164{
165#if !defined(ARM_NPU_STUB)
166 write_reg(NPU_REG_CMD, 2);
167#else
168#endif
169 return ETHOSU_SUCCESS;
170}
171
172// TODO Understand settings of privilege/sequrity level and update API.
173enum ethosu_error_codes ethosu_soft_reset(void)
174{
175 enum ethosu_error_codes return_code = ETHOSU_SUCCESS;
176#if !defined(ARM_NPU_STUB)
177 struct reset_r reset;
178 struct prot_r prot;
179
180 reset.word = 0;
181 reset.pending_CPL = PRIVILEGE_LEVEL_USER; // TODO, how to get the host priviledge level
182 reset.pending_CSL = SECURITY_LEVEL_NON_SECURE; // TODO, how to get Security level
183
184 prot.word = read_reg(NPU_REG_PROT);
185
186 if (prot.active_CPL < reset.pending_CPL && prot.active_CSL > reset.pending_CSL)
187 {
188 // Register access not permitted
189 return ETHOSU_GENERIC_FAILURE;
190 }
191 // Reset and set security level
192 write_reg(NPU_REG_RESET, reset.word);
193
194 return_code = ethosu_wait_for_reset();
195#endif
196
197 return return_code;
198}
199
200enum ethosu_error_codes ethosu_wait_for_reset(void)
201{
202#if !defined(ARM_NPU_STUB)
203 struct status_r status;
204
205 // Wait until reset status indicates that reset has been completed
206 for (int i = 0; i < 100000; i++)
207 {
208 status.word = read_reg(NPU_REG_STATUS);
209 if (0 == status.reset_status)
210 {
211 break;
212 }
213 }
214
215 if (1 == status.reset_status)
216 {
217 return ETHOSU_GENERIC_FAILURE;
218 }
219#endif
220
221 return ETHOSU_SUCCESS;
222}
223
224enum ethosu_error_codes ethosu_read_apb_reg(uint32_t start_address, uint16_t num_reg, uint32_t *reg)
225{
226#if !defined(ARM_NPU_STUB)
227 uint32_t address = start_address;
228
Douglas Troha2e7e3b72020-05-14 20:28:31 +0200229 ASSERT((start_address + num_reg) < ID_REGISTERS_SIZE);
Kristofer Jonsson49bdee82020-04-06 13:21:21 +0200230
231 for (int i = 0; i < num_reg; i++)
232 {
233 reg[i] = read_reg(address);
234 address += REG_OFFSET;
235 }
236#else
237 // NPU stubbed
238 UNUSED(start_address);
239 UNUSED(num_reg);
240 UNUSED(reg);
241#endif
242
243 return ETHOSU_SUCCESS;
244}
245
246enum ethosu_error_codes ethosu_set_qconfig(enum ethosu_memory_type memory_type)
247{
248 if (memory_type > ETHOSU_AXI1_OUTSTANDING_COUNTER3)
249 {
250 return ETHOSU_INVALID_PARAM;
251 }
252#if !defined(ARM_NPU_STUB)
253 write_reg(NPU_REG_QCONFIG, memory_type);
254#else
255 // NPU stubbed
256 UNUSED(memory_type);
257#endif
258 return ETHOSU_SUCCESS;
259}
260
261enum ethosu_error_codes ethosu_set_regioncfg(uint8_t region, enum ethosu_memory_type memory_type)
262{
263 if (region > 7)
264 {
265 return ETHOSU_INVALID_PARAM;
266 }
267#if !defined(ARM_NPU_STUB)
268 struct regioncfg_r regioncfg;
269 regioncfg.word = read_reg(NPU_REG_REGIONCFG);
270 regioncfg.word &= ~(0x3 << (2 * region));
271 regioncfg.word |= (memory_type & 0x3) << (2 * region);
272 write_reg(NPU_REG_REGIONCFG, regioncfg.word);
273#else
274 // NPU stubbed
275 UNUSED(region);
276 UNUSED(memory_type);
277#endif
278 return ETHOSU_SUCCESS;
279}
280
281enum ethosu_error_codes ethosu_set_axi_limit0(enum ethosu_axi_limit_beats max_beats,
282 enum ethosu_axi_limit_mem_type memtype,
283 uint8_t max_reads,
284 uint8_t max_writes)
285{
286#if !defined(ARM_NPU_STUB)
287 struct axi_limit0_r axi_limit0;
288 axi_limit0.max_beats = max_beats;
289 axi_limit0.memtype = memtype;
290 axi_limit0.max_outstanding_read_m1 = max_reads - 1;
291 axi_limit0.max_outstanding_write_m1 = max_writes - 1;
292
293 write_reg(NPU_REG_AXI_LIMIT0, axi_limit0.word);
294#else
295 // NPU stubbed
296 UNUSED(max_beats);
297 UNUSED(memtype);
298 UNUSED(max_reads);
299 UNUSED(max_writes);
300#endif
301
302 return ETHOSU_SUCCESS;
303}
304
305enum ethosu_error_codes ethosu_set_axi_limit1(enum ethosu_axi_limit_beats max_beats,
306 enum ethosu_axi_limit_mem_type memtype,
307 uint8_t max_reads,
308 uint8_t max_writes)
309{
310#if !defined(ARM_NPU_STUB)
311 struct axi_limit1_r axi_limit1;
312 axi_limit1.max_beats = max_beats;
313 axi_limit1.memtype = memtype;
314 axi_limit1.max_outstanding_read_m1 = max_reads - 1;
315 axi_limit1.max_outstanding_write_m1 = max_writes - 1;
316
317 write_reg(NPU_REG_AXI_LIMIT1, axi_limit1.word);
318#else
319 // NPU stubbed
320 UNUSED(max_beats);
321 UNUSED(memtype);
322 UNUSED(max_reads);
323 UNUSED(max_writes);
324#endif
325
326 return ETHOSU_SUCCESS;
327}
328
329enum ethosu_error_codes ethosu_set_axi_limit2(enum ethosu_axi_limit_beats max_beats,
330 enum ethosu_axi_limit_mem_type memtype,
331 uint8_t max_reads,
332 uint8_t max_writes)
333{
334#if !defined(ARM_NPU_STUB)
335 struct axi_limit2_r axi_limit2;
336 axi_limit2.max_beats = max_beats;
337 axi_limit2.memtype = memtype;
338 axi_limit2.max_outstanding_read_m1 = max_reads - 1;
339 axi_limit2.max_outstanding_write_m1 = max_writes - 1;
340
341 write_reg(NPU_REG_AXI_LIMIT2, axi_limit2.word);
342#else
343 // NPU stubbed
344 UNUSED(max_beats);
345 UNUSED(memtype);
346 UNUSED(max_reads);
347 UNUSED(max_writes);
348#endif
349
350 return ETHOSU_SUCCESS;
351}
352
353enum ethosu_error_codes ethosu_set_axi_limit3(enum ethosu_axi_limit_beats max_beats,
354 enum ethosu_axi_limit_mem_type memtype,
355 uint8_t max_reads,
356 uint8_t max_writes)
357{
358#if !defined(ARM_NPU_STUB)
359 struct axi_limit3_r axi_limit3;
360 axi_limit3.max_beats = max_beats;
361 axi_limit3.memtype = memtype;
362 axi_limit3.max_outstanding_read_m1 = max_reads - 1;
363 axi_limit3.max_outstanding_write_m1 = max_writes - 1;
364
365 write_reg(NPU_REG_AXI_LIMIT3, axi_limit3.word);
366#else
367 // NPU stubbed
368 UNUSED(max_beats);
369 UNUSED(memtype);
370 UNUSED(max_reads);
371 UNUSED(max_writes);
372#endif
373
374 return ETHOSU_SUCCESS;
375}
376
377enum ethosu_error_codes ethosu_get_revision(uint32_t *revision)
378{
379#if !defined(ARM_NPU_STUB)
380 *revision = read_reg(NPU_REG_REVISION);
381#else
382 *revision = 0xDEADC0DE;
383#endif
384 return ETHOSU_SUCCESS;
385}
386
387enum ethosu_error_codes ethosu_get_qread(uint32_t *qread)
388{
389#if !defined(ARM_NPU_STUB)
390 *qread = read_reg(NPU_REG_QREAD);
391#else
392 *qread = stream_length;
393#endif
394 return ETHOSU_SUCCESS;
395}
396
397enum ethosu_error_codes ethosu_get_status_mask(uint16_t *status_mask)
398{
399#if !defined(ARM_NPU_STUB)
400 struct status_r status;
401
402 status.word = read_reg(NPU_REG_STATUS);
403 *status_mask = status.word & 0xFFFF;
404#else
405 *status_mask = 0x0000;
406#endif
407 return ETHOSU_SUCCESS;
408}
409
410enum ethosu_error_codes ethosu_get_irq_history_mask(uint16_t *irq_history_mask)
411{
412#if !defined(ARM_NPU_STUB)
413 struct status_r status;
414
415 status.word = read_reg(NPU_REG_STATUS);
416 *irq_history_mask = status.irq_history_mask;
417#else
418 *irq_history_mask = 0xffff;
419#endif
420 return ETHOSU_SUCCESS;
421}
422
423enum ethosu_error_codes ethosu_clear_irq_history_mask(uint16_t irq_history_clear_mask)
424{
425#if !defined(ARM_NPU_STUB)
426 write_reg(NPU_REG_CMD, (uint32_t)irq_history_clear_mask << 16);
427#else
Bhavik Patelbcb5aaa2020-05-12 10:09:41 +0200428 UNUSED(irq_history_clear_mask);
Kristofer Jonsson49bdee82020-04-06 13:21:21 +0200429#endif
430 return ETHOSU_SUCCESS;
431}
432
433enum ethosu_error_codes ethosu_set_command_run(void)
434{
435#if !defined(ARM_NPU_STUB)
436 write_reg(NPU_REG_CMD, 1);
437#else
438#endif
439 return ETHOSU_SUCCESS;
440}
441
442enum ethosu_error_codes ethosu_get_shram_data(int section, uint32_t *shram_p)
443{
444#if !defined(ARM_NPU_STUB)
445 int i = 0;
446 uint32_t address = NPU_REG_SHARED_BUFFER0;
Douglas Troha2e7e3b72020-05-14 20:28:31 +0200447 write_reg(NPU_REG_DEBUG_ADDRESS, section * BYTES_1KB);
Kristofer Jonsson49bdee82020-04-06 13:21:21 +0200448
449 while (address <= NPU_REG_SHARED_BUFFER255)
450 {
451 shram_p[i] = read_reg(address);
452 address += REG_OFFSET;
453 i++;
454 }
455#else
456 // NPU stubbed
457 UNUSED(section);
458 UNUSED(shram_p);
459#endif
460
461 return ETHOSU_SUCCESS;
462}
463
464enum ethosu_error_codes ethosu_set_clock_and_power(enum ethosu_clock_q_request clock_q,
465 enum ethosu_power_q_request power_q)
466{
467#if !defined(ARM_NPU_STUB)
468 struct cmd_r cmd;
469 cmd.word = 0;
470 cmd.clock_q_enable = clock_q;
471 cmd.power_q_enable = power_q;
472 write_reg(NPU_REG_CMD, cmd.word);
473#else
474 UNUSED(clock_q);
475 UNUSED(power_q);
476#endif
477 return ETHOSU_SUCCESS;
478}