diff options
Diffstat (limited to 'arch/arm/plat-s5p/s5p-sysmmu.c')
-rw-r--r-- | arch/arm/plat-s5p/s5p-sysmmu.c | 42 |
1 files changed, 42 insertions, 0 deletions
diff --git a/arch/arm/plat-s5p/s5p-sysmmu.c b/arch/arm/plat-s5p/s5p-sysmmu.c index dae74e1..70edd49 100644 --- a/arch/arm/plat-s5p/s5p-sysmmu.c +++ b/arch/arm/plat-s5p/s5p-sysmmu.c @@ -85,6 +85,11 @@ static struct sysmmu_drvdata *get_sysmmu_data(struct device *owner, return NULL; } +struct list_head *get_sysmmu_list(void) +{ + return &sysmmu_list; +} + static struct sysmmu_drvdata *get_sysmmu_data_rollback(struct device *owner, struct sysmmu_drvdata *start) { @@ -148,6 +153,12 @@ static void __sysmmu_tlb_invalidate(void __iomem *sfrbase) __raw_writel(0x1, sfrbase + S5P_MMU_FLUSH); } +static void __sysmmu_tlb_invalidate_entry(void __iomem *sfrbase, + unsigned long iova) +{ + __raw_writel((iova & PAGE_MASK) | 1, sfrbase + S5P_MMU_FLUSH_ENTRY); +} + static void __sysmmu_set_ptbase(void __iomem *sfrbase, unsigned long pgd) { @@ -322,6 +333,8 @@ void s5p_sysmmu_set_tablebase_pgd(struct device *owner, unsigned long pgd) { struct sysmmu_drvdata *mmudata = NULL; + s5p_sysmmu_tlb_invalidate(owner); + while ((mmudata = get_sysmmu_data(owner, mmudata))) { unsigned long flags; @@ -467,6 +480,35 @@ void s5p_sysmmu_tlb_invalidate(struct device *owner) } } +void s5p_sysmmu_tlb_invalidate_entry(struct device *owner, unsigned long iova, + unsigned int count, + unsigned long page_size) +{ + struct sysmmu_drvdata *mmudata = NULL; + + while ((mmudata = get_sysmmu_data(owner, mmudata))) { + unsigned long flags; + + read_lock_irqsave(&mmudata->lock, flags); + + if (is_sysmmu_active(mmudata)) { + while (count > 0) { + sysmmu_block(mmudata->sfrbase); + __sysmmu_tlb_invalidate_entry(mmudata->sfrbase, + iova); + sysmmu_unblock(mmudata->sfrbase); + count--; + iova += page_size; + } + } else { + dev_dbg(mmudata->dev, + "Disabled: Skipping invalidating TLB.\n"); + } + + read_unlock_irqrestore(&mmudata->lock, flags); + } +} + static int s5p_sysmmu_probe(struct platform_device *pdev) { struct resource *res, *ioarea; |