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