From 192c344e7cd4e19a4260752604ba219ffa41deb1 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Fri, 26 Mar 2021 13:00:54 +0100 Subject: [PATCH 001/161] 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 002/161] 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 003/161] 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 004/161] 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 005/161] 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 006/161] 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 007/161] 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 008/161] 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 009/161] 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 010/161] 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 011/161] 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 012/161] 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 013/161] 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 014/161] 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 015/161] 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 23029150a05b59ebacca6dd76f6c14dc67a95877 Mon Sep 17 00:00:00 2001 From: Elaine Zhang Date: Tue, 11 May 2021 17:07:26 +0800 Subject: [PATCH 016/161] clk: rockchip: Optimize PLL table memory usage Before the change: The sizeof rk3568_pll_rates = 2544 Use union: The sizeof rk3568_pll_rates = 1696 In future Soc, more PLL types will be added, and the rockchip_pll_rate_table will add more members, and the space savings will be even more pronounced by using union. Signed-off-by: Elaine Zhang Link: https://lore.kernel.org/r/20210511090726.15146-1-zhangqing@rock-chips.com Signed-off-by: Heiko Stuebner --- drivers/clk/rockchip/clk.h | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/drivers/clk/rockchip/clk.h b/drivers/clk/rockchip/clk.h index 571cee7bbfdc..7aa45cc70287 100644 --- a/drivers/clk/rockchip/clk.h +++ b/drivers/clk/rockchip/clk.h @@ -271,17 +271,24 @@ struct rockchip_clk_provider { struct rockchip_pll_rate_table { unsigned long rate; - unsigned int nr; - unsigned int nf; - unsigned int no; - unsigned int nb; - /* for RK3036/RK3399 */ - unsigned int fbdiv; - unsigned int postdiv1; - unsigned int refdiv; - unsigned int postdiv2; - unsigned int dsmpd; - unsigned int frac; + union { + struct { + /* for RK3066 */ + unsigned int nr; + unsigned int nf; + unsigned int no; + unsigned int nb; + }; + struct { + /* for RK3036/RK3399 */ + unsigned int fbdiv; + unsigned int postdiv1; + unsigned int refdiv; + unsigned int postdiv2; + unsigned int dsmpd; + unsigned int frac; + }; + }; }; /** From 4cbf0cd6bf4c704746b6a6c6d42a8ee327070005 Mon Sep 17 00:00:00 2001 From: Martin Blumenstingl Date: Mon, 17 May 2021 22:37:24 +0200 Subject: [PATCH 017/161] clk: meson: pll: switch to determine_rate for the PLL ops This increases the maxmium supported frequency on 32-bit systems from 2^31 (signed long as used by clk_ops.round_rate, maximum value: approx. 2.14GHz) to 2^32 (unsigned long as used by clk_ops.determine_rate, maximum value: approx. 4.29GHz). On Meson8/8b/8m2 the HDMI PLL and it's OD (post-dividers) are capable of running at up to 2.97GHz. So switch the divider implementation in clk-regmap to clk_ops.determine_rate to support these higher frequencies on 32-bit systems. Signed-off-by: Martin Blumenstingl Signed-off-by: Jerome Brunet Link: https://lore.kernel.org/r/20210517203724.1006254-4-martin.blumenstingl@googlemail.com --- drivers/clk/meson/clk-pll.c | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/drivers/clk/meson/clk-pll.c b/drivers/clk/meson/clk-pll.c index 49f27fe53213..9e55617bc3b4 100644 --- a/drivers/clk/meson/clk-pll.c +++ b/drivers/clk/meson/clk-pll.c @@ -242,8 +242,8 @@ static int meson_clk_get_pll_settings(unsigned long rate, return best ? 0 : -EINVAL; } -static long meson_clk_pll_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *parent_rate) +static int meson_clk_pll_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) { struct clk_regmap *clk = to_clk_regmap(hw); struct meson_clk_pll_data *pll = meson_clk_pll_data(clk); @@ -251,22 +251,26 @@ static long meson_clk_pll_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long round; int ret; - ret = meson_clk_get_pll_settings(rate, *parent_rate, &m, &n, pll); + ret = meson_clk_get_pll_settings(req->rate, req->best_parent_rate, + &m, &n, pll); if (ret) - return meson_clk_pll_recalc_rate(hw, *parent_rate); + return ret; - round = __pll_params_to_rate(*parent_rate, m, n, 0, pll); + round = __pll_params_to_rate(req->best_parent_rate, m, n, 0, pll); - if (!MESON_PARM_APPLICABLE(&pll->frac) || rate == round) - return round; + if (!MESON_PARM_APPLICABLE(&pll->frac) || req->rate == round) { + req->rate = round; + return 0; + } /* * The rate provided by the setting is not an exact match, let's * try to improve the result using the fractional parameter */ - frac = __pll_params_with_frac(rate, *parent_rate, m, n, pll); + frac = __pll_params_with_frac(req->rate, req->best_parent_rate, m, n, pll); + req->rate = __pll_params_to_rate(req->best_parent_rate, m, n, frac, pll); - return __pll_params_to_rate(*parent_rate, m, n, frac, pll); + return 0; } static int meson_clk_pll_wait_lock(struct clk_hw *hw) @@ -419,7 +423,7 @@ static int meson_clk_pll_set_rate(struct clk_hw *hw, unsigned long rate, */ const struct clk_ops meson_clk_pcie_pll_ops = { .recalc_rate = meson_clk_pll_recalc_rate, - .round_rate = meson_clk_pll_round_rate, + .determine_rate = meson_clk_pll_determine_rate, .is_enabled = meson_clk_pll_is_enabled, .enable = meson_clk_pcie_pll_enable, .disable = meson_clk_pll_disable @@ -429,7 +433,7 @@ EXPORT_SYMBOL_GPL(meson_clk_pcie_pll_ops); const struct clk_ops meson_clk_pll_ops = { .init = meson_clk_pll_init, .recalc_rate = meson_clk_pll_recalc_rate, - .round_rate = meson_clk_pll_round_rate, + .determine_rate = meson_clk_pll_determine_rate, .set_rate = meson_clk_pll_set_rate, .is_enabled = meson_clk_pll_is_enabled, .enable = meson_clk_pll_enable, From bc794f8c56abddf709f1f84fcb2a3c9e7d9cc9b4 Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Thu, 29 Apr 2021 11:03:25 +0200 Subject: [PATCH 018/161] clk: meson: g12a: fix gp0 and hifi ranges While some SoC samples are able to lock with a PLL factor of 55, others samples can't. ATM, a minimum of 60 appears to work on all the samples I have tried. Even with 60, it sometimes takes a long time for the PLL to eventually lock. The documentation says that the minimum rate of these PLLs DCO should be 3GHz, a factor of 125. Let's use that to be on the safe side. With factor range changed, the PLL seems to lock quickly (enough) so far. It is still unclear if the range was the only reason for the delay. Fixes: 085a4ea93d54 ("clk: meson: g12a: add peripheral clock controller") Signed-off-by: Jerome Brunet Acked-by: Neil Armstrong Link: https://lore.kernel.org/r/20210429090325.60970-1-jbrunet@baylibre.com --- drivers/clk/meson/g12a.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/meson/g12a.c b/drivers/clk/meson/g12a.c index b080359b4645..a805bac93c11 100644 --- a/drivers/clk/meson/g12a.c +++ b/drivers/clk/meson/g12a.c @@ -1603,7 +1603,7 @@ static struct clk_regmap g12b_cpub_clk_trace = { }; static const struct pll_mult_range g12a_gp0_pll_mult_range = { - .min = 55, + .min = 125, .max = 255, }; From 2f3877d609e7951ef96d24979eb9d163f1f004f8 Mon Sep 17 00:00:00 2001 From: Peter Geis Date: Wed, 19 May 2021 13:41:49 -0400 Subject: [PATCH 019/161] clk: rockchip: fix rk3568 cpll clk gate bits The cpll clk gate bits had an ordering issue. This led to the loss of the boot sdmmc controller when the gmac was shut down with: `ip link set eth0 down` as the cpll_100m was shut off instead of the cpll_62p5. cpll_62p5, cpll_50m, cpll_25m were all off by one with cpll_100m misplaced. Fixes: cf911d89c4c5 ("clk: rockchip: add clock controller for rk3568") Signed-off-by: Peter Geis Reviewed-by: Elaine Zhang Link: https://lore.kernel.org/r/20210519174149.3691335-1-pgwipeout@gmail.com Signed-off-by: Heiko Stuebner --- drivers/clk/rockchip/clk-rk3568.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/clk/rockchip/clk-rk3568.c b/drivers/clk/rockchip/clk-rk3568.c index 946ea2f45bf3..75ca855e720d 100644 --- a/drivers/clk/rockchip/clk-rk3568.c +++ b/drivers/clk/rockchip/clk-rk3568.c @@ -454,17 +454,17 @@ static struct rockchip_clk_branch rk3568_clk_branches[] __initdata = { COMPOSITE_NOMUX(CPLL_125M, "cpll_125m", "cpll", CLK_IGNORE_UNUSED, RK3568_CLKSEL_CON(80), 0, 5, DFLAGS, RK3568_CLKGATE_CON(35), 10, GFLAGS), - COMPOSITE_NOMUX(CPLL_62P5M, "cpll_62p5", "cpll", CLK_IGNORE_UNUSED, - RK3568_CLKSEL_CON(80), 8, 5, DFLAGS, - RK3568_CLKGATE_CON(35), 11, GFLAGS), - COMPOSITE_NOMUX(CPLL_50M, "cpll_50m", "cpll", CLK_IGNORE_UNUSED, - RK3568_CLKSEL_CON(81), 0, 5, DFLAGS, - RK3568_CLKGATE_CON(35), 12, GFLAGS), - COMPOSITE_NOMUX(CPLL_25M, "cpll_25m", "cpll", CLK_IGNORE_UNUSED, - RK3568_CLKSEL_CON(81), 8, 6, DFLAGS, - RK3568_CLKGATE_CON(35), 13, GFLAGS), COMPOSITE_NOMUX(CPLL_100M, "cpll_100m", "cpll", CLK_IGNORE_UNUSED, RK3568_CLKSEL_CON(82), 0, 5, DFLAGS, + RK3568_CLKGATE_CON(35), 11, GFLAGS), + COMPOSITE_NOMUX(CPLL_62P5M, "cpll_62p5", "cpll", CLK_IGNORE_UNUSED, + RK3568_CLKSEL_CON(80), 8, 5, DFLAGS, + RK3568_CLKGATE_CON(35), 12, GFLAGS), + COMPOSITE_NOMUX(CPLL_50M, "cpll_50m", "cpll", CLK_IGNORE_UNUSED, + RK3568_CLKSEL_CON(81), 0, 5, DFLAGS, + RK3568_CLKGATE_CON(35), 13, GFLAGS), + COMPOSITE_NOMUX(CPLL_25M, "cpll_25m", "cpll", CLK_IGNORE_UNUSED, + RK3568_CLKSEL_CON(81), 8, 6, DFLAGS, RK3568_CLKGATE_CON(35), 14, GFLAGS), COMPOSITE_NOMUX(0, "clk_osc0_div_750k", "xin24m", CLK_IGNORE_UNUSED, RK3568_CLKSEL_CON(82), 8, 6, DFLAGS, From 50cb321f16f6665873071792d89ab8563be1658d Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Thu, 20 May 2021 09:31:36 +0200 Subject: [PATCH 020/161] clk: meson: axg-audio: improve deferral handling Use dev_err_probe() for clock and reset resources to indicate the deferral reason through sysfs when waiting for the resource to come up. Signed-off-by: Jerome Brunet Reviewed-by: Martin Blumenstingl Link: https://lore.kernel.org/r/20210520073136.272925-1-jbrunet@baylibre.com --- drivers/clk/meson/axg-audio.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/clk/meson/axg-audio.c b/drivers/clk/meson/axg-audio.c index 7c8d02164443..bfe36bd41339 100644 --- a/drivers/clk/meson/axg-audio.c +++ b/drivers/clk/meson/axg-audio.c @@ -1665,8 +1665,7 @@ static int devm_clk_get_enable(struct device *dev, char *id) clk = devm_clk_get(dev, id); if (IS_ERR(clk)) { ret = PTR_ERR(clk); - if (ret != -EPROBE_DEFER) - dev_err(dev, "failed to get %s", id); + dev_err_probe(dev, ret, "failed to get %s", id); return ret; } @@ -1811,7 +1810,7 @@ static int axg_audio_clkc_probe(struct platform_device *pdev) ret = device_reset(dev); if (ret) { - dev_err(dev, "failed to reset device\n"); + dev_err_probe(dev, ret, "failed to reset device\n"); return ret; } From 47e4dc4e63e1dcb8eec01c4214bcefc248eb72ed Mon Sep 17 00:00:00 2001 From: Tobias Schramm Date: Thu, 13 May 2021 15:13:15 +0200 Subject: [PATCH 021/161] clk: sunxi-ng: v3s: fix incorrect postdivider on pll-audio Commit 46060be6d840 ("clk: sunxi-ng: v3s: use sigma-delta modulation for audio-pll") changed the audio pll on the Allwinner V3s and V3 SoCs to use sigma-delta modulation. In the process the declaration of fixed postdivider providing "pll-audio" was adjusted to provide the desired clock rates from the now sigma-delta modulated pll. However, while the divider used for calculations by the clock framework was adjusted the actual divider programmed into the hardware in sun8i_v3_v3s_ccu_init was left at "divide by four". This broke the "pll-audio" clock, now only providing quater the expected clock rate. It would in general be desirable to program the postdivider for "pll-audio" to four, such that a broader range of frequencies were available on the pll outputs. But the clock for the integrated codec "ac-dig" does not feature a mux that allows to select from all pll outputs as it is just a simple clock gate connected to "pll-audio". Thus we need to set the postdivider to one to be able to provide the 22.5792MHz and 24.576MHz rates required by the internal sun4i codec. This patches fixes the incorrect clock rate by forcing the postdivider to one in sun8i_v3_v3s_ccu_init. Fixes: 46060be6d840 ("clk: sunxi-ng: v3s: use sigma-delta modulation for audio-pll") Signed-off-by: Tobias Schramm Signed-off-by: Maxime Ripard Link: https://lore.kernel.org/r/20210513131315.2059451-1-t.schramm@manjaro.org --- drivers/clk/sunxi-ng/ccu-sun8i-v3s.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-v3s.c b/drivers/clk/sunxi-ng/ccu-sun8i-v3s.c index a774942cb153..f49724a22540 100644 --- a/drivers/clk/sunxi-ng/ccu-sun8i-v3s.c +++ b/drivers/clk/sunxi-ng/ccu-sun8i-v3s.c @@ -817,10 +817,10 @@ static void __init sun8i_v3_v3s_ccu_init(struct device_node *node, return; } - /* Force the PLL-Audio-1x divider to 4 */ + /* Force the PLL-Audio-1x divider to 1 */ val = readl(reg + SUN8I_V3S_PLL_AUDIO_REG); val &= ~GENMASK(19, 16); - writel(val | (3 << 16), reg + SUN8I_V3S_PLL_AUDIO_REG); + writel(val, reg + SUN8I_V3S_PLL_AUDIO_REG); sunxi_ccu_probe(node, reg, ccu_desc); } From 7f891faf596ede96dd209b2257abf9df636b481f Mon Sep 17 00:00:00 2001 From: Taniya Das Date: Sun, 25 Apr 2021 12:38:22 +0530 Subject: [PATCH 022/161] clk: qcom: clk-rcg2: Add support for duty-cycle for RCG The root clock generators with MND divider has the capability to support change in duty-cycle by updating the 'D'. Add the clock ops which would check all the boundary conditions and enable setting the desired duty-cycle as per the consumer. Signed-off-by: Taniya Das Link: https://lore.kernel.org/r/1619334502-9880-2-git-send-email-tdas@codeaurora.org [sboyd@kernel.org: Remove _val everywhere] Signed-off-by: Stephen Boyd --- drivers/clk/qcom/clk-rcg2.c | 81 +++++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) diff --git a/drivers/clk/qcom/clk-rcg2.c b/drivers/clk/qcom/clk-rcg2.c index 05ff3b0d233e..e1b1b426fae4 100644 --- a/drivers/clk/qcom/clk-rcg2.c +++ b/drivers/clk/qcom/clk-rcg2.c @@ -357,6 +357,83 @@ static int clk_rcg2_set_floor_rate_and_parent(struct clk_hw *hw, return __clk_rcg2_set_rate(hw, rate, FLOOR); } +static int clk_rcg2_get_duty_cycle(struct clk_hw *hw, struct clk_duty *duty) +{ + struct clk_rcg2 *rcg = to_clk_rcg2(hw); + u32 notn_m, n, m, d, not2d, mask; + + if (!rcg->mnd_width) { + /* 50 % duty-cycle for Non-MND RCGs */ + duty->num = 1; + duty->den = 2; + return 0; + } + + regmap_read(rcg->clkr.regmap, RCG_D_OFFSET(rcg), ¬2d); + regmap_read(rcg->clkr.regmap, RCG_M_OFFSET(rcg), &m); + regmap_read(rcg->clkr.regmap, RCG_N_OFFSET(rcg), ¬n_m); + + if (!not2d && !m && !notn_m) { + /* 50 % duty-cycle always */ + duty->num = 1; + duty->den = 2; + return 0; + } + + mask = BIT(rcg->mnd_width) - 1; + + d = ~(not2d) & mask; + d = DIV_ROUND_CLOSEST(d, 2); + + n = (~(notn_m) + m) & mask; + + duty->num = d; + duty->den = n; + + return 0; +} + +static int clk_rcg2_set_duty_cycle(struct clk_hw *hw, struct clk_duty *duty) +{ + struct clk_rcg2 *rcg = to_clk_rcg2(hw); + u32 notn_m, n, m, d, not2d, mask, duty_per; + int ret; + + /* Duty-cycle cannot be modified for non-MND RCGs */ + if (!rcg->mnd_width) + return -EINVAL; + + mask = BIT(rcg->mnd_width) - 1; + + regmap_read(rcg->clkr.regmap, RCG_N_OFFSET(rcg), ¬n_m); + regmap_read(rcg->clkr.regmap, RCG_M_OFFSET(rcg), &m); + + n = (~(notn_m) + m) & mask; + + duty_per = (duty->num * 100) / duty->den; + + /* Calculate 2d value */ + d = DIV_ROUND_CLOSEST(n * duty_per * 2, 100); + + /* Check bit widths of 2d. If D is too big reduce duty cycle. */ + if (d > mask) + d = mask; + + if ((d / 2) > (n - m)) + d = (n - m) * 2; + else if ((d / 2) < (m / 2)) + d = m; + + not2d = ~d & mask; + + ret = regmap_update_bits(rcg->clkr.regmap, RCG_D_OFFSET(rcg), mask, + not2d); + if (ret) + return ret; + + return update_config(rcg); +} + const struct clk_ops clk_rcg2_ops = { .is_enabled = clk_rcg2_is_enabled, .get_parent = clk_rcg2_get_parent, @@ -365,6 +442,8 @@ const struct clk_ops clk_rcg2_ops = { .determine_rate = clk_rcg2_determine_rate, .set_rate = clk_rcg2_set_rate, .set_rate_and_parent = clk_rcg2_set_rate_and_parent, + .get_duty_cycle = clk_rcg2_get_duty_cycle, + .set_duty_cycle = clk_rcg2_set_duty_cycle, }; EXPORT_SYMBOL_GPL(clk_rcg2_ops); @@ -376,6 +455,8 @@ const struct clk_ops clk_rcg2_floor_ops = { .determine_rate = clk_rcg2_determine_floor_rate, .set_rate = clk_rcg2_set_floor_rate, .set_rate_and_parent = clk_rcg2_set_floor_rate_and_parent, + .get_duty_cycle = clk_rcg2_get_duty_cycle, + .set_duty_cycle = clk_rcg2_set_duty_cycle, }; EXPORT_SYMBOL_GPL(clk_rcg2_floor_ops); From 682b108ba598e36d8232c9df14d41b3e9993784f Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 4 May 2021 11:17:21 +0200 Subject: [PATCH 023/161] 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 024/161] 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 025/161] 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), From 2adafc0512625bbd090dc37a353ddda15d525e9d Mon Sep 17 00:00:00 2001 From: Alex Bee Date: Fri, 28 May 2021 16:07:36 +0200 Subject: [PATCH 026/161] clk: rockchip: export ACLK_VCODEC for RK3036 It is required for the series at [1] to let hantro driver aquire the clock and set the rate for RK3036 correctly, but I didn't want to add a patch for yet another subsystem to this series. [1] https://lore.kernel.org/linux-media/20210525152225.154302-1-knaerzche@gmail.com/ Signed-off-by: Alex Bee Link: https://lore.kernel.org/r/20210528140736.79686-1-knaerzche@gmail.com Signed-off-by: Heiko Stuebner --- drivers/clk/rockchip/clk-rk3036.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/rockchip/clk-rk3036.c b/drivers/clk/rockchip/clk-rk3036.c index 91d56ad45817..614845cc5b4a 100644 --- a/drivers/clk/rockchip/clk-rk3036.c +++ b/drivers/clk/rockchip/clk-rk3036.c @@ -259,7 +259,7 @@ static struct rockchip_clk_branch rk3036_clk_branches[] __initdata = { RK2928_CLKGATE_CON(1), 13, GFLAGS, &rk3036_uart2_fracmux), - COMPOSITE(0, "aclk_vcodec", mux_pll_src_3plls_p, 0, + COMPOSITE(ACLK_VCODEC, "aclk_vcodec", mux_pll_src_3plls_p, 0, RK2928_CLKSEL_CON(32), 14, 2, MFLAGS, 8, 5, DFLAGS, RK2928_CLKGATE_CON(3), 11, GFLAGS), FACTOR_GATE(HCLK_VCODEC, "hclk_vcodec", "aclk_vcodec", 0, 1, 4, From 56bb7c28ad00e7bcfc851c4e183c42d148d3ad4e Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Sun, 16 May 2021 19:30:33 +0300 Subject: [PATCH 027/161] clk: tegra30: Use 300MHz for video decoder by default The 600MHz is a too high clock rate for some SoC versions for the video decoder hardware and this may cause stability issues. Use 300MHz for the video decoder by default, which is supported by all hardware versions. Fixes: ed1a2459e20c ("clk: tegra: Add Tegra20/30 EMC clock implementation") Acked-by: Thierry Reding Signed-off-by: Dmitry Osipenko Signed-off-by: Thierry Reding --- drivers/clk/tegra/clk-tegra30.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/tegra/clk-tegra30.c b/drivers/clk/tegra/clk-tegra30.c index 16dbf83d2f62..a33688b2359e 100644 --- a/drivers/clk/tegra/clk-tegra30.c +++ b/drivers/clk/tegra/clk-tegra30.c @@ -1245,7 +1245,7 @@ static struct tegra_clk_init_table init_table[] __initdata = { { TEGRA30_CLK_GR3D, TEGRA30_CLK_PLL_C, 300000000, 0 }, { TEGRA30_CLK_GR3D2, TEGRA30_CLK_PLL_C, 300000000, 0 }, { TEGRA30_CLK_PLL_U, TEGRA30_CLK_CLK_MAX, 480000000, 0 }, - { TEGRA30_CLK_VDE, TEGRA30_CLK_PLL_C, 600000000, 0 }, + { TEGRA30_CLK_VDE, TEGRA30_CLK_PLL_C, 300000000, 0 }, { TEGRA30_CLK_SPDIF_IN_SYNC, TEGRA30_CLK_CLK_MAX, 24000000, 0 }, { TEGRA30_CLK_I2S0_SYNC, TEGRA30_CLK_CLK_MAX, 24000000, 0 }, { TEGRA30_CLK_I2S1_SYNC, TEGRA30_CLK_CLK_MAX, 24000000, 0 }, From c592c8a28f5821e880ac6675781cd8a151b0737c Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Sun, 16 May 2021 19:30:34 +0300 Subject: [PATCH 028/161] clk: tegra: Fix refcounting of gate clocks The refcounting of the gate clocks has a bug causing the enable_refcnt to underflow when unused clocks are disabled. This happens because clk provider erroneously bumps the refcount if clock is enabled at a boot time, which it shouldn't be doing, and it does this only for the gate clocks, while peripheral clocks are using the same gate ops and the peripheral clocks are missing the initial bump. Hence the refcount of the peripheral clocks is 0 when unused clocks are disabled and then the counter is decremented further by the gate ops, causing the integer underflow. Fix this problem by removing the erroneous bump and by implementing the disable_unused() callback, which disables the unused gates properly. The visible effect of the bug is such that the unused clocks are never gated if a loaded kernel module grabs the unused clocks and starts to use them. In practice this shouldn't cause any real problems for the drivers and boards supported by the kernel today. Acked-by: Thierry Reding Signed-off-by: Dmitry Osipenko Signed-off-by: Thierry Reding --- drivers/clk/tegra/clk-periph-gate.c | 72 +++++++++++++++++++---------- drivers/clk/tegra/clk-periph.c | 11 +++++ 2 files changed, 58 insertions(+), 25 deletions(-) diff --git a/drivers/clk/tegra/clk-periph-gate.c b/drivers/clk/tegra/clk-periph-gate.c index 4b31beefc9fc..dc3f92678407 100644 --- a/drivers/clk/tegra/clk-periph-gate.c +++ b/drivers/clk/tegra/clk-periph-gate.c @@ -48,18 +48,9 @@ static int clk_periph_is_enabled(struct clk_hw *hw) return state; } -static int clk_periph_enable(struct clk_hw *hw) +static void clk_periph_enable_locked(struct clk_hw *hw) { struct tegra_clk_periph_gate *gate = to_clk_periph_gate(hw); - unsigned long flags = 0; - - spin_lock_irqsave(&periph_ref_lock, flags); - - gate->enable_refcnt[gate->clk_num]++; - if (gate->enable_refcnt[gate->clk_num] > 1) { - spin_unlock_irqrestore(&periph_ref_lock, flags); - return 0; - } write_enb_set(periph_clk_to_bit(gate), gate); udelay(2); @@ -78,6 +69,32 @@ static int clk_periph_enable(struct clk_hw *hw) udelay(1); writel_relaxed(0, gate->clk_base + LVL2_CLK_GATE_OVRE); } +} + +static void clk_periph_disable_locked(struct clk_hw *hw) +{ + struct tegra_clk_periph_gate *gate = to_clk_periph_gate(hw); + + /* + * If peripheral is in the APB bus then read the APB bus to + * flush the write operation in apb bus. This will avoid the + * peripheral access after disabling clock + */ + if (gate->flags & TEGRA_PERIPH_ON_APB) + tegra_read_chipid(); + + write_enb_clr(periph_clk_to_bit(gate), gate); +} + +static int clk_periph_enable(struct clk_hw *hw) +{ + struct tegra_clk_periph_gate *gate = to_clk_periph_gate(hw); + unsigned long flags = 0; + + spin_lock_irqsave(&periph_ref_lock, flags); + + if (!gate->enable_refcnt[gate->clk_num]++) + clk_periph_enable_locked(hw); spin_unlock_irqrestore(&periph_ref_lock, flags); @@ -91,21 +108,28 @@ static void clk_periph_disable(struct clk_hw *hw) spin_lock_irqsave(&periph_ref_lock, flags); - gate->enable_refcnt[gate->clk_num]--; - if (gate->enable_refcnt[gate->clk_num] > 0) { - spin_unlock_irqrestore(&periph_ref_lock, flags); - return; - } + WARN_ON(!gate->enable_refcnt[gate->clk_num]); + + if (--gate->enable_refcnt[gate->clk_num] == 0) + clk_periph_disable_locked(hw); + + spin_unlock_irqrestore(&periph_ref_lock, flags); +} + +static void clk_periph_disable_unused(struct clk_hw *hw) +{ + struct tegra_clk_periph_gate *gate = to_clk_periph_gate(hw); + unsigned long flags = 0; + + spin_lock_irqsave(&periph_ref_lock, flags); /* - * If peripheral is in the APB bus then read the APB bus to - * flush the write operation in apb bus. This will avoid the - * peripheral access after disabling clock + * Some clocks are duplicated and some of them are marked as critical, + * like fuse and fuse_burn for example, thus the enable_refcnt will + * be non-zero here if the "unused" duplicate is disabled by CCF. */ - if (gate->flags & TEGRA_PERIPH_ON_APB) - tegra_read_chipid(); - - write_enb_clr(periph_clk_to_bit(gate), gate); + if (!gate->enable_refcnt[gate->clk_num]) + clk_periph_disable_locked(hw); spin_unlock_irqrestore(&periph_ref_lock, flags); } @@ -114,6 +138,7 @@ const struct clk_ops tegra_clk_periph_gate_ops = { .is_enabled = clk_periph_is_enabled, .enable = clk_periph_enable, .disable = clk_periph_disable, + .disable_unused = clk_periph_disable_unused, }; struct clk *tegra_clk_register_periph_gate(const char *name, @@ -148,9 +173,6 @@ struct clk *tegra_clk_register_periph_gate(const char *name, gate->enable_refcnt = enable_refcnt; gate->regs = pregs; - if (read_enb(gate) & periph_clk_to_bit(gate)) - enable_refcnt[clk_num]++; - /* Data in .init is copied by clk_register(), so stack variable OK */ gate->hw.init = &init; diff --git a/drivers/clk/tegra/clk-periph.c b/drivers/clk/tegra/clk-periph.c index 67620c7ecd9e..79ca3aa072b7 100644 --- a/drivers/clk/tegra/clk-periph.c +++ b/drivers/clk/tegra/clk-periph.c @@ -100,6 +100,15 @@ static void clk_periph_disable(struct clk_hw *hw) gate_ops->disable(gate_hw); } +static void clk_periph_disable_unused(struct clk_hw *hw) +{ + struct tegra_clk_periph *periph = to_clk_periph(hw); + const struct clk_ops *gate_ops = periph->gate_ops; + struct clk_hw *gate_hw = &periph->gate.hw; + + gate_ops->disable_unused(gate_hw); +} + static void clk_periph_restore_context(struct clk_hw *hw) { struct tegra_clk_periph *periph = to_clk_periph(hw); @@ -126,6 +135,7 @@ const struct clk_ops tegra_clk_periph_ops = { .is_enabled = clk_periph_is_enabled, .enable = clk_periph_enable, .disable = clk_periph_disable, + .disable_unused = clk_periph_disable_unused, .restore_context = clk_periph_restore_context, }; @@ -135,6 +145,7 @@ static const struct clk_ops tegra_clk_periph_nodiv_ops = { .is_enabled = clk_periph_is_enabled, .enable = clk_periph_enable, .disable = clk_periph_disable, + .disable_unused = clk_periph_disable_unused, .restore_context = clk_periph_restore_context, }; From a7196048cd5168096c2c4f44a3939d7a6dcd06b9 Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Sun, 16 May 2021 19:30:35 +0300 Subject: [PATCH 029/161] clk: tegra: Ensure that PLLU configuration is applied properly The PLLU (USB) consists of the PLL configuration itself and configuration of the PLLU outputs. The PLLU programming is inconsistent on T30 vs T114, where T114 immediately bails out if PLLU is enabled and T30 re-enables a potentially already enabled PLL (left after bootloader) and then fully reprograms it, which could be unsafe to do. The correct way should be to skip enabling of the PLL if it's already enabled and then apply configuration to the outputs. This patch doesn't fix any known problems, it's a minor improvement. Acked-by: Thierry Reding Signed-off-by: Dmitry Osipenko Signed-off-by: Thierry Reding --- drivers/clk/tegra/clk-pll.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/drivers/clk/tegra/clk-pll.c b/drivers/clk/tegra/clk-pll.c index 0193cebe8c5a..823a567f2adc 100644 --- a/drivers/clk/tegra/clk-pll.c +++ b/drivers/clk/tegra/clk-pll.c @@ -1131,7 +1131,8 @@ static int clk_pllu_enable(struct clk_hw *hw) if (pll->lock) spin_lock_irqsave(pll->lock, flags); - _clk_pll_enable(hw); + if (!clk_pll_is_enabled(hw)) + _clk_pll_enable(hw); ret = clk_pll_wait_for_lock(pll); if (ret < 0) @@ -1748,15 +1749,13 @@ static int clk_pllu_tegra114_enable(struct clk_hw *hw) return -EINVAL; } - if (clk_pll_is_enabled(hw)) - return 0; - input_rate = clk_hw_get_rate(__clk_get_hw(osc)); if (pll->lock) spin_lock_irqsave(pll->lock, flags); - _clk_pll_enable(hw); + if (!clk_pll_is_enabled(hw)) + _clk_pll_enable(hw); ret = clk_pll_wait_for_lock(pll); if (ret < 0) From 18a6a7150a894383e89152a820bd71d664628abd Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Sun, 16 May 2021 19:30:36 +0300 Subject: [PATCH 030/161] clk: tegra: Halve SCLK rate on Tegra20 Higher SCLK rates on Tegra20 require high core voltage. The higher clock rate may have a positive performance effect only for AHB DMA transfers and AVP CPU, but both aren't used by upstream kernel at all. Halve SCLK rate on Tegra20 in order to remove the high core voltage requirement. Acked-by: Thierry Reding Signed-off-by: Dmitry Osipenko Signed-off-by: Thierry Reding --- drivers/clk/tegra/clk-tegra20.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/clk/tegra/clk-tegra20.c b/drivers/clk/tegra/clk-tegra20.c index 3efc651b42e3..3664593a5ba4 100644 --- a/drivers/clk/tegra/clk-tegra20.c +++ b/drivers/clk/tegra/clk-tegra20.c @@ -1021,9 +1021,9 @@ static struct tegra_clk_init_table init_table[] __initdata = { { TEGRA20_CLK_PLL_P_OUT3, TEGRA20_CLK_CLK_MAX, 72000000, 1 }, { TEGRA20_CLK_PLL_P_OUT4, TEGRA20_CLK_CLK_MAX, 24000000, 1 }, { TEGRA20_CLK_PLL_C, TEGRA20_CLK_CLK_MAX, 600000000, 0 }, - { TEGRA20_CLK_PLL_C_OUT1, TEGRA20_CLK_CLK_MAX, 240000000, 0 }, - { TEGRA20_CLK_SCLK, TEGRA20_CLK_PLL_C_OUT1, 240000000, 0 }, - { TEGRA20_CLK_HCLK, TEGRA20_CLK_CLK_MAX, 240000000, 0 }, + { TEGRA20_CLK_PLL_C_OUT1, TEGRA20_CLK_CLK_MAX, 120000000, 0 }, + { TEGRA20_CLK_SCLK, TEGRA20_CLK_PLL_C_OUT1, 120000000, 0 }, + { TEGRA20_CLK_HCLK, TEGRA20_CLK_CLK_MAX, 120000000, 0 }, { TEGRA20_CLK_PCLK, TEGRA20_CLK_CLK_MAX, 60000000, 0 }, { TEGRA20_CLK_CSITE, TEGRA20_CLK_CLK_MAX, 0, 1 }, { TEGRA20_CLK_CCLK, TEGRA20_CLK_CLK_MAX, 0, 1 }, From 78086386b3d1e363e2152066f48efcbdbb158d0f Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Sun, 16 May 2021 19:30:37 +0300 Subject: [PATCH 031/161] clk: tegra: Don't allow zero clock rate for PLLs Zero clock rate doesn't make sense for PLLs and tegra-clk driver enters into infinite loop on trying to calculate PLL parameters for zero rate. Make code to error out if requested rate is zero. Originally this trouble was found by Robert Yang while he was trying to bring up upstream kernel on Samsung Galaxy Tab, which happened due to a bug in Tegra DRM driver that erroneously sets PLL rate to zero. This issues came over again recently during of kernel bring up on ASUS TF700T. Signed-off-by: Dmitry Osipenko Signed-off-by: Thierry Reding --- drivers/clk/tegra/clk-pll.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/clk/tegra/clk-pll.c b/drivers/clk/tegra/clk-pll.c index 823a567f2adc..eaa079c177c3 100644 --- a/drivers/clk/tegra/clk-pll.c +++ b/drivers/clk/tegra/clk-pll.c @@ -558,6 +558,9 @@ static int _calc_rate(struct clk_hw *hw, struct tegra_clk_pll_freq_table *cfg, u32 p_div = 0; int ret; + if (!rate) + return -EINVAL; + switch (parent_rate) { case 12000000: case 26000000: From 344d5df34f5abd468267daa98f041abf90b2f660 Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Sun, 16 May 2021 19:30:38 +0300 Subject: [PATCH 032/161] clk: tegra: cclk: Handle thermal DIV2 CPU frequency throttling Check whether thermal DIV2 throttle is active in order to report the CPU frequency properly. This very useful for userspace tools like cpufreq-info which show actual frequency asserted from hardware. Signed-off-by: Dmitry Osipenko Signed-off-by: Thierry Reding --- drivers/clk/tegra/clk-tegra-super-cclk.c | 18 +++++++++++++++--- drivers/clk/tegra/clk-tegra30.c | 2 +- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/drivers/clk/tegra/clk-tegra-super-cclk.c b/drivers/clk/tegra/clk-tegra-super-cclk.c index a03119c30456..68d7bcd5fc8a 100644 --- a/drivers/clk/tegra/clk-tegra-super-cclk.c +++ b/drivers/clk/tegra/clk-tegra-super-cclk.c @@ -25,6 +25,8 @@ #define SUPER_CDIV_ENB BIT(31) +#define TSENSOR_SLOWDOWN BIT(23) + static struct tegra_clk_super_mux *cclk_super; static bool cclk_on_pllx; @@ -47,10 +49,20 @@ static int cclk_super_set_rate(struct clk_hw *hw, unsigned long rate, static unsigned long cclk_super_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { - if (cclk_super_get_parent(hw) == PLLX_INDEX) - return parent_rate; + struct tegra_clk_super_mux *super = to_clk_super_mux(hw); + u32 val = readl_relaxed(super->reg); + unsigned int div2; - return tegra_clk_super_ops.recalc_rate(hw, parent_rate); + /* check whether thermal throttling is active */ + if (val & TSENSOR_SLOWDOWN) + div2 = 1; + else + div2 = 0; + + if (cclk_super_get_parent(hw) == PLLX_INDEX) + return parent_rate >> div2; + + return tegra_clk_super_ops.recalc_rate(hw, parent_rate) >> div2; } static int cclk_super_determine_rate(struct clk_hw *hw, diff --git a/drivers/clk/tegra/clk-tegra30.c b/drivers/clk/tegra/clk-tegra30.c index a33688b2359e..5b6bd138be84 100644 --- a/drivers/clk/tegra/clk-tegra30.c +++ b/drivers/clk/tegra/clk-tegra30.c @@ -930,7 +930,7 @@ static void __init tegra30_super_clk_init(void) /* CCLKG */ clk = tegra_clk_register_super_cclk("cclk_g", cclk_g_parents, ARRAY_SIZE(cclk_g_parents), - CLK_SET_RATE_PARENT, + CLK_SET_RATE_PARENT | CLK_GET_RATE_NOCACHE, clk_base + CCLKG_BURST_POLICY, 0, NULL); clks[TEGRA30_CLK_CCLK_G] = clk; From 5d0f1c8ab10aee9934a418ddd7ec977b01ab2370 Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Sun, 16 May 2021 19:30:39 +0300 Subject: [PATCH 033/161] clk: tegra: Mark external clocks as not having reset control The external clocks don't have reset bits as they don't belong to any specific hardware unit. Mark them as not having reset control for consistency. Signed-off-by: Dmitry Osipenko Signed-off-by: Thierry Reding --- drivers/clk/tegra/clk-tegra-periph.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/clk/tegra/clk-tegra-periph.c b/drivers/clk/tegra/clk-tegra-periph.c index 60cc34f90cb9..292d6269daf1 100644 --- a/drivers/clk/tegra/clk-tegra-periph.c +++ b/drivers/clk/tegra/clk-tegra-periph.c @@ -712,9 +712,9 @@ static struct tegra_periph_init_data periph_clks[] = { MUX8("ndflash", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_NDFLASH, 13, TEGRA_PERIPH_ON_APB, tegra_clk_ndflash_8), MUX8("ndspeed", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_NDSPEED, 80, TEGRA_PERIPH_ON_APB, tegra_clk_ndspeed_8), MUX8("hdmi", mux_pllp_pllm_plld_plla_pllc_plld2_clkm, CLK_SOURCE_HDMI, 51, 0, tegra_clk_hdmi), - MUX8("extern1", mux_plla_clk32_pllp_clkm_plle, CLK_SOURCE_EXTERN1, 120, 0, tegra_clk_extern1), - MUX8("extern2", mux_plla_clk32_pllp_clkm_plle, CLK_SOURCE_EXTERN2, 121, 0, tegra_clk_extern2), - MUX8("extern3", mux_plla_clk32_pllp_clkm_plle, CLK_SOURCE_EXTERN3, 122, 0, tegra_clk_extern3), + MUX8("extern1", mux_plla_clk32_pllp_clkm_plle, CLK_SOURCE_EXTERN1, 120, TEGRA_PERIPH_NO_RESET, tegra_clk_extern1), + MUX8("extern2", mux_plla_clk32_pllp_clkm_plle, CLK_SOURCE_EXTERN2, 121, TEGRA_PERIPH_NO_RESET, tegra_clk_extern2), + MUX8("extern3", mux_plla_clk32_pllp_clkm_plle, CLK_SOURCE_EXTERN3, 122, TEGRA_PERIPH_NO_RESET, tegra_clk_extern3), MUX8("soc_therm", mux_pllm_pllc_pllp_plla, CLK_SOURCE_SOC_THERM, 78, TEGRA_PERIPH_ON_APB, tegra_clk_soc_therm), MUX8("soc_therm", mux_clkm_pllc_pllp_plla, CLK_SOURCE_SOC_THERM, 78, TEGRA_PERIPH_ON_APB, tegra_clk_soc_therm_8), MUX8("vi_sensor", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_VI_SENSOR, 164, TEGRA_PERIPH_NO_RESET, tegra_clk_vi_sensor_8), From 4782c0a5dd88e3797426e08c5c437e95a3156631 Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Sun, 16 May 2021 19:30:40 +0300 Subject: [PATCH 034/161] clk: tegra: Don't deassert reset on enabling clocks The Tegra clock driver contains legacy code which deasserts hardware reset when peripheral clocks are enabled. This behaviour comes from a pre-CCF era of the Tegra drivers. This is unacceptable for modern kernel drivers which use generic CCF and reset-control APIs because it breaks assumptions of the drivers about clk/reset sequences and about reset-propagation delays. Hence remove the awkward legacy behaviour from the clk driver. In particular PMC driver assumes that hardware blocks remains in reset while power domain is turning on, but the clk driver deasserts the reset before power clamp is removed, hence breaking the driver's assumption. Signed-off-by: Dmitry Osipenko Signed-off-by: Thierry Reding --- drivers/clk/tegra/clk-periph-gate.c | 8 -------- drivers/clk/tegra/clk-tegra30.c | 2 +- drivers/clk/tegra/clk.h | 4 ---- 3 files changed, 1 insertion(+), 13 deletions(-) diff --git a/drivers/clk/tegra/clk-periph-gate.c b/drivers/clk/tegra/clk-periph-gate.c index dc3f92678407..2091fc9b0ca9 100644 --- a/drivers/clk/tegra/clk-periph-gate.c +++ b/drivers/clk/tegra/clk-periph-gate.c @@ -55,14 +55,6 @@ static void clk_periph_enable_locked(struct clk_hw *hw) write_enb_set(periph_clk_to_bit(gate), gate); udelay(2); - if (!(gate->flags & TEGRA_PERIPH_NO_RESET) && - !(gate->flags & TEGRA_PERIPH_MANUAL_RESET)) { - if (read_rst(gate) & periph_clk_to_bit(gate)) { - udelay(5); /* reset propogation delay */ - write_rst_clr(periph_clk_to_bit(gate), gate); - } - } - if (gate->flags & TEGRA_PERIPH_WAR_1005168) { writel_relaxed(0, gate->clk_base + LVL2_CLK_GATE_OVRE); writel_relaxed(BIT(22), gate->clk_base + LVL2_CLK_GATE_OVRE); diff --git a/drivers/clk/tegra/clk-tegra30.c b/drivers/clk/tegra/clk-tegra30.c index 5b6bd138be84..64121bc66d85 100644 --- a/drivers/clk/tegra/clk-tegra30.c +++ b/drivers/clk/tegra/clk-tegra30.c @@ -1006,7 +1006,7 @@ static struct tegra_periph_init_data tegra_periph_clk_list[] = { TEGRA_INIT_DATA_MUX("dam0", mux_pllacp_clkm, CLK_SOURCE_DAM0, 108, 0, TEGRA30_CLK_DAM0), TEGRA_INIT_DATA_MUX("dam1", mux_pllacp_clkm, CLK_SOURCE_DAM1, 109, 0, TEGRA30_CLK_DAM1), TEGRA_INIT_DATA_MUX("dam2", mux_pllacp_clkm, CLK_SOURCE_DAM2, 110, 0, TEGRA30_CLK_DAM2), - TEGRA_INIT_DATA_INT("3d2", mux_pllmcpa, CLK_SOURCE_3D2, 98, TEGRA_PERIPH_MANUAL_RESET, TEGRA30_CLK_GR3D2), + TEGRA_INIT_DATA_INT("3d2", mux_pllmcpa, CLK_SOURCE_3D2, 98, 0, TEGRA30_CLK_GR3D2), TEGRA_INIT_DATA_INT("se", mux_pllpcm_clkm, CLK_SOURCE_SE, 127, 0, TEGRA30_CLK_SE), TEGRA_INIT_DATA_MUX8("hdmi", mux_pllpmdacd2_clkm, CLK_SOURCE_HDMI, 51, 0, TEGRA30_CLK_HDMI), TEGRA_INIT_DATA("pwm", NULL, NULL, pwm_parents, CLK_SOURCE_PWM, 28, 2, 0, 0, 8, 1, 0, 17, TEGRA_PERIPH_ON_APB, TEGRA30_CLK_PWM), diff --git a/drivers/clk/tegra/clk.h b/drivers/clk/tegra/clk.h index c3e36b5dcc75..0c3ba0ccce1a 100644 --- a/drivers/clk/tegra/clk.h +++ b/drivers/clk/tegra/clk.h @@ -553,9 +553,6 @@ struct tegra_clk_periph_regs { * Flags: * TEGRA_PERIPH_NO_RESET - This flag indicates that reset is not allowed * for this module. - * TEGRA_PERIPH_MANUAL_RESET - This flag indicates not to reset module - * after clock enable and driver for the module is responsible for - * doing reset. * TEGRA_PERIPH_ON_APB - If peripheral is in the APB bus then read the * bus to flush the write operation in apb bus. This flag indicates * that this peripheral is in apb bus. @@ -577,7 +574,6 @@ struct tegra_clk_periph_gate { #define TEGRA_CLK_PERIPH_GATE_MAGIC 0x17760309 #define TEGRA_PERIPH_NO_RESET BIT(0) -#define TEGRA_PERIPH_MANUAL_RESET BIT(1) #define TEGRA_PERIPH_ON_APB BIT(2) #define TEGRA_PERIPH_WAR_1005168 BIT(3) #define TEGRA_PERIPH_NO_DIV BIT(4) From e848edae31263d2119e7cde779d754439277fbba Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Tue, 1 Jun 2021 05:31:11 +0300 Subject: [PATCH 035/161] clk: tegra: Add stubs needed for compile-testing Add stubs needed for compile-testing of Tegra memory drivers. Signed-off-by: Dmitry Osipenko Signed-off-by: Thierry Reding --- drivers/soc/tegra/pmc.c | 5 -- include/linux/clk/tegra.h | 100 ++++++++++++++++++++++++++++++-------- 2 files changed, 79 insertions(+), 26 deletions(-) diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c index 8e3b78bb2ac2..4a582eae82ef 100644 --- a/drivers/soc/tegra/pmc.c +++ b/drivers/soc/tegra/pmc.c @@ -743,11 +743,6 @@ out: return err; } -int __weak tegra210_clk_handle_mbist_war(unsigned int id) -{ - return 0; -} - static int tegra_powergate_power_up(struct tegra_powergate *pg, bool disable_clocks) { diff --git a/include/linux/clk/tegra.h b/include/linux/clk/tegra.h index f7ff722a03dd..d128ad1570aa 100644 --- a/include/linux/clk/tegra.h +++ b/include/linux/clk/tegra.h @@ -123,20 +123,6 @@ static inline void tegra_cpu_clock_resume(void) } #endif -extern int tegra210_plle_hw_sequence_start(void); -extern bool tegra210_plle_hw_sequence_is_enabled(void); -extern void tegra210_xusb_pll_hw_control_enable(void); -extern void tegra210_xusb_pll_hw_sequence_start(void); -extern void tegra210_sata_pll_hw_control_enable(void); -extern void tegra210_sata_pll_hw_sequence_start(void); -extern void tegra210_set_sata_pll_seq_sw(bool state); -extern void tegra210_put_utmipll_in_iddq(void); -extern void tegra210_put_utmipll_out_iddq(void); -extern int tegra210_clk_handle_mbist_war(unsigned int id); -extern void tegra210_clk_emc_dll_enable(bool flag); -extern void tegra210_clk_emc_dll_update_setting(u32 emc_dll_src_value); -extern void tegra210_clk_emc_update_setting(u32 emc_src_value); - struct clk; struct tegra_emc; @@ -144,17 +130,10 @@ typedef long (tegra20_clk_emc_round_cb)(unsigned long rate, unsigned long min_rate, unsigned long max_rate, void *arg); - -void tegra20_clk_set_emc_round_callback(tegra20_clk_emc_round_cb *round_cb, - void *cb_arg); -int tegra20_clk_prepare_emc_mc_same_freq(struct clk *emc_clk, bool same); - typedef int (tegra124_emc_prepare_timing_change_cb)(struct tegra_emc *emc, unsigned long rate); typedef void (tegra124_emc_complete_timing_change_cb)(struct tegra_emc *emc, unsigned long rate); -void tegra124_clk_set_emc_callbacks(tegra124_emc_prepare_timing_change_cb *prep_cb, - tegra124_emc_complete_timing_change_cb *complete_cb); struct tegra210_clk_emc_config { unsigned long rate; @@ -176,8 +155,87 @@ struct tegra210_clk_emc_provider { const struct tegra210_clk_emc_config *config); }; +#if defined(CONFIG_ARCH_TEGRA_2x_SOC) || defined(CONFIG_ARCH_TEGRA_3x_SOC) +void tegra20_clk_set_emc_round_callback(tegra20_clk_emc_round_cb *round_cb, + void *cb_arg); +int tegra20_clk_prepare_emc_mc_same_freq(struct clk *emc_clk, bool same); +#else +static inline void +tegra20_clk_set_emc_round_callback(tegra20_clk_emc_round_cb *round_cb, + void *cb_arg) +{ +} + +static inline int +tegra20_clk_prepare_emc_mc_same_freq(struct clk *emc_clk, bool same) +{ + return 0; +} +#endif + +#ifdef CONFIG_TEGRA124_CLK_EMC +void tegra124_clk_set_emc_callbacks(tegra124_emc_prepare_timing_change_cb *prep_cb, + tegra124_emc_complete_timing_change_cb *complete_cb); +#else +static inline void +tegra124_clk_set_emc_callbacks(tegra124_emc_prepare_timing_change_cb *prep_cb, + tegra124_emc_complete_timing_change_cb *complete_cb) +{ +} +#endif + +#ifdef CONFIG_ARCH_TEGRA_210_SOC +int tegra210_plle_hw_sequence_start(void); +bool tegra210_plle_hw_sequence_is_enabled(void); +void tegra210_xusb_pll_hw_control_enable(void); +void tegra210_xusb_pll_hw_sequence_start(void); +void tegra210_sata_pll_hw_control_enable(void); +void tegra210_sata_pll_hw_sequence_start(void); +void tegra210_set_sata_pll_seq_sw(bool state); +void tegra210_put_utmipll_in_iddq(void); +void tegra210_put_utmipll_out_iddq(void); +int tegra210_clk_handle_mbist_war(unsigned int id); +void tegra210_clk_emc_dll_enable(bool flag); +void tegra210_clk_emc_dll_update_setting(u32 emc_dll_src_value); +void tegra210_clk_emc_update_setting(u32 emc_src_value); + int tegra210_clk_emc_attach(struct clk *clk, struct tegra210_clk_emc_provider *provider); void tegra210_clk_emc_detach(struct clk *clk); +#else +static inline int tegra210_plle_hw_sequence_start(void) +{ + return 0; +} + +static inline bool tegra210_plle_hw_sequence_is_enabled(void) +{ + return false; +} + +static inline int tegra210_clk_handle_mbist_war(unsigned int id) +{ + return 0; +} + +static inline int +tegra210_clk_emc_attach(struct clk *clk, + struct tegra210_clk_emc_provider *provider) +{ + return 0; +} + +static inline void tegra210_xusb_pll_hw_control_enable(void) {} +static inline void tegra210_xusb_pll_hw_sequence_start(void) {} +static inline void tegra210_sata_pll_hw_control_enable(void) {} +static inline void tegra210_sata_pll_hw_sequence_start(void) {} +static inline void tegra210_set_sata_pll_seq_sw(bool state) {} +static inline void tegra210_put_utmipll_in_iddq(void) {} +static inline void tegra210_put_utmipll_out_iddq(void) {} +static inline void tegra210_clk_emc_dll_enable(bool flag) {} +static inline void tegra210_clk_emc_dll_update_setting(u32 emc_dll_src_value) {} +static inline void tegra210_clk_emc_update_setting(u32 emc_src_value) {} +static inline void tegra210_clk_emc_detach(struct clk *clk) {} +#endif #endif /* __LINUX_CLK_TEGRA_H_ */ From 86881de4939a4d14d773de006de2292fd86b6a08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Tue, 27 Apr 2021 18:45:22 +0200 Subject: [PATCH 036/161] clk: qcom: Simplify usage of dev_err_probe() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit dev_err_probe() returns the error code passed as second parameter. Also if the error code is -EPROBE_DEFER dev_err_probe() is silent, so there is no need to check for this value before calling dev_err_probe(). Signed-off-by: Uwe Kleine-König Link: https://lore.kernel.org/r/20210427164522.2886825-1-uwe@kleine-koenig.org Reviewed-by: Bjorn Andersson Signed-off-by: Stephen Boyd --- drivers/clk/qcom/apcs-sdx55.c | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/drivers/clk/qcom/apcs-sdx55.c b/drivers/clk/qcom/apcs-sdx55.c index d0edabebf9c2..6810637f32e3 100644 --- a/drivers/clk/qcom/apcs-sdx55.c +++ b/drivers/clk/qcom/apcs-sdx55.c @@ -56,10 +56,8 @@ static int qcom_apcs_sdx55_clk_probe(struct platform_device *pdev) int ret; regmap = dev_get_regmap(parent, NULL); - if (!regmap) { - dev_err_probe(dev, -ENODEV, "Failed to get parent regmap\n"); - return -ENODEV; - } + if (!regmap) + return dev_err_probe(dev, -ENODEV, "Failed to get parent regmap\n"); a7cc = devm_kzalloc(dev, sizeof(*a7cc), GFP_KERNEL); if (!a7cc) @@ -80,19 +78,15 @@ static int qcom_apcs_sdx55_clk_probe(struct platform_device *pdev) a7cc->parent_map = apcs_mux_clk_parent_map; a7cc->pclk = devm_clk_get(parent, "pll"); - if (IS_ERR(a7cc->pclk)) { - ret = PTR_ERR(a7cc->pclk); - if (ret != -EPROBE_DEFER) - dev_err_probe(dev, ret, "Failed to get PLL clk\n"); - return ret; - } + if (IS_ERR(a7cc->pclk)) + return dev_err_probe(dev, PTR_ERR(a7cc->pclk), + "Failed to get PLL clk\n"); a7cc->clk_nb.notifier_call = a7cc_notifier_cb; ret = clk_notifier_register(a7cc->pclk, &a7cc->clk_nb); - if (ret) { - dev_err_probe(dev, ret, "Failed to register clock notifier\n"); - return ret; - } + if (ret) + return dev_err_probe(dev, ret, + "Failed to register clock notifier\n"); ret = devm_clk_register_regmap(dev, &a7cc->clkr); if (ret) { From 15abefda7fde690b7091ac5854135da41c7f759c Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 11 May 2021 10:09:08 +0300 Subject: [PATCH 037/161] clk: qcom: cleanup some dev_err_probe() calls The dev_err_probe() function prints an error message if the error code is not -EPROBE_DEFER. If we know the error code in is -ENODEV then there is no reason to check. Signed-off-by: Dan Carpenter Link: https://lore.kernel.org/r/YJotlJBJ1CVAgvMT@mwanda Signed-off-by: Stephen Boyd --- drivers/clk/qcom/apcs-sdx55.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/clk/qcom/apcs-sdx55.c b/drivers/clk/qcom/apcs-sdx55.c index 6810637f32e3..e599f862ec44 100644 --- a/drivers/clk/qcom/apcs-sdx55.c +++ b/drivers/clk/qcom/apcs-sdx55.c @@ -56,8 +56,10 @@ static int qcom_apcs_sdx55_clk_probe(struct platform_device *pdev) int ret; regmap = dev_get_regmap(parent, NULL); - if (!regmap) - return dev_err_probe(dev, -ENODEV, "Failed to get parent regmap\n"); + if (!regmap) { + dev_err(dev, "Failed to get parent regmap\n"); + return -ENODEV; + } a7cc = devm_kzalloc(dev, sizeof(*a7cc), GFP_KERNEL); if (!a7cc) From 419b3ab6987f2a108cc4710030184365b17467ac Mon Sep 17 00:00:00 2001 From: Peter Collingbourne Date: Thu, 20 May 2021 17:17:02 +0100 Subject: [PATCH 038/161] clk: versatile: remove dependency on ARCH_* It is now possible to build a modular kernel for vexpress by not setting CONFIG_ARCH_VEXPRESS=y and instead setting =m on the drivers that it normally implies. This is with the exception of CLK_VEXPRESS_OSC which is currently hidden behind a dependency on one of several ARCH_* variables. Remove that dependency so that CLK_VEXPRESS_OSC may be enabled without it. Signed-off-by: Peter Collingbourne Link: https://linux-review.googlesource.com/id/I435a21e2e5f6187db54f4ef2079b60028ab2ea69 Signed-off-by: Lee Jones Link: https://lore.kernel.org/r/20210520161702.3746174-1-lee.jones@linaro.org Reviewed-by: Linus Walleij Signed-off-by: Stephen Boyd --- drivers/clk/versatile/Kconfig | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/clk/versatile/Kconfig b/drivers/clk/versatile/Kconfig index 91f0ff54237d..792315d893db 100644 --- a/drivers/clk/versatile/Kconfig +++ b/drivers/clk/versatile/Kconfig @@ -1,8 +1,6 @@ # SPDX-License-Identifier: GPL-2.0-only menu "Clock driver for ARM Reference designs" - depends on ARCH_INTEGRATOR || ARCH_REALVIEW || \ - ARCH_VERSATILE || ARCH_VEXPRESS || COMPILE_TEST config ICST bool "Clock driver for ARM Reference designs ICST" From c37f1cdd1fc9b128f254c9fb3ec81d0df3cc6117 Mon Sep 17 00:00:00 2001 From: Yang Li Date: Mon, 24 May 2021 18:22:10 +0800 Subject: [PATCH 039/161] clk: sifive: Fix kernel-doc Fix function name in sifive-prci.c kernel-doc comment to remove a warning. drivers/clk/sifive/sifive-prci.c:573: warning: expecting prototype for sifive_prci_init(). Prototype was for sifive_prci_probe() instead Reported-by: Abaci Robot Signed-off-by: Yang Li Link: https://lore.kernel.org/r/1621851730-32287-1-git-send-email-yang.lee@linux.alibaba.com Reviewed-by: Palmer Dabbelt Acked-by: Palmer Dabbelt Signed-off-by: Stephen Boyd --- drivers/clk/sifive/sifive-prci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/sifive/sifive-prci.c b/drivers/clk/sifive/sifive-prci.c index 0d79ba31a793..80a288c59e56 100644 --- a/drivers/clk/sifive/sifive-prci.c +++ b/drivers/clk/sifive/sifive-prci.c @@ -564,7 +564,7 @@ static int __prci_register_clocks(struct device *dev, struct __prci_data *pd, } /** - * sifive_prci_init() - initialize prci data and check parent count + * sifive_prci_probe() - initialize prci data and check parent count * @pdev: platform device pointer for the prci * * Return: 0 upon success or a negative error code upon failure. From 06abc7537686ad013825bef6aa0f03fd484ca5ad Mon Sep 17 00:00:00 2001 From: Yang Yingliang Date: Tue, 1 Jun 2021 19:41:54 +0800 Subject: [PATCH 040/161] clk: analogbits: fix doc warning in wrpll-cln28hpc.c Fix the following make W=1 warning: drivers/clk/analogbits/wrpll-cln28hpc.c:227: warning: expecting prototype for wrpll_configure(). Prototype was for wrpll_configure_for_rate() instead Signed-off-by: Yang Yingliang Link: https://lore.kernel.org/r/20210601114154.3163327-1-yangyingliang@huawei.com Signed-off-by: Stephen Boyd --- drivers/clk/analogbits/wrpll-cln28hpc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/analogbits/wrpll-cln28hpc.c b/drivers/clk/analogbits/wrpll-cln28hpc.c index 776ead319ae9..3b1947575dcc 100644 --- a/drivers/clk/analogbits/wrpll-cln28hpc.c +++ b/drivers/clk/analogbits/wrpll-cln28hpc.c @@ -198,7 +198,7 @@ static int __wrpll_update_parent_rate(struct wrpll_cfg *c, } /** - * wrpll_configure() - compute PLL configuration for a target rate + * wrpll_configure_for_rate() - compute PLL configuration for a target rate * @c: ptr to a struct wrpll_cfg record to write into * @target_rate: target PLL output clock rate (post-Q-divider) * @parent_rate: PLL input refclk rate (pre-R-divider) From 6faa7e4ddce6ddd5e93b0e521537e0360c7dac2b Mon Sep 17 00:00:00 2001 From: Konrad Dybcio Date: Sat, 13 Mar 2021 03:03:07 +0100 Subject: [PATCH 041/161] dt-bindings: clock: Add MDM9607 GCC clock bindings Add device tree bindings for global clock controller on MDM9607 SoC. Signed-off-by: Konrad Dybcio Link: https://lore.kernel.org/r/20210313020310.386152-1-konrad.dybcio@somainline.org Acked-by: Rob Herring Signed-off-by: Stephen Boyd --- .../devicetree/bindings/clock/qcom,gcc.yaml | 2 + include/dt-bindings/clock/qcom,gcc-mdm9607.h | 104 ++++++++++++++++++ 2 files changed, 106 insertions(+) create mode 100644 include/dt-bindings/clock/qcom,gcc-mdm9607.h diff --git a/Documentation/devicetree/bindings/clock/qcom,gcc.yaml b/Documentation/devicetree/bindings/clock/qcom,gcc.yaml index 490edad25830..3599702cd428 100644 --- a/Documentation/devicetree/bindings/clock/qcom,gcc.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,gcc.yaml @@ -29,6 +29,7 @@ description: | - dt-bindings/clock/qcom,gcc-msm8974.h - dt-bindings/reset/qcom,gcc-msm8974.h - dt-bindings/clock/qcom,gcc-msm8994.h + - dt-bindings/clock/qcom,gcc-mdm9607.h - dt-bindings/clock/qcom,gcc-mdm9615.h - dt-bindings/reset/qcom,gcc-mdm9615.h - dt-bindings/clock/qcom,gcc-sdm660.h (qcom,gcc-sdm630 and qcom,gcc-sdm660) @@ -40,6 +41,7 @@ properties: - qcom,gcc-ipq4019 - qcom,gcc-ipq6018 - qcom,gcc-ipq8064 + - qcom,gcc-mdm9607 - qcom,gcc-msm8660 - qcom,gcc-msm8916 - qcom,gcc-msm8939 diff --git a/include/dt-bindings/clock/qcom,gcc-mdm9607.h b/include/dt-bindings/clock/qcom,gcc-mdm9607.h new file mode 100644 index 000000000000..357a680a40da --- /dev/null +++ b/include/dt-bindings/clock/qcom,gcc-mdm9607.h @@ -0,0 +1,104 @@ +/* SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) */ +/* + * Copyright (c) 2021, Konrad Dybcio + */ + +#ifndef _DT_BINDINGS_CLK_MSM_GCC_9607_H +#define _DT_BINDINGS_CLK_MSM_GCC_9607_H + +#define GPLL0 0 +#define GPLL0_EARLY 1 +#define GPLL1 2 +#define GPLL1_VOTE 3 +#define GPLL2 4 +#define GPLL2_EARLY 5 +#define PCNOC_BFDCD_CLK_SRC 6 +#define SYSTEM_NOC_BFDCD_CLK_SRC 7 +#define GCC_SMMU_CFG_CLK 8 +#define APSS_AHB_CLK_SRC 9 +#define GCC_QDSS_DAP_CLK 10 +#define BLSP1_QUP1_I2C_APPS_CLK_SRC 11 +#define BLSP1_QUP1_SPI_APPS_CLK_SRC 12 +#define BLSP1_QUP2_I2C_APPS_CLK_SRC 13 +#define BLSP1_QUP2_SPI_APPS_CLK_SRC 14 +#define BLSP1_QUP3_I2C_APPS_CLK_SRC 15 +#define BLSP1_QUP3_SPI_APPS_CLK_SRC 16 +#define BLSP1_QUP4_I2C_APPS_CLK_SRC 17 +#define BLSP1_QUP4_SPI_APPS_CLK_SRC 18 +#define BLSP1_QUP5_I2C_APPS_CLK_SRC 19 +#define BLSP1_QUP5_SPI_APPS_CLK_SRC 20 +#define BLSP1_QUP6_I2C_APPS_CLK_SRC 21 +#define BLSP1_QUP6_SPI_APPS_CLK_SRC 22 +#define BLSP1_UART1_APPS_CLK_SRC 23 +#define BLSP1_UART2_APPS_CLK_SRC 24 +#define CRYPTO_CLK_SRC 25 +#define GP1_CLK_SRC 26 +#define GP2_CLK_SRC 27 +#define GP3_CLK_SRC 28 +#define PDM2_CLK_SRC 29 +#define SDCC1_APPS_CLK_SRC 30 +#define SDCC2_APPS_CLK_SRC 31 +#define APSS_TCU_CLK_SRC 32 +#define USB_HS_SYSTEM_CLK_SRC 33 +#define GCC_BLSP1_AHB_CLK 34 +#define GCC_BLSP1_SLEEP_CLK 35 +#define GCC_BLSP1_QUP1_I2C_APPS_CLK 36 +#define GCC_BLSP1_QUP1_SPI_APPS_CLK 37 +#define GCC_BLSP1_QUP2_I2C_APPS_CLK 38 +#define GCC_BLSP1_QUP2_SPI_APPS_CLK 39 +#define GCC_BLSP1_QUP3_I2C_APPS_CLK 40 +#define GCC_BLSP1_QUP3_SPI_APPS_CLK 41 +#define GCC_BLSP1_QUP4_I2C_APPS_CLK 42 +#define GCC_BLSP1_QUP4_SPI_APPS_CLK 43 +#define GCC_BLSP1_QUP5_I2C_APPS_CLK 44 +#define GCC_BLSP1_QUP5_SPI_APPS_CLK 45 +#define GCC_BLSP1_QUP6_I2C_APPS_CLK 46 +#define GCC_BLSP1_QUP6_SPI_APPS_CLK 47 +#define GCC_BLSP1_UART1_APPS_CLK 48 +#define GCC_BLSP1_UART2_APPS_CLK 49 +#define GCC_BOOT_ROM_AHB_CLK 50 +#define GCC_CRYPTO_AHB_CLK 51 +#define GCC_CRYPTO_AXI_CLK 52 +#define GCC_CRYPTO_CLK 53 +#define GCC_GP1_CLK 54 +#define GCC_GP2_CLK 55 +#define GCC_GP3_CLK 56 +#define GCC_MSS_CFG_AHB_CLK 57 +#define GCC_PDM2_CLK 58 +#define GCC_PDM_AHB_CLK 59 +#define GCC_PRNG_AHB_CLK 60 +#define GCC_SDCC1_AHB_CLK 61 +#define GCC_SDCC1_APPS_CLK 62 +#define GCC_SDCC2_AHB_CLK 63 +#define GCC_SDCC2_APPS_CLK 64 +#define GCC_USB2A_PHY_SLEEP_CLK 65 +#define GCC_USB_HS_AHB_CLK 66 +#define GCC_USB_HS_SYSTEM_CLK 67 +#define GCC_APSS_TCU_CLK 68 +#define GCC_MSS_Q6_BIMC_AXI_CLK 69 +#define BIMC_PLL 70 +#define BIMC_PLL_VOTE 71 +#define BIMC_DDR_CLK_SRC 72 +#define BLSP1_UART3_APPS_CLK_SRC 73 +#define BLSP1_UART4_APPS_CLK_SRC 74 +#define BLSP1_UART5_APPS_CLK_SRC 75 +#define BLSP1_UART6_APPS_CLK_SRC 76 +#define GCC_BLSP1_UART3_APPS_CLK 77 +#define GCC_BLSP1_UART4_APPS_CLK 78 +#define GCC_BLSP1_UART5_APPS_CLK 79 +#define GCC_BLSP1_UART6_APPS_CLK 80 +#define GCC_APSS_AHB_CLK 81 +#define GCC_APSS_AXI_CLK 82 +#define GCC_USB_HS_PHY_CFG_AHB_CLK 83 +#define GCC_USB_HSIC_CLK_SRC 84 +#define GCC_USB_HSIC_IO_CAL_CLK_SRC 85 +#define GCC_USB_HSIC_SYSTEM_CLK_SRC 86 + +/* Resets */ +#define USB2_HS_PHY_ONLY_BCR 0 +#define QUSB2_PHY_BCR 1 +#define GCC_MSS_RESTART 2 +#define USB_HS_HSIC_BCR 3 +#define USB_HS_BCR 4 + +#endif From 48b7253264eadc05a3d84db9ea11eef528a0108a Mon Sep 17 00:00:00 2001 From: Konrad Dybcio Date: Sat, 13 Mar 2021 03:03:08 +0100 Subject: [PATCH 042/161] clk: qcom: Add MDM9607 GCC driver Add Global Clock Controller (GCC) support for MDM9607 SoC. Signed-off-by: Konrad Dybcio Link: https://lore.kernel.org/r/20210313020310.386152-2-konrad.dybcio@somainline.org [sboyd@kernel.org: Drop clk.h include] Signed-off-by: Stephen Boyd --- drivers/clk/qcom/Kconfig | 7 + drivers/clk/qcom/Makefile | 1 + drivers/clk/qcom/gcc-mdm9607.c | 1655 ++++++++++++++++++++++++++++++++ 3 files changed, 1663 insertions(+) create mode 100644 drivers/clk/qcom/gcc-mdm9607.c diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig index 45646b867cdb..c84b2c896a27 100644 --- a/drivers/clk/qcom/Kconfig +++ b/drivers/clk/qcom/Kconfig @@ -210,6 +210,13 @@ config MSM_LCC_8960 Say Y if you want to use audio devices such as i2s, pcm, SLIMBus, etc. +config MDM_GCC_9607 + tristate "MDM9607 Global Clock Controller" + help + Support for the global clock controller on mdm9607 devices. + Say Y if you want to use peripheral devices such as UART, SPI, + I2C, USB, SD/eMMC, etc. + config MDM_GCC_9615 tristate "MDM9615 Global Clock Controller" help diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile index c8291312e723..9495bf6a18d0 100644 --- a/drivers/clk/qcom/Makefile +++ b/drivers/clk/qcom/Makefile @@ -27,6 +27,7 @@ obj-$(CONFIG_IPQ_GCC_6018) += gcc-ipq6018.o obj-$(CONFIG_IPQ_GCC_806X) += gcc-ipq806x.o obj-$(CONFIG_IPQ_GCC_8074) += gcc-ipq8074.o obj-$(CONFIG_IPQ_LCC_806X) += lcc-ipq806x.o +obj-$(CONFIG_MDM_GCC_9607) += gcc-mdm9607.o obj-$(CONFIG_MDM_GCC_9615) += gcc-mdm9615.o obj-$(CONFIG_MDM_LCC_9615) += lcc-mdm9615.o obj-$(CONFIG_MSM_GCC_8660) += gcc-msm8660.o diff --git a/drivers/clk/qcom/gcc-mdm9607.c b/drivers/clk/qcom/gcc-mdm9607.c new file mode 100644 index 000000000000..5918dc51ffcd --- /dev/null +++ b/drivers/clk/qcom/gcc-mdm9607.c @@ -0,0 +1,1655 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2021, Konrad Dybcio + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "common.h" +#include "clk-regmap.h" +#include "clk-alpha-pll.h" +#include "clk-pll.h" +#include "clk-rcg.h" +#include "clk-branch.h" +#include "reset.h" +#include "gdsc.h" + +enum { + P_XO, + P_BIMC, + P_GPLL0, + P_GPLL1, + P_GPLL2, + P_SLEEP_CLK, +}; + +static const struct parent_map gcc_xo_sleep_map[] = { + { P_XO, 0 }, + { P_SLEEP_CLK, 6 } +}; + +static const struct clk_parent_data gcc_xo_sleep[] = { + { .fw_name = "xo" }, + { .fw_name = "sleep_clk" }, +}; + +static struct clk_alpha_pll gpll0_early = { + .offset = 0x21000, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT], + .clkr = { + .enable_reg = 0x45000, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data) + { + .name = "gpll0_early", + .parent_data = &(const struct clk_parent_data){ + .fw_name = "xo", + }, + .num_parents = 1, + .ops = &clk_alpha_pll_ops, + }, + }, +}; + +static struct clk_alpha_pll_postdiv gpll0 = { + .offset = 0x21000, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT], + .clkr.hw.init = &(struct clk_init_data) + { + .name = "gpll0", + .parent_hws = (const struct clk_hw *[]){ &gpll0_early.clkr.hw }, + .num_parents = 1, + .ops = &clk_alpha_pll_postdiv_ops, + }, +}; + +static const struct parent_map gcc_xo_gpll0_map[] = { + { P_XO, 0 }, + { P_GPLL0, 1 }, +}; + +static const struct clk_parent_data gcc_xo_gpll0[] = { + { .fw_name = "xo" }, + { .hw = &gpll0.clkr.hw }, +}; + +static struct clk_pll gpll1 = { + .l_reg = 0x20004, + .m_reg = 0x20008, + .n_reg = 0x2000c, + .config_reg = 0x20010, + .mode_reg = 0x20000, + .status_reg = 0x2001c, + .status_bit = 17, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gpll1", + .parent_data = &(const struct clk_parent_data){ + .fw_name = "xo", + }, + .num_parents = 1, + .ops = &clk_pll_ops, + }, +}; + +static struct clk_regmap gpll1_vote = { + .enable_reg = 0x45000, + .enable_mask = BIT(1), + .hw.init = &(struct clk_init_data){ + .name = "gpll1_vote", + .parent_hws = (const struct clk_hw *[]){ &gpll1.clkr.hw }, + .num_parents = 1, + .ops = &clk_pll_vote_ops, + }, +}; + +static const struct parent_map gcc_xo_gpll0_gpll1_map[] = { + { P_XO, 0 }, + { P_GPLL0, 1 }, + { P_GPLL1, 2 }, +}; + +static const struct clk_parent_data gcc_xo_gpll0_gpll1[] = { + { .fw_name = "xo" }, + { .hw = &gpll0.clkr.hw }, + { .hw = &gpll1_vote.hw }, +}; + + +static const struct parent_map gcc_xo_gpll0_gpll1_sleep_map[] = { + { P_XO, 0 }, + { P_GPLL0, 1 }, + { P_GPLL1, 2 }, + { P_SLEEP_CLK, 6 }, +}; + +static const struct clk_parent_data gcc_xo_gpll0_gpll1_sleep[] = { + { .fw_name = "xo" }, + { .hw = &gpll0.clkr.hw }, + { .hw = &gpll1_vote.hw }, + { .fw_name = "sleep_clk" }, +}; + +static struct clk_alpha_pll gpll2_early = { + .offset = 0x25000, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT], + .clkr = { + .enable_reg = 0x45000, + .enable_mask = BIT(3), /* Yeah, apparently it's not 2 */ + .hw.init = &(struct clk_init_data) + { + .name = "gpll2_early", + .parent_data = &(const struct clk_parent_data){ + .fw_name = "xo", + }, + .num_parents = 1, + .ops = &clk_alpha_pll_ops, + }, + }, +}; + +static struct clk_alpha_pll_postdiv gpll2 = { + .offset = 0x25000, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT], + .clkr.hw.init = &(struct clk_init_data) + { + .name = "gpll2", + .parent_hws = (const struct clk_hw *[]){ &gpll2_early.clkr.hw }, + .num_parents = 1, + .ops = &clk_alpha_pll_postdiv_ops, + }, +}; + +static const struct parent_map gcc_xo_gpll0_gpll2_map[] = { + { P_XO, 0 }, + { P_GPLL0, 1 }, + { P_GPLL2, 2 }, +}; + +static const struct clk_parent_data gcc_xo_gpll0_gpll2[] = { + { .fw_name = "xo" }, + { .hw = &gpll0.clkr.hw }, + { .hw = &gpll2.clkr.hw }, +}; + +static const struct parent_map gcc_xo_gpll0_gpll1_gpll2_map[] = { + { P_XO, 0 }, + { P_GPLL0, 1 }, + { P_GPLL1, 2 }, + { P_GPLL2, 3 }, +}; + +static const struct clk_parent_data gcc_xo_gpll0_gpll1_gpll2[] = { + { .fw_name = "xo" }, + { .hw = &gpll0.clkr.hw }, + { .hw = &gpll1_vote.hw }, + { .hw = &gpll2.clkr.hw }, +}; + +static const struct freq_tbl ftbl_apss_ahb_clk[] = { + F(19200000, P_XO, 1, 0, 0), + F(50000000, P_GPLL0, 16, 0, 0), + F(100000000, P_GPLL0, 8, 0, 0), + { } +}; + +static struct clk_rcg2 apss_ahb_clk_src = { + .cmd_rcgr = 0x46000, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_map, + .freq_tbl = ftbl_apss_ahb_clk, + .clkr.hw.init = &(struct clk_init_data){ + .name = "apss_ahb_clk_src", + .parent_data = gcc_xo_gpll0, + .num_parents = 2, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_pll bimc_pll = { + .l_reg = 0x23004, + .m_reg = 0x23008, + .n_reg = 0x2300c, + .config_reg = 0x23010, + .mode_reg = 0x23000, + .status_reg = 0x2301c, + .status_bit = 17, + .clkr.hw.init = &(struct clk_init_data){ + .name = "bimc_pll", + .parent_data = &(const struct clk_parent_data){ + .fw_name = "xo", + }, + .num_parents = 1, + .ops = &clk_pll_ops, + }, +}; + +static struct clk_regmap bimc_pll_vote = { + .enable_reg = 0x45000, + .enable_mask = BIT(3), + .hw.init = &(struct clk_init_data){ + .name = "bimc_pll_vote", + .parent_hws = (const struct clk_hw *[]){ &bimc_pll.clkr.hw }, + .num_parents = 1, + .ops = &clk_pll_vote_ops, + }, +}; + +static const struct parent_map gcc_xo_gpll0_bimc_map[] = { + { P_XO, 0 }, + { P_GPLL0, 1 }, + { P_BIMC, 2 }, +}; + +static const struct clk_parent_data gcc_xo_gpll0_bimc[] = { + { .fw_name = "xo" }, + { .hw = &gpll0.clkr.hw }, + { .hw = &bimc_pll_vote.hw }, +}; + +static const struct freq_tbl ftbl_pcnoc_bfdcd_clk_src[] = { + F(19200000, P_XO, 1, 0, 0), + F(50000000, P_GPLL0, 16, 0, 0), + F(100000000, P_GPLL0, 8, 0, 0), + { } +}; + +static struct clk_rcg2 pcnoc_bfdcd_clk_src = { + .cmd_rcgr = 0x27000, + .freq_tbl = ftbl_pcnoc_bfdcd_clk_src, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_bimc_map, + .clkr.hw.init = &(struct clk_init_data){ + .name = "pcnoc_bfdcd_clk_src", + .parent_data = gcc_xo_gpll0_bimc, + .num_parents = ARRAY_SIZE(gcc_xo_gpll0_bimc), + .ops = &clk_rcg2_ops, + .flags = CLK_IS_CRITICAL, + }, +}; + +static struct clk_rcg2 system_noc_bfdcd_clk_src = { + .cmd_rcgr = 0x26004, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_bimc_map, + .clkr.hw.init = &(struct clk_init_data){ + .name = "system_noc_bfdcd_clk_src", + .parent_data = gcc_xo_gpll0_bimc, + .num_parents = ARRAY_SIZE(gcc_xo_gpll0_bimc), + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_blsp1_qup1_6_i2c_apps_clk[] = { + F(19200000, P_XO, 1, 0, 0), + F(50000000, P_GPLL0, 16, 0, 0), + { } +}; + +static struct clk_rcg2 blsp1_qup1_i2c_apps_clk_src = { + .cmd_rcgr = 0x200c, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_map, + .freq_tbl = ftbl_gcc_blsp1_qup1_6_i2c_apps_clk, + .clkr.hw.init = &(struct clk_init_data){ + .name = "blsp1_qup1_i2c_apps_clk_src", + .parent_data = gcc_xo_gpll0, + .num_parents = 2, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_blsp1_qup1_6_spi_apps_clk[] = { + F(960000, P_XO, 10, 1, 2), + F(4800000, P_XO, 4, 0, 0), + F(9600000, P_XO, 2, 0, 0), + F(16000000, P_GPLL0, 10, 1, 5), + F(19200000, P_XO, 1, 0, 0), + F(25000000, P_GPLL0, 16, 1, 2), + F(50000000, P_GPLL0, 16, 0, 0), + { } +}; + +static struct clk_rcg2 blsp1_qup1_spi_apps_clk_src = { + .cmd_rcgr = 0x2024, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_map, + .freq_tbl = ftbl_gcc_blsp1_qup1_6_spi_apps_clk, + .clkr.hw.init = &(struct clk_init_data){ + .name = "blsp1_qup1_spi_apps_clk_src", + .parent_data = gcc_xo_gpll0, + .num_parents = 2, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 blsp1_qup2_i2c_apps_clk_src = { + .cmd_rcgr = 0x3000, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_map, + .freq_tbl = ftbl_gcc_blsp1_qup1_6_i2c_apps_clk, + .clkr.hw.init = &(struct clk_init_data){ + .name = "blsp1_qup2_i2c_apps_clk_src", + .parent_data = gcc_xo_gpll0, + .num_parents = 2, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 blsp1_qup2_spi_apps_clk_src = { + .cmd_rcgr = 0x3014, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_map, + .freq_tbl = ftbl_gcc_blsp1_qup1_6_spi_apps_clk, + .clkr.hw.init = &(struct clk_init_data){ + .name = "blsp1_qup2_spi_apps_clk_src", + .parent_data = gcc_xo_gpll0, + .num_parents = 2, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 blsp1_qup3_i2c_apps_clk_src = { + .cmd_rcgr = 0x4000, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_map, + .freq_tbl = ftbl_gcc_blsp1_qup1_6_i2c_apps_clk, + .clkr.hw.init = &(struct clk_init_data){ + .name = "blsp1_qup3_i2c_apps_clk_src", + .parent_data = gcc_xo_gpll0, + .num_parents = 2, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 blsp1_qup3_spi_apps_clk_src = { + .cmd_rcgr = 0x4024, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_map, + .freq_tbl = ftbl_gcc_blsp1_qup1_6_spi_apps_clk, + .clkr.hw.init = &(struct clk_init_data){ + .name = "blsp1_qup3_spi_apps_clk_src", + .parent_data = gcc_xo_gpll0, + .num_parents = 2, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 blsp1_qup4_i2c_apps_clk_src = { + .cmd_rcgr = 0x5000, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_map, + .freq_tbl = ftbl_gcc_blsp1_qup1_6_i2c_apps_clk, + .clkr.hw.init = &(struct clk_init_data){ + .name = "blsp1_qup4_i2c_apps_clk_src", + .parent_data = gcc_xo_gpll0, + .num_parents = 2, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 blsp1_qup4_spi_apps_clk_src = { + .cmd_rcgr = 0x5024, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_map, + .freq_tbl = ftbl_gcc_blsp1_qup1_6_spi_apps_clk, + .clkr.hw.init = &(struct clk_init_data){ + .name = "blsp1_qup4_spi_apps_clk_src", + .parent_data = gcc_xo_gpll0, + .num_parents = 2, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 blsp1_qup5_i2c_apps_clk_src = { + .cmd_rcgr = 0x6000, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_map, + .freq_tbl = ftbl_gcc_blsp1_qup1_6_i2c_apps_clk, + .clkr.hw.init = &(struct clk_init_data){ + .name = "blsp1_qup5_i2c_apps_clk_src", + .parent_data = gcc_xo_gpll0, + .num_parents = 2, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 blsp1_qup5_spi_apps_clk_src = { + .cmd_rcgr = 0x6024, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_map, + .freq_tbl = ftbl_gcc_blsp1_qup1_6_spi_apps_clk, + .clkr.hw.init = &(struct clk_init_data){ + .name = "blsp1_qup5_spi_apps_clk_src", + .parent_data = gcc_xo_gpll0, + .num_parents = 2, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 blsp1_qup6_i2c_apps_clk_src = { + .cmd_rcgr = 0x7000, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_map, + .freq_tbl = ftbl_gcc_blsp1_qup1_6_i2c_apps_clk, + .clkr.hw.init = &(struct clk_init_data){ + .name = "blsp1_qup6_i2c_apps_clk_src", + .parent_data = gcc_xo_gpll0, + .num_parents = 2, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 blsp1_qup6_spi_apps_clk_src = { + .cmd_rcgr = 0x7024, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_map, + .freq_tbl = ftbl_gcc_blsp1_qup1_6_spi_apps_clk, + .clkr.hw.init = &(struct clk_init_data){ + .name = "blsp1_qup6_spi_apps_clk_src", + .parent_data = gcc_xo_gpll0, + .num_parents = 2, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_blsp1_uart1_6_apps_clk[] = { + F(3686400, P_GPLL0, 1, 72, 15625), + F(7372800, P_GPLL0, 1, 144, 15625), + F(14745600, P_GPLL0, 1, 288, 15625), + F(16000000, P_GPLL0, 10, 1, 5), + F(19200000, P_XO, 1, 0, 0), + F(24000000, P_GPLL0, 1, 3, 100), + F(25000000, P_GPLL0, 16, 1, 2), + F(32000000, P_GPLL0, 1, 1, 25), + F(40000000, P_GPLL0, 1, 1, 20), + F(46400000, P_GPLL0, 1, 29, 500), + F(48000000, P_GPLL0, 1, 3, 50), + F(51200000, P_GPLL0, 1, 8, 125), + F(56000000, P_GPLL0, 1, 7, 100), + F(58982400, P_GPLL0, 1, 1152, 15625), + F(60000000, P_GPLL0, 1, 3, 40), + { } +}; + +static struct clk_rcg2 blsp1_uart1_apps_clk_src = { + .cmd_rcgr = 0x2044, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_map, + .freq_tbl = ftbl_gcc_blsp1_uart1_6_apps_clk, + .clkr.hw.init = &(struct clk_init_data){ + .name = "blsp1_uart1_apps_clk_src", + .parent_data = gcc_xo_gpll0, + .num_parents = 2, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 blsp1_uart2_apps_clk_src = { + .cmd_rcgr = 0x3034, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_map, + .freq_tbl = ftbl_gcc_blsp1_uart1_6_apps_clk, + .clkr.hw.init = &(struct clk_init_data){ + .name = "blsp1_uart2_apps_clk_src", + .parent_data = gcc_xo_gpll0, + .num_parents = 2, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 blsp1_uart3_apps_clk_src = { + .cmd_rcgr = 0x4044, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_map, + .freq_tbl = ftbl_gcc_blsp1_uart1_6_apps_clk, + .clkr.hw.init = &(struct clk_init_data){ + .name = "blsp1_uart3_apps_clk_src", + .parent_data = gcc_xo_gpll0, + .num_parents = 2, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 blsp1_uart4_apps_clk_src = { + .cmd_rcgr = 0x5044, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_map, + .freq_tbl = ftbl_gcc_blsp1_uart1_6_apps_clk, + .clkr.hw.init = &(struct clk_init_data){ + .name = "blsp1_uart4_apps_clk_src", + .parent_data = gcc_xo_gpll0, + .num_parents = 2, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 blsp1_uart5_apps_clk_src = { + .cmd_rcgr = 0x6044, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_map, + .freq_tbl = ftbl_gcc_blsp1_uart1_6_apps_clk, + .clkr.hw.init = &(struct clk_init_data){ + .name = "blsp1_uart5_apps_clk_src", + .parent_data = gcc_xo_gpll0, + .num_parents = 2, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 blsp1_uart6_apps_clk_src = { + .cmd_rcgr = 0x6044, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_map, + .freq_tbl = ftbl_gcc_blsp1_uart1_6_apps_clk, + .clkr.hw.init = &(struct clk_init_data){ + .name = "blsp1_uart6_apps_clk_src", + .parent_data = gcc_xo_gpll0, + .num_parents = 2, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_crypto_clk[] = { + F(50000000, P_GPLL0, 16, 0, 0), + F(80000000, P_GPLL0, 10, 0, 0), + F(100000000, P_GPLL0, 8, 0, 0), + F(160000000, P_GPLL0, 5, 0, 0), + { } +}; + +static struct clk_rcg2 crypto_clk_src = { + .cmd_rcgr = 0x16004, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_map, + .freq_tbl = ftbl_gcc_crypto_clk, + .clkr.hw.init = &(struct clk_init_data){ + .name = "crypto_clk_src", + .parent_data = gcc_xo_gpll0, + .num_parents = 2, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_gp1_3_clk[] = { + F(19200000, P_XO, 1, 0, 0), + { } +}; + +static struct clk_rcg2 gp1_clk_src = { + .cmd_rcgr = 0x8004, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_gpll1_sleep_map, + .freq_tbl = ftbl_gcc_gp1_3_clk, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gp1_clk_src", + .parent_data = gcc_xo_gpll0_gpll1_sleep, + .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll1_sleep), + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 gp2_clk_src = { + .cmd_rcgr = 0x09004, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_gpll1_sleep_map, + .freq_tbl = ftbl_gcc_gp1_3_clk, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gp2_clk_src", + .parent_data = gcc_xo_gpll0_gpll1_sleep, + .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll1_sleep), + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 gp3_clk_src = { + .cmd_rcgr = 0x0a004, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_gpll1_sleep_map, + .freq_tbl = ftbl_gcc_gp1_3_clk, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gp3_clk_src", + .parent_data = gcc_xo_gpll0_gpll1_sleep, + .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll1_sleep), + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_pdm2_clk[] = { + F(64000000, P_GPLL0, 12.5, 0, 0), + { } +}; + +static struct clk_rcg2 pdm2_clk_src = { + .cmd_rcgr = 0x44010, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_map, + .freq_tbl = ftbl_gcc_pdm2_clk, + .clkr.hw.init = &(struct clk_init_data){ + .name = "pdm2_clk_src", + .parent_data = gcc_xo_gpll0, + .num_parents = 2, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_sdcc_apps_clk[] = { + F(144000, P_XO, 16, 3, 25), + F(400000, P_XO, 12, 1, 4), + F(20000000, P_GPLL0, 10, 1, 4), + F(25000000, P_GPLL0, 16, 1, 2), + F(50000000, P_GPLL0, 16, 0, 0), + F(100000000, P_GPLL0, 8, 0, 0), + F(177770000, P_GPLL0, 4.5, 0, 0), + F(200000000, P_GPLL0, 4, 0, 0), + { } +}; + +static struct clk_rcg2 sdcc1_apps_clk_src = { + .cmd_rcgr = 0x42004, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_map, + .freq_tbl = ftbl_gcc_sdcc_apps_clk, + .clkr.hw.init = &(struct clk_init_data){ + .name = "sdcc1_apps_clk_src", + .parent_data = gcc_xo_gpll0, + .num_parents = 2, + .ops = &clk_rcg2_floor_ops, + }, +}; + +static struct clk_rcg2 sdcc2_apps_clk_src = { + .cmd_rcgr = 0x43004, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_map, + .freq_tbl = ftbl_gcc_sdcc_apps_clk, + .clkr.hw.init = &(struct clk_init_data){ + .name = "sdcc2_apps_clk_src", + .parent_data = gcc_xo_gpll0, + .num_parents = 2, + .ops = &clk_rcg2_floor_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_apss_tcu_clk[] = { + F(155000000, P_GPLL2, 6, 0, 0), + F(310000000, P_GPLL2, 3, 0, 0), + F(400000000, P_GPLL0, 2, 0, 0), + { } +}; + +static struct clk_rcg2 apss_tcu_clk_src = { + .cmd_rcgr = 0x1207c, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_gpll1_gpll2_map, + .freq_tbl = ftbl_gcc_apss_tcu_clk, + .clkr.hw.init = &(struct clk_init_data){ + .name = "apss_tcu_clk_src", + .parent_data = gcc_xo_gpll0_gpll1_gpll2, + .num_parents = 4, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_usb_hs_system_clk[] = { + F(19200000, P_XO, 1, 0, 0), + F(57140000, P_GPLL0, 14, 0, 0), + F(69565000, P_GPLL0, 11.5, 0, 0), + F(133330000, P_GPLL0, 6, 0, 0), + F(177778000, P_GPLL0, 4.5, 0, 0), + { } +}; + +static struct clk_rcg2 usb_hs_system_clk_src = { + .cmd_rcgr = 0x41010, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_map, + .freq_tbl = ftbl_gcc_usb_hs_system_clk, + .clkr.hw.init = &(struct clk_init_data){ + .name = "usb_hs_system_clk_src", + .parent_data = gcc_xo_gpll0, + .num_parents = 2, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_usb_hsic_clk_src[] = { + F(480000000, P_GPLL2, 1, 0, 0), + { } +}; + +static struct clk_rcg2 usb_hsic_clk_src = { + .cmd_rcgr = 0x3d018, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_gpll2_map, + .freq_tbl = ftbl_usb_hsic_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "usb_hsic_clk_src", + .parent_data = gcc_xo_gpll0_gpll2, + .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll2), + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_usb_hsic_io_cal_clk_src[] = { + F(9600000, P_XO, 2, 0, 0), + { } +}; + +static struct clk_rcg2 usb_hsic_io_cal_clk_src = { + .cmd_rcgr = 0x3d030, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_map, + .freq_tbl = ftbl_usb_hsic_io_cal_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "usb_hsic_io_cal_clk_src", + .parent_data = gcc_xo_gpll0, + .num_parents = ARRAY_SIZE(gcc_xo_gpll0), + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_usb_hsic_system_clk_src[] = { + F(19200000, P_XO, 1, 0, 0), + F(57140000, P_GPLL0, 14, 0, 0), + F(133330000, P_GPLL0, 6, 0, 0), + F(177778000, P_GPLL0, 4.5, 0, 0), + { } +}; + +static struct clk_rcg2 usb_hsic_system_clk_src = { + .cmd_rcgr = 0x3d000, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_map, + .freq_tbl = ftbl_usb_hsic_system_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "usb_hsic_system_clk_src", + .parent_data = gcc_xo_gpll0, + .num_parents = ARRAY_SIZE(gcc_xo_gpll0), + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_branch gcc_blsp1_ahb_clk = { + .halt_reg = 0x1008, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x45004, + .enable_mask = BIT(10), + .hw.init = &(struct clk_init_data){ + .name = "gcc_blsp1_ahb_clk", + .parent_hws = (const struct clk_hw *[]){ &pcnoc_bfdcd_clk_src.clkr.hw }, + .num_parents = 1, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_blsp1_sleep_clk = { + .halt_reg = 0x1004, + .clkr = { + .enable_reg = 0x1004, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_blsp1_sleep_clk", + .parent_data = &(const struct clk_parent_data){ + .fw_name = "sleep_clk", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_blsp1_qup1_i2c_apps_clk = { + .halt_reg = 0x2008, + .clkr = { + .enable_reg = 0x2008, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_blsp1_qup1_i2c_apps_clk", + .parent_hws = (const struct clk_hw *[]){ &blsp1_qup1_i2c_apps_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_blsp1_qup1_spi_apps_clk = { + .halt_reg = 0x2004, + .clkr = { + .enable_reg = 0x2004, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_blsp1_qup1_spi_apps_clk", + .parent_hws = (const struct clk_hw *[]){ &blsp1_qup1_spi_apps_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_blsp1_qup2_i2c_apps_clk = { + .halt_reg = 0x3010, + .clkr = { + .enable_reg = 0x3010, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_blsp1_qup2_i2c_apps_clk", + .parent_hws = (const struct clk_hw *[]){ &blsp1_qup2_i2c_apps_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_blsp1_qup2_spi_apps_clk = { + .halt_reg = 0x300c, + .clkr = { + .enable_reg = 0x300c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_blsp1_qup2_spi_apps_clk", + .parent_hws = (const struct clk_hw *[]){ &blsp1_qup2_spi_apps_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_blsp1_qup3_i2c_apps_clk = { + .halt_reg = 0x4020, + .clkr = { + .enable_reg = 0x4020, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_blsp1_qup3_i2c_apps_clk", + .parent_hws = (const struct clk_hw *[]){ &blsp1_qup3_i2c_apps_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_blsp1_qup3_spi_apps_clk = { + .halt_reg = 0x401c, + .clkr = { + .enable_reg = 0x401c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_blsp1_qup3_spi_apps_clk", + .parent_hws = (const struct clk_hw *[]){ &blsp1_qup3_spi_apps_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_blsp1_qup4_i2c_apps_clk = { + .halt_reg = 0x5020, + .clkr = { + .enable_reg = 0x5020, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_blsp1_qup4_i2c_apps_clk", + .parent_hws = (const struct clk_hw *[]){ &blsp1_qup4_i2c_apps_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_blsp1_qup4_spi_apps_clk = { + .halt_reg = 0x501c, + .clkr = { + .enable_reg = 0x501c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_blsp1_qup4_spi_apps_clk", + .parent_hws = (const struct clk_hw *[]){ &blsp1_qup4_spi_apps_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_blsp1_qup5_i2c_apps_clk = { + .halt_reg = 0x6020, + .clkr = { + .enable_reg = 0x6020, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_blsp1_qup5_i2c_apps_clk", + .parent_hws = (const struct clk_hw *[]){ &blsp1_qup5_i2c_apps_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_blsp1_qup5_spi_apps_clk = { + .halt_reg = 0x601c, + .clkr = { + .enable_reg = 0x601c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_blsp1_qup5_spi_apps_clk", + .parent_hws = (const struct clk_hw *[]){ &blsp1_qup5_spi_apps_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_blsp1_qup6_i2c_apps_clk = { + .halt_reg = 0x7020, + .clkr = { + .enable_reg = 0x7020, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_blsp1_qup6_i2c_apps_clk", + .parent_hws = (const struct clk_hw *[]){ &blsp1_qup6_i2c_apps_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_blsp1_qup6_spi_apps_clk = { + .halt_reg = 0x701c, + .clkr = { + .enable_reg = 0x701c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_blsp1_qup6_spi_apps_clk", + .parent_hws = (const struct clk_hw *[]){ &blsp1_qup6_spi_apps_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_blsp1_uart1_apps_clk = { + .halt_reg = 0x203c, + .clkr = { + .enable_reg = 0x203c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_blsp1_uart1_apps_clk", + .parent_hws = (const struct clk_hw *[]){ &blsp1_uart1_apps_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_blsp1_uart2_apps_clk = { + .halt_reg = 0x302c, + .clkr = { + .enable_reg = 0x302c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_blsp1_uart2_apps_clk", + .parent_hws = (const struct clk_hw *[]){ &blsp1_uart2_apps_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_blsp1_uart3_apps_clk = { + .halt_reg = 0x403c, + .clkr = { + .enable_reg = 0x403c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_blsp1_uart3_apps_clk", + .parent_hws = (const struct clk_hw *[]){ &blsp1_uart3_apps_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_blsp1_uart4_apps_clk = { + .halt_reg = 0x503c, + .clkr = { + .enable_reg = 0x503c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_blsp1_uart4_apps_clk", + .parent_hws = (const struct clk_hw *[]){ &blsp1_uart4_apps_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_blsp1_uart5_apps_clk = { + .halt_reg = 0x603c, + .clkr = { + .enable_reg = 0x603c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_blsp1_uart5_apps_clk", + .parent_hws = (const struct clk_hw *[]){ &blsp1_uart5_apps_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_blsp1_uart6_apps_clk = { + .halt_reg = 0x703c, + .clkr = { + .enable_reg = 0x703c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_blsp1_uart6_apps_clk", + .parent_hws = (const struct clk_hw *[]){ &blsp1_uart6_apps_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_boot_rom_ahb_clk = { + .halt_reg = 0x1300c, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x45004, + .enable_mask = BIT(7), + .hw.init = &(struct clk_init_data){ + .name = "gcc_boot_rom_ahb_clk", + .parent_hws = (const struct clk_hw *[]){ &pcnoc_bfdcd_clk_src.clkr.hw }, + .num_parents = 1, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_crypto_ahb_clk = { + .halt_reg = 0x16024, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x45004, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_crypto_ahb_clk", + .parent_hws = (const struct clk_hw *[]){ &pcnoc_bfdcd_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_crypto_axi_clk = { + .halt_reg = 0x16020, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x45004, + .enable_mask = BIT(1), + .hw.init = &(struct clk_init_data){ + .name = "gcc_crypto_axi_clk", + .parent_hws = (const struct clk_hw *[]){ &pcnoc_bfdcd_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_crypto_clk = { + .halt_reg = 0x1601c, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x45004, + .enable_mask = BIT(2), + .hw.init = &(struct clk_init_data){ + .name = "gcc_crypto_clk", + .parent_hws = (const struct clk_hw *[]){ &crypto_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_gp1_clk = { + .halt_reg = 0x08000, + .clkr = { + .enable_reg = 0x08000, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_gp1_clk", + .parent_hws = (const struct clk_hw *[]){ &gp1_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_gp2_clk = { + .halt_reg = 0x09000, + .clkr = { + .enable_reg = 0x09000, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_gp2_clk", + .parent_hws = (const struct clk_hw *[]){ &gp2_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_gp3_clk = { + .halt_reg = 0x0a000, + .clkr = { + .enable_reg = 0x0a000, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_gp3_clk", + .parent_hws = (const struct clk_hw *[]){ &gp3_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_mss_cfg_ahb_clk = { + .halt_reg = 0x49000, + .clkr = { + .enable_reg = 0x49000, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_mss_cfg_ahb_clk", + .parent_hws = (const struct clk_hw *[]){ &pcnoc_bfdcd_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pdm2_clk = { + .halt_reg = 0x4400c, + .clkr = { + .enable_reg = 0x4400c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_pdm2_clk", + .parent_hws = (const struct clk_hw *[]){ &pdm2_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pdm_ahb_clk = { + .halt_reg = 0x44004, + .clkr = { + .enable_reg = 0x44004, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_pdm_ahb_clk", + .parent_hws = (const struct clk_hw *[]){ &pcnoc_bfdcd_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_prng_ahb_clk = { + .halt_reg = 0x13004, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x45004, + .enable_mask = BIT(8), + .hw.init = &(struct clk_init_data){ + .name = "gcc_prng_ahb_clk", + .parent_hws = (const struct clk_hw *[]){ &pcnoc_bfdcd_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_sdcc1_ahb_clk = { + .halt_reg = 0x4201c, + .clkr = { + .enable_reg = 0x4201c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_sdcc1_ahb_clk", + .parent_hws = (const struct clk_hw *[]){ &pcnoc_bfdcd_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_sdcc1_apps_clk = { + .halt_reg = 0x42018, + .clkr = { + .enable_reg = 0x42018, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_sdcc1_apps_clk", + .parent_hws = (const struct clk_hw *[]){ &sdcc1_apps_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_sdcc2_ahb_clk = { + .halt_reg = 0x4301c, + .clkr = { + .enable_reg = 0x4301c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_sdcc2_ahb_clk", + .parent_hws = (const struct clk_hw *[]){ &pcnoc_bfdcd_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_sdcc2_apps_clk = { + .halt_reg = 0x43018, + .clkr = { + .enable_reg = 0x43018, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_sdcc2_apps_clk", + .parent_hws = (const struct clk_hw *[]){ &sdcc2_apps_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_rcg2 bimc_ddr_clk_src = { + .cmd_rcgr = 0x32004, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_bimc_map, + .clkr.hw.init = &(struct clk_init_data){ + .name = "bimc_ddr_clk_src", + .parent_data = gcc_xo_gpll0_bimc, + .num_parents = 3, + .ops = &clk_rcg2_ops, + .flags = CLK_GET_RATE_NOCACHE, + }, +}; + +static struct clk_branch gcc_mss_q6_bimc_axi_clk = { + .halt_reg = 0x49004, + .clkr = { + .enable_reg = 0x49004, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_mss_q6_bimc_axi_clk", + .parent_hws = (const struct clk_hw *[]){ &bimc_ddr_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_apss_tcu_clk = { + .halt_reg = 0x12018, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x4500c, + .enable_mask = BIT(1), + .hw.init = &(struct clk_init_data){ + .name = "gcc_apss_tcu_clk", + .parent_hws = (const struct clk_hw *[]){ &bimc_ddr_clk_src.clkr.hw }, + .num_parents = 1, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_smmu_cfg_clk = { + .halt_reg = 0x12038, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x4500c, + .enable_mask = BIT(12), + .hw.init = &(struct clk_init_data){ + .name = "gcc_smmu_cfg_clk", + .parent_hws = (const struct clk_hw *[]){ &pcnoc_bfdcd_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qdss_dap_clk = { + .halt_reg = 0x29084, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x45004, + .enable_mask = BIT(19), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qdss_dap_clk", + .parent_data = &(const struct clk_parent_data){ + .fw_name = "xo", + }, + .num_parents = 1, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb2a_phy_sleep_clk = { + .halt_reg = 0x4102c, + .clkr = { + .enable_reg = 0x4102c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_usb2a_phy_sleep_clk", + .parent_data = &(const struct clk_parent_data){ + .fw_name = "sleep_clk", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb_hs_phy_cfg_ahb_clk = { + .halt_reg = 0x41030, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x41030, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_usb_hs_phy_cfg_ahb_clk", + .parent_hws = (const struct clk_hw *[]){ &pcnoc_bfdcd_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb_hs_ahb_clk = { + .halt_reg = 0x41008, + .clkr = { + .enable_reg = 0x41008, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_usb_hs_ahb_clk", + .parent_hws = (const struct clk_hw *[]){ &pcnoc_bfdcd_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb_hs_system_clk = { + .halt_reg = 0x41004, + .clkr = { + .enable_reg = 0x41004, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_usb_hs_system_clk", + .parent_hws = (const struct clk_hw *[]){ &usb_hs_system_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_apss_ahb_clk = { + .halt_reg = 0x4601c, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x45004, + .enable_mask = BIT(14), + .hw.init = &(struct clk_init_data){ + .name = "gcc_apss_ahb_clk", + .parent_hws = (const struct clk_hw *[]){ &pcnoc_bfdcd_clk_src.clkr.hw }, + .num_parents = 1, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_apss_axi_clk = { + .halt_reg = 0x4601c, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x45004, + .enable_mask = BIT(13), + .hw.init = &(struct clk_init_data){ + .name = "gcc_apss_axi_clk", + .parent_hws = (const struct clk_hw *[]){ &pcnoc_bfdcd_clk_src.clkr.hw }, + .num_parents = 1, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_regmap *gcc_mdm9607_clocks[] = { + [GPLL0] = &gpll0.clkr, + [GPLL0_EARLY] = &gpll0_early.clkr, + [GPLL1] = &gpll1.clkr, + [GPLL1_VOTE] = &gpll1_vote, + [GPLL2] = &gpll2.clkr, + [GPLL2_EARLY] = &gpll2_early.clkr, + [BIMC_PLL] = &bimc_pll.clkr, + [BIMC_PLL_VOTE] = &bimc_pll_vote, + [BIMC_DDR_CLK_SRC] = &bimc_ddr_clk_src.clkr, + [PCNOC_BFDCD_CLK_SRC] = &pcnoc_bfdcd_clk_src.clkr, + [SYSTEM_NOC_BFDCD_CLK_SRC] = &system_noc_bfdcd_clk_src.clkr, + [APSS_AHB_CLK_SRC] = &apss_ahb_clk_src.clkr, + [BLSP1_QUP1_I2C_APPS_CLK_SRC] = &blsp1_qup1_i2c_apps_clk_src.clkr, + [BLSP1_QUP1_SPI_APPS_CLK_SRC] = &blsp1_qup1_spi_apps_clk_src.clkr, + [BLSP1_QUP2_I2C_APPS_CLK_SRC] = &blsp1_qup2_i2c_apps_clk_src.clkr, + [BLSP1_QUP2_SPI_APPS_CLK_SRC] = &blsp1_qup2_spi_apps_clk_src.clkr, + [BLSP1_QUP3_I2C_APPS_CLK_SRC] = &blsp1_qup3_i2c_apps_clk_src.clkr, + [BLSP1_QUP3_SPI_APPS_CLK_SRC] = &blsp1_qup3_spi_apps_clk_src.clkr, + [BLSP1_QUP4_I2C_APPS_CLK_SRC] = &blsp1_qup4_i2c_apps_clk_src.clkr, + [BLSP1_QUP4_SPI_APPS_CLK_SRC] = &blsp1_qup4_spi_apps_clk_src.clkr, + [BLSP1_QUP5_I2C_APPS_CLK_SRC] = &blsp1_qup5_i2c_apps_clk_src.clkr, + [BLSP1_QUP5_SPI_APPS_CLK_SRC] = &blsp1_qup5_spi_apps_clk_src.clkr, + [BLSP1_QUP6_I2C_APPS_CLK_SRC] = &blsp1_qup6_i2c_apps_clk_src.clkr, + [BLSP1_QUP6_SPI_APPS_CLK_SRC] = &blsp1_qup6_spi_apps_clk_src.clkr, + [BLSP1_UART1_APPS_CLK_SRC] = &blsp1_uart1_apps_clk_src.clkr, + [BLSP1_UART2_APPS_CLK_SRC] = &blsp1_uart2_apps_clk_src.clkr, + [BLSP1_UART3_APPS_CLK_SRC] = &blsp1_uart3_apps_clk_src.clkr, + [BLSP1_UART4_APPS_CLK_SRC] = &blsp1_uart4_apps_clk_src.clkr, + [BLSP1_UART5_APPS_CLK_SRC] = &blsp1_uart5_apps_clk_src.clkr, + [BLSP1_UART6_APPS_CLK_SRC] = &blsp1_uart6_apps_clk_src.clkr, + [CRYPTO_CLK_SRC] = &crypto_clk_src.clkr, + [GP1_CLK_SRC] = &gp1_clk_src.clkr, + [GP2_CLK_SRC] = &gp2_clk_src.clkr, + [GP3_CLK_SRC] = &gp3_clk_src.clkr, + [PDM2_CLK_SRC] = &pdm2_clk_src.clkr, + [SDCC1_APPS_CLK_SRC] = &sdcc1_apps_clk_src.clkr, + [SDCC2_APPS_CLK_SRC] = &sdcc2_apps_clk_src.clkr, + [APSS_TCU_CLK_SRC] = &apss_tcu_clk_src.clkr, + [USB_HS_SYSTEM_CLK_SRC] = &usb_hs_system_clk_src.clkr, + [GCC_BLSP1_AHB_CLK] = &gcc_blsp1_ahb_clk.clkr, + [GCC_BLSP1_SLEEP_CLK] = &gcc_blsp1_sleep_clk.clkr, + [GCC_BLSP1_QUP1_I2C_APPS_CLK] = &gcc_blsp1_qup1_i2c_apps_clk.clkr, + [GCC_BLSP1_QUP1_SPI_APPS_CLK] = &gcc_blsp1_qup1_spi_apps_clk.clkr, + [GCC_BLSP1_QUP2_I2C_APPS_CLK] = &gcc_blsp1_qup2_i2c_apps_clk.clkr, + [GCC_BLSP1_QUP2_SPI_APPS_CLK] = &gcc_blsp1_qup2_spi_apps_clk.clkr, + [GCC_BLSP1_QUP3_I2C_APPS_CLK] = &gcc_blsp1_qup3_i2c_apps_clk.clkr, + [GCC_BLSP1_QUP3_SPI_APPS_CLK] = &gcc_blsp1_qup3_spi_apps_clk.clkr, + [GCC_BLSP1_QUP4_I2C_APPS_CLK] = &gcc_blsp1_qup4_i2c_apps_clk.clkr, + [GCC_BLSP1_QUP4_SPI_APPS_CLK] = &gcc_blsp1_qup4_spi_apps_clk.clkr, + [GCC_BLSP1_QUP5_I2C_APPS_CLK] = &gcc_blsp1_qup5_i2c_apps_clk.clkr, + [GCC_BLSP1_QUP5_SPI_APPS_CLK] = &gcc_blsp1_qup5_spi_apps_clk.clkr, + [GCC_BLSP1_QUP6_I2C_APPS_CLK] = &gcc_blsp1_qup6_i2c_apps_clk.clkr, + [GCC_BLSP1_QUP6_SPI_APPS_CLK] = &gcc_blsp1_qup6_spi_apps_clk.clkr, + [GCC_BLSP1_UART1_APPS_CLK] = &gcc_blsp1_uart1_apps_clk.clkr, + [GCC_BLSP1_UART2_APPS_CLK] = &gcc_blsp1_uart2_apps_clk.clkr, + [GCC_BLSP1_UART3_APPS_CLK] = &gcc_blsp1_uart3_apps_clk.clkr, + [GCC_BLSP1_UART4_APPS_CLK] = &gcc_blsp1_uart4_apps_clk.clkr, + [GCC_BLSP1_UART5_APPS_CLK] = &gcc_blsp1_uart5_apps_clk.clkr, + [GCC_BLSP1_UART6_APPS_CLK] = &gcc_blsp1_uart6_apps_clk.clkr, + [GCC_BOOT_ROM_AHB_CLK] = &gcc_boot_rom_ahb_clk.clkr, + [GCC_CRYPTO_AHB_CLK] = &gcc_crypto_ahb_clk.clkr, + [GCC_CRYPTO_AXI_CLK] = &gcc_crypto_axi_clk.clkr, + [GCC_CRYPTO_CLK] = &gcc_crypto_clk.clkr, + [GCC_GP1_CLK] = &gcc_gp1_clk.clkr, + [GCC_GP2_CLK] = &gcc_gp2_clk.clkr, + [GCC_GP3_CLK] = &gcc_gp3_clk.clkr, + [GCC_MSS_CFG_AHB_CLK] = &gcc_mss_cfg_ahb_clk.clkr, + [GCC_PDM2_CLK] = &gcc_pdm2_clk.clkr, + [GCC_PDM_AHB_CLK] = &gcc_pdm_ahb_clk.clkr, + [GCC_PRNG_AHB_CLK] = &gcc_prng_ahb_clk.clkr, + [GCC_SDCC1_AHB_CLK] = &gcc_sdcc1_ahb_clk.clkr, + [GCC_SDCC1_APPS_CLK] = &gcc_sdcc1_apps_clk.clkr, + [GCC_SDCC2_AHB_CLK] = &gcc_sdcc2_ahb_clk.clkr, + [GCC_SDCC2_APPS_CLK] = &gcc_sdcc2_apps_clk.clkr, + [GCC_SMMU_CFG_CLK] = &gcc_smmu_cfg_clk.clkr, + [GCC_USB2A_PHY_SLEEP_CLK] = &gcc_usb2a_phy_sleep_clk.clkr, + [GCC_USB_HS_PHY_CFG_AHB_CLK] = &gcc_usb_hs_phy_cfg_ahb_clk.clkr, + [GCC_USB_HS_AHB_CLK] = &gcc_usb_hs_ahb_clk.clkr, + [GCC_USB_HS_SYSTEM_CLK] = &gcc_usb_hs_system_clk.clkr, + [GCC_APSS_TCU_CLK] = &gcc_apss_tcu_clk.clkr, + [GCC_MSS_Q6_BIMC_AXI_CLK] = &gcc_mss_q6_bimc_axi_clk.clkr, + [GCC_QDSS_DAP_CLK] = &gcc_qdss_dap_clk.clkr, + [GCC_APSS_AHB_CLK] = &gcc_apss_ahb_clk.clkr, + [GCC_APSS_AXI_CLK] = &gcc_apss_axi_clk.clkr, + [GCC_USB_HSIC_CLK_SRC] = &usb_hsic_clk_src.clkr, + [GCC_USB_HSIC_IO_CAL_CLK_SRC] = &usb_hsic_io_cal_clk_src.clkr, + [GCC_USB_HSIC_SYSTEM_CLK_SRC] = &usb_hsic_system_clk_src.clkr, +}; + +static const struct qcom_reset_map gcc_mdm9607_resets[] = { + [USB_HS_HSIC_BCR] = { 0x3d05c }, + [GCC_MSS_RESTART] = { 0x3e000 }, + [USB_HS_BCR] = { 0x41000 }, + [USB2_HS_PHY_ONLY_BCR] = { 0x41034 }, + [QUSB2_PHY_BCR] = { 0x4103c }, +}; + +static const struct regmap_config gcc_mdm9607_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = 0x80000, + .fast_io = true, +}; + +static const struct qcom_cc_desc gcc_mdm9607_desc = { + .config = &gcc_mdm9607_regmap_config, + .clks = gcc_mdm9607_clocks, + .num_clks = ARRAY_SIZE(gcc_mdm9607_clocks), + .resets = gcc_mdm9607_resets, + .num_resets = ARRAY_SIZE(gcc_mdm9607_resets), +}; + +static const struct of_device_id gcc_mdm9607_match_table[] = { + { .compatible = "qcom,gcc-mdm9607" }, + { } +}; +MODULE_DEVICE_TABLE(of, gcc_mdm9607_match_table); + +static int gcc_mdm9607_probe(struct platform_device *pdev) +{ + struct regmap *regmap; + + regmap = qcom_cc_map(pdev, &gcc_mdm9607_desc); + if (IS_ERR(regmap)) + return PTR_ERR(regmap); + + /* Vote for GPLL0 to turn on. Needed by acpuclock. */ + regmap_update_bits(regmap, 0x45000, BIT(0), BIT(0)); + + return qcom_cc_really_probe(pdev, &gcc_mdm9607_desc, regmap); +} + +static struct platform_driver gcc_mdm9607_driver = { + .probe = gcc_mdm9607_probe, + .driver = { + .name = "gcc-mdm9607", + .of_match_table = gcc_mdm9607_match_table, + }, +}; + +static int __init gcc_mdm9607_init(void) +{ + return platform_driver_register(&gcc_mdm9607_driver); +} +core_initcall(gcc_mdm9607_init); + +static void __exit gcc_mdm9607_exit(void) +{ + platform_driver_unregister(&gcc_mdm9607_driver); +} +module_exit(gcc_mdm9607_exit); + +MODULE_DESCRIPTION("Qualcomm GCC mdm9607 Driver"); +MODULE_LICENSE("GPL v2"); From 52a436e0b7fe00e3f23fa8a7c757ee7a6fbcf3e9 Mon Sep 17 00:00:00 2001 From: Konrad Dybcio Date: Tue, 25 May 2021 00:54:55 +0200 Subject: [PATCH 043/161] clk: qcom: smd-rpm: Switch to parent_data Switch to parent_data and with that fix the longstanding issue where if there wasn't a clock precisely named "xo_board", rpmcc would not play along well. This started to show lately when "xo_board" was being changed to "xo-board" so as to align with DTS naming spec. Signed-off-by: Konrad Dybcio Link: https://lore.kernel.org/r/20210524225456.398817-1-konrad.dybcio@somainline.org Signed-off-by: Stephen Boyd --- drivers/clk/qcom/clk-smd-rpm.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/drivers/clk/qcom/clk-smd-rpm.c b/drivers/clk/qcom/clk-smd-rpm.c index 0e1dfa89489e..9204aae1867e 100644 --- a/drivers/clk/qcom/clk-smd-rpm.c +++ b/drivers/clk/qcom/clk-smd-rpm.c @@ -39,7 +39,10 @@ .hw.init = &(struct clk_init_data){ \ .ops = &clk_smd_rpm_ops, \ .name = #_name, \ - .parent_names = (const char *[]){ "xo_board" }, \ + .parent_data = &(const struct clk_parent_data){ \ + .fw_name = "xo", \ + .name = "xo_board", \ + }, \ .num_parents = 1, \ }, \ }; \ @@ -54,7 +57,10 @@ .hw.init = &(struct clk_init_data){ \ .ops = &clk_smd_rpm_ops, \ .name = #_active, \ - .parent_names = (const char *[]){ "xo_board" }, \ + .parent_data = &(const struct clk_parent_data){ \ + .fw_name = "xo", \ + .name = "xo_board", \ + }, \ .num_parents = 1, \ }, \ } @@ -73,7 +79,10 @@ .hw.init = &(struct clk_init_data){ \ .ops = &clk_smd_rpm_branch_ops, \ .name = #_name, \ - .parent_names = (const char *[]){ "xo_board" }, \ + .parent_data = &(const struct clk_parent_data){ \ + .fw_name = "xo", \ + .name = "xo_board", \ + }, \ .num_parents = 1, \ }, \ }; \ @@ -89,7 +98,10 @@ .hw.init = &(struct clk_init_data){ \ .ops = &clk_smd_rpm_branch_ops, \ .name = #_active, \ - .parent_names = (const char *[]){ "xo_board" }, \ + .parent_data = &(const struct clk_parent_data){ \ + .fw_name = "xo", \ + .name = "xo_board", \ + }, \ .num_parents = 1, \ }, \ } From a0384ecfe2aa8f3da7a845dbe9e13c8d38e14ffd Mon Sep 17 00:00:00 2001 From: Konrad Dybcio Date: Tue, 25 May 2021 00:54:56 +0200 Subject: [PATCH 044/161] clk: qcom: smd-rpm: De-duplicate identical entries It makes negative sense to keep repeating the same definitions over and over and over and over again, just with changed names.. De-duplicate to make for a drastically smaller file size. This makes the object file size 55% smaller according to bloat-o-meter: Total: Before=70713, After=31353, chg -55.66% Signed-off-by: Konrad Dybcio Link: https://lore.kernel.org/r/20210524225456.398817-2-konrad.dybcio@somainline.org Signed-off-by: Stephen Boyd --- drivers/clk/qcom/clk-smd-rpm.c | 652 +++++++++++++-------------------- 1 file changed, 247 insertions(+), 405 deletions(-) diff --git a/drivers/clk/qcom/clk-smd-rpm.c b/drivers/clk/qcom/clk-smd-rpm.c index 9204aae1867e..295fc08eddb9 100644 --- a/drivers/clk/qcom/clk-smd-rpm.c +++ b/drivers/clk/qcom/clk-smd-rpm.c @@ -418,7 +418,6 @@ static const struct clk_ops clk_smd_rpm_branch_ops = { .unprepare = clk_smd_rpm_unprepare, }; -/* msm8916 */ DEFINE_CLK_SMD_RPM(msm8916, pcnoc_clk, pcnoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 0); DEFINE_CLK_SMD_RPM(msm8916, snoc_clk, snoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 1); DEFINE_CLK_SMD_RPM(msm8916, bimc_clk, bimc_a_clk, QCOM_SMD_RPM_MEM_CLK, 0); @@ -464,48 +463,35 @@ static const struct rpm_smd_clk_desc rpm_clk_msm8916 = { .num_clks = ARRAY_SIZE(msm8916_clks), }; -/* msm8936 */ -DEFINE_CLK_SMD_RPM(msm8936, pcnoc_clk, pcnoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 0); -DEFINE_CLK_SMD_RPM(msm8936, snoc_clk, snoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 1); -DEFINE_CLK_SMD_RPM(msm8936, bimc_clk, bimc_a_clk, QCOM_SMD_RPM_MEM_CLK, 0); DEFINE_CLK_SMD_RPM(msm8936, sysmmnoc_clk, sysmmnoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 2); -DEFINE_CLK_SMD_RPM_QDSS(msm8936, qdss_clk, qdss_a_clk, QCOM_SMD_RPM_MISC_CLK, 1); -DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8936, bb_clk1, bb_clk1_a, 1); -DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8936, bb_clk2, bb_clk2_a, 2); -DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8936, rf_clk1, rf_clk1_a, 4); -DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8936, rf_clk2, rf_clk2_a, 5); -DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8936, bb_clk1_pin, bb_clk1_a_pin, 1); -DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8936, bb_clk2_pin, bb_clk2_a_pin, 2); -DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8936, rf_clk1_pin, rf_clk1_a_pin, 4); -DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8936, rf_clk2_pin, rf_clk2_a_pin, 5); static struct clk_smd_rpm *msm8936_clks[] = { - [RPM_SMD_PCNOC_CLK] = &msm8936_pcnoc_clk, - [RPM_SMD_PCNOC_A_CLK] = &msm8936_pcnoc_a_clk, - [RPM_SMD_SNOC_CLK] = &msm8936_snoc_clk, - [RPM_SMD_SNOC_A_CLK] = &msm8936_snoc_a_clk, - [RPM_SMD_BIMC_CLK] = &msm8936_bimc_clk, - [RPM_SMD_BIMC_A_CLK] = &msm8936_bimc_a_clk, + [RPM_SMD_PCNOC_CLK] = &msm8916_pcnoc_clk, + [RPM_SMD_PCNOC_A_CLK] = &msm8916_pcnoc_clk, + [RPM_SMD_SNOC_CLK] = &msm8916_snoc_clk, + [RPM_SMD_SNOC_A_CLK] = &msm8916_snoc_a_clk, + [RPM_SMD_BIMC_CLK] = &msm8916_bimc_clk, + [RPM_SMD_BIMC_A_CLK] = &msm8916_bimc_a_clk, [RPM_SMD_SYSMMNOC_CLK] = &msm8936_sysmmnoc_clk, [RPM_SMD_SYSMMNOC_A_CLK] = &msm8936_sysmmnoc_a_clk, - [RPM_SMD_QDSS_CLK] = &msm8936_qdss_clk, - [RPM_SMD_QDSS_A_CLK] = &msm8936_qdss_a_clk, - [RPM_SMD_BB_CLK1] = &msm8936_bb_clk1, - [RPM_SMD_BB_CLK1_A] = &msm8936_bb_clk1_a, - [RPM_SMD_BB_CLK2] = &msm8936_bb_clk2, - [RPM_SMD_BB_CLK2_A] = &msm8936_bb_clk2_a, - [RPM_SMD_RF_CLK1] = &msm8936_rf_clk1, - [RPM_SMD_RF_CLK1_A] = &msm8936_rf_clk1_a, - [RPM_SMD_RF_CLK2] = &msm8936_rf_clk2, - [RPM_SMD_RF_CLK2_A] = &msm8936_rf_clk2_a, - [RPM_SMD_BB_CLK1_PIN] = &msm8936_bb_clk1_pin, - [RPM_SMD_BB_CLK1_A_PIN] = &msm8936_bb_clk1_a_pin, - [RPM_SMD_BB_CLK2_PIN] = &msm8936_bb_clk2_pin, - [RPM_SMD_BB_CLK2_A_PIN] = &msm8936_bb_clk2_a_pin, - [RPM_SMD_RF_CLK1_PIN] = &msm8936_rf_clk1_pin, - [RPM_SMD_RF_CLK1_A_PIN] = &msm8936_rf_clk1_a_pin, - [RPM_SMD_RF_CLK2_PIN] = &msm8936_rf_clk2_pin, - [RPM_SMD_RF_CLK2_A_PIN] = &msm8936_rf_clk2_a_pin, + [RPM_SMD_QDSS_CLK] = &msm8916_qdss_clk, + [RPM_SMD_QDSS_A_CLK] = &msm8916_qdss_a_clk, + [RPM_SMD_BB_CLK1] = &msm8916_bb_clk1, + [RPM_SMD_BB_CLK1_A] = &msm8916_bb_clk1_a, + [RPM_SMD_BB_CLK2] = &msm8916_bb_clk2, + [RPM_SMD_BB_CLK2_A] = &msm8916_bb_clk2_a, + [RPM_SMD_RF_CLK1] = &msm8916_rf_clk1, + [RPM_SMD_RF_CLK1_A] = &msm8916_rf_clk1_a, + [RPM_SMD_RF_CLK2] = &msm8916_rf_clk2, + [RPM_SMD_RF_CLK2_A] = &msm8916_rf_clk2_a, + [RPM_SMD_BB_CLK1_PIN] = &msm8916_bb_clk1_pin, + [RPM_SMD_BB_CLK1_A_PIN] = &msm8916_bb_clk1_a_pin, + [RPM_SMD_BB_CLK2_PIN] = &msm8916_bb_clk2_pin, + [RPM_SMD_BB_CLK2_A_PIN] = &msm8916_bb_clk2_a_pin, + [RPM_SMD_RF_CLK1_PIN] = &msm8916_rf_clk1_pin, + [RPM_SMD_RF_CLK1_A_PIN] = &msm8916_rf_clk1_a_pin, + [RPM_SMD_RF_CLK2_PIN] = &msm8916_rf_clk2_pin, + [RPM_SMD_RF_CLK2_A_PIN] = &msm8916_rf_clk2_a_pin, }; static const struct rpm_smd_clk_desc rpm_clk_msm8936 = { @@ -513,15 +499,10 @@ static const struct rpm_smd_clk_desc rpm_clk_msm8936 = { .num_clks = ARRAY_SIZE(msm8936_clks), }; -/* msm8974 */ -DEFINE_CLK_SMD_RPM(msm8974, pnoc_clk, pnoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 0); -DEFINE_CLK_SMD_RPM(msm8974, snoc_clk, snoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 1); DEFINE_CLK_SMD_RPM(msm8974, cnoc_clk, cnoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 2); DEFINE_CLK_SMD_RPM(msm8974, mmssnoc_ahb_clk, mmssnoc_ahb_a_clk, QCOM_SMD_RPM_BUS_CLK, 3); -DEFINE_CLK_SMD_RPM(msm8974, bimc_clk, bimc_a_clk, QCOM_SMD_RPM_MEM_CLK, 0); DEFINE_CLK_SMD_RPM(msm8974, gfx3d_clk_src, gfx3d_a_clk_src, QCOM_SMD_RPM_MEM_CLK, 1); DEFINE_CLK_SMD_RPM(msm8974, ocmemgx_clk, ocmemgx_a_clk, QCOM_SMD_RPM_MEM_CLK, 2); -DEFINE_CLK_SMD_RPM_QDSS(msm8974, qdss_clk, qdss_a_clk, QCOM_SMD_RPM_MISC_CLK, 1); DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8974, cxo_d0, cxo_d0_a, 1); DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8974, cxo_d1, cxo_d1_a, 2); DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8974, cxo_a0, cxo_a0_a, 4); @@ -537,22 +518,22 @@ DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8974, cxo_a1_pin, cxo_a1_a_pin, 5); DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8974, cxo_a2_pin, cxo_a2_a_pin, 6); static struct clk_smd_rpm *msm8974_clks[] = { - [RPM_SMD_PNOC_CLK] = &msm8974_pnoc_clk, - [RPM_SMD_PNOC_A_CLK] = &msm8974_pnoc_a_clk, - [RPM_SMD_SNOC_CLK] = &msm8974_snoc_clk, - [RPM_SMD_SNOC_A_CLK] = &msm8974_snoc_a_clk, + [RPM_SMD_PNOC_CLK] = &msm8916_pcnoc_a_clk, + [RPM_SMD_PNOC_A_CLK] = &msm8916_pcnoc_a_clk, + [RPM_SMD_SNOC_CLK] = &msm8916_snoc_clk, + [RPM_SMD_SNOC_A_CLK] = &msm8916_snoc_a_clk, [RPM_SMD_CNOC_CLK] = &msm8974_cnoc_clk, [RPM_SMD_CNOC_A_CLK] = &msm8974_cnoc_a_clk, [RPM_SMD_MMSSNOC_AHB_CLK] = &msm8974_mmssnoc_ahb_clk, [RPM_SMD_MMSSNOC_AHB_A_CLK] = &msm8974_mmssnoc_ahb_a_clk, - [RPM_SMD_BIMC_CLK] = &msm8974_bimc_clk, + [RPM_SMD_BIMC_CLK] = &msm8916_bimc_clk, [RPM_SMD_GFX3D_CLK_SRC] = &msm8974_gfx3d_clk_src, [RPM_SMD_GFX3D_A_CLK_SRC] = &msm8974_gfx3d_a_clk_src, - [RPM_SMD_BIMC_A_CLK] = &msm8974_bimc_a_clk, + [RPM_SMD_BIMC_A_CLK] = &msm8916_bimc_a_clk, [RPM_SMD_OCMEMGX_CLK] = &msm8974_ocmemgx_clk, [RPM_SMD_OCMEMGX_A_CLK] = &msm8974_ocmemgx_a_clk, - [RPM_SMD_QDSS_CLK] = &msm8974_qdss_clk, - [RPM_SMD_QDSS_A_CLK] = &msm8974_qdss_a_clk, + [RPM_SMD_QDSS_CLK] = &msm8916_qdss_clk, + [RPM_SMD_QDSS_A_CLK] = &msm8916_qdss_a_clk, [RPM_SMD_CXO_D0] = &msm8974_cxo_d0, [RPM_SMD_CXO_D0_A] = &msm8974_cxo_d0_a, [RPM_SMD_CXO_D1] = &msm8974_cxo_d1, @@ -586,46 +567,33 @@ static const struct rpm_smd_clk_desc rpm_clk_msm8974 = { .num_clks = ARRAY_SIZE(msm8974_clks), }; - -/* msm8976 */ -DEFINE_CLK_SMD_RPM(msm8976, pcnoc_clk, pcnoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 0); -DEFINE_CLK_SMD_RPM(msm8976, snoc_clk, snoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 1); DEFINE_CLK_SMD_RPM(msm8976, mmssnoc_ahb_clk, mmssnoc_ahb_a_clk, QCOM_SMD_RPM_BUS_CLK, 2); -DEFINE_CLK_SMD_RPM(msm8976, bimc_clk, bimc_a_clk, QCOM_SMD_RPM_MEM_CLK, 0); DEFINE_CLK_SMD_RPM(msm8976, ipa_clk, ipa_a_clk, QCOM_SMD_RPM_IPA_CLK, 0); -DEFINE_CLK_SMD_RPM_QDSS(msm8976, qdss_clk, qdss_a_clk, - QCOM_SMD_RPM_MISC_CLK, 1); -DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8976, bb_clk1, bb_clk1_a, 1); -DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8976, bb_clk2, bb_clk2_a, 2); -DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8976, rf_clk2, rf_clk2_a, 5); -DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8976, div_clk2, div_clk2_a, 12); -DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8976, bb_clk1_pin, bb_clk1_a_pin, 1); -DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8976, bb_clk2_pin, bb_clk2_a_pin, 2); static struct clk_smd_rpm *msm8976_clks[] = { - [RPM_SMD_PCNOC_CLK] = &msm8976_pcnoc_clk, - [RPM_SMD_PCNOC_A_CLK] = &msm8976_pcnoc_a_clk, - [RPM_SMD_SNOC_CLK] = &msm8976_snoc_clk, - [RPM_SMD_SNOC_A_CLK] = &msm8976_snoc_a_clk, - [RPM_SMD_BIMC_CLK] = &msm8976_bimc_clk, - [RPM_SMD_BIMC_A_CLK] = &msm8976_bimc_a_clk, - [RPM_SMD_QDSS_CLK] = &msm8976_qdss_clk, - [RPM_SMD_QDSS_A_CLK] = &msm8976_qdss_a_clk, - [RPM_SMD_BB_CLK1] = &msm8976_bb_clk1, - [RPM_SMD_BB_CLK1_A] = &msm8976_bb_clk1_a, - [RPM_SMD_BB_CLK2] = &msm8976_bb_clk2, - [RPM_SMD_BB_CLK2_A] = &msm8976_bb_clk2_a, - [RPM_SMD_RF_CLK2] = &msm8976_rf_clk2, - [RPM_SMD_RF_CLK2_A] = &msm8976_rf_clk2_a, - [RPM_SMD_BB_CLK1_PIN] = &msm8976_bb_clk1_pin, - [RPM_SMD_BB_CLK1_A_PIN] = &msm8976_bb_clk1_a_pin, - [RPM_SMD_BB_CLK2_PIN] = &msm8976_bb_clk2_pin, - [RPM_SMD_BB_CLK2_A_PIN] = &msm8976_bb_clk2_a_pin, + [RPM_SMD_PCNOC_CLK] = &msm8916_pcnoc_clk, + [RPM_SMD_PCNOC_A_CLK] = &msm8916_pcnoc_a_clk, + [RPM_SMD_SNOC_CLK] = &msm8916_snoc_clk, + [RPM_SMD_SNOC_A_CLK] = &msm8916_snoc_a_clk, + [RPM_SMD_BIMC_CLK] = &msm8916_bimc_clk, + [RPM_SMD_BIMC_A_CLK] = &msm8916_bimc_a_clk, + [RPM_SMD_QDSS_CLK] = &msm8916_qdss_clk, + [RPM_SMD_QDSS_A_CLK] = &msm8916_qdss_a_clk, + [RPM_SMD_BB_CLK1] = &msm8916_bb_clk1, + [RPM_SMD_BB_CLK1_A] = &msm8916_bb_clk1_a, + [RPM_SMD_BB_CLK2] = &msm8916_bb_clk2, + [RPM_SMD_BB_CLK2_A] = &msm8916_bb_clk2_a, + [RPM_SMD_RF_CLK2] = &msm8916_rf_clk2, + [RPM_SMD_RF_CLK2_A] = &msm8916_rf_clk2_a, + [RPM_SMD_BB_CLK1_PIN] = &msm8916_bb_clk1_pin, + [RPM_SMD_BB_CLK1_A_PIN] = &msm8916_bb_clk1_a_pin, + [RPM_SMD_BB_CLK2_PIN] = &msm8916_bb_clk2_pin, + [RPM_SMD_BB_CLK2_A_PIN] = &msm8916_bb_clk2_a_pin, [RPM_SMD_MMSSNOC_AHB_CLK] = &msm8976_mmssnoc_ahb_clk, [RPM_SMD_MMSSNOC_AHB_A_CLK] = &msm8976_mmssnoc_ahb_a_clk, - [RPM_SMD_DIV_CLK2] = &msm8976_div_clk2, - [RPM_SMD_DIV_A_CLK2] = &msm8976_div_clk2_a, + [RPM_SMD_DIV_CLK2] = &msm8974_div_clk2, + [RPM_SMD_DIV_A_CLK2] = &msm8974_div_a_clk2, [RPM_SMD_IPA_CLK] = &msm8976_ipa_clk, [RPM_SMD_IPA_A_CLK] = &msm8976_ipa_a_clk, }; @@ -635,78 +603,55 @@ static const struct rpm_smd_clk_desc rpm_clk_msm8976 = { .num_clks = ARRAY_SIZE(msm8976_clks), }; -/* msm8992 */ -DEFINE_CLK_SMD_RPM(msm8992, pnoc_clk, pnoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 0); -DEFINE_CLK_SMD_RPM(msm8992, ocmemgx_clk, ocmemgx_a_clk, QCOM_SMD_RPM_MEM_CLK, 2); -DEFINE_CLK_SMD_RPM(msm8992, bimc_clk, bimc_a_clk, QCOM_SMD_RPM_MEM_CLK, 0); -DEFINE_CLK_SMD_RPM(msm8992, cnoc_clk, cnoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 2); -DEFINE_CLK_SMD_RPM(msm8992, gfx3d_clk_src, gfx3d_a_clk_src, QCOM_SMD_RPM_MEM_CLK, 1); -DEFINE_CLK_SMD_RPM(msm8992, snoc_clk, snoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 1); -DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8992, bb_clk1, bb_clk1_a, 1); -DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8992, bb_clk1_pin, bb_clk1_a_pin, 1); -DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8992, bb_clk2, bb_clk2_a, 2); -DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8992, bb_clk2_pin, bb_clk2_a_pin, 2); - -DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8992, div_clk1, div_clk1_a, 11); -DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8992, div_clk2, div_clk2_a, 12); DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8992, div_clk3, div_clk3_a, 13); -DEFINE_CLK_SMD_RPM(msm8992, ipa_clk, ipa_a_clk, QCOM_SMD_RPM_IPA_CLK, 0); DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8992, ln_bb_clk, ln_bb_a_clk, 8); -DEFINE_CLK_SMD_RPM(msm8992, mmssnoc_ahb_clk, mmssnoc_ahb_a_clk, - QCOM_SMD_RPM_BUS_CLK, 3); -DEFINE_CLK_SMD_RPM_QDSS(msm8992, qdss_clk, qdss_a_clk, - QCOM_SMD_RPM_MISC_CLK, 1); -DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8992, rf_clk1, rf_clk1_a, 4); -DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8992, rf_clk2, rf_clk2_a, 5); -DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8992, rf_clk1_pin, rf_clk1_a_pin, 4); -DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8992, rf_clk2_pin, rf_clk2_a_pin, 5); DEFINE_CLK_SMD_RPM(msm8992, ce1_clk, ce1_a_clk, QCOM_SMD_RPM_CE_CLK, 0); DEFINE_CLK_SMD_RPM(msm8992, ce2_clk, ce2_a_clk, QCOM_SMD_RPM_CE_CLK, 1); static struct clk_smd_rpm *msm8992_clks[] = { - [RPM_SMD_PNOC_CLK] = &msm8992_pnoc_clk, - [RPM_SMD_PNOC_A_CLK] = &msm8992_pnoc_a_clk, - [RPM_SMD_OCMEMGX_CLK] = &msm8992_ocmemgx_clk, - [RPM_SMD_OCMEMGX_A_CLK] = &msm8992_ocmemgx_a_clk, - [RPM_SMD_BIMC_CLK] = &msm8992_bimc_clk, - [RPM_SMD_BIMC_A_CLK] = &msm8992_bimc_a_clk, - [RPM_SMD_CNOC_CLK] = &msm8992_cnoc_clk, - [RPM_SMD_CNOC_A_CLK] = &msm8992_cnoc_a_clk, - [RPM_SMD_GFX3D_CLK_SRC] = &msm8992_gfx3d_clk_src, - [RPM_SMD_GFX3D_A_CLK_SRC] = &msm8992_gfx3d_a_clk_src, - [RPM_SMD_SNOC_CLK] = &msm8992_snoc_clk, - [RPM_SMD_SNOC_A_CLK] = &msm8992_snoc_a_clk, - [RPM_SMD_BB_CLK1] = &msm8992_bb_clk1, - [RPM_SMD_BB_CLK1_A] = &msm8992_bb_clk1_a, - [RPM_SMD_BB_CLK1_PIN] = &msm8992_bb_clk1_pin, - [RPM_SMD_BB_CLK1_A_PIN] = &msm8992_bb_clk1_a_pin, - [RPM_SMD_BB_CLK2] = &msm8992_bb_clk2, - [RPM_SMD_BB_CLK2_A] = &msm8992_bb_clk2_a, - [RPM_SMD_BB_CLK2_PIN] = &msm8992_bb_clk2_pin, - [RPM_SMD_BB_CLK2_A_PIN] = &msm8992_bb_clk2_a_pin, - [RPM_SMD_DIV_CLK1] = &msm8992_div_clk1, - [RPM_SMD_DIV_A_CLK1] = &msm8992_div_clk1_a, - [RPM_SMD_DIV_CLK2] = &msm8992_div_clk2, - [RPM_SMD_DIV_A_CLK2] = &msm8992_div_clk2_a, + [RPM_SMD_PNOC_CLK] = &msm8916_pcnoc_clk, + [RPM_SMD_PNOC_A_CLK] = &msm8916_pcnoc_a_clk, + [RPM_SMD_OCMEMGX_CLK] = &msm8974_ocmemgx_clk, + [RPM_SMD_OCMEMGX_A_CLK] = &msm8974_ocmemgx_a_clk, + [RPM_SMD_BIMC_CLK] = &msm8916_bimc_clk, + [RPM_SMD_BIMC_A_CLK] = &msm8916_bimc_a_clk, + [RPM_SMD_CNOC_CLK] = &msm8974_cnoc_clk, + [RPM_SMD_CNOC_A_CLK] = &msm8974_cnoc_a_clk, + [RPM_SMD_GFX3D_CLK_SRC] = &msm8974_gfx3d_clk_src, + [RPM_SMD_GFX3D_A_CLK_SRC] = &msm8974_gfx3d_a_clk_src, + [RPM_SMD_SNOC_CLK] = &msm8916_snoc_clk, + [RPM_SMD_SNOC_A_CLK] = &msm8916_snoc_a_clk, + [RPM_SMD_BB_CLK1] = &msm8916_bb_clk1, + [RPM_SMD_BB_CLK1_A] = &msm8916_bb_clk1_a, + [RPM_SMD_BB_CLK1_PIN] = &msm8916_bb_clk1_pin, + [RPM_SMD_BB_CLK1_A_PIN] = &msm8916_bb_clk1_a_pin, + [RPM_SMD_BB_CLK2] = &msm8916_bb_clk2, + [RPM_SMD_BB_CLK2_A] = &msm8916_bb_clk2_a, + [RPM_SMD_BB_CLK2_PIN] = &msm8916_bb_clk2_pin, + [RPM_SMD_BB_CLK2_A_PIN] = &msm8916_bb_clk2_a_pin, + [RPM_SMD_DIV_CLK1] = &msm8974_div_clk1, + [RPM_SMD_DIV_A_CLK1] = &msm8974_div_a_clk1, + [RPM_SMD_DIV_CLK2] = &msm8974_div_clk2, + [RPM_SMD_DIV_A_CLK2] = &msm8974_div_a_clk2, [RPM_SMD_DIV_CLK3] = &msm8992_div_clk3, [RPM_SMD_DIV_A_CLK3] = &msm8992_div_clk3_a, - [RPM_SMD_IPA_CLK] = &msm8992_ipa_clk, - [RPM_SMD_IPA_A_CLK] = &msm8992_ipa_a_clk, + [RPM_SMD_IPA_CLK] = &msm8976_ipa_clk, + [RPM_SMD_IPA_A_CLK] = &msm8976_ipa_a_clk, [RPM_SMD_LN_BB_CLK] = &msm8992_ln_bb_clk, [RPM_SMD_LN_BB_A_CLK] = &msm8992_ln_bb_a_clk, - [RPM_SMD_MMSSNOC_AHB_CLK] = &msm8992_mmssnoc_ahb_clk, - [RPM_SMD_MMSSNOC_AHB_A_CLK] = &msm8992_mmssnoc_ahb_a_clk, - [RPM_SMD_QDSS_CLK] = &msm8992_qdss_clk, - [RPM_SMD_QDSS_A_CLK] = &msm8992_qdss_a_clk, - [RPM_SMD_RF_CLK1] = &msm8992_rf_clk1, - [RPM_SMD_RF_CLK1_A] = &msm8992_rf_clk1_a, - [RPM_SMD_RF_CLK2] = &msm8992_rf_clk2, - [RPM_SMD_RF_CLK2_A] = &msm8992_rf_clk2_a, - [RPM_SMD_RF_CLK1_PIN] = &msm8992_rf_clk1_pin, - [RPM_SMD_RF_CLK1_A_PIN] = &msm8992_rf_clk1_a_pin, - [RPM_SMD_RF_CLK2_PIN] = &msm8992_rf_clk2_pin, - [RPM_SMD_RF_CLK2_A_PIN] = &msm8992_rf_clk2_a_pin, + [RPM_SMD_MMSSNOC_AHB_CLK] = &msm8974_mmssnoc_ahb_clk, + [RPM_SMD_MMSSNOC_AHB_A_CLK] = &msm8974_mmssnoc_ahb_a_clk, + [RPM_SMD_QDSS_CLK] = &msm8916_qdss_clk, + [RPM_SMD_QDSS_A_CLK] = &msm8916_qdss_a_clk, + [RPM_SMD_RF_CLK1] = &msm8916_rf_clk1, + [RPM_SMD_RF_CLK1_A] = &msm8916_rf_clk1_a, + [RPM_SMD_RF_CLK2] = &msm8916_rf_clk2, + [RPM_SMD_RF_CLK2_A] = &msm8916_rf_clk2_a, + [RPM_SMD_RF_CLK1_PIN] = &msm8916_rf_clk1_pin, + [RPM_SMD_RF_CLK1_A_PIN] = &msm8916_rf_clk1_a_pin, + [RPM_SMD_RF_CLK2_PIN] = &msm8916_rf_clk2_pin, + [RPM_SMD_RF_CLK2_A_PIN] = &msm8916_rf_clk2_a_pin, [RPM_SMD_CE1_CLK] = &msm8992_ce1_clk, [RPM_SMD_CE1_A_CLK] = &msm8992_ce1_a_clk, [RPM_SMD_CE2_CLK] = &msm8992_ce2_clk, @@ -718,83 +663,55 @@ static const struct rpm_smd_clk_desc rpm_clk_msm8992 = { .num_clks = ARRAY_SIZE(msm8992_clks), }; -/* msm8994 */ -DEFINE_CLK_SMD_RPM(msm8994, pnoc_clk, pnoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 0); -DEFINE_CLK_SMD_RPM(msm8994, ocmemgx_clk, ocmemgx_a_clk, QCOM_SMD_RPM_MEM_CLK, 2); -DEFINE_CLK_SMD_RPM(msm8994, bimc_clk, bimc_a_clk, QCOM_SMD_RPM_MEM_CLK, 0); -DEFINE_CLK_SMD_RPM(msm8994, cnoc_clk, cnoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 2); -DEFINE_CLK_SMD_RPM(msm8994, gfx3d_clk_src, gfx3d_a_clk_src, QCOM_SMD_RPM_MEM_CLK, 1); -DEFINE_CLK_SMD_RPM(msm8994, snoc_clk, snoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 1); -DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8994, bb_clk1, bb_clk1_a, 1); -DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8994, bb_clk1_pin, bb_clk1_a_pin, 1); -DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8994, bb_clk2, bb_clk2_a, 2); -DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8994, bb_clk2_pin, bb_clk2_a_pin, 2); - -DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8994, div_clk1, div_clk1_a, 11); -DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8994, div_clk2, div_clk2_a, 12); -DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8994, div_clk3, div_clk3_a, 13); -DEFINE_CLK_SMD_RPM(msm8994, ipa_clk, ipa_a_clk, QCOM_SMD_RPM_IPA_CLK, 0); -DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8994, ln_bb_clk, ln_bb_a_clk, 8); -DEFINE_CLK_SMD_RPM(msm8994, mmssnoc_ahb_clk, mmssnoc_ahb_a_clk, - QCOM_SMD_RPM_BUS_CLK, 3); -DEFINE_CLK_SMD_RPM_QDSS(msm8994, qdss_clk, qdss_a_clk, - QCOM_SMD_RPM_MISC_CLK, 1); -DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8994, rf_clk1, rf_clk1_a, 4); -DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8994, rf_clk2, rf_clk2_a, 5); -DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8994, rf_clk1_pin, rf_clk1_a_pin, 4); -DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8994, rf_clk2_pin, rf_clk2_a_pin, 5); - -DEFINE_CLK_SMD_RPM(msm8994, ce1_clk, ce1_a_clk, QCOM_SMD_RPM_CE_CLK, 0); -DEFINE_CLK_SMD_RPM(msm8994, ce2_clk, ce2_a_clk, QCOM_SMD_RPM_CE_CLK, 1); DEFINE_CLK_SMD_RPM(msm8994, ce3_clk, ce3_a_clk, QCOM_SMD_RPM_CE_CLK, 2); static struct clk_smd_rpm *msm8994_clks[] = { - [RPM_SMD_PNOC_CLK] = &msm8994_pnoc_clk, - [RPM_SMD_PNOC_A_CLK] = &msm8994_pnoc_a_clk, - [RPM_SMD_OCMEMGX_CLK] = &msm8994_ocmemgx_clk, - [RPM_SMD_OCMEMGX_A_CLK] = &msm8994_ocmemgx_a_clk, - [RPM_SMD_BIMC_CLK] = &msm8994_bimc_clk, - [RPM_SMD_BIMC_A_CLK] = &msm8994_bimc_a_clk, - [RPM_SMD_CNOC_CLK] = &msm8994_cnoc_clk, - [RPM_SMD_CNOC_A_CLK] = &msm8994_cnoc_a_clk, - [RPM_SMD_GFX3D_CLK_SRC] = &msm8994_gfx3d_clk_src, - [RPM_SMD_GFX3D_A_CLK_SRC] = &msm8994_gfx3d_a_clk_src, - [RPM_SMD_SNOC_CLK] = &msm8994_snoc_clk, - [RPM_SMD_SNOC_A_CLK] = &msm8994_snoc_a_clk, - [RPM_SMD_BB_CLK1] = &msm8994_bb_clk1, - [RPM_SMD_BB_CLK1_A] = &msm8994_bb_clk1_a, - [RPM_SMD_BB_CLK1_PIN] = &msm8994_bb_clk1_pin, - [RPM_SMD_BB_CLK1_A_PIN] = &msm8994_bb_clk1_a_pin, - [RPM_SMD_BB_CLK2] = &msm8994_bb_clk2, - [RPM_SMD_BB_CLK2_A] = &msm8994_bb_clk2_a, - [RPM_SMD_BB_CLK2_PIN] = &msm8994_bb_clk2_pin, - [RPM_SMD_BB_CLK2_A_PIN] = &msm8994_bb_clk2_a_pin, - [RPM_SMD_DIV_CLK1] = &msm8994_div_clk1, - [RPM_SMD_DIV_A_CLK1] = &msm8994_div_clk1_a, - [RPM_SMD_DIV_CLK2] = &msm8994_div_clk2, - [RPM_SMD_DIV_A_CLK2] = &msm8994_div_clk2_a, - [RPM_SMD_DIV_CLK3] = &msm8994_div_clk3, - [RPM_SMD_DIV_A_CLK3] = &msm8994_div_clk3_a, - [RPM_SMD_IPA_CLK] = &msm8994_ipa_clk, - [RPM_SMD_IPA_A_CLK] = &msm8994_ipa_a_clk, - [RPM_SMD_LN_BB_CLK] = &msm8994_ln_bb_clk, - [RPM_SMD_LN_BB_A_CLK] = &msm8994_ln_bb_a_clk, - [RPM_SMD_MMSSNOC_AHB_CLK] = &msm8994_mmssnoc_ahb_clk, - [RPM_SMD_MMSSNOC_AHB_A_CLK] = &msm8994_mmssnoc_ahb_a_clk, - [RPM_SMD_QDSS_CLK] = &msm8994_qdss_clk, - [RPM_SMD_QDSS_A_CLK] = &msm8994_qdss_a_clk, - [RPM_SMD_RF_CLK1] = &msm8994_rf_clk1, - [RPM_SMD_RF_CLK1_A] = &msm8994_rf_clk1_a, - [RPM_SMD_RF_CLK2] = &msm8994_rf_clk2, - [RPM_SMD_RF_CLK2_A] = &msm8994_rf_clk2_a, - [RPM_SMD_RF_CLK1_PIN] = &msm8994_rf_clk1_pin, - [RPM_SMD_RF_CLK1_A_PIN] = &msm8994_rf_clk1_a_pin, - [RPM_SMD_RF_CLK2_PIN] = &msm8994_rf_clk2_pin, - [RPM_SMD_RF_CLK2_A_PIN] = &msm8994_rf_clk2_a_pin, - [RPM_SMD_CE1_CLK] = &msm8994_ce1_clk, - [RPM_SMD_CE1_A_CLK] = &msm8994_ce1_a_clk, - [RPM_SMD_CE2_CLK] = &msm8994_ce2_clk, - [RPM_SMD_CE2_A_CLK] = &msm8994_ce2_a_clk, + [RPM_SMD_PNOC_CLK] = &msm8916_pcnoc_clk, + [RPM_SMD_PNOC_A_CLK] = &msm8916_pcnoc_a_clk, + [RPM_SMD_OCMEMGX_CLK] = &msm8974_ocmemgx_clk, + [RPM_SMD_OCMEMGX_A_CLK] = &msm8974_ocmemgx_a_clk, + [RPM_SMD_BIMC_CLK] = &msm8916_bimc_clk, + [RPM_SMD_BIMC_A_CLK] = &msm8916_bimc_a_clk, + [RPM_SMD_CNOC_CLK] = &msm8974_cnoc_clk, + [RPM_SMD_CNOC_A_CLK] = &msm8974_cnoc_a_clk, + [RPM_SMD_GFX3D_CLK_SRC] = &msm8974_gfx3d_clk_src, + [RPM_SMD_GFX3D_A_CLK_SRC] = &msm8974_gfx3d_a_clk_src, + [RPM_SMD_SNOC_CLK] = &msm8916_snoc_clk, + [RPM_SMD_SNOC_A_CLK] = &msm8916_snoc_a_clk, + [RPM_SMD_BB_CLK1] = &msm8916_bb_clk1, + [RPM_SMD_BB_CLK1_A] = &msm8916_bb_clk1_a, + [RPM_SMD_BB_CLK1_PIN] = &msm8916_bb_clk1_pin, + [RPM_SMD_BB_CLK1_A_PIN] = &msm8916_bb_clk1_a_pin, + [RPM_SMD_BB_CLK2] = &msm8916_bb_clk2, + [RPM_SMD_BB_CLK2_A] = &msm8916_bb_clk2_a, + [RPM_SMD_BB_CLK2_PIN] = &msm8916_bb_clk2_pin, + [RPM_SMD_BB_CLK2_A_PIN] = &msm8916_bb_clk2_a_pin, + [RPM_SMD_DIV_CLK1] = &msm8974_div_clk1, + [RPM_SMD_DIV_A_CLK1] = &msm8974_div_a_clk1, + [RPM_SMD_DIV_CLK2] = &msm8974_div_clk2, + [RPM_SMD_DIV_A_CLK2] = &msm8974_div_a_clk2, + [RPM_SMD_DIV_CLK3] = &msm8992_div_clk3, + [RPM_SMD_DIV_A_CLK3] = &msm8992_div_clk3_a, + [RPM_SMD_IPA_CLK] = &msm8976_ipa_clk, + [RPM_SMD_IPA_A_CLK] = &msm8976_ipa_a_clk, + [RPM_SMD_LN_BB_CLK] = &msm8992_ln_bb_clk, + [RPM_SMD_LN_BB_A_CLK] = &msm8992_ln_bb_a_clk, + [RPM_SMD_MMSSNOC_AHB_CLK] = &msm8974_mmssnoc_ahb_clk, + [RPM_SMD_MMSSNOC_AHB_A_CLK] = &msm8974_mmssnoc_ahb_a_clk, + [RPM_SMD_QDSS_CLK] = &msm8916_qdss_clk, + [RPM_SMD_QDSS_A_CLK] = &msm8916_qdss_a_clk, + [RPM_SMD_RF_CLK1] = &msm8916_rf_clk1, + [RPM_SMD_RF_CLK1_A] = &msm8916_rf_clk1_a, + [RPM_SMD_RF_CLK2] = &msm8916_rf_clk2, + [RPM_SMD_RF_CLK2_A] = &msm8916_rf_clk2_a, + [RPM_SMD_RF_CLK1_PIN] = &msm8916_rf_clk1_pin, + [RPM_SMD_RF_CLK1_A_PIN] = &msm8916_rf_clk1_a_pin, + [RPM_SMD_RF_CLK2_PIN] = &msm8916_rf_clk2_pin, + [RPM_SMD_RF_CLK2_A_PIN] = &msm8916_rf_clk2_a_pin, + [RPM_SMD_CE1_CLK] = &msm8992_ce1_clk, + [RPM_SMD_CE1_A_CLK] = &msm8992_ce1_a_clk, + [RPM_SMD_CE2_CLK] = &msm8992_ce2_clk, + [RPM_SMD_CE2_A_CLK] = &msm8992_ce2_a_clk, [RPM_SMD_CE3_CLK] = &msm8994_ce3_clk, [RPM_SMD_CE3_A_CLK] = &msm8994_ce3_a_clk, }; @@ -804,79 +721,58 @@ static const struct rpm_smd_clk_desc rpm_clk_msm8994 = { .num_clks = ARRAY_SIZE(msm8994_clks), }; -/* msm8996 */ -DEFINE_CLK_SMD_RPM(msm8996, pcnoc_clk, pcnoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 0); -DEFINE_CLK_SMD_RPM(msm8996, snoc_clk, snoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 1); -DEFINE_CLK_SMD_RPM(msm8996, cnoc_clk, cnoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 2); -DEFINE_CLK_SMD_RPM(msm8996, bimc_clk, bimc_a_clk, QCOM_SMD_RPM_MEM_CLK, 0); DEFINE_CLK_SMD_RPM(msm8996, mmssnoc_axi_rpm_clk, mmssnoc_axi_rpm_a_clk, QCOM_SMD_RPM_MMAXI_CLK, 0); -DEFINE_CLK_SMD_RPM(msm8996, ipa_clk, ipa_a_clk, QCOM_SMD_RPM_IPA_CLK, 0); -DEFINE_CLK_SMD_RPM(msm8996, ce1_clk, ce1_a_clk, QCOM_SMD_RPM_CE_CLK, 0); DEFINE_CLK_SMD_RPM_BRANCH(msm8996, aggre1_noc_clk, aggre1_noc_a_clk, QCOM_SMD_RPM_AGGR_CLK, 1, 1000); DEFINE_CLK_SMD_RPM_BRANCH(msm8996, aggre2_noc_clk, aggre2_noc_a_clk, QCOM_SMD_RPM_AGGR_CLK, 2, 1000); -DEFINE_CLK_SMD_RPM_QDSS(msm8996, qdss_clk, qdss_a_clk, - QCOM_SMD_RPM_MISC_CLK, 1); -DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8996, bb_clk1, bb_clk1_a, 1); -DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8996, bb_clk2, bb_clk2_a, 2); -DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8996, rf_clk1, rf_clk1_a, 4); -DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8996, rf_clk2, rf_clk2_a, 5); -DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8996, ln_bb_clk, ln_bb_a_clk, 8); -DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8996, div_clk1, div_clk1_a, 0xb); -DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8996, div_clk2, div_clk2_a, 0xc); -DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8996, div_clk3, div_clk3_a, 0xd); -DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8996, bb_clk1_pin, bb_clk1_a_pin, 1); -DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8996, bb_clk2_pin, bb_clk2_a_pin, 2); -DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8996, rf_clk1_pin, rf_clk1_a_pin, 4); -DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8996, rf_clk2_pin, rf_clk2_a_pin, 5); static struct clk_smd_rpm *msm8996_clks[] = { - [RPM_SMD_PCNOC_CLK] = &msm8996_pcnoc_clk, - [RPM_SMD_PCNOC_A_CLK] = &msm8996_pcnoc_a_clk, - [RPM_SMD_SNOC_CLK] = &msm8996_snoc_clk, - [RPM_SMD_SNOC_A_CLK] = &msm8996_snoc_a_clk, - [RPM_SMD_CNOC_CLK] = &msm8996_cnoc_clk, - [RPM_SMD_CNOC_A_CLK] = &msm8996_cnoc_a_clk, - [RPM_SMD_BIMC_CLK] = &msm8996_bimc_clk, - [RPM_SMD_BIMC_A_CLK] = &msm8996_bimc_a_clk, + [RPM_SMD_PCNOC_CLK] = &msm8916_pcnoc_clk, + [RPM_SMD_PCNOC_A_CLK] = &msm8916_pcnoc_a_clk, + [RPM_SMD_SNOC_CLK] = &msm8916_snoc_clk, + [RPM_SMD_SNOC_A_CLK] = &msm8916_snoc_a_clk, + [RPM_SMD_CNOC_CLK] = &msm8974_cnoc_clk, + [RPM_SMD_CNOC_A_CLK] = &msm8974_cnoc_a_clk, + [RPM_SMD_BIMC_CLK] = &msm8916_bimc_clk, + [RPM_SMD_BIMC_A_CLK] = &msm8916_bimc_a_clk, [RPM_SMD_MMAXI_CLK] = &msm8996_mmssnoc_axi_rpm_clk, [RPM_SMD_MMAXI_A_CLK] = &msm8996_mmssnoc_axi_rpm_a_clk, - [RPM_SMD_IPA_CLK] = &msm8996_ipa_clk, - [RPM_SMD_IPA_A_CLK] = &msm8996_ipa_a_clk, - [RPM_SMD_CE1_CLK] = &msm8996_ce1_clk, - [RPM_SMD_CE1_A_CLK] = &msm8996_ce1_a_clk, + [RPM_SMD_IPA_CLK] = &msm8976_ipa_clk, + [RPM_SMD_IPA_A_CLK] = &msm8976_ipa_a_clk, + [RPM_SMD_CE1_CLK] = &msm8992_ce1_clk, + [RPM_SMD_CE1_A_CLK] = &msm8992_ce1_a_clk, [RPM_SMD_AGGR1_NOC_CLK] = &msm8996_aggre1_noc_clk, [RPM_SMD_AGGR1_NOC_A_CLK] = &msm8996_aggre1_noc_a_clk, [RPM_SMD_AGGR2_NOC_CLK] = &msm8996_aggre2_noc_clk, [RPM_SMD_AGGR2_NOC_A_CLK] = &msm8996_aggre2_noc_a_clk, - [RPM_SMD_QDSS_CLK] = &msm8996_qdss_clk, - [RPM_SMD_QDSS_A_CLK] = &msm8996_qdss_a_clk, - [RPM_SMD_BB_CLK1] = &msm8996_bb_clk1, - [RPM_SMD_BB_CLK1_A] = &msm8996_bb_clk1_a, - [RPM_SMD_BB_CLK2] = &msm8996_bb_clk2, - [RPM_SMD_BB_CLK2_A] = &msm8996_bb_clk2_a, - [RPM_SMD_RF_CLK1] = &msm8996_rf_clk1, - [RPM_SMD_RF_CLK1_A] = &msm8996_rf_clk1_a, - [RPM_SMD_RF_CLK2] = &msm8996_rf_clk2, - [RPM_SMD_RF_CLK2_A] = &msm8996_rf_clk2_a, - [RPM_SMD_LN_BB_CLK] = &msm8996_ln_bb_clk, - [RPM_SMD_LN_BB_A_CLK] = &msm8996_ln_bb_a_clk, - [RPM_SMD_DIV_CLK1] = &msm8996_div_clk1, - [RPM_SMD_DIV_A_CLK1] = &msm8996_div_clk1_a, - [RPM_SMD_DIV_CLK2] = &msm8996_div_clk2, - [RPM_SMD_DIV_A_CLK2] = &msm8996_div_clk2_a, - [RPM_SMD_DIV_CLK3] = &msm8996_div_clk3, - [RPM_SMD_DIV_A_CLK3] = &msm8996_div_clk3_a, - [RPM_SMD_BB_CLK1_PIN] = &msm8996_bb_clk1_pin, - [RPM_SMD_BB_CLK1_A_PIN] = &msm8996_bb_clk1_a_pin, - [RPM_SMD_BB_CLK2_PIN] = &msm8996_bb_clk2_pin, - [RPM_SMD_BB_CLK2_A_PIN] = &msm8996_bb_clk2_a_pin, - [RPM_SMD_RF_CLK1_PIN] = &msm8996_rf_clk1_pin, - [RPM_SMD_RF_CLK1_A_PIN] = &msm8996_rf_clk1_a_pin, - [RPM_SMD_RF_CLK2_PIN] = &msm8996_rf_clk2_pin, - [RPM_SMD_RF_CLK2_A_PIN] = &msm8996_rf_clk2_a_pin, + [RPM_SMD_QDSS_CLK] = &msm8916_qdss_clk, + [RPM_SMD_QDSS_A_CLK] = &msm8916_qdss_a_clk, + [RPM_SMD_BB_CLK1] = &msm8916_bb_clk1, + [RPM_SMD_BB_CLK1_A] = &msm8916_bb_clk1_a, + [RPM_SMD_BB_CLK2] = &msm8916_bb_clk2, + [RPM_SMD_BB_CLK2_A] = &msm8916_bb_clk2_a, + [RPM_SMD_RF_CLK1] = &msm8916_rf_clk1, + [RPM_SMD_RF_CLK1_A] = &msm8916_rf_clk1_a, + [RPM_SMD_RF_CLK2] = &msm8916_rf_clk2, + [RPM_SMD_RF_CLK2_A] = &msm8916_rf_clk2_a, + [RPM_SMD_LN_BB_CLK] = &msm8992_ln_bb_clk, + [RPM_SMD_LN_BB_A_CLK] = &msm8992_ln_bb_a_clk, + [RPM_SMD_DIV_CLK1] = &msm8974_div_clk1, + [RPM_SMD_DIV_A_CLK1] = &msm8974_div_a_clk1, + [RPM_SMD_DIV_CLK2] = &msm8974_div_clk2, + [RPM_SMD_DIV_A_CLK2] = &msm8974_div_a_clk2, + [RPM_SMD_DIV_CLK3] = &msm8992_div_clk3, + [RPM_SMD_DIV_A_CLK3] = &msm8992_div_clk3_a, + [RPM_SMD_BB_CLK1_PIN] = &msm8916_bb_clk1_pin, + [RPM_SMD_BB_CLK1_A_PIN] = &msm8916_bb_clk1_a_pin, + [RPM_SMD_BB_CLK2_PIN] = &msm8916_bb_clk2_pin, + [RPM_SMD_BB_CLK2_A_PIN] = &msm8916_bb_clk2_a_pin, + [RPM_SMD_RF_CLK1_PIN] = &msm8916_rf_clk1_pin, + [RPM_SMD_RF_CLK1_A_PIN] = &msm8916_rf_clk1_a_pin, + [RPM_SMD_RF_CLK2_PIN] = &msm8916_rf_clk2_pin, + [RPM_SMD_RF_CLK2_A_PIN] = &msm8916_rf_clk2_a_pin, }; static const struct rpm_smd_clk_desc rpm_clk_msm8996 = { @@ -884,43 +780,29 @@ static const struct rpm_smd_clk_desc rpm_clk_msm8996 = { .num_clks = ARRAY_SIZE(msm8996_clks), }; -/* QCS404 */ -DEFINE_CLK_SMD_RPM_QDSS(qcs404, qdss_clk, qdss_a_clk, QCOM_SMD_RPM_MISC_CLK, 1); - -DEFINE_CLK_SMD_RPM(qcs404, pnoc_clk, pnoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 0); -DEFINE_CLK_SMD_RPM(qcs404, snoc_clk, snoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 1); - -DEFINE_CLK_SMD_RPM(qcs404, bimc_clk, bimc_a_clk, QCOM_SMD_RPM_MEM_CLK, 0); DEFINE_CLK_SMD_RPM(qcs404, bimc_gpu_clk, bimc_gpu_a_clk, QCOM_SMD_RPM_MEM_CLK, 2); - DEFINE_CLK_SMD_RPM(qcs404, qpic_clk, qpic_a_clk, QCOM_SMD_RPM_QPIC_CLK, 0); -DEFINE_CLK_SMD_RPM(qcs404, ce1_clk, ce1_a_clk, QCOM_SMD_RPM_CE_CLK, 0); - -DEFINE_CLK_SMD_RPM_XO_BUFFER(qcs404, rf_clk1, rf_clk1_a, 4); -DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(qcs404, rf_clk1_pin, rf_clk1_a_pin, 4); - -DEFINE_CLK_SMD_RPM_XO_BUFFER(qcs404, ln_bb_clk, ln_bb_a_clk, 8); DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(qcs404, ln_bb_clk_pin, ln_bb_clk_a_pin, 8); static struct clk_smd_rpm *qcs404_clks[] = { - [RPM_SMD_QDSS_CLK] = &qcs404_qdss_clk, - [RPM_SMD_QDSS_A_CLK] = &qcs404_qdss_a_clk, - [RPM_SMD_PNOC_CLK] = &qcs404_pnoc_clk, - [RPM_SMD_PNOC_A_CLK] = &qcs404_pnoc_a_clk, - [RPM_SMD_SNOC_CLK] = &qcs404_snoc_clk, - [RPM_SMD_SNOC_A_CLK] = &qcs404_snoc_a_clk, - [RPM_SMD_BIMC_CLK] = &qcs404_bimc_clk, - [RPM_SMD_BIMC_A_CLK] = &qcs404_bimc_a_clk, + [RPM_SMD_QDSS_CLK] = &msm8916_qdss_clk, + [RPM_SMD_QDSS_A_CLK] = &msm8916_qdss_a_clk, + [RPM_SMD_PNOC_CLK] = &msm8916_pcnoc_clk, + [RPM_SMD_PNOC_A_CLK] = &msm8916_pcnoc_a_clk, + [RPM_SMD_SNOC_CLK] = &msm8916_snoc_clk, + [RPM_SMD_SNOC_A_CLK] = &msm8916_snoc_a_clk, + [RPM_SMD_BIMC_CLK] = &msm8916_bimc_clk, + [RPM_SMD_BIMC_A_CLK] = &msm8916_bimc_a_clk, [RPM_SMD_BIMC_GPU_CLK] = &qcs404_bimc_gpu_clk, [RPM_SMD_BIMC_GPU_A_CLK] = &qcs404_bimc_gpu_a_clk, [RPM_SMD_QPIC_CLK] = &qcs404_qpic_clk, [RPM_SMD_QPIC_CLK_A] = &qcs404_qpic_a_clk, - [RPM_SMD_CE1_CLK] = &qcs404_ce1_clk, - [RPM_SMD_CE1_A_CLK] = &qcs404_ce1_a_clk, - [RPM_SMD_RF_CLK1] = &qcs404_rf_clk1, - [RPM_SMD_RF_CLK1_A] = &qcs404_rf_clk1_a, - [RPM_SMD_LN_BB_CLK] = &qcs404_ln_bb_clk, - [RPM_SMD_LN_BB_A_CLK] = &qcs404_ln_bb_a_clk, + [RPM_SMD_CE1_CLK] = &msm8992_ce1_clk, + [RPM_SMD_CE1_A_CLK] = &msm8992_ce1_a_clk, + [RPM_SMD_RF_CLK1] = &msm8916_rf_clk1, + [RPM_SMD_RF_CLK1_A] = &msm8916_rf_clk1_a, + [RPM_SMD_LN_BB_CLK] = &msm8992_ln_bb_clk, + [RPM_SMD_LN_BB_A_CLK] = &msm8992_ln_bb_a_clk, }; static const struct rpm_smd_clk_desc rpm_clk_qcs404 = { @@ -928,63 +810,47 @@ static const struct rpm_smd_clk_desc rpm_clk_qcs404 = { .num_clks = ARRAY_SIZE(qcs404_clks), }; -/* msm8998 */ -DEFINE_CLK_SMD_RPM(msm8998, bimc_clk, bimc_a_clk, QCOM_SMD_RPM_MEM_CLK, 0); -DEFINE_CLK_SMD_RPM(msm8998, pcnoc_clk, pcnoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 0); -DEFINE_CLK_SMD_RPM(msm8998, snoc_clk, snoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 1); -DEFINE_CLK_SMD_RPM(msm8998, cnoc_clk, cnoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 2); -DEFINE_CLK_SMD_RPM(msm8998, ce1_clk, ce1_a_clk, QCOM_SMD_RPM_CE_CLK, 0); -DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8998, div_clk1, div_clk1_a, 0xb); -DEFINE_CLK_SMD_RPM(msm8998, ipa_clk, ipa_a_clk, QCOM_SMD_RPM_IPA_CLK, 0); -DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8998, ln_bb_clk1, ln_bb_clk1_a, 1); -DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8998, ln_bb_clk2, ln_bb_clk2_a, 2); DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8998, ln_bb_clk3_pin, ln_bb_clk3_a_pin, 3); -DEFINE_CLK_SMD_RPM(msm8998, mmssnoc_axi_rpm_clk, mmssnoc_axi_rpm_a_clk, - QCOM_SMD_RPM_MMAXI_CLK, 0); DEFINE_CLK_SMD_RPM(msm8998, aggre1_noc_clk, aggre1_noc_a_clk, QCOM_SMD_RPM_AGGR_CLK, 1); DEFINE_CLK_SMD_RPM(msm8998, aggre2_noc_clk, aggre2_noc_a_clk, QCOM_SMD_RPM_AGGR_CLK, 2); -DEFINE_CLK_SMD_RPM_QDSS(msm8998, qdss_clk, qdss_a_clk, - QCOM_SMD_RPM_MISC_CLK, 1); -DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8998, rf_clk1, rf_clk1_a, 4); -DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8998, rf_clk2_pin, rf_clk2_a_pin, 5); DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8998, rf_clk3, rf_clk3_a, 6); DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8998, rf_clk3_pin, rf_clk3_a_pin, 6); static struct clk_smd_rpm *msm8998_clks[] = { - [RPM_SMD_BIMC_CLK] = &msm8998_bimc_clk, - [RPM_SMD_BIMC_A_CLK] = &msm8998_bimc_a_clk, - [RPM_SMD_PCNOC_CLK] = &msm8998_pcnoc_clk, - [RPM_SMD_PCNOC_A_CLK] = &msm8998_pcnoc_a_clk, - [RPM_SMD_SNOC_CLK] = &msm8998_snoc_clk, - [RPM_SMD_SNOC_A_CLK] = &msm8998_snoc_a_clk, - [RPM_SMD_CNOC_CLK] = &msm8998_cnoc_clk, - [RPM_SMD_CNOC_A_CLK] = &msm8998_cnoc_a_clk, - [RPM_SMD_CE1_CLK] = &msm8998_ce1_clk, - [RPM_SMD_CE1_A_CLK] = &msm8998_ce1_a_clk, - [RPM_SMD_DIV_CLK1] = &msm8998_div_clk1, - [RPM_SMD_DIV_A_CLK1] = &msm8998_div_clk1_a, - [RPM_SMD_IPA_CLK] = &msm8998_ipa_clk, - [RPM_SMD_IPA_A_CLK] = &msm8998_ipa_a_clk, - [RPM_SMD_LN_BB_CLK1] = &msm8998_ln_bb_clk1, - [RPM_SMD_LN_BB_CLK1_A] = &msm8998_ln_bb_clk1_a, - [RPM_SMD_LN_BB_CLK2] = &msm8998_ln_bb_clk2, - [RPM_SMD_LN_BB_CLK2_A] = &msm8998_ln_bb_clk2_a, + [RPM_SMD_BIMC_CLK] = &msm8916_bimc_clk, + [RPM_SMD_BIMC_A_CLK] = &msm8916_bimc_a_clk, + [RPM_SMD_PCNOC_CLK] = &msm8916_pcnoc_clk, + [RPM_SMD_PCNOC_A_CLK] = &msm8916_pcnoc_a_clk, + [RPM_SMD_SNOC_CLK] = &msm8916_snoc_clk, + [RPM_SMD_SNOC_A_CLK] = &msm8916_snoc_a_clk, + [RPM_SMD_CNOC_CLK] = &msm8974_cnoc_clk, + [RPM_SMD_CNOC_A_CLK] = &msm8974_cnoc_a_clk, + [RPM_SMD_CE1_CLK] = &msm8992_ce1_clk, + [RPM_SMD_CE1_A_CLK] = &msm8992_ce1_a_clk, + [RPM_SMD_DIV_CLK1] = &msm8974_div_clk1, + [RPM_SMD_DIV_A_CLK1] = &msm8974_div_a_clk1, + [RPM_SMD_IPA_CLK] = &msm8976_ipa_clk, + [RPM_SMD_IPA_A_CLK] = &msm8976_ipa_a_clk, + [RPM_SMD_LN_BB_CLK1] = &msm8916_bb_clk1, + [RPM_SMD_LN_BB_CLK1_A] = &msm8916_bb_clk1_a, + [RPM_SMD_LN_BB_CLK2] = &msm8916_bb_clk2, + [RPM_SMD_LN_BB_CLK2_A] = &msm8916_bb_clk2_a, [RPM_SMD_LN_BB_CLK3_PIN] = &msm8998_ln_bb_clk3_pin, [RPM_SMD_LN_BB_CLK3_A_PIN] = &msm8998_ln_bb_clk3_a_pin, - [RPM_SMD_MMAXI_CLK] = &msm8998_mmssnoc_axi_rpm_clk, - [RPM_SMD_MMAXI_A_CLK] = &msm8998_mmssnoc_axi_rpm_a_clk, + [RPM_SMD_MMAXI_CLK] = &msm8996_mmssnoc_axi_rpm_clk, + [RPM_SMD_MMAXI_A_CLK] = &msm8996_mmssnoc_axi_rpm_a_clk, [RPM_SMD_AGGR1_NOC_CLK] = &msm8998_aggre1_noc_clk, [RPM_SMD_AGGR1_NOC_A_CLK] = &msm8998_aggre1_noc_a_clk, [RPM_SMD_AGGR2_NOC_CLK] = &msm8998_aggre2_noc_clk, [RPM_SMD_AGGR2_NOC_A_CLK] = &msm8998_aggre2_noc_a_clk, - [RPM_SMD_QDSS_CLK] = &msm8998_qdss_clk, - [RPM_SMD_QDSS_A_CLK] = &msm8998_qdss_a_clk, - [RPM_SMD_RF_CLK1] = &msm8998_rf_clk1, - [RPM_SMD_RF_CLK1_A] = &msm8998_rf_clk1_a, - [RPM_SMD_RF_CLK2_PIN] = &msm8998_rf_clk2_pin, - [RPM_SMD_RF_CLK2_A_PIN] = &msm8998_rf_clk2_a_pin, + [RPM_SMD_QDSS_CLK] = &msm8916_qdss_clk, + [RPM_SMD_QDSS_A_CLK] = &msm8916_qdss_a_clk, + [RPM_SMD_RF_CLK1] = &msm8916_rf_clk1, + [RPM_SMD_RF_CLK1_A] = &msm8916_rf_clk1_a, + [RPM_SMD_RF_CLK2_PIN] = &msm8916_rf_clk2_pin, + [RPM_SMD_RF_CLK2_A_PIN] = &msm8916_rf_clk2_a_pin, [RPM_SMD_RF_CLK3] = &msm8998_rf_clk3, [RPM_SMD_RF_CLK3_A] = &msm8998_rf_clk3_a, [RPM_SMD_RF_CLK3_PIN] = &msm8998_rf_clk3_pin, @@ -996,72 +862,48 @@ static const struct rpm_smd_clk_desc rpm_clk_msm8998 = { .num_clks = ARRAY_SIZE(msm8998_clks), }; -/* sdm660 */ DEFINE_CLK_SMD_RPM_BRANCH(sdm660, bi_tcxo, bi_tcxo_a, QCOM_SMD_RPM_MISC_CLK, 0, 19200000); -DEFINE_CLK_SMD_RPM(sdm660, snoc_clk, snoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 1); -DEFINE_CLK_SMD_RPM(sdm660, cnoc_clk, cnoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 2); -DEFINE_CLK_SMD_RPM(sdm660, cnoc_periph_clk, cnoc_periph_a_clk, - QCOM_SMD_RPM_BUS_CLK, 0); -DEFINE_CLK_SMD_RPM(sdm660, bimc_clk, bimc_a_clk, QCOM_SMD_RPM_MEM_CLK, 0); -DEFINE_CLK_SMD_RPM(sdm660, mmssnoc_axi_clk, mmssnoc_axi_a_clk, - QCOM_SMD_RPM_MMAXI_CLK, 0); -DEFINE_CLK_SMD_RPM(sdm660, ipa_clk, ipa_a_clk, QCOM_SMD_RPM_IPA_CLK, 0); -DEFINE_CLK_SMD_RPM(sdm660, ce1_clk, ce1_a_clk, QCOM_SMD_RPM_CE_CLK, 0); -DEFINE_CLK_SMD_RPM(sdm660, aggre2_noc_clk, aggre2_noc_a_clk, - QCOM_SMD_RPM_AGGR_CLK, 2); -DEFINE_CLK_SMD_RPM_QDSS(sdm660, qdss_clk, qdss_a_clk, - QCOM_SMD_RPM_MISC_CLK, 1); -DEFINE_CLK_SMD_RPM_XO_BUFFER(sdm660, rf_clk1, rf_clk1_a, 4); -DEFINE_CLK_SMD_RPM_XO_BUFFER(sdm660, div_clk1, div_clk1_a, 11); -DEFINE_CLK_SMD_RPM_XO_BUFFER(sdm660, ln_bb_clk1, ln_bb_clk1_a, 1); -DEFINE_CLK_SMD_RPM_XO_BUFFER(sdm660, ln_bb_clk2, ln_bb_clk2_a, 2); DEFINE_CLK_SMD_RPM_XO_BUFFER(sdm660, ln_bb_clk3, ln_bb_clk3_a, 3); +DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(sdm660, ln_bb_clk3_pin, ln_bb_clk3_pin_a, 3); -DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(sdm660, rf_clk1_pin, rf_clk1_a_pin, 4); -DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(sdm660, ln_bb_clk1_pin, - ln_bb_clk1_pin_a, 1); -DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(sdm660, ln_bb_clk2_pin, - ln_bb_clk2_pin_a, 2); -DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(sdm660, ln_bb_clk3_pin, - ln_bb_clk3_pin_a, 3); static struct clk_smd_rpm *sdm660_clks[] = { [RPM_SMD_XO_CLK_SRC] = &sdm660_bi_tcxo, [RPM_SMD_XO_A_CLK_SRC] = &sdm660_bi_tcxo_a, - [RPM_SMD_SNOC_CLK] = &sdm660_snoc_clk, - [RPM_SMD_SNOC_A_CLK] = &sdm660_snoc_a_clk, - [RPM_SMD_CNOC_CLK] = &sdm660_cnoc_clk, - [RPM_SMD_CNOC_A_CLK] = &sdm660_cnoc_a_clk, - [RPM_SMD_CNOC_PERIPH_CLK] = &sdm660_cnoc_periph_clk, - [RPM_SMD_CNOC_PERIPH_A_CLK] = &sdm660_cnoc_periph_a_clk, - [RPM_SMD_BIMC_CLK] = &sdm660_bimc_clk, - [RPM_SMD_BIMC_A_CLK] = &sdm660_bimc_a_clk, - [RPM_SMD_MMSSNOC_AXI_CLK] = &sdm660_mmssnoc_axi_clk, - [RPM_SMD_MMSSNOC_AXI_CLK_A] = &sdm660_mmssnoc_axi_a_clk, - [RPM_SMD_IPA_CLK] = &sdm660_ipa_clk, - [RPM_SMD_IPA_A_CLK] = &sdm660_ipa_a_clk, - [RPM_SMD_CE1_CLK] = &sdm660_ce1_clk, - [RPM_SMD_CE1_A_CLK] = &sdm660_ce1_a_clk, - [RPM_SMD_AGGR2_NOC_CLK] = &sdm660_aggre2_noc_clk, - [RPM_SMD_AGGR2_NOC_A_CLK] = &sdm660_aggre2_noc_a_clk, - [RPM_SMD_QDSS_CLK] = &sdm660_qdss_clk, - [RPM_SMD_QDSS_A_CLK] = &sdm660_qdss_a_clk, - [RPM_SMD_RF_CLK1] = &sdm660_rf_clk1, - [RPM_SMD_RF_CLK1_A] = &sdm660_rf_clk1_a, - [RPM_SMD_DIV_CLK1] = &sdm660_div_clk1, - [RPM_SMD_DIV_A_CLK1] = &sdm660_div_clk1_a, - [RPM_SMD_LN_BB_CLK] = &sdm660_ln_bb_clk1, - [RPM_SMD_LN_BB_A_CLK] = &sdm660_ln_bb_clk1_a, - [RPM_SMD_LN_BB_CLK2] = &sdm660_ln_bb_clk2, - [RPM_SMD_LN_BB_CLK2_A] = &sdm660_ln_bb_clk2_a, + [RPM_SMD_SNOC_CLK] = &msm8916_snoc_clk, + [RPM_SMD_SNOC_A_CLK] = &msm8916_snoc_a_clk, + [RPM_SMD_CNOC_CLK] = &msm8974_cnoc_clk, + [RPM_SMD_CNOC_A_CLK] = &msm8974_cnoc_a_clk, + [RPM_SMD_CNOC_PERIPH_CLK] = &msm8916_pcnoc_clk, + [RPM_SMD_CNOC_PERIPH_A_CLK] = &msm8916_pcnoc_a_clk, + [RPM_SMD_BIMC_CLK] = &msm8916_bimc_clk, + [RPM_SMD_BIMC_A_CLK] = &msm8916_bimc_a_clk, + [RPM_SMD_MMSSNOC_AXI_CLK] = &msm8996_mmssnoc_axi_rpm_clk, + [RPM_SMD_MMSSNOC_AXI_CLK_A] = &msm8996_mmssnoc_axi_rpm_a_clk, + [RPM_SMD_IPA_CLK] = &msm8976_ipa_clk, + [RPM_SMD_IPA_A_CLK] = &msm8976_ipa_a_clk, + [RPM_SMD_CE1_CLK] = &msm8992_ce1_clk, + [RPM_SMD_CE1_A_CLK] = &msm8992_ce1_a_clk, + [RPM_SMD_AGGR2_NOC_CLK] = &msm8998_aggre2_noc_clk, + [RPM_SMD_AGGR2_NOC_A_CLK] = &msm8998_aggre2_noc_a_clk, + [RPM_SMD_QDSS_CLK] = &msm8916_qdss_clk, + [RPM_SMD_QDSS_A_CLK] = &msm8916_qdss_a_clk, + [RPM_SMD_RF_CLK1] = &msm8916_rf_clk1, + [RPM_SMD_RF_CLK1_A] = &msm8916_rf_clk1_a, + [RPM_SMD_DIV_CLK1] = &msm8974_div_clk1, + [RPM_SMD_DIV_A_CLK1] = &msm8974_div_a_clk1, + [RPM_SMD_LN_BB_CLK] = &msm8916_bb_clk1, + [RPM_SMD_LN_BB_A_CLK] = &msm8916_bb_clk1_a, + [RPM_SMD_LN_BB_CLK2] = &msm8916_bb_clk2, + [RPM_SMD_LN_BB_CLK2_A] = &msm8916_bb_clk2_a, [RPM_SMD_LN_BB_CLK3] = &sdm660_ln_bb_clk3, [RPM_SMD_LN_BB_CLK3_A] = &sdm660_ln_bb_clk3_a, - [RPM_SMD_RF_CLK1_PIN] = &sdm660_rf_clk1_pin, - [RPM_SMD_RF_CLK1_A_PIN] = &sdm660_rf_clk1_a_pin, - [RPM_SMD_LN_BB_CLK1_PIN] = &sdm660_ln_bb_clk1_pin, - [RPM_SMD_LN_BB_CLK1_A_PIN] = &sdm660_ln_bb_clk1_pin_a, - [RPM_SMD_LN_BB_CLK2_PIN] = &sdm660_ln_bb_clk2_pin, - [RPM_SMD_LN_BB_CLK2_A_PIN] = &sdm660_ln_bb_clk2_pin_a, + [RPM_SMD_RF_CLK1_PIN] = &msm8916_rf_clk1_pin, + [RPM_SMD_RF_CLK1_A_PIN] = &msm8916_rf_clk1_a_pin, + [RPM_SMD_LN_BB_CLK1_PIN] = &msm8916_bb_clk1_pin, + [RPM_SMD_LN_BB_CLK1_A_PIN] = &msm8916_bb_clk1_a_pin, + [RPM_SMD_LN_BB_CLK2_PIN] = &msm8916_bb_clk2_pin, + [RPM_SMD_LN_BB_CLK2_A_PIN] = &msm8916_bb_clk2_a_pin, [RPM_SMD_LN_BB_CLK3_PIN] = &sdm660_ln_bb_clk3_pin, [RPM_SMD_LN_BB_CLK3_A_PIN] = &sdm660_ln_bb_clk3_pin_a, }; From 8ff48c82df66bf8864070922b9d7ddcfd8ab2918 Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Mon, 10 May 2021 23:17:18 -0500 Subject: [PATCH 045/161] clk: qcom: dispcc-sm8250: Add sc8180x support The display clock controller in SC8180x is reused from SM8150, so add the necessary compatible and wire up the driver to enable this. Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/20210511041719.591969-1-bjorn.andersson@linaro.org Acked-by: Rob Herring Signed-off-by: Stephen Boyd --- .../devicetree/bindings/clock/qcom,dispcc-sm8x50.yaml | 1 + drivers/clk/qcom/dispcc-sm8250.c | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/clock/qcom,dispcc-sm8x50.yaml b/Documentation/devicetree/bindings/clock/qcom,dispcc-sm8x50.yaml index 0cdf53f41f84..6667261dc665 100644 --- a/Documentation/devicetree/bindings/clock/qcom,dispcc-sm8x50.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,dispcc-sm8x50.yaml @@ -20,6 +20,7 @@ description: | properties: compatible: enum: + - qcom,sc8180x-dispcc - qcom,sm8150-dispcc - qcom,sm8250-dispcc diff --git a/drivers/clk/qcom/dispcc-sm8250.c b/drivers/clk/qcom/dispcc-sm8250.c index de09cd5c209f..12ef6f1d5c62 100644 --- a/drivers/clk/qcom/dispcc-sm8250.c +++ b/drivers/clk/qcom/dispcc-sm8250.c @@ -1037,6 +1037,7 @@ static const struct qcom_cc_desc disp_cc_sm8250_desc = { }; static const struct of_device_id disp_cc_sm8250_match_table[] = { + { .compatible = "qcom,sc8180x-dispcc" }, { .compatible = "qcom,sm8150-dispcc" }, { .compatible = "qcom,sm8250-dispcc" }, { } @@ -1053,7 +1054,8 @@ static int disp_cc_sm8250_probe(struct platform_device *pdev) /* note: trion == lucid, except for the prepare() op */ BUILD_BUG_ON(CLK_ALPHA_PLL_TYPE_TRION != CLK_ALPHA_PLL_TYPE_LUCID); - if (of_device_is_compatible(pdev->dev.of_node, "qcom,sm8150-dispcc")) { + if (of_device_is_compatible(pdev->dev.of_node, "qcom,sc8180x-dispcc") || + of_device_is_compatible(pdev->dev.of_node, "qcom,sm8150-dispcc")) { disp_cc_pll0_config.config_ctl_hi_val = 0x00002267; disp_cc_pll0_config.config_ctl_hi1_val = 0x00000024; disp_cc_pll0_config.user_ctl_hi1_val = 0x000000D0; From 2ebdd326d19954c4705bf4417f33e765bff70c8e Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Mon, 10 May 2021 23:17:19 -0500 Subject: [PATCH 046/161] clk: qcom: dispcc-sm8250: Add EDP clocks Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/20210511041719.591969-2-bjorn.andersson@linaro.org Acked-by: Rob Herring Signed-off-by: Stephen Boyd --- drivers/clk/qcom/dispcc-sm8250.c | 186 +++++++++++++++++- .../dt-bindings/clock/qcom,dispcc-sm8250.h | 9 + 2 files changed, 193 insertions(+), 2 deletions(-) diff --git a/drivers/clk/qcom/dispcc-sm8250.c b/drivers/clk/qcom/dispcc-sm8250.c index 12ef6f1d5c62..601c7c0ba483 100644 --- a/drivers/clk/qcom/dispcc-sm8250.c +++ b/drivers/clk/qcom/dispcc-sm8250.c @@ -26,6 +26,8 @@ enum { P_DISP_CC_PLL1_OUT_MAIN, P_DP_PHY_PLL_LINK_CLK, P_DP_PHY_PLL_VCO_DIV_CLK, + P_EDP_PHY_PLL_LINK_CLK, + P_EDP_PHY_PLL_VCO_DIV_CLK, P_DSI0_PHY_PLL_OUT_BYTECLK, P_DSI0_PHY_PLL_OUT_DSICLK, P_DSI1_PHY_PLL_OUT_BYTECLK, @@ -134,6 +136,18 @@ static const struct clk_parent_data disp_cc_parent_data_3[] = { { .hw = &disp_cc_pll1.clkr.hw }, }; +static const struct parent_map disp_cc_parent_map_4[] = { + { P_BI_TCXO, 0 }, + { P_EDP_PHY_PLL_LINK_CLK, 1 }, + { P_EDP_PHY_PLL_VCO_DIV_CLK, 2}, +}; + +static const struct clk_parent_data disp_cc_parent_data_4[] = { + { .fw_name = "bi_tcxo" }, + { .fw_name = "edp_phy_pll_link_clk" }, + { .fw_name = "edp_phy_pll_vco_div_clk" }, +}; + static const struct parent_map disp_cc_parent_map_5[] = { { P_BI_TCXO, 0 }, { P_DISP_CC_PLL0_OUT_MAIN, 1 }, @@ -158,6 +172,18 @@ static const struct clk_parent_data disp_cc_parent_data_6[] = { { .fw_name = "dsi1_phy_pll_out_dsiclk" }, }; +static const struct parent_map disp_cc_parent_map_7[] = { + { P_BI_TCXO, 0 }, + { P_DISP_CC_PLL1_OUT_MAIN, 4 }, + /* { P_DISP_CC_PLL1_OUT_EVEN, 5 }, */ +}; + +static const struct clk_parent_data disp_cc_parent_data_7[] = { + { .fw_name = "bi_tcxo" }, + { .hw = &disp_cc_pll1.clkr.hw }, + /* { .hw = &disp_cc_pll1_out_even.clkr.hw }, */ +}; + static const struct freq_tbl ftbl_disp_cc_mdss_ahb_clk_src[] = { F(19200000, P_BI_TCXO, 1, 0, 0), F(37500000, P_DISP_CC_PLL1_OUT_MAIN, 16, 0, 0), @@ -261,7 +287,7 @@ static struct clk_rcg2 disp_cc_mdss_dp_link1_clk_src = { .name = "disp_cc_mdss_dp_link1_clk_src", .parent_data = disp_cc_parent_data_0, .num_parents = ARRAY_SIZE(disp_cc_parent_data_0), - .ops = &clk_rcg2_ops, + .ops = &clk_byte2_ops, }, }; @@ -275,7 +301,7 @@ static struct clk_rcg2 disp_cc_mdss_dp_link_clk_src = { .name = "disp_cc_mdss_dp_link_clk_src", .parent_data = disp_cc_parent_data_0, .num_parents = ARRAY_SIZE(disp_cc_parent_data_0), - .ops = &clk_rcg2_ops, + .ops = &clk_byte2_ops, }, }; @@ -318,6 +344,153 @@ static struct clk_rcg2 disp_cc_mdss_dp_pixel_clk_src = { }, }; +static struct clk_rcg2 disp_cc_mdss_edp_aux_clk_src = { + .cmd_rcgr = 0x228c, + .mnd_width = 0, + .hid_width = 5, + .parent_map = disp_cc_parent_map_1, + .freq_tbl = ftbl_disp_cc_mdss_byte0_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "disp_cc_mdss_edp_aux_clk_src", + .parent_data = disp_cc_parent_data_1, + .num_parents = ARRAY_SIZE(disp_cc_parent_data_1), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 disp_cc_mdss_edp_gtc_clk_src = { + .cmd_rcgr = 0x22a4, + .mnd_width = 0, + .hid_width = 5, + .parent_map = disp_cc_parent_map_7, + .freq_tbl = ftbl_disp_cc_mdss_byte0_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "disp_cc_mdss_edp_gtc_clk_src", + .parent_data = disp_cc_parent_data_7, + .num_parents = ARRAY_SIZE(disp_cc_parent_data_7), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 disp_cc_mdss_edp_link_clk_src = { + .cmd_rcgr = 0x2270, + .mnd_width = 0, + .hid_width = 5, + .parent_map = disp_cc_parent_map_4, + .clkr.hw.init = &(struct clk_init_data){ + .name = "disp_cc_mdss_edp_link_clk_src", + .parent_data = disp_cc_parent_data_4, + .num_parents = ARRAY_SIZE(disp_cc_parent_data_4), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_byte2_ops, + }, +}; + +static struct clk_rcg2 disp_cc_mdss_edp_pixel_clk_src = { + .cmd_rcgr = 0x2258, + .mnd_width = 16, + .hid_width = 5, + .parent_map = disp_cc_parent_map_4, + .clkr.hw.init = &(struct clk_init_data){ + .name = "disp_cc_mdss_edp_pixel_clk_src", + .parent_data = disp_cc_parent_data_4, + .num_parents = ARRAY_SIZE(disp_cc_parent_data_4), + .ops = &clk_dp_ops, + }, +}; + +static struct clk_branch disp_cc_mdss_edp_aux_clk = { + .halt_reg = 0x2078, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x2078, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "disp_cc_mdss_edp_aux_clk", + .parent_hws = (const struct clk_hw*[]){ + &disp_cc_mdss_edp_aux_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch disp_cc_mdss_edp_gtc_clk = { + .halt_reg = 0x207c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x207c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "disp_cc_mdss_edp_gtc_clk", + .parent_hws = (const struct clk_hw*[]){ + &disp_cc_mdss_edp_gtc_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch disp_cc_mdss_edp_link_clk = { + .halt_reg = 0x2070, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x2070, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "disp_cc_mdss_edp_link_clk", + .parent_hws = (const struct clk_hw*[]){ + &disp_cc_mdss_edp_link_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch disp_cc_mdss_edp_link_intf_clk = { + .halt_reg = 0x2074, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x2074, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "disp_cc_mdss_edp_link_intf_clk", + .parent_hws = (const struct clk_hw*[]){ + &disp_cc_mdss_edp_link_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_GET_RATE_NOCACHE, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch disp_cc_mdss_edp_pixel_clk = { + .halt_reg = 0x206c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x206c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "disp_cc_mdss_edp_pixel_clk", + .parent_hws = (const struct clk_hw*[]){ + &disp_cc_mdss_edp_pixel_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + static struct clk_rcg2 disp_cc_mdss_esc0_clk_src = { .cmd_rcgr = 0x2148, .mnd_width = 0, @@ -987,6 +1160,15 @@ static struct clk_regmap *disp_cc_sm8250_clocks[] = { [DISP_CC_MDSS_DP_PIXEL2_CLK_SRC] = &disp_cc_mdss_dp_pixel2_clk_src.clkr, [DISP_CC_MDSS_DP_PIXEL_CLK] = &disp_cc_mdss_dp_pixel_clk.clkr, [DISP_CC_MDSS_DP_PIXEL_CLK_SRC] = &disp_cc_mdss_dp_pixel_clk_src.clkr, + [DISP_CC_MDSS_EDP_AUX_CLK] = &disp_cc_mdss_edp_aux_clk.clkr, + [DISP_CC_MDSS_EDP_AUX_CLK_SRC] = &disp_cc_mdss_edp_aux_clk_src.clkr, + [DISP_CC_MDSS_EDP_GTC_CLK] = &disp_cc_mdss_edp_gtc_clk.clkr, + [DISP_CC_MDSS_EDP_GTC_CLK_SRC] = &disp_cc_mdss_edp_gtc_clk_src.clkr, + [DISP_CC_MDSS_EDP_LINK_CLK] = &disp_cc_mdss_edp_link_clk.clkr, + [DISP_CC_MDSS_EDP_LINK_CLK_SRC] = &disp_cc_mdss_edp_link_clk_src.clkr, + [DISP_CC_MDSS_EDP_LINK_INTF_CLK] = &disp_cc_mdss_edp_link_intf_clk.clkr, + [DISP_CC_MDSS_EDP_PIXEL_CLK] = &disp_cc_mdss_edp_pixel_clk.clkr, + [DISP_CC_MDSS_EDP_PIXEL_CLK_SRC] = &disp_cc_mdss_edp_pixel_clk_src.clkr, [DISP_CC_MDSS_ESC0_CLK] = &disp_cc_mdss_esc0_clk.clkr, [DISP_CC_MDSS_ESC0_CLK_SRC] = &disp_cc_mdss_esc0_clk_src.clkr, [DISP_CC_MDSS_ESC1_CLK] = &disp_cc_mdss_esc1_clk.clkr, diff --git a/include/dt-bindings/clock/qcom,dispcc-sm8250.h b/include/dt-bindings/clock/qcom,dispcc-sm8250.h index fdaca6ad5c85..ce001cbbc27f 100644 --- a/include/dt-bindings/clock/qcom,dispcc-sm8250.h +++ b/include/dt-bindings/clock/qcom,dispcc-sm8250.h @@ -55,6 +55,15 @@ #define DISP_CC_MDSS_VSYNC_CLK_SRC 45 #define DISP_CC_PLL0 46 #define DISP_CC_PLL1 47 +#define DISP_CC_MDSS_EDP_AUX_CLK 48 +#define DISP_CC_MDSS_EDP_AUX_CLK_SRC 49 +#define DISP_CC_MDSS_EDP_GTC_CLK 50 +#define DISP_CC_MDSS_EDP_GTC_CLK_SRC 51 +#define DISP_CC_MDSS_EDP_LINK_CLK 52 +#define DISP_CC_MDSS_EDP_LINK_CLK_SRC 53 +#define DISP_CC_MDSS_EDP_LINK_INTF_CLK 54 +#define DISP_CC_MDSS_EDP_PIXEL_CLK 55 +#define DISP_CC_MDSS_EDP_PIXEL_CLK_SRC 56 /* DISP_CC Reset */ #define DISP_CC_MDSS_CORE_BCR 0 From ec7e22abec97b6bd577027380077ec395864a3c5 Mon Sep 17 00:00:00 2001 From: Bartosz Dudziak Date: Sun, 2 May 2021 14:20:26 +0200 Subject: [PATCH 047/161] dt-bindings: clock: qcom: rpmcc: Document MSM8226 compatible Add the dt-binding for the RPM Clock Controller on the MSM8226 SoC. Signed-off-by: Bartosz Dudziak Link: https://lore.kernel.org/r/20210502122027.9351-4-bartosz.dudziak@snejp.pl Acked-by: Rob Herring Signed-off-by: Stephen Boyd --- Documentation/devicetree/bindings/clock/qcom,rpmcc.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/clock/qcom,rpmcc.txt b/Documentation/devicetree/bindings/clock/qcom,rpmcc.txt index b44a0622fb3a..6cf5a7ec2b4c 100644 --- a/Documentation/devicetree/bindings/clock/qcom,rpmcc.txt +++ b/Documentation/devicetree/bindings/clock/qcom,rpmcc.txt @@ -12,6 +12,7 @@ Required properties : "qcom,rpmcc-msm8660", "qcom,rpmcc" "qcom,rpmcc-apq8060", "qcom,rpmcc" + "qcom,rpmcc-msm8226", "qcom,rpmcc" "qcom,rpmcc-msm8916", "qcom,rpmcc" "qcom,rpmcc-msm8936", "qcom,rpmcc" "qcom,rpmcc-msm8974", "qcom,rpmcc" From f13570e7e830ca4fbf4869015af8492b8918445e Mon Sep 17 00:00:00 2001 From: Yang Yingliang Date: Tue, 18 May 2021 12:42:47 +0800 Subject: [PATCH 048/161] clk: tegra: tegra124-emc: Fix clock imbalance in emc_set_timing() After calling clk_prepare_enable(), clk_disable_unprepare() needs be called when prepare_timing_change() failed. Reported-by: Hulk Robot Signed-off-by: Yang Yingliang Signed-off-by: Thierry Reding --- drivers/clk/tegra/clk-tegra124-emc.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/clk/tegra/clk-tegra124-emc.c b/drivers/clk/tegra/clk-tegra124-emc.c index bdf6f4a51617..74c1d894cca8 100644 --- a/drivers/clk/tegra/clk-tegra124-emc.c +++ b/drivers/clk/tegra/clk-tegra124-emc.c @@ -249,8 +249,10 @@ static int emc_set_timing(struct tegra_clk_emc *tegra, div = timing->parent_rate / (timing->rate / 2) - 2; err = tegra->prepare_timing_change(emc, timing->rate); - if (err) + if (err) { + clk_disable_unprepare(timing->parent); return err; + } spin_lock_irqsave(tegra->lock, flags); From 51c8b49762e497b6f72185af951b192e7678c61d Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Fri, 4 Jun 2021 12:20:22 -0700 Subject: [PATCH 049/161] clk: versatile: Depend on HAS_IOMEM kbuild robot reports that s390 fails to build this driver with COMPILE_TEST. Let's depend on HAS_IOMEM so that s390 doesn't try to build it. Cc: Lee Jones Acked-by: Linus Walleij Reported-by: kernel test robot Fixes: 419b3ab6987f ("clk: versatile: remove dependency on ARCH_*") Link: https://lore.kernel.org/r/20210604192321.2594519-1-sboyd@kernel.org Signed-off-by: Stephen Boyd --- drivers/clk/versatile/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/clk/versatile/Kconfig b/drivers/clk/versatile/Kconfig index 792315d893db..481de5657d85 100644 --- a/drivers/clk/versatile/Kconfig +++ b/drivers/clk/versatile/Kconfig @@ -1,6 +1,7 @@ # SPDX-License-Identifier: GPL-2.0-only menu "Clock driver for ARM Reference designs" + depends on HAS_IOMEM config ICST bool "Clock driver for ARM Reference designs ICST" From 4410c4236e6de337f35d4d88e503f414a8d5d10f Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Sat, 29 May 2021 17:04:37 +0200 Subject: [PATCH 050/161] mips: ar7: convert to clkdev_lookup ar7 is one of only two platforms that provide the clock interface but implement a custom version of the clkdev_lookup code. Change this to use the generic version instead. Signed-off-by: Arnd Bergmann --- arch/mips/Kconfig | 1 + arch/mips/ar7/clock.c | 31 +++++++++++-------------------- 2 files changed, 12 insertions(+), 20 deletions(-) diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index ed51970c08e7..1cc03a7652a9 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -215,6 +215,7 @@ config AR7 select SYS_SUPPORTS_ZBOOT_UART16550 select GPIOLIB select VLYNQ + select CLKDEV_LOOKUP select HAVE_LEGACY_CLK help Support for the Texas Instruments AR7 System-on-a-Chip diff --git a/arch/mips/ar7/clock.c b/arch/mips/ar7/clock.c index 95def949c971..e8648e3eb27b 100644 --- a/arch/mips/ar7/clock.c +++ b/arch/mips/ar7/clock.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -424,27 +425,15 @@ unsigned long clk_get_rate(struct clk *clk) } EXPORT_SYMBOL(clk_get_rate); -struct clk *clk_get(struct device *dev, const char *id) -{ - if (!strcmp(id, "bus")) - return &bus_clk; +static struct clk_lookup ar7_clkdev_table[] = { + CLKDEV_INIT(NULL, "bus", &bus_clk), /* cpmac and vbus share the same rate */ - if (!strcmp(id, "cpmac")) - return &vbus_clk; - if (!strcmp(id, "cpu")) - return &cpu_clk; - if (!strcmp(id, "dsp")) - return &dsp_clk; - if (!strcmp(id, "vbus")) - return &vbus_clk; - return ERR_PTR(-ENOENT); -} -EXPORT_SYMBOL(clk_get); - -void clk_put(struct clk *clk) -{ -} -EXPORT_SYMBOL(clk_put); + CLKDEV_INIT("cpmac.0", "cpmac", &vbus_clk), + CLKDEV_INIT("cpmac.1", "cpmac", &vbus_clk), + CLKDEV_INIT(NULL, "cpu", &cpu_clk), + CLKDEV_INIT(NULL, "dsp", &dsp_clk), + CLKDEV_INIT(NULL, "vbus", &vbus_clk), +}; void __init ar7_init_clocks(void) { @@ -462,6 +451,8 @@ void __init ar7_init_clocks(void) } /* adjust vbus clock rate */ vbus_clk.rate = bus_clk.rate / 2; + + clkdev_add_table(ar7_clkdev_table, ARRAY_SIZE(ar7_clkdev_table)); } /* dummy functions, should not be called */ From b408b611eb951594691abfee8ca687b405d27757 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 31 May 2021 15:22:37 +0200 Subject: [PATCH 051/161] mips: ar7: convert to CONFIG_COMMON_CLK Perform a minimal conversion of the ar7 clock implementation to the common clock framework. While the hardware can control the rates, this is left unchanged, and all clocks are registered as fixed-rate or fixed-divider clocks. Similarly, the clkdev lookup information is left unchanged but moved from the table format into individual allocations. There is a small increase in code size: text data bss dec hex filename 4757116 596640 91328 5445084 5315dc vmlinux-before 4806159 602360 91344 5499863 53ebd7 vmlinux-after Signed-off-by: Arnd Bergmann --- arch/mips/Kconfig | 3 +- arch/mips/ar7/clock.c | 104 ++++++++------------------- arch/mips/include/asm/mach-ar7/ar7.h | 4 -- 3 files changed, 30 insertions(+), 81 deletions(-) diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 1cc03a7652a9..5dbc60adb2f0 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -201,6 +201,7 @@ config MIPS_ALCHEMY config AR7 bool "Texas Instruments AR7" select BOOT_ELF32 + select COMMON_CLK select DMA_NONCOHERENT select CEVT_R4K select CSRC_R4K @@ -215,8 +216,6 @@ config AR7 select SYS_SUPPORTS_ZBOOT_UART16550 select GPIOLIB select VLYNQ - select CLKDEV_LOOKUP - select HAVE_LEGACY_CLK help Support for the Texas Instruments AR7 System-on-a-Chip family: TNETD7100, 7200 and 7300. diff --git a/arch/mips/ar7/clock.c b/arch/mips/ar7/clock.c index e8648e3eb27b..c717acbc5506 100644 --- a/arch/mips/ar7/clock.c +++ b/arch/mips/ar7/clock.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -85,17 +86,17 @@ struct tnetd7200_clocks { struct tnetd7200_clock usb; }; -static struct clk bus_clk = { +struct clk_rate { + u32 rate; +}; +static struct clk_rate bus_clk = { .rate = 125000000, }; -static struct clk cpu_clk = { +static struct clk_rate cpu_clk = { .rate = 150000000, }; -static struct clk dsp_clk; -static struct clk vbus_clk; - static void approximate(int base, int target, int *prediv, int *postdiv, int *mul) { @@ -241,6 +242,8 @@ static void __init tnetd7300_init_clocks(void) struct tnetd7300_clocks *clocks = ioremap(UR8_REGS_CLOCKS, sizeof(struct tnetd7300_clocks)); + u32 dsp_clk; + struct clk *clk; bus_clk.rate = tnetd7300_get_clock(BUS_PLL_SOURCE_SHIFT, &clocks->bus, bootcr, AR7_AFE_CLOCK); @@ -251,12 +254,18 @@ static void __init tnetd7300_init_clocks(void) else cpu_clk.rate = bus_clk.rate; - if (dsp_clk.rate == 250000000) + dsp_clk = tnetd7300_dsp_clock(); + if (dsp_clk == 250000000) tnetd7300_set_clock(DSP_PLL_SOURCE_SHIFT, &clocks->dsp, - bootcr, dsp_clk.rate); + bootcr, dsp_clk); iounmap(clocks); iounmap(bootcr); + + clk = clk_register_fixed_rate(NULL, "cpu", NULL, 0, cpu_clk.rate); + clkdev_create(clk, "cpu", NULL); + clk = clk_register_fixed_rate(NULL, "dsp", NULL, 0, dsp_clk); + clkdev_create(clk, "dsp", NULL); } static void tnetd7200_set_clock(int base, struct tnetd7200_clock *clock, @@ -328,6 +337,7 @@ static void __init tnetd7200_init_clocks(void) int cpu_base, cpu_mul, cpu_prediv, cpu_postdiv; int dsp_base, dsp_mul, dsp_prediv, dsp_postdiv; int usb_base, usb_mul, usb_prediv, usb_postdiv; + struct clk *clk; cpu_base = tnetd7200_get_clock_base(TNETD7200_CLOCK_ID_CPU, bootcr); dsp_base = tnetd7200_get_clock_base(TNETD7200_CLOCK_ID_DSP, bootcr); @@ -396,90 +406,34 @@ static void __init tnetd7200_init_clocks(void) usb_prediv, usb_postdiv, -1, usb_mul, TNETD7200_DEF_USB_CLK); - dsp_clk.rate = cpu_clk.rate; - iounmap(clocks); iounmap(bootcr); + + clk = clk_register_fixed_rate(NULL, "cpu", NULL, 0, cpu_clk.rate); + clkdev_create(clk, "cpu", NULL); + clkdev_create(clk, "dsp", NULL); } -/* - * Linux clock API - */ -int clk_enable(struct clk *clk) -{ - return 0; -} -EXPORT_SYMBOL(clk_enable); - -void clk_disable(struct clk *clk) -{ -} -EXPORT_SYMBOL(clk_disable); - -unsigned long clk_get_rate(struct clk *clk) -{ - if (!clk) - return 0; - - return clk->rate; -} -EXPORT_SYMBOL(clk_get_rate); - -static struct clk_lookup ar7_clkdev_table[] = { - CLKDEV_INIT(NULL, "bus", &bus_clk), - /* cpmac and vbus share the same rate */ - CLKDEV_INIT("cpmac.0", "cpmac", &vbus_clk), - CLKDEV_INIT("cpmac.1", "cpmac", &vbus_clk), - CLKDEV_INIT(NULL, "cpu", &cpu_clk), - CLKDEV_INIT(NULL, "dsp", &dsp_clk), - CLKDEV_INIT(NULL, "vbus", &vbus_clk), -}; - void __init ar7_init_clocks(void) { + struct clk *clk; + switch (ar7_chip_id()) { case AR7_CHIP_7100: case AR7_CHIP_7200: tnetd7200_init_clocks(); break; case AR7_CHIP_7300: - dsp_clk.rate = tnetd7300_dsp_clock(); tnetd7300_init_clocks(); break; default: break; } + clk = clk_register_fixed_rate(NULL, "bus", NULL, 0, bus_clk.rate); + clkdev_create(clk, "bus", NULL); /* adjust vbus clock rate */ - vbus_clk.rate = bus_clk.rate / 2; - - clkdev_add_table(ar7_clkdev_table, ARRAY_SIZE(ar7_clkdev_table)); + clk = clk_register_fixed_factor(NULL, "vbus", "bus", 0, 1, 2); + clkdev_create(clk, "vbus", NULL); + clkdev_create(clk, "cpmac", "cpmac.1"); + clkdev_create(clk, "cpmac", "cpmac.1"); } - -/* dummy functions, should not be called */ -long clk_round_rate(struct clk *clk, unsigned long rate) -{ - WARN_ON(clk); - return 0; -} -EXPORT_SYMBOL(clk_round_rate); - -int clk_set_rate(struct clk *clk, unsigned long rate) -{ - WARN_ON(clk); - return 0; -} -EXPORT_SYMBOL(clk_set_rate); - -int clk_set_parent(struct clk *clk, struct clk *parent) -{ - WARN_ON(clk); - return 0; -} -EXPORT_SYMBOL(clk_set_parent); - -struct clk *clk_get_parent(struct clk *clk) -{ - WARN_ON(clk); - return NULL; -} -EXPORT_SYMBOL(clk_get_parent); diff --git a/arch/mips/include/asm/mach-ar7/ar7.h b/arch/mips/include/asm/mach-ar7/ar7.h index dd09c3bf0601..cbe75ade3277 100644 --- a/arch/mips/include/asm/mach-ar7/ar7.h +++ b/arch/mips/include/asm/mach-ar7/ar7.h @@ -131,10 +131,6 @@ static inline u8 ar7_chip_rev(void) 0x14))) >> 16) & 0xff; } -struct clk { - unsigned int rate; -}; - static inline int ar7_has_high_cpmac(void) { u16 chip_id = ar7_chip_id(); From 35f752be4f412a1a58f4c15fa9282c53b956e067 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 31 May 2021 13:51:18 +0200 Subject: [PATCH 052/161] mips: ralink: convert to CONFIG_COMMON_CLK ralink only has a very trivial clock implementation, with everything being fixed clocks. Convert it to CONFIG_COMMON_CLK to reduce the number of platforms that rely on legacy clocks. Of course, the clocks really should be read from the device tree instead, but this is a step into that direction. This adds about 50KB to the kernel image size, which is an unfortunate increase, but not as bad as I had feared: text data bss dec hex filename 3778560 1582216 92256 5453032 5334e8 vmlinux-vocore-before 3822148 1601192 92304 5515644 54297c vmlinux-vocore-after 3870226 1644468 200192 5714886 5733c6 vmlinux-rt305x-before 3916727 1668404 200240 5785371 58471b vmlinux-rt305x-after Signed-off-by: Arnd Bergmann --- arch/mips/Kconfig | 1 + arch/mips/ralink/Kconfig | 5 ---- arch/mips/ralink/clk.c | 64 ++-------------------------------------- 3 files changed, 4 insertions(+), 66 deletions(-) diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 5dbc60adb2f0..8fe6b30de7dd 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -630,6 +630,7 @@ config MACH_NINTENDO64 config RALINK bool "Ralink based machines" select CEVT_R4K + select COMMON_CLK select CSRC_R4K select BOOT_RAW select DMA_NONCOHERENT diff --git a/arch/mips/ralink/Kconfig b/arch/mips/ralink/Kconfig index ec4daa63c5e3..c800bf5559b5 100644 --- a/arch/mips/ralink/Kconfig +++ b/arch/mips/ralink/Kconfig @@ -28,22 +28,18 @@ choice bool "RT288x" select MIPS_AUTO_PFN_OFFSET select MIPS_L1_CACHE_SHIFT_4 - select HAVE_LEGACY_CLK select HAVE_PCI config SOC_RT305X bool "RT305x" - select HAVE_LEGACY_CLK config SOC_RT3883 bool "RT3883" - select HAVE_LEGACY_CLK select HAVE_PCI config SOC_MT7620 bool "MT7620/8" select CPU_MIPSR2_IRQ_VI - select HAVE_LEGACY_CLK select HAVE_PCI config SOC_MT7621 @@ -54,7 +50,6 @@ choice select SYS_SUPPORTS_MIPS_CPS select SYS_SUPPORTS_HIGHMEM select MIPS_GIC - select COMMON_CLK select CLKSRC_MIPS_GIC select HAVE_PCI if PCI_MT7621 select SOC_BUS diff --git a/arch/mips/ralink/clk.c b/arch/mips/ralink/clk.c index f0bcb1051c30..5b02bb7e0829 100644 --- a/arch/mips/ralink/clk.c +++ b/arch/mips/ralink/clk.c @@ -10,80 +10,22 @@ #include #include #include +#include #include #include "common.h" -struct clk { - struct clk_lookup cl; - unsigned long rate; -}; - void ralink_clk_add(const char *dev, unsigned long rate) { - struct clk *clk = kzalloc(sizeof(struct clk), GFP_KERNEL); + struct clk *clk = clk_register_fixed_rate(NULL, dev, NULL, 0, rate); if (!clk) panic("failed to add clock"); - clk->cl.dev_id = dev; - clk->cl.clk = clk; - - clk->rate = rate; - - clkdev_add(&clk->cl); + clkdev_create(clk, NULL, "%s", dev); } -/* - * Linux clock API - */ -int clk_enable(struct clk *clk) -{ - return 0; -} -EXPORT_SYMBOL_GPL(clk_enable); - -void clk_disable(struct clk *clk) -{ -} -EXPORT_SYMBOL_GPL(clk_disable); - -unsigned long clk_get_rate(struct clk *clk) -{ - if (!clk) - return 0; - - return clk->rate; -} -EXPORT_SYMBOL_GPL(clk_get_rate); - -int clk_set_rate(struct clk *clk, unsigned long rate) -{ - return -1; -} -EXPORT_SYMBOL_GPL(clk_set_rate); - -long clk_round_rate(struct clk *clk, unsigned long rate) -{ - return -1; -} -EXPORT_SYMBOL_GPL(clk_round_rate); - -int clk_set_parent(struct clk *clk, struct clk *parent) -{ - WARN_ON(clk); - return -1; -} -EXPORT_SYMBOL_GPL(clk_set_parent); - -struct clk *clk_get_parent(struct clk *clk) -{ - WARN_ON(clk); - return NULL; -} -EXPORT_SYMBOL_GPL(clk_get_parent); - void __init plat_time_init(void) { struct clk *clk; From 63aadb77669a6856b26d73da85b4f788731524a3 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 31 May 2021 11:12:55 +0200 Subject: [PATCH 053/161] m68k: coldfire: use clkdev_lookup on most coldfire Coldfire is now the only target that implements the clk_get()/clk_put() helpers itself rather than using the common implementation. Most coldfire variants only have two distinct clocks and use the clk code purely for lookup. Change those over to use clkdev_lookup instead but leave the custom clk interface for those two clocks. Also leave the four SoCs that have gated clocks. Acked-by: Greg Ungerer Tested-by: Greg Ungerer Signed-off-by: Arnd Bergmann --- arch/m68k/Kconfig.cpu | 4 ++++ arch/m68k/coldfire/clk.c | 16 +++++++-------- arch/m68k/coldfire/m5206.c | 25 ++++++++++------------- arch/m68k/coldfire/m523x.c | 40 +++++++++++++++--------------------- arch/m68k/coldfire/m5249.c | 31 ++++++++++++---------------- arch/m68k/coldfire/m525x.c | 31 ++++++++++++---------------- arch/m68k/coldfire/m5272.c | 33 ++++++++++++------------------ arch/m68k/coldfire/m527x.c | 42 +++++++++++++++----------------------- arch/m68k/coldfire/m528x.c | 40 +++++++++++++++--------------------- arch/m68k/coldfire/m5307.c | 25 ++++++++++------------- arch/m68k/coldfire/m5407.c | 25 ++++++++++------------- arch/m68k/coldfire/m54xx.c | 31 ++++++++++++---------------- 12 files changed, 145 insertions(+), 198 deletions(-) diff --git a/arch/m68k/Kconfig.cpu b/arch/m68k/Kconfig.cpu index f4d23977d2a5..b3483929b313 100644 --- a/arch/m68k/Kconfig.cpu +++ b/arch/m68k/Kconfig.cpu @@ -328,6 +328,10 @@ config COLDFIRE_SLTIMERS bool select LEGACY_TIMER_TICK +config COLDFIRE_CLKDEV_LOOKUP + def_bool !(M5206 || M5206e || M53xx || M5441x) + select CLKDEV_LOOKUP + endif # COLDFIRE diff --git a/arch/m68k/coldfire/clk.c b/arch/m68k/coldfire/clk.c index 076a9caa9557..ffe36627bab8 100644 --- a/arch/m68k/coldfire/clk.c +++ b/arch/m68k/coldfire/clk.c @@ -71,7 +71,6 @@ struct clk_ops clk_ops1 = { .disable = __clk_disable1, }; #endif /* MCFPM_PPMCR1 */ -#endif /* MCFPM_PPMCR0 */ struct clk *clk_get(struct device *dev, const char *id) { @@ -87,6 +86,14 @@ struct clk *clk_get(struct device *dev, const char *id) } EXPORT_SYMBOL(clk_get); +void clk_put(struct clk *clk) +{ + if (clk->enabled != 0) + pr_warn("clk_put %s still enabled\n", clk->name); +} +EXPORT_SYMBOL(clk_put); +#endif /* MCFPM_PPMCR0 */ + int clk_enable(struct clk *clk) { unsigned long flags; @@ -117,13 +124,6 @@ void clk_disable(struct clk *clk) } EXPORT_SYMBOL(clk_disable); -void clk_put(struct clk *clk) -{ - if (clk->enabled != 0) - pr_warn("clk_put %s still enabled\n", clk->name); -} -EXPORT_SYMBOL(clk_put); - unsigned long clk_get_rate(struct clk *clk) { if (!clk) diff --git a/arch/m68k/coldfire/m5206.c b/arch/m68k/coldfire/m5206.c index 2f14ea95c391..5e726e94b5ab 100644 --- a/arch/m68k/coldfire/m5206.c +++ b/arch/m68k/coldfire/m5206.c @@ -10,6 +10,7 @@ /***************************************************************************/ +#include #include #include #include @@ -23,21 +24,15 @@ DEFINE_CLK(pll, "pll.0", MCF_CLK); DEFINE_CLK(sys, "sys.0", MCF_BUSCLK); -DEFINE_CLK(mcftmr0, "mcftmr.0", MCF_BUSCLK); -DEFINE_CLK(mcftmr1, "mcftmr.1", MCF_BUSCLK); -DEFINE_CLK(mcfuart0, "mcfuart.0", MCF_BUSCLK); -DEFINE_CLK(mcfuart1, "mcfuart.1", MCF_BUSCLK); -DEFINE_CLK(mcfi2c0, "imx1-i2c.0", MCF_BUSCLK); -struct clk *mcf_clks[] = { - &clk_pll, - &clk_sys, - &clk_mcftmr0, - &clk_mcftmr1, - &clk_mcfuart0, - &clk_mcfuart1, - &clk_mcfi2c0, - NULL +static struct clk_lookup m5206_clk_lookup[] = { + CLKDEV_INIT(NULL, "pll.0", &clk_pll), + CLKDEV_INIT(NULL, "sys.0", &clk_sys), + CLKDEV_INIT("mcftmr.0", NULL, &clk_sys), + CLKDEV_INIT("mcftmr.1", NULL, &clk_sys), + CLKDEV_INIT("mcfuart.0", NULL, &clk_sys), + CLKDEV_INIT("mcfuart.1", NULL, &clk_sys), + CLKDEV_INIT("imx1-i2c.0", NULL, &clk_sys), }; /***************************************************************************/ @@ -66,6 +61,8 @@ void __init config_BSP(char *commandp, int size) mcf_mapirq2imr(28, MCFINTC_EINT4); mcf_mapirq2imr(31, MCFINTC_EINT7); m5206_i2c_init(); + + clkdev_add_table(m5206_clk_lookup, ARRAY_SIZE(m5206_clk_lookup)); } /***************************************************************************/ diff --git a/arch/m68k/coldfire/m523x.c b/arch/m68k/coldfire/m523x.c index ddf2496ed117..193c178162c1 100644 --- a/arch/m68k/coldfire/m523x.c +++ b/arch/m68k/coldfire/m523x.c @@ -13,6 +13,7 @@ /***************************************************************************/ +#include #include #include #include @@ -26,31 +27,20 @@ DEFINE_CLK(pll, "pll.0", MCF_CLK); DEFINE_CLK(sys, "sys.0", MCF_BUSCLK); -DEFINE_CLK(mcfpit0, "mcfpit.0", MCF_CLK); -DEFINE_CLK(mcfpit1, "mcfpit.1", MCF_CLK); -DEFINE_CLK(mcfpit2, "mcfpit.2", MCF_CLK); -DEFINE_CLK(mcfpit3, "mcfpit.3", MCF_CLK); -DEFINE_CLK(mcfuart0, "mcfuart.0", MCF_BUSCLK); -DEFINE_CLK(mcfuart1, "mcfuart.1", MCF_BUSCLK); -DEFINE_CLK(mcfuart2, "mcfuart.2", MCF_BUSCLK); -DEFINE_CLK(mcfqspi0, "mcfqspi.0", MCF_BUSCLK); -DEFINE_CLK(fec0, "fec.0", MCF_BUSCLK); -DEFINE_CLK(mcfi2c0, "imx1-i2c.0", MCF_BUSCLK); -struct clk *mcf_clks[] = { - &clk_pll, - &clk_sys, - &clk_mcfpit0, - &clk_mcfpit1, - &clk_mcfpit2, - &clk_mcfpit3, - &clk_mcfuart0, - &clk_mcfuart1, - &clk_mcfuart2, - &clk_mcfqspi0, - &clk_fec0, - &clk_mcfi2c0, - NULL +struct clk_lookup m523x_clk_lookup[] = { + CLKDEV_INIT(NULL, "pll.0", &clk_pll), + CLKDEV_INIT(NULL, "sys.0", &clk_sys), + CLKDEV_INIT("mcfpit.0", NULL, &clk_pll), + CLKDEV_INIT("mcfpit.1", NULL, &clk_pll), + CLKDEV_INIT("mcfpit.2", NULL, &clk_pll), + CLKDEV_INIT("mcfpit.3", NULL, &clk_pll), + CLKDEV_INIT("mcfuart.0", NULL, &clk_sys), + CLKDEV_INIT("mcfuart.1", NULL, &clk_sys), + CLKDEV_INIT("mcfuart.2", NULL, &clk_sys), + CLKDEV_INIT("mcfqspi.0", NULL, &clk_sys), + CLKDEV_INIT("fec.0", NULL, &clk_sys), + CLKDEV_INIT("imx1-i2c.0", NULL, &clk_sys), }; /***************************************************************************/ @@ -100,6 +90,8 @@ void __init config_BSP(char *commandp, int size) m523x_fec_init(); m523x_qspi_init(); m523x_i2c_init(); + + clkdev_add_table(m523x_clk_lookup, ARRAY_SIZE(m523x_clk_lookup)); } /***************************************************************************/ diff --git a/arch/m68k/coldfire/m5249.c b/arch/m68k/coldfire/m5249.c index 0590f8c421f1..6d66972de214 100644 --- a/arch/m68k/coldfire/m5249.c +++ b/arch/m68k/coldfire/m5249.c @@ -9,6 +9,7 @@ /***************************************************************************/ +#include #include #include #include @@ -23,25 +24,17 @@ DEFINE_CLK(pll, "pll.0", MCF_CLK); DEFINE_CLK(sys, "sys.0", MCF_BUSCLK); -DEFINE_CLK(mcftmr0, "mcftmr.0", MCF_BUSCLK); -DEFINE_CLK(mcftmr1, "mcftmr.1", MCF_BUSCLK); -DEFINE_CLK(mcfuart0, "mcfuart.0", MCF_BUSCLK); -DEFINE_CLK(mcfuart1, "mcfuart.1", MCF_BUSCLK); -DEFINE_CLK(mcfqspi0, "mcfqspi.0", MCF_BUSCLK); -DEFINE_CLK(mcfi2c0, "imx1-i2c.0", MCF_BUSCLK); -DEFINE_CLK(mcfi2c1, "imx1-i2c.1", MCF_BUSCLK); -struct clk *mcf_clks[] = { - &clk_pll, - &clk_sys, - &clk_mcftmr0, - &clk_mcftmr1, - &clk_mcfuart0, - &clk_mcfuart1, - &clk_mcfqspi0, - &clk_mcfi2c0, - &clk_mcfi2c1, - NULL +struct clk_lookup m5249_clk_lookup[] = { + CLKDEV_INIT(NULL, "pll.0", &clk_pll), + CLKDEV_INIT(NULL, "sys.0", &clk_sys), + CLKDEV_INIT("mcftmr.0", NULL, &clk_sys), + CLKDEV_INIT("mcftmr.1", NULL, &clk_sys), + CLKDEV_INIT("mcfuart.0", NULL, &clk_sys), + CLKDEV_INIT("mcfuart.1", NULL, &clk_sys), + CLKDEV_INIT("mcfqspi.0", NULL, &clk_sys), + CLKDEV_INIT("imx1-i2c.0", NULL, &clk_sys), + CLKDEV_INIT("imx1-i2c.1", NULL, &clk_sys), }; /***************************************************************************/ @@ -137,6 +130,8 @@ void __init config_BSP(char *commandp, int size) #endif m5249_qspi_init(); m5249_i2c_init(); + + clkdev_add_table(m5249_clk_lookup, ARRAY_SIZE(m5249_clk_lookup)); } /***************************************************************************/ diff --git a/arch/m68k/coldfire/m525x.c b/arch/m68k/coldfire/m525x.c index 1772359c416c..2c4d2ca2f20d 100644 --- a/arch/m68k/coldfire/m525x.c +++ b/arch/m68k/coldfire/m525x.c @@ -9,6 +9,7 @@ /***************************************************************************/ +#include #include #include #include @@ -23,25 +24,17 @@ DEFINE_CLK(pll, "pll.0", MCF_CLK); DEFINE_CLK(sys, "sys.0", MCF_BUSCLK); -DEFINE_CLK(mcftmr0, "mcftmr.0", MCF_BUSCLK); -DEFINE_CLK(mcftmr1, "mcftmr.1", MCF_BUSCLK); -DEFINE_CLK(mcfuart0, "mcfuart.0", MCF_BUSCLK); -DEFINE_CLK(mcfuart1, "mcfuart.1", MCF_BUSCLK); -DEFINE_CLK(mcfqspi0, "mcfqspi.0", MCF_BUSCLK); -DEFINE_CLK(mcfi2c0, "imx1-i2c.0", MCF_BUSCLK); -DEFINE_CLK(mcfi2c1, "imx1-i2c.1", MCF_BUSCLK); -struct clk *mcf_clks[] = { - &clk_pll, - &clk_sys, - &clk_mcftmr0, - &clk_mcftmr1, - &clk_mcfuart0, - &clk_mcfuart1, - &clk_mcfqspi0, - &clk_mcfi2c0, - &clk_mcfi2c1, - NULL +static struct clk_lookup m525x_clk_lookup[] = { + CLKDEV_INIT(NULL, "pll.0", &pll), + CLKDEV_INIT(NULL, "sys.0", &clk_sys), + CLKDEV_INIT("mcftmr.0", NULL, &clk_sys), + CLKDEV_INIT("mcftmr.1", NULL, &clk_sys), + CLKDEV_INIT("mcfuart.0", NULL, &clk_sys), + CLKDEV_INIT("mcfuart.1", NULL, &clk_sys), + CLKDEV_INIT("mcfqspi.0", NULL, &clk_sys), + CLKDEV_INIT("imx1-i2c.0", NULL, &clk_sys), + CLKDEV_INIT("imx1-i2c.1", NULL, &clk_sys), }; /***************************************************************************/ @@ -88,6 +81,8 @@ void __init config_BSP(char *commandp, int size) m525x_qspi_init(); m525x_i2c_init(); + + clkdev_add_table(m525x_clk_lookup, ARRAY_SIZE(m525x_clk_lookup)); } /***************************************************************************/ diff --git a/arch/m68k/coldfire/m5272.c b/arch/m68k/coldfire/m5272.c index 6b3ab583c698..734dab657fe3 100644 --- a/arch/m68k/coldfire/m5272.c +++ b/arch/m68k/coldfire/m5272.c @@ -10,6 +10,7 @@ /***************************************************************************/ +#include #include #include #include @@ -34,27 +35,18 @@ unsigned char ledbank = 0xff; DEFINE_CLK(pll, "pll.0", MCF_CLK); DEFINE_CLK(sys, "sys.0", MCF_BUSCLK); -DEFINE_CLK(mcftmr0, "mcftmr.0", MCF_BUSCLK); -DEFINE_CLK(mcftmr1, "mcftmr.1", MCF_BUSCLK); -DEFINE_CLK(mcftmr2, "mcftmr.2", MCF_BUSCLK); -DEFINE_CLK(mcftmr3, "mcftmr.3", MCF_BUSCLK); -DEFINE_CLK(mcfuart0, "mcfuart.0", MCF_BUSCLK); -DEFINE_CLK(mcfuart1, "mcfuart.1", MCF_BUSCLK); -DEFINE_CLK(mcfqspi0, "mcfqspi.0", MCF_BUSCLK); -DEFINE_CLK(fec0, "fec.0", MCF_BUSCLK); -struct clk *mcf_clks[] = { - &clk_pll, - &clk_sys, - &clk_mcftmr0, - &clk_mcftmr1, - &clk_mcftmr2, - &clk_mcftmr3, - &clk_mcfuart0, - &clk_mcfuart1, - &clk_mcfqspi0, - &clk_fec0, - NULL +static struct clk_lookup m5272_clk_lookup[] = { + CLKDEV_INIT(NULL, "pll.0", &clk_pll), + CLKDEV_INIT(NULL, "sys.0", &clk_sys), + CLKDEV_INIT("mcftmr.0", NULL, &clk_sys), + CLKDEV_INIT("mcftmr.1", NULL, &clk_sys), + CLKDEV_INIT("mcftmr.2", NULL, &clk_sys), + CLKDEV_INIT("mcftmr.3", NULL, &clk_sys), + CLKDEV_INIT("mcfuart.0", NULL, &clk_sys), + CLKDEV_INIT("mcfuart.1", NULL, &clk_sys), + CLKDEV_INIT("mcfqspi.0", NULL, &clk_sys), + CLKDEV_INIT("fec.0", NULL, &clk_sys), }; /***************************************************************************/ @@ -128,6 +120,7 @@ static int __init init_BSP(void) { m5272_uarts_init(); fixed_phy_add(PHY_POLL, 0, &nettel_fixed_phy_status); + clkdev_add_table(m5272_clk_lookup, ARRAY_SIZE(m5272_clk_lookup)); return 0; } diff --git a/arch/m68k/coldfire/m527x.c b/arch/m68k/coldfire/m527x.c index cad462df6861..037f3e520acc 100644 --- a/arch/m68k/coldfire/m527x.c +++ b/arch/m68k/coldfire/m527x.c @@ -13,6 +13,7 @@ /***************************************************************************/ +#include #include #include #include @@ -27,33 +28,21 @@ DEFINE_CLK(pll, "pll.0", MCF_CLK); DEFINE_CLK(sys, "sys.0", MCF_BUSCLK); -DEFINE_CLK(mcfpit0, "mcfpit.0", MCF_CLK); -DEFINE_CLK(mcfpit1, "mcfpit.1", MCF_CLK); -DEFINE_CLK(mcfpit2, "mcfpit.2", MCF_CLK); -DEFINE_CLK(mcfpit3, "mcfpit.3", MCF_CLK); -DEFINE_CLK(mcfuart0, "mcfuart.0", MCF_BUSCLK); -DEFINE_CLK(mcfuart1, "mcfuart.1", MCF_BUSCLK); -DEFINE_CLK(mcfuart2, "mcfuart.2", MCF_BUSCLK); -DEFINE_CLK(mcfqspi0, "mcfqspi.0", MCF_BUSCLK); -DEFINE_CLK(fec0, "fec.0", MCF_BUSCLK); -DEFINE_CLK(fec1, "fec.1", MCF_BUSCLK); -DEFINE_CLK(mcfi2c0, "imx1-i2c.0", MCF_BUSCLK); -struct clk *mcf_clks[] = { - &clk_pll, - &clk_sys, - &clk_mcfpit0, - &clk_mcfpit1, - &clk_mcfpit2, - &clk_mcfpit3, - &clk_mcfuart0, - &clk_mcfuart1, - &clk_mcfuart2, - &clk_mcfqspi0, - &clk_fec0, - &clk_fec1, - &clk_mcfi2c0, - NULL +static struct clk_lookup m527x_clk_lookup[] = { + CLKDEV_INIT(NULL, "pll.0", &clk_pll), + CLKDEV_INIT(NULL, "sys.0", &clk_sys), + CLKDEV_INIT("mcfpit.0", NULL, &clk_pll), + CLKDEV_INIT("mcfpit.1", NULL, &clk_pll), + CLKDEV_INIT("mcfpit.2", NULL, &clk_pll), + CLKDEV_INIT("mcfpit.3", NULL, &clk_pll), + CLKDEV_INIT("mcfuart.0", NULL, &clk_sys), + CLKDEV_INIT("mcfuart.1", NULL, &clk_sys), + CLKDEV_INIT("mcfuart.2", NULL, &clk_sys), + CLKDEV_INIT("mcfqspi.0", NULL, &clk_sys), + CLKDEV_INIT("fec.0", NULL, &clk_sys), + CLKDEV_INIT("fec.1", NULL, &clk_sys), + CLKDEV_INIT("imx1-i2c.0", NULL, &clk_sys), }; /***************************************************************************/ @@ -151,6 +140,7 @@ void __init config_BSP(char *commandp, int size) m527x_fec_init(); m527x_qspi_init(); m527x_i2c_init(); + clkdev_add_table(m527x_clk_lookup, ARRAY_SIZE(m527x_clk_lookup)); } /***************************************************************************/ diff --git a/arch/m68k/coldfire/m528x.c b/arch/m68k/coldfire/m528x.c index 7ad3193887e8..51a6a6236e12 100644 --- a/arch/m68k/coldfire/m528x.c +++ b/arch/m68k/coldfire/m528x.c @@ -13,6 +13,7 @@ /***************************************************************************/ +#include #include #include #include @@ -28,31 +29,20 @@ DEFINE_CLK(pll, "pll.0", MCF_CLK); DEFINE_CLK(sys, "sys.0", MCF_BUSCLK); -DEFINE_CLK(mcfpit0, "mcfpit.0", MCF_CLK); -DEFINE_CLK(mcfpit1, "mcfpit.1", MCF_CLK); -DEFINE_CLK(mcfpit2, "mcfpit.2", MCF_CLK); -DEFINE_CLK(mcfpit3, "mcfpit.3", MCF_CLK); -DEFINE_CLK(mcfuart0, "mcfuart.0", MCF_BUSCLK); -DEFINE_CLK(mcfuart1, "mcfuart.1", MCF_BUSCLK); -DEFINE_CLK(mcfuart2, "mcfuart.2", MCF_BUSCLK); -DEFINE_CLK(mcfqspi0, "mcfqspi.0", MCF_BUSCLK); -DEFINE_CLK(fec0, "fec.0", MCF_BUSCLK); -DEFINE_CLK(mcfi2c0, "imx1-i2c.0", MCF_BUSCLK); -struct clk *mcf_clks[] = { - &clk_pll, - &clk_sys, - &clk_mcfpit0, - &clk_mcfpit1, - &clk_mcfpit2, - &clk_mcfpit3, - &clk_mcfuart0, - &clk_mcfuart1, - &clk_mcfuart2, - &clk_mcfqspi0, - &clk_fec0, - &clk_mcfi2c0, - NULL +static struct clk_lookup m528x_clk_lookup[] = { + CLKDEV_INIT(NULL, "pll.0", &clk_pll), + CLKDEV_INIT(NULL, "sys.0", &clk_sys), + CLKDEV_INIT("mcfpit.0", NULL, &clk_pll), + CLKDEV_INIT("mcfpit.1", NULL, &clk_pll), + CLKDEV_INIT("mcfpit.2", NULL, &clk_pll), + CLKDEV_INIT("mcfpit.3", NULL, &clk_pll), + CLKDEV_INIT("mcfuart.0", NULL, &clk_sys), + CLKDEV_INIT("mcfuart.1", NULL, &clk_sys), + CLKDEV_INIT("mcfuart.2", NULL, &clk_sys), + CLKDEV_INIT("mcfqspi.0", NULL, &clk_sys), + CLKDEV_INIT("fec.0", NULL, &clk_sys), + CLKDEV_INIT("imx1-i2c.0", NULL, &clk_sys), }; /***************************************************************************/ @@ -146,6 +136,8 @@ void __init config_BSP(char *commandp, int size) m528x_fec_init(); m528x_qspi_init(); m528x_i2c_init(); + + clkdev_add_table(m528x_clk_lookup, ARRAY_SIZE(m528x_clk_lookup)); } /***************************************************************************/ diff --git a/arch/m68k/coldfire/m5307.c b/arch/m68k/coldfire/m5307.c index 64b4b1fd34ff..4ed2e43ab3ad 100644 --- a/arch/m68k/coldfire/m5307.c +++ b/arch/m68k/coldfire/m5307.c @@ -10,6 +10,7 @@ /***************************************************************************/ +#include #include #include #include @@ -32,21 +33,15 @@ unsigned char ledbank = 0xff; DEFINE_CLK(pll, "pll.0", MCF_CLK); DEFINE_CLK(sys, "sys.0", MCF_BUSCLK); -DEFINE_CLK(mcftmr0, "mcftmr.0", MCF_BUSCLK); -DEFINE_CLK(mcftmr1, "mcftmr.1", MCF_BUSCLK); -DEFINE_CLK(mcfuart0, "mcfuart.0", MCF_BUSCLK); -DEFINE_CLK(mcfuart1, "mcfuart.1", MCF_BUSCLK); -DEFINE_CLK(mcfi2c0, "imx1-i2c.0", MCF_BUSCLK); -struct clk *mcf_clks[] = { - &clk_pll, - &clk_sys, - &clk_mcftmr0, - &clk_mcftmr1, - &clk_mcfuart0, - &clk_mcfuart1, - &clk_mcfi2c0, - NULL +static struct clk_lookup m5307_clk_lookup[] = { + CLKDEV_INIT(NULL, "pll.0", &clk_pll), + CLKDEV_INIT(NULL, "sys.0", &clk_sys), + CLKDEV_INIT("mcftmr.0", NULL, &clk_sys), + CLKDEV_INIT("mcftmr.1", NULL, &clk_sys), + CLKDEV_INIT("mcfuart.0", NULL, &clk_sys), + CLKDEV_INIT("mcfuart.1", NULL, &clk_sys), + CLKDEV_INIT("imx1-i2c.0", NULL, &clk_sys), }; /***************************************************************************/ @@ -88,6 +83,8 @@ void __init config_BSP(char *commandp, int size) wdebug(MCFDEBUG_CSR, MCFDEBUG_CSR_PSTCLK); #endif m5307_i2c_init(); + + clkdev_add_table(m5307_clk_lookup, ARRAY_SIZE(m5307_clk_lookup)); } /***************************************************************************/ diff --git a/arch/m68k/coldfire/m5407.c b/arch/m68k/coldfire/m5407.c index 0400d76115a1..b32efb3042a2 100644 --- a/arch/m68k/coldfire/m5407.c +++ b/arch/m68k/coldfire/m5407.c @@ -10,6 +10,7 @@ /***************************************************************************/ +#include #include #include #include @@ -23,21 +24,15 @@ DEFINE_CLK(pll, "pll.0", MCF_CLK); DEFINE_CLK(sys, "sys.0", MCF_BUSCLK); -DEFINE_CLK(mcftmr0, "mcftmr.0", MCF_BUSCLK); -DEFINE_CLK(mcftmr1, "mcftmr.1", MCF_BUSCLK); -DEFINE_CLK(mcfuart0, "mcfuart.0", MCF_BUSCLK); -DEFINE_CLK(mcfuart1, "mcfuart.1", MCF_BUSCLK); -DEFINE_CLK(mcfi2c0, "imx1-i2c.0", MCF_BUSCLK); -struct clk *mcf_clks[] = { - &clk_pll, - &clk_sys, - &clk_mcftmr0, - &clk_mcftmr1, - &clk_mcfuart0, - &clk_mcfuart1, - &clk_mcfi2c0, - NULL +static struct clk_lookup m5407_clk_lookup[] = { + CLKDEV_INIT(NULL, "pll.0", &clk_pll), + CLKDEV_INIT(NULL, "sys.0", &clk_sys), + CLKDEV_INIT("mcftmr.0", NULL, &clk_sys), + CLKDEV_INIT("mcftmr.1", NULL, &clk_sys), + CLKDEV_INIT("mcfuart.0", NULL, &clk_sys), + CLKDEV_INIT("mcfuart.1", NULL, &clk_sys), + CLKDEV_INIT("imx1-i2c.0", NULL, &clk_sys), }; /***************************************************************************/ @@ -63,6 +58,8 @@ void __init config_BSP(char *commandp, int size) mcf_mapirq2imr(29, MCFINTC_EINT5); mcf_mapirq2imr(31, MCFINTC_EINT7); m5407_i2c_init(); + + clkdev_add_table(m5407_clk_lookup, ARRAY_SIZE(m5407_clk_lookup)); } /***************************************************************************/ diff --git a/arch/m68k/coldfire/m54xx.c b/arch/m68k/coldfire/m54xx.c index 360c723c0ae6..8e3c8fee8327 100644 --- a/arch/m68k/coldfire/m54xx.c +++ b/arch/m68k/coldfire/m54xx.c @@ -9,6 +9,7 @@ /***************************************************************************/ +#include #include #include #include @@ -32,25 +33,17 @@ DEFINE_CLK(pll, "pll.0", MCF_CLK); DEFINE_CLK(sys, "sys.0", MCF_BUSCLK); -DEFINE_CLK(mcfslt0, "mcfslt.0", MCF_BUSCLK); -DEFINE_CLK(mcfslt1, "mcfslt.1", MCF_BUSCLK); -DEFINE_CLK(mcfuart0, "mcfuart.0", MCF_BUSCLK); -DEFINE_CLK(mcfuart1, "mcfuart.1", MCF_BUSCLK); -DEFINE_CLK(mcfuart2, "mcfuart.2", MCF_BUSCLK); -DEFINE_CLK(mcfuart3, "mcfuart.3", MCF_BUSCLK); -DEFINE_CLK(mcfi2c0, "imx1-i2c.0", MCF_BUSCLK); -struct clk *mcf_clks[] = { - &clk_pll, - &clk_sys, - &clk_mcfslt0, - &clk_mcfslt1, - &clk_mcfuart0, - &clk_mcfuart1, - &clk_mcfuart2, - &clk_mcfuart3, - &clk_mcfi2c0, - NULL +static struct clk_lookup m54xx_clk_lookup[] = { + CLKDEV_INIT(NULL, "pll.0", &clk_pll), + CLKDEV_INIT(NULL, "sys.0", &clk_sys), + CLKDEV_INIT("mcfslt.0", NULL, &clk_sys), + CLKDEV_INIT("mcfslt.1", NULL, &clk_sys), + CLKDEV_INIT("mcfuart.0", NULL, &clk_sys), + CLKDEV_INIT("mcfuart.1", NULL, &clk_sys), + CLKDEV_INIT("mcfuart.2", NULL, &clk_sys), + CLKDEV_INIT("mcfuart.3", NULL, &clk_sys), + CLKDEV_INIT("imx1-i2c.0", NULL, &clk_sys), }; /***************************************************************************/ @@ -100,6 +93,8 @@ void __init config_BSP(char *commandp, int size) mach_sched_init = hw_timer_init; m54xx_uarts_init(); m54xx_i2c_init(); + + clkdev_add_table(m54xx_clk_lookup, ARRAY_SIZE(m54xx_clk_lookup)); } /***************************************************************************/ From 007f84ede6e3ea893b1a68724e8796c45fa98d85 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 31 May 2021 11:43:22 +0200 Subject: [PATCH 054/161] m68k: coldfire: remove private clk_get/clk_put Only three SoCs remain that use the custom clk_get/clk_put. Move these over to clkdev_lookup tables as well. As before, treat the "sys.0" and "pll.0" clocks as system-wide clocks, and all the other ones as device specific. The "name" field in 'struct clock' is now unused, so rename that as well as a cleanup and to reduce the object code size. The DEFINE_CLK macro could be changed the same way, but it is less churn to just leave those in place, that can be done as a follow-up later if someone is interested. Acked-by: Greg Ungerer Tested-by: Greg Ungerer Signed-off-by: Arnd Bergmann --- arch/m68k/Kconfig.cpu | 5 +- arch/m68k/coldfire/clk.c | 21 ------ arch/m68k/coldfire/m520x.c | 51 ++++++------- arch/m68k/coldfire/m53xx.c | 78 ++++++++++---------- arch/m68k/coldfire/m5441x.c | 126 ++++++++++++++++----------------- arch/m68k/include/asm/mcfclk.h | 5 -- 6 files changed, 128 insertions(+), 158 deletions(-) diff --git a/arch/m68k/Kconfig.cpu b/arch/m68k/Kconfig.cpu index b3483929b313..e54167a64cbf 100644 --- a/arch/m68k/Kconfig.cpu +++ b/arch/m68k/Kconfig.cpu @@ -29,6 +29,7 @@ config COLDFIRE select CPU_HAS_NO_MULDIV64 select GENERIC_CSUM select GPIOLIB + select CLKDEV_LOOKUP select HAVE_LEGACY_CLK endchoice @@ -328,10 +329,6 @@ config COLDFIRE_SLTIMERS bool select LEGACY_TIMER_TICK -config COLDFIRE_CLKDEV_LOOKUP - def_bool !(M5206 || M5206e || M53xx || M5441x) - select CLKDEV_LOOKUP - endif # COLDFIRE diff --git a/arch/m68k/coldfire/clk.c b/arch/m68k/coldfire/clk.c index ffe36627bab8..2ed841e94111 100644 --- a/arch/m68k/coldfire/clk.c +++ b/arch/m68k/coldfire/clk.c @@ -71,27 +71,6 @@ struct clk_ops clk_ops1 = { .disable = __clk_disable1, }; #endif /* MCFPM_PPMCR1 */ - -struct clk *clk_get(struct device *dev, const char *id) -{ - const char *clk_name = dev ? dev_name(dev) : id ? id : NULL; - struct clk *clk; - unsigned i; - - for (i = 0; (clk = mcf_clks[i]) != NULL; ++i) - if (!strcmp(clk->name, clk_name)) - return clk; - pr_warn("clk_get: didn't find clock %s\n", clk_name); - return ERR_PTR(-ENOENT); -} -EXPORT_SYMBOL(clk_get); - -void clk_put(struct clk *clk) -{ - if (clk->enabled != 0) - pr_warn("clk_put %s still enabled\n", clk->name); -} -EXPORT_SYMBOL(clk_put); #endif /* MCFPM_PPMCR0 */ int clk_enable(struct clk *clk) diff --git a/arch/m68k/coldfire/m520x.c b/arch/m68k/coldfire/m520x.c index b5b2a267dada..d2f96b40aee1 100644 --- a/arch/m68k/coldfire/m520x.c +++ b/arch/m68k/coldfire/m520x.c @@ -12,6 +12,7 @@ /***************************************************************************/ +#include #include #include #include @@ -48,31 +49,29 @@ DEFINE_CLK(0, "sys.0", 40, MCF_BUSCLK); DEFINE_CLK(0, "gpio.0", 41, MCF_BUSCLK); DEFINE_CLK(0, "sdram.0", 42, MCF_CLK); -struct clk *mcf_clks[] = { - &__clk_0_2, /* flexbus */ - &__clk_0_12, /* fec.0 */ - &__clk_0_17, /* edma */ - &__clk_0_18, /* intc.0 */ - &__clk_0_21, /* iack.0 */ - &__clk_0_22, /* imx1-i2c.0 */ - &__clk_0_23, /* mcfqspi.0 */ - &__clk_0_24, /* mcfuart.0 */ - &__clk_0_25, /* mcfuart.1 */ - &__clk_0_26, /* mcfuart.2 */ - &__clk_0_28, /* mcftmr.0 */ - &__clk_0_29, /* mcftmr.1 */ - &__clk_0_30, /* mcftmr.2 */ - &__clk_0_31, /* mcftmr.3 */ - - &__clk_0_32, /* mcfpit.0 */ - &__clk_0_33, /* mcfpit.1 */ - &__clk_0_34, /* mcfeport.0 */ - &__clk_0_35, /* mcfwdt.0 */ - &__clk_0_36, /* pll.0 */ - &__clk_0_40, /* sys.0 */ - &__clk_0_41, /* gpio.0 */ - &__clk_0_42, /* sdram.0 */ - NULL, +static struct clk_lookup m520x_clk_lookup[] = { + CLKDEV_INIT(NULL, "flexbus", &__clk_0_2), + CLKDEV_INIT("fec.0", NULL, &__clk_0_12), + CLKDEV_INIT("edma", NULL, &__clk_0_17), + CLKDEV_INIT("intc.0", NULL, &__clk_0_18), + CLKDEV_INIT("iack.0", NULL, &__clk_0_21), + CLKDEV_INIT("imx1-i2c.0", NULL, &__clk_0_22), + CLKDEV_INIT("mcfqspi.0", NULL, &__clk_0_23), + CLKDEV_INIT("mcfuart.0", NULL, &__clk_0_24), + CLKDEV_INIT("mcfuart.1", NULL, &__clk_0_25), + CLKDEV_INIT("mcfuart.2", NULL, &__clk_0_26), + CLKDEV_INIT("mcftmr.0", NULL, &__clk_0_28), + CLKDEV_INIT("mcftmr.1", NULL, &__clk_0_29), + CLKDEV_INIT("mcftmr.2", NULL, &__clk_0_30), + CLKDEV_INIT("mcftmr.3", NULL, &__clk_0_31), + CLKDEV_INIT("mcfpit.0", NULL, &__clk_0_32), + CLKDEV_INIT("mcfpit.1", NULL, &__clk_0_33), + CLKDEV_INIT("mcfeport.0", NULL, &__clk_0_34), + CLKDEV_INIT("mcfwdt.0", NULL, &__clk_0_35), + CLKDEV_INIT(NULL, "pll.0", &__clk_0_36), + CLKDEV_INIT(NULL, "sys.0", &__clk_0_40), + CLKDEV_INIT("gpio.0", NULL, &__clk_0_41), + CLKDEV_INIT("sdram.0", NULL, &__clk_0_42), }; static struct clk * const enable_clks[] __initconst = { @@ -115,6 +114,8 @@ static void __init m520x_clk_init(void) /* make sure these clocks are disabled */ for (i = 0; i < ARRAY_SIZE(disable_clks); ++i) __clk_init_disabled(disable_clks[i]); + + clkdev_add_table(m520x_clk_lookup, ARRAY_SIZE(m520x_clk_lookup)); } /***************************************************************************/ diff --git a/arch/m68k/coldfire/m53xx.c b/arch/m68k/coldfire/m53xx.c index 075722c0c4f0..bd033e1975bf 100644 --- a/arch/m68k/coldfire/m53xx.c +++ b/arch/m68k/coldfire/m53xx.c @@ -13,6 +13,7 @@ /***************************************************************************/ +#include #include #include #include @@ -65,45 +66,42 @@ DEFINE_CLK(1, "mdha.0", 32, MCF_CLK); DEFINE_CLK(1, "skha.0", 33, MCF_CLK); DEFINE_CLK(1, "rng.0", 34, MCF_CLK); -struct clk *mcf_clks[] = { - &__clk_0_2, /* flexbus */ - &__clk_0_8, /* mcfcan.0 */ - &__clk_0_12, /* fec.0 */ - &__clk_0_17, /* edma */ - &__clk_0_18, /* intc.0 */ - &__clk_0_19, /* intc.1 */ - &__clk_0_21, /* iack.0 */ - &__clk_0_22, /* imx1-i2c.0 */ - &__clk_0_23, /* mcfqspi.0 */ - &__clk_0_24, /* mcfuart.0 */ - &__clk_0_25, /* mcfuart.1 */ - &__clk_0_26, /* mcfuart.2 */ - &__clk_0_28, /* mcftmr.0 */ - &__clk_0_29, /* mcftmr.1 */ - &__clk_0_30, /* mcftmr.2 */ - &__clk_0_31, /* mcftmr.3 */ - - &__clk_0_32, /* mcfpit.0 */ - &__clk_0_33, /* mcfpit.1 */ - &__clk_0_34, /* mcfpit.2 */ - &__clk_0_35, /* mcfpit.3 */ - &__clk_0_36, /* mcfpwm.0 */ - &__clk_0_37, /* mcfeport.0 */ - &__clk_0_38, /* mcfwdt.0 */ - &__clk_0_40, /* sys.0 */ - &__clk_0_41, /* gpio.0 */ - &__clk_0_42, /* mcfrtc.0 */ - &__clk_0_43, /* mcflcd.0 */ - &__clk_0_44, /* mcfusb-otg.0 */ - &__clk_0_45, /* mcfusb-host.0 */ - &__clk_0_46, /* sdram.0 */ - &__clk_0_47, /* ssi.0 */ - &__clk_0_48, /* pll.0 */ - - &__clk_1_32, /* mdha.0 */ - &__clk_1_33, /* skha.0 */ - &__clk_1_34, /* rng.0 */ - NULL, +static struct clk_lookup m53xx_clk_lookup[] = { + CLKDEV_INIT("flexbus", NULL, &__clk_0_2), + CLKDEV_INIT("mcfcan.0", NULL, &__clk_0_8), + CLKDEV_INIT("fec.0", NULL, &__clk_0_12), + CLKDEV_INIT("edma", NULL, &__clk_0_17), + CLKDEV_INIT("intc.0", NULL, &__clk_0_18), + CLKDEV_INIT("intc.1", NULL, &__clk_0_19), + CLKDEV_INIT("iack.0", NULL, &__clk_0_21), + CLKDEV_INIT("imx1-i2c.0", NULL, &__clk_0_22), + CLKDEV_INIT("mcfqspi.0", NULL, &__clk_0_23), + CLKDEV_INIT("mcfuart.0", NULL, &__clk_0_24), + CLKDEV_INIT("mcfuart.1", NULL, &__clk_0_25), + CLKDEV_INIT("mcfuart.2", NULL, &__clk_0_26), + CLKDEV_INIT("mcftmr.0", NULL, &__clk_0_28), + CLKDEV_INIT("mcftmr.1", NULL, &__clk_0_29), + CLKDEV_INIT("mcftmr.2", NULL, &__clk_0_30), + CLKDEV_INIT("mcftmr.3", NULL, &__clk_0_31), + CLKDEV_INIT("mcfpit.0", NULL, &__clk_0_32), + CLKDEV_INIT("mcfpit.1", NULL, &__clk_0_33), + CLKDEV_INIT("mcfpit.2", NULL, &__clk_0_34), + CLKDEV_INIT("mcfpit.3", NULL, &__clk_0_35), + CLKDEV_INIT("mcfpwm.0", NULL, &__clk_0_36), + CLKDEV_INIT("mcfeport.0", NULL, &__clk_0_37), + CLKDEV_INIT("mcfwdt.0", NULL, &__clk_0_38), + CLKDEV_INIT(NULL, "sys.0", &__clk_0_40), + CLKDEV_INIT("gpio.0", NULL, &__clk_0_41), + CLKDEV_INIT("mcfrtc.0", NULL, &__clk_0_42), + CLKDEV_INIT("mcflcd.0", NULL, &__clk_0_43), + CLKDEV_INIT("mcfusb-otg.0", NULL, &__clk_0_44), + CLKDEV_INIT("mcfusb-host.0", NULL, &__clk_0_45), + CLKDEV_INIT("sdram.0", NULL, &__clk_0_46), + CLKDEV_INIT("ssi.0", NULL, &__clk_0_47), + CLKDEV_INIT(NULL, "pll.0", &__clk_0_48), + CLKDEV_INIT("mdha.0", NULL, &__clk_1_32), + CLKDEV_INIT("skha.0", NULL, &__clk_1_33), + CLKDEV_INIT("rng.0", NULL, &__clk_1_34), }; static struct clk * const enable_clks[] __initconst = { @@ -158,6 +156,8 @@ static void __init m53xx_clk_init(void) /* make sure these clocks are disabled */ for (i = 0; i < ARRAY_SIZE(disable_clks); ++i) __clk_init_disabled(disable_clks[i]); + + clkdev_add_table(m53xx_clk_lookup, ARRAY_SIZE(m53xx_clk_lookup)); } /***************************************************************************/ diff --git a/arch/m68k/coldfire/m5441x.c b/arch/m68k/coldfire/m5441x.c index 1e5259a652d1..ce14693d18b6 100644 --- a/arch/m68k/coldfire/m5441x.c +++ b/arch/m68k/coldfire/m5441x.c @@ -5,6 +5,7 @@ * (C) Copyright Steven King */ +#include #include #include #include @@ -78,72 +79,67 @@ DEFINE_CLK(2, "ipg.0", 0, MCF_CLK); DEFINE_CLK(2, "ahb.0", 1, MCF_CLK); DEFINE_CLK(2, "per.0", 2, MCF_CLK); -struct clk *mcf_clks[] = { - &__clk_0_2, - &__clk_0_8, - &__clk_0_9, - &__clk_0_14, - &__clk_0_15, - &__clk_0_17, - &__clk_0_18, - &__clk_0_19, - &__clk_0_20, - &__clk_0_22, - &__clk_0_23, - &__clk_0_24, - &__clk_0_25, - &__clk_0_26, - &__clk_0_27, - &__clk_0_28, - &__clk_0_29, - &__clk_0_30, - &__clk_0_31, - &__clk_0_32, - &__clk_0_33, - &__clk_0_34, - &__clk_0_35, - &__clk_0_37, - &__clk_0_38, - &__clk_0_39, - &__clk_0_42, - &__clk_0_43, - &__clk_0_44, - &__clk_0_45, - &__clk_0_46, - &__clk_0_47, - &__clk_0_48, - &__clk_0_49, - &__clk_0_50, - &__clk_0_51, - &__clk_0_53, - &__clk_0_54, - &__clk_0_55, - &__clk_0_56, - &__clk_0_63, - - &__clk_1_2, - &__clk_1_4, - &__clk_1_5, - &__clk_1_6, - &__clk_1_7, - &__clk_1_24, - &__clk_1_25, - &__clk_1_26, - &__clk_1_27, - &__clk_1_28, - &__clk_1_29, - &__clk_1_34, - &__clk_1_36, - &__clk_1_37, - - &__clk_2_0, - &__clk_2_1, - &__clk_2_2, - - NULL, +static struct clk_lookup m5411x_clk_lookup[] = { + CLKDEV_INIT("flexbus", NULL, &__clk_0_2), + CLKDEV_INIT("mcfcan.0", NULL, &__clk_0_8), + CLKDEV_INIT("mcfcan.1", NULL, &__clk_0_9), + CLKDEV_INIT("imx1-i2c.1", NULL, &__clk_0_14), + CLKDEV_INIT("mcfdspi.1", NULL, &__clk_0_15), + CLKDEV_INIT("edma", NULL, &__clk_0_17), + CLKDEV_INIT("intc.0", NULL, &__clk_0_18), + CLKDEV_INIT("intc.1", NULL, &__clk_0_19), + CLKDEV_INIT("intc.2", NULL, &__clk_0_20), + CLKDEV_INIT("imx1-i2c.0", NULL, &__clk_0_22), + CLKDEV_INIT("fsl-dspi.0", NULL, &__clk_0_23), + CLKDEV_INIT("mcfuart.0", NULL, &__clk_0_24), + CLKDEV_INIT("mcfuart.1", NULL, &__clk_0_25), + CLKDEV_INIT("mcfuart.2", NULL, &__clk_0_26), + CLKDEV_INIT("mcfuart.3", NULL, &__clk_0_27), + CLKDEV_INIT("mcftmr.0", NULL, &__clk_0_28), + CLKDEV_INIT("mcftmr.1", NULL, &__clk_0_29), + CLKDEV_INIT("mcftmr.2", NULL, &__clk_0_30), + CLKDEV_INIT("mcftmr.3", NULL, &__clk_0_31), + CLKDEV_INIT("mcfpit.0", NULL, &__clk_0_32), + CLKDEV_INIT("mcfpit.1", NULL, &__clk_0_33), + CLKDEV_INIT("mcfpit.2", NULL, &__clk_0_34), + CLKDEV_INIT("mcfpit.3", NULL, &__clk_0_35), + CLKDEV_INIT("mcfeport.0", NULL, &__clk_0_37), + CLKDEV_INIT("mcfadc.0", NULL, &__clk_0_38), + CLKDEV_INIT("mcfdac.0", NULL, &__clk_0_39), + CLKDEV_INIT("mcfrtc.0", NULL, &__clk_0_42), + CLKDEV_INIT("mcfsim.0", NULL, &__clk_0_43), + CLKDEV_INIT("mcfusb-otg.0", NULL, &__clk_0_44), + CLKDEV_INIT("mcfusb-host.0", NULL, &__clk_0_45), + CLKDEV_INIT("mcfddr-sram.0", NULL, &__clk_0_46), + CLKDEV_INIT("mcfssi.0", NULL, &__clk_0_47), + CLKDEV_INIT(NULL, "pll.0", &__clk_0_48), + CLKDEV_INIT("mcfrng.0", NULL, &__clk_0_49), + CLKDEV_INIT("mcfssi.1", NULL, &__clk_0_50), + CLKDEV_INIT("sdhci-esdhc-mcf.0", NULL, &__clk_0_51), + CLKDEV_INIT("enet-fec.0", NULL, &__clk_0_53), + CLKDEV_INIT("enet-fec.1", NULL, &__clk_0_54), + CLKDEV_INIT("switch.0", NULL, &__clk_0_55), + CLKDEV_INIT("switch.1", NULL, &__clk_0_56), + CLKDEV_INIT("nand.0", NULL, &__clk_0_63), + CLKDEV_INIT("mcfow.0", NULL, &__clk_1_2), + CLKDEV_INIT("imx1-i2c.2", NULL, &__clk_1_4), + CLKDEV_INIT("imx1-i2c.3", NULL, &__clk_1_5), + CLKDEV_INIT("imx1-i2c.4", NULL, &__clk_1_6), + CLKDEV_INIT("imx1-i2c.5", NULL, &__clk_1_7), + CLKDEV_INIT("mcfuart.4", NULL, &__clk_1_24), + CLKDEV_INIT("mcfuart.5", NULL, &__clk_1_25), + CLKDEV_INIT("mcfuart.6", NULL, &__clk_1_26), + CLKDEV_INIT("mcfuart.7", NULL, &__clk_1_27), + CLKDEV_INIT("mcfuart.8", NULL, &__clk_1_28), + CLKDEV_INIT("mcfuart.9", NULL, &__clk_1_29), + CLKDEV_INIT("mcfpwm.0", NULL, &__clk_1_34), + CLKDEV_INIT(NULL, "sys.0", &__clk_1_36), + CLKDEV_INIT("gpio.0", NULL, &__clk_1_37), + CLKDEV_INIT("ipg.0", NULL, &__clk_2_0), + CLKDEV_INIT("ahb.0", NULL, &__clk_2_1), + CLKDEV_INIT("per.0", NULL, &__clk_2_2), }; - static struct clk * const enable_clks[] __initconst = { /* make sure these clocks are enabled */ &__clk_0_15, /* dspi.1 */ @@ -228,6 +224,8 @@ static void __init m5441x_clk_init(void) /* make sure these clocks are disabled */ for (i = 0; i < ARRAY_SIZE(disable_clks); ++i) __clk_init_disabled(disable_clks[i]); + + clkdev_add_table(m5411x_clk_lookup, ARRAY_SIZE(m5411x_clk_lookup)); } static void __init m5441x_uarts_init(void) diff --git a/arch/m68k/include/asm/mcfclk.h b/arch/m68k/include/asm/mcfclk.h index 722627e06d66..4e9a6b827a14 100644 --- a/arch/m68k/include/asm/mcfclk.h +++ b/arch/m68k/include/asm/mcfclk.h @@ -15,15 +15,12 @@ struct clk_ops { }; struct clk { - const char *name; struct clk_ops *clk_ops; unsigned long rate; unsigned long enabled; u8 slot; }; -extern struct clk *mcf_clks[]; - #ifdef MCFPM_PPMCR0 extern struct clk_ops clk_ops0; #ifdef MCFPM_PPMCR1 @@ -34,7 +31,6 @@ extern struct clk_ops clk_ops2; #define DEFINE_CLK(clk_bank, clk_name, clk_slot, clk_rate) \ static struct clk __clk_##clk_bank##_##clk_slot = { \ - .name = clk_name, \ .clk_ops = &clk_ops##clk_bank, \ .rate = clk_rate, \ .slot = clk_slot, \ @@ -45,7 +41,6 @@ void __clk_init_disabled(struct clk *); #else #define DEFINE_CLK(clk_ref, clk_name, clk_rate) \ static struct clk clk_##clk_ref = { \ - .name = clk_name, \ .rate = clk_rate, \ } #endif /* MCFPM_PPMCR0 */ From 2f4574dd6dd19eb3e8ab0415a3ae960d04be3a65 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 31 May 2021 11:48:49 +0200 Subject: [PATCH 055/161] clkdev: remove CONFIG_CLKDEV_LOOKUP This option is now synonymous with CONFIG_HAVE_CLK, so use the latter globally. Any out-of-tree platform ports that still use a private clk_get()/clk_put() implementation should move to CONFIG_COMMON_CLK. Signed-off-by: Arnd Bergmann --- arch/arm/Kconfig | 2 -- arch/m68k/Kconfig.cpu | 1 - arch/mips/Kconfig | 3 --- arch/mips/pic32/Kconfig | 1 - arch/sh/Kconfig | 1 - drivers/clk/Kconfig | 6 +----- drivers/clk/Makefile | 3 +-- drivers/clocksource/Kconfig | 6 +++--- drivers/mmc/host/Kconfig | 4 ++-- drivers/staging/board/Kconfig | 2 +- sound/soc/dwc/Kconfig | 2 +- sound/soc/rockchip/Kconfig | 14 +++++++------- 12 files changed, 16 insertions(+), 29 deletions(-) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 24804f11302d..809317b5a6c6 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -353,7 +353,6 @@ config ARCH_EP93XX select ARM_VIC select GENERIC_IRQ_MULTI_HANDLER select AUTO_ZRELADDR - select CLKDEV_LOOKUP select CLKSRC_MMIO select CPU_ARM920T select GPIOLIB @@ -504,7 +503,6 @@ config ARCH_OMAP1 bool "TI OMAP1" depends on MMU select ARCH_OMAP - select CLKDEV_LOOKUP select CLKSRC_MMIO select GENERIC_IRQ_CHIP select GENERIC_IRQ_MULTI_HANDLER diff --git a/arch/m68k/Kconfig.cpu b/arch/m68k/Kconfig.cpu index e54167a64cbf..f4d23977d2a5 100644 --- a/arch/m68k/Kconfig.cpu +++ b/arch/m68k/Kconfig.cpu @@ -29,7 +29,6 @@ config COLDFIRE select CPU_HAS_NO_MULDIV64 select GENERIC_CSUM select GPIOLIB - select CLKDEV_LOOKUP select HAVE_LEGACY_CLK endchoice diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 8fe6b30de7dd..96ab1a2a9357 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -332,7 +332,6 @@ config BCM63XX select SWAP_IO_SPACE select GPIOLIB select MIPS_L1_CACHE_SHIFT_4 - select CLKDEV_LOOKUP select HAVE_LEGACY_CLK help Support for BCM63XX based boards @@ -446,7 +445,6 @@ config LANTIQ select GPIOLIB select SWAP_IO_SPACE select BOOT_RAW - select CLKDEV_LOOKUP select HAVE_LEGACY_CLK select USE_OF select PINCTRL @@ -643,7 +641,6 @@ config RALINK select SYS_SUPPORTS_MIPS16 select SYS_SUPPORTS_ZBOOT select SYS_HAS_EARLY_PRINTK - select CLKDEV_LOOKUP select ARCH_HAS_RESET_CONTROLLER select RESET_CONTROLLER diff --git a/arch/mips/pic32/Kconfig b/arch/mips/pic32/Kconfig index 7acbb50c1dcd..bb6ab1f3e80d 100644 --- a/arch/mips/pic32/Kconfig +++ b/arch/mips/pic32/Kconfig @@ -17,7 +17,6 @@ config PIC32MZDA select SYS_SUPPORTS_LITTLE_ENDIAN select GPIOLIB select COMMON_CLK - select CLKDEV_LOOKUP select LIBFDT select USE_OF select PINCTRL diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig index 68129537e350..45a0549421cd 100644 --- a/arch/sh/Kconfig +++ b/arch/sh/Kconfig @@ -14,7 +14,6 @@ config SUPERH select ARCH_HIBERNATION_POSSIBLE if MMU select ARCH_MIGHT_HAVE_PC_PARPORT select ARCH_WANT_IPC_PARSE_VERSION - select CLKDEV_LOOKUP select CPU_NO_EFFICIENT_FFS select DMA_DECLARE_COHERENT select GENERIC_ATOMIC64 diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index e80918be8e9c..ed1364ac376b 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig @@ -6,10 +6,6 @@ config HAVE_CLK The calls support software clock gating and thus are a key power management tool on many systems. -config CLKDEV_LOOKUP - bool - select HAVE_CLK - config HAVE_CLK_PREPARE bool @@ -26,7 +22,7 @@ menuconfig COMMON_CLK bool "Common Clock Framework" depends on !HAVE_LEGACY_CLK select HAVE_CLK_PREPARE - select CLKDEV_LOOKUP + select HAVE_CLK select SRCU select RATIONAL help diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index 5f06879d7fe9..5341c37b62dc 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -1,7 +1,6 @@ # SPDX-License-Identifier: GPL-2.0 # common clock types -obj-$(CONFIG_HAVE_CLK) += clk-devres.o clk-bulk.o -obj-$(CONFIG_CLKDEV_LOOKUP) += clkdev.o +obj-$(CONFIG_HAVE_CLK) += clk-devres.o clk-bulk.o clkdev.o obj-$(CONFIG_COMMON_CLK) += clk.o obj-$(CONFIG_COMMON_CLK) += clk-divider.o obj-$(CONFIG_COMMON_CLK) += clk-fixed-factor.o diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index 39aa21d01e05..938087347927 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig @@ -360,7 +360,7 @@ config ARM_GLOBAL_TIMER config ARM_TIMER_SP804 bool "Support for Dual Timer SP804 module" if COMPILE_TEST - depends on GENERIC_SCHED_CLOCK && CLKDEV_LOOKUP + depends on GENERIC_SCHED_CLOCK && HAVE_CLK select CLKSRC_MMIO select TIMER_OF if OF @@ -570,12 +570,12 @@ config H8300_TPU config CLKSRC_IMX_GPT bool "Clocksource using i.MX GPT" if COMPILE_TEST - depends on (ARM || ARM64) && CLKDEV_LOOKUP + depends on (ARM || ARM64) && HAVE_CLK select CLKSRC_MMIO config CLKSRC_IMX_TPM bool "Clocksource using i.MX TPM" if COMPILE_TEST - depends on (ARM || ARM64) && CLKDEV_LOOKUP + depends on (ARM || ARM64) && HAVE_CLK select CLKSRC_MMIO select TIMER_OF help diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig index a4d4c757eea0..4f1468a79126 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig @@ -329,7 +329,7 @@ config MMC_SDHCI_S3C config MMC_SDHCI_PXAV3 tristate "Marvell MMP2 SD Host Controller support (PXAV3)" - depends on CLKDEV_LOOKUP + depends on HAVE_CLK depends on MMC_SDHCI_PLTFM depends on ARCH_BERLIN || ARCH_MMP || ARCH_MVEBU || COMPILE_TEST default CPU_MMP2 @@ -342,7 +342,7 @@ config MMC_SDHCI_PXAV3 config MMC_SDHCI_PXAV2 tristate "Marvell PXA9XX SD Host Controller support (PXAV2)" - depends on CLKDEV_LOOKUP + depends on HAVE_CLK depends on MMC_SDHCI_PLTFM depends on ARCH_MMP || COMPILE_TEST default CPU_PXA910 diff --git a/drivers/staging/board/Kconfig b/drivers/staging/board/Kconfig index 64c77970eee8..b49216768ef6 100644 --- a/drivers/staging/board/Kconfig +++ b/drivers/staging/board/Kconfig @@ -1,7 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 config STAGING_BOARD bool "Staging Board Support" - depends on OF_ADDRESS && OF_IRQ && CLKDEV_LOOKUP + depends on OF_ADDRESS && OF_IRQ && HAVE_CLK help Staging board base is to support continuous upstream in-tree development and integration of platform devices. diff --git a/sound/soc/dwc/Kconfig b/sound/soc/dwc/Kconfig index 0cd1a15f40aa..71a58f7ac13a 100644 --- a/sound/soc/dwc/Kconfig +++ b/sound/soc/dwc/Kconfig @@ -1,7 +1,7 @@ # SPDX-License-Identifier: GPL-2.0-only config SND_DESIGNWARE_I2S tristate "Synopsys I2S Device Driver" - depends on CLKDEV_LOOKUP + depends on HAVE_CLK select SND_SOC_GENERIC_DMAENGINE_PCM help Say Y or M if you want to add support for I2S driver for diff --git a/sound/soc/rockchip/Kconfig b/sound/soc/rockchip/Kconfig index d610b553ea3b..053097b73e28 100644 --- a/sound/soc/rockchip/Kconfig +++ b/sound/soc/rockchip/Kconfig @@ -9,7 +9,7 @@ config SND_SOC_ROCKCHIP config SND_SOC_ROCKCHIP_I2S tristate "Rockchip I2S Device Driver" - depends on CLKDEV_LOOKUP && SND_SOC_ROCKCHIP + depends on HAVE_CLK && SND_SOC_ROCKCHIP select SND_SOC_GENERIC_DMAENGINE_PCM help Say Y or M if you want to add support for I2S driver for @@ -18,7 +18,7 @@ config SND_SOC_ROCKCHIP_I2S config SND_SOC_ROCKCHIP_PDM tristate "Rockchip PDM Controller Driver" - depends on CLKDEV_LOOKUP && SND_SOC_ROCKCHIP + depends on HAVE_CLK && SND_SOC_ROCKCHIP select SND_SOC_GENERIC_DMAENGINE_PCM select RATIONAL help @@ -28,7 +28,7 @@ config SND_SOC_ROCKCHIP_PDM config SND_SOC_ROCKCHIP_SPDIF tristate "Rockchip SPDIF Device Driver" - depends on CLKDEV_LOOKUP && SND_SOC_ROCKCHIP + depends on HAVE_CLK && SND_SOC_ROCKCHIP select SND_SOC_GENERIC_DMAENGINE_PCM help Say Y or M if you want to add support for SPDIF driver for @@ -36,7 +36,7 @@ config SND_SOC_ROCKCHIP_SPDIF config SND_SOC_ROCKCHIP_MAX98090 tristate "ASoC support for Rockchip boards using a MAX98090 codec" - depends on SND_SOC_ROCKCHIP && I2C && GPIOLIB && CLKDEV_LOOKUP + depends on SND_SOC_ROCKCHIP && I2C && GPIOLIB && HAVE_CLK select SND_SOC_ROCKCHIP_I2S select SND_SOC_MAX98090 select SND_SOC_TS3A227E @@ -47,7 +47,7 @@ config SND_SOC_ROCKCHIP_MAX98090 config SND_SOC_ROCKCHIP_RT5645 tristate "ASoC support for Rockchip boards using a RT5645/RT5650 codec" - depends on SND_SOC_ROCKCHIP && I2C && GPIOLIB && CLKDEV_LOOKUP + depends on SND_SOC_ROCKCHIP && I2C && GPIOLIB && HAVE_CLK select SND_SOC_ROCKCHIP_I2S select SND_SOC_RT5645 help @@ -56,7 +56,7 @@ config SND_SOC_ROCKCHIP_RT5645 config SND_SOC_RK3288_HDMI_ANALOG tristate "ASoC support multiple codecs for Rockchip RK3288 boards" - depends on SND_SOC_ROCKCHIP && I2C && GPIOLIB && CLKDEV_LOOKUP + depends on SND_SOC_ROCKCHIP && I2C && GPIOLIB && HAVE_CLK select SND_SOC_ROCKCHIP_I2S select SND_SOC_HDMI_CODEC select SND_SOC_ES8328_I2C @@ -68,7 +68,7 @@ config SND_SOC_RK3288_HDMI_ANALOG config SND_SOC_RK3399_GRU_SOUND tristate "ASoC support multiple codecs for Rockchip RK3399 GRU boards" - depends on SND_SOC_ROCKCHIP && I2C && GPIOLIB && CLKDEV_LOOKUP && SPI + depends on SND_SOC_ROCKCHIP && I2C && GPIOLIB && HAVE_CLK && SPI select SND_SOC_ROCKCHIP_I2S select SND_SOC_MAX98357A select SND_SOC_RT5514 From 5617c9125bb66a923f3560d5739eb7f3a21c00b5 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Sat, 29 May 2021 16:52:32 +0200 Subject: [PATCH 056/161] clkdev: remove unused clkdev_alloc() interfaces The last user of clkdev_alloc() and clkdev_hw_alloc() was removed last year, so everything now calls clkdev_create() and clkdev_hw_create() instead. Removing the unused functions lets the compiler optimize the remaining ones slightly better. Fixes: e5006671acc7 ("clk: versatile: Drop the legacy IM-PD1 clock code") Reviewed-by: Stephen Boyd Signed-off-by: Arnd Bergmann --- drivers/clk/clkdev.c | 28 ---------------------------- include/linux/clkdev.h | 5 ----- 2 files changed, 33 deletions(-) diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c index 0f2e3fcf0f19..67f601a41023 100644 --- a/drivers/clk/clkdev.c +++ b/drivers/clk/clkdev.c @@ -190,34 +190,6 @@ vclkdev_create(struct clk_hw *hw, const char *con_id, const char *dev_fmt, return cl; } -struct clk_lookup * __ref -clkdev_alloc(struct clk *clk, const char *con_id, const char *dev_fmt, ...) -{ - struct clk_lookup *cl; - va_list ap; - - va_start(ap, dev_fmt); - cl = vclkdev_alloc(__clk_get_hw(clk), con_id, dev_fmt, ap); - va_end(ap); - - return cl; -} -EXPORT_SYMBOL(clkdev_alloc); - -struct clk_lookup * -clkdev_hw_alloc(struct clk_hw *hw, const char *con_id, const char *dev_fmt, ...) -{ - struct clk_lookup *cl; - va_list ap; - - va_start(ap, dev_fmt); - cl = vclkdev_alloc(hw, con_id, dev_fmt, ap); - va_end(ap); - - return cl; -} -EXPORT_SYMBOL(clkdev_hw_alloc); - /** * clkdev_create - allocate and add a clkdev lookup structure * @clk: struct clk to associate with all clk_lookups diff --git a/include/linux/clkdev.h b/include/linux/clkdev.h index fd06b2780a22..8a8423eb8e9a 100644 --- a/include/linux/clkdev.h +++ b/include/linux/clkdev.h @@ -30,11 +30,6 @@ struct clk_lookup { .clk = c, \ } -struct clk_lookup *clkdev_alloc(struct clk *clk, const char *con_id, - const char *dev_fmt, ...) __printf(3, 4); -struct clk_lookup *clkdev_hw_alloc(struct clk_hw *hw, const char *con_id, - const char *dev_fmt, ...) __printf(3, 4); - void clkdev_add(struct clk_lookup *cl); void clkdev_drop(struct clk_lookup *cl); From 2d32cd3315f37a20cd4753a2bad7e28be183e748 Mon Sep 17 00:00:00 2001 From: Konrad Dybcio Date: Sun, 6 Jun 2021 21:26:57 +0200 Subject: [PATCH 057/161] clk: qcom: smd-rpm: Fix wrongly assigned RPM_SMD_PNOC_CLK During my big cleanup I managed to assign an AO clock to its non-AO binding. Fix this. Reported-by: Bartosz Dudziak Signed-off-by: Konrad Dybcio Link: https://lore.kernel.org/r/20210606192657.51037-1-konrad.dybcio@somainline.org Fixes: a0384ecfe2aa ("clk: qcom: smd-rpm: De-duplicate identical entries") Signed-off-by: Stephen Boyd --- drivers/clk/qcom/clk-smd-rpm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/qcom/clk-smd-rpm.c b/drivers/clk/qcom/clk-smd-rpm.c index 295fc08eddb9..daf09dd61055 100644 --- a/drivers/clk/qcom/clk-smd-rpm.c +++ b/drivers/clk/qcom/clk-smd-rpm.c @@ -518,7 +518,7 @@ DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8974, cxo_a1_pin, cxo_a1_a_pin, 5); DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8974, cxo_a2_pin, cxo_a2_a_pin, 6); static struct clk_smd_rpm *msm8974_clks[] = { - [RPM_SMD_PNOC_CLK] = &msm8916_pcnoc_a_clk, + [RPM_SMD_PNOC_CLK] = &msm8916_pcnoc_clk, [RPM_SMD_PNOC_A_CLK] = &msm8916_pcnoc_a_clk, [RPM_SMD_SNOC_CLK] = &msm8916_snoc_clk, [RPM_SMD_SNOC_A_CLK] = &msm8916_snoc_a_clk, From c255f15105bad60741a71d03cb9e84de79a8380c Mon Sep 17 00:00:00 2001 From: Dario Binacchi Date: Sun, 6 Jun 2021 22:22:49 +0200 Subject: [PATCH 058/161] clk: ti: fix typo in routine description Replace _omap3_noncore_dpll_program with omap3_noncore_dpll_program. Signed-off-by: Dario Binacchi Reviewed-by: Stephen Boyd Link: https://lore.kernel.org/r/20210606202253.31649-2-dariobin@libero.it Signed-off-by: Stephen Boyd --- drivers/clk/ti/dpll3xxx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/ti/dpll3xxx.c b/drivers/clk/ti/dpll3xxx.c index 6097b099a5df..94d5b5fe9a2b 100644 --- a/drivers/clk/ti/dpll3xxx.c +++ b/drivers/clk/ti/dpll3xxx.c @@ -292,7 +292,7 @@ static void _lookup_sddiv(struct clk_hw_omap *clk, u8 *sd_div, u16 m, u8 n) } /** - * _omap3_noncore_dpll_program - set non-core DPLL M,N values directly + * omap3_noncore_dpll_program - set non-core DPLL M,N values directly * @clk: struct clk * of DPLL to set * @freqsel: FREQSEL value to set * From 4a8bc2644ef0cbf8ebe46da3887eafd309b0f187 Mon Sep 17 00:00:00 2001 From: Dario Binacchi Date: Sun, 6 Jun 2021 22:22:50 +0200 Subject: [PATCH 059/161] dt-bindings: ti: dpll: add spread spectrum support DT bindings for enabling and adjusting spread spectrum clocking have been added. Signed-off-by: Dario Binacchi Reviewed-by: Rob Herring Link: https://lore.kernel.org/r/20210606202253.31649-3-dariobin@libero.it Signed-off-by: Stephen Boyd --- .../devicetree/bindings/clock/ti/dpll.txt | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/Documentation/devicetree/bindings/clock/ti/dpll.txt b/Documentation/devicetree/bindings/clock/ti/dpll.txt index df57009ff8e7..37a7cb6ad07d 100644 --- a/Documentation/devicetree/bindings/clock/ti/dpll.txt +++ b/Documentation/devicetree/bindings/clock/ti/dpll.txt @@ -42,6 +42,11 @@ Required properties: "idlest" - contains the idle status register base address "mult-div1" - contains the multiplier / divider register base address "autoidle" - contains the autoidle register base address (optional) + "ssc-deltam" - DPLL supports spread spectrum clocking (SSC), contains + the frequency spreading register base address (optional) + "ssc-modfreq" - DPLL supports spread spectrum clocking (SSC), contains + the modulation frequency register base address + (optional) ti,am3-* dpll types do not have autoidle register ti,omap2-* dpll type does not support idlest / autoidle registers @@ -51,6 +56,14 @@ Optional properties: - ti,low-power-stop : DPLL supports low power stop mode, gating output - ti,low-power-bypass : DPLL output matches rate of parent bypass clock - ti,lock : DPLL locks in programmed rate + - ti,min-div : the minimum divisor to start from to round the DPLL + target rate + - ti,ssc-deltam : DPLL supports spread spectrum clocking, frequency + spreading in permille (10th of a percent) + - ti,ssc-modfreq-hz : DPLL supports spread spectrum clocking, spread + spectrum modulation frequency + - ti,ssc-downspread : DPLL supports spread spectrum clocking, boolean + to enable the downspread feature Examples: dpll_core_ck: dpll_core_ck@44e00490 { @@ -83,3 +96,10 @@ Examples: clocks = <&sys_ck>, <&sys_ck>; reg = <0x0500>, <0x0540>; }; + + dpll_disp_ck: dpll_disp_ck { + #clock-cells = <0>; + compatible = "ti,am3-dpll-no-gate-clock"; + clocks = <&sys_clkin_ck>, <&sys_clkin_ck>; + reg = <0x0498>, <0x0448>, <0x0454>, <0x044c>, <0x0450>; + }; From a543293391ad9711948c6a255716e375c6c060e6 Mon Sep 17 00:00:00 2001 From: Dario Binacchi Date: Sun, 6 Jun 2021 22:22:51 +0200 Subject: [PATCH 060/161] ARM: dts: am33xx-clocks: add spread spectrum support Registers for adjusting the spread spectrum clocking (SSC) have been added. As reported by the TI spruh73x RM, SSC is supported only for LCD and MPU PLLs, but the CM_SSC_DELTAMSTEP_DPLL_XXX and CM_SSC_MODFREQDIV_DPLL_XXX registers, as well as the enable field in the CM_CLKMODE_DPLL_XXX registers are mapped for all PLLs (CORE, MPU, DDR, PER, DISP). Signed-off-by: Dario Binacchi Acked-by: Tony Lindgren Link: https://lore.kernel.org/r/20210606202253.31649-4-dariobin@libero.it Signed-off-by: Stephen Boyd --- arch/arm/boot/dts/am33xx-clocks.dtsi | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/arm/boot/dts/am33xx-clocks.dtsi b/arch/arm/boot/dts/am33xx-clocks.dtsi index dced92a8970e..b7b7106f2dee 100644 --- a/arch/arm/boot/dts/am33xx-clocks.dtsi +++ b/arch/arm/boot/dts/am33xx-clocks.dtsi @@ -164,7 +164,7 @@ #clock-cells = <0>; compatible = "ti,am3-dpll-core-clock"; clocks = <&sys_clkin_ck>, <&sys_clkin_ck>; - reg = <0x0490>, <0x045c>, <0x0468>; + reg = <0x0490>, <0x045c>, <0x0468>, <0x0460>, <0x0464>; }; dpll_core_x2_ck: dpll_core_x2_ck { @@ -204,7 +204,7 @@ #clock-cells = <0>; compatible = "ti,am3-dpll-clock"; clocks = <&sys_clkin_ck>, <&sys_clkin_ck>; - reg = <0x0488>, <0x0420>, <0x042c>; + reg = <0x0488>, <0x0420>, <0x042c>, <0x0424>, <0x0428>; }; dpll_mpu_m2_ck: dpll_mpu_m2_ck@4a8 { @@ -220,7 +220,7 @@ #clock-cells = <0>; compatible = "ti,am3-dpll-no-gate-clock"; clocks = <&sys_clkin_ck>, <&sys_clkin_ck>; - reg = <0x0494>, <0x0434>, <0x0440>; + reg = <0x0494>, <0x0434>, <0x0440>, <0x0438>, <0x043c>; }; dpll_ddr_m2_ck: dpll_ddr_m2_ck@4a0 { @@ -244,7 +244,7 @@ #clock-cells = <0>; compatible = "ti,am3-dpll-no-gate-clock"; clocks = <&sys_clkin_ck>, <&sys_clkin_ck>; - reg = <0x0498>, <0x0448>, <0x0454>; + reg = <0x0498>, <0x0448>, <0x0454>, <0x044c>, <0x0450>; }; dpll_disp_m2_ck: dpll_disp_m2_ck@4a4 { @@ -261,7 +261,7 @@ #clock-cells = <0>; compatible = "ti,am3-dpll-no-gate-j-type-clock"; clocks = <&sys_clkin_ck>, <&sys_clkin_ck>; - reg = <0x048c>, <0x0470>, <0x049c>; + reg = <0x048c>, <0x0470>, <0x049c>, <0x0474>, <0x0478>; }; dpll_per_m2_ck: dpll_per_m2_ck@4ac { From 2fdf0b888eba99c244b5ddde69243088951f1976 Mon Sep 17 00:00:00 2001 From: Dario Binacchi Date: Sun, 6 Jun 2021 22:22:52 +0200 Subject: [PATCH 061/161] ARM: dts: am43xx-clocks: add spread spectrum support Registers for adjusting the spread spectrum clocking (SSC) have been added. As reported by the TI spruhl7x RM, SSC is supported only for LCD and MPU PLLs, but the PRCM_CM_SSC_DELTAMSTEP_DPLL_XXX and PRCM_CM_SSC_MODFREQDIV_DPLL_XXX registers, as well as the enable field in the PRCM_CM_CLKMODE_DPLL_XXX registers are mapped for all PLLs (CORE, MPU, DDR, PER, DISP, EXTDEV). Signed-off-by: Dario Binacchi Acked-by: Tony Lindgren Link: https://lore.kernel.org/r/20210606202253.31649-5-dariobin@libero.it Signed-off-by: Stephen Boyd --- arch/arm/boot/dts/am43xx-clocks.dtsi | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/arch/arm/boot/dts/am43xx-clocks.dtsi b/arch/arm/boot/dts/am43xx-clocks.dtsi index c726cd8dbdf1..314fc5975acb 100644 --- a/arch/arm/boot/dts/am43xx-clocks.dtsi +++ b/arch/arm/boot/dts/am43xx-clocks.dtsi @@ -204,7 +204,7 @@ #clock-cells = <0>; compatible = "ti,am3-dpll-core-clock"; clocks = <&sys_clkin_ck>, <&sys_clkin_ck>; - reg = <0x2d20>, <0x2d24>, <0x2d2c>; + reg = <0x2d20>, <0x2d24>, <0x2d2c>, <0x2d48>, <0x2d4c>; }; dpll_core_x2_ck: dpll_core_x2_ck { @@ -250,7 +250,7 @@ #clock-cells = <0>; compatible = "ti,am3-dpll-clock"; clocks = <&sys_clkin_ck>, <&sys_clkin_ck>; - reg = <0x2d60>, <0x2d64>, <0x2d6c>; + reg = <0x2d60>, <0x2d64>, <0x2d6c>, <0x2d88>, <0x2d8c>; }; dpll_mpu_m2_ck: dpll_mpu_m2_ck@2d70 { @@ -276,7 +276,7 @@ #clock-cells = <0>; compatible = "ti,am3-dpll-clock"; clocks = <&sys_clkin_ck>, <&sys_clkin_ck>; - reg = <0x2da0>, <0x2da4>, <0x2dac>; + reg = <0x2da0>, <0x2da4>, <0x2dac>, <0x2dc8>, <0x2dcc>; }; dpll_ddr_m2_ck: dpll_ddr_m2_ck@2db0 { @@ -294,7 +294,7 @@ #clock-cells = <0>; compatible = "ti,am3-dpll-clock"; clocks = <&sys_clkin_ck>, <&sys_clkin_ck>; - reg = <0x2e20>, <0x2e24>, <0x2e2c>; + reg = <0x2e20>, <0x2e24>, <0x2e2c>, <0x2e48>, <0x2e4c>; }; dpll_disp_m2_ck: dpll_disp_m2_ck@2e30 { @@ -313,7 +313,7 @@ #clock-cells = <0>; compatible = "ti,am3-dpll-j-type-clock"; clocks = <&sys_clkin_ck>, <&sys_clkin_ck>; - reg = <0x2de0>, <0x2de4>, <0x2dec>; + reg = <0x2de0>, <0x2de4>, <0x2dec>, <0x2e08>, <0x2e0c>; }; dpll_per_m2_ck: dpll_per_m2_ck@2df0 { @@ -557,7 +557,7 @@ #clock-cells = <0>; compatible = "ti,am3-dpll-clock"; clocks = <&sys_clkin_ck>, <&sys_clkin_ck>; - reg = <0x2e60>, <0x2e64>, <0x2e6c>; + reg = <0x2e60>, <0x2e64>, <0x2e6c>, <0x2e88>, <0x2e8c>; }; dpll_extdev_m2_ck: dpll_extdev_m2_ck@2e70 { From 0899431f95a7a695f342527548b24ffd902c68ab Mon Sep 17 00:00:00 2001 From: Dario Binacchi Date: Sun, 6 Jun 2021 22:22:53 +0200 Subject: [PATCH 062/161] clk: ti: add am33xx/am43xx spread spectrum clock support The patch enables spread spectrum clocking (SSC) for MPU and LCD PLLs. As reported by the TI spruh73x/spruhl7x RM, SSC is only supported for the DISP/LCD and MPU PLLs on am33xx/am43xx. SSC is not supported for DDR, PER, and CORE PLLs. Calculating the required values and setting the registers accordingly was taken from the set_mpu_spreadspectrum routine contained in the arch/arm/mach-omap2/am33xx/clock_am33xx.c file of the u-boot project. In locked condition, DPLL output clock = CLKINP *[M/N]. In case of SSC enabled, the reference manual explains that there is a restriction of range of M values. Since the omap2_dpll_round_rate routine attempts to select the minimum possible N, the value of M obtained is not guaranteed to be within the range required. With the new "ti,min-div" parameter it is possible to increase N and consequently M to satisfy the constraint imposed by SSC. Signed-off-by: Dario Binacchi Reviewed-by: Tero Kristo Link: https://lore.kernel.org/r/20210606202253.31649-6-dariobin@libero.it Signed-off-by: Stephen Boyd --- drivers/clk/ti/dpll.c | 39 ++++++++++++++++++ drivers/clk/ti/dpll3xxx.c | 85 +++++++++++++++++++++++++++++++++++++++ include/linux/clk/ti.h | 22 ++++++++++ 3 files changed, 146 insertions(+) diff --git a/drivers/clk/ti/dpll.c b/drivers/clk/ti/dpll.c index d6f1ac5b53e1..e9f9aee936ae 100644 --- a/drivers/clk/ti/dpll.c +++ b/drivers/clk/ti/dpll.c @@ -290,7 +290,9 @@ static void __init of_ti_dpll_setup(struct device_node *node, struct clk_init_data *init = NULL; const char **parent_names = NULL; struct dpll_data *dd = NULL; + int ssc_clk_index; u8 dpll_mode = 0; + u32 min_div; dd = kmemdup(ddt, sizeof(*dd), GFP_KERNEL); clk_hw = kzalloc(sizeof(*clk_hw), GFP_KERNEL); @@ -345,6 +347,27 @@ static void __init of_ti_dpll_setup(struct device_node *node, if (dd->autoidle_mask) { if (ti_clk_get_reg_addr(node, 3, &dd->autoidle_reg)) goto cleanup; + + ssc_clk_index = 4; + } else { + ssc_clk_index = 3; + } + + if (dd->ssc_deltam_int_mask && dd->ssc_deltam_frac_mask && + dd->ssc_modfreq_mant_mask && dd->ssc_modfreq_exp_mask) { + if (ti_clk_get_reg_addr(node, ssc_clk_index++, + &dd->ssc_deltam_reg)) + goto cleanup; + + if (ti_clk_get_reg_addr(node, ssc_clk_index++, + &dd->ssc_modfreq_reg)) + goto cleanup; + + of_property_read_u32(node, "ti,ssc-modfreq-hz", + &dd->ssc_modfreq); + of_property_read_u32(node, "ti,ssc-deltam", &dd->ssc_deltam); + dd->ssc_downspread = + of_property_read_bool(node, "ti,ssc-downspread"); } if (of_property_read_bool(node, "ti,low-power-stop")) @@ -356,6 +379,10 @@ static void __init of_ti_dpll_setup(struct device_node *node, if (of_property_read_bool(node, "ti,lock")) dpll_mode |= 1 << DPLL_LOCKED; + if (!of_property_read_u32(node, "ti,min-div", &min_div) && + min_div > dd->min_divider) + dd->min_divider = min_div; + if (dpll_mode) dd->modes = dpll_mode; @@ -585,8 +612,14 @@ static void __init of_ti_am3_no_gate_dpll_setup(struct device_node *node) const struct dpll_data dd = { .idlest_mask = 0x1, .enable_mask = 0x7, + .ssc_enable_mask = 0x1 << 12, + .ssc_downspread_mask = 0x1 << 14, .mult_mask = 0x7ff << 8, .div1_mask = 0x7f, + .ssc_deltam_int_mask = 0x3 << 18, + .ssc_deltam_frac_mask = 0x3ffff, + .ssc_modfreq_mant_mask = 0x7f, + .ssc_modfreq_exp_mask = 0x7 << 8, .max_multiplier = 2047, .max_divider = 128, .min_divider = 1, @@ -645,8 +678,14 @@ static void __init of_ti_am3_dpll_setup(struct device_node *node) const struct dpll_data dd = { .idlest_mask = 0x1, .enable_mask = 0x7, + .ssc_enable_mask = 0x1 << 12, + .ssc_downspread_mask = 0x1 << 14, .mult_mask = 0x7ff << 8, .div1_mask = 0x7f, + .ssc_deltam_int_mask = 0x3 << 18, + .ssc_deltam_frac_mask = 0x3ffff, + .ssc_modfreq_mant_mask = 0x7f, + .ssc_modfreq_exp_mask = 0x7 << 8, .max_multiplier = 2047, .max_divider = 128, .min_divider = 1, diff --git a/drivers/clk/ti/dpll3xxx.c b/drivers/clk/ti/dpll3xxx.c index 94d5b5fe9a2b..e32b3515f9e7 100644 --- a/drivers/clk/ti/dpll3xxx.c +++ b/drivers/clk/ti/dpll3xxx.c @@ -291,6 +291,88 @@ static void _lookup_sddiv(struct clk_hw_omap *clk, u8 *sd_div, u16 m, u8 n) *sd_div = sd; } +/** + * omap3_noncore_dpll_ssc_program - set spread-spectrum clocking registers + * @clk: struct clk * of DPLL to set + * + * Enable the DPLL spread spectrum clocking if frequency modulation and + * frequency spreading have been set, otherwise disable it. + */ +static void omap3_noncore_dpll_ssc_program(struct clk_hw_omap *clk) +{ + struct dpll_data *dd = clk->dpll_data; + unsigned long ref_rate; + u32 v, ctrl, mod_freq_divider, exponent, mantissa; + u32 deltam_step, deltam_ceil; + + ctrl = ti_clk_ll_ops->clk_readl(&dd->control_reg); + + if (dd->ssc_modfreq && dd->ssc_deltam) { + ctrl |= dd->ssc_enable_mask; + + if (dd->ssc_downspread) + ctrl |= dd->ssc_downspread_mask; + else + ctrl &= ~dd->ssc_downspread_mask; + + ref_rate = clk_hw_get_rate(dd->clk_ref); + mod_freq_divider = + (ref_rate / dd->last_rounded_n) / (4 * dd->ssc_modfreq); + if (dd->ssc_modfreq > (ref_rate / 70)) + pr_warn("clock: SSC modulation frequency of DPLL %s greater than %ld\n", + __clk_get_name(clk->hw.clk), ref_rate / 70); + + exponent = 0; + mantissa = mod_freq_divider; + while ((mantissa > 127) && (exponent < 7)) { + exponent++; + mantissa /= 2; + } + if (mantissa > 127) + mantissa = 127; + + v = ti_clk_ll_ops->clk_readl(&dd->ssc_modfreq_reg); + v &= ~(dd->ssc_modfreq_mant_mask | dd->ssc_modfreq_exp_mask); + v |= mantissa << __ffs(dd->ssc_modfreq_mant_mask); + v |= exponent << __ffs(dd->ssc_modfreq_exp_mask); + ti_clk_ll_ops->clk_writel(v, &dd->ssc_modfreq_reg); + + deltam_step = dd->last_rounded_m * dd->ssc_deltam; + deltam_step /= 10; + if (dd->ssc_downspread) + deltam_step /= 2; + + deltam_step <<= __ffs(dd->ssc_deltam_int_mask); + deltam_step /= 100; + deltam_step /= mod_freq_divider; + if (deltam_step > 0xFFFFF) + deltam_step = 0xFFFFF; + + deltam_ceil = (deltam_step & dd->ssc_deltam_int_mask) >> + __ffs(dd->ssc_deltam_int_mask); + if (deltam_step & dd->ssc_deltam_frac_mask) + deltam_ceil++; + + if ((dd->ssc_downspread && + ((dd->last_rounded_m - (2 * deltam_ceil)) < 20 || + dd->last_rounded_m > 2045)) || + ((dd->last_rounded_m - deltam_ceil) < 20 || + (dd->last_rounded_m + deltam_ceil) > 2045)) + pr_warn("clock: SSC multiplier of DPLL %s is out of range\n", + __clk_get_name(clk->hw.clk)); + + v = ti_clk_ll_ops->clk_readl(&dd->ssc_deltam_reg); + v &= ~(dd->ssc_deltam_int_mask | dd->ssc_deltam_frac_mask); + v |= deltam_step << __ffs(dd->ssc_deltam_int_mask | + dd->ssc_deltam_frac_mask); + ti_clk_ll_ops->clk_writel(v, &dd->ssc_deltam_reg); + } else { + ctrl &= ~dd->ssc_enable_mask; + } + + ti_clk_ll_ops->clk_writel(ctrl, &dd->control_reg); +} + /** * omap3_noncore_dpll_program - set non-core DPLL M,N values directly * @clk: struct clk * of DPLL to set @@ -390,6 +472,9 @@ static int omap3_noncore_dpll_program(struct clk_hw_omap *clk, u16 freqsel) ti_clk_ll_ops->clk_writel(v, &dd->control_reg); } + if (dd->ssc_enable_mask) + omap3_noncore_dpll_ssc_program(clk); + /* We let the clock framework set the other output dividers later */ /* REVISIT: Set ramp-up delay? */ diff --git a/include/linux/clk/ti.h b/include/linux/clk/ti.h index c62f6fa6763d..3486f20a3753 100644 --- a/include/linux/clk/ti.h +++ b/include/linux/clk/ti.h @@ -63,6 +63,17 @@ struct clk_omap_reg { * @auto_recal_bit: bitshift of the driftguard enable bit in @control_reg * @recal_en_bit: bitshift of the PRM_IRQENABLE_* bit for recalibration IRQs * @recal_st_bit: bitshift of the PRM_IRQSTATUS_* bit for recalibration IRQs + * @ssc_deltam_reg: register containing the DPLL SSC frequency spreading + * @ssc_modfreq_reg: register containing the DPLL SSC modulation frequency + * @ssc_modfreq_mant_mask: mask of the mantissa component in @ssc_modfreq_reg + * @ssc_modfreq_exp_mask: mask of the exponent component in @ssc_modfreq_reg + * @ssc_enable_mask: mask of the DPLL SSC enable bit in @control_reg + * @ssc_downspread_mask: mask of the DPLL SSC low frequency only bit in + * @control_reg + * @ssc_modfreq: the DPLL SSC frequency modulation in kHz + * @ssc_deltam: the DPLL SSC frequency spreading in permille (10th of percent) + * @ssc_downspread: require the only low frequency spread of the DPLL in SSC + * mode * @flags: DPLL type/features (see below) * * Possible values for @flags: @@ -110,6 +121,17 @@ struct dpll_data { u8 auto_recal_bit; u8 recal_en_bit; u8 recal_st_bit; + struct clk_omap_reg ssc_deltam_reg; + struct clk_omap_reg ssc_modfreq_reg; + u32 ssc_deltam_int_mask; + u32 ssc_deltam_frac_mask; + u32 ssc_modfreq_mant_mask; + u32 ssc_modfreq_exp_mask; + u32 ssc_enable_mask; + u32 ssc_downspread_mask; + u32 ssc_modfreq; + u32 ssc_deltam; + bool ssc_downspread; u8 flags; }; From fc336ae622df0ec114dbe5551a4d2760c535ecd0 Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Thu, 27 May 2021 23:16:47 +0200 Subject: [PATCH 063/161] clk: vc5: fix output disabling when enabling a FOD MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On 5P49V6965, when an output is enabled we enable the corresponding FOD. When this happens for the first time, and specifically when writing register VC5_OUT_DIV_CONTROL in vc5_clk_out_prepare(), all other outputs are stopped for a short time and then restarted. According to Renesas support this is intended: "The reason for that is VC6E has synced up all output function". This behaviour can be disabled at least on VersaClock 6E devices, of which only the 5P49V6965 is currently implemented by this driver. This requires writing bit 7 (bypass_sync{1..4}) in register 0x20..0x50. Those registers are named "Unused Factory Reserved Register", and the bits are documented as "Skip VDDO verification", which does not clearly explain the relation to FOD sync. However according to Renesas support as well as my testing setting this bit does prevent disabling of all clock outputs when enabling a FOD. See "VersaClock ® 6E Family Register Descriptions and Programming Guide" (August 30, 2018), Table 116 "Power Up VDD check", page 58: https://www.renesas.com/us/en/document/mau/versaclock-6e-family-register-descriptions-and-programming-guide Signed-off-by: Luca Ceresoli Reviewed-by: Adam Ford Link: https://lore.kernel.org/r/20210527211647.1520720-1-luca@lucaceresoli.net Fixes: 2bda748e6ad8 ("clk: vc5: Add support for IDT VersaClock 5P49V6965") Signed-off-by: Stephen Boyd --- drivers/clk/clk-versaclock5.c | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/drivers/clk/clk-versaclock5.c b/drivers/clk/clk-versaclock5.c index 344cd6c61188..3c737742c2a9 100644 --- a/drivers/clk/clk-versaclock5.c +++ b/drivers/clk/clk-versaclock5.c @@ -69,7 +69,10 @@ #define VC5_FEEDBACK_FRAC_DIV(n) (0x19 + (n)) #define VC5_RC_CONTROL0 0x1e #define VC5_RC_CONTROL1 0x1f -/* Register 0x20 is factory reserved */ + +/* These registers are named "Unused Factory Reserved Registers" */ +#define VC5_RESERVED_X0(idx) (0x20 + ((idx) * 0x10)) +#define VC5_RESERVED_X0_BYPASS_SYNC BIT(7) /* bypass_sync bit */ /* Output divider control for divider 1,2,3,4 */ #define VC5_OUT_DIV_CONTROL(idx) (0x21 + ((idx) * 0x10)) @@ -87,7 +90,6 @@ #define VC5_OUT_DIV_SKEW_INT(idx, n) (0x2b + ((idx) * 0x10) + (n)) #define VC5_OUT_DIV_INT(idx, n) (0x2d + ((idx) * 0x10) + (n)) #define VC5_OUT_DIV_SKEW_FRAC(idx) (0x2f + ((idx) * 0x10)) -/* Registers 0x30, 0x40, 0x50 are factory reserved */ /* Clock control register for clock 1,2 */ #define VC5_CLK_OUTPUT_CFG(idx, n) (0x60 + ((idx) * 0x2) + (n)) @@ -140,6 +142,8 @@ #define VC5_HAS_INTERNAL_XTAL BIT(0) /* chip has PFD requency doubler */ #define VC5_HAS_PFD_FREQ_DBL BIT(1) +/* chip has bits to disable FOD sync */ +#define VC5_HAS_BYPASS_SYNC_BIT BIT(2) /* Supported IDT VC5 models. */ enum vc5_model { @@ -581,6 +585,23 @@ static int vc5_clk_out_prepare(struct clk_hw *hw) unsigned int src; int ret; + /* + * When enabling a FOD, all currently enabled FODs are briefly + * stopped in order to synchronize all of them. This causes a clock + * disruption to any unrelated chips that might be already using + * other clock outputs. Bypass the sync feature to avoid the issue, + * which is possible on the VersaClock 6E family via reserved + * registers. + */ + if (vc5->chip_info->flags & VC5_HAS_BYPASS_SYNC_BIT) { + ret = regmap_update_bits(vc5->regmap, + VC5_RESERVED_X0(hwdata->num), + VC5_RESERVED_X0_BYPASS_SYNC, + VC5_RESERVED_X0_BYPASS_SYNC); + if (ret) + return ret; + } + /* * If the input mux is disabled, enable it first and * select source from matching FOD. @@ -1166,7 +1187,7 @@ static const struct vc5_chip_info idt_5p49v6965_info = { .model = IDT_VC6_5P49V6965, .clk_fod_cnt = 4, .clk_out_cnt = 5, - .flags = 0, + .flags = VC5_HAS_BYPASS_SYNC_BIT, }; static const struct i2c_device_id vc5_id[] = { From 8271813e404cd0620f99fbccffd2746f85a17259 Mon Sep 17 00:00:00 2001 From: Nick Xie Date: Fri, 4 Jun 2021 11:29:57 +0800 Subject: [PATCH 064/161] clk: meson: g12a: Add missing NNA source clocks for g12b This adds the Neural Network Accelerator source clocks for g12b. Initial support for sm1 already exist in commit 2f1efa5340ef ("clk: meson: g12a: Add support for NNA CLK source clocks") The sm1 and g12b share the same NNA source clocks. This patch add missing NNA clocks for A311D (g12b). Signed-off-by: Nick Xie Acked-by: Neil Armstrong Reviewed-by: Martin Blumenstingl Signed-off-by: Jerome Brunet Link: https://lore.kernel.org/r/20210604032957.224496-1-xieqinick@gmail.com --- drivers/clk/meson/g12a.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/clk/meson/g12a.c b/drivers/clk/meson/g12a.c index a805bac93c11..310accf94830 100644 --- a/drivers/clk/meson/g12a.c +++ b/drivers/clk/meson/g12a.c @@ -4723,6 +4723,12 @@ static struct clk_hw_onecell_data g12b_hw_onecell_data = { [CLKID_SPICC1_SCLK_SEL] = &g12a_spicc1_sclk_sel.hw, [CLKID_SPICC1_SCLK_DIV] = &g12a_spicc1_sclk_div.hw, [CLKID_SPICC1_SCLK] = &g12a_spicc1_sclk.hw, + [CLKID_NNA_AXI_CLK_SEL] = &sm1_nna_axi_clk_sel.hw, + [CLKID_NNA_AXI_CLK_DIV] = &sm1_nna_axi_clk_div.hw, + [CLKID_NNA_AXI_CLK] = &sm1_nna_axi_clk.hw, + [CLKID_NNA_CORE_CLK_SEL] = &sm1_nna_core_clk_sel.hw, + [CLKID_NNA_CORE_CLK_DIV] = &sm1_nna_core_clk_div.hw, + [CLKID_NNA_CORE_CLK] = &sm1_nna_core_clk.hw, [CLKID_MIPI_DSI_PXCLK_SEL] = &g12a_mipi_dsi_pxclk_sel.hw, [CLKID_MIPI_DSI_PXCLK_DIV] = &g12a_mipi_dsi_pxclk_div.hw, [CLKID_MIPI_DSI_PXCLK] = &g12a_mipi_dsi_pxclk.hw, From 403921373799a133e41b59cb730e2c4239663f51 Mon Sep 17 00:00:00 2001 From: Lad Prabhakar Date: Wed, 9 Jun 2021 16:32:25 +0100 Subject: [PATCH 065/161] dt-bindings: clock: Add r9a07g044 CPG Clock Definitions Define RZ/G2L (R9A07G044) Clock Pulse Generator Core Clock and module clock outputs, as listed in Table 8.3 ("Clock List") of the RZ/G2L Hardware User's Manual (Rev.0.42, Feb.2021). Signed-off-by: Lad Prabhakar Reviewed-by: Biju Das Link: https://lore.kernel.org/r/20210609153230.6967-7-prabhakar.mahadev-lad.rj@bp.renesas.com Signed-off-by: Geert Uytterhoeven --- include/dt-bindings/clock/r9a07g044-cpg.h | 89 +++++++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 include/dt-bindings/clock/r9a07g044-cpg.h diff --git a/include/dt-bindings/clock/r9a07g044-cpg.h b/include/dt-bindings/clock/r9a07g044-cpg.h new file mode 100644 index 000000000000..1d8986563fc5 --- /dev/null +++ b/include/dt-bindings/clock/r9a07g044-cpg.h @@ -0,0 +1,89 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) + * + * Copyright (C) 2021 Renesas Electronics Corp. + */ +#ifndef __DT_BINDINGS_CLOCK_R9A07G044_CPG_H__ +#define __DT_BINDINGS_CLOCK_R9A07G044_CPG_H__ + +#include + +/* R9A07G044 CPG Core Clocks */ +#define R9A07G044_CLK_I 0 +#define R9A07G044_CLK_I2 1 +#define R9A07G044_CLK_G 2 +#define R9A07G044_CLK_S0 3 +#define R9A07G044_CLK_S1 4 +#define R9A07G044_CLK_SPI0 5 +#define R9A07G044_CLK_SPI1 6 +#define R9A07G044_CLK_SD0 7 +#define R9A07G044_CLK_SD1 8 +#define R9A07G044_CLK_M0 9 +#define R9A07G044_CLK_M1 10 +#define R9A07G044_CLK_M2 11 +#define R9A07G044_CLK_M3 12 +#define R9A07G044_CLK_M4 13 +#define R9A07G044_CLK_HP 14 +#define R9A07G044_CLK_TSU 15 +#define R9A07G044_CLK_ZT 16 +#define R9A07G044_CLK_P0 17 +#define R9A07G044_CLK_P1 18 +#define R9A07G044_CLK_P2 19 +#define R9A07G044_CLK_AT 20 +#define R9A07G044_OSCCLK 21 + +/* R9A07G044 Module Clocks */ +#define R9A07G044_CLK_GIC600 0 +#define R9A07G044_CLK_IA55 1 +#define R9A07G044_CLK_SYC 2 +#define R9A07G044_CLK_DMAC 3 +#define R9A07G044_CLK_SYSC 4 +#define R9A07G044_CLK_MTU 5 +#define R9A07G044_CLK_GPT 6 +#define R9A07G044_CLK_ETH0 7 +#define R9A07G044_CLK_ETH1 8 +#define R9A07G044_CLK_I2C0 9 +#define R9A07G044_CLK_I2C1 10 +#define R9A07G044_CLK_I2C2 11 +#define R9A07G044_CLK_I2C3 12 +#define R9A07G044_CLK_SCIF0 13 +#define R9A07G044_CLK_SCIF1 14 +#define R9A07G044_CLK_SCIF2 15 +#define R9A07G044_CLK_SCIF3 16 +#define R9A07G044_CLK_SCIF4 17 +#define R9A07G044_CLK_SCI0 18 +#define R9A07G044_CLK_SCI1 19 +#define R9A07G044_CLK_GPIO 20 +#define R9A07G044_CLK_SDHI0 21 +#define R9A07G044_CLK_SDHI1 22 +#define R9A07G044_CLK_USB0 23 +#define R9A07G044_CLK_USB1 24 +#define R9A07G044_CLK_CANFD 25 +#define R9A07G044_CLK_SSI0 26 +#define R9A07G044_CLK_SSI1 27 +#define R9A07G044_CLK_SSI2 28 +#define R9A07G044_CLK_SSI3 29 +#define R9A07G044_CLK_MHU 30 +#define R9A07G044_CLK_OSTM0 31 +#define R9A07G044_CLK_OSTM1 32 +#define R9A07G044_CLK_OSTM2 33 +#define R9A07G044_CLK_WDT0 34 +#define R9A07G044_CLK_WDT1 35 +#define R9A07G044_CLK_WDT2 36 +#define R9A07G044_CLK_WDT_PON 37 +#define R9A07G044_CLK_GPU 38 +#define R9A07G044_CLK_ISU 39 +#define R9A07G044_CLK_H264 40 +#define R9A07G044_CLK_CRU 41 +#define R9A07G044_CLK_MIPI_DSI 42 +#define R9A07G044_CLK_LCDC 43 +#define R9A07G044_CLK_SRC 44 +#define R9A07G044_CLK_RSPI0 45 +#define R9A07G044_CLK_RSPI1 46 +#define R9A07G044_CLK_RSPI2 47 +#define R9A07G044_CLK_ADC 48 +#define R9A07G044_CLK_TSU_PCLK 49 +#define R9A07G044_CLK_SPI 50 +#define R9A07G044_CLK_MIPI_DSI_V 51 +#define R9A07G044_CLK_MIPI_DSI_PIN 52 + +#endif /* __DT_BINDINGS_CLOCK_R9A07G044_CPG_H__ */ From f8ec89126a72b399e63399d8d21fd413f4059f00 Mon Sep 17 00:00:00 2001 From: Lad Prabhakar Date: Wed, 9 Jun 2021 16:32:26 +0100 Subject: [PATCH 066/161] dt-bindings: clock: renesas: Document RZ/G2L SoC CPG driver Document the device tree bindings of the Renesas RZ/G2L SoC clock driver in Documentation/devicetree/bindings/clock/renesas,rzg2l-cpg.yaml. Signed-off-by: Lad Prabhakar Reviewed-by: Biju Das Reviewed-by: Rob Herring Link: https://lore.kernel.org/r/20210609153230.6967-8-prabhakar.mahadev-lad.rj@bp.renesas.com Signed-off-by: Geert Uytterhoeven --- .../bindings/clock/renesas,rzg2l-cpg.yaml | 83 +++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/renesas,rzg2l-cpg.yaml diff --git a/Documentation/devicetree/bindings/clock/renesas,rzg2l-cpg.yaml b/Documentation/devicetree/bindings/clock/renesas,rzg2l-cpg.yaml new file mode 100644 index 000000000000..30b2e3d0d25d --- /dev/null +++ b/Documentation/devicetree/bindings/clock/renesas,rzg2l-cpg.yaml @@ -0,0 +1,83 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: "http://devicetree.org/schemas/clock/renesas,rzg2l-cpg.yaml#" +$schema: "http://devicetree.org/meta-schemas/core.yaml#" + +title: Renesas RZ/G2L Clock Pulse Generator / Module Standby Mode + +maintainers: + - Geert Uytterhoeven + +description: | + On Renesas RZ/G2L SoC, the CPG (Clock Pulse Generator) and Module + Standby Mode share the same register block. + + They provide the following functionalities: + - The CPG block generates various core clocks, + - The Module Standby Mode block provides two functions: + 1. Module Standby, providing a Clock Domain to control the clock supply + to individual SoC devices, + 2. Reset Control, to perform a software reset of individual SoC devices. + +properties: + compatible: + const: renesas,r9a07g044-cpg # RZ/G2{L,LC} + + reg: + maxItems: 1 + + clocks: + maxItems: 1 + + clock-names: + description: + Clock source to CPG can be either from external clock input (EXCLK) or + crystal oscillator (XIN/XOUT). + const: extal + + '#clock-cells': + description: | + - For CPG core clocks, the two clock specifier cells must be "CPG_CORE" + and a core clock reference, as defined in + + - For module clocks, the two clock specifier cells must be "CPG_MOD" and + a module number, as defined in the . + const: 2 + + '#power-domain-cells': + description: + SoC devices that are part of the CPG/Module Standby Mode Clock Domain and + can be power-managed through Module Standby should refer to the CPG device + node in their "power-domains" property, as documented by the generic PM + Domain bindings in Documentation/devicetree/bindings/power/power-domain.yaml. + const: 0 + + '#reset-cells': + description: + The single reset specifier cell must be the module number, as defined in + the . + const: 1 + +required: + - compatible + - reg + - clocks + - clock-names + - '#clock-cells' + - '#power-domain-cells' + - '#reset-cells' + +additionalProperties: false + +examples: + - | + cpg: clock-controller@11010000 { + compatible = "renesas,r9a07g044-cpg"; + reg = <0x11010000 0x10000>; + clocks = <&extal_clk>; + clock-names = "extal"; + #clock-cells = <2>; + #power-domain-cells = <0>; + #reset-cells = <1>; + }; From ef3c613ccd68a78727b817c3dacf4a68d1ffc67f Mon Sep 17 00:00:00 2001 From: Lad Prabhakar Date: Wed, 9 Jun 2021 16:32:27 +0100 Subject: [PATCH 067/161] clk: renesas: Add CPG core wrapper for RZ/G2L SoC Add CPG core wrapper for RZ/G2L family. Based on a patch in the BSP by Binh Nguyen . Signed-off-by: Lad Prabhakar Reviewed-by: Biju Das Link: https://lore.kernel.org/r/20210609153230.6967-9-prabhakar.mahadev-lad.rj@bp.renesas.com Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/Kconfig | 4 + drivers/clk/renesas/Makefile | 1 + drivers/clk/renesas/renesas-rzg2l-cpg.c | 744 ++++++++++++++++++++++++ drivers/clk/renesas/renesas-rzg2l-cpg.h | 134 +++++ 4 files changed, 883 insertions(+) create mode 100644 drivers/clk/renesas/renesas-rzg2l-cpg.c create mode 100644 drivers/clk/renesas/renesas-rzg2l-cpg.h diff --git a/drivers/clk/renesas/Kconfig b/drivers/clk/renesas/Kconfig index 607e64a17d72..6ec698de2d65 100644 --- a/drivers/clk/renesas/Kconfig +++ b/drivers/clk/renesas/Kconfig @@ -182,6 +182,10 @@ config CLK_RCAR_USB2_CLOCK_SEL help This is a driver for R-Car USB2 clock selector +config CLK_RZG2L + bool "Renesas RZ/G2L family clock support" if COMPILE_TEST + select RESET_CONTROLLER + # Generic config CLK_RENESAS_CPG_MSSR bool "CPG/MSSR clock support" if COMPILE_TEST diff --git a/drivers/clk/renesas/Makefile b/drivers/clk/renesas/Makefile index ef0d2bba92bf..a9c299686b4a 100644 --- a/drivers/clk/renesas/Makefile +++ b/drivers/clk/renesas/Makefile @@ -36,6 +36,7 @@ obj-$(CONFIG_CLK_RCAR_CPG_LIB) += rcar-cpg-lib.o obj-$(CONFIG_CLK_RCAR_GEN2_CPG) += rcar-gen2-cpg.o obj-$(CONFIG_CLK_RCAR_GEN3_CPG) += rcar-gen3-cpg.o obj-$(CONFIG_CLK_RCAR_USB2_CLOCK_SEL) += rcar-usb2-clock-sel.o +obj-$(CONFIG_CLK_RZG2L) += renesas-rzg2l-cpg.o # Generic obj-$(CONFIG_CLK_RENESAS_CPG_MSSR) += renesas-cpg-mssr.o diff --git a/drivers/clk/renesas/renesas-rzg2l-cpg.c b/drivers/clk/renesas/renesas-rzg2l-cpg.c new file mode 100644 index 000000000000..cc2842d31a71 --- /dev/null +++ b/drivers/clk/renesas/renesas-rzg2l-cpg.c @@ -0,0 +1,744 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * RZ/G2L Clock Pulse Generator + * + * Copyright (C) 2021 Renesas Electronics Corp. + * + * Based on renesas-cpg-mssr.c + * + * Copyright (C) 2015 Glider bvba + * Copyright (C) 2013 Ideas On Board SPRL + * Copyright (C) 2015 Renesas Electronics Corp. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "renesas-rzg2l-cpg.h" + +#ifdef DEBUG +#define WARN_DEBUG(x) WARN_ON(x) +#else +#define WARN_DEBUG(x) do { } while (0) +#endif + +#define DIV_RSMASK(v, s, m) ((v >> s) & m) +#define GET_SHIFT(val) ((val >> 12) & 0xff) +#define GET_WIDTH(val) ((val >> 8) & 0xf) + +#define KDIV(val) DIV_RSMASK(val, 16, 0xffff) +#define MDIV(val) DIV_RSMASK(val, 6, 0x3ff) +#define PDIV(val) DIV_RSMASK(val, 0, 0x3f) +#define SDIV(val) DIV_RSMASK(val, 0, 0x7) + +#define CLK_ON_R(reg) (reg) +#define CLK_MON_R(reg) (0x680 - 0x500 + (reg)) +#define CLK_RST_R(reg) (0x800 - 0x500 + (reg)) +#define CLK_MRST_R(reg) (0x980 - 0x500 + (reg)) + +#define GET_REG_OFFSET(val) ((val >> 20) & 0xfff) +#define GET_REG_SAMPLL_CLK1(val) ((val >> 22) & 0xfff) +#define GET_REG_SAMPLL_CLK2(val) ((val >> 12) & 0xfff) + +/** + * struct rzg2l_cpg_priv - Clock Pulse Generator Private Data + * + * @rcdev: Reset controller entity + * @dev: CPG device + * @base: CPG register block base address + * @rmw_lock: protects register accesses + * @clks: Array containing all Core and Module Clocks + * @num_core_clks: Number of Core Clocks in clks[] + * @num_mod_clks: Number of Module Clocks in clks[] + * @last_dt_core_clk: ID of the last Core Clock exported to DT + * @notifiers: Notifier chain to save/restore clock state for system resume + * @info: Pointer to platform data + */ +struct rzg2l_cpg_priv { + struct reset_controller_dev rcdev; + struct device *dev; + void __iomem *base; + spinlock_t rmw_lock; + + struct clk **clks; + unsigned int num_core_clks; + unsigned int num_mod_clks; + unsigned int last_dt_core_clk; + + struct raw_notifier_head notifiers; + const struct rzg2l_cpg_info *info; +}; + +static void rzg2l_cpg_del_clk_provider(void *data) +{ + of_clk_del_provider(data); +} + +static struct clk * __init +rzg2l_cpg_div_clk_register(const struct cpg_core_clk *core, + struct clk **clks, + void __iomem *base, + struct rzg2l_cpg_priv *priv) +{ + struct device *dev = priv->dev; + const struct clk *parent; + const char *parent_name; + struct clk_hw *clk_hw; + + parent = clks[core->parent & 0xffff]; + if (IS_ERR(parent)) + return ERR_CAST(parent); + + parent_name = __clk_get_name(parent); + + if (core->dtable) + clk_hw = clk_hw_register_divider_table(dev, core->name, + parent_name, 0, + base + GET_REG_OFFSET(core->conf), + GET_SHIFT(core->conf), + GET_WIDTH(core->conf), + core->flag, + core->dtable, + &priv->rmw_lock); + else + clk_hw = clk_hw_register_divider(dev, core->name, + parent_name, 0, + base + GET_REG_OFFSET(core->conf), + GET_SHIFT(core->conf), + GET_WIDTH(core->conf), + core->flag, &priv->rmw_lock); + + if (IS_ERR(clk_hw)) + return NULL; + + return clk_hw->clk; +} + +struct pll_clk { + struct clk_hw hw; + unsigned int conf; + unsigned int type; + void __iomem *base; + struct rzg2l_cpg_priv *priv; +}; + +#define to_pll(_hw) container_of(_hw, struct pll_clk, hw) + +static unsigned long rzg2l_cpg_pll_clk_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct pll_clk *pll_clk = to_pll(hw); + struct rzg2l_cpg_priv *priv = pll_clk->priv; + unsigned int val1, val2; + unsigned int mult = 1; + unsigned int div = 1; + + if (pll_clk->type != CLK_TYPE_SAM_PLL) + return parent_rate; + + val1 = readl(priv->base + GET_REG_SAMPLL_CLK1(pll_clk->conf)); + val2 = readl(priv->base + GET_REG_SAMPLL_CLK2(pll_clk->conf)); + mult = MDIV(val1) + KDIV(val1) / 65536; + div = PDIV(val1) * (1 << SDIV(val2)); + + return DIV_ROUND_CLOSEST_ULL((u64)parent_rate * mult, div); +} + +static const struct clk_ops rzg2l_cpg_pll_ops = { + .recalc_rate = rzg2l_cpg_pll_clk_recalc_rate, +}; + +static struct clk * __init +rzg2l_cpg_pll_clk_register(const struct cpg_core_clk *core, + struct clk **clks, + void __iomem *base, + struct rzg2l_cpg_priv *priv) +{ + struct device *dev = priv->dev; + const struct clk *parent; + struct clk_init_data init; + const char *parent_name; + struct pll_clk *pll_clk; + struct clk *clk; + + parent = clks[core->parent & 0xffff]; + if (IS_ERR(parent)) + return ERR_CAST(parent); + + pll_clk = devm_kzalloc(dev, sizeof(*pll_clk), GFP_KERNEL); + if (!pll_clk) { + clk = ERR_PTR(-ENOMEM); + return NULL; + } + + parent_name = __clk_get_name(parent); + init.name = core->name; + init.ops = &rzg2l_cpg_pll_ops; + init.flags = 0; + init.parent_names = &parent_name; + init.num_parents = 1; + + pll_clk->hw.init = &init; + pll_clk->conf = core->conf; + pll_clk->base = base; + pll_clk->priv = priv; + pll_clk->type = core->type; + + clk = clk_register(NULL, &pll_clk->hw); + if (IS_ERR(clk)) + kfree(pll_clk); + + return clk; +} + +static struct clk +*rzg2l_cpg_clk_src_twocell_get(struct of_phandle_args *clkspec, + void *data) +{ + unsigned int clkidx = clkspec->args[1]; + struct rzg2l_cpg_priv *priv = data; + struct device *dev = priv->dev; + const char *type; + struct clk *clk; + + switch (clkspec->args[0]) { + case CPG_CORE: + type = "core"; + if (clkidx > priv->last_dt_core_clk) { + dev_err(dev, "Invalid %s clock index %u\n", type, clkidx); + return ERR_PTR(-EINVAL); + } + clk = priv->clks[clkidx]; + break; + + case CPG_MOD: + type = "module"; + if (clkidx > priv->num_mod_clks) { + dev_err(dev, "Invalid %s clock index %u\n", type, + clkidx); + return ERR_PTR(-EINVAL); + } + clk = priv->clks[priv->num_core_clks + clkidx]; + break; + + default: + dev_err(dev, "Invalid CPG clock type %u\n", clkspec->args[0]); + return ERR_PTR(-EINVAL); + } + + if (IS_ERR(clk)) + dev_err(dev, "Cannot get %s clock %u: %ld", type, clkidx, + PTR_ERR(clk)); + else + dev_dbg(dev, "clock (%u, %u) is %pC at %lu Hz\n", + clkspec->args[0], clkspec->args[1], clk, + clk_get_rate(clk)); + return clk; +} + +static void __init +rzg2l_cpg_register_core_clk(const struct cpg_core_clk *core, + const struct rzg2l_cpg_info *info, + struct rzg2l_cpg_priv *priv) +{ + struct clk *clk = ERR_PTR(-EOPNOTSUPP), *parent; + struct device *dev = priv->dev; + unsigned int id = core->id, div = core->div; + const char *parent_name; + + WARN_DEBUG(id >= priv->num_core_clks); + WARN_DEBUG(PTR_ERR(priv->clks[id]) != -ENOENT); + + if (!core->name) { + /* Skip NULLified clock */ + return; + } + + switch (core->type) { + case CLK_TYPE_IN: + clk = of_clk_get_by_name(priv->dev->of_node, core->name); + break; + case CLK_TYPE_FF: + WARN_DEBUG(core->parent >= priv->num_core_clks); + parent = priv->clks[core->parent]; + if (IS_ERR(parent)) { + clk = parent; + goto fail; + } + + parent_name = __clk_get_name(parent); + clk = clk_register_fixed_factor(NULL, core->name, + parent_name, CLK_SET_RATE_PARENT, + core->mult, div); + break; + case CLK_TYPE_SAM_PLL: + clk = rzg2l_cpg_pll_clk_register(core, priv->clks, + priv->base, priv); + break; + case CLK_TYPE_DIV: + clk = rzg2l_cpg_div_clk_register(core, priv->clks, + priv->base, priv); + break; + default: + goto fail; + }; + + if (IS_ERR_OR_NULL(clk)) + goto fail; + + dev_dbg(dev, "Core clock %pC at %lu Hz\n", clk, clk_get_rate(clk)); + priv->clks[id] = clk; + return; + +fail: + dev_err(dev, "Failed to register %s clock %s: %ld\n", "core", + core->name, PTR_ERR(clk)); +} + +/** + * struct mstp_clock - MSTP gating clock + * + * @hw: handle between common and hardware-specific interfaces + * @off: register offset + * @onoff: ON/MON bits + * @reset: reset bits + * @priv: CPG/MSTP private data + */ +struct mstp_clock { + struct clk_hw hw; + u16 off; + u8 onoff; + u8 reset; + struct rzg2l_cpg_priv *priv; +}; + +#define to_mod_clock(_hw) container_of(_hw, struct mstp_clock, hw) + +static int rzg2l_mod_clock_endisable(struct clk_hw *hw, bool enable) +{ + struct mstp_clock *clock = to_mod_clock(hw); + struct rzg2l_cpg_priv *priv = clock->priv; + unsigned int reg = clock->off; + struct device *dev = priv->dev; + unsigned long flags; + unsigned int i; + u32 value; + + if (!clock->off) { + dev_dbg(dev, "%pC does not support ON/OFF\n", hw->clk); + return 0; + } + + dev_dbg(dev, "CLK_ON %u/%pC %s\n", CLK_ON_R(reg), hw->clk, + enable ? "ON" : "OFF"); + spin_lock_irqsave(&priv->rmw_lock, flags); + + if (enable) + value = (clock->onoff << 16) | clock->onoff; + else + value = clock->onoff << 16; + writel(value, priv->base + CLK_ON_R(reg)); + + spin_unlock_irqrestore(&priv->rmw_lock, flags); + + if (!enable) + return 0; + + for (i = 1000; i > 0; --i) { + if (((readl(priv->base + CLK_MON_R(reg))) & clock->onoff)) + break; + cpu_relax(); + } + + if (!i) { + dev_err(dev, "Failed to enable CLK_ON %p\n", + priv->base + CLK_ON_R(reg)); + return -ETIMEDOUT; + } + + return 0; +} + +static int rzg2l_mod_clock_enable(struct clk_hw *hw) +{ + return rzg2l_mod_clock_endisable(hw, true); +} + +static void rzg2l_mod_clock_disable(struct clk_hw *hw) +{ + rzg2l_mod_clock_endisable(hw, false); +} + +static int rzg2l_mod_clock_is_enabled(struct clk_hw *hw) +{ + struct mstp_clock *clock = to_mod_clock(hw); + struct rzg2l_cpg_priv *priv = clock->priv; + u32 value; + + if (!clock->off) { + dev_dbg(priv->dev, "%pC does not support ON/OFF\n", hw->clk); + return 1; + } + + value = readl(priv->base + CLK_MON_R(clock->off)); + + return !(value & clock->onoff); +} + +static const struct clk_ops rzg2l_mod_clock_ops = { + .enable = rzg2l_mod_clock_enable, + .disable = rzg2l_mod_clock_disable, + .is_enabled = rzg2l_mod_clock_is_enabled, +}; + +static void __init +rzg2l_cpg_register_mod_clk(const struct rzg2l_mod_clk *mod, + const struct rzg2l_cpg_info *info, + struct rzg2l_cpg_priv *priv) +{ + struct mstp_clock *clock = NULL; + struct device *dev = priv->dev; + unsigned int id = mod->id; + struct clk_init_data init; + struct clk *parent, *clk; + const char *parent_name; + unsigned int i; + + WARN_DEBUG(id < priv->num_core_clks); + WARN_DEBUG(id >= priv->num_core_clks + priv->num_mod_clks); + WARN_DEBUG(mod->parent >= priv->num_core_clks + priv->num_mod_clks); + WARN_DEBUG(PTR_ERR(priv->clks[id]) != -ENOENT); + + if (!mod->name) { + /* Skip NULLified clock */ + return; + } + + parent = priv->clks[mod->parent]; + if (IS_ERR(parent)) { + clk = parent; + goto fail; + } + + clock = devm_kzalloc(dev, sizeof(*clock), GFP_KERNEL); + if (!clock) { + clk = ERR_PTR(-ENOMEM); + goto fail; + } + + init.name = mod->name; + init.ops = &rzg2l_mod_clock_ops; + init.flags = CLK_SET_RATE_PARENT; + for (i = 0; i < info->num_crit_mod_clks; i++) + if (id == info->crit_mod_clks[i]) { + dev_dbg(dev, "CPG %s setting CLK_IS_CRITICAL\n", + mod->name); + init.flags |= CLK_IS_CRITICAL; + break; + } + + parent_name = __clk_get_name(parent); + init.parent_names = &parent_name; + init.num_parents = 1; + + clock->off = mod->off; + clock->onoff = mod->onoff; + clock->reset = mod->reset; + clock->priv = priv; + clock->hw.init = &init; + + clk = clk_register(NULL, &clock->hw); + if (IS_ERR(clk)) + goto fail; + + dev_dbg(dev, "Module clock %pC at %lu Hz\n", clk, clk_get_rate(clk)); + priv->clks[id] = clk; + return; + +fail: + dev_err(dev, "Failed to register %s clock %s: %ld\n", "module", + mod->name, PTR_ERR(clk)); + kfree(clock); +} + +#define rcdev_to_priv(x) container_of(x, struct rzg2l_cpg_priv, rcdev) + +static int rzg2l_cpg_reset(struct reset_controller_dev *rcdev, + unsigned long id) +{ + struct rzg2l_cpg_priv *priv = rcdev_to_priv(rcdev); + const struct rzg2l_cpg_info *info = priv->info; + unsigned int reg = info->mod_clks[id].off; + u32 dis = info->mod_clks[id].reset; + u32 we = dis << 16; + + dev_dbg(rcdev->dev, "reset name:%s id:%ld offset:0x%x\n", + info->mod_clks[id].name, id, CLK_RST_R(reg)); + + /* Reset module */ + writel(we, priv->base + CLK_RST_R(reg)); + + /* Wait for at least one cycle of the RCLK clock (@ ca. 32 kHz) */ + udelay(35); + + /* Release module from reset state */ + writel(we | dis, priv->base + CLK_RST_R(reg)); + + return 0; +} + +static int rzg2l_cpg_assert(struct reset_controller_dev *rcdev, + unsigned long id) +{ + struct rzg2l_cpg_priv *priv = rcdev_to_priv(rcdev); + const struct rzg2l_cpg_info *info = priv->info; + unsigned int reg = info->mod_clks[id].off; + u32 value = info->mod_clks[id].reset << 16; + + dev_dbg(rcdev->dev, "assert name:%s id:%ld offset:0x%x\n", + info->mod_clks[id].name, id, CLK_RST_R(reg)); + + writel(value, priv->base + CLK_RST_R(reg)); + return 0; +} + +static int rzg2l_cpg_deassert(struct reset_controller_dev *rcdev, + unsigned long id) +{ + struct rzg2l_cpg_priv *priv = rcdev_to_priv(rcdev); + const struct rzg2l_cpg_info *info = priv->info; + unsigned int reg = info->mod_clks[id].off; + u32 dis = info->mod_clks[id].reset; + u32 value = (dis << 16) | dis; + + dev_dbg(rcdev->dev, "deassert name:%s id:%ld offset:0x%x\n", + info->mod_clks[id].name, id, CLK_RST_R(reg)); + + writel(value, priv->base + CLK_RST_R(reg)); + return 0; +} + +static int rzg2l_cpg_status(struct reset_controller_dev *rcdev, + unsigned long id) +{ + struct rzg2l_cpg_priv *priv = rcdev_to_priv(rcdev); + const struct rzg2l_cpg_info *info = priv->info; + unsigned int reg = info->mod_clks[id].off; + u32 bitmask = info->mod_clks[id].reset; + + return !(readl(priv->base + CLK_MRST_R(reg)) & bitmask); +} + +static const struct reset_control_ops rzg2l_cpg_reset_ops = { + .reset = rzg2l_cpg_reset, + .assert = rzg2l_cpg_assert, + .deassert = rzg2l_cpg_deassert, + .status = rzg2l_cpg_status, +}; + +static int rzg2l_cpg_reset_xlate(struct reset_controller_dev *rcdev, + const struct of_phandle_args *reset_spec) +{ + unsigned int id = reset_spec->args[0]; + + if (id >= rcdev->nr_resets) { + dev_err(rcdev->dev, "Invalid reset index %u\n", id); + return -EINVAL; + } + + return id; +} + +static int rzg2l_cpg_reset_controller_register(struct rzg2l_cpg_priv *priv) +{ + priv->rcdev.ops = &rzg2l_cpg_reset_ops; + priv->rcdev.of_node = priv->dev->of_node; + priv->rcdev.dev = priv->dev; + priv->rcdev.of_reset_n_cells = 1; + priv->rcdev.of_xlate = rzg2l_cpg_reset_xlate; + priv->rcdev.nr_resets = priv->num_mod_clks; + + return devm_reset_controller_register(priv->dev, &priv->rcdev); +} + +static bool rzg2l_cpg_is_pm_clk(const struct of_phandle_args *clkspec) +{ + if (clkspec->args_count != 2) + return false; + + switch (clkspec->args[0]) { + case CPG_MOD: + return true; + + default: + return false; + } +} + +static int rzg2l_cpg_attach_dev(struct generic_pm_domain *unused, struct device *dev) +{ + struct device_node *np = dev->of_node; + struct of_phandle_args clkspec; + struct clk *clk; + int error; + int i = 0; + + while (!of_parse_phandle_with_args(np, "clocks", "#clock-cells", i, + &clkspec)) { + if (rzg2l_cpg_is_pm_clk(&clkspec)) + goto found; + + of_node_put(clkspec.np); + i++; + } + + return 0; + +found: + clk = of_clk_get_from_provider(&clkspec); + of_node_put(clkspec.np); + + if (IS_ERR(clk)) + return PTR_ERR(clk); + + error = pm_clk_create(dev); + if (error) + goto fail_put; + + error = pm_clk_add_clk(dev, clk); + if (error) + goto fail_destroy; + + return 0; + +fail_destroy: + pm_clk_destroy(dev); +fail_put: + clk_put(clk); + return error; +} + +static void rzg2l_cpg_detach_dev(struct generic_pm_domain *unused, struct device *dev) +{ + if (!pm_clk_no_clocks(dev)) + pm_clk_destroy(dev); +} + +static int __init rzg2l_cpg_add_clk_domain(struct device *dev) +{ + struct device_node *np = dev->of_node; + struct generic_pm_domain *genpd; + + genpd = devm_kzalloc(dev, sizeof(*genpd), GFP_KERNEL); + if (!genpd) + return -ENOMEM; + + genpd->name = np->name; + genpd->flags = GENPD_FLAG_PM_CLK | GENPD_FLAG_ALWAYS_ON | + GENPD_FLAG_ACTIVE_WAKEUP; + genpd->attach_dev = rzg2l_cpg_attach_dev; + genpd->detach_dev = rzg2l_cpg_detach_dev; + pm_genpd_init(genpd, &pm_domain_always_on_gov, false); + + of_genpd_add_provider_simple(np, genpd); + return 0; +} + +static int __init rzg2l_cpg_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; + const struct rzg2l_cpg_info *info; + struct rzg2l_cpg_priv *priv; + unsigned int nclks, i; + struct clk **clks; + int error; + + info = of_device_get_match_data(dev); + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->dev = dev; + priv->info = info; + spin_lock_init(&priv->rmw_lock); + + priv->base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(priv->base)) + return PTR_ERR(priv->base); + + nclks = info->num_total_core_clks + info->num_hw_mod_clks; + clks = devm_kmalloc_array(dev, nclks, sizeof(*clks), GFP_KERNEL); + if (!clks) + return -ENOMEM; + + dev_set_drvdata(dev, priv); + priv->clks = clks; + priv->num_core_clks = info->num_total_core_clks; + priv->num_mod_clks = info->num_hw_mod_clks; + priv->last_dt_core_clk = info->last_dt_core_clk; + + for (i = 0; i < nclks; i++) + clks[i] = ERR_PTR(-ENOENT); + + for (i = 0; i < info->num_core_clks; i++) + rzg2l_cpg_register_core_clk(&info->core_clks[i], info, priv); + + for (i = 0; i < info->num_mod_clks; i++) + rzg2l_cpg_register_mod_clk(&info->mod_clks[i], info, priv); + + error = of_clk_add_provider(np, rzg2l_cpg_clk_src_twocell_get, priv); + if (error) + return error; + + error = devm_add_action_or_reset(dev, rzg2l_cpg_del_clk_provider, np); + if (error) + return error; + + error = rzg2l_cpg_add_clk_domain(dev); + if (error) + return error; + + error = rzg2l_cpg_reset_controller_register(priv); + if (error) + return error; + + return 0; +} + +static const struct of_device_id rzg2l_cpg_match[] = { + { /* sentinel */ } +}; + +static struct platform_driver rzg2l_cpg_driver = { + .driver = { + .name = "rzg2l-cpg", + .of_match_table = rzg2l_cpg_match, + }, +}; + +static int __init rzg2l_cpg_init(void) +{ + return platform_driver_probe(&rzg2l_cpg_driver, rzg2l_cpg_probe); +} + +subsys_initcall(rzg2l_cpg_init); + +MODULE_DESCRIPTION("Renesas RZ/G2L CPG Driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/clk/renesas/renesas-rzg2l-cpg.h b/drivers/clk/renesas/renesas-rzg2l-cpg.h new file mode 100644 index 000000000000..8ff0047ffeb9 --- /dev/null +++ b/drivers/clk/renesas/renesas-rzg2l-cpg.h @@ -0,0 +1,134 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * RZ/G2L Clock Pulse Generator + * + * Copyright (C) 2021 Renesas Electronics Corp. + * + */ + +#ifndef __RENESAS_RZG2L_CPG_H__ +#define __RENESAS_RZG2L_CPG_H__ + +#define CPG_PL2_DDIV (0x204) +#define CPG_PL3A_DDIV (0x208) + +/* n = 0/1/2 for PLL1/4/6 */ +#define CPG_SAMPLL_CLK1(n) (0x04 + (16 * n)) +#define CPG_SAMPLL_CLK2(n) (0x08 + (16 * n)) + +#define PLL146_CONF(n) (CPG_SAMPLL_CLK1(n) << 22 | CPG_SAMPLL_CLK2(n) << 12) + +#define DDIV_PACK(offset, bitpos, size) \ + (((offset) << 20) | ((bitpos) << 12) | ((size) << 8)) +#define DIVPL2A DDIV_PACK(CPG_PL2_DDIV, 0, 3) +#define DIVPL3B DDIV_PACK(CPG_PL3A_DDIV, 4, 3) + +/** + * Definitions of CPG Core Clocks + * + * These include: + * - Clock outputs exported to DT + * - External input clocks + * - Internal CPG clocks + */ +struct cpg_core_clk { + const char *name; + unsigned int id; + unsigned int parent; + unsigned int div; + unsigned int mult; + unsigned int type; + unsigned int conf; + const struct clk_div_table *dtable; + const char * const *parent_names; + int flag; + int num_parents; +}; + +enum clk_types { + /* Generic */ + CLK_TYPE_IN, /* External Clock Input */ + CLK_TYPE_FF, /* Fixed Factor Clock */ + CLK_TYPE_SAM_PLL, + + /* Clock with divider */ + CLK_TYPE_DIV, +}; + +#define DEF_TYPE(_name, _id, _type...) \ + { .name = _name, .id = _id, .type = _type } +#define DEF_BASE(_name, _id, _type, _parent...) \ + DEF_TYPE(_name, _id, _type, .parent = _parent) +#define DEF_SAMPLL(_name, _id, _parent, _conf) \ + DEF_TYPE(_name, _id, CLK_TYPE_SAM_PLL, .parent = _parent, .conf = _conf) +#define DEF_INPUT(_name, _id) \ + DEF_TYPE(_name, _id, CLK_TYPE_IN) +#define DEF_FIXED(_name, _id, _parent, _mult, _div) \ + DEF_BASE(_name, _id, CLK_TYPE_FF, _parent, .div = _div, .mult = _mult) +#define DEF_DIV(_name, _id, _parent, _conf, _dtable, _flag) \ + DEF_TYPE(_name, _id, CLK_TYPE_DIV, .conf = _conf, \ + .parent = _parent, .dtable = _dtable, .flag = _flag) + +/** + * struct rzg2l_mod_clk - Module Clocks definitions + * + * @name: handle between common and hardware-specific interfaces + * @id: clock index in array containing all Core and Module Clocks + * @parent: id of parent clock + * @off: register offset + * @onoff: ON/MON bits + * @reset: reset bits + */ +struct rzg2l_mod_clk { + const char *name; + unsigned int id; + unsigned int parent; + u16 off; + u8 onoff; + u8 reset; +}; + +#define DEF_MOD(_name, _id, _parent, _off, _onoff, _reset) \ + [_id] = { \ + .name = _name, \ + .id = MOD_CLK_BASE + _id, \ + .parent = (_parent), \ + .off = (_off), \ + .onoff = (_onoff), \ + .reset = (_reset) \ + } + +/** + * struct rzg2l_cpg_info - SoC-specific CPG Description + * + * @core_clks: Array of Core Clock definitions + * @num_core_clks: Number of entries in core_clks[] + * @last_dt_core_clk: ID of the last Core Clock exported to DT + * @num_total_core_clks: Total number of Core Clocks (exported + internal) + * + * @mod_clks: Array of Module Clock definitions + * @num_mod_clks: Number of entries in mod_clks[] + * @num_hw_mod_clks: Number of Module Clocks supported by the hardware + * + * @crit_mod_clks: Array with Module Clock IDs of critical clocks that + * should not be disabled without a knowledgeable driver + * @num_crit_mod_clks: Number of entries in crit_mod_clks[] + */ +struct rzg2l_cpg_info { + /* Core Clocks */ + const struct cpg_core_clk *core_clks; + unsigned int num_core_clks; + unsigned int last_dt_core_clk; + unsigned int num_total_core_clks; + + /* Module Clocks */ + const struct rzg2l_mod_clk *mod_clks; + unsigned int num_mod_clks; + unsigned int num_hw_mod_clks; + + /* Critical Module Clocks that should not be disabled */ + const unsigned int *crit_mod_clks; + unsigned int num_crit_mod_clks; +}; + +#endif From 17f0ff3d49ff1a9d4027f9c2bef4725ab41aa9a5 Mon Sep 17 00:00:00 2001 From: Lad Prabhakar Date: Wed, 9 Jun 2021 16:32:28 +0100 Subject: [PATCH 068/161] clk: renesas: Add support for R9A07G044 SoC Define the clock outputs supported by RZ/G2L (R9A07G044) SoC and bind it with RZ/G2L CPG core. Based on a patch in the BSP by Binh Nguyen . Signed-off-by: Lad Prabhakar Reviewed-by: Biju Das Link: https://lore.kernel.org/r/20210609153230.6967-10-prabhakar.mahadev-lad.rj@bp.renesas.com Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/Kconfig | 5 + drivers/clk/renesas/Makefile | 1 + drivers/clk/renesas/r9a07g044-cpg.c | 127 ++++++++++++++++++++++++ drivers/clk/renesas/renesas-rzg2l-cpg.c | 6 ++ drivers/clk/renesas/renesas-rzg2l-cpg.h | 2 + 5 files changed, 141 insertions(+) create mode 100644 drivers/clk/renesas/r9a07g044-cpg.c diff --git a/drivers/clk/renesas/Kconfig b/drivers/clk/renesas/Kconfig index 6ec698de2d65..7b450650bcae 100644 --- a/drivers/clk/renesas/Kconfig +++ b/drivers/clk/renesas/Kconfig @@ -32,6 +32,7 @@ config CLK_RENESAS select CLK_R8A77995 if ARCH_R8A77995 select CLK_R8A779A0 if ARCH_R8A779A0 select CLK_R9A06G032 if ARCH_R9A06G032 + select CLK_R9A07G044 if ARCH_R9A07G044 select CLK_SH73A0 if ARCH_SH73A0 if CLK_RENESAS @@ -156,6 +157,10 @@ config CLK_R9A06G032 help This is a driver for R9A06G032 clocks +config CLK_R9A07G044 + bool "RZ/G2L clock support" if COMPILE_TEST + select CLK_RZG2L + config CLK_SH73A0 bool "SH-Mobile AG5 clock support" if COMPILE_TEST select CLK_RENESAS_CPG_MSTP diff --git a/drivers/clk/renesas/Makefile b/drivers/clk/renesas/Makefile index a9c299686b4a..5c6c5c721d98 100644 --- a/drivers/clk/renesas/Makefile +++ b/drivers/clk/renesas/Makefile @@ -29,6 +29,7 @@ obj-$(CONFIG_CLK_R8A77990) += r8a77990-cpg-mssr.o obj-$(CONFIG_CLK_R8A77995) += r8a77995-cpg-mssr.o obj-$(CONFIG_CLK_R8A779A0) += r8a779a0-cpg-mssr.o obj-$(CONFIG_CLK_R9A06G032) += r9a06g032-clocks.o +obj-$(CONFIG_CLK_R9A07G044) += r9a07g044-cpg.o obj-$(CONFIG_CLK_SH73A0) += clk-sh73a0.o # Family diff --git a/drivers/clk/renesas/r9a07g044-cpg.c b/drivers/clk/renesas/r9a07g044-cpg.c new file mode 100644 index 000000000000..50b5269586a4 --- /dev/null +++ b/drivers/clk/renesas/r9a07g044-cpg.c @@ -0,0 +1,127 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * RZ/G2L CPG driver + * + * Copyright (C) 2021 Renesas Electronics Corp. + */ + +#include +#include +#include +#include + +#include + +#include "renesas-rzg2l-cpg.h" + +enum clk_ids { + /* Core Clock Outputs exported to DT */ + LAST_DT_CORE_CLK = R9A07G044_OSCCLK, + + /* External Input Clocks */ + CLK_EXTAL, + + /* Internal Core Clocks */ + CLK_OSC_DIV1000, + CLK_PLL1, + CLK_PLL2, + CLK_PLL2_DIV2, + CLK_PLL2_DIV16, + CLK_PLL2_DIV20, + CLK_PLL3, + CLK_PLL3_DIV2, + CLK_PLL3_DIV4, + CLK_PLL3_DIV8, + CLK_PLL4, + CLK_PLL5, + CLK_PLL5_DIV2, + CLK_PLL6, + + /* Module Clocks */ + MOD_CLK_BASE, +}; + +/* Divider tables */ +static const struct clk_div_table dtable_3b[] = { + {0, 1}, + {1, 2}, + {2, 4}, + {3, 8}, + {4, 32}, +}; + +static const struct cpg_core_clk r9a07g044_core_clks[] __initconst = { + /* External Clock Inputs */ + DEF_INPUT("extal", CLK_EXTAL), + + /* Internal Core Clocks */ + DEF_FIXED(".osc", R9A07G044_OSCCLK, CLK_EXTAL, 1, 1), + DEF_FIXED(".osc_div1000", CLK_OSC_DIV1000, CLK_EXTAL, 1, 1000), + DEF_SAMPLL(".pll1", CLK_PLL1, CLK_EXTAL, PLL146_CONF(0)), + DEF_FIXED(".pll2", CLK_PLL2, CLK_EXTAL, 133, 2), + DEF_FIXED(".pll3", CLK_PLL3, CLK_EXTAL, 133, 2), + + DEF_FIXED(".pll2_div2", CLK_PLL2_DIV2, CLK_PLL2, 1, 2), + DEF_FIXED(".pll2_div16", CLK_PLL2_DIV16, CLK_PLL2, 1, 16), + DEF_FIXED(".pll2_div20", CLK_PLL2_DIV20, CLK_PLL2, 1, 20), + + DEF_FIXED(".pll3_div2", CLK_PLL3_DIV2, CLK_PLL3, 1, 2), + DEF_FIXED(".pll3_div4", CLK_PLL3_DIV4, CLK_PLL3, 1, 4), + DEF_FIXED(".pll3_div8", CLK_PLL3_DIV8, CLK_PLL3, 1, 8), + + /* Core output clk */ + DEF_FIXED("I", R9A07G044_CLK_I, CLK_PLL1, 1, 1), + DEF_DIV("P0", R9A07G044_CLK_P0, CLK_PLL2_DIV16, DIVPL2A, + dtable_3b, CLK_DIVIDER_HIWORD_MASK), + DEF_FIXED("TSU", R9A07G044_CLK_TSU, CLK_PLL2_DIV20, 1, 1), + DEF_DIV("P1", R9A07G044_CLK_P1, CLK_PLL3_DIV8, + DIVPL3B, dtable_3b, CLK_DIVIDER_HIWORD_MASK), +}; + +static struct rzg2l_mod_clk r9a07g044_mod_clks[] = { + DEF_MOD("gic", R9A07G044_CLK_GIC600, + R9A07G044_CLK_P1, + 0x514, BIT(0), (BIT(0) | BIT(1))), + DEF_MOD("ia55", R9A07G044_CLK_IA55, + R9A07G044_CLK_P1, + 0x518, (BIT(0) | BIT(1)), BIT(0)), + DEF_MOD("scif0", R9A07G044_CLK_SCIF0, + R9A07G044_CLK_P0, + 0x584, BIT(0), BIT(0)), + DEF_MOD("scif1", R9A07G044_CLK_SCIF1, + R9A07G044_CLK_P0, + 0x584, BIT(1), BIT(1)), + DEF_MOD("scif2", R9A07G044_CLK_SCIF2, + R9A07G044_CLK_P0, + 0x584, BIT(2), BIT(2)), + DEF_MOD("scif3", R9A07G044_CLK_SCIF3, + R9A07G044_CLK_P0, + 0x584, BIT(3), BIT(3)), + DEF_MOD("scif4", R9A07G044_CLK_SCIF4, + R9A07G044_CLK_P0, + 0x584, BIT(4), BIT(4)), + DEF_MOD("sci0", R9A07G044_CLK_SCI0, + R9A07G044_CLK_P0, + 0x588, BIT(0), BIT(0)), +}; + +static const unsigned int r9a07g044_crit_mod_clks[] __initconst = { + MOD_CLK_BASE + R9A07G044_CLK_GIC600, +}; + +const struct rzg2l_cpg_info r9a07g044_cpg_info = { + /* Core Clocks */ + .core_clks = r9a07g044_core_clks, + .num_core_clks = ARRAY_SIZE(r9a07g044_core_clks), + .last_dt_core_clk = LAST_DT_CORE_CLK, + .num_total_core_clks = MOD_CLK_BASE, + + /* Critical Module Clocks */ + .crit_mod_clks = r9a07g044_crit_mod_clks, + .num_crit_mod_clks = ARRAY_SIZE(r9a07g044_crit_mod_clks), + + /* Module Clocks */ + .mod_clks = r9a07g044_mod_clks, + .num_mod_clks = ARRAY_SIZE(r9a07g044_mod_clks), + .num_hw_mod_clks = R9A07G044_CLK_MIPI_DSI_PIN + 1, +}; diff --git a/drivers/clk/renesas/renesas-rzg2l-cpg.c b/drivers/clk/renesas/renesas-rzg2l-cpg.c index cc2842d31a71..5009b9e48b13 100644 --- a/drivers/clk/renesas/renesas-rzg2l-cpg.c +++ b/drivers/clk/renesas/renesas-rzg2l-cpg.c @@ -723,6 +723,12 @@ static int __init rzg2l_cpg_probe(struct platform_device *pdev) } static const struct of_device_id rzg2l_cpg_match[] = { +#ifdef CONFIG_CLK_R9A07G044 + { + .compatible = "renesas,r9a07g044-cpg", + .data = &r9a07g044_cpg_info, + }, +#endif { /* sentinel */ } }; diff --git a/drivers/clk/renesas/renesas-rzg2l-cpg.h b/drivers/clk/renesas/renesas-rzg2l-cpg.h index 8ff0047ffeb9..3948bdd8afc9 100644 --- a/drivers/clk/renesas/renesas-rzg2l-cpg.h +++ b/drivers/clk/renesas/renesas-rzg2l-cpg.h @@ -131,4 +131,6 @@ struct rzg2l_cpg_info { unsigned int num_crit_mod_clks; }; +extern const struct rzg2l_cpg_info r9a07g044_cpg_info; + #endif From b24e288d5063356dfcfc5250dc122cc8af73e6ac Mon Sep 17 00:00:00 2001 From: Jacky Bai Date: Tue, 20 Apr 2021 13:54:53 +0800 Subject: [PATCH 069/161] clk: imx: Remove the audio ipg clock from imx8mp There is no audio ipg clock on i.MX8MP, so remove this from the clock driver. Signed-off-by: Jacky Bai Reviewed-by: Abel Vesa Signed-off-by: Abel Vesa --- drivers/clk/imx/clk-imx8mp.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/clk/imx/clk-imx8mp.c b/drivers/clk/imx/clk-imx8mp.c index e39c9c907c38..12837304545d 100644 --- a/drivers/clk/imx/clk-imx8mp.c +++ b/drivers/clk/imx/clk-imx8mp.c @@ -556,7 +556,6 @@ static int imx8mp_clocks_probe(struct platform_device *pdev) hws[IMX8MP_CLK_MIPI_DSI_ESC_RX] = imx8m_clk_hw_composite_bus("mipi_dsi_esc_rx", imx8mp_mipi_dsi_esc_rx_sels, ccm_base + 0x9200); hws[IMX8MP_CLK_IPG_ROOT] = imx_clk_hw_divider2("ipg_root", "ahb_root", ccm_base + 0x9080, 0, 1); - hws[IMX8MP_CLK_IPG_AUDIO_ROOT] = imx_clk_hw_divider2("ipg_audio_root", "audio_ahb", ccm_base + 0x9180, 0, 1); hws[IMX8MP_CLK_DRAM_ALT] = imx8m_clk_hw_composite("dram_alt", imx8mp_dram_alt_sels, ccm_base + 0xa000); hws[IMX8MP_CLK_DRAM_APB] = imx8m_clk_hw_composite_critical("dram_apb", imx8mp_dram_apb_sels, ccm_base + 0xa080); From e446441a058a39f092cc536402230e852f658c4f Mon Sep 17 00:00:00 2001 From: Dong Aisheng Date: Fri, 23 Apr 2021 11:33:29 +0800 Subject: [PATCH 070/161] dt-bindings: arm: imx: scu: fix naming typo of clk compatible string There is a typo in binding doc that the name of compatible string of scu clock should be "fsl,xxx-clk" rather than "fsl,xxx-clock". In reality, both example and dts using "fsl,xxx-clk", so fixing the doc is enough. Cc: devicetree@vger.kernel.org Signed-off-by: Dong Aisheng Acked-by: Rob Herring Signed-off-by: Abel Vesa --- Documentation/devicetree/bindings/arm/freescale/fsl,scu.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/arm/freescale/fsl,scu.txt b/Documentation/devicetree/bindings/arm/freescale/fsl,scu.txt index 395359dc94fd..3adf3f6f2beb 100644 --- a/Documentation/devicetree/bindings/arm/freescale/fsl,scu.txt +++ b/Documentation/devicetree/bindings/arm/freescale/fsl,scu.txt @@ -86,8 +86,8 @@ This binding uses the common clock binding[1]. Required properties: - compatible: Should be one of: - "fsl,imx8qm-clock" - "fsl,imx8qxp-clock" + "fsl,imx8qm-clk" + "fsl,imx8qxp-clk" followed by "fsl,scu-clk" - #clock-cells: Should be either 2: Contains the Resource and Clock ID value. From 659c12c7f5ceda8a62c92da1b730307c537247fa Mon Sep 17 00:00:00 2001 From: Dong Aisheng Date: Fri, 23 Apr 2021 11:33:30 +0800 Subject: [PATCH 071/161] dt-bindings: arm: imx: scu: drop deprecated legacy clock binding The legacy clock binding are not maintained anymore. It has only a very preliminary supported clocks during initial upstream and meaningless for users. So drop it from binding doc now. Cc: devicetree@vger.kernel.org Signed-off-by: Dong Aisheng Acked-by: Rob Herring Signed-off-by: Abel Vesa --- Documentation/devicetree/bindings/arm/freescale/fsl,scu.txt | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Documentation/devicetree/bindings/arm/freescale/fsl,scu.txt b/Documentation/devicetree/bindings/arm/freescale/fsl,scu.txt index 3adf3f6f2beb..fd0061712443 100644 --- a/Documentation/devicetree/bindings/arm/freescale/fsl,scu.txt +++ b/Documentation/devicetree/bindings/arm/freescale/fsl,scu.txt @@ -89,10 +89,8 @@ Required properties: "fsl,imx8qm-clk" "fsl,imx8qxp-clk" followed by "fsl,scu-clk" -- #clock-cells: Should be either - 2: Contains the Resource and Clock ID value. - or - 1: Contains the Clock ID value. (DEPRECATED) +- #clock-cells: Should be 2. + Contains the Resource and Clock ID value. - clocks: List of clock specifiers, must contain an entry for each required entry in clock-names - clock-names: Should include entries "xtal_32KHz", "xtal_24MHz" From 91e916771de0abaf58094aa9375cd0227eca102a Mon Sep 17 00:00:00 2001 From: Dong Aisheng Date: Fri, 23 Apr 2021 11:33:31 +0800 Subject: [PATCH 072/161] clk: imx: scu: remove legacy scu clock binding support Legacy scu clock binding are not maintained anymore, it has a very limited clocks supported during initial upstreaming and obviously unusable by products. So it's meaningless to keep it in kernel which worse the code readability. Remove it to keep code much cleaner. Signed-off-by: Dong Aisheng Reviewed-by: Abel Vesa Signed-off-by: Abel Vesa --- drivers/clk/imx/clk-imx8qxp.c | 199 ++++++++++--------------- drivers/clk/imx/clk-scu.h | 15 +- include/dt-bindings/clock/imx8-clock.h | 128 ---------------- 3 files changed, 80 insertions(+), 262 deletions(-) diff --git a/drivers/clk/imx/clk-imx8qxp.c b/drivers/clk/imx/clk-imx8qxp.c index fbf1170c09ed..d17b418ac577 100644 --- a/drivers/clk/imx/clk-imx8qxp.c +++ b/drivers/clk/imx/clk-imx8qxp.c @@ -14,7 +14,6 @@ #include "clk-scu.h" -#include #include static const char *dc0_sels[] = { @@ -28,149 +27,103 @@ static const char *dc0_sels[] = { static int imx8qxp_clk_probe(struct platform_device *pdev) { struct device_node *ccm_node = pdev->dev.of_node; - struct clk_hw_onecell_data *clk_data; - struct clk_hw **clks; - u32 clk_cells; - int ret, i; + int ret; ret = imx_clk_scu_init(ccm_node); if (ret) return ret; - clk_data = devm_kzalloc(&pdev->dev, struct_size(clk_data, hws, - IMX_SCU_CLK_END), GFP_KERNEL); - if (!clk_data) - return -ENOMEM; - - if (of_property_read_u32(ccm_node, "#clock-cells", &clk_cells)) - return -EINVAL; - - clk_data->num = IMX_SCU_CLK_END; - clks = clk_data->hws; - - /* Fixed clocks */ - clks[IMX_CLK_DUMMY] = clk_hw_register_fixed_rate(NULL, "dummy", NULL, 0, 0); - clks[IMX_ADMA_IPG_CLK_ROOT] = clk_hw_register_fixed_rate(NULL, "dma_ipg_clk_root", NULL, 0, 120000000); - clks[IMX_CONN_AXI_CLK_ROOT] = clk_hw_register_fixed_rate(NULL, "conn_axi_clk_root", NULL, 0, 333333333); - clks[IMX_CONN_AHB_CLK_ROOT] = clk_hw_register_fixed_rate(NULL, "conn_ahb_clk_root", NULL, 0, 166666666); - clks[IMX_CONN_IPG_CLK_ROOT] = clk_hw_register_fixed_rate(NULL, "conn_ipg_clk_root", NULL, 0, 83333333); - clks[IMX_DC_AXI_EXT_CLK] = clk_hw_register_fixed_rate(NULL, "dc_axi_ext_clk_root", NULL, 0, 800000000); - clks[IMX_DC_AXI_INT_CLK] = clk_hw_register_fixed_rate(NULL, "dc_axi_int_clk_root", NULL, 0, 400000000); - clks[IMX_DC_CFG_CLK] = clk_hw_register_fixed_rate(NULL, "dc_cfg_clk_root", NULL, 0, 100000000); - clks[IMX_MIPI_IPG_CLK] = clk_hw_register_fixed_rate(NULL, "mipi_ipg_clk_root", NULL, 0, 120000000); - clks[IMX_IMG_AXI_CLK] = clk_hw_register_fixed_rate(NULL, "img_axi_clk_root", NULL, 0, 400000000); - clks[IMX_IMG_IPG_CLK] = clk_hw_register_fixed_rate(NULL, "img_ipg_clk_root", NULL, 0, 200000000); - clks[IMX_IMG_PXL_CLK] = clk_hw_register_fixed_rate(NULL, "img_pxl_clk_root", NULL, 0, 600000000); - clks[IMX_HSIO_AXI_CLK] = clk_hw_register_fixed_rate(NULL, "hsio_axi_clk_root", NULL, 0, 400000000); - clks[IMX_HSIO_PER_CLK] = clk_hw_register_fixed_rate(NULL, "hsio_per_clk_root", NULL, 0, 133333333); - clks[IMX_LSIO_MEM_CLK] = clk_hw_register_fixed_rate(NULL, "lsio_mem_clk_root", NULL, 0, 200000000); - clks[IMX_LSIO_BUS_CLK] = clk_hw_register_fixed_rate(NULL, "lsio_bus_clk_root", NULL, 0, 100000000); - /* ARM core */ - clks[IMX_A35_CLK] = imx_clk_scu("a35_clk", IMX_SC_R_A35, IMX_SC_PM_CLK_CPU, clk_cells); + imx_clk_scu("a35_clk", IMX_SC_R_A35, IMX_SC_PM_CLK_CPU); /* LSIO SS */ - clks[IMX_LSIO_PWM0_CLK] = imx_clk_scu("pwm0_clk", IMX_SC_R_PWM_0, IMX_SC_PM_CLK_PER, clk_cells); - clks[IMX_LSIO_PWM1_CLK] = imx_clk_scu("pwm1_clk", IMX_SC_R_PWM_1, IMX_SC_PM_CLK_PER, clk_cells); - clks[IMX_LSIO_PWM2_CLK] = imx_clk_scu("pwm2_clk", IMX_SC_R_PWM_2, IMX_SC_PM_CLK_PER, clk_cells); - clks[IMX_LSIO_PWM3_CLK] = imx_clk_scu("pwm3_clk", IMX_SC_R_PWM_3, IMX_SC_PM_CLK_PER, clk_cells); - clks[IMX_LSIO_PWM4_CLK] = imx_clk_scu("pwm4_clk", IMX_SC_R_PWM_4, IMX_SC_PM_CLK_PER, clk_cells); - clks[IMX_LSIO_PWM5_CLK] = imx_clk_scu("pwm5_clk", IMX_SC_R_PWM_5, IMX_SC_PM_CLK_PER, clk_cells); - clks[IMX_LSIO_PWM6_CLK] = imx_clk_scu("pwm6_clk", IMX_SC_R_PWM_6, IMX_SC_PM_CLK_PER, clk_cells); - clks[IMX_LSIO_PWM7_CLK] = imx_clk_scu("pwm7_clk", IMX_SC_R_PWM_7, IMX_SC_PM_CLK_PER, clk_cells); - clks[IMX_LSIO_GPT0_CLK] = imx_clk_scu("gpt0_clk", IMX_SC_R_GPT_0, IMX_SC_PM_CLK_PER, clk_cells); - clks[IMX_LSIO_GPT1_CLK] = imx_clk_scu("gpt1_clk", IMX_SC_R_GPT_1, IMX_SC_PM_CLK_PER, clk_cells); - clks[IMX_LSIO_GPT2_CLK] = imx_clk_scu("gpt2_clk", IMX_SC_R_GPT_2, IMX_SC_PM_CLK_PER, clk_cells); - clks[IMX_LSIO_GPT3_CLK] = imx_clk_scu("gpt3_clk", IMX_SC_R_GPT_3, IMX_SC_PM_CLK_PER, clk_cells); - clks[IMX_LSIO_GPT4_CLK] = imx_clk_scu("gpt4_clk", IMX_SC_R_GPT_4, IMX_SC_PM_CLK_PER, clk_cells); - clks[IMX_LSIO_FSPI0_CLK] = imx_clk_scu("fspi0_clk", IMX_SC_R_FSPI_0, IMX_SC_PM_CLK_PER, clk_cells); - clks[IMX_LSIO_FSPI1_CLK] = imx_clk_scu("fspi1_clk", IMX_SC_R_FSPI_1, IMX_SC_PM_CLK_PER, clk_cells); + imx_clk_scu("pwm0_clk", IMX_SC_R_PWM_0, IMX_SC_PM_CLK_PER); + imx_clk_scu("pwm1_clk", IMX_SC_R_PWM_1, IMX_SC_PM_CLK_PER); + imx_clk_scu("pwm2_clk", IMX_SC_R_PWM_2, IMX_SC_PM_CLK_PER); + imx_clk_scu("pwm3_clk", IMX_SC_R_PWM_3, IMX_SC_PM_CLK_PER); + imx_clk_scu("pwm4_clk", IMX_SC_R_PWM_4, IMX_SC_PM_CLK_PER); + imx_clk_scu("pwm5_clk", IMX_SC_R_PWM_5, IMX_SC_PM_CLK_PER); + imx_clk_scu("pwm6_clk", IMX_SC_R_PWM_6, IMX_SC_PM_CLK_PER); + imx_clk_scu("pwm7_clk", IMX_SC_R_PWM_7, IMX_SC_PM_CLK_PER); + imx_clk_scu("gpt0_clk", IMX_SC_R_GPT_0, IMX_SC_PM_CLK_PER); + imx_clk_scu("gpt1_clk", IMX_SC_R_GPT_1, IMX_SC_PM_CLK_PER); + imx_clk_scu("gpt2_clk", IMX_SC_R_GPT_2, IMX_SC_PM_CLK_PER); + imx_clk_scu("gpt3_clk", IMX_SC_R_GPT_3, IMX_SC_PM_CLK_PER); + imx_clk_scu("gpt4_clk", IMX_SC_R_GPT_4, IMX_SC_PM_CLK_PER); + imx_clk_scu("fspi0_clk", IMX_SC_R_FSPI_0, IMX_SC_PM_CLK_PER); + imx_clk_scu("fspi1_clk", IMX_SC_R_FSPI_1, IMX_SC_PM_CLK_PER); /* ADMA SS */ - clks[IMX_ADMA_UART0_CLK] = imx_clk_scu("uart0_clk", IMX_SC_R_UART_0, IMX_SC_PM_CLK_PER, clk_cells); - clks[IMX_ADMA_UART1_CLK] = imx_clk_scu("uart1_clk", IMX_SC_R_UART_1, IMX_SC_PM_CLK_PER, clk_cells); - clks[IMX_ADMA_UART2_CLK] = imx_clk_scu("uart2_clk", IMX_SC_R_UART_2, IMX_SC_PM_CLK_PER, clk_cells); - clks[IMX_ADMA_UART3_CLK] = imx_clk_scu("uart3_clk", IMX_SC_R_UART_3, IMX_SC_PM_CLK_PER, clk_cells); - clks[IMX_ADMA_SPI0_CLK] = imx_clk_scu("spi0_clk", IMX_SC_R_SPI_0, IMX_SC_PM_CLK_PER, clk_cells); - clks[IMX_ADMA_SPI1_CLK] = imx_clk_scu("spi1_clk", IMX_SC_R_SPI_1, IMX_SC_PM_CLK_PER, clk_cells); - clks[IMX_ADMA_SPI2_CLK] = imx_clk_scu("spi2_clk", IMX_SC_R_SPI_2, IMX_SC_PM_CLK_PER, clk_cells); - clks[IMX_ADMA_SPI3_CLK] = imx_clk_scu("spi3_clk", IMX_SC_R_SPI_3, IMX_SC_PM_CLK_PER, clk_cells); - clks[IMX_ADMA_CAN0_CLK] = imx_clk_scu("can0_clk", IMX_SC_R_CAN_0, IMX_SC_PM_CLK_PER, clk_cells); - clks[IMX_ADMA_I2C0_CLK] = imx_clk_scu("i2c0_clk", IMX_SC_R_I2C_0, IMX_SC_PM_CLK_PER, clk_cells); - clks[IMX_ADMA_I2C1_CLK] = imx_clk_scu("i2c1_clk", IMX_SC_R_I2C_1, IMX_SC_PM_CLK_PER, clk_cells); - clks[IMX_ADMA_I2C2_CLK] = imx_clk_scu("i2c2_clk", IMX_SC_R_I2C_2, IMX_SC_PM_CLK_PER, clk_cells); - clks[IMX_ADMA_I2C3_CLK] = imx_clk_scu("i2c3_clk", IMX_SC_R_I2C_3, IMX_SC_PM_CLK_PER, clk_cells); - clks[IMX_ADMA_FTM0_CLK] = imx_clk_scu("ftm0_clk", IMX_SC_R_FTM_0, IMX_SC_PM_CLK_PER, clk_cells); - clks[IMX_ADMA_FTM1_CLK] = imx_clk_scu("ftm1_clk", IMX_SC_R_FTM_1, IMX_SC_PM_CLK_PER, clk_cells); - clks[IMX_ADMA_ADC0_CLK] = imx_clk_scu("adc0_clk", IMX_SC_R_ADC_0, IMX_SC_PM_CLK_PER, clk_cells); - clks[IMX_ADMA_PWM_CLK] = imx_clk_scu("pwm_clk", IMX_SC_R_LCD_0_PWM_0, IMX_SC_PM_CLK_PER, clk_cells); - clks[IMX_ADMA_LCD_CLK] = imx_clk_scu("lcd_clk", IMX_SC_R_LCD_0, IMX_SC_PM_CLK_PER, clk_cells); + imx_clk_scu("uart0_clk", IMX_SC_R_UART_0, IMX_SC_PM_CLK_PER); + imx_clk_scu("uart1_clk", IMX_SC_R_UART_1, IMX_SC_PM_CLK_PER); + imx_clk_scu("uart2_clk", IMX_SC_R_UART_2, IMX_SC_PM_CLK_PER); + imx_clk_scu("uart3_clk", IMX_SC_R_UART_3, IMX_SC_PM_CLK_PER); + imx_clk_scu("spi0_clk", IMX_SC_R_SPI_0, IMX_SC_PM_CLK_PER); + imx_clk_scu("spi1_clk", IMX_SC_R_SPI_1, IMX_SC_PM_CLK_PER); + imx_clk_scu("spi2_clk", IMX_SC_R_SPI_2, IMX_SC_PM_CLK_PER); + imx_clk_scu("spi3_clk", IMX_SC_R_SPI_3, IMX_SC_PM_CLK_PER); + imx_clk_scu("can0_clk", IMX_SC_R_CAN_0, IMX_SC_PM_CLK_PER); + imx_clk_scu("i2c0_clk", IMX_SC_R_I2C_0, IMX_SC_PM_CLK_PER); + imx_clk_scu("i2c1_clk", IMX_SC_R_I2C_1, IMX_SC_PM_CLK_PER); + imx_clk_scu("i2c2_clk", IMX_SC_R_I2C_2, IMX_SC_PM_CLK_PER); + imx_clk_scu("i2c3_clk", IMX_SC_R_I2C_3, IMX_SC_PM_CLK_PER); + imx_clk_scu("ftm0_clk", IMX_SC_R_FTM_0, IMX_SC_PM_CLK_PER); + imx_clk_scu("ftm1_clk", IMX_SC_R_FTM_1, IMX_SC_PM_CLK_PER); + imx_clk_scu("adc0_clk", IMX_SC_R_ADC_0, IMX_SC_PM_CLK_PER); + imx_clk_scu("pwm_clk", IMX_SC_R_LCD_0_PWM_0, IMX_SC_PM_CLK_PER); + imx_clk_scu("lcd_clk", IMX_SC_R_LCD_0, IMX_SC_PM_CLK_PER); /* Connectivity */ - clks[IMX_CONN_SDHC0_CLK] = imx_clk_scu("sdhc0_clk", IMX_SC_R_SDHC_0, IMX_SC_PM_CLK_PER, clk_cells); - clks[IMX_CONN_SDHC1_CLK] = imx_clk_scu("sdhc1_clk", IMX_SC_R_SDHC_1, IMX_SC_PM_CLK_PER, clk_cells); - clks[IMX_CONN_SDHC2_CLK] = imx_clk_scu("sdhc2_clk", IMX_SC_R_SDHC_2, IMX_SC_PM_CLK_PER, clk_cells); - clks[IMX_CONN_ENET0_ROOT_CLK] = imx_clk_scu("enet0_clk", IMX_SC_R_ENET_0, IMX_SC_PM_CLK_PER, clk_cells); - clks[IMX_CONN_ENET0_BYPASS_CLK] = imx_clk_scu("enet0_bypass_clk", IMX_SC_R_ENET_0, IMX_SC_PM_CLK_BYPASS, clk_cells); - clks[IMX_CONN_ENET0_RGMII_CLK] = imx_clk_scu("enet0_rgmii_clk", IMX_SC_R_ENET_0, IMX_SC_PM_CLK_MISC0, clk_cells); - clks[IMX_CONN_ENET1_ROOT_CLK] = imx_clk_scu("enet1_clk", IMX_SC_R_ENET_1, IMX_SC_PM_CLK_PER, clk_cells); - clks[IMX_CONN_ENET1_BYPASS_CLK] = imx_clk_scu("enet1_bypass_clk", IMX_SC_R_ENET_1, IMX_SC_PM_CLK_BYPASS, clk_cells); - clks[IMX_CONN_ENET1_RGMII_CLK] = imx_clk_scu("enet1_rgmii_clk", IMX_SC_R_ENET_1, IMX_SC_PM_CLK_MISC0, clk_cells); - clks[IMX_CONN_GPMI_BCH_IO_CLK] = imx_clk_scu("gpmi_io_clk", IMX_SC_R_NAND, IMX_SC_PM_CLK_MST_BUS, clk_cells); - clks[IMX_CONN_GPMI_BCH_CLK] = imx_clk_scu("gpmi_bch_clk", IMX_SC_R_NAND, IMX_SC_PM_CLK_PER, clk_cells); - clks[IMX_CONN_USB2_ACLK] = imx_clk_scu("usb3_aclk_div", IMX_SC_R_USB_2, IMX_SC_PM_CLK_PER, clk_cells); - clks[IMX_CONN_USB2_BUS_CLK] = imx_clk_scu("usb3_bus_div", IMX_SC_R_USB_2, IMX_SC_PM_CLK_MST_BUS, clk_cells); - clks[IMX_CONN_USB2_LPM_CLK] = imx_clk_scu("usb3_lpm_div", IMX_SC_R_USB_2, IMX_SC_PM_CLK_MISC, clk_cells); + imx_clk_scu("sdhc0_clk", IMX_SC_R_SDHC_0, IMX_SC_PM_CLK_PER); + imx_clk_scu("sdhc1_clk", IMX_SC_R_SDHC_1, IMX_SC_PM_CLK_PER); + imx_clk_scu("sdhc2_clk", IMX_SC_R_SDHC_2, IMX_SC_PM_CLK_PER); + imx_clk_scu("enet0_clk", IMX_SC_R_ENET_0, IMX_SC_PM_CLK_PER); + imx_clk_scu("enet0_bypass_clk", IMX_SC_R_ENET_0, IMX_SC_PM_CLK_BYPASS); + imx_clk_scu("enet0_rgmii_clk", IMX_SC_R_ENET_0, IMX_SC_PM_CLK_MISC0); + imx_clk_scu("enet1_clk", IMX_SC_R_ENET_1, IMX_SC_PM_CLK_PER); + imx_clk_scu("enet1_bypass_clk", IMX_SC_R_ENET_1, IMX_SC_PM_CLK_BYPASS); + imx_clk_scu("enet1_rgmii_clk", IMX_SC_R_ENET_1, IMX_SC_PM_CLK_MISC0); + imx_clk_scu("gpmi_io_clk", IMX_SC_R_NAND, IMX_SC_PM_CLK_MST_BUS); + imx_clk_scu("gpmi_bch_clk", IMX_SC_R_NAND, IMX_SC_PM_CLK_PER); + imx_clk_scu("usb3_aclk_div", IMX_SC_R_USB_2, IMX_SC_PM_CLK_PER); + imx_clk_scu("usb3_bus_div", IMX_SC_R_USB_2, IMX_SC_PM_CLK_MST_BUS); + imx_clk_scu("usb3_lpm_div", IMX_SC_R_USB_2, IMX_SC_PM_CLK_MISC); /* Display controller SS */ - clks[IMX_DC0_DISP0_CLK] = imx_clk_scu2("dc0_disp0_clk", dc0_sels, ARRAY_SIZE(dc0_sels), IMX_SC_R_DC_0, IMX_SC_PM_CLK_MISC0, clk_cells); - clks[IMX_DC0_DISP1_CLK] = imx_clk_scu2("dc0_disp1_clk", dc0_sels, ARRAY_SIZE(dc0_sels), IMX_SC_R_DC_0, IMX_SC_PM_CLK_MISC1, clk_cells); - clks[IMX_DC0_PLL0_CLK] = imx_clk_scu("dc0_pll0_clk", IMX_SC_R_DC_0_PLL_0, IMX_SC_PM_CLK_PLL, clk_cells); - clks[IMX_DC0_PLL1_CLK] = imx_clk_scu("dc0_pll1_clk", IMX_SC_R_DC_0_PLL_1, IMX_SC_PM_CLK_PLL, clk_cells); - clks[IMX_DC0_BYPASS0_CLK] = imx_clk_scu("dc0_bypass0_clk", IMX_SC_R_DC_0_VIDEO0, IMX_SC_PM_CLK_BYPASS, clk_cells); - clks[IMX_DC0_BYPASS1_CLK] = imx_clk_scu("dc0_bypass1_clk", IMX_SC_R_DC_0_VIDEO1, IMX_SC_PM_CLK_BYPASS, clk_cells); + imx_clk_scu2("dc0_disp0_clk", dc0_sels, ARRAY_SIZE(dc0_sels), IMX_SC_R_DC_0, IMX_SC_PM_CLK_MISC0); + imx_clk_scu2("dc0_disp1_clk", dc0_sels, ARRAY_SIZE(dc0_sels), IMX_SC_R_DC_0, IMX_SC_PM_CLK_MISC1); + imx_clk_scu("dc0_pll0_clk", IMX_SC_R_DC_0_PLL_0, IMX_SC_PM_CLK_PLL); + imx_clk_scu("dc0_pll1_clk", IMX_SC_R_DC_0_PLL_1, IMX_SC_PM_CLK_PLL); + imx_clk_scu("dc0_bypass0_clk", IMX_SC_R_DC_0_VIDEO0, IMX_SC_PM_CLK_BYPASS); + imx_clk_scu("dc0_bypass1_clk", IMX_SC_R_DC_0_VIDEO1, IMX_SC_PM_CLK_BYPASS); /* MIPI-LVDS SS */ - clks[IMX_MIPI0_LVDS_PIXEL_CLK] = imx_clk_scu("mipi0_lvds_pixel_clk", IMX_SC_R_LVDS_0, IMX_SC_PM_CLK_MISC2, clk_cells); - clks[IMX_MIPI0_LVDS_BYPASS_CLK] = imx_clk_scu("mipi0_lvds_bypass_clk", IMX_SC_R_LVDS_0, IMX_SC_PM_CLK_BYPASS, clk_cells); - clks[IMX_MIPI0_LVDS_PHY_CLK] = imx_clk_scu("mipi0_lvds_phy_clk", IMX_SC_R_LVDS_0, IMX_SC_PM_CLK_MISC3, clk_cells); - clks[IMX_MIPI0_I2C0_CLK] = imx_clk_scu("mipi0_i2c0_clk", IMX_SC_R_MIPI_0_I2C_0, IMX_SC_PM_CLK_MISC2, clk_cells); - clks[IMX_MIPI0_I2C1_CLK] = imx_clk_scu("mipi0_i2c1_clk", IMX_SC_R_MIPI_0_I2C_1, IMX_SC_PM_CLK_MISC2, clk_cells); - clks[IMX_MIPI0_PWM0_CLK] = imx_clk_scu("mipi0_pwm0_clk", IMX_SC_R_MIPI_0_PWM_0, IMX_SC_PM_CLK_PER, clk_cells); - clks[IMX_MIPI1_LVDS_PIXEL_CLK] = imx_clk_scu("mipi1_lvds_pixel_clk", IMX_SC_R_LVDS_1, IMX_SC_PM_CLK_MISC2, clk_cells); - clks[IMX_MIPI1_LVDS_BYPASS_CLK] = imx_clk_scu("mipi1_lvds_bypass_clk", IMX_SC_R_LVDS_1, IMX_SC_PM_CLK_BYPASS, clk_cells); - clks[IMX_MIPI1_LVDS_PHY_CLK] = imx_clk_scu("mipi1_lvds_phy_clk", IMX_SC_R_LVDS_1, IMX_SC_PM_CLK_MISC3, clk_cells); - clks[IMX_MIPI1_I2C0_CLK] = imx_clk_scu("mipi1_i2c0_clk", IMX_SC_R_MIPI_1_I2C_0, IMX_SC_PM_CLK_MISC2, clk_cells); - clks[IMX_MIPI1_I2C1_CLK] = imx_clk_scu("mipi1_i2c1_clk", IMX_SC_R_MIPI_1_I2C_1, IMX_SC_PM_CLK_MISC2, clk_cells); - clks[IMX_MIPI1_PWM0_CLK] = imx_clk_scu("mipi1_pwm0_clk", IMX_SC_R_MIPI_1_PWM_0, IMX_SC_PM_CLK_PER, clk_cells); + imx_clk_scu("mipi0_lvds_pixel_clk", IMX_SC_R_LVDS_0, IMX_SC_PM_CLK_MISC2); + imx_clk_scu("mipi0_lvds_bypass_clk", IMX_SC_R_LVDS_0, IMX_SC_PM_CLK_BYPASS); + imx_clk_scu("mipi0_lvds_phy_clk", IMX_SC_R_LVDS_0, IMX_SC_PM_CLK_MISC3); + imx_clk_scu("mipi0_i2c0_clk", IMX_SC_R_MIPI_0_I2C_0, IMX_SC_PM_CLK_MISC2); + imx_clk_scu("mipi0_i2c1_clk", IMX_SC_R_MIPI_0_I2C_1, IMX_SC_PM_CLK_MISC2); + imx_clk_scu("mipi0_pwm0_clk", IMX_SC_R_MIPI_0_PWM_0, IMX_SC_PM_CLK_PER); + imx_clk_scu("mipi1_lvds_pixel_clk", IMX_SC_R_LVDS_1, IMX_SC_PM_CLK_MISC2); + imx_clk_scu("mipi1_lvds_bypass_clk", IMX_SC_R_LVDS_1, IMX_SC_PM_CLK_BYPASS); + imx_clk_scu("mipi1_lvds_phy_clk", IMX_SC_R_LVDS_1, IMX_SC_PM_CLK_MISC3); + imx_clk_scu("mipi1_i2c0_clk", IMX_SC_R_MIPI_1_I2C_0, IMX_SC_PM_CLK_MISC2); + imx_clk_scu("mipi1_i2c1_clk", IMX_SC_R_MIPI_1_I2C_1, IMX_SC_PM_CLK_MISC2); + imx_clk_scu("mipi1_pwm0_clk", IMX_SC_R_MIPI_1_PWM_0, IMX_SC_PM_CLK_PER); /* MIPI CSI SS */ - clks[IMX_CSI0_CORE_CLK] = imx_clk_scu("mipi_csi0_core_clk", IMX_SC_R_CSI_0, IMX_SC_PM_CLK_PER, clk_cells); - clks[IMX_CSI0_ESC_CLK] = imx_clk_scu("mipi_csi0_esc_clk", IMX_SC_R_CSI_0, IMX_SC_PM_CLK_MISC, clk_cells); - clks[IMX_CSI0_I2C0_CLK] = imx_clk_scu("mipi_csi0_i2c0_clk", IMX_SC_R_CSI_0_I2C_0, IMX_SC_PM_CLK_PER, clk_cells); - clks[IMX_CSI0_PWM0_CLK] = imx_clk_scu("mipi_csi0_pwm0_clk", IMX_SC_R_CSI_0_PWM_0, IMX_SC_PM_CLK_PER, clk_cells); + imx_clk_scu("mipi_csi0_core_clk", IMX_SC_R_CSI_0, IMX_SC_PM_CLK_PER); + imx_clk_scu("mipi_csi0_esc_clk", IMX_SC_R_CSI_0, IMX_SC_PM_CLK_MISC); + imx_clk_scu("mipi_csi0_i2c0_clk", IMX_SC_R_CSI_0_I2C_0, IMX_SC_PM_CLK_PER); + imx_clk_scu("mipi_csi0_pwm0_clk", IMX_SC_R_CSI_0_PWM_0, IMX_SC_PM_CLK_PER); /* GPU SS */ - clks[IMX_GPU0_CORE_CLK] = imx_clk_scu("gpu_core0_clk", IMX_SC_R_GPU_0_PID0, IMX_SC_PM_CLK_PER, clk_cells); - clks[IMX_GPU0_SHADER_CLK] = imx_clk_scu("gpu_shader0_clk", IMX_SC_R_GPU_0_PID0, IMX_SC_PM_CLK_MISC, clk_cells); + imx_clk_scu("gpu_core0_clk", IMX_SC_R_GPU_0_PID0, IMX_SC_PM_CLK_PER); + imx_clk_scu("gpu_shader0_clk", IMX_SC_R_GPU_0_PID0, IMX_SC_PM_CLK_MISC); - for (i = 0; i < clk_data->num; i++) { - if (IS_ERR(clks[i])) - pr_warn("i.MX clk %u: register failed with %ld\n", - i, PTR_ERR(clks[i])); - } - - if (clk_cells == 2) { - ret = of_clk_add_hw_provider(ccm_node, imx_scu_of_clk_src_get, imx_scu_clks); - if (ret) - imx_clk_scu_unregister(); - } else { - /* - * legacy binding code path doesn't unregister here because - * it will be removed later. - */ - ret = of_clk_add_hw_provider(ccm_node, of_clk_hw_onecell_get, clk_data); - } + ret = of_clk_add_hw_provider(ccm_node, imx_scu_of_clk_src_get, imx_scu_clks); + if (ret) + imx_clk_scu_unregister(); return ret; } diff --git a/drivers/clk/imx/clk-scu.h b/drivers/clk/imx/clk-scu.h index e8352164923e..a6c6d3103e94 100644 --- a/drivers/clk/imx/clk-scu.h +++ b/drivers/clk/imx/clk-scu.h @@ -32,22 +32,15 @@ struct clk_hw *__imx_clk_lpcg_scu(struct device *dev, const char *name, void imx_clk_lpcg_scu_unregister(struct clk_hw *hw); static inline struct clk_hw *imx_clk_scu(const char *name, u32 rsrc_id, - u8 clk_type, u8 clk_cells) + u8 clk_type) { - if (clk_cells == 2) - return imx_clk_scu_alloc_dev(name, NULL, 0, rsrc_id, clk_type); - else - return __imx_clk_scu(NULL, name, NULL, 0, rsrc_id, clk_type); + return imx_clk_scu_alloc_dev(name, NULL, 0, rsrc_id, clk_type); } static inline struct clk_hw *imx_clk_scu2(const char *name, const char * const *parents, - int num_parents, u32 rsrc_id, u8 clk_type, - u8 clk_cells) + int num_parents, u32 rsrc_id, u8 clk_type) { - if (clk_cells == 2) - return imx_clk_scu_alloc_dev(name, parents, num_parents, rsrc_id, clk_type); - else - return __imx_clk_scu(NULL, name, parents, num_parents, rsrc_id, clk_type); + return imx_clk_scu_alloc_dev(name, parents, num_parents, rsrc_id, clk_type); } static inline struct clk_hw *imx_clk_lpcg_scu_dev(struct device *dev, const char *name, diff --git a/include/dt-bindings/clock/imx8-clock.h b/include/dt-bindings/clock/imx8-clock.h index 82b1fc8d1ee0..2e60ce4d2622 100644 --- a/include/dt-bindings/clock/imx8-clock.h +++ b/include/dt-bindings/clock/imx8-clock.h @@ -7,134 +7,6 @@ #ifndef __DT_BINDINGS_CLOCK_IMX_H #define __DT_BINDINGS_CLOCK_IMX_H -/* SCU Clocks */ - -#define IMX_CLK_DUMMY 0 - -/* CPU */ -#define IMX_A35_CLK 1 - -/* LSIO SS */ -#define IMX_LSIO_MEM_CLK 2 -#define IMX_LSIO_BUS_CLK 3 -#define IMX_LSIO_PWM0_CLK 10 -#define IMX_LSIO_PWM1_CLK 11 -#define IMX_LSIO_PWM2_CLK 12 -#define IMX_LSIO_PWM3_CLK 13 -#define IMX_LSIO_PWM4_CLK 14 -#define IMX_LSIO_PWM5_CLK 15 -#define IMX_LSIO_PWM6_CLK 16 -#define IMX_LSIO_PWM7_CLK 17 -#define IMX_LSIO_GPT0_CLK 18 -#define IMX_LSIO_GPT1_CLK 19 -#define IMX_LSIO_GPT2_CLK 20 -#define IMX_LSIO_GPT3_CLK 21 -#define IMX_LSIO_GPT4_CLK 22 -#define IMX_LSIO_FSPI0_CLK 23 -#define IMX_LSIO_FSPI1_CLK 24 - -/* Connectivity SS */ -#define IMX_CONN_AXI_CLK_ROOT 30 -#define IMX_CONN_AHB_CLK_ROOT 31 -#define IMX_CONN_IPG_CLK_ROOT 32 -#define IMX_CONN_SDHC0_CLK 40 -#define IMX_CONN_SDHC1_CLK 41 -#define IMX_CONN_SDHC2_CLK 42 -#define IMX_CONN_ENET0_ROOT_CLK 43 -#define IMX_CONN_ENET0_BYPASS_CLK 44 -#define IMX_CONN_ENET0_RGMII_CLK 45 -#define IMX_CONN_ENET1_ROOT_CLK 46 -#define IMX_CONN_ENET1_BYPASS_CLK 47 -#define IMX_CONN_ENET1_RGMII_CLK 48 -#define IMX_CONN_GPMI_BCH_IO_CLK 49 -#define IMX_CONN_GPMI_BCH_CLK 50 -#define IMX_CONN_USB2_ACLK 51 -#define IMX_CONN_USB2_BUS_CLK 52 -#define IMX_CONN_USB2_LPM_CLK 53 - -/* HSIO SS */ -#define IMX_HSIO_AXI_CLK 60 -#define IMX_HSIO_PER_CLK 61 - -/* Display controller SS */ -#define IMX_DC_AXI_EXT_CLK 70 -#define IMX_DC_AXI_INT_CLK 71 -#define IMX_DC_CFG_CLK 72 -#define IMX_DC0_PLL0_CLK 80 -#define IMX_DC0_PLL1_CLK 81 -#define IMX_DC0_DISP0_CLK 82 -#define IMX_DC0_DISP1_CLK 83 -#define IMX_DC0_BYPASS0_CLK 84 -#define IMX_DC0_BYPASS1_CLK 85 - -/* MIPI-LVDS SS */ -#define IMX_MIPI_IPG_CLK 90 -#define IMX_MIPI0_PIXEL_CLK 100 -#define IMX_MIPI0_BYPASS_CLK 101 -#define IMX_MIPI0_LVDS_PIXEL_CLK 102 -#define IMX_MIPI0_LVDS_BYPASS_CLK 103 -#define IMX_MIPI0_LVDS_PHY_CLK 104 -#define IMX_MIPI0_I2C0_CLK 105 -#define IMX_MIPI0_I2C1_CLK 106 -#define IMX_MIPI0_PWM0_CLK 107 -#define IMX_MIPI1_PIXEL_CLK 108 -#define IMX_MIPI1_BYPASS_CLK 109 -#define IMX_MIPI1_LVDS_PIXEL_CLK 110 -#define IMX_MIPI1_LVDS_BYPASS_CLK 111 -#define IMX_MIPI1_LVDS_PHY_CLK 112 -#define IMX_MIPI1_I2C0_CLK 113 -#define IMX_MIPI1_I2C1_CLK 114 -#define IMX_MIPI1_PWM0_CLK 115 - -/* IMG SS */ -#define IMX_IMG_AXI_CLK 120 -#define IMX_IMG_IPG_CLK 121 -#define IMX_IMG_PXL_CLK 122 - -/* MIPI-CSI SS */ -#define IMX_CSI0_CORE_CLK 130 -#define IMX_CSI0_ESC_CLK 131 -#define IMX_CSI0_PWM0_CLK 132 -#define IMX_CSI0_I2C0_CLK 133 - -/* PARALLER CSI SS */ -#define IMX_PARALLEL_CSI_DPLL_CLK 140 -#define IMX_PARALLEL_CSI_PIXEL_CLK 141 -#define IMX_PARALLEL_CSI_MCLK_CLK 142 - -/* VPU SS */ -#define IMX_VPU_ENC_CLK 150 -#define IMX_VPU_DEC_CLK 151 - -/* GPU SS */ -#define IMX_GPU0_CORE_CLK 160 -#define IMX_GPU0_SHADER_CLK 161 - -/* ADMA SS */ -#define IMX_ADMA_IPG_CLK_ROOT 165 -#define IMX_ADMA_UART0_CLK 170 -#define IMX_ADMA_UART1_CLK 171 -#define IMX_ADMA_UART2_CLK 172 -#define IMX_ADMA_UART3_CLK 173 -#define IMX_ADMA_SPI0_CLK 174 -#define IMX_ADMA_SPI1_CLK 175 -#define IMX_ADMA_SPI2_CLK 176 -#define IMX_ADMA_SPI3_CLK 177 -#define IMX_ADMA_CAN0_CLK 178 -#define IMX_ADMA_CAN1_CLK 179 -#define IMX_ADMA_CAN2_CLK 180 -#define IMX_ADMA_I2C0_CLK 181 -#define IMX_ADMA_I2C1_CLK 182 -#define IMX_ADMA_I2C2_CLK 183 -#define IMX_ADMA_I2C3_CLK 184 -#define IMX_ADMA_FTM0_CLK 185 -#define IMX_ADMA_FTM1_CLK 186 -#define IMX_ADMA_ADC0_CLK 187 -#define IMX_ADMA_PWM_CLK 188 -#define IMX_ADMA_LCD_CLK 189 - -#define IMX_SCU_CLK_END 190 - /* LPCG clocks */ /* LSIO SS LPCG */ From 5392c5de096a1cad7cc06265a8cbf18de2da22c7 Mon Sep 17 00:00:00 2001 From: Dong Aisheng Date: Fri, 23 Apr 2021 11:33:32 +0800 Subject: [PATCH 073/161] clk: imx: scu: add gpr clocks support SCU clock protocol supports a few clocks based on GPR controller registers including mux/divider/gate. Add a generic clock register API to support them all. Signed-off-by: Dong Aisheng Reviewed-by: Abel Vesa Signed-off-by: Abel Vesa --- drivers/clk/imx/clk-scu.c | 186 ++++++++++++++++++++++++++++++++++++++ drivers/clk/imx/clk-scu.h | 29 ++++++ 2 files changed, 215 insertions(+) diff --git a/drivers/clk/imx/clk-scu.c b/drivers/clk/imx/clk-scu.c index f89b4da10e80..bd169083350c 100644 --- a/drivers/clk/imx/clk-scu.c +++ b/drivers/clk/imx/clk-scu.c @@ -52,6 +52,22 @@ struct clk_scu { u32 rate; }; +/* + * struct clk_gpr_scu - Description of one SCU GPR clock + * @hw: the common clk_hw + * @rsrc_id: resource ID of this SCU clock + * @gpr_id: GPR ID index to control the divider + */ +struct clk_gpr_scu { + struct clk_hw hw; + u16 rsrc_id; + u8 gpr_id; + u8 flags; + bool gate_invert; +}; + +#define to_clk_gpr_scu(_hw) container_of(_hw, struct clk_gpr_scu, hw) + /* * struct imx_sc_msg_req_set_clock_rate - clock set rate protocol * @hdr: SCU protocol header @@ -605,3 +621,173 @@ void imx_clk_scu_unregister(void) } } } + +static unsigned long clk_gpr_div_scu_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct clk_gpr_scu *clk = to_clk_gpr_scu(hw); + unsigned long rate = 0; + u32 val; + int err; + + err = imx_sc_misc_get_control(ccm_ipc_handle, clk->rsrc_id, + clk->gpr_id, &val); + + rate = val ? parent_rate / 2 : parent_rate; + + return err ? 0 : rate; +} + +static long clk_gpr_div_scu_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *prate) +{ + if (rate < *prate) + rate = *prate / 2; + else + rate = *prate; + + return rate; +} + +static int clk_gpr_div_scu_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct clk_gpr_scu *clk = to_clk_gpr_scu(hw); + uint32_t val; + int err; + + val = (rate < parent_rate) ? 1 : 0; + err = imx_sc_misc_set_control(ccm_ipc_handle, clk->rsrc_id, + clk->gpr_id, val); + + return err ? -EINVAL : 0; +} + +static const struct clk_ops clk_gpr_div_scu_ops = { + .recalc_rate = clk_gpr_div_scu_recalc_rate, + .round_rate = clk_gpr_div_scu_round_rate, + .set_rate = clk_gpr_div_scu_set_rate, +}; + +static u8 clk_gpr_mux_scu_get_parent(struct clk_hw *hw) +{ + struct clk_gpr_scu *clk = to_clk_gpr_scu(hw); + u32 val = 0; + + imx_sc_misc_get_control(ccm_ipc_handle, clk->rsrc_id, + clk->gpr_id, &val); + + return (u8)val; +} + +static int clk_gpr_mux_scu_set_parent(struct clk_hw *hw, u8 index) +{ + struct clk_gpr_scu *clk = to_clk_gpr_scu(hw); + + return imx_sc_misc_set_control(ccm_ipc_handle, clk->rsrc_id, + clk->gpr_id, index); +} + +static const struct clk_ops clk_gpr_mux_scu_ops = { + .get_parent = clk_gpr_mux_scu_get_parent, + .set_parent = clk_gpr_mux_scu_set_parent, +}; + +static int clk_gpr_gate_scu_prepare(struct clk_hw *hw) +{ + struct clk_gpr_scu *clk = to_clk_gpr_scu(hw); + + return imx_sc_misc_set_control(ccm_ipc_handle, clk->rsrc_id, + clk->gpr_id, !clk->gate_invert); +} + +static void clk_gpr_gate_scu_unprepare(struct clk_hw *hw) +{ + struct clk_gpr_scu *clk = to_clk_gpr_scu(hw); + int ret; + + ret = imx_sc_misc_set_control(ccm_ipc_handle, clk->rsrc_id, + clk->gpr_id, clk->gate_invert); + if (ret) + pr_err("%s: clk unprepare failed %d\n", clk_hw_get_name(hw), + ret); +} + +static int clk_gpr_gate_scu_is_prepared(struct clk_hw *hw) +{ + struct clk_gpr_scu *clk = to_clk_gpr_scu(hw); + int ret; + u32 val; + + ret = imx_sc_misc_get_control(ccm_ipc_handle, clk->rsrc_id, + clk->gpr_id, &val); + if (ret) + return ret; + + return clk->gate_invert ? !val : val; +} + +static const struct clk_ops clk_gpr_gate_scu_ops = { + .prepare = clk_gpr_gate_scu_prepare, + .unprepare = clk_gpr_gate_scu_unprepare, + .is_prepared = clk_gpr_gate_scu_is_prepared, +}; + +struct clk_hw *__imx_clk_gpr_scu(const char *name, const char * const *parent_name, + int num_parents, u32 rsrc_id, u8 gpr_id, u8 flags, + bool invert) +{ + struct imx_scu_clk_node *clk_node; + struct clk_gpr_scu *clk; + struct clk_hw *hw; + struct clk_init_data init; + int ret; + + if (rsrc_id >= IMX_SC_R_LAST || gpr_id >= IMX_SC_C_LAST) + return ERR_PTR(-EINVAL); + + clk_node = kzalloc(sizeof(*clk_node), GFP_KERNEL); + if (!clk_node) + return ERR_PTR(-ENOMEM); + + clk = kzalloc(sizeof(*clk), GFP_KERNEL); + if (!clk) { + kfree(clk_node); + return ERR_PTR(-ENOMEM); + } + + clk->rsrc_id = rsrc_id; + clk->gpr_id = gpr_id; + clk->flags = flags; + clk->gate_invert = invert; + + if (flags & IMX_SCU_GPR_CLK_GATE) + init.ops = &clk_gpr_gate_scu_ops; + + if (flags & IMX_SCU_GPR_CLK_DIV) + init.ops = &clk_gpr_div_scu_ops; + + if (flags & IMX_SCU_GPR_CLK_MUX) + init.ops = &clk_gpr_mux_scu_ops; + + init.flags = 0; + init.name = name; + init.parent_names = parent_name; + init.num_parents = num_parents; + + clk->hw.init = &init; + + hw = &clk->hw; + ret = clk_hw_register(NULL, hw); + if (ret) { + kfree(clk); + kfree(clk_node); + hw = ERR_PTR(ret); + } else { + clk_node->hw = hw; + clk_node->clk_type = gpr_id; + list_add_tail(&clk_node->node, &imx_scu_clks[rsrc_id]); + } + + return hw; +} diff --git a/drivers/clk/imx/clk-scu.h b/drivers/clk/imx/clk-scu.h index a6c6d3103e94..8ebee0cb0fe6 100644 --- a/drivers/clk/imx/clk-scu.h +++ b/drivers/clk/imx/clk-scu.h @@ -10,6 +10,10 @@ #include #include +#define IMX_SCU_GPR_CLK_GATE BIT(0) +#define IMX_SCU_GPR_CLK_DIV BIT(1) +#define IMX_SCU_GPR_CLK_MUX BIT(2) + extern struct list_head imx_scu_clks[]; extern const struct dev_pm_ops imx_clk_lpcg_scu_pm_ops; @@ -31,6 +35,10 @@ struct clk_hw *__imx_clk_lpcg_scu(struct device *dev, const char *name, void __iomem *reg, u8 bit_idx, bool hw_gate); void imx_clk_lpcg_scu_unregister(struct clk_hw *hw); +struct clk_hw *__imx_clk_gpr_scu(const char *name, const char * const *parent_name, + int num_parents, u32 rsrc_id, u8 gpr_id, u8 flags, + bool invert); + static inline struct clk_hw *imx_clk_scu(const char *name, u32 rsrc_id, u8 clk_type) { @@ -58,4 +66,25 @@ static inline struct clk_hw *imx_clk_lpcg_scu(const char *name, const char *pare return __imx_clk_lpcg_scu(NULL, name, parent_name, flags, reg, bit_idx, hw_gate); } + +static inline struct clk_hw *imx_clk_gate_gpr_scu(const char *name, const char *parent_name, + u32 rsrc_id, u8 gpr_id, bool invert) +{ + return __imx_clk_gpr_scu(name, &parent_name, 1, rsrc_id, gpr_id, + IMX_SCU_GPR_CLK_GATE, invert); +} + +static inline struct clk_hw *imx_clk_divider_gpr_scu(const char *name, const char *parent_name, + u32 rsrc_id, u8 gpr_id) +{ + return __imx_clk_gpr_scu(name, &parent_name, 1, rsrc_id, gpr_id, + IMX_SCU_GPR_CLK_DIV, 0); +} + +static inline struct clk_hw *imx_clk_mux_gpr_scu(const char *name, const char * const *parent_names, + int num_parents, u32 rsrc_id, u8 gpr_id) +{ + return __imx_clk_gpr_scu(name, parent_names, num_parents, rsrc_id, + gpr_id, IMX_SCU_GPR_CLK_MUX, 0); +} #endif From 5964012ce37e66d2588a9bc82f7184a008851cac Mon Sep 17 00:00:00 2001 From: Dong Aisheng Date: Fri, 23 Apr 2021 11:33:33 +0800 Subject: [PATCH 074/161] clk: imx8qxp: add clock valid checking mechnism clk-imx8qxp is a common SCU clock driver used by both QM and QXP platforms. The clock numbers vary a bit between those two platforms. This patch introduces a mechanism to only register the valid clocks for one platform by checking the clk resource id table. Signed-off-by: Dong Aisheng Reviewed-by: Abel Vesa Signed-off-by: Abel Vesa --- drivers/clk/imx/Makefile | 3 +- drivers/clk/imx/clk-imx8qxp-rsrc.c | 89 ++++++++++++++++++++++++++++++ drivers/clk/imx/clk-imx8qxp.c | 9 ++- drivers/clk/imx/clk-scu.c | 33 ++++++++++- drivers/clk/imx/clk-scu.h | 11 +++- 5 files changed, 137 insertions(+), 8 deletions(-) create mode 100644 drivers/clk/imx/clk-imx8qxp-rsrc.c diff --git a/drivers/clk/imx/Makefile b/drivers/clk/imx/Makefile index dd6a737d060b..2fdd2fff16c7 100644 --- a/drivers/clk/imx/Makefile +++ b/drivers/clk/imx/Makefile @@ -27,7 +27,8 @@ obj-$(CONFIG_CLK_IMX8MP) += clk-imx8mp.o obj-$(CONFIG_CLK_IMX8MQ) += clk-imx8mq.o obj-$(CONFIG_MXC_CLK_SCU) += clk-imx-scu.o clk-imx-lpcg-scu.o -clk-imx-scu-$(CONFIG_CLK_IMX8QXP) += clk-scu.o clk-imx8qxp.o +clk-imx-scu-$(CONFIG_CLK_IMX8QXP) += clk-scu.o clk-imx8qxp.o \ + clk-imx8qxp-rsrc.o clk-imx-lpcg-scu-$(CONFIG_CLK_IMX8QXP) += clk-lpcg-scu.o clk-imx8qxp-lpcg.o obj-$(CONFIG_CLK_IMX1) += clk-imx1.o diff --git a/drivers/clk/imx/clk-imx8qxp-rsrc.c b/drivers/clk/imx/clk-imx8qxp-rsrc.c new file mode 100644 index 000000000000..df09f2a7996d --- /dev/null +++ b/drivers/clk/imx/clk-imx8qxp-rsrc.c @@ -0,0 +1,89 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2019-2021 NXP + * Dong Aisheng + */ + +#include + +#include "clk-scu.h" + +/* Keep sorted in the ascending order */ +static const u32 imx8qxp_clk_scu_rsrc_table[] = { + IMX_SC_R_DC_0_VIDEO0, + IMX_SC_R_DC_0_VIDEO1, + IMX_SC_R_DC_0, + IMX_SC_R_DC_0_PLL_0, + IMX_SC_R_DC_0_PLL_1, + IMX_SC_R_SPI_0, + IMX_SC_R_SPI_1, + IMX_SC_R_SPI_2, + IMX_SC_R_SPI_3, + IMX_SC_R_UART_0, + IMX_SC_R_UART_1, + IMX_SC_R_UART_2, + IMX_SC_R_UART_3, + IMX_SC_R_I2C_0, + IMX_SC_R_I2C_1, + IMX_SC_R_I2C_2, + IMX_SC_R_I2C_3, + IMX_SC_R_ADC_0, + IMX_SC_R_FTM_0, + IMX_SC_R_FTM_1, + IMX_SC_R_CAN_0, + IMX_SC_R_GPU_0_PID0, + IMX_SC_R_LCD_0, + IMX_SC_R_LCD_0_PWM_0, + IMX_SC_R_PWM_0, + IMX_SC_R_PWM_1, + IMX_SC_R_PWM_2, + IMX_SC_R_PWM_3, + IMX_SC_R_PWM_4, + IMX_SC_R_PWM_5, + IMX_SC_R_PWM_6, + IMX_SC_R_PWM_7, + IMX_SC_R_GPT_0, + IMX_SC_R_GPT_1, + IMX_SC_R_GPT_2, + IMX_SC_R_GPT_3, + IMX_SC_R_GPT_4, + IMX_SC_R_FSPI_0, + IMX_SC_R_FSPI_1, + IMX_SC_R_SDHC_0, + IMX_SC_R_SDHC_1, + IMX_SC_R_SDHC_2, + IMX_SC_R_ENET_0, + IMX_SC_R_ENET_1, + IMX_SC_R_MLB_0, + IMX_SC_R_USB_2, + IMX_SC_R_NAND, + IMX_SC_R_LVDS_0, + IMX_SC_R_LVDS_1, + IMX_SC_R_M4_0_I2C, + IMX_SC_R_ELCDIF_PLL, + IMX_SC_R_AUDIO_PLL_0, + IMX_SC_R_PI_0, + IMX_SC_R_PI_0_PLL, + IMX_SC_R_MIPI_0, + IMX_SC_R_MIPI_0_PWM_0, + IMX_SC_R_MIPI_0_I2C_0, + IMX_SC_R_MIPI_0_I2C_1, + IMX_SC_R_MIPI_1, + IMX_SC_R_MIPI_1_PWM_0, + IMX_SC_R_MIPI_1_I2C_0, + IMX_SC_R_MIPI_1_I2C_1, + IMX_SC_R_CSI_0, + IMX_SC_R_CSI_0_PWM_0, + IMX_SC_R_CSI_0_I2C_0, + IMX_SC_R_AUDIO_PLL_1, + IMX_SC_R_AUDIO_CLK_0, + IMX_SC_R_AUDIO_CLK_1, + IMX_SC_R_A35, + IMX_SC_R_VPU_DEC_0, + IMX_SC_R_VPU_ENC_0, +}; + +const struct imx_clk_scu_rsrc_table imx_clk_scu_rsrc_imx8qxp = { + .rsrc = imx8qxp_clk_scu_rsrc_table, + .num = ARRAY_SIZE(imx8qxp_clk_scu_rsrc_table), +}; diff --git a/drivers/clk/imx/clk-imx8qxp.c b/drivers/clk/imx/clk-imx8qxp.c index d17b418ac577..9e35ae45b3a0 100644 --- a/drivers/clk/imx/clk-imx8qxp.c +++ b/drivers/clk/imx/clk-imx8qxp.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0+ /* - * Copyright 2018 NXP + * Copyright 2018-2021 NXP * Dong Aisheng */ @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -27,9 +28,11 @@ static const char *dc0_sels[] = { static int imx8qxp_clk_probe(struct platform_device *pdev) { struct device_node *ccm_node = pdev->dev.of_node; + const struct imx_clk_scu_rsrc_table *rsrc_table; int ret; - ret = imx_clk_scu_init(ccm_node); + rsrc_table = of_device_get_match_data(&pdev->dev); + ret = imx_clk_scu_init(ccm_node, rsrc_table); if (ret) return ret; @@ -130,7 +133,7 @@ static int imx8qxp_clk_probe(struct platform_device *pdev) static const struct of_device_id imx8qxp_match[] = { { .compatible = "fsl,scu-clk", }, - { .compatible = "fsl,imx8qxp-clk", }, + { .compatible = "fsl,imx8qxp-clk", &imx_clk_scu_rsrc_imx8qxp, }, { /* sentinel */ } }; diff --git a/drivers/clk/imx/clk-scu.c b/drivers/clk/imx/clk-scu.c index bd169083350c..f4efb3b76c86 100644 --- a/drivers/clk/imx/clk-scu.c +++ b/drivers/clk/imx/clk-scu.c @@ -1,11 +1,12 @@ // SPDX-License-Identifier: GPL-2.0+ /* - * Copyright 2018 NXP + * Copyright 2018-2021 NXP * Dong Aisheng */ #include #include +#include #include #include #include @@ -22,6 +23,7 @@ static struct imx_sc_ipc *ccm_ipc_handle; static struct device_node *pd_np; static struct platform_driver imx_clk_scu_driver; +static const struct imx_clk_scu_rsrc_table *rsrc_table; struct imx_scu_clk_node { const char *name; @@ -167,7 +169,26 @@ static inline struct clk_scu *to_clk_scu(struct clk_hw *hw) return container_of(hw, struct clk_scu, hw); } -int imx_clk_scu_init(struct device_node *np) +static inline int imx_scu_clk_search_cmp(const void *rsrc, const void *rsrc_p) +{ + return *(u32 *)rsrc - *(u32 *)rsrc_p; +} + +static bool imx_scu_clk_is_valid(u32 rsrc_id) +{ + void *p; + + if (!rsrc_table) + return true; + + p = bsearch(&rsrc_id, rsrc_table->rsrc, rsrc_table->num, + sizeof(rsrc_table->rsrc[0]), imx_scu_clk_search_cmp); + + return p != NULL; +} + +int imx_clk_scu_init(struct device_node *np, + const struct imx_clk_scu_rsrc_table *data) { u32 clk_cells; int ret, i; @@ -186,6 +207,8 @@ int imx_clk_scu_init(struct device_node *np) pd_np = of_find_compatible_node(NULL, NULL, "fsl,scu-pd"); if (!pd_np) return -EINVAL; + + rsrc_table = data; } return platform_driver_register(&imx_clk_scu_driver); @@ -583,6 +606,9 @@ struct clk_hw *imx_clk_scu_alloc_dev(const char *name, struct platform_device *pdev; int ret; + if (!imx_scu_clk_is_valid(rsrc_id)) + return ERR_PTR(-EINVAL); + pdev = platform_device_alloc(name, PLATFORM_DEVID_NONE); if (!pdev) { pr_err("%s: failed to allocate scu clk dev rsrc %d type %d\n", @@ -750,6 +776,9 @@ struct clk_hw *__imx_clk_gpr_scu(const char *name, const char * const *parent_na if (!clk_node) return ERR_PTR(-ENOMEM); + if (!imx_scu_clk_is_valid(rsrc_id)) + return ERR_PTR(-EINVAL); + clk = kzalloc(sizeof(*clk), GFP_KERNEL); if (!clk) { kfree(clk_node); diff --git a/drivers/clk/imx/clk-scu.h b/drivers/clk/imx/clk-scu.h index 8ebee0cb0fe6..bcacd8b1d1ab 100644 --- a/drivers/clk/imx/clk-scu.h +++ b/drivers/clk/imx/clk-scu.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0+ */ /* - * Copyright 2018 NXP + * Copyright 2018-2021 NXP * Dong Aisheng */ @@ -14,10 +14,17 @@ #define IMX_SCU_GPR_CLK_DIV BIT(1) #define IMX_SCU_GPR_CLK_MUX BIT(2) +struct imx_clk_scu_rsrc_table { + const u32 *rsrc; + u8 num; +}; + extern struct list_head imx_scu_clks[]; extern const struct dev_pm_ops imx_clk_lpcg_scu_pm_ops; +extern const struct imx_clk_scu_rsrc_table imx_clk_scu_rsrc_imx8qxp; -int imx_clk_scu_init(struct device_node *np); +int imx_clk_scu_init(struct device_node *np, + const struct imx_clk_scu_rsrc_table *data); struct clk_hw *imx_scu_of_clk_src_get(struct of_phandle_args *clkspec, void *data); struct clk_hw *imx_clk_scu_alloc_dev(const char *name, From afd0406b4663014ef1f5993454db89c8a0e8bb42 Mon Sep 17 00:00:00 2001 From: Dong Aisheng Date: Fri, 23 Apr 2021 11:33:34 +0800 Subject: [PATCH 075/161] clk: imx8qm: add clock valid resource checking Add imx8qm clock valid resource checking mechanism Signed-off-by: Dong Aisheng Reviewed-by: Abel Vesa Signed-off-by: Abel Vesa --- drivers/clk/imx/Makefile | 2 +- drivers/clk/imx/clk-imx8qm-rsrc.c | 116 ++++++++++++++++++++++++++++++ drivers/clk/imx/clk-imx8qxp.c | 1 + drivers/clk/imx/clk-scu.h | 1 + 4 files changed, 119 insertions(+), 1 deletion(-) create mode 100644 drivers/clk/imx/clk-imx8qm-rsrc.c diff --git a/drivers/clk/imx/Makefile b/drivers/clk/imx/Makefile index 2fdd2fff16c7..c24a2acbfa56 100644 --- a/drivers/clk/imx/Makefile +++ b/drivers/clk/imx/Makefile @@ -28,7 +28,7 @@ obj-$(CONFIG_CLK_IMX8MQ) += clk-imx8mq.o obj-$(CONFIG_MXC_CLK_SCU) += clk-imx-scu.o clk-imx-lpcg-scu.o clk-imx-scu-$(CONFIG_CLK_IMX8QXP) += clk-scu.o clk-imx8qxp.o \ - clk-imx8qxp-rsrc.o + clk-imx8qxp-rsrc.o clk-imx8qm-rsrc.o clk-imx-lpcg-scu-$(CONFIG_CLK_IMX8QXP) += clk-lpcg-scu.o clk-imx8qxp-lpcg.o obj-$(CONFIG_CLK_IMX1) += clk-imx1.o diff --git a/drivers/clk/imx/clk-imx8qm-rsrc.c b/drivers/clk/imx/clk-imx8qm-rsrc.c new file mode 100644 index 000000000000..87e0b6ac027e --- /dev/null +++ b/drivers/clk/imx/clk-imx8qm-rsrc.c @@ -0,0 +1,116 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2019-2021 NXP + * Dong Aisheng + */ + +#include + +#include "clk-scu.h" + +/* Keep sorted in the ascending order */ +static const u32 imx8qm_clk_scu_rsrc_table[] = { + IMX_SC_R_A53, + IMX_SC_R_A72, + IMX_SC_R_DC_0_VIDEO0, + IMX_SC_R_DC_0_VIDEO1, + IMX_SC_R_DC_0, + IMX_SC_R_DC_0_PLL_0, + IMX_SC_R_DC_0_PLL_1, + IMX_SC_R_DC_1_VIDEO0, + IMX_SC_R_DC_1_VIDEO1, + IMX_SC_R_DC_1, + IMX_SC_R_DC_1_PLL_0, + IMX_SC_R_DC_1_PLL_1, + IMX_SC_R_SPI_0, + IMX_SC_R_SPI_1, + IMX_SC_R_SPI_2, + IMX_SC_R_SPI_3, + IMX_SC_R_UART_0, + IMX_SC_R_UART_1, + IMX_SC_R_UART_2, + IMX_SC_R_UART_3, + IMX_SC_R_UART_4, + IMX_SC_R_EMVSIM_0, + IMX_SC_R_EMVSIM_1, + IMX_SC_R_I2C_0, + IMX_SC_R_I2C_1, + IMX_SC_R_I2C_2, + IMX_SC_R_I2C_3, + IMX_SC_R_I2C_4, + IMX_SC_R_ADC_0, + IMX_SC_R_ADC_1, + IMX_SC_R_FTM_0, + IMX_SC_R_FTM_1, + IMX_SC_R_CAN_0, + IMX_SC_R_GPU_0_PID0, + IMX_SC_R_GPU_1_PID0, + IMX_SC_R_PWM_0, + IMX_SC_R_PWM_1, + IMX_SC_R_PWM_2, + IMX_SC_R_PWM_3, + IMX_SC_R_PWM_4, + IMX_SC_R_PWM_5, + IMX_SC_R_PWM_6, + IMX_SC_R_PWM_7, + IMX_SC_R_GPT_0, + IMX_SC_R_GPT_1, + IMX_SC_R_GPT_2, + IMX_SC_R_GPT_3, + IMX_SC_R_GPT_4, + IMX_SC_R_FSPI_0, + IMX_SC_R_FSPI_1, + IMX_SC_R_SDHC_0, + IMX_SC_R_SDHC_1, + IMX_SC_R_SDHC_2, + IMX_SC_R_ENET_0, + IMX_SC_R_ENET_1, + IMX_SC_R_MLB_0, + IMX_SC_R_USB_2, + IMX_SC_R_NAND, + IMX_SC_R_LVDS_0, + IMX_SC_R_LVDS_0_PWM_0, + IMX_SC_R_LVDS_0_I2C_0, + IMX_SC_R_LVDS_0_I2C_1, + IMX_SC_R_LVDS_1, + IMX_SC_R_LVDS_1_PWM_0, + IMX_SC_R_LVDS_1_I2C_0, + IMX_SC_R_LVDS_1_I2C_1, + IMX_SC_R_M4_0_I2C, + IMX_SC_R_M4_1_I2C, + IMX_SC_R_AUDIO_PLL_0, + IMX_SC_R_VPU_UART, + IMX_SC_R_VPUCORE, + IMX_SC_R_MIPI_0, + IMX_SC_R_MIPI_0_PWM_0, + IMX_SC_R_MIPI_0_I2C_0, + IMX_SC_R_MIPI_0_I2C_1, + IMX_SC_R_MIPI_1, + IMX_SC_R_MIPI_1_PWM_0, + IMX_SC_R_MIPI_1_I2C_0, + IMX_SC_R_MIPI_1_I2C_1, + IMX_SC_R_CSI_0, + IMX_SC_R_CSI_0_PWM_0, + IMX_SC_R_CSI_0_I2C_0, + IMX_SC_R_CSI_1, + IMX_SC_R_CSI_1_PWM_0, + IMX_SC_R_CSI_1_I2C_0, + IMX_SC_R_HDMI, + IMX_SC_R_HDMI_I2S, + IMX_SC_R_HDMI_I2C_0, + IMX_SC_R_HDMI_PLL_0, + IMX_SC_R_HDMI_RX, + IMX_SC_R_HDMI_RX_BYPASS, + IMX_SC_R_HDMI_RX_I2C_0, + IMX_SC_R_AUDIO_PLL_1, + IMX_SC_R_AUDIO_CLK_0, + IMX_SC_R_AUDIO_CLK_1, + IMX_SC_R_HDMI_RX_PWM_0, + IMX_SC_R_HDMI_PLL_1, + IMX_SC_R_VPU, +}; + +const struct imx_clk_scu_rsrc_table imx_clk_scu_rsrc_imx8qm = { + .rsrc = imx8qm_clk_scu_rsrc_table, + .num = ARRAY_SIZE(imx8qm_clk_scu_rsrc_table), +}; diff --git a/drivers/clk/imx/clk-imx8qxp.c b/drivers/clk/imx/clk-imx8qxp.c index 9e35ae45b3a0..88cc737ee125 100644 --- a/drivers/clk/imx/clk-imx8qxp.c +++ b/drivers/clk/imx/clk-imx8qxp.c @@ -134,6 +134,7 @@ static int imx8qxp_clk_probe(struct platform_device *pdev) static const struct of_device_id imx8qxp_match[] = { { .compatible = "fsl,scu-clk", }, { .compatible = "fsl,imx8qxp-clk", &imx_clk_scu_rsrc_imx8qxp, }, + { .compatible = "fsl,imx8qm-clk", &imx_clk_scu_rsrc_imx8qm, }, { /* sentinel */ } }; diff --git a/drivers/clk/imx/clk-scu.h b/drivers/clk/imx/clk-scu.h index bcacd8b1d1ab..22156e93b85d 100644 --- a/drivers/clk/imx/clk-scu.h +++ b/drivers/clk/imx/clk-scu.h @@ -22,6 +22,7 @@ struct imx_clk_scu_rsrc_table { extern struct list_head imx_scu_clks[]; extern const struct dev_pm_ops imx_clk_lpcg_scu_pm_ops; extern const struct imx_clk_scu_rsrc_table imx_clk_scu_rsrc_imx8qxp; +extern const struct imx_clk_scu_rsrc_table imx_clk_scu_rsrc_imx8qm; int imx_clk_scu_init(struct device_node *np, const struct imx_clk_scu_rsrc_table *data); From 2924b0b0c1cde59edeeaf3b709ec7a8a7779e4b8 Mon Sep 17 00:00:00 2001 From: Dong Aisheng Date: Fri, 21 May 2021 11:12:47 +0800 Subject: [PATCH 076/161] clk: imx: scu: add enet rgmii gpr clocks enet tx clk actually is sourced from a gpr divider, not default enet clk. Add enet grp clocks for user to use correctly. Cc: Abel Vesa Cc: Stephen Boyd Cc: Shawn Guo Signed-off-by: Dong Aisheng Reviewed-by: Abel Vesa Signed-off-by: Abel Vesa --- drivers/clk/imx/clk-imx8qxp.c | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/drivers/clk/imx/clk-imx8qxp.c b/drivers/clk/imx/clk-imx8qxp.c index 88cc737ee125..827ffcde5bbc 100644 --- a/drivers/clk/imx/clk-imx8qxp.c +++ b/drivers/clk/imx/clk-imx8qxp.c @@ -25,6 +25,16 @@ static const char *dc0_sels[] = { "dc0_bypass0_clk", }; +static const char * const enet0_rgmii_txc_sels[] = { + "enet0_ref_div", + "clk_dummy", +}; + +static const char * const enet1_rgmii_txc_sels[] = { + "enet1_ref_div", + "clk_dummy", +}; + static int imx8qxp_clk_probe(struct platform_device *pdev) { struct device_node *ccm_node = pdev->dev.of_node; @@ -80,12 +90,16 @@ static int imx8qxp_clk_probe(struct platform_device *pdev) imx_clk_scu("sdhc0_clk", IMX_SC_R_SDHC_0, IMX_SC_PM_CLK_PER); imx_clk_scu("sdhc1_clk", IMX_SC_R_SDHC_1, IMX_SC_PM_CLK_PER); imx_clk_scu("sdhc2_clk", IMX_SC_R_SDHC_2, IMX_SC_PM_CLK_PER); - imx_clk_scu("enet0_clk", IMX_SC_R_ENET_0, IMX_SC_PM_CLK_PER); + imx_clk_scu("enet0_root_clk", IMX_SC_R_ENET_0, IMX_SC_PM_CLK_PER); + imx_clk_divider_gpr_scu("enet0_ref_div", "enet0_root_clk", IMX_SC_R_ENET_0, IMX_SC_C_CLKDIV); + imx_clk_mux_gpr_scu("enet0_rgmii_txc_sel", enet0_rgmii_txc_sels, ARRAY_SIZE(enet0_rgmii_txc_sels), IMX_SC_R_ENET_0, IMX_SC_C_TXCLK); imx_clk_scu("enet0_bypass_clk", IMX_SC_R_ENET_0, IMX_SC_PM_CLK_BYPASS); - imx_clk_scu("enet0_rgmii_clk", IMX_SC_R_ENET_0, IMX_SC_PM_CLK_MISC0); - imx_clk_scu("enet1_clk", IMX_SC_R_ENET_1, IMX_SC_PM_CLK_PER); + imx_clk_scu("enet0_rgmii_rx_clk", IMX_SC_R_ENET_0, IMX_SC_PM_CLK_MISC0); + imx_clk_scu("enet1_root_clk", IMX_SC_R_ENET_1, IMX_SC_PM_CLK_PER); + imx_clk_divider_gpr_scu("enet1_ref_div", "enet1_root_clk", IMX_SC_R_ENET_1, IMX_SC_C_CLKDIV); + imx_clk_mux_gpr_scu("enet1_rgmii_txc_sel", enet1_rgmii_txc_sels, ARRAY_SIZE(enet1_rgmii_txc_sels), IMX_SC_R_ENET_1, IMX_SC_C_TXCLK); imx_clk_scu("enet1_bypass_clk", IMX_SC_R_ENET_1, IMX_SC_PM_CLK_BYPASS); - imx_clk_scu("enet1_rgmii_clk", IMX_SC_R_ENET_1, IMX_SC_PM_CLK_MISC0); + imx_clk_scu("enet1_rgmii_rx_clk", IMX_SC_R_ENET_1, IMX_SC_PM_CLK_MISC0); imx_clk_scu("gpmi_io_clk", IMX_SC_R_NAND, IMX_SC_PM_CLK_MST_BUS); imx_clk_scu("gpmi_bch_clk", IMX_SC_R_NAND, IMX_SC_PM_CLK_PER); imx_clk_scu("usb3_aclk_div", IMX_SC_R_USB_2, IMX_SC_PM_CLK_PER); From babfaa9556d7a9df2784bfcddafdeba29d24c8fd Mon Sep 17 00:00:00 2001 From: Dong Aisheng Date: Fri, 4 Jun 2021 17:09:34 +0800 Subject: [PATCH 077/161] clk: imx: scu: add more scu clocks Add more scu clocks used by i.MX8 platforms. Signed-off-by: Dong Aisheng Reviewed-by: Abel Vesa Signed-off-by: Abel Vesa --- drivers/clk/imx/clk-imx8qxp.c | 152 +++++++++++++++++++++++++++++++++- 1 file changed, 150 insertions(+), 2 deletions(-) diff --git a/drivers/clk/imx/clk-imx8qxp.c b/drivers/clk/imx/clk-imx8qxp.c index 827ffcde5bbc..c53a688d8ccc 100644 --- a/drivers/clk/imx/clk-imx8qxp.c +++ b/drivers/clk/imx/clk-imx8qxp.c @@ -25,6 +25,14 @@ static const char *dc0_sels[] = { "dc0_bypass0_clk", }; +static const char * const dc1_sels[] = { + "clk_dummy", + "clk_dummy", + "dc1_pll0_clk", + "dc1_pll1_clk", + "dc1_bypass0_clk", +}; + static const char * const enet0_rgmii_txc_sels[] = { "enet0_ref_div", "clk_dummy", @@ -35,6 +43,54 @@ static const char * const enet1_rgmii_txc_sels[] = { "clk_dummy", }; +static const char * const hdmi_sels[] = { + "clk_dummy", + "hdmi_dig_pll_clk", + "clk_dummy", + "clk_dummy", + "hdmi_av_pll_clk", +}; + +static const char * const hdmi_rx_sels[] = { + "clk_dummy", + "hdmi_rx_dig_pll_clk", + "clk_dummy", + "clk_dummy", + "hdmi_rx_bypass_clk", +}; + +static const char * const lcd_pxl_sels[] = { + "clk_dummy", + "clk_dummy", + "clk_dummy", + "clk_dummy", + "lcd_pxl_bypass_div_clk", +}; + +static const char * const mipi_sels[] = { + "clk_dummy", + "clk_dummy", + "mipi_pll_div2_clk", + "clk_dummy", + "clk_dummy", +}; + +static const char * const lcd_sels[] = { + "clk_dummy", + "clk_dummy", + "clk_dummy", + "clk_dummy", + "elcdif_pll", +}; + +static const char * const pi_pll0_sels[] = { + "clk_dummy", + "pi_dpll_clk", + "clk_dummy", + "clk_dummy", + "clk_dummy", +}; + static int imx8qxp_clk_probe(struct platform_device *pdev) { struct device_node *ccm_node = pdev->dev.of_node; @@ -48,6 +104,8 @@ static int imx8qxp_clk_probe(struct platform_device *pdev) /* ARM core */ imx_clk_scu("a35_clk", IMX_SC_R_A35, IMX_SC_PM_CLK_CPU); + imx_clk_scu("a53_clk", IMX_SC_R_A53, IMX_SC_PM_CLK_CPU); + imx_clk_scu("a72_clk", IMX_SC_R_A72, IMX_SC_PM_CLK_CPU); /* LSIO SS */ imx_clk_scu("pwm0_clk", IMX_SC_R_PWM_0, IMX_SC_PM_CLK_PER); @@ -66,25 +124,42 @@ static int imx8qxp_clk_probe(struct platform_device *pdev) imx_clk_scu("fspi0_clk", IMX_SC_R_FSPI_0, IMX_SC_PM_CLK_PER); imx_clk_scu("fspi1_clk", IMX_SC_R_FSPI_1, IMX_SC_PM_CLK_PER); - /* ADMA SS */ + /* DMA SS */ imx_clk_scu("uart0_clk", IMX_SC_R_UART_0, IMX_SC_PM_CLK_PER); imx_clk_scu("uart1_clk", IMX_SC_R_UART_1, IMX_SC_PM_CLK_PER); imx_clk_scu("uart2_clk", IMX_SC_R_UART_2, IMX_SC_PM_CLK_PER); imx_clk_scu("uart3_clk", IMX_SC_R_UART_3, IMX_SC_PM_CLK_PER); + imx_clk_scu("uart4_clk", IMX_SC_R_UART_4, IMX_SC_PM_CLK_PER); + imx_clk_scu("sim0_clk", IMX_SC_R_EMVSIM_0, IMX_SC_PM_CLK_PER); imx_clk_scu("spi0_clk", IMX_SC_R_SPI_0, IMX_SC_PM_CLK_PER); imx_clk_scu("spi1_clk", IMX_SC_R_SPI_1, IMX_SC_PM_CLK_PER); imx_clk_scu("spi2_clk", IMX_SC_R_SPI_2, IMX_SC_PM_CLK_PER); imx_clk_scu("spi3_clk", IMX_SC_R_SPI_3, IMX_SC_PM_CLK_PER); imx_clk_scu("can0_clk", IMX_SC_R_CAN_0, IMX_SC_PM_CLK_PER); + imx_clk_scu("can1_clk", IMX_SC_R_CAN_1, IMX_SC_PM_CLK_PER); + imx_clk_scu("can2_clk", IMX_SC_R_CAN_2, IMX_SC_PM_CLK_PER); imx_clk_scu("i2c0_clk", IMX_SC_R_I2C_0, IMX_SC_PM_CLK_PER); imx_clk_scu("i2c1_clk", IMX_SC_R_I2C_1, IMX_SC_PM_CLK_PER); imx_clk_scu("i2c2_clk", IMX_SC_R_I2C_2, IMX_SC_PM_CLK_PER); imx_clk_scu("i2c3_clk", IMX_SC_R_I2C_3, IMX_SC_PM_CLK_PER); + imx_clk_scu("i2c4_clk", IMX_SC_R_I2C_4, IMX_SC_PM_CLK_PER); imx_clk_scu("ftm0_clk", IMX_SC_R_FTM_0, IMX_SC_PM_CLK_PER); imx_clk_scu("ftm1_clk", IMX_SC_R_FTM_1, IMX_SC_PM_CLK_PER); imx_clk_scu("adc0_clk", IMX_SC_R_ADC_0, IMX_SC_PM_CLK_PER); + imx_clk_scu("adc1_clk", IMX_SC_R_ADC_1, IMX_SC_PM_CLK_PER); imx_clk_scu("pwm_clk", IMX_SC_R_LCD_0_PWM_0, IMX_SC_PM_CLK_PER); - imx_clk_scu("lcd_clk", IMX_SC_R_LCD_0, IMX_SC_PM_CLK_PER); + imx_clk_scu2("lcd_clk", lcd_sels, ARRAY_SIZE(lcd_sels), IMX_SC_R_LCD_0, IMX_SC_PM_CLK_PER); + imx_clk_scu2("lcd_pxl_clk", lcd_pxl_sels, ARRAY_SIZE(lcd_pxl_sels), IMX_SC_R_LCD_0, IMX_SC_PM_CLK_MISC0); + imx_clk_scu("lcd_pxl_bypass_div_clk", IMX_SC_R_LCD_0, IMX_SC_PM_CLK_BYPASS); + imx_clk_scu("elcdif_pll", IMX_SC_R_ELCDIF_PLL, IMX_SC_PM_CLK_PLL); + + /* Audio SS */ + imx_clk_scu("audio_pll0_clk", IMX_SC_R_AUDIO_PLL_0, IMX_SC_PM_CLK_PLL); + imx_clk_scu("audio_pll1_clk", IMX_SC_R_AUDIO_PLL_1, IMX_SC_PM_CLK_PLL); + imx_clk_scu("audio_pll_div_clk0_clk", IMX_SC_R_AUDIO_PLL_0, IMX_SC_PM_CLK_MISC0); + imx_clk_scu("audio_pll_div_clk1_clk", IMX_SC_R_AUDIO_PLL_1, IMX_SC_PM_CLK_MISC0); + imx_clk_scu("audio_rec_clk0_clk", IMX_SC_R_AUDIO_PLL_0, IMX_SC_PM_CLK_MISC1); + imx_clk_scu("audio_rec_clk1_clk", IMX_SC_R_AUDIO_PLL_1, IMX_SC_PM_CLK_MISC1); /* Connectivity */ imx_clk_scu("sdhc0_clk", IMX_SC_R_SDHC_0, IMX_SC_PM_CLK_PER); @@ -94,11 +169,13 @@ static int imx8qxp_clk_probe(struct platform_device *pdev) imx_clk_divider_gpr_scu("enet0_ref_div", "enet0_root_clk", IMX_SC_R_ENET_0, IMX_SC_C_CLKDIV); imx_clk_mux_gpr_scu("enet0_rgmii_txc_sel", enet0_rgmii_txc_sels, ARRAY_SIZE(enet0_rgmii_txc_sels), IMX_SC_R_ENET_0, IMX_SC_C_TXCLK); imx_clk_scu("enet0_bypass_clk", IMX_SC_R_ENET_0, IMX_SC_PM_CLK_BYPASS); + imx_clk_gate_gpr_scu("enet0_ref_50_clk", "clk_dummy", IMX_SC_R_ENET_0, IMX_SC_C_DISABLE_50, true); imx_clk_scu("enet0_rgmii_rx_clk", IMX_SC_R_ENET_0, IMX_SC_PM_CLK_MISC0); imx_clk_scu("enet1_root_clk", IMX_SC_R_ENET_1, IMX_SC_PM_CLK_PER); imx_clk_divider_gpr_scu("enet1_ref_div", "enet1_root_clk", IMX_SC_R_ENET_1, IMX_SC_C_CLKDIV); imx_clk_mux_gpr_scu("enet1_rgmii_txc_sel", enet1_rgmii_txc_sels, ARRAY_SIZE(enet1_rgmii_txc_sels), IMX_SC_R_ENET_1, IMX_SC_C_TXCLK); imx_clk_scu("enet1_bypass_clk", IMX_SC_R_ENET_1, IMX_SC_PM_CLK_BYPASS); + imx_clk_gate_gpr_scu("enet1_ref_50_clk", "clk_dummy", IMX_SC_R_ENET_1, IMX_SC_C_DISABLE_50, true); imx_clk_scu("enet1_rgmii_rx_clk", IMX_SC_R_ENET_1, IMX_SC_PM_CLK_MISC0); imx_clk_scu("gpmi_io_clk", IMX_SC_R_NAND, IMX_SC_PM_CLK_MST_BUS); imx_clk_scu("gpmi_bch_clk", IMX_SC_R_NAND, IMX_SC_PM_CLK_PER); @@ -114,30 +191,101 @@ static int imx8qxp_clk_probe(struct platform_device *pdev) imx_clk_scu("dc0_bypass0_clk", IMX_SC_R_DC_0_VIDEO0, IMX_SC_PM_CLK_BYPASS); imx_clk_scu("dc0_bypass1_clk", IMX_SC_R_DC_0_VIDEO1, IMX_SC_PM_CLK_BYPASS); + imx_clk_scu2("dc1_disp0_clk", dc1_sels, ARRAY_SIZE(dc1_sels), IMX_SC_R_DC_1, IMX_SC_PM_CLK_MISC0); + imx_clk_scu2("dc1_disp1_clk", dc1_sels, ARRAY_SIZE(dc1_sels), IMX_SC_R_DC_1, IMX_SC_PM_CLK_MISC1); + imx_clk_scu("dc1_pll0_clk", IMX_SC_R_DC_1_PLL_0, IMX_SC_PM_CLK_PLL); + imx_clk_scu("dc1_pll1_clk", IMX_SC_R_DC_1_PLL_1, IMX_SC_PM_CLK_PLL); + imx_clk_scu("dc1_bypass0_clk", IMX_SC_R_DC_1_VIDEO0, IMX_SC_PM_CLK_BYPASS); + imx_clk_scu("dc1_bypass1_clk", IMX_SC_R_DC_1_VIDEO1, IMX_SC_PM_CLK_BYPASS); + /* MIPI-LVDS SS */ + imx_clk_scu("mipi0_bypass_clk", IMX_SC_R_MIPI_0, IMX_SC_PM_CLK_BYPASS); + imx_clk_scu("mipi0_pixel_clk", IMX_SC_R_MIPI_0, IMX_SC_PM_CLK_PER); imx_clk_scu("mipi0_lvds_pixel_clk", IMX_SC_R_LVDS_0, IMX_SC_PM_CLK_MISC2); imx_clk_scu("mipi0_lvds_bypass_clk", IMX_SC_R_LVDS_0, IMX_SC_PM_CLK_BYPASS); imx_clk_scu("mipi0_lvds_phy_clk", IMX_SC_R_LVDS_0, IMX_SC_PM_CLK_MISC3); + imx_clk_scu2("mipi0_dsi_tx_esc_clk", mipi_sels, ARRAY_SIZE(mipi_sels), IMX_SC_R_MIPI_0, IMX_SC_PM_CLK_MST_BUS); + imx_clk_scu2("mipi0_dsi_rx_esc_clk", mipi_sels, ARRAY_SIZE(mipi_sels), IMX_SC_R_MIPI_0, IMX_SC_PM_CLK_SLV_BUS); + imx_clk_scu2("mipi0_dsi_phy_clk", mipi_sels, ARRAY_SIZE(mipi_sels), IMX_SC_R_MIPI_0, IMX_SC_PM_CLK_PHY); imx_clk_scu("mipi0_i2c0_clk", IMX_SC_R_MIPI_0_I2C_0, IMX_SC_PM_CLK_MISC2); imx_clk_scu("mipi0_i2c1_clk", IMX_SC_R_MIPI_0_I2C_1, IMX_SC_PM_CLK_MISC2); imx_clk_scu("mipi0_pwm0_clk", IMX_SC_R_MIPI_0_PWM_0, IMX_SC_PM_CLK_PER); + + imx_clk_scu("mipi1_bypass_clk", IMX_SC_R_MIPI_1, IMX_SC_PM_CLK_BYPASS); + imx_clk_scu("mipi1_pixel_clk", IMX_SC_R_MIPI_1, IMX_SC_PM_CLK_PER); imx_clk_scu("mipi1_lvds_pixel_clk", IMX_SC_R_LVDS_1, IMX_SC_PM_CLK_MISC2); imx_clk_scu("mipi1_lvds_bypass_clk", IMX_SC_R_LVDS_1, IMX_SC_PM_CLK_BYPASS); imx_clk_scu("mipi1_lvds_phy_clk", IMX_SC_R_LVDS_1, IMX_SC_PM_CLK_MISC3); + + imx_clk_scu2("mipi1_dsi_tx_esc_clk", mipi_sels, ARRAY_SIZE(mipi_sels), IMX_SC_R_MIPI_1, IMX_SC_PM_CLK_MST_BUS); + imx_clk_scu2("mipi1_dsi_rx_esc_clk", mipi_sels, ARRAY_SIZE(mipi_sels), IMX_SC_R_MIPI_1, IMX_SC_PM_CLK_SLV_BUS); + imx_clk_scu2("mipi1_dsi_phy_clk", mipi_sels, ARRAY_SIZE(mipi_sels), IMX_SC_R_MIPI_1, IMX_SC_PM_CLK_PHY); imx_clk_scu("mipi1_i2c0_clk", IMX_SC_R_MIPI_1_I2C_0, IMX_SC_PM_CLK_MISC2); imx_clk_scu("mipi1_i2c1_clk", IMX_SC_R_MIPI_1_I2C_1, IMX_SC_PM_CLK_MISC2); imx_clk_scu("mipi1_pwm0_clk", IMX_SC_R_MIPI_1_PWM_0, IMX_SC_PM_CLK_PER); + imx_clk_scu("lvds0_i2c0_clk", IMX_SC_R_LVDS_0_I2C_0, IMX_SC_PM_CLK_PER); + imx_clk_scu("lvds0_i2c1_clk", IMX_SC_R_LVDS_0_I2C_1, IMX_SC_PM_CLK_PER); + imx_clk_scu("lvds0_pwm0_clk", IMX_SC_R_LVDS_0_PWM_0, IMX_SC_PM_CLK_PER); + + imx_clk_scu("lvds1_i2c0_clk", IMX_SC_R_LVDS_1_I2C_0, IMX_SC_PM_CLK_PER); + imx_clk_scu("lvds1_i2c1_clk", IMX_SC_R_LVDS_1_I2C_1, IMX_SC_PM_CLK_PER); + imx_clk_scu("lvds1_pwm0_clk", IMX_SC_R_LVDS_1_PWM_0, IMX_SC_PM_CLK_PER); + /* MIPI CSI SS */ imx_clk_scu("mipi_csi0_core_clk", IMX_SC_R_CSI_0, IMX_SC_PM_CLK_PER); imx_clk_scu("mipi_csi0_esc_clk", IMX_SC_R_CSI_0, IMX_SC_PM_CLK_MISC); imx_clk_scu("mipi_csi0_i2c0_clk", IMX_SC_R_CSI_0_I2C_0, IMX_SC_PM_CLK_PER); imx_clk_scu("mipi_csi0_pwm0_clk", IMX_SC_R_CSI_0_PWM_0, IMX_SC_PM_CLK_PER); + imx_clk_scu("mipi_csi1_core_clk", IMX_SC_R_CSI_1, IMX_SC_PM_CLK_PER); + imx_clk_scu("mipi_csi1_esc_clk", IMX_SC_R_CSI_1, IMX_SC_PM_CLK_MISC); + imx_clk_scu("mipi_csi1_i2c0_clk", IMX_SC_R_CSI_1_I2C_0, IMX_SC_PM_CLK_PER); + imx_clk_scu("mipi_csi1_pwm0_clk", IMX_SC_R_CSI_1_PWM_0, IMX_SC_PM_CLK_PER); + + /* Parallel Interface SS */ + imx_clk_scu("pi_dpll_clk", IMX_SC_R_PI_0_PLL, IMX_SC_PM_CLK_PLL); + imx_clk_scu2("pi_per_div_clk", pi_pll0_sels, ARRAY_SIZE(pi_pll0_sels), IMX_SC_R_PI_0, IMX_SC_PM_CLK_PER); + imx_clk_scu("pi_mclk_div_clk", IMX_SC_R_PI_0, IMX_SC_PM_CLK_MISC0); + imx_clk_scu("pi_i2c0_div_clk", IMX_SC_R_PI_0_I2C_0, IMX_SC_PM_CLK_PER); /* GPU SS */ imx_clk_scu("gpu_core0_clk", IMX_SC_R_GPU_0_PID0, IMX_SC_PM_CLK_PER); imx_clk_scu("gpu_shader0_clk", IMX_SC_R_GPU_0_PID0, IMX_SC_PM_CLK_MISC); + imx_clk_scu("gpu_core1_clk", IMX_SC_R_GPU_1_PID0, IMX_SC_PM_CLK_PER); + imx_clk_scu("gpu_shader1_clk", IMX_SC_R_GPU_1_PID0, IMX_SC_PM_CLK_MISC); + + /* CM40 SS */ + imx_clk_scu("cm40_i2c_div", IMX_SC_R_M4_0_I2C, IMX_SC_PM_CLK_PER); + imx_clk_scu("cm40_lpuart_div", IMX_SC_R_M4_0_UART, IMX_SC_PM_CLK_PER); + + /* CM41 SS */ + imx_clk_scu("cm41_i2c_div", IMX_SC_R_M4_1_I2C, IMX_SC_PM_CLK_PER); + + /* HDMI TX SS */ + imx_clk_scu("hdmi_dig_pll_clk", IMX_SC_R_HDMI_PLL_0, IMX_SC_PM_CLK_PLL); + imx_clk_scu("hdmi_av_pll_clk", IMX_SC_R_HDMI_PLL_1, IMX_SC_PM_CLK_PLL); + imx_clk_scu2("hdmi_pixel_mux_clk", hdmi_sels, ARRAY_SIZE(hdmi_sels), IMX_SC_R_HDMI, IMX_SC_PM_CLK_MISC0); + imx_clk_scu2("hdmi_pixel_link_clk", hdmi_sels, ARRAY_SIZE(hdmi_sels), IMX_SC_R_HDMI, IMX_SC_PM_CLK_MISC1); + imx_clk_scu("hdmi_ipg_clk", IMX_SC_R_HDMI, IMX_SC_PM_CLK_MISC4); + imx_clk_scu("hdmi_i2c0_clk", IMX_SC_R_HDMI_I2C_0, IMX_SC_PM_CLK_MISC2); + imx_clk_scu("hdmi_hdp_core_clk", IMX_SC_R_HDMI, IMX_SC_PM_CLK_MISC2); + imx_clk_scu2("hdmi_pxl_clk", hdmi_sels, ARRAY_SIZE(hdmi_sels), IMX_SC_R_HDMI, IMX_SC_PM_CLK_MISC3); + imx_clk_scu("hdmi_i2s_bypass_clk", IMX_SC_R_HDMI_I2S, IMX_SC_PM_CLK_BYPASS); + imx_clk_scu("hdmi_i2s_clk", IMX_SC_R_HDMI_I2S, IMX_SC_PM_CLK_MISC0); + + /* HDMI RX SS */ + imx_clk_scu("hdmi_rx_i2s_bypass_clk", IMX_SC_R_HDMI_RX_BYPASS, IMX_SC_PM_CLK_MISC0); + imx_clk_scu("hdmi_rx_spdif_bypass_clk", IMX_SC_R_HDMI_RX_BYPASS, IMX_SC_PM_CLK_MISC1); + imx_clk_scu("hdmi_rx_bypass_clk", IMX_SC_R_HDMI_RX_BYPASS, IMX_SC_PM_CLK_MISC2); + imx_clk_scu("hdmi_rx_i2c0_clk", IMX_SC_R_HDMI_RX_I2C_0, IMX_SC_PM_CLK_MISC2); + imx_clk_scu("hdmi_rx_pwm_clk", IMX_SC_R_HDMI_RX_PWM_0, IMX_SC_PM_CLK_MISC2); + imx_clk_scu("hdmi_rx_spdif_clk", IMX_SC_R_HDMI_RX, IMX_SC_PM_CLK_MISC0); + imx_clk_scu2("hdmi_rx_hd_ref_clk", hdmi_rx_sels, ARRAY_SIZE(hdmi_rx_sels), IMX_SC_R_HDMI_RX, IMX_SC_PM_CLK_MISC1); + imx_clk_scu2("hdmi_rx_hd_core_clk", hdmi_rx_sels, ARRAY_SIZE(hdmi_rx_sels), IMX_SC_R_HDMI_RX, IMX_SC_PM_CLK_MISC2); + imx_clk_scu2("hdmi_rx_pxl_clk", hdmi_rx_sels, ARRAY_SIZE(hdmi_rx_sels), IMX_SC_R_HDMI_RX, IMX_SC_PM_CLK_MISC3); + imx_clk_scu("hdmi_rx_i2s_clk", IMX_SC_R_HDMI_RX, IMX_SC_PM_CLK_MISC4); + ret = of_clk_add_hw_provider(ccm_node, imx_scu_of_clk_src_get, imx_scu_clks); if (ret) imx_clk_scu_unregister(); From b192d04011ee7dadfa3045beae4a2ef7dd71d027 Mon Sep 17 00:00:00 2001 From: "Guoniu.zhou" Date: Fri, 4 Jun 2021 17:09:35 +0800 Subject: [PATCH 078/161] clk: imx: scu: add parallel port clock ops Because digital pll for parallel interface is on by default, and not provide enable/disable function by scu, so add the related ops for this kind of clocks. Signed-off-by: Guoniu.zhou Signed-off-by: Dong Aisheng Reviewed-by: Abel Vesa Signed-off-by: Abel Vesa --- drivers/clk/imx/clk-scu.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/clk/imx/clk-scu.c b/drivers/clk/imx/clk-scu.c index f4efb3b76c86..680b2650fd45 100644 --- a/drivers/clk/imx/clk-scu.c +++ b/drivers/clk/imx/clk-scu.c @@ -425,6 +425,12 @@ static const struct clk_ops clk_scu_cpu_ops = { .unprepare = clk_scu_unprepare, }; +static const struct clk_ops clk_scu_pi_ops = { + .recalc_rate = clk_scu_recalc_rate, + .round_rate = clk_scu_round_rate, + .set_rate = clk_scu_set_rate, +}; + struct clk_hw *__imx_clk_scu(struct device *dev, const char *name, const char * const *parents, int num_parents, u32 rsrc_id, u8 clk_type) @@ -445,6 +451,8 @@ struct clk_hw *__imx_clk_scu(struct device *dev, const char *name, init.ops = &clk_scu_ops; if (rsrc_id == IMX_SC_R_A35) init.ops = &clk_scu_cpu_ops; + else if (rsrc_id == IMX_SC_R_PI_0_PLL) + init.ops = &clk_scu_pi_ops; else init.ops = &clk_scu_ops; init.parent_names = parents; From aecf425fa948e0ea9d0f7d86317b2c509108daae Mon Sep 17 00:00:00 2001 From: Dong Aisheng Date: Fri, 4 Jun 2021 17:09:36 +0800 Subject: [PATCH 079/161] clk: imx: scu: bypass cpu clock save and restore CPU clock is managed by ATF. No need save and restore. Signed-off-by: Dong Aisheng Reviewed-by: Abel Vesa Signed-off-by: Abel Vesa --- drivers/clk/imx/clk-scu.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/clk/imx/clk-scu.c b/drivers/clk/imx/clk-scu.c index 680b2650fd45..d87a1a1b297e 100644 --- a/drivers/clk/imx/clk-scu.c +++ b/drivers/clk/imx/clk-scu.c @@ -538,6 +538,11 @@ static int imx_clk_scu_probe(struct platform_device *pdev) static int __maybe_unused imx_clk_scu_suspend(struct device *dev) { struct clk_scu *clk = dev_get_drvdata(dev); + u32 rsrc_id = clk->rsrc_id; + + if ((rsrc_id == IMX_SC_R_A35) || (rsrc_id == IMX_SC_R_A53) || + (rsrc_id == IMX_SC_R_A72)) + return 0; clk->rate = clk_hw_get_rate(&clk->hw); clk->is_enabled = clk_hw_is_enabled(&clk->hw); @@ -554,8 +559,13 @@ static int __maybe_unused imx_clk_scu_suspend(struct device *dev) static int __maybe_unused imx_clk_scu_resume(struct device *dev) { struct clk_scu *clk = dev_get_drvdata(dev); + u32 rsrc_id = clk->rsrc_id; int ret = 0; + if ((rsrc_id == IMX_SC_R_A35) || (rsrc_id == IMX_SC_R_A53) || + (rsrc_id == IMX_SC_R_A72)) + return 0; + if (clk->rate) { ret = clk_scu_set_rate(&clk->hw, clk->rate, 0); dev_dbg(dev, "restore rate %d %s\n", clk->rate, From 6618b5aa655a793a5ad3b988cb4e2ff80777f06e Mon Sep 17 00:00:00 2001 From: Dong Aisheng Date: Fri, 4 Jun 2021 17:09:37 +0800 Subject: [PATCH 080/161] clk: imx: scu: detach pd if can't power up detach pd if can't power up as it may be allocated to a differet partition. Signed-off-by: Dong Aisheng Reviewed-by: Abel Vesa Signed-off-by: Abel Vesa --- drivers/clk/imx/clk-scu.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/clk/imx/clk-scu.c b/drivers/clk/imx/clk-scu.c index d87a1a1b297e..95fcac7f73b6 100644 --- a/drivers/clk/imx/clk-scu.c +++ b/drivers/clk/imx/clk-scu.c @@ -512,6 +512,7 @@ static int imx_clk_scu_probe(struct platform_device *pdev) ret = pm_runtime_get_sync(dev); if (ret) { + pm_genpd_remove_device(dev); pm_runtime_disable(dev); return ret; } From a61cea83daafc60618be3ac89dc6c5e2d1367697 Mon Sep 17 00:00:00 2001 From: Dong Aisheng Date: Fri, 4 Jun 2021 17:09:38 +0800 Subject: [PATCH 081/161] clk: imx: scu: bypass pi_pll enable status restore PI PLL does not support enable/disable. So bypass it's enable status restore. Signed-off-by: Dong Aisheng Reviewed-by: Abel Vesa Signed-off-by: Abel Vesa --- drivers/clk/imx/clk-scu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/imx/clk-scu.c b/drivers/clk/imx/clk-scu.c index 95fcac7f73b6..2537e68ded16 100644 --- a/drivers/clk/imx/clk-scu.c +++ b/drivers/clk/imx/clk-scu.c @@ -573,7 +573,7 @@ static int __maybe_unused imx_clk_scu_resume(struct device *dev) !ret ? "success" : "failed"); } - if (clk->is_enabled) { + if (clk->is_enabled && rsrc_id != IMX_SC_R_PI_0_PLL) { ret = clk_scu_prepare(&clk->hw); dev_dbg(dev, "restore enabled state %s\n", !ret ? "success" : "failed"); From cd8bd2f3ca64cac701084a5b3fc21e721bb15278 Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Fri, 4 Jun 2021 17:09:39 +0800 Subject: [PATCH 082/161] clk: imx: scu: Add A53 frequency scaling support Add i.MX8QM cpufreq support for A53 cluster. Signed-off-by: Anson Huang Signed-off-by: Dong Aisheng Reviewed-by: Abel Vesa Signed-off-by: Abel Vesa --- drivers/clk/imx/clk-scu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/clk/imx/clk-scu.c b/drivers/clk/imx/clk-scu.c index 2537e68ded16..8b3eb58e6d12 100644 --- a/drivers/clk/imx/clk-scu.c +++ b/drivers/clk/imx/clk-scu.c @@ -273,7 +273,7 @@ static int clk_scu_atf_set_cpu_rate(struct clk_hw *hw, unsigned long rate, struct arm_smccc_res res; unsigned long cluster_id; - if (clk->rsrc_id == IMX_SC_R_A35) + if (clk->rsrc_id == IMX_SC_R_A35 || clk->rsrc_id == IMX_SC_R_A53) cluster_id = 0; else return -EINVAL; @@ -449,7 +449,7 @@ struct clk_hw *__imx_clk_scu(struct device *dev, const char *name, init.name = name; init.ops = &clk_scu_ops; - if (rsrc_id == IMX_SC_R_A35) + if (rsrc_id == IMX_SC_R_A35 || rsrc_id == IMX_SC_R_A53) init.ops = &clk_scu_cpu_ops; else if (rsrc_id == IMX_SC_R_PI_0_PLL) init.ops = &clk_scu_pi_ops; From a43f6e8ae429f5ca594ae4463cc31c2a8ad4339c Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Fri, 4 Jun 2021 17:09:40 +0800 Subject: [PATCH 083/161] clk: imx: scu: Add A72 frequency scaling support Add A72 clock to support cpufreq on A72 cluster. Signed-off-by: Anson Huang Signed-off-by: Dong Aisheng Reviewed-by: Abel Vesa Signed-off-by: Abel Vesa --- drivers/clk/imx/clk-scu.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/clk/imx/clk-scu.c b/drivers/clk/imx/clk-scu.c index 8b3eb58e6d12..9f7ad3ca1039 100644 --- a/drivers/clk/imx/clk-scu.c +++ b/drivers/clk/imx/clk-scu.c @@ -275,6 +275,8 @@ static int clk_scu_atf_set_cpu_rate(struct clk_hw *hw, unsigned long rate, if (clk->rsrc_id == IMX_SC_R_A35 || clk->rsrc_id == IMX_SC_R_A53) cluster_id = 0; + else if (clk->rsrc_id == IMX_SC_R_A72) + cluster_id = 1; else return -EINVAL; @@ -449,7 +451,7 @@ struct clk_hw *__imx_clk_scu(struct device *dev, const char *name, init.name = name; init.ops = &clk_scu_ops; - if (rsrc_id == IMX_SC_R_A35 || rsrc_id == IMX_SC_R_A53) + if (rsrc_id == IMX_SC_R_A35 || rsrc_id == IMX_SC_R_A53 || rsrc_id == IMX_SC_R_A72) init.ops = &clk_scu_cpu_ops; else if (rsrc_id == IMX_SC_R_PI_0_PLL) init.ops = &clk_scu_pi_ops; From 7487986c9a010410b7e7af13072a5c04ea804eda Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Fri, 4 Jun 2021 17:09:41 +0800 Subject: [PATCH 084/161] clk: imx: scu: Only save DC SS clock using non-cached clock rate Display sub-system has special clock settings in SCFW, the bypassed clock is used instead of PLL in Linux kernel clock tree, so when saving clock rate, need to save non-cached clock rate for Display sub-system's bypass clocks, and other clocks still use the cached clock rate which is with runtime PM ON. Signed-off-by: Anson Huang Signed-off-by: Dong Aisheng Reviewed-by: Abel Vesa Signed-off-by: Abel Vesa --- drivers/clk/imx/clk-scu.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/clk/imx/clk-scu.c b/drivers/clk/imx/clk-scu.c index 9f7ad3ca1039..37919ffc46a2 100644 --- a/drivers/clk/imx/clk-scu.c +++ b/drivers/clk/imx/clk-scu.c @@ -547,7 +547,14 @@ static int __maybe_unused imx_clk_scu_suspend(struct device *dev) (rsrc_id == IMX_SC_R_A72)) return 0; - clk->rate = clk_hw_get_rate(&clk->hw); + /* DC SS needs to handle bypass clock using non-cached clock rate */ + if (clk->rsrc_id == IMX_SC_R_DC_0_VIDEO0 || + clk->rsrc_id == IMX_SC_R_DC_0_VIDEO1 || + clk->rsrc_id == IMX_SC_R_DC_1_VIDEO0 || + clk->rsrc_id == IMX_SC_R_DC_1_VIDEO1) + clk->rate = clk_scu_recalc_rate(&clk->hw, 0); + else + clk->rate = clk_hw_get_rate(&clk->hw); clk->is_enabled = clk_hw_is_enabled(&clk->hw); if (clk->rate) From a82327cc5edb2283efe6a63bde7516e67d02f2a2 Mon Sep 17 00:00:00 2001 From: Dong Aisheng Date: Fri, 4 Jun 2021 17:09:42 +0800 Subject: [PATCH 085/161] clk: imx: scu: add parent save and restore Add clock parent save and restore. Signed-off-by: Dong Aisheng Reviewed-by: Abel Vesa Signed-off-by: Abel Vesa --- drivers/clk/imx/clk-scu.c | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/drivers/clk/imx/clk-scu.c b/drivers/clk/imx/clk-scu.c index 37919ffc46a2..597cd2754370 100644 --- a/drivers/clk/imx/clk-scu.c +++ b/drivers/clk/imx/clk-scu.c @@ -50,6 +50,8 @@ struct clk_scu { u8 clk_type; /* for state save&restore */ + struct clk_hw *parent; + u8 parent_index; bool is_enabled; u32 rate; }; @@ -337,6 +339,8 @@ static u8 clk_scu_get_parent(struct clk_hw *hw) return 0; } + clk->parent_index = msg.data.resp.parent; + return msg.data.resp.parent; } @@ -345,6 +349,7 @@ static int clk_scu_set_parent(struct clk_hw *hw, u8 index) struct clk_scu *clk = to_clk_scu(hw); struct imx_sc_msg_set_clock_parent msg; struct imx_sc_rpc_msg *hdr = &msg.hdr; + int ret; hdr->ver = IMX_SC_RPC_VERSION; hdr->svc = IMX_SC_RPC_SVC_PM; @@ -355,7 +360,16 @@ static int clk_scu_set_parent(struct clk_hw *hw, u8 index) msg.clk = clk->clk_type; msg.parent = index; - return imx_scu_call_rpc(ccm_ipc_handle, &msg, true); + ret = imx_scu_call_rpc(ccm_ipc_handle, &msg, true); + if (ret) { + pr_err("%s: failed to set clock parent %d\n", + clk_hw_get_name(hw), ret); + return ret; + } + + clk->parent_index = index; + + return 0; } static int sc_pm_clock_enable(struct imx_sc_ipc *ipc, u16 resource, @@ -547,6 +561,8 @@ static int __maybe_unused imx_clk_scu_suspend(struct device *dev) (rsrc_id == IMX_SC_R_A72)) return 0; + clk->parent = clk_hw_get_parent(&clk->hw); + /* DC SS needs to handle bypass clock using non-cached clock rate */ if (clk->rsrc_id == IMX_SC_R_DC_0_VIDEO0 || clk->rsrc_id == IMX_SC_R_DC_0_VIDEO1 || @@ -557,6 +573,10 @@ static int __maybe_unused imx_clk_scu_suspend(struct device *dev) clk->rate = clk_hw_get_rate(&clk->hw); clk->is_enabled = clk_hw_is_enabled(&clk->hw); + if (clk->parent) + dev_dbg(dev, "save parent %s idx %u\n", clk_hw_get_name(clk->parent), + clk->parent_index); + if (clk->rate) dev_dbg(dev, "save rate %d\n", clk->rate); @@ -576,6 +596,13 @@ static int __maybe_unused imx_clk_scu_resume(struct device *dev) (rsrc_id == IMX_SC_R_A72)) return 0; + if (clk->parent) { + ret = clk_scu_set_parent(&clk->hw, clk->parent_index); + dev_dbg(dev, "restore parent %s idx %u %s\n", + clk_hw_get_name(clk->parent), + clk->parent_index, !ret ? "success" : "failed"); + } + if (clk->rate) { ret = clk_scu_set_rate(&clk->hw, clk->rate, 0); dev_dbg(dev, "restore rate %d %s\n", clk->rate, From 18a50f82cd2ff3e43589d44349e71fdbef0d3fdd Mon Sep 17 00:00:00 2001 From: Nitin Garg Date: Fri, 4 Jun 2021 17:09:43 +0800 Subject: [PATCH 086/161] clk: imx: scu: Do not enable runtime PM for CPU clks Since CPU clocks are managed by CPUFREQ and ATF, do not enable runtime PM otherwise rpm gets out of status as cpufreq also manages clock states. Signed-off-by: Nitin Garg Signed-off-by: Dong Aisheng Reviewed-by: Abel Vesa Signed-off-by: Abel Vesa --- drivers/clk/imx/clk-scu.c | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/drivers/clk/imx/clk-scu.c b/drivers/clk/imx/clk-scu.c index 597cd2754370..083da31dc3ea 100644 --- a/drivers/clk/imx/clk-scu.c +++ b/drivers/clk/imx/clk-scu.c @@ -521,16 +521,19 @@ static int imx_clk_scu_probe(struct platform_device *pdev) struct clk_hw *hw; int ret; - pm_runtime_set_suspended(dev); - pm_runtime_set_autosuspend_delay(dev, 50); - pm_runtime_use_autosuspend(&pdev->dev); - pm_runtime_enable(dev); + if (!((clk->rsrc == IMX_SC_R_A35) || (clk->rsrc == IMX_SC_R_A53) || + (clk->rsrc == IMX_SC_R_A72))) { + pm_runtime_set_suspended(dev); + pm_runtime_set_autosuspend_delay(dev, 50); + pm_runtime_use_autosuspend(&pdev->dev); + pm_runtime_enable(dev); - ret = pm_runtime_get_sync(dev); - if (ret) { - pm_genpd_remove_device(dev); - pm_runtime_disable(dev); - return ret; + ret = pm_runtime_get_sync(dev); + if (ret) { + pm_genpd_remove_device(dev); + pm_runtime_disable(dev); + return ret; + } } hw = __imx_clk_scu(dev, clk->name, clk->parents, clk->num_parents, @@ -543,8 +546,11 @@ static int imx_clk_scu_probe(struct platform_device *pdev) clk->hw = hw; list_add_tail(&clk->node, &imx_scu_clks[clk->rsrc]); - pm_runtime_mark_last_busy(&pdev->dev); - pm_runtime_put_autosuspend(&pdev->dev); + if (!((clk->rsrc == IMX_SC_R_A35) || (clk->rsrc == IMX_SC_R_A53) || + (clk->rsrc == IMX_SC_R_A72))) { + pm_runtime_mark_last_busy(&pdev->dev); + pm_runtime_put_autosuspend(&pdev->dev); + } dev_dbg(dev, "register SCU clock rsrc:%d type:%d\n", clk->rsrc, clk->clk_type); From c586f53ae159c6c1390f093a1ec94baef2df9f3a Mon Sep 17 00:00:00 2001 From: Lucas Stach Date: Fri, 28 May 2021 20:01:35 +0200 Subject: [PATCH 087/161] clk: imx8mq: remove SYS PLL 1/2 clock gates Remove the PLL clock gates as the allowing to gate the sys1_pll_266m breaks the uSDHC module which is sporadically unable to enumerate devices after this change. Also it makes AMP clock management harder with no obvious benefit to Linux, so just revert the change. Link: https://lore.kernel.org/r/20210528180135.1640876-1-l.stach@pengutronix.de Fixes: b04383b6a558 ("clk: imx8mq: Define gates for pll1/2 fixed dividers") Signed-off-by: Lucas Stach Reviewed-by: Abel Vesa Signed-off-by: Abel Vesa --- drivers/clk/imx/clk-imx8mq.c | 56 ++++++++---------------- include/dt-bindings/clock/imx8mq-clock.h | 19 -------- 2 files changed, 18 insertions(+), 57 deletions(-) diff --git a/drivers/clk/imx/clk-imx8mq.c b/drivers/clk/imx/clk-imx8mq.c index b08019e1faf9..c491bc9c61ce 100644 --- a/drivers/clk/imx/clk-imx8mq.c +++ b/drivers/clk/imx/clk-imx8mq.c @@ -358,46 +358,26 @@ static int imx8mq_clocks_probe(struct platform_device *pdev) hws[IMX8MQ_VIDEO2_PLL_OUT] = imx_clk_hw_sscg_pll("video2_pll_out", video2_pll_out_sels, ARRAY_SIZE(video2_pll_out_sels), 0, 0, 0, base + 0x54, 0); /* SYS PLL1 fixed output */ - hws[IMX8MQ_SYS1_PLL_40M_CG] = imx_clk_hw_gate("sys1_pll_40m_cg", "sys1_pll_out", base + 0x30, 9); - hws[IMX8MQ_SYS1_PLL_80M_CG] = imx_clk_hw_gate("sys1_pll_80m_cg", "sys1_pll_out", base + 0x30, 11); - hws[IMX8MQ_SYS1_PLL_100M_CG] = imx_clk_hw_gate("sys1_pll_100m_cg", "sys1_pll_out", base + 0x30, 13); - hws[IMX8MQ_SYS1_PLL_133M_CG] = imx_clk_hw_gate("sys1_pll_133m_cg", "sys1_pll_out", base + 0x30, 15); - hws[IMX8MQ_SYS1_PLL_160M_CG] = imx_clk_hw_gate("sys1_pll_160m_cg", "sys1_pll_out", base + 0x30, 17); - hws[IMX8MQ_SYS1_PLL_200M_CG] = imx_clk_hw_gate("sys1_pll_200m_cg", "sys1_pll_out", base + 0x30, 19); - hws[IMX8MQ_SYS1_PLL_266M_CG] = imx_clk_hw_gate("sys1_pll_266m_cg", "sys1_pll_out", base + 0x30, 21); - hws[IMX8MQ_SYS1_PLL_400M_CG] = imx_clk_hw_gate("sys1_pll_400m_cg", "sys1_pll_out", base + 0x30, 23); - hws[IMX8MQ_SYS1_PLL_800M_CG] = imx_clk_hw_gate("sys1_pll_800m_cg", "sys1_pll_out", base + 0x30, 25); - - hws[IMX8MQ_SYS1_PLL_40M] = imx_clk_hw_fixed_factor("sys1_pll_40m", "sys1_pll_40m_cg", 1, 20); - hws[IMX8MQ_SYS1_PLL_80M] = imx_clk_hw_fixed_factor("sys1_pll_80m", "sys1_pll_80m_cg", 1, 10); - hws[IMX8MQ_SYS1_PLL_100M] = imx_clk_hw_fixed_factor("sys1_pll_100m", "sys1_pll_100m_cg", 1, 8); - hws[IMX8MQ_SYS1_PLL_133M] = imx_clk_hw_fixed_factor("sys1_pll_133m", "sys1_pll_133m_cg", 1, 6); - hws[IMX8MQ_SYS1_PLL_160M] = imx_clk_hw_fixed_factor("sys1_pll_160m", "sys1_pll_160m_cg", 1, 5); - hws[IMX8MQ_SYS1_PLL_200M] = imx_clk_hw_fixed_factor("sys1_pll_200m", "sys1_pll_200m_cg", 1, 4); - hws[IMX8MQ_SYS1_PLL_266M] = imx_clk_hw_fixed_factor("sys1_pll_266m", "sys1_pll_266m_cg", 1, 3); - hws[IMX8MQ_SYS1_PLL_400M] = imx_clk_hw_fixed_factor("sys1_pll_400m", "sys1_pll_400m_cg", 1, 2); - hws[IMX8MQ_SYS1_PLL_800M] = imx_clk_hw_fixed_factor("sys1_pll_800m", "sys1_pll_800m_cg", 1, 1); + hws[IMX8MQ_SYS1_PLL_40M] = imx_clk_hw_fixed_factor("sys1_pll_40m", "sys1_pll_out", 1, 20); + hws[IMX8MQ_SYS1_PLL_80M] = imx_clk_hw_fixed_factor("sys1_pll_80m", "sys1_pll_out", 1, 10); + hws[IMX8MQ_SYS1_PLL_100M] = imx_clk_hw_fixed_factor("sys1_pll_100m", "sys1_pll_out", 1, 8); + hws[IMX8MQ_SYS1_PLL_133M] = imx_clk_hw_fixed_factor("sys1_pll_133m", "sys1_pll_out", 1, 6); + hws[IMX8MQ_SYS1_PLL_160M] = imx_clk_hw_fixed_factor("sys1_pll_160m", "sys1_pll_out", 1, 5); + hws[IMX8MQ_SYS1_PLL_200M] = imx_clk_hw_fixed_factor("sys1_pll_200m", "sys1_pll_out", 1, 4); + hws[IMX8MQ_SYS1_PLL_266M] = imx_clk_hw_fixed_factor("sys1_pll_266m", "sys1_pll_out", 1, 3); + hws[IMX8MQ_SYS1_PLL_400M] = imx_clk_hw_fixed_factor("sys1_pll_400m", "sys1_pll_out", 1, 2); + hws[IMX8MQ_SYS1_PLL_800M] = imx_clk_hw_fixed_factor("sys1_pll_800m", "sys1_pll_out", 1, 1); /* SYS PLL2 fixed output */ - hws[IMX8MQ_SYS2_PLL_50M_CG] = imx_clk_hw_gate("sys2_pll_50m_cg", "sys2_pll_out", base + 0x3c, 9); - hws[IMX8MQ_SYS2_PLL_100M_CG] = imx_clk_hw_gate("sys2_pll_100m_cg", "sys2_pll_out", base + 0x3c, 11); - hws[IMX8MQ_SYS2_PLL_125M_CG] = imx_clk_hw_gate("sys2_pll_125m_cg", "sys2_pll_out", base + 0x3c, 13); - hws[IMX8MQ_SYS2_PLL_166M_CG] = imx_clk_hw_gate("sys2_pll_166m_cg", "sys2_pll_out", base + 0x3c, 15); - hws[IMX8MQ_SYS2_PLL_200M_CG] = imx_clk_hw_gate("sys2_pll_200m_cg", "sys2_pll_out", base + 0x3c, 17); - hws[IMX8MQ_SYS2_PLL_250M_CG] = imx_clk_hw_gate("sys2_pll_250m_cg", "sys2_pll_out", base + 0x3c, 19); - hws[IMX8MQ_SYS2_PLL_333M_CG] = imx_clk_hw_gate("sys2_pll_333m_cg", "sys2_pll_out", base + 0x3c, 21); - hws[IMX8MQ_SYS2_PLL_500M_CG] = imx_clk_hw_gate("sys2_pll_500m_cg", "sys2_pll_out", base + 0x3c, 23); - hws[IMX8MQ_SYS2_PLL_1000M_CG] = imx_clk_hw_gate("sys2_pll_1000m_cg", "sys2_pll_out", base + 0x3c, 25); - - hws[IMX8MQ_SYS2_PLL_50M] = imx_clk_hw_fixed_factor("sys2_pll_50m", "sys2_pll_50m_cg", 1, 20); - hws[IMX8MQ_SYS2_PLL_100M] = imx_clk_hw_fixed_factor("sys2_pll_100m", "sys2_pll_100m_cg", 1, 10); - hws[IMX8MQ_SYS2_PLL_125M] = imx_clk_hw_fixed_factor("sys2_pll_125m", "sys2_pll_125m_cg", 1, 8); - hws[IMX8MQ_SYS2_PLL_166M] = imx_clk_hw_fixed_factor("sys2_pll_166m", "sys2_pll_166m_cg", 1, 6); - hws[IMX8MQ_SYS2_PLL_200M] = imx_clk_hw_fixed_factor("sys2_pll_200m", "sys2_pll_200m_cg", 1, 5); - hws[IMX8MQ_SYS2_PLL_250M] = imx_clk_hw_fixed_factor("sys2_pll_250m", "sys2_pll_250m_cg", 1, 4); - hws[IMX8MQ_SYS2_PLL_333M] = imx_clk_hw_fixed_factor("sys2_pll_333m", "sys2_pll_333m_cg", 1, 3); - hws[IMX8MQ_SYS2_PLL_500M] = imx_clk_hw_fixed_factor("sys2_pll_500m", "sys2_pll_500m_cg", 1, 2); - hws[IMX8MQ_SYS2_PLL_1000M] = imx_clk_hw_fixed_factor("sys2_pll_1000m", "sys2_pll_1000m_cg", 1, 1); + hws[IMX8MQ_SYS2_PLL_50M] = imx_clk_hw_fixed_factor("sys2_pll_50m", "sys2_pll_out", 1, 20); + hws[IMX8MQ_SYS2_PLL_100M] = imx_clk_hw_fixed_factor("sys2_pll_100m", "sys2_pll_out", 1, 10); + hws[IMX8MQ_SYS2_PLL_125M] = imx_clk_hw_fixed_factor("sys2_pll_125m", "sys2_pll_out", 1, 8); + hws[IMX8MQ_SYS2_PLL_166M] = imx_clk_hw_fixed_factor("sys2_pll_166m", "sys2_pll_out", 1, 6); + hws[IMX8MQ_SYS2_PLL_200M] = imx_clk_hw_fixed_factor("sys2_pll_200m", "sys2_pll_out", 1, 5); + hws[IMX8MQ_SYS2_PLL_250M] = imx_clk_hw_fixed_factor("sys2_pll_250m", "sys2_pll_out", 1, 4); + hws[IMX8MQ_SYS2_PLL_333M] = imx_clk_hw_fixed_factor("sys2_pll_333m", "sys2_pll_out", 1, 3); + hws[IMX8MQ_SYS2_PLL_500M] = imx_clk_hw_fixed_factor("sys2_pll_500m", "sys2_pll_out", 1, 2); + hws[IMX8MQ_SYS2_PLL_1000M] = imx_clk_hw_fixed_factor("sys2_pll_1000m", "sys2_pll_out", 1, 1); hws[IMX8MQ_CLK_MON_AUDIO_PLL1_DIV] = imx_clk_hw_divider("audio_pll1_out_monitor", "audio_pll1_bypass", base + 0x78, 0, 3); hws[IMX8MQ_CLK_MON_AUDIO_PLL2_DIV] = imx_clk_hw_divider("audio_pll2_out_monitor", "audio_pll2_bypass", base + 0x78, 4, 3); diff --git a/include/dt-bindings/clock/imx8mq-clock.h b/include/dt-bindings/clock/imx8mq-clock.h index 82e907ce7bdd..afa74d7ba100 100644 --- a/include/dt-bindings/clock/imx8mq-clock.h +++ b/include/dt-bindings/clock/imx8mq-clock.h @@ -405,25 +405,6 @@ #define IMX8MQ_VIDEO2_PLL1_REF_SEL 266 -#define IMX8MQ_SYS1_PLL_40M_CG 267 -#define IMX8MQ_SYS1_PLL_80M_CG 268 -#define IMX8MQ_SYS1_PLL_100M_CG 269 -#define IMX8MQ_SYS1_PLL_133M_CG 270 -#define IMX8MQ_SYS1_PLL_160M_CG 271 -#define IMX8MQ_SYS1_PLL_200M_CG 272 -#define IMX8MQ_SYS1_PLL_266M_CG 273 -#define IMX8MQ_SYS1_PLL_400M_CG 274 -#define IMX8MQ_SYS1_PLL_800M_CG 275 -#define IMX8MQ_SYS2_PLL_50M_CG 276 -#define IMX8MQ_SYS2_PLL_100M_CG 277 -#define IMX8MQ_SYS2_PLL_125M_CG 278 -#define IMX8MQ_SYS2_PLL_166M_CG 279 -#define IMX8MQ_SYS2_PLL_200M_CG 280 -#define IMX8MQ_SYS2_PLL_250M_CG 281 -#define IMX8MQ_SYS2_PLL_333M_CG 282 -#define IMX8MQ_SYS2_PLL_500M_CG 283 -#define IMX8MQ_SYS2_PLL_1000M_CG 284 - #define IMX8MQ_CLK_GPU_CORE 285 #define IMX8MQ_CLK_GPU_SHADER 286 #define IMX8MQ_CLK_M4_CORE 287 From 958ae02e8df8b656fa66d6172e8e35e8da2e3a4c Mon Sep 17 00:00:00 2001 From: Lokesh Vutla Date: Fri, 28 May 2021 10:27:42 +0530 Subject: [PATCH 088/161] dt-bindings: clock: ehrpwm: Add support for AM64 specific compatible Introduce AM64 specific compatible for epwm time-base sub-module clock. Signed-off-by: Lokesh Vutla Link: https://lore.kernel.org/r/20210528045743.16537-2-lokeshvutla@ti.com Acked-by: Rob Herring Reviewed-by: Tero Kristo Signed-off-by: Stephen Boyd --- .../devicetree/bindings/clock/ti,am654-ehrpwm-tbclk.yaml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/clock/ti,am654-ehrpwm-tbclk.yaml b/Documentation/devicetree/bindings/clock/ti,am654-ehrpwm-tbclk.yaml index 6b419a9878f3..9b537bc876b5 100644 --- a/Documentation/devicetree/bindings/clock/ti,am654-ehrpwm-tbclk.yaml +++ b/Documentation/devicetree/bindings/clock/ti,am654-ehrpwm-tbclk.yaml @@ -12,7 +12,9 @@ maintainers: properties: compatible: items: - - const: ti,am654-ehrpwm-tbclk + - enum: + - ti,am654-ehrpwm-tbclk + - ti,am64-epwm-tbclk - const: syscon "#clock-cells": From 87e2a58ca6c7095e5dc43e25212183afbfe0ad64 Mon Sep 17 00:00:00 2001 From: Lokesh Vutla Date: Fri, 28 May 2021 10:27:43 +0530 Subject: [PATCH 089/161] clk: keystone: syscon-clk: Add support for AM64 specific epwm-tbclk AM64 has 9 instances of EPWM modules. And each instance has a clk to Timer-Base sub-module that can be controlled by Control module. Update the driver with all the 9 instance of clocks associated to ti,am64-epwm-tbclk. Signed-off-by: Lokesh Vutla Link: https://lore.kernel.org/r/20210528045743.16537-3-lokeshvutla@ti.com Reviewed-by: Tero Kristo Signed-off-by: Stephen Boyd --- drivers/clk/keystone/syscon-clk.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/drivers/clk/keystone/syscon-clk.c b/drivers/clk/keystone/syscon-clk.c index 5b3d36462174..aae1a4076281 100644 --- a/drivers/clk/keystone/syscon-clk.c +++ b/drivers/clk/keystone/syscon-clk.c @@ -149,11 +149,28 @@ static const struct ti_syscon_gate_clk_data am654_clk_data[] = { { /* Sentinel */ }, }; +static const struct ti_syscon_gate_clk_data am64_clk_data[] = { + TI_SYSCON_CLK_GATE("epwm_tbclk0", 0x0, 0), + TI_SYSCON_CLK_GATE("epwm_tbclk1", 0x0, 1), + TI_SYSCON_CLK_GATE("epwm_tbclk2", 0x0, 2), + TI_SYSCON_CLK_GATE("epwm_tbclk3", 0x0, 3), + TI_SYSCON_CLK_GATE("epwm_tbclk4", 0x0, 4), + TI_SYSCON_CLK_GATE("epwm_tbclk5", 0x0, 5), + TI_SYSCON_CLK_GATE("epwm_tbclk6", 0x0, 6), + TI_SYSCON_CLK_GATE("epwm_tbclk7", 0x0, 7), + TI_SYSCON_CLK_GATE("epwm_tbclk8", 0x0, 8), + { /* Sentinel */ }, +}; + static const struct of_device_id ti_syscon_gate_clk_ids[] = { { .compatible = "ti,am654-ehrpwm-tbclk", .data = &am654_clk_data, }, + { + .compatible = "ti,am64-epwm-tbclk", + .data = &am64_clk_data, + }, { } }; MODULE_DEVICE_TABLE(of, ti_syscon_gate_clk_ids); From feb29cc744c1d4d503138708964f21840c23b3ea Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Fri, 11 Jun 2021 14:30:47 +0200 Subject: [PATCH 090/161] dt-bindings: clock: gpio-mux-clock: Convert to json-schema Convert the simple GPIO clock multiplexer Device Tree binding documentation to json-schema. Signed-off-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/14cb3b4da446f26a4780e0bd1b58788eb6085d05.1623414619.git.geert+renesas@glider.be Reviewed-by: Rob Herring Signed-off-by: Stephen Boyd --- .../bindings/clock/gpio-mux-clock.txt | 19 -------- .../bindings/clock/gpio-mux-clock.yaml | 45 +++++++++++++++++++ 2 files changed, 45 insertions(+), 19 deletions(-) delete mode 100644 Documentation/devicetree/bindings/clock/gpio-mux-clock.txt create mode 100644 Documentation/devicetree/bindings/clock/gpio-mux-clock.yaml diff --git a/Documentation/devicetree/bindings/clock/gpio-mux-clock.txt b/Documentation/devicetree/bindings/clock/gpio-mux-clock.txt deleted file mode 100644 index 2be1e038ca62..000000000000 --- a/Documentation/devicetree/bindings/clock/gpio-mux-clock.txt +++ /dev/null @@ -1,19 +0,0 @@ -Binding for simple gpio clock multiplexer. - -This binding uses the common clock binding[1]. - -[1] Documentation/devicetree/bindings/clock/clock-bindings.txt - -Required properties: -- compatible : shall be "gpio-mux-clock". -- clocks: list of two references to parent clocks. -- #clock-cells : from common clock binding; shall be set to 0. -- select-gpios : GPIO reference for selecting the parent clock. - -Example: - clock { - compatible = "gpio-mux-clock"; - clocks = <&parentclk1>, <&parentclk2>; - #clock-cells = <0>; - select-gpios = <&gpio 1 GPIO_ACTIVE_HIGH>; - }; diff --git a/Documentation/devicetree/bindings/clock/gpio-mux-clock.yaml b/Documentation/devicetree/bindings/clock/gpio-mux-clock.yaml new file mode 100644 index 000000000000..1e21f8b3a4ff --- /dev/null +++ b/Documentation/devicetree/bindings/clock/gpio-mux-clock.yaml @@ -0,0 +1,45 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/gpio-mux-clock.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Simple GPIO clock multiplexer + +maintainers: + - Sergej Sawazki + +properties: + compatible: + const: gpio-mux-clock + + clocks: + items: + - description: First parent clock + - description: Second parent clock + + '#clock-cells': + const: 0 + + select-gpios: + description: GPIO reference for selecting the parent clock. + maxItems: 1 + +required: + - compatible + - clocks + - '#clock-cells' + - select-gpios + +additionalProperties: false + +examples: + - | + #include + + clock { + compatible = "gpio-mux-clock"; + clocks = <&parentclk1>, <&parentclk2>; + #clock-cells = <0>; + select-gpios = <&gpio 1 GPIO_ACTIVE_HIGH>; + }; From 6c9feabc2c6bd49abbd2130341e7cb91f42d3fa5 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Tue, 22 Jun 2021 12:15:11 +0200 Subject: [PATCH 091/161] clk: zynqmp: fix compile testing without ZYNQMP_FIRMWARE When the firmware code is disabled, the incomplete error handling in the clk driver causes compile-time warnings: drivers/clk/zynqmp/pll.c: In function 'zynqmp_pll_recalc_rate': drivers/clk/zynqmp/pll.c:147:29: error: 'fbdiv' is used uninitialized [-Werror=uninitialized] 147 | rate = parent_rate * fbdiv; | ~~~~~~~~~~~~^~~~~~~ In function 'zynqmp_pll_get_mode', inlined from 'zynqmp_pll_recalc_rate' at drivers/clk/zynqmp/pll.c:148:6: drivers/clk/zynqmp/pll.c:61:27: error: 'ret_payload' is used uninitialized [-Werror=uninitialized] 61 | return ret_payload[1]; | ~~~~~~~~~~~^~~ drivers/clk/zynqmp/pll.c: In function 'zynqmp_pll_recalc_rate': drivers/clk/zynqmp/pll.c:53:13: note: 'ret_payload' declared here 53 | u32 ret_payload[PAYLOAD_ARG_CNT]; | ^~~~~~~~~~~ drivers/clk/zynqmp/clk-mux-zynqmp.c: In function 'zynqmp_clk_mux_get_parent': drivers/clk/zynqmp/clk-mux-zynqmp.c:57:16: error: 'val' is used uninitialized [-Werror=uninitialized] 57 | return val; | ^~~ As it was apparently intentional to support this for compile testing purposes, change the code to have just enough error handling for the compiler to not notice the remaining bugs. Fixes: 21f237534661 ("clk: zynqmp: Drop dependency on ARCH_ZYNQMP") Co-developed-by: Arnd Bergmann Signed-off-by: Michal Simek Link: https://lore.kernel.org/r/f1c4e8c903fe2d5df5413421920a56890a46387a.1624356908.git.michal.simek@xilinx.com Signed-off-by: Stephen Boyd --- drivers/clk/zynqmp/clk-mux-zynqmp.c | 10 ++++++++-- drivers/clk/zynqmp/pll.c | 22 ++++++++++++++++------ 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/drivers/clk/zynqmp/clk-mux-zynqmp.c b/drivers/clk/zynqmp/clk-mux-zynqmp.c index 06194149be83..d576c900dee0 100644 --- a/drivers/clk/zynqmp/clk-mux-zynqmp.c +++ b/drivers/clk/zynqmp/clk-mux-zynqmp.c @@ -38,7 +38,7 @@ struct zynqmp_clk_mux { * zynqmp_clk_mux_get_parent() - Get parent of clock * @hw: handle between common and hardware-specific interfaces * - * Return: Parent index + * Return: Parent index on success or number of parents in case of error */ static u8 zynqmp_clk_mux_get_parent(struct clk_hw *hw) { @@ -50,9 +50,15 @@ static u8 zynqmp_clk_mux_get_parent(struct clk_hw *hw) ret = zynqmp_pm_clock_getparent(clk_id, &val); - if (ret) + if (ret) { pr_warn_once("%s() getparent failed for clock: %s, ret = %d\n", __func__, clk_name, ret); + /* + * clk_core_get_parent_by_index() takes num_parents as incorrect + * index which is exactly what I want to return here + */ + return clk_hw_get_num_parents(hw); + } return val; } diff --git a/drivers/clk/zynqmp/pll.c b/drivers/clk/zynqmp/pll.c index abe6afbf3407..e025581f0d54 100644 --- a/drivers/clk/zynqmp/pll.c +++ b/drivers/clk/zynqmp/pll.c @@ -31,8 +31,9 @@ struct zynqmp_pll { #define PS_PLL_VCO_MAX 3000000000UL enum pll_mode { - PLL_MODE_INT, - PLL_MODE_FRAC, + PLL_MODE_INT = 0, + PLL_MODE_FRAC = 1, + PLL_MODE_ERROR = 2, }; #define FRAC_OFFSET 0x8 @@ -54,9 +55,11 @@ static inline enum pll_mode zynqmp_pll_get_mode(struct clk_hw *hw) int ret; ret = zynqmp_pm_get_pll_frac_mode(clk_id, ret_payload); - if (ret) + if (ret) { pr_warn_once("%s() PLL get frac mode failed for %s, ret = %d\n", __func__, clk_name, ret); + return PLL_MODE_ERROR; + } return ret_payload[1]; } @@ -126,7 +129,7 @@ static long zynqmp_pll_round_rate(struct clk_hw *hw, unsigned long rate, * @hw: Handle between common and hardware-specific interfaces * @parent_rate: Clock frequency of parent clock * - * Return: Current clock frequency + * Return: Current clock frequency or 0 in case of error */ static unsigned long zynqmp_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) @@ -138,14 +141,21 @@ static unsigned long zynqmp_pll_recalc_rate(struct clk_hw *hw, unsigned long rate, frac; u32 ret_payload[PAYLOAD_ARG_CNT]; int ret; + enum pll_mode mode; ret = zynqmp_pm_clock_getdivider(clk_id, &fbdiv); - if (ret) + if (ret) { pr_warn_once("%s() get divider failed for %s, ret = %d\n", __func__, clk_name, ret); + return 0ul; + } + + mode = zynqmp_pll_get_mode(hw); + if (mode == PLL_MODE_ERROR) + return 0ul; rate = parent_rate * fbdiv; - if (zynqmp_pll_get_mode(hw) == PLL_MODE_FRAC) { + if (mode == PLL_MODE_FRAC) { zynqmp_pm_get_pll_frac_data(clk_id, ret_payload); data = ret_payload[1]; frac = (parent_rate * data) / FRAC_DIV; From b9ec1c1f9c1bd0344a34a3309b9cc8eba59d7da8 Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Sat, 1 May 2021 13:24:32 +0200 Subject: [PATCH 092/161] clk: zynqmp: pll: Remove some dead code 'clk_hw_set_rate_range()' does not return any error code and 'ret' is known to be 0 at this point, so this message can never be displayed. Remove it. Fixes: 3fde0e16d016 ("drivers: clk: Add ZynqMP clock driver") Signed-off-by: Christophe JAILLET Link: https://lore.kernel.org/r/71a9fed5f762a71248b8ac73c0a15af82f3ce1e2.1619867987.git.christophe.jaillet@wanadoo.fr Reviewed-by: Michael Tretter Signed-off-by: Stephen Boyd --- drivers/clk/zynqmp/pll.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/clk/zynqmp/pll.c b/drivers/clk/zynqmp/pll.c index e025581f0d54..793b950ade09 100644 --- a/drivers/clk/zynqmp/pll.c +++ b/drivers/clk/zynqmp/pll.c @@ -341,8 +341,6 @@ struct clk_hw *zynqmp_clk_register_pll(const char *name, u32 clk_id, } clk_hw_set_rate_range(hw, PS_PLL_VCO_MIN, PS_PLL_VCO_MAX); - if (ret < 0) - pr_err("%s:ERROR clk_set_rate_range failed %d\n", name, ret); return hw; } From 2f0d67bf4cecb7b5c1c91c85c6a0c08a830adb85 Mon Sep 17 00:00:00 2001 From: Alexandru Ardelean Date: Thu, 24 Jun 2021 11:47:37 +0300 Subject: [PATCH 093/161] clk: tegra: clk-tegra124-dfll-fcpu: don't use devm functions for regulator The purpose of the device-managed functions is to bind the life-time of an object to that of a parent device object. This is not the case for the 'vdd-cpu' regulator in this driver. A reference is obtained via devm_regulator_get() and immediately released with devm_regulator_put(). In this case, the usage of devm_ functions is slightly excessive, as the un-managed versions of these functions is a little cleaner (and slightly more economical in terms of allocation). This change converts the devm_regulator_{get,put}() to regulator_{get,put}() in the get_alignment_from_regulator() function of this driver. Signed-off-by: Alexandru Ardelean Link: https://lore.kernel.org/r/20210624084737.42336-1-aardelean@deviqon.com Reviewed-by: Thierry Reding Signed-off-by: Stephen Boyd --- drivers/clk/tegra/clk-tegra124-dfll-fcpu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/clk/tegra/clk-tegra124-dfll-fcpu.c b/drivers/clk/tegra/clk-tegra124-dfll-fcpu.c index 2ac2679d696d..5e339ad0a97c 100644 --- a/drivers/clk/tegra/clk-tegra124-dfll-fcpu.c +++ b/drivers/clk/tegra/clk-tegra124-dfll-fcpu.c @@ -537,7 +537,7 @@ static void get_alignment_from_dt(struct device *dev, static int get_alignment_from_regulator(struct device *dev, struct rail_alignment *align) { - struct regulator *reg = devm_regulator_get(dev, "vdd-cpu"); + struct regulator *reg = regulator_get(dev, "vdd-cpu"); if (IS_ERR(reg)) return PTR_ERR(reg); @@ -545,7 +545,7 @@ static int get_alignment_from_regulator(struct device *dev, align->offset_uv = regulator_list_voltage(reg, 0); align->step_uv = regulator_get_linear_step(reg); - devm_regulator_put(reg); + regulator_put(reg); return 0; } From efbe21df3e889c0f4bf682c2b7e2465d60b0127c Mon Sep 17 00:00:00 2001 From: Dinh Nguyen Date: Thu, 10 Jun 2021 21:51:58 -0500 Subject: [PATCH 094/161] clk: agilex/stratix10: remove noc_clk Early documentation had a noc_clk, but in reality, it's just the noc_free_clk. Remove the noc_clk clock and just use the noc_free_clk. Fixes: 80c6b7a0894f ("clk: socfpga: agilex: add clock driver for the Agilex platform") Cc: stable@vger.kernel.org Signed-off-by: Dinh Nguyen Link: https://lore.kernel.org/r/20210611025201.118799-1-dinguyen@kernel.org Signed-off-by: Stephen Boyd --- drivers/clk/socfpga/clk-agilex.c | 32 +++++++++++++++----------------- drivers/clk/socfpga/clk-s10.c | 32 +++++++++++++++----------------- 2 files changed, 30 insertions(+), 34 deletions(-) diff --git a/drivers/clk/socfpga/clk-agilex.c b/drivers/clk/socfpga/clk-agilex.c index 92a6d740a799..5b8131542218 100644 --- a/drivers/clk/socfpga/clk-agilex.c +++ b/drivers/clk/socfpga/clk-agilex.c @@ -222,11 +222,9 @@ static const struct stratix10_perip_cnt_clock agilex_main_perip_cnt_clks[] = { { AGILEX_MPU_FREE_CLK, "mpu_free_clk", NULL, mpu_free_mux, ARRAY_SIZE(mpu_free_mux), 0, 0x3C, 0, 0, 0}, { AGILEX_NOC_FREE_CLK, "noc_free_clk", NULL, noc_free_mux, ARRAY_SIZE(noc_free_mux), - 0, 0x40, 0, 0, 1}, - { AGILEX_L4_SYS_FREE_CLK, "l4_sys_free_clk", "noc_free_clk", NULL, 1, 0, - 0, 4, 0, 0}, - { AGILEX_NOC_CLK, "noc_clk", NULL, noc_mux, ARRAY_SIZE(noc_mux), - 0, 0, 0, 0x30, 1}, + 0, 0x40, 0, 0, 0}, + { AGILEX_L4_SYS_FREE_CLK, "l4_sys_free_clk", NULL, noc_mux, ARRAY_SIZE(noc_mux), 0, + 0, 4, 0x30, 1}, { AGILEX_EMAC_A_FREE_CLK, "emaca_free_clk", NULL, emaca_free_mux, ARRAY_SIZE(emaca_free_mux), 0, 0xD4, 0, 0x88, 0}, { AGILEX_EMAC_B_FREE_CLK, "emacb_free_clk", NULL, emacb_free_mux, ARRAY_SIZE(emacb_free_mux), @@ -252,24 +250,24 @@ static const struct stratix10_gate_clock agilex_gate_clks[] = { 0, 0, 0, 0, 0, 0, 4}, { AGILEX_MPU_CCU_CLK, "mpu_ccu_clk", "mpu_clk", NULL, 1, 0, 0x24, 0, 0, 0, 0, 0, 0, 2}, - { AGILEX_L4_MAIN_CLK, "l4_main_clk", "noc_clk", NULL, 1, 0, 0x24, - 1, 0x44, 0, 2, 0, 0, 0}, - { AGILEX_L4_MP_CLK, "l4_mp_clk", "noc_clk", NULL, 1, 0, 0x24, - 2, 0x44, 8, 2, 0, 0, 0}, + { AGILEX_L4_MAIN_CLK, "l4_main_clk", NULL, noc_mux, ARRAY_SIZE(noc_mux), 0, 0x24, + 1, 0x44, 0, 2, 0x30, 1, 0}, + { AGILEX_L4_MP_CLK, "l4_mp_clk", NULL, noc_mux, ARRAY_SIZE(noc_mux), 0, 0x24, + 2, 0x44, 8, 2, 0x30, 1, 0}, /* * The l4_sp_clk feeds a 100 MHz clock to various peripherals, one of them * being the SP timers, thus cannot get gated. */ - { AGILEX_L4_SP_CLK, "l4_sp_clk", "noc_clk", NULL, 1, CLK_IS_CRITICAL, 0x24, - 3, 0x44, 16, 2, 0, 0, 0}, - { AGILEX_CS_AT_CLK, "cs_at_clk", "noc_clk", NULL, 1, 0, 0x24, - 4, 0x44, 24, 2, 0, 0, 0}, - { AGILEX_CS_TRACE_CLK, "cs_trace_clk", "noc_clk", NULL, 1, 0, 0x24, - 4, 0x44, 26, 2, 0, 0, 0}, + { AGILEX_L4_SP_CLK, "l4_sp_clk", NULL, noc_mux, ARRAY_SIZE(noc_mux), CLK_IS_CRITICAL, 0x24, + 3, 0x44, 16, 2, 0x30, 1, 0}, + { AGILEX_CS_AT_CLK, "cs_at_clk", NULL, noc_mux, ARRAY_SIZE(noc_mux), 0, 0x24, + 4, 0x44, 24, 2, 0x30, 1, 0}, + { AGILEX_CS_TRACE_CLK, "cs_trace_clk", NULL, noc_mux, ARRAY_SIZE(noc_mux), 0, 0x24, + 4, 0x44, 26, 2, 0x30, 1, 0}, { AGILEX_CS_PDBG_CLK, "cs_pdbg_clk", "cs_at_clk", NULL, 1, 0, 0x24, 4, 0x44, 28, 1, 0, 0, 0}, - { AGILEX_CS_TIMER_CLK, "cs_timer_clk", "noc_clk", NULL, 1, 0, 0x24, - 5, 0, 0, 0, 0, 0, 0}, + { AGILEX_CS_TIMER_CLK, "cs_timer_clk", NULL, noc_mux, ARRAY_SIZE(noc_mux), 0, 0x24, + 5, 0, 0, 0, 0x30, 1, 0}, { AGILEX_S2F_USER0_CLK, "s2f_user0_clk", NULL, s2f_usr0_mux, ARRAY_SIZE(s2f_usr0_mux), 0, 0x24, 6, 0, 0, 0, 0, 0, 0}, { AGILEX_EMAC0_CLK, "emac0_clk", NULL, emac_mux, ARRAY_SIZE(emac_mux), 0, 0x7C, diff --git a/drivers/clk/socfpga/clk-s10.c b/drivers/clk/socfpga/clk-s10.c index f0bd77138ecb..0199cffe4d77 100644 --- a/drivers/clk/socfpga/clk-s10.c +++ b/drivers/clk/socfpga/clk-s10.c @@ -167,7 +167,7 @@ static const struct stratix10_perip_cnt_clock s10_main_perip_cnt_clks[] = { { STRATIX10_MPU_FREE_CLK, "mpu_free_clk", NULL, mpu_free_mux, ARRAY_SIZE(mpu_free_mux), 0, 0x48, 0, 0, 0}, { STRATIX10_NOC_FREE_CLK, "noc_free_clk", NULL, noc_free_mux, ARRAY_SIZE(noc_free_mux), - 0, 0x4C, 0, 0, 0}, + 0, 0x4C, 0, 0x3C, 1}, { STRATIX10_MAIN_EMACA_CLK, "main_emaca_clk", "main_noc_base_clk", NULL, 1, 0, 0x50, 0, 0, 0}, { STRATIX10_MAIN_EMACB_CLK, "main_emacb_clk", "main_noc_base_clk", NULL, 1, 0, @@ -200,10 +200,8 @@ static const struct stratix10_perip_cnt_clock s10_main_perip_cnt_clks[] = { 0, 0xD4, 0, 0, 0}, { STRATIX10_PERI_PSI_REF_CLK, "peri_psi_ref_clk", "peri_noc_base_clk", NULL, 1, 0, 0xD8, 0, 0, 0}, - { STRATIX10_L4_SYS_FREE_CLK, "l4_sys_free_clk", "noc_free_clk", NULL, 1, 0, - 0, 4, 0, 0}, - { STRATIX10_NOC_CLK, "noc_clk", NULL, noc_mux, ARRAY_SIZE(noc_mux), - 0, 0, 0, 0x3C, 1}, + { STRATIX10_L4_SYS_FREE_CLK, "l4_sys_free_clk", NULL, noc_mux, ARRAY_SIZE(noc_mux), 0, + 0, 4, 0x3C, 1}, { STRATIX10_EMAC_A_FREE_CLK, "emaca_free_clk", NULL, emaca_free_mux, ARRAY_SIZE(emaca_free_mux), 0, 0, 2, 0xB0, 0}, { STRATIX10_EMAC_B_FREE_CLK, "emacb_free_clk", NULL, emacb_free_mux, ARRAY_SIZE(emacb_free_mux), @@ -227,20 +225,20 @@ static const struct stratix10_gate_clock s10_gate_clks[] = { 0, 0, 0, 0, 0, 0, 4}, { STRATIX10_MPU_L2RAM_CLK, "mpu_l2ram_clk", "mpu_clk", NULL, 1, 0, 0x30, 0, 0, 0, 0, 0, 0, 2}, - { STRATIX10_L4_MAIN_CLK, "l4_main_clk", "noc_clk", NULL, 1, 0, 0x30, - 1, 0x70, 0, 2, 0, 0, 0}, - { STRATIX10_L4_MP_CLK, "l4_mp_clk", "noc_clk", NULL, 1, 0, 0x30, - 2, 0x70, 8, 2, 0, 0, 0}, - { STRATIX10_L4_SP_CLK, "l4_sp_clk", "noc_clk", NULL, 1, CLK_IS_CRITICAL, 0x30, - 3, 0x70, 16, 2, 0, 0, 0}, - { STRATIX10_CS_AT_CLK, "cs_at_clk", "noc_clk", NULL, 1, 0, 0x30, - 4, 0x70, 24, 2, 0, 0, 0}, - { STRATIX10_CS_TRACE_CLK, "cs_trace_clk", "noc_clk", NULL, 1, 0, 0x30, - 4, 0x70, 26, 2, 0, 0, 0}, + { STRATIX10_L4_MAIN_CLK, "l4_main_clk", NULL, noc_mux, ARRAY_SIZE(noc_mux), 0, 0x30, + 1, 0x70, 0, 2, 0x3C, 1, 0}, + { STRATIX10_L4_MP_CLK, "l4_mp_clk", NULL, noc_mux, ARRAY_SIZE(noc_mux), 0, 0x30, + 2, 0x70, 8, 2, 0x3C, 1, 0}, + { STRATIX10_L4_SP_CLK, "l4_sp_clk", NULL, noc_mux, ARRAY_SIZE(noc_mux), CLK_IS_CRITICAL, 0x30, + 3, 0x70, 16, 2, 0x3C, 1, 0}, + { STRATIX10_CS_AT_CLK, "cs_at_clk", NULL, noc_mux, ARRAY_SIZE(noc_mux), 0, 0x30, + 4, 0x70, 24, 2, 0x3C, 1, 0}, + { STRATIX10_CS_TRACE_CLK, "cs_trace_clk", NULL, noc_mux, ARRAY_SIZE(noc_mux), 0, 0x30, + 4, 0x70, 26, 2, 0x3C, 1, 0}, { STRATIX10_CS_PDBG_CLK, "cs_pdbg_clk", "cs_at_clk", NULL, 1, 0, 0x30, 4, 0x70, 28, 1, 0, 0, 0}, - { STRATIX10_CS_TIMER_CLK, "cs_timer_clk", "noc_clk", NULL, 1, 0, 0x30, - 5, 0, 0, 0, 0, 0, 0}, + { STRATIX10_CS_TIMER_CLK, "cs_timer_clk", NULL, noc_mux, ARRAY_SIZE(noc_mux), 0, 0x30, + 5, 0, 0, 0, 0x3C, 1, 0}, { STRATIX10_S2F_USER0_CLK, "s2f_user0_clk", NULL, s2f_usr0_mux, ARRAY_SIZE(s2f_usr0_mux), 0, 0x30, 6, 0, 0, 0, 0, 0, 0}, { STRATIX10_EMAC0_CLK, "emac0_clk", NULL, emac_mux, ARRAY_SIZE(emac_mux), 0, 0xA4, From 6855ee839699bdabb4b16cf942557fd763bcb1fa Mon Sep 17 00:00:00 2001 From: Dinh Nguyen Date: Thu, 10 Jun 2021 21:51:59 -0500 Subject: [PATCH 095/161] clk: agilex/stratix10: fix bypass representation Each of these clocks(s2f_usr0/1, sdmmc_clk, gpio_db, emac_ptp, emac0/1/2) have a bypass setting that can use the boot_clk. The previous representation was not correct. Fix the representation. Fixes: 80c6b7a0894f ("clk: socfpga: agilex: add clock driver for the Agilex platform") Cc: stable@vger.kernel.org Signed-off-by: Dinh Nguyen Link: https://lore.kernel.org/r/20210611025201.118799-2-dinguyen@kernel.org Signed-off-by: Stephen Boyd --- drivers/clk/socfpga/clk-agilex.c | 57 ++++++++++++++++++++++++++------ drivers/clk/socfpga/clk-s10.c | 55 ++++++++++++++++++++++++------ 2 files changed, 91 insertions(+), 21 deletions(-) diff --git a/drivers/clk/socfpga/clk-agilex.c b/drivers/clk/socfpga/clk-agilex.c index 5b8131542218..edfa87d0cd76 100644 --- a/drivers/clk/socfpga/clk-agilex.c +++ b/drivers/clk/socfpga/clk-agilex.c @@ -186,6 +186,41 @@ static const struct clk_parent_data noc_mux[] = { .name = "boot_clk", }, }; +static const struct clk_parent_data sdmmc_mux[] = { + { .fw_name = "sdmmc_free_clk", + .name = "sdmmc_free_clk", }, + { .fw_name = "boot_clk", + .name = "boot_clk", }, +}; + +static const struct clk_parent_data s2f_user1_mux[] = { + { .fw_name = "s2f_user1_free_clk", + .name = "s2f_user1_free_clk", }, + { .fw_name = "boot_clk", + .name = "boot_clk", }, +}; + +static const struct clk_parent_data psi_mux[] = { + { .fw_name = "psi_ref_free_clk", + .name = "psi_ref_free_clk", }, + { .fw_name = "boot_clk", + .name = "boot_clk", }, +}; + +static const struct clk_parent_data gpio_db_mux[] = { + { .fw_name = "gpio_db_free_clk", + .name = "gpio_db_free_clk", }, + { .fw_name = "boot_clk", + .name = "boot_clk", }, +}; + +static const struct clk_parent_data emac_ptp_mux[] = { + { .fw_name = "emac_ptp_free_clk", + .name = "emac_ptp_free_clk", }, + { .fw_name = "boot_clk", + .name = "boot_clk", }, +}; + /* clocks in AO (always on) controller */ static const struct stratix10_pll_clock agilex_pll_clks[] = { { AGILEX_BOOT_CLK, "boot_clk", boot_mux, ARRAY_SIZE(boot_mux), 0, @@ -234,7 +269,7 @@ static const struct stratix10_perip_cnt_clock agilex_main_perip_cnt_clks[] = { { AGILEX_GPIO_DB_FREE_CLK, "gpio_db_free_clk", NULL, gpio_db_free_mux, ARRAY_SIZE(gpio_db_free_mux), 0, 0xE0, 0, 0x88, 3}, { AGILEX_SDMMC_FREE_CLK, "sdmmc_free_clk", NULL, sdmmc_free_mux, - ARRAY_SIZE(sdmmc_free_mux), 0, 0xE4, 0, 0x88, 4}, + ARRAY_SIZE(sdmmc_free_mux), 0, 0xE4, 0, 0, 0}, { AGILEX_S2F_USER0_FREE_CLK, "s2f_user0_free_clk", NULL, s2f_usr0_free_mux, ARRAY_SIZE(s2f_usr0_free_mux), 0, 0xE8, 0, 0, 0}, { AGILEX_S2F_USER1_FREE_CLK, "s2f_user1_free_clk", NULL, s2f_usr1_free_mux, @@ -276,16 +311,16 @@ static const struct stratix10_gate_clock agilex_gate_clks[] = { 1, 0, 0, 0, 0x94, 27, 0}, { AGILEX_EMAC2_CLK, "emac2_clk", NULL, emac_mux, ARRAY_SIZE(emac_mux), 0, 0x7C, 2, 0, 0, 0, 0x94, 28, 0}, - { AGILEX_EMAC_PTP_CLK, "emac_ptp_clk", "emac_ptp_free_clk", NULL, 1, 0, 0x7C, - 3, 0, 0, 0, 0, 0, 0}, - { AGILEX_GPIO_DB_CLK, "gpio_db_clk", "gpio_db_free_clk", NULL, 1, 0, 0x7C, - 4, 0x98, 0, 16, 0, 0, 0}, - { AGILEX_SDMMC_CLK, "sdmmc_clk", "sdmmc_free_clk", NULL, 1, 0, 0x7C, - 5, 0, 0, 0, 0, 0, 4}, - { AGILEX_S2F_USER1_CLK, "s2f_user1_clk", "s2f_user1_free_clk", NULL, 1, 0, 0x7C, - 6, 0, 0, 0, 0, 0, 0}, - { AGILEX_PSI_REF_CLK, "psi_ref_clk", "psi_ref_free_clk", NULL, 1, 0, 0x7C, - 7, 0, 0, 0, 0, 0, 0}, + { AGILEX_EMAC_PTP_CLK, "emac_ptp_clk", NULL, emac_ptp_mux, ARRAY_SIZE(emac_ptp_mux), 0, 0x7C, + 3, 0, 0, 0, 0x88, 2, 0}, + { AGILEX_GPIO_DB_CLK, "gpio_db_clk", NULL, gpio_db_mux, ARRAY_SIZE(gpio_db_mux), 0, 0x7C, + 4, 0x98, 0, 16, 0x88, 3, 0}, + { AGILEX_SDMMC_CLK, "sdmmc_clk", NULL, sdmmc_mux, ARRAY_SIZE(sdmmc_mux), 0, 0x7C, + 5, 0, 0, 0, 0x88, 4, 4}, + { AGILEX_S2F_USER1_CLK, "s2f_user1_clk", NULL, s2f_user1_mux, ARRAY_SIZE(s2f_user1_mux), 0, 0x7C, + 6, 0, 0, 0, 0x88, 5, 0}, + { AGILEX_PSI_REF_CLK, "psi_ref_clk", NULL, psi_mux, ARRAY_SIZE(psi_mux), 0, 0x7C, + 7, 0, 0, 0, 0x88, 6, 0}, { AGILEX_USB_CLK, "usb_clk", "l4_mp_clk", NULL, 1, 0, 0x7C, 8, 0, 0, 0, 0, 0, 0}, { AGILEX_SPI_M_CLK, "spi_m_clk", "l4_mp_clk", NULL, 1, 0, 0x7C, diff --git a/drivers/clk/socfpga/clk-s10.c b/drivers/clk/socfpga/clk-s10.c index 0199cffe4d77..b532d51faaee 100644 --- a/drivers/clk/socfpga/clk-s10.c +++ b/drivers/clk/socfpga/clk-s10.c @@ -144,6 +144,41 @@ static const struct clk_parent_data mpu_free_mux[] = { .name = "f2s-free-clk", }, }; +static const struct clk_parent_data sdmmc_mux[] = { + { .fw_name = "sdmmc_free_clk", + .name = "sdmmc_free_clk", }, + { .fw_name = "boot_clk", + .name = "boot_clk", }, +}; + +static const struct clk_parent_data s2f_user1_mux[] = { + { .fw_name = "s2f_user1_free_clk", + .name = "s2f_user1_free_clk", }, + { .fw_name = "boot_clk", + .name = "boot_clk", }, +}; + +static const struct clk_parent_data psi_mux[] = { + { .fw_name = "psi_ref_free_clk", + .name = "psi_ref_free_clk", }, + { .fw_name = "boot_clk", + .name = "boot_clk", }, +}; + +static const struct clk_parent_data gpio_db_mux[] = { + { .fw_name = "gpio_db_free_clk", + .name = "gpio_db_free_clk", }, + { .fw_name = "boot_clk", + .name = "boot_clk", }, +}; + +static const struct clk_parent_data emac_ptp_mux[] = { + { .fw_name = "emac_ptp_free_clk", + .name = "emac_ptp_free_clk", }, + { .fw_name = "boot_clk", + .name = "boot_clk", }, +}; + /* clocks in AO (always on) controller */ static const struct stratix10_pll_clock s10_pll_clks[] = { { STRATIX10_BOOT_CLK, "boot_clk", boot_mux, ARRAY_SIZE(boot_mux), 0, @@ -247,16 +282,16 @@ static const struct stratix10_gate_clock s10_gate_clks[] = { 1, 0, 0, 0, 0xDC, 27, 0}, { STRATIX10_EMAC2_CLK, "emac2_clk", NULL, emac_mux, ARRAY_SIZE(emac_mux), 0, 0xA4, 2, 0, 0, 0, 0xDC, 28, 0}, - { STRATIX10_EMAC_PTP_CLK, "emac_ptp_clk", "emac_ptp_free_clk", NULL, 1, 0, 0xA4, - 3, 0, 0, 0, 0, 0, 0}, - { STRATIX10_GPIO_DB_CLK, "gpio_db_clk", "gpio_db_free_clk", NULL, 1, 0, 0xA4, - 4, 0xE0, 0, 16, 0, 0, 0}, - { STRATIX10_SDMMC_CLK, "sdmmc_clk", "sdmmc_free_clk", NULL, 1, 0, 0xA4, - 5, 0, 0, 0, 0, 0, 4}, - { STRATIX10_S2F_USER1_CLK, "s2f_user1_clk", "s2f_user1_free_clk", NULL, 1, 0, 0xA4, - 6, 0, 0, 0, 0, 0, 0}, - { STRATIX10_PSI_REF_CLK, "psi_ref_clk", "psi_ref_free_clk", NULL, 1, 0, 0xA4, - 7, 0, 0, 0, 0, 0, 0}, + { STRATIX10_EMAC_PTP_CLK, "emac_ptp_clk", NULL, emac_ptp_mux, ARRAY_SIZE(emac_ptp_mux), 0, 0xA4, + 3, 0, 0, 0, 0xB0, 2, 0}, + { STRATIX10_GPIO_DB_CLK, "gpio_db_clk", NULL, gpio_db_mux, ARRAY_SIZE(gpio_db_mux), 0, 0xA4, + 4, 0xE0, 0, 16, 0xB0, 3, 0}, + { STRATIX10_SDMMC_CLK, "sdmmc_clk", NULL, sdmmc_mux, ARRAY_SIZE(sdmmc_mux), 0, 0xA4, + 5, 0, 0, 0, 0xB0, 4, 4}, + { STRATIX10_S2F_USER1_CLK, "s2f_user1_clk", NULL, s2f_user1_mux, ARRAY_SIZE(s2f_user1_mux), 0, 0xA4, + 6, 0, 0, 0, 0xB0, 5, 0}, + { STRATIX10_PSI_REF_CLK, "psi_ref_clk", NULL, psi_mux, ARRAY_SIZE(psi_mux), 0, 0xA4, + 7, 0, 0, 0, 0xB0, 6, 0}, { STRATIX10_USB_CLK, "usb_clk", "l4_mp_clk", NULL, 1, 0, 0xA4, 8, 0, 0, 0, 0, 0, 0}, { STRATIX10_SPI_M_CLK, "spi_m_clk", "l4_mp_clk", NULL, 1, 0, 0xA4, From c2c9c5661a48bf2e67dcb4e989003144304acd6a Mon Sep 17 00:00:00 2001 From: Dinh Nguyen Date: Thu, 10 Jun 2021 21:52:00 -0500 Subject: [PATCH 096/161] clk: agilex/stratix10: add support for the 2nd bypass The EMAC clocks on Stratix10/Agilex/N5X have an additional bypass that was not being accounted for. The bypass selects between emaca_clk/emacb_clk and boot_clk. Because the bypass register offset is different between Stratix10 and Agilex/N5X, it's best to create a new function to calculate the bypass. Fixes: 80c6b7a0894f ("clk: socfpga: agilex: add clock driver for the Agilex platform") Cc: stable@vger.kernel.org Signed-off-by: Dinh Nguyen Link: https://lore.kernel.org/r/20210611025201.118799-3-dinguyen@kernel.org Signed-off-by: Stephen Boyd --- drivers/clk/socfpga/clk-agilex.c | 4 +- drivers/clk/socfpga/clk-gate-s10.c | 119 +++++++++++++++++++++++++++- drivers/clk/socfpga/stratix10-clk.h | 2 + 3 files changed, 123 insertions(+), 2 deletions(-) diff --git a/drivers/clk/socfpga/clk-agilex.c b/drivers/clk/socfpga/clk-agilex.c index edfa87d0cd76..1cb21ea79c64 100644 --- a/drivers/clk/socfpga/clk-agilex.c +++ b/drivers/clk/socfpga/clk-agilex.c @@ -177,6 +177,8 @@ static const struct clk_parent_data emac_mux[] = { .name = "emaca_free_clk", }, { .fw_name = "emacb_free_clk", .name = "emacb_free_clk", }, + { .fw_name = "boot_clk", + .name = "boot_clk", }, }; static const struct clk_parent_data noc_mux[] = { @@ -399,7 +401,7 @@ static int agilex_clk_register_gate(const struct stratix10_gate_clock *clks, int i; for (i = 0; i < nums; i++) { - hw_clk = s10_register_gate(&clks[i], base); + hw_clk = agilex_register_gate(&clks[i], base); if (IS_ERR(hw_clk)) { pr_err("%s: failed to register clock %s\n", __func__, clks[i].name); diff --git a/drivers/clk/socfpga/clk-gate-s10.c b/drivers/clk/socfpga/clk-gate-s10.c index b84f2627551e..32567795765f 100644 --- a/drivers/clk/socfpga/clk-gate-s10.c +++ b/drivers/clk/socfpga/clk-gate-s10.c @@ -11,6 +11,13 @@ #define SOCFPGA_CS_PDBG_CLK "cs_pdbg_clk" #define to_socfpga_gate_clk(p) container_of(p, struct socfpga_gate_clk, hw.hw) +#define SOCFPGA_EMAC0_CLK "emac0_clk" +#define SOCFPGA_EMAC1_CLK "emac1_clk" +#define SOCFPGA_EMAC2_CLK "emac2_clk" +#define AGILEX_BYPASS_OFFSET 0xC +#define STRATIX10_BYPASS_OFFSET 0x2C +#define BOOTCLK_BYPASS 2 + static unsigned long socfpga_gate_clk_recalc_rate(struct clk_hw *hwclk, unsigned long parent_rate) { @@ -44,14 +51,61 @@ static unsigned long socfpga_dbg_clk_recalc_rate(struct clk_hw *hwclk, static u8 socfpga_gate_get_parent(struct clk_hw *hwclk) { struct socfpga_gate_clk *socfpgaclk = to_socfpga_gate_clk(hwclk); - u32 mask; + u32 mask, second_bypass; u8 parent = 0; + const char *name = clk_hw_get_name(hwclk); if (socfpgaclk->bypass_reg) { mask = (0x1 << socfpgaclk->bypass_shift); parent = ((readl(socfpgaclk->bypass_reg) & mask) >> socfpgaclk->bypass_shift); } + + if (streq(name, SOCFPGA_EMAC0_CLK) || + streq(name, SOCFPGA_EMAC1_CLK) || + streq(name, SOCFPGA_EMAC2_CLK)) { + second_bypass = readl(socfpgaclk->bypass_reg - + STRATIX10_BYPASS_OFFSET); + /* EMACA bypass to bootclk @0xB0 offset */ + if (second_bypass & 0x1) + if (parent == 0) /* only applicable if parent is maca */ + parent = BOOTCLK_BYPASS; + + if (second_bypass & 0x2) + if (parent == 1) /* only applicable if parent is macb */ + parent = BOOTCLK_BYPASS; + } + return parent; +} + +static u8 socfpga_agilex_gate_get_parent(struct clk_hw *hwclk) +{ + struct socfpga_gate_clk *socfpgaclk = to_socfpga_gate_clk(hwclk); + u32 mask, second_bypass; + u8 parent = 0; + const char *name = clk_hw_get_name(hwclk); + + if (socfpgaclk->bypass_reg) { + mask = (0x1 << socfpgaclk->bypass_shift); + parent = ((readl(socfpgaclk->bypass_reg) & mask) >> + socfpgaclk->bypass_shift); + } + + if (streq(name, SOCFPGA_EMAC0_CLK) || + streq(name, SOCFPGA_EMAC1_CLK) || + streq(name, SOCFPGA_EMAC2_CLK)) { + second_bypass = readl(socfpgaclk->bypass_reg - + AGILEX_BYPASS_OFFSET); + /* EMACA bypass to bootclk @0x88 offset */ + if (second_bypass & 0x1) + if (parent == 0) /* only applicable if parent is maca */ + parent = BOOTCLK_BYPASS; + + if (second_bypass & 0x2) + if (parent == 1) /* only applicable if parent is macb */ + parent = BOOTCLK_BYPASS; + } + return parent; } @@ -60,6 +114,11 @@ static struct clk_ops gateclk_ops = { .get_parent = socfpga_gate_get_parent, }; +static const struct clk_ops agilex_gateclk_ops = { + .recalc_rate = socfpga_gate_clk_recalc_rate, + .get_parent = socfpga_agilex_gate_get_parent, +}; + static const struct clk_ops dbgclk_ops = { .recalc_rate = socfpga_dbg_clk_recalc_rate, .get_parent = socfpga_gate_get_parent, @@ -122,3 +181,61 @@ struct clk_hw *s10_register_gate(const struct stratix10_gate_clock *clks, void _ } return hw_clk; } + +struct clk_hw *agilex_register_gate(const struct stratix10_gate_clock *clks, void __iomem *regbase) +{ + struct clk_hw *hw_clk; + struct socfpga_gate_clk *socfpga_clk; + struct clk_init_data init; + const char *parent_name = clks->parent_name; + int ret; + + socfpga_clk = kzalloc(sizeof(*socfpga_clk), GFP_KERNEL); + if (!socfpga_clk) + return NULL; + + socfpga_clk->hw.reg = regbase + clks->gate_reg; + socfpga_clk->hw.bit_idx = clks->gate_idx; + + gateclk_ops.enable = clk_gate_ops.enable; + gateclk_ops.disable = clk_gate_ops.disable; + + socfpga_clk->fixed_div = clks->fixed_div; + + if (clks->div_reg) + socfpga_clk->div_reg = regbase + clks->div_reg; + else + socfpga_clk->div_reg = NULL; + + socfpga_clk->width = clks->div_width; + socfpga_clk->shift = clks->div_offset; + + if (clks->bypass_reg) + socfpga_clk->bypass_reg = regbase + clks->bypass_reg; + else + socfpga_clk->bypass_reg = NULL; + socfpga_clk->bypass_shift = clks->bypass_shift; + + if (streq(clks->name, "cs_pdbg_clk")) + init.ops = &dbgclk_ops; + else + init.ops = &agilex_gateclk_ops; + + init.name = clks->name; + init.flags = clks->flags; + + init.num_parents = clks->num_parents; + init.parent_names = parent_name ? &parent_name : NULL; + if (init.parent_names == NULL) + init.parent_data = clks->parent_data; + socfpga_clk->hw.hw.init = &init; + + hw_clk = &socfpga_clk->hw.hw; + + ret = clk_hw_register(NULL, &socfpga_clk->hw.hw); + if (ret) { + kfree(socfpga_clk); + return ERR_PTR(ret); + } + return hw_clk; +} diff --git a/drivers/clk/socfpga/stratix10-clk.h b/drivers/clk/socfpga/stratix10-clk.h index 61eaf3a41fbb..75234e0783e1 100644 --- a/drivers/clk/socfpga/stratix10-clk.h +++ b/drivers/clk/socfpga/stratix10-clk.h @@ -85,4 +85,6 @@ struct clk_hw *s10_register_cnt_periph(const struct stratix10_perip_cnt_clock *c void __iomem *reg); struct clk_hw *s10_register_gate(const struct stratix10_gate_clock *clks, void __iomem *reg); +struct clk_hw *agilex_register_gate(const struct stratix10_gate_clock *clks, + void __iomem *reg); #endif /* __STRATIX10_CLK_H */ From dfd1427c3769ba51297777dbb296f1802d72dbf6 Mon Sep 17 00:00:00 2001 From: Dinh Nguyen Date: Thu, 10 Jun 2021 21:52:01 -0500 Subject: [PATCH 097/161] clk: agilex/stratix10/n5x: fix how the bypass_reg is handled If the bypass_reg is set, then we can return the bypass parent, however, if there is not a bypass_reg, we need to figure what the correct parent mux is. The previous code never handled the parent mux if there was a bypass_reg. Fixes: 80c6b7a0894f ("clk: socfpga: agilex: add clock driver for the Agilex platform") Cc: stable@vger.kernel.org Signed-off-by: Dinh Nguyen Link: https://lore.kernel.org/r/20210611025201.118799-4-dinguyen@kernel.org Signed-off-by: Stephen Boyd --- drivers/clk/socfpga/clk-periph-s10.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/clk/socfpga/clk-periph-s10.c b/drivers/clk/socfpga/clk-periph-s10.c index e5a5fef76df7..cbabde2b476b 100644 --- a/drivers/clk/socfpga/clk-periph-s10.c +++ b/drivers/clk/socfpga/clk-periph-s10.c @@ -64,16 +64,21 @@ static u8 clk_periclk_get_parent(struct clk_hw *hwclk) { struct socfpga_periph_clk *socfpgaclk = to_periph_clk(hwclk); u32 clk_src, mask; - u8 parent; + u8 parent = 0; + /* handle the bypass first */ if (socfpgaclk->bypass_reg) { mask = (0x1 << socfpgaclk->bypass_shift); parent = ((readl(socfpgaclk->bypass_reg) & mask) >> socfpgaclk->bypass_shift); - } else { + if (parent) + return parent; + } + + if (socfpgaclk->hw.reg) { clk_src = readl(socfpgaclk->hw.reg); parent = (clk_src >> CLK_MGR_FREE_SHIFT) & - CLK_MGR_FREE_MASK; + CLK_MGR_FREE_MASK; } return parent; } From ca1c667f4be935825fffb232a106c9d3f1c09b0b Mon Sep 17 00:00:00 2001 From: Taniya Das Date: Wed, 23 Jun 2021 17:27:51 +0530 Subject: [PATCH 098/161] clk: qcom: gcc: Add support for a new frequency for SC7280 There is a requirement to support 52MHz for qup clocks for bluetooth usecase, thus update the frequency table to support the frequency. Fixes: a3cc092196ef ("clk: qcom: Add Global Clock controller (GCC) driver for SC7280") Signed-off-by: Taniya Das Link: https://lore.kernel.org/r/1624449471-9984-1-git-send-email-tdas@codeaurora.org Signed-off-by: Stephen Boyd --- drivers/clk/qcom/gcc-sc7280.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/clk/qcom/gcc-sc7280.c b/drivers/clk/qcom/gcc-sc7280.c index ef734db316df..6cefcdc86990 100644 --- a/drivers/clk/qcom/gcc-sc7280.c +++ b/drivers/clk/qcom/gcc-sc7280.c @@ -716,6 +716,7 @@ static const struct freq_tbl ftbl_gcc_qupv3_wrap0_s2_clk_src[] = { F(29491200, P_GCC_GPLL0_OUT_EVEN, 1, 1536, 15625), F(32000000, P_GCC_GPLL0_OUT_EVEN, 1, 8, 75), F(48000000, P_GCC_GPLL0_OUT_EVEN, 1, 4, 25), + F(52174000, P_GCC_GPLL0_OUT_MAIN, 1, 2, 23), F(64000000, P_GCC_GPLL0_OUT_EVEN, 1, 16, 75), F(75000000, P_GCC_GPLL0_OUT_EVEN, 4, 0, 0), F(80000000, P_GCC_GPLL0_OUT_EVEN, 1, 4, 15), From 11fa5f8392eede198bc1218b97b03c063ee9d080 Mon Sep 17 00:00:00 2001 From: Martin Botka Date: Sat, 5 Jun 2021 14:10:37 +0200 Subject: [PATCH 099/161] dt-bindings: clk: qcom: gcc-sm6125: Document SM6125 GCC driver Document the newly added SM6125 GCC driver. Signed-off-by: Martin Botka Link: https://lore.kernel.org/r/20210605121040.282053-1-martin.botka@somainline.org Reviewed-by: Rob Herring Reviewed-by: Bjorn Andersson Signed-off-by: Stephen Boyd --- .../bindings/clock/qcom,gcc-sm6125.yaml | 72 ++++++ include/dt-bindings/clock/qcom,gcc-sm6125.h | 240 ++++++++++++++++++ 2 files changed, 312 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/qcom,gcc-sm6125.yaml create mode 100644 include/dt-bindings/clock/qcom,gcc-sm6125.h diff --git a/Documentation/devicetree/bindings/clock/qcom,gcc-sm6125.yaml b/Documentation/devicetree/bindings/clock/qcom,gcc-sm6125.yaml new file mode 100644 index 000000000000..ab12b391effc --- /dev/null +++ b/Documentation/devicetree/bindings/clock/qcom,gcc-sm6125.yaml @@ -0,0 +1,72 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/qcom,gcc-sm6125.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm Global Clock & Reset Controller Binding for SM6125 + +maintainers: + - Konrad Dybcio + +description: | + Qualcomm global clock control module which supports the clocks, resets and + power domains on SM6125. + + See also: + - dt-bindings/clock/qcom,gcc-sm6125.h + +properties: + compatible: + const: qcom,gcc-sm6125 + + clocks: + items: + - description: Board XO source + - description: Sleep clock source + + clock-names: + items: + - const: bi_tcxo + - const: sleep_clk + + '#clock-cells': + const: 1 + + '#reset-cells': + const: 1 + + '#power-domain-cells': + const: 1 + + reg: + maxItems: 1 + + protected-clocks: + description: + Protected clock specifier list as per common clock binding. + +required: + - compatible + - clocks + - clock-names + - reg + - '#clock-cells' + - '#reset-cells' + - '#power-domain-cells' + +additionalProperties: false + +examples: + - | + #include + clock-controller@1400000 { + compatible = "qcom,gcc-sm6125"; + reg = <0x01400000 0x1f0000>; + #clock-cells = <1>; + #reset-cells = <1>; + #power-domain-cells = <1>; + clock-names = "bi_tcxo", "sleep_clk"; + clocks = <&rpmcc RPM_SMD_XO_CLK_SRC>, <&sleep_clk>; + }; +... diff --git a/include/dt-bindings/clock/qcom,gcc-sm6125.h b/include/dt-bindings/clock/qcom,gcc-sm6125.h new file mode 100644 index 000000000000..08ea18086824 --- /dev/null +++ b/include/dt-bindings/clock/qcom,gcc-sm6125.h @@ -0,0 +1,240 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ +/* + * Copyright (c) 2021, Konrad Dybcio + */ + +#ifndef _DT_BINDINGS_CLK_QCOM_GCC_SM6125_H +#define _DT_BINDINGS_CLK_QCOM_GCC_SM6125_H + +#define GPLL0_OUT_AUX2 0 +#define GPLL0_OUT_MAIN 1 +#define GPLL6_OUT_MAIN 2 +#define GPLL7_OUT_MAIN 3 +#define GPLL8_OUT_MAIN 4 +#define GPLL9_OUT_MAIN 5 +#define GPLL0_OUT_EARLY 6 +#define GPLL3_OUT_EARLY 7 +#define GPLL4_OUT_MAIN 8 +#define GPLL5_OUT_MAIN 9 +#define GPLL6_OUT_EARLY 10 +#define GPLL7_OUT_EARLY 11 +#define GPLL8_OUT_EARLY 12 +#define GPLL9_OUT_EARLY 13 +#define GCC_AHB2PHY_CSI_CLK 14 +#define GCC_AHB2PHY_USB_CLK 15 +#define GCC_APC_VS_CLK 16 +#define GCC_BOOT_ROM_AHB_CLK 17 +#define GCC_CAMERA_AHB_CLK 18 +#define GCC_CAMERA_XO_CLK 19 +#define GCC_CAMSS_AHB_CLK_SRC 20 +#define GCC_CAMSS_CCI_AHB_CLK 21 +#define GCC_CAMSS_CCI_CLK 22 +#define GCC_CAMSS_CCI_CLK_SRC 23 +#define GCC_CAMSS_CPHY_CSID0_CLK 24 +#define GCC_CAMSS_CPHY_CSID1_CLK 25 +#define GCC_CAMSS_CPHY_CSID2_CLK 26 +#define GCC_CAMSS_CPHY_CSID3_CLK 27 +#define GCC_CAMSS_CPP_AHB_CLK 28 +#define GCC_CAMSS_CPP_AXI_CLK 29 +#define GCC_CAMSS_CPP_CLK 30 +#define GCC_CAMSS_CPP_CLK_SRC 31 +#define GCC_CAMSS_CPP_VBIF_AHB_CLK 32 +#define GCC_CAMSS_CSI0_AHB_CLK 33 +#define GCC_CAMSS_CSI0_CLK 34 +#define GCC_CAMSS_CSI0_CLK_SRC 35 +#define GCC_CAMSS_CSI0PHYTIMER_CLK 36 +#define GCC_CAMSS_CSI0PHYTIMER_CLK_SRC 37 +#define GCC_CAMSS_CSI0PIX_CLK 38 +#define GCC_CAMSS_CSI0RDI_CLK 39 +#define GCC_CAMSS_CSI1_AHB_CLK 40 +#define GCC_CAMSS_CSI1_CLK 41 +#define GCC_CAMSS_CSI1_CLK_SRC 42 +#define GCC_CAMSS_CSI1PHYTIMER_CLK 43 +#define GCC_CAMSS_CSI1PHYTIMER_CLK_SRC 44 +#define GCC_CAMSS_CSI1PIX_CLK 45 +#define GCC_CAMSS_CSI1RDI_CLK 46 +#define GCC_CAMSS_CSI2_AHB_CLK 47 +#define GCC_CAMSS_CSI2_CLK 48 +#define GCC_CAMSS_CSI2_CLK_SRC 49 +#define GCC_CAMSS_CSI2PHYTIMER_CLK 50 +#define GCC_CAMSS_CSI2PHYTIMER_CLK_SRC 51 +#define GCC_CAMSS_CSI2PIX_CLK 52 +#define GCC_CAMSS_CSI2RDI_CLK 53 +#define GCC_CAMSS_CSI3_AHB_CLK 54 +#define GCC_CAMSS_CSI3_CLK 55 +#define GCC_CAMSS_CSI3_CLK_SRC 56 +#define GCC_CAMSS_CSI3PIX_CLK 57 +#define GCC_CAMSS_CSI3RDI_CLK 58 +#define GCC_CAMSS_CSI_VFE0_CLK 59 +#define GCC_CAMSS_CSI_VFE1_CLK 60 +#define GCC_CAMSS_CSIPHY0_CLK 61 +#define GCC_CAMSS_CSIPHY1_CLK 62 +#define GCC_CAMSS_CSIPHY2_CLK 63 +#define GCC_CAMSS_CSIPHY_CLK_SRC 64 +#define GCC_CAMSS_GP0_CLK 65 +#define GCC_CAMSS_GP0_CLK_SRC 66 +#define GCC_CAMSS_GP1_CLK 67 +#define GCC_CAMSS_GP1_CLK_SRC 68 +#define GCC_CAMSS_ISPIF_AHB_CLK 69 +#define GCC_CAMSS_JPEG_AHB_CLK 70 +#define GCC_CAMSS_JPEG_AXI_CLK 71 +#define GCC_CAMSS_JPEG_CLK 72 +#define GCC_CAMSS_JPEG_CLK_SRC 73 +#define GCC_CAMSS_MCLK0_CLK 74 +#define GCC_CAMSS_MCLK0_CLK_SRC 75 +#define GCC_CAMSS_MCLK1_CLK 76 +#define GCC_CAMSS_MCLK1_CLK_SRC 77 +#define GCC_CAMSS_MCLK2_CLK 78 +#define GCC_CAMSS_MCLK2_CLK_SRC 79 +#define GCC_CAMSS_MCLK3_CLK 80 +#define GCC_CAMSS_MCLK3_CLK_SRC 81 +#define GCC_CAMSS_MICRO_AHB_CLK 82 +#define GCC_CAMSS_THROTTLE_NRT_AXI_CLK 83 +#define GCC_CAMSS_THROTTLE_RT_AXI_CLK 84 +#define GCC_CAMSS_TOP_AHB_CLK 85 +#define GCC_CAMSS_VFE0_AHB_CLK 86 +#define GCC_CAMSS_VFE0_CLK 87 +#define GCC_CAMSS_VFE0_CLK_SRC 88 +#define GCC_CAMSS_VFE0_STREAM_CLK 89 +#define GCC_CAMSS_VFE1_AHB_CLK 90 +#define GCC_CAMSS_VFE1_CLK 91 +#define GCC_CAMSS_VFE1_CLK_SRC 92 +#define GCC_CAMSS_VFE1_STREAM_CLK 93 +#define GCC_CAMSS_VFE_TSCTR_CLK 94 +#define GCC_CAMSS_VFE_VBIF_AHB_CLK 95 +#define GCC_CAMSS_VFE_VBIF_AXI_CLK 96 +#define GCC_CE1_AHB_CLK 97 +#define GCC_CE1_AXI_CLK 98 +#define GCC_CE1_CLK 99 +#define GCC_CFG_NOC_USB3_PRIM_AXI_CLK 100 +#define GCC_CPUSS_GNOC_CLK 101 +#define GCC_DISP_AHB_CLK 102 +#define GCC_DISP_GPLL0_DIV_CLK_SRC 103 +#define GCC_DISP_HF_AXI_CLK 104 +#define GCC_DISP_THROTTLE_CORE_CLK 105 +#define GCC_DISP_XO_CLK 106 +#define GCC_GP1_CLK 107 +#define GCC_GP1_CLK_SRC 108 +#define GCC_GP2_CLK 109 +#define GCC_GP2_CLK_SRC 110 +#define GCC_GP3_CLK 111 +#define GCC_GP3_CLK_SRC 112 +#define GCC_GPU_CFG_AHB_CLK 113 +#define GCC_GPU_GPLL0_CLK_SRC 114 +#define GCC_GPU_GPLL0_DIV_CLK_SRC 115 +#define GCC_GPU_MEMNOC_GFX_CLK 116 +#define GCC_GPU_SNOC_DVM_GFX_CLK 117 +#define GCC_GPU_THROTTLE_CORE_CLK 118 +#define GCC_GPU_THROTTLE_XO_CLK 119 +#define GCC_MSS_VS_CLK 120 +#define GCC_PDM2_CLK 121 +#define GCC_PDM2_CLK_SRC 122 +#define GCC_PDM_AHB_CLK 123 +#define GCC_PDM_XO4_CLK 124 +#define GCC_PRNG_AHB_CLK 125 +#define GCC_QMIP_CAMERA_NRT_AHB_CLK 126 +#define GCC_QMIP_CAMERA_RT_AHB_CLK 127 +#define GCC_QMIP_DISP_AHB_CLK 128 +#define GCC_QMIP_GPU_CFG_AHB_CLK 129 +#define GCC_QMIP_VIDEO_VCODEC_AHB_CLK 130 +#define GCC_QUPV3_WRAP0_CORE_2X_CLK 131 +#define GCC_QUPV3_WRAP0_CORE_CLK 132 +#define GCC_QUPV3_WRAP0_S0_CLK 133 +#define GCC_QUPV3_WRAP0_S0_CLK_SRC 134 +#define GCC_QUPV3_WRAP0_S1_CLK 135 +#define GCC_QUPV3_WRAP0_S1_CLK_SRC 136 +#define GCC_QUPV3_WRAP0_S2_CLK 137 +#define GCC_QUPV3_WRAP0_S2_CLK_SRC 138 +#define GCC_QUPV3_WRAP0_S3_CLK 139 +#define GCC_QUPV3_WRAP0_S3_CLK_SRC 140 +#define GCC_QUPV3_WRAP0_S4_CLK 141 +#define GCC_QUPV3_WRAP0_S4_CLK_SRC 142 +#define GCC_QUPV3_WRAP0_S5_CLK 143 +#define GCC_QUPV3_WRAP0_S5_CLK_SRC 144 +#define GCC_QUPV3_WRAP1_CORE_2X_CLK 145 +#define GCC_QUPV3_WRAP1_CORE_CLK 146 +#define GCC_QUPV3_WRAP1_S0_CLK 147 +#define GCC_QUPV3_WRAP1_S0_CLK_SRC 148 +#define GCC_QUPV3_WRAP1_S1_CLK 149 +#define GCC_QUPV3_WRAP1_S1_CLK_SRC 150 +#define GCC_QUPV3_WRAP1_S2_CLK 151 +#define GCC_QUPV3_WRAP1_S2_CLK_SRC 152 +#define GCC_QUPV3_WRAP1_S3_CLK 153 +#define GCC_QUPV3_WRAP1_S3_CLK_SRC 154 +#define GCC_QUPV3_WRAP1_S4_CLK 155 +#define GCC_QUPV3_WRAP1_S4_CLK_SRC 156 +#define GCC_QUPV3_WRAP1_S5_CLK 157 +#define GCC_QUPV3_WRAP1_S5_CLK_SRC 158 +#define GCC_QUPV3_WRAP_0_M_AHB_CLK 159 +#define GCC_QUPV3_WRAP_0_S_AHB_CLK 160 +#define GCC_QUPV3_WRAP_1_M_AHB_CLK 161 +#define GCC_QUPV3_WRAP_1_S_AHB_CLK 162 +#define GCC_SDCC1_AHB_CLK 163 +#define GCC_SDCC1_APPS_CLK 164 +#define GCC_SDCC1_APPS_CLK_SRC 165 +#define GCC_SDCC1_ICE_CORE_CLK 166 +#define GCC_SDCC1_ICE_CORE_CLK_SRC 167 +#define GCC_SDCC2_AHB_CLK 168 +#define GCC_SDCC2_APPS_CLK 169 +#define GCC_SDCC2_APPS_CLK_SRC 170 +#define GCC_SYS_NOC_CPUSS_AHB_CLK 171 +#define GCC_SYS_NOC_UFS_PHY_AXI_CLK 172 +#define GCC_SYS_NOC_USB3_PRIM_AXI_CLK 173 +#define GCC_UFS_PHY_AHB_CLK 174 +#define GCC_UFS_PHY_AXI_CLK 175 +#define GCC_UFS_PHY_AXI_CLK_SRC 176 +#define GCC_UFS_PHY_ICE_CORE_CLK 177 +#define GCC_UFS_PHY_ICE_CORE_CLK_SRC 178 +#define GCC_UFS_PHY_PHY_AUX_CLK 179 +#define GCC_UFS_PHY_PHY_AUX_CLK_SRC 180 +#define GCC_UFS_PHY_RX_SYMBOL_0_CLK 181 +#define GCC_UFS_PHY_TX_SYMBOL_0_CLK 182 +#define GCC_UFS_PHY_UNIPRO_CORE_CLK 183 +#define GCC_UFS_PHY_UNIPRO_CORE_CLK_SRC 184 +#define GCC_USB30_PRIM_MASTER_CLK 185 +#define GCC_USB30_PRIM_MASTER_CLK_SRC 186 +#define GCC_USB30_PRIM_MOCK_UTMI_CLK 187 +#define GCC_USB30_PRIM_MOCK_UTMI_CLK_SRC 188 +#define GCC_USB30_PRIM_SLEEP_CLK 189 +#define GCC_USB3_PRIM_PHY_AUX_CLK_SRC 190 +#define GCC_USB3_PRIM_PHY_COM_AUX_CLK 191 +#define GCC_USB3_PRIM_PHY_PIPE_CLK 192 +#define GCC_VDDA_VS_CLK 193 +#define GCC_VDDCX_VS_CLK 194 +#define GCC_VDDMX_VS_CLK 195 +#define GCC_VIDEO_AHB_CLK 196 +#define GCC_VIDEO_AXI0_CLK 197 +#define GCC_VIDEO_THROTTLE_CORE_CLK 198 +#define GCC_VIDEO_XO_CLK 199 +#define GCC_VS_CTRL_AHB_CLK 200 +#define GCC_VS_CTRL_CLK 201 +#define GCC_VS_CTRL_CLK_SRC 202 +#define GCC_VSENSOR_CLK_SRC 203 +#define GCC_WCSS_VS_CLK 204 +#define GCC_USB3_PRIM_CLKREF_CLK 205 +#define GCC_SYS_NOC_COMPUTE_SF_AXI_CLK 206 +#define GCC_BIMC_GPU_AXI_CLK 207 +#define GCC_UFS_MEM_CLKREF_CLK 208 + +/* GDSCs */ +#define USB30_PRIM_GDSC 0 +#define UFS_PHY_GDSC 1 +#define CAMSS_VFE0_GDSC 2 +#define CAMSS_VFE1_GDSC 3 +#define CAMSS_TOP_GDSC 4 +#define CAM_CPP_GDSC 5 +#define HLOS1_VOTE_TURING_MMU_TBU1_GDSC 6 +#define HLOS1_VOTE_MM_SNOC_MMU_TBU_RT_GDSC 7 +#define HLOS1_VOTE_MM_SNOC_MMU_TBU_NRT_GDSC 8 +#define HLOS1_VOTE_TURING_MMU_TBU0_GDSC 9 + +#define GCC_QUSB2PHY_PRIM_BCR 0 +#define GCC_QUSB2PHY_SEC_BCR 1 +#define GCC_UFS_PHY_BCR 2 +#define GCC_USB30_PRIM_BCR 3 +#define GCC_USB_PHY_CFG_AHB2PHY_BCR 4 +#define GCC_USB3_PHY_PRIM_SP0_BCR 5 +#define GCC_USB3PHY_PHY_PRIM_SP0_BCR 6 +#define GCC_CAMSS_MICRO_BCR 7 + +#endif From 4b8d6ae57cdf7ac50b473b89ec05613fc2c8143c Mon Sep 17 00:00:00 2001 From: Konrad Dybcio Date: Sat, 5 Jun 2021 14:10:38 +0200 Subject: [PATCH 100/161] clk: qcom: Add SM6125 (TRINKET) GCC driver Add the clocks supported in global clock controller, which clock the peripherals like BLSPs, SDCC, USB, MDSS etc. Register all the clocks to the clock framework for the clients to be able to request for them. Signed-off-by: Konrad Dybcio Signed-off-by: Martin Botka Link: https://lore.kernel.org/r/20210605121040.282053-2-martin.botka@somainline.org Reviewed-by: Bjorn Andersson [sboyd@kernel.org: Mark gcc_sm6125_hws array static] Signed-off-by: Stephen Boyd --- drivers/clk/qcom/Kconfig | 7 + drivers/clk/qcom/Makefile | 1 + drivers/clk/qcom/gcc-sm6125.c | 4190 +++++++++++++++++++++++++++++++++ 3 files changed, 4198 insertions(+) create mode 100644 drivers/clk/qcom/gcc-sm6125.c diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig index c84b2c896a27..dba1f266dc45 100644 --- a/drivers/clk/qcom/Kconfig +++ b/drivers/clk/qcom/Kconfig @@ -499,6 +499,13 @@ config SM_DISPCC_8250 Say Y if you want to support display devices and functionality such as splash screen. +config SM_GCC_6125 + tristate "SM6125 Global Clock Controller" + help + Support for the global clock controller on SM6125 devices. + Say Y if you want to use peripheral devices such as UART, + SPI, I2C, USB, SD/UFS, PCIe etc. + config SM_GCC_8150 tristate "SM8150 Global Clock Controller" help diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile index 9495bf6a18d0..0f1ad7a0b22f 100644 --- a/drivers/clk/qcom/Makefile +++ b/drivers/clk/qcom/Makefile @@ -75,6 +75,7 @@ obj-$(CONFIG_SDM_LPASSCC_845) += lpasscc-sdm845.o obj-$(CONFIG_SDM_VIDEOCC_845) += videocc-sdm845.o obj-$(CONFIG_SDX_GCC_55) += gcc-sdx55.o obj-$(CONFIG_SM_DISPCC_8250) += dispcc-sm8250.o +obj-$(CONFIG_SM_GCC_6125) += gcc-sm6125.o obj-$(CONFIG_SM_GCC_8150) += gcc-sm8150.o obj-$(CONFIG_SM_GCC_8250) += gcc-sm8250.o obj-$(CONFIG_SM_GCC_8350) += gcc-sm8350.o diff --git a/drivers/clk/qcom/gcc-sm6125.c b/drivers/clk/qcom/gcc-sm6125.c new file mode 100644 index 000000000000..543cfab7561f --- /dev/null +++ b/drivers/clk/qcom/gcc-sm6125.c @@ -0,0 +1,4190 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2021, Konrad Dybcio + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "clk-alpha-pll.h" +#include "clk-branch.h" +#include "clk-rcg.h" +#include "clk-regmap.h" +#include "common.h" +#include "gdsc.h" +#include "reset.h" + +enum { + P_BI_TCXO, + P_GPLL0_OUT_AUX2, + P_GPLL0_OUT_EARLY, + P_GPLL3_OUT_EARLY, + P_GPLL4_OUT_MAIN, + P_GPLL5_OUT_MAIN, + P_GPLL6_OUT_EARLY, + P_GPLL6_OUT_MAIN, + P_GPLL7_OUT_MAIN, + P_GPLL8_OUT_EARLY, + P_GPLL8_OUT_MAIN, + P_GPLL9_OUT_MAIN, + P_SLEEP_CLK, +}; + +static struct clk_alpha_pll gpll0_out_early = { + .offset = 0x0, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT], + .clkr = { + .enable_reg = 0x79000, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gpll0_out_early", + .parent_data = &(const struct clk_parent_data){ + .fw_name = "bi_tcxo", + }, + .num_parents = 1, + .ops = &clk_alpha_pll_ops, + }, + }, +}; + +static struct clk_fixed_factor gpll0_out_aux2 = { + .mult = 1, + .div = 2, + .hw.init = &(struct clk_init_data){ + .name = "gpll0_out_aux2", + .parent_hws = (const struct clk_hw*[]){ + &gpll0_out_early.clkr.hw, + }, + .num_parents = 1, + .ops = &clk_fixed_factor_ops, + }, +}; + +static struct clk_fixed_factor gpll0_out_main = { + .mult = 1, + .div = 2, + .hw.init = &(struct clk_init_data){ + .name = "gpll0_out_main", + .parent_hws = (const struct clk_hw*[]){ + &gpll0_out_early.clkr.hw, + }, + .num_parents = 1, + .ops = &clk_fixed_factor_ops, + }, +}; + +static struct clk_alpha_pll gpll3_out_early = { + .offset = 0x3000, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT], + .clkr = { + .enable_reg = 0x79000, + .enable_mask = BIT(3), + .hw.init = &(struct clk_init_data){ + .name = "gpll3_out_early", + .parent_data = &(const struct clk_parent_data){ + .fw_name = "bi_tcxo", + }, + .num_parents = 1, + .ops = &clk_alpha_pll_ops, + }, + }, +}; + +static struct clk_alpha_pll gpll4_out_main = { + .offset = 0x4000, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT], + .clkr = { + .enable_reg = 0x79000, + .enable_mask = BIT(4), + .hw.init = &(struct clk_init_data){ + .name = "gpll4_out_main", + .parent_data = &(const struct clk_parent_data){ + .fw_name = "bi_tcxo", + }, + .num_parents = 1, + .ops = &clk_alpha_pll_ops, + }, + }, +}; + +static struct clk_alpha_pll gpll5_out_main = { + .offset = 0x5000, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT], + .clkr = { + .enable_reg = 0x79000, + .enable_mask = BIT(5), + .hw.init = &(struct clk_init_data){ + .name = "gpll5_out_main", + .parent_data = &(const struct clk_parent_data){ + .fw_name = "bi_tcxo", + }, + .num_parents = 1, + .ops = &clk_alpha_pll_ops, + }, + }, +}; + +static struct clk_alpha_pll gpll6_out_early = { + .offset = 0x6000, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT], + .clkr = { + .enable_reg = 0x79000, + .enable_mask = BIT(6), + .hw.init = &(struct clk_init_data){ + .name = "gpll6_out_early", + .parent_data = &(const struct clk_parent_data){ + .fw_name = "bi_tcxo", + }, + .num_parents = 1, + .ops = &clk_alpha_pll_ops, + }, + }, +}; + +static struct clk_fixed_factor gpll6_out_main = { + .mult = 1, + .div = 2, + .hw.init = &(struct clk_init_data){ + .name = "gpll6_out_main", + .parent_hws = (const struct clk_hw*[]){ + &gpll6_out_early.clkr.hw, + }, + .num_parents = 1, + .ops = &clk_fixed_factor_ops, + }, +}; + +static struct clk_alpha_pll gpll7_out_early = { + .offset = 0x7000, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT], + .clkr = { + .enable_reg = 0x79000, + .enable_mask = BIT(7), + .hw.init = &(struct clk_init_data){ + .name = "gpll7_out_early", + .parent_data = &(const struct clk_parent_data){ + .fw_name = "bi_tcxo", + }, + .num_parents = 1, + .ops = &clk_alpha_pll_ops, + }, + }, +}; + +static struct clk_fixed_factor gpll7_out_main = { + .mult = 1, + .div = 2, + .hw.init = &(struct clk_init_data){ + .name = "gpll7_out_main", + .parent_hws = (const struct clk_hw*[]){ + &gpll7_out_early.clkr.hw, + }, + .num_parents = 1, + .ops = &clk_fixed_factor_ops, + }, +}; + +static struct clk_alpha_pll gpll8_out_early = { + .offset = 0x8000, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT], + .clkr = { + .enable_reg = 0x79000, + .enable_mask = BIT(8), + .hw.init = &(struct clk_init_data){ + .name = "gpll8_out_early", + .parent_data = &(const struct clk_parent_data){ + .fw_name = "bi_tcxo", + }, + .num_parents = 1, + .ops = &clk_alpha_pll_ops, + }, + }, +}; + +static struct clk_fixed_factor gpll8_out_main = { + .mult = 1, + .div = 2, + .hw.init = &(struct clk_init_data){ + .name = "gpll8_out_main", + .parent_hws = (const struct clk_hw*[]){ + &gpll8_out_early.clkr.hw, + }, + .num_parents = 1, + .ops = &clk_fixed_factor_ops, + }, +}; + +static struct clk_alpha_pll gpll9_out_early = { + .offset = 0x9000, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT], + .clkr = { + .enable_reg = 0x79000, + .enable_mask = BIT(9), + .hw.init = &(struct clk_init_data){ + .name = "gpll9_out_early", + .parent_data = &(const struct clk_parent_data){ + .fw_name = "bi_tcxo", + }, + .num_parents = 1, + .ops = &clk_alpha_pll_ops, + }, + }, +}; + +static struct clk_fixed_factor gpll9_out_main = { + .mult = 1, + .div = 2, + .hw.init = &(struct clk_init_data){ + .name = "gpll9_out_main", + .parent_hws = (const struct clk_hw*[]){ + &gpll9_out_early.clkr.hw, + }, + .num_parents = 1, + .ops = &clk_fixed_factor_ops, + }, +}; + +static const struct parent_map gcc_parent_map_0[] = { + { P_BI_TCXO, 0 }, + { P_GPLL0_OUT_EARLY, 1 }, + { P_GPLL0_OUT_AUX2, 2 }, +}; + +static const struct clk_parent_data gcc_parent_data_0[] = { + { .fw_name = "bi_tcxo" }, + { .hw = &gpll0_out_early.clkr.hw }, + { .hw = &gpll0_out_aux2.hw }, +}; + +static const struct parent_map gcc_parent_map_1[] = { + { P_BI_TCXO, 0 }, + { P_GPLL0_OUT_EARLY, 1 }, + { P_GPLL0_OUT_AUX2, 2 }, + { P_GPLL6_OUT_MAIN, 4 }, +}; + +static const struct clk_parent_data gcc_parent_data_1[] = { + { .fw_name = "bi_tcxo" }, + { .hw = &gpll0_out_early.clkr.hw }, + { .hw = &gpll0_out_aux2.hw }, + { .hw = &gpll6_out_main.hw }, +}; + +static const struct parent_map gcc_parent_map_2[] = { + { P_BI_TCXO, 0 }, + { P_GPLL0_OUT_EARLY, 1 }, + { P_GPLL0_OUT_AUX2, 2 }, + { P_SLEEP_CLK, 5 }, +}; + +static const struct clk_parent_data gcc_parent_data_2[] = { + { .fw_name = "bi_tcxo" }, + { .hw = &gpll0_out_early.clkr.hw }, + { .hw = &gpll0_out_aux2.hw }, + { .fw_name = "sleep_clk" }, +}; + +static const struct parent_map gcc_parent_map_3[] = { + { P_BI_TCXO, 0 }, + { P_GPLL0_OUT_EARLY, 1 }, + { P_GPLL5_OUT_MAIN, 3 }, + { P_GPLL4_OUT_MAIN, 5 }, +}; + +static const struct clk_parent_data gcc_parent_data_3[] = { + { .fw_name = "bi_tcxo" }, + { .hw = &gpll0_out_early.clkr.hw }, + { .hw = &gpll5_out_main.clkr.hw }, + { .hw = &gpll4_out_main.clkr.hw }, +}; + +static const struct parent_map gcc_parent_map_4[] = { + { P_BI_TCXO, 0 }, + { P_GPLL0_OUT_EARLY, 1 }, + { P_GPLL9_OUT_MAIN, 2 }, +}; + +static const struct clk_parent_data gcc_parent_data_4[] = { + { .fw_name = "bi_tcxo" }, + { .hw = &gpll0_out_early.clkr.hw }, + { .hw = &gpll9_out_main.hw }, +}; + +static const struct parent_map gcc_parent_map_5[] = { + { P_BI_TCXO, 0 }, + { P_GPLL0_OUT_EARLY, 1 }, +}; + +static const struct clk_parent_data gcc_parent_data_5[] = { + { .fw_name = "bi_tcxo" }, + { .hw = &gpll0_out_early.clkr.hw }, +}; + +static const struct parent_map gcc_parent_map_6[] = { + { P_BI_TCXO, 0 }, + { P_GPLL0_OUT_EARLY, 1 }, + { P_GPLL4_OUT_MAIN, 5 }, +}; + +static const struct clk_parent_data gcc_parent_data_6[] = { + { .fw_name = "bi_tcxo" }, + { .hw = &gpll0_out_early.clkr.hw }, + { .hw = &gpll4_out_main.clkr.hw }, +}; + +static const struct parent_map gcc_parent_map_7[] = { + { P_BI_TCXO, 0 }, + { P_GPLL0_OUT_EARLY, 1 }, + { P_SLEEP_CLK, 5 }, +}; + +static const struct clk_parent_data gcc_parent_data_7[] = { + { .fw_name = "bi_tcxo" }, + { .hw = &gpll0_out_early.clkr.hw }, + { .fw_name = "sleep_clk" }, +}; + +static const struct parent_map gcc_parent_map_8[] = { + { P_BI_TCXO, 0 }, + { P_GPLL0_OUT_EARLY, 1 }, + { P_GPLL9_OUT_MAIN, 2 }, + { P_GPLL6_OUT_EARLY, 3 }, + { P_GPLL8_OUT_MAIN, 4 }, + { P_GPLL4_OUT_MAIN, 5 }, + { P_GPLL3_OUT_EARLY, 6 }, +}; + +static const struct clk_parent_data gcc_parent_data_8[] = { + { .fw_name = "bi_tcxo" }, + { .hw = &gpll0_out_early.clkr.hw }, + { .hw = &gpll9_out_main.hw }, + { .hw = &gpll6_out_early.clkr.hw }, + { .hw = &gpll8_out_main.hw }, + { .hw = &gpll4_out_main.clkr.hw }, + { .hw = &gpll3_out_early.clkr.hw }, +}; + +static const struct parent_map gcc_parent_map_9[] = { + { P_BI_TCXO, 0 }, + { P_GPLL0_OUT_EARLY, 1 }, + { P_GPLL8_OUT_MAIN, 4 }, +}; + +static const struct clk_parent_data gcc_parent_data_9[] = { + { .fw_name = "bi_tcxo" }, + { .hw = &gpll0_out_early.clkr.hw }, + { .hw = &gpll8_out_main.hw }, +}; + +static const struct parent_map gcc_parent_map_10[] = { + { P_BI_TCXO, 0 }, + { P_GPLL0_OUT_EARLY, 1 }, + { P_GPLL9_OUT_MAIN, 2 }, + { P_GPLL6_OUT_EARLY, 3 }, + { P_GPLL8_OUT_MAIN, 4 }, + { P_GPLL3_OUT_EARLY, 6 }, +}; + +static const struct clk_parent_data gcc_parent_data_10[] = { + { .fw_name = "bi_tcxo" }, + { .hw = &gpll0_out_early.clkr.hw }, + { .hw = &gpll9_out_main.hw }, + { .hw = &gpll6_out_early.clkr.hw }, + { .hw = &gpll8_out_main.hw }, + { .hw = &gpll3_out_early.clkr.hw }, +}; + +static const struct parent_map gcc_parent_map_11[] = { + { P_BI_TCXO, 0 }, + { P_GPLL0_OUT_EARLY, 1 }, + { P_GPLL8_OUT_EARLY, 4 }, + { P_GPLL4_OUT_MAIN, 5 }, +}; + +static const struct clk_parent_data gcc_parent_data_11[] = { + { .fw_name = "bi_tcxo" }, + { .hw = &gpll0_out_early.clkr.hw }, + { .hw = &gpll8_out_early.clkr.hw }, + { .hw = &gpll4_out_main.clkr.hw }, +}; + +static const struct parent_map gcc_parent_map_12[] = { + { P_BI_TCXO, 0 }, + { P_GPLL0_OUT_EARLY, 1 }, + { P_GPLL6_OUT_EARLY, 3 }, + { P_GPLL8_OUT_EARLY, 4 }, +}; + +static const struct clk_parent_data gcc_parent_data_12[] = { + { .fw_name = "bi_tcxo" }, + { .hw = &gpll0_out_early.clkr.hw }, + { .hw = &gpll6_out_early.clkr.hw }, + { .hw = &gpll8_out_early.clkr.hw }, +}; + +static const struct parent_map gcc_parent_map_13[] = { + { P_BI_TCXO, 0 }, + { P_GPLL0_OUT_EARLY, 1 }, + { P_GPLL0_OUT_AUX2, 2 }, + { P_GPLL7_OUT_MAIN, 3 }, + { P_GPLL4_OUT_MAIN, 5 }, +}; + +static const struct clk_parent_data gcc_parent_data_13[] = { + { .fw_name = "bi_tcxo" }, + { .hw = &gpll0_out_early.clkr.hw }, + { .hw = &gpll0_out_aux2.hw }, + { .hw = &gpll7_out_main.hw }, + { .hw = &gpll4_out_main.clkr.hw }, +}; + +static const struct parent_map gcc_parent_map_14[] = { + { P_BI_TCXO, 0 }, + { P_SLEEP_CLK, 5 }, +}; + +static const struct clk_parent_data gcc_parent_data_14[] = { + { .fw_name = "bi_tcxo" }, + { .fw_name = "sleep_clk" }, +}; + +static const struct freq_tbl ftbl_gcc_camss_ahb_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + F(40000000, P_GPLL8_OUT_MAIN, 12, 0, 0), + F(80000000, P_GPLL8_OUT_MAIN, 6, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_camss_ahb_clk_src = { + .cmd_rcgr = 0x56088, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_9, + .freq_tbl = ftbl_gcc_camss_ahb_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_camss_ahb_clk_src", + .parent_data = gcc_parent_data_9, + .num_parents = ARRAY_SIZE(gcc_parent_data_9), + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_camss_cci_clk_src[] = { + F(37500000, P_GPLL0_OUT_EARLY, 16, 0, 0), + F(50000000, P_GPLL0_OUT_EARLY, 12, 0, 0), + F(100000000, P_GPLL0_OUT_EARLY, 6, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_camss_cci_clk_src = { + .cmd_rcgr = 0x52004, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_parent_map_5, + .freq_tbl = ftbl_gcc_camss_cci_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_camss_cci_clk_src", + .parent_data = gcc_parent_data_5, + .num_parents = ARRAY_SIZE(gcc_parent_data_5), + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_camss_cpp_clk_src[] = { + F(120000000, P_GPLL8_OUT_MAIN, 4, 0, 0), + F(240000000, P_GPLL8_OUT_MAIN, 2, 0, 0), + F(320000000, P_GPLL8_OUT_MAIN, 1.5, 0, 0), + F(480000000, P_GPLL8_OUT_MAIN, 1, 0, 0), + F(576000000, P_GPLL9_OUT_MAIN, 1, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_camss_cpp_clk_src = { + .cmd_rcgr = 0x560c8, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_10, + .freq_tbl = ftbl_gcc_camss_cpp_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_camss_cpp_clk_src", + .parent_data = gcc_parent_data_10, + .num_parents = ARRAY_SIZE(gcc_parent_data_10), + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_camss_csi0_clk_src[] = { + F(100000000, P_GPLL0_OUT_EARLY, 6, 0, 0), + F(200000000, P_GPLL0_OUT_EARLY, 3, 0, 0), + F(311000000, P_GPLL5_OUT_MAIN, 3, 0, 0), + F(403200000, P_GPLL4_OUT_MAIN, 2, 0, 0), + F(466500000, P_GPLL5_OUT_MAIN, 2, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_camss_csi0_clk_src = { + .cmd_rcgr = 0x55030, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_3, + .freq_tbl = ftbl_gcc_camss_csi0_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_camss_csi0_clk_src", + .parent_data = gcc_parent_data_3, + .num_parents = ARRAY_SIZE(gcc_parent_data_3), + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_camss_csi0phytimer_clk_src[] = { + F(100000000, P_GPLL0_OUT_EARLY, 6, 0, 0), + F(200000000, P_GPLL0_OUT_EARLY, 3, 0, 0), + F(268800000, P_GPLL4_OUT_MAIN, 3, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_camss_csi0phytimer_clk_src = { + .cmd_rcgr = 0x53004, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_6, + .freq_tbl = ftbl_gcc_camss_csi0phytimer_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_camss_csi0phytimer_clk_src", + .parent_data = gcc_parent_data_6, + .num_parents = ARRAY_SIZE(gcc_parent_data_6), + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 gcc_camss_csi1_clk_src = { + .cmd_rcgr = 0x5506c, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_3, + .freq_tbl = ftbl_gcc_camss_csi0_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_camss_csi1_clk_src", + .parent_data = gcc_parent_data_3, + .num_parents = ARRAY_SIZE(gcc_parent_data_3), + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 gcc_camss_csi1phytimer_clk_src = { + .cmd_rcgr = 0x53024, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_6, + .freq_tbl = ftbl_gcc_camss_csi0phytimer_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_camss_csi1phytimer_clk_src", + .parent_data = gcc_parent_data_6, + .num_parents = ARRAY_SIZE(gcc_parent_data_6), + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 gcc_camss_csi2_clk_src = { + .cmd_rcgr = 0x550a4, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_3, + .freq_tbl = ftbl_gcc_camss_csi0_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_camss_csi2_clk_src", + .parent_data = gcc_parent_data_3, + .num_parents = ARRAY_SIZE(gcc_parent_data_3), + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 gcc_camss_csi2phytimer_clk_src = { + .cmd_rcgr = 0x53044, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_6, + .freq_tbl = ftbl_gcc_camss_csi0phytimer_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_camss_csi2phytimer_clk_src", + .parent_data = gcc_parent_data_6, + .num_parents = ARRAY_SIZE(gcc_parent_data_6), + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 gcc_camss_csi3_clk_src = { + .cmd_rcgr = 0x550e0, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_3, + .freq_tbl = ftbl_gcc_camss_csi0_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_camss_csi3_clk_src", + .parent_data = gcc_parent_data_3, + .num_parents = ARRAY_SIZE(gcc_parent_data_3), + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_camss_csiphy_clk_src[] = { + F(100000000, P_GPLL0_OUT_EARLY, 6, 0, 0), + F(200000000, P_GPLL0_OUT_EARLY, 3, 0, 0), + F(268800000, P_GPLL4_OUT_MAIN, 3, 0, 0), + F(320000000, P_GPLL8_OUT_EARLY, 3, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_camss_csiphy_clk_src = { + .cmd_rcgr = 0x55000, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_11, + .freq_tbl = ftbl_gcc_camss_csiphy_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_camss_csiphy_clk_src", + .parent_data = gcc_parent_data_11, + .num_parents = ARRAY_SIZE(gcc_parent_data_11), + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_camss_gp0_clk_src[] = { + F(50000000, P_GPLL0_OUT_EARLY, 12, 0, 0), + F(100000000, P_GPLL0_OUT_EARLY, 6, 0, 0), + F(200000000, P_GPLL0_OUT_EARLY, 3, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_camss_gp0_clk_src = { + .cmd_rcgr = 0x50000, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_parent_map_7, + .freq_tbl = ftbl_gcc_camss_gp0_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_camss_gp0_clk_src", + .parent_data = gcc_parent_data_7, + .num_parents = ARRAY_SIZE(gcc_parent_data_7), + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 gcc_camss_gp1_clk_src = { + .cmd_rcgr = 0x5001c, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_parent_map_7, + .freq_tbl = ftbl_gcc_camss_gp0_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_camss_gp1_clk_src", + .parent_data = gcc_parent_data_7, + .num_parents = ARRAY_SIZE(gcc_parent_data_7), + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_camss_jpeg_clk_src[] = { + F(66666667, P_GPLL0_OUT_EARLY, 9, 0, 0), + F(133333333, P_GPLL0_OUT_EARLY, 4.5, 0, 0), + F(219428571, P_GPLL6_OUT_EARLY, 3.5, 0, 0), + F(320000000, P_GPLL8_OUT_EARLY, 3, 0, 0), + F(480000000, P_GPLL8_OUT_EARLY, 2, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_camss_jpeg_clk_src = { + .cmd_rcgr = 0x52028, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_12, + .freq_tbl = ftbl_gcc_camss_jpeg_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_camss_jpeg_clk_src", + .parent_data = gcc_parent_data_12, + .num_parents = ARRAY_SIZE(gcc_parent_data_12), + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_camss_mclk0_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + F(24000000, P_GPLL9_OUT_MAIN, 1, 1, 24), + F(64000000, P_GPLL9_OUT_MAIN, 1, 1, 9), + { } +}; + +static struct clk_rcg2 gcc_camss_mclk0_clk_src = { + .cmd_rcgr = 0x51000, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_parent_map_4, + .freq_tbl = ftbl_gcc_camss_mclk0_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_camss_mclk0_clk_src", + .parent_data = gcc_parent_data_4, + .num_parents = ARRAY_SIZE(gcc_parent_data_4), + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 gcc_camss_mclk1_clk_src = { + .cmd_rcgr = 0x5101c, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_parent_map_4, + .freq_tbl = ftbl_gcc_camss_mclk0_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_camss_mclk1_clk_src", + .parent_data = gcc_parent_data_4, + .num_parents = ARRAY_SIZE(gcc_parent_data_4), + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 gcc_camss_mclk2_clk_src = { + .cmd_rcgr = 0x51038, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_parent_map_4, + .freq_tbl = ftbl_gcc_camss_mclk0_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_camss_mclk2_clk_src", + .parent_data = gcc_parent_data_4, + .num_parents = ARRAY_SIZE(gcc_parent_data_4), + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 gcc_camss_mclk3_clk_src = { + .cmd_rcgr = 0x51054, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_parent_map_4, + .freq_tbl = ftbl_gcc_camss_mclk0_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_camss_mclk3_clk_src", + .parent_data = gcc_parent_data_4, + .num_parents = ARRAY_SIZE(gcc_parent_data_4), + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_camss_vfe0_clk_src[] = { + F(120000000, P_GPLL8_OUT_MAIN, 4, 0, 0), + F(256000000, P_GPLL6_OUT_EARLY, 3, 0, 0), + F(403200000, P_GPLL4_OUT_MAIN, 2, 0, 0), + F(480000000, P_GPLL8_OUT_MAIN, 1, 0, 0), + F(533000000, P_GPLL3_OUT_EARLY, 2, 0, 0), + F(576000000, P_GPLL9_OUT_MAIN, 1, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_camss_vfe0_clk_src = { + .cmd_rcgr = 0x54010, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_8, + .freq_tbl = ftbl_gcc_camss_vfe0_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_camss_vfe0_clk_src", + .parent_data = gcc_parent_data_8, + .num_parents = ARRAY_SIZE(gcc_parent_data_8), + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 gcc_camss_vfe1_clk_src = { + .cmd_rcgr = 0x54048, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_8, + .freq_tbl = ftbl_gcc_camss_vfe0_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_camss_vfe1_clk_src", + .parent_data = gcc_parent_data_8, + .num_parents = ARRAY_SIZE(gcc_parent_data_8), + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_gp1_clk_src[] = { + F(25000000, P_GPLL0_OUT_AUX2, 12, 0, 0), + F(50000000, P_GPLL0_OUT_AUX2, 6, 0, 0), + F(100000000, P_GPLL0_OUT_EARLY, 6, 0, 0), + F(200000000, P_GPLL0_OUT_EARLY, 3, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_gp1_clk_src = { + .cmd_rcgr = 0x4d004, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_parent_map_2, + .freq_tbl = ftbl_gcc_gp1_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_gp1_clk_src", + .parent_data = gcc_parent_data_2, + .num_parents = ARRAY_SIZE(gcc_parent_data_2), + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 gcc_gp2_clk_src = { + .cmd_rcgr = 0x4e004, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_parent_map_2, + .freq_tbl = ftbl_gcc_gp1_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_gp2_clk_src", + .parent_data = gcc_parent_data_2, + .num_parents = ARRAY_SIZE(gcc_parent_data_2), + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 gcc_gp3_clk_src = { + .cmd_rcgr = 0x4f004, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_parent_map_2, + .freq_tbl = ftbl_gcc_gp1_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_gp3_clk_src", + .parent_data = gcc_parent_data_2, + .num_parents = ARRAY_SIZE(gcc_parent_data_2), + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_pdm2_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + F(60000000, P_GPLL0_OUT_EARLY, 10, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_pdm2_clk_src = { + .cmd_rcgr = 0x20010, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_pdm2_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_pdm2_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = ARRAY_SIZE(gcc_parent_data_0), + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_qupv3_wrap0_s0_clk_src[] = { + F(7372800, P_GPLL0_OUT_AUX2, 1, 384, 15625), + F(14745600, P_GPLL0_OUT_AUX2, 1, 768, 15625), + F(19200000, P_BI_TCXO, 1, 0, 0), + F(29491200, P_GPLL0_OUT_AUX2, 1, 1536, 15625), + F(32000000, P_GPLL0_OUT_AUX2, 1, 8, 75), + F(48000000, P_GPLL0_OUT_AUX2, 1, 4, 25), + F(64000000, P_GPLL0_OUT_AUX2, 1, 16, 75), + F(75000000, P_GPLL0_OUT_AUX2, 4, 0, 0), + F(80000000, P_GPLL0_OUT_AUX2, 1, 4, 15), + F(96000000, P_GPLL0_OUT_AUX2, 1, 8, 25), + F(100000000, P_GPLL0_OUT_EARLY, 6, 0, 0), + F(102400000, P_GPLL0_OUT_AUX2, 1, 128, 375), + F(112000000, P_GPLL0_OUT_AUX2, 1, 28, 75), + F(117964800, P_GPLL0_OUT_AUX2, 1, 6144, 15625), + F(120000000, P_GPLL0_OUT_AUX2, 2.5, 0, 0), + F(128000000, P_GPLL6_OUT_MAIN, 3, 0, 0), + { } +}; + +static struct clk_init_data gcc_qupv3_wrap0_s0_clk_src_init = { + .name = "gcc_qupv3_wrap0_s0_clk_src", + .parent_data = gcc_parent_data_1, + .num_parents = ARRAY_SIZE(gcc_parent_data_1), + .ops = &clk_rcg2_ops, +}; + +static struct clk_rcg2 gcc_qupv3_wrap0_s0_clk_src = { + .cmd_rcgr = 0x1f148, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_1, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, + .clkr.hw.init = &gcc_qupv3_wrap0_s0_clk_src_init, +}; + +static struct clk_init_data gcc_qupv3_wrap0_s1_clk_src_init = { + .name = "gcc_qupv3_wrap0_s1_clk_src", + .parent_data = gcc_parent_data_1, + .num_parents = ARRAY_SIZE(gcc_parent_data_1), + .ops = &clk_rcg2_ops, +}; + +static struct clk_rcg2 gcc_qupv3_wrap0_s1_clk_src = { + .cmd_rcgr = 0x1f278, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_1, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, + .clkr.hw.init = &gcc_qupv3_wrap0_s1_clk_src_init, +}; + +static struct clk_init_data gcc_qupv3_wrap0_s2_clk_src_init = { + .name = "gcc_qupv3_wrap0_s2_clk_src", + .parent_data = gcc_parent_data_1, + .num_parents = ARRAY_SIZE(gcc_parent_data_1), + .ops = &clk_rcg2_ops, +}; + +static struct clk_rcg2 gcc_qupv3_wrap0_s2_clk_src = { + .cmd_rcgr = 0x1f3a8, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_1, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, + .clkr.hw.init = &gcc_qupv3_wrap0_s2_clk_src_init, +}; + +static struct clk_init_data gcc_qupv3_wrap0_s3_clk_src_init = { + .name = "gcc_qupv3_wrap0_s3_clk_src", + .parent_data = gcc_parent_data_1, + .num_parents = ARRAY_SIZE(gcc_parent_data_1), + .ops = &clk_rcg2_ops, +}; + +static struct clk_rcg2 gcc_qupv3_wrap0_s3_clk_src = { + .cmd_rcgr = 0x1f4d8, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_1, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, + .clkr.hw.init = &gcc_qupv3_wrap0_s3_clk_src_init, +}; + +static struct clk_init_data gcc_qupv3_wrap0_s4_clk_src_init = { + .name = "gcc_qupv3_wrap0_s4_clk_src", + .parent_data = gcc_parent_data_1, + .num_parents = ARRAY_SIZE(gcc_parent_data_1), + .ops = &clk_rcg2_ops, +}; + +static struct clk_rcg2 gcc_qupv3_wrap0_s4_clk_src = { + .cmd_rcgr = 0x1f608, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_1, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, + .clkr.hw.init = &gcc_qupv3_wrap0_s4_clk_src_init, +}; + +static struct clk_init_data gcc_qupv3_wrap0_s5_clk_src_init = { + .name = "gcc_qupv3_wrap0_s5_clk_src", + .parent_data = gcc_parent_data_1, + .num_parents = ARRAY_SIZE(gcc_parent_data_1), + .ops = &clk_rcg2_ops, +}; + +static struct clk_rcg2 gcc_qupv3_wrap0_s5_clk_src = { + .cmd_rcgr = 0x1f738, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_1, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, + .clkr.hw.init = &gcc_qupv3_wrap0_s5_clk_src_init, +}; + +static struct clk_init_data gcc_qupv3_wrap1_s0_clk_src_init = { + .name = "gcc_qupv3_wrap1_s0_clk_src", + .parent_data = gcc_parent_data_1, + .num_parents = ARRAY_SIZE(gcc_parent_data_1), + .ops = &clk_rcg2_ops, +}; + +static struct clk_rcg2 gcc_qupv3_wrap1_s0_clk_src = { + .cmd_rcgr = 0x39148, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_1, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, + .clkr.hw.init = &gcc_qupv3_wrap1_s0_clk_src_init, +}; + +static struct clk_init_data gcc_qupv3_wrap1_s1_clk_src_init = { + .name = "gcc_qupv3_wrap1_s1_clk_src", + .parent_data = gcc_parent_data_1, + .num_parents = ARRAY_SIZE(gcc_parent_data_1), + .ops = &clk_rcg2_ops, +}; + +static struct clk_rcg2 gcc_qupv3_wrap1_s1_clk_src = { + .cmd_rcgr = 0x39278, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_1, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, + .clkr.hw.init = &gcc_qupv3_wrap1_s1_clk_src_init, +}; + +static struct clk_init_data gcc_qupv3_wrap1_s2_clk_src_init = { + .name = "gcc_qupv3_wrap1_s2_clk_src", + .parent_data = gcc_parent_data_1, + .num_parents = ARRAY_SIZE(gcc_parent_data_1), + .ops = &clk_rcg2_ops, +}; + +static struct clk_rcg2 gcc_qupv3_wrap1_s2_clk_src = { + .cmd_rcgr = 0x393a8, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_1, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, + .clkr.hw.init = &gcc_qupv3_wrap1_s2_clk_src_init, +}; + +static struct clk_init_data gcc_qupv3_wrap1_s3_clk_src_init = { + .name = "gcc_qupv3_wrap1_s3_clk_src", + .parent_data = gcc_parent_data_1, + .num_parents = ARRAY_SIZE(gcc_parent_data_1), + .ops = &clk_rcg2_ops, +}; + +static struct clk_rcg2 gcc_qupv3_wrap1_s3_clk_src = { + .cmd_rcgr = 0x394d8, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_1, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, + .clkr.hw.init = &gcc_qupv3_wrap1_s3_clk_src_init, +}; + +static struct clk_init_data gcc_qupv3_wrap1_s4_clk_src_init = { + .name = "gcc_qupv3_wrap1_s4_clk_src", + .parent_data = gcc_parent_data_1, + .num_parents = ARRAY_SIZE(gcc_parent_data_1), + .ops = &clk_rcg2_ops, +}; + +static struct clk_rcg2 gcc_qupv3_wrap1_s4_clk_src = { + .cmd_rcgr = 0x39608, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_1, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, + .clkr.hw.init = &gcc_qupv3_wrap1_s4_clk_src_init, +}; + +static struct clk_init_data gcc_qupv3_wrap1_s5_clk_src_init = { + .name = "gcc_qupv3_wrap1_s5_clk_src", + .parent_data = gcc_parent_data_1, + .num_parents = ARRAY_SIZE(gcc_parent_data_1), + .ops = &clk_rcg2_ops, +}; + +static struct clk_rcg2 gcc_qupv3_wrap1_s5_clk_src = { + .cmd_rcgr = 0x39738, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_1, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, + .clkr.hw.init = &gcc_qupv3_wrap1_s5_clk_src_init, +}; + +static const struct freq_tbl ftbl_gcc_sdcc1_apps_clk_src[] = { + F(144000, P_BI_TCXO, 16, 3, 25), + F(400000, P_BI_TCXO, 12, 1, 4), + F(20000000, P_GPLL0_OUT_AUX2, 5, 1, 3), + F(25000000, P_GPLL0_OUT_AUX2, 6, 1, 2), + F(50000000, P_GPLL0_OUT_AUX2, 6, 0, 0), + F(100000000, P_GPLL0_OUT_AUX2, 3, 0, 0), + F(192000000, P_GPLL6_OUT_MAIN, 2, 0, 0), + F(384000000, P_GPLL6_OUT_MAIN, 1, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_sdcc1_apps_clk_src = { + .cmd_rcgr = 0x38028, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_parent_map_1, + .freq_tbl = ftbl_gcc_sdcc1_apps_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_sdcc1_apps_clk_src", + .parent_data = gcc_parent_data_1, + .num_parents = ARRAY_SIZE(gcc_parent_data_1), + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_sdcc1_ice_core_clk_src[] = { + F(75000000, P_GPLL0_OUT_AUX2, 4, 0, 0), + F(150000000, P_GPLL0_OUT_EARLY, 4, 0, 0), + F(200000000, P_GPLL0_OUT_EARLY, 3, 0, 0), + F(300000000, P_GPLL0_OUT_EARLY, 2, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_sdcc1_ice_core_clk_src = { + .cmd_rcgr = 0x38010, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_sdcc1_ice_core_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_sdcc1_ice_core_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = ARRAY_SIZE(gcc_parent_data_0), + .ops = &clk_rcg2_floor_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_sdcc2_apps_clk_src[] = { + F(400000, P_BI_TCXO, 12, 1, 4), + F(19200000, P_BI_TCXO, 1, 0, 0), + F(25000000, P_GPLL0_OUT_AUX2, 12, 0, 0), + F(50000000, P_GPLL0_OUT_AUX2, 6, 0, 0), + F(100000000, P_GPLL0_OUT_AUX2, 3, 0, 0), + F(202000000, P_GPLL7_OUT_MAIN, 2, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_sdcc2_apps_clk_src = { + .cmd_rcgr = 0x1e00c, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_parent_map_13, + .freq_tbl = ftbl_gcc_sdcc2_apps_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_sdcc2_apps_clk_src", + .parent_data = gcc_parent_data_13, + .num_parents = ARRAY_SIZE(gcc_parent_data_13), + .ops = &clk_rcg2_floor_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_ufs_phy_axi_clk_src[] = { + F(25000000, P_GPLL0_OUT_AUX2, 12, 0, 0), + F(50000000, P_GPLL0_OUT_AUX2, 6, 0, 0), + F(100000000, P_GPLL0_OUT_EARLY, 6, 0, 0), + F(200000000, P_GPLL0_OUT_EARLY, 3, 0, 0), + F(240000000, P_GPLL0_OUT_EARLY, 2.5, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_ufs_phy_axi_clk_src = { + .cmd_rcgr = 0x45020, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_ufs_phy_axi_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_ufs_phy_axi_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = ARRAY_SIZE(gcc_parent_data_0), + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_ufs_phy_ice_core_clk_src[] = { + F(37500000, P_GPLL0_OUT_AUX2, 8, 0, 0), + F(75000000, P_GPLL0_OUT_AUX2, 4, 0, 0), + F(150000000, P_GPLL0_OUT_EARLY, 4, 0, 0), + F(300000000, P_GPLL0_OUT_EARLY, 2, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_ufs_phy_ice_core_clk_src = { + .cmd_rcgr = 0x45048, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_ufs_phy_ice_core_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_ufs_phy_ice_core_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = ARRAY_SIZE(gcc_parent_data_0), + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_ufs_phy_phy_aux_clk_src[] = { + F(9600000, P_BI_TCXO, 2, 0, 0), + F(19200000, P_BI_TCXO, 1, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_ufs_phy_phy_aux_clk_src = { + .cmd_rcgr = 0x4507c, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_ufs_phy_phy_aux_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_ufs_phy_phy_aux_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = ARRAY_SIZE(gcc_parent_data_0), + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_ufs_phy_unipro_core_clk_src[] = { + F(37500000, P_GPLL0_OUT_AUX2, 8, 0, 0), + F(75000000, P_GPLL0_OUT_EARLY, 8, 0, 0), + F(150000000, P_GPLL0_OUT_EARLY, 4, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_ufs_phy_unipro_core_clk_src = { + .cmd_rcgr = 0x45060, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_ufs_phy_unipro_core_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_ufs_phy_unipro_core_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = ARRAY_SIZE(gcc_parent_data_0), + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_usb30_prim_master_clk_src[] = { + F(66666667, P_GPLL0_OUT_AUX2, 4.5, 0, 0), + F(133333333, P_GPLL0_OUT_EARLY, 4.5, 0, 0), + F(200000000, P_GPLL0_OUT_EARLY, 3, 0, 0), + F(240000000, P_GPLL0_OUT_EARLY, 2.5, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_usb30_prim_master_clk_src = { + .cmd_rcgr = 0x1a01c, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_usb30_prim_master_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_usb30_prim_master_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = ARRAY_SIZE(gcc_parent_data_0), + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_usb30_prim_mock_utmi_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + F(20000000, P_GPLL0_OUT_AUX2, 15, 0, 0), + F(40000000, P_GPLL0_OUT_AUX2, 7.5, 0, 0), + F(60000000, P_GPLL0_OUT_EARLY, 10, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_usb30_prim_mock_utmi_clk_src = { + .cmd_rcgr = 0x1a034, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_usb30_prim_mock_utmi_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_usb30_prim_mock_utmi_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = ARRAY_SIZE(gcc_parent_data_0), + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_usb3_prim_phy_aux_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_usb3_prim_phy_aux_clk_src = { + .cmd_rcgr = 0x1a060, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_14, + .freq_tbl = ftbl_gcc_usb3_prim_phy_aux_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_usb3_prim_phy_aux_clk_src", + .parent_data = gcc_parent_data_14, + .num_parents = ARRAY_SIZE(gcc_parent_data_14), + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 gcc_vs_ctrl_clk_src = { + .cmd_rcgr = 0x42030, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_5, + .freq_tbl = ftbl_gcc_usb3_prim_phy_aux_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_vs_ctrl_clk_src", + .parent_data = gcc_parent_data_5, + .num_parents = ARRAY_SIZE(gcc_parent_data_5), + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_vsensor_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + F(400000000, P_GPLL0_OUT_EARLY, 1.5, 0, 0), + F(600000000, P_GPLL0_OUT_EARLY, 1, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_vsensor_clk_src = { + .cmd_rcgr = 0x42018, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_5, + .freq_tbl = ftbl_gcc_vsensor_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_vsensor_clk_src", + .parent_data = gcc_parent_data_5, + .num_parents = ARRAY_SIZE(gcc_parent_data_5), + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_branch gcc_ahb2phy_csi_clk = { + .halt_reg = 0x1d004, + .halt_check = BRANCH_HALT, + .hwcg_reg = 0x1d004, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x1d004, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_ahb2phy_csi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ahb2phy_usb_clk = { + .halt_reg = 0x1d008, + .halt_check = BRANCH_HALT, + .hwcg_reg = 0x1d008, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x1d008, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_ahb2phy_usb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_apc_vs_clk = { + .halt_reg = 0x4204c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x4204c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_apc_vs_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_vsensor_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_bimc_gpu_axi_clk = { + .halt_reg = 0x71154, + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x71154, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_bimc_gpu_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_boot_rom_ahb_clk = { + .halt_reg = 0x23004, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x23004, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x79004, + .enable_mask = BIT(10), + .hw.init = &(struct clk_init_data){ + .name = "gcc_boot_rom_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camera_ahb_clk = { + .halt_reg = 0x17008, + .halt_check = BRANCH_HALT_DELAY, + .hwcg_reg = 0x17008, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x17008, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camera_ahb_clk", + .flags = CLK_IS_CRITICAL, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camera_xo_clk = { + .halt_reg = 0x17028, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x17028, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camera_xo_clk", + .flags = CLK_IS_CRITICAL, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_cci_ahb_clk = { + .halt_reg = 0x52020, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x52020, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camss_cci_ahb_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_camss_ahb_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_cci_clk = { + .halt_reg = 0x5201c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x5201c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camss_cci_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_camss_cci_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_cphy_csid0_clk = { + .halt_reg = 0x5504c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x5504c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camss_cphy_csid0_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_camss_csiphy_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_cphy_csid1_clk = { + .halt_reg = 0x55088, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x55088, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camss_cphy_csid1_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_camss_csiphy_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_cphy_csid2_clk = { + .halt_reg = 0x550c0, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x550c0, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camss_cphy_csid2_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_camss_csiphy_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_cphy_csid3_clk = { + .halt_reg = 0x550fc, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x550fc, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camss_cphy_csid3_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_camss_csiphy_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_cpp_ahb_clk = { + .halt_reg = 0x560e8, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x560e8, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camss_cpp_ahb_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_camss_ahb_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_cpp_axi_clk = { + .halt_reg = 0x560f4, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x560f4, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camss_cpp_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_cpp_clk = { + .halt_reg = 0x560e0, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x560e0, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camss_cpp_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_camss_cpp_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_cpp_vbif_ahb_clk = { + .halt_reg = 0x560f0, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x560f0, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camss_cpp_vbif_ahb_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_camss_ahb_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_csi0_ahb_clk = { + .halt_reg = 0x55050, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x55050, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camss_csi0_ahb_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_camss_ahb_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_csi0_clk = { + .halt_reg = 0x55048, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x55048, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camss_csi0_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_camss_csi0_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_csi0phytimer_clk = { + .halt_reg = 0x5301c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x5301c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camss_csi0phytimer_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_camss_csi0phytimer_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_csi0pix_clk = { + .halt_reg = 0x55060, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x55060, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camss_csi0pix_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_camss_csi0_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_csi0rdi_clk = { + .halt_reg = 0x55058, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x55058, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camss_csi0rdi_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_camss_csi0_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_csi1_ahb_clk = { + .halt_reg = 0x5508c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x5508c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camss_csi1_ahb_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_camss_ahb_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_csi1_clk = { + .halt_reg = 0x55084, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x55084, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camss_csi1_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_camss_csi1_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_csi1phytimer_clk = { + .halt_reg = 0x5303c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x5303c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camss_csi1phytimer_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_camss_csi1phytimer_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_csi1pix_clk = { + .halt_reg = 0x5509c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x5509c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camss_csi1pix_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_camss_csi1_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_csi1rdi_clk = { + .halt_reg = 0x55094, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x55094, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camss_csi1rdi_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_camss_csi1_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_csi2_ahb_clk = { + .halt_reg = 0x550c4, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x550c4, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camss_csi2_ahb_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_camss_ahb_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_csi2_clk = { + .halt_reg = 0x550bc, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x550bc, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camss_csi2_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_camss_csi2_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_csi2phytimer_clk = { + .halt_reg = 0x5305c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x5305c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camss_csi2phytimer_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_camss_csi2phytimer_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_csi2pix_clk = { + .halt_reg = 0x550d4, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x550d4, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camss_csi2pix_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_camss_csi2_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_csi2rdi_clk = { + .halt_reg = 0x550cc, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x550cc, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camss_csi2rdi_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_camss_csi2_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_csi3_ahb_clk = { + .halt_reg = 0x55100, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x55100, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camss_csi3_ahb_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_camss_ahb_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_csi3_clk = { + .halt_reg = 0x550f8, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x550f8, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camss_csi3_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_camss_csi3_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_csi3pix_clk = { + .halt_reg = 0x55110, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x55110, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camss_csi3pix_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_camss_csi3_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_csi3rdi_clk = { + .halt_reg = 0x55108, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x55108, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camss_csi3rdi_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_camss_csi3_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_csi_vfe0_clk = { + .halt_reg = 0x54074, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x54074, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camss_csi_vfe0_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_camss_vfe0_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_csi_vfe1_clk = { + .halt_reg = 0x54080, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x54080, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camss_csi_vfe1_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_camss_vfe1_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_csiphy0_clk = { + .halt_reg = 0x55018, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x55018, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camss_csiphy0_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_camss_csiphy_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_csiphy1_clk = { + .halt_reg = 0x5501c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x5501c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camss_csiphy1_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_camss_csiphy_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_csiphy2_clk = { + .halt_reg = 0x55020, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x55020, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camss_csiphy2_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_camss_csiphy_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_gp0_clk = { + .halt_reg = 0x50018, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x50018, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camss_gp0_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_camss_gp0_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_gp1_clk = { + .halt_reg = 0x50034, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x50034, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camss_gp1_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_camss_gp1_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_ispif_ahb_clk = { + .halt_reg = 0x540a4, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x540a4, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camss_ispif_ahb_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_camss_ahb_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_jpeg_ahb_clk = { + .halt_reg = 0x52048, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x52048, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camss_jpeg_ahb_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_camss_ahb_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_jpeg_axi_clk = { + .halt_reg = 0x5204c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x5204c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camss_jpeg_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_jpeg_clk = { + .halt_reg = 0x52040, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x52040, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camss_jpeg_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_camss_jpeg_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_mclk0_clk = { + .halt_reg = 0x51018, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x51018, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camss_mclk0_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_camss_mclk0_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_mclk1_clk = { + .halt_reg = 0x51034, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x51034, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camss_mclk1_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_camss_mclk1_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_mclk2_clk = { + .halt_reg = 0x51050, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x51050, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camss_mclk2_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_camss_mclk2_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_mclk3_clk = { + .halt_reg = 0x5106c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x5106c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camss_mclk3_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_camss_mclk3_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_micro_ahb_clk = { + .halt_reg = 0x560b0, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x560b0, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camss_micro_ahb_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_camss_ahb_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_throttle_nrt_axi_clk = { + .halt_reg = 0x560a4, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x79004, + .enable_mask = BIT(27), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camss_throttle_nrt_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_throttle_rt_axi_clk = { + .halt_reg = 0x560a8, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x79004, + .enable_mask = BIT(26), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camss_throttle_rt_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_top_ahb_clk = { + .halt_reg = 0x560a0, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x560a0, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camss_top_ahb_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_camss_ahb_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_vfe0_ahb_clk = { + .halt_reg = 0x54034, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x54034, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camss_vfe0_ahb_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_camss_ahb_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_vfe0_clk = { + .halt_reg = 0x54028, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x54028, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camss_vfe0_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_camss_vfe0_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_vfe0_stream_clk = { + .halt_reg = 0x54030, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x54030, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camss_vfe0_stream_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_camss_vfe0_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_vfe1_ahb_clk = { + .halt_reg = 0x5406c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x5406c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camss_vfe1_ahb_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_camss_ahb_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_vfe1_clk = { + .halt_reg = 0x54060, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x54060, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camss_vfe1_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_camss_vfe1_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_vfe1_stream_clk = { + .halt_reg = 0x54068, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x54068, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camss_vfe1_stream_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_camss_vfe1_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_vfe_tsctr_clk = { + .halt_reg = 0x5409c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x5409c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camss_vfe_tsctr_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_vfe_vbif_ahb_clk = { + .halt_reg = 0x5408c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x5408c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camss_vfe_vbif_ahb_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_camss_ahb_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_vfe_vbif_axi_clk = { + .halt_reg = 0x54090, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x54090, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camss_vfe_vbif_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ce1_ahb_clk = { + .halt_reg = 0x2700c, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x2700c, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x79004, + .enable_mask = BIT(3), + .hw.init = &(struct clk_init_data){ + .name = "gcc_ce1_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ce1_axi_clk = { + .halt_reg = 0x27008, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x79004, + .enable_mask = BIT(4), + .hw.init = &(struct clk_init_data){ + .name = "gcc_ce1_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ce1_clk = { + .halt_reg = 0x27004, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x79004, + .enable_mask = BIT(5), + .hw.init = &(struct clk_init_data){ + .name = "gcc_ce1_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_cfg_noc_usb3_prim_axi_clk = { + .halt_reg = 0x1a084, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1a084, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_cfg_noc_usb3_prim_axi_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_usb30_prim_master_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_cpuss_gnoc_clk = { + .halt_reg = 0x2b004, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x2b004, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x79004, + .enable_mask = BIT(22), + .hw.init = &(struct clk_init_data){ + .name = "gcc_cpuss_gnoc_clk", + .flags = CLK_IS_CRITICAL, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_disp_ahb_clk = { + .halt_reg = 0x1700c, + .halt_check = BRANCH_HALT, + .hwcg_reg = 0x1700c, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x1700c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_disp_ahb_clk", + .flags = CLK_IS_CRITICAL, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_disp_gpll0_div_clk_src = { + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x79004, + .enable_mask = BIT(20), + .hw.init = &(struct clk_init_data){ + .name = "gcc_disp_gpll0_div_clk_src", + .parent_hws = (const struct clk_hw*[]){ + &gpll0_out_early.clkr.hw, + }, + .num_parents = 1, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_disp_hf_axi_clk = { + .halt_reg = 0x17020, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x17020, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_disp_hf_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_disp_throttle_core_clk = { + .halt_reg = 0x17064, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x7900c, + .enable_mask = BIT(5), + .hw.init = &(struct clk_init_data){ + .name = "gcc_disp_throttle_core_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_disp_xo_clk = { + .halt_reg = 0x1702c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1702c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_disp_xo_clk", + .flags = CLK_IS_CRITICAL, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_gp1_clk = { + .halt_reg = 0x4d000, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x4d000, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_gp1_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_gp1_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_gp2_clk = { + .halt_reg = 0x4e000, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x4e000, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_gp2_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_gp2_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_gp3_clk = { + .halt_reg = 0x4f000, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x4f000, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_gp3_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_gp3_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_gpu_cfg_ahb_clk = { + .halt_reg = 0x36004, + .halt_check = BRANCH_HALT, + .hwcg_reg = 0x36004, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x36004, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_gpu_cfg_ahb_clk", + .flags = CLK_IS_CRITICAL, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_gpu_gpll0_clk_src = { + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x79004, + .enable_mask = BIT(15), + .hw.init = &(struct clk_init_data){ + .name = "gcc_gpu_gpll0_clk_src", + .parent_hws = (const struct clk_hw*[]){ + &gpll0_out_early.clkr.hw, + }, + .num_parents = 1, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_gpu_gpll0_div_clk_src = { + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x79004, + .enable_mask = BIT(16), + .hw.init = &(struct clk_init_data){ + .name = "gcc_gpu_gpll0_div_clk_src", + .parent_hws = (const struct clk_hw*[]){ + &gpll0_out_aux2.hw, + }, + .num_parents = 1, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_gpu_memnoc_gfx_clk = { + .halt_reg = 0x3600c, + .halt_check = BRANCH_VOTED, + .clkr = { + .enable_reg = 0x3600c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_gpu_memnoc_gfx_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_gpu_snoc_dvm_gfx_clk = { + .halt_reg = 0x36018, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x36018, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_gpu_snoc_dvm_gfx_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_gpu_throttle_core_clk = { + .halt_reg = 0x36048, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x79004, + .enable_mask = BIT(31), + .hw.init = &(struct clk_init_data){ + .name = "gcc_gpu_throttle_core_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_gpu_throttle_xo_clk = { + .halt_reg = 0x36044, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x36044, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_gpu_throttle_xo_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_mss_vs_clk = { + .halt_reg = 0x42048, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x42048, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_mss_vs_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_vsensor_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pdm2_clk = { + .halt_reg = 0x2000c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x2000c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_pdm2_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_pdm2_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pdm_ahb_clk = { + .halt_reg = 0x20004, + .halt_check = BRANCH_HALT, + .hwcg_reg = 0x20004, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x20004, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_pdm_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pdm_xo4_clk = { + .halt_reg = 0x20008, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x20008, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_pdm_xo4_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_prng_ahb_clk = { + .halt_reg = 0x21004, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x21004, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x79004, + .enable_mask = BIT(13), + .hw.init = &(struct clk_init_data){ + .name = "gcc_prng_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qmip_camera_nrt_ahb_clk = { + .halt_reg = 0x17014, + .halt_check = BRANCH_HALT, + .hwcg_reg = 0x17014, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x7900c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qmip_camera_nrt_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qmip_camera_rt_ahb_clk = { + .halt_reg = 0x17060, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x17060, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x7900c, + .enable_mask = BIT(2), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qmip_camera_rt_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qmip_disp_ahb_clk = { + .halt_reg = 0x17018, + .halt_check = BRANCH_HALT, + .hwcg_reg = 0x17018, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x7900c, + .enable_mask = BIT(1), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qmip_disp_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qmip_gpu_cfg_ahb_clk = { + .halt_reg = 0x36040, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x36040, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x7900c, + .enable_mask = BIT(4), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qmip_gpu_cfg_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qmip_video_vcodec_ahb_clk = { + .halt_reg = 0x17010, + .halt_check = BRANCH_HALT, + .hwcg_reg = 0x17010, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x79004, + .enable_mask = BIT(25), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qmip_video_vcodec_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap0_core_2x_clk = { + .halt_reg = 0x1f014, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x7900c, + .enable_mask = BIT(9), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap0_core_2x_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap0_core_clk = { + .halt_reg = 0x1f00c, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x7900c, + .enable_mask = BIT(8), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap0_core_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap0_s0_clk = { + .halt_reg = 0x1f144, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x7900c, + .enable_mask = BIT(10), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap0_s0_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_qupv3_wrap0_s0_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap0_s1_clk = { + .halt_reg = 0x1f274, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x7900c, + .enable_mask = BIT(11), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap0_s1_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_qupv3_wrap0_s1_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap0_s2_clk = { + .halt_reg = 0x1f3a4, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x7900c, + .enable_mask = BIT(12), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap0_s2_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_qupv3_wrap0_s2_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap0_s3_clk = { + .halt_reg = 0x1f4d4, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x7900c, + .enable_mask = BIT(13), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap0_s3_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_qupv3_wrap0_s3_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap0_s4_clk = { + .halt_reg = 0x1f604, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x7900c, + .enable_mask = BIT(14), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap0_s4_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_qupv3_wrap0_s4_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap0_s5_clk = { + .halt_reg = 0x1f734, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x7900c, + .enable_mask = BIT(15), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap0_s5_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_qupv3_wrap0_s5_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap1_core_2x_clk = { + .halt_reg = 0x39014, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x7900c, + .enable_mask = BIT(18), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap1_core_2x_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap1_core_clk = { + .halt_reg = 0x3900c, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x7900c, + .enable_mask = BIT(19), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap1_core_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap1_s0_clk = { + .halt_reg = 0x39144, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x7900c, + .enable_mask = BIT(22), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap1_s0_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_qupv3_wrap1_s0_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap1_s1_clk = { + .halt_reg = 0x39274, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x7900c, + .enable_mask = BIT(23), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap1_s1_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_qupv3_wrap1_s1_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap1_s2_clk = { + .halt_reg = 0x393a4, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x7900c, + .enable_mask = BIT(24), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap1_s2_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_qupv3_wrap1_s2_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap1_s3_clk = { + .halt_reg = 0x394d4, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x7900c, + .enable_mask = BIT(25), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap1_s3_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_qupv3_wrap1_s3_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap1_s4_clk = { + .halt_reg = 0x39604, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x7900c, + .enable_mask = BIT(26), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap1_s4_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_qupv3_wrap1_s4_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap1_s5_clk = { + .halt_reg = 0x39734, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x7900c, + .enable_mask = BIT(27), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap1_s5_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_qupv3_wrap1_s5_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap_0_m_ahb_clk = { + .halt_reg = 0x1f004, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x7900c, + .enable_mask = BIT(6), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap_0_m_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap_0_s_ahb_clk = { + .halt_reg = 0x1f008, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x1f008, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x7900c, + .enable_mask = BIT(7), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap_0_s_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap_1_m_ahb_clk = { + .halt_reg = 0x39004, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x7900c, + .enable_mask = BIT(20), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap_1_m_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap_1_s_ahb_clk = { + .halt_reg = 0x39008, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x39008, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x7900c, + .enable_mask = BIT(21), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap_1_s_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_sdcc1_ahb_clk = { + .halt_reg = 0x38008, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x38008, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_sdcc1_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_sdcc1_apps_clk = { + .halt_reg = 0x38004, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x38004, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_sdcc1_apps_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_sdcc1_apps_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_sdcc1_ice_core_clk = { + .halt_reg = 0x3800c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x3800c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_sdcc1_ice_core_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_sdcc1_ice_core_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_sdcc2_ahb_clk = { + .halt_reg = 0x1e008, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1e008, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_sdcc2_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_sdcc2_apps_clk = { + .halt_reg = 0x1e004, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1e004, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_sdcc2_apps_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_sdcc2_apps_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_sys_noc_compute_sf_axi_clk = { + .halt_reg = 0x1050c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1050c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_sys_noc_compute_sf_axi_clk", + .flags = CLK_IS_CRITICAL, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_sys_noc_cpuss_ahb_clk = { + .halt_reg = 0x2b06c, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x79004, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_sys_noc_cpuss_ahb_clk", + .flags = CLK_IS_CRITICAL, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_sys_noc_ufs_phy_axi_clk = { + .halt_reg = 0x45098, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x45098, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_sys_noc_ufs_phy_axi_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_ufs_phy_axi_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_sys_noc_usb3_prim_axi_clk = { + .halt_reg = 0x1a080, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1a080, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_sys_noc_usb3_prim_axi_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_usb30_prim_master_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ufs_mem_clkref_clk = { + .halt_reg = 0x8c000, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x8c000, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_ufs_mem_clkref_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ufs_phy_ahb_clk = { + .halt_reg = 0x45014, + .halt_check = BRANCH_HALT, + .hwcg_reg = 0x45014, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x45014, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_ufs_phy_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ufs_phy_axi_clk = { + .halt_reg = 0x45010, + .halt_check = BRANCH_HALT, + .hwcg_reg = 0x45010, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x45010, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_ufs_phy_axi_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_ufs_phy_axi_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ufs_phy_ice_core_clk = { + .halt_reg = 0x45044, + .halt_check = BRANCH_HALT, + .hwcg_reg = 0x45044, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x45044, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_ufs_phy_ice_core_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_ufs_phy_ice_core_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ufs_phy_phy_aux_clk = { + .halt_reg = 0x45078, + .halt_check = BRANCH_HALT, + .hwcg_reg = 0x45078, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x45078, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_ufs_phy_phy_aux_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_ufs_phy_phy_aux_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ufs_phy_rx_symbol_0_clk = { + .halt_reg = 0x4501c, + .halt_check = BRANCH_HALT_SKIP, + .clkr = { + .enable_reg = 0x4501c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_ufs_phy_rx_symbol_0_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ufs_phy_tx_symbol_0_clk = { + .halt_reg = 0x45018, + .halt_check = BRANCH_HALT_SKIP, + .clkr = { + .enable_reg = 0x45018, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_ufs_phy_tx_symbol_0_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ufs_phy_unipro_core_clk = { + .halt_reg = 0x45040, + .halt_check = BRANCH_HALT, + .hwcg_reg = 0x45040, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x45040, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_ufs_phy_unipro_core_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_ufs_phy_unipro_core_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb30_prim_master_clk = { + .halt_reg = 0x1a010, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1a010, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_usb30_prim_master_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_usb30_prim_master_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb30_prim_mock_utmi_clk = { + .halt_reg = 0x1a018, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1a018, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_usb30_prim_mock_utmi_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_usb30_prim_mock_utmi_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb30_prim_sleep_clk = { + .halt_reg = 0x1a014, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1a014, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_usb30_prim_sleep_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb3_prim_clkref_clk = { + .halt_reg = 0x80278, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x80278, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_usb3_prim_clkref_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb3_prim_phy_com_aux_clk = { + .halt_reg = 0x1a054, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1a054, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_usb3_prim_phy_com_aux_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_usb3_prim_phy_aux_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb3_prim_phy_pipe_clk = { + .halt_check = BRANCH_HALT_SKIP, + .clkr = { + .enable_reg = 0x1a058, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_usb3_prim_phy_pipe_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_vdda_vs_clk = { + .halt_reg = 0x4200c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x4200c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_vdda_vs_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_vsensor_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_vddcx_vs_clk = { + .halt_reg = 0x42004, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x42004, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_vddcx_vs_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_vsensor_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_vddmx_vs_clk = { + .halt_reg = 0x42008, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x42008, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_vddmx_vs_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_vsensor_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_video_ahb_clk = { + .halt_reg = 0x17004, + .halt_check = BRANCH_HALT, + .hwcg_reg = 0x17004, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x17004, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_video_ahb_clk", + .flags = CLK_IS_CRITICAL, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_video_axi0_clk = { + .halt_reg = 0x1701c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1701c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_video_axi0_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_video_throttle_core_clk = { + .halt_reg = 0x17068, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x79004, + .enable_mask = BIT(28), + .hw.init = &(struct clk_init_data){ + .name = "gcc_video_throttle_core_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_video_xo_clk = { + .halt_reg = 0x17024, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x17024, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_video_xo_clk", + .flags = CLK_IS_CRITICAL, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_vs_ctrl_ahb_clk = { + .halt_reg = 0x42014, + .halt_check = BRANCH_HALT, + .hwcg_reg = 0x42014, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x42014, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_vs_ctrl_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_vs_ctrl_clk = { + .halt_reg = 0x42010, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x42010, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_vs_ctrl_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_vs_ctrl_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_wcss_vs_clk = { + .halt_reg = 0x42050, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x42050, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_wcss_vs_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_vsensor_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct gdsc usb30_prim_gdsc = { + .gdscr = 0x1a004, + .pd = { + .name = "usb30_prim_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, +}; + +static struct gdsc ufs_phy_gdsc = { + .gdscr = 0x45004, + .pd = { + .name = "ufs_phy_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, +}; + +static struct gdsc camss_vfe0_gdsc = { + .gdscr = 0x54004, + .pd = { + .name = "camss_vfe0_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, +}; + +static struct gdsc camss_vfe1_gdsc = { + .gdscr = 0x5403c, + .pd = { + .name = "camss_vfe1_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, +}; + +static struct gdsc camss_top_gdsc = { + .gdscr = 0x5607c, + .pd = { + .name = "camss_top_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, +}; + +static struct gdsc cam_cpp_gdsc = { + .gdscr = 0x560bc, + .pd = { + .name = "cam_cpp_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, +}; + +static struct gdsc hlos1_vote_turing_mmu_tbu1_gdsc = { + .gdscr = 0x7d060, + .pd = { + .name = "hlos1_vote_turing_mmu_tbu1_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, + .flags = VOTABLE, +}; + +static struct gdsc hlos1_vote_mm_snoc_mmu_tbu_rt_gdsc = { + .gdscr = 0x80074, + .pd = { + .name = "hlos1_vote_mm_snoc_mmu_tbu_rt_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, + .flags = VOTABLE, +}; + +static struct gdsc hlos1_vote_mm_snoc_mmu_tbu_nrt_gdsc = { + .gdscr = 0x80084, + .pd = { + .name = "hlos1_vote_mm_snoc_mmu_tbu_nrt_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, + .flags = VOTABLE, +}; + + +static struct gdsc hlos1_vote_turing_mmu_tbu0_gdsc = { + .gdscr = 0x80094, + .pd = { + .name = "hlos1_vote_turing_mmu_tbu0_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, + .flags = VOTABLE, +}; + +static struct gdsc *gcc_sm6125_gdscs[] = { + [USB30_PRIM_GDSC] = &usb30_prim_gdsc, + [UFS_PHY_GDSC] = &ufs_phy_gdsc, + [CAMSS_VFE0_GDSC] = &camss_vfe0_gdsc, + [CAMSS_VFE1_GDSC] = &camss_vfe1_gdsc, + [CAMSS_TOP_GDSC] = &camss_top_gdsc, + [CAM_CPP_GDSC] = &cam_cpp_gdsc, + [HLOS1_VOTE_TURING_MMU_TBU1_GDSC] = &hlos1_vote_turing_mmu_tbu1_gdsc, + [HLOS1_VOTE_MM_SNOC_MMU_TBU_RT_GDSC] = &hlos1_vote_mm_snoc_mmu_tbu_rt_gdsc, + [HLOS1_VOTE_MM_SNOC_MMU_TBU_NRT_GDSC] = &hlos1_vote_mm_snoc_mmu_tbu_nrt_gdsc, + [HLOS1_VOTE_TURING_MMU_TBU0_GDSC] = &hlos1_vote_turing_mmu_tbu0_gdsc, +}; + +static struct clk_hw *gcc_sm6125_hws[] = { + [GPLL0_OUT_AUX2] = &gpll0_out_aux2.hw, + [GPLL0_OUT_MAIN] = &gpll0_out_main.hw, + [GPLL6_OUT_MAIN] = &gpll6_out_main.hw, + [GPLL7_OUT_MAIN] = &gpll7_out_main.hw, + [GPLL8_OUT_MAIN] = &gpll8_out_main.hw, + [GPLL9_OUT_MAIN] = &gpll9_out_main.hw, +}; + +static struct clk_regmap *gcc_sm6125_clocks[] = { + [GCC_AHB2PHY_CSI_CLK] = &gcc_ahb2phy_csi_clk.clkr, + [GCC_AHB2PHY_USB_CLK] = &gcc_ahb2phy_usb_clk.clkr, + [GCC_APC_VS_CLK] = &gcc_apc_vs_clk.clkr, + [GCC_BIMC_GPU_AXI_CLK] = &gcc_bimc_gpu_axi_clk.clkr, + [GCC_BOOT_ROM_AHB_CLK] = &gcc_boot_rom_ahb_clk.clkr, + [GCC_CAMERA_AHB_CLK] = &gcc_camera_ahb_clk.clkr, + [GCC_CAMERA_XO_CLK] = &gcc_camera_xo_clk.clkr, + [GCC_CAMSS_AHB_CLK_SRC] = &gcc_camss_ahb_clk_src.clkr, + [GCC_CAMSS_CCI_AHB_CLK] = &gcc_camss_cci_ahb_clk.clkr, + [GCC_CAMSS_CCI_CLK] = &gcc_camss_cci_clk.clkr, + [GCC_CAMSS_CCI_CLK_SRC] = &gcc_camss_cci_clk_src.clkr, + [GCC_CAMSS_CPHY_CSID0_CLK] = &gcc_camss_cphy_csid0_clk.clkr, + [GCC_CAMSS_CPHY_CSID1_CLK] = &gcc_camss_cphy_csid1_clk.clkr, + [GCC_CAMSS_CPHY_CSID2_CLK] = &gcc_camss_cphy_csid2_clk.clkr, + [GCC_CAMSS_CPHY_CSID3_CLK] = &gcc_camss_cphy_csid3_clk.clkr, + [GCC_CAMSS_CPP_AHB_CLK] = &gcc_camss_cpp_ahb_clk.clkr, + [GCC_CAMSS_CPP_AXI_CLK] = &gcc_camss_cpp_axi_clk.clkr, + [GCC_CAMSS_CPP_CLK] = &gcc_camss_cpp_clk.clkr, + [GCC_CAMSS_CPP_CLK_SRC] = &gcc_camss_cpp_clk_src.clkr, + [GCC_CAMSS_CPP_VBIF_AHB_CLK] = &gcc_camss_cpp_vbif_ahb_clk.clkr, + [GCC_CAMSS_CSI0_AHB_CLK] = &gcc_camss_csi0_ahb_clk.clkr, + [GCC_CAMSS_CSI0_CLK] = &gcc_camss_csi0_clk.clkr, + [GCC_CAMSS_CSI0_CLK_SRC] = &gcc_camss_csi0_clk_src.clkr, + [GCC_CAMSS_CSI0PHYTIMER_CLK] = &gcc_camss_csi0phytimer_clk.clkr, + [GCC_CAMSS_CSI0PHYTIMER_CLK_SRC] = &gcc_camss_csi0phytimer_clk_src.clkr, + [GCC_CAMSS_CSI0PIX_CLK] = &gcc_camss_csi0pix_clk.clkr, + [GCC_CAMSS_CSI0RDI_CLK] = &gcc_camss_csi0rdi_clk.clkr, + [GCC_CAMSS_CSI1_AHB_CLK] = &gcc_camss_csi1_ahb_clk.clkr, + [GCC_CAMSS_CSI1_CLK] = &gcc_camss_csi1_clk.clkr, + [GCC_CAMSS_CSI1_CLK_SRC] = &gcc_camss_csi1_clk_src.clkr, + [GCC_CAMSS_CSI1PHYTIMER_CLK] = &gcc_camss_csi1phytimer_clk.clkr, + [GCC_CAMSS_CSI1PHYTIMER_CLK_SRC] = &gcc_camss_csi1phytimer_clk_src.clkr, + [GCC_CAMSS_CSI1PIX_CLK] = &gcc_camss_csi1pix_clk.clkr, + [GCC_CAMSS_CSI1RDI_CLK] = &gcc_camss_csi1rdi_clk.clkr, + [GCC_CAMSS_CSI2_AHB_CLK] = &gcc_camss_csi2_ahb_clk.clkr, + [GCC_CAMSS_CSI2_CLK] = &gcc_camss_csi2_clk.clkr, + [GCC_CAMSS_CSI2_CLK_SRC] = &gcc_camss_csi2_clk_src.clkr, + [GCC_CAMSS_CSI2PHYTIMER_CLK] = &gcc_camss_csi2phytimer_clk.clkr, + [GCC_CAMSS_CSI2PHYTIMER_CLK_SRC] = &gcc_camss_csi2phytimer_clk_src.clkr, + [GCC_CAMSS_CSI2PIX_CLK] = &gcc_camss_csi2pix_clk.clkr, + [GCC_CAMSS_CSI2RDI_CLK] = &gcc_camss_csi2rdi_clk.clkr, + [GCC_CAMSS_CSI3_AHB_CLK] = &gcc_camss_csi3_ahb_clk.clkr, + [GCC_CAMSS_CSI3_CLK] = &gcc_camss_csi3_clk.clkr, + [GCC_CAMSS_CSI3_CLK_SRC] = &gcc_camss_csi3_clk_src.clkr, + [GCC_CAMSS_CSI3PIX_CLK] = &gcc_camss_csi3pix_clk.clkr, + [GCC_CAMSS_CSI3RDI_CLK] = &gcc_camss_csi3rdi_clk.clkr, + [GCC_CAMSS_CSI_VFE0_CLK] = &gcc_camss_csi_vfe0_clk.clkr, + [GCC_CAMSS_CSI_VFE1_CLK] = &gcc_camss_csi_vfe1_clk.clkr, + [GCC_CAMSS_CSIPHY0_CLK] = &gcc_camss_csiphy0_clk.clkr, + [GCC_CAMSS_CSIPHY1_CLK] = &gcc_camss_csiphy1_clk.clkr, + [GCC_CAMSS_CSIPHY2_CLK] = &gcc_camss_csiphy2_clk.clkr, + [GCC_CAMSS_CSIPHY_CLK_SRC] = &gcc_camss_csiphy_clk_src.clkr, + [GCC_CAMSS_GP0_CLK] = &gcc_camss_gp0_clk.clkr, + [GCC_CAMSS_GP0_CLK_SRC] = &gcc_camss_gp0_clk_src.clkr, + [GCC_CAMSS_GP1_CLK] = &gcc_camss_gp1_clk.clkr, + [GCC_CAMSS_GP1_CLK_SRC] = &gcc_camss_gp1_clk_src.clkr, + [GCC_CAMSS_ISPIF_AHB_CLK] = &gcc_camss_ispif_ahb_clk.clkr, + [GCC_CAMSS_JPEG_AHB_CLK] = &gcc_camss_jpeg_ahb_clk.clkr, + [GCC_CAMSS_JPEG_AXI_CLK] = &gcc_camss_jpeg_axi_clk.clkr, + [GCC_CAMSS_JPEG_CLK] = &gcc_camss_jpeg_clk.clkr, + [GCC_CAMSS_JPEG_CLK_SRC] = &gcc_camss_jpeg_clk_src.clkr, + [GCC_CAMSS_MCLK0_CLK] = &gcc_camss_mclk0_clk.clkr, + [GCC_CAMSS_MCLK0_CLK_SRC] = &gcc_camss_mclk0_clk_src.clkr, + [GCC_CAMSS_MCLK1_CLK] = &gcc_camss_mclk1_clk.clkr, + [GCC_CAMSS_MCLK1_CLK_SRC] = &gcc_camss_mclk1_clk_src.clkr, + [GCC_CAMSS_MCLK2_CLK] = &gcc_camss_mclk2_clk.clkr, + [GCC_CAMSS_MCLK2_CLK_SRC] = &gcc_camss_mclk2_clk_src.clkr, + [GCC_CAMSS_MCLK3_CLK] = &gcc_camss_mclk3_clk.clkr, + [GCC_CAMSS_MCLK3_CLK_SRC] = &gcc_camss_mclk3_clk_src.clkr, + [GCC_CAMSS_MICRO_AHB_CLK] = &gcc_camss_micro_ahb_clk.clkr, + [GCC_CAMSS_THROTTLE_NRT_AXI_CLK] = &gcc_camss_throttle_nrt_axi_clk.clkr, + [GCC_CAMSS_THROTTLE_RT_AXI_CLK] = &gcc_camss_throttle_rt_axi_clk.clkr, + [GCC_CAMSS_TOP_AHB_CLK] = &gcc_camss_top_ahb_clk.clkr, + [GCC_CAMSS_VFE0_AHB_CLK] = &gcc_camss_vfe0_ahb_clk.clkr, + [GCC_CAMSS_VFE0_CLK] = &gcc_camss_vfe0_clk.clkr, + [GCC_CAMSS_VFE0_CLK_SRC] = &gcc_camss_vfe0_clk_src.clkr, + [GCC_CAMSS_VFE0_STREAM_CLK] = &gcc_camss_vfe0_stream_clk.clkr, + [GCC_CAMSS_VFE1_AHB_CLK] = &gcc_camss_vfe1_ahb_clk.clkr, + [GCC_CAMSS_VFE1_CLK] = &gcc_camss_vfe1_clk.clkr, + [GCC_CAMSS_VFE1_CLK_SRC] = &gcc_camss_vfe1_clk_src.clkr, + [GCC_CAMSS_VFE1_STREAM_CLK] = &gcc_camss_vfe1_stream_clk.clkr, + [GCC_CAMSS_VFE_TSCTR_CLK] = &gcc_camss_vfe_tsctr_clk.clkr, + [GCC_CAMSS_VFE_VBIF_AHB_CLK] = &gcc_camss_vfe_vbif_ahb_clk.clkr, + [GCC_CAMSS_VFE_VBIF_AXI_CLK] = &gcc_camss_vfe_vbif_axi_clk.clkr, + [GCC_CE1_AHB_CLK] = &gcc_ce1_ahb_clk.clkr, + [GCC_CE1_AXI_CLK] = &gcc_ce1_axi_clk.clkr, + [GCC_CE1_CLK] = &gcc_ce1_clk.clkr, + [GCC_CFG_NOC_USB3_PRIM_AXI_CLK] = &gcc_cfg_noc_usb3_prim_axi_clk.clkr, + [GCC_CPUSS_GNOC_CLK] = &gcc_cpuss_gnoc_clk.clkr, + [GCC_DISP_AHB_CLK] = &gcc_disp_ahb_clk.clkr, + [GCC_DISP_GPLL0_DIV_CLK_SRC] = &gcc_disp_gpll0_div_clk_src.clkr, + [GCC_DISP_HF_AXI_CLK] = &gcc_disp_hf_axi_clk.clkr, + [GCC_DISP_THROTTLE_CORE_CLK] = &gcc_disp_throttle_core_clk.clkr, + [GCC_DISP_XO_CLK] = &gcc_disp_xo_clk.clkr, + [GCC_GP1_CLK] = &gcc_gp1_clk.clkr, + [GCC_GP1_CLK_SRC] = &gcc_gp1_clk_src.clkr, + [GCC_GP2_CLK] = &gcc_gp2_clk.clkr, + [GCC_GP2_CLK_SRC] = &gcc_gp2_clk_src.clkr, + [GCC_GP3_CLK] = &gcc_gp3_clk.clkr, + [GCC_GP3_CLK_SRC] = &gcc_gp3_clk_src.clkr, + [GCC_GPU_CFG_AHB_CLK] = &gcc_gpu_cfg_ahb_clk.clkr, + [GCC_GPU_GPLL0_CLK_SRC] = &gcc_gpu_gpll0_clk_src.clkr, + [GCC_GPU_GPLL0_DIV_CLK_SRC] = &gcc_gpu_gpll0_div_clk_src.clkr, + [GCC_GPU_MEMNOC_GFX_CLK] = &gcc_gpu_memnoc_gfx_clk.clkr, + [GCC_GPU_SNOC_DVM_GFX_CLK] = &gcc_gpu_snoc_dvm_gfx_clk.clkr, + [GCC_GPU_THROTTLE_CORE_CLK] = &gcc_gpu_throttle_core_clk.clkr, + [GCC_GPU_THROTTLE_XO_CLK] = &gcc_gpu_throttle_xo_clk.clkr, + [GCC_MSS_VS_CLK] = &gcc_mss_vs_clk.clkr, + [GCC_PDM2_CLK] = &gcc_pdm2_clk.clkr, + [GCC_PDM2_CLK_SRC] = &gcc_pdm2_clk_src.clkr, + [GCC_PDM_AHB_CLK] = &gcc_pdm_ahb_clk.clkr, + [GCC_PDM_XO4_CLK] = &gcc_pdm_xo4_clk.clkr, + [GCC_PRNG_AHB_CLK] = &gcc_prng_ahb_clk.clkr, + [GCC_QMIP_CAMERA_NRT_AHB_CLK] = &gcc_qmip_camera_nrt_ahb_clk.clkr, + [GCC_QMIP_CAMERA_RT_AHB_CLK] = &gcc_qmip_camera_rt_ahb_clk.clkr, + [GCC_QMIP_DISP_AHB_CLK] = &gcc_qmip_disp_ahb_clk.clkr, + [GCC_QMIP_GPU_CFG_AHB_CLK] = &gcc_qmip_gpu_cfg_ahb_clk.clkr, + [GCC_QMIP_VIDEO_VCODEC_AHB_CLK] = &gcc_qmip_video_vcodec_ahb_clk.clkr, + [GCC_QUPV3_WRAP0_CORE_2X_CLK] = &gcc_qupv3_wrap0_core_2x_clk.clkr, + [GCC_QUPV3_WRAP0_CORE_CLK] = &gcc_qupv3_wrap0_core_clk.clkr, + [GCC_QUPV3_WRAP0_S0_CLK] = &gcc_qupv3_wrap0_s0_clk.clkr, + [GCC_QUPV3_WRAP0_S0_CLK_SRC] = &gcc_qupv3_wrap0_s0_clk_src.clkr, + [GCC_QUPV3_WRAP0_S1_CLK] = &gcc_qupv3_wrap0_s1_clk.clkr, + [GCC_QUPV3_WRAP0_S1_CLK_SRC] = &gcc_qupv3_wrap0_s1_clk_src.clkr, + [GCC_QUPV3_WRAP0_S2_CLK] = &gcc_qupv3_wrap0_s2_clk.clkr, + [GCC_QUPV3_WRAP0_S2_CLK_SRC] = &gcc_qupv3_wrap0_s2_clk_src.clkr, + [GCC_QUPV3_WRAP0_S3_CLK] = &gcc_qupv3_wrap0_s3_clk.clkr, + [GCC_QUPV3_WRAP0_S3_CLK_SRC] = &gcc_qupv3_wrap0_s3_clk_src.clkr, + [GCC_QUPV3_WRAP0_S4_CLK] = &gcc_qupv3_wrap0_s4_clk.clkr, + [GCC_QUPV3_WRAP0_S4_CLK_SRC] = &gcc_qupv3_wrap0_s4_clk_src.clkr, + [GCC_QUPV3_WRAP0_S5_CLK] = &gcc_qupv3_wrap0_s5_clk.clkr, + [GCC_QUPV3_WRAP0_S5_CLK_SRC] = &gcc_qupv3_wrap0_s5_clk_src.clkr, + [GCC_QUPV3_WRAP1_CORE_2X_CLK] = &gcc_qupv3_wrap1_core_2x_clk.clkr, + [GCC_QUPV3_WRAP1_CORE_CLK] = &gcc_qupv3_wrap1_core_clk.clkr, + [GCC_QUPV3_WRAP1_S0_CLK] = &gcc_qupv3_wrap1_s0_clk.clkr, + [GCC_QUPV3_WRAP1_S0_CLK_SRC] = &gcc_qupv3_wrap1_s0_clk_src.clkr, + [GCC_QUPV3_WRAP1_S1_CLK] = &gcc_qupv3_wrap1_s1_clk.clkr, + [GCC_QUPV3_WRAP1_S1_CLK_SRC] = &gcc_qupv3_wrap1_s1_clk_src.clkr, + [GCC_QUPV3_WRAP1_S2_CLK] = &gcc_qupv3_wrap1_s2_clk.clkr, + [GCC_QUPV3_WRAP1_S2_CLK_SRC] = &gcc_qupv3_wrap1_s2_clk_src.clkr, + [GCC_QUPV3_WRAP1_S3_CLK] = &gcc_qupv3_wrap1_s3_clk.clkr, + [GCC_QUPV3_WRAP1_S3_CLK_SRC] = &gcc_qupv3_wrap1_s3_clk_src.clkr, + [GCC_QUPV3_WRAP1_S4_CLK] = &gcc_qupv3_wrap1_s4_clk.clkr, + [GCC_QUPV3_WRAP1_S4_CLK_SRC] = &gcc_qupv3_wrap1_s4_clk_src.clkr, + [GCC_QUPV3_WRAP1_S5_CLK] = &gcc_qupv3_wrap1_s5_clk.clkr, + [GCC_QUPV3_WRAP1_S5_CLK_SRC] = &gcc_qupv3_wrap1_s5_clk_src.clkr, + [GCC_QUPV3_WRAP_0_M_AHB_CLK] = &gcc_qupv3_wrap_0_m_ahb_clk.clkr, + [GCC_QUPV3_WRAP_0_S_AHB_CLK] = &gcc_qupv3_wrap_0_s_ahb_clk.clkr, + [GCC_QUPV3_WRAP_1_M_AHB_CLK] = &gcc_qupv3_wrap_1_m_ahb_clk.clkr, + [GCC_QUPV3_WRAP_1_S_AHB_CLK] = &gcc_qupv3_wrap_1_s_ahb_clk.clkr, + [GCC_SDCC1_AHB_CLK] = &gcc_sdcc1_ahb_clk.clkr, + [GCC_SDCC1_APPS_CLK] = &gcc_sdcc1_apps_clk.clkr, + [GCC_SDCC1_APPS_CLK_SRC] = &gcc_sdcc1_apps_clk_src.clkr, + [GCC_SDCC1_ICE_CORE_CLK] = &gcc_sdcc1_ice_core_clk.clkr, + [GCC_SDCC1_ICE_CORE_CLK_SRC] = &gcc_sdcc1_ice_core_clk_src.clkr, + [GCC_SDCC2_AHB_CLK] = &gcc_sdcc2_ahb_clk.clkr, + [GCC_SDCC2_APPS_CLK] = &gcc_sdcc2_apps_clk.clkr, + [GCC_SDCC2_APPS_CLK_SRC] = &gcc_sdcc2_apps_clk_src.clkr, + [GCC_SYS_NOC_COMPUTE_SF_AXI_CLK] = &gcc_sys_noc_compute_sf_axi_clk.clkr, + [GCC_SYS_NOC_CPUSS_AHB_CLK] = &gcc_sys_noc_cpuss_ahb_clk.clkr, + [GCC_SYS_NOC_UFS_PHY_AXI_CLK] = &gcc_sys_noc_ufs_phy_axi_clk.clkr, + [GCC_SYS_NOC_USB3_PRIM_AXI_CLK] = &gcc_sys_noc_usb3_prim_axi_clk.clkr, + [GCC_UFS_MEM_CLKREF_CLK] = &gcc_ufs_mem_clkref_clk.clkr, + [GCC_UFS_PHY_AHB_CLK] = &gcc_ufs_phy_ahb_clk.clkr, + [GCC_UFS_PHY_AXI_CLK] = &gcc_ufs_phy_axi_clk.clkr, + [GCC_UFS_PHY_AXI_CLK_SRC] = &gcc_ufs_phy_axi_clk_src.clkr, + [GCC_UFS_PHY_ICE_CORE_CLK] = &gcc_ufs_phy_ice_core_clk.clkr, + [GCC_UFS_PHY_ICE_CORE_CLK_SRC] = &gcc_ufs_phy_ice_core_clk_src.clkr, + [GCC_UFS_PHY_PHY_AUX_CLK] = &gcc_ufs_phy_phy_aux_clk.clkr, + [GCC_UFS_PHY_PHY_AUX_CLK_SRC] = &gcc_ufs_phy_phy_aux_clk_src.clkr, + [GCC_UFS_PHY_RX_SYMBOL_0_CLK] = &gcc_ufs_phy_rx_symbol_0_clk.clkr, + [GCC_UFS_PHY_TX_SYMBOL_0_CLK] = &gcc_ufs_phy_tx_symbol_0_clk.clkr, + [GCC_UFS_PHY_UNIPRO_CORE_CLK] = &gcc_ufs_phy_unipro_core_clk.clkr, + [GCC_UFS_PHY_UNIPRO_CORE_CLK_SRC] = + &gcc_ufs_phy_unipro_core_clk_src.clkr, + [GCC_USB30_PRIM_MASTER_CLK] = &gcc_usb30_prim_master_clk.clkr, + [GCC_USB30_PRIM_MASTER_CLK_SRC] = &gcc_usb30_prim_master_clk_src.clkr, + [GCC_USB30_PRIM_MOCK_UTMI_CLK] = &gcc_usb30_prim_mock_utmi_clk.clkr, + [GCC_USB30_PRIM_MOCK_UTMI_CLK_SRC] = + &gcc_usb30_prim_mock_utmi_clk_src.clkr, + [GCC_USB30_PRIM_SLEEP_CLK] = &gcc_usb30_prim_sleep_clk.clkr, + [GCC_USB3_PRIM_PHY_AUX_CLK_SRC] = &gcc_usb3_prim_phy_aux_clk_src.clkr, + [GCC_USB3_PRIM_PHY_COM_AUX_CLK] = &gcc_usb3_prim_phy_com_aux_clk.clkr, + [GCC_USB3_PRIM_PHY_PIPE_CLK] = &gcc_usb3_prim_phy_pipe_clk.clkr, + [GCC_VDDA_VS_CLK] = &gcc_vdda_vs_clk.clkr, + [GCC_VDDCX_VS_CLK] = &gcc_vddcx_vs_clk.clkr, + [GCC_VDDMX_VS_CLK] = &gcc_vddmx_vs_clk.clkr, + [GCC_VIDEO_AHB_CLK] = &gcc_video_ahb_clk.clkr, + [GCC_VIDEO_AXI0_CLK] = &gcc_video_axi0_clk.clkr, + [GCC_VIDEO_THROTTLE_CORE_CLK] = &gcc_video_throttle_core_clk.clkr, + [GCC_VIDEO_XO_CLK] = &gcc_video_xo_clk.clkr, + [GCC_VS_CTRL_AHB_CLK] = &gcc_vs_ctrl_ahb_clk.clkr, + [GCC_VS_CTRL_CLK] = &gcc_vs_ctrl_clk.clkr, + [GCC_VS_CTRL_CLK_SRC] = &gcc_vs_ctrl_clk_src.clkr, + [GCC_VSENSOR_CLK_SRC] = &gcc_vsensor_clk_src.clkr, + [GCC_WCSS_VS_CLK] = &gcc_wcss_vs_clk.clkr, + [GPLL0_OUT_EARLY] = &gpll0_out_early.clkr, + [GPLL3_OUT_EARLY] = &gpll3_out_early.clkr, + [GPLL4_OUT_MAIN] = &gpll4_out_main.clkr, + [GPLL5_OUT_MAIN] = &gpll5_out_main.clkr, + [GPLL6_OUT_EARLY] = &gpll6_out_early.clkr, + [GPLL7_OUT_EARLY] = &gpll7_out_early.clkr, + [GPLL8_OUT_EARLY] = &gpll8_out_early.clkr, + [GPLL9_OUT_EARLY] = &gpll9_out_early.clkr, + [GCC_USB3_PRIM_CLKREF_CLK] = &gcc_usb3_prim_clkref_clk.clkr, +}; + +static const struct qcom_reset_map gcc_sm6125_resets[] = { + [GCC_QUSB2PHY_PRIM_BCR] = { 0x1c000 }, + [GCC_QUSB2PHY_SEC_BCR] = { 0x1c004 }, + [GCC_UFS_PHY_BCR] = { 0x45000 }, + [GCC_USB30_PRIM_BCR] = { 0x1a000 }, + [GCC_USB_PHY_CFG_AHB2PHY_BCR] = { 0x1d000 }, + [GCC_USB3PHY_PHY_PRIM_SP0_BCR] = { 0x1b008 }, + [GCC_USB3_PHY_PRIM_SP0_BCR] = { 0x1b000 }, + [GCC_CAMSS_MICRO_BCR] = { 0x560ac }, +}; + +static struct clk_rcg_dfs_data gcc_dfs_clocks[] = { + DEFINE_RCG_DFS(gcc_qupv3_wrap0_s0_clk_src), + DEFINE_RCG_DFS(gcc_qupv3_wrap0_s1_clk_src), + DEFINE_RCG_DFS(gcc_qupv3_wrap0_s2_clk_src), + DEFINE_RCG_DFS(gcc_qupv3_wrap0_s3_clk_src), + DEFINE_RCG_DFS(gcc_qupv3_wrap0_s4_clk_src), + DEFINE_RCG_DFS(gcc_qupv3_wrap0_s5_clk_src), + DEFINE_RCG_DFS(gcc_qupv3_wrap1_s0_clk_src), + DEFINE_RCG_DFS(gcc_qupv3_wrap1_s1_clk_src), + DEFINE_RCG_DFS(gcc_qupv3_wrap1_s2_clk_src), + DEFINE_RCG_DFS(gcc_qupv3_wrap1_s3_clk_src), + DEFINE_RCG_DFS(gcc_qupv3_wrap1_s4_clk_src), + DEFINE_RCG_DFS(gcc_qupv3_wrap1_s5_clk_src), +}; + +static const struct regmap_config gcc_sm6125_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = 0xc7000, + .fast_io = true, +}; + +static const struct qcom_cc_desc gcc_sm6125_desc = { + .config = &gcc_sm6125_regmap_config, + .clks = gcc_sm6125_clocks, + .num_clks = ARRAY_SIZE(gcc_sm6125_clocks), + .clk_hws = gcc_sm6125_hws, + .num_clk_hws = ARRAY_SIZE(gcc_sm6125_hws), + .resets = gcc_sm6125_resets, + .num_resets = ARRAY_SIZE(gcc_sm6125_resets), + .gdscs = gcc_sm6125_gdscs, + .num_gdscs = ARRAY_SIZE(gcc_sm6125_gdscs), +}; + +static const struct of_device_id gcc_sm6125_match_table[] = { + { .compatible = "qcom,gcc-sm6125" }, + { } +}; +MODULE_DEVICE_TABLE(of, gcc_sm6125_match_table); + +static int gcc_sm6125_probe(struct platform_device *pdev) +{ + struct regmap *regmap; + int ret; + + regmap = qcom_cc_map(pdev, &gcc_sm6125_desc); + if (IS_ERR(regmap)) + return PTR_ERR(regmap); + + /* + * Disable the GPLL0 active input to video block via + * MISC registers. + */ + regmap_update_bits(regmap, 0x80258, 0x1, 0x1); + + /* + * Enable DUAL_EDGE mode for MCLK RCGs + * This is requierd to enable MND divider mode + */ + regmap_update_bits(regmap, 0x51004, 0x3000, 0x2000); + regmap_update_bits(regmap, 0x51020, 0x3000, 0x2000); + regmap_update_bits(regmap, 0x5103c, 0x3000, 0x2000); + regmap_update_bits(regmap, 0x51058, 0x3000, 0x2000); + + ret = qcom_cc_register_rcg_dfs(regmap, gcc_dfs_clocks, + ARRAY_SIZE(gcc_dfs_clocks)); + if (ret) + return ret; + + return qcom_cc_really_probe(pdev, &gcc_sm6125_desc, regmap); +} + +static struct platform_driver gcc_sm6125_driver = { + .probe = gcc_sm6125_probe, + .driver = { + .name = "gcc-sm6125", + .of_match_table = gcc_sm6125_match_table, + }, +}; + +static int __init gcc_sm6125_init(void) +{ + return platform_driver_register(&gcc_sm6125_driver); +} +subsys_initcall(gcc_sm6125_init); + +static void __exit gcc_sm6125_exit(void) +{ + platform_driver_unregister(&gcc_sm6125_driver); +} +module_exit(gcc_sm6125_exit); + +MODULE_DESCRIPTION("QTI GCC SM6125 Driver"); +MODULE_LICENSE("GPL v2"); From e184d788af5c10d00c7430dcb1f8c7cf086567a2 Mon Sep 17 00:00:00 2001 From: Bartosz Dudziak Date: Sun, 18 Apr 2021 14:29:05 +0200 Subject: [PATCH 101/161] dt-bindings: clock: qcom: Add MSM8226 GCC clock bindings Add compatible device strings and the include files for the MSM8226 GCC. Signed-off-by: Bartosz Dudziak Link: https://lore.kernel.org/r/20210418122909.71434-2-bartosz.dudziak@snejp.pl Acked-by: Rob Herring Signed-off-by: Stephen Boyd --- Documentation/devicetree/bindings/clock/qcom,gcc.yaml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/clock/qcom,gcc.yaml b/Documentation/devicetree/bindings/clock/qcom,gcc.yaml index 3599702cd428..8453eeddf30e 100644 --- a/Documentation/devicetree/bindings/clock/qcom,gcc.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,gcc.yaml @@ -26,8 +26,8 @@ description: | - dt-bindings/reset/qcom,gcc-msm8939.h - dt-bindings/clock/qcom,gcc-msm8660.h - dt-bindings/reset/qcom,gcc-msm8660.h - - dt-bindings/clock/qcom,gcc-msm8974.h - - dt-bindings/reset/qcom,gcc-msm8974.h + - dt-bindings/clock/qcom,gcc-msm8974.h (qcom,gcc-msm8226 and qcom,gcc-msm8974) + - dt-bindings/reset/qcom,gcc-msm8974.h (qcom,gcc-msm8226 and qcom,gcc-msm8974) - dt-bindings/clock/qcom,gcc-msm8994.h - dt-bindings/clock/qcom,gcc-mdm9607.h - dt-bindings/clock/qcom,gcc-mdm9615.h @@ -42,6 +42,7 @@ properties: - qcom,gcc-ipq6018 - qcom,gcc-ipq8064 - qcom,gcc-mdm9607 + - qcom,gcc-msm8226 - qcom,gcc-msm8660 - qcom,gcc-msm8916 - qcom,gcc-msm8939 From 76f53d9bd900996072e7565d1d5ad8aeedae2bb5 Mon Sep 17 00:00:00 2001 From: Bartosz Dudziak Date: Sun, 18 Apr 2021 14:29:06 +0200 Subject: [PATCH 102/161] clk: qcom: gcc: Add support for Global Clock controller found on MSM8226 Modify existing MSM8974 driver to support MSM8226 SoC. Override frequencies which are different in this older chip. Register all the clocks to the framework for the clients to be able to request for them. Signed-off-by: Bartosz Dudziak Link: https://lore.kernel.org/r/20210418122909.71434-3-bartosz.dudziak@snejp.pl Signed-off-by: Stephen Boyd --- drivers/clk/qcom/gcc-msm8974.c | 169 +++++++++++++++++++++++++++++++-- 1 file changed, 162 insertions(+), 7 deletions(-) diff --git a/drivers/clk/qcom/gcc-msm8974.c b/drivers/clk/qcom/gcc-msm8974.c index 740d3c44c04b..bf305fa9e522 100644 --- a/drivers/clk/qcom/gcc-msm8974.c +++ b/drivers/clk/qcom/gcc-msm8974.c @@ -719,6 +719,12 @@ static struct clk_rcg2 blsp2_uart6_apps_clk_src = { }, }; +static const struct freq_tbl ftbl_gcc_ce1_clk_msm8226[] = { + F(50000000, P_GPLL0, 12, 0, 0), + F(100000000, P_GPLL0, 6, 0, 0), + { } +}; + static const struct freq_tbl ftbl_gcc_ce1_clk[] = { F(50000000, P_GPLL0, 12, 0, 0), F(75000000, P_GPLL0, 8, 0, 0), @@ -761,6 +767,11 @@ static struct clk_rcg2 ce2_clk_src = { }, }; +static const struct freq_tbl ftbl_gcc_gp_clk_msm8226[] = { + F(19200000, P_XO, 1, 0, 0), + { } +}; + static const struct freq_tbl ftbl_gcc_gp_clk[] = { F(4800000, P_XO, 4, 0, 0), F(6000000, P_GPLL0, 10, 1, 10), @@ -1955,6 +1966,10 @@ static struct clk_branch gcc_mss_q6_bimc_axi_clk = { .enable_mask = BIT(0), .hw.init = &(struct clk_init_data){ .name = "gcc_mss_q6_bimc_axi_clk", + .parent_names = (const char *[]){ + "system_noc_clk_src", + }, + .num_parents = 1, .ops = &clk_branch2_ops, }, }, @@ -1993,6 +2008,20 @@ static struct clk_branch gcc_pdm_ahb_clk = { }, }; +static struct clk_branch gcc_pdm_xo4_clk = { + .halt_reg = 0x0cc8, + .clkr = { + .enable_reg = 0x0cc8, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_pdm_xo4_clk", + .parent_names = (const char *[]){ "xo" }, + .num_parents = 1, + .ops = &clk_branch2_ops, + }, + }, +}; + static struct clk_branch gcc_prng_ahb_clk = { .halt_reg = 0x0d04, .halt_check = BRANCH_HALT_VOTED, @@ -2430,6 +2459,121 @@ static struct gdsc usb_hs_hsic_gdsc = { .pwrsts = PWRSTS_OFF_ON, }; +static struct clk_regmap *gcc_msm8226_clocks[] = { + [GPLL0] = &gpll0.clkr, + [GPLL0_VOTE] = &gpll0_vote, + [GPLL1] = &gpll1.clkr, + [GPLL1_VOTE] = &gpll1_vote, + [CONFIG_NOC_CLK_SRC] = &config_noc_clk_src.clkr, + [PERIPH_NOC_CLK_SRC] = &periph_noc_clk_src.clkr, + [SYSTEM_NOC_CLK_SRC] = &system_noc_clk_src.clkr, + [BLSP1_QUP1_I2C_APPS_CLK_SRC] = &blsp1_qup1_i2c_apps_clk_src.clkr, + [BLSP1_QUP1_SPI_APPS_CLK_SRC] = &blsp1_qup1_spi_apps_clk_src.clkr, + [BLSP1_QUP2_I2C_APPS_CLK_SRC] = &blsp1_qup2_i2c_apps_clk_src.clkr, + [BLSP1_QUP2_SPI_APPS_CLK_SRC] = &blsp1_qup2_spi_apps_clk_src.clkr, + [BLSP1_QUP3_I2C_APPS_CLK_SRC] = &blsp1_qup3_i2c_apps_clk_src.clkr, + [BLSP1_QUP3_SPI_APPS_CLK_SRC] = &blsp1_qup3_spi_apps_clk_src.clkr, + [BLSP1_QUP4_I2C_APPS_CLK_SRC] = &blsp1_qup4_i2c_apps_clk_src.clkr, + [BLSP1_QUP4_SPI_APPS_CLK_SRC] = &blsp1_qup4_spi_apps_clk_src.clkr, + [BLSP1_QUP5_I2C_APPS_CLK_SRC] = &blsp1_qup5_i2c_apps_clk_src.clkr, + [BLSP1_QUP5_SPI_APPS_CLK_SRC] = &blsp1_qup5_spi_apps_clk_src.clkr, + [BLSP1_QUP6_I2C_APPS_CLK_SRC] = &blsp1_qup6_i2c_apps_clk_src.clkr, + [BLSP1_QUP6_SPI_APPS_CLK_SRC] = &blsp1_qup6_spi_apps_clk_src.clkr, + [BLSP1_UART1_APPS_CLK_SRC] = &blsp1_uart1_apps_clk_src.clkr, + [BLSP1_UART2_APPS_CLK_SRC] = &blsp1_uart2_apps_clk_src.clkr, + [BLSP1_UART3_APPS_CLK_SRC] = &blsp1_uart3_apps_clk_src.clkr, + [BLSP1_UART4_APPS_CLK_SRC] = &blsp1_uart4_apps_clk_src.clkr, + [BLSP1_UART5_APPS_CLK_SRC] = &blsp1_uart5_apps_clk_src.clkr, + [BLSP1_UART6_APPS_CLK_SRC] = &blsp1_uart6_apps_clk_src.clkr, + [CE1_CLK_SRC] = &ce1_clk_src.clkr, + [GP1_CLK_SRC] = &gp1_clk_src.clkr, + [GP2_CLK_SRC] = &gp2_clk_src.clkr, + [GP3_CLK_SRC] = &gp3_clk_src.clkr, + [PDM2_CLK_SRC] = &pdm2_clk_src.clkr, + [SDCC1_APPS_CLK_SRC] = &sdcc1_apps_clk_src.clkr, + [SDCC2_APPS_CLK_SRC] = &sdcc2_apps_clk_src.clkr, + [SDCC3_APPS_CLK_SRC] = &sdcc3_apps_clk_src.clkr, + [USB_HS_SYSTEM_CLK_SRC] = &usb_hs_system_clk_src.clkr, + [USB_HSIC_CLK_SRC] = &usb_hsic_clk_src.clkr, + [USB_HSIC_IO_CAL_CLK_SRC] = &usb_hsic_io_cal_clk_src.clkr, + [USB_HSIC_SYSTEM_CLK_SRC] = &usb_hsic_system_clk_src.clkr, + [GCC_BAM_DMA_AHB_CLK] = &gcc_bam_dma_ahb_clk.clkr, + [GCC_BLSP1_AHB_CLK] = &gcc_blsp1_ahb_clk.clkr, + [GCC_BLSP1_QUP1_I2C_APPS_CLK] = &gcc_blsp1_qup1_i2c_apps_clk.clkr, + [GCC_BLSP1_QUP1_SPI_APPS_CLK] = &gcc_blsp1_qup1_spi_apps_clk.clkr, + [GCC_BLSP1_QUP2_I2C_APPS_CLK] = &gcc_blsp1_qup2_i2c_apps_clk.clkr, + [GCC_BLSP1_QUP2_SPI_APPS_CLK] = &gcc_blsp1_qup2_spi_apps_clk.clkr, + [GCC_BLSP1_QUP3_I2C_APPS_CLK] = &gcc_blsp1_qup3_i2c_apps_clk.clkr, + [GCC_BLSP1_QUP3_SPI_APPS_CLK] = &gcc_blsp1_qup3_spi_apps_clk.clkr, + [GCC_BLSP1_QUP4_I2C_APPS_CLK] = &gcc_blsp1_qup4_i2c_apps_clk.clkr, + [GCC_BLSP1_QUP4_SPI_APPS_CLK] = &gcc_blsp1_qup4_spi_apps_clk.clkr, + [GCC_BLSP1_QUP5_I2C_APPS_CLK] = &gcc_blsp1_qup5_i2c_apps_clk.clkr, + [GCC_BLSP1_QUP5_SPI_APPS_CLK] = &gcc_blsp1_qup5_spi_apps_clk.clkr, + [GCC_BLSP1_QUP6_I2C_APPS_CLK] = &gcc_blsp1_qup6_i2c_apps_clk.clkr, + [GCC_BLSP1_QUP6_SPI_APPS_CLK] = &gcc_blsp1_qup6_spi_apps_clk.clkr, + [GCC_BLSP1_UART1_APPS_CLK] = &gcc_blsp1_uart1_apps_clk.clkr, + [GCC_BLSP1_UART2_APPS_CLK] = &gcc_blsp1_uart2_apps_clk.clkr, + [GCC_BLSP1_UART3_APPS_CLK] = &gcc_blsp1_uart3_apps_clk.clkr, + [GCC_BLSP1_UART4_APPS_CLK] = &gcc_blsp1_uart4_apps_clk.clkr, + [GCC_BLSP1_UART5_APPS_CLK] = &gcc_blsp1_uart5_apps_clk.clkr, + [GCC_BLSP1_UART6_APPS_CLK] = &gcc_blsp1_uart6_apps_clk.clkr, + [GCC_BOOT_ROM_AHB_CLK] = &gcc_boot_rom_ahb_clk.clkr, + [GCC_CE1_AHB_CLK] = &gcc_ce1_ahb_clk.clkr, + [GCC_CE1_AXI_CLK] = &gcc_ce1_axi_clk.clkr, + [GCC_CE1_CLK] = &gcc_ce1_clk.clkr, + [GCC_GP1_CLK] = &gcc_gp1_clk.clkr, + [GCC_GP2_CLK] = &gcc_gp2_clk.clkr, + [GCC_GP3_CLK] = &gcc_gp3_clk.clkr, + [GCC_LPASS_Q6_AXI_CLK] = &gcc_lpass_q6_axi_clk.clkr, + [GCC_MSS_CFG_AHB_CLK] = &gcc_mss_cfg_ahb_clk.clkr, + [GCC_MSS_Q6_BIMC_AXI_CLK] = &gcc_mss_q6_bimc_axi_clk.clkr, + [GCC_PDM2_CLK] = &gcc_pdm2_clk.clkr, + [GCC_PDM_AHB_CLK] = &gcc_pdm_ahb_clk.clkr, + [GCC_PDM_XO4_CLK] = &gcc_pdm_xo4_clk.clkr, + [GCC_PRNG_AHB_CLK] = &gcc_prng_ahb_clk.clkr, + [GCC_SDCC1_AHB_CLK] = &gcc_sdcc1_ahb_clk.clkr, + [GCC_SDCC1_APPS_CLK] = &gcc_sdcc1_apps_clk.clkr, + [GCC_SDCC2_AHB_CLK] = &gcc_sdcc2_ahb_clk.clkr, + [GCC_SDCC2_APPS_CLK] = &gcc_sdcc2_apps_clk.clkr, + [GCC_SDCC3_AHB_CLK] = &gcc_sdcc3_ahb_clk.clkr, + [GCC_SDCC3_APPS_CLK] = &gcc_sdcc3_apps_clk.clkr, + [GCC_USB2A_PHY_SLEEP_CLK] = &gcc_usb2a_phy_sleep_clk.clkr, + [GCC_USB_HS_AHB_CLK] = &gcc_usb_hs_ahb_clk.clkr, + [GCC_USB_HS_SYSTEM_CLK] = &gcc_usb_hs_system_clk.clkr, + [GCC_USB_HSIC_AHB_CLK] = &gcc_usb_hsic_ahb_clk.clkr, + [GCC_USB_HSIC_CLK] = &gcc_usb_hsic_clk.clkr, + [GCC_USB_HSIC_IO_CAL_CLK] = &gcc_usb_hsic_io_cal_clk.clkr, + [GCC_USB_HSIC_SYSTEM_CLK] = &gcc_usb_hsic_system_clk.clkr, +}; + +static const struct qcom_reset_map gcc_msm8226_resets[] = { + [GCC_USB_HS_HSIC_BCR] = { 0x0400 }, + [GCC_USB_HS_BCR] = { 0x0480 }, + [GCC_USB2A_PHY_BCR] = { 0x04a8 }, +}; + +static struct gdsc *gcc_msm8226_gdscs[] = { + [USB_HS_HSIC_GDSC] = &usb_hs_hsic_gdsc, +}; + +static const struct regmap_config gcc_msm8226_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = 0x1a80, + .fast_io = true, +}; + +static const struct qcom_cc_desc gcc_msm8226_desc = { + .config = &gcc_msm8226_regmap_config, + .clks = gcc_msm8226_clocks, + .num_clks = ARRAY_SIZE(gcc_msm8226_clocks), + .resets = gcc_msm8226_resets, + .num_resets = ARRAY_SIZE(gcc_msm8226_resets), + .gdscs = gcc_msm8226_gdscs, + .num_gdscs = ARRAY_SIZE(gcc_msm8226_gdscs), +}; + static struct clk_regmap *gcc_msm8974_clocks[] = { [GPLL0] = &gpll0.clkr, [GPLL0_VOTE] = &gpll0_vote, @@ -2682,13 +2826,22 @@ static const struct qcom_cc_desc gcc_msm8974_desc = { }; static const struct of_device_id gcc_msm8974_match_table[] = { - { .compatible = "qcom,gcc-msm8974" }, - { .compatible = "qcom,gcc-msm8974pro" , .data = (void *)1UL }, - { .compatible = "qcom,gcc-msm8974pro-ac", .data = (void *)1UL }, + { .compatible = "qcom,gcc-msm8226", .data = &gcc_msm8226_desc }, + { .compatible = "qcom,gcc-msm8974", .data = &gcc_msm8974_desc }, + { .compatible = "qcom,gcc-msm8974pro", .data = &gcc_msm8974_desc }, + { .compatible = "qcom,gcc-msm8974pro-ac", .data = &gcc_msm8974_desc }, { } }; MODULE_DEVICE_TABLE(of, gcc_msm8974_match_table); +static void msm8226_clock_override(void) +{ + ce1_clk_src.freq_tbl = ftbl_gcc_ce1_clk_msm8226; + gp1_clk_src.freq_tbl = ftbl_gcc_gp_clk_msm8226; + gp2_clk_src.freq_tbl = ftbl_gcc_gp_clk_msm8226; + gp3_clk_src.freq_tbl = ftbl_gcc_gp_clk_msm8226; +} + static void msm8974_pro_clock_override(void) { sdcc1_apps_clk_src_init.parent_names = gcc_xo_gpll0_gpll4; @@ -2708,16 +2861,18 @@ static int gcc_msm8974_probe(struct platform_device *pdev) { int ret; struct device *dev = &pdev->dev; - bool pro; const struct of_device_id *id; id = of_match_device(gcc_msm8974_match_table, dev); if (!id) return -ENODEV; - pro = !!(id->data); - if (pro) - msm8974_pro_clock_override(); + if (!of_device_is_compatible(dev->of_node, "qcom,gcc-msm8974")) { + if (id->data == &gcc_msm8226_desc) + msm8226_clock_override(); + else + msm8974_pro_clock_override(); + } ret = qcom_cc_register_board_clk(dev, "xo_board", "xo", 19200000); if (ret) From d1312020feec95d43bde0e04b4cf16916f979393 Mon Sep 17 00:00:00 2001 From: Bartosz Dudziak Date: Sat, 5 Jun 2021 12:40:40 +0200 Subject: [PATCH 103/161] clk: qcom: smd-rpmcc: Add support for MSM8226 rpm clocks Add compatible for rpm smd clocks, PMIC and bus clocks which are required on MSM8226 for clients to vote on. Signed-off-by: Bartosz Dudziak Link: https://lore.kernel.org/r/20210605104040.12960-1-bartosz.dudziak@snejp.pl Signed-off-by: Stephen Boyd --- drivers/clk/qcom/clk-smd-rpm.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/clk/qcom/clk-smd-rpm.c b/drivers/clk/qcom/clk-smd-rpm.c index daf09dd61055..800b2fef1887 100644 --- a/drivers/clk/qcom/clk-smd-rpm.c +++ b/drivers/clk/qcom/clk-smd-rpm.c @@ -914,6 +914,7 @@ static const struct rpm_smd_clk_desc rpm_clk_sdm660 = { }; static const struct of_device_id rpm_smd_clk_match_table[] = { + { .compatible = "qcom,rpmcc-msm8226", .data = &rpm_clk_msm8974 }, { .compatible = "qcom,rpmcc-msm8916", .data = &rpm_clk_msm8916 }, { .compatible = "qcom,rpmcc-msm8936", .data = &rpm_clk_msm8936 }, { .compatible = "qcom,rpmcc-msm8974", .data = &rpm_clk_msm8974 }, From 652c96bb9bfe5e28f859785575d68e8d50140c14 Mon Sep 17 00:00:00 2001 From: Pu Lehui Date: Wed, 9 Jun 2021 14:18:48 +0800 Subject: [PATCH 104/161] clk/qcom: Remove unused variables Fix gcc '-Wunused-const-variable' warnings: drivers/clk/qcom/gcc-mdm9607.c:122:37: warning: 'gcc_xo_gpll0_gpll1' defined but not used [-Wunused-const-variable=] drivers/clk/qcom/gcc-mdm9607.c:116:32: warning: 'gcc_xo_gpll0_gpll1_map' defined but not used [-Wunused-const-variable=] drivers/clk/qcom/gcc-mdm9607.c:42:37: warning: 'gcc_xo_sleep' defined but not used [-Wunused-const-variable=] drivers/clk/qcom/gcc-mdm9607.c:37:32: warning: 'gcc_xo_sleep_map' defined but not used [-Wunused-const-variable=] Let's remove them. Signed-off-by: Pu Lehui Link: https://lore.kernel.org/r/20210609061848.87415-1-pulehui@huawei.com Reported-by: kbuild test robot Signed-off-by: Stephen Boyd --- drivers/clk/qcom/gcc-mdm9607.c | 23 ----------------------- 1 file changed, 23 deletions(-) diff --git a/drivers/clk/qcom/gcc-mdm9607.c b/drivers/clk/qcom/gcc-mdm9607.c index 5918dc51ffcd..4c9078e99bb3 100644 --- a/drivers/clk/qcom/gcc-mdm9607.c +++ b/drivers/clk/qcom/gcc-mdm9607.c @@ -34,16 +34,6 @@ enum { P_SLEEP_CLK, }; -static const struct parent_map gcc_xo_sleep_map[] = { - { P_XO, 0 }, - { P_SLEEP_CLK, 6 } -}; - -static const struct clk_parent_data gcc_xo_sleep[] = { - { .fw_name = "xo" }, - { .fw_name = "sleep_clk" }, -}; - static struct clk_alpha_pll gpll0_early = { .offset = 0x21000, .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT], @@ -113,19 +103,6 @@ static struct clk_regmap gpll1_vote = { }, }; -static const struct parent_map gcc_xo_gpll0_gpll1_map[] = { - { P_XO, 0 }, - { P_GPLL0, 1 }, - { P_GPLL1, 2 }, -}; - -static const struct clk_parent_data gcc_xo_gpll0_gpll1[] = { - { .fw_name = "xo" }, - { .hw = &gpll0.clkr.hw }, - { .hw = &gpll1_vote.hw }, -}; - - static const struct parent_map gcc_xo_gpll0_gpll1_sleep_map[] = { { P_XO, 0 }, { P_GPLL0, 1 }, From f21b6bfecc2760eaa9c2b485c74dffddbe92151a Mon Sep 17 00:00:00 2001 From: Jonathan Marek Date: Tue, 8 Jun 2021 22:20:46 -0400 Subject: [PATCH 105/161] clk: qcom: clk-alpha-pll: add support for zonda pll Ported over from the downstream driver. Will be used by SM8250 CAMCC. Signed-off-by: Jonathan Marek Link: https://lore.kernel.org/r/20210609022051.2171-2-jonathan@marek.ca Signed-off-by: Stephen Boyd --- drivers/clk/qcom/clk-alpha-pll.c | 174 +++++++++++++++++++++++++++++++ drivers/clk/qcom/clk-alpha-pll.h | 6 ++ 2 files changed, 180 insertions(+) diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c index c6eb99169ddc..94b53c7db2f7 100644 --- a/drivers/clk/qcom/clk-alpha-pll.c +++ b/drivers/clk/qcom/clk-alpha-pll.c @@ -126,6 +126,19 @@ const u8 clk_alpha_pll_regs[][PLL_OFF_MAX_REGS] = { [PLL_OFF_TEST_CTL_U] = 0x1c, [PLL_OFF_STATUS] = 0x2c, }, + [CLK_ALPHA_PLL_TYPE_ZONDA] = { + [PLL_OFF_L_VAL] = 0x04, + [PLL_OFF_ALPHA_VAL] = 0x08, + [PLL_OFF_USER_CTL] = 0x0c, + [PLL_OFF_CONFIG_CTL] = 0x10, + [PLL_OFF_CONFIG_CTL_U] = 0x14, + [PLL_OFF_CONFIG_CTL_U1] = 0x18, + [PLL_OFF_TEST_CTL] = 0x1c, + [PLL_OFF_TEST_CTL_U] = 0x20, + [PLL_OFF_TEST_CTL_U1] = 0x24, + [PLL_OFF_OPMODE] = 0x28, + [PLL_OFF_STATUS] = 0x38, + }, }; EXPORT_SYMBOL_GPL(clk_alpha_pll_regs); @@ -162,6 +175,11 @@ EXPORT_SYMBOL_GPL(clk_alpha_pll_regs); #define LUCID_5LPE_PLL_LATCH_INPUT BIT(14) #define LUCID_5LPE_ENABLE_VOTE_RUN BIT(21) +/* ZONDA PLL specific */ +#define ZONDA_PLL_OUT_MASK 0xf +#define ZONDA_STAY_IN_CFA BIT(16) +#define ZONDA_PLL_FREQ_LOCK_DET BIT(29) + #define pll_alpha_width(p) \ ((PLL_ALPHA_VAL_U(p) - PLL_ALPHA_VAL(p) == 4) ? \ ALPHA_REG_BITWIDTH : ALPHA_REG_16BIT_WIDTH) @@ -208,6 +226,9 @@ static int wait_for_pll(struct clk_alpha_pll *pll, u32 mask, bool inverse, #define wait_for_pll_enable_lock(pll) \ wait_for_pll(pll, PLL_LOCK_DET, 0, "enable") +#define wait_for_zonda_pll_freq_lock(pll) \ + wait_for_pll(pll, ZONDA_PLL_FREQ_LOCK_DET, 0, "freq enable") + #define wait_for_pll_disable(pll) \ wait_for_pll(pll, PLL_ACTIVE_FLAG, 1, "disable") @@ -1777,3 +1798,156 @@ const struct clk_ops clk_alpha_pll_postdiv_lucid_5lpe_ops = { .set_rate = clk_lucid_5lpe_pll_postdiv_set_rate, }; EXPORT_SYMBOL(clk_alpha_pll_postdiv_lucid_5lpe_ops); + +void clk_zonda_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap, + const struct alpha_pll_config *config) +{ + clk_alpha_pll_write_config(regmap, PLL_L_VAL(pll), config->l); + clk_alpha_pll_write_config(regmap, PLL_ALPHA_VAL(pll), config->alpha); + clk_alpha_pll_write_config(regmap, PLL_CONFIG_CTL(pll), config->config_ctl_val); + clk_alpha_pll_write_config(regmap, PLL_CONFIG_CTL_U(pll), config->config_ctl_hi_val); + clk_alpha_pll_write_config(regmap, PLL_CONFIG_CTL_U1(pll), config->config_ctl_hi1_val); + clk_alpha_pll_write_config(regmap, PLL_USER_CTL(pll), config->user_ctl_val); + clk_alpha_pll_write_config(regmap, PLL_USER_CTL_U(pll), config->user_ctl_hi_val); + clk_alpha_pll_write_config(regmap, PLL_USER_CTL_U1(pll), config->user_ctl_hi1_val); + clk_alpha_pll_write_config(regmap, PLL_TEST_CTL(pll), config->test_ctl_val); + clk_alpha_pll_write_config(regmap, PLL_TEST_CTL_U(pll), config->test_ctl_hi_val); + clk_alpha_pll_write_config(regmap, PLL_TEST_CTL_U1(pll), config->test_ctl_hi1_val); + + regmap_update_bits(regmap, PLL_MODE(pll), PLL_BYPASSNL, 0); + + /* Disable PLL output */ + regmap_update_bits(regmap, PLL_MODE(pll), PLL_OUTCTRL, 0); + + /* Set operation mode to OFF */ + regmap_write(regmap, PLL_OPMODE(pll), PLL_STANDBY); + + /* Place the PLL in STANDBY mode */ + regmap_update_bits(regmap, PLL_MODE(pll), PLL_RESET_N, PLL_RESET_N); +} +EXPORT_SYMBOL_GPL(clk_zonda_pll_configure); + +static int clk_zonda_pll_enable(struct clk_hw *hw) +{ + struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); + struct regmap *regmap = pll->clkr.regmap; + u32 val; + int ret; + + regmap_read(regmap, PLL_MODE(pll), &val); + + /* If in FSM mode, just vote for it */ + if (val & PLL_VOTE_FSM_ENA) { + ret = clk_enable_regmap(hw); + if (ret) + return ret; + return wait_for_pll_enable_active(pll); + } + + /* Get the PLL out of bypass mode */ + regmap_update_bits(regmap, PLL_MODE(pll), PLL_BYPASSNL, PLL_BYPASSNL); + + /* + * H/W requires a 1us delay between disabling the bypass and + * de-asserting the reset. + */ + udelay(1); + + regmap_update_bits(regmap, PLL_MODE(pll), PLL_RESET_N, PLL_RESET_N); + + /* Set operation mode to RUN */ + regmap_write(regmap, PLL_OPMODE(pll), PLL_RUN); + + regmap_read(regmap, PLL_TEST_CTL(pll), &val); + + /* If cfa mode then poll for freq lock */ + if (val & ZONDA_STAY_IN_CFA) + ret = wait_for_zonda_pll_freq_lock(pll); + else + ret = wait_for_pll_enable_lock(pll); + if (ret) + return ret; + + /* Enable the PLL outputs */ + regmap_update_bits(regmap, PLL_USER_CTL(pll), ZONDA_PLL_OUT_MASK, ZONDA_PLL_OUT_MASK); + + /* Enable the global PLL outputs */ + regmap_update_bits(regmap, PLL_MODE(pll), PLL_OUTCTRL, PLL_OUTCTRL); + + return 0; +} + +static void clk_zonda_pll_disable(struct clk_hw *hw) +{ + struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); + struct regmap *regmap = pll->clkr.regmap; + u32 val; + + regmap_read(regmap, PLL_MODE(pll), &val); + + /* If in FSM mode, just unvote it */ + if (val & PLL_VOTE_FSM_ENA) { + clk_disable_regmap(hw); + return; + } + + /* Disable the global PLL output */ + regmap_update_bits(regmap, PLL_MODE(pll), PLL_OUTCTRL, 0); + + /* Disable the PLL outputs */ + regmap_update_bits(regmap, PLL_USER_CTL(pll), ZONDA_PLL_OUT_MASK, 0); + + /* Put the PLL in bypass and reset */ + regmap_update_bits(regmap, PLL_MODE(pll), PLL_RESET_N | PLL_BYPASSNL, 0); + + /* Place the PLL mode in OFF state */ + regmap_write(regmap, PLL_OPMODE(pll), 0x0); +} + +static int clk_zonda_pll_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long prate) +{ + struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); + unsigned long rrate; + u32 test_ctl_val; + u32 l, alpha_width = pll_alpha_width(pll); + u64 a; + int ret; + + rrate = alpha_pll_round_rate(rate, prate, &l, &a, alpha_width); + + ret = alpha_pll_check_rate_margin(hw, rrate, rate); + if (ret < 0) + return ret; + + regmap_write(pll->clkr.regmap, PLL_ALPHA_VAL(pll), a); + regmap_write(pll->clkr.regmap, PLL_L_VAL(pll), l); + + /* Wait before polling for the frequency latch */ + udelay(5); + + /* Read stay in cfa mode */ + regmap_read(pll->clkr.regmap, PLL_TEST_CTL(pll), &test_ctl_val); + + /* If cfa mode then poll for freq lock */ + if (test_ctl_val & ZONDA_STAY_IN_CFA) + ret = wait_for_zonda_pll_freq_lock(pll); + else + ret = wait_for_pll_enable_lock(pll); + if (ret) + return ret; + + /* Wait for PLL output to stabilize */ + udelay(100); + return 0; +} + +const struct clk_ops clk_alpha_pll_zonda_ops = { + .enable = clk_zonda_pll_enable, + .disable = clk_zonda_pll_disable, + .is_enabled = clk_trion_pll_is_enabled, + .recalc_rate = clk_trion_pll_recalc_rate, + .round_rate = clk_alpha_pll_round_rate, + .set_rate = clk_zonda_pll_set_rate, +}; +EXPORT_SYMBOL(clk_alpha_pll_zonda_ops); diff --git a/drivers/clk/qcom/clk-alpha-pll.h b/drivers/clk/qcom/clk-alpha-pll.h index 6943e933be0f..55e4fa47912f 100644 --- a/drivers/clk/qcom/clk-alpha-pll.h +++ b/drivers/clk/qcom/clk-alpha-pll.h @@ -16,6 +16,7 @@ enum { CLK_ALPHA_PLL_TYPE_TRION, CLK_ALPHA_PLL_TYPE_LUCID = CLK_ALPHA_PLL_TYPE_TRION, CLK_ALPHA_PLL_TYPE_AGERA, + CLK_ALPHA_PLL_TYPE_ZONDA, CLK_ALPHA_PLL_TYPE_MAX, }; @@ -148,6 +149,9 @@ extern const struct clk_ops clk_alpha_pll_lucid_5lpe_ops; extern const struct clk_ops clk_alpha_pll_fixed_lucid_5lpe_ops; extern const struct clk_ops clk_alpha_pll_postdiv_lucid_5lpe_ops; +extern const struct clk_ops clk_alpha_pll_zonda_ops; +#define clk_alpha_pll_postdiv_zonda_ops clk_alpha_pll_postdiv_fabia_ops + void clk_alpha_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap, const struct alpha_pll_config *config); void clk_fabia_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap, @@ -159,6 +163,8 @@ void clk_agera_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap, #define clk_lucid_pll_configure(pll, regmap, config) \ clk_trion_pll_configure(pll, regmap, config) +void clk_zonda_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap, + const struct alpha_pll_config *config); #endif From a3b82fa77b861364b5abac3bf310124276e8f65d Mon Sep 17 00:00:00 2001 From: Jonathan Marek Date: Tue, 8 Jun 2021 22:20:47 -0400 Subject: [PATCH 106/161] dt-bindings: clock: add QCOM SM8250 camera clock bindings Add device tree bindings for camera clock controller for Qualcomm Technology Inc's SM8250 SoC. Signed-off-by: Jonathan Marek Link: https://lore.kernel.org/r/20210609022051.2171-3-jonathan@marek.ca Reviewed-by: Rob Herring Signed-off-by: Stephen Boyd --- .../bindings/clock/qcom,camcc-sm8250.yaml | 68 +++++++++ include/dt-bindings/clock/qcom,camcc-sm8250.h | 138 ++++++++++++++++++ 2 files changed, 206 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/qcom,camcc-sm8250.yaml create mode 100644 include/dt-bindings/clock/qcom,camcc-sm8250.h diff --git a/Documentation/devicetree/bindings/clock/qcom,camcc-sm8250.yaml b/Documentation/devicetree/bindings/clock/qcom,camcc-sm8250.yaml new file mode 100644 index 000000000000..9f239c3960d1 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/qcom,camcc-sm8250.yaml @@ -0,0 +1,68 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/qcom,camcc-sm8250.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm Camera Clock & Reset Controller Binding for SM8250 + +maintainers: + - Jonathan Marek + +description: | + Qualcomm camera clock control module which supports the clocks, resets and + power domains on SM8250. + + See also dt-bindings/clock/qcom,camcc-sm8250.h + +properties: + compatible: + const: qcom,sm8250-camcc + + clocks: + items: + - description: Board XO source + - description: Sleep clock source + + clock-names: + items: + - const: bi_tcxo + - const: sleep_clk + + '#clock-cells': + const: 1 + + '#reset-cells': + const: 1 + + '#power-domain-cells': + const: 1 + + reg: + maxItems: 1 + +required: + - compatible + - reg + - clocks + - clock-names + - '#clock-cells' + - '#reset-cells' + - '#power-domain-cells' + +additionalProperties: false + +examples: + - | + #include + clock-controller@ad00000 { + compatible = "qcom,sm8250-camcc"; + reg = <0x0ad00000 0x10000>; + clocks = <&rpmhcc RPMH_CXO_CLK>, + <&sleep_clk>; + clock-names = "bi_tcxo", "sleep_clk"; + #clock-cells = <1>; + #reset-cells = <1>; + #power-domain-cells = <1>; + }; +... diff --git a/include/dt-bindings/clock/qcom,camcc-sm8250.h b/include/dt-bindings/clock/qcom,camcc-sm8250.h new file mode 100644 index 000000000000..383ead17608d --- /dev/null +++ b/include/dt-bindings/clock/qcom,camcc-sm8250.h @@ -0,0 +1,138 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2018-2021, The Linux Foundation. All rights reserved. + */ + +#ifndef _DT_BINDINGS_CLK_QCOM_CAM_CC_SM8250_H +#define _DT_BINDINGS_CLK_QCOM_CAM_CC_SM8250_H + +/* CAM_CC clocks */ +#define CAM_CC_BPS_AHB_CLK 0 +#define CAM_CC_BPS_AREG_CLK 1 +#define CAM_CC_BPS_AXI_CLK 2 +#define CAM_CC_BPS_CLK 3 +#define CAM_CC_BPS_CLK_SRC 4 +#define CAM_CC_CAMNOC_AXI_CLK 5 +#define CAM_CC_CAMNOC_AXI_CLK_SRC 6 +#define CAM_CC_CAMNOC_DCD_XO_CLK 7 +#define CAM_CC_CCI_0_CLK 8 +#define CAM_CC_CCI_0_CLK_SRC 9 +#define CAM_CC_CCI_1_CLK 10 +#define CAM_CC_CCI_1_CLK_SRC 11 +#define CAM_CC_CORE_AHB_CLK 12 +#define CAM_CC_CPAS_AHB_CLK 13 +#define CAM_CC_CPHY_RX_CLK_SRC 14 +#define CAM_CC_CSI0PHYTIMER_CLK 15 +#define CAM_CC_CSI0PHYTIMER_CLK_SRC 16 +#define CAM_CC_CSI1PHYTIMER_CLK 17 +#define CAM_CC_CSI1PHYTIMER_CLK_SRC 18 +#define CAM_CC_CSI2PHYTIMER_CLK 19 +#define CAM_CC_CSI2PHYTIMER_CLK_SRC 20 +#define CAM_CC_CSI3PHYTIMER_CLK 21 +#define CAM_CC_CSI3PHYTIMER_CLK_SRC 22 +#define CAM_CC_CSI4PHYTIMER_CLK 23 +#define CAM_CC_CSI4PHYTIMER_CLK_SRC 24 +#define CAM_CC_CSI5PHYTIMER_CLK 25 +#define CAM_CC_CSI5PHYTIMER_CLK_SRC 26 +#define CAM_CC_CSIPHY0_CLK 27 +#define CAM_CC_CSIPHY1_CLK 28 +#define CAM_CC_CSIPHY2_CLK 29 +#define CAM_CC_CSIPHY3_CLK 30 +#define CAM_CC_CSIPHY4_CLK 31 +#define CAM_CC_CSIPHY5_CLK 32 +#define CAM_CC_FAST_AHB_CLK_SRC 33 +#define CAM_CC_FD_CORE_CLK 34 +#define CAM_CC_FD_CORE_CLK_SRC 35 +#define CAM_CC_FD_CORE_UAR_CLK 36 +#define CAM_CC_GDSC_CLK 37 +#define CAM_CC_ICP_AHB_CLK 38 +#define CAM_CC_ICP_CLK 39 +#define CAM_CC_ICP_CLK_SRC 40 +#define CAM_CC_IFE_0_AHB_CLK 41 +#define CAM_CC_IFE_0_AREG_CLK 42 +#define CAM_CC_IFE_0_AXI_CLK 43 +#define CAM_CC_IFE_0_CLK 44 +#define CAM_CC_IFE_0_CLK_SRC 45 +#define CAM_CC_IFE_0_CPHY_RX_CLK 46 +#define CAM_CC_IFE_0_CSID_CLK 47 +#define CAM_CC_IFE_0_CSID_CLK_SRC 48 +#define CAM_CC_IFE_0_DSP_CLK 49 +#define CAM_CC_IFE_1_AHB_CLK 50 +#define CAM_CC_IFE_1_AREG_CLK 51 +#define CAM_CC_IFE_1_AXI_CLK 52 +#define CAM_CC_IFE_1_CLK 53 +#define CAM_CC_IFE_1_CLK_SRC 54 +#define CAM_CC_IFE_1_CPHY_RX_CLK 55 +#define CAM_CC_IFE_1_CSID_CLK 56 +#define CAM_CC_IFE_1_CSID_CLK_SRC 57 +#define CAM_CC_IFE_1_DSP_CLK 58 +#define CAM_CC_IFE_LITE_AHB_CLK 59 +#define CAM_CC_IFE_LITE_AXI_CLK 60 +#define CAM_CC_IFE_LITE_CLK 61 +#define CAM_CC_IFE_LITE_CLK_SRC 62 +#define CAM_CC_IFE_LITE_CPHY_RX_CLK 63 +#define CAM_CC_IFE_LITE_CSID_CLK 64 +#define CAM_CC_IFE_LITE_CSID_CLK_SRC 65 +#define CAM_CC_IPE_0_AHB_CLK 66 +#define CAM_CC_IPE_0_AREG_CLK 67 +#define CAM_CC_IPE_0_AXI_CLK 68 +#define CAM_CC_IPE_0_CLK 69 +#define CAM_CC_IPE_0_CLK_SRC 70 +#define CAM_CC_JPEG_CLK 71 +#define CAM_CC_JPEG_CLK_SRC 72 +#define CAM_CC_MCLK0_CLK 73 +#define CAM_CC_MCLK0_CLK_SRC 74 +#define CAM_CC_MCLK1_CLK 75 +#define CAM_CC_MCLK1_CLK_SRC 76 +#define CAM_CC_MCLK2_CLK 77 +#define CAM_CC_MCLK2_CLK_SRC 78 +#define CAM_CC_MCLK3_CLK 79 +#define CAM_CC_MCLK3_CLK_SRC 80 +#define CAM_CC_MCLK4_CLK 81 +#define CAM_CC_MCLK4_CLK_SRC 82 +#define CAM_CC_MCLK5_CLK 83 +#define CAM_CC_MCLK5_CLK_SRC 84 +#define CAM_CC_MCLK6_CLK 85 +#define CAM_CC_MCLK6_CLK_SRC 86 +#define CAM_CC_PLL0 87 +#define CAM_CC_PLL0_OUT_EVEN 88 +#define CAM_CC_PLL0_OUT_ODD 89 +#define CAM_CC_PLL1 90 +#define CAM_CC_PLL1_OUT_EVEN 91 +#define CAM_CC_PLL2 92 +#define CAM_CC_PLL2_OUT_MAIN 93 +#define CAM_CC_PLL3 94 +#define CAM_CC_PLL3_OUT_EVEN 95 +#define CAM_CC_PLL4 96 +#define CAM_CC_PLL4_OUT_EVEN 97 +#define CAM_CC_SBI_AHB_CLK 98 +#define CAM_CC_SBI_AXI_CLK 99 +#define CAM_CC_SBI_CLK 100 +#define CAM_CC_SBI_CPHY_RX_CLK 101 +#define CAM_CC_SBI_CSID_CLK 102 +#define CAM_CC_SBI_CSID_CLK_SRC 103 +#define CAM_CC_SBI_DIV_CLK_SRC 104 +#define CAM_CC_SBI_IFE_0_CLK 105 +#define CAM_CC_SBI_IFE_1_CLK 106 +#define CAM_CC_SLEEP_CLK 107 +#define CAM_CC_SLEEP_CLK_SRC 108 +#define CAM_CC_SLOW_AHB_CLK_SRC 109 +#define CAM_CC_XO_CLK_SRC 110 + +/* CAM_CC resets */ +#define CAM_CC_BPS_BCR 0 +#define CAM_CC_ICP_BCR 1 +#define CAM_CC_IFE_0_BCR 2 +#define CAM_CC_IFE_1_BCR 3 +#define CAM_CC_IPE_0_BCR 4 +#define CAM_CC_SBI_BCR 5 + +/* CAM_CC GDSCRs */ +#define BPS_GDSC 0 +#define IPE_0_GDSC 1 +#define SBI_GDSC 2 +#define IFE_0_GDSC 3 +#define IFE_1_GDSC 4 +#define TITAN_TOP_GDSC 5 + +#endif From 5d66ca79b58cb3cbeb4720c7da064faf03c27446 Mon Sep 17 00:00:00 2001 From: Jonathan Marek Date: Tue, 8 Jun 2021 22:20:48 -0400 Subject: [PATCH 107/161] clk: qcom: Add camera clock controller driver for SM8250 Add support for the camera clock controller found on SM8250. Based on the downstream driver. Signed-off-by: Jonathan Marek Reviewed-by: Robert Foss Link: https://lore.kernel.org/r/20210609022051.2171-4-jonathan@marek.ca [sboyd@kernel.org: Add UL to avoid decimal problems] Signed-off-by: Stephen Boyd --- drivers/clk/qcom/Kconfig | 7 + drivers/clk/qcom/Makefile | 1 + drivers/clk/qcom/camcc-sm8250.c | 2456 +++++++++++++++++++++++++++++++ 3 files changed, 2464 insertions(+) create mode 100644 drivers/clk/qcom/camcc-sm8250.c diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig index dba1f266dc45..62e00e15495c 100644 --- a/drivers/clk/qcom/Kconfig +++ b/drivers/clk/qcom/Kconfig @@ -490,6 +490,13 @@ config SDX_GCC_55 Say Y if you want to use peripheral devices such as UART, SPI, I2C, USB, SD/UFS, PCIe etc. +config SM_CAMCC_8250 + tristate "SM8250 Camera Clock Controller" + select SM_GCC_8250 + help + Support for the camera clock controller on SM8250 devices. + Say Y if you want to support camera devices and camera functionality. + config SM_DISPCC_8250 tristate "SM8150 and SM8250 Display Clock Controller" depends on SM_GCC_8150 || SM_GCC_8250 diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile index 0f1ad7a0b22f..c2a1cafb31bc 100644 --- a/drivers/clk/qcom/Makefile +++ b/drivers/clk/qcom/Makefile @@ -74,6 +74,7 @@ obj-$(CONFIG_SDM_GPUCC_845) += gpucc-sdm845.o obj-$(CONFIG_SDM_LPASSCC_845) += lpasscc-sdm845.o obj-$(CONFIG_SDM_VIDEOCC_845) += videocc-sdm845.o obj-$(CONFIG_SDX_GCC_55) += gcc-sdx55.o +obj-$(CONFIG_SM_CAMCC_8250) += camcc-sm8250.o obj-$(CONFIG_SM_DISPCC_8250) += dispcc-sm8250.o obj-$(CONFIG_SM_GCC_6125) += gcc-sm6125.o obj-$(CONFIG_SM_GCC_8150) += gcc-sm8150.o diff --git a/drivers/clk/qcom/camcc-sm8250.c b/drivers/clk/qcom/camcc-sm8250.c new file mode 100644 index 000000000000..439eaafdcc86 --- /dev/null +++ b/drivers/clk/qcom/camcc-sm8250.c @@ -0,0 +1,2456 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2018-2021, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include +#include + +#include + +#include "clk-alpha-pll.h" +#include "clk-branch.h" +#include "clk-rcg.h" +#include "clk-regmap-divider.h" +#include "common.h" +#include "gdsc.h" +#include "reset.h" + +enum { + P_BI_TCXO, + P_CAM_CC_PLL0_OUT_EVEN, + P_CAM_CC_PLL0_OUT_MAIN, + P_CAM_CC_PLL0_OUT_ODD, + P_CAM_CC_PLL1_OUT_EVEN, + P_CAM_CC_PLL2_OUT_EARLY, + P_CAM_CC_PLL2_OUT_MAIN, + P_CAM_CC_PLL3_OUT_EVEN, + P_CAM_CC_PLL4_OUT_EVEN, + P_SLEEP_CLK, +}; + +static struct pll_vco lucid_vco[] = { + { 249600000, 2000000000, 0 }, +}; + +static struct pll_vco zonda_vco[] = { + { 595200000UL, 3600000000UL, 0 }, +}; + +static const struct alpha_pll_config cam_cc_pll0_config = { + .l = 0x3e, + .alpha = 0x8000, + .config_ctl_val = 0x20485699, + .config_ctl_hi_val = 0x00002261, + .config_ctl_hi1_val = 0x329A699c, + .user_ctl_val = 0x00003100, + .user_ctl_hi_val = 0x00000805, + .user_ctl_hi1_val = 0x00000000, +}; + +static struct clk_alpha_pll cam_cc_pll0 = { + .offset = 0x0, + .vco_table = lucid_vco, + .num_vco = ARRAY_SIZE(lucid_vco), + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID], + .clkr = { + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_pll0", + .parent_data = &(const struct clk_parent_data){ + .fw_name = "bi_tcxo", + }, + .num_parents = 1, + .ops = &clk_alpha_pll_lucid_ops, + }, + }, +}; + +static const struct clk_div_table post_div_table_cam_cc_pll0_out_even[] = { + { 0x1, 2 }, + { } +}; + +static struct clk_alpha_pll_postdiv cam_cc_pll0_out_even = { + .offset = 0x0, + .post_div_shift = 8, + .post_div_table = post_div_table_cam_cc_pll0_out_even, + .num_post_div = ARRAY_SIZE(post_div_table_cam_cc_pll0_out_even), + .width = 4, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID], + .clkr.hw.init = &(struct clk_init_data){ + .name = "cam_cc_pll0_out_even", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_pll0.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_alpha_pll_postdiv_lucid_ops, + }, +}; + +static const struct clk_div_table post_div_table_cam_cc_pll0_out_odd[] = { + { 0x3, 3 }, + { } +}; + +static struct clk_alpha_pll_postdiv cam_cc_pll0_out_odd = { + .offset = 0x0, + .post_div_shift = 12, + .post_div_table = post_div_table_cam_cc_pll0_out_odd, + .num_post_div = ARRAY_SIZE(post_div_table_cam_cc_pll0_out_odd), + .width = 4, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID], + .clkr.hw.init = &(struct clk_init_data){ + .name = "cam_cc_pll0_out_odd", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_pll0.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_alpha_pll_postdiv_lucid_ops, + }, +}; + +static const struct alpha_pll_config cam_cc_pll1_config = { + .l = 0x1f, + .alpha = 0x4000, + .config_ctl_val = 0x20485699, + .config_ctl_hi_val = 0x00002261, + .config_ctl_hi1_val = 0x329A699c, + .user_ctl_val = 0x00000100, + .user_ctl_hi_val = 0x00000805, + .user_ctl_hi1_val = 0x00000000, +}; + +static struct clk_alpha_pll cam_cc_pll1 = { + .offset = 0x1000, + .vco_table = lucid_vco, + .num_vco = ARRAY_SIZE(lucid_vco), + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID], + .clkr = { + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_pll1", + .parent_data = &(const struct clk_parent_data){ + .fw_name = "bi_tcxo", + }, + .num_parents = 1, + .ops = &clk_alpha_pll_lucid_ops, + }, + }, +}; + +static const struct clk_div_table post_div_table_cam_cc_pll1_out_even[] = { + { 0x1, 2 }, + { } +}; + +static struct clk_alpha_pll_postdiv cam_cc_pll1_out_even = { + .offset = 0x1000, + .post_div_shift = 8, + .post_div_table = post_div_table_cam_cc_pll1_out_even, + .num_post_div = ARRAY_SIZE(post_div_table_cam_cc_pll1_out_even), + .width = 4, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID], + .clkr.hw.init = &(struct clk_init_data){ + .name = "cam_cc_pll1_out_even", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_pll1.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_alpha_pll_postdiv_lucid_ops, + }, +}; + +static const struct alpha_pll_config cam_cc_pll2_config = { + .l = 0x4b, + .alpha = 0x0, + .config_ctl_val = 0x08200920, + .config_ctl_hi_val = 0x05002015, + .config_ctl_hi1_val = 0x00000000, + .user_ctl_val = 0x00000100, + .user_ctl_hi_val = 0x00000000, + .user_ctl_hi1_val = 0x00000000, +}; + +static struct clk_alpha_pll cam_cc_pll2 = { + .offset = 0x2000, + .vco_table = zonda_vco, + .num_vco = ARRAY_SIZE(zonda_vco), + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_ZONDA], + .clkr = { + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_pll2", + .parent_data = &(const struct clk_parent_data){ + .fw_name = "bi_tcxo", + }, + .num_parents = 1, + .ops = &clk_alpha_pll_zonda_ops, + }, + }, +}; + +static const struct clk_div_table post_div_table_cam_cc_pll2_out_main[] = { + { 0x1, 2 }, + { } +}; + +static struct clk_alpha_pll_postdiv cam_cc_pll2_out_main = { + .offset = 0x2000, + .post_div_shift = 8, + .post_div_table = post_div_table_cam_cc_pll2_out_main, + .num_post_div = ARRAY_SIZE(post_div_table_cam_cc_pll2_out_main), + .width = 2, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_ZONDA], + .clkr.hw.init = &(struct clk_init_data){ + .name = "cam_cc_pll2_out_main", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_pll2.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_alpha_pll_postdiv_zonda_ops, + }, +}; + +static const struct alpha_pll_config cam_cc_pll3_config = { + .l = 0x24, + .alpha = 0x7555, + .config_ctl_val = 0x20485699, + .config_ctl_hi_val = 0x00002261, + .config_ctl_hi1_val = 0x329A699c, + .user_ctl_val = 0x00000100, + .user_ctl_hi_val = 0x00000805, + .user_ctl_hi1_val = 0x00000000, +}; + +static struct clk_alpha_pll cam_cc_pll3 = { + .offset = 0x3000, + .vco_table = lucid_vco, + .num_vco = ARRAY_SIZE(lucid_vco), + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID], + .clkr = { + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_pll3", + .parent_data = &(const struct clk_parent_data){ + .fw_name = "bi_tcxo", + }, + .num_parents = 1, + .ops = &clk_alpha_pll_lucid_ops, + }, + }, +}; + +static const struct clk_div_table post_div_table_cam_cc_pll3_out_even[] = { + { 0x1, 2 }, + { } +}; + +static struct clk_alpha_pll_postdiv cam_cc_pll3_out_even = { + .offset = 0x3000, + .post_div_shift = 8, + .post_div_table = post_div_table_cam_cc_pll3_out_even, + .num_post_div = ARRAY_SIZE(post_div_table_cam_cc_pll3_out_even), + .width = 4, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID], + .clkr.hw.init = &(struct clk_init_data){ + .name = "cam_cc_pll3_out_even", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_pll3.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_alpha_pll_postdiv_lucid_ops, + }, +}; + +static const struct alpha_pll_config cam_cc_pll4_config = { + .l = 0x24, + .alpha = 0x7555, + .config_ctl_val = 0x20485699, + .config_ctl_hi_val = 0x00002261, + .config_ctl_hi1_val = 0x329A699c, + .user_ctl_val = 0x00000100, + .user_ctl_hi_val = 0x00000805, + .user_ctl_hi1_val = 0x00000000, +}; + +static struct clk_alpha_pll cam_cc_pll4 = { + .offset = 0x4000, + .vco_table = lucid_vco, + .num_vco = ARRAY_SIZE(lucid_vco), + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID], + .clkr = { + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_pll4", + .parent_data = &(const struct clk_parent_data){ + .fw_name = "bi_tcxo", + }, + .num_parents = 1, + .ops = &clk_alpha_pll_lucid_ops, + }, + }, +}; + +static const struct clk_div_table post_div_table_cam_cc_pll4_out_even[] = { + { 0x1, 2 }, + { } +}; + +static struct clk_alpha_pll_postdiv cam_cc_pll4_out_even = { + .offset = 0x4000, + .post_div_shift = 8, + .post_div_table = post_div_table_cam_cc_pll4_out_even, + .num_post_div = ARRAY_SIZE(post_div_table_cam_cc_pll4_out_even), + .width = 4, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID], + .clkr.hw.init = &(struct clk_init_data){ + .name = "cam_cc_pll4_out_even", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_pll4.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_alpha_pll_postdiv_lucid_ops, + }, +}; + +static const struct parent_map cam_cc_parent_map_0[] = { + { P_BI_TCXO, 0 }, + { P_CAM_CC_PLL0_OUT_MAIN, 1 }, + { P_CAM_CC_PLL0_OUT_EVEN, 2 }, + { P_CAM_CC_PLL0_OUT_ODD, 3 }, + { P_CAM_CC_PLL2_OUT_MAIN, 5 }, +}; + +static const struct clk_parent_data cam_cc_parent_data_0[] = { + { .fw_name = "bi_tcxo" }, + { .hw = &cam_cc_pll0.clkr.hw }, + { .hw = &cam_cc_pll0_out_even.clkr.hw }, + { .hw = &cam_cc_pll0_out_odd.clkr.hw }, + { .hw = &cam_cc_pll2_out_main.clkr.hw }, +}; + +static const struct parent_map cam_cc_parent_map_1[] = { + { P_BI_TCXO, 0 }, + { P_CAM_CC_PLL2_OUT_EARLY, 5 }, +}; + +static const struct clk_parent_data cam_cc_parent_data_1[] = { + { .fw_name = "bi_tcxo" }, + { .hw = &cam_cc_pll2.clkr.hw }, +}; + +static const struct parent_map cam_cc_parent_map_2[] = { + { P_BI_TCXO, 0 }, + { P_CAM_CC_PLL3_OUT_EVEN, 6 }, +}; + +static const struct clk_parent_data cam_cc_parent_data_2[] = { + { .fw_name = "bi_tcxo" }, + { .hw = &cam_cc_pll3_out_even.clkr.hw }, +}; + +static const struct parent_map cam_cc_parent_map_3[] = { + { P_BI_TCXO, 0 }, + { P_CAM_CC_PLL4_OUT_EVEN, 6 }, +}; + +static const struct clk_parent_data cam_cc_parent_data_3[] = { + { .fw_name = "bi_tcxo" }, + { .hw = &cam_cc_pll4_out_even.clkr.hw }, +}; + +static const struct parent_map cam_cc_parent_map_4[] = { + { P_BI_TCXO, 0 }, + { P_CAM_CC_PLL1_OUT_EVEN, 4 }, +}; + +static const struct clk_parent_data cam_cc_parent_data_4[] = { + { .fw_name = "bi_tcxo" }, + { .hw = &cam_cc_pll1_out_even.clkr.hw }, +}; + +static const struct parent_map cam_cc_parent_map_5[] = { + { P_SLEEP_CLK, 0 }, +}; + +static const struct clk_parent_data cam_cc_parent_data_5[] = { + { .fw_name = "sleep_clk" }, +}; + +static const struct parent_map cam_cc_parent_map_6[] = { + { P_BI_TCXO, 0 }, +}; + +static const struct clk_parent_data cam_cc_parent_data_6[] = { + { .fw_name = "bi_tcxo" }, +}; + +static const struct freq_tbl ftbl_cam_cc_bps_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + F(100000000, P_CAM_CC_PLL0_OUT_EVEN, 6, 0, 0), + F(200000000, P_CAM_CC_PLL0_OUT_ODD, 2, 0, 0), + F(400000000, P_CAM_CC_PLL0_OUT_ODD, 1, 0, 0), + F(480000000, P_CAM_CC_PLL2_OUT_MAIN, 1.5, 0, 0), + F(600000000, P_CAM_CC_PLL0_OUT_MAIN, 2, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_bps_clk_src = { + .cmd_rcgr = 0x7010, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_0, + .freq_tbl = ftbl_cam_cc_bps_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "cam_cc_bps_clk_src", + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_cam_cc_camnoc_axi_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + F(300000000, P_CAM_CC_PLL0_OUT_EVEN, 2, 0, 0), + F(400000000, P_CAM_CC_PLL0_OUT_ODD, 1, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_camnoc_axi_clk_src = { + .cmd_rcgr = 0xc0f8, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_0, + .freq_tbl = ftbl_cam_cc_camnoc_axi_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "cam_cc_camnoc_axi_clk_src", + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_cam_cc_cci_0_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + F(37500000, P_CAM_CC_PLL0_OUT_EVEN, 16, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_cci_0_clk_src = { + .cmd_rcgr = 0xc0bc, + .mnd_width = 8, + .hid_width = 5, + .parent_map = cam_cc_parent_map_0, + .freq_tbl = ftbl_cam_cc_cci_0_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "cam_cc_cci_0_clk_src", + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 cam_cc_cci_1_clk_src = { + .cmd_rcgr = 0xc0d8, + .mnd_width = 8, + .hid_width = 5, + .parent_map = cam_cc_parent_map_0, + .freq_tbl = ftbl_cam_cc_cci_0_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "cam_cc_cci_1_clk_src", + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_cam_cc_cphy_rx_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + F(400000000, P_CAM_CC_PLL0_OUT_ODD, 1, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_cphy_rx_clk_src = { + .cmd_rcgr = 0xa068, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_0, + .freq_tbl = ftbl_cam_cc_cphy_rx_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "cam_cc_cphy_rx_clk_src", + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_cam_cc_csi0phytimer_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + F(300000000, P_CAM_CC_PLL0_OUT_EVEN, 2, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_csi0phytimer_clk_src = { + .cmd_rcgr = 0x6000, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_0, + .freq_tbl = ftbl_cam_cc_csi0phytimer_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "cam_cc_csi0phytimer_clk_src", + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 cam_cc_csi1phytimer_clk_src = { + .cmd_rcgr = 0x6020, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_0, + .freq_tbl = ftbl_cam_cc_csi0phytimer_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "cam_cc_csi1phytimer_clk_src", + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 cam_cc_csi2phytimer_clk_src = { + .cmd_rcgr = 0x6040, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_0, + .freq_tbl = ftbl_cam_cc_csi0phytimer_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "cam_cc_csi2phytimer_clk_src", + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 cam_cc_csi3phytimer_clk_src = { + .cmd_rcgr = 0x6060, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_0, + .freq_tbl = ftbl_cam_cc_csi0phytimer_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "cam_cc_csi3phytimer_clk_src", + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 cam_cc_csi4phytimer_clk_src = { + .cmd_rcgr = 0x6080, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_0, + .freq_tbl = ftbl_cam_cc_csi0phytimer_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "cam_cc_csi4phytimer_clk_src", + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 cam_cc_csi5phytimer_clk_src = { + .cmd_rcgr = 0x60a0, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_0, + .freq_tbl = ftbl_cam_cc_csi0phytimer_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "cam_cc_csi5phytimer_clk_src", + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_cam_cc_fast_ahb_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + F(50000000, P_CAM_CC_PLL0_OUT_EVEN, 12, 0, 0), + F(100000000, P_CAM_CC_PLL0_OUT_EVEN, 6, 0, 0), + F(200000000, P_CAM_CC_PLL0_OUT_EVEN, 3, 0, 0), + F(300000000, P_CAM_CC_PLL0_OUT_MAIN, 4, 0, 0), + F(400000000, P_CAM_CC_PLL0_OUT_MAIN, 3, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_fast_ahb_clk_src = { + .cmd_rcgr = 0x703c, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_0, + .freq_tbl = ftbl_cam_cc_fast_ahb_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "cam_cc_fast_ahb_clk_src", + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_cam_cc_fd_core_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + F(400000000, P_CAM_CC_PLL0_OUT_ODD, 1, 0, 0), + F(480000000, P_CAM_CC_PLL2_OUT_MAIN, 1.5, 0, 0), + F(600000000, P_CAM_CC_PLL0_OUT_MAIN, 2, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_fd_core_clk_src = { + .cmd_rcgr = 0xc098, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_0, + .freq_tbl = ftbl_cam_cc_fd_core_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "cam_cc_fd_core_clk_src", + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 cam_cc_icp_clk_src = { + .cmd_rcgr = 0xc074, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_0, + .freq_tbl = ftbl_cam_cc_fd_core_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "cam_cc_icp_clk_src", + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_cam_cc_ife_0_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + F(350000000, P_CAM_CC_PLL3_OUT_EVEN, 1, 0, 0), + F(475000000, P_CAM_CC_PLL3_OUT_EVEN, 1, 0, 0), + F(576000000, P_CAM_CC_PLL3_OUT_EVEN, 1, 0, 0), + F(680000000, P_CAM_CC_PLL3_OUT_EVEN, 1, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_ife_0_clk_src = { + .cmd_rcgr = 0xa010, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_2, + .freq_tbl = ftbl_cam_cc_ife_0_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "cam_cc_ife_0_clk_src", + .parent_data = cam_cc_parent_data_2, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_2), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_regmap_div cam_cc_sbi_div_clk_src = { + .reg = 0x9010, + .shift = 0, + .width = 3, + .clkr.hw.init = &(struct clk_init_data) { + .name = "cam_cc_sbi_div_clk_src", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_ife_0_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_regmap_div_ro_ops, + }, +}; + +static const struct freq_tbl ftbl_cam_cc_ife_0_csid_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + F(75000000, P_CAM_CC_PLL0_OUT_EVEN, 8, 0, 0), + F(400000000, P_CAM_CC_PLL0_OUT_ODD, 1, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_ife_0_csid_clk_src = { + .cmd_rcgr = 0xa040, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_0, + .freq_tbl = ftbl_cam_cc_ife_0_csid_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "cam_cc_ife_0_csid_clk_src", + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_cam_cc_ife_1_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + F(350000000, P_CAM_CC_PLL4_OUT_EVEN, 1, 0, 0), + F(475000000, P_CAM_CC_PLL4_OUT_EVEN, 1, 0, 0), + F(576000000, P_CAM_CC_PLL4_OUT_EVEN, 1, 0, 0), + F(680000000, P_CAM_CC_PLL4_OUT_EVEN, 1, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_ife_1_clk_src = { + .cmd_rcgr = 0xb010, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_3, + .freq_tbl = ftbl_cam_cc_ife_1_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "cam_cc_ife_1_clk_src", + .parent_data = cam_cc_parent_data_3, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_3), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 cam_cc_ife_1_csid_clk_src = { + .cmd_rcgr = 0xb040, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_0, + .freq_tbl = ftbl_cam_cc_ife_0_csid_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "cam_cc_ife_1_csid_clk_src", + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_cam_cc_ife_lite_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + F(400000000, P_CAM_CC_PLL0_OUT_ODD, 1, 0, 0), + F(480000000, P_CAM_CC_PLL2_OUT_MAIN, 1.5, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_ife_lite_clk_src = { + .cmd_rcgr = 0xc000, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_0, + .freq_tbl = ftbl_cam_cc_ife_lite_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "cam_cc_ife_lite_clk_src", + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 cam_cc_ife_lite_csid_clk_src = { + .cmd_rcgr = 0xc01c, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_0, + .freq_tbl = ftbl_cam_cc_cphy_rx_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "cam_cc_ife_lite_csid_clk_src", + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_cam_cc_ipe_0_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + F(300000000, P_CAM_CC_PLL1_OUT_EVEN, 1, 0, 0), + F(475000000, P_CAM_CC_PLL1_OUT_EVEN, 1, 0, 0), + F(525000000, P_CAM_CC_PLL1_OUT_EVEN, 1, 0, 0), + F(700000000, P_CAM_CC_PLL1_OUT_EVEN, 1, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_ipe_0_clk_src = { + .cmd_rcgr = 0x8010, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_4, + .freq_tbl = ftbl_cam_cc_ipe_0_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "cam_cc_ipe_0_clk_src", + .parent_data = cam_cc_parent_data_4, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_4), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 cam_cc_jpeg_clk_src = { + .cmd_rcgr = 0xc048, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_0, + .freq_tbl = ftbl_cam_cc_bps_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "cam_cc_jpeg_clk_src", + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_cam_cc_mclk0_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + F(24000000, P_CAM_CC_PLL2_OUT_EARLY, 10, 1, 6), + F(68571429, P_CAM_CC_PLL2_OUT_EARLY, 1, 1, 21), + { } +}; + +static struct clk_rcg2 cam_cc_mclk0_clk_src = { + .cmd_rcgr = 0x5000, + .mnd_width = 8, + .hid_width = 5, + .parent_map = cam_cc_parent_map_1, + .freq_tbl = ftbl_cam_cc_mclk0_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "cam_cc_mclk0_clk_src", + .parent_data = cam_cc_parent_data_1, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_1), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 cam_cc_mclk1_clk_src = { + .cmd_rcgr = 0x501c, + .mnd_width = 8, + .hid_width = 5, + .parent_map = cam_cc_parent_map_1, + .freq_tbl = ftbl_cam_cc_mclk0_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "cam_cc_mclk1_clk_src", + .parent_data = cam_cc_parent_data_1, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_1), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 cam_cc_mclk2_clk_src = { + .cmd_rcgr = 0x5038, + .mnd_width = 8, + .hid_width = 5, + .parent_map = cam_cc_parent_map_1, + .freq_tbl = ftbl_cam_cc_mclk0_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "cam_cc_mclk2_clk_src", + .parent_data = cam_cc_parent_data_1, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_1), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 cam_cc_mclk3_clk_src = { + .cmd_rcgr = 0x5054, + .mnd_width = 8, + .hid_width = 5, + .parent_map = cam_cc_parent_map_1, + .freq_tbl = ftbl_cam_cc_mclk0_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "cam_cc_mclk3_clk_src", + .parent_data = cam_cc_parent_data_1, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_1), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 cam_cc_mclk4_clk_src = { + .cmd_rcgr = 0x5070, + .mnd_width = 8, + .hid_width = 5, + .parent_map = cam_cc_parent_map_1, + .freq_tbl = ftbl_cam_cc_mclk0_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "cam_cc_mclk4_clk_src", + .parent_data = cam_cc_parent_data_1, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_1), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 cam_cc_mclk5_clk_src = { + .cmd_rcgr = 0x508c, + .mnd_width = 8, + .hid_width = 5, + .parent_map = cam_cc_parent_map_1, + .freq_tbl = ftbl_cam_cc_mclk0_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "cam_cc_mclk5_clk_src", + .parent_data = cam_cc_parent_data_1, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_1), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 cam_cc_mclk6_clk_src = { + .cmd_rcgr = 0x50a8, + .mnd_width = 8, + .hid_width = 5, + .parent_map = cam_cc_parent_map_1, + .freq_tbl = ftbl_cam_cc_mclk0_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "cam_cc_mclk6_clk_src", + .parent_data = cam_cc_parent_data_1, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_1), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 cam_cc_sbi_csid_clk_src = { + .cmd_rcgr = 0x901c, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_0, + .freq_tbl = ftbl_cam_cc_cphy_rx_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "cam_cc_sbi_csid_clk_src", + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_cam_cc_sleep_clk_src[] = { + F(32768, P_SLEEP_CLK, 1, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_sleep_clk_src = { + .cmd_rcgr = 0xc170, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_5, + .freq_tbl = ftbl_cam_cc_sleep_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "cam_cc_sleep_clk_src", + .parent_data = cam_cc_parent_data_5, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_5), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_cam_cc_slow_ahb_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + F(80000000, P_CAM_CC_PLL0_OUT_EVEN, 7.5, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_slow_ahb_clk_src = { + .cmd_rcgr = 0x7058, + .mnd_width = 8, + .hid_width = 5, + .parent_map = cam_cc_parent_map_0, + .freq_tbl = ftbl_cam_cc_slow_ahb_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "cam_cc_slow_ahb_clk_src", + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_cam_cc_xo_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_xo_clk_src = { + .cmd_rcgr = 0xc154, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_6, + .freq_tbl = ftbl_cam_cc_xo_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "cam_cc_xo_clk_src", + .parent_data = cam_cc_parent_data_6, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_6), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_branch cam_cc_bps_ahb_clk = { + .halt_reg = 0x7070, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x7070, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_bps_ahb_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_slow_ahb_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_bps_areg_clk = { + .halt_reg = 0x7054, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x7054, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_bps_areg_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_fast_ahb_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_bps_axi_clk = { + .halt_reg = 0x7038, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x7038, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_bps_axi_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_camnoc_axi_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_bps_clk = { + .halt_reg = 0x7028, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x7028, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_bps_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_bps_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_camnoc_axi_clk = { + .halt_reg = 0xc114, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xc114, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_camnoc_axi_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_camnoc_axi_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_camnoc_dcd_xo_clk = { + .halt_reg = 0xc11c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xc11c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_camnoc_dcd_xo_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_xo_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_cci_0_clk = { + .halt_reg = 0xc0d4, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xc0d4, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_cci_0_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_cci_0_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_cci_1_clk = { + .halt_reg = 0xc0f0, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xc0f0, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_cci_1_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_cci_1_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_core_ahb_clk = { + .halt_reg = 0xc150, + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0xc150, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_core_ahb_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_slow_ahb_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_cpas_ahb_clk = { + .halt_reg = 0xc0f4, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xc0f4, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_cpas_ahb_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_slow_ahb_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_csi0phytimer_clk = { + .halt_reg = 0x6018, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x6018, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_csi0phytimer_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_csi0phytimer_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_csi1phytimer_clk = { + .halt_reg = 0x6038, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x6038, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_csi1phytimer_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_csi1phytimer_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_csi2phytimer_clk = { + .halt_reg = 0x6058, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x6058, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_csi2phytimer_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_csi2phytimer_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_csi3phytimer_clk = { + .halt_reg = 0x6078, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x6078, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_csi3phytimer_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_csi3phytimer_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_csi4phytimer_clk = { + .halt_reg = 0x6098, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x6098, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_csi4phytimer_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_csi4phytimer_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_csi5phytimer_clk = { + .halt_reg = 0x60b8, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x60b8, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_csi5phytimer_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_csi5phytimer_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_csiphy0_clk = { + .halt_reg = 0x601c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x601c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_csiphy0_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_cphy_rx_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_csiphy1_clk = { + .halt_reg = 0x603c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x603c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_csiphy1_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_cphy_rx_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_csiphy2_clk = { + .halt_reg = 0x605c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x605c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_csiphy2_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_cphy_rx_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_csiphy3_clk = { + .halt_reg = 0x607c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x607c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_csiphy3_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_cphy_rx_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_csiphy4_clk = { + .halt_reg = 0x609c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x609c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_csiphy4_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_cphy_rx_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_csiphy5_clk = { + .halt_reg = 0x60bc, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x60bc, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_csiphy5_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_cphy_rx_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_fd_core_clk = { + .halt_reg = 0xc0b0, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xc0b0, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_fd_core_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_fd_core_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_fd_core_uar_clk = { + .halt_reg = 0xc0b8, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xc0b8, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_fd_core_uar_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_fd_core_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_gdsc_clk = { + .halt_reg = 0xc16c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xc16c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_gdsc_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_xo_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_IS_CRITICAL | CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_icp_ahb_clk = { + .halt_reg = 0xc094, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xc094, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_icp_ahb_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_slow_ahb_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_icp_clk = { + .halt_reg = 0xc08c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xc08c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_icp_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_icp_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ife_0_ahb_clk = { + .halt_reg = 0xa088, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xa088, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_ife_0_ahb_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_slow_ahb_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ife_0_areg_clk = { + .halt_reg = 0xa030, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xa030, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_ife_0_areg_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_fast_ahb_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ife_0_axi_clk = { + .halt_reg = 0xa084, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xa084, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_ife_0_axi_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_camnoc_axi_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ife_0_clk = { + .halt_reg = 0xa028, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xa028, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_ife_0_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_ife_0_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ife_0_cphy_rx_clk = { + .halt_reg = 0xa080, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xa080, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_ife_0_cphy_rx_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_cphy_rx_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ife_0_csid_clk = { + .halt_reg = 0xa058, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xa058, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_ife_0_csid_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_ife_0_csid_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ife_0_dsp_clk = { + .halt_reg = 0xa03c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xa03c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_ife_0_dsp_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_ife_0_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ife_1_ahb_clk = { + .halt_reg = 0xb068, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xb068, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_ife_1_ahb_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_slow_ahb_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ife_1_areg_clk = { + .halt_reg = 0xb030, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xb030, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_ife_1_areg_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_fast_ahb_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ife_1_axi_clk = { + .halt_reg = 0xb064, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xb064, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_ife_1_axi_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_camnoc_axi_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ife_1_clk = { + .halt_reg = 0xb028, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xb028, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_ife_1_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_ife_1_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ife_1_cphy_rx_clk = { + .halt_reg = 0xb060, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xb060, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_ife_1_cphy_rx_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_cphy_rx_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ife_1_csid_clk = { + .halt_reg = 0xb058, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xb058, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_ife_1_csid_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_ife_1_csid_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ife_1_dsp_clk = { + .halt_reg = 0xb03c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xb03c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_ife_1_dsp_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_ife_1_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ife_lite_ahb_clk = { + .halt_reg = 0xc040, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xc040, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_ife_lite_ahb_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_slow_ahb_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ife_lite_axi_clk = { + .halt_reg = 0xc044, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xc044, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_ife_lite_axi_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_camnoc_axi_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ife_lite_clk = { + .halt_reg = 0xc018, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xc018, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_ife_lite_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_ife_lite_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ife_lite_cphy_rx_clk = { + .halt_reg = 0xc03c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xc03c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_ife_lite_cphy_rx_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_cphy_rx_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ife_lite_csid_clk = { + .halt_reg = 0xc034, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xc034, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_ife_lite_csid_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_ife_lite_csid_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ipe_0_ahb_clk = { + .halt_reg = 0x8040, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x8040, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_ipe_0_ahb_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_slow_ahb_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ipe_0_areg_clk = { + .halt_reg = 0x803c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x803c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_ipe_0_areg_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_fast_ahb_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ipe_0_axi_clk = { + .halt_reg = 0x8038, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x8038, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_ipe_0_axi_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_camnoc_axi_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ipe_0_clk = { + .halt_reg = 0x8028, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x8028, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_ipe_0_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_ipe_0_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_jpeg_clk = { + .halt_reg = 0xc060, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xc060, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_jpeg_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_jpeg_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_mclk0_clk = { + .halt_reg = 0x5018, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x5018, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_mclk0_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_mclk0_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_mclk1_clk = { + .halt_reg = 0x5034, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x5034, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_mclk1_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_mclk1_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_mclk2_clk = { + .halt_reg = 0x5050, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x5050, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_mclk2_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_mclk2_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_mclk3_clk = { + .halt_reg = 0x506c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x506c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_mclk3_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_mclk3_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_mclk4_clk = { + .halt_reg = 0x5088, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x5088, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_mclk4_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_mclk4_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_mclk5_clk = { + .halt_reg = 0x50a4, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x50a4, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_mclk5_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_mclk5_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_mclk6_clk = { + .halt_reg = 0x50c0, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x50c0, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_mclk6_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_mclk6_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_sbi_ahb_clk = { + .halt_reg = 0x9040, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x9040, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_sbi_ahb_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_slow_ahb_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_sbi_axi_clk = { + .halt_reg = 0x903c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x903c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_sbi_axi_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_camnoc_axi_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_sbi_clk = { + .halt_reg = 0x9014, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x9014, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_sbi_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_sbi_div_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_sbi_cphy_rx_clk = { + .halt_reg = 0x9038, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x9038, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_sbi_cphy_rx_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_cphy_rx_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_sbi_csid_clk = { + .halt_reg = 0x9034, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x9034, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_sbi_csid_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_sbi_csid_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_sbi_ife_0_clk = { + .halt_reg = 0x9044, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x9044, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_sbi_ife_0_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_ife_0_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_sbi_ife_1_clk = { + .halt_reg = 0x9048, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x9048, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_sbi_ife_1_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_ife_1_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_sleep_clk = { + .halt_reg = 0xc188, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xc188, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_sleep_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_sleep_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct gdsc bps_gdsc = { + .gdscr = 0x7004, + .pd = { + .name = "bps_gdsc", + }, + .flags = HW_CTRL | POLL_CFG_GDSCR, + .pwrsts = PWRSTS_OFF_ON, +}; + +static struct gdsc ipe_0_gdsc = { + .gdscr = 0x8004, + .pd = { + .name = "ipe_0_gdsc", + }, + .flags = HW_CTRL | POLL_CFG_GDSCR, + .pwrsts = PWRSTS_OFF_ON, +}; + +static struct gdsc sbi_gdsc = { + .gdscr = 0x9004, + .pd = { + .name = "sbi_gdsc", + }, + .flags = HW_CTRL | POLL_CFG_GDSCR, + .pwrsts = PWRSTS_OFF_ON, +}; + +static struct gdsc ife_0_gdsc = { + .gdscr = 0xa004, + .pd = { + .name = "ife_0_gdsc", + }, + .flags = POLL_CFG_GDSCR, + .pwrsts = PWRSTS_OFF_ON, +}; + +static struct gdsc ife_1_gdsc = { + .gdscr = 0xb004, + .pd = { + .name = "ife_1_gdsc", + }, + .flags = POLL_CFG_GDSCR, + .pwrsts = PWRSTS_OFF_ON, +}; + +static struct gdsc titan_top_gdsc = { + .gdscr = 0xc144, + .pd = { + .name = "titan_top_gdsc", + }, + .flags = POLL_CFG_GDSCR, + .pwrsts = PWRSTS_OFF_ON, +}; + +static struct clk_regmap *cam_cc_sm8250_clocks[] = { + [CAM_CC_BPS_AHB_CLK] = &cam_cc_bps_ahb_clk.clkr, + [CAM_CC_BPS_AREG_CLK] = &cam_cc_bps_areg_clk.clkr, + [CAM_CC_BPS_AXI_CLK] = &cam_cc_bps_axi_clk.clkr, + [CAM_CC_BPS_CLK] = &cam_cc_bps_clk.clkr, + [CAM_CC_BPS_CLK_SRC] = &cam_cc_bps_clk_src.clkr, + [CAM_CC_CAMNOC_AXI_CLK] = &cam_cc_camnoc_axi_clk.clkr, + [CAM_CC_CAMNOC_AXI_CLK_SRC] = &cam_cc_camnoc_axi_clk_src.clkr, + [CAM_CC_CAMNOC_DCD_XO_CLK] = &cam_cc_camnoc_dcd_xo_clk.clkr, + [CAM_CC_CCI_0_CLK] = &cam_cc_cci_0_clk.clkr, + [CAM_CC_CCI_0_CLK_SRC] = &cam_cc_cci_0_clk_src.clkr, + [CAM_CC_CCI_1_CLK] = &cam_cc_cci_1_clk.clkr, + [CAM_CC_CCI_1_CLK_SRC] = &cam_cc_cci_1_clk_src.clkr, + [CAM_CC_CORE_AHB_CLK] = &cam_cc_core_ahb_clk.clkr, + [CAM_CC_CPAS_AHB_CLK] = &cam_cc_cpas_ahb_clk.clkr, + [CAM_CC_CPHY_RX_CLK_SRC] = &cam_cc_cphy_rx_clk_src.clkr, + [CAM_CC_CSI0PHYTIMER_CLK] = &cam_cc_csi0phytimer_clk.clkr, + [CAM_CC_CSI0PHYTIMER_CLK_SRC] = &cam_cc_csi0phytimer_clk_src.clkr, + [CAM_CC_CSI1PHYTIMER_CLK] = &cam_cc_csi1phytimer_clk.clkr, + [CAM_CC_CSI1PHYTIMER_CLK_SRC] = &cam_cc_csi1phytimer_clk_src.clkr, + [CAM_CC_CSI2PHYTIMER_CLK] = &cam_cc_csi2phytimer_clk.clkr, + [CAM_CC_CSI2PHYTIMER_CLK_SRC] = &cam_cc_csi2phytimer_clk_src.clkr, + [CAM_CC_CSI3PHYTIMER_CLK] = &cam_cc_csi3phytimer_clk.clkr, + [CAM_CC_CSI3PHYTIMER_CLK_SRC] = &cam_cc_csi3phytimer_clk_src.clkr, + [CAM_CC_CSI4PHYTIMER_CLK] = &cam_cc_csi4phytimer_clk.clkr, + [CAM_CC_CSI4PHYTIMER_CLK_SRC] = &cam_cc_csi4phytimer_clk_src.clkr, + [CAM_CC_CSI5PHYTIMER_CLK] = &cam_cc_csi5phytimer_clk.clkr, + [CAM_CC_CSI5PHYTIMER_CLK_SRC] = &cam_cc_csi5phytimer_clk_src.clkr, + [CAM_CC_CSIPHY0_CLK] = &cam_cc_csiphy0_clk.clkr, + [CAM_CC_CSIPHY1_CLK] = &cam_cc_csiphy1_clk.clkr, + [CAM_CC_CSIPHY2_CLK] = &cam_cc_csiphy2_clk.clkr, + [CAM_CC_CSIPHY3_CLK] = &cam_cc_csiphy3_clk.clkr, + [CAM_CC_CSIPHY4_CLK] = &cam_cc_csiphy4_clk.clkr, + [CAM_CC_CSIPHY5_CLK] = &cam_cc_csiphy5_clk.clkr, + [CAM_CC_FAST_AHB_CLK_SRC] = &cam_cc_fast_ahb_clk_src.clkr, + [CAM_CC_FD_CORE_CLK] = &cam_cc_fd_core_clk.clkr, + [CAM_CC_FD_CORE_CLK_SRC] = &cam_cc_fd_core_clk_src.clkr, + [CAM_CC_FD_CORE_UAR_CLK] = &cam_cc_fd_core_uar_clk.clkr, + [CAM_CC_GDSC_CLK] = &cam_cc_gdsc_clk.clkr, + [CAM_CC_ICP_AHB_CLK] = &cam_cc_icp_ahb_clk.clkr, + [CAM_CC_ICP_CLK] = &cam_cc_icp_clk.clkr, + [CAM_CC_ICP_CLK_SRC] = &cam_cc_icp_clk_src.clkr, + [CAM_CC_IFE_0_AHB_CLK] = &cam_cc_ife_0_ahb_clk.clkr, + [CAM_CC_IFE_0_AREG_CLK] = &cam_cc_ife_0_areg_clk.clkr, + [CAM_CC_IFE_0_AXI_CLK] = &cam_cc_ife_0_axi_clk.clkr, + [CAM_CC_IFE_0_CLK] = &cam_cc_ife_0_clk.clkr, + [CAM_CC_IFE_0_CLK_SRC] = &cam_cc_ife_0_clk_src.clkr, + [CAM_CC_IFE_0_CPHY_RX_CLK] = &cam_cc_ife_0_cphy_rx_clk.clkr, + [CAM_CC_IFE_0_CSID_CLK] = &cam_cc_ife_0_csid_clk.clkr, + [CAM_CC_IFE_0_CSID_CLK_SRC] = &cam_cc_ife_0_csid_clk_src.clkr, + [CAM_CC_IFE_0_DSP_CLK] = &cam_cc_ife_0_dsp_clk.clkr, + [CAM_CC_IFE_1_AHB_CLK] = &cam_cc_ife_1_ahb_clk.clkr, + [CAM_CC_IFE_1_AREG_CLK] = &cam_cc_ife_1_areg_clk.clkr, + [CAM_CC_IFE_1_AXI_CLK] = &cam_cc_ife_1_axi_clk.clkr, + [CAM_CC_IFE_1_CLK] = &cam_cc_ife_1_clk.clkr, + [CAM_CC_IFE_1_CLK_SRC] = &cam_cc_ife_1_clk_src.clkr, + [CAM_CC_IFE_1_CPHY_RX_CLK] = &cam_cc_ife_1_cphy_rx_clk.clkr, + [CAM_CC_IFE_1_CSID_CLK] = &cam_cc_ife_1_csid_clk.clkr, + [CAM_CC_IFE_1_CSID_CLK_SRC] = &cam_cc_ife_1_csid_clk_src.clkr, + [CAM_CC_IFE_1_DSP_CLK] = &cam_cc_ife_1_dsp_clk.clkr, + [CAM_CC_IFE_LITE_AHB_CLK] = &cam_cc_ife_lite_ahb_clk.clkr, + [CAM_CC_IFE_LITE_AXI_CLK] = &cam_cc_ife_lite_axi_clk.clkr, + [CAM_CC_IFE_LITE_CLK] = &cam_cc_ife_lite_clk.clkr, + [CAM_CC_IFE_LITE_CLK_SRC] = &cam_cc_ife_lite_clk_src.clkr, + [CAM_CC_IFE_LITE_CPHY_RX_CLK] = &cam_cc_ife_lite_cphy_rx_clk.clkr, + [CAM_CC_IFE_LITE_CSID_CLK] = &cam_cc_ife_lite_csid_clk.clkr, + [CAM_CC_IFE_LITE_CSID_CLK_SRC] = &cam_cc_ife_lite_csid_clk_src.clkr, + [CAM_CC_IPE_0_AHB_CLK] = &cam_cc_ipe_0_ahb_clk.clkr, + [CAM_CC_IPE_0_AREG_CLK] = &cam_cc_ipe_0_areg_clk.clkr, + [CAM_CC_IPE_0_AXI_CLK] = &cam_cc_ipe_0_axi_clk.clkr, + [CAM_CC_IPE_0_CLK] = &cam_cc_ipe_0_clk.clkr, + [CAM_CC_IPE_0_CLK_SRC] = &cam_cc_ipe_0_clk_src.clkr, + [CAM_CC_JPEG_CLK] = &cam_cc_jpeg_clk.clkr, + [CAM_CC_JPEG_CLK_SRC] = &cam_cc_jpeg_clk_src.clkr, + [CAM_CC_MCLK0_CLK] = &cam_cc_mclk0_clk.clkr, + [CAM_CC_MCLK0_CLK_SRC] = &cam_cc_mclk0_clk_src.clkr, + [CAM_CC_MCLK1_CLK] = &cam_cc_mclk1_clk.clkr, + [CAM_CC_MCLK1_CLK_SRC] = &cam_cc_mclk1_clk_src.clkr, + [CAM_CC_MCLK2_CLK] = &cam_cc_mclk2_clk.clkr, + [CAM_CC_MCLK2_CLK_SRC] = &cam_cc_mclk2_clk_src.clkr, + [CAM_CC_MCLK3_CLK] = &cam_cc_mclk3_clk.clkr, + [CAM_CC_MCLK3_CLK_SRC] = &cam_cc_mclk3_clk_src.clkr, + [CAM_CC_MCLK4_CLK] = &cam_cc_mclk4_clk.clkr, + [CAM_CC_MCLK4_CLK_SRC] = &cam_cc_mclk4_clk_src.clkr, + [CAM_CC_MCLK5_CLK] = &cam_cc_mclk5_clk.clkr, + [CAM_CC_MCLK5_CLK_SRC] = &cam_cc_mclk5_clk_src.clkr, + [CAM_CC_MCLK6_CLK] = &cam_cc_mclk6_clk.clkr, + [CAM_CC_MCLK6_CLK_SRC] = &cam_cc_mclk6_clk_src.clkr, + [CAM_CC_PLL0] = &cam_cc_pll0.clkr, + [CAM_CC_PLL0_OUT_EVEN] = &cam_cc_pll0_out_even.clkr, + [CAM_CC_PLL0_OUT_ODD] = &cam_cc_pll0_out_odd.clkr, + [CAM_CC_PLL1] = &cam_cc_pll1.clkr, + [CAM_CC_PLL1_OUT_EVEN] = &cam_cc_pll1_out_even.clkr, + [CAM_CC_PLL2] = &cam_cc_pll2.clkr, + [CAM_CC_PLL2_OUT_MAIN] = &cam_cc_pll2_out_main.clkr, + [CAM_CC_PLL3] = &cam_cc_pll3.clkr, + [CAM_CC_PLL3_OUT_EVEN] = &cam_cc_pll3_out_even.clkr, + [CAM_CC_PLL4] = &cam_cc_pll4.clkr, + [CAM_CC_PLL4_OUT_EVEN] = &cam_cc_pll4_out_even.clkr, + [CAM_CC_SBI_AHB_CLK] = &cam_cc_sbi_ahb_clk.clkr, + [CAM_CC_SBI_AXI_CLK] = &cam_cc_sbi_axi_clk.clkr, + [CAM_CC_SBI_CLK] = &cam_cc_sbi_clk.clkr, + [CAM_CC_SBI_CPHY_RX_CLK] = &cam_cc_sbi_cphy_rx_clk.clkr, + [CAM_CC_SBI_CSID_CLK] = &cam_cc_sbi_csid_clk.clkr, + [CAM_CC_SBI_CSID_CLK_SRC] = &cam_cc_sbi_csid_clk_src.clkr, + [CAM_CC_SBI_DIV_CLK_SRC] = &cam_cc_sbi_div_clk_src.clkr, + [CAM_CC_SBI_IFE_0_CLK] = &cam_cc_sbi_ife_0_clk.clkr, + [CAM_CC_SBI_IFE_1_CLK] = &cam_cc_sbi_ife_1_clk.clkr, + [CAM_CC_SLEEP_CLK] = &cam_cc_sleep_clk.clkr, + [CAM_CC_SLEEP_CLK_SRC] = &cam_cc_sleep_clk_src.clkr, + [CAM_CC_SLOW_AHB_CLK_SRC] = &cam_cc_slow_ahb_clk_src.clkr, + [CAM_CC_XO_CLK_SRC] = &cam_cc_xo_clk_src.clkr, +}; + +static struct gdsc *cam_cc_sm8250_gdscs[] = { + [BPS_GDSC] = &bps_gdsc, + [IPE_0_GDSC] = &ipe_0_gdsc, + [SBI_GDSC] = &sbi_gdsc, + [IFE_0_GDSC] = &ife_0_gdsc, + [IFE_1_GDSC] = &ife_1_gdsc, + [TITAN_TOP_GDSC] = &titan_top_gdsc, +}; + +static const struct qcom_reset_map cam_cc_sm8250_resets[] = { + [CAM_CC_BPS_BCR] = { 0x7000 }, + [CAM_CC_ICP_BCR] = { 0xc070 }, + [CAM_CC_IFE_0_BCR] = { 0xa000 }, + [CAM_CC_IFE_1_BCR] = { 0xb000 }, + [CAM_CC_IPE_0_BCR] = { 0x8000 }, + [CAM_CC_SBI_BCR] = { 0x9000 }, +}; + +static const struct regmap_config cam_cc_sm8250_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = 0xe004, + .fast_io = true, +}; + +static const struct qcom_cc_desc cam_cc_sm8250_desc = { + .config = &cam_cc_sm8250_regmap_config, + .clks = cam_cc_sm8250_clocks, + .num_clks = ARRAY_SIZE(cam_cc_sm8250_clocks), + .resets = cam_cc_sm8250_resets, + .num_resets = ARRAY_SIZE(cam_cc_sm8250_resets), + .gdscs = cam_cc_sm8250_gdscs, + .num_gdscs = ARRAY_SIZE(cam_cc_sm8250_gdscs), +}; + +static const struct of_device_id cam_cc_sm8250_match_table[] = { + { .compatible = "qcom,sm8250-camcc" }, + { } +}; +MODULE_DEVICE_TABLE(of, cam_cc_sm8250_match_table); + +static int cam_cc_sm8250_probe(struct platform_device *pdev) +{ + struct regmap *regmap; + + regmap = qcom_cc_map(pdev, &cam_cc_sm8250_desc); + if (IS_ERR(regmap)) + return PTR_ERR(regmap); + + clk_lucid_pll_configure(&cam_cc_pll0, regmap, &cam_cc_pll0_config); + clk_lucid_pll_configure(&cam_cc_pll1, regmap, &cam_cc_pll1_config); + clk_zonda_pll_configure(&cam_cc_pll2, regmap, &cam_cc_pll2_config); + clk_lucid_pll_configure(&cam_cc_pll3, regmap, &cam_cc_pll3_config); + clk_lucid_pll_configure(&cam_cc_pll4, regmap, &cam_cc_pll4_config); + + return qcom_cc_really_probe(pdev, &cam_cc_sm8250_desc, regmap); +} + +static struct platform_driver cam_cc_sm8250_driver = { + .probe = cam_cc_sm8250_probe, + .driver = { + .name = "cam_cc-sm8250", + .of_match_table = cam_cc_sm8250_match_table, + }, +}; + +static int __init cam_cc_sm8250_init(void) +{ + return platform_driver_register(&cam_cc_sm8250_driver); +} +subsys_initcall(cam_cc_sm8250_init); + +static void __exit cam_cc_sm8250_exit(void) +{ + platform_driver_unregister(&cam_cc_sm8250_driver); +} +module_exit(cam_cc_sm8250_exit); + +MODULE_DESCRIPTION("QTI CAMCC SM8250 Driver"); +MODULE_LICENSE("GPL v2"); From 99c6fc6d7ecb7961b33d6503a71c868bb4009478 Mon Sep 17 00:00:00 2001 From: Jian Xin Date: Wed, 9 Jun 2021 15:37:42 +0800 Subject: [PATCH 108/161] clk: socfpga: clk-pll: Remove unused variable 'rc' MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix the following build warning: drivers/clk/socfpga/clk-pll.c: In function ‘__socfpga_pll_init’: drivers/clk/socfpga/clk-pll.c:83:6: warning: variable ‘rc’ set but not used [-Wunused-but-set-variable] Signed-off-by: Jian Xin Link: https://lore.kernel.org/r/20210609073742.722911-1-xinjian34324@163.com Signed-off-by: Stephen Boyd --- drivers/clk/socfpga/clk-pll.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/clk/socfpga/clk-pll.c b/drivers/clk/socfpga/clk-pll.c index dcb573d44034..127cc849c5ee 100644 --- a/drivers/clk/socfpga/clk-pll.c +++ b/drivers/clk/socfpga/clk-pll.c @@ -80,7 +80,6 @@ static __init struct clk_hw *__socfpga_pll_init(struct device_node *node, const char *parent_name[SOCFPGA_MAX_PARENTS]; struct clk_init_data init; struct device_node *clkmgr_np; - int rc; int err; of_property_read_u32(node, "reg", ®); @@ -114,7 +113,7 @@ static __init struct clk_hw *__socfpga_pll_init(struct device_node *node, kfree(pll_clk); return ERR_PTR(err); } - rc = of_clk_add_provider(node, of_clk_src_simple_get, hw_clk); + of_clk_add_provider(node, of_clk_src_simple_get, hw_clk); return hw_clk; } From 199ead4008b2078772c4efc3851a31af75eb4013 Mon Sep 17 00:00:00 2001 From: Liam Beguin Date: Thu, 22 Apr 2021 20:40:57 -0400 Subject: [PATCH 109/161] dt-bindings: clock: add ti,lmk04832 bindings Document devicetree bindings for Texas Instruments' LMK04832. The LMK04208 is a high performance clock conditioner with superior clock jitter cleaning, generation, and distribution with JEDEC JESD204B support. Signed-off-by: Liam Beguin Link: https://lore.kernel.org/r/20210423004057.283926-4-liambeguin@gmail.com Reviewed-by: Rob Herring Signed-off-by: Stephen Boyd --- .../bindings/clock/ti,lmk04832.yaml | 209 ++++++++++++++++++ 1 file changed, 209 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/ti,lmk04832.yaml diff --git a/Documentation/devicetree/bindings/clock/ti,lmk04832.yaml b/Documentation/devicetree/bindings/clock/ti,lmk04832.yaml new file mode 100644 index 000000000000..bd8173848253 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/ti,lmk04832.yaml @@ -0,0 +1,209 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/ti,lmk04832.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Clock bindings for the Texas Instruments LMK04832 + +maintainers: + - Liam Beguin + +description: | + Devicetree binding for the LMK04832, a clock conditioner with JEDEC JESD204B + support. The LMK04832 is pin compatible with the LMK0482x family. + + Link to datasheet, https://www.ti.com/lit/ds/symlink/lmk04832.pdf + +properties: + compatible: + enum: + - ti,lmk04832 + + reg: + maxItems: 1 + + '#address-cells': + const: 1 + + '#size-cells': + const: 0 + + '#clock-cells': + const: 1 + + spi-max-frequency: + maximum: 5000000 + + clocks: + items: + - description: PLL2 reference clock. + + clock-names: + items: + - const: oscin + + reset-gpios: + maxItems: 1 + + ti,spi-4wire-rdbk: + description: | + Select SPI 4wire readback pin configuration. + Available readback pins are, + CLKin_SEL0 0 + CLKin_SEL1 1 + RESET 2 + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [0, 1, 2] + default: 1 + + ti,vco-hz: + description: Optional to set VCO frequency of the PLL in Hertz. + + ti,sysref-ddly: + description: SYSREF digital delay value. + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 8 + maximum: 8191 + default: 8 + + ti,sysref-mux: + description: | + SYSREF Mux configuration. + Available options are, + Normal SYNC 0 + Re-clocked 1 + SYSREF Pulser 2 + SYSREF Continuous 3 + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [0, 1, 2, 3] + default: 3 + + ti,sync-mode: + description: SYNC pin configuration. + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [0, 1, 2] + default: 1 + + ti,sysref-pulse-count: + description: + Number of SYSREF pulses to send when SYSREF is not in continuous mode. + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [1, 2, 4, 8] + default: 4 + +patternProperties: + "@[0-9a-d]+$": + type: object + description: + Child nodes used to configure output clocks. + + properties: + reg: + description: + clock output identifier. + minimum: 0 + maximum: 13 + + ti,clkout-fmt: + description: + Clock output format. + Available options are, + Powerdown 0x00 + LVDS 0x01 + HSDS 6 mA 0x02 + HSDS 8 mA 0x03 + LVPECL 1600 mV 0x04 + LVPECL 2000 mV 0x05 + LCPECL 0x06 + CML 16 mA 0x07 + CML 24 mA 0x08 + CML 32 mA 0x09 + CMOS (Off/Inverted) 0x0a + CMOS (Normal/Off) 0x0b + CMOS (Inverted/Inverted) 0x0c + CMOS (Inverted/Normal) 0x0d + CMOS (Normal/Inverted) 0x0e + CMOS (Normal/Normal) 0x0f + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 0 + maximum: 15 + + ti,clkout-sysref: + description: + Select SYSREF clock path for output clock. + type: boolean + + required: + - reg + + additionalProperties: false + +required: + - compatible + - reg + - '#clock-cells' + - clocks + - clock-names + +additionalProperties: false + +examples: + - | + clocks { + lmk04832_oscin: oscin { + compatible = "fixed-clock"; + + #clock-cells = <0>; + clock-frequency = <122880000>; + clock-output-names = "lmk04832-oscin"; + }; + }; + + spi0 { + #address-cells = <1>; + #size-cells = <0>; + + lmk04832: clock-controller@0 { + #address-cells = <1>; + #size-cells = <0>; + + reg = <0>; + + compatible = "ti,lmk04832"; + spi-max-frequency = <781250>; + + reset-gpios = <&gpio_lmk 0 0 0>; + + #clock-cells = <1>; + clocks = <&lmk04832_oscin>; + clock-names = "oscin"; + + ti,spi-4wire-rdbk = <0>; + ti,vco-hz = <2457600000>; + + assigned-clocks = + <&lmk04832 0>, <&lmk04832 1>, + <&lmk04832 2>, <&lmk04832 3>, + <&lmk04832 4>, + <&lmk04832 6>, <&lmk04832 7>, + <&lmk04832 10>, <&lmk04832 11>; + assigned-clock-rates = + <122880000>, <384000>, + <122880000>, <384000>, + <122880000>, + <153600000>, <384000>, + <614400000>, <384000>; + + clkout0@0 { + reg = <0>; + ti,clkout-fmt = <0x01>; // LVDS + }; + + clkout1@1 { + reg = <1>; + ti,clkout-fmt = <0x01>; // LVDS + ti,clkout-sysref; + }; + }; + }; From 3bc61cfd6f4a57de32132075b15b0ac8987ced1d Mon Sep 17 00:00:00 2001 From: Liam Beguin Date: Thu, 22 Apr 2021 20:40:55 -0400 Subject: [PATCH 110/161] clk: add support for the lmk04832 The LMK04832 is an ultra-high performance clock conditioner with JEDEC JESD204B support and is also pin compatible with the LMK0482x family of devices. Signed-off-by: Liam Beguin Link: https://lore.kernel.org/r/20210423004057.283926-2-liambeguin@gmail.com Signed-off-by: Stephen Boyd --- drivers/clk/Kconfig | 7 + drivers/clk/Makefile | 1 + drivers/clk/clk-lmk04832.c | 1288 ++++++++++++++++++++++++++++++++++++ 3 files changed, 1296 insertions(+) create mode 100644 drivers/clk/clk-lmk04832.c diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index e80918be8e9c..ccf77849bdbd 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig @@ -55,6 +55,13 @@ config CLK_HSDK This driver supports the HSDK core, system, ddr, tunnel and hdmi PLLs control. +config LMK04832 + tristate "Ti LMK04832 JESD204B Compliant Clock Jitter Cleaner" + select REGMAP_SPI + help + Say yes here to build support for Texas Instruments' LMK04832 Ultra + Low-Noise JESD204B Compliant Clock Jitter Cleaner With Dual Loop PLLs + config COMMON_CLK_MAX77686 tristate "Clock driver for Maxim 77620/77686/77802 MFD" depends on MFD_MAX77686 || MFD_MAX77620 || COMPILE_TEST diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index 5f06879d7fe9..63ba0db1e017 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -37,6 +37,7 @@ obj-$(CONFIG_MACH_ASPEED_G6) += clk-ast2600.o obj-$(CONFIG_ARCH_HIGHBANK) += clk-highbank.o obj-$(CONFIG_CLK_HSDK) += clk-hsdk-pll.o obj-$(CONFIG_COMMON_CLK_K210) += clk-k210.o +obj-$(CONFIG_LMK04832) += clk-lmk04832.o obj-$(CONFIG_COMMON_CLK_LOCHNAGAR) += clk-lochnagar.o obj-$(CONFIG_COMMON_CLK_MAX77686) += clk-max77686.o obj-$(CONFIG_COMMON_CLK_MAX9485) += clk-max9485.o diff --git a/drivers/clk/clk-lmk04832.c b/drivers/clk/clk-lmk04832.c new file mode 100644 index 000000000000..ae80af7f89fb --- /dev/null +++ b/drivers/clk/clk-lmk04832.c @@ -0,0 +1,1288 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * LMK04832 Ultra Low-Noise JESD204B Compliant Clock Jitter Cleaner + * Pin compatible with the LMK0482x family + * + * Datasheet: https://www.ti.com/lit/ds/symlink/lmk04832.pdf + * + * Copyright (c) 2020, Xiphos Systems Corp. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* 0x000 - 0x00d System Functions */ +#define LMK04832_REG_RST3W 0x000 +#define LMK04832_BIT_RESET BIT(7) +#define LMK04832_BIT_SPI_3WIRE_DIS BIT(4) +#define LMK04832_REG_POWERDOWN 0x002 +#define LMK04832_REG_ID_DEV_TYPE 0x003 +#define LMK04832_REG_ID_PROD_MSB 0x004 +#define LMK04832_REG_ID_PROD_LSB 0x005 +#define LMK04832_REG_ID_MASKREV 0x006 +#define LMK04832_REG_ID_VNDR_MSB 0x00c +#define LMK04832_REG_ID_VNDR_LSB 0x00d + +/* 0x100 - 0x137 Device Clock and SYSREF Clock Output Control */ +#define LMK04832_REG_CLKOUT_CTRL0(ch) (0x100 + (ch >> 1) * 8) +#define LMK04832_BIT_DCLK_DIV_LSB GENMASK(7, 0) +#define LMK04832_REG_CLKOUT_CTRL1(ch) (0x101 + (ch >> 1) * 8) +#define LMK04832_REG_CLKOUT_CTRL2(ch) (0x102 + (ch >> 1) * 8) +#define LMK04832_BIT_CLKOUTX_Y_PD BIT(7) +#define LMK04832_BIT_DCLK_DIV_MSB GENMASK(1, 0) +#define LMK04832_REG_CLKOUT_SRC_MUX(ch) (0x103 + (ch % 2) + (ch >> 1) * 8) +#define LMK04832_BIT_CLKOUT_SRC_MUX BIT(5) +#define LMK04832_REG_CLKOUT_CTRL3(ch) (0x103 + (ch >> 1) * 8) +#define LMK04832_BIT_DCLKX_Y_PD BIT(4) +#define LMK04832_BIT_DCLKX_Y_DCC BIT(2) +#define LMK04832_REG_CLKOUT_CTRL4(ch) (0x104 + (ch >> 1) * 8) +#define LMK04832_BIT_SCLK_PD BIT(4) +#define LMK04832_REG_CLKOUT_FMT(ch) (0x107 + (ch >> 1) * 8) +#define LMK04832_BIT_CLKOUT_FMT(ch) (ch % 2 ? 0xf0 : 0x0f) +#define LMK04832_VAL_CLKOUT_FMT_POWERDOWN 0x00 +#define LMK04832_VAL_CLKOUT_FMT_LVDS 0x01 +#define LMK04832_VAL_CLKOUT_FMT_HSDS6 0x02 +#define LMK04832_VAL_CLKOUT_FMT_HSDS8 0x03 +#define LMK04832_VAL_CLKOUT_FMT_LVPECL1600 0x04 +#define LMK04832_VAL_CLKOUT_FMT_LVPECL2000 0x05 +#define LMK04832_VAL_CLKOUT_FMT_LCPECL 0x06 +#define LMK04832_VAL_CLKOUT_FMT_CML16 0x07 +#define LMK04832_VAL_CLKOUT_FMT_CML24 0x08 +#define LMK04832_VAL_CLKOUT_FMT_CML32 0x09 +#define LMK04832_VAL_CLKOUT_FMT_CMOS_OFF_INV 0x0a +#define LMK04832_VAL_CLKOUT_FMT_CMOS_NOR_OFF 0x0b +#define LMK04832_VAL_CLKOUT_FMT_CMOS_INV_INV 0x0c +#define LMK04832_VAL_CLKOUT_FMT_CMOS_INV_NOR 0x0d +#define LMK04832_VAL_CLKOUT_FMT_CMOS_NOR_INV 0x0e +#define LMK04832_VAL_CLKOUT_FMT_CMOS_NOR_NOR 0x0f + +/* 0x138 - 0x145 SYSREF, SYNC, and Device Config */ +#define LMK04832_REG_VCO_OSCOUT 0x138 +#define LMK04832_BIT_VCO_MUX GENMASK(6, 5) +#define LMK04832_VAL_VCO_MUX_VCO0 0x00 +#define LMK04832_VAL_VCO_MUX_VCO1 0x01 +#define LMK04832_VAL_VCO_MUX_EXT 0x02 +#define LMK04832_REG_SYSREF_OUT 0x139 +#define LMK04832_BIT_SYSREF_MUX GENMASK(1, 0) +#define LMK04832_VAL_SYSREF_MUX_CONTINUOUS 0x03 +#define LMK04832_REG_SYSREF_DIV_MSB 0x13a +#define LMK04832_BIT_SYSREF_DIV_MSB GENMASK(4, 0) +#define LMK04832_REG_SYSREF_DIV_LSB 0x13b +#define LMK04832_REG_FB_CTRL 0x13f +#define LMK04832_BIT_PLL2_RCLK_MUX BIT(7) +#define LMK04832_VAL_PLL2_RCLK_MUX_OSCIN 0x00 +#define LMK04832_VAL_PLL2_RCLK_MUX_CLKIN 0x01 +#define LMK04832_BIT_PLL2_NCLK_MUX BIT(5) +#define LMK04832_VAL_PLL2_NCLK_MUX_PLL2_P 0x00 +#define LMK04832_VAL_PLL2_NCLK_MUX_FB_MUX 0x01 +#define LMK04832_BIT_FB_MUX_EN BIT(0) +#define LMK04832_REG_MAIN_PD 0x140 +#define LMK04832_BIT_PLL1_PD BIT(7) +#define LMK04832_BIT_VCO_LDO_PD BIT(6) +#define LMK04832_BIT_VCO_PD BIT(5) +#define LMK04832_BIT_OSCIN_PD BIT(4) +#define LMK04832_BIT_SYSREF_GBL_PD BIT(3) +#define LMK04832_BIT_SYSREF_PD BIT(2) +#define LMK04832_BIT_SYSREF_DDLY_PD BIT(1) +#define LMK04832_BIT_SYSREF_PLSR_PD BIT(0) +#define LMK04832_REG_SYNC 0x143 +#define LMK04832_BIT_SYNC_EN BIT(4) +#define LMK04832_REG_SYNC_DIS 0x144 + +/* 0x146 - 0x14a CLKin Control */ +#define LMK04832_REG_CLKIN_SEL0 0x148 +#define LMK04832_REG_CLKIN_SEL1 0x149 +#define LMK04832_REG_CLKIN_RST 0x14a +#define LMK04832_BIT_SDIO_RDBK_TYPE BIT(6) +#define LMK04832_BIT_CLKIN_SEL_MUX GENMASK(5, 3) +#define LMK04832_VAL_CLKIN_SEL_MUX_SPI_RDBK 0x06 +#define LMK04832_BIT_CLKIN_SEL_TYPE GENMASK(2, 0) +#define LMK04832_VAL_CLKIN_SEL_TYPE_OUT 0x03 + +/* 0x14b - 0x152 Holdover */ + +/* 0x153 - 0x15f PLL1 Configuration */ + +/* 0x160 - 0x16e PLL2 Configuration */ +#define LMK04832_REG_PLL2_R_MSB 0x160 +#define LMK04832_BIT_PLL2_R_MSB GENMASK(3, 0) +#define LMK04832_REG_PLL2_R_LSB 0x161 +#define LMK04832_REG_PLL2_MISC 0x162 +#define LMK04832_BIT_PLL2_MISC_P GENMASK(7, 5) +#define LMK04832_BIT_PLL2_MISC_REF_2X_EN BIT(0) +#define LMK04832_REG_PLL2_N_CAL_0 0x163 +#define LMK04832_BIT_PLL2_N_CAL_0 GENMASK(1, 0) +#define LMK04832_REG_PLL2_N_CAL_1 0x164 +#define LMK04832_REG_PLL2_N_CAL_2 0x165 +#define LMK04832_REG_PLL2_N_0 0x166 +#define LMK04832_BIT_PLL2_N_0 GENMASK(1, 0) +#define LMK04832_REG_PLL2_N_1 0x167 +#define LMK04832_REG_PLL2_N_2 0x168 +#define LMK04832_REG_PLL2_DLD_CNT_LSB 0x16b +#define LMK04832_REG_PLL2_LD 0x16e +#define LMK04832_BIT_PLL2_LD_MUX GENMASK(7, 3) +#define LMK04832_VAL_PLL2_LD_MUX_PLL2_DLD 0x02 +#define LMK04832_BIT_PLL2_LD_TYPE GENMASK(2, 0) +#define LMK04832_VAL_PLL2_LD_TYPE_OUT_PP 0x03 + +/* 0x16F - 0x555 Misc Registers */ +#define LMK04832_REG_PLL2_PD 0x173 +#define LMK04832_BIT_PLL2_PRE_PD BIT(6) +#define LMK04832_BIT_PLL2_PD BIT(5) +#define LMK04832_REG_PLL1R_RST 0x177 +#define LMK04832_REG_CLR_PLL_LOST 0x182 +#define LMK04832_REG_RB_PLL_LD 0x183 +#define LMK04832_REG_RB_CLK_DAC_VAL_MSB 0x184 +#define LMK04832_REG_RB_DAC_VAL_LSB 0x185 +#define LMK04832_REG_RB_HOLDOVER 0x188 +#define LMK04832_REG_SPI_LOCK 0x555 + +enum lmk04832_device_types { + LMK04832, +}; + +/** + * lmk04832_device_info - Holds static device information that is specific to + * the chip revision + * + * pid: Product Identifier + * maskrev: IC version identifier + * num_channels: Number of available output channels (clkout count) + * vco0_range: {min, max} of the VCO0 operating range (in MHz) + * vco1_range: {min, max} of the VCO1 operating range (in MHz) + */ +struct lmk04832_device_info { + u16 pid; + u8 maskrev; + size_t num_channels; + unsigned int vco0_range[2]; + unsigned int vco1_range[2]; +}; + +static const struct lmk04832_device_info lmk04832_device_info[] = { + [LMK04832] = { + .pid = 0x63d1, /* WARNING PROD_ID is inverted in the datasheet */ + .maskrev = 0x70, + .num_channels = 14, + .vco0_range = { 2440, 2580 }, + .vco1_range = { 2945, 3255 }, + }, +}; + +enum lmk04832_rdbk_type { + RDBK_CLKIN_SEL0, + RDBK_CLKIN_SEL1, + RDBK_RESET, +}; + +struct lmk_dclk { + struct lmk04832 *lmk; + struct clk_hw hw; + u8 id; +}; + +struct lmk_clkout { + struct lmk04832 *lmk; + struct clk_hw hw; + bool sysref; + u32 format; + u8 id; +}; + +/** + * struct lmk04832 - The LMK04832 device structure + * + * @dev: reference to a struct device, linked to the spi_device + * @regmap: struct regmap instance use to access the chip + * @oscin: PLL2 input clock + * @vco: reference to the internal VCO clock + * @sclk: reference to the internal sysref clock (SCLK) + * @vco_rate: user provided VCO rate + * @reset_gpio: reference to the reset GPIO + * @dclk: list of internal device clock references. + * Each pair of clkout clocks share a single device clock (DCLKX_Y) + * @clkout: list of output clock references + * @clk_data: holds clkout related data like clk_hw* and number of clocks + */ +struct lmk04832 { + struct device *dev; + struct regmap *regmap; + + struct clk *oscin; + struct clk_hw vco; + struct clk_hw sclk; + unsigned int vco_rate; + + struct gpio_desc *reset_gpio; + + struct lmk_dclk *dclk; + struct lmk_clkout *clkout; + struct clk_hw_onecell_data *clk_data; +}; + +static bool lmk04832_regmap_rd_regs(struct device *dev, unsigned int reg) +{ + switch (reg) { + case LMK04832_REG_RST3W ... LMK04832_REG_ID_MASKREV: + fallthrough; + case LMK04832_REG_ID_VNDR_MSB: + fallthrough; + case LMK04832_REG_ID_VNDR_LSB: + fallthrough; + case LMK04832_REG_CLKOUT_CTRL0(0) ... LMK04832_REG_PLL2_DLD_CNT_LSB: + fallthrough; + case LMK04832_REG_PLL2_LD: + fallthrough; + case LMK04832_REG_PLL2_PD: + fallthrough; + case LMK04832_REG_PLL1R_RST: + fallthrough; + case LMK04832_REG_CLR_PLL_LOST ... LMK04832_REG_RB_DAC_VAL_LSB: + fallthrough; + case LMK04832_REG_RB_HOLDOVER: + fallthrough; + case LMK04832_REG_SPI_LOCK: + return true; + default: + return false; + }; +}; + +static bool lmk04832_regmap_wr_regs(struct device *dev, unsigned int reg) +{ + switch (reg) { + case LMK04832_REG_RST3W: + fallthrough; + case LMK04832_REG_POWERDOWN: + return true; + case LMK04832_REG_ID_DEV_TYPE ... LMK04832_REG_ID_MASKREV: + fallthrough; + case LMK04832_REG_ID_VNDR_MSB: + fallthrough; + case LMK04832_REG_ID_VNDR_LSB: + return false; + case LMK04832_REG_CLKOUT_CTRL0(0) ... LMK04832_REG_PLL2_DLD_CNT_LSB: + fallthrough; + case LMK04832_REG_PLL2_LD: + fallthrough; + case LMK04832_REG_PLL2_PD: + fallthrough; + case LMK04832_REG_PLL1R_RST: + fallthrough; + case LMK04832_REG_CLR_PLL_LOST ... LMK04832_REG_RB_DAC_VAL_LSB: + fallthrough; + case LMK04832_REG_RB_HOLDOVER: + fallthrough; + case LMK04832_REG_SPI_LOCK: + return true; + default: + return false; + }; +}; + +static const struct regmap_config regmap_config = { + .name = "lmk04832", + .reg_bits = 16, + .val_bits = 8, + .use_single_read = 1, + .use_single_write = 1, + .read_flag_mask = 0x80, + .write_flag_mask = 0x00, + .readable_reg = lmk04832_regmap_rd_regs, + .writeable_reg = lmk04832_regmap_wr_regs, + .cache_type = REGCACHE_NONE, + .max_register = LMK04832_REG_SPI_LOCK, +}; + +static int lmk04832_vco_is_enabled(struct clk_hw *hw) +{ + struct lmk04832 *lmk = container_of(hw, struct lmk04832, vco); + unsigned int tmp; + int ret; + + ret = regmap_read(lmk->regmap, LMK04832_REG_MAIN_PD, &tmp); + if (ret) + return ret; + + return !(FIELD_GET(LMK04832_BIT_OSCIN_PD, tmp) | + FIELD_GET(LMK04832_BIT_VCO_PD, tmp) | + FIELD_GET(LMK04832_BIT_VCO_LDO_PD, tmp)); +} + +static int lmk04832_vco_prepare(struct clk_hw *hw) +{ + struct lmk04832 *lmk = container_of(hw, struct lmk04832, vco); + int ret; + + ret = regmap_update_bits(lmk->regmap, LMK04832_REG_PLL2_PD, + LMK04832_BIT_PLL2_PRE_PD | + LMK04832_BIT_PLL2_PD, + 0x00); + if (ret) + return ret; + + return regmap_update_bits(lmk->regmap, LMK04832_REG_MAIN_PD, + LMK04832_BIT_VCO_LDO_PD | + LMK04832_BIT_VCO_PD | + LMK04832_BIT_OSCIN_PD, 0x00); +} + +static void lmk04832_vco_unprepare(struct clk_hw *hw) +{ + struct lmk04832 *lmk = container_of(hw, struct lmk04832, vco); + + regmap_update_bits(lmk->regmap, LMK04832_REG_PLL2_PD, + LMK04832_BIT_PLL2_PRE_PD | LMK04832_BIT_PLL2_PD, + 0xff); + + /* Don't set LMK04832_BIT_OSCIN_PD since other clocks depend on it */ + regmap_update_bits(lmk->regmap, LMK04832_REG_MAIN_PD, + LMK04832_BIT_VCO_LDO_PD | LMK04832_BIT_VCO_PD, 0xff); +} + +static unsigned long lmk04832_vco_recalc_rate(struct clk_hw *hw, + unsigned long prate) +{ + struct lmk04832 *lmk = container_of(hw, struct lmk04832, vco); + unsigned int pll2_p[] = {8, 2, 2, 3, 4, 5, 6, 7}; + unsigned int pll2_n, p, pll2_r; + unsigned int pll2_misc; + unsigned long vco_rate; + u8 tmp[3]; + int ret; + + ret = regmap_read(lmk->regmap, LMK04832_REG_PLL2_MISC, &pll2_misc); + if (ret) + return ret; + + p = FIELD_GET(LMK04832_BIT_PLL2_MISC_P, pll2_misc); + + ret = regmap_bulk_read(lmk->regmap, LMK04832_REG_PLL2_N_0, &tmp, 3); + if (ret) + return ret; + + pll2_n = FIELD_PREP(0x030000, tmp[0]) | + FIELD_PREP(0x00ff00, tmp[1]) | + FIELD_PREP(0x0000ff, tmp[2]); + + ret = regmap_bulk_read(lmk->regmap, LMK04832_REG_PLL2_R_MSB, &tmp, 2); + if (ret) + return ret; + + pll2_r = FIELD_PREP(0x0f00, tmp[0]) | + FIELD_PREP(0x00ff, tmp[1]); + + vco_rate = (prate << FIELD_GET(LMK04832_BIT_PLL2_MISC_REF_2X_EN, + pll2_misc)) * pll2_n * pll2_p[p] / pll2_r; + + return vco_rate; +}; + +/** + * lmk04832_check_vco_ranges - Check requested VCO frequency against VCO ranges + * + * @lmk: Reference to the lmk device + * @rate: Desired output rate for the VCO + * + * The LMK04832 has 2 internal VCO, each with independent operating ranges. + * Use the device_info structure to determine which VCO to use based on rate. + * + * Returns VCO_MUX value or negative errno. + */ +static int lmk04832_check_vco_ranges(struct lmk04832 *lmk, unsigned long rate) +{ + struct spi_device *spi = to_spi_device(lmk->dev); + const struct lmk04832_device_info *info; + unsigned long mhz = rate / 1000000; + + info = &lmk04832_device_info[spi_get_device_id(spi)->driver_data]; + + if (mhz >= info->vco0_range[0] && mhz <= info->vco0_range[1]) + return LMK04832_VAL_VCO_MUX_VCO0; + + if (mhz >= info->vco1_range[0] && mhz <= info->vco1_range[1]) + return LMK04832_VAL_VCO_MUX_VCO1; + + dev_err(lmk->dev, "%lu Hz is out of VCO ranges\n", rate); + return -ERANGE; +} + +/** + * lmk04832_calc_pll2_params - Get PLL2 parameters used to set the VCO frequency + * + * @prate: parent rate to the PLL2, usually OSCin + * @rate: Desired output rate for the VCO + * @n: reference to PLL2_N + * @p: reference to PLL2_P + * @r: reference to PLL2_R + * + * This functions assumes LMK04832_BIT_PLL2_MISC_REF_2X_EN is set since it is + * recommended in the datasheet because a higher phase detector frequencies + * makes the design of wider loop bandwidth filters possible. + * + * the VCO rate can be calculated using the following expression: + * + * VCO = OSCin * 2 * PLL2_N * PLL2_P / PLL2_R + * + * Returns vco rate or negative errno. + */ +static long lmk04832_calc_pll2_params(unsigned long prate, unsigned long rate, + unsigned int *n, unsigned int *p, + unsigned int *r) +{ + unsigned int pll2_n, pll2_p, pll2_r; + unsigned long num, div; + + /* Set PLL2_P to a fixed value to simplify optimizations */ + pll2_p = 2; + + div = gcd(rate, prate); + + num = DIV_ROUND_CLOSEST(rate, div); + pll2_r = DIV_ROUND_CLOSEST(prate, div); + + if (num > 4) { + pll2_n = num >> 2; + } else { + pll2_r = pll2_r << 2; + pll2_n = num; + } + + if (pll2_n < 1 || pll2_n > 0x03ffff) + return -EINVAL; + if (pll2_r < 1 || pll2_r > 0xfff) + return -EINVAL; + + *n = pll2_n; + *p = pll2_p; + *r = pll2_r; + + return DIV_ROUND_CLOSEST(prate * 2 * pll2_p * pll2_n, pll2_r); +} + +static long lmk04832_vco_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *prate) +{ + struct lmk04832 *lmk = container_of(hw, struct lmk04832, vco); + unsigned int n, p, r; + long vco_rate; + int ret; + + ret = lmk04832_check_vco_ranges(lmk, rate); + if (ret < 0) + return ret; + + vco_rate = lmk04832_calc_pll2_params(*prate, rate, &n, &p, &r); + if (vco_rate < 0) { + dev_err(lmk->dev, "PLL2 parmeters out of range\n"); + return vco_rate; + } + + if (rate != vco_rate) + return -EINVAL; + + return vco_rate; +}; + +static int lmk04832_vco_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long prate) +{ + struct lmk04832 *lmk = container_of(hw, struct lmk04832, vco); + unsigned int n, p, r; + long vco_rate; + int vco_mux; + int ret; + + vco_mux = lmk04832_check_vco_ranges(lmk, rate); + if (vco_mux < 0) + return vco_mux; + + ret = regmap_update_bits(lmk->regmap, LMK04832_REG_VCO_OSCOUT, + LMK04832_BIT_VCO_MUX, + FIELD_PREP(LMK04832_BIT_VCO_MUX, vco_mux)); + if (ret) + return ret; + + vco_rate = lmk04832_calc_pll2_params(prate, rate, &n, &p, &r); + if (vco_rate < 0) { + dev_err(lmk->dev, "failed to determine PLL2 parmeters\n"); + return vco_rate; + } + + ret = regmap_update_bits(lmk->regmap, LMK04832_REG_PLL2_R_MSB, + LMK04832_BIT_PLL2_R_MSB, + FIELD_GET(0x000700, r)); + if (ret) + return ret; + + ret = regmap_write(lmk->regmap, LMK04832_REG_PLL2_R_LSB, + FIELD_GET(0x0000ff, r)); + if (ret) + return ret; + + ret = regmap_update_bits(lmk->regmap, LMK04832_REG_PLL2_MISC, + LMK04832_BIT_PLL2_MISC_P, + FIELD_PREP(LMK04832_BIT_PLL2_MISC_P, p)); + if (ret) + return ret; + + /* + * PLL2_N registers must be programmed after other PLL2 dividers are + * programed to ensure proper VCO frequency calibration + */ + ret = regmap_write(lmk->regmap, LMK04832_REG_PLL2_N_0, + FIELD_GET(0x030000, n)); + if (ret) + return ret; + ret = regmap_write(lmk->regmap, LMK04832_REG_PLL2_N_1, + FIELD_GET(0x00ff00, n)); + if (ret) + return ret; + + return regmap_write(lmk->regmap, LMK04832_REG_PLL2_N_2, + FIELD_GET(0x0000ff, n)); +}; + +static const struct clk_ops lmk04832_vco_ops = { + .is_enabled = lmk04832_vco_is_enabled, + .prepare = lmk04832_vco_prepare, + .unprepare = lmk04832_vco_unprepare, + .recalc_rate = lmk04832_vco_recalc_rate, + .round_rate = lmk04832_vco_round_rate, + .set_rate = lmk04832_vco_set_rate, +}; + +/* + * lmk04832_register_vco - Initialize the internal VCO and clock distribution + * path in PLL2 single loop mode. + */ +static int lmk04832_register_vco(struct lmk04832 *lmk) +{ + const char *parent_names[1]; + struct clk_init_data init; + int ret; + + init.name = "lmk-vco"; + parent_names[0] = __clk_get_name(lmk->oscin); + init.parent_names = parent_names; + + init.ops = &lmk04832_vco_ops; + init.num_parents = 1; + + ret = regmap_update_bits(lmk->regmap, LMK04832_REG_VCO_OSCOUT, + LMK04832_BIT_VCO_MUX, + FIELD_PREP(LMK04832_BIT_VCO_MUX, + LMK04832_VAL_VCO_MUX_VCO1)); + if (ret) + return ret; + + ret = regmap_update_bits(lmk->regmap, LMK04832_REG_FB_CTRL, + LMK04832_BIT_PLL2_RCLK_MUX | + LMK04832_BIT_PLL2_NCLK_MUX, + FIELD_PREP(LMK04832_BIT_PLL2_RCLK_MUX, + LMK04832_VAL_PLL2_RCLK_MUX_OSCIN)| + FIELD_PREP(LMK04832_BIT_PLL2_NCLK_MUX, + LMK04832_VAL_PLL2_NCLK_MUX_PLL2_P)); + if (ret) + return ret; + + ret = regmap_update_bits(lmk->regmap, LMK04832_REG_PLL2_MISC, + LMK04832_BIT_PLL2_MISC_REF_2X_EN, + LMK04832_BIT_PLL2_MISC_REF_2X_EN); + if (ret) + return ret; + + ret = regmap_write(lmk->regmap, LMK04832_REG_PLL2_LD, + FIELD_PREP(LMK04832_BIT_PLL2_LD_MUX, + LMK04832_VAL_PLL2_LD_MUX_PLL2_DLD) | + FIELD_PREP(LMK04832_BIT_PLL2_LD_TYPE, + LMK04832_VAL_PLL2_LD_TYPE_OUT_PP)); + if (ret) + return ret; + + lmk->vco.init = &init; + return devm_clk_hw_register(lmk->dev, &lmk->vco); +} + +static int lmk04832_sclk_is_enabled(struct clk_hw *hw) +{ + struct lmk04832 *lmk = container_of(hw, struct lmk04832, sclk); + unsigned int tmp; + int ret; + + ret = regmap_read(lmk->regmap, LMK04832_REG_MAIN_PD, &tmp); + if (ret) + return ret; + + return FIELD_GET(LMK04832_BIT_SYSREF_PD, tmp); +} + +static int lmk04832_sclk_prepare(struct clk_hw *hw) +{ + struct lmk04832 *lmk = container_of(hw, struct lmk04832, sclk); + + return regmap_update_bits(lmk->regmap, LMK04832_REG_MAIN_PD, + LMK04832_BIT_SYSREF_PD, 0x00); +} + +static void lmk04832_sclk_unprepare(struct clk_hw *hw) +{ + struct lmk04832 *lmk = container_of(hw, struct lmk04832, sclk); + + regmap_update_bits(lmk->regmap, LMK04832_REG_MAIN_PD, + LMK04832_BIT_SYSREF_PD, LMK04832_BIT_SYSREF_PD); +} + +static unsigned long lmk04832_sclk_recalc_rate(struct clk_hw *hw, + unsigned long prate) +{ + struct lmk04832 *lmk = container_of(hw, struct lmk04832, sclk); + unsigned int sysref_div; + u8 tmp[2]; + int ret; + + ret = regmap_bulk_read(lmk->regmap, LMK04832_REG_SYSREF_DIV_MSB, &tmp, 2); + if (ret) + return ret; + + sysref_div = FIELD_GET(LMK04832_BIT_SYSREF_DIV_MSB, tmp[0]) << 8 | + tmp[1]; + + return DIV_ROUND_CLOSEST(prate, sysref_div); +} + +static long lmk04832_sclk_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *prate) +{ + struct lmk04832 *lmk = container_of(hw, struct lmk04832, sclk); + unsigned long sclk_rate; + unsigned int sysref_div; + + sysref_div = DIV_ROUND_CLOSEST(*prate, rate); + sclk_rate = DIV_ROUND_CLOSEST(*prate, sysref_div); + + if (sysref_div < 0x07 || sysref_div > 0x1fff) { + dev_err(lmk->dev, "SYSREF divider out of range\n"); + return -EINVAL; + } + + if (rate != sclk_rate) + return -EINVAL; + + return sclk_rate; +} + +static int lmk04832_sclk_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long prate) +{ + struct lmk04832 *lmk = container_of(hw, struct lmk04832, sclk); + unsigned int sysref_div; + int ret; + + sysref_div = DIV_ROUND_CLOSEST(prate, rate); + + if (sysref_div < 0x07 || sysref_div > 0x1fff) { + dev_err(lmk->dev, "SYSREF divider out of range\n"); + return -EINVAL; + } + + ret = regmap_write(lmk->regmap, LMK04832_REG_SYSREF_DIV_MSB, + FIELD_GET(0x1f00, sysref_div)); + if (ret) + return ret; + + return regmap_write(lmk->regmap, LMK04832_REG_SYSREF_DIV_LSB, + FIELD_GET(0x00ff, sysref_div)); +} + +static const struct clk_ops lmk04832_sclk_ops = { + .is_enabled = lmk04832_sclk_is_enabled, + .prepare = lmk04832_sclk_prepare, + .unprepare = lmk04832_sclk_unprepare, + .recalc_rate = lmk04832_sclk_recalc_rate, + .round_rate = lmk04832_sclk_round_rate, + .set_rate = lmk04832_sclk_set_rate, +}; + +static int lmk04832_register_sclk(struct lmk04832 *lmk) +{ + const char *parent_names[1]; + struct clk_init_data init; + int ret; + + init.name = "lmk-sclk"; + parent_names[0] = clk_hw_get_name(&lmk->vco); + init.parent_names = parent_names; + + init.ops = &lmk04832_sclk_ops; + init.flags = CLK_SET_RATE_PARENT; + init.num_parents = 1; + + ret = regmap_update_bits(lmk->regmap, LMK04832_REG_SYSREF_OUT, + LMK04832_BIT_SYSREF_MUX, + FIELD_PREP(LMK04832_BIT_SYSREF_MUX, + LMK04832_VAL_SYSREF_MUX_CONTINUOUS)); + if (ret) + return ret; + + ret = regmap_update_bits(lmk->regmap, LMK04832_REG_MAIN_PD, + LMK04832_BIT_SYSREF_PLSR_PD, + LMK04832_BIT_SYSREF_PLSR_PD); + if (ret) + return ret; + + ret = regmap_update_bits(lmk->regmap, LMK04832_REG_SYNC, + LMK04832_BIT_SYNC_EN, 0xff); + if (ret) + return ret; + + ret = regmap_write(lmk->regmap, LMK04832_REG_SYNC_DIS, 0xff); + if (ret) + return ret; + + lmk->sclk.init = &init; + return devm_clk_hw_register(lmk->dev, &lmk->sclk); +} + +static int lmk04832_dclk_is_enabled(struct clk_hw *hw) +{ + struct lmk_dclk *dclk = container_of(hw, struct lmk_dclk, hw); + struct lmk04832 *lmk = dclk->lmk; + unsigned int tmp; + int ret; + + ret = regmap_read(lmk->regmap, LMK04832_REG_CLKOUT_CTRL3(dclk->id), + &tmp); + if (ret) + return ret; + + return !FIELD_GET(LMK04832_BIT_DCLKX_Y_PD, tmp); +} + +static int lmk04832_dclk_prepare(struct clk_hw *hw) +{ + struct lmk_dclk *dclk = container_of(hw, struct lmk_dclk, hw); + struct lmk04832 *lmk = dclk->lmk; + + return regmap_update_bits(lmk->regmap, + LMK04832_REG_CLKOUT_CTRL3(dclk->id), + LMK04832_BIT_DCLKX_Y_PD, 0x00); +} + +static void lmk04832_dclk_unprepare(struct clk_hw *hw) +{ + struct lmk_dclk *dclk = container_of(hw, struct lmk_dclk, hw); + struct lmk04832 *lmk = dclk->lmk; + + regmap_update_bits(lmk->regmap, + LMK04832_REG_CLKOUT_CTRL3(dclk->id), + LMK04832_BIT_DCLKX_Y_PD, 0xff); +} + +static unsigned long lmk04832_dclk_recalc_rate(struct clk_hw *hw, + unsigned long prate) +{ + struct lmk_dclk *dclk = container_of(hw, struct lmk_dclk, hw); + struct lmk04832 *lmk = dclk->lmk; + unsigned int dclk_div; + unsigned int lsb, msb; + unsigned long rate; + int ret; + + ret = regmap_read(lmk->regmap, LMK04832_REG_CLKOUT_CTRL0(dclk->id), + &lsb); + if (ret) + return ret; + + ret = regmap_read(lmk->regmap, LMK04832_REG_CLKOUT_CTRL2(dclk->id), + &msb); + if (ret) + return ret; + + dclk_div = FIELD_GET(LMK04832_BIT_DCLK_DIV_MSB, msb) << 8 | lsb; + rate = DIV_ROUND_CLOSEST(prate, dclk_div); + + return rate; +}; + +static long lmk04832_dclk_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *prate) +{ + struct lmk_dclk *dclk = container_of(hw, struct lmk_dclk, hw); + struct lmk04832 *lmk = dclk->lmk; + unsigned long dclk_rate; + unsigned int dclk_div; + + dclk_div = DIV_ROUND_CLOSEST(*prate, rate); + dclk_rate = DIV_ROUND_CLOSEST(*prate, dclk_div); + + if (dclk_div < 1 || dclk_div > 0x3ff) { + dev_err(lmk->dev, "%s_div out of range\n", clk_hw_get_name(hw)); + return -EINVAL; + } + + if (rate != dclk_rate) + return -EINVAL; + + return dclk_rate; +}; + +static int lmk04832_dclk_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long prate) +{ + struct lmk_dclk *dclk = container_of(hw, struct lmk_dclk, hw); + struct lmk04832 *lmk = dclk->lmk; + unsigned int dclk_div; + int ret; + + dclk_div = DIV_ROUND_CLOSEST(prate, rate); + + if (dclk_div > 0x3ff) { + dev_err(lmk->dev, "%s_div out of range\n", clk_hw_get_name(hw)); + return -EINVAL; + } + + /* Enable Duty Cycle Corretion */ + if (dclk_div == 1) { + ret = regmap_update_bits(lmk->regmap, + LMK04832_REG_CLKOUT_CTRL3(dclk->id), + LMK04832_BIT_DCLKX_Y_DCC, + FIELD_PREP(LMK04832_BIT_DCLKX_Y_DCC, 1)); + if (ret) + return ret; + } + + ret = regmap_write(lmk->regmap, LMK04832_REG_CLKOUT_CTRL0(dclk->id), + FIELD_GET(0x0ff, dclk_div)); + if (ret) + return ret; + + return regmap_update_bits(lmk->regmap, + LMK04832_REG_CLKOUT_CTRL2(dclk->id), + LMK04832_BIT_DCLK_DIV_MSB, + FIELD_GET(0x300, dclk_div)); +}; + +static const struct clk_ops lmk04832_dclk_ops = { + .is_enabled = lmk04832_dclk_is_enabled, + .prepare = lmk04832_dclk_prepare, + .unprepare = lmk04832_dclk_unprepare, + .recalc_rate = lmk04832_dclk_recalc_rate, + .round_rate = lmk04832_dclk_round_rate, + .set_rate = lmk04832_dclk_set_rate, +}; + +static int lmk04832_clkout_is_enabled(struct clk_hw *hw) +{ + struct lmk_clkout *clkout = container_of(hw, struct lmk_clkout, hw); + struct lmk04832 *lmk = clkout->lmk; + unsigned int clkoutx_y_pd; + unsigned int sclkx_y_pd; + unsigned int tmp; + u32 enabled; + int ret; + u8 fmt; + + ret = regmap_read(lmk->regmap, LMK04832_REG_CLKOUT_CTRL2(clkout->id), + &clkoutx_y_pd); + if (ret) + return ret; + + enabled = !FIELD_GET(LMK04832_BIT_CLKOUTX_Y_PD, clkoutx_y_pd); + + ret = regmap_read(lmk->regmap, LMK04832_REG_CLKOUT_SRC_MUX(clkout->id), + &tmp); + if (ret) + return ret; + + if (FIELD_GET(LMK04832_BIT_CLKOUT_SRC_MUX, tmp)) { + ret = regmap_read(lmk->regmap, + LMK04832_REG_CLKOUT_CTRL4(clkout->id), + &sclkx_y_pd); + if (ret) + return ret; + + enabled = enabled && !FIELD_GET(LMK04832_BIT_SCLK_PD, sclkx_y_pd); + } + + ret = regmap_read(lmk->regmap, LMK04832_REG_CLKOUT_FMT(clkout->id), + &tmp); + if (ret) + return ret; + + if (clkout->id % 2) + fmt = FIELD_GET(0xf0, tmp); + else + fmt = FIELD_GET(0x0f, tmp); + + return enabled && !fmt; +} + +static int lmk04832_clkout_prepare(struct clk_hw *hw) +{ + struct lmk_clkout *clkout = container_of(hw, struct lmk_clkout, hw); + struct lmk04832 *lmk = clkout->lmk; + unsigned int tmp; + int ret; + + if (clkout->format == LMK04832_VAL_CLKOUT_FMT_POWERDOWN) + dev_err(lmk->dev, "prepared %s but format is powerdown\n", + clk_hw_get_name(hw)); + + ret = regmap_update_bits(lmk->regmap, + LMK04832_REG_CLKOUT_CTRL2(clkout->id), + LMK04832_BIT_CLKOUTX_Y_PD, 0x00); + if (ret) + return ret; + + ret = regmap_read(lmk->regmap, LMK04832_REG_CLKOUT_SRC_MUX(clkout->id), + &tmp); + if (ret) + return ret; + + if (FIELD_GET(LMK04832_BIT_CLKOUT_SRC_MUX, tmp)) { + ret = regmap_update_bits(lmk->regmap, + LMK04832_REG_CLKOUT_CTRL4(clkout->id), + LMK04832_BIT_SCLK_PD, 0x00); + if (ret) + return ret; + } + + return regmap_update_bits(lmk->regmap, + LMK04832_REG_CLKOUT_FMT(clkout->id), + LMK04832_BIT_CLKOUT_FMT(clkout->id), + clkout->format << 4 * (clkout->id % 2)); +} + +static void lmk04832_clkout_unprepare(struct clk_hw *hw) +{ + struct lmk_clkout *clkout = container_of(hw, struct lmk_clkout, hw); + struct lmk04832 *lmk = clkout->lmk; + + regmap_update_bits(lmk->regmap, LMK04832_REG_CLKOUT_FMT(clkout->id), + LMK04832_BIT_CLKOUT_FMT(clkout->id), + 0x00); +} + +static int lmk04832_clkout_set_parent(struct clk_hw *hw, uint8_t index) +{ + struct lmk_clkout *clkout = container_of(hw, struct lmk_clkout, hw); + struct lmk04832 *lmk = clkout->lmk; + + return regmap_update_bits(lmk->regmap, + LMK04832_REG_CLKOUT_SRC_MUX(clkout->id), + LMK04832_BIT_CLKOUT_SRC_MUX, + FIELD_PREP(LMK04832_BIT_CLKOUT_SRC_MUX, + index)); +} + +static uint8_t lmk04832_clkout_get_parent(struct clk_hw *hw) +{ + struct lmk_clkout *clkout = container_of(hw, struct lmk_clkout, hw); + struct lmk04832 *lmk = clkout->lmk; + unsigned int tmp; + int ret; + + ret = regmap_read(lmk->regmap, LMK04832_REG_CLKOUT_SRC_MUX(clkout->id), + &tmp); + if (ret) + return ret; + + return FIELD_GET(LMK04832_BIT_CLKOUT_SRC_MUX, tmp); +} + +static const struct clk_ops lmk04832_clkout_ops = { + .is_enabled = lmk04832_clkout_is_enabled, + .prepare = lmk04832_clkout_prepare, + .unprepare = lmk04832_clkout_unprepare, + .set_parent = lmk04832_clkout_set_parent, + .get_parent = lmk04832_clkout_get_parent, +}; + +static int lmk04832_register_clkout(struct lmk04832 *lmk, const int num) +{ + char name[] = "lmk-clkoutXX"; + char dclk_name[] = "lmk-dclkXX_YY"; + const char *parent_names[2]; + struct clk_init_data init; + int dclk_num = num / 2; + int ret; + + if (num % 2 == 0) { + sprintf(dclk_name, "lmk-dclk%02d_%02d", num, num + 1); + init.name = dclk_name; + parent_names[0] = clk_hw_get_name(&lmk->vco); + init.ops = &lmk04832_dclk_ops; + init.flags = CLK_SET_RATE_PARENT; + init.num_parents = 1; + + lmk->dclk[dclk_num].id = num; + lmk->dclk[dclk_num].lmk = lmk; + lmk->dclk[dclk_num].hw.init = &init; + + ret = devm_clk_hw_register(lmk->dev, &lmk->dclk[dclk_num].hw); + if (ret) + return ret; + } else { + sprintf(dclk_name, "lmk-dclk%02d_%02d", num - 1, num); + } + + if (of_property_read_string_index(lmk->dev->of_node, + "clock-output-names", + num, &init.name)) { + sprintf(name, "lmk-clkout%02d", num); + init.name = name; + } + + parent_names[0] = dclk_name; + parent_names[1] = clk_hw_get_name(&lmk->sclk); + init.parent_names = parent_names; + init.ops = &lmk04832_clkout_ops; + init.flags = CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT; + init.num_parents = ARRAY_SIZE(parent_names); + + lmk->clkout[num].id = num; + lmk->clkout[num].lmk = lmk; + lmk->clkout[num].hw.init = &init; + lmk->clk_data->hws[num] = &lmk->clkout[num].hw; + + /* Set initial parent */ + regmap_update_bits(lmk->regmap, + LMK04832_REG_CLKOUT_SRC_MUX(num), + LMK04832_BIT_CLKOUT_SRC_MUX, + FIELD_PREP(LMK04832_BIT_CLKOUT_SRC_MUX, + lmk->clkout[num].sysref)); + + return devm_clk_hw_register(lmk->dev, &lmk->clkout[num].hw); +} + +static int lmk04832_set_spi_rdbk(const struct lmk04832 *lmk, const int rdbk_pin) +{ + int reg; + int ret; + + dev_info(lmk->dev, "setting up 4-wire mode\n"); + ret = regmap_write(lmk->regmap, LMK04832_REG_RST3W, + LMK04832_BIT_SPI_3WIRE_DIS); + if (ret) + return ret; + + switch (rdbk_pin) { + case RDBK_CLKIN_SEL0: + reg = LMK04832_REG_CLKIN_SEL0; + break; + case RDBK_CLKIN_SEL1: + reg = LMK04832_REG_CLKIN_SEL1; + break; + case RDBK_RESET: + reg = LMK04832_REG_CLKIN_RST; + break; + default: + return -EINVAL; + } + + return regmap_write(lmk->regmap, reg, + FIELD_PREP(LMK04832_BIT_CLKIN_SEL_MUX, + LMK04832_VAL_CLKIN_SEL_MUX_SPI_RDBK) | + FIELD_PREP(LMK04832_BIT_CLKIN_SEL_TYPE, + LMK04832_VAL_CLKIN_SEL_TYPE_OUT)); +} + +static int lmk04832_probe(struct spi_device *spi) +{ + const struct lmk04832_device_info *info; + int rdbk_pin = RDBK_CLKIN_SEL1; + struct device_node *child; + struct lmk04832 *lmk; + u8 tmp[3]; + int ret; + int i; + + info = &lmk04832_device_info[spi_get_device_id(spi)->driver_data]; + + lmk = devm_kzalloc(&spi->dev, sizeof(struct lmk04832), GFP_KERNEL); + if (!lmk) + return -ENOMEM; + + lmk->dev = &spi->dev; + + lmk->oscin = devm_clk_get(lmk->dev, "oscin"); + if (IS_ERR(lmk->oscin)) { + dev_err(lmk->dev, "failed to get oscin clock\n"); + return PTR_ERR(lmk->oscin); + } + + ret = clk_prepare_enable(lmk->oscin); + if (ret) + return ret; + + lmk->reset_gpio = devm_gpiod_get_optional(&spi->dev, "reset", + GPIOD_OUT_LOW); + + lmk->dclk = devm_kcalloc(lmk->dev, info->num_channels >> 1, + sizeof(struct lmk_dclk), GFP_KERNEL); + if (IS_ERR(lmk->dclk)) { + ret = PTR_ERR(lmk->dclk); + goto err_disable_oscin; + } + + lmk->clkout = devm_kcalloc(lmk->dev, info->num_channels, + sizeof(*lmk->clkout), GFP_KERNEL); + if (IS_ERR(lmk->clkout)) { + ret = PTR_ERR(lmk->clkout); + goto err_disable_oscin; + } + + lmk->clk_data = devm_kzalloc(lmk->dev, struct_size(lmk->clk_data, hws, + info->num_channels), + GFP_KERNEL); + if (IS_ERR(lmk->clk_data)) { + ret = PTR_ERR(lmk->clk_data); + goto err_disable_oscin; + } + + device_property_read_u32(lmk->dev, "ti,vco-hz", &lmk->vco_rate); + + for_each_child_of_node(lmk->dev->of_node, child) { + int reg; + + ret = of_property_read_u32(child, "reg", ®); + if (ret) { + dev_err(lmk->dev, "missing reg property in child: %s\n", + child->full_name); + of_node_put(child); + goto err_disable_oscin; + } + + of_property_read_u32(child, "ti,clkout-fmt", + &lmk->clkout[reg].format); + + if (lmk->clkout[reg].format >= 0x0a && reg % 2 == 0 + && reg != 8 && reg != 10) + dev_err(lmk->dev, "invalid format for clkout%02d\n", + reg); + + lmk->clkout[reg].sysref = + of_property_read_bool(child, "ti,clkout-sysref"); + } + + lmk->regmap = devm_regmap_init_spi(spi, ®map_config); + if (IS_ERR(lmk->regmap)) { + dev_err(lmk->dev, "%s: regmap allocation failed: %ld\n", + + __func__, PTR_ERR(lmk->regmap)); + ret = PTR_ERR(lmk->regmap); + goto err_disable_oscin; + } + + regmap_write(lmk->regmap, LMK04832_REG_RST3W, LMK04832_BIT_RESET); + + if (!(spi->mode & SPI_3WIRE)) { + device_property_read_u32(lmk->dev, "ti,spi-4wire-rdbk", + &rdbk_pin); + ret = lmk04832_set_spi_rdbk(lmk, rdbk_pin); + if (ret) + goto err_disable_oscin; + } + + regmap_bulk_read(lmk->regmap, LMK04832_REG_ID_PROD_MSB, &tmp, 3); + if ((tmp[0] << 8 | tmp[1]) != info->pid || tmp[2] != info->maskrev) { + dev_err(lmk->dev, "unsupported device type: pid 0x%04x, maskrev 0x%02x\n", + tmp[0] << 8 | tmp[1], tmp[2]); + ret = -EINVAL; + goto err_disable_oscin; + } + + ret = lmk04832_register_vco(lmk); + if (ret) { + dev_err(lmk->dev, "failed to init device clock path\n"); + goto err_disable_oscin; + } + + if (lmk->vco_rate) { + dev_info(lmk->dev, "setting VCO rate to %u Hz\n", lmk->vco_rate); + ret = clk_set_rate(lmk->vco.clk, lmk->vco_rate); + if (ret) { + dev_err(lmk->dev, "failed to set VCO rate\n"); + goto err_disable_vco; + } + } + + ret = lmk04832_register_sclk(lmk); + if (ret) { + dev_err(lmk->dev, "failed to init SYNC/SYSREF clock path\n"); + goto err_disable_vco; + } + + for (i = 0; i < info->num_channels; i++) { + ret = lmk04832_register_clkout(lmk, i); + if (ret) { + dev_err(lmk->dev, "failed to register clk %d\n", i); + goto err_disable_vco; + } + } + + lmk->clk_data->num = info->num_channels; + ret = of_clk_add_hw_provider(lmk->dev->of_node, of_clk_hw_onecell_get, + lmk->clk_data); + if (ret) { + dev_err(lmk->dev, "failed to add provider (%d)\n", ret); + goto err_disable_vco; + } + + spi_set_drvdata(spi, lmk); + + return 0; + +err_disable_vco: + clk_disable_unprepare(lmk->vco.clk); + +err_disable_oscin: + clk_disable_unprepare(lmk->oscin); + + return ret; +} + +static int lmk04832_remove(struct spi_device *spi) +{ + struct lmk04832 *lmk = spi_get_drvdata(spi); + + clk_disable_unprepare(lmk->oscin); + of_clk_del_provider(spi->dev.of_node); + + return 0; +} +static const struct spi_device_id lmk04832_id[] = { + { "lmk04832", LMK04832 }, + {}, +}; +MODULE_DEVICE_TABLE(spi, lmk04832_id); + +static const struct of_device_id lmk04832_of_id[] = { + { .compatible = "ti,lmk04832" }, + {}, +}; + +static struct spi_driver lmk04832_driver = { + .driver = { + .name = "lmk04832", + }, + .probe = lmk04832_probe, + .remove = lmk04832_remove, + .id_table = lmk04832_id, +}; +module_spi_driver(lmk04832_driver); + +MODULE_AUTHOR("Liam Beguin "); +MODULE_DESCRIPTION("Texas Instruments LMK04832"); +MODULE_LICENSE("GPL v2"); From 6181baa177d417211ea28de793524ec3d13b256d Mon Sep 17 00:00:00 2001 From: Liam Beguin Date: Thu, 22 Apr 2021 20:40:56 -0400 Subject: [PATCH 111/161] clk: lmk04832: add support for digital delay The digital delay allows outputs to be delayed from 8 to 1023 VCO cycles. The delay step can be as small as half the period of the clock distribution path. For example, a 3.2-GHz VCO frequency results in 156.25-ps steps. The digital delay value takes effect on the clock output phase after a SYNC event. This is required to support JESD204B subclass 1. Signed-off-by: Liam Beguin Link: https://lore.kernel.org/r/20210423004057.283926-3-liambeguin@gmail.com Signed-off-by: Stephen Boyd --- drivers/clk/clk-lmk04832.c | 321 ++++++++++++++++++++++++++++++++++++- 1 file changed, 315 insertions(+), 6 deletions(-) diff --git a/drivers/clk/clk-lmk04832.c b/drivers/clk/clk-lmk04832.c index ae80af7f89fb..0cd76e626c3d 100644 --- a/drivers/clk/clk-lmk04832.c +++ b/drivers/clk/clk-lmk04832.c @@ -37,16 +37,24 @@ #define LMK04832_REG_CLKOUT_CTRL0(ch) (0x100 + (ch >> 1) * 8) #define LMK04832_BIT_DCLK_DIV_LSB GENMASK(7, 0) #define LMK04832_REG_CLKOUT_CTRL1(ch) (0x101 + (ch >> 1) * 8) +#define LMK04832_BIT_DCLKX_Y_DDLY_LSB GENMASK(7, 0) #define LMK04832_REG_CLKOUT_CTRL2(ch) (0x102 + (ch >> 1) * 8) #define LMK04832_BIT_CLKOUTX_Y_PD BIT(7) +#define LMK04832_BIT_DCLKX_Y_DDLY_PD BIT(4) +#define LMK04832_BIT_DCLKX_Y_DDLY_MSB GENMASK(3, 2) #define LMK04832_BIT_DCLK_DIV_MSB GENMASK(1, 0) #define LMK04832_REG_CLKOUT_SRC_MUX(ch) (0x103 + (ch % 2) + (ch >> 1) * 8) #define LMK04832_BIT_CLKOUT_SRC_MUX BIT(5) #define LMK04832_REG_CLKOUT_CTRL3(ch) (0x103 + (ch >> 1) * 8) #define LMK04832_BIT_DCLKX_Y_PD BIT(4) #define LMK04832_BIT_DCLKX_Y_DCC BIT(2) +#define LMK04832_BIT_DCLKX_Y_HS BIT(0) #define LMK04832_REG_CLKOUT_CTRL4(ch) (0x104 + (ch >> 1) * 8) #define LMK04832_BIT_SCLK_PD BIT(4) +#define LMK04832_BIT_SCLKX_Y_DIS_MODE GENMASK(3, 2) +#define LMK04832_REG_SCLKX_Y_ADLY(ch) (0x105 + (ch >> 1) * 8) +#define LMK04832_REG_SCLKX_Y_DDLY(ch) (0x106 + (ch >> 1) * 8) +#define LMK04832_BIT_SCLKX_Y_DDLY GENMASK(3, 0) #define LMK04832_REG_CLKOUT_FMT(ch) (0x107 + (ch >> 1) * 8) #define LMK04832_BIT_CLKOUT_FMT(ch) (ch % 2 ? 0xf0 : 0x0f) #define LMK04832_VAL_CLKOUT_FMT_POWERDOWN 0x00 @@ -73,11 +81,19 @@ #define LMK04832_VAL_VCO_MUX_VCO1 0x01 #define LMK04832_VAL_VCO_MUX_EXT 0x02 #define LMK04832_REG_SYSREF_OUT 0x139 +#define LMK04832_BIT_SYSREF_REQ_EN BIT(6) #define LMK04832_BIT_SYSREF_MUX GENMASK(1, 0) +#define LMK04832_VAL_SYSREF_MUX_NORMAL_SYNC 0x00 +#define LMK04832_VAL_SYSREF_MUX_RECLK 0x01 +#define LMK04832_VAL_SYSREF_MUX_PULSER 0x02 #define LMK04832_VAL_SYSREF_MUX_CONTINUOUS 0x03 #define LMK04832_REG_SYSREF_DIV_MSB 0x13a #define LMK04832_BIT_SYSREF_DIV_MSB GENMASK(4, 0) #define LMK04832_REG_SYSREF_DIV_LSB 0x13b +#define LMK04832_REG_SYSREF_DDLY_MSB 0x13c +#define LMK04832_BIT_SYSREF_DDLY_MSB GENMASK(4, 0) +#define LMK04832_REG_SYSREF_DDLY_LSB 0x13d +#define LMK04832_REG_SYSREF_PULSE_CNT 0x13e #define LMK04832_REG_FB_CTRL 0x13f #define LMK04832_BIT_PLL2_RCLK_MUX BIT(7) #define LMK04832_VAL_PLL2_RCLK_MUX_OSCIN 0x00 @@ -96,7 +112,15 @@ #define LMK04832_BIT_SYSREF_DDLY_PD BIT(1) #define LMK04832_BIT_SYSREF_PLSR_PD BIT(0) #define LMK04832_REG_SYNC 0x143 +#define LMK04832_BIT_SYNC_CLR BIT(7) +#define LMK04832_BIT_SYNC_1SHOT_EN BIT(6) +#define LMK04832_BIT_SYNC_POL BIT(5) #define LMK04832_BIT_SYNC_EN BIT(4) +#define LMK04832_BIT_SYNC_MODE GENMASK(1, 0) +#define LMK04832_VAL_SYNC_MODE_OFF 0x00 +#define LMK04832_VAL_SYNC_MODE_ON 0x01 +#define LMK04832_VAL_SYNC_MODE_PULSER_PIN 0x02 +#define LMK04832_VAL_SYNC_MODE_PULSER_SPI 0x03 #define LMK04832_REG_SYNC_DIS 0x144 /* 0x146 - 0x14a CLKin Control */ @@ -128,6 +152,7 @@ #define LMK04832_BIT_PLL2_N_0 GENMASK(1, 0) #define LMK04832_REG_PLL2_N_1 0x167 #define LMK04832_REG_PLL2_N_2 0x168 +#define LMK04832_REG_PLL2_DLD_CNT_MSB 0x16a #define LMK04832_REG_PLL2_DLD_CNT_LSB 0x16b #define LMK04832_REG_PLL2_LD 0x16e #define LMK04832_BIT_PLL2_LD_MUX GENMASK(7, 3) @@ -204,6 +229,11 @@ struct lmk_clkout { * * @dev: reference to a struct device, linked to the spi_device * @regmap: struct regmap instance use to access the chip + * @sync_mode: operational mode for SYNC signal + * @sysref_mux: select SYSREF source + * @sysref_pulse_cnt: number of SYSREF pulses generated while not in continuous + * mode. + * @sysref_ddly: SYSREF digital delay value * @oscin: PLL2 input clock * @vco: reference to the internal VCO clock * @sclk: reference to the internal sysref clock (SCLK) @@ -218,6 +248,11 @@ struct lmk04832 { struct device *dev; struct regmap *regmap; + unsigned int sync_mode; + unsigned int sysref_mux; + unsigned int sysref_pulse_cnt; + unsigned int sysref_ddly; + struct clk *oscin; struct clk_hw vco; struct clk_hw sclk; @@ -614,6 +649,212 @@ static int lmk04832_register_vco(struct lmk04832 *lmk) return devm_clk_hw_register(lmk->dev, &lmk->vco); } +static int lmk04832_clkout_set_ddly(struct lmk04832 *lmk, int id) +{ + int dclk_div_adj[] = {0, 0, -2, -2, 0, 3, -1, 0}; + unsigned int sclkx_y_ddly = 10; + unsigned int dclkx_y_ddly; + unsigned int dclkx_y_div; + unsigned int sysref_ddly; + unsigned int dclkx_y_hs; + unsigned int lsb, msb; + int ret; + + ret = regmap_update_bits(lmk->regmap, + LMK04832_REG_CLKOUT_CTRL2(id), + LMK04832_BIT_DCLKX_Y_DDLY_PD, + FIELD_PREP(LMK04832_BIT_DCLKX_Y_DDLY_PD, 0)); + if (ret) + return ret; + + ret = regmap_read(lmk->regmap, LMK04832_REG_SYSREF_DDLY_LSB, &lsb); + if (ret) + return ret; + + ret = regmap_read(lmk->regmap, LMK04832_REG_SYSREF_DDLY_MSB, &msb); + if (ret) + return ret; + + sysref_ddly = FIELD_GET(LMK04832_BIT_SYSREF_DDLY_MSB, msb) << 8 | lsb; + + ret = regmap_read(lmk->regmap, LMK04832_REG_CLKOUT_CTRL0(id), &lsb); + if (ret) + return ret; + + ret = regmap_read(lmk->regmap, LMK04832_REG_CLKOUT_CTRL2(id), &msb); + if (ret) + return ret; + + dclkx_y_div = FIELD_GET(LMK04832_BIT_DCLK_DIV_MSB, msb) << 8 | lsb; + + ret = regmap_read(lmk->regmap, LMK04832_REG_CLKOUT_CTRL3(id), &lsb); + if (ret) + return ret; + + dclkx_y_hs = FIELD_GET(LMK04832_BIT_DCLKX_Y_HS, lsb); + + dclkx_y_ddly = sysref_ddly + 1 - + dclk_div_adj[dclkx_y_div < 6 ? dclkx_y_div : 7] - + dclkx_y_hs + sclkx_y_ddly; + + if (dclkx_y_ddly < 7 || dclkx_y_ddly > 0x3fff) { + dev_err(lmk->dev, "DCLKX_Y_DDLY out of range (%d)\n", + dclkx_y_ddly); + return -EINVAL; + } + + ret = regmap_write(lmk->regmap, + LMK04832_REG_SCLKX_Y_DDLY(id), + FIELD_GET(LMK04832_BIT_SCLKX_Y_DDLY, sclkx_y_ddly)); + if (ret) + return ret; + + ret = regmap_write(lmk->regmap, LMK04832_REG_CLKOUT_CTRL1(id), + FIELD_GET(0x00ff, dclkx_y_ddly)); + if (ret) + return ret; + + dev_dbg(lmk->dev, "clkout%02u: sysref_ddly=%u, dclkx_y_ddly=%u, " + "dclk_div_adj=%+d, dclkx_y_hs=%u, sclkx_y_ddly=%u\n", + id, sysref_ddly, dclkx_y_ddly, + dclk_div_adj[dclkx_y_div < 6 ? dclkx_y_div : 7], + dclkx_y_hs, sclkx_y_ddly); + + return regmap_update_bits(lmk->regmap, LMK04832_REG_CLKOUT_CTRL2(id), + LMK04832_BIT_DCLKX_Y_DDLY_MSB, + FIELD_GET(0x0300, dclkx_y_ddly)); +} + +/** lmk04832_sclk_sync - Establish deterministic phase relationship between sclk + * and dclk + * + * @lmk: Reference to the lmk device + * + * The synchronization sequence: + * - in the datasheet https://www.ti.com/lit/ds/symlink/lmk04832.pdf, p.31 + * (8.3.3.1 How to enable SYSREF) + * - Ti forum: https://e2e.ti.com/support/clock-and-timing/f/48/t/970972 + * + * Returns 0 or negative errno. + */ +static int lmk04832_sclk_sync_sequence(struct lmk04832 *lmk) +{ + int ret; + int i; + + /* 1. (optional) mute all sysref_outputs during synchronization */ + /* 2. Enable and write device clock digital delay to applicable clocks */ + ret = regmap_update_bits(lmk->regmap, LMK04832_REG_MAIN_PD, + LMK04832_BIT_SYSREF_DDLY_PD, + FIELD_PREP(LMK04832_BIT_SYSREF_DDLY_PD, 0)); + if (ret) + return ret; + + for (i = 0; i < lmk->clk_data->num; i += 2) { + ret = lmk04832_clkout_set_ddly(lmk, i); + if (ret) + return ret; + } + + /* + * 3. Configure SYNC_MODE to SYNC_PIN and SYSREF_MUX to Normal SYNC, + * and clear SYSREF_REQ_EN (see 6.) + */ + ret = regmap_update_bits(lmk->regmap, LMK04832_REG_SYSREF_OUT, + LMK04832_BIT_SYSREF_REQ_EN | + LMK04832_BIT_SYSREF_MUX, + FIELD_PREP(LMK04832_BIT_SYSREF_REQ_EN, 0) | + FIELD_PREP(LMK04832_BIT_SYSREF_MUX, + LMK04832_VAL_SYSREF_MUX_NORMAL_SYNC)); + if (ret) + return ret; + + ret = regmap_update_bits(lmk->regmap, LMK04832_REG_SYNC, + LMK04832_BIT_SYNC_MODE, + FIELD_PREP(LMK04832_BIT_SYNC_MODE, + LMK04832_VAL_SYNC_MODE_ON)); + if (ret) + return ret; + + /* 4. Clear SYNXC_DISx or applicable clocks and clear SYNC_DISSYSREF */ + ret = regmap_write(lmk->regmap, LMK04832_REG_SYNC_DIS, 0x00); + if (ret) + return ret; + + /* + * 5. If SCLKX_Y_DDLY != 0, Set SYSREF_CLR=1 for at least 15 clock + * distribution path cycles (VCO cycles), then back to 0. In + * PLL2-only use case, this will be complete in less than one SPI + * transaction. If SYSREF local digital delay is not used, this step + * can be skipped. + */ + ret = regmap_update_bits(lmk->regmap, LMK04832_REG_SYNC, + LMK04832_BIT_SYNC_CLR, + FIELD_PREP(LMK04832_BIT_SYNC_CLR, 0x01)); + if (ret) + return ret; + + ret = regmap_update_bits(lmk->regmap, LMK04832_REG_SYNC, + LMK04832_BIT_SYNC_CLR, + FIELD_PREP(LMK04832_BIT_SYNC_CLR, 0x00)); + if (ret) + return ret; + + /* + * 6. Toggle SYNC_POL state between inverted and not inverted. + * If you use an external signal on the SYNC pin instead of toggling + * SYNC_POL, make sure that SYSREF_REQ_EN=0 so that the SYSREF_MUX + * does not shift into continuous SYSREF mode. + */ + ret = regmap_update_bits(lmk->regmap, LMK04832_REG_SYNC, + LMK04832_BIT_SYNC_POL, + FIELD_PREP(LMK04832_BIT_SYNC_POL, 0x01)); + if (ret) + return ret; + + ret = regmap_update_bits(lmk->regmap, LMK04832_REG_SYNC, + LMK04832_BIT_SYNC_POL, + FIELD_PREP(LMK04832_BIT_SYNC_POL, 0x00)); + if (ret) + return ret; + + /* 7. Set all SYNC_DISx=1, including SYNC_DISSYSREF */ + ret = regmap_write(lmk->regmap, LMK04832_REG_SYNC_DIS, 0xff); + if (ret) + return ret; + + /* 8. Restore state of SYNC_MODE and SYSREF_MUX to desired values */ + ret = regmap_update_bits(lmk->regmap, LMK04832_REG_SYSREF_OUT, + LMK04832_BIT_SYSREF_MUX, + FIELD_PREP(LMK04832_BIT_SYSREF_MUX, + lmk->sysref_mux)); + if (ret) + return ret; + + ret = regmap_update_bits(lmk->regmap, LMK04832_REG_SYNC, + LMK04832_BIT_SYNC_MODE, + FIELD_PREP(LMK04832_BIT_SYNC_MODE, + lmk->sync_mode)); + if (ret) + return ret; + + /* + * 9. (optional) if SCLKx_y_DIS_MODE was used to mute SYSREF outputs + * during the SYNC event, restore SCLKx_y_DIS_MODE=0 for active state, + * or set SYSREF_GBL_PD=0 if SCLKx_y_DIS_MODE is set to a conditional + * option. + */ + + /* + * 10. (optional) To reduce power consumption, after the synchronization + * event is complete, DCLKx_y_DDLY_PD=1 and SYSREF_DDLY_PD=1 disable the + * digital delay counters (which are only used immediately after the + * SYNC pulse to delay the output by some number of VCO counts). + */ + + return ret; +} + static int lmk04832_sclk_is_enabled(struct clk_hw *hw) { struct lmk04832 *lmk = container_of(hw, struct lmk04832, sclk); @@ -701,8 +942,16 @@ static int lmk04832_sclk_set_rate(struct clk_hw *hw, unsigned long rate, if (ret) return ret; - return regmap_write(lmk->regmap, LMK04832_REG_SYSREF_DIV_LSB, + ret = regmap_write(lmk->regmap, LMK04832_REG_SYSREF_DIV_LSB, FIELD_GET(0x00ff, sysref_div)); + if (ret) + return ret; + + ret = lmk04832_sclk_sync_sequence(lmk); + if (ret) + dev_err(lmk->dev, "SYNC sequence failed\n"); + + return ret; } static const struct clk_ops lmk04832_sclk_ops = { @@ -731,18 +980,37 @@ static int lmk04832_register_sclk(struct lmk04832 *lmk) ret = regmap_update_bits(lmk->regmap, LMK04832_REG_SYSREF_OUT, LMK04832_BIT_SYSREF_MUX, FIELD_PREP(LMK04832_BIT_SYSREF_MUX, - LMK04832_VAL_SYSREF_MUX_CONTINUOUS)); + lmk->sysref_mux)); + if (ret) + return ret; + + ret = regmap_write(lmk->regmap, LMK04832_REG_SYSREF_DDLY_LSB, + FIELD_GET(0x00ff, lmk->sysref_ddly)); + if (ret) + return ret; + + ret = regmap_write(lmk->regmap, LMK04832_REG_SYSREF_DDLY_MSB, + FIELD_GET(0x1f00, lmk->sysref_ddly)); + if (ret) + return ret; + + ret = regmap_write(lmk->regmap, LMK04832_REG_SYSREF_PULSE_CNT, + ilog2(lmk->sysref_pulse_cnt)); if (ret) return ret; ret = regmap_update_bits(lmk->regmap, LMK04832_REG_MAIN_PD, + LMK04832_BIT_SYSREF_DDLY_PD | LMK04832_BIT_SYSREF_PLSR_PD, - LMK04832_BIT_SYSREF_PLSR_PD); + FIELD_PREP(LMK04832_BIT_SYSREF_DDLY_PD, 0) | + FIELD_PREP(LMK04832_BIT_SYSREF_PLSR_PD, 0)); if (ret) return ret; - ret = regmap_update_bits(lmk->regmap, LMK04832_REG_SYNC, - LMK04832_BIT_SYNC_EN, 0xff); + ret = regmap_write(lmk->regmap, LMK04832_REG_SYNC, + FIELD_PREP(LMK04832_BIT_SYNC_POL, 0) | + FIELD_PREP(LMK04832_BIT_SYNC_EN, 1) | + FIELD_PREP(LMK04832_BIT_SYNC_MODE, lmk->sync_mode)); if (ret) return ret; @@ -862,15 +1130,41 @@ static int lmk04832_dclk_set_rate(struct clk_hw *hw, unsigned long rate, return ret; } + /* + * While using Divide-by-2 or Divide-by-3 for DCLK_X_Y_DIV, SYNC + * procedure requires to first program Divide-by-4 and then back to + * Divide-by-2 or Divide-by-3 before doing SYNC. + */ + if (dclk_div == 2 || dclk_div == 3) { + ret = regmap_update_bits(lmk->regmap, + LMK04832_REG_CLKOUT_CTRL2(dclk->id), + LMK04832_BIT_DCLK_DIV_MSB, 0x00); + if (ret) + return ret; + + ret = regmap_write(lmk->regmap, + LMK04832_REG_CLKOUT_CTRL0(dclk->id), 0x04); + if (ret) + return ret; + } + ret = regmap_write(lmk->regmap, LMK04832_REG_CLKOUT_CTRL0(dclk->id), FIELD_GET(0x0ff, dclk_div)); if (ret) return ret; - return regmap_update_bits(lmk->regmap, + ret = regmap_update_bits(lmk->regmap, LMK04832_REG_CLKOUT_CTRL2(dclk->id), LMK04832_BIT_DCLK_DIV_MSB, FIELD_GET(0x300, dclk_div)); + if (ret) + return ret; + + ret = lmk04832_sclk_sync_sequence(lmk); + if (ret) + dev_err(lmk->dev, "SYNC sequence failed\n"); + + return ret; }; static const struct clk_ops lmk04832_dclk_ops = { @@ -1153,6 +1447,21 @@ static int lmk04832_probe(struct spi_device *spi) device_property_read_u32(lmk->dev, "ti,vco-hz", &lmk->vco_rate); + lmk->sysref_ddly = 8; + device_property_read_u32(lmk->dev, "ti,sysref-ddly", &lmk->sysref_ddly); + + lmk->sysref_mux = LMK04832_VAL_SYSREF_MUX_CONTINUOUS; + device_property_read_u32(lmk->dev, "ti,sysref-mux", + &lmk->sysref_mux); + + lmk->sync_mode = LMK04832_VAL_SYNC_MODE_OFF; + device_property_read_u32(lmk->dev, "ti,sync-mode", + &lmk->sync_mode); + + lmk->sysref_pulse_cnt = 4; + device_property_read_u32(lmk->dev, "ti,sysref-pulse-count", + &lmk->sysref_pulse_cnt); + for_each_child_of_node(lmk->dev->of_node, child) { int reg; From 47c671da45dc6e0940843cb67e644e77c84cede3 Mon Sep 17 00:00:00 2001 From: Gabriel Fernandez Date: Thu, 17 Jun 2021 07:18:04 +0200 Subject: [PATCH 112/161] clk: stm32mp1: merge 'clk-hsi-div' and 'ck_hsi' into one clock This patch is to prepare STM32MP1 clocks in trusted mode. This Merge will facilitate to have a more coherent clock tree in no trusted / trusted world. Signed-off-by: Gabriel Fernandez Link: https://lore.kernel.org/r/20210617051814.12018-2-gabriel.fernandez@foss.st.com Signed-off-by: Stephen Boyd --- drivers/clk/clk-stm32mp1.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/clk/clk-stm32mp1.c b/drivers/clk/clk-stm32mp1.c index a875649df8b8..35d5aee8f9b0 100644 --- a/drivers/clk/clk-stm32mp1.c +++ b/drivers/clk/clk-stm32mp1.c @@ -1657,16 +1657,16 @@ static const struct stm32_mux_cfg ker_mux_cfg[M_LAST] = { }; static const struct clock_config stm32mp1_clock_cfg[] = { - /* Oscillator divider */ - DIV(NO_ID, "clk-hsi-div", "clk-hsi", CLK_DIVIDER_POWER_OF_TWO, - RCC_HSICFGR, 0, 2, CLK_DIVIDER_READ_ONLY), - /* External / Internal Oscillators */ GATE_MP1(CK_HSE, "ck_hse", "clk-hse", 0, RCC_OCENSETR, 8, 0), /* ck_csi is used by IO compensation and should be critical */ GATE_MP1(CK_CSI, "ck_csi", "clk-csi", CLK_IS_CRITICAL, RCC_OCENSETR, 4, 0), - GATE_MP1(CK_HSI, "ck_hsi", "clk-hsi-div", 0, RCC_OCENSETR, 0, 0), + COMPOSITE(CK_HSI, "ck_hsi", PARENT("clk-hsi"), 0, + _GATE_MP1(RCC_OCENSETR, 0, 0), + _NO_MUX, + _DIV(RCC_HSICFGR, 0, 2, CLK_DIVIDER_POWER_OF_TWO | + CLK_DIVIDER_READ_ONLY, NULL)), GATE(CK_LSI, "ck_lsi", "clk-lsi", 0, RCC_RDLSICR, 0, 0), GATE(CK_LSE, "ck_lse", "clk-lse", 0, RCC_BDCR, 0, 0), From 152efe5662ea442085a20dd7993c472bed5b084c Mon Sep 17 00:00:00 2001 From: Gabriel Fernandez Date: Thu, 17 Jun 2021 07:18:05 +0200 Subject: [PATCH 113/161] clk: stm32mp1: merge 'ck_hse_rtc' and 'ck_rtc' into one clock 'ck_rtc' has multiple clocks as input (ck_hsi, ck_lsi, and ck_hse). A divider is available only on the specific rtc input for ck_hse. This Merge will facilitate to have a more coherent clock tree in no trusted / trusted world. Signed-off-by: Gabriel Fernandez Link: https://lore.kernel.org/r/20210617051814.12018-3-gabriel.fernandez@foss.st.com Signed-off-by: Stephen Boyd --- drivers/clk/clk-stm32mp1.c | 54 +++++++++++++++++++++++++++++++++----- 1 file changed, 48 insertions(+), 6 deletions(-) diff --git a/drivers/clk/clk-stm32mp1.c b/drivers/clk/clk-stm32mp1.c index 35d5aee8f9b0..a7c244fd0b03 100644 --- a/drivers/clk/clk-stm32mp1.c +++ b/drivers/clk/clk-stm32mp1.c @@ -245,7 +245,7 @@ static const char * const dsi_src[] = { }; static const char * const rtc_src[] = { - "off", "ck_lse", "ck_lsi", "ck_hse_rtc" + "off", "ck_lse", "ck_lsi", "ck_hse" }; static const char * const mco1_src[] = { @@ -1031,6 +1031,47 @@ static struct clk_hw *clk_register_cktim(struct device *dev, const char *name, return hw; } +/* The divider of RTC clock concerns only ck_hse clock */ +#define HSE_RTC 3 + +static unsigned long clk_divider_rtc_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + if (clk_hw_get_parent(hw) == clk_hw_get_parent_by_index(hw, HSE_RTC)) + return clk_divider_ops.recalc_rate(hw, parent_rate); + + return parent_rate; +} + +static int clk_divider_rtc_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + if (clk_hw_get_parent(hw) == clk_hw_get_parent_by_index(hw, HSE_RTC)) + return clk_divider_ops.set_rate(hw, rate, parent_rate); + + return parent_rate; +} + +static int clk_divider_rtc_determine_rate(struct clk_hw *hw, struct clk_rate_request *req) +{ + unsigned long best_parent_rate = req->best_parent_rate; + + if (req->best_parent_hw == clk_hw_get_parent_by_index(hw, HSE_RTC)) { + req->rate = clk_divider_ops.round_rate(hw, req->rate, &best_parent_rate); + req->best_parent_rate = best_parent_rate; + } else { + req->rate = best_parent_rate; + } + + return 0; +} + +static const struct clk_ops rtc_div_clk_ops = { + .recalc_rate = clk_divider_rtc_recalc_rate, + .set_rate = clk_divider_rtc_set_rate, + .determine_rate = clk_divider_rtc_determine_rate +}; + struct stm32_pll_cfg { u32 offset; }; @@ -1243,6 +1284,10 @@ _clk_stm32_register_composite(struct device *dev, _STM32_DIV(_div_offset, _div_shift, _div_width,\ _div_flags, _div_table, NULL)\ +#define _DIV_RTC(_div_offset, _div_shift, _div_width, _div_flags, _div_table)\ + _STM32_DIV(_div_offset, _div_shift, _div_width,\ + _div_flags, _div_table, &rtc_div_clk_ops) + #define _STM32_MUX(_offset, _shift, _width, _mux_flags, _mmux, _ops)\ .mux = &(struct stm32_mux_cfg) {\ &(struct mux_cfg) {\ @@ -1965,13 +2010,10 @@ static const struct clock_config stm32mp1_clock_cfg[] = { _DIV(RCC_ETHCKSELR, 4, 4, 0, NULL)), /* RTC clock */ - DIV(NO_ID, "ck_hse_rtc", "ck_hse", 0, RCC_RTCDIVR, 0, 6, 0), - - COMPOSITE(RTC, "ck_rtc", rtc_src, CLK_OPS_PARENT_ENABLE | - CLK_SET_RATE_PARENT, + COMPOSITE(RTC, "ck_rtc", rtc_src, CLK_OPS_PARENT_ENABLE, _GATE(RCC_BDCR, 20, 0), _MUX(RCC_BDCR, 16, 2, 0), - _NO_DIV), + _DIV_RTC(RCC_RTCDIVR, 0, 6, 0, NULL)), /* MCO clocks */ COMPOSITE(CK_MCO1, "ck_mco1", mco1_src, CLK_OPS_PARENT_ENABLE | From 9008fddee4be8797b2e7ab1747348176079fed25 Mon Sep 17 00:00:00 2001 From: Gabriel Fernandez Date: Thu, 17 Jun 2021 07:18:06 +0200 Subject: [PATCH 114/161] clk: stm32mp1: remove intermediate pll clocks This patch is to prepare STM32MP1 clocks in trusted mode. Integrate the mux clock into pll clock will facilitate to have a more coherent clock tree in no trusted / trusted mode. Signed-off-by: Gabriel Fernandez Link: https://lore.kernel.org/r/20210617051814.12018-4-gabriel.fernandez@foss.st.com Signed-off-by: Stephen Boyd --- drivers/clk/clk-stm32mp1.c | 65 ++++++++++++++++++++++++-------------- 1 file changed, 42 insertions(+), 23 deletions(-) diff --git a/drivers/clk/clk-stm32mp1.c b/drivers/clk/clk-stm32mp1.c index a7c244fd0b03..24d99da07fc8 100644 --- a/drivers/clk/clk-stm32mp1.c +++ b/drivers/clk/clk-stm32mp1.c @@ -731,6 +731,7 @@ struct stm32_pll_obj { spinlock_t *lock; void __iomem *reg; struct clk_hw hw; + struct clk_mux mux; }; #define to_pll(_hw) container_of(_hw, struct stm32_pll_obj, hw) @@ -745,6 +746,8 @@ struct stm32_pll_obj { #define FRAC_MASK 0x1FFF #define FRAC_SHIFT 3 #define FRACLE BIT(16) +#define PLL_MUX_SHIFT 0 +#define PLL_MUX_MASK 3 static int __pll_is_enabled(struct clk_hw *hw) { @@ -856,16 +859,29 @@ static int pll_is_enabled(struct clk_hw *hw) return ret; } +static u8 pll_get_parent(struct clk_hw *hw) +{ + struct stm32_pll_obj *clk_elem = to_pll(hw); + struct clk_hw *mux_hw = &clk_elem->mux.hw; + + __clk_hw_set_clk(mux_hw, hw); + + return clk_mux_ops.get_parent(mux_hw); +} + static const struct clk_ops pll_ops = { .enable = pll_enable, .disable = pll_disable, .recalc_rate = pll_recalc_rate, .is_enabled = pll_is_enabled, + .get_parent = pll_get_parent, }; static struct clk_hw *clk_register_pll(struct device *dev, const char *name, - const char *parent_name, + const char * const *parent_names, + int num_parents, void __iomem *reg, + void __iomem *mux_reg, unsigned long flags, spinlock_t *lock) { @@ -881,8 +897,15 @@ static struct clk_hw *clk_register_pll(struct device *dev, const char *name, init.name = name; init.ops = &pll_ops; init.flags = flags; - init.parent_names = &parent_name; - init.num_parents = 1; + init.parent_names = parent_names; + init.num_parents = num_parents; + + element->mux.lock = lock; + element->mux.reg = mux_reg; + element->mux.shift = PLL_MUX_SHIFT; + element->mux.mask = PLL_MUX_MASK; + element->mux.flags = CLK_MUX_READ_ONLY; + element->mux.reg = mux_reg; element->hw.init = &init; element->reg = reg; @@ -1074,6 +1097,7 @@ static const struct clk_ops rtc_div_clk_ops = { struct stm32_pll_cfg { u32 offset; + u32 muxoff; }; static struct clk_hw *_clk_register_pll(struct device *dev, @@ -1083,8 +1107,11 @@ static struct clk_hw *_clk_register_pll(struct device *dev, { struct stm32_pll_cfg *stm_pll_cfg = cfg->cfg; - return clk_register_pll(dev, cfg->name, cfg->parent_name, - base + stm_pll_cfg->offset, cfg->flags, lock); + return clk_register_pll(dev, cfg->name, cfg->parent_names, + cfg->num_parents, + base + stm_pll_cfg->offset, + base + stm_pll_cfg->muxoff, + cfg->flags, lock); } struct stm32_cktim_cfg { @@ -1194,14 +1221,16 @@ _clk_stm32_register_composite(struct device *dev, .func = _clk_hw_register_mux,\ } -#define PLL(_id, _name, _parent, _flags, _offset)\ +#define PLL(_id, _name, _parents, _flags, _offset_p, _offset_mux)\ {\ .id = _id,\ .name = _name,\ - .parent_name = _parent,\ - .flags = _flags,\ + .parent_names = _parents,\ + .num_parents = ARRAY_SIZE(_parents),\ + .flags = CLK_IGNORE_UNUSED | (_flags),\ .cfg = &(struct stm32_pll_cfg) {\ - .offset = _offset,\ + .offset = _offset_p,\ + .muxoff = _offset_mux,\ },\ .func = _clk_register_pll,\ } @@ -1717,21 +1746,11 @@ static const struct clock_config stm32mp1_clock_cfg[] = { FIXED_FACTOR(CK_HSE_DIV2, "clk-hse-div2", "ck_hse", 0, 1, 2), - /* ref clock pll */ - MUX(NO_ID, "ref1", ref12_parents, CLK_OPS_PARENT_ENABLE, RCC_RCK12SELR, - 0, 2, CLK_MUX_READ_ONLY), - - MUX(NO_ID, "ref3", ref3_parents, CLK_OPS_PARENT_ENABLE, RCC_RCK3SELR, - 0, 2, CLK_MUX_READ_ONLY), - - MUX(NO_ID, "ref4", ref4_parents, CLK_OPS_PARENT_ENABLE, RCC_RCK4SELR, - 0, 2, CLK_MUX_READ_ONLY), - /* PLLs */ - PLL(PLL1, "pll1", "ref1", CLK_IGNORE_UNUSED, RCC_PLL1CR), - PLL(PLL2, "pll2", "ref1", CLK_IGNORE_UNUSED, RCC_PLL2CR), - PLL(PLL3, "pll3", "ref3", CLK_IGNORE_UNUSED, RCC_PLL3CR), - PLL(PLL4, "pll4", "ref4", CLK_IGNORE_UNUSED, RCC_PLL4CR), + PLL(PLL1, "pll1", ref12_parents, 0, RCC_PLL1CR, RCC_RCK12SELR), + PLL(PLL2, "pll2", ref12_parents, 0, RCC_PLL2CR, RCC_RCK12SELR), + PLL(PLL3, "pll3", ref3_parents, 0, RCC_PLL3CR, RCC_RCK3SELR), + PLL(PLL4, "pll4", ref4_parents, 0, RCC_PLL4CR, RCC_RCK4SELR), /* ODF */ COMPOSITE(PLL1_P, "pll1_p", PARENT("pll1"), 0, From 95272370e2905cbe30d29112101cd8fb8c4c5db6 Mon Sep 17 00:00:00 2001 From: Gabriel Fernandez Date: Thu, 17 Jun 2021 07:18:07 +0200 Subject: [PATCH 115/161] clk: stm32mp1: convert to module driver Adds support for probe deferral in way to prepare integration of the security in RCC clock and reset drivers. Some kernel clocks will be provided by the SCMI drivers. Since RCC clock driver create clocks which parents are SCMI clocks, RCC clock driver probe can be deferred. Signed-off-by: Etienne Carriere Signed-off-by: Gabriel Fernandez Link: https://lore.kernel.org/r/20210617051814.12018-5-gabriel.fernandez@foss.st.com Signed-off-by: Stephen Boyd --- drivers/clk/clk-stm32mp1.c | 121 ++++++++++++++++++++++++------------- 1 file changed, 78 insertions(+), 43 deletions(-) diff --git a/drivers/clk/clk-stm32mp1.c b/drivers/clk/clk-stm32mp1.c index 24d99da07fc8..e2e9331f1cba 100644 --- a/drivers/clk/clk-stm32mp1.c +++ b/drivers/clk/clk-stm32mp1.c @@ -10,8 +10,10 @@ #include #include #include +#include #include #include +#include #include #include @@ -469,7 +471,7 @@ static const struct clk_ops mp1_gate_clk_ops = { .is_enabled = clk_gate_is_enabled, }; -static struct clk_hw *_get_stm32_mux(void __iomem *base, +static struct clk_hw *_get_stm32_mux(struct device *dev, void __iomem *base, const struct stm32_mux_cfg *cfg, spinlock_t *lock) { @@ -478,7 +480,7 @@ static struct clk_hw *_get_stm32_mux(void __iomem *base, struct clk_hw *mux_hw; if (cfg->mmux) { - mmux = kzalloc(sizeof(*mmux), GFP_KERNEL); + mmux = devm_kzalloc(dev, sizeof(*mmux), GFP_KERNEL); if (!mmux) return ERR_PTR(-ENOMEM); @@ -493,7 +495,7 @@ static struct clk_hw *_get_stm32_mux(void __iomem *base, cfg->mmux->hws[cfg->mmux->nbr_clk++] = mux_hw; } else { - mux = kzalloc(sizeof(*mux), GFP_KERNEL); + mux = devm_kzalloc(dev, sizeof(*mux), GFP_KERNEL); if (!mux) return ERR_PTR(-ENOMEM); @@ -509,13 +511,13 @@ static struct clk_hw *_get_stm32_mux(void __iomem *base, return mux_hw; } -static struct clk_hw *_get_stm32_div(void __iomem *base, +static struct clk_hw *_get_stm32_div(struct device *dev, void __iomem *base, const struct stm32_div_cfg *cfg, spinlock_t *lock) { struct clk_divider *div; - div = kzalloc(sizeof(*div), GFP_KERNEL); + div = devm_kzalloc(dev, sizeof(*div), GFP_KERNEL); if (!div) return ERR_PTR(-ENOMEM); @@ -530,16 +532,16 @@ static struct clk_hw *_get_stm32_div(void __iomem *base, return &div->hw; } -static struct clk_hw * -_get_stm32_gate(void __iomem *base, - const struct stm32_gate_cfg *cfg, spinlock_t *lock) +static struct clk_hw *_get_stm32_gate(struct device *dev, void __iomem *base, + const struct stm32_gate_cfg *cfg, + spinlock_t *lock) { struct stm32_clk_mgate *mgate; struct clk_gate *gate; struct clk_hw *gate_hw; if (cfg->mgate) { - mgate = kzalloc(sizeof(*mgate), GFP_KERNEL); + mgate = devm_kzalloc(dev, sizeof(*mgate), GFP_KERNEL); if (!mgate) return ERR_PTR(-ENOMEM); @@ -554,7 +556,7 @@ _get_stm32_gate(void __iomem *base, gate_hw = &mgate->gate.hw; } else { - gate = kzalloc(sizeof(*gate), GFP_KERNEL); + gate = devm_kzalloc(dev, sizeof(*gate), GFP_KERNEL); if (!gate) return ERR_PTR(-ENOMEM); @@ -592,7 +594,7 @@ clk_stm32_register_gate_ops(struct device *dev, if (cfg->ops) init.ops = cfg->ops; - hw = _get_stm32_gate(base, cfg, lock); + hw = _get_stm32_gate(dev, base, cfg, lock); if (IS_ERR(hw)) return ERR_PTR(-ENOMEM); @@ -623,7 +625,7 @@ clk_stm32_register_composite(struct device *dev, gate_ops = NULL; if (cfg->mux) { - mux_hw = _get_stm32_mux(base, cfg->mux, lock); + mux_hw = _get_stm32_mux(dev, base, cfg->mux, lock); if (!IS_ERR(mux_hw)) { mux_ops = &clk_mux_ops; @@ -634,7 +636,7 @@ clk_stm32_register_composite(struct device *dev, } if (cfg->div) { - div_hw = _get_stm32_div(base, cfg->div, lock); + div_hw = _get_stm32_div(dev, base, cfg->div, lock); if (!IS_ERR(div_hw)) { div_ops = &clk_divider_ops; @@ -645,7 +647,7 @@ clk_stm32_register_composite(struct device *dev, } if (cfg->gate) { - gate_hw = _get_stm32_gate(base, cfg->gate, lock); + gate_hw = _get_stm32_gate(dev, base, cfg->gate, lock); if (!IS_ERR(gate_hw)) { gate_ops = &clk_gate_ops; @@ -890,7 +892,7 @@ static struct clk_hw *clk_register_pll(struct device *dev, const char *name, struct clk_hw *hw; int err; - element = kzalloc(sizeof(*element), GFP_KERNEL); + element = devm_kzalloc(dev, sizeof(*element), GFP_KERNEL); if (!element) return ERR_PTR(-ENOMEM); @@ -914,10 +916,8 @@ static struct clk_hw *clk_register_pll(struct device *dev, const char *name, hw = &element->hw; err = clk_hw_register(dev, hw); - if (err) { - kfree(element); + if (err) return ERR_PTR(err); - } return hw; } @@ -1028,7 +1028,7 @@ static struct clk_hw *clk_register_cktim(struct device *dev, const char *name, struct clk_hw *hw; int err; - tim_ker = kzalloc(sizeof(*tim_ker), GFP_KERNEL); + tim_ker = devm_kzalloc(dev, sizeof(*tim_ker), GFP_KERNEL); if (!tim_ker) return ERR_PTR(-ENOMEM); @@ -1046,10 +1046,8 @@ static struct clk_hw *clk_register_cktim(struct device *dev, const char *name, hw = &tim_ker->hw; err = clk_hw_register(dev, hw); - if (err) { - kfree(tim_ker); + if (err) return ERR_PTR(err); - } return hw; } @@ -2076,6 +2074,7 @@ static const struct of_device_id stm32mp1_match_data[] = { }, { } }; +MODULE_DEVICE_TABLE(of, stm32mp1_match_data); static int stm32_register_hw_clk(struct device *dev, struct clk_hw_onecell_data *clk_data, @@ -2101,8 +2100,7 @@ static int stm32_register_hw_clk(struct device *dev, return 0; } -static int stm32_rcc_init(struct device_node *np, - void __iomem *base, +static int stm32_rcc_init(struct device *dev, void __iomem *base, const struct of_device_id *match_data) { struct clk_hw_onecell_data *clk_data; @@ -2111,9 +2109,9 @@ static int stm32_rcc_init(struct device_node *np, const struct stm32_clock_match_data *data; int err, n, max_binding; - match = of_match_node(match_data, np); + match = of_match_node(match_data, dev_of_node(dev)); if (!match) { - pr_err("%s: match data not found\n", __func__); + dev_err(dev, "match data not found\n"); return -ENODEV; } @@ -2121,8 +2119,8 @@ static int stm32_rcc_init(struct device_node *np, max_binding = data->maxbinding; - clk_data = kzalloc(struct_size(clk_data, hws, max_binding), - GFP_KERNEL); + clk_data = devm_kzalloc(dev, struct_size(clk_data, hws, max_binding), + GFP_KERNEL); if (!clk_data) return -ENOMEM; @@ -2134,36 +2132,73 @@ static int stm32_rcc_init(struct device_node *np, hws[n] = ERR_PTR(-ENOENT); for (n = 0; n < data->num; n++) { - err = stm32_register_hw_clk(NULL, clk_data, base, &rlock, + err = stm32_register_hw_clk(dev, clk_data, base, &rlock, &data->cfg[n]); if (err) { - pr_err("%s: can't register %s\n", __func__, - data->cfg[n].name); - - kfree(clk_data); + dev_err(dev, "Can't register clk %s: %d\n", + data->cfg[n].name, err); return err; } } - return of_clk_add_hw_provider(np, of_clk_hw_onecell_get, clk_data); + return of_clk_add_hw_provider(dev_of_node(dev), of_clk_hw_onecell_get, clk_data); } -static void stm32mp1_rcc_init(struct device_node *np) +static int stm32mp1_rcc_init(struct device *dev) { void __iomem *base; + int ret; - base = of_iomap(np, 0); + base = of_iomap(dev_of_node(dev), 0); if (!base) { - pr_err("%pOFn: unable to map resource", np); - of_node_put(np); - return; + pr_err("%pOFn: unable to map resource", dev_of_node(dev)); + ret = -ENOMEM; + goto out; } - if (stm32_rcc_init(np, base, stm32mp1_match_data)) { - iounmap(base); - of_node_put(np); + ret = stm32_rcc_init(dev, base, stm32mp1_match_data); + +out: + if (ret) { + if (base) + iounmap(base); + + of_node_put(dev_of_node(dev)); } + + return ret; } -CLK_OF_DECLARE_DRIVER(stm32mp1_rcc, "st,stm32mp1-rcc", stm32mp1_rcc_init); +static int stm32mp1_rcc_clocks_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + + return stm32mp1_rcc_init(dev); +} + +static int stm32mp1_rcc_clocks_remove(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct device_node *child, *np = dev_of_node(dev); + + for_each_available_child_of_node(np, child) + of_clk_del_provider(child); + + return 0; +} + +static struct platform_driver stm32mp1_rcc_clocks_driver = { + .driver = { + .name = "stm32mp1_rcc", + .of_match_table = stm32mp1_match_data, + }, + .probe = stm32mp1_rcc_clocks_probe, + .remove = stm32mp1_rcc_clocks_remove, +}; + +static int __init stm32mp1_clocks_init(void) +{ + return platform_driver_register(&stm32mp1_rcc_clocks_driver); +} +core_initcall(stm32mp1_clocks_init); From c392df194a2d126124128c9ce2109b27e3c43077 Mon Sep 17 00:00:00 2001 From: Gabriel Fernandez Date: Thu, 17 Jun 2021 07:18:08 +0200 Subject: [PATCH 116/161] clk: stm32mp1: move RCC reset controller into RCC clock driver RCC clock and reset controller shared same memory mapping. As RCC clock driver is now a module, the best way to register clock and reset controller is to do it in same driver. Signed-off-by: Gabriel Fernandez Link: https://lore.kernel.org/r/20210617051814.12018-6-gabriel.fernandez@foss.st.com Signed-off-by: Stephen Boyd --- drivers/clk/clk-stm32mp1.c | 159 +++++++++++++++++++++++++++++++++---- 1 file changed, 145 insertions(+), 14 deletions(-) diff --git a/drivers/clk/clk-stm32mp1.c b/drivers/clk/clk-stm32mp1.c index e2e9331f1cba..6d3a36f81b2d 100644 --- a/drivers/clk/clk-stm32mp1.c +++ b/drivers/clk/clk-stm32mp1.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -2055,16 +2056,18 @@ static const struct clock_config stm32mp1_clock_cfg[] = { _DIV(RCC_DBGCFGR, 0, 3, 0, ck_trace_div_table)), }; -struct stm32_clock_match_data { +struct stm32_rcc_match_data { const struct clock_config *cfg; unsigned int num; unsigned int maxbinding; + u32 clear_offset; }; -static struct stm32_clock_match_data stm32mp1_data = { +static struct stm32_rcc_match_data stm32mp1_data = { .cfg = stm32mp1_clock_cfg, .num = ARRAY_SIZE(stm32mp1_clock_cfg), .maxbinding = STM32MP1_LAST_CLK, + .clear_offset = RCC_CLR, }; static const struct of_device_id stm32mp1_match_data[] = { @@ -2100,23 +2103,122 @@ static int stm32_register_hw_clk(struct device *dev, return 0; } -static int stm32_rcc_init(struct device *dev, void __iomem *base, - const struct of_device_id *match_data) -{ - struct clk_hw_onecell_data *clk_data; - struct clk_hw **hws; - const struct of_device_id *match; - const struct stm32_clock_match_data *data; - int err, n, max_binding; +#define STM32_RESET_ID_MASK GENMASK(15, 0) - match = of_match_node(match_data, dev_of_node(dev)); - if (!match) { - dev_err(dev, "match data not found\n"); - return -ENODEV; +struct stm32_reset_data { + /* reset lock */ + spinlock_t lock; + struct reset_controller_dev rcdev; + void __iomem *membase; + u32 clear_offset; +}; + +static inline struct stm32_reset_data * +to_stm32_reset_data(struct reset_controller_dev *rcdev) +{ + return container_of(rcdev, struct stm32_reset_data, rcdev); +} + +static int stm32_reset_update(struct reset_controller_dev *rcdev, + unsigned long id, bool assert) +{ + struct stm32_reset_data *data = to_stm32_reset_data(rcdev); + int reg_width = sizeof(u32); + int bank = id / (reg_width * BITS_PER_BYTE); + int offset = id % (reg_width * BITS_PER_BYTE); + + if (data->clear_offset) { + void __iomem *addr; + + addr = data->membase + (bank * reg_width); + if (!assert) + addr += data->clear_offset; + + writel(BIT(offset), addr); + + } else { + unsigned long flags; + u32 reg; + + spin_lock_irqsave(&data->lock, flags); + + reg = readl(data->membase + (bank * reg_width)); + + if (assert) + reg |= BIT(offset); + else + reg &= ~BIT(offset); + + writel(reg, data->membase + (bank * reg_width)); + + spin_unlock_irqrestore(&data->lock, flags); } + return 0; +} + +static int stm32_reset_assert(struct reset_controller_dev *rcdev, + unsigned long id) +{ + return stm32_reset_update(rcdev, id, true); +} + +static int stm32_reset_deassert(struct reset_controller_dev *rcdev, + unsigned long id) +{ + return stm32_reset_update(rcdev, id, false); +} + +static int stm32_reset_status(struct reset_controller_dev *rcdev, + unsigned long id) +{ + struct stm32_reset_data *data = to_stm32_reset_data(rcdev); + int reg_width = sizeof(u32); + int bank = id / (reg_width * BITS_PER_BYTE); + int offset = id % (reg_width * BITS_PER_BYTE); + u32 reg; + + reg = readl(data->membase + (bank * reg_width)); + + return !!(reg & BIT(offset)); +} + +static const struct reset_control_ops stm32_reset_ops = { + .assert = stm32_reset_assert, + .deassert = stm32_reset_deassert, + .status = stm32_reset_status, +}; + +static int stm32_rcc_reset_init(struct device *dev, void __iomem *base, + const struct of_device_id *match) +{ + const struct stm32_rcc_match_data *data = match->data; + struct stm32_reset_data *reset_data = NULL; + data = match->data; + reset_data = kzalloc(sizeof(*reset_data), GFP_KERNEL); + if (!reset_data) + return -ENOMEM; + + reset_data->membase = base; + reset_data->rcdev.owner = THIS_MODULE; + reset_data->rcdev.ops = &stm32_reset_ops; + reset_data->rcdev.of_node = dev_of_node(dev); + reset_data->rcdev.nr_resets = STM32_RESET_ID_MASK; + reset_data->clear_offset = data->clear_offset; + + return reset_controller_register(&reset_data->rcdev); +} + +static int stm32_rcc_clock_init(struct device *dev, void __iomem *base, + const struct of_device_id *match) +{ + const struct stm32_rcc_match_data *data = match->data; + struct clk_hw_onecell_data *clk_data; + struct clk_hw **hws; + int err, n, max_binding; + max_binding = data->maxbinding; clk_data = devm_kzalloc(dev, struct_size(clk_data, hws, max_binding), @@ -2145,6 +2247,35 @@ static int stm32_rcc_init(struct device *dev, void __iomem *base, return of_clk_add_hw_provider(dev_of_node(dev), of_clk_hw_onecell_get, clk_data); } +static int stm32_rcc_init(struct device *dev, void __iomem *base, + const struct of_device_id *match_data) +{ + const struct of_device_id *match; + int err; + + match = of_match_node(match_data, dev_of_node(dev)); + if (!match) { + dev_err(dev, "match data not found\n"); + return -ENODEV; + } + + /* RCC Reset Configuration */ + err = stm32_rcc_reset_init(dev, base, match); + if (err) { + pr_err("stm32mp1 reset failed to initialize\n"); + return err; + } + + /* RCC Clock Configuration */ + err = stm32_rcc_clock_init(dev, base, match); + if (err) { + pr_err("stm32mp1 clock failed to initialize\n"); + return err; + } + + return 0; +} + static int stm32mp1_rcc_init(struct device *dev) { void __iomem *base; From fa5b6541423e7e1fb5deeacc36abea9163d23720 Mon Sep 17 00:00:00 2001 From: Matti Vaittinen Date: Tue, 25 May 2021 13:15:10 +0300 Subject: [PATCH 117/161] clk: bd718xx: Drop BD70528 support The only known BD70528 use-cases are such that the PMIC is controlled from separate MCU which is not running Linux. I am not aware of any Linux driver users. Furthermore, it seems there is no demand for this IC. Let's ease the maintenance burden and drop the driver. We can always add it back if there is sudden need for it. Signed-off-by: Matti Vaittinen Link: https://lore.kernel.org/r/937ed0828486a08e2d00bce2815d491c1c9c49b4.1621937490.git.matti.vaittinen@fi.rohmeurope.com Signed-off-by: Stephen Boyd --- drivers/clk/Kconfig | 6 +++--- drivers/clk/clk-bd718x7.c | 11 ++--------- 2 files changed, 5 insertions(+), 12 deletions(-) diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index e80918be8e9c..84983cd6029c 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig @@ -358,10 +358,10 @@ config COMMON_CLK_MMP2_AUDIO config COMMON_CLK_BD718XX tristate "Clock driver for 32K clk gates on ROHM PMICs" - depends on MFD_ROHM_BD718XX || MFD_ROHM_BD70528 || MFD_ROHM_BD71828 + depends on MFD_ROHM_BD718XX || MFD_ROHM_BD71828 help - This driver supports ROHM BD71837, ROHM BD71847, ROHM BD71828 and - ROHM BD70528 PMICs clock gates. + This driver supports ROHM BD71837, BD71847, BD71850, BD71815 + and BD71828 PMICs clock gates. config COMMON_CLK_FIXED_MMIO bool "Clock driver for Memory Mapped Fixed values" diff --git a/drivers/clk/clk-bd718x7.c b/drivers/clk/clk-bd718x7.c index d9e70e506d18..ac40b669d60b 100644 --- a/drivers/clk/clk-bd718x7.c +++ b/drivers/clk/clk-bd718x7.c @@ -15,15 +15,13 @@ /* clk control registers */ /* BD71815 */ #define BD71815_REG_OUT32K 0x1d -/* BD70528 */ -#define BD70528_REG_OUT32K 0x2c /* BD71828 */ #define BD71828_REG_OUT32K 0x4B /* BD71837 and BD71847 */ #define BD718XX_REG_OUT32K 0x2E /* - * BD71837, BD71847, BD70528 and BD71828 all use bit [0] to clk output control + * BD71837, BD71847, and BD71828 all use bit [0] to clk output control */ #define CLK_OUT_EN_MASK BIT(0) @@ -116,10 +114,6 @@ static int bd71837_clk_probe(struct platform_device *pdev) c->reg = BD71828_REG_OUT32K; c->mask = CLK_OUT_EN_MASK; break; - case ROHM_CHIP_TYPE_BD70528: - c->reg = BD70528_REG_OUT32K; - c->mask = CLK_OUT_EN_MASK; - break; case ROHM_CHIP_TYPE_BD71815: c->reg = BD71815_REG_OUT32K; c->mask = CLK_OUT_EN_MASK; @@ -150,7 +144,6 @@ static int bd71837_clk_probe(struct platform_device *pdev) static const struct platform_device_id bd718x7_clk_id[] = { { "bd71837-clk", ROHM_CHIP_TYPE_BD71837 }, { "bd71847-clk", ROHM_CHIP_TYPE_BD71847 }, - { "bd70528-clk", ROHM_CHIP_TYPE_BD70528 }, { "bd71828-clk", ROHM_CHIP_TYPE_BD71828 }, { "bd71815-clk", ROHM_CHIP_TYPE_BD71815 }, { }, @@ -168,6 +161,6 @@ static struct platform_driver bd71837_clk = { module_platform_driver(bd71837_clk); MODULE_AUTHOR("Matti Vaittinen "); -MODULE_DESCRIPTION("BD718(15/18/28/37/47/50) and BD70528 chip clk driver"); +MODULE_DESCRIPTION("BD718(15/18/28/37/47/50) and chip clk driver"); MODULE_LICENSE("GPL"); MODULE_ALIAS("platform:bd718xx-clk"); From 2dca2a619a907579e3e65e7c1789230c2b912e88 Mon Sep 17 00:00:00 2001 From: Cristian Ciocaltea Date: Thu, 10 Jun 2021 23:05:21 +0300 Subject: [PATCH 118/161] clk: actions: Fix UART clock dividers on Owl S500 SoC Use correct divider registers for the Actions Semi Owl S500 SoC's UART clocks. Fixes: ed6b4795ece4 ("clk: actions: Add clock driver for S500 SoC") Signed-off-by: Cristian Ciocaltea Reviewed-by: Manivannan Sadhasivam Link: https://lore.kernel.org/r/4714d05982b19ac5fec2ed74f54be42d8238e392.1623354574.git.cristian.ciocaltea@gmail.com Signed-off-by: Stephen Boyd --- drivers/clk/actions/owl-s500.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/clk/actions/owl-s500.c b/drivers/clk/actions/owl-s500.c index 61bb224f6330..75b7186185b0 100644 --- a/drivers/clk/actions/owl-s500.c +++ b/drivers/clk/actions/owl-s500.c @@ -305,7 +305,7 @@ static OWL_COMP_FIXED_FACTOR(i2c3_clk, "i2c3_clk", "ethernet_pll_clk", static OWL_COMP_DIV(uart0_clk, "uart0_clk", uart_clk_mux_p, OWL_MUX_HW(CMU_UART0CLK, 16, 1), OWL_GATE_HW(CMU_DEVCLKEN1, 6, 0), - OWL_DIVIDER_HW(CMU_UART1CLK, 0, 8, CLK_DIVIDER_ROUND_CLOSEST, NULL), + OWL_DIVIDER_HW(CMU_UART0CLK, 0, 8, CLK_DIVIDER_ROUND_CLOSEST, NULL), CLK_IGNORE_UNUSED); static OWL_COMP_DIV(uart1_clk, "uart1_clk", uart_clk_mux_p, @@ -317,31 +317,31 @@ static OWL_COMP_DIV(uart1_clk, "uart1_clk", uart_clk_mux_p, static OWL_COMP_DIV(uart2_clk, "uart2_clk", uart_clk_mux_p, OWL_MUX_HW(CMU_UART2CLK, 16, 1), OWL_GATE_HW(CMU_DEVCLKEN1, 8, 0), - OWL_DIVIDER_HW(CMU_UART1CLK, 0, 8, CLK_DIVIDER_ROUND_CLOSEST, NULL), + OWL_DIVIDER_HW(CMU_UART2CLK, 0, 8, CLK_DIVIDER_ROUND_CLOSEST, NULL), CLK_IGNORE_UNUSED); static OWL_COMP_DIV(uart3_clk, "uart3_clk", uart_clk_mux_p, OWL_MUX_HW(CMU_UART3CLK, 16, 1), OWL_GATE_HW(CMU_DEVCLKEN1, 19, 0), - OWL_DIVIDER_HW(CMU_UART1CLK, 0, 8, CLK_DIVIDER_ROUND_CLOSEST, NULL), + OWL_DIVIDER_HW(CMU_UART3CLK, 0, 8, CLK_DIVIDER_ROUND_CLOSEST, NULL), CLK_IGNORE_UNUSED); static OWL_COMP_DIV(uart4_clk, "uart4_clk", uart_clk_mux_p, OWL_MUX_HW(CMU_UART4CLK, 16, 1), OWL_GATE_HW(CMU_DEVCLKEN1, 20, 0), - OWL_DIVIDER_HW(CMU_UART1CLK, 0, 8, CLK_DIVIDER_ROUND_CLOSEST, NULL), + OWL_DIVIDER_HW(CMU_UART4CLK, 0, 8, CLK_DIVIDER_ROUND_CLOSEST, NULL), CLK_IGNORE_UNUSED); static OWL_COMP_DIV(uart5_clk, "uart5_clk", uart_clk_mux_p, OWL_MUX_HW(CMU_UART5CLK, 16, 1), OWL_GATE_HW(CMU_DEVCLKEN1, 21, 0), - OWL_DIVIDER_HW(CMU_UART1CLK, 0, 8, CLK_DIVIDER_ROUND_CLOSEST, NULL), + OWL_DIVIDER_HW(CMU_UART5CLK, 0, 8, CLK_DIVIDER_ROUND_CLOSEST, NULL), CLK_IGNORE_UNUSED); static OWL_COMP_DIV(uart6_clk, "uart6_clk", uart_clk_mux_p, OWL_MUX_HW(CMU_UART6CLK, 16, 1), OWL_GATE_HW(CMU_DEVCLKEN1, 18, 0), - OWL_DIVIDER_HW(CMU_UART1CLK, 0, 8, CLK_DIVIDER_ROUND_CLOSEST, NULL), + OWL_DIVIDER_HW(CMU_UART6CLK, 0, 8, CLK_DIVIDER_ROUND_CLOSEST, NULL), CLK_IGNORE_UNUSED); static OWL_COMP_DIV(i2srx_clk, "i2srx_clk", i2s_clk_mux_p, From fe1f71e338d77814da3ef44e9f64d32981a6ccdf Mon Sep 17 00:00:00 2001 From: Cristian Ciocaltea Date: Thu, 10 Jun 2021 23:05:22 +0300 Subject: [PATCH 119/161] clk: actions: Fix SD clocks factor table on Owl S500 SoC Drop the unsupported entries in the factor table used for the SD[0-2] clocks definitions on the Actions Semi Owl S500 SoC. Fixes: ed6b4795ece4 ("clk: actions: Add clock driver for S500 SoC") Signed-off-by: Cristian Ciocaltea Reviewed-by: Manivannan Sadhasivam Link: https://lore.kernel.org/r/196c948d708a22b8198c95f064a0f6b6820f9980.1623354574.git.cristian.ciocaltea@gmail.com Signed-off-by: Stephen Boyd --- drivers/clk/actions/owl-s500.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/clk/actions/owl-s500.c b/drivers/clk/actions/owl-s500.c index 75b7186185b0..42abdf964044 100644 --- a/drivers/clk/actions/owl-s500.c +++ b/drivers/clk/actions/owl-s500.c @@ -127,8 +127,7 @@ static struct clk_factor_table sd_factor_table[] = { { 12, 1, 13 }, { 13, 1, 14 }, { 14, 1, 15 }, { 15, 1, 16 }, { 16, 1, 17 }, { 17, 1, 18 }, { 18, 1, 19 }, { 19, 1, 20 }, { 20, 1, 21 }, { 21, 1, 22 }, { 22, 1, 23 }, { 23, 1, 24 }, - { 24, 1, 25 }, { 25, 1, 26 }, { 26, 1, 27 }, { 27, 1, 28 }, - { 28, 1, 29 }, { 29, 1, 30 }, { 30, 1, 31 }, { 31, 1, 32 }, + { 24, 1, 25 }, /* bit8: /128 */ { 256, 1, 1 * 128 }, { 257, 1, 2 * 128 }, { 258, 1, 3 * 128 }, { 259, 1, 4 * 128 }, @@ -137,8 +136,7 @@ static struct clk_factor_table sd_factor_table[] = { { 268, 1, 13 * 128 }, { 269, 1, 14 * 128 }, { 270, 1, 15 * 128 }, { 271, 1, 16 * 128 }, { 272, 1, 17 * 128 }, { 273, 1, 18 * 128 }, { 274, 1, 19 * 128 }, { 275, 1, 20 * 128 }, { 276, 1, 21 * 128 }, { 277, 1, 22 * 128 }, { 278, 1, 23 * 128 }, { 279, 1, 24 * 128 }, - { 280, 1, 25 * 128 }, { 281, 1, 26 * 128 }, { 282, 1, 27 * 128 }, { 283, 1, 28 * 128 }, - { 284, 1, 29 * 128 }, { 285, 1, 30 * 128 }, { 286, 1, 31 * 128 }, { 287, 1, 32 * 128 }, + { 280, 1, 25 * 128 }, { 0, 0, 0 }, }; From a8f1f03caa51aa7a69c671aa87c475034db7d368 Mon Sep 17 00:00:00 2001 From: Cristian Ciocaltea Date: Thu, 10 Jun 2021 23:05:23 +0300 Subject: [PATCH 120/161] clk: actions: Fix bisp_factor_table based clocks on Owl S500 SoC The following clocks of the Actions Semi Owl S500 SoC have been defined to use a shared clock factor table 'bisp_factor_table[]': DE[1-2], VCE, VDE, BISP, SENSOR[0-1] There are several issues involved in this approach: * 'bisp_factor_table[]' describes the configuration of a regular 8-rates divider, so its usage is redundant. Additionally, judging by the BISP clock context, it is incomplete since it maps only 8 out of 12 possible entries. * The clocks mentioned above are not identical in terms of the available rates, therefore cannot rely on the same factor table. Specifically, BISP and SENSOR* are standard 12-rate dividers so their configuration should rely on a proper clock div table, while VCE and VDE require a factor table that is a actually a subset of the one needed for DE[1-2] clocks. Let's fix this by implementing the following: * Add new factor tables 'de_factor_table' and 'hde_factor_table' to properly handle DE[1-2], VCE and VDE clocks. * Add a common div table 'std12rate_div_table' for BISP and SENSOR[0-1] clocks converted to OWL_COMP_DIV. * Drop the now unused 'bisp_factor_table[]'. Additionally, drop the CLK_IGNORE_UNUSED flag for SENSOR[0-1] since there is no reason to always keep ON those clocks. Fixes: ed6b4795ece4 ("clk: actions: Add clock driver for S500 SoC") Signed-off-by: Cristian Ciocaltea Reviewed-by: Manivannan Sadhasivam Link: https://lore.kernel.org/r/e675820a46cd9930d8d576c6cae61d41c1a8416f.1623354574.git.cristian.ciocaltea@gmail.com Signed-off-by: Stephen Boyd --- drivers/clk/actions/owl-s500.c | 44 ++++++++++++++++++++++------------ 1 file changed, 29 insertions(+), 15 deletions(-) diff --git a/drivers/clk/actions/owl-s500.c b/drivers/clk/actions/owl-s500.c index 42abdf964044..42d6899755e6 100644 --- a/drivers/clk/actions/owl-s500.c +++ b/drivers/clk/actions/owl-s500.c @@ -140,9 +140,16 @@ static struct clk_factor_table sd_factor_table[] = { { 0, 0, 0 }, }; -static struct clk_factor_table bisp_factor_table[] = { - { 0, 1, 1 }, { 1, 1, 2 }, { 2, 1, 3 }, { 3, 1, 4 }, - { 4, 1, 5 }, { 5, 1, 6 }, { 6, 1, 7 }, { 7, 1, 8 }, +static struct clk_factor_table de_factor_table[] = { + { 0, 1, 1 }, { 1, 2, 3 }, { 2, 1, 2 }, { 3, 2, 5 }, + { 4, 1, 3 }, { 5, 1, 4 }, { 6, 1, 6 }, { 7, 1, 8 }, + { 8, 1, 12 }, + { 0, 0, 0 }, +}; + +static struct clk_factor_table hde_factor_table[] = { + { 0, 1, 1 }, { 1, 2, 3 }, { 2, 1, 2 }, { 3, 2, 5 }, + { 4, 1, 3 }, { 5, 1, 4 }, { 6, 1, 6 }, { 7, 1, 8 }, { 0, 0, 0 }, }; @@ -156,6 +163,13 @@ static struct clk_div_table rmii_ref_div_table[] = { { 0, 0 }, }; +static struct clk_div_table std12rate_div_table[] = { + { 0, 1 }, { 1, 2 }, { 2, 3 }, { 3, 4 }, + { 4, 5 }, { 5, 6 }, { 6, 7 }, { 7, 8 }, + { 8, 9 }, { 9, 10 }, { 10, 11 }, { 11, 12 }, + { 0, 0 }, +}; + static struct clk_div_table i2s_div_table[] = { { 0, 1 }, { 1, 2 }, { 2, 3 }, { 3, 4 }, { 4, 6 }, { 5, 8 }, { 6, 12 }, { 7, 16 }, @@ -191,39 +205,39 @@ static OWL_DIVIDER(rmii_ref_clk, "rmii_ref_clk", "ethernet_pll_clk", CMU_ETHERNE /* factor clocks */ static OWL_FACTOR(ahb_clk, "ahb_clk", "h_clk", CMU_BUSCLK1, 2, 2, ahb_factor_table, 0, 0); -static OWL_FACTOR(de1_clk, "de_clk1", "de_clk", CMU_DECLK, 0, 3, bisp_factor_table, 0, 0); -static OWL_FACTOR(de2_clk, "de_clk2", "de_clk", CMU_DECLK, 4, 3, bisp_factor_table, 0, 0); +static OWL_FACTOR(de1_clk, "de_clk1", "de_clk", CMU_DECLK, 0, 4, de_factor_table, 0, 0); +static OWL_FACTOR(de2_clk, "de_clk2", "de_clk", CMU_DECLK, 4, 4, de_factor_table, 0, 0); /* composite clocks */ static OWL_COMP_FACTOR(vce_clk, "vce_clk", hde_clk_mux_p, OWL_MUX_HW(CMU_VCECLK, 4, 2), OWL_GATE_HW(CMU_DEVCLKEN0, 26, 0), - OWL_FACTOR_HW(CMU_VCECLK, 0, 3, 0, bisp_factor_table), + OWL_FACTOR_HW(CMU_VCECLK, 0, 3, 0, hde_factor_table), 0); static OWL_COMP_FACTOR(vde_clk, "vde_clk", hde_clk_mux_p, OWL_MUX_HW(CMU_VDECLK, 4, 2), OWL_GATE_HW(CMU_DEVCLKEN0, 25, 0), - OWL_FACTOR_HW(CMU_VDECLK, 0, 3, 0, bisp_factor_table), + OWL_FACTOR_HW(CMU_VDECLK, 0, 3, 0, hde_factor_table), 0); -static OWL_COMP_FACTOR(bisp_clk, "bisp_clk", bisp_clk_mux_p, +static OWL_COMP_DIV(bisp_clk, "bisp_clk", bisp_clk_mux_p, OWL_MUX_HW(CMU_BISPCLK, 4, 1), OWL_GATE_HW(CMU_DEVCLKEN0, 14, 0), - OWL_FACTOR_HW(CMU_BISPCLK, 0, 3, 0, bisp_factor_table), + OWL_DIVIDER_HW(CMU_BISPCLK, 0, 4, 0, std12rate_div_table), 0); -static OWL_COMP_FACTOR(sensor0_clk, "sensor0_clk", sensor_clk_mux_p, +static OWL_COMP_DIV(sensor0_clk, "sensor0_clk", sensor_clk_mux_p, OWL_MUX_HW(CMU_SENSORCLK, 4, 1), OWL_GATE_HW(CMU_DEVCLKEN0, 14, 0), - OWL_FACTOR_HW(CMU_SENSORCLK, 0, 3, 0, bisp_factor_table), - CLK_IGNORE_UNUSED); + OWL_DIVIDER_HW(CMU_SENSORCLK, 0, 4, 0, std12rate_div_table), + 0); -static OWL_COMP_FACTOR(sensor1_clk, "sensor1_clk", sensor_clk_mux_p, +static OWL_COMP_DIV(sensor1_clk, "sensor1_clk", sensor_clk_mux_p, OWL_MUX_HW(CMU_SENSORCLK, 4, 1), OWL_GATE_HW(CMU_DEVCLKEN0, 14, 0), - OWL_FACTOR_HW(CMU_SENSORCLK, 8, 3, 0, bisp_factor_table), - CLK_IGNORE_UNUSED); + OWL_DIVIDER_HW(CMU_SENSORCLK, 8, 4, 0, std12rate_div_table), + 0); static OWL_COMP_FACTOR(sd0_clk, "sd0_clk", sd_clk_mux_p, OWL_MUX_HW(CMU_SD0CLK, 9, 1), From fd90b5b9045274360b12cea0f2ce50f3bcfb25cc Mon Sep 17 00:00:00 2001 From: Cristian Ciocaltea Date: Thu, 10 Jun 2021 23:05:24 +0300 Subject: [PATCH 121/161] clk: actions: Fix AHPPREDIV-H-AHB clock chain on Owl S500 SoC There are a few issues with the setup of the Actions Semi Owl S500 SoC's clock chain involving AHPPREDIV, H and AHB clocks: * AHBPREDIV clock is defined as a muxer only, although it also acts as a divider. * H clock is using a wrong divider register offset * AHB is defined as a multi-rate factor clock, but it is actually just a fixed pass clock. Let's provide the following fixes: * Change AHBPREDIV clock to an ungated OWL_COMP_DIV definition. * Use the correct register shift value in the OWL_DIVIDER definition for H clock * Drop the unneeded 'ahb_factor_table[]' and change AHB clock to an ungated OWL_COMP_FIXED_FACTOR definition. Fixes: ed6b4795ece4 ("clk: actions: Add clock driver for S500 SoC") Signed-off-by: Cristian Ciocaltea Link: https://lore.kernel.org/r/21c1abd19a7089b65a34852ac6513961be88cbe1.1623354574.git.cristian.ciocaltea@gmail.com Reviewed-by: Manivannan Sadhasivam Signed-off-by: Stephen Boyd --- drivers/clk/actions/owl-s500.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/drivers/clk/actions/owl-s500.c b/drivers/clk/actions/owl-s500.c index 42d6899755e6..cbeb51c804eb 100644 --- a/drivers/clk/actions/owl-s500.c +++ b/drivers/clk/actions/owl-s500.c @@ -153,11 +153,6 @@ static struct clk_factor_table hde_factor_table[] = { { 0, 0, 0 }, }; -static struct clk_factor_table ahb_factor_table[] = { - { 1, 1, 2 }, { 2, 1, 3 }, - { 0, 0, 0 }, -}; - static struct clk_div_table rmii_ref_div_table[] = { { 0, 4 }, { 1, 10 }, { 0, 0 }, @@ -186,7 +181,6 @@ static struct clk_div_table nand_div_table[] = { /* mux clock */ static OWL_MUX(dev_clk, "dev_clk", dev_clk_mux_p, CMU_DEVPLL, 12, 1, CLK_SET_RATE_PARENT); -static OWL_MUX(ahbprediv_clk, "ahbprediv_clk", ahbprediv_clk_mux_p, CMU_BUSCLK1, 8, 3, CLK_SET_RATE_PARENT); /* gate clocks */ static OWL_GATE(gpio_clk, "gpio_clk", "apb_clk", CMU_DEVCLKEN0, 18, 0, 0); @@ -199,16 +193,25 @@ static OWL_GATE(timer_clk, "timer_clk", "hosc", CMU_DEVCLKEN1, 27, 0, 0); static OWL_GATE(hdmi_clk, "hdmi_clk", "hosc", CMU_DEVCLKEN1, 3, 0, 0); /* divider clocks */ -static OWL_DIVIDER(h_clk, "h_clk", "ahbprediv_clk", CMU_BUSCLK1, 12, 2, NULL, 0, 0); +static OWL_DIVIDER(h_clk, "h_clk", "ahbprediv_clk", CMU_BUSCLK1, 2, 2, NULL, 0, 0); static OWL_DIVIDER(apb_clk, "apb_clk", "ahb_clk", CMU_BUSCLK1, 14, 2, NULL, 0, 0); static OWL_DIVIDER(rmii_ref_clk, "rmii_ref_clk", "ethernet_pll_clk", CMU_ETHERNETPLL, 1, 1, rmii_ref_div_table, 0, 0); /* factor clocks */ -static OWL_FACTOR(ahb_clk, "ahb_clk", "h_clk", CMU_BUSCLK1, 2, 2, ahb_factor_table, 0, 0); static OWL_FACTOR(de1_clk, "de_clk1", "de_clk", CMU_DECLK, 0, 4, de_factor_table, 0, 0); static OWL_FACTOR(de2_clk, "de_clk2", "de_clk", CMU_DECLK, 4, 4, de_factor_table, 0, 0); /* composite clocks */ +static OWL_COMP_DIV(ahbprediv_clk, "ahbprediv_clk", ahbprediv_clk_mux_p, + OWL_MUX_HW(CMU_BUSCLK1, 8, 3), + { 0 }, + OWL_DIVIDER_HW(CMU_BUSCLK1, 12, 2, 0, NULL), + CLK_SET_RATE_PARENT); + +static OWL_COMP_FIXED_FACTOR(ahb_clk, "ahb_clk", "h_clk", + { 0 }, + 1, 1, 0); + static OWL_COMP_FACTOR(vce_clk, "vce_clk", hde_clk_mux_p, OWL_MUX_HW(CMU_VCECLK, 4, 2), OWL_GATE_HW(CMU_DEVCLKEN0, 26, 0), From a4acefd85825f1d0b7299a804b2c3fc4153f1e3a Mon Sep 17 00:00:00 2001 From: Cristian Ciocaltea Date: Thu, 10 Jun 2021 23:05:25 +0300 Subject: [PATCH 122/161] dt-bindings: clock: Add NIC and ETHERNET bindings for Actions S500 SoC Add the missing NIC and ETHERNET clock bindings constants for Actions Semi Owl S500 SoC. Signed-off-by: Cristian Ciocaltea Acked-by: Rob Herring Reviewed-by: Manivannan Sadhasivam Link: https://lore.kernel.org/r/1d0902cf073f76a1a602410061481ccb3fc36a72.1623354574.git.cristian.ciocaltea@gmail.com Signed-off-by: Stephen Boyd --- include/dt-bindings/clock/actions,s500-cmu.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/include/dt-bindings/clock/actions,s500-cmu.h b/include/dt-bindings/clock/actions,s500-cmu.h index a250a52a6192..a237eb26accb 100644 --- a/include/dt-bindings/clock/actions,s500-cmu.h +++ b/include/dt-bindings/clock/actions,s500-cmu.h @@ -74,10 +74,12 @@ #define CLK_RMII_REF 54 #define CLK_GPIO 55 -/* system clock (part 2) */ +/* additional clocks */ #define CLK_APB 56 #define CLK_DMAC 57 +#define CLK_NIC 58 +#define CLK_ETHERNET 59 -#define CLK_NR_CLKS (CLK_DMAC + 1) +#define CLK_NR_CLKS (CLK_ETHERNET + 1) #endif /* __DT_BINDINGS_CLOCK_S500_CMU_H */ From db01868f1b26378baf254c1f2c57b7deeeda7f08 Mon Sep 17 00:00:00 2001 From: Cristian Ciocaltea Date: Thu, 10 Jun 2021 23:05:26 +0300 Subject: [PATCH 123/161] clk: actions: Add NIC and ETHERNET clock support for Actions S500 SoC Add support for the missing NIC and ETHERNET clocks in the Actions Semi Owl S500 SoC clock driver. Additionally, change APB clock parent from AHB to the newly added NIC. Signed-off-by: Cristian Ciocaltea Reviewed-by: Manivannan Sadhasivam Link: https://lore.kernel.org/r/d62e4f1f85c5cef05be14d9e8143e88bbddd2e0f.1623354574.git.cristian.ciocaltea@gmail.com Signed-off-by: Stephen Boyd --- drivers/clk/actions/owl-s500.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/drivers/clk/actions/owl-s500.c b/drivers/clk/actions/owl-s500.c index cbeb51c804eb..57d06e183dff 100644 --- a/drivers/clk/actions/owl-s500.c +++ b/drivers/clk/actions/owl-s500.c @@ -113,6 +113,7 @@ static const char * const sensor_clk_mux_p[] = { "hosc", "bisp_clk" }; static const char * const sd_clk_mux_p[] = { "dev_clk", "nand_pll_clk" }; static const char * const pwm_clk_mux_p[] = { "losc", "hosc" }; static const char * const ahbprediv_clk_mux_p[] = { "dev_clk", "display_pll_clk", "nand_pll_clk", "ddr_pll_clk" }; +static const char * const nic_clk_mux_p[] = { "dev_clk", "display_pll_clk", "nand_pll_clk", "ddr_pll_clk" }; static const char * const uart_clk_mux_p[] = { "hosc", "dev_pll_clk" }; static const char * const de_clk_mux_p[] = { "display_pll_clk", "dev_clk" }; static const char * const i2s_clk_mux_p[] = { "audio_pll_clk" }; @@ -194,7 +195,7 @@ static OWL_GATE(hdmi_clk, "hdmi_clk", "hosc", CMU_DEVCLKEN1, 3, 0, 0); /* divider clocks */ static OWL_DIVIDER(h_clk, "h_clk", "ahbprediv_clk", CMU_BUSCLK1, 2, 2, NULL, 0, 0); -static OWL_DIVIDER(apb_clk, "apb_clk", "ahb_clk", CMU_BUSCLK1, 14, 2, NULL, 0, 0); +static OWL_DIVIDER(apb_clk, "apb_clk", "nic_clk", CMU_BUSCLK1, 14, 2, NULL, 0, 0); static OWL_DIVIDER(rmii_ref_clk, "rmii_ref_clk", "ethernet_pll_clk", CMU_ETHERNETPLL, 1, 1, rmii_ref_div_table, 0, 0); /* factor clocks */ @@ -202,6 +203,12 @@ static OWL_FACTOR(de1_clk, "de_clk1", "de_clk", CMU_DECLK, 0, 4, de_factor_table static OWL_FACTOR(de2_clk, "de_clk2", "de_clk", CMU_DECLK, 4, 4, de_factor_table, 0, 0); /* composite clocks */ +static OWL_COMP_DIV(nic_clk, "nic_clk", nic_clk_mux_p, + OWL_MUX_HW(CMU_BUSCLK1, 4, 3), + { 0 }, + OWL_DIVIDER_HW(CMU_BUSCLK1, 16, 2, 0, NULL), + 0); + static OWL_COMP_DIV(ahbprediv_clk, "ahbprediv_clk", ahbprediv_clk_mux_p, OWL_MUX_HW(CMU_BUSCLK1, 8, 3), { 0 }, @@ -317,6 +324,10 @@ static OWL_COMP_FIXED_FACTOR(i2c3_clk, "i2c3_clk", "ethernet_pll_clk", OWL_GATE_HW(CMU_DEVCLKEN1, 31, 0), 1, 5, 0); +static OWL_COMP_FIXED_FACTOR(ethernet_clk, "ethernet_clk", "ethernet_pll_clk", + OWL_GATE_HW(CMU_DEVCLKEN1, 22, 0), + 1, 20, 0); + static OWL_COMP_DIV(uart0_clk, "uart0_clk", uart_clk_mux_p, OWL_MUX_HW(CMU_UART0CLK, 16, 1), OWL_GATE_HW(CMU_DEVCLKEN1, 6, 0), @@ -451,6 +462,8 @@ static struct owl_clk_common *s500_clks[] = { &apb_clk.common, &dmac_clk.common, &gpio_clk.common, + &nic_clk.common, + ðernet_clk.common, }; static struct clk_hw_onecell_data s500_hw_clks = { @@ -510,6 +523,8 @@ static struct clk_hw_onecell_data s500_hw_clks = { [CLK_APB] = &apb_clk.common.hw, [CLK_DMAC] = &dmac_clk.common.hw, [CLK_GPIO] = &gpio_clk.common.hw, + [CLK_NIC] = &nic_clk.common.hw, + [CLK_ETHERNET] = ðernet_clk.common.hw, }, .num = CLK_NR_CLKS, }; From 7f54bf2640e877c8a9b4cc7e2b29f82e3ca1a284 Mon Sep 17 00:00:00 2001 From: Jonathan Marek Date: Tue, 8 Jun 2021 22:28:52 -0400 Subject: [PATCH 124/161] clk: qcom: clk-alpha-pll: fix CAL_L write in alpha_pll_fabia_prepare Caught this when looking at alpha-pll code. Untested but it is clear that this was intended to write to PLL_CAL_L_VAL and not PLL_ALPHA_VAL. Fixes: 691865bad627 ("clk: qcom: clk-alpha-pll: Add support for Fabia PLL calibration") Signed-off-by: Jonathan Marek Link: https://lore.kernel.org/r/20210609022852.4151-1-jonathan@marek.ca Signed-off-by: Stephen Boyd --- drivers/clk/qcom/clk-alpha-pll.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c index 94b53c7db2f7..eaedcceb766f 100644 --- a/drivers/clk/qcom/clk-alpha-pll.c +++ b/drivers/clk/qcom/clk-alpha-pll.c @@ -1255,7 +1255,7 @@ static int alpha_pll_fabia_prepare(struct clk_hw *hw) return ret; /* Setup PLL for calibration frequency */ - regmap_write(pll->clkr.regmap, PLL_ALPHA_VAL(pll), cal_l); + regmap_write(pll->clkr.regmap, PLL_CAL_L_VAL(pll), cal_l); /* Bringup the PLL at calibration frequency */ ret = clk_alpha_pll_enable(hw); From 2e1ae04f7fe049bb012c273e5281a3c145924ea1 Mon Sep 17 00:00:00 2001 From: Paul Cercueil Date: Sun, 30 May 2021 17:49:18 +0100 Subject: [PATCH 125/161] dt-bindings: clock: ingenic: Add ingenic,jz4760{,b}-cgu compatibles Add ingenic,jz4760-cgu and ingenic,jz4760b-cgu compatible strings for the JZ4760 and JZ4760B SoCs respectively. Signed-off-by: Paul Cercueil Acked-by: Rob Herring Link: https://lore.kernel.org/r/20210530164923.18134-2-paul@crapouillou.net Signed-off-by: Stephen Boyd --- Documentation/devicetree/bindings/clock/ingenic,cgu.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Documentation/devicetree/bindings/clock/ingenic,cgu.yaml b/Documentation/devicetree/bindings/clock/ingenic,cgu.yaml index c65b9458c0b6..6d6236e02c22 100644 --- a/Documentation/devicetree/bindings/clock/ingenic,cgu.yaml +++ b/Documentation/devicetree/bindings/clock/ingenic,cgu.yaml @@ -22,6 +22,8 @@ select: enum: - ingenic,jz4740-cgu - ingenic,jz4725b-cgu + - ingenic,jz4760-cgu + - ingenic,jz4760b-cgu - ingenic,jz4770-cgu - ingenic,jz4780-cgu - ingenic,x1000-cgu @@ -49,6 +51,8 @@ properties: - enum: - ingenic,jz4740-cgu - ingenic,jz4725b-cgu + - ingenic,jz4760-cgu + - ingenic,jz4760b-cgu - ingenic,jz4770-cgu - ingenic,jz4780-cgu - ingenic,x1000-cgu From 249592bf6d5d52cacdc2f5a07f23368fc1b11324 Mon Sep 17 00:00:00 2001 From: Paul Cercueil Date: Sun, 30 May 2021 17:49:19 +0100 Subject: [PATCH 126/161] clk: Support bypassing dividers When a clock is declared as both CGU_CLK_DIV and CGU_CLK_MUX, the CGU code expects the mux to be applied first, the divider second. On the JZ4760, and maybe on some other SoCs, some clocks also have a mux setting and a divider, but the divider is not applied to all parents selectable from the mux. This could be solved by creating two clocks, one with CGU_CLK_DIV and one with CGU_CLK_MUX, but that would increase the number of clocks. Instead, add a 8-bit mask to CGU_CLK_DIV clocks. If the bit corresponding to the parent clock's index is set, the divider is bypassed. Signed-off-by: Paul Cercueil Link: https://lore.kernel.org/r/20210530164923.18134-3-paul@crapouillou.net Signed-off-by: Stephen Boyd --- drivers/clk/ingenic/cgu.c | 33 ++++++++++++++++++++----------- drivers/clk/ingenic/cgu.h | 2 ++ drivers/clk/ingenic/jz4725b-cgu.c | 12 +++++------ drivers/clk/ingenic/jz4740-cgu.c | 12 +++++------ drivers/clk/ingenic/jz4770-cgu.c | 12 +++++------ 5 files changed, 42 insertions(+), 29 deletions(-) diff --git a/drivers/clk/ingenic/cgu.c b/drivers/clk/ingenic/cgu.c index c8e9cb6c8e39..0619d45a950c 100644 --- a/drivers/clk/ingenic/cgu.c +++ b/drivers/clk/ingenic/cgu.c @@ -369,18 +369,23 @@ ingenic_clk_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) struct ingenic_cgu *cgu = ingenic_clk->cgu; unsigned long rate = parent_rate; u32 div_reg, div; + u8 parent; if (clk_info->type & CGU_CLK_DIV) { - div_reg = readl(cgu->base + clk_info->div.reg); - div = (div_reg >> clk_info->div.shift) & - GENMASK(clk_info->div.bits - 1, 0); + parent = ingenic_clk_get_parent(hw); - if (clk_info->div.div_table) - div = clk_info->div.div_table[div]; - else - div = (div + 1) * clk_info->div.div; + if (!(clk_info->div.bypass_mask & BIT(parent))) { + div_reg = readl(cgu->base + clk_info->div.reg); + div = (div_reg >> clk_info->div.shift) & + GENMASK(clk_info->div.bits - 1, 0); - rate /= div; + if (clk_info->div.div_table) + div = clk_info->div.div_table[div]; + else + div = (div + 1) * clk_info->div.div; + + rate /= div; + } } else if (clk_info->type & CGU_CLK_FIXDIV) { rate /= clk_info->fixdiv.div; } @@ -410,10 +415,16 @@ ingenic_clk_calc_hw_div(const struct ingenic_cgu_clk_info *clk_info, } static unsigned -ingenic_clk_calc_div(const struct ingenic_cgu_clk_info *clk_info, +ingenic_clk_calc_div(struct clk_hw *hw, + const struct ingenic_cgu_clk_info *clk_info, unsigned long parent_rate, unsigned long req_rate) { unsigned int div, hw_div; + u8 parent; + + parent = ingenic_clk_get_parent(hw); + if (clk_info->div.bypass_mask & BIT(parent)) + return 1; /* calculate the divide */ div = DIV_ROUND_UP(parent_rate, req_rate); @@ -448,7 +459,7 @@ ingenic_clk_round_rate(struct clk_hw *hw, unsigned long req_rate, unsigned int div = 1; if (clk_info->type & CGU_CLK_DIV) - div = ingenic_clk_calc_div(clk_info, *parent_rate, req_rate); + div = ingenic_clk_calc_div(hw, clk_info, *parent_rate, req_rate); else if (clk_info->type & CGU_CLK_FIXDIV) div = clk_info->fixdiv.div; else if (clk_hw_can_set_rate_parent(hw)) @@ -480,7 +491,7 @@ ingenic_clk_set_rate(struct clk_hw *hw, unsigned long req_rate, int ret = 0; if (clk_info->type & CGU_CLK_DIV) { - div = ingenic_clk_calc_div(clk_info, parent_rate, req_rate); + div = ingenic_clk_calc_div(hw, clk_info, parent_rate, req_rate); rate = DIV_ROUND_UP(parent_rate, div); if (rate != req_rate) diff --git a/drivers/clk/ingenic/cgu.h b/drivers/clk/ingenic/cgu.h index 2c75ef4a36f5..44d97a259692 100644 --- a/drivers/clk/ingenic/cgu.h +++ b/drivers/clk/ingenic/cgu.h @@ -84,6 +84,7 @@ struct ingenic_cgu_mux_info { * isn't one * @busy_bit: the index of the busy bit within reg, or -1 if there isn't one * @stop_bit: the index of the stop bit within reg, or -1 if there isn't one + * @bypass_mask: mask of parent clocks for which the divider does not apply * @div_table: optional table to map the value read from the register to the * actual divider value */ @@ -95,6 +96,7 @@ struct ingenic_cgu_div_info { s8 ce_bit; s8 busy_bit; s8 stop_bit; + u8 bypass_mask; const u8 *div_table; }; diff --git a/drivers/clk/ingenic/jz4725b-cgu.c b/drivers/clk/ingenic/jz4725b-cgu.c index 8c38e72d14a7..5154b0cf8ad6 100644 --- a/drivers/clk/ingenic/jz4725b-cgu.c +++ b/drivers/clk/ingenic/jz4725b-cgu.c @@ -80,7 +80,7 @@ static const struct ingenic_cgu_clk_info jz4725b_cgu_clocks[] = { "pll half", CGU_CLK_DIV, .parents = { JZ4725B_CLK_PLL, -1, -1, -1 }, .div = { - CGU_REG_CPCCR, 21, 1, 1, -1, -1, -1, + CGU_REG_CPCCR, 21, 1, 1, -1, -1, -1, 0, jz4725b_cgu_pll_half_div_table, }, }, @@ -89,7 +89,7 @@ static const struct ingenic_cgu_clk_info jz4725b_cgu_clocks[] = { "cclk", CGU_CLK_DIV, .parents = { JZ4725B_CLK_PLL, -1, -1, -1 }, .div = { - CGU_REG_CPCCR, 0, 1, 4, 22, -1, -1, + CGU_REG_CPCCR, 0, 1, 4, 22, -1, -1, 0, jz4725b_cgu_cpccr_div_table, }, }, @@ -98,7 +98,7 @@ static const struct ingenic_cgu_clk_info jz4725b_cgu_clocks[] = { "hclk", CGU_CLK_DIV, .parents = { JZ4725B_CLK_PLL, -1, -1, -1 }, .div = { - CGU_REG_CPCCR, 4, 1, 4, 22, -1, -1, + CGU_REG_CPCCR, 4, 1, 4, 22, -1, -1, 0, jz4725b_cgu_cpccr_div_table, }, }, @@ -107,7 +107,7 @@ static const struct ingenic_cgu_clk_info jz4725b_cgu_clocks[] = { "pclk", CGU_CLK_DIV, .parents = { JZ4725B_CLK_PLL, -1, -1, -1 }, .div = { - CGU_REG_CPCCR, 8, 1, 4, 22, -1, -1, + CGU_REG_CPCCR, 8, 1, 4, 22, -1, -1, 0, jz4725b_cgu_cpccr_div_table, }, }, @@ -116,7 +116,7 @@ static const struct ingenic_cgu_clk_info jz4725b_cgu_clocks[] = { "mclk", CGU_CLK_DIV, .parents = { JZ4725B_CLK_PLL, -1, -1, -1 }, .div = { - CGU_REG_CPCCR, 12, 1, 4, 22, -1, -1, + CGU_REG_CPCCR, 12, 1, 4, 22, -1, -1, 0, jz4725b_cgu_cpccr_div_table, }, }, @@ -125,7 +125,7 @@ static const struct ingenic_cgu_clk_info jz4725b_cgu_clocks[] = { "ipu", CGU_CLK_DIV | CGU_CLK_GATE, .parents = { JZ4725B_CLK_PLL, -1, -1, -1 }, .div = { - CGU_REG_CPCCR, 16, 1, 4, 22, -1, -1, + CGU_REG_CPCCR, 16, 1, 4, 22, -1, -1, 0, jz4725b_cgu_cpccr_div_table, }, .gate = { CGU_REG_CLKGR, 13 }, diff --git a/drivers/clk/ingenic/jz4740-cgu.c b/drivers/clk/ingenic/jz4740-cgu.c index c0ac9196a581..cd878f08aca3 100644 --- a/drivers/clk/ingenic/jz4740-cgu.c +++ b/drivers/clk/ingenic/jz4740-cgu.c @@ -95,7 +95,7 @@ static const struct ingenic_cgu_clk_info jz4740_cgu_clocks[] = { "pll half", CGU_CLK_DIV, .parents = { JZ4740_CLK_PLL, -1, -1, -1 }, .div = { - CGU_REG_CPCCR, 21, 1, 1, -1, -1, -1, + CGU_REG_CPCCR, 21, 1, 1, -1, -1, -1, 0, jz4740_cgu_pll_half_div_table, }, }, @@ -104,7 +104,7 @@ static const struct ingenic_cgu_clk_info jz4740_cgu_clocks[] = { "cclk", CGU_CLK_DIV, .parents = { JZ4740_CLK_PLL, -1, -1, -1 }, .div = { - CGU_REG_CPCCR, 0, 1, 4, 22, -1, -1, + CGU_REG_CPCCR, 0, 1, 4, 22, -1, -1, 0, jz4740_cgu_cpccr_div_table, }, }, @@ -113,7 +113,7 @@ static const struct ingenic_cgu_clk_info jz4740_cgu_clocks[] = { "hclk", CGU_CLK_DIV, .parents = { JZ4740_CLK_PLL, -1, -1, -1 }, .div = { - CGU_REG_CPCCR, 4, 1, 4, 22, -1, -1, + CGU_REG_CPCCR, 4, 1, 4, 22, -1, -1, 0, jz4740_cgu_cpccr_div_table, }, }, @@ -122,7 +122,7 @@ static const struct ingenic_cgu_clk_info jz4740_cgu_clocks[] = { "pclk", CGU_CLK_DIV, .parents = { JZ4740_CLK_PLL, -1, -1, -1 }, .div = { - CGU_REG_CPCCR, 8, 1, 4, 22, -1, -1, + CGU_REG_CPCCR, 8, 1, 4, 22, -1, -1, 0, jz4740_cgu_cpccr_div_table, }, }, @@ -131,7 +131,7 @@ static const struct ingenic_cgu_clk_info jz4740_cgu_clocks[] = { "mclk", CGU_CLK_DIV, .parents = { JZ4740_CLK_PLL, -1, -1, -1 }, .div = { - CGU_REG_CPCCR, 12, 1, 4, 22, -1, -1, + CGU_REG_CPCCR, 12, 1, 4, 22, -1, -1, 0, jz4740_cgu_cpccr_div_table, }, }, @@ -140,7 +140,7 @@ static const struct ingenic_cgu_clk_info jz4740_cgu_clocks[] = { "lcd", CGU_CLK_DIV | CGU_CLK_GATE, .parents = { JZ4740_CLK_PLL_HALF, -1, -1, -1 }, .div = { - CGU_REG_CPCCR, 16, 1, 5, 22, -1, -1, + CGU_REG_CPCCR, 16, 1, 5, 22, -1, -1, 0, jz4740_cgu_cpccr_div_table, }, .gate = { CGU_REG_CLKGR, 10 }, diff --git a/drivers/clk/ingenic/jz4770-cgu.c b/drivers/clk/ingenic/jz4770-cgu.c index 9ea4490ecb7f..381a27f20b51 100644 --- a/drivers/clk/ingenic/jz4770-cgu.c +++ b/drivers/clk/ingenic/jz4770-cgu.c @@ -152,7 +152,7 @@ static const struct ingenic_cgu_clk_info jz4770_cgu_clocks[] = { "cclk", CGU_CLK_DIV, .parents = { JZ4770_CLK_PLL0, }, .div = { - CGU_REG_CPCCR, 0, 1, 4, 22, -1, -1, + CGU_REG_CPCCR, 0, 1, 4, 22, -1, -1, 0, jz4770_cgu_cpccr_div_table, }, }, @@ -160,7 +160,7 @@ static const struct ingenic_cgu_clk_info jz4770_cgu_clocks[] = { "h0clk", CGU_CLK_DIV, .parents = { JZ4770_CLK_PLL0, }, .div = { - CGU_REG_CPCCR, 4, 1, 4, 22, -1, -1, + CGU_REG_CPCCR, 4, 1, 4, 22, -1, -1, 0, jz4770_cgu_cpccr_div_table, }, }, @@ -168,7 +168,7 @@ static const struct ingenic_cgu_clk_info jz4770_cgu_clocks[] = { "h1clk", CGU_CLK_DIV | CGU_CLK_GATE, .parents = { JZ4770_CLK_PLL0, }, .div = { - CGU_REG_CPCCR, 24, 1, 4, 22, -1, -1, + CGU_REG_CPCCR, 24, 1, 4, 22, -1, -1, 0, jz4770_cgu_cpccr_div_table, }, .gate = { CGU_REG_CLKGR1, 7 }, @@ -177,7 +177,7 @@ static const struct ingenic_cgu_clk_info jz4770_cgu_clocks[] = { "h2clk", CGU_CLK_DIV, .parents = { JZ4770_CLK_PLL0, }, .div = { - CGU_REG_CPCCR, 16, 1, 4, 22, -1, -1, + CGU_REG_CPCCR, 16, 1, 4, 22, -1, -1, 0, jz4770_cgu_cpccr_div_table, }, }, @@ -185,7 +185,7 @@ static const struct ingenic_cgu_clk_info jz4770_cgu_clocks[] = { "c1clk", CGU_CLK_DIV | CGU_CLK_GATE, .parents = { JZ4770_CLK_PLL0, }, .div = { - CGU_REG_CPCCR, 12, 1, 4, 22, -1, -1, + CGU_REG_CPCCR, 12, 1, 4, 22, -1, -1, 0, jz4770_cgu_cpccr_div_table, }, .gate = { CGU_REG_OPCR, 31, true }, // disable CCLK stop on idle @@ -194,7 +194,7 @@ static const struct ingenic_cgu_clk_info jz4770_cgu_clocks[] = { "pclk", CGU_CLK_DIV, .parents = { JZ4770_CLK_PLL0, }, .div = { - CGU_REG_CPCCR, 8, 1, 4, 22, -1, -1, + CGU_REG_CPCCR, 8, 1, 4, 22, -1, -1, 0, jz4770_cgu_cpccr_div_table, }, }, From 315a8423b20362bb675c5263cb237ecb51d9589e Mon Sep 17 00:00:00 2001 From: Paul Cercueil Date: Sun, 30 May 2021 17:49:20 +0100 Subject: [PATCH 127/161] clk: ingenic: Read bypass register only when there is one MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rework the clock code so that the bypass register is only read when there is actually a bypass functionality. Signed-off-by: Paul Cercueil Link: https://lore.kernel.org/r/20210530164923.18134-4-paul@crapouillou.net Tested-by: 周琰杰 (Zhou Yanjie) # on CU1830-neo/X1830 Signed-off-by: Stephen Boyd --- drivers/clk/ingenic/cgu.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/drivers/clk/ingenic/cgu.c b/drivers/clk/ingenic/cgu.c index 0619d45a950c..7686072aff8f 100644 --- a/drivers/clk/ingenic/cgu.c +++ b/drivers/clk/ingenic/cgu.c @@ -99,13 +99,14 @@ ingenic_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) od_enc = ctl >> pll_info->od_shift; od_enc &= GENMASK(pll_info->od_bits - 1, 0); - ctl = readl(cgu->base + pll_info->bypass_reg); + if (!pll_info->no_bypass_bit) { + ctl = readl(cgu->base + pll_info->bypass_reg); - bypass = !pll_info->no_bypass_bit && - !!(ctl & BIT(pll_info->bypass_bit)); + bypass = !!(ctl & BIT(pll_info->bypass_bit)); - if (bypass) - return parent_rate; + if (bypass) + return parent_rate; + } for (od = 0; od < pll_info->od_max; od++) { if (pll_info->od_encoding[od] == od_enc) @@ -225,11 +226,13 @@ static int ingenic_pll_enable(struct clk_hw *hw) u32 ctl; spin_lock_irqsave(&cgu->lock, flags); - ctl = readl(cgu->base + pll_info->bypass_reg); + if (!pll_info->no_bypass_bit) { + ctl = readl(cgu->base + pll_info->bypass_reg); - ctl &= ~BIT(pll_info->bypass_bit); + ctl &= ~BIT(pll_info->bypass_bit); - writel(ctl, cgu->base + pll_info->bypass_reg); + writel(ctl, cgu->base + pll_info->bypass_reg); + } ctl = readl(cgu->base + pll_info->reg); From 037f1ffd0f0a6bad89e17aa4698c97ef430c6ad1 Mon Sep 17 00:00:00 2001 From: Paul Cercueil Date: Sun, 30 May 2021 17:49:21 +0100 Subject: [PATCH 128/161] clk: ingenic: Remove pll_info.no_bypass_bit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We can express that a PLL has no bypass bit by simply setting the .bypass_bit field to a negative value. Signed-off-by: Paul Cercueil Link: https://lore.kernel.org/r/20210530164923.18134-5-paul@crapouillou.net Tested-by: 周琰杰 (Zhou Yanjie) # on CU1830-neo/X1830 Signed-off-by: Stephen Boyd --- drivers/clk/ingenic/cgu.c | 4 ++-- drivers/clk/ingenic/cgu.h | 7 +++---- drivers/clk/ingenic/jz4770-cgu.c | 3 +-- 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/drivers/clk/ingenic/cgu.c b/drivers/clk/ingenic/cgu.c index 7686072aff8f..58f7ab5cf0fe 100644 --- a/drivers/clk/ingenic/cgu.c +++ b/drivers/clk/ingenic/cgu.c @@ -99,7 +99,7 @@ ingenic_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) od_enc = ctl >> pll_info->od_shift; od_enc &= GENMASK(pll_info->od_bits - 1, 0); - if (!pll_info->no_bypass_bit) { + if (pll_info->bypass_bit >= 0) { ctl = readl(cgu->base + pll_info->bypass_reg); bypass = !!(ctl & BIT(pll_info->bypass_bit)); @@ -226,7 +226,7 @@ static int ingenic_pll_enable(struct clk_hw *hw) u32 ctl; spin_lock_irqsave(&cgu->lock, flags); - if (!pll_info->no_bypass_bit) { + if (pll_info->bypass_bit >= 0) { ctl = readl(cgu->base + pll_info->bypass_reg); ctl &= ~BIT(pll_info->bypass_bit); diff --git a/drivers/clk/ingenic/cgu.h b/drivers/clk/ingenic/cgu.h index 44d97a259692..10521d1b7b12 100644 --- a/drivers/clk/ingenic/cgu.h +++ b/drivers/clk/ingenic/cgu.h @@ -39,10 +39,10 @@ * their encoded values in the PLL control register, or -1 for * unsupported values * @bypass_reg: the offset of the bypass control register within the CGU - * @bypass_bit: the index of the bypass bit in the PLL control register + * @bypass_bit: the index of the bypass bit in the PLL control register, or + * -1 if there is no bypass bit * @enable_bit: the index of the enable bit in the PLL control register * @stable_bit: the index of the stable bit in the PLL control register - * @no_bypass_bit: if set, the PLL has no bypass functionality */ struct ingenic_cgu_pll_info { unsigned reg; @@ -52,10 +52,9 @@ struct ingenic_cgu_pll_info { u8 n_shift, n_bits, n_offset; u8 od_shift, od_bits, od_max; unsigned bypass_reg; - u8 bypass_bit; + s8 bypass_bit; u8 enable_bit; u8 stable_bit; - bool no_bypass_bit; }; /** diff --git a/drivers/clk/ingenic/jz4770-cgu.c b/drivers/clk/ingenic/jz4770-cgu.c index 381a27f20b51..2321742b3471 100644 --- a/drivers/clk/ingenic/jz4770-cgu.c +++ b/drivers/clk/ingenic/jz4770-cgu.c @@ -139,8 +139,7 @@ static const struct ingenic_cgu_clk_info jz4770_cgu_clocks[] = { .od_bits = 2, .od_max = 8, .od_encoding = pll_od_encoding, - .bypass_reg = CGU_REG_CPPCR1, - .no_bypass_bit = true, + .bypass_bit = -1, .enable_bit = 7, .stable_bit = 6, }, From b60b0b55926bea93c0f00000ac884fa1b3c9a492 Mon Sep 17 00:00:00 2001 From: Paul Cercueil Date: Sun, 30 May 2021 17:49:22 +0100 Subject: [PATCH 129/161] clk: ingenic: Support overriding PLLs M/N/OD calc algorithm MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit SoC-specific code can now provide a callback if they need to compute the M/N/OD values in a specific way. Signed-off-by: Paul Cercueil Tested-by: 周琰杰 (Zhou Yanjie) # on CU1000-neo/X1000E Link: https://lore.kernel.org/r/20210530164923.18134-6-paul@crapouillou.net Signed-off-by: Stephen Boyd --- drivers/clk/ingenic/cgu.c | 40 ++++++++++++++++++++++++++------------- drivers/clk/ingenic/cgu.h | 3 +++ 2 files changed, 30 insertions(+), 13 deletions(-) diff --git a/drivers/clk/ingenic/cgu.c b/drivers/clk/ingenic/cgu.c index 58f7ab5cf0fe..266c7595d330 100644 --- a/drivers/clk/ingenic/cgu.c +++ b/drivers/clk/ingenic/cgu.c @@ -119,28 +119,42 @@ ingenic_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) n * od); } -static unsigned long -ingenic_pll_calc(const struct ingenic_cgu_clk_info *clk_info, - unsigned long rate, unsigned long parent_rate, - unsigned *pm, unsigned *pn, unsigned *pod) +static void +ingenic_pll_calc_m_n_od(const struct ingenic_cgu_pll_info *pll_info, + unsigned long rate, unsigned long parent_rate, + unsigned int *pm, unsigned int *pn, unsigned int *pod) { - const struct ingenic_cgu_pll_info *pll_info; - unsigned m, n, od; - - pll_info = &clk_info->pll; - od = 1; + unsigned int m, n, od = 1; /* * The frequency after the input divider must be between 10 and 50 MHz. * The highest divider yields the best resolution. */ n = parent_rate / (10 * MHZ); - n = min_t(unsigned, n, 1 << clk_info->pll.n_bits); - n = max_t(unsigned, n, pll_info->n_offset); + n = min_t(unsigned int, n, 1 << pll_info->n_bits); + n = max_t(unsigned int, n, pll_info->n_offset); m = (rate / MHZ) * od * n / (parent_rate / MHZ); - m = min_t(unsigned, m, 1 << clk_info->pll.m_bits); - m = max_t(unsigned, m, pll_info->m_offset); + m = min_t(unsigned int, m, 1 << pll_info->m_bits); + m = max_t(unsigned int, m, pll_info->m_offset); + + *pm = m; + *pn = n; + *pod = od; +} + +static unsigned long +ingenic_pll_calc(const struct ingenic_cgu_clk_info *clk_info, + unsigned long rate, unsigned long parent_rate, + unsigned int *pm, unsigned int *pn, unsigned int *pod) +{ + const struct ingenic_cgu_pll_info *pll_info = &clk_info->pll; + unsigned int m, n, od; + + if (pll_info->calc_m_n_od) + (*pll_info->calc_m_n_od)(pll_info, rate, parent_rate, &m, &n, &od); + else + ingenic_pll_calc_m_n_od(pll_info, rate, parent_rate, &m, &n, &od); if (pm) *pm = m; diff --git a/drivers/clk/ingenic/cgu.h b/drivers/clk/ingenic/cgu.h index 10521d1b7b12..bfc2b9c38a41 100644 --- a/drivers/clk/ingenic/cgu.h +++ b/drivers/clk/ingenic/cgu.h @@ -55,6 +55,9 @@ struct ingenic_cgu_pll_info { s8 bypass_bit; u8 enable_bit; u8 stable_bit; + void (*calc_m_n_od)(const struct ingenic_cgu_pll_info *pll_info, + unsigned long rate, unsigned long parent_rate, + unsigned int *m, unsigned int *n, unsigned int *od); }; /** From bdbfc029374f6d9ed31bc44983501fd1008b677f Mon Sep 17 00:00:00 2001 From: Paul Cercueil Date: Sun, 30 May 2021 17:49:23 +0100 Subject: [PATCH 130/161] clk: ingenic: Add support for the JZ4760 Add the CGU code and the compatible string to the TCU driver to support the JZ4760 SoC. Signed-off-by: Paul Cercueil Link: https://lore.kernel.org/r/20210530164923.18134-7-paul@crapouillou.net Signed-off-by: Stephen Boyd --- drivers/clk/ingenic/Kconfig | 10 + drivers/clk/ingenic/Makefile | 1 + drivers/clk/ingenic/jz4760-cgu.c | 428 +++++++++++++++++++++++++ drivers/clk/ingenic/tcu.c | 2 + include/dt-bindings/clock/jz4760-cgu.h | 54 ++++ 5 files changed, 495 insertions(+) create mode 100644 drivers/clk/ingenic/jz4760-cgu.c create mode 100644 include/dt-bindings/clock/jz4760-cgu.h diff --git a/drivers/clk/ingenic/Kconfig b/drivers/clk/ingenic/Kconfig index 580b0cf69ed5..898f1bc478c9 100644 --- a/drivers/clk/ingenic/Kconfig +++ b/drivers/clk/ingenic/Kconfig @@ -25,6 +25,16 @@ config INGENIC_CGU_JZ4725B If building for a JZ4725B SoC, you want to say Y here. +config INGENIC_CGU_JZ4760 + bool "Ingenic JZ4760 CGU driver" + default MACH_JZ4760 + select INGENIC_CGU_COMMON + help + Support the clocks provided by the CGU hardware on Ingenic JZ4760 + and compatible SoCs. + + If building for a JZ4760 SoC, you want to say Y here. + config INGENIC_CGU_JZ4770 bool "Ingenic JZ4770 CGU driver" default MACH_JZ4770 diff --git a/drivers/clk/ingenic/Makefile b/drivers/clk/ingenic/Makefile index aaa4bffe03c6..9edfaf4610b9 100644 --- a/drivers/clk/ingenic/Makefile +++ b/drivers/clk/ingenic/Makefile @@ -2,6 +2,7 @@ obj-$(CONFIG_INGENIC_CGU_COMMON) += cgu.o pm.o obj-$(CONFIG_INGENIC_CGU_JZ4740) += jz4740-cgu.o obj-$(CONFIG_INGENIC_CGU_JZ4725B) += jz4725b-cgu.o +obj-$(CONFIG_INGENIC_CGU_JZ4760) += jz4760-cgu.o obj-$(CONFIG_INGENIC_CGU_JZ4770) += jz4770-cgu.o obj-$(CONFIG_INGENIC_CGU_JZ4780) += jz4780-cgu.o obj-$(CONFIG_INGENIC_CGU_X1000) += x1000-cgu.o diff --git a/drivers/clk/ingenic/jz4760-cgu.c b/drivers/clk/ingenic/jz4760-cgu.c new file mode 100644 index 000000000000..14483797a4db --- /dev/null +++ b/drivers/clk/ingenic/jz4760-cgu.c @@ -0,0 +1,428 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * JZ4760 SoC CGU driver + * Copyright 2018, Paul Cercueil + */ + +#include +#include +#include +#include +#include + +#include + +#include + +#include "cgu.h" +#include "pm.h" + +#define MHZ (1000 * 1000) + +/* + * CPM registers offset address definition + */ +#define CGU_REG_CPCCR 0x00 +#define CGU_REG_LCR 0x04 +#define CGU_REG_CPPCR0 0x10 +#define CGU_REG_CLKGR0 0x20 +#define CGU_REG_OPCR 0x24 +#define CGU_REG_CLKGR1 0x28 +#define CGU_REG_CPPCR1 0x30 +#define CGU_REG_USBPCR 0x3c +#define CGU_REG_USBCDR 0x50 +#define CGU_REG_I2SCDR 0x60 +#define CGU_REG_LPCDR 0x64 +#define CGU_REG_MSCCDR 0x68 +#define CGU_REG_UHCCDR 0x6c +#define CGU_REG_SSICDR 0x74 +#define CGU_REG_CIMCDR 0x7c +#define CGU_REG_GPSCDR 0x80 +#define CGU_REG_PCMCDR 0x84 +#define CGU_REG_GPUCDR 0x88 + +static const s8 pll_od_encoding[8] = { + 0x0, 0x1, -1, 0x2, -1, -1, -1, 0x3, +}; + +static const u8 jz4760_cgu_cpccr_div_table[] = { + 1, 2, 3, 4, 6, 8, +}; + +static const u8 jz4760_cgu_pll_half_div_table[] = { + 2, 1, +}; + +static void +jz4760_cgu_calc_m_n_od(const struct ingenic_cgu_pll_info *pll_info, + unsigned long rate, unsigned long parent_rate, + unsigned int *pm, unsigned int *pn, unsigned int *pod) +{ + unsigned int m, n, od, m_max = (1 << pll_info->m_bits) - 2; + + /* The frequency after the N divider must be between 1 and 50 MHz. */ + n = parent_rate / (1 * MHZ); + + /* The N divider must be >= 2. */ + n = clamp_val(n, 2, 1 << pll_info->n_bits); + + for (;; n >>= 1) { + od = (unsigned int)-1; + + do { + m = (rate / MHZ) * (1 << ++od) * n / (parent_rate / MHZ); + } while ((m > m_max || m & 1) && (od < 4)); + + if (od < 4 && m >= 4 && m <= m_max) + break; + } + + *pm = m; + *pn = n; + *pod = 1 << od; +} + +static const struct ingenic_cgu_clk_info jz4760_cgu_clocks[] = { + + /* External clocks */ + + [JZ4760_CLK_EXT] = { "ext", CGU_CLK_EXT }, + [JZ4760_CLK_OSC32K] = { "osc32k", CGU_CLK_EXT }, + + /* PLLs */ + + [JZ4760_CLK_PLL0] = { + "pll0", CGU_CLK_PLL, + .parents = { JZ4760_CLK_EXT }, + .pll = { + .reg = CGU_REG_CPPCR0, + .rate_multiplier = 1, + .m_shift = 23, + .m_bits = 8, + .m_offset = 0, + .n_shift = 18, + .n_bits = 4, + .n_offset = 0, + .od_shift = 16, + .od_bits = 2, + .od_max = 8, + .od_encoding = pll_od_encoding, + .bypass_reg = CGU_REG_CPPCR0, + .bypass_bit = 9, + .enable_bit = 8, + .stable_bit = 10, + .calc_m_n_od = jz4760_cgu_calc_m_n_od, + }, + }, + + [JZ4760_CLK_PLL1] = { + /* TODO: PLL1 can depend on PLL0 */ + "pll1", CGU_CLK_PLL, + .parents = { JZ4760_CLK_EXT }, + .pll = { + .reg = CGU_REG_CPPCR1, + .rate_multiplier = 1, + .m_shift = 23, + .m_bits = 8, + .m_offset = 0, + .n_shift = 18, + .n_bits = 4, + .n_offset = 0, + .od_shift = 16, + .od_bits = 2, + .od_max = 8, + .od_encoding = pll_od_encoding, + .bypass_bit = -1, + .enable_bit = 7, + .stable_bit = 6, + .calc_m_n_od = jz4760_cgu_calc_m_n_od, + }, + }, + + /* Main clocks */ + + [JZ4760_CLK_CCLK] = { + "cclk", CGU_CLK_DIV, + .parents = { JZ4760_CLK_PLL0, }, + .div = { + CGU_REG_CPCCR, 0, 1, 4, 22, -1, -1, 0, + jz4760_cgu_cpccr_div_table, + }, + }, + [JZ4760_CLK_HCLK] = { + "hclk", CGU_CLK_DIV, + .parents = { JZ4760_CLK_PLL0, }, + .div = { + CGU_REG_CPCCR, 4, 1, 4, 22, -1, -1, 0, + jz4760_cgu_cpccr_div_table, + }, + }, + [JZ4760_CLK_SCLK] = { + "sclk", CGU_CLK_DIV, + .parents = { JZ4760_CLK_PLL0, }, + .div = { + CGU_REG_CPCCR, 24, 1, 4, 22, -1, -1, 0, + jz4760_cgu_cpccr_div_table, + }, + }, + [JZ4760_CLK_H2CLK] = { + "h2clk", CGU_CLK_DIV, + .parents = { JZ4760_CLK_PLL0, }, + .div = { + CGU_REG_CPCCR, 16, 1, 4, 22, -1, -1, 0, + jz4760_cgu_cpccr_div_table, + }, + }, + [JZ4760_CLK_MCLK] = { + "mclk", CGU_CLK_DIV, + .parents = { JZ4760_CLK_PLL0, }, + .div = { + CGU_REG_CPCCR, 12, 1, 4, 22, -1, -1, 0, + jz4760_cgu_cpccr_div_table, + }, + }, + [JZ4760_CLK_PCLK] = { + "pclk", CGU_CLK_DIV, + .parents = { JZ4760_CLK_PLL0, }, + .div = { + CGU_REG_CPCCR, 8, 1, 4, 22, -1, -1, 0, + jz4760_cgu_cpccr_div_table, + }, + }, + + /* Divided clocks */ + + [JZ4760_CLK_PLL0_HALF] = { + "pll0_half", CGU_CLK_DIV, + .parents = { JZ4760_CLK_PLL0 }, + .div = { + CGU_REG_CPCCR, 21, 1, 1, 22, -1, -1, 0, + jz4760_cgu_pll_half_div_table, + }, + }, + + /* Those divided clocks can connect to PLL0 or PLL1 */ + + [JZ4760_CLK_UHC] = { + "uhc", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX, + .parents = { JZ4760_CLK_PLL0_HALF, JZ4760_CLK_PLL1, }, + .mux = { CGU_REG_UHCCDR, 31, 1 }, + .div = { CGU_REG_UHCCDR, 0, 1, 4, -1, -1, -1 }, + .gate = { CGU_REG_CLKGR0, 24 }, + }, + [JZ4760_CLK_GPU] = { + "gpu", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX, + .parents = { JZ4760_CLK_PLL0_HALF, JZ4760_CLK_PLL1, }, + .mux = { CGU_REG_GPUCDR, 31, 1 }, + .div = { CGU_REG_GPUCDR, 0, 1, 3, -1, -1, -1 }, + .gate = { CGU_REG_CLKGR1, 9 }, + }, + [JZ4760_CLK_LPCLK_DIV] = { + "lpclk_div", CGU_CLK_DIV | CGU_CLK_MUX, + .parents = { JZ4760_CLK_PLL0_HALF, JZ4760_CLK_PLL1, }, + .mux = { CGU_REG_LPCDR, 29, 1 }, + .div = { CGU_REG_LPCDR, 0, 1, 11, -1, -1, -1 }, + }, + [JZ4760_CLK_TVE] = { + "tve", CGU_CLK_GATE | CGU_CLK_MUX, + .parents = { JZ4760_CLK_LPCLK_DIV, JZ4760_CLK_EXT, }, + .mux = { CGU_REG_LPCDR, 31, 1 }, + .gate = { CGU_REG_CLKGR0, 27 }, + }, + [JZ4760_CLK_LPCLK] = { + "lpclk", CGU_CLK_GATE | CGU_CLK_MUX, + .parents = { JZ4760_CLK_LPCLK_DIV, JZ4760_CLK_TVE, }, + .mux = { CGU_REG_LPCDR, 30, 1 }, + .gate = { CGU_REG_CLKGR0, 28 }, + }, + [JZ4760_CLK_GPS] = { + "gps", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX, + .parents = { JZ4760_CLK_PLL0_HALF, JZ4760_CLK_PLL1, }, + .mux = { CGU_REG_GPSCDR, 31, 1 }, + .div = { CGU_REG_GPSCDR, 0, 1, 4, -1, -1, -1 }, + .gate = { CGU_REG_CLKGR0, 22 }, + }, + + /* Those divided clocks can connect to EXT, PLL0 or PLL1 */ + + [JZ4760_CLK_PCM] = { + "pcm", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX, + .parents = { JZ4760_CLK_EXT, -1, + JZ4760_CLK_PLL0_HALF, JZ4760_CLK_PLL1 }, + .mux = { CGU_REG_PCMCDR, 30, 2 }, + .div = { CGU_REG_PCMCDR, 0, 1, 9, -1, -1, -1, BIT(0) }, + .gate = { CGU_REG_CLKGR1, 8 }, + }, + [JZ4760_CLK_I2S] = { + "i2s", CGU_CLK_DIV | CGU_CLK_MUX, + .parents = { JZ4760_CLK_EXT, -1, + JZ4760_CLK_PLL0_HALF, JZ4760_CLK_PLL1 }, + .mux = { CGU_REG_I2SCDR, 30, 2 }, + .div = { CGU_REG_I2SCDR, 0, 1, 9, -1, -1, -1, BIT(0) }, + }, + [JZ4760_CLK_OTG] = { + "usb", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX, + .parents = { JZ4760_CLK_EXT, -1, + JZ4760_CLK_PLL0_HALF, JZ4760_CLK_PLL1 }, + .mux = { CGU_REG_USBCDR, 30, 2 }, + .div = { CGU_REG_USBCDR, 0, 1, 8, -1, -1, -1 }, + .gate = { CGU_REG_CLKGR0, 2 }, + }, + + /* Those divided clocks can connect to EXT or PLL0 */ + [JZ4760_CLK_MMC_MUX] = { + "mmc_mux", CGU_CLK_MUX | CGU_CLK_DIV, + .parents = { JZ4760_CLK_EXT, JZ4760_CLK_PLL0_HALF, }, + .mux = { CGU_REG_MSCCDR, 31, 1 }, + .div = { CGU_REG_MSCCDR, 0, 1, 6, -1, -1, -1, BIT(0) }, + }, + [JZ4760_CLK_SSI_MUX] = { + "ssi_mux", CGU_CLK_DIV | CGU_CLK_MUX, + .parents = { JZ4760_CLK_EXT, JZ4760_CLK_PLL0_HALF, }, + .mux = { CGU_REG_SSICDR, 31, 1 }, + .div = { CGU_REG_SSICDR, 0, 1, 6, -1, -1, -1, BIT(0) }, + }, + + /* These divided clock can connect to PLL0 only */ + [JZ4760_CLK_CIM] = { + "cim", CGU_CLK_DIV | CGU_CLK_GATE, + .parents = { JZ4760_CLK_PLL0_HALF }, + .div = { CGU_REG_CIMCDR, 0, 1, 8, -1, -1, -1 }, + .gate = { CGU_REG_CLKGR0, 26 }, + }, + + /* Gate-only clocks */ + + [JZ4760_CLK_SSI0] = { + "ssi0", CGU_CLK_GATE, + .parents = { JZ4760_CLK_SSI_MUX, }, + .gate = { CGU_REG_CLKGR0, 4 }, + }, + [JZ4760_CLK_SSI1] = { + "ssi1", CGU_CLK_GATE, + .parents = { JZ4760_CLK_SSI_MUX, }, + .gate = { CGU_REG_CLKGR0, 19 }, + }, + [JZ4760_CLK_SSI2] = { + "ssi2", CGU_CLK_GATE, + .parents = { JZ4760_CLK_SSI_MUX, }, + .gate = { CGU_REG_CLKGR0, 20 }, + }, + [JZ4760_CLK_DMA] = { + "dma", CGU_CLK_GATE, + .parents = { JZ4760_CLK_H2CLK, }, + .gate = { CGU_REG_CLKGR0, 21 }, + }, + [JZ4760_CLK_I2C0] = { + "i2c0", CGU_CLK_GATE, + .parents = { JZ4760_CLK_EXT, }, + .gate = { CGU_REG_CLKGR0, 5 }, + }, + [JZ4760_CLK_I2C1] = { + "i2c1", CGU_CLK_GATE, + .parents = { JZ4760_CLK_EXT, }, + .gate = { CGU_REG_CLKGR0, 6 }, + }, + [JZ4760_CLK_UART0] = { + "uart0", CGU_CLK_GATE, + .parents = { JZ4760_CLK_EXT, }, + .gate = { CGU_REG_CLKGR0, 15 }, + }, + [JZ4760_CLK_UART1] = { + "uart1", CGU_CLK_GATE, + .parents = { JZ4760_CLK_EXT, }, + .gate = { CGU_REG_CLKGR0, 16 }, + }, + [JZ4760_CLK_UART2] = { + "uart2", CGU_CLK_GATE, + .parents = { JZ4760_CLK_EXT, }, + .gate = { CGU_REG_CLKGR0, 17 }, + }, + [JZ4760_CLK_UART3] = { + "uart3", CGU_CLK_GATE, + .parents = { JZ4760_CLK_EXT, }, + .gate = { CGU_REG_CLKGR0, 18 }, + }, + [JZ4760_CLK_IPU] = { + "ipu", CGU_CLK_GATE, + .parents = { JZ4760_CLK_HCLK, }, + .gate = { CGU_REG_CLKGR0, 29 }, + }, + [JZ4760_CLK_ADC] = { + "adc", CGU_CLK_GATE, + .parents = { JZ4760_CLK_EXT, }, + .gate = { CGU_REG_CLKGR0, 14 }, + }, + [JZ4760_CLK_AIC] = { + "aic", CGU_CLK_GATE, + .parents = { JZ4760_CLK_EXT, }, + .gate = { CGU_REG_CLKGR0, 8 }, + }, + [JZ4760_CLK_VPU] = { + "vpu", CGU_CLK_GATE, + .parents = { JZ4760_CLK_HCLK, }, + .gate = { CGU_REG_LCR, 30, false, 150 }, + }, + [JZ4760_CLK_MMC0] = { + "mmc0", CGU_CLK_GATE, + .parents = { JZ4760_CLK_MMC_MUX, }, + .gate = { CGU_REG_CLKGR0, 3 }, + }, + [JZ4760_CLK_MMC1] = { + "mmc1", CGU_CLK_GATE, + .parents = { JZ4760_CLK_MMC_MUX, }, + .gate = { CGU_REG_CLKGR0, 11 }, + }, + [JZ4760_CLK_MMC2] = { + "mmc2", CGU_CLK_GATE, + .parents = { JZ4760_CLK_MMC_MUX, }, + .gate = { CGU_REG_CLKGR0, 12 }, + }, + [JZ4760_CLK_UHC_PHY] = { + "uhc_phy", CGU_CLK_GATE, + .parents = { JZ4760_CLK_UHC, }, + .gate = { CGU_REG_OPCR, 5 }, + }, + [JZ4760_CLK_OTG_PHY] = { + "usb_phy", CGU_CLK_GATE, + .parents = { JZ4760_CLK_OTG }, + .gate = { CGU_REG_OPCR, 7, true, 50 }, + }, + + /* Custom clocks */ + [JZ4760_CLK_EXT512] = { + "ext/512", CGU_CLK_FIXDIV, + .parents = { JZ4760_CLK_EXT }, + .fixdiv = { 512 }, + }, + [JZ4760_CLK_RTC] = { + "rtc", CGU_CLK_MUX, + .parents = { JZ4760_CLK_EXT512, JZ4760_CLK_OSC32K, }, + .mux = { CGU_REG_OPCR, 2, 1}, + }, +}; + +static void __init jz4760_cgu_init(struct device_node *np) +{ + struct ingenic_cgu *cgu; + int retval; + + cgu = ingenic_cgu_new(jz4760_cgu_clocks, + ARRAY_SIZE(jz4760_cgu_clocks), np); + if (!cgu) { + pr_err("%s: failed to initialise CGU\n", __func__); + return; + } + + retval = ingenic_cgu_register_clocks(cgu); + if (retval) + pr_err("%s: failed to register CGU Clocks\n", __func__); + + ingenic_cgu_register_syscore_ops(cgu); +} + +/* We only probe via devicetree, no need for a platform driver */ +CLK_OF_DECLARE_DRIVER(jz4760_cgu, "ingenic,jz4760-cgu", jz4760_cgu_init); + +/* JZ4760B has some small differences, but we don't implement them. */ +CLK_OF_DECLARE_DRIVER(jz4760b_cgu, "ingenic,jz4760b-cgu", jz4760_cgu_init); diff --git a/drivers/clk/ingenic/tcu.c b/drivers/clk/ingenic/tcu.c index 9382dc3aa27e..77acfbeb4830 100644 --- a/drivers/clk/ingenic/tcu.c +++ b/drivers/clk/ingenic/tcu.c @@ -326,6 +326,7 @@ static const struct ingenic_soc_info x1000_soc_info = { static const struct of_device_id __maybe_unused ingenic_tcu_of_match[] __initconst = { { .compatible = "ingenic,jz4740-tcu", .data = &jz4740_soc_info, }, { .compatible = "ingenic,jz4725b-tcu", .data = &jz4725b_soc_info, }, + { .compatible = "ingenic,jz4760-tcu", .data = &jz4770_soc_info, }, { .compatible = "ingenic,jz4770-tcu", .data = &jz4770_soc_info, }, { .compatible = "ingenic,x1000-tcu", .data = &x1000_soc_info, }, { /* sentinel */ } @@ -477,5 +478,6 @@ static void __init ingenic_tcu_init(struct device_node *np) CLK_OF_DECLARE_DRIVER(jz4740_cgu, "ingenic,jz4740-tcu", ingenic_tcu_init); CLK_OF_DECLARE_DRIVER(jz4725b_cgu, "ingenic,jz4725b-tcu", ingenic_tcu_init); +CLK_OF_DECLARE_DRIVER(jz4760_cgu, "ingenic,jz4760-tcu", ingenic_tcu_init); CLK_OF_DECLARE_DRIVER(jz4770_cgu, "ingenic,jz4770-tcu", ingenic_tcu_init); CLK_OF_DECLARE_DRIVER(x1000_cgu, "ingenic,x1000-tcu", ingenic_tcu_init); diff --git a/include/dt-bindings/clock/jz4760-cgu.h b/include/dt-bindings/clock/jz4760-cgu.h new file mode 100644 index 000000000000..4bb2e19c4743 --- /dev/null +++ b/include/dt-bindings/clock/jz4760-cgu.h @@ -0,0 +1,54 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * This header provides clock numbers for the ingenic,jz4760-cgu DT binding. + */ + +#ifndef __DT_BINDINGS_CLOCK_JZ4760_CGU_H__ +#define __DT_BINDINGS_CLOCK_JZ4760_CGU_H__ + +#define JZ4760_CLK_EXT 0 +#define JZ4760_CLK_OSC32K 1 +#define JZ4760_CLK_PLL0 2 +#define JZ4760_CLK_PLL0_HALF 3 +#define JZ4760_CLK_PLL1 4 +#define JZ4760_CLK_CCLK 5 +#define JZ4760_CLK_HCLK 6 +#define JZ4760_CLK_SCLK 7 +#define JZ4760_CLK_H2CLK 8 +#define JZ4760_CLK_MCLK 9 +#define JZ4760_CLK_PCLK 10 +#define JZ4760_CLK_MMC_MUX 11 +#define JZ4760_CLK_MMC0 12 +#define JZ4760_CLK_MMC1 13 +#define JZ4760_CLK_MMC2 14 +#define JZ4760_CLK_CIM 15 +#define JZ4760_CLK_UHC 16 +#define JZ4760_CLK_GPU 17 +#define JZ4760_CLK_GPS 18 +#define JZ4760_CLK_SSI_MUX 19 +#define JZ4760_CLK_PCM 20 +#define JZ4760_CLK_I2S 21 +#define JZ4760_CLK_OTG 22 +#define JZ4760_CLK_SSI0 23 +#define JZ4760_CLK_SSI1 24 +#define JZ4760_CLK_SSI2 25 +#define JZ4760_CLK_DMA 26 +#define JZ4760_CLK_I2C0 27 +#define JZ4760_CLK_I2C1 28 +#define JZ4760_CLK_UART0 29 +#define JZ4760_CLK_UART1 30 +#define JZ4760_CLK_UART2 31 +#define JZ4760_CLK_UART3 32 +#define JZ4760_CLK_IPU 33 +#define JZ4760_CLK_ADC 34 +#define JZ4760_CLK_AIC 35 +#define JZ4760_CLK_VPU 36 +#define JZ4760_CLK_UHC_PHY 37 +#define JZ4760_CLK_OTG_PHY 38 +#define JZ4760_CLK_EXT512 39 +#define JZ4760_CLK_RTC 40 +#define JZ4760_CLK_LPCLK_DIV 41 +#define JZ4760_CLK_TVE 42 +#define JZ4760_CLK_LPCLK 43 + +#endif /* __DT_BINDINGS_CLOCK_JZ4760_CGU_H__ */ From b5a87e692c044c42bf9309cde4bc455bec246c60 Mon Sep 17 00:00:00 2001 From: Alain Volmat Date: Wed, 31 Mar 2021 22:16:26 +0200 Subject: [PATCH 131/161] clk: st: clkgen-pll: remove unused variable of struct clkgen_pll ODF field within the struct clkgen_pll is never used by the driver and can thus be removed. Signed-off-by: Alain Volmat Reviewed-by: Patrice Chotard Link: https://lore.kernel.org/r/20210331201632.24530-2-avolmat@me.com Signed-off-by: Stephen Boyd --- drivers/clk/st/clkgen-pll.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/clk/st/clkgen-pll.c b/drivers/clk/st/clkgen-pll.c index 119c5b33080c..f6c56ca90c7d 100644 --- a/drivers/clk/st/clkgen-pll.c +++ b/drivers/clk/st/clkgen-pll.c @@ -146,7 +146,6 @@ struct clkgen_pll { u32 ndiv; u32 idf; - u32 odf; u32 cp; }; From 574dffc2995cc96f1c13e802576d1fb146ebd387 Mon Sep 17 00:00:00 2001 From: Alain Volmat Date: Wed, 31 Mar 2021 22:16:27 +0200 Subject: [PATCH 132/161] clk: st: flexgen: embed soc clock outputs within compatible data In order to avoid relying on the old style description via the DT clock-output-names, add compatible data describing the flexgen outputs clocks for all STiH407/STiH410 and STiH418 SOCs. In order to ease transition between the two methods, this commit introduce the new compatible without removing the old method. Once DTs will be fixed, the method relying on DT clock-output-names will be removed from this driver as well as old compatibles. Signed-off-by: Alain Volmat Reviewed-by: Patrice Chotard Link: https://lore.kernel.org/r/20210331201632.24530-3-avolmat@me.com Signed-off-by: Stephen Boyd --- drivers/clk/st/clk-flexgen.c | 367 +++++++++++++++++++++++++++++++++-- 1 file changed, 353 insertions(+), 14 deletions(-) diff --git a/drivers/clk/st/clk-flexgen.c b/drivers/clk/st/clk-flexgen.c index 55873d4b7603..7ae4f656191e 100644 --- a/drivers/clk/st/clk-flexgen.c +++ b/drivers/clk/st/clk-flexgen.c @@ -16,9 +16,16 @@ #include #include +struct clkgen_clk_out { + const char *name; + unsigned long flags; +}; + struct clkgen_data { unsigned long flags; bool mode; + const struct clkgen_clk_out *outputs; + const unsigned int outputs_nb; }; struct flexgen { @@ -295,6 +302,290 @@ static const struct clkgen_data clkgen_video = { .mode = 1, }; +static const struct clkgen_clk_out clkgen_stih407_a0_clk_out[] = { + /* This clk needs to be on so that memory interface is accessible */ + { .name = "clk-ic-lmi0", .flags = CLK_IS_CRITICAL }, +}; + +static const struct clkgen_data clkgen_stih407_a0 = { + .outputs = clkgen_stih407_a0_clk_out, + .outputs_nb = ARRAY_SIZE(clkgen_stih407_a0_clk_out), +}; + +static const struct clkgen_clk_out clkgen_stih410_a0_clk_out[] = { + /* Those clks need to be on so that memory interface is accessible */ + { .name = "clk-ic-lmi0", .flags = CLK_IS_CRITICAL }, + { .name = "clk-ic-lmi1", .flags = CLK_IS_CRITICAL }, +}; + +static const struct clkgen_data clkgen_stih410_a0 = { + .outputs = clkgen_stih410_a0_clk_out, + .outputs_nb = ARRAY_SIZE(clkgen_stih410_a0_clk_out), +}; + +static const struct clkgen_clk_out clkgen_stih407_c0_clk_out[] = { + { .name = "clk-icn-gpu", }, + { .name = "clk-fdma", }, + { .name = "clk-nand", }, + { .name = "clk-hva", }, + { .name = "clk-proc-stfe", }, + { .name = "clk-proc-tp", }, + { .name = "clk-rx-icn-dmu", }, + { .name = "clk-rx-icn-hva", }, + /* This clk needs to be on to keep bus interconnect alive */ + { .name = "clk-icn-cpu", .flags = CLK_IS_CRITICAL }, + /* This clk needs to be on to keep bus interconnect alive */ + { .name = "clk-tx-icn-dmu", .flags = CLK_IS_CRITICAL }, + { .name = "clk-mmc-0", }, + { .name = "clk-mmc-1", }, + { .name = "clk-jpegdec", }, + /* This clk needs to be on to keep A9 running */ + { .name = "clk-ext2fa9", .flags = CLK_IS_CRITICAL }, + { .name = "clk-ic-bdisp-0", }, + { .name = "clk-ic-bdisp-1", }, + { .name = "clk-pp-dmu", }, + { .name = "clk-vid-dmu", }, + { .name = "clk-dss-lpc", }, + { .name = "clk-st231-aud-0", }, + { .name = "clk-st231-gp-1", }, + { .name = "clk-st231-dmu", }, + /* This clk needs to be on to keep bus interconnect alive */ + { .name = "clk-icn-lmi", .flags = CLK_IS_CRITICAL }, + { .name = "clk-tx-icn-disp-1", }, + /* This clk needs to be on to keep bus interconnect alive */ + { .name = "clk-icn-sbc", .flags = CLK_IS_CRITICAL }, + { .name = "clk-stfe-frc2", }, + { .name = "clk-eth-phy", }, + { .name = "clk-eth-ref-phyclk", }, + { .name = "clk-flash-promip", }, + { .name = "clk-main-disp", }, + { .name = "clk-aux-disp", }, + { .name = "clk-compo-dvp", }, +}; + +static const struct clkgen_data clkgen_stih407_c0 = { + .outputs = clkgen_stih407_c0_clk_out, + .outputs_nb = ARRAY_SIZE(clkgen_stih407_c0_clk_out), +}; + +static const struct clkgen_clk_out clkgen_stih410_c0_clk_out[] = { + { .name = "clk-icn-gpu", }, + { .name = "clk-fdma", }, + { .name = "clk-nand", }, + { .name = "clk-hva", }, + { .name = "clk-proc-stfe", }, + { .name = "clk-proc-tp", }, + { .name = "clk-rx-icn-dmu", }, + { .name = "clk-rx-icn-hva", }, + /* This clk needs to be on to keep bus interconnect alive */ + { .name = "clk-icn-cpu", .flags = CLK_IS_CRITICAL }, + /* This clk needs to be on to keep bus interconnect alive */ + { .name = "clk-tx-icn-dmu", .flags = CLK_IS_CRITICAL }, + { .name = "clk-mmc-0", }, + { .name = "clk-mmc-1", }, + { .name = "clk-jpegdec", }, + /* This clk needs to be on to keep A9 running */ + { .name = "clk-ext2fa9", .flags = CLK_IS_CRITICAL }, + { .name = "clk-ic-bdisp-0", }, + { .name = "clk-ic-bdisp-1", }, + { .name = "clk-pp-dmu", }, + { .name = "clk-vid-dmu", }, + { .name = "clk-dss-lpc", }, + { .name = "clk-st231-aud-0", }, + { .name = "clk-st231-gp-1", }, + { .name = "clk-st231-dmu", }, + /* This clk needs to be on to keep bus interconnect alive */ + { .name = "clk-icn-lmi", .flags = CLK_IS_CRITICAL }, + { .name = "clk-tx-icn-disp-1", }, + /* This clk needs to be on to keep bus interconnect alive */ + { .name = "clk-icn-sbc", .flags = CLK_IS_CRITICAL }, + { .name = "clk-stfe-frc2", }, + { .name = "clk-eth-phy", }, + { .name = "clk-eth-ref-phyclk", }, + { .name = "clk-flash-promip", }, + { .name = "clk-main-disp", }, + { .name = "clk-aux-disp", }, + { .name = "clk-compo-dvp", }, + { .name = "clk-tx-icn-hades", }, + { .name = "clk-rx-icn-hades", }, + /* This clk needs to be on to keep bus interconnect alive */ + { .name = "clk-icn-reg-16", .flags = CLK_IS_CRITICAL }, + { .name = "clk-pp-hades", }, + { .name = "clk-clust-hades", }, + { .name = "clk-hwpe-hades", }, + { .name = "clk-fc-hades", }, +}; + +static const struct clkgen_data clkgen_stih410_c0 = { + .outputs = clkgen_stih410_c0_clk_out, + .outputs_nb = ARRAY_SIZE(clkgen_stih410_c0_clk_out), +}; + +static const struct clkgen_clk_out clkgen_stih418_c0_clk_out[] = { + { .name = "clk-icn-gpu", }, + { .name = "clk-fdma", }, + { .name = "clk-nand", }, + { .name = "clk-hva", }, + { .name = "clk-proc-stfe", }, + { .name = "clk-tp", }, + /* This clk needs to be on to keep bus interconnect alive */ + { .name = "clk-rx-icn-dmu", .flags = CLK_IS_CRITICAL }, + /* This clk needs to be on to keep bus interconnect alive */ + { .name = "clk-rx-icn-hva", .flags = CLK_IS_CRITICAL }, + { .name = "clk-icn-cpu", .flags = CLK_IS_CRITICAL }, + /* This clk needs to be on to keep bus interconnect alive */ + { .name = "clk-tx-icn-dmu", .flags = CLK_IS_CRITICAL }, + { .name = "clk-mmc-0", }, + { .name = "clk-mmc-1", }, + { .name = "clk-jpegdec", }, + /* This clk needs to be on to keep bus interconnect alive */ + { .name = "clk-icn-reg", .flags = CLK_IS_CRITICAL }, + { .name = "clk-proc-bdisp-0", }, + { .name = "clk-proc-bdisp-1", }, + { .name = "clk-pp-dmu", }, + { .name = "clk-vid-dmu", }, + { .name = "clk-dss-lpc", }, + { .name = "clk-st231-aud-0", }, + { .name = "clk-st231-gp-1", }, + { .name = "clk-st231-dmu", }, + /* This clk needs to be on to keep bus interconnect alive */ + { .name = "clk-icn-lmi", .flags = CLK_IS_CRITICAL }, + /* This clk needs to be on to keep bus interconnect alive */ + { .name = "clk-tx-icn-1", .flags = CLK_IS_CRITICAL }, + /* This clk needs to be on to keep bus interconnect alive */ + { .name = "clk-icn-sbc", .flags = CLK_IS_CRITICAL }, + { .name = "clk-stfe-frc2", }, + { .name = "clk-eth-phyref", }, + { .name = "clk-eth-ref-phyclk", }, + { .name = "clk-flash-promip", }, + { .name = "clk-main-disp", }, + { .name = "clk-aux-disp", }, + { .name = "clk-compo-dvp", }, + /* This clk needs to be on to keep bus interconnect alive */ + { .name = "clk-tx-icn-hades", .flags = CLK_IS_CRITICAL }, + /* This clk needs to be on to keep bus interconnect alive */ + { .name = "clk-rx-icn-hades", .flags = CLK_IS_CRITICAL }, + /* This clk needs to be on to keep bus interconnect alive */ + { .name = "clk-icn-reg-16", .flags = CLK_IS_CRITICAL }, + { .name = "clk-pp-hevc", }, + { .name = "clk-clust-hevc", }, + { .name = "clk-hwpe-hevc", }, + { .name = "clk-fc-hevc", }, + { .name = "clk-proc-mixer", }, + { .name = "clk-proc-sc", }, + { .name = "clk-avsp-hevc", }, +}; + +static const struct clkgen_data clkgen_stih418_c0 = { + .outputs = clkgen_stih418_c0_clk_out, + .outputs_nb = ARRAY_SIZE(clkgen_stih418_c0_clk_out), +}; + +static const struct clkgen_clk_out clkgen_stih407_d0_clk_out[] = { + { .name = "clk-pcm-0", }, + { .name = "clk-pcm-1", }, + { .name = "clk-pcm-2", }, + { .name = "clk-spdiff", }, +}; + +static const struct clkgen_data clkgen_stih407_d0 = { + .flags = CLK_SET_RATE_PARENT, + .outputs = clkgen_stih407_d0_clk_out, + .outputs_nb = ARRAY_SIZE(clkgen_stih407_d0_clk_out), +}; + +static const struct clkgen_clk_out clkgen_stih410_d0_clk_out[] = { + { .name = "clk-pcm-0", }, + { .name = "clk-pcm-1", }, + { .name = "clk-pcm-2", }, + { .name = "clk-spdiff", }, + { .name = "clk-pcmr10-master", }, + { .name = "clk-usb2-phy", }, +}; + +static const struct clkgen_data clkgen_stih410_d0 = { + .flags = CLK_SET_RATE_PARENT, + .outputs = clkgen_stih410_d0_clk_out, + .outputs_nb = ARRAY_SIZE(clkgen_stih410_d0_clk_out), +}; + +static const struct clkgen_clk_out clkgen_stih407_d2_clk_out[] = { + { .name = "clk-pix-main-disp", }, + { .name = "clk-pix-pip", }, + { .name = "clk-pix-gdp1", }, + { .name = "clk-pix-gdp2", }, + { .name = "clk-pix-gdp3", }, + { .name = "clk-pix-gdp4", }, + { .name = "clk-pix-aux-disp", }, + { .name = "clk-denc", }, + { .name = "clk-pix-hddac", }, + { .name = "clk-hddac", }, + { .name = "clk-sddac", }, + { .name = "clk-pix-dvo", }, + { .name = "clk-dvo", }, + { .name = "clk-pix-hdmi", }, + { .name = "clk-tmds-hdmi", }, + { .name = "clk-ref-hdmiphy", }, +}; + +static const struct clkgen_data clkgen_stih407_d2 = { + .outputs = clkgen_stih407_d2_clk_out, + .outputs_nb = ARRAY_SIZE(clkgen_stih407_d2_clk_out), + .flags = CLK_SET_RATE_PARENT, + .mode = 1, +}; + +static const struct clkgen_clk_out clkgen_stih418_d2_clk_out[] = { + { .name = "clk-pix-main-disp", }, + { .name = "", }, + { .name = "", }, + { .name = "", }, + { .name = "", }, + { .name = "clk-tmds-hdmi-div2", }, + { .name = "clk-pix-aux-disp", }, + { .name = "clk-denc", }, + { .name = "clk-pix-hddac", }, + { .name = "clk-hddac", }, + { .name = "clk-sddac", }, + { .name = "clk-pix-dvo", }, + { .name = "clk-dvo", }, + { .name = "clk-pix-hdmi", }, + { .name = "clk-tmds-hdmi", }, + { .name = "clk-ref-hdmiphy", }, + { .name = "", }, { .name = "", }, { .name = "", }, { .name = "", }, + { .name = "", }, { .name = "", }, { .name = "", }, { .name = "", }, + { .name = "", }, { .name = "", }, { .name = "", }, { .name = "", }, + { .name = "", }, { .name = "", }, { .name = "", }, { .name = "", }, + { .name = "", }, { .name = "", }, { .name = "", }, { .name = "", }, + { .name = "", }, { .name = "", }, { .name = "", }, { .name = "", }, + { .name = "", }, { .name = "", }, { .name = "", }, { .name = "", }, + { .name = "", }, { .name = "", }, { .name = "", }, + { .name = "clk-vp9", }, +}; + +static const struct clkgen_data clkgen_stih418_d2 = { + .outputs = clkgen_stih418_d2_clk_out, + .outputs_nb = ARRAY_SIZE(clkgen_stih418_d2_clk_out), + .flags = CLK_SET_RATE_PARENT, + .mode = 1, +}; + +static const struct clkgen_clk_out clkgen_stih407_d3_clk_out[] = { + { .name = "clk-stfe-frc1", }, + { .name = "clk-tsout-0", }, + { .name = "clk-tsout-1", }, + { .name = "clk-mchi", }, + { .name = "clk-vsens-compo", }, + { .name = "clk-frc1-remote", }, + { .name = "clk-lpc-0", }, + { .name = "clk-lpc-1", }, +}; + +static const struct clkgen_data clkgen_stih407_d3 = { + .outputs = clkgen_stih407_d3_clk_out, + .outputs_nb = ARRAY_SIZE(clkgen_stih407_d3_clk_out), +}; + static const struct of_device_id flexgen_of_match[] = { { .compatible = "st,flexgen-audio", @@ -304,6 +595,46 @@ static const struct of_device_id flexgen_of_match[] = { .compatible = "st,flexgen-video", .data = &clkgen_video, }, + { + .compatible = "st,flexgen-stih407-a0", + .data = &clkgen_stih407_a0, + }, + { + .compatible = "st,flexgen-stih410-a0", + .data = &clkgen_stih410_a0, + }, + { + .compatible = "st,flexgen-stih407-c0", + .data = &clkgen_stih407_c0, + }, + { + .compatible = "st,flexgen-stih410-c0", + .data = &clkgen_stih410_c0, + }, + { + .compatible = "st,flexgen-stih418-c0", + .data = &clkgen_stih418_c0, + }, + { + .compatible = "st,flexgen-stih407-d0", + .data = &clkgen_stih407_d0, + }, + { + .compatible = "st,flexgen-stih410-d0", + .data = &clkgen_stih410_d0, + }, + { + .compatible = "st,flexgen-stih407-d2", + .data = &clkgen_stih407_d2, + }, + { + .compatible = "st,flexgen-stih418-d2", + .data = &clkgen_stih418_d2, + }, + { + .compatible = "st,flexgen-stih407-d3", + .data = &clkgen_stih407_d3, + }, {} }; @@ -320,6 +651,7 @@ static void __init st_of_flexgen_setup(struct device_node *np) unsigned long flex_flags = 0; int ret; bool clk_mode = 0; + const char *clk_name; pnode = of_get_parent(np); if (!pnode) @@ -347,13 +679,17 @@ static void __init st_of_flexgen_setup(struct device_node *np) if (!clk_data) goto err; - ret = of_property_count_strings(np, "clock-output-names"); - if (ret <= 0) { - pr_err("%s: Failed to get number of output clocks (%d)", - __func__, clk_data->clk_num); - goto err; - } - clk_data->clk_num = ret; + /* First try to get output information from the compatible data */ + if (!data || !data->outputs_nb || !data->outputs) { + ret = of_property_count_strings(np, "clock-output-names"); + if (ret <= 0) { + pr_err("%s: Failed to get number of output clocks (%d)", + __func__, clk_data->clk_num); + goto err; + } + clk_data->clk_num = ret; + } else + clk_data->clk_num = data->outputs_nb; clk_data->clks = kcalloc(clk_data->clk_num, sizeof(struct clk *), GFP_KERNEL); @@ -368,16 +704,19 @@ static void __init st_of_flexgen_setup(struct device_node *np) for (i = 0; i < clk_data->clk_num; i++) { struct clk *clk; - const char *clk_name; - if (of_property_read_string_index(np, "clock-output-names", - i, &clk_name)) { - break; + if (!data || !data->outputs_nb || !data->outputs) { + if (of_property_read_string_index(np, + "clock-output-names", + i, &clk_name)) + break; + flex_flags &= ~CLK_IS_CRITICAL; + of_clk_detect_critical(np, i, &flex_flags); + } else { + clk_name = data->outputs[i].name; + flex_flags = data->flags | data->outputs[i].flags; } - flex_flags &= ~CLK_IS_CRITICAL; - of_clk_detect_critical(np, i, &flex_flags); - /* * If we read an empty clock name then the output is unused */ From fa745c71b8e75e85ce129dd9097a00ac7a9df47f Mon Sep 17 00:00:00 2001 From: Alain Volmat Date: Wed, 31 Mar 2021 22:16:28 +0200 Subject: [PATCH 133/161] dt-bindings: clock: st: flexgen: add new introduced compatible New compatible are added, supporting various kind of flexgen in STiH407, STiH410 and STiH418 Signed-off-by: Alain Volmat Acked-by: Rob Herring Link: https://lore.kernel.org/r/20210331201632.24530-4-avolmat@me.com Signed-off-by: Stephen Boyd --- .../devicetree/bindings/clock/st/st,flexgen.txt | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Documentation/devicetree/bindings/clock/st/st,flexgen.txt b/Documentation/devicetree/bindings/clock/st/st,flexgen.txt index 7ff77fc57dff..55a18939bddd 100644 --- a/Documentation/devicetree/bindings/clock/st/st,flexgen.txt +++ b/Documentation/devicetree/bindings/clock/st/st,flexgen.txt @@ -64,6 +64,16 @@ Required properties: audio use case) "st,flexgen-video", "st,flexgen" (enable clock propagation on parent and activate synchronous mode) + "st,flexgen-stih407-a0" + "st,flexgen-stih410-a0" + "st,flexgen-stih407-c0" + "st,flexgen-stih410-c0" + "st,flexgen-stih418-c0" + "st,flexgen-stih407-d0" + "st,flexgen-stih410-d0" + "st,flexgen-stih407-d2" + "st,flexgen-stih418-d2" + "st,flexgen-stih407-d3" - #clock-cells : from common clock binding; shall be set to 1 (multiple clock outputs). From 92ef1b2beb109c23e2348de8b7ef9d0736fa0b3d Mon Sep 17 00:00:00 2001 From: Alain Volmat Date: Wed, 31 Mar 2021 22:16:29 +0200 Subject: [PATCH 134/161] clk: st: clkgen-pll: embed soc clock outputs within compatible data In order to avoid relying on the old style description via the DT clock-output-names, add compatible data describing the flexgen outputs clocks for all STiH407/STiH410 and STiH418 SOCs. In order to ease transition between the two methods, this commit introduce the new compatible without removing the old method. Once DTs will be fixed, the method relying on DT clock-output-names will be removed from this driver as well as old compatibles. Signed-off-by: Alain Volmat Reviewed-by: Patrice Chotard Link: https://lore.kernel.org/r/20210331201632.24530-5-avolmat@me.com Signed-off-by: Stephen Boyd --- drivers/clk/st/clkgen-pll.c | 120 +++++++++++++++++++++++++++++++----- 1 file changed, 106 insertions(+), 14 deletions(-) diff --git a/drivers/clk/st/clkgen-pll.c b/drivers/clk/st/clkgen-pll.c index f6c56ca90c7d..b36e4d803636 100644 --- a/drivers/clk/st/clkgen-pll.c +++ b/drivers/clk/st/clkgen-pll.c @@ -57,6 +57,17 @@ struct clkgen_pll_data { const struct clk_ops *ops; }; +struct clkgen_clk_out { + const char *name; + unsigned long flags; +}; + +struct clkgen_pll_data_clks { + struct clkgen_pll_data *data; + const struct clkgen_clk_out *outputs; +}; + + static const struct clk_ops stm_pll3200c32_ops; static const struct clk_ops stm_pll3200c32_a9_ops; static const struct clk_ops stm_pll4600c28_ops; @@ -74,6 +85,28 @@ static const struct clkgen_pll_data st_pll3200c32_cx_0 = { .ops = &stm_pll3200c32_ops, }; +static const struct clkgen_pll_data_clks st_pll3200c32_cx_0_legacy_data = { + .data = (struct clkgen_pll_data *)&st_pll3200c32_cx_0, +}; + +static const struct clkgen_clk_out st_pll3200c32_ax_0_clks[] = { + { .name = "clk-s-a0-pll-odf-0", }, +}; + +static const struct clkgen_pll_data_clks st_pll3200c32_a0_data = { + .data = (struct clkgen_pll_data *)&st_pll3200c32_cx_0, + .outputs = st_pll3200c32_ax_0_clks, +}; + +static const struct clkgen_clk_out st_pll3200c32_cx_0_clks[] = { + { .name = "clk-s-c0-pll0-odf-0", }, +}; + +static const struct clkgen_pll_data_clks st_pll3200c32_c0_data = { + .data = (struct clkgen_pll_data *)&st_pll3200c32_cx_0, + .outputs = st_pll3200c32_cx_0_clks, +}; + static const struct clkgen_pll_data st_pll3200c32_cx_1 = { /* 407 C0 PLL1 */ .pdn_status = CLKGEN_FIELD(0x2c8, 0x1, 8), @@ -87,6 +120,19 @@ static const struct clkgen_pll_data st_pll3200c32_cx_1 = { .ops = &stm_pll3200c32_ops, }; +static const struct clkgen_pll_data_clks st_pll3200c32_cx_1_legacy_data = { + .data = (struct clkgen_pll_data *)&st_pll3200c32_cx_1, +}; + +static const struct clkgen_clk_out st_pll3200c32_cx_1_clks[] = { + { .name = "clk-s-c0-pll1-odf-0", }, +}; + +static const struct clkgen_pll_data_clks st_pll3200c32_c1_data = { + .data = (struct clkgen_pll_data *)&st_pll3200c32_cx_1, + .outputs = st_pll3200c32_cx_1_clks, +}; + static const struct clkgen_pll_data st_pll3200c32_407_a9 = { /* 407 A9 */ .pdn_status = CLKGEN_FIELD(0x1a8, 0x1, 0), @@ -104,6 +150,15 @@ static const struct clkgen_pll_data st_pll3200c32_407_a9 = { .ops = &stm_pll3200c32_a9_ops, }; +static const struct clkgen_clk_out st_pll3200c32_407_a9_clks[] = { + { .name = "clockgen-a9-pll-odf", }, +}; + +static const struct clkgen_pll_data_clks st_pll3200c32_407_a9_data = { + .data = (struct clkgen_pll_data *)&st_pll3200c32_407_a9, + .outputs = st_pll3200c32_407_a9_clks, +}; + static struct clkgen_pll_data st_pll4600c28_418_a9 = { /* 418 A9 */ .pdn_status = CLKGEN_FIELD(0x1a8, 0x1, 0), @@ -120,6 +175,15 @@ static struct clkgen_pll_data st_pll4600c28_418_a9 = { .ops = &stm_pll4600c28_ops, }; +static const struct clkgen_clk_out st_pll4600c28_418_a9_clks[] = { + { .name = "clockgen-a9-pll-odf", }, +}; + +static const struct clkgen_pll_data_clks st_pll4600c28_418_a9_data = { + .data = (struct clkgen_pll_data *)&st_pll4600c28_418_a9, + .outputs = st_pll4600c28_418_a9_clks, +}; + /** * DOC: Clock Generated by PLL, rate set and enabled by bootloader * @@ -684,7 +748,7 @@ static struct clk * __init clkgen_odf_register(const char *parent_name, static void __init clkgen_c32_pll_setup(struct device_node *np, - struct clkgen_pll_data *data) + struct clkgen_pll_data_clks *datac) { struct clk *clk; const char *parent_name, *pll_name; @@ -704,14 +768,14 @@ static void __init clkgen_c32_pll_setup(struct device_node *np, of_clk_detect_critical(np, 0, &pll_flags); - clk = clkgen_pll_register(parent_name, data, pll_base, pll_flags, - np->name, data->lock); + clk = clkgen_pll_register(parent_name, datac->data, pll_base, pll_flags, + np->name, datac->data->lock); if (IS_ERR(clk)) return; pll_name = __clk_get_name(clk); - num_odfs = data->num_odfs; + num_odfs = datac->data->num_odfs; clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL); if (!clk_data) @@ -729,14 +793,21 @@ static void __init clkgen_c32_pll_setup(struct device_node *np, const char *clk_name; unsigned long odf_flags = 0; - if (of_property_read_string_index(np, "clock-output-names", - odf, &clk_name)) - return; + if (datac->outputs) { + clk_name = datac->outputs[odf].name; + odf_flags = datac->outputs[odf].flags; + } else { + if (of_property_read_string_index(np, + "clock-output-names", + odf, &clk_name)) + return; - of_clk_detect_critical(np, odf, &odf_flags); + of_clk_detect_critical(np, odf, &odf_flags); + } - clk = clkgen_odf_register(pll_name, pll_base, data, odf_flags, - odf, &clkgena_c32_odf_lock, clk_name); + clk = clkgen_odf_register(pll_name, pll_base, datac->data, + odf_flags, odf, &clkgena_c32_odf_lock, + clk_name); if (IS_ERR(clk)) goto err; @@ -754,27 +825,48 @@ err: static void __init clkgen_c32_pll0_setup(struct device_node *np) { clkgen_c32_pll_setup(np, - (struct clkgen_pll_data *) &st_pll3200c32_cx_0); + (struct clkgen_pll_data_clks *) &st_pll3200c32_cx_0_legacy_data); } CLK_OF_DECLARE(c32_pll0, "st,clkgen-pll0", clkgen_c32_pll0_setup); +static void __init clkgen_c32_pll0_a0_setup(struct device_node *np) +{ + clkgen_c32_pll_setup(np, + (struct clkgen_pll_data_clks *) &st_pll3200c32_a0_data); +} +CLK_OF_DECLARE(c32_pll0_a0, "st,clkgen-pll0-a0", clkgen_c32_pll0_a0_setup); + +static void __init clkgen_c32_pll0_c0_setup(struct device_node *np) +{ + clkgen_c32_pll_setup(np, + (struct clkgen_pll_data_clks *) &st_pll3200c32_c0_data); +} +CLK_OF_DECLARE(c32_pll0_c0, "st,clkgen-pll0-c0", clkgen_c32_pll0_c0_setup); + static void __init clkgen_c32_pll1_setup(struct device_node *np) { clkgen_c32_pll_setup(np, - (struct clkgen_pll_data *) &st_pll3200c32_cx_1); + (struct clkgen_pll_data_clks *) &st_pll3200c32_cx_1_legacy_data); } CLK_OF_DECLARE(c32_pll1, "st,clkgen-pll1", clkgen_c32_pll1_setup); +static void __init clkgen_c32_pll1_c0_setup(struct device_node *np) +{ + clkgen_c32_pll_setup(np, + (struct clkgen_pll_data_clks *) &st_pll3200c32_c1_data); +} +CLK_OF_DECLARE(c32_pll1_c0, "st,clkgen-pll1-c0", clkgen_c32_pll1_c0_setup); + static void __init clkgen_c32_plla9_setup(struct device_node *np) { clkgen_c32_pll_setup(np, - (struct clkgen_pll_data *) &st_pll3200c32_407_a9); + (struct clkgen_pll_data_clks *) &st_pll3200c32_407_a9_data); } CLK_OF_DECLARE(c32_plla9, "st,stih407-clkgen-plla9", clkgen_c32_plla9_setup); static void __init clkgen_c28_plla9_setup(struct device_node *np) { clkgen_c32_pll_setup(np, - (struct clkgen_pll_data *) &st_pll4600c28_418_a9); + (struct clkgen_pll_data_clks *) &st_pll4600c28_418_a9_data); } CLK_OF_DECLARE(c28_plla9, "st,stih418-clkgen-plla9", clkgen_c28_plla9_setup); From 8df309e9c5e173eea83909d5575eab89965541af Mon Sep 17 00:00:00 2001 From: Alain Volmat Date: Wed, 31 Mar 2021 22:16:30 +0200 Subject: [PATCH 135/161] dt-bindings: clock: st: clkgen-pll: add new introduced compatible New compatible are added, supporting various kind of clkgen-pll used for STiH407, STiH410 and STiH418 Signed-off-by: Alain Volmat Acked-by: Rob Herring Link: https://lore.kernel.org/r/20210331201632.24530-6-avolmat@me.com Signed-off-by: Stephen Boyd --- Documentation/devicetree/bindings/clock/st/st,clkgen-pll.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Documentation/devicetree/bindings/clock/st/st,clkgen-pll.txt b/Documentation/devicetree/bindings/clock/st/st,clkgen-pll.txt index f207053e0550..d0fa1e02d06d 100644 --- a/Documentation/devicetree/bindings/clock/st/st,clkgen-pll.txt +++ b/Documentation/devicetree/bindings/clock/st/st,clkgen-pll.txt @@ -10,7 +10,10 @@ Required properties: - compatible : shall be: "st,clkgen-pll0" + "st,clkgen-pll0-a0" + "st,clkgen-pll0-c0" "st,clkgen-pll1" + "st,clkgen-pll1-c0" "st,stih407-clkgen-plla9" "st,stih418-clkgen-plla9" From 5dc1a12711b3338e3227f30c5ac15921d719d5c4 Mon Sep 17 00:00:00 2001 From: Alain Volmat Date: Wed, 31 Mar 2021 22:16:31 +0200 Subject: [PATCH 136/161] clk: st: clkgen-fsyn: embed soc clock outputs within compatible data In order to avoid relying on the old style description via the DT clock-output-names, add compatible data describing the flexgen outputs clocks for all STiH407/STiH410 and STiH418 SOCs. In order to ease transition between the two methods, this commit introduce the new compatible without removing the old method. Once DTs will be fixed, the method relying on DT clock-output-names will be removed from this driver as well as old compatibles. Signed-off-by: Alain Volmat Reviewed-by: Patrice Chotard Link: https://lore.kernel.org/r/20210331201632.24530-7-avolmat@me.com Signed-off-by: Stephen Boyd --- drivers/clk/st/clkgen-fsyn.c | 113 +++++++++++++++++++++++++++++++---- 1 file changed, 101 insertions(+), 12 deletions(-) diff --git a/drivers/clk/st/clkgen-fsyn.c b/drivers/clk/st/clkgen-fsyn.c index dd6062e043e0..164285d6be97 100644 --- a/drivers/clk/st/clkgen-fsyn.c +++ b/drivers/clk/st/clkgen-fsyn.c @@ -66,6 +66,16 @@ struct clkgen_quadfs_data { unsigned long *); }; +struct clkgen_clk_out { + const char *name; + unsigned long flags; +}; + +struct clkgen_quadfs_data_clks { + struct clkgen_quadfs_data *data; + const struct clkgen_clk_out *outputs; +}; + static const struct clk_ops st_quadfs_pll_c32_ops; static int clk_fs660c32_dig_get_params(unsigned long input, @@ -115,6 +125,18 @@ static const struct clkgen_quadfs_data st_fs660c32_C = { .get_rate = clk_fs660c32_dig_get_rate, }; +static const struct clkgen_clk_out st_fs660c32_C_clks[] = { + { .name = "clk-s-c0-fs0-ch0", }, + { .name = "clk-s-c0-fs0-ch1", }, + { .name = "clk-s-c0-fs0-ch2", }, + { .name = "clk-s-c0-fs0-ch3", }, +}; + +static const struct clkgen_quadfs_data_clks st_fs660c32_C_data = { + .data = (struct clkgen_quadfs_data *)&st_fs660c32_C, + .outputs = st_fs660c32_C_clks, +}; + static const struct clkgen_quadfs_data st_fs660c32_D = { .nrst_present = true, .nrst = { CLKGEN_FIELD(0x2a0, 0x1, 0), @@ -156,6 +178,46 @@ static const struct clkgen_quadfs_data st_fs660c32_D = { .get_params = clk_fs660c32_dig_get_params, .get_rate = clk_fs660c32_dig_get_rate,}; +static const struct clkgen_quadfs_data_clks st_fs660c32_D_data = { + .data = (struct clkgen_quadfs_data *)&st_fs660c32_D, +}; + +static const struct clkgen_clk_out st_fs660c32_D0_clks[] = { + { .name = "clk-s-d0-fs0-ch0", }, + { .name = "clk-s-d0-fs0-ch1", }, + { .name = "clk-s-d0-fs0-ch2", }, + { .name = "clk-s-d0-fs0-ch3", }, +}; + +static const struct clkgen_quadfs_data_clks st_fs660c32_D0_data = { + .data = (struct clkgen_quadfs_data *)&st_fs660c32_D, + .outputs = st_fs660c32_D0_clks, +}; + +static const struct clkgen_clk_out st_fs660c32_D2_clks[] = { + { .name = "clk-s-d2-fs0-ch0", }, + { .name = "clk-s-d2-fs0-ch1", }, + { .name = "clk-s-d2-fs0-ch2", }, + { .name = "clk-s-d2-fs0-ch3", }, +}; + +static const struct clkgen_quadfs_data_clks st_fs660c32_D2_data = { + .data = (struct clkgen_quadfs_data *)&st_fs660c32_D, + .outputs = st_fs660c32_D2_clks, +}; + +static const struct clkgen_clk_out st_fs660c32_D3_clks[] = { + { .name = "clk-s-d3-fs0-ch0", }, + { .name = "clk-s-d3-fs0-ch1", }, + { .name = "clk-s-d3-fs0-ch2", }, + { .name = "clk-s-d3-fs0-ch3", }, +}; + +static const struct clkgen_quadfs_data_clks st_fs660c32_D3_data = { + .data = (struct clkgen_quadfs_data *)&st_fs660c32_D, + .outputs = st_fs660c32_D3_clks, +}; + /** * DOC: A Frequency Synthesizer that multiples its input clock by a fixed factor * @@ -857,7 +919,7 @@ static struct clk * __init st_clk_register_quadfs_fsynth( static void __init st_of_create_quadfs_fsynths( struct device_node *np, const char *pll_name, - struct clkgen_quadfs_data *quadfs, void __iomem *reg, + struct clkgen_quadfs_data_clks *quadfs, void __iomem *reg, spinlock_t *lock) { struct clk_onecell_data *clk_data; @@ -881,9 +943,15 @@ static void __init st_of_create_quadfs_fsynths( const char *clk_name; unsigned long flags = 0; - if (of_property_read_string_index(np, "clock-output-names", - fschan, &clk_name)) { - break; + if (quadfs->outputs) { + clk_name = quadfs->outputs[fschan].name; + flags = quadfs->outputs[fschan].flags; + } else { + if (of_property_read_string_index(np, + "clock-output-names", + fschan, &clk_name)) + break; + of_clk_detect_critical(np, fschan, &flags); } /* @@ -892,10 +960,8 @@ static void __init st_of_create_quadfs_fsynths( if (*clk_name == '\0') continue; - of_clk_detect_critical(np, fschan, &flags); - clk = st_clk_register_quadfs_fsynth(clk_name, pll_name, - quadfs, reg, fschan, + quadfs->data, reg, fschan, flags, lock); /* @@ -915,7 +981,7 @@ static void __init st_of_create_quadfs_fsynths( } static void __init st_of_quadfs_setup(struct device_node *np, - struct clkgen_quadfs_data *data) + struct clkgen_quadfs_data_clks *datac) { struct clk *clk; const char *pll_name, *clk_parent_name; @@ -940,7 +1006,7 @@ static void __init st_of_quadfs_setup(struct device_node *np, spin_lock_init(lock); - clk = st_clk_register_quadfs_pll(pll_name, clk_parent_name, data, + clk = st_clk_register_quadfs_pll(pll_name, clk_parent_name, datac->data, reg, lock); if (IS_ERR(clk)) goto err_exit; @@ -950,7 +1016,7 @@ static void __init st_of_quadfs_setup(struct device_node *np, __clk_get_name(clk_get_parent(clk)), (unsigned int)clk_get_rate(clk)); - st_of_create_quadfs_fsynths(np, pll_name, data, reg, lock); + st_of_create_quadfs_fsynths(np, pll_name, datac, reg, lock); err_exit: kfree(pll_name); /* No longer need local copy of the PLL name */ @@ -958,12 +1024,35 @@ err_exit: static void __init st_of_quadfs660C_setup(struct device_node *np) { - st_of_quadfs_setup(np, (struct clkgen_quadfs_data *) &st_fs660c32_C); + st_of_quadfs_setup(np, + (struct clkgen_quadfs_data_clks *) &st_fs660c32_C_data); } CLK_OF_DECLARE(quadfs660C, "st,quadfs-pll", st_of_quadfs660C_setup); static void __init st_of_quadfs660D_setup(struct device_node *np) { - st_of_quadfs_setup(np, (struct clkgen_quadfs_data *) &st_fs660c32_D); + st_of_quadfs_setup(np, + (struct clkgen_quadfs_data_clks *) &st_fs660c32_D_data); } CLK_OF_DECLARE(quadfs660D, "st,quadfs", st_of_quadfs660D_setup); + +static void __init st_of_quadfs660D0_setup(struct device_node *np) +{ + st_of_quadfs_setup(np, + (struct clkgen_quadfs_data_clks *) &st_fs660c32_D0_data); +} +CLK_OF_DECLARE(quadfs660D0, "st,quadfs-d0", st_of_quadfs660D0_setup); + +static void __init st_of_quadfs660D2_setup(struct device_node *np) +{ + st_of_quadfs_setup(np, + (struct clkgen_quadfs_data_clks *) &st_fs660c32_D2_data); +} +CLK_OF_DECLARE(quadfs660D2, "st,quadfs-d2", st_of_quadfs660D2_setup); + +static void __init st_of_quadfs660D3_setup(struct device_node *np) +{ + st_of_quadfs_setup(np, + (struct clkgen_quadfs_data_clks *) &st_fs660c32_D3_data); +} +CLK_OF_DECLARE(quadfs660D3, "st,quadfs-d3", st_of_quadfs660D3_setup); From 301035c32e6754c2293d3aba77e6de3e3dded7fe Mon Sep 17 00:00:00 2001 From: Alain Volmat Date: Wed, 31 Mar 2021 22:16:32 +0200 Subject: [PATCH 137/161] dt-bindings: clock: st: clkgen-fsyn: add new introduced compatible New compatible are added, supporting various kind of clkgen-fsyn used for STiH407, STiH410 and STiH418 Signed-off-by: Alain Volmat Link: https://lore.kernel.org/r/20210331201632.24530-8-avolmat@me.com Acked-by: Rob Herring Signed-off-by: Stephen Boyd --- Documentation/devicetree/bindings/clock/st/st,quadfs.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Documentation/devicetree/bindings/clock/st/st,quadfs.txt b/Documentation/devicetree/bindings/clock/st/st,quadfs.txt index d93d49342e60..c4ba2adb0b4f 100644 --- a/Documentation/devicetree/bindings/clock/st/st,quadfs.txt +++ b/Documentation/devicetree/bindings/clock/st/st,quadfs.txt @@ -12,6 +12,9 @@ This binding uses the common clock binding[1]. Required properties: - compatible : shall be: "st,quadfs" + "st,quadfs-d0" + "st,quadfs-d2" + "st,quadfs-d3" "st,quadfs-pll" From 9ba98c08dcb827b84318f9547536423d3afa68ac Mon Sep 17 00:00:00 2001 From: Yu Jiahua Date: Tue, 15 Jun 2021 19:48:26 -0800 Subject: [PATCH 138/161] drivers: ti: remove redundant error message in adpll.c There is a error message within devm_ioremap_resource already, so remove the dev_err call to avoid redundant error message. Signed-off-by: Yu Jiahua Link: https://lore.kernel.org/r/20210616034826.37276-1-yujiahua1@huawei.com Signed-off-by: Stephen Boyd --- drivers/clk/ti/adpll.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/clk/ti/adpll.c b/drivers/clk/ti/adpll.c index bb2f2836dab2..b341cd990be7 100644 --- a/drivers/clk/ti/adpll.c +++ b/drivers/clk/ti/adpll.c @@ -896,11 +896,8 @@ static int ti_adpll_probe(struct platform_device *pdev) d->pa = res->start; d->iobase = devm_ioremap_resource(dev, res); - if (IS_ERR(d->iobase)) { - dev_err(dev, "could not get IO base: %li\n", - PTR_ERR(d->iobase)); + if (IS_ERR(d->iobase)) return PTR_ERR(d->iobase); - } err = ti_adpll_init_registers(d); if (err) From c832bb98d3706f843a207fff44ddf8a6422289a1 Mon Sep 17 00:00:00 2001 From: Robert Hancock Date: Thu, 25 Mar 2021 13:26:35 -0600 Subject: [PATCH 139/161] dt-bindings: clock: clk-si5341: Add new attributes Add new silabs,xaxb-ext-clk and silabs,iovdd-33 properties. Changed vdd-supply on top-level node to optional since it is not actually used by the driver. Removed vdd-supply from output sub-nodes, as it was not supported by the driver and it is not easily possible to support this in that location with the kernel regulator infrastructure. Changed to have vddoX-supply attributes for each output on the top-level device node. Signed-off-by: Robert Hancock Link: https://lore.kernel.org/r/20210325192643.2190069-2-robert.hancock@calian.com Reviewed-by: Rob Herring Signed-off-by: Stephen Boyd --- .../devicetree/bindings/clock/silabs,si5341.txt | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/Documentation/devicetree/bindings/clock/silabs,si5341.txt b/Documentation/devicetree/bindings/clock/silabs,si5341.txt index 504cce3abe46..ce55aba0ce22 100644 --- a/Documentation/devicetree/bindings/clock/silabs,si5341.txt +++ b/Documentation/devicetree/bindings/clock/silabs,si5341.txt @@ -24,9 +24,8 @@ it. The device type, speed grade and revision are determined runtime by probing. -The driver currently only supports XTAL input mode, and does not support any -fancy input configurations. They can still be programmed into the chip and -the driver will leave them "as is". +The driver currently does not support any fancy input configurations. They can +still be programmed into the chip and the driver will leave them "as is". ==I2C device node== @@ -45,9 +44,9 @@ Required properties: corresponding to inputs. Use a fixed clock for the "xtal" input. At least one must be present. - clock-names: One of: "xtal", "in0", "in1", "in2" -- vdd-supply: Regulator node for VDD Optional properties: +- vdd-supply: Regulator node for VDD - vdda-supply: Regulator node for VDDA - vdds-supply: Regulator node for VDDS - silabs,pll-m-num, silabs,pll-m-den: Numerator and denominator for PLL @@ -60,7 +59,14 @@ Optional properties: be initialized, and always performs the soft-reset routine. Since this will temporarily stop all output clocks, don't do this if the chip is generating the CPU clock for example. +- silabs,xaxb-ext-clk: When present, indicates that the XA/XB pins are used + in EXTCLK (external reference clock) rather than XTAL (crystal) mode. - interrupts: Interrupt for INTRb pin. +- silabs,iovdd-33: When present, indicates that the I2C lines are using 3.3V + rather than 1.8V thresholds. +- vddoX-supply (where X is an output index): Regulator node for VDDO for the + specified output. The driver selects the output VDD_SEL setting based on this + voltage. - #address-cells: shall be set to 1. - #size-cells: shall be set to 0. @@ -77,8 +83,6 @@ Required child node properties: - reg: number of clock output. Optional child node properties: -- vdd-supply: Regulator node for VDD for this output. The driver selects default - values for common-mode and amplitude based on the voltage. - silabs,format: Output format, one of: 1 = differential (defaults to LVDS levels) 2 = low-power (defaults to HCSL levels) From 6e7d2de1e000d36990923ed80d2e78dfcb545cee Mon Sep 17 00:00:00 2001 From: Robert Hancock Date: Thu, 25 Mar 2021 13:26:36 -0600 Subject: [PATCH 140/161] clk: si5341: Wait for DEVICE_READY on startup The Si5341 datasheet warns that before accessing any other registers, including the PAGE register, we need to wait for the DEVICE_READY register to indicate the device is ready, or the process of the device loading its state from NVM can be corrupted. Wait for DEVICE_READY on startup before continuing initialization. This is done using a raw I2C register read prior to setting up regmap to avoid any potential unwanted automatic PAGE register accesses from regmap at this stage. Fixes: 3044a860fd ("clk: Add Si5341/Si5340 driver") Signed-off-by: Robert Hancock Link: https://lore.kernel.org/r/20210325192643.2190069-3-robert.hancock@calian.com Signed-off-by: Stephen Boyd --- drivers/clk/clk-si5341.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/drivers/clk/clk-si5341.c b/drivers/clk/clk-si5341.c index e0446e66fa64..b8a960e927bc 100644 --- a/drivers/clk/clk-si5341.c +++ b/drivers/clk/clk-si5341.c @@ -94,6 +94,7 @@ struct clk_si5341_output_config { #define SI5341_STATUS 0x000C #define SI5341_SOFT_RST 0x001C #define SI5341_IN_SEL 0x0021 +#define SI5341_DEVICE_READY 0x00FE #define SI5341_XAXB_CFG 0x090E #define SI5341_IN_EN 0x0949 #define SI5341_INX_TO_PFD_EN 0x094A @@ -1189,6 +1190,32 @@ static const struct regmap_range_cfg si5341_regmap_ranges[] = { }, }; +static int si5341_wait_device_ready(struct i2c_client *client) +{ + int count; + + /* Datasheet warns: Any attempt to read or write any register other + * than DEVICE_READY before DEVICE_READY reads as 0x0F may corrupt the + * NVM programming and may corrupt the register contents, as they are + * read from NVM. Note that this includes accesses to the PAGE register. + * Also: DEVICE_READY is available on every register page, so no page + * change is needed to read it. + * Do this outside regmap to avoid automatic PAGE register access. + * May take up to 300ms to complete. + */ + for (count = 0; count < 15; ++count) { + s32 result = i2c_smbus_read_byte_data(client, + SI5341_DEVICE_READY); + if (result < 0) + return result; + if (result == 0x0F) + return 0; + msleep(20); + } + dev_err(&client->dev, "timeout waiting for DEVICE_READY\n"); + return -EIO; +} + static const struct regmap_config si5341_regmap_config = { .reg_bits = 8, .val_bits = 8, @@ -1385,6 +1412,11 @@ static int si5341_probe(struct i2c_client *client, data->i2c_client = client; + /* Must be done before otherwise touching hardware */ + err = si5341_wait_device_ready(client); + if (err) + return err; + for (i = 0; i < SI5341_NUM_INPUTS; ++i) { input = devm_clk_get(&client->dev, si5341_input_clock_names[i]); if (IS_ERR(input)) { From 78f6f406026d688868223d5dbeb197a4f7e9a9fd Mon Sep 17 00:00:00 2001 From: Robert Hancock Date: Thu, 25 Mar 2021 13:26:37 -0600 Subject: [PATCH 141/161] clk: si5341: Avoid divide errors due to bogus register contents If the Si5341 is being initially programmed and has no stored NVM configuration, some of the register contents may contain unexpected values, such as zeros, which could cause divide by zero errors during driver initialization. Trap errors caused by zero registers or zero clock rates which could result in divide errors later in the code. Fixes: 3044a860fd ("clk: Add Si5341/Si5340 driver") Signed-off-by: Robert Hancock Link: https://lore.kernel.org/r/20210325192643.2190069-4-robert.hancock@calian.com Signed-off-by: Stephen Boyd --- drivers/clk/clk-si5341.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/drivers/clk/clk-si5341.c b/drivers/clk/clk-si5341.c index b8a960e927bc..ac1ccec2b681 100644 --- a/drivers/clk/clk-si5341.c +++ b/drivers/clk/clk-si5341.c @@ -624,6 +624,9 @@ static unsigned long si5341_synth_clk_recalc_rate(struct clk_hw *hw, SI5341_SYNTH_N_NUM(synth->index), &n_num, &n_den); if (err < 0) return err; + /* Check for bogus/uninitialized settings */ + if (!n_num || !n_den) + return 0; /* * n_num and n_den are shifted left as much as possible, so to prevent @@ -807,6 +810,9 @@ static long si5341_output_clk_round_rate(struct clk_hw *hw, unsigned long rate, { unsigned long r; + if (!rate) + return 0; + r = *parent_rate >> 1; /* If rate is an even divisor, no changes to parent required */ @@ -835,11 +841,16 @@ static int si5341_output_clk_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate) { struct clk_si5341_output *output = to_clk_si5341_output(hw); - /* Frequency divider is (r_div + 1) * 2 */ - u32 r_div = (parent_rate / rate) >> 1; + u32 r_div; int err; u8 r[3]; + if (!rate) + return -EINVAL; + + /* Frequency divider is (r_div + 1) * 2 */ + r_div = (parent_rate / rate) >> 1; + if (r_div <= 1) r_div = 0; else if (r_div >= BIT(24)) From 71dcc4d1f7d2ad97ff7ab831281bc6893ff713a2 Mon Sep 17 00:00:00 2001 From: Robert Hancock Date: Thu, 25 Mar 2021 13:26:38 -0600 Subject: [PATCH 142/161] clk: si5341: Check for input clock presence and PLL lock on startup After initializing the device, wait for it to report that the input clock is present and the PLL has locked before declaring success. Fixes: 3044a860fd ("clk: Add Si5341/Si5340 driver") Signed-off-by: Robert Hancock Link: https://lore.kernel.org/r/20210325192643.2190069-5-robert.hancock@calian.com Signed-off-by: Stephen Boyd --- drivers/clk/clk-si5341.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/drivers/clk/clk-si5341.c b/drivers/clk/clk-si5341.c index ac1ccec2b681..da40b90c2aa8 100644 --- a/drivers/clk/clk-si5341.c +++ b/drivers/clk/clk-si5341.c @@ -92,6 +92,9 @@ struct clk_si5341_output_config { #define SI5341_PN_BASE 0x0002 #define SI5341_DEVICE_REV 0x0005 #define SI5341_STATUS 0x000C +#define SI5341_LOS 0x000D +#define SI5341_STATUS_STICKY 0x0011 +#define SI5341_LOS_STICKY 0x0012 #define SI5341_SOFT_RST 0x001C #define SI5341_IN_SEL 0x0021 #define SI5341_DEVICE_READY 0x00FE @@ -99,6 +102,12 @@ struct clk_si5341_output_config { #define SI5341_IN_EN 0x0949 #define SI5341_INX_TO_PFD_EN 0x094A +/* Status bits */ +#define SI5341_STATUS_SYSINCAL BIT(0) +#define SI5341_STATUS_LOSXAXB BIT(1) +#define SI5341_STATUS_LOSREF BIT(2) +#define SI5341_STATUS_LOL BIT(3) + /* Input selection */ #define SI5341_IN_SEL_MASK 0x06 #define SI5341_IN_SEL_SHIFT 1 @@ -1416,6 +1425,7 @@ static int si5341_probe(struct i2c_client *client, unsigned int i; struct clk_si5341_output_config config[SI5341_MAX_NUM_OUTPUTS]; bool initialization_required; + u32 status; data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL); if (!data) @@ -1583,6 +1593,22 @@ static int si5341_probe(struct i2c_client *client, return err; } + /* wait for device to report input clock present and PLL lock */ + err = regmap_read_poll_timeout(data->regmap, SI5341_STATUS, status, + !(status & (SI5341_STATUS_LOSREF | SI5341_STATUS_LOL)), + 10000, 250000); + if (err) { + dev_err(&client->dev, "Error waiting for input clock or PLL lock\n"); + return err; + } + + /* clear sticky alarm bits from initialization */ + err = regmap_write(data->regmap, SI5341_STATUS_STICKY, 0); + if (err) { + dev_err(&client->dev, "unable to clear sticky status\n"); + return err; + } + /* Free the names, clk framework makes copies */ for (i = 0; i < data->num_synth; ++i) devm_kfree(&client->dev, (void *)synth_clock_names[i]); From 3c9b49b0031aefb81adfdba5ab0ddf3ca3a2cdc9 Mon Sep 17 00:00:00 2001 From: Robert Hancock Date: Thu, 25 Mar 2021 13:26:39 -0600 Subject: [PATCH 143/161] clk: si5341: Update initialization magic Update the default register settings to include the VCO_RESET_CALCODE settings (set by the SiLabs ClockBuilder software but not described in the datasheet). Also update part of the initialization sequence to match ClockBuilder and the datasheet. Fixes: 3044a860fd ("clk: Add Si5341/Si5340 driver") Signed-off-by: Robert Hancock Link: https://lore.kernel.org/r/20210325192643.2190069-6-robert.hancock@calian.com Signed-off-by: Stephen Boyd --- drivers/clk/clk-si5341.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/clk/clk-si5341.c b/drivers/clk/clk-si5341.c index da40b90c2aa8..eb22f4fdbc6b 100644 --- a/drivers/clk/clk-si5341.c +++ b/drivers/clk/clk-si5341.c @@ -350,6 +350,8 @@ static const struct si5341_reg_default si5341_reg_defaults[] = { { 0x094A, 0x00 }, /* INx_TO_PFD_EN (disabled) */ { 0x0A02, 0x00 }, /* Not in datasheet */ { 0x0B44, 0x0F }, /* PDIV_ENB (datasheet does not mention what it is) */ + { 0x0B57, 0x10 }, /* VCO_RESET_CALCODE (not described in datasheet) */ + { 0x0B58, 0x05 }, /* VCO_RESET_CALCODE (not described in datasheet) */ }; /* Read and interpret a 44-bit followed by a 32-bit value in the regmap */ @@ -1104,7 +1106,7 @@ static const struct si5341_reg_default si5341_preamble[] = { { 0x0B25, 0x00 }, { 0x0502, 0x01 }, { 0x0505, 0x03 }, - { 0x0957, 0x1F }, + { 0x0957, 0x17 }, { 0x0B4E, 0x1A }, }; From b7bbf6ec4940d1a69811ec354edeeb9751fa8e85 Mon Sep 17 00:00:00 2001 From: Robert Hancock Date: Thu, 25 Mar 2021 13:26:40 -0600 Subject: [PATCH 144/161] clk: si5341: Allow different output VDD_SEL values The driver was not previously programming the VDD_SEL values for each output to indicate what external VDDO voltage was used for each. Add ability to specify a regulator supplying the VDDO pin for each output of the device. The voltage of the regulator is used to automatically set the VDD_SEL value appropriately. If no regulator is specified and the chip is being reconfigured, assume 2.5V which appears to be the chip default. Signed-off-by: Robert Hancock Link: https://lore.kernel.org/r/20210325192643.2190069-7-robert.hancock@calian.com Signed-off-by: Stephen Boyd --- drivers/clk/clk-si5341.c | 136 +++++++++++++++++++++++++++++++-------- 1 file changed, 110 insertions(+), 26 deletions(-) diff --git a/drivers/clk/clk-si5341.c b/drivers/clk/clk-si5341.c index eb22f4fdbc6b..28ac7085f362 100644 --- a/drivers/clk/clk-si5341.c +++ b/drivers/clk/clk-si5341.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -59,6 +60,7 @@ struct clk_si5341_synth { struct clk_si5341_output { struct clk_hw hw; struct clk_si5341 *data; + struct regulator *vddo_reg; u8 index; }; #define to_clk_si5341_output(_hw) \ @@ -84,6 +86,7 @@ struct clk_si5341 { struct clk_si5341_output_config { u8 out_format_drv_bits; u8 out_cm_ampl_bits; + u8 vdd_sel_bits; bool synth_master; bool always_on; }; @@ -136,6 +139,8 @@ struct clk_si5341_output_config { #define SI5341_OUT_R_REG(output) \ ((output)->data->reg_rdiv_offset[(output)->index]) +#define SI5341_OUT_MUX_VDD_SEL_MASK 0x38 + /* Synthesize N divider */ #define SI5341_SYNTH_N_NUM(x) (0x0302 + ((x) * 11)) #define SI5341_SYNTH_N_DEN(x) (0x0308 + ((x) * 11)) @@ -1248,11 +1253,11 @@ static const struct regmap_config si5341_regmap_config = { .volatile_table = &si5341_regmap_volatile, }; -static int si5341_dt_parse_dt(struct i2c_client *client, - struct clk_si5341_output_config *config) +static int si5341_dt_parse_dt(struct clk_si5341 *data, + struct clk_si5341_output_config *config) { struct device_node *child; - struct device_node *np = client->dev.of_node; + struct device_node *np = data->i2c_client->dev.of_node; u32 num; u32 val; @@ -1261,13 +1266,13 @@ static int si5341_dt_parse_dt(struct i2c_client *client, for_each_child_of_node(np, child) { if (of_property_read_u32(child, "reg", &num)) { - dev_err(&client->dev, "missing reg property of %s\n", + dev_err(&data->i2c_client->dev, "missing reg property of %s\n", child->name); goto put_child; } if (num >= SI5341_MAX_NUM_OUTPUTS) { - dev_err(&client->dev, "invalid clkout %d\n", num); + dev_err(&data->i2c_client->dev, "invalid clkout %d\n", num); goto put_child; } @@ -1286,7 +1291,7 @@ static int si5341_dt_parse_dt(struct i2c_client *client, config[num].out_format_drv_bits |= 0xc0; break; default: - dev_err(&client->dev, + dev_err(&data->i2c_client->dev, "invalid silabs,format %u for %u\n", val, num); goto put_child; @@ -1299,7 +1304,7 @@ static int si5341_dt_parse_dt(struct i2c_client *client, if (!of_property_read_u32(child, "silabs,common-mode", &val)) { if (val > 0xf) { - dev_err(&client->dev, + dev_err(&data->i2c_client->dev, "invalid silabs,common-mode %u\n", val); goto put_child; @@ -1310,7 +1315,7 @@ static int si5341_dt_parse_dt(struct i2c_client *client, if (!of_property_read_u32(child, "silabs,amplitude", &val)) { if (val > 0xf) { - dev_err(&client->dev, + dev_err(&data->i2c_client->dev, "invalid silabs,amplitude %u\n", val); goto put_child; @@ -1327,6 +1332,34 @@ static int si5341_dt_parse_dt(struct i2c_client *client, config[num].always_on = of_property_read_bool(child, "always-on"); + + config[num].vdd_sel_bits = 0x08; + if (data->clk[num].vddo_reg) { + int vdd = regulator_get_voltage(data->clk[num].vddo_reg); + + switch (vdd) { + case 3300000: + config[num].vdd_sel_bits |= 0 << 4; + break; + case 1800000: + config[num].vdd_sel_bits |= 1 << 4; + break; + case 2500000: + config[num].vdd_sel_bits |= 2 << 4; + break; + default: + dev_err(&data->i2c_client->dev, + "unsupported vddo voltage %d for %s\n", + vdd, child->name); + goto put_child; + } + } else { + /* chip seems to default to 2.5V when not set */ + dev_warn(&data->i2c_client->dev, + "no regulator set, defaulting vdd_sel to 2.5V for %s\n", + child->name); + config[num].vdd_sel_bits |= 2 << 4; + } } return 0; @@ -1452,9 +1485,33 @@ static int si5341_probe(struct i2c_client *client, } } - err = si5341_dt_parse_dt(client, config); + for (i = 0; i < SI5341_MAX_NUM_OUTPUTS; ++i) { + char reg_name[10]; + + snprintf(reg_name, sizeof(reg_name), "vddo%d", i); + data->clk[i].vddo_reg = devm_regulator_get_optional( + &client->dev, reg_name); + if (IS_ERR(data->clk[i].vddo_reg)) { + err = PTR_ERR(data->clk[i].vddo_reg); + data->clk[i].vddo_reg = NULL; + if (err == -ENODEV) + continue; + goto cleanup; + } else { + err = regulator_enable(data->clk[i].vddo_reg); + if (err) { + dev_err(&client->dev, + "failed to enable %s regulator: %d\n", + reg_name, err); + data->clk[i].vddo_reg = NULL; + goto cleanup; + } + } + } + + err = si5341_dt_parse_dt(data, config); if (err) - return err; + goto cleanup; if (of_property_read_string(client->dev.of_node, "clock-output-names", &init.name)) @@ -1462,21 +1519,23 @@ static int si5341_probe(struct i2c_client *client, root_clock_name = init.name; data->regmap = devm_regmap_init_i2c(client, &si5341_regmap_config); - if (IS_ERR(data->regmap)) - return PTR_ERR(data->regmap); + if (IS_ERR(data->regmap)) { + err = PTR_ERR(data->regmap); + goto cleanup; + } i2c_set_clientdata(client, data); err = si5341_probe_chip_id(data); if (err < 0) - return err; + goto cleanup; if (of_property_read_bool(client->dev.of_node, "silabs,reprogram")) { initialization_required = true; } else { err = si5341_is_programmed_already(data); if (err < 0) - return err; + goto cleanup; initialization_required = !err; } @@ -1485,11 +1544,11 @@ static int si5341_probe(struct i2c_client *client, /* Populate the regmap cache in preparation for "cache only" */ err = si5341_read_settings(data); if (err < 0) - return err; + goto cleanup; err = si5341_send_preamble(data); if (err < 0) - return err; + goto cleanup; /* * We intend to send all 'final' register values in a single @@ -1502,19 +1561,19 @@ static int si5341_probe(struct i2c_client *client, err = si5341_write_multiple(data, si5341_reg_defaults, ARRAY_SIZE(si5341_reg_defaults)); if (err < 0) - return err; + goto cleanup; } /* Input must be up and running at this point */ err = si5341_clk_select_active_input(data); if (err < 0) - return err; + goto cleanup; if (initialization_required) { /* PLL configuration is required */ err = si5341_initialize_pll(data); if (err < 0) - return err; + goto cleanup; } /* Register the PLL */ @@ -1527,7 +1586,7 @@ static int si5341_probe(struct i2c_client *client, err = devm_clk_hw_register(&client->dev, &data->hw); if (err) { dev_err(&client->dev, "clock registration failed\n"); - return err; + goto cleanup; } init.num_parents = 1; @@ -1564,13 +1623,17 @@ static int si5341_probe(struct i2c_client *client, regmap_write(data->regmap, SI5341_OUT_CM(&data->clk[i]), config[i].out_cm_ampl_bits); + regmap_update_bits(data->regmap, + SI5341_OUT_MUX_SEL(&data->clk[i]), + SI5341_OUT_MUX_VDD_SEL_MASK, + config[i].vdd_sel_bits); } err = devm_clk_hw_register(&client->dev, &data->clk[i].hw); kfree(init.name); /* clock framework made a copy of the name */ if (err) { dev_err(&client->dev, "output %u registration failed\n", i); - return err; + goto cleanup; } if (config[i].always_on) clk_prepare(data->clk[i].hw.clk); @@ -1580,7 +1643,7 @@ static int si5341_probe(struct i2c_client *client, data); if (err) { dev_err(&client->dev, "unable to add clk provider\n"); - return err; + goto cleanup; } if (initialization_required) { @@ -1588,11 +1651,11 @@ static int si5341_probe(struct i2c_client *client, regcache_cache_only(data->regmap, false); err = regcache_sync(data->regmap); if (err < 0) - return err; + goto cleanup; err = si5341_finalize_defaults(data); if (err < 0) - return err; + goto cleanup; } /* wait for device to report input clock present and PLL lock */ @@ -1601,14 +1664,14 @@ static int si5341_probe(struct i2c_client *client, 10000, 250000); if (err) { dev_err(&client->dev, "Error waiting for input clock or PLL lock\n"); - return err; + goto cleanup; } /* clear sticky alarm bits from initialization */ err = regmap_write(data->regmap, SI5341_STATUS_STICKY, 0); if (err) { dev_err(&client->dev, "unable to clear sticky status\n"); - return err; + goto cleanup; } /* Free the names, clk framework makes copies */ @@ -1616,6 +1679,26 @@ static int si5341_probe(struct i2c_client *client, devm_kfree(&client->dev, (void *)synth_clock_names[i]); return 0; + +cleanup: + for (i = 0; i < SI5341_MAX_NUM_OUTPUTS; ++i) { + if (data->clk[i].vddo_reg) + regulator_disable(data->clk[i].vddo_reg); + } + return err; +} + +static int si5341_remove(struct i2c_client *client) +{ + struct clk_si5341 *data = i2c_get_clientdata(client); + int i; + + for (i = 0; i < SI5341_MAX_NUM_OUTPUTS; ++i) { + if (data->clk[i].vddo_reg) + regulator_disable(data->clk[i].vddo_reg); + } + + return 0; } static const struct i2c_device_id si5341_id[] = { @@ -1644,6 +1727,7 @@ static struct i2c_driver si5341_driver = { .of_match_table = clk_si5341_of_match, }, .probe = si5341_probe, + .remove = si5341_remove, .id_table = si5341_id, }; module_i2c_driver(si5341_driver); From ab89a3439ffa61913a625c34758a46c8ca0c0713 Mon Sep 17 00:00:00 2001 From: Robert Hancock Date: Thu, 25 Mar 2021 13:26:41 -0600 Subject: [PATCH 145/161] clk: si5341: Add silabs,xaxb-ext-clk property Add a property to allow specifying that the device XA/XB pins are used for an external clock input rather than for a clock crystal. Signed-off-by: Robert Hancock Link: https://lore.kernel.org/r/20210325192643.2190069-8-robert.hancock@calian.com Signed-off-by: Stephen Boyd --- drivers/clk/clk-si5341.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/clk/clk-si5341.c b/drivers/clk/clk-si5341.c index 28ac7085f362..c5ab4a5ae6a5 100644 --- a/drivers/clk/clk-si5341.c +++ b/drivers/clk/clk-si5341.c @@ -80,6 +80,7 @@ struct clk_si5341 { u8 num_outputs; u8 num_synth; u16 chip_id; + bool xaxb_ext_clk; }; #define to_clk_si5341(_hw) container_of(_hw, struct clk_si5341, hw) @@ -529,9 +530,11 @@ static int si5341_clk_reparent(struct clk_si5341 *data, u8 index) if (err < 0) return err; - /* Power up XTAL oscillator and buffer */ + /* Power up XTAL oscillator and buffer, select clock mode */ err = regmap_update_bits(data->regmap, SI5341_XAXB_CFG, - SI5341_XAXB_CFG_PDNB, SI5341_XAXB_CFG_PDNB); + SI5341_XAXB_CFG_PDNB | SI5341_XAXB_CFG_EXTCLK_EN, + SI5341_XAXB_CFG_PDNB | (data->xaxb_ext_clk ? + SI5341_XAXB_CFG_EXTCLK_EN : 0)); if (err < 0) return err; } @@ -1539,6 +1542,8 @@ static int si5341_probe(struct i2c_client *client, initialization_required = !err; } + data->xaxb_ext_clk = of_property_read_bool(client->dev.of_node, + "silabs,xaxb-ext-clk"); if (initialization_required) { /* Populate the regmap cache in preparation for "cache only" */ From 2f02c5e42a55fbdb1b4f113df2c26a5c99e8d578 Mon Sep 17 00:00:00 2001 From: Robert Hancock Date: Thu, 25 Mar 2021 13:26:42 -0600 Subject: [PATCH 146/161] clk: si5341: Add silabs,iovdd-33 property Add a property to allow specifying that the external I2C IO pins are using 3.3V voltage thresholds rather than 1.8V. Signed-off-by: Robert Hancock Link: https://lore.kernel.org/r/20210325192643.2190069-9-robert.hancock@calian.com Signed-off-by: Stephen Boyd --- drivers/clk/clk-si5341.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/clk/clk-si5341.c b/drivers/clk/clk-si5341.c index c5ab4a5ae6a5..d4aa67a4dc66 100644 --- a/drivers/clk/clk-si5341.c +++ b/drivers/clk/clk-si5341.c @@ -81,6 +81,7 @@ struct clk_si5341 { u8 num_synth; u16 chip_id; bool xaxb_ext_clk; + bool iovdd_33; }; #define to_clk_si5341(_hw) container_of(_hw, struct clk_si5341, hw) @@ -103,6 +104,7 @@ struct clk_si5341_output_config { #define SI5341_IN_SEL 0x0021 #define SI5341_DEVICE_READY 0x00FE #define SI5341_XAXB_CFG 0x090E +#define SI5341_IO_VDD_SEL 0x0943 #define SI5341_IN_EN 0x0949 #define SI5341_INX_TO_PFD_EN 0x094A @@ -351,7 +353,6 @@ static const struct si5341_reg_default si5341_reg_defaults[] = { { 0x0804, 0x00 }, /* Not in datasheet */ { 0x090E, 0x02 }, /* XAXB_EXTCLK_EN=0 XAXB_PDNB=1 (use XTAL) */ { 0x091C, 0x04 }, /* ZDM_EN=4 (Normal mode) */ - { 0x0943, 0x00 }, /* IO_VDD_SEL=0 (0=1v8, use 1=3v3) */ { 0x0949, 0x00 }, /* IN_EN (disable input clocks) */ { 0x094A, 0x00 }, /* INx_TO_PFD_EN (disabled) */ { 0x0A02, 0x00 }, /* Not in datasheet */ @@ -1160,6 +1161,11 @@ static int si5341_finalize_defaults(struct clk_si5341 *data) int res; u32 revision; + res = regmap_write(data->regmap, SI5341_IO_VDD_SEL, + data->iovdd_33 ? 1 : 0); + if (res < 0) + return res; + res = regmap_read(data->regmap, SI5341_DEVICE_REV, &revision); if (res < 0) return res; @@ -1544,6 +1550,8 @@ static int si5341_probe(struct i2c_client *client, } data->xaxb_ext_clk = of_property_read_bool(client->dev.of_node, "silabs,xaxb-ext-clk"); + data->iovdd_33 = of_property_read_bool(client->dev.of_node, + "silabs,iovdd-33"); if (initialization_required) { /* Populate the regmap cache in preparation for "cache only" */ From 9b13ff4340dff30f361462999a6a122fcc4e473f Mon Sep 17 00:00:00 2001 From: Robert Hancock Date: Thu, 25 Mar 2021 13:26:43 -0600 Subject: [PATCH 147/161] clk: si5341: Add sysfs properties to allow checking/resetting device faults Add sysfs property files to allow viewing the current and latched states of the input present and PLL lock bits, and allow resetting the latched fault state. This allows manual checks or automated userspace polling for faults occurring after initialization. Signed-off-by: Robert Hancock Link: https://lore.kernel.org/r/20210325192643.2190069-10-robert.hancock@calian.com Signed-off-by: Stephen Boyd --- drivers/clk/clk-si5341.c | 96 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) diff --git a/drivers/clk/clk-si5341.c b/drivers/clk/clk-si5341.c index d4aa67a4dc66..57ae183982d8 100644 --- a/drivers/clk/clk-si5341.c +++ b/drivers/clk/clk-si5341.c @@ -1457,6 +1457,94 @@ static int si5341_clk_select_active_input(struct clk_si5341 *data) return res; } +static ssize_t input_present_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct clk_si5341 *data = dev_get_drvdata(dev); + u32 status; + int res = regmap_read(data->regmap, SI5341_STATUS, &status); + + if (res < 0) + return res; + res = !(status & SI5341_STATUS_LOSREF); + return snprintf(buf, PAGE_SIZE, "%d\n", res); +} +static DEVICE_ATTR_RO(input_present); + +static ssize_t input_present_sticky_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct clk_si5341 *data = dev_get_drvdata(dev); + u32 status; + int res = regmap_read(data->regmap, SI5341_STATUS_STICKY, &status); + + if (res < 0) + return res; + res = !(status & SI5341_STATUS_LOSREF); + return snprintf(buf, PAGE_SIZE, "%d\n", res); +} +static DEVICE_ATTR_RO(input_present_sticky); + +static ssize_t pll_locked_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct clk_si5341 *data = dev_get_drvdata(dev); + u32 status; + int res = regmap_read(data->regmap, SI5341_STATUS, &status); + + if (res < 0) + return res; + res = !(status & SI5341_STATUS_LOL); + return snprintf(buf, PAGE_SIZE, "%d\n", res); +} +static DEVICE_ATTR_RO(pll_locked); + +static ssize_t pll_locked_sticky_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct clk_si5341 *data = dev_get_drvdata(dev); + u32 status; + int res = regmap_read(data->regmap, SI5341_STATUS_STICKY, &status); + + if (res < 0) + return res; + res = !(status & SI5341_STATUS_LOL); + return snprintf(buf, PAGE_SIZE, "%d\n", res); +} +static DEVICE_ATTR_RO(pll_locked_sticky); + +static ssize_t clear_sticky_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct clk_si5341 *data = dev_get_drvdata(dev); + long val; + + if (kstrtol(buf, 10, &val)) + return -EINVAL; + if (val) { + int res = regmap_write(data->regmap, SI5341_STATUS_STICKY, 0); + + if (res < 0) + return res; + } + return count; +} +static DEVICE_ATTR_WO(clear_sticky); + +static const struct attribute *si5341_attributes[] = { + &dev_attr_input_present.attr, + &dev_attr_input_present_sticky.attr, + &dev_attr_pll_locked.attr, + &dev_attr_pll_locked_sticky.attr, + &dev_attr_clear_sticky.attr, + NULL +}; + static int si5341_probe(struct i2c_client *client, const struct i2c_device_id *id) { @@ -1687,6 +1775,12 @@ static int si5341_probe(struct i2c_client *client, goto cleanup; } + err = sysfs_create_files(&client->dev.kobj, si5341_attributes); + if (err) { + dev_err(&client->dev, "unable to create sysfs files\n"); + goto cleanup; + } + /* Free the names, clk framework makes copies */ for (i = 0; i < data->num_synth; ++i) devm_kfree(&client->dev, (void *)synth_clock_names[i]); @@ -1706,6 +1800,8 @@ static int si5341_remove(struct i2c_client *client) struct clk_si5341 *data = i2c_get_clientdata(client); int i; + sysfs_remove_files(&client->dev.kobj, si5341_attributes); + for (i = 0; i < SI5341_MAX_NUM_OUTPUTS; ++i) { if (data->clk[i].vddo_reg) regulator_disable(data->clk[i].vddo_reg); From b87111da42f328c0e658e36e6782bb341ee742ea Mon Sep 17 00:00:00 2001 From: Dongjiu Geng Date: Tue, 23 Mar 2021 19:29:32 +0800 Subject: [PATCH 148/161] dt-bindings: Document the hi3559a clock bindings Add DT bindings documentation for hi3559a SoC clock. Signed-off-by: Dongjiu Geng Reviewed-by: Rob Herring Link: https://lore.kernel.org/r/1616498973-47067-2-git-send-email-gengdongjiu1@gmail.com Signed-off-by: Stephen Boyd --- .../clock/hisilicon,hi3559av100-clock.yaml | 59 +++++++ include/dt-bindings/clock/hi3559av100-clock.h | 165 ++++++++++++++++++ 2 files changed, 224 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/hisilicon,hi3559av100-clock.yaml create mode 100644 include/dt-bindings/clock/hi3559av100-clock.h diff --git a/Documentation/devicetree/bindings/clock/hisilicon,hi3559av100-clock.yaml b/Documentation/devicetree/bindings/clock/hisilicon,hi3559av100-clock.yaml new file mode 100644 index 000000000000..3ceb29cec704 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/hisilicon,hi3559av100-clock.yaml @@ -0,0 +1,59 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/hisilicon,hi3559av100-clock.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Hisilicon SOC Clock for HI3559AV100 + +maintainers: + - Dongjiu Geng + +description: | + Hisilicon SOC clock control module which supports the clocks, resets and + power domains on HI3559AV100. + + See also: + dt-bindings/clock/hi3559av100-clock.h + +properties: + compatible: + enum: + - hisilicon,hi3559av100-clock + - hisilicon,hi3559av100-shub-clock + + reg: + minItems: 1 + maxItems: 2 + + '#clock-cells': + const: 1 + + '#reset-cells': + const: 2 + description: | + First cell is reset request register offset. + Second cell is bit offset in reset request register. + +required: + - compatible + - reg + - '#clock-cells' + - '#reset-cells' + +additionalProperties: false + +examples: + - | + soc { + #address-cells = <2>; + #size-cells = <2>; + + clock-controller@12010000 { + compatible = "hisilicon,hi3559av100-clock"; + #clock-cells = <1>; + #reset-cells = <2>; + reg = <0x0 0x12010000 0x0 0x10000>; + }; + }; +... diff --git a/include/dt-bindings/clock/hi3559av100-clock.h b/include/dt-bindings/clock/hi3559av100-clock.h new file mode 100644 index 000000000000..5fe7689010a0 --- /dev/null +++ b/include/dt-bindings/clock/hi3559av100-clock.h @@ -0,0 +1,165 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later or BSD-2-Clause */ +/* + * Copyright (c) 2019-2020, Huawei Tech. Co., Ltd. + * + * Author: Dongjiu Geng + */ + +#ifndef __DTS_HI3559AV100_CLOCK_H +#define __DTS_HI3559AV100_CLOCK_H + +/* fixed rate */ +#define HI3559AV100_FIXED_1188M 1 +#define HI3559AV100_FIXED_1000M 2 +#define HI3559AV100_FIXED_842M 3 +#define HI3559AV100_FIXED_792M 4 +#define HI3559AV100_FIXED_750M 5 +#define HI3559AV100_FIXED_710M 6 +#define HI3559AV100_FIXED_680M 7 +#define HI3559AV100_FIXED_667M 8 +#define HI3559AV100_FIXED_631M 9 +#define HI3559AV100_FIXED_600M 10 +#define HI3559AV100_FIXED_568M 11 +#define HI3559AV100_FIXED_500M 12 +#define HI3559AV100_FIXED_475M 13 +#define HI3559AV100_FIXED_428M 14 +#define HI3559AV100_FIXED_400M 15 +#define HI3559AV100_FIXED_396M 16 +#define HI3559AV100_FIXED_300M 17 +#define HI3559AV100_FIXED_250M 18 +#define HI3559AV100_FIXED_198M 19 +#define HI3559AV100_FIXED_187p5M 20 +#define HI3559AV100_FIXED_150M 21 +#define HI3559AV100_FIXED_148p5M 22 +#define HI3559AV100_FIXED_125M 23 +#define HI3559AV100_FIXED_107M 24 +#define HI3559AV100_FIXED_100M 25 +#define HI3559AV100_FIXED_99M 26 +#define HI3559AV100_FIXED_74p25M 27 +#define HI3559AV100_FIXED_72M 28 +#define HI3559AV100_FIXED_60M 29 +#define HI3559AV100_FIXED_54M 30 +#define HI3559AV100_FIXED_50M 31 +#define HI3559AV100_FIXED_49p5M 32 +#define HI3559AV100_FIXED_37p125M 33 +#define HI3559AV100_FIXED_36M 34 +#define HI3559AV100_FIXED_32p4M 35 +#define HI3559AV100_FIXED_27M 36 +#define HI3559AV100_FIXED_25M 37 +#define HI3559AV100_FIXED_24M 38 +#define HI3559AV100_FIXED_12M 39 +#define HI3559AV100_FIXED_3M 40 +#define HI3559AV100_FIXED_1p6M 41 +#define HI3559AV100_FIXED_400K 42 +#define HI3559AV100_FIXED_100K 43 +#define HI3559AV100_FIXED_200M 44 +#define HI3559AV100_FIXED_75M 75 + +#define HI3559AV100_I2C0_CLK 50 +#define HI3559AV100_I2C1_CLK 51 +#define HI3559AV100_I2C2_CLK 52 +#define HI3559AV100_I2C3_CLK 53 +#define HI3559AV100_I2C4_CLK 54 +#define HI3559AV100_I2C5_CLK 55 +#define HI3559AV100_I2C6_CLK 56 +#define HI3559AV100_I2C7_CLK 57 +#define HI3559AV100_I2C8_CLK 58 +#define HI3559AV100_I2C9_CLK 59 +#define HI3559AV100_I2C10_CLK 60 +#define HI3559AV100_I2C11_CLK 61 + +#define HI3559AV100_SPI0_CLK 62 +#define HI3559AV100_SPI1_CLK 63 +#define HI3559AV100_SPI2_CLK 64 +#define HI3559AV100_SPI3_CLK 65 +#define HI3559AV100_SPI4_CLK 66 +#define HI3559AV100_SPI5_CLK 67 +#define HI3559AV100_SPI6_CLK 68 + +#define HI3559AV100_EDMAC_CLK 69 +#define HI3559AV100_EDMAC_AXICLK 70 +#define HI3559AV100_EDMAC1_CLK 71 +#define HI3559AV100_EDMAC1_AXICLK 72 +#define HI3559AV100_VDMAC_CLK 73 + +/* mux clocks */ +#define HI3559AV100_FMC_MUX 80 +#define HI3559AV100_SYSAPB_MUX 81 +#define HI3559AV100_UART_MUX 82 +#define HI3559AV100_SYSBUS_MUX 83 +#define HI3559AV100_A73_MUX 84 +#define HI3559AV100_MMC0_MUX 85 +#define HI3559AV100_MMC1_MUX 86 +#define HI3559AV100_MMC2_MUX 87 +#define HI3559AV100_MMC3_MUX 88 + +/* gate clocks */ +#define HI3559AV100_FMC_CLK 90 +#define HI3559AV100_UART0_CLK 91 +#define HI3559AV100_UART1_CLK 92 +#define HI3559AV100_UART2_CLK 93 +#define HI3559AV100_UART3_CLK 94 +#define HI3559AV100_UART4_CLK 95 +#define HI3559AV100_MMC0_CLK 96 +#define HI3559AV100_MMC1_CLK 97 +#define HI3559AV100_MMC2_CLK 98 +#define HI3559AV100_MMC3_CLK 99 + +#define HI3559AV100_ETH_CLK 100 +#define HI3559AV100_ETH_MACIF_CLK 101 +#define HI3559AV100_ETH1_CLK 102 +#define HI3559AV100_ETH1_MACIF_CLK 103 + +/* complex */ +#define HI3559AV100_MAC0_CLK 110 +#define HI3559AV100_MAC1_CLK 111 +#define HI3559AV100_SATA_CLK 112 +#define HI3559AV100_USB_CLK 113 +#define HI3559AV100_USB1_CLK 114 + +/* pll clocks */ +#define HI3559AV100_APLL_CLK 250 +#define HI3559AV100_GPLL_CLK 251 + +#define HI3559AV100_CRG_NR_CLKS 256 + +#define HI3559AV100_SHUB_SOURCE_SOC_24M 0 +#define HI3559AV100_SHUB_SOURCE_SOC_200M 1 +#define HI3559AV100_SHUB_SOURCE_SOC_300M 2 +#define HI3559AV100_SHUB_SOURCE_PLL 3 +#define HI3559AV100_SHUB_SOURCE_CLK 4 + +#define HI3559AV100_SHUB_I2C0_CLK 10 +#define HI3559AV100_SHUB_I2C1_CLK 11 +#define HI3559AV100_SHUB_I2C2_CLK 12 +#define HI3559AV100_SHUB_I2C3_CLK 13 +#define HI3559AV100_SHUB_I2C4_CLK 14 +#define HI3559AV100_SHUB_I2C5_CLK 15 +#define HI3559AV100_SHUB_I2C6_CLK 16 +#define HI3559AV100_SHUB_I2C7_CLK 17 + +#define HI3559AV100_SHUB_SPI_SOURCE_CLK 20 +#define HI3559AV100_SHUB_SPI4_SOURCE_CLK 21 +#define HI3559AV100_SHUB_SPI0_CLK 22 +#define HI3559AV100_SHUB_SPI1_CLK 23 +#define HI3559AV100_SHUB_SPI2_CLK 24 +#define HI3559AV100_SHUB_SPI3_CLK 25 +#define HI3559AV100_SHUB_SPI4_CLK 26 + +#define HI3559AV100_SHUB_UART_CLK_32K 30 +#define HI3559AV100_SHUB_UART_SOURCE_CLK 31 +#define HI3559AV100_SHUB_UART_DIV_CLK 32 +#define HI3559AV100_SHUB_UART0_CLK 33 +#define HI3559AV100_SHUB_UART1_CLK 34 +#define HI3559AV100_SHUB_UART2_CLK 35 +#define HI3559AV100_SHUB_UART3_CLK 36 +#define HI3559AV100_SHUB_UART4_CLK 37 +#define HI3559AV100_SHUB_UART5_CLK 38 +#define HI3559AV100_SHUB_UART6_CLK 39 + +#define HI3559AV100_SHUB_EDMAC_CLK 40 + +#define HI3559AV100_SHUB_NR_CLKS 50 + +#endif /* __DTS_HI3559AV100_CLOCK_H */ + From 6c81966107dc0caa5d2ebedbcebb5f10d865064d Mon Sep 17 00:00:00 2001 From: Dongjiu Geng Date: Tue, 23 Mar 2021 19:29:33 +0800 Subject: [PATCH 149/161] clk: hisilicon: Add clock driver for hi3559A SoC Add clock drivers for hi3559A SoC, this driver controls the SoC registers to supply different clocks to different IPs in the SoC. Signed-off-by: Dongjiu Geng Link: https://lore.kernel.org/r/1616498973-47067-3-git-send-email-gengdongjiu1@gmail.com [sboyd@kernel.org: Mark arrays static, add __iomem, drop unused array, avoid kfree of devm memory] Signed-off-by: Stephen Boyd --- drivers/clk/hisilicon/Kconfig | 7 + drivers/clk/hisilicon/Makefile | 1 + drivers/clk/hisilicon/clk-hi3559a.c | 846 ++++++++++++++++++++++++++++ drivers/clk/hisilicon/clk.c | 2 +- drivers/clk/hisilicon/clk.h | 2 +- 5 files changed, 856 insertions(+), 2 deletions(-) create mode 100644 drivers/clk/hisilicon/clk-hi3559a.c diff --git a/drivers/clk/hisilicon/Kconfig b/drivers/clk/hisilicon/Kconfig index 6a9e93a0bb95..5ecc37aaa118 100644 --- a/drivers/clk/hisilicon/Kconfig +++ b/drivers/clk/hisilicon/Kconfig @@ -15,6 +15,13 @@ config COMMON_CLK_HI3519 help Build the clock driver for hi3519. +config COMMON_CLK_HI3559A + bool "Hi3559A Clock Driver" + depends on ARCH_HISI || COMPILE_TEST + default ARCH_HISI + help + Build the clock driver for hi3559a. + config COMMON_CLK_HI3660 bool "Hi3660 Clock Driver" depends on ARCH_HISI || COMPILE_TEST diff --git a/drivers/clk/hisilicon/Makefile b/drivers/clk/hisilicon/Makefile index b2441b99f3d5..2978e56cb876 100644 --- a/drivers/clk/hisilicon/Makefile +++ b/drivers/clk/hisilicon/Makefile @@ -10,6 +10,7 @@ obj-$(CONFIG_ARCH_HIP04) += clk-hip04.o obj-$(CONFIG_ARCH_HIX5HD2) += clk-hix5hd2.o obj-$(CONFIG_COMMON_CLK_HI3516CV300) += crg-hi3516cv300.o obj-$(CONFIG_COMMON_CLK_HI3519) += clk-hi3519.o +obj-$(CONFIG_COMMON_CLK_HI3559A) += clk-hi3559a.o obj-$(CONFIG_COMMON_CLK_HI3660) += clk-hi3660.o obj-$(CONFIG_COMMON_CLK_HI3670) += clk-hi3670.o obj-$(CONFIG_COMMON_CLK_HI3798CV200) += crg-hi3798cv200.o diff --git a/drivers/clk/hisilicon/clk-hi3559a.c b/drivers/clk/hisilicon/clk-hi3559a.c new file mode 100644 index 000000000000..b1f19c43b558 --- /dev/null +++ b/drivers/clk/hisilicon/clk-hi3559a.c @@ -0,0 +1,846 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Hisilicon Hi3559A clock driver + * + * Copyright (c) 2019-2020, Huawei Tech. Co., Ltd. + * + * Author: Dongjiu Geng + */ + +#include +#include +#include +#include +#include + +#include + +#include "clk.h" +#include "crg.h" +#include "reset.h" + +#define CRG_BASE_ADDR 0x18020000 +#define PLL_MASK_WIDTH 24 + +struct hi3559av100_pll_clock { + u32 id; + const char *name; + const char *parent_name; + const u32 ctrl_reg1; + const u8 frac_shift; + const u8 frac_width; + const u8 postdiv1_shift; + const u8 postdiv1_width; + const u8 postdiv2_shift; + const u8 postdiv2_width; + const u32 ctrl_reg2; + const u8 fbdiv_shift; + const u8 fbdiv_width; + const u8 refdiv_shift; + const u8 refdiv_width; +}; + +struct hi3559av100_clk_pll { + struct clk_hw hw; + u32 id; + void __iomem *ctrl_reg1; + u8 frac_shift; + u8 frac_width; + u8 postdiv1_shift; + u8 postdiv1_width; + u8 postdiv2_shift; + u8 postdiv2_width; + void __iomem *ctrl_reg2; + u8 fbdiv_shift; + u8 fbdiv_width; + u8 refdiv_shift; + u8 refdiv_width; +}; + +/* soc clk config */ +static const struct hisi_fixed_rate_clock hi3559av100_fixed_rate_clks_crg[] = { + { HI3559AV100_FIXED_1188M, "1188m", NULL, 0, 1188000000, }, + { HI3559AV100_FIXED_1000M, "1000m", NULL, 0, 1000000000, }, + { HI3559AV100_FIXED_842M, "842m", NULL, 0, 842000000, }, + { HI3559AV100_FIXED_792M, "792m", NULL, 0, 792000000, }, + { HI3559AV100_FIXED_750M, "750m", NULL, 0, 750000000, }, + { HI3559AV100_FIXED_710M, "710m", NULL, 0, 710000000, }, + { HI3559AV100_FIXED_680M, "680m", NULL, 0, 680000000, }, + { HI3559AV100_FIXED_667M, "667m", NULL, 0, 667000000, }, + { HI3559AV100_FIXED_631M, "631m", NULL, 0, 631000000, }, + { HI3559AV100_FIXED_600M, "600m", NULL, 0, 600000000, }, + { HI3559AV100_FIXED_568M, "568m", NULL, 0, 568000000, }, + { HI3559AV100_FIXED_500M, "500m", NULL, 0, 500000000, }, + { HI3559AV100_FIXED_475M, "475m", NULL, 0, 475000000, }, + { HI3559AV100_FIXED_428M, "428m", NULL, 0, 428000000, }, + { HI3559AV100_FIXED_400M, "400m", NULL, 0, 400000000, }, + { HI3559AV100_FIXED_396M, "396m", NULL, 0, 396000000, }, + { HI3559AV100_FIXED_300M, "300m", NULL, 0, 300000000, }, + { HI3559AV100_FIXED_250M, "250m", NULL, 0, 250000000, }, + { HI3559AV100_FIXED_200M, "200m", NULL, 0, 200000000, }, + { HI3559AV100_FIXED_198M, "198m", NULL, 0, 198000000, }, + { HI3559AV100_FIXED_187p5M, "187p5m", NULL, 0, 187500000, }, + { HI3559AV100_FIXED_150M, "150m", NULL, 0, 150000000, }, + { HI3559AV100_FIXED_148p5M, "148p5m", NULL, 0, 1485000000, }, + { HI3559AV100_FIXED_125M, "125m", NULL, 0, 125000000, }, + { HI3559AV100_FIXED_107M, "107m", NULL, 0, 107000000, }, + { HI3559AV100_FIXED_100M, "100m", NULL, 0, 100000000, }, + { HI3559AV100_FIXED_99M, "99m", NULL, 0, 99000000, }, + { HI3559AV100_FIXED_75M, "75m", NULL, 0, 75000000, }, + { HI3559AV100_FIXED_74p25M, "74p25m", NULL, 0, 74250000, }, + { HI3559AV100_FIXED_72M, "72m", NULL, 0, 72000000, }, + { HI3559AV100_FIXED_60M, "60m", NULL, 0, 60000000, }, + { HI3559AV100_FIXED_54M, "54m", NULL, 0, 54000000, }, + { HI3559AV100_FIXED_50M, "50m", NULL, 0, 50000000, }, + { HI3559AV100_FIXED_49p5M, "49p5m", NULL, 0, 49500000, }, + { HI3559AV100_FIXED_37p125M, "37p125m", NULL, 0, 37125000, }, + { HI3559AV100_FIXED_36M, "36m", NULL, 0, 36000000, }, + { HI3559AV100_FIXED_32p4M, "32p4m", NULL, 0, 32400000, }, + { HI3559AV100_FIXED_27M, "27m", NULL, 0, 27000000, }, + { HI3559AV100_FIXED_25M, "25m", NULL, 0, 25000000, }, + { HI3559AV100_FIXED_24M, "24m", NULL, 0, 24000000, }, + { HI3559AV100_FIXED_12M, "12m", NULL, 0, 12000000, }, + { HI3559AV100_FIXED_3M, "3m", NULL, 0, 3000000, }, + { HI3559AV100_FIXED_1p6M, "1p6m", NULL, 0, 1600000, }, + { HI3559AV100_FIXED_400K, "400k", NULL, 0, 400000, }, + { HI3559AV100_FIXED_100K, "100k", NULL, 0, 100000, }, +}; + + +static const char *fmc_mux_p[] __initconst = { + "24m", "75m", "125m", "150m", "200m", "250m", "300m", "400m" +}; + +static const char *mmc_mux_p[] __initconst = { + "100k", "25m", "49p5m", "99m", "187p5m", "150m", "198m", "400k" +}; + +static const char *sysapb_mux_p[] __initconst = { + "24m", "50m", +}; + +static const char *sysbus_mux_p[] __initconst = { + "24m", "300m" +}; + +static const char *uart_mux_p[] __initconst = { "50m", "24m", "3m" }; + +static const char *a73_clksel_mux_p[] __initconst = { + "24m", "apll", "1000m" +}; + +static const u32 fmc_mux_table[] = { 0, 1, 2, 3, 4, 5, 6, 7 }; +static const u32 mmc_mux_table[] = { 0, 1, 2, 3, 4, 5, 6, 7 }; +static const u32 sysapb_mux_table[] = { 0, 1 }; +static const u32 sysbus_mux_table[] = { 0, 1 }; +static const u32 uart_mux_table[] = { 0, 1, 2 }; +static const u32 a73_clksel_mux_table[] = { 0, 1, 2 }; + +static struct hisi_mux_clock hi3559av100_mux_clks_crg[] __initdata = { + { + HI3559AV100_FMC_MUX, "fmc_mux", fmc_mux_p, ARRAY_SIZE(fmc_mux_p), + CLK_SET_RATE_PARENT, 0x170, 2, 3, 0, fmc_mux_table, + }, + { + HI3559AV100_MMC0_MUX, "mmc0_mux", mmc_mux_p, ARRAY_SIZE(mmc_mux_p), + CLK_SET_RATE_PARENT, 0x1a8, 24, 3, 0, mmc_mux_table, + }, + { + HI3559AV100_MMC1_MUX, "mmc1_mux", mmc_mux_p, ARRAY_SIZE(mmc_mux_p), + CLK_SET_RATE_PARENT, 0x1ec, 24, 3, 0, mmc_mux_table, + }, + + { + HI3559AV100_MMC2_MUX, "mmc2_mux", mmc_mux_p, ARRAY_SIZE(mmc_mux_p), + CLK_SET_RATE_PARENT, 0x214, 24, 3, 0, mmc_mux_table, + }, + + { + HI3559AV100_MMC3_MUX, "mmc3_mux", mmc_mux_p, ARRAY_SIZE(mmc_mux_p), + CLK_SET_RATE_PARENT, 0x23c, 24, 3, 0, mmc_mux_table, + }, + + { + HI3559AV100_SYSAPB_MUX, "sysapb_mux", sysapb_mux_p, ARRAY_SIZE(sysapb_mux_p), + CLK_SET_RATE_PARENT, 0xe8, 3, 1, 0, sysapb_mux_table + }, + + { + HI3559AV100_SYSBUS_MUX, "sysbus_mux", sysbus_mux_p, ARRAY_SIZE(sysbus_mux_p), + CLK_SET_RATE_PARENT, 0xe8, 0, 1, 0, sysbus_mux_table + }, + + { + HI3559AV100_UART_MUX, "uart_mux", uart_mux_p, ARRAY_SIZE(uart_mux_p), + CLK_SET_RATE_PARENT, 0x198, 28, 2, 0, uart_mux_table + }, + + { + HI3559AV100_A73_MUX, "a73_mux", a73_clksel_mux_p, ARRAY_SIZE(a73_clksel_mux_p), + CLK_SET_RATE_PARENT, 0xe4, 0, 2, 0, a73_clksel_mux_table + }, +}; + +static struct hisi_gate_clock hi3559av100_gate_clks[] __initdata = { + { + HI3559AV100_FMC_CLK, "clk_fmc", "fmc_mux", + CLK_SET_RATE_PARENT, 0x170, 1, 0, + }, + { + HI3559AV100_MMC0_CLK, "clk_mmc0", "mmc0_mux", + CLK_SET_RATE_PARENT, 0x1a8, 28, 0, + }, + { + HI3559AV100_MMC1_CLK, "clk_mmc1", "mmc1_mux", + CLK_SET_RATE_PARENT, 0x1ec, 28, 0, + }, + { + HI3559AV100_MMC2_CLK, "clk_mmc2", "mmc2_mux", + CLK_SET_RATE_PARENT, 0x214, 28, 0, + }, + { + HI3559AV100_MMC3_CLK, "clk_mmc3", "mmc3_mux", + CLK_SET_RATE_PARENT, 0x23c, 28, 0, + }, + { + HI3559AV100_UART0_CLK, "clk_uart0", "uart_mux", + CLK_SET_RATE_PARENT, 0x198, 23, 0, + }, + { + HI3559AV100_UART1_CLK, "clk_uart1", "uart_mux", + CLK_SET_RATE_PARENT, 0x198, 24, 0, + }, + { + HI3559AV100_UART2_CLK, "clk_uart2", "uart_mux", + CLK_SET_RATE_PARENT, 0x198, 25, 0, + }, + { + HI3559AV100_UART3_CLK, "clk_uart3", "uart_mux", + CLK_SET_RATE_PARENT, 0x198, 26, 0, + }, + { + HI3559AV100_UART4_CLK, "clk_uart4", "uart_mux", + CLK_SET_RATE_PARENT, 0x198, 27, 0, + }, + { + HI3559AV100_ETH_CLK, "clk_eth", NULL, + CLK_SET_RATE_PARENT, 0x0174, 1, 0, + }, + { + HI3559AV100_ETH_MACIF_CLK, "clk_eth_macif", NULL, + CLK_SET_RATE_PARENT, 0x0174, 5, 0, + }, + { + HI3559AV100_ETH1_CLK, "clk_eth1", NULL, + CLK_SET_RATE_PARENT, 0x0174, 3, 0, + }, + { + HI3559AV100_ETH1_MACIF_CLK, "clk_eth1_macif", NULL, + CLK_SET_RATE_PARENT, 0x0174, 7, 0, + }, + { + HI3559AV100_I2C0_CLK, "clk_i2c0", "50m", + CLK_SET_RATE_PARENT, 0x01a0, 16, 0, + }, + { + HI3559AV100_I2C1_CLK, "clk_i2c1", "50m", + CLK_SET_RATE_PARENT, 0x01a0, 17, 0, + }, + { + HI3559AV100_I2C2_CLK, "clk_i2c2", "50m", + CLK_SET_RATE_PARENT, 0x01a0, 18, 0, + }, + { + HI3559AV100_I2C3_CLK, "clk_i2c3", "50m", + CLK_SET_RATE_PARENT, 0x01a0, 19, 0, + }, + { + HI3559AV100_I2C4_CLK, "clk_i2c4", "50m", + CLK_SET_RATE_PARENT, 0x01a0, 20, 0, + }, + { + HI3559AV100_I2C5_CLK, "clk_i2c5", "50m", + CLK_SET_RATE_PARENT, 0x01a0, 21, 0, + }, + { + HI3559AV100_I2C6_CLK, "clk_i2c6", "50m", + CLK_SET_RATE_PARENT, 0x01a0, 22, 0, + }, + { + HI3559AV100_I2C7_CLK, "clk_i2c7", "50m", + CLK_SET_RATE_PARENT, 0x01a0, 23, 0, + }, + { + HI3559AV100_I2C8_CLK, "clk_i2c8", "50m", + CLK_SET_RATE_PARENT, 0x01a0, 24, 0, + }, + { + HI3559AV100_I2C9_CLK, "clk_i2c9", "50m", + CLK_SET_RATE_PARENT, 0x01a0, 25, 0, + }, + { + HI3559AV100_I2C10_CLK, "clk_i2c10", "50m", + CLK_SET_RATE_PARENT, 0x01a0, 26, 0, + }, + { + HI3559AV100_I2C11_CLK, "clk_i2c11", "50m", + CLK_SET_RATE_PARENT, 0x01a0, 27, 0, + }, + { + HI3559AV100_SPI0_CLK, "clk_spi0", "100m", + CLK_SET_RATE_PARENT, 0x0198, 16, 0, + }, + { + HI3559AV100_SPI1_CLK, "clk_spi1", "100m", + CLK_SET_RATE_PARENT, 0x0198, 17, 0, + }, + { + HI3559AV100_SPI2_CLK, "clk_spi2", "100m", + CLK_SET_RATE_PARENT, 0x0198, 18, 0, + }, + { + HI3559AV100_SPI3_CLK, "clk_spi3", "100m", + CLK_SET_RATE_PARENT, 0x0198, 19, 0, + }, + { + HI3559AV100_SPI4_CLK, "clk_spi4", "100m", + CLK_SET_RATE_PARENT, 0x0198, 20, 0, + }, + { + HI3559AV100_SPI5_CLK, "clk_spi5", "100m", + CLK_SET_RATE_PARENT, 0x0198, 21, 0, + }, + { + HI3559AV100_SPI6_CLK, "clk_spi6", "100m", + CLK_SET_RATE_PARENT, 0x0198, 22, 0, + }, + { + HI3559AV100_EDMAC_AXICLK, "axi_clk_edmac", NULL, + CLK_SET_RATE_PARENT, 0x16c, 6, 0, + }, + { + HI3559AV100_EDMAC_CLK, "clk_edmac", NULL, + CLK_SET_RATE_PARENT, 0x16c, 5, 0, + }, + { + HI3559AV100_EDMAC1_AXICLK, "axi_clk_edmac1", NULL, + CLK_SET_RATE_PARENT, 0x16c, 9, 0, + }, + { + HI3559AV100_EDMAC1_CLK, "clk_edmac1", NULL, + CLK_SET_RATE_PARENT, 0x16c, 8, 0, + }, + { + HI3559AV100_VDMAC_CLK, "clk_vdmac", NULL, + CLK_SET_RATE_PARENT, 0x14c, 5, 0, + }, +}; + +static struct hi3559av100_pll_clock hi3559av100_pll_clks[] __initdata = { + { + HI3559AV100_APLL_CLK, "apll", NULL, 0x0, 0, 24, 24, 3, 28, 3, + 0x4, 0, 12, 12, 6 + }, + { + HI3559AV100_GPLL_CLK, "gpll", NULL, 0x20, 0, 24, 24, 3, 28, 3, + 0x24, 0, 12, 12, 6 + }, +}; + +#define to_pll_clk(_hw) container_of(_hw, struct hi3559av100_clk_pll, hw) +static void hi3559av100_calc_pll(u32 *frac_val, u32 *postdiv1_val, + u32 *postdiv2_val, + u32 *fbdiv_val, u32 *refdiv_val, u64 rate) +{ + u64 rem; + + *postdiv1_val = 2; + *postdiv2_val = 1; + + rate = rate * ((*postdiv1_val) * (*postdiv2_val)); + + *frac_val = 0; + rem = do_div(rate, 1000000); + rem = do_div(rate, PLL_MASK_WIDTH); + *fbdiv_val = rate; + *refdiv_val = 1; + rem = rem * (1 << PLL_MASK_WIDTH); + do_div(rem, PLL_MASK_WIDTH); + *frac_val = rem; +} + +static int clk_pll_set_rate(struct clk_hw *hw, + unsigned long rate, + unsigned long parent_rate) +{ + struct hi3559av100_clk_pll *clk = to_pll_clk(hw); + u32 frac_val, postdiv1_val, postdiv2_val, fbdiv_val, refdiv_val; + u32 val; + + postdiv1_val = postdiv2_val = 0; + + hi3559av100_calc_pll(&frac_val, &postdiv1_val, &postdiv2_val, + &fbdiv_val, &refdiv_val, (u64)rate); + + val = readl_relaxed(clk->ctrl_reg1); + val &= ~(((1 << clk->frac_width) - 1) << clk->frac_shift); + val &= ~(((1 << clk->postdiv1_width) - 1) << clk->postdiv1_shift); + val &= ~(((1 << clk->postdiv2_width) - 1) << clk->postdiv2_shift); + + val |= frac_val << clk->frac_shift; + val |= postdiv1_val << clk->postdiv1_shift; + val |= postdiv2_val << clk->postdiv2_shift; + writel_relaxed(val, clk->ctrl_reg1); + + val = readl_relaxed(clk->ctrl_reg2); + val &= ~(((1 << clk->fbdiv_width) - 1) << clk->fbdiv_shift); + val &= ~(((1 << clk->refdiv_width) - 1) << clk->refdiv_shift); + + val |= fbdiv_val << clk->fbdiv_shift; + val |= refdiv_val << clk->refdiv_shift; + writel_relaxed(val, clk->ctrl_reg2); + + return 0; +} + +static unsigned long clk_pll_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct hi3559av100_clk_pll *clk = to_pll_clk(hw); + u64 frac_val, fbdiv_val, refdiv_val; + u32 postdiv1_val, postdiv2_val; + u32 val; + u64 tmp, rate; + + val = readl_relaxed(clk->ctrl_reg1); + val = val >> clk->frac_shift; + val &= ((1 << clk->frac_width) - 1); + frac_val = val; + + val = readl_relaxed(clk->ctrl_reg1); + val = val >> clk->postdiv1_shift; + val &= ((1 << clk->postdiv1_width) - 1); + postdiv1_val = val; + + val = readl_relaxed(clk->ctrl_reg1); + val = val >> clk->postdiv2_shift; + val &= ((1 << clk->postdiv2_width) - 1); + postdiv2_val = val; + + val = readl_relaxed(clk->ctrl_reg2); + val = val >> clk->fbdiv_shift; + val &= ((1 << clk->fbdiv_width) - 1); + fbdiv_val = val; + + val = readl_relaxed(clk->ctrl_reg2); + val = val >> clk->refdiv_shift; + val &= ((1 << clk->refdiv_width) - 1); + refdiv_val = val; + + /* rate = 24000000 * (fbdiv + frac / (1<<24) ) / refdiv */ + rate = 0; + tmp = 24000000 * fbdiv_val + (24000000 * frac_val) / (1 << 24); + rate += tmp; + do_div(rate, refdiv_val); + do_div(rate, postdiv1_val * postdiv2_val); + + return rate; +} + +static const struct clk_ops hisi_clk_pll_ops = { + .set_rate = clk_pll_set_rate, + .recalc_rate = clk_pll_recalc_rate, +}; + +static void hisi_clk_register_pll(struct hi3559av100_pll_clock *clks, + int nums, struct hisi_clock_data *data, struct device *dev) +{ + void __iomem *base = data->base; + struct hi3559av100_clk_pll *p_clk = NULL; + struct clk *clk = NULL; + struct clk_init_data init; + int i; + + p_clk = devm_kzalloc(dev, sizeof(*p_clk) * nums, GFP_KERNEL); + + if (!p_clk) + return; + + for (i = 0; i < nums; i++) { + init.name = clks[i].name; + init.flags = 0; + init.parent_names = + (clks[i].parent_name ? &clks[i].parent_name : NULL); + init.num_parents = (clks[i].parent_name ? 1 : 0); + init.ops = &hisi_clk_pll_ops; + + p_clk->ctrl_reg1 = base + clks[i].ctrl_reg1; + p_clk->frac_shift = clks[i].frac_shift; + p_clk->frac_width = clks[i].frac_width; + p_clk->postdiv1_shift = clks[i].postdiv1_shift; + p_clk->postdiv1_width = clks[i].postdiv1_width; + p_clk->postdiv2_shift = clks[i].postdiv2_shift; + p_clk->postdiv2_width = clks[i].postdiv2_width; + + p_clk->ctrl_reg2 = base + clks[i].ctrl_reg2; + p_clk->fbdiv_shift = clks[i].fbdiv_shift; + p_clk->fbdiv_width = clks[i].fbdiv_width; + p_clk->refdiv_shift = clks[i].refdiv_shift; + p_clk->refdiv_width = clks[i].refdiv_width; + p_clk->hw.init = &init; + + clk = clk_register(NULL, &p_clk->hw); + if (IS_ERR(clk)) { + devm_kfree(dev, p_clk); + dev_err(dev, "%s: failed to register clock %s\n", + __func__, clks[i].name); + continue; + } + + data->clk_data.clks[clks[i].id] = clk; + p_clk++; + } +} + +static __init struct hisi_clock_data *hi3559av100_clk_register( + struct platform_device *pdev) +{ + struct hisi_clock_data *clk_data; + int ret; + + clk_data = hisi_clk_alloc(pdev, HI3559AV100_CRG_NR_CLKS); + if (!clk_data) + return ERR_PTR(-ENOMEM); + + ret = hisi_clk_register_fixed_rate(hi3559av100_fixed_rate_clks_crg, + ARRAY_SIZE(hi3559av100_fixed_rate_clks_crg), clk_data); + if (ret) + return ERR_PTR(ret); + + hisi_clk_register_pll(hi3559av100_pll_clks, + ARRAY_SIZE(hi3559av100_pll_clks), clk_data, &pdev->dev); + + ret = hisi_clk_register_mux(hi3559av100_mux_clks_crg, + ARRAY_SIZE(hi3559av100_mux_clks_crg), clk_data); + if (ret) + goto unregister_fixed_rate; + + ret = hisi_clk_register_gate(hi3559av100_gate_clks, + ARRAY_SIZE(hi3559av100_gate_clks), clk_data); + if (ret) + goto unregister_mux; + + ret = of_clk_add_provider(pdev->dev.of_node, + of_clk_src_onecell_get, &clk_data->clk_data); + if (ret) + goto unregister_gate; + + return clk_data; + +unregister_gate: + hisi_clk_unregister_gate(hi3559av100_gate_clks, + ARRAY_SIZE(hi3559av100_gate_clks), clk_data); +unregister_mux: + hisi_clk_unregister_mux(hi3559av100_mux_clks_crg, + ARRAY_SIZE(hi3559av100_mux_clks_crg), clk_data); +unregister_fixed_rate: + hisi_clk_unregister_fixed_rate(hi3559av100_fixed_rate_clks_crg, + ARRAY_SIZE(hi3559av100_fixed_rate_clks_crg), clk_data); + return ERR_PTR(ret); +} + +static __init void hi3559av100_clk_unregister(struct platform_device *pdev) +{ + struct hisi_crg_dev *crg = platform_get_drvdata(pdev); + + of_clk_del_provider(pdev->dev.of_node); + + hisi_clk_unregister_gate(hi3559av100_gate_clks, + ARRAY_SIZE(hi3559av100_gate_clks), crg->clk_data); + hisi_clk_unregister_mux(hi3559av100_mux_clks_crg, + ARRAY_SIZE(hi3559av100_mux_clks_crg), crg->clk_data); + hisi_clk_unregister_fixed_rate(hi3559av100_fixed_rate_clks_crg, + ARRAY_SIZE(hi3559av100_fixed_rate_clks_crg), crg->clk_data); +} + +static const struct hisi_crg_funcs hi3559av100_crg_funcs = { + .register_clks = hi3559av100_clk_register, + .unregister_clks = hi3559av100_clk_unregister, +}; + +static struct hisi_fixed_rate_clock hi3559av100_shub_fixed_rate_clks[] + __initdata = { + { HI3559AV100_SHUB_SOURCE_SOC_24M, "clk_source_24M", NULL, 0, 24000000UL, }, + { HI3559AV100_SHUB_SOURCE_SOC_200M, "clk_source_200M", NULL, 0, 200000000UL, }, + { HI3559AV100_SHUB_SOURCE_SOC_300M, "clk_source_300M", NULL, 0, 300000000UL, }, + { HI3559AV100_SHUB_SOURCE_PLL, "clk_source_PLL", NULL, 0, 192000000UL, }, + { HI3559AV100_SHUB_I2C0_CLK, "clk_shub_i2c0", NULL, 0, 48000000UL, }, + { HI3559AV100_SHUB_I2C1_CLK, "clk_shub_i2c1", NULL, 0, 48000000UL, }, + { HI3559AV100_SHUB_I2C2_CLK, "clk_shub_i2c2", NULL, 0, 48000000UL, }, + { HI3559AV100_SHUB_I2C3_CLK, "clk_shub_i2c3", NULL, 0, 48000000UL, }, + { HI3559AV100_SHUB_I2C4_CLK, "clk_shub_i2c4", NULL, 0, 48000000UL, }, + { HI3559AV100_SHUB_I2C5_CLK, "clk_shub_i2c5", NULL, 0, 48000000UL, }, + { HI3559AV100_SHUB_I2C6_CLK, "clk_shub_i2c6", NULL, 0, 48000000UL, }, + { HI3559AV100_SHUB_I2C7_CLK, "clk_shub_i2c7", NULL, 0, 48000000UL, }, + { HI3559AV100_SHUB_UART_CLK_32K, "clk_uart_32K", NULL, 0, 32000UL, }, +}; + +/* shub mux clk */ +static u32 shub_source_clk_mux_table[] = {0, 1, 2, 3}; +static const char *shub_source_clk_mux_p[] __initconst = { + "clk_source_24M", "clk_source_200M", "clk_source_300M", "clk_source_PLL" +}; + +static u32 shub_uart_source_clk_mux_table[] = {0, 1, 2, 3}; +static const char *shub_uart_source_clk_mux_p[] __initconst = { + "clk_uart_32K", "clk_uart_div_clk", "clk_uart_div_clk", "clk_source_24M" +}; + +static struct hisi_mux_clock hi3559av100_shub_mux_clks[] __initdata = { + { + HI3559AV100_SHUB_SOURCE_CLK, "shub_clk", shub_source_clk_mux_p, + ARRAY_SIZE(shub_source_clk_mux_p), + 0, 0x0, 0, 2, 0, shub_source_clk_mux_table, + }, + + { + HI3559AV100_SHUB_UART_SOURCE_CLK, "shub_uart_source_clk", + shub_uart_source_clk_mux_p, ARRAY_SIZE(shub_uart_source_clk_mux_p), + 0, 0x1c, 28, 2, 0, shub_uart_source_clk_mux_table, + }, +}; + + +/* shub div clk */ +static struct clk_div_table shub_spi_clk_table[] = {{0, 8}, {1, 4}, {2, 2}}; +static struct clk_div_table shub_uart_div_clk_table[] = {{1, 8}, {2, 4}}; + +static struct hisi_divider_clock hi3559av100_shub_div_clks[] __initdata = { + { HI3559AV100_SHUB_SPI_SOURCE_CLK, "clk_spi_clk", "shub_clk", 0, 0x20, 24, 2, + CLK_DIVIDER_ALLOW_ZERO, shub_spi_clk_table, + }, + { HI3559AV100_SHUB_UART_DIV_CLK, "clk_uart_div_clk", "shub_clk", 0, 0x1c, 28, 2, + CLK_DIVIDER_ALLOW_ZERO, shub_uart_div_clk_table, + }, +}; + +/* shub gate clk */ +static struct hisi_gate_clock hi3559av100_shub_gate_clks[] __initdata = { + { + HI3559AV100_SHUB_SPI0_CLK, "clk_shub_spi0", "clk_spi_clk", + 0, 0x20, 1, 0, + }, + { + HI3559AV100_SHUB_SPI1_CLK, "clk_shub_spi1", "clk_spi_clk", + 0, 0x20, 5, 0, + }, + { + HI3559AV100_SHUB_SPI2_CLK, "clk_shub_spi2", "clk_spi_clk", + 0, 0x20, 9, 0, + }, + + { + HI3559AV100_SHUB_UART0_CLK, "clk_shub_uart0", "shub_uart_source_clk", + 0, 0x1c, 1, 0, + }, + { + HI3559AV100_SHUB_UART1_CLK, "clk_shub_uart1", "shub_uart_source_clk", + 0, 0x1c, 5, 0, + }, + { + HI3559AV100_SHUB_UART2_CLK, "clk_shub_uart2", "shub_uart_source_clk", + 0, 0x1c, 9, 0, + }, + { + HI3559AV100_SHUB_UART3_CLK, "clk_shub_uart3", "shub_uart_source_clk", + 0, 0x1c, 13, 0, + }, + { + HI3559AV100_SHUB_UART4_CLK, "clk_shub_uart4", "shub_uart_source_clk", + 0, 0x1c, 17, 0, + }, + { + HI3559AV100_SHUB_UART5_CLK, "clk_shub_uart5", "shub_uart_source_clk", + 0, 0x1c, 21, 0, + }, + { + HI3559AV100_SHUB_UART6_CLK, "clk_shub_uart6", "shub_uart_source_clk", + 0, 0x1c, 25, 0, + }, + + { + HI3559AV100_SHUB_EDMAC_CLK, "clk_shub_dmac", "shub_clk", + 0, 0x24, 4, 0, + }, +}; + +static int hi3559av100_shub_default_clk_set(void) +{ + void __iomem *crg_base; + unsigned int val; + + crg_base = ioremap(CRG_BASE_ADDR, SZ_4K); + + /* SSP: 192M/2 */ + val = readl_relaxed(crg_base + 0x20); + val |= (0x2 << 24); + writel_relaxed(val, crg_base + 0x20); + + /* UART: 192M/8 */ + val = readl_relaxed(crg_base + 0x1C); + val |= (0x1 << 28); + writel_relaxed(val, crg_base + 0x1C); + + iounmap(crg_base); + crg_base = NULL; + + return 0; +} + +static __init struct hisi_clock_data *hi3559av100_shub_clk_register( + struct platform_device *pdev) +{ + struct hisi_clock_data *clk_data = NULL; + int ret; + + hi3559av100_shub_default_clk_set(); + + clk_data = hisi_clk_alloc(pdev, HI3559AV100_SHUB_NR_CLKS); + if (!clk_data) + return ERR_PTR(-ENOMEM); + + ret = hisi_clk_register_fixed_rate(hi3559av100_shub_fixed_rate_clks, + ARRAY_SIZE(hi3559av100_shub_fixed_rate_clks), clk_data); + if (ret) + return ERR_PTR(ret); + + ret = hisi_clk_register_mux(hi3559av100_shub_mux_clks, + ARRAY_SIZE(hi3559av100_shub_mux_clks), clk_data); + if (ret) + goto unregister_fixed_rate; + + ret = hisi_clk_register_divider(hi3559av100_shub_div_clks, + ARRAY_SIZE(hi3559av100_shub_div_clks), clk_data); + if (ret) + goto unregister_mux; + + ret = hisi_clk_register_gate(hi3559av100_shub_gate_clks, + ARRAY_SIZE(hi3559av100_shub_gate_clks), clk_data); + if (ret) + goto unregister_factor; + + ret = of_clk_add_provider(pdev->dev.of_node, + of_clk_src_onecell_get, &clk_data->clk_data); + if (ret) + goto unregister_gate; + + return clk_data; + +unregister_gate: + hisi_clk_unregister_gate(hi3559av100_shub_gate_clks, + ARRAY_SIZE(hi3559av100_shub_gate_clks), clk_data); +unregister_factor: + hisi_clk_unregister_divider(hi3559av100_shub_div_clks, + ARRAY_SIZE(hi3559av100_shub_div_clks), clk_data); +unregister_mux: + hisi_clk_unregister_mux(hi3559av100_shub_mux_clks, + ARRAY_SIZE(hi3559av100_shub_mux_clks), clk_data); +unregister_fixed_rate: + hisi_clk_unregister_fixed_rate(hi3559av100_shub_fixed_rate_clks, + ARRAY_SIZE(hi3559av100_shub_fixed_rate_clks), clk_data); + return ERR_PTR(ret); +} + +static __init void hi3559av100_shub_clk_unregister(struct platform_device *pdev) +{ + struct hisi_crg_dev *crg = platform_get_drvdata(pdev); + + of_clk_del_provider(pdev->dev.of_node); + + hisi_clk_unregister_gate(hi3559av100_shub_gate_clks, + ARRAY_SIZE(hi3559av100_shub_gate_clks), crg->clk_data); + hisi_clk_unregister_divider(hi3559av100_shub_div_clks, + ARRAY_SIZE(hi3559av100_shub_div_clks), crg->clk_data); + hisi_clk_unregister_mux(hi3559av100_shub_mux_clks, + ARRAY_SIZE(hi3559av100_shub_mux_clks), crg->clk_data); + hisi_clk_unregister_fixed_rate(hi3559av100_shub_fixed_rate_clks, + ARRAY_SIZE(hi3559av100_shub_fixed_rate_clks), crg->clk_data); +} + +static const struct hisi_crg_funcs hi3559av100_shub_crg_funcs = { + .register_clks = hi3559av100_shub_clk_register, + .unregister_clks = hi3559av100_shub_clk_unregister, +}; + +static const struct of_device_id hi3559av100_crg_match_table[] = { + { + .compatible = "hisilicon,hi3559av100-clock", + .data = &hi3559av100_crg_funcs + }, + { + .compatible = "hisilicon,hi3559av100-shub-clock", + .data = &hi3559av100_shub_crg_funcs + }, + { } +}; +MODULE_DEVICE_TABLE(of, hi3559av100_crg_match_table); + +static int hi3559av100_crg_probe(struct platform_device *pdev) +{ + struct hisi_crg_dev *crg; + + crg = devm_kmalloc(&pdev->dev, sizeof(*crg), GFP_KERNEL); + if (!crg) + return -ENOMEM; + + crg->funcs = of_device_get_match_data(&pdev->dev); + if (!crg->funcs) + return -ENOENT; + + crg->rstc = hisi_reset_init(pdev); + if (!crg->rstc) + return -ENOMEM; + + crg->clk_data = crg->funcs->register_clks(pdev); + if (IS_ERR(crg->clk_data)) { + hisi_reset_exit(crg->rstc); + return PTR_ERR(crg->clk_data); + } + + platform_set_drvdata(pdev, crg); + return 0; +} + +static int hi3559av100_crg_remove(struct platform_device *pdev) +{ + struct hisi_crg_dev *crg = platform_get_drvdata(pdev); + + hisi_reset_exit(crg->rstc); + crg->funcs->unregister_clks(pdev); + return 0; +} + +static struct platform_driver hi3559av100_crg_driver = { + .probe = hi3559av100_crg_probe, + .remove = hi3559av100_crg_remove, + .driver = { + .name = "hi3559av100-clock", + .of_match_table = hi3559av100_crg_match_table, + }, +}; + +static int __init hi3559av100_crg_init(void) +{ + return platform_driver_register(&hi3559av100_crg_driver); +} +core_initcall(hi3559av100_crg_init); + +static void __exit hi3559av100_crg_exit(void) +{ + platform_driver_unregister(&hi3559av100_crg_driver); +} +module_exit(hi3559av100_crg_exit); + + +MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("HiSilicon Hi3559AV100 CRG Driver"); diff --git a/drivers/clk/hisilicon/clk.c b/drivers/clk/hisilicon/clk.c index 54d9fdc93599..9361fba7cd4c 100644 --- a/drivers/clk/hisilicon/clk.c +++ b/drivers/clk/hisilicon/clk.c @@ -162,7 +162,7 @@ int hisi_clk_register_mux(const struct hisi_mux_clock *clks, clks[i].num_parents, clks[i].flags, base + clks[i].offset, clks[i].shift, mask, clks[i].mux_flags, - clks[i].table, &hisi_clk_lock); + (u32 *)clks[i].table, &hisi_clk_lock); if (IS_ERR(clk)) { pr_err("%s: failed to register clock %s\n", __func__, clks[i].name); diff --git a/drivers/clk/hisilicon/clk.h b/drivers/clk/hisilicon/clk.h index 61cbd90d1213..7a9b42e1b027 100644 --- a/drivers/clk/hisilicon/clk.h +++ b/drivers/clk/hisilicon/clk.h @@ -50,7 +50,7 @@ struct hisi_mux_clock { u8 shift; u8 width; u8 mux_flags; - u32 *table; + const u32 *table; const char *alias; }; From 590ff40e06d802f6080e03443c6bcff0cd4ba37d Mon Sep 17 00:00:00 2001 From: Gabriel Fernandez Date: Thu, 17 Jun 2021 07:18:09 +0200 Subject: [PATCH 150/161] reset: stm32mp1: remove stm32mp1 reset st32mp1 RCC reset driver was moved into stm32mp1 RCC clock driver. Signed-off-by: Gabriel Fernandez Link: https://lore.kernel.org/r/20210617051814.12018-7-gabriel.fernandez@foss.st.com Acked-by: Philipp Zabel Signed-off-by: Stephen Boyd --- drivers/reset/Kconfig | 6 -- drivers/reset/Makefile | 1 - drivers/reset/reset-stm32mp1.c | 115 --------------------------------- 3 files changed, 122 deletions(-) delete mode 100644 drivers/reset/reset-stm32mp1.c diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig index 3e7f55e44d84..29fb33c0e26d 100644 --- a/drivers/reset/Kconfig +++ b/drivers/reset/Kconfig @@ -199,12 +199,6 @@ config RESET_SIMPLE - ZTE's zx2967 family - SiFive FU740 SoCs -config RESET_STM32MP157 - bool "STM32MP157 Reset Driver" if COMPILE_TEST - default MACH_STM32MP157 - help - This enables the RCC reset controller driver for STM32 MPUs. - config RESET_SOCFPGA bool "SoCFPGA Reset Driver" if COMPILE_TEST && (!ARM || !ARCH_INTEL_SOCFPGA) default ARM && ARCH_INTEL_SOCFPGA diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile index 65a118a91b27..ac3e612ad953 100644 --- a/drivers/reset/Makefile +++ b/drivers/reset/Makefile @@ -26,7 +26,6 @@ obj-$(CONFIG_RESET_QCOM_PDC) += reset-qcom-pdc.o obj-$(CONFIG_RESET_RASPBERRYPI) += reset-raspberrypi.o obj-$(CONFIG_RESET_SCMI) += reset-scmi.o obj-$(CONFIG_RESET_SIMPLE) += reset-simple.o -obj-$(CONFIG_RESET_STM32MP157) += reset-stm32mp1.o obj-$(CONFIG_RESET_SOCFPGA) += reset-socfpga.o obj-$(CONFIG_RESET_SUNXI) += reset-sunxi.o obj-$(CONFIG_RESET_TI_SCI) += reset-ti-sci.o diff --git a/drivers/reset/reset-stm32mp1.c b/drivers/reset/reset-stm32mp1.c deleted file mode 100644 index b221a28041fa..000000000000 --- a/drivers/reset/reset-stm32mp1.c +++ /dev/null @@ -1,115 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright (C) STMicroelectronics 2018 - All Rights Reserved - * Author: Gabriel Fernandez for STMicroelectronics. - */ - -#include -#include -#include -#include -#include -#include - -#define CLR_OFFSET 0x4 - -struct stm32_reset_data { - struct reset_controller_dev rcdev; - void __iomem *membase; -}; - -static inline struct stm32_reset_data * -to_stm32_reset_data(struct reset_controller_dev *rcdev) -{ - return container_of(rcdev, struct stm32_reset_data, rcdev); -} - -static int stm32_reset_update(struct reset_controller_dev *rcdev, - unsigned long id, bool assert) -{ - struct stm32_reset_data *data = to_stm32_reset_data(rcdev); - int reg_width = sizeof(u32); - int bank = id / (reg_width * BITS_PER_BYTE); - int offset = id % (reg_width * BITS_PER_BYTE); - void __iomem *addr; - - addr = data->membase + (bank * reg_width); - if (!assert) - addr += CLR_OFFSET; - - writel(BIT(offset), addr); - - return 0; -} - -static int stm32_reset_assert(struct reset_controller_dev *rcdev, - unsigned long id) -{ - return stm32_reset_update(rcdev, id, true); -} - -static int stm32_reset_deassert(struct reset_controller_dev *rcdev, - unsigned long id) -{ - return stm32_reset_update(rcdev, id, false); -} - -static int stm32_reset_status(struct reset_controller_dev *rcdev, - unsigned long id) -{ - struct stm32_reset_data *data = to_stm32_reset_data(rcdev); - int reg_width = sizeof(u32); - int bank = id / (reg_width * BITS_PER_BYTE); - int offset = id % (reg_width * BITS_PER_BYTE); - u32 reg; - - reg = readl(data->membase + (bank * reg_width)); - - return !!(reg & BIT(offset)); -} - -static const struct reset_control_ops stm32_reset_ops = { - .assert = stm32_reset_assert, - .deassert = stm32_reset_deassert, - .status = stm32_reset_status, -}; - -static const struct of_device_id stm32_reset_dt_ids[] = { - { .compatible = "st,stm32mp1-rcc"}, - { /* sentinel */ }, -}; - -static int stm32_reset_probe(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct stm32_reset_data *data; - void __iomem *membase; - struct resource *res; - - data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); - if (!data) - return -ENOMEM; - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - membase = devm_ioremap_resource(dev, res); - if (IS_ERR(membase)) - return PTR_ERR(membase); - - data->membase = membase; - data->rcdev.owner = THIS_MODULE; - data->rcdev.nr_resets = resource_size(res) * BITS_PER_BYTE; - data->rcdev.ops = &stm32_reset_ops; - data->rcdev.of_node = dev->of_node; - - return devm_reset_controller_register(dev, &data->rcdev); -} - -static struct platform_driver stm32_reset_driver = { - .probe = stm32_reset_probe, - .driver = { - .name = "stm32mp1-reset", - .of_match_table = stm32_reset_dt_ids, - }, -}; - -builtin_platform_driver(stm32_reset_driver); From bd08b193cf13e26d77dd68dbda1c60c7a2e86b6c Mon Sep 17 00:00:00 2001 From: Gabriel Fernandez Date: Thu, 17 Jun 2021 07:18:10 +0200 Subject: [PATCH 151/161] dt-bindings: clock: add IDs for SCMI clocks on stm32mp15 stm32mp15 TZ secure firmware provides SCMI clocks for oscillators, some PLL output and few secure aware interfaces. This change defines the SCMI clock identifiers used by SCMI agents and servers. Server SCMI0 exposes clocks and reset controllers for resources under RCC[TZEN] configuration control. Server SCMI1 exposes clocks for resources under RCC[MCKPROT] control. Signed-off-by: Etienne Carriere Signed-off-by: Gabriel Fernandez Acked-by: Rob Herring Link: https://lore.kernel.org/r/20210617051814.12018-8-gabriel.fernandez@foss.st.com Signed-off-by: Stephen Boyd --- include/dt-bindings/clock/stm32mp1-clks.h | 27 +++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/include/dt-bindings/clock/stm32mp1-clks.h b/include/dt-bindings/clock/stm32mp1-clks.h index 4cdaf135829c..e02770b98e6c 100644 --- a/include/dt-bindings/clock/stm32mp1-clks.h +++ b/include/dt-bindings/clock/stm32mp1-clks.h @@ -248,4 +248,31 @@ #define STM32MP1_LAST_CLK 232 +/* SCMI clock identifiers */ +#define CK_SCMI0_HSE 0 +#define CK_SCMI0_HSI 1 +#define CK_SCMI0_CSI 2 +#define CK_SCMI0_LSE 3 +#define CK_SCMI0_LSI 4 +#define CK_SCMI0_PLL2_Q 5 +#define CK_SCMI0_PLL2_R 6 +#define CK_SCMI0_MPU 7 +#define CK_SCMI0_AXI 8 +#define CK_SCMI0_BSEC 9 +#define CK_SCMI0_CRYP1 10 +#define CK_SCMI0_GPIOZ 11 +#define CK_SCMI0_HASH1 12 +#define CK_SCMI0_I2C4 13 +#define CK_SCMI0_I2C6 14 +#define CK_SCMI0_IWDG1 15 +#define CK_SCMI0_RNG1 16 +#define CK_SCMI0_RTC 17 +#define CK_SCMI0_RTCAPB 18 +#define CK_SCMI0_SPI6 19 +#define CK_SCMI0_USART1 20 + +#define CK_SCMI1_PLL3_Q 0 +#define CK_SCMI1_PLL3_R 1 +#define CK_SCMI1_MCU 2 + #endif /* _DT_BINDINGS_STM32MP1_CLKS_H_ */ From 256c7521cb5e964c67fc807f0afc27104561018d Mon Sep 17 00:00:00 2001 From: Gabriel Fernandez Date: Thu, 17 Jun 2021 07:18:11 +0200 Subject: [PATCH 152/161] dt-bindings: reset: add IDs for SCMI reset domains on stm32mp15 stm32mp15 TZ secure firmware provides SCMI reset domains for secure resources. This change defines the SCMI reset domain identifiers used by SCMI agents and servers. Stm32mp15 TZ secure firmware provides SCMI clocks for oscillators, some PLL output and few secure aware interfaces. This change defines the SCMI clock identifiers used by SCMI agents and servers. Server SCMI0 exposes reset controllers for resources under RCC[TZEN] configuration control. Signed-off-by: Etienne Carriere Signed-off-by: Gabriel Fernandez Acked-by: Rob Herring Link: https://lore.kernel.org/r/20210617051814.12018-9-gabriel.fernandez@foss.st.com Signed-off-by: Stephen Boyd --- include/dt-bindings/reset/stm32mp1-resets.h | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/include/dt-bindings/reset/stm32mp1-resets.h b/include/dt-bindings/reset/stm32mp1-resets.h index f0c3aaef67a0..bc71924faa54 100644 --- a/include/dt-bindings/reset/stm32mp1-resets.h +++ b/include/dt-bindings/reset/stm32mp1-resets.h @@ -105,4 +105,17 @@ #define GPIOJ_R 19785 #define GPIOK_R 19786 +/* SCMI reset domain identifiers */ +#define RST_SCMI0_SPI6 0 +#define RST_SCMI0_I2C4 1 +#define RST_SCMI0_I2C6 2 +#define RST_SCMI0_USART1 3 +#define RST_SCMI0_STGEN 4 +#define RST_SCMI0_GPIOZ 5 +#define RST_SCMI0_CRYP1 6 +#define RST_SCMI0_HASH1 7 +#define RST_SCMI0_RNG1 8 +#define RST_SCMI0_MDMA 9 +#define RST_SCMI0_MCU 10 + #endif /* _DT_BINDINGS_STM32MP1_RESET_H_ */ From f040e135c59adeddfbe8be276cf9adc88caf678c Mon Sep 17 00:00:00 2001 From: Gabriel Fernandez Date: Thu, 17 Jun 2021 07:18:12 +0200 Subject: [PATCH 153/161] dt-bindings: reset: add MCU HOLD BOOT ID for SCMI reset domains on stm32mp15 Add ID to SCMI0 to exposes reset controller for the MCU HOLD BOOT resource. Signed-off-by: Arnaud Pouliquen Signed-off-by: Gabriel Fernandez Acked-by: Rob Herring Link: https://lore.kernel.org/r/20210617051814.12018-10-gabriel.fernandez@foss.st.com Signed-off-by: Stephen Boyd --- include/dt-bindings/reset/stm32mp1-resets.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/dt-bindings/reset/stm32mp1-resets.h b/include/dt-bindings/reset/stm32mp1-resets.h index bc71924faa54..f3a0ed317835 100644 --- a/include/dt-bindings/reset/stm32mp1-resets.h +++ b/include/dt-bindings/reset/stm32mp1-resets.h @@ -7,6 +7,7 @@ #ifndef _DT_BINDINGS_STM32MP1_RESET_H_ #define _DT_BINDINGS_STM32MP1_RESET_H_ +#define MCU_HOLD_BOOT_R 2144 #define LTDC_R 3072 #define DSI_R 3076 #define DDRPERFM_R 3080 @@ -117,5 +118,6 @@ #define RST_SCMI0_RNG1 8 #define RST_SCMI0_MDMA 9 #define RST_SCMI0_MCU 10 +#define RST_SCMI0_MCU_HOLD_BOOT 11 #endif /* _DT_BINDINGS_STM32MP1_RESET_H_ */ From 94b7888b67c4e301635bbfdea1403ed0693242fd Mon Sep 17 00:00:00 2001 From: Gabriel Fernandez Date: Thu, 17 Jun 2021 07:18:13 +0200 Subject: [PATCH 154/161] dt-bindings: clock: stm32mp1 new compatible for secure rcc Introduce new compatible string "st,stm32mp1-rcc-secure" for stm32mp1 clock driver when the device is configured with RCC security support hardened. Signed-off-by: Etienne Carriere Signed-off-by: Gabriel Fernandez Acked-by: Rob Herring Link: https://lore.kernel.org/r/20210617051814.12018-11-gabriel.fernandez@foss.st.com Signed-off-by: Stephen Boyd --- .../devicetree/bindings/clock/st,stm32mp1-rcc.yaml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/clock/st,stm32mp1-rcc.yaml b/Documentation/devicetree/bindings/clock/st,stm32mp1-rcc.yaml index 4e385508f516..8b1ecb2ecdd5 100644 --- a/Documentation/devicetree/bindings/clock/st,stm32mp1-rcc.yaml +++ b/Documentation/devicetree/bindings/clock/st,stm32mp1-rcc.yaml @@ -54,7 +54,9 @@ properties: compatible: items: - - const: st,stm32mp1-rcc + - enum: + - st,stm32mp1-rcc-secure + - st,stm32mp1-rcc - const: syscon reg: @@ -71,7 +73,7 @@ additionalProperties: false examples: - | rcc: rcc@50000000 { - compatible = "st,stm32mp1-rcc", "syscon"; + compatible = "st,stm32mp1-rcc-secure", "syscon"; reg = <0x50000000 0x1000>; #clock-cells = <1>; #reset-cells = <1>; From 21e743300dd0b9e57425de4a9ba651493b165e03 Mon Sep 17 00:00:00 2001 From: Gabriel Fernandez Date: Thu, 17 Jun 2021 07:18:14 +0200 Subject: [PATCH 155/161] clk: stm32mp1: new compatible for secure RCC support Platform STM32MP1 can be used in configuration where some clock resources cannot be accessed by Linux kernel when executing in non-secure state of the CPU(s). In such configuration, the RCC clock driver must not register clocks it cannot access. They are expected to be registered from another clock driver such as the SCMI clock driver. This change uses specific compatible string "st,stm32mp1-rcc-secure" to specify RCC clock driver configuration where RCC is secure. Signed-off-by: Etienne Carriere Signed-off-by: Gabriel Fernandez Link: https://lore.kernel.org/r/20210617051814.12018-12-gabriel.fernandez@foss.st.com Signed-off-by: Stephen Boyd --- drivers/clk/Kconfig | 10 ++++ drivers/clk/clk-stm32mp1.c | 101 ++++++++++++++++++++++++++++++++++++- 2 files changed, 110 insertions(+), 1 deletion(-) diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index e80918be8e9c..e367a033e121 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig @@ -335,6 +335,16 @@ config COMMON_CLK_STM32MP157 help Support for stm32mp157 SoC family clocks +config COMMON_CLK_STM32MP157_SCMI + bool "stm32mp157 Clock driver with Trusted Firmware" + depends on COMMON_CLK_STM32MP157 + select COMMON_CLK_SCMI + select ARM_SCMI_PROTOCOL + default y + help + Support for stm32mp157 SoC family clocks with Trusted Firmware using + SCMI protocol. + config COMMON_CLK_STM32F def_bool COMMON_CLK && (MACH_STM32F429 || MACH_STM32F469 || MACH_STM32F746) help diff --git a/drivers/clk/clk-stm32mp1.c b/drivers/clk/clk-stm32mp1.c index 6d3a36f81b2d..6adc625e79cb 100644 --- a/drivers/clk/clk-stm32mp1.c +++ b/drivers/clk/clk-stm32mp1.c @@ -2056,11 +2056,61 @@ static const struct clock_config stm32mp1_clock_cfg[] = { _DIV(RCC_DBGCFGR, 0, 3, 0, ck_trace_div_table)), }; +static const u32 stm32mp1_clock_secured[] = { + CK_HSE, + CK_HSI, + CK_CSI, + CK_LSI, + CK_LSE, + PLL1, + PLL2, + PLL1_P, + PLL2_P, + PLL2_Q, + PLL2_R, + CK_MPU, + CK_AXI, + SPI6, + I2C4, + I2C6, + USART1, + RTCAPB, + TZC1, + TZC2, + TZPC, + IWDG1, + BSEC, + STGEN, + GPIOZ, + CRYP1, + HASH1, + RNG1, + BKPSRAM, + RNG1_K, + STGEN_K, + SPI6_K, + I2C4_K, + I2C6_K, + USART1_K, + RTC, +}; + +static bool stm32_check_security(const struct clock_config *cfg) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(stm32mp1_clock_secured); i++) + if (cfg->id == stm32mp1_clock_secured[i]) + return true; + return false; +} + struct stm32_rcc_match_data { const struct clock_config *cfg; unsigned int num; unsigned int maxbinding; u32 clear_offset; + bool (*check_security)(const struct clock_config *cfg); }; static struct stm32_rcc_match_data stm32mp1_data = { @@ -2070,11 +2120,23 @@ static struct stm32_rcc_match_data stm32mp1_data = { .clear_offset = RCC_CLR, }; +static struct stm32_rcc_match_data stm32mp1_data_secure = { + .cfg = stm32mp1_clock_cfg, + .num = ARRAY_SIZE(stm32mp1_clock_cfg), + .maxbinding = STM32MP1_LAST_CLK, + .clear_offset = RCC_CLR, + .check_security = &stm32_check_security +}; + static const struct of_device_id stm32mp1_match_data[] = { { .compatible = "st,stm32mp1-rcc", .data = &stm32mp1_data, }, + { + .compatible = "st,stm32mp1-rcc-secure", + .data = &stm32mp1_data_secure, + }, { } }; MODULE_DEVICE_TABLE(of, stm32mp1_match_data); @@ -2234,6 +2296,9 @@ static int stm32_rcc_clock_init(struct device *dev, void __iomem *base, hws[n] = ERR_PTR(-ENOENT); for (n = 0; n < data->num; n++) { + if (data->check_security && data->check_security(&data->cfg[n])) + continue; + err = stm32_register_hw_clk(dev, clk_data, base, &rlock, &data->cfg[n]); if (err) { @@ -2301,11 +2366,45 @@ out: return ret; } +static int get_clock_deps(struct device *dev) +{ + static const char * const clock_deps_name[] = { + "hsi", "hse", "csi", "lsi", "lse", + }; + size_t deps_size = sizeof(struct clk *) * ARRAY_SIZE(clock_deps_name); + struct clk **clk_deps; + int i; + + clk_deps = devm_kzalloc(dev, deps_size, GFP_KERNEL); + if (!clk_deps) + return -ENOMEM; + + for (i = 0; i < ARRAY_SIZE(clock_deps_name); i++) { + struct clk *clk = of_clk_get_by_name(dev_of_node(dev), + clock_deps_name[i]); + + if (IS_ERR(clk)) { + if (PTR_ERR(clk) != -EINVAL && PTR_ERR(clk) != -ENOENT) + return PTR_ERR(clk); + } else { + /* Device gets a reference count on the clock */ + clk_deps[i] = devm_clk_get(dev, __clk_get_name(clk)); + clk_put(clk); + } + } + + return 0; +} + static int stm32mp1_rcc_clocks_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; + int ret = get_clock_deps(dev); - return stm32mp1_rcc_init(dev); + if (!ret) + ret = stm32mp1_rcc_init(dev); + + return ret; } static int stm32mp1_rcc_clocks_remove(struct platform_device *pdev) From 97a1c5cbbfe4b84573df2edc6b782132f8e012ad Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Mon, 28 Jun 2021 23:07:50 -0700 Subject: [PATCH 156/161] clk: lmk04832: Depend on SPI This driver depends on SPI. Otherwise compilation fails clk-lmk04832.c:(.text+0x1668): undefined reference to `spi_get_device_id' Reported-by: kernel test robot Cc: Liam Beguin Fixes: 3bc61cfd6f4a ("clk: add support for the lmk04832") Link: https://lore.kernel.org/r/20210629060751.3119453-1-sboyd@kernel.org Signed-off-by: Stephen Boyd --- drivers/clk/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index ccf77849bdbd..d49cf3ae52aa 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig @@ -57,6 +57,7 @@ config CLK_HSDK config LMK04832 tristate "Ti LMK04832 JESD204B Compliant Clock Jitter Cleaner" + depends on SPI select REGMAP_SPI help Say yes here to build support for Texas Instruments' LMK04832 Ultra From bf68fdfdec6cd9a14323a61612ae9d7c510fbbdc Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Mon, 28 Jun 2021 23:07:51 -0700 Subject: [PATCH 157/161] clk: lmk04832: Use of match table Presumably we want to use this match table so add a module device table and set the driver match pointer appropriately. Reported-by: kernel test robot Cc: Liam Beguin Fixes: 3bc61cfd6f4a ("clk: add support for the lmk04832") Link: https://lore.kernel.org/r/20210629060751.3119453-2-sboyd@kernel.org Signed-off-by: Stephen Boyd --- drivers/clk/clk-lmk04832.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/clk/clk-lmk04832.c b/drivers/clk/clk-lmk04832.c index 0cd76e626c3d..c1095e733220 100644 --- a/drivers/clk/clk-lmk04832.c +++ b/drivers/clk/clk-lmk04832.c @@ -1573,18 +1573,20 @@ static int lmk04832_remove(struct spi_device *spi) } static const struct spi_device_id lmk04832_id[] = { { "lmk04832", LMK04832 }, - {}, + {} }; MODULE_DEVICE_TABLE(spi, lmk04832_id); static const struct of_device_id lmk04832_of_id[] = { { .compatible = "ti,lmk04832" }, - {}, + {} }; +MODULE_DEVICE_TABLE(of, lmk04832_of_id); static struct spi_driver lmk04832_driver = { .driver = { .name = "lmk04832", + .of_match_table = lmk04832_of_id, }, .probe = lmk04832_probe, .remove = lmk04832_remove, From 610a5d83010eaf02a857321092cf0cd02178bee7 Mon Sep 17 00:00:00 2001 From: Rajan Vaja Date: Mon, 28 Jun 2021 00:01:19 -0700 Subject: [PATCH 158/161] clk: zynqmp: Use firmware specific common clock flags Currently firmware passes CCF specific flags to ZynqMP clock driver. So firmware needs to be updated if CCF flags are changed. The firmware should have its own 'flag number space' that is distinct from the common clk framework's 'flag number space'. So define and use ZynqMP specific common clock flags instead of using CCF flags. Signed-off-by: Rajan Vaja Link: https://lore.kernel.org/r/20210628070122.26217-2-rajan.vaja@xilinx.com Signed-off-by: Stephen Boyd --- drivers/clk/zynqmp/clk-gate-zynqmp.c | 4 +++- drivers/clk/zynqmp/clk-mux-zynqmp.c | 4 +++- drivers/clk/zynqmp/clk-zynqmp.h | 16 ++++++++++++++++ drivers/clk/zynqmp/clkc.c | 25 ++++++++++++++++++++++++- drivers/clk/zynqmp/divider.c | 5 +++-- drivers/clk/zynqmp/pll.c | 4 +++- 6 files changed, 52 insertions(+), 6 deletions(-) diff --git a/drivers/clk/zynqmp/clk-gate-zynqmp.c b/drivers/clk/zynqmp/clk-gate-zynqmp.c index 10c9b889324f..695feaa82da5 100644 --- a/drivers/clk/zynqmp/clk-gate-zynqmp.c +++ b/drivers/clk/zynqmp/clk-gate-zynqmp.c @@ -121,7 +121,9 @@ struct clk_hw *zynqmp_clk_register_gate(const char *name, u32 clk_id, init.name = name; init.ops = &zynqmp_clk_gate_ops; - init.flags = nodes->flag; + + init.flags = zynqmp_clk_map_common_ccf_flags(nodes->flag); + init.parent_names = parents; init.num_parents = 1; diff --git a/drivers/clk/zynqmp/clk-mux-zynqmp.c b/drivers/clk/zynqmp/clk-mux-zynqmp.c index d576c900dee0..42ad324b1c64 100644 --- a/drivers/clk/zynqmp/clk-mux-zynqmp.c +++ b/drivers/clk/zynqmp/clk-mux-zynqmp.c @@ -126,7 +126,9 @@ struct clk_hw *zynqmp_clk_register_mux(const char *name, u32 clk_id, init.ops = &zynqmp_clk_mux_ro_ops; else init.ops = &zynqmp_clk_mux_ops; - init.flags = nodes->flag; + + init.flags = zynqmp_clk_map_common_ccf_flags(nodes->flag); + init.parent_names = parents; init.num_parents = num_parents; mux->flags = nodes->type_flag; diff --git a/drivers/clk/zynqmp/clk-zynqmp.h b/drivers/clk/zynqmp/clk-zynqmp.h index 5beeb41b29fa..aa013a59c7cc 100644 --- a/drivers/clk/zynqmp/clk-zynqmp.h +++ b/drivers/clk/zynqmp/clk-zynqmp.h @@ -10,6 +10,20 @@ #include +/* Common Flags */ +/* must be gated across rate change */ +#define ZYNQMP_CLK_SET_RATE_GATE BIT(0) +/* must be gated across re-parent */ +#define ZYNQMP_CLK_SET_PARENT_GATE BIT(1) +/* propagate rate change up one level */ +#define ZYNQMP_CLK_SET_RATE_PARENT BIT(2) +/* do not gate even if unused */ +#define ZYNQMP_CLK_IGNORE_UNUSED BIT(3) +/* don't re-parent on rate change */ +#define ZYNQMP_CLK_SET_RATE_NO_REPARENT BIT(7) +/* do not gate, ever */ +#define ZYNQMP_CLK_IS_CRITICAL BIT(11) + enum topology_type { TYPE_INVALID, TYPE_MUX, @@ -33,6 +47,8 @@ struct clock_topology { u8 custom_type_flag; }; +unsigned long zynqmp_clk_map_common_ccf_flags(const u32 zynqmp_flag); + struct clk_hw *zynqmp_clk_register_pll(const char *name, u32 clk_id, const char * const *parents, u8 num_parents, diff --git a/drivers/clk/zynqmp/clkc.c b/drivers/clk/zynqmp/clkc.c index db8d0d7161ce..871184e406e1 100644 --- a/drivers/clk/zynqmp/clkc.c +++ b/drivers/clk/zynqmp/clkc.c @@ -271,6 +271,26 @@ static int zynqmp_pm_clock_get_topology(u32 clock_id, u32 index, return ret; } +unsigned long zynqmp_clk_map_common_ccf_flags(const u32 zynqmp_flag) +{ + unsigned long ccf_flag = 0; + + if (zynqmp_flag & ZYNQMP_CLK_SET_RATE_GATE) + ccf_flag |= CLK_SET_RATE_GATE; + if (zynqmp_flag & ZYNQMP_CLK_SET_PARENT_GATE) + ccf_flag |= CLK_SET_PARENT_GATE; + if (zynqmp_flag & ZYNQMP_CLK_SET_RATE_PARENT) + ccf_flag |= CLK_SET_RATE_PARENT; + if (zynqmp_flag & ZYNQMP_CLK_IGNORE_UNUSED) + ccf_flag |= CLK_IGNORE_UNUSED; + if (zynqmp_flag & ZYNQMP_CLK_SET_RATE_NO_REPARENT) + ccf_flag |= CLK_SET_RATE_NO_REPARENT; + if (zynqmp_flag & ZYNQMP_CLK_IS_CRITICAL) + ccf_flag |= CLK_IS_CRITICAL; + + return ccf_flag; +} + /** * zynqmp_clk_register_fixed_factor() - Register fixed factor with the * clock framework @@ -292,6 +312,7 @@ struct clk_hw *zynqmp_clk_register_fixed_factor(const char *name, u32 clk_id, struct zynqmp_pm_query_data qdata = {0}; u32 ret_payload[PAYLOAD_ARG_CNT]; int ret; + unsigned long flag; qdata.qid = PM_QID_CLOCK_GET_FIXEDFACTOR_PARAMS; qdata.arg1 = clk_id; @@ -303,9 +324,11 @@ struct clk_hw *zynqmp_clk_register_fixed_factor(const char *name, u32 clk_id, mult = ret_payload[1]; div = ret_payload[2]; + flag = zynqmp_clk_map_common_ccf_flags(nodes->flag); + hw = clk_hw_register_fixed_factor(NULL, name, parents[0], - nodes->flag, mult, + flag, mult, div); return hw; diff --git a/drivers/clk/zynqmp/divider.c b/drivers/clk/zynqmp/divider.c index e9bf7958b821..0becdc0a8bff 100644 --- a/drivers/clk/zynqmp/divider.c +++ b/drivers/clk/zynqmp/divider.c @@ -312,8 +312,9 @@ struct clk_hw *zynqmp_clk_register_divider(const char *name, init.name = name; init.ops = &zynqmp_clk_divider_ops; - /* CLK_FRAC is not defined in the common clk framework */ - init.flags = nodes->flag & ~CLK_FRAC; + + init.flags = zynqmp_clk_map_common_ccf_flags(nodes->flag); + init.parent_names = parents; init.num_parents = 1; diff --git a/drivers/clk/zynqmp/pll.c b/drivers/clk/zynqmp/pll.c index 793b950ade09..036e4ff64a2f 100644 --- a/drivers/clk/zynqmp/pll.c +++ b/drivers/clk/zynqmp/pll.c @@ -322,7 +322,9 @@ struct clk_hw *zynqmp_clk_register_pll(const char *name, u32 clk_id, init.name = name; init.ops = &zynqmp_pll_ops; - init.flags = nodes->flag; + + init.flags = zynqmp_clk_map_common_ccf_flags(nodes->flag); + init.parent_names = parents; init.num_parents = 1; From 1b09c308e64969f545f4b9474b786ad90dddf9a2 Mon Sep 17 00:00:00 2001 From: Rajan Vaja Date: Mon, 28 Jun 2021 00:01:20 -0700 Subject: [PATCH 159/161] clk: zynqmp: Use firmware specific divider clock flags Use ZynqMP specific divider clock flags instead of using CCF flags. Signed-off-by: Rajan Vaja Link: https://lore.kernel.org/r/20210628070122.26217-3-rajan.vaja@xilinx.com Signed-off-by: Stephen Boyd --- drivers/clk/zynqmp/clk-zynqmp.h | 9 +++++++++ drivers/clk/zynqmp/divider.c | 25 ++++++++++++++++++++++++- 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/drivers/clk/zynqmp/clk-zynqmp.h b/drivers/clk/zynqmp/clk-zynqmp.h index aa013a59c7cc..925a727eb383 100644 --- a/drivers/clk/zynqmp/clk-zynqmp.h +++ b/drivers/clk/zynqmp/clk-zynqmp.h @@ -24,6 +24,15 @@ /* do not gate, ever */ #define ZYNQMP_CLK_IS_CRITICAL BIT(11) +/* Type Flags for divider clock */ +#define ZYNQMP_CLK_DIVIDER_ONE_BASED BIT(0) +#define ZYNQMP_CLK_DIVIDER_POWER_OF_TWO BIT(1) +#define ZYNQMP_CLK_DIVIDER_ALLOW_ZERO BIT(2) +#define ZYNQMP_CLK_DIVIDER_HIWORD_MASK BIT(3) +#define ZYNQMP_CLK_DIVIDER_ROUND_CLOSEST BIT(4) +#define ZYNQMP_CLK_DIVIDER_READ_ONLY BIT(5) +#define ZYNQMP_CLK_DIVIDER_MAX_AT_ZERO BIT(6) + enum topology_type { TYPE_INVALID, TYPE_MUX, diff --git a/drivers/clk/zynqmp/divider.c b/drivers/clk/zynqmp/divider.c index 0becdc0a8bff..c07423e03bc8 100644 --- a/drivers/clk/zynqmp/divider.c +++ b/drivers/clk/zynqmp/divider.c @@ -284,6 +284,29 @@ static u32 zynqmp_clk_get_max_divisor(u32 clk_id, u32 type) return ret_payload[1]; } +static inline unsigned long zynqmp_clk_map_divider_ccf_flags( + const u32 zynqmp_type_flag) +{ + unsigned long ccf_flag = 0; + + if (zynqmp_type_flag & ZYNQMP_CLK_DIVIDER_ONE_BASED) + ccf_flag |= CLK_DIVIDER_ONE_BASED; + if (zynqmp_type_flag & ZYNQMP_CLK_DIVIDER_POWER_OF_TWO) + ccf_flag |= CLK_DIVIDER_POWER_OF_TWO; + if (zynqmp_type_flag & ZYNQMP_CLK_DIVIDER_ALLOW_ZERO) + ccf_flag |= CLK_DIVIDER_ALLOW_ZERO; + if (zynqmp_type_flag & ZYNQMP_CLK_DIVIDER_POWER_OF_TWO) + ccf_flag |= CLK_DIVIDER_HIWORD_MASK; + if (zynqmp_type_flag & ZYNQMP_CLK_DIVIDER_ROUND_CLOSEST) + ccf_flag |= CLK_DIVIDER_ROUND_CLOSEST; + if (zynqmp_type_flag & ZYNQMP_CLK_DIVIDER_READ_ONLY) + ccf_flag |= CLK_DIVIDER_READ_ONLY; + if (zynqmp_type_flag & ZYNQMP_CLK_DIVIDER_MAX_AT_ZERO) + ccf_flag |= CLK_DIVIDER_MAX_AT_ZERO; + + return ccf_flag; +} + /** * zynqmp_clk_register_divider() - Register a divider clock * @name: Name of this clock @@ -321,7 +344,7 @@ struct clk_hw *zynqmp_clk_register_divider(const char *name, /* struct clk_divider assignments */ div->is_frac = !!((nodes->flag & CLK_FRAC) | (nodes->custom_type_flag & CUSTOM_FLAG_CLK_FRAC)); - div->flags = nodes->type_flag; + div->flags = zynqmp_clk_map_divider_ccf_flags(nodes->type_flag); div->hw.init = &init; div->clk_id = clk_id; div->div_type = nodes->type; From 54530ed17d1cc096f9ab0319001c96a63f772c62 Mon Sep 17 00:00:00 2001 From: Rajan Vaja Date: Mon, 28 Jun 2021 00:01:21 -0700 Subject: [PATCH 160/161] clk: zynqmp: Use firmware specific mux clock flags Use ZynqMP specific mux clock flags instead of using CCF flags. Signed-off-by: Rajan Vaja Link: https://lore.kernel.org/r/20210628070122.26217-4-rajan.vaja@xilinx.com Signed-off-by: Stephen Boyd --- drivers/clk/zynqmp/clk-mux-zynqmp.c | 23 ++++++++++++++++++++++- drivers/clk/zynqmp/clk-zynqmp.h | 8 ++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/drivers/clk/zynqmp/clk-mux-zynqmp.c b/drivers/clk/zynqmp/clk-mux-zynqmp.c index 42ad324b1c64..157d4a960bf4 100644 --- a/drivers/clk/zynqmp/clk-mux-zynqmp.c +++ b/drivers/clk/zynqmp/clk-mux-zynqmp.c @@ -96,6 +96,27 @@ static const struct clk_ops zynqmp_clk_mux_ro_ops = { .get_parent = zynqmp_clk_mux_get_parent, }; +static inline unsigned long zynqmp_clk_map_mux_ccf_flags( + const u32 zynqmp_type_flag) +{ + unsigned long ccf_flag = 0; + + if (zynqmp_type_flag & ZYNQMP_CLK_MUX_INDEX_ONE) + ccf_flag |= CLK_MUX_INDEX_ONE; + if (zynqmp_type_flag & ZYNQMP_CLK_MUX_INDEX_BIT) + ccf_flag |= CLK_MUX_INDEX_BIT; + if (zynqmp_type_flag & ZYNQMP_CLK_MUX_HIWORD_MASK) + ccf_flag |= CLK_MUX_HIWORD_MASK; + if (zynqmp_type_flag & ZYNQMP_CLK_MUX_READ_ONLY) + ccf_flag |= CLK_MUX_READ_ONLY; + if (zynqmp_type_flag & ZYNQMP_CLK_MUX_ROUND_CLOSEST) + ccf_flag |= CLK_MUX_ROUND_CLOSEST; + if (zynqmp_type_flag & ZYNQMP_CLK_MUX_BIG_ENDIAN) + ccf_flag |= CLK_MUX_BIG_ENDIAN; + + return ccf_flag; +} + /** * zynqmp_clk_register_mux() - Register a mux table with the clock * framework @@ -131,7 +152,7 @@ struct clk_hw *zynqmp_clk_register_mux(const char *name, u32 clk_id, init.parent_names = parents; init.num_parents = num_parents; - mux->flags = nodes->type_flag; + mux->flags = zynqmp_clk_map_mux_ccf_flags(nodes->type_flag); mux->hw.init = &init; mux->clk_id = clk_id; diff --git a/drivers/clk/zynqmp/clk-zynqmp.h b/drivers/clk/zynqmp/clk-zynqmp.h index 925a727eb383..84fa80a969a9 100644 --- a/drivers/clk/zynqmp/clk-zynqmp.h +++ b/drivers/clk/zynqmp/clk-zynqmp.h @@ -33,6 +33,14 @@ #define ZYNQMP_CLK_DIVIDER_READ_ONLY BIT(5) #define ZYNQMP_CLK_DIVIDER_MAX_AT_ZERO BIT(6) +/* Type Flags for mux clock */ +#define ZYNQMP_CLK_MUX_INDEX_ONE BIT(0) +#define ZYNQMP_CLK_MUX_INDEX_BIT BIT(1) +#define ZYNQMP_CLK_MUX_HIWORD_MASK BIT(2) +#define ZYNQMP_CLK_MUX_READ_ONLY BIT(3) +#define ZYNQMP_CLK_MUX_ROUND_CLOSEST BIT(4) +#define ZYNQMP_CLK_MUX_BIG_ENDIAN BIT(5) + enum topology_type { TYPE_INVALID, TYPE_MUX, From 03aea91bbe06d4ffae8c22c9e1e6671a76fd6d5a Mon Sep 17 00:00:00 2001 From: Rajan Vaja Date: Mon, 28 Jun 2021 00:01:22 -0700 Subject: [PATCH 161/161] clk: zynqmp: Handle divider specific read only flag Add support for divider specific read only CCF flag (CLK_DIVIDER_READ_ONLY). Signed-off-by: Rajan Vaja Link: https://lore.kernel.org/r/20210628070122.26217-5-rajan.vaja@xilinx.com Signed-off-by: Stephen Boyd --- drivers/clk/zynqmp/divider.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/clk/zynqmp/divider.c b/drivers/clk/zynqmp/divider.c index c07423e03bc8..cb49281f9cf9 100644 --- a/drivers/clk/zynqmp/divider.c +++ b/drivers/clk/zynqmp/divider.c @@ -256,6 +256,11 @@ static const struct clk_ops zynqmp_clk_divider_ops = { .set_rate = zynqmp_clk_divider_set_rate, }; +static const struct clk_ops zynqmp_clk_divider_ro_ops = { + .recalc_rate = zynqmp_clk_divider_recalc_rate, + .round_rate = zynqmp_clk_divider_round_rate, +}; + /** * zynqmp_clk_get_max_divisor() - Get maximum supported divisor from firmware. * @clk_id: Id of clock @@ -334,7 +339,10 @@ struct clk_hw *zynqmp_clk_register_divider(const char *name, return ERR_PTR(-ENOMEM); init.name = name; - init.ops = &zynqmp_clk_divider_ops; + if (nodes->type_flag & CLK_DIVIDER_READ_ONLY) + init.ops = &zynqmp_clk_divider_ro_ops; + else + init.ops = &zynqmp_clk_divider_ops; init.flags = zynqmp_clk_map_common_ccf_flags(nodes->flag);