@@ -124,6 +124,18 @@ static void omap2_iommu_disable(struct iommu *obj)
dev_dbg(obj->dev, "%s is shutting down\n", obj->name);
}
+static void omap2_iommu_disable_twl(struct iommu *obj)
+{
+ u32 l = iommu_read_reg(obj, MMU_CNTL);
+
+ l &= ~MMU_CNTL_MASK;
+ l |= (MMU_CNTL_MMU_EN);
+ iommu_write_reg(obj, l, MMU_CNTL);
+
+ /* Enable TLB miss interrupt */
+ iommu_write_reg(obj, MMU_IRQ_TLB_MISS_MASK, MMU_IRQENABLE);
+}
+
static u32 omap2_iommu_fault_isr(struct iommu *obj, u32 *ra)
{
int i;
@@ -306,6 +318,7 @@ static const struct iommu_functions omap2_iommu_ops = {
.enable = omap2_iommu_enable,
.disable = omap2_iommu_disable,
+ .disable_twl = omap2_iommu_disable_twl,
.fault_isr = omap2_iommu_fault_isr,
.tlb_read_cr = omap2_tlb_read_cr,
@@ -80,6 +80,7 @@ struct iommu_functions {
int (*enable)(struct iommu *obj);
void (*disable)(struct iommu *obj);
+ void (*disable_twl)(struct iommu *obj);
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_disable_twl(struct iommu *obj);
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);
@@ -370,6 +370,18 @@ void flush_iotlb_all(struct iommu *obj)
}
EXPORT_SYMBOL_GPL(flush_iotlb_all);
+/**
+ * Call this function if working with locked TLB entries and
+ * TWL disabled
+ */
+extern void iommu_disable_twl(struct iommu *obj)
+{
+ clk_enable(obj->clk);
+ arch_iommu->disable_twl(obj);
+ clk_disable(obj->clk);
+}
+EXPORT_SYMBOL_GPL(iommu_disable_twl);
+
#if defined(CONFIG_OMAP_IOMMU_DEBUG_MODULE)
ssize_t iommu_dump_ctx(struct iommu *obj, char *buf, ssize_t bytes)