aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarek Szyprowski <m.szyprowski@samsung.com>2016-05-23 05:30:09 -0400
committerJoerg Roedel <jroedel@suse.de>2016-06-15 07:59:58 -0400
commitfecc49db884b902f7abbea4c9287d17a56966be4 (patch)
treebb14c90246772c708e09669b4dad65ec10bae557
parent01324ab2c990bbd39ec0ef388b7c311a54452a0b (diff)
iommu/exynos: Prepare clocks when needed, not in driver probe
Make clock preparation together with clk_enable(). This way inactive SYSMMU controllers will not keep clocks prepared all the time. This change allows more fine graded power management in the future. All the code assumes that clock management doesn't fail, so guard clock_prepare_enable() it with BUG_ON(). Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com> Signed-off-by: Joerg Roedel <jroedel@suse.de>
-rw-r--r--drivers/iommu/exynos-iommu.c54
1 files changed, 26 insertions, 28 deletions
diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c
index 018bcd5d5edc..e0b834375f17 100644
--- a/drivers/iommu/exynos-iommu.c
+++ b/drivers/iommu/exynos-iommu.c
@@ -322,14 +322,27 @@ static void __sysmmu_set_ptbase(struct sysmmu_drvdata *data, phys_addr_t pgd)
322 __sysmmu_tlb_invalidate(data); 322 __sysmmu_tlb_invalidate(data);
323} 323}
324 324
325static void __sysmmu_enable_clocks(struct sysmmu_drvdata *data)
326{
327 BUG_ON(clk_prepare_enable(data->clk_master));
328 BUG_ON(clk_prepare_enable(data->clk));
329 BUG_ON(clk_prepare_enable(data->pclk));
330 BUG_ON(clk_prepare_enable(data->aclk));
331}
332
333static void __sysmmu_disable_clocks(struct sysmmu_drvdata *data)
334{
335 clk_disable_unprepare(data->aclk);
336 clk_disable_unprepare(data->pclk);
337 clk_disable_unprepare(data->clk);
338 clk_disable_unprepare(data->clk_master);
339}
340
325static void __sysmmu_get_version(struct sysmmu_drvdata *data) 341static void __sysmmu_get_version(struct sysmmu_drvdata *data)
326{ 342{
327 u32 ver; 343 u32 ver;
328 344
329 clk_enable(data->clk_master); 345 __sysmmu_enable_clocks(data);
330 clk_enable(data->clk);
331 clk_enable(data->pclk);
332 clk_enable(data->aclk);
333 346
334 ver = readl(data->sfrbase + REG_MMU_VERSION); 347 ver = readl(data->sfrbase + REG_MMU_VERSION);
335 348
@@ -342,10 +355,7 @@ static void __sysmmu_get_version(struct sysmmu_drvdata *data)
342 dev_dbg(data->sysmmu, "hardware version: %d.%d\n", 355 dev_dbg(data->sysmmu, "hardware version: %d.%d\n",
343 MMU_MAJ_VER(data->version), MMU_MIN_VER(data->version)); 356 MMU_MAJ_VER(data->version), MMU_MIN_VER(data->version));
344 357
345 clk_disable(data->aclk); 358 __sysmmu_disable_clocks(data);
346 clk_disable(data->pclk);
347 clk_disable(data->clk);
348 clk_disable(data->clk_master);
349} 359}
350 360
351static void show_fault_information(struct sysmmu_drvdata *data, 361static void show_fault_information(struct sysmmu_drvdata *data,
@@ -427,10 +437,7 @@ static void __sysmmu_disable_nocount(struct sysmmu_drvdata *data)
427 writel(CTRL_DISABLE, data->sfrbase + REG_MMU_CTRL); 437 writel(CTRL_DISABLE, data->sfrbase + REG_MMU_CTRL);
428 writel(0, data->sfrbase + REG_MMU_CFG); 438 writel(0, data->sfrbase + REG_MMU_CFG);
429 439
430 clk_disable(data->aclk); 440 __sysmmu_disable_clocks(data);
431 clk_disable(data->pclk);
432 clk_disable(data->clk);
433 clk_disable(data->clk_master);
434} 441}
435 442
436static bool __sysmmu_disable(struct sysmmu_drvdata *data) 443static bool __sysmmu_disable(struct sysmmu_drvdata *data)
@@ -475,10 +482,7 @@ static void __sysmmu_init_config(struct sysmmu_drvdata *data)
475 482
476static void __sysmmu_enable_nocount(struct sysmmu_drvdata *data) 483static void __sysmmu_enable_nocount(struct sysmmu_drvdata *data)
477{ 484{
478 clk_enable(data->clk_master); 485 __sysmmu_enable_clocks(data);
479 clk_enable(data->clk);
480 clk_enable(data->pclk);
481 clk_enable(data->aclk);
482 486
483 writel(CTRL_BLOCK, data->sfrbase + REG_MMU_CTRL); 487 writel(CTRL_BLOCK, data->sfrbase + REG_MMU_CTRL);
484 488
@@ -488,6 +492,12 @@ static void __sysmmu_enable_nocount(struct sysmmu_drvdata *data)
488 492
489 writel(CTRL_ENABLE, data->sfrbase + REG_MMU_CTRL); 493 writel(CTRL_ENABLE, data->sfrbase + REG_MMU_CTRL);
490 494
495 /*
496 * SYSMMU driver keeps master's clock enabled only for the short
497 * time, while accessing the registers. For performing address
498 * translation during DMA transaction it relies on the client
499 * driver to enable it.
500 */
491 clk_disable(data->clk_master); 501 clk_disable(data->clk_master);
492} 502}
493 503
@@ -605,27 +615,18 @@ static int __init exynos_sysmmu_probe(struct platform_device *pdev)
605 data->clk = NULL; 615 data->clk = NULL;
606 else if (IS_ERR(data->clk)) 616 else if (IS_ERR(data->clk))
607 return PTR_ERR(data->clk); 617 return PTR_ERR(data->clk);
608 ret = clk_prepare(data->clk);
609 if (ret)
610 return ret;
611 618
612 data->aclk = devm_clk_get(dev, "aclk"); 619 data->aclk = devm_clk_get(dev, "aclk");
613 if (PTR_ERR(data->aclk) == -ENOENT) 620 if (PTR_ERR(data->aclk) == -ENOENT)
614 data->aclk = NULL; 621 data->aclk = NULL;
615 else if (IS_ERR(data->aclk)) 622 else if (IS_ERR(data->aclk))
616 return PTR_ERR(data->aclk); 623 return PTR_ERR(data->aclk);
617 ret = clk_prepare(data->aclk);
618 if (ret)
619 return ret;
620 624
621 data->pclk = devm_clk_get(dev, "pclk"); 625 data->pclk = devm_clk_get(dev, "pclk");
622 if (PTR_ERR(data->pclk) == -ENOENT) 626 if (PTR_ERR(data->pclk) == -ENOENT)
623 data->pclk = NULL; 627 data->pclk = NULL;
624 else if (IS_ERR(data->pclk)) 628 else if (IS_ERR(data->pclk))
625 return PTR_ERR(data->pclk); 629 return PTR_ERR(data->pclk);
626 ret = clk_prepare(data->pclk);
627 if (ret)
628 return ret;
629 630
630 if (!data->clk && (!data->aclk || !data->pclk)) { 631 if (!data->clk && (!data->aclk || !data->pclk)) {
631 dev_err(dev, "Failed to get device clock(s)!\n"); 632 dev_err(dev, "Failed to get device clock(s)!\n");
@@ -637,9 +638,6 @@ static int __init exynos_sysmmu_probe(struct platform_device *pdev)
637 data->clk_master = NULL; 638 data->clk_master = NULL;
638 else if (IS_ERR(data->clk_master)) 639 else if (IS_ERR(data->clk_master))
639 return PTR_ERR(data->clk_master); 640 return PTR_ERR(data->clk_master);
640 ret = clk_prepare(data->clk_master);
641 if (ret)
642 return ret;
643 641
644 data->sysmmu = dev; 642 data->sysmmu = dev;
645 spin_lock_init(&data->lock); 643 spin_lock_init(&data->lock);