index 9187d69af0964eb6e59dec8d2ea436bd9477a4ab..9ddfa93c0edb0718e3d254ef5e68a3de23c1492a 100644 (file)
#include <string.h>
#include "openamp/rpmsg.h"
+#include "openamp/remoteproc.h"
#include "metal/utilities.h"
+#include "metal/alloc.h"
+#include "metal/atomic.h"
+#include "metal/cpu.h"
/* Macro to initialize vring HW info */
#define INIT_VRING_ALLOC_INFO(ring_info,vring_hw) \
* This function creates and initializes the remote device. The remote device
* encapsulates virtio device.
*
- * @param pdata - platform data for remote processor
+ * @param proc - pointer to hil_proc
* @param rdev - pointer to newly created remote device
- * @param dev-id - ID of device to create , remote cpu id
* @param role - role of the other device, Master or Remote
* @param channel_created - callback function for channel creation
* @param channel_destroyed - callback function for channel deletion
* @return - status of function execution
*
*/
-int rpmsg_rdev_init(void *pdata, struct remote_device **rdev, int dev_id, int role,
+int rpmsg_rdev_init(struct hil_proc *proc,
+ struct remote_device **rdev, int role,
rpmsg_chnl_cb_t channel_created,
rpmsg_chnl_cb_t channel_destroyed, rpmsg_rx_cb_t default_cb)
{
struct remote_device *rdev_loc;
struct virtio_device *virt_dev;
- struct hil_proc *proc;
struct proc_shm *shm;
int status;
+ if (!proc)
+ return RPMSG_ERR_PARAM;
/* Initialize HIL data structures for given device */
- proc = hil_create_proc(pdata, dev_id);
-
- if (!proc) {
- return RPMSG_ERR_DEV_ID;
- }
+ if (hil_init_proc(proc))
+ return RPMSG_ERR_DEV_INIT;
/* Create software representation of remote processor. */
- rdev_loc =
- (struct remote_device *)
- env_allocate_memory(sizeof(struct remote_device));
+ rdev_loc = (struct remote_device *)metal_allocate_memory(sizeof(struct remote_device));
if (!rdev_loc) {
return RPMSG_ERR_NO_MEM;
@@ -151,6 +151,9 @@ int rpmsg_rdev_init(void *pdata, struct remote_device **rdev, int dev_id, int ro
}
}
+ if (!rpmsg_rdev_remote_ready(rdev_loc))
+ return RPMSG_ERR_DEV_INIT;
+
/* Initialize endpoints list */
metal_list_init(&rdev_loc->rp_endpoints);
rdev->proc = 0;
}
- env_free_memory(rdev);
+ metal_free_memory(rdev);
}
/**
return RPMSG_SUCCESS;
}
+/**
+ * check if the remote is ready to start RPMsg communication
+ */
+int rpmsg_rdev_remote_ready(struct remote_device *rdev)
+{
+ struct virtio_device *vdev = &rdev->virt_dev;
+ uint8_t status;
+ if (rdev->role == RPMSG_MASTER) {
+ while (1) {
+ /* Busy wait until the remote is ready */
+ status = vdev->func->get_status(vdev);
+ if (status & VIRTIO_CONFIG_STATUS_DRIVER_OK)
+ return true;
+ metal_cpu_yield();
+ }
+ } else {
+ return true;
+ }
+ /* Never come here */
+ return false;
+}
+
+static void rpmsg_memset_io(struct metal_io_region *io, void *dst, int c, size_t count)
+{
+ if ((io->mem_flags & METAL_IO_MAPPED)) {
+ metal_memset_io(dst, c, count);
+ } else {
+ memset(dst, c, count);
+ }
+}
+
/**
*------------------------------------------------------------------------
* The rest of the file implements the virtio device interface as defined
@@ -405,13 +439,14 @@ int rpmsg_rdev_create_virtqueues(struct virtio_device *dev, int flags, int nvqs,
INIT_VRING_ALLOC_INFO(ring_info, vring_table[idx]);
if (rdev->role == RPMSG_REMOTE) {
- memset((void *)ring_info.vaddr, 0x00,
+ rpmsg_memset_io(vring_table[idx].io, (void *)ring_info.vaddr, 0x00,
vring_size(vring_table[idx].num_descs, vring_table[idx].align));
}
status =
virtqueue_create(dev, idx, (char *)names[idx], &ring_info,
callbacks[idx], hil_vring_notify,
+ rdev->proc->sh_buff.io,
&vqs[idx]);
if (status != RPMSG_SUCCESS) {
@@ -444,7 +479,7 @@ int rpmsg_rdev_create_virtqueues(struct virtio_device *dev, int flags, int nvqs,
sg.virt = buffer;
- memset(buffer, 0x00, RPMSG_BUFFER_SIZE);
+ rpmsg_memset_io(sg.io, buffer, 0x00, RPMSG_BUFFER_SIZE);
status =
virtqueue_add_buffer(rdev->rvq, &sg, 0, 1,
buffer);
@@ -460,14 +495,28 @@ int rpmsg_rdev_create_virtqueues(struct virtio_device *dev, int flags, int nvqs,
unsigned char rpmsg_rdev_get_status(struct virtio_device *dev)
{
- (void)dev;
- return 0;
+ struct hil_proc *proc = dev->device;
+ struct proc_vdev *pvdev = &proc->vdev;
+ struct fw_rsc_vdev *vdev_rsc = pvdev->vdev_info;
+
+ if (!vdev_rsc)
+ return -1;
+
+ return vdev_rsc->status;
}
void rpmsg_rdev_set_status(struct virtio_device *dev, unsigned char status)
{
- (void)dev;
- (void)status;
+ struct hil_proc *proc = dev->device;
+ struct proc_vdev *pvdev = &proc->vdev;
+ struct fw_rsc_vdev *vdev_rsc = pvdev->vdev_info;
+
+ if (!vdev_rsc)
+ return;
+
+ vdev_rsc->status = status;
+
+ atomic_thread_fence(memory_order_seq_cst);
}
uint32_t rpmsg_rdev_get_feature(struct virtio_device *dev)