blob: 8fda69ba4960de293cffc6f3499d2c94a235bcf9 [file] [log] [blame]
Kristofer Jonsson3f5510f2023-02-08 14:23:00 +01001/*
2 * SPDX-FileCopyrightText: Copyright 2022-2023 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) :
47 mailbox(_mailbox),
Kristofer Jonsson3f5510f2023-02-08 14:23:00 +010048 ops{
Mikael Olsson67add212023-05-31 19:00:48 +020049 .init = init, // initialize the remoteproc instance
50 .remove = remove, // remove the remoteproc instance
51 .mmap = nullptr, // memory mapped the memory with physical address as input
52 .handle_rsc = handle_rsc, // handle the vendor specific resource
53 .config = nullptr, // configure the remoteproc to make it ready to load and run executable
54 .start = nullptr, // kick the remoteproc to run application
Kristofer Jonsson3f5510f2023-02-08 14:23:00 +010055 .stop = nullptr, // stop the remoteproc from running application, the resource such as memory may not be off.
56 .shutdown = nullptr, // shutdown the remoteproc and release its resources.
57 .notify = notify, // notify the remote
58 .get_mem = nullptr, // get remoteproc memory I/O region.
59 },
Mikael Olsson67add212023-05-31 19:00:48 +020060 vdev(nullptr), mems(), regions(), notifySemaphore(xSemaphoreCreateBinary()) {
Kristofer Jonsson3f5510f2023-02-08 14:23:00 +010061 mailbox.registerCallback(mailboxCallback, static_cast<void *>(this));
62
63 if (!remoteproc_init(&rproc, &ops, this)) {
64 LOG_ERR("Failed to intialize remoteproc");
65 abort();
66 }
67
Mikael Olsson67add212023-05-31 19:00:48 +020068 // Setup memory region for resource table
69 const metal_phys_addr_t rsc_addr = reinterpret_cast<metal_phys_addr_t>(&table);
70 // No translation is needed for rsc_addr because it already contains the DA
71 // so PA is set to DA
72 setupRProcMem(rproc, rsc_addr, rsc_addr, tableSize, rsc_mem, rsc_region);
73
Kristofer Jonsson3f5510f2023-02-08 14:23:00 +010074 int ret = remoteproc_set_rsc_table(&rproc, &table, tableSize);
75 if (ret) {
76 LOG_ERR("Failed to set resource table. ret=%d", ret);
77 abort();
78 }
79
80 vdev = remoteproc_create_virtio(&rproc, 0, VIRTIO_DEV_DEVICE, nullptr);
81 if (!vdev) {
82 LOG_ERR("Failed to create vdev");
83 abort();
84 }
85
86 BaseType_t taskret = xTaskCreate(notifyTask, "notifyTask", 1024, this, 2, &notifyHandle);
87 if (taskret != pdPASS) {
88 LOG_ERR("Failed to create remoteproc notify task");
89 abort();
90 }
91}
92
93RProc::~RProc() {
94 mailbox.deregisterCallback(mailboxCallback, static_cast<void *>(this));
95 vTaskDelete(notifyHandle);
96}
97
98remoteproc *RProc::getRProc() {
99 return &rproc;
100}
101
102virtio_device *RProc::getVDev() {
103 return vdev;
104}
105
106void RProc::mailboxCallback(void *userArg) {
107 auto _this = static_cast<RProc *>(userArg);
108
109 xSemaphoreGiveFromISR(_this->notifySemaphore, nullptr);
110}
111
112void RProc::notifyTask(void *param) {
113 LOG_DEBUG("Starting message notify task");
114
115 auto _this = static_cast<RProc *>(param);
116
117 while (true) {
118 // Wait for event
119 xSemaphoreTake(_this->notifySemaphore, portMAX_DELAY);
120
121 // Read virtio queue and notify all rpmsg clients
122 rproc_virtio_notified(_this->vdev, RSC_NOTIFY_ID_ANY);
123 }
124}
125
126struct remoteproc *RProc::init(remoteproc *rproc, const remoteproc_ops *ops, void *arg) {
127 LOG_DEBUG("");
128
Kristofer Jonsson3f5510f2023-02-08 14:23:00 +0100129 rproc->ops = ops;
130 rproc->priv = arg;
Kristofer Jonsson3f5510f2023-02-08 14:23:00 +0100131
132 return rproc;
133}
134
Mikael Olsson67add212023-05-31 19:00:48 +0200135int RProc::handle_rsc(remoteproc *rproc, void *rsc, size_t len) {
136 auto _this = static_cast<RProc *>(rproc->priv);
137 struct fw_rsc_mapping *mapping = static_cast<fw_rsc_mapping *>(rsc);
138
139 if (mapping->type != RSC_MAPPING) {
140 LOG_ERR("Unknown resource type %" PRIu32, mapping->type);
141 return -RPROC_ERR_RSC_TAB_NS;
142 }
143
144 for (uint32_t i = 0; i < mapping->num_ranges; ++i) {
145 const fw_rsc_map_range *range = &mapping->range[i];
146 if (range->len == 0) {
147 LOG_DEBUG("Ignored zero length memory map range[%" PRIu32 "]", i);
148 continue;
149 }
150 setupRProcMem(*rproc, range->pa, range->da, range->len, _this->mems[i], _this->regions[i]);
151 }
152
153 return 0;
154}
155
Kristofer Jonsson3f5510f2023-02-08 14:23:00 +0100156void RProc::remove(remoteproc *rproc) {
157 LOG_DEBUG("");
158}
159
160int RProc::notify(remoteproc *rproc, uint32_t id) {
161 LOG_DEBUG("");
162
163 auto *_this = static_cast<RProc *>(rproc->priv);
164 _this->mailbox.sendMessage();
165 return 0;
166}
167
168/*****************************************************************************
169 * Rpmsg
170 *****************************************************************************/
171
172Rpmsg::Rpmsg(RProc &rproc, const char *const name) {
Mikael Olsson67add212023-05-31 19:00:48 +0200173 struct virtio_device *vdev = rproc.getVDev();
Kristofer Jonsson3f5510f2023-02-08 14:23:00 +0100174
Mikael Olsson67add212023-05-31 19:00:48 +0200175 if (vdev->vrings_num != ResourceTable::NUM_VRINGS) {
176 LOG_ERR("Invalid number of vrings");
Kristofer Jonsson3f5510f2023-02-08 14:23:00 +0100177 abort();
178 }
179
Mikael Olsson67add212023-05-31 19:00:48 +0200180 // Vdev can use the same IO region for translations as the vring
181 if (rpmsg_init_vdev(&rvdev, vdev, nullptr, vdev->vrings_info[0].io, nullptr)) {
Kristofer Jonsson3f5510f2023-02-08 14:23:00 +0100182 LOG_ERR("Failed to initialize rpmsg vdev");
183 abort();
184 }
185
186 rdev = rpmsg_virtio_get_rpmsg_device(&rvdev);
187 if (!rdev) {
188 LOG_ERR("Failed to get rpmsg dev");
189 abort();
190 }
191
192 int ret =
193 rpmsg_create_ept(&endpoint, rdev, name, RPMSG_ADDR_ANY, RPMSG_ADDR_ANY, endpointCallback, nsUnbindCallback);
194 if (ret != RPMSG_SUCCESS) {
195 LOG_ERR("Failed to create rpmsg endpoint. ret=%d", ret);
196 abort();
197 }
198
199 endpoint.priv = static_cast<void *>(this);
200}
201
202int Rpmsg::send(void *data, size_t len, uint32_t dst) {
203 LOG_DEBUG("Sending rpmsg. dst=%" PRIu32 ", len=%zu", dst, len);
204
205 int ret = rpmsg_sendto(&endpoint, data, len, dst);
206 return ret;
207}
208
209void *Rpmsg::physicalToVirtual(metal_phys_addr_t pa) {
210 return metal_io_phys_to_virt(rvdev.shbuf_io, pa);
211}
212
213void Rpmsg::rpmsgNsBind(rpmsg_device *rdev, const char *name, uint32_t dest) {
214 LOG_DEBUG("");
215}
216
217void Rpmsg::nsUnbindCallback(rpmsg_endpoint *ept) {
218 LOG_DEBUG("");
219}
220
221int Rpmsg::endpointCallback(rpmsg_endpoint *ept, void *data, size_t len, uint32_t src, void *priv) {
222 LOG_DEBUG("src=%" PRIX32 ", len=%zu", src, len);
223
224 auto _this = static_cast<Rpmsg *>(priv);
225 _this->handleMessage(data, len, src);
226
227 return 0;
228}
229
230int Rpmsg::handleMessage(void *data, size_t len, uint32_t src) {
231 LOG_DEBUG("Receiving rpmsg. src=%" PRIu32 ", len=%zu", src, len);
232
233 auto c = static_cast<char *>(data);
234 for (size_t i = 0; i < len; i++) {
235 printf("%c", c[i]);
236 }
237 printf("\n");
238
239 return 0;
240}