From f3ea14c6a243d927c172caf123e9d2ce803fdafc Mon Sep 17 00:00:00 2001 From: Yang Yingliang Date: Wed, 2 Aug 2023 17:19:20 +0800 Subject: clk: renesas: r9a06g032: Use for_each_compatible_node() Use for_each_compatible_node() instead of open-coding it. Signed-off-by: Yang Yingliang Reviewed-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/20230802091920.3270703-1-yangyingliang@huawei.com Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/r9a06g032-clocks.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/clk/renesas/r9a06g032-clocks.c b/drivers/clk/renesas/r9a06g032-clocks.c index 55db63c7041a..9a50166c02b9 100644 --- a/drivers/clk/renesas/r9a06g032-clocks.c +++ b/drivers/clk/renesas/r9a06g032-clocks.c @@ -1269,11 +1269,10 @@ static void r9a06g032_clocks_del_clk_provider(void *data) static void __init r9a06g032_init_h2mode(struct r9a06g032_priv *clocks) { - struct device_node *usbf_np = NULL; + struct device_node *usbf_np; u32 usb; - while ((usbf_np = of_find_compatible_node(usbf_np, NULL, - "renesas,rzn1-usbf"))) { + for_each_compatible_node(usbf_np, NULL, "renesas,rzn1-usbf") { if (of_device_is_available(usbf_np)) break; } -- cgit v1.2.3-59-g8ed1b From f2af7cb8ac0f825b415b4846a526bddba68807b1 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Fri, 8 Sep 2023 17:07:02 -0700 Subject: clk: asm9620: Remove 'hw' local variable that isn't checked The 'hw' pointer local variable in this function became unused after commit f5290d8e4f0c ("clk: asm9260: use parent index to link the reference clock"). Remove it to silence an unused but set variable warning. drivers/clk/clk-asm9260.c:258:17: warning: variable 'hw' set but not used [-Wunused-but-set-variable] struct clk_hw *hw, *pll_hw; ^ 1 warning generated. Cc: Dmitry Baryshkov Fixes: f5290d8e4f0c ("clk: asm9260: use parent index to link the reference clock") Reported-by: kernel test robot Closes: https://lore.kernel.org/oe-kbuild-all/202309042014.IWERPl09-lkp@intel.com/ Signed-off-by: Stephen Boyd Link: https://lore.kernel.org/r/20230909000703.3478902-1-sboyd@kernel.org --- drivers/clk/clk-asm9260.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/clk/clk-asm9260.c b/drivers/clk/clk-asm9260.c index 8b3c059e19a1..3432c801f1bd 100644 --- a/drivers/clk/clk-asm9260.c +++ b/drivers/clk/clk-asm9260.c @@ -255,7 +255,7 @@ static struct asm9260_mux_clock asm9260_mux_clks[] __initdata = { static void __init asm9260_acc_init(struct device_node *np) { - struct clk_hw *hw, *pll_hw; + struct clk_hw *pll_hw; struct clk_hw **hws; const char *pll_clk = "pll"; struct clk_parent_data pll_parent_data = { .index = 0 }; @@ -283,7 +283,7 @@ static void __init asm9260_acc_init(struct device_node *np) for (n = 0; n < ARRAY_SIZE(asm9260_mux_clks); n++) { const struct asm9260_mux_clock *mc = &asm9260_mux_clks[n]; - hw = clk_hw_register_mux_table_parent_data(NULL, mc->name, mc->parent_data, + clk_hw_register_mux_table_parent_data(NULL, mc->name, mc->parent_data, mc->num_parents, mc->flags, base + mc->offset, 0, mc->mask, 0, mc->table, &asm9260_clk_lock); } @@ -292,7 +292,7 @@ static void __init asm9260_acc_init(struct device_node *np) for (n = 0; n < ARRAY_SIZE(asm9260_mux_gates); n++) { const struct asm9260_gate_data *gd = &asm9260_mux_gates[n]; - hw = clk_hw_register_gate(NULL, gd->name, + clk_hw_register_gate(NULL, gd->name, gd->parent_name, gd->flags | CLK_SET_RATE_PARENT, base + gd->reg, gd->bit_idx, 0, &asm9260_clk_lock); } -- cgit v1.2.3-59-g8ed1b From 14aaccbd34e93c0bbaaf475d174ece170f10f694 Mon Sep 17 00:00:00 2001 From: Baruch Siach Date: Thu, 31 Aug 2023 15:36:55 +0300 Subject: clk: gate: fix comment typo and grammar Change ouput -> output. While at it change also grammatically incorrect "it's" to "its". Signed-off-by: Baruch Siach Link: https://lore.kernel.org/r/d47978a09dd0320f9929a19fa3e829608a02b224.1693485415.git.baruch@tkos.co.il Signed-off-by: Stephen Boyd --- drivers/clk/clk-gate.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/clk-gate.c b/drivers/clk/clk-gate.c index 64283807600b..68e585a02fd9 100644 --- a/drivers/clk/clk-gate.c +++ b/drivers/clk/clk-gate.c @@ -15,7 +15,7 @@ #include /** - * DOC: basic gatable clock which can gate and ungate it's ouput + * DOC: basic gatable clock which can gate and ungate its output * * Traits of this clock: * prepare - clk_(un)prepare only ensures parent is (un)prepared -- cgit v1.2.3-59-g8ed1b From 500a4609eef46d49a260173b66cabb20bd5159ad Mon Sep 17 00:00:00 2001 From: Adam Skladowski Date: Sat, 12 Aug 2023 13:24:45 +0200 Subject: clk: qcom: clk-hfpll: Configure l_val in init when required Add support for pre-configuring default frequency multiplier, this appears to be required on some platforms like MSM8976. Without configuring L_VAL device reboots when trying to bring PLL up. Signed-off-by: Adam Skladowski Reviewed-by: Konrad Dybcio Link: https://lore.kernel.org/r/20230812112534.8610-3-a39.skl@gmail.com Signed-off-by: Bjorn Andersson --- drivers/clk/qcom/clk-hfpll.c | 4 ++++ drivers/clk/qcom/clk-hfpll.h | 1 + 2 files changed, 5 insertions(+) diff --git a/drivers/clk/qcom/clk-hfpll.c b/drivers/clk/qcom/clk-hfpll.c index 86f728dc69e5..705352aff067 100644 --- a/drivers/clk/qcom/clk-hfpll.c +++ b/drivers/clk/qcom/clk-hfpll.c @@ -44,6 +44,10 @@ static void __clk_hfpll_init_once(struct clk_hw *hw) regmap_write(regmap, hd->user_reg, regval); } + /* Write L_VAL from conf if it exist */ + if (hd->l_val) + regmap_write(regmap, hd->l_reg, hd->l_val); + if (hd->droop_reg) regmap_write(regmap, hd->droop_reg, hd->droop_val); diff --git a/drivers/clk/qcom/clk-hfpll.h b/drivers/clk/qcom/clk-hfpll.h index 2a57b2fb2f2f..27b9effcb3fd 100644 --- a/drivers/clk/qcom/clk-hfpll.h +++ b/drivers/clk/qcom/clk-hfpll.h @@ -18,6 +18,7 @@ struct hfpll_data { u32 status_reg; u8 lock_bit; + u32 l_val; u32 droop_val; u32 config_val; u32 user_val; -- cgit v1.2.3-59-g8ed1b From 34e000c0963e55f24be2254fa645f8dd8257a9e0 Mon Sep 17 00:00:00 2001 From: Adam Skladowski Date: Sat, 12 Aug 2023 13:24:46 +0200 Subject: clk: qcom: hfpll: Allow matching pdata HFPLL driver can be used to drive PLLs also on different SoCs like MSM8976 On MSM8976 each PLL gets it own different configuration, add matching pdata to driver to support multiple configurations. Signed-off-by: Adam Skladowski Reviewed-by: Konrad Dybcio Link: https://lore.kernel.org/r/20230812112534.8610-4-a39.skl@gmail.com Signed-off-by: Bjorn Andersson --- drivers/clk/qcom/hfpll.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/clk/qcom/hfpll.c b/drivers/clk/qcom/hfpll.c index f4d78003d189..47325eb17f07 100644 --- a/drivers/clk/qcom/hfpll.c +++ b/drivers/clk/qcom/hfpll.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -32,7 +33,7 @@ static const struct hfpll_data hdata = { }; static const struct of_device_id qcom_hfpll_match_table[] = { - { .compatible = "qcom,hfpll" }, + { .compatible = "qcom,hfpll", .data = &hdata }, { } }; MODULE_DEVICE_TABLE(of, qcom_hfpll_match_table); @@ -83,7 +84,7 @@ static int qcom_hfpll_probe(struct platform_device *pdev) init.parent_data = &pdata; - h->d = &hdata; + h->d = of_device_get_match_data(&pdev->dev); h->clkr.hw.init = &init; spin_lock_init(&h->lock); -- cgit v1.2.3-59-g8ed1b From de37ca2dc98607e74522d8f243aa7feac74577c5 Mon Sep 17 00:00:00 2001 From: Adam Skladowski Date: Sat, 12 Aug 2023 13:24:47 +0200 Subject: dt-bindings: clock: qcom,hfpll: Document MSM8976 compatibles Document MSM8976 HFPLL compatibles. Signed-off-by: Adam Skladowski Acked-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20230812112534.8610-5-a39.skl@gmail.com Signed-off-by: Bjorn Andersson --- Documentation/devicetree/bindings/clock/qcom,hfpll.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Documentation/devicetree/bindings/clock/qcom,hfpll.txt b/Documentation/devicetree/bindings/clock/qcom,hfpll.txt index ec02a024424c..5769cbbe76be 100644 --- a/Documentation/devicetree/bindings/clock/qcom,hfpll.txt +++ b/Documentation/devicetree/bindings/clock/qcom,hfpll.txt @@ -12,6 +12,9 @@ PROPERTIES "qcom,hfpll-apq8064", "qcom,hfpll" "qcom,hfpll-msm8974", "qcom,hfpll" "qcom,hfpll-msm8960", "qcom,hfpll" + "qcom,msm8976-hfpll-a53", "qcom,hfpll" + "qcom,msm8976-hfpll-a72", "qcom,hfpll" + "qcom,msm8976-hfpll-cci", "qcom,hfpll" - reg: Usage: required -- cgit v1.2.3-59-g8ed1b From 1fa2d1a887c763246662a88e203d69b36052770c Mon Sep 17 00:00:00 2001 From: Adam Skladowski Date: Sat, 12 Aug 2023 13:24:48 +0200 Subject: clk: qcom: hfpll: Add MSM8976 PLL data Add PLL configuration for MSM8976 SoC, this SoC offers 3 HFPLL. Small cluster offers two presets for 652-902Mhz range and 902Mhz-1.47Ghz. For simplicity only add second range as smaller frequencies can be obtained via apcs divider or safe parent this also saves us a hassle of reconfiguring VCO bit and config_val. A72 and CCI cluster only use single frequency range with their outputs/post_dividers/vco_bits being static. Signed-off-by: Adam Skladowski Reviewed-by: Konrad Dybcio Link: https://lore.kernel.org/r/20230812112534.8610-6-a39.skl@gmail.com Signed-off-by: Bjorn Andersson --- drivers/clk/qcom/hfpll.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/drivers/clk/qcom/hfpll.c b/drivers/clk/qcom/hfpll.c index 47325eb17f07..dac27e31ef60 100644 --- a/drivers/clk/qcom/hfpll.c +++ b/drivers/clk/qcom/hfpll.c @@ -32,8 +32,62 @@ static const struct hfpll_data hdata = { .max_rate = 2900000000UL, }; +static const struct hfpll_data msm8976_a53 = { + .mode_reg = 0x00, + .l_reg = 0x04, + .m_reg = 0x08, + .n_reg = 0x0c, + .user_reg = 0x10, + .config_reg = 0x14, + .config_val = 0x341600, + .status_reg = 0x1c, + .lock_bit = 16, + + .l_val = 0x35, + .user_val = 0x109, + .min_rate = 902400000UL, + .max_rate = 1478400000UL, +}; + +static const struct hfpll_data msm8976_a72 = { + .mode_reg = 0x00, + .l_reg = 0x04, + .m_reg = 0x08, + .n_reg = 0x0c, + .user_reg = 0x10, + .config_reg = 0x14, + .config_val = 0x4e0405d, + .status_reg = 0x1c, + .lock_bit = 16, + + .l_val = 0x3e, + .user_val = 0x100109, + .min_rate = 940800000UL, + .max_rate = 2016000000UL, +}; + +static const struct hfpll_data msm8976_cci = { + .mode_reg = 0x00, + .l_reg = 0x04, + .m_reg = 0x08, + .n_reg = 0x0c, + .user_reg = 0x10, + .config_reg = 0x14, + .config_val = 0x141400, + .status_reg = 0x1c, + .lock_bit = 16, + + .l_val = 0x20, + .user_val = 0x100109, + .min_rate = 556800000UL, + .max_rate = 902400000UL, +}; + static const struct of_device_id qcom_hfpll_match_table[] = { { .compatible = "qcom,hfpll", .data = &hdata }, + { .compatible = "qcom,msm8976-hfpll-a53", .data = &msm8976_a53 }, + { .compatible = "qcom,msm8976-hfpll-a72", .data = &msm8976_a72 }, + { .compatible = "qcom,msm8976-hfpll-cci", .data = &msm8976_cci }, { } }; MODULE_DEVICE_TABLE(of, qcom_hfpll_match_table); -- cgit v1.2.3-59-g8ed1b From 17939df3c9acd26e4dac1c5943dd8e58e1bcb4e7 Mon Sep 17 00:00:00 2001 From: Claudiu Beznea Date: Tue, 12 Sep 2023 07:51:30 +0300 Subject: clk: renesas: rzg2l: Use core->name for clock name core->name already contains the clock name thus, there is no need to check the GET_SHIFT(core->conf) to decide on it. Signed-off-by: Claudiu Beznea Reviewed-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/20230912045157.177966-11-claudiu.beznea.uj@bp.renesas.com Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/rzg2l-cpg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/renesas/rzg2l-cpg.c b/drivers/clk/renesas/rzg2l-cpg.c index 47f488387f33..a1e820d2eb9e 100644 --- a/drivers/clk/renesas/rzg2l-cpg.c +++ b/drivers/clk/renesas/rzg2l-cpg.c @@ -265,7 +265,7 @@ rzg2l_cpg_sd_mux_clk_register(const struct cpg_core_clk *core, clk_hw_data->priv = priv; clk_hw_data->conf = core->conf; - init.name = GET_SHIFT(core->conf) ? "sd1" : "sd0"; + init.name = core->name; init.ops = &rzg2l_cpg_sd_clk_mux_ops; init.flags = 0; init.num_parents = core->num_parents; -- cgit v1.2.3-59-g8ed1b From becf4a771a12b52dc5b3d2b089598d5603f3bbec Mon Sep 17 00:00:00 2001 From: Claudiu Beznea Date: Tue, 12 Sep 2023 07:51:31 +0300 Subject: clk: renesas: rzg2l: Simplify the logic in rzg2l_mod_clock_endisable() The bitmask << 16 is anyway set on both branches of if thus move it before the if and set the lower bits of registers only in case clock is enabled. Signed-off-by: Claudiu Beznea Reviewed-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/20230912045157.177966-12-claudiu.beznea.uj@bp.renesas.com Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/rzg2l-cpg.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/clk/renesas/rzg2l-cpg.c b/drivers/clk/renesas/rzg2l-cpg.c index a1e820d2eb9e..115e19823b70 100644 --- a/drivers/clk/renesas/rzg2l-cpg.c +++ b/drivers/clk/renesas/rzg2l-cpg.c @@ -909,10 +909,9 @@ static int rzg2l_mod_clock_endisable(struct clk_hw *hw, bool enable) enable ? "ON" : "OFF"); spin_lock_irqsave(&priv->rmw_lock, flags); + value = bitmask << 16; if (enable) - value = (bitmask << 16) | bitmask; - else - value = bitmask << 16; + value |= bitmask; writel(value, priv->base + CLK_ON_R(reg)); spin_unlock_irqrestore(&priv->rmw_lock, flags); -- cgit v1.2.3-59-g8ed1b From 72977f07b035e488c3f1928832a1616c6cae7278 Mon Sep 17 00:00:00 2001 From: Claudiu Beznea Date: Tue, 12 Sep 2023 07:51:33 +0300 Subject: clk: renesas: rzg2l: Use FIELD_GET() for PLL register fields Use FIELD_GET() for PLL register fields. This is its purpose. Signed-off-by: Claudiu Beznea Reviewed-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/20230912045157.177966-14-claudiu.beznea.uj@bp.renesas.com Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/rzg2l-cpg.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/clk/renesas/rzg2l-cpg.c b/drivers/clk/renesas/rzg2l-cpg.c index 115e19823b70..9baae7bb7094 100644 --- a/drivers/clk/renesas/rzg2l-cpg.c +++ b/drivers/clk/renesas/rzg2l-cpg.c @@ -11,6 +11,7 @@ * Copyright (C) 2015 Renesas Electronics Corp. */ +#include #include #include #include @@ -38,14 +39,13 @@ #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 KDIV(val) FIELD_GET(GENMASK(31, 16), val) +#define MDIV(val) FIELD_GET(GENMASK(15, 6), val) +#define PDIV(val) FIELD_GET(GENMASK(5, 0), val) +#define SDIV(val) FIELD_GET(GENMASK(2, 0), val) #define CLK_ON_R(reg) (reg) #define CLK_MON_R(reg) (0x180 + (reg)) -- cgit v1.2.3-59-g8ed1b From 897a3e34d6e73d2386715d5c44c57992f2c0eada Mon Sep 17 00:00:00 2001 From: Claudiu Beznea Date: Tue, 12 Sep 2023 07:51:34 +0300 Subject: clk: renesas: rzg2l: Use u32 for flag and mux_flags flag and mux_flags are intended to keep bit masks. Use u32 type for it. Signed-off-by: Claudiu Beznea Reviewed-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/20230912045157.177966-15-claudiu.beznea.uj@bp.renesas.com Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/rzg2l-cpg.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/clk/renesas/rzg2l-cpg.h b/drivers/clk/renesas/rzg2l-cpg.h index 6cee9e56acc7..0b28870a6f9d 100644 --- a/drivers/clk/renesas/rzg2l-cpg.h +++ b/drivers/clk/renesas/rzg2l-cpg.h @@ -92,8 +92,8 @@ struct cpg_core_clk { unsigned int conf; const struct clk_div_table *dtable; const char * const *parent_names; - int flag; - int mux_flags; + u32 flag; + u32 mux_flags; int num_parents; }; -- cgit v1.2.3-59-g8ed1b From 80374a7fbf7af69bb81b6e4311f2018205b62644 Mon Sep 17 00:00:00 2001 From: Ralph Siemsen Date: Wed, 13 Sep 2023 16:38:04 -0400 Subject: clk: renesas: r9a06g032: Fix kerneldoc warning Mention the 'dual' structure in the kdoc. This fixes the following W=1 warning during build: > drivers/clk/renesas/r9a06g032-clocks.c:119: warning: Function parameter or member 'dual' not described in 'r9a06g032_clkdesc' Reported-by: kernel test robot Closes: https://lore.kernel.org/oe-kbuild-all/202309101314.kTRoxND5-lkp@intel.com/ Signed-off-by: Ralph Siemsen Reviewed-by: Miquel Raynal Reviewed-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/20230913203805.465780-1-ralph.siemsen@linaro.org Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/r9a06g032-clocks.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/clk/renesas/r9a06g032-clocks.c b/drivers/clk/renesas/r9a06g032-clocks.c index 9a50166c02b9..5f91bc8348b3 100644 --- a/drivers/clk/renesas/r9a06g032-clocks.c +++ b/drivers/clk/renesas/r9a06g032-clocks.c @@ -109,6 +109,7 @@ enum gate_type { * must be in ascending order, zero for unused * @div: divisor for fixed-factor clock * @mul: multiplier for fixed-factor clock + * @dual: substructure for dual clock gates * @group: UART group, 0=UART0/1/2, 1=UART3/4/5/6/7 * @sel: select either g1/r1 or g2/r2 as clock source * @g1: 1st source gate (clock enable/disable) -- cgit v1.2.3-59-g8ed1b From fbb991530fdcf1150bc23c83775c338059f4f642 Mon Sep 17 00:00:00 2001 From: Ralph Siemsen Date: Wed, 13 Sep 2023 16:38:05 -0400 Subject: clk: renesas: r9a06g032: Name anonymous structs Clarify the content of the r9a06g032_clkdesc structure by naming the remaining anonymous structures defined inside. Renaming each field and updating the doc then becomes necessary in order to avoid name duplications and kdoc warnings. Signed-off-by: Ralph Siemsen Reviewed-by: Miquel Raynal Reviewed-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/20230913203805.465780-2-ralph.siemsen@linaro.org Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/r9a06g032-clocks.c | 63 ++++++++++++++++++---------------- 1 file changed, 33 insertions(+), 30 deletions(-) diff --git a/drivers/clk/renesas/r9a06g032-clocks.c b/drivers/clk/renesas/r9a06g032-clocks.c index 5f91bc8348b3..c1348e2d450c 100644 --- a/drivers/clk/renesas/r9a06g032-clocks.c +++ b/drivers/clk/renesas/r9a06g032-clocks.c @@ -102,20 +102,22 @@ enum gate_type { * @source: the ID+1 of the parent clock element. * Root clock uses ID of ~0 (PARENT_ID); * @gate: clock enable/disable - * @div_min: smallest permitted clock divider - * @div_max: largest permitted clock divider - * @reg: clock divider register offset, in 32-bit words - * @div_table: optional list of fixed clock divider values; + * @div: substructure for clock divider + * @div.min: smallest permitted clock divider + * @div.max: largest permitted clock divider + * @div.reg: clock divider register offset, in 32-bit words + * @div.table: optional list of fixed clock divider values; * must be in ascending order, zero for unused - * @div: divisor for fixed-factor clock - * @mul: multiplier for fixed-factor clock + * @ffc: substructure for fixed-factor clocks + * @ffc.div: divisor for fixed-factor clock + * @ffc.mul: multiplier for fixed-factor clock * @dual: substructure for dual clock gates - * @group: UART group, 0=UART0/1/2, 1=UART3/4/5/6/7 - * @sel: select either g1/r1 or g2/r2 as clock source - * @g1: 1st source gate (clock enable/disable) - * @r1: 1st source reset (module reset) - * @g2: 2nd source gate (clock enable/disable) - * @r2: 2nd source reset (module reset) + * @dual.group: UART group, 0=UART0/1/2, 1=UART3/4/5/6/7 + * @dual.sel: select either g1/r1 or g2/r2 as clock source + * @dual.g1: 1st source gate (clock enable/disable) + * @dual.r1: 1st source reset (module reset) + * @dual.g2: 2nd source gate (clock enable/disable) + * @dual.r2: 2nd source reset (module reset) * * Describes a single element in the clock tree hierarchy. * As there are quite a large number of clock elements, this @@ -132,13 +134,13 @@ struct r9a06g032_clkdesc { struct r9a06g032_gate gate; /* type = K_DIV */ struct { - unsigned int div_min:10, div_max:10, reg:10; - u16 div_table[4]; - }; + unsigned int min:10, max:10, reg:10; + u16 table[4]; + } div; /* type = K_FFC */ struct { u16 div, mul; - }; + } ffc; /* type = K_DUALGATE */ struct { uint16_t group:1; @@ -179,26 +181,26 @@ struct r9a06g032_clkdesc { .type = K_FFC, \ .index = R9A06G032_##_idx, \ .name = _n, \ - .div = _div, \ - .mul = _mul \ + .ffc.div = _div, \ + .ffc.mul = _mul \ } #define D_FFC(_idx, _n, _src, _div) { \ .type = K_FFC, \ .index = R9A06G032_##_idx, \ .source = 1 + R9A06G032_##_src, \ .name = _n, \ - .div = _div, \ - .mul = 1 \ + .ffc.div = _div, \ + .ffc.mul = 1 \ } #define D_DIV(_idx, _n, _src, _reg, _min, _max, ...) { \ .type = K_DIV, \ .index = R9A06G032_##_idx, \ .source = 1 + R9A06G032_##_src, \ .name = _n, \ - .reg = _reg, \ - .div_min = _min, \ - .div_max = _max, \ - .div_table = { __VA_ARGS__ } \ + .div.reg = _reg, \ + .div.min = _min, \ + .div.max = _max, \ + .div.table = { __VA_ARGS__ } \ } #define D_UGATE(_idx, _n, _src, _g, _g1, _r1, _g2, _r2) { \ .type = K_DUALGATE, \ @@ -1064,14 +1066,14 @@ r9a06g032_register_div(struct r9a06g032_priv *clocks, div->clocks = clocks; div->index = desc->index; - div->reg = desc->reg; + div->reg = desc->div.reg; div->hw.init = &init; - div->min = desc->div_min; - div->max = desc->div_max; + div->min = desc->div.min; + div->max = desc->div.max; /* populate (optional) divider table fixed values */ for (i = 0; i < ARRAY_SIZE(div->table) && - i < ARRAY_SIZE(desc->div_table) && desc->div_table[i]; i++) { - div->table[div->table_size++] = desc->div_table[i]; + i < ARRAY_SIZE(desc->div.table) && desc->div.table[i]; i++) { + div->table[div->table_size++] = desc->div.table[i]; } clk = clk_register(NULL, &div->hw); @@ -1333,7 +1335,8 @@ static int __init r9a06g032_clocks_probe(struct platform_device *pdev) case K_FFC: clk = clk_register_fixed_factor(NULL, d->name, parent_name, 0, - d->mul, d->div); + d->ffc.mul, + d->ffc.div); break; case K_GATE: clk = r9a06g032_register_gate(clocks, parent_name, d); -- cgit v1.2.3-59-g8ed1b From 9cbc64745fc6744c0b7a35b59545f21236d81a53 Mon Sep 17 00:00:00 2001 From: Jagadeesh Kona Date: Fri, 7 Jul 2023 09:27:40 +0530 Subject: dt-bindings: clock: qcom: Add SM8550 camera clock controller Add device tree bindings for the camera clock controller on Qualcomm SM8550 platform. Co-developed-by: Taniya Das Signed-off-by: Taniya Das Signed-off-by: Jagadeesh Kona Reviewed-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20230707035744.22245-2-quic_jkona@quicinc.com Signed-off-by: Bjorn Andersson --- .../bindings/clock/qcom,sm8450-camcc.yaml | 8 +- include/dt-bindings/clock/qcom,sm8550-camcc.h | 187 +++++++++++++++++++++ 2 files changed, 193 insertions(+), 2 deletions(-) create mode 100644 include/dt-bindings/clock/qcom,sm8550-camcc.h diff --git a/Documentation/devicetree/bindings/clock/qcom,sm8450-camcc.yaml b/Documentation/devicetree/bindings/clock/qcom,sm8450-camcc.yaml index 8178c35bc348..dc3c18e4ead7 100644 --- a/Documentation/devicetree/bindings/clock/qcom,sm8450-camcc.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,sm8450-camcc.yaml @@ -13,11 +13,15 @@ description: | Qualcomm camera clock control module provides the clocks, resets and power domains on SM8450. - See also:: include/dt-bindings/clock/qcom,sm8450-camcc.h + See also:: + include/dt-bindings/clock/qcom,sm8450-camcc.h + include/dt-bindings/clock/qcom,sm8550-camcc.h properties: compatible: - const: qcom,sm8450-camcc + enum: + - qcom,sm8450-camcc + - qcom,sm8550-camcc clocks: items: diff --git a/include/dt-bindings/clock/qcom,sm8550-camcc.h b/include/dt-bindings/clock/qcom,sm8550-camcc.h new file mode 100644 index 000000000000..a2a256691c2b --- /dev/null +++ b/include/dt-bindings/clock/qcom,sm8550-camcc.h @@ -0,0 +1,187 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ +/* + * Copyright (c) 2023, Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#ifndef _DT_BINDINGS_CLK_QCOM_CAM_CC_SM8550_H +#define _DT_BINDINGS_CLK_QCOM_CAM_CC_SM8550_H + +/* CAM_CC clocks */ +#define CAM_CC_BPS_AHB_CLK 0 +#define CAM_CC_BPS_CLK 1 +#define CAM_CC_BPS_CLK_SRC 2 +#define CAM_CC_BPS_FAST_AHB_CLK 3 +#define CAM_CC_CAMNOC_AXI_CLK 4 +#define CAM_CC_CAMNOC_AXI_CLK_SRC 5 +#define CAM_CC_CAMNOC_DCD_XO_CLK 6 +#define CAM_CC_CAMNOC_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_CCI_2_CLK 12 +#define CAM_CC_CCI_2_CLK_SRC 13 +#define CAM_CC_CORE_AHB_CLK 14 +#define CAM_CC_CPAS_AHB_CLK 15 +#define CAM_CC_CPAS_BPS_CLK 16 +#define CAM_CC_CPAS_CRE_CLK 17 +#define CAM_CC_CPAS_FAST_AHB_CLK 18 +#define CAM_CC_CPAS_IFE_0_CLK 19 +#define CAM_CC_CPAS_IFE_1_CLK 20 +#define CAM_CC_CPAS_IFE_2_CLK 21 +#define CAM_CC_CPAS_IFE_LITE_CLK 22 +#define CAM_CC_CPAS_IPE_NPS_CLK 23 +#define CAM_CC_CPAS_SBI_CLK 24 +#define CAM_CC_CPAS_SFE_0_CLK 25 +#define CAM_CC_CPAS_SFE_1_CLK 26 +#define CAM_CC_CPHY_RX_CLK_SRC 27 +#define CAM_CC_CRE_AHB_CLK 28 +#define CAM_CC_CRE_CLK 29 +#define CAM_CC_CRE_CLK_SRC 30 +#define CAM_CC_CSI0PHYTIMER_CLK 31 +#define CAM_CC_CSI0PHYTIMER_CLK_SRC 32 +#define CAM_CC_CSI1PHYTIMER_CLK 33 +#define CAM_CC_CSI1PHYTIMER_CLK_SRC 34 +#define CAM_CC_CSI2PHYTIMER_CLK 35 +#define CAM_CC_CSI2PHYTIMER_CLK_SRC 36 +#define CAM_CC_CSI3PHYTIMER_CLK 37 +#define CAM_CC_CSI3PHYTIMER_CLK_SRC 38 +#define CAM_CC_CSI4PHYTIMER_CLK 39 +#define CAM_CC_CSI4PHYTIMER_CLK_SRC 40 +#define CAM_CC_CSI5PHYTIMER_CLK 41 +#define CAM_CC_CSI5PHYTIMER_CLK_SRC 42 +#define CAM_CC_CSI6PHYTIMER_CLK 43 +#define CAM_CC_CSI6PHYTIMER_CLK_SRC 44 +#define CAM_CC_CSI7PHYTIMER_CLK 45 +#define CAM_CC_CSI7PHYTIMER_CLK_SRC 46 +#define CAM_CC_CSID_CLK 47 +#define CAM_CC_CSID_CLK_SRC 48 +#define CAM_CC_CSID_CSIPHY_RX_CLK 49 +#define CAM_CC_CSIPHY0_CLK 50 +#define CAM_CC_CSIPHY1_CLK 51 +#define CAM_CC_CSIPHY2_CLK 52 +#define CAM_CC_CSIPHY3_CLK 53 +#define CAM_CC_CSIPHY4_CLK 54 +#define CAM_CC_CSIPHY5_CLK 55 +#define CAM_CC_CSIPHY6_CLK 56 +#define CAM_CC_CSIPHY7_CLK 57 +#define CAM_CC_DRV_AHB_CLK 58 +#define CAM_CC_DRV_XO_CLK 59 +#define CAM_CC_FAST_AHB_CLK_SRC 60 +#define CAM_CC_GDSC_CLK 61 +#define CAM_CC_ICP_AHB_CLK 62 +#define CAM_CC_ICP_CLK 63 +#define CAM_CC_ICP_CLK_SRC 64 +#define CAM_CC_IFE_0_CLK 65 +#define CAM_CC_IFE_0_CLK_SRC 66 +#define CAM_CC_IFE_0_DSP_CLK 67 +#define CAM_CC_IFE_0_DSP_CLK_SRC 68 +#define CAM_CC_IFE_0_FAST_AHB_CLK 69 +#define CAM_CC_IFE_1_CLK 70 +#define CAM_CC_IFE_1_CLK_SRC 71 +#define CAM_CC_IFE_1_DSP_CLK 72 +#define CAM_CC_IFE_1_DSP_CLK_SRC 73 +#define CAM_CC_IFE_1_FAST_AHB_CLK 74 +#define CAM_CC_IFE_2_CLK 75 +#define CAM_CC_IFE_2_CLK_SRC 76 +#define CAM_CC_IFE_2_DSP_CLK 77 +#define CAM_CC_IFE_2_DSP_CLK_SRC 78 +#define CAM_CC_IFE_2_FAST_AHB_CLK 79 +#define CAM_CC_IFE_LITE_AHB_CLK 80 +#define CAM_CC_IFE_LITE_CLK 81 +#define CAM_CC_IFE_LITE_CLK_SRC 82 +#define CAM_CC_IFE_LITE_CPHY_RX_CLK 83 +#define CAM_CC_IFE_LITE_CSID_CLK 84 +#define CAM_CC_IFE_LITE_CSID_CLK_SRC 85 +#define CAM_CC_IPE_NPS_AHB_CLK 86 +#define CAM_CC_IPE_NPS_CLK 87 +#define CAM_CC_IPE_NPS_CLK_SRC 88 +#define CAM_CC_IPE_NPS_FAST_AHB_CLK 89 +#define CAM_CC_IPE_PPS_CLK 90 +#define CAM_CC_IPE_PPS_FAST_AHB_CLK 91 +#define CAM_CC_JPEG_1_CLK 92 +#define CAM_CC_JPEG_CLK 93 +#define CAM_CC_JPEG_CLK_SRC 94 +#define CAM_CC_MCLK0_CLK 95 +#define CAM_CC_MCLK0_CLK_SRC 96 +#define CAM_CC_MCLK1_CLK 97 +#define CAM_CC_MCLK1_CLK_SRC 98 +#define CAM_CC_MCLK2_CLK 99 +#define CAM_CC_MCLK2_CLK_SRC 100 +#define CAM_CC_MCLK3_CLK 101 +#define CAM_CC_MCLK3_CLK_SRC 102 +#define CAM_CC_MCLK4_CLK 103 +#define CAM_CC_MCLK4_CLK_SRC 104 +#define CAM_CC_MCLK5_CLK 105 +#define CAM_CC_MCLK5_CLK_SRC 106 +#define CAM_CC_MCLK6_CLK 107 +#define CAM_CC_MCLK6_CLK_SRC 108 +#define CAM_CC_MCLK7_CLK 109 +#define CAM_CC_MCLK7_CLK_SRC 110 +#define CAM_CC_PLL0 111 +#define CAM_CC_PLL0_OUT_EVEN 112 +#define CAM_CC_PLL0_OUT_ODD 113 +#define CAM_CC_PLL1 114 +#define CAM_CC_PLL1_OUT_EVEN 115 +#define CAM_CC_PLL2 116 +#define CAM_CC_PLL3 117 +#define CAM_CC_PLL3_OUT_EVEN 118 +#define CAM_CC_PLL4 119 +#define CAM_CC_PLL4_OUT_EVEN 120 +#define CAM_CC_PLL5 121 +#define CAM_CC_PLL5_OUT_EVEN 122 +#define CAM_CC_PLL6 123 +#define CAM_CC_PLL6_OUT_EVEN 124 +#define CAM_CC_PLL7 125 +#define CAM_CC_PLL7_OUT_EVEN 126 +#define CAM_CC_PLL8 127 +#define CAM_CC_PLL8_OUT_EVEN 128 +#define CAM_CC_PLL9 129 +#define CAM_CC_PLL9_OUT_EVEN 130 +#define CAM_CC_PLL10 131 +#define CAM_CC_PLL10_OUT_EVEN 132 +#define CAM_CC_PLL11 133 +#define CAM_CC_PLL11_OUT_EVEN 134 +#define CAM_CC_PLL12 135 +#define CAM_CC_PLL12_OUT_EVEN 136 +#define CAM_CC_QDSS_DEBUG_CLK 137 +#define CAM_CC_QDSS_DEBUG_CLK_SRC 138 +#define CAM_CC_QDSS_DEBUG_XO_CLK 139 +#define CAM_CC_SBI_CLK 140 +#define CAM_CC_SBI_FAST_AHB_CLK 141 +#define CAM_CC_SFE_0_CLK 142 +#define CAM_CC_SFE_0_CLK_SRC 143 +#define CAM_CC_SFE_0_FAST_AHB_CLK 144 +#define CAM_CC_SFE_1_CLK 145 +#define CAM_CC_SFE_1_CLK_SRC 146 +#define CAM_CC_SFE_1_FAST_AHB_CLK 147 +#define CAM_CC_SLEEP_CLK 148 +#define CAM_CC_SLEEP_CLK_SRC 149 +#define CAM_CC_SLOW_AHB_CLK_SRC 150 +#define CAM_CC_XO_CLK_SRC 151 + +/* CAM_CC power domains */ +#define CAM_CC_BPS_GDSC 0 +#define CAM_CC_IFE_0_GDSC 1 +#define CAM_CC_IFE_1_GDSC 2 +#define CAM_CC_IFE_2_GDSC 3 +#define CAM_CC_IPE_0_GDSC 4 +#define CAM_CC_SBI_GDSC 5 +#define CAM_CC_SFE_0_GDSC 6 +#define CAM_CC_SFE_1_GDSC 7 +#define CAM_CC_TITAN_TOP_GDSC 8 + +/* CAM_CC resets */ +#define CAM_CC_BPS_BCR 0 +#define CAM_CC_DRV_BCR 1 +#define CAM_CC_ICP_BCR 2 +#define CAM_CC_IFE_0_BCR 3 +#define CAM_CC_IFE_1_BCR 4 +#define CAM_CC_IFE_2_BCR 5 +#define CAM_CC_IPE_0_BCR 6 +#define CAM_CC_QDSS_DEBUG_BCR 7 +#define CAM_CC_SBI_BCR 8 +#define CAM_CC_SFE_0_BCR 9 +#define CAM_CC_SFE_1_BCR 10 + +#endif -- cgit v1.2.3-59-g8ed1b From 3132a9a11e57f257ab79ae79ce101a38952fa50a Mon Sep 17 00:00:00 2001 From: Jagadeesh Kona Date: Fri, 7 Jul 2023 09:27:41 +0530 Subject: clk: qcom: clk-alpha-pll: Add support for lucid ole pll configure Lucid ole pll has as extra RINGOSC_CAL_L field in L register in addition to the fields that are part of lucid evo pll, hence add support for lucid ole pll configure function to configure the ole plls. Signed-off-by: Jagadeesh Kona Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20230707035744.22245-3-quic_jkona@quicinc.com Signed-off-by: Bjorn Andersson --- drivers/clk/qcom/clk-alpha-pll.c | 29 +++++++++++++++++++++++++++++ drivers/clk/qcom/clk-alpha-pll.h | 2 ++ 2 files changed, 31 insertions(+) diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c index e4ef645f65d1..4edbf77f3360 100644 --- a/drivers/clk/qcom/clk-alpha-pll.c +++ b/drivers/clk/qcom/clk-alpha-pll.c @@ -271,6 +271,7 @@ EXPORT_SYMBOL_GPL(clk_alpha_pll_regs); #define LUCID_EVO_ENABLE_VOTE_RUN BIT(25) #define LUCID_EVO_PLL_L_VAL_MASK GENMASK(15, 0) #define LUCID_EVO_PLL_CAL_L_VAL_SHIFT 16 +#define LUCID_OLE_PLL_RINGOSC_CAL_L_VAL_SHIFT 24 /* ZONDA PLL specific */ #define ZONDA_PLL_OUT_MASK 0xf @@ -2119,6 +2120,34 @@ void clk_lucid_evo_pll_configure(struct clk_alpha_pll *pll, struct regmap *regma } EXPORT_SYMBOL_GPL(clk_lucid_evo_pll_configure); +void clk_lucid_ole_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap, + const struct alpha_pll_config *config) +{ + u32 lval = config->l; + + lval |= TRION_PLL_CAL_VAL << LUCID_EVO_PLL_CAL_L_VAL_SHIFT; + lval |= TRION_PLL_CAL_VAL << LUCID_OLE_PLL_RINGOSC_CAL_L_VAL_SHIFT; + clk_alpha_pll_write_config(regmap, PLL_L_VAL(pll), lval); + 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_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); + clk_alpha_pll_write_config(regmap, PLL_TEST_CTL_U2(pll), config->test_ctl_hi2_val); + + /* Disable PLL output */ + regmap_update_bits(regmap, PLL_MODE(pll), PLL_OUTCTRL, 0); + + /* Set operation mode to STANDBY and de-assert the reset */ + regmap_write(regmap, PLL_OPMODE(pll), PLL_STANDBY); + regmap_update_bits(regmap, PLL_MODE(pll), PLL_RESET_N, PLL_RESET_N); +} +EXPORT_SYMBOL_GPL(clk_lucid_ole_pll_configure); + static int alpha_pll_lucid_evo_enable(struct clk_hw *hw) { struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); diff --git a/drivers/clk/qcom/clk-alpha-pll.h b/drivers/clk/qcom/clk-alpha-pll.h index e4bd863027ab..3b24a660daac 100644 --- a/drivers/clk/qcom/clk-alpha-pll.h +++ b/drivers/clk/qcom/clk-alpha-pll.h @@ -199,6 +199,8 @@ void clk_zonda_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap, const struct alpha_pll_config *config); void clk_lucid_evo_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap, const struct alpha_pll_config *config); +void clk_lucid_ole_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap, + const struct alpha_pll_config *config); void clk_rivian_evo_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap, const struct alpha_pll_config *config); void clk_stromer_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap, -- cgit v1.2.3-59-g8ed1b From ccc4e6a061a21d75b96d82fc4b084a8d96df6eb4 Mon Sep 17 00:00:00 2001 From: Jagadeesh Kona Date: Fri, 7 Jul 2023 09:27:42 +0530 Subject: clk: qcom: camcc-sm8550: Add camera clock controller driver for SM8550 Add support for the camera clock controller for camera clients to be able to request for camcc clocks on SM8550 platform. Co-developed-by: Taniya Das Signed-off-by: Taniya Das Signed-off-by: Jagadeesh Kona Reviewed-by: Konrad Dybcio Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20230707035744.22245-4-quic_jkona@quicinc.com Signed-off-by: Bjorn Andersson --- drivers/clk/qcom/Kconfig | 7 + drivers/clk/qcom/Makefile | 1 + drivers/clk/qcom/camcc-sm8550.c | 3383 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 3391 insertions(+) create mode 100644 drivers/clk/qcom/camcc-sm8550.c diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig index 865db5202e4c..4b72e98eaa70 100644 --- a/drivers/clk/qcom/Kconfig +++ b/drivers/clk/qcom/Kconfig @@ -764,6 +764,13 @@ config SM_CAMCC_8450 Support for the camera clock controller on SM8450 devices. Say Y if you want to support camera devices and camera functionality. +config SM_CAMCC_8550 + tristate "SM8550 Camera Clock Controller" + select SM_GCC_8550 + help + Support for the camera clock controller on SM8550 devices. + Say Y if you want to support camera devices and camera functionality. + config SM_DISPCC_6115 tristate "SM6115 Display Clock Controller" depends on ARM64 || COMPILE_TEST diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile index 4790c8cca426..a301b08dba05 100644 --- a/drivers/clk/qcom/Makefile +++ b/drivers/clk/qcom/Makefile @@ -102,6 +102,7 @@ obj-$(CONFIG_SDX_GCC_75) += gcc-sdx75.o obj-$(CONFIG_SM_CAMCC_6350) += camcc-sm6350.o obj-$(CONFIG_SM_CAMCC_8250) += camcc-sm8250.o obj-$(CONFIG_SM_CAMCC_8450) += camcc-sm8450.o +obj-$(CONFIG_SM_CAMCC_8550) += camcc-sm8550.o obj-$(CONFIG_SM_DISPCC_6115) += dispcc-sm6115.o obj-$(CONFIG_SM_DISPCC_6125) += dispcc-sm6125.o obj-$(CONFIG_SM_DISPCC_6350) += dispcc-sm6350.o diff --git a/drivers/clk/qcom/camcc-sm8550.c b/drivers/clk/qcom/camcc-sm8550.c new file mode 100644 index 000000000000..075bea32087c --- /dev/null +++ b/drivers/clk/qcom/camcc-sm8550.c @@ -0,0 +1,3383 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2023, Qualcomm Innovation Center, Inc. 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.h" +#include "common.h" +#include "gdsc.h" +#include "reset.h" + +enum { + DT_IFACE, + DT_BI_TCXO, +}; + +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_EVEN, + P_CAM_CC_PLL2_OUT_MAIN, + P_CAM_CC_PLL3_OUT_EVEN, + P_CAM_CC_PLL4_OUT_EVEN, + P_CAM_CC_PLL5_OUT_EVEN, + P_CAM_CC_PLL6_OUT_EVEN, + P_CAM_CC_PLL7_OUT_EVEN, + P_CAM_CC_PLL8_OUT_EVEN, + P_CAM_CC_PLL9_OUT_EVEN, + P_CAM_CC_PLL9_OUT_ODD, + P_CAM_CC_PLL10_OUT_EVEN, + P_CAM_CC_PLL11_OUT_EVEN, + P_CAM_CC_PLL12_OUT_EVEN, +}; + +static const struct pll_vco lucid_ole_vco[] = { + { 249600000, 2300000000, 0 }, +}; + +static const struct pll_vco rivian_ole_vco[] = { + { 777000000, 1285000000, 0 }, +}; + +static const struct alpha_pll_config cam_cc_pll0_config = { + .l = 0x3e, + .alpha = 0x8000, + .config_ctl_val = 0x20485699, + .config_ctl_hi_val = 0x00182261, + .config_ctl_hi1_val = 0x82aa299c, + .test_ctl_val = 0x00000000, + .test_ctl_hi_val = 0x00000003, + .test_ctl_hi1_val = 0x00009000, + .test_ctl_hi2_val = 0x00000034, + .user_ctl_val = 0x00008400, + .user_ctl_hi_val = 0x00000005, +}; + +static struct clk_alpha_pll cam_cc_pll0 = { + .offset = 0x0, + .vco_table = lucid_ole_vco, + .num_vco = ARRAY_SIZE(lucid_ole_vco), + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE], + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_pll0", + .parent_data = &(const struct clk_parent_data) { + .index = DT_BI_TCXO, + }, + .num_parents = 1, + .ops = &clk_alpha_pll_lucid_evo_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 = 10, + .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_OLE], + .clkr.hw.init = &(const 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_ole_ops, + }, +}; + +static const struct clk_div_table post_div_table_cam_cc_pll0_out_odd[] = { + { 0x2, 3 }, + { } +}; + +static struct clk_alpha_pll_postdiv cam_cc_pll0_out_odd = { + .offset = 0x0, + .post_div_shift = 14, + .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_OLE], + .clkr.hw.init = &(const 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_ole_ops, + }, +}; + +static const struct alpha_pll_config cam_cc_pll1_config = { + .l = 0x2f, + .alpha = 0x6555, + .config_ctl_val = 0x20485699, + .config_ctl_hi_val = 0x00182261, + .config_ctl_hi1_val = 0x82aa299c, + .test_ctl_val = 0x00000000, + .test_ctl_hi_val = 0x00000003, + .test_ctl_hi1_val = 0x00009000, + .test_ctl_hi2_val = 0x00000034, + .user_ctl_val = 0x00000400, + .user_ctl_hi_val = 0x00000005, +}; + +static struct clk_alpha_pll cam_cc_pll1 = { + .offset = 0x1000, + .vco_table = lucid_ole_vco, + .num_vco = ARRAY_SIZE(lucid_ole_vco), + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE], + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_pll1", + .parent_data = &(const struct clk_parent_data) { + .index = DT_BI_TCXO, + }, + .num_parents = 1, + .ops = &clk_alpha_pll_lucid_evo_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 = 10, + .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_OLE], + .clkr.hw.init = &(const 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_ole_ops, + }, +}; + +static const struct alpha_pll_config cam_cc_pll2_config = { + .l = 0x32, + .alpha = 0x0, + .config_ctl_val = 0x10000030, + .config_ctl_hi_val = 0x80890263, + .config_ctl_hi1_val = 0x00000217, + .user_ctl_val = 0x00000000, + .user_ctl_hi_val = 0x00100000, +}; + +static struct clk_alpha_pll cam_cc_pll2 = { + .offset = 0x2000, + .vco_table = rivian_ole_vco, + .num_vco = ARRAY_SIZE(rivian_ole_vco), + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_RIVIAN_EVO], + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_pll2", + .parent_data = &(const struct clk_parent_data) { + .index = DT_BI_TCXO, + }, + .num_parents = 1, + .ops = &clk_alpha_pll_rivian_evo_ops, + }, + }, +}; + +static const struct alpha_pll_config cam_cc_pll3_config = { + .l = 0x30, + .alpha = 0x8aaa, + .config_ctl_val = 0x20485699, + .config_ctl_hi_val = 0x00182261, + .config_ctl_hi1_val = 0x82aa299c, + .test_ctl_val = 0x00000000, + .test_ctl_hi_val = 0x00000003, + .test_ctl_hi1_val = 0x00009000, + .test_ctl_hi2_val = 0x00000034, + .user_ctl_val = 0x00000400, + .user_ctl_hi_val = 0x00000005, +}; + +static struct clk_alpha_pll cam_cc_pll3 = { + .offset = 0x3000, + .vco_table = lucid_ole_vco, + .num_vco = ARRAY_SIZE(lucid_ole_vco), + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE], + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_pll3", + .parent_data = &(const struct clk_parent_data) { + .index = DT_BI_TCXO, + }, + .num_parents = 1, + .ops = &clk_alpha_pll_lucid_evo_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 = 10, + .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_OLE], + .clkr.hw.init = &(const 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_ole_ops, + }, +}; + +static const struct alpha_pll_config cam_cc_pll4_config = { + .l = 0x30, + .alpha = 0x8aaa, + .config_ctl_val = 0x20485699, + .config_ctl_hi_val = 0x00182261, + .config_ctl_hi1_val = 0x82aa299c, + .test_ctl_val = 0x00000000, + .test_ctl_hi_val = 0x00000003, + .test_ctl_hi1_val = 0x00009000, + .test_ctl_hi2_val = 0x00000034, + .user_ctl_val = 0x00000400, + .user_ctl_hi_val = 0x00000005, +}; + +static struct clk_alpha_pll cam_cc_pll4 = { + .offset = 0x4000, + .vco_table = lucid_ole_vco, + .num_vco = ARRAY_SIZE(lucid_ole_vco), + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE], + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_pll4", + .parent_data = &(const struct clk_parent_data) { + .index = DT_BI_TCXO, + }, + .num_parents = 1, + .ops = &clk_alpha_pll_lucid_evo_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 = 10, + .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_OLE], + .clkr.hw.init = &(const 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_ole_ops, + }, +}; + +static const struct alpha_pll_config cam_cc_pll5_config = { + .l = 0x30, + .alpha = 0x8aaa, + .config_ctl_val = 0x20485699, + .config_ctl_hi_val = 0x00182261, + .config_ctl_hi1_val = 0x82aa299c, + .test_ctl_val = 0x00000000, + .test_ctl_hi_val = 0x00000003, + .test_ctl_hi1_val = 0x00009000, + .test_ctl_hi2_val = 0x00000034, + .user_ctl_val = 0x00000400, + .user_ctl_hi_val = 0x00000005, +}; + +static struct clk_alpha_pll cam_cc_pll5 = { + .offset = 0x5000, + .vco_table = lucid_ole_vco, + .num_vco = ARRAY_SIZE(lucid_ole_vco), + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE], + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_pll5", + .parent_data = &(const struct clk_parent_data) { + .index = DT_BI_TCXO, + }, + .num_parents = 1, + .ops = &clk_alpha_pll_lucid_evo_ops, + }, + }, +}; + +static const struct clk_div_table post_div_table_cam_cc_pll5_out_even[] = { + { 0x1, 2 }, + { } +}; + +static struct clk_alpha_pll_postdiv cam_cc_pll5_out_even = { + .offset = 0x5000, + .post_div_shift = 10, + .post_div_table = post_div_table_cam_cc_pll5_out_even, + .num_post_div = ARRAY_SIZE(post_div_table_cam_cc_pll5_out_even), + .width = 4, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE], + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_cc_pll5_out_even", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_pll5.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_alpha_pll_postdiv_lucid_ole_ops, + }, +}; + +static const struct alpha_pll_config cam_cc_pll6_config = { + .l = 0x30, + .alpha = 0x8aaa, + .config_ctl_val = 0x20485699, + .config_ctl_hi_val = 0x00182261, + .config_ctl_hi1_val = 0x82aa299c, + .test_ctl_val = 0x00000000, + .test_ctl_hi_val = 0x00000003, + .test_ctl_hi1_val = 0x00009000, + .test_ctl_hi2_val = 0x00000034, + .user_ctl_val = 0x00000400, + .user_ctl_hi_val = 0x00000005, +}; + +static struct clk_alpha_pll cam_cc_pll6 = { + .offset = 0x6000, + .vco_table = lucid_ole_vco, + .num_vco = ARRAY_SIZE(lucid_ole_vco), + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE], + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_pll6", + .parent_data = &(const struct clk_parent_data) { + .index = DT_BI_TCXO, + }, + .num_parents = 1, + .ops = &clk_alpha_pll_lucid_evo_ops, + }, + }, +}; + +static const struct clk_div_table post_div_table_cam_cc_pll6_out_even[] = { + { 0x1, 2 }, + { } +}; + +static struct clk_alpha_pll_postdiv cam_cc_pll6_out_even = { + .offset = 0x6000, + .post_div_shift = 10, + .post_div_table = post_div_table_cam_cc_pll6_out_even, + .num_post_div = ARRAY_SIZE(post_div_table_cam_cc_pll6_out_even), + .width = 4, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE], + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_cc_pll6_out_even", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_pll6.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_alpha_pll_postdiv_lucid_ole_ops, + }, +}; + +static const struct alpha_pll_config cam_cc_pll7_config = { + .l = 0x30, + .alpha = 0x8aaa, + .config_ctl_val = 0x20485699, + .config_ctl_hi_val = 0x00182261, + .config_ctl_hi1_val = 0x82aa299c, + .test_ctl_val = 0x00000000, + .test_ctl_hi_val = 0x00000003, + .test_ctl_hi1_val = 0x00009000, + .test_ctl_hi2_val = 0x00000034, + .user_ctl_val = 0x00000400, + .user_ctl_hi_val = 0x00000005, +}; + +static struct clk_alpha_pll cam_cc_pll7 = { + .offset = 0x7000, + .vco_table = lucid_ole_vco, + .num_vco = ARRAY_SIZE(lucid_ole_vco), + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE], + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_pll7", + .parent_data = &(const struct clk_parent_data) { + .index = DT_BI_TCXO, + }, + .num_parents = 1, + .ops = &clk_alpha_pll_lucid_evo_ops, + }, + }, +}; + +static const struct clk_div_table post_div_table_cam_cc_pll7_out_even[] = { + { 0x1, 2 }, + { } +}; + +static struct clk_alpha_pll_postdiv cam_cc_pll7_out_even = { + .offset = 0x7000, + .post_div_shift = 10, + .post_div_table = post_div_table_cam_cc_pll7_out_even, + .num_post_div = ARRAY_SIZE(post_div_table_cam_cc_pll7_out_even), + .width = 4, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE], + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_cc_pll7_out_even", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_pll7.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_alpha_pll_postdiv_lucid_ole_ops, + }, +}; + +static const struct alpha_pll_config cam_cc_pll8_config = { + .l = 0x14, + .alpha = 0xd555, + .config_ctl_val = 0x20485699, + .config_ctl_hi_val = 0x00182261, + .config_ctl_hi1_val = 0x82aa299c, + .test_ctl_val = 0x00000000, + .test_ctl_hi_val = 0x00000003, + .test_ctl_hi1_val = 0x00009000, + .test_ctl_hi2_val = 0x00000034, + .user_ctl_val = 0x00000400, + .user_ctl_hi_val = 0x00000005, +}; + +static struct clk_alpha_pll cam_cc_pll8 = { + .offset = 0x8000, + .vco_table = lucid_ole_vco, + .num_vco = ARRAY_SIZE(lucid_ole_vco), + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE], + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_pll8", + .parent_data = &(const struct clk_parent_data) { + .index = DT_BI_TCXO, + }, + .num_parents = 1, + .ops = &clk_alpha_pll_lucid_evo_ops, + }, + }, +}; + +static const struct clk_div_table post_div_table_cam_cc_pll8_out_even[] = { + { 0x1, 2 }, + { } +}; + +static struct clk_alpha_pll_postdiv cam_cc_pll8_out_even = { + .offset = 0x8000, + .post_div_shift = 10, + .post_div_table = post_div_table_cam_cc_pll8_out_even, + .num_post_div = ARRAY_SIZE(post_div_table_cam_cc_pll8_out_even), + .width = 4, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE], + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_cc_pll8_out_even", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_pll8.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_alpha_pll_postdiv_lucid_ole_ops, + }, +}; + +static const struct alpha_pll_config cam_cc_pll9_config = { + .l = 0x32, + .alpha = 0x0, + .config_ctl_val = 0x20485699, + .config_ctl_hi_val = 0x00182261, + .config_ctl_hi1_val = 0x82aa299c, + .test_ctl_val = 0x00000000, + .test_ctl_hi_val = 0x00000003, + .test_ctl_hi1_val = 0x00009000, + .test_ctl_hi2_val = 0x00000034, + .user_ctl_val = 0x00000400, + .user_ctl_hi_val = 0x00000005, +}; + +static struct clk_alpha_pll cam_cc_pll9 = { + .offset = 0x9000, + .vco_table = lucid_ole_vco, + .num_vco = ARRAY_SIZE(lucid_ole_vco), + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE], + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_pll9", + .parent_data = &(const struct clk_parent_data) { + .index = DT_BI_TCXO, + }, + .num_parents = 1, + .ops = &clk_alpha_pll_lucid_evo_ops, + }, + }, +}; + +static const struct clk_div_table post_div_table_cam_cc_pll9_out_even[] = { + { 0x1, 2 }, + { } +}; + +static struct clk_alpha_pll_postdiv cam_cc_pll9_out_even = { + .offset = 0x9000, + .post_div_shift = 10, + .post_div_table = post_div_table_cam_cc_pll9_out_even, + .num_post_div = ARRAY_SIZE(post_div_table_cam_cc_pll9_out_even), + .width = 4, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE], + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_cc_pll9_out_even", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_pll9.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_alpha_pll_postdiv_lucid_ole_ops, + }, +}; + +static const struct alpha_pll_config cam_cc_pll10_config = { + .l = 0x30, + .alpha = 0x8aaa, + .config_ctl_val = 0x20485699, + .config_ctl_hi_val = 0x00182261, + .config_ctl_hi1_val = 0x82aa299c, + .test_ctl_val = 0x00000000, + .test_ctl_hi_val = 0x00000003, + .test_ctl_hi1_val = 0x00009000, + .test_ctl_hi2_val = 0x00000034, + .user_ctl_val = 0x00000400, + .user_ctl_hi_val = 0x00000005, +}; + +static struct clk_alpha_pll cam_cc_pll10 = { + .offset = 0xa000, + .vco_table = lucid_ole_vco, + .num_vco = ARRAY_SIZE(lucid_ole_vco), + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE], + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_pll10", + .parent_data = &(const struct clk_parent_data) { + .index = DT_BI_TCXO, + }, + .num_parents = 1, + .ops = &clk_alpha_pll_lucid_evo_ops, + }, + }, +}; + +static const struct clk_div_table post_div_table_cam_cc_pll10_out_even[] = { + { 0x1, 2 }, + { } +}; + +static struct clk_alpha_pll_postdiv cam_cc_pll10_out_even = { + .offset = 0xa000, + .post_div_shift = 10, + .post_div_table = post_div_table_cam_cc_pll10_out_even, + .num_post_div = ARRAY_SIZE(post_div_table_cam_cc_pll10_out_even), + .width = 4, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE], + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_cc_pll10_out_even", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_pll10.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_alpha_pll_postdiv_lucid_ole_ops, + }, +}; + +static const struct alpha_pll_config cam_cc_pll11_config = { + .l = 0x30, + .alpha = 0x8aaa, + .config_ctl_val = 0x20485699, + .config_ctl_hi_val = 0x00182261, + .config_ctl_hi1_val = 0x82aa299c, + .test_ctl_val = 0x00000000, + .test_ctl_hi_val = 0x00000003, + .test_ctl_hi1_val = 0x00009000, + .test_ctl_hi2_val = 0x00000034, + .user_ctl_val = 0x00000400, + .user_ctl_hi_val = 0x00000005, +}; + +static struct clk_alpha_pll cam_cc_pll11 = { + .offset = 0xb000, + .vco_table = lucid_ole_vco, + .num_vco = ARRAY_SIZE(lucid_ole_vco), + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE], + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_pll11", + .parent_data = &(const struct clk_parent_data) { + .index = DT_BI_TCXO, + }, + .num_parents = 1, + .ops = &clk_alpha_pll_lucid_evo_ops, + }, + }, +}; + +static const struct clk_div_table post_div_table_cam_cc_pll11_out_even[] = { + { 0x1, 2 }, + { } +}; + +static struct clk_alpha_pll_postdiv cam_cc_pll11_out_even = { + .offset = 0xb000, + .post_div_shift = 10, + .post_div_table = post_div_table_cam_cc_pll11_out_even, + .num_post_div = ARRAY_SIZE(post_div_table_cam_cc_pll11_out_even), + .width = 4, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE], + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_cc_pll11_out_even", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_pll11.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_alpha_pll_postdiv_lucid_ole_ops, + }, +}; + +static const struct alpha_pll_config cam_cc_pll12_config = { + .l = 0x30, + .alpha = 0x8aaa, + .config_ctl_val = 0x20485699, + .config_ctl_hi_val = 0x00182261, + .config_ctl_hi1_val = 0x82aa299c, + .test_ctl_val = 0x00000000, + .test_ctl_hi_val = 0x00000003, + .test_ctl_hi1_val = 0x00009000, + .test_ctl_hi2_val = 0x00000034, + .user_ctl_val = 0x00000400, + .user_ctl_hi_val = 0x00000005, +}; + +static struct clk_alpha_pll cam_cc_pll12 = { + .offset = 0xc000, + .vco_table = lucid_ole_vco, + .num_vco = ARRAY_SIZE(lucid_ole_vco), + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE], + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_pll12", + .parent_data = &(const struct clk_parent_data) { + .index = DT_BI_TCXO, + }, + .num_parents = 1, + .ops = &clk_alpha_pll_lucid_evo_ops, + }, + }, +}; + +static const struct clk_div_table post_div_table_cam_cc_pll12_out_even[] = { + { 0x1, 2 }, + { } +}; + +static struct clk_alpha_pll_postdiv cam_cc_pll12_out_even = { + .offset = 0xc000, + .post_div_shift = 10, + .post_div_table = post_div_table_cam_cc_pll12_out_even, + .num_post_div = ARRAY_SIZE(post_div_table_cam_cc_pll12_out_even), + .width = 4, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE], + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_cc_pll12_out_even", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_pll12.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_alpha_pll_postdiv_lucid_ole_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_PLL9_OUT_ODD, 4 }, + { P_CAM_CC_PLL9_OUT_EVEN, 5 }, +}; + +static const struct clk_parent_data cam_cc_parent_data_0[] = { + { .index = DT_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_pll9.clkr.hw }, + { .hw = &cam_cc_pll9_out_even.clkr.hw }, +}; + +static const struct parent_map cam_cc_parent_map_1[] = { + { P_BI_TCXO, 0 }, + { P_CAM_CC_PLL2_OUT_EVEN, 3 }, + { P_CAM_CC_PLL2_OUT_MAIN, 5 }, +}; + +static const struct clk_parent_data cam_cc_parent_data_1[] = { + { .index = DT_BI_TCXO }, + { .hw = &cam_cc_pll2.clkr.hw }, + { .hw = &cam_cc_pll2.clkr.hw }, +}; + +static const struct parent_map cam_cc_parent_map_2[] = { + { P_BI_TCXO, 0 }, + { P_CAM_CC_PLL8_OUT_EVEN, 6 }, +}; + +static const struct clk_parent_data cam_cc_parent_data_2[] = { + { .index = DT_BI_TCXO }, + { .hw = &cam_cc_pll8_out_even.clkr.hw }, +}; + +static const struct parent_map cam_cc_parent_map_3[] = { + { P_BI_TCXO, 0 }, + { P_CAM_CC_PLL3_OUT_EVEN, 6 }, +}; + +static const struct clk_parent_data cam_cc_parent_data_3[] = { + { .index = DT_BI_TCXO }, + { .hw = &cam_cc_pll3_out_even.clkr.hw }, +}; + +static const struct parent_map cam_cc_parent_map_4[] = { + { P_BI_TCXO, 0 }, + { P_CAM_CC_PLL10_OUT_EVEN, 6 }, +}; + +static const struct clk_parent_data cam_cc_parent_data_4[] = { + { .index = DT_BI_TCXO }, + { .hw = &cam_cc_pll10_out_even.clkr.hw }, +}; + +static const struct parent_map cam_cc_parent_map_5[] = { + { P_BI_TCXO, 0 }, + { P_CAM_CC_PLL4_OUT_EVEN, 6 }, +}; + +static const struct clk_parent_data cam_cc_parent_data_5[] = { + { .index = DT_BI_TCXO }, + { .hw = &cam_cc_pll4_out_even.clkr.hw }, +}; + +static const struct parent_map cam_cc_parent_map_6[] = { + { P_BI_TCXO, 0 }, + { P_CAM_CC_PLL11_OUT_EVEN, 6 }, +}; + +static const struct clk_parent_data cam_cc_parent_data_6[] = { + { .index = DT_BI_TCXO }, + { .hw = &cam_cc_pll11_out_even.clkr.hw }, +}; + +static const struct parent_map cam_cc_parent_map_7[] = { + { P_BI_TCXO, 0 }, + { P_CAM_CC_PLL5_OUT_EVEN, 6 }, +}; + +static const struct clk_parent_data cam_cc_parent_data_7[] = { + { .index = DT_BI_TCXO }, + { .hw = &cam_cc_pll5_out_even.clkr.hw }, +}; + +static const struct parent_map cam_cc_parent_map_8[] = { + { P_BI_TCXO, 0 }, + { P_CAM_CC_PLL12_OUT_EVEN, 6 }, +}; + +static const struct clk_parent_data cam_cc_parent_data_8[] = { + { .index = DT_BI_TCXO }, + { .hw = &cam_cc_pll12_out_even.clkr.hw }, +}; + +static const struct parent_map cam_cc_parent_map_9[] = { + { P_BI_TCXO, 0 }, + { P_CAM_CC_PLL1_OUT_EVEN, 4 }, +}; + +static const struct clk_parent_data cam_cc_parent_data_9[] = { + { .index = DT_BI_TCXO }, + { .hw = &cam_cc_pll1_out_even.clkr.hw }, +}; + +static const struct parent_map cam_cc_parent_map_10[] = { + { P_BI_TCXO, 0 }, + { P_CAM_CC_PLL6_OUT_EVEN, 6 }, +}; + +static const struct clk_parent_data cam_cc_parent_data_10[] = { + { .index = DT_BI_TCXO }, + { .hw = &cam_cc_pll6_out_even.clkr.hw }, +}; + +static const struct parent_map cam_cc_parent_map_11[] = { + { P_BI_TCXO, 0 }, + { P_CAM_CC_PLL7_OUT_EVEN, 6 }, +}; + +static const struct clk_parent_data cam_cc_parent_data_11[] = { + { .index = DT_BI_TCXO }, + { .hw = &cam_cc_pll7_out_even.clkr.hw }, +}; + +static const struct freq_tbl ftbl_cam_cc_bps_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + F(200000000, P_CAM_CC_PLL8_OUT_EVEN, 1, 0, 0), + F(400000000, P_CAM_CC_PLL8_OUT_EVEN, 1, 0, 0), + F(480000000, P_CAM_CC_PLL8_OUT_EVEN, 1, 0, 0), + F(785000000, P_CAM_CC_PLL8_OUT_EVEN, 1, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_bps_clk_src = { + .cmd_rcgr = 0x10278, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_2, + .freq_tbl = ftbl_cam_cc_bps_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_cc_bps_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_shared_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 = 0x13de0, + .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 = &(const 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_shared_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 = 0x13900, + .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 = &(const 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_shared_ops, + }, +}; + +static struct clk_rcg2 cam_cc_cci_1_clk_src = { + .cmd_rcgr = 0x13a30, + .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 = &(const 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_shared_ops, + }, +}; + +static struct clk_rcg2 cam_cc_cci_2_clk_src = { + .cmd_rcgr = 0x13b60, + .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 = &(const struct clk_init_data) { + .name = "cam_cc_cci_2_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_shared_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_MAIN, 3, 0, 0), + F(480000000, P_CAM_CC_PLL0_OUT_MAIN, 2.5, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_cphy_rx_clk_src = { + .cmd_rcgr = 0x11290, + .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 = &(const 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_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_cam_cc_cre_clk_src[] = { + 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_PLL9_OUT_EVEN, 1, 0, 0), + F(600000000, P_CAM_CC_PLL0_OUT_EVEN, 1, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_cre_clk_src = { + .cmd_rcgr = 0x1353c, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_0, + .freq_tbl = ftbl_cam_cc_cre_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_cc_cre_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_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_cam_cc_csi0phytimer_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + F(400000000, P_CAM_CC_PLL0_OUT_EVEN, 1.5, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_csi0phytimer_clk_src = { + .cmd_rcgr = 0x15980, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_0, + .freq_tbl = ftbl_cam_cc_csi0phytimer_clk_src, + .clkr.hw.init = &(const 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_shared_ops, + }, +}; + +static struct clk_rcg2 cam_cc_csi1phytimer_clk_src = { + .cmd_rcgr = 0x15ab8, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_0, + .freq_tbl = ftbl_cam_cc_csi0phytimer_clk_src, + .clkr.hw.init = &(const 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_shared_ops, + }, +}; + +static struct clk_rcg2 cam_cc_csi2phytimer_clk_src = { + .cmd_rcgr = 0x15bec, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_0, + .freq_tbl = ftbl_cam_cc_csi0phytimer_clk_src, + .clkr.hw.init = &(const 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_shared_ops, + }, +}; + +static struct clk_rcg2 cam_cc_csi3phytimer_clk_src = { + .cmd_rcgr = 0x15d20, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_0, + .freq_tbl = ftbl_cam_cc_csi0phytimer_clk_src, + .clkr.hw.init = &(const 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_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_cam_cc_csi4phytimer_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_csi4phytimer_clk_src = { + .cmd_rcgr = 0x15e54, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_0, + .freq_tbl = ftbl_cam_cc_csi4phytimer_clk_src, + .clkr.hw.init = &(const 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_shared_ops, + }, +}; + +static struct clk_rcg2 cam_cc_csi5phytimer_clk_src = { + .cmd_rcgr = 0x15f88, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_0, + .freq_tbl = ftbl_cam_cc_csi0phytimer_clk_src, + .clkr.hw.init = &(const 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_shared_ops, + }, +}; + +static struct clk_rcg2 cam_cc_csi6phytimer_clk_src = { + .cmd_rcgr = 0x160bc, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_0, + .freq_tbl = ftbl_cam_cc_csi0phytimer_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_cc_csi6phytimer_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_shared_ops, + }, +}; + +static struct clk_rcg2 cam_cc_csi7phytimer_clk_src = { + .cmd_rcgr = 0x161f0, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_0, + .freq_tbl = ftbl_cam_cc_csi0phytimer_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_cc_csi7phytimer_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_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_cam_cc_csid_clk_src[] = { + F(400000000, P_CAM_CC_PLL0_OUT_MAIN, 3, 0, 0), + F(480000000, P_CAM_CC_PLL0_OUT_MAIN, 2.5, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_csid_clk_src = { + .cmd_rcgr = 0x13ca8, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_0, + .freq_tbl = ftbl_cam_cc_csid_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_cc_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_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_cam_cc_fast_ahb_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_MAIN, 3, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_fast_ahb_clk_src = { + .cmd_rcgr = 0x10018, + .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 = &(const 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_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_cam_cc_icp_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_PLL9_OUT_EVEN, 1, 0, 0), + F(600000000, P_CAM_CC_PLL0_OUT_MAIN, 2, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_icp_clk_src = { + .cmd_rcgr = 0x137c4, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_0, + .freq_tbl = ftbl_cam_cc_icp_clk_src, + .clkr.hw.init = &(const 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_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_cam_cc_ife_0_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + F(466000000, P_CAM_CC_PLL3_OUT_EVEN, 1, 0, 0), + F(594000000, P_CAM_CC_PLL3_OUT_EVEN, 1, 0, 0), + F(675000000, P_CAM_CC_PLL3_OUT_EVEN, 1, 0, 0), + F(785000000, P_CAM_CC_PLL3_OUT_EVEN, 1, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_ife_0_clk_src = { + .cmd_rcgr = 0x11018, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_3, + .freq_tbl = ftbl_cam_cc_ife_0_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_cc_ife_0_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_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_cam_cc_ife_0_dsp_clk_src[] = { + F(466000000, P_CAM_CC_PLL10_OUT_EVEN, 1, 0, 0), + F(594000000, P_CAM_CC_PLL10_OUT_EVEN, 1, 0, 0), + F(675000000, P_CAM_CC_PLL10_OUT_EVEN, 1, 0, 0), + F(785000000, P_CAM_CC_PLL10_OUT_EVEN, 1, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_ife_0_dsp_clk_src = { + .cmd_rcgr = 0x11154, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_4, + .freq_tbl = ftbl_cam_cc_ife_0_dsp_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_cc_ife_0_dsp_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_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_cam_cc_ife_1_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + F(466000000, P_CAM_CC_PLL4_OUT_EVEN, 1, 0, 0), + F(594000000, P_CAM_CC_PLL4_OUT_EVEN, 1, 0, 0), + F(675000000, P_CAM_CC_PLL4_OUT_EVEN, 1, 0, 0), + F(785000000, P_CAM_CC_PLL4_OUT_EVEN, 1, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_ife_1_clk_src = { + .cmd_rcgr = 0x12018, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_5, + .freq_tbl = ftbl_cam_cc_ife_1_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_cc_ife_1_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_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_cam_cc_ife_1_dsp_clk_src[] = { + F(466000000, P_CAM_CC_PLL11_OUT_EVEN, 1, 0, 0), + F(594000000, P_CAM_CC_PLL11_OUT_EVEN, 1, 0, 0), + F(675000000, P_CAM_CC_PLL11_OUT_EVEN, 1, 0, 0), + F(785000000, P_CAM_CC_PLL11_OUT_EVEN, 1, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_ife_1_dsp_clk_src = { + .cmd_rcgr = 0x12154, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_6, + .freq_tbl = ftbl_cam_cc_ife_1_dsp_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_cc_ife_1_dsp_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_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_cam_cc_ife_2_clk_src[] = { + F(466000000, P_CAM_CC_PLL5_OUT_EVEN, 1, 0, 0), + F(594000000, P_CAM_CC_PLL5_OUT_EVEN, 1, 0, 0), + F(675000000, P_CAM_CC_PLL5_OUT_EVEN, 1, 0, 0), + F(785000000, P_CAM_CC_PLL5_OUT_EVEN, 1, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_ife_2_clk_src = { + .cmd_rcgr = 0x122a8, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_7, + .freq_tbl = ftbl_cam_cc_ife_2_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_cc_ife_2_clk_src", + .parent_data = cam_cc_parent_data_7, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_7), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_cam_cc_ife_2_dsp_clk_src[] = { + F(466000000, P_CAM_CC_PLL12_OUT_EVEN, 1, 0, 0), + F(594000000, P_CAM_CC_PLL12_OUT_EVEN, 1, 0, 0), + F(675000000, P_CAM_CC_PLL12_OUT_EVEN, 1, 0, 0), + F(785000000, P_CAM_CC_PLL12_OUT_EVEN, 1, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_ife_2_dsp_clk_src = { + .cmd_rcgr = 0x123e4, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_8, + .freq_tbl = ftbl_cam_cc_ife_2_dsp_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_cc_ife_2_dsp_clk_src", + .parent_data = cam_cc_parent_data_8, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_8), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 cam_cc_ife_lite_clk_src = { + .cmd_rcgr = 0x13000, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_0, + .freq_tbl = ftbl_cam_cc_csid_clk_src, + .clkr.hw.init = &(const 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_shared_ops, + }, +}; + +static struct clk_rcg2 cam_cc_ife_lite_csid_clk_src = { + .cmd_rcgr = 0x1313c, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_0, + .freq_tbl = ftbl_cam_cc_csid_clk_src, + .clkr.hw.init = &(const 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_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_cam_cc_ipe_nps_clk_src[] = { + F(455000000, P_CAM_CC_PLL1_OUT_EVEN, 1, 0, 0), + F(575000000, P_CAM_CC_PLL1_OUT_EVEN, 1, 0, 0), + F(675000000, P_CAM_CC_PLL1_OUT_EVEN, 1, 0, 0), + F(825000000, P_CAM_CC_PLL1_OUT_EVEN, 1, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_ipe_nps_clk_src = { + .cmd_rcgr = 0x103cc, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_9, + .freq_tbl = ftbl_cam_cc_ipe_nps_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_cc_ipe_nps_clk_src", + .parent_data = cam_cc_parent_data_9, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_9), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_cam_cc_jpeg_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 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_PLL9_OUT_EVEN, 1, 0, 0), + F(600000000, P_CAM_CC_PLL0_OUT_EVEN, 1, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_jpeg_clk_src = { + .cmd_rcgr = 0x13674, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_0, + .freq_tbl = ftbl_cam_cc_jpeg_clk_src, + .clkr.hw.init = &(const 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_shared_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_MAIN, 10, 1, 4), + F(68571429, P_CAM_CC_PLL2_OUT_MAIN, 14, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_mclk0_clk_src = { + .cmd_rcgr = 0x15000, + .mnd_width = 8, + .hid_width = 5, + .parent_map = cam_cc_parent_map_1, + .freq_tbl = ftbl_cam_cc_mclk0_clk_src, + .clkr.hw.init = &(const 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_shared_ops, + }, +}; + +static struct clk_rcg2 cam_cc_mclk1_clk_src = { + .cmd_rcgr = 0x15130, + .mnd_width = 8, + .hid_width = 5, + .parent_map = cam_cc_parent_map_1, + .freq_tbl = ftbl_cam_cc_mclk0_clk_src, + .clkr.hw.init = &(const 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_shared_ops, + }, +}; + +static struct clk_rcg2 cam_cc_mclk2_clk_src = { + .cmd_rcgr = 0x15260, + .mnd_width = 8, + .hid_width = 5, + .parent_map = cam_cc_parent_map_1, + .freq_tbl = ftbl_cam_cc_mclk0_clk_src, + .clkr.hw.init = &(const 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_shared_ops, + }, +}; + +static struct clk_rcg2 cam_cc_mclk3_clk_src = { + .cmd_rcgr = 0x15390, + .mnd_width = 8, + .hid_width = 5, + .parent_map = cam_cc_parent_map_1, + .freq_tbl = ftbl_cam_cc_mclk0_clk_src, + .clkr.hw.init = &(const 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_shared_ops, + }, +}; + +static struct clk_rcg2 cam_cc_mclk4_clk_src = { + .cmd_rcgr = 0x154c0, + .mnd_width = 8, + .hid_width = 5, + .parent_map = cam_cc_parent_map_1, + .freq_tbl = ftbl_cam_cc_mclk0_clk_src, + .clkr.hw.init = &(const 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_shared_ops, + }, +}; + +static struct clk_rcg2 cam_cc_mclk5_clk_src = { + .cmd_rcgr = 0x155f0, + .mnd_width = 8, + .hid_width = 5, + .parent_map = cam_cc_parent_map_1, + .freq_tbl = ftbl_cam_cc_mclk0_clk_src, + .clkr.hw.init = &(const 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_shared_ops, + }, +}; + +static struct clk_rcg2 cam_cc_mclk6_clk_src = { + .cmd_rcgr = 0x15720, + .mnd_width = 8, + .hid_width = 5, + .parent_map = cam_cc_parent_map_1, + .freq_tbl = ftbl_cam_cc_mclk0_clk_src, + .clkr.hw.init = &(const 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_shared_ops, + }, +}; + +static struct clk_rcg2 cam_cc_mclk7_clk_src = { + .cmd_rcgr = 0x15850, + .mnd_width = 8, + .hid_width = 5, + .parent_map = cam_cc_parent_map_1, + .freq_tbl = ftbl_cam_cc_mclk0_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_cc_mclk7_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_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_cam_cc_sfe_0_clk_src[] = { + F(466000000, P_CAM_CC_PLL6_OUT_EVEN, 1, 0, 0), + F(594000000, P_CAM_CC_PLL6_OUT_EVEN, 1, 0, 0), + F(675000000, P_CAM_CC_PLL6_OUT_EVEN, 1, 0, 0), + F(785000000, P_CAM_CC_PLL6_OUT_EVEN, 1, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_sfe_0_clk_src = { + .cmd_rcgr = 0x13294, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_10, + .freq_tbl = ftbl_cam_cc_sfe_0_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_cc_sfe_0_clk_src", + .parent_data = cam_cc_parent_data_10, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_10), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_cam_cc_sfe_1_clk_src[] = { + F(466000000, P_CAM_CC_PLL7_OUT_EVEN, 1, 0, 0), + F(594000000, P_CAM_CC_PLL7_OUT_EVEN, 1, 0, 0), + F(675000000, P_CAM_CC_PLL7_OUT_EVEN, 1, 0, 0), + F(785000000, P_CAM_CC_PLL7_OUT_EVEN, 1, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_sfe_1_clk_src = { + .cmd_rcgr = 0x133f4, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_11, + .freq_tbl = ftbl_cam_cc_sfe_1_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_cc_sfe_1_clk_src", + .parent_data = cam_cc_parent_data_11, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_11), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_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 = 0x10148, + .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 = &(const 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_shared_ops, + }, +}; + +static struct clk_branch cam_cc_bps_ahb_clk = { + .halt_reg = 0x10274, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x10274, + .enable_mask = BIT(0), + .hw.init = &(const 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_clk = { + .halt_reg = 0x103a4, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x103a4, + .enable_mask = BIT(0), + .hw.init = &(const 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_bps_fast_ahb_clk = { + .halt_reg = 0x10144, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x10144, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_bps_fast_ahb_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_camnoc_axi_clk = { + .halt_reg = 0x13f0c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x13f0c, + .enable_mask = BIT(0), + .hw.init = &(const 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_cci_0_clk = { + .halt_reg = 0x13a2c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x13a2c, + .enable_mask = BIT(0), + .hw.init = &(const 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 = 0x13b5c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x13b5c, + .enable_mask = BIT(0), + .hw.init = &(const 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_cci_2_clk = { + .halt_reg = 0x13c8c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x13c8c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_cci_2_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_cci_2_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 = 0x1406c, + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x1406c, + .enable_mask = BIT(0), + .hw.init = &(const 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 = 0x13c90, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x13c90, + .enable_mask = BIT(0), + .hw.init = &(const 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_cpas_bps_clk = { + .halt_reg = 0x103b0, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x103b0, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_cpas_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_cpas_cre_clk = { + .halt_reg = 0x1366c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1366c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_cpas_cre_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_cre_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_cpas_fast_ahb_clk = { + .halt_reg = 0x13c9c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x13c9c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_cpas_fast_ahb_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_cpas_ife_0_clk = { + .halt_reg = 0x11150, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x11150, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_cpas_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_cpas_ife_1_clk = { + .halt_reg = 0x12150, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x12150, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_cpas_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_cpas_ife_2_clk = { + .halt_reg = 0x123e0, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x123e0, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_cpas_ife_2_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_ife_2_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_cpas_ife_lite_clk = { + .halt_reg = 0x13138, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x13138, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_cpas_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_cpas_ipe_nps_clk = { + .halt_reg = 0x10504, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x10504, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_cpas_ipe_nps_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_ipe_nps_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_cpas_sbi_clk = { + .halt_reg = 0x1054c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1054c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_cpas_sbi_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_cpas_sfe_0_clk = { + .halt_reg = 0x133cc, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x133cc, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_cpas_sfe_0_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_sfe_0_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_cpas_sfe_1_clk = { + .halt_reg = 0x1352c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1352c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_cpas_sfe_1_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_sfe_1_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_cre_ahb_clk = { + .halt_reg = 0x13670, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x13670, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_cre_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_cre_clk = { + .halt_reg = 0x13668, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x13668, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_cre_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_cre_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 = 0x15aac, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x15aac, + .enable_mask = BIT(0), + .hw.init = &(const 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 = 0x15be4, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x15be4, + .enable_mask = BIT(0), + .hw.init = &(const 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 = 0x15d18, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x15d18, + .enable_mask = BIT(0), + .hw.init = &(const 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 = 0x15e4c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x15e4c, + .enable_mask = BIT(0), + .hw.init = &(const 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 = 0x15f80, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x15f80, + .enable_mask = BIT(0), + .hw.init = &(const 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 = 0x160b4, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x160b4, + .enable_mask = BIT(0), + .hw.init = &(const 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_csi6phytimer_clk = { + .halt_reg = 0x161e8, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x161e8, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_csi6phytimer_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_csi6phytimer_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_csi7phytimer_clk = { + .halt_reg = 0x1631c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1631c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_csi7phytimer_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_csi7phytimer_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_csid_clk = { + .halt_reg = 0x13dd4, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x13dd4, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_csid_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_csid_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_csid_csiphy_rx_clk = { + .halt_reg = 0x15ab4, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x15ab4, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_csid_csiphy_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_csiphy0_clk = { + .halt_reg = 0x15ab0, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x15ab0, + .enable_mask = BIT(0), + .hw.init = &(const 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 = 0x15be8, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x15be8, + .enable_mask = BIT(0), + .hw.init = &(const 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 = 0x15d1c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x15d1c, + .enable_mask = BIT(0), + .hw.init = &(const 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 = 0x15e50, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x15e50, + .enable_mask = BIT(0), + .hw.init = &(const 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 = 0x15f84, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x15f84, + .enable_mask = BIT(0), + .hw.init = &(const 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 = 0x160b8, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x160b8, + .enable_mask = BIT(0), + .hw.init = &(const 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_csiphy6_clk = { + .halt_reg = 0x161ec, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x161ec, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_csiphy6_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_csiphy7_clk = { + .halt_reg = 0x16320, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x16320, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_csiphy7_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_drv_ahb_clk = { + .halt_reg = 0x142d8, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x142d8, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_drv_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_ahb_clk = { + .halt_reg = 0x138fc, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x138fc, + .enable_mask = BIT(0), + .hw.init = &(const 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 = 0x138f0, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x138f0, + .enable_mask = BIT(0), + .hw.init = &(const 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_clk = { + .halt_reg = 0x11144, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x11144, + .enable_mask = BIT(0), + .hw.init = &(const 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_dsp_clk = { + .halt_reg = 0x11280, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x11280, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_ife_0_dsp_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_ife_0_dsp_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ife_0_fast_ahb_clk = { + .halt_reg = 0x1128c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1128c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_ife_0_fast_ahb_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_clk = { + .halt_reg = 0x12144, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x12144, + .enable_mask = BIT(0), + .hw.init = &(const 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_dsp_clk = { + .halt_reg = 0x12280, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x12280, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_ife_1_dsp_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_ife_1_dsp_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ife_1_fast_ahb_clk = { + .halt_reg = 0x1228c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1228c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_ife_1_fast_ahb_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_2_clk = { + .halt_reg = 0x123d4, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x123d4, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_ife_2_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_ife_2_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ife_2_dsp_clk = { + .halt_reg = 0x12510, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x12510, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_ife_2_dsp_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_ife_2_dsp_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ife_2_fast_ahb_clk = { + .halt_reg = 0x1251c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1251c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_ife_2_fast_ahb_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_lite_ahb_clk = { + .halt_reg = 0x13278, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x13278, + .enable_mask = BIT(0), + .hw.init = &(const 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_clk = { + .halt_reg = 0x1312c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1312c, + .enable_mask = BIT(0), + .hw.init = &(const 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 = 0x13274, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x13274, + .enable_mask = BIT(0), + .hw.init = &(const 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 = 0x13268, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x13268, + .enable_mask = BIT(0), + .hw.init = &(const 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_nps_ahb_clk = { + .halt_reg = 0x1051c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1051c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_ipe_nps_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_nps_clk = { + .halt_reg = 0x104f8, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x104f8, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_ipe_nps_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_ipe_nps_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ipe_nps_fast_ahb_clk = { + .halt_reg = 0x10520, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x10520, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_ipe_nps_fast_ahb_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_pps_clk = { + .halt_reg = 0x10508, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x10508, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_ipe_pps_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_ipe_nps_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ipe_pps_fast_ahb_clk = { + .halt_reg = 0x10524, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x10524, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_ipe_pps_fast_ahb_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_jpeg_1_clk = { + .halt_reg = 0x137ac, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x137ac, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_jpeg_1_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_jpeg_clk = { + .halt_reg = 0x137a0, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x137a0, + .enable_mask = BIT(0), + .hw.init = &(const 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 = 0x1512c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1512c, + .enable_mask = BIT(0), + .hw.init = &(const 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 = 0x1525c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1525c, + .enable_mask = BIT(0), + .hw.init = &(const 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 = 0x1538c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1538c, + .enable_mask = BIT(0), + .hw.init = &(const 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 = 0x154bc, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x154bc, + .enable_mask = BIT(0), + .hw.init = &(const 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 = 0x155ec, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x155ec, + .enable_mask = BIT(0), + .hw.init = &(const 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 = 0x1571c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1571c, + .enable_mask = BIT(0), + .hw.init = &(const 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 = 0x1584c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1584c, + .enable_mask = BIT(0), + .hw.init = &(const 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_mclk7_clk = { + .halt_reg = 0x1597c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1597c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_mclk7_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_mclk7_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 = 0x10540, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x10540, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_sbi_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_fast_ahb_clk = { + .halt_reg = 0x10550, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x10550, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_sbi_fast_ahb_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_sfe_0_clk = { + .halt_reg = 0x133c0, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x133c0, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_sfe_0_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_sfe_0_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_sfe_0_fast_ahb_clk = { + .halt_reg = 0x133d8, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x133d8, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_sfe_0_fast_ahb_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_sfe_1_clk = { + .halt_reg = 0x13520, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x13520, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_sfe_1_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_sfe_1_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_sfe_1_fast_ahb_clk = { + .halt_reg = 0x13538, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x13538, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_sfe_1_fast_ahb_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 gdsc cam_cc_bps_gdsc = { + .gdscr = 0x10004, + .en_rest_wait_val = 0x2, + .en_few_wait_val = 0x2, + .clk_dis_wait_val = 0xf, + .pd = { + .name = "cam_cc_bps_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, + .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE, +}; + +static struct gdsc cam_cc_ife_0_gdsc = { + .gdscr = 0x11004, + .en_rest_wait_val = 0x2, + .en_few_wait_val = 0x2, + .clk_dis_wait_val = 0xf, + .pd = { + .name = "cam_cc_ife_0_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, + .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE, +}; + +static struct gdsc cam_cc_ife_1_gdsc = { + .gdscr = 0x12004, + .en_rest_wait_val = 0x2, + .en_few_wait_val = 0x2, + .clk_dis_wait_val = 0xf, + .pd = { + .name = "cam_cc_ife_1_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, + .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE, +}; + +static struct gdsc cam_cc_ife_2_gdsc = { + .gdscr = 0x12294, + .en_rest_wait_val = 0x2, + .en_few_wait_val = 0x2, + .clk_dis_wait_val = 0xf, + .pd = { + .name = "cam_cc_ife_2_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, + .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE, +}; + +static struct gdsc cam_cc_ipe_0_gdsc = { + .gdscr = 0x103b8, + .en_rest_wait_val = 0x2, + .en_few_wait_val = 0x2, + .clk_dis_wait_val = 0xf, + .pd = { + .name = "cam_cc_ipe_0_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, + .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE, +}; + +static struct gdsc cam_cc_sbi_gdsc = { + .gdscr = 0x1052c, + .en_rest_wait_val = 0x2, + .en_few_wait_val = 0x2, + .clk_dis_wait_val = 0xf, + .pd = { + .name = "cam_cc_sbi_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, + .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE, +}; + +static struct gdsc cam_cc_sfe_0_gdsc = { + .gdscr = 0x13280, + .en_rest_wait_val = 0x2, + .en_few_wait_val = 0x2, + .clk_dis_wait_val = 0xf, + .pd = { + .name = "cam_cc_sfe_0_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, + .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE, +}; + +static struct gdsc cam_cc_sfe_1_gdsc = { + .gdscr = 0x133e0, + .en_rest_wait_val = 0x2, + .en_few_wait_val = 0x2, + .clk_dis_wait_val = 0xf, + .pd = { + .name = "cam_cc_sfe_1_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, + .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE, +}; + +static struct gdsc cam_cc_titan_top_gdsc = { + .gdscr = 0x14058, + .en_rest_wait_val = 0x2, + .en_few_wait_val = 0x2, + .clk_dis_wait_val = 0xf, + .pd = { + .name = "cam_cc_titan_top_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, + .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE, +}; + +static struct clk_regmap *cam_cc_sm8550_clocks[] = { + [CAM_CC_BPS_AHB_CLK] = &cam_cc_bps_ahb_clk.clkr, + [CAM_CC_BPS_CLK] = &cam_cc_bps_clk.clkr, + [CAM_CC_BPS_CLK_SRC] = &cam_cc_bps_clk_src.clkr, + [CAM_CC_BPS_FAST_AHB_CLK] = &cam_cc_bps_fast_ahb_clk.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_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_CCI_2_CLK] = &cam_cc_cci_2_clk.clkr, + [CAM_CC_CCI_2_CLK_SRC] = &cam_cc_cci_2_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_CPAS_BPS_CLK] = &cam_cc_cpas_bps_clk.clkr, + [CAM_CC_CPAS_CRE_CLK] = &cam_cc_cpas_cre_clk.clkr, + [CAM_CC_CPAS_FAST_AHB_CLK] = &cam_cc_cpas_fast_ahb_clk.clkr, + [CAM_CC_CPAS_IFE_0_CLK] = &cam_cc_cpas_ife_0_clk.clkr, + [CAM_CC_CPAS_IFE_1_CLK] = &cam_cc_cpas_ife_1_clk.clkr, + [CAM_CC_CPAS_IFE_2_CLK] = &cam_cc_cpas_ife_2_clk.clkr, + [CAM_CC_CPAS_IFE_LITE_CLK] = &cam_cc_cpas_ife_lite_clk.clkr, + [CAM_CC_CPAS_IPE_NPS_CLK] = &cam_cc_cpas_ipe_nps_clk.clkr, + [CAM_CC_CPAS_SBI_CLK] = &cam_cc_cpas_sbi_clk.clkr, + [CAM_CC_CPAS_SFE_0_CLK] = &cam_cc_cpas_sfe_0_clk.clkr, + [CAM_CC_CPAS_SFE_1_CLK] = &cam_cc_cpas_sfe_1_clk.clkr, + [CAM_CC_CPHY_RX_CLK_SRC] = &cam_cc_cphy_rx_clk_src.clkr, + [CAM_CC_CRE_AHB_CLK] = &cam_cc_cre_ahb_clk.clkr, + [CAM_CC_CRE_CLK] = &cam_cc_cre_clk.clkr, + [CAM_CC_CRE_CLK_SRC] = &cam_cc_cre_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_CSI6PHYTIMER_CLK] = &cam_cc_csi6phytimer_clk.clkr, + [CAM_CC_CSI6PHYTIMER_CLK_SRC] = &cam_cc_csi6phytimer_clk_src.clkr, + [CAM_CC_CSI7PHYTIMER_CLK] = &cam_cc_csi7phytimer_clk.clkr, + [CAM_CC_CSI7PHYTIMER_CLK_SRC] = &cam_cc_csi7phytimer_clk_src.clkr, + [CAM_CC_CSID_CLK] = &cam_cc_csid_clk.clkr, + [CAM_CC_CSID_CLK_SRC] = &cam_cc_csid_clk_src.clkr, + [CAM_CC_CSID_CSIPHY_RX_CLK] = &cam_cc_csid_csiphy_rx_clk.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_CSIPHY6_CLK] = &cam_cc_csiphy6_clk.clkr, + [CAM_CC_CSIPHY7_CLK] = &cam_cc_csiphy7_clk.clkr, + [CAM_CC_DRV_AHB_CLK] = &cam_cc_drv_ahb_clk.clkr, + [CAM_CC_FAST_AHB_CLK_SRC] = &cam_cc_fast_ahb_clk_src.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_CLK] = &cam_cc_ife_0_clk.clkr, + [CAM_CC_IFE_0_CLK_SRC] = &cam_cc_ife_0_clk_src.clkr, + [CAM_CC_IFE_0_DSP_CLK] = &cam_cc_ife_0_dsp_clk.clkr, + [CAM_CC_IFE_0_DSP_CLK_SRC] = &cam_cc_ife_0_dsp_clk_src.clkr, + [CAM_CC_IFE_0_FAST_AHB_CLK] = &cam_cc_ife_0_fast_ahb_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_DSP_CLK] = &cam_cc_ife_1_dsp_clk.clkr, + [CAM_CC_IFE_1_DSP_CLK_SRC] = &cam_cc_ife_1_dsp_clk_src.clkr, + [CAM_CC_IFE_1_FAST_AHB_CLK] = &cam_cc_ife_1_fast_ahb_clk.clkr, + [CAM_CC_IFE_2_CLK] = &cam_cc_ife_2_clk.clkr, + [CAM_CC_IFE_2_CLK_SRC] = &cam_cc_ife_2_clk_src.clkr, + [CAM_CC_IFE_2_DSP_CLK] = &cam_cc_ife_2_dsp_clk.clkr, + [CAM_CC_IFE_2_DSP_CLK_SRC] = &cam_cc_ife_2_dsp_clk_src.clkr, + [CAM_CC_IFE_2_FAST_AHB_CLK] = &cam_cc_ife_2_fast_ahb_clk.clkr, + [CAM_CC_IFE_LITE_AHB_CLK] = &cam_cc_ife_lite_ahb_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_NPS_AHB_CLK] = &cam_cc_ipe_nps_ahb_clk.clkr, + [CAM_CC_IPE_NPS_CLK] = &cam_cc_ipe_nps_clk.clkr, + [CAM_CC_IPE_NPS_CLK_SRC] = &cam_cc_ipe_nps_clk_src.clkr, + [CAM_CC_IPE_NPS_FAST_AHB_CLK] = &cam_cc_ipe_nps_fast_ahb_clk.clkr, + [CAM_CC_IPE_PPS_CLK] = &cam_cc_ipe_pps_clk.clkr, + [CAM_CC_IPE_PPS_FAST_AHB_CLK] = &cam_cc_ipe_pps_fast_ahb_clk.clkr, + [CAM_CC_JPEG_1_CLK] = &cam_cc_jpeg_1_clk.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_MCLK7_CLK] = &cam_cc_mclk7_clk.clkr, + [CAM_CC_MCLK7_CLK_SRC] = &cam_cc_mclk7_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_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_PLL5] = &cam_cc_pll5.clkr, + [CAM_CC_PLL5_OUT_EVEN] = &cam_cc_pll5_out_even.clkr, + [CAM_CC_PLL6] = &cam_cc_pll6.clkr, + [CAM_CC_PLL6_OUT_EVEN] = &cam_cc_pll6_out_even.clkr, + [CAM_CC_PLL7] = &cam_cc_pll7.clkr, + [CAM_CC_PLL7_OUT_EVEN] = &cam_cc_pll7_out_even.clkr, + [CAM_CC_PLL8] = &cam_cc_pll8.clkr, + [CAM_CC_PLL8_OUT_EVEN] = &cam_cc_pll8_out_even.clkr, + [CAM_CC_PLL9] = &cam_cc_pll9.clkr, + [CAM_CC_PLL9_OUT_EVEN] = &cam_cc_pll9_out_even.clkr, + [CAM_CC_PLL10] = &cam_cc_pll10.clkr, + [CAM_CC_PLL10_OUT_EVEN] = &cam_cc_pll10_out_even.clkr, + [CAM_CC_PLL11] = &cam_cc_pll11.clkr, + [CAM_CC_PLL11_OUT_EVEN] = &cam_cc_pll11_out_even.clkr, + [CAM_CC_PLL12] = &cam_cc_pll12.clkr, + [CAM_CC_PLL12_OUT_EVEN] = &cam_cc_pll12_out_even.clkr, + [CAM_CC_SBI_CLK] = &cam_cc_sbi_clk.clkr, + [CAM_CC_SBI_FAST_AHB_CLK] = &cam_cc_sbi_fast_ahb_clk.clkr, + [CAM_CC_SFE_0_CLK] = &cam_cc_sfe_0_clk.clkr, + [CAM_CC_SFE_0_CLK_SRC] = &cam_cc_sfe_0_clk_src.clkr, + [CAM_CC_SFE_0_FAST_AHB_CLK] = &cam_cc_sfe_0_fast_ahb_clk.clkr, + [CAM_CC_SFE_1_CLK] = &cam_cc_sfe_1_clk.clkr, + [CAM_CC_SFE_1_CLK_SRC] = &cam_cc_sfe_1_clk_src.clkr, + [CAM_CC_SFE_1_FAST_AHB_CLK] = &cam_cc_sfe_1_fast_ahb_clk.clkr, + [CAM_CC_SLOW_AHB_CLK_SRC] = &cam_cc_slow_ahb_clk_src.clkr, +}; + +static struct gdsc *cam_cc_sm8550_gdscs[] = { + [CAM_CC_BPS_GDSC] = &cam_cc_bps_gdsc, + [CAM_CC_IFE_0_GDSC] = &cam_cc_ife_0_gdsc, + [CAM_CC_IFE_1_GDSC] = &cam_cc_ife_1_gdsc, + [CAM_CC_IFE_2_GDSC] = &cam_cc_ife_2_gdsc, + [CAM_CC_IPE_0_GDSC] = &cam_cc_ipe_0_gdsc, + [CAM_CC_SBI_GDSC] = &cam_cc_sbi_gdsc, + [CAM_CC_SFE_0_GDSC] = &cam_cc_sfe_0_gdsc, + [CAM_CC_SFE_1_GDSC] = &cam_cc_sfe_1_gdsc, + [CAM_CC_TITAN_TOP_GDSC] = &cam_cc_titan_top_gdsc, +}; + +static const struct qcom_reset_map cam_cc_sm8550_resets[] = { + [CAM_CC_BPS_BCR] = { 0x10000 }, + [CAM_CC_DRV_BCR] = { 0x142d0 }, + [CAM_CC_ICP_BCR] = { 0x137c0 }, + [CAM_CC_IFE_0_BCR] = { 0x11000 }, + [CAM_CC_IFE_1_BCR] = { 0x12000 }, + [CAM_CC_IFE_2_BCR] = { 0x12290 }, + [CAM_CC_IPE_0_BCR] = { 0x103b4 }, + [CAM_CC_QDSS_DEBUG_BCR] = { 0x13f20 }, + [CAM_CC_SBI_BCR] = { 0x10528 }, + [CAM_CC_SFE_0_BCR] = { 0x1327c }, + [CAM_CC_SFE_1_BCR] = { 0x133dc }, +}; + +static const struct regmap_config cam_cc_sm8550_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = 0x16320, + .fast_io = true, +}; + +static struct qcom_cc_desc cam_cc_sm8550_desc = { + .config = &cam_cc_sm8550_regmap_config, + .clks = cam_cc_sm8550_clocks, + .num_clks = ARRAY_SIZE(cam_cc_sm8550_clocks), + .resets = cam_cc_sm8550_resets, + .num_resets = ARRAY_SIZE(cam_cc_sm8550_resets), + .gdscs = cam_cc_sm8550_gdscs, + .num_gdscs = ARRAY_SIZE(cam_cc_sm8550_gdscs), +}; + +static const struct of_device_id cam_cc_sm8550_match_table[] = { + { .compatible = "qcom,sm8550-camcc" }, + { } +}; +MODULE_DEVICE_TABLE(of, cam_cc_sm8550_match_table); + +static int cam_cc_sm8550_probe(struct platform_device *pdev) +{ + struct regmap *regmap; + int ret; + + ret = devm_pm_runtime_enable(&pdev->dev); + if (ret) + return ret; + + ret = pm_runtime_resume_and_get(&pdev->dev); + if (ret) + return ret; + + regmap = qcom_cc_map(pdev, &cam_cc_sm8550_desc); + if (IS_ERR(regmap)) { + pm_runtime_put(&pdev->dev); + return PTR_ERR(regmap); + } + + clk_lucid_ole_pll_configure(&cam_cc_pll0, regmap, &cam_cc_pll0_config); + clk_lucid_ole_pll_configure(&cam_cc_pll1, regmap, &cam_cc_pll1_config); + clk_rivian_evo_pll_configure(&cam_cc_pll2, regmap, &cam_cc_pll2_config); + clk_lucid_ole_pll_configure(&cam_cc_pll3, regmap, &cam_cc_pll3_config); + clk_lucid_ole_pll_configure(&cam_cc_pll4, regmap, &cam_cc_pll4_config); + clk_lucid_ole_pll_configure(&cam_cc_pll5, regmap, &cam_cc_pll5_config); + clk_lucid_ole_pll_configure(&cam_cc_pll6, regmap, &cam_cc_pll6_config); + clk_lucid_ole_pll_configure(&cam_cc_pll7, regmap, &cam_cc_pll7_config); + clk_lucid_ole_pll_configure(&cam_cc_pll8, regmap, &cam_cc_pll8_config); + clk_lucid_ole_pll_configure(&cam_cc_pll9, regmap, &cam_cc_pll9_config); + clk_lucid_ole_pll_configure(&cam_cc_pll10, regmap, &cam_cc_pll10_config); + clk_lucid_ole_pll_configure(&cam_cc_pll11, regmap, &cam_cc_pll11_config); + clk_lucid_ole_pll_configure(&cam_cc_pll12, regmap, &cam_cc_pll12_config); + + /* + * Keep clocks always enabled: + * cam_cc_gdsc_clk + * cam_cc_sleep_clk + */ + regmap_update_bits(regmap, 0x1419c, BIT(0), BIT(0)); + regmap_update_bits(regmap, 0x142cc, BIT(0), BIT(0)); + + ret = qcom_cc_really_probe(pdev, &cam_cc_sm8550_desc, regmap); + + pm_runtime_put(&pdev->dev); + + return ret; +} + +static struct platform_driver cam_cc_sm8550_driver = { + .probe = cam_cc_sm8550_probe, + .driver = { + .name = "cam_cc-sm8550", + .of_match_table = cam_cc_sm8550_match_table, + }, +}; + +module_platform_driver(cam_cc_sm8550_driver); + +MODULE_DESCRIPTION("QTI CAMCC SM8550 Driver"); +MODULE_LICENSE("GPL"); -- cgit v1.2.3-59-g8ed1b From a209cf9cc8ae436c227e28c3e6a36fc1894b2dea Mon Sep 17 00:00:00 2001 From: Jagadeesh Kona Date: Fri, 7 Jul 2023 09:27:43 +0530 Subject: clk: qcom: camcc-sm8550: Add support for qdss, sleep and xo clocks Add support for camera qdss, sleep and xo clocks. Co-developed-by: Taniya Das Signed-off-by: Taniya Das Signed-off-by: Jagadeesh Kona Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20230707035744.22245-5-quic_jkona@quicinc.com Signed-off-by: Bjorn Andersson --- drivers/clk/qcom/camcc-sm8550.c | 181 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 181 insertions(+) diff --git a/drivers/clk/qcom/camcc-sm8550.c b/drivers/clk/qcom/camcc-sm8550.c index 075bea32087c..2133e768b891 100644 --- a/drivers/clk/qcom/camcc-sm8550.c +++ b/drivers/clk/qcom/camcc-sm8550.c @@ -22,10 +22,13 @@ enum { DT_IFACE, DT_BI_TCXO, + DT_BI_TCXO_AO, + DT_SLEEP_CLK, }; enum { P_BI_TCXO, + P_BI_TCXO_AO, P_CAM_CC_PLL0_OUT_EVEN, P_CAM_CC_PLL0_OUT_MAIN, P_CAM_CC_PLL0_OUT_ODD, @@ -43,6 +46,7 @@ enum { P_CAM_CC_PLL10_OUT_EVEN, P_CAM_CC_PLL11_OUT_EVEN, P_CAM_CC_PLL12_OUT_EVEN, + P_SLEEP_CLK, }; static const struct pll_vco lucid_ole_vco[] = { @@ -881,6 +885,22 @@ static const struct clk_parent_data cam_cc_parent_data_11[] = { { .hw = &cam_cc_pll7_out_even.clkr.hw }, }; +static const struct parent_map cam_cc_parent_map_12[] = { + { P_SLEEP_CLK, 0 }, +}; + +static const struct clk_parent_data cam_cc_parent_data_12[] = { + { .index = DT_SLEEP_CLK }, +}; + +static const struct parent_map cam_cc_parent_map_13_ao[] = { + { P_BI_TCXO_AO, 0 }, +}; + +static const struct clk_parent_data cam_cc_parent_data_13_ao[] = { + { .index = DT_BI_TCXO_AO }, +}; + static const struct freq_tbl ftbl_cam_cc_bps_clk_src[] = { F(19200000, P_BI_TCXO, 1, 0, 0), F(200000000, P_CAM_CC_PLL8_OUT_EVEN, 1, 0, 0), @@ -1565,6 +1585,29 @@ static struct clk_rcg2 cam_cc_mclk7_clk_src = { }, }; +static const struct freq_tbl ftbl_cam_cc_qdss_debug_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + F(75000000, P_CAM_CC_PLL0_OUT_EVEN, 8, 0, 0), + F(150000000, P_CAM_CC_PLL0_OUT_EVEN, 4, 0, 0), + F(300000000, P_CAM_CC_PLL0_OUT_MAIN, 4, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_qdss_debug_clk_src = { + .cmd_rcgr = 0x13f24, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_0, + .freq_tbl = ftbl_cam_cc_qdss_debug_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_cc_qdss_debug_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_shared_ops, + }, +}; + static const struct freq_tbl ftbl_cam_cc_sfe_0_clk_src[] = { F(466000000, P_CAM_CC_PLL6_OUT_EVEN, 1, 0, 0), F(594000000, P_CAM_CC_PLL6_OUT_EVEN, 1, 0, 0), @@ -1611,6 +1654,26 @@ static struct clk_rcg2 cam_cc_sfe_1_clk_src = { }, }; +static const struct freq_tbl ftbl_cam_cc_sleep_clk_src[] = { + F(32000, P_SLEEP_CLK, 1, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_sleep_clk_src = { + .cmd_rcgr = 0x141a0, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_12, + .freq_tbl = ftbl_cam_cc_sleep_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_cc_sleep_clk_src", + .parent_data = cam_cc_parent_data_12, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_12), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_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), @@ -1632,6 +1695,26 @@ static struct clk_rcg2 cam_cc_slow_ahb_clk_src = { }, }; +static const struct freq_tbl ftbl_cam_cc_xo_clk_src[] = { + F(19200000, P_BI_TCXO_AO, 1, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_xo_clk_src = { + .cmd_rcgr = 0x14070, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_13_ao, + .freq_tbl = ftbl_cam_cc_xo_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "cam_cc_xo_clk_src", + .parent_data = cam_cc_parent_data_13_ao, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_13_ao), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + static struct clk_branch cam_cc_bps_ahb_clk = { .halt_reg = 0x10274, .halt_check = BRANCH_HALT, @@ -1704,6 +1787,42 @@ static struct clk_branch cam_cc_camnoc_axi_clk = { }, }; +static struct clk_branch cam_cc_camnoc_dcd_xo_clk = { + .halt_reg = 0x13f18, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x13f18, + .enable_mask = BIT(0), + .hw.init = &(const 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_camnoc_xo_clk = { + .halt_reg = 0x13f1c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x13f1c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_camnoc_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 = 0x13a2c, .halt_check = BRANCH_HALT, @@ -2370,6 +2489,24 @@ static struct clk_branch cam_cc_drv_ahb_clk = { }, }; +static struct clk_branch cam_cc_drv_xo_clk = { + .halt_reg = 0x142d4, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x142d4, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_drv_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_icp_ahb_clk = { .halt_reg = 0x138fc, .halt_check = BRANCH_HALT, @@ -2910,6 +3047,42 @@ static struct clk_branch cam_cc_mclk7_clk = { }, }; +static struct clk_branch cam_cc_qdss_debug_clk = { + .halt_reg = 0x14050, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x14050, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_qdss_debug_clk", + .parent_hws = (const struct clk_hw*[]) { + &cam_cc_qdss_debug_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_qdss_debug_xo_clk = { + .halt_reg = 0x14054, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x14054, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "cam_cc_qdss_debug_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_sbi_clk = { .halt_reg = 0x10540, .halt_check = BRANCH_HALT, @@ -3133,6 +3306,8 @@ static struct clk_regmap *cam_cc_sm8550_clocks[] = { [CAM_CC_BPS_FAST_AHB_CLK] = &cam_cc_bps_fast_ahb_clk.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_CAMNOC_XO_CLK] = &cam_cc_camnoc_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, @@ -3184,6 +3359,7 @@ static struct clk_regmap *cam_cc_sm8550_clocks[] = { [CAM_CC_CSIPHY6_CLK] = &cam_cc_csiphy6_clk.clkr, [CAM_CC_CSIPHY7_CLK] = &cam_cc_csiphy7_clk.clkr, [CAM_CC_DRV_AHB_CLK] = &cam_cc_drv_ahb_clk.clkr, + [CAM_CC_DRV_XO_CLK] = &cam_cc_drv_xo_clk.clkr, [CAM_CC_FAST_AHB_CLK_SRC] = &cam_cc_fast_ahb_clk_src.clkr, [CAM_CC_ICP_AHB_CLK] = &cam_cc_icp_ahb_clk.clkr, [CAM_CC_ICP_CLK] = &cam_cc_icp_clk.clkr, @@ -3260,6 +3436,9 @@ static struct clk_regmap *cam_cc_sm8550_clocks[] = { [CAM_CC_PLL11_OUT_EVEN] = &cam_cc_pll11_out_even.clkr, [CAM_CC_PLL12] = &cam_cc_pll12.clkr, [CAM_CC_PLL12_OUT_EVEN] = &cam_cc_pll12_out_even.clkr, + [CAM_CC_QDSS_DEBUG_CLK] = &cam_cc_qdss_debug_clk.clkr, + [CAM_CC_QDSS_DEBUG_CLK_SRC] = &cam_cc_qdss_debug_clk_src.clkr, + [CAM_CC_QDSS_DEBUG_XO_CLK] = &cam_cc_qdss_debug_xo_clk.clkr, [CAM_CC_SBI_CLK] = &cam_cc_sbi_clk.clkr, [CAM_CC_SBI_FAST_AHB_CLK] = &cam_cc_sbi_fast_ahb_clk.clkr, [CAM_CC_SFE_0_CLK] = &cam_cc_sfe_0_clk.clkr, @@ -3268,7 +3447,9 @@ static struct clk_regmap *cam_cc_sm8550_clocks[] = { [CAM_CC_SFE_1_CLK] = &cam_cc_sfe_1_clk.clkr, [CAM_CC_SFE_1_CLK_SRC] = &cam_cc_sfe_1_clk_src.clkr, [CAM_CC_SFE_1_FAST_AHB_CLK] = &cam_cc_sfe_1_fast_ahb_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_sm8550_gdscs[] = { -- cgit v1.2.3-59-g8ed1b From ccd8ab030643040600a663edde56b434b6f4fb6c Mon Sep 17 00:00:00 2001 From: Varadarajan Narayanan Date: Thu, 31 Aug 2023 14:58:53 +0530 Subject: clk: qcom: ipq5332: Drop set rate parent from gpll0 dependent clocks IPQ5332's GPLL0's nominal/turbo frequency is 800MHz. This must not be scaled based on the requirement of dependent clocks. Hence remove the CLK_SET_RATE_PARENT flag. Fixes: 3d89d52970fd ("clk: qcom: add Global Clock controller (GCC) driver for IPQ5332 SoC") Signed-off-by: Varadarajan Narayanan Reviewed-by: Kathiravan T Link: https://lore.kernel.org/r/1693474133-10467-1-git-send-email-quic_varada@quicinc.com Signed-off-by: Bjorn Andersson --- drivers/clk/qcom/gcc-ipq5332.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/clk/qcom/gcc-ipq5332.c b/drivers/clk/qcom/gcc-ipq5332.c index b02026f8549b..b836159fbdef 100644 --- a/drivers/clk/qcom/gcc-ipq5332.c +++ b/drivers/clk/qcom/gcc-ipq5332.c @@ -71,7 +71,6 @@ static struct clk_fixed_factor gpll0_div2 = { &gpll0_main.clkr.hw }, .num_parents = 1, .ops = &clk_fixed_factor_ops, - .flags = CLK_SET_RATE_PARENT, }, }; @@ -85,7 +84,6 @@ static struct clk_alpha_pll_postdiv gpll0 = { &gpll0_main.clkr.hw }, .num_parents = 1, .ops = &clk_alpha_pll_postdiv_ro_ops, - .flags = CLK_SET_RATE_PARENT, }, }; -- cgit v1.2.3-59-g8ed1b From 4afda5f6bcdf673ef2556fcfa458daf3a5a648d8 Mon Sep 17 00:00:00 2001 From: Konrad Dybcio Date: Thu, 31 Aug 2023 11:39:14 +0200 Subject: clk: qcom: gcc-msm8996: Remove RPM bus clocks The GCC driver contains clocks that are owned (meaning configured and scaled) by the RPM core. Remove them from Linux to stop interjecting the RPM's logic. Fixes: b1e010c0730a ("clk: qcom: Add MSM8996 Global Clock Control (GCC) driver") Signed-off-by: Konrad Dybcio Reviewed-by: Dmitry Baryshkov Tested-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20230830-topic-rpmbusclocks8996gcc-v1-1-9e99bedcdc3b@linaro.org Signed-off-by: Bjorn Andersson --- drivers/clk/qcom/gcc-msm8996.c | 237 +---------------------------------------- 1 file changed, 5 insertions(+), 232 deletions(-) diff --git a/drivers/clk/qcom/gcc-msm8996.c b/drivers/clk/qcom/gcc-msm8996.c index 14dcc3f03668..e7b03a17514a 100644 --- a/drivers/clk/qcom/gcc-msm8996.c +++ b/drivers/clk/qcom/gcc-msm8996.c @@ -244,71 +244,6 @@ static const struct clk_parent_data gcc_xo_gpll0_gpll4_gpll0_early_div[] = { { .hw = &gpll0_early_div.hw } }; -static const struct freq_tbl ftbl_system_noc_clk_src[] = { - F(19200000, P_XO, 1, 0, 0), - F(50000000, P_GPLL0_EARLY_DIV, 6, 0, 0), - F(100000000, P_GPLL0, 6, 0, 0), - F(150000000, P_GPLL0, 4, 0, 0), - F(200000000, P_GPLL0, 3, 0, 0), - F(240000000, P_GPLL0, 2.5, 0, 0), - { } -}; - -static struct clk_rcg2 system_noc_clk_src = { - .cmd_rcgr = 0x0401c, - .hid_width = 5, - .parent_map = gcc_xo_gpll0_gpll0_early_div_map, - .freq_tbl = ftbl_system_noc_clk_src, - .clkr.hw.init = &(struct clk_init_data){ - .name = "system_noc_clk_src", - .parent_data = gcc_xo_gpll0_gpll0_early_div, - .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0_early_div), - .ops = &clk_rcg2_ops, - }, -}; - -static const struct freq_tbl ftbl_config_noc_clk_src[] = { - F(19200000, P_XO, 1, 0, 0), - F(37500000, P_GPLL0, 16, 0, 0), - F(75000000, P_GPLL0, 8, 0, 0), - { } -}; - -static struct clk_rcg2 config_noc_clk_src = { - .cmd_rcgr = 0x0500c, - .hid_width = 5, - .parent_map = gcc_xo_gpll0_map, - .freq_tbl = ftbl_config_noc_clk_src, - .clkr.hw.init = &(struct clk_init_data){ - .name = "config_noc_clk_src", - .parent_data = gcc_xo_gpll0, - .num_parents = ARRAY_SIZE(gcc_xo_gpll0), - .ops = &clk_rcg2_ops, - }, -}; - -static const struct freq_tbl ftbl_periph_noc_clk_src[] = { - F(19200000, P_XO, 1, 0, 0), - F(37500000, P_GPLL0, 16, 0, 0), - F(50000000, P_GPLL0, 12, 0, 0), - F(75000000, P_GPLL0, 8, 0, 0), - F(100000000, P_GPLL0, 6, 0, 0), - { } -}; - -static struct clk_rcg2 periph_noc_clk_src = { - .cmd_rcgr = 0x06014, - .hid_width = 5, - .parent_map = gcc_xo_gpll0_map, - .freq_tbl = ftbl_periph_noc_clk_src, - .clkr.hw.init = &(struct clk_init_data){ - .name = "periph_noc_clk_src", - .parent_data = gcc_xo_gpll0, - .num_parents = ARRAY_SIZE(gcc_xo_gpll0), - .ops = &clk_rcg2_ops, - }, -}; - static const struct freq_tbl ftbl_usb30_master_clk_src[] = { F(19200000, P_XO, 1, 0, 0), F(120000000, P_GPLL0, 5, 0, 0), @@ -1297,11 +1232,7 @@ static struct clk_branch gcc_mmss_noc_cfg_ahb_clk = { .enable_mask = BIT(0), .hw.init = &(struct clk_init_data){ .name = "gcc_mmss_noc_cfg_ahb_clk", - .parent_hws = (const struct clk_hw*[]){ - &config_noc_clk_src.clkr.hw, - }, - .num_parents = 1, - .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, + .flags = CLK_IGNORE_UNUSED, .ops = &clk_branch2_ops, }, }, @@ -1464,11 +1395,6 @@ static struct clk_branch gcc_usb_phy_cfg_ahb2phy_clk = { .enable_mask = BIT(0), .hw.init = &(struct clk_init_data){ .name = "gcc_usb_phy_cfg_ahb2phy_clk", - .parent_hws = (const struct clk_hw*[]){ - &periph_noc_clk_src.clkr.hw, - }, - .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, .ops = &clk_branch2_ops, }, }, @@ -1498,11 +1424,6 @@ static struct clk_branch gcc_sdcc1_ahb_clk = { .enable_mask = BIT(0), .hw.init = &(struct clk_init_data){ .name = "gcc_sdcc1_ahb_clk", - .parent_hws = (const struct clk_hw*[]){ - &periph_noc_clk_src.clkr.hw, - }, - .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, .ops = &clk_branch2_ops, }, }, @@ -1549,11 +1470,6 @@ static struct clk_branch gcc_sdcc2_ahb_clk = { .enable_mask = BIT(0), .hw.init = &(struct clk_init_data){ .name = "gcc_sdcc2_ahb_clk", - .parent_hws = (const struct clk_hw*[]){ - &periph_noc_clk_src.clkr.hw, - }, - .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, .ops = &clk_branch2_ops, }, }, @@ -1583,11 +1499,6 @@ static struct clk_branch gcc_sdcc3_ahb_clk = { .enable_mask = BIT(0), .hw.init = &(struct clk_init_data){ .name = "gcc_sdcc3_ahb_clk", - .parent_hws = (const struct clk_hw*[]){ - &periph_noc_clk_src.clkr.hw, - }, - .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, .ops = &clk_branch2_ops, }, }, @@ -1617,11 +1528,6 @@ static struct clk_branch gcc_sdcc4_ahb_clk = { .enable_mask = BIT(0), .hw.init = &(struct clk_init_data){ .name = "gcc_sdcc4_ahb_clk", - .parent_hws = (const struct clk_hw*[]){ - &periph_noc_clk_src.clkr.hw, - }, - .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, .ops = &clk_branch2_ops, }, }, @@ -1635,11 +1541,6 @@ static struct clk_branch gcc_blsp1_ahb_clk = { .enable_mask = BIT(17), .hw.init = &(struct clk_init_data){ .name = "gcc_blsp1_ahb_clk", - .parent_hws = (const struct clk_hw*[]){ - &periph_noc_clk_src.clkr.hw, - }, - .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, .ops = &clk_branch2_ops, }, }, @@ -1977,11 +1878,6 @@ static struct clk_branch gcc_blsp2_ahb_clk = { .enable_mask = BIT(15), .hw.init = &(struct clk_init_data){ .name = "gcc_blsp2_ahb_clk", - .parent_hws = (const struct clk_hw*[]){ - &periph_noc_clk_src.clkr.hw, - }, - .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, .ops = &clk_branch2_ops, }, }, @@ -2318,11 +2214,6 @@ static struct clk_branch gcc_pdm_ahb_clk = { .enable_mask = BIT(0), .hw.init = &(struct clk_init_data){ .name = "gcc_pdm_ahb_clk", - .parent_hws = (const struct clk_hw*[]){ - &periph_noc_clk_src.clkr.hw, - }, - .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, .ops = &clk_branch2_ops, }, }, @@ -2353,11 +2244,6 @@ static struct clk_branch gcc_prng_ahb_clk = { .enable_mask = BIT(13), .hw.init = &(struct clk_init_data){ .name = "gcc_prng_ahb_clk", - .parent_hws = (const struct clk_hw*[]){ - &config_noc_clk_src.clkr.hw, - }, - .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, .ops = &clk_branch2_ops, }, }, @@ -2370,11 +2256,6 @@ static struct clk_branch gcc_tsif_ahb_clk = { .enable_mask = BIT(0), .hw.init = &(struct clk_init_data){ .name = "gcc_tsif_ahb_clk", - .parent_hws = (const struct clk_hw*[]){ - &periph_noc_clk_src.clkr.hw, - }, - .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, .ops = &clk_branch2_ops, }, }, @@ -2422,11 +2303,6 @@ static struct clk_branch gcc_boot_rom_ahb_clk = { .enable_mask = BIT(10), .hw.init = &(struct clk_init_data){ .name = "gcc_boot_rom_ahb_clk", - .parent_hws = (const struct clk_hw*[]){ - &config_noc_clk_src.clkr.hw, - }, - .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, .ops = &clk_branch2_ops, }, }, @@ -2520,11 +2396,6 @@ static struct clk_branch gcc_pcie_0_slv_axi_clk = { .enable_mask = BIT(0), .hw.init = &(struct clk_init_data){ .name = "gcc_pcie_0_slv_axi_clk", - .parent_hws = (const struct clk_hw*[]){ - &system_noc_clk_src.clkr.hw, - }, - .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, .ops = &clk_branch2_ops, }, }, @@ -2537,11 +2408,6 @@ static struct clk_branch gcc_pcie_0_mstr_axi_clk = { .enable_mask = BIT(0), .hw.init = &(struct clk_init_data){ .name = "gcc_pcie_0_mstr_axi_clk", - .parent_hws = (const struct clk_hw*[]){ - &system_noc_clk_src.clkr.hw, - }, - .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, .ops = &clk_branch2_ops, }, }, @@ -2554,11 +2420,6 @@ static struct clk_branch gcc_pcie_0_cfg_ahb_clk = { .enable_mask = BIT(0), .hw.init = &(struct clk_init_data){ .name = "gcc_pcie_0_cfg_ahb_clk", - .parent_hws = (const struct clk_hw*[]){ - &config_noc_clk_src.clkr.hw, - }, - .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, .ops = &clk_branch2_ops, }, }, @@ -2606,11 +2467,6 @@ static struct clk_branch gcc_pcie_1_slv_axi_clk = { .enable_mask = BIT(0), .hw.init = &(struct clk_init_data){ .name = "gcc_pcie_1_slv_axi_clk", - .parent_hws = (const struct clk_hw*[]){ - &system_noc_clk_src.clkr.hw, - }, - .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, .ops = &clk_branch2_ops, }, }, @@ -2623,11 +2479,6 @@ static struct clk_branch gcc_pcie_1_mstr_axi_clk = { .enable_mask = BIT(0), .hw.init = &(struct clk_init_data){ .name = "gcc_pcie_1_mstr_axi_clk", - .parent_hws = (const struct clk_hw*[]){ - &system_noc_clk_src.clkr.hw, - }, - .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, .ops = &clk_branch2_ops, }, }, @@ -2640,11 +2491,6 @@ static struct clk_branch gcc_pcie_1_cfg_ahb_clk = { .enable_mask = BIT(0), .hw.init = &(struct clk_init_data){ .name = "gcc_pcie_1_cfg_ahb_clk", - .parent_hws = (const struct clk_hw*[]){ - &config_noc_clk_src.clkr.hw, - }, - .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, .ops = &clk_branch2_ops, }, }, @@ -2692,11 +2538,6 @@ static struct clk_branch gcc_pcie_2_slv_axi_clk = { .enable_mask = BIT(0), .hw.init = &(struct clk_init_data){ .name = "gcc_pcie_2_slv_axi_clk", - .parent_hws = (const struct clk_hw*[]){ - &system_noc_clk_src.clkr.hw, - }, - .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, .ops = &clk_branch2_ops, }, }, @@ -2709,11 +2550,6 @@ static struct clk_branch gcc_pcie_2_mstr_axi_clk = { .enable_mask = BIT(0), .hw.init = &(struct clk_init_data){ .name = "gcc_pcie_2_mstr_axi_clk", - .parent_hws = (const struct clk_hw*[]){ - &system_noc_clk_src.clkr.hw, - }, - .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, .ops = &clk_branch2_ops, }, }, @@ -2726,11 +2562,6 @@ static struct clk_branch gcc_pcie_2_cfg_ahb_clk = { .enable_mask = BIT(0), .hw.init = &(struct clk_init_data){ .name = "gcc_pcie_2_cfg_ahb_clk", - .parent_hws = (const struct clk_hw*[]){ - &config_noc_clk_src.clkr.hw, - }, - .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, .ops = &clk_branch2_ops, }, }, @@ -2778,11 +2609,6 @@ static struct clk_branch gcc_pcie_phy_cfg_ahb_clk = { .enable_mask = BIT(0), .hw.init = &(struct clk_init_data){ .name = "gcc_pcie_phy_cfg_ahb_clk", - .parent_hws = (const struct clk_hw*[]){ - &config_noc_clk_src.clkr.hw, - }, - .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, .ops = &clk_branch2_ops, }, }, @@ -2829,11 +2655,6 @@ static struct clk_branch gcc_ufs_ahb_clk = { .enable_mask = BIT(0), .hw.init = &(struct clk_init_data){ .name = "gcc_ufs_ahb_clk", - .parent_hws = (const struct clk_hw*[]){ - &config_noc_clk_src.clkr.hw, - }, - .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, .ops = &clk_branch2_ops, }, }, @@ -3060,11 +2881,7 @@ static struct clk_branch gcc_aggre0_snoc_axi_clk = { .enable_mask = BIT(0), .hw.init = &(struct clk_init_data){ .name = "gcc_aggre0_snoc_axi_clk", - .parent_hws = (const struct clk_hw*[]){ - &system_noc_clk_src.clkr.hw, - }, - .num_parents = 1, - .flags = CLK_SET_RATE_PARENT | CLK_IS_CRITICAL, + .flags = CLK_IS_CRITICAL, .ops = &clk_branch2_ops, }, }, @@ -3077,11 +2894,7 @@ static struct clk_branch gcc_aggre0_cnoc_ahb_clk = { .enable_mask = BIT(0), .hw.init = &(struct clk_init_data){ .name = "gcc_aggre0_cnoc_ahb_clk", - .parent_hws = (const struct clk_hw*[]){ - &config_noc_clk_src.clkr.hw, - }, - .num_parents = 1, - .flags = CLK_SET_RATE_PARENT | CLK_IS_CRITICAL, + .flags = CLK_IS_CRITICAL, .ops = &clk_branch2_ops, }, }, @@ -3094,11 +2907,7 @@ static struct clk_branch gcc_smmu_aggre0_axi_clk = { .enable_mask = BIT(0), .hw.init = &(struct clk_init_data){ .name = "gcc_smmu_aggre0_axi_clk", - .parent_hws = (const struct clk_hw*[]){ - &system_noc_clk_src.clkr.hw, - }, - .num_parents = 1, - .flags = CLK_SET_RATE_PARENT | CLK_IS_CRITICAL, + .flags = CLK_IS_CRITICAL, .ops = &clk_branch2_ops, }, }, @@ -3111,11 +2920,7 @@ static struct clk_branch gcc_smmu_aggre0_ahb_clk = { .enable_mask = BIT(0), .hw.init = &(struct clk_init_data){ .name = "gcc_smmu_aggre0_ahb_clk", - .parent_hws = (const struct clk_hw*[]){ - &config_noc_clk_src.clkr.hw, - }, - .num_parents = 1, - .flags = CLK_SET_RATE_PARENT | CLK_IS_CRITICAL, + .flags = CLK_IS_CRITICAL, .ops = &clk_branch2_ops, }, }, @@ -3162,10 +2967,6 @@ static struct clk_branch gcc_dcc_ahb_clk = { .enable_mask = BIT(0), .hw.init = &(struct clk_init_data){ .name = "gcc_dcc_ahb_clk", - .parent_hws = (const struct clk_hw*[]){ - &config_noc_clk_src.clkr.hw, - }, - .num_parents = 1, .ops = &clk_branch2_ops, }, }, @@ -3178,10 +2979,6 @@ static struct clk_branch gcc_aggre0_noc_mpu_cfg_ahb_clk = { .enable_mask = BIT(0), .hw.init = &(struct clk_init_data){ .name = "gcc_aggre0_noc_mpu_cfg_ahb_clk", - .parent_hws = (const struct clk_hw*[]){ - &config_noc_clk_src.clkr.hw, - }, - .num_parents = 1, .ops = &clk_branch2_ops, }, }, @@ -3194,11 +2991,6 @@ static struct clk_branch gcc_qspi_ahb_clk = { .enable_mask = BIT(0), .hw.init = &(struct clk_init_data){ .name = "gcc_qspi_ahb_clk", - .parent_hws = (const struct clk_hw*[]){ - &periph_noc_clk_src.clkr.hw, - }, - .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, .ops = &clk_branch2_ops, }, }, @@ -3347,10 +3139,6 @@ static struct clk_branch gcc_mss_cfg_ahb_clk = { .enable_mask = BIT(0), .hw.init = &(struct clk_init_data){ .name = "gcc_mss_cfg_ahb_clk", - .parent_hws = (const struct clk_hw*[]){ - &config_noc_clk_src.clkr.hw, - }, - .num_parents = 1, .ops = &clk_branch2_ops, }, }, @@ -3363,10 +3151,6 @@ static struct clk_branch gcc_mss_mnoc_bimc_axi_clk = { .enable_mask = BIT(0), .hw.init = &(struct clk_init_data){ .name = "gcc_mss_mnoc_bimc_axi_clk", - .parent_hws = (const struct clk_hw*[]){ - &system_noc_clk_src.clkr.hw, - }, - .num_parents = 1, .ops = &clk_branch2_ops, }, }, @@ -3379,10 +3163,6 @@ static struct clk_branch gcc_mss_snoc_axi_clk = { .enable_mask = BIT(0), .hw.init = &(struct clk_init_data){ .name = "gcc_mss_snoc_axi_clk", - .parent_hws = (const struct clk_hw*[]){ - &system_noc_clk_src.clkr.hw, - }, - .num_parents = 1, .ops = &clk_branch2_ops, }, }, @@ -3395,10 +3175,6 @@ 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_hws = (const struct clk_hw*[]){ - &system_noc_clk_src.clkr.hw, - }, - .num_parents = 1, .ops = &clk_branch2_ops, }, }, @@ -3495,9 +3271,6 @@ static struct clk_regmap *gcc_msm8996_clocks[] = { [GPLL0] = &gpll0.clkr, [GPLL4_EARLY] = &gpll4_early.clkr, [GPLL4] = &gpll4.clkr, - [SYSTEM_NOC_CLK_SRC] = &system_noc_clk_src.clkr, - [CONFIG_NOC_CLK_SRC] = &config_noc_clk_src.clkr, - [PERIPH_NOC_CLK_SRC] = &periph_noc_clk_src.clkr, [USB30_MASTER_CLK_SRC] = &usb30_master_clk_src.clkr, [USB30_MOCK_UTMI_CLK_SRC] = &usb30_mock_utmi_clk_src.clkr, [USB3_PHY_AUX_CLK_SRC] = &usb3_phy_aux_clk_src.clkr, -- cgit v1.2.3-59-g8ed1b From f7b7d30158cff246667273bd2a62fc93ee0725d2 Mon Sep 17 00:00:00 2001 From: Devi Priya Date: Fri, 1 Sep 2023 13:06:40 +0530 Subject: clk: qcom: clk-rcg2: Fix clock rate overflow for high parent frequencies If the parent clock rate is greater than unsigned long max/2 then integer overflow happens when calculating the clock rate on 32-bit systems. As RCG2 uses half integer dividers, the clock rate is first being multiplied by 2 which will overflow the unsigned long max value. Hence, replace the common pattern of doing 64-bit multiplication and then a do_div() call with simpler mult_frac call. Fixes: bcd61c0f535a ("clk: qcom: Add support for root clock generators (RCGs)") Signed-off-by: Devi Priya Reviewed-by: Marijn Suijten Link: https://lore.kernel.org/r/20230901073640.4973-1-quic_devipriy@quicinc.com [bjorn: Also drop unnecessary {} around single statements] Signed-off-by: Bjorn Andersson --- drivers/clk/qcom/clk-rcg2.c | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/drivers/clk/qcom/clk-rcg2.c b/drivers/clk/qcom/clk-rcg2.c index e22baf3a7112..5183c74b074f 100644 --- a/drivers/clk/qcom/clk-rcg2.c +++ b/drivers/clk/qcom/clk-rcg2.c @@ -158,17 +158,11 @@ static int clk_rcg2_set_parent(struct clk_hw *hw, u8 index) static unsigned long calc_rate(unsigned long rate, u32 m, u32 n, u32 mode, u32 hid_div) { - if (hid_div) { - rate *= 2; - rate /= hid_div + 1; - } + if (hid_div) + rate = mult_frac(rate, 2, hid_div + 1); - if (mode) { - u64 tmp = rate; - tmp *= m; - do_div(tmp, n); - rate = tmp; - } + if (mode) + rate = mult_frac(rate, m, n); return rate; } -- cgit v1.2.3-59-g8ed1b From 9906c4140897bbdbff7bb71c6ae67903cb9954ce Mon Sep 17 00:00:00 2001 From: Konrad Dybcio Date: Wed, 9 Aug 2023 21:20:27 +0200 Subject: clk: qcom: mmcc-msm8998: Don't check halt bit on some branch clks Some branch clocks are governed externally and we're only supposed to send a request concerning their shutdown, not actually ensure it happens. Use the BRANCH_HALT_SKIP define to skip checking the halt bit. Fixes: d14b15b5931c ("clk: qcom: Add MSM8998 Multimedia Clock Controller (MMCC) driver") Reviewed-by: Jeffrey Hugo Signed-off-by: Konrad Dybcio Link: https://lore.kernel.org/r/20230531-topic-8998_mmssclk-v3-4-ba1b1fd9ee75@linaro.org Signed-off-by: Bjorn Andersson --- drivers/clk/qcom/mmcc-msm8998.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/clk/qcom/mmcc-msm8998.c b/drivers/clk/qcom/mmcc-msm8998.c index a023c4374be9..b0b51adb73a5 100644 --- a/drivers/clk/qcom/mmcc-msm8998.c +++ b/drivers/clk/qcom/mmcc-msm8998.c @@ -2439,6 +2439,7 @@ static struct clk_branch fd_ahb_clk = { static struct clk_branch mnoc_ahb_clk = { .halt_reg = 0x5024, + .halt_check = BRANCH_HALT_SKIP, .clkr = { .enable_reg = 0x5024, .enable_mask = BIT(0), @@ -2454,6 +2455,7 @@ static struct clk_branch mnoc_ahb_clk = { static struct clk_branch bimc_smmu_ahb_clk = { .halt_reg = 0xe004, + .halt_check = BRANCH_HALT_SKIP, .hwcg_reg = 0xe004, .hwcg_bit = 1, .clkr = { @@ -2471,6 +2473,7 @@ static struct clk_branch bimc_smmu_ahb_clk = { static struct clk_branch bimc_smmu_axi_clk = { .halt_reg = 0xe008, + .halt_check = BRANCH_HALT_SKIP, .hwcg_reg = 0xe008, .hwcg_bit = 1, .clkr = { -- cgit v1.2.3-59-g8ed1b From 1fc62c8347397faf4e18249e88ecd4470c0a5357 Mon Sep 17 00:00:00 2001 From: Konrad Dybcio Date: Wed, 9 Aug 2023 21:20:28 +0200 Subject: clk: qcom: mmcc-msm8998: Fix the SMMU GDSC The SMMU GDSC doesn't have to be ALWAYS-ON and shouldn't feature the HW_CTRL flag (it's separate from hw_ctrl_addr). In addition to that, it should feature a cxc entry for bimc_smmu_axi_clk and be marked as votable. Fix all of these issues. Fixes: d14b15b5931c ("clk: qcom: Add MSM8998 Multimedia Clock Controller (MMCC) driver") Signed-off-by: Konrad Dybcio Reviewed-by: Jeffrey Hugo Link: https://lore.kernel.org/r/20230531-topic-8998_mmssclk-v3-5-ba1b1fd9ee75@linaro.org Signed-off-by: Bjorn Andersson --- drivers/clk/qcom/mmcc-msm8998.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/clk/qcom/mmcc-msm8998.c b/drivers/clk/qcom/mmcc-msm8998.c index b0b51adb73a5..1180e48c687a 100644 --- a/drivers/clk/qcom/mmcc-msm8998.c +++ b/drivers/clk/qcom/mmcc-msm8998.c @@ -2610,11 +2610,13 @@ static struct gdsc camss_cpp_gdsc = { static struct gdsc bimc_smmu_gdsc = { .gdscr = 0xe020, .gds_hw_ctrl = 0xe024, + .cxcs = (unsigned int []){ 0xe008 }, + .cxc_count = 1, .pd = { .name = "bimc_smmu", }, .pwrsts = PWRSTS_OFF_ON, - .flags = HW_CTRL | ALWAYS_ON, + .flags = VOTABLE, }; static struct clk_regmap *mmcc_msm8998_clocks[] = { -- cgit v1.2.3-59-g8ed1b From 471e2875f8904539985e62220afd6c88e70779fa Mon Sep 17 00:00:00 2001 From: Luca Weiss Date: Sat, 2 Sep 2023 19:34:23 +0200 Subject: clk: qcom: mmcc-msm8974: remove ocmemcx_ahb_clk According to a commit in the 3.4 vendor kernel sources[0] the ocmemcx_ahb_clk clock "is controlled by RPM and should not be touched by APPS.". [0] https://git.codelinaro.org/clo/la/kernel/msm/-/commit/37df5f2d91b4d5768b37fcaacaeea958dd683ebc And indeed, when using MDSS+GPU+OCMEM on MSM8226 and not using clk_ignore_unused, when Linux tries to disable the clock the device crashes and reboots. And since there's also no evidence of this clock in msm8974 vendor kernel sources, remove the clock for msm8226 and msm8974. Fixes: d8b212014e69 ("clk: qcom: Add support for MSM8974's multimedia clock controller (MMCC)") Signed-off-by: Luca Weiss Reviewed-by: Konrad Dybcio Link: https://lore.kernel.org/r/20230902-msm8226-ocmemcx_ahb_clk-remove-v1-1-8124dbde83b9@z3ntu.xyz Signed-off-by: Bjorn Andersson --- drivers/clk/qcom/mmcc-msm8974.c | 18 ------------------ include/dt-bindings/clock/qcom,mmcc-msm8974.h | 1 - 2 files changed, 19 deletions(-) diff --git a/drivers/clk/qcom/mmcc-msm8974.c b/drivers/clk/qcom/mmcc-msm8974.c index 1f3bd302fe6e..a31f6cf0c4e0 100644 --- a/drivers/clk/qcom/mmcc-msm8974.c +++ b/drivers/clk/qcom/mmcc-msm8974.c @@ -2170,22 +2170,6 @@ static struct clk_branch mmss_s0_axi_clk = { }, }; -static struct clk_branch ocmemcx_ahb_clk = { - .halt_reg = 0x405c, - .clkr = { - .enable_reg = 0x405c, - .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data){ - .name = "ocmemcx_ahb_clk", - .parent_hws = (const struct clk_hw*[]){ - &mmss_ahb_clk_src.clkr.hw - }, - .num_parents = 1, - .ops = &clk_branch2_ops, - }, - }, -}; - static struct clk_branch ocmemcx_ocmemnoc_clk = { .halt_reg = 0x4058, .clkr = { @@ -2503,7 +2487,6 @@ static struct clk_regmap *mmcc_msm8226_clocks[] = { [MMSS_MMSSNOC_BTO_AHB_CLK] = &mmss_mmssnoc_bto_ahb_clk.clkr, [MMSS_MMSSNOC_AXI_CLK] = &mmss_mmssnoc_axi_clk.clkr, [MMSS_S0_AXI_CLK] = &mmss_s0_axi_clk.clkr, - [OCMEMCX_AHB_CLK] = &ocmemcx_ahb_clk.clkr, [OXILI_GFX3D_CLK] = &oxili_gfx3d_clk.clkr, [OXILICX_AHB_CLK] = &oxilicx_ahb_clk.clkr, [OXILICX_AXI_CLK] = &oxilicx_axi_clk.clkr, @@ -2660,7 +2643,6 @@ static struct clk_regmap *mmcc_msm8974_clocks[] = { [MMSS_MMSSNOC_BTO_AHB_CLK] = &mmss_mmssnoc_bto_ahb_clk.clkr, [MMSS_MMSSNOC_AXI_CLK] = &mmss_mmssnoc_axi_clk.clkr, [MMSS_S0_AXI_CLK] = &mmss_s0_axi_clk.clkr, - [OCMEMCX_AHB_CLK] = &ocmemcx_ahb_clk.clkr, [OCMEMCX_OCMEMNOC_CLK] = &ocmemcx_ocmemnoc_clk.clkr, [OCMEMNOC_CLK] = &ocmemnoc_clk.clkr, [OXILI_GFX3D_CLK] = &oxili_gfx3d_clk.clkr, diff --git a/include/dt-bindings/clock/qcom,mmcc-msm8974.h b/include/dt-bindings/clock/qcom,mmcc-msm8974.h index a62cb0629a7a..743ee60632eb 100644 --- a/include/dt-bindings/clock/qcom,mmcc-msm8974.h +++ b/include/dt-bindings/clock/qcom,mmcc-msm8974.h @@ -121,7 +121,6 @@ #define MMSS_MMSSNOC_BTO_AHB_CLK 112 #define MMSS_MMSSNOC_AXI_CLK 113 #define MMSS_S0_AXI_CLK 114 -#define OCMEMCX_AHB_CLK 115 #define OCMEMCX_OCMEMNOC_CLK 116 #define OXILI_OCMEMGX_CLK 117 #define OCMEMNOC_CLK 118 -- cgit v1.2.3-59-g8ed1b From 0b8aae7ed8eaf24d5f59d390325e9b2ebf1c78bd Mon Sep 17 00:00:00 2001 From: Ajit Pandey Date: Sat, 9 Sep 2023 18:04:28 +0530 Subject: dt-bindings: clock: qcom: Add RPMHCC for SM4450 Add compatible string for qcom RPMHCC for SM4450 platform. Signed-off-by: Ajit Pandey Acked-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20230909123431.1725728-2-quic_ajipan@quicinc.com Signed-off-by: Bjorn Andersson --- Documentation/devicetree/bindings/clock/qcom,rpmhcc.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/clock/qcom,rpmhcc.yaml b/Documentation/devicetree/bindings/clock/qcom,rpmhcc.yaml index fd14d18309a8..4eb5e59f6772 100644 --- a/Documentation/devicetree/bindings/clock/qcom,rpmhcc.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,rpmhcc.yaml @@ -28,6 +28,7 @@ properties: - qcom,sdx55-rpmh-clk - qcom,sdx65-rpmh-clk - qcom,sdx75-rpmh-clk + - qcom,sm4450-rpmh-clk - qcom,sm6350-rpmh-clk - qcom,sm8150-rpmh-clk - qcom,sm8250-rpmh-clk -- cgit v1.2.3-59-g8ed1b From 5a6eabf3268f91ce3cb5350210d0a876fa65b481 Mon Sep 17 00:00:00 2001 From: Ajit Pandey Date: Sat, 9 Sep 2023 18:04:29 +0530 Subject: clk: qcom: rpmh: Add RPMH clocks support for SM4450 Add support for RPMH clocks for SM4450 platform. Signed-off-by: Ajit Pandey Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20230909123431.1725728-3-quic_ajipan@quicinc.com Signed-off-by: Bjorn Andersson --- drivers/clk/qcom/clk-rpmh.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/drivers/clk/qcom/clk-rpmh.c b/drivers/clk/qcom/clk-rpmh.c index 4c5b552b47b6..5d853fd43294 100644 --- a/drivers/clk/qcom/clk-rpmh.c +++ b/drivers/clk/qcom/clk-rpmh.c @@ -350,6 +350,7 @@ DEFINE_CLK_RPMH_VRM(ln_bb_clk3, _a2, "lnbclka3", 2); DEFINE_CLK_RPMH_VRM(ln_bb_clk1, _a4, "lnbclka1", 4); DEFINE_CLK_RPMH_VRM(ln_bb_clk2, _a4, "lnbclka2", 4); +DEFINE_CLK_RPMH_VRM(ln_bb_clk3, _a4, "lnbclka3", 4); DEFINE_CLK_RPMH_VRM(ln_bb_clk2, _g4, "lnbclkg2", 4); DEFINE_CLK_RPMH_VRM(ln_bb_clk3, _g4, "lnbclkg3", 4); @@ -717,6 +718,25 @@ static const struct clk_rpmh_desc clk_rpmh_sdx75 = { .num_clks = ARRAY_SIZE(sdx75_rpmh_clocks), }; +static struct clk_hw *sm4450_rpmh_clocks[] = { + [RPMH_CXO_CLK] = &clk_rpmh_bi_tcxo_div4.hw, + [RPMH_CXO_CLK_A] = &clk_rpmh_bi_tcxo_div4_ao.hw, + [RPMH_LN_BB_CLK2] = &clk_rpmh_ln_bb_clk2_a4.hw, + [RPMH_LN_BB_CLK2_A] = &clk_rpmh_ln_bb_clk2_a4_ao.hw, + [RPMH_LN_BB_CLK3] = &clk_rpmh_ln_bb_clk3_a4.hw, + [RPMH_LN_BB_CLK3_A] = &clk_rpmh_ln_bb_clk3_a4_ao.hw, + [RPMH_RF_CLK1] = &clk_rpmh_rf_clk1_a.hw, + [RPMH_RF_CLK1_A] = &clk_rpmh_rf_clk1_a_ao.hw, + [RPMH_RF_CLK5] = &clk_rpmh_rf_clk5_a.hw, + [RPMH_RF_CLK5_A] = &clk_rpmh_rf_clk5_a_ao.hw, + [RPMH_IPA_CLK] = &clk_rpmh_ipa.hw, +}; + +static const struct clk_rpmh_desc clk_rpmh_sm4450 = { + .clks = sm4450_rpmh_clocks, + .num_clks = ARRAY_SIZE(sm4450_rpmh_clocks), +}; + static struct clk_hw *of_clk_rpmh_hw_get(struct of_phandle_args *clkspec, void *data) { @@ -810,6 +830,7 @@ static const struct of_device_id clk_rpmh_match_table[] = { { .compatible = "qcom,sdx55-rpmh-clk", .data = &clk_rpmh_sdx55}, { .compatible = "qcom,sdx65-rpmh-clk", .data = &clk_rpmh_sdx65}, { .compatible = "qcom,sdx75-rpmh-clk", .data = &clk_rpmh_sdx75}, + { .compatible = "qcom,sm4450-rpmh-clk", .data = &clk_rpmh_sm4450}, { .compatible = "qcom,sm6350-rpmh-clk", .data = &clk_rpmh_sm6350}, { .compatible = "qcom,sm8150-rpmh-clk", .data = &clk_rpmh_sm8150}, { .compatible = "qcom,sm8250-rpmh-clk", .data = &clk_rpmh_sm8250}, -- cgit v1.2.3-59-g8ed1b From d2d04deb5566b82aeb795f24014f5b3bdb8315ed Mon Sep 17 00:00:00 2001 From: Ajit Pandey Date: Sat, 9 Sep 2023 18:04:30 +0530 Subject: dt-bindings: clock: qcom: Add GCC clocks for SM4450 Add support for qcom global clock controller bindings for SM4450 platform. Signed-off-by: Ajit Pandey Reviewed-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20230909123431.1725728-4-quic_ajipan@quicinc.com Signed-off-by: Bjorn Andersson --- .../devicetree/bindings/clock/qcom,sm4450-gcc.yaml | 55 ++++++ include/dt-bindings/clock/qcom,sm4450-gcc.h | 197 +++++++++++++++++++++ 2 files changed, 252 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/qcom,sm4450-gcc.yaml create mode 100644 include/dt-bindings/clock/qcom,sm4450-gcc.h diff --git a/Documentation/devicetree/bindings/clock/qcom,sm4450-gcc.yaml b/Documentation/devicetree/bindings/clock/qcom,sm4450-gcc.yaml new file mode 100644 index 000000000000..5953c8d92436 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/qcom,sm4450-gcc.yaml @@ -0,0 +1,55 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/qcom,sm4450-gcc.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm Global Clock & Reset Controller on SM4450 + +maintainers: + - Ajit Pandey + - Taniya Das + +description: | + Qualcomm global clock control module provides the clocks, resets and power + domains on SM4450 + + See also:: include/dt-bindings/clock/qcom,sm4450-gcc.h + +properties: + compatible: + const: qcom,sm4450-gcc + + clocks: + items: + - description: Board XO source + - description: Sleep clock source + - description: UFS Phy Rx symbol 0 clock source + - description: UFS Phy Rx symbol 1 clock source + - description: UFS Phy Tx symbol 0 clock source + - description: USB3 Phy wrapper pipe clock source + +required: + - compatible + - clocks + +allOf: + - $ref: qcom,gcc.yaml# + +unevaluatedProperties: false + +examples: + - | + #include + clock-controller@100000 { + compatible = "qcom,sm4450-gcc"; + reg = <0x00100000 0x001f4200>; + clocks = <&rpmhcc RPMH_CXO_CLK>, <&sleep_clk>, + <&ufs_mem_phy 0>, <&ufs_mem_phy 1>, + <&ufs_mem_phy 2>, <&usb_1_qmpphy>; + #clock-cells = <1>; + #reset-cells = <1>; + #power-domain-cells = <1>; + }; + +... diff --git a/include/dt-bindings/clock/qcom,sm4450-gcc.h b/include/dt-bindings/clock/qcom,sm4450-gcc.h new file mode 100644 index 000000000000..c18e47a86f40 --- /dev/null +++ b/include/dt-bindings/clock/qcom,sm4450-gcc.h @@ -0,0 +1,197 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ +/* + * Copyright (c) 2023, Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#ifndef _DT_BINDINGS_CLK_QCOM_GCC_SM4450_H +#define _DT_BINDINGS_CLK_QCOM_GCC_SM4450_H + +/* GCC clocks */ +#define GCC_AGGRE_NOC_PCIE_0_AXI_CLK 0 +#define GCC_AGGRE_UFS_PHY_AXI_CLK 1 +#define GCC_AGGRE_UFS_PHY_AXI_HW_CTL_CLK 2 +#define GCC_AGGRE_USB3_PRIM_AXI_CLK 3 +#define GCC_BOOT_ROM_AHB_CLK 4 +#define GCC_CAMERA_AHB_CLK 5 +#define GCC_CAMERA_HF_AXI_CLK 6 +#define GCC_CAMERA_SF_AXI_CLK 7 +#define GCC_CAMERA_SLEEP_CLK 8 +#define GCC_CAMERA_XO_CLK 9 +#define GCC_CFG_NOC_PCIE_ANOC_AHB_CLK 10 +#define GCC_CFG_NOC_USB3_PRIM_AXI_CLK 11 +#define GCC_DDRSS_GPU_AXI_CLK 12 +#define GCC_DDRSS_PCIE_SF_TBU_CLK 13 +#define GCC_DISP_AHB_CLK 14 +#define GCC_DISP_HF_AXI_CLK 15 +#define GCC_DISP_XO_CLK 16 +#define GCC_EUSB3_0_CLKREF_EN 17 +#define GCC_GP1_CLK 18 +#define GCC_GP1_CLK_SRC 19 +#define GCC_GP2_CLK 20 +#define GCC_GP2_CLK_SRC 21 +#define GCC_GP3_CLK 22 +#define GCC_GP3_CLK_SRC 23 +#define GCC_GPLL0 24 +#define GCC_GPLL0_OUT_EVEN 25 +#define GCC_GPLL0_OUT_ODD 26 +#define GCC_GPLL1 27 +#define GCC_GPLL3 28 +#define GCC_GPLL4 29 +#define GCC_GPLL9 30 +#define GCC_GPLL10 31 +#define GCC_GPU_CFG_AHB_CLK 32 +#define GCC_GPU_GPLL0_CLK_SRC 33 +#define GCC_GPU_GPLL0_DIV_CLK_SRC 34 +#define GCC_GPU_MEMNOC_GFX_CLK 35 +#define GCC_GPU_SNOC_DVM_GFX_CLK 36 +#define GCC_HLOS1_VOTE_AGGRE_NOC_MMU_AUDIO_TBU_CLK 37 +#define GCC_HLOS1_VOTE_AGGRE_NOC_MMU_PCIE_TBU_CLK 38 +#define GCC_HLOS1_VOTE_AGGRE_NOC_MMU_TBU1_CLK 39 +#define GCC_HLOS1_VOTE_AGGRE_NOC_MMU_TBU2_CLK 40 +#define GCC_HLOS1_VOTE_MMNOC_MMU_TBU_HF0_CLK 41 +#define GCC_HLOS1_VOTE_MMNOC_MMU_TBU_HF1_CLK 42 +#define GCC_HLOS1_VOTE_MMNOC_MMU_TBU_SF0_CLK 43 +#define GCC_HLOS1_VOTE_MMU_TCU_CLK 44 +#define GCC_PCIE_0_AUX_CLK 45 +#define GCC_PCIE_0_AUX_CLK_SRC 46 +#define GCC_PCIE_0_CFG_AHB_CLK 47 +#define GCC_PCIE_0_CLKREF_EN 48 +#define GCC_PCIE_0_MSTR_AXI_CLK 49 +#define GCC_PCIE_0_PHY_RCHNG_CLK 50 +#define GCC_PCIE_0_PHY_RCHNG_CLK_SRC 51 +#define GCC_PCIE_0_PIPE_CLK 52 +#define GCC_PCIE_0_PIPE_CLK_SRC 53 +#define GCC_PCIE_0_PIPE_DIV2_CLK 54 +#define GCC_PCIE_0_PIPE_DIV2_CLK_SRC 55 +#define GCC_PCIE_0_SLV_AXI_CLK 56 +#define GCC_PCIE_0_SLV_Q2A_AXI_CLK 57 +#define GCC_PDM2_CLK 58 +#define GCC_PDM2_CLK_SRC 59 +#define GCC_PDM_AHB_CLK 60 +#define GCC_PDM_XO4_CLK 61 +#define GCC_QMIP_CAMERA_NRT_AHB_CLK 62 +#define GCC_QMIP_CAMERA_RT_AHB_CLK 63 +#define GCC_QMIP_DISP_AHB_CLK 64 +#define GCC_QMIP_GPU_AHB_CLK 65 +#define GCC_QMIP_PCIE_AHB_CLK 66 +#define GCC_QMIP_VIDEO_VCODEC_AHB_CLK 67 +#define GCC_QUPV3_WRAP0_CORE_2X_CLK 68 +#define GCC_QUPV3_WRAP0_CORE_CLK 69 +#define GCC_QUPV3_WRAP0_S0_CLK 70 +#define GCC_QUPV3_WRAP0_S0_CLK_SRC 71 +#define GCC_QUPV3_WRAP0_S1_CLK 72 +#define GCC_QUPV3_WRAP0_S1_CLK_SRC 73 +#define GCC_QUPV3_WRAP0_S2_CLK 74 +#define GCC_QUPV3_WRAP0_S2_CLK_SRC 75 +#define GCC_QUPV3_WRAP0_S3_CLK 76 +#define GCC_QUPV3_WRAP0_S3_CLK_SRC 77 +#define GCC_QUPV3_WRAP0_S4_CLK 78 +#define GCC_QUPV3_WRAP0_S4_CLK_SRC 79 +#define GCC_QUPV3_WRAP1_CORE_2X_CLK 80 +#define GCC_QUPV3_WRAP1_CORE_CLK 81 +#define GCC_QUPV3_WRAP1_S0_CLK 82 +#define GCC_QUPV3_WRAP1_S0_CLK_SRC 83 +#define GCC_QUPV3_WRAP1_S1_CLK 84 +#define GCC_QUPV3_WRAP1_S1_CLK_SRC 85 +#define GCC_QUPV3_WRAP1_S2_CLK 86 +#define GCC_QUPV3_WRAP1_S2_CLK_SRC 87 +#define GCC_QUPV3_WRAP1_S3_CLK 88 +#define GCC_QUPV3_WRAP1_S3_CLK_SRC 89 +#define GCC_QUPV3_WRAP1_S4_CLK 90 +#define GCC_QUPV3_WRAP1_S4_CLK_SRC 91 +#define GCC_QUPV3_WRAP_0_M_AHB_CLK 92 +#define GCC_QUPV3_WRAP_0_S_AHB_CLK 93 +#define GCC_QUPV3_WRAP_1_M_AHB_CLK 94 +#define GCC_QUPV3_WRAP_1_S_AHB_CLK 95 +#define GCC_SDCC1_AHB_CLK 96 +#define GCC_SDCC1_APPS_CLK 97 +#define GCC_SDCC1_APPS_CLK_SRC 98 +#define GCC_SDCC1_ICE_CORE_CLK 99 +#define GCC_SDCC1_ICE_CORE_CLK_SRC 100 +#define GCC_SDCC2_AHB_CLK 101 +#define GCC_SDCC2_APPS_CLK 102 +#define GCC_SDCC2_APPS_CLK_SRC 103 +#define GCC_UFS_0_CLKREF_EN 104 +#define GCC_UFS_PAD_CLKREF_EN 105 +#define GCC_UFS_PHY_AHB_CLK 106 +#define GCC_UFS_PHY_AXI_CLK 107 +#define GCC_UFS_PHY_AXI_CLK_SRC 108 +#define GCC_UFS_PHY_AXI_HW_CTL_CLK 109 +#define GCC_UFS_PHY_ICE_CORE_CLK 110 +#define GCC_UFS_PHY_ICE_CORE_CLK_SRC 111 +#define GCC_UFS_PHY_ICE_CORE_HW_CTL_CLK 112 +#define GCC_UFS_PHY_PHY_AUX_CLK 113 +#define GCC_UFS_PHY_PHY_AUX_CLK_SRC 114 +#define GCC_UFS_PHY_PHY_AUX_HW_CTL_CLK 115 +#define GCC_UFS_PHY_RX_SYMBOL_0_CLK 116 +#define GCC_UFS_PHY_RX_SYMBOL_0_CLK_SRC 117 +#define GCC_UFS_PHY_RX_SYMBOL_1_CLK 118 +#define GCC_UFS_PHY_RX_SYMBOL_1_CLK_SRC 119 +#define GCC_UFS_PHY_TX_SYMBOL_0_CLK 120 +#define GCC_UFS_PHY_TX_SYMBOL_0_CLK_SRC 121 +#define GCC_UFS_PHY_UNIPRO_CORE_CLK 122 +#define GCC_UFS_PHY_UNIPRO_CORE_CLK_SRC 123 +#define GCC_UFS_PHY_UNIPRO_CORE_HW_CTL_CLK 124 +#define GCC_USB30_PRIM_MASTER_CLK 125 +#define GCC_USB30_PRIM_MASTER_CLK_SRC 126 +#define GCC_USB30_PRIM_MOCK_UTMI_CLK 127 +#define GCC_USB30_PRIM_MOCK_UTMI_CLK_SRC 128 +#define GCC_USB30_PRIM_MOCK_UTMI_POSTDIV_CLK_SRC 129 +#define GCC_USB30_PRIM_SLEEP_CLK 130 +#define GCC_USB3_0_CLKREF_EN 131 +#define GCC_USB3_PRIM_PHY_AUX_CLK 132 +#define GCC_USB3_PRIM_PHY_AUX_CLK_SRC 133 +#define GCC_USB3_PRIM_PHY_COM_AUX_CLK 134 +#define GCC_USB3_PRIM_PHY_PIPE_CLK 135 +#define GCC_USB3_PRIM_PHY_PIPE_CLK_SRC 136 +#define GCC_VCODEC0_AXI_CLK 137 +#define GCC_VENUS_CTL_AXI_CLK 138 +#define GCC_VIDEO_AHB_CLK 139 +#define GCC_VIDEO_THROTTLE_CORE_CLK 140 +#define GCC_VIDEO_VCODEC0_SYS_CLK 141 +#define GCC_VIDEO_VENUS_CLK_SRC 142 +#define GCC_VIDEO_VENUS_CTL_CLK 143 +#define GCC_VIDEO_XO_CLK 144 + +/* GCC power domains */ +#define GCC_PCIE_0_GDSC 0 +#define GCC_UFS_PHY_GDSC 1 +#define GCC_USB30_PRIM_GDSC 2 +#define GCC_VCODEC0_GDSC 3 +#define GCC_VENUS_GDSC 4 + +/* GCC resets */ +#define GCC_CAMERA_BCR 0 +#define GCC_DISPLAY_BCR 1 +#define GCC_GPU_BCR 2 +#define GCC_PCIE_0_BCR 3 +#define GCC_PCIE_0_LINK_DOWN_BCR 4 +#define GCC_PCIE_0_NOCSR_COM_PHY_BCR 5 +#define GCC_PCIE_0_PHY_BCR 6 +#define GCC_PCIE_0_PHY_NOCSR_COM_PHY_BCR 7 +#define GCC_PCIE_PHY_BCR 8 +#define GCC_PCIE_PHY_CFG_AHB_BCR 9 +#define GCC_PCIE_PHY_COM_BCR 10 +#define GCC_PDM_BCR 11 +#define GCC_QUPV3_WRAPPER_0_BCR 12 +#define GCC_QUPV3_WRAPPER_1_BCR 13 +#define GCC_QUSB2PHY_PRIM_BCR 14 +#define GCC_QUSB2PHY_SEC_BCR 15 +#define GCC_SDCC1_BCR 16 +#define GCC_SDCC2_BCR 17 +#define GCC_UFS_PHY_BCR 18 +#define GCC_USB30_PRIM_BCR 19 +#define GCC_USB3_DP_PHY_PRIM_BCR 20 +#define GCC_USB3_DP_PHY_SEC_BCR 21 +#define GCC_USB3_PHY_PRIM_BCR 22 +#define GCC_USB3_PHY_SEC_BCR 23 +#define GCC_USB3PHY_PHY_PRIM_BCR 24 +#define GCC_USB3PHY_PHY_SEC_BCR 25 +#define GCC_VCODEC0_BCR 26 +#define GCC_VENUS_BCR 27 +#define GCC_VIDEO_BCR 28 +#define GCC_VIDEO_VENUS_BCR 29 +#define GCC_VENUS_CTL_AXI_CLK_ARES 30 +#define GCC_VIDEO_VENUS_CTL_CLK_ARES 31 + +#endif -- cgit v1.2.3-59-g8ed1b From c32c4ef98baca6dfedbddace1e0bbcae0ca65050 Mon Sep 17 00:00:00 2001 From: Ajit Pandey Date: Sat, 9 Sep 2023 18:04:31 +0530 Subject: clk: qcom: Add GCC driver support for SM4450 Add Global Clock Controller (GCC) support for SM4450 platform. Signed-off-by: Ajit Pandey Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20230909123431.1725728-5-quic_ajipan@quicinc.com Signed-off-by: Bjorn Andersson --- drivers/clk/qcom/Kconfig | 9 + drivers/clk/qcom/Makefile | 1 + drivers/clk/qcom/gcc-sm4450.c | 2897 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 2907 insertions(+) create mode 100644 drivers/clk/qcom/gcc-sm4450.c diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig index 865db5202e4c..0f7aa00ea33d 100644 --- a/drivers/clk/qcom/Kconfig +++ b/drivers/clk/qcom/Kconfig @@ -834,6 +834,15 @@ config SM_DISPCC_8550 Say Y if you want to support display devices and functionality such as splash screen. +config SM_GCC_4450 + tristate "SM4450 Global Clock Controller" + depends on ARM64 || COMPILE_TEST + select QCOM_GDSC + help + Support for the global clock controller on SM4450 devices. + Say Y if you want to use peripheral devices such as UART, SPI, + I2C, USB, SD/UFS, PCIe, etc. + config SM_GCC_6115 tristate "SM6115 and SM4250 Global Clock Controller" depends on ARM64 || COMPILE_TEST diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile index 4790c8cca426..74d3a7724c91 100644 --- a/drivers/clk/qcom/Makefile +++ b/drivers/clk/qcom/Makefile @@ -109,6 +109,7 @@ obj-$(CONFIG_SM_DISPCC_6375) += dispcc-sm6375.o obj-$(CONFIG_SM_DISPCC_8250) += dispcc-sm8250.o obj-$(CONFIG_SM_DISPCC_8450) += dispcc-sm8450.o obj-$(CONFIG_SM_DISPCC_8550) += dispcc-sm8550.o +obj-$(CONFIG_SM_GCC_4450) += gcc-sm4450.o obj-$(CONFIG_SM_GCC_6115) += gcc-sm6115.o obj-$(CONFIG_SM_GCC_6125) += gcc-sm6125.o obj-$(CONFIG_SM_GCC_6350) += gcc-sm6350.o diff --git a/drivers/clk/qcom/gcc-sm4450.c b/drivers/clk/qcom/gcc-sm4450.c new file mode 100644 index 000000000000..41c6357d09bc --- /dev/null +++ b/drivers/clk/qcom/gcc-sm4450.c @@ -0,0 +1,2897 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2023, Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#include +#include +#include +#include + +#include + +#include "clk-alpha-pll.h" +#include "clk-branch.h" +#include "clk-rcg.h" +#include "clk-regmap.h" +#include "clk-regmap-divider.h" +#include "clk-regmap-mux.h" +#include "clk-regmap-phy-mux.h" +#include "gdsc.h" +#include "reset.h" + +enum { + DT_BI_TCXO, + DT_SLEEP_CLK, + DT_PCIE_0_PIPE_CLK, + DT_UFS_PHY_RX_SYMBOL_0_CLK, + DT_UFS_PHY_RX_SYMBOL_1_CLK, + DT_UFS_PHY_TX_SYMBOL_0_CLK, + DT_USB3_PHY_WRAPPER_GCC_USB30_PIPE_CLK, +}; + +enum { + P_BI_TCXO, + P_GCC_GPLL0_OUT_EVEN, + P_GCC_GPLL0_OUT_MAIN, + P_GCC_GPLL0_OUT_ODD, + P_GCC_GPLL1_OUT_MAIN, + P_GCC_GPLL3_OUT_MAIN, + P_GCC_GPLL4_OUT_MAIN, + P_GCC_GPLL9_OUT_MAIN, + P_GCC_GPLL10_OUT_MAIN, + P_SLEEP_CLK, + P_UFS_PHY_RX_SYMBOL_0_CLK, + P_UFS_PHY_RX_SYMBOL_1_CLK, + P_UFS_PHY_TX_SYMBOL_0_CLK, + P_USB3_PHY_WRAPPER_GCC_USB30_PIPE_CLK, +}; + +static const struct pll_vco lucid_evo_vco[] = { + { 249600000, 2020000000, 0 }, +}; + +static struct clk_alpha_pll gcc_gpll0 = { + .offset = 0x0, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_EVO], + .clkr = { + .enable_reg = 0x62018, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_gpll0", + .parent_data = &(const struct clk_parent_data) { + .index = DT_BI_TCXO, + }, + .num_parents = 1, + .ops = &clk_alpha_pll_fixed_lucid_evo_ops, + }, + }, +}; + +static const struct clk_div_table post_div_table_gcc_gpll0_out_even[] = { + { 0x1, 2 }, + { } +}; + +static struct clk_alpha_pll_postdiv gcc_gpll0_out_even = { + .offset = 0x0, + .post_div_shift = 10, + .post_div_table = post_div_table_gcc_gpll0_out_even, + .num_post_div = ARRAY_SIZE(post_div_table_gcc_gpll0_out_even), + .width = 4, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_EVO], + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_gpll0_out_even", + .parent_hws = (const struct clk_hw*[]) { + &gcc_gpll0.clkr.hw, + }, + .num_parents = 1, + .ops = &clk_alpha_pll_postdiv_lucid_evo_ops, + }, +}; + +static const struct clk_div_table post_div_table_gcc_gpll0_out_odd[] = { + { 0x2, 3 }, + { } +}; + +static struct clk_alpha_pll_postdiv gcc_gpll0_out_odd = { + .offset = 0x0, + .post_div_shift = 14, + .post_div_table = post_div_table_gcc_gpll0_out_odd, + .num_post_div = ARRAY_SIZE(post_div_table_gcc_gpll0_out_odd), + .width = 4, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_EVO], + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_gpll0_out_odd", + .parent_hws = (const struct clk_hw*[]) { + &gcc_gpll0.clkr.hw, + }, + .num_parents = 1, + .ops = &clk_alpha_pll_postdiv_lucid_evo_ops, + }, +}; + +static struct clk_alpha_pll gcc_gpll1 = { + .offset = 0x1000, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_EVO], + .clkr = { + .enable_reg = 0x62018, + .enable_mask = BIT(1), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_gpll1", + .parent_data = &(const struct clk_parent_data) { + .index = DT_BI_TCXO, + }, + .num_parents = 1, + .ops = &clk_alpha_pll_fixed_lucid_evo_ops, + }, + }, +}; + +static const struct alpha_pll_config gcc_gpll3_config = { + .l = 0x14, + .alpha = 0xd555, + .config_ctl_val = 0x20485699, + .config_ctl_hi_val = 0x00182261, + .config_ctl_hi1_val = 0x32aa299c, + .user_ctl_val = 0x00000000, + .user_ctl_hi_val = 0x00000805, +}; + +static struct clk_alpha_pll gcc_gpll3 = { + .offset = 0x3000, + .vco_table = lucid_evo_vco, + .num_vco = ARRAY_SIZE(lucid_evo_vco), + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_EVO], + .clkr = { + .enable_reg = 0x62018, + .enable_mask = BIT(3), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_gpll3", + .parent_data = &(const struct clk_parent_data) { + .index = DT_BI_TCXO, + }, + .num_parents = 1, + .ops = &clk_alpha_pll_lucid_evo_ops, + }, + }, +}; + +static struct clk_alpha_pll gcc_gpll4 = { + .offset = 0x4000, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_EVO], + .clkr = { + .enable_reg = 0x62018, + .enable_mask = BIT(4), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_gpll4", + .parent_data = &(const struct clk_parent_data) { + .index = DT_BI_TCXO, + }, + .num_parents = 1, + .ops = &clk_alpha_pll_fixed_lucid_evo_ops, + }, + }, +}; + +static struct clk_alpha_pll gcc_gpll9 = { + .offset = 0x9000, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_EVO], + .clkr = { + .enable_reg = 0x62018, + .enable_mask = BIT(9), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_gpll9", + .parent_data = &(const struct clk_parent_data) { + .index = DT_BI_TCXO, + }, + .num_parents = 1, + .ops = &clk_alpha_pll_fixed_lucid_evo_ops, + }, + }, +}; + +static struct clk_alpha_pll gcc_gpll10 = { + .offset = 0xa000, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_EVO], + .clkr = { + .enable_reg = 0x62018, + .enable_mask = BIT(10), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_gpll10", + .parent_data = &(const struct clk_parent_data) { + .index = DT_BI_TCXO, + }, + .num_parents = 1, + .ops = &clk_alpha_pll_fixed_lucid_evo_ops, + }, + }, +}; + +static const struct parent_map gcc_parent_map_0[] = { + { P_BI_TCXO, 0 }, + { P_GCC_GPLL0_OUT_MAIN, 1 }, + { P_GCC_GPLL0_OUT_EVEN, 6 }, +}; + +static const struct clk_parent_data gcc_parent_data_0[] = { + { .index = DT_BI_TCXO }, + { .hw = &gcc_gpll0.clkr.hw }, + { .hw = &gcc_gpll0_out_even.clkr.hw }, +}; + +static const struct parent_map gcc_parent_map_1[] = { + { P_BI_TCXO, 0 }, + { P_GCC_GPLL0_OUT_MAIN, 1 }, + { P_SLEEP_CLK, 5 }, + { P_GCC_GPLL0_OUT_EVEN, 6 }, +}; + +static const struct clk_parent_data gcc_parent_data_1[] = { + { .index = DT_BI_TCXO }, + { .hw = &gcc_gpll0.clkr.hw }, + { .index = DT_SLEEP_CLK }, + { .hw = &gcc_gpll0_out_even.clkr.hw }, +}; + +static const struct parent_map gcc_parent_map_2[] = { + { P_BI_TCXO, 0 }, + { P_GCC_GPLL0_OUT_MAIN, 1 }, + { P_GCC_GPLL1_OUT_MAIN, 4 }, + { P_GCC_GPLL4_OUT_MAIN, 5 }, + { P_GCC_GPLL0_OUT_EVEN, 6 }, +}; + +static const struct clk_parent_data gcc_parent_data_2[] = { + { .index = DT_BI_TCXO }, + { .hw = &gcc_gpll0.clkr.hw }, + { .hw = &gcc_gpll1.clkr.hw }, + { .hw = &gcc_gpll4.clkr.hw }, + { .hw = &gcc_gpll0_out_even.clkr.hw }, +}; + +static const struct parent_map gcc_parent_map_3[] = { + { P_BI_TCXO, 0 }, + { P_SLEEP_CLK, 5 }, +}; + +static const struct clk_parent_data gcc_parent_data_3[] = { + { .index = DT_BI_TCXO }, + { .index = DT_SLEEP_CLK }, +}; + +static const struct parent_map gcc_parent_map_4[] = { + { P_BI_TCXO, 0 }, + { P_GCC_GPLL0_OUT_MAIN, 1 }, + { P_GCC_GPLL0_OUT_ODD, 2 }, + { P_GCC_GPLL10_OUT_MAIN, 3 }, + { P_GCC_GPLL0_OUT_EVEN, 6 }, +}; + +static const struct clk_parent_data gcc_parent_data_4[] = { + { .index = DT_BI_TCXO }, + { .hw = &gcc_gpll0.clkr.hw }, + { .hw = &gcc_gpll0_out_odd.clkr.hw }, + { .hw = &gcc_gpll10.clkr.hw }, + { .hw = &gcc_gpll0_out_even.clkr.hw }, +}; + +static const struct parent_map gcc_parent_map_5[] = { + { P_BI_TCXO, 0 }, +}; + +static const struct clk_parent_data gcc_parent_data_5[] = { + { .index = DT_BI_TCXO }, +}; + +static const struct parent_map gcc_parent_map_6[] = { + { P_BI_TCXO, 0 }, + { P_GCC_GPLL0_OUT_MAIN, 1 }, + { P_GCC_GPLL9_OUT_MAIN, 2 }, + { P_GCC_GPLL4_OUT_MAIN, 5 }, + { P_GCC_GPLL0_OUT_EVEN, 6 }, +}; + +static const struct clk_parent_data gcc_parent_data_6[] = { + { .index = DT_BI_TCXO }, + { .hw = &gcc_gpll0.clkr.hw }, + { .hw = &gcc_gpll9.clkr.hw }, + { .hw = &gcc_gpll4.clkr.hw }, + { .hw = &gcc_gpll0_out_even.clkr.hw }, +}; + +static const struct parent_map gcc_parent_map_7[] = { + { P_UFS_PHY_RX_SYMBOL_0_CLK, 0 }, + { P_BI_TCXO, 2 }, +}; + +static const struct clk_parent_data gcc_parent_data_7[] = { + { .index = DT_UFS_PHY_RX_SYMBOL_0_CLK }, + { .index = DT_BI_TCXO }, +}; + +static const struct parent_map gcc_parent_map_8[] = { + { P_UFS_PHY_RX_SYMBOL_1_CLK, 0 }, + { P_BI_TCXO, 2 }, +}; + +static const struct clk_parent_data gcc_parent_data_8[] = { + { .index = DT_UFS_PHY_RX_SYMBOL_1_CLK }, + { .index = DT_BI_TCXO }, +}; + +static const struct parent_map gcc_parent_map_9[] = { + { P_UFS_PHY_TX_SYMBOL_0_CLK, 0 }, + { P_BI_TCXO, 2 }, +}; + +static const struct clk_parent_data gcc_parent_data_9[] = { + { .index = DT_UFS_PHY_TX_SYMBOL_0_CLK }, + { .index = DT_BI_TCXO }, +}; + +static const struct parent_map gcc_parent_map_10[] = { + { P_USB3_PHY_WRAPPER_GCC_USB30_PIPE_CLK, 0 }, + { P_BI_TCXO, 2 }, +}; + +static const struct clk_parent_data gcc_parent_data_10[] = { + { .index = DT_USB3_PHY_WRAPPER_GCC_USB30_PIPE_CLK }, + { .index = DT_BI_TCXO }, +}; + +static const struct parent_map gcc_parent_map_11[] = { + { P_BI_TCXO, 0 }, + { P_GCC_GPLL0_OUT_MAIN, 1 }, + { P_GCC_GPLL3_OUT_MAIN, 5 }, +}; + +static const struct clk_parent_data gcc_parent_data_11[] = { + { .index = DT_BI_TCXO }, + { .hw = &gcc_gpll0.clkr.hw }, + { .hw = &gcc_gpll3.clkr.hw }, +}; + +static struct clk_regmap_phy_mux gcc_pcie_0_pipe_clk_src = { + .reg = 0x7b060, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_0_pipe_clk_src", + .parent_data = &(const struct clk_parent_data) { + .index = DT_PCIE_0_PIPE_CLK, + }, + .num_parents = 1, + .ops = &clk_regmap_phy_mux_ops, + }, + }, +}; + +static struct clk_regmap_mux gcc_ufs_phy_rx_symbol_0_clk_src = { + .reg = 0x87060, + .shift = 0, + .width = 2, + .parent_map = gcc_parent_map_7, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "gcc_ufs_phy_rx_symbol_0_clk_src", + .parent_data = gcc_parent_data_7, + .num_parents = ARRAY_SIZE(gcc_parent_data_7), + .ops = &clk_regmap_mux_closest_ops, + }, + }, +}; + +static struct clk_regmap_mux gcc_ufs_phy_rx_symbol_1_clk_src = { + .reg = 0x870d0, + .shift = 0, + .width = 2, + .parent_map = gcc_parent_map_8, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "gcc_ufs_phy_rx_symbol_1_clk_src", + .parent_data = gcc_parent_data_8, + .num_parents = ARRAY_SIZE(gcc_parent_data_8), + .ops = &clk_regmap_mux_closest_ops, + }, + }, +}; + +static struct clk_regmap_mux gcc_ufs_phy_tx_symbol_0_clk_src = { + .reg = 0x87050, + .shift = 0, + .width = 2, + .parent_map = gcc_parent_map_9, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "gcc_ufs_phy_tx_symbol_0_clk_src", + .parent_data = gcc_parent_data_9, + .num_parents = ARRAY_SIZE(gcc_parent_data_9), + .ops = &clk_regmap_mux_closest_ops, + }, + }, +}; + +static struct clk_regmap_mux gcc_usb3_prim_phy_pipe_clk_src = { + .reg = 0x49068, + .shift = 0, + .width = 2, + .parent_map = gcc_parent_map_10, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb3_prim_phy_pipe_clk_src", + .parent_data = gcc_parent_data_10, + .num_parents = ARRAY_SIZE(gcc_parent_data_10), + .ops = &clk_regmap_mux_closest_ops, + }, + }, +}; + +static const struct freq_tbl ftbl_gcc_gp1_clk_src[] = { + F(50000000, P_GCC_GPLL0_OUT_EVEN, 6, 0, 0), + F(100000000, P_GCC_GPLL0_OUT_MAIN, 6, 0, 0), + F(200000000, P_GCC_GPLL0_OUT_MAIN, 3, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_gp1_clk_src = { + .cmd_rcgr = 0x74004, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_1, + .freq_tbl = ftbl_gcc_gp1_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_gp1_clk_src", + .parent_data = gcc_parent_data_1, + .num_parents = ARRAY_SIZE(gcc_parent_data_1), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 gcc_gp2_clk_src = { + .cmd_rcgr = 0x75004, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_1, + .freq_tbl = ftbl_gcc_gp1_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_gp2_clk_src", + .parent_data = gcc_parent_data_1, + .num_parents = ARRAY_SIZE(gcc_parent_data_1), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 gcc_gp3_clk_src = { + .cmd_rcgr = 0x76004, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_1, + .freq_tbl = ftbl_gcc_gp1_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_gp3_clk_src", + .parent_data = gcc_parent_data_1, + .num_parents = ARRAY_SIZE(gcc_parent_data_1), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_pcie_0_aux_clk_src[] = { + F(9600000, P_BI_TCXO, 2, 0, 0), + F(19200000, P_BI_TCXO, 1, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_pcie_0_aux_clk_src = { + .cmd_rcgr = 0x7b064, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_3, + .freq_tbl = ftbl_gcc_pcie_0_aux_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_0_aux_clk_src", + .parent_data = gcc_parent_data_3, + .num_parents = ARRAY_SIZE(gcc_parent_data_3), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_pcie_0_phy_rchng_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + F(100000000, P_GCC_GPLL0_OUT_MAIN, 6, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_pcie_0_phy_rchng_clk_src = { + .cmd_rcgr = 0x7b048, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_pcie_0_phy_rchng_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_0_phy_rchng_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = ARRAY_SIZE(gcc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_pdm2_clk_src[] = { + F(60000000, P_GCC_GPLL0_OUT_MAIN, 10, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_pdm2_clk_src = { + .cmd_rcgr = 0x43010, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_pdm2_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_pdm2_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = ARRAY_SIZE(gcc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_qupv3_wrap0_s0_clk_src[] = { + F(7372800, P_GCC_GPLL0_OUT_EVEN, 1, 384, 15625), + F(14745600, P_GCC_GPLL0_OUT_EVEN, 1, 768, 15625), + F(19200000, P_BI_TCXO, 1, 0, 0), + 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(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), + F(96000000, P_GCC_GPLL0_OUT_EVEN, 1, 8, 25), + F(100000000, P_GCC_GPLL0_OUT_MAIN, 6, 0, 0), + F(102400000, P_GCC_GPLL0_OUT_EVEN, 1, 128, 375), + F(112000000, P_GCC_GPLL0_OUT_EVEN, 1, 28, 75), + F(117964800, P_GCC_GPLL0_OUT_EVEN, 1, 6144, 15625), + F(120000000, P_GCC_GPLL0_OUT_EVEN, 2.5, 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_0, + .num_parents = ARRAY_SIZE(gcc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, +}; + +static struct clk_rcg2 gcc_qupv3_wrap0_s0_clk_src = { + .cmd_rcgr = 0x27014, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, + .clkr.hw.init = &gcc_qupv3_wrap0_s0_clk_src_init, +}; + +static const struct freq_tbl ftbl_gcc_qupv3_wrap0_s1_clk_src[] = { + F(7372800, P_GCC_GPLL0_OUT_EVEN, 1, 384, 15625), + F(14745600, P_GCC_GPLL0_OUT_EVEN, 1, 768, 15625), + F(19200000, P_BI_TCXO, 1, 0, 0), + 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(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), + F(96000000, P_GCC_GPLL0_OUT_EVEN, 1, 8, 25), + F(100000000, P_GCC_GPLL0_OUT_MAIN, 6, 0, 0), + { } +}; + +static struct clk_init_data gcc_qupv3_wrap0_s1_clk_src_init = { + .name = "gcc_qupv3_wrap0_s1_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = ARRAY_SIZE(gcc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, +}; + +static struct clk_rcg2 gcc_qupv3_wrap0_s1_clk_src = { + .cmd_rcgr = 0x27148, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s1_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_0, + .num_parents = ARRAY_SIZE(gcc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, +}; + +static struct clk_rcg2 gcc_qupv3_wrap0_s2_clk_src = { + .cmd_rcgr = 0x2727c, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s1_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_0, + .num_parents = ARRAY_SIZE(gcc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, +}; + +static struct clk_rcg2 gcc_qupv3_wrap0_s3_clk_src = { + .cmd_rcgr = 0x273b0, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s1_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_0, + .num_parents = ARRAY_SIZE(gcc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, +}; + +static struct clk_rcg2 gcc_qupv3_wrap0_s4_clk_src = { + .cmd_rcgr = 0x274e4, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s1_clk_src, + .clkr.hw.init = &gcc_qupv3_wrap0_s4_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_0, + .num_parents = ARRAY_SIZE(gcc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, +}; + +static struct clk_rcg2 gcc_qupv3_wrap1_s0_clk_src = { + .cmd_rcgr = 0x28014, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .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_0, + .num_parents = ARRAY_SIZE(gcc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, +}; + +static struct clk_rcg2 gcc_qupv3_wrap1_s1_clk_src = { + .cmd_rcgr = 0x28148, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s1_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_0, + .num_parents = ARRAY_SIZE(gcc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, +}; + +static struct clk_rcg2 gcc_qupv3_wrap1_s2_clk_src = { + .cmd_rcgr = 0x2827c, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s1_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_0, + .num_parents = ARRAY_SIZE(gcc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, +}; + +static struct clk_rcg2 gcc_qupv3_wrap1_s3_clk_src = { + .cmd_rcgr = 0x283b0, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s1_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_0, + .num_parents = ARRAY_SIZE(gcc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, +}; + +static struct clk_rcg2 gcc_qupv3_wrap1_s4_clk_src = { + .cmd_rcgr = 0x284e4, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s1_clk_src, + .clkr.hw.init = &gcc_qupv3_wrap1_s4_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_GCC_GPLL0_OUT_EVEN, 5, 1, 3), + F(25000000, P_GCC_GPLL0_OUT_EVEN, 12, 0, 0), + F(50000000, P_GCC_GPLL0_OUT_EVEN, 6, 0, 0), + F(100000000, P_GCC_GPLL0_OUT_ODD, 2, 0, 0), + F(192000000, P_GCC_GPLL10_OUT_MAIN, 2, 0, 0), + F(384000000, P_GCC_GPLL10_OUT_MAIN, 1, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_sdcc1_apps_clk_src = { + .cmd_rcgr = 0xb3010, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_parent_map_4, + .freq_tbl = ftbl_gcc_sdcc1_apps_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_sdcc1_apps_clk_src", + .parent_data = gcc_parent_data_4, + .num_parents = ARRAY_SIZE(gcc_parent_data_4), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_floor_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_sdcc1_ice_core_clk_src[] = { + F(100000000, P_GCC_GPLL0_OUT_ODD, 2, 0, 0), + F(150000000, P_GCC_GPLL0_OUT_EVEN, 2, 0, 0), + F(300000000, P_GCC_GPLL0_OUT_EVEN, 1, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_sdcc1_ice_core_clk_src = { + .cmd_rcgr = 0xb3030, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_4, + .freq_tbl = ftbl_gcc_sdcc1_ice_core_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_sdcc1_ice_core_clk_src", + .parent_data = gcc_parent_data_4, + .num_parents = ARRAY_SIZE(gcc_parent_data_4), + .flags = CLK_SET_RATE_PARENT, + .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(25000000, P_GCC_GPLL0_OUT_EVEN, 12, 0, 0), + F(50000000, P_GCC_GPLL0_OUT_EVEN, 6, 0, 0), + F(100000000, P_GCC_GPLL0_OUT_EVEN, 3, 0, 0), + F(202000000, P_GCC_GPLL9_OUT_MAIN, 4, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_sdcc2_apps_clk_src = { + .cmd_rcgr = 0x24014, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_parent_map_6, + .freq_tbl = ftbl_gcc_sdcc2_apps_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_sdcc2_apps_clk_src", + .parent_data = gcc_parent_data_6, + .num_parents = ARRAY_SIZE(gcc_parent_data_6), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_floor_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_ufs_phy_axi_clk_src[] = { + F(25000000, P_GCC_GPLL0_OUT_EVEN, 12, 0, 0), + F(75000000, P_GCC_GPLL0_OUT_EVEN, 4, 0, 0), + F(150000000, P_GCC_GPLL0_OUT_MAIN, 4, 0, 0), + F(300000000, P_GCC_GPLL0_OUT_MAIN, 2, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_ufs_phy_axi_clk_src = { + .cmd_rcgr = 0x8702c, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_ufs_phy_axi_clk_src, + .clkr.hw.init = &(const 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), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_ufs_phy_ice_core_clk_src[] = { + F(100000000, P_GCC_GPLL0_OUT_MAIN, 6, 0, 0), + F(200000000, P_GCC_GPLL0_OUT_MAIN, 3, 0, 0), + F(403000000, P_GCC_GPLL4_OUT_MAIN, 2, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_ufs_phy_ice_core_clk_src = { + .cmd_rcgr = 0x87074, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_2, + .freq_tbl = ftbl_gcc_ufs_phy_ice_core_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_ufs_phy_ice_core_clk_src", + .parent_data = gcc_parent_data_2, + .num_parents = ARRAY_SIZE(gcc_parent_data_2), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 gcc_ufs_phy_phy_aux_clk_src = { + .cmd_rcgr = 0x870a8, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_5, + .freq_tbl = ftbl_gcc_pcie_0_aux_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_ufs_phy_phy_aux_clk_src", + .parent_data = gcc_parent_data_5, + .num_parents = ARRAY_SIZE(gcc_parent_data_5), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_ufs_phy_unipro_core_clk_src[] = { + F(75000000, P_GCC_GPLL0_OUT_EVEN, 4, 0, 0), + F(150000000, P_GCC_GPLL0_OUT_MAIN, 4, 0, 0), + F(300000000, P_GCC_GPLL0_OUT_MAIN, 2, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_ufs_phy_unipro_core_clk_src = { + .cmd_rcgr = 0x8708c, + .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 = &(const 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), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_usb30_prim_master_clk_src[] = { + F(66666667, P_GCC_GPLL0_OUT_EVEN, 4.5, 0, 0), + F(133333333, P_GCC_GPLL0_OUT_MAIN, 4.5, 0, 0), + F(200000000, P_GCC_GPLL0_OUT_MAIN, 3, 0, 0), + F(240000000, P_GCC_GPLL0_OUT_MAIN, 2.5, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_usb30_prim_master_clk_src = { + .cmd_rcgr = 0x49028, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_usb30_prim_master_clk_src, + .clkr.hw.init = &(const 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), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_usb30_prim_mock_utmi_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_usb30_prim_mock_utmi_clk_src = { + .cmd_rcgr = 0x49040, + .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 = &(const 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), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 gcc_usb3_prim_phy_aux_clk_src = { + .cmd_rcgr = 0x4906c, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_3, + .freq_tbl = ftbl_gcc_usb30_prim_mock_utmi_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_usb3_prim_phy_aux_clk_src", + .parent_data = gcc_parent_data_3, + .num_parents = ARRAY_SIZE(gcc_parent_data_3), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_video_venus_clk_src[] = { + F(133333333, P_GCC_GPLL3_OUT_MAIN, 3, 0, 0), + F(240000000, P_GCC_GPLL3_OUT_MAIN, 2, 0, 0), + F(365000000, P_GCC_GPLL3_OUT_MAIN, 2, 0, 0), + F(384000000, P_GCC_GPLL3_OUT_MAIN, 2, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_video_venus_clk_src = { + .cmd_rcgr = 0xb6004, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_11, + .freq_tbl = ftbl_gcc_video_venus_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_video_venus_clk_src", + .parent_data = gcc_parent_data_11, + .num_parents = ARRAY_SIZE(gcc_parent_data_11), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_regmap_div gcc_pcie_0_pipe_div2_clk_src = { + .reg = 0x7b084, + .shift = 0, + .width = 4, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_0_pipe_div2_clk_src", + .parent_hws = (const struct clk_hw*[]) { + &gcc_pcie_0_pipe_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_regmap_div_ro_ops, + }, +}; + +static struct clk_regmap_div gcc_usb30_prim_mock_utmi_postdiv_clk_src = { + .reg = 0x49058, + .shift = 0, + .width = 4, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_usb30_prim_mock_utmi_postdiv_clk_src", + .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_regmap_div_ro_ops, + }, +}; + +static struct clk_branch gcc_aggre_noc_pcie_0_axi_clk = { + .halt_reg = 0x7b08c, + .halt_check = BRANCH_HALT_SKIP, + .hwcg_reg = 0x7b08c, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x62000, + .enable_mask = BIT(12), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_aggre_noc_pcie_0_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_aggre_ufs_phy_axi_clk = { + .halt_reg = 0x870d4, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x870d4, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x870d4, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_aggre_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_aggre_ufs_phy_axi_hw_ctl_clk = { + .halt_reg = 0x870d4, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x870d4, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x870d4, + .enable_mask = BIT(1), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_aggre_ufs_phy_axi_hw_ctl_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_aggre_usb3_prim_axi_clk = { + .halt_reg = 0x49088, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x49088, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x49088, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_aggre_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_boot_rom_ahb_clk = { + .halt_reg = 0x48004, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x48004, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x62000, + .enable_mask = BIT(10), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_boot_rom_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camera_hf_axi_clk = { + .halt_reg = 0x36010, + .halt_check = BRANCH_HALT_SKIP, + .hwcg_reg = 0x36010, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x36010, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_camera_hf_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camera_sf_axi_clk = { + .halt_reg = 0x36014, + .halt_check = BRANCH_HALT_SKIP, + .hwcg_reg = 0x36014, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x36014, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_camera_sf_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_cfg_noc_pcie_anoc_ahb_clk = { + .halt_reg = 0x20030, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x20030, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x62000, + .enable_mask = BIT(20), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_cfg_noc_pcie_anoc_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_cfg_noc_usb3_prim_axi_clk = { + .halt_reg = 0x49084, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x49084, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x49084, + .enable_mask = BIT(0), + .hw.init = &(const 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_ddrss_gpu_axi_clk = { + .halt_reg = 0x81154, + .halt_check = BRANCH_HALT_SKIP, + .hwcg_reg = 0x81154, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x81154, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_ddrss_gpu_axi_clk", + .ops = &clk_branch2_aon_ops, + }, + }, +}; + +static struct clk_branch gcc_ddrss_pcie_sf_tbu_clk = { + .halt_reg = 0x7b090, + .halt_check = BRANCH_HALT_SKIP, + .hwcg_reg = 0x7b090, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x62000, + .enable_mask = BIT(19), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_ddrss_pcie_sf_tbu_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_disp_hf_axi_clk = { + .halt_reg = 0x3700c, + .halt_check = BRANCH_HALT_SKIP, + .hwcg_reg = 0x3700c, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x3700c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_disp_hf_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_eusb3_0_clkref_en = { + .halt_reg = 0x9c00c, + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x9c00c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_eusb3_0_clkref_en", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_gp1_clk = { + .halt_reg = 0x74000, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x74000, + .enable_mask = BIT(0), + .hw.init = &(const 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 = 0x75000, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x75000, + .enable_mask = BIT(0), + .hw.init = &(const 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 = 0x76000, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x76000, + .enable_mask = BIT(0), + .hw.init = &(const 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_gpll0_clk_src = { + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x62000, + .enable_mask = BIT(15), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_gpu_gpll0_clk_src", + .parent_hws = (const struct clk_hw*[]) { + &gcc_gpll0.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_gpu_gpll0_div_clk_src = { + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x62000, + .enable_mask = BIT(16), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_gpu_gpll0_div_clk_src", + .parent_hws = (const struct clk_hw*[]) { + &gcc_gpll0_out_even.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_gpu_memnoc_gfx_clk = { + .halt_reg = 0x81010, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x81010, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x81010, + .enable_mask = BIT(0), + .hw.init = &(const 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 = 0x81018, + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x81018, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_gpu_snoc_dvm_gfx_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_hlos1_vote_aggre_noc_mmu_audio_tbu_clk = { + .halt_reg = 0x8d004, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x8d004, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data){ + .name = "gcc_hlos1_vote_aggre_noc_mmu_audio_tbu_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_hlos1_vote_aggre_noc_mmu_pcie_tbu_clk = { + .halt_reg = 0x8d010, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x8d010, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data){ + .name = "gcc_hlos1_vote_aggre_noc_mmu_pcie_tbu_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_hlos1_vote_aggre_noc_mmu_tbu1_clk = { + .halt_reg = 0x8d008, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x8d008, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data){ + .name = "gcc_hlos1_vote_aggre_noc_mmu_tbu1_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_hlos1_vote_aggre_noc_mmu_tbu2_clk = { + .halt_reg = 0x8d00c, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x8d00c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data){ + .name = "gcc_hlos1_vote_aggre_noc_mmu_tbu2_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_hlos1_vote_mmnoc_mmu_tbu_hf0_clk = { + .halt_reg = 0x8d018, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x8d018, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data){ + .name = "gcc_hlos1_vote_mmnoc_mmu_tbu_hf0_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_hlos1_vote_mmnoc_mmu_tbu_hf1_clk = { + .halt_reg = 0x8d01c, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x8d01c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data){ + .name = "gcc_hlos1_vote_mmnoc_mmu_tbu_hf1_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_hlos1_vote_mmnoc_mmu_tbu_sf0_clk = { + .halt_reg = 0x8d014, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x8d014, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data){ + .name = "gcc_hlos1_vote_mmnoc_mmu_tbu_sf0_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_hlos1_vote_mmu_tcu_clk = { + .halt_reg = 0x8d02c, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x8d02c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data){ + .name = "gcc_hlos1_vote_mmu_tcu_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_0_aux_clk = { + .halt_reg = 0x7b034, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x62008, + .enable_mask = BIT(3), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_0_aux_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_pcie_0_aux_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_0_cfg_ahb_clk = { + .halt_reg = 0x7b030, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x7b030, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x62008, + .enable_mask = BIT(2), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_0_cfg_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_0_clkref_en = { + .halt_reg = 0x9c004, + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x9c004, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_0_clkref_en", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_0_mstr_axi_clk = { + .halt_reg = 0x7b028, + .halt_check = BRANCH_HALT_SKIP, + .clkr = { + .enable_reg = 0x62008, + .enable_mask = BIT(1), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_0_mstr_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_0_phy_rchng_clk = { + .halt_reg = 0x7b044, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x62000, + .enable_mask = BIT(22), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_0_phy_rchng_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_pcie_0_phy_rchng_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_0_pipe_clk = { + .halt_reg = 0x7b03c, + .halt_check = BRANCH_HALT_SKIP, + .clkr = { + .enable_reg = 0x62008, + .enable_mask = BIT(4), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_0_pipe_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_pcie_0_pipe_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_0_pipe_div2_clk = { + .halt_reg = 0x7b094, + .halt_check = BRANCH_HALT_SKIP, + .clkr = { + .enable_reg = 0x62010, + .enable_mask = BIT(26), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_0_pipe_div2_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_pcie_0_pipe_div2_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_0_slv_axi_clk = { + .halt_reg = 0x7b020, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x7b020, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x62008, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_0_slv_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_0_slv_q2a_axi_clk = { + .halt_reg = 0x7b01c, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x62008, + .enable_mask = BIT(5), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_0_slv_q2a_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pdm2_clk = { + .halt_reg = 0x4300c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x4300c, + .enable_mask = BIT(0), + .hw.init = &(const 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 = 0x43004, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x43004, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x43004, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pdm_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pdm_xo4_clk = { + .halt_reg = 0x43008, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x43008, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pdm_xo4_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qmip_camera_nrt_ahb_clk = { + .halt_reg = 0x36008, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x36008, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x36008, + .enable_mask = BIT(0), + .hw.init = &(const 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 = 0x3600c, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x3600c, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x3600c, + .enable_mask = BIT(0), + .hw.init = &(const 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 = 0x37008, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x37008, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x37008, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_qmip_disp_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qmip_gpu_ahb_clk = { + .halt_reg = 0x81008, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x81008, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x81008, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_qmip_gpu_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qmip_pcie_ahb_clk = { + .halt_reg = 0x7b018, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x7b018, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x7b018, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_qmip_pcie_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qmip_video_vcodec_ahb_clk = { + .halt_reg = 0x42008, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x42008, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x42008, + .enable_mask = BIT(0), + .hw.init = &(const 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 = 0x3300c, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x62008, + .enable_mask = BIT(9), + .hw.init = &(const 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 = 0x33000, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x62008, + .enable_mask = BIT(8), + .hw.init = &(const 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 = 0x2700c, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x62008, + .enable_mask = BIT(10), + .hw.init = &(const 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 = 0x27140, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x62008, + .enable_mask = BIT(11), + .hw.init = &(const 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 = 0x27274, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x62008, + .enable_mask = BIT(12), + .hw.init = &(const 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 = 0x273a8, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x62008, + .enable_mask = BIT(13), + .hw.init = &(const 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 = 0x274dc, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x62008, + .enable_mask = BIT(14), + .hw.init = &(const 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_wrap1_core_2x_clk = { + .halt_reg = 0x3314c, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x62008, + .enable_mask = BIT(18), + .hw.init = &(const 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 = 0x33140, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x62008, + .enable_mask = BIT(19), + .hw.init = &(const 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 = 0x2800c, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x62008, + .enable_mask = BIT(22), + .hw.init = &(const 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 = 0x28140, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x62008, + .enable_mask = BIT(23), + .hw.init = &(const 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 = 0x28274, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x62008, + .enable_mask = BIT(24), + .hw.init = &(const 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 = 0x283a8, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x62008, + .enable_mask = BIT(25), + .hw.init = &(const 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 = 0x284dc, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x62008, + .enable_mask = BIT(26), + .hw.init = &(const 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_wrap_0_m_ahb_clk = { + .halt_reg = 0x27004, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x27004, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x62008, + .enable_mask = BIT(6), + .hw.init = &(const 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 = 0x27008, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x27008, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x62008, + .enable_mask = BIT(7), + .hw.init = &(const 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 = 0x28004, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x28004, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x62008, + .enable_mask = BIT(20), + .hw.init = &(const 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 = 0x28008, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x28008, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x62008, + .enable_mask = BIT(21), + .hw.init = &(const 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 = 0xb3004, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xb3004, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_sdcc1_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_sdcc1_apps_clk = { + .halt_reg = 0xb3008, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xb3008, + .enable_mask = BIT(0), + .hw.init = &(const 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 = 0xb3028, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0xb3028, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0xb3028, + .enable_mask = BIT(0), + .hw.init = &(const 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 = 0x2400c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x2400c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_sdcc2_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_sdcc2_apps_clk = { + .halt_reg = 0x24004, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x24004, + .enable_mask = BIT(0), + .hw.init = &(const 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_ufs_0_clkref_en = { + .halt_reg = 0x9c000, + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x9c000, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_ufs_0_clkref_en", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ufs_pad_clkref_en = { + .halt_reg = 0x9c024, + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x9c024, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_ufs_pad_clkref_en", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ufs_phy_ahb_clk = { + .halt_reg = 0x87020, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x87020, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x87020, + .enable_mask = BIT(0), + .hw.init = &(const 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 = 0x87018, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x87018, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x87018, + .enable_mask = BIT(0), + .hw.init = &(const 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_axi_hw_ctl_clk = { + .halt_reg = 0x87018, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x87018, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x87018, + .enable_mask = BIT(1), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_ufs_phy_axi_hw_ctl_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 = 0x8706c, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x8706c, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x8706c, + .enable_mask = BIT(0), + .hw.init = &(const 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_ice_core_hw_ctl_clk = { + .halt_reg = 0x8706c, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x8706c, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x8706c, + .enable_mask = BIT(1), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_ufs_phy_ice_core_hw_ctl_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 = 0x870a4, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x870a4, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x870a4, + .enable_mask = BIT(0), + .hw.init = &(const 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_phy_aux_hw_ctl_clk = { + .halt_reg = 0x870a4, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x870a4, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x870a4, + .enable_mask = BIT(1), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_ufs_phy_phy_aux_hw_ctl_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 = 0x87028, + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x87028, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_ufs_phy_rx_symbol_0_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_ufs_phy_rx_symbol_0_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_1_clk = { + .halt_reg = 0x870c0, + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x870c0, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_ufs_phy_rx_symbol_1_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_ufs_phy_rx_symbol_1_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ufs_phy_tx_symbol_0_clk = { + .halt_reg = 0x87024, + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x87024, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_ufs_phy_tx_symbol_0_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_ufs_phy_tx_symbol_0_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ufs_phy_unipro_core_clk = { + .halt_reg = 0x87064, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x87064, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x87064, + .enable_mask = BIT(0), + .hw.init = &(const 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_ufs_phy_unipro_core_hw_ctl_clk = { + .halt_reg = 0x87064, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x87064, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x87064, + .enable_mask = BIT(1), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_ufs_phy_unipro_core_hw_ctl_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 = 0x49018, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x49018, + .enable_mask = BIT(0), + .hw.init = &(const 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 = 0x49024, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x49024, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb30_prim_mock_utmi_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_usb30_prim_mock_utmi_postdiv_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 = 0x49020, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x49020, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb30_prim_sleep_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb3_0_clkref_en = { + .halt_reg = 0x9c010, + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x9c010, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb3_0_clkref_en", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb3_prim_phy_aux_clk = { + .halt_reg = 0x4905c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x4905c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb3_prim_phy_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_com_aux_clk = { + .halt_reg = 0x49060, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x49060, + .enable_mask = BIT(0), + .hw.init = &(const 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_reg = 0x49064, + .halt_check = BRANCH_HALT_DELAY, + .hwcg_reg = 0x49064, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x49064, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb3_prim_phy_pipe_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_usb3_prim_phy_pipe_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_vcodec0_axi_clk = { + .halt_reg = 0x42020, + .halt_check = BRANCH_HALT_SKIP, + .hwcg_reg = 0x42020, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x42020, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_vcodec0_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_venus_ctl_axi_clk = { + .halt_reg = 0x4201c, + .halt_check = BRANCH_HALT_SKIP, + .clkr = { + .enable_reg = 0x4201c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_venus_ctl_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_video_throttle_core_clk = { + .halt_reg = 0x42014, + .halt_check = BRANCH_HALT_SKIP, + .hwcg_reg = 0x42014, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x42014, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_video_throttle_core_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_video_vcodec0_sys_clk = { + .halt_reg = 0xb6058, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0xb6058, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0xb6058, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_video_vcodec0_sys_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_video_venus_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_video_venus_ctl_clk = { + .halt_reg = 0xb6038, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xb6038, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_video_venus_ctl_clk", + .parent_hws = (const struct clk_hw*[]) { + &gcc_video_venus_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct gdsc gcc_pcie_0_gdsc = { + .gdscr = 0x7b004, + .en_rest_wait_val = 0x2, + .en_few_wait_val = 0x2, + .clk_dis_wait_val = 0xf, + .pd = { + .name = "gcc_pcie_0_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, + .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE | VOTABLE, +}; + +static struct gdsc gcc_ufs_phy_gdsc = { + .gdscr = 0x87004, + .en_rest_wait_val = 0x2, + .en_few_wait_val = 0x2, + .clk_dis_wait_val = 0xf, + .pd = { + .name = "gcc_ufs_phy_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, + .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE, +}; + +static struct gdsc gcc_usb30_prim_gdsc = { + .gdscr = 0x49004, + .en_rest_wait_val = 0x2, + .en_few_wait_val = 0x2, + .clk_dis_wait_val = 0xf, + .pd = { + .name = "gcc_usb30_prim_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, + .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE, +}; + +static struct gdsc gcc_vcodec0_gdsc = { + .gdscr = 0xb6044, + .en_rest_wait_val = 0x2, + .en_few_wait_val = 0x2, + .clk_dis_wait_val = 0xf, + .pd = { + .name = "gcc_vcodec0_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, + .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE | HW_CTRL, +}; + +static struct gdsc gcc_venus_gdsc = { + .gdscr = 0xb6020, + .en_rest_wait_val = 0x2, + .en_few_wait_val = 0x2, + .clk_dis_wait_val = 0xf, + .pd = { + .name = "gcc_venus_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, + .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE, +}; + +static struct clk_regmap *gcc_sm4450_clocks[] = { + [GCC_AGGRE_NOC_PCIE_0_AXI_CLK] = &gcc_aggre_noc_pcie_0_axi_clk.clkr, + [GCC_AGGRE_UFS_PHY_AXI_CLK] = &gcc_aggre_ufs_phy_axi_clk.clkr, + [GCC_AGGRE_UFS_PHY_AXI_HW_CTL_CLK] = &gcc_aggre_ufs_phy_axi_hw_ctl_clk.clkr, + [GCC_AGGRE_USB3_PRIM_AXI_CLK] = &gcc_aggre_usb3_prim_axi_clk.clkr, + [GCC_BOOT_ROM_AHB_CLK] = &gcc_boot_rom_ahb_clk.clkr, + [GCC_CAMERA_HF_AXI_CLK] = &gcc_camera_hf_axi_clk.clkr, + [GCC_CAMERA_SF_AXI_CLK] = &gcc_camera_sf_axi_clk.clkr, + [GCC_CFG_NOC_PCIE_ANOC_AHB_CLK] = &gcc_cfg_noc_pcie_anoc_ahb_clk.clkr, + [GCC_CFG_NOC_USB3_PRIM_AXI_CLK] = &gcc_cfg_noc_usb3_prim_axi_clk.clkr, + [GCC_DDRSS_GPU_AXI_CLK] = &gcc_ddrss_gpu_axi_clk.clkr, + [GCC_DDRSS_PCIE_SF_TBU_CLK] = &gcc_ddrss_pcie_sf_tbu_clk.clkr, + [GCC_DISP_HF_AXI_CLK] = &gcc_disp_hf_axi_clk.clkr, + [GCC_EUSB3_0_CLKREF_EN] = &gcc_eusb3_0_clkref_en.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_GPLL0] = &gcc_gpll0.clkr, + [GCC_GPLL0_OUT_EVEN] = &gcc_gpll0_out_even.clkr, + [GCC_GPLL0_OUT_ODD] = &gcc_gpll0_out_odd.clkr, + [GCC_GPLL1] = &gcc_gpll1.clkr, + [GCC_GPLL3] = &gcc_gpll3.clkr, + [GCC_GPLL4] = &gcc_gpll4.clkr, + [GCC_GPLL9] = &gcc_gpll9.clkr, + [GCC_GPLL10] = &gcc_gpll10.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_HLOS1_VOTE_AGGRE_NOC_MMU_AUDIO_TBU_CLK] = + &gcc_hlos1_vote_aggre_noc_mmu_audio_tbu_clk.clkr, + [GCC_HLOS1_VOTE_AGGRE_NOC_MMU_PCIE_TBU_CLK] = + &gcc_hlos1_vote_aggre_noc_mmu_pcie_tbu_clk.clkr, + [GCC_HLOS1_VOTE_AGGRE_NOC_MMU_TBU1_CLK] = &gcc_hlos1_vote_aggre_noc_mmu_tbu1_clk.clkr, + [GCC_HLOS1_VOTE_AGGRE_NOC_MMU_TBU2_CLK] = &gcc_hlos1_vote_aggre_noc_mmu_tbu2_clk.clkr, + [GCC_HLOS1_VOTE_MMNOC_MMU_TBU_HF0_CLK] = &gcc_hlos1_vote_mmnoc_mmu_tbu_hf0_clk.clkr, + [GCC_HLOS1_VOTE_MMNOC_MMU_TBU_HF1_CLK] = &gcc_hlos1_vote_mmnoc_mmu_tbu_hf1_clk.clkr, + [GCC_HLOS1_VOTE_MMNOC_MMU_TBU_SF0_CLK] = &gcc_hlos1_vote_mmnoc_mmu_tbu_sf0_clk.clkr, + [GCC_HLOS1_VOTE_MMU_TCU_CLK] = &gcc_hlos1_vote_mmu_tcu_clk.clkr, + [GCC_PCIE_0_AUX_CLK] = &gcc_pcie_0_aux_clk.clkr, + [GCC_PCIE_0_AUX_CLK_SRC] = &gcc_pcie_0_aux_clk_src.clkr, + [GCC_PCIE_0_CFG_AHB_CLK] = &gcc_pcie_0_cfg_ahb_clk.clkr, + [GCC_PCIE_0_CLKREF_EN] = &gcc_pcie_0_clkref_en.clkr, + [GCC_PCIE_0_MSTR_AXI_CLK] = &gcc_pcie_0_mstr_axi_clk.clkr, + [GCC_PCIE_0_PHY_RCHNG_CLK] = &gcc_pcie_0_phy_rchng_clk.clkr, + [GCC_PCIE_0_PHY_RCHNG_CLK_SRC] = &gcc_pcie_0_phy_rchng_clk_src.clkr, + [GCC_PCIE_0_PIPE_CLK] = &gcc_pcie_0_pipe_clk.clkr, + [GCC_PCIE_0_PIPE_CLK_SRC] = &gcc_pcie_0_pipe_clk_src.clkr, + [GCC_PCIE_0_PIPE_DIV2_CLK] = &gcc_pcie_0_pipe_div2_clk.clkr, + [GCC_PCIE_0_PIPE_DIV2_CLK_SRC] = &gcc_pcie_0_pipe_div2_clk_src.clkr, + [GCC_PCIE_0_SLV_AXI_CLK] = &gcc_pcie_0_slv_axi_clk.clkr, + [GCC_PCIE_0_SLV_Q2A_AXI_CLK] = &gcc_pcie_0_slv_q2a_axi_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_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_AHB_CLK] = &gcc_qmip_gpu_ahb_clk.clkr, + [GCC_QMIP_PCIE_AHB_CLK] = &gcc_qmip_pcie_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_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_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_UFS_0_CLKREF_EN] = &gcc_ufs_0_clkref_en.clkr, + [GCC_UFS_PAD_CLKREF_EN] = &gcc_ufs_pad_clkref_en.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_AXI_HW_CTL_CLK] = &gcc_ufs_phy_axi_hw_ctl_clk.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_ICE_CORE_HW_CTL_CLK] = &gcc_ufs_phy_ice_core_hw_ctl_clk.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_PHY_AUX_HW_CTL_CLK] = &gcc_ufs_phy_phy_aux_hw_ctl_clk.clkr, + [GCC_UFS_PHY_RX_SYMBOL_0_CLK] = &gcc_ufs_phy_rx_symbol_0_clk.clkr, + [GCC_UFS_PHY_RX_SYMBOL_0_CLK_SRC] = &gcc_ufs_phy_rx_symbol_0_clk_src.clkr, + [GCC_UFS_PHY_RX_SYMBOL_1_CLK] = &gcc_ufs_phy_rx_symbol_1_clk.clkr, + [GCC_UFS_PHY_RX_SYMBOL_1_CLK_SRC] = &gcc_ufs_phy_rx_symbol_1_clk_src.clkr, + [GCC_UFS_PHY_TX_SYMBOL_0_CLK] = &gcc_ufs_phy_tx_symbol_0_clk.clkr, + [GCC_UFS_PHY_TX_SYMBOL_0_CLK_SRC] = &gcc_ufs_phy_tx_symbol_0_clk_src.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_UFS_PHY_UNIPRO_CORE_HW_CTL_CLK] = &gcc_ufs_phy_unipro_core_hw_ctl_clk.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_MOCK_UTMI_POSTDIV_CLK_SRC] = &gcc_usb30_prim_mock_utmi_postdiv_clk_src.clkr, + [GCC_USB30_PRIM_SLEEP_CLK] = &gcc_usb30_prim_sleep_clk.clkr, + [GCC_USB3_0_CLKREF_EN] = &gcc_usb3_0_clkref_en.clkr, + [GCC_USB3_PRIM_PHY_AUX_CLK] = &gcc_usb3_prim_phy_aux_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_USB3_PRIM_PHY_PIPE_CLK_SRC] = &gcc_usb3_prim_phy_pipe_clk_src.clkr, + [GCC_VCODEC0_AXI_CLK] = &gcc_vcodec0_axi_clk.clkr, + [GCC_VENUS_CTL_AXI_CLK] = &gcc_venus_ctl_axi_clk.clkr, + [GCC_VIDEO_THROTTLE_CORE_CLK] = &gcc_video_throttle_core_clk.clkr, + [GCC_VIDEO_VCODEC0_SYS_CLK] = &gcc_video_vcodec0_sys_clk.clkr, + [GCC_VIDEO_VENUS_CLK_SRC] = &gcc_video_venus_clk_src.clkr, + [GCC_VIDEO_VENUS_CTL_CLK] = &gcc_video_venus_ctl_clk.clkr, +}; + +static struct gdsc *gcc_sm4450_gdscs[] = { + [GCC_PCIE_0_GDSC] = &gcc_pcie_0_gdsc, + [GCC_UFS_PHY_GDSC] = &gcc_ufs_phy_gdsc, + [GCC_USB30_PRIM_GDSC] = &gcc_usb30_prim_gdsc, + [GCC_VCODEC0_GDSC] = &gcc_vcodec0_gdsc, + [GCC_VENUS_GDSC] = &gcc_venus_gdsc, +}; + +static const struct qcom_reset_map gcc_sm4450_resets[] = { + [GCC_CAMERA_BCR] = { 0x36000 }, + [GCC_DISPLAY_BCR] = { 0x37000 }, + [GCC_GPU_BCR] = { 0x81000 }, + [GCC_PCIE_0_BCR] = { 0x7b000 }, + [GCC_PCIE_0_LINK_DOWN_BCR] = { 0x7c014 }, + [GCC_PCIE_0_NOCSR_COM_PHY_BCR] = { 0x7c020 }, + [GCC_PCIE_0_PHY_BCR] = { 0x7c01c }, + [GCC_PCIE_0_PHY_NOCSR_COM_PHY_BCR] = { 0x7c028 }, + [GCC_PCIE_PHY_BCR] = { 0x7f000 }, + [GCC_PCIE_PHY_CFG_AHB_BCR] = { 0x7f00c }, + [GCC_PCIE_PHY_COM_BCR] = { 0x7f010 }, + [GCC_PDM_BCR] = { 0x43000 }, + [GCC_QUPV3_WRAPPER_0_BCR] = { 0x27000 }, + [GCC_QUPV3_WRAPPER_1_BCR] = { 0x28000 }, + [GCC_QUSB2PHY_PRIM_BCR] = { 0x22000 }, + [GCC_QUSB2PHY_SEC_BCR] = { 0x22004 }, + [GCC_SDCC1_BCR] = { 0xb3000 }, + [GCC_SDCC2_BCR] = { 0x24000 }, + [GCC_UFS_PHY_BCR] = { 0x87000 }, + [GCC_USB30_PRIM_BCR] = { 0x49000 }, + [GCC_USB3_DP_PHY_PRIM_BCR] = { 0x60008 }, + [GCC_USB3_DP_PHY_SEC_BCR] = { 0x60014 }, + [GCC_USB3_PHY_PRIM_BCR] = { 0x60000 }, + [GCC_USB3_PHY_SEC_BCR] = { 0x6000c }, + [GCC_USB3PHY_PHY_PRIM_BCR] = { 0x60004 }, + [GCC_USB3PHY_PHY_SEC_BCR] = { 0x60010 }, + [GCC_VCODEC0_BCR] = { 0xb6040 }, + [GCC_VENUS_BCR] = { 0xb601c }, + [GCC_VIDEO_BCR] = { 0x42000 }, + [GCC_VIDEO_VENUS_BCR] = { 0xb6000 }, + [GCC_VENUS_CTL_AXI_CLK_ARES] = { 0x4201c, 2 }, + [GCC_VIDEO_VENUS_CTL_CLK_ARES] = { 0xb6038, 2 }, +}; + +static const 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_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), +}; + +static const struct regmap_config gcc_sm4450_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = 0x1f41f0, + .fast_io = true, +}; + +static const struct qcom_cc_desc gcc_sm4450_desc = { + .config = &gcc_sm4450_regmap_config, + .clks = gcc_sm4450_clocks, + .num_clks = ARRAY_SIZE(gcc_sm4450_clocks), + .resets = gcc_sm4450_resets, + .num_resets = ARRAY_SIZE(gcc_sm4450_resets), + .gdscs = gcc_sm4450_gdscs, + .num_gdscs = ARRAY_SIZE(gcc_sm4450_gdscs), +}; + +static const struct of_device_id gcc_sm4450_match_table[] = { + { .compatible = "qcom,sm4450-gcc" }, + { } +}; +MODULE_DEVICE_TABLE(of, gcc_sm4450_match_table); + +static int gcc_sm4450_probe(struct platform_device *pdev) +{ + struct regmap *regmap; + int ret; + + regmap = qcom_cc_map(pdev, &gcc_sm4450_desc); + if (IS_ERR(regmap)) + return PTR_ERR(regmap); + + clk_lucid_evo_pll_configure(&gcc_gpll3, regmap, &gcc_gpll3_config); + ret = qcom_cc_register_rcg_dfs(regmap, gcc_dfs_clocks, + ARRAY_SIZE(gcc_dfs_clocks)); + if (ret) + return ret; + + qcom_branch_set_force_mem_core(regmap, gcc_ufs_phy_ice_core_clk, true); + + /* + * Keep clocks always enabled: + * gcc_camera_ahb_clk + * gcc_camera_sleep_clk + * gcc_camera_xo_clk + * gcc_disp_ahb_clk + * gcc_disp_xo_clk + * gcc_gpu_cfg_ahb_clk + * gcc_video_ahb_clk + * gcc_video_xo_clk + */ + regmap_update_bits(regmap, 0x36004, BIT(0), BIT(0)); + regmap_update_bits(regmap, 0x36018, BIT(0), BIT(0)); + regmap_update_bits(regmap, 0x3601c, BIT(0), BIT(0)); + regmap_update_bits(regmap, 0x37004, BIT(0), BIT(0)); + regmap_update_bits(regmap, 0x37014, BIT(0), BIT(0)); + regmap_update_bits(regmap, 0x81004, BIT(0), BIT(0)); + regmap_update_bits(regmap, 0x42004, BIT(0), BIT(0)); + regmap_update_bits(regmap, 0x42018, BIT(0), BIT(0)); + + regmap_update_bits(regmap, 0x4201c, BIT(21), BIT(21)); + + return qcom_cc_really_probe(pdev, &gcc_sm4450_desc, regmap); +} + +static struct platform_driver gcc_sm4450_driver = { + .probe = gcc_sm4450_probe, + .driver = { + .name = "gcc-sm4450", + .of_match_table = gcc_sm4450_match_table, + }, +}; + +static int __init gcc_sm4450_init(void) +{ + return platform_driver_register(&gcc_sm4450_driver); +} +subsys_initcall(gcc_sm4450_init); + +static void __exit gcc_sm4450_exit(void) +{ + platform_driver_unregister(&gcc_sm4450_driver); +} +module_exit(gcc_sm4450_exit); + +MODULE_DESCRIPTION("QTI GCC SM4450 Driver"); +MODULE_LICENSE("GPL"); -- cgit v1.2.3-59-g8ed1b From 7138c244fb293f24ce8ab782961022eff00a10c4 Mon Sep 17 00:00:00 2001 From: Danila Tikhonov Date: Wed, 13 Sep 2023 20:56:11 +0300 Subject: clk: qcom: gcc-sm8150: Fix gcc_sdcc2_apps_clk_src Set .flags = CLK_OPS_PARENT_ENABLE to fix "gcc_sdcc2_apps_clk_src: rcg didn't update its configuration" error. Fixes: 2a1d7eb854bb ("clk: qcom: gcc: Add global clock controller driver for SM8150") Tested-by: Arseniy Velikanov Signed-off-by: Danila Tikhonov Reviewed-by: Konrad Dybcio Link: https://lore.kernel.org/r/20230913175612.8685-1-danila@jiaxyga.com Signed-off-by: Bjorn Andersson --- drivers/clk/qcom/gcc-sm8150.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/qcom/gcc-sm8150.c b/drivers/clk/qcom/gcc-sm8150.c index 41ab210875fb..05d115c52dfe 100644 --- a/drivers/clk/qcom/gcc-sm8150.c +++ b/drivers/clk/qcom/gcc-sm8150.c @@ -774,7 +774,7 @@ static struct clk_rcg2 gcc_sdcc2_apps_clk_src = { .name = "gcc_sdcc2_apps_clk_src", .parent_data = gcc_parents_6, .num_parents = ARRAY_SIZE(gcc_parents_6), - .flags = CLK_SET_RATE_PARENT, + .flags = CLK_OPS_PARENT_ENABLE, .ops = &clk_rcg2_floor_ops, }, }; -- cgit v1.2.3-59-g8ed1b From 87882525e5ddae7ef6f1b1df5e1eda9bcbcd7720 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sun, 17 Sep 2023 11:58:32 +0200 Subject: clk: renesas: r8a7795: Constify r8a7795_*_clks Make r8a7795_core_clks and r8a7795_mod_clks arrays const and align them with the other clock tables in other *cpg-mssr.c . No functional change. Signed-off-by: Marek Vasut Reviewed-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/20230917095832.39007-1-marek.vasut+renesas@mailbox.org Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/r8a7795-cpg-mssr.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/clk/renesas/r8a7795-cpg-mssr.c b/drivers/clk/renesas/r8a7795-cpg-mssr.c index ad20b3301ef6..e47d9b1fcc0a 100644 --- a/drivers/clk/renesas/r8a7795-cpg-mssr.c +++ b/drivers/clk/renesas/r8a7795-cpg-mssr.c @@ -51,7 +51,7 @@ enum clk_ids { MOD_CLK_BASE }; -static struct cpg_core_clk r8a7795_core_clks[] __initdata = { +static const struct cpg_core_clk r8a7795_core_clks[] __initconst = { /* External Clock Inputs */ DEF_INPUT("extal", CLK_EXTAL), DEF_INPUT("extalr", CLK_EXTALR), @@ -128,7 +128,7 @@ static struct cpg_core_clk r8a7795_core_clks[] __initdata = { DEF_BASE("r", R8A7795_CLK_R, CLK_TYPE_GEN3_R, CLK_RINT), }; -static struct mssr_mod_clk r8a7795_mod_clks[] __initdata = { +static const struct mssr_mod_clk r8a7795_mod_clks[] __initconst = { DEF_MOD("3dge", 112, R8A7795_CLK_ZG), DEF_MOD("fdp1-1", 118, R8A7795_CLK_S0D1), DEF_MOD("fdp1-0", 119, R8A7795_CLK_S0D1), -- cgit v1.2.3-59-g8ed1b From 923a77a2e18001f290432b96cb71f68b3423296d Mon Sep 17 00:00:00 2001 From: Yu Tu Date: Mon, 4 Sep 2023 15:55:01 +0800 Subject: dt-bindings: clock: document Amlogic S4 SoC PLL clock controller Add the S4 PLL clock controller dt-bindings in the S4 SoC family. Signed-off-by: Yu Tu Reviewed-by: Rob Herring Link: https://lore.kernel.org/r/20230904075504.23263-2-yu.tu@amlogic.com Signed-off-by: Jerome Brunet --- .../bindings/clock/amlogic,s4-pll-clkc.yaml | 49 ++++++++++++++++++++++ include/dt-bindings/clock/amlogic,s4-pll-clkc.h | 43 +++++++++++++++++++ 2 files changed, 92 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/amlogic,s4-pll-clkc.yaml create mode 100644 include/dt-bindings/clock/amlogic,s4-pll-clkc.h diff --git a/Documentation/devicetree/bindings/clock/amlogic,s4-pll-clkc.yaml b/Documentation/devicetree/bindings/clock/amlogic,s4-pll-clkc.yaml new file mode 100644 index 000000000000..d8932ec26ca8 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/amlogic,s4-pll-clkc.yaml @@ -0,0 +1,49 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +# Copyright (C) 2022-2023 Amlogic, Inc. All rights reserved +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/amlogic,s4-pll-clkc.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Amlogic S4 PLL Clock Controller + +maintainers: + - Yu Tu + +properties: + compatible: + const: amlogic,s4-pll-clkc + + reg: + maxItems: 1 + + clocks: + maxItems: 1 + + clock-names: + items: + - const: xtal + + "#clock-cells": + const: 1 + +required: + - compatible + - reg + - clocks + - clock-names + - "#clock-cells" + +additionalProperties: false + +examples: + - | + clkc_pll: clock-controller@fe008000 { + compatible = "amlogic,s4-pll-clkc"; + reg = <0xfe008000 0x1e8>; + clocks = <&xtal>; + clock-names = "xtal"; + #clock-cells = <1>; + }; + +... diff --git a/include/dt-bindings/clock/amlogic,s4-pll-clkc.h b/include/dt-bindings/clock/amlogic,s4-pll-clkc.h new file mode 100644 index 000000000000..af9f110f8b62 --- /dev/null +++ b/include/dt-bindings/clock/amlogic,s4-pll-clkc.h @@ -0,0 +1,43 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR MIT) */ +/* + * Copyright (c) 2022-2023 Amlogic, Inc. All rights reserved. + * Author: Yu Tu + */ + +#ifndef _DT_BINDINGS_CLOCK_AMLOGIC_S4_PLL_CLKC_H +#define _DT_BINDINGS_CLOCK_AMLOGIC_S4_PLL_CLKC_H + +#define CLKID_FIXED_PLL_DCO 0 +#define CLKID_FIXED_PLL 1 +#define CLKID_FCLK_DIV2_DIV 2 +#define CLKID_FCLK_DIV2 3 +#define CLKID_FCLK_DIV3_DIV 4 +#define CLKID_FCLK_DIV3 5 +#define CLKID_FCLK_DIV4_DIV 6 +#define CLKID_FCLK_DIV4 7 +#define CLKID_FCLK_DIV5_DIV 8 +#define CLKID_FCLK_DIV5 9 +#define CLKID_FCLK_DIV7_DIV 10 +#define CLKID_FCLK_DIV7 11 +#define CLKID_FCLK_DIV2P5_DIV 12 +#define CLKID_FCLK_DIV2P5 13 +#define CLKID_GP0_PLL_DCO 14 +#define CLKID_GP0_PLL 15 +#define CLKID_HIFI_PLL_DCO 16 +#define CLKID_HIFI_PLL 17 +#define CLKID_HDMI_PLL_DCO 18 +#define CLKID_HDMI_PLL_OD 19 +#define CLKID_HDMI_PLL 20 +#define CLKID_MPLL_50M_DIV 21 +#define CLKID_MPLL_50M 22 +#define CLKID_MPLL_PREDIV 23 +#define CLKID_MPLL0_DIV 24 +#define CLKID_MPLL0 25 +#define CLKID_MPLL1_DIV 26 +#define CLKID_MPLL1 27 +#define CLKID_MPLL2_DIV 28 +#define CLKID_MPLL2 29 +#define CLKID_MPLL3_DIV 30 +#define CLKID_MPLL3 31 + +#endif /* _DT_BINDINGS_CLOCK_AMLOGIC_S4_PLL_CLKC_H */ -- cgit v1.2.3-59-g8ed1b From 98949499169634263ed4a0bb21e9d9677301c17d Mon Sep 17 00:00:00 2001 From: Yu Tu Date: Mon, 4 Sep 2023 15:55:02 +0800 Subject: dt-bindings: clock: document Amlogic S4 SoC peripherals clock controller Add the S4 peripherals clock controller dt-bindings in the S4 SoC family. Signed-off-by: Yu Tu Reviewed-by: Rob Herring Link: https://lore.kernel.org/r/20230904075504.23263-3-yu.tu@amlogic.com Signed-off-by: Jerome Brunet --- .../clock/amlogic,s4-peripherals-clkc.yaml | 96 +++++++++ .../clock/amlogic,s4-peripherals-clkc.h | 236 +++++++++++++++++++++ 2 files changed, 332 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/amlogic,s4-peripherals-clkc.yaml create mode 100644 include/dt-bindings/clock/amlogic,s4-peripherals-clkc.h diff --git a/Documentation/devicetree/bindings/clock/amlogic,s4-peripherals-clkc.yaml b/Documentation/devicetree/bindings/clock/amlogic,s4-peripherals-clkc.yaml new file mode 100644 index 000000000000..c229e4f0c1d9 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/amlogic,s4-peripherals-clkc.yaml @@ -0,0 +1,96 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +# Copyright (C) 2022-2023 Amlogic, Inc. All rights reserved +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/amlogic,s4-peripherals-clkc.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Amlogic S4 Peripherals Clock Controller + +maintainers: + - Yu Tu + +properties: + compatible: + const: amlogic,s4-peripherals-clkc + + reg: + maxItems: 1 + + clocks: + minItems: 14 + items: + - description: input fixed pll div2 + - description: input fixed pll div2p5 + - description: input fixed pll div3 + - description: input fixed pll div4 + - description: input fixed pll div5 + - description: input fixed pll div7 + - description: input hifi pll + - description: input gp0 pll + - description: input mpll0 + - description: input mpll1 + - description: input mpll2 + - description: input mpll3 + - description: input hdmi pll + - description: input oscillator (usually at 24MHz) + - description: input external 32kHz reference (optional) + + clock-names: + minItems: 14 + items: + - const: fclk_div2 + - const: fclk_div2p5 + - const: fclk_div3 + - const: fclk_div4 + - const: fclk_div5 + - const: fclk_div7 + - const: hifi_pll + - const: gp0_pll + - const: mpll0 + - const: mpll1 + - const: mpll2 + - const: mpll3 + - const: hdmi_pll + - const: xtal + - const: ext_32k + + "#clock-cells": + const: 1 + +required: + - compatible + - reg + - clocks + - clock-names + - "#clock-cells" + +additionalProperties: false + +examples: + - | + #include + + clkc_periphs: clock-controller@fe000000 { + compatible = "amlogic,s4-peripherals-clkc"; + reg = <0xfe000000 0x49c>; + clocks = <&clkc_pll 3>, + <&clkc_pll 13>, + <&clkc_pll 5>, + <&clkc_pll 7>, + <&clkc_pll 9>, + <&clkc_pll 11>, + <&clkc_pll 17>, + <&clkc_pll 15>, + <&clkc_pll 25>, + <&clkc_pll 27>, + <&clkc_pll 29>, + <&clkc_pll 31>, + <&clkc_pll 20>, + <&xtal>; + clock-names = "fclk_div2", "fclk_div2p5", "fclk_div3", "fclk_div4", + "fclk_div5", "fclk_div7", "hifi_pll", "gp0_pll", + "mpll0", "mpll1", "mpll2", "mpll3", "hdmi_pll", "xtal"; + #clock-cells = <1>; + }; +... diff --git a/include/dt-bindings/clock/amlogic,s4-peripherals-clkc.h b/include/dt-bindings/clock/amlogic,s4-peripherals-clkc.h new file mode 100644 index 000000000000..861a331963ac --- /dev/null +++ b/include/dt-bindings/clock/amlogic,s4-peripherals-clkc.h @@ -0,0 +1,236 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR MIT) */ +/* + * Copyright (c) 2022-2023 Amlogic, Inc. All rights reserved. + * Author: Yu Tu + */ + +#ifndef _DT_BINDINGS_CLOCK_AMLOGIC_S4_PERIPHERALS_CLKC_H +#define _DT_BINDINGS_CLOCK_AMLOGIC_S4_PERIPHERALS_CLKC_H + +#define CLKID_RTC_32K_CLKIN 0 +#define CLKID_RTC_32K_DIV 1 +#define CLKID_RTC_32K_SEL 2 +#define CLKID_RTC_32K_XATL 3 +#define CLKID_RTC 4 +#define CLKID_SYS_CLK_B_SEL 5 +#define CLKID_SYS_CLK_B_DIV 6 +#define CLKID_SYS_CLK_B 7 +#define CLKID_SYS_CLK_A_SEL 8 +#define CLKID_SYS_CLK_A_DIV 9 +#define CLKID_SYS_CLK_A 10 +#define CLKID_SYS 11 +#define CLKID_CECA_32K_CLKIN 12 +#define CLKID_CECA_32K_DIV 13 +#define CLKID_CECA_32K_SEL_PRE 14 +#define CLKID_CECA_32K_SEL 15 +#define CLKID_CECA_32K_CLKOUT 16 +#define CLKID_CECB_32K_CLKIN 17 +#define CLKID_CECB_32K_DIV 18 +#define CLKID_CECB_32K_SEL_PRE 19 +#define CLKID_CECB_32K_SEL 20 +#define CLKID_CECB_32K_CLKOUT 21 +#define CLKID_SC_CLK_SEL 22 +#define CLKID_SC_CLK_DIV 23 +#define CLKID_SC 24 +#define CLKID_12_24M 25 +#define CLKID_12M_CLK_DIV 26 +#define CLKID_12_24M_CLK_SEL 27 +#define CLKID_VID_PLL_DIV 28 +#define CLKID_VID_PLL_SEL 29 +#define CLKID_VID_PLL 30 +#define CLKID_VCLK_SEL 31 +#define CLKID_VCLK2_SEL 32 +#define CLKID_VCLK_INPUT 33 +#define CLKID_VCLK2_INPUT 34 +#define CLKID_VCLK_DIV 35 +#define CLKID_VCLK2_DIV 36 +#define CLKID_VCLK 37 +#define CLKID_VCLK2 38 +#define CLKID_VCLK_DIV1 39 +#define CLKID_VCLK_DIV2_EN 40 +#define CLKID_VCLK_DIV4_EN 41 +#define CLKID_VCLK_DIV6_EN 42 +#define CLKID_VCLK_DIV12_EN 43 +#define CLKID_VCLK2_DIV1 44 +#define CLKID_VCLK2_DIV2_EN 45 +#define CLKID_VCLK2_DIV4_EN 46 +#define CLKID_VCLK2_DIV6_EN 47 +#define CLKID_VCLK2_DIV12_EN 48 +#define CLKID_VCLK_DIV2 49 +#define CLKID_VCLK_DIV4 50 +#define CLKID_VCLK_DIV6 51 +#define CLKID_VCLK_DIV12 52 +#define CLKID_VCLK2_DIV2 53 +#define CLKID_VCLK2_DIV4 54 +#define CLKID_VCLK2_DIV6 55 +#define CLKID_VCLK2_DIV12 56 +#define CLKID_CTS_ENCI_SEL 57 +#define CLKID_CTS_ENCP_SEL 58 +#define CLKID_CTS_VDAC_SEL 59 +#define CLKID_HDMI_TX_SEL 60 +#define CLKID_CTS_ENCI 61 +#define CLKID_CTS_ENCP 62 +#define CLKID_CTS_VDAC 63 +#define CLKID_HDMI_TX 64 +#define CLKID_HDMI_SEL 65 +#define CLKID_HDMI_DIV 66 +#define CLKID_HDMI 67 +#define CLKID_TS_CLK_DIV 68 +#define CLKID_TS 69 +#define CLKID_MALI_0_SEL 70 +#define CLKID_MALI_0_DIV 71 +#define CLKID_MALI_0 72 +#define CLKID_MALI_1_SEL 73 +#define CLKID_MALI_1_DIV 74 +#define CLKID_MALI_1 75 +#define CLKID_MALI_SEL 76 +#define CLKID_VDEC_P0_SEL 77 +#define CLKID_VDEC_P0_DIV 78 +#define CLKID_VDEC_P0 79 +#define CLKID_VDEC_P1_SEL 80 +#define CLKID_VDEC_P1_DIV 81 +#define CLKID_VDEC_P1 82 +#define CLKID_VDEC_SEL 83 +#define CLKID_HEVCF_P0_SEL 84 +#define CLKID_HEVCF_P0_DIV 85 +#define CLKID_HEVCF_P0 86 +#define CLKID_HEVCF_P1_SEL 87 +#define CLKID_HEVCF_P1_DIV 88 +#define CLKID_HEVCF_P1 89 +#define CLKID_HEVCF_SEL 90 +#define CLKID_VPU_0_SEL 91 +#define CLKID_VPU_0_DIV 92 +#define CLKID_VPU_0 93 +#define CLKID_VPU_1_SEL 94 +#define CLKID_VPU_1_DIV 95 +#define CLKID_VPU_1 96 +#define CLKID_VPU 97 +#define CLKID_VPU_CLKB_TMP_SEL 98 +#define CLKID_VPU_CLKB_TMP_DIV 99 +#define CLKID_VPU_CLKB_TMP 100 +#define CLKID_VPU_CLKB_DIV 101 +#define CLKID_VPU_CLKB 102 +#define CLKID_VPU_CLKC_P0_SEL 103 +#define CLKID_VPU_CLKC_P0_DIV 104 +#define CLKID_VPU_CLKC_P0 105 +#define CLKID_VPU_CLKC_P1_SEL 106 +#define CLKID_VPU_CLKC_P1_DIV 107 +#define CLKID_VPU_CLKC_P1 108 +#define CLKID_VPU_CLKC_SEL 109 +#define CLKID_VAPB_0_SEL 110 +#define CLKID_VAPB_0_DIV 111 +#define CLKID_VAPB_0 112 +#define CLKID_VAPB_1_SEL 113 +#define CLKID_VAPB_1_DIV 114 +#define CLKID_VAPB_1 115 +#define CLKID_VAPB 116 +#define CLKID_GE2D 117 +#define CLKID_VDIN_MEAS_SEL 118 +#define CLKID_VDIN_MEAS_DIV 119 +#define CLKID_VDIN_MEAS 120 +#define CLKID_SD_EMMC_C_CLK_SEL 121 +#define CLKID_SD_EMMC_C_CLK_DIV 122 +#define CLKID_SD_EMMC_C 123 +#define CLKID_SD_EMMC_A_CLK_SEL 124 +#define CLKID_SD_EMMC_A_CLK_DIV 125 +#define CLKID_SD_EMMC_A 126 +#define CLKID_SD_EMMC_B_CLK_SEL 127 +#define CLKID_SD_EMMC_B_CLK_DIV 128 +#define CLKID_SD_EMMC_B 129 +#define CLKID_SPICC0_SEL 130 +#define CLKID_SPICC0_DIV 131 +#define CLKID_SPICC0_EN 132 +#define CLKID_PWM_A_SEL 133 +#define CLKID_PWM_A_DIV 134 +#define CLKID_PWM_A 135 +#define CLKID_PWM_B_SEL 136 +#define CLKID_PWM_B_DIV 137 +#define CLKID_PWM_B 138 +#define CLKID_PWM_C_SEL 139 +#define CLKID_PWM_C_DIV 140 +#define CLKID_PWM_C 141 +#define CLKID_PWM_D_SEL 142 +#define CLKID_PWM_D_DIV 143 +#define CLKID_PWM_D 144 +#define CLKID_PWM_E_SEL 145 +#define CLKID_PWM_E_DIV 146 +#define CLKID_PWM_E 147 +#define CLKID_PWM_F_SEL 148 +#define CLKID_PWM_F_DIV 149 +#define CLKID_PWM_F 150 +#define CLKID_PWM_G_SEL 151 +#define CLKID_PWM_G_DIV 152 +#define CLKID_PWM_G 153 +#define CLKID_PWM_H_SEL 154 +#define CLKID_PWM_H_DIV 155 +#define CLKID_PWM_H 156 +#define CLKID_PWM_I_SEL 157 +#define CLKID_PWM_I_DIV 158 +#define CLKID_PWM_I 159 +#define CLKID_PWM_J_SEL 160 +#define CLKID_PWM_J_DIV 161 +#define CLKID_PWM_J 162 +#define CLKID_SARADC_SEL 163 +#define CLKID_SARADC_DIV 164 +#define CLKID_SARADC 165 +#define CLKID_GEN_SEL 166 +#define CLKID_GEN_DIV 167 +#define CLKID_GEN 168 +#define CLKID_DDR 169 +#define CLKID_DOS 170 +#define CLKID_ETHPHY 171 +#define CLKID_MALI 172 +#define CLKID_AOCPU 173 +#define CLKID_AUCPU 174 +#define CLKID_CEC 175 +#define CLKID_SDEMMC_A 176 +#define CLKID_SDEMMC_B 177 +#define CLKID_NAND 178 +#define CLKID_SMARTCARD 179 +#define CLKID_ACODEC 180 +#define CLKID_SPIFC 181 +#define CLKID_MSR 182 +#define CLKID_IR_CTRL 183 +#define CLKID_AUDIO 184 +#define CLKID_ETH 185 +#define CLKID_UART_A 186 +#define CLKID_UART_B 187 +#define CLKID_UART_C 188 +#define CLKID_UART_D 189 +#define CLKID_UART_E 190 +#define CLKID_AIFIFO 191 +#define CLKID_TS_DDR 192 +#define CLKID_TS_PLL 193 +#define CLKID_G2D 194 +#define CLKID_SPICC0 195 +#define CLKID_SPICC1 196 +#define CLKID_USB 197 +#define CLKID_I2C_M_A 198 +#define CLKID_I2C_M_B 199 +#define CLKID_I2C_M_C 200 +#define CLKID_I2C_M_D 201 +#define CLKID_I2C_M_E 202 +#define CLKID_HDMITX_APB 203 +#define CLKID_I2C_S_A 204 +#define CLKID_USB1_TO_DDR 205 +#define CLKID_HDCP22 206 +#define CLKID_MMC_APB 207 +#define CLKID_RSA 208 +#define CLKID_CPU_DEBUG 209 +#define CLKID_VPU_INTR 210 +#define CLKID_DEMOD 211 +#define CLKID_SAR_ADC 212 +#define CLKID_GIC 213 +#define CLKID_PWM_AB 214 +#define CLKID_PWM_CD 215 +#define CLKID_PWM_EF 216 +#define CLKID_PWM_GH 217 +#define CLKID_PWM_IJ 218 +#define CLKID_HDCP22_ESMCLK_SEL 219 +#define CLKID_HDCP22_ESMCLK_DIV 220 +#define CLKID_HDCP22_ESMCLK 221 +#define CLKID_HDCP22_SKPCLK_SEL 222 +#define CLKID_HDCP22_SKPCLK_DIV 223 +#define CLKID_HDCP22_SKPCLK 224 + +#endif /* _DT_BINDINGS_CLOCK_AMLOGIC_S4_PERIPHERALS_CLKC_H */ -- cgit v1.2.3-59-g8ed1b From e787c9c55edadb5d9d6c75ce5080dd3c64bd996b Mon Sep 17 00:00:00 2001 From: Yu Tu Date: Mon, 4 Sep 2023 15:55:03 +0800 Subject: clk: meson: S4: add support for Amlogic S4 SoC PLL clock driver Add the S4 PLL clock controller driver in the S4 SoC family. Signed-off-by: Yu Tu Link: https://lore.kernel.org/r/20230904075504.23263-4-yu.tu@amlogic.com Signed-off-by: Jerome Brunet --- drivers/clk/meson/Kconfig | 12 + drivers/clk/meson/Makefile | 1 + drivers/clk/meson/s4-pll.c | 867 +++++++++++++++++++++++++++++++++++++++++++++ drivers/clk/meson/s4-pll.h | 38 ++ 4 files changed, 918 insertions(+) create mode 100644 drivers/clk/meson/s4-pll.c create mode 100644 drivers/clk/meson/s4-pll.h diff --git a/drivers/clk/meson/Kconfig b/drivers/clk/meson/Kconfig index 135da8f2d0b1..e90982d77598 100644 --- a/drivers/clk/meson/Kconfig +++ b/drivers/clk/meson/Kconfig @@ -144,4 +144,16 @@ config COMMON_CLK_G12A help Support for the clock controller on Amlogic S905D2, S905X2 and S905Y2 devices, aka g12a. Say Y if you want peripherals to work. + +config COMMON_CLK_S4_PLL + tristate "S4 SoC PLL clock controllers support" + depends on ARM64 + default y + select COMMON_CLK_MESON_MPLL + select COMMON_CLK_MESON_PLL + select COMMON_CLK_MESON_REGMAP + help + Support for the PLL clock controller on Amlogic S805X2 and S905Y4 devices, + AKA S4. Say Y if you want the board to work, because PLLs are the parent of + most peripherals. endmenu diff --git a/drivers/clk/meson/Makefile b/drivers/clk/meson/Makefile index cd961cc4f4db..612cee923890 100644 --- a/drivers/clk/meson/Makefile +++ b/drivers/clk/meson/Makefile @@ -22,3 +22,4 @@ obj-$(CONFIG_COMMON_CLK_A1_PERIPHERALS) += a1-peripherals.o obj-$(CONFIG_COMMON_CLK_GXBB) += gxbb.o gxbb-aoclk.o obj-$(CONFIG_COMMON_CLK_G12A) += g12a.o g12a-aoclk.o obj-$(CONFIG_COMMON_CLK_MESON8B) += meson8b.o meson8-ddr.o +obj-$(CONFIG_COMMON_CLK_S4_PLL) += s4-pll.o diff --git a/drivers/clk/meson/s4-pll.c b/drivers/clk/meson/s4-pll.c new file mode 100644 index 000000000000..8dfaeccaadc2 --- /dev/null +++ b/drivers/clk/meson/s4-pll.c @@ -0,0 +1,867 @@ +// SPDX-License-Identifier: (GPL-2.0-only OR MIT) +/* + * Amlogic S4 PLL Clock Controller Driver + * + * Copyright (c) 2022-2023 Amlogic, inc. All rights reserved + * Author: Yu Tu + */ + +#include +#include +#include + +#include "clk-mpll.h" +#include "clk-pll.h" +#include "clk-regmap.h" +#include "s4-pll.h" +#include "meson-clkc-utils.h" +#include + +static DEFINE_SPINLOCK(meson_clk_lock); + +/* + * These clock are a fixed value (fixed_pll is 2GHz) that is initialized by ROMcode. + * The chip was changed fixed pll for security reasons. Fixed PLL registers are not writable + * in the kernel phase. Write of fixed PLL-related register will cause the system to crash. + * Meanwhile, these clock won't ever change at runtime. + * For the above reasons, we can only use ro_ops for fixed PLL related clocks. + */ +static struct clk_regmap s4_fixed_pll_dco = { + .data = &(struct meson_clk_pll_data){ + .en = { + .reg_off = ANACTRL_FIXPLL_CTRL0, + .shift = 28, + .width = 1, + }, + .m = { + .reg_off = ANACTRL_FIXPLL_CTRL0, + .shift = 0, + .width = 8, + }, + .n = { + .reg_off = ANACTRL_FIXPLL_CTRL0, + .shift = 10, + .width = 5, + }, + .l = { + .reg_off = ANACTRL_FIXPLL_CTRL0, + .shift = 31, + .width = 1, + }, + .rst = { + .reg_off = ANACTRL_FIXPLL_CTRL0, + .shift = 29, + .width = 1, + }, + }, + .hw.init = &(struct clk_init_data){ + .name = "fixed_pll_dco", + .ops = &meson_clk_pll_ro_ops, + .parent_data = (const struct clk_parent_data []) { + { .fw_name = "xtal", } + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap s4_fixed_pll = { + .data = &(struct clk_regmap_div_data){ + .offset = ANACTRL_FIXPLL_CTRL0, + .shift = 16, + .width = 2, + .flags = CLK_DIVIDER_POWER_OF_TWO, + }, + .hw.init = &(struct clk_init_data){ + .name = "fixed_pll", + .ops = &clk_regmap_divider_ro_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_fixed_pll_dco.hw + }, + .num_parents = 1, + /* + * This clock won't ever change at runtime so + * CLK_SET_RATE_PARENT is not required + */ + }, +}; + +static struct clk_fixed_factor s4_fclk_div2_div = { + .mult = 1, + .div = 2, + .hw.init = &(struct clk_init_data){ + .name = "fclk_div2_div", + .ops = &clk_fixed_factor_ops, + .parent_hws = (const struct clk_hw *[]) { &s4_fixed_pll.hw }, + .num_parents = 1, + }, +}; + +static struct clk_regmap s4_fclk_div2 = { + .data = &(struct clk_regmap_gate_data){ + .offset = ANACTRL_FIXPLL_CTRL1, + .bit_idx = 24, + }, + .hw.init = &(struct clk_init_data){ + .name = "fclk_div2", + .ops = &clk_regmap_gate_ro_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_fclk_div2_div.hw + }, + .num_parents = 1, + }, +}; + +static struct clk_fixed_factor s4_fclk_div3_div = { + .mult = 1, + .div = 3, + .hw.init = &(struct clk_init_data){ + .name = "fclk_div3_div", + .ops = &clk_fixed_factor_ops, + .parent_hws = (const struct clk_hw *[]) { &s4_fixed_pll.hw }, + .num_parents = 1, + }, +}; + +static struct clk_regmap s4_fclk_div3 = { + .data = &(struct clk_regmap_gate_data){ + .offset = ANACTRL_FIXPLL_CTRL1, + .bit_idx = 20, + }, + .hw.init = &(struct clk_init_data){ + .name = "fclk_div3", + .ops = &clk_regmap_gate_ro_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_fclk_div3_div.hw + }, + .num_parents = 1, + }, +}; + +static struct clk_fixed_factor s4_fclk_div4_div = { + .mult = 1, + .div = 4, + .hw.init = &(struct clk_init_data){ + .name = "fclk_div4_div", + .ops = &clk_fixed_factor_ops, + .parent_hws = (const struct clk_hw *[]) { &s4_fixed_pll.hw }, + .num_parents = 1, + }, +}; + +static struct clk_regmap s4_fclk_div4 = { + .data = &(struct clk_regmap_gate_data){ + .offset = ANACTRL_FIXPLL_CTRL1, + .bit_idx = 21, + }, + .hw.init = &(struct clk_init_data){ + .name = "fclk_div4", + .ops = &clk_regmap_gate_ro_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_fclk_div4_div.hw + }, + .num_parents = 1, + }, +}; + +static struct clk_fixed_factor s4_fclk_div5_div = { + .mult = 1, + .div = 5, + .hw.init = &(struct clk_init_data){ + .name = "fclk_div5_div", + .ops = &clk_fixed_factor_ops, + .parent_hws = (const struct clk_hw *[]) { &s4_fixed_pll.hw }, + .num_parents = 1, + }, +}; + +static struct clk_regmap s4_fclk_div5 = { + .data = &(struct clk_regmap_gate_data){ + .offset = ANACTRL_FIXPLL_CTRL1, + .bit_idx = 22, + }, + .hw.init = &(struct clk_init_data){ + .name = "fclk_div5", + .ops = &clk_regmap_gate_ro_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_fclk_div5_div.hw + }, + .num_parents = 1, + }, +}; + +static struct clk_fixed_factor s4_fclk_div7_div = { + .mult = 1, + .div = 7, + .hw.init = &(struct clk_init_data){ + .name = "fclk_div7_div", + .ops = &clk_fixed_factor_ops, + .parent_hws = (const struct clk_hw *[]) { &s4_fixed_pll.hw }, + .num_parents = 1, + }, +}; + +static struct clk_regmap s4_fclk_div7 = { + .data = &(struct clk_regmap_gate_data){ + .offset = ANACTRL_FIXPLL_CTRL1, + .bit_idx = 23, + }, + .hw.init = &(struct clk_init_data){ + .name = "fclk_div7", + .ops = &clk_regmap_gate_ro_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_fclk_div7_div.hw + }, + .num_parents = 1, + }, +}; + +static struct clk_fixed_factor s4_fclk_div2p5_div = { + .mult = 2, + .div = 5, + .hw.init = &(struct clk_init_data){ + .name = "fclk_div2p5_div", + .ops = &clk_fixed_factor_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_fixed_pll.hw + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap s4_fclk_div2p5 = { + .data = &(struct clk_regmap_gate_data){ + .offset = ANACTRL_FIXPLL_CTRL1, + .bit_idx = 25, + }, + .hw.init = &(struct clk_init_data){ + .name = "fclk_div2p5", + .ops = &clk_regmap_gate_ro_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_fclk_div2p5_div.hw + }, + .num_parents = 1, + }, +}; + +static const struct pll_mult_range s4_gp0_pll_mult_range = { + .min = 125, + .max = 250, +}; + +/* + * Internal gp0 pll emulation configuration parameters + */ +static const struct reg_sequence s4_gp0_init_regs[] = { + { .reg = ANACTRL_GP0PLL_CTRL1, .def = 0x00000000 }, + { .reg = ANACTRL_GP0PLL_CTRL2, .def = 0x00000000 }, + { .reg = ANACTRL_GP0PLL_CTRL3, .def = 0x48681c00 }, + { .reg = ANACTRL_GP0PLL_CTRL4, .def = 0x88770290 }, + { .reg = ANACTRL_GP0PLL_CTRL5, .def = 0x39272000 }, + { .reg = ANACTRL_GP0PLL_CTRL6, .def = 0x56540000 } +}; + +static struct clk_regmap s4_gp0_pll_dco = { + .data = &(struct meson_clk_pll_data){ + .en = { + .reg_off = ANACTRL_GP0PLL_CTRL0, + .shift = 28, + .width = 1, + }, + .m = { + .reg_off = ANACTRL_GP0PLL_CTRL0, + .shift = 0, + .width = 8, + }, + .n = { + .reg_off = ANACTRL_GP0PLL_CTRL0, + .shift = 10, + .width = 5, + }, + .l = { + .reg_off = ANACTRL_GP0PLL_CTRL0, + .shift = 31, + .width = 1, + }, + .rst = { + .reg_off = ANACTRL_GP0PLL_CTRL0, + .shift = 29, + .width = 1, + }, + .range = &s4_gp0_pll_mult_range, + .init_regs = s4_gp0_init_regs, + .init_count = ARRAY_SIZE(s4_gp0_init_regs), + }, + .hw.init = &(struct clk_init_data){ + .name = "gp0_pll_dco", + .ops = &meson_clk_pll_ops, + .parent_data = (const struct clk_parent_data []) { + { .fw_name = "xtal", } + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap s4_gp0_pll = { + .data = &(struct clk_regmap_div_data){ + .offset = ANACTRL_GP0PLL_CTRL0, + .shift = 16, + .width = 3, + .flags = (CLK_DIVIDER_POWER_OF_TWO | + CLK_DIVIDER_ROUND_CLOSEST), + }, + .hw.init = &(struct clk_init_data){ + .name = "gp0_pll", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_gp0_pll_dco.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +/* + * Internal hifi pll emulation configuration parameters + */ +static const struct reg_sequence s4_hifi_init_regs[] = { + { .reg = ANACTRL_HIFIPLL_CTRL1, .def = 0x00010e56 }, + { .reg = ANACTRL_HIFIPLL_CTRL2, .def = 0x00000000 }, + { .reg = ANACTRL_HIFIPLL_CTRL3, .def = 0x6a285c00 }, + { .reg = ANACTRL_HIFIPLL_CTRL4, .def = 0x65771290 }, + { .reg = ANACTRL_HIFIPLL_CTRL5, .def = 0x39272000 }, + { .reg = ANACTRL_HIFIPLL_CTRL6, .def = 0x56540000 } +}; + +static struct clk_regmap s4_hifi_pll_dco = { + .data = &(struct meson_clk_pll_data){ + .en = { + .reg_off = ANACTRL_HIFIPLL_CTRL0, + .shift = 28, + .width = 1, + }, + .m = { + .reg_off = ANACTRL_HIFIPLL_CTRL0, + .shift = 0, + .width = 8, + }, + .n = { + .reg_off = ANACTRL_HIFIPLL_CTRL0, + .shift = 10, + .width = 5, + }, + .l = { + .reg_off = ANACTRL_HIFIPLL_CTRL0, + .shift = 31, + .width = 1, + }, + .rst = { + .reg_off = ANACTRL_HIFIPLL_CTRL0, + .shift = 29, + .width = 1, + }, + .range = &s4_gp0_pll_mult_range, + .init_regs = s4_hifi_init_regs, + .init_count = ARRAY_SIZE(s4_hifi_init_regs), + .flags = CLK_MESON_PLL_ROUND_CLOSEST, + }, + .hw.init = &(struct clk_init_data){ + .name = "hifi_pll_dco", + .ops = &meson_clk_pll_ops, + .parent_data = (const struct clk_parent_data []) { + { .fw_name = "xtal", } + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap s4_hifi_pll = { + .data = &(struct clk_regmap_div_data){ + .offset = ANACTRL_HIFIPLL_CTRL0, + .shift = 16, + .width = 2, + .flags = (CLK_DIVIDER_POWER_OF_TWO | + CLK_DIVIDER_ROUND_CLOSEST), + }, + .hw.init = &(struct clk_init_data){ + .name = "hifi_pll", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_hifi_pll_dco.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap s4_hdmi_pll_dco = { + .data = &(struct meson_clk_pll_data){ + .en = { + .reg_off = ANACTRL_HDMIPLL_CTRL0, + .shift = 28, + .width = 1, + }, + .m = { + .reg_off = ANACTRL_HDMIPLL_CTRL0, + .shift = 0, + .width = 8, + }, + .n = { + .reg_off = ANACTRL_HDMIPLL_CTRL0, + .shift = 10, + .width = 5, + }, + .l = { + .reg_off = ANACTRL_HDMIPLL_CTRL0, + .shift = 31, + .width = 1, + }, + .rst = { + .reg_off = ANACTRL_HDMIPLL_CTRL0, + .shift = 29, + .width = 1, + }, + .range = &s4_gp0_pll_mult_range, + }, + .hw.init = &(struct clk_init_data){ + .name = "hdmi_pll_dco", + .ops = &meson_clk_pll_ops, + .parent_data = (const struct clk_parent_data []) { + { .fw_name = "xtal", } + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap s4_hdmi_pll_od = { + .data = &(struct clk_regmap_div_data){ + .offset = ANACTRL_HDMIPLL_CTRL0, + .shift = 16, + .width = 4, + .flags = CLK_DIVIDER_POWER_OF_TWO, + }, + .hw.init = &(struct clk_init_data){ + .name = "hdmi_pll_od", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_hdmi_pll_dco.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap s4_hdmi_pll = { + .data = &(struct clk_regmap_div_data){ + .offset = ANACTRL_HDMIPLL_CTRL0, + .shift = 20, + .width = 2, + .flags = CLK_DIVIDER_POWER_OF_TWO, + }, + .hw.init = &(struct clk_init_data){ + .name = "hdmi_pll", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_hdmi_pll_od.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_fixed_factor s4_mpll_50m_div = { + .mult = 1, + .div = 80, + .hw.init = &(struct clk_init_data){ + .name = "mpll_50m_div", + .ops = &clk_fixed_factor_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_fixed_pll_dco.hw + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap s4_mpll_50m = { + .data = &(struct clk_regmap_mux_data){ + .offset = ANACTRL_FIXPLL_CTRL3, + .mask = 0x1, + .shift = 5, + }, + .hw.init = &(struct clk_init_data){ + .name = "mpll_50m", + .ops = &clk_regmap_mux_ro_ops, + .parent_data = (const struct clk_parent_data []) { + { .fw_name = "xtal", }, + { .hw = &s4_mpll_50m_div.hw }, + }, + .num_parents = 2, + }, +}; + +static struct clk_fixed_factor s4_mpll_prediv = { + .mult = 1, + .div = 2, + .hw.init = &(struct clk_init_data){ + .name = "mpll_prediv", + .ops = &clk_fixed_factor_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_fixed_pll_dco.hw + }, + .num_parents = 1, + }, +}; + +static const struct reg_sequence s4_mpll0_init_regs[] = { + { .reg = ANACTRL_MPLL_CTRL2, .def = 0x40000033 } +}; + +static struct clk_regmap s4_mpll0_div = { + .data = &(struct meson_clk_mpll_data){ + .sdm = { + .reg_off = ANACTRL_MPLL_CTRL1, + .shift = 0, + .width = 14, + }, + .sdm_en = { + .reg_off = ANACTRL_MPLL_CTRL1, + .shift = 30, + .width = 1, + }, + .n2 = { + .reg_off = ANACTRL_MPLL_CTRL1, + .shift = 20, + .width = 9, + }, + .ssen = { + .reg_off = ANACTRL_MPLL_CTRL1, + .shift = 29, + .width = 1, + }, + .lock = &meson_clk_lock, + .init_regs = s4_mpll0_init_regs, + .init_count = ARRAY_SIZE(s4_mpll0_init_regs), + }, + .hw.init = &(struct clk_init_data){ + .name = "mpll0_div", + .ops = &meson_clk_mpll_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_mpll_prediv.hw + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap s4_mpll0 = { + .data = &(struct clk_regmap_gate_data){ + .offset = ANACTRL_MPLL_CTRL1, + .bit_idx = 31, + }, + .hw.init = &(struct clk_init_data){ + .name = "mpll0", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { &s4_mpll0_div.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static const struct reg_sequence s4_mpll1_init_regs[] = { + { .reg = ANACTRL_MPLL_CTRL4, .def = 0x40000033 } +}; + +static struct clk_regmap s4_mpll1_div = { + .data = &(struct meson_clk_mpll_data){ + .sdm = { + .reg_off = ANACTRL_MPLL_CTRL3, + .shift = 0, + .width = 14, + }, + .sdm_en = { + .reg_off = ANACTRL_MPLL_CTRL3, + .shift = 30, + .width = 1, + }, + .n2 = { + .reg_off = ANACTRL_MPLL_CTRL3, + .shift = 20, + .width = 9, + }, + .ssen = { + .reg_off = ANACTRL_MPLL_CTRL3, + .shift = 29, + .width = 1, + }, + .lock = &meson_clk_lock, + .init_regs = s4_mpll1_init_regs, + .init_count = ARRAY_SIZE(s4_mpll1_init_regs), + }, + .hw.init = &(struct clk_init_data){ + .name = "mpll1_div", + .ops = &meson_clk_mpll_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_mpll_prediv.hw + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap s4_mpll1 = { + .data = &(struct clk_regmap_gate_data){ + .offset = ANACTRL_MPLL_CTRL3, + .bit_idx = 31, + }, + .hw.init = &(struct clk_init_data){ + .name = "mpll1", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { &s4_mpll1_div.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static const struct reg_sequence s4_mpll2_init_regs[] = { + { .reg = ANACTRL_MPLL_CTRL6, .def = 0x40000033 } +}; + +static struct clk_regmap s4_mpll2_div = { + .data = &(struct meson_clk_mpll_data){ + .sdm = { + .reg_off = ANACTRL_MPLL_CTRL5, + .shift = 0, + .width = 14, + }, + .sdm_en = { + .reg_off = ANACTRL_MPLL_CTRL5, + .shift = 30, + .width = 1, + }, + .n2 = { + .reg_off = ANACTRL_MPLL_CTRL5, + .shift = 20, + .width = 9, + }, + .ssen = { + .reg_off = ANACTRL_MPLL_CTRL5, + .shift = 29, + .width = 1, + }, + .lock = &meson_clk_lock, + .init_regs = s4_mpll2_init_regs, + .init_count = ARRAY_SIZE(s4_mpll2_init_regs), + }, + .hw.init = &(struct clk_init_data){ + .name = "mpll2_div", + .ops = &meson_clk_mpll_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_mpll_prediv.hw + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap s4_mpll2 = { + .data = &(struct clk_regmap_gate_data){ + .offset = ANACTRL_MPLL_CTRL5, + .bit_idx = 31, + }, + .hw.init = &(struct clk_init_data){ + .name = "mpll2", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { &s4_mpll2_div.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static const struct reg_sequence s4_mpll3_init_regs[] = { + { .reg = ANACTRL_MPLL_CTRL8, .def = 0x40000033 } +}; + +static struct clk_regmap s4_mpll3_div = { + .data = &(struct meson_clk_mpll_data){ + .sdm = { + .reg_off = ANACTRL_MPLL_CTRL7, + .shift = 0, + .width = 14, + }, + .sdm_en = { + .reg_off = ANACTRL_MPLL_CTRL7, + .shift = 30, + .width = 1, + }, + .n2 = { + .reg_off = ANACTRL_MPLL_CTRL7, + .shift = 20, + .width = 9, + }, + .ssen = { + .reg_off = ANACTRL_MPLL_CTRL7, + .shift = 29, + .width = 1, + }, + .lock = &meson_clk_lock, + .init_regs = s4_mpll3_init_regs, + .init_count = ARRAY_SIZE(s4_mpll3_init_regs), + }, + .hw.init = &(struct clk_init_data){ + .name = "mpll3_div", + .ops = &meson_clk_mpll_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_mpll_prediv.hw + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap s4_mpll3 = { + .data = &(struct clk_regmap_gate_data){ + .offset = ANACTRL_MPLL_CTRL7, + .bit_idx = 31, + }, + .hw.init = &(struct clk_init_data){ + .name = "mpll3", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { &s4_mpll3_div.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +/* Array of all clocks provided by this provider */ +static struct clk_hw *s4_pll_hw_clks[] = { + [CLKID_FIXED_PLL_DCO] = &s4_fixed_pll_dco.hw, + [CLKID_FIXED_PLL] = &s4_fixed_pll.hw, + [CLKID_FCLK_DIV2_DIV] = &s4_fclk_div2_div.hw, + [CLKID_FCLK_DIV2] = &s4_fclk_div2.hw, + [CLKID_FCLK_DIV3_DIV] = &s4_fclk_div3_div.hw, + [CLKID_FCLK_DIV3] = &s4_fclk_div3.hw, + [CLKID_FCLK_DIV4_DIV] = &s4_fclk_div4_div.hw, + [CLKID_FCLK_DIV4] = &s4_fclk_div4.hw, + [CLKID_FCLK_DIV5_DIV] = &s4_fclk_div5_div.hw, + [CLKID_FCLK_DIV5] = &s4_fclk_div5.hw, + [CLKID_FCLK_DIV7_DIV] = &s4_fclk_div7_div.hw, + [CLKID_FCLK_DIV7] = &s4_fclk_div7.hw, + [CLKID_FCLK_DIV2P5_DIV] = &s4_fclk_div2p5_div.hw, + [CLKID_FCLK_DIV2P5] = &s4_fclk_div2p5.hw, + [CLKID_GP0_PLL_DCO] = &s4_gp0_pll_dco.hw, + [CLKID_GP0_PLL] = &s4_gp0_pll.hw, + [CLKID_HIFI_PLL_DCO] = &s4_hifi_pll_dco.hw, + [CLKID_HIFI_PLL] = &s4_hifi_pll.hw, + [CLKID_HDMI_PLL_DCO] = &s4_hdmi_pll_dco.hw, + [CLKID_HDMI_PLL_OD] = &s4_hdmi_pll_od.hw, + [CLKID_HDMI_PLL] = &s4_hdmi_pll.hw, + [CLKID_MPLL_50M_DIV] = &s4_mpll_50m_div.hw, + [CLKID_MPLL_50M] = &s4_mpll_50m.hw, + [CLKID_MPLL_PREDIV] = &s4_mpll_prediv.hw, + [CLKID_MPLL0_DIV] = &s4_mpll0_div.hw, + [CLKID_MPLL0] = &s4_mpll0.hw, + [CLKID_MPLL1_DIV] = &s4_mpll1_div.hw, + [CLKID_MPLL1] = &s4_mpll1.hw, + [CLKID_MPLL2_DIV] = &s4_mpll2_div.hw, + [CLKID_MPLL2] = &s4_mpll2.hw, + [CLKID_MPLL3_DIV] = &s4_mpll3_div.hw, + [CLKID_MPLL3] = &s4_mpll3.hw, +}; + +static struct clk_regmap *const s4_pll_clk_regmaps[] = { + &s4_fixed_pll_dco, + &s4_fixed_pll, + &s4_fclk_div2, + &s4_fclk_div3, + &s4_fclk_div4, + &s4_fclk_div5, + &s4_fclk_div7, + &s4_fclk_div2p5, + &s4_gp0_pll_dco, + &s4_gp0_pll, + &s4_hifi_pll_dco, + &s4_hifi_pll, + &s4_hdmi_pll_dco, + &s4_hdmi_pll_od, + &s4_hdmi_pll, + &s4_mpll_50m, + &s4_mpll0_div, + &s4_mpll0, + &s4_mpll1_div, + &s4_mpll1, + &s4_mpll2_div, + &s4_mpll2, + &s4_mpll3_div, + &s4_mpll3, +}; + +static const struct reg_sequence s4_init_regs[] = { + { .reg = ANACTRL_MPLL_CTRL0, .def = 0x00000543 }, +}; + +static struct regmap_config clkc_regmap_config = { + .reg_bits = 32, + .val_bits = 32, + .reg_stride = 4, +}; + +static struct meson_clk_hw_data s4_pll_clks = { + .hws = s4_pll_hw_clks, + .num = ARRAY_SIZE(s4_pll_hw_clks), +}; + +static int meson_s4_pll_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct regmap *regmap; + void __iomem *base; + int ret, i; + + base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(base)) + return dev_err_probe(dev, PTR_ERR(base), + "can't ioremap resource\n"); + + regmap = devm_regmap_init_mmio(dev, base, &clkc_regmap_config); + if (IS_ERR(regmap)) + return dev_err_probe(dev, PTR_ERR(regmap), + "can't init regmap mmio region\n"); + + ret = regmap_multi_reg_write(regmap, s4_init_regs, ARRAY_SIZE(s4_init_regs)); + if (ret) + return dev_err_probe(dev, ret, + "Failed to init registers\n"); + + /* Populate regmap for the regmap backed clocks */ + for (i = 0; i < ARRAY_SIZE(s4_pll_clk_regmaps); i++) + s4_pll_clk_regmaps[i]->map = regmap; + + /* Register clocks */ + for (i = 0; i < s4_pll_clks.num; i++) { + /* array might be sparse */ + if (!s4_pll_clks.hws[i]) + continue; + + ret = devm_clk_hw_register(dev, s4_pll_clks.hws[i]); + if (ret) + return dev_err_probe(dev, ret, + "clock[%d] registration failed\n", i); + } + + return devm_of_clk_add_hw_provider(dev, meson_clk_hw_get, + &s4_pll_clks); +} + +static const struct of_device_id clkc_match_table[] = { + { + .compatible = "amlogic,s4-pll-clkc", + }, + {} +}; + +static struct platform_driver s4_driver = { + .probe = meson_s4_pll_probe, + .driver = { + .name = "s4-pll-clkc", + .of_match_table = clkc_match_table, + }, +}; + +module_platform_driver(s4_driver); +MODULE_AUTHOR("Yu Tu "); +MODULE_LICENSE("GPL"); diff --git a/drivers/clk/meson/s4-pll.h b/drivers/clk/meson/s4-pll.h new file mode 100644 index 000000000000..ff7d58302f2a --- /dev/null +++ b/drivers/clk/meson/s4-pll.h @@ -0,0 +1,38 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR MIT) */ +/* + * Copyright (c) 2022-2023 Amlogic, inc. All rights reserved + * Author: Yu Tu + */ + +#ifndef __MESON_S4_PLL_H__ +#define __MESON_S4_PLL_H__ + +#define ANACTRL_FIXPLL_CTRL0 0x040 +#define ANACTRL_FIXPLL_CTRL1 0x044 +#define ANACTRL_FIXPLL_CTRL3 0x04c +#define ANACTRL_GP0PLL_CTRL0 0x080 +#define ANACTRL_GP0PLL_CTRL1 0x084 +#define ANACTRL_GP0PLL_CTRL2 0x088 +#define ANACTRL_GP0PLL_CTRL3 0x08c +#define ANACTRL_GP0PLL_CTRL4 0x090 +#define ANACTRL_GP0PLL_CTRL5 0x094 +#define ANACTRL_GP0PLL_CTRL6 0x098 +#define ANACTRL_HIFIPLL_CTRL0 0x100 +#define ANACTRL_HIFIPLL_CTRL1 0x104 +#define ANACTRL_HIFIPLL_CTRL2 0x108 +#define ANACTRL_HIFIPLL_CTRL3 0x10c +#define ANACTRL_HIFIPLL_CTRL4 0x110 +#define ANACTRL_HIFIPLL_CTRL5 0x114 +#define ANACTRL_HIFIPLL_CTRL6 0x118 +#define ANACTRL_MPLL_CTRL0 0x180 +#define ANACTRL_MPLL_CTRL1 0x184 +#define ANACTRL_MPLL_CTRL2 0x188 +#define ANACTRL_MPLL_CTRL3 0x18c +#define ANACTRL_MPLL_CTRL4 0x190 +#define ANACTRL_MPLL_CTRL5 0x194 +#define ANACTRL_MPLL_CTRL6 0x198 +#define ANACTRL_MPLL_CTRL7 0x19c +#define ANACTRL_MPLL_CTRL8 0x1a0 +#define ANACTRL_HDMIPLL_CTRL0 0x1c0 + +#endif /* __MESON_S4_PLL_H__ */ -- cgit v1.2.3-59-g8ed1b From 57b55c76aaf1ba50ecc6dcee5cd6843dc4d85239 Mon Sep 17 00:00:00 2001 From: Yu Tu Date: Mon, 4 Sep 2023 15:55:04 +0800 Subject: clk: meson: S4: add support for Amlogic S4 SoC peripheral clock controller Add the peripherals clock controller driver in the S4 SoC family. [jbrunet: remove extra new line at end of s4-peripherals.h] Signed-off-by: Yu Tu Link: https://lore.kernel.org/r/20230904075504.23263-5-yu.tu@amlogic.com Signed-off-by: Jerome Brunet --- drivers/clk/meson/Kconfig | 11 + drivers/clk/meson/Makefile | 1 + drivers/clk/meson/s4-peripherals.c | 3813 ++++++++++++++++++++++++++++++++++++ drivers/clk/meson/s4-peripherals.h | 56 + 4 files changed, 3881 insertions(+) create mode 100644 drivers/clk/meson/s4-peripherals.c create mode 100644 drivers/clk/meson/s4-peripherals.h diff --git a/drivers/clk/meson/Kconfig b/drivers/clk/meson/Kconfig index e90982d77598..c5303e4c1604 100644 --- a/drivers/clk/meson/Kconfig +++ b/drivers/clk/meson/Kconfig @@ -156,4 +156,15 @@ config COMMON_CLK_S4_PLL Support for the PLL clock controller on Amlogic S805X2 and S905Y4 devices, AKA S4. Say Y if you want the board to work, because PLLs are the parent of most peripherals. + +config COMMON_CLK_S4_PERIPHERALS + tristate "S4 SoC peripherals clock controllers support" + depends on ARM64 + default y + select COMMON_CLK_MESON_REGMAP + select COMMON_CLK_MESON_DUALDIV + select COMMON_CLK_MESON_VID_PLL_DIV + help + Support for the peripherals clock controller on Amlogic S805X2 and S905Y4 + devices, AKA S4. Say Y if you want S4 peripherals clock controller to work. endmenu diff --git a/drivers/clk/meson/Makefile b/drivers/clk/meson/Makefile index 612cee923890..9ee4b954c896 100644 --- a/drivers/clk/meson/Makefile +++ b/drivers/clk/meson/Makefile @@ -23,3 +23,4 @@ obj-$(CONFIG_COMMON_CLK_GXBB) += gxbb.o gxbb-aoclk.o obj-$(CONFIG_COMMON_CLK_G12A) += g12a.o g12a-aoclk.o obj-$(CONFIG_COMMON_CLK_MESON8B) += meson8b.o meson8-ddr.o obj-$(CONFIG_COMMON_CLK_S4_PLL) += s4-pll.o +obj-$(CONFIG_COMMON_CLK_S4_PERIPHERALS) += s4-peripherals.o diff --git a/drivers/clk/meson/s4-peripherals.c b/drivers/clk/meson/s4-peripherals.c new file mode 100644 index 000000000000..6c35de3d536f --- /dev/null +++ b/drivers/clk/meson/s4-peripherals.c @@ -0,0 +1,3813 @@ +// SPDX-License-Identifier: (GPL-2.0-only OR MIT) +/* + * Amlogic S4 Peripherals Clock Controller Driver + * + * Copyright (c) 2022-2023 Amlogic, inc. All rights reserved + * Author: Yu Tu + */ + +#include +#include +#include + +#include "clk-regmap.h" +#include "vid-pll-div.h" +#include "clk-dualdiv.h" +#include "s4-peripherals.h" +#include "meson-clkc-utils.h" +#include + +static struct clk_regmap s4_rtc_32k_by_oscin_clkin = { + .data = &(struct clk_regmap_gate_data){ + .offset = CLKCTRL_RTC_BY_OSCIN_CTRL0, + .bit_idx = 31, + }, + .hw.init = &(struct clk_init_data) { + .name = "rtc_32k_by_oscin_clkin", + .ops = &clk_regmap_gate_ops, + .parent_data = (const struct clk_parent_data []) { + { .fw_name = "xtal", } + }, + .num_parents = 1, + }, +}; + +static const struct meson_clk_dualdiv_param s4_32k_div_table[] = { + { + .dual = 1, + .n1 = 733, + .m1 = 8, + .n2 = 732, + .m2 = 11, + }, + {} +}; + +static struct clk_regmap s4_rtc_32k_by_oscin_div = { + .data = &(struct meson_clk_dualdiv_data){ + .n1 = { + .reg_off = CLKCTRL_RTC_BY_OSCIN_CTRL0, + .shift = 0, + .width = 12, + }, + .n2 = { + .reg_off = CLKCTRL_RTC_BY_OSCIN_CTRL0, + .shift = 12, + .width = 12, + }, + .m1 = { + .reg_off = CLKCTRL_RTC_BY_OSCIN_CTRL1, + .shift = 0, + .width = 12, + }, + .m2 = { + .reg_off = CLKCTRL_RTC_BY_OSCIN_CTRL1, + .shift = 12, + .width = 12, + }, + .dual = { + .reg_off = CLKCTRL_RTC_BY_OSCIN_CTRL0, + .shift = 28, + .width = 1, + }, + .table = s4_32k_div_table, + }, + .hw.init = &(struct clk_init_data){ + .name = "rtc_32k_by_oscin_div", + .ops = &meson_clk_dualdiv_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_rtc_32k_by_oscin_clkin.hw + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap s4_rtc_32k_by_oscin_sel = { + .data = &(struct clk_regmap_mux_data) { + .offset = CLKCTRL_RTC_BY_OSCIN_CTRL1, + .mask = 0x1, + .shift = 24, + .flags = CLK_MUX_ROUND_CLOSEST, + }, + .hw.init = &(struct clk_init_data){ + .name = "rtc_32k_by_oscin_sel", + .ops = &clk_regmap_mux_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_rtc_32k_by_oscin_div.hw, + &s4_rtc_32k_by_oscin_clkin.hw, + }, + .num_parents = 2, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap s4_rtc_32k_by_oscin = { + .data = &(struct clk_regmap_gate_data){ + .offset = CLKCTRL_RTC_BY_OSCIN_CTRL0, + .bit_idx = 30, + }, + .hw.init = &(struct clk_init_data) { + .name = "rtc_32k_by_oscin", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_rtc_32k_by_oscin_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap s4_rtc_clk = { + .data = &(struct clk_regmap_mux_data) { + .offset = CLKCTRL_RTC_CTRL, + .mask = 0x3, + .shift = 0, + .flags = CLK_MUX_ROUND_CLOSEST, + }, + .hw.init = &(struct clk_init_data){ + .name = "rtc_clk_sel", + .ops = &clk_regmap_mux_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_rtc_32k_by_oscin.hw, + &s4_rtc_32k_by_oscin_div.hw, + }, + .num_parents = 2, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +/* The index 5 is AXI_CLK, which is dedicated to AXI. So skip it. */ +static u32 mux_table_sys_ab_clk_sel[] = { 0, 1, 2, 3, 4, 6, 7 }; +static const struct clk_parent_data sys_ab_clk_parent_data[] = { + { .fw_name = "xtal" }, + { .fw_name = "fclk_div2" }, + { .fw_name = "fclk_div3" }, + { .fw_name = "fclk_div4" }, + { .fw_name = "fclk_div5" }, + { .fw_name = "fclk_div7" }, + { .hw = &s4_rtc_clk.hw } +}; + +/* + * This clock is initialized by ROMcode. + * The chip was changed SYS CLK for security reasons. SYS CLK registers are not writable + * in the kernel phase. Write of SYS related register will cause the system to crash. + * Meanwhile, these clock won't ever change at runtime. + * For the above reasons, we can only use ro_ops for SYS related clocks. + */ +static struct clk_regmap s4_sysclk_b_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = CLKCTRL_SYS_CLK_CTRL0, + .mask = 0x7, + .shift = 26, + .table = mux_table_sys_ab_clk_sel, + }, + .hw.init = &(struct clk_init_data){ + .name = "sysclk_b_sel", + .ops = &clk_regmap_mux_ro_ops, + .parent_data = sys_ab_clk_parent_data, + .num_parents = ARRAY_SIZE(sys_ab_clk_parent_data), + }, +}; + +static struct clk_regmap s4_sysclk_b_div = { + .data = &(struct clk_regmap_div_data){ + .offset = CLKCTRL_SYS_CLK_CTRL0, + .shift = 16, + .width = 10, + }, + .hw.init = &(struct clk_init_data){ + .name = "sysclk_b_div", + .ops = &clk_regmap_divider_ro_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_sysclk_b_sel.hw + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap s4_sysclk_b = { + .data = &(struct clk_regmap_gate_data){ + .offset = CLKCTRL_SYS_CLK_CTRL0, + .bit_idx = 29, + }, + .hw.init = &(struct clk_init_data) { + .name = "sysclk_b", + .ops = &clk_regmap_gate_ro_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_sysclk_b_div.hw + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap s4_sysclk_a_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = CLKCTRL_SYS_CLK_CTRL0, + .mask = 0x7, + .shift = 10, + .table = mux_table_sys_ab_clk_sel, + }, + .hw.init = &(struct clk_init_data){ + .name = "sysclk_a_sel", + .ops = &clk_regmap_mux_ro_ops, + .parent_data = sys_ab_clk_parent_data, + .num_parents = ARRAY_SIZE(sys_ab_clk_parent_data), + }, +}; + +static struct clk_regmap s4_sysclk_a_div = { + .data = &(struct clk_regmap_div_data){ + .offset = CLKCTRL_SYS_CLK_CTRL0, + .shift = 0, + .width = 10, + }, + .hw.init = &(struct clk_init_data){ + .name = "sysclk_a_div", + .ops = &clk_regmap_divider_ro_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_sysclk_a_sel.hw + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap s4_sysclk_a = { + .data = &(struct clk_regmap_gate_data){ + .offset = CLKCTRL_SYS_CLK_CTRL0, + .bit_idx = 13, + }, + .hw.init = &(struct clk_init_data) { + .name = "sysclk_a", + .ops = &clk_regmap_gate_ro_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_sysclk_a_div.hw + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap s4_sys_clk = { + .data = &(struct clk_regmap_mux_data){ + .offset = CLKCTRL_SYS_CLK_CTRL0, + .mask = 0x1, + .shift = 31, + }, + .hw.init = &(struct clk_init_data){ + .name = "sys_clk", + .ops = &clk_regmap_mux_ro_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_sysclk_a.hw, + &s4_sysclk_b.hw + }, + .num_parents = 2, + }, +}; + +static struct clk_regmap s4_ceca_32k_clkin = { + .data = &(struct clk_regmap_gate_data){ + .offset = CLKCTRL_CECA_CTRL0, + .bit_idx = 31, + }, + .hw.init = &(struct clk_init_data) { + .name = "ceca_32k_clkin", + .ops = &clk_regmap_gate_ops, + .parent_data = (const struct clk_parent_data []) { + { .fw_name = "xtal", } + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap s4_ceca_32k_div = { + .data = &(struct meson_clk_dualdiv_data){ + .n1 = { + .reg_off = CLKCTRL_CECA_CTRL0, + .shift = 0, + .width = 12, + }, + .n2 = { + .reg_off = CLKCTRL_CECA_CTRL0, + .shift = 12, + .width = 12, + }, + .m1 = { + .reg_off = CLKCTRL_CECA_CTRL1, + .shift = 0, + .width = 12, + }, + .m2 = { + .reg_off = CLKCTRL_CECA_CTRL1, + .shift = 12, + .width = 12, + }, + .dual = { + .reg_off = CLKCTRL_CECA_CTRL0, + .shift = 28, + .width = 1, + }, + .table = s4_32k_div_table, + }, + .hw.init = &(struct clk_init_data){ + .name = "ceca_32k_div", + .ops = &meson_clk_dualdiv_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_ceca_32k_clkin.hw + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap s4_ceca_32k_sel_pre = { + .data = &(struct clk_regmap_mux_data) { + .offset = CLKCTRL_CECA_CTRL1, + .mask = 0x1, + .shift = 24, + .flags = CLK_MUX_ROUND_CLOSEST, + }, + .hw.init = &(struct clk_init_data){ + .name = "ceca_32k_sel_pre", + .ops = &clk_regmap_mux_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_ceca_32k_div.hw, + &s4_ceca_32k_clkin.hw + }, + .num_parents = 2, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap s4_ceca_32k_sel = { + .data = &(struct clk_regmap_mux_data) { + .offset = CLKCTRL_CECA_CTRL1, + .mask = 0x1, + .shift = 31, + .flags = CLK_MUX_ROUND_CLOSEST, + }, + .hw.init = &(struct clk_init_data){ + .name = "ceca_32k_sel", + .ops = &clk_regmap_mux_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_ceca_32k_sel_pre.hw, + &s4_rtc_clk.hw + }, + .num_parents = 2, + }, +}; + +static struct clk_regmap s4_ceca_32k_clkout = { + .data = &(struct clk_regmap_gate_data){ + .offset = CLKCTRL_CECA_CTRL0, + .bit_idx = 30, + }, + .hw.init = &(struct clk_init_data){ + .name = "ceca_32k_clkout", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_ceca_32k_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap s4_cecb_32k_clkin = { + .data = &(struct clk_regmap_gate_data){ + .offset = CLKCTRL_CECB_CTRL0, + .bit_idx = 31, + }, + .hw.init = &(struct clk_init_data) { + .name = "cecb_32k_clkin", + .ops = &clk_regmap_gate_ops, + .parent_data = (const struct clk_parent_data []) { + { .fw_name = "xtal", } + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap s4_cecb_32k_div = { + .data = &(struct meson_clk_dualdiv_data){ + .n1 = { + .reg_off = CLKCTRL_CECB_CTRL0, + .shift = 0, + .width = 12, + }, + .n2 = { + .reg_off = CLKCTRL_CECB_CTRL0, + .shift = 12, + .width = 12, + }, + .m1 = { + .reg_off = CLKCTRL_CECB_CTRL1, + .shift = 0, + .width = 12, + }, + .m2 = { + .reg_off = CLKCTRL_CECB_CTRL1, + .shift = 12, + .width = 12, + }, + .dual = { + .reg_off = CLKCTRL_CECB_CTRL0, + .shift = 28, + .width = 1, + }, + .table = s4_32k_div_table, + }, + .hw.init = &(struct clk_init_data){ + .name = "cecb_32k_div", + .ops = &meson_clk_dualdiv_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_cecb_32k_clkin.hw + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap s4_cecb_32k_sel_pre = { + .data = &(struct clk_regmap_mux_data) { + .offset = CLKCTRL_CECB_CTRL1, + .mask = 0x1, + .shift = 24, + .flags = CLK_MUX_ROUND_CLOSEST, + }, + .hw.init = &(struct clk_init_data){ + .name = "cecb_32k_sel_pre", + .ops = &clk_regmap_mux_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_cecb_32k_div.hw, + &s4_cecb_32k_clkin.hw + }, + .num_parents = 2, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap s4_cecb_32k_sel = { + .data = &(struct clk_regmap_mux_data) { + .offset = CLKCTRL_CECB_CTRL1, + .mask = 0x1, + .shift = 31, + .flags = CLK_MUX_ROUND_CLOSEST, + }, + .hw.init = &(struct clk_init_data){ + .name = "cecb_32k_sel", + .ops = &clk_regmap_mux_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_cecb_32k_sel_pre.hw, + &s4_rtc_clk.hw + }, + .num_parents = 2, + }, +}; + +static struct clk_regmap s4_cecb_32k_clkout = { + .data = &(struct clk_regmap_gate_data){ + .offset = CLKCTRL_CECB_CTRL0, + .bit_idx = 30, + }, + .hw.init = &(struct clk_init_data){ + .name = "cecb_32k_clkout", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_cecb_32k_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static const struct clk_parent_data s4_sc_parent_data[] = { + { .fw_name = "fclk_div4" }, + { .fw_name = "fclk_div3" }, + { .fw_name = "fclk_div5" }, + { .fw_name = "xtal", } +}; + +static struct clk_regmap s4_sc_clk_mux = { + .data = &(struct clk_regmap_mux_data){ + .offset = CLKCTRL_SC_CLK_CTRL, + .mask = 0x3, + .shift = 9, + }, + .hw.init = &(struct clk_init_data) { + .name = "sc_clk_mux", + .ops = &clk_regmap_mux_ops, + .parent_data = s4_sc_parent_data, + .num_parents = ARRAY_SIZE(s4_sc_parent_data), + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap s4_sc_clk_div = { + .data = &(struct clk_regmap_div_data){ + .offset = CLKCTRL_SC_CLK_CTRL, + .shift = 0, + .width = 8, + }, + .hw.init = &(struct clk_init_data) { + .name = "sc_clk_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_sc_clk_mux.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap s4_sc_clk_gate = { + .data = &(struct clk_regmap_gate_data){ + .offset = CLKCTRL_SC_CLK_CTRL, + .bit_idx = 8, + }, + .hw.init = &(struct clk_init_data){ + .name = "sc_clk_gate", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_sc_clk_div.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap s4_12_24M_clk_gate = { + .data = &(struct clk_regmap_gate_data){ + .offset = CLKCTRL_CLK12_24_CTRL, + .bit_idx = 11, + }, + .hw.init = &(struct clk_init_data) { + .name = "12_24m_gate", + .ops = &clk_regmap_gate_ops, + .parent_data = (const struct clk_parent_data []) { + { .fw_name = "xtal", } + }, + .num_parents = 1, + }, +}; + +static struct clk_fixed_factor s4_12M_clk_div = { + .mult = 1, + .div = 2, + .hw.init = &(struct clk_init_data){ + .name = "12M", + .ops = &clk_fixed_factor_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_12_24M_clk_gate.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap s4_12_24M_clk = { + .data = &(struct clk_regmap_mux_data){ + .offset = CLKCTRL_CLK12_24_CTRL, + .mask = 0x1, + .shift = 10, + }, + .hw.init = &(struct clk_init_data) { + .name = "12_24m", + .ops = &clk_regmap_mux_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_12_24M_clk_gate.hw, + &s4_12M_clk_div.hw, + }, + .num_parents = 2, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +/* Video Clocks */ +static struct clk_regmap s4_vid_pll_div = { + .data = &(struct meson_vid_pll_div_data){ + .val = { + .reg_off = CLKCTRL_VID_PLL_CLK_DIV, + .shift = 0, + .width = 15, + }, + .sel = { + .reg_off = CLKCTRL_VID_PLL_CLK_DIV, + .shift = 16, + .width = 2, + }, + }, + .hw.init = &(struct clk_init_data) { + .name = "vid_pll_div", + /* + * TODO meson_vid_pll_div_ro_ops to meson_vid_pll_div_ops + */ + .ops = &meson_vid_pll_div_ro_ops, + .parent_data = (const struct clk_parent_data []) { + { .fw_name = "hdmi_pll", } + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap s4_vid_pll_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = CLKCTRL_VID_PLL_CLK_DIV, + .mask = 0x1, + .shift = 18, + }, + .hw.init = &(struct clk_init_data){ + .name = "vid_pll_sel", + .ops = &clk_regmap_mux_ops, + .parent_data = (const struct clk_parent_data []) { + { .hw = &s4_vid_pll_div.hw }, + { .fw_name = "hdmi_pll", } + }, + .num_parents = 2, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap s4_vid_pll = { + .data = &(struct clk_regmap_gate_data){ + .offset = CLKCTRL_VID_PLL_CLK_DIV, + .bit_idx = 19, + }, + .hw.init = &(struct clk_init_data) { + .name = "vid_pll", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_vid_pll_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static const struct clk_parent_data s4_vclk_parent_data[] = { + { .hw = &s4_vid_pll.hw }, + { .fw_name = "gp0_pll", }, + { .fw_name = "hifi_pll", }, + { .fw_name = "mpll1", }, + { .fw_name = "fclk_div3", }, + { .fw_name = "fclk_div4", }, + { .fw_name = "fclk_div5", }, + { .fw_name = "fclk_div7", }, +}; + +static struct clk_regmap s4_vclk_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = CLKCTRL_VID_CLK_CTRL, + .mask = 0x7, + .shift = 16, + }, + .hw.init = &(struct clk_init_data){ + .name = "vclk_sel", + .ops = &clk_regmap_mux_ops, + .parent_data = s4_vclk_parent_data, + .num_parents = ARRAY_SIZE(s4_vclk_parent_data), + .flags = 0, + }, +}; + +static struct clk_regmap s4_vclk2_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = CLKCTRL_VIID_CLK_CTRL, + .mask = 0x7, + .shift = 16, + }, + .hw.init = &(struct clk_init_data){ + .name = "vclk2_sel", + .ops = &clk_regmap_mux_ops, + .parent_data = s4_vclk_parent_data, + .num_parents = ARRAY_SIZE(s4_vclk_parent_data), + .flags = 0, + }, +}; + +static struct clk_regmap s4_vclk_input = { + .data = &(struct clk_regmap_gate_data){ + .offset = CLKCTRL_VID_CLK_DIV, + .bit_idx = 16, + }, + .hw.init = &(struct clk_init_data) { + .name = "vclk_input", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { &s4_vclk_sel.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap s4_vclk2_input = { + .data = &(struct clk_regmap_gate_data){ + .offset = CLKCTRL_VIID_CLK_DIV, + .bit_idx = 16, + }, + .hw.init = &(struct clk_init_data) { + .name = "vclk2_input", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { &s4_vclk2_sel.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap s4_vclk_div = { + .data = &(struct clk_regmap_div_data){ + .offset = CLKCTRL_VID_CLK_DIV, + .shift = 0, + .width = 8, + }, + .hw.init = &(struct clk_init_data){ + .name = "vclk_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_vclk_input.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap s4_vclk2_div = { + .data = &(struct clk_regmap_div_data){ + .offset = CLKCTRL_VIID_CLK_DIV, + .shift = 0, + .width = 8, + }, + .hw.init = &(struct clk_init_data){ + .name = "vclk2_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_vclk2_input.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap s4_vclk = { + .data = &(struct clk_regmap_gate_data){ + .offset = CLKCTRL_VID_CLK_CTRL, + .bit_idx = 19, + }, + .hw.init = &(struct clk_init_data) { + .name = "vclk", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { &s4_vclk_div.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap s4_vclk2 = { + .data = &(struct clk_regmap_gate_data){ + .offset = CLKCTRL_VIID_CLK_CTRL, + .bit_idx = 19, + }, + .hw.init = &(struct clk_init_data) { + .name = "vclk2", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { &s4_vclk2_div.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap s4_vclk_div1 = { + .data = &(struct clk_regmap_gate_data){ + .offset = CLKCTRL_VID_CLK_CTRL, + .bit_idx = 0, + }, + .hw.init = &(struct clk_init_data) { + .name = "vclk_div1", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { &s4_vclk.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap s4_vclk_div2_en = { + .data = &(struct clk_regmap_gate_data){ + .offset = CLKCTRL_VID_CLK_CTRL, + .bit_idx = 1, + }, + .hw.init = &(struct clk_init_data) { + .name = "vclk_div2_en", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { &s4_vclk.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap s4_vclk_div4_en = { + .data = &(struct clk_regmap_gate_data){ + .offset = CLKCTRL_VID_CLK_CTRL, + .bit_idx = 2, + }, + .hw.init = &(struct clk_init_data) { + .name = "vclk_div4_en", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { &s4_vclk.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap s4_vclk_div6_en = { + .data = &(struct clk_regmap_gate_data){ + .offset = CLKCTRL_VID_CLK_CTRL, + .bit_idx = 3, + }, + .hw.init = &(struct clk_init_data) { + .name = "vclk_div6_en", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { &s4_vclk.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap s4_vclk_div12_en = { + .data = &(struct clk_regmap_gate_data){ + .offset = CLKCTRL_VID_CLK_CTRL, + .bit_idx = 4, + }, + .hw.init = &(struct clk_init_data) { + .name = "vclk_div12_en", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { &s4_vclk.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap s4_vclk2_div1 = { + .data = &(struct clk_regmap_gate_data){ + .offset = CLKCTRL_VIID_CLK_CTRL, + .bit_idx = 0, + }, + .hw.init = &(struct clk_init_data) { + .name = "vclk2_div1", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { &s4_vclk2.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap s4_vclk2_div2_en = { + .data = &(struct clk_regmap_gate_data){ + .offset = CLKCTRL_VIID_CLK_CTRL, + .bit_idx = 1, + }, + .hw.init = &(struct clk_init_data) { + .name = "vclk2_div2_en", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { &s4_vclk2.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap s4_vclk2_div4_en = { + .data = &(struct clk_regmap_gate_data){ + .offset = CLKCTRL_VIID_CLK_CTRL, + .bit_idx = 2, + }, + .hw.init = &(struct clk_init_data) { + .name = "vclk2_div4_en", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { &s4_vclk2.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap s4_vclk2_div6_en = { + .data = &(struct clk_regmap_gate_data){ + .offset = CLKCTRL_VIID_CLK_CTRL, + .bit_idx = 3, + }, + .hw.init = &(struct clk_init_data) { + .name = "vclk2_div6_en", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { &s4_vclk2.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap s4_vclk2_div12_en = { + .data = &(struct clk_regmap_gate_data){ + .offset = CLKCTRL_VIID_CLK_CTRL, + .bit_idx = 4, + }, + .hw.init = &(struct clk_init_data) { + .name = "vclk2_div12_en", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { &s4_vclk2.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_fixed_factor s4_vclk_div2 = { + .mult = 1, + .div = 2, + .hw.init = &(struct clk_init_data){ + .name = "vclk_div2", + .ops = &clk_fixed_factor_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_vclk_div2_en.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_fixed_factor s4_vclk_div4 = { + .mult = 1, + .div = 4, + .hw.init = &(struct clk_init_data){ + .name = "vclk_div4", + .ops = &clk_fixed_factor_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_vclk_div4_en.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_fixed_factor s4_vclk_div6 = { + .mult = 1, + .div = 6, + .hw.init = &(struct clk_init_data){ + .name = "vclk_div6", + .ops = &clk_fixed_factor_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_vclk_div6_en.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_fixed_factor s4_vclk_div12 = { + .mult = 1, + .div = 12, + .hw.init = &(struct clk_init_data){ + .name = "vclk_div12", + .ops = &clk_fixed_factor_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_vclk_div12_en.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_fixed_factor s4_vclk2_div2 = { + .mult = 1, + .div = 2, + .hw.init = &(struct clk_init_data){ + .name = "vclk2_div2", + .ops = &clk_fixed_factor_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_vclk2_div2_en.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_fixed_factor s4_vclk2_div4 = { + .mult = 1, + .div = 4, + .hw.init = &(struct clk_init_data){ + .name = "vclk2_div4", + .ops = &clk_fixed_factor_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_vclk2_div4_en.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_fixed_factor s4_vclk2_div6 = { + .mult = 1, + .div = 6, + .hw.init = &(struct clk_init_data){ + .name = "vclk2_div6", + .ops = &clk_fixed_factor_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_vclk2_div6_en.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_fixed_factor s4_vclk2_div12 = { + .mult = 1, + .div = 12, + .hw.init = &(struct clk_init_data){ + .name = "vclk2_div12", + .ops = &clk_fixed_factor_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_vclk2_div12_en.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +/* The 5,6,7 indexes corresponds to no real clock, so there are not used. */ +static u32 mux_table_cts_sel[] = { 0, 1, 2, 3, 4, 8, 9, 10, 11, 12 }; +static const struct clk_hw *s4_cts_parent_hws[] = { + &s4_vclk_div1.hw, + &s4_vclk_div2.hw, + &s4_vclk_div4.hw, + &s4_vclk_div6.hw, + &s4_vclk_div12.hw, + &s4_vclk2_div1.hw, + &s4_vclk2_div2.hw, + &s4_vclk2_div4.hw, + &s4_vclk2_div6.hw, + &s4_vclk2_div12.hw +}; + +static struct clk_regmap s4_cts_enci_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = CLKCTRL_VID_CLK_DIV, + .mask = 0xf, + .shift = 28, + .table = mux_table_cts_sel, + }, + .hw.init = &(struct clk_init_data){ + .name = "cts_enci_sel", + .ops = &clk_regmap_mux_ops, + .parent_hws = s4_cts_parent_hws, + .num_parents = ARRAY_SIZE(s4_cts_parent_hws), + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap s4_cts_encp_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = CLKCTRL_VID_CLK_DIV, + .mask = 0xf, + .shift = 20, + .table = mux_table_cts_sel, + }, + .hw.init = &(struct clk_init_data){ + .name = "cts_encp_sel", + .ops = &clk_regmap_mux_ops, + .parent_hws = s4_cts_parent_hws, + .num_parents = ARRAY_SIZE(s4_cts_parent_hws), + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap s4_cts_vdac_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = CLKCTRL_VIID_CLK_DIV, + .mask = 0xf, + .shift = 28, + .table = mux_table_cts_sel, + }, + .hw.init = &(struct clk_init_data){ + .name = "cts_vdac_sel", + .ops = &clk_regmap_mux_ops, + .parent_hws = s4_cts_parent_hws, + .num_parents = ARRAY_SIZE(s4_cts_parent_hws), + .flags = CLK_SET_RATE_PARENT, + }, +}; + +/* The 5,6,7 indexes corresponds to no real clock, so there are not used. */ +static u32 mux_table_hdmi_tx_sel[] = { 0, 1, 2, 3, 4, 8, 9, 10, 11, 12 }; +static const struct clk_hw *s4_cts_hdmi_tx_parent_hws[] = { + &s4_vclk_div1.hw, + &s4_vclk_div2.hw, + &s4_vclk_div4.hw, + &s4_vclk_div6.hw, + &s4_vclk_div12.hw, + &s4_vclk2_div1.hw, + &s4_vclk2_div2.hw, + &s4_vclk2_div4.hw, + &s4_vclk2_div6.hw, + &s4_vclk2_div12.hw +}; + +static struct clk_regmap s4_hdmi_tx_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = CLKCTRL_HDMI_CLK_CTRL, + .mask = 0xf, + .shift = 16, + .table = mux_table_hdmi_tx_sel, + }, + .hw.init = &(struct clk_init_data){ + .name = "hdmi_tx_sel", + .ops = &clk_regmap_mux_ops, + .parent_hws = s4_cts_hdmi_tx_parent_hws, + .num_parents = ARRAY_SIZE(s4_cts_hdmi_tx_parent_hws), + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap s4_cts_enci = { + .data = &(struct clk_regmap_gate_data){ + .offset = CLKCTRL_VID_CLK_CTRL2, + .bit_idx = 0, + }, + .hw.init = &(struct clk_init_data) { + .name = "cts_enci", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_cts_enci_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap s4_cts_encp = { + .data = &(struct clk_regmap_gate_data){ + .offset = CLKCTRL_VID_CLK_CTRL2, + .bit_idx = 2, + }, + .hw.init = &(struct clk_init_data) { + .name = "cts_encp", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_cts_encp_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap s4_cts_vdac = { + .data = &(struct clk_regmap_gate_data){ + .offset = CLKCTRL_VID_CLK_CTRL2, + .bit_idx = 4, + }, + .hw.init = &(struct clk_init_data) { + .name = "cts_vdac", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_cts_vdac_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap s4_hdmi_tx = { + .data = &(struct clk_regmap_gate_data){ + .offset = CLKCTRL_VID_CLK_CTRL2, + .bit_idx = 5, + }, + .hw.init = &(struct clk_init_data) { + .name = "hdmi_tx", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_hdmi_tx_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +/* HDMI Clocks */ +static const struct clk_parent_data s4_hdmi_parent_data[] = { + { .fw_name = "xtal", }, + { .fw_name = "fclk_div4", }, + { .fw_name = "fclk_div3", }, + { .fw_name = "fclk_div5", } +}; + +static struct clk_regmap s4_hdmi_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = CLKCTRL_HDMI_CLK_CTRL, + .mask = 0x3, + .shift = 9, + .flags = CLK_MUX_ROUND_CLOSEST, + }, + .hw.init = &(struct clk_init_data){ + .name = "hdmi_sel", + .ops = &clk_regmap_mux_ops, + .parent_data = s4_hdmi_parent_data, + .num_parents = ARRAY_SIZE(s4_hdmi_parent_data), + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap s4_hdmi_div = { + .data = &(struct clk_regmap_div_data){ + .offset = CLKCTRL_HDMI_CLK_CTRL, + .shift = 0, + .width = 7, + }, + .hw.init = &(struct clk_init_data){ + .name = "hdmi_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { &s4_hdmi_sel.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap s4_hdmi = { + .data = &(struct clk_regmap_gate_data){ + .offset = CLKCTRL_HDMI_CLK_CTRL, + .bit_idx = 8, + }, + .hw.init = &(struct clk_init_data) { + .name = "hdmi", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { &s4_hdmi_div.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap s4_ts_clk_div = { + .data = &(struct clk_regmap_div_data){ + .offset = CLKCTRL_TS_CLK_CTRL, + .shift = 0, + .width = 8, + }, + .hw.init = &(struct clk_init_data){ + .name = "ts_clk_div", + .ops = &clk_regmap_divider_ops, + .parent_data = &(const struct clk_parent_data) { + .fw_name = "xtal", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap s4_ts_clk_gate = { + .data = &(struct clk_regmap_gate_data){ + .offset = CLKCTRL_TS_CLK_CTRL, + .bit_idx = 8, + }, + .hw.init = &(struct clk_init_data){ + .name = "ts_clk", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_ts_clk_div.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +/* + * The MALI IP is clocked by two identical clocks (mali_0 and mali_1) + * muxed by a glitch-free switch. The CCF can manage this glitch-free + * mux because it does top-to-bottom updates the each clock tree and + * switches to the "inactive" one when CLK_SET_RATE_GATE is set. + */ +static const struct clk_parent_data s4_mali_0_1_parent_data[] = { + { .fw_name = "xtal", }, + { .fw_name = "gp0_pll", }, + { .fw_name = "hifi_pll", }, + { .fw_name = "fclk_div2p5", }, + { .fw_name = "fclk_div3", }, + { .fw_name = "fclk_div4", }, + { .fw_name = "fclk_div5", }, + { .fw_name = "fclk_div7", } +}; + +static struct clk_regmap s4_mali_0_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = CLKCTRL_MALI_CLK_CTRL, + .mask = 0x7, + .shift = 9, + }, + .hw.init = &(struct clk_init_data){ + .name = "mali_0_sel", + .ops = &clk_regmap_mux_ops, + .parent_data = s4_mali_0_1_parent_data, + .num_parents = ARRAY_SIZE(s4_mali_0_1_parent_data), + /* + * Don't request the parent to change the rate because + * all GPU frequencies can be derived from the fclk_* + * clocks and one special GP0_PLL setting. This is + * important because we need the HIFI PLL clock for audio. + */ + .flags = 0, + }, +}; + +static struct clk_regmap s4_mali_0_div = { + .data = &(struct clk_regmap_div_data){ + .offset = CLKCTRL_MALI_CLK_CTRL, + .shift = 0, + .width = 7, + }, + .hw.init = &(struct clk_init_data){ + .name = "mali_0_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_mali_0_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap s4_mali_0 = { + .data = &(struct clk_regmap_gate_data){ + .offset = CLKCTRL_MALI_CLK_CTRL, + .bit_idx = 8, + }, + .hw.init = &(struct clk_init_data){ + .name = "mali_0", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_mali_0_div.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_GATE | CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap s4_mali_1_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = CLKCTRL_MALI_CLK_CTRL, + .mask = 0x7, + .shift = 25, + }, + .hw.init = &(struct clk_init_data){ + .name = "mali_1_sel", + .ops = &clk_regmap_mux_ops, + .parent_data = s4_mali_0_1_parent_data, + .num_parents = ARRAY_SIZE(s4_mali_0_1_parent_data), + .flags = 0, + }, +}; + +static struct clk_regmap s4_mali_1_div = { + .data = &(struct clk_regmap_div_data){ + .offset = CLKCTRL_MALI_CLK_CTRL, + .shift = 16, + .width = 7, + }, + .hw.init = &(struct clk_init_data){ + .name = "mali_1_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_mali_1_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap s4_mali_1 = { + .data = &(struct clk_regmap_gate_data){ + .offset = CLKCTRL_MALI_CLK_CTRL, + .bit_idx = 24, + }, + .hw.init = &(struct clk_init_data){ + .name = "mali_1", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_mali_1_div.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_GATE | CLK_SET_RATE_PARENT, + }, +}; + +static const struct clk_hw *s4_mali_parent_hws[] = { + &s4_mali_0.hw, + &s4_mali_1.hw +}; + +static struct clk_regmap s4_mali_mux = { + .data = &(struct clk_regmap_mux_data){ + .offset = CLKCTRL_MALI_CLK_CTRL, + .mask = 1, + .shift = 31, + }, + .hw.init = &(struct clk_init_data){ + .name = "mali", + .ops = &clk_regmap_mux_ops, + .parent_hws = s4_mali_parent_hws, + .num_parents = 2, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +/* VDEC clocks */ +static const struct clk_parent_data s4_dec_parent_data[] = { + { .fw_name = "fclk_div2p5", }, + { .fw_name = "fclk_div3", }, + { .fw_name = "fclk_div4", }, + { .fw_name = "fclk_div5", }, + { .fw_name = "fclk_div7", }, + { .fw_name = "hifi_pll", }, + { .fw_name = "gp0_pll", }, + { .fw_name = "xtal", } +}; + +static struct clk_regmap s4_vdec_p0_mux = { + .data = &(struct clk_regmap_mux_data){ + .offset = CLKCTRL_VDEC_CLK_CTRL, + .mask = 0x7, + .shift = 9, + .flags = CLK_MUX_ROUND_CLOSEST, + }, + .hw.init = &(struct clk_init_data) { + .name = "vdec_p0_mux", + .ops = &clk_regmap_mux_ops, + .parent_data = s4_dec_parent_data, + .num_parents = ARRAY_SIZE(s4_dec_parent_data), + .flags = 0, + }, +}; + +static struct clk_regmap s4_vdec_p0_div = { + .data = &(struct clk_regmap_div_data){ + .offset = CLKCTRL_VDEC_CLK_CTRL, + .shift = 0, + .width = 7, + .flags = CLK_DIVIDER_ROUND_CLOSEST, + }, + .hw.init = &(struct clk_init_data) { + .name = "vdec_p0_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_vdec_p0_mux.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap s4_vdec_p0 = { + .data = &(struct clk_regmap_gate_data){ + .offset = CLKCTRL_VDEC_CLK_CTRL, + .bit_idx = 8, + }, + .hw.init = &(struct clk_init_data){ + .name = "vdec_p0", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_vdec_p0_div.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap s4_vdec_p1_mux = { + .data = &(struct clk_regmap_mux_data){ + .offset = CLKCTRL_VDEC3_CLK_CTRL, + .mask = 0x7, + .shift = 9, + .flags = CLK_MUX_ROUND_CLOSEST, + }, + .hw.init = &(struct clk_init_data) { + .name = "vdec_p1_mux", + .ops = &clk_regmap_mux_ops, + .parent_data = s4_dec_parent_data, + .num_parents = ARRAY_SIZE(s4_dec_parent_data), + .flags = 0, + }, +}; + +static struct clk_regmap s4_vdec_p1_div = { + .data = &(struct clk_regmap_div_data){ + .offset = CLKCTRL_VDEC3_CLK_CTRL, + .shift = 0, + .width = 7, + .flags = CLK_DIVIDER_ROUND_CLOSEST, + }, + .hw.init = &(struct clk_init_data) { + .name = "vdec_p1_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_vdec_p1_mux.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap s4_vdec_p1 = { + .data = &(struct clk_regmap_gate_data){ + .offset = CLKCTRL_VDEC3_CLK_CTRL, + .bit_idx = 8, + }, + .hw.init = &(struct clk_init_data){ + .name = "vdec_p1", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_vdec_p1_div.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static const struct clk_hw *s4_vdec_mux_parent_hws[] = { + &s4_vdec_p0.hw, + &s4_vdec_p1.hw +}; + +static struct clk_regmap s4_vdec_mux = { + .data = &(struct clk_regmap_mux_data){ + .offset = CLKCTRL_VDEC3_CLK_CTRL, + .mask = 0x1, + .shift = 15, + }, + .hw.init = &(struct clk_init_data) { + .name = "vdec_mux", + .ops = &clk_regmap_mux_ops, + .parent_hws = s4_vdec_mux_parent_hws, + .num_parents = ARRAY_SIZE(s4_vdec_mux_parent_hws), + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap s4_hevcf_p0_mux = { + .data = &(struct clk_regmap_mux_data){ + .offset = CLKCTRL_VDEC2_CLK_CTRL, + .mask = 0x7, + .shift = 9, + .flags = CLK_MUX_ROUND_CLOSEST, + }, + .hw.init = &(struct clk_init_data) { + .name = "hevcf_p0_mux", + .ops = &clk_regmap_mux_ops, + .parent_data = s4_dec_parent_data, + .num_parents = ARRAY_SIZE(s4_dec_parent_data), + .flags = 0, + }, +}; + +static struct clk_regmap s4_hevcf_p0_div = { + .data = &(struct clk_regmap_div_data){ + .offset = CLKCTRL_VDEC2_CLK_CTRL, + .shift = 0, + .width = 7, + .flags = CLK_DIVIDER_ROUND_CLOSEST, + }, + .hw.init = &(struct clk_init_data) { + .name = "hevcf_p0_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_hevcf_p0_mux.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap s4_hevcf_p0 = { + .data = &(struct clk_regmap_gate_data){ + .offset = CLKCTRL_VDEC2_CLK_CTRL, + .bit_idx = 8, + }, + .hw.init = &(struct clk_init_data){ + .name = "hevcf_p0_gate", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_hevcf_p0_div.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap s4_hevcf_p1_mux = { + .data = &(struct clk_regmap_mux_data){ + .offset = CLKCTRL_VDEC4_CLK_CTRL, + .mask = 0x7, + .shift = 9, + .flags = CLK_MUX_ROUND_CLOSEST, + }, + .hw.init = &(struct clk_init_data) { + .name = "hevcf_p1_mux", + .ops = &clk_regmap_mux_ops, + .parent_data = s4_dec_parent_data, + .num_parents = ARRAY_SIZE(s4_dec_parent_data), + .flags = 0, + }, +}; + +static struct clk_regmap s4_hevcf_p1_div = { + .data = &(struct clk_regmap_div_data){ + .offset = CLKCTRL_VDEC4_CLK_CTRL, + .shift = 0, + .width = 7, + .flags = CLK_DIVIDER_ROUND_CLOSEST, + }, + .hw.init = &(struct clk_init_data) { + .name = "hevcf_p1_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_hevcf_p1_mux.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap s4_hevcf_p1 = { + .data = &(struct clk_regmap_gate_data){ + .offset = CLKCTRL_VDEC4_CLK_CTRL, + .bit_idx = 8, + }, + .hw.init = &(struct clk_init_data){ + .name = "hevcf_p1", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_hevcf_p1_div.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static const struct clk_hw *s4_hevcf_mux_parent_hws[] = { + &s4_hevcf_p0.hw, + &s4_hevcf_p1.hw +}; + +static struct clk_regmap s4_hevcf_mux = { + .data = &(struct clk_regmap_mux_data){ + .offset = CLKCTRL_VDEC4_CLK_CTRL, + .mask = 0x1, + .shift = 15, + }, + .hw.init = &(struct clk_init_data) { + .name = "hevcf", + .ops = &clk_regmap_mux_ops, + .parent_hws = s4_hevcf_mux_parent_hws, + .num_parents = ARRAY_SIZE(s4_hevcf_mux_parent_hws), + .flags = CLK_SET_RATE_PARENT, + }, +}; + +/* VPU Clock */ +static const struct clk_parent_data s4_vpu_parent_data[] = { + { .fw_name = "fclk_div3", }, + { .fw_name = "fclk_div4", }, + { .fw_name = "fclk_div5", }, + { .fw_name = "fclk_div7", }, + { .fw_name = "mpll1", }, + { .hw = &s4_vid_pll.hw }, + { .fw_name = "hifi_pll", }, + { .fw_name = "gp0_pll", }, +}; + +static struct clk_regmap s4_vpu_0_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = CLKCTRL_VPU_CLK_CTRL, + .mask = 0x7, + .shift = 9, + }, + .hw.init = &(struct clk_init_data){ + .name = "vpu_0_sel", + .ops = &clk_regmap_mux_ops, + .parent_data = s4_vpu_parent_data, + .num_parents = ARRAY_SIZE(s4_vpu_parent_data), + .flags = 0, + }, +}; + +static struct clk_regmap s4_vpu_0_div = { + .data = &(struct clk_regmap_div_data){ + .offset = CLKCTRL_VPU_CLK_CTRL, + .shift = 0, + .width = 7, + }, + .hw.init = &(struct clk_init_data){ + .name = "vpu_0_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { &s4_vpu_0_sel.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap s4_vpu_0 = { + .data = &(struct clk_regmap_gate_data){ + .offset = CLKCTRL_VPU_CLK_CTRL, + .bit_idx = 8, + }, + .hw.init = &(struct clk_init_data) { + .name = "vpu_0", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { &s4_vpu_0_div.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap s4_vpu_1_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = CLKCTRL_VPU_CLK_CTRL, + .mask = 0x7, + .shift = 25, + }, + .hw.init = &(struct clk_init_data){ + .name = "vpu_1_sel", + .ops = &clk_regmap_mux_ops, + .parent_data = s4_vpu_parent_data, + .num_parents = ARRAY_SIZE(s4_vpu_parent_data), + .flags = 0, + }, +}; + +static struct clk_regmap s4_vpu_1_div = { + .data = &(struct clk_regmap_div_data){ + .offset = CLKCTRL_VPU_CLK_CTRL, + .shift = 16, + .width = 7, + }, + .hw.init = &(struct clk_init_data){ + .name = "vpu_1_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { &s4_vpu_1_sel.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap s4_vpu_1 = { + .data = &(struct clk_regmap_gate_data){ + .offset = CLKCTRL_VPU_CLK_CTRL, + .bit_idx = 24, + }, + .hw.init = &(struct clk_init_data) { + .name = "vpu_1", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { &s4_vpu_1_div.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap s4_vpu = { + .data = &(struct clk_regmap_mux_data){ + .offset = CLKCTRL_VPU_CLK_CTRL, + .mask = 1, + .shift = 31, + }, + .hw.init = &(struct clk_init_data){ + .name = "vpu", + .ops = &clk_regmap_mux_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_vpu_0.hw, + &s4_vpu_1.hw, + }, + .num_parents = 2, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static const struct clk_parent_data vpu_clkb_tmp_parent_data[] = { + { .hw = &s4_vpu.hw }, + { .fw_name = "fclk_div4", }, + { .fw_name = "fclk_div5", }, + { .fw_name = "fclk_div7", } +}; + +static struct clk_regmap s4_vpu_clkb_tmp_mux = { + .data = &(struct clk_regmap_mux_data){ + .offset = CLKCTRL_VPU_CLKB_CTRL, + .mask = 0x3, + .shift = 20, + }, + .hw.init = &(struct clk_init_data) { + .name = "vpu_clkb_tmp_mux", + .ops = &clk_regmap_mux_ops, + .parent_data = vpu_clkb_tmp_parent_data, + .num_parents = ARRAY_SIZE(vpu_clkb_tmp_parent_data), + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap s4_vpu_clkb_tmp_div = { + .data = &(struct clk_regmap_div_data){ + .offset = CLKCTRL_VPU_CLKB_CTRL, + .shift = 16, + .width = 4, + }, + .hw.init = &(struct clk_init_data) { + .name = "vpu_clkb_tmp_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_vpu_clkb_tmp_mux.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap s4_vpu_clkb_tmp = { + .data = &(struct clk_regmap_gate_data){ + .offset = CLKCTRL_VPU_CLKB_CTRL, + .bit_idx = 24, + }, + .hw.init = &(struct clk_init_data){ + .name = "vpu_clkb_tmp", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_vpu_clkb_tmp_div.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap s4_vpu_clkb_div = { + .data = &(struct clk_regmap_div_data){ + .offset = CLKCTRL_VPU_CLKB_CTRL, + .shift = 0, + .width = 8, + }, + .hw.init = &(struct clk_init_data) { + .name = "vpu_clkb_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_vpu_clkb_tmp.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap s4_vpu_clkb = { + .data = &(struct clk_regmap_gate_data){ + .offset = CLKCTRL_VPU_CLKB_CTRL, + .bit_idx = 8, + }, + .hw.init = &(struct clk_init_data){ + .name = "vpu_clkb", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_vpu_clkb_div.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static const struct clk_parent_data s4_vpu_clkc_parent_data[] = { + { .fw_name = "fclk_div4", }, + { .fw_name = "fclk_div3", }, + { .fw_name = "fclk_div5", }, + { .fw_name = "fclk_div7", }, + { .fw_name = "mpll1", }, + { .hw = &s4_vid_pll.hw }, + { .fw_name = "mpll2", }, + { .fw_name = "gp0_pll", }, +}; + +static struct clk_regmap s4_vpu_clkc_p0_mux = { + .data = &(struct clk_regmap_mux_data){ + .offset = CLKCTRL_VPU_CLKC_CTRL, + .mask = 0x7, + .shift = 9, + }, + .hw.init = &(struct clk_init_data) { + .name = "vpu_clkc_p0_mux", + .ops = &clk_regmap_mux_ops, + .parent_data = s4_vpu_clkc_parent_data, + .num_parents = ARRAY_SIZE(s4_vpu_clkc_parent_data), + .flags = 0, + }, +}; + +static struct clk_regmap s4_vpu_clkc_p0_div = { + .data = &(struct clk_regmap_div_data){ + .offset = CLKCTRL_VPU_CLKC_CTRL, + .shift = 0, + .width = 7, + }, + .hw.init = &(struct clk_init_data) { + .name = "vpu_clkc_p0_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_vpu_clkc_p0_mux.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap s4_vpu_clkc_p0 = { + .data = &(struct clk_regmap_gate_data){ + .offset = CLKCTRL_VPU_CLKC_CTRL, + .bit_idx = 8, + }, + .hw.init = &(struct clk_init_data){ + .name = "vpu_clkc_p0", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_vpu_clkc_p0_div.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap s4_vpu_clkc_p1_mux = { + .data = &(struct clk_regmap_mux_data){ + .offset = CLKCTRL_VPU_CLKC_CTRL, + .mask = 0x7, + .shift = 25, + }, + .hw.init = &(struct clk_init_data) { + .name = "vpu_clkc_p1_mux", + .ops = &clk_regmap_mux_ops, + .parent_data = s4_vpu_clkc_parent_data, + .num_parents = ARRAY_SIZE(s4_vpu_clkc_parent_data), + .flags = 0, + }, +}; + +static struct clk_regmap s4_vpu_clkc_p1_div = { + .data = &(struct clk_regmap_div_data){ + .offset = CLKCTRL_VPU_CLKC_CTRL, + .shift = 16, + .width = 7, + }, + .hw.init = &(struct clk_init_data) { + .name = "vpu_clkc_p1_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_vpu_clkc_p1_mux.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap s4_vpu_clkc_p1 = { + .data = &(struct clk_regmap_gate_data){ + .offset = CLKCTRL_VPU_CLKC_CTRL, + .bit_idx = 24, + }, + .hw.init = &(struct clk_init_data){ + .name = "vpu_clkc_p1", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_vpu_clkc_p1_div.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static const struct clk_hw *s4_vpu_mux_parent_hws[] = { + &s4_vpu_clkc_p0.hw, + &s4_vpu_clkc_p1.hw +}; + +static struct clk_regmap s4_vpu_clkc_mux = { + .data = &(struct clk_regmap_mux_data){ + .offset = CLKCTRL_VPU_CLKC_CTRL, + .mask = 0x1, + .shift = 31, + }, + .hw.init = &(struct clk_init_data) { + .name = "vpu_clkc_mux", + .ops = &clk_regmap_mux_ops, + .parent_hws = s4_vpu_mux_parent_hws, + .num_parents = ARRAY_SIZE(s4_vpu_mux_parent_hws), + .flags = CLK_SET_RATE_PARENT, + }, +}; + +/* VAPB Clock */ +static const struct clk_parent_data s4_vapb_parent_data[] = { + { .fw_name = "fclk_div4", }, + { .fw_name = "fclk_div3", }, + { .fw_name = "fclk_div5", }, + { .fw_name = "fclk_div7", }, + { .fw_name = "mpll1", }, + { .hw = &s4_vid_pll.hw }, + { .fw_name = "mpll2", }, + { .fw_name = "fclk_div2p5", }, +}; + +static struct clk_regmap s4_vapb_0_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = CLKCTRL_VAPBCLK_CTRL, + .mask = 0x7, + .shift = 9, + }, + .hw.init = &(struct clk_init_data){ + .name = "vapb_0_sel", + .ops = &clk_regmap_mux_ops, + .parent_data = s4_vapb_parent_data, + .num_parents = ARRAY_SIZE(s4_vapb_parent_data), + .flags = 0, + }, +}; + +static struct clk_regmap s4_vapb_0_div = { + .data = &(struct clk_regmap_div_data){ + .offset = CLKCTRL_VAPBCLK_CTRL, + .shift = 0, + .width = 7, + }, + .hw.init = &(struct clk_init_data){ + .name = "vapb_0_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_vapb_0_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap s4_vapb_0 = { + .data = &(struct clk_regmap_gate_data){ + .offset = CLKCTRL_VAPBCLK_CTRL, + .bit_idx = 8, + }, + .hw.init = &(struct clk_init_data) { + .name = "vapb_0", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_vapb_0_div.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap s4_vapb_1_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = CLKCTRL_VAPBCLK_CTRL, + .mask = 0x7, + .shift = 25, + }, + .hw.init = &(struct clk_init_data){ + .name = "vapb_1_sel", + .ops = &clk_regmap_mux_ops, + .parent_data = s4_vapb_parent_data, + .num_parents = ARRAY_SIZE(s4_vapb_parent_data), + .flags = 0, + }, +}; + +static struct clk_regmap s4_vapb_1_div = { + .data = &(struct clk_regmap_div_data){ + .offset = CLKCTRL_VAPBCLK_CTRL, + .shift = 16, + .width = 7, + }, + .hw.init = &(struct clk_init_data){ + .name = "vapb_1_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_vapb_1_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap s4_vapb_1 = { + .data = &(struct clk_regmap_gate_data){ + .offset = CLKCTRL_VAPBCLK_CTRL, + .bit_idx = 24, + }, + .hw.init = &(struct clk_init_data) { + .name = "vapb_1", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_vapb_1_div.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap s4_vapb = { + .data = &(struct clk_regmap_mux_data){ + .offset = CLKCTRL_VAPBCLK_CTRL, + .mask = 1, + .shift = 31, + }, + .hw.init = &(struct clk_init_data){ + .name = "vapb_sel", + .ops = &clk_regmap_mux_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_vapb_0.hw, + &s4_vapb_1.hw + }, + .num_parents = 2, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap s4_ge2d_gate = { + .data = &(struct clk_regmap_gate_data){ + .offset = CLKCTRL_VAPBCLK_CTRL, + .bit_idx = 30, + }, + .hw.init = &(struct clk_init_data) { + .name = "ge2d_clk", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { &s4_vapb.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static const struct clk_parent_data s4_esmclk_parent_data[] = { + { .fw_name = "fclk_div7", }, + { .fw_name = "fclk_div4", }, + { .fw_name = "fclk_div3", }, + { .fw_name = "fclk_div5", }, +}; + +static struct clk_regmap s4_hdcp22_esmclk_mux = { + .data = &(struct clk_regmap_mux_data){ + .offset = CLKCTRL_HDCP22_CTRL, + .mask = 0x3, + .shift = 9, + }, + .hw.init = &(struct clk_init_data) { + .name = "hdcp22_esmclk_mux", + .ops = &clk_regmap_mux_ops, + .parent_data = s4_esmclk_parent_data, + .num_parents = ARRAY_SIZE(s4_esmclk_parent_data), + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap s4_hdcp22_esmclk_div = { + .data = &(struct clk_regmap_div_data){ + .offset = CLKCTRL_HDCP22_CTRL, + .shift = 0, + .width = 7, + }, + .hw.init = &(struct clk_init_data) { + .name = "hdcp22_esmclk_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_hdcp22_esmclk_mux.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap s4_hdcp22_esmclk_gate = { + .data = &(struct clk_regmap_gate_data){ + .offset = CLKCTRL_HDCP22_CTRL, + .bit_idx = 8, + }, + .hw.init = &(struct clk_init_data){ + .name = "hdcp22_esmclk_gate", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_hdcp22_esmclk_div.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static const struct clk_parent_data s4_skpclk_parent_data[] = { + { .fw_name = "xtal", }, + { .fw_name = "fclk_div4", }, + { .fw_name = "fclk_div3", }, + { .fw_name = "fclk_div5", }, +}; + +static struct clk_regmap s4_hdcp22_skpclk_mux = { + .data = &(struct clk_regmap_mux_data){ + .offset = CLKCTRL_HDCP22_CTRL, + .mask = 0x3, + .shift = 25, + }, + .hw.init = &(struct clk_init_data) { + .name = "hdcp22_skpclk_mux", + .ops = &clk_regmap_mux_ops, + .parent_data = s4_skpclk_parent_data, + .num_parents = ARRAY_SIZE(s4_skpclk_parent_data), + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap s4_hdcp22_skpclk_div = { + .data = &(struct clk_regmap_div_data){ + .offset = CLKCTRL_HDCP22_CTRL, + .shift = 16, + .width = 7, + }, + .hw.init = &(struct clk_init_data) { + .name = "hdcp22_skpclk_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_hdcp22_skpclk_mux.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap s4_hdcp22_skpclk_gate = { + .data = &(struct clk_regmap_gate_data){ + .offset = CLKCTRL_HDCP22_CTRL, + .bit_idx = 24, + }, + .hw.init = &(struct clk_init_data){ + .name = "hdcp22_skpclk_gate", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_hdcp22_skpclk_div.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static const struct clk_parent_data s4_vdin_parent_data[] = { + { .fw_name = "xtal", }, + { .fw_name = "fclk_div4", }, + { .fw_name = "fclk_div3", }, + { .fw_name = "fclk_div5", }, + { .hw = &s4_vid_pll.hw } +}; + +static struct clk_regmap s4_vdin_meas_mux = { + .data = &(struct clk_regmap_mux_data){ + .offset = CLKCTRL_VDIN_MEAS_CLK_CTRL, + .mask = 0x7, + .shift = 9, + }, + .hw.init = &(struct clk_init_data) { + .name = "vdin_meas_mux", + .ops = &clk_regmap_mux_ops, + .parent_data = s4_vdin_parent_data, + .num_parents = ARRAY_SIZE(s4_vdin_parent_data), + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap s4_vdin_meas_div = { + .data = &(struct clk_regmap_div_data){ + .offset = CLKCTRL_VDIN_MEAS_CLK_CTRL, + .shift = 0, + .width = 7, + }, + .hw.init = &(struct clk_init_data) { + .name = "vdin_meas_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_vdin_meas_mux.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap s4_vdin_meas_gate = { + .data = &(struct clk_regmap_gate_data){ + .offset = CLKCTRL_VDIN_MEAS_CLK_CTRL, + .bit_idx = 8, + }, + .hw.init = &(struct clk_init_data){ + .name = "vdin_meas_gate", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_vdin_meas_div.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +/* EMMC/NAND clock */ +static const struct clk_parent_data s4_sd_emmc_clk0_parent_data[] = { + { .fw_name = "xtal", }, + { .fw_name = "fclk_div2", }, + { .fw_name = "fclk_div3", }, + { .fw_name = "hifi_pll", }, + { .fw_name = "fclk_div2p5", }, + { .fw_name = "mpll2", }, + { .fw_name = "mpll3", }, + { .fw_name = "gp0_pll", }, +}; + +static struct clk_regmap s4_sd_emmc_c_clk0_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = CLKCTRL_NAND_CLK_CTRL, + .mask = 0x7, + .shift = 9, + }, + .hw.init = &(struct clk_init_data) { + .name = "sd_emmc_c_clk0_sel", + .ops = &clk_regmap_mux_ops, + .parent_data = s4_sd_emmc_clk0_parent_data, + .num_parents = ARRAY_SIZE(s4_sd_emmc_clk0_parent_data), + .flags = 0, + }, +}; + +static struct clk_regmap s4_sd_emmc_c_clk0_div = { + .data = &(struct clk_regmap_div_data){ + .offset = CLKCTRL_NAND_CLK_CTRL, + .shift = 0, + .width = 7, + }, + .hw.init = &(struct clk_init_data) { + .name = "sd_emmc_c_clk0_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_sd_emmc_c_clk0_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap s4_sd_emmc_c_clk0 = { + .data = &(struct clk_regmap_gate_data){ + .offset = CLKCTRL_NAND_CLK_CTRL, + .bit_idx = 7, + }, + .hw.init = &(struct clk_init_data){ + .name = "sd_emmc_c_clk0", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_sd_emmc_c_clk0_div.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap s4_sd_emmc_a_clk0_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = CLKCTRL_SD_EMMC_CLK_CTRL, + .mask = 0x7, + .shift = 9, + }, + .hw.init = &(struct clk_init_data) { + .name = "sd_emmc_a_clk0_sel", + .ops = &clk_regmap_mux_ops, + .parent_data = s4_sd_emmc_clk0_parent_data, + .num_parents = ARRAY_SIZE(s4_sd_emmc_clk0_parent_data), + .flags = 0, + }, +}; + +static struct clk_regmap s4_sd_emmc_a_clk0_div = { + .data = &(struct clk_regmap_div_data){ + .offset = CLKCTRL_SD_EMMC_CLK_CTRL, + .shift = 0, + .width = 7, + }, + .hw.init = &(struct clk_init_data) { + .name = "sd_emmc_a_clk0_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_sd_emmc_a_clk0_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap s4_sd_emmc_a_clk0 = { + .data = &(struct clk_regmap_gate_data){ + .offset = CLKCTRL_SD_EMMC_CLK_CTRL, + .bit_idx = 7, + }, + .hw.init = &(struct clk_init_data){ + .name = "sd_emmc_a_clk0", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_sd_emmc_a_clk0_div.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap s4_sd_emmc_b_clk0_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = CLKCTRL_SD_EMMC_CLK_CTRL, + .mask = 0x7, + .shift = 25, + }, + .hw.init = &(struct clk_init_data) { + .name = "sd_emmc_b_clk0_sel", + .ops = &clk_regmap_mux_ops, + .parent_data = s4_sd_emmc_clk0_parent_data, + .num_parents = ARRAY_SIZE(s4_sd_emmc_clk0_parent_data), + .flags = 0, + }, +}; + +static struct clk_regmap s4_sd_emmc_b_clk0_div = { + .data = &(struct clk_regmap_div_data){ + .offset = CLKCTRL_SD_EMMC_CLK_CTRL, + .shift = 16, + .width = 7, + }, + .hw.init = &(struct clk_init_data) { + .name = "sd_emmc_b_clk0_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_sd_emmc_b_clk0_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap s4_sd_emmc_b_clk0 = { + .data = &(struct clk_regmap_gate_data){ + .offset = CLKCTRL_SD_EMMC_CLK_CTRL, + .bit_idx = 23, + }, + .hw.init = &(struct clk_init_data){ + .name = "sd_emmc_b_clk0", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_sd_emmc_b_clk0_div.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +/* SPICC Clock */ +static const struct clk_parent_data s4_spicc_parent_data[] = { + { .fw_name = "xtal", }, + { .hw = &s4_sys_clk.hw }, + { .fw_name = "fclk_div4", }, + { .fw_name = "fclk_div3", }, + { .fw_name = "fclk_div2", }, + { .fw_name = "fclk_div5", }, + { .fw_name = "fclk_div7", }, +}; + +static struct clk_regmap s4_spicc0_mux = { + .data = &(struct clk_regmap_mux_data){ + .offset = CLKCTRL_SPICC_CLK_CTRL, + .mask = 0x7, + .shift = 7, + }, + .hw.init = &(struct clk_init_data) { + .name = "spicc0_mux", + .ops = &clk_regmap_mux_ops, + .parent_data = s4_spicc_parent_data, + .num_parents = ARRAY_SIZE(s4_spicc_parent_data), + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap s4_spicc0_div = { + .data = &(struct clk_regmap_div_data){ + .offset = CLKCTRL_SPICC_CLK_CTRL, + .shift = 0, + .width = 6, + }, + .hw.init = &(struct clk_init_data) { + .name = "spicc0_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_spicc0_mux.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap s4_spicc0_gate = { + .data = &(struct clk_regmap_gate_data){ + .offset = CLKCTRL_SPICC_CLK_CTRL, + .bit_idx = 6, + }, + .hw.init = &(struct clk_init_data){ + .name = "spicc0", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_spicc0_div.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +/* PWM Clock */ +static const struct clk_parent_data s4_pwm_parent_data[] = { + { .fw_name = "xtal", }, + { .hw = &s4_vid_pll.hw }, + { .fw_name = "fclk_div4", }, + { .fw_name = "fclk_div3", }, +}; + +static struct clk_regmap s4_pwm_a_mux = { + .data = &(struct clk_regmap_mux_data) { + .offset = CLKCTRL_PWM_CLK_AB_CTRL, + .mask = 0x3, + .shift = 9, + }, + .hw.init = &(struct clk_init_data){ + .name = "pwm_a_mux", + .ops = &clk_regmap_mux_ops, + .parent_data = s4_pwm_parent_data, + .num_parents = ARRAY_SIZE(s4_pwm_parent_data), + .flags = 0, + }, +}; + +static struct clk_regmap s4_pwm_a_div = { + .data = &(struct clk_regmap_div_data) { + .offset = CLKCTRL_PWM_CLK_AB_CTRL, + .shift = 0, + .width = 8, + }, + .hw.init = &(struct clk_init_data){ + .name = "pwm_a_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_pwm_a_mux.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap s4_pwm_a_gate = { + .data = &(struct clk_regmap_gate_data) { + .offset = CLKCTRL_PWM_CLK_AB_CTRL, + .bit_idx = 8, + }, + .hw.init = &(struct clk_init_data){ + .name = "pwm_a_gate", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_pwm_a_div.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap s4_pwm_b_mux = { + .data = &(struct clk_regmap_mux_data) { + .offset = CLKCTRL_PWM_CLK_AB_CTRL, + .mask = 0x3, + .shift = 25, + }, + .hw.init = &(struct clk_init_data){ + .name = "pwm_b_mux", + .ops = &clk_regmap_mux_ops, + .parent_data = s4_pwm_parent_data, + .num_parents = ARRAY_SIZE(s4_pwm_parent_data), + .flags = 0, + }, +}; + +static struct clk_regmap s4_pwm_b_div = { + .data = &(struct clk_regmap_div_data) { + .offset = CLKCTRL_PWM_CLK_AB_CTRL, + .shift = 16, + .width = 8, + }, + .hw.init = &(struct clk_init_data){ + .name = "pwm_b_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_pwm_b_mux.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap s4_pwm_b_gate = { + .data = &(struct clk_regmap_gate_data) { + .offset = CLKCTRL_PWM_CLK_AB_CTRL, + .bit_idx = 24, + }, + .hw.init = &(struct clk_init_data){ + .name = "pwm_b_gate", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_pwm_b_div.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap s4_pwm_c_mux = { + .data = &(struct clk_regmap_mux_data) { + .offset = CLKCTRL_PWM_CLK_CD_CTRL, + .mask = 0x3, + .shift = 9, + }, + .hw.init = &(struct clk_init_data){ + .name = "pwm_c_mux", + .ops = &clk_regmap_mux_ops, + .parent_data = s4_pwm_parent_data, + .num_parents = ARRAY_SIZE(s4_pwm_parent_data), + .flags = 0, + }, +}; + +static struct clk_regmap s4_pwm_c_div = { + .data = &(struct clk_regmap_div_data) { + .offset = CLKCTRL_PWM_CLK_CD_CTRL, + .shift = 0, + .width = 8, + }, + .hw.init = &(struct clk_init_data){ + .name = "pwm_c_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_pwm_c_mux.hw + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap s4_pwm_c_gate = { + .data = &(struct clk_regmap_gate_data) { + .offset = CLKCTRL_PWM_CLK_CD_CTRL, + .bit_idx = 8, + }, + .hw.init = &(struct clk_init_data){ + .name = "pwm_c_gate", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_pwm_c_div.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap s4_pwm_d_mux = { + .data = &(struct clk_regmap_mux_data) { + .offset = CLKCTRL_PWM_CLK_CD_CTRL, + .mask = 0x3, + .shift = 25, + }, + .hw.init = &(struct clk_init_data){ + .name = "pwm_d_mux", + .ops = &clk_regmap_mux_ops, + .parent_data = s4_pwm_parent_data, + .num_parents = ARRAY_SIZE(s4_pwm_parent_data), + .flags = 0, + }, +}; + +static struct clk_regmap s4_pwm_d_div = { + .data = &(struct clk_regmap_div_data) { + .offset = CLKCTRL_PWM_CLK_CD_CTRL, + .shift = 16, + .width = 8, + }, + .hw.init = &(struct clk_init_data){ + .name = "pwm_d_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_pwm_d_mux.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap s4_pwm_d_gate = { + .data = &(struct clk_regmap_gate_data) { + .offset = CLKCTRL_PWM_CLK_CD_CTRL, + .bit_idx = 24, + }, + .hw.init = &(struct clk_init_data){ + .name = "pwm_d_gate", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_pwm_d_div.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap s4_pwm_e_mux = { + .data = &(struct clk_regmap_mux_data) { + .offset = CLKCTRL_PWM_CLK_EF_CTRL, + .mask = 0x3, + .shift = 9, + }, + .hw.init = &(struct clk_init_data){ + .name = "pwm_e_mux", + .ops = &clk_regmap_mux_ops, + .parent_data = s4_pwm_parent_data, + .num_parents = ARRAY_SIZE(s4_pwm_parent_data), + .flags = 0, + }, +}; + +static struct clk_regmap s4_pwm_e_div = { + .data = &(struct clk_regmap_div_data) { + .offset = CLKCTRL_PWM_CLK_EF_CTRL, + .shift = 0, + .width = 8, + }, + .hw.init = &(struct clk_init_data){ + .name = "pwm_e_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_pwm_e_mux.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap s4_pwm_e_gate = { + .data = &(struct clk_regmap_gate_data) { + .offset = CLKCTRL_PWM_CLK_EF_CTRL, + .bit_idx = 8, + }, + .hw.init = &(struct clk_init_data){ + .name = "pwm_e_gate", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_pwm_e_div.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap s4_pwm_f_mux = { + .data = &(struct clk_regmap_mux_data) { + .offset = CLKCTRL_PWM_CLK_EF_CTRL, + .mask = 0x3, + .shift = 25, + }, + .hw.init = &(struct clk_init_data){ + .name = "pwm_f_mux", + .ops = &clk_regmap_mux_ops, + .parent_data = s4_pwm_parent_data, + .num_parents = ARRAY_SIZE(s4_pwm_parent_data), + .flags = 0, + }, +}; + +static struct clk_regmap s4_pwm_f_div = { + .data = &(struct clk_regmap_div_data) { + .offset = CLKCTRL_PWM_CLK_EF_CTRL, + .shift = 16, + .width = 8, + }, + .hw.init = &(struct clk_init_data){ + .name = "pwm_f_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_pwm_f_mux.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap s4_pwm_f_gate = { + .data = &(struct clk_regmap_gate_data) { + .offset = CLKCTRL_PWM_CLK_EF_CTRL, + .bit_idx = 24, + }, + .hw.init = &(struct clk_init_data){ + .name = "pwm_f_gate", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_pwm_f_div.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap s4_pwm_g_mux = { + .data = &(struct clk_regmap_mux_data) { + .offset = CLKCTRL_PWM_CLK_GH_CTRL, + .mask = 0x3, + .shift = 9, + }, + .hw.init = &(struct clk_init_data){ + .name = "pwm_g_mux", + .ops = &clk_regmap_mux_ops, + .parent_data = s4_pwm_parent_data, + .num_parents = ARRAY_SIZE(s4_pwm_parent_data), + .flags = 0, + }, +}; + +static struct clk_regmap s4_pwm_g_div = { + .data = &(struct clk_regmap_div_data) { + .offset = CLKCTRL_PWM_CLK_GH_CTRL, + .shift = 0, + .width = 8, + }, + .hw.init = &(struct clk_init_data){ + .name = "pwm_g_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_pwm_g_mux.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap s4_pwm_g_gate = { + .data = &(struct clk_regmap_gate_data) { + .offset = CLKCTRL_PWM_CLK_GH_CTRL, + .bit_idx = 8, + }, + .hw.init = &(struct clk_init_data){ + .name = "pwm_g_gate", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_pwm_g_div.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap s4_pwm_h_mux = { + .data = &(struct clk_regmap_mux_data) { + .offset = CLKCTRL_PWM_CLK_GH_CTRL, + .mask = 0x3, + .shift = 25, + }, + .hw.init = &(struct clk_init_data){ + .name = "pwm_h_mux", + .ops = &clk_regmap_mux_ops, + .parent_data = s4_pwm_parent_data, + .num_parents = ARRAY_SIZE(s4_pwm_parent_data), + .flags = 0, + }, +}; + +static struct clk_regmap s4_pwm_h_div = { + .data = &(struct clk_regmap_div_data) { + .offset = CLKCTRL_PWM_CLK_GH_CTRL, + .shift = 16, + .width = 8, + }, + .hw.init = &(struct clk_init_data){ + .name = "pwm_h_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_pwm_h_mux.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap s4_pwm_h_gate = { + .data = &(struct clk_regmap_gate_data) { + .offset = CLKCTRL_PWM_CLK_GH_CTRL, + .bit_idx = 24, + }, + .hw.init = &(struct clk_init_data){ + .name = "pwm_h_gate", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_pwm_h_div.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap s4_pwm_i_mux = { + .data = &(struct clk_regmap_mux_data) { + .offset = CLKCTRL_PWM_CLK_IJ_CTRL, + .mask = 0x3, + .shift = 9, + }, + .hw.init = &(struct clk_init_data){ + .name = "pwm_i_mux", + .ops = &clk_regmap_mux_ops, + .parent_data = s4_pwm_parent_data, + .num_parents = ARRAY_SIZE(s4_pwm_parent_data), + .flags = 0, + }, +}; + +static struct clk_regmap s4_pwm_i_div = { + .data = &(struct clk_regmap_div_data) { + .offset = CLKCTRL_PWM_CLK_IJ_CTRL, + .shift = 0, + .width = 8, + }, + .hw.init = &(struct clk_init_data){ + .name = "pwm_i_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_pwm_i_mux.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap s4_pwm_i_gate = { + .data = &(struct clk_regmap_gate_data) { + .offset = CLKCTRL_PWM_CLK_IJ_CTRL, + .bit_idx = 8, + }, + .hw.init = &(struct clk_init_data){ + .name = "pwm_i_gate", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_pwm_i_div.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap s4_pwm_j_mux = { + .data = &(struct clk_regmap_mux_data) { + .offset = CLKCTRL_PWM_CLK_IJ_CTRL, + .mask = 0x3, + .shift = 25, + }, + .hw.init = &(struct clk_init_data){ + .name = "pwm_j_mux", + .ops = &clk_regmap_mux_ops, + .parent_data = s4_pwm_parent_data, + .num_parents = ARRAY_SIZE(s4_pwm_parent_data), + .flags = 0, + }, +}; + +static struct clk_regmap s4_pwm_j_div = { + .data = &(struct clk_regmap_div_data) { + .offset = CLKCTRL_PWM_CLK_IJ_CTRL, + .shift = 16, + .width = 8, + }, + .hw.init = &(struct clk_init_data){ + .name = "pwm_j_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_pwm_h_mux.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap s4_pwm_j_gate = { + .data = &(struct clk_regmap_gate_data) { + .offset = CLKCTRL_PWM_CLK_IJ_CTRL, + .bit_idx = 24, + }, + .hw.init = &(struct clk_init_data){ + .name = "pwm_j_gate", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_pwm_j_div.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap s4_saradc_mux = { + .data = &(struct clk_regmap_mux_data) { + .offset = CLKCTRL_SAR_CLK_CTRL, + .mask = 0x3, + .shift = 9, + }, + .hw.init = &(struct clk_init_data){ + .name = "saradc_mux", + .ops = &clk_regmap_mux_ops, + .parent_data = (const struct clk_parent_data []) { + { .fw_name = "xtal", }, + { .hw = &s4_sys_clk.hw }, + }, + .num_parents = 2, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap s4_saradc_div = { + .data = &(struct clk_regmap_div_data) { + .offset = CLKCTRL_SAR_CLK_CTRL, + .shift = 0, + .width = 8, + }, + .hw.init = &(struct clk_init_data){ + .name = "saradc_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_saradc_mux.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap s4_saradc_gate = { + .data = &(struct clk_regmap_gate_data) { + .offset = CLKCTRL_SAR_CLK_CTRL, + .bit_idx = 8, + }, + .hw.init = &(struct clk_init_data){ + .name = "saradc_clk", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_saradc_div.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +/* + * gen clk is designed for debug/monitor some internal clock quality. Some of the + * corresponding clock sources are not described in the clock tree and internal clock + * for debug, so they are skipped. + */ +static u32 s4_gen_clk_mux_table[] = { 0, 4, 5, 7, 19, 21, 22, + 23, 24, 25, 26, 27, 28 }; +static const struct clk_parent_data s4_gen_clk_parent_data[] = { + { .fw_name = "xtal", }, + { .hw = &s4_vid_pll.hw }, + { .fw_name = "gp0_pll", }, + { .fw_name = "hifi_pll", }, + { .fw_name = "fclk_div2", }, + { .fw_name = "fclk_div3", }, + { .fw_name = "fclk_div4", }, + { .fw_name = "fclk_div5", }, + { .fw_name = "fclk_div7", }, + { .fw_name = "mpll0", }, + { .fw_name = "mpll1", }, + { .fw_name = "mpll2", }, + { .fw_name = "mpll3", }, +}; + +static struct clk_regmap s4_gen_clk_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = CLKCTRL_GEN_CLK_CTRL, + .mask = 0x1f, + .shift = 12, + .table = s4_gen_clk_mux_table, + }, + .hw.init = &(struct clk_init_data){ + .name = "gen_clk_sel", + .ops = &clk_regmap_mux_ops, + .parent_data = s4_gen_clk_parent_data, + .num_parents = ARRAY_SIZE(s4_gen_clk_parent_data), + /* + * Because the GEN clock can be connected to an external pad + * and may be set up directly from the device tree. Don't + * really want to automatically reparent. + */ + .flags = CLK_SET_RATE_NO_REPARENT, + }, +}; + +static struct clk_regmap s4_gen_clk_div = { + .data = &(struct clk_regmap_div_data){ + .offset = CLKCTRL_GEN_CLK_CTRL, + .shift = 0, + .width = 11, + }, + .hw.init = &(struct clk_init_data){ + .name = "gen_clk_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_gen_clk_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap s4_gen_clk = { + .data = &(struct clk_regmap_gate_data){ + .offset = CLKCTRL_GEN_CLK_CTRL, + .bit_idx = 11, + }, + .hw.init = &(struct clk_init_data) { + .name = "gen_clk", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_gen_clk_div.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static const struct clk_parent_data s4_adc_extclk_in_parent_data[] = { + { .fw_name = "xtal", }, + { .fw_name = "fclk_div4", }, + { .fw_name = "fclk_div3", }, + { .fw_name = "fclk_div5", }, + { .fw_name = "fclk_div7", }, + { .fw_name = "mpll2", }, + { .fw_name = "gp0_pll", }, + { .fw_name = "hifi_pll", }, +}; + +static struct clk_regmap s4_adc_extclk_in_mux = { + .data = &(struct clk_regmap_mux_data) { + .offset = CLKCTRL_DEMOD_CLK_CTRL, + .mask = 0x7, + .shift = 25, + }, + .hw.init = &(struct clk_init_data){ + .name = "adc_extclk_in_mux", + .ops = &clk_regmap_mux_ops, + .parent_data = s4_adc_extclk_in_parent_data, + .num_parents = ARRAY_SIZE(s4_adc_extclk_in_parent_data), + .flags = 0, + }, +}; + +static struct clk_regmap s4_adc_extclk_in_div = { + .data = &(struct clk_regmap_div_data) { + .offset = CLKCTRL_DEMOD_CLK_CTRL, + .shift = 16, + .width = 7, + }, + .hw.init = &(struct clk_init_data){ + .name = "adc_extclk_in_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_adc_extclk_in_mux.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap s4_adc_extclk_in_gate = { + .data = &(struct clk_regmap_gate_data) { + .offset = CLKCTRL_DEMOD_CLK_CTRL, + .bit_idx = 24, + }, + .hw.init = &(struct clk_init_data){ + .name = "adc_extclk_in", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_adc_extclk_in_div.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap s4_demod_core_clk_mux = { + .data = &(struct clk_regmap_mux_data) { + .offset = CLKCTRL_DEMOD_CLK_CTRL, + .mask = 0x3, + .shift = 9, + }, + .hw.init = &(struct clk_init_data){ + .name = "demod_core_clk_mux", + .ops = &clk_regmap_mux_ops, + .parent_data = (const struct clk_parent_data []) { + { .fw_name = "xtal", }, + { .fw_name = "fclk_div7", }, + { .fw_name = "fclk_div4", }, + { .hw = &s4_adc_extclk_in_gate.hw } + }, + .num_parents = 4, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap s4_demod_core_clk_div = { + .data = &(struct clk_regmap_div_data) { + .offset = CLKCTRL_DEMOD_CLK_CTRL, + .shift = 0, + .width = 7, + }, + .hw.init = &(struct clk_init_data){ + .name = "demod_core_clk_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_demod_core_clk_mux.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap s4_demod_core_clk_gate = { + .data = &(struct clk_regmap_gate_data) { + .offset = CLKCTRL_DEMOD_CLK_CTRL, + .bit_idx = 8, + }, + .hw.init = &(struct clk_init_data){ + .name = "demod_core_clk", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &s4_demod_core_clk_div.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +#define MESON_GATE(_name, _reg, _bit) \ + MESON_PCLK(_name, _reg, _bit, &s4_sys_clk.hw) + +static MESON_GATE(s4_ddr, CLKCTRL_SYS_CLK_EN0_REG0, 0); +static MESON_GATE(s4_dos, CLKCTRL_SYS_CLK_EN0_REG0, 1); +static MESON_GATE(s4_ethphy, CLKCTRL_SYS_CLK_EN0_REG0, 4); +static MESON_GATE(s4_mali, CLKCTRL_SYS_CLK_EN0_REG0, 6); +static MESON_GATE(s4_aocpu, CLKCTRL_SYS_CLK_EN0_REG0, 13); +static MESON_GATE(s4_aucpu, CLKCTRL_SYS_CLK_EN0_REG0, 14); +static MESON_GATE(s4_cec, CLKCTRL_SYS_CLK_EN0_REG0, 16); +static MESON_GATE(s4_sdemmca, CLKCTRL_SYS_CLK_EN0_REG0, 24); +static MESON_GATE(s4_sdemmcb, CLKCTRL_SYS_CLK_EN0_REG0, 25); +static MESON_GATE(s4_nand, CLKCTRL_SYS_CLK_EN0_REG0, 26); +static MESON_GATE(s4_smartcard, CLKCTRL_SYS_CLK_EN0_REG0, 27); +static MESON_GATE(s4_acodec, CLKCTRL_SYS_CLK_EN0_REG0, 28); +static MESON_GATE(s4_spifc, CLKCTRL_SYS_CLK_EN0_REG0, 29); +static MESON_GATE(s4_msr_clk, CLKCTRL_SYS_CLK_EN0_REG0, 30); +static MESON_GATE(s4_ir_ctrl, CLKCTRL_SYS_CLK_EN0_REG0, 31); +static MESON_GATE(s4_audio, CLKCTRL_SYS_CLK_EN0_REG1, 0); +static MESON_GATE(s4_eth, CLKCTRL_SYS_CLK_EN0_REG1, 3); +static MESON_GATE(s4_uart_a, CLKCTRL_SYS_CLK_EN0_REG1, 5); +static MESON_GATE(s4_uart_b, CLKCTRL_SYS_CLK_EN0_REG1, 6); +static MESON_GATE(s4_uart_c, CLKCTRL_SYS_CLK_EN0_REG1, 7); +static MESON_GATE(s4_uart_d, CLKCTRL_SYS_CLK_EN0_REG1, 8); +static MESON_GATE(s4_uart_e, CLKCTRL_SYS_CLK_EN0_REG1, 9); +static MESON_GATE(s4_aififo, CLKCTRL_SYS_CLK_EN0_REG1, 11); +static MESON_GATE(s4_ts_ddr, CLKCTRL_SYS_CLK_EN0_REG1, 15); +static MESON_GATE(s4_ts_pll, CLKCTRL_SYS_CLK_EN0_REG1, 16); +static MESON_GATE(s4_g2d, CLKCTRL_SYS_CLK_EN0_REG1, 20); +static MESON_GATE(s4_spicc0, CLKCTRL_SYS_CLK_EN0_REG1, 21); +static MESON_GATE(s4_usb, CLKCTRL_SYS_CLK_EN0_REG1, 26); +static MESON_GATE(s4_i2c_m_a, CLKCTRL_SYS_CLK_EN0_REG1, 30); +static MESON_GATE(s4_i2c_m_b, CLKCTRL_SYS_CLK_EN0_REG1, 31); +static MESON_GATE(s4_i2c_m_c, CLKCTRL_SYS_CLK_EN0_REG2, 0); +static MESON_GATE(s4_i2c_m_d, CLKCTRL_SYS_CLK_EN0_REG2, 1); +static MESON_GATE(s4_i2c_m_e, CLKCTRL_SYS_CLK_EN0_REG2, 2); +static MESON_GATE(s4_hdmitx_apb, CLKCTRL_SYS_CLK_EN0_REG2, 4); +static MESON_GATE(s4_i2c_s_a, CLKCTRL_SYS_CLK_EN0_REG2, 5); +static MESON_GATE(s4_usb1_to_ddr, CLKCTRL_SYS_CLK_EN0_REG2, 8); +static MESON_GATE(s4_hdcp22, CLKCTRL_SYS_CLK_EN0_REG2, 10); +static MESON_GATE(s4_mmc_apb, CLKCTRL_SYS_CLK_EN0_REG2, 11); +static MESON_GATE(s4_rsa, CLKCTRL_SYS_CLK_EN0_REG2, 18); +static MESON_GATE(s4_cpu_debug, CLKCTRL_SYS_CLK_EN0_REG2, 19); +static MESON_GATE(s4_vpu_intr, CLKCTRL_SYS_CLK_EN0_REG2, 25); +static MESON_GATE(s4_demod, CLKCTRL_SYS_CLK_EN0_REG2, 27); +static MESON_GATE(s4_sar_adc, CLKCTRL_SYS_CLK_EN0_REG2, 28); +static MESON_GATE(s4_gic, CLKCTRL_SYS_CLK_EN0_REG2, 30); +static MESON_GATE(s4_pwm_ab, CLKCTRL_SYS_CLK_EN0_REG3, 7); +static MESON_GATE(s4_pwm_cd, CLKCTRL_SYS_CLK_EN0_REG3, 8); +static MESON_GATE(s4_pwm_ef, CLKCTRL_SYS_CLK_EN0_REG3, 9); +static MESON_GATE(s4_pwm_gh, CLKCTRL_SYS_CLK_EN0_REG3, 10); +static MESON_GATE(s4_pwm_ij, CLKCTRL_SYS_CLK_EN0_REG3, 11); + +/* Array of all clocks provided by this provider */ +static struct clk_hw *s4_periphs_hw_clks[] = { + [CLKID_RTC_32K_CLKIN] = &s4_rtc_32k_by_oscin_clkin.hw, + [CLKID_RTC_32K_DIV] = &s4_rtc_32k_by_oscin_div.hw, + [CLKID_RTC_32K_SEL] = &s4_rtc_32k_by_oscin_sel.hw, + [CLKID_RTC_32K_XATL] = &s4_rtc_32k_by_oscin.hw, + [CLKID_RTC] = &s4_rtc_clk.hw, + [CLKID_SYS_CLK_B_SEL] = &s4_sysclk_b_sel.hw, + [CLKID_SYS_CLK_B_DIV] = &s4_sysclk_b_div.hw, + [CLKID_SYS_CLK_B] = &s4_sysclk_b.hw, + [CLKID_SYS_CLK_A_SEL] = &s4_sysclk_a_sel.hw, + [CLKID_SYS_CLK_A_DIV] = &s4_sysclk_a_div.hw, + [CLKID_SYS_CLK_A] = &s4_sysclk_a.hw, + [CLKID_SYS] = &s4_sys_clk.hw, + [CLKID_CECA_32K_CLKIN] = &s4_ceca_32k_clkin.hw, + [CLKID_CECA_32K_DIV] = &s4_ceca_32k_div.hw, + [CLKID_CECA_32K_SEL_PRE] = &s4_ceca_32k_sel_pre.hw, + [CLKID_CECA_32K_SEL] = &s4_ceca_32k_sel.hw, + [CLKID_CECA_32K_CLKOUT] = &s4_ceca_32k_clkout.hw, + [CLKID_CECB_32K_CLKIN] = &s4_cecb_32k_clkin.hw, + [CLKID_CECB_32K_DIV] = &s4_cecb_32k_div.hw, + [CLKID_CECB_32K_SEL_PRE] = &s4_cecb_32k_sel_pre.hw, + [CLKID_CECB_32K_SEL] = &s4_cecb_32k_sel.hw, + [CLKID_CECB_32K_CLKOUT] = &s4_cecb_32k_clkout.hw, + [CLKID_SC_CLK_SEL] = &s4_sc_clk_mux.hw, + [CLKID_SC_CLK_DIV] = &s4_sc_clk_div.hw, + [CLKID_SC] = &s4_sc_clk_gate.hw, + [CLKID_12_24M] = &s4_12_24M_clk_gate.hw, + [CLKID_12M_CLK_DIV] = &s4_12M_clk_div.hw, + [CLKID_12_24M_CLK_SEL] = &s4_12_24M_clk.hw, + [CLKID_VID_PLL_DIV] = &s4_vid_pll_div.hw, + [CLKID_VID_PLL_SEL] = &s4_vid_pll_sel.hw, + [CLKID_VID_PLL] = &s4_vid_pll.hw, + [CLKID_VCLK_SEL] = &s4_vclk_sel.hw, + [CLKID_VCLK2_SEL] = &s4_vclk2_sel.hw, + [CLKID_VCLK_INPUT] = &s4_vclk_input.hw, + [CLKID_VCLK2_INPUT] = &s4_vclk2_input.hw, + [CLKID_VCLK_DIV] = &s4_vclk_div.hw, + [CLKID_VCLK2_DIV] = &s4_vclk2_div.hw, + [CLKID_VCLK] = &s4_vclk.hw, + [CLKID_VCLK2] = &s4_vclk2.hw, + [CLKID_VCLK_DIV1] = &s4_vclk_div1.hw, + [CLKID_VCLK_DIV2_EN] = &s4_vclk_div2_en.hw, + [CLKID_VCLK_DIV4_EN] = &s4_vclk_div4_en.hw, + [CLKID_VCLK_DIV6_EN] = &s4_vclk_div6_en.hw, + [CLKID_VCLK_DIV12_EN] = &s4_vclk_div12_en.hw, + [CLKID_VCLK2_DIV1] = &s4_vclk2_div1.hw, + [CLKID_VCLK2_DIV2_EN] = &s4_vclk2_div2_en.hw, + [CLKID_VCLK2_DIV4_EN] = &s4_vclk2_div4_en.hw, + [CLKID_VCLK2_DIV6_EN] = &s4_vclk2_div6_en.hw, + [CLKID_VCLK2_DIV12_EN] = &s4_vclk2_div12_en.hw, + [CLKID_VCLK_DIV2] = &s4_vclk_div2.hw, + [CLKID_VCLK_DIV4] = &s4_vclk_div4.hw, + [CLKID_VCLK_DIV6] = &s4_vclk_div6.hw, + [CLKID_VCLK_DIV12] = &s4_vclk_div12.hw, + [CLKID_VCLK2_DIV2] = &s4_vclk2_div2.hw, + [CLKID_VCLK2_DIV4] = &s4_vclk2_div4.hw, + [CLKID_VCLK2_DIV6] = &s4_vclk2_div6.hw, + [CLKID_VCLK2_DIV12] = &s4_vclk2_div12.hw, + [CLKID_CTS_ENCI_SEL] = &s4_cts_enci_sel.hw, + [CLKID_CTS_ENCP_SEL] = &s4_cts_encp_sel.hw, + [CLKID_CTS_VDAC_SEL] = &s4_cts_vdac_sel.hw, + [CLKID_HDMI_TX_SEL] = &s4_hdmi_tx_sel.hw, + [CLKID_CTS_ENCI] = &s4_cts_enci.hw, + [CLKID_CTS_ENCP] = &s4_cts_encp.hw, + [CLKID_CTS_VDAC] = &s4_cts_vdac.hw, + [CLKID_HDMI_TX] = &s4_hdmi_tx.hw, + [CLKID_HDMI_SEL] = &s4_hdmi_sel.hw, + [CLKID_HDMI_DIV] = &s4_hdmi_div.hw, + [CLKID_HDMI] = &s4_hdmi.hw, + [CLKID_TS_CLK_DIV] = &s4_ts_clk_div.hw, + [CLKID_TS] = &s4_ts_clk_gate.hw, + [CLKID_MALI_0_SEL] = &s4_mali_0_sel.hw, + [CLKID_MALI_0_DIV] = &s4_mali_0_div.hw, + [CLKID_MALI_0] = &s4_mali_0.hw, + [CLKID_MALI_1_SEL] = &s4_mali_1_sel.hw, + [CLKID_MALI_1_DIV] = &s4_mali_1_div.hw, + [CLKID_MALI_1] = &s4_mali_1.hw, + [CLKID_MALI_SEL] = &s4_mali_mux.hw, + [CLKID_VDEC_P0_SEL] = &s4_vdec_p0_mux.hw, + [CLKID_VDEC_P0_DIV] = &s4_vdec_p0_div.hw, + [CLKID_VDEC_P0] = &s4_vdec_p0.hw, + [CLKID_VDEC_P1_SEL] = &s4_vdec_p1_mux.hw, + [CLKID_VDEC_P1_DIV] = &s4_vdec_p1_div.hw, + [CLKID_VDEC_P1] = &s4_vdec_p1.hw, + [CLKID_VDEC_SEL] = &s4_vdec_mux.hw, + [CLKID_HEVCF_P0_SEL] = &s4_hevcf_p0_mux.hw, + [CLKID_HEVCF_P0_DIV] = &s4_hevcf_p0_div.hw, + [CLKID_HEVCF_P0] = &s4_hevcf_p0.hw, + [CLKID_HEVCF_P1_SEL] = &s4_hevcf_p1_mux.hw, + [CLKID_HEVCF_P1_DIV] = &s4_hevcf_p1_div.hw, + [CLKID_HEVCF_P1] = &s4_hevcf_p1.hw, + [CLKID_HEVCF_SEL] = &s4_hevcf_mux.hw, + [CLKID_VPU_0_SEL] = &s4_vpu_0_sel.hw, + [CLKID_VPU_0_DIV] = &s4_vpu_0_div.hw, + [CLKID_VPU_0] = &s4_vpu_0.hw, + [CLKID_VPU_1_SEL] = &s4_vpu_1_sel.hw, + [CLKID_VPU_1_DIV] = &s4_vpu_1_div.hw, + [CLKID_VPU_1] = &s4_vpu_1.hw, + [CLKID_VPU] = &s4_vpu.hw, + [CLKID_VPU_CLKB_TMP_SEL] = &s4_vpu_clkb_tmp_mux.hw, + [CLKID_VPU_CLKB_TMP_DIV] = &s4_vpu_clkb_tmp_div.hw, + [CLKID_VPU_CLKB_TMP] = &s4_vpu_clkb_tmp.hw, + [CLKID_VPU_CLKB_DIV] = &s4_vpu_clkb_div.hw, + [CLKID_VPU_CLKB] = &s4_vpu_clkb.hw, + [CLKID_VPU_CLKC_P0_SEL] = &s4_vpu_clkc_p0_mux.hw, + [CLKID_VPU_CLKC_P0_DIV] = &s4_vpu_clkc_p0_div.hw, + [CLKID_VPU_CLKC_P0] = &s4_vpu_clkc_p0.hw, + [CLKID_VPU_CLKC_P1_SEL] = &s4_vpu_clkc_p1_mux.hw, + [CLKID_VPU_CLKC_P1_DIV] = &s4_vpu_clkc_p1_div.hw, + [CLKID_VPU_CLKC_P1] = &s4_vpu_clkc_p1.hw, + [CLKID_VPU_CLKC_SEL] = &s4_vpu_clkc_mux.hw, + [CLKID_VAPB_0_SEL] = &s4_vapb_0_sel.hw, + [CLKID_VAPB_0_DIV] = &s4_vapb_0_div.hw, + [CLKID_VAPB_0] = &s4_vapb_0.hw, + [CLKID_VAPB_1_SEL] = &s4_vapb_1_sel.hw, + [CLKID_VAPB_1_DIV] = &s4_vapb_1_div.hw, + [CLKID_VAPB_1] = &s4_vapb_1.hw, + [CLKID_VAPB] = &s4_vapb.hw, + [CLKID_GE2D] = &s4_ge2d_gate.hw, + [CLKID_VDIN_MEAS_SEL] = &s4_vdin_meas_mux.hw, + [CLKID_VDIN_MEAS_DIV] = &s4_vdin_meas_div.hw, + [CLKID_VDIN_MEAS] = &s4_vdin_meas_gate.hw, + [CLKID_SD_EMMC_C_CLK_SEL] = &s4_sd_emmc_c_clk0_sel.hw, + [CLKID_SD_EMMC_C_CLK_DIV] = &s4_sd_emmc_c_clk0_div.hw, + [CLKID_SD_EMMC_C] = &s4_sd_emmc_c_clk0.hw, + [CLKID_SD_EMMC_A_CLK_SEL] = &s4_sd_emmc_a_clk0_sel.hw, + [CLKID_SD_EMMC_A_CLK_DIV] = &s4_sd_emmc_a_clk0_div.hw, + [CLKID_SD_EMMC_A] = &s4_sd_emmc_a_clk0.hw, + [CLKID_SD_EMMC_B_CLK_SEL] = &s4_sd_emmc_b_clk0_sel.hw, + [CLKID_SD_EMMC_B_CLK_DIV] = &s4_sd_emmc_b_clk0_div.hw, + [CLKID_SD_EMMC_B] = &s4_sd_emmc_b_clk0.hw, + [CLKID_SPICC0_SEL] = &s4_spicc0_mux.hw, + [CLKID_SPICC0_DIV] = &s4_spicc0_div.hw, + [CLKID_SPICC0_EN] = &s4_spicc0_gate.hw, + [CLKID_PWM_A_SEL] = &s4_pwm_a_mux.hw, + [CLKID_PWM_A_DIV] = &s4_pwm_a_div.hw, + [CLKID_PWM_A] = &s4_pwm_a_gate.hw, + [CLKID_PWM_B_SEL] = &s4_pwm_b_mux.hw, + [CLKID_PWM_B_DIV] = &s4_pwm_b_div.hw, + [CLKID_PWM_B] = &s4_pwm_b_gate.hw, + [CLKID_PWM_C_SEL] = &s4_pwm_c_mux.hw, + [CLKID_PWM_C_DIV] = &s4_pwm_c_div.hw, + [CLKID_PWM_C] = &s4_pwm_c_gate.hw, + [CLKID_PWM_D_SEL] = &s4_pwm_d_mux.hw, + [CLKID_PWM_D_DIV] = &s4_pwm_d_div.hw, + [CLKID_PWM_D] = &s4_pwm_d_gate.hw, + [CLKID_PWM_E_SEL] = &s4_pwm_e_mux.hw, + [CLKID_PWM_E_DIV] = &s4_pwm_e_div.hw, + [CLKID_PWM_E] = &s4_pwm_e_gate.hw, + [CLKID_PWM_F_SEL] = &s4_pwm_f_mux.hw, + [CLKID_PWM_F_DIV] = &s4_pwm_f_div.hw, + [CLKID_PWM_F] = &s4_pwm_f_gate.hw, + [CLKID_PWM_G_SEL] = &s4_pwm_g_mux.hw, + [CLKID_PWM_G_DIV] = &s4_pwm_g_div.hw, + [CLKID_PWM_G] = &s4_pwm_g_gate.hw, + [CLKID_PWM_H_SEL] = &s4_pwm_h_mux.hw, + [CLKID_PWM_H_DIV] = &s4_pwm_h_div.hw, + [CLKID_PWM_H] = &s4_pwm_h_gate.hw, + [CLKID_PWM_I_SEL] = &s4_pwm_i_mux.hw, + [CLKID_PWM_I_DIV] = &s4_pwm_i_div.hw, + [CLKID_PWM_I] = &s4_pwm_i_gate.hw, + [CLKID_PWM_J_SEL] = &s4_pwm_j_mux.hw, + [CLKID_PWM_J_DIV] = &s4_pwm_j_div.hw, + [CLKID_PWM_J] = &s4_pwm_j_gate.hw, + [CLKID_SARADC_SEL] = &s4_saradc_mux.hw, + [CLKID_SARADC_DIV] = &s4_saradc_div.hw, + [CLKID_SARADC] = &s4_saradc_gate.hw, + [CLKID_GEN_SEL] = &s4_gen_clk_sel.hw, + [CLKID_GEN_DIV] = &s4_gen_clk_div.hw, + [CLKID_GEN] = &s4_gen_clk.hw, + [CLKID_DDR] = &s4_ddr.hw, + [CLKID_DOS] = &s4_dos.hw, + [CLKID_ETHPHY] = &s4_ethphy.hw, + [CLKID_MALI] = &s4_mali.hw, + [CLKID_AOCPU] = &s4_aocpu.hw, + [CLKID_AUCPU] = &s4_aucpu.hw, + [CLKID_CEC] = &s4_cec.hw, + [CLKID_SDEMMC_A] = &s4_sdemmca.hw, + [CLKID_SDEMMC_B] = &s4_sdemmcb.hw, + [CLKID_NAND] = &s4_nand.hw, + [CLKID_SMARTCARD] = &s4_smartcard.hw, + [CLKID_ACODEC] = &s4_acodec.hw, + [CLKID_SPIFC] = &s4_spifc.hw, + [CLKID_MSR] = &s4_msr_clk.hw, + [CLKID_IR_CTRL] = &s4_ir_ctrl.hw, + [CLKID_AUDIO] = &s4_audio.hw, + [CLKID_ETH] = &s4_eth.hw, + [CLKID_UART_A] = &s4_uart_a.hw, + [CLKID_UART_B] = &s4_uart_b.hw, + [CLKID_UART_C] = &s4_uart_c.hw, + [CLKID_UART_D] = &s4_uart_d.hw, + [CLKID_UART_E] = &s4_uart_e.hw, + [CLKID_AIFIFO] = &s4_aififo.hw, + [CLKID_TS_DDR] = &s4_ts_ddr.hw, + [CLKID_TS_PLL] = &s4_ts_pll.hw, + [CLKID_G2D] = &s4_g2d.hw, + [CLKID_SPICC0] = &s4_spicc0.hw, + [CLKID_USB] = &s4_usb.hw, + [CLKID_I2C_M_A] = &s4_i2c_m_a.hw, + [CLKID_I2C_M_B] = &s4_i2c_m_b.hw, + [CLKID_I2C_M_C] = &s4_i2c_m_c.hw, + [CLKID_I2C_M_D] = &s4_i2c_m_d.hw, + [CLKID_I2C_M_E] = &s4_i2c_m_e.hw, + [CLKID_HDMITX_APB] = &s4_hdmitx_apb.hw, + [CLKID_I2C_S_A] = &s4_i2c_s_a.hw, + [CLKID_USB1_TO_DDR] = &s4_usb1_to_ddr.hw, + [CLKID_HDCP22] = &s4_hdcp22.hw, + [CLKID_MMC_APB] = &s4_mmc_apb.hw, + [CLKID_RSA] = &s4_rsa.hw, + [CLKID_CPU_DEBUG] = &s4_cpu_debug.hw, + [CLKID_VPU_INTR] = &s4_vpu_intr.hw, + [CLKID_DEMOD] = &s4_demod.hw, + [CLKID_SAR_ADC] = &s4_sar_adc.hw, + [CLKID_GIC] = &s4_gic.hw, + [CLKID_PWM_AB] = &s4_pwm_ab.hw, + [CLKID_PWM_CD] = &s4_pwm_cd.hw, + [CLKID_PWM_EF] = &s4_pwm_ef.hw, + [CLKID_PWM_GH] = &s4_pwm_gh.hw, + [CLKID_PWM_IJ] = &s4_pwm_ij.hw, + [CLKID_HDCP22_ESMCLK_SEL] = &s4_hdcp22_esmclk_mux.hw, + [CLKID_HDCP22_ESMCLK_DIV] = &s4_hdcp22_esmclk_div.hw, + [CLKID_HDCP22_ESMCLK] = &s4_hdcp22_esmclk_gate.hw, + [CLKID_HDCP22_SKPCLK_SEL] = &s4_hdcp22_skpclk_mux.hw, + [CLKID_HDCP22_SKPCLK_DIV] = &s4_hdcp22_skpclk_div.hw, + [CLKID_HDCP22_SKPCLK] = &s4_hdcp22_skpclk_gate.hw, +}; + +/* Convenience table to populate regmap in .probe */ +static struct clk_regmap *const s4_periphs_clk_regmaps[] = { + &s4_rtc_32k_by_oscin_clkin, + &s4_rtc_32k_by_oscin_div, + &s4_rtc_32k_by_oscin_sel, + &s4_rtc_32k_by_oscin, + &s4_rtc_clk, + &s4_sysclk_b_sel, + &s4_sysclk_b_div, + &s4_sysclk_b, + &s4_sysclk_a_sel, + &s4_sysclk_a_div, + &s4_sysclk_a, + &s4_sys_clk, + &s4_ceca_32k_clkin, + &s4_ceca_32k_div, + &s4_ceca_32k_sel_pre, + &s4_ceca_32k_sel, + &s4_ceca_32k_clkout, + &s4_cecb_32k_clkin, + &s4_cecb_32k_div, + &s4_cecb_32k_sel_pre, + &s4_cecb_32k_sel, + &s4_cecb_32k_clkout, + &s4_sc_clk_mux, + &s4_sc_clk_div, + &s4_sc_clk_gate, + &s4_12_24M_clk_gate, + &s4_12_24M_clk, + &s4_vid_pll_div, + &s4_vid_pll_sel, + &s4_vid_pll, + &s4_vclk_sel, + &s4_vclk2_sel, + &s4_vclk_input, + &s4_vclk2_input, + &s4_vclk_div, + &s4_vclk2_div, + &s4_vclk, + &s4_vclk2, + &s4_vclk_div1, + &s4_vclk_div2_en, + &s4_vclk_div4_en, + &s4_vclk_div6_en, + &s4_vclk_div12_en, + &s4_vclk2_div1, + &s4_vclk2_div2_en, + &s4_vclk2_div4_en, + &s4_vclk2_div6_en, + &s4_vclk2_div12_en, + &s4_cts_enci_sel, + &s4_cts_encp_sel, + &s4_cts_vdac_sel, + &s4_hdmi_tx_sel, + &s4_cts_enci, + &s4_cts_encp, + &s4_cts_vdac, + &s4_hdmi_tx, + &s4_hdmi_sel, + &s4_hdmi_div, + &s4_hdmi, + &s4_ts_clk_div, + &s4_ts_clk_gate, + &s4_mali_0_sel, + &s4_mali_0_div, + &s4_mali_0, + &s4_mali_1_sel, + &s4_mali_1_div, + &s4_mali_1, + &s4_mali_mux, + &s4_vdec_p0_mux, + &s4_vdec_p0_div, + &s4_vdec_p0, + &s4_vdec_p1_mux, + &s4_vdec_p1_div, + &s4_vdec_p1, + &s4_vdec_mux, + &s4_hevcf_p0_mux, + &s4_hevcf_p0_div, + &s4_hevcf_p0, + &s4_hevcf_p1_mux, + &s4_hevcf_p1_div, + &s4_hevcf_p1, + &s4_hevcf_mux, + &s4_vpu_0_sel, + &s4_vpu_0_div, + &s4_vpu_0, + &s4_vpu_1_sel, + &s4_vpu_1_div, + &s4_vpu_1, + &s4_vpu, + &s4_vpu_clkb_tmp_mux, + &s4_vpu_clkb_tmp_div, + &s4_vpu_clkb_tmp, + &s4_vpu_clkb_div, + &s4_vpu_clkb, + &s4_vpu_clkc_p0_mux, + &s4_vpu_clkc_p0_div, + &s4_vpu_clkc_p0, + &s4_vpu_clkc_p1_mux, + &s4_vpu_clkc_p1_div, + &s4_vpu_clkc_p1, + &s4_vpu_clkc_mux, + &s4_vapb_0_sel, + &s4_vapb_0_div, + &s4_vapb_0, + &s4_vapb_1_sel, + &s4_vapb_1_div, + &s4_vapb_1, + &s4_vapb, + &s4_ge2d_gate, + &s4_hdcp22_esmclk_mux, + &s4_hdcp22_esmclk_div, + &s4_hdcp22_esmclk_gate, + &s4_hdcp22_skpclk_mux, + &s4_hdcp22_skpclk_div, + &s4_hdcp22_skpclk_gate, + &s4_vdin_meas_mux, + &s4_vdin_meas_div, + &s4_vdin_meas_gate, + &s4_sd_emmc_c_clk0_sel, + &s4_sd_emmc_c_clk0_div, + &s4_sd_emmc_c_clk0, + &s4_sd_emmc_a_clk0_sel, + &s4_sd_emmc_a_clk0_div, + &s4_sd_emmc_a_clk0, + &s4_sd_emmc_b_clk0_sel, + &s4_sd_emmc_b_clk0_div, + &s4_sd_emmc_b_clk0, + &s4_spicc0_mux, + &s4_spicc0_div, + &s4_spicc0_gate, + &s4_pwm_a_mux, + &s4_pwm_a_div, + &s4_pwm_a_gate, + &s4_pwm_b_mux, + &s4_pwm_b_div, + &s4_pwm_b_gate, + &s4_pwm_c_mux, + &s4_pwm_c_div, + &s4_pwm_c_gate, + &s4_pwm_d_mux, + &s4_pwm_d_div, + &s4_pwm_d_gate, + &s4_pwm_e_mux, + &s4_pwm_e_div, + &s4_pwm_e_gate, + &s4_pwm_f_mux, + &s4_pwm_f_div, + &s4_pwm_f_gate, + &s4_pwm_g_mux, + &s4_pwm_g_div, + &s4_pwm_g_gate, + &s4_pwm_h_mux, + &s4_pwm_h_div, + &s4_pwm_h_gate, + &s4_pwm_i_mux, + &s4_pwm_i_div, + &s4_pwm_i_gate, + &s4_pwm_j_mux, + &s4_pwm_j_div, + &s4_pwm_j_gate, + &s4_saradc_mux, + &s4_saradc_div, + &s4_saradc_gate, + &s4_gen_clk_sel, + &s4_gen_clk_div, + &s4_gen_clk, + &s4_ddr, + &s4_dos, + &s4_ethphy, + &s4_mali, + &s4_aocpu, + &s4_aucpu, + &s4_cec, + &s4_sdemmca, + &s4_sdemmcb, + &s4_nand, + &s4_smartcard, + &s4_acodec, + &s4_spifc, + &s4_msr_clk, + &s4_ir_ctrl, + &s4_audio, + &s4_eth, + &s4_uart_a, + &s4_uart_b, + &s4_uart_c, + &s4_uart_d, + &s4_uart_e, + &s4_aififo, + &s4_ts_ddr, + &s4_ts_pll, + &s4_g2d, + &s4_spicc0, + &s4_usb, + &s4_i2c_m_a, + &s4_i2c_m_b, + &s4_i2c_m_c, + &s4_i2c_m_d, + &s4_i2c_m_e, + &s4_hdmitx_apb, + &s4_i2c_s_a, + &s4_usb1_to_ddr, + &s4_hdcp22, + &s4_mmc_apb, + &s4_rsa, + &s4_cpu_debug, + &s4_vpu_intr, + &s4_demod, + &s4_sar_adc, + &s4_gic, + &s4_pwm_ab, + &s4_pwm_cd, + &s4_pwm_ef, + &s4_pwm_gh, + &s4_pwm_ij, + &s4_demod_core_clk_mux, + &s4_demod_core_clk_div, + &s4_demod_core_clk_gate, + &s4_adc_extclk_in_mux, + &s4_adc_extclk_in_div, + &s4_adc_extclk_in_gate, +}; + +static struct regmap_config clkc_regmap_config = { + .reg_bits = 32, + .val_bits = 32, + .reg_stride = 4, +}; + +static struct meson_clk_hw_data s4_periphs_clks = { + .hws = s4_periphs_hw_clks, + .num = ARRAY_SIZE(s4_periphs_hw_clks), +}; + +static int meson_s4_periphs_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct regmap *regmap; + void __iomem *base; + int ret, i; + + base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(base)) + return dev_err_probe(dev, PTR_ERR(base), + "can't ioremap resource\n"); + + regmap = devm_regmap_init_mmio(dev, base, &clkc_regmap_config); + if (IS_ERR(regmap)) + return dev_err_probe(dev, PTR_ERR(regmap), + "can't init regmap mmio region\n"); + + /* Populate regmap for the regmap backed clocks */ + for (i = 0; i < ARRAY_SIZE(s4_periphs_clk_regmaps); i++) + s4_periphs_clk_regmaps[i]->map = regmap; + + for (i = 0; i < s4_periphs_clks.num; i++) { + /* array might be sparse */ + if (!s4_periphs_clks.hws[i]) + continue; + + ret = devm_clk_hw_register(dev, s4_periphs_clks.hws[i]); + if (ret) + return dev_err_probe(dev, ret, + "clock[%d] registration failed\n", i); + } + + return devm_of_clk_add_hw_provider(dev, meson_clk_hw_get, &s4_periphs_clks); +} + +static const struct of_device_id clkc_match_table[] = { + { + .compatible = "amlogic,s4-peripherals-clkc", + }, + {} +}; + +static struct platform_driver s4_driver = { + .probe = meson_s4_periphs_probe, + .driver = { + .name = "s4-periphs-clkc", + .of_match_table = clkc_match_table, + }, +}; + +module_platform_driver(s4_driver); +MODULE_AUTHOR("Yu Tu "); +MODULE_LICENSE("GPL"); diff --git a/drivers/clk/meson/s4-peripherals.h b/drivers/clk/meson/s4-peripherals.h new file mode 100644 index 000000000000..1e298713c2b2 --- /dev/null +++ b/drivers/clk/meson/s4-peripherals.h @@ -0,0 +1,56 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR MIT) */ +/* + * Copyright (c) 2022-2023 Amlogic, inc. All rights reserved + * Author: Yu Tu + */ + +#ifndef __MESON_S4_PERIPHERALS_H__ +#define __MESON_S4_PERIPHERALS_H__ + +#define CLKCTRL_RTC_BY_OSCIN_CTRL0 0x008 +#define CLKCTRL_RTC_BY_OSCIN_CTRL1 0x00c +#define CLKCTRL_RTC_CTRL 0x010 +#define CLKCTRL_SYS_CLK_CTRL0 0x040 +#define CLKCTRL_SYS_CLK_EN0_REG0 0x044 +#define CLKCTRL_SYS_CLK_EN0_REG1 0x048 +#define CLKCTRL_SYS_CLK_EN0_REG2 0x04c +#define CLKCTRL_SYS_CLK_EN0_REG3 0x050 +#define CLKCTRL_CECA_CTRL0 0x088 +#define CLKCTRL_CECA_CTRL1 0x08c +#define CLKCTRL_CECB_CTRL0 0x090 +#define CLKCTRL_CECB_CTRL1 0x094 +#define CLKCTRL_SC_CLK_CTRL 0x098 +#define CLKCTRL_CLK12_24_CTRL 0x0a8 +#define CLKCTRL_VID_CLK_CTRL 0x0c0 +#define CLKCTRL_VID_CLK_CTRL2 0x0c4 +#define CLKCTRL_VID_CLK_DIV 0x0c8 +#define CLKCTRL_VIID_CLK_DIV 0x0cc +#define CLKCTRL_VIID_CLK_CTRL 0x0d0 +#define CLKCTRL_HDMI_CLK_CTRL 0x0e0 +#define CLKCTRL_VID_PLL_CLK_DIV 0x0e4 +#define CLKCTRL_VPU_CLK_CTRL 0x0e8 +#define CLKCTRL_VPU_CLKB_CTRL 0x0ec +#define CLKCTRL_VPU_CLKC_CTRL 0x0f0 +#define CLKCTRL_VID_LOCK_CLK_CTRL 0x0f4 +#define CLKCTRL_VDIN_MEAS_CLK_CTRL 0x0f8 +#define CLKCTRL_VAPBCLK_CTRL 0x0fc +#define CLKCTRL_HDCP22_CTRL 0x100 +#define CLKCTRL_VDEC_CLK_CTRL 0x140 +#define CLKCTRL_VDEC2_CLK_CTRL 0x144 +#define CLKCTRL_VDEC3_CLK_CTRL 0x148 +#define CLKCTRL_VDEC4_CLK_CTRL 0x14c +#define CLKCTRL_TS_CLK_CTRL 0x158 +#define CLKCTRL_MALI_CLK_CTRL 0x15c +#define CLKCTRL_NAND_CLK_CTRL 0x168 +#define CLKCTRL_SD_EMMC_CLK_CTRL 0x16c +#define CLKCTRL_SPICC_CLK_CTRL 0x174 +#define CLKCTRL_GEN_CLK_CTRL 0x178 +#define CLKCTRL_SAR_CLK_CTRL 0x17c +#define CLKCTRL_PWM_CLK_AB_CTRL 0x180 +#define CLKCTRL_PWM_CLK_CD_CTRL 0x184 +#define CLKCTRL_PWM_CLK_EF_CTRL 0x188 +#define CLKCTRL_PWM_CLK_GH_CTRL 0x18c +#define CLKCTRL_PWM_CLK_IJ_CTRL 0x190 +#define CLKCTRL_DEMOD_CLK_CTRL 0x200 + +#endif /* __MESON_S4_PERIPHERALS_H__ */ -- cgit v1.2.3-59-g8ed1b From 317e69c49b4ceef8aebb47d771498ccb3571bdf9 Mon Sep 17 00:00:00 2001 From: Abel Vesa Date: Thu, 21 Sep 2023 12:23:54 +0300 Subject: clk: imx: Select MXC_CLK for CLK_IMX8QXP If the i.MX8QXP clock provider is built-in but the MXC_CLK is built as module, build fails: aarch64-linux-ld: drivers/clk/imx/clk-imx8-acm.o: in function `imx8_acm_clk_probe': clk-imx8-acm.c:(.text+0x3d0): undefined reference to `imx_check_clk_hws' Fix that by selecting MXC_CLK in case of CLK_IMX8QXP. Fixes: c2cccb6d0b33 ("clk: imx: add imx8qxp clk driver") Closes: https://lore.kernel.org/all/8b77219e-b59e-40f1-96f1-980a0b2debcf@infradead.org/ Reported-by: Randy Dunlap Reviewed-by: Peng Fan Acked-by: Randy Dunlap Tested-by: Randy Dunlap Signed-off-by: Abel Vesa --- drivers/clk/imx/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/clk/imx/Kconfig b/drivers/clk/imx/Kconfig index f6b82e0b9703..db3bca5f4ec9 100644 --- a/drivers/clk/imx/Kconfig +++ b/drivers/clk/imx/Kconfig @@ -96,6 +96,7 @@ config CLK_IMX8QXP depends on (ARCH_MXC && ARM64) || COMPILE_TEST depends on IMX_SCU && HAVE_ARM_SMCCC select MXC_CLK_SCU + select MXC_CLK help Build the driver for IMX8QXP SCU based clocks. -- cgit v1.2.3-59-g8ed1b From 156624e2cf815ce98fad5a24f04370f4459ae6f4 Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Thu, 14 Sep 2023 22:31:02 +0200 Subject: clk: imx: imx8: Fix an error handling path in clk_imx_acm_attach_pm_domains() If a dev_pm_domain_attach_by_id() call fails, previously allocated resources need to be released. Fixes: d3a0946d7ac9 ("clk: imx: imx8: add audio clock mux driver") Reviewed-by: Peng Fan Signed-off-by: Christophe JAILLET Signed-off-by: Abel Vesa --- drivers/clk/imx/clk-imx8-acm.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/clk/imx/clk-imx8-acm.c b/drivers/clk/imx/clk-imx8-acm.c index 1e82f72b75c6..87025a6772d0 100644 --- a/drivers/clk/imx/clk-imx8-acm.c +++ b/drivers/clk/imx/clk-imx8-acm.c @@ -279,8 +279,10 @@ static int clk_imx_acm_attach_pm_domains(struct device *dev, for (i = 0; i < dev_pm->num_domains; i++) { dev_pm->pd_dev[i] = dev_pm_domain_attach_by_id(dev, i); - if (IS_ERR(dev_pm->pd_dev[i])) - return PTR_ERR(dev_pm->pd_dev[i]); + if (IS_ERR(dev_pm->pd_dev[i])) { + ret = PTR_ERR(dev_pm->pd_dev[i]); + goto detach_pm; + } dev_pm->pd_dev_link[i] = device_link_add(dev, dev_pm->pd_dev[i], -- cgit v1.2.3-59-g8ed1b From 9a0108acdb1b6189dcc8f9318edfc6b7e0281df4 Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Thu, 14 Sep 2023 22:31:03 +0200 Subject: clk: imx: imx8: Fix an error handling path if devm_clk_hw_register_mux_parent_data_table() fails If a devm_clk_hw_register_mux_parent_data_table() call fails, it is likely that the probe should fail with an error code. Set 'ret' before leaving the function. Fixes: d3a0946d7ac9 ("clk: imx: imx8: add audio clock mux driver") Reviewed-by: Peng Fan Signed-off-by: Christophe JAILLET Signed-off-by: Abel Vesa --- drivers/clk/imx/clk-imx8-acm.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/clk/imx/clk-imx8-acm.c b/drivers/clk/imx/clk-imx8-acm.c index 87025a6772d0..73b3b5354951 100644 --- a/drivers/clk/imx/clk-imx8-acm.c +++ b/drivers/clk/imx/clk-imx8-acm.c @@ -373,6 +373,7 @@ static int imx8_acm_clk_probe(struct platform_device *pdev) sels[i].shift, sels[i].width, 0, NULL, NULL); if (IS_ERR(hws[sels[i].clkid])) { + ret = PTR_ERR(hws[sels[i].clkid]); pm_runtime_disable(&pdev->dev); goto err_clk_register; } -- cgit v1.2.3-59-g8ed1b From e9a164e367f039629fd5466a79b9f495646e1261 Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Thu, 14 Sep 2023 22:31:04 +0200 Subject: clk: imx: imx8: Fix an error handling path in imx8_acm_clk_probe() If an error occurs after a successful clk_imx_acm_attach_pm_domains() call, it must be undone. Add an explicit error handling path, re-order the code and add the missing clk_imx_acm_detach_pm_domains() call. Fixes: d3a0946d7ac9 ("clk: imx: imx8: add audio clock mux driver") Reviewed-by: Peng Fan Signed-off-by: Christophe JAILLET Signed-off-by: Abel Vesa --- drivers/clk/imx/clk-imx8-acm.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/clk/imx/clk-imx8-acm.c b/drivers/clk/imx/clk-imx8-acm.c index 73b3b5354951..1c95ae905eec 100644 --- a/drivers/clk/imx/clk-imx8-acm.c +++ b/drivers/clk/imx/clk-imx8-acm.c @@ -374,7 +374,6 @@ static int imx8_acm_clk_probe(struct platform_device *pdev) 0, NULL, NULL); if (IS_ERR(hws[sels[i].clkid])) { ret = PTR_ERR(hws[sels[i].clkid]); - pm_runtime_disable(&pdev->dev); goto err_clk_register; } } @@ -384,12 +383,16 @@ static int imx8_acm_clk_probe(struct platform_device *pdev) ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, clk_hw_data); if (ret < 0) { dev_err(dev, "failed to register hws for ACM\n"); - pm_runtime_disable(&pdev->dev); + goto err_clk_register; } -err_clk_register: + pm_runtime_put_sync(&pdev->dev); + return 0; +err_clk_register: pm_runtime_put_sync(&pdev->dev); + pm_runtime_disable(&pdev->dev); + clk_imx_acm_detach_pm_domains(&pdev->dev, &priv->dev_pm); return ret; } -- cgit v1.2.3-59-g8ed1b From ef23d44b7fcbd19773dcedcb50ca2f625107604f Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Thu, 14 Sep 2023 22:31:05 +0200 Subject: clk: imx: imx8: Add a message in case of devm_clk_hw_register_mux_parent_data_table() error If devm_clk_hw_register_mux_parent_data_table() fails, we branch to the error handling path and imx_check_clk_hws() is never called. Actually, imx_check_clk_hws() is a no-op because values in 'hws' are either valid, either NULL. Move the call to imx_check_clk_hws() in the error handling path, so that an error is logged. Fixes: d3a0946d7ac9 ("clk: imx: imx8: add audio clock mux driver") Reviewed-by: Peng Fan Signed-off-by: Christophe JAILLET Signed-off-by: Abel Vesa --- drivers/clk/imx/clk-imx8-acm.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/clk/imx/clk-imx8-acm.c b/drivers/clk/imx/clk-imx8-acm.c index 1c95ae905eec..c744fb78bb44 100644 --- a/drivers/clk/imx/clk-imx8-acm.c +++ b/drivers/clk/imx/clk-imx8-acm.c @@ -374,12 +374,11 @@ static int imx8_acm_clk_probe(struct platform_device *pdev) 0, NULL, NULL); if (IS_ERR(hws[sels[i].clkid])) { ret = PTR_ERR(hws[sels[i].clkid]); + imx_check_clk_hws(hws, IMX_ADMA_ACM_CLK_END); goto err_clk_register; } } - imx_check_clk_hws(hws, IMX_ADMA_ACM_CLK_END); - ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, clk_hw_data); if (ret < 0) { dev_err(dev, "failed to register hws for ACM\n"); -- cgit v1.2.3-59-g8ed1b From 3af29a89de2c6e49737a1201b7d6fd5ad3f635a4 Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Thu, 14 Sep 2023 22:31:06 +0200 Subject: clk: imx: imx8: Simplify clk_imx_acm_detach_pm_domains() The return value of clk_imx_acm_detach_pm_domains() is never used. Simplify the code and turn it into a void function. Reviewed-by: Peng Fan Signed-off-by: Christophe JAILLET Signed-off-by: Abel Vesa --- drivers/clk/imx/clk-imx8-acm.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/clk/imx/clk-imx8-acm.c b/drivers/clk/imx/clk-imx8-acm.c index c744fb78bb44..735b08296cc8 100644 --- a/drivers/clk/imx/clk-imx8-acm.c +++ b/drivers/clk/imx/clk-imx8-acm.c @@ -310,20 +310,18 @@ detach_pm: * @dev: deivice pointer * @dev_pm: multi power domain for device */ -static int clk_imx_acm_detach_pm_domains(struct device *dev, - struct clk_imx_acm_pm_domains *dev_pm) +static void clk_imx_acm_detach_pm_domains(struct device *dev, + struct clk_imx_acm_pm_domains *dev_pm) { int i; if (dev_pm->num_domains <= 1) - return 0; + return; for (i = 0; i < dev_pm->num_domains; i++) { device_link_del(dev_pm->pd_dev_link[i]); dev_pm_domain_detach(dev_pm->pd_dev[i], false); } - - return 0; } static int imx8_acm_clk_probe(struct platform_device *pdev) -- cgit v1.2.3-59-g8ed1b From 05eeeff22b216e871be76dcf216a2fdda48880e2 Mon Sep 17 00:00:00 2001 From: Adam Ford Date: Wed, 30 Aug 2023 23:44:31 -0500 Subject: clk: imx8mp: Remove non-existent IMX8MP_CLK_AUDIOMIX_PDM_ROOT The TRM shows there is only one AUDIOMIX PDM Root Clock Select register, and it's called IMX8MP_CLK_AUDIOMIX_PDM_SEL. That selector doesn't appear to have any more children and the MICFIL driver can reference IMX8MP_CLK_AUDIOMIX_PDM_SEL directly without the need for any other. Remove this errant clock, since it doesn't really exist. Signed-off-by: Adam Ford Acked-by: Rob Herring Link: https://lore.kernel.org/r/20230831044431.250338-3-aford173@gmail.com Signed-off-by: Abel Vesa --- include/dt-bindings/clock/imx8mp-clock.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/dt-bindings/clock/imx8mp-clock.h b/include/dt-bindings/clock/imx8mp-clock.h index 11cb0a4fe999..7da4243984b2 100644 --- a/include/dt-bindings/clock/imx8mp-clock.h +++ b/include/dt-bindings/clock/imx8mp-clock.h @@ -376,7 +376,6 @@ #define IMX8MP_CLK_AUDIOMIX_MU2_ROOT 36 #define IMX8MP_CLK_AUDIOMIX_MU3_ROOT 37 #define IMX8MP_CLK_AUDIOMIX_EARC_PHY 38 -#define IMX8MP_CLK_AUDIOMIX_PDM_ROOT 39 #define IMX8MP_CLK_AUDIOMIX_SAI1_MCLK1_SEL 40 #define IMX8MP_CLK_AUDIOMIX_SAI1_MCLK2_SEL 41 #define IMX8MP_CLK_AUDIOMIX_SAI2_MCLK1_SEL 42 -- cgit v1.2.3-59-g8ed1b From 577ad169966e6e75b10e004389a3f79813e84b5d Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Sun, 1 Oct 2023 20:26:18 +0800 Subject: clk: imx: imx8mq: correct error handling path Avoid memory leak in error handling path. It does not make much sense for the SoC without clk driver, to make program behavior correct, let's fix it. Fixes: b80522040cd3 ("clk: imx: Add clock driver for i.MX8MQ CCM") Reported-by: kernel test robot Reported-by: Dan Carpenter Closes: https://lore.kernel.org/r/202309240551.e46NllPa-lkp@intel.com/ Signed-off-by: Peng Fan Link: https://lore.kernel.org/r/20231001122618.194498-1-peng.fan@oss.nxp.com Signed-off-by: Abel Vesa --- drivers/clk/imx/clk-imx8mq.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/drivers/clk/imx/clk-imx8mq.c b/drivers/clk/imx/clk-imx8mq.c index 4bd65879fcd3..f70ed231b92d 100644 --- a/drivers/clk/imx/clk-imx8mq.c +++ b/drivers/clk/imx/clk-imx8mq.c @@ -288,8 +288,7 @@ static int imx8mq_clocks_probe(struct platform_device *pdev) void __iomem *base; int err; - clk_hw_data = kzalloc(struct_size(clk_hw_data, hws, - IMX8MQ_CLK_END), GFP_KERNEL); + clk_hw_data = devm_kzalloc(dev, struct_size(clk_hw_data, hws, IMX8MQ_CLK_END), GFP_KERNEL); if (WARN_ON(!clk_hw_data)) return -ENOMEM; @@ -306,10 +305,12 @@ static int imx8mq_clocks_probe(struct platform_device *pdev) hws[IMX8MQ_CLK_EXT4] = imx_get_clk_hw_by_name(np, "clk_ext4"); np = of_find_compatible_node(NULL, NULL, "fsl,imx8mq-anatop"); - base = of_iomap(np, 0); + base = devm_of_iomap(dev, np, 0, NULL); of_node_put(np); - if (WARN_ON(!base)) - return -ENOMEM; + if (WARN_ON(IS_ERR(base))) { + err = PTR_ERR(base); + goto unregister_hws; + } hws[IMX8MQ_ARM_PLL_REF_SEL] = imx_clk_hw_mux("arm_pll_ref_sel", base + 0x28, 16, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels)); hws[IMX8MQ_GPU_PLL_REF_SEL] = imx_clk_hw_mux("gpu_pll_ref_sel", base + 0x18, 16, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels)); @@ -395,8 +396,10 @@ static int imx8mq_clocks_probe(struct platform_device *pdev) np = dev->of_node; base = devm_platform_ioremap_resource(pdev, 0); - if (WARN_ON(IS_ERR(base))) - return PTR_ERR(base); + if (WARN_ON(IS_ERR(base))) { + err = PTR_ERR(base); + goto unregister_hws; + } /* CORE */ hws[IMX8MQ_CLK_A53_DIV] = imx8m_clk_hw_composite_core("arm_a53_div", imx8mq_a53_sels, base + 0x8000); -- cgit v1.2.3-59-g8ed1b From 0a22b3a6f446223aff5bcdcc06003ef6e412bfd8 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Tue, 15 Aug 2023 10:09:23 -0300 Subject: clk: imx: imx6sx: Allow a different LCDIF1 clock parent It is not a good idea to hardcode the LCDIF1 parent inside the clock driver because some users may want to use a different clock parent for LCDIF1. One of the reasons could be related to EMI tests. Remove the harcoded LCDIF1 parent when the LCDIF1 parent is described via devicetree. Old dtb's that do not describe the LCDIF1 parent via devicetree will use the same PLL5 clock as parent to keep the original behavior. Signed-off-by: Fabio Estevam Reviewed-by: Abel Vesa Link: https://lore.kernel.org/r/20230815130923.775117-1-festevam@gmail.com Signed-off-by: Abel Vesa --- drivers/clk/imx/clk-imx6sx.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/drivers/clk/imx/clk-imx6sx.c b/drivers/clk/imx/clk-imx6sx.c index 3f1502933e59..69f8f6f9ca49 100644 --- a/drivers/clk/imx/clk-imx6sx.c +++ b/drivers/clk/imx/clk-imx6sx.c @@ -121,6 +121,7 @@ static void __init imx6sx_clocks_init(struct device_node *ccm_node) { struct device_node *np; void __iomem *base; + bool lcdif1_assigned_clk; clk_hw_data = kzalloc(struct_size(clk_hw_data, hws, IMX6SX_CLK_CLK_END), GFP_KERNEL); @@ -498,9 +499,16 @@ static void __init imx6sx_clocks_init(struct device_node *ccm_node) clk_set_parent(hws[IMX6SX_CLK_EIM_SLOW_SEL]->clk, hws[IMX6SX_CLK_PLL2_PFD2]->clk); clk_set_rate(hws[IMX6SX_CLK_EIM_SLOW]->clk, 132000000); - /* set parent clock for LCDIF1 pixel clock */ - clk_set_parent(hws[IMX6SX_CLK_LCDIF1_PRE_SEL]->clk, hws[IMX6SX_CLK_PLL5_VIDEO_DIV]->clk); - clk_set_parent(hws[IMX6SX_CLK_LCDIF1_SEL]->clk, hws[IMX6SX_CLK_LCDIF1_PODF]->clk); + np = of_find_node_by_path("/soc/bus@2200000/spba-bus@2240000/lcdif@2220000"); + lcdif1_assigned_clk = of_find_property(np, "assigned-clock-parents", NULL); + + /* Set parent clock for LCDIF1 pixel clock if not done via devicetree */ + if (!lcdif1_assigned_clk) { + clk_set_parent(hws[IMX6SX_CLK_LCDIF1_PRE_SEL]->clk, + hws[IMX6SX_CLK_PLL5_VIDEO_DIV]->clk); + clk_set_parent(hws[IMX6SX_CLK_LCDIF1_SEL]->clk, + hws[IMX6SX_CLK_LCDIF1_PODF]->clk); + } /* Set the parent clks of PCIe lvds1 and pcie_axi to be pcie ref, axi */ if (clk_set_parent(hws[IMX6SX_CLK_LVDS1_SEL]->clk, hws[IMX6SX_CLK_PCIE_REF_125M]->clk)) -- cgit v1.2.3-59-g8ed1b From ab2c30f6bbe34dbf13ff2cc0cf7bc237de2df013 Mon Sep 17 00:00:00 2001 From: Viorel Suman Date: Tue, 12 Sep 2023 17:18:59 +0800 Subject: clk: imx: imx8dxl-rsrc: keep sorted in the ascending order Entries in imx8dxl_clk_scu_rsrc_table must be kept in the ascending order, and IMX_SC_R_M4_0_UART < IMX_SC_R_M4_0_I2C. Fixes: 036a4b4b4dfa ("clk: imx: Add imx8dxl clk driver") Signed-off-by: Viorel Suman Signed-off-by: Peng Fan Reviewed-by: Abel Vesa Link: https://lore.kernel.org/r/20230912-imx8-clk-v1-v1-1-69a34bcfcae1@nxp.com Signed-off-by: Abel Vesa --- drivers/clk/imx/clk-imx8dxl-rsrc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/imx/clk-imx8dxl-rsrc.c b/drivers/clk/imx/clk-imx8dxl-rsrc.c index 69b7aa34fff5..a36e821ba807 100644 --- a/drivers/clk/imx/clk-imx8dxl-rsrc.c +++ b/drivers/clk/imx/clk-imx8dxl-rsrc.c @@ -50,8 +50,8 @@ static u32 imx8dxl_clk_scu_rsrc_table[] = { IMX_SC_R_MLB_0, IMX_SC_R_USB_1, IMX_SC_R_NAND, - IMX_SC_R_M4_0_I2C, IMX_SC_R_M4_0_UART, + IMX_SC_R_M4_0_I2C, IMX_SC_R_ELCDIF_PLL, IMX_SC_R_AUDIO_PLL_0, IMX_SC_R_AUDIO_PLL_1, -- cgit v1.2.3-59-g8ed1b From 15cee75dacb82ade710d61bfd536011933ef9bf2 Mon Sep 17 00:00:00 2001 From: Robert Chiras Date: Tue, 12 Sep 2023 17:19:00 +0800 Subject: clk: imx: imx8qxp: Fix elcdif_pll clock Move the elcdif_pll clock initialization before the lcd_clk, since the elcdif_clk needs to be initialized ahead of lcd_clk, being its parent. This change fixes issues with the LCD clocks during suspend/resume. Fixes: babfaa9556d7 ("clk: imx: scu: add more scu clocks") Suggested-by: Ranjani Vaidyanathan Acked-by: Laurentiu Palcu Signed-off-by: Robert Chiras Signed-off-by: Peng Fan Reviewed-by: Abel Vesa Link: https://lore.kernel.org/r/20230912-imx8-clk-v1-v1-2-69a34bcfcae1@nxp.com Signed-off-by: Abel Vesa --- drivers/clk/imx/clk-imx8qxp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/imx/clk-imx8qxp.c b/drivers/clk/imx/clk-imx8qxp.c index cadcbb318f5c..4020aa4b79bf 100644 --- a/drivers/clk/imx/clk-imx8qxp.c +++ b/drivers/clk/imx/clk-imx8qxp.c @@ -147,10 +147,10 @@ static int imx8qxp_clk_probe(struct platform_device *pdev) 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("elcdif_pll", IMX_SC_R_ELCDIF_PLL, IMX_SC_PM_CLK_PLL); 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); -- cgit v1.2.3-59-g8ed1b From 8568b3c499268456b76cdc2e9e1b9d86d8b08837 Mon Sep 17 00:00:00 2001 From: Shenwei Wang Date: Tue, 12 Sep 2023 17:19:01 +0800 Subject: clk: imx: imx8qxp: correct the enet clocks for i.MX8DXL The SC_PM_CLK_MISC0 clock is not available for the resources of ENET0/1 on i.MX8DXL. Using the clock device compatible string to identify the platform and only initialize the enetX_rgmii_rx_clk clock for non i.MX8DXL platform. Signed-off-by: Shenwei Wang Reviewed-by: Ranjani Vaidyanathan Reviewed-by: Jacky Bai Acked-by: Jason Liu Signed-off-by: Peng Fan Reviewed-by: Abel Vesa Link: https://lore.kernel.org/r/20230912-imx8-clk-v1-v1-3-69a34bcfcae1@nxp.com Signed-off-by: Abel Vesa --- drivers/clk/imx/clk-imx8qxp.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/drivers/clk/imx/clk-imx8qxp.c b/drivers/clk/imx/clk-imx8qxp.c index 4020aa4b79bf..41f0a45aa162 100644 --- a/drivers/clk/imx/clk-imx8qxp.c +++ b/drivers/clk/imx/clk-imx8qxp.c @@ -90,6 +90,11 @@ static const char * const pi_pll0_sels[] = { "clk_dummy", }; +static inline bool clk_on_imx8dxl(struct device_node *node) +{ + return of_device_is_compatible(node, "fsl,imx8dxl-clk"); +} + static int imx8qxp_clk_probe(struct platform_device *pdev) { struct device_node *ccm_node = pdev->dev.of_node; @@ -169,13 +174,15 @@ static int imx8qxp_clk_probe(struct platform_device *pdev) 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); + if (!clk_on_imx8dxl(ccm_node)) { + imx_clk_scu("enet0_rgmii_rx_clk", IMX_SC_R_ENET_0, 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("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); imx_clk_scu("usb3_aclk_div", IMX_SC_R_USB_2, IMX_SC_PM_CLK_PER); -- cgit v1.2.3-59-g8ed1b From 4fcb51fb0e3084ee81edaf8aea98ac01e456a871 Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Tue, 12 Sep 2023 17:19:02 +0800 Subject: clk: imx: imx8qm-rsrc: drop VPU_UART/VPUCORE IMX_SC_R_VPU_UART and IMX_SC_R_VPUCORE was used in i.MX8QM A0 which not for mass production. i.MX8QM B0 not have the two resources, so drop it. Signed-off-by: Peng Fan Reviewed-by: Abel Vesa Link: https://lore.kernel.org/r/20230912-imx8-clk-v1-v1-4-69a34bcfcae1@nxp.com Signed-off-by: Abel Vesa --- drivers/clk/imx/clk-imx8qm-rsrc.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/clk/imx/clk-imx8qm-rsrc.c b/drivers/clk/imx/clk-imx8qm-rsrc.c index 87e0b6ac027e..8412fa349569 100644 --- a/drivers/clk/imx/clk-imx8qm-rsrc.c +++ b/drivers/clk/imx/clk-imx8qm-rsrc.c @@ -79,8 +79,6 @@ static const u32 imx8qm_clk_scu_rsrc_table[] = { 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, -- cgit v1.2.3-59-g8ed1b From a699148b8704aa11600321b9f6b6b21f09418c42 Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Tue, 12 Sep 2023 17:19:03 +0800 Subject: clk: imx8: remove MLB support MLB was de-featured, so drop MLB clk for i.MX8QM/QXP/DXL Signed-off-by: Peng Fan Reviewed-by: Abel Vesa Link: https://lore.kernel.org/r/20230912-imx8-clk-v1-v1-5-69a34bcfcae1@nxp.com Signed-off-by: Abel Vesa --- drivers/clk/imx/clk-imx8-acm.c | 6 +++--- drivers/clk/imx/clk-imx8dxl-rsrc.c | 1 - drivers/clk/imx/clk-imx8qm-rsrc.c | 1 - drivers/clk/imx/clk-imx8qxp-lpcg.h | 1 - drivers/clk/imx/clk-imx8qxp-rsrc.c | 1 - 5 files changed, 3 insertions(+), 7 deletions(-) diff --git a/drivers/clk/imx/clk-imx8-acm.c b/drivers/clk/imx/clk-imx8-acm.c index 735b08296cc8..f68877eef873 100644 --- a/drivers/clk/imx/clk-imx8-acm.c +++ b/drivers/clk/imx/clk-imx8-acm.c @@ -77,7 +77,7 @@ struct imx8_acm_priv { static const struct clk_parent_data imx8qm_aud_clk_sels[] = { { .fw_name = "aud_rec_clk0_lpcg_clk" }, { .fw_name = "aud_rec_clk1_lpcg_clk" }, - { .fw_name = "mlb_clk" }, + { .fw_name = "dummy" }, { .fw_name = "hdmi_rx_mclk" }, { .fw_name = "ext_aud_mclk0" }, { .fw_name = "ext_aud_mclk1" }, @@ -103,7 +103,7 @@ static const struct clk_parent_data imx8qm_aud_clk_sels[] = { static const struct clk_parent_data imx8qm_mclk_out_sels[] = { { .fw_name = "aud_rec_clk0_lpcg_clk" }, { .fw_name = "aud_rec_clk1_lpcg_clk" }, - { .fw_name = "mlb_clk" }, + { .fw_name = "dummy" }, { .fw_name = "hdmi_rx_mclk" }, { .fw_name = "spdif0_rx" }, { .fw_name = "spdif1_rx" }, @@ -122,7 +122,7 @@ static const struct clk_parent_data imx8qm_asrc_mux_clk_sels[] = { { .fw_name = "sai4_rx_bclk" }, { .fw_name = "sai5_tx_bclk" }, { .index = -1 }, - { .fw_name = "mlb_clk" }, + { .fw_name = "dummy" }, }; diff --git a/drivers/clk/imx/clk-imx8dxl-rsrc.c b/drivers/clk/imx/clk-imx8dxl-rsrc.c index a36e821ba807..0f940335d83c 100644 --- a/drivers/clk/imx/clk-imx8dxl-rsrc.c +++ b/drivers/clk/imx/clk-imx8dxl-rsrc.c @@ -47,7 +47,6 @@ static u32 imx8dxl_clk_scu_rsrc_table[] = { IMX_SC_R_SDHC_2, IMX_SC_R_ENET_0, IMX_SC_R_ENET_1, - IMX_SC_R_MLB_0, IMX_SC_R_USB_1, IMX_SC_R_NAND, IMX_SC_R_M4_0_UART, diff --git a/drivers/clk/imx/clk-imx8qm-rsrc.c b/drivers/clk/imx/clk-imx8qm-rsrc.c index 8412fa349569..634bc3058657 100644 --- a/drivers/clk/imx/clk-imx8qm-rsrc.c +++ b/drivers/clk/imx/clk-imx8qm-rsrc.c @@ -65,7 +65,6 @@ static const u32 imx8qm_clk_scu_rsrc_table[] = { 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, diff --git a/drivers/clk/imx/clk-imx8qxp-lpcg.h b/drivers/clk/imx/clk-imx8qxp-lpcg.h index 2a37ce57c500..ebca8fa9268f 100644 --- a/drivers/clk/imx/clk-imx8qxp-lpcg.h +++ b/drivers/clk/imx/clk-imx8qxp-lpcg.h @@ -42,7 +42,6 @@ #define CONN_ENET_0_LPCG 0x30000 #define CONN_ENET_1_LPCG 0x40000 #define CONN_DTCP_LPCG 0x50000 -#define CONN_MLB_LPCG 0x60000 #define CONN_USB_2_LPCG 0x70000 #define CONN_USB_3_LPCG 0x80000 #define CONN_NAND_LPCG 0x90000 diff --git a/drivers/clk/imx/clk-imx8qxp-rsrc.c b/drivers/clk/imx/clk-imx8qxp-rsrc.c index df09f2a7996d..29868e686921 100644 --- a/drivers/clk/imx/clk-imx8qxp-rsrc.c +++ b/drivers/clk/imx/clk-imx8qxp-rsrc.c @@ -54,7 +54,6 @@ static const u32 imx8qxp_clk_scu_rsrc_table[] = { 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, -- cgit v1.2.3-59-g8ed1b From eaefd1cf36a6507ff7dd2d30f68201de259eec63 Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Tue, 12 Sep 2023 17:19:04 +0800 Subject: clk: imx: scu: ignore clks not owned by Cortex-A partition Not register clks that not owned to current partition. CPU resources are specical resources, it is assigned in ATF, not non-secure OS, but we still need to allow cpu freq, so return true for non-secure OS for cpu resources. Otherwise there will be error log if the resources are owned by current partition: [ 19.387291] cm40_i2c_div: failed to attached the power domain -2 [ 19.389305] cm40_lpuart_div: failed to attached the power domain -2 Signed-off-by: Peng Fan Reviewed-by: Abel Vesa Link: https://lore.kernel.org/r/20230912-imx8-clk-v1-v1-6-69a34bcfcae1@nxp.com Signed-off-by: Abel Vesa --- drivers/clk/imx/clk-scu.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/drivers/clk/imx/clk-scu.c b/drivers/clk/imx/clk-scu.c index cd83c52e9952..be89180dd19c 100644 --- a/drivers/clk/imx/clk-scu.c +++ b/drivers/clk/imx/clk-scu.c @@ -10,10 +10,12 @@ #include #include #include +#include #include #include #include #include +#include #include "clk-scu.h" @@ -670,6 +672,18 @@ static int imx_clk_scu_attach_pd(struct device *dev, u32 rsrc_id) return of_genpd_add_device(&genpdspec, dev); } +static bool imx_clk_is_resource_owned(u32 rsrc) +{ + /* + * A-core resources are special. SCFW reports they are not "owned" by + * current partition but linux can still adjust them for cpufreq. + */ + if (rsrc == IMX_SC_R_A53 || rsrc == IMX_SC_R_A72 || rsrc == IMX_SC_R_A35) + return true; + + return imx_sc_rm_is_resource_owned(ccm_ipc_handle, rsrc); +} + struct clk_hw *imx_clk_scu_alloc_dev(const char *name, const char * const *parents, int num_parents, u32 rsrc_id, u8 clk_type) @@ -687,6 +701,9 @@ struct clk_hw *imx_clk_scu_alloc_dev(const char *name, if (!imx_scu_clk_is_valid(rsrc_id)) return ERR_PTR(-EINVAL); + if (!imx_clk_is_resource_owned(rsrc_id)) + return NULL; + pdev = platform_device_alloc(name, PLATFORM_DEVID_NONE); if (!pdev) { pr_err("%s: failed to allocate scu clk dev rsrc %d type %d\n", @@ -869,6 +886,9 @@ struct clk_hw *__imx_clk_gpr_scu(const char *name, const char * const *parent_na return ERR_PTR(-EINVAL); } + if (!imx_clk_is_resource_owned(rsrc_id)) + return NULL; + clk = kzalloc(sizeof(*clk), GFP_KERNEL); if (!clk) { kfree(clk_node); -- cgit v1.2.3-59-g8ed1b From 2838820800dcaa60f32bef715c7e2e87e049aebc Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Tue, 12 Sep 2023 17:19:05 +0800 Subject: clk: imx: imx8qm/qxp: add more resources to whitelist Add CAN_1/2 support for i.MX8QM Add M4_0, PI_0_PWM_0 and PI_0_I2C_0 for i.MX8QXP Signed-off-by: Peng Fan Reviewed-by: Abel Vesa Link: https://lore.kernel.org/r/20230912-imx8-clk-v1-v1-7-69a34bcfcae1@nxp.com Signed-off-by: Abel Vesa --- drivers/clk/imx/clk-imx8qm-rsrc.c | 2 ++ drivers/clk/imx/clk-imx8qxp-rsrc.c | 3 +++ 2 files changed, 5 insertions(+) diff --git a/drivers/clk/imx/clk-imx8qm-rsrc.c b/drivers/clk/imx/clk-imx8qm-rsrc.c index 634bc3058657..dadfdd9a4541 100644 --- a/drivers/clk/imx/clk-imx8qm-rsrc.c +++ b/drivers/clk/imx/clk-imx8qm-rsrc.c @@ -43,6 +43,8 @@ static const u32 imx8qm_clk_scu_rsrc_table[] = { IMX_SC_R_FTM_0, IMX_SC_R_FTM_1, IMX_SC_R_CAN_0, + IMX_SC_R_CAN_1, + IMX_SC_R_CAN_2, IMX_SC_R_GPU_0_PID0, IMX_SC_R_GPU_1_PID0, IMX_SC_R_PWM_0, diff --git a/drivers/clk/imx/clk-imx8qxp-rsrc.c b/drivers/clk/imx/clk-imx8qxp-rsrc.c index 29868e686921..585c425524a4 100644 --- a/drivers/clk/imx/clk-imx8qxp-rsrc.c +++ b/drivers/clk/imx/clk-imx8qxp-rsrc.c @@ -58,10 +58,13 @@ static const u32 imx8qxp_clk_scu_rsrc_table[] = { IMX_SC_R_NAND, IMX_SC_R_LVDS_0, IMX_SC_R_LVDS_1, + IMX_SC_R_M4_0_UART, 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_PWM_0, + IMX_SC_R_PI_0_I2C_0, IMX_SC_R_PI_0_PLL, IMX_SC_R_MIPI_0, IMX_SC_R_MIPI_0_PWM_0, -- cgit v1.2.3-59-g8ed1b From e372aee8c24957cbcb55d93b14ba386096497bca Mon Sep 17 00:00:00 2001 From: Claudiu Beznea Date: Fri, 29 Sep 2023 08:38:59 +0300 Subject: dt-bindings: clock: renesas,rzg2l-cpg: Document RZ/G3S SoC Add documentation for the RZ/G3S CPG. The RZ/G3S CPG module is almost identical to the one available in RZ/G2{L,UL}, the exception being some core clocks as follows: - The SD clock is composed of a mux and a divider, and the divider has some limitations (div = 1 cannot be set if mux rate is 800MHz), - There are 3 SD clocks, - The OCTA and TSU clocks are specific to RZ/G3S, - PLL1/4/6 are specific to RZ/G3S with its own computation formula. Even with this RZ/G3S could use the same bindings as RZ/G2L. Along with documentation bindings for the RZ/G3S (R9A08G045) Clock Pulse Generator (CPG) core clocks, module clocks and resets were added. Signed-off-by: Claudiu Beznea Acked-by: Rob Herring Reviewed-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/20230929053915.1530607-13-claudiu.beznea@bp.renesas.com Signed-off-by: Geert Uytterhoeven --- .../bindings/clock/renesas,rzg2l-cpg.yaml | 1 + include/dt-bindings/clock/r9a08g045-cpg.h | 242 +++++++++++++++++++++ 2 files changed, 243 insertions(+) create mode 100644 include/dt-bindings/clock/r9a08g045-cpg.h diff --git a/Documentation/devicetree/bindings/clock/renesas,rzg2l-cpg.yaml b/Documentation/devicetree/bindings/clock/renesas,rzg2l-cpg.yaml index fe2fba18ae84..80a8c7114c31 100644 --- a/Documentation/devicetree/bindings/clock/renesas,rzg2l-cpg.yaml +++ b/Documentation/devicetree/bindings/clock/renesas,rzg2l-cpg.yaml @@ -27,6 +27,7 @@ properties: - renesas,r9a07g043-cpg # RZ/G2UL{Type-1,Type-2} and RZ/Five - renesas,r9a07g044-cpg # RZ/G2{L,LC} - renesas,r9a07g054-cpg # RZ/V2L + - renesas,r9a08g045-cpg # RZ/G3S - renesas,r9a09g011-cpg # RZ/V2M reg: diff --git a/include/dt-bindings/clock/r9a08g045-cpg.h b/include/dt-bindings/clock/r9a08g045-cpg.h new file mode 100644 index 000000000000..410725b778a8 --- /dev/null +++ b/include/dt-bindings/clock/r9a08g045-cpg.h @@ -0,0 +1,242 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) + * + * Copyright (C) 2023 Renesas Electronics Corp. + */ +#ifndef __DT_BINDINGS_CLOCK_R9A08G045_CPG_H__ +#define __DT_BINDINGS_CLOCK_R9A08G045_CPG_H__ + +#include + +/* R9A08G045 CPG Core Clocks */ +#define R9A08G045_CLK_I 0 +#define R9A08G045_CLK_I2 1 +#define R9A08G045_CLK_I3 2 +#define R9A08G045_CLK_S0 3 +#define R9A08G045_CLK_SPI0 4 +#define R9A08G045_CLK_SPI1 5 +#define R9A08G045_CLK_SD0 6 +#define R9A08G045_CLK_SD1 7 +#define R9A08G045_CLK_SD2 8 +#define R9A08G045_CLK_M0 9 +#define R9A08G045_CLK_HP 10 +#define R9A08G045_CLK_TSU 11 +#define R9A08G045_CLK_ZT 12 +#define R9A08G045_CLK_P0 13 +#define R9A08G045_CLK_P1 14 +#define R9A08G045_CLK_P2 15 +#define R9A08G045_CLK_P3 16 +#define R9A08G045_CLK_P4 17 +#define R9A08G045_CLK_P5 18 +#define R9A08G045_CLK_AT 19 +#define R9A08G045_CLK_OC0 20 +#define R9A08G045_CLK_OC1 21 +#define R9A08G045_OSCCLK 22 +#define R9A08G045_OSCCLK2 23 +#define R9A08G045_SWD 24 + +/* R9A08G045 Module Clocks */ +#define R9A08G045_OCTA_ACLK 0 +#define R9A08G045_OCTA_MCLK 1 +#define R9A08G045_CA55_SCLK 2 +#define R9A08G045_CA55_PCLK 3 +#define R9A08G045_CA55_ATCLK 4 +#define R9A08G045_CA55_GICCLK 5 +#define R9A08G045_CA55_PERICLK 6 +#define R9A08G045_CA55_ACLK 7 +#define R9A08G045_CA55_TSCLK 8 +#define R9A08G045_SRAM_ACPU_ACLK0 9 +#define R9A08G045_SRAM_ACPU_ACLK1 10 +#define R9A08G045_SRAM_ACPU_ACLK2 11 +#define R9A08G045_GIC600_GICCLK 12 +#define R9A08G045_IA55_CLK 13 +#define R9A08G045_IA55_PCLK 14 +#define R9A08G045_MHU_PCLK 15 +#define R9A08G045_SYC_CNT_CLK 16 +#define R9A08G045_DMAC_ACLK 17 +#define R9A08G045_DMAC_PCLK 18 +#define R9A08G045_OSTM0_PCLK 19 +#define R9A08G045_OSTM1_PCLK 20 +#define R9A08G045_OSTM2_PCLK 21 +#define R9A08G045_OSTM3_PCLK 22 +#define R9A08G045_OSTM4_PCLK 23 +#define R9A08G045_OSTM5_PCLK 24 +#define R9A08G045_OSTM6_PCLK 25 +#define R9A08G045_OSTM7_PCLK 26 +#define R9A08G045_MTU_X_MCK_MTU3 27 +#define R9A08G045_POE3_CLKM_POE 28 +#define R9A08G045_GPT_PCLK 29 +#define R9A08G045_POEG_A_CLKP 30 +#define R9A08G045_POEG_B_CLKP 31 +#define R9A08G045_POEG_C_CLKP 32 +#define R9A08G045_POEG_D_CLKP 33 +#define R9A08G045_WDT0_PCLK 34 +#define R9A08G045_WDT0_CLK 35 +#define R9A08G045_WDT1_PCLK 36 +#define R9A08G045_WDT1_CLK 37 +#define R9A08G045_WDT2_PCLK 38 +#define R9A08G045_WDT2_CLK 39 +#define R9A08G045_SPI_HCLK 40 +#define R9A08G045_SPI_ACLK 41 +#define R9A08G045_SPI_CLK 42 +#define R9A08G045_SPI_CLKX2 43 +#define R9A08G045_SDHI0_IMCLK 44 +#define R9A08G045_SDHI0_IMCLK2 45 +#define R9A08G045_SDHI0_CLK_HS 46 +#define R9A08G045_SDHI0_ACLK 47 +#define R9A08G045_SDHI1_IMCLK 48 +#define R9A08G045_SDHI1_IMCLK2 49 +#define R9A08G045_SDHI1_CLK_HS 50 +#define R9A08G045_SDHI1_ACLK 51 +#define R9A08G045_SDHI2_IMCLK 52 +#define R9A08G045_SDHI2_IMCLK2 53 +#define R9A08G045_SDHI2_CLK_HS 54 +#define R9A08G045_SDHI2_ACLK 55 +#define R9A08G045_SSI0_PCLK2 56 +#define R9A08G045_SSI0_PCLK_SFR 57 +#define R9A08G045_SSI1_PCLK2 58 +#define R9A08G045_SSI1_PCLK_SFR 59 +#define R9A08G045_SSI2_PCLK2 60 +#define R9A08G045_SSI2_PCLK_SFR 61 +#define R9A08G045_SSI3_PCLK2 62 +#define R9A08G045_SSI3_PCLK_SFR 63 +#define R9A08G045_SRC_CLKP 64 +#define R9A08G045_USB_U2H0_HCLK 65 +#define R9A08G045_USB_U2H1_HCLK 66 +#define R9A08G045_USB_U2P_EXR_CPUCLK 67 +#define R9A08G045_USB_PCLK 68 +#define R9A08G045_ETH0_CLK_AXI 69 +#define R9A08G045_ETH0_CLK_CHI 70 +#define R9A08G045_ETH0_REFCLK 71 +#define R9A08G045_ETH1_CLK_AXI 72 +#define R9A08G045_ETH1_CLK_CHI 73 +#define R9A08G045_ETH1_REFCLK 74 +#define R9A08G045_I2C0_PCLK 75 +#define R9A08G045_I2C1_PCLK 76 +#define R9A08G045_I2C2_PCLK 77 +#define R9A08G045_I2C3_PCLK 78 +#define R9A08G045_SCIF0_CLK_PCK 79 +#define R9A08G045_SCIF1_CLK_PCK 80 +#define R9A08G045_SCIF2_CLK_PCK 81 +#define R9A08G045_SCIF3_CLK_PCK 82 +#define R9A08G045_SCIF4_CLK_PCK 83 +#define R9A08G045_SCIF5_CLK_PCK 84 +#define R9A08G045_SCI0_CLKP 85 +#define R9A08G045_SCI1_CLKP 86 +#define R9A08G045_IRDA_CLKP 87 +#define R9A08G045_RSPI0_CLKB 88 +#define R9A08G045_RSPI1_CLKB 89 +#define R9A08G045_RSPI2_CLKB 90 +#define R9A08G045_RSPI3_CLKB 91 +#define R9A08G045_RSPI4_CLKB 92 +#define R9A08G045_CANFD_PCLK 93 +#define R9A08G045_CANFD_CLK_RAM 94 +#define R9A08G045_GPIO_HCLK 95 +#define R9A08G045_ADC_ADCLK 96 +#define R9A08G045_ADC_PCLK 97 +#define R9A08G045_TSU_PCLK 98 +#define R9A08G045_PDM_PCLK 99 +#define R9A08G045_PDM_CCLK 100 +#define R9A08G045_PCI_ACLK 101 +#define R9A08G045_PCI_CLKL1PM 102 +#define R9A08G045_SPDIF_PCLK 103 +#define R9A08G045_I3C_PCLK 104 +#define R9A08G045_I3C_TCLK 105 +#define R9A08G045_VBAT_BCLK 106 + +/* R9A08G045 Resets */ +#define R9A08G045_CA55_RST_1_0 0 +#define R9A08G045_CA55_RST_3_0 1 +#define R9A08G045_CA55_RST_4 2 +#define R9A08G045_CA55_RST_5 3 +#define R9A08G045_CA55_RST_6 4 +#define R9A08G045_CA55_RST_7 5 +#define R9A08G045_CA55_RST_8 6 +#define R9A08G045_CA55_RST_9 7 +#define R9A08G045_CA55_RST_10 8 +#define R9A08G045_CA55_RST_11 9 +#define R9A08G045_CA55_RST_12 10 +#define R9A08G045_SRAM_ACPU_ARESETN0 11 +#define R9A08G045_SRAM_ACPU_ARESETN1 12 +#define R9A08G045_SRAM_ACPU_ARESETN2 13 +#define R9A08G045_GIC600_GICRESET_N 14 +#define R9A08G045_GIC600_DBG_GICRESET_N 15 +#define R9A08G045_IA55_RESETN 16 +#define R9A08G045_MHU_RESETN 17 +#define R9A08G045_DMAC_ARESETN 18 +#define R9A08G045_DMAC_RST_ASYNC 19 +#define R9A08G045_SYC_RESETN 20 +#define R9A08G045_OSTM0_PRESETZ 21 +#define R9A08G045_OSTM1_PRESETZ 22 +#define R9A08G045_OSTM2_PRESETZ 23 +#define R9A08G045_OSTM3_PRESETZ 24 +#define R9A08G045_OSTM4_PRESETZ 25 +#define R9A08G045_OSTM5_PRESETZ 26 +#define R9A08G045_OSTM6_PRESETZ 27 +#define R9A08G045_OSTM7_PRESETZ 28 +#define R9A08G045_MTU_X_PRESET_MTU3 29 +#define R9A08G045_POE3_RST_M_REG 30 +#define R9A08G045_GPT_RST_C 31 +#define R9A08G045_POEG_A_RST 32 +#define R9A08G045_POEG_B_RST 33 +#define R9A08G045_POEG_C_RST 34 +#define R9A08G045_POEG_D_RST 35 +#define R9A08G045_WDT0_PRESETN 36 +#define R9A08G045_WDT1_PRESETN 37 +#define R9A08G045_WDT2_PRESETN 38 +#define R9A08G045_SPI_HRESETN 39 +#define R9A08G045_SPI_ARESETN 40 +#define R9A08G045_SDHI0_IXRST 41 +#define R9A08G045_SDHI1_IXRST 42 +#define R9A08G045_SDHI2_IXRST 43 +#define R9A08G045_SSI0_RST_M2_REG 44 +#define R9A08G045_SSI1_RST_M2_REG 45 +#define R9A08G045_SSI2_RST_M2_REG 46 +#define R9A08G045_SSI3_RST_M2_REG 47 +#define R9A08G045_SRC_RST 48 +#define R9A08G045_USB_U2H0_HRESETN 49 +#define R9A08G045_USB_U2H1_HRESETN 50 +#define R9A08G045_USB_U2P_EXL_SYSRST 51 +#define R9A08G045_USB_PRESETN 52 +#define R9A08G045_ETH0_RST_HW_N 53 +#define R9A08G045_ETH1_RST_HW_N 54 +#define R9A08G045_I2C0_MRST 55 +#define R9A08G045_I2C1_MRST 56 +#define R9A08G045_I2C2_MRST 57 +#define R9A08G045_I2C3_MRST 58 +#define R9A08G045_SCIF0_RST_SYSTEM_N 59 +#define R9A08G045_SCIF1_RST_SYSTEM_N 60 +#define R9A08G045_SCIF2_RST_SYSTEM_N 61 +#define R9A08G045_SCIF3_RST_SYSTEM_N 62 +#define R9A08G045_SCIF4_RST_SYSTEM_N 63 +#define R9A08G045_SCIF5_RST_SYSTEM_N 64 +#define R9A08G045_SCI0_RST 65 +#define R9A08G045_SCI1_RST 66 +#define R9A08G045_IRDA_RST 67 +#define R9A08G045_RSPI0_RST 68 +#define R9A08G045_RSPI1_RST 69 +#define R9A08G045_RSPI2_RST 70 +#define R9A08G045_RSPI3_RST 71 +#define R9A08G045_RSPI4_RST 72 +#define R9A08G045_CANFD_RSTP_N 73 +#define R9A08G045_CANFD_RSTC_N 74 +#define R9A08G045_GPIO_RSTN 75 +#define R9A08G045_GPIO_PORT_RESETN 76 +#define R9A08G045_GPIO_SPARE_RESETN 77 +#define R9A08G045_ADC_PRESETN 78 +#define R9A08G045_ADC_ADRST_N 79 +#define R9A08G045_TSU_PRESETN 80 +#define R9A08G045_OCTA_ARESETN 81 +#define R9A08G045_PDM0_PRESETNT 82 +#define R9A08G045_PCI_ARESETN 83 +#define R9A08G045_PCI_RST_B 84 +#define R9A08G045_PCI_RST_GP_B 85 +#define R9A08G045_PCI_RST_PS_B 86 +#define R9A08G045_PCI_RST_RSM_B 87 +#define R9A08G045_PCI_RST_CFG_B 88 +#define R9A08G045_PCI_RST_LOAD_B 89 +#define R9A08G045_SPDIF_RST 90 +#define R9A08G045_I3C_TRESETN 91 +#define R9A08G045_I3C_PRESETN 92 +#define R9A08G045_VBAT_BRESETN 93 + +#endif /* __DT_BINDINGS_CLOCK_R9A08G045_CPG_H__ */ -- cgit v1.2.3-59-g8ed1b From d5252d9697a3e7007c741e9c103073868955a304 Mon Sep 17 00:00:00 2001 From: Dirk Behme Date: Thu, 28 Sep 2023 10:03:17 +0200 Subject: clk: renesas: rcar-gen3: Extend SDnH divider table The clock dividers might be used with clock stop bit enabled or not. Current tables only support recommended values from the datasheet. This might result in warnings like below because no valid clock divider is found. Resulting in a 0 divider. There are Renesas ARM Trusted Firmware version out there which e.g. configure 0x201 (shifted logical right by 2: 0x80) and with this match the added { STPnHCK | 0, 1 }: https://github.com/renesas-rcar/arm-trusted-firmware/blob/rcar_gen3_v2.3/drivers/renesas/rcar/emmc/emmc_init.c#L108 ------------[ cut here ]------------ sd1h: Zero divisor and CLK_DIVIDER_ALLOW_ZERO not set WARNING: CPU: 1 PID: 1 at drivers/clk/clk-divider.c:141 divider_recalc_rate+0x48/0x70 Modules linked in: CPU: 1 PID: 1 Comm: swapper/0 Not tainted 6.1.52 #1 Hardware name: Custom board based on r8a7796 (DT) pstate: 40000005 (nZcv daif -PAN -UAO -TCO -DIT -SSBS BTYPE=--) pc : divider_recalc_rate+0x48/0x70 ... ------------[ cut here ]------------ Fixes: bb6d3fa98a41 ("clk: renesas: rcar-gen3: Switch to new SD clock handling") Signed-off-by: Dirk Behme [wsa: extended the table to 5 entries, added comments, reword commit message a little] Signed-off-by: Wolfram Sang Tested-by: Dirk Behme Reviewed-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/20230928080317.28224-1-wsa+renesas@sang-engineering.com Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/rcar-cpg-lib.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/drivers/clk/renesas/rcar-cpg-lib.c b/drivers/clk/renesas/rcar-cpg-lib.c index e2e0447de190..5a15f8788b92 100644 --- a/drivers/clk/renesas/rcar-cpg-lib.c +++ b/drivers/clk/renesas/rcar-cpg-lib.c @@ -70,8 +70,21 @@ void cpg_simple_notifier_register(struct raw_notifier_head *notifiers, #define STPnHCK BIT(9 - SDnSRCFC_SHIFT) static const struct clk_div_table cpg_sdh_div_table[] = { + /* + * These values are recommended by the datasheet. Because they come + * first, Linux will only use these. + */ { 0, 1 }, { 1, 2 }, { STPnHCK | 2, 4 }, { STPnHCK | 3, 8 }, - { STPnHCK | 4, 16 }, { 0, 0 }, + { STPnHCK | 4, 16 }, + /* + * These values are not recommended because STPnHCK is wrong. But they + * have been seen because of broken firmware. So, we support reading + * them but Linux will sanitize them when initializing through + * recalc_rate. + */ + { STPnHCK | 0, 1 }, { STPnHCK | 1, 2 }, { 2, 4 }, { 3, 8 }, { 4, 16 }, + /* Sentinel */ + { 0, 0 } }; struct clk * __init cpg_sdh_clk_register(const char *name, -- cgit v1.2.3-59-g8ed1b From 549f4ae2601f968e2474c6031fb4799468882f64 Mon Sep 17 00:00:00 2001 From: Claudiu Beznea Date: Fri, 29 Sep 2023 08:38:49 +0300 Subject: clk: renesas: rzg2l: Wait for status bit of SD mux before continuing The hardware user manual for RZ/G2L (r01uh0914ej0130-rzg2l-rzg2lc.pdf, chapter 7.4.7 Procedure for Switching Clocks by the Dynamic Switching Frequency Selectors) specifies that we need to check CPG_PL2SDHI_DSEL for SD clock switching status. Fixes: eaff33646f4cb ("clk: renesas: rzg2l: Add SDHI clk mux support") Signed-off-by: Claudiu Beznea Reviewed-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/20230929053915.1530607-3-claudiu.beznea@bp.renesas.com Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/rzg2l-cpg.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/drivers/clk/renesas/rzg2l-cpg.c b/drivers/clk/renesas/rzg2l-cpg.c index 9baae7bb7094..5343d04fd70d 100644 --- a/drivers/clk/renesas/rzg2l-cpg.c +++ b/drivers/clk/renesas/rzg2l-cpg.c @@ -188,7 +188,8 @@ static int rzg2l_cpg_sd_clk_mux_set_parent(struct clk_hw *hw, u8 index) u32 off = GET_REG_OFFSET(hwdata->conf); u32 shift = GET_SHIFT(hwdata->conf); const u32 clk_src_266 = 2; - u32 bitmask; + u32 msk, val, bitmask; + int ret; /* * As per the HW manual, we should not directly switch from 533 MHz to @@ -202,14 +203,10 @@ static int rzg2l_cpg_sd_clk_mux_set_parent(struct clk_hw *hw, u8 index) * the index to value mapping is done by adding 1 to the index. */ bitmask = (GENMASK(GET_WIDTH(hwdata->conf) - 1, 0) << shift) << 16; + msk = off ? CPG_CLKSTATUS_SELSDHI1_STS : CPG_CLKSTATUS_SELSDHI0_STS; if (index != clk_src_266) { - u32 msk, val; - int ret; - writel(bitmask | ((clk_src_266 + 1) << shift), priv->base + off); - msk = off ? CPG_CLKSTATUS_SELSDHI1_STS : CPG_CLKSTATUS_SELSDHI0_STS; - ret = readl_poll_timeout(priv->base + CPG_CLKSTATUS, val, !(val & msk), 100, CPG_SDHI_CLK_SWITCH_STATUS_TIMEOUT_US); @@ -221,7 +218,13 @@ static int rzg2l_cpg_sd_clk_mux_set_parent(struct clk_hw *hw, u8 index) writel(bitmask | ((index + 1) << shift), priv->base + off); - return 0; + ret = readl_poll_timeout(priv->base + CPG_CLKSTATUS, val, + !(val & msk), 100, + CPG_SDHI_CLK_SWITCH_STATUS_TIMEOUT_US); + if (ret) + dev_err(priv->dev, "failed to switch clk source\n"); + + return ret; } static u8 rzg2l_cpg_sd_clk_mux_get_parent(struct clk_hw *hw) -- cgit v1.2.3-59-g8ed1b From d2692ed490e680a41401cef879adebcfafb4298f Mon Sep 17 00:00:00 2001 From: Claudiu Beznea Date: Fri, 29 Sep 2023 08:38:50 +0300 Subject: clk: renesas: rzg2l: Lock around writes to mux register The SD MUX output (SD0) is further divided by 4 in G2{L,UL}. The divided clock is SD0_DIV4. SD0_DIV4 is registered with CLK_SET_RATE_PARENT which means a rate request for it is propagated to the MUX and could reach rzg2l_cpg_sd_clk_mux_set_parent() concurrently with the users of SD0. Add proper locking to avoid concurrent accesses on SD MUX set rate registers. Fixes: eaff33646f4cb ("clk: renesas: rzg2l: Add SDHI clk mux support") Signed-off-by: Claudiu Beznea Reviewed-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/20230929053915.1530607-4-claudiu.beznea@bp.renesas.com Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/rzg2l-cpg.c | 23 +++++++++++++---------- drivers/clk/renesas/rzg2l-cpg.h | 2 +- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/drivers/clk/renesas/rzg2l-cpg.c b/drivers/clk/renesas/rzg2l-cpg.c index 5343d04fd70d..0679f2c7649e 100644 --- a/drivers/clk/renesas/rzg2l-cpg.c +++ b/drivers/clk/renesas/rzg2l-cpg.c @@ -189,6 +189,7 @@ static int rzg2l_cpg_sd_clk_mux_set_parent(struct clk_hw *hw, u8 index) u32 shift = GET_SHIFT(hwdata->conf); const u32 clk_src_266 = 2; u32 msk, val, bitmask; + unsigned long flags; int ret; /* @@ -204,23 +205,25 @@ static int rzg2l_cpg_sd_clk_mux_set_parent(struct clk_hw *hw, u8 index) */ bitmask = (GENMASK(GET_WIDTH(hwdata->conf) - 1, 0) << shift) << 16; msk = off ? CPG_CLKSTATUS_SELSDHI1_STS : CPG_CLKSTATUS_SELSDHI0_STS; + spin_lock_irqsave(&priv->rmw_lock, flags); if (index != clk_src_266) { writel(bitmask | ((clk_src_266 + 1) << shift), priv->base + off); - ret = readl_poll_timeout(priv->base + CPG_CLKSTATUS, val, - !(val & msk), 100, - CPG_SDHI_CLK_SWITCH_STATUS_TIMEOUT_US); - if (ret) { - dev_err(priv->dev, "failed to switch clk source\n"); - return ret; - } + ret = readl_poll_timeout_atomic(priv->base + CPG_CLKSTATUS, val, + !(val & msk), 10, + CPG_SDHI_CLK_SWITCH_STATUS_TIMEOUT_US); + if (ret) + goto unlock; } writel(bitmask | ((index + 1) << shift), priv->base + off); - ret = readl_poll_timeout(priv->base + CPG_CLKSTATUS, val, - !(val & msk), 100, - CPG_SDHI_CLK_SWITCH_STATUS_TIMEOUT_US); + ret = readl_poll_timeout_atomic(priv->base + CPG_CLKSTATUS, val, + !(val & msk), 10, + CPG_SDHI_CLK_SWITCH_STATUS_TIMEOUT_US); +unlock: + spin_unlock_irqrestore(&priv->rmw_lock, flags); + if (ret) dev_err(priv->dev, "failed to switch clk source\n"); diff --git a/drivers/clk/renesas/rzg2l-cpg.h b/drivers/clk/renesas/rzg2l-cpg.h index 0b28870a6f9d..097fd8f61680 100644 --- a/drivers/clk/renesas/rzg2l-cpg.h +++ b/drivers/clk/renesas/rzg2l-cpg.h @@ -43,7 +43,7 @@ #define CPG_CLKSTATUS_SELSDHI0_STS BIT(28) #define CPG_CLKSTATUS_SELSDHI1_STS BIT(29) -#define CPG_SDHI_CLK_SWITCH_STATUS_TIMEOUT_US 20000 +#define CPG_SDHI_CLK_SWITCH_STATUS_TIMEOUT_US 200 /* n = 0/1/2 for PLL1/4/6 */ #define CPG_SAMPLL_CLK1(n) (0x04 + (16 * n)) -- cgit v1.2.3-59-g8ed1b From bf51d3b2d048c312764a55d91d67a85ee5535e31 Mon Sep 17 00:00:00 2001 From: Claudiu Beznea Date: Fri, 29 Sep 2023 08:38:51 +0300 Subject: clk: renesas: rzg2l: Trust value returned by hardware The onitial value of the CPG_PL2SDHI_DSEL bits 0..1 or 4..6 is 01b. The hardware user's manual (r01uh0914ej0130-rzg2l-rzg2lc.pdf) specifies that setting 0 is prohibited. Hence rzg2l_cpg_sd_clk_mux_get_parent() should just read CPG_PL2SDHI_DSEL, trust the value, and return the proper clock parent index based on the value read. Fixes: eaff33646f4cb ("clk: renesas: rzg2l: Add SDHI clk mux support") Signed-off-by: Claudiu Beznea Reviewed-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/20230929053915.1530607-5-claudiu.beznea@bp.renesas.com Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/rzg2l-cpg.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/drivers/clk/renesas/rzg2l-cpg.c b/drivers/clk/renesas/rzg2l-cpg.c index 0679f2c7649e..6f50f0329ecf 100644 --- a/drivers/clk/renesas/rzg2l-cpg.c +++ b/drivers/clk/renesas/rzg2l-cpg.c @@ -238,14 +238,8 @@ static u8 rzg2l_cpg_sd_clk_mux_get_parent(struct clk_hw *hw) val >>= GET_SHIFT(hwdata->conf); val &= GENMASK(GET_WIDTH(hwdata->conf) - 1, 0); - if (val) { - val--; - } else { - /* Prohibited clk source, change it to 533 MHz(reset value) */ - rzg2l_cpg_sd_clk_mux_set_parent(hw, 0); - } - return val; + return val ? val - 1 : 0; } static const struct clk_ops rzg2l_cpg_sd_clk_mux_ops = { -- cgit v1.2.3-59-g8ed1b From a2b23159499efd36b2d63b3c4534075d12ddc97a Mon Sep 17 00:00:00 2001 From: Claudiu Beznea Date: Fri, 29 Sep 2023 08:38:52 +0300 Subject: clk: renesas: rzg2l: Fix computation formula According to the hardware manual for RZ/G2L (r01uh0914ej0130-rzg2l-rzg2lc.pdf), the computation formula for PLL rate is as follows: Fout = ((m + k/65536) * Fin) / (p * 2^s) and k has values in the range [-32768, 32767]. Dividing k by 65536 with integer arithmetic gives zero all the time, causing slight differences b/w what has been set vs. what is displayed. Thus, get rid of this and decompose the formula before dividing k by 65536. Fixes: ef3c613ccd68a ("clk: renesas: Add CPG core wrapper for RZ/G2L SoC") Signed-off-by: Claudiu Beznea Reviewed-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/20230929053915.1530607-6-claudiu.beznea@bp.renesas.com Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/rzg2l-cpg.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/clk/renesas/rzg2l-cpg.c b/drivers/clk/renesas/rzg2l-cpg.c index 6f50f0329ecf..a4723dd3a070 100644 --- a/drivers/clk/renesas/rzg2l-cpg.c +++ b/drivers/clk/renesas/rzg2l-cpg.c @@ -42,7 +42,7 @@ #define GET_SHIFT(val) ((val >> 12) & 0xff) #define GET_WIDTH(val) ((val >> 8) & 0xf) -#define KDIV(val) FIELD_GET(GENMASK(31, 16), val) +#define KDIV(val) ((s16)FIELD_GET(GENMASK(31, 16), val)) #define MDIV(val) FIELD_GET(GENMASK(15, 6), val) #define PDIV(val) FIELD_GET(GENMASK(5, 0), val) #define SDIV(val) FIELD_GET(GENMASK(2, 0), val) @@ -695,18 +695,18 @@ static unsigned long rzg2l_cpg_pll_clk_recalc_rate(struct clk_hw *hw, 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; + u64 rate; 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) << SDIV(val2); - return DIV_ROUND_CLOSEST_ULL((u64)parent_rate * mult, div); + rate = mul_u64_u32_shr(parent_rate, (MDIV(val1) << 16) + KDIV(val1), + 16 + SDIV(val2)); + + return DIV_ROUND_CLOSEST_ULL(rate, PDIV(val1)); } static const struct clk_ops rzg2l_cpg_pll_ops = { -- cgit v1.2.3-59-g8ed1b From 5f710e3bc5987373737470f98798bbd49134a2e0 Mon Sep 17 00:00:00 2001 From: Claudiu Beznea Date: Fri, 29 Sep 2023 08:38:53 +0300 Subject: clk: renesas: rzg2l: Remove critical area The spinlock in rzg2l_mod_clock_endisable() is intended to protect RMW-accesses to the hardware register. There is no need to protect instructions that set temporary variables which will be written afterwards to a hardware register. With this only one write to one clock register is executed thus locking/unlocking rmw_lock is removed. Signed-off-by: Claudiu Beznea Reviewed-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/20230929053915.1530607-7-claudiu.beznea@bp.renesas.com Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/rzg2l-cpg.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/clk/renesas/rzg2l-cpg.c b/drivers/clk/renesas/rzg2l-cpg.c index a4723dd3a070..3e4773b13076 100644 --- a/drivers/clk/renesas/rzg2l-cpg.c +++ b/drivers/clk/renesas/rzg2l-cpg.c @@ -895,7 +895,6 @@ static int rzg2l_mod_clock_endisable(struct clk_hw *hw, bool enable) struct rzg2l_cpg_priv *priv = clock->priv; unsigned int reg = clock->off; struct device *dev = priv->dev; - unsigned long flags; u32 bitmask = BIT(clock->bit); u32 value; int error; @@ -907,14 +906,12 @@ static int rzg2l_mod_clock_endisable(struct clk_hw *hw, bool enable) 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); value = bitmask << 16; if (enable) value |= bitmask; - writel(value, priv->base + CLK_ON_R(reg)); - spin_unlock_irqrestore(&priv->rmw_lock, flags); + writel(value, priv->base + CLK_ON_R(reg)); if (!enable) return 0; -- cgit v1.2.3-59-g8ed1b From 01eabef547e63d80086acd3f247d36c5f9f92456 Mon Sep 17 00:00:00 2001 From: Claudiu Beznea Date: Fri, 29 Sep 2023 08:38:54 +0300 Subject: clk: renesas: rzg2l: Add support for RZ/G3S PLL Add support for reading the frequency of PLL1/4/6 as available on RZ/G3S. The computation formula for the PLL frequency is as follows: Fout = (nir + nfr / 4096) * Fin / (mr * pr) Signed-off-by: Claudiu Beznea Reviewed-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/20230929053915.1530607-8-claudiu.beznea@bp.renesas.com Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/rzg2l-cpg.c | 49 +++++++++++++++++++++++++++++++++++++---- drivers/clk/renesas/rzg2l-cpg.h | 3 +++ 2 files changed, 48 insertions(+), 4 deletions(-) diff --git a/drivers/clk/renesas/rzg2l-cpg.c b/drivers/clk/renesas/rzg2l-cpg.c index 3e4773b13076..f8ab433a4253 100644 --- a/drivers/clk/renesas/rzg2l-cpg.c +++ b/drivers/clk/renesas/rzg2l-cpg.c @@ -47,6 +47,11 @@ #define PDIV(val) FIELD_GET(GENMASK(5, 0), val) #define SDIV(val) FIELD_GET(GENMASK(2, 0), val) +#define RZG3S_DIV_P GENMASK(28, 26) +#define RZG3S_DIV_M GENMASK(25, 22) +#define RZG3S_DIV_NI GENMASK(21, 13) +#define RZG3S_DIV_NF GENMASK(12, 1) + #define CLK_ON_R(reg) (reg) #define CLK_MON_R(reg) (0x180 + (reg)) #define CLK_RST_R(reg) (reg) @@ -713,11 +718,43 @@ static const struct clk_ops rzg2l_cpg_pll_ops = { .recalc_rate = rzg2l_cpg_pll_clk_recalc_rate, }; +static unsigned long rzg3s_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; + u32 nir, nfr, mr, pr, val; + u64 rate; + + if (pll_clk->type != CLK_TYPE_G3S_PLL) + return parent_rate; + + val = readl(priv->base + GET_REG_SAMPLL_CLK1(pll_clk->conf)); + + pr = 1 << FIELD_GET(RZG3S_DIV_P, val); + /* Hardware interprets values higher than 8 as p = 16. */ + if (pr > 8) + pr = 16; + + mr = FIELD_GET(RZG3S_DIV_M, val) + 1; + nir = FIELD_GET(RZG3S_DIV_NI, val) + 1; + nfr = FIELD_GET(RZG3S_DIV_NF, val); + + rate = mul_u64_u32_shr(parent_rate, 4096 * nir + nfr, 12); + + return DIV_ROUND_CLOSEST_ULL(rate, (mr * pr)); +} + +static const struct clk_ops rzg3s_cpg_pll_ops = { + .recalc_rate = rzg3s_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 rzg2l_cpg_priv *priv, + const struct clk_ops *ops) { struct device *dev = priv->dev; const struct clk *parent; @@ -735,7 +772,7 @@ rzg2l_cpg_pll_clk_register(const struct cpg_core_clk *core, parent_name = __clk_get_name(parent); init.name = core->name; - init.ops = &rzg2l_cpg_pll_ops; + init.ops = ops; init.flags = 0; init.parent_names = &parent_name; init.num_parents = 1; @@ -830,8 +867,12 @@ rzg2l_cpg_register_core_clk(const struct cpg_core_clk *core, core->mult, div); break; case CLK_TYPE_SAM_PLL: - clk = rzg2l_cpg_pll_clk_register(core, priv->clks, - priv->base, priv); + clk = rzg2l_cpg_pll_clk_register(core, priv->clks, priv->base, priv, + &rzg2l_cpg_pll_ops); + break; + case CLK_TYPE_G3S_PLL: + clk = rzg2l_cpg_pll_clk_register(core, priv->clks, priv->base, priv, + &rzg3s_cpg_pll_ops); break; case CLK_TYPE_SIPLL5: clk = rzg2l_cpg_sipll5_register(core, priv->clks, priv); diff --git a/drivers/clk/renesas/rzg2l-cpg.h b/drivers/clk/renesas/rzg2l-cpg.h index 097fd8f61680..20da0c620b90 100644 --- a/drivers/clk/renesas/rzg2l-cpg.h +++ b/drivers/clk/renesas/rzg2l-cpg.h @@ -102,6 +102,7 @@ enum clk_types { CLK_TYPE_IN, /* External Clock Input */ CLK_TYPE_FF, /* Fixed Factor Clock */ CLK_TYPE_SAM_PLL, + CLK_TYPE_G3S_PLL, /* Clock with divider */ CLK_TYPE_DIV, @@ -129,6 +130,8 @@ enum clk_types { 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_G3S_PLL(_name, _id, _parent, _conf) \ + DEF_TYPE(_name, _id, CLK_TYPE_G3S_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) \ -- cgit v1.2.3-59-g8ed1b From 97c1c4ccda76d2919775d748cf223637cf0e82ae Mon Sep 17 00:00:00 2001 From: Claudiu Beznea Date: Fri, 29 Sep 2023 08:38:55 +0300 Subject: clk: renesas: rzg2l: Add struct clk_hw_data Add clk_hw_data struct that keeps the core part of the clock data. sd_hw_data embeds a member of type struct clk_hw_data along with other members (in the next commits). This commit prepares the field for refactoring the SD MUX clock driver. Signed-off-by: Claudiu Beznea Reviewed-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/20230929053915.1530607-9-claudiu.beznea@bp.renesas.com Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/rzg2l-cpg.c | 52 +++++++++++++++++++++++++++-------------- 1 file changed, 34 insertions(+), 18 deletions(-) diff --git a/drivers/clk/renesas/rzg2l-cpg.c b/drivers/clk/renesas/rzg2l-cpg.c index f8ab433a4253..6ca81d22c669 100644 --- a/drivers/clk/renesas/rzg2l-cpg.c +++ b/drivers/clk/renesas/rzg2l-cpg.c @@ -63,13 +63,29 @@ #define MAX_VCLK_FREQ (148500000) -struct sd_hw_data { +/** + * struct clk_hw_data - clock hardware data + * @hw: clock hw + * @conf: clock configuration (register offset, shift, width) + * @priv: CPG private data structure + */ +struct clk_hw_data { struct clk_hw hw; u32 conf; struct rzg2l_cpg_priv *priv; }; -#define to_sd_hw_data(_hw) container_of(_hw, struct sd_hw_data, hw) +#define to_clk_hw_data(_hw) container_of(_hw, struct clk_hw_data, hw) + +/** + * struct sd_hw_data - SD clock hardware data + * @hw_data: clock hw data + */ +struct sd_hw_data { + struct clk_hw_data hw_data; +}; + +#define to_sd_hw_data(_hw) container_of(_hw, struct sd_hw_data, hw_data) struct rzg2l_pll5_param { u32 pl5_fracin; @@ -188,10 +204,10 @@ rzg2l_cpg_mux_clk_register(const struct cpg_core_clk *core, static int rzg2l_cpg_sd_clk_mux_set_parent(struct clk_hw *hw, u8 index) { - struct sd_hw_data *hwdata = to_sd_hw_data(hw); - struct rzg2l_cpg_priv *priv = hwdata->priv; - u32 off = GET_REG_OFFSET(hwdata->conf); - u32 shift = GET_SHIFT(hwdata->conf); + struct clk_hw_data *clk_hw_data = to_clk_hw_data(hw); + struct rzg2l_cpg_priv *priv = clk_hw_data->priv; + u32 off = GET_REG_OFFSET(clk_hw_data->conf); + u32 shift = GET_SHIFT(clk_hw_data->conf); const u32 clk_src_266 = 2; u32 msk, val, bitmask; unsigned long flags; @@ -208,7 +224,7 @@ static int rzg2l_cpg_sd_clk_mux_set_parent(struct clk_hw *hw, u8 index) * The clock mux has 3 input clocks(533 MHz, 400 MHz, and 266 MHz), and * the index to value mapping is done by adding 1 to the index. */ - bitmask = (GENMASK(GET_WIDTH(hwdata->conf) - 1, 0) << shift) << 16; + bitmask = (GENMASK(GET_WIDTH(clk_hw_data->conf) - 1, 0) << shift) << 16; msk = off ? CPG_CLKSTATUS_SELSDHI1_STS : CPG_CLKSTATUS_SELSDHI0_STS; spin_lock_irqsave(&priv->rmw_lock, flags); if (index != clk_src_266) { @@ -237,12 +253,12 @@ unlock: static u8 rzg2l_cpg_sd_clk_mux_get_parent(struct clk_hw *hw) { - struct sd_hw_data *hwdata = to_sd_hw_data(hw); - struct rzg2l_cpg_priv *priv = hwdata->priv; - u32 val = readl(priv->base + GET_REG_OFFSET(hwdata->conf)); + struct clk_hw_data *clk_hw_data = to_clk_hw_data(hw); + struct rzg2l_cpg_priv *priv = clk_hw_data->priv; + u32 val = readl(priv->base + GET_REG_OFFSET(clk_hw_data->conf)); - val >>= GET_SHIFT(hwdata->conf); - val &= GENMASK(GET_WIDTH(hwdata->conf) - 1, 0); + val >>= GET_SHIFT(clk_hw_data->conf); + val &= GENMASK(GET_WIDTH(clk_hw_data->conf) - 1, 0); return val ? val - 1 : 0; } @@ -258,17 +274,17 @@ rzg2l_cpg_sd_mux_clk_register(const struct cpg_core_clk *core, void __iomem *base, struct rzg2l_cpg_priv *priv) { - struct sd_hw_data *clk_hw_data; + struct sd_hw_data *sd_hw_data; struct clk_init_data init; struct clk_hw *clk_hw; int ret; - clk_hw_data = devm_kzalloc(priv->dev, sizeof(*clk_hw_data), GFP_KERNEL); - if (!clk_hw_data) + sd_hw_data = devm_kzalloc(priv->dev, sizeof(*sd_hw_data), GFP_KERNEL); + if (!sd_hw_data) return ERR_PTR(-ENOMEM); - clk_hw_data->priv = priv; - clk_hw_data->conf = core->conf; + sd_hw_data->hw_data.priv = priv; + sd_hw_data->hw_data.conf = core->conf; init.name = core->name; init.ops = &rzg2l_cpg_sd_clk_mux_ops; @@ -276,7 +292,7 @@ rzg2l_cpg_sd_mux_clk_register(const struct cpg_core_clk *core, init.num_parents = core->num_parents; init.parent_names = core->parent_names; - clk_hw = &clk_hw_data->hw; + clk_hw = &sd_hw_data->hw_data.hw; clk_hw->init = &init; ret = devm_clk_hw_register(priv->dev, clk_hw); -- cgit v1.2.3-59-g8ed1b From 3e8008fcf6b7f7c65ad2718c18fb79f37007f1a5 Mon Sep 17 00:00:00 2001 From: Claudiu Beznea Date: Fri, 29 Sep 2023 08:38:56 +0300 Subject: clk: renesas: rzg2l: Remove CPG_SDHI_DSEL from generic header Remove CPG_SDHI_DSEL and its bits from the generic header as RZ/G3S has different offset registers and bits for this, thus avoid mixing them. Signed-off-by: Claudiu Beznea Reviewed-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/20230929053915.1530607-10-claudiu.beznea@bp.renesas.com Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/r9a07g043-cpg.c | 7 +++++++ drivers/clk/renesas/r9a07g044-cpg.c | 7 +++++++ drivers/clk/renesas/rzg2l-cpg.h | 4 ---- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/drivers/clk/renesas/r9a07g043-cpg.c b/drivers/clk/renesas/r9a07g043-cpg.c index 1a7a6d60aca4..e0ae25644e1a 100644 --- a/drivers/clk/renesas/r9a07g043-cpg.c +++ b/drivers/clk/renesas/r9a07g043-cpg.c @@ -14,6 +14,13 @@ #include "rzg2l-cpg.h" +/* Specific registers. */ +#define CPG_PL2SDHI_DSEL (0x218) + +/* Clock select configuration. */ +#define SEL_SDHI0 SEL_PLL_PACK(CPG_PL2SDHI_DSEL, 0, 2) +#define SEL_SDHI1 SEL_PLL_PACK(CPG_PL2SDHI_DSEL, 4, 2) + enum clk_ids { /* Core Clock Outputs exported to DT */ LAST_DT_CORE_CLK = R9A07G043_CLK_P0_DIV2, diff --git a/drivers/clk/renesas/r9a07g044-cpg.c b/drivers/clk/renesas/r9a07g044-cpg.c index c597414a94d8..d4dcf5d896d4 100644 --- a/drivers/clk/renesas/r9a07g044-cpg.c +++ b/drivers/clk/renesas/r9a07g044-cpg.c @@ -15,6 +15,13 @@ #include "rzg2l-cpg.h" +/* Specific registers. */ +#define CPG_PL2SDHI_DSEL (0x218) + +/* Clock select configuration. */ +#define SEL_SDHI0 SEL_PLL_PACK(CPG_PL2SDHI_DSEL, 0, 2) +#define SEL_SDHI1 SEL_PLL_PACK(CPG_PL2SDHI_DSEL, 4, 2) + enum clk_ids { /* Core Clock Outputs exported to DT */ LAST_DT_CORE_CLK = R9A07G054_CLK_DRP_A, diff --git a/drivers/clk/renesas/rzg2l-cpg.h b/drivers/clk/renesas/rzg2l-cpg.h index 20da0c620b90..f5382333d327 100644 --- a/drivers/clk/renesas/rzg2l-cpg.h +++ b/drivers/clk/renesas/rzg2l-cpg.h @@ -19,7 +19,6 @@ #define CPG_PL2_DDIV (0x204) #define CPG_PL3A_DDIV (0x208) #define CPG_PL6_DDIV (0x210) -#define CPG_PL2SDHI_DSEL (0x218) #define CPG_CLKSTATUS (0x280) #define CPG_PL3_SSEL (0x408) #define CPG_PL6_SSEL (0x414) @@ -69,9 +68,6 @@ #define SEL_PLL6_2 SEL_PLL_PACK(CPG_PL6_ETH_SSEL, 0, 1) #define SEL_GPU2 SEL_PLL_PACK(CPG_PL6_SSEL, 12, 1) -#define SEL_SDHI0 DDIV_PACK(CPG_PL2SDHI_DSEL, 0, 2) -#define SEL_SDHI1 DDIV_PACK(CPG_PL2SDHI_DSEL, 4, 2) - #define EXTAL_FREQ_IN_MEGA_HZ (24) /** -- cgit v1.2.3-59-g8ed1b From 096b256c9a786b42199fcb63ef5d9f65c312a3f6 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Tue, 12 Sep 2023 10:55:30 -0700 Subject: clk: Drive clk_leaf_mux_set_rate_parent test from clk_ops Running this kunit test with lockdep enabled leads to warning splats about calling clk provider APIs without the clk_prepare lock held. I proposed adding a wrapper around these APIs to grab the prepare lock so we can call them from anywhere, and Maxime implemented that approach[1], but it didn't look great. That's because we had to make more kunit testing APIs just to call code from a place that isn't a clk provider when the prepare lock isn't held. Instead of doing that, let's implement a determine_rate clk_op for a new leaf clk that is the child of the existing leaf clk. We can call __clk_determine_rate() on the existing leaf clk from there, and stash away the clk_rate_request struct to check once the clk_op returns. Drive that clk_op by calling clk_round_rate() to keep things similar to how it was before (i.e. nothing actually changes rate, just the new rate is determined). This silences the warning by driving the test from a clk_op where we know the prepare lock is held. While looking at this in more detail, it was determined that the code we intended to test in commit 262ca38f4b6e ("clk: Stop forwarding clk_rate_requests to the parent") wasn't actually tested. The call to __clk_determine_rate() wasn't actually getting to the newly introduced code under the CLK_SET_RATE_PARENT if condition in clk_core_round_rate_nolock() because the parent clk (the mux) could round rates. We introduce a new leaf and make sure the parent of that clk has no clk_ops so that we can be certain that the CLK_SET_RATE_PARENT condition in clk_core_round_rate_nolock() is evaluated. Reported-by: Guenter Roeck Closes: https://lore.kernel.org/linux-clk/2b594e50-2bbf-4a2d-88e6-49fc39f3957a@roeck-us.net/ Reported-by: kernel test robot Closes: https://lore.kernel.org/oe-lkp/202301310919.b9d56ee3-yujie.liu@intel.com Cc: Maxime Ripard Link: https://lore.kernel.org/r/20230721-clk-fix-kunit-lockdep-v1-0-32cdba4c8fc1@kernel.org [1] Fixes: 262ca38f4b6e ("clk: Stop forwarding clk_rate_requests to the parent") Link: https://lore.kernel.org/r/20230912175534.2427862-2-sboyd@kernel.org Acked-by: Maxime Ripard Signed-off-by: Stephen Boyd --- drivers/clk/clk_test.c | 65 +++++++++++++++++++++++++++++++++++++------------- 1 file changed, 48 insertions(+), 17 deletions(-) diff --git a/drivers/clk/clk_test.c b/drivers/clk/clk_test.c index a154ec9d0111..43e85fc0b025 100644 --- a/drivers/clk/clk_test.c +++ b/drivers/clk/clk_test.c @@ -10,6 +10,8 @@ #include +static const struct clk_ops empty_clk_ops = { }; + #define DUMMY_CLOCK_INIT_RATE (42 * 1000 * 1000) #define DUMMY_CLOCK_RATE_1 (142 * 1000 * 1000) #define DUMMY_CLOCK_RATE_2 (242 * 1000 * 1000) @@ -2155,6 +2157,30 @@ static struct kunit_suite clk_range_minimize_test_suite = { struct clk_leaf_mux_ctx { struct clk_multiple_parent_ctx mux_ctx; struct clk_hw hw; + struct clk_hw parent; + struct clk_rate_request *req; +}; + +static int clk_leaf_mux_determine_rate(struct clk_hw *hw, struct clk_rate_request *req) +{ + struct clk_leaf_mux_ctx *ctx = container_of(hw, struct clk_leaf_mux_ctx, hw); + int ret; + struct clk_rate_request *parent_req = ctx->req; + + clk_hw_forward_rate_request(hw, req, req->best_parent_hw, parent_req, req->rate); + ret = __clk_determine_rate(req->best_parent_hw, parent_req); + if (ret) + return ret; + + req->rate = parent_req->rate; + + return 0; +} + +static const struct clk_ops clk_leaf_mux_set_rate_parent_ops = { + .determine_rate = clk_leaf_mux_determine_rate, + .set_parent = clk_dummy_single_set_parent, + .get_parent = clk_dummy_single_get_parent, }; static int @@ -2193,8 +2219,14 @@ clk_leaf_mux_set_rate_parent_test_init(struct kunit *test) if (ret) return ret; - ctx->hw.init = CLK_HW_INIT_HW("test-clock", &ctx->mux_ctx.hw, - &clk_dummy_single_parent_ops, + ctx->parent.init = CLK_HW_INIT_HW("test-parent", &ctx->mux_ctx.hw, + &empty_clk_ops, CLK_SET_RATE_PARENT); + ret = clk_hw_register(NULL, &ctx->parent); + if (ret) + return ret; + + ctx->hw.init = CLK_HW_INIT_HW("test-clock", &ctx->parent, + &clk_leaf_mux_set_rate_parent_ops, CLK_SET_RATE_PARENT); ret = clk_hw_register(NULL, &ctx->hw); if (ret) @@ -2208,32 +2240,31 @@ static void clk_leaf_mux_set_rate_parent_test_exit(struct kunit *test) struct clk_leaf_mux_ctx *ctx = test->priv; clk_hw_unregister(&ctx->hw); + clk_hw_unregister(&ctx->parent); clk_hw_unregister(&ctx->mux_ctx.hw); clk_hw_unregister(&ctx->mux_ctx.parents_ctx[0].hw); clk_hw_unregister(&ctx->mux_ctx.parents_ctx[1].hw); } /* - * Test that, for a clock that will forward any rate request to its - * parent, the rate request structure returned by __clk_determine_rate - * is sane and will be what we expect. + * Test that, for a clock that will forward any rate request to its parent, the + * rate request structure returned by __clk_determine_rate() is sane and + * doesn't have the clk_rate_request's best_parent_hw pointer point to the + * clk_hw passed into __clk_determine_rate(). See commit 262ca38f4b6e ("clk: + * Stop forwarding clk_rate_requests to the parent") for more background. */ -static void clk_leaf_mux_set_rate_parent_determine_rate(struct kunit *test) +static void clk_leaf_mux_set_rate_parent__clk_determine_rate_proper_parent(struct kunit *test) { struct clk_leaf_mux_ctx *ctx = test->priv; struct clk_hw *hw = &ctx->hw; struct clk *clk = clk_hw_get_clk(hw, NULL); struct clk_rate_request req; unsigned long rate; - int ret; + ctx->req = &req; rate = clk_get_rate(clk); KUNIT_ASSERT_EQ(test, rate, DUMMY_CLOCK_RATE_1); - - clk_hw_init_rate_request(hw, &req, DUMMY_CLOCK_RATE_2); - - ret = __clk_determine_rate(hw, &req); - KUNIT_ASSERT_EQ(test, ret, 0); + KUNIT_ASSERT_EQ(test, DUMMY_CLOCK_RATE_2, clk_round_rate(clk, DUMMY_CLOCK_RATE_2)); KUNIT_EXPECT_EQ(test, req.rate, DUMMY_CLOCK_RATE_2); KUNIT_EXPECT_EQ(test, req.best_parent_rate, DUMMY_CLOCK_RATE_2); @@ -2243,15 +2274,15 @@ static void clk_leaf_mux_set_rate_parent_determine_rate(struct kunit *test) } static struct kunit_case clk_leaf_mux_set_rate_parent_test_cases[] = { - KUNIT_CASE(clk_leaf_mux_set_rate_parent_determine_rate), + KUNIT_CASE(clk_leaf_mux_set_rate_parent__clk_determine_rate_proper_parent), {} }; /* - * Test suite for a clock whose parent is a mux with multiple parents. - * The leaf clock has CLK_SET_RATE_PARENT, and will forward rate - * requests to the mux, which will then select which parent is the best - * fit for a given rate. + * Test suite for a clock whose parent is a pass-through clk whose parent is a + * mux with multiple parents. The leaf and pass-through clocks have the + * CLK_SET_RATE_PARENT flag, and will forward rate requests to the mux, which + * will then select which parent is the best fit for a given rate. * * These tests exercise the behaviour of muxes, and the proper selection * of parents. -- cgit v1.2.3-59-g8ed1b From 831187c6946f29ba8309d386d5ca466eec8b9f79 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Tue, 12 Sep 2023 10:55:31 -0700 Subject: clk: Parameterize clk_leaf_mux_set_rate_parent Transform the existing clk_leaf_mux_set_rate_parent test into a parameterized test that calls the various determine rate APIs that exist for clk providers. This ensures that whatever determine rate API is used by a clk provider will return the correct parent in the best_parent_hw pointer of the clk_rate_request because clk_rate_requests are forwarded properly. Cc: Guenter Roeck Cc: Maxime Ripard Link: https://lore.kernel.org/r/20230912175534.2427862-3-sboyd@kernel.org Acked-by: Maxime Ripard Signed-off-by: Stephen Boyd --- drivers/clk/clk_test.c | 81 +++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 73 insertions(+), 8 deletions(-) diff --git a/drivers/clk/clk_test.c b/drivers/clk/clk_test.c index 43e85fc0b025..39e2b5ff4f51 100644 --- a/drivers/clk/clk_test.c +++ b/drivers/clk/clk_test.c @@ -2159,6 +2159,7 @@ struct clk_leaf_mux_ctx { struct clk_hw hw; struct clk_hw parent; struct clk_rate_request *req; + int (*determine_rate_func)(struct clk_hw *hw, struct clk_rate_request *req); }; static int clk_leaf_mux_determine_rate(struct clk_hw *hw, struct clk_rate_request *req) @@ -2168,7 +2169,7 @@ static int clk_leaf_mux_determine_rate(struct clk_hw *hw, struct clk_rate_reques struct clk_rate_request *parent_req = ctx->req; clk_hw_forward_rate_request(hw, req, req->best_parent_hw, parent_req, req->rate); - ret = __clk_determine_rate(req->best_parent_hw, parent_req); + ret = ctx->determine_rate_func(req->best_parent_hw, parent_req); if (ret) return ret; @@ -2246,20 +2247,83 @@ static void clk_leaf_mux_set_rate_parent_test_exit(struct kunit *test) clk_hw_unregister(&ctx->mux_ctx.parents_ctx[1].hw); } +struct clk_leaf_mux_set_rate_parent_determine_rate_test_case { + const char *desc; + int (*determine_rate_func)(struct clk_hw *hw, struct clk_rate_request *req); +}; + +static void +clk_leaf_mux_set_rate_parent_determine_rate_test_case_to_desc( + const struct clk_leaf_mux_set_rate_parent_determine_rate_test_case *t, char *desc) +{ + strcpy(desc, t->desc); +} + +static const struct clk_leaf_mux_set_rate_parent_determine_rate_test_case +clk_leaf_mux_set_rate_parent_determine_rate_test_cases[] = { + { + /* + * Test that __clk_determine_rate() on the parent that can't + * change rate doesn't return a clk_rate_request structure with + * the best_parent_hw pointer pointing to the parent. + */ + .desc = "clk_leaf_mux_set_rate_parent__clk_determine_rate_proper_parent", + .determine_rate_func = __clk_determine_rate, + }, + { + /* + * Test that __clk_mux_determine_rate() on the parent that + * can't change rate doesn't return a clk_rate_request + * structure with the best_parent_hw pointer pointing to + * the parent. + */ + .desc = "clk_leaf_mux_set_rate_parent__clk_mux_determine_rate_proper_parent", + .determine_rate_func = __clk_mux_determine_rate, + }, + { + /* + * Test that __clk_mux_determine_rate_closest() on the parent + * that can't change rate doesn't return a clk_rate_request + * structure with the best_parent_hw pointer pointing to + * the parent. + */ + .desc = "clk_leaf_mux_set_rate_parent__clk_mux_determine_rate_closest_proper_parent", + .determine_rate_func = __clk_mux_determine_rate_closest, + }, + { + /* + * Test that clk_hw_determine_rate_no_reparent() on the parent + * that can't change rate doesn't return a clk_rate_request + * structure with the best_parent_hw pointer pointing to + * the parent. + */ + .desc = "clk_leaf_mux_set_rate_parent_clk_hw_determine_rate_no_reparent_proper_parent", + .determine_rate_func = clk_hw_determine_rate_no_reparent, + }, +}; + +KUNIT_ARRAY_PARAM(clk_leaf_mux_set_rate_parent_determine_rate_test, + clk_leaf_mux_set_rate_parent_determine_rate_test_cases, + clk_leaf_mux_set_rate_parent_determine_rate_test_case_to_desc) + /* - * Test that, for a clock that will forward any rate request to its parent, the - * rate request structure returned by __clk_determine_rate() is sane and - * doesn't have the clk_rate_request's best_parent_hw pointer point to the - * clk_hw passed into __clk_determine_rate(). See commit 262ca38f4b6e ("clk: - * Stop forwarding clk_rate_requests to the parent") for more background. + * Test that when a clk that can't change rate itself calls a function like + * __clk_determine_rate() on its parent it doesn't get back a clk_rate_request + * structure that has the best_parent_hw pointer point to the clk_hw passed + * into the determine rate function. See commit 262ca38f4b6e ("clk: Stop + * forwarding clk_rate_requests to the parent") for more background. */ -static void clk_leaf_mux_set_rate_parent__clk_determine_rate_proper_parent(struct kunit *test) +static void clk_leaf_mux_set_rate_parent_determine_rate_test(struct kunit *test) { struct clk_leaf_mux_ctx *ctx = test->priv; struct clk_hw *hw = &ctx->hw; struct clk *clk = clk_hw_get_clk(hw, NULL); struct clk_rate_request req; unsigned long rate; + const struct clk_leaf_mux_set_rate_parent_determine_rate_test_case *test_param; + + test_param = test->param_value; + ctx->determine_rate_func = test_param->determine_rate_func; ctx->req = &req; rate = clk_get_rate(clk); @@ -2274,7 +2338,8 @@ static void clk_leaf_mux_set_rate_parent__clk_determine_rate_proper_parent(struc } static struct kunit_case clk_leaf_mux_set_rate_parent_test_cases[] = { - KUNIT_CASE(clk_leaf_mux_set_rate_parent__clk_determine_rate_proper_parent), + KUNIT_CASE_PARAM(clk_leaf_mux_set_rate_parent_determine_rate_test, + clk_leaf_mux_set_rate_parent_determine_rate_test_gen_params), {} }; -- cgit v1.2.3-59-g8ed1b From 6fc469ab7fe50e03abef0550482613d736bd1e9b Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 29 Sep 2023 14:03:43 +0200 Subject: clk: cdce925: Convert to use maple tree register cache The maple tree register cache is based on a much more modern data structure than the rbtree cache and makes optimisation choices which are probably more appropriate for modern systems than those made by the rbtree cache. Signed-off-by: Mark Brown Link: https://lore.kernel.org/r/20230929-clk-rbtree-cdce925-v1-1-a36b459002f7@kernel.org Signed-off-by: Stephen Boyd --- drivers/clk/clk-cdce925.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/clk-cdce925.c b/drivers/clk/clk-cdce925.c index cdee4958f26d..5ffaf1255ff7 100644 --- a/drivers/clk/clk-cdce925.c +++ b/drivers/clk/clk-cdce925.c @@ -647,7 +647,7 @@ static int cdce925_probe(struct i2c_client *client) .name = "configuration0", .reg_bits = 8, .val_bits = 8, - .cache_type = REGCACHE_RBTREE, + .cache_type = REGCACHE_MAPLE, }; dev_dbg(&client->dev, "%s\n", __func__); -- cgit v1.2.3-59-g8ed1b From 29171344a1cdbf2b897cbbef78649fd0e90f6d67 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 29 Sep 2023 14:21:59 +0200 Subject: clk: si514: Convert to use maple tree register cache The maple tree register cache is based on a much more modern data structure than the rbtree cache and makes optimisation choices which are probably more appropriate for modern systems than those made by the rbtree cache. Signed-off-by: Mark Brown Link: https://lore.kernel.org/r/20230929-clk-maple-si-v1-1-e26cfcaf27bd@kernel.org Signed-off-by: Stephen Boyd --- drivers/clk/clk-si514.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/clk-si514.c b/drivers/clk/clk-si514.c index e8c18afac184..6ee148e5469d 100644 --- a/drivers/clk/clk-si514.c +++ b/drivers/clk/clk-si514.c @@ -321,7 +321,7 @@ static bool si514_regmap_is_writeable(struct device *dev, unsigned int reg) static const struct regmap_config si514_regmap_config = { .reg_bits = 8, .val_bits = 8, - .cache_type = REGCACHE_RBTREE, + .cache_type = REGCACHE_MAPLE, .max_register = SI514_REG_CONTROL, .writeable_reg = si514_regmap_is_writeable, .volatile_reg = si514_regmap_is_volatile, -- cgit v1.2.3-59-g8ed1b From e2ec8f6631739b9319239f5be6354758ad04fb09 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 29 Sep 2023 14:22:00 +0200 Subject: clk: si5341: Convert to use maple tree register cache The maple tree register cache is based on a much more modern data structure than the rbtree cache and makes optimisation choices which are probably more appropriate for modern systems than those made by the rbtree cache. Signed-off-by: Mark Brown Link: https://lore.kernel.org/r/20230929-clk-maple-si-v1-2-e26cfcaf27bd@kernel.org Signed-off-by: Stephen Boyd --- drivers/clk/clk-si5341.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/clk-si5341.c b/drivers/clk/clk-si5341.c index 9599857842c7..845b451511d2 100644 --- a/drivers/clk/clk-si5341.c +++ b/drivers/clk/clk-si5341.c @@ -1260,7 +1260,7 @@ static int si5341_wait_device_ready(struct i2c_client *client) static const struct regmap_config si5341_regmap_config = { .reg_bits = 8, .val_bits = 8, - .cache_type = REGCACHE_RBTREE, + .cache_type = REGCACHE_MAPLE, .ranges = si5341_regmap_ranges, .num_ranges = ARRAY_SIZE(si5341_regmap_ranges), .max_register = SI5341_REGISTER_MAX, -- cgit v1.2.3-59-g8ed1b From 41d2288629b9a627c4b55f05c6c6998b1e62726d Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 29 Sep 2023 14:22:01 +0200 Subject: clk: si5351: Convert to use maple tree register cache The maple tree register cache is based on a much more modern data structure than the rbtree cache and makes optimisation choices which are probably more appropriate for modern systems than those made by the rbtree cache. Signed-off-by: Mark Brown Link: https://lore.kernel.org/r/20230929-clk-maple-si-v1-3-e26cfcaf27bd@kernel.org Signed-off-by: Stephen Boyd --- drivers/clk/clk-si5351.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/clk-si5351.c b/drivers/clk/clk-si5351.c index 00fb9b09e030..cbf7cde01157 100644 --- a/drivers/clk/clk-si5351.c +++ b/drivers/clk/clk-si5351.c @@ -206,7 +206,7 @@ static bool si5351_regmap_is_writeable(struct device *dev, unsigned int reg) static const struct regmap_config si5351_regmap_config = { .reg_bits = 8, .val_bits = 8, - .cache_type = REGCACHE_RBTREE, + .cache_type = REGCACHE_MAPLE, .max_register = 187, .writeable_reg = si5351_regmap_is_writeable, .volatile_reg = si5351_regmap_is_volatile, -- cgit v1.2.3-59-g8ed1b From 8df090919db2d566233757879adf4ee09de7e818 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 29 Sep 2023 14:22:02 +0200 Subject: clk: si544: Convert to use maple tree register cache The maple tree register cache is based on a much more modern data structure than the rbtree cache and makes optimisation choices which are probably more appropriate for modern systems than those made by the rbtree cache. Signed-off-by: Mark Brown Link: https://lore.kernel.org/r/20230929-clk-maple-si-v1-4-e26cfcaf27bd@kernel.org Signed-off-by: Stephen Boyd --- drivers/clk/clk-si544.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/clk-si544.c b/drivers/clk/clk-si544.c index 22925968aa35..c4288cf83f9f 100644 --- a/drivers/clk/clk-si544.c +++ b/drivers/clk/clk-si544.c @@ -446,7 +446,7 @@ static bool si544_regmap_is_volatile(struct device *dev, unsigned int reg) static const struct regmap_config si544_regmap_config = { .reg_bits = 8, .val_bits = 8, - .cache_type = REGCACHE_RBTREE, + .cache_type = REGCACHE_MAPLE, .max_register = SI544_REG_PAGE_SELECT, .volatile_reg = si544_regmap_is_volatile, }; -- cgit v1.2.3-59-g8ed1b From ebb7a1919f44303abe7623ce2ead4fb948d48fd2 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 29 Sep 2023 14:22:03 +0200 Subject: clk: si570: Convert to use maple tree register cache The maple tree register cache is based on a much more modern data structure than the rbtree cache and makes optimisation choices which are probably more appropriate for modern systems than those made by the rbtree cache. Signed-off-by: Mark Brown Link: https://lore.kernel.org/r/20230929-clk-maple-si-v1-5-e26cfcaf27bd@kernel.org Signed-off-by: Stephen Boyd --- drivers/clk/clk-si570.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/clk-si570.c b/drivers/clk/clk-si570.c index de0212fb5f87..262f582c9213 100644 --- a/drivers/clk/clk-si570.c +++ b/drivers/clk/clk-si570.c @@ -392,7 +392,7 @@ static bool si570_regmap_is_writeable(struct device *dev, unsigned int reg) static const struct regmap_config si570_regmap_config = { .reg_bits = 8, .val_bits = 8, - .cache_type = REGCACHE_RBTREE, + .cache_type = REGCACHE_MAPLE, .max_register = 137, .writeable_reg = si570_regmap_is_writeable, .volatile_reg = si570_regmap_is_volatile, -- cgit v1.2.3-59-g8ed1b From df43983922c2307ff0b796913e0ca614f8f51705 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 29 Sep 2023 16:26:05 +0200 Subject: clk: versaclock3: Remove redundant _is_writeable() The versaclock3 driver provides an _is_writeable() function which returns true for all registers. This is the default assumption for regmaps so we can remove the function for a very minor improvement in performance and code size. Signed-off-by: Mark Brown Link: https://lore.kernel.org/r/20230929-clk-maple-versaclk-v1-1-24dd5b3d8689@kernel.org Signed-off-by: Stephen Boyd --- drivers/clk/clk-versaclock3.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/clk/clk-versaclock3.c b/drivers/clk/clk-versaclock3.c index 7ab2447bd203..a5ab48ff242c 100644 --- a/drivers/clk/clk-versaclock3.c +++ b/drivers/clk/clk-versaclock3.c @@ -586,17 +586,11 @@ static const struct clk_ops vc3_clk_mux_ops = { .get_parent = vc3_clk_mux_get_parent, }; -static bool vc3_regmap_is_writeable(struct device *dev, unsigned int reg) -{ - return true; -} - static const struct regmap_config vc3_regmap_config = { .reg_bits = 8, .val_bits = 8, .cache_type = REGCACHE_RBTREE, .max_register = 0x24, - .writeable_reg = vc3_regmap_is_writeable, }; static struct vc3_hw_data clk_div[5]; -- cgit v1.2.3-59-g8ed1b From 4b58a0144b1b041818f89851eea87606a3cd80a1 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 29 Sep 2023 16:26:06 +0200 Subject: clk: versaclock3: Convert to use maple tree register cache The maple tree register cache is based on a much more modern data structure than the rbtree cache and makes optimisation choices which are probably more appropriate for modern systems than those made by the rbtree cache. Signed-off-by: Mark Brown Link: https://lore.kernel.org/r/20230929-clk-maple-versaclk-v1-2-24dd5b3d8689@kernel.org Signed-off-by: Stephen Boyd --- drivers/clk/clk-versaclock3.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/clk-versaclock3.c b/drivers/clk/clk-versaclock3.c index a5ab48ff242c..b4a89c083c11 100644 --- a/drivers/clk/clk-versaclock3.c +++ b/drivers/clk/clk-versaclock3.c @@ -589,7 +589,7 @@ static const struct clk_ops vc3_clk_mux_ops = { static const struct regmap_config vc3_regmap_config = { .reg_bits = 8, .val_bits = 8, - .cache_type = REGCACHE_RBTREE, + .cache_type = REGCACHE_MAPLE, .max_register = 0x24, }; -- cgit v1.2.3-59-g8ed1b From 2902ba682ae1b59687b5ae8794202a4649e62954 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 29 Sep 2023 16:26:07 +0200 Subject: clk: versaclock5: Convert to use maple tree register cache The maple tree register cache is based on a much more modern data structure than the rbtree cache and makes optimisation choices which are probably more appropriate for modern systems than those made by the rbtree cache. Signed-off-by: Mark Brown Link: https://lore.kernel.org/r/20230929-clk-maple-versaclk-v1-3-24dd5b3d8689@kernel.org Signed-off-by: Stephen Boyd --- drivers/clk/clk-versaclock5.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/clk-versaclock5.c b/drivers/clk/clk-versaclock5.c index 17cbb30d20ad..6d31cd54d7cf 100644 --- a/drivers/clk/clk-versaclock5.c +++ b/drivers/clk/clk-versaclock5.c @@ -217,7 +217,7 @@ static bool vc5_regmap_is_writeable(struct device *dev, unsigned int reg) static const struct regmap_config vc5_regmap_config = { .reg_bits = 8, .val_bits = 8, - .cache_type = REGCACHE_RBTREE, + .cache_type = REGCACHE_MAPLE, .max_register = 0x76, .writeable_reg = vc5_regmap_is_writeable, }; -- cgit v1.2.3-59-g8ed1b From 9e952929dfe22aa1566d930f363213e1ccfe004d Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 29 Sep 2023 16:26:08 +0200 Subject: clk: versaclock7: Convert to use maple tree register cache The maple tree register cache is based on a much more modern data structure than the rbtree cache and makes optimisation choices which are probably more appropriate for modern systems than those made by the rbtree cache. Signed-off-by: Mark Brown Link: https://lore.kernel.org/r/20230929-clk-maple-versaclk-v1-4-24dd5b3d8689@kernel.org Signed-off-by: Stephen Boyd --- drivers/clk/clk-versaclock7.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/clk-versaclock7.c b/drivers/clk/clk-versaclock7.c index 9ab35c1af0ff..f323263e32c3 100644 --- a/drivers/clk/clk-versaclock7.c +++ b/drivers/clk/clk-versaclock7.c @@ -1275,7 +1275,7 @@ static const struct regmap_config vc7_regmap_config = { .ranges = vc7_range_cfg, .num_ranges = ARRAY_SIZE(vc7_range_cfg), .volatile_reg = vc7_volatile_reg, - .cache_type = REGCACHE_RBTREE, + .cache_type = REGCACHE_MAPLE, .can_multi_write = true, .reg_format_endian = REGMAP_ENDIAN_LITTLE, .val_format_endian = REGMAP_ENDIAN_LITTLE, -- cgit v1.2.3-59-g8ed1b From 16b86e5c03c5b3ef35bf5126b35384faa97428f0 Mon Sep 17 00:00:00 2001 From: Claudiu Beznea Date: Fri, 6 Oct 2023 13:39:57 +0300 Subject: clk: renesas: rzg2l: Refactor SD mux driver Refactor SD MUX driver to be able to reuse the same code on RZ/G3S. RZ/G2{L,UL} has a limitation with regards to switching the clock source for SD MUX (MUX clock source has to be switched to 266MHz before switching b/w 533MHz and 400MHz). Rework the handling of this limitation to use a clock notifier that is registered according to platform based initialization data, so the SD MUX code can be reused on RZ/G3S. As RZ/G2{L,UL} and RZ/G3S use different bits in different registers to check if the clock switching has been done, this configuration (register offset, register bits and bitfield width) is now passed through struct cpg_core_clk::sconf (status configuration) from platform specific initialization code. Along with struct cpg_core_clk::sconf the mux table indices are also passed from platform specific initialization code. Also, mux flags are now passed to DEF_SD_MUX() as they will be used later by RZ/G3S. CPG_WEN_BIT macro has been introduced to select properly the WEN bit of various registers. Signed-off-by: Claudiu Beznea Reviewed-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/20231006103959.197485-3-claudiu.beznea.uj@bp.renesas.com Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/r9a07g043-cpg.c | 12 ++- drivers/clk/renesas/r9a07g044-cpg.c | 12 ++- drivers/clk/renesas/rzg2l-cpg.c | 150 ++++++++++++++++++++++++++---------- drivers/clk/renesas/rzg2l-cpg.h | 16 ++-- 4 files changed, 139 insertions(+), 51 deletions(-) diff --git a/drivers/clk/renesas/r9a07g043-cpg.c b/drivers/clk/renesas/r9a07g043-cpg.c index e0ae25644e1a..b70bb378ab46 100644 --- a/drivers/clk/renesas/r9a07g043-cpg.c +++ b/drivers/clk/renesas/r9a07g043-cpg.c @@ -21,6 +21,10 @@ #define SEL_SDHI0 SEL_PLL_PACK(CPG_PL2SDHI_DSEL, 0, 2) #define SEL_SDHI1 SEL_PLL_PACK(CPG_PL2SDHI_DSEL, 4, 2) +/* Clock status configuration. */ +#define SEL_SDHI0_STS SEL_PLL_PACK(CPG_CLKSTATUS, 28, 1) +#define SEL_SDHI1_STS SEL_PLL_PACK(CPG_CLKSTATUS, 29, 1) + enum clk_ids { /* Core Clock Outputs exported to DT */ LAST_DT_CORE_CLK = R9A07G043_CLK_P0_DIV2, @@ -85,6 +89,8 @@ static const char * const sel_pll3_3[] = { ".pll3_533", ".pll3_400" }; static const char * const sel_pll6_2[] = { ".pll6_250", ".pll5_250" }; static const char * const sel_shdi[] = { ".clk_533", ".clk_400", ".clk_266" }; +static const u32 mtable_sdhi[] = { 1, 2, 3 }; + static const struct cpg_core_clk r9a07g043_core_clks[] __initconst = { /* External Clock Inputs */ DEF_INPUT("extal", CLK_EXTAL), @@ -130,8 +136,10 @@ static const struct cpg_core_clk r9a07g043_core_clks[] __initconst = { DEF_MUX("HP", R9A07G043_CLK_HP, SEL_PLL6_2, sel_pll6_2), DEF_FIXED("SPI0", R9A07G043_CLK_SPI0, CLK_DIV_PLL3_C, 1, 2), DEF_FIXED("SPI1", R9A07G043_CLK_SPI1, CLK_DIV_PLL3_C, 1, 4), - DEF_SD_MUX("SD0", R9A07G043_CLK_SD0, SEL_SDHI0, sel_shdi), - DEF_SD_MUX("SD1", R9A07G043_CLK_SD1, SEL_SDHI1, sel_shdi), + DEF_SD_MUX("SD0", R9A07G043_CLK_SD0, SEL_SDHI0, SEL_SDHI0_STS, sel_shdi, + mtable_sdhi, 0, rzg2l_cpg_sd_clk_mux_notifier), + DEF_SD_MUX("SD1", R9A07G043_CLK_SD1, SEL_SDHI1, SEL_SDHI0_STS, sel_shdi, + mtable_sdhi, 0, rzg2l_cpg_sd_clk_mux_notifier), DEF_FIXED("SD0_DIV4", CLK_SD0_DIV4, R9A07G043_CLK_SD0, 1, 4), DEF_FIXED("SD1_DIV4", CLK_SD1_DIV4, R9A07G043_CLK_SD1, 1, 4), }; diff --git a/drivers/clk/renesas/r9a07g044-cpg.c b/drivers/clk/renesas/r9a07g044-cpg.c index d4dcf5d896d4..1047278c9079 100644 --- a/drivers/clk/renesas/r9a07g044-cpg.c +++ b/drivers/clk/renesas/r9a07g044-cpg.c @@ -22,6 +22,10 @@ #define SEL_SDHI0 SEL_PLL_PACK(CPG_PL2SDHI_DSEL, 0, 2) #define SEL_SDHI1 SEL_PLL_PACK(CPG_PL2SDHI_DSEL, 4, 2) +/* Clock status configuration. */ +#define SEL_SDHI0_STS SEL_PLL_PACK(CPG_CLKSTATUS, 28, 1) +#define SEL_SDHI1_STS SEL_PLL_PACK(CPG_CLKSTATUS, 29, 1) + enum clk_ids { /* Core Clock Outputs exported to DT */ LAST_DT_CORE_CLK = R9A07G054_CLK_DRP_A, @@ -105,6 +109,8 @@ static const char * const sel_pll6_2[] = { ".pll6_250", ".pll5_250" }; static const char * const sel_shdi[] = { ".clk_533", ".clk_400", ".clk_266" }; static const char * const sel_gpu2[] = { ".pll6", ".pll3_div2_2" }; +static const u32 mtable_sdhi[] = { 1, 2, 3 }; + static const struct { struct cpg_core_clk common[56]; #ifdef CONFIG_CLK_R9A07G054 @@ -170,8 +176,10 @@ static const struct { DEF_MUX("HP", R9A07G044_CLK_HP, SEL_PLL6_2, sel_pll6_2), DEF_FIXED("SPI0", R9A07G044_CLK_SPI0, CLK_DIV_PLL3_C, 1, 2), DEF_FIXED("SPI1", R9A07G044_CLK_SPI1, CLK_DIV_PLL3_C, 1, 4), - DEF_SD_MUX("SD0", R9A07G044_CLK_SD0, SEL_SDHI0, sel_shdi), - DEF_SD_MUX("SD1", R9A07G044_CLK_SD1, SEL_SDHI1, sel_shdi), + DEF_SD_MUX("SD0", R9A07G044_CLK_SD0, SEL_SDHI0, SEL_SDHI0_STS, sel_shdi, + mtable_sdhi, 0, rzg2l_cpg_sd_clk_mux_notifier), + DEF_SD_MUX("SD1", R9A07G044_CLK_SD1, SEL_SDHI1, SEL_SDHI0_STS, sel_shdi, + mtable_sdhi, 0, rzg2l_cpg_sd_clk_mux_notifier), DEF_FIXED("SD0_DIV4", CLK_SD0_DIV4, R9A07G044_CLK_SD0, 1, 4), DEF_FIXED("SD1_DIV4", CLK_SD1_DIV4, R9A07G044_CLK_SD1, 1, 4), DEF_DIV("G", R9A07G044_CLK_G, CLK_SEL_GPU2, DIVGPU, dtable_1_8), diff --git a/drivers/clk/renesas/rzg2l-cpg.c b/drivers/clk/renesas/rzg2l-cpg.c index 6ca81d22c669..8f927568a3c8 100644 --- a/drivers/clk/renesas/rzg2l-cpg.c +++ b/drivers/clk/renesas/rzg2l-cpg.c @@ -61,31 +61,37 @@ #define GET_REG_SAMPLL_CLK1(val) ((val >> 22) & 0xfff) #define GET_REG_SAMPLL_CLK2(val) ((val >> 12) & 0xfff) +#define CPG_WEN_BIT BIT(16) + #define MAX_VCLK_FREQ (148500000) /** * struct clk_hw_data - clock hardware data * @hw: clock hw * @conf: clock configuration (register offset, shift, width) + * @sconf: clock status configuration (register offset, shift, width) * @priv: CPG private data structure */ struct clk_hw_data { struct clk_hw hw; u32 conf; + u32 sconf; struct rzg2l_cpg_priv *priv; }; #define to_clk_hw_data(_hw) container_of(_hw, struct clk_hw_data, hw) /** - * struct sd_hw_data - SD clock hardware data + * struct sd_mux_hw_data - SD MUX clock hardware data * @hw_data: clock hw data + * @mtable: clock mux table */ -struct sd_hw_data { +struct sd_mux_hw_data { struct clk_hw_data hw_data; + const u32 *mtable; }; -#define to_sd_hw_data(_hw) container_of(_hw, struct sd_hw_data, hw_data) +#define to_sd_mux_hw_data(_hw) container_of(_hw, struct sd_mux_hw_data, hw_data) struct rzg2l_pll5_param { u32 pl5_fracin; @@ -142,6 +148,76 @@ static void rzg2l_cpg_del_clk_provider(void *data) of_clk_del_provider(data); } +/* Must be called in atomic context. */ +static int rzg2l_cpg_wait_clk_update_done(void __iomem *base, u32 conf) +{ + u32 bitmask = GENMASK(GET_WIDTH(conf) - 1, 0) << GET_SHIFT(conf); + u32 off = GET_REG_OFFSET(conf); + u32 val; + + return readl_poll_timeout_atomic(base + off, val, !(val & bitmask), 10, 200); +} + +int rzg2l_cpg_sd_clk_mux_notifier(struct notifier_block *nb, unsigned long event, + void *data) +{ + struct clk_notifier_data *cnd = data; + struct clk_hw *hw = __clk_get_hw(cnd->clk); + struct clk_hw_data *clk_hw_data = to_clk_hw_data(hw); + struct rzg2l_cpg_priv *priv = clk_hw_data->priv; + u32 off = GET_REG_OFFSET(clk_hw_data->conf); + u32 shift = GET_SHIFT(clk_hw_data->conf); + const u32 clk_src_266 = 3; + unsigned long flags; + int ret; + + if (event != PRE_RATE_CHANGE || (cnd->new_rate / MEGA == 266)) + return NOTIFY_DONE; + + spin_lock_irqsave(&priv->rmw_lock, flags); + + /* + * As per the HW manual, we should not directly switch from 533 MHz to + * 400 MHz and vice versa. To change the setting from 2’b01 (533 MHz) + * to 2’b10 (400 MHz) or vice versa, Switch to 2’b11 (266 MHz) first, + * and then switch to the target setting (2’b01 (533 MHz) or 2’b10 + * (400 MHz)). + * Setting a value of '0' to the SEL_SDHI0_SET or SEL_SDHI1_SET clock + * switching register is prohibited. + * The clock mux has 3 input clocks(533 MHz, 400 MHz, and 266 MHz), and + * the index to value mapping is done by adding 1 to the index. + */ + + writel((CPG_WEN_BIT | clk_src_266) << shift, priv->base + off); + + /* Wait for the update done. */ + ret = rzg2l_cpg_wait_clk_update_done(priv->base, clk_hw_data->sconf); + + spin_unlock_irqrestore(&priv->rmw_lock, flags); + + if (ret) + dev_err(priv->dev, "failed to switch to safe clk source\n"); + + return notifier_from_errno(ret); +} + +static int rzg2l_register_notifier(struct clk_hw *hw, const struct cpg_core_clk *core, + struct rzg2l_cpg_priv *priv) +{ + struct notifier_block *nb; + + if (!core->notifier) + return 0; + + nb = devm_kzalloc(priv->dev, sizeof(*nb), GFP_KERNEL); + if (!nb) + return -ENOMEM; + + nb->notifier_call = core->notifier; + + return clk_notifier_register(hw->clk, nb); +} + static struct clk * __init rzg2l_cpg_div_clk_register(const struct cpg_core_clk *core, struct clk **clks, @@ -205,48 +281,27 @@ rzg2l_cpg_mux_clk_register(const struct cpg_core_clk *core, static int rzg2l_cpg_sd_clk_mux_set_parent(struct clk_hw *hw, u8 index) { struct clk_hw_data *clk_hw_data = to_clk_hw_data(hw); + struct sd_mux_hw_data *sd_mux_hw_data = to_sd_mux_hw_data(clk_hw_data); struct rzg2l_cpg_priv *priv = clk_hw_data->priv; u32 off = GET_REG_OFFSET(clk_hw_data->conf); u32 shift = GET_SHIFT(clk_hw_data->conf); - const u32 clk_src_266 = 2; - u32 msk, val, bitmask; unsigned long flags; + u32 val; int ret; - /* - * As per the HW manual, we should not directly switch from 533 MHz to - * 400 MHz and vice versa. To change the setting from 2’b01 (533 MHz) - * to 2’b10 (400 MHz) or vice versa, Switch to 2’b11 (266 MHz) first, - * and then switch to the target setting (2’b01 (533 MHz) or 2’b10 - * (400 MHz)). - * Setting a value of '0' to the SEL_SDHI0_SET or SEL_SDHI1_SET clock - * switching register is prohibited. - * The clock mux has 3 input clocks(533 MHz, 400 MHz, and 266 MHz), and - * the index to value mapping is done by adding 1 to the index. - */ - bitmask = (GENMASK(GET_WIDTH(clk_hw_data->conf) - 1, 0) << shift) << 16; - msk = off ? CPG_CLKSTATUS_SELSDHI1_STS : CPG_CLKSTATUS_SELSDHI0_STS; + val = clk_mux_index_to_val(sd_mux_hw_data->mtable, CLK_MUX_ROUND_CLOSEST, index); + spin_lock_irqsave(&priv->rmw_lock, flags); - if (index != clk_src_266) { - writel(bitmask | ((clk_src_266 + 1) << shift), priv->base + off); - - ret = readl_poll_timeout_atomic(priv->base + CPG_CLKSTATUS, val, - !(val & msk), 10, - CPG_SDHI_CLK_SWITCH_STATUS_TIMEOUT_US); - if (ret) - goto unlock; - } - writel(bitmask | ((index + 1) << shift), priv->base + off); + writel((CPG_WEN_BIT | val) << shift, priv->base + off); + + /* Wait for the update done. */ + ret = rzg2l_cpg_wait_clk_update_done(priv->base, clk_hw_data->sconf); - ret = readl_poll_timeout_atomic(priv->base + CPG_CLKSTATUS, val, - !(val & msk), 10, - CPG_SDHI_CLK_SWITCH_STATUS_TIMEOUT_US); -unlock: spin_unlock_irqrestore(&priv->rmw_lock, flags); if (ret) - dev_err(priv->dev, "failed to switch clk source\n"); + dev_err(priv->dev, "Failed to switch parent\n"); return ret; } @@ -254,13 +309,15 @@ unlock: static u8 rzg2l_cpg_sd_clk_mux_get_parent(struct clk_hw *hw) { struct clk_hw_data *clk_hw_data = to_clk_hw_data(hw); + struct sd_mux_hw_data *sd_mux_hw_data = to_sd_mux_hw_data(clk_hw_data); struct rzg2l_cpg_priv *priv = clk_hw_data->priv; - u32 val = readl(priv->base + GET_REG_OFFSET(clk_hw_data->conf)); + u32 val; + val = readl(priv->base + GET_REG_OFFSET(clk_hw_data->conf)); val >>= GET_SHIFT(clk_hw_data->conf); val &= GENMASK(GET_WIDTH(clk_hw_data->conf) - 1, 0); - return val ? val - 1 : 0; + return clk_mux_val_to_index(hw, sd_mux_hw_data->mtable, CLK_MUX_ROUND_CLOSEST, val); } static const struct clk_ops rzg2l_cpg_sd_clk_mux_ops = { @@ -274,31 +331,40 @@ rzg2l_cpg_sd_mux_clk_register(const struct cpg_core_clk *core, void __iomem *base, struct rzg2l_cpg_priv *priv) { - struct sd_hw_data *sd_hw_data; + struct sd_mux_hw_data *sd_mux_hw_data; struct clk_init_data init; struct clk_hw *clk_hw; int ret; - sd_hw_data = devm_kzalloc(priv->dev, sizeof(*sd_hw_data), GFP_KERNEL); - if (!sd_hw_data) + sd_mux_hw_data = devm_kzalloc(priv->dev, sizeof(*sd_mux_hw_data), GFP_KERNEL); + if (!sd_mux_hw_data) return ERR_PTR(-ENOMEM); - sd_hw_data->hw_data.priv = priv; - sd_hw_data->hw_data.conf = core->conf; + sd_mux_hw_data->hw_data.priv = priv; + sd_mux_hw_data->hw_data.conf = core->conf; + sd_mux_hw_data->hw_data.sconf = core->sconf; + sd_mux_hw_data->mtable = core->mtable; init.name = core->name; init.ops = &rzg2l_cpg_sd_clk_mux_ops; - init.flags = 0; + init.flags = core->flag; init.num_parents = core->num_parents; init.parent_names = core->parent_names; - clk_hw = &sd_hw_data->hw_data.hw; + clk_hw = &sd_mux_hw_data->hw_data.hw; clk_hw->init = &init; ret = devm_clk_hw_register(priv->dev, clk_hw); if (ret) return ERR_PTR(ret); + ret = rzg2l_register_notifier(clk_hw, core, priv); + if (ret) { + dev_err(priv->dev, "Failed to register notifier for %s\n", + core->name); + return ERR_PTR(ret); + } + return clk_hw->clk; } diff --git a/drivers/clk/renesas/rzg2l-cpg.h b/drivers/clk/renesas/rzg2l-cpg.h index f5382333d327..f1910913b29a 100644 --- a/drivers/clk/renesas/rzg2l-cpg.h +++ b/drivers/clk/renesas/rzg2l-cpg.h @@ -9,6 +9,8 @@ #ifndef __RENESAS_RZG2L_CPG_H__ #define __RENESAS_RZG2L_CPG_H__ +#include + #define CPG_SIPLL5_STBY (0x140) #define CPG_SIPLL5_CLK1 (0x144) #define CPG_SIPLL5_CLK3 (0x14C) @@ -42,8 +44,6 @@ #define CPG_CLKSTATUS_SELSDHI0_STS BIT(28) #define CPG_CLKSTATUS_SELSDHI1_STS BIT(29) -#define CPG_SDHI_CLK_SWITCH_STATUS_TIMEOUT_US 200 - /* n = 0/1/2 for PLL1/4/6 */ #define CPG_SAMPLL_CLK1(n) (0x04 + (16 * n)) #define CPG_SAMPLL_CLK2(n) (0x08 + (16 * n)) @@ -86,8 +86,11 @@ struct cpg_core_clk { unsigned int mult; unsigned int type; unsigned int conf; + unsigned int sconf; const struct clk_div_table *dtable; + const u32 *mtable; const char * const *parent_names; + notifier_fn_t notifier; u32 flag; u32 mux_flags; int num_parents; @@ -150,10 +153,11 @@ enum clk_types { .parent_names = _parent_names, \ .num_parents = ARRAY_SIZE(_parent_names), \ .mux_flags = CLK_MUX_READ_ONLY) -#define DEF_SD_MUX(_name, _id, _conf, _parent_names) \ - DEF_TYPE(_name, _id, CLK_TYPE_SD_MUX, .conf = _conf, \ +#define DEF_SD_MUX(_name, _id, _conf, _sconf, _parent_names, _mtable, _clk_flags, _notifier) \ + DEF_TYPE(_name, _id, CLK_TYPE_SD_MUX, .conf = _conf, .sconf = _sconf, \ .parent_names = _parent_names, \ - .num_parents = ARRAY_SIZE(_parent_names)) + .num_parents = ARRAY_SIZE(_parent_names), \ + .mtable = _mtable, .flag = _clk_flags, .notifier = _notifier) #define DEF_PLL5_FOUTPOSTDIV(_name, _id, _parent) \ DEF_TYPE(_name, _id, CLK_TYPE_SIPLL5, .parent = _parent) #define DEF_PLL5_4_MUX(_name, _id, _conf, _parent_names) \ @@ -272,4 +276,6 @@ extern const struct rzg2l_cpg_info r9a07g044_cpg_info; extern const struct rzg2l_cpg_info r9a07g054_cpg_info; extern const struct rzg2l_cpg_info r9a09g011_cpg_info; +int rzg2l_cpg_sd_clk_mux_notifier(struct notifier_block *nb, unsigned long event, void *data); + #endif -- cgit v1.2.3-59-g8ed1b From 62b1feac485866494f111e3a6aa4a9ae03a7a2b9 Mon Sep 17 00:00:00 2001 From: Claudiu Beznea Date: Fri, 6 Oct 2023 13:39:58 +0300 Subject: clk: renesas: rzg2l: Add divider clock for RZ/G3S Add a divider clock driver for RZ/G3S. This will be used on RZ/G3S for the SDHI, SPI, OCTA, I, I2, I3, P0, P1, P2, and P3 core clocks. The divider has some limitation for SDHI, OCTA and SPI clocks: - SDHI div cannot be 1 if parent rate is 800MHz, - OCTA, SPI div cannot be 1 if parent rate is 400MHz. To handle these limitations, a notifier is registered from platform specific clock driver, which makes sure proper actions are taken before the clock rate is changed, when needed. Signed-off-by: Claudiu Beznea Reviewed-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/20231006103959.197485-4-claudiu.beznea.uj@bp.renesas.com Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/rzg2l-cpg.c | 186 ++++++++++++++++++++++++++++++++++++++++ drivers/clk/renesas/rzg2l-cpg.h | 11 +++ 2 files changed, 197 insertions(+) diff --git a/drivers/clk/renesas/rzg2l-cpg.c b/drivers/clk/renesas/rzg2l-cpg.c index 8f927568a3c8..49dc6c5c0b0c 100644 --- a/drivers/clk/renesas/rzg2l-cpg.c +++ b/drivers/clk/renesas/rzg2l-cpg.c @@ -93,6 +93,24 @@ struct sd_mux_hw_data { #define to_sd_mux_hw_data(_hw) container_of(_hw, struct sd_mux_hw_data, hw_data) +/** + * struct div_hw_data - divider clock hardware data + * @hw_data: clock hw data + * @dtable: pointer to divider table + * @invalid_rate: invalid rate for divider + * @max_rate: maximum rate for divider + * @width: divider width + */ +struct div_hw_data { + struct clk_hw_data hw_data; + const struct clk_div_table *dtable; + unsigned long invalid_rate; + unsigned long max_rate; + u32 width; +}; + +#define to_div_hw_data(_hw) container_of(_hw, struct div_hw_data, hw_data) + struct rzg2l_pll5_param { u32 pl5_fracin; u8 pl5_refdiv; @@ -201,6 +219,53 @@ int rzg2l_cpg_sd_clk_mux_notifier(struct notifier_block *nb, unsigned long event return notifier_from_errno(ret); } +int rzg3s_cpg_div_clk_notifier(struct notifier_block *nb, unsigned long event, + void *data) +{ + struct clk_notifier_data *cnd = data; + struct clk_hw *hw = __clk_get_hw(cnd->clk); + struct clk_hw_data *clk_hw_data = to_clk_hw_data(hw); + struct div_hw_data *div_hw_data = to_div_hw_data(clk_hw_data); + struct rzg2l_cpg_priv *priv = clk_hw_data->priv; + u32 off = GET_REG_OFFSET(clk_hw_data->conf); + u32 shift = GET_SHIFT(clk_hw_data->conf); + unsigned long flags; + int ret = 0; + u32 val; + + if (event != PRE_RATE_CHANGE || !div_hw_data->invalid_rate || + div_hw_data->invalid_rate % cnd->new_rate) + return NOTIFY_DONE; + + spin_lock_irqsave(&priv->rmw_lock, flags); + + val = readl(priv->base + off); + val >>= shift; + val &= GENMASK(GET_WIDTH(clk_hw_data->conf) - 1, 0); + + /* + * There are different constraints for the user of this notifiers as follows: + * 1/ SD div cannot be 1 (val == 0) if parent rate is 800MHz + * 2/ OCTA / SPI div cannot be 1 (val == 0) if parent rate is 400MHz + * As SD can have only one parent having 800MHz and OCTA div can have + * only one parent having 400MHz we took into account the parent rate + * at the beginning of function (by checking invalid_rate % new_rate). + * Now it is time to check the hardware divider and update it accordingly. + */ + if (!val) { + writel((CPG_WEN_BIT | 1) << shift, priv->base + off); + /* Wait for the update done. */ + ret = rzg2l_cpg_wait_clk_update_done(priv->base, clk_hw_data->sconf); + } + + spin_unlock_irqrestore(&priv->rmw_lock, flags); + + if (ret) + dev_err(priv->dev, "Failed to downgrade the div\n"); + + return notifier_from_errno(ret); +} + static int rzg2l_register_notifier(struct clk_hw *hw, const struct cpg_core_clk *core, struct rzg2l_cpg_priv *priv) { @@ -218,6 +283,124 @@ static int rzg2l_register_notifier(struct clk_hw *hw, const struct cpg_core_clk return clk_notifier_register(hw->clk, nb); } +static unsigned long rzg3s_div_clk_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct clk_hw_data *clk_hw_data = to_clk_hw_data(hw); + struct div_hw_data *div_hw_data = to_div_hw_data(clk_hw_data); + struct rzg2l_cpg_priv *priv = clk_hw_data->priv; + u32 val; + + val = readl(priv->base + GET_REG_OFFSET(clk_hw_data->conf)); + val >>= GET_SHIFT(clk_hw_data->conf); + val &= GENMASK(GET_WIDTH(clk_hw_data->conf) - 1, 0); + + return divider_recalc_rate(hw, parent_rate, val, div_hw_data->dtable, + CLK_DIVIDER_ROUND_CLOSEST, div_hw_data->width); +} + +static int rzg3s_div_clk_determine_rate(struct clk_hw *hw, struct clk_rate_request *req) +{ + struct clk_hw_data *clk_hw_data = to_clk_hw_data(hw); + struct div_hw_data *div_hw_data = to_div_hw_data(clk_hw_data); + + if (div_hw_data->max_rate && req->rate > div_hw_data->max_rate) + req->rate = div_hw_data->max_rate; + + return divider_determine_rate(hw, req, div_hw_data->dtable, div_hw_data->width, + CLK_DIVIDER_ROUND_CLOSEST); +} + +static int rzg3s_div_clk_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct clk_hw_data *clk_hw_data = to_clk_hw_data(hw); + struct div_hw_data *div_hw_data = to_div_hw_data(clk_hw_data); + struct rzg2l_cpg_priv *priv = clk_hw_data->priv; + u32 off = GET_REG_OFFSET(clk_hw_data->conf); + u32 shift = GET_SHIFT(clk_hw_data->conf); + unsigned long flags; + u32 val; + int ret; + + val = divider_get_val(rate, parent_rate, div_hw_data->dtable, div_hw_data->width, + CLK_DIVIDER_ROUND_CLOSEST); + + spin_lock_irqsave(&priv->rmw_lock, flags); + writel((CPG_WEN_BIT | val) << shift, priv->base + off); + /* Wait for the update done. */ + ret = rzg2l_cpg_wait_clk_update_done(priv->base, clk_hw_data->sconf); + spin_unlock_irqrestore(&priv->rmw_lock, flags); + + return ret; +} + +static const struct clk_ops rzg3s_div_clk_ops = { + .recalc_rate = rzg3s_div_clk_recalc_rate, + .determine_rate = rzg3s_div_clk_determine_rate, + .set_rate = rzg3s_div_clk_set_rate, +}; + +static struct clk * __init +rzg3s_cpg_div_clk_register(const struct cpg_core_clk *core, struct clk **clks, + void __iomem *base, struct rzg2l_cpg_priv *priv) +{ + struct div_hw_data *div_hw_data; + struct clk_init_data init = {}; + const struct clk_div_table *clkt; + struct clk_hw *clk_hw; + const struct clk *parent; + const char *parent_name; + u32 max = 0; + int ret; + + parent = clks[core->parent & 0xffff]; + if (IS_ERR(parent)) + return ERR_CAST(parent); + + parent_name = __clk_get_name(parent); + + div_hw_data = devm_kzalloc(priv->dev, sizeof(*div_hw_data), GFP_KERNEL); + if (!div_hw_data) + return ERR_PTR(-ENOMEM); + + init.name = core->name; + init.flags = core->flag; + init.ops = &rzg3s_div_clk_ops; + init.parent_names = &parent_name; + init.num_parents = 1; + + /* Get the maximum divider to retrieve div width. */ + for (clkt = core->dtable; clkt->div; clkt++) { + if (max < clkt->div) + max = clkt->div; + } + + div_hw_data->hw_data.priv = priv; + div_hw_data->hw_data.conf = core->conf; + div_hw_data->hw_data.sconf = core->sconf; + div_hw_data->dtable = core->dtable; + div_hw_data->invalid_rate = core->invalid_rate; + div_hw_data->max_rate = core->max_rate; + div_hw_data->width = fls(max) - 1; + + clk_hw = &div_hw_data->hw_data.hw; + clk_hw->init = &init; + + ret = devm_clk_hw_register(priv->dev, clk_hw); + if (ret) + return ERR_PTR(ret); + + ret = rzg2l_register_notifier(clk_hw, core, priv); + if (ret) { + dev_err(priv->dev, "Failed to register notifier for %s\n", + core->name); + return ERR_PTR(ret); + } + + return clk_hw->clk; +} + static struct clk * __init rzg2l_cpg_div_clk_register(const struct cpg_core_clk *core, struct clk **clks, @@ -963,6 +1146,9 @@ rzg2l_cpg_register_core_clk(const struct cpg_core_clk *core, clk = rzg2l_cpg_div_clk_register(core, priv->clks, priv->base, priv); break; + case CLK_TYPE_G3S_DIV: + clk = rzg3s_cpg_div_clk_register(core, priv->clks, priv->base, priv); + break; case CLK_TYPE_MUX: clk = rzg2l_cpg_mux_clk_register(core, priv->base, priv); break; diff --git a/drivers/clk/renesas/rzg2l-cpg.h b/drivers/clk/renesas/rzg2l-cpg.h index f1910913b29a..4755befaf38e 100644 --- a/drivers/clk/renesas/rzg2l-cpg.h +++ b/drivers/clk/renesas/rzg2l-cpg.h @@ -89,6 +89,8 @@ struct cpg_core_clk { unsigned int sconf; const struct clk_div_table *dtable; const u32 *mtable; + const unsigned long invalid_rate; + const unsigned long max_rate; const char * const *parent_names; notifier_fn_t notifier; u32 flag; @@ -105,6 +107,7 @@ enum clk_types { /* Clock with divider */ CLK_TYPE_DIV, + CLK_TYPE_G3S_DIV, /* Clock with clock source selector */ CLK_TYPE_MUX, @@ -143,6 +146,13 @@ enum clk_types { DEF_TYPE(_name, _id, CLK_TYPE_DIV, .conf = _conf, \ .parent = _parent, .dtable = _dtable, \ .flag = CLK_DIVIDER_READ_ONLY) +#define DEF_G3S_DIV(_name, _id, _parent, _conf, _sconf, _dtable, _invalid_rate, \ + _max_rate, _clk_flags, _notif) \ + DEF_TYPE(_name, _id, CLK_TYPE_G3S_DIV, .conf = _conf, .sconf = _sconf, \ + .parent = _parent, .dtable = _dtable, \ + .invalid_rate = _invalid_rate, \ + .max_rate = _max_rate, .flag = (_clk_flags), \ + .notifier = _notif) #define DEF_MUX(_name, _id, _conf, _parent_names) \ DEF_TYPE(_name, _id, CLK_TYPE_MUX, .conf = _conf, \ .parent_names = _parent_names, \ @@ -277,5 +287,6 @@ extern const struct rzg2l_cpg_info r9a07g054_cpg_info; extern const struct rzg2l_cpg_info r9a09g011_cpg_info; int rzg2l_cpg_sd_clk_mux_notifier(struct notifier_block *nb, unsigned long event, void *data); +int rzg3s_cpg_div_clk_notifier(struct notifier_block *nb, unsigned long event, void *data); #endif -- cgit v1.2.3-59-g8ed1b From de60a3ebe410670ffdbbc95faa25a820da44ab11 Mon Sep 17 00:00:00 2001 From: Claudiu Beznea Date: Fri, 6 Oct 2023 13:39:59 +0300 Subject: clk: renesas: Add minimal boot support for RZ/G3S SoC Add minimal clock and reset support for the RZ/G3S SoC to be able to boot Linux from SD Card/eMMC. This includes necessary core clocks for booting and GIC, SCIF, GPIO, and SD0 module clocks and resets. Signed-off-by: Claudiu Beznea Reviewed-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/20231006103959.197485-5-claudiu.beznea.uj@bp.renesas.com Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/Kconfig | 7 +- drivers/clk/renesas/Makefile | 1 + drivers/clk/renesas/r9a08g045-cpg.c | 214 ++++++++++++++++++++++++++++++++++++ drivers/clk/renesas/rzg2l-cpg.c | 6 + drivers/clk/renesas/rzg2l-cpg.h | 1 + 5 files changed, 228 insertions(+), 1 deletion(-) create mode 100644 drivers/clk/renesas/r9a08g045-cpg.c diff --git a/drivers/clk/renesas/Kconfig b/drivers/clk/renesas/Kconfig index 37632a0659d8..69396e197959 100644 --- a/drivers/clk/renesas/Kconfig +++ b/drivers/clk/renesas/Kconfig @@ -37,6 +37,7 @@ config CLK_RENESAS select CLK_R9A07G043 if ARCH_R9A07G043 select CLK_R9A07G044 if ARCH_R9A07G044 select CLK_R9A07G054 if ARCH_R9A07G054 + select CLK_R9A08G045 if ARCH_R9A08G045 select CLK_R9A09G011 if ARCH_R9A09G011 select CLK_SH73A0 if ARCH_SH73A0 @@ -179,6 +180,10 @@ config CLK_R9A07G054 bool "RZ/V2L clock support" if COMPILE_TEST select CLK_RZG2L +config CLK_R9A08G045 + bool "RZ/G3S clock support" if COMPILE_TEST + select CLK_RZG2L + config CLK_R9A09G011 bool "RZ/V2M clock support" if COMPILE_TEST select CLK_RZG2L @@ -215,7 +220,7 @@ config CLK_RCAR_USB2_CLOCK_SEL This is a driver for R-Car USB2 clock selector config CLK_RZG2L - bool "Renesas RZ/{G2L,G2UL,V2L} family clock support" if COMPILE_TEST + bool "Renesas RZ/{G2L,G2UL,G3S,V2L} family clock support" if COMPILE_TEST select RESET_CONTROLLER # Generic diff --git a/drivers/clk/renesas/Makefile b/drivers/clk/renesas/Makefile index de907623fe3f..879a07d445f9 100644 --- a/drivers/clk/renesas/Makefile +++ b/drivers/clk/renesas/Makefile @@ -34,6 +34,7 @@ obj-$(CONFIG_CLK_R9A06G032) += r9a06g032-clocks.o obj-$(CONFIG_CLK_R9A07G043) += r9a07g043-cpg.o obj-$(CONFIG_CLK_R9A07G044) += r9a07g044-cpg.o obj-$(CONFIG_CLK_R9A07G054) += r9a07g044-cpg.o +obj-$(CONFIG_CLK_R9A08G045) += r9a08g045-cpg.o obj-$(CONFIG_CLK_R9A09G011) += r9a09g011-cpg.o obj-$(CONFIG_CLK_SH73A0) += clk-sh73a0.o diff --git a/drivers/clk/renesas/r9a08g045-cpg.c b/drivers/clk/renesas/r9a08g045-cpg.c new file mode 100644 index 000000000000..389d32b32168 --- /dev/null +++ b/drivers/clk/renesas/r9a08g045-cpg.c @@ -0,0 +1,214 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * RZ/G3S CPG driver + * + * Copyright (C) 2023 Renesas Electronics Corp. + */ + +#include +#include +#include +#include + +#include + +#include "rzg2l-cpg.h" + +/* RZ/G3S Specific registers. */ +#define G3S_CPG_PL2_DDIV (0x204) +#define G3S_CPG_SDHI_DDIV (0x218) +#define G3S_CPG_PLL_DSEL (0x240) +#define G3S_CPG_SDHI_DSEL (0x244) +#define G3S_CLKDIVSTATUS (0x280) +#define G3S_CLKSELSTATUS (0x284) + +/* RZ/G3S Specific division configuration. */ +#define G3S_DIVPL2B DDIV_PACK(G3S_CPG_PL2_DDIV, 4, 3) +#define G3S_DIV_SDHI0 DDIV_PACK(G3S_CPG_SDHI_DDIV, 0, 1) + +/* RZ/G3S Clock status configuration. */ +#define G3S_DIVPL1A_STS DDIV_PACK(G3S_CLKDIVSTATUS, 0, 1) +#define G3S_DIVPL2B_STS DDIV_PACK(G3S_CLKDIVSTATUS, 5, 1) +#define G3S_DIVPL3A_STS DDIV_PACK(G3S_CLKDIVSTATUS, 8, 1) +#define G3S_DIVPL3B_STS DDIV_PACK(G3S_CLKDIVSTATUS, 9, 1) +#define G3S_DIVPL3C_STS DDIV_PACK(G3S_CLKDIVSTATUS, 10, 1) +#define G3S_DIV_SDHI0_STS DDIV_PACK(G3S_CLKDIVSTATUS, 24, 1) + +#define G3S_SEL_PLL4_STS SEL_PLL_PACK(G3S_CLKSELSTATUS, 6, 1) +#define G3S_SEL_SDHI0_STS SEL_PLL_PACK(G3S_CLKSELSTATUS, 16, 1) + +/* RZ/G3S Specific clocks select. */ +#define G3S_SEL_PLL4 SEL_PLL_PACK(G3S_CPG_PLL_DSEL, 6, 1) +#define G3S_SEL_SDHI0 SEL_PLL_PACK(G3S_CPG_SDHI_DSEL, 0, 2) + +/* PLL 1/4/6 configuration registers macro. */ +#define G3S_PLL146_CONF(clk1, clk2) ((clk1) << 22 | (clk2) << 12) + +#define DEF_G3S_MUX(_name, _id, _conf, _parent_names, _mux_flags, _clk_flags) \ + DEF_TYPE(_name, _id, CLK_TYPE_MUX, .conf = (_conf), \ + .parent_names = (_parent_names), \ + .num_parents = ARRAY_SIZE((_parent_names)), \ + .mux_flags = CLK_MUX_HIWORD_MASK | (_mux_flags), \ + .flag = (_clk_flags)) + +enum clk_ids { + /* Core Clock Outputs exported to DT */ + LAST_DT_CORE_CLK = R9A08G045_SWD, + + /* External Input Clocks */ + CLK_EXTAL, + + /* Internal Core Clocks */ + CLK_OSC_DIV1000, + CLK_PLL1, + CLK_PLL2, + CLK_PLL2_DIV2, + CLK_PLL2_DIV2_8, + CLK_PLL2_DIV6, + CLK_PLL3, + CLK_PLL3_DIV2, + CLK_PLL3_DIV2_4, + CLK_PLL3_DIV2_8, + CLK_PLL3_DIV6, + CLK_PLL4, + CLK_PLL6, + CLK_PLL6_DIV2, + CLK_SEL_SDHI0, + CLK_SEL_PLL4, + CLK_P1_DIV2, + CLK_P3_DIV2, + CLK_SD0_DIV4, + + /* Module Clocks */ + MOD_CLK_BASE, +}; + +/* Divider tables */ +static const struct clk_div_table dtable_1_2[] = { + { 0, 1 }, + { 1, 2 }, + { 0, 0 }, +}; + +static const struct clk_div_table dtable_1_8[] = { + { 0, 1 }, + { 1, 2 }, + { 2, 4 }, + { 3, 8 }, + { 0, 0 }, +}; + +static const struct clk_div_table dtable_1_32[] = { + { 0, 1 }, + { 1, 2 }, + { 2, 4 }, + { 3, 8 }, + { 4, 32 }, + { 0, 0 }, +}; + +/* Mux clock names tables. */ +static const char * const sel_sdhi[] = { ".pll2_div2", ".pll6", ".pll2_div6" }; +static const char * const sel_pll4[] = { ".osc_div1000", ".pll4" }; + +/* Mux clock indices tables. */ +static const u32 mtable_sd[] = { 0, 2, 3 }; +static const u32 mtable_pll4[] = { 0, 1 }; + +static const struct cpg_core_clk r9a08g045_core_clks[] __initconst = { + /* External Clock Inputs */ + DEF_INPUT("extal", CLK_EXTAL), + + /* Internal Core Clocks */ + DEF_FIXED(".osc_div1000", CLK_OSC_DIV1000, CLK_EXTAL, 1, 1000), + DEF_G3S_PLL(".pll1", CLK_PLL1, CLK_EXTAL, G3S_PLL146_CONF(0x4, 0x8)), + DEF_FIXED(".pll2", CLK_PLL2, CLK_EXTAL, 200, 3), + DEF_FIXED(".pll3", CLK_PLL3, CLK_EXTAL, 200, 3), + DEF_FIXED(".pll4", CLK_PLL4, CLK_EXTAL, 100, 3), + DEF_FIXED(".pll6", CLK_PLL6, CLK_EXTAL, 125, 6), + DEF_FIXED(".pll2_div2", CLK_PLL2_DIV2, CLK_PLL2, 1, 2), + DEF_FIXED(".pll2_div2_8", CLK_PLL2_DIV2_8, CLK_PLL2_DIV2, 1, 8), + DEF_FIXED(".pll2_div6", CLK_PLL2_DIV6, CLK_PLL2, 1, 6), + DEF_FIXED(".pll3_div2", CLK_PLL3_DIV2, CLK_PLL3, 1, 2), + DEF_FIXED(".pll3_div2_4", CLK_PLL3_DIV2_4, CLK_PLL3_DIV2, 1, 4), + DEF_FIXED(".pll3_div2_8", CLK_PLL3_DIV2_8, CLK_PLL3_DIV2, 1, 8), + DEF_FIXED(".pll3_div6", CLK_PLL3_DIV6, CLK_PLL3, 1, 6), + DEF_FIXED(".pll6_div2", CLK_PLL6_DIV2, CLK_PLL6, 1, 2), + DEF_SD_MUX(".sel_sd0", CLK_SEL_SDHI0, G3S_SEL_SDHI0, G3S_SEL_SDHI0_STS, sel_sdhi, + mtable_sd, 0, NULL), + DEF_SD_MUX(".sel_pll4", CLK_SEL_PLL4, G3S_SEL_PLL4, G3S_SEL_PLL4_STS, sel_pll4, + mtable_pll4, CLK_SET_PARENT_GATE, NULL), + + /* Core output clk */ + DEF_G3S_DIV("I", R9A08G045_CLK_I, CLK_PLL1, DIVPL1A, G3S_DIVPL1A_STS, dtable_1_8, + 0, 0, 0, NULL), + DEF_G3S_DIV("P0", R9A08G045_CLK_P0, CLK_PLL2_DIV2_8, G3S_DIVPL2B, G3S_DIVPL2B_STS, + dtable_1_32, 0, 0, 0, NULL), + DEF_G3S_DIV("SD0", R9A08G045_CLK_SD0, CLK_SEL_SDHI0, G3S_DIV_SDHI0, G3S_DIV_SDHI0_STS, + dtable_1_2, 800000000UL, 500000000UL, CLK_SET_RATE_PARENT, + rzg3s_cpg_div_clk_notifier), + DEF_FIXED(".sd0_div4", CLK_SD0_DIV4, R9A08G045_CLK_SD0, 1, 4), + DEF_FIXED("M0", R9A08G045_CLK_M0, CLK_PLL3_DIV2_4, 1, 1), + DEF_G3S_DIV("P1", R9A08G045_CLK_P1, CLK_PLL3_DIV2_4, DIVPL3A, G3S_DIVPL3A_STS, + dtable_1_32, 0, 0, 0, NULL), + DEF_FIXED("P1_DIV2", CLK_P1_DIV2, R9A08G045_CLK_P1, 1, 2), + DEF_G3S_DIV("P2", R9A08G045_CLK_P2, CLK_PLL3_DIV2_8, DIVPL3B, G3S_DIVPL3B_STS, + dtable_1_32, 0, 0, 0, NULL), + DEF_G3S_DIV("P3", R9A08G045_CLK_P3, CLK_PLL3_DIV2_4, DIVPL3C, G3S_DIVPL3C_STS, + dtable_1_32, 0, 0, 0, NULL), + DEF_FIXED("P3_DIV2", CLK_P3_DIV2, R9A08G045_CLK_P3, 1, 2), + DEF_FIXED("S0", R9A08G045_CLK_S0, CLK_SEL_PLL4, 1, 2), + DEF_FIXED("OSC", R9A08G045_OSCCLK, CLK_EXTAL, 1, 1), + DEF_FIXED("OSC2", R9A08G045_OSCCLK2, CLK_EXTAL, 1, 3), +}; + +static const struct rzg2l_mod_clk r9a08g045_mod_clks[] = { + DEF_MOD("gic_gicclk", R9A08G045_GIC600_GICCLK, R9A08G045_CLK_P1, 0x514, 0), + DEF_MOD("ia55_clk", R9A08G045_IA55_CLK, R9A08G045_CLK_P1, 0x518, 1), + DEF_MOD("dmac_aclk", R9A08G045_DMAC_ACLK, R9A08G045_CLK_P3, 0x52c, 0), + DEF_MOD("sdhi0_imclk", R9A08G045_SDHI0_IMCLK, CLK_SD0_DIV4, 0x554, 0), + DEF_MOD("sdhi0_imclk2", R9A08G045_SDHI0_IMCLK2, CLK_SD0_DIV4, 0x554, 1), + DEF_MOD("sdhi0_clk_hs", R9A08G045_SDHI0_CLK_HS, R9A08G045_CLK_SD0, 0x554, 2), + DEF_MOD("sdhi0_aclk", R9A08G045_SDHI0_ACLK, R9A08G045_CLK_P1, 0x554, 3), + DEF_MOD("scif0_clk_pck", R9A08G045_SCIF0_CLK_PCK, R9A08G045_CLK_P0, 0x584, 0), + DEF_MOD("gpio_hclk", R9A08G045_GPIO_HCLK, R9A08G045_OSCCLK, 0x598, 0), +}; + +static const struct rzg2l_reset r9a08g045_resets[] = { + DEF_RST(R9A08G045_GIC600_GICRESET_N, 0x814, 0), + DEF_RST(R9A08G045_GIC600_DBG_GICRESET_N, 0x814, 1), + DEF_RST(R9A08G045_SDHI0_IXRST, 0x854, 0), + DEF_RST(R9A08G045_SCIF0_RST_SYSTEM_N, 0x884, 0), + DEF_RST(R9A08G045_GPIO_RSTN, 0x898, 0), + DEF_RST(R9A08G045_GPIO_PORT_RESETN, 0x898, 1), + DEF_RST(R9A08G045_GPIO_SPARE_RESETN, 0x898, 2), +}; + +static const unsigned int r9a08g045_crit_mod_clks[] __initconst = { + MOD_CLK_BASE + R9A08G045_GIC600_GICCLK, + MOD_CLK_BASE + R9A08G045_IA55_CLK, + MOD_CLK_BASE + R9A08G045_DMAC_ACLK, +}; + +const struct rzg2l_cpg_info r9a08g045_cpg_info = { + /* Core Clocks */ + .core_clks = r9a08g045_core_clks, + .num_core_clks = ARRAY_SIZE(r9a08g045_core_clks), + .last_dt_core_clk = LAST_DT_CORE_CLK, + .num_total_core_clks = MOD_CLK_BASE, + + /* Critical Module Clocks */ + .crit_mod_clks = r9a08g045_crit_mod_clks, + .num_crit_mod_clks = ARRAY_SIZE(r9a08g045_crit_mod_clks), + + /* Module Clocks */ + .mod_clks = r9a08g045_mod_clks, + .num_mod_clks = ARRAY_SIZE(r9a08g045_mod_clks), + .num_hw_mod_clks = R9A08G045_VBAT_BCLK + 1, + + /* Resets */ + .resets = r9a08g045_resets, + .num_resets = R9A08G045_VBAT_BRESETN + 1, /* Last reset ID + 1 */ + + .has_clk_mon_regs = true, +}; diff --git a/drivers/clk/renesas/rzg2l-cpg.c b/drivers/clk/renesas/rzg2l-cpg.c index 49dc6c5c0b0c..d62f1bc1f60e 100644 --- a/drivers/clk/renesas/rzg2l-cpg.c +++ b/drivers/clk/renesas/rzg2l-cpg.c @@ -1706,6 +1706,12 @@ static const struct of_device_id rzg2l_cpg_match[] = { .data = &r9a07g054_cpg_info, }, #endif +#ifdef CONFIG_CLK_R9A08G045 + { + .compatible = "renesas,r9a08g045-cpg", + .data = &r9a08g045_cpg_info, + }, +#endif #ifdef CONFIG_CLK_R9A09G011 { .compatible = "renesas,r9a09g011-cpg", diff --git a/drivers/clk/renesas/rzg2l-cpg.h b/drivers/clk/renesas/rzg2l-cpg.h index 4755befaf38e..6e38c8fc888c 100644 --- a/drivers/clk/renesas/rzg2l-cpg.h +++ b/drivers/clk/renesas/rzg2l-cpg.h @@ -284,6 +284,7 @@ struct rzg2l_cpg_info { extern const struct rzg2l_cpg_info r9a07g043_cpg_info; extern const struct rzg2l_cpg_info r9a07g044_cpg_info; extern const struct rzg2l_cpg_info r9a07g054_cpg_info; +extern const struct rzg2l_cpg_info r9a08g045_cpg_info; extern const struct rzg2l_cpg_info r9a09g011_cpg_info; int rzg2l_cpg_sd_clk_mux_notifier(struct notifier_block *nb, unsigned long event, void *data); -- cgit v1.2.3-59-g8ed1b From fd627207aaa782c1fd4224076b56a03a1059f516 Mon Sep 17 00:00:00 2001 From: Claudiu Beznea Date: Tue, 10 Oct 2023 16:26:56 +0300 Subject: clk: renesas: rzg2l: Use %x format specifier to print CLK_ON_R() Use the %x format specifier to print CLK_ON_R(). This makes debugging easier as the value printed will be hexadecimal like in the hardware manual. Along with it add "0x" in front of the printed value. Signed-off-by: Claudiu Beznea Reviewed-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/20231010132701.1658737-2-claudiu.beznea.uj@bp.renesas.com Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/rzg2l-cpg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/renesas/rzg2l-cpg.c b/drivers/clk/renesas/rzg2l-cpg.c index d62f1bc1f60e..764bd72cf059 100644 --- a/drivers/clk/renesas/rzg2l-cpg.c +++ b/drivers/clk/renesas/rzg2l-cpg.c @@ -1213,7 +1213,7 @@ static int rzg2l_mod_clock_endisable(struct clk_hw *hw, bool enable) return 0; } - dev_dbg(dev, "CLK_ON %u/%pC %s\n", CLK_ON_R(reg), hw->clk, + dev_dbg(dev, "CLK_ON 0x%x/%pC %s\n", CLK_ON_R(reg), hw->clk, enable ? "ON" : "OFF"); value = bitmask << 16; -- cgit v1.2.3-59-g8ed1b From 4bce4bedbe6daa54cf701184601f913a0c00bb1c Mon Sep 17 00:00:00 2001 From: Claudiu Beznea Date: Tue, 10 Oct 2023 16:26:57 +0300 Subject: clk: renesas: r9a08g045: Add clock and reset support for SDHI1 and SDHI2 Add clock and reset support for the SDHI1 and SDHI2 blocks on the RZ/G3S (R9A08G045) SoC. Signed-off-by: Claudiu Beznea Reviewed-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/20231010132701.1658737-3-claudiu.beznea.uj@bp.renesas.com Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/r9a08g045-cpg.c | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/drivers/clk/renesas/r9a08g045-cpg.c b/drivers/clk/renesas/r9a08g045-cpg.c index 389d32b32168..4394cb241d99 100644 --- a/drivers/clk/renesas/r9a08g045-cpg.c +++ b/drivers/clk/renesas/r9a08g045-cpg.c @@ -25,6 +25,8 @@ /* RZ/G3S Specific division configuration. */ #define G3S_DIVPL2B DDIV_PACK(G3S_CPG_PL2_DDIV, 4, 3) #define G3S_DIV_SDHI0 DDIV_PACK(G3S_CPG_SDHI_DDIV, 0, 1) +#define G3S_DIV_SDHI1 DDIV_PACK(G3S_CPG_SDHI_DDIV, 4, 1) +#define G3S_DIV_SDHI2 DDIV_PACK(G3S_CPG_SDHI_DDIV, 8, 1) /* RZ/G3S Clock status configuration. */ #define G3S_DIVPL1A_STS DDIV_PACK(G3S_CLKDIVSTATUS, 0, 1) @@ -33,13 +35,19 @@ #define G3S_DIVPL3B_STS DDIV_PACK(G3S_CLKDIVSTATUS, 9, 1) #define G3S_DIVPL3C_STS DDIV_PACK(G3S_CLKDIVSTATUS, 10, 1) #define G3S_DIV_SDHI0_STS DDIV_PACK(G3S_CLKDIVSTATUS, 24, 1) +#define G3S_DIV_SDHI1_STS DDIV_PACK(G3S_CLKDIVSTATUS, 25, 1) +#define G3S_DIV_SDHI2_STS DDIV_PACK(G3S_CLKDIVSTATUS, 26, 1) #define G3S_SEL_PLL4_STS SEL_PLL_PACK(G3S_CLKSELSTATUS, 6, 1) #define G3S_SEL_SDHI0_STS SEL_PLL_PACK(G3S_CLKSELSTATUS, 16, 1) +#define G3S_SEL_SDHI1_STS SEL_PLL_PACK(G3S_CLKSELSTATUS, 17, 1) +#define G3S_SEL_SDHI2_STS SEL_PLL_PACK(G3S_CLKSELSTATUS, 18, 1) /* RZ/G3S Specific clocks select. */ #define G3S_SEL_PLL4 SEL_PLL_PACK(G3S_CPG_PLL_DSEL, 6, 1) #define G3S_SEL_SDHI0 SEL_PLL_PACK(G3S_CPG_SDHI_DSEL, 0, 2) +#define G3S_SEL_SDHI1 SEL_PLL_PACK(G3S_CPG_SDHI_DSEL, 4, 2) +#define G3S_SEL_SDHI2 SEL_PLL_PACK(G3S_CPG_SDHI_DSEL, 8, 2) /* PLL 1/4/6 configuration registers macro. */ #define G3S_PLL146_CONF(clk1, clk2) ((clk1) << 22 | (clk2) << 12) @@ -74,10 +82,14 @@ enum clk_ids { CLK_PLL6, CLK_PLL6_DIV2, CLK_SEL_SDHI0, + CLK_SEL_SDHI1, + CLK_SEL_SDHI2, CLK_SEL_PLL4, CLK_P1_DIV2, CLK_P3_DIV2, CLK_SD0_DIV4, + CLK_SD1_DIV4, + CLK_SD2_DIV4, /* Module Clocks */ MOD_CLK_BASE, @@ -136,6 +148,10 @@ static const struct cpg_core_clk r9a08g045_core_clks[] __initconst = { DEF_FIXED(".pll6_div2", CLK_PLL6_DIV2, CLK_PLL6, 1, 2), DEF_SD_MUX(".sel_sd0", CLK_SEL_SDHI0, G3S_SEL_SDHI0, G3S_SEL_SDHI0_STS, sel_sdhi, mtable_sd, 0, NULL), + DEF_SD_MUX(".sel_sd1", CLK_SEL_SDHI1, G3S_SEL_SDHI1, G3S_SEL_SDHI1_STS, sel_sdhi, + mtable_sd, 0, NULL), + DEF_SD_MUX(".sel_sd2", CLK_SEL_SDHI2, G3S_SEL_SDHI2, G3S_SEL_SDHI2_STS, sel_sdhi, + mtable_sd, 0, NULL), DEF_SD_MUX(".sel_pll4", CLK_SEL_PLL4, G3S_SEL_PLL4, G3S_SEL_PLL4_STS, sel_pll4, mtable_pll4, CLK_SET_PARENT_GATE, NULL), @@ -147,7 +163,15 @@ static const struct cpg_core_clk r9a08g045_core_clks[] __initconst = { DEF_G3S_DIV("SD0", R9A08G045_CLK_SD0, CLK_SEL_SDHI0, G3S_DIV_SDHI0, G3S_DIV_SDHI0_STS, dtable_1_2, 800000000UL, 500000000UL, CLK_SET_RATE_PARENT, rzg3s_cpg_div_clk_notifier), + DEF_G3S_DIV("SD1", R9A08G045_CLK_SD1, CLK_SEL_SDHI1, G3S_DIV_SDHI1, G3S_DIV_SDHI1_STS, + dtable_1_2, 800000000UL, 500000000UL, CLK_SET_RATE_PARENT, + rzg3s_cpg_div_clk_notifier), + DEF_G3S_DIV("SD2", R9A08G045_CLK_SD2, CLK_SEL_SDHI2, G3S_DIV_SDHI2, G3S_DIV_SDHI2_STS, + dtable_1_2, 800000000UL, 500000000UL, CLK_SET_RATE_PARENT, + rzg3s_cpg_div_clk_notifier), DEF_FIXED(".sd0_div4", CLK_SD0_DIV4, R9A08G045_CLK_SD0, 1, 4), + DEF_FIXED(".sd1_div4", CLK_SD1_DIV4, R9A08G045_CLK_SD1, 1, 4), + DEF_FIXED(".sd2_div4", CLK_SD2_DIV4, R9A08G045_CLK_SD2, 1, 4), DEF_FIXED("M0", R9A08G045_CLK_M0, CLK_PLL3_DIV2_4, 1, 1), DEF_G3S_DIV("P1", R9A08G045_CLK_P1, CLK_PLL3_DIV2_4, DIVPL3A, G3S_DIVPL3A_STS, dtable_1_32, 0, 0, 0, NULL), @@ -170,6 +194,14 @@ static const struct rzg2l_mod_clk r9a08g045_mod_clks[] = { DEF_MOD("sdhi0_imclk2", R9A08G045_SDHI0_IMCLK2, CLK_SD0_DIV4, 0x554, 1), DEF_MOD("sdhi0_clk_hs", R9A08G045_SDHI0_CLK_HS, R9A08G045_CLK_SD0, 0x554, 2), DEF_MOD("sdhi0_aclk", R9A08G045_SDHI0_ACLK, R9A08G045_CLK_P1, 0x554, 3), + DEF_MOD("sdhi1_imclk", R9A08G045_SDHI1_IMCLK, CLK_SD1_DIV4, 0x554, 4), + DEF_MOD("sdhi1_imclk2", R9A08G045_SDHI1_IMCLK2, CLK_SD1_DIV4, 0x554, 5), + DEF_MOD("sdhi1_clk_hs", R9A08G045_SDHI1_CLK_HS, R9A08G045_CLK_SD1, 0x554, 6), + DEF_MOD("sdhi1_aclk", R9A08G045_SDHI1_ACLK, R9A08G045_CLK_P1, 0x554, 7), + DEF_MOD("sdhi2_imclk", R9A08G045_SDHI2_IMCLK, CLK_SD2_DIV4, 0x554, 8), + DEF_MOD("sdhi2_imclk2", R9A08G045_SDHI2_IMCLK2, CLK_SD2_DIV4, 0x554, 9), + DEF_MOD("sdhi2_clk_hs", R9A08G045_SDHI2_CLK_HS, R9A08G045_CLK_SD2, 0x554, 10), + DEF_MOD("sdhi2_aclk", R9A08G045_SDHI2_ACLK, R9A08G045_CLK_P1, 0x554, 11), DEF_MOD("scif0_clk_pck", R9A08G045_SCIF0_CLK_PCK, R9A08G045_CLK_P0, 0x584, 0), DEF_MOD("gpio_hclk", R9A08G045_GPIO_HCLK, R9A08G045_OSCCLK, 0x598, 0), }; @@ -178,6 +210,8 @@ static const struct rzg2l_reset r9a08g045_resets[] = { DEF_RST(R9A08G045_GIC600_GICRESET_N, 0x814, 0), DEF_RST(R9A08G045_GIC600_DBG_GICRESET_N, 0x814, 1), DEF_RST(R9A08G045_SDHI0_IXRST, 0x854, 0), + DEF_RST(R9A08G045_SDHI1_IXRST, 0x854, 1), + DEF_RST(R9A08G045_SDHI2_IXRST, 0x854, 2), DEF_RST(R9A08G045_SCIF0_RST_SYSTEM_N, 0x884, 0), DEF_RST(R9A08G045_GPIO_RSTN, 0x898, 0), DEF_RST(R9A08G045_GPIO_PORT_RESETN, 0x898, 1), -- cgit v1.2.3-59-g8ed1b From 2e9abc6ec108370ad341f98d0e05e02e4e165b5a Mon Sep 17 00:00:00 2001 From: Frank Oltmanns Date: Sat, 17 Jun 2023 15:10:40 +0200 Subject: clk: fractional-divider: Improve approximation when zero based and export Consider the CLK_FRAC_DIVIDER_ZERO_BASED flag when finding the best approximation for m and n. By doing so, increase the range of valid values for the numerator and denominator by 1. Furthermore, export the approximation function so that users of this function can be compiled as modules. Cc: A.s. Dong Signed-off-by: Frank Oltmanns Link: https://lore.kernel.org/r/20230617131041.18313-2-frank@oltmanns.dev Signed-off-by: Stephen Boyd --- drivers/clk/clk-fractional-divider.c | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/drivers/clk/clk-fractional-divider.c b/drivers/clk/clk-fractional-divider.c index 479297763e70..5067e067e906 100644 --- a/drivers/clk/clk-fractional-divider.c +++ b/drivers/clk/clk-fractional-divider.c @@ -123,6 +123,7 @@ void clk_fractional_divider_general_approximation(struct clk_hw *hw, unsigned long *m, unsigned long *n) { struct clk_fractional_divider *fd = to_clk_fd(hw); + unsigned long max_m, max_n; /* * Get rate closer to *parent_rate to guarantee there is no overflow @@ -138,10 +139,17 @@ void clk_fractional_divider_general_approximation(struct clk_hw *hw, rate <<= scale - fd->nwidth; } - rational_best_approximation(rate, *parent_rate, - GENMASK(fd->mwidth - 1, 0), GENMASK(fd->nwidth - 1, 0), - m, n); + if (fd->flags & CLK_FRAC_DIVIDER_ZERO_BASED) { + max_m = 1 << fd->mwidth; + max_n = 1 << fd->nwidth; + } else { + max_m = GENMASK(fd->mwidth - 1, 0); + max_n = GENMASK(fd->nwidth - 1, 0); + } + + rational_best_approximation(rate, *parent_rate, max_m, max_n, m, n); } +EXPORT_SYMBOL_GPL(clk_fractional_divider_general_approximation); static long clk_fd_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long *parent_rate) @@ -169,13 +177,18 @@ static int clk_fd_set_rate(struct clk_hw *hw, unsigned long rate, { struct clk_fractional_divider *fd = to_clk_fd(hw); unsigned long flags = 0; - unsigned long m, n; + unsigned long m, n, max_m, max_n; u32 mmask, nmask; u32 val; - rational_best_approximation(rate, parent_rate, - GENMASK(fd->mwidth - 1, 0), GENMASK(fd->nwidth - 1, 0), - &m, &n); + if (fd->flags & CLK_FRAC_DIVIDER_ZERO_BASED) { + max_m = 1 << fd->mwidth; + max_n = 1 << fd->nwidth; + } else { + max_m = GENMASK(fd->mwidth - 1, 0); + max_n = GENMASK(fd->nwidth - 1, 0); + } + rational_best_approximation(rate, parent_rate, max_m, max_n, &m, &n); if (fd->flags & CLK_FRAC_DIVIDER_ZERO_BASED) { m--; -- cgit v1.2.3-59-g8ed1b From 2790e2a33aa9e0710354aaabce8ae1a92925348f Mon Sep 17 00:00:00 2001 From: Frank Oltmanns Date: Sat, 17 Jun 2023 15:10:41 +0200 Subject: clk: fractional-divider: tests: Add test suite for edge cases In light of the recent discovery that the fractional divisor approximation does not utilize the full available range for clocks that are flagged CLK_FRAC_DIVIDER_ZERO_BASED [1], implement tests for the edge cases of this clock type. Signed-off-by: Frank Oltmanns Link: https://lore.kernel.org/lkml/20230529133433.56215-1-frank@oltmanns.dev [1] Link: https://lore.kernel.org/r/20230617131041.18313-3-frank@oltmanns.dev [sboyd@kernel.org: Rename suite and tests slightly, drop unused includes, store parent rate to compare instead of repeating equation] Signed-off-by: Stephen Boyd --- drivers/clk/.kunitconfig | 1 + drivers/clk/Kconfig | 7 ++ drivers/clk/Makefile | 1 + drivers/clk/clk-fractional-divider_test.c | 147 ++++++++++++++++++++++++++++++ 4 files changed, 156 insertions(+) create mode 100644 drivers/clk/clk-fractional-divider_test.c diff --git a/drivers/clk/.kunitconfig b/drivers/clk/.kunitconfig index 2fbeb71316f8..efa12ac2b3f2 100644 --- a/drivers/clk/.kunitconfig +++ b/drivers/clk/.kunitconfig @@ -2,4 +2,5 @@ CONFIG_KUNIT=y CONFIG_COMMON_CLK=y CONFIG_CLK_KUNIT_TEST=y CONFIG_CLK_GATE_KUNIT_TEST=y +CONFIG_CLK_FD_KUNIT_TEST=y CONFIG_UML_PCI_OVER_VIRTIO=n diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index c30099866174..5ac8f0692d75 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig @@ -517,4 +517,11 @@ config CLK_GATE_KUNIT_TEST help Kunit test for the basic clk gate type. +config CLK_FD_KUNIT_TEST + tristate "Basic fractional divider type Kunit test" if !KUNIT_ALL_TESTS + depends on KUNIT + default KUNIT_ALL_TESTS + help + Kunit test for the clk-fractional-divider type. + endif diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index 18969cbd4bb1..fde9ceb53ce4 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -12,6 +12,7 @@ obj-$(CONFIG_COMMON_CLK) += clk-multiplier.o obj-$(CONFIG_COMMON_CLK) += clk-mux.o obj-$(CONFIG_COMMON_CLK) += clk-composite.o obj-$(CONFIG_COMMON_CLK) += clk-fractional-divider.o +obj-$(CONFIG_CLK_FD_KUNIT_TEST) += clk-fractional-divider_test.o obj-$(CONFIG_COMMON_CLK) += clk-gpio.o ifeq ($(CONFIG_OF), y) obj-$(CONFIG_COMMON_CLK) += clk-conf.o diff --git a/drivers/clk/clk-fractional-divider_test.c b/drivers/clk/clk-fractional-divider_test.c new file mode 100644 index 000000000000..929eec927548 --- /dev/null +++ b/drivers/clk/clk-fractional-divider_test.c @@ -0,0 +1,147 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Kunit test for clock fractional divider + */ +#include +#include + +#include "clk-fractional-divider.h" + +/* + * Test the maximum denominator case for fd clock without flags. + * + * Expect the highest possible denominator to be used in order to get as close as possible to the + * requested rate. + */ +static void clk_fd_test_approximation_max_denominator(struct kunit *test) +{ + struct clk_fractional_divider *fd; + unsigned long rate, parent_rate, parent_rate_before, m, n, max_n; + + fd = kunit_kzalloc(test, sizeof(*fd), GFP_KERNEL); + KUNIT_ASSERT_NOT_NULL(test, fd); + + fd->mwidth = 3; + fd->nwidth = 3; + max_n = 7; + + rate = 240000000; + parent_rate = (max_n + 1) * rate; /* so that it exceeds the maximum divisor */ + parent_rate_before = parent_rate; + + clk_fractional_divider_general_approximation(&fd->hw, rate, &parent_rate, &m, &n); + KUNIT_ASSERT_EQ(test, parent_rate, parent_rate_before); + + KUNIT_EXPECT_EQ(test, m, 1); + KUNIT_EXPECT_EQ(test, n, max_n); +} + +/* + * Test the maximum numerator case for fd clock without flags. + * + * Expect the highest possible numerator to be used in order to get as close as possible to the + * requested rate. + */ +static void clk_fd_test_approximation_max_numerator(struct kunit *test) +{ + struct clk_fractional_divider *fd; + unsigned long rate, parent_rate, parent_rate_before, m, n, max_m; + + fd = kunit_kzalloc(test, sizeof(*fd), GFP_KERNEL); + KUNIT_ASSERT_NOT_NULL(test, fd); + + fd->mwidth = 3; + max_m = 7; + fd->nwidth = 3; + + rate = 240000000; + parent_rate = rate / (max_m + 1); /* so that it exceeds the maximum numerator */ + parent_rate_before = parent_rate; + + clk_fractional_divider_general_approximation(&fd->hw, rate, &parent_rate, &m, &n); + KUNIT_ASSERT_EQ(test, parent_rate, parent_rate_before); + + KUNIT_EXPECT_EQ(test, m, max_m); + KUNIT_EXPECT_EQ(test, n, 1); +} + +/* + * Test the maximum denominator case for zero based fd clock. + * + * Expect the highest possible denominator to be used in order to get as close as possible to the + * requested rate. + */ +static void clk_fd_test_approximation_max_denominator_zero_based(struct kunit *test) +{ + struct clk_fractional_divider *fd; + unsigned long rate, parent_rate, parent_rate_before, m, n, max_n; + + fd = kunit_kzalloc(test, sizeof(*fd), GFP_KERNEL); + KUNIT_ASSERT_NOT_NULL(test, fd); + + fd->flags = CLK_FRAC_DIVIDER_ZERO_BASED; + fd->mwidth = 3; + fd->nwidth = 3; + max_n = 8; + + rate = 240000000; + parent_rate = (max_n + 1) * rate; /* so that it exceeds the maximum divisor */ + parent_rate_before = parent_rate; + + clk_fractional_divider_general_approximation(&fd->hw, rate, &parent_rate, &m, &n); + KUNIT_ASSERT_EQ(test, parent_rate, parent_rate_before); + + KUNIT_EXPECT_EQ(test, m, 1); + KUNIT_EXPECT_EQ(test, n, max_n); +} + +/* + * Test the maximum numerator case for zero based fd clock. + * + * Expect the highest possible numerator to be used in order to get as close as possible to the + * requested rate. + */ +static void clk_fd_test_approximation_max_numerator_zero_based(struct kunit *test) +{ + struct clk_fractional_divider *fd; + unsigned long rate, parent_rate, parent_rate_before, m, n, max_m; + + fd = kunit_kzalloc(test, sizeof(*fd), GFP_KERNEL); + KUNIT_ASSERT_NOT_NULL(test, fd); + + fd->flags = CLK_FRAC_DIVIDER_ZERO_BASED; + fd->mwidth = 3; + max_m = 8; + fd->nwidth = 3; + + rate = 240000000; + parent_rate = rate / (max_m + 1); /* so that it exceeds the maximum numerator */ + parent_rate_before = parent_rate; + + clk_fractional_divider_general_approximation(&fd->hw, rate, &parent_rate, &m, &n); + KUNIT_ASSERT_EQ(test, parent_rate, parent_rate_before); + + KUNIT_EXPECT_EQ(test, m, max_m); + KUNIT_EXPECT_EQ(test, n, 1); +} + +static struct kunit_case clk_fd_approximation_test_cases[] = { + KUNIT_CASE(clk_fd_test_approximation_max_denominator), + KUNIT_CASE(clk_fd_test_approximation_max_numerator), + KUNIT_CASE(clk_fd_test_approximation_max_denominator_zero_based), + KUNIT_CASE(clk_fd_test_approximation_max_numerator_zero_based), + {} +}; + +/* + * Test suite for clk_fractional_divider_general_approximation(). + */ +static struct kunit_suite clk_fd_approximation_suite = { + .name = "clk-fd-approximation", + .test_cases = clk_fd_approximation_test_cases, +}; + +kunit_test_suites( + &clk_fd_approximation_suite +); +MODULE_LICENSE("GPL"); -- cgit v1.2.3-59-g8ed1b From 84aefafe6b294041b7fa0757414c4a29c1bdeea2 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Sat, 30 Sep 2023 15:14:26 -0700 Subject: clk: linux/clk-provider.h: fix kernel-doc warnings and typos Fix spelling of "Structure". Fix multiple kernel-doc warnings: clk-provider.h:269: warning: Function parameter or member 'recalc_rate' not described in 'clk_ops' clk-provider.h:468: warning: Function parameter or member 'parent_data' not described in 'clk_hw_register_fixed_rate_with_accuracy_parent_data' clk-provider.h:468: warning: Excess function parameter 'parent_name' description in 'clk_hw_register_fixed_rate_with_accuracy_parent_data' clk-provider.h:482: warning: Function parameter or member 'parent_data' not described in 'clk_hw_register_fixed_rate_parent_accuracy' clk-provider.h:482: warning: Excess function parameter 'parent_name' description in 'clk_hw_register_fixed_rate_parent_accuracy' clk-provider.h:687: warning: Function parameter or member 'flags' not described in 'clk_divider' clk-provider.h:1164: warning: Function parameter or member 'flags' not described in 'clk_fractional_divider' clk-provider.h:1164: warning: Function parameter or member 'approximation' not described in 'clk_fractional_divider' clk-provider.h:1213: warning: Function parameter or member 'flags' not described in 'clk_multiplier' Fixes: 9fba738a53dd ("clk: add duty cycle support") Fixes: b2476490ef11 ("clk: introduce the common clock framework") Fixes: 2d34f09e79c9 ("clk: fixed-rate: Add support for specifying parents via DT/pointers") Fixes: f5290d8e4f0c ("clk: asm9260: use parent index to link the reference clock") Fixes: 9d9f78ed9af0 ("clk: basic clock hardware types") Fixes: e2d0e90fae82 ("clk: new basic clk type for fractional divider") Fixes: f2e0a53271a4 ("clk: Add a basic multiplier clock") Signed-off-by: Randy Dunlap Cc: Michael Turquette Cc: Stephen Boyd Cc: linux-clk@vger.kernel.org Link: https://lore.kernel.org/r/20230930221428.18463-1-rdunlap@infradead.org Signed-off-by: Stephen Boyd --- include/linux/clk-provider.h | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h index ec32ec58c59f..ace3a4ce2fc9 100644 --- a/include/linux/clk-provider.h +++ b/include/linux/clk-provider.h @@ -74,7 +74,7 @@ void clk_hw_forward_rate_request(const struct clk_hw *core, unsigned long parent_rate); /** - * struct clk_duty - Struture encoding the duty cycle ratio of a clock + * struct clk_duty - Structure encoding the duty cycle ratio of a clock * * @num: Numerator of the duty cycle ratio * @den: Denominator of the duty cycle ratio @@ -129,7 +129,7 @@ struct clk_duty { * @restore_context: Restore the context of the clock after a restoration * of power. * - * @recalc_rate Recalculate the rate of this clock, by querying hardware. The + * @recalc_rate: Recalculate the rate of this clock, by querying hardware. The * parent rate is an input parameter. It is up to the caller to * ensure that the prepare_mutex is held across this call. If the * driver cannot figure out a rate for this clock, it must return @@ -456,7 +456,7 @@ struct clk *clk_register_fixed_rate(struct device *dev, const char *name, * clock with the clock framework * @dev: device that is registering this clock * @name: name of this clock - * @parent_name: name of clock's parent + * @parent_data: name of clock's parent * @flags: framework-specific flags * @fixed_rate: non-adjustable clock rate * @fixed_accuracy: non-adjustable clock accuracy @@ -471,7 +471,7 @@ struct clk *clk_register_fixed_rate(struct device *dev, const char *name, * the clock framework * @dev: device that is registering this clock * @name: name of this clock - * @parent_name: name of clock's parent + * @parent_data: name of clock's parent * @flags: framework-specific flags * @fixed_rate: non-adjustable clock rate */ @@ -649,7 +649,7 @@ struct clk_div_table { * Clock with an adjustable divider affecting its output frequency. Implements * .recalc_rate, .set_rate and .round_rate * - * Flags: + * @flags: * CLK_DIVIDER_ONE_BASED - by default the divisor is the value read from the * register plus one. If CLK_DIVIDER_ONE_BASED is set then the divider is * the raw value read from the register, with the value of zero considered @@ -1130,11 +1130,12 @@ struct clk_hw *clk_hw_register_fixed_factor_parent_hw(struct device *dev, * @mwidth: width of the numerator bit field * @nshift: shift to the denominator bit field * @nwidth: width of the denominator bit field + * @approximation: clk driver's callback for calculating the divider clock * @lock: register lock * * Clock with adjustable fractional divider affecting its output frequency. * - * Flags: + * @flags: * CLK_FRAC_DIVIDER_ZERO_BASED - by default the numerator and denominator * is the value read from the register. If CLK_FRAC_DIVIDER_ZERO_BASED * is set then the numerator and denominator are both the value read @@ -1191,7 +1192,7 @@ void clk_hw_unregister_fractional_divider(struct clk_hw *hw); * Clock with an adjustable multiplier affecting its output frequency. * Implements .recalc_rate, .set_rate and .round_rate * - * Flags: + * @flags: * CLK_MULTIPLIER_ZERO_BYPASS - By default, the multiplier is the value read * from the register, with 0 being a valid value effectively * zeroing the output clock rate. If CLK_MULTIPLIER_ZERO_BYPASS is -- cgit v1.2.3-59-g8ed1b From 619102313466eaf8a6ac188e711f5df749dac6d4 Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos Date: Sun, 27 Aug 2023 04:39:32 +0200 Subject: clk: ralink: mtmips: quiet unused variable warning When CONFIG_OF is disabled then the matching table is not referenced and the following warning appears: drivers/clk/ralink/clk-mtmips.c:821:34: warning: unused variable 'mtmips_of_match' [-Wunused-const-variable] 821 | static const struct of_device_id mtmips_of_match[] = { | ^ There are two match tables in the driver: one for the clock driver and the other for the reset driver. The only difference between them is that the clock driver uses 'data' and does not have 'ralink,rt2880-reset' compatible. Both just can be merged into a single one just by adding the compatible 'ralink,rt2880-reset' entry to 'mtmips_of_match[]', which will allow it to be used for 'mtmips_clk_driver' (which doesn't use the data) as well as for 'mtmips_clk_init()' (which doesn't need get called for 'ralink,rt2880-reset'). Doing in this way ensures that 'CONFIG_OF' is not disabled anymore so the above warning disapears. Fixes: 6f3b15586eef ("clk: ralink: add clock and reset driver for MTMIPS SoCs") Reported-by: kernel test robot Closes: https://lore.kernel.org/oe-kbuild-all/202307242310.CdOnd2py-lkp@intel.com/ Suggested-by: Arnd Bergmann Signed-off-by: Sergio Paracuellos Link: https://lore.kernel.org/r/20230827023932.501102-1-sergio.paracuellos@gmail.com Reviewed-by: Nathan Chancellor Signed-off-by: Stephen Boyd --- drivers/clk/ralink/clk-mtmips.c | 20 +++++--------------- 1 file changed, 5 insertions(+), 15 deletions(-) diff --git a/drivers/clk/ralink/clk-mtmips.c b/drivers/clk/ralink/clk-mtmips.c index 1e7991439527..50a443bf79ec 100644 --- a/drivers/clk/ralink/clk-mtmips.c +++ b/drivers/clk/ralink/clk-mtmips.c @@ -821,6 +821,10 @@ static const struct mtmips_clk_data mt76x8_clk_data = { }; static const struct of_device_id mtmips_of_match[] = { + { + .compatible = "ralink,rt2880-reset", + .data = NULL, + }, { .compatible = "ralink,rt2880-sysc", .data = &rt2880_clk_data, @@ -1088,25 +1092,11 @@ static int mtmips_clk_probe(struct platform_device *pdev) return 0; } -static const struct of_device_id mtmips_clk_of_match[] = { - { .compatible = "ralink,rt2880-reset" }, - { .compatible = "ralink,rt2880-sysc" }, - { .compatible = "ralink,rt3050-sysc" }, - { .compatible = "ralink,rt3052-sysc" }, - { .compatible = "ralink,rt3352-sysc" }, - { .compatible = "ralink,rt3883-sysc" }, - { .compatible = "ralink,rt5350-sysc" }, - { .compatible = "ralink,mt7620-sysc" }, - { .compatible = "ralink,mt7628-sysc" }, - { .compatible = "ralink,mt7688-sysc" }, - {} -}; - static struct platform_driver mtmips_clk_driver = { .probe = mtmips_clk_probe, .driver = { .name = "mtmips-clk", - .of_match_table = mtmips_clk_of_match, + .of_match_table = mtmips_of_match, }, }; -- cgit v1.2.3-59-g8ed1b From a5d14f8b551eb1551c10053653ee8e27f19672fa Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 5 Oct 2023 17:01:57 +0300 Subject: clk: keystone: pll: fix a couple NULL vs IS_ERR() checks The clk_register_divider() and clk_register_mux() functions returns error pointers on error but this code checks for NULL. Fix that. Fixes: b9e0d40c0d83 ("clk: keystone: add Keystone PLL clock driver") Signed-off-by: Dan Carpenter Link: https://lore.kernel.org/r/d9da4c97-0da9-499f-9a21-1f8e3f148dc1@moroto.mountain Signed-off-by: Stephen Boyd --- drivers/clk/keystone/pll.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/drivers/clk/keystone/pll.c b/drivers/clk/keystone/pll.c index ee5c72369334..6bbdd4705d71 100644 --- a/drivers/clk/keystone/pll.c +++ b/drivers/clk/keystone/pll.c @@ -281,12 +281,13 @@ static void __init of_pll_div_clk_init(struct device_node *node) clk = clk_register_divider(NULL, clk_name, parent_name, 0, reg, shift, mask, 0, NULL); - if (clk) { - of_clk_add_provider(node, of_clk_src_simple_get, clk); - } else { + if (IS_ERR(clk)) { pr_err("%s: error registering divider %s\n", __func__, clk_name); iounmap(reg); + return; } + + of_clk_add_provider(node, of_clk_src_simple_get, clk); } CLK_OF_DECLARE(pll_divider_clock, "ti,keystone,pll-divider-clock", of_pll_div_clk_init); @@ -328,10 +329,12 @@ static void __init of_pll_mux_clk_init(struct device_node *node) clk = clk_register_mux(NULL, clk_name, (const char **)&parents, ARRAY_SIZE(parents) , 0, reg, shift, mask, 0, NULL); - if (clk) - of_clk_add_provider(node, of_clk_src_simple_get, clk); - else + if (IS_ERR(clk)) { pr_err("%s: error registering mux %s\n", __func__, clk_name); + return; + } + + of_clk_add_provider(node, of_clk_src_simple_get, clk); } CLK_OF_DECLARE(pll_mux_clock, "ti,keystone,pll-mux-clock", of_pll_mux_clk_init); -- cgit v1.2.3-59-g8ed1b From 7af5b9eadd64c9e02a71f97c45bcdf3b64841f6b Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Mon, 2 Oct 2023 10:04:36 +0300 Subject: clk: ti: fix double free in of_ti_divider_clk_setup() The "div" pointer is freed in _register_divider() and again in of_ti_divider_clk_setup(). Delete the free in _register_divider() Fixes: fbbc18591585 ("clk: ti: divider: cleanup _register_divider and ti_clk_get_div_table") Signed-off-by: Dan Carpenter Link: https://lore.kernel.org/r/6d36eeec-6c8a-4f11-a579-aa3cd7c38749@moroto.mountain Reviewed-by: Tony Lindgren Signed-off-by: Stephen Boyd --- drivers/clk/ti/divider.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/drivers/clk/ti/divider.c b/drivers/clk/ti/divider.c index 768a1f3398b4..5d5bb123ba94 100644 --- a/drivers/clk/ti/divider.c +++ b/drivers/clk/ti/divider.c @@ -309,7 +309,6 @@ static struct clk *_register_divider(struct device_node *node, u32 flags, struct clk_omap_divider *div) { - struct clk *clk; struct clk_init_data init; const char *parent_name; const char *name; @@ -326,12 +325,7 @@ static struct clk *_register_divider(struct device_node *node, div->hw.init = &init; /* register the clock */ - clk = of_ti_clk_register(node, &div->hw, name); - - if (IS_ERR(clk)) - kfree(div); - - return clk; + return of_ti_clk_register(node, &div->hw, name); } int ti_clk_parse_divider_data(int *div_table, int num_dividers, int max_div, -- cgit v1.2.3-59-g8ed1b From 43a354a21a6a21f050b95317148661a465108cba Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 17 Oct 2023 17:06:53 +0300 Subject: clk: at91: remove unnecessary conditions This code checks "if (parent_hw)" is non-NULL, but then it has more checks if parent_hw is non-NULL on the lines inside the if statement. It is a bit confusing. For the else statement, keep in mind that at the start of the function we checked: if (!(parent_name || parent_hw)) return ERR_PTR(-EINVAL); That check ensures that if parent_hw is NULL that means that parent_name is non-NULL. At least one must always be non-NULL. So here again, the checks inside the if statement can be removed. In the original code, it was a bit confusing and you could easily get the impression that "init.num_parents" could be zero. When we remove the unnecessary checking it's more obvious that it's always set to 1. Signed-off-by: Dan Carpenter Link: https://lore.kernel.org/r/7782b4f1-deed-49dc-8207-b6ea06d7602f@moroto.mountain Reviewed-by: Claudiu Beznea Signed-off-by: Stephen Boyd --- drivers/clk/at91/clk-utmi.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/drivers/clk/at91/clk-utmi.c b/drivers/clk/at91/clk-utmi.c index 40c84f5af5e8..b991180beea1 100644 --- a/drivers/clk/at91/clk-utmi.c +++ b/drivers/clk/at91/clk-utmi.c @@ -161,13 +161,11 @@ at91_clk_register_utmi_internal(struct regmap *regmap_pmc, init.name = name; init.ops = ops; - if (parent_hw) { - init.parent_hws = parent_hw ? (const struct clk_hw **)&parent_hw : NULL; - init.num_parents = parent_hw ? 1 : 0; - } else { - init.parent_names = parent_name ? &parent_name : NULL; - init.num_parents = parent_name ? 1 : 0; - } + if (parent_hw) + init.parent_hws = (const struct clk_hw **)&parent_hw; + else + init.parent_names = &parent_name; + init.num_parents = 1; init.flags = flags; utmi->hw.init = &init; -- cgit v1.2.3-59-g8ed1b From bbc5080bef4a245106aa8e8d424ba8847ca7c0ca Mon Sep 17 00:00:00 2001 From: Jonathan Neuschäfer Date: Sat, 23 Sep 2023 15:31:27 +0200 Subject: clk: npcm7xx: Fix incorrect kfree MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The corresponding allocation is: > npcm7xx_clk_data = kzalloc(struct_size(npcm7xx_clk_data, hws, > NPCM7XX_NUM_CLOCKS), GFP_KERNEL); ... so, kfree should be applied to npcm7xx_clk_data, not npcm7xx_clk_data->hws. Fixes: fcfd14369856 ("clk: npcm7xx: add clock controller") Signed-off-by: Jonathan Neuschäfer Link: https://lore.kernel.org/r/20230923133127.1815621-1-j.neuschaefer@gmx.net Signed-off-by: Stephen Boyd --- drivers/clk/clk-npcm7xx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/clk-npcm7xx.c b/drivers/clk/clk-npcm7xx.c index e319cfa51a8a..030186def9c6 100644 --- a/drivers/clk/clk-npcm7xx.c +++ b/drivers/clk/clk-npcm7xx.c @@ -510,7 +510,7 @@ static void __init npcm7xx_clk_init(struct device_node *clk_np) return; npcm7xx_init_fail: - kfree(npcm7xx_clk_data->hws); + kfree(npcm7xx_clk_data); npcm7xx_init_np_err: iounmap(clk_base); npcm7xx_init_error: -- cgit v1.2.3-59-g8ed1b From b82681042724924ae3ba0f2f2eeec217fa31e830 Mon Sep 17 00:00:00 2001 From: Jiasheng Jiang Date: Tue, 12 Sep 2023 17:34:03 +0800 Subject: clk: mediatek: clk-mt6765: Add check for mtk_alloc_clk_data Add the check for the return value of mtk_alloc_clk_data() in order to avoid NULL pointer dereference. Fixes: 1aca9939bf72 ("clk: mediatek: Add MT6765 clock support") Signed-off-by: Jiasheng Jiang Link: https://lore.kernel.org/r/20230912093407.21505-1-jiasheng@iscas.ac.cn Reviewed-by: AngeloGioacchino Del Regno Signed-off-by: Stephen Boyd --- drivers/clk/mediatek/clk-mt6765.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/clk/mediatek/clk-mt6765.c b/drivers/clk/mediatek/clk-mt6765.c index 1f4c8d0c041a..9c7f7407d798 100644 --- a/drivers/clk/mediatek/clk-mt6765.c +++ b/drivers/clk/mediatek/clk-mt6765.c @@ -737,6 +737,8 @@ static int clk_mt6765_apmixed_probe(struct platform_device *pdev) return PTR_ERR(base); clk_data = mtk_alloc_clk_data(CLK_APMIXED_NR_CLK); + if (!clk_data) + return -ENOMEM; mtk_clk_register_plls(node, plls, ARRAY_SIZE(plls), clk_data); @@ -769,6 +771,8 @@ static int clk_mt6765_top_probe(struct platform_device *pdev) return PTR_ERR(base); clk_data = mtk_alloc_clk_data(CLK_TOP_NR_CLK); + if (!clk_data) + return -ENOMEM; mtk_clk_register_fixed_clks(fixed_clks, ARRAY_SIZE(fixed_clks), clk_data); @@ -807,6 +811,8 @@ static int clk_mt6765_ifr_probe(struct platform_device *pdev) return PTR_ERR(base); clk_data = mtk_alloc_clk_data(CLK_IFR_NR_CLK); + if (!clk_data) + return -ENOMEM; mtk_clk_register_gates(&pdev->dev, node, ifr_clks, ARRAY_SIZE(ifr_clks), clk_data); -- cgit v1.2.3-59-g8ed1b From 1f57f78fbacf630430bf954e5a84caafdfea30c0 Mon Sep 17 00:00:00 2001 From: Jiasheng Jiang Date: Tue, 12 Sep 2023 17:34:04 +0800 Subject: clk: mediatek: clk-mt6779: Add check for mtk_alloc_clk_data Add the check for the return value of mtk_alloc_clk_data() in order to avoid NULL pointer dereference. Fixes: 710774e04861 ("clk: mediatek: Add MT6779 clock support") Signed-off-by: Jiasheng Jiang Link: https://lore.kernel.org/r/20230912093407.21505-2-jiasheng@iscas.ac.cn Reviewed-by: AngeloGioacchino Del Regno Signed-off-by: Stephen Boyd --- drivers/clk/mediatek/clk-mt6779.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/clk/mediatek/clk-mt6779.c b/drivers/clk/mediatek/clk-mt6779.c index 3ee2f5a2319a..ffedb1fe3c67 100644 --- a/drivers/clk/mediatek/clk-mt6779.c +++ b/drivers/clk/mediatek/clk-mt6779.c @@ -1217,6 +1217,8 @@ static int clk_mt6779_apmixed_probe(struct platform_device *pdev) struct device_node *node = pdev->dev.of_node; clk_data = mtk_alloc_clk_data(CLK_APMIXED_NR_CLK); + if (!clk_data) + return -ENOMEM; mtk_clk_register_plls(node, plls, ARRAY_SIZE(plls), clk_data); @@ -1237,6 +1239,8 @@ static int clk_mt6779_top_probe(struct platform_device *pdev) return PTR_ERR(base); clk_data = mtk_alloc_clk_data(CLK_TOP_NR_CLK); + if (!clk_data) + return -ENOMEM; mtk_clk_register_fixed_clks(top_fixed_clks, ARRAY_SIZE(top_fixed_clks), clk_data); -- cgit v1.2.3-59-g8ed1b From 606f6366a35a3329545e38129804d65ef26ed7d2 Mon Sep 17 00:00:00 2001 From: Jiasheng Jiang Date: Tue, 12 Sep 2023 17:34:05 +0800 Subject: clk: mediatek: clk-mt6797: Add check for mtk_alloc_clk_data Add the check for the return value of mtk_alloc_clk_data() in order to avoid NULL pointer dereference. Fixes: 96596aa06628 ("clk: mediatek: add clk support for MT6797") Signed-off-by: Jiasheng Jiang Link: https://lore.kernel.org/r/20230912093407.21505-3-jiasheng@iscas.ac.cn Reviewed-by: AngeloGioacchino Del Regno Signed-off-by: Stephen Boyd --- drivers/clk/mediatek/clk-mt6797.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/clk/mediatek/clk-mt6797.c b/drivers/clk/mediatek/clk-mt6797.c index 2ebd25f0ce71..f12d4e9ff0bb 100644 --- a/drivers/clk/mediatek/clk-mt6797.c +++ b/drivers/clk/mediatek/clk-mt6797.c @@ -390,6 +390,8 @@ static int mtk_topckgen_init(struct platform_device *pdev) return PTR_ERR(base); clk_data = mtk_alloc_clk_data(CLK_TOP_NR); + if (!clk_data) + return -ENOMEM; mtk_clk_register_factors(top_fixed_divs, ARRAY_SIZE(top_fixed_divs), clk_data); @@ -545,6 +547,8 @@ static void mtk_infrasys_init_early(struct device_node *node) if (!infra_clk_data) { infra_clk_data = mtk_alloc_clk_data(CLK_INFRA_NR); + if (!infra_clk_data) + return; for (i = 0; i < CLK_INFRA_NR; i++) infra_clk_data->hws[i] = ERR_PTR(-EPROBE_DEFER); @@ -570,6 +574,8 @@ static int mtk_infrasys_init(struct platform_device *pdev) if (!infra_clk_data) { infra_clk_data = mtk_alloc_clk_data(CLK_INFRA_NR); + if (!infra_clk_data) + return -ENOMEM; } else { for (i = 0; i < CLK_INFRA_NR; i++) { if (infra_clk_data->hws[i] == ERR_PTR(-EPROBE_DEFER)) -- cgit v1.2.3-59-g8ed1b From 0884393c63cc9a1772f7121a6645ba7bd76feeb9 Mon Sep 17 00:00:00 2001 From: Jiasheng Jiang Date: Tue, 12 Sep 2023 17:34:06 +0800 Subject: clk: mediatek: clk-mt7629-eth: Add check for mtk_alloc_clk_data Add the check for the return value of mtk_alloc_clk_data() in order to avoid NULL pointer dereference. Fixes: 3b5e748615e7 ("clk: mediatek: add clock support for MT7629 SoC") Signed-off-by: Jiasheng Jiang Link: https://lore.kernel.org/r/20230912093407.21505-4-jiasheng@iscas.ac.cn Reviewed-by: AngeloGioacchino Del Regno Signed-off-by: Stephen Boyd --- drivers/clk/mediatek/clk-mt7629-eth.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/clk/mediatek/clk-mt7629-eth.c b/drivers/clk/mediatek/clk-mt7629-eth.c index fe714debdc9e..1bfedc988cfe 100644 --- a/drivers/clk/mediatek/clk-mt7629-eth.c +++ b/drivers/clk/mediatek/clk-mt7629-eth.c @@ -77,6 +77,8 @@ static int clk_mt7629_ethsys_init(struct platform_device *pdev) int r; clk_data = mtk_alloc_clk_data(CLK_ETH_NR_CLK); + if (!clk_data) + return -ENOMEM; mtk_clk_register_gates(&pdev->dev, node, eth_clks, CLK_ETH_NR_CLK, clk_data); @@ -100,6 +102,8 @@ static int clk_mt7629_sgmiisys_init(struct platform_device *pdev) int r; clk_data = mtk_alloc_clk_data(CLK_SGMII_NR_CLK); + if (!clk_data) + return -ENOMEM; mtk_clk_register_gates(&pdev->dev, node, sgmii_clks[id++], CLK_SGMII_NR_CLK, clk_data); -- cgit v1.2.3-59-g8ed1b From 2befa515c1bb6cdd33c262b909d93d1973a219aa Mon Sep 17 00:00:00 2001 From: Jiasheng Jiang Date: Tue, 12 Sep 2023 17:34:07 +0800 Subject: clk: mediatek: clk-mt7629: Add check for mtk_alloc_clk_data Add the check for the return value of mtk_alloc_clk_data() in order to avoid NULL pointer dereference. Fixes: 3b5e748615e7 ("clk: mediatek: add clock support for MT7629 SoC") Signed-off-by: Jiasheng Jiang Link: https://lore.kernel.org/r/20230912093407.21505-5-jiasheng@iscas.ac.cn Reviewed-by: AngeloGioacchino Del Regno Signed-off-by: Stephen Boyd --- drivers/clk/mediatek/clk-mt7629.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/clk/mediatek/clk-mt7629.c b/drivers/clk/mediatek/clk-mt7629.c index 2882107d0f24..b8a1f01bc974 100644 --- a/drivers/clk/mediatek/clk-mt7629.c +++ b/drivers/clk/mediatek/clk-mt7629.c @@ -555,6 +555,8 @@ static int mtk_topckgen_init(struct platform_device *pdev) return PTR_ERR(base); clk_data = mtk_alloc_clk_data(CLK_TOP_NR_CLK); + if (!clk_data) + return -ENOMEM; mtk_clk_register_fixed_clks(top_fixed_clks, ARRAY_SIZE(top_fixed_clks), clk_data); @@ -579,6 +581,8 @@ static int mtk_infrasys_init(struct platform_device *pdev) struct clk_hw_onecell_data *clk_data; clk_data = mtk_alloc_clk_data(CLK_INFRA_NR_CLK); + if (!clk_data) + return -ENOMEM; mtk_clk_register_gates(&pdev->dev, node, infra_clks, ARRAY_SIZE(infra_clks), clk_data); @@ -602,6 +606,8 @@ static int mtk_pericfg_init(struct platform_device *pdev) return PTR_ERR(base); clk_data = mtk_alloc_clk_data(CLK_PERI_NR_CLK); + if (!clk_data) + return -ENOMEM; mtk_clk_register_gates(&pdev->dev, node, peri_clks, ARRAY_SIZE(peri_clks), clk_data); -- cgit v1.2.3-59-g8ed1b From 0d6e24b422a2166a9297a8286ff2e6ab9a5e8cd3 Mon Sep 17 00:00:00 2001 From: Jiasheng Jiang Date: Fri, 1 Sep 2023 10:46:58 +0800 Subject: clk: mediatek: clk-mt2701: Add check for mtk_alloc_clk_data Add the check for the return value of mtk_alloc_clk_data() in order to avoid NULL pointer dereference. Fixes: e9862118272a ("clk: mediatek: Add MT2701 clock support") Signed-off-by: Jiasheng Jiang Link: https://lore.kernel.org/r/20230901024658.23405-1-jiasheng@iscas.ac.cn Reviewed-by: Markus Schneider-Pargmann Reviewed-by: AngeloGioacchino Del Regno Signed-off-by: Stephen Boyd --- drivers/clk/mediatek/clk-mt2701.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/clk/mediatek/clk-mt2701.c b/drivers/clk/mediatek/clk-mt2701.c index c81f3e33ce56..12d9560eb4ba 100644 --- a/drivers/clk/mediatek/clk-mt2701.c +++ b/drivers/clk/mediatek/clk-mt2701.c @@ -667,6 +667,8 @@ static int mtk_topckgen_init(struct platform_device *pdev) return PTR_ERR(base); clk_data = mtk_alloc_clk_data(CLK_TOP_NR); + if (!clk_data) + return -ENOMEM; mtk_clk_register_fixed_clks(top_fixed_clks, ARRAY_SIZE(top_fixed_clks), clk_data); @@ -747,6 +749,8 @@ static void __init mtk_infrasys_init_early(struct device_node *node) if (!infra_clk_data) { infra_clk_data = mtk_alloc_clk_data(CLK_INFRA_NR); + if (!infra_clk_data) + return; for (i = 0; i < CLK_INFRA_NR; i++) infra_clk_data->hws[i] = ERR_PTR(-EPROBE_DEFER); @@ -774,6 +778,8 @@ static int mtk_infrasys_init(struct platform_device *pdev) if (!infra_clk_data) { infra_clk_data = mtk_alloc_clk_data(CLK_INFRA_NR); + if (!infra_clk_data) + return -ENOMEM; } else { for (i = 0; i < CLK_INFRA_NR; i++) { if (infra_clk_data->hws[i] == ERR_PTR(-EPROBE_DEFER)) @@ -890,6 +896,8 @@ static int mtk_pericfg_init(struct platform_device *pdev) return PTR_ERR(base); clk_data = mtk_alloc_clk_data(CLK_PERI_NR); + if (!clk_data) + return -ENOMEM; mtk_clk_register_gates(&pdev->dev, node, peri_clks, ARRAY_SIZE(peri_clks), clk_data); -- cgit v1.2.3-59-g8ed1b From 4eb15b036367006ec7f0b9880993ceb6ae259ec8 Mon Sep 17 00:00:00 2001 From: Andreas Kemnade Date: Sat, 16 Sep 2023 12:05:14 +0200 Subject: clk: twl: add clock driver for TWL6032 The TWL6032 has some clock outputs which are controlled like fixed-voltage regulators, in some drivers for these chips found in the wild, just the regulator api is abused for controlling them, so simply use something similar to the regulator functions. Due to a lack of hardware available for testing, leave out the TWL6030-specific part of those functions. Signed-off-by: Andreas Kemnade Link: https://lore.kernel.org/r/20230916100515.1650336-5-andreas@kemnade.info Signed-off-by: Stephen Boyd --- drivers/clk/Kconfig | 9 +++ drivers/clk/Makefile | 1 + drivers/clk/clk-twl.c | 197 ++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 207 insertions(+) create mode 100644 drivers/clk/clk-twl.c diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index c30099866174..3944f081ebad 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig @@ -277,6 +277,15 @@ config COMMON_CLK_S2MPS11 clock. These multi-function devices have two (S2MPS14) or three (S2MPS11, S5M8767) fixed-rate oscillators, clocked at 32KHz each. +config CLK_TWL + tristate "Clock driver for the TWL PMIC family" + depends on TWL4030_CORE + help + Enable support for controlling the clock resources on TWL family + PMICs. These devices have some 32K clock outputs which can be + controlled by software. For now, only the TWL6032 clocks are + supported. + config CLK_TWL6040 tristate "External McPDM functional clock from twl6040" depends on TWL6040_CORE diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index 18969cbd4bb1..86e46adcb619 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -72,6 +72,7 @@ obj-$(CONFIG_COMMON_CLK_STM32H7) += clk-stm32h7.o obj-$(CONFIG_COMMON_CLK_STM32MP157) += clk-stm32mp1.o obj-$(CONFIG_COMMON_CLK_TPS68470) += clk-tps68470.o obj-$(CONFIG_CLK_TWL6040) += clk-twl6040.o +obj-$(CONFIG_CLK_TWL) += clk-twl.o obj-$(CONFIG_ARCH_VT8500) += clk-vt8500.o obj-$(CONFIG_COMMON_CLK_RS9_PCIE) += clk-renesas-pcie.o obj-$(CONFIG_COMMON_CLK_SI521XX) += clk-si521xx.o diff --git a/drivers/clk/clk-twl.c b/drivers/clk/clk-twl.c new file mode 100644 index 000000000000..eab9d3c8ed8a --- /dev/null +++ b/drivers/clk/clk-twl.c @@ -0,0 +1,197 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Clock driver for twl device. + * + * inspired by the driver for the Palmas device + */ + +#include +#include +#include +#include +#include + +#define VREG_STATE 2 +#define TWL6030_CFG_STATE_OFF 0x00 +#define TWL6030_CFG_STATE_ON 0x01 +#define TWL6030_CFG_STATE_MASK 0x03 + +struct twl_clock_info { + struct device *dev; + u8 base; + struct clk_hw hw; +}; + +static inline int +twlclk_read(struct twl_clock_info *info, unsigned int slave_subgp, + unsigned int offset) +{ + u8 value; + int status; + + status = twl_i2c_read_u8(slave_subgp, &value, + info->base + offset); + return (status < 0) ? status : value; +} + +static inline int +twlclk_write(struct twl_clock_info *info, unsigned int slave_subgp, + unsigned int offset, u8 value) +{ + return twl_i2c_write_u8(slave_subgp, value, + info->base + offset); +} + +static inline struct twl_clock_info *to_twl_clks_info(struct clk_hw *hw) +{ + return container_of(hw, struct twl_clock_info, hw); +} + +static unsigned long twl_clks_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + return 32768; +} + +static int twl6032_clks_prepare(struct clk_hw *hw) +{ + struct twl_clock_info *cinfo = to_twl_clks_info(hw); + int ret; + + ret = twlclk_write(cinfo, TWL_MODULE_PM_RECEIVER, VREG_STATE, + TWL6030_CFG_STATE_ON); + if (ret < 0) + dev_err(cinfo->dev, "clk prepare failed\n"); + + return ret; +} + +static void twl6032_clks_unprepare(struct clk_hw *hw) +{ + struct twl_clock_info *cinfo = to_twl_clks_info(hw); + int ret; + + ret = twlclk_write(cinfo, TWL_MODULE_PM_RECEIVER, VREG_STATE, + TWL6030_CFG_STATE_OFF); + if (ret < 0) + dev_err(cinfo->dev, "clk unprepare failed\n"); +} + +static int twl6032_clks_is_prepared(struct clk_hw *hw) +{ + struct twl_clock_info *cinfo = to_twl_clks_info(hw); + int val; + + val = twlclk_read(cinfo, TWL_MODULE_PM_RECEIVER, VREG_STATE); + if (val < 0) { + dev_err(cinfo->dev, "clk read failed\n"); + return val; + } + + val &= TWL6030_CFG_STATE_MASK; + + return val == TWL6030_CFG_STATE_ON; +} + +static const struct clk_ops twl6032_clks_ops = { + .prepare = twl6032_clks_prepare, + .unprepare = twl6032_clks_unprepare, + .is_prepared = twl6032_clks_is_prepared, + .recalc_rate = twl_clks_recalc_rate, +}; + +struct twl_clks_data { + struct clk_init_data init; + u8 base; +}; + +static const struct twl_clks_data twl6032_clks[] = { + { + .init = { + .name = "clk32kg", + .ops = &twl6032_clks_ops, + .flags = CLK_IGNORE_UNUSED, + }, + .base = 0x8C, + }, + { + .init = { + .name = "clk32kaudio", + .ops = &twl6032_clks_ops, + .flags = CLK_IGNORE_UNUSED, + }, + .base = 0x8F, + }, + { + /* sentinel */ + } +}; + +static int twl_clks_probe(struct platform_device *pdev) +{ + struct clk_hw_onecell_data *clk_data; + const struct twl_clks_data *hw_data; + + struct twl_clock_info *cinfo; + int ret; + int i; + int count; + + hw_data = twl6032_clks; + for (count = 0; hw_data[count].init.name; count++) + ; + + clk_data = devm_kzalloc(&pdev->dev, + struct_size(clk_data, hws, count), + GFP_KERNEL); + if (!clk_data) + return -ENOMEM; + + clk_data->num = count; + cinfo = devm_kcalloc(&pdev->dev, count, sizeof(*cinfo), GFP_KERNEL); + if (!cinfo) + return -ENOMEM; + + for (i = 0; i < count; i++) { + cinfo[i].base = hw_data[i].base; + cinfo[i].dev = &pdev->dev; + cinfo[i].hw.init = &hw_data[i].init; + ret = devm_clk_hw_register(&pdev->dev, &cinfo[i].hw); + if (ret) { + return dev_err_probe(&pdev->dev, ret, + "Fail to register clock %s\n", + hw_data[i].init.name); + } + clk_data->hws[i] = &cinfo[i].hw; + } + + ret = devm_of_clk_add_hw_provider(&pdev->dev, + of_clk_hw_onecell_get, clk_data); + if (ret < 0) + return dev_err_probe(&pdev->dev, ret, + "Fail to add clock driver\n"); + + return 0; +} + +static const struct platform_device_id twl_clks_id[] = { + { + .name = "twl6032-clk", + }, { + /* sentinel */ + } +}; +MODULE_DEVICE_TABLE(platform, twl_clks_id); + +static struct platform_driver twl_clks_driver = { + .driver = { + .name = "twl-clk", + }, + .probe = twl_clks_probe, + .id_table = twl_clks_id, +}; + +module_platform_driver(twl_clks_driver); + +MODULE_DESCRIPTION("Clock driver for TWL Series Devices"); +MODULE_LICENSE("GPL"); -- cgit v1.2.3-59-g8ed1b From abaf59c470a7c9c59bda8da3517ec2ff0513f5a6 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Mon, 11 Sep 2023 17:15:48 +0200 Subject: clk: qcom: cbf-msm8996: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is ignored (apart from emitting a warning) and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Eventually after all drivers are converted, .remove_new() is renamed to .remove(). qcom_msm8996_cbf_icc_remove() returned zero unconditionally. After changing this function to return void instead, the driver can be converted trivially to use .remove_new(). Signed-off-by: Uwe Kleine-König Link: https://lore.kernel.org/r/20230911151548.672485-1-u.kleine-koenig@pengutronix.de Signed-off-by: Bjorn Andersson --- drivers/clk/qcom/clk-cbf-8996.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/drivers/clk/qcom/clk-cbf-8996.c b/drivers/clk/qcom/clk-cbf-8996.c index 53f205a3f183..fe24b4abeab4 100644 --- a/drivers/clk/qcom/clk-cbf-8996.c +++ b/drivers/clk/qcom/clk-cbf-8996.c @@ -250,13 +250,11 @@ static int qcom_msm8996_cbf_icc_register(struct platform_device *pdev, struct cl return 0; } -static int qcom_msm8996_cbf_icc_remove(struct platform_device *pdev) +static void qcom_msm8996_cbf_icc_remove(struct platform_device *pdev) { struct icc_provider *provider = platform_get_drvdata(pdev); icc_clk_unregister(provider); - - return 0; } #define qcom_msm8996_cbf_icc_sync_state icc_sync_state #else @@ -266,7 +264,7 @@ static int qcom_msm8996_cbf_icc_register(struct platform_device *pdev, struct c return 0; } -#define qcom_msm8996_cbf_icc_remove(pdev) (0) +#define qcom_msm8996_cbf_icc_remove(pdev) { } #define qcom_msm8996_cbf_icc_sync_state NULL #endif @@ -340,9 +338,9 @@ static int qcom_msm8996_cbf_probe(struct platform_device *pdev) return qcom_msm8996_cbf_icc_register(pdev, &cbf_mux.clkr.hw); } -static int qcom_msm8996_cbf_remove(struct platform_device *pdev) +static void qcom_msm8996_cbf_remove(struct platform_device *pdev) { - return qcom_msm8996_cbf_icc_remove(pdev); + qcom_msm8996_cbf_icc_remove(pdev); } static const struct of_device_id qcom_msm8996_cbf_match_table[] = { @@ -354,7 +352,7 @@ MODULE_DEVICE_TABLE(of, qcom_msm8996_cbf_match_table); static struct platform_driver qcom_msm8996_cbf_driver = { .probe = qcom_msm8996_cbf_probe, - .remove = qcom_msm8996_cbf_remove, + .remove_new = qcom_msm8996_cbf_remove, .driver = { .name = "qcom-msm8996-cbf", .of_match_table = qcom_msm8996_cbf_match_table, -- cgit v1.2.3-59-g8ed1b From 76ca22bd3d95cfb5113206894abbc80de6ceb1fe Mon Sep 17 00:00:00 2001 From: Konrad Dybcio Date: Fri, 25 Aug 2023 17:38:32 +0200 Subject: clk: qcom: smd-rpm: Move CPUSS_GNoC clock to interconnect As it turns out, it's yet another interconnect bus clock. Move it there. See [1] for reference. [1] https://android.googlesource.com/kernel/msm-extra/devicetree/+/02f8c342b23c20a5cf967df649814be37a08227c%5E%21/#F0 Signed-off-by: Konrad Dybcio Link: https://lore.kernel.org/r/20230726-topic-icc_coeff-v4-10-c04b60caa467@linaro.org Signed-off-by: Bjorn Andersson --- drivers/clk/qcom/clk-smd-rpm.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/drivers/clk/qcom/clk-smd-rpm.c b/drivers/clk/qcom/clk-smd-rpm.c index 0191fc0dd7da..8602c02047d0 100644 --- a/drivers/clk/qcom/clk-smd-rpm.c +++ b/drivers/clk/qcom/clk-smd-rpm.c @@ -574,6 +574,16 @@ static const struct clk_smd_rpm *sm_qnoc_icc_clks[] = { &clk_smd_rpm_bus_2_snoc_clk, }; +static const struct clk_smd_rpm *qcm2290_icc_clks[] = { + &clk_smd_rpm_bimc_clk, + &clk_smd_rpm_bus_1_cnoc_clk, + &clk_smd_rpm_mmnrt_clk, + &clk_smd_rpm_mmrt_clk, + &clk_smd_rpm_qup_clk, + &clk_smd_rpm_bus_2_snoc_clk, + &clk_smd_rpm_cpuss_gnoc_clk, +}; + static struct clk_smd_rpm *msm8909_clks[] = { [RPM_SMD_QPIC_CLK] = &clk_smd_rpm_qpic_clk, [RPM_SMD_QPIC_CLK_A] = &clk_smd_rpm_qpic_a_clk, @@ -1189,15 +1199,13 @@ static struct clk_smd_rpm *qcm2290_clks[] = { [RPM_SMD_PKA_A_CLK] = &clk_smd_rpm_pka_a_clk, [RPM_SMD_BIMC_GPU_CLK] = &clk_smd_rpm_bimc_gpu_clk, [RPM_SMD_BIMC_GPU_A_CLK] = &clk_smd_rpm_bimc_gpu_a_clk, - [RPM_SMD_CPUSS_GNOC_CLK] = &clk_smd_rpm_cpuss_gnoc_clk, - [RPM_SMD_CPUSS_GNOC_A_CLK] = &clk_smd_rpm_cpuss_gnoc_a_clk, }; static const struct rpm_smd_clk_desc rpm_clk_qcm2290 = { .clks = qcm2290_clks, .num_clks = ARRAY_SIZE(qcm2290_clks), - .icc_clks = sm_qnoc_icc_clks, - .num_icc_clks = ARRAY_SIZE(sm_qnoc_icc_clks) + .icc_clks = qcm2290_icc_clks, + .num_icc_clks = ARRAY_SIZE(qcm2290_icc_clks) }; static const struct of_device_id rpm_smd_clk_match_table[] = { -- cgit v1.2.3-59-g8ed1b From bff482ace43eebc5b4394cc9a7c7723f08413f80 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Tue, 10 Oct 2023 15:57:10 -0500 Subject: clk: qcom: Replace of_device.h with explicit includes The DT of_device.h and of_platform.h date back to the separate of_platform_bus_type before it as merged into the regular platform bus. As part of that merge prepping Arm DT support 13 years ago, they "temporarily" include each other and pull in various other headers. In preparation to fix this, adjust the includes for what is actually needed. of_device.h isn't needed, but mod_devicetable.h and platform_device.h were implicitly included by it. Signed-off-by: Rob Herring Link: https://lore.kernel.org/r/20231010205710.1585232-1-robh@kernel.org Signed-off-by: Bjorn Andersson --- drivers/clk/qcom/camcc-sm8550.c | 3 ++- drivers/clk/qcom/gcc-ipq5018.c | 3 ++- drivers/clk/qcom/gcc-sm4450.c | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/clk/qcom/camcc-sm8550.c b/drivers/clk/qcom/camcc-sm8550.c index 2133e768b891..dd51ba4ea757 100644 --- a/drivers/clk/qcom/camcc-sm8550.c +++ b/drivers/clk/qcom/camcc-sm8550.c @@ -4,8 +4,9 @@ */ #include +#include #include -#include +#include #include #include diff --git a/drivers/clk/qcom/gcc-ipq5018.c b/drivers/clk/qcom/gcc-ipq5018.c index 19dc2b71cacf..70f6ade3ac2a 100644 --- a/drivers/clk/qcom/gcc-ipq5018.c +++ b/drivers/clk/qcom/gcc-ipq5018.c @@ -3,8 +3,9 @@ * Copyright (c) 2023, The Linux Foundation. All rights reserved. */ #include +#include #include -#include +#include #include #include diff --git a/drivers/clk/qcom/gcc-sm4450.c b/drivers/clk/qcom/gcc-sm4450.c index 41c6357d09bc..31abe2775fc8 100644 --- a/drivers/clk/qcom/gcc-sm4450.c +++ b/drivers/clk/qcom/gcc-sm4450.c @@ -4,8 +4,9 @@ */ #include +#include #include -#include +#include #include #include -- cgit v1.2.3-59-g8ed1b From 21134ec8af94981b3127a691df2d73540ba4d8aa Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Mon, 16 Oct 2023 11:43:55 +0300 Subject: clk: qcom: gpucc-sm8550: switch to clk_lucid_ole_pll_configure Instead of manually specifying the RINGOSC_CAL_L and CAL_L values in the alpha_pll_config.l field, use the proper clk_lucid_ole_pll_configure() function to configure the PLL. Signed-off-by: Dmitry Baryshkov Reviewed-by: Konrad Dybcio Link: https://lore.kernel.org/r/20231016084356.1301854-1-dmitry.baryshkov@linaro.org Signed-off-by: Bjorn Andersson --- drivers/clk/qcom/gpucc-sm8550.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/clk/qcom/gpucc-sm8550.c b/drivers/clk/qcom/gpucc-sm8550.c index 775e0b931923..420dcb27b47d 100644 --- a/drivers/clk/qcom/gpucc-sm8550.c +++ b/drivers/clk/qcom/gpucc-sm8550.c @@ -39,8 +39,7 @@ static const struct pll_vco lucid_ole_vco[] = { }; static const struct alpha_pll_config gpu_cc_pll0_config = { - /* .l includes RINGOSC_CAL_L_VAL, CAL_L_VAL, L_VAL fields */ - .l = 0x4444000d, + .l = 0x0d, .alpha = 0x0, .config_ctl_val = 0x20485699, .config_ctl_hi_val = 0x00182261, @@ -71,8 +70,7 @@ static struct clk_alpha_pll gpu_cc_pll0 = { }; static const struct alpha_pll_config gpu_cc_pll1_config = { - /* .l includes RINGOSC_CAL_L_VAL, CAL_L_VAL, L_VAL fields */ - .l = 0x44440016, + .l = 0x16, .alpha = 0xeaaa, .config_ctl_val = 0x20485699, .config_ctl_hi_val = 0x00182261, @@ -574,8 +572,8 @@ static int gpu_cc_sm8550_probe(struct platform_device *pdev) if (IS_ERR(regmap)) return PTR_ERR(regmap); - clk_lucid_evo_pll_configure(&gpu_cc_pll0, regmap, &gpu_cc_pll0_config); - clk_lucid_evo_pll_configure(&gpu_cc_pll1, regmap, &gpu_cc_pll1_config); + clk_lucid_ole_pll_configure(&gpu_cc_pll0, regmap, &gpu_cc_pll0_config); + clk_lucid_ole_pll_configure(&gpu_cc_pll1, regmap, &gpu_cc_pll1_config); /* * Keep clocks always enabled: -- cgit v1.2.3-59-g8ed1b From a2620539ae2529916a98585c6d7311c48fb67e9f Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Mon, 16 Oct 2023 11:43:56 +0300 Subject: clk: qcom: videocc-sm8550: switch to clk_lucid_ole_pll_configure Instead of manually specifying the RINGOSC_CAL_L and CAL_L values in the alpha_pll_config.l field, use the proper clk_lucid_ole_pll_configure() function to configure the PLL. Signed-off-by: Dmitry Baryshkov Reviewed-by: Konrad Dybcio Link: https://lore.kernel.org/r/20231016084356.1301854-2-dmitry.baryshkov@linaro.org Signed-off-by: Bjorn Andersson --- drivers/clk/qcom/videocc-sm8550.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/clk/qcom/videocc-sm8550.c b/drivers/clk/qcom/videocc-sm8550.c index 3bb136ec31b1..f3c9dfaee968 100644 --- a/drivers/clk/qcom/videocc-sm8550.c +++ b/drivers/clk/qcom/videocc-sm8550.c @@ -36,8 +36,7 @@ static const struct pll_vco lucid_ole_vco[] = { }; static const struct alpha_pll_config video_cc_pll0_config = { - /* .l includes RINGOSC_CAL_L_VAL, CAL_L_VAL, L_VAL fields */ - .l = 0x44440025, + .l = 0x25, .alpha = 0x8000, .config_ctl_val = 0x20485699, .config_ctl_hi_val = 0x00182261, @@ -68,8 +67,7 @@ static struct clk_alpha_pll video_cc_pll0 = { }; static const struct alpha_pll_config video_cc_pll1_config = { - /* .l includes RINGOSC_CAL_L_VAL, CAL_L_VAL, L_VAL fields */ - .l = 0x44440036, + .l = 0x36, .alpha = 0xb000, .config_ctl_val = 0x20485699, .config_ctl_hi_val = 0x00182261, @@ -427,8 +425,8 @@ static int video_cc_sm8550_probe(struct platform_device *pdev) return PTR_ERR(regmap); } - clk_lucid_evo_pll_configure(&video_cc_pll0, regmap, &video_cc_pll0_config); - clk_lucid_evo_pll_configure(&video_cc_pll1, regmap, &video_cc_pll1_config); + clk_lucid_ole_pll_configure(&video_cc_pll0, regmap, &video_cc_pll0_config); + clk_lucid_ole_pll_configure(&video_cc_pll1, regmap, &video_cc_pll1_config); /* * Keep clocks always enabled: -- cgit v1.2.3-59-g8ed1b From 6a15647d0adc686226045e8046369f34d6ab03ed Mon Sep 17 00:00:00 2001 From: Varadarajan Narayanan Date: Fri, 20 Oct 2023 11:49:31 +0530 Subject: clk: qcom: config IPQ_APSS_6018 should depend on QCOM_SMEM The config IPQ_APSS_6018 should depend on QCOM_SMEM, to avoid the following error reported by 'kernel test robot' loongarch64-linux-ld: drivers/clk/qcom/apss-ipq6018.o: in function `apss_ipq6018_probe': >> apss-ipq6018.c:(.text+0xd0): undefined reference to `qcom_smem_get_soc_id' Fixes: 5e77b4ef1b19 ("clk: qcom: Add ipq6018 apss clock controller") Reported-by: kernel test robot Closes: https://lore.kernel.org/r/202310181650.g8THtfsm-lkp@intel.com/ Signed-off-by: Varadarajan Narayanan Link: https://lore.kernel.org/r/f4c4d65a7cb71e807d6d472c63c7718408c8f5f0.1697781921.git.quic_varada@quicinc.com Signed-off-by: Bjorn Andersson --- drivers/clk/qcom/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig index 3194c8beb06d..ad1acd9b7426 100644 --- a/drivers/clk/qcom/Kconfig +++ b/drivers/clk/qcom/Kconfig @@ -131,6 +131,7 @@ config IPQ_APSS_6018 tristate "IPQ APSS Clock Controller" select IPQ_APSS_PLL depends on QCOM_APCS_IPC || COMPILE_TEST + depends on QCOM_SMEM help Support for APSS clock controller on IPQ platforms. The APSS clock controller manages the Mux and enable block that feeds the -- cgit v1.2.3-59-g8ed1b From 84da48921a97cee3dd1391659e93ee01d122b78b Mon Sep 17 00:00:00 2001 From: Varadarajan Narayanan Date: Fri, 20 Oct 2023 11:49:32 +0530 Subject: clk: qcom: clk-alpha-pll: introduce stromer plus ops Stromer plus APSS PLL does not support dynamic frequency scaling. To switch between frequencies, we have to shut down the PLL, configure the L and ALPHA values and turn on again. So introduce the separate set of ops for Stromer Plus PLL. Reviewed-by: Dmitry Baryshkov Signed-off-by: Kathiravan T Signed-off-by: Varadarajan Narayanan Link: https://lore.kernel.org/r/2affa6c63ff0c4342230623a7d4eef02ec7c02d4.1697781921.git.quic_varada@quicinc.com Signed-off-by: Bjorn Andersson --- drivers/clk/qcom/clk-alpha-pll.c | 63 ++++++++++++++++++++++++++++++++++++++++ drivers/clk/qcom/clk-alpha-pll.h | 1 + 2 files changed, 64 insertions(+) diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c index 4edbf77f3360..05898d2a8b22 100644 --- a/drivers/clk/qcom/clk-alpha-pll.c +++ b/drivers/clk/qcom/clk-alpha-pll.c @@ -2508,3 +2508,66 @@ const struct clk_ops clk_alpha_pll_stromer_ops = { .set_rate = clk_alpha_pll_stromer_set_rate, }; EXPORT_SYMBOL_GPL(clk_alpha_pll_stromer_ops); + +static int clk_alpha_pll_stromer_plus_set_rate(struct clk_hw *hw, + unsigned long rate, + unsigned long prate) +{ + struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); + u32 l, alpha_width = pll_alpha_width(pll); + int ret, pll_mode; + u64 a; + + rate = alpha_pll_round_rate(rate, prate, &l, &a, alpha_width); + + ret = regmap_read(pll->clkr.regmap, PLL_MODE(pll), &pll_mode); + if (ret) + return ret; + + regmap_write(pll->clkr.regmap, PLL_MODE(pll), 0); + + /* Delay of 2 output clock ticks required until output is disabled */ + udelay(1); + + regmap_write(pll->clkr.regmap, PLL_L_VAL(pll), l); + + if (alpha_width > ALPHA_BITWIDTH) + a <<= alpha_width - ALPHA_BITWIDTH; + + regmap_write(pll->clkr.regmap, PLL_ALPHA_VAL(pll), a); + regmap_write(pll->clkr.regmap, PLL_ALPHA_VAL_U(pll), + a >> ALPHA_BITWIDTH); + + regmap_write(pll->clkr.regmap, PLL_MODE(pll), PLL_BYPASSNL); + + /* Wait five micro seconds or more */ + udelay(5); + regmap_update_bits(pll->clkr.regmap, PLL_MODE(pll), PLL_RESET_N, + PLL_RESET_N); + + /* The lock time should be less than 50 micro seconds worst case */ + usleep_range(50, 60); + + ret = wait_for_pll_enable_lock(pll); + if (ret) { + pr_err("Wait for PLL enable lock failed [%s] %d\n", + clk_hw_get_name(hw), ret); + return ret; + } + + if (pll_mode & PLL_OUTCTRL) + regmap_update_bits(pll->clkr.regmap, PLL_MODE(pll), PLL_OUTCTRL, + PLL_OUTCTRL); + + return 0; +} + +const struct clk_ops clk_alpha_pll_stromer_plus_ops = { + .prepare = clk_alpha_pll_enable, + .unprepare = clk_alpha_pll_disable, + .is_enabled = clk_alpha_pll_is_enabled, + .recalc_rate = clk_alpha_pll_recalc_rate, + .determine_rate = clk_alpha_pll_stromer_determine_rate, + .set_rate = clk_alpha_pll_stromer_plus_set_rate, +}; +EXPORT_SYMBOL_GPL(clk_alpha_pll_stromer_plus_ops); diff --git a/drivers/clk/qcom/clk-alpha-pll.h b/drivers/clk/qcom/clk-alpha-pll.h index 3b24a660daac..a1a75bb12fe8 100644 --- a/drivers/clk/qcom/clk-alpha-pll.h +++ b/drivers/clk/qcom/clk-alpha-pll.h @@ -152,6 +152,7 @@ extern const struct clk_ops clk_alpha_pll_postdiv_ops; extern const struct clk_ops clk_alpha_pll_huayra_ops; extern const struct clk_ops clk_alpha_pll_postdiv_ro_ops; extern const struct clk_ops clk_alpha_pll_stromer_ops; +extern const struct clk_ops clk_alpha_pll_stromer_plus_ops; extern const struct clk_ops clk_alpha_pll_fabia_ops; extern const struct clk_ops clk_alpha_pll_fixed_fabia_ops; -- cgit v1.2.3-59-g8ed1b From 267e29198436a8cb6770213471f72502c895096a Mon Sep 17 00:00:00 2001 From: Varadarajan Narayanan Date: Fri, 20 Oct 2023 11:49:33 +0530 Subject: clk: qcom: apss-ipq-pll: Use stromer plus ops for stromer plus pll The set rate and determine rate operations are different between Stromer and Stromer Plus PLLs. Since the programming sequence is different, the PLLs dont get configured properly and random, inexplicable crash/freeze is seen. Hence, use stromer plus ops for ipq_pll_stromer_plus. Reviewed-by: Dmitry Baryshkov Acked-by: Stephen Boyd Fixes: c7ef7fbb1ccf ("clk: qcom: apss-ipq-pll: add support for IPQ5332") Signed-off-by: Kathiravan T Signed-off-by: Varadarajan Narayanan Link: https://lore.kernel.org/r/c86ecaa23dc4f39650bcf4a3bd54a617a932e4fd.1697781921.git.quic_varada@quicinc.com Signed-off-by: Bjorn Andersson --- drivers/clk/qcom/apss-ipq-pll.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/qcom/apss-ipq-pll.c b/drivers/clk/qcom/apss-ipq-pll.c index e170331858cc..18c4ffe153d6 100644 --- a/drivers/clk/qcom/apss-ipq-pll.c +++ b/drivers/clk/qcom/apss-ipq-pll.c @@ -68,7 +68,7 @@ static struct clk_alpha_pll ipq_pll_stromer_plus = { .fw_name = "xo", }, .num_parents = 1, - .ops = &clk_alpha_pll_stromer_ops, + .ops = &clk_alpha_pll_stromer_plus_ops, }, }, }; -- cgit v1.2.3-59-g8ed1b From 5b7a4d3d2b33398330aef69e0ff5656273483587 Mon Sep 17 00:00:00 2001 From: Varadarajan Narayanan Date: Fri, 20 Oct 2023 11:49:34 +0530 Subject: clk: qcom: apss-ipq-pll: Fix 'l' value for ipq5332_pll_config The earlier 'l' value of 0x3e is for 1.5GHz. Not all SKUs support this frequency. Hence set it to 0x2d to get 1.1GHz which is supported in all SKUs. The frequency can still increase above this initial configuration made here when the cpufreq driver picks a different OPP. Reviewed-by: Dmitry Baryshkov Reviewed-by: Konrad Dybcio Fixes: c7ef7fbb1ccf ("clk: qcom: apss-ipq-pll: add support for IPQ5332") Signed-off-by: Kathiravan T Signed-off-by: Varadarajan Narayanan Link: https://lore.kernel.org/r/00e6be6cb9cee56628123a64ade118d0a752018b.1697781921.git.quic_varada@quicinc.com Signed-off-by: Bjorn Andersson --- drivers/clk/qcom/apss-ipq-pll.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/qcom/apss-ipq-pll.c b/drivers/clk/qcom/apss-ipq-pll.c index 18c4ffe153d6..41279e5437a6 100644 --- a/drivers/clk/qcom/apss-ipq-pll.c +++ b/drivers/clk/qcom/apss-ipq-pll.c @@ -74,7 +74,7 @@ static struct clk_alpha_pll ipq_pll_stromer_plus = { }; static const struct alpha_pll_config ipq5332_pll_config = { - .l = 0x3e, + .l = 0x2d, .config_ctl_val = 0x4001075b, .config_ctl_hi_val = 0x304, .main_output_mask = BIT(0), -- cgit v1.2.3-59-g8ed1b From 00331227f42045314b3775957f2f7809fb3ac32f Mon Sep 17 00:00:00 2001 From: Varadarajan Narayanan Date: Fri, 20 Oct 2023 11:49:35 +0530 Subject: clk: qcom: apss-ipq6018: ipq5332: add safe source switch for a53pll Stromer Plus PLL found on IPQ53xx doesn't support dynamic frequency scaling. To achieve the same, we need to park the APPS PLL source to GPLL0, re configure the PLL and then switch the source to APSS_PLL_EARLY. To support this, register a clock notifier to get the PRE_RATE and POST_RATE notification. Change the APSS PLL source to GPLL0 when PRE_RATE notification is received, then configure the PLL and then change back the source to APSS_PLL_EARLY. Additionally, not all SKUs of IPQ53xx support scaling. Hence, do the above to the SKUs that support scaling. Reviewed-by: Dmitry Baryshkov Signed-off-by: Kathiravan T Signed-off-by: Varadarajan Narayanan Link: https://lore.kernel.org/r/49422d258d67d33a2547fbb7f4f6e72d489c2301.1697781921.git.quic_varada@quicinc.com Signed-off-by: Bjorn Andersson --- drivers/clk/qcom/apss-ipq6018.c | 58 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 57 insertions(+), 1 deletion(-) diff --git a/drivers/clk/qcom/apss-ipq6018.c b/drivers/clk/qcom/apss-ipq6018.c index f2f502e2d5a4..0783d1aa8efa 100644 --- a/drivers/clk/qcom/apss-ipq6018.c +++ b/drivers/clk/qcom/apss-ipq6018.c @@ -9,8 +9,11 @@ #include #include #include +#include +#include #include +#include #include "common.h" #include "clk-regmap.h" @@ -81,15 +84,68 @@ static const struct qcom_cc_desc apss_ipq6018_desc = { .num_clks = ARRAY_SIZE(apss_ipq6018_clks), }; +static int cpu_clk_notifier_fn(struct notifier_block *nb, unsigned long action, + void *data) +{ + struct clk_hw *hw; + u8 index; + int err; + + if (action == PRE_RATE_CHANGE) + index = P_GPLL0; + else if (action == POST_RATE_CHANGE || action == ABORT_RATE_CHANGE) + index = P_APSS_PLL_EARLY; + else + return NOTIFY_OK; + + hw = &apcs_alias0_clk_src.clkr.hw; + err = clk_rcg2_mux_closest_ops.set_parent(hw, index); + + return notifier_from_errno(err); +} + static int apss_ipq6018_probe(struct platform_device *pdev) { + struct clk_hw *hw = &apcs_alias0_clk_src.clkr.hw; + struct notifier_block *cpu_clk_notifier; struct regmap *regmap; + u32 soc_id; + int ret; + + ret = qcom_smem_get_soc_id(&soc_id); + if (ret) + return ret; regmap = dev_get_regmap(pdev->dev.parent, NULL); if (!regmap) return -ENODEV; - return qcom_cc_really_probe(pdev, &apss_ipq6018_desc, regmap); + ret = qcom_cc_really_probe(pdev, &apss_ipq6018_desc, regmap); + if (ret) + return ret; + + switch (soc_id) { + /* Only below variants of IPQ53xx support scaling */ + case QCOM_ID_IPQ5332: + case QCOM_ID_IPQ5322: + case QCOM_ID_IPQ5300: + cpu_clk_notifier = devm_kzalloc(&pdev->dev, + sizeof(*cpu_clk_notifier), + GFP_KERNEL); + if (!cpu_clk_notifier) + return -ENOMEM; + + cpu_clk_notifier->notifier_call = cpu_clk_notifier_fn; + + ret = devm_clk_notifier_register(&pdev->dev, hw->clk, cpu_clk_notifier); + if (ret) + return ret; + break; + default: + break; + } + + return 0; } static struct platform_driver apss_ipq6018_driver = { -- cgit v1.2.3-59-g8ed1b From 3dcf7b59393812a5fbd83f8cd8d34b94afb4c4d1 Mon Sep 17 00:00:00 2001 From: Robert Marko Date: Sat, 21 Oct 2023 13:55:18 +0200 Subject: clk: qcom: gcc-ipq6018: add QUP6 I2C clock QUP6 I2C clock is listed in the dt bindings but it was never included in the GCC driver. So lets add support for it, it is marked as criticial as it is used by RPM to communicate to the external PMIC over I2C so this clock must not be disabled. Signed-off-by: Robert Marko Reviewed-by: Kathiravan Thirumoorthy Reviewed-by: Konrad Dybcio Link: https://lore.kernel.org/r/20231021115545.229060-1-robimarko@gmail.com Signed-off-by: Bjorn Andersson --- drivers/clk/qcom/gcc-ipq6018.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/drivers/clk/qcom/gcc-ipq6018.c b/drivers/clk/qcom/gcc-ipq6018.c index 6120fbbc5de0..bff878268fa6 100644 --- a/drivers/clk/qcom/gcc-ipq6018.c +++ b/drivers/clk/qcom/gcc-ipq6018.c @@ -2125,6 +2125,26 @@ static struct clk_branch gcc_blsp1_qup5_spi_apps_clk = { }, }; +static struct clk_branch gcc_blsp1_qup6_i2c_apps_clk = { + .halt_reg = 0x07010, + .clkr = { + .enable_reg = 0x07010, + .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, + /* + * RPM uses QUP6 I2C to communicate with the external + * PMIC so it must not be disabled. + */ + .flags = CLK_SET_RATE_PARENT | CLK_IS_CRITICAL, + .ops = &clk_branch2_ops, + }, + }, +}; + static struct clk_branch gcc_blsp1_qup6_spi_apps_clk = { .halt_reg = 0x0700c, .clkr = { @@ -4281,6 +4301,7 @@ static struct clk_regmap *gcc_ipq6018_clks[] = { [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, -- cgit v1.2.3-59-g8ed1b From e641a070137dd959932c7c222e000d9d941167a2 Mon Sep 17 00:00:00 2001 From: Kathiravan Thirumoorthy Date: Thu, 14 Sep 2023 12:29:51 +0530 Subject: clk: qcom: ipq8074: drop the CLK_SET_RATE_PARENT flag from PLL clocks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit GPLL, NSS crypto PLL clock rates are fixed and shouldn't be scaled based on the request from dependent clocks. Doing so will result in the unexpected behaviour. So drop the CLK_SET_RATE_PARENT flag from the PLL clocks. Cc: stable@vger.kernel.org Fixes: b8e7e519625f ("clk: qcom: ipq8074: add remaining PLL’s") Signed-off-by: Kathiravan Thirumoorthy Link: https://lore.kernel.org/r/20230913-gpll_cleanup-v2-1-c8ceb1a37680@quicinc.com Signed-off-by: Bjorn Andersson --- drivers/clk/qcom/gcc-ipq8074.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/clk/qcom/gcc-ipq8074.c b/drivers/clk/qcom/gcc-ipq8074.c index 63ac2ced76bb..b7faf12a511a 100644 --- a/drivers/clk/qcom/gcc-ipq8074.c +++ b/drivers/clk/qcom/gcc-ipq8074.c @@ -75,7 +75,6 @@ static struct clk_fixed_factor gpll0_out_main_div2 = { &gpll0_main.clkr.hw }, .num_parents = 1, .ops = &clk_fixed_factor_ops, - .flags = CLK_SET_RATE_PARENT, }, }; @@ -121,7 +120,6 @@ static struct clk_alpha_pll_postdiv gpll2 = { &gpll2_main.clkr.hw }, .num_parents = 1, .ops = &clk_alpha_pll_postdiv_ro_ops, - .flags = CLK_SET_RATE_PARENT, }, }; @@ -154,7 +152,6 @@ static struct clk_alpha_pll_postdiv gpll4 = { &gpll4_main.clkr.hw }, .num_parents = 1, .ops = &clk_alpha_pll_postdiv_ro_ops, - .flags = CLK_SET_RATE_PARENT, }, }; @@ -188,7 +185,6 @@ static struct clk_alpha_pll_postdiv gpll6 = { &gpll6_main.clkr.hw }, .num_parents = 1, .ops = &clk_alpha_pll_postdiv_ro_ops, - .flags = CLK_SET_RATE_PARENT, }, }; @@ -201,7 +197,6 @@ static struct clk_fixed_factor gpll6_out_main_div2 = { &gpll6_main.clkr.hw }, .num_parents = 1, .ops = &clk_fixed_factor_ops, - .flags = CLK_SET_RATE_PARENT, }, }; @@ -266,7 +261,6 @@ static struct clk_alpha_pll_postdiv nss_crypto_pll = { &nss_crypto_pll_main.clkr.hw }, .num_parents = 1, .ops = &clk_alpha_pll_postdiv_ro_ops, - .flags = CLK_SET_RATE_PARENT, }, }; -- cgit v1.2.3-59-g8ed1b From 99cd4935cb972d0aafb16838bb2aeadbcaf196ce Mon Sep 17 00:00:00 2001 From: Kathiravan Thirumoorthy Date: Thu, 14 Sep 2023 12:29:52 +0530 Subject: clk: qcom: ipq6018: drop the CLK_SET_RATE_PARENT flag from PLL clocks GPLL, NSS crypto PLL clock rates are fixed and shouldn't be scaled based on the request from dependent clocks. Doing so will result in the unexpected behaviour. So drop the CLK_SET_RATE_PARENT flag from the PLL clocks. Cc: stable@vger.kernel.org Fixes: d9db07f088af ("clk: qcom: Add ipq6018 Global Clock Controller support") Signed-off-by: Kathiravan Thirumoorthy Reviewed-by: Konrad Dybcio Link: https://lore.kernel.org/r/20230913-gpll_cleanup-v2-2-c8ceb1a37680@quicinc.com Signed-off-by: Bjorn Andersson --- drivers/clk/qcom/gcc-ipq6018.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/clk/qcom/gcc-ipq6018.c b/drivers/clk/qcom/gcc-ipq6018.c index bff878268fa6..b366912cd648 100644 --- a/drivers/clk/qcom/gcc-ipq6018.c +++ b/drivers/clk/qcom/gcc-ipq6018.c @@ -72,7 +72,6 @@ static struct clk_fixed_factor gpll0_out_main_div2 = { &gpll0_main.clkr.hw }, .num_parents = 1, .ops = &clk_fixed_factor_ops, - .flags = CLK_SET_RATE_PARENT, }, }; @@ -86,7 +85,6 @@ static struct clk_alpha_pll_postdiv gpll0 = { &gpll0_main.clkr.hw }, .num_parents = 1, .ops = &clk_alpha_pll_postdiv_ro_ops, - .flags = CLK_SET_RATE_PARENT, }, }; @@ -161,7 +159,6 @@ static struct clk_alpha_pll_postdiv gpll6 = { &gpll6_main.clkr.hw }, .num_parents = 1, .ops = &clk_alpha_pll_postdiv_ro_ops, - .flags = CLK_SET_RATE_PARENT, }, }; @@ -192,7 +189,6 @@ static struct clk_alpha_pll_postdiv gpll4 = { &gpll4_main.clkr.hw }, .num_parents = 1, .ops = &clk_alpha_pll_postdiv_ro_ops, - .flags = CLK_SET_RATE_PARENT, }, }; @@ -243,7 +239,6 @@ static struct clk_alpha_pll_postdiv gpll2 = { &gpll2_main.clkr.hw }, .num_parents = 1, .ops = &clk_alpha_pll_postdiv_ro_ops, - .flags = CLK_SET_RATE_PARENT, }, }; @@ -274,7 +269,6 @@ static struct clk_alpha_pll_postdiv nss_crypto_pll = { &nss_crypto_pll_main.clkr.hw }, .num_parents = 1, .ops = &clk_alpha_pll_postdiv_ro_ops, - .flags = CLK_SET_RATE_PARENT, }, }; -- cgit v1.2.3-59-g8ed1b From 01a5e4c6731ab6b4b74822661d296f8893fc1230 Mon Sep 17 00:00:00 2001 From: Kathiravan Thirumoorthy Date: Thu, 14 Sep 2023 12:29:53 +0530 Subject: clk: qcom: ipq5018: drop the CLK_SET_RATE_PARENT flag from GPLL clocks GPLL clock rates are fixed and shouldn't be scaled based on the request from dependent clocks. Doing so will result in the unexpected behaviour. So drop the CLK_SET_RATE_PARENT flag from the GPLL clocks. ---- Changes in V2: - New patch Fixes: e3fdbef1bab8 ("clk: qcom: Add Global Clock controller (GCC) driver for IPQ5018") Signed-off-by: Kathiravan Thirumoorthy Reviewed-by: Konrad Dybcio Link: https://lore.kernel.org/r/20230913-gpll_cleanup-v2-3-c8ceb1a37680@quicinc.com Signed-off-by: Bjorn Andersson --- drivers/clk/qcom/gcc-ipq5018.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/clk/qcom/gcc-ipq5018.c b/drivers/clk/qcom/gcc-ipq5018.c index 70f6ade3ac2a..4aba47e8700d 100644 --- a/drivers/clk/qcom/gcc-ipq5018.c +++ b/drivers/clk/qcom/gcc-ipq5018.c @@ -129,7 +129,6 @@ static struct clk_alpha_pll_postdiv gpll0 = { }, .num_parents = 1, .ops = &clk_alpha_pll_postdiv_ro_ops, - .flags = CLK_SET_RATE_PARENT, }, }; @@ -144,7 +143,6 @@ static struct clk_alpha_pll_postdiv gpll2 = { }, .num_parents = 1, .ops = &clk_alpha_pll_postdiv_ro_ops, - .flags = CLK_SET_RATE_PARENT, }, }; @@ -159,7 +157,6 @@ static struct clk_alpha_pll_postdiv gpll4 = { }, .num_parents = 1, .ops = &clk_alpha_pll_postdiv_ro_ops, - .flags = CLK_SET_RATE_PARENT, }, }; -- cgit v1.2.3-59-g8ed1b From 99a8f8764b70158a712992640a6be46a8fd79d15 Mon Sep 17 00:00:00 2001 From: Kathiravan Thirumoorthy Date: Thu, 14 Sep 2023 12:29:54 +0530 Subject: clk: qcom: ipq9574: drop the CLK_SET_RATE_PARENT flag from GPLL clocks GPLL clock rates are fixed and shouldn't be scaled based on the request from dependent clocks. Doing so will result in the unexpected behaviour. So drop the CLK_SET_RATE_PARENT flag from the GPLL clocks. ---- Changes in V2: - No changes Fixes: d75b82cff488 ("clk: qcom: Add Global Clock Controller driver for IPQ9574") Signed-off-by: Kathiravan Thirumoorthy Reviewed-by: Konrad Dybcio Link: https://lore.kernel.org/r/20230913-gpll_cleanup-v2-4-c8ceb1a37680@quicinc.com Signed-off-by: Bjorn Andersson --- drivers/clk/qcom/gcc-ipq9574.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/clk/qcom/gcc-ipq9574.c b/drivers/clk/qcom/gcc-ipq9574.c index 8f430367299e..e8190108e1ae 100644 --- a/drivers/clk/qcom/gcc-ipq9574.c +++ b/drivers/clk/qcom/gcc-ipq9574.c @@ -87,7 +87,6 @@ static struct clk_fixed_factor gpll0_out_main_div2 = { &gpll0_main.clkr.hw }, .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, .ops = &clk_fixed_factor_ops, }, }; @@ -102,7 +101,6 @@ static struct clk_alpha_pll_postdiv gpll0 = { &gpll0_main.clkr.hw }, .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, .ops = &clk_alpha_pll_postdiv_ro_ops, }, }; @@ -132,7 +130,6 @@ static struct clk_alpha_pll_postdiv gpll4 = { &gpll4_main.clkr.hw }, .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, .ops = &clk_alpha_pll_postdiv_ro_ops, }, }; @@ -162,7 +159,6 @@ static struct clk_alpha_pll_postdiv gpll2 = { &gpll2_main.clkr.hw }, .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, .ops = &clk_alpha_pll_postdiv_ro_ops, }, }; -- cgit v1.2.3-59-g8ed1b From 5635ef0bd1052420bc659a00be6fd0c60cec5cb9 Mon Sep 17 00:00:00 2001 From: Kathiravan Thirumoorthy Date: Thu, 14 Sep 2023 12:29:55 +0530 Subject: clk: qcom: ipq5332: drop the CLK_SET_RATE_PARENT flag from GPLL clocks GPLL clock rates are fixed and shouldn't be scaled based on the request from dependent clocks. Doing so will result in the unexpected behaviour. So drop the CLK_SET_RATE_PARENT flag from the GPLL clocks. Fixes: 3d89d52970fd ("clk: qcom: add Global Clock controller (GCC) driver for IPQ5332 SoC") Signed-off-by: Kathiravan Thirumoorthy Reviewed-by: Konrad Dybcio Link: https://lore.kernel.org/r/20230913-gpll_cleanup-v2-5-c8ceb1a37680@quicinc.com Signed-off-by: Bjorn Andersson --- drivers/clk/qcom/gcc-ipq5332.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/clk/qcom/gcc-ipq5332.c b/drivers/clk/qcom/gcc-ipq5332.c index b836159fbdef..f98591148a97 100644 --- a/drivers/clk/qcom/gcc-ipq5332.c +++ b/drivers/clk/qcom/gcc-ipq5332.c @@ -112,7 +112,6 @@ static struct clk_alpha_pll_postdiv gpll2 = { &gpll2_main.clkr.hw }, .num_parents = 1, .ops = &clk_alpha_pll_postdiv_ro_ops, - .flags = CLK_SET_RATE_PARENT, }, }; @@ -152,7 +151,6 @@ static struct clk_alpha_pll_postdiv gpll4 = { &gpll4_main.clkr.hw }, .num_parents = 1, .ops = &clk_alpha_pll_postdiv_ro_ops, - .flags = CLK_SET_RATE_PARENT, }, }; -- cgit v1.2.3-59-g8ed1b From e0e6373d653b7707bf042ecf1538884597c5d0da Mon Sep 17 00:00:00 2001 From: Kathiravan Thirumoorthy Date: Thu, 14 Sep 2023 12:29:57 +0530 Subject: clk: qcom: apss-ipq6018: add the GPLL0 clock also as clock provider While the kernel is booting up, APSS PLL will be running at 800MHz with GPLL0 as source. Once the cpufreq driver is available, APSS PLL will be configured and select the rate based on the opp table and the source will be changed to APSS_PLL_EARLY. Without this patch, CPU Freq driver reports that CPU is running at 24MHz instead of the 800MHz. Reviewed-by: Konrad Dybcio Tested-by: Robert Marko Signed-off-by: Kathiravan Thirumoorthy Link: https://lore.kernel.org/r/20230913-gpll_cleanup-v2-7-c8ceb1a37680@quicinc.com Signed-off-by: Bjorn Andersson --- drivers/clk/qcom/apss-ipq6018.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/clk/qcom/apss-ipq6018.c b/drivers/clk/qcom/apss-ipq6018.c index 0783d1aa8efa..e6295b832686 100644 --- a/drivers/clk/qcom/apss-ipq6018.c +++ b/drivers/clk/qcom/apss-ipq6018.c @@ -23,16 +23,19 @@ enum { P_XO, + P_GPLL0, P_APSS_PLL_EARLY, }; static const struct clk_parent_data parents_apcs_alias0_clk_src[] = { { .fw_name = "xo" }, + { .fw_name = "gpll0" }, { .fw_name = "pll" }, }; static const struct parent_map parents_apcs_alias0_clk_src_map[] = { { P_XO, 0 }, + { P_GPLL0, 4 }, { P_APSS_PLL_EARLY, 5 }, }; -- cgit v1.2.3-59-g8ed1b From 98408df6ad1fa14ad352f8d28d68eacdc94ca382 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 23 Oct 2023 12:28:02 +0200 Subject: clk: meson: S4: select CONFIG_COMMON_CLK_MESON_CLKC_UTILS Without this, the newly added drivers fail to link: aarch64-linux-ld: drivers/clk/meson/s4-pll.o: in function `meson_s4_pll_probe': s4-pll.c:(.text+0x13c): undefined reference to `meson_clk_hw_get' aarch64-linux-ld: drivers/clk/meson/s4-peripherals.o: in function `meson_s4_periphs_probe': s4-peripherals.c:(.text+0xb0): undefined reference to `meson_clk_hw_get' Fixes: e787c9c55eda ("clk: meson: S4: add support for Amlogic S4 SoC PLL clock driver") Reviewed-by: Jerome Brunet Reviewed-by: Neil Armstrong Signed-off-by: Arnd Bergmann Link: https://lore.kernel.org/r/20231023102810.4001943-1-arnd@kernel.org [jbrunet: use 12 char for the Fixes as recommended ] Signed-off-by: Jerome Brunet --- drivers/clk/meson/Kconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/clk/meson/Kconfig b/drivers/clk/meson/Kconfig index c5303e4c1604..29ffd14d267b 100644 --- a/drivers/clk/meson/Kconfig +++ b/drivers/clk/meson/Kconfig @@ -149,6 +149,7 @@ config COMMON_CLK_S4_PLL tristate "S4 SoC PLL clock controllers support" depends on ARM64 default y + select COMMON_CLK_MESON_CLKC_UTILS select COMMON_CLK_MESON_MPLL select COMMON_CLK_MESON_PLL select COMMON_CLK_MESON_REGMAP @@ -161,6 +162,7 @@ config COMMON_CLK_S4_PERIPHERALS tristate "S4 SoC peripherals clock controllers support" depends on ARM64 default y + select COMMON_CLK_MESON_CLKC_UTILS select COMMON_CLK_MESON_REGMAP select COMMON_CLK_MESON_DUALDIV select COMMON_CLK_MESON_VID_PLL_DIV -- cgit v1.2.3-59-g8ed1b From ebcae17f87b34f71e8e55512226c4da35a9e3233 Mon Sep 17 00:00:00 2001 From: Biju Das Date: Sat, 9 Sep 2023 16:28:47 +0100 Subject: clk: si521xx: Use i2c_get_match_data() instead of device_get_match_data() The device_get_match_data(), is to get match data for firmware interfaces such as just OF/ACPI. This driver has I2C matching table as well. Use i2c_get_match_data() to get match data for I2C, ACPI and DT-based matching. Signed-off-by: Biju Das Link: https://lore.kernel.org/r/20230909152847.16216-1-biju.das.jz@bp.renesas.com Signed-off-by: Stephen Boyd --- drivers/clk/clk-si521xx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/clk-si521xx.c b/drivers/clk/clk-si521xx.c index 4eaf1b53f06b..14c8741b9ba0 100644 --- a/drivers/clk/clk-si521xx.c +++ b/drivers/clk/clk-si521xx.c @@ -279,7 +279,7 @@ si521xx_of_clk_get(struct of_phandle_args *clkspec, void *data) static int si521xx_probe(struct i2c_client *client) { - const u16 chip_info = (u16)(uintptr_t)device_get_match_data(&client->dev); + const u16 chip_info = (u16)(uintptr_t)i2c_get_match_data(client); const struct clk_parent_data clk_parent_data = { .index = 0 }; struct si521xx *si; unsigned char name[6] = "DIFF0"; -- cgit v1.2.3-59-g8ed1b From b28f95c61965fd31ca15556e7ac65dfc84a15fad Mon Sep 17 00:00:00 2001 From: Biju Das Date: Sat, 9 Sep 2023 16:54:18 +0100 Subject: clk: clk-si544: Simplify probe() and is_valid_frequency() The driver has an OF match table, still, it uses an ID lookup table for retrieving match data. Currently, the driver is working on the assumption that an I2C device registered via OF will always match a legacy I2C device ID. The correct approach is to have an OF device ID table using i2c_get_match_data() if the devices are registered via OF/ID. Unify the OF/ID table by using max_freq as match data instead of enum si544_speed_grade and replace the ID lookup table for the match data by i2c_get_match_data(). This allows to simplify both probe() and is_valid_frequency(). Drop enum si544_speed_grade as there is no user. While at it, remove the trailing comma in the terminator entry for the OF table making code robust against (theoretical) misrebases or other similar things where the new entry goes _after_ the termination without the compiler noticing. Signed-off-by: Biju Das Link: https://lore.kernel.org/r/20230909155418.24426-1-biju.das.jz@bp.renesas.com Signed-off-by: Stephen Boyd --- drivers/clk/clk-si544.c | 51 +++++++++++++++---------------------------------- 1 file changed, 15 insertions(+), 36 deletions(-) diff --git a/drivers/clk/clk-si544.c b/drivers/clk/clk-si544.c index 22925968aa35..4132db706144 100644 --- a/drivers/clk/clk-si544.c +++ b/drivers/clk/clk-si544.c @@ -56,17 +56,11 @@ #define DELTA_M_FRAC_NUM 19 #define DELTA_M_FRAC_DEN 20000 -enum si544_speed_grade { - si544a, - si544b, - si544c, -}; - struct clk_si544 { struct clk_hw hw; struct regmap *regmap; struct i2c_client *i2c_client; - enum si544_speed_grade speed_grade; + unsigned long max_freq; }; #define to_clk_si544(_hw) container_of(_hw, struct clk_si544, hw) @@ -196,24 +190,10 @@ static int si544_set_muldiv(struct clk_si544 *data, static bool is_valid_frequency(const struct clk_si544 *data, unsigned long frequency) { - unsigned long max_freq = 0; - if (frequency < SI544_MIN_FREQ) return false; - switch (data->speed_grade) { - case si544a: - max_freq = 1500000000; - break; - case si544b: - max_freq = 800000000; - break; - case si544c: - max_freq = 350000000; - break; - } - - return frequency <= max_freq; + return frequency <= data->max_freq; } /* Calculate divider settings for a given frequency */ @@ -451,19 +431,10 @@ static const struct regmap_config si544_regmap_config = { .volatile_reg = si544_regmap_is_volatile, }; -static const struct i2c_device_id si544_id[] = { - { "si544a", si544a }, - { "si544b", si544b }, - { "si544c", si544c }, - { } -}; -MODULE_DEVICE_TABLE(i2c, si544_id); - static int si544_probe(struct i2c_client *client) { struct clk_si544 *data; struct clk_init_data init; - const struct i2c_device_id *id = i2c_match_id(si544_id, client); int err; data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL); @@ -475,7 +446,7 @@ static int si544_probe(struct i2c_client *client) init.num_parents = 0; data->hw.init = &init; data->i2c_client = client; - data->speed_grade = id->driver_data; + data->max_freq = (uintptr_t)i2c_get_match_data(client); if (of_property_read_string(client->dev.of_node, "clock-output-names", &init.name)) @@ -507,11 +478,19 @@ static int si544_probe(struct i2c_client *client) return 0; } +static const struct i2c_device_id si544_id[] = { + { "si544a", 1500000000 }, + { "si544b", 800000000 }, + { "si544c", 350000000 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, si544_id); + static const struct of_device_id clk_si544_of_match[] = { - { .compatible = "silabs,si544a" }, - { .compatible = "silabs,si544b" }, - { .compatible = "silabs,si544c" }, - { }, + { .compatible = "silabs,si544a", .data = (void *)1500000000 }, + { .compatible = "silabs,si544b", .data = (void *)800000000 }, + { .compatible = "silabs,si544c", .data = (void *)350000000 }, + { } }; MODULE_DEVICE_TABLE(of, clk_si544_of_match); -- cgit v1.2.3-59-g8ed1b From 38a929ab128d7f0ac61f7cb506e6687d145b9eba Mon Sep 17 00:00:00 2001 From: Biju Das Date: Sat, 9 Sep 2023 17:02:18 +0100 Subject: clk: rs9: Use i2c_get_match_data() instead of device_get_match_data() The device_get_match_data(), is to get match data for firmware interfaces such as just OF/ACPI. This driver has I2C matching table as well. Use i2c_get_match_data() to get match data for I2C, ACPI and DT-based matching. Signed-off-by: Biju Das Link: https://lore.kernel.org/r/20230909160218.33078-1-biju.das.jz@bp.renesas.com Signed-off-by: Stephen Boyd --- drivers/clk/clk-renesas-pcie.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/clk-renesas-pcie.c b/drivers/clk/clk-renesas-pcie.c index 7d7b2cb75318..380245f635d6 100644 --- a/drivers/clk/clk-renesas-pcie.c +++ b/drivers/clk/clk-renesas-pcie.c @@ -298,7 +298,7 @@ static int rs9_probe(struct i2c_client *client) i2c_set_clientdata(client, rs9); rs9->client = client; - rs9->chip_info = device_get_match_data(&client->dev); + rs9->chip_info = i2c_get_match_data(client); if (!rs9->chip_info) return -EINVAL; -- cgit v1.2.3-59-g8ed1b From f234f028727f8634973f8a9ef2ec933eb0eade5b Mon Sep 17 00:00:00 2001 From: Biju Das Date: Sat, 9 Sep 2023 17:20:47 +0100 Subject: clk: si5351: Simplify probe The driver has an OF match table, still, it uses an ID lookup table for retrieving match data. Currently, the driver is working on the assumption that an I2C device registered via OF will always match a legacy I2C device ID. The correct approach is to have an OF device ID table using i2c_get_match_data() if the devices are registered via OF/ID. Simplify probe() by replacing ID lookup table for retrieving match data with i2c_get_match_data(). Signed-off-by: Biju Das Link: https://lore.kernel.org/r/20230909162047.41845-1-biju.das.jz@bp.renesas.com Signed-off-by: Stephen Boyd --- drivers/clk/clk-si5351.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/clk/clk-si5351.c b/drivers/clk/clk-si5351.c index 00fb9b09e030..afe12d1a9ddc 100644 --- a/drivers/clk/clk-si5351.c +++ b/drivers/clk/clk-si5351.c @@ -1385,8 +1385,7 @@ MODULE_DEVICE_TABLE(i2c, si5351_i2c_ids); static int si5351_i2c_probe(struct i2c_client *client) { - const struct i2c_device_id *id = i2c_match_id(si5351_i2c_ids, client); - enum si5351_variant variant = (enum si5351_variant)id->driver_data; + enum si5351_variant variant; struct si5351_platform_data *pdata; struct si5351_driver_data *drvdata; struct clk_init_data init; @@ -1394,6 +1393,7 @@ static int si5351_i2c_probe(struct i2c_client *client) u8 num_parents, num_clocks; int ret, n; + variant = (enum si5351_variant)(uintptr_t)i2c_get_match_data(client); ret = si5351_dt_parse(client, variant); if (ret) return ret; -- cgit v1.2.3-59-g8ed1b From 15f5e2e4225a94fe76302e87ecdf95e56e571382 Mon Sep 17 00:00:00 2001 From: Biju Das Date: Sat, 9 Sep 2023 17:47:38 +0100 Subject: clk: si570: Simplify probe The driver has an OF match table, still, it uses an ID lookup table for retrieving match data. Currently, the driver is working on the assumption that an I2C device registered via OF will always match a legacy I2C device ID. The correct approach is to have an OF device ID table using i2c_get_match_data() if the devices are registered via OF/ID. Unify the OF/ID table by adding struct clk_si570_info as match data instead of clk_si570_variant and replace the ID lookup table for the match data by i2c_get_match_data(). This allows to simplify probe(). Drop enum clk_si570_variant as there is no user. While at it, remove the trailing comma in the terminator entry for the OF table making code robust against (theoretical) misrebases or other similar things where the new entry goes _after_ the termination without the compiler noticing. Signed-off-by: Biju Das Link: https://lore.kernel.org/r/20230909164738.47708-1-biju.das.jz@bp.renesas.com Signed-off-by: Stephen Boyd --- drivers/clk/clk-si570.c | 67 ++++++++++++++++++++++++++++--------------------- 1 file changed, 38 insertions(+), 29 deletions(-) diff --git a/drivers/clk/clk-si570.c b/drivers/clk/clk-si570.c index de0212fb5f87..ad053a922a42 100644 --- a/drivers/clk/clk-si570.c +++ b/drivers/clk/clk-si570.c @@ -49,12 +49,22 @@ #define SI570_FREEZE_DCO (1 << 4) +/** + * struct clk_si570_info: + * @max_freq: Maximum frequency for this device + * @has_temperature_stability: Device support temperature stability + */ +struct clk_si570_info { + u64 max_freq; + bool has_temperature_stability; +}; + /** * struct clk_si570: * @hw: Clock hw struct * @regmap: Device's regmap * @div_offset: Rgister offset for dividers - * @max_freq: Maximum frequency for this device + * @info: Device info * @fxtal: Factory xtal frequency * @n1: Clock divider N1 * @hs_div: Clock divider HSDIV @@ -66,7 +76,7 @@ struct clk_si570 { struct clk_hw hw; struct regmap *regmap; unsigned int div_offset; - u64 max_freq; + const struct clk_si570_info *info; u64 fxtal; unsigned int n1; unsigned int hs_div; @@ -76,11 +86,6 @@ struct clk_si570 { }; #define to_clk_si570(_hw) container_of(_hw, struct clk_si570, hw) -enum clk_si570_variant { - si57x, - si59x -}; - /** * si570_get_divs() - Read clock dividers from HW * @data: Pointer to struct clk_si570 @@ -341,7 +346,7 @@ static int si570_set_rate(struct clk_hw *hw, unsigned long rate, struct i2c_client *client = data->i2c_client; int err; - if (rate < SI570_MIN_FREQ || rate > data->max_freq) { + if (rate < SI570_MIN_FREQ || rate > data->info->max_freq) { dev_err(&client->dev, "requested frequency %lu Hz is out of range\n", rate); return -EINVAL; @@ -398,24 +403,13 @@ static const struct regmap_config si570_regmap_config = { .volatile_reg = si570_regmap_is_volatile, }; -static const struct i2c_device_id si570_id[] = { - { "si570", si57x }, - { "si571", si57x }, - { "si598", si59x }, - { "si599", si59x }, - { } -}; -MODULE_DEVICE_TABLE(i2c, si570_id); - static int si570_probe(struct i2c_client *client) { struct clk_si570 *data; struct clk_init_data init; - const struct i2c_device_id *id = i2c_match_id(si570_id, client); u32 initial_fout, factory_fout, stability; bool skip_recall; int err; - enum clk_si570_variant variant = id->driver_data; data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL); if (!data) @@ -427,7 +421,8 @@ static int si570_probe(struct i2c_client *client) data->hw.init = &init; data->i2c_client = client; - if (variant == si57x) { + data->info = i2c_get_match_data(client); + if (data->info->has_temperature_stability) { err = of_property_read_u32(client->dev.of_node, "temperature-stability", &stability); if (err) { @@ -438,10 +433,6 @@ static int si570_probe(struct i2c_client *client) /* adjust register offsets for 7ppm devices */ if (stability == 7) data->div_offset = SI570_DIV_OFFSET_7PPM; - - data->max_freq = SI570_MAX_FREQ; - } else { - data->max_freq = SI598_MAX_FREQ; } if (of_property_read_string(client->dev.of_node, "clock-output-names", @@ -496,12 +487,30 @@ static int si570_probe(struct i2c_client *client) return 0; } +static const struct clk_si570_info clk_si570_info = { + .max_freq = SI570_MAX_FREQ, + .has_temperature_stability = true, +}; + +static const struct clk_si570_info clk_si590_info = { + .max_freq = SI598_MAX_FREQ, +}; + +static const struct i2c_device_id si570_id[] = { + { "si570", (kernel_ulong_t)&clk_si570_info }, + { "si571", (kernel_ulong_t)&clk_si570_info }, + { "si598", (kernel_ulong_t)&clk_si590_info }, + { "si599", (kernel_ulong_t)&clk_si590_info }, + { } +}; +MODULE_DEVICE_TABLE(i2c, si570_id); + static const struct of_device_id clk_si570_of_match[] = { - { .compatible = "silabs,si570" }, - { .compatible = "silabs,si571" }, - { .compatible = "silabs,si598" }, - { .compatible = "silabs,si599" }, - { }, + { .compatible = "silabs,si570", .data = &clk_si570_info }, + { .compatible = "silabs,si571", .data = &clk_si570_info }, + { .compatible = "silabs,si598", .data = &clk_si590_info }, + { .compatible = "silabs,si599", .data = &clk_si590_info }, + { } }; MODULE_DEVICE_TABLE(of, clk_si570_of_match); -- cgit v1.2.3-59-g8ed1b From faf6b92ee0091ff7a7bba03a1726a1a97112e9db Mon Sep 17 00:00:00 2001 From: Biju Das Date: Sat, 9 Sep 2023 16:05:16 +0100 Subject: clk: cdce925: Extend match support for OF tables The driver has an OF match table, still, it uses an ID lookup table for retrieving match data. Currently, the driver is working on the assumption that an I2C device registered via OF will always match a legacy I2C device ID. The correct approach is to have an OF device ID table using i2c_get_match_data() if the devices are registered via OF/ID. Unify the OF/ID table by using struct clk_cdce925_chip_info as match data for both these tables and replace the ID lookup table for the match data by i2c_get_match_data(). Split the array clk_cdce925_chip_info_tbl[] as individual variables, and make lines shorter by referring to e.g. &clk_cdce913_info instead of &clk_cdce925_chip_info_tbl[CDCE913]. Drop enum related to chip type as there is no user. While at it, remove the trailing comma in the terminator entry for the OF table making code robust against (theoretical) misrebases or other similar things where the new entry goes _after_ the termination without the compiler noticing. Signed-off-by: Biju Das Link: https://lore.kernel.org/r/20230909150516.10353-1-biju.das.jz@bp.renesas.com Signed-off-by: Stephen Boyd --- drivers/clk/clk-cdce925.c | 65 +++++++++++++++++++++++++---------------------- 1 file changed, 35 insertions(+), 30 deletions(-) diff --git a/drivers/clk/clk-cdce925.c b/drivers/clk/clk-cdce925.c index cdee4958f26d..584c103394bb 100644 --- a/drivers/clk/clk-cdce925.c +++ b/drivers/clk/clk-cdce925.c @@ -25,25 +25,11 @@ * Model this as 2 PLL clocks which are parents to the outputs. */ -enum { - CDCE913, - CDCE925, - CDCE937, - CDCE949, -}; - struct clk_cdce925_chip_info { int num_plls; int num_outputs; }; -static const struct clk_cdce925_chip_info clk_cdce925_chip_info_tbl[] = { - [CDCE913] = { .num_plls = 1, .num_outputs = 3 }, - [CDCE925] = { .num_plls = 2, .num_outputs = 5 }, - [CDCE937] = { .num_plls = 3, .num_outputs = 7 }, - [CDCE949] = { .num_plls = 4, .num_outputs = 9 }, -}; - #define MAX_NUMBER_OF_PLLS 4 #define MAX_NUMBER_OF_OUTPUTS 9 @@ -621,20 +607,10 @@ static struct regmap_bus regmap_cdce925_bus = { .read = cdce925_regmap_i2c_read, }; -static const struct i2c_device_id cdce925_id[] = { - { "cdce913", CDCE913 }, - { "cdce925", CDCE925 }, - { "cdce937", CDCE937 }, - { "cdce949", CDCE949 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, cdce925_id); - static int cdce925_probe(struct i2c_client *client) { struct clk_cdce925_chip *data; struct device_node *node = client->dev.of_node; - const struct i2c_device_id *id = i2c_match_id(cdce925_id, client); const char *parent_name; const char *pll_clk_name[MAX_NUMBER_OF_PLLS] = {NULL,}; struct clk_init_data init; @@ -665,7 +641,7 @@ static int cdce925_probe(struct i2c_client *client) return -ENOMEM; data->i2c_client = client; - data->chip_info = &clk_cdce925_chip_info_tbl[id->driver_data]; + data->chip_info = i2c_get_match_data(client); config.max_register = CDCE925_OFFSET_PLL + data->chip_info->num_plls * 0x10 - 1; data->regmap = devm_regmap_init(&client->dev, ®map_cdce925_bus, @@ -822,12 +798,41 @@ error: return err; } +static const struct clk_cdce925_chip_info clk_cdce913_info = { + .num_plls = 1, + .num_outputs = 3, +}; + +static const struct clk_cdce925_chip_info clk_cdce925_info = { + .num_plls = 2, + .num_outputs = 5, +}; + +static const struct clk_cdce925_chip_info clk_cdce937_info = { + .num_plls = 3, + .num_outputs = 7, +}; + +static const struct clk_cdce925_chip_info clk_cdce949_info = { + .num_plls = 4, + .num_outputs = 9, +}; + +static const struct i2c_device_id cdce925_id[] = { + { "cdce913", (kernel_ulong_t)&clk_cdce913_info }, + { "cdce925", (kernel_ulong_t)&clk_cdce925_info }, + { "cdce937", (kernel_ulong_t)&clk_cdce937_info }, + { "cdce949", (kernel_ulong_t)&clk_cdce949_info }, + { } +}; +MODULE_DEVICE_TABLE(i2c, cdce925_id); + static const struct of_device_id clk_cdce925_of_match[] = { - { .compatible = "ti,cdce913" }, - { .compatible = "ti,cdce925" }, - { .compatible = "ti,cdce937" }, - { .compatible = "ti,cdce949" }, - { }, + { .compatible = "ti,cdce913", .data = &clk_cdce913_info }, + { .compatible = "ti,cdce925", .data = &clk_cdce925_info }, + { .compatible = "ti,cdce937", .data = &clk_cdce937_info }, + { .compatible = "ti,cdce949", .data = &clk_cdce949_info }, + { } }; MODULE_DEVICE_TABLE(of, clk_cdce925_of_match); -- cgit v1.2.3-59-g8ed1b From 5ad1e217a2b23aa046b241183bd9452d259d70d0 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Mon, 16 Oct 2023 16:05:27 -0600 Subject: clk: visconti: Fix undefined behavior bug in struct visconti_pll_provider `struct clk_hw_onecell_data` is a flexible structure, which means that it contains flexible-array member at the bottom, in this case array `hws`: include/linux/clk-provider.h: 1380 struct clk_hw_onecell_data { 1381 unsigned int num; 1382 struct clk_hw *hws[] __counted_by(num); 1383 }; This could potentially lead to an overwrite of the objects following `clk_data` in `struct visconti_pll_provider`, in this case `struct device_node *node;`, at run-time: drivers/clk/visconti/pll.h: 16 struct visconti_pll_provider { 17 void __iomem *reg_base; 18 struct clk_hw_onecell_data clk_data; 19 struct device_node *node; 20 }; Notice that a total of 56 bytes are allocated for flexible-array `hws` at line 328. See below: include/dt-bindings/clock/toshiba,tmpv770x.h: 14 #define TMPV770X_NR_PLL 7 drivers/clk/visconti/pll-tmpv770x.c: 69 ctx = visconti_init_pll(np, reg_base, TMPV770X_NR_PLL); drivers/clk/visconti/pll.c: 321 struct visconti_pll_provider * __init visconti_init_pll(struct device_node *np, 322 void __iomem *base, 323 unsigned long nr_plls) 324 { 325 struct visconti_pll_provider *ctx; ... 328 ctx = kzalloc(struct_size(ctx, clk_data.hws, nr_plls), GFP_KERNEL); `struct_size(ctx, clk_data.hws, nr_plls)` above translates to sizeof(struct visconti_pll_provider) + sizeof(struct clk_hw *) * 7 == 24 + 8 * 7 == 24 + 56 ^^^^ | allocated bytes for flex array `hws` $ pahole -C visconti_pll_provider drivers/clk/visconti/pll.o struct visconti_pll_provider { void * reg_base; /* 0 8 */ struct clk_hw_onecell_data clk_data; /* 8 8 */ struct device_node * node; /* 16 8 */ /* size: 24, cachelines: 1, members: 3 */ /* last cacheline: 24 bytes */ }; And then, after the allocation, some data is written into all members of `struct visconti_pll_provider`: 332 for (i = 0; i < nr_plls; ++i) 333 ctx->clk_data.hws[i] = ERR_PTR(-ENOENT); 334 335 ctx->node = np; 336 ctx->reg_base = base; 337 ctx->clk_data.num = nr_plls; Fix all these by placing the declaration of object `clk_data` at the end of `struct visconti_pll_provider`. Also, add a comment to make it clear that this object must always be last in the structure, and prevent this bug from being introduced again in the future. -Wflex-array-member-not-at-end is coming in GCC-14, and we are getting ready to enable it globally. Fixes: b4cbe606dc36 ("clk: visconti: Add support common clock driver and reset driver") Cc: stable@vger.kernel.org Reviewed-by: Kees Cook Acked-by: Nobuhiro Iwamatsu Signed-off-by: Gustavo A. R. Silva Link: https://lore.kernel.org/r/57a831d94ee2b3889b11525d4ad500356f89576f.1697492890.git.gustavoars@kernel.org Signed-off-by: Stephen Boyd --- drivers/clk/visconti/pll.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/clk/visconti/pll.h b/drivers/clk/visconti/pll.h index 01d07f1bf01b..c4bd40676da4 100644 --- a/drivers/clk/visconti/pll.h +++ b/drivers/clk/visconti/pll.h @@ -15,8 +15,10 @@ struct visconti_pll_provider { void __iomem *reg_base; - struct clk_hw_onecell_data clk_data; struct device_node *node; + + /* Must be last */ + struct clk_hw_onecell_data clk_data; }; #define VISCONTI_PLL_RATE(_rate, _dacen, _dsmen, \ -- cgit v1.2.3-59-g8ed1b From 397d887c1601a71e8a8abdb6beea67d58f0472d3 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Mon, 16 Oct 2023 16:06:16 -0600 Subject: clk: visconti: Add bounds-checking coverage for struct visconti_pll_provider In order to gain the bounds-checking coverage that __counted_by provides to flexible-array members at run-time via CONFIG_UBSAN_BOUNDS (for array indexing) and CONFIG_FORTIFY_SOURCE (for strcpy/memcpy-family functions), we must make sure that the counter member, in this particular case `num`, is updated before the first access to the flex-array member, in this particular case array `hws`. See below: commit f316cdff8d67 ("clk: Annotate struct clk_hw_onecell_data with __counted_by") introduced `__counted_by` for `struct clk_hw_onecell_data` together with changes to relocate some of assignments of counter `num` before `hws` is accessed: include/linux/clk-provider.h: 1380 struct clk_hw_onecell_data { 1381 unsigned int num; 1382 struct clk_hw *hws[] __counted_by(num); 1383 }; However, this structure is used as a member in other structs, in this case in `struct visconti_pll_provider`: drivers/clk/visconti/pll.h: 16 struct visconti_pll_provider { 17 void __iomem *reg_base; 18 struct device_node *node; 19 20 /* Must be last */ 21 struct clk_hw_onecell_data clk_data; 22 }; Hence, we need to move the assignments to `ctx->clk_data.num` after allocation for `struct visconti_pll_provider` and before accessing the flexible array `ctx->clk_data.hws`. And, as assignments for all members in `struct visconti_pll_provider` are originally adjacent to each other, relocate all assignments together, so we don't split up `ctx->clk_data.hws = nr_plls` from the rest. :) Reviewed-by: Kees Cook Acked-by: Nobuhiro Iwamatsu Signed-off-by: Gustavo A. R. Silva Link: https://lore.kernel.org/r/e3189f3e40e8723b6d794fb2260e2e9ab6b960bd.1697492890.git.gustavoars@kernel.org Signed-off-by: Stephen Boyd --- drivers/clk/visconti/pll.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/clk/visconti/pll.c b/drivers/clk/visconti/pll.c index 1f3234f22667..e9cd80e085dc 100644 --- a/drivers/clk/visconti/pll.c +++ b/drivers/clk/visconti/pll.c @@ -329,12 +329,12 @@ struct visconti_pll_provider * __init visconti_init_pll(struct device_node *np, if (!ctx) return ERR_PTR(-ENOMEM); - for (i = 0; i < nr_plls; ++i) - ctx->clk_data.hws[i] = ERR_PTR(-ENOENT); - ctx->node = np; ctx->reg_base = base; ctx->clk_data.num = nr_plls; + for (i = 0; i < nr_plls; ++i) + ctx->clk_data.hws[i] = ERR_PTR(-ENOENT); + return ctx; } -- cgit v1.2.3-59-g8ed1b From 409c39ec92a35e3708f5b5798c78eae78512cd71 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Fri, 6 Oct 2023 16:39:58 -0500 Subject: clk: Use device_get_match_data() Use preferred device_get_match_data() instead of of_match_device() to get the driver match data. With this, adjust the includes to explicitly include the correct headers. Signed-off-by: Rob Herring Link: https://lore.kernel.org/r/20231006213959.334439-1-robh@kernel.org Reviewed-by: Dmitry Baryshkov #msm part Acked-by: Krzysztof Kozlowski # Samsung Acked-by: David Lechner Acked-by: Chanwoo Choi Acked-by: Charles Keepax Reviewed-by: Bjorn Andersson Signed-off-by: Stephen Boyd --- drivers/clk/clk-lochnagar.c | 9 ++------- drivers/clk/davinci/da8xx-cfgchip.c | 8 +++----- drivers/clk/davinci/pll.c | 10 +++------- drivers/clk/davinci/psc.c | 10 +++------- drivers/clk/qcom/gcc-msm8960.c | 13 +++++-------- drivers/clk/qcom/gcc-msm8974.c | 10 +++------- drivers/clk/qcom/kpss-xcc.c | 9 ++------- drivers/clk/qcom/krait-cc.c | 14 +++++--------- drivers/clk/qcom/mmcc-msm8960.c | 16 +++++----------- drivers/clk/qcom/mmcc-sdm660.c | 8 ++------ drivers/clk/rockchip/clk-rk3399.c | 9 ++------- drivers/clk/samsung/clk-exynos-clkout.c | 8 +++----- drivers/clk/ti/adpll.c | 14 ++++---------- 13 files changed, 42 insertions(+), 96 deletions(-) diff --git a/drivers/clk/clk-lochnagar.c b/drivers/clk/clk-lochnagar.c index db468a62c8d7..5561a2c66b69 100644 --- a/drivers/clk/clk-lochnagar.c +++ b/drivers/clk/clk-lochnagar.c @@ -12,8 +12,8 @@ #include #include #include -#include #include +#include #include #include @@ -242,22 +242,17 @@ static int lochnagar_clk_probe(struct platform_device *pdev) }; struct device *dev = &pdev->dev; struct lochnagar_clk_priv *priv; - const struct of_device_id *of_id; struct lochnagar_clk *lclk; struct lochnagar_config *conf; int ret, i; - of_id = of_match_device(lochnagar_of_match, dev); - if (!of_id) - return -EINVAL; - priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; priv->dev = dev; priv->regmap = dev_get_regmap(dev->parent, NULL); - conf = (struct lochnagar_config *)of_id->data; + conf = (struct lochnagar_config *)device_get_match_data(dev); memcpy(priv->lclks, conf->clks, sizeof(priv->lclks)); diff --git a/drivers/clk/davinci/da8xx-cfgchip.c b/drivers/clk/davinci/da8xx-cfgchip.c index e5b2cdfe88ce..ad2d0df43dc6 100644 --- a/drivers/clk/davinci/da8xx-cfgchip.c +++ b/drivers/clk/davinci/da8xx-cfgchip.c @@ -11,10 +11,10 @@ #include #include #include -#include #include #include #include +#include #include #include @@ -744,15 +744,13 @@ static int da8xx_cfgchip_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct da8xx_cfgchip_clk_platform_data *pdata = dev->platform_data; - const struct of_device_id *of_id; da8xx_cfgchip_init clk_init = NULL; struct regmap *regmap = NULL; - of_id = of_match_device(da8xx_cfgchip_of_match, dev); - if (of_id) { + clk_init = device_get_match_data(dev); + if (clk_init) { struct device_node *parent; - clk_init = of_id->data; parent = of_get_parent(dev->of_node); regmap = syscon_node_to_regmap(parent); of_node_put(parent); diff --git a/drivers/clk/davinci/pll.c b/drivers/clk/davinci/pll.c index 87bdf8879045..5bbbb3a66477 100644 --- a/drivers/clk/davinci/pll.c +++ b/drivers/clk/davinci/pll.c @@ -18,11 +18,10 @@ #include #include #include -#include -#include #include #include #include +#include #include #include #include @@ -892,14 +891,11 @@ static int davinci_pll_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct davinci_pll_platform_data *pdata; - const struct of_device_id *of_id; davinci_pll_init pll_init = NULL; void __iomem *base; - of_id = of_match_device(davinci_pll_of_match, dev); - if (of_id) - pll_init = of_id->data; - else if (pdev->id_entry) + pll_init = device_get_match_data(dev); + if (!pll_init && pdev->id_entry) pll_init = (void *)pdev->id_entry->driver_data; if (!pll_init) { diff --git a/drivers/clk/davinci/psc.c b/drivers/clk/davinci/psc.c index cd85d9f158b0..355d1be0b5d8 100644 --- a/drivers/clk/davinci/psc.c +++ b/drivers/clk/davinci/psc.c @@ -18,10 +18,9 @@ #include #include #include -#include -#include #include #include +#include #include #include #include @@ -517,15 +516,12 @@ static const struct platform_device_id davinci_psc_id_table[] = { static int davinci_psc_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; - const struct of_device_id *of_id; const struct davinci_psc_init_data *init_data = NULL; void __iomem *base; int ret; - of_id = of_match_device(davinci_psc_of_match, dev); - if (of_id) - init_data = of_id->data; - else if (pdev->id_entry) + init_data = device_get_match_data(dev); + if (!init_data && pdev->id_entry) init_data = (void *)pdev->id_entry->driver_data; if (!init_data) { diff --git a/drivers/clk/qcom/gcc-msm8960.c b/drivers/clk/qcom/gcc-msm8960.c index dbc7093ab9cc..6236a458e4eb 100644 --- a/drivers/clk/qcom/gcc-msm8960.c +++ b/drivers/clk/qcom/gcc-msm8960.c @@ -7,9 +7,10 @@ #include #include #include +#include #include #include -#include +#include #include #include #include @@ -3716,14 +3717,10 @@ MODULE_DEVICE_TABLE(of, gcc_msm8960_match_table); static int gcc_msm8960_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; - const struct of_device_id *match; struct platform_device *tsens; + const struct qcom_cc_desc *desc = device_get_match_data(dev); int ret; - match = of_match_device(gcc_msm8960_match_table, &pdev->dev); - if (!match) - return -EINVAL; - ret = qcom_cc_register_board_clk(dev, "cxo_board", "cxo", 19200000); if (ret) return ret; @@ -3732,11 +3729,11 @@ static int gcc_msm8960_probe(struct platform_device *pdev) if (ret) return ret; - ret = qcom_cc_probe(pdev, match->data); + ret = qcom_cc_probe(pdev, desc); if (ret) return ret; - if (match->data == &gcc_apq8064_desc) { + if (desc == &gcc_apq8064_desc) { hfpll1.d = &hfpll1_8064_data; hfpll_l2.d = &hfpll_l2_8064_data; } diff --git a/drivers/clk/qcom/gcc-msm8974.c b/drivers/clk/qcom/gcc-msm8974.c index 0231c1efd286..b32e66714951 100644 --- a/drivers/clk/qcom/gcc-msm8974.c +++ b/drivers/clk/qcom/gcc-msm8974.c @@ -7,9 +7,9 @@ #include #include #include +#include #include #include -#include #include #include #include @@ -2875,14 +2875,10 @@ static int gcc_msm8974_probe(struct platform_device *pdev) { int ret; struct device *dev = &pdev->dev; - const struct of_device_id *id; - - id = of_match_device(gcc_msm8974_match_table, dev); - if (!id) - return -ENODEV; + const void *data = device_get_match_data(dev); if (!of_device_is_compatible(dev->of_node, "qcom,gcc-msm8974")) { - if (id->data == &gcc_msm8226_desc) + if (data == &gcc_msm8226_desc) msm8226_clock_override(); else msm8974_pro_clock_override(); diff --git a/drivers/clk/qcom/kpss-xcc.c b/drivers/clk/qcom/kpss-xcc.c index 97358c98c6c9..23b0b11f0007 100644 --- a/drivers/clk/qcom/kpss-xcc.c +++ b/drivers/clk/qcom/kpss-xcc.c @@ -5,10 +5,10 @@ #include #include #include +#include #include #include #include -#include #include #include @@ -32,20 +32,15 @@ MODULE_DEVICE_TABLE(of, kpss_xcc_match_table); static int kpss_xcc_driver_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; - const struct of_device_id *id; void __iomem *base; struct clk_hw *hw; const char *name; - id = of_match_device(kpss_xcc_match_table, dev); - if (!id) - return -ENODEV; - base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(base)) return PTR_ERR(base); - if (id->data) { + if (device_get_match_data(&pdev->dev)) { if (of_property_read_string_index(dev->of_node, "clock-output-names", 0, &name)) diff --git a/drivers/clk/qcom/krait-cc.c b/drivers/clk/qcom/krait-cc.c index 410ae8390f1c..ae325f4e1047 100644 --- a/drivers/clk/qcom/krait-cc.c +++ b/drivers/clk/qcom/krait-cc.c @@ -5,10 +5,10 @@ #include #include #include +#include #include #include #include -#include #include #include #include @@ -347,22 +347,18 @@ MODULE_DEVICE_TABLE(of, krait_cc_match_table); static int krait_cc_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; - const struct of_device_id *id; unsigned long cur_rate, aux_rate; int cpu; struct clk_hw *mux, *l2_pri_mux; struct clk *clk, **clks; - - id = of_match_device(krait_cc_match_table, dev); - if (!id) - return -ENODEV; + bool unique_aux = !!device_get_match_data(dev); /* Rate is 1 because 0 causes problems for __clk_mux_determine_rate */ clk = clk_register_fixed_rate(dev, "qsb", NULL, 0, 1); if (IS_ERR(clk)) return PTR_ERR(clk); - if (!id->data) { + if (!unique_aux) { clk = clk_register_fixed_factor(dev, "acpu_aux", "gpll0_vote", 0, 1, 2); if (IS_ERR(clk)) @@ -375,13 +371,13 @@ static int krait_cc_probe(struct platform_device *pdev) return -ENOMEM; for_each_possible_cpu(cpu) { - mux = krait_add_clks(dev, cpu, id->data); + mux = krait_add_clks(dev, cpu, unique_aux); if (IS_ERR(mux)) return PTR_ERR(mux); clks[cpu] = mux->clk; } - l2_pri_mux = krait_add_clks(dev, -1, id->data); + l2_pri_mux = krait_add_clks(dev, -1, unique_aux); if (IS_ERR(l2_pri_mux)) return PTR_ERR(l2_pri_mux); clks[l2_mux] = l2_pri_mux->clk; diff --git a/drivers/clk/qcom/mmcc-msm8960.c b/drivers/clk/qcom/mmcc-msm8960.c index 6bf908a51f53..50638ab341ec 100644 --- a/drivers/clk/qcom/mmcc-msm8960.c +++ b/drivers/clk/qcom/mmcc-msm8960.c @@ -8,9 +8,9 @@ #include #include #include +#include #include #include -#include #include #include #include @@ -3105,30 +3105,24 @@ MODULE_DEVICE_TABLE(of, mmcc_msm8960_match_table); static int mmcc_msm8960_probe(struct platform_device *pdev) { - const struct of_device_id *match; struct regmap *regmap; - bool is_8064; struct device *dev = &pdev->dev; + const struct qcom_cc_desc *desc = device_get_match_data(dev); - match = of_match_device(mmcc_msm8960_match_table, dev); - if (!match) - return -EINVAL; - - is_8064 = of_device_is_compatible(dev->of_node, "qcom,mmcc-apq8064"); - if (is_8064) { + if (desc == &mmcc_apq8064_desc) { gfx3d_src.freq_tbl = clk_tbl_gfx3d_8064; gfx3d_src.clkr.hw.init = &gfx3d_8064_init; gfx3d_src.s[0].parent_map = mmcc_pxo_pll8_pll2_pll15_map; gfx3d_src.s[1].parent_map = mmcc_pxo_pll8_pll2_pll15_map; } - regmap = qcom_cc_map(pdev, match->data); + regmap = qcom_cc_map(pdev, desc); if (IS_ERR(regmap)) return PTR_ERR(regmap); clk_pll_configure_sr(&pll15, regmap, &pll15_config, false); - return qcom_cc_really_probe(pdev, match->data, regmap); + return qcom_cc_really_probe(pdev, desc, regmap); } static struct platform_driver mmcc_msm8960_driver = { diff --git a/drivers/clk/qcom/mmcc-sdm660.c b/drivers/clk/qcom/mmcc-sdm660.c index bc19a23e13f8..996bd01fb9ac 100644 --- a/drivers/clk/qcom/mmcc-sdm660.c +++ b/drivers/clk/qcom/mmcc-sdm660.c @@ -9,9 +9,9 @@ #include #include #include +#include #include #include -#include #include #include #include @@ -2828,14 +2828,10 @@ static void sdm630_clock_override(void) static int mmcc_660_probe(struct platform_device *pdev) { - const struct of_device_id *id; struct regmap *regmap; bool is_sdm630; - id = of_match_device(mmcc_660_match_table, &pdev->dev); - if (!id) - return -ENODEV; - is_sdm630 = !!(id->data); + is_sdm630 = !!device_get_match_data(&pdev->dev); regmap = qcom_cc_map(pdev, &mmcc_660_desc); if (IS_ERR(regmap)) diff --git a/drivers/clk/rockchip/clk-rk3399.c b/drivers/clk/rockchip/clk-rk3399.c index 9ebd6c451b3d..9316e5c8a0ea 100644 --- a/drivers/clk/rockchip/clk-rk3399.c +++ b/drivers/clk/rockchip/clk-rk3399.c @@ -9,8 +9,8 @@ #include #include #include -#include #include +#include #include #include #include "clk.h" @@ -1634,14 +1634,9 @@ static const struct of_device_id clk_rk3399_match_table[] = { static int __init clk_rk3399_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; - const struct of_device_id *match; const struct clk_rk3399_inits *init_data; - match = of_match_device(clk_rk3399_match_table, &pdev->dev); - if (!match || !match->data) - return -EINVAL; - - init_data = match->data; + init_data = device_get_match_data(&pdev->dev); if (init_data->inits) init_data->inits(np); diff --git a/drivers/clk/samsung/clk-exynos-clkout.c b/drivers/clk/samsung/clk-exynos-clkout.c index 72b6cf83aff4..3484e6cc80ad 100644 --- a/drivers/clk/samsung/clk-exynos-clkout.c +++ b/drivers/clk/samsung/clk-exynos-clkout.c @@ -13,9 +13,9 @@ #include #include #include -#include #include #include +#include #define EXYNOS_CLKOUT_NR_CLKS 1 #define EXYNOS_CLKOUT_PARENTS 32 @@ -84,19 +84,17 @@ MODULE_DEVICE_TABLE(of, exynos_clkout_ids); static int exynos_clkout_match_parent_dev(struct device *dev, u32 *mux_mask) { const struct exynos_clkout_variant *variant; - const struct of_device_id *match; if (!dev->parent) { dev_err(dev, "not instantiated from MFD\n"); return -EINVAL; } - match = of_match_device(exynos_clkout_ids, dev->parent); - if (!match) { + variant = device_get_match_data(dev->parent); + if (!variant) { dev_err(dev, "cannot match parent device\n"); return -EINVAL; } - variant = match->data; *mux_mask = variant->mux_mask; diff --git a/drivers/clk/ti/adpll.c b/drivers/clk/ti/adpll.c index ff42ea75cb43..6121020b4b38 100644 --- a/drivers/clk/ti/adpll.c +++ b/drivers/clk/ti/adpll.c @@ -8,7 +8,9 @@ #include #include #include -#include +#include +#include +#include #include #define ADPLL_PLLSS_MMR_LOCK_OFFSET 0x00 /* Managed by MPPULL */ @@ -860,24 +862,16 @@ static int ti_adpll_probe(struct platform_device *pdev) { struct device_node *node = pdev->dev.of_node; struct device *dev = &pdev->dev; - const struct of_device_id *match; - const struct ti_adpll_platform_data *pdata; struct ti_adpll_data *d; struct resource *res; int err; - match = of_match_device(ti_adpll_match, dev); - if (match) - pdata = match->data; - else - return -ENODEV; - d = devm_kzalloc(dev, sizeof(*d), GFP_KERNEL); if (!d) return -ENOMEM; d->dev = dev; d->np = node; - d->c = pdata; + d->c = device_get_match_data(dev); dev_set_drvdata(d->dev, d); spin_lock_init(&d->lock); -- cgit v1.2.3-59-g8ed1b From dcce5cc7826e9c6b3a2443e5e6b7f8d02a103c35 Mon Sep 17 00:00:00 2001 From: Vishal Badole Date: Sun, 27 Nov 2022 22:53:19 +0530 Subject: clk: Show active consumers of clocks in debugfs This feature lists the clock consumer's name and respective connection id. Using this feature user can easily check that which user has acquired and enabled a particular clock. Usage: >> cat /sys/kernel/debug/clk/clk_summary enable prepare protect duty hardware Connection clock count count count rate accuracy phase cycle enable consumer Id ------------------------------------------------------------------------------------------------------------------------------ clk_mcasp0_fixed 0 0 0 24576000 0 0 50000 Y deviceless of_clk_get_from_provider deviceless no_connection_id clk_mcasp0 0 0 0 24576000 0 0 50000 N simple-audio-card,cpu no_connection_id deviceless no_connection_id Co-developed-by: Chinmoy Ghosh Signed-off-by: Chinmoy Ghosh Co-developed-by: Mintu Patel Signed-off-by: Mintu Patel Co-developed-by: Vimal Kumar Signed-off-by: Vimal Kumar Signed-off-by: Vishal Badole Link: https://lore.kernel.org/r/1669569799-8526-1-git-send-email-badolevishal1116@gmail.com Signed-off-by: Stephen Boyd --- drivers/clk/clk.c | 34 ++++++++++++++++++++++++---------- 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index c249f9791ae8..0544615d2a1d 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -3188,28 +3188,41 @@ static void clk_summary_show_one(struct seq_file *s, struct clk_core *c, int level) { int phase; + struct clk *clk_user; + int multi_node = 0; - seq_printf(s, "%*s%-*s %7d %8d %8d %11lu %10lu ", + seq_printf(s, "%*s%-*s %-7d %-8d %-8d %-11lu %-10lu ", level * 3 + 1, "", - 30 - level * 3, c->name, + 35 - level * 3, c->name, c->enable_count, c->prepare_count, c->protect_count, clk_core_get_rate_recalc(c), clk_core_get_accuracy_recalc(c)); phase = clk_core_get_phase(c); if (phase >= 0) - seq_printf(s, "%5d", phase); + seq_printf(s, "%-5d", phase); else seq_puts(s, "-----"); - seq_printf(s, " %6d", clk_core_get_scaled_duty_cycle(c, 100000)); + seq_printf(s, " %-6d", clk_core_get_scaled_duty_cycle(c, 100000)); if (c->ops->is_enabled) - seq_printf(s, " %9c\n", clk_core_is_enabled(c) ? 'Y' : 'N'); + seq_printf(s, " %5c ", clk_core_is_enabled(c) ? 'Y' : 'N'); else if (!c->ops->enable) - seq_printf(s, " %9c\n", 'Y'); + seq_printf(s, " %5c ", 'Y'); else - seq_printf(s, " %9c\n", '?'); + seq_printf(s, " %5c ", '?'); + + hlist_for_each_entry(clk_user, &c->clks, clks_node) { + seq_printf(s, "%*s%-*s %-25s\n", + level * 3 + 2 + 105 * multi_node, "", + 30, + clk_user->dev_id ? clk_user->dev_id : "deviceless", + clk_user->con_id ? clk_user->con_id : "no_connection_id"); + + multi_node = 1; + } + } static void clk_summary_show_subtree(struct seq_file *s, struct clk_core *c, @@ -3230,9 +3243,10 @@ static int clk_summary_show(struct seq_file *s, void *data) struct clk_core *c; struct hlist_head **lists = s->private; - seq_puts(s, " enable prepare protect duty hardware\n"); - seq_puts(s, " clock count count count rate accuracy phase cycle enable\n"); - seq_puts(s, "-------------------------------------------------------------------------------------------------------\n"); + seq_puts(s, " enable prepare protect duty hardware connection\n"); + seq_puts(s, " clock count count count rate accuracy phase cycle enable consumer id\n"); + seq_puts(s, "---------------------------------------------------------------------------------------------------------------------------------------------\n"); + clk_prepare_lock(); -- cgit v1.2.3-59-g8ed1b From e43d31915cc4fca4e04daeca6c0ff25cc57cf956 Mon Sep 17 00:00:00 2001 From: John Keeping Date: Thu, 20 Apr 2023 11:38:04 +0100 Subject: clk: Allow phase adjustment from debugfs For testing it may be useful to manually adjust a clock's phase. Add support for writing to the existing clk_phase debugfs file, with the written value clamped to [0, 360) to match the behaviour of the clk_set_phase() function. This is a dangerous feature, so use the existing define CLOCK_ALLOW_WRITE_DEBUGFS to allow it only if the source is modified. Signed-off-by: John Keeping Link: https://lore.kernel.org/r/20230420103805.125246-1-john@metanate.com Signed-off-by: Stephen Boyd --- drivers/clk/clk.c | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 0544615d2a1d..2f0885e4f6bf 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -3343,6 +3343,21 @@ static int clk_rate_set(void *data, u64 val) #define clk_rate_mode 0644 +static int clk_phase_set(void *data, u64 val) +{ + struct clk_core *core = data; + int degrees = do_div(val, 360); + int ret; + + clk_prepare_lock(); + ret = clk_core_set_phase_nolock(core, degrees); + clk_prepare_unlock(); + + return ret; +} + +#define clk_phase_mode 0644 + static int clk_prepare_enable_set(void *data, u64 val) { struct clk_core *core = data; @@ -3370,6 +3385,9 @@ DEFINE_DEBUGFS_ATTRIBUTE(clk_prepare_enable_fops, clk_prepare_enable_get, #else #define clk_rate_set NULL #define clk_rate_mode 0444 + +#define clk_phase_set NULL +#define clk_phase_mode 0644 #endif static int clk_rate_get(void *data, u64 *val) @@ -3385,6 +3403,16 @@ static int clk_rate_get(void *data, u64 *val) DEFINE_DEBUGFS_ATTRIBUTE(clk_rate_fops, clk_rate_get, clk_rate_set, "%llu\n"); +static int clk_phase_get(void *data, u64 *val) +{ + struct clk_core *core = data; + + *val = core->phase; + return 0; +} + +DEFINE_DEBUGFS_ATTRIBUTE(clk_phase_fops, clk_phase_get, clk_phase_set, "%llu\n"); + static const struct { unsigned long flag; const char *name; @@ -3575,7 +3603,8 @@ static void clk_debug_create_one(struct clk_core *core, struct dentry *pdentry) debugfs_create_file("clk_min_rate", 0444, root, core, &clk_min_rate_fops); debugfs_create_file("clk_max_rate", 0444, root, core, &clk_max_rate_fops); debugfs_create_ulong("clk_accuracy", 0444, root, &core->accuracy); - debugfs_create_u32("clk_phase", 0444, root, &core->phase); + debugfs_create_file("clk_phase", clk_phase_mode, root, core, + &clk_phase_fops); debugfs_create_file("clk_flags", 0444, root, core, &clk_flags_fops); debugfs_create_u32("clk_prepare_count", 0444, root, &core->prepare_count); debugfs_create_u32("clk_enable_count", 0444, root, &core->enable_count); -- cgit v1.2.3-59-g8ed1b From 48a8748fd0d18b07741f311cd6929982490c5903 Mon Sep 17 00:00:00 2001 From: Zhifeng Tang Date: Wed, 13 Sep 2023 19:52:11 +0800 Subject: clk: sprd: Composite driver support offset config The composite interface support the offset configuration, which is used to support mux and div in different registers. Because some sprd projects, the divider has different addresses from mux for one composite clk. Signed-off-by: Zhifeng Tang Reviewed-by: Chunyan Zhang Link: https://lore.kernel.org/r/20230913115211.11512-1-zhifeng.tang@unisoc.com Signed-off-by: Stephen Boyd --- drivers/clk/sprd/composite.h | 36 +++++++++++++++++++++++++++--------- drivers/clk/sprd/div.c | 6 +++--- drivers/clk/sprd/div.h | 17 ++++++++++++----- 3 files changed, 42 insertions(+), 17 deletions(-) diff --git a/drivers/clk/sprd/composite.h b/drivers/clk/sprd/composite.h index adbabbe596b7..15cec97d2aa7 100644 --- a/drivers/clk/sprd/composite.h +++ b/drivers/clk/sprd/composite.h @@ -19,24 +19,24 @@ struct sprd_comp { }; #define SPRD_COMP_CLK_HW_INIT_FN(_struct, _name, _parent, _reg, _table, \ - _mshift, _mwidth, _dshift, _dwidth, \ - _flags, _fn) \ + _mshift, _mwidth, _doffset, _dshift, \ + _dwidth, _flags, _fn) \ struct sprd_comp _struct = { \ .mux = _SPRD_MUX_CLK(_mshift, _mwidth, _table), \ - .div = _SPRD_DIV_CLK(_dshift, _dwidth), \ + .div = _SPRD_DIV_CLK(_doffset, _dshift, _dwidth), \ .common = { \ .regmap = NULL, \ .reg = _reg, \ .hw.init = _fn(_name, _parent, \ &sprd_comp_ops, _flags), \ - } \ + } \ } #define SPRD_COMP_CLK_TABLE(_struct, _name, _parent, _reg, _table, \ _mshift, _mwidth, _dshift, _dwidth, _flags) \ SPRD_COMP_CLK_HW_INIT_FN(_struct, _name, _parent, _reg, _table, \ - _mshift, _mwidth, _dshift, _dwidth, \ - _flags, CLK_HW_INIT_PARENTS) + _mshift, _mwidth, 0x0, _dshift, \ + _dwidth, _flags, CLK_HW_INIT_PARENTS) #define SPRD_COMP_CLK(_struct, _name, _parent, _reg, _mshift, \ _mwidth, _dshift, _dwidth, _flags) \ @@ -47,15 +47,33 @@ struct sprd_comp { _mshift, _mwidth, _dshift, \ _dwidth, _flags) \ SPRD_COMP_CLK_HW_INIT_FN(_struct, _name, _parent, _reg, _table, \ - _mshift, _mwidth, _dshift, _dwidth, \ - _flags, CLK_HW_INIT_PARENTS_DATA) + _mshift, _mwidth, 0x0, _dshift, \ + _dwidth, _flags, \ + CLK_HW_INIT_PARENTS_DATA) #define SPRD_COMP_CLK_DATA(_struct, _name, _parent, _reg, _mshift, \ _mwidth, _dshift, _dwidth, _flags) \ - SPRD_COMP_CLK_DATA_TABLE(_struct, _name, _parent, _reg, NULL, \ + SPRD_COMP_CLK_DATA_TABLE(_struct, _name, _parent, _reg, NULL, \ _mshift, _mwidth, _dshift, _dwidth, \ _flags) +#define SPRD_COMP_CLK_DATA_TABLE_OFFSET(_struct, _name, _parent, _reg, \ + _table, _mshift, _mwidth, \ + _doffset, _dshift, _dwidth, \ + _flags) \ + SPRD_COMP_CLK_HW_INIT_FN(_struct, _name, _parent, _reg, _table, \ + _mshift, _mwidth, _doffset, _dshift, \ + _dwidth, _flags, \ + CLK_HW_INIT_PARENTS_DATA) + +#define SPRD_COMP_CLK_DATA_OFFSET(_struct, _name, _parent, _reg, \ + _mshift, _mwidth, _doffset, _dshift, \ + _dwidth, _flags) \ + SPRD_COMP_CLK_DATA_TABLE_OFFSET(_struct, _name, _parent, _reg, \ + NULL, _mshift, _mwidth, \ + _doffset, _dshift, _dwidth, \ + _flags) + static inline struct sprd_comp *hw_to_sprd_comp(const struct clk_hw *hw) { struct sprd_clk_common *common = hw_to_sprd_clk_common(hw); diff --git a/drivers/clk/sprd/div.c b/drivers/clk/sprd/div.c index c7261630cab4..936782c24127 100644 --- a/drivers/clk/sprd/div.c +++ b/drivers/clk/sprd/div.c @@ -25,7 +25,7 @@ unsigned long sprd_div_helper_recalc_rate(struct sprd_clk_common *common, unsigned long val; unsigned int reg; - regmap_read(common->regmap, common->reg, ®); + regmap_read(common->regmap, common->reg + div->offset, ®); val = reg >> div->shift; val &= (1 << div->width) - 1; @@ -53,10 +53,10 @@ int sprd_div_helper_set_rate(const struct sprd_clk_common *common, val = divider_get_val(rate, parent_rate, NULL, div->width, 0); - regmap_read(common->regmap, common->reg, ®); + regmap_read(common->regmap, common->reg + div->offset, ®); reg &= ~GENMASK(div->width + div->shift - 1, div->shift); - regmap_write(common->regmap, common->reg, + regmap_write(common->regmap, common->reg + div->offset, reg | (val << div->shift)); return 0; diff --git a/drivers/clk/sprd/div.h b/drivers/clk/sprd/div.h index f5d614b3dcf1..a0bcad80498f 100644 --- a/drivers/clk/sprd/div.h +++ b/drivers/clk/sprd/div.h @@ -20,12 +20,14 @@ * classes. */ struct sprd_div_internal { + s32 offset; u8 shift; u8 width; }; -#define _SPRD_DIV_CLK(_shift, _width) \ +#define _SPRD_DIV_CLK(_offset, _shift, _width) \ { \ + .offset = _offset, \ .shift = _shift, \ .width = _width, \ } @@ -35,10 +37,10 @@ struct sprd_div { struct sprd_clk_common common; }; -#define SPRD_DIV_CLK_HW_INIT_FN(_struct, _name, _parent, _reg, \ +#define SPRD_DIV_CLK_HW_INIT_FN(_struct, _name, _parent, _reg, _offset, \ _shift, _width, _flags, _fn) \ struct sprd_div _struct = { \ - .div = _SPRD_DIV_CLK(_shift, _width), \ + .div = _SPRD_DIV_CLK(_offset, _shift, _width), \ .common = { \ .regmap = NULL, \ .reg = _reg, \ @@ -49,12 +51,17 @@ struct sprd_div { #define SPRD_DIV_CLK(_struct, _name, _parent, _reg, \ _shift, _width, _flags) \ - SPRD_DIV_CLK_HW_INIT_FN(_struct, _name, _parent, _reg, \ + SPRD_DIV_CLK_HW_INIT_FN(_struct, _name, _parent, _reg, 0x0, \ _shift, _width, _flags, CLK_HW_INIT) +#define SPRD_DIV_CLK_FW_NAME(_struct, _name, _parent, _reg, \ + _shift, _width, _flags) \ + SPRD_DIV_CLK_HW_INIT_FN(_struct, _name, _parent, _reg, 0x0, \ + _shift, _width, _flags, CLK_HW_INIT_FW_NAME) + #define SPRD_DIV_CLK_HW(_struct, _name, _parent, _reg, \ _shift, _width, _flags) \ - SPRD_DIV_CLK_HW_INIT_FN(_struct, _name, _parent, _reg, \ + SPRD_DIV_CLK_HW_INIT_FN(_struct, _name, _parent, _reg, 0x0, \ _shift, _width, _flags, CLK_HW_INIT_HW) static inline struct sprd_div *hw_to_sprd_div(const struct clk_hw *hw) -- cgit v1.2.3-59-g8ed1b From ee58d6a115cefd7e8065eb469788dafa00b999d1 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Mon, 24 Jul 2023 17:42:47 -0700 Subject: clk: analogbits: Allow building the library as a module This library is only used by the SiFive PRCI driver. When that driver is built as a module, it makes sense to build this library as a module too. Signed-off-by: Samuel Holland Link: https://lore.kernel.org/r/20230725004248.381868-1-samuel.holland@sifive.com Signed-off-by: Stephen Boyd --- drivers/clk/analogbits/Kconfig | 2 +- drivers/clk/analogbits/wrpll-cln28hpc.c | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/clk/analogbits/Kconfig b/drivers/clk/analogbits/Kconfig index 1e291b185438..7d73db0fcd49 100644 --- a/drivers/clk/analogbits/Kconfig +++ b/drivers/clk/analogbits/Kconfig @@ -1,3 +1,3 @@ # SPDX-License-Identifier: GPL-2.0-only config CLK_ANALOGBITS_WRPLL_CLN28HPC - bool + tristate diff --git a/drivers/clk/analogbits/wrpll-cln28hpc.c b/drivers/clk/analogbits/wrpll-cln28hpc.c index 09ca82356399..65d422a588e1 100644 --- a/drivers/clk/analogbits/wrpll-cln28hpc.c +++ b/drivers/clk/analogbits/wrpll-cln28hpc.c @@ -28,6 +28,7 @@ #include #include #include +#include #include @@ -312,6 +313,7 @@ int wrpll_configure_for_rate(struct wrpll_cfg *c, u32 target_rate, return 0; } +EXPORT_SYMBOL_GPL(wrpll_configure_for_rate); /** * wrpll_calc_output_rate() - calculate the PLL's target output rate @@ -349,6 +351,7 @@ unsigned long wrpll_calc_output_rate(const struct wrpll_cfg *c, return n; } +EXPORT_SYMBOL_GPL(wrpll_calc_output_rate); /** * wrpll_calc_max_lock_us() - return the time for the PLL to lock @@ -366,3 +369,8 @@ unsigned int wrpll_calc_max_lock_us(const struct wrpll_cfg *c) { return MAX_LOCK_US; } +EXPORT_SYMBOL_GPL(wrpll_calc_max_lock_us); + +MODULE_AUTHOR("Paul Walmsley "); +MODULE_DESCRIPTION("Analog Bits Wide-Range PLL library"); +MODULE_LICENSE("GPL"); -- cgit v1.2.3-59-g8ed1b From c8e1d8ae6aba7521d96d5cde21384edde1f06d3d Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Mon, 24 Jul 2023 17:42:48 -0700 Subject: clk: sifive: Allow building the driver as a module This can reduce the kernel image size in multiplatform configurations. Signed-off-by: Samuel Holland Link: https://lore.kernel.org/r/20230725004248.381868-2-samuel.holland@sifive.com Signed-off-by: Stephen Boyd --- drivers/clk/sifive/Kconfig | 2 +- drivers/clk/sifive/sifive-prci.c | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/clk/sifive/Kconfig b/drivers/clk/sifive/Kconfig index 2322f634a910..49597d95602e 100644 --- a/drivers/clk/sifive/Kconfig +++ b/drivers/clk/sifive/Kconfig @@ -10,7 +10,7 @@ menuconfig CLK_SIFIVE if CLK_SIFIVE config CLK_SIFIVE_PRCI - bool "PRCI driver for SiFive SoCs" + tristate "PRCI driver for SiFive SoCs" default ARCH_SIFIVE select RESET_CONTROLLER select RESET_SIMPLE diff --git a/drivers/clk/sifive/sifive-prci.c b/drivers/clk/sifive/sifive-prci.c index af81eb835bc2..25b8e1a80ddc 100644 --- a/drivers/clk/sifive/sifive-prci.c +++ b/drivers/clk/sifive/sifive-prci.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include "sifive-prci.h" #include "fu540-prci.h" @@ -618,9 +619,8 @@ static struct platform_driver sifive_prci_driver = { }, .probe = sifive_prci_probe, }; +module_platform_driver(sifive_prci_driver); -static int __init sifive_prci_init(void) -{ - return platform_driver_register(&sifive_prci_driver); -} -core_initcall(sifive_prci_init); +MODULE_AUTHOR("Paul Walmsley "); +MODULE_DESCRIPTION("SiFive Power Reset Clock Interface (PRCI) driver"); +MODULE_LICENSE("GPL"); -- cgit v1.2.3-59-g8ed1b From d761bb01c85b22d5b44abe283eb89019693f6595 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Mon, 23 Oct 2023 21:30:52 -0600 Subject: clk: socfpga: Fix undefined behavior bug in struct stratix10_clock_data `struct clk_hw_onecell_data` is a flexible structure, which means that it contains flexible-array member at the bottom, in this case array `hws`: include/linux/clk-provider.h: 1380 struct clk_hw_onecell_data { 1381 unsigned int num; 1382 struct clk_hw *hws[] __counted_by(num); 1383 }; This could potentially lead to an overwrite of the objects following `clk_data` in `struct stratix10_clock_data`, in this case `void __iomem *base;` at run-time: drivers/clk/socfpga/stratix10-clk.h: 9 struct stratix10_clock_data { 10 struct clk_hw_onecell_data clk_data; 11 void __iomem *base; 12 }; There are currently three different places where memory is allocated for `struct stratix10_clock_data`, including the flex-array `hws` in `struct clk_hw_onecell_data`: drivers/clk/socfpga/clk-agilex.c: 469 clk_data = devm_kzalloc(dev, struct_size(clk_data, clk_data.hws, 470 num_clks), GFP_KERNEL); drivers/clk/socfpga/clk-agilex.c: 509 clk_data = devm_kzalloc(dev, struct_size(clk_data, clk_data.hws, 510 num_clks), GFP_KERNEL); drivers/clk/socfpga/clk-s10.c: 400 clk_data = devm_kzalloc(dev, struct_size(clk_data, clk_data.hws, 401 num_clks), GFP_KERNEL); I'll use just one of them to describe the issue. See below. Notice that a total of 440 bytes are allocated for flexible-array member `hws` at line 469: include/dt-bindings/clock/agilex-clock.h: 70 #define AGILEX_NUM_CLKS 55 drivers/clk/socfpga/clk-agilex.c: 459 struct stratix10_clock_data *clk_data; 460 void __iomem *base; ... 466 467 num_clks = AGILEX_NUM_CLKS; 468 469 clk_data = devm_kzalloc(dev, struct_size(clk_data, clk_data.hws, 470 num_clks), GFP_KERNEL); `struct_size(clk_data, clk_data.hws, num_clks)` above translates to sizeof(struct stratix10_clock_data) + sizeof(struct clk_hw *) * 55 == 16 + 8 * 55 == 16 + 440 ^^^ | allocated bytes for flex-array `hws` 474 for (i = 0; i < num_clks; i++) 475 clk_data->clk_data.hws[i] = ERR_PTR(-ENOENT); 476 477 clk_data->base = base; and then some data is written into both `hws` and `base` objects. Fix this by placing the declaration of object `clk_data` at the end of `struct stratix10_clock_data`. Also, add a comment to make it clear that this object must always be last in the structure. -Wflex-array-member-not-at-end is coming in GCC-14, and we are getting ready to enable it globally. Fixes: ba7e258425ac ("clk: socfpga: Convert to s10/agilex/n5x to use clk_hw") Cc: stable@vger.kernel.org Reviewed-by: Kees Cook Signed-off-by: Gustavo A. R. Silva Link: https://lore.kernel.org/r/1da736106d8e0806aeafa6e471a13ced490eae22.1698117815.git.gustavoars@kernel.org Signed-off-by: Stephen Boyd --- drivers/clk/socfpga/stratix10-clk.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/clk/socfpga/stratix10-clk.h b/drivers/clk/socfpga/stratix10-clk.h index 75234e0783e1..83fe4eb3133c 100644 --- a/drivers/clk/socfpga/stratix10-clk.h +++ b/drivers/clk/socfpga/stratix10-clk.h @@ -7,8 +7,10 @@ #define __STRATIX10_CLK_H struct stratix10_clock_data { - struct clk_hw_onecell_data clk_data; void __iomem *base; + + /* Must be last */ + struct clk_hw_onecell_data clk_data; }; struct stratix10_pll_clock { -- cgit v1.2.3-59-g8ed1b From 65f9e1becb5592c120c9f11adce97f5ca31dce9b Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Mon, 23 Oct 2023 21:31:42 -0600 Subject: clk: socfpga: agilex: Add bounds-checking coverage for struct stratix10_clock_data In order to gain the bounds-checking coverage that __counted_by provides to flexible-array members at run-time via CONFIG_UBSAN_BOUNDS (for array indexing) and CONFIG_FORTIFY_SOURCE (for strcpy/memcpy-family functions), we must make sure that the counter member, in this case `num`, is updated before the first access to the flex-array member, in this case array `hws`. commit f316cdff8d67 ("clk: Annotate struct clk_hw_onecell_data with __counted_by") introduced `__counted_by` for `struct clk_hw_onecell_data` together with changes to relocate some of assignments of counter `num` before `hws` is accessed: include/linux/clk-provider.h: 1380 struct clk_hw_onecell_data { 1381 unsigned int num; 1382 struct clk_hw *hws[] __counted_by(num); 1383 }; However, this structure is used as a member in other structs, in this case in `struct sstratix10_clock_data`: drivers/clk/socfpga/stratix10-clk.h: 9 struct stratix10_clock_data { 10 void __iomem *base; 11 12 /* Must be last */ 13 struct clk_hw_onecell_data clk_data; 14 }; Hence, we need to move the assignments to `clk_data->clk_data.num` after allocations for `struct stratix10_clock_data` and before accessing the flexible array `clk_data->clk_data.hws`. And, as assignments for both `clk_data->clk_data.num` and `clk_data->base` are originally adjacent to each other, relocate both assignments together. Reviewed-by: Kees Cook Signed-off-by: Gustavo A. R. Silva Link: https://lore.kernel.org/r/385c516c498e07eb9a521107e16a7efd26e86ea5.1698117815.git.gustavoars@kernel.org Signed-off-by: Stephen Boyd --- drivers/clk/socfpga/clk-agilex.c | 12 ++++++------ drivers/clk/socfpga/clk-s10.c | 6 +++--- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/clk/socfpga/clk-agilex.c b/drivers/clk/socfpga/clk-agilex.c index 6b65a74aefa6..8dd94f64756b 100644 --- a/drivers/clk/socfpga/clk-agilex.c +++ b/drivers/clk/socfpga/clk-agilex.c @@ -471,12 +471,12 @@ static int agilex_clkmgr_init(struct platform_device *pdev) if (!clk_data) return -ENOMEM; + clk_data->clk_data.num = num_clks; + clk_data->base = base; + for (i = 0; i < num_clks; i++) clk_data->clk_data.hws[i] = ERR_PTR(-ENOENT); - clk_data->base = base; - clk_data->clk_data.num = num_clks; - agilex_clk_register_pll(agilex_pll_clks, ARRAY_SIZE(agilex_pll_clks), clk_data); agilex_clk_register_c_perip(agilex_main_perip_c_clks, @@ -511,12 +511,12 @@ static int n5x_clkmgr_init(struct platform_device *pdev) if (!clk_data) return -ENOMEM; - for (i = 0; i < num_clks; i++) - clk_data->clk_data.hws[i] = ERR_PTR(-ENOENT); - clk_data->base = base; clk_data->clk_data.num = num_clks; + for (i = 0; i < num_clks; i++) + clk_data->clk_data.hws[i] = ERR_PTR(-ENOENT); + n5x_clk_register_pll(agilex_pll_clks, ARRAY_SIZE(agilex_pll_clks), clk_data); n5x_clk_register_c_perip(n5x_main_perip_c_clks, diff --git a/drivers/clk/socfpga/clk-s10.c b/drivers/clk/socfpga/clk-s10.c index 3752bd9c103c..b4bf4e2d38e1 100644 --- a/drivers/clk/socfpga/clk-s10.c +++ b/drivers/clk/socfpga/clk-s10.c @@ -402,12 +402,12 @@ static int s10_clkmgr_init(struct platform_device *pdev) if (!clk_data) return -ENOMEM; - for (i = 0; i < num_clks; i++) - clk_data->clk_data.hws[i] = ERR_PTR(-ENOENT); - clk_data->base = base; clk_data->clk_data.num = num_clks; + for (i = 0; i < num_clks; i++) + clk_data->clk_data.hws[i] = ERR_PTR(-ENOENT); + s10_clk_register_pll(s10_pll_clks, ARRAY_SIZE(s10_pll_clks), clk_data); s10_clk_register_c_perip(s10_main_perip_c_clks, -- cgit v1.2.3-59-g8ed1b From bd54ccc0f147019dac38e7841876a7415459b875 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 24 Oct 2023 08:00:53 +0300 Subject: clk: mediatek: fix double free in mtk_clk_register_pllfh() The mtk_clk_register_pll_ops() currently frees the "pll" parameter. The function has two callers, mtk_clk_register_pll() and mtk_clk_register_pllfh(). The first one, the _pll() function relies on the free, but for the second _pllfh() function it causes a double free bug. Really the frees should be done in the caller because that's where the allocation is. Fixes: d7964de8a8ea ("clk: mediatek: Add new clock driver to handle FHCTL hardware") Signed-off-by: Dan Carpenter Link: https://lore.kernel.org/r/cd7fa365-28cc-4c34-ac64-6da57c98baa6@moroto.mountain Reviewed-by: AngeloGioacchino Del Regno Signed-off-by: Stephen Boyd --- drivers/clk/mediatek/clk-pll.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/clk/mediatek/clk-pll.c b/drivers/clk/mediatek/clk-pll.c index a4eca5fd539c..513ab6b1b322 100644 --- a/drivers/clk/mediatek/clk-pll.c +++ b/drivers/clk/mediatek/clk-pll.c @@ -321,10 +321,8 @@ struct clk_hw *mtk_clk_register_pll_ops(struct mtk_clk_pll *pll, ret = clk_hw_register(NULL, &pll->hw); - if (ret) { - kfree(pll); + if (ret) return ERR_PTR(ret); - } return &pll->hw; } @@ -340,6 +338,8 @@ struct clk_hw *mtk_clk_register_pll(const struct mtk_pll_data *data, return ERR_PTR(-ENOMEM); hw = mtk_clk_register_pll_ops(pll, data, base, &mtk_pll_ops); + if (IS_ERR(hw)) + kfree(pll); return hw; } -- cgit v1.2.3-59-g8ed1b From 7e52b1164a474dc7b90f68fbb40e35ccd7f7e2e2 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Fri, 27 Oct 2023 10:58:24 +0200 Subject: clk: si521xx: Increase stack based print buffer size in probe Increase the size of temporary print buffer on stack to fix the following warnings reported by LKP. Since all the input parameters of snprintf() are under control of this driver, it is not possible to trigger and overflow here, but since the print buffer is on stack and discarded once driver probe() finishes, it is not an issue to increase it by 10 bytes and fix the warning in the process. Make it so. " drivers/clk/clk-si521xx.c: In function 'si521xx_probe': >> drivers/clk/clk-si521xx.c:318:26: warning: '%d' directive output may be truncated writing between 1 and 10 bytes into a region of size 2 [-Wformat-truncation=] snprintf(name, 6, "DIFF%d", i); ^~ drivers/clk/clk-si521xx.c:318:21: note: directive argument in the range [0, 2147483647] snprintf(name, 6, "DIFF%d", i); ^~~~~~~~ drivers/clk/clk-si521xx.c:318:3: note: 'snprintf' output between 6 and 15 bytes into a destination of size 6 snprintf(name, 6, "DIFF%d", i); ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ " Fixes: edc12763a3a2 ("clk: si521xx: Clock driver for Skyworks Si521xx I2C PCIe clock generators") Reported-by: kernel test robot Closes: https://lore.kernel.org/oe-kbuild-all/202310260412.AGASjFN4-lkp@intel.com/ Signed-off-by: Marek Vasut Link: https://lore.kernel.org/r/20231027085840.30098-1-marex@denx.de Signed-off-by: Stephen Boyd --- drivers/clk/clk-si521xx.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/clk/clk-si521xx.c b/drivers/clk/clk-si521xx.c index 14c8741b9ba0..0f8da64f87bb 100644 --- a/drivers/clk/clk-si521xx.c +++ b/drivers/clk/clk-si521xx.c @@ -282,7 +282,7 @@ static int si521xx_probe(struct i2c_client *client) const u16 chip_info = (u16)(uintptr_t)i2c_get_match_data(client); const struct clk_parent_data clk_parent_data = { .index = 0 }; struct si521xx *si; - unsigned char name[6] = "DIFF0"; + unsigned char name[16] = "DIFF0"; struct clk_init_data init = {}; int i, ret; @@ -315,7 +315,7 @@ static int si521xx_probe(struct i2c_client *client) /* Register clock */ for (i = 0; i < hweight16(chip_info); i++) { memset(&init, 0, sizeof(init)); - snprintf(name, 6, "DIFF%d", i); + snprintf(name, sizeof(name), "DIFF%d", i); init.name = name; init.ops = &si521xx_diff_clk_ops; init.parent_data = &clk_parent_data; -- cgit v1.2.3-59-g8ed1b From 75357829cc8ef20808f38b6256fa167f36267c9f Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Fri, 27 Oct 2023 15:58:21 -0700 Subject: clk: Fix clk gate kunit test on big-endian CPUs The clk gate kunit test checks that the implementation of the basic clk gate reads and writes the proper bits in an MMIO register. The implementation of the basic clk gate type uses writel() and readl() which operate on little-endian registers. This test fails on big-endian CPUs because the clk gate implementation writes to 'fake_reg' with writel(), which converts the value to be written to little-endian before storing the value in the fake register. When the test checks the bits in the fake register on a big-endian machine it falsely assumes the format of the register is also big-endian, when it is really always little-endian. Suffice to say things don't work very well. Mark 'fake_reg' as __le32 and push through endian accessor fixes wherever the value is inspected to make this test endian agnostic. There's a CLK_GATE_BIG_ENDIAN flag for big-endian MMIO devices, which this test isn't using. A follow-up patch will test with and without that flag. Reported-by: Boqun Feng Closes: https://lore.kernel.org/r/ZTLH5o0GlFBYsAHq@boqun-archlinux Tested-by: Boqun Feng Signed-off-by: Stephen Boyd Link: https://lore.kernel.org/r/20231027225821.95833-1-sboyd@kernel.org --- drivers/clk/clk-gate_test.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/drivers/clk/clk-gate_test.c b/drivers/clk/clk-gate_test.c index e136aaad48bf..c96d93b19ddf 100644 --- a/drivers/clk/clk-gate_test.c +++ b/drivers/clk/clk-gate_test.c @@ -131,7 +131,7 @@ struct clk_gate_test_context { void __iomem *fake_mem; struct clk_hw *hw; struct clk_hw *parent; - u32 fake_reg; /* Keep at end, KASAN can detect out of bounds */ + __le32 fake_reg; /* Keep at end, KASAN can detect out of bounds */ }; static struct clk_gate_test_context *clk_gate_test_alloc_ctx(struct kunit *test) @@ -166,7 +166,7 @@ static void clk_gate_test_enable(struct kunit *test) KUNIT_ASSERT_EQ(test, clk_prepare_enable(clk), 0); - KUNIT_EXPECT_EQ(test, enable_val, ctx->fake_reg); + KUNIT_EXPECT_EQ(test, enable_val, le32_to_cpu(ctx->fake_reg)); KUNIT_EXPECT_TRUE(test, clk_hw_is_enabled(hw)); KUNIT_EXPECT_TRUE(test, clk_hw_is_prepared(hw)); KUNIT_EXPECT_TRUE(test, clk_hw_is_enabled(parent)); @@ -183,10 +183,10 @@ static void clk_gate_test_disable(struct kunit *test) u32 disable_val = 0; KUNIT_ASSERT_EQ(test, clk_prepare_enable(clk), 0); - KUNIT_ASSERT_EQ(test, enable_val, ctx->fake_reg); + KUNIT_ASSERT_EQ(test, enable_val, le32_to_cpu(ctx->fake_reg)); clk_disable_unprepare(clk); - KUNIT_EXPECT_EQ(test, disable_val, ctx->fake_reg); + KUNIT_EXPECT_EQ(test, disable_val, le32_to_cpu(ctx->fake_reg)); KUNIT_EXPECT_FALSE(test, clk_hw_is_enabled(hw)); KUNIT_EXPECT_FALSE(test, clk_hw_is_prepared(hw)); KUNIT_EXPECT_FALSE(test, clk_hw_is_enabled(parent)); @@ -246,7 +246,7 @@ static void clk_gate_test_invert_enable(struct kunit *test) KUNIT_ASSERT_EQ(test, clk_prepare_enable(clk), 0); - KUNIT_EXPECT_EQ(test, enable_val, ctx->fake_reg); + KUNIT_EXPECT_EQ(test, enable_val, le32_to_cpu(ctx->fake_reg)); KUNIT_EXPECT_TRUE(test, clk_hw_is_enabled(hw)); KUNIT_EXPECT_TRUE(test, clk_hw_is_prepared(hw)); KUNIT_EXPECT_TRUE(test, clk_hw_is_enabled(parent)); @@ -263,10 +263,10 @@ static void clk_gate_test_invert_disable(struct kunit *test) u32 disable_val = BIT(15); KUNIT_ASSERT_EQ(test, clk_prepare_enable(clk), 0); - KUNIT_ASSERT_EQ(test, enable_val, ctx->fake_reg); + KUNIT_ASSERT_EQ(test, enable_val, le32_to_cpu(ctx->fake_reg)); clk_disable_unprepare(clk); - KUNIT_EXPECT_EQ(test, disable_val, ctx->fake_reg); + KUNIT_EXPECT_EQ(test, disable_val, le32_to_cpu(ctx->fake_reg)); KUNIT_EXPECT_FALSE(test, clk_hw_is_enabled(hw)); KUNIT_EXPECT_FALSE(test, clk_hw_is_prepared(hw)); KUNIT_EXPECT_FALSE(test, clk_hw_is_enabled(parent)); @@ -290,7 +290,7 @@ static int clk_gate_test_invert_init(struct kunit *test) 2000000); KUNIT_ASSERT_NOT_ERR_OR_NULL(test, parent); - ctx->fake_reg = BIT(15); /* Default to off */ + ctx->fake_reg = cpu_to_le32(BIT(15)); /* Default to off */ hw = clk_hw_register_gate_parent_hw(NULL, "test_gate", parent, 0, ctx->fake_mem, 15, CLK_GATE_SET_TO_DISABLE, NULL); @@ -319,7 +319,7 @@ static void clk_gate_test_hiword_enable(struct kunit *test) KUNIT_ASSERT_EQ(test, clk_prepare_enable(clk), 0); - KUNIT_EXPECT_EQ(test, enable_val, ctx->fake_reg); + KUNIT_EXPECT_EQ(test, enable_val, le32_to_cpu(ctx->fake_reg)); KUNIT_EXPECT_TRUE(test, clk_hw_is_enabled(hw)); KUNIT_EXPECT_TRUE(test, clk_hw_is_prepared(hw)); KUNIT_EXPECT_TRUE(test, clk_hw_is_enabled(parent)); @@ -336,10 +336,10 @@ static void clk_gate_test_hiword_disable(struct kunit *test) u32 disable_val = BIT(9 + 16); KUNIT_ASSERT_EQ(test, clk_prepare_enable(clk), 0); - KUNIT_ASSERT_EQ(test, enable_val, ctx->fake_reg); + KUNIT_ASSERT_EQ(test, enable_val, le32_to_cpu(ctx->fake_reg)); clk_disable_unprepare(clk); - KUNIT_EXPECT_EQ(test, disable_val, ctx->fake_reg); + KUNIT_EXPECT_EQ(test, disable_val, le32_to_cpu(ctx->fake_reg)); KUNIT_EXPECT_FALSE(test, clk_hw_is_enabled(hw)); KUNIT_EXPECT_FALSE(test, clk_hw_is_prepared(hw)); KUNIT_EXPECT_FALSE(test, clk_hw_is_enabled(parent)); @@ -387,7 +387,7 @@ static void clk_gate_test_is_enabled(struct kunit *test) struct clk_gate_test_context *ctx; ctx = clk_gate_test_alloc_ctx(test); - ctx->fake_reg = BIT(7); + ctx->fake_reg = cpu_to_le32(BIT(7)); hw = clk_hw_register_gate(NULL, "test_gate", NULL, 0, ctx->fake_mem, 7, 0, NULL); KUNIT_ASSERT_NOT_ERR_OR_NULL(test, hw); @@ -402,7 +402,7 @@ static void clk_gate_test_is_disabled(struct kunit *test) struct clk_gate_test_context *ctx; ctx = clk_gate_test_alloc_ctx(test); - ctx->fake_reg = BIT(4); + ctx->fake_reg = cpu_to_le32(BIT(4)); hw = clk_hw_register_gate(NULL, "test_gate", NULL, 0, ctx->fake_mem, 7, 0, NULL); KUNIT_ASSERT_NOT_ERR_OR_NULL(test, hw); @@ -417,7 +417,7 @@ static void clk_gate_test_is_enabled_inverted(struct kunit *test) struct clk_gate_test_context *ctx; ctx = clk_gate_test_alloc_ctx(test); - ctx->fake_reg = BIT(31); + ctx->fake_reg = cpu_to_le32(BIT(31)); hw = clk_hw_register_gate(NULL, "test_gate", NULL, 0, ctx->fake_mem, 2, CLK_GATE_SET_TO_DISABLE, NULL); KUNIT_ASSERT_NOT_ERR_OR_NULL(test, hw); @@ -432,7 +432,7 @@ static void clk_gate_test_is_disabled_inverted(struct kunit *test) struct clk_gate_test_context *ctx; ctx = clk_gate_test_alloc_ctx(test); - ctx->fake_reg = BIT(29); + ctx->fake_reg = cpu_to_le32(BIT(29)); hw = clk_hw_register_gate(NULL, "test_gate", NULL, 0, ctx->fake_mem, 29, CLK_GATE_SET_TO_DISABLE, NULL); KUNIT_ASSERT_NOT_ERR_OR_NULL(test, hw); -- cgit v1.2.3-59-g8ed1b