aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/iommu/exynos-iommu.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/iommu/exynos-iommu.c')
-rw-r--r--drivers/iommu/exynos-iommu.c38
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
235static unsigned int __raw_sysmmu_version(struct sysmmu_drvdata *data)
236{
237 return MMU_RAW_VER(__raw_readl(data->sfrbase + REG_MMU_VERSION));
238}
239
222static bool sysmmu_block(void __iomem *sfrbase) 240static 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
375static void __sysmmu_init_config(struct sysmmu_drvdata *data) 393static 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)) {