@@ -8,6 +8,7 @@
*/
#include <linux/firmware.h>
+#include <linux/iommu.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/notifier.h>
@@ -35,6 +36,8 @@
#define MINIDUMP_SS_ENCR_DONE ('D' << 24 | 'O' << 16 | 'N' << 8 | 'E' << 0)
#define MINIDUMP_SS_ENABLED ('E' << 24 | 'N' << 16 | 'B' << 8 | 'L' << 0)
+#define SID_MASK_DEFAULT 0xfUL
+
/**
* struct minidump_region - Minidump region
* @name : Name of the region to be dumped
@@ -606,5 +609,54 @@ void qcom_remove_pdm_subdev(struct rproc *rproc, struct qcom_rproc_pdm *pdm)
}
EXPORT_SYMBOL_GPL(qcom_remove_pdm_subdev);
+/**
+ * qcom_map_unmap_carveout() - iommu map and unmap carveout region
+ *
+ * @rproc: rproc handle
+ * @mem_phys: starting physical address of carveout region
+ * @mem_size: size of carveout region
+ * @map: if true, map otherwise, unmap
+ * @use_sid: decision to append sid to iova
+ * @sid: SID value
+ */
+int qcom_map_unmap_carveout(struct rproc *rproc, phys_addr_t mem_phys, size_t mem_size,
+ bool map, bool use_sid, unsigned long sid)
+{
+ unsigned long iova = mem_phys;
+ unsigned long sid_def_val;
+ int ret;
+
+ if (!rproc->has_iommu)
+ return 0;
+
+ if (!rproc->domain)
+ return -EINVAL;
+
+ /*
+ * Remote processor like ADSP supports upto 36 bit device
+ * address space and some of its clients like fastrpc uses
+ * upper 32-35 bits to keep lower 4 bits of its SID to use
+ * larger address space. To keep this consistent across other
+ * use cases add remoteproc SID configuration for firmware
+ * to IOMMU for carveouts.
+ */
+ if (use_sid && sid) {
+ sid_def_val = sid & SID_MASK_DEFAULT;
+ iova |= (sid_def_val << 32);
+ }
+
+ if (map)
+ ret = iommu_map(rproc->domain, iova, mem_phys, mem_size, IOMMU_READ | IOMMU_WRITE, GFP_KERNEL);
+ else
+ ret = iommu_unmap(rproc->domain, iova, mem_size);
+
+ if (ret)
+ dev_err(&rproc->dev, "Unable to %s IOVA Memory, ret: %d\n",
+ map ? "map" : "unmap", ret);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(qcom_map_unmap_carveout);
+
MODULE_DESCRIPTION("Qualcomm Remoteproc helper driver");
MODULE_LICENSE("GPL v2");
@@ -59,6 +59,9 @@ void qcom_add_ssr_subdev(struct rproc *rproc, struct qcom_rproc_ssr *ssr,
const char *ssr_name);
void qcom_remove_ssr_subdev(struct rproc *rproc, struct qcom_rproc_ssr *ssr);
+int qcom_map_unmap_carveout(struct rproc *rproc, phys_addr_t mem_phys, size_t mem_size,
+ bool map, bool use_sid, unsigned long sid);
+
void qcom_add_pdm_subdev(struct rproc *rproc, struct qcom_rproc_pdm *pdm);
void qcom_remove_pdm_subdev(struct rproc *rproc, struct qcom_rproc_pdm *pdm);