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