359 lines
12 KiB
C
359 lines
12 KiB
C
/*
|
|
* Remote processor messaging
|
|
*
|
|
* Copyright (C) 2011 Texas Instruments, Inc.
|
|
* Copyright (C) 2011 Google, Inc.
|
|
* All rights reserved.
|
|
* Copyright (c) 2016 Freescale Semiconductor, Inc. All rights reserved.
|
|
*
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
*/
|
|
|
|
#ifndef _RPMSG_H_
|
|
#define _RPMSG_H_
|
|
|
|
#include <openamp/compiler.h>
|
|
#include <metal/mutex.h>
|
|
#include <metal/list.h>
|
|
#include <metal/utilities.h>
|
|
#include <string.h>
|
|
#include <stdbool.h>
|
|
#include <stdint.h>
|
|
|
|
#if defined __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
/* Configurable parameters */
|
|
#define RPMSG_NAME_SIZE (32)
|
|
#define RPMSG_ADDR_BMP_SIZE (128)
|
|
|
|
#define RPMSG_NS_EPT_ADDR (0x35)
|
|
#define RPMSG_ADDR_ANY 0xFFFFFFFF
|
|
|
|
/* Error macros. */
|
|
#define RPMSG_SUCCESS 0
|
|
#define RPMSG_ERROR_BASE -2000
|
|
#define RPMSG_ERR_NO_MEM (RPMSG_ERROR_BASE - 1)
|
|
#define RPMSG_ERR_NO_BUFF (RPMSG_ERROR_BASE - 2)
|
|
#define RPMSG_ERR_PARAM (RPMSG_ERROR_BASE - 3)
|
|
#define RPMSG_ERR_DEV_STATE (RPMSG_ERROR_BASE - 4)
|
|
#define RPMSG_ERR_BUFF_SIZE (RPMSG_ERROR_BASE - 5)
|
|
#define RPMSG_ERR_INIT (RPMSG_ERROR_BASE - 6)
|
|
#define RPMSG_ERR_ADDR (RPMSG_ERROR_BASE - 7)
|
|
|
|
struct rpmsg_endpoint;
|
|
struct rpmsg_device;
|
|
|
|
typedef int (*rpmsg_ept_cb)(struct rpmsg_endpoint *ept, void *data,
|
|
size_t len, uint32_t src, void *priv);
|
|
typedef void (*rpmsg_ns_unbind_cb)(struct rpmsg_endpoint *ept);
|
|
typedef void (*rpmsg_ns_bind_cb)(struct rpmsg_device *rdev,
|
|
const char *name, uint32_t dest);
|
|
|
|
/**
|
|
* struct rpmsg_endpoint - binds a local rpmsg address to its user
|
|
* @name:name of the service supported
|
|
* @rdev: pointer to the rpmsg device
|
|
* @addr: local address of the endpoint
|
|
* @dest_addr: address of the default remote endpoint binded.
|
|
* @cb: user rx callback, return value of this callback is reserved
|
|
* for future use, for now, only allow RPMSG_SUCCESS as return value.
|
|
* @ns_unbind_cb: end point service service unbind callback, called when remote
|
|
* ept is destroyed.
|
|
* @node: end point node.
|
|
* @addr: local rpmsg address
|
|
* @priv: private data for the driver's use
|
|
*
|
|
* In essence, an rpmsg endpoint represents a listener on the rpmsg bus, as
|
|
* it binds an rpmsg address with an rx callback handler.
|
|
*/
|
|
struct rpmsg_endpoint {
|
|
char name[RPMSG_NAME_SIZE];
|
|
struct rpmsg_device *rdev;
|
|
uint32_t addr;
|
|
uint32_t dest_addr;
|
|
rpmsg_ept_cb cb;
|
|
rpmsg_ns_unbind_cb ns_unbind_cb;
|
|
struct metal_list node;
|
|
void *priv;
|
|
};
|
|
|
|
/**
|
|
* struct rpmsg_device_ops - RPMsg device operations
|
|
* @send_offchannel_raw: send RPMsg data
|
|
*/
|
|
struct rpmsg_device_ops {
|
|
int (*send_offchannel_raw)(struct rpmsg_device *rdev,
|
|
uint32_t src, uint32_t dst,
|
|
const void *data, int size, int wait);
|
|
};
|
|
|
|
/**
|
|
* struct rpmsg_device - representation of a RPMsg device
|
|
* @endpoints: list of endpoints
|
|
* @ns_ept: name service endpoint
|
|
* @bitmap: table endpoin address allocation.
|
|
* @lock: mutex lock for rpmsg management
|
|
* @ns_bind_cb: callback handler for name service announcement without local
|
|
* endpoints waiting to bind.
|
|
* @ops: RPMsg device operations
|
|
*/
|
|
struct rpmsg_device {
|
|
struct metal_list endpoints;
|
|
struct rpmsg_endpoint ns_ept;
|
|
unsigned long bitmap[metal_bitmap_longs(RPMSG_ADDR_BMP_SIZE)];
|
|
metal_mutex_t lock;
|
|
rpmsg_ns_bind_cb ns_bind_cb;
|
|
struct rpmsg_device_ops ops;
|
|
};
|
|
|
|
/**
|
|
* rpmsg_send_offchannel_raw() - send a message across to the remote processor,
|
|
* specifying source and destination address.
|
|
* @ept: the rpmsg endpoint
|
|
* @data: payload of the message
|
|
* @len: length of the payload
|
|
*
|
|
* This function sends @data of length @len to the remote @dst address from
|
|
* the source @src address.
|
|
* The message will be sent to the remote processor which the channel belongs
|
|
* to.
|
|
* In case there are no TX buffers available, the function will block until
|
|
* one becomes available, or a timeout of 15 seconds elapses. When the latter
|
|
* happens, -ERESTARTSYS is returned.
|
|
*
|
|
* Returns number of bytes it has sent or negative error value on failure.
|
|
*/
|
|
int rpmsg_send_offchannel_raw(struct rpmsg_endpoint *ept, uint32_t src,
|
|
uint32_t dst, const void *data, int size,
|
|
int wait);
|
|
|
|
/**
|
|
* rpmsg_send() - send a message across to the remote processor
|
|
* @ept: the rpmsg endpoint
|
|
* @data: payload of the message
|
|
* @len: length of the payload
|
|
*
|
|
* This function sends @data of length @len based on the @ept.
|
|
* The message will be sent to the remote processor which the channel belongs
|
|
* to, using @ept's source and destination addresses.
|
|
* In case there are no TX buffers available, the function will block until
|
|
* one becomes available, or a timeout of 15 seconds elapses. When the latter
|
|
* happens, -ERESTARTSYS is returned.
|
|
*
|
|
* Returns number of bytes it has sent or negative error value on failure.
|
|
*/
|
|
static inline int rpmsg_send(struct rpmsg_endpoint *ept, const void *data,
|
|
int len)
|
|
{
|
|
if (ept->dest_addr == RPMSG_ADDR_ANY)
|
|
return RPMSG_ERR_ADDR;
|
|
return rpmsg_send_offchannel_raw(ept, ept->addr, ept->dest_addr, data,
|
|
len, true);
|
|
}
|
|
|
|
/**
|
|
* rpmsg_sendto() - send a message across to the remote processor, specify dst
|
|
* @ept: the rpmsg endpoint
|
|
* @data: payload of message
|
|
* @len: length of payload
|
|
* @dst: destination address
|
|
*
|
|
* This function sends @data of length @len to the remote @dst address.
|
|
* The message will be sent to the remote processor which the @ept
|
|
* channel belongs to, using @ept's source address.
|
|
* In case there are no TX buffers available, the function will block until
|
|
* one becomes available, or a timeout of 15 seconds elapses. When the latter
|
|
* happens, -ERESTARTSYS is returned.
|
|
*
|
|
* Returns number of bytes it has sent or negative error value on failure.
|
|
*/
|
|
static inline int rpmsg_sendto(struct rpmsg_endpoint *ept, const void *data,
|
|
int len, uint32_t dst)
|
|
{
|
|
return rpmsg_send_offchannel_raw(ept, ept->addr, dst, data, len, true);
|
|
}
|
|
|
|
/**
|
|
* rpmsg_send_offchannel() - send a message using explicit src/dst addresses
|
|
* @ept: the rpmsg endpoint
|
|
* @src: source address
|
|
* @dst: destination address
|
|
* @data: payload of message
|
|
* @len: length of payload
|
|
*
|
|
* This function sends @data of length @len to the remote @dst address,
|
|
* and uses @src as the source address.
|
|
* The message will be sent to the remote processor which the @ept
|
|
* channel belongs to.
|
|
* In case there are no TX buffers available, the function will block until
|
|
* one becomes available, or a timeout of 15 seconds elapses. When the latter
|
|
* happens, -ERESTARTSYS is returned.
|
|
*
|
|
* Returns number of bytes it has sent or negative error value on failure.
|
|
*/
|
|
static inline int rpmsg_send_offchannel(struct rpmsg_endpoint *ept,
|
|
uint32_t src, uint32_t dst,
|
|
const void *data, int len)
|
|
{
|
|
return rpmsg_send_offchannel_raw(ept, src, dst, data, len, true);
|
|
}
|
|
|
|
/**
|
|
* rpmsg_trysend() - send a message across to the remote processor
|
|
* @ept: the rpmsg endpoint
|
|
* @data: payload of message
|
|
* @len: length of payload
|
|
*
|
|
* This function sends @data of length @len on the @ept channel.
|
|
* The message will be sent to the remote processor which the @ept
|
|
* channel belongs to, using @ept's source and destination addresses.
|
|
* In case there are no TX buffers available, the function will immediately
|
|
* return -ENOMEM without waiting until one becomes available.
|
|
*
|
|
* Returns number of bytes it has sent or negative error value on failure.
|
|
*/
|
|
static inline int rpmsg_trysend(struct rpmsg_endpoint *ept, const void *data,
|
|
int len)
|
|
{
|
|
if (ept->dest_addr == RPMSG_ADDR_ANY)
|
|
return RPMSG_ERR_ADDR;
|
|
return rpmsg_send_offchannel_raw(ept, ept->addr, ept->dest_addr, data,
|
|
len, false);
|
|
}
|
|
|
|
/**
|
|
* rpmsg_trysendto() - send a message across to the remote processor,
|
|
* specify dst
|
|
* @ept: the rpmsg endpoint
|
|
* @data: payload of message
|
|
* @len: length of payload
|
|
* @dst: destination address
|
|
*
|
|
* This function sends @data of length @len to the remote @dst address.
|
|
* The message will be sent to the remote processor which the @ept
|
|
* channel belongs to, using @ept's source address.
|
|
* In case there are no TX buffers available, the function will immediately
|
|
* return -ENOMEM without waiting until one becomes available.
|
|
*
|
|
* Returns number of bytes it has sent or negative error value on failure.
|
|
*/
|
|
static inline int rpmsg_trysendto(struct rpmsg_endpoint *ept, const void *data,
|
|
int len, uint32_t dst)
|
|
{
|
|
return rpmsg_send_offchannel_raw(ept, ept->addr, dst, data, len, false);
|
|
}
|
|
|
|
/**
|
|
* rpmsg_trysend_offchannel() - send a message using explicit src/dst addresses
|
|
* @ept: the rpmsg endpoint
|
|
* @src: source address
|
|
* @dst: destination address
|
|
* @data: payload of message
|
|
* @len: length of payload
|
|
*
|
|
* This function sends @data of length @len to the remote @dst address,
|
|
* and uses @src as the source address.
|
|
* The message will be sent to the remote processor which the @ept
|
|
* channel belongs to.
|
|
* In case there are no TX buffers available, the function will immediately
|
|
* return -ENOMEM without waiting until one becomes available.
|
|
*
|
|
* Returns number of bytes it has sent or negative error value on failure.
|
|
*/
|
|
static inline int rpmsg_trysend_offchannel(struct rpmsg_endpoint *ept,
|
|
uint32_t src, uint32_t dst,
|
|
const void *data, int len)
|
|
{
|
|
return rpmsg_send_offchannel_raw(ept, src, dst, data, len, false);
|
|
}
|
|
|
|
/**
|
|
* rpmsg_init_ept - initialize rpmsg endpoint
|
|
*
|
|
* Initialize an RPMsg endpoint with a name, source address,
|
|
* remoteproc address, endpoitn callback, and destroy endpoint callback.
|
|
*
|
|
* @ept: pointer to rpmsg endpoint
|
|
* @name: service name associated to the endpoint
|
|
* @src: local address of the endpoint
|
|
* @dest: target address of the endpoint
|
|
* @cb: endpoint callback
|
|
* @ns_unbind_cb: end point service unbind callback, called when remote ept is
|
|
* destroyed.
|
|
*/
|
|
static inline void rpmsg_init_ept(struct rpmsg_endpoint *ept,
|
|
const char *name,
|
|
uint32_t src, uint32_t dest,
|
|
rpmsg_ept_cb cb,
|
|
rpmsg_ns_unbind_cb ns_unbind_cb)
|
|
{
|
|
strncpy(ept->name, name, sizeof(ept->name));
|
|
ept->addr = src;
|
|
ept->dest_addr = dest;
|
|
ept->cb = cb;
|
|
ept->ns_unbind_cb = ns_unbind_cb;
|
|
}
|
|
|
|
/**
|
|
* rpmsg_create_ept - create rpmsg endpoint and register it to rpmsg device
|
|
*
|
|
* Create a RPMsg endpoint, initialize it with a name, source address,
|
|
* remoteproc address, endpoitn callback, and destroy endpoint callback,
|
|
* and register it to the RPMsg device.
|
|
*
|
|
* @ept: pointer to rpmsg endpoint
|
|
* @name: service name associated to the endpoint
|
|
* @src: local address of the endpoint
|
|
* @dest: target address of the endpoint
|
|
* @cb: endpoint callback
|
|
* @ns_unbind_cb: end point service unbind callback, called when remote ept is
|
|
* destroyed.
|
|
*
|
|
* In essence, an rpmsg endpoint represents a listener on the rpmsg bus, as
|
|
* it binds an rpmsg address with an rx callback handler.
|
|
*
|
|
* Rpmsg client should create an endpoint to discuss with remote. rpmsg client
|
|
* provide at least a channel name, a callback for message notification and by
|
|
* default endpoint source address should be set to RPMSG_ADDR_ANY.
|
|
*
|
|
* As an option Some rpmsg clients can specify an endpoint with a specific
|
|
* source address.
|
|
*/
|
|
|
|
int rpmsg_create_ept(struct rpmsg_endpoint *ept, struct rpmsg_device *rdev,
|
|
const char *name, uint32_t src, uint32_t dest,
|
|
rpmsg_ept_cb cb, rpmsg_ns_unbind_cb ns_unbind_cb);
|
|
|
|
/**
|
|
* rpmsg_destroy_ept - destroy rpmsg endpoint and unregister it from rpmsg
|
|
* device
|
|
*
|
|
* @ept: pointer to the rpmsg endpoint
|
|
*
|
|
* It unregisters the rpmsg endpoint from the rpmsg device and calls the
|
|
* destroy endpoint callback if it is provided.
|
|
*/
|
|
void rpmsg_destroy_ept(struct rpmsg_endpoint *ept);
|
|
|
|
/**
|
|
* is_rpmsg_ept_ready - check if the rpmsg endpoint ready to send
|
|
*
|
|
* @ept: pointer to rpmsg endpoint
|
|
*
|
|
* Returns 1 if the rpmsg endpoint has both local addr and destination
|
|
* addr set, 0 otherwise
|
|
*/
|
|
static inline unsigned int is_rpmsg_ept_ready(struct rpmsg_endpoint *ept)
|
|
{
|
|
return (ept->dest_addr != RPMSG_ADDR_ANY &&
|
|
ept->addr != RPMSG_ADDR_ANY);
|
|
}
|
|
|
|
#if defined __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#endif /* _RPMSG_H_ */
|