Commit ddfa975a authored by Kanigeri, Hari's avatar Kanigeri, Hari Committed by Hiroshi DOYU

omap iommu: add functionality to get TLB miss interrupt

In order to enable TLB miss interrupt, the TWL should be
disabled. This patch provides the functionality to get the
MMU fault interrupt for a TLB miss in the cases where the
users are working with the locked TLB entries and with TWL
disabled.
New interface is added to select twl and to enable TLB miss
interrupt.
Signed-off-by: default avatarHari Kanigeri <h-kanigeri2@ti.com>
Signed-off-by: default avatarRamesh Gupta <grgupta@ti.com>
Signed-off-by: default avatarHiroshi Doyu <Hiroshi.DOYU@nokia.com>
parent 993dd17e
...@@ -65,6 +65,26 @@ ...@@ -65,6 +65,26 @@
((pgsz) == MMU_CAM_PGSZ_64K) ? 0xffff0000 : \ ((pgsz) == MMU_CAM_PGSZ_64K) ? 0xffff0000 : \
((pgsz) == MMU_CAM_PGSZ_4K) ? 0xfffff000 : 0) ((pgsz) == MMU_CAM_PGSZ_4K) ? 0xfffff000 : 0)
static void __iommu_set_twl(struct iommu *obj, bool on)
{
u32 l = iommu_read_reg(obj, MMU_CNTL);
if (on)
iommu_write_reg(obj, MMU_IRQ_TWL_MASK, MMU_IRQENABLE);
else
iommu_write_reg(obj, MMU_IRQ_TLB_MISS_MASK, MMU_IRQENABLE);
l &= ~MMU_CNTL_MASK;
if (on)
l |= (MMU_CNTL_MMU_EN | MMU_CNTL_TWL_EN);
else
l |= (MMU_CNTL_MMU_EN);
iommu_write_reg(obj, l, MMU_CNTL);
}
static int omap2_iommu_enable(struct iommu *obj) static int omap2_iommu_enable(struct iommu *obj)
{ {
u32 l, pa; u32 l, pa;
...@@ -100,13 +120,9 @@ static int omap2_iommu_enable(struct iommu *obj) ...@@ -100,13 +120,9 @@ static int omap2_iommu_enable(struct iommu *obj)
l |= (MMU_SYS_IDLE_SMART | MMU_SYS_AUTOIDLE); l |= (MMU_SYS_IDLE_SMART | MMU_SYS_AUTOIDLE);
iommu_write_reg(obj, l, MMU_SYSCONFIG); iommu_write_reg(obj, l, MMU_SYSCONFIG);
iommu_write_reg(obj, MMU_IRQ_TWL_MASK, MMU_IRQENABLE);
iommu_write_reg(obj, pa, MMU_TTB); iommu_write_reg(obj, pa, MMU_TTB);
l = iommu_read_reg(obj, MMU_CNTL); __iommu_set_twl(obj, true);
l &= ~MMU_CNTL_MASK;
l |= (MMU_CNTL_MMU_EN | MMU_CNTL_TWL_EN);
iommu_write_reg(obj, l, MMU_CNTL);
return 0; return 0;
} }
...@@ -122,6 +138,11 @@ static void omap2_iommu_disable(struct iommu *obj) ...@@ -122,6 +138,11 @@ static void omap2_iommu_disable(struct iommu *obj)
dev_dbg(obj->dev, "%s is shutting down\n", obj->name); dev_dbg(obj->dev, "%s is shutting down\n", obj->name);
} }
static void omap2_iommu_set_twl(struct iommu *obj, bool on)
{
__iommu_set_twl(obj, false);
}
static u32 omap2_iommu_fault_isr(struct iommu *obj, u32 *ra) static u32 omap2_iommu_fault_isr(struct iommu *obj, u32 *ra)
{ {
int i; int i;
...@@ -304,6 +325,7 @@ static const struct iommu_functions omap2_iommu_ops = { ...@@ -304,6 +325,7 @@ static const struct iommu_functions omap2_iommu_ops = {
.enable = omap2_iommu_enable, .enable = omap2_iommu_enable,
.disable = omap2_iommu_disable, .disable = omap2_iommu_disable,
.set_twl = omap2_iommu_set_twl,
.fault_isr = omap2_iommu_fault_isr, .fault_isr = omap2_iommu_fault_isr,
.tlb_read_cr = omap2_tlb_read_cr, .tlb_read_cr = omap2_tlb_read_cr,
......
...@@ -80,6 +80,7 @@ struct iommu_functions { ...@@ -80,6 +80,7 @@ struct iommu_functions {
int (*enable)(struct iommu *obj); int (*enable)(struct iommu *obj);
void (*disable)(struct iommu *obj); void (*disable)(struct iommu *obj);
void (*set_twl)(struct iommu *obj, bool on);
u32 (*fault_isr)(struct iommu *obj, u32 *ra); u32 (*fault_isr)(struct iommu *obj, u32 *ra);
void (*tlb_read_cr)(struct iommu *obj, struct cr_regs *cr); 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); ...@@ -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 u32 iotlb_cr_to_virt(struct cr_regs *cr);
extern int load_iotlb_entry(struct iommu *obj, struct iotlb_entry *e); 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_page(struct iommu *obj, u32 da);
extern void flush_iotlb_range(struct iommu *obj, u32 start, u32 end); extern void flush_iotlb_range(struct iommu *obj, u32 start, u32 end);
extern void flush_iotlb_all(struct iommu *obj); extern void flush_iotlb_all(struct iommu *obj);
......
...@@ -370,6 +370,23 @@ void flush_iotlb_all(struct iommu *obj) ...@@ -370,6 +370,23 @@ void flush_iotlb_all(struct iommu *obj)
} }
EXPORT_SYMBOL_GPL(flush_iotlb_all); 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) #if defined(CONFIG_OMAP_IOMMU_DEBUG_MODULE)
ssize_t iommu_dump_ctx(struct iommu *obj, char *buf, ssize_t bytes) ssize_t iommu_dump_ctx(struct iommu *obj, char *buf, ssize_t bytes)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment