blob: 599452b73805f4169cb82e6ddb5830fb81914f46 [file] [log] [blame]
Kristofer Jonsson3f5510f2023-02-08 14:23:00 +01001/*
Mikael Olsson296c4c22024-01-16 10:51:11 +01002 * SPDX-FileCopyrightText: Copyright 2022-2024 Arm Limited and/or its affiliates <open-source-office@arm.com>
Kristofer Jonsson3f5510f2023-02-08 14:23:00 +01003 * SPDX-License-Identifier: Apache-2.0
4 *
5 * Licensed under the Apache License, Version 2.0 (the License); you may
6 * not use _this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an AS IS BASIS, WITHOUT
13 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18/*****************************************************************************
19 * Includes
20 *****************************************************************************/
21
22#include "remoteproc.hpp"
23
24#include <cinttypes>
25
26#include <ethosu_log.h>
27
Mikael Olsson67add212023-05-31 19:00:48 +020028namespace {
29void setupRProcMem(remoteproc &rproc,
30 metal_phys_addr_t pa,
31 metal_phys_addr_t da,
32 size_t size,
33 remoteproc_mem &mem,
34 metal_io_region &region) {
Kristofer Jonsson3f5510f2023-02-08 14:23:00 +010035
Mikael Olsson67add212023-05-31 19:00:48 +020036 remoteproc_init_mem(&mem, nullptr, pa, da, size, &region);
37 metal_io_init(&region, (void *)da, &mem.pa, size, -1, 0, nullptr);
38 remoteproc_add_mem(&rproc, &mem);
Kristofer Jonsson3f5510f2023-02-08 14:23:00 +010039}
Mikael Olsson67add212023-05-31 19:00:48 +020040}; // namespace
Kristofer Jonsson3f5510f2023-02-08 14:23:00 +010041
42/*****************************************************************************
43 * RProc
44 *****************************************************************************/
45
Mikael Olsson67add212023-05-31 19:00:48 +020046RProc::RProc(Mailbox::Mailbox &_mailbox, resource_table &table, size_t tableSize) :
Mikael Olsson296c4c22024-01-16 10:51:11 +010047 mailbox(_mailbox), ops({}), vdev(nullptr), mems(), regions(), notifySemaphore(xSemaphoreCreateBinary()) {
48 ops.init = init; // initialize the remoteproc instance
49 ops.remove = remove; // remove the remoteproc instance
50 ops.handle_rsc = handle_rsc; // handle the vendor specific resource
51 ops.notify = notify; // notify the remote
Kristofer Jonsson3f5510f2023-02-08 14:23:00 +010052 mailbox.registerCallback(mailboxCallback, static_cast<void *>(this));
53
54 if (!remoteproc_init(&rproc, &ops, this)) {
55 LOG_ERR("Failed to intialize remoteproc");
56 abort();
57 }
58
Mikael Olsson67add212023-05-31 19:00:48 +020059 // Setup memory region for resource table
60 const metal_phys_addr_t rsc_addr = reinterpret_cast<metal_phys_addr_t>(&table);
61 // No translation is needed for rsc_addr because it already contains the DA
62 // so PA is set to DA
63 setupRProcMem(rproc, rsc_addr, rsc_addr, tableSize, rsc_mem, rsc_region);
64
Kristofer Jonsson3f5510f2023-02-08 14:23:00 +010065 int ret = remoteproc_set_rsc_table(&rproc, &table, tableSize);
66 if (ret) {
67 LOG_ERR("Failed to set resource table. ret=%d", ret);
68 abort();
69 }
70
71 vdev = remoteproc_create_virtio(&rproc, 0, VIRTIO_DEV_DEVICE, nullptr);
72 if (!vdev) {
73 LOG_ERR("Failed to create vdev");
74 abort();
75 }
76
77 BaseType_t taskret = xTaskCreate(notifyTask, "notifyTask", 1024, this, 2, &notifyHandle);
78 if (taskret != pdPASS) {
79 LOG_ERR("Failed to create remoteproc notify task");
80 abort();
81 }
82}
83
84RProc::~RProc() {
85 mailbox.deregisterCallback(mailboxCallback, static_cast<void *>(this));
86 vTaskDelete(notifyHandle);
87}
88
89remoteproc *RProc::getRProc() {
90 return &rproc;
91}
92
93virtio_device *RProc::getVDev() {
94 return vdev;
95}
96
97void RProc::mailboxCallback(void *userArg) {
98 auto _this = static_cast<RProc *>(userArg);
99
100 xSemaphoreGiveFromISR(_this->notifySemaphore, nullptr);
101}
102
103void RProc::notifyTask(void *param) {
104 LOG_DEBUG("Starting message notify task");
105
106 auto _this = static_cast<RProc *>(param);
107
108 while (true) {
109 // Wait for event
110 xSemaphoreTake(_this->notifySemaphore, portMAX_DELAY);
111
112 // Read virtio queue and notify all rpmsg clients
113 rproc_virtio_notified(_this->vdev, RSC_NOTIFY_ID_ANY);
114 }
115}
116
117struct remoteproc *RProc::init(remoteproc *rproc, const remoteproc_ops *ops, void *arg) {
118 LOG_DEBUG("");
119
Kristofer Jonsson3f5510f2023-02-08 14:23:00 +0100120 rproc->ops = ops;
121 rproc->priv = arg;
Kristofer Jonsson3f5510f2023-02-08 14:23:00 +0100122
123 return rproc;
124}
125
Mikael Olsson67add212023-05-31 19:00:48 +0200126int RProc::handle_rsc(remoteproc *rproc, void *rsc, size_t len) {
127 auto _this = static_cast<RProc *>(rproc->priv);
128 struct fw_rsc_mapping *mapping = static_cast<fw_rsc_mapping *>(rsc);
129
130 if (mapping->type != RSC_MAPPING) {
131 LOG_ERR("Unknown resource type %" PRIu32, mapping->type);
132 return -RPROC_ERR_RSC_TAB_NS;
133 }
134
135 for (uint32_t i = 0; i < mapping->num_ranges; ++i) {
136 const fw_rsc_map_range *range = &mapping->range[i];
137 if (range->len == 0) {
138 LOG_DEBUG("Ignored zero length memory map range[%" PRIu32 "]", i);
139 continue;
140 }
141 setupRProcMem(*rproc, range->pa, range->da, range->len, _this->mems[i], _this->regions[i]);
142 }
143
144 return 0;
145}
146
Kristofer Jonsson3f5510f2023-02-08 14:23:00 +0100147void RProc::remove(remoteproc *rproc) {
148 LOG_DEBUG("");
149}
150
151int RProc::notify(remoteproc *rproc, uint32_t id) {
152 LOG_DEBUG("");
153
154 auto *_this = static_cast<RProc *>(rproc->priv);
155 _this->mailbox.sendMessage();
156 return 0;
157}
158
159/*****************************************************************************
160 * Rpmsg
161 *****************************************************************************/
162
Mikael Olssonf870d112024-04-02 17:20:47 +0200163Rpmsg::Rpmsg(RProc &rproc, const char *const name) : rvdev({}), rdev(), endpoint({}) {
Mikael Olsson67add212023-05-31 19:00:48 +0200164 struct virtio_device *vdev = rproc.getVDev();
Kristofer Jonsson3f5510f2023-02-08 14:23:00 +0100165
Mikael Olsson67add212023-05-31 19:00:48 +0200166 if (vdev->vrings_num != ResourceTable::NUM_VRINGS) {
167 LOG_ERR("Invalid number of vrings");
Kristofer Jonsson3f5510f2023-02-08 14:23:00 +0100168 abort();
169 }
170
Mikael Olsson67add212023-05-31 19:00:48 +0200171 // Vdev can use the same IO region for translations as the vring
172 if (rpmsg_init_vdev(&rvdev, vdev, nullptr, vdev->vrings_info[0].io, nullptr)) {
Kristofer Jonsson3f5510f2023-02-08 14:23:00 +0100173 LOG_ERR("Failed to initialize rpmsg vdev");
174 abort();
175 }
176
177 rdev = rpmsg_virtio_get_rpmsg_device(&rvdev);
178 if (!rdev) {
179 LOG_ERR("Failed to get rpmsg dev");
180 abort();
181 }
182
183 int ret =
184 rpmsg_create_ept(&endpoint, rdev, name, RPMSG_ADDR_ANY, RPMSG_ADDR_ANY, endpointCallback, nsUnbindCallback);
185 if (ret != RPMSG_SUCCESS) {
186 LOG_ERR("Failed to create rpmsg endpoint. ret=%d", ret);
187 abort();
188 }
189
190 endpoint.priv = static_cast<void *>(this);
191}
192
193int Rpmsg::send(void *data, size_t len, uint32_t dst) {
194 LOG_DEBUG("Sending rpmsg. dst=%" PRIu32 ", len=%zu", dst, len);
195
196 int ret = rpmsg_sendto(&endpoint, data, len, dst);
197 return ret;
198}
199
200void *Rpmsg::physicalToVirtual(metal_phys_addr_t pa) {
201 return metal_io_phys_to_virt(rvdev.shbuf_io, pa);
202}
203
204void Rpmsg::rpmsgNsBind(rpmsg_device *rdev, const char *name, uint32_t dest) {
205 LOG_DEBUG("");
206}
207
208void Rpmsg::nsUnbindCallback(rpmsg_endpoint *ept) {
209 LOG_DEBUG("");
210}
211
212int Rpmsg::endpointCallback(rpmsg_endpoint *ept, void *data, size_t len, uint32_t src, void *priv) {
213 LOG_DEBUG("src=%" PRIX32 ", len=%zu", src, len);
214
215 auto _this = static_cast<Rpmsg *>(priv);
216 _this->handleMessage(data, len, src);
217
218 return 0;
219}
220
221int Rpmsg::handleMessage(void *data, size_t len, uint32_t src) {
222 LOG_DEBUG("Receiving rpmsg. src=%" PRIu32 ", len=%zu", src, len);
223
224 auto c = static_cast<char *>(data);
225 for (size_t i = 0; i < len; i++) {
226 printf("%c", c[i]);
227 }
228 printf("\n");
229
230 return 0;
231}