diff options
-rw-r--r-- | Documentation/devicetree/bindings/iommu/samsung,sysmmu.txt | 5 | ||||
-rw-r--r-- | drivers/iommu/Kconfig | 2 | ||||
-rw-r--r-- | drivers/iommu/exynos-iommu.c | 187 |
3 files changed, 143 insertions, 51 deletions
diff --git a/Documentation/devicetree/bindings/iommu/samsung,sysmmu.txt b/Documentation/devicetree/bindings/iommu/samsung,sysmmu.txt index f61ca25ca136..85f068805dd8 100644 --- a/Documentation/devicetree/bindings/iommu/samsung,sysmmu.txt +++ b/Documentation/devicetree/bindings/iommu/samsung,sysmmu.txt | |||
@@ -35,9 +35,10 @@ Required properties: | |||
35 | - interrupts: An interrupt specifier for interrupt signal of System MMU, | 35 | - interrupts: An interrupt specifier for interrupt signal of System MMU, |
36 | according to the format defined by a particular interrupt | 36 | according to the format defined by a particular interrupt |
37 | controller. | 37 | controller. |
38 | - clock-names: Should be "sysmmu" if the System MMU is needed to gate its clock. | 38 | - clock-names: Should be "sysmmu" or a pair of "aclk" and "pclk" to gate |
39 | SYSMMU core clocks. | ||
39 | Optional "master" if the clock to the System MMU is gated by | 40 | Optional "master" if the clock to the System MMU is gated by |
40 | another gate clock other than "sysmmu" (usually main gate clock | 41 | another gate clock other core (usually main gate clock |
41 | of peripheral device this SYSMMU belongs to). | 42 | of peripheral device this SYSMMU belongs to). |
42 | - clocks: Phandles for respective clocks described by clock-names. | 43 | - clocks: Phandles for respective clocks described by clock-names. |
43 | - power-domains: Required if the System MMU is needed to gate its power. | 44 | - power-domains: Required if the System MMU is needed to gate its power. |
diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig index a1e75cba18e0..1674de1cfed0 100644 --- a/drivers/iommu/Kconfig +++ b/drivers/iommu/Kconfig | |||
@@ -243,7 +243,7 @@ config TEGRA_IOMMU_SMMU | |||
243 | 243 | ||
244 | config EXYNOS_IOMMU | 244 | config EXYNOS_IOMMU |
245 | bool "Exynos IOMMU Support" | 245 | bool "Exynos IOMMU Support" |
246 | depends on ARCH_EXYNOS && ARM && MMU | 246 | depends on ARCH_EXYNOS && MMU |
247 | select IOMMU_API | 247 | select IOMMU_API |
248 | select ARM_DMA_USE_IOMMU | 248 | select ARM_DMA_USE_IOMMU |
249 | help | 249 | help |
diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c index 8e289e2a05fb..9c8ce951158d 100644 --- a/drivers/iommu/exynos-iommu.c +++ b/drivers/iommu/exynos-iommu.c | |||
@@ -1,6 +1,5 @@ | |||
1 | /* linux/drivers/iommu/exynos_iommu.c | 1 | /* |
2 | * | 2 | * Copyright (c) 2011,2016 Samsung Electronics Co., Ltd. |
3 | * Copyright (c) 2011 Samsung Electronics Co., Ltd. | ||
4 | * http://www.samsung.com | 3 | * http://www.samsung.com |
5 | * | 4 | * |
6 | * This program is free software; you can redistribute it and/or modify | 5 | * This program is free software; you can redistribute it and/or modify |
@@ -55,17 +54,25 @@ typedef u32 sysmmu_pte_t; | |||
55 | #define lv2ent_small(pent) ((*(pent) & 2) == 2) | 54 | #define lv2ent_small(pent) ((*(pent) & 2) == 2) |
56 | #define lv2ent_large(pent) ((*(pent) & 3) == 1) | 55 | #define lv2ent_large(pent) ((*(pent) & 3) == 1) |
57 | 56 | ||
58 | static u32 sysmmu_page_offset(sysmmu_iova_t iova, u32 size) | 57 | /* |
59 | { | 58 | * v1.x - v3.x SYSMMU supports 32bit physical and 32bit virtual address spaces |
60 | return iova & (size - 1); | 59 | * v5.0 introduced support for 36bit physical address space by shifting |
61 | } | 60 | * all page entry values by 4 bits. |
62 | 61 | * All SYSMMU controllers in the system support the address spaces of the same | |
63 | #define section_phys(sent) (*(sent) & SECT_MASK) | 62 | * size, so PG_ENT_SHIFT can be initialized on first SYSMMU probe to proper |
64 | #define section_offs(iova) sysmmu_page_offset((iova), SECT_SIZE) | 63 | * value (0 or 4). |
65 | #define lpage_phys(pent) (*(pent) & LPAGE_MASK) | 64 | */ |
66 | #define lpage_offs(iova) sysmmu_page_offset((iova), LPAGE_SIZE) | 65 | static short PG_ENT_SHIFT = -1; |
67 | #define spage_phys(pent) (*(pent) & SPAGE_MASK) | 66 | #define SYSMMU_PG_ENT_SHIFT 0 |
68 | #define spage_offs(iova) sysmmu_page_offset((iova), SPAGE_SIZE) | 67 | #define SYSMMU_V5_PG_ENT_SHIFT 4 |
68 | |||
69 | #define sect_to_phys(ent) (((phys_addr_t) ent) << PG_ENT_SHIFT) | ||
70 | #define section_phys(sent) (sect_to_phys(*(sent)) & SECT_MASK) | ||
71 | #define section_offs(iova) (iova & (SECT_SIZE - 1)) | ||
72 | #define lpage_phys(pent) (sect_to_phys(*(pent)) & LPAGE_MASK) | ||
73 | #define lpage_offs(iova) (iova & (LPAGE_SIZE - 1)) | ||
74 | #define spage_phys(pent) (sect_to_phys(*(pent)) & SPAGE_MASK) | ||
75 | #define spage_offs(iova) (iova & (SPAGE_SIZE - 1)) | ||
69 | 76 | ||
70 | #define NUM_LV1ENTRIES 4096 | 77 | #define NUM_LV1ENTRIES 4096 |
71 | #define NUM_LV2ENTRIES (SECT_SIZE / SPAGE_SIZE) | 78 | #define NUM_LV2ENTRIES (SECT_SIZE / SPAGE_SIZE) |
@@ -84,13 +91,12 @@ static u32 lv2ent_offset(sysmmu_iova_t iova) | |||
84 | #define LV2TABLE_SIZE (NUM_LV2ENTRIES * sizeof(sysmmu_pte_t)) | 91 | #define LV2TABLE_SIZE (NUM_LV2ENTRIES * sizeof(sysmmu_pte_t)) |
85 | 92 | ||
86 | #define SPAGES_PER_LPAGE (LPAGE_SIZE / SPAGE_SIZE) | 93 | #define SPAGES_PER_LPAGE (LPAGE_SIZE / SPAGE_SIZE) |
94 | #define lv2table_base(sent) (sect_to_phys(*(sent) & 0xFFFFFFC0)) | ||
87 | 95 | ||
88 | #define lv2table_base(sent) (*(sent) & 0xFFFFFC00) | 96 | #define mk_lv1ent_sect(pa) ((pa >> PG_ENT_SHIFT) | 2) |
89 | 97 | #define mk_lv1ent_page(pa) ((pa >> PG_ENT_SHIFT) | 1) | |
90 | #define mk_lv1ent_sect(pa) ((pa) | 2) | 98 | #define mk_lv2ent_lpage(pa) ((pa >> PG_ENT_SHIFT) | 1) |
91 | #define mk_lv1ent_page(pa) ((pa) | 1) | 99 | #define mk_lv2ent_spage(pa) ((pa >> PG_ENT_SHIFT) | 2) |
92 | #define mk_lv2ent_lpage(pa) ((pa) | 1) | ||
93 | #define mk_lv2ent_spage(pa) ((pa) | 2) | ||
94 | 100 | ||
95 | #define CTRL_ENABLE 0x5 | 101 | #define CTRL_ENABLE 0x5 |
96 | #define CTRL_BLOCK 0x7 | 102 | #define CTRL_BLOCK 0x7 |
@@ -98,14 +104,23 @@ static u32 lv2ent_offset(sysmmu_iova_t iova) | |||
98 | 104 | ||
99 | #define CFG_LRU 0x1 | 105 | #define CFG_LRU 0x1 |
100 | #define CFG_QOS(n) ((n & 0xF) << 7) | 106 | #define CFG_QOS(n) ((n & 0xF) << 7) |
101 | #define CFG_MASK 0x0150FFFF /* Selecting bit 0-15, 20, 22 and 24 */ | ||
102 | #define CFG_ACGEN (1 << 24) /* System MMU 3.3 only */ | 107 | #define CFG_ACGEN (1 << 24) /* System MMU 3.3 only */ |
103 | #define CFG_SYSSEL (1 << 22) /* System MMU 3.2 only */ | 108 | #define CFG_SYSSEL (1 << 22) /* System MMU 3.2 only */ |
104 | #define CFG_FLPDCACHE (1 << 20) /* System MMU 3.2+ only */ | 109 | #define CFG_FLPDCACHE (1 << 20) /* System MMU 3.2+ only */ |
105 | 110 | ||
111 | /* common registers */ | ||
106 | #define REG_MMU_CTRL 0x000 | 112 | #define REG_MMU_CTRL 0x000 |
107 | #define REG_MMU_CFG 0x004 | 113 | #define REG_MMU_CFG 0x004 |
108 | #define REG_MMU_STATUS 0x008 | 114 | #define REG_MMU_STATUS 0x008 |
115 | #define REG_MMU_VERSION 0x034 | ||
116 | |||
117 | #define MMU_MAJ_VER(val) ((val) >> 7) | ||
118 | #define MMU_MIN_VER(val) ((val) & 0x7F) | ||
119 | #define MMU_RAW_VER(reg) (((reg) >> 21) & ((1 << 11) - 1)) /* 11 bits */ | ||
120 | |||
121 | #define MAKE_MMU_VER(maj, min) ((((maj) & 0xF) << 7) | ((min) & 0x7F)) | ||
122 | |||
123 | /* v1.x - v3.x registers */ | ||
109 | #define REG_MMU_FLUSH 0x00C | 124 | #define REG_MMU_FLUSH 0x00C |
110 | #define REG_MMU_FLUSH_ENTRY 0x010 | 125 | #define REG_MMU_FLUSH_ENTRY 0x010 |
111 | #define REG_PT_BASE_ADDR 0x014 | 126 | #define REG_PT_BASE_ADDR 0x014 |
@@ -117,18 +132,14 @@ static u32 lv2ent_offset(sysmmu_iova_t iova) | |||
117 | #define REG_AR_FAULT_ADDR 0x02C | 132 | #define REG_AR_FAULT_ADDR 0x02C |
118 | #define REG_DEFAULT_SLAVE_ADDR 0x030 | 133 | #define REG_DEFAULT_SLAVE_ADDR 0x030 |
119 | 134 | ||
120 | #define REG_MMU_VERSION 0x034 | 135 | /* v5.x registers */ |
121 | 136 | #define REG_V5_PT_BASE_PFN 0x00C | |
122 | #define MMU_MAJ_VER(val) ((val) >> 7) | 137 | #define REG_V5_MMU_FLUSH_ALL 0x010 |
123 | #define MMU_MIN_VER(val) ((val) & 0x7F) | 138 | #define REG_V5_MMU_FLUSH_ENTRY 0x014 |
124 | #define MMU_RAW_VER(reg) (((reg) >> 21) & ((1 << 11) - 1)) /* 11 bits */ | 139 | #define REG_V5_INT_STATUS 0x060 |
125 | 140 | #define REG_V5_INT_CLEAR 0x064 | |
126 | #define MAKE_MMU_VER(maj, min) ((((maj) & 0xF) << 7) | ((min) & 0x7F)) | 141 | #define REG_V5_FAULT_AR_VA 0x070 |
127 | 142 | #define REG_V5_FAULT_AW_VA 0x080 | |
128 | #define REG_PB0_SADDR 0x04C | ||
129 | #define REG_PB0_EADDR 0x050 | ||
130 | #define REG_PB1_SADDR 0x054 | ||
131 | #define REG_PB1_EADDR 0x058 | ||
132 | 143 | ||
133 | #define has_sysmmu(dev) (dev->archdata.iommu != NULL) | 144 | #define has_sysmmu(dev) (dev->archdata.iommu != NULL) |
134 | 145 | ||
@@ -169,6 +180,19 @@ static const struct sysmmu_fault_info sysmmu_faults[] = { | |||
169 | { 7, REG_AW_FAULT_ADDR, "AW ACCESS PROTECTION", IOMMU_FAULT_WRITE }, | 180 | { 7, REG_AW_FAULT_ADDR, "AW ACCESS PROTECTION", IOMMU_FAULT_WRITE }, |
170 | }; | 181 | }; |
171 | 182 | ||
183 | static const struct sysmmu_fault_info sysmmu_v5_faults[] = { | ||
184 | { 0, REG_V5_FAULT_AR_VA, "AR PTW", IOMMU_FAULT_READ }, | ||
185 | { 1, REG_V5_FAULT_AR_VA, "AR PAGE", IOMMU_FAULT_READ }, | ||
186 | { 2, REG_V5_FAULT_AR_VA, "AR MULTI-HIT", IOMMU_FAULT_READ }, | ||
187 | { 3, REG_V5_FAULT_AR_VA, "AR ACCESS PROTECTION", IOMMU_FAULT_READ }, | ||
188 | { 4, REG_V5_FAULT_AR_VA, "AR SECURITY PROTECTION", IOMMU_FAULT_READ }, | ||
189 | { 16, REG_V5_FAULT_AW_VA, "AW PTW", IOMMU_FAULT_WRITE }, | ||
190 | { 17, REG_V5_FAULT_AW_VA, "AW PAGE", IOMMU_FAULT_WRITE }, | ||
191 | { 18, REG_V5_FAULT_AW_VA, "AW MULTI-HIT", IOMMU_FAULT_WRITE }, | ||
192 | { 19, REG_V5_FAULT_AW_VA, "AW ACCESS PROTECTION", IOMMU_FAULT_WRITE }, | ||
193 | { 20, REG_V5_FAULT_AW_VA, "AW SECURITY PROTECTION", IOMMU_FAULT_WRITE }, | ||
194 | }; | ||
195 | |||
172 | /* | 196 | /* |
173 | * This structure is attached to dev.archdata.iommu of the master device | 197 | * This structure is attached to dev.archdata.iommu of the master device |
174 | * on device add, contains a list of SYSMMU controllers defined by device tree, | 198 | * on device add, contains a list of SYSMMU controllers defined by device tree, |
@@ -205,6 +229,8 @@ struct sysmmu_drvdata { | |||
205 | struct device *master; /* master device (owner) */ | 229 | struct device *master; /* master device (owner) */ |
206 | void __iomem *sfrbase; /* our registers */ | 230 | void __iomem *sfrbase; /* our registers */ |
207 | struct clk *clk; /* SYSMMU's clock */ | 231 | struct clk *clk; /* SYSMMU's clock */ |
232 | struct clk *aclk; /* SYSMMU's aclk clock */ | ||
233 | struct clk *pclk; /* SYSMMU's pclk clock */ | ||
208 | struct clk *clk_master; /* master's device clock */ | 234 | struct clk *clk_master; /* master's device clock */ |
209 | int activations; /* number of calls to sysmmu_enable */ | 235 | int activations; /* number of calls to sysmmu_enable */ |
210 | spinlock_t lock; /* lock for modyfying state */ | 236 | spinlock_t lock; /* lock for modyfying state */ |
@@ -262,7 +288,10 @@ static bool sysmmu_block(struct sysmmu_drvdata *data) | |||
262 | 288 | ||
263 | static void __sysmmu_tlb_invalidate(struct sysmmu_drvdata *data) | 289 | static void __sysmmu_tlb_invalidate(struct sysmmu_drvdata *data) |
264 | { | 290 | { |
265 | __raw_writel(0x1, data->sfrbase + REG_MMU_FLUSH); | 291 | if (MMU_MAJ_VER(data->version) < 5) |
292 | __raw_writel(0x1, data->sfrbase + REG_MMU_FLUSH); | ||
293 | else | ||
294 | __raw_writel(0x1, data->sfrbase + REG_V5_MMU_FLUSH_ALL); | ||
266 | } | 295 | } |
267 | 296 | ||
268 | static void __sysmmu_tlb_invalidate_entry(struct sysmmu_drvdata *data, | 297 | static void __sysmmu_tlb_invalidate_entry(struct sysmmu_drvdata *data, |
@@ -271,15 +300,23 @@ static void __sysmmu_tlb_invalidate_entry(struct sysmmu_drvdata *data, | |||
271 | unsigned int i; | 300 | unsigned int i; |
272 | 301 | ||
273 | for (i = 0; i < num_inv; i++) { | 302 | for (i = 0; i < num_inv; i++) { |
274 | __raw_writel((iova & SPAGE_MASK) | 1, | 303 | if (MMU_MAJ_VER(data->version) < 5) |
275 | data->sfrbase + REG_MMU_FLUSH_ENTRY); | 304 | __raw_writel((iova & SPAGE_MASK) | 1, |
305 | data->sfrbase + REG_MMU_FLUSH_ENTRY); | ||
306 | else | ||
307 | __raw_writel((iova & SPAGE_MASK) | 1, | ||
308 | data->sfrbase + REG_V5_MMU_FLUSH_ENTRY); | ||
276 | iova += SPAGE_SIZE; | 309 | iova += SPAGE_SIZE; |
277 | } | 310 | } |
278 | } | 311 | } |
279 | 312 | ||
280 | static void __sysmmu_set_ptbase(struct sysmmu_drvdata *data, phys_addr_t pgd) | 313 | static void __sysmmu_set_ptbase(struct sysmmu_drvdata *data, phys_addr_t pgd) |
281 | { | 314 | { |
282 | __raw_writel(pgd, data->sfrbase + REG_PT_BASE_ADDR); | 315 | if (MMU_MAJ_VER(data->version) < 5) |
316 | __raw_writel(pgd, data->sfrbase + REG_PT_BASE_ADDR); | ||
317 | else | ||
318 | __raw_writel(pgd >> PAGE_SHIFT, | ||
319 | data->sfrbase + REG_V5_PT_BASE_PFN); | ||
283 | 320 | ||
284 | __sysmmu_tlb_invalidate(data); | 321 | __sysmmu_tlb_invalidate(data); |
285 | } | 322 | } |
@@ -290,6 +327,8 @@ static void __sysmmu_get_version(struct sysmmu_drvdata *data) | |||
290 | 327 | ||
291 | clk_enable(data->clk_master); | 328 | clk_enable(data->clk_master); |
292 | clk_enable(data->clk); | 329 | clk_enable(data->clk); |
330 | clk_enable(data->pclk); | ||
331 | clk_enable(data->aclk); | ||
293 | 332 | ||
294 | ver = __raw_readl(data->sfrbase + REG_MMU_VERSION); | 333 | ver = __raw_readl(data->sfrbase + REG_MMU_VERSION); |
295 | 334 | ||
@@ -302,6 +341,8 @@ static void __sysmmu_get_version(struct sysmmu_drvdata *data) | |||
302 | dev_dbg(data->sysmmu, "hardware version: %d.%d\n", | 341 | dev_dbg(data->sysmmu, "hardware version: %d.%d\n", |
303 | MMU_MAJ_VER(data->version), MMU_MIN_VER(data->version)); | 342 | MMU_MAJ_VER(data->version), MMU_MIN_VER(data->version)); |
304 | 343 | ||
344 | clk_disable(data->aclk); | ||
345 | clk_disable(data->pclk); | ||
305 | clk_disable(data->clk); | 346 | clk_disable(data->clk); |
306 | clk_disable(data->clk_master); | 347 | clk_disable(data->clk_master); |
307 | } | 348 | } |
@@ -326,19 +367,31 @@ static irqreturn_t exynos_sysmmu_irq(int irq, void *dev_id) | |||
326 | { | 367 | { |
327 | /* SYSMMU is in blocked state when interrupt occurred. */ | 368 | /* SYSMMU is in blocked state when interrupt occurred. */ |
328 | struct sysmmu_drvdata *data = dev_id; | 369 | struct sysmmu_drvdata *data = dev_id; |
329 | const struct sysmmu_fault_info *finfo = sysmmu_faults; | 370 | const struct sysmmu_fault_info *finfo; |
330 | int i, n = ARRAY_SIZE(sysmmu_faults); | 371 | unsigned int i, n, itype; |
331 | unsigned int itype; | ||
332 | sysmmu_iova_t fault_addr = -1; | 372 | sysmmu_iova_t fault_addr = -1; |
373 | unsigned short reg_status, reg_clear; | ||
333 | int ret = -ENOSYS; | 374 | int ret = -ENOSYS; |
334 | 375 | ||
335 | WARN_ON(!is_sysmmu_active(data)); | 376 | WARN_ON(!is_sysmmu_active(data)); |
336 | 377 | ||
378 | if (MMU_MAJ_VER(data->version) < 5) { | ||
379 | reg_status = REG_INT_STATUS; | ||
380 | reg_clear = REG_INT_CLEAR; | ||
381 | finfo = sysmmu_faults; | ||
382 | n = ARRAY_SIZE(sysmmu_faults); | ||
383 | } else { | ||
384 | reg_status = REG_V5_INT_STATUS; | ||
385 | reg_clear = REG_V5_INT_CLEAR; | ||
386 | finfo = sysmmu_v5_faults; | ||
387 | n = ARRAY_SIZE(sysmmu_v5_faults); | ||
388 | } | ||
389 | |||
337 | spin_lock(&data->lock); | 390 | spin_lock(&data->lock); |
338 | 391 | ||
339 | clk_enable(data->clk_master); | 392 | clk_enable(data->clk_master); |
340 | 393 | ||
341 | itype = __ffs(__raw_readl(data->sfrbase + REG_INT_STATUS)); | 394 | itype = __ffs(__raw_readl(data->sfrbase + reg_status)); |
342 | for (i = 0; i < n; i++, finfo++) | 395 | for (i = 0; i < n; i++, finfo++) |
343 | if (finfo->bit == itype) | 396 | if (finfo->bit == itype) |
344 | break; | 397 | break; |
@@ -355,7 +408,7 @@ static irqreturn_t exynos_sysmmu_irq(int irq, void *dev_id) | |||
355 | /* fault is not recovered by fault handler */ | 408 | /* fault is not recovered by fault handler */ |
356 | BUG_ON(ret != 0); | 409 | BUG_ON(ret != 0); |
357 | 410 | ||
358 | __raw_writel(1 << itype, data->sfrbase + REG_INT_CLEAR); | 411 | __raw_writel(1 << itype, data->sfrbase + reg_clear); |
359 | 412 | ||
360 | sysmmu_unblock(data); | 413 | sysmmu_unblock(data); |
361 | 414 | ||
@@ -373,6 +426,8 @@ static void __sysmmu_disable_nocount(struct sysmmu_drvdata *data) | |||
373 | __raw_writel(CTRL_DISABLE, data->sfrbase + REG_MMU_CTRL); | 426 | __raw_writel(CTRL_DISABLE, data->sfrbase + REG_MMU_CTRL); |
374 | __raw_writel(0, data->sfrbase + REG_MMU_CFG); | 427 | __raw_writel(0, data->sfrbase + REG_MMU_CFG); |
375 | 428 | ||
429 | clk_disable(data->aclk); | ||
430 | clk_disable(data->pclk); | ||
376 | clk_disable(data->clk); | 431 | clk_disable(data->clk); |
377 | clk_disable(data->clk_master); | 432 | clk_disable(data->clk_master); |
378 | } | 433 | } |
@@ -421,6 +476,8 @@ static void __sysmmu_enable_nocount(struct sysmmu_drvdata *data) | |||
421 | { | 476 | { |
422 | clk_enable(data->clk_master); | 477 | clk_enable(data->clk_master); |
423 | clk_enable(data->clk); | 478 | clk_enable(data->clk); |
479 | clk_enable(data->pclk); | ||
480 | clk_enable(data->aclk); | ||
424 | 481 | ||
425 | __raw_writel(CTRL_BLOCK, data->sfrbase + REG_MMU_CTRL); | 482 | __raw_writel(CTRL_BLOCK, data->sfrbase + REG_MMU_CTRL); |
426 | 483 | ||
@@ -544,22 +601,47 @@ static int __init exynos_sysmmu_probe(struct platform_device *pdev) | |||
544 | } | 601 | } |
545 | 602 | ||
546 | data->clk = devm_clk_get(dev, "sysmmu"); | 603 | data->clk = devm_clk_get(dev, "sysmmu"); |
547 | if (IS_ERR(data->clk)) { | 604 | if (!IS_ERR(data->clk)) { |
548 | dev_err(dev, "Failed to get clock!\n"); | ||
549 | return PTR_ERR(data->clk); | ||
550 | } else { | ||
551 | ret = clk_prepare(data->clk); | 605 | ret = clk_prepare(data->clk); |
552 | if (ret) { | 606 | if (ret) { |
553 | dev_err(dev, "Failed to prepare clk\n"); | 607 | dev_err(dev, "Failed to prepare clk\n"); |
554 | return ret; | 608 | return ret; |
555 | } | 609 | } |
610 | } else { | ||
611 | data->clk = NULL; | ||
612 | } | ||
613 | |||
614 | data->aclk = devm_clk_get(dev, "aclk"); | ||
615 | if (!IS_ERR(data->aclk)) { | ||
616 | ret = clk_prepare(data->aclk); | ||
617 | if (ret) { | ||
618 | dev_err(dev, "Failed to prepare aclk\n"); | ||
619 | return ret; | ||
620 | } | ||
621 | } else { | ||
622 | data->aclk = NULL; | ||
623 | } | ||
624 | |||
625 | data->pclk = devm_clk_get(dev, "pclk"); | ||
626 | if (!IS_ERR(data->pclk)) { | ||
627 | ret = clk_prepare(data->pclk); | ||
628 | if (ret) { | ||
629 | dev_err(dev, "Failed to prepare pclk\n"); | ||
630 | return ret; | ||
631 | } | ||
632 | } else { | ||
633 | data->pclk = NULL; | ||
634 | } | ||
635 | |||
636 | if (!data->clk && (!data->aclk || !data->pclk)) { | ||
637 | dev_err(dev, "Failed to get device clock(s)!\n"); | ||
638 | return -ENOSYS; | ||
556 | } | 639 | } |
557 | 640 | ||
558 | data->clk_master = devm_clk_get(dev, "master"); | 641 | data->clk_master = devm_clk_get(dev, "master"); |
559 | if (!IS_ERR(data->clk_master)) { | 642 | if (!IS_ERR(data->clk_master)) { |
560 | ret = clk_prepare(data->clk_master); | 643 | ret = clk_prepare(data->clk_master); |
561 | if (ret) { | 644 | if (ret) { |
562 | clk_unprepare(data->clk); | ||
563 | dev_err(dev, "Failed to prepare master's clk\n"); | 645 | dev_err(dev, "Failed to prepare master's clk\n"); |
564 | return ret; | 646 | return ret; |
565 | } | 647 | } |
@@ -573,6 +655,13 @@ static int __init exynos_sysmmu_probe(struct platform_device *pdev) | |||
573 | platform_set_drvdata(pdev, data); | 655 | platform_set_drvdata(pdev, data); |
574 | 656 | ||
575 | __sysmmu_get_version(data); | 657 | __sysmmu_get_version(data); |
658 | if (PG_ENT_SHIFT < 0) { | ||
659 | if (MMU_MAJ_VER(data->version) < 5) | ||
660 | PG_ENT_SHIFT = SYSMMU_PG_ENT_SHIFT; | ||
661 | else | ||
662 | PG_ENT_SHIFT = SYSMMU_V5_PG_ENT_SHIFT; | ||
663 | } | ||
664 | |||
576 | pm_runtime_enable(dev); | 665 | pm_runtime_enable(dev); |
577 | 666 | ||
578 | return 0; | 667 | return 0; |
@@ -637,6 +726,8 @@ static struct iommu_domain *exynos_iommu_domain_alloc(unsigned type) | |||
637 | dma_addr_t handle; | 726 | dma_addr_t handle; |
638 | int i; | 727 | int i; |
639 | 728 | ||
729 | /* Check if correct PTE offsets are initialized */ | ||
730 | BUG_ON(PG_ENT_SHIFT < 0 || !dma_dev); | ||
640 | 731 | ||
641 | domain = kzalloc(sizeof(*domain), GFP_KERNEL); | 732 | domain = kzalloc(sizeof(*domain), GFP_KERNEL); |
642 | if (!domain) | 733 | if (!domain) |
@@ -816,7 +907,7 @@ static sysmmu_pte_t *alloc_lv2entry(struct exynos_iommu_domain *domain, | |||
816 | bool need_flush_flpd_cache = lv1ent_zero(sent); | 907 | bool need_flush_flpd_cache = lv1ent_zero(sent); |
817 | 908 | ||
818 | pent = kmem_cache_zalloc(lv2table_kmem_cache, GFP_ATOMIC); | 909 | pent = kmem_cache_zalloc(lv2table_kmem_cache, GFP_ATOMIC); |
819 | BUG_ON((unsigned int)pent & (LV2TABLE_SIZE - 1)); | 910 | BUG_ON((phys_addr_t)pent & (LV2TABLE_SIZE - 1)); |
820 | if (!pent) | 911 | if (!pent) |
821 | return ERR_PTR(-ENOMEM); | 912 | return ERR_PTR(-ENOMEM); |
822 | 913 | ||