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