From 192c344e7cd4e19a4260752604ba219ffa41deb1 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Fri, 26 Mar 2021 13:00:54 +0100 Subject: [PATCH 01/18] clk: renesas: rcar-gen3: Update Z clock rate formula in comments The fixed divider in the calculation of the Z and Z2 clock rates was generalized from a hardcoded value of two to a parameterized value, but the comments were not updated accordingly. Fixes: 20cc05ba04a93f05 ("clk: renesas: rcar-gen3: Parameterise Z and Z2 clock fixed divisor") Signed-off-by: Geert Uytterhoeven Acked-by: Stephen Boyd Reviewed-by: Yoshihiro Shimoda Link: https://lore.kernel.org/r/20210326120100.1577596-2-geert+renesas@glider.be --- drivers/clk/renesas/rcar-gen3-cpg.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/clk/renesas/rcar-gen3-cpg.c b/drivers/clk/renesas/rcar-gen3-cpg.c index caa0f9414e45..5edc85ab04b4 100644 --- a/drivers/clk/renesas/rcar-gen3-cpg.c +++ b/drivers/clk/renesas/rcar-gen3-cpg.c @@ -38,7 +38,8 @@ * Traits of this clock: * prepare - clk_prepare only ensures that parents are prepared * enable - clk_enable only ensures that parents are enabled - * rate - rate is adjustable. clk->rate = (parent->rate * mult / 32 ) / 2 + * rate - rate is adjustable. + * clk->rate = (parent->rate * mult / 32 ) / fixed_div * parent - fixed parent. No clk_set_parent support */ #define CPG_FRQCRB 0x00000004 From 58effcd350c81735154313aa49b1c0801fdb04a2 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Fri, 26 Mar 2021 13:00:55 +0100 Subject: [PATCH 02/18] clk: renesas: rcar-gen3: Make cpg_z_clk.mask u32 cpg_z_clk.mask contains a mask for a 32-bit register. Hence its size can be reduced from unsigned long to u32. Signed-off-by: Geert Uytterhoeven Acked-by: Stephen Boyd Reviewed-by: Yoshihiro Shimoda Tested-by: Yoshihiro Shimoda Link: https://lore.kernel.org/r/20210326120100.1577596-3-geert+renesas@glider.be --- drivers/clk/renesas/rcar-gen3-cpg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/renesas/rcar-gen3-cpg.c b/drivers/clk/renesas/rcar-gen3-cpg.c index 5edc85ab04b4..e5edf1b90841 100644 --- a/drivers/clk/renesas/rcar-gen3-cpg.c +++ b/drivers/clk/renesas/rcar-gen3-cpg.c @@ -50,8 +50,8 @@ struct cpg_z_clk { struct clk_hw hw; void __iomem *reg; void __iomem *kick_reg; - unsigned long mask; unsigned int fixed_div; + u32 mask; }; #define to_z_clk(_hw) container_of(_hw, struct cpg_z_clk, hw) From c141897caafb4754b6ef862a67c87b8feed4d921 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Fri, 26 Mar 2021 13:00:56 +0100 Subject: [PATCH 03/18] clk: renesas: rcar-gen3: Remove superfluous masking in cpg_z_clk_set_rate() Due to the clamping of mult, "(32 - mult) << __ffs(zclk->mask)" can never exceed the mask. Signed-off-by: Geert Uytterhoeven Acked-by: Stephen Boyd Reviewed-by: Yoshihiro Shimoda Tested-by: Yoshihiro Shimoda Link: https://lore.kernel.org/r/20210326120100.1577596-4-geert+renesas@glider.be --- drivers/clk/renesas/rcar-gen3-cpg.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/clk/renesas/rcar-gen3-cpg.c b/drivers/clk/renesas/rcar-gen3-cpg.c index e5edf1b90841..cf0d049aa8c7 100644 --- a/drivers/clk/renesas/rcar-gen3-cpg.c +++ b/drivers/clk/renesas/rcar-gen3-cpg.c @@ -104,8 +104,7 @@ static int cpg_z_clk_set_rate(struct clk_hw *hw, unsigned long rate, if (readl(zclk->kick_reg) & CPG_FRQCRB_KICK) return -EBUSY; - cpg_reg_modify(zclk->reg, zclk->mask, - ((32 - mult) << __ffs(zclk->mask)) & zclk->mask); + cpg_reg_modify(zclk->reg, zclk->mask, (32 - mult) << __ffs(zclk->mask)); /* * Set KICK bit in FRQCRB to update hardware setting and wait for From 67a1b9b65165bd3204adef13f0d557b5705116b4 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Fri, 26 Mar 2021 13:00:57 +0100 Subject: [PATCH 04/18] clk: renesas: rcar-gen3: Grammar s/dependent of/dependent on/ Fix grammar in comments for cpg_z_clk_set_rate(). Signed-off-by: Geert Uytterhoeven Acked-by: Stephen Boyd Reviewed-by: Yoshihiro Shimoda Link: https://lore.kernel.org/r/20210326120100.1577596-5-geert+renesas@glider.be --- drivers/clk/renesas/rcar-gen3-cpg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/renesas/rcar-gen3-cpg.c b/drivers/clk/renesas/rcar-gen3-cpg.c index cf0d049aa8c7..a241bf6e904f 100644 --- a/drivers/clk/renesas/rcar-gen3-cpg.c +++ b/drivers/clk/renesas/rcar-gen3-cpg.c @@ -117,7 +117,7 @@ static int cpg_z_clk_set_rate(struct clk_hw *hw, unsigned long rate, * * Using experimental measurements, it seems that no more than * ~10 iterations are needed, independently of the CPU rate. - * Since this value might be dependent of external xtal rate, pll1 + * Since this value might be dependent on external xtal rate, pll1 * rate or even the other emulation clocks rate, use 1000 as a * "super" safe value. */ From 50086045bd07a9bc55c113f2b19a8f3746c9f9b0 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Fri, 26 Mar 2021 13:00:58 +0100 Subject: [PATCH 05/18] clk: renesas: rcar-gen3: Increase Z clock accuracy Improve accuracy in the .determine_rate() callback for Z and Z2 clocks by using rounded divisions. This is similar to the calculation of rates and multipliers in the .recalc_rate() resp. set_rate() callbacks. Sample impact for a few requested clock rates: - R-Car H3: - Z 500 MHz: 468 MHz => 515 MHz - Z2 1000 MHz: 973 MHz => 1011 MHz - R-Car M3-W: - Z 500 MHz: 422 MHz => 516 MHz - Z2 800 MHz: 750 MHz => 788 MHz Signed-off-by: Geert Uytterhoeven Acked-by: Stephen Boyd Reviewed-by: Yoshihiro Shimoda Tested-by: Yoshihiro Shimoda Link: https://lore.kernel.org/r/20210326120100.1577596-6-geert+renesas@glider.be --- drivers/clk/renesas/rcar-gen3-cpg.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/clk/renesas/rcar-gen3-cpg.c b/drivers/clk/renesas/rcar-gen3-cpg.c index a241bf6e904f..6b389c1caca7 100644 --- a/drivers/clk/renesas/rcar-gen3-cpg.c +++ b/drivers/clk/renesas/rcar-gen3-cpg.c @@ -83,10 +83,10 @@ static int cpg_z_clk_determine_rate(struct clk_hw *hw, if (max_mult < min_mult) return -EINVAL; - mult = div64_ul(req->rate * 32ULL, prate); + mult = DIV_ROUND_CLOSEST_ULL(req->rate * 32ULL, prate); mult = clamp(mult, min_mult, max_mult); - req->rate = div_u64((u64)prate * mult, 32); + req->rate = DIV_ROUND_CLOSEST_ULL((u64)prate * mult, 32); return 0; } From 3f70795636853214fd941d3ffe0a9701176cb8ba Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Fri, 26 Mar 2021 13:00:59 +0100 Subject: [PATCH 06/18] clk: renesas: rcar-gen3: Add custom clock for PLLs Currently the PLLs are modeled as fixed factor clocks, based on initial settings. However, enabling CPU boost clock rates requires increasing the PLL clock rates. Add a custom clock driver to model the PLL clocks. This will allow the Z (CPU) clock driver to request changing the PLL clock rate. Based on a patch in the BSP by Takeshi Kihara . Signed-off-by: Geert Uytterhoeven Acked-by: Stephen Boyd Reviewed-by: Yoshihiro Shimoda Tested-by: Yoshihiro Shimoda Link: https://lore.kernel.org/r/20210326120100.1577596-7-geert+renesas@glider.be --- drivers/clk/renesas/rcar-gen3-cpg.c | 147 ++++++++++++++++++++++++---- 1 file changed, 128 insertions(+), 19 deletions(-) diff --git a/drivers/clk/renesas/rcar-gen3-cpg.c b/drivers/clk/renesas/rcar-gen3-cpg.c index 6b389c1caca7..cc9a116d7d09 100644 --- a/drivers/clk/renesas/rcar-gen3-cpg.c +++ b/drivers/clk/renesas/rcar-gen3-cpg.c @@ -26,12 +26,127 @@ #include "rcar-cpg-lib.h" #include "rcar-gen3-cpg.h" -#define CPG_PLL0CR 0x00d8 +#define CPG_PLLECR 0x00d0 /* PLL Enable Control Register */ + +#define CPG_PLLECR_PLLST(n) BIT(8 + (n)) /* PLLn Circuit Status */ + +#define CPG_PLL0CR 0x00d8 /* PLLn Control Registers */ #define CPG_PLL2CR 0x002c #define CPG_PLL4CR 0x01f4 +#define CPG_PLLnCR_STC_MASK GENMASK(30, 24) /* PLL Circuit Mult. Ratio */ + #define CPG_RCKCR_CKSEL BIT(15) /* RCLK Clock Source Select */ +/* PLL Clocks */ +struct cpg_pll_clk { + struct clk_hw hw; + void __iomem *pllcr_reg; + void __iomem *pllecr_reg; + unsigned int fixed_mult; + u32 pllecr_pllst_mask; +}; + +#define to_pll_clk(_hw) container_of(_hw, struct cpg_pll_clk, hw) + +static unsigned long cpg_pll_clk_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct cpg_pll_clk *pll_clk = to_pll_clk(hw); + unsigned int mult; + u32 val; + + val = readl(pll_clk->pllcr_reg) & CPG_PLLnCR_STC_MASK; + mult = (val >> __ffs(CPG_PLLnCR_STC_MASK)) + 1; + + return parent_rate * mult * pll_clk->fixed_mult; +} + +static int cpg_pll_clk_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) +{ + struct cpg_pll_clk *pll_clk = to_pll_clk(hw); + unsigned int min_mult, max_mult, mult; + unsigned long prate; + + prate = req->best_parent_rate * pll_clk->fixed_mult; + min_mult = max(div64_ul(req->min_rate, prate), 1ULL); + max_mult = min(div64_ul(req->max_rate, prate), 128ULL); + if (max_mult < min_mult) + return -EINVAL; + + mult = DIV_ROUND_CLOSEST_ULL(req->rate, prate); + mult = clamp(mult, min_mult, max_mult); + + req->rate = prate * mult; + return 0; +} + +static int cpg_pll_clk_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct cpg_pll_clk *pll_clk = to_pll_clk(hw); + unsigned int mult, i; + u32 val; + + mult = DIV_ROUND_CLOSEST_ULL(rate, parent_rate * pll_clk->fixed_mult); + mult = clamp(mult, 1U, 128U); + + val = readl(pll_clk->pllcr_reg); + val &= ~CPG_PLLnCR_STC_MASK; + val |= (mult - 1) << __ffs(CPG_PLLnCR_STC_MASK); + writel(val, pll_clk->pllcr_reg); + + for (i = 1000; i; i--) { + if (readl(pll_clk->pllecr_reg) & pll_clk->pllecr_pllst_mask) + return 0; + + cpu_relax(); + } + + return -ETIMEDOUT; +} + +static const struct clk_ops cpg_pll_clk_ops = { + .recalc_rate = cpg_pll_clk_recalc_rate, + .determine_rate = cpg_pll_clk_determine_rate, + .set_rate = cpg_pll_clk_set_rate, +}; + +static struct clk * __init cpg_pll_clk_register(const char *name, + const char *parent_name, + void __iomem *base, + unsigned int mult, + unsigned int offset, + unsigned int index) + +{ + struct cpg_pll_clk *pll_clk; + struct clk_init_data init = {}; + struct clk *clk; + + pll_clk = kzalloc(sizeof(*pll_clk), GFP_KERNEL); + if (!pll_clk) + return ERR_PTR(-ENOMEM); + + init.name = name; + init.ops = &cpg_pll_clk_ops; + init.parent_names = &parent_name; + init.num_parents = 1; + + pll_clk->hw.init = &init; + pll_clk->pllcr_reg = base + offset; + pll_clk->pllecr_reg = base + CPG_PLLECR; + pll_clk->fixed_mult = mult; /* PLL refclk x (setting + 1) x mult */ + pll_clk->pllecr_pllst_mask = CPG_PLLECR_PLLST(index); + + clk = clk_register(NULL, &pll_clk->hw); + if (IS_ERR(clk)) + kfree(pll_clk); + + return clk; +} + /* * Z Clock & Z2 Clock * @@ -314,16 +429,13 @@ struct clk * __init rcar_gen3_cpg_clk_register(struct device *dev, case CLK_TYPE_GEN3_PLL0: /* - * PLL0 is a configurable multiplier clock. Register it as a - * fixed factor clock for now as there's no generic multiplier - * clock implementation and we currently have no need to change - * the multiplier value. + * PLL0 is implemented as a custom clock, to change the + * multiplier when cpufreq changes between normal and boost + * modes. */ - value = readl(base + CPG_PLL0CR); - mult = (((value >> 24) & 0x7f) + 1) * 2; - if (cpg_quirks & PLL_ERRATA) - mult *= 2; - break; + mult = (cpg_quirks & PLL_ERRATA) ? 4 : 2; + return cpg_pll_clk_register(core->name, __clk_get_name(parent), + base, mult, CPG_PLL0CR, 0); case CLK_TYPE_GEN3_PLL1: mult = cpg_pll_config->pll1_mult; @@ -332,16 +444,13 @@ struct clk * __init rcar_gen3_cpg_clk_register(struct device *dev, case CLK_TYPE_GEN3_PLL2: /* - * PLL2 is a configurable multiplier clock. Register it as a - * fixed factor clock for now as there's no generic multiplier - * clock implementation and we currently have no need to change - * the multiplier value. + * PLL2 is implemented as a custom clock, to change the + * multiplier when cpufreq changes between normal and boost + * modes. */ - value = readl(base + CPG_PLL2CR); - mult = (((value >> 24) & 0x7f) + 1) * 2; - if (cpg_quirks & PLL_ERRATA) - mult *= 2; - break; + mult = (cpg_quirks & PLL_ERRATA) ? 4 : 2; + return cpg_pll_clk_register(core->name, __clk_get_name(parent), + base, mult, CPG_PLL2CR, 2); case CLK_TYPE_GEN3_PLL3: mult = cpg_pll_config->pll3_mult; From 3a0e84845891eebccce767b4f8cd5ed1b9bffc14 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Fri, 26 Mar 2021 13:01:00 +0100 Subject: [PATCH 07/18] clk: renesas: rcar-gen3: Add boost support to Z clocks Add support for switching the Z and Z2 clocks between normal and boost modes, by requesting clock rate changes to parent PLLs. Inspired by a patch in the BSP by Takeshi Kihara . Signed-off-by: Geert Uytterhoeven Acked-by: Stephen Boyd Reviewed-by: Yoshihiro Shimoda Tested-by: Yoshihiro Shimoda Link: https://lore.kernel.org/r/20210326120100.1577596-8-geert+renesas@glider.be --- drivers/clk/renesas/rcar-gen3-cpg.c | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/drivers/clk/renesas/rcar-gen3-cpg.c b/drivers/clk/renesas/rcar-gen3-cpg.c index cc9a116d7d09..558191c99b48 100644 --- a/drivers/clk/renesas/rcar-gen3-cpg.c +++ b/drivers/clk/renesas/rcar-gen3-cpg.c @@ -165,6 +165,7 @@ struct cpg_z_clk { struct clk_hw hw; void __iomem *reg; void __iomem *kick_reg; + unsigned long max_rate; /* Maximum rate for normal mode */ unsigned int fixed_div; u32 mask; }; @@ -190,7 +191,18 @@ static int cpg_z_clk_determine_rate(struct clk_hw *hw, { struct cpg_z_clk *zclk = to_z_clk(hw); unsigned int min_mult, max_mult, mult; - unsigned long prate; + unsigned long rate, prate; + + rate = min(req->rate, req->max_rate); + if (rate <= zclk->max_rate) { + /* Set parent rate to initial value for normal modes */ + prate = zclk->max_rate; + } else { + /* Set increased parent rate for boost modes */ + prate = rate; + } + req->best_parent_rate = clk_hw_round_rate(clk_hw_get_parent(hw), + prate * zclk->fixed_div); prate = req->best_parent_rate / zclk->fixed_div; min_mult = max(div64_ul(req->min_rate * 32ULL, prate), 1ULL); @@ -198,7 +210,7 @@ static int cpg_z_clk_determine_rate(struct clk_hw *hw, if (max_mult < min_mult) return -EINVAL; - mult = DIV_ROUND_CLOSEST_ULL(req->rate * 32ULL, prate); + mult = DIV_ROUND_CLOSEST_ULL(rate * 32ULL, prate); mult = clamp(mult, min_mult, max_mult); req->rate = DIV_ROUND_CLOSEST_ULL((u64)prate * mult, 32); @@ -268,7 +280,7 @@ static struct clk * __init cpg_z_clk_register(const char *name, init.name = name; init.ops = &cpg_z_clk_ops; - init.flags = 0; + init.flags = CLK_SET_RATE_PARENT; init.parent_names = &parent_name; init.num_parents = 1; @@ -279,9 +291,13 @@ static struct clk * __init cpg_z_clk_register(const char *name, zclk->fixed_div = div; /* PLLVCO x 1/div x SYS-CPU divider */ clk = clk_register(NULL, &zclk->hw); - if (IS_ERR(clk)) + if (IS_ERR(clk)) { kfree(zclk); + return clk; + } + zclk->max_rate = clk_hw_get_rate(clk_hw_get_parent(&zclk->hw)) / + zclk->fixed_div; return clk; } From 16927401d92401b8f1fe6b57707e08271347ee80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niklas=20S=C3=B6derlund?= Date: Tue, 30 Mar 2021 00:32:20 +0200 Subject: [PATCH 08/18] clk: renesas: r8a779a0: Add ISPCS clocks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add support for the ISPCS clocks on R-Car V3U. Signed-off-by: Niklas Söderlund Link: https://lore.kernel.org/r/20210329223220.1139211-1-niklas.soderlund+renesas@ragnatech.se Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/r8a779a0-cpg-mssr.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/clk/renesas/r8a779a0-cpg-mssr.c b/drivers/clk/renesas/r8a779a0-cpg-mssr.c index 867c565cb58f..acaf5a93f1d3 100644 --- a/drivers/clk/renesas/r8a779a0-cpg-mssr.c +++ b/drivers/clk/renesas/r8a779a0-cpg-mssr.c @@ -180,6 +180,10 @@ static const struct mssr_mod_clk r8a779a0_mod_clks[] __initconst = { DEF_MOD("i2c4", 522, R8A779A0_CLK_S1D4), DEF_MOD("i2c5", 523, R8A779A0_CLK_S1D4), DEF_MOD("i2c6", 524, R8A779A0_CLK_S1D4), + DEF_MOD("ispcs0", 612, R8A779A0_CLK_S1D1), + DEF_MOD("ispcs1", 613, R8A779A0_CLK_S1D1), + DEF_MOD("ispcs2", 614, R8A779A0_CLK_S1D1), + DEF_MOD("ispcs3", 615, R8A779A0_CLK_S1D1), DEF_MOD("msi0", 618, R8A779A0_CLK_MSO), DEF_MOD("msi1", 619, R8A779A0_CLK_MSO), DEF_MOD("msi2", 620, R8A779A0_CLK_MSO), From a20a40a8bbc2cf4b29d7248ea31e974e9103dd7f Mon Sep 17 00:00:00 2001 From: Dinghao Liu Date: Thu, 15 Apr 2021 15:33:38 +0800 Subject: [PATCH 09/18] clk: renesas: rcar-usb2-clock-sel: Fix error handling in .probe() The error handling paths after pm_runtime_get_sync() have no refcount decrement, which leads to refcount leak. Signed-off-by: Dinghao Liu Link: https://lore.kernel.org/r/20210415073338.22287-1-dinghao.liu@zju.edu.cn [geert: Remove now unused variable priv] Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/rcar-usb2-clock-sel.c | 24 ++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/drivers/clk/renesas/rcar-usb2-clock-sel.c b/drivers/clk/renesas/rcar-usb2-clock-sel.c index 34a85dc95beb..9fb79bd79435 100644 --- a/drivers/clk/renesas/rcar-usb2-clock-sel.c +++ b/drivers/clk/renesas/rcar-usb2-clock-sel.c @@ -128,10 +128,8 @@ static int rcar_usb2_clock_sel_resume(struct device *dev) static int rcar_usb2_clock_sel_remove(struct platform_device *pdev) { struct device *dev = &pdev->dev; - struct usb2_clock_sel_priv *priv = platform_get_drvdata(pdev); of_clk_del_provider(dev->of_node); - clk_hw_unregister(&priv->hw); pm_runtime_put(dev); pm_runtime_disable(dev); @@ -164,9 +162,6 @@ static int rcar_usb2_clock_sel_probe(struct platform_device *pdev) if (IS_ERR(priv->rsts)) return PTR_ERR(priv->rsts); - pm_runtime_enable(dev); - pm_runtime_get_sync(dev); - clk = devm_clk_get(dev, "usb_extal"); if (!IS_ERR(clk) && !clk_prepare_enable(clk)) { priv->extal = !!clk_get_rate(clk); @@ -183,6 +178,8 @@ static int rcar_usb2_clock_sel_probe(struct platform_device *pdev) return -ENOENT; } + pm_runtime_enable(dev); + pm_runtime_get_sync(dev); platform_set_drvdata(pdev, priv); dev_set_drvdata(dev, priv); @@ -190,11 +187,20 @@ static int rcar_usb2_clock_sel_probe(struct platform_device *pdev) init.ops = &usb2_clock_sel_clock_ops; priv->hw.init = &init; - clk = clk_register(NULL, &priv->hw); - if (IS_ERR(clk)) - return PTR_ERR(clk); + ret = devm_clk_hw_register(NULL, &priv->hw); + if (ret) + goto pm_put; - return of_clk_add_hw_provider(np, of_clk_hw_simple_get, &priv->hw); + ret = of_clk_add_hw_provider(np, of_clk_hw_simple_get, &priv->hw); + if (ret) + goto pm_put; + + return 0; + +pm_put: + pm_runtime_put(dev); + pm_runtime_disable(dev); + return ret; } static const struct dev_pm_ops rcar_usb2_clock_sel_pm_ops = { From 6c7bc7dbcc4122745a214134749a0b1ab2658c80 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 1 Apr 2021 15:01:34 +0200 Subject: [PATCH 10/18] clk: renesas: div6: Use clamp() instead of clamp_t() As "div" is already "unsigned int", adding "U" suffixes to the constants "1" and "64" allows us to replace the call to clamp_t() by a call to clamp(). This removes hidden casts, and thus helps the compiler doing a better job at type-checking. Signed-off-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/2670c1e3c82a245666578cbbd1fb20d37932fd8e.1617281699.git.geert+renesas@glider.be --- drivers/clk/renesas/clk-div6.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/renesas/clk-div6.c b/drivers/clk/renesas/clk-div6.c index 8fb68e703a6b..a3c4fbeb7b0d 100644 --- a/drivers/clk/renesas/clk-div6.c +++ b/drivers/clk/renesas/clk-div6.c @@ -99,7 +99,7 @@ static unsigned int cpg_div6_clock_calc_div(unsigned long rate, rate = 1; div = DIV_ROUND_CLOSEST(parent_rate, rate); - return clamp_t(unsigned int, div, 1, 64); + return clamp(div, 1U, 64U); } static long cpg_div6_clock_round_rate(struct clk_hw *hw, unsigned long rate, From 23b04c84e201e82c1929144a2ce1442bd64e77f3 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 1 Apr 2021 15:01:35 +0200 Subject: [PATCH 11/18] clk: renesas: div6: Simplify src mask handling Simplify the handling of the register bits to select the parent clock, by storing a bitmask instead of separate shift and width values. Signed-off-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/5f05a5110d222ce5a113e683fe2aa726f4100b73.1617281699.git.geert+renesas@glider.be --- drivers/clk/renesas/clk-div6.c | 31 +++++++++++-------------------- 1 file changed, 11 insertions(+), 20 deletions(-) diff --git a/drivers/clk/renesas/clk-div6.c b/drivers/clk/renesas/clk-div6.c index a3c4fbeb7b0d..2920bec49bce 100644 --- a/drivers/clk/renesas/clk-div6.c +++ b/drivers/clk/renesas/clk-div6.c @@ -28,8 +28,7 @@ * @hw: handle between common and hardware-specific interfaces * @reg: IO-remapped register * @div: divisor value (1-64) - * @src_shift: Shift to access the register bits to select the parent clock - * @src_width: Number of register bits to select the parent clock (may be 0) + * @src_mask: Bitmask covering the register bits to select the parent clock * @nb: Notifier block to save/restore clock state for system resume * @parents: Array to map from valid parent clocks indices to hardware indices */ @@ -37,8 +36,7 @@ struct div6_clock { struct clk_hw hw; void __iomem *reg; unsigned int div; - u32 src_shift; - u32 src_width; + u32 src_mask; struct notifier_block nb; u8 parents[]; }; @@ -133,11 +131,11 @@ static u8 cpg_div6_clock_get_parent(struct clk_hw *hw) unsigned int i; u8 hw_index; - if (clock->src_width == 0) + if (clock->src_mask == 0) return 0; - hw_index = (readl(clock->reg) >> clock->src_shift) & - (BIT(clock->src_width) - 1); + hw_index = (readl(clock->reg) & clock->src_mask) >> + __ffs(clock->src_mask); for (i = 0; i < clk_hw_get_num_parents(hw); i++) { if (clock->parents[i] == hw_index) return i; @@ -151,18 +149,13 @@ static u8 cpg_div6_clock_get_parent(struct clk_hw *hw) static int cpg_div6_clock_set_parent(struct clk_hw *hw, u8 index) { struct div6_clock *clock = to_div6_clock(hw); - u8 hw_index; - u32 mask; + u32 src; if (index >= clk_hw_get_num_parents(hw)) return -EINVAL; - mask = ~((BIT(clock->src_width) - 1) << clock->src_shift); - hw_index = clock->parents[index]; - - writel((readl(clock->reg) & mask) | (hw_index << clock->src_shift), - clock->reg); - + src = clock->parents[index] << __ffs(clock->src_mask); + writel((readl(clock->reg) & ~clock->src_mask) | src, clock->reg); return 0; } @@ -236,17 +229,15 @@ struct clk * __init cpg_div6_register(const char *name, switch (num_parents) { case 1: /* fixed parent clock */ - clock->src_shift = clock->src_width = 0; + clock->src_mask = 0; break; case 4: /* clock with EXSRC bits 6-7 */ - clock->src_shift = 6; - clock->src_width = 2; + clock->src_mask = GENMASK(7, 6); break; case 8: /* VCLK with EXSRC bits 12-14 */ - clock->src_shift = 12; - clock->src_width = 3; + clock->src_mask = GENMASK(14, 12); break; default: pr_err("%s: invalid number of parents for DIV6 clock %s\n", From c9d1b58b272e272fc7121929e2d0e0755ea1656e Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 1 Apr 2021 15:01:36 +0200 Subject: [PATCH 12/18] clk: renesas: div6: Switch to .determine_rate() As the .round_rate() callback returns a long clock rate, it cannot return clock rates that do not fit in signed long, but do fit in unsigned long. Hence switch the DIV6 clocks on SH/R-Mobile and R-Car SoCs from the old .round_rate() callback to the newer .determine_rate() callback, which does not suffer from this limitation. Signed-off-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/7fd8c45cd8bf5c6d928ca69c8b669be35b93de09.1617281699.git.geert+renesas@glider.be --- drivers/clk/renesas/clk-div6.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/clk/renesas/clk-div6.c b/drivers/clk/renesas/clk-div6.c index 2920bec49bce..3af65ef5690e 100644 --- a/drivers/clk/renesas/clk-div6.c +++ b/drivers/clk/renesas/clk-div6.c @@ -100,12 +100,14 @@ static unsigned int cpg_div6_clock_calc_div(unsigned long rate, return clamp(div, 1U, 64U); } -static long cpg_div6_clock_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *parent_rate) +static int cpg_div6_clock_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) { - unsigned int div = cpg_div6_clock_calc_div(rate, *parent_rate); + unsigned int div = cpg_div6_clock_calc_div(req->rate, + req->best_parent_rate); - return *parent_rate / div; + req->rate = req->best_parent_rate / div; + return 0; } static int cpg_div6_clock_set_rate(struct clk_hw *hw, unsigned long rate, @@ -166,7 +168,7 @@ static const struct clk_ops cpg_div6_clock_ops = { .get_parent = cpg_div6_clock_get_parent, .set_parent = cpg_div6_clock_set_parent, .recalc_rate = cpg_div6_clock_recalc_rate, - .round_rate = cpg_div6_clock_round_rate, + .determine_rate = cpg_div6_clock_determine_rate, .set_rate = cpg_div6_clock_set_rate, }; From 1c924fc679123e6057239693d226c8d8c5780626 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 1 Apr 2021 15:01:37 +0200 Subject: [PATCH 13/18] clk: renesas: div6: Consider all parents for requested rate Currently the .determine_rate() callback considers only the current parent clock, limiting the range of achievable clock rates on DIV6 clocks with multiple parents, as found on SH/R-Mobile SoCs. Extend the callback to consider all available parent clocks. Signed-off-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/60e639692b462f99e0b6ab868c3675b3d97dbdb0.1617281699.git.geert+renesas@glider.be --- drivers/clk/renesas/clk-div6.c | 35 +++++++++++++++++++++++++++++++--- 1 file changed, 32 insertions(+), 3 deletions(-) diff --git a/drivers/clk/renesas/clk-div6.c b/drivers/clk/renesas/clk-div6.c index 3af65ef5690e..a9ac2a83c1d0 100644 --- a/drivers/clk/renesas/clk-div6.c +++ b/drivers/clk/renesas/clk-div6.c @@ -103,10 +103,39 @@ static unsigned int cpg_div6_clock_calc_div(unsigned long rate, static int cpg_div6_clock_determine_rate(struct clk_hw *hw, struct clk_rate_request *req) { - unsigned int div = cpg_div6_clock_calc_div(req->rate, - req->best_parent_rate); + unsigned long prate, calc_rate, diff, best_rate, best_prate; + unsigned int num_parents = clk_hw_get_num_parents(hw); + struct clk_hw *parent, *best_parent = NULL; + unsigned long min_diff = ULONG_MAX; + unsigned int i, div; - req->rate = req->best_parent_rate / div; + for (i = 0; i < num_parents; i++) { + parent = clk_hw_get_parent_by_index(hw, i); + if (!parent) + continue; + + prate = clk_hw_get_rate(parent); + if (!prate) + continue; + + div = cpg_div6_clock_calc_div(req->rate, prate); + calc_rate = prate / div; + diff = calc_rate > req->rate ? calc_rate - req->rate + : req->rate - calc_rate; + if (diff < min_diff) { + best_rate = calc_rate; + best_parent = parent; + best_prate = prate; + min_diff = diff; + } + } + + if (!best_parent) + return -EINVAL; + + req->best_parent_rate = best_prate; + req->best_parent_hw = best_parent; + req->rate = best_rate; return 0; } From 02c69593e62d51dd6b29b58724a6947ba72074f0 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 1 Apr 2021 15:01:38 +0200 Subject: [PATCH 14/18] clk: renesas: div6: Implement range checking Consider the minimum and maximum clock rates imposed by clock users when calculating the most appropriate clock rate in the .determine_rate() callback. Signed-off-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/35ceb262c71f1b2e9864a39bde9dafd78b2981f4.1617281699.git.geert+renesas@glider.be --- drivers/clk/renesas/clk-div6.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/clk/renesas/clk-div6.c b/drivers/clk/renesas/clk-div6.c index a9ac2a83c1d0..3abd6e5400ad 100644 --- a/drivers/clk/renesas/clk-div6.c +++ b/drivers/clk/renesas/clk-div6.c @@ -106,8 +106,8 @@ static int cpg_div6_clock_determine_rate(struct clk_hw *hw, unsigned long prate, calc_rate, diff, best_rate, best_prate; unsigned int num_parents = clk_hw_get_num_parents(hw); struct clk_hw *parent, *best_parent = NULL; + unsigned int i, min_div, max_div, div; unsigned long min_diff = ULONG_MAX; - unsigned int i, div; for (i = 0; i < num_parents; i++) { parent = clk_hw_get_parent_by_index(hw, i); @@ -118,7 +118,13 @@ static int cpg_div6_clock_determine_rate(struct clk_hw *hw, if (!prate) continue; + min_div = max(DIV_ROUND_UP(prate, req->max_rate), 1UL); + max_div = req->min_rate ? min(prate / req->min_rate, 64UL) : 64; + if (max_div < min_div) + continue; + div = cpg_div6_clock_calc_div(req->rate, prate); + div = clamp(div, min_div, max_div); calc_rate = prate / div; diff = calc_rate > req->rate ? calc_rate - req->rate : req->rate - calc_rate; From 6bd913f54f2f1973e741c6cf36b90175e8963175 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 1 Apr 2021 15:03:24 +0200 Subject: [PATCH 15/18] clk: renesas: r9a06g032: Switch to .determine_rate() As the .round_rate() callback returns a long clock rate, it cannot return clock rates that do not fit in signed long, but do fit in unsigned long. Hence switch the divider clocks on RZ/N1 from the old .round_rate() callback to the newer .determine_rate() callback, which does not suffer from this limitation. Note that range checking is not yet implemented. Signed-off-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/7a384d02b85cdaac4a0e2b357582c8244b9a6f98.1617282116.git.geert+renesas@glider.be --- drivers/clk/renesas/r9a06g032-clocks.c | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/drivers/clk/renesas/r9a06g032-clocks.c b/drivers/clk/renesas/r9a06g032-clocks.c index 71b11443f6fc..c99942f0e4d4 100644 --- a/drivers/clk/renesas/r9a06g032-clocks.c +++ b/drivers/clk/renesas/r9a06g032-clocks.c @@ -604,20 +604,19 @@ r9a06g032_div_clamp_div(struct r9a06g032_clk_div *clk, return div; } -static long -r9a06g032_div_round_rate(struct clk_hw *hw, - unsigned long rate, unsigned long *prate) +static int +r9a06g032_div_determine_rate(struct clk_hw *hw, struct clk_rate_request *req) { struct r9a06g032_clk_div *clk = to_r9a06g032_div(hw); - u32 div = DIV_ROUND_UP(*prate, rate); + u32 div = DIV_ROUND_UP(req->best_parent_rate, req->rate); pr_devel("%s %pC %ld (prate %ld) (wanted div %u)\n", __func__, - hw->clk, rate, *prate, div); + hw->clk, req->rate, req->best_parent_rate, div); pr_devel(" min %d (%ld) max %d (%ld)\n", - clk->min, DIV_ROUND_UP(*prate, clk->min), - clk->max, DIV_ROUND_UP(*prate, clk->max)); + clk->min, DIV_ROUND_UP(req->best_parent_rate, clk->min), + clk->max, DIV_ROUND_UP(req->best_parent_rate, clk->max)); - div = r9a06g032_div_clamp_div(clk, rate, *prate); + div = r9a06g032_div_clamp_div(clk, req->rate, req->best_parent_rate); /* * this is a hack. Currently the serial driver asks for a clock rate * that is 16 times the baud rate -- and that is wildly outside the @@ -630,11 +629,13 @@ r9a06g032_div_round_rate(struct clk_hw *hw, if (clk->index == R9A06G032_DIV_UART || clk->index == R9A06G032_DIV_P2_PG) { pr_devel("%s div uart hack!\n", __func__); - return clk_get_rate(hw->clk); + req->rate = clk_get_rate(hw->clk); + return 0; } + req->rate = DIV_ROUND_UP(req->best_parent_rate, div); pr_devel("%s %pC %ld / %u = %ld\n", __func__, hw->clk, - *prate, div, DIV_ROUND_UP(*prate, div)); - return DIV_ROUND_UP(*prate, div); + req->best_parent_rate, div, req->rate); + return 0; } static int @@ -663,7 +664,7 @@ r9a06g032_div_set_rate(struct clk_hw *hw, static const struct clk_ops r9a06g032_clk_div_ops = { .recalc_rate = r9a06g032_div_recalc_rate, - .round_rate = r9a06g032_div_round_rate, + .determine_rate = r9a06g032_div_determine_rate, .set_rate = r9a06g032_div_set_rate, }; From 682b108ba598e36d8232c9df14d41b3e9993784f Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 4 May 2021 11:17:21 +0200 Subject: [PATCH 16/18] clk: renesas: cpg-mssr: Remove unused [RM]MSTPCR() definitions The Realtime Module Stop Control Register definitions (RMSTPCR(i)) are incorrect for i >= 8 on R-Car Gen2 and Gen3. As these are unused, and not planned to be used, just like the corresponding Modem Module Stop Control Register definitions (MMSTPCR()) on R-Mobile APE6 (they are intended for the software running on the Real-Time and Modem CPU cores), they can just be removed. Reported-by: Hai Nguyen Pham Signed-off-by: Geert Uytterhoeven Acked-by: Stephen Boyd Link: https://lore.kernel.org/r/2d8bc4d9806b419ebb06030d2f31b2ea1e59b1d6.1620119700.git.geert+renesas@glider.be --- drivers/clk/renesas/renesas-cpg-mssr.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/clk/renesas/renesas-cpg-mssr.c b/drivers/clk/renesas/renesas-cpg-mssr.c index fc531d35b269..c3230398e1c1 100644 --- a/drivers/clk/renesas/renesas-cpg-mssr.c +++ b/drivers/clk/renesas/renesas-cpg-mssr.c @@ -100,12 +100,6 @@ static const u16 srcr_for_v3u[] = { 0x2C20, 0x2C24, 0x2C28, 0x2C2C, 0x2C30, 0x2C34, 0x2C38, }; -/* Realtime Module Stop Control Register offsets */ -#define RMSTPCR(i) (smstpcr[i] - 0x20) - -/* Modem Module Stop Control Register offsets (r8a73a4) */ -#define MMSTPCR(i) (smstpcr[i] + 0x20) - /* Software Reset Clearing Register offsets */ static const u16 srstclr[] = { From 3f6ecaf1cad98b266ba3eea4691a71c9ccac8076 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 4 May 2021 11:17:22 +0200 Subject: [PATCH 17/18] clk: renesas: cpg-mssr: Make srstclr[] comment block consistent Make the style of the comment block for the Software Reset Clearing Register offsets consistent with the comment blocks for the other register offsets. Signed-off-by: Geert Uytterhoeven Acked-by: Stephen Boyd Link: https://lore.kernel.org/r/97dde75fe3ff27b9639c59a43cddbd9d5c405d0c.1620119700.git.geert+renesas@glider.be --- drivers/clk/renesas/renesas-cpg-mssr.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/clk/renesas/renesas-cpg-mssr.c b/drivers/clk/renesas/renesas-cpg-mssr.c index c3230398e1c1..21f762aa2131 100644 --- a/drivers/clk/renesas/renesas-cpg-mssr.c +++ b/drivers/clk/renesas/renesas-cpg-mssr.c @@ -100,7 +100,9 @@ static const u16 srcr_for_v3u[] = { 0x2C20, 0x2C24, 0x2C28, 0x2C2C, 0x2C30, 0x2C34, 0x2C38, }; -/* Software Reset Clearing Register offsets */ +/* + * Software Reset Clearing Register offsets + */ static const u16 srstclr[] = { 0x940, 0x944, 0x948, 0x94C, 0x950, 0x954, 0x958, 0x95C, From 790c06cc5df263cdaff748670cc65958c81b0951 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 27 May 2021 13:36:38 +0900 Subject: [PATCH 18/18] clk: renesas: r8a77995: Add ZA2 clock R-Car D3 ZA2 clock is from PLL0D3 or S0, and it can be controlled by ZA2CKCR. It is needed for R-Car Sound, but is not used so far. Using default settings is very enough at this point. This patch adds it by DEF_FIXED(). Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87pmxclrmy.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/r8a77995-cpg-mssr.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/clk/renesas/r8a77995-cpg-mssr.c b/drivers/clk/renesas/r8a77995-cpg-mssr.c index 9cfd00cf4e69..81c0bc1e78af 100644 --- a/drivers/clk/renesas/r8a77995-cpg-mssr.c +++ b/drivers/clk/renesas/r8a77995-cpg-mssr.c @@ -75,6 +75,7 @@ static const struct cpg_core_clk r8a77995_core_clks[] __initconst = { DEF_RATE(".oco", CLK_OCO, 8 * 1000 * 1000), /* Core Clock Outputs */ + DEF_FIXED("za2", R8A77995_CLK_ZA2, CLK_PLL0D3, 2, 1), DEF_FIXED("z2", R8A77995_CLK_Z2, CLK_PLL0D3, 1, 1), DEF_FIXED("ztr", R8A77995_CLK_ZTR, CLK_PLL1, 6, 1), DEF_FIXED("zt", R8A77995_CLK_ZT, CLK_PLL1, 4, 1),