#include "exynos-iommu.h"
+/* Default IOVA region: [0x1000000, 0xD0000000) */
+#define IOVA_START 0x10000000
+#define IOVA_END 0xD0000000
+#define IOVA_OVFL(x) ((x) > 0xFFFFFFFF)
+
static struct kmem_cache *lv2table_kmem_cache;
static struct sysmmu_drvdata *sysmmu_drvdata_list;
struct device_node *np;
struct exynos_iovmm *vmm = NULL;
struct exynos_iommu_domain *domain;
+ unsigned int start = IOVA_START, end = IOVA_END;
+ dma_addr_t d_addr;
+ size_t d_size;
int i = 0;
+ ret = of_get_dma_window(domain_np, NULL, 0, NULL, &d_addr, &d_size);
+ if (!ret) {
+ if (d_addr == 0 || IOVA_OVFL(d_addr + d_size)) {
+ pr_err("Failed to get valid dma ranges,\n");
+ pr_err("Domain %s, range %pad++%#zx]\n",
+ domain_np->name, &d_addr, d_size);
+ of_node_put(domain_np);
+ return -EINVAL;
+ }
+ start = d_addr;
+ end = d_addr + d_size;
+ }
+ pr_info("DMA ranges for domain %s. [%#x..%#x]\n",
+ domain_np->name, start, end);
+
while ((np = of_parse_phandle(domain_np, "domain-clients", i++))) {
if (!vmm) {
- vmm = exynos_create_single_iovmm(np->name);
+ vmm = exynos_create_single_iovmm(np->name,
+ start, end);
if (IS_ERR(vmm)) {
pr_err("%s: Failed to create IOVM space\
of %s\n",
struct exynos_vm_region *find_iovm_region(struct exynos_iovmm *vmm,
dma_addr_t iova);
-struct exynos_iovmm *exynos_create_single_iovmm(const char *name);
+struct exynos_iovmm *exynos_create_single_iovmm(const char *name,
+ unsigned int start, unsigned int end);
#else
static inline struct exynos_iovmm *exynos_get_iovmm(struct device *dev)
{
return NULL;
}
-static inline struct exynos_iovmm *exynos_create_single_iovmm(const char *name)
+static inline struct exynos_iovmm *exynos_create_single_iovmm(const char *name,
+ unsigned int start, unsigned int end);
{
return NULL;
}
#include "exynos-iommu.h"
-/* IOVM region: [0x1000000, 0xD0000000) */
-#define IOVA_START 0x10000000
-#define IOVM_SIZE (0xD0000000 - IOVA_START)
#define sg_physically_continuous(sg) (sg_next(sg) == NULL)
/* alloc_iovm_region - Allocate IO virtual memory region
exynos_iovmm_debugfs_root, vmm, &iovmm_debug_fops);
}
-struct exynos_iovmm *exynos_create_single_iovmm(const char *name)
+struct exynos_iovmm *exynos_create_single_iovmm(const char *name,
+ unsigned int start, unsigned int end)
{
struct exynos_iovmm *vmm;
int ret = 0;
goto err_alloc_vmm;
}
- vmm->iovm_size = IOVM_SIZE;
- vmm->iova_start = IOVA_START;
- vmm->vm_map = kzalloc(IOVM_BITMAP_SIZE(IOVM_SIZE), GFP_KERNEL);
+ vmm->iovm_size = (size_t)(end - start);
+ vmm->iova_start = start;
+ vmm->vm_map = kzalloc(IOVM_BITMAP_SIZE(vmm->iovm_size), GFP_KERNEL);
if (!vmm->vm_map) {
ret = -ENOMEM;
goto err_setup_domain;
iovmm_register_debugfs(vmm);
- pr_debug("%s IOVMM: Created %#x B IOVMM from %#x.\n",
- name, IOVM_SIZE, IOVA_START);
+ pr_debug("%s IOVMM: Created %#zx B IOVMM from %#x.\n",
+ name, vmm->iovm_size, vmm->iova_start);
return vmm;
err_setup_domain: