return -ENOENT;
 }
 
-static void *imx_rproc_da_to_va(struct rproc *rproc, u64 da, size_t len)
+static void *imx_rproc_da_to_va(struct rproc *rproc, u64 da, size_t len, bool *is_iomem)
 {
        struct imx_rproc *priv = rproc->priv;
        void *va = NULL;
 
        writel(vqid, vpu->aux_base + REG_CORE_MSG);
 }
 
-static void *ingenic_rproc_da_to_va(struct rproc *rproc, u64 da, size_t len)
+static void *ingenic_rproc_da_to_va(struct rproc *rproc, u64 da, size_t len, bool *is_iomem)
 {
        struct vpu *vpu = rproc->priv;
        void __iomem *va = NULL;
 
  * can be used either by the remoteproc core for loading (when using kernel
  * remoteproc loader), or by any rpmsg bus drivers.
  */
-static void *keystone_rproc_da_to_va(struct rproc *rproc, u64 da, size_t len)
+static void *keystone_rproc_da_to_va(struct rproc *rproc, u64 da, size_t len, bool *is_iomem)
 {
        struct keystone_rproc *ksproc = rproc->priv;
        void __iomem *va = NULL;
 
                }
 
                /* grab the kernel address for this device address */
-               ptr = (void __iomem *)rproc_da_to_va(rproc, da, memsz);
+               ptr = (void __iomem *)rproc_da_to_va(rproc, da, memsz, NULL);
                if (!ptr) {
                        dev_err(dev, "bad phdr da 0x%x mem 0x%x\n", da, memsz);
                        ret = -EINVAL;
        return NULL;
 }
 
-static void *scp_da_to_va(struct rproc *rproc, u64 da, size_t len)
+static void *scp_da_to_va(struct rproc *rproc, u64 da, size_t len, bool *is_iomem)
 {
        struct mtk_scp *scp = (struct mtk_scp *)rproc->priv;
 
 {
        void *ptr;
 
-       ptr = scp_da_to_va(scp->rproc, mem_addr, 0);
+       ptr = scp_da_to_va(scp->rproc, mem_addr, 0, NULL);
        if (!ptr)
                return ERR_PTR(-EINVAL);
 
 
  * Return: translated virtual address in kernel memory space on success,
  *         or NULL on failure.
  */
-static void *omap_rproc_da_to_va(struct rproc *rproc, u64 da, size_t len)
+static void *omap_rproc_da_to_va(struct rproc *rproc, u64 da, size_t len, bool *is_iomem)
 {
        struct omap_rproc *oproc = rproc->priv;
        int i;
 
  * core for any PRU client drivers. The PRU Instruction RAM access is restricted
  * only to the PRU loader code.
  */
-static void *pru_rproc_da_to_va(struct rproc *rproc, u64 da, size_t len)
+static void *pru_rproc_da_to_va(struct rproc *rproc, u64 da, size_t len, bool *is_iomem)
 {
        struct pru_rproc *pru = rproc->priv;
 
 
        return ret;
 }
 
-static void *adsp_da_to_va(struct rproc *rproc, u64 da, size_t len)
+static void *adsp_da_to_va(struct rproc *rproc, u64 da, size_t len, bool *is_iomem)
 {
        struct qcom_adsp *adsp = (struct qcom_adsp *)rproc->priv;
        int offset;
 
        return ret;
 }
 
-static void *adsp_da_to_va(struct rproc *rproc, u64 da, size_t len)
+static void *adsp_da_to_va(struct rproc *rproc, u64 da, size_t len, bool *is_iomem)
 {
        struct qcom_adsp *adsp = (struct qcom_adsp *)rproc->priv;
        int offset;
 
        return 0;
 }
 
-static void *q6v5_wcss_da_to_va(struct rproc *rproc, u64 da, size_t len)
+static void *q6v5_wcss_da_to_va(struct rproc *rproc, u64 da, size_t len, bool *is_iomem)
 {
        struct q6v5_wcss *wcss = rproc->priv;
        int offset;
 
        return ret;
 }
 
-static void *wcnss_da_to_va(struct rproc *rproc, u64 da, size_t len)
+static void *wcnss_da_to_va(struct rproc *rproc, u64 da, size_t len, bool *is_iomem)
 {
        struct qcom_wcnss *wcnss = (struct qcom_wcnss *)rproc->priv;
        int offset;
 
  * here the output of the DMA API for the carveouts, which should be more
  * correct.
  */
-void *rproc_da_to_va(struct rproc *rproc, u64 da, size_t len)
+void *rproc_da_to_va(struct rproc *rproc, u64 da, size_t len, bool *is_iomem)
 {
        struct rproc_mem_entry *carveout;
        void *ptr = NULL;
 
        if (rproc->ops->da_to_va) {
-               ptr = rproc->ops->da_to_va(rproc, da, len);
+               ptr = rproc->ops->da_to_va(rproc, da, len, is_iomem);
                if (ptr)
                        goto out;
        }
 
                ptr = carveout->va + offset;
 
+               if (is_iomem)
+                       *is_iomem = carveout->is_iomem;
+
                break;
        }
 
 
                               size_t offset, size_t size)
 {
        void *ptr;
+       bool is_iomem;
 
        if (segment->dump) {
                segment->dump(rproc, segment, dest, offset, size);
        } else {
-               ptr = rproc_da_to_va(rproc, segment->da + offset, size);
+               ptr = rproc_da_to_va(rproc, segment->da + offset, size, &is_iomem);
                if (!ptr) {
                        dev_err(&rproc->dev,
                                "invalid copy request for segment %pad with offset %zu and size %zu)\n",
                                &segment->da, offset, size);
                        memset(dest, 0xff, size);
                } else {
-                       memcpy(dest, ptr, size);
+                       if (is_iomem)
+                               memcpy_fromio(dest, ptr, size);
+                       else
+                               memcpy(dest, ptr, size);
                }
        }
 }
 
        char buf[100];
        int len;
 
-       va = rproc_da_to_va(data->rproc, trace->da, trace->len);
+       va = rproc_da_to_va(data->rproc, trace->da, trace->len, NULL);
 
        if (!va) {
                len = scnprintf(buf, sizeof(buf), "Trace %s not available\n",
 
                u64 offset = elf_phdr_get_p_offset(class, phdr);
                u32 type = elf_phdr_get_p_type(class, phdr);
                void *ptr;
+               bool is_iomem;
 
                if (type != PT_LOAD)
                        continue;
                }
 
                /* grab the kernel address for this device address */
-               ptr = rproc_da_to_va(rproc, da, memsz);
+               ptr = rproc_da_to_va(rproc, da, memsz, &is_iomem);
                if (!ptr) {
                        dev_err(dev, "bad phdr da 0x%llx mem 0x%llx\n", da,
                                memsz);
                }
 
                /* put the segment where the remote processor expects it */
-               if (filesz)
-                       memcpy(ptr, elf_data + offset, filesz);
+               if (filesz) {
+                       if (is_iomem)
+                               memcpy_fromio(ptr, (void __iomem *)(elf_data + offset), filesz);
+                       else
+                               memcpy(ptr, elf_data + offset, filesz);
+               }
 
                /*
                 * Zero out remaining memory for this segment.
                 * did this for us. albeit harmless, we may consider removing
                 * this.
                 */
-               if (memsz > filesz)
-                       memset(ptr + filesz, 0, memsz - filesz);
+               if (memsz > filesz) {
+                       if (is_iomem)
+                               memset_io((void __iomem *)(ptr + filesz), 0, memsz - filesz);
+                       else
+                               memset(ptr + filesz, 0, memsz - filesz);
+               }
        }
 
        return ret;
                return NULL;
        }
 
-       return rproc_da_to_va(rproc, sh_addr, sh_size);
+       return rproc_da_to_va(rproc, sh_addr, sh_size, NULL);
 }
 EXPORT_SYMBOL(rproc_elf_find_loaded_rsc_table);
 
 void rproc_free_vring(struct rproc_vring *rvring);
 int rproc_alloc_vring(struct rproc_vdev *rvdev, int i);
 
-void *rproc_da_to_va(struct rproc *rproc, u64 da, size_t len);
+void *rproc_da_to_va(struct rproc *rproc, u64 da, size_t len, bool *is_iomem);
 phys_addr_t rproc_va_to_pa(void *cpu_addr);
 int rproc_trigger_recovery(struct rproc *rproc);
 
 
        return 0;
 }
 
-static void *slim_rproc_da_to_va(struct rproc *rproc, u64 da, size_t len)
+static void *slim_rproc_da_to_va(struct rproc *rproc, u64 da, size_t len, bool *is_iomem)
 {
        struct st_slim_rproc *slim_rproc = rproc->priv;
        void *va = NULL;
 
  * can be used either by the remoteproc core for loading (when using kernel
  * remoteproc loader), or by any rpmsg bus drivers.
  */
-static void *k3_dsp_rproc_da_to_va(struct rproc *rproc, u64 da, size_t len)
+static void *k3_dsp_rproc_da_to_va(struct rproc *rproc, u64 da, size_t len, bool *is_iomem)
 {
        struct k3_dsp_rproc *kproc = rproc->priv;
        void __iomem *va = NULL;
 
  * present in a DSP or IPU device). The translated addresses can be used
  * either by the remoteproc core for loading, or by any rpmsg bus drivers.
  */
-static void *k3_r5_rproc_da_to_va(struct rproc *rproc, u64 da, size_t len)
+static void *k3_r5_rproc_da_to_va(struct rproc *rproc, u64 da, size_t len, bool *is_iomem)
 {
        struct k3_r5_rproc *kproc = rproc->priv;
        struct k3_r5_core *core = kproc->core;
 
        return error;
 }
 
-static void *wkup_m3_rproc_da_to_va(struct rproc *rproc, u64 da, size_t len)
+static void *wkup_m3_rproc_da_to_va(struct rproc *rproc, u64 da, size_t len, bool *is_iomem)
 {
        struct wkup_m3_rproc *wkupm3 = rproc->priv;
        void *va = NULL;
 
        int (*stop)(struct rproc *rproc);
        int (*attach)(struct rproc *rproc);
        void (*kick)(struct rproc *rproc, int vqid);
-       void * (*da_to_va)(struct rproc *rproc, u64 da, size_t len);
+       void * (*da_to_va)(struct rproc *rproc, u64 da, size_t len, bool *is_iomem);
        int (*parse_fw)(struct rproc *rproc, const struct firmware *fw);
        int (*handle_rsc)(struct rproc *rproc, u32 rsc_type, void *rsc,
                          int offset, int avail);