blob: b889a7bd978a9d29f1f52447b08d149204246623 [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"
Mikael Olsson7c843dc2023-08-03 12:41:48 +020034#include "ethosu_version.h"
Kristofer Jonsson116a6352020-08-20 17:25:23 +020035#include "uapi/ethosu.h"
36
Mikael Olsson099d90c2023-05-02 10:39:22 +020037#include <linux/dma-mapping.h>
Kristofer Jonsson116a6352020-08-20 17:25:23 +020038#include <linux/errno.h>
39#include <linux/fs.h>
Kristofer Jonsson116a6352020-08-20 17:25:23 +020040#include <linux/io.h>
41#include <linux/of_reserved_mem.h>
Kristofer Jonssonec477042023-01-20 13:38:13 +010042#include <linux/remoteproc.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/****************************************************************************
Kristofer Jonsson074ef902023-01-23 13:05:36 +010047 * Defines
48 ****************************************************************************/
49
50#define MINOR_BASE 0 /* Minor version starts at 0 */
51#define MINOR_COUNT 64 /* Allocate minor versions */
52
Mikael Olsson099d90c2023-05-02 10:39:22 +020053#define DMA_ADDR_BITS 32 /* Number of address bits */
54
Kristofer Jonsson074ef902023-01-23 13:05:36 +010055/****************************************************************************
56 * Variables
57 ****************************************************************************/
58
59static DECLARE_BITMAP(minors, MINOR_COUNT);
60
61/****************************************************************************
Kristofer Jonsson116a6352020-08-20 17:25:23 +020062 * Functions
63 ****************************************************************************/
64
Jonny Svärd7c24c772021-01-14 19:53:17 +010065/* Incoming messages */
Kristofer Jonssonec477042023-01-20 13:38:13 +010066static int ethosu_handle_rpmsg(struct rpmsg_device *rpdev,
67 void *data,
68 int len,
69 void *priv,
70 u32 src)
Kristofer Jonsson116a6352020-08-20 17:25:23 +020071{
Kristofer Jonssond779a082023-01-04 17:09:47 +010072 struct ethosu_device *edev = dev_get_drvdata(&rpdev->dev);
Kristofer Jonsson074ef902023-01-23 13:05:36 +010073 struct device *dev = &edev->dev;
Mikael Olsson6fb238f2023-08-23 11:02:47 +020074 struct ethosu_mailbox *mbox = &edev->mailbox;
Kristofer Jonssond779a082023-01-04 17:09:47 +010075 struct ethosu_core_rpmsg *rpmsg = data;
76 int length = len - sizeof(rpmsg->header);
Mikael Olsson0483d662023-08-11 16:12:56 +020077 int ret = 0;
Kristofer Jonsson116a6352020-08-20 17:25:23 +020078
Mikael Olssonfd6b8dc2023-05-10 14:46:30 +020079 if (unlikely(rpmsg->header.magic != ETHOSU_CORE_MSG_MAGIC)) {
80 dev_warn(dev, "Msg: Error invalid message magic. magic=0x%08x",
81 rpmsg->header.magic);
82
83 return -EBADMSG;
84 }
85
Mikael Olsson5fcc28c2023-05-16 16:53:09 +020086 device_lock(dev);
87
Kristofer Jonssond779a082023-01-04 17:09:47 +010088 dev_info(dev,
89 "Msg: magic=0x%08x, type=%u, msg_id=%llu",
90 rpmsg->header.magic, rpmsg->header.type, rpmsg->header.msg_id);
Kristofer Jonsson116a6352020-08-20 17:25:23 +020091
Kristofer Jonssond779a082023-01-04 17:09:47 +010092 switch (rpmsg->header.type) {
Kristofer Jonsson074ef902023-01-23 13:05:36 +010093 case ETHOSU_CORE_MSG_ERR:
Kristofer Jonssond779a082023-01-04 17:09:47 +010094 if (length != sizeof(rpmsg->error)) {
95 dev_warn(dev,
96 "Msg: Error message of incorrect size. size=%u, expected=%zu", length,
97 sizeof(rpmsg->error));
Jonny Svärd7c24c772021-01-14 19:53:17 +010098 ret = -EBADMSG;
99 break;
100 }
101
Kristofer Jonssond779a082023-01-04 17:09:47 +0100102 rpmsg->error.msg[sizeof(rpmsg->error.msg) - 1] = '\0';
103 dev_warn(dev, "Msg: Error. type=%u, msg=\"%s\"",
104 rpmsg->error.type, rpmsg->error.msg);
Kristofer Jonsson074ef902023-01-23 13:05:36 +0100105
106 rproc_report_crash(rproc_get_by_child(dev), RPROC_FATAL_ERROR);
Jonny Svärd7c24c772021-01-14 19:53:17 +0100107 break;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200108 case ETHOSU_CORE_MSG_PING:
Kristofer Jonssond779a082023-01-04 17:09:47 +0100109 dev_info(dev, "Msg: Ping");
Mikael Olsson6fb238f2023-08-23 11:02:47 +0200110 ret = ethosu_mailbox_pong(mbox);
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200111 break;
112 case ETHOSU_CORE_MSG_PONG:
Kristofer Jonssond779a082023-01-04 17:09:47 +0100113 dev_info(dev, "Msg: Pong");
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200114 break;
115 case ETHOSU_CORE_MSG_INFERENCE_RSP:
Kristofer Jonssond779a082023-01-04 17:09:47 +0100116 if (length != sizeof(rpmsg->inf_rsp)) {
117 dev_warn(dev,
118 "Msg: Inference response of incorrect size. size=%u, expected=%zu", length,
119 sizeof(rpmsg->inf_rsp));
Jonny Svärd7c24c772021-01-14 19:53:17 +0100120 ret = -EBADMSG;
121 break;
122 }
123
Kristofer Jonssond779a082023-01-04 17:09:47 +0100124 dev_info(dev,
125 "Msg: Inference response. ofm_count=%u, status=%u",
126 rpmsg->inf_rsp.ofm_count, rpmsg->inf_rsp.status);
Kristofer Jonsson442fefb2022-03-17 17:15:52 +0100127
Mikael Olsson6fb238f2023-08-23 11:02:47 +0200128 ethosu_inference_rsp(mbox, rpmsg->header.msg_id,
Kristofer Jonssond779a082023-01-04 17:09:47 +0100129 &rpmsg->inf_rsp);
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200130 break;
Davide Grohmann7e8f5082022-03-23 12:48:45 +0100131 case ETHOSU_CORE_MSG_CANCEL_INFERENCE_RSP:
Kristofer Jonssond779a082023-01-04 17:09:47 +0100132 if (length != sizeof(rpmsg->cancel_rsp)) {
133 dev_warn(dev,
134 "Msg: Cancel Inference response of incorrect size. size=%u, expected=%zu", length,
135 sizeof(rpmsg->cancel_rsp));
Davide Grohmann7e8f5082022-03-23 12:48:45 +0100136 ret = -EBADMSG;
137 break;
138 }
139
Kristofer Jonssond779a082023-01-04 17:09:47 +0100140 dev_info(dev,
141 "Msg: Cancel Inference response. status=%u",
142 rpmsg->cancel_rsp.status);
Mikael Olsson6fb238f2023-08-23 11:02:47 +0200143 ethosu_cancel_inference_rsp(mbox,
Kristofer Jonssonec477042023-01-20 13:38:13 +0100144 rpmsg->header.msg_id,
Kristofer Jonssond779a082023-01-04 17:09:47 +0100145 &rpmsg->cancel_rsp);
Davide Grohmann7e8f5082022-03-23 12:48:45 +0100146 break;
Jonny Svärd7c24c772021-01-14 19:53:17 +0100147 case ETHOSU_CORE_MSG_VERSION_RSP:
Kristofer Jonssond779a082023-01-04 17:09:47 +0100148 if (length != sizeof(rpmsg->version_rsp)) {
149 dev_warn(dev,
Mikael Olsson7c843dc2023-08-03 12:41:48 +0200150 "Msg: Protocol version response of incorrect size. size=%u, expected=%zu", length,
Kristofer Jonssond779a082023-01-04 17:09:47 +0100151 sizeof(rpmsg->version_rsp));
Jonny Svärd7c24c772021-01-14 19:53:17 +0100152 ret = -EBADMSG;
153 break;
154 }
155
Mikael Olsson7c843dc2023-08-03 12:41:48 +0200156 dev_dbg(dev, "Msg: Protocol version response %u.%u.%u",
157 rpmsg->version_rsp.major, rpmsg->version_rsp.minor,
158 rpmsg->version_rsp.patch);
Jonny Svärd7c24c772021-01-14 19:53:17 +0100159
Mikael Olsson6fb238f2023-08-23 11:02:47 +0200160 ethosu_version_rsp(mbox, rpmsg->header.msg_id,
Mikael Olsson7c843dc2023-08-03 12:41:48 +0200161 &rpmsg->version_rsp);
Jonny Svärd7c24c772021-01-14 19:53:17 +0100162 break;
Davide Grohmann35ce6c82021-06-01 15:03:51 +0200163 case ETHOSU_CORE_MSG_CAPABILITIES_RSP:
Kristofer Jonssond779a082023-01-04 17:09:47 +0100164 if (length != sizeof(rpmsg->cap_rsp)) {
165 dev_warn(dev,
166 "Msg: Capabilities response of incorrect size. size=%u, expected=%zu", length,
167 sizeof(rpmsg->cap_rsp));
Davide Grohmann35ce6c82021-06-01 15:03:51 +0200168 ret = -EBADMSG;
169 break;
170 }
Jonny Svärd7c24c772021-01-14 19:53:17 +0100171
Kristofer Jonssond779a082023-01-04 17:09:47 +0100172 dev_info(dev,
173 "Msg: Capabilities response vs%hhu v%hhu.%hhu p%hhu av%hhu.%hhu.%hhu dv%hhu.%hhu.%hhu mcc%hhu csv%hhu cd%hhu",
174 rpmsg->cap_rsp.version_status,
175 rpmsg->cap_rsp.version_major,
176 rpmsg->cap_rsp.version_minor,
177 rpmsg->cap_rsp.product_major,
178 rpmsg->cap_rsp.arch_major_rev,
179 rpmsg->cap_rsp.arch_minor_rev,
180 rpmsg->cap_rsp.arch_patch_rev,
181 rpmsg->cap_rsp.driver_major_rev,
182 rpmsg->cap_rsp.driver_minor_rev,
183 rpmsg->cap_rsp.driver_patch_rev,
184 rpmsg->cap_rsp.macs_per_cc,
185 rpmsg->cap_rsp.cmd_stream_version,
186 rpmsg->cap_rsp.custom_dma);
Davide Grohmann35ce6c82021-06-01 15:03:51 +0200187
Mikael Olsson6fb238f2023-08-23 11:02:47 +0200188 ethosu_capability_rsp(mbox, rpmsg->header.msg_id,
Kristofer Jonssond779a082023-01-04 17:09:47 +0100189 &rpmsg->cap_rsp);
Davide Grohmann35ce6c82021-06-01 15:03:51 +0200190 break;
Kristofer Jonsson3c6a2602022-03-10 11:17:29 +0100191 case ETHOSU_CORE_MSG_NETWORK_INFO_RSP:
Kristofer Jonssond779a082023-01-04 17:09:47 +0100192 if (length != sizeof(rpmsg->net_info_rsp)) {
193 dev_warn(dev,
194 "Msg: Network info response of incorrect size. size=%u, expected=%zu", length,
195 sizeof(rpmsg->net_info_rsp));
Kristofer Jonsson3c6a2602022-03-10 11:17:29 +0100196 ret = -EBADMSG;
197 break;
198 }
199
Kristofer Jonssond779a082023-01-04 17:09:47 +0100200 dev_info(dev,
201 "Msg: Network info response. status=%u",
202 rpmsg->net_info_rsp.status);
Kristofer Jonsson3c6a2602022-03-10 11:17:29 +0100203
Mikael Olsson6fb238f2023-08-23 11:02:47 +0200204 ethosu_network_info_rsp(mbox,
Kristofer Jonssonec477042023-01-20 13:38:13 +0100205 rpmsg->header.msg_id,
Kristofer Jonssond779a082023-01-04 17:09:47 +0100206 &rpmsg->net_info_rsp);
Kristofer Jonsson3c6a2602022-03-10 11:17:29 +0100207
208 break;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200209 default:
Jonny Svärd7c24c772021-01-14 19:53:17 +0100210 /* This should not happen due to version checks */
Kristofer Jonssond779a082023-01-04 17:09:47 +0100211 dev_warn(dev, "Msg: Protocol error. type=%u",
212 rpmsg->header.type);
Jonny Svärd7c24c772021-01-14 19:53:17 +0100213 ret = -EPROTO;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200214 break;
215 }
216
Mikael Olsson5fcc28c2023-05-16 16:53:09 +0200217 device_unlock(dev);
218
Mikael Olsson6fb238f2023-08-23 11:02:47 +0200219 wake_up(&mbox->send_queue);
220
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200221 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;
Mikael Olsson891156d2023-08-24 13:20:31 +0200248 int ret;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200249
Kristofer Jonssonec477042023-01-20 13:38:13 +0100250 dev_info(dev, "Device ioctl. file=0x%pK, cmd=0x%x, arg=0x%lx",
Kristofer Jonsson53fd03d2022-06-21 16:58:45 +0200251 file, cmd, arg);
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200252
253 switch (cmd) {
Mikael Olssonf1cfe192023-06-12 15:00:41 +0200254 case ETHOSU_IOCTL_DRIVER_VERSION_GET: {
255 const struct ethosu_uapi_kernel_driver_version version = {
256 .major = ETHOSU_KERNEL_DRIVER_VERSION_MAJOR,
257 .minor = ETHOSU_KERNEL_DRIVER_VERSION_MINOR,
258 .patch = ETHOSU_KERNEL_DRIVER_VERSION_PATCH,
259 };
260
261 ret = copy_to_user(udata, &version,
262 sizeof(version)) ? -EFAULT : 0;
263 break;
264 }
Davide Grohmann32660f92022-04-27 16:49:07 +0200265 case ETHOSU_IOCTL_CAPABILITIES_REQ: {
Mikael Olsson252ed6a2023-05-29 18:07:55 +0200266 dev_info(dev, "Device ioctl: Capabilities request");
Kristofer Jonsson53fd03d2022-06-21 16:58:45 +0200267
Mikael Olsson252ed6a2023-05-29 18:07:55 +0200268 ret = copy_to_user(udata, &edev->capabilities,
269 sizeof(edev->capabilities)) ? -EFAULT : 0;
Davide Grohmann35ce6c82021-06-01 15:03:51 +0200270 break;
Davide Grohmann32660f92022-04-27 16:49:07 +0200271 }
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200272 case ETHOSU_IOCTL_PING: {
Mikael Olsson18257602023-08-23 11:02:20 +0200273 ret = device_lock_interruptible(dev);
274 if (ret)
275 return ret;
276
Kristofer Jonssonec477042023-01-20 13:38:13 +0100277 dev_info(dev, "Device ioctl: Send ping");
Mikael Olsson18257602023-08-23 11:02:20 +0200278
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200279 ret = ethosu_mailbox_ping(&edev->mailbox);
Mikael Olsson18257602023-08-23 11:02:20 +0200280
281 device_unlock(dev);
282
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200283 break;
284 }
285 case ETHOSU_IOCTL_BUFFER_CREATE: {
286 struct ethosu_uapi_buffer_create uapi;
287
Mikael Olsson891156d2023-08-24 13:20:31 +0200288 if (copy_from_user(&uapi, udata, sizeof(uapi))) {
289 ret = -EFAULT;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200290 break;
Mikael Olsson891156d2023-08-24 13:20:31 +0200291 }
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200292
Mikael Olsson18257602023-08-23 11:02:20 +0200293 ret = device_lock_interruptible(dev);
294 if (ret)
295 return ret;
296
Kristofer Jonssonec477042023-01-20 13:38:13 +0100297 dev_info(dev,
Kristofer Jonssond779a082023-01-04 17:09:47 +0100298 "Device ioctl: Buffer create. capacity=%u",
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200299 uapi.capacity);
300
Kristofer Jonssonec477042023-01-20 13:38:13 +0100301 ret = ethosu_buffer_create(dev, uapi.capacity);
Mikael Olsson18257602023-08-23 11:02:20 +0200302
303 device_unlock(dev);
304
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200305 break;
306 }
307 case ETHOSU_IOCTL_NETWORK_CREATE: {
308 struct ethosu_uapi_network_create uapi;
309
Mikael Olsson891156d2023-08-24 13:20:31 +0200310 if (copy_from_user(&uapi, udata, sizeof(uapi))) {
311 ret = -EFAULT;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200312 break;
Mikael Olsson891156d2023-08-24 13:20:31 +0200313 }
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200314
Mikael Olsson18257602023-08-23 11:02:20 +0200315 ret = device_lock_interruptible(dev);
316 if (ret)
317 return ret;
318
Kristofer Jonssonec477042023-01-20 13:38:13 +0100319 dev_info(dev,
Kristofer Jonssond779a082023-01-04 17:09:47 +0100320 "Device ioctl: Network create. type=%u, fd/index=%u",
Kristofer Jonsson53fd03d2022-06-21 16:58:45 +0200321 uapi.type, uapi.fd);
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200322
Kristofer Jonssonec477042023-01-20 13:38:13 +0100323 ret = ethosu_network_create(dev, &edev->mailbox, &uapi);
Mikael Olsson18257602023-08-23 11:02:20 +0200324
325 device_unlock(dev);
326
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200327 break;
328 }
329 default: {
Kristofer Jonssonec477042023-01-20 13:38:13 +0100330 dev_err(dev, "Invalid ioctl. cmd=%u, arg=%lu",
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200331 cmd, arg);
Mikael Olsson891156d2023-08-24 13:20:31 +0200332 ret = -ENOIOCTLCMD;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200333 break;
334 }
335 }
336
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200337 return ret;
338}
339
Kristofer Jonssond779a082023-01-04 17:09:47 +0100340static struct rpmsg_endpoint *ethosu_create_ept(struct rpmsg_device *rpdev)
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200341{
Kristofer Jonssond779a082023-01-04 17:09:47 +0100342 struct device *dev = &rpdev->dev;
343 struct rpmsg_channel_info info;
344 struct rpmsg_endpoint *ept;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200345
Kristofer Jonssond779a082023-01-04 17:09:47 +0100346 /* Create rpmsg endpoint */
347 strncpy(info.name, rpdev->id.name, sizeof(info.name));
348 info.src = 0;
349 info.dst = rpdev->dst;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200350
Kristofer Jonssond779a082023-01-04 17:09:47 +0100351 dev_info(dev, "Creating rpmsg endpoint. name=%s, src=%u, dst=%u",
352 info.name, info.src, info.dst);
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200353
Kristofer Jonssonec477042023-01-20 13:38:13 +0100354 ept = rpmsg_create_ept(rpdev, ethosu_handle_rpmsg, NULL, info);
Kristofer Jonssond779a082023-01-04 17:09:47 +0100355 if (!ept) {
356 dev_err(&rpdev->dev, "Failed to create endpoint");
357
358 return ERR_PTR(-EINVAL);
359 }
360
361 return ept;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200362}
363
Kristofer Jonssonec477042023-01-20 13:38:13 +0100364static const struct file_operations fops = {
365 .owner = THIS_MODULE,
366 .open = &ethosu_open,
367 .unlocked_ioctl = &ethosu_ioctl,
368#ifdef CONFIG_COMPAT
369 .compat_ioctl = &ethosu_ioctl,
370#endif
371};
372
Kristofer Jonsson074ef902023-01-23 13:05:36 +0100373static void ethosu_dev_release(struct device *dev)
374{
375 struct ethosu_device *edev = dev_get_drvdata(dev);
376
377 dev_info(dev, "%s", __FUNCTION__);
378
379 clear_bit(MINOR(edev->cdev.dev), minors);
380
381 ethosu_mailbox_deinit(&edev->mailbox);
382 device_destroy(edev->class, edev->cdev.dev);
383 kfree(edev);
384}
385
386static int ethosu_device_register(struct device *dev,
387 struct device *parent,
388 void *drvdata,
389 dev_t devt)
390{
391 struct rproc *rproc = rproc_get_by_child(parent);
392 int ret;
393
394 dev->parent = parent;
395 dev->release = ethosu_dev_release;
396 dev_set_drvdata(dev, drvdata);
397
398 ret = dev_set_name(dev, "ethosu%d", MINOR(devt));
399 if (ret) {
400 dev_err(parent, "Failed to set device name. ret=%d", ret);
401
402 return ret;
403 }
404
405 /* Inherit DMA settings for rproc device */
406 ret = of_reserved_mem_device_init_by_idx(dev,
407 rproc->dev.parent->of_node, 0);
408 if (ret) {
409 dev_err(parent, "Failed to initialize reserved memory. ret=%d",
410 ret);
411
412 return ret;
413 }
414
Mikael Olsson099d90c2023-05-02 10:39:22 +0200415 /* Set mask for coherent DMA addressing */
416 ret = dma_set_coherent_mask(dev, DMA_BIT_MASK(DMA_ADDR_BITS));
417 if (ret) {
418 dev_err(parent, "Failed to set coherent DMA mask. ret=%d", ret);
419
420 return ret;
421 }
422
Kristofer Jonsson074ef902023-01-23 13:05:36 +0100423 ret = device_register(dev);
424 if (ret) {
425 dev_err(parent, "Failed to register device. ret=%d", ret);
426
427 return ret;
428 }
429
430 return 0;
431}
432
Kristofer Jonssonec477042023-01-20 13:38:13 +0100433int ethosu_dev_init(struct rpmsg_device *rpdev,
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200434 struct class *class,
Kristofer Jonssond779a082023-01-04 17:09:47 +0100435 dev_t devt)
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200436{
Kristofer Jonssonec477042023-01-20 13:38:13 +0100437 struct device *dev = &rpdev->dev;
438 struct ethosu_device *edev;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200439 struct device *sysdev;
Kristofer Jonsson074ef902023-01-23 13:05:36 +0100440 int minor;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200441 int ret;
442
Kristofer Jonssonec477042023-01-20 13:38:13 +0100443 dev_info(dev, "%s", __FUNCTION__);
444
Kristofer Jonsson074ef902023-01-23 13:05:36 +0100445 /* Reserve minor number for device node */
446 minor = find_first_zero_bit(minors, MINOR_COUNT);
447 if (minor >= MINOR_COUNT) {
448 dev_err(dev, "No more minor numbers.");
449
450 return -ENOMEM;
451 }
452
453 devt = MKDEV(MAJOR(devt), minor);
454
Kristofer Jonssonec477042023-01-20 13:38:13 +0100455 /* Allocate and create Ethos-U device */
Kristofer Jonsson074ef902023-01-23 13:05:36 +0100456 edev = kzalloc(sizeof(*edev), GFP_KERNEL);
Kristofer Jonssonec477042023-01-20 13:38:13 +0100457 if (!edev)
458 return -ENOMEM;
459
Kristofer Jonsson074ef902023-01-23 13:05:36 +0100460 dev_set_drvdata(&rpdev->dev, edev);
Kristofer Jonssonec477042023-01-20 13:38:13 +0100461
Kristofer Jonssond779a082023-01-04 17:09:47 +0100462 edev->rpdev = rpdev;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200463 edev->class = class;
Kristofer Jonsson074ef902023-01-23 13:05:36 +0100464
465 /* Create device object */
466 ret = ethosu_device_register(&edev->dev, &rpdev->dev, edev,
467 devt);
Mikael Olsson229e1252023-06-22 14:34:55 +0200468 if (ret) {
469 kfree(edev);
470
471 return ret;
472 }
Kristofer Jonsson074ef902023-01-23 13:05:36 +0100473
474 /* Continue with new device */
475 dev = &edev->dev;
Kristofer Jonsson442fefb2022-03-17 17:15:52 +0100476
Kristofer Jonssonec477042023-01-20 13:38:13 +0100477 /* Create RPMsg endpoint */
Kristofer Jonssond779a082023-01-04 17:09:47 +0100478 edev->ept = ethosu_create_ept(rpdev);
Kristofer Jonsson074ef902023-01-23 13:05:36 +0100479 if (IS_ERR(edev->ept)) {
480 ret = PTR_ERR(edev->ept);
481 goto device_unregister;
482 }
Kristofer Jonssond779a082023-01-04 17:09:47 +0100483
Kristofer Jonssonec477042023-01-20 13:38:13 +0100484 ret = ethosu_mailbox_init(&edev->mailbox, dev, edev->ept);
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200485 if (ret)
Mikael Olsson08c42f52023-06-22 15:13:35 +0200486 goto free_rpmsg_ept;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200487
Mikael Olsson7c843dc2023-08-03 12:41:48 +0200488 device_lock(dev);
489 ret = ethosu_version_check_request(dev, &edev->mailbox);
490 device_unlock(dev);
491 if (ret) {
492 dev_err(dev, "Protocol version check failed: %d", ret);
493 goto deinit_mailbox;
494 }
Mikael Olsson252ed6a2023-05-29 18:07:55 +0200495
496 device_lock(dev);
497 ret = ethosu_capabilities_request(dev, &edev->mailbox,
498 &edev->capabilities);
499 device_unlock(dev);
500 if (ret) {
501 dev_err(dev, "Failed to get device capabilities: %d", ret);
502 goto deinit_mailbox;
503 }
504
Kristofer Jonssonec477042023-01-20 13:38:13 +0100505 /* Create device node */
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200506 cdev_init(&edev->cdev, &fops);
507 edev->cdev.owner = THIS_MODULE;
508
Kristofer Jonsson074ef902023-01-23 13:05:36 +0100509 cdev_set_parent(&edev->cdev, &dev->kobj);
510
511 ret = cdev_add(&edev->cdev, devt, 1);
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200512 if (ret) {
Kristofer Jonssonec477042023-01-20 13:38:13 +0100513 dev_err(dev, "Failed to add character device.");
Kristofer Jonsson4aec3762021-10-13 17:09:27 +0200514 goto deinit_mailbox;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200515 }
516
Kristofer Jonsson074ef902023-01-23 13:05:36 +0100517 sysdev = device_create(edev->class, NULL, devt, rpdev,
518 "ethosu%d", MINOR(devt));
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200519 if (IS_ERR(sysdev)) {
Kristofer Jonssonec477042023-01-20 13:38:13 +0100520 dev_err(dev, "Failed to create device.");
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200521 ret = PTR_ERR(sysdev);
522 goto del_cdev;
523 }
524
Kristofer Jonsson074ef902023-01-23 13:05:36 +0100525 set_bit(minor, minors);
526
Kristofer Jonssonec477042023-01-20 13:38:13 +0100527 dev_info(dev,
Kristofer Jonssond779a082023-01-04 17:09:47 +0100528 "Created Arm Ethos-U device. name=%s, major=%d, minor=%d",
Kristofer Jonsson074ef902023-01-23 13:05:36 +0100529 dev_name(sysdev), MAJOR(devt), MINOR(devt));
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200530
531 return 0;
532
533del_cdev:
534 cdev_del(&edev->cdev);
535
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200536deinit_mailbox:
537 ethosu_mailbox_deinit(&edev->mailbox);
538
Mikael Olsson08c42f52023-06-22 15:13:35 +0200539free_rpmsg_ept:
540 rpmsg_destroy_ept(edev->ept);
541
Kristofer Jonsson074ef902023-01-23 13:05:36 +0100542device_unregister:
543 device_unregister(dev);
544
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200545 return ret;
546}
547
Kristofer Jonssonec477042023-01-20 13:38:13 +0100548void ethosu_dev_deinit(struct rpmsg_device *rpdev)
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200549{
Kristofer Jonssonec477042023-01-20 13:38:13 +0100550 struct device *dev = &rpdev->dev;
551 struct ethosu_device *edev = dev_get_drvdata(dev);
552
553 dev_info(dev, "%s", __FUNCTION__);
Kristofer Jonssond779a082023-01-04 17:09:47 +0100554
Mikael Olsson529cfad2023-06-14 17:14:14 +0200555 device_lock(&edev->dev);
Kristofer Jonsson074ef902023-01-23 13:05:36 +0100556 ethosu_mailbox_fail(&edev->mailbox);
Mikael Olsson529cfad2023-06-14 17:14:14 +0200557 device_unlock(&edev->dev);
558
Kristofer Jonssond779a082023-01-04 17:09:47 +0100559 rpmsg_destroy_ept(edev->ept);
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200560 cdev_del(&edev->cdev);
Kristofer Jonsson074ef902023-01-23 13:05:36 +0100561 device_unregister(&edev->dev);
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200562}