* [PATCH v9 0/7] rockchip: clk: add GATE_LINK support
@ 2024-03-25 19:33 Sebastian Reichel
2024-03-25 19:33 ` [PATCH v9 1/7] clk: rockchip: rk3588: drop unused code Sebastian Reichel
` (7 more replies)
0 siblings, 8 replies; 11+ messages in thread
From: Sebastian Reichel @ 2024-03-25 19:33 UTC (permalink / raw)
To: Michael Turquette, Stephen Boyd, linux-clk
Cc: Elaine Zhang, Kever Yang, Heiko Stuebner, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, huangtao, andy.yan,
Michal Tomek, Ilya K, Chad LeClair, devicetree, linux-rockchip,
Sebastian Reichel, kernel
Hi,
This implements proper GATE_LINK support following the suggestion from Stephen
Boyd to use clk PM operations by creating MFD dynamically. This required some
restructuring, since CLK_OF_DECLARE() is called before devices are available.
Apart from improved power consumption, this fixes the runtime errors from the
pmdomain driver (failed to set idle on domain '%s').
Changes since PATCHv8:
* https://lore.kernel.org/linux-rockchip/20240126182919.48402-1-sebastian.reichel@collabora.com/
* rebased to v6.9-rc1
* dropped all merged patches (i.e. all but the last one)
* rewrote and split the final patch
- should be easier to review
- properly calls pm_clk_suspend/pm_clk_resume
- now works on Orange Pi
Changes since PATCHv7:
* https://lore.kernel.org/all/20231213185114.47565-1-sebastian.reichel@collabora.com/
* rebased to v6.8-rc1
* Collected Reviewed-by/Acked-by from Krzysztof Kozlowski for DT binding patches
* support nr_clk=0 in rockchip_clk_find_max_clk_id() for smatch
Greetings,
-- Sebstian
Sebastian Reichel (7):
clk: rockchip: rk3588: drop unused code
clk: rockchip: handle missing clocks with -EPROBE_DEFER
clk: rockchip: rk3588: register GATE_LINK later
clk: rockchip: expose rockchip_clk_set_lookup
clk: rockchip: fix error for unknown clocks
clk: rockchip: implement linked gate clock support
clk: rockchip: rk3588: drop RK3588_LINKED_CLK
drivers/clk/rockchip/Makefile | 1 +
drivers/clk/rockchip/clk-rk3588.c | 124 +++++++++++++-----------------
drivers/clk/rockchip/clk.c | 71 ++++++++++++++---
drivers/clk/rockchip/clk.h | 37 +++++++++
drivers/clk/rockchip/gate-link.c | 99 ++++++++++++++++++++++++
5 files changed, 251 insertions(+), 81 deletions(-)
create mode 100644 drivers/clk/rockchip/gate-link.c
--
2.43.0
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH v9 1/7] clk: rockchip: rk3588: drop unused code
2024-03-25 19:33 [PATCH v9 0/7] rockchip: clk: add GATE_LINK support Sebastian Reichel
@ 2024-03-25 19:33 ` Sebastian Reichel
2024-03-25 19:33 ` [PATCH v9 2/7] clk: rockchip: handle missing clocks with -EPROBE_DEFER Sebastian Reichel
` (6 subsequent siblings)
7 siblings, 0 replies; 11+ messages in thread
From: Sebastian Reichel @ 2024-03-25 19:33 UTC (permalink / raw)
To: Michael Turquette, Stephen Boyd, linux-clk
Cc: Elaine Zhang, Kever Yang, Heiko Stuebner, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, huangtao, andy.yan,
Michal Tomek, Ilya K, Chad LeClair, devicetree, linux-rockchip,
Sebastian Reichel, kernel
All clocks are registered early using CLK_OF_DECLARE(), which marks
the DT node as processed. For the processed DT node the probe routine
is never called. Thus this whole code is never executed. This could
be "fixed" by using CLK_OF_DECLARE_DRIVER, which avoids marking the
DT node as processed. But then the probe routine would re-register
all the clocks by calling rk3588_clk_init() again.
Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
---
drivers/clk/rockchip/clk-rk3588.c | 40 -------------------------------
1 file changed, 40 deletions(-)
diff --git a/drivers/clk/rockchip/clk-rk3588.c b/drivers/clk/rockchip/clk-rk3588.c
index b30279a96dc8..74051277ecea 100644
--- a/drivers/clk/rockchip/clk-rk3588.c
+++ b/drivers/clk/rockchip/clk-rk3588.c
@@ -2502,43 +2502,3 @@ static void __init rk3588_clk_init(struct device_node *np)
}
CLK_OF_DECLARE(rk3588_cru, "rockchip,rk3588-cru", rk3588_clk_init);
-
-struct clk_rk3588_inits {
- void (*inits)(struct device_node *np);
-};
-
-static const struct clk_rk3588_inits clk_3588_cru_init = {
- .inits = rk3588_clk_init,
-};
-
-static const struct of_device_id clk_rk3588_match_table[] = {
- {
- .compatible = "rockchip,rk3588-cru",
- .data = &clk_3588_cru_init,
- },
- { }
-};
-
-static int __init clk_rk3588_probe(struct platform_device *pdev)
-{
- const struct clk_rk3588_inits *init_data;
- struct device *dev = &pdev->dev;
-
- init_data = device_get_match_data(dev);
- if (!init_data)
- return -EINVAL;
-
- if (init_data->inits)
- init_data->inits(dev->of_node);
-
- return 0;
-}
-
-static struct platform_driver clk_rk3588_driver = {
- .driver = {
- .name = "clk-rk3588",
- .of_match_table = clk_rk3588_match_table,
- .suppress_bind_attrs = true,
- },
-};
-builtin_platform_driver_probe(clk_rk3588_driver, clk_rk3588_probe);
--
2.43.0
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH v9 2/7] clk: rockchip: handle missing clocks with -EPROBE_DEFER
2024-03-25 19:33 [PATCH v9 0/7] rockchip: clk: add GATE_LINK support Sebastian Reichel
2024-03-25 19:33 ` [PATCH v9 1/7] clk: rockchip: rk3588: drop unused code Sebastian Reichel
@ 2024-03-25 19:33 ` Sebastian Reichel
2024-08-31 10:48 ` Heiko Stübner
2024-03-25 19:33 ` [PATCH v9 3/7] clk: rockchip: rk3588: register GATE_LINK later Sebastian Reichel
` (5 subsequent siblings)
7 siblings, 1 reply; 11+ messages in thread
From: Sebastian Reichel @ 2024-03-25 19:33 UTC (permalink / raw)
To: Michael Turquette, Stephen Boyd, linux-clk
Cc: Elaine Zhang, Kever Yang, Heiko Stuebner, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, huangtao, andy.yan,
Michal Tomek, Ilya K, Chad LeClair, devicetree, linux-rockchip,
Sebastian Reichel, kernel
In the future some clocks will be registered using CLK_OF_DECLARE
and some are registered later from the driver probe routine. Any
clock handled by the probe routine should return -EPROBE_DEFER
until that routine has been called.
Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
---
drivers/clk/rockchip/clk.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/clk/rockchip/clk.c b/drivers/clk/rockchip/clk.c
index 73d2cbdc716b..31b7cc243d82 100644
--- a/drivers/clk/rockchip/clk.c
+++ b/drivers/clk/rockchip/clk.c
@@ -376,7 +376,7 @@ struct rockchip_clk_provider *rockchip_clk_init(struct device_node *np,
goto err_free;
for (i = 0; i < nr_clks; ++i)
- clk_table[i] = ERR_PTR(-ENOENT);
+ clk_table[i] = ERR_PTR(-EPROBE_DEFER);
ctx->reg_base = base;
ctx->clk_data.clks = clk_table;
--
2.43.0
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH v9 3/7] clk: rockchip: rk3588: register GATE_LINK later
2024-03-25 19:33 [PATCH v9 0/7] rockchip: clk: add GATE_LINK support Sebastian Reichel
2024-03-25 19:33 ` [PATCH v9 1/7] clk: rockchip: rk3588: drop unused code Sebastian Reichel
2024-03-25 19:33 ` [PATCH v9 2/7] clk: rockchip: handle missing clocks with -EPROBE_DEFER Sebastian Reichel
@ 2024-03-25 19:33 ` Sebastian Reichel
2024-03-25 19:33 ` [PATCH v9 4/7] clk: rockchip: expose rockchip_clk_set_lookup Sebastian Reichel
` (4 subsequent siblings)
7 siblings, 0 replies; 11+ messages in thread
From: Sebastian Reichel @ 2024-03-25 19:33 UTC (permalink / raw)
To: Michael Turquette, Stephen Boyd, linux-clk
Cc: Elaine Zhang, Kever Yang, Heiko Stuebner, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, huangtao, andy.yan,
Michal Tomek, Ilya K, Chad LeClair, devicetree, linux-rockchip,
Sebastian Reichel, kernel
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>
---
drivers/clk/rockchip/clk-rk3588.c | 64 +++++++++++++++++++++++++++----
1 file changed, 56 insertions(+), 8 deletions(-)
diff --git a/drivers/clk/rockchip/clk-rk3588.c b/drivers/clk/rockchip/clk-rk3588.c
index 74051277ecea..29f31a5526fa 100644
--- a/drivers/clk/rockchip/clk-rk3588.c
+++ b/drivers/clk/rockchip/clk-rk3588.c
@@ -266,6 +266,8 @@ static struct rockchip_pll_rate_table rk3588_pll_rates[] = {
}, \
}
+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_pll_clks[] __initdata = {
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_clk_branches[] __initdata = {
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,14 +2457,18 @@ static struct rockchip_clk_branch rk3588_clk_branches[] __initdata = {
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__);
@@ -2473,6 +2481,7 @@ static void __init rk3588_clk_init(struct device_node *np)
iounmap(reg_base);
return;
}
+ early_ctx = ctx;
rockchip_clk_register_plls(ctx, rk3588_pll_clks,
ARRAY_SIZE(rk3588_pll_clks),
@@ -2491,14 +2500,53 @@ static void __init rk3588_clk_init(struct device_node *np)
&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);
-
+ 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);
--
2.43.0
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH v9 4/7] clk: rockchip: expose rockchip_clk_set_lookup
2024-03-25 19:33 [PATCH v9 0/7] rockchip: clk: add GATE_LINK support Sebastian Reichel
` (2 preceding siblings ...)
2024-03-25 19:33 ` [PATCH v9 3/7] clk: rockchip: rk3588: register GATE_LINK later Sebastian Reichel
@ 2024-03-25 19:33 ` Sebastian Reichel
2024-03-25 19:33 ` [PATCH v9 5/7] clk: rockchip: fix error for unknown clocks Sebastian Reichel
` (3 subsequent siblings)
7 siblings, 0 replies; 11+ messages in thread
From: Sebastian Reichel @ 2024-03-25 19:33 UTC (permalink / raw)
To: Michael Turquette, Stephen Boyd, linux-clk
Cc: Elaine Zhang, Kever Yang, Heiko Stuebner, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, huangtao, andy.yan,
Michal Tomek, Ilya K, Chad LeClair, devicetree, linux-rockchip,
Sebastian Reichel, kernel
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_add_lookup.
Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
---
drivers/clk/rockchip/clk.c | 14 ++++----------
drivers/clk/rockchip/clk.h | 12 ++++++++++++
2 files changed, 16 insertions(+), 10 deletions(-)
diff --git a/drivers/clk/rockchip/clk.c b/drivers/clk/rockchip/clk.c
index 31b7cc243d82..ef2408f10f39 100644
--- a/drivers/clk/rockchip/clk.c
+++ b/drivers/clk/rockchip/clk.c
@@ -197,12 +197,6 @@ static void rockchip_fractional_approximation(struct clk_hw *hw,
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_frac_branch(
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) {
@@ -424,7 +418,7 @@ void rockchip_clk_register_plls(struct rockchip_clk_provider *ctx,
continue;
}
- rockchip_clk_add_lookup(ctx, clk, list->id);
+ rockchip_clk_set_lookup(ctx, clk, list->id);
}
}
EXPORT_SYMBOL_GPL(rockchip_clk_register_plls);
@@ -585,7 +579,7 @@ void rockchip_clk_register_branches(struct rockchip_clk_provider *ctx,
continue;
}
- rockchip_clk_add_lookup(ctx, clk, list->id);
+ rockchip_clk_set_lookup(ctx, clk, list->id);
}
}
EXPORT_SYMBOL_GPL(rockchip_clk_register_branches);
@@ -609,7 +603,7 @@ void rockchip_clk_register_armclk(struct rockchip_clk_provider *ctx,
return;
}
- rockchip_clk_add_lookup(ctx, clk, lookup_id);
+ rockchip_clk_set_lookup(ctx, clk, lookup_id);
}
EXPORT_SYMBOL_GPL(rockchip_clk_register_armclk);
diff --git a/drivers/clk/rockchip/clk.h b/drivers/clk/rockchip/clk.h
index fd3b476dedda..e39392e1c2a2 100644
--- a/drivers/clk/rockchip/clk.h
+++ b/drivers/clk/rockchip/clk.h
@@ -969,6 +969,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);
void rockchip_clk_of_add_provider(struct device_node *np,
--
2.43.0
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH v9 5/7] clk: rockchip: fix error for unknown clocks
2024-03-25 19:33 [PATCH v9 0/7] rockchip: clk: add GATE_LINK support Sebastian Reichel
` (3 preceding siblings ...)
2024-03-25 19:33 ` [PATCH v9 4/7] clk: rockchip: expose rockchip_clk_set_lookup Sebastian Reichel
@ 2024-03-25 19:33 ` Sebastian Reichel
2024-03-25 19:33 ` [PATCH v9 6/7] clk: rockchip: implement linked gate clock support Sebastian Reichel
` (2 subsequent siblings)
7 siblings, 0 replies; 11+ messages in thread
From: Sebastian Reichel @ 2024-03-25 19:33 UTC (permalink / raw)
To: Michael Turquette, Stephen Boyd, linux-clk
Cc: Elaine Zhang, Kever Yang, Heiko Stuebner, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, huangtao, andy.yan,
Michal Tomek, Ilya K, Chad LeClair, devicetree, linux-rockchip,
Sebastian Reichel, kernel
There is a clk == NULL check after the switch to check for
unsupported clk types. Since clk is re-assigned in a loop,
this check is useless right now for anything but the first
round. Let's fix this up by assigning clk = NULL in the
loop before the switch statement.
Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
---
drivers/clk/rockchip/clk.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/clk/rockchip/clk.c b/drivers/clk/rockchip/clk.c
index ef2408f10f39..e150bc1fc319 100644
--- a/drivers/clk/rockchip/clk.c
+++ b/drivers/clk/rockchip/clk.c
@@ -444,12 +444,13 @@ void rockchip_clk_register_branches(struct rockchip_clk_provider *ctx,
struct rockchip_clk_branch *list,
unsigned int nr_clk)
{
- struct clk *clk = NULL;
+ struct clk *clk;
unsigned int idx;
unsigned long flags;
for (idx = 0; idx < nr_clk; idx++, list++) {
flags = list->flags;
+ clk = NULL;
/* catch simple muxes */
switch (list->branch_type) {
--
2.43.0
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH v9 6/7] clk: rockchip: implement linked gate clock support
2024-03-25 19:33 [PATCH v9 0/7] rockchip: clk: add GATE_LINK support Sebastian Reichel
` (4 preceding siblings ...)
2024-03-25 19:33 ` [PATCH v9 5/7] clk: rockchip: fix error for unknown clocks Sebastian Reichel
@ 2024-03-25 19:33 ` Sebastian Reichel
2024-09-02 14:03 ` Heiko Stübner
2024-03-25 19:33 ` [PATCH v9 7/7] clk: rockchip: rk3588: drop RK3588_LINKED_CLK Sebastian Reichel
2024-08-30 15:13 ` (subset) [PATCH v9 0/7] rockchip: clk: add GATE_LINK support Heiko Stuebner
7 siblings, 1 reply; 11+ messages in thread
From: Sebastian Reichel @ 2024-03-25 19:33 UTC (permalink / raw)
To: Michael Turquette, Stephen Boyd, linux-clk
Cc: Elaine Zhang, Kever Yang, Heiko Stuebner, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, huangtao, andy.yan,
Michal Tomek, Ilya K, Chad LeClair, devicetree, linux-rockchip,
Sebastian Reichel, kernel
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>
---
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 | 99 +++++++++++++++++++++++++++++++
5 files changed, 179 insertions(+), 21 deletions(-)
create mode 100644 drivers/clk/rockchip/gate-link.c
diff --git a/drivers/clk/rockchip/Makefile b/drivers/clk/rockchip/Makefile
index 36894f6a7022..179be95c6ffb 100644
--- 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
diff --git a/drivers/clk/rockchip/clk-rk3588.c b/drivers/clk/rockchip/clk-rk3588.c
index 29f31a5526fa..1bf84ac44e85 100644
--- 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 platform_device *pdev)
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));
rk3588_rst_init(np, ctx->reg_base);
rockchip_register_restart_notifier(ctx, RK3588_GLB_SRST_FST, NULL);
diff --git a/drivers/clk/rockchip/clk.c b/drivers/clk/rockchip/clk.c
index e150bc1fc319..f5f11cc60046 100644
--- 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>
@@ -440,6 +441,29 @@ unsigned long rockchip_clk_find_max_clk_id(struct rockchip_clk_branch *list,
}
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)
@@ -565,6 +589,9 @@ void rockchip_clk_register_branches(struct rockchip_clk_provider *ctx,
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 */
@@ -585,6 +612,31 @@ void rockchip_clk_register_branches(struct rockchip_clk_provider *ctx,
}
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,
diff --git a/drivers/clk/rockchip/clk.h b/drivers/clk/rockchip/clk.h
index e39392e1c2a2..15aa2fd5265b 100644
--- a/drivers/clk/rockchip/clk.h
+++ b/drivers/clk/rockchip/clk.h
@@ -517,6 +517,7 @@ enum rockchip_clk_branch_type {
branch_divider,
branch_fraction_divider,
branch_gate,
+ branch_linked_gate,
branch_mmc,
branch_inverter,
branch_factor,
@@ -544,6 +545,7 @@ struct rockchip_clk_branch {
int gate_offset;
u8 gate_shift;
u8 gate_flags;
+ unsigned int linked_clk_id;
struct rockchip_clk_branch *child;
};
@@ -842,6 +844,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, \
@@ -981,6 +997,11 @@ static inline void rockchip_clk_set_lookup(struct rockchip_clk_provider *ctx,
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);
void rockchip_clk_of_add_provider(struct device_node *np,
@@ -990,6 +1011,10 @@ unsigned long rockchip_clk_find_max_clk_id(struct rockchip_clk_branch *list,
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);
diff --git a/drivers/clk/rockchip/gate-link.c b/drivers/clk/rockchip/gate-link.c
new file mode 100644
index 000000000000..47b6f3e7a6a2
--- /dev/null
+++ b/drivers/clk/rockchip/gate-link.c
@@ -0,0 +1,99 @@
+// 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 void rk_clk_gate_link_remove(struct platform_device *pdev)
+{
+ struct rockchip_gate_link_platdata *pdata;
+ struct device *dev = &pdev->dev;
+ struct clk *clk, *linked_clk;
+
+ pdata = dev_get_platdata(dev);
+ clk = rockchip_clk_get_lookup(pdata->ctx, pdata->clkbr->id);
+ linked_clk = rockchip_clk_get_lookup(pdata->ctx, pdata->clkbr->linked_clk_id);
+ rockchip_clk_set_lookup(pdata->ctx, ERR_PTR(-ENODEV), pdata->clkbr->id);
+ clk_unregister_gate(clk);
+ pm_clk_remove_clk(dev, linked_clk);
+}
+
+static const struct dev_pm_ops rk_clk_gate_link_pm_ops = {
+ SET_RUNTIME_PM_OPS(pm_clk_suspend, pm_clk_resume, NULL)
+};
+
+struct platform_driver rk_clk_gate_link_driver = {
+ .probe = rk_clk_gate_link_probe,
+ .remove_new = rk_clk_gate_link_remove,
+ .driver = {
+ .name = "rockchip-gate-link-clk",
+ .pm = &rk_clk_gate_link_pm_ops,
+ },
+};
+
+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);
--
2.43.0
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH v9 7/7] clk: rockchip: rk3588: drop RK3588_LINKED_CLK
2024-03-25 19:33 [PATCH v9 0/7] rockchip: clk: add GATE_LINK support Sebastian Reichel
` (5 preceding siblings ...)
2024-03-25 19:33 ` [PATCH v9 6/7] clk: rockchip: implement linked gate clock support Sebastian Reichel
@ 2024-03-25 19:33 ` Sebastian Reichel
2024-08-30 15:13 ` (subset) [PATCH v9 0/7] rockchip: clk: add GATE_LINK support Heiko Stuebner
7 siblings, 0 replies; 11+ messages in thread
From: Sebastian Reichel @ 2024-03-25 19:33 UTC (permalink / raw)
To: Michael Turquette, Stephen Boyd, linux-clk
Cc: Elaine Zhang, Kever Yang, Heiko Stuebner, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, huangtao, andy.yan,
Michal Tomek, Ilya K, Chad LeClair, devicetree, linux-rockchip,
Sebastian Reichel, kernel
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>
---
drivers/clk/rockchip/clk-rk3588.c | 27 ++++++++++++---------------
1 file changed, 12 insertions(+), 15 deletions(-)
diff --git a/drivers/clk/rockchip/clk-rk3588.c b/drivers/clk/rockchip/clk-rk3588.c
index 1bf84ac44e85..42579b6f74b4 100644
--- 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_early_clk_branches[] __initdata = {
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_early_clk_branches[] __initdata = {
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_early_clk_branches[] __initdata = {
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_early_clk_branches[] __initdata = {
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_early_clk_branches[] __initdata = {
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_early_clk_branches[] __initdata = {
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_clk_branches[] = {
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),
--
2.43.0
^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: (subset) [PATCH v9 0/7] rockchip: clk: add GATE_LINK support
2024-03-25 19:33 [PATCH v9 0/7] rockchip: clk: add GATE_LINK support Sebastian Reichel
` (6 preceding siblings ...)
2024-03-25 19:33 ` [PATCH v9 7/7] clk: rockchip: rk3588: drop RK3588_LINKED_CLK Sebastian Reichel
@ 2024-08-30 15:13 ` Heiko Stuebner
7 siblings, 0 replies; 11+ messages in thread
From: Heiko Stuebner @ 2024-08-30 15:13 UTC (permalink / raw)
To: Sebastian Reichel, Stephen Boyd, linux-clk, Michael Turquette,
Detlev Casanova
Cc: Heiko Stuebner, andy.yan, Michal Tomek, huangtao, Elaine Zhang,
linux-rockchip, Chad LeClair, Rob Herring, devicetree,
Krzysztof Kozlowski, Conor Dooley, Kever Yang, kernel, Ilya K
On Mon, 25 Mar 2024 20:33:31 +0100, Sebastian Reichel wrote:
> This implements proper GATE_LINK support following the suggestion from Stephen
> Boyd to use clk PM operations by creating MFD dynamically. This required some
> restructuring, since CLK_OF_DECLARE() is called before devices are available.
>
> Apart from improved power consumption, this fixes the runtime errors from the
> pmdomain driver (failed to set idle on domain '%s').
>
> [...]
Applied, thanks!
[1/7] clk: rockchip: rk3588: drop unused code
commit: 2e7b3daa8cb1ebd17e6a7f417ef5e6553203035c
@Detlev: I think the rk3576 driver I added days ago, might also want
that change? Can you take a look please?
[I don't have rk3576 hardware, so can't check myself ;-) ]
[5/7] clk: rockchip: fix error for unknown clocks
commit: 12fd64babaca4dc09d072f63eda76ba44119816a
I've added a fixes that to that, looks like overlooked that issue
way back in 2014 ... pure nostalgia.
Anyway, rest of the series hopefully later today.
Best regards,
--
Heiko Stuebner <heiko@sntech.de>
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v9 2/7] clk: rockchip: handle missing clocks with -EPROBE_DEFER
2024-03-25 19:33 ` [PATCH v9 2/7] clk: rockchip: handle missing clocks with -EPROBE_DEFER Sebastian Reichel
@ 2024-08-31 10:48 ` Heiko Stübner
0 siblings, 0 replies; 11+ messages in thread
From: Heiko Stübner @ 2024-08-31 10:48 UTC (permalink / raw)
To: Michael Turquette, Stephen Boyd, linux-clk, Sebastian Reichel
Cc: Elaine Zhang, Kever Yang, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, huangtao, andy.yan, Michal Tomek, Ilya K,
Chad LeClair, devicetree, linux-rockchip, Sebastian Reichel,
kernel
Am Montag, 25. März 2024, 20:33:33 CEST schrieb Sebastian Reichel:
> In the future some clocks will be registered using CLK_OF_DECLARE
> and some are registered later from the driver probe routine. Any
> clock handled by the probe routine should return -EPROBE_DEFER
> until that routine has been called.
So this changes the behaviour for misconfigured systems/devicetrees.
Before a driver would get the ENOENT if they requested a clock from an
empty lookup field, but now they will just defer forever.
Can we do some rockchip_clk_finalize() that runs after _all_ clocks are
registered (in the CLK_OF_DECLARE function for most drivers, at the end
of probe for i.e. rk3588) that takes all lookup entries that are still
EPROBE_DEFER and set it to ENOENT again please?
Thanks
Heiko
> Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
> ---
> drivers/clk/rockchip/clk.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/clk/rockchip/clk.c b/drivers/clk/rockchip/clk.c
> index 73d2cbdc716b..31b7cc243d82 100644
> --- a/drivers/clk/rockchip/clk.c
> +++ b/drivers/clk/rockchip/clk.c
> @@ -376,7 +376,7 @@ struct rockchip_clk_provider *rockchip_clk_init(struct device_node *np,
> goto err_free;
>
> for (i = 0; i < nr_clks; ++i)
> - clk_table[i] = ERR_PTR(-ENOENT);
> + clk_table[i] = ERR_PTR(-EPROBE_DEFER);
>
> ctx->reg_base = base;
> ctx->clk_data.clks = clk_table;
>
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v9 6/7] clk: rockchip: implement linked gate clock support
2024-03-25 19:33 ` [PATCH v9 6/7] clk: rockchip: implement linked gate clock support Sebastian Reichel
@ 2024-09-02 14:03 ` Heiko Stübner
0 siblings, 0 replies; 11+ messages in thread
From: Heiko Stübner @ 2024-09-02 14:03 UTC (permalink / raw)
To: Michael Turquette, Stephen Boyd, linux-clk, Sebastian Reichel
Cc: Elaine Zhang, Kever Yang, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, huangtao, andy.yan, Michal Tomek, Ilya K,
Chad LeClair, devicetree, linux-rockchip, Sebastian Reichel,
kernel
Am Montag, 25. März 2024, 20:33:37 CEST schrieb Sebastian Reichel:
> 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>
> +static void rk_clk_gate_link_remove(struct platform_device *pdev)
> +{
> + struct rockchip_gate_link_platdata *pdata;
> + struct device *dev = &pdev->dev;
> + struct clk *clk, *linked_clk;
> +
> + pdata = dev_get_platdata(dev);
> + clk = rockchip_clk_get_lookup(pdata->ctx, pdata->clkbr->id);
> + linked_clk = rockchip_clk_get_lookup(pdata->ctx, pdata->clkbr->linked_clk_id);
> + rockchip_clk_set_lookup(pdata->ctx, ERR_PTR(-ENODEV), pdata->clkbr->id);
> + clk_unregister_gate(clk);
> + pm_clk_remove_clk(dev, linked_clk);
> +}
> +
> +static const struct dev_pm_ops rk_clk_gate_link_pm_ops = {
> + SET_RUNTIME_PM_OPS(pm_clk_suspend, pm_clk_resume, NULL)
> +};
> +
> +struct platform_driver rk_clk_gate_link_driver = {
> + .probe = rk_clk_gate_link_probe,
> + .remove_new = rk_clk_gate_link_remove,
what's the use-case for remove?
We don't allow the main clock driver to be unbound, so I guess we might
want to do the same here? On a system-level they're getting registered
automatically but never unregistered, so the only case here would be
a manual unbind - but I'd think that would cause mayhem anyway?
^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2024-09-02 14:02 UTC | newest]
Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-03-25 19:33 [PATCH v9 0/7] rockchip: clk: add GATE_LINK support Sebastian Reichel
2024-03-25 19:33 ` [PATCH v9 1/7] clk: rockchip: rk3588: drop unused code Sebastian Reichel
2024-03-25 19:33 ` [PATCH v9 2/7] clk: rockchip: handle missing clocks with -EPROBE_DEFER Sebastian Reichel
2024-08-31 10:48 ` Heiko Stübner
2024-03-25 19:33 ` [PATCH v9 3/7] clk: rockchip: rk3588: register GATE_LINK later Sebastian Reichel
2024-03-25 19:33 ` [PATCH v9 4/7] clk: rockchip: expose rockchip_clk_set_lookup Sebastian Reichel
2024-03-25 19:33 ` [PATCH v9 5/7] clk: rockchip: fix error for unknown clocks Sebastian Reichel
2024-03-25 19:33 ` [PATCH v9 6/7] clk: rockchip: implement linked gate clock support Sebastian Reichel
2024-09-02 14:03 ` Heiko Stübner
2024-03-25 19:33 ` [PATCH v9 7/7] clk: rockchip: rk3588: drop RK3588_LINKED_CLK Sebastian Reichel
2024-08-30 15:13 ` (subset) [PATCH v9 0/7] rockchip: clk: add GATE_LINK support Heiko Stuebner
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox