aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/iommu
diff options
context:
space:
mode:
authorOmar Ramirez Luna <omar.luna@linaro.org>2012-11-19 20:05:51 -0500
committerJoerg Roedel <joro@8bytes.org>2012-12-03 12:48:23 -0500
commitebf7cda0f92effd8169b831fae81e9437dce1fef (patch)
tree4c506bb094eee7c2128c7c9b17a6b0480a99a0dd /drivers/iommu
parent72b15b6ae97796c5fac687addde5dbfab872cf94 (diff)
iommu/omap: Adapt to runtime pm
Use runtime PM functionality interfaced with hwmod enable/idle functions, to replace direct clock operations and sysconfig handling. Due to reset sequence, pm_runtime_[get|put]_sync must be used, to avoid possible operations with the module under reset. Because of this and given that the driver uses spin_locks to protect their critical sections, we must use pm_runtime_irq_safe in order for the runtime ops to be happy, otherwise might_sleep_if checks in runtime framework will complain. The remaining pm_runtime out of iommu_enable and iommu_disable corresponds to paths that can be accessed through debugfs, some of them doesn't work if the module is not enabled first, but in future if the mmu is idled withouth freeing, these are needed to debug. Signed-off-by: Omar Ramirez Luna <omar.luna@linaro.org> Tested-by: Ohad Ben-Cohen <ohad@wizery.com> Acked-by: Tony Lindgren <tony@atomide.com> Signed-off-by: Joerg Roedel <joro@8bytes.org>
Diffstat (limited to 'drivers/iommu')
-rw-r--r--drivers/iommu/omap-iommu.c40
-rw-r--r--drivers/iommu/omap-iommu.h3
-rw-r--r--drivers/iommu/omap-iommu2.c17
3 files changed, 19 insertions, 41 deletions
diff --git a/drivers/iommu/omap-iommu.c b/drivers/iommu/omap-iommu.c
index af9b4f31f594..18108c1405e2 100644
--- a/drivers/iommu/omap-iommu.c
+++ b/drivers/iommu/omap-iommu.c
@@ -16,13 +16,13 @@
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>
22#include <linux/omap-iommu.h> 21#include <linux/omap-iommu.h>
23#include <linux/mutex.h> 22#include <linux/mutex.h>
24#include <linux/spinlock.h> 23#include <linux/spinlock.h>
25#include <linux/io.h> 24#include <linux/io.h>
25#include <linux/pm_runtime.h>
26 26
27#include <asm/cacheflush.h> 27#include <asm/cacheflush.h>
28 28
@@ -160,7 +160,7 @@ static int iommu_enable(struct omap_iommu *obj)
160 } 160 }
161 } 161 }
162 162
163 clk_enable(obj->clk); 163 pm_runtime_get_sync(obj->dev);
164 164
165 err = arch_iommu->enable(obj); 165 err = arch_iommu->enable(obj);
166 166
@@ -177,7 +177,7 @@ static void iommu_disable(struct omap_iommu *obj)
177 177
178 arch_iommu->disable(obj); 178 arch_iommu->disable(obj);
179 179
180 clk_disable(obj->clk); 180 pm_runtime_put_sync(obj->dev);
181 181
182 if (pdata->assert_reset) 182 if (pdata->assert_reset)
183 pdata->assert_reset(pdev, pdata->reset_name); 183 pdata->assert_reset(pdev, pdata->reset_name);
@@ -303,7 +303,7 @@ static int load_iotlb_entry(struct omap_iommu *obj, struct iotlb_entry *e)
303 if (!obj || !obj->nr_tlb_entries || !e) 303 if (!obj || !obj->nr_tlb_entries || !e)
304 return -EINVAL; 304 return -EINVAL;
305 305
306 clk_enable(obj->clk); 306 pm_runtime_get_sync(obj->dev);
307 307
308 iotlb_lock_get(obj, &l); 308 iotlb_lock_get(obj, &l);
309 if (l.base == obj->nr_tlb_entries) { 309 if (l.base == obj->nr_tlb_entries) {
@@ -333,7 +333,7 @@ static int load_iotlb_entry(struct omap_iommu *obj, struct iotlb_entry *e)
333 333
334 cr = iotlb_alloc_cr(obj, e); 334 cr = iotlb_alloc_cr(obj, e);
335 if (IS_ERR(cr)) { 335 if (IS_ERR(cr)) {
336 clk_disable(obj->clk); 336 pm_runtime_put_sync(obj->dev);
337 return PTR_ERR(cr); 337 return PTR_ERR(cr);
338 } 338 }
339 339
@@ -347,7 +347,7 @@ static int load_iotlb_entry(struct omap_iommu *obj, struct iotlb_entry *e)
347 l.vict = l.base; 347 l.vict = l.base;
348 iotlb_lock_set(obj, &l); 348 iotlb_lock_set(obj, &l);
349out: 349out:
350 clk_disable(obj->clk); 350 pm_runtime_put_sync(obj->dev);
351 return err; 351 return err;
352} 352}
353 353
@@ -377,7 +377,7 @@ static void flush_iotlb_page(struct omap_iommu *obj, u32 da)
377 int i; 377 int i;
378 struct cr_regs cr; 378 struct cr_regs cr;
379 379
380 clk_enable(obj->clk); 380 pm_runtime_get_sync(obj->dev);
381 381
382 for_each_iotlb_cr(obj, obj->nr_tlb_entries, i, cr) { 382 for_each_iotlb_cr(obj, obj->nr_tlb_entries, i, cr) {
383 u32 start; 383 u32 start;
@@ -396,7 +396,7 @@ static void flush_iotlb_page(struct omap_iommu *obj, u32 da)
396 iommu_write_reg(obj, 1, MMU_FLUSH_ENTRY); 396 iommu_write_reg(obj, 1, MMU_FLUSH_ENTRY);
397 } 397 }
398 } 398 }
399 clk_disable(obj->clk); 399 pm_runtime_put_sync(obj->dev);
400 400
401 if (i == obj->nr_tlb_entries) 401 if (i == obj->nr_tlb_entries)
402 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);
@@ -410,7 +410,7 @@ static void flush_iotlb_all(struct omap_iommu *obj)
410{ 410{
411 struct iotlb_lock l; 411 struct iotlb_lock l;
412 412
413 clk_enable(obj->clk); 413 pm_runtime_get_sync(obj->dev);
414 414
415 l.base = 0; 415 l.base = 0;
416 l.vict = 0; 416 l.vict = 0;
@@ -418,7 +418,7 @@ static void flush_iotlb_all(struct omap_iommu *obj)
418 418
419 iommu_write_reg(obj, 1, MMU_GFLUSH); 419 iommu_write_reg(obj, 1, MMU_GFLUSH);
420 420
421 clk_disable(obj->clk); 421 pm_runtime_put_sync(obj->dev);
422} 422}
423 423
424#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)
@@ -428,11 +428,11 @@ ssize_t omap_iommu_dump_ctx(struct omap_iommu *obj, char *buf, ssize_t bytes)
428 if (!obj || !buf) 428 if (!obj || !buf)
429 return -EINVAL; 429 return -EINVAL;
430 430
431 clk_enable(obj->clk); 431 pm_runtime_get_sync(obj->dev);
432 432
433 bytes = arch_iommu->dump_ctx(obj, buf, bytes); 433 bytes = arch_iommu->dump_ctx(obj, buf, bytes);
434 434
435 clk_disable(obj->clk); 435 pm_runtime_put_sync(obj->dev);
436 436
437 return bytes; 437 return bytes;
438} 438}
@@ -446,7 +446,7 @@ __dump_tlb_entries(struct omap_iommu *obj, struct cr_regs *crs, int num)
446 struct cr_regs tmp; 446 struct cr_regs tmp;
447 struct cr_regs *p = crs; 447 struct cr_regs *p = crs;
448 448
449 clk_enable(obj->clk); 449 pm_runtime_get_sync(obj->dev);
450 iotlb_lock_get(obj, &saved); 450 iotlb_lock_get(obj, &saved);
451 451
452 for_each_iotlb_cr(obj, num, i, tmp) { 452 for_each_iotlb_cr(obj, num, i, tmp) {
@@ -456,7 +456,7 @@ __dump_tlb_entries(struct omap_iommu *obj, struct cr_regs *crs, int num)
456 } 456 }
457 457
458 iotlb_lock_set(obj, &saved); 458 iotlb_lock_set(obj, &saved);
459 clk_disable(obj->clk); 459 pm_runtime_put_sync(obj->dev);
460 460
461 return p - crs; 461 return p - crs;
462} 462}
@@ -946,10 +946,6 @@ static int __devinit omap_iommu_probe(struct platform_device *pdev)
946 if (!obj) 946 if (!obj)
947 return -ENOMEM; 947 return -ENOMEM;
948 948
949 obj->clk = clk_get(&pdev->dev, pdata->clk_name);
950 if (IS_ERR(obj->clk))
951 goto err_clk;
952
953 obj->nr_tlb_entries = pdata->nr_tlb_entries; 949 obj->nr_tlb_entries = pdata->nr_tlb_entries;
954 obj->name = pdata->name; 950 obj->name = pdata->name;
955 obj->dev = &pdev->dev; 951 obj->dev = &pdev->dev;
@@ -992,6 +988,9 @@ static int __devinit omap_iommu_probe(struct platform_device *pdev)
992 goto err_irq; 988 goto err_irq;
993 platform_set_drvdata(pdev, obj); 989 platform_set_drvdata(pdev, obj);
994 990
991 pm_runtime_irq_safe(obj->dev);
992 pm_runtime_enable(obj->dev);
993
995 dev_info(&pdev->dev, "%s registered\n", obj->name); 994 dev_info(&pdev->dev, "%s registered\n", obj->name);
996 return 0; 995 return 0;
997 996
@@ -1000,8 +999,6 @@ err_irq:
1000err_ioremap: 999err_ioremap:
1001 release_mem_region(res->start, resource_size(res)); 1000 release_mem_region(res->start, resource_size(res));
1002err_mem: 1001err_mem:
1003 clk_put(obj->clk);
1004err_clk:
1005 kfree(obj); 1002 kfree(obj);
1006 return err; 1003 return err;
1007} 1004}
@@ -1022,7 +1019,8 @@ static int __devexit omap_iommu_remove(struct platform_device *pdev)
1022 release_mem_region(res->start, resource_size(res)); 1019 release_mem_region(res->start, resource_size(res));
1023 iounmap(obj->regbase); 1020 iounmap(obj->regbase);
1024 1021
1025 clk_put(obj->clk); 1022 pm_runtime_disable(obj->dev);
1023
1026 dev_info(&pdev->dev, "%s removed\n", obj->name); 1024 dev_info(&pdev->dev, "%s removed\n", obj->name);
1027 kfree(obj); 1025 kfree(obj);
1028 return 0; 1026 return 0;
diff --git a/drivers/iommu/omap-iommu.h b/drivers/iommu/omap-iommu.h
index 2b5f3c04d167..120084206602 100644
--- a/drivers/iommu/omap-iommu.h
+++ b/drivers/iommu/omap-iommu.h
@@ -29,7 +29,6 @@ struct iotlb_entry {
29struct omap_iommu { 29struct omap_iommu {
30 const char *name; 30 const char *name;
31 struct module *owner; 31 struct module *owner;
32 struct clk *clk;
33 void __iomem *regbase; 32 void __iomem *regbase;
34 struct device *dev; 33 struct device *dev;
35 void *isr_priv; 34 void *isr_priv;
@@ -116,8 +115,6 @@ static inline struct omap_iommu *dev_to_omap_iommu(struct device *dev)
116 * MMU Register offsets 115 * MMU Register offsets
117 */ 116 */
118#define MMU_REVISION 0x00 117#define MMU_REVISION 0x00
119#define MMU_SYSCONFIG 0x10
120#define MMU_SYSSTATUS 0x14
121#define MMU_IRQSTATUS 0x18 118#define MMU_IRQSTATUS 0x18
122#define MMU_IRQENABLE 0x1c 119#define MMU_IRQENABLE 0x1c
123#define MMU_WALKING_ST 0x40 120#define MMU_WALKING_ST 0x40
diff --git a/drivers/iommu/omap-iommu2.c b/drivers/iommu/omap-iommu2.c
index 4a3a1c7a38c1..d745094a69dd 100644
--- a/drivers/iommu/omap-iommu2.c
+++ b/drivers/iommu/omap-iommu2.c
@@ -28,15 +28,6 @@
28 */ 28 */
29#define IOMMU_ARCH_VERSION 0x00000011 29#define IOMMU_ARCH_VERSION 0x00000011
30 30
31/* SYSCONF */
32#define MMU_SYS_IDLE_SHIFT 3
33#define MMU_SYS_IDLE_FORCE (0 << MMU_SYS_IDLE_SHIFT)
34#define MMU_SYS_IDLE_NONE (1 << MMU_SYS_IDLE_SHIFT)
35#define MMU_SYS_IDLE_SMART (2 << MMU_SYS_IDLE_SHIFT)
36#define MMU_SYS_IDLE_MASK (3 << MMU_SYS_IDLE_SHIFT)
37
38#define MMU_SYS_AUTOIDLE 1
39
40/* IRQSTATUS & IRQENABLE */ 31/* IRQSTATUS & IRQENABLE */
41#define MMU_IRQ_MULTIHITFAULT (1 << 4) 32#define MMU_IRQ_MULTIHITFAULT (1 << 4)
42#define MMU_IRQ_TABLEWALKFAULT (1 << 3) 33#define MMU_IRQ_TABLEWALKFAULT (1 << 3)
@@ -105,11 +96,6 @@ static int omap2_iommu_enable(struct omap_iommu *obj)
105 dev_info(obj->dev, "%s: version %d.%d\n", obj->name, 96 dev_info(obj->dev, "%s: version %d.%d\n", obj->name,
106 (l >> 4) & 0xf, l & 0xf); 97 (l >> 4) & 0xf, l & 0xf);
107 98
108 l = iommu_read_reg(obj, MMU_SYSCONFIG);
109 l &= ~MMU_SYS_IDLE_MASK;
110 l |= (MMU_SYS_IDLE_SMART | MMU_SYS_AUTOIDLE);
111 iommu_write_reg(obj, l, MMU_SYSCONFIG);
112
113 iommu_write_reg(obj, pa, MMU_TTB); 99 iommu_write_reg(obj, pa, MMU_TTB);
114 100
115 __iommu_set_twl(obj, true); 101 __iommu_set_twl(obj, true);
@@ -123,7 +109,6 @@ static void omap2_iommu_disable(struct omap_iommu *obj)
123 109
124 l &= ~MMU_CNTL_MASK; 110 l &= ~MMU_CNTL_MASK;
125 iommu_write_reg(obj, l, MMU_CNTL); 111 iommu_write_reg(obj, l, MMU_CNTL);
126 iommu_write_reg(obj, MMU_SYS_IDLE_FORCE, MMU_SYSCONFIG);
127 112
128 dev_dbg(obj->dev, "%s is shutting down\n", obj->name); 113 dev_dbg(obj->dev, "%s is shutting down\n", obj->name);
129} 114}
@@ -252,8 +237,6 @@ omap2_iommu_dump_ctx(struct omap_iommu *obj, char *buf, ssize_t len)
252 char *p = buf; 237 char *p = buf;
253 238
254 pr_reg(REVISION); 239 pr_reg(REVISION);
255 pr_reg(SYSCONFIG);
256 pr_reg(SYSSTATUS);
257 pr_reg(IRQSTATUS); 240 pr_reg(IRQSTATUS);
258 pr_reg(IRQENABLE); 241 pr_reg(IRQENABLE);
259 pr_reg(WALKING_ST); 242 pr_reg(WALKING_ST);