Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Omar Ramirez Luna and committed by
Joerg Roedel
ebf7cda0 72b15b6a

+19 -43
-1
arch/arm/mach-omap2/omap-iommu.c
··· 31 31 return -ENOMEM; 32 32 33 33 pdata->name = oh->name; 34 - pdata->clk_name = oh->main_clk; 35 34 pdata->nr_tlb_entries = a->nr_tlb_entries; 36 35 pdata->da_start = a->da_start; 37 36 pdata->da_end = a->da_end;
+19 -21
drivers/iommu/omap-iommu.c
··· 16 16 #include <linux/slab.h> 17 17 #include <linux/interrupt.h> 18 18 #include <linux/ioport.h> 19 - #include <linux/clk.h> 20 19 #include <linux/platform_device.h> 21 20 #include <linux/iommu.h> 22 21 #include <linux/omap-iommu.h> 23 22 #include <linux/mutex.h> 24 23 #include <linux/spinlock.h> 25 24 #include <linux/io.h> 25 + #include <linux/pm_runtime.h> 26 26 27 27 #include <asm/cacheflush.h> 28 28 ··· 160 160 } 161 161 } 162 162 163 - clk_enable(obj->clk); 163 + pm_runtime_get_sync(obj->dev); 164 164 165 165 err = arch_iommu->enable(obj); 166 166 ··· 177 177 178 178 arch_iommu->disable(obj); 179 179 180 - clk_disable(obj->clk); 180 + pm_runtime_put_sync(obj->dev); 181 181 182 182 if (pdata->assert_reset) 183 183 pdata->assert_reset(pdev, pdata->reset_name); ··· 303 303 if (!obj || !obj->nr_tlb_entries || !e) 304 304 return -EINVAL; 305 305 306 - clk_enable(obj->clk); 306 + pm_runtime_get_sync(obj->dev); 307 307 308 308 iotlb_lock_get(obj, &l); 309 309 if (l.base == obj->nr_tlb_entries) { ··· 333 333 334 334 cr = iotlb_alloc_cr(obj, e); 335 335 if (IS_ERR(cr)) { 336 - clk_disable(obj->clk); 336 + pm_runtime_put_sync(obj->dev); 337 337 return PTR_ERR(cr); 338 338 } 339 339 ··· 347 347 l.vict = l.base; 348 348 iotlb_lock_set(obj, &l); 349 349 out: 350 - clk_disable(obj->clk); 350 + pm_runtime_put_sync(obj->dev); 351 351 return err; 352 352 } 353 353 ··· 377 377 int i; 378 378 struct cr_regs cr; 379 379 380 - clk_enable(obj->clk); 380 + pm_runtime_get_sync(obj->dev); 381 381 382 382 for_each_iotlb_cr(obj, obj->nr_tlb_entries, i, cr) { 383 383 u32 start; ··· 396 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 401 if (i == obj->nr_tlb_entries) 402 402 dev_dbg(obj->dev, "%s: no page for %08x\n", __func__, da); ··· 410 410 { 411 411 struct iotlb_lock l; 412 412 413 - clk_enable(obj->clk); 413 + pm_runtime_get_sync(obj->dev); 414 414 415 415 l.base = 0; 416 416 l.vict = 0; ··· 418 418 419 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 424 #if defined(CONFIG_OMAP_IOMMU_DEBUG) || defined(CONFIG_OMAP_IOMMU_DEBUG_MODULE) ··· 428 428 if (!obj || !buf) 429 429 return -EINVAL; 430 430 431 - clk_enable(obj->clk); 431 + pm_runtime_get_sync(obj->dev); 432 432 433 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 437 return bytes; 438 438 } ··· 446 446 struct cr_regs tmp; 447 447 struct cr_regs *p = crs; 448 448 449 - clk_enable(obj->clk); 449 + pm_runtime_get_sync(obj->dev); 450 450 iotlb_lock_get(obj, &saved); 451 451 452 452 for_each_iotlb_cr(obj, num, i, tmp) { ··· 456 456 } 457 457 458 458 iotlb_lock_set(obj, &saved); 459 - clk_disable(obj->clk); 459 + pm_runtime_put_sync(obj->dev); 460 460 461 461 return p - crs; 462 462 } ··· 946 946 if (!obj) 947 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 949 obj->nr_tlb_entries = pdata->nr_tlb_entries; 954 950 obj->name = pdata->name; 955 951 obj->dev = &pdev->dev; ··· 988 992 goto err_irq; 989 993 platform_set_drvdata(pdev, obj); 990 994 995 + pm_runtime_irq_safe(obj->dev); 996 + pm_runtime_enable(obj->dev); 997 + 991 998 dev_info(&pdev->dev, "%s registered\n", obj->name); 992 999 return 0; 993 1000 ··· 999 1000 err_ioremap: 1000 1001 release_mem_region(res->start, resource_size(res)); 1001 1002 err_mem: 1002 - clk_put(obj->clk); 1003 - err_clk: 1004 1003 kfree(obj); 1005 1004 return err; 1006 1005 } ··· 1019 1022 release_mem_region(res->start, resource_size(res)); 1020 1023 iounmap(obj->regbase); 1021 1024 1022 - clk_put(obj->clk); 1025 + pm_runtime_disable(obj->dev); 1026 + 1023 1027 dev_info(&pdev->dev, "%s removed\n", obj->name); 1024 1028 kfree(obj); 1025 1029 return 0;
-3
drivers/iommu/omap-iommu.h
··· 29 29 struct omap_iommu { 30 30 const char *name; 31 31 struct module *owner; 32 - struct clk *clk; 33 32 void __iomem *regbase; 34 33 struct device *dev; 35 34 void *isr_priv; ··· 115 116 * MMU Register offsets 116 117 */ 117 118 #define MMU_REVISION 0x00 118 - #define MMU_SYSCONFIG 0x10 119 - #define MMU_SYSSTATUS 0x14 120 119 #define MMU_IRQSTATUS 0x18 121 120 #define MMU_IRQENABLE 0x1c 122 121 #define MMU_WALKING_ST 0x40
-17
drivers/iommu/omap-iommu2.c
··· 28 28 */ 29 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 31 /* IRQSTATUS & IRQENABLE */ 41 32 #define MMU_IRQ_MULTIHITFAULT (1 << 4) 42 33 #define MMU_IRQ_TABLEWALKFAULT (1 << 3) ··· 96 105 dev_info(obj->dev, "%s: version %d.%d\n", obj->name, 97 106 (l >> 4) & 0xf, l & 0xf); 98 107 99 - l = iommu_read_reg(obj, MMU_SYSCONFIG); 100 - l &= ~MMU_SYS_IDLE_MASK; 101 - l |= (MMU_SYS_IDLE_SMART | MMU_SYS_AUTOIDLE); 102 - iommu_write_reg(obj, l, MMU_SYSCONFIG); 103 - 104 108 iommu_write_reg(obj, pa, MMU_TTB); 105 109 106 110 __iommu_set_twl(obj, true); ··· 109 123 110 124 l &= ~MMU_CNTL_MASK; 111 125 iommu_write_reg(obj, l, MMU_CNTL); 112 - iommu_write_reg(obj, MMU_SYS_IDLE_FORCE, MMU_SYSCONFIG); 113 126 114 127 dev_dbg(obj->dev, "%s is shutting down\n", obj->name); 115 128 } ··· 237 252 char *p = buf; 238 253 239 254 pr_reg(REVISION); 240 - pr_reg(SYSCONFIG); 241 - pr_reg(SYSSTATUS); 242 255 pr_reg(IRQSTATUS); 243 256 pr_reg(IRQENABLE); 244 257 pr_reg(WALKING_ST);
-1
include/linux/platform_data/iommu-omap.h
··· 44 44 45 45 struct iommu_platform_data { 46 46 const char *name; 47 - const char *clk_name; 48 47 const char *reset_name; 49 48 int nr_tlb_entries; 50 49 u32 da_start;