Commit ebf7cda0 authored by Omar Ramirez Luna's avatar Omar Ramirez Luna Committed by Joerg Roedel

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: default avatarOmar Ramirez Luna <omar.luna@linaro.org>
Tested-by: default avatarOhad Ben-Cohen <ohad@wizery.com>
Acked-by: default avatarTony Lindgren <tony@atomide.com>
Signed-off-by: default avatarJoerg Roedel <joro@8bytes.org>
parent 72b15b6a
...@@ -31,7 +31,6 @@ static int __init omap_iommu_dev_init(struct omap_hwmod *oh, void *unused) ...@@ -31,7 +31,6 @@ static int __init omap_iommu_dev_init(struct omap_hwmod *oh, void *unused)
return -ENOMEM; return -ENOMEM;
pdata->name = oh->name; pdata->name = oh->name;
pdata->clk_name = oh->main_clk;
pdata->nr_tlb_entries = a->nr_tlb_entries; pdata->nr_tlb_entries = a->nr_tlb_entries;
pdata->da_start = a->da_start; pdata->da_start = a->da_start;
pdata->da_end = a->da_end; pdata->da_end = a->da_end;
......
...@@ -16,13 +16,13 @@ ...@@ -16,13 +16,13 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/clk.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/iommu.h> #include <linux/iommu.h>
#include <linux/omap-iommu.h> #include <linux/omap-iommu.h>
#include <linux/mutex.h> #include <linux/mutex.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/pm_runtime.h>
#include <asm/cacheflush.h> #include <asm/cacheflush.h>
...@@ -160,7 +160,7 @@ static int iommu_enable(struct omap_iommu *obj) ...@@ -160,7 +160,7 @@ static int iommu_enable(struct omap_iommu *obj)
} }
} }
clk_enable(obj->clk); pm_runtime_get_sync(obj->dev);
err = arch_iommu->enable(obj); err = arch_iommu->enable(obj);
...@@ -177,7 +177,7 @@ static void iommu_disable(struct omap_iommu *obj) ...@@ -177,7 +177,7 @@ static void iommu_disable(struct omap_iommu *obj)
arch_iommu->disable(obj); arch_iommu->disable(obj);
clk_disable(obj->clk); pm_runtime_put_sync(obj->dev);
if (pdata->assert_reset) if (pdata->assert_reset)
pdata->assert_reset(pdev, pdata->reset_name); 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,7 +303,7 @@ static int load_iotlb_entry(struct omap_iommu *obj, struct iotlb_entry *e)
if (!obj || !obj->nr_tlb_entries || !e) if (!obj || !obj->nr_tlb_entries || !e)
return -EINVAL; return -EINVAL;
clk_enable(obj->clk); pm_runtime_get_sync(obj->dev);
iotlb_lock_get(obj, &l); iotlb_lock_get(obj, &l);
if (l.base == obj->nr_tlb_entries) { 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,7 +333,7 @@ static int load_iotlb_entry(struct omap_iommu *obj, struct iotlb_entry *e)
cr = iotlb_alloc_cr(obj, e); cr = iotlb_alloc_cr(obj, e);
if (IS_ERR(cr)) { if (IS_ERR(cr)) {
clk_disable(obj->clk); pm_runtime_put_sync(obj->dev);
return PTR_ERR(cr); return PTR_ERR(cr);
} }
...@@ -347,7 +347,7 @@ static int load_iotlb_entry(struct omap_iommu *obj, struct iotlb_entry *e) ...@@ -347,7 +347,7 @@ static int load_iotlb_entry(struct omap_iommu *obj, struct iotlb_entry *e)
l.vict = l.base; l.vict = l.base;
iotlb_lock_set(obj, &l); iotlb_lock_set(obj, &l);
out: out:
clk_disable(obj->clk); pm_runtime_put_sync(obj->dev);
return err; return err;
} }
...@@ -377,7 +377,7 @@ static void flush_iotlb_page(struct omap_iommu *obj, u32 da) ...@@ -377,7 +377,7 @@ static void flush_iotlb_page(struct omap_iommu *obj, u32 da)
int i; int i;
struct cr_regs cr; struct cr_regs cr;
clk_enable(obj->clk); pm_runtime_get_sync(obj->dev);
for_each_iotlb_cr(obj, obj->nr_tlb_entries, i, cr) { for_each_iotlb_cr(obj, obj->nr_tlb_entries, i, cr) {
u32 start; u32 start;
...@@ -396,7 +396,7 @@ static void flush_iotlb_page(struct omap_iommu *obj, u32 da) ...@@ -396,7 +396,7 @@ static void flush_iotlb_page(struct omap_iommu *obj, u32 da)
iommu_write_reg(obj, 1, MMU_FLUSH_ENTRY); iommu_write_reg(obj, 1, MMU_FLUSH_ENTRY);
} }
} }
clk_disable(obj->clk); pm_runtime_put_sync(obj->dev);
if (i == obj->nr_tlb_entries) if (i == obj->nr_tlb_entries)
dev_dbg(obj->dev, "%s: no page for %08x\n", __func__, da); 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,7 +410,7 @@ static void flush_iotlb_all(struct omap_iommu *obj)
{ {
struct iotlb_lock l; struct iotlb_lock l;
clk_enable(obj->clk); pm_runtime_get_sync(obj->dev);
l.base = 0; l.base = 0;
l.vict = 0; l.vict = 0;
...@@ -418,7 +418,7 @@ static void flush_iotlb_all(struct omap_iommu *obj) ...@@ -418,7 +418,7 @@ static void flush_iotlb_all(struct omap_iommu *obj)
iommu_write_reg(obj, 1, MMU_GFLUSH); iommu_write_reg(obj, 1, MMU_GFLUSH);
clk_disable(obj->clk); pm_runtime_put_sync(obj->dev);
} }
#if defined(CONFIG_OMAP_IOMMU_DEBUG) || defined(CONFIG_OMAP_IOMMU_DEBUG_MODULE) #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,11 +428,11 @@ ssize_t omap_iommu_dump_ctx(struct omap_iommu *obj, char *buf, ssize_t bytes)
if (!obj || !buf) if (!obj || !buf)
return -EINVAL; return -EINVAL;
clk_enable(obj->clk); pm_runtime_get_sync(obj->dev);
bytes = arch_iommu->dump_ctx(obj, buf, bytes); bytes = arch_iommu->dump_ctx(obj, buf, bytes);
clk_disable(obj->clk); pm_runtime_put_sync(obj->dev);
return bytes; return bytes;
} }
...@@ -446,7 +446,7 @@ __dump_tlb_entries(struct omap_iommu *obj, struct cr_regs *crs, int num) ...@@ -446,7 +446,7 @@ __dump_tlb_entries(struct omap_iommu *obj, struct cr_regs *crs, int num)
struct cr_regs tmp; struct cr_regs tmp;
struct cr_regs *p = crs; struct cr_regs *p = crs;
clk_enable(obj->clk); pm_runtime_get_sync(obj->dev);
iotlb_lock_get(obj, &saved); iotlb_lock_get(obj, &saved);
for_each_iotlb_cr(obj, num, i, tmp) { 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,7 +456,7 @@ __dump_tlb_entries(struct omap_iommu *obj, struct cr_regs *crs, int num)
} }
iotlb_lock_set(obj, &saved); iotlb_lock_set(obj, &saved);
clk_disable(obj->clk); pm_runtime_put_sync(obj->dev);
return p - crs; return p - crs;
} }
...@@ -946,10 +946,6 @@ static int __devinit omap_iommu_probe(struct platform_device *pdev) ...@@ -946,10 +946,6 @@ static int __devinit omap_iommu_probe(struct platform_device *pdev)
if (!obj) if (!obj)
return -ENOMEM; return -ENOMEM;
obj->clk = clk_get(&pdev->dev, pdata->clk_name);
if (IS_ERR(obj->clk))
goto err_clk;
obj->nr_tlb_entries = pdata->nr_tlb_entries; obj->nr_tlb_entries = pdata->nr_tlb_entries;
obj->name = pdata->name; obj->name = pdata->name;
obj->dev = &pdev->dev; obj->dev = &pdev->dev;
...@@ -992,6 +988,9 @@ static int __devinit omap_iommu_probe(struct platform_device *pdev) ...@@ -992,6 +988,9 @@ static int __devinit omap_iommu_probe(struct platform_device *pdev)
goto err_irq; goto err_irq;
platform_set_drvdata(pdev, obj); platform_set_drvdata(pdev, obj);
pm_runtime_irq_safe(obj->dev);
pm_runtime_enable(obj->dev);
dev_info(&pdev->dev, "%s registered\n", obj->name); dev_info(&pdev->dev, "%s registered\n", obj->name);
return 0; return 0;
...@@ -1000,8 +999,6 @@ static int __devinit omap_iommu_probe(struct platform_device *pdev) ...@@ -1000,8 +999,6 @@ static int __devinit omap_iommu_probe(struct platform_device *pdev)
err_ioremap: err_ioremap:
release_mem_region(res->start, resource_size(res)); release_mem_region(res->start, resource_size(res));
err_mem: err_mem:
clk_put(obj->clk);
err_clk:
kfree(obj); kfree(obj);
return err; return err;
} }
...@@ -1022,7 +1019,8 @@ static int __devexit omap_iommu_remove(struct platform_device *pdev) ...@@ -1022,7 +1019,8 @@ static int __devexit omap_iommu_remove(struct platform_device *pdev)
release_mem_region(res->start, resource_size(res)); release_mem_region(res->start, resource_size(res));
iounmap(obj->regbase); iounmap(obj->regbase);
clk_put(obj->clk); pm_runtime_disable(obj->dev);
dev_info(&pdev->dev, "%s removed\n", obj->name); dev_info(&pdev->dev, "%s removed\n", obj->name);
kfree(obj); kfree(obj);
return 0; return 0;
......
...@@ -29,7 +29,6 @@ struct iotlb_entry { ...@@ -29,7 +29,6 @@ struct iotlb_entry {
struct omap_iommu { struct omap_iommu {
const char *name; const char *name;
struct module *owner; struct module *owner;
struct clk *clk;
void __iomem *regbase; void __iomem *regbase;
struct device *dev; struct device *dev;
void *isr_priv; void *isr_priv;
...@@ -116,8 +115,6 @@ static inline struct omap_iommu *dev_to_omap_iommu(struct device *dev) ...@@ -116,8 +115,6 @@ static inline struct omap_iommu *dev_to_omap_iommu(struct device *dev)
* MMU Register offsets * MMU Register offsets
*/ */
#define MMU_REVISION 0x00 #define MMU_REVISION 0x00
#define MMU_SYSCONFIG 0x10
#define MMU_SYSSTATUS 0x14
#define MMU_IRQSTATUS 0x18 #define MMU_IRQSTATUS 0x18
#define MMU_IRQENABLE 0x1c #define MMU_IRQENABLE 0x1c
#define MMU_WALKING_ST 0x40 #define MMU_WALKING_ST 0x40
......
...@@ -28,15 +28,6 @@ ...@@ -28,15 +28,6 @@
*/ */
#define IOMMU_ARCH_VERSION 0x00000011 #define IOMMU_ARCH_VERSION 0x00000011
/* SYSCONF */
#define MMU_SYS_IDLE_SHIFT 3
#define MMU_SYS_IDLE_FORCE (0 << MMU_SYS_IDLE_SHIFT)
#define MMU_SYS_IDLE_NONE (1 << MMU_SYS_IDLE_SHIFT)
#define MMU_SYS_IDLE_SMART (2 << MMU_SYS_IDLE_SHIFT)
#define MMU_SYS_IDLE_MASK (3 << MMU_SYS_IDLE_SHIFT)
#define MMU_SYS_AUTOIDLE 1
/* IRQSTATUS & IRQENABLE */ /* IRQSTATUS & IRQENABLE */
#define MMU_IRQ_MULTIHITFAULT (1 << 4) #define MMU_IRQ_MULTIHITFAULT (1 << 4)
#define MMU_IRQ_TABLEWALKFAULT (1 << 3) #define MMU_IRQ_TABLEWALKFAULT (1 << 3)
...@@ -105,11 +96,6 @@ static int omap2_iommu_enable(struct omap_iommu *obj) ...@@ -105,11 +96,6 @@ static int omap2_iommu_enable(struct omap_iommu *obj)
dev_info(obj->dev, "%s: version %d.%d\n", obj->name, dev_info(obj->dev, "%s: version %d.%d\n", obj->name,
(l >> 4) & 0xf, l & 0xf); (l >> 4) & 0xf, l & 0xf);
l = iommu_read_reg(obj, MMU_SYSCONFIG);
l &= ~MMU_SYS_IDLE_MASK;
l |= (MMU_SYS_IDLE_SMART | MMU_SYS_AUTOIDLE);
iommu_write_reg(obj, l, MMU_SYSCONFIG);
iommu_write_reg(obj, pa, MMU_TTB); iommu_write_reg(obj, pa, MMU_TTB);
__iommu_set_twl(obj, true); __iommu_set_twl(obj, true);
...@@ -123,7 +109,6 @@ static void omap2_iommu_disable(struct omap_iommu *obj) ...@@ -123,7 +109,6 @@ static void omap2_iommu_disable(struct omap_iommu *obj)
l &= ~MMU_CNTL_MASK; l &= ~MMU_CNTL_MASK;
iommu_write_reg(obj, l, MMU_CNTL); iommu_write_reg(obj, l, MMU_CNTL);
iommu_write_reg(obj, MMU_SYS_IDLE_FORCE, MMU_SYSCONFIG);
dev_dbg(obj->dev, "%s is shutting down\n", obj->name); dev_dbg(obj->dev, "%s is shutting down\n", obj->name);
} }
...@@ -252,8 +237,6 @@ omap2_iommu_dump_ctx(struct omap_iommu *obj, char *buf, ssize_t len) ...@@ -252,8 +237,6 @@ omap2_iommu_dump_ctx(struct omap_iommu *obj, char *buf, ssize_t len)
char *p = buf; char *p = buf;
pr_reg(REVISION); pr_reg(REVISION);
pr_reg(SYSCONFIG);
pr_reg(SYSSTATUS);
pr_reg(IRQSTATUS); pr_reg(IRQSTATUS);
pr_reg(IRQENABLE); pr_reg(IRQENABLE);
pr_reg(WALKING_ST); pr_reg(WALKING_ST);
......
...@@ -44,7 +44,6 @@ struct omap_mmu_dev_attr { ...@@ -44,7 +44,6 @@ struct omap_mmu_dev_attr {
struct iommu_platform_data { struct iommu_platform_data {
const char *name; const char *name;
const char *clk_name;
const char *reset_name; const char *reset_name;
int nr_tlb_entries; int nr_tlb_entries;
u32 da_start; u32 da_start;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment