blob: f66c2acedce71760982e6adefc482588bb30f594 [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
86 cap->errno = -EFAULT;
87 complete(&cap->done);
88}
89
90static int ethosu_capabilities_resend(struct ethosu_mailbox_msg *msg)
91{
92 struct ethosu_capabilities *cap =
93 container_of(msg, typeof(*cap), msg);
94 int ret;
95
96 /* Don't resend request if response has already been received */
97 if (completion_done(&cap->done))
98 return 0;
99
100 /* Resend request */
101 ret = ethosu_capabilities_send(cap);
102 if (ret)
103 return ret;
104
105 return 0;
106}
107
108static void ethosu_capability_rsp(struct ethosu_device *edev,
109 struct ethosu_core_msg_capabilities_rsp *msg)
110{
111 struct ethosu_capabilities *cap =
112 (struct ethosu_capabilities *)msg->user_arg;
Davide Grohmann35ce6c82021-06-01 15:03:51 +0200113 struct ethosu_uapi_device_capabilities *capabilities;
114 int ret;
115
Kristofer Jonsson442fefb2022-03-17 17:15:52 +0100116 ret = ethosu_mailbox_find(&edev->mailbox, &cap->msg);
117 if (ret) {
Davide Grohmann35ce6c82021-06-01 15:03:51 +0200118 dev_warn(edev->dev,
Kristofer Jonsson442fefb2022-03-17 17:15:52 +0100119 "Capabilities not found in pending list. handle=0x%p\n",
Davide Grohmann35ce6c82021-06-01 15:03:51 +0200120 cap);
121
Kristofer Jonsson442fefb2022-03-17 17:15:52 +0100122 return;
Davide Grohmann35ce6c82021-06-01 15:03:51 +0200123 }
124
Kristofer Jonsson442fefb2022-03-17 17:15:52 +0100125 if (completion_done(&cap->done))
126 return;
127
Davide Grohmann35ce6c82021-06-01 15:03:51 +0200128 capabilities = cap->capabilities;
129
130 capabilities->hw_id.version_status = msg->version_status;
131 capabilities->hw_id.version_minor = msg->version_minor;
132 capabilities->hw_id.version_major = msg->version_major;
133 capabilities->hw_id.product_major = msg->product_major;
134 capabilities->hw_id.arch_patch_rev = msg->arch_patch_rev;
135 capabilities->hw_id.arch_minor_rev = msg->arch_minor_rev;
136 capabilities->hw_id.arch_major_rev = msg->arch_major_rev;
137 capabilities->driver_patch_rev = msg->driver_patch_rev;
138 capabilities->driver_minor_rev = msg->driver_minor_rev;
139 capabilities->driver_major_rev = msg->driver_major_rev;
140 capabilities->hw_cfg.macs_per_cc = msg->macs_per_cc;
141 capabilities->hw_cfg.cmd_stream_version = msg->cmd_stream_version;
Davide Grohmann35ce6c82021-06-01 15:03:51 +0200142 capabilities->hw_cfg.custom_dma = msg->custom_dma;
143
Kristofer Jonsson442fefb2022-03-17 17:15:52 +0100144 cap->errno = 0;
Davide Grohmann35ce6c82021-06-01 15:03:51 +0200145 complete(&cap->done);
Kristofer Jonsson442fefb2022-03-17 17:15:52 +0100146}
Davide Grohmann35ce6c82021-06-01 15:03:51 +0200147
Kristofer Jonsson442fefb2022-03-17 17:15:52 +0100148static int ethosu_capabilities_request(struct ethosu_device *edev,
149 void __user *udata)
150{
151 struct ethosu_uapi_device_capabilities uapi;
152 struct ethosu_capabilities *cap;
153 int ret;
154 int timeout;
155
156 cap = devm_kzalloc(edev->dev, sizeof(struct ethosu_capabilities),
157 GFP_KERNEL);
158 if (!cap)
159 return -ENOMEM;
160
161 cap->edev = edev;
162 cap->capabilities = &uapi;
163 kref_init(&cap->refcount);
164 init_completion(&cap->done);
165 list_add(&cap->msg.list, &edev->mailbox.pending_list);
166 cap->msg.fail = ethosu_capabilities_fail;
167 cap->msg.resend = ethosu_capabilities_resend;
168
169 ret = ethosu_capabilities_send(cap);
170 if (0 != ret)
171 goto put_kref;
172
173 /* Unlock the mutex before going to block on the condition */
174 mutex_unlock(&edev->mutex);
175
176 /* wait for response to arrive back */
177 timeout = wait_for_completion_timeout(&cap->done,
178 msecs_to_jiffies(
179 CAPABILITIES_RESP_TIMEOUT_MS));
180
181 /* take back the mutex before resuming to do anything */
182 mutex_lock(&edev->mutex);
183
184 if (0 == timeout) {
185 dev_warn(edev->dev, "Capabilities response timeout");
186 ret = -EIO;
187 goto put_kref;
188 }
189
190 if (cap->errno)
191 goto put_kref;
192
193 ret = copy_to_user(udata, &uapi, sizeof(uapi)) ? -EFAULT : 0;
194
195put_kref:
Davide Grohmann35ce6c82021-06-01 15:03:51 +0200196 kref_put(&cap->refcount, ethosu_capabilities_destroy);
197
Kristofer Jonsson442fefb2022-03-17 17:15:52 +0100198 return ret;
Davide Grohmann35ce6c82021-06-01 15:03:51 +0200199}
200
Jonny Svärd7c24c772021-01-14 19:53:17 +0100201/* Incoming messages */
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200202static int ethosu_handle_msg(struct ethosu_device *edev)
203{
Jonny Svärd7c24c772021-01-14 19:53:17 +0100204 int ret;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200205 struct ethosu_core_msg header;
206
207 union {
Davide Grohmann35ce6c82021-06-01 15:03:51 +0200208 struct ethosu_core_msg_err error;
209 struct ethosu_core_inference_rsp inf;
210 struct ethosu_core_msg_version version;
211 struct ethosu_core_msg_capabilities_rsp capabilities;
Kristofer Jonsson3c6a2602022-03-10 11:17:29 +0100212 struct ethosu_core_network_info_rsp network_info;
Davide Grohmann7e8f5082022-03-23 12:48:45 +0100213 struct ethosu_core_cancel_inference_rsp cancellation;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200214 } data;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200215
216 /* Read message */
217 ret = ethosu_mailbox_read(&edev->mailbox, &header, &data, sizeof(data));
218 if (ret)
219 return ret;
220
221 switch (header.type) {
Jonny Svärd7c24c772021-01-14 19:53:17 +0100222 case ETHOSU_CORE_MSG_ERR:
223 if (header.length != sizeof(data.error)) {
224 dev_warn(edev->dev,
225 "Msg: Error message of incorrect size. size=%u, expected=%zu\n", header.length,
226 sizeof(data.error));
227 ret = -EBADMSG;
228 break;
229 }
230
231 data.error.msg[sizeof(data.error.msg) - 1] = '\0';
232 dev_warn(edev->dev, "Msg: Error. type=%u, msg=\"%s\"\n",
233 data.error.type, data.error.msg);
234 ret = -EBADMSG;
235 break;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200236 case ETHOSU_CORE_MSG_PING:
237 dev_info(edev->dev, "Msg: Ping\n");
Jonny Svärd7c24c772021-01-14 19:53:17 +0100238 ret = ethosu_mailbox_pong(&edev->mailbox);
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200239 break;
240 case ETHOSU_CORE_MSG_PONG:
241 dev_info(edev->dev, "Msg: Pong\n");
242 break;
243 case ETHOSU_CORE_MSG_INFERENCE_RSP:
Jonny Svärd7c24c772021-01-14 19:53:17 +0100244 if (header.length != sizeof(data.inf)) {
245 dev_warn(edev->dev,
246 "Msg: Inference response of incorrect size. size=%u, expected=%zu\n", header.length,
247 sizeof(data.inf));
248 ret = -EBADMSG;
249 break;
250 }
251
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200252 dev_info(edev->dev,
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200253 "Msg: Inference response. user_arg=0x%llx, ofm_count=%u, status=%u\n",
254 data.inf.user_arg, data.inf.ofm_count,
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200255 data.inf.status);
Kristofer Jonsson442fefb2022-03-17 17:15:52 +0100256
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200257 ethosu_inference_rsp(edev, &data.inf);
258 break;
Davide Grohmann7e8f5082022-03-23 12:48:45 +0100259 case ETHOSU_CORE_MSG_CANCEL_INFERENCE_RSP:
260 if (header.length != sizeof(data.cancellation)) {
261 dev_warn(edev->dev,
262 "Msg: Cancel Inference response of incorrect size. size=%u, expected=%zu\n", header.length,
263 sizeof(data.cancellation));
264 ret = -EBADMSG;
265 break;
266 }
267
268 dev_info(edev->dev,
269 "Msg: Cancel Inference response. user_arg=0x%llx, status=%u\n",
270 data.cancellation.user_arg, data.cancellation.status);
271 ethosu_cancel_inference_rsp(edev, &data.cancellation);
272 break;
Jonny Svärd7c24c772021-01-14 19:53:17 +0100273 case ETHOSU_CORE_MSG_VERSION_RSP:
274 if (header.length != sizeof(data.version)) {
275 dev_warn(edev->dev,
276 "Msg: Version response of incorrect size. size=%u, expected=%zu\n", header.length,
277 sizeof(data.version));
278 ret = -EBADMSG;
279 break;
280 }
281
282 dev_info(edev->dev, "Msg: Version response v%u.%u.%u\n",
283 data.version.major, data.version.minor,
284 data.version.patch);
285
286 /* Check major and minor version match, else return error */
287 if (data.version.major != ETHOSU_CORE_MSG_VERSION_MAJOR ||
288 data.version.minor != ETHOSU_CORE_MSG_VERSION_MINOR) {
289 dev_warn(edev->dev, "Msg: Version mismatch detected! ");
290 dev_warn(edev->dev, "Local version: v%u.%u.%u\n",
291 ETHOSU_CORE_MSG_VERSION_MAJOR,
292 ETHOSU_CORE_MSG_VERSION_MINOR,
293 ETHOSU_CORE_MSG_VERSION_PATCH);
294 }
295
296 break;
Davide Grohmann35ce6c82021-06-01 15:03:51 +0200297 case ETHOSU_CORE_MSG_CAPABILITIES_RSP:
298 if (header.length != sizeof(data.capabilities)) {
299 dev_warn(edev->dev,
300 "Msg: Capabilities response of incorrect size. size=%u, expected=%zu\n", header.length,
301 sizeof(data.capabilities));
302 ret = -EBADMSG;
303 break;
304 }
Jonny Svärd7c24c772021-01-14 19:53:17 +0100305
Davide Grohmann35ce6c82021-06-01 15:03:51 +0200306 dev_info(edev->dev,
Davide Grohmann40e23d12021-06-17 09:59:40 +0200307 "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 +0200308 data.capabilities.user_arg,
309 data.capabilities.version_status,
310 data.capabilities.version_major,
311 data.capabilities.version_minor,
312 data.capabilities.product_major,
313 data.capabilities.arch_major_rev,
314 data.capabilities.arch_minor_rev,
315 data.capabilities.arch_patch_rev,
316 data.capabilities.driver_major_rev,
317 data.capabilities.driver_minor_rev,
318 data.capabilities.driver_patch_rev,
319 data.capabilities.macs_per_cc,
320 data.capabilities.cmd_stream_version,
Davide Grohmann35ce6c82021-06-01 15:03:51 +0200321 data.capabilities.custom_dma);
322
Kristofer Jonsson442fefb2022-03-17 17:15:52 +0100323 ethosu_capability_rsp(edev, &data.capabilities);
Davide Grohmann35ce6c82021-06-01 15:03:51 +0200324 break;
Kristofer Jonsson3c6a2602022-03-10 11:17:29 +0100325 case ETHOSU_CORE_MSG_NETWORK_INFO_RSP:
326 if (header.length != sizeof(data.network_info)) {
327 dev_warn(edev->dev,
328 "Msg: Network info response of incorrect size. size=%u, expected=%zu\n", header.length,
329 sizeof(data.network_info));
330 ret = -EBADMSG;
331 break;
332 }
333
334 dev_info(edev->dev,
335 "Msg: Network info response. user_arg=0x%llx, status=%u",
336 data.network_info.user_arg,
337 data.network_info.status);
338
339 ethosu_network_info_rsp(edev, &data.network_info);
340
341 break;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200342 default:
Jonny Svärd7c24c772021-01-14 19:53:17 +0100343 /* This should not happen due to version checks */
344 dev_warn(edev->dev, "Msg: Protocol error\n");
345 ret = -EPROTO;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200346 break;
347 }
348
349 return ret;
350}
351
Kristofer Jonsson442fefb2022-03-17 17:15:52 +0100352static int ethosu_firmware_reset(struct ethosu_device *edev)
353{
354 int ret;
355
356 /* No reset control for this device */
357 if (IS_ERR(edev->reset))
358 return PTR_ERR(edev->reset);
359
360 dev_info(edev->dev, "Resetting firmware.");
361
362 ret = reset_control_assert(edev->reset);
363 if (ret) {
364 dev_warn(edev->dev, "Failed to reset assert firmware. ret=%d",
365 ret);
366
367 return ret;
368 }
369
370 /* Initialize mailbox header with illegal values */
371 ethosu_mailbox_wait_prepare(&edev->mailbox);
372
373 /* If this call fails we have a problem. We managed halt the firmware,
374 * but not to release the reset.
375 */
376 ret = reset_control_deassert(edev->reset);
377 if (ret) {
378 dev_warn(edev->dev, "Failed to reset deassert firmware. ret=%d",
379 ret);
380 goto fail;
381 }
382
383 /* Wait for firmware to boot up and initialize mailbox */
384 ret = ethosu_mailbox_wait_firmware(&edev->mailbox);
385 if (ret) {
386 dev_warn(edev->dev, "Wait on firmware boot timed out. ret=%d",
387 ret);
388 goto fail;
389 }
390
391 edev->mailbox.ping_count = 0;
392 ethosu_watchdog_reset(&edev->watchdog);
393
394 ret = ethosu_mailbox_ping(&edev->mailbox);
395 if (ret)
396 goto fail;
397
398 /* Resend messages */
399 ethosu_mailbox_resend(&edev->mailbox);
400
401 return ret;
402
403fail:
404 ethosu_mailbox_fail(&edev->mailbox);
405
406 return ret;
407}
408
Kristofer Jonssonf5b98c92022-03-14 16:09:12 +0100409static void ethosu_watchdog_callback(struct ethosu_watchdog *wdog)
410{
411 struct ethosu_device *edev =
412 container_of(wdog, struct ethosu_device, watchdog);
413
414 mutex_lock(&edev->mutex);
415
Kristofer Jonsson442fefb2022-03-17 17:15:52 +0100416 dev_warn(edev->dev, "Device watchdog timeout. ping_count=%u",
417 edev->mailbox.ping_count);
418
419 if (edev->mailbox.ping_count < 1)
420 ethosu_mailbox_ping(&edev->mailbox);
421 else
422 ethosu_firmware_reset(edev);
Kristofer Jonssonf5b98c92022-03-14 16:09:12 +0100423
424 mutex_unlock(&edev->mutex);
425}
426
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200427static int ethosu_open(struct inode *inode,
428 struct file *file)
429{
430 struct ethosu_device *edev =
431 container_of(inode->i_cdev, struct ethosu_device, cdev);
432
433 file->private_data = edev;
434
435 dev_info(edev->dev, "Opening device node.\n");
436
437 return nonseekable_open(inode, file);
438}
439
440static long ethosu_ioctl(struct file *file,
441 unsigned int cmd,
442 unsigned long arg)
443{
444 struct ethosu_device *edev = file->private_data;
445 void __user *udata = (void __user *)arg;
446 int ret = -EINVAL;
447
448 ret = mutex_lock_interruptible(&edev->mutex);
449 if (ret)
450 return ret;
451
Kristofer Jonsson3c6a2602022-03-10 11:17:29 +0100452 dev_info(edev->dev, "Ioctl. cmd=0x%x, arg=0x%lx\n", cmd, arg);
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200453
454 switch (cmd) {
Jonny Svärd7c24c772021-01-14 19:53:17 +0100455 case ETHOSU_IOCTL_VERSION_REQ:
456 dev_info(edev->dev, "Ioctl: Send version request\n");
457 ret = ethosu_mailbox_version_request(&edev->mailbox);
458 break;
Davide Grohmann35ce6c82021-06-01 15:03:51 +0200459 case ETHOSU_IOCTL_CAPABILITIES_REQ:
460 dev_info(edev->dev, "Ioctl: Send capabilities request\n");
Kristofer Jonsson442fefb2022-03-17 17:15:52 +0100461 ret = ethosu_capabilities_request(edev, udata);
Davide Grohmann35ce6c82021-06-01 15:03:51 +0200462 break;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200463 case ETHOSU_IOCTL_PING: {
464 dev_info(edev->dev, "Ioctl: Send ping\n");
465 ret = ethosu_mailbox_ping(&edev->mailbox);
466 break;
467 }
468 case ETHOSU_IOCTL_BUFFER_CREATE: {
469 struct ethosu_uapi_buffer_create uapi;
470
471 dev_info(edev->dev, "Ioctl: Buffer create\n");
472
473 if (copy_from_user(&uapi, udata, sizeof(uapi)))
474 break;
475
476 dev_info(edev->dev, "Ioctl: Buffer. capacity=%u\n",
477 uapi.capacity);
478
479 ret = ethosu_buffer_create(edev, uapi.capacity);
480 break;
481 }
482 case ETHOSU_IOCTL_NETWORK_CREATE: {
483 struct ethosu_uapi_network_create uapi;
484
485 if (copy_from_user(&uapi, udata, sizeof(uapi)))
486 break;
487
488 dev_info(edev->dev, "Ioctl: Network. fd=%u\n", uapi.fd);
489
490 ret = ethosu_network_create(edev, &uapi);
491 break;
492 }
493 default: {
494 dev_err(edev->dev, "Invalid ioctl. cmd=%u, arg=%lu",
495 cmd, arg);
496 break;
497 }
498 }
499
500 mutex_unlock(&edev->mutex);
501
502 return ret;
503}
504
505static void ethosu_mbox_rx(void *user_arg)
506{
507 struct ethosu_device *edev = user_arg;
508 int ret;
509
510 mutex_lock(&edev->mutex);
511
512 do {
513 ret = ethosu_handle_msg(edev);
Jonny Svärd7c24c772021-01-14 19:53:17 +0100514 if (ret && ret != -ENOMSG)
515 /* Need to start over in case of error, empty the queue
516 * by fast-forwarding read position to write position.
517 * */
518 ethosu_mailbox_reset(&edev->mailbox);
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200519 } while (ret == 0);
520
521 mutex_unlock(&edev->mutex);
522}
523
524int ethosu_dev_init(struct ethosu_device *edev,
525 struct device *dev,
526 struct class *class,
Kristofer Jonsson4aec3762021-10-13 17:09:27 +0200527 dev_t devt,
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200528 struct resource *in_queue,
529 struct resource *out_queue)
530{
531 static const struct file_operations fops = {
532 .owner = THIS_MODULE,
533 .open = &ethosu_open,
534 .unlocked_ioctl = &ethosu_ioctl,
535#ifdef CONFIG_COMPAT
536 .compat_ioctl = &ethosu_ioctl,
537#endif
538 };
539 struct device *sysdev;
540 int ret;
541
542 edev->dev = dev;
543 edev->class = class;
Kristofer Jonsson4aec3762021-10-13 17:09:27 +0200544 edev->devt = devt;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200545 mutex_init(&edev->mutex);
Kristofer Jonsson442fefb2022-03-17 17:15:52 +0100546
547 edev->reset = devm_reset_control_get_by_index(edev->dev, 0);
548 if (IS_ERR(edev->reset))
549 dev_warn(edev->dev, "No reset control found for this device.");
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200550
551 ret = of_reserved_mem_device_init(edev->dev);
552 if (ret)
553 return ret;
554
555 dma_set_mask_and_coherent(edev->dev, DMA_BIT_MASK(DMA_ADDR_BITS));
556
Kristofer Jonssonf5b98c92022-03-14 16:09:12 +0100557 ret = ethosu_watchdog_init(&edev->watchdog, dev,
558 ethosu_watchdog_callback);
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200559 if (ret)
560 goto release_reserved_mem;
561
Kristofer Jonssonf5b98c92022-03-14 16:09:12 +0100562 ret = ethosu_mailbox_init(&edev->mailbox, dev, in_queue, out_queue,
563 ethosu_mbox_rx, edev, &edev->watchdog);
564 if (ret)
565 goto deinit_watchdog;
566
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200567 cdev_init(&edev->cdev, &fops);
568 edev->cdev.owner = THIS_MODULE;
569
Kristofer Jonsson4aec3762021-10-13 17:09:27 +0200570 ret = cdev_add(&edev->cdev, edev->devt, 1);
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200571 if (ret) {
572 dev_err(edev->dev, "Failed to add character device.\n");
Kristofer Jonsson4aec3762021-10-13 17:09:27 +0200573 goto deinit_mailbox;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200574 }
575
576 sysdev = device_create(edev->class, NULL, edev->devt, edev,
Kristofer Jonsson4aec3762021-10-13 17:09:27 +0200577 "ethosu%d", MINOR(edev->devt));
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200578 if (IS_ERR(sysdev)) {
579 dev_err(edev->dev, "Failed to create device.\n");
580 ret = PTR_ERR(sysdev);
581 goto del_cdev;
582 }
583
Kristofer Jonsson442fefb2022-03-17 17:15:52 +0100584 ethosu_firmware_reset(edev);
585
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200586 dev_info(edev->dev,
587 "Created Arm Ethos-U device. name=%s, major=%d, minor=%d\n",
588 dev_name(sysdev), MAJOR(edev->devt), MINOR(edev->devt));
589
590 return 0;
591
592del_cdev:
593 cdev_del(&edev->cdev);
594
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200595deinit_mailbox:
596 ethosu_mailbox_deinit(&edev->mailbox);
597
Kristofer Jonssonf5b98c92022-03-14 16:09:12 +0100598deinit_watchdog:
599 ethosu_watchdog_deinit(&edev->watchdog);
600
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200601release_reserved_mem:
602 of_reserved_mem_device_release(edev->dev);
603
604 return ret;
605}
606
607void ethosu_dev_deinit(struct ethosu_device *edev)
608{
609 ethosu_mailbox_deinit(&edev->mailbox);
Kristofer Jonssonf5b98c92022-03-14 16:09:12 +0100610 ethosu_watchdog_deinit(&edev->watchdog);
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200611 device_destroy(edev->class, edev->cdev.dev);
612 cdev_del(&edev->cdev);
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200613 of_reserved_mem_device_release(edev->dev);
614
615 dev_info(edev->dev, "%s\n", __FUNCTION__);
616}