]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - rpmsg/rpmsg.git/blobdiff - drivers/remoteproc/remoteproc_core.c
remoteproc: add an api to do pa to da conversion
[rpmsg/rpmsg.git] / drivers / remoteproc / remoteproc_core.c
index aa6206706fe335008060a9e3da7a8a97d2f91e50..3defd9ebc4e7dc118666a07a5bc9a847c4d0fcc7 100644 (file)
@@ -41,6 +41,8 @@
 #include <linux/crc32.h>
 #include <linux/virtio_ids.h>
 #include <linux/virtio_ring.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
 #include <asm/byteorder.h>
 
 #include "remoteproc_internal.h"
@@ -201,6 +203,61 @@ out:
 }
 EXPORT_SYMBOL(rproc_da_to_va);
 
+/**
+ * rproc_pa_to_da() - lookup the rproc device address for a physical address
+ * @rproc: handle of a remote processor
+ * @pa: physical address of the buffer to translate
+ * @da: device address to return
+ *
+ * Communication clients of remote processors usually would need a means to
+ * convert a host buffer pointer to an equivalent device virtual address pointer
+ * that the code running on the remote processor can operate on. These buffer
+ * pointers can either be from the physically contiguous memory regions (or
+ * "carveouts") or can be some memory-mapped Device IO memory. This function
+ * provides a means to translate a given physical address to its associated
+ * device address.
+ *
+ * The function looks through both the carveouts and the device memory mappings
+ * since both of them are stored in separate lists.
+ *
+ * Returns 0 on success, or an appropriate error code otherwise. The translated
+ * device address is returned through the appropriate function argument.
+ */
+int rproc_pa_to_da(struct rproc *rproc, phys_addr_t pa, u64 *da)
+{
+       int ret = -EINVAL;
+       struct rproc_mem_entry *maps = NULL;
+
+       if (!rproc || !da)
+               return -EINVAL;
+
+       if (mutex_lock_interruptible(&rproc->lock))
+               return -EINTR;
+
+       if (rproc->state == RPROC_RUNNING || rproc->state == RPROC_SUSPENDED) {
+               /* Look in the mappings first */
+               list_for_each_entry(maps, &rproc->mappings, node) {
+                       if (pa >= maps->dma && pa < (maps->dma + maps->len)) {
+                               *da = maps->da + (pa - maps->dma);
+                               ret = 0;
+                               goto exit;
+                       }
+               }
+               /* If not, check in the carveouts */
+               list_for_each_entry(maps, &rproc->carveouts, node) {
+                       if (pa >= maps->dma && pa < (maps->dma + maps->len)) {
+                               *da = maps->da + (pa - maps->dma);
+                               ret = 0;
+                               break;
+                       }
+               }
+       }
+exit:
+       mutex_unlock(&rproc->lock);
+       return ret;
+}
+EXPORT_SYMBOL(rproc_pa_to_da);
+
 int rproc_alloc_vring(struct rproc_vdev *rvdev, int i)
 {
        struct rproc *rproc = rvdev->rproc;
@@ -569,6 +626,7 @@ static int rproc_handle_devmem(struct rproc *rproc, struct fw_rsc_devmem *rsc,
         * We can't trust the remote processor not to change the resource
         * table, so we must maintain this info independently.
         */
+       mapping->dma = rsc->pa;
        mapping->da = rsc->da;
        mapping->len = rsc->len;
        list_add_tail(&mapping->node, &rproc->mappings);
@@ -709,6 +767,7 @@ static int rproc_handle_carveout(struct rproc *rproc,
        carveout->len = rsc->len;
        carveout->dma = dma;
        carveout->da = rsc->da;
+       strlcpy(carveout->name, rsc->name, sizeof(carveout->name));
 
        list_add_tail(&carveout->node, &rproc->carveouts);
 
@@ -1277,6 +1336,36 @@ static void rproc_crash_handler_work(struct work_struct *work)
                rproc_trigger_recovery(rproc);
 }
 
+/**
+ * rproc_get_id() - return the id for the rproc device
+ * @rproc: handle of a remote processor
+ *
+ * Each rproc device is associated with a platform device, which is created
+ * either from device tree (majority newer platforms) or using legacy style
+ * platform device creation (fewer legacy platforms). This function retrieves
+ * an unique id for each remote processor and is useful for clients needing
+ * to distinguish each of the remoteprocs. This unique id is derived using
+ * the platform device id for non-DT devices, or an alternate alias id for
+ * DT devices (since they do not have a valid platform device id). It is
+ * assumed that the platform devices were created with known ids or were
+ * given proper alias ids using the stem "rproc".
+ *
+ * Return: alias id for DT devices or platform device id for non-DT devices
+ * associated with the rproc
+ */
+int rproc_get_id(struct rproc *rproc)
+{
+       struct device *dev = rproc->dev.parent;
+       struct device_node *np = dev->of_node;
+       struct platform_device *pdev = to_platform_device(dev);
+
+       if (np)
+               return of_alias_get_id(np, "rproc");
+       else
+               return pdev->id;
+}
+EXPORT_SYMBOL(rproc_get_id);
+
 /**
  * rproc_boot() - boot a remote processor
  * @rproc: handle of a remote processor