1 /*
2 * Copyright 2021-2022 Arm Limited and/or its affiliates <open-source-office@arm.com>
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/device.h>
8 #include <zephyr/devicetree.h>
9 #include <zephyr/init.h>
10 #include <zephyr/kernel.h>
11 #include <zephyr/irq.h>
12 #include <zephyr/sys/util.h>
13
14 #include <ethosu_driver.h>
15
16 #include <zephyr/logging/log.h>
17 LOG_MODULE_REGISTER(ethos_u, CONFIG_ARM_ETHOS_U_LOG_LEVEL);
18
19 #define DT_DRV_COMPAT arm_ethos_u
20
21 /*******************************************************************************
22 * Re-implementation/Overrides __((weak)) symbol functions from ethosu_driver.c
23 * To handle mutex and semaphores
24 *******************************************************************************/
25
ethosu_mutex_create(void)26 void *ethosu_mutex_create(void)
27 {
28 struct k_mutex *mutex;
29
30 mutex = k_malloc(sizeof(*mutex));
31 if (mutex == NULL) {
32 LOG_ERR("Failed allocate mutex");
33 return NULL;
34 }
35
36 k_mutex_init(mutex);
37
38 return (void *)mutex;
39 }
40
ethosu_mutex_lock(void * mutex)41 int ethosu_mutex_lock(void *mutex)
42 {
43 int status;
44
45 status = k_mutex_lock((struct k_mutex *)mutex, K_FOREVER);
46 if (status != 0) {
47 LOG_ERR("Failed to lock mutex with error - %d", status);
48 return -1;
49 }
50
51 return 0;
52 }
53
ethosu_mutex_unlock(void * mutex)54 int ethosu_mutex_unlock(void *mutex)
55 {
56 k_mutex_unlock((struct k_mutex *)mutex);
57 return 0;
58 }
59
ethosu_semaphore_create(void)60 void *ethosu_semaphore_create(void)
61 {
62 struct k_sem *sem;
63
64 sem = k_malloc(sizeof(*sem));
65 if (sem == NULL) {
66 LOG_ERR("Failed to allocate semaphore");
67 return NULL;
68 }
69
70 k_sem_init(sem, 0, 100);
71
72 return (void *)sem;
73 }
74
ethosu_semaphore_take(void * sem)75 int ethosu_semaphore_take(void *sem)
76 {
77 int status;
78
79 status = k_sem_take((struct k_sem *)sem, K_FOREVER);
80 if (status != 0) {
81 LOG_ERR("Failed to take semaphore with error - %d", status);
82 return -1;
83 }
84
85 return 0;
86 }
87
ethosu_semaphore_give(void * sem)88 int ethosu_semaphore_give(void *sem)
89 {
90 k_sem_give((struct k_sem *)sem);
91 return 0;
92 }
93
94 struct ethosu_dts_info {
95 void *base_addr;
96 bool secure_enable;
97 bool privilege_enable;
98 void (*irq_config)(void);
99 };
100
101 struct ethosu_data {
102 struct ethosu_driver drv;
103 };
104
ethosu_zephyr_irq_handler(const struct device * dev)105 void ethosu_zephyr_irq_handler(const struct device *dev)
106 {
107 struct ethosu_data *data = dev->data;
108 struct ethosu_driver *drv = &data->drv;
109
110 ethosu_irq_handler(drv);
111 }
112
ethosu_zephyr_init(const struct device * dev)113 static int ethosu_zephyr_init(const struct device *dev)
114 {
115 const struct ethosu_dts_info *config = dev->config;
116 struct ethosu_data *data = dev->data;
117 struct ethosu_driver *drv = &data->drv;
118 struct ethosu_driver_version version;
119
120 LOG_DBG("Ethos-U DTS info. base_address=0x%p, secure_enable=%u, privilege_enable=%u",
121 config->base_addr, config->secure_enable, config->privilege_enable);
122
123 ethosu_get_driver_version(&version);
124
125 LOG_DBG("Version. major=%u, minor=%u, patch=%u", version.major, version.minor,
126 version.patch);
127
128 if (ethosu_init(drv, config->base_addr, NULL, 0, config->secure_enable,
129 config->privilege_enable)) {
130 LOG_ERR("Failed to initialize NPU with ethosu_init().");
131 return -EINVAL;
132 }
133
134 config->irq_config();
135
136 return 0;
137 }
138
139 #define ETHOSU_DEVICE_INIT(n) \
140 static struct ethosu_data ethosu_data_##n; \
141 \
142 static void ethosu_zephyr_irq_config_##n(void) \
143 { \
144 IRQ_CONNECT(DT_INST_IRQN(n), \
145 DT_INST_IRQ(n, priority), \
146 ethosu_zephyr_irq_handler, \
147 DEVICE_DT_INST_GET(n), 0); \
148 irq_enable(DT_INST_IRQN(n)); \
149 } \
150 \
151 static const struct ethosu_dts_info ethosu_dts_info_##n = { \
152 .base_addr = (void *)DT_INST_REG_ADDR(n), \
153 .secure_enable = DT_INST_PROP(n, secure_enable), \
154 .privilege_enable = DT_INST_PROP(n, privilege_enable), \
155 .irq_config = ðosu_zephyr_irq_config_##n, \
156 }; \
157 \
158 DEVICE_DT_INST_DEFINE(n, ethosu_zephyr_init, NULL, ðosu_data_##n, ðosu_dts_info_##n, \
159 POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, NULL);
160
161 DT_INST_FOREACH_STATUS_OKAY(ETHOSU_DEVICE_INIT);
162