diff options
author | Andy Green <andy.green@linaro.org> | 2012-01-02 12:13:03 +0800 |
---|---|---|
committer | Andy Green <andy.green@linaro.org> | 2012-01-09 08:39:55 +0800 |
commit | 3f45858d6de845aa0e621bb211211e50da391a57 (patch) | |
tree | 9d2eb2d6c1d93bfdf9ced1ed46a315ff351bd702 | |
parent | 1a847e6c0724675812dad47da5992233ecfc90db (diff) |
omap iommu migrate enable get put to domain
Signed-off-by: Andy Green <andy.green@linaro.org>
-rw-r--r-- | arch/arm/mach-omap2/iommu2.c | 41 | ||||
-rw-r--r-- | arch/arm/plat-omap/include/plat/iommu.h | 14 | ||||
-rw-r--r-- | arch/arm/plat-omap/iodmm.c | 1 | ||||
-rw-r--r-- | drivers/dsp/syslink/multicore_ipc/ipc.c | 4 | ||||
-rw-r--r-- | drivers/iommu/omap-iommu.c | 67 |
5 files changed, 86 insertions, 41 deletions
diff --git a/arch/arm/mach-omap2/iommu2.c b/arch/arm/mach-omap2/iommu2.c index a7dead52864..a8c7ac1e398 100644 --- a/arch/arm/mach-omap2/iommu2.c +++ b/arch/arm/mach-omap2/iommu2.c @@ -17,6 +17,7 @@ #include <linux/module.h> #include <linux/slab.h> #include <linux/stringify.h> +#include <linux/iommu.h> #include <plat/iommu.h> #include <plat/omap_device.h> @@ -104,22 +105,33 @@ static int omap2_iommu_enable(struct omap_iommu *obj) u32 l, pa; unsigned long timeout; int ret = 0; + struct iommu_domain *i_domain = obj->domain; + struct omap_iommu_domain *omap_domain; - if (!obj->iopgd) { - pr_err("omap2_iommu_enable: NULL obj->iopgd\n"); + if (!i_domain) { + pr_err("omap2_iommu_enable: NULL iommu_domain\n"); + return -EINVAL; + } + + omap_domain = i_domain->priv; + + if (!omap_domain) { + pr_err("omap2_iommu_enable: NULL omap_domain\n"); return -EINVAL; } - if (!IS_ALIGNED((u32)obj->iopgd, SZ_16K)) { - pr_err("omap2_iommu_enable: iopgd is not 16K aligned!\n"); + if (!omap_domain->pgtable) { + pr_err("omap2_iommu_enable: NULL omap_domain->pgtable\n"); return -EINVAL; } - - pa = virt_to_phys(obj->iopgd); + if (!IS_ALIGNED((u32)omap_domain->pgtable, SZ_16K)) { + pr_err("omap2_iommu_enable: omap_domain->pgtable is not 16K aligned!\n"); + return -EINVAL; + } + pa = virt_to_phys(omap_domain->pgtable); if (!IS_ALIGNED(pa, SZ_16K)) { pr_err("omap2_iommu_enable: virt_to_phys not 16K aligned!\n"); return -EINVAL; } - #ifdef CONFIG_OMAP_PM if (!strcmp(obj->name, "ducati")) { ret = omap_pm_set_max_sdma_lat(&pm_iommu1_handle, @@ -136,8 +148,10 @@ static int omap2_iommu_enable(struct omap_iommu *obj) return ret; } - iommu_write_reg(obj, MMU_SYS_SOFTRESET, MMU_SYSCONFIG); + if (!obj->regbase) + return 0; + iommu_write_reg(obj, MMU_SYS_SOFTRESET, MMU_SYSCONFIG); timeout = jiffies + msecs_to_jiffies(20); do { l = iommu_read_reg(obj, MMU_SYSSTATUS); @@ -172,12 +186,15 @@ static int omap2_iommu_enable(struct omap_iommu *obj) static void omap2_iommu_disable(struct omap_iommu *obj) { int ret = 0; + u32 l; - u32 l = iommu_read_reg(obj, MMU_CNTL); + if (obj->regbase) { + l = iommu_read_reg(obj, MMU_CNTL); - l &= ~MMU_CNTL_MASK; - iommu_write_reg(obj, l, MMU_CNTL); - iommu_write_reg(obj, MMU_SYS_IDLE_FORCE, MMU_SYSCONFIG); + l &= ~MMU_CNTL_MASK; + 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); if (omap_device_shutdown(obj->pdev)) diff --git a/arch/arm/plat-omap/include/plat/iommu.h b/arch/arm/plat-omap/include/plat/iommu.h index 360309fac59..51e4b80cd01 100644 --- a/arch/arm/plat-omap/include/plat/iommu.h +++ b/arch/arm/plat-omap/include/plat/iommu.h @@ -60,6 +60,20 @@ struct omap_iommu { spinlock_t event_lock; }; +/** + * * struct omap_iommu_domain - omap iommu domain + * * @pgtable: the page table + * * @iommu_dev: an omap iommu device attached to this domain. only a single + * * iommu device can be attached for now. + * * @lock: domain lock, should be taken when attaching/detaching + * */ +struct omap_iommu_domain { + u32 *pgtable; + struct omap_iommu *iommu_dev; + spinlock_t lock; +}; + + struct cr_regs { union { struct { diff --git a/arch/arm/plat-omap/iodmm.c b/arch/arm/plat-omap/iodmm.c index 54d5800d7af..c2a2cc9053c 100644 --- a/arch/arm/plat-omap/iodmm.c +++ b/arch/arm/plat-omap/iodmm.c @@ -804,7 +804,6 @@ static int phys_to_device_map(struct omap_iodmm_struct *obj, size_flag[i] | MMU_RAM_ENDIAN_LITTLE | MMU_RAM_ELSZ_32); - pr_err("phys_to_device_map: calling omap_iopgtable_store_entry\n"); omap_iopgtable_store_entry(obj->iovmm->iommu, &e); bytes -= pg_size[i]; da += pg_size[i]; diff --git a/drivers/dsp/syslink/multicore_ipc/ipc.c b/drivers/dsp/syslink/multicore_ipc/ipc.c index 323006f0a72..c8acd992d88 100644 --- a/drivers/dsp/syslink/multicore_ipc/ipc.c +++ b/drivers/dsp/syslink/multicore_ipc/ipc.c @@ -872,8 +872,10 @@ static int ipc_proc_sync_start(u16 remote_proc_id, void *shared_addr) Cache_inv((void *)remote, reserved_size, Cache_Type_ALL, true); #endif - if (remote->started_key != IPC_PROCSYNCSTART) + if (remote->started_key != IPC_PROCSYNCSTART) { + pr_err("(remote->started_key != IPC_PROCSYNCSTART))\n"); status = IPC_E_FAIL; + } goto exit; } diff --git a/drivers/iommu/omap-iommu.c b/drivers/iommu/omap-iommu.c index 5569084c4fe..7348620860c 100644 --- a/drivers/iommu/omap-iommu.c +++ b/drivers/iommu/omap-iommu.c @@ -33,19 +33,6 @@ (__i < (n)) && (cr = __iotlb_read_cr((obj), __i), true); \ __i++) -/** - * struct omap_iommu_domain - omap iommu domain - * @pgtable: the page table - * @iommu_dev: an omap iommu device attached to this domain. only a single - * iommu device can be attached for now. - * @lock: domain lock, should be taken when attaching/detaching - */ -struct omap_iommu_domain { - u32 *pgtable; - struct omap_iommu *iommu_dev; - spinlock_t lock; -}; - /* accommodate the difference between omap1 and omap2/3 */ static const struct omap_iommu_functions *arch_iommu; @@ -349,10 +336,6 @@ static void flush_iotlb_page(struct omap_iommu *obj, u32 da) int i; struct cr_regs cr; - pr_err("flush_iotlb_page: obj=%p da=0x%x\n", obj, da); - - WARN_ON(1); - for_each_iotlb_cr(obj, obj->nr_tlb_entries, i, cr) { u32 start; size_t bytes; @@ -882,38 +865,41 @@ static irqreturn_t iommu_fault_handler(int irq, void *data) u32 da, errs; u32 *iopgd, *iopte; struct omap_iommu *obj = data; - struct iommu_domain *domain = obj->domain; + struct iommu_domain *domain; + + if (!data) + return IRQ_NONE; if (!obj->refcount) return IRQ_NONE; + domain = obj->domain; + if (!domain) + pr_err("iommu_fault_handler: NULL domain\n"); eventfd_notification(obj); /* Dynamic loading TLB or PTE */ errs = iommu_notify_event(obj, IOMMU_FAULT, data); if (errs == NOTIFY_OK) return IRQ_HANDLED; - errs = iommu_report_fault(obj, &da); if (errs == 0) return IRQ_HANDLED; - +pr_err("d\n"); /* Fault callback or TLB/PTE Dynamic loading */ if (!report_iommu_fault(domain, obj->dev, da, 0)) return IRQ_HANDLED; - +pr_err("e\n"); iommu_disable(obj); - +pr_err("f\n"); iopgd = iopgd_offset(obj, da); - +pr_err("g\n"); if (!iopgd_is_table(*iopgd)) { dev_err(obj->dev, "%s: errs:0x%08x da:0x%08x pgd:0x%p " "*pgd:px%08x\n", obj->name, errs, da, iopgd, *iopgd); return IRQ_NONE; } - iopte = iopte_offset(iopgd, da); - dev_err(obj->dev, "%s: errs:0x%08x da:0x%08x pgd:0x%p *pgd:0x%08x " "pte:0x%p *pte:0x%08x\n", obj->name, errs, da, iopgd, *iopgd, iopte, *iopte); @@ -975,13 +961,15 @@ static struct omap_iommu *omap_iommu_attach(struct device *dev, u32 *iopgd) err = iommu_enable(obj); if (err) goto err_enable; - flush_iotlb_all(obj); + if (obj->regbase) + flush_iotlb_all(obj); if (!try_module_get(obj->owner)) goto err_module; spin_unlock(&obj->iommu_lock); - iommu_set_twl(obj, true); + if (obj->regbase) + iommu_set_twl(obj, true); dev_dbg(obj->dev, "%s: %s\n", __func__, obj->name); return obj; @@ -1057,10 +1045,35 @@ static int __devinit omap_iommu_probe(struct platform_device *pdev) if (err < 0) goto error; platform_set_drvdata(pdev, obj); + + if (obj->regbase) { + + obj->domain = iommu_domain_alloc(pdev->dev.bus); + if (!obj->domain) { + dev_err(&pdev->dev, "can't alloc iommu domain\n"); + err = -ENOMEM; + goto err_free_irq; + } + + err = iommu_attach_device(obj->domain, obj->dev); + if (err) { + dev_err(&pdev->dev, "can't attach iommu device: %d\n", err); + goto free_domain; + } + + BUG_ON(!IS_ALIGNED((unsigned long)obj->iopgd, IOPGD_TABLE_SIZE)); + } dev_info(&pdev->dev, "%s registered\n", obj->name); return 0; + +free_domain: + iommu_domain_free(obj->domain); + +err_free_irq: + free_irq(pdata->irq, obj); + error: kfree(obj); return err; |