aboutsummaryrefslogtreecommitdiff
path: root/applications/message_handler_openamp/remoteproc.hpp
blob: 090a3eaf7861afa6852dc671e8a5ee1371f2be2a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
/*
 * SPDX-FileCopyrightText: Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
 * SPDX-License-Identifier: Apache-2.0
 *
 * Licensed under the Apache License, Version 2.0 (the License); you may
 * not use _this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an AS IS BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#pragma once

/*****************************************************************************
 * Includes
 *****************************************************************************/

#include <FreeRTOS.h>
#include <queue.h>
#include <semphr.h>

#include <metal/alloc.h>
#include <openamp/open_amp.h>
#include <openamp/remoteproc.h>

#include <mailbox.hpp>

/*****************************************************************************
 * Resource table
 *****************************************************************************/

static constexpr uint32_t RSC_MAPPING = RSC_VENDOR_START + 1;

/**
 * struct fw_rsc_map_range - memory map range
 * @da: Start device address of the memory address range
 * @pa: Start physical address of the memory address range
 * @len: length of memory address range
 *
 * Memory range to translate between physical and device addresses.
 */
METAL_PACKED_BEGIN
struct fw_rsc_map_range {
    uint32_t da;
    uint32_t pa;
    uint32_t len;
} METAL_PACKED_END;

/**
 * struct fw_rsc_mapping - memory map for address translation
 * @type: RSC_MAPPING
 * @num_ranges: Number of ranges in the memory map
 * @range: Array of the ranges in the memory map
 *
 * This resource entry requests the host to provide information for how to
 * translate between physical and device addresses.
 */
METAL_PACKED_BEGIN
struct fw_rsc_mapping {
    uint32_t type;
    uint8_t num_ranges;
    struct fw_rsc_map_range range[0];
} METAL_PACKED_END;

struct ResourceTable {
    static constexpr uint32_t VERSION = 1;
#if defined(REMOTEPROC_TRACE_BUFFER)
    static constexpr uint32_t NUM_RESOURCES = 4;
#else
    static constexpr uint32_t NUM_RESOURCES = 3;
#endif
    static constexpr uint32_t NUM_RANGES  = 2;
    static constexpr uint32_t NUM_VRINGS  = 2;
    static constexpr uint32_t VRING_ALIGN = 0x100;
    static constexpr uint32_t VRING_SIZE  = 0x08;
    static constexpr uint32_t RESERVED    = 0;

    resource_table table;
    uint32_t offset[NUM_RESOURCES];
    fw_rsc_mapping mapping;
    fw_rsc_map_range range[NUM_RANGES];
#if defined(REMOTEPROC_TRACE_BUFFER)
    fw_rsc_trace trace;
#endif
    fw_rsc_vdev vdev;
    fw_rsc_vdev_vring vring[NUM_VRINGS];
    fw_rsc_carveout carveout;
} __attribute__((packed));

/*****************************************************************************
 * RProc
 *****************************************************************************/

class RProc {
public:
    RProc(Mailbox::Mailbox &_mailbox, resource_table &table, size_t tableSize);
    ~RProc();

    remoteproc *getRProc();
    virtio_device *getVDev();

private:
    // IRQ notification callback
    static void mailboxCallback(void *userArg);

    // Notification task handling virtio messages
    static void notifyTask(void *param);

    // Remote proc ops
    static struct remoteproc *init(remoteproc *rproc, const remoteproc_ops *ops, void *arg);
    static void remove(remoteproc *rproc);
    static int handle_rsc(struct remoteproc *rproc, void *rsc, size_t len);
    static int notify(remoteproc *rproc, uint32_t id);

    // IRQ notification
    Mailbox::Mailbox &mailbox;

    // Remoteproc
    remoteproc rproc;
    remoteproc_ops ops;
    virtio_device *vdev;

    // Resource table memory region
    remoteproc_mem rsc_mem;
    metal_io_region rsc_region;

    // Host provided memory regions
    remoteproc_mem mems[ResourceTable::NUM_RANGES];
    metal_io_region regions[ResourceTable::NUM_RANGES];

    // FreeRTOS
    SemaphoreHandle_t notifySemaphore;
    TaskHandle_t notifyHandle;
};

/*****************************************************************************
 * Rpmsg
 *****************************************************************************/

class Rpmsg {
public:
    Rpmsg(RProc &rproc, const char *const name);

    int send(void *data, size_t len, uint32_t dst = 0);
    void *physicalToVirtual(metal_phys_addr_t pa);

protected:
    virtual int handleMessage(void *data, size_t len, uint32_t src);

private:
    // RPMsg ops
    static void rpmsgNsBind(rpmsg_device *rdev, const char *name, uint32_t dest);
    static void nsUnbindCallback(rpmsg_endpoint *ept);
    static int endpointCallback(rpmsg_endpoint *ept, void *data, size_t len, uint32_t src, void *priv);

    // RPMsg
    rpmsg_virtio_device rvdev;
    rpmsg_device *rdev;
    rpmsg_endpoint endpoint;
};