blob: 6b911cafae7f9d49c59c928a9bd586b4868681d6 [file] [log] [blame]
Kristofer Jonsson116a6352020-08-20 17:25:23 +02001/*
Kristofer Jonsson35de9e62022-03-08 13:25:45 +01002 * Copyright (c) 2020-2022 Arm Limited.
Kristofer Jonsson116a6352020-08-20 17:25:23 +02003 *
4 * This program is free software and is provided to you under the terms of the
5 * GNU General Public License version 2 as published by the Free Software
6 * Foundation, and any use by you of this program is subject to the terms
7 * of such GNU licence.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, you can access it online at
16 * http://www.gnu.org/licenses/gpl-2.0.html.
17 *
18 * SPDX-License-Identifier: GPL-2.0-only
19 */
20
21/****************************************************************************
22 * Includes
23 ****************************************************************************/
24
25#include "ethosu_device.h"
26
27#include "ethosu_buffer.h"
28#include "ethosu_core_interface.h"
29#include "ethosu_inference.h"
Davide Grohmann7e8f5082022-03-23 12:48:45 +010030#include "ethosu_cancel_inference.h"
Kristofer Jonsson116a6352020-08-20 17:25:23 +020031#include "ethosu_network.h"
Kristofer Jonsson3c6a2602022-03-10 11:17:29 +010032#include "ethosu_network_info.h"
Kristofer Jonsson116a6352020-08-20 17:25:23 +020033#include "uapi/ethosu.h"
34
35#include <linux/delay.h>
36#include <linux/dma-mapping.h>
37#include <linux/errno.h>
38#include <linux/fs.h>
39#include <linux/interrupt.h>
40#include <linux/io.h>
41#include <linux/of_reserved_mem.h>
Kristofer Jonsson442fefb2022-03-17 17:15:52 +010042#include <linux/reset.h>
Davide Grohmann35ce6c82021-06-01 15:03:51 +020043#include <linux/slab.h>
Kristofer Jonsson442fefb2022-03-17 17:15:52 +010044#include <linux/uaccess.h>
Kristofer Jonsson116a6352020-08-20 17:25:23 +020045
46/****************************************************************************
47 * Defines
48 ****************************************************************************/
49
Kristofer Jonsson116a6352020-08-20 17:25:23 +020050#define DMA_ADDR_BITS 32 /* Number of address bits */
51
Per Åstrandbb175272021-10-25 12:37:36 +020052#define CAPABILITIES_RESP_TIMEOUT_MS 2000
Davide Grohmann35ce6c82021-06-01 15:03:51 +020053
Kristofer Jonsson116a6352020-08-20 17:25:23 +020054/****************************************************************************
Kristofer Jonsson116a6352020-08-20 17:25:23 +020055 * Functions
56 ****************************************************************************/
57
Davide Grohmann35ce6c82021-06-01 15:03:51 +020058static void ethosu_capabilities_destroy(struct kref *kref)
59{
60 struct ethosu_capabilities *cap =
61 container_of(kref, struct ethosu_capabilities, refcount);
62
Kristofer Jonsson442fefb2022-03-17 17:15:52 +010063 dev_info(cap->edev->dev, "Capabilities destroy. handle=0x%pK\n", cap);
64
65 list_del(&cap->msg.list);
Davide Grohmann35ce6c82021-06-01 15:03:51 +020066
67 devm_kfree(cap->edev->dev, cap);
68}
69
Kristofer Jonsson442fefb2022-03-17 17:15:52 +010070static int ethosu_capabilities_send(struct ethosu_capabilities *cap)
Davide Grohmann35ce6c82021-06-01 15:03:51 +020071{
Kristofer Jonsson442fefb2022-03-17 17:15:52 +010072 int ret;
Davide Grohmann35ce6c82021-06-01 15:03:51 +020073
Kristofer Jonsson442fefb2022-03-17 17:15:52 +010074 ret = ethosu_mailbox_capabilities_request(&cap->edev->mailbox, cap);
75 if (ret)
76 return ret;
Davide Grohmann35ce6c82021-06-01 15:03:51 +020077
Kristofer Jonsson442fefb2022-03-17 17:15:52 +010078 return 0;
Davide Grohmann35ce6c82021-06-01 15:03:51 +020079}
80
Kristofer Jonsson442fefb2022-03-17 17:15:52 +010081static void ethosu_capabilities_fail(struct ethosu_mailbox_msg *msg)
Davide Grohmann35ce6c82021-06-01 15:03:51 +020082{
Kristofer Jonsson442fefb2022-03-17 17:15:52 +010083 struct ethosu_capabilities *cap =
84 container_of(msg, typeof(*cap), msg);
85
Davide Grohmann8b1fe552022-04-07 16:58:32 +020086 if (completion_done(&cap->done))
87 return;
88
Kristofer Jonsson442fefb2022-03-17 17:15:52 +010089 cap->errno = -EFAULT;
90 complete(&cap->done);
91}
92
93static int ethosu_capabilities_resend(struct ethosu_mailbox_msg *msg)
94{
95 struct ethosu_capabilities *cap =
96 container_of(msg, typeof(*cap), msg);
97 int ret;
98
99 /* Don't resend request if response has already been received */
100 if (completion_done(&cap->done))
101 return 0;
102
103 /* Resend request */
104 ret = ethosu_capabilities_send(cap);
105 if (ret)
106 return ret;
107
108 return 0;
109}
110
111static void ethosu_capability_rsp(struct ethosu_device *edev,
112 struct ethosu_core_msg_capabilities_rsp *msg)
113{
114 struct ethosu_capabilities *cap =
115 (struct ethosu_capabilities *)msg->user_arg;
Davide Grohmann35ce6c82021-06-01 15:03:51 +0200116 struct ethosu_uapi_device_capabilities *capabilities;
117 int ret;
118
Kristofer Jonsson442fefb2022-03-17 17:15:52 +0100119 ret = ethosu_mailbox_find(&edev->mailbox, &cap->msg);
120 if (ret) {
Davide Grohmann35ce6c82021-06-01 15:03:51 +0200121 dev_warn(edev->dev,
Kristofer Jonsson442fefb2022-03-17 17:15:52 +0100122 "Capabilities not found in pending list. handle=0x%p\n",
Davide Grohmann35ce6c82021-06-01 15:03:51 +0200123 cap);
124
Kristofer Jonsson442fefb2022-03-17 17:15:52 +0100125 return;
Davide Grohmann35ce6c82021-06-01 15:03:51 +0200126 }
127
Kristofer Jonsson442fefb2022-03-17 17:15:52 +0100128 if (completion_done(&cap->done))
129 return;
130
Davide Grohmann35ce6c82021-06-01 15:03:51 +0200131 capabilities = cap->capabilities;
132
133 capabilities->hw_id.version_status = msg->version_status;
134 capabilities->hw_id.version_minor = msg->version_minor;
135 capabilities->hw_id.version_major = msg->version_major;
136 capabilities->hw_id.product_major = msg->product_major;
137 capabilities->hw_id.arch_patch_rev = msg->arch_patch_rev;
138 capabilities->hw_id.arch_minor_rev = msg->arch_minor_rev;
139 capabilities->hw_id.arch_major_rev = msg->arch_major_rev;
140 capabilities->driver_patch_rev = msg->driver_patch_rev;
141 capabilities->driver_minor_rev = msg->driver_minor_rev;
142 capabilities->driver_major_rev = msg->driver_major_rev;
143 capabilities->hw_cfg.macs_per_cc = msg->macs_per_cc;
144 capabilities->hw_cfg.cmd_stream_version = msg->cmd_stream_version;
Davide Grohmann35ce6c82021-06-01 15:03:51 +0200145 capabilities->hw_cfg.custom_dma = msg->custom_dma;
146
Kristofer Jonsson442fefb2022-03-17 17:15:52 +0100147 cap->errno = 0;
Davide Grohmann35ce6c82021-06-01 15:03:51 +0200148 complete(&cap->done);
Kristofer Jonsson442fefb2022-03-17 17:15:52 +0100149}
Davide Grohmann35ce6c82021-06-01 15:03:51 +0200150
Kristofer Jonsson442fefb2022-03-17 17:15:52 +0100151static int ethosu_capabilities_request(struct ethosu_device *edev,
152 void __user *udata)
153{
154 struct ethosu_uapi_device_capabilities uapi;
155 struct ethosu_capabilities *cap;
156 int ret;
157 int timeout;
158
159 cap = devm_kzalloc(edev->dev, sizeof(struct ethosu_capabilities),
160 GFP_KERNEL);
161 if (!cap)
162 return -ENOMEM;
163
164 cap->edev = edev;
165 cap->capabilities = &uapi;
166 kref_init(&cap->refcount);
167 init_completion(&cap->done);
168 list_add(&cap->msg.list, &edev->mailbox.pending_list);
169 cap->msg.fail = ethosu_capabilities_fail;
170 cap->msg.resend = ethosu_capabilities_resend;
171
172 ret = ethosu_capabilities_send(cap);
173 if (0 != ret)
174 goto put_kref;
175
176 /* Unlock the mutex before going to block on the condition */
177 mutex_unlock(&edev->mutex);
178
179 /* wait for response to arrive back */
180 timeout = wait_for_completion_timeout(&cap->done,
181 msecs_to_jiffies(
182 CAPABILITIES_RESP_TIMEOUT_MS));
183
184 /* take back the mutex before resuming to do anything */
185 mutex_lock(&edev->mutex);
186
187 if (0 == timeout) {
188 dev_warn(edev->dev, "Capabilities response timeout");
189 ret = -EIO;
190 goto put_kref;
191 }
192
193 if (cap->errno)
194 goto put_kref;
195
196 ret = copy_to_user(udata, &uapi, sizeof(uapi)) ? -EFAULT : 0;
197
198put_kref:
Davide Grohmann35ce6c82021-06-01 15:03:51 +0200199 kref_put(&cap->refcount, ethosu_capabilities_destroy);
200
Kristofer Jonsson442fefb2022-03-17 17:15:52 +0100201 return ret;
Davide Grohmann35ce6c82021-06-01 15:03:51 +0200202}
203
Jonny Svärd7c24c772021-01-14 19:53:17 +0100204/* Incoming messages */
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200205static int ethosu_handle_msg(struct ethosu_device *edev)
206{
Jonny Svärd7c24c772021-01-14 19:53:17 +0100207 int ret;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200208 struct ethosu_core_msg header;
209
210 union {
Davide Grohmann35ce6c82021-06-01 15:03:51 +0200211 struct ethosu_core_msg_err error;
212 struct ethosu_core_inference_rsp inf;
213 struct ethosu_core_msg_version version;
214 struct ethosu_core_msg_capabilities_rsp capabilities;
Kristofer Jonsson3c6a2602022-03-10 11:17:29 +0100215 struct ethosu_core_network_info_rsp network_info;
Davide Grohmann7e8f5082022-03-23 12:48:45 +0100216 struct ethosu_core_cancel_inference_rsp cancellation;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200217 } data;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200218
219 /* Read message */
220 ret = ethosu_mailbox_read(&edev->mailbox, &header, &data, sizeof(data));
221 if (ret)
222 return ret;
223
224 switch (header.type) {
Jonny Svärd7c24c772021-01-14 19:53:17 +0100225 case ETHOSU_CORE_MSG_ERR:
226 if (header.length != sizeof(data.error)) {
227 dev_warn(edev->dev,
228 "Msg: Error message of incorrect size. size=%u, expected=%zu\n", header.length,
229 sizeof(data.error));
230 ret = -EBADMSG;
231 break;
232 }
233
234 data.error.msg[sizeof(data.error.msg) - 1] = '\0';
235 dev_warn(edev->dev, "Msg: Error. type=%u, msg=\"%s\"\n",
236 data.error.type, data.error.msg);
237 ret = -EBADMSG;
238 break;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200239 case ETHOSU_CORE_MSG_PING:
240 dev_info(edev->dev, "Msg: Ping\n");
Jonny Svärd7c24c772021-01-14 19:53:17 +0100241 ret = ethosu_mailbox_pong(&edev->mailbox);
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200242 break;
243 case ETHOSU_CORE_MSG_PONG:
244 dev_info(edev->dev, "Msg: Pong\n");
245 break;
246 case ETHOSU_CORE_MSG_INFERENCE_RSP:
Jonny Svärd7c24c772021-01-14 19:53:17 +0100247 if (header.length != sizeof(data.inf)) {
248 dev_warn(edev->dev,
249 "Msg: Inference response of incorrect size. size=%u, expected=%zu\n", header.length,
250 sizeof(data.inf));
251 ret = -EBADMSG;
252 break;
253 }
254
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200255 dev_info(edev->dev,
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200256 "Msg: Inference response. user_arg=0x%llx, ofm_count=%u, status=%u\n",
257 data.inf.user_arg, data.inf.ofm_count,
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200258 data.inf.status);
Kristofer Jonsson442fefb2022-03-17 17:15:52 +0100259
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200260 ethosu_inference_rsp(edev, &data.inf);
261 break;
Davide Grohmann7e8f5082022-03-23 12:48:45 +0100262 case ETHOSU_CORE_MSG_CANCEL_INFERENCE_RSP:
263 if (header.length != sizeof(data.cancellation)) {
264 dev_warn(edev->dev,
265 "Msg: Cancel Inference response of incorrect size. size=%u, expected=%zu\n", header.length,
266 sizeof(data.cancellation));
267 ret = -EBADMSG;
268 break;
269 }
270
271 dev_info(edev->dev,
272 "Msg: Cancel Inference response. user_arg=0x%llx, status=%u\n",
273 data.cancellation.user_arg, data.cancellation.status);
274 ethosu_cancel_inference_rsp(edev, &data.cancellation);
275 break;
Jonny Svärd7c24c772021-01-14 19:53:17 +0100276 case ETHOSU_CORE_MSG_VERSION_RSP:
277 if (header.length != sizeof(data.version)) {
278 dev_warn(edev->dev,
279 "Msg: Version response of incorrect size. size=%u, expected=%zu\n", header.length,
280 sizeof(data.version));
281 ret = -EBADMSG;
282 break;
283 }
284
285 dev_info(edev->dev, "Msg: Version response v%u.%u.%u\n",
286 data.version.major, data.version.minor,
287 data.version.patch);
288
289 /* Check major and minor version match, else return error */
290 if (data.version.major != ETHOSU_CORE_MSG_VERSION_MAJOR ||
291 data.version.minor != ETHOSU_CORE_MSG_VERSION_MINOR) {
292 dev_warn(edev->dev, "Msg: Version mismatch detected! ");
293 dev_warn(edev->dev, "Local version: v%u.%u.%u\n",
294 ETHOSU_CORE_MSG_VERSION_MAJOR,
295 ETHOSU_CORE_MSG_VERSION_MINOR,
296 ETHOSU_CORE_MSG_VERSION_PATCH);
297 }
298
299 break;
Davide Grohmann35ce6c82021-06-01 15:03:51 +0200300 case ETHOSU_CORE_MSG_CAPABILITIES_RSP:
301 if (header.length != sizeof(data.capabilities)) {
302 dev_warn(edev->dev,
303 "Msg: Capabilities response of incorrect size. size=%u, expected=%zu\n", header.length,
304 sizeof(data.capabilities));
305 ret = -EBADMSG;
306 break;
307 }
Jonny Svärd7c24c772021-01-14 19:53:17 +0100308
Davide Grohmann35ce6c82021-06-01 15:03:51 +0200309 dev_info(edev->dev,
Davide Grohmann40e23d12021-06-17 09:59:40 +0200310 "Msg: Capabilities response ua%llx vs%hhu v%hhu.%hhu p%hhu av%hhu.%hhu.%hhu dv%hhu.%hhu.%hhu mcc%hhu csv%hhu cd%hhu\n",
Davide Grohmann35ce6c82021-06-01 15:03:51 +0200311 data.capabilities.user_arg,
312 data.capabilities.version_status,
313 data.capabilities.version_major,
314 data.capabilities.version_minor,
315 data.capabilities.product_major,
316 data.capabilities.arch_major_rev,
317 data.capabilities.arch_minor_rev,
318 data.capabilities.arch_patch_rev,
319 data.capabilities.driver_major_rev,
320 data.capabilities.driver_minor_rev,
321 data.capabilities.driver_patch_rev,
322 data.capabilities.macs_per_cc,
323 data.capabilities.cmd_stream_version,
Davide Grohmann35ce6c82021-06-01 15:03:51 +0200324 data.capabilities.custom_dma);
325
Kristofer Jonsson442fefb2022-03-17 17:15:52 +0100326 ethosu_capability_rsp(edev, &data.capabilities);
Davide Grohmann35ce6c82021-06-01 15:03:51 +0200327 break;
Kristofer Jonsson3c6a2602022-03-10 11:17:29 +0100328 case ETHOSU_CORE_MSG_NETWORK_INFO_RSP:
329 if (header.length != sizeof(data.network_info)) {
330 dev_warn(edev->dev,
331 "Msg: Network info response of incorrect size. size=%u, expected=%zu\n", header.length,
332 sizeof(data.network_info));
333 ret = -EBADMSG;
334 break;
335 }
336
337 dev_info(edev->dev,
338 "Msg: Network info response. user_arg=0x%llx, status=%u",
339 data.network_info.user_arg,
340 data.network_info.status);
341
342 ethosu_network_info_rsp(edev, &data.network_info);
343
344 break;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200345 default:
Jonny Svärd7c24c772021-01-14 19:53:17 +0100346 /* This should not happen due to version checks */
347 dev_warn(edev->dev, "Msg: Protocol error\n");
348 ret = -EPROTO;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200349 break;
350 }
351
352 return ret;
353}
354
Davide Grohmann8b1fe552022-04-07 16:58:32 +0200355int ethosu_firmware_reset(struct ethosu_device *edev)
Kristofer Jonsson442fefb2022-03-17 17:15:52 +0100356{
357 int ret;
358
359 /* No reset control for this device */
360 if (IS_ERR(edev->reset))
361 return PTR_ERR(edev->reset);
362
363 dev_info(edev->dev, "Resetting firmware.");
364
365 ret = reset_control_assert(edev->reset);
366 if (ret) {
Davide Grohmann8b1fe552022-04-07 16:58:32 +0200367 dev_err(edev->dev, "Failed to reset assert firmware. ret=%d",
368 ret);
Kristofer Jonsson442fefb2022-03-17 17:15:52 +0100369
370 return ret;
371 }
372
373 /* Initialize mailbox header with illegal values */
374 ethosu_mailbox_wait_prepare(&edev->mailbox);
375
376 /* If this call fails we have a problem. We managed halt the firmware,
377 * but not to release the reset.
378 */
379 ret = reset_control_deassert(edev->reset);
380 if (ret) {
Davide Grohmann8b1fe552022-04-07 16:58:32 +0200381 dev_err(edev->dev, "Failed to reset deassert firmware. ret=%d",
382 ret);
Kristofer Jonsson442fefb2022-03-17 17:15:52 +0100383 goto fail;
384 }
385
386 /* Wait for firmware to boot up and initialize mailbox */
387 ret = ethosu_mailbox_wait_firmware(&edev->mailbox);
388 if (ret) {
Davide Grohmann8b1fe552022-04-07 16:58:32 +0200389 dev_err(edev->dev, "Wait on firmware boot timed out. ret=%d",
390 ret);
Kristofer Jonsson442fefb2022-03-17 17:15:52 +0100391 goto fail;
392 }
393
394 edev->mailbox.ping_count = 0;
395 ethosu_watchdog_reset(&edev->watchdog);
396
397 ret = ethosu_mailbox_ping(&edev->mailbox);
Davide Grohmann8b1fe552022-04-07 16:58:32 +0200398 if (ret) {
399 dev_warn(edev->dev,
400 "Failed to send ping after firmware reset. ret=%d",
401 ret);
Kristofer Jonsson442fefb2022-03-17 17:15:52 +0100402 goto fail;
Davide Grohmann8b1fe552022-04-07 16:58:32 +0200403 }
Kristofer Jonsson442fefb2022-03-17 17:15:52 +0100404
405 /* Resend messages */
406 ethosu_mailbox_resend(&edev->mailbox);
407
408 return ret;
409
410fail:
411 ethosu_mailbox_fail(&edev->mailbox);
412
413 return ret;
414}
415
Kristofer Jonssonf5b98c92022-03-14 16:09:12 +0100416static void ethosu_watchdog_callback(struct ethosu_watchdog *wdog)
417{
418 struct ethosu_device *edev =
419 container_of(wdog, struct ethosu_device, watchdog);
420
421 mutex_lock(&edev->mutex);
422
Kristofer Jonsson442fefb2022-03-17 17:15:52 +0100423 dev_warn(edev->dev, "Device watchdog timeout. ping_count=%u",
424 edev->mailbox.ping_count);
425
426 if (edev->mailbox.ping_count < 1)
427 ethosu_mailbox_ping(&edev->mailbox);
428 else
429 ethosu_firmware_reset(edev);
Kristofer Jonssonf5b98c92022-03-14 16:09:12 +0100430
431 mutex_unlock(&edev->mutex);
432}
433
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200434static int ethosu_open(struct inode *inode,
435 struct file *file)
436{
437 struct ethosu_device *edev =
438 container_of(inode->i_cdev, struct ethosu_device, cdev);
439
440 file->private_data = edev;
441
442 dev_info(edev->dev, "Opening device node.\n");
443
444 return nonseekable_open(inode, file);
445}
446
447static long ethosu_ioctl(struct file *file,
448 unsigned int cmd,
449 unsigned long arg)
450{
451 struct ethosu_device *edev = file->private_data;
452 void __user *udata = (void __user *)arg;
453 int ret = -EINVAL;
454
455 ret = mutex_lock_interruptible(&edev->mutex);
456 if (ret)
457 return ret;
458
Kristofer Jonsson3c6a2602022-03-10 11:17:29 +0100459 dev_info(edev->dev, "Ioctl. cmd=0x%x, arg=0x%lx\n", cmd, arg);
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200460
461 switch (cmd) {
Jonny Svärd7c24c772021-01-14 19:53:17 +0100462 case ETHOSU_IOCTL_VERSION_REQ:
463 dev_info(edev->dev, "Ioctl: Send version request\n");
464 ret = ethosu_mailbox_version_request(&edev->mailbox);
465 break;
Davide Grohmann35ce6c82021-06-01 15:03:51 +0200466 case ETHOSU_IOCTL_CAPABILITIES_REQ:
467 dev_info(edev->dev, "Ioctl: Send capabilities request\n");
Kristofer Jonsson442fefb2022-03-17 17:15:52 +0100468 ret = ethosu_capabilities_request(edev, udata);
Davide Grohmann35ce6c82021-06-01 15:03:51 +0200469 break;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200470 case ETHOSU_IOCTL_PING: {
471 dev_info(edev->dev, "Ioctl: Send ping\n");
472 ret = ethosu_mailbox_ping(&edev->mailbox);
473 break;
474 }
475 case ETHOSU_IOCTL_BUFFER_CREATE: {
476 struct ethosu_uapi_buffer_create uapi;
477
478 dev_info(edev->dev, "Ioctl: Buffer create\n");
479
480 if (copy_from_user(&uapi, udata, sizeof(uapi)))
481 break;
482
483 dev_info(edev->dev, "Ioctl: Buffer. capacity=%u\n",
484 uapi.capacity);
485
486 ret = ethosu_buffer_create(edev, uapi.capacity);
487 break;
488 }
489 case ETHOSU_IOCTL_NETWORK_CREATE: {
490 struct ethosu_uapi_network_create uapi;
491
492 if (copy_from_user(&uapi, udata, sizeof(uapi)))
493 break;
494
495 dev_info(edev->dev, "Ioctl: Network. fd=%u\n", uapi.fd);
496
497 ret = ethosu_network_create(edev, &uapi);
498 break;
499 }
500 default: {
501 dev_err(edev->dev, "Invalid ioctl. cmd=%u, arg=%lu",
502 cmd, arg);
503 break;
504 }
505 }
506
507 mutex_unlock(&edev->mutex);
508
509 return ret;
510}
511
512static void ethosu_mbox_rx(void *user_arg)
513{
514 struct ethosu_device *edev = user_arg;
515 int ret;
516
517 mutex_lock(&edev->mutex);
518
519 do {
520 ret = ethosu_handle_msg(edev);
Jonny Svärd7c24c772021-01-14 19:53:17 +0100521 if (ret && ret != -ENOMSG)
522 /* Need to start over in case of error, empty the queue
523 * by fast-forwarding read position to write position.
524 * */
525 ethosu_mailbox_reset(&edev->mailbox);
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200526 } while (ret == 0);
527
528 mutex_unlock(&edev->mutex);
529}
530
531int ethosu_dev_init(struct ethosu_device *edev,
532 struct device *dev,
533 struct class *class,
Kristofer Jonsson4aec3762021-10-13 17:09:27 +0200534 dev_t devt,
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200535 struct resource *in_queue,
536 struct resource *out_queue)
537{
538 static const struct file_operations fops = {
539 .owner = THIS_MODULE,
540 .open = &ethosu_open,
541 .unlocked_ioctl = &ethosu_ioctl,
542#ifdef CONFIG_COMPAT
543 .compat_ioctl = &ethosu_ioctl,
544#endif
545 };
546 struct device *sysdev;
547 int ret;
548
549 edev->dev = dev;
550 edev->class = class;
Kristofer Jonsson4aec3762021-10-13 17:09:27 +0200551 edev->devt = devt;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200552 mutex_init(&edev->mutex);
Kristofer Jonsson442fefb2022-03-17 17:15:52 +0100553
554 edev->reset = devm_reset_control_get_by_index(edev->dev, 0);
555 if (IS_ERR(edev->reset))
556 dev_warn(edev->dev, "No reset control found for this device.");
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200557
558 ret = of_reserved_mem_device_init(edev->dev);
559 if (ret)
560 return ret;
561
562 dma_set_mask_and_coherent(edev->dev, DMA_BIT_MASK(DMA_ADDR_BITS));
563
Kristofer Jonssonf5b98c92022-03-14 16:09:12 +0100564 ret = ethosu_watchdog_init(&edev->watchdog, dev,
565 ethosu_watchdog_callback);
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200566 if (ret)
567 goto release_reserved_mem;
568
Kristofer Jonssonf5b98c92022-03-14 16:09:12 +0100569 ret = ethosu_mailbox_init(&edev->mailbox, dev, in_queue, out_queue,
570 ethosu_mbox_rx, edev, &edev->watchdog);
571 if (ret)
572 goto deinit_watchdog;
573
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200574 cdev_init(&edev->cdev, &fops);
575 edev->cdev.owner = THIS_MODULE;
576
Kristofer Jonsson4aec3762021-10-13 17:09:27 +0200577 ret = cdev_add(&edev->cdev, edev->devt, 1);
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200578 if (ret) {
579 dev_err(edev->dev, "Failed to add character device.\n");
Kristofer Jonsson4aec3762021-10-13 17:09:27 +0200580 goto deinit_mailbox;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200581 }
582
583 sysdev = device_create(edev->class, NULL, edev->devt, edev,
Kristofer Jonsson4aec3762021-10-13 17:09:27 +0200584 "ethosu%d", MINOR(edev->devt));
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200585 if (IS_ERR(sysdev)) {
586 dev_err(edev->dev, "Failed to create device.\n");
587 ret = PTR_ERR(sysdev);
588 goto del_cdev;
589 }
590
Kristofer Jonsson442fefb2022-03-17 17:15:52 +0100591 ethosu_firmware_reset(edev);
592
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200593 dev_info(edev->dev,
594 "Created Arm Ethos-U device. name=%s, major=%d, minor=%d\n",
595 dev_name(sysdev), MAJOR(edev->devt), MINOR(edev->devt));
596
597 return 0;
598
599del_cdev:
600 cdev_del(&edev->cdev);
601
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200602deinit_mailbox:
603 ethosu_mailbox_deinit(&edev->mailbox);
604
Kristofer Jonssonf5b98c92022-03-14 16:09:12 +0100605deinit_watchdog:
606 ethosu_watchdog_deinit(&edev->watchdog);
607
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200608release_reserved_mem:
609 of_reserved_mem_device_release(edev->dev);
610
611 return ret;
612}
613
614void ethosu_dev_deinit(struct ethosu_device *edev)
615{
616 ethosu_mailbox_deinit(&edev->mailbox);
Kristofer Jonssonf5b98c92022-03-14 16:09:12 +0100617 ethosu_watchdog_deinit(&edev->watchdog);
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200618 device_destroy(edev->class, edev->cdev.dev);
619 cdev_del(&edev->cdev);
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200620 of_reserved_mem_device_release(edev->dev);
621
622 dev_info(edev->dev, "%s\n", __FUNCTION__);
623}