aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/iommu
diff options
context:
space:
mode:
authorCho KyongHo <pullip.cho@samsung.com>2014-05-12 02:14:55 -0400
committerJoerg Roedel <jroedel@suse.de>2014-05-13 13:12:55 -0400
commit7060587052e0370ea1b7a41c84d5ad364be16f51 (patch)
treee9cdb5f0764594786ccf9f83415fb0317c15aba0 /drivers/iommu
parent46c16d1e4c11ffa0481b1dd6841e0bcabcf278e7 (diff)
iommu/exynos: Gating clocks of master H/W
This patch gates clocks of master H/W as well as clocks of System MMU if master clocks are specified. Some Exynos SoCs (i.e. GScalers in Exynos5250) have dependencies in the gating clocks of master H/W and its System MMU. If a H/W is the case, accessing control registers of System MMU is prohibited unless both of the gating clocks of System MMU and its master H/W. CC: Tomasz Figa <t.figa@samsung.com> 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.c40
1 files changed, 38 insertions, 2 deletions
diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c
index c86e3745e98f..5af5c5c16f49 100644
--- a/drivers/iommu/exynos-iommu.c
+++ b/drivers/iommu/exynos-iommu.c
@@ -172,6 +172,7 @@ struct sysmmu_drvdata {
172 struct device *dev; /* Owner of system MMU */ 172 struct device *dev; /* Owner of system MMU */
173 void __iomem *sfrbase; 173 void __iomem *sfrbase;
174 struct clk *clk; 174 struct clk *clk;
175 struct clk *clk_master;
175 int activations; 176 int activations;
176 rwlock_t lock; 177 rwlock_t lock;
177 struct iommu_domain *domain; 178 struct iommu_domain *domain;
@@ -300,6 +301,8 @@ static irqreturn_t exynos_sysmmu_irq(int irq, void *dev_id)
300 301
301 WARN_ON(!is_sysmmu_active(data)); 302 WARN_ON(!is_sysmmu_active(data));
302 303
304 if (!IS_ERR(data->clk_master))
305 clk_enable(data->clk_master);
303 itype = (enum exynos_sysmmu_inttype) 306 itype = (enum exynos_sysmmu_inttype)
304 __ffs(__raw_readl(data->sfrbase + REG_INT_STATUS)); 307 __ffs(__raw_readl(data->sfrbase + REG_INT_STATUS));
305 if (WARN_ON(!((itype >= 0) && (itype < SYSMMU_FAULT_UNKNOWN)))) 308 if (WARN_ON(!((itype >= 0) && (itype < SYSMMU_FAULT_UNKNOWN))))
@@ -326,6 +329,9 @@ static irqreturn_t exynos_sysmmu_irq(int irq, void *dev_id)
326 if (itype != SYSMMU_FAULT_UNKNOWN) 329 if (itype != SYSMMU_FAULT_UNKNOWN)
327 sysmmu_unblock(data->sfrbase); 330 sysmmu_unblock(data->sfrbase);
328 331
332 if (!IS_ERR(data->clk_master))
333 clk_disable(data->clk_master);
334
329 read_unlock(&data->lock); 335 read_unlock(&data->lock);
330 336
331 return IRQ_HANDLED; 337 return IRQ_HANDLED;
@@ -341,9 +347,14 @@ static bool __exynos_sysmmu_disable(struct sysmmu_drvdata *data)
341 if (!set_sysmmu_inactive(data)) 347 if (!set_sysmmu_inactive(data))
342 goto finish; 348 goto finish;
343 349
350 if (!IS_ERR(data->clk_master))
351 clk_enable(data->clk_master);
352
344 __raw_writel(CTRL_DISABLE, data->sfrbase + REG_MMU_CTRL); 353 __raw_writel(CTRL_DISABLE, data->sfrbase + REG_MMU_CTRL);
345 354
346 clk_disable(data->clk); 355 clk_disable(data->clk);
356 if (!IS_ERR(data->clk_master))
357 clk_disable(data->clk_master);
347 358
348 disabled = true; 359 disabled = true;
349 data->pgtable = 0; 360 data->pgtable = 0;
@@ -386,14 +397,19 @@ static int __exynos_sysmmu_enable(struct sysmmu_drvdata *data,
386 goto finish; 397 goto finish;
387 } 398 }
388 399
389 clk_enable(data->clk);
390
391 data->pgtable = pgtable; 400 data->pgtable = pgtable;
392 401
402 if (!IS_ERR(data->clk_master))
403 clk_enable(data->clk_master);
404 clk_enable(data->clk);
405
393 __sysmmu_set_ptbase(data->sfrbase, pgtable); 406 __sysmmu_set_ptbase(data->sfrbase, pgtable);
394 407
395 __raw_writel(CTRL_ENABLE, data->sfrbase + REG_MMU_CTRL); 408 __raw_writel(CTRL_ENABLE, data->sfrbase + REG_MMU_CTRL);
396 409
410 if (!IS_ERR(data->clk_master))
411 clk_disable(data->clk_master);
412
397 data->domain = domain; 413 data->domain = domain;
398 414
399 dev_dbg(data->sysmmu, "Enabled\n"); 415 dev_dbg(data->sysmmu, "Enabled\n");
@@ -450,6 +466,10 @@ static void sysmmu_tlb_invalidate_entry(struct device *dev, unsigned long iova,
450 if (is_sysmmu_active(data)) { 466 if (is_sysmmu_active(data)) {
451 unsigned int maj; 467 unsigned int maj;
452 unsigned int num_inv = 1; 468 unsigned int num_inv = 1;
469
470 if (!IS_ERR(data->clk_master))
471 clk_enable(data->clk_master);
472
453 maj = __raw_readl(data->sfrbase + REG_MMU_VERSION); 473 maj = __raw_readl(data->sfrbase + REG_MMU_VERSION);
454 /* 474 /*
455 * L2TLB invalidation required 475 * L2TLB invalidation required
@@ -469,6 +489,8 @@ static void sysmmu_tlb_invalidate_entry(struct device *dev, unsigned long iova,
469 data->sfrbase, iova, num_inv); 489 data->sfrbase, iova, num_inv);
470 sysmmu_unblock(data->sfrbase); 490 sysmmu_unblock(data->sfrbase);
471 } 491 }
492 if (!IS_ERR(data->clk_master))
493 clk_disable(data->clk_master);
472 } else { 494 } else {
473 dev_dbg(data->sysmmu, "Disabled. Skipping invalidating TLB.\n"); 495 dev_dbg(data->sysmmu, "Disabled. Skipping invalidating TLB.\n");
474 } 496 }
@@ -484,10 +506,14 @@ void exynos_sysmmu_tlb_invalidate(struct device *dev)
484 read_lock_irqsave(&data->lock, flags); 506 read_lock_irqsave(&data->lock, flags);
485 507
486 if (is_sysmmu_active(data)) { 508 if (is_sysmmu_active(data)) {
509 if (!IS_ERR(data->clk_master))
510 clk_enable(data->clk_master);
487 if (sysmmu_block(data->sfrbase)) { 511 if (sysmmu_block(data->sfrbase)) {
488 __sysmmu_tlb_invalidate(data->sfrbase); 512 __sysmmu_tlb_invalidate(data->sfrbase);
489 sysmmu_unblock(data->sfrbase); 513 sysmmu_unblock(data->sfrbase);
490 } 514 }
515 if (!IS_ERR(data->clk_master))
516 clk_disable(data->clk_master);
491 } else { 517 } else {
492 dev_dbg(data->sysmmu, "Disabled. Skipping invalidating TLB.\n"); 518 dev_dbg(data->sysmmu, "Disabled. Skipping invalidating TLB.\n");
493 } 519 }
@@ -536,6 +562,16 @@ static int exynos_sysmmu_probe(struct platform_device *pdev)
536 } 562 }
537 } 563 }
538 564
565 data->clk_master = devm_clk_get(dev, "master");
566 if (!IS_ERR(data->clk_master)) {
567 ret = clk_prepare(data->clk_master);
568 if (ret) {
569 clk_unprepare(data->clk);
570 dev_err(dev, "Failed to prepare master's clk\n");
571 return ret;
572 }
573 }
574
539 data->sysmmu = dev; 575 data->sysmmu = dev;
540 rwlock_init(&data->lock); 576 rwlock_init(&data->lock);
541 INIT_LIST_HEAD(&data->node); 577 INIT_LIST_HEAD(&data->node);