1 /*
2  * SPDX-FileCopyrightText: Copyright 2019-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
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 #ifndef ETHOSU_DRIVER_H
20 #define ETHOSU_DRIVER_H
21 
22 /******************************************************************************
23  * Includes
24  ******************************************************************************/
25 
26 #include "ethosu_types.h"
27 
28 #include <stdbool.h>
29 #include <stddef.h>
30 #include <stdint.h>
31 
32 #ifdef __cplusplus
33 extern "C" {
34 #endif
35 
36 /******************************************************************************
37  * Defines
38  ******************************************************************************/
39 
40 #define ETHOSU_DRIVER_VERSION_MAJOR 0  ///< Driver major version
41 #define ETHOSU_DRIVER_VERSION_MINOR 16 ///< Driver minor version
42 #define ETHOSU_DRIVER_VERSION_PATCH 0  ///< Driver patch version
43 
44 #define ETHOSU_SEMAPHORE_WAIT_FOREVER (UINT64_MAX)
45 
46 #ifndef ETHOSU_SEMAPHORE_WAIT_INFERENCE
47 #define ETHOSU_SEMAPHORE_WAIT_INFERENCE ETHOSU_SEMAPHORE_WAIT_FOREVER
48 #endif
49 
50 /******************************************************************************
51  * Types
52  ******************************************************************************/
53 
54 // Forward declare
55 struct ethosu_device;
56 
57 enum ethosu_job_state
58 {
59     ETHOSU_JOB_IDLE = 0,
60     ETHOSU_JOB_RUNNING,
61     ETHOSU_JOB_DONE
62 };
63 
64 enum ethosu_job_result
65 {
66     ETHOSU_JOB_RESULT_OK = 0,
67     ETHOSU_JOB_RESULT_TIMEOUT,
68     ETHOSU_JOB_RESULT_ERROR
69 };
70 
71 struct ethosu_job
72 {
73     volatile enum ethosu_job_state state;
74     volatile enum ethosu_job_result result;
75     const void *custom_data_ptr;
76     int custom_data_size;
77     const uint64_t *base_addr;
78     const size_t *base_addr_size;
79     int num_base_addr;
80     void *user_arg;
81 };
82 
83 struct ethosu_driver
84 {
85     struct ethosu_device *dev;
86     struct ethosu_driver *next;
87     struct ethosu_job job;
88     void *semaphore;
89     uint64_t fast_memory;
90     size_t fast_memory_size;
91     uint32_t power_request_counter;
92     bool reserved;
93 };
94 
95 struct ethosu_driver_version
96 {
97     uint8_t major;
98     uint8_t minor;
99     uint8_t patch;
100 };
101 
102 enum ethosu_request_clients
103 {
104     ETHOSU_PMU_REQUEST       = 0,
105     ETHOSU_INFERENCE_REQUEST = 1,
106 };
107 
108 /******************************************************************************
109  * Prototypes (weak functions in driver)
110  ******************************************************************************/
111 
112 /**
113  * Interrupt handler to be called on IRQ from Ethos-U
114  *
115  * @param drv       Pointer to driver handle
116  */
117 void ethosu_irq_handler(struct ethosu_driver *drv);
118 
119 /**
120  * Flush/clean the data cache by address and size. Passing NULL as p argument
121  * expects the whole cache to be flushed.
122  *
123  * Addresses passed to this function must be 16 byte aligned.
124  *
125  * @param p         16 byte aligned address
126  * @param bytes     Size of memory block in bytes
127  */
128 void ethosu_flush_dcache(uint32_t *p, size_t bytes);
129 
130 /**
131  * Invalidate the data cache by address and size. Passing NULL as p argument
132  * expects the whole cache to be invalidated.
133  *
134  * Addresses passed to this function must be 16 byte aligned.
135  *
136  * @param p         16 byte aligned address
137  * @param bytes     Size in bytes
138  */
139 void ethosu_invalidate_dcache(uint32_t *p, size_t bytes);
140 
141 /**
142  * Minimal mutex implementation for baremetal applications. See
143  * ethosu_driver.c.
144  *
145  * @return Pointer to mutex handle
146  */
147 void *ethosu_mutex_create(void);
148 
149 /**
150  * Minimal sempahore implementation for baremetal applications. See
151  * ethosu_driver.c.
152  *
153  * @return Pointer to semaphore handle
154  */
155 void *ethosu_semaphore_create(void);
156 
157 /**
158  * Lock mutex.
159  *
160  * @param mutex     Pointer to mutex handle
161  * @returns 0 on success, else negative error code
162  */
163 int ethosu_mutex_lock(void *mutex);
164 
165 /**
166  * Unlock mutex.
167  *
168  * @param mutex     Pointer to mutex handle
169  * @returns 0 on success, else negative error code
170  */
171 int ethosu_mutex_unlock(void *mutex);
172 
173 /**
174  * Take semaphore.
175  *
176  * @param sem       Pointer to semaphore handle
177  * @param timeout   Timeout value (unit impl. defined)
178  * @returns 0 on success else negative error code
179  */
180 int ethosu_semaphore_take(void *sem, uint64_t timeout);
181 
182 /**
183  * Give semaphore.
184  *
185  * @param sem       Pointer to semaphore handle
186  * @returns 0 on success, else negative error code
187  */
188 int ethosu_semaphore_give(void *sem);
189 
190 /**
191  * Callback invoked just before the inference is started.
192  *
193  * @param drv       Pointer to driver handle
194  * @param user_arg  User argument provided to ethosu_invoke_*()
195  */
196 void ethosu_inference_begin(struct ethosu_driver *drv, void *user_arg);
197 
198 /**
199  * Callback invoked just after the inference has completed.
200  *
201  * @param drv       Pointer to driver handle
202  * @param user_arg  User argument provided to ethosu_invoke_*()
203  */
204 void ethosu_inference_end(struct ethosu_driver *drv, void *user_arg);
205 
206 /**
207  * Remapping command stream and base pointer addresses.
208  *
209  * @param address   Address to be remapped.
210  * @param index     -1 command stream, 0-n base address index
211  *
212  * @return Remapped address
213  */
214 uint64_t ethosu_address_remap(uint64_t address, int index);
215 
216 /******************************************************************************
217  * Prototypes
218  ******************************************************************************/
219 
220 /**
221  * Initialize the Ethos-U driver.
222  *
223  * @param drv               Pointer to driver handle
224  * @param base_address      NPU register base address
225  * @param fast_memory       Fast memory area, used for Ethos-U65 with spilling
226  * @param fast_memory_size  Size in bytes of fast memory area
227  * @param secure_enable     Configure NPU in secure- or non-secure mode
228  * @param privilege_enable  Configure NPU in privileged- or non-privileged mode
229  * @return 0 on success, else negative error code
230  */
231 int ethosu_init(struct ethosu_driver *drv,
232                 void *const base_address,
233                 const void *fast_memory,
234                 const size_t fast_memory_size,
235                 uint32_t secure_enable,
236                 uint32_t privilege_enable);
237 
238 /**
239  * Deinitialize the Ethos-U driver.
240  *
241  * @param drv       Pointer to driver handle
242  */
243 void ethosu_deinit(struct ethosu_driver *drv);
244 
245 /**
246  * Soft resets the Ethos-U device.
247  *
248  * @param drv       Pointer to driver handle
249  * @return 0 on success, else negative error code
250  */
251 int ethosu_soft_reset(struct ethosu_driver *drv);
252 
253 /**
254  * Request to disable Q-channel power gating of the Ethos-U device.
255  * Power requests are ref.counted. Increases count.
256  * (Note: clock gating is made to follow power gating)
257  *
258  * @param drv       Pointer to driver handle
259  * @return 0 on success, else negative error code
260  */
261 int ethosu_request_power(struct ethosu_driver *drv);
262 
263 /**
264  * Release disable request for Q-channel power gating of the Ethos-U device.
265  * Power requests are ref.counted. Decreases count.
266  *
267  * @param drv       Pointer to driver handle
268  */
269 void ethosu_release_power(struct ethosu_driver *drv);
270 
271 /**
272  * Get Ethos-U driver version.
273  *
274  * @param ver       Driver version struct
275  */
276 void ethosu_get_driver_version(struct ethosu_driver_version *ver);
277 
278 /**
279  * Get Ethos-U hardware information.
280  *
281  * @param drv       Pointer to driver handle
282  * @param hw        Hardware information struct
283  */
284 void ethosu_get_hw_info(struct ethosu_driver *drv, struct ethosu_hw_info *hw);
285 
286 /**
287  * Invoke command stream.
288  *
289  * @param drv               Pointer to driver handle
290  * @param custom_data_ptr   Custom data payload
291  * @param custom_data_size  Size in bytes of custom data
292  * @param base_addr         Array of base address pointers
293  * @param base_addr_size    Size in bytes of each address in base_addr
294  * @param num_base_addr     Number of elements in base_addr array
295  * @param user_arg          User argument, will be passed to
296  *                          ethosu_inference_begin() and ethosu_inference_end()
297  * @return 0 on success, else negative error code
298  */
299 int ethosu_invoke_v3(struct ethosu_driver *drv,
300                      const void *custom_data_ptr,
301                      const int custom_data_size,
302                      uint64_t *const base_addr,
303                      const size_t *base_addr_size,
304                      const int num_base_addr,
305                      void *user_arg);
306 
307 #define ethosu_invoke(drv, custom_data_ptr, custom_data_size, base_addr, base_addr_size, num_base_addr)                \
308     ethosu_invoke_v3(drv, custom_data_ptr, custom_data_size, base_addr, base_addr_size, num_base_addr, 0)
309 
310 /**
311  * Invoke command stream using async interface.
312  * Must be followed by call(s) to ethosu_wait() upon successful return.
313  *
314  * @see ethosu_invoke_v3 for documentation.
315  */
316 int ethosu_invoke_async(struct ethosu_driver *drv,
317                         const void *custom_data_ptr,
318                         const int custom_data_size,
319                         uint64_t *const base_addr,
320                         const size_t *base_addr_size,
321                         const int num_base_addr,
322                         void *user_arg);
323 
324 /**
325  * Wait for inference to complete (block=true)
326  * Poll status or finish up if inference is complete (block=false)
327  * (This function is only intended to be used in conjuction with ethosu_invoke_async)
328  *
329  * @param drv       Pointer to driver handle
330  * @param block     If call should block if inference is running
331  * @return -2 on inference not invoked, -1 on inference error, 0 on success, 1 on inference running
332  */
333 int ethosu_wait(struct ethosu_driver *drv, bool block);
334 
335 /**
336  * Reserves a driver to execute inference with. Call will block until a driver
337  * is available.
338  *
339  * @return Pointer to driver handle.
340  */
341 struct ethosu_driver *ethosu_reserve_driver(void);
342 
343 /**
344  * Release driver that was previously reserved with @see ethosu_reserve_driver.
345  *
346  * @param drv       Pointer to driver handle
347  */
348 void ethosu_release_driver(struct ethosu_driver *drv);
349 
350 /**
351  * Static inline for backwards-compatibility.
352  *
353  * @see ethosu_invoke_v3 for documentation.
354  */
ethosu_invoke_v2(const void * custom_data_ptr,const int custom_data_size,uint64_t * const base_addr,const size_t * base_addr_size,const int num_base_addr)355 static inline int ethosu_invoke_v2(const void *custom_data_ptr,
356                                    const int custom_data_size,
357                                    uint64_t *const base_addr,
358                                    const size_t *base_addr_size,
359                                    const int num_base_addr)
360 {
361     struct ethosu_driver *drv = ethosu_reserve_driver();
362     if (!drv)
363     {
364         return -1;
365     }
366     int result = ethosu_invoke_v3(drv, custom_data_ptr, custom_data_size, base_addr, base_addr_size, num_base_addr, 0);
367     ethosu_release_driver(drv);
368     return result;
369 }
370 
371 #ifdef __cplusplus
372 }
373 #endif
374 
375 #endif // ETHOSU_DRIVER_H
376