summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndy Green <andy.green@linaro.org>2012-01-02 12:13:03 +0800
committerAndy Green <andy.green@linaro.org>2012-01-09 08:39:55 +0800
commit3f45858d6de845aa0e621bb211211e50da391a57 (patch)
tree9d2eb2d6c1d93bfdf9ced1ed46a315ff351bd702
parent1a847e6c0724675812dad47da5992233ecfc90db (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.c41
-rw-r--r--arch/arm/plat-omap/include/plat/iommu.h14
-rw-r--r--arch/arm/plat-omap/iodmm.c1
-rw-r--r--drivers/dsp/syslink/multicore_ipc/ipc.c4
-rw-r--r--drivers/iommu/omap-iommu.c67
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;