blob: 2ce26849df9ed3419d3f38d815a742b819658445 [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
Kshitij Sisodia659fcd92021-05-19 10:30:06 +010031extern struct ethosu_driver ethosu_drv; /* Default Ethos-U55 device driver */
32
alexander3c798932021-03-26 21:42:19 +000033/**
34 * @brief Initialises the Arm Ethos-U55 NPU
35 * @return 0 if successful, error code otherwise
36 **/
alexanderc350cdc2021-04-29 20:36:09 +010037static int arm_npu_init(void);
alexander3c798932021-03-26 21:42:19 +000038
39#endif /* ARM_NPU */
40
41int hal_init(hal_platform* platform, data_acq_module* data_acq,
42 data_psn_module* data_psn, platform_timer* timer)
43{
44 assert(platform && data_acq && data_psn);
45
46 platform->data_acq = data_acq;
47 platform->data_psn = data_psn;
48 platform->timer = timer;
49 platform->platform_init = system_init;
50 platform->platform_release = system_release;
51 system_name(platform->plat_name, sizeof(platform->plat_name));
52
53 return 0;
54}
55
56/**
57 * @brief Local helper function to clean the slate for current platform.
58 **/
alexanderc350cdc2021-04-29 20:36:09 +010059static void hal_platform_clear(hal_platform* platform)
alexander3c798932021-03-26 21:42:19 +000060{
61 assert(platform);
62 platform->inited = 0;
63}
64
65int hal_platform_init(hal_platform* platform)
66{
67 int state;
68 assert(platform && platform->platform_init);
alexanderc350cdc2021-04-29 20:36:09 +010069 hal_platform_clear(platform);
alexander3c798932021-03-26 21:42:19 +000070
71 /* Initialise platform */
72 if (0 != (state = platform->platform_init())) {
73 printf_err("failed to initialise platform %s\n", platform->plat_name);
74 return state;
75 }
76
77 /* Initialise the data acquisition module */
78 if (0 != (state = data_acq_channel_init(platform->data_acq))) {
79 if (!platform->data_acq->inited) {
80 printf_err("failed to initialise data acq module: %s\n",
81 platform->data_acq->system_name);
82 }
83 hal_platform_release(platform);
84 return state;
85 }
86
87 /* Initialise the presentation module */
88 if (0 != (state = data_psn_system_init(platform->data_psn))) {
89 printf_err("failed to initialise data psn module: %s\n",
90 platform->data_psn->system_name);
91 data_acq_channel_release(platform->data_acq);
92 hal_platform_release(platform);
93 return state;
94 }
95
96#if defined(ARM_NPU)
97
98 /* If Arm Ethos-U55 NPU is to be used, we initialise it here */
alexanderc350cdc2021-04-29 20:36:09 +010099 if (0 != (state = arm_npu_init())) {
alexander3c798932021-03-26 21:42:19 +0000100 return state;
101 }
102
103#endif /* ARM_NPU */
104
105 /* followed by the timer module */
106 init_timer(platform->timer);
107
108 info("%s platform initialised\n", platform->plat_name);
109 debug("using %s module for data acquisition\n",
110 platform->data_acq->system_name);
111 debug("using %s module for data presentation\n",
112 platform->data_psn->system_name);
113
114 platform->inited = !state;
115
116 return state;
117}
118
119void hal_platform_release(hal_platform *platform)
120{
121 assert(platform && platform->platform_release);
122 data_acq_channel_release(platform->data_acq);
123 data_psn_system_release(platform->data_psn);
124
alexanderc350cdc2021-04-29 20:36:09 +0100125 hal_platform_clear(platform);
alexander3c798932021-03-26 21:42:19 +0000126 info("releasing platform %s\n", platform->plat_name);
127 platform->platform_release();
128}
129
130#if defined(ARM_NPU)
131/**
132 * @brief Defines the Ethos-U interrupt handler: just a wrapper around the default
133 * implementation.
134 **/
alexanderc350cdc2021-04-29 20:36:09 +0100135static void arm_npu_irq_handler(void)
alexander3c798932021-03-26 21:42:19 +0000136{
137 /* Call the default interrupt handler from the NPU driver */
Kshitij Sisodia659fcd92021-05-19 10:30:06 +0100138 ethosu_irq_handler(&ethosu_drv);
alexander3c798932021-03-26 21:42:19 +0000139}
140
141/**
142 * @brief Initialises the NPU IRQ
143 **/
alexanderc350cdc2021-04-29 20:36:09 +0100144static void arm_npu_irq_init(void)
alexander3c798932021-03-26 21:42:19 +0000145{
146 const IRQn_Type ethosu_irqnum = (IRQn_Type)EthosU_IRQn;
147
148 /* Register the EthosU IRQ handler in our vector table.
149 * Note, this handler comes from the EthosU driver */
alexanderc350cdc2021-04-29 20:36:09 +0100150 NVIC_SetVector(ethosu_irqnum, (uint32_t)arm_npu_irq_handler);
alexander3c798932021-03-26 21:42:19 +0000151
152 /* Enable the IRQ */
153 NVIC_EnableIRQ(ethosu_irqnum);
154
155 debug("EthosU IRQ#: %u, Handler: 0x%p\n",
alexanderc350cdc2021-04-29 20:36:09 +0100156 ethosu_irqnum, arm_npu_irq_handler);
alexander3c798932021-03-26 21:42:19 +0000157}
158
159static int _arm_npu_timing_adapter_init(void)
160{
161#if defined (TA0_BASE)
162 struct timing_adapter ta_0;
163 struct timing_adapter_settings ta_0_settings = {
164 .maxr = TA0_MAXR,
165 .maxw = TA0_MAXW,
166 .maxrw = TA0_MAXRW,
167 .rlatency = TA0_RLATENCY,
168 .wlatency = TA0_WLATENCY,
169 .pulse_on = TA0_PULSE_ON,
170 .pulse_off = TA0_PULSE_OFF,
171 .bwcap = TA0_BWCAP,
172 .perfctrl = TA0_PERFCTRL,
173 .perfcnt = TA0_PERFCNT,
174 .mode = TA0_MODE,
175 .maxpending = 0, /* This is a read-only parameter */
176 .histbin = TA0_HISTBIN,
177 .histcnt = TA0_HISTCNT
178 };
179
180 if (0 != ta_init(&ta_0, TA0_BASE)) {
181 printf_err("TA0 initialisation failed\n");
182 return 1;
183 }
184
185 ta_set_all(&ta_0, &ta_0_settings);
186#endif /* defined (TA0_BASE) */
187
188#if defined (TA1_BASE)
189 struct timing_adapter ta_1;
190 struct timing_adapter_settings ta_1_settings = {
191 .maxr = TA1_MAXR,
192 .maxw = TA1_MAXW,
193 .maxrw = TA1_MAXRW,
194 .rlatency = TA1_RLATENCY,
195 .wlatency = TA1_WLATENCY,
196 .pulse_on = TA1_PULSE_ON,
197 .pulse_off = TA1_PULSE_OFF,
198 .bwcap = TA1_BWCAP,
199 .perfctrl = TA1_PERFCTRL,
200 .perfcnt = TA1_PERFCNT,
201 .mode = TA1_MODE,
202 .maxpending = 0, /* This is a read-only parameter */
203 .histbin = TA1_HISTBIN,
204 .histcnt = TA1_HISTCNT
205 };
206
207 if (0 != ta_init(&ta_1, TA1_BASE)) {
208 printf_err("TA1 initialisation failed\n");
209 return 1;
210 }
211
212 ta_set_all(&ta_1, &ta_1_settings);
213#endif /* defined (TA1_BASE) */
214
215 return 0;
216}
217
alexanderc350cdc2021-04-29 20:36:09 +0100218static int arm_npu_init(void)
alexander3c798932021-03-26 21:42:19 +0000219{
220 int err = 0;
221
222 /* If the platform has timing adapter blocks along with Ethos-U55 core
223 * block, initialise them here. */
224 if (0 != (err = _arm_npu_timing_adapter_init())) {
225 return err;
226 }
227
228 /* Initialise the IRQ */
alexanderc350cdc2021-04-29 20:36:09 +0100229 arm_npu_irq_init();
alexander3c798932021-03-26 21:42:19 +0000230
231 /* Initialise Ethos-U55 device */
232 const void * ethosu_base_address = (void *)(SEC_ETHOS_U55_BASE);
233
Kshitij Sisodia659fcd92021-05-19 10:30:06 +0100234 if (0 != (err = ethosu_init(
235 &ethosu_drv, /* Ethos-U55 driver device pointer */
alexander3c798932021-03-26 21:42:19 +0000236 ethosu_base_address, /* Ethos-U55's base address. */
237 NULL, /* Pointer to fast mem area - NULL for U55. */
238 0, /* Fast mem region size. */
239 1, /* Security enable. */
240 1))) { /* Privilege enable. */
241 printf_err("failed to initalise Ethos-U55 device\n");
242 return err;
243 }
244
245 info("Ethos-U55 device initialised\n");
246
247 /* Get Ethos-U55 version */
248 struct ethosu_version version;
Kshitij Sisodia659fcd92021-05-19 10:30:06 +0100249 if (0 != (err = ethosu_get_version(&ethosu_drv, &version))) {
alexander3c798932021-03-26 21:42:19 +0000250 printf_err("failed to fetch Ethos-U55 version info\n");
251 return err;
252 }
253
254 info("Ethos-U55 version info:\n");
255 info("\tArch: v%u.%u.%u\n", version.id.arch_major_rev,
256 version.id.arch_minor_rev,
257 version.id.arch_patch_rev);
258 info("\tDriver: v%u.%u.%u\n", version.id.driver_major_rev,
259 version.id.driver_minor_rev,
260 version.id.driver_patch_rev);
261 info("\tMACs/cc: %u\n", (1 << version.cfg.macs_per_cc));
262 info("\tCmd stream: v%u\n", version.cfg.cmd_stream_version);
263 info("\tSHRAM size: %u\n", version.cfg.shram_size);
264
265 return 0;
266}
267#endif /* ARM_NPU */