aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/plat-omap
diff options
context:
space:
mode:
authorGuzman Lugo, Fernando <x0095840@ti.com>2010-12-14 19:54:03 -0500
committerHari Kanigeri <h-kanigeri2@ti.com>2010-12-15 12:29:10 -0500
commitc7f4ab26e3bcdaeb3e19ec658e3ad9092f1a6ceb (patch)
treeb80f93995d8e9daa1f53a18c105e8d532102cd21 /arch/arm/plat-omap
parent9205a109fbeee180254bb5a4020eb71d50735944 (diff)
OMAP: iommu: create new api to set valid da range
Some IOMMUs cannot use the whole 0x0 - 0xFFFFFFFF range. With this new API the valid range can be set. Signed-off-by: Fernando Guzman Lugo <x0095840@ti.com> Acked-by: Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
Diffstat (limited to 'arch/arm/plat-omap')
-rw-r--r--arch/arm/plat-omap/include/plat/iommu.h5
-rw-r--r--arch/arm/plat-omap/iommu.c24
-rw-r--r--arch/arm/plat-omap/iovmm.c15
3 files changed, 37 insertions, 7 deletions
diff --git a/arch/arm/plat-omap/include/plat/iommu.h b/arch/arm/plat-omap/include/plat/iommu.h
index 33c7d41cb6a5..69230d685538 100644
--- a/arch/arm/plat-omap/include/plat/iommu.h
+++ b/arch/arm/plat-omap/include/plat/iommu.h
@@ -50,6 +50,8 @@ struct iommu {
50 int (*isr)(struct iommu *obj); 50 int (*isr)(struct iommu *obj);
51 51
52 void *ctx; /* iommu context: registres saved area */ 52 void *ctx; /* iommu context: registres saved area */
53 u32 da_start;
54 u32 da_end;
53}; 55};
54 56
55struct cr_regs { 57struct cr_regs {
@@ -103,6 +105,8 @@ struct iommu_platform_data {
103 const char *name; 105 const char *name;
104 const char *clk_name; 106 const char *clk_name;
105 const int nr_tlb_entries; 107 const int nr_tlb_entries;
108 u32 da_start;
109 u32 da_end;
106}; 110};
107 111
108#if defined(CONFIG_ARCH_OMAP1) 112#if defined(CONFIG_ARCH_OMAP1)
@@ -152,6 +156,7 @@ extern void flush_iotlb_all(struct iommu *obj);
152extern int iopgtable_store_entry(struct iommu *obj, struct iotlb_entry *e); 156extern int iopgtable_store_entry(struct iommu *obj, struct iotlb_entry *e);
153extern size_t iopgtable_clear_entry(struct iommu *obj, u32 iova); 157extern size_t iopgtable_clear_entry(struct iommu *obj, u32 iova);
154 158
159extern int iommu_set_da_range(struct iommu *obj, u32 start, u32 end);
155extern struct iommu *iommu_get(const char *name); 160extern struct iommu *iommu_get(const char *name);
156extern void iommu_put(struct iommu *obj); 161extern void iommu_put(struct iommu *obj);
157 162
diff --git a/arch/arm/plat-omap/iommu.c b/arch/arm/plat-omap/iommu.c
index 6cd151b31bc5..b1107c08da56 100644
--- a/arch/arm/plat-omap/iommu.c
+++ b/arch/arm/plat-omap/iommu.c
@@ -830,6 +830,28 @@ static int device_match_by_alias(struct device *dev, void *data)
830} 830}
831 831
832/** 832/**
833 * iommu_set_da_range - Set a valid device address range
834 * @obj: target iommu
835 * @start Start of valid range
836 * @end End of valid range
837 **/
838int iommu_set_da_range(struct iommu *obj, u32 start, u32 end)
839{
840
841 if (!obj)
842 return -EFAULT;
843
844 if (end < start || !PAGE_ALIGN(start | end))
845 return -EINVAL;
846
847 obj->da_start = start;
848 obj->da_end = end;
849
850 return 0;
851}
852EXPORT_SYMBOL_GPL(iommu_set_da_range);
853
854/**
833 * iommu_get - Get iommu handler 855 * iommu_get - Get iommu handler
834 * @name: target iommu name 856 * @name: target iommu name
835 **/ 857 **/
@@ -922,6 +944,8 @@ static int __devinit omap_iommu_probe(struct platform_device *pdev)
922 obj->name = pdata->name; 944 obj->name = pdata->name;
923 obj->dev = &pdev->dev; 945 obj->dev = &pdev->dev;
924 obj->ctx = (void *)obj + sizeof(*obj); 946 obj->ctx = (void *)obj + sizeof(*obj);
947 obj->da_start = pdata->da_start;
948 obj->da_end = pdata->da_end;
925 949
926 mutex_init(&obj->iommu_lock); 950 mutex_init(&obj->iommu_lock);
927 mutex_init(&obj->mmap_lock); 951 mutex_init(&obj->mmap_lock);
diff --git a/arch/arm/plat-omap/iovmm.c b/arch/arm/plat-omap/iovmm.c
index fa6e64332a9e..6dc1296c8c77 100644
--- a/arch/arm/plat-omap/iovmm.c
+++ b/arch/arm/plat-omap/iovmm.c
@@ -280,13 +280,14 @@ static struct iovm_struct *alloc_iovm_area(struct iommu *obj, u32 da,
280 alignement = PAGE_SIZE; 280 alignement = PAGE_SIZE;
281 281
282 if (flags & IOVMF_DA_ANON) { 282 if (flags & IOVMF_DA_ANON) {
283 /* 283 start = obj->da_start;
284 * Reserve the first page for NULL 284
285 */
286 start = PAGE_SIZE;
287 if (flags & IOVMF_LINEAR) 285 if (flags & IOVMF_LINEAR)
288 alignement = iopgsz_max(bytes); 286 alignement = iopgsz_max(bytes);
289 start = roundup(start, alignement); 287 start = roundup(start, alignement);
288 } else if (start < obj->da_start || start > obj->da_end ||
289 obj->da_end - start < bytes) {
290 return ERR_PTR(-EINVAL);
290 } 291 }
291 292
292 tmp = NULL; 293 tmp = NULL;
@@ -299,16 +300,16 @@ static struct iovm_struct *alloc_iovm_area(struct iommu *obj, u32 da,
299 if (prev_end > start) 300 if (prev_end > start)
300 break; 301 break;
301 302
302 if (start + bytes <= tmp->da_start) 303 if (tmp->da_start > start && (tmp->da_start - start) >= bytes)
303 goto found; 304 goto found;
304 305
305 if (flags & IOVMF_DA_ANON) 306 if (tmp->da_end >= start && flags & IOVMF_DA_ANON)
306 start = roundup(tmp->da_end + 1, alignement); 307 start = roundup(tmp->da_end + 1, alignement);
307 308
308 prev_end = tmp->da_end; 309 prev_end = tmp->da_end;
309 } 310 }
310 311
311 if ((start >= prev_end) && (ULONG_MAX - start + 1 >= bytes)) 312 if ((start >= prev_end) && (obj->da_end - start >= bytes))
312 goto found; 313 goto found;
313 314
314 dev_dbg(obj->dev, "%s: no space to fit %08x(%x) flags: %08x\n", 315 dev_dbg(obj->dev, "%s: no space to fit %08x(%x) flags: %08x\n",