• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-2022 Huawei Technologies Co., Ltd. All rights reserved.
3  *
4  * UniProton is licensed under Mulan PSL v2.
5  * You can use this software according to the terms and conditions of the Mulan PSL v2.
6  * You may obtain a copy of Mulan PSL v2 at:
7  * 	http://license.coscl.org.cn/MulanPSL2
8  * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
9  * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
10  * See the Mulan PSL v2 for more details.
11  * Create: 2022-12-05
12  * Description: openamp backend
13  */
14 
15 #include "rpmsg_backend.h"
16 #include "metal/device.h"
17 #include "prt_hwi.h"
18 
19 static metal_phys_addr_t shm_physmap[] = { SHM_START_ADDR };
20 static struct metal_device shm_device = {
21     .name = SHM_DEVICE_NAME,
22     .bus = NULL,
23     .num_regions = 1,
24     {
25         {
26             .virt       = (void *) SHM_START_ADDR,
27             .physmap    = shm_physmap,
28             .size       = SHM_SIZE,
29             .page_shift = DEFAULT_PAGE_SHIFT,
30             .page_mask  = DEFAULT_PAGE_MASK,
31             .mem_flags  = 0,
32             .ops        = { NULL },
33         },
34     },
35     .node = { NULL },
36     .irq_num = 0,
37     .irq_info = NULL
38 };
39 
40 static struct virtio_vring_info rvrings[2] = {
41     [0] = {
42         .info.align = VRING_ALIGNMENT,
43     },
44     [1] = {
45         .info.align = VRING_ALIGNMENT,
46     },
47 };
48 
49 static struct virtqueue *vq[2];
50 
virtio_get_status(struct virtio_device * vdev)51 static unsigned char virtio_get_status(struct virtio_device *vdev)
52 {
53     return sys_read8(VDEV_STATUS_ADDR);
54 }
55 
virtio_set_status(struct virtio_device * vdev,unsigned char status)56 static void virtio_set_status(struct virtio_device *vdev, unsigned char status)
57 {
58     sys_write8(status, VDEV_STATUS_ADDR);
59 }
60 
virtio_get_features(struct virtio_device * vdev)61 static uint32_t virtio_get_features(struct virtio_device *vdev)
62 {
63     return BIT(VIRTIO_RPMSG_F_NS);
64 }
65 
virtio_set_features(struct virtio_device * vdev,uint32_t features)66 static void virtio_set_features(struct virtio_device *vdev, uint32_t features)
67 {
68 }
69 
virtio_notify(struct virtqueue * vq)70 static void virtio_notify(struct virtqueue *vq)
71 {
72     uint16_t coreMask = 1;
73     OsHwiMcTrigger(coreMask, OS_HWI_IPI_NO_07);
74 }
75 
76 const struct virtio_dispatch dispatch = {
77     .get_status = virtio_get_status,
78     .set_status = virtio_set_status,
79     .get_features = virtio_get_features,
80     .set_features = virtio_set_features,
81     .notify = virtio_notify,
82 };
83 
rpmsg_hwi_handler(void)84 static void rpmsg_hwi_handler(void)
85 {
86     virtqueue_notification(vq[VIRTQUEUE_ID]);
87 }
88 
rpmsg_hwi_init(void)89 static U32 rpmsg_hwi_init(void)
90 {
91     U32 ret;
92 
93     ret = PRT_HwiSetAttr(OS_OPENAMP_NOTIFY_HWI_NUM, OS_OPENAMP_NOTIFY_HWI_PRIO, OS_HWI_MODE_ENGROSS);
94     if (ret != OS_OK) {
95         return ret;
96     }
97 
98     ret = PRT_HwiCreate(OS_OPENAMP_NOTIFY_HWI_NUM, (HwiProcFunc)rpmsg_hwi_handler, 0);
99     if (ret != OS_OK) {
100         return ret;
101     }
102 
103 #if (OS_GIC_VER == 3)
104     ret = PRT_HwiEnable(OS_OPENAMP_NOTIFY_HWI_NUM);
105     if (ret != OS_OK) {
106         return ret;
107     }
108 #endif
109 
110     return OS_OK;
111 }
112 
rpmsg_backend_init(struct metal_io_region ** io,struct virtio_device * vdev)113 int rpmsg_backend_init(struct metal_io_region **io, struct virtio_device *vdev)
114 {
115     int32_t                  err;
116     struct metal_init_params metal_params = METAL_INIT_DEFAULTS;
117     struct metal_device     *device;
118 
119     err = rpmsg_hwi_init();
120     if (err) {
121         return err;
122     }
123 
124     /* Libmetal setup */
125     err = metal_init(&metal_params);
126     if (err) {
127         return err;
128     }
129 
130     err = metal_register_generic_device(&shm_device);
131     if (err) {
132         return err;
133     }
134 
135     err = metal_device_open("generic", SHM_DEVICE_NAME, &device);
136     if (err) {
137         return err;
138     }
139 
140     *io = metal_device_io_region(device, 0);
141     if (!*io) {
142         return err;
143     }
144 
145     /* Virtqueue setup */
146     vq[0] = virtqueue_allocate(VRING_SIZE);
147     if (!vq[0]) {
148         return -ENOMEM;
149     }
150 
151     vq[1] = virtqueue_allocate(VRING_SIZE);
152     if (!vq[1]) {
153         return -ENOMEM;
154     }
155 
156     rvrings[0].io = *io;
157     rvrings[0].info.vaddr = (void *)VRING_TX_ADDRESS;
158     rvrings[0].info.num_descs = VRING_SIZE;
159     rvrings[0].info.align = VRING_ALIGNMENT;
160     rvrings[0].vq = vq[0];
161 
162     rvrings[1].io = *io;
163     rvrings[1].info.vaddr = (void *)VRING_RX_ADDRESS;
164     rvrings[1].info.num_descs = VRING_SIZE;
165     rvrings[1].info.align = VRING_ALIGNMENT;
166     rvrings[1].vq = vq[1];
167 
168     vdev->role = RPMSG_ROLE;
169     vdev->vrings_num = VRING_COUNT;
170     vdev->func = &dispatch;
171     vdev->vrings_info = &rvrings[0];
172 
173     return 0;
174 }
175