diff options
Diffstat (limited to 'drivers/iommu/omap-iommu.c')
| -rw-r--r-- | drivers/iommu/omap-iommu.c | 74 | 
1 files changed, 40 insertions, 34 deletions
diff --git a/drivers/iommu/omap-iommu.c b/drivers/iommu/omap-iommu.c index badc17c2bcb..d33c980e9c2 100644 --- a/drivers/iommu/omap-iommu.c +++ b/drivers/iommu/omap-iommu.c @@ -16,13 +16,13 @@  #include <linux/slab.h>  #include <linux/interrupt.h>  #include <linux/ioport.h> -#include <linux/clk.h>  #include <linux/platform_device.h>  #include <linux/iommu.h>  #include <linux/omap-iommu.h>  #include <linux/mutex.h>  #include <linux/spinlock.h>  #include <linux/io.h> +#include <linux/pm_runtime.h>  #include <asm/cacheflush.h> @@ -143,31 +143,44 @@ EXPORT_SYMBOL_GPL(omap_iommu_arch_version);  static int iommu_enable(struct omap_iommu *obj)  {  	int err; +	struct platform_device *pdev = to_platform_device(obj->dev); +	struct iommu_platform_data *pdata = pdev->dev.platform_data; -	if (!obj) +	if (!obj || !pdata)  		return -EINVAL;  	if (!arch_iommu)  		return -ENODEV; -	clk_enable(obj->clk); +	if (pdata->deassert_reset) { +		err = pdata->deassert_reset(pdev, pdata->reset_name); +		if (err) { +			dev_err(obj->dev, "deassert_reset failed: %d\n", err); +			return err; +		} +	} + +	pm_runtime_get_sync(obj->dev);  	err = arch_iommu->enable(obj); -	clk_disable(obj->clk);  	return err;  }  static void iommu_disable(struct omap_iommu *obj)  { -	if (!obj) -		return; +	struct platform_device *pdev = to_platform_device(obj->dev); +	struct iommu_platform_data *pdata = pdev->dev.platform_data; -	clk_enable(obj->clk); +	if (!obj || !pdata) +		return;  	arch_iommu->disable(obj); -	clk_disable(obj->clk); +	pm_runtime_put_sync(obj->dev); + +	if (pdata->assert_reset) +		pdata->assert_reset(pdev, pdata->reset_name);  }  /* @@ -290,7 +303,7 @@ static int load_iotlb_entry(struct omap_iommu *obj, struct iotlb_entry *e)  	if (!obj || !obj->nr_tlb_entries || !e)  		return -EINVAL; -	clk_enable(obj->clk); +	pm_runtime_get_sync(obj->dev);  	iotlb_lock_get(obj, &l);  	if (l.base == obj->nr_tlb_entries) { @@ -320,7 +333,7 @@ static int load_iotlb_entry(struct omap_iommu *obj, struct iotlb_entry *e)  	cr = iotlb_alloc_cr(obj, e);  	if (IS_ERR(cr)) { -		clk_disable(obj->clk); +		pm_runtime_put_sync(obj->dev);  		return PTR_ERR(cr);  	} @@ -334,7 +347,7 @@ static int load_iotlb_entry(struct omap_iommu *obj, struct iotlb_entry *e)  		l.vict = l.base;  	iotlb_lock_set(obj, &l);  out: -	clk_disable(obj->clk); +	pm_runtime_put_sync(obj->dev);  	return err;  } @@ -364,7 +377,7 @@ static void flush_iotlb_page(struct omap_iommu *obj, u32 da)  	int i;  	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) {  		u32 start; @@ -383,7 +396,7 @@ static void flush_iotlb_page(struct omap_iommu *obj, u32 da)  			iommu_write_reg(obj, 1, MMU_FLUSH_ENTRY);  		}  	} -	clk_disable(obj->clk); +	pm_runtime_put_sync(obj->dev);  	if (i == obj->nr_tlb_entries)  		dev_dbg(obj->dev, "%s: no page for %08x\n", __func__, da); @@ -397,7 +410,7 @@ static void flush_iotlb_all(struct omap_iommu *obj)  {  	struct iotlb_lock l; -	clk_enable(obj->clk); +	pm_runtime_get_sync(obj->dev);  	l.base = 0;  	l.vict = 0; @@ -405,7 +418,7 @@ static void flush_iotlb_all(struct omap_iommu *obj)  	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) @@ -415,11 +428,11 @@ ssize_t omap_iommu_dump_ctx(struct omap_iommu *obj, char *buf, ssize_t bytes)  	if (!obj || !buf)  		return -EINVAL; -	clk_enable(obj->clk); +	pm_runtime_get_sync(obj->dev);  	bytes = arch_iommu->dump_ctx(obj, buf, bytes); -	clk_disable(obj->clk); +	pm_runtime_put_sync(obj->dev);  	return bytes;  } @@ -433,7 +446,7 @@ __dump_tlb_entries(struct omap_iommu *obj, struct cr_regs *crs, int num)  	struct cr_regs tmp;  	struct cr_regs *p = crs; -	clk_enable(obj->clk); +	pm_runtime_get_sync(obj->dev);  	iotlb_lock_get(obj, &saved);  	for_each_iotlb_cr(obj, num, i, tmp) { @@ -443,7 +456,7 @@ __dump_tlb_entries(struct omap_iommu *obj, struct cr_regs *crs, int num)  	}  	iotlb_lock_set(obj, &saved); -	clk_disable(obj->clk); +	pm_runtime_put_sync(obj->dev);  	return  p - crs;  } @@ -807,9 +820,7 @@ static irqreturn_t iommu_fault_handler(int irq, void *data)  	if (!obj->refcount)  		return IRQ_NONE; -	clk_enable(obj->clk);  	errs = iommu_report_fault(obj, &da); -	clk_disable(obj->clk);  	if (errs == 0)  		return IRQ_HANDLED; @@ -923,7 +934,7 @@ static void omap_iommu_detach(struct omap_iommu *obj)  /*   *	OMAP Device MMU(IOMMU) detection   */ -static int __devinit omap_iommu_probe(struct platform_device *pdev) +static int omap_iommu_probe(struct platform_device *pdev)  {  	int err = -ENODEV;  	int irq; @@ -931,17 +942,10 @@ static int __devinit omap_iommu_probe(struct platform_device *pdev)  	struct resource *res;  	struct iommu_platform_data *pdata = pdev->dev.platform_data; -	if (pdev->num_resources != 2) -		return -EINVAL; -  	obj = kzalloc(sizeof(*obj) + MMU_REG_SIZE, GFP_KERNEL);  	if (!obj)  		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->name = pdata->name;  	obj->dev = &pdev->dev; @@ -984,6 +988,9 @@ static int __devinit omap_iommu_probe(struct platform_device *pdev)  		goto err_irq;  	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);  	return 0; @@ -992,13 +999,11 @@ err_irq:  err_ioremap:  	release_mem_region(res->start, resource_size(res));  err_mem: -	clk_put(obj->clk); -err_clk:  	kfree(obj);  	return err;  } -static int __devexit omap_iommu_remove(struct platform_device *pdev) +static int omap_iommu_remove(struct platform_device *pdev)  {  	int irq;  	struct resource *res; @@ -1014,7 +1019,8 @@ static int __devexit omap_iommu_remove(struct platform_device *pdev)  	release_mem_region(res->start, resource_size(res));  	iounmap(obj->regbase); -	clk_put(obj->clk); +	pm_runtime_disable(obj->dev); +  	dev_info(&pdev->dev, "%s removed\n", obj->name);  	kfree(obj);  	return 0; @@ -1022,7 +1028,7 @@ static int __devexit omap_iommu_remove(struct platform_device *pdev)  static struct platform_driver omap_iommu_driver = {  	.probe	= omap_iommu_probe, -	.remove	= __devexit_p(omap_iommu_remove), +	.remove	= omap_iommu_remove,  	.driver	= {  		.name	= "omap-iommu",  	},  |