Exynos IOMMU: improve clock management
Subsystems (3)
Marek Szyprowski
maintainercover Exynos IOMMU: improve clock management
Hello,
This patch series improves clock management in Exynos IOMMU driver, so the driver will be ready for potential deferred probe caused by not-yet-available clocks. Such case doesn't happen with current kernel, but it may happen with the planned rework on clocks and power domain code.
Best regards
Marek Szyprowski
Samsung R&D Institute Poland
Marek Szyprowski (3):
iommu/exynos: Return proper errors from getting clocks iommu/exynos: Fix master clock management for inactive SYSMMU iommu/exynos: Prepare clocks when needed, not in driver probe
drivers/iommu/exynos-iommu.c | 95 ++++++++++++++++++++------------------------ 1 file changed, 42 insertions(+), 53 deletions(-)
Signature · 1 line
1.9.2
Marek Szyprowski
maintainerPATCH 1/3 iommu/exynos: Return proper errors from getting clocks
This patch reworks driver probe code to propagate error codes from clk_get() operation. This will allow to properly handle deferred probe in the future.
--- drivers/iommu/exynos-iommu.c | 56 +++++++++++++++++++------------------------- 1 file changed, 24 insertions(+), 32 deletions(-)
drivers/iommu/exynos-iommu.c +24 -32
@@ -602,37 +602,31 @@ static int __init exynos_sysmmu_probe(struct platform_device *pdev) } data->clk =devm_clk_get (dev,"sysmmu" ); -if (!IS_ERR (data->clk)) { - ret =clk_prepare (data->clk); -if (ret) { -dev_err (dev,"Failed to prepare clk\n" ); -return ret; - } - }else { +if (PTR_ERR (data->clk) == -ENOENT ) data->clk =NULL ; - } +else if (IS_ERR (data->clk)) +return PTR_ERR (data->clk); + ret =clk_prepare (data->clk); +if (ret) +return ret; data->aclk =devm_clk_get (dev,"aclk" ); -if (!IS_ERR (data->aclk)) { - ret =clk_prepare (data->aclk); -if (ret) { -dev_err (dev,"Failed to prepare aclk\n" ); -return ret; - } - }else { +if (PTR_ERR (data->aclk) == -ENOENT ) data->aclk =NULL ; - } +else if (IS_ERR (data->aclk)) +return PTR_ERR (data->aclk); + ret =clk_prepare (data->aclk); +if (ret) +return ret; data->pclk =devm_clk_get (dev,"pclk" ); -if (!IS_ERR (data->pclk)) { - ret =clk_prepare (data->pclk); -if (ret) { -dev_err (dev,"Failed to prepare pclk\n" ); -return ret; - } - }else { +if (PTR_ERR (data->pclk) == -ENOENT ) data->pclk =NULL ; - } +else if (IS_ERR (data->pclk)) +return PTR_ERR (data->pclk); + ret =clk_prepare (data->pclk); +if (ret) +return ret;if (!data->clk && (!data->aclk || !data->pclk)) {dev_err (dev,"Failed to get device clock(s)!\n" );
@@ -640,15 +634,13 @@ static int __init exynos_sysmmu_probe(struct platform_device *pdev) } data->clk_master =devm_clk_get (dev,"master" ); -if (!IS_ERR (data->clk_master)) { - ret =clk_prepare (data->clk_master); -if (ret) { -dev_err (dev,"Failed to prepare master's clk\n" ); -return ret; - } - }else { +if (PTR_ERR (data->clk_master) == -ENOENT ) data->clk_master =NULL ; - } +else if (IS_ERR (data->clk_master)) +return PTR_ERR (data->clk_master); + ret =clk_prepare (data->clk_master); +if (ret) +return ret; data->sysmmu = dev;spin_lock_init (&data->lock);
Signature · 1 line
1.9.2
Marek Szyprowski
maintainerPATCH 2/3 iommu/exynos: Fix master clock management for inactive SYSMMU
In reply to Marek SzyprowskiIf SYSMMU controller is not active, there is no point in enabling master's clock just for doing the the of internal state. This patch moves enabling that clock to the block which actually does the register access.
--- drivers/iommu/exynos-iommu.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-)
drivers/iommu/exynos-iommu.c +4 -5
@@ -524,16 +524,15 @@ static void sysmmu_tlb_invalidate_flpdcache(struct sysmmu_drvdata *data, {unsigned long flags; -clk_enable (data->clk_master);spin_lock_irqsave (&data->lock, flags); -if (is_sysmmu_active (data)) { -if (data->version >=MAKE_MMU_VER (3 ,3 )) -__sysmmu_tlb_invalidate_entry (data, iova,1 ); +if (is_sysmmu_active (data) && data->version >=MAKE_MMU_VER (3 ,3 )) { +clk_enable (data->clk_master); +__sysmmu_tlb_invalidate_entry (data, iova,1 ); +clk_disable (data->clk_master); }spin_unlock_irqrestore (&data->lock, flags); -clk_disable (data->clk_master); } static void sysmmu_tlb_invalidate_entry(struct sysmmu_drvdata *data,
Signature · 1 line
1.9.2
Marek Szyprowski
maintainerPATCH 3/3 iommu/exynos: Prepare clocks when needed, not in driver probe
In reply to Marek SzyprowskiMake 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().
--- drivers/iommu/exynos-iommu.c | 54 +++++++++++++++++++++----------------------- 1 file changed, 26 insertions(+), 28 deletions(-)
drivers/iommu/exynos-iommu.c +26 -28
@@ -322,14 +322,27 @@ static void __sysmmu_set_ptbase(struct sysmmu_drvdata *data, phys_addr_t pgd)__sysmmu_tlb_invalidate (data); } +static void __sysmmu_enable_clocks (struct sysmmu_drvdata *data) +{ +BUG_ON (clk_prepare_enable (data->clk_master)); +BUG_ON (clk_prepare_enable (data->clk)); +BUG_ON (clk_prepare_enable (data->pclk)); +BUG_ON (clk_prepare_enable (data->aclk)); +} + +static void __sysmmu_disable_clocks (struct sysmmu_drvdata *data) +{ +clk_disable_unprepare (data->aclk); +clk_disable_unprepare (data->pclk); +clk_disable_unprepare (data->clk); +clk_disable_unprepare (data->clk_master); +} +static void __sysmmu_get_version (struct sysmmu_drvdata *data) {u32 ver; -clk_enable (data->clk_master); -clk_enable (data->clk); -clk_enable (data->pclk); -clk_enable (data->aclk); +__sysmmu_enable_clocks (data); ver =readl (data->sfrbase +REG_MMU_VERSION );
@@ -342,10 +355,7 @@ static void __sysmmu_get_version(struct sysmmu_drvdata *data)dev_dbg (data->sysmmu,"hardware version: %d.%d\n" ,MMU_MAJ_VER (data->version),MMU_MIN_VER (data->version)); -clk_disable (data->aclk); -clk_disable (data->pclk); -clk_disable (data->clk); -clk_disable (data->clk_master); +__sysmmu_disable_clocks (data); } static void show_fault_information(struct sysmmu_drvdata *data,
@@ -427,10 +437,7 @@ static void __sysmmu_disable_nocount(struct sysmmu_drvdata *data)writel (CTRL_DISABLE , data->sfrbase +REG_MMU_CTRL );writel (0 , data->sfrbase +REG_MMU_CFG ); -clk_disable (data->aclk); -clk_disable (data->pclk); -clk_disable (data->clk); -clk_disable (data->clk_master); +__sysmmu_disable_clocks (data); }static bool __sysmmu_disable (struct sysmmu_drvdata *data)
@@ -475,10 +482,7 @@ static void __sysmmu_init_config(struct sysmmu_drvdata *data)static void __sysmmu_enable_nocount (struct sysmmu_drvdata *data) { -clk_enable (data->clk_master); -clk_enable (data->clk); -clk_enable (data->pclk); -clk_enable (data->aclk); +__sysmmu_enable_clocks (data);writel (CTRL_BLOCK , data->sfrbase +REG_MMU_CTRL );
@@ -488,6 +492,12 @@ static void __sysmmu_enable_nocount(struct sysmmu_drvdata *data)writel (CTRL_ENABLE , data->sfrbase +REG_MMU_CTRL ); +/* +* SYSMMU driver keeps master's clock enabled only for the short +* time, while accessing the registers. For performing address +* translation during DMA transaction it relies on the client +* driver to enable it. +*/ clk_disable (data->clk_master); }
@@ -605,27 +615,18 @@ static int __init exynos_sysmmu_probe(struct platform_device *pdev) data->clk =NULL ; else if (IS_ERR(data->clk)) return PTR_ERR(data->clk); - ret = clk_prepare(data->clk); -if (ret) -return ret; data->aclk =devm_clk_get (dev,"aclk" );if (PTR_ERR (data->aclk) == -ENOENT ) data->aclk =NULL ;else if (IS_ERR (data->aclk))return PTR_ERR (data->aclk); - ret =clk_prepare (data->aclk); -if (ret) -return ret; data->pclk =devm_clk_get (dev,"pclk" );if (PTR_ERR (data->pclk) == -ENOENT ) data->pclk =NULL ;else if (IS_ERR (data->pclk))return PTR_ERR (data->pclk); - ret =clk_prepare (data->pclk); -if (ret) -return ret;if (!data->clk && (!data->aclk || !data->pclk)) {dev_err (dev,"Failed to get device clock(s)!\n" );
@@ -637,9 +638,6 @@ static int __init exynos_sysmmu_probe(struct platform_device *pdev) data->clk_master =NULL ; else if (IS_ERR(data->clk_master)) return PTR_ERR(data->clk_master); - ret = clk_prepare(data->clk_master); -if (ret) -return ret; data->sysmmu = dev;spin_lock_init (&data->lock);
Signature · 1 line
1.9.2
Marek Szyprowski
maintainer[PATCH 4/3] iommu/exynos: Prepare for deferred probe support
In reply to Marek SzyprowskiRegister iommu_ops at the end of successful probe instead of doing that unconditionally. This makes Exynos IOMMU driver ready for deferred probe caused by not-yet-available clocks.
---
I'm sorry for the confussing patch number. This patch got lost while rebasing, but it should belong to the "Exynos IOMMU: improve clock management" patchset.
Best regards
Marek Szyprowski
Samsung R&D Institute Poland
--- drivers/iommu/exynos-iommu.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
drivers/iommu/exynos-iommu.c +4 -1
@@ -581,6 +581,8 @@ static void sysmmu_tlb_invalidate_entry(struct sysmmu_drvdata *data,spin_unlock_irqrestore (&data->lock, flags); } +static struct iommu_ops exynos_iommu_ops; +static int __init exynos_sysmmu_probe (struct platform_device *pdev) {int irq, ret;
@@ -654,6 +656,8 @@ static int __init exynos_sysmmu_probe(struct platform_device *pdev)pm_runtime_enable (dev); +of_iommu_set_ops (dev->of_node, &exynos_iommu_ops); +return 0 ; }
@@ -1347,7 +1351,6 @@ static int __init exynos_iommu_of_setup(struct device_node *np)if (!dma_dev) dma_dev = &pdev->dev; -of_iommu_set_ops (np, &exynos_iommu_ops);return 0 ; }
Signature · 1 line
1.9.2
cover Exynos IOMMU: improve clock management
In reply to Marek SzyprowskiQuoted 13 lines · Marek Szyprowski
Hello,
This patch series improves clock management in Exynos IOMMU driver, so the driver will be ready for potential deferred probe caused by not-yet-available clocks. Such case doesn't happen with current kernel, but it may happen with the planned rework on clocks and power domain code.
Best regards
Marek Szyprowski
Samsung R&D Institute Poland
Quoted 7 lines
Marek Szyprowski (3):
iommu/exynos: Return proper errors from getting clocks iommu/exynos: Fix master clock management for inactive SYSMMU iommu/exynos: Prepare clocks when needed, not in driver probedrivers/iommu/exynos-iommu.c | 95 ++++++++++++++++++++------------------------ 1 file changed, 42 insertions(+), 53 deletions(-)
Applied all, thanks.