aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarek Szyprowski <m.szyprowski@samsung.com>2017-03-24 05:19:01 -0400
committerJoerg Roedel <jroedel@suse.de>2017-03-24 07:11:43 -0400
commitd5bf739dc7628a35b334cdb9058750388927760a (patch)
tree9929bda98dc8f1826872334ba115384b0de38ea0
parente75276638c1423d286e425fd29375e5736c7635c (diff)
iommu/exynos: Use smarter TLB flush method for v5 SYSMMU
SYSMMU v5 has dedicated registers to perform TLB flush range operation, so use them instead of looping with FLUSH_ENTRY command. Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com> Signed-off-by: Joerg Roedel <jroedel@suse.de>
-rw-r--r--drivers/iommu/exynos-iommu.c20
1 files changed, 16 insertions, 4 deletions
diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c
index b83df7196e76..88b26d3e8c2c 100644
--- a/drivers/iommu/exynos-iommu.c
+++ b/drivers/iommu/exynos-iommu.c
@@ -171,6 +171,9 @@ static u32 lv2ent_offset(sysmmu_iova_t iova)
171#define REG_V5_PT_BASE_PFN 0x00C 171#define REG_V5_PT_BASE_PFN 0x00C
172#define REG_V5_MMU_FLUSH_ALL 0x010 172#define REG_V5_MMU_FLUSH_ALL 0x010
173#define REG_V5_MMU_FLUSH_ENTRY 0x014 173#define REG_V5_MMU_FLUSH_ENTRY 0x014
174#define REG_V5_MMU_FLUSH_RANGE 0x018
175#define REG_V5_MMU_FLUSH_START 0x020
176#define REG_V5_MMU_FLUSH_END 0x024
174#define REG_V5_INT_STATUS 0x060 177#define REG_V5_INT_STATUS 0x060
175#define REG_V5_INT_CLEAR 0x064 178#define REG_V5_INT_CLEAR 0x064
176#define REG_V5_FAULT_AR_VA 0x070 179#define REG_V5_FAULT_AR_VA 0x070
@@ -319,14 +322,23 @@ static void __sysmmu_tlb_invalidate_entry(struct sysmmu_drvdata *data,
319{ 322{
320 unsigned int i; 323 unsigned int i;
321 324
322 for (i = 0; i < num_inv; i++) { 325 if (MMU_MAJ_VER(data->version) < 5) {
323 if (MMU_MAJ_VER(data->version) < 5) 326 for (i = 0; i < num_inv; i++) {
324 writel((iova & SPAGE_MASK) | 1, 327 writel((iova & SPAGE_MASK) | 1,
325 data->sfrbase + REG_MMU_FLUSH_ENTRY); 328 data->sfrbase + REG_MMU_FLUSH_ENTRY);
326 else 329 iova += SPAGE_SIZE;
330 }
331 } else {
332 if (num_inv == 1) {
327 writel((iova & SPAGE_MASK) | 1, 333 writel((iova & SPAGE_MASK) | 1,
328 data->sfrbase + REG_V5_MMU_FLUSH_ENTRY); 334 data->sfrbase + REG_V5_MMU_FLUSH_ENTRY);
329 iova += SPAGE_SIZE; 335 } else {
336 writel((iova & SPAGE_MASK),
337 data->sfrbase + REG_V5_MMU_FLUSH_START);
338 writel((iova & SPAGE_MASK) + (num_inv - 1) * SPAGE_SIZE,
339 data->sfrbase + REG_V5_MMU_FLUSH_END);
340 writel(1, data->sfrbase + REG_V5_MMU_FLUSH_RANGE);
341 }
330 } 342 }
331} 343}
332 344