1 /* 2 * Copyright (c) 2014, Mentor Graphics Corporation 3 * Copyright (c) 2015 Xilinx, Inc. 4 * Copyright (c) 2016 Freescale Semiconductor, Inc. 5 * Copyright 2016-2024 NXP 6 * Copyright 2021 ACRIOS Systems s.r.o. 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions are met: 11 * 12 * 1. Redistributions of source code must retain the above copyright notice, 13 * this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright notice, 15 * this list of conditions and the following disclaimer in the documentation 16 * and/or other materials provided with the distribution. 17 * 3. Neither the name of the copyright holder nor the names of its 18 * contributors may be used to endorse or promote products derived from this 19 * software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 22 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 25 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 * POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 #ifndef RPMSG_LITE_H_ 35 #define RPMSG_LITE_H_ 36 37 #if defined(__cplusplus) 38 extern "C" { 39 #endif 40 41 #include <stddef.h> 42 #include "rpmsg_compiler.h" 43 #include "virtqueue.h" 44 #include "rpmsg_env.h" 45 #include "llist.h" 46 #include "rpmsg_default_config.h" 47 48 //! @addtogroup rpmsg_lite 49 //! @{ 50 51 /******************************************************************************* 52 * Definitions 53 ******************************************************************************/ 54 55 #define RL_VERSION "5.1.2" /*!< Current RPMsg Lite version */ 56 57 /* Shared memory "allocator" parameters */ 58 #define RL_WORD_SIZE (sizeof(uint32_t)) 59 #define RL_WORD_ALIGN_UP(a) \ 60 (((((uintptr_t)(a)) & (RL_WORD_SIZE - 1U)) != 0U) ? ((((uintptr_t)(a)) & (~(RL_WORD_SIZE - 1U))) + 4U) : \ 61 ((uintptr_t)(a))) 62 #define RL_WORD_ALIGN_DOWN(a) \ 63 (((((uintptr_t)(a)) & (RL_WORD_SIZE - 1U)) != 0U) ? (((uintptr_t)(a)) & (~(RL_WORD_SIZE - 1U))) : ((uintptr_t)(a))) 64 65 /* Definitions for device types , null pointer, etc.*/ 66 #define RL_SUCCESS (0) 67 #define RL_NULL ((void *)0) 68 #define RL_REMOTE (0) 69 #define RL_MASTER (1) 70 #define RL_TRUE (1UL) 71 #define RL_FALSE (0UL) 72 #define RL_ADDR_ANY (0xFFFFFFFFU) 73 #define RL_RELEASE (0) 74 #define RL_HOLD (1) 75 #define RL_DONT_BLOCK (0) 76 #define RL_BLOCK (~0UL) 77 78 /* Error macros. */ 79 #define RL_ERRORS_BASE (-5000) 80 #define RL_ERR_NO_MEM (RL_ERRORS_BASE - 1) 81 #define RL_ERR_BUFF_SIZE (RL_ERRORS_BASE - 2) 82 #define RL_ERR_PARAM (RL_ERRORS_BASE - 3) 83 #define RL_ERR_DEV_ID (RL_ERRORS_BASE - 4) 84 #define RL_ERR_MAX_VQ (RL_ERRORS_BASE - 5) 85 #define RL_ERR_NO_BUFF (RL_ERRORS_BASE - 6) 86 #define RL_NOT_READY (RL_ERRORS_BASE - 7) 87 #define RL_ALREADY_DONE (RL_ERRORS_BASE - 8) 88 89 /* Init flags */ 90 #define RL_NO_FLAGS (0U) 91 92 /* rpmsg_std_hdr contains a reserved field, 93 * this implementation of RPMSG uses this reserved 94 * field to hold the idx and totlen of the buffer 95 * not being returned to the vring in the receive 96 * callback function. This way, the no-copy API 97 * can use this field to return the buffer later. 98 */ 99 struct rpmsg_hdr_reserved 100 { 101 uint16_t rfu; /* reserved for future usage */ 102 uint16_t idx; 103 }; 104 105 RL_PACKED_BEGIN 106 /*! 107 * Common header for all rpmsg messages. 108 * Every message sent/received on the rpmsg bus begins with this header. 109 */ 110 struct rpmsg_std_hdr 111 { 112 uint32_t src; /*!< source endpoint address */ 113 uint32_t dst; /*!< destination endpoint address */ 114 struct rpmsg_hdr_reserved reserved; /*!< reserved for future use */ 115 uint16_t len; /*!< length of payload (in bytes) */ 116 uint16_t flags; /*!< message flags */ 117 } RL_PACKED_END; 118 119 RL_PACKED_BEGIN 120 /*! 121 * Common message structure. 122 * Contains the header and the payload. 123 */ 124 struct rpmsg_std_msg 125 { 126 struct rpmsg_std_hdr hdr; /*!< RPMsg message header */ 127 uint8_t data[1]; /*!< bytes of message payload data */ 128 } RL_PACKED_END; 129 130 /*! \typedef rl_ept_rx_cb_t 131 \brief Receive callback function type. 132 */ 133 typedef int32_t (*rl_ept_rx_cb_t)(void *payload, uint32_t payload_len, uint32_t src, void *priv); 134 135 /*! 136 * RPMsg Lite Endpoint structure 137 */ 138 struct rpmsg_lite_endpoint 139 { 140 uint32_t addr; /*!< endpoint address */ 141 rl_ept_rx_cb_t rx_cb; /*!< ISR callback function */ 142 void *rx_cb_data; /*!< ISR callback data */ 143 void *rfu; /*!< reserved for future usage */ 144 /* 16 bytes aligned on 32bit architecture */ 145 }; 146 147 /*! 148 * RPMsg Lite Endpoint static context 149 */ 150 struct rpmsg_lite_ept_static_context 151 { 152 struct rpmsg_lite_endpoint ept; /*!< memory for endpoint structure */ 153 struct llist node; /*!< memory for linked list node structure */ 154 }; 155 156 /*! 157 * Structure describing the local instance 158 * of RPMSG lite communication stack and 159 * holds all runtime variables needed internally 160 * by the stack. 161 */ 162 struct rpmsg_lite_instance 163 { 164 struct virtqueue *rvq; /*!< receive virtqueue */ 165 struct virtqueue *tvq; /*!< transmit virtqueue */ 166 struct llist *rl_endpoints; /*!< linked list of endpoints */ 167 LOCK *lock; /*!< local RPMsg Lite mutex lock */ 168 #if defined(RL_USE_STATIC_API) && (RL_USE_STATIC_API == 1) 169 LOCK_STATIC_CONTEXT lock_static_ctxt; /*!< Static context for lock object creation */ 170 #endif 171 uint32_t link_state; /*!< state of the link, up/down*/ 172 char *sh_mem_base; /*!< base address of the shared memory */ 173 uint32_t sh_mem_remaining; /*!< amount of remaining unused buffers in shared memory */ 174 uint32_t sh_mem_total; /*!< total amount of buffers in shared memory */ 175 struct virtqueue_ops const *vq_ops; /*!< ops functions table pointer */ 176 #if defined(RL_USE_ENVIRONMENT_CONTEXT) && (RL_USE_ENVIRONMENT_CONTEXT == 1) 177 void *env; /*!< pointer to the environment layer context */ 178 #endif 179 180 #if defined(RL_USE_STATIC_API) && (RL_USE_STATIC_API == 1) 181 struct vq_static_context vq_ctxt[2]; 182 #endif 183 uint32_t link_id; /*!< linkID of this rpmsg_lite instance */ 184 }; 185 186 /******************************************************************************* 187 * API 188 ******************************************************************************/ 189 190 /* Exported API functions */ 191 192 /*! 193 * @brief Initializes the RPMsg-Lite communication stack. 194 * Must be called prior to any other RPMSG lite API. 195 * To be called by the master side. 196 * 197 * @param shmem_addr Shared memory base used for this instance of RPMsg-Lite 198 * @param shmem_length Length of memory area given by previous parameter 199 * @param link_id Link ID used to define the rpmsg-lite instance, see rpmsg_platform.h 200 * @param init_flags Initialization flags 201 * @param env_cfg Initialization data for the environement RPMsg-Lite layer, used when 202 * the environment layer uses its own context (RL_USE_ENVIRONMENT_CONTEXT) 203 * @param static_context RPMsg-Lite preallocated context pointer, used in case of static api (RL_USE_STATIC_API) 204 * 205 * @return New RPMsg-Lite instance pointer or RL_NULL. 206 * 207 */ 208 #if defined(RL_USE_STATIC_API) && (RL_USE_STATIC_API == 1) 209 struct rpmsg_lite_instance *rpmsg_lite_master_init(void *shmem_addr, 210 size_t shmem_length, 211 uint32_t link_id, 212 uint32_t init_flags, 213 struct rpmsg_lite_instance *static_context); 214 #elif defined(RL_USE_ENVIRONMENT_CONTEXT) && (RL_USE_ENVIRONMENT_CONTEXT == 1) 215 struct rpmsg_lite_instance *rpmsg_lite_master_init( 216 void *shmem_addr, size_t shmem_length, uint32_t link_id, uint32_t init_flags, void *env_cfg); 217 #else 218 struct rpmsg_lite_instance *rpmsg_lite_master_init(void *shmem_addr, 219 size_t shmem_length, 220 uint32_t link_id, 221 uint32_t init_flags); 222 #endif 223 224 /** 225 * @brief Initializes the RPMsg-Lite communication stack. 226 * Must be called prior to any other RPMsg-Lite API. 227 * To be called by the remote side. 228 * 229 * @param shmem_addr Shared memory base used for this instance of RPMsg-Lite 230 * @param link_id Link ID used to define the rpmsg-lite instance, see rpmsg_platform.h 231 * @param init_flags Initialization flags 232 * @param env_cfg Initialization data for the environement RPMsg-Lite layer, used when 233 * the environment layer uses its own context (RL_USE_ENVIRONMENT_CONTEXT) 234 * @param static_context RPMsg-Lite preallocated context pointer, used in case of static api (RL_USE_STATIC_API) 235 * 236 * @return New RPMsg-Lite instance pointer or RL_NULL. 237 * 238 */ 239 #if defined(RL_USE_STATIC_API) && (RL_USE_STATIC_API == 1) 240 struct rpmsg_lite_instance *rpmsg_lite_remote_init(void *shmem_addr, 241 uint32_t link_id, 242 uint32_t init_flags, 243 struct rpmsg_lite_instance *static_context); 244 #elif defined(RL_USE_ENVIRONMENT_CONTEXT) && (RL_USE_ENVIRONMENT_CONTEXT == 1) 245 struct rpmsg_lite_instance *rpmsg_lite_remote_init(void *shmem_addr, 246 uint32_t link_id, 247 uint32_t init_flags, 248 void *env_cfg); 249 #else 250 struct rpmsg_lite_instance *rpmsg_lite_remote_init(void *shmem_addr, uint32_t link_id, uint32_t init_flags); 251 #endif 252 253 /*! 254 * 255 * @brief Deinitialized the RPMsg-Lite communication stack 256 * This function always succeeds. 257 * rpmsg_lite_init() can be called again after this 258 * function has been called. 259 * 260 * @param rpmsg_lite_dev RPMsg-Lite instance 261 * 262 * @return Status of function execution, RL_SUCCESS on success. 263 */ 264 int32_t rpmsg_lite_deinit(struct rpmsg_lite_instance *rpmsg_lite_dev); 265 266 /*! 267 * @brief Create a new rpmsg endpoint, which can be used 268 * for communication. 269 * 270 * @param rpmsg_lite_dev RPMsg-Lite instance 271 * @param addr Desired address, RL_ADDR_ANY for automatic selection 272 * @param rx_cb Callback function called on receive 273 * @param rx_cb_data Callback data pointer, passed to rx_cb 274 * @param ept_context Endpoint preallocated context pointer, used in case of static api (RL_USE_STATIC_API) 275 * 276 * @return RL_NULL on error, new endpoint pointer on success. 277 * 278 */ 279 #if defined(RL_USE_STATIC_API) && (RL_USE_STATIC_API == 1) 280 struct rpmsg_lite_endpoint *rpmsg_lite_create_ept(struct rpmsg_lite_instance *rpmsg_lite_dev, 281 uint32_t addr, 282 rl_ept_rx_cb_t rx_cb, 283 void *rx_cb_data, 284 struct rpmsg_lite_ept_static_context *ept_context); 285 #else 286 struct rpmsg_lite_endpoint *rpmsg_lite_create_ept(struct rpmsg_lite_instance *rpmsg_lite_dev, 287 uint32_t addr, 288 rl_ept_rx_cb_t rx_cb, 289 void *rx_cb_data); 290 #endif 291 292 /*! 293 * @brief This function deletes rpmsg endpoint and performs cleanup. 294 * 295 * @param rpmsg_lite_dev RPMsg-Lite instance 296 * @param rl_ept Pointer to endpoint to destroy 297 * 298 */ 299 int32_t rpmsg_lite_destroy_ept(struct rpmsg_lite_instance *rpmsg_lite_dev, struct rpmsg_lite_endpoint *rl_ept); 300 301 /*! 302 * 303 * @brief Sends a message contained in data field of length size 304 * to the remote endpoint with address dst. 305 * ept->addr is used as source address in the rpmsg header 306 * of the message being sent. 307 * 308 * @param rpmsg_lite_dev RPMsg-Lite instance 309 * @param ept Sender endpoint 310 * @param dst Remote endpoint address 311 * @param data Payload buffer 312 * @param size Size of payload, in bytes 313 * @param timeout Timeout in ms, 0 if nonblocking 314 * 315 * @return Status of function execution, RL_SUCCESS on success. 316 * 317 */ 318 int32_t rpmsg_lite_send(struct rpmsg_lite_instance *rpmsg_lite_dev, 319 struct rpmsg_lite_endpoint *ept, 320 uint32_t dst, 321 char *data, 322 uint32_t size, 323 uintptr_t timeout); 324 325 /*! 326 * @brief Function to get the link state 327 * 328 * @param rpmsg_lite_dev RPMsg-Lite instance pointer 329 * 330 * @return RL_TRUE when link up, RL_FALSE when down. 331 * 332 */ 333 uint32_t rpmsg_lite_is_link_up(struct rpmsg_lite_instance *rpmsg_lite_dev); 334 335 /*! 336 * @brief Function to wait until the link is up. Returns RL_TRUE 337 * once the link_state is set or RL_FALSE in case of timeout. 338 * 339 * @param rpmsg_lite_dev RPMsg-Lite instance pointer 340 * @param timeout Timeout in ms, 0 if nonblocking 341 * 342 * @return RL_TRUE when link up, RL_FALSE when timeout. 343 * 344 */ 345 uint32_t rpmsg_lite_wait_for_link_up(struct rpmsg_lite_instance *rpmsg_lite_dev, uint32_t timeout); 346 347 #if defined(RL_API_HAS_ZEROCOPY) && (RL_API_HAS_ZEROCOPY == 1) 348 349 /*! 350 * @brief Releases the rx buffer for future reuse in vring. 351 * This API can be called at process context when the 352 * message in rx buffer is processed. 353 * 354 * @param rpmsg_lite_dev RPMsg-Lite instance 355 * @param rxbuf Rx buffer with message payload 356 * 357 * @return Status of function execution, RL_SUCCESS on success. 358 */ 359 int32_t rpmsg_lite_release_rx_buffer(struct rpmsg_lite_instance *rpmsg_lite_dev, void *rxbuf); 360 361 /*! 362 * @brief Allocates the tx buffer for message payload. 363 * 364 * This API can only be called at process context to get the tx buffer in vring. By this way, the 365 * application can directly put its message into the vring tx buffer without copy from an application buffer. 366 * It is the application responsibility to correctly fill the allocated tx buffer by data and passing correct 367 * parameters to the rpmsg_lite_send_nocopy() function to perform data no-copy-send mechanism. 368 * 369 * @param rpmsg_lite_dev RPMsg-Lite instance 370 * @param[in] size Pointer to store maximum payload size available 371 * @param[in] timeout Integer, wait upto timeout ms or not for buffer to become available 372 * 373 * @return The tx buffer address on success and RL_NULL on failure. 374 * 375 * @see rpmsg_lite_send_nocopy 376 */ 377 void *rpmsg_lite_alloc_tx_buffer(struct rpmsg_lite_instance *rpmsg_lite_dev, uint32_t *size, uintptr_t timeout); 378 379 /*! 380 * @brief Sends a message in tx buffer allocated by rpmsg_lite_alloc_tx_buffer() 381 * 382 * This function sends txbuf of length len to the remote dst address, 383 * and uses ept->addr as the source address. 384 * The application has to take the responsibility for: 385 * 1. tx buffer allocation (rpmsg_lite_alloc_tx_buffer()) 386 * 2. filling the data to be sent into the pre-allocated tx buffer 387 * 3. not exceeding the buffer size when filling the data 388 * 4. data cache coherency 389 * 390 * After the rpmsg_lite_send_nocopy() function is issued the tx buffer is no more owned 391 * by the sending task and must not be touched anymore unless the rpmsg_lite_send_nocopy() 392 * function fails and returns an error. 393 * 394 * @param rpmsg_lite_dev RPMsg-Lite instance 395 * @param[in] ept Sender endpoint pointer 396 * @param[in] dst Destination address 397 * @param[in] data TX buffer with message filled 398 * @param[in] size Length of payload 399 * 400 * @return 0 on success and an appropriate error value on failure. 401 * 402 * @see rpmsg_lite_alloc_tx_buffer 403 */ 404 int32_t rpmsg_lite_send_nocopy(struct rpmsg_lite_instance *rpmsg_lite_dev, 405 struct rpmsg_lite_endpoint *ept, 406 uint32_t dst, 407 void *data, 408 uint32_t size); 409 #endif /* RL_API_HAS_ZEROCOPY */ 410 411 //! @} 412 413 #if defined(__cplusplus) 414 } 415 #endif 416 417 #endif /* RPMSG_LITE_H_ */ 418