1 /* 2 * Copyright (c) 2021 Nordic Semiconductor ASA 3 * 4 * SPDX-License-Identifier: Apache-2.0 5 */ 6 7 #ifndef ZEPHYR_INCLUDE_RPMSG_MULTIPLE_INSTANCE_H_ 8 #define ZEPHYR_INCLUDE_RPMSG_MULTIPLE_INSTANCE_H_ 9 10 #include <openamp/open_amp.h> 11 #include <metal/sys.h> 12 #include <metal/device.h> 13 #include <metal/alloc.h> 14 15 #ifdef __cplusplus 16 extern "C" { 17 #endif 18 19 /** 20 * @brief RPMsg multiple instance API 21 * @defgroup rpmsg_multiple_instance_api RPMsg multiple instance APIs 22 * @{ 23 */ 24 25 #define VDEV_START_ADDR CONFIG_RPMSG_MULTI_INSTANCE_SHM_BASE_ADDRESS 26 #define VDEV_SIZE CONFIG_RPMSG_MULTI_INSTANCE_SHM_SIZE 27 28 #define SHM_START_ADDR VDEV_START_ADDR 29 #define SHM_SIZE VDEV_SIZE 30 31 #define VRING_ALIGNMENT (4) /**< Alignment of vring buffer. */ 32 #define VDEV_STATUS_SIZE (0x4) /**< Size of status region. */ 33 34 /** @brief Event callback structure. 35 * 36 * It is registered during endpoint registration. 37 * This structure is packed into the endpoint configuration. 38 */ 39 struct rpmsg_mi_cb { 40 /** @brief Bind was successful. 41 * 42 * @param priv Private user data. 43 */ 44 void (*bound)(void *priv); 45 46 /** @brief New packet arrived. 47 * 48 * @param data Pointer to data buffer. 49 * @param len Length of @a data. 50 * @param priv Private user data. 51 */ 52 void (*received)(const void *data, size_t len, void *priv); 53 }; 54 55 /** @brief Endpoint instance. */ 56 struct rpmsg_mi_ept { 57 58 /** Name of endpoint. */ 59 const char *name; 60 61 /** RPMsg endpoint. */ 62 struct rpmsg_endpoint ep; 63 64 /** Event callback structure. */ 65 struct rpmsg_mi_cb *cb; 66 67 /** Private user data. */ 68 void *priv; 69 70 /** Endpoint was bound. */ 71 volatile bool bound; 72 73 /** Linked list node. */ 74 sys_snode_t node; 75 }; 76 77 /** @brief Endpoint configuration. */ 78 struct rpmsg_mi_ept_cfg { 79 80 /** Name of endpoint. */ 81 const char *name; 82 83 /** Event callback structure. */ 84 struct rpmsg_mi_cb *cb; 85 86 /** Private user data. */ 87 void *priv; 88 }; 89 90 /** @brief Struct describing the context of the RPMsg instance. */ 91 struct rpmsg_mi_ctx { 92 const char *name; 93 struct k_work_q ipm_work_q; 94 struct k_work ipm_work; 95 96 const struct device *ipm_tx_handle; 97 const struct device *ipm_rx_handle; 98 99 unsigned int ipm_tx_id; 100 101 uintptr_t shm_status_reg_addr; 102 struct metal_io_region *shm_io; 103 struct metal_device shm_device; 104 metal_phys_addr_t shm_physmap[1]; 105 106 struct rpmsg_virtio_device rvdev; 107 struct rpmsg_virtio_shm_pool shpool; 108 struct rpmsg_device *rdev; 109 110 struct virtqueue *vq[2]; 111 struct virtio_vring_info rvrings[2]; 112 struct virtio_device vdev; 113 114 uintptr_t vring_tx_addr; 115 uintptr_t vring_rx_addr; 116 117 sys_slist_t endpoints; 118 }; 119 120 struct rpmsg_mi_ctx_shm_cfg { 121 /** Physical address shared memory region. */ 122 uintptr_t addr; 123 124 /** Size shared memory region. */ 125 size_t size; 126 127 /** Internal counter. */ 128 unsigned int instance; 129 }; 130 131 /** @brief Configuration of the RPMsg instance. */ 132 struct rpmsg_mi_ctx_cfg { 133 134 /** Name of instance. */ 135 const char *name; 136 137 /** Stack area for k_work_q. */ 138 k_thread_stack_t *ipm_stack_area; 139 140 /** Size of stack area. */ 141 size_t ipm_stack_size; 142 143 /** Priority of work_q. */ 144 int ipm_work_q_prio; 145 146 /** Name of work_q thread. */ 147 const char *ipm_thread_name; 148 149 /** Name of the TX IPM channel. */ 150 const char *ipm_tx_name; 151 152 /** Name of the RX IPM channel. */ 153 const char *ipm_rx_name; 154 155 /** IPM message identifier. */ 156 unsigned int ipm_tx_id; 157 158 /** SHM struct. */ 159 struct rpmsg_mi_ctx_shm_cfg *shm; 160 }; 161 162 /** @brief Initialization of RPMsg instance. 163 * 164 * Each instance has an automatically allocated area of shared memory. 165 * 166 * @param ctx Pointer to the RPMsg instance. 167 * @param cfg Pointer to the configuration structure. 168 * @retval 0 if the operation was successful. 169 * -EINVAL when the incorrect parameters have been passed. 170 * -EIO when the configuration is not correct. 171 * -ENODEV failed to get TX or RX IPM handle. 172 * -ENOMEM when there is not enough memory to register virqueue. 173 * < 0 on other negative errno code, reported by rpmsg. 174 */ 175 int rpmsg_mi_ctx_init(struct rpmsg_mi_ctx *ctx, const struct rpmsg_mi_ctx_cfg *cfg); 176 177 /** @brief Register IPC endpoint. 178 * 179 * Registers IPC endpoint to enable communication with a remote device. 180 * 181 * @param ctx Pointer to the RPMsg instance. 182 * @param ept Pointer to endpoint object. 183 * @param cfg Pointer to the endpoint configuration. 184 * 185 * @retval -EINVAL One of the parameters is incorrect. 186 * @retval other errno code reported by rpmsg. 187 */ 188 int rpmsg_mi_ept_register(struct rpmsg_mi_ctx *ctx, 189 struct rpmsg_mi_ept *ept, 190 struct rpmsg_mi_ept_cfg *cfg); 191 192 /** @brief Send data using given IPC endpoint. 193 * 194 * Note: It is not possible to send a message of zero length. 195 * 196 * @param ept Endpoint object. 197 * @param data Pointer to the buffer to send through RPMsg. 198 * @param len Number of bytes to send. 199 * 200 * @retval Number of bytes it has sent or negative error value on failure. 201 */ 202 int rpmsg_mi_send(struct rpmsg_mi_ept *ept, const void *data, size_t len); 203 204 /** 205 * @} 206 */ 207 208 #ifdef __cplusplus 209 } 210 #endif 211 212 #endif /* ZEPHYR_INCLUDE_RPMSG_MULTIPLE_INNSTANCE_H_ */ 213