blob: ff470d56a82031d97182fff580054b08bbb546a2 [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"
alexander31ae9f02022-02-10 16:15:54 +000021#include "log_macros.h"
alexander3c798932021-03-26 21:42:19 +000022
23#include <stdio.h>
24#include <assert.h>
25
26#if defined(ARM_NPU)
27
Isabella Gottardi118f73e2021-09-16 17:54:35 +010028#include "ethosu_mem_config.h" /* Arm Ethos-U memory config */
Cisco Cervelleraf085fa52021-08-02 09:32:07 +010029#include "ethosu_driver.h" /* Arm Ethos-U driver header */
30#include "timing_adapter.h" /* Arm Ethos-U timing adapter driver header */
alexander31ae9f02022-02-10 16:15:54 +000031
32#if defined(TIMING_ADAPTER_AVAILABLE)
Cisco Cervelleraf085fa52021-08-02 09:32:07 +010033#include "timing_adapter_settings.h" /* Arm Ethos-U timing adapter settings */
alexander31ae9f02022-02-10 16:15:54 +000034#endif /* defined(TIMING_ADAPTER_AVAILABLE) */
alexander3c798932021-03-26 21:42:19 +000035
Cisco Cervellera414b1b92021-09-28 18:15:10 +010036struct ethosu_driver ethosu_drv; /* Default Ethos-U device driver */
Kshitij Sisodia659fcd92021-05-19 10:30:06 +010037
Isabella Gottardi118f73e2021-09-16 17:54:35 +010038#if defined(ETHOS_U_CACHE_BUF_SZ) && (ETHOS_U_CACHE_BUF_SZ > 0)
39 static uint8_t cache_arena[ETHOS_U_CACHE_BUF_SZ] CACHE_BUF_ATTRIBUTE;
40#else /* defined (ETHOS_U_CACHE_BUF_SZ) && (ETHOS_U_CACHE_BUF_SZ > 0) */
41 static uint8_t* cache_arena = NULL;
42#endif /* defined (ETHOS_U_CACHE_BUF_SZ) && (ETHOS_U_CACHE_BUF_SZ > 0) */
43
alexander3c798932021-03-26 21:42:19 +000044/**
Cisco Cervelleraf085fa52021-08-02 09:32:07 +010045 * @brief Initialises the Arm Ethos-U NPU
alexander3c798932021-03-26 21:42:19 +000046 * @return 0 if successful, error code otherwise
47 **/
alexanderc350cdc2021-04-29 20:36:09 +010048static int arm_npu_init(void);
alexander3c798932021-03-26 21:42:19 +000049
Isabella Gottardi118f73e2021-09-16 17:54:35 +010050static uint8_t * get_cache_arena()
51{
52 return cache_arena;
53}
54
55static size_t get_cache_arena_size()
56{
57#if defined(ETHOS_U_CACHE_BUF_SZ) && (ETHOS_U_CACHE_BUF_SZ > 0)
58 return sizeof(cache_arena);
59#else /* defined (ETHOS_U_CACHE_BUF_SZ) && (ETHOS_U_CACHE_BUF_SZ > 0) */
60 return 0;
61#endif /* defined (ETHOS_U_CACHE_BUF_SZ) && (ETHOS_U_CACHE_BUF_SZ > 0) */
62}
63
alexander3c798932021-03-26 21:42:19 +000064#endif /* ARM_NPU */
65
66int hal_init(hal_platform* platform, data_acq_module* data_acq,
67 data_psn_module* data_psn, platform_timer* timer)
68{
69 assert(platform && data_acq && data_psn);
70
71 platform->data_acq = data_acq;
72 platform->data_psn = data_psn;
73 platform->timer = timer;
74 platform->platform_init = system_init;
75 platform->platform_release = system_release;
76 system_name(platform->plat_name, sizeof(platform->plat_name));
77
78 return 0;
79}
80
81/**
82 * @brief Local helper function to clean the slate for current platform.
83 **/
alexanderc350cdc2021-04-29 20:36:09 +010084static void hal_platform_clear(hal_platform* platform)
alexander3c798932021-03-26 21:42:19 +000085{
86 assert(platform);
87 platform->inited = 0;
88}
89
90int hal_platform_init(hal_platform* platform)
91{
92 int state;
93 assert(platform && platform->platform_init);
alexanderc350cdc2021-04-29 20:36:09 +010094 hal_platform_clear(platform);
alexander3c798932021-03-26 21:42:19 +000095
96 /* Initialise platform */
97 if (0 != (state = platform->platform_init())) {
98 printf_err("failed to initialise platform %s\n", platform->plat_name);
99 return state;
100 }
101
102 /* Initialise the data acquisition module */
103 if (0 != (state = data_acq_channel_init(platform->data_acq))) {
104 if (!platform->data_acq->inited) {
105 printf_err("failed to initialise data acq module: %s\n",
106 platform->data_acq->system_name);
107 }
108 hal_platform_release(platform);
109 return state;
110 }
111
112 /* Initialise the presentation module */
113 if (0 != (state = data_psn_system_init(platform->data_psn))) {
114 printf_err("failed to initialise data psn module: %s\n",
115 platform->data_psn->system_name);
116 data_acq_channel_release(platform->data_acq);
117 hal_platform_release(platform);
118 return state;
119 }
120
121#if defined(ARM_NPU)
122
Cisco Cervelleraf085fa52021-08-02 09:32:07 +0100123 /* If Arm Ethos-U NPU is to be used, we initialise it here */
alexanderc350cdc2021-04-29 20:36:09 +0100124 if (0 != (state = arm_npu_init())) {
alexander3c798932021-03-26 21:42:19 +0000125 return state;
126 }
127
128#endif /* ARM_NPU */
129
130 /* followed by the timer module */
131 init_timer(platform->timer);
132
133 info("%s platform initialised\n", platform->plat_name);
134 debug("using %s module for data acquisition\n",
135 platform->data_acq->system_name);
136 debug("using %s module for data presentation\n",
137 platform->data_psn->system_name);
138
139 platform->inited = !state;
140
141 return state;
142}
143
144void hal_platform_release(hal_platform *platform)
145{
146 assert(platform && platform->platform_release);
147 data_acq_channel_release(platform->data_acq);
148 data_psn_system_release(platform->data_psn);
149
alexanderc350cdc2021-04-29 20:36:09 +0100150 hal_platform_clear(platform);
alexander3c798932021-03-26 21:42:19 +0000151 info("releasing platform %s\n", platform->plat_name);
152 platform->platform_release();
153}
154
155#if defined(ARM_NPU)
156/**
157 * @brief Defines the Ethos-U interrupt handler: just a wrapper around the default
158 * implementation.
159 **/
alexanderc350cdc2021-04-29 20:36:09 +0100160static void arm_npu_irq_handler(void)
alexander3c798932021-03-26 21:42:19 +0000161{
162 /* Call the default interrupt handler from the NPU driver */
Kshitij Sisodia659fcd92021-05-19 10:30:06 +0100163 ethosu_irq_handler(&ethosu_drv);
alexander3c798932021-03-26 21:42:19 +0000164}
165
166/**
167 * @brief Initialises the NPU IRQ
168 **/
alexanderc350cdc2021-04-29 20:36:09 +0100169static void arm_npu_irq_init(void)
alexander3c798932021-03-26 21:42:19 +0000170{
171 const IRQn_Type ethosu_irqnum = (IRQn_Type)EthosU_IRQn;
172
173 /* Register the EthosU IRQ handler in our vector table.
174 * Note, this handler comes from the EthosU driver */
alexanderc350cdc2021-04-29 20:36:09 +0100175 NVIC_SetVector(ethosu_irqnum, (uint32_t)arm_npu_irq_handler);
alexander3c798932021-03-26 21:42:19 +0000176
177 /* Enable the IRQ */
178 NVIC_EnableIRQ(ethosu_irqnum);
179
180 debug("EthosU IRQ#: %u, Handler: 0x%p\n",
alexanderc350cdc2021-04-29 20:36:09 +0100181 ethosu_irqnum, arm_npu_irq_handler);
alexander3c798932021-03-26 21:42:19 +0000182}
183
alexander31ae9f02022-02-10 16:15:54 +0000184#if defined(TIMING_ADAPTER_AVAILABLE)
185 static int _arm_npu_timing_adapter_init(void)
186 {
187 #if defined (TA0_BASE)
188 struct timing_adapter ta_0;
189 struct timing_adapter_settings ta_0_settings = {
190 .maxr = TA0_MAXR,
191 .maxw = TA0_MAXW,
192 .maxrw = TA0_MAXRW,
193 .rlatency = TA0_RLATENCY,
194 .wlatency = TA0_WLATENCY,
195 .pulse_on = TA0_PULSE_ON,
196 .pulse_off = TA0_PULSE_OFF,
197 .bwcap = TA0_BWCAP,
198 .perfctrl = TA0_PERFCTRL,
199 .perfcnt = TA0_PERFCNT,
200 .mode = TA0_MODE,
201 .maxpending = 0, /* This is a read-only parameter */
202 .histbin = TA0_HISTBIN,
203 .histcnt = TA0_HISTCNT
204 };
alexander3c798932021-03-26 21:42:19 +0000205
alexander31ae9f02022-02-10 16:15:54 +0000206 if (0 != ta_init(&ta_0, TA0_BASE)) {
207 printf_err("TA0 initialisation failed\n");
208 return 1;
209 }
210
211 ta_set_all(&ta_0, &ta_0_settings);
212 #endif /* defined (TA0_BASE) */
213
214 #if defined (TA1_BASE)
215 struct timing_adapter ta_1;
216 struct timing_adapter_settings ta_1_settings = {
217 .maxr = TA1_MAXR,
218 .maxw = TA1_MAXW,
219 .maxrw = TA1_MAXRW,
220 .rlatency = TA1_RLATENCY,
221 .wlatency = TA1_WLATENCY,
222 .pulse_on = TA1_PULSE_ON,
223 .pulse_off = TA1_PULSE_OFF,
224 .bwcap = TA1_BWCAP,
225 .perfctrl = TA1_PERFCTRL,
226 .perfcnt = TA1_PERFCNT,
227 .mode = TA1_MODE,
228 .maxpending = 0, /* This is a read-only parameter */
229 .histbin = TA1_HISTBIN,
230 .histcnt = TA1_HISTCNT
231 };
232
233 if (0 != ta_init(&ta_1, TA1_BASE)) {
234 printf_err("TA1 initialisation failed\n");
235 return 1;
236 }
237
238 ta_set_all(&ta_1, &ta_1_settings);
239 #endif /* defined (TA1_BASE) */
240
241 return 0;
alexander3c798932021-03-26 21:42:19 +0000242 }
alexander31ae9f02022-02-10 16:15:54 +0000243#endif /* defined(TIMING_ADAPTER_AVAILABLE) */
alexander3c798932021-03-26 21:42:19 +0000244
alexanderc350cdc2021-04-29 20:36:09 +0100245static int arm_npu_init(void)
alexander3c798932021-03-26 21:42:19 +0000246{
247 int err = 0;
248
Cisco Cervelleraf085fa52021-08-02 09:32:07 +0100249 /* If the platform has timing adapter blocks along with Ethos-U core
alexander3c798932021-03-26 21:42:19 +0000250 * block, initialise them here. */
alexander31ae9f02022-02-10 16:15:54 +0000251#if defined(TIMING_ADAPTER_AVAILABLE)
alexander3c798932021-03-26 21:42:19 +0000252 if (0 != (err = _arm_npu_timing_adapter_init())) {
253 return err;
254 }
alexander31ae9f02022-02-10 16:15:54 +0000255#endif /* defined(TIMING_ADAPTER_AVAILABLE) */
alexander3c798932021-03-26 21:42:19 +0000256
257 /* Initialise the IRQ */
alexanderc350cdc2021-04-29 20:36:09 +0100258 arm_npu_irq_init();
alexander3c798932021-03-26 21:42:19 +0000259
Cisco Cervelleraf085fa52021-08-02 09:32:07 +0100260 /* Initialise Ethos-U device */
261 const void * ethosu_base_address = (void *)(SEC_ETHOS_U_NPU_BASE);
alexander3c798932021-03-26 21:42:19 +0000262
Kshitij Sisodia659fcd92021-05-19 10:30:06 +0100263 if (0 != (err = ethosu_init(
Isabella Gottardi118f73e2021-09-16 17:54:35 +0100264 &ethosu_drv, /* Ethos-U driver device pointer */
265 ethosu_base_address, /* Ethos-U NPU's base address. */
266 get_cache_arena(), /* Pointer to fast mem area - NULL for U55. */
267 get_cache_arena_size(), /* Fast mem region size. */
268 1, /* Security enable. */
269 1))) { /* Privilege enable. */
Cisco Cervelleraf085fa52021-08-02 09:32:07 +0100270 printf_err("failed to initalise Ethos-U device\n");
alexander3c798932021-03-26 21:42:19 +0000271 return err;
272 }
273
Cisco Cervelleraf085fa52021-08-02 09:32:07 +0100274 info("Ethos-U device initialised\n");
alexander3c798932021-03-26 21:42:19 +0000275
Cisco Cervelleraf085fa52021-08-02 09:32:07 +0100276 /* Get Ethos-U version */
Cisco Cervellera414b1b92021-09-28 18:15:10 +0100277 struct ethosu_driver_version driver_version;
278 struct ethosu_hw_info hw_info;
alexander31ae9f02022-02-10 16:15:54 +0000279
Cisco Cervellera414b1b92021-09-28 18:15:10 +0100280 ethosu_get_driver_version(&driver_version);
281 ethosu_get_hw_info(&ethosu_drv, &hw_info);
alexander3c798932021-03-26 21:42:19 +0000282
Cisco Cervelleraf085fa52021-08-02 09:32:07 +0100283 info("Ethos-U version info:\n");
alexander31ae9f02022-02-10 16:15:54 +0000284 info("\tArch: v%"PRIu32".%"PRIu32".%"PRIu32"\n",
Cisco Cervellera414b1b92021-09-28 18:15:10 +0100285 hw_info.version.arch_major_rev,
286 hw_info.version.arch_minor_rev,
287 hw_info.version.arch_patch_rev);
alexander31ae9f02022-02-10 16:15:54 +0000288 info("\tDriver: v%"PRIu8".%"PRIu8".%"PRIu8"\n",
Cisco Cervellera414b1b92021-09-28 18:15:10 +0100289 driver_version.major,
290 driver_version.minor,
291 driver_version.patch);
292 info("\tMACs/cc: %"PRIu32"\n", (uint32_t)(1 << hw_info.cfg.macs_per_cc));
293 info("\tCmd stream: v%"PRIu32"\n", hw_info.cfg.cmd_stream_version);
alexander3c798932021-03-26 21:42:19 +0000294
295 return 0;
296}
Isabella Gottardi118f73e2021-09-16 17:54:35 +0100297
alexander3c798932021-03-26 21:42:19 +0000298#endif /* ARM_NPU */