blob: 18f2789234a96449fd9fd19fefefa61fdea74827 [file] [log] [blame]
Per Åstrand2cd53972021-04-12 13:46:04 +02001/*
Mikael Olsson4bfd9872024-04-16 16:36:47 +02002 * SPDX-FileCopyrightText: Copyright 2021-2024 Arm Limited and/or its affiliates <open-source-office@arm.com>
Mikael Olsson9d0ea8b2023-06-05 16:16:36 +02003 * SPDX-License-Identifier: GPL-2.0-only
Per Åstrand2cd53972021-04-12 13:46:04 +02004 *
5 * This program is free software and is provided to you under the terms of the
6 * GNU General Public License version 2 as published by the Free Software
7 * Foundation, and any use by you of this program is subject to the terms
8 * of such GNU licence.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, you can access it online at
17 * http://www.gnu.org/licenses/gpl-2.0.html.
Per Åstrand2cd53972021-04-12 13:46:04 +020018 */
Mikael Olsson9d0ea8b2023-06-05 16:16:36 +020019
Kristofer Jonssona70bfde2023-01-12 10:00:03 +010020#include <linux/dma-mapping.h>
Mikael Olsson9d0ea8b2023-06-05 16:16:36 +020021#include <linux/dma-direct.h>
Per Åstrand2cd53972021-04-12 13:46:04 +020022#include <linux/firmware.h>
23#include <linux/io.h>
Kristofer Jonssona70bfde2023-01-12 10:00:03 +010024#include <linux/irqreturn.h>
Per Åstrand2cd53972021-04-12 13:46:04 +020025#include <linux/kernel.h>
Kristofer Jonssona70bfde2023-01-12 10:00:03 +010026#include <linux/mailbox_client.h>
Per Åstrand2cd53972021-04-12 13:46:04 +020027#include <linux/module.h>
28#include <linux/of.h>
29#include <linux/of_address.h>
30#include <linux/of_device.h>
Kristofer Jonssona70bfde2023-01-12 10:00:03 +010031#include <linux/of_reserved_mem.h>
Per Åstrand2cd53972021-04-12 13:46:04 +020032#include <linux/platform_device.h>
33#include <linux/remoteproc.h>
34#include <linux/reset.h>
Nir Ekhauz48239212021-11-23 10:28:34 +020035#include <linux/version.h>
Kristofer Jonssona70bfde2023-01-12 10:00:03 +010036#include <linux/workqueue.h>
37
38/****************************************************************************
39 * Defines
40 ****************************************************************************/
41
42#define DMA_ADDR_BITS 32 /* Number of address bits */
Per Åstrand2cd53972021-04-12 13:46:04 +020043
44#define ETHOSU_RPROC_DRIVER_VERSION "0.0.1"
45
46#define DEFAULT_FW_FILE "arm-ethos-u65.fw"
Kristofer Jonssona70bfde2023-01-12 10:00:03 +010047#define DEFAULT_AUTO_BOOT false
Per Åstrand2cd53972021-04-12 13:46:04 +020048
49/* firmware naming module parameter */
50static char fw_filename_param[256] = DEFAULT_FW_FILE;
Kristofer Jonssona70bfde2023-01-12 10:00:03 +010051
Per Åstrand2cd53972021-04-12 13:46:04 +020052/* As the remoteproc is setup at probe, just allow the filename readonly */
53module_param_string(filename, fw_filename_param, sizeof(fw_filename_param),
54 0444);
55MODULE_PARM_DESC(filename,
56 "Filename for firmware image for Ethos-U remoteproc");
57
58static bool auto_boot = DEFAULT_AUTO_BOOT;
Kristofer Jonssona70bfde2023-01-12 10:00:03 +010059module_param(auto_boot, bool, 0);
Per Åstrand2cd53972021-04-12 13:46:04 +020060MODULE_PARM_DESC(auto_boot, "Set to one to auto boot at load.");
61
Mikael Olsson9d0ea8b2023-06-05 16:16:36 +020062#define RSC_MAPPING RSC_VENDOR_START + 1
63
64/**
65 * struct fw_rsc_map_range - memory map range
66 * @da: Start device address of the memory address range
67 * @pa: Start physical address of the memory address range
68 * @len: length of memory address range
69 *
70 * Memory range to translate between physical and device addresses.
71 */
72struct fw_rsc_map_range {
73 uint32_t da;
74 uint32_t pa;
75 uint32_t len;
76} __packed;
77
78/**
79 * struct fw_rsc_mapping - memory map for address translation
80 * @num_ranges: Number of ranges in the memory map
81 * @range: Array of the ranges in the memory map
82 *
83 * This resource entry requests the host to provide information for how to
84 * translate between physical and device addresses.
85 */
86struct fw_rsc_mapping {
87 uint8_t num_ranges;
88 struct fw_rsc_map_range range[0];
89} __packed;
90
Per Åstrand2cd53972021-04-12 13:46:04 +020091struct ethosu_rproc {
Kristofer Jonssona70bfde2023-01-12 10:00:03 +010092 struct device *dev;
93 struct reset_control *rstc;
94 struct mbox_client mbox_client;
95 struct mbox_chan *ch_rx;
96 struct mbox_chan *ch_tx;
97 struct workqueue_struct *wq;
98 struct work_struct work;
Per Åstrand2cd53972021-04-12 13:46:04 +020099};
100
Kristofer Jonssona70bfde2023-01-12 10:00:03 +0100101/* declaration is in remoteproc_internal.h */
102extern irqreturn_t rproc_vq_interrupt(struct rproc *rproc,
103 int vq_id);
Per Åstrand2cd53972021-04-12 13:46:04 +0200104
Kristofer Jonssona70bfde2023-01-12 10:00:03 +0100105static void ethosu_mbox_bottom(struct work_struct *work)
106{
107 struct ethosu_rproc *erproc = container_of(
108 work, struct ethosu_rproc, work);
109 struct rproc *rproc = dev_get_drvdata(erproc->dev);
Per Åstrand2cd53972021-04-12 13:46:04 +0200110
Kristofer Jonssona70bfde2023-01-12 10:00:03 +0100111 dev_dbg(&rproc->dev, "Handle interrupt");
112
113 rproc_vq_interrupt(rproc, 0);
114}
115
116static void ethosu_mbox_top(struct mbox_client *client,
117 void *message)
118{
119 struct ethosu_rproc *erproc = container_of(
120 client, struct ethosu_rproc, mbox_client);
121
122 queue_work(erproc->wq, &erproc->work);
123}
124
Mikael Olsson9f176ba2023-11-10 15:15:34 +0100125static int ethosu_mem_alloc(struct rproc *rproc,
126 struct rproc_mem_entry *mem)
127{
128 struct device *dev = rproc->dev.parent;
129 void *va;
130
Mikael Olsson4bfd9872024-04-16 16:36:47 +0200131 if (mem->is_iomem)
132 va = (__force void *)devm_ioremap(dev, mem->dma, mem->len);
133 else
134 va = devm_memremap(dev, mem->dma, mem->len, MEMREMAP_WC);
135
Mikael Olsson9f176ba2023-11-10 15:15:34 +0100136 if (IS_ERR_OR_NULL(va)) {
137 dev_err(dev, "Failed to remap address. pa=%pa, len=%zu",
138 &mem->dma,
139 mem->len);
140
141 return -ENOMEM;
142 }
143
144 mem->va = va;
Mikael Olsson9f176ba2023-11-10 15:15:34 +0100145
146 return 0;
147}
148
149static int ethosu_mem_release(struct rproc *rproc,
150 struct rproc_mem_entry *mem)
151{
152 struct device *dev = rproc->dev.parent;
153
Mikael Olsson4bfd9872024-04-16 16:36:47 +0200154 if (!mem->va) {
155 dev_warn(dev,
156 "Memory release. No mapping for memory %s pa=%p len=%zu",
157 mem->name, &mem->dma, mem->len);
158 goto done;
159 }
160
161 if (mem->is_iomem)
Mikael Olsson9f176ba2023-11-10 15:15:34 +0100162 devm_iounmap(dev, (__force __iomem void *)mem->va);
Mikael Olsson4bfd9872024-04-16 16:36:47 +0200163 else
164 devm_memunmap(dev, mem->va);
165
166done:
Mikael Olsson9f176ba2023-11-10 15:15:34 +0100167
168 return 0;
169}
170
Kristofer Jonssona70bfde2023-01-12 10:00:03 +0100171static int ethosu_add_carveout(struct rproc *rproc,
172 const phys_addr_t pa,
173 const size_t size,
Mikael Olsson4bfd9872024-04-16 16:36:47 +0200174 const char *name,
175 bool is_iomem)
Kristofer Jonssona70bfde2023-01-12 10:00:03 +0100176{
177 struct device *dev = rproc->dev.parent;
178 dma_addr_t da;
Kristofer Jonssona70bfde2023-01-12 10:00:03 +0100179 struct rproc_mem_entry *mem;
180
Mikael Olsson9d0ea8b2023-06-05 16:16:36 +0200181 da = translate_phys_to_dma(dev, pa);
182 dev_dbg(dev, "PA to DA. pa=0x%pa, da=0x%pad", &pa, &da);
183 if (da == DMA_MAPPING_ERROR) {
184 dev_err(dev, "No mapping found for PA. pa=%pa, size=%zu", &pa,
Kristofer Jonssona70bfde2023-01-12 10:00:03 +0100185 size);
186
187 return -ENOMEM;
188 }
189
Mikael Olsson9f176ba2023-11-10 15:15:34 +0100190 mem = rproc_mem_entry_init(dev, NULL, pa, size, da, ethosu_mem_alloc,
191 ethosu_mem_release, name);
Kristofer Jonssona70bfde2023-01-12 10:00:03 +0100192 if (!mem)
193 return -ENOMEM;
194
Mikael Olsson4bfd9872024-04-16 16:36:47 +0200195 mem->is_iomem = is_iomem;
196
Ledion Dajaedd25502023-10-17 09:15:32 +0200197 dev_dbg(dev, "Add carveout mapping. dma=%pad, da=%x, va=%p, len=%zu",
198 &mem->dma, mem->da, mem->va, mem->len);
Kristofer Jonssona70bfde2023-01-12 10:00:03 +0100199
200 rproc_add_carveout(rproc, mem);
201
202 return 0;
203}
204
205static int ethosu_rproc_prepare(struct rproc *rproc)
206{
207 struct device *dev = rproc->dev.parent;
208 struct device_node *np = dev->of_node;
209 struct of_phandle_iterator it;
210 struct resource res;
211 int i;
212 int ret;
213
Kristofer Jonssona70bfde2023-01-12 10:00:03 +0100214 /* Add carveout for each 'reg' device tree entry */
215 for (i = 0; of_address_to_resource(np, i, &res) == 0; i++) {
Ledion Dajaedd25502023-10-17 09:15:32 +0200216 dev_dbg(dev, "Found resource. start=%llx, size=%llx",
217 res.start, resource_size(&res));
Kristofer Jonssona70bfde2023-01-12 10:00:03 +0100218
219 ret = ethosu_add_carveout(rproc, res.start,
Mikael Olsson4bfd9872024-04-16 16:36:47 +0200220 resource_size(&res), res.name,
221 !strncmp(res.name, "rom", 3));
Kristofer Jonssona70bfde2023-01-12 10:00:03 +0100222 if (ret)
223 return ret;
224 }
225
226 of_phandle_iterator_init(&it, np, "memory-region", NULL, 0);
227 while (of_phandle_iterator_next(&it) == 0) {
228 struct reserved_mem *res_mem = of_reserved_mem_lookup(it.node);
229
230 if (!res_mem) {
231 dev_err(dev, "Failed to look up memory region. node=%p",
232 it.node);
233
234 return -EINVAL;
235 }
236
Ledion Dajaedd25502023-10-17 09:15:32 +0200237 dev_dbg(dev,
238 "Found memory region. pa=%llx, size=%llu, name=%s",
239 res_mem->base, res_mem->size, it.node->name);
Kristofer Jonssona70bfde2023-01-12 10:00:03 +0100240
241 ret = ethosu_add_carveout(rproc, res_mem->base, res_mem->size,
Mikael Olsson4bfd9872024-04-16 16:36:47 +0200242 it.node->name, false);
Kristofer Jonssona70bfde2023-01-12 10:00:03 +0100243 if (ret)
244 return ret;
245 }
246
247 return 0;
248}
Per Åstrand2cd53972021-04-12 13:46:04 +0200249
250static int ethosu_rproc_start(struct rproc *rproc)
251{
Kristofer Jonssona70bfde2023-01-12 10:00:03 +0100252 struct ethosu_rproc *erproc = (struct ethosu_rproc *)rproc->priv;
253 struct device *dev = erproc->dev;
Per Åstrand2cd53972021-04-12 13:46:04 +0200254
Kristofer Jonssona70bfde2023-01-12 10:00:03 +0100255 dev_info(dev, "Starting up Ethos-U subsystem CPU");
Per Åstrand2cd53972021-04-12 13:46:04 +0200256
Kristofer Jonssona70bfde2023-01-12 10:00:03 +0100257 return reset_control_deassert(erproc->rstc);
Per Åstrand2cd53972021-04-12 13:46:04 +0200258}
259
260static int ethosu_rproc_stop(struct rproc *rproc)
261{
Kristofer Jonssona70bfde2023-01-12 10:00:03 +0100262 struct ethosu_rproc *erproc = (struct ethosu_rproc *)rproc->priv;
263 struct device *dev = erproc->dev;
Per Åstrand2cd53972021-04-12 13:46:04 +0200264
Kristofer Jonssona70bfde2023-01-12 10:00:03 +0100265 dev_info(dev, "Stopping Ethos-U subsystem CPU");
Per Åstrand2cd53972021-04-12 13:46:04 +0200266
Kristofer Jonssona70bfde2023-01-12 10:00:03 +0100267 return reset_control_assert(erproc->rstc);
Per Åstrand2cd53972021-04-12 13:46:04 +0200268}
269
270static void ethosu_rproc_kick(struct rproc *rproc,
271 int vqid)
272{
Kristofer Jonssona70bfde2023-01-12 10:00:03 +0100273 struct ethosu_rproc *erproc = (struct ethosu_rproc *)rproc->priv;
Per Åstrand2cd53972021-04-12 13:46:04 +0200274
Kristofer Jonssona70bfde2023-01-12 10:00:03 +0100275 dev_dbg(&rproc->dev, "Kicking Ethos-U remoteproc vqid: %d!", vqid);
Per Åstrand2cd53972021-04-12 13:46:04 +0200276
Kristofer Jonssona70bfde2023-01-12 10:00:03 +0100277 mbox_send_message(erproc->ch_tx, (void *)&vqid);
Per Åstrand2cd53972021-04-12 13:46:04 +0200278}
279
Mikael Olsson9d0ea8b2023-06-05 16:16:36 +0200280static int ethosu_rproc_handle_rsc(struct rproc *rproc,
281 u32 rsc_type,
282 void *rsc,
283 int offset,
284 int avail)
285{
286 struct ethosu_rproc *erproc = (struct ethosu_rproc *)rproc->priv;
287 struct device *dev = erproc->dev;
288 struct fw_rsc_mapping *mapping = rsc;
289 const struct bus_dma_region *map;
290 size_t num_ranges = 0U;
291 size_t i;
292
293 if (rsc_type != RSC_MAPPING)
294 return RSC_IGNORED;
295
296 if (struct_size(mapping, range, mapping->num_ranges) > avail) {
297 dev_err(dev, "mapping rsc is truncated\n");
298
299 return -EINVAL;
300 }
301
302 for (map = dev->dma_range_map; map->size; ++map)
303 num_ranges++;
304
305 if (num_ranges > mapping->num_ranges) {
306 dev_err(dev,
307 "Mapping rsc doesn't have enough room for DMA ranges\n");
308
309 return -EINVAL;
310 }
311
312 for (i = 0U; i < num_ranges; ++i) {
Mikael Olsson9d0ea8b2023-06-05 16:16:36 +0200313 struct fw_rsc_map_range *range = &mapping->range[i];
Mikael Olssonf1b23f32023-10-06 13:39:16 +0200314 map = &dev->dma_range_map[i];
Mikael Olsson9d0ea8b2023-06-05 16:16:36 +0200315
316 range->da = map->dma_start;
317 range->pa = map->cpu_start;
318 range->len = map->size;
319 }
320
321 dev_dbg(dev, "handle_rsc: Mapping rsc setup");
322
323 return RSC_HANDLED;
324}
325
Per Åstrand2cd53972021-04-12 13:46:04 +0200326static const struct rproc_ops ethosu_rproc_ops = {
Mikael Olsson9d0ea8b2023-06-05 16:16:36 +0200327 .prepare = &ethosu_rproc_prepare,
328 .start = &ethosu_rproc_start,
329 .stop = &ethosu_rproc_stop,
330 .kick = &ethosu_rproc_kick,
331 .handle_rsc = &ethosu_rproc_handle_rsc,
Per Åstrand2cd53972021-04-12 13:46:04 +0200332};
333
Kristofer Jonssona70bfde2023-01-12 10:00:03 +0100334static int ethosu_mailbox_init(struct ethosu_rproc *erproc)
Per Åstrand2cd53972021-04-12 13:46:04 +0200335{
Kristofer Jonssona70bfde2023-01-12 10:00:03 +0100336 struct device *dev = erproc->dev;
337 struct mbox_client *cl = &erproc->mbox_client;
Per Åstrand2cd53972021-04-12 13:46:04 +0200338
Kristofer Jonssona70bfde2023-01-12 10:00:03 +0100339 INIT_WORK(&erproc->work, ethosu_mbox_bottom);
Per Åstrand2cd53972021-04-12 13:46:04 +0200340
Kristofer Jonssona70bfde2023-01-12 10:00:03 +0100341 erproc->wq = create_singlethread_workqueue("ethosu_rproc_wq");
342 if (!erproc->wq) {
343 dev_err(dev, "Failed to create work queue");
Per Åstrand2cd53972021-04-12 13:46:04 +0200344
345 return -EINVAL;
346 }
347
Kristofer Jonssona70bfde2023-01-12 10:00:03 +0100348 cl->dev = dev;
349 cl->rx_callback = ethosu_mbox_top;
350 cl->tx_prepare = NULL;
351 cl->tx_done = NULL;
352 cl->tx_block = true;
353 cl->knows_txdone = false;
354 cl->tx_tout = 500;
Per Åstrand2cd53972021-04-12 13:46:04 +0200355
Kristofer Jonssona70bfde2023-01-12 10:00:03 +0100356 erproc->ch_rx = mbox_request_channel_byname(cl, "rx");
357 if (IS_ERR(erproc->ch_rx)) {
358 dev_err(dev, "Failed to request mbox chan rx");
Per Åstrand2cd53972021-04-12 13:46:04 +0200359
Kristofer Jonssona70bfde2023-01-12 10:00:03 +0100360 return PTR_ERR(erproc->ch_rx);
Per Åstrand2cd53972021-04-12 13:46:04 +0200361 }
362
Kristofer Jonssona70bfde2023-01-12 10:00:03 +0100363 erproc->ch_tx = mbox_request_channel_byname(cl, "tx");
364 if (IS_ERR(erproc->ch_tx)) {
Ledion Dajaedd25502023-10-17 09:15:32 +0200365 dev_dbg(dev, "Using same channel for RX and TX");
Kristofer Jonssona70bfde2023-01-12 10:00:03 +0100366 erproc->ch_tx = erproc->ch_rx;
367 }
Per Åstrand2cd53972021-04-12 13:46:04 +0200368
Kristofer Jonssona70bfde2023-01-12 10:00:03 +0100369 return 0;
Per Åstrand2cd53972021-04-12 13:46:04 +0200370}
371
372static const struct of_device_id ethosu_rproc_match[] = {
Per Åstrand9f36f2e2021-09-30 09:57:34 +0200373 { .compatible = "arm,ethosu-rproc" },
Per Åstrandb9248a42022-05-18 16:05:16 +0200374 { /* sentinel */ },
Per Åstrand2cd53972021-04-12 13:46:04 +0200375};
376
377static int ethosu_rproc_probe(struct platform_device *pdev)
378{
379 struct device *dev = &pdev->dev;
380 struct device_node *np = dev->of_node;
Kristofer Jonssona70bfde2023-01-12 10:00:03 +0100381 struct ethosu_rproc *erproc;
Per Åstrand2cd53972021-04-12 13:46:04 +0200382 struct rproc *rproc;
Kristofer Jonssona70bfde2023-01-12 10:00:03 +0100383 int ret;
Per Åstrand2cd53972021-04-12 13:46:04 +0200384
Kristofer Jonssona70bfde2023-01-12 10:00:03 +0100385 /* map the first 'memory-region' for DMA-mapping */
386 ret = of_reserved_mem_device_init(dev);
387 if (ret)
388 return ret;
389
390 dma_set_mask_and_coherent(dev, DMA_BIT_MASK(DMA_ADDR_BITS));
391
392 rproc = devm_rproc_alloc(dev, np->name, &ethosu_rproc_ops,
393 fw_filename_param,
394 sizeof(*erproc));
395 if (!rproc)
396 return -ENOMEM;
397
398 platform_set_drvdata(pdev, rproc);
Per Åstrand2cd53972021-04-12 13:46:04 +0200399
400 /* Configure rproc */
401 rproc->has_iommu = false;
402 rproc->auto_boot = auto_boot;
403
Kristofer Jonssona70bfde2023-01-12 10:00:03 +0100404 /* Configure Ethos-U rproc */
405 erproc = rproc->priv;
406 erproc->dev = dev;
Per Åstrand2cd53972021-04-12 13:46:04 +0200407
408 /* Get the reset handler for the subsystem */
Kristofer Jonssona70bfde2023-01-12 10:00:03 +0100409 erproc->rstc = devm_reset_control_get_exclusive_by_index(dev, 0);
410 if (IS_ERR(erproc->rstc)) {
411 dev_err(&pdev->dev, "Failed to get reset controller.");
412
413 return PTR_ERR(erproc->rstc);
Per Åstrand2cd53972021-04-12 13:46:04 +0200414 }
415
Kristofer Jonssona70bfde2023-01-12 10:00:03 +0100416 /* Allocate and initialize mailbox client */
417 ret = ethosu_mailbox_init(erproc);
Per Åstrand2cd53972021-04-12 13:46:04 +0200418 if (ret)
Kristofer Jonssona70bfde2023-01-12 10:00:03 +0100419 return ret;
Per Åstrand2cd53972021-04-12 13:46:04 +0200420
421 ret = rproc_add(rproc);
Kristofer Jonssona70bfde2023-01-12 10:00:03 +0100422 if (ret) {
423 dev_err(dev, "Failed to add rproc");
424 goto free_mbox;
425 }
Per Åstrand2cd53972021-04-12 13:46:04 +0200426
Kristofer Jonssona70bfde2023-01-12 10:00:03 +0100427 return 0;
Per Åstrand2cd53972021-04-12 13:46:04 +0200428
Kristofer Jonssona70bfde2023-01-12 10:00:03 +0100429free_mbox:
430 if (erproc->wq)
431 destroy_workqueue(erproc->wq);
432
433 mbox_free_channel(erproc->ch_rx);
434
435 if (erproc->ch_tx != erproc->ch_rx)
436 mbox_free_channel(erproc->ch_tx);
Per Åstrand2cd53972021-04-12 13:46:04 +0200437
438 return ret;
439}
440
441static int ethosu_rproc_remove(struct platform_device *pdev)
442{
443 struct rproc *rproc = platform_get_drvdata(pdev);
Kristofer Jonssona70bfde2023-01-12 10:00:03 +0100444 struct ethosu_rproc *erproc = rproc->priv;
445
446 if (erproc->wq)
447 destroy_workqueue(erproc->wq);
448
449 if (erproc->ch_tx != erproc->ch_rx)
450 mbox_free_channel(erproc->ch_tx);
451
452 mbox_free_channel(erproc->ch_rx);
Per Åstrand2cd53972021-04-12 13:46:04 +0200453
454 rproc_del(rproc);
Per Åstrand2cd53972021-04-12 13:46:04 +0200455
456 return 0;
457}
458
459static struct platform_driver ethosu_rproc_driver = {
460 .probe = ethosu_rproc_probe,
461 .remove = ethosu_rproc_remove,
462 .driver = {
463 .name = "ethosu-rproc",
464 .of_match_table = of_match_ptr(ethosu_rproc_match),
465 },
466};
467
468module_platform_driver(ethosu_rproc_driver);
469
470MODULE_LICENSE("GPL v2");
471MODULE_AUTHOR("Arm Ltd");
472MODULE_DESCRIPTION("Arm Ethos-U NPU RemoteProc Driver");
473MODULE_VERSION(ETHOSU_RPROC_DRIVER_VERSION);