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