@@ -1319,6 +1319,12 @@ S: Maintained
T: git https://source.denx.de/u-boot/custodians/u-boot-nand-flash.git
F: drivers/mtd/nand/raw/
+REMOTEPROC
+M: Tanmay Shah <tanmay.shah@amd.com>
+S: Maintained
+F: drivers/remoteproc/rproc_virtio.c
+F: include/rproc_virtio.h
+
RISC-V
M: Rick Chen <rick@andestech.com>
M: Leo <ycliang@andestech.com>
@@ -102,4 +102,15 @@ config REMOTEPROC_TI_IPU
help
Say 'y' here to add support for TI' K3 remoteproc driver.
+config REMOTEPROC_VIRTIO
+ bool "Support remoteproc virtio devices"
+ select REMOTEPROC
+ select VIRTIO
+ depends on DM
+ help
+ Say 'y' here to add support of remoteproc virtio devices.
+ rproc_virtio is virtio transport layer driver. The transport
+ drivers provide a set of ops for the real virtio device
+ driver to call.
+
endmenu
@@ -16,3 +16,4 @@ obj-$(CONFIG_REMOTEPROC_TI_K3_R5F) += ti_k3_r5f_rproc.o
obj-$(CONFIG_REMOTEPROC_TI_POWER) += ti_power_proc.o
obj-$(CONFIG_REMOTEPROC_TI_PRU) += pru_rproc.o
obj-$(CONFIG_REMOTEPROC_TI_IPU) += ipu_rproc.o
+obj-$(CONFIG_REMOTEPROC_VIRTIO) += rproc_virtio.o
@@ -14,6 +14,7 @@
#include <malloc.h>
#include <virtio_ring.h>
#include <remoteproc.h>
+#include <rproc_virtio.h>
#include <asm/io.h>
#include <dm/device-internal.h>
#include <dm.h>
@@ -279,6 +280,33 @@ static int rproc_config_pagetable(struct udevice *dev, unsigned int virt,
return 0;
}
+/**
+ * rproc_find_res_by_name() - After parsing the resource table add the mappings
+ * @dev: device we finished probing
+ * @name: name of rproc_mem_entry resource
+ *
+ * Return: If failed NULL, else first carveout entry with matching name.
+ */
+struct rproc_mem_entry *rproc_find_res_by_name(struct udevice *dev,
+ const char *name)
+{
+ struct rproc *rproc = rproc_get_cfg(dev);
+ struct rproc_mem_entry *mapping = NULL;
+ int ret;
+
+ if (!rproc)
+ return NULL;
+
+ list_for_each_entry(mapping, &rproc->mappings.node, node) {
+ ret = strcmp(mapping->name, name);
+ if (!ret)
+ return mapping;
+ }
+
+ debug("%s: %s carveout not found\n", dev->name, name);
+ return NULL;
+}
+
UCLASS_DRIVER(rproc) = {
.id = UCLASS_REMOTEPROC,
.name = "remoteproc",
@@ -688,6 +716,7 @@ static int alloc_vring(struct udevice *dev, struct fw_rsc_vdev *rsc, int i)
static int handle_vdev(struct udevice *dev, struct fw_rsc_vdev *rsc,
int offset, int avail)
{
+ struct rproc *rproc;
int i, ret;
void *pa;
@@ -720,7 +749,18 @@ static int handle_vdev(struct udevice *dev, struct fw_rsc_vdev *rsc,
}
/*
- * allocate the vrings
+ * If virtio device creation is supported, then prefer to get vrings
+ * during find_vq op
+ */
+ rproc = rproc_get_cfg(dev);
+
+ if (rproc && rproc->support_rpmsg_virtio &&
+ !(IS_ENABLED(CONFIG_SANDBOX))) {
+ return rproc_virtio_create_dev(dev, rsc, offset);
+ }
+
+ /*
+ * allocate the vrings traditional way
*/
for (i = 0; i < rsc->num_of_vrings; i++) {
ret = alloc_vring(dev, rsc, i);
new file mode 100644
@@ -0,0 +1,422 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Remote Processor Messaging transport
+ *
+ * Copyright (C) 2011 Texas Instruments, Inc.
+ * Copyright (C) 2011 Google, Inc.
+ * Copyright (C) 2023, Advanced Micro Devices Inc.
+ *
+ * VirtIO RPMsg transport driver
+ * Ported from Linux drivers/remoteproc/remoteproc_virtio.c
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <log.h>
+#include <remoteproc.h>
+#include <rproc_virtio.h>
+#include <virtio.h>
+#include <virtio_ring.h>
+#include <virtio_types.h>
+#include <asm/io.h>
+#include <dm/device_compat.h>
+#include <dm/device-internal.h>
+#include <linux/bug.h>
+#include <linux/compat.h>
+#include <linux/err.h>
+
+/**
+ * rproc_flush_dcache() - flush shared memory regions
+ * @dev: valid remoteproc virtio device
+ *
+ * Some platforms have dcache enabled. If dcache is on then data written
+ * to shared memory is actually written to cache memory. This function
+ * checks if cache is on or not and if it is on, then it performs
+ * flush and invalidate operation on address range or reserved memory
+ * created by platform driver for remoteproc
+ *
+ * Return: none
+ */
+void rproc_flush_dcache(struct udevice *dev)
+{
+ struct rproc *rproc = rproc_get_cfg(dev->parent);
+ struct rproc_mem_entry *mapping = NULL;
+ struct list_head *mapping_node = NULL;
+
+ /* If dcache is off, don't perform cache operation */
+ if (dcache_status() == false)
+ return;
+
+ /*
+ * If cache is on, then flush cache
+ * specially reserved mem regions for,
+ * resource table, vrings and vdevbuffer of platform dev
+ */
+ list_for_each(mapping_node, &rproc->mappings.node) {
+ mapping = container_of(mapping_node, struct rproc_mem_entry,
+ node);
+
+ /*
+ * First flush data so current data from cache is written
+ * to actual memory from cache. Then invalidate cache so
+ * next time data will be accessed from actual memory
+ */
+ flush_dcache_range(mapping->da, mapping->da + mapping->len);
+ invalidate_dcache_range(mapping->da, mapping->da + mapping->len);
+ }
+}
+
+int rproc_virtio_create_dev(struct udevice *parent, struct fw_rsc_vdev *rsc,
+ int offset)
+{
+ struct rproc_rvdev_data *rvdev_data;
+ struct udevice *vdev = NULL;
+ struct rproc *rproc;
+ char *dev_name;
+ int ret;
+
+ rproc = rproc_get_cfg(parent);
+ if (!rproc)
+ return -EINVAL;
+
+ rvdev_data = kzalloc(sizeof(*rvdev_data), GFP_KERNEL);
+ rvdev_data->id = rsc->id;
+ rvdev_data->rsc_offset = offset;
+
+ dev_name = kcalloc(32, sizeof(char), GFP_KERNEL);
+ sprintf(dev_name, "rproc-virtio#%d", rproc->rproc_id);
+
+ rvdev_data->index = rproc->rproc_id;
+ ret = device_bind(parent, DM_DRIVER_GET(rproc_virtio),
+ dev_name, rvdev_data, ofnode_null(),
+ &vdev);
+ if (ret) {
+ debug("failed to bind %s device\n", dev_name);
+ return ret;
+ }
+
+ ret = device_probe(vdev);
+ if (ret) {
+ debug("probing device %s failed\n", dev_name);
+ return ret;
+ }
+
+ free(dev_name);
+ dev_name = NULL;
+
+ return 0;
+}
+
+static int rproc_virtio_get_config(struct udevice *dev, unsigned int offset,
+ void *buf, unsigned int len)
+{
+ struct rproc_rvdev_data *rvdev_data;
+ struct fw_rsc_vdev *rsc;
+ struct rproc *rproc;
+ void *cfg;
+
+ rvdev_data = dev_get_plat(dev);
+ rproc = rproc_get_cfg(dev->parent);
+
+ rsc = (void *)rproc->table_ptr + rvdev_data->rsc_offset;
+
+ /* flush cache before reading configurations */
+ rproc_flush_dcache(dev);
+
+ cfg = &rsc->vring[rsc->num_of_vrings];
+
+ if (offset + len > rsc->config_len || offset + len < len) {
+ dev_err(dev, "rproc_virtio_get: access out of bounds\n");
+ return -EINVAL;
+ }
+
+ memcpy(buf, cfg + offset, len);
+
+ return 0;
+}
+
+static void rproc_transport_features(struct udevice *dev)
+{
+ /*
+ * Packed ring isn't enabled on remoteproc for now,
+ * because remoteproc uses vring_new_virtqueue() which
+ * creates virtio rings on preallocated memory.
+ */
+ __virtio_clear_bit(dev, VIRTIO_F_RING_PACKED);
+}
+
+static int rproc_virtio_set_config(struct udevice *dev, unsigned int offset,
+ const void *buf, unsigned int len)
+{
+ struct rproc_rvdev_data *rvdev_data;
+ struct fw_rsc_vdev *rsc;
+ struct rproc *rproc;
+ void *cfg;
+
+ rvdev_data = dev_get_plat(dev);
+ rproc = rproc_get_cfg(dev->parent);
+
+ rsc = (void *)rproc->table_ptr + rvdev_data->rsc_offset;
+ cfg = &rsc->vring[rsc->num_of_vrings];
+
+ if (offset + len > rsc->config_len || offset + len < len) {
+ dev_err(dev, "rproc_virtio_set: access out of bounds\n");
+ return -EINVAL;
+ }
+
+ memcpy(cfg + offset, buf, len);
+ rproc_flush_dcache(dev);
+
+ return 0;
+}
+
+static int rproc_virtio_get_status(struct udevice *dev, u8 *status)
+{
+ struct rproc_rvdev_data *rvdev_data;
+ struct fw_rsc_vdev *rsc;
+ struct rproc *rproc;
+
+ rvdev_data = dev_get_plat(dev);
+ rproc = rproc_get_cfg(dev->parent);
+
+ rsc = (void *)rproc->table_ptr + rvdev_data->rsc_offset;
+
+ *status = rsc->status;
+
+ rproc_flush_dcache(dev);
+
+ return 0;
+}
+
+static int rproc_virtio_set_status(struct udevice *dev, u8 status)
+{
+ struct rproc_rvdev_data *rvdev_data;
+ struct fw_rsc_vdev *rsc;
+ struct rproc *rproc;
+
+ rvdev_data = dev_get_plat(dev);
+ rproc = rproc_get_cfg(dev->parent);
+
+ rsc = (void *)rproc->table_ptr + rvdev_data->rsc_offset;
+
+ rsc->status = status;
+
+ rproc_flush_dcache(dev);
+
+ return 0;
+}
+
+static int rproc_virtio_reset(struct udevice *dev)
+{
+ struct rproc_rvdev_data *rvdev_data;
+ struct fw_rsc_vdev *rsc;
+ struct rproc *rproc;
+
+ rvdev_data = dev_get_plat(dev);
+ rproc = rproc_get_cfg(dev->parent);
+
+ rsc = (void *)rproc->table_ptr + rvdev_data->rsc_offset;
+
+ rsc->status = 0;
+
+ rproc_flush_dcache(dev);
+
+ return 0;
+}
+
+static int rproc_virtio_get_features(struct udevice *dev, u64 *features)
+{
+ struct rproc_rvdev_data *rvdev_data;
+ struct fw_rsc_vdev *rsc;
+ struct rproc *rproc;
+
+ rvdev_data = dev_get_plat(dev);
+ rproc = rproc_get_cfg(dev->parent);
+
+ rsc = (void *)rproc->table_ptr + rvdev_data->rsc_offset;
+
+ rproc_flush_dcache(dev);
+
+ *features = rsc->dfeatures;
+
+ return 0;
+}
+
+static int rproc_virtio_set_features(struct udevice *dev)
+{
+ struct virtio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
+ struct rproc_rvdev_data *rvdev_data;
+ struct fw_rsc_vdev *rsc;
+ struct rproc *rproc;
+
+ rvdev_data = dev_get_plat(dev);
+ rproc = rproc_get_cfg(dev->parent);
+
+ rsc = (void *)rproc->table_ptr + rvdev_data->rsc_offset;
+
+ /* Give virtio_rproc a chance to accept features. */
+ rproc_transport_features(dev);
+
+ /* reject any features > 32 bits! */
+ if (WARN_ON((u32)uc_priv->features != uc_priv->features))
+ return -EINVAL;
+
+ /*
+ * Remember the finalized features of our vdev, and provide it
+ * to the remote processor once it is powered on.
+ */
+ rsc->gfeatures = uc_priv->features;
+
+ rproc_flush_dcache(dev);
+
+ return 0;
+}
+
+static void rproc_virtio_del_vq(struct virtqueue *vq)
+{
+ vring_del_virtqueue(vq);
+}
+
+static int rproc_virtio_del_vqs(struct udevice *vdev)
+{
+ struct virtio_dev_priv *uc_priv = dev_get_uclass_priv(vdev);
+ struct virtqueue *vq, *n;
+
+ list_for_each_entry_safe(vq, n, &uc_priv->vqs, list)
+ rproc_virtio_del_vq(vq);
+
+ return 0;
+}
+
+static int rproc_virtio_find_vqs(struct udevice *vdev, unsigned int nvqs,
+ struct virtqueue *vqs[])
+{
+ int queue_index = 0, align, i, core_id, da;
+ struct rproc_rvdev_data *rvdev_data;
+ struct fw_rsc_vdev_vring *rvring;
+ struct rproc_mem_entry *mapping;
+ struct fw_rsc_vdev *rsc;
+ char name[32] = {0};
+ struct rproc *rproc;
+ struct vring vring;
+ unsigned int num;
+
+ rvdev_data = dev_get_plat(vdev);
+ rproc = rproc_get_cfg(vdev->parent);
+
+ if (nvqs > 2)
+ return -EINVAL;
+
+ core_id = rvdev_data->index;
+
+ rsc = (void *)rproc->table_ptr + rvdev_data->rsc_offset;
+
+ for (i = 0; i < nvqs; i++) {
+ sprintf(name, "vdev%dvring%d", core_id, i);
+ mapping = rproc_find_res_by_name(vdev->parent, name);
+ if (!mapping) {
+ dev_err(vdev, "carveout %s not found\n", name);
+ return -EINVAL;
+ }
+
+ num = rsc->vring[i].num;
+ /* assume num is a power of 2 */
+ if (num & (num - 1)) {
+ dev_err(vdev, "Bad virtqueue length %u\n", num);
+ return -EINVAL;
+ }
+
+ align = rsc->vring[i].align;
+ rvring = &rvdev_data->vring[i];
+
+ memset(mapping->va, 0, vring_size(num, align));
+ vring_init(&vring, num, mapping->va, align, NULL);
+
+ vqs[i] = vring_new_virtqueue(queue_index, vring, vdev);
+ if (!vqs[i]) {
+ dev_err(vdev, "failed to create vq\n");
+ return -EINVAL;
+ }
+
+ rvring->da = da;
+ rvring->notifyid = vqs[i]->index;
+ rvring->num = num;
+ rvring->align = align;
+
+ /* update vring in resource table */
+ rsc->vring[i].notifyid = rvring->notifyid;
+ rsc->vring[i].da = mapping->da;
+ rsc->vring[i].pa = mapping->da;
+ queue_index++;
+
+ rproc_flush_dcache(vdev);
+ }
+
+ return 0;
+}
+
+static int rproc_virtio_notify(struct udevice *dev, struct virtqueue *vq)
+{
+ struct dm_rproc_ops *ops;
+
+ ops = rproc_get_ops(dev->parent);
+ if (!ops || !ops->kick) {
+ dev_err(dev, "kick op not available for dev %s\n",
+ dev->parent->name);
+ return -EINVAL;
+ }
+
+ rproc_flush_dcache(dev);
+
+ return ops->kick(dev->parent, vq->index);
+}
+
+static int rproc_virtio_probe(struct udevice *vdev)
+{
+ struct virtio_dev_priv *ucpriv = dev_get_uclass_priv(vdev);
+ struct rproc_rvdev_data *rvdev_data;
+ struct udevice *rproc_dev;
+ char rvdev_name[32] = {0};
+
+ rvdev_data = dev_get_plat(vdev);
+
+ rproc_dev = vdev->parent;
+
+ sprintf(rvdev_name, "vdev%dbuffer", rvdev_data->index);
+ rvdev_data->vdev_buf = rproc_find_res_by_name(vdev->parent, rvdev_name);
+ if (!rvdev_data->vdev_buf) {
+ dev_err(vdev, "%s carveout not found", rvdev_name);
+ return -EINVAL;
+ }
+
+ ucpriv->vdev = vdev;
+ ucpriv->device = rvdev_data->id;
+
+ return 0;
+}
+
+static const struct dm_virtio_ops rproc_virtio_ops = {
+ .get_config = rproc_virtio_get_config,
+ .set_config = rproc_virtio_set_config,
+ .get_status = rproc_virtio_get_status,
+ .set_status = rproc_virtio_set_status,
+ .reset = rproc_virtio_reset,
+ .get_features = rproc_virtio_get_features,
+ .set_features = rproc_virtio_set_features,
+ .find_vqs = rproc_virtio_find_vqs,
+ .del_vqs = rproc_virtio_del_vqs,
+ .notify = rproc_virtio_notify,
+};
+
+static const struct udevice_id rproc_virtio_ids[] = {
+ { .compatible = "rproc,virtio" },
+};
+
+U_BOOT_DRIVER(rproc_virtio) = {
+ .name = "rproc_virtio",
+ .id = UCLASS_VIRTIO,
+ .of_match = rproc_virtio_ids,
+ .ops = &rproc_virtio_ops,
+ .probe = rproc_virtio_probe,
+ .plat_auto = sizeof(struct rproc_rvdev_data),
+};
@@ -331,6 +331,22 @@ static struct virtqueue *__vring_new_virtqueue(unsigned int index,
return vq;
}
+struct virtqueue *vring_new_virtqueue(unsigned int index,
+ struct vring vring,
+ struct udevice *udev)
+{
+ struct virtqueue *vq;
+
+ vq = __vring_new_virtqueue(index, vring, udev);
+ if (!vq)
+ return NULL;
+
+ debug("(%s): created vring @ %p for vq @ %p\n", udev->name,
+ vring.desc, vq);
+
+ return vq;
+}
+
struct virtqueue *vring_create_virtqueue(unsigned int index, unsigned int num,
unsigned int vring_align,
struct udevice *udev)
@@ -343,25 +343,20 @@ enum rproc_crash_type {
#define RPMSG_TOTAL_BUF_SPACE (RPMSG_NUM_BUFS * RPMSG_BUF_SIZE)
/**
- * struct rproc_vring - remoteproc vring state
- * @va: virtual address
- * @dma: dma address
- * @len: length, in bytes
- * @da: device address
- * @align: vring alignment
- * @notifyid: rproc-specific unique vring index
- * @rvdev: remote vdev
- * @vq: the virtqueue of this vring
- */
-struct rproc_vring {
- void *va;
- dma_addr_t dma;
- int len;
- u32 da;
- u32 align;
- int notifyid;
- struct rproc_vdev *rvdev;
- struct virtqueue *vq;
+ * struct rproc_rvdev_data - remoteproc virito device data
+ *
+ * @rsc_offset: resource offset
+ * @id: virtio dev id
+ * @index: vdev position vs other vdev declared in resource table
+ * @vring: store tx and rx vrings description
+ * @vdev_buf: vdev0buffer carveout mapping
+ */
+struct rproc_rvdev_data {
+ u32 rsc_offset;
+ unsigned int id;
+ u32 index;
+ struct fw_rsc_vdev_vring vring[2];
+ struct rproc_mem_entry *vdev_buf;
};
/** struct rproc - structure with all processor specific information for
@@ -383,6 +378,7 @@ struct rproc_vring {
*
* @entry_point: address that is the entry point for the remote core. This
* address is in the memory view of the remotecore.
+ * @rproc_id: per core id
*
* @load_addr: Address to which the bootloader loads the firmware from
* persistent storage before invoking the ELF loader. Keeping this address
@@ -393,6 +389,11 @@ struct rproc_vring {
* @firmware_name: Name of the file that is expected to contain the ELF image.
*
* @has_rsc_table: Flag populated after parsing the ELF binary on target.
+ * @support_rpmsg_virtio: set in rproc platform driver to support new rpmsg framework
+ * @mappings: list of reserved memory regions created by platform driver
+ * such as vring0, vring1, vdevbuffer etc...
+ * @table_ptr: holds address of resource table from shared memory between host
+ * and remote processors
*/
struct rproc {
@@ -403,6 +404,7 @@ struct rproc {
unsigned long mmu_base_addr[2];
unsigned long load_addr;
unsigned long entry_point;
+ int rproc_id;
char *core_name;
char *firmware_name;
char *ptn;
@@ -414,6 +416,9 @@ struct rproc {
struct rproc_intmem_to_l3_mapping *intmem_to_l3_mapping;
u32 trace_pa;
u32 trace_len;
+ bool support_rpmsg_virtio;
+ struct rproc_mem_entry mappings;
+ struct resource_table *table_ptr;
};
extern struct rproc *rproc_cfg_arr[2];
@@ -444,6 +449,7 @@ struct dm_rproc_uclass_pdata {
const char *name;
enum rproc_mem_type mem_type;
void *driver_plat_data;
+ struct rproc *rproc;
};
/**
@@ -534,10 +540,22 @@ struct dm_rproc_ops {
unsigned long align);
unsigned int (*config_pagetable)(struct udevice *dev, unsigned int virt,
unsigned int phys, unsigned int len);
+ struct resource_table *(*get_loaded_rsc_table)(struct udevice *dev,
+ int *tablesz);
+ /**
+ * kick() - kick the remote device for communication (needed for rpmsg)
+ *
+ * @dev: Remote proc device
+ * @notify_id: vq id to be notified
+ * @return 0 on success, 1 if not responding, -ve on other errors.
+ */
+ int (*kick)(struct udevice *dev, int notify_id);
};
/* Accessor */
#define rproc_get_ops(dev) ((struct dm_rproc_ops *)(dev)->driver->ops)
+#define rproc_get_cfg(dev) (((struct dm_rproc_uclass_pdata *) \
+ dev_get_plat(dev))->rproc)
#if CONFIG_IS_ENABLED(REMOTEPROC)
/**
@@ -737,6 +755,10 @@ unsigned long rproc_parse_resource_table(struct udevice *dev,
struct resource_table *rproc_find_resource_table(struct udevice *dev,
unsigned int addr,
int *tablesz);
+struct resource_table *rproc_get_loaded_rsc_table(struct udevice *dev,
+ struct rproc *cfg);
+struct rproc_mem_entry *rproc_find_res_by_name(struct udevice *dev,
+ const char *name);
#else
static inline int rproc_init(void) { return -ENOSYS; }
static inline int rproc_dev_init(int id) { return -ENOSYS; }
@@ -776,6 +798,12 @@ static inline int rproc_elf_load_rsc_table(struct udevice *dev, ulong fw_addr,
ulong fw_size, ulong *rsc_addr,
ulong *rsc_size)
{ return -ENOSYS; }
+
+static inline struct rproc_mem_entry *rproc_find_res_by_name(struct udevice *dev,
+ const char *name)
+{
+ return NULL;
+}
#endif
#endif /* _RPROC_H_ */
new file mode 100644
@@ -0,0 +1,29 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2023, Advanced Micro Devices Inc.
+ */
+
+#ifndef _RPROC_VIRTIO_H_
+#define _RPROC_VIRTIO_H_
+
+#include <remoteproc.h>
+#include <dm/device.h>
+
+void rproc_flush_dcache(struct udevice *dev);
+
+#ifndef CONFIG_SANDBOX
+
+int rproc_virtio_create_dev(struct udevice *parent, struct fw_rsc_vdev *rsc,
+ int offset);
+
+#else
+
+int rproc_virtio_create_dev(struct udevice *parent, struct fw_rsc_vdev *rsc,
+ int offset)
+{
+ return -ENODEV;
+}
+
+#endif /* CONFIG_SANDBOX */
+
+#endif /* _RPROC_VIRTIO_H_ */
@@ -69,6 +69,9 @@
/* v1.0 compliant */
#define VIRTIO_F_VERSION_1 32
+/* packed virtqueue layout */
+#define VIRTIO_F_RING_PACKED 34
+
/*
* If clear - device has the IOMMU bypass quirk feature.
* If set - use platform tools to detect the IOMMU.
@@ -2,6 +2,7 @@
/*
* Copyright (C) 2018, Tuomas Tynkkynen <tuomas.tynkkynen@iki.fi>
* Copyright (C) 2018, Bin Meng <bmeng.cn@gmail.com>
+ * Copyright (C) 2023, Advanced Micro Devices Inc.
*
* From Linux kernel include/uapi/linux/virtio_ring.h
*/
@@ -227,6 +228,22 @@ void virtqueue_kick(struct virtqueue *vq);
*/
void *virtqueue_get_buf(struct virtqueue *vq, unsigned int *len);
+/**
+ * vring_new_virtqueue - create a virtqueue at user defined vring address
+ *
+ * @index: the index of the queue
+ * @vring: vring created at user defined address
+ * @udev: the virtio transport udevice
+ * @return: the virtqueue pointer or NULL if failed
+ *
+ * This creates a virtqueue using vring address decided by the user of API
+ *
+ * This API is supposed to be called by the virtio transport driver in the
+ * virtio find_vqs() uclass method.
+ */
+struct virtqueue *vring_new_virtqueue(unsigned int index, struct vring vring,
+ struct udevice *udev);
+
/**
* vring_create_virtqueue - create a virtqueue for a virtio device
*
Remoteproc virtio is virtio transport layer driver for remoteproc. Implement virtio config ops used by actual virtio driver using remoteproc virtio device Ported from the Linux kernel version 6.4-rc2 (d848a4819d85), Introduced in kernel version v3.10 (ac8954a41393) file: drivers/remoteproc/remoteproc_virtio.c. Signed-off-by: Tanmay Shah <tanmay.shah@amd.com> --- MAINTAINERS | 6 + drivers/remoteproc/Kconfig | 11 + drivers/remoteproc/Makefile | 1 + drivers/remoteproc/rproc-uclass.c | 42 ++- drivers/remoteproc/rproc_virtio.c | 422 ++++++++++++++++++++++++++++++ drivers/virtio/virtio_ring.c | 16 ++ include/remoteproc.h | 66 +++-- include/rproc_virtio.h | 29 ++ include/virtio.h | 3 + include/virtio_ring.h | 17 ++ 10 files changed, 593 insertions(+), 20 deletions(-) create mode 100644 drivers/remoteproc/rproc_virtio.c create mode 100644 include/rproc_virtio.h