aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/iommu
diff options
context:
space:
mode:
authorCho KyongHo <pullip.cho@samsung.com>2014-05-12 02:15:03 -0400
committerJoerg Roedel <jroedel@suse.de>2014-05-13 13:12:59 -0400
commiteeb5184bb7a149b539fe725ee8e9cd89b4bf2840 (patch)
tree8bcd7696908fdbdfe77b45bfa40a8c5fcf2e4aba /drivers/iommu
parent6b21a5db36427d54a94091fc26b5890c3d6a8af3 (diff)
iommu/exynos: Turn on useful configuration options
This turns on FLPD_CACHE, ACGEN and SYSSEL. FLPD_CACHE is a cache of 1st level page table entries that contains the address of a 2nd level page table to reduce latency of page table walking. ACGEN is architectural clock gating that gates clocks by System MMU itself if it is not active. Note that ACGEN is different from clock gating by the CPU. ACGEN just gates clocks to the internal logic of System MMU while clock gating by the CPU gates clocks to the System MMU. SYSSEL selects System MMU version in some Exynos SoCs. Some Exynos SoCs have an option to select System MMU versions exclusively because the SoCs adopts new System MMU version experimentally. This also always selects LRU as TLB replacement policy. Selecting TLB replacement policy is deprecated from System MMU 3.2. TLB in System MMU 3.3 has single TLB replacement policy, LRU. The bit of MMU_CFG selecting TLB replacement policy is remained as reserved. QoS value of page table walking is set to 15 (highst value). System MMU 3.3 can inherit QoS value of page table walking from its master H/W's transaction. This new feature is enabled by default and QoS value written to MMU_CFG is ignored. This patch also adds simplifies the sysmmu version checking by introducing some macros. Signed-off-by: Cho KyongHo <pullip.cho@samsung.com> Signed-off-by: Shaik Ameer Basha <shaik.ameer@samsung.com> Signed-off-by: Joerg Roedel <jroedel@suse.de>
Diffstat (limited to 'drivers/iommu')
-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)) {