aboutsummaryrefslogtreecommitdiff
path: root/applications/message_handler_openamp/remoteproc.hpp
blob: eec7b44eb214c7cb752524c1cf9941e9f6b889c1 (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
/*
 * 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
 *****************************************************************************/

struct ResourceTable {
    static constexpr uint32_t VERSION = 1;
#if defined(REMOTEPROC_TRACE_BUFFER)
    static constexpr uint32_t NUM_RESOURCES = 3;
#else
    static constexpr uint32_t NUM_RESOURCES = 2;
#endif
    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];
#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));

/*****************************************************************************
 * MetalIO
 *****************************************************************************/

class MetalIO {
public:
    MetalIO();

    remoteproc_mem *operator&();

private:
    static metal_phys_addr_t offsetToPhys(metal_io_region *io, unsigned long offset);
    static unsigned long physToOffset(metal_io_region *io, metal_phys_addr_t phys);

    metal_io_ops ops;
    metal_io_region region;
    remoteproc_mem mem;
};

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

class RProc {
public:
    RProc(Mailbox::Mailbox &_mailbox, resource_table &table, size_t tableSize, MetalIO &_mem);
    ~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 void *mmap(remoteproc *rproc,
                      metal_phys_addr_t *pa,
                      metal_phys_addr_t *da,
                      size_t size,
                      unsigned int attribute,
                      metal_io_region **io);
    static int notify(remoteproc *rproc, uint32_t id);
    static struct remoteproc_mem *getMem(remoteproc *rproc,
                                         const char *name,
                                         metal_phys_addr_t pa,
                                         metal_phys_addr_t da,
                                         void *va,
                                         size_t size,
                                         remoteproc_mem *buf);

    // IRQ notification
    Mailbox::Mailbox &mailbox;

    // Remoteproc
    MetalIO &mem;
    remoteproc rproc;
    remoteproc_ops ops;
    virtio_device *vdev;

    // 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;
};