]> git.ipfire.org Git - thirdparty/openwrt.git/commitdiff
rockchip: backport GATE_LINK support for RK3588 19925/head
authorTianling Shen <cnsztl@immortalwrt.org>
Mon, 1 Sep 2025 09:53:18 +0000 (17:53 +0800)
committerHauke Mehrtens <hauke@hauke-m.de>
Mon, 8 Sep 2025 12:28:49 +0000 (14:28 +0200)
Apart from improved power consumption, this fixes the runtime errors
from the pmdomain driver (failed to set idle on domain '%s')

Backport four clk fixes while at it.

Signed-off-by: Tianling Shen <cnsztl@immortalwrt.org>
Link: https://github.com/openwrt/openwrt/pull/19925
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
target/linux/rockchip/patches-6.12/032-01-v6.14-clk-rockchip-support-clocks-registered-late.patch [new file with mode: 0644]
target/linux/rockchip/patches-6.12/032-02-v6.14-clk-rockchip-rk3588-register-GATE_LINK-later.patch [new file with mode: 0644]
target/linux/rockchip/patches-6.12/032-03-v6.14-clk-rockchip-expose-rockchip_clk_set_lookup.patch [new file with mode: 0644]
target/linux/rockchip/patches-6.12/032-04-v6.14-clk-rockchip-implement-linked-gate-clock-support.patch [new file with mode: 0644]
target/linux/rockchip/patches-6.12/032-05-v6.14-clk-rockchip-rk3588-drop-RK3588_LINKED_CLK.patch [new file with mode: 0644]
target/linux/rockchip/patches-6.12/032-06-v6.14-clk-rockchip-rk3588-make-refclko25m_ethX-critical.patch [new file with mode: 0644]
target/linux/rockchip/patches-6.12/032-07-v6.15-clk-rockchip-rk3568-mark-hclk_vi-as-critical.patch [new file with mode: 0644]
target/linux/rockchip/patches-6.12/032-08-v6.16-clk-rockchip-rk3588-Add-PLL-rate-for-1500-MHz.patch [new file with mode: 0644]
target/linux/rockchip/patches-6.12/032-09-v6.16-clk-rockchip-Drop-empty-init-callback-for-rk3588-PLL-type.patch [new file with mode: 0644]

diff --git a/target/linux/rockchip/patches-6.12/032-01-v6.14-clk-rockchip-support-clocks-registered-late.patch b/target/linux/rockchip/patches-6.12/032-01-v6.14-clk-rockchip-support-clocks-registered-late.patch
new file mode 100644 (file)
index 0000000..6251731
--- /dev/null
@@ -0,0 +1,106 @@
+From 9e89f02da718bc912f7f253b58804d4a52efed30 Mon Sep 17 00:00:00 2001
+From: Sebastian Reichel <sebastian.reichel@collabora.com>
+Date: Wed, 11 Dec 2024 17:58:50 +0100
+Subject: [PATCH] clk: rockchip: support clocks registered late
+
+When some clocks are registered late and some clocks are registered
+early we need to make sure the late registered clocks report probe defer
+until the final registration has happened.
+
+But we do not want to keep reporting probe defer after the late
+registration has happened. Also not all Rockchip SoCs have late
+registered clocks and may not need to report probe defer at all.
+
+This restructures code a bit, so that there is a new function
+rockchip_clk_init_early(), which should be used for initializing the CRU
+structure on SoCs making use of late initialization in addition to the
+early init. These platforms should call rockchip_clk_finalize()
+once all clocks have been registered.
+
+Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
+[added EXPORT_SYMBOL_GPL(rockchip_clk_finalize) to match the early function]
+Link: https://lore.kernel.org/r/20241211165957.94922-2-sebastian.reichel@collabora.com
+Signed-off-by: Heiko Stuebner <heiko@sntech.de>
+---
+ drivers/clk/rockchip/clk.c | 36 ++++++++++++++++++++++++++++++++----
+ drivers/clk/rockchip/clk.h |  3 +++
+ 2 files changed, 35 insertions(+), 4 deletions(-)
+
+--- a/drivers/clk/rockchip/clk.c
++++ b/drivers/clk/rockchip/clk.c
+@@ -359,14 +359,17 @@ static struct clk *rockchip_clk_register
+       return hw->clk;
+ }
+-struct rockchip_clk_provider *rockchip_clk_init(struct device_node *np,
+-                                              void __iomem *base,
+-                                              unsigned long nr_clks)
++static struct rockchip_clk_provider *rockchip_clk_init_base(
++              struct device_node *np, void __iomem *base,
++              unsigned long nr_clks, bool has_late_clocks)
+ {
+       struct rockchip_clk_provider *ctx;
+       struct clk **clk_table;
++      struct clk *default_clk_val;
+       int i;
++      default_clk_val = ERR_PTR(has_late_clocks ? -EPROBE_DEFER : -ENOENT);
++
+       ctx = kzalloc(sizeof(struct rockchip_clk_provider), GFP_KERNEL);
+       if (!ctx)
+               return ERR_PTR(-ENOMEM);
+@@ -376,7 +379,7 @@ struct rockchip_clk_provider *rockchip_c
+               goto err_free;
+       for (i = 0; i < nr_clks; ++i)
+-              clk_table[i] = ERR_PTR(-ENOENT);
++              clk_table[i] = default_clk_val;
+       ctx->reg_base = base;
+       ctx->clk_data.clks = clk_table;
+@@ -393,8 +396,33 @@ err_free:
+       kfree(ctx);
+       return ERR_PTR(-ENOMEM);
+ }
++
++struct rockchip_clk_provider *rockchip_clk_init(struct device_node *np,
++                                              void __iomem *base,
++                                              unsigned long nr_clks)
++{
++      return rockchip_clk_init_base(np, base, nr_clks, false);
++}
+ EXPORT_SYMBOL_GPL(rockchip_clk_init);
++struct rockchip_clk_provider *rockchip_clk_init_early(struct device_node *np,
++                                                    void __iomem *base,
++                                                    unsigned long nr_clks)
++{
++      return rockchip_clk_init_base(np, base, nr_clks, true);
++}
++EXPORT_SYMBOL_GPL(rockchip_clk_init_early);
++
++void rockchip_clk_finalize(struct rockchip_clk_provider *ctx)
++{
++      int i;
++
++      for (i = 0; i < ctx->clk_data.clk_num; ++i)
++              if (ctx->clk_data.clks[i] == ERR_PTR(-EPROBE_DEFER))
++                      ctx->clk_data.clks[i] = ERR_PTR(-ENOENT);
++}
++EXPORT_SYMBOL_GPL(rockchip_clk_finalize);
++
+ void rockchip_clk_of_add_provider(struct device_node *np,
+                                 struct rockchip_clk_provider *ctx)
+ {
+--- a/drivers/clk/rockchip/clk.h
++++ b/drivers/clk/rockchip/clk.h
+@@ -1024,6 +1024,9 @@ struct rockchip_clk_branch {
+ struct rockchip_clk_provider *rockchip_clk_init(struct device_node *np,
+                       void __iomem *base, unsigned long nr_clks);
++struct rockchip_clk_provider *rockchip_clk_init_early(struct device_node *np,
++                      void __iomem *base, unsigned long nr_clks);
++void rockchip_clk_finalize(struct rockchip_clk_provider *ctx);
+ void rockchip_clk_of_add_provider(struct device_node *np,
+                               struct rockchip_clk_provider *ctx);
+ unsigned long rockchip_clk_find_max_clk_id(struct rockchip_clk_branch *list,
diff --git a/target/linux/rockchip/patches-6.12/032-02-v6.14-clk-rockchip-rk3588-register-GATE_LINK-later.patch b/target/linux/rockchip/patches-6.12/032-02-v6.14-clk-rockchip-rk3588-register-GATE_LINK-later.patch
new file mode 100644 (file)
index 0000000..5e47d89
--- /dev/null
@@ -0,0 +1,150 @@
+From 33af96244a66f855baa43d424844bb437c79c30c Mon Sep 17 00:00:00 2001
+From: Sebastian Reichel <sebastian.reichel@collabora.com>
+Date: Wed, 11 Dec 2024 17:58:51 +0100
+Subject: [PATCH] clk: rockchip: rk3588: register GATE_LINK later
+
+The proper GATE_LINK implementation will use runtime PM to handle the
+linked gate clocks, which requires device context. Currently all clocks
+are registered early via CLK_OF_DECLARE, which is before the kernel
+knows about devices.
+
+Moving the full clocks registration to the probe routine does not work,
+since the clocks needed for timers must be registered early.
+
+To work around this issue, most of the clock tree is registered early,
+but GATE_LINK clocks are handled in the probe routine. Since the resets
+are not needed early either, they have also been moved to the probe
+routine.
+
+Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
+Link: https://lore.kernel.org/r/20241211165957.94922-3-sebastian.reichel@collabora.com
+Signed-off-by: Heiko Stuebner <heiko@sntech.de>
+---
+ drivers/clk/rockchip/clk-rk3588.c | 66 +++++++++++++++++++++++++++----
+ 1 file changed, 58 insertions(+), 8 deletions(-)
+
+--- a/drivers/clk/rockchip/clk-rk3588.c
++++ b/drivers/clk/rockchip/clk-rk3588.c
+@@ -266,6 +266,8 @@ static struct rockchip_pll_rate_table rk
+       },                                                      \
+ }
++static struct rockchip_clk_provider *early_ctx;
++
+ static struct rockchip_cpuclk_rate_table rk3588_cpub0clk_rates[] __initdata = {
+       RK3588_CPUB01CLK_RATE(2496000000, 1),
+       RK3588_CPUB01CLK_RATE(2400000000, 1),
+@@ -694,7 +696,7 @@ static struct rockchip_pll_clock rk3588_
+                    RK3588_MODE_CON0, 10, 15, 0, rk3588_pll_rates),
+ };
+-static struct rockchip_clk_branch rk3588_clk_branches[] __initdata = {
++static struct rockchip_clk_branch rk3588_early_clk_branches[] __initdata = {
+       /*
+        * CRU Clock-Architecture
+        */
+@@ -2428,7 +2430,9 @@ static struct rockchip_clk_branch rk3588
+                       RK3588_CLKGATE_CON(68), 5, GFLAGS),
+       GATE(ACLK_AV1, "aclk_av1", "aclk_av1_pre", 0,
+                       RK3588_CLKGATE_CON(68), 2, GFLAGS),
++};
++static struct rockchip_clk_branch rk3588_clk_branches[] = {
+       GATE_LINK(ACLK_ISP1_PRE, "aclk_isp1_pre", "aclk_isp1_root", ACLK_VI_ROOT, 0, RK3588_CLKGATE_CON(26), 6, GFLAGS),
+       GATE_LINK(HCLK_ISP1_PRE, "hclk_isp1_pre", "hclk_isp1_root", HCLK_VI_ROOT, 0, RK3588_CLKGATE_CON(26), 8, GFLAGS),
+       GATE_LINK(HCLK_NVM, "hclk_nvm", "hclk_nvm_root", ACLK_NVM_ROOT, RK3588_LINKED_CLK, RK3588_CLKGATE_CON(31), 2, GFLAGS),
+@@ -2453,26 +2457,31 @@ static struct rockchip_clk_branch rk3588
+       GATE_LINK(PCLK_VO1GRF, "pclk_vo1grf", "pclk_vo1_root", HCLK_VO1, CLK_IGNORE_UNUSED, RK3588_CLKGATE_CON(59), 12, GFLAGS),
+ };
+-static void __init rk3588_clk_init(struct device_node *np)
++static void __init rk3588_clk_early_init(struct device_node *np)
+ {
+       struct rockchip_clk_provider *ctx;
+-      unsigned long clk_nr_clks;
++      unsigned long clk_nr_clks, max_clk_id1, max_clk_id2;
+       void __iomem *reg_base;
+-      clk_nr_clks = rockchip_clk_find_max_clk_id(rk3588_clk_branches,
+-                                      ARRAY_SIZE(rk3588_clk_branches)) + 1;
++      max_clk_id1 = rockchip_clk_find_max_clk_id(rk3588_clk_branches,
++                                      ARRAY_SIZE(rk3588_clk_branches));
++      max_clk_id2 = rockchip_clk_find_max_clk_id(rk3588_early_clk_branches,
++                                      ARRAY_SIZE(rk3588_early_clk_branches));
++      clk_nr_clks = max(max_clk_id1, max_clk_id2) + 1;
++
+       reg_base = of_iomap(np, 0);
+       if (!reg_base) {
+               pr_err("%s: could not map cru region\n", __func__);
+               return;
+       }
+-      ctx = rockchip_clk_init(np, reg_base, clk_nr_clks);
++      ctx = rockchip_clk_init_early(np, reg_base, clk_nr_clks);
+       if (IS_ERR(ctx)) {
+               pr_err("%s: rockchip clk init failed\n", __func__);
+               iounmap(reg_base);
+               return;
+       }
++      early_ctx = ctx;
+       rockchip_clk_register_plls(ctx, rk3588_pll_clks,
+                                  ARRAY_SIZE(rk3588_pll_clks),
+@@ -2491,14 +2500,55 @@ static void __init rk3588_clk_init(struc
+                       &rk3588_cpub1clk_data, rk3588_cpub1clk_rates,
+                       ARRAY_SIZE(rk3588_cpub1clk_rates));
++      rockchip_clk_register_branches(ctx, rk3588_early_clk_branches,
++                                     ARRAY_SIZE(rk3588_early_clk_branches));
++
++      rockchip_clk_of_add_provider(np, ctx);
++}
++CLK_OF_DECLARE_DRIVER(rk3588_cru, "rockchip,rk3588-cru", rk3588_clk_early_init);
++
++static int clk_rk3588_probe(struct platform_device *pdev)
++{
++      struct rockchip_clk_provider *ctx = early_ctx;
++      struct device *dev = &pdev->dev;
++      struct device_node *np = dev->of_node;
++
+       rockchip_clk_register_branches(ctx, rk3588_clk_branches,
+                                      ARRAY_SIZE(rk3588_clk_branches));
+-      rk3588_rst_init(np, reg_base);
++      rockchip_clk_finalize(ctx);
++      rk3588_rst_init(np, ctx->reg_base);
+       rockchip_register_restart_notifier(ctx, RK3588_GLB_SRST_FST, NULL);
++      /*
++       * Re-add clock provider, so that the newly added clocks are also
++       * re-parented and get their defaults configured.
++       */
++      of_clk_del_provider(np);
+       rockchip_clk_of_add_provider(np, ctx);
++
++      return 0;
+ }
+-CLK_OF_DECLARE(rk3588_cru, "rockchip,rk3588-cru", rk3588_clk_init);
++static const struct of_device_id clk_rk3588_match_table[] = {
++      {
++              .compatible = "rockchip,rk3588-cru",
++      },
++      { }
++};
++
++static struct platform_driver clk_rk3588_driver = {
++      .probe          = clk_rk3588_probe,
++      .driver         = {
++              .name   = "clk-rk3588",
++              .of_match_table = clk_rk3588_match_table,
++              .suppress_bind_attrs = true,
++      },
++};
++
++static int __init rockchip_clk_rk3588_drv_register(void)
++{
++      return platform_driver_register(&clk_rk3588_driver);
++}
++core_initcall(rockchip_clk_rk3588_drv_register);
diff --git a/target/linux/rockchip/patches-6.12/032-03-v6.14-clk-rockchip-expose-rockchip_clk_set_lookup.patch b/target/linux/rockchip/patches-6.12/032-03-v6.14-clk-rockchip-expose-rockchip_clk_set_lookup.patch
new file mode 100644 (file)
index 0000000..ca05b23
--- /dev/null
@@ -0,0 +1,90 @@
+From fe0fb6675fa48cade97d8bcd46226479c4a704df Mon Sep 17 00:00:00 2001
+From: Sebastian Reichel <sebastian.reichel@collabora.com>
+Date: Wed, 11 Dec 2024 17:58:52 +0100
+Subject: [PATCH] clk: rockchip: expose rockchip_clk_set_lookup
+
+Move rockchip_clk_add_lookup to clk.h, so that it can be used
+by sub-devices with their own driver. These might also have to
+do a lookup, so rename the function to rockchip_clk_set_lookup
+and add a matching rockchip_clk_get_lookup.
+
+Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
+Link: https://lore.kernel.org/r/20241211165957.94922-4-sebastian.reichel@collabora.com
+Signed-off-by: Heiko Stuebner <heiko@sntech.de>
+---
+ drivers/clk/rockchip/clk.c | 14 ++++----------
+ drivers/clk/rockchip/clk.h | 12 ++++++++++++
+ 2 files changed, 16 insertions(+), 10 deletions(-)
+
+--- a/drivers/clk/rockchip/clk.c
++++ b/drivers/clk/rockchip/clk.c
+@@ -197,12 +197,6 @@ static void rockchip_fractional_approxim
+       clk_fractional_divider_general_approximation(hw, rate, parent_rate, m, n);
+ }
+-static void rockchip_clk_add_lookup(struct rockchip_clk_provider *ctx,
+-                                  struct clk *clk, unsigned int id)
+-{
+-      ctx->clk_data.clks[id] = clk;
+-}
+-
+ static struct clk *rockchip_clk_register_frac_branch(
+               struct rockchip_clk_provider *ctx, const char *name,
+               const char *const *parent_names, u8 num_parents,
+@@ -292,7 +286,7 @@ static struct clk *rockchip_clk_register
+                       return mux_clk;
+               }
+-              rockchip_clk_add_lookup(ctx, mux_clk, child->id);
++              rockchip_clk_set_lookup(ctx, mux_clk, child->id);
+               /* notifier on the fraction divider to catch rate changes */
+               if (frac->mux_frac_idx >= 0) {
+@@ -452,7 +446,7 @@ void rockchip_clk_register_plls(struct r
+                       continue;
+               }
+-              rockchip_clk_add_lookup(ctx, clk, list->id);
++              rockchip_clk_set_lookup(ctx, clk, list->id);
+       }
+ }
+ EXPORT_SYMBOL_GPL(rockchip_clk_register_plls);
+@@ -614,7 +608,7 @@ void rockchip_clk_register_branches(stru
+                       continue;
+               }
+-              rockchip_clk_add_lookup(ctx, clk, list->id);
++              rockchip_clk_set_lookup(ctx, clk, list->id);
+       }
+ }
+ EXPORT_SYMBOL_GPL(rockchip_clk_register_branches);
+@@ -638,7 +632,7 @@ void rockchip_clk_register_armclk(struct
+               return;
+       }
+-      rockchip_clk_add_lookup(ctx, clk, lookup_id);
++      rockchip_clk_set_lookup(ctx, clk, lookup_id);
+ }
+ EXPORT_SYMBOL_GPL(rockchip_clk_register_armclk);
+--- a/drivers/clk/rockchip/clk.h
++++ b/drivers/clk/rockchip/clk.h
+@@ -1022,6 +1022,18 @@ struct rockchip_clk_branch {
+ #define SGRF_GATE(_id, cname, pname)                          \
+               FACTOR(_id, cname, pname, 0, 1, 1)
++static inline struct clk *rockchip_clk_get_lookup(struct rockchip_clk_provider *ctx,
++                                                unsigned int id)
++{
++      return ctx->clk_data.clks[id];
++}
++
++static inline void rockchip_clk_set_lookup(struct rockchip_clk_provider *ctx,
++                                         struct clk *clk, unsigned int id)
++{
++      ctx->clk_data.clks[id] = clk;
++}
++
+ struct rockchip_clk_provider *rockchip_clk_init(struct device_node *np,
+                       void __iomem *base, unsigned long nr_clks);
+ struct rockchip_clk_provider *rockchip_clk_init_early(struct device_node *np,
diff --git a/target/linux/rockchip/patches-6.12/032-04-v6.14-clk-rockchip-implement-linked-gate-clock-support.patch b/target/linux/rockchip/patches-6.12/032-04-v6.14-clk-rockchip-implement-linked-gate-clock-support.patch
new file mode 100644 (file)
index 0000000..30371a0
--- /dev/null
@@ -0,0 +1,314 @@
+From c62fa612cfa66ab58ab215e5afc95c43c613b513 Mon Sep 17 00:00:00 2001
+From: Sebastian Reichel <sebastian.reichel@collabora.com>
+Date: Wed, 11 Dec 2024 17:58:53 +0100
+Subject: [PATCH] clk: rockchip: implement linked gate clock support
+
+Recent Rockchip SoCs have a new hardware block called Native Interface
+Unit (NIU), which gates clocks to devices behind them. These clock
+gates will only have a running output clock when all of the following
+conditions are met:
+
+1. the parent clock is enabled
+2. the enable bit is set correctly
+3. the linked clock is enabled
+
+To handle them this code registers them as a normal gate type clock,
+which takes care of condition 1 + 2. The linked clock is handled by
+using runtime PM clocks. Handling it via runtime PM requires setting
+up a struct device for each of these clocks with a driver attached
+to use the correct runtime PM operations. Thus the complete handling
+of these clocks has been moved into its own driver.
+
+Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
+Link: https://lore.kernel.org/r/20241211165957.94922-5-sebastian.reichel@collabora.com
+Signed-off-by: Heiko Stuebner <heiko@sntech.de>
+---
+ drivers/clk/rockchip/Makefile     |  1 +
+ drivers/clk/rockchip/clk-rk3588.c | 23 +--------
+ drivers/clk/rockchip/clk.c        | 52 +++++++++++++++++++
+ drivers/clk/rockchip/clk.h        | 25 +++++++++
+ drivers/clk/rockchip/gate-link.c  | 85 +++++++++++++++++++++++++++++++
+ 5 files changed, 165 insertions(+), 21 deletions(-)
+ create mode 100644 drivers/clk/rockchip/gate-link.c
+
+--- a/drivers/clk/rockchip/Makefile
++++ b/drivers/clk/rockchip/Makefile
+@@ -13,6 +13,7 @@ clk-rockchip-y += clk-inverter.o
+ clk-rockchip-y += clk-mmc-phase.o
+ clk-rockchip-y += clk-muxgrf.o
+ clk-rockchip-y += clk-ddr.o
++clk-rockchip-y += gate-link.o
+ clk-rockchip-$(CONFIG_RESET_CONTROLLER) += softrst.o
+ obj-$(CONFIG_CLK_PX30)          += clk-px30.o
+--- a/drivers/clk/rockchip/clk-rk3588.c
++++ b/drivers/clk/rockchip/clk-rk3588.c
+@@ -12,25 +12,6 @@
+ #include <dt-bindings/clock/rockchip,rk3588-cru.h>
+ #include "clk.h"
+-/*
+- * Recent Rockchip SoCs have a new hardware block called Native Interface
+- * Unit (NIU), which gates clocks to devices behind them. These effectively
+- * need two parent clocks.
+- *
+- * Downstream enables the linked clock via runtime PM whenever the gate is
+- * enabled. This implementation uses separate clock nodes for each of the
+- * linked gate clocks, which leaks parts of the clock tree into DT.
+- *
+- * The GATE_LINK macro instead takes the second parent via 'linkname', but
+- * ignores the information. Once the clock framework is ready to handle it, the
+- * information should be passed on here. But since these clocks are required to
+- * access multiple relevant IP blocks, such as PCIe or USB, we mark all linked
+- * clocks critical until a better solution is available. This will waste some
+- * power, but avoids leaking implementation details into DT or hanging the
+- * system.
+- */
+-#define GATE_LINK(_id, cname, pname, linkedclk, f, o, b, gf) \
+-      GATE(_id, cname, pname, f, o, b, gf)
+ #define RK3588_LINKED_CLK             CLK_IS_CRITICAL
+@@ -2513,8 +2494,8 @@ static int clk_rk3588_probe(struct platf
+       struct device *dev = &pdev->dev;
+       struct device_node *np = dev->of_node;
+-      rockchip_clk_register_branches(ctx, rk3588_clk_branches,
+-                                     ARRAY_SIZE(rk3588_clk_branches));
++      rockchip_clk_register_late_branches(dev, ctx, rk3588_clk_branches,
++                                          ARRAY_SIZE(rk3588_clk_branches));
+       rockchip_clk_finalize(ctx);
+--- a/drivers/clk/rockchip/clk.c
++++ b/drivers/clk/rockchip/clk.c
+@@ -19,6 +19,7 @@
+ #include <linux/clk-provider.h>
+ #include <linux/io.h>
+ #include <linux/mfd/syscon.h>
++#include <linux/platform_device.h>
+ #include <linux/regmap.h>
+ #include <linux/reboot.h>
+@@ -468,6 +469,29 @@ unsigned long rockchip_clk_find_max_clk_
+ }
+ EXPORT_SYMBOL_GPL(rockchip_clk_find_max_clk_id);
++static struct platform_device *rockchip_clk_register_gate_link(
++              struct device *parent_dev,
++              struct rockchip_clk_provider *ctx,
++              struct rockchip_clk_branch *clkbr)
++{
++      struct rockchip_gate_link_platdata gate_link_pdata = {
++              .ctx = ctx,
++              .clkbr = clkbr,
++      };
++
++      struct platform_device_info pdevinfo = {
++              .parent = parent_dev,
++              .name = "rockchip-gate-link-clk",
++              .id = clkbr->id,
++              .fwnode = dev_fwnode(parent_dev),
++              .of_node_reused = true,
++              .data = &gate_link_pdata,
++              .size_data = sizeof(gate_link_pdata),
++      };
++
++      return platform_device_register_full(&pdevinfo);
++}
++
+ void rockchip_clk_register_branches(struct rockchip_clk_provider *ctx,
+                                   struct rockchip_clk_branch *list,
+                                   unsigned int nr_clk)
+@@ -593,6 +617,9 @@ void rockchip_clk_register_branches(stru
+                               list->div_width, list->div_flags,
+                               ctx->reg_base, &ctx->lock);
+                       break;
++              case branch_linked_gate:
++                      /* must be registered late, fall-through for error message */
++                      break;
+               }
+               /* none of the cases above matched */
+@@ -613,6 +640,31 @@ void rockchip_clk_register_branches(stru
+ }
+ EXPORT_SYMBOL_GPL(rockchip_clk_register_branches);
++void rockchip_clk_register_late_branches(struct device *dev,
++                                       struct rockchip_clk_provider *ctx,
++                                       struct rockchip_clk_branch *list,
++                                       unsigned int nr_clk)
++{
++      unsigned int idx;
++
++      for (idx = 0; idx < nr_clk; idx++, list++) {
++              struct platform_device *pdev = NULL;
++
++              switch (list->branch_type) {
++              case branch_linked_gate:
++                      pdev = rockchip_clk_register_gate_link(dev, ctx, list);
++                      break;
++              default:
++                      dev_err(dev, "unknown clock type %d\n", list->branch_type);
++                      break;
++              }
++
++              if (!pdev)
++                      dev_err(dev, "failed to register device for clock %s\n", list->name);
++      }
++}
++EXPORT_SYMBOL_GPL(rockchip_clk_register_late_branches);
++
+ void rockchip_clk_register_armclk(struct rockchip_clk_provider *ctx,
+                                 unsigned int lookup_id,
+                                 const char *name, const char *const *parent_names,
+--- a/drivers/clk/rockchip/clk.h
++++ b/drivers/clk/rockchip/clk.h
+@@ -570,6 +570,7 @@ enum rockchip_clk_branch_type {
+       branch_divider,
+       branch_fraction_divider,
+       branch_gate,
++      branch_linked_gate,
+       branch_mmc,
+       branch_inverter,
+       branch_factor,
+@@ -597,6 +598,7 @@ struct rockchip_clk_branch {
+       int                             gate_offset;
+       u8                              gate_shift;
+       u8                              gate_flags;
++      unsigned int                    linked_clk_id;
+       struct rockchip_clk_branch      *child;
+ };
+@@ -895,6 +897,20 @@ struct rockchip_clk_branch {
+               .gate_flags     = gf,                           \
+       }
++#define GATE_LINK(_id, cname, pname, linkedclk, f, o, b, gf)  \
++      {                                                       \
++              .id             = _id,                          \
++              .branch_type    = branch_linked_gate,           \
++              .name           = cname,                        \
++              .parent_names   = (const char *[]){ pname },    \
++              .linked_clk_id  = linkedclk,                    \
++              .num_parents    = 1,                            \
++              .flags          = f,                            \
++              .gate_offset    = o,                            \
++              .gate_shift     = b,                            \
++              .gate_flags     = gf,                           \
++      }
++
+ #define MMC(_id, cname, pname, offset, shift)                 \
+       {                                                       \
+               .id             = _id,                          \
+@@ -1034,6 +1050,11 @@ static inline void rockchip_clk_set_look
+       ctx->clk_data.clks[id] = clk;
+ }
++struct rockchip_gate_link_platdata {
++      struct rockchip_clk_provider *ctx;
++      struct rockchip_clk_branch *clkbr;
++};
++
+ struct rockchip_clk_provider *rockchip_clk_init(struct device_node *np,
+                       void __iomem *base, unsigned long nr_clks);
+ struct rockchip_clk_provider *rockchip_clk_init_early(struct device_node *np,
+@@ -1046,6 +1067,10 @@ unsigned long rockchip_clk_find_max_clk_
+ void rockchip_clk_register_branches(struct rockchip_clk_provider *ctx,
+                                   struct rockchip_clk_branch *list,
+                                   unsigned int nr_clk);
++void rockchip_clk_register_late_branches(struct device *dev,
++                                       struct rockchip_clk_provider *ctx,
++                                       struct rockchip_clk_branch *list,
++                                       unsigned int nr_clk);
+ void rockchip_clk_register_plls(struct rockchip_clk_provider *ctx,
+                               struct rockchip_pll_clock *pll_list,
+                               unsigned int nr_pll, int grf_lock_offset);
+--- /dev/null
++++ b/drivers/clk/rockchip/gate-link.c
+@@ -0,0 +1,85 @@
++// SPDX-License-Identifier: GPL-2.0-or-later
++/*
++ * Copyright (c) 2024 Collabora Ltd.
++ * Author: Sebastian Reichel <sebastian.reichel@collabora.com>
++ */
++
++#include <linux/clk.h>
++#include <linux/platform_device.h>
++#include <linux/pm_clock.h>
++#include <linux/pm_runtime.h>
++#include <linux/property.h>
++#include "clk.h"
++
++static int rk_clk_gate_link_register(struct device *dev,
++                                   struct rockchip_clk_provider *ctx,
++                                   struct rockchip_clk_branch *clkbr)
++{
++      unsigned long flags = clkbr->flags | CLK_SET_RATE_PARENT;
++      struct clk *clk;
++
++      clk = clk_register_gate(dev, clkbr->name, clkbr->parent_names[0],
++                              flags, ctx->reg_base + clkbr->gate_offset,
++                              clkbr->gate_shift, clkbr->gate_flags,
++                              &ctx->lock);
++
++      if (IS_ERR(clk))
++              return PTR_ERR(clk);
++
++      rockchip_clk_set_lookup(ctx, clk, clkbr->id);
++      return 0;
++}
++
++static int rk_clk_gate_link_probe(struct platform_device *pdev)
++{
++      struct rockchip_gate_link_platdata *pdata;
++      struct device *dev = &pdev->dev;
++      struct clk *linked_clk;
++      int ret;
++
++      pdata = dev_get_platdata(dev);
++      if (!pdata)
++              return dev_err_probe(dev, -ENODEV, "missing platform data");
++
++      ret = devm_pm_runtime_enable(dev);
++      if (ret)
++              return ret;
++
++      ret = devm_pm_clk_create(dev);
++      if (ret)
++              return ret;
++
++      linked_clk = rockchip_clk_get_lookup(pdata->ctx, pdata->clkbr->linked_clk_id);
++      ret = pm_clk_add_clk(dev, linked_clk);
++      if (ret)
++              return ret;
++
++      ret = rk_clk_gate_link_register(dev, pdata->ctx, pdata->clkbr);
++      if (ret)
++              goto err;
++
++      return 0;
++
++err:
++      pm_clk_remove_clk(dev, linked_clk);
++      return ret;
++}
++
++static const struct dev_pm_ops rk_clk_gate_link_pm_ops = {
++      SET_RUNTIME_PM_OPS(pm_clk_suspend, pm_clk_resume, NULL)
++};
++
++static struct platform_driver rk_clk_gate_link_driver = {
++      .probe          = rk_clk_gate_link_probe,
++      .driver         = {
++              .name   = "rockchip-gate-link-clk",
++              .pm = &rk_clk_gate_link_pm_ops,
++              .suppress_bind_attrs = true,
++      },
++};
++
++static int __init rk_clk_gate_link_drv_register(void)
++{
++      return platform_driver_register(&rk_clk_gate_link_driver);
++}
++core_initcall(rk_clk_gate_link_drv_register);
diff --git a/target/linux/rockchip/patches-6.12/032-05-v6.14-clk-rockchip-rk3588-drop-RK3588_LINKED_CLK.patch b/target/linux/rockchip/patches-6.12/032-05-v6.14-clk-rockchip-rk3588-drop-RK3588_LINKED_CLK.patch
new file mode 100644 (file)
index 0000000..0e487f9
--- /dev/null
@@ -0,0 +1,112 @@
+From e9cdd7d6cf2a5031a968dc21f4f566101b602150 Mon Sep 17 00:00:00 2001
+From: Sebastian Reichel <sebastian.reichel@collabora.com>
+Date: Wed, 11 Dec 2024 17:58:54 +0100
+Subject: [PATCH] clk: rockchip: rk3588: drop RK3588_LINKED_CLK
+
+With the proper GATE_LINK support, we no longer need to keep the
+linked clocks always on. Thus it's time to drop the CLK_IS_CRITICAL
+flag for them.
+
+Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
+Link: https://lore.kernel.org/r/20241211165957.94922-6-sebastian.reichel@collabora.com
+Signed-off-by: Heiko Stuebner <heiko@sntech.de>
+---
+ drivers/clk/rockchip/clk-rk3588.c | 27 ++++++++++++---------------
+ 1 file changed, 12 insertions(+), 15 deletions(-)
+
+--- a/drivers/clk/rockchip/clk-rk3588.c
++++ b/drivers/clk/rockchip/clk-rk3588.c
+@@ -12,9 +12,6 @@
+ #include <dt-bindings/clock/rockchip,rk3588-cru.h>
+ #include "clk.h"
+-#define RK3588_LINKED_CLK             CLK_IS_CRITICAL
+-
+-
+ #define RK3588_GRF_SOC_STATUS0                0x600
+ #define RK3588_PHYREF_ALT_GATE                0xc38
+@@ -1439,7 +1436,7 @@ static struct rockchip_clk_branch rk3588
+       COMPOSITE_NODIV(HCLK_NVM_ROOT,  "hclk_nvm_root", mux_200m_100m_50m_24m_p, 0,
+                       RK3588_CLKSEL_CON(77), 0, 2, MFLAGS,
+                       RK3588_CLKGATE_CON(31), 0, GFLAGS),
+-      COMPOSITE(ACLK_NVM_ROOT, "aclk_nvm_root", gpll_cpll_p, RK3588_LINKED_CLK,
++      COMPOSITE(ACLK_NVM_ROOT, "aclk_nvm_root", gpll_cpll_p, 0,
+                       RK3588_CLKSEL_CON(77), 7, 1, MFLAGS, 2, 5, DFLAGS,
+                       RK3588_CLKGATE_CON(31), 1, GFLAGS),
+       GATE(ACLK_EMMC, "aclk_emmc", "aclk_nvm_root", 0,
+@@ -1668,13 +1665,13 @@ static struct rockchip_clk_branch rk3588
+                       RK3588_CLKGATE_CON(42), 9, GFLAGS),
+       /* vdpu */
+-      COMPOSITE(ACLK_VDPU_ROOT, "aclk_vdpu_root", gpll_cpll_aupll_p, RK3588_LINKED_CLK,
++      COMPOSITE(ACLK_VDPU_ROOT, "aclk_vdpu_root", gpll_cpll_aupll_p, 0,
+                       RK3588_CLKSEL_CON(98), 5, 2, MFLAGS, 0, 5, DFLAGS,
+                       RK3588_CLKGATE_CON(44), 0, GFLAGS),
+       COMPOSITE_NODIV(ACLK_VDPU_LOW_ROOT, "aclk_vdpu_low_root", mux_400m_200m_100m_24m_p, 0,
+                       RK3588_CLKSEL_CON(98), 7, 2, MFLAGS,
+                       RK3588_CLKGATE_CON(44), 1, GFLAGS),
+-      COMPOSITE_NODIV(HCLK_VDPU_ROOT, "hclk_vdpu_root", mux_200m_100m_50m_24m_p, RK3588_LINKED_CLK,
++      COMPOSITE_NODIV(HCLK_VDPU_ROOT, "hclk_vdpu_root", mux_200m_100m_50m_24m_p, 0,
+                       RK3588_CLKSEL_CON(98), 9, 2, MFLAGS,
+                       RK3588_CLKGATE_CON(44), 2, GFLAGS),
+       COMPOSITE(ACLK_JPEG_DECODER_ROOT, "aclk_jpeg_decoder_root", gpll_cpll_aupll_spll_p, 0,
+@@ -1725,9 +1722,9 @@ static struct rockchip_clk_branch rk3588
+       COMPOSITE(ACLK_RKVENC0_ROOT, "aclk_rkvenc0_root", gpll_cpll_npll_p, 0,
+                       RK3588_CLKSEL_CON(102), 7, 2, MFLAGS, 2, 5, DFLAGS,
+                       RK3588_CLKGATE_CON(47), 1, GFLAGS),
+-      GATE(HCLK_RKVENC0, "hclk_rkvenc0", "hclk_rkvenc0_root", RK3588_LINKED_CLK,
++      GATE(HCLK_RKVENC0, "hclk_rkvenc0", "hclk_rkvenc0_root", 0,
+                       RK3588_CLKGATE_CON(47), 4, GFLAGS),
+-      GATE(ACLK_RKVENC0, "aclk_rkvenc0", "aclk_rkvenc0_root", RK3588_LINKED_CLK,
++      GATE(ACLK_RKVENC0, "aclk_rkvenc0", "aclk_rkvenc0_root", 0,
+                       RK3588_CLKGATE_CON(47), 5, GFLAGS),
+       COMPOSITE(CLK_RKVENC0_CORE, "clk_rkvenc0_core", gpll_cpll_aupll_npll_p, 0,
+                       RK3588_CLKSEL_CON(102), 14, 2, MFLAGS, 9, 5, DFLAGS,
+@@ -1737,10 +1734,10 @@ static struct rockchip_clk_branch rk3588
+                       RK3588_CLKGATE_CON(48), 6, GFLAGS),
+       /* vi */
+-      COMPOSITE(ACLK_VI_ROOT, "aclk_vi_root", gpll_cpll_npll_aupll_spll_p, RK3588_LINKED_CLK,
++      COMPOSITE(ACLK_VI_ROOT, "aclk_vi_root", gpll_cpll_npll_aupll_spll_p, 0,
+                       RK3588_CLKSEL_CON(106), 5, 3, MFLAGS, 0, 5, DFLAGS,
+                       RK3588_CLKGATE_CON(49), 0, GFLAGS),
+-      COMPOSITE_NODIV(HCLK_VI_ROOT, "hclk_vi_root", mux_200m_100m_50m_24m_p, RK3588_LINKED_CLK,
++      COMPOSITE_NODIV(HCLK_VI_ROOT, "hclk_vi_root", mux_200m_100m_50m_24m_p, 0,
+                       RK3588_CLKSEL_CON(106), 8, 2, MFLAGS,
+                       RK3588_CLKGATE_CON(49), 1, GFLAGS),
+       COMPOSITE_NODIV(PCLK_VI_ROOT, "pclk_vi_root", mux_100m_50m_24m_p, 0,
+@@ -1910,10 +1907,10 @@ static struct rockchip_clk_branch rk3588
+       COMPOSITE(ACLK_VOP_ROOT, "aclk_vop_root", gpll_cpll_dmyaupll_npll_spll_p, 0,
+                       RK3588_CLKSEL_CON(110), 5, 3, MFLAGS, 0, 5, DFLAGS,
+                       RK3588_CLKGATE_CON(52), 0, GFLAGS),
+-      COMPOSITE_NODIV(ACLK_VOP_LOW_ROOT, "aclk_vop_low_root", mux_400m_200m_100m_24m_p, RK3588_LINKED_CLK,
++      COMPOSITE_NODIV(ACLK_VOP_LOW_ROOT, "aclk_vop_low_root", mux_400m_200m_100m_24m_p, 0,
+                       RK3588_CLKSEL_CON(110), 8, 2, MFLAGS,
+                       RK3588_CLKGATE_CON(52), 1, GFLAGS),
+-      COMPOSITE_NODIV(HCLK_VOP_ROOT, "hclk_vop_root", mux_200m_100m_50m_24m_p, RK3588_LINKED_CLK,
++      COMPOSITE_NODIV(HCLK_VOP_ROOT, "hclk_vop_root", mux_200m_100m_50m_24m_p, 0,
+                       RK3588_CLKSEL_CON(110), 10, 2, MFLAGS,
+                       RK3588_CLKGATE_CON(52), 2, GFLAGS),
+       COMPOSITE_NODIV(PCLK_VOP_ROOT, "pclk_vop_root", mux_100m_50m_24m_p, 0,
+@@ -2416,7 +2413,7 @@ static struct rockchip_clk_branch rk3588
+ static struct rockchip_clk_branch rk3588_clk_branches[] = {
+       GATE_LINK(ACLK_ISP1_PRE, "aclk_isp1_pre", "aclk_isp1_root", ACLK_VI_ROOT, 0, RK3588_CLKGATE_CON(26), 6, GFLAGS),
+       GATE_LINK(HCLK_ISP1_PRE, "hclk_isp1_pre", "hclk_isp1_root", HCLK_VI_ROOT, 0, RK3588_CLKGATE_CON(26), 8, GFLAGS),
+-      GATE_LINK(HCLK_NVM, "hclk_nvm", "hclk_nvm_root", ACLK_NVM_ROOT, RK3588_LINKED_CLK, RK3588_CLKGATE_CON(31), 2, GFLAGS),
++      GATE_LINK(HCLK_NVM, "hclk_nvm", "hclk_nvm_root", ACLK_NVM_ROOT, 0, RK3588_CLKGATE_CON(31), 2, GFLAGS),
+       GATE_LINK(ACLK_USB, "aclk_usb", "aclk_usb_root", ACLK_VO1USB_TOP_ROOT, 0, RK3588_CLKGATE_CON(42), 2, GFLAGS),
+       GATE_LINK(HCLK_USB, "hclk_usb", "hclk_usb_root", HCLK_VO1USB_TOP_ROOT, 0, RK3588_CLKGATE_CON(42), 3, GFLAGS),
+       GATE_LINK(ACLK_JPEG_DECODER_PRE, "aclk_jpeg_decoder_pre", "aclk_jpeg_decoder_root", ACLK_VDPU_ROOT, 0, RK3588_CLKGATE_CON(44), 7, GFLAGS),
+@@ -2428,9 +2425,9 @@ static struct rockchip_clk_branch rk3588
+       GATE_LINK(HCLK_RKVDEC1_PRE, "hclk_rkvdec1_pre", "hclk_rkvdec1_root", HCLK_VDPU_ROOT, 0, RK3588_CLKGATE_CON(41), 4, GFLAGS),
+       GATE_LINK(ACLK_RKVDEC1_PRE, "aclk_rkvdec1_pre", "aclk_rkvdec1_root", ACLK_VDPU_ROOT, 0, RK3588_CLKGATE_CON(41), 5, GFLAGS),
+       GATE_LINK(ACLK_HDCP0_PRE, "aclk_hdcp0_pre", "aclk_vo0_root", ACLK_VOP_LOW_ROOT, 0, RK3588_CLKGATE_CON(55), 9, GFLAGS),
+-      GATE_LINK(HCLK_VO0, "hclk_vo0", "hclk_vo0_root", HCLK_VOP_ROOT, RK3588_LINKED_CLK, RK3588_CLKGATE_CON(55), 5, GFLAGS),
++      GATE_LINK(HCLK_VO0, "hclk_vo0", "hclk_vo0_root", HCLK_VOP_ROOT, 0, RK3588_CLKGATE_CON(55), 5, GFLAGS),
+       GATE_LINK(ACLK_HDCP1_PRE, "aclk_hdcp1_pre", "aclk_hdcp1_root", ACLK_VO1USB_TOP_ROOT, 0, RK3588_CLKGATE_CON(59), 6, GFLAGS),
+-      GATE_LINK(HCLK_VO1, "hclk_vo1", "hclk_vo1_root", HCLK_VO1USB_TOP_ROOT, RK3588_LINKED_CLK, RK3588_CLKGATE_CON(59), 9, GFLAGS),
++      GATE_LINK(HCLK_VO1, "hclk_vo1", "hclk_vo1_root", HCLK_VO1USB_TOP_ROOT, 0, RK3588_CLKGATE_CON(59), 9, GFLAGS),
+       GATE_LINK(ACLK_AV1_PRE, "aclk_av1_pre", "aclk_av1_root", ACLK_VDPU_ROOT, 0, RK3588_CLKGATE_CON(68), 1, GFLAGS),
+       GATE_LINK(PCLK_AV1_PRE, "pclk_av1_pre", "pclk_av1_root", HCLK_VDPU_ROOT, 0, RK3588_CLKGATE_CON(68), 4, GFLAGS),
+       GATE_LINK(HCLK_SDIO_PRE, "hclk_sdio_pre", "hclk_sdio_root", HCLK_NVM, 0, RK3588_CLKGATE_CON(75), 1, GFLAGS),
diff --git a/target/linux/rockchip/patches-6.12/032-06-v6.14-clk-rockchip-rk3588-make-refclko25m_ethX-critical.patch b/target/linux/rockchip/patches-6.12/032-06-v6.14-clk-rockchip-rk3588-make-refclko25m_ethX-critical.patch
new file mode 100644 (file)
index 0000000..7642555
--- /dev/null
@@ -0,0 +1,54 @@
+From cd8b5366636bdff0449b789fb2d33abb20804255 Mon Sep 17 00:00:00 2001
+From: Heiko Stuebner <heiko.stuebner@cherry.de>
+Date: Sat, 14 Dec 2024 23:48:19 +0100
+Subject: [PATCH] clk: rockchip: rk3588: make refclko25m_ethX critical
+
+Ethernet phys normally need a 25MHz refclk input. On a lot of boards
+this is done with a dedicated 25MHz crystal. But the rk3588 CRU also
+provides a means for that via the refclko25m_ethX clock outputs that
+can be used for that function.
+
+The mdio bus normally probes devices on the bus at runtime, by reading
+specific phy registers. This requires the phy to be running and thus
+also being supplied by its reference clock.
+
+While there exist the possibility and dt-binding to declare these
+input clocks for each phy in the phy-dt-node, this is only relevant
+_after_ the phy has been detected and during the drivers probe-run.
+
+This results in a chicken-and-egg-problem. The refclks in the CRU are
+running on boot of course, but phy-probing can very well happen after
+clk_disable_unused has run.
+
+In the past I tried to make clock-handling part of the mdio bus code [0]
+but that wasn't very well received, due to it being specific to OF and
+clocks with the consensus being that resources needed for detection
+need to be enabled before.
+
+So to make probing ethernet phys using the internal refclks possible,
+make those 2 clocks critical.
+
+[0] https://lore.kernel.org/netdev/13590315.F0gNSz5aLb@diego/T/
+
+Signed-off-by: Heiko Stuebner <heiko.stuebner@cherry.de>
+Link: https://lore.kernel.org/r/20241214224820.200665-1-heiko@sntech.de
+Signed-off-by: Heiko Stuebner <heiko@sntech.de>
+---
+ drivers/clk/rockchip/clk-rk3588.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/clk/rockchip/clk-rk3588.c
++++ b/drivers/clk/rockchip/clk-rk3588.c
+@@ -772,10 +772,10 @@ static struct rockchip_clk_branch rk3588
+       COMPOSITE(MCLK_GMAC0_OUT, "mclk_gmac0_out", gpll_cpll_p, 0,
+                       RK3588_CLKSEL_CON(15), 7, 1, MFLAGS, 0, 7, DFLAGS,
+                       RK3588_CLKGATE_CON(5), 3, GFLAGS),
+-      COMPOSITE(REFCLKO25M_ETH0_OUT, "refclko25m_eth0_out", gpll_cpll_p, 0,
++      COMPOSITE(REFCLKO25M_ETH0_OUT, "refclko25m_eth0_out", gpll_cpll_p, CLK_IS_CRITICAL,
+                       RK3588_CLKSEL_CON(15), 15, 1, MFLAGS, 8, 7, DFLAGS,
+                       RK3588_CLKGATE_CON(5), 4, GFLAGS),
+-      COMPOSITE(REFCLKO25M_ETH1_OUT, "refclko25m_eth1_out", gpll_cpll_p, 0,
++      COMPOSITE(REFCLKO25M_ETH1_OUT, "refclko25m_eth1_out", gpll_cpll_p, CLK_IS_CRITICAL,
+                       RK3588_CLKSEL_CON(16), 7, 1, MFLAGS, 0, 7, DFLAGS,
+                       RK3588_CLKGATE_CON(5), 5, GFLAGS),
+       COMPOSITE(CLK_CIFOUT_OUT, "clk_cifout_out", gpll_cpll_24m_spll_p, 0,
diff --git a/target/linux/rockchip/patches-6.12/032-07-v6.15-clk-rockchip-rk3568-mark-hclk_vi-as-critical.patch b/target/linux/rockchip/patches-6.12/032-07-v6.15-clk-rockchip-rk3568-mark-hclk_vi-as-critical.patch
new file mode 100644 (file)
index 0000000..dd25898
--- /dev/null
@@ -0,0 +1,31 @@
+From 83dbeca33f7422f4a30c8a91a79d6c0dba4fb6af Mon Sep 17 00:00:00 2001
+From: Michael Riesch <michael.riesch@wolfvision.net>
+Date: Mon, 10 Feb 2025 09:29:02 +0100
+Subject: [PATCH] clk: rockchip: rk3568: mark hclk_vi as critical
+
+The clock 'pclk_vi_niu' has a dependency on 'hclk_vi_niu' according
+to the Technical Reference Manual section '2.8.6 NIU Clock gating
+reliance'. However, this kind of dependency cannot be addressed
+properly at the moment (until the support for linked clocks is
+implemented for the RK3568).
+As an intermediate solution, mark the hclk_vi as critical on the
+Rockchip RK3568.
+
+Suggested-by: Nicolas Frattaroli <frattaroli.nicolas@gmail.com>
+Signed-off-by: Michael Riesch <michael.riesch@wolfvision.net>
+Link: https://lore.kernel.org/r/20250210-rk3568-hclk-vi-v1-1-9ade2626f638@wolfvision.net
+Signed-off-by: Heiko Stuebner <heiko@sntech.de>
+---
+ drivers/clk/rockchip/clk-rk3568.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/clk/rockchip/clk-rk3568.c
++++ b/drivers/clk/rockchip/clk-rk3568.c
+@@ -1602,6 +1602,7 @@ static const char *const rk3568_cru_crit
+       "pclk_php",
+       "hclk_usb",
+       "pclk_usb",
++      "hclk_vi",
+       "hclk_vo",
+ };
diff --git a/target/linux/rockchip/patches-6.12/032-08-v6.16-clk-rockchip-rk3588-Add-PLL-rate-for-1500-MHz.patch b/target/linux/rockchip/patches-6.12/032-08-v6.16-clk-rockchip-rk3588-Add-PLL-rate-for-1500-MHz.patch
new file mode 100644 (file)
index 0000000..ba4df3d
--- /dev/null
@@ -0,0 +1,25 @@
+From 831a8ac72264426ccd0ee5d2b0d74491ea7d2bfb Mon Sep 17 00:00:00 2001
+From: Alexander Shiyan <eagle.alexander923@gmail.com>
+Date: Tue, 8 Apr 2025 09:46:12 +0300
+Subject: [PATCH] clk: rockchip: rk3588: Add PLL rate for 1500 MHz
+
+At least one RK3588 clock (CPLL) uses 1.5 GHz, so let's add
+that frequency to the PLL table.
+
+Signed-off-by: Alexander Shiyan <eagle.alexander923@gmail.com>
+Link: https://lore.kernel.org/r/20250408064612.41359-1-eagle.alexander923@gmail.com
+Signed-off-by: Heiko Stuebner <heiko@sntech.de>
+---
+ drivers/clk/rockchip/clk-rk3588.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/clk/rockchip/clk-rk3588.c
++++ b/drivers/clk/rockchip/clk-rk3588.c
+@@ -64,6 +64,7 @@ static struct rockchip_pll_rate_table rk
+       RK3588_PLL_RATE(1560000000, 2, 260, 1, 0),
+       RK3588_PLL_RATE(1536000000, 2, 256, 1, 0),
+       RK3588_PLL_RATE(1512000000, 2, 252, 1, 0),
++      RK3588_PLL_RATE(1500000000, 2, 250, 1, 0),
+       RK3588_PLL_RATE(1488000000, 2, 248, 1, 0),
+       RK3588_PLL_RATE(1464000000, 2, 244, 1, 0),
+       RK3588_PLL_RATE(1440000000, 2, 240, 1, 0),
diff --git a/target/linux/rockchip/patches-6.12/032-09-v6.16-clk-rockchip-Drop-empty-init-callback-for-rk3588-PLL-type.patch b/target/linux/rockchip/patches-6.12/032-09-v6.16-clk-rockchip-Drop-empty-init-callback-for-rk3588-PLL-type.patch
new file mode 100644 (file)
index 0000000..61341a8
--- /dev/null
@@ -0,0 +1,44 @@
+From 646bfc52bbe184c0579060c3919e5d70885b0dcc Mon Sep 17 00:00:00 2001
+From: Yao Zi <ziyao@disroot.org>
+Date: Wed, 26 Mar 2025 11:35:56 +0000
+Subject: [PATCH] clk: rockchip: Drop empty init callback for rk3588 PLL type
+
+Unlike PLLs in previous geneation of SoCs, PLLs in RK3588 type don't
+require any platform-specific initialization. Drop callback
+rockchip_rk3588_pll_init() that does nothing in fact to clean the
+driver up.
+
+Signed-off-by: Yao Zi <ziyao@disroot.org>
+Link: https://lore.kernel.org/r/20250326113556.21039-1-ziyao@disroot.org
+Signed-off-by: Heiko Stuebner <heiko@sntech.de>
+---
+ drivers/clk/rockchip/clk-pll.c | 11 -----------
+ 1 file changed, 11 deletions(-)
+
+--- a/drivers/clk/rockchip/clk-pll.c
++++ b/drivers/clk/rockchip/clk-pll.c
+@@ -1025,16 +1025,6 @@ static int rockchip_rk3588_pll_is_enable
+       return !(pllcon & RK3588_PLLCON1_PWRDOWN);
+ }
+-static int rockchip_rk3588_pll_init(struct clk_hw *hw)
+-{
+-      struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
+-
+-      if (!(pll->flags & ROCKCHIP_PLL_SYNC_RATE))
+-              return 0;
+-
+-      return 0;
+-}
+-
+ static const struct clk_ops rockchip_rk3588_pll_clk_norate_ops = {
+       .recalc_rate = rockchip_rk3588_pll_recalc_rate,
+       .enable = rockchip_rk3588_pll_enable,
+@@ -1049,7 +1039,6 @@ static const struct clk_ops rockchip_rk3
+       .enable = rockchip_rk3588_pll_enable,
+       .disable = rockchip_rk3588_pll_disable,
+       .is_enabled = rockchip_rk3588_pll_is_enabled,
+-      .init = rockchip_rk3588_pll_init,
+ };
+ /*