summaryrefslogtreecommitdiffstats
path: root/arch/arm/plat-omap
diff options
context:
space:
mode:
authorTony Lindgren <tony@atomide.com>2010-07-02 11:23:30 +0300
committerTony Lindgren <tony@atomide.com>2010-07-02 11:23:30 +0300
commitf40fd0e215b1bde4e43add1aacbe6faf6dbbea53 (patch)
tree05eeb8b7236f07303510162602afe05bfceecebe /arch/arm/plat-omap
parent9f2952dbcbc0a143cff19f2e44fc504901aad86f (diff)
parent1fd7f467127fcaea490451052fea22f234bbb206 (diff)
Merge branch 'v2.6.35-rc3-iommu-for-next' of git://gitorious.org/~doyu/lk/mainline into omap-for-linus
Diffstat (limited to 'arch/arm/plat-omap')
-rw-r--r--arch/arm/plat-omap/include/plat/iommu.h2
-rw-r--r--arch/arm/plat-omap/iommu.c27
-rw-r--r--arch/arm/plat-omap/iopgtable.h8
3 files changed, 30 insertions, 7 deletions
diff --git a/arch/arm/plat-omap/include/plat/iommu.h b/arch/arm/plat-omap/include/plat/iommu.h
index 0752af9d099..33c7d41cb6a 100644
--- a/arch/arm/plat-omap/include/plat/iommu.h
+++ b/arch/arm/plat-omap/include/plat/iommu.h
@@ -80,6 +80,7 @@ struct iommu_functions {
int (*enable)(struct iommu *obj);
void (*disable)(struct iommu *obj);
+ void (*set_twl)(struct iommu *obj, bool on);
u32 (*fault_isr)(struct iommu *obj, u32 *ra);
void (*tlb_read_cr)(struct iommu *obj, struct cr_regs *cr);
@@ -143,6 +144,7 @@ extern void iotlb_cr_to_e(struct cr_regs *cr, struct iotlb_entry *e);
extern u32 iotlb_cr_to_virt(struct cr_regs *cr);
extern int load_iotlb_entry(struct iommu *obj, struct iotlb_entry *e);
+extern void iommu_set_twl(struct iommu *obj, bool on);
extern void flush_iotlb_page(struct iommu *obj, u32 da);
extern void flush_iotlb_range(struct iommu *obj, u32 start, u32 end);
extern void flush_iotlb_all(struct iommu *obj);
diff --git a/arch/arm/plat-omap/iommu.c b/arch/arm/plat-omap/iommu.c
index bc094dbacee..a202a2ce6e3 100644
--- a/arch/arm/plat-omap/iommu.c
+++ b/arch/arm/plat-omap/iommu.c
@@ -370,6 +370,23 @@ void flush_iotlb_all(struct iommu *obj)
}
EXPORT_SYMBOL_GPL(flush_iotlb_all);
+/**
+ * iommu_set_twl - enable/disable table walking logic
+ * @obj: target iommu
+ * @on: enable/disable
+ *
+ * Function used to enable/disable TWL. If one wants to work
+ * exclusively with locked TLB entries and receive notifications
+ * for TLB miss then call this function to disable TWL.
+ */
+void iommu_set_twl(struct iommu *obj, bool on)
+{
+ clk_enable(obj->clk);
+ arch_iommu->set_twl(obj, on);
+ clk_disable(obj->clk);
+}
+EXPORT_SYMBOL_GPL(iommu_set_twl);
+
#if defined(CONFIG_OMAP_IOMMU_DEBUG_MODULE)
ssize_t iommu_dump_ctx(struct iommu *obj, char *buf, ssize_t bytes)
@@ -653,7 +670,7 @@ void iopgtable_lookup_entry(struct iommu *obj, u32 da, u32 **ppgd, u32 **ppte)
if (!*iopgd)
goto out;
- if (*iopgd & IOPGD_TABLE)
+ if (iopgd_is_table(*iopgd))
iopte = iopte_offset(iopgd, da);
out:
*ppgd = iopgd;
@@ -670,7 +687,7 @@ static size_t iopgtable_clear_entry_core(struct iommu *obj, u32 da)
if (!*iopgd)
return 0;
- if (*iopgd & IOPGD_TABLE) {
+ if (iopgd_is_table(*iopgd)) {
int i;
u32 *iopte = iopte_offset(iopgd, da);
@@ -745,7 +762,7 @@ static void iopgtable_clear_entry_all(struct iommu *obj)
if (!*iopgd)
continue;
- if (*iopgd & IOPGD_TABLE)
+ if (iopgd_is_table(*iopgd))
iopte_free(iopte_offset(iopgd, 0));
*iopgd = 0;
@@ -783,9 +800,11 @@ static irqreturn_t iommu_fault_handler(int irq, void *data)
if (!stat)
return IRQ_HANDLED;
+ iommu_disable(obj);
+
iopgd = iopgd_offset(obj, da);
- if (!(*iopgd & IOPGD_TABLE)) {
+ if (!iopgd_is_table(*iopgd)) {
dev_err(obj->dev, "%s: da:%08x pgd:%p *pgd:%08x\n", __func__,
da, iopgd, *iopgd);
return IRQ_NONE;
diff --git a/arch/arm/plat-omap/iopgtable.h b/arch/arm/plat-omap/iopgtable.h
index ab23b6a140f..c3e93bb0911 100644
--- a/arch/arm/plat-omap/iopgtable.h
+++ b/arch/arm/plat-omap/iopgtable.h
@@ -63,6 +63,8 @@
#define IOPGD_SECTION (2 << 0)
#define IOPGD_SUPER (1 << 18 | 2 << 0)
+#define iopgd_is_table(x) (((x) & 3) == IOPGD_TABLE)
+
#define IOPTE_SMALL (2 << 0)
#define IOPTE_LARGE (1 << 0)
@@ -70,12 +72,12 @@
#define iopgd_index(da) (((da) >> IOPGD_SHIFT) & (PTRS_PER_IOPGD - 1))
#define iopgd_offset(obj, da) ((obj)->iopgd + iopgd_index(da))
-#define iopte_paddr(iopgd) (*iopgd & ~((1 << 10) - 1))
-#define iopte_vaddr(iopgd) ((u32 *)phys_to_virt(iopte_paddr(iopgd)))
+#define iopgd_page_paddr(iopgd) (*iopgd & ~((1 << 10) - 1))
+#define iopgd_page_vaddr(iopgd) ((u32 *)phys_to_virt(iopgd_page_paddr(iopgd)))
/* to find an entry in the second-level page table. */
#define iopte_index(da) (((da) >> IOPTE_SHIFT) & (PTRS_PER_IOPTE - 1))
-#define iopte_offset(iopgd, da) (iopte_vaddr(iopgd) + iopte_index(da))
+#define iopte_offset(iopgd, da) (iopgd_page_vaddr(iopgd) + iopte_index(da))
static inline u32 iotlb_init_entry(struct iotlb_entry *e, u32 da, u32 pa,
u32 flags)