blob: 96bd8b4a67108bd6a6d88881f1ec534cbeddf776 [file] [log] [blame]
Kristofer Jonsson116a6352020-08-20 17:25:23 +02001/*
Kristofer Jonssonb42bc0b2023-01-04 17:09:28 +01002 * Copyright 2020-2023 Arm Limited and/or its affiliates
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"
Kristofer Jonssond779a082023-01-04 17:09:47 +010028#include "ethosu_core_rpmsg.h"
Davide Grohmann32660f92022-04-27 16:49:07 +020029#include "ethosu_capabilities.h"
Kristofer Jonsson116a6352020-08-20 17:25:23 +020030#include "ethosu_inference.h"
Davide Grohmann7e8f5082022-03-23 12:48:45 +010031#include "ethosu_cancel_inference.h"
Kristofer Jonsson116a6352020-08-20 17:25:23 +020032#include "ethosu_network.h"
Kristofer Jonsson3c6a2602022-03-10 11:17:29 +010033#include "ethosu_network_info.h"
Kristofer Jonsson116a6352020-08-20 17:25:23 +020034#include "uapi/ethosu.h"
35
Kristofer Jonsson116a6352020-08-20 17:25:23 +020036#include <linux/errno.h>
37#include <linux/fs.h>
Kristofer Jonsson116a6352020-08-20 17:25:23 +020038#include <linux/io.h>
39#include <linux/of_reserved_mem.h>
Kristofer Jonssonec477042023-01-20 13:38:13 +010040#include <linux/remoteproc.h>
Davide Grohmann35ce6c82021-06-01 15:03:51 +020041#include <linux/slab.h>
Kristofer Jonsson442fefb2022-03-17 17:15:52 +010042#include <linux/uaccess.h>
Kristofer Jonsson116a6352020-08-20 17:25:23 +020043
44/****************************************************************************
Kristofer Jonsson074ef902023-01-23 13:05:36 +010045 * Defines
46 ****************************************************************************/
47
48#define MINOR_BASE 0 /* Minor version starts at 0 */
49#define MINOR_COUNT 64 /* Allocate minor versions */
50
51/****************************************************************************
52 * Variables
53 ****************************************************************************/
54
55static DECLARE_BITMAP(minors, MINOR_COUNT);
56
57/****************************************************************************
Kristofer Jonsson116a6352020-08-20 17:25:23 +020058 * Functions
59 ****************************************************************************/
60
Jonny Svärd7c24c772021-01-14 19:53:17 +010061/* Incoming messages */
Kristofer Jonssonec477042023-01-20 13:38:13 +010062static int ethosu_handle_rpmsg(struct rpmsg_device *rpdev,
63 void *data,
64 int len,
65 void *priv,
66 u32 src)
Kristofer Jonsson116a6352020-08-20 17:25:23 +020067{
Kristofer Jonssond779a082023-01-04 17:09:47 +010068 struct ethosu_device *edev = dev_get_drvdata(&rpdev->dev);
Kristofer Jonsson074ef902023-01-23 13:05:36 +010069 struct device *dev = &edev->dev;
Kristofer Jonssond779a082023-01-04 17:09:47 +010070 struct ethosu_core_rpmsg *rpmsg = data;
71 int length = len - sizeof(rpmsg->header);
Jonny Svärd7c24c772021-01-14 19:53:17 +010072 int ret;
Kristofer Jonsson116a6352020-08-20 17:25:23 +020073
Kristofer Jonssond779a082023-01-04 17:09:47 +010074 dev_info(dev,
75 "Msg: magic=0x%08x, type=%u, msg_id=%llu",
76 rpmsg->header.magic, rpmsg->header.type, rpmsg->header.msg_id);
Kristofer Jonsson116a6352020-08-20 17:25:23 +020077
Kristofer Jonssond779a082023-01-04 17:09:47 +010078 switch (rpmsg->header.type) {
Kristofer Jonsson074ef902023-01-23 13:05:36 +010079 case ETHOSU_CORE_MSG_ERR:
Kristofer Jonssond779a082023-01-04 17:09:47 +010080 if (length != sizeof(rpmsg->error)) {
81 dev_warn(dev,
82 "Msg: Error message of incorrect size. size=%u, expected=%zu", length,
83 sizeof(rpmsg->error));
Jonny Svärd7c24c772021-01-14 19:53:17 +010084 ret = -EBADMSG;
85 break;
86 }
87
Kristofer Jonssond779a082023-01-04 17:09:47 +010088 rpmsg->error.msg[sizeof(rpmsg->error.msg) - 1] = '\0';
89 dev_warn(dev, "Msg: Error. type=%u, msg=\"%s\"",
90 rpmsg->error.type, rpmsg->error.msg);
Kristofer Jonsson074ef902023-01-23 13:05:36 +010091
92 rproc_report_crash(rproc_get_by_child(dev), RPROC_FATAL_ERROR);
Jonny Svärd7c24c772021-01-14 19:53:17 +010093 break;
Kristofer Jonsson116a6352020-08-20 17:25:23 +020094 case ETHOSU_CORE_MSG_PING:
Kristofer Jonssond779a082023-01-04 17:09:47 +010095 dev_info(dev, "Msg: Ping");
Jonny Svärd7c24c772021-01-14 19:53:17 +010096 ret = ethosu_mailbox_pong(&edev->mailbox);
Kristofer Jonsson116a6352020-08-20 17:25:23 +020097 break;
98 case ETHOSU_CORE_MSG_PONG:
Kristofer Jonssond779a082023-01-04 17:09:47 +010099 dev_info(dev, "Msg: Pong");
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200100 break;
101 case ETHOSU_CORE_MSG_INFERENCE_RSP:
Kristofer Jonssond779a082023-01-04 17:09:47 +0100102 if (length != sizeof(rpmsg->inf_rsp)) {
103 dev_warn(dev,
104 "Msg: Inference response of incorrect size. size=%u, expected=%zu", length,
105 sizeof(rpmsg->inf_rsp));
Jonny Svärd7c24c772021-01-14 19:53:17 +0100106 ret = -EBADMSG;
107 break;
108 }
109
Kristofer Jonssond779a082023-01-04 17:09:47 +0100110 dev_info(dev,
111 "Msg: Inference response. ofm_count=%u, status=%u",
112 rpmsg->inf_rsp.ofm_count, rpmsg->inf_rsp.status);
Kristofer Jonsson442fefb2022-03-17 17:15:52 +0100113
Kristofer Jonssonec477042023-01-20 13:38:13 +0100114 ethosu_inference_rsp(&edev->mailbox, rpmsg->header.msg_id,
Kristofer Jonssond779a082023-01-04 17:09:47 +0100115 &rpmsg->inf_rsp);
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200116 break;
Davide Grohmann7e8f5082022-03-23 12:48:45 +0100117 case ETHOSU_CORE_MSG_CANCEL_INFERENCE_RSP:
Kristofer Jonssond779a082023-01-04 17:09:47 +0100118 if (length != sizeof(rpmsg->cancel_rsp)) {
119 dev_warn(dev,
120 "Msg: Cancel Inference response of incorrect size. size=%u, expected=%zu", length,
121 sizeof(rpmsg->cancel_rsp));
Davide Grohmann7e8f5082022-03-23 12:48:45 +0100122 ret = -EBADMSG;
123 break;
124 }
125
Kristofer Jonssond779a082023-01-04 17:09:47 +0100126 dev_info(dev,
127 "Msg: Cancel Inference response. status=%u",
128 rpmsg->cancel_rsp.status);
Kristofer Jonssonec477042023-01-20 13:38:13 +0100129 ethosu_cancel_inference_rsp(&edev->mailbox,
130 rpmsg->header.msg_id,
Kristofer Jonssond779a082023-01-04 17:09:47 +0100131 &rpmsg->cancel_rsp);
Davide Grohmann7e8f5082022-03-23 12:48:45 +0100132 break;
Jonny Svärd7c24c772021-01-14 19:53:17 +0100133 case ETHOSU_CORE_MSG_VERSION_RSP:
Kristofer Jonssond779a082023-01-04 17:09:47 +0100134 if (length != sizeof(rpmsg->version_rsp)) {
135 dev_warn(dev,
136 "Msg: Version response of incorrect size. size=%u, expected=%zu", length,
137 sizeof(rpmsg->version_rsp));
Jonny Svärd7c24c772021-01-14 19:53:17 +0100138 ret = -EBADMSG;
139 break;
140 }
141
Kristofer Jonssond779a082023-01-04 17:09:47 +0100142 dev_info(dev, "Msg: Version response v%u.%u.%u",
143 rpmsg->version_rsp.major, rpmsg->version_rsp.minor,
144 rpmsg->version_rsp.patch);
Jonny Svärd7c24c772021-01-14 19:53:17 +0100145
146 /* Check major and minor version match, else return error */
Kristofer Jonssond779a082023-01-04 17:09:47 +0100147 if (rpmsg->version_rsp.major != ETHOSU_CORE_MSG_VERSION_MAJOR ||
148 rpmsg->version_rsp.minor != ETHOSU_CORE_MSG_VERSION_MINOR) {
149 dev_warn(dev, "Msg: Version mismatch detected! ");
150 dev_warn(dev, "Local version: v%u.%u.%u",
Jonny Svärd7c24c772021-01-14 19:53:17 +0100151 ETHOSU_CORE_MSG_VERSION_MAJOR,
152 ETHOSU_CORE_MSG_VERSION_MINOR,
153 ETHOSU_CORE_MSG_VERSION_PATCH);
154 }
155
156 break;
Davide Grohmann35ce6c82021-06-01 15:03:51 +0200157 case ETHOSU_CORE_MSG_CAPABILITIES_RSP:
Kristofer Jonssond779a082023-01-04 17:09:47 +0100158 if (length != sizeof(rpmsg->cap_rsp)) {
159 dev_warn(dev,
160 "Msg: Capabilities response of incorrect size. size=%u, expected=%zu", length,
161 sizeof(rpmsg->cap_rsp));
Davide Grohmann35ce6c82021-06-01 15:03:51 +0200162 ret = -EBADMSG;
163 break;
164 }
Jonny Svärd7c24c772021-01-14 19:53:17 +0100165
Kristofer Jonssond779a082023-01-04 17:09:47 +0100166 dev_info(dev,
167 "Msg: Capabilities response vs%hhu v%hhu.%hhu p%hhu av%hhu.%hhu.%hhu dv%hhu.%hhu.%hhu mcc%hhu csv%hhu cd%hhu",
168 rpmsg->cap_rsp.version_status,
169 rpmsg->cap_rsp.version_major,
170 rpmsg->cap_rsp.version_minor,
171 rpmsg->cap_rsp.product_major,
172 rpmsg->cap_rsp.arch_major_rev,
173 rpmsg->cap_rsp.arch_minor_rev,
174 rpmsg->cap_rsp.arch_patch_rev,
175 rpmsg->cap_rsp.driver_major_rev,
176 rpmsg->cap_rsp.driver_minor_rev,
177 rpmsg->cap_rsp.driver_patch_rev,
178 rpmsg->cap_rsp.macs_per_cc,
179 rpmsg->cap_rsp.cmd_stream_version,
180 rpmsg->cap_rsp.custom_dma);
Davide Grohmann35ce6c82021-06-01 15:03:51 +0200181
Kristofer Jonssonec477042023-01-20 13:38:13 +0100182 ethosu_capability_rsp(&edev->mailbox, rpmsg->header.msg_id,
Kristofer Jonssond779a082023-01-04 17:09:47 +0100183 &rpmsg->cap_rsp);
Davide Grohmann35ce6c82021-06-01 15:03:51 +0200184 break;
Kristofer Jonsson3c6a2602022-03-10 11:17:29 +0100185 case ETHOSU_CORE_MSG_NETWORK_INFO_RSP:
Kristofer Jonssond779a082023-01-04 17:09:47 +0100186 if (length != sizeof(rpmsg->net_info_rsp)) {
187 dev_warn(dev,
188 "Msg: Network info response of incorrect size. size=%u, expected=%zu", length,
189 sizeof(rpmsg->net_info_rsp));
Kristofer Jonsson3c6a2602022-03-10 11:17:29 +0100190 ret = -EBADMSG;
191 break;
192 }
193
Kristofer Jonssond779a082023-01-04 17:09:47 +0100194 dev_info(dev,
195 "Msg: Network info response. status=%u",
196 rpmsg->net_info_rsp.status);
Kristofer Jonsson3c6a2602022-03-10 11:17:29 +0100197
Kristofer Jonssonec477042023-01-20 13:38:13 +0100198 ethosu_network_info_rsp(&edev->mailbox,
199 rpmsg->header.msg_id,
Kristofer Jonssond779a082023-01-04 17:09:47 +0100200 &rpmsg->net_info_rsp);
Kristofer Jonsson3c6a2602022-03-10 11:17:29 +0100201
202 break;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200203 default:
Jonny Svärd7c24c772021-01-14 19:53:17 +0100204 /* This should not happen due to version checks */
Kristofer Jonssond779a082023-01-04 17:09:47 +0100205 dev_warn(dev, "Msg: Protocol error. type=%u",
206 rpmsg->header.type);
Jonny Svärd7c24c772021-01-14 19:53:17 +0100207 ret = -EPROTO;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200208 break;
209 }
210
211 return ret;
212}
213
214static int ethosu_open(struct inode *inode,
215 struct file *file)
216{
Kristofer Jonssonec477042023-01-20 13:38:13 +0100217 struct cdev *cdev = inode->i_cdev;
218 struct ethosu_device *edev = container_of(cdev, struct ethosu_device,
219 cdev);
220 struct rpmsg_device *rpdev = edev->rpdev;
Kristofer Jonsson074ef902023-01-23 13:05:36 +0100221 struct device *dev = &edev->dev;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200222
Kristofer Jonssonec477042023-01-20 13:38:13 +0100223 dev_info(dev, "Device open. file=0x%pK", file);
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200224
Kristofer Jonssonec477042023-01-20 13:38:13 +0100225 file->private_data = rpdev;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200226
227 return nonseekable_open(inode, file);
228}
229
230static long ethosu_ioctl(struct file *file,
231 unsigned int cmd,
232 unsigned long arg)
233{
Kristofer Jonssonec477042023-01-20 13:38:13 +0100234 struct rpmsg_device *rpdev = file->private_data;
Kristofer Jonsson074ef902023-01-23 13:05:36 +0100235 struct ethosu_device *edev = dev_get_drvdata(&rpdev->dev);
236 struct device *dev = &edev->dev;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200237 void __user *udata = (void __user *)arg;
238 int ret = -EINVAL;
239
Kristofer Jonssonec477042023-01-20 13:38:13 +0100240 ret = device_lock_interruptible(dev);
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200241 if (ret)
242 return ret;
243
Kristofer Jonssonec477042023-01-20 13:38:13 +0100244 dev_info(dev, "Device ioctl. file=0x%pK, cmd=0x%x, arg=0x%lx",
Kristofer Jonsson53fd03d2022-06-21 16:58:45 +0200245 file, cmd, arg);
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200246
247 switch (cmd) {
Jonny Svärd7c24c772021-01-14 19:53:17 +0100248 case ETHOSU_IOCTL_VERSION_REQ:
Kristofer Jonssonec477042023-01-20 13:38:13 +0100249 dev_info(dev, "Device ioctl: Send version request");
Jonny Svärd7c24c772021-01-14 19:53:17 +0100250 ret = ethosu_mailbox_version_request(&edev->mailbox);
251 break;
Davide Grohmann32660f92022-04-27 16:49:07 +0200252 case ETHOSU_IOCTL_CAPABILITIES_REQ: {
253 struct ethosu_uapi_device_capabilities uapi;
Kristofer Jonsson53fd03d2022-06-21 16:58:45 +0200254
Kristofer Jonssonec477042023-01-20 13:38:13 +0100255 dev_info(dev,
Kristofer Jonssond779a082023-01-04 17:09:47 +0100256 "Device ioctl: Send capabilities request");
Kristofer Jonsson53fd03d2022-06-21 16:58:45 +0200257
Kristofer Jonssonec477042023-01-20 13:38:13 +0100258 ret = ethosu_capabilities_request(dev, &edev->mailbox, &uapi);
Davide Grohmann32660f92022-04-27 16:49:07 +0200259 if (ret)
260 break;
261
262 ret = copy_to_user(udata, &uapi, sizeof(uapi)) ? -EFAULT : 0;
Davide Grohmann35ce6c82021-06-01 15:03:51 +0200263 break;
Davide Grohmann32660f92022-04-27 16:49:07 +0200264 }
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200265 case ETHOSU_IOCTL_PING: {
Kristofer Jonssonec477042023-01-20 13:38:13 +0100266 dev_info(dev, "Device ioctl: Send ping");
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200267 ret = ethosu_mailbox_ping(&edev->mailbox);
268 break;
269 }
270 case ETHOSU_IOCTL_BUFFER_CREATE: {
271 struct ethosu_uapi_buffer_create uapi;
272
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200273 if (copy_from_user(&uapi, udata, sizeof(uapi)))
274 break;
275
Kristofer Jonssonec477042023-01-20 13:38:13 +0100276 dev_info(dev,
Kristofer Jonssond779a082023-01-04 17:09:47 +0100277 "Device ioctl: Buffer create. capacity=%u",
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200278 uapi.capacity);
279
Kristofer Jonssonec477042023-01-20 13:38:13 +0100280 ret = ethosu_buffer_create(dev, uapi.capacity);
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200281 break;
282 }
283 case ETHOSU_IOCTL_NETWORK_CREATE: {
284 struct ethosu_uapi_network_create uapi;
285
286 if (copy_from_user(&uapi, udata, sizeof(uapi)))
287 break;
288
Kristofer Jonssonec477042023-01-20 13:38:13 +0100289 dev_info(dev,
Kristofer Jonssond779a082023-01-04 17:09:47 +0100290 "Device ioctl: Network create. type=%u, fd/index=%u",
Kristofer Jonsson53fd03d2022-06-21 16:58:45 +0200291 uapi.type, uapi.fd);
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200292
Kristofer Jonssonec477042023-01-20 13:38:13 +0100293 ret = ethosu_network_create(dev, &edev->mailbox, &uapi);
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200294 break;
295 }
296 default: {
Kristofer Jonssonec477042023-01-20 13:38:13 +0100297 dev_err(dev, "Invalid ioctl. cmd=%u, arg=%lu",
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200298 cmd, arg);
299 break;
300 }
301 }
302
Kristofer Jonssonec477042023-01-20 13:38:13 +0100303 device_unlock(dev);
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200304
305 return ret;
306}
307
Kristofer Jonssond779a082023-01-04 17:09:47 +0100308static struct rpmsg_endpoint *ethosu_create_ept(struct rpmsg_device *rpdev)
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200309{
Kristofer Jonssond779a082023-01-04 17:09:47 +0100310 struct device *dev = &rpdev->dev;
311 struct rpmsg_channel_info info;
312 struct rpmsg_endpoint *ept;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200313
Kristofer Jonssond779a082023-01-04 17:09:47 +0100314 /* Create rpmsg endpoint */
315 strncpy(info.name, rpdev->id.name, sizeof(info.name));
316 info.src = 0;
317 info.dst = rpdev->dst;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200318
Kristofer Jonssond779a082023-01-04 17:09:47 +0100319 dev_info(dev, "Creating rpmsg endpoint. name=%s, src=%u, dst=%u",
320 info.name, info.src, info.dst);
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200321
Kristofer Jonssonec477042023-01-20 13:38:13 +0100322 ept = rpmsg_create_ept(rpdev, ethosu_handle_rpmsg, NULL, info);
Kristofer Jonssond779a082023-01-04 17:09:47 +0100323 if (!ept) {
324 dev_err(&rpdev->dev, "Failed to create endpoint");
325
326 return ERR_PTR(-EINVAL);
327 }
328
329 return ept;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200330}
331
Kristofer Jonssonec477042023-01-20 13:38:13 +0100332static const struct file_operations fops = {
333 .owner = THIS_MODULE,
334 .open = &ethosu_open,
335 .unlocked_ioctl = &ethosu_ioctl,
336#ifdef CONFIG_COMPAT
337 .compat_ioctl = &ethosu_ioctl,
338#endif
339};
340
Kristofer Jonsson074ef902023-01-23 13:05:36 +0100341static void ethosu_dev_release(struct device *dev)
342{
343 struct ethosu_device *edev = dev_get_drvdata(dev);
344
345 dev_info(dev, "%s", __FUNCTION__);
346
347 clear_bit(MINOR(edev->cdev.dev), minors);
348
349 ethosu_mailbox_deinit(&edev->mailbox);
350 device_destroy(edev->class, edev->cdev.dev);
351 kfree(edev);
352}
353
354static int ethosu_device_register(struct device *dev,
355 struct device *parent,
356 void *drvdata,
357 dev_t devt)
358{
359 struct rproc *rproc = rproc_get_by_child(parent);
360 int ret;
361
362 dev->parent = parent;
363 dev->release = ethosu_dev_release;
364 dev_set_drvdata(dev, drvdata);
365
366 ret = dev_set_name(dev, "ethosu%d", MINOR(devt));
367 if (ret) {
368 dev_err(parent, "Failed to set device name. ret=%d", ret);
369
370 return ret;
371 }
372
373 /* Inherit DMA settings for rproc device */
374 ret = of_reserved_mem_device_init_by_idx(dev,
375 rproc->dev.parent->of_node, 0);
376 if (ret) {
377 dev_err(parent, "Failed to initialize reserved memory. ret=%d",
378 ret);
379
380 return ret;
381 }
382
383 ret = device_register(dev);
384 if (ret) {
385 dev_err(parent, "Failed to register device. ret=%d", ret);
386
387 return ret;
388 }
389
390 return 0;
391}
392
Kristofer Jonssonec477042023-01-20 13:38:13 +0100393int ethosu_dev_init(struct rpmsg_device *rpdev,
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200394 struct class *class,
Kristofer Jonssond779a082023-01-04 17:09:47 +0100395 dev_t devt)
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200396{
Kristofer Jonssonec477042023-01-20 13:38:13 +0100397 struct device *dev = &rpdev->dev;
398 struct ethosu_device *edev;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200399 struct device *sysdev;
Kristofer Jonsson074ef902023-01-23 13:05:36 +0100400 int minor;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200401 int ret;
402
Kristofer Jonssonec477042023-01-20 13:38:13 +0100403 dev_info(dev, "%s", __FUNCTION__);
404
Kristofer Jonsson074ef902023-01-23 13:05:36 +0100405 /* Reserve minor number for device node */
406 minor = find_first_zero_bit(minors, MINOR_COUNT);
407 if (minor >= MINOR_COUNT) {
408 dev_err(dev, "No more minor numbers.");
409
410 return -ENOMEM;
411 }
412
413 devt = MKDEV(MAJOR(devt), minor);
414
Kristofer Jonssonec477042023-01-20 13:38:13 +0100415 /* Allocate and create Ethos-U device */
Kristofer Jonsson074ef902023-01-23 13:05:36 +0100416 edev = kzalloc(sizeof(*edev), GFP_KERNEL);
Kristofer Jonssonec477042023-01-20 13:38:13 +0100417 if (!edev)
418 return -ENOMEM;
419
Kristofer Jonsson074ef902023-01-23 13:05:36 +0100420 dev_set_drvdata(&rpdev->dev, edev);
Kristofer Jonssonec477042023-01-20 13:38:13 +0100421
Kristofer Jonssond779a082023-01-04 17:09:47 +0100422 edev->rpdev = rpdev;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200423 edev->class = class;
Kristofer Jonsson074ef902023-01-23 13:05:36 +0100424
425 /* Create device object */
426 ret = ethosu_device_register(&edev->dev, &rpdev->dev, edev,
427 devt);
428 if (ret)
429 goto free_edev;
430
431 /* Continue with new device */
432 dev = &edev->dev;
Kristofer Jonsson442fefb2022-03-17 17:15:52 +0100433
Kristofer Jonssonec477042023-01-20 13:38:13 +0100434 /* Create RPMsg endpoint */
Kristofer Jonssond779a082023-01-04 17:09:47 +0100435 edev->ept = ethosu_create_ept(rpdev);
Kristofer Jonsson074ef902023-01-23 13:05:36 +0100436 if (IS_ERR(edev->ept)) {
437 ret = PTR_ERR(edev->ept);
438 goto device_unregister;
439 }
Kristofer Jonssond779a082023-01-04 17:09:47 +0100440
Kristofer Jonssonec477042023-01-20 13:38:13 +0100441 ret = ethosu_mailbox_init(&edev->mailbox, dev, edev->ept);
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200442 if (ret)
Kristofer Jonsson074ef902023-01-23 13:05:36 +0100443 goto device_unregister;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200444
Kristofer Jonssonec477042023-01-20 13:38:13 +0100445 /* Create device node */
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200446 cdev_init(&edev->cdev, &fops);
447 edev->cdev.owner = THIS_MODULE;
448
Kristofer Jonsson074ef902023-01-23 13:05:36 +0100449 cdev_set_parent(&edev->cdev, &dev->kobj);
450
451 ret = cdev_add(&edev->cdev, devt, 1);
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200452 if (ret) {
Kristofer Jonssonec477042023-01-20 13:38:13 +0100453 dev_err(dev, "Failed to add character device.");
Kristofer Jonsson4aec3762021-10-13 17:09:27 +0200454 goto deinit_mailbox;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200455 }
456
Kristofer Jonsson074ef902023-01-23 13:05:36 +0100457 sysdev = device_create(edev->class, NULL, devt, rpdev,
458 "ethosu%d", MINOR(devt));
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200459 if (IS_ERR(sysdev)) {
Kristofer Jonssonec477042023-01-20 13:38:13 +0100460 dev_err(dev, "Failed to create device.");
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200461 ret = PTR_ERR(sysdev);
462 goto del_cdev;
463 }
464
Kristofer Jonsson074ef902023-01-23 13:05:36 +0100465 set_bit(minor, minors);
466
Kristofer Jonssonec477042023-01-20 13:38:13 +0100467 dev_info(dev,
Kristofer Jonssond779a082023-01-04 17:09:47 +0100468 "Created Arm Ethos-U device. name=%s, major=%d, minor=%d",
Kristofer Jonsson074ef902023-01-23 13:05:36 +0100469 dev_name(sysdev), MAJOR(devt), MINOR(devt));
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200470
Kristofer Jonssond779a082023-01-04 17:09:47 +0100471 ethosu_mailbox_ping(&edev->mailbox);
472
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200473 return 0;
474
475del_cdev:
476 cdev_del(&edev->cdev);
477
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200478deinit_mailbox:
479 ethosu_mailbox_deinit(&edev->mailbox);
480
Kristofer Jonsson074ef902023-01-23 13:05:36 +0100481device_unregister:
482 device_unregister(dev);
483
484free_edev:
485 kfree(edev);
486
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200487 return ret;
488}
489
Kristofer Jonssonec477042023-01-20 13:38:13 +0100490void ethosu_dev_deinit(struct rpmsg_device *rpdev)
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200491{
Kristofer Jonssonec477042023-01-20 13:38:13 +0100492 struct device *dev = &rpdev->dev;
493 struct ethosu_device *edev = dev_get_drvdata(dev);
494
495 dev_info(dev, "%s", __FUNCTION__);
Kristofer Jonssond779a082023-01-04 17:09:47 +0100496
Kristofer Jonsson074ef902023-01-23 13:05:36 +0100497 ethosu_mailbox_fail(&edev->mailbox);
Kristofer Jonssond779a082023-01-04 17:09:47 +0100498 rpmsg_destroy_ept(edev->ept);
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200499 cdev_del(&edev->cdev);
Kristofer Jonsson074ef902023-01-23 13:05:36 +0100500 device_unregister(&edev->dev);
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200501}