blob: 002e93404a683e7d75fdc05d8fdc9019d66adad3 [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
Mikael Olsson099d90c2023-05-02 10:39:22 +020036#include <linux/dma-mapping.h>
Kristofer Jonsson116a6352020-08-20 17:25:23 +020037#include <linux/errno.h>
38#include <linux/fs.h>
Kristofer Jonsson116a6352020-08-20 17:25:23 +020039#include <linux/io.h>
40#include <linux/of_reserved_mem.h>
Kristofer Jonssonec477042023-01-20 13:38:13 +010041#include <linux/remoteproc.h>
Davide Grohmann35ce6c82021-06-01 15:03:51 +020042#include <linux/slab.h>
Kristofer Jonsson442fefb2022-03-17 17:15:52 +010043#include <linux/uaccess.h>
Kristofer Jonsson116a6352020-08-20 17:25:23 +020044
45/****************************************************************************
Kristofer Jonsson074ef902023-01-23 13:05:36 +010046 * Defines
47 ****************************************************************************/
48
49#define MINOR_BASE 0 /* Minor version starts at 0 */
50#define MINOR_COUNT 64 /* Allocate minor versions */
51
Mikael Olsson099d90c2023-05-02 10:39:22 +020052#define DMA_ADDR_BITS 32 /* Number of address bits */
53
Kristofer Jonsson074ef902023-01-23 13:05:36 +010054/****************************************************************************
55 * Variables
56 ****************************************************************************/
57
58static DECLARE_BITMAP(minors, MINOR_COUNT);
59
60/****************************************************************************
Kristofer Jonsson116a6352020-08-20 17:25:23 +020061 * Functions
62 ****************************************************************************/
63
Jonny Svärd7c24c772021-01-14 19:53:17 +010064/* Incoming messages */
Kristofer Jonssonec477042023-01-20 13:38:13 +010065static int ethosu_handle_rpmsg(struct rpmsg_device *rpdev,
66 void *data,
67 int len,
68 void *priv,
69 u32 src)
Kristofer Jonsson116a6352020-08-20 17:25:23 +020070{
Kristofer Jonssond779a082023-01-04 17:09:47 +010071 struct ethosu_device *edev = dev_get_drvdata(&rpdev->dev);
Kristofer Jonsson074ef902023-01-23 13:05:36 +010072 struct device *dev = &edev->dev;
Kristofer Jonssond779a082023-01-04 17:09:47 +010073 struct ethosu_core_rpmsg *rpmsg = data;
74 int length = len - sizeof(rpmsg->header);
Jonny Svärd7c24c772021-01-14 19:53:17 +010075 int ret;
Kristofer Jonsson116a6352020-08-20 17:25:23 +020076
Mikael Olssonfd6b8dc2023-05-10 14:46:30 +020077 if (unlikely(rpmsg->header.magic != ETHOSU_CORE_MSG_MAGIC)) {
78 dev_warn(dev, "Msg: Error invalid message magic. magic=0x%08x",
79 rpmsg->header.magic);
80
81 return -EBADMSG;
82 }
83
Kristofer Jonssond779a082023-01-04 17:09:47 +010084 dev_info(dev,
85 "Msg: magic=0x%08x, type=%u, msg_id=%llu",
86 rpmsg->header.magic, rpmsg->header.type, rpmsg->header.msg_id);
Kristofer Jonsson116a6352020-08-20 17:25:23 +020087
Kristofer Jonssond779a082023-01-04 17:09:47 +010088 switch (rpmsg->header.type) {
Kristofer Jonsson074ef902023-01-23 13:05:36 +010089 case ETHOSU_CORE_MSG_ERR:
Kristofer Jonssond779a082023-01-04 17:09:47 +010090 if (length != sizeof(rpmsg->error)) {
91 dev_warn(dev,
92 "Msg: Error message of incorrect size. size=%u, expected=%zu", length,
93 sizeof(rpmsg->error));
Jonny Svärd7c24c772021-01-14 19:53:17 +010094 ret = -EBADMSG;
95 break;
96 }
97
Kristofer Jonssond779a082023-01-04 17:09:47 +010098 rpmsg->error.msg[sizeof(rpmsg->error.msg) - 1] = '\0';
99 dev_warn(dev, "Msg: Error. type=%u, msg=\"%s\"",
100 rpmsg->error.type, rpmsg->error.msg);
Kristofer Jonsson074ef902023-01-23 13:05:36 +0100101
102 rproc_report_crash(rproc_get_by_child(dev), RPROC_FATAL_ERROR);
Jonny Svärd7c24c772021-01-14 19:53:17 +0100103 break;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200104 case ETHOSU_CORE_MSG_PING:
Kristofer Jonssond779a082023-01-04 17:09:47 +0100105 dev_info(dev, "Msg: Ping");
Jonny Svärd7c24c772021-01-14 19:53:17 +0100106 ret = ethosu_mailbox_pong(&edev->mailbox);
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200107 break;
108 case ETHOSU_CORE_MSG_PONG:
Kristofer Jonssond779a082023-01-04 17:09:47 +0100109 dev_info(dev, "Msg: Pong");
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200110 break;
111 case ETHOSU_CORE_MSG_INFERENCE_RSP:
Kristofer Jonssond779a082023-01-04 17:09:47 +0100112 if (length != sizeof(rpmsg->inf_rsp)) {
113 dev_warn(dev,
114 "Msg: Inference response of incorrect size. size=%u, expected=%zu", length,
115 sizeof(rpmsg->inf_rsp));
Jonny Svärd7c24c772021-01-14 19:53:17 +0100116 ret = -EBADMSG;
117 break;
118 }
119
Kristofer Jonssond779a082023-01-04 17:09:47 +0100120 dev_info(dev,
121 "Msg: Inference response. ofm_count=%u, status=%u",
122 rpmsg->inf_rsp.ofm_count, rpmsg->inf_rsp.status);
Kristofer Jonsson442fefb2022-03-17 17:15:52 +0100123
Kristofer Jonssonec477042023-01-20 13:38:13 +0100124 ethosu_inference_rsp(&edev->mailbox, rpmsg->header.msg_id,
Kristofer Jonssond779a082023-01-04 17:09:47 +0100125 &rpmsg->inf_rsp);
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200126 break;
Davide Grohmann7e8f5082022-03-23 12:48:45 +0100127 case ETHOSU_CORE_MSG_CANCEL_INFERENCE_RSP:
Kristofer Jonssond779a082023-01-04 17:09:47 +0100128 if (length != sizeof(rpmsg->cancel_rsp)) {
129 dev_warn(dev,
130 "Msg: Cancel Inference response of incorrect size. size=%u, expected=%zu", length,
131 sizeof(rpmsg->cancel_rsp));
Davide Grohmann7e8f5082022-03-23 12:48:45 +0100132 ret = -EBADMSG;
133 break;
134 }
135
Kristofer Jonssond779a082023-01-04 17:09:47 +0100136 dev_info(dev,
137 "Msg: Cancel Inference response. status=%u",
138 rpmsg->cancel_rsp.status);
Kristofer Jonssonec477042023-01-20 13:38:13 +0100139 ethosu_cancel_inference_rsp(&edev->mailbox,
140 rpmsg->header.msg_id,
Kristofer Jonssond779a082023-01-04 17:09:47 +0100141 &rpmsg->cancel_rsp);
Davide Grohmann7e8f5082022-03-23 12:48:45 +0100142 break;
Jonny Svärd7c24c772021-01-14 19:53:17 +0100143 case ETHOSU_CORE_MSG_VERSION_RSP:
Kristofer Jonssond779a082023-01-04 17:09:47 +0100144 if (length != sizeof(rpmsg->version_rsp)) {
145 dev_warn(dev,
146 "Msg: Version response of incorrect size. size=%u, expected=%zu", length,
147 sizeof(rpmsg->version_rsp));
Jonny Svärd7c24c772021-01-14 19:53:17 +0100148 ret = -EBADMSG;
149 break;
150 }
151
Kristofer Jonssond779a082023-01-04 17:09:47 +0100152 dev_info(dev, "Msg: Version response v%u.%u.%u",
153 rpmsg->version_rsp.major, rpmsg->version_rsp.minor,
154 rpmsg->version_rsp.patch);
Jonny Svärd7c24c772021-01-14 19:53:17 +0100155
156 /* Check major and minor version match, else return error */
Kristofer Jonssond779a082023-01-04 17:09:47 +0100157 if (rpmsg->version_rsp.major != ETHOSU_CORE_MSG_VERSION_MAJOR ||
158 rpmsg->version_rsp.minor != ETHOSU_CORE_MSG_VERSION_MINOR) {
159 dev_warn(dev, "Msg: Version mismatch detected! ");
160 dev_warn(dev, "Local version: v%u.%u.%u",
Jonny Svärd7c24c772021-01-14 19:53:17 +0100161 ETHOSU_CORE_MSG_VERSION_MAJOR,
162 ETHOSU_CORE_MSG_VERSION_MINOR,
163 ETHOSU_CORE_MSG_VERSION_PATCH);
164 }
165
166 break;
Davide Grohmann35ce6c82021-06-01 15:03:51 +0200167 case ETHOSU_CORE_MSG_CAPABILITIES_RSP:
Kristofer Jonssond779a082023-01-04 17:09:47 +0100168 if (length != sizeof(rpmsg->cap_rsp)) {
169 dev_warn(dev,
170 "Msg: Capabilities response of incorrect size. size=%u, expected=%zu", length,
171 sizeof(rpmsg->cap_rsp));
Davide Grohmann35ce6c82021-06-01 15:03:51 +0200172 ret = -EBADMSG;
173 break;
174 }
Jonny Svärd7c24c772021-01-14 19:53:17 +0100175
Kristofer Jonssond779a082023-01-04 17:09:47 +0100176 dev_info(dev,
177 "Msg: Capabilities response vs%hhu v%hhu.%hhu p%hhu av%hhu.%hhu.%hhu dv%hhu.%hhu.%hhu mcc%hhu csv%hhu cd%hhu",
178 rpmsg->cap_rsp.version_status,
179 rpmsg->cap_rsp.version_major,
180 rpmsg->cap_rsp.version_minor,
181 rpmsg->cap_rsp.product_major,
182 rpmsg->cap_rsp.arch_major_rev,
183 rpmsg->cap_rsp.arch_minor_rev,
184 rpmsg->cap_rsp.arch_patch_rev,
185 rpmsg->cap_rsp.driver_major_rev,
186 rpmsg->cap_rsp.driver_minor_rev,
187 rpmsg->cap_rsp.driver_patch_rev,
188 rpmsg->cap_rsp.macs_per_cc,
189 rpmsg->cap_rsp.cmd_stream_version,
190 rpmsg->cap_rsp.custom_dma);
Davide Grohmann35ce6c82021-06-01 15:03:51 +0200191
Kristofer Jonssonec477042023-01-20 13:38:13 +0100192 ethosu_capability_rsp(&edev->mailbox, rpmsg->header.msg_id,
Kristofer Jonssond779a082023-01-04 17:09:47 +0100193 &rpmsg->cap_rsp);
Davide Grohmann35ce6c82021-06-01 15:03:51 +0200194 break;
Kristofer Jonsson3c6a2602022-03-10 11:17:29 +0100195 case ETHOSU_CORE_MSG_NETWORK_INFO_RSP:
Kristofer Jonssond779a082023-01-04 17:09:47 +0100196 if (length != sizeof(rpmsg->net_info_rsp)) {
197 dev_warn(dev,
198 "Msg: Network info response of incorrect size. size=%u, expected=%zu", length,
199 sizeof(rpmsg->net_info_rsp));
Kristofer Jonsson3c6a2602022-03-10 11:17:29 +0100200 ret = -EBADMSG;
201 break;
202 }
203
Kristofer Jonssond779a082023-01-04 17:09:47 +0100204 dev_info(dev,
205 "Msg: Network info response. status=%u",
206 rpmsg->net_info_rsp.status);
Kristofer Jonsson3c6a2602022-03-10 11:17:29 +0100207
Kristofer Jonssonec477042023-01-20 13:38:13 +0100208 ethosu_network_info_rsp(&edev->mailbox,
209 rpmsg->header.msg_id,
Kristofer Jonssond779a082023-01-04 17:09:47 +0100210 &rpmsg->net_info_rsp);
Kristofer Jonsson3c6a2602022-03-10 11:17:29 +0100211
212 break;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200213 default:
Jonny Svärd7c24c772021-01-14 19:53:17 +0100214 /* This should not happen due to version checks */
Kristofer Jonssond779a082023-01-04 17:09:47 +0100215 dev_warn(dev, "Msg: Protocol error. type=%u",
216 rpmsg->header.type);
Jonny Svärd7c24c772021-01-14 19:53:17 +0100217 ret = -EPROTO;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200218 break;
219 }
220
221 return ret;
222}
223
224static int ethosu_open(struct inode *inode,
225 struct file *file)
226{
Kristofer Jonssonec477042023-01-20 13:38:13 +0100227 struct cdev *cdev = inode->i_cdev;
228 struct ethosu_device *edev = container_of(cdev, struct ethosu_device,
229 cdev);
230 struct rpmsg_device *rpdev = edev->rpdev;
Kristofer Jonsson074ef902023-01-23 13:05:36 +0100231 struct device *dev = &edev->dev;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200232
Kristofer Jonssonec477042023-01-20 13:38:13 +0100233 dev_info(dev, "Device open. file=0x%pK", file);
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200234
Kristofer Jonssonec477042023-01-20 13:38:13 +0100235 file->private_data = rpdev;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200236
237 return nonseekable_open(inode, file);
238}
239
240static long ethosu_ioctl(struct file *file,
241 unsigned int cmd,
242 unsigned long arg)
243{
Kristofer Jonssonec477042023-01-20 13:38:13 +0100244 struct rpmsg_device *rpdev = file->private_data;
Kristofer Jonsson074ef902023-01-23 13:05:36 +0100245 struct ethosu_device *edev = dev_get_drvdata(&rpdev->dev);
246 struct device *dev = &edev->dev;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200247 void __user *udata = (void __user *)arg;
248 int ret = -EINVAL;
249
Kristofer Jonssonec477042023-01-20 13:38:13 +0100250 ret = device_lock_interruptible(dev);
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200251 if (ret)
252 return ret;
253
Kristofer Jonssonec477042023-01-20 13:38:13 +0100254 dev_info(dev, "Device ioctl. file=0x%pK, cmd=0x%x, arg=0x%lx",
Kristofer Jonsson53fd03d2022-06-21 16:58:45 +0200255 file, cmd, arg);
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200256
257 switch (cmd) {
Jonny Svärd7c24c772021-01-14 19:53:17 +0100258 case ETHOSU_IOCTL_VERSION_REQ:
Kristofer Jonssonec477042023-01-20 13:38:13 +0100259 dev_info(dev, "Device ioctl: Send version request");
Jonny Svärd7c24c772021-01-14 19:53:17 +0100260 ret = ethosu_mailbox_version_request(&edev->mailbox);
261 break;
Davide Grohmann32660f92022-04-27 16:49:07 +0200262 case ETHOSU_IOCTL_CAPABILITIES_REQ: {
263 struct ethosu_uapi_device_capabilities uapi;
Kristofer Jonsson53fd03d2022-06-21 16:58:45 +0200264
Kristofer Jonssonec477042023-01-20 13:38:13 +0100265 dev_info(dev,
Kristofer Jonssond779a082023-01-04 17:09:47 +0100266 "Device ioctl: Send capabilities request");
Kristofer Jonsson53fd03d2022-06-21 16:58:45 +0200267
Kristofer Jonssonec477042023-01-20 13:38:13 +0100268 ret = ethosu_capabilities_request(dev, &edev->mailbox, &uapi);
Davide Grohmann32660f92022-04-27 16:49:07 +0200269 if (ret)
270 break;
271
272 ret = copy_to_user(udata, &uapi, sizeof(uapi)) ? -EFAULT : 0;
Davide Grohmann35ce6c82021-06-01 15:03:51 +0200273 break;
Davide Grohmann32660f92022-04-27 16:49:07 +0200274 }
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200275 case ETHOSU_IOCTL_PING: {
Kristofer Jonssonec477042023-01-20 13:38:13 +0100276 dev_info(dev, "Device ioctl: Send ping");
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200277 ret = ethosu_mailbox_ping(&edev->mailbox);
278 break;
279 }
280 case ETHOSU_IOCTL_BUFFER_CREATE: {
281 struct ethosu_uapi_buffer_create uapi;
282
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200283 if (copy_from_user(&uapi, udata, sizeof(uapi)))
284 break;
285
Kristofer Jonssonec477042023-01-20 13:38:13 +0100286 dev_info(dev,
Kristofer Jonssond779a082023-01-04 17:09:47 +0100287 "Device ioctl: Buffer create. capacity=%u",
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200288 uapi.capacity);
289
Kristofer Jonssonec477042023-01-20 13:38:13 +0100290 ret = ethosu_buffer_create(dev, uapi.capacity);
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200291 break;
292 }
293 case ETHOSU_IOCTL_NETWORK_CREATE: {
294 struct ethosu_uapi_network_create uapi;
295
296 if (copy_from_user(&uapi, udata, sizeof(uapi)))
297 break;
298
Kristofer Jonssonec477042023-01-20 13:38:13 +0100299 dev_info(dev,
Kristofer Jonssond779a082023-01-04 17:09:47 +0100300 "Device ioctl: Network create. type=%u, fd/index=%u",
Kristofer Jonsson53fd03d2022-06-21 16:58:45 +0200301 uapi.type, uapi.fd);
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200302
Kristofer Jonssonec477042023-01-20 13:38:13 +0100303 ret = ethosu_network_create(dev, &edev->mailbox, &uapi);
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200304 break;
305 }
306 default: {
Kristofer Jonssonec477042023-01-20 13:38:13 +0100307 dev_err(dev, "Invalid ioctl. cmd=%u, arg=%lu",
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200308 cmd, arg);
309 break;
310 }
311 }
312
Kristofer Jonssonec477042023-01-20 13:38:13 +0100313 device_unlock(dev);
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200314
315 return ret;
316}
317
Kristofer Jonssond779a082023-01-04 17:09:47 +0100318static struct rpmsg_endpoint *ethosu_create_ept(struct rpmsg_device *rpdev)
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200319{
Kristofer Jonssond779a082023-01-04 17:09:47 +0100320 struct device *dev = &rpdev->dev;
321 struct rpmsg_channel_info info;
322 struct rpmsg_endpoint *ept;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200323
Kristofer Jonssond779a082023-01-04 17:09:47 +0100324 /* Create rpmsg endpoint */
325 strncpy(info.name, rpdev->id.name, sizeof(info.name));
326 info.src = 0;
327 info.dst = rpdev->dst;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200328
Kristofer Jonssond779a082023-01-04 17:09:47 +0100329 dev_info(dev, "Creating rpmsg endpoint. name=%s, src=%u, dst=%u",
330 info.name, info.src, info.dst);
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200331
Kristofer Jonssonec477042023-01-20 13:38:13 +0100332 ept = rpmsg_create_ept(rpdev, ethosu_handle_rpmsg, NULL, info);
Kristofer Jonssond779a082023-01-04 17:09:47 +0100333 if (!ept) {
334 dev_err(&rpdev->dev, "Failed to create endpoint");
335
336 return ERR_PTR(-EINVAL);
337 }
338
339 return ept;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200340}
341
Kristofer Jonssonec477042023-01-20 13:38:13 +0100342static const struct file_operations fops = {
343 .owner = THIS_MODULE,
344 .open = &ethosu_open,
345 .unlocked_ioctl = &ethosu_ioctl,
346#ifdef CONFIG_COMPAT
347 .compat_ioctl = &ethosu_ioctl,
348#endif
349};
350
Kristofer Jonsson074ef902023-01-23 13:05:36 +0100351static void ethosu_dev_release(struct device *dev)
352{
353 struct ethosu_device *edev = dev_get_drvdata(dev);
354
355 dev_info(dev, "%s", __FUNCTION__);
356
357 clear_bit(MINOR(edev->cdev.dev), minors);
358
359 ethosu_mailbox_deinit(&edev->mailbox);
360 device_destroy(edev->class, edev->cdev.dev);
361 kfree(edev);
362}
363
364static int ethosu_device_register(struct device *dev,
365 struct device *parent,
366 void *drvdata,
367 dev_t devt)
368{
369 struct rproc *rproc = rproc_get_by_child(parent);
370 int ret;
371
372 dev->parent = parent;
373 dev->release = ethosu_dev_release;
374 dev_set_drvdata(dev, drvdata);
375
376 ret = dev_set_name(dev, "ethosu%d", MINOR(devt));
377 if (ret) {
378 dev_err(parent, "Failed to set device name. ret=%d", ret);
379
380 return ret;
381 }
382
383 /* Inherit DMA settings for rproc device */
384 ret = of_reserved_mem_device_init_by_idx(dev,
385 rproc->dev.parent->of_node, 0);
386 if (ret) {
387 dev_err(parent, "Failed to initialize reserved memory. ret=%d",
388 ret);
389
390 return ret;
391 }
392
Mikael Olsson099d90c2023-05-02 10:39:22 +0200393 /* Set mask for coherent DMA addressing */
394 ret = dma_set_coherent_mask(dev, DMA_BIT_MASK(DMA_ADDR_BITS));
395 if (ret) {
396 dev_err(parent, "Failed to set coherent DMA mask. ret=%d", ret);
397
398 return ret;
399 }
400
Kristofer Jonsson074ef902023-01-23 13:05:36 +0100401 ret = device_register(dev);
402 if (ret) {
403 dev_err(parent, "Failed to register device. ret=%d", ret);
404
405 return ret;
406 }
407
408 return 0;
409}
410
Kristofer Jonssonec477042023-01-20 13:38:13 +0100411int ethosu_dev_init(struct rpmsg_device *rpdev,
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200412 struct class *class,
Kristofer Jonssond779a082023-01-04 17:09:47 +0100413 dev_t devt)
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200414{
Kristofer Jonssonec477042023-01-20 13:38:13 +0100415 struct device *dev = &rpdev->dev;
416 struct ethosu_device *edev;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200417 struct device *sysdev;
Kristofer Jonsson074ef902023-01-23 13:05:36 +0100418 int minor;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200419 int ret;
420
Kristofer Jonssonec477042023-01-20 13:38:13 +0100421 dev_info(dev, "%s", __FUNCTION__);
422
Kristofer Jonsson074ef902023-01-23 13:05:36 +0100423 /* Reserve minor number for device node */
424 minor = find_first_zero_bit(minors, MINOR_COUNT);
425 if (minor >= MINOR_COUNT) {
426 dev_err(dev, "No more minor numbers.");
427
428 return -ENOMEM;
429 }
430
431 devt = MKDEV(MAJOR(devt), minor);
432
Kristofer Jonssonec477042023-01-20 13:38:13 +0100433 /* Allocate and create Ethos-U device */
Kristofer Jonsson074ef902023-01-23 13:05:36 +0100434 edev = kzalloc(sizeof(*edev), GFP_KERNEL);
Kristofer Jonssonec477042023-01-20 13:38:13 +0100435 if (!edev)
436 return -ENOMEM;
437
Kristofer Jonsson074ef902023-01-23 13:05:36 +0100438 dev_set_drvdata(&rpdev->dev, edev);
Kristofer Jonssonec477042023-01-20 13:38:13 +0100439
Kristofer Jonssond779a082023-01-04 17:09:47 +0100440 edev->rpdev = rpdev;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200441 edev->class = class;
Kristofer Jonsson074ef902023-01-23 13:05:36 +0100442
443 /* Create device object */
444 ret = ethosu_device_register(&edev->dev, &rpdev->dev, edev,
445 devt);
446 if (ret)
447 goto free_edev;
448
449 /* Continue with new device */
450 dev = &edev->dev;
Kristofer Jonsson442fefb2022-03-17 17:15:52 +0100451
Kristofer Jonssonec477042023-01-20 13:38:13 +0100452 /* Create RPMsg endpoint */
Kristofer Jonssond779a082023-01-04 17:09:47 +0100453 edev->ept = ethosu_create_ept(rpdev);
Kristofer Jonsson074ef902023-01-23 13:05:36 +0100454 if (IS_ERR(edev->ept)) {
455 ret = PTR_ERR(edev->ept);
456 goto device_unregister;
457 }
Kristofer Jonssond779a082023-01-04 17:09:47 +0100458
Kristofer Jonssonec477042023-01-20 13:38:13 +0100459 ret = ethosu_mailbox_init(&edev->mailbox, dev, edev->ept);
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200460 if (ret)
Kristofer Jonsson074ef902023-01-23 13:05:36 +0100461 goto device_unregister;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200462
Kristofer Jonssonec477042023-01-20 13:38:13 +0100463 /* Create device node */
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200464 cdev_init(&edev->cdev, &fops);
465 edev->cdev.owner = THIS_MODULE;
466
Kristofer Jonsson074ef902023-01-23 13:05:36 +0100467 cdev_set_parent(&edev->cdev, &dev->kobj);
468
469 ret = cdev_add(&edev->cdev, devt, 1);
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200470 if (ret) {
Kristofer Jonssonec477042023-01-20 13:38:13 +0100471 dev_err(dev, "Failed to add character device.");
Kristofer Jonsson4aec3762021-10-13 17:09:27 +0200472 goto deinit_mailbox;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200473 }
474
Kristofer Jonsson074ef902023-01-23 13:05:36 +0100475 sysdev = device_create(edev->class, NULL, devt, rpdev,
476 "ethosu%d", MINOR(devt));
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200477 if (IS_ERR(sysdev)) {
Kristofer Jonssonec477042023-01-20 13:38:13 +0100478 dev_err(dev, "Failed to create device.");
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200479 ret = PTR_ERR(sysdev);
480 goto del_cdev;
481 }
482
Kristofer Jonsson074ef902023-01-23 13:05:36 +0100483 set_bit(minor, minors);
484
Kristofer Jonssonec477042023-01-20 13:38:13 +0100485 dev_info(dev,
Kristofer Jonssond779a082023-01-04 17:09:47 +0100486 "Created Arm Ethos-U device. name=%s, major=%d, minor=%d",
Kristofer Jonsson074ef902023-01-23 13:05:36 +0100487 dev_name(sysdev), MAJOR(devt), MINOR(devt));
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200488
Kristofer Jonssond779a082023-01-04 17:09:47 +0100489 ethosu_mailbox_ping(&edev->mailbox);
490
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200491 return 0;
492
493del_cdev:
494 cdev_del(&edev->cdev);
495
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200496deinit_mailbox:
497 ethosu_mailbox_deinit(&edev->mailbox);
498
Kristofer Jonsson074ef902023-01-23 13:05:36 +0100499device_unregister:
500 device_unregister(dev);
501
502free_edev:
503 kfree(edev);
504
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200505 return ret;
506}
507
Kristofer Jonssonec477042023-01-20 13:38:13 +0100508void ethosu_dev_deinit(struct rpmsg_device *rpdev)
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200509{
Kristofer Jonssonec477042023-01-20 13:38:13 +0100510 struct device *dev = &rpdev->dev;
511 struct ethosu_device *edev = dev_get_drvdata(dev);
512
513 dev_info(dev, "%s", __FUNCTION__);
Kristofer Jonssond779a082023-01-04 17:09:47 +0100514
Kristofer Jonsson074ef902023-01-23 13:05:36 +0100515 ethosu_mailbox_fail(&edev->mailbox);
Kristofer Jonssond779a082023-01-04 17:09:47 +0100516 rpmsg_destroy_ept(edev->ept);
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200517 cdev_del(&edev->cdev);
Kristofer Jonsson074ef902023-01-23 13:05:36 +0100518 device_unregister(&edev->dev);
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200519}