diff options
Diffstat (limited to 'drivers/iommu/exynos-iommu.c')
-rw-r--r-- | drivers/iommu/exynos-iommu.c | 38 |
1 files changed, 34 insertions, 4 deletions
diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c index b937490fdd5d..26fb4d777ae2 100644 --- a/drivers/iommu/exynos-iommu.c +++ b/drivers/iommu/exynos-iommu.c | |||
@@ -93,6 +93,13 @@ static u32 lv2ent_offset(sysmmu_iova_t iova) | |||
93 | #define CTRL_BLOCK 0x7 | 93 | #define CTRL_BLOCK 0x7 |
94 | #define CTRL_DISABLE 0x0 | 94 | #define CTRL_DISABLE 0x0 |
95 | 95 | ||
96 | #define CFG_LRU 0x1 | ||
97 | #define CFG_QOS(n) ((n & 0xF) << 7) | ||
98 | #define CFG_MASK 0x0150FFFF /* Selecting bit 0-15, 20, 22 and 24 */ | ||
99 | #define CFG_ACGEN (1 << 24) /* System MMU 3.3 only */ | ||
100 | #define CFG_SYSSEL (1 << 22) /* System MMU 3.2 only */ | ||
101 | #define CFG_FLPDCACHE (1 << 20) /* System MMU 3.2+ only */ | ||
102 | |||
96 | #define REG_MMU_CTRL 0x000 | 103 | #define REG_MMU_CTRL 0x000 |
97 | #define REG_MMU_CFG 0x004 | 104 | #define REG_MMU_CFG 0x004 |
98 | #define REG_MMU_STATUS 0x008 | 105 | #define REG_MMU_STATUS 0x008 |
@@ -109,6 +116,12 @@ static u32 lv2ent_offset(sysmmu_iova_t iova) | |||
109 | 116 | ||
110 | #define REG_MMU_VERSION 0x034 | 117 | #define REG_MMU_VERSION 0x034 |
111 | 118 | ||
119 | #define MMU_MAJ_VER(val) ((val) >> 7) | ||
120 | #define MMU_MIN_VER(val) ((val) & 0x7F) | ||
121 | #define MMU_RAW_VER(reg) (((reg) >> 21) & ((1 << 11) - 1)) /* 11 bits */ | ||
122 | |||
123 | #define MAKE_MMU_VER(maj, min) ((((maj) & 0xF) << 7) | ((min) & 0x7F)) | ||
124 | |||
112 | #define REG_PB0_SADDR 0x04C | 125 | #define REG_PB0_SADDR 0x04C |
113 | #define REG_PB0_EADDR 0x050 | 126 | #define REG_PB0_EADDR 0x050 |
114 | #define REG_PB1_SADDR 0x054 | 127 | #define REG_PB1_SADDR 0x054 |
@@ -219,6 +232,11 @@ static void sysmmu_unblock(void __iomem *sfrbase) | |||
219 | __raw_writel(CTRL_ENABLE, sfrbase + REG_MMU_CTRL); | 232 | __raw_writel(CTRL_ENABLE, sfrbase + REG_MMU_CTRL); |
220 | } | 233 | } |
221 | 234 | ||
235 | static unsigned int __raw_sysmmu_version(struct sysmmu_drvdata *data) | ||
236 | { | ||
237 | return MMU_RAW_VER(__raw_readl(data->sfrbase + REG_MMU_VERSION)); | ||
238 | } | ||
239 | |||
222 | static bool sysmmu_block(void __iomem *sfrbase) | 240 | static bool sysmmu_block(void __iomem *sfrbase) |
223 | { | 241 | { |
224 | int i = 120; | 242 | int i = 120; |
@@ -374,7 +392,21 @@ static bool __sysmmu_disable(struct sysmmu_drvdata *data) | |||
374 | 392 | ||
375 | static void __sysmmu_init_config(struct sysmmu_drvdata *data) | 393 | static void __sysmmu_init_config(struct sysmmu_drvdata *data) |
376 | { | 394 | { |
377 | unsigned int cfg = 0; | 395 | unsigned int cfg = CFG_LRU | CFG_QOS(15); |
396 | unsigned int ver; | ||
397 | |||
398 | ver = __raw_sysmmu_version(data); | ||
399 | if (MMU_MAJ_VER(ver) == 3) { | ||
400 | if (MMU_MIN_VER(ver) >= 2) { | ||
401 | cfg |= CFG_FLPDCACHE; | ||
402 | if (MMU_MIN_VER(ver) == 3) { | ||
403 | cfg |= CFG_ACGEN; | ||
404 | cfg &= ~CFG_LRU; | ||
405 | } else { | ||
406 | cfg |= CFG_SYSSEL; | ||
407 | } | ||
408 | } | ||
409 | } | ||
378 | 410 | ||
379 | __raw_writel(cfg, data->sfrbase + REG_MMU_CFG); | 411 | __raw_writel(cfg, data->sfrbase + REG_MMU_CFG); |
380 | } | 412 | } |
@@ -494,13 +526,11 @@ static void sysmmu_tlb_invalidate_entry(struct device *dev, sysmmu_iova_t iova, | |||
494 | 526 | ||
495 | spin_lock_irqsave(&data->lock, flags); | 527 | spin_lock_irqsave(&data->lock, flags); |
496 | if (is_sysmmu_active(data)) { | 528 | if (is_sysmmu_active(data)) { |
497 | unsigned int maj; | ||
498 | unsigned int num_inv = 1; | 529 | unsigned int num_inv = 1; |
499 | 530 | ||
500 | if (!IS_ERR(data->clk_master)) | 531 | if (!IS_ERR(data->clk_master)) |
501 | clk_enable(data->clk_master); | 532 | clk_enable(data->clk_master); |
502 | 533 | ||
503 | maj = __raw_readl(data->sfrbase + REG_MMU_VERSION); | ||
504 | /* | 534 | /* |
505 | * L2TLB invalidation required | 535 | * L2TLB invalidation required |
506 | * 4KB page: 1 invalidation | 536 | * 4KB page: 1 invalidation |
@@ -511,7 +541,7 @@ static void sysmmu_tlb_invalidate_entry(struct device *dev, sysmmu_iova_t iova, | |||
511 | * 1MB page can be cached in one of all sets. | 541 | * 1MB page can be cached in one of all sets. |
512 | * 64KB page can be one of 16 consecutive sets. | 542 | * 64KB page can be one of 16 consecutive sets. |
513 | */ | 543 | */ |
514 | if ((maj >> 28) == 2) /* major version number */ | 544 | if (MMU_MAJ_VER(__raw_sysmmu_version(data)) == 2) |
515 | num_inv = min_t(unsigned int, size / PAGE_SIZE, 64); | 545 | num_inv = min_t(unsigned int, size / PAGE_SIZE, 64); |
516 | 546 | ||
517 | if (sysmmu_block(data->sfrbase)) { | 547 | if (sysmmu_block(data->sfrbase)) { |