Kristofer Jonsson | 3f5510f | 2023-02-08 14:23:00 +0100 | [diff] [blame] | 1 | /* |
Mikael Olsson | 296c4c2 | 2024-01-16 10:51:11 +0100 | [diff] [blame] | 2 | * SPDX-FileCopyrightText: Copyright 2022-2024 Arm Limited and/or its affiliates <open-source-office@arm.com> |
Kristofer Jonsson | 3f5510f | 2023-02-08 14:23:00 +0100 | [diff] [blame] | 3 | * 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 Olsson | 67add21 | 2023-05-31 19:00:48 +0200 | [diff] [blame] | 28 | namespace { |
| 29 | void 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 ®ion) { |
Kristofer Jonsson | 3f5510f | 2023-02-08 14:23:00 +0100 | [diff] [blame] | 35 | |
Mikael Olsson | 67add21 | 2023-05-31 19:00:48 +0200 | [diff] [blame] | 36 | remoteproc_init_mem(&mem, nullptr, pa, da, size, ®ion); |
| 37 | metal_io_init(®ion, (void *)da, &mem.pa, size, -1, 0, nullptr); |
| 38 | remoteproc_add_mem(&rproc, &mem); |
Kristofer Jonsson | 3f5510f | 2023-02-08 14:23:00 +0100 | [diff] [blame] | 39 | } |
Mikael Olsson | 67add21 | 2023-05-31 19:00:48 +0200 | [diff] [blame] | 40 | }; // namespace |
Kristofer Jonsson | 3f5510f | 2023-02-08 14:23:00 +0100 | [diff] [blame] | 41 | |
| 42 | /***************************************************************************** |
| 43 | * RProc |
| 44 | *****************************************************************************/ |
| 45 | |
Mikael Olsson | 67add21 | 2023-05-31 19:00:48 +0200 | [diff] [blame] | 46 | RProc::RProc(Mailbox::Mailbox &_mailbox, resource_table &table, size_t tableSize) : |
Mikael Olsson | c218583 | 2024-04-05 16:58:49 +0200 | [diff] [blame] | 47 | mailbox(_mailbox), ops({}), vdev(nullptr), rsc_mem(), rsc_region(), mems(), regions(), |
| 48 | notifySemaphore(xSemaphoreCreateBinary()), notifyHandle() { |
Mikael Olsson | 296c4c2 | 2024-01-16 10:51:11 +0100 | [diff] [blame] | 49 | ops.init = init; // initialize the remoteproc instance |
| 50 | ops.remove = remove; // remove the remoteproc instance |
| 51 | ops.handle_rsc = handle_rsc; // handle the vendor specific resource |
| 52 | ops.notify = notify; // notify the remote |
Kristofer Jonsson | 3f5510f | 2023-02-08 14:23:00 +0100 | [diff] [blame] | 53 | mailbox.registerCallback(mailboxCallback, static_cast<void *>(this)); |
| 54 | |
| 55 | if (!remoteproc_init(&rproc, &ops, this)) { |
| 56 | LOG_ERR("Failed to intialize remoteproc"); |
| 57 | abort(); |
| 58 | } |
| 59 | |
Mikael Olsson | 67add21 | 2023-05-31 19:00:48 +0200 | [diff] [blame] | 60 | // Setup memory region for resource table |
| 61 | const metal_phys_addr_t rsc_addr = reinterpret_cast<metal_phys_addr_t>(&table); |
| 62 | // No translation is needed for rsc_addr because it already contains the DA |
| 63 | // so PA is set to DA |
| 64 | setupRProcMem(rproc, rsc_addr, rsc_addr, tableSize, rsc_mem, rsc_region); |
| 65 | |
Kristofer Jonsson | 3f5510f | 2023-02-08 14:23:00 +0100 | [diff] [blame] | 66 | int ret = remoteproc_set_rsc_table(&rproc, &table, tableSize); |
| 67 | if (ret) { |
| 68 | LOG_ERR("Failed to set resource table. ret=%d", ret); |
| 69 | abort(); |
| 70 | } |
| 71 | |
| 72 | vdev = remoteproc_create_virtio(&rproc, 0, VIRTIO_DEV_DEVICE, nullptr); |
| 73 | if (!vdev) { |
| 74 | LOG_ERR("Failed to create vdev"); |
| 75 | abort(); |
| 76 | } |
| 77 | |
| 78 | BaseType_t taskret = xTaskCreate(notifyTask, "notifyTask", 1024, this, 2, ¬ifyHandle); |
| 79 | if (taskret != pdPASS) { |
| 80 | LOG_ERR("Failed to create remoteproc notify task"); |
| 81 | abort(); |
| 82 | } |
| 83 | } |
| 84 | |
| 85 | RProc::~RProc() { |
| 86 | mailbox.deregisterCallback(mailboxCallback, static_cast<void *>(this)); |
| 87 | vTaskDelete(notifyHandle); |
Mikael Olsson | 30902c3 | 2024-04-02 17:41:55 +0200 | [diff] [blame] | 88 | vSemaphoreDelete(notifySemaphore); |
Kristofer Jonsson | 3f5510f | 2023-02-08 14:23:00 +0100 | [diff] [blame] | 89 | } |
| 90 | |
| 91 | remoteproc *RProc::getRProc() { |
| 92 | return &rproc; |
| 93 | } |
| 94 | |
| 95 | virtio_device *RProc::getVDev() { |
| 96 | return vdev; |
| 97 | } |
| 98 | |
| 99 | void RProc::mailboxCallback(void *userArg) { |
| 100 | auto _this = static_cast<RProc *>(userArg); |
| 101 | |
| 102 | xSemaphoreGiveFromISR(_this->notifySemaphore, nullptr); |
| 103 | } |
| 104 | |
| 105 | void RProc::notifyTask(void *param) { |
| 106 | LOG_DEBUG("Starting message notify task"); |
| 107 | |
| 108 | auto _this = static_cast<RProc *>(param); |
| 109 | |
| 110 | while (true) { |
| 111 | // Wait for event |
| 112 | xSemaphoreTake(_this->notifySemaphore, portMAX_DELAY); |
| 113 | |
| 114 | // Read virtio queue and notify all rpmsg clients |
| 115 | rproc_virtio_notified(_this->vdev, RSC_NOTIFY_ID_ANY); |
| 116 | } |
| 117 | } |
| 118 | |
| 119 | struct remoteproc *RProc::init(remoteproc *rproc, const remoteproc_ops *ops, void *arg) { |
| 120 | LOG_DEBUG(""); |
| 121 | |
Kristofer Jonsson | 3f5510f | 2023-02-08 14:23:00 +0100 | [diff] [blame] | 122 | rproc->ops = ops; |
| 123 | rproc->priv = arg; |
Kristofer Jonsson | 3f5510f | 2023-02-08 14:23:00 +0100 | [diff] [blame] | 124 | |
| 125 | return rproc; |
| 126 | } |
| 127 | |
Mikael Olsson | 67add21 | 2023-05-31 19:00:48 +0200 | [diff] [blame] | 128 | int RProc::handle_rsc(remoteproc *rproc, void *rsc, size_t len) { |
| 129 | auto _this = static_cast<RProc *>(rproc->priv); |
| 130 | struct fw_rsc_mapping *mapping = static_cast<fw_rsc_mapping *>(rsc); |
| 131 | |
| 132 | if (mapping->type != RSC_MAPPING) { |
| 133 | LOG_ERR("Unknown resource type %" PRIu32, mapping->type); |
| 134 | return -RPROC_ERR_RSC_TAB_NS; |
| 135 | } |
| 136 | |
| 137 | for (uint32_t i = 0; i < mapping->num_ranges; ++i) { |
| 138 | const fw_rsc_map_range *range = &mapping->range[i]; |
| 139 | if (range->len == 0) { |
| 140 | LOG_DEBUG("Ignored zero length memory map range[%" PRIu32 "]", i); |
| 141 | continue; |
| 142 | } |
| 143 | setupRProcMem(*rproc, range->pa, range->da, range->len, _this->mems[i], _this->regions[i]); |
| 144 | } |
| 145 | |
| 146 | return 0; |
| 147 | } |
| 148 | |
Kristofer Jonsson | 3f5510f | 2023-02-08 14:23:00 +0100 | [diff] [blame] | 149 | void RProc::remove(remoteproc *rproc) { |
| 150 | LOG_DEBUG(""); |
| 151 | } |
| 152 | |
| 153 | int RProc::notify(remoteproc *rproc, uint32_t id) { |
| 154 | LOG_DEBUG(""); |
| 155 | |
| 156 | auto *_this = static_cast<RProc *>(rproc->priv); |
| 157 | _this->mailbox.sendMessage(); |
| 158 | return 0; |
| 159 | } |
| 160 | |
| 161 | /***************************************************************************** |
| 162 | * Rpmsg |
| 163 | *****************************************************************************/ |
| 164 | |
Mikael Olsson | f870d11 | 2024-04-02 17:20:47 +0200 | [diff] [blame] | 165 | Rpmsg::Rpmsg(RProc &rproc, const char *const name) : rvdev({}), rdev(), endpoint({}) { |
Mikael Olsson | 67add21 | 2023-05-31 19:00:48 +0200 | [diff] [blame] | 166 | struct virtio_device *vdev = rproc.getVDev(); |
Kristofer Jonsson | 3f5510f | 2023-02-08 14:23:00 +0100 | [diff] [blame] | 167 | |
Mikael Olsson | 67add21 | 2023-05-31 19:00:48 +0200 | [diff] [blame] | 168 | if (vdev->vrings_num != ResourceTable::NUM_VRINGS) { |
| 169 | LOG_ERR("Invalid number of vrings"); |
Kristofer Jonsson | 3f5510f | 2023-02-08 14:23:00 +0100 | [diff] [blame] | 170 | abort(); |
| 171 | } |
| 172 | |
Mikael Olsson | 67add21 | 2023-05-31 19:00:48 +0200 | [diff] [blame] | 173 | // Vdev can use the same IO region for translations as the vring |
| 174 | if (rpmsg_init_vdev(&rvdev, vdev, nullptr, vdev->vrings_info[0].io, nullptr)) { |
Kristofer Jonsson | 3f5510f | 2023-02-08 14:23:00 +0100 | [diff] [blame] | 175 | LOG_ERR("Failed to initialize rpmsg vdev"); |
| 176 | abort(); |
| 177 | } |
| 178 | |
| 179 | rdev = rpmsg_virtio_get_rpmsg_device(&rvdev); |
| 180 | if (!rdev) { |
| 181 | LOG_ERR("Failed to get rpmsg dev"); |
| 182 | abort(); |
| 183 | } |
| 184 | |
| 185 | int ret = |
| 186 | rpmsg_create_ept(&endpoint, rdev, name, RPMSG_ADDR_ANY, RPMSG_ADDR_ANY, endpointCallback, nsUnbindCallback); |
| 187 | if (ret != RPMSG_SUCCESS) { |
| 188 | LOG_ERR("Failed to create rpmsg endpoint. ret=%d", ret); |
| 189 | abort(); |
| 190 | } |
| 191 | |
| 192 | endpoint.priv = static_cast<void *>(this); |
| 193 | } |
| 194 | |
| 195 | int Rpmsg::send(void *data, size_t len, uint32_t dst) { |
| 196 | LOG_DEBUG("Sending rpmsg. dst=%" PRIu32 ", len=%zu", dst, len); |
| 197 | |
| 198 | int ret = rpmsg_sendto(&endpoint, data, len, dst); |
| 199 | return ret; |
| 200 | } |
| 201 | |
| 202 | void *Rpmsg::physicalToVirtual(metal_phys_addr_t pa) { |
| 203 | return metal_io_phys_to_virt(rvdev.shbuf_io, pa); |
| 204 | } |
| 205 | |
| 206 | void Rpmsg::rpmsgNsBind(rpmsg_device *rdev, const char *name, uint32_t dest) { |
| 207 | LOG_DEBUG(""); |
| 208 | } |
| 209 | |
| 210 | void Rpmsg::nsUnbindCallback(rpmsg_endpoint *ept) { |
| 211 | LOG_DEBUG(""); |
| 212 | } |
| 213 | |
| 214 | int Rpmsg::endpointCallback(rpmsg_endpoint *ept, void *data, size_t len, uint32_t src, void *priv) { |
| 215 | LOG_DEBUG("src=%" PRIX32 ", len=%zu", src, len); |
| 216 | |
| 217 | auto _this = static_cast<Rpmsg *>(priv); |
| 218 | _this->handleMessage(data, len, src); |
| 219 | |
| 220 | return 0; |
| 221 | } |
| 222 | |
| 223 | int Rpmsg::handleMessage(void *data, size_t len, uint32_t src) { |
| 224 | LOG_DEBUG("Receiving rpmsg. src=%" PRIu32 ", len=%zu", src, len); |
| 225 | |
| 226 | auto c = static_cast<char *>(data); |
| 227 | for (size_t i = 0; i < len; i++) { |
| 228 | printf("%c", c[i]); |
| 229 | } |
| 230 | printf("\n"); |
| 231 | |
| 232 | return 0; |
| 233 | } |