aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/iommu/omap-iommu.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/iommu/omap-iommu.c')
-rw-r--r--drivers/iommu/omap-iommu.c107
1 files changed, 74 insertions, 33 deletions
diff --git a/drivers/iommu/omap-iommu.c b/drivers/iommu/omap-iommu.c
index d0b1234581b..18108c1405e 100644
--- a/drivers/iommu/omap-iommu.c
+++ b/drivers/iommu/omap-iommu.c
@@ -16,17 +16,20 @@
16#include <linux/slab.h> 16#include <linux/slab.h>
17#include <linux/interrupt.h> 17#include <linux/interrupt.h>
18#include <linux/ioport.h> 18#include <linux/ioport.h>
19#include <linux/clk.h>
20#include <linux/platform_device.h> 19#include <linux/platform_device.h>
21#include <linux/iommu.h> 20#include <linux/iommu.h>
21#include <linux/omap-iommu.h>
22#include <linux/mutex.h> 22#include <linux/mutex.h>
23#include <linux/spinlock.h> 23#include <linux/spinlock.h>
24#include <linux/io.h>
25#include <linux/pm_runtime.h>
24 26
25#include <asm/cacheflush.h> 27#include <asm/cacheflush.h>
26 28
27#include <plat/iommu.h> 29#include <linux/platform_data/iommu-omap.h>
28 30
29#include <plat/iopgtable.h> 31#include "omap-iopgtable.h"
32#include "omap-iommu.h"
30 33
31#define for_each_iotlb_cr(obj, n, __i, cr) \ 34#define for_each_iotlb_cr(obj, n, __i, cr) \
32 for (__i = 0; \ 35 for (__i = 0; \
@@ -51,6 +54,21 @@ struct omap_iommu_domain {
51 spinlock_t lock; 54 spinlock_t lock;
52}; 55};
53 56
57#define MMU_LOCK_BASE_SHIFT 10
58#define MMU_LOCK_BASE_MASK (0x1f << MMU_LOCK_BASE_SHIFT)
59#define MMU_LOCK_BASE(x) \
60 ((x & MMU_LOCK_BASE_MASK) >> MMU_LOCK_BASE_SHIFT)
61
62#define MMU_LOCK_VICT_SHIFT 4
63#define MMU_LOCK_VICT_MASK (0x1f << MMU_LOCK_VICT_SHIFT)
64#define MMU_LOCK_VICT(x) \
65 ((x & MMU_LOCK_VICT_MASK) >> MMU_LOCK_VICT_SHIFT)
66
67struct iotlb_lock {
68 short base;
69 short vict;
70};
71
54/* accommodate the difference between omap1 and omap2/3 */ 72/* accommodate the difference between omap1 and omap2/3 */
55static const struct iommu_functions *arch_iommu; 73static const struct iommu_functions *arch_iommu;
56 74
@@ -125,31 +143,44 @@ EXPORT_SYMBOL_GPL(omap_iommu_arch_version);
125static int iommu_enable(struct omap_iommu *obj) 143static int iommu_enable(struct omap_iommu *obj)
126{ 144{
127 int err; 145 int err;
146 struct platform_device *pdev = to_platform_device(obj->dev);
147 struct iommu_platform_data *pdata = pdev->dev.platform_data;
128 148
129 if (!obj) 149 if (!obj || !pdata)
130 return -EINVAL; 150 return -EINVAL;
131 151
132 if (!arch_iommu) 152 if (!arch_iommu)
133 return -ENODEV; 153 return -ENODEV;
134 154
135 clk_enable(obj->clk); 155 if (pdata->deassert_reset) {
156 err = pdata->deassert_reset(pdev, pdata->reset_name);
157 if (err) {
158 dev_err(obj->dev, "deassert_reset failed: %d\n", err);
159 return err;
160 }
161 }
162
163 pm_runtime_get_sync(obj->dev);
136 164
137 err = arch_iommu->enable(obj); 165 err = arch_iommu->enable(obj);
138 166
139 clk_disable(obj->clk);
140 return err; 167 return err;
141} 168}
142 169
143static void iommu_disable(struct omap_iommu *obj) 170static void iommu_disable(struct omap_iommu *obj)
144{ 171{
145 if (!obj) 172 struct platform_device *pdev = to_platform_device(obj->dev);
146 return; 173 struct iommu_platform_data *pdata = pdev->dev.platform_data;
147 174
148 clk_enable(obj->clk); 175 if (!obj || !pdata)
176 return;
149 177
150 arch_iommu->disable(obj); 178 arch_iommu->disable(obj);
151 179
152 clk_disable(obj->clk); 180 pm_runtime_put_sync(obj->dev);
181
182 if (pdata->assert_reset)
183 pdata->assert_reset(pdev, pdata->reset_name);
153} 184}
154 185
155/* 186/*
@@ -272,7 +303,7 @@ static int load_iotlb_entry(struct omap_iommu *obj, struct iotlb_entry *e)
272 if (!obj || !obj->nr_tlb_entries || !e) 303 if (!obj || !obj->nr_tlb_entries || !e)
273 return -EINVAL; 304 return -EINVAL;
274 305
275 clk_enable(obj->clk); 306 pm_runtime_get_sync(obj->dev);
276 307
277 iotlb_lock_get(obj, &l); 308 iotlb_lock_get(obj, &l);
278 if (l.base == obj->nr_tlb_entries) { 309 if (l.base == obj->nr_tlb_entries) {
@@ -302,7 +333,7 @@ static int load_iotlb_entry(struct omap_iommu *obj, struct iotlb_entry *e)
302 333
303 cr = iotlb_alloc_cr(obj, e); 334 cr = iotlb_alloc_cr(obj, e);
304 if (IS_ERR(cr)) { 335 if (IS_ERR(cr)) {
305 clk_disable(obj->clk); 336 pm_runtime_put_sync(obj->dev);
306 return PTR_ERR(cr); 337 return PTR_ERR(cr);
307 } 338 }
308 339
@@ -316,7 +347,7 @@ static int load_iotlb_entry(struct omap_iommu *obj, struct iotlb_entry *e)
316 l.vict = l.base; 347 l.vict = l.base;
317 iotlb_lock_set(obj, &l); 348 iotlb_lock_set(obj, &l);
318out: 349out:
319 clk_disable(obj->clk); 350 pm_runtime_put_sync(obj->dev);
320 return err; 351 return err;
321} 352}
322 353
@@ -346,7 +377,7 @@ static void flush_iotlb_page(struct omap_iommu *obj, u32 da)
346 int i; 377 int i;
347 struct cr_regs cr; 378 struct cr_regs cr;
348 379
349 clk_enable(obj->clk); 380 pm_runtime_get_sync(obj->dev);
350 381
351 for_each_iotlb_cr(obj, obj->nr_tlb_entries, i, cr) { 382 for_each_iotlb_cr(obj, obj->nr_tlb_entries, i, cr) {
352 u32 start; 383 u32 start;
@@ -365,7 +396,7 @@ static void flush_iotlb_page(struct omap_iommu *obj, u32 da)
365 iommu_write_reg(obj, 1, MMU_FLUSH_ENTRY); 396 iommu_write_reg(obj, 1, MMU_FLUSH_ENTRY);
366 } 397 }
367 } 398 }
368 clk_disable(obj->clk); 399 pm_runtime_put_sync(obj->dev);
369 400
370 if (i == obj->nr_tlb_entries) 401 if (i == obj->nr_tlb_entries)
371 dev_dbg(obj->dev, "%s: no page for %08x\n", __func__, da); 402 dev_dbg(obj->dev, "%s: no page for %08x\n", __func__, da);
@@ -379,7 +410,7 @@ static void flush_iotlb_all(struct omap_iommu *obj)
379{ 410{
380 struct iotlb_lock l; 411 struct iotlb_lock l;
381 412
382 clk_enable(obj->clk); 413 pm_runtime_get_sync(obj->dev);
383 414
384 l.base = 0; 415 l.base = 0;
385 l.vict = 0; 416 l.vict = 0;
@@ -387,7 +418,7 @@ static void flush_iotlb_all(struct omap_iommu *obj)
387 418
388 iommu_write_reg(obj, 1, MMU_GFLUSH); 419 iommu_write_reg(obj, 1, MMU_GFLUSH);
389 420
390 clk_disable(obj->clk); 421 pm_runtime_put_sync(obj->dev);
391} 422}
392 423
393#if defined(CONFIG_OMAP_IOMMU_DEBUG) || defined(CONFIG_OMAP_IOMMU_DEBUG_MODULE) 424#if defined(CONFIG_OMAP_IOMMU_DEBUG) || defined(CONFIG_OMAP_IOMMU_DEBUG_MODULE)
@@ -397,11 +428,11 @@ ssize_t omap_iommu_dump_ctx(struct omap_iommu *obj, char *buf, ssize_t bytes)
397 if (!obj || !buf) 428 if (!obj || !buf)
398 return -EINVAL; 429 return -EINVAL;
399 430
400 clk_enable(obj->clk); 431 pm_runtime_get_sync(obj->dev);
401 432
402 bytes = arch_iommu->dump_ctx(obj, buf, bytes); 433 bytes = arch_iommu->dump_ctx(obj, buf, bytes);
403 434
404 clk_disable(obj->clk); 435 pm_runtime_put_sync(obj->dev);
405 436
406 return bytes; 437 return bytes;
407} 438}
@@ -415,7 +446,7 @@ __dump_tlb_entries(struct omap_iommu *obj, struct cr_regs *crs, int num)
415 struct cr_regs tmp; 446 struct cr_regs tmp;
416 struct cr_regs *p = crs; 447 struct cr_regs *p = crs;
417 448
418 clk_enable(obj->clk); 449 pm_runtime_get_sync(obj->dev);
419 iotlb_lock_get(obj, &saved); 450 iotlb_lock_get(obj, &saved);
420 451
421 for_each_iotlb_cr(obj, num, i, tmp) { 452 for_each_iotlb_cr(obj, num, i, tmp) {
@@ -425,7 +456,7 @@ __dump_tlb_entries(struct omap_iommu *obj, struct cr_regs *crs, int num)
425 } 456 }
426 457
427 iotlb_lock_set(obj, &saved); 458 iotlb_lock_set(obj, &saved);
428 clk_disable(obj->clk); 459 pm_runtime_put_sync(obj->dev);
429 460
430 return p - crs; 461 return p - crs;
431} 462}
@@ -789,9 +820,7 @@ static irqreturn_t iommu_fault_handler(int irq, void *data)
789 if (!obj->refcount) 820 if (!obj->refcount)
790 return IRQ_NONE; 821 return IRQ_NONE;
791 822
792 clk_enable(obj->clk);
793 errs = iommu_report_fault(obj, &da); 823 errs = iommu_report_fault(obj, &da);
794 clk_disable(obj->clk);
795 if (errs == 0) 824 if (errs == 0)
796 return IRQ_HANDLED; 825 return IRQ_HANDLED;
797 826
@@ -913,17 +942,10 @@ static int __devinit omap_iommu_probe(struct platform_device *pdev)
913 struct resource *res; 942 struct resource *res;
914 struct iommu_platform_data *pdata = pdev->dev.platform_data; 943 struct iommu_platform_data *pdata = pdev->dev.platform_data;
915 944
916 if (pdev->num_resources != 2)
917 return -EINVAL;
918
919 obj = kzalloc(sizeof(*obj) + MMU_REG_SIZE, GFP_KERNEL); 945 obj = kzalloc(sizeof(*obj) + MMU_REG_SIZE, GFP_KERNEL);
920 if (!obj) 946 if (!obj)
921 return -ENOMEM; 947 return -ENOMEM;
922 948
923 obj->clk = clk_get(&pdev->dev, pdata->clk_name);
924 if (IS_ERR(obj->clk))
925 goto err_clk;
926
927 obj->nr_tlb_entries = pdata->nr_tlb_entries; 949 obj->nr_tlb_entries = pdata->nr_tlb_entries;
928 obj->name = pdata->name; 950 obj->name = pdata->name;
929 obj->dev = &pdev->dev; 951 obj->dev = &pdev->dev;
@@ -966,6 +988,9 @@ static int __devinit omap_iommu_probe(struct platform_device *pdev)
966 goto err_irq; 988 goto err_irq;
967 platform_set_drvdata(pdev, obj); 989 platform_set_drvdata(pdev, obj);
968 990
991 pm_runtime_irq_safe(obj->dev);
992 pm_runtime_enable(obj->dev);
993
969 dev_info(&pdev->dev, "%s registered\n", obj->name); 994 dev_info(&pdev->dev, "%s registered\n", obj->name);
970 return 0; 995 return 0;
971 996
@@ -974,8 +999,6 @@ err_irq:
974err_ioremap: 999err_ioremap:
975 release_mem_region(res->start, resource_size(res)); 1000 release_mem_region(res->start, resource_size(res));
976err_mem: 1001err_mem:
977 clk_put(obj->clk);
978err_clk:
979 kfree(obj); 1002 kfree(obj);
980 return err; 1003 return err;
981} 1004}
@@ -996,7 +1019,8 @@ static int __devexit omap_iommu_remove(struct platform_device *pdev)
996 release_mem_region(res->start, resource_size(res)); 1019 release_mem_region(res->start, resource_size(res));
997 iounmap(obj->regbase); 1020 iounmap(obj->regbase);
998 1021
999 clk_put(obj->clk); 1022 pm_runtime_disable(obj->dev);
1023
1000 dev_info(&pdev->dev, "%s removed\n", obj->name); 1024 dev_info(&pdev->dev, "%s removed\n", obj->name);
1001 kfree(obj); 1025 kfree(obj);
1002 return 0; 1026 return 0;
@@ -1015,6 +1039,23 @@ static void iopte_cachep_ctor(void *iopte)
1015 clean_dcache_area(iopte, IOPTE_TABLE_SIZE); 1039 clean_dcache_area(iopte, IOPTE_TABLE_SIZE);
1016} 1040}
1017 1041
1042static u32 iotlb_init_entry(struct iotlb_entry *e, u32 da, u32 pa,
1043 u32 flags)
1044{
1045 memset(e, 0, sizeof(*e));
1046
1047 e->da = da;
1048 e->pa = pa;
1049 e->valid = 1;
1050 /* FIXME: add OMAP1 support */
1051 e->pgsz = flags & MMU_CAM_PGSZ_MASK;
1052 e->endian = flags & MMU_RAM_ENDIAN_MASK;
1053 e->elsz = flags & MMU_RAM_ELSZ_MASK;
1054 e->mixed = flags & MMU_RAM_MIXED_MASK;
1055
1056 return iopgsz_to_bytes(e->pgsz);
1057}
1058
1018static int omap_iommu_map(struct iommu_domain *domain, unsigned long da, 1059static int omap_iommu_map(struct iommu_domain *domain, unsigned long da,
1019 phys_addr_t pa, size_t bytes, int prot) 1060 phys_addr_t pa, size_t bytes, int prot)
1020{ 1061{