/* * Copyright (c) 2021 Nordic Semiconductor ASA * * SPDX-License-Identifier: Apache-2.0 */ #ifndef ZEPHYR_INCLUDE_RPMSG_MULTIPLE_INSTANCE_H_ #define ZEPHYR_INCLUDE_RPMSG_MULTIPLE_INSTANCE_H_ #include #include #include #include #ifdef __cplusplus extern "C" { #endif /** * @brief RPMsg multiple instance API * @defgroup rpmsg_multiple_instance_api RPMsg multiple instance APIs * @{ */ #define VDEV_START_ADDR CONFIG_RPMSG_MULTI_INSTANCE_SHM_BASE_ADDRESS #define VDEV_SIZE CONFIG_RPMSG_MULTI_INSTANCE_SHM_SIZE #define SHM_START_ADDR VDEV_START_ADDR #define SHM_SIZE VDEV_SIZE #define VRING_ALIGNMENT (4) /**< Alignment of vring buffer. */ #define VDEV_STATUS_SIZE (0x4) /**< Size of status region. */ /** @brief Event callback structure. * * It is registered during endpoint registration. * This structure is packed into the endpoint configuration. */ struct rpmsg_mi_cb { /** @brief Bind was successful. * * @param priv Private user data. */ void (*bound)(void *priv); /** @brief New packet arrived. * * @param data Pointer to data buffer. * @param len Length of @a data. * @param priv Private user data. */ void (*received)(const void *data, size_t len, void *priv); }; /** @brief Endpoint instance. */ struct rpmsg_mi_ept { /** Name of endpoint. */ const char *name; /** RPMsg endpoint. */ struct rpmsg_endpoint ep; /** Event callback structure. */ struct rpmsg_mi_cb *cb; /** Private user data. */ void *priv; /** Endpoint was bound. */ volatile bool bound; /** Linked list node. */ sys_snode_t node; }; /** @brief Endpoint configuration. */ struct rpmsg_mi_ept_cfg { /** Name of endpoint. */ const char *name; /** Event callback structure. */ struct rpmsg_mi_cb *cb; /** Private user data. */ void *priv; }; /** @brief Struct describing the context of the RPMsg instance. */ struct rpmsg_mi_ctx { const char *name; struct k_work_q ipm_work_q; struct k_work ipm_work; const struct device *ipm_tx_handle; const struct device *ipm_rx_handle; unsigned int ipm_tx_id; uintptr_t shm_status_reg_addr; struct metal_io_region *shm_io; struct metal_device shm_device; metal_phys_addr_t shm_physmap[1]; struct rpmsg_virtio_device rvdev; struct rpmsg_virtio_shm_pool shpool; struct rpmsg_device *rdev; struct virtqueue *vq[2]; struct virtio_vring_info rvrings[2]; struct virtio_device vdev; uintptr_t vring_tx_addr; uintptr_t vring_rx_addr; sys_slist_t endpoints; }; struct rpmsg_mi_ctx_shm_cfg { /** Physical address shared memory region. */ uintptr_t addr; /** Size shared memory region. */ size_t size; /** Internal counter. */ unsigned int instance; }; /** @brief Configuration of the RPMsg instance. */ struct rpmsg_mi_ctx_cfg { /** Name of instance. */ const char *name; /** Stack area for k_work_q. */ k_thread_stack_t *ipm_stack_area; /** Size of stack area. */ size_t ipm_stack_size; /** Priority of work_q. */ int ipm_work_q_prio; /** Name of work_q thread. */ const char *ipm_thread_name; /** Name of the TX IPM channel. */ const char *ipm_tx_name; /** Name of the RX IPM channel. */ const char *ipm_rx_name; /** IPM message identifier. */ unsigned int ipm_tx_id; /** SHM struct. */ struct rpmsg_mi_ctx_shm_cfg *shm; }; /** @brief Initialization of RPMsg instance. * * Each instance has an automatically allocated area of shared memory. * * @param ctx Pointer to the RPMsg instance. * @param cfg Pointer to the configuration structure. * @retval 0 if the operation was successful. * -EINVAL when the incorrect parameters have been passed. * -EIO when the configuration is not correct. * -ENODEV failed to get TX or RX IPM handle. * -ENOMEM when there is not enough memory to register virqueue. * < 0 on other negative errno code, reported by rpmsg. */ int rpmsg_mi_ctx_init(struct rpmsg_mi_ctx *ctx, const struct rpmsg_mi_ctx_cfg *cfg); /** @brief Register IPC endpoint. * * Registers IPC endpoint to enable communication with a remote device. * * @param ctx Pointer to the RPMsg instance. * @param ept Pointer to endpoint object. * @param cfg Pointer to the endpoint configuration. * * @retval -EINVAL One of the parameters is incorrect. * @retval other errno code reported by rpmsg. */ int rpmsg_mi_ept_register(struct rpmsg_mi_ctx *ctx, struct rpmsg_mi_ept *ept, struct rpmsg_mi_ept_cfg *cfg); /** @brief Send data using given IPC endpoint. * * Note: It is not possible to send a message of zero length. * * @param ept Endpoint object. * @param data Pointer to the buffer to send through RPMsg. * @param len Number of bytes to send. * * @retval Number of bytes it has sent or negative error value on failure. */ int rpmsg_mi_send(struct rpmsg_mi_ept *ept, const void *data, size_t len); /** * @} */ #ifdef __cplusplus } #endif #endif /* ZEPHYR_INCLUDE_RPMSG_MULTIPLE_INNSTANCE_H_ */