blob: 9c2ce322228314ff1a5c34f2a506797bfad28924 [file] [log] [blame]
alexander3c798932021-03-26 21:42:19 +00001/*
2 * Copyright (c) 2021 Arm Limited. All rights reserved.
3 * SPDX-License-Identifier: Apache-2.0
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17#include "hal.h" /* API */
18
19#include "hal_config.h" /* HAL configuration */
20#include "system_init.h"
21
22#include <stdio.h>
23#include <assert.h>
24
25#if defined(ARM_NPU)
26
27#include "ethosu_driver.h" /* Arm Ethos-U55 driver header */
28#include "timing_adapter.h" /* Arm Ethos-U55 timing adapter driver header */
29#include "timing_adapter_settings.h" /* Arm Ethos-U55 timing adapter settings */
30
31/**
32 * @brief Initialises the Arm Ethos-U55 NPU
33 * @return 0 if successful, error code otherwise
34 **/
alexanderc350cdc2021-04-29 20:36:09 +010035static int arm_npu_init(void);
alexander3c798932021-03-26 21:42:19 +000036
37#endif /* ARM_NPU */
38
39int hal_init(hal_platform* platform, data_acq_module* data_acq,
40 data_psn_module* data_psn, platform_timer* timer)
41{
42 assert(platform && data_acq && data_psn);
43
44 platform->data_acq = data_acq;
45 platform->data_psn = data_psn;
46 platform->timer = timer;
47 platform->platform_init = system_init;
48 platform->platform_release = system_release;
49 system_name(platform->plat_name, sizeof(platform->plat_name));
50
51 return 0;
52}
53
54/**
55 * @brief Local helper function to clean the slate for current platform.
56 **/
alexanderc350cdc2021-04-29 20:36:09 +010057static void hal_platform_clear(hal_platform* platform)
alexander3c798932021-03-26 21:42:19 +000058{
59 assert(platform);
60 platform->inited = 0;
61}
62
63int hal_platform_init(hal_platform* platform)
64{
65 int state;
66 assert(platform && platform->platform_init);
alexanderc350cdc2021-04-29 20:36:09 +010067 hal_platform_clear(platform);
alexander3c798932021-03-26 21:42:19 +000068
69 /* Initialise platform */
70 if (0 != (state = platform->platform_init())) {
71 printf_err("failed to initialise platform %s\n", platform->plat_name);
72 return state;
73 }
74
75 /* Initialise the data acquisition module */
76 if (0 != (state = data_acq_channel_init(platform->data_acq))) {
77 if (!platform->data_acq->inited) {
78 printf_err("failed to initialise data acq module: %s\n",
79 platform->data_acq->system_name);
80 }
81 hal_platform_release(platform);
82 return state;
83 }
84
85 /* Initialise the presentation module */
86 if (0 != (state = data_psn_system_init(platform->data_psn))) {
87 printf_err("failed to initialise data psn module: %s\n",
88 platform->data_psn->system_name);
89 data_acq_channel_release(platform->data_acq);
90 hal_platform_release(platform);
91 return state;
92 }
93
94#if defined(ARM_NPU)
95
96 /* If Arm Ethos-U55 NPU is to be used, we initialise it here */
alexanderc350cdc2021-04-29 20:36:09 +010097 if (0 != (state = arm_npu_init())) {
alexander3c798932021-03-26 21:42:19 +000098 return state;
99 }
100
101#endif /* ARM_NPU */
102
103 /* followed by the timer module */
104 init_timer(platform->timer);
105
106 info("%s platform initialised\n", platform->plat_name);
107 debug("using %s module for data acquisition\n",
108 platform->data_acq->system_name);
109 debug("using %s module for data presentation\n",
110 platform->data_psn->system_name);
111
112 platform->inited = !state;
113
114 return state;
115}
116
117void hal_platform_release(hal_platform *platform)
118{
119 assert(platform && platform->platform_release);
120 data_acq_channel_release(platform->data_acq);
121 data_psn_system_release(platform->data_psn);
122
alexanderc350cdc2021-04-29 20:36:09 +0100123 hal_platform_clear(platform);
alexander3c798932021-03-26 21:42:19 +0000124 info("releasing platform %s\n", platform->plat_name);
125 platform->platform_release();
126}
127
128#if defined(ARM_NPU)
129/**
130 * @brief Defines the Ethos-U interrupt handler: just a wrapper around the default
131 * implementation.
132 **/
alexanderc350cdc2021-04-29 20:36:09 +0100133static void arm_npu_irq_handler(void)
alexander3c798932021-03-26 21:42:19 +0000134{
135 /* Call the default interrupt handler from the NPU driver */
136 ethosu_irq_handler();
137}
138
139/**
140 * @brief Initialises the NPU IRQ
141 **/
alexanderc350cdc2021-04-29 20:36:09 +0100142static void arm_npu_irq_init(void)
alexander3c798932021-03-26 21:42:19 +0000143{
144 const IRQn_Type ethosu_irqnum = (IRQn_Type)EthosU_IRQn;
145
146 /* Register the EthosU IRQ handler in our vector table.
147 * Note, this handler comes from the EthosU driver */
alexanderc350cdc2021-04-29 20:36:09 +0100148 NVIC_SetVector(ethosu_irqnum, (uint32_t)arm_npu_irq_handler);
alexander3c798932021-03-26 21:42:19 +0000149
150 /* Enable the IRQ */
151 NVIC_EnableIRQ(ethosu_irqnum);
152
153 debug("EthosU IRQ#: %u, Handler: 0x%p\n",
alexanderc350cdc2021-04-29 20:36:09 +0100154 ethosu_irqnum, arm_npu_irq_handler);
alexander3c798932021-03-26 21:42:19 +0000155}
156
157static int _arm_npu_timing_adapter_init(void)
158{
159#if defined (TA0_BASE)
160 struct timing_adapter ta_0;
161 struct timing_adapter_settings ta_0_settings = {
162 .maxr = TA0_MAXR,
163 .maxw = TA0_MAXW,
164 .maxrw = TA0_MAXRW,
165 .rlatency = TA0_RLATENCY,
166 .wlatency = TA0_WLATENCY,
167 .pulse_on = TA0_PULSE_ON,
168 .pulse_off = TA0_PULSE_OFF,
169 .bwcap = TA0_BWCAP,
170 .perfctrl = TA0_PERFCTRL,
171 .perfcnt = TA0_PERFCNT,
172 .mode = TA0_MODE,
173 .maxpending = 0, /* This is a read-only parameter */
174 .histbin = TA0_HISTBIN,
175 .histcnt = TA0_HISTCNT
176 };
177
178 if (0 != ta_init(&ta_0, TA0_BASE)) {
179 printf_err("TA0 initialisation failed\n");
180 return 1;
181 }
182
183 ta_set_all(&ta_0, &ta_0_settings);
184#endif /* defined (TA0_BASE) */
185
186#if defined (TA1_BASE)
187 struct timing_adapter ta_1;
188 struct timing_adapter_settings ta_1_settings = {
189 .maxr = TA1_MAXR,
190 .maxw = TA1_MAXW,
191 .maxrw = TA1_MAXRW,
192 .rlatency = TA1_RLATENCY,
193 .wlatency = TA1_WLATENCY,
194 .pulse_on = TA1_PULSE_ON,
195 .pulse_off = TA1_PULSE_OFF,
196 .bwcap = TA1_BWCAP,
197 .perfctrl = TA1_PERFCTRL,
198 .perfcnt = TA1_PERFCNT,
199 .mode = TA1_MODE,
200 .maxpending = 0, /* This is a read-only parameter */
201 .histbin = TA1_HISTBIN,
202 .histcnt = TA1_HISTCNT
203 };
204
205 if (0 != ta_init(&ta_1, TA1_BASE)) {
206 printf_err("TA1 initialisation failed\n");
207 return 1;
208 }
209
210 ta_set_all(&ta_1, &ta_1_settings);
211#endif /* defined (TA1_BASE) */
212
213 return 0;
214}
215
alexanderc350cdc2021-04-29 20:36:09 +0100216static int arm_npu_init(void)
alexander3c798932021-03-26 21:42:19 +0000217{
218 int err = 0;
219
220 /* If the platform has timing adapter blocks along with Ethos-U55 core
221 * block, initialise them here. */
222 if (0 != (err = _arm_npu_timing_adapter_init())) {
223 return err;
224 }
225
226 /* Initialise the IRQ */
alexanderc350cdc2021-04-29 20:36:09 +0100227 arm_npu_irq_init();
alexander3c798932021-03-26 21:42:19 +0000228
229 /* Initialise Ethos-U55 device */
230 const void * ethosu_base_address = (void *)(SEC_ETHOS_U55_BASE);
231
232 if (0 != (err = ethosu_init_v3(
233 ethosu_base_address, /* Ethos-U55's base address. */
234 NULL, /* Pointer to fast mem area - NULL for U55. */
235 0, /* Fast mem region size. */
236 1, /* Security enable. */
237 1))) { /* Privilege enable. */
238 printf_err("failed to initalise Ethos-U55 device\n");
239 return err;
240 }
241
242 info("Ethos-U55 device initialised\n");
243
244 /* Get Ethos-U55 version */
245 struct ethosu_version version;
246 if (0 != (err = ethosu_get_version(&version))) {
247 printf_err("failed to fetch Ethos-U55 version info\n");
248 return err;
249 }
250
251 info("Ethos-U55 version info:\n");
252 info("\tArch: v%u.%u.%u\n", version.id.arch_major_rev,
253 version.id.arch_minor_rev,
254 version.id.arch_patch_rev);
255 info("\tDriver: v%u.%u.%u\n", version.id.driver_major_rev,
256 version.id.driver_minor_rev,
257 version.id.driver_patch_rev);
258 info("\tMACs/cc: %u\n", (1 << version.cfg.macs_per_cc));
259 info("\tCmd stream: v%u\n", version.cfg.cmd_stream_version);
260 info("\tSHRAM size: %u\n", version.cfg.shram_size);
261
262 return 0;
263}
264#endif /* ARM_NPU */