rockchip: update rk3588 gate link patches
Signed-off-by: Tianling Shen <cnsztl@immortalwrt.org>
This commit is contained in:
parent
1b53b6d0d2
commit
a09aab301f
@ -0,0 +1,79 @@
|
|||||||
|
From: Sebastian Reichel <sebastian.reichel@collabora.com>
|
||||||
|
To: Michael Turquette <mturquette@baylibre.com>,
|
||||||
|
Stephen Boyd <sboyd@kernel.org>,
|
||||||
|
linux-clk@vger.kernel.org
|
||||||
|
Cc: Elaine Zhang <zhangqing@rock-chips.com>,
|
||||||
|
Kever Yang <kever.yang@rock-chips.com>,
|
||||||
|
Heiko Stuebner <heiko@sntech.de>,
|
||||||
|
Rob Herring <robh+dt@kernel.org>,
|
||||||
|
Krzysztof Kozlowski <krzysztof.kozlowski+dt@linaro.org>,
|
||||||
|
Conor Dooley <conor+dt@kernel.org>,
|
||||||
|
huangtao@rock-chips.com, andy.yan@rock-chips.com,
|
||||||
|
Michal Tomek <mtdev79b@gmail.com>, Ilya K <me@0upti.me>,
|
||||||
|
Chad LeClair <leclair@gmail.com>,
|
||||||
|
devicetree@vger.kernel.org, linux-rockchip@lists.infradead.org,
|
||||||
|
Sebastian Reichel <sebastian.reichel@collabora.com>,
|
||||||
|
kernel@collabora.com
|
||||||
|
Subject: [PATCH v9 1/7] clk: rockchip: rk3588: drop unused code
|
||||||
|
Date: Mon, 25 Mar 2024 20:33:32 +0100 [thread overview]
|
||||||
|
Message-ID: <20240325193609.237182-2-sebastian.reichel@collabora.com> (raw)
|
||||||
|
In-Reply-To: <20240325193609.237182-1-sebastian.reichel@collabora.com>
|
||||||
|
|
||||||
|
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(-)
|
||||||
|
|
||||||
|
--- a/drivers/clk/rockchip/clk-rk3588.c
|
||||||
|
+++ b/drivers/clk/rockchip/clk-rk3588.c
|
||||||
|
@@ -2502,43 +2502,3 @@ static void __init rk3588_clk_init(struc
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
@ -1,33 +0,0 @@
|
|||||||
From ab1b4994d0d920a17ddead2b1ae8131f9d873cba Mon Sep 17 00:00:00 2001
|
|
||||||
From: Sebastian Reichel <sebastian.reichel@collabora.com>
|
|
||||||
Date: Tue, 24 Oct 2023 16:09:35 +0200
|
|
||||||
Subject: [PATCH] math.h: add DIV_ROUND_UP_NO_OVERFLOW
|
|
||||||
|
|
||||||
Add a new DIV_ROUND_UP helper, which cannot overflow when
|
|
||||||
big numbers are being used.
|
|
||||||
|
|
||||||
Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
|
|
||||||
---
|
|
||||||
include/linux/math.h | 11 +++++++++++
|
|
||||||
1 file changed, 11 insertions(+)
|
|
||||||
|
|
||||||
--- a/include/linux/math.h
|
|
||||||
+++ b/include/linux/math.h
|
|
||||||
@@ -36,6 +36,17 @@
|
|
||||||
|
|
||||||
#define DIV_ROUND_UP __KERNEL_DIV_ROUND_UP
|
|
||||||
|
|
||||||
+/**
|
|
||||||
+ * DIV_ROUND_UP_NO_OVERFLOW - divide two numbers and always round up
|
|
||||||
+ * @n: numerator / dividend
|
|
||||||
+ * @d: denominator / divisor
|
|
||||||
+ *
|
|
||||||
+ * This functions does the same as DIV_ROUND_UP, but internally uses a
|
|
||||||
+ * division and a modulo operation instead of math tricks. This way it
|
|
||||||
+ * avoids overflowing when handling big numbers.
|
|
||||||
+ */
|
|
||||||
+#define DIV_ROUND_UP_NO_OVERFLOW(n, d) (((n) / (d)) + !!((n) % (d)))
|
|
||||||
+
|
|
||||||
#define DIV_ROUND_DOWN_ULL(ll, d) \
|
|
||||||
({ unsigned long long _tmp = (ll); do_div(_tmp, d); _tmp; })
|
|
||||||
|
|
||||||
@ -1,59 +0,0 @@
|
|||||||
From b55f69688803c3c7d8fd51d8c833002591dd271b Mon Sep 17 00:00:00 2001
|
|
||||||
From: Sebastian Reichel <sebastian.reichel@collabora.com>
|
|
||||||
Date: Tue, 24 Oct 2023 16:13:50 +0200
|
|
||||||
Subject: [PATCH] clk: divider: Fix divisor masking on 64 bit platforms
|
|
||||||
|
|
||||||
The clock framework handles clock rates as "unsigned long", so u32 on
|
|
||||||
32-bit architectures and u64 on 64-bit architectures.
|
|
||||||
|
|
||||||
The current code casts the dividend to u64 on 32-bit to avoid a
|
|
||||||
potential overflow. For example DIV_ROUND_UP(3000000000, 1500000000)
|
|
||||||
= (3.0G + 1.5G - 1) / 1.5G = = OVERFLOW / 1.5G, which has been
|
|
||||||
introduced in commit 9556f9dad8f5 ("clk: divider: handle integer overflow
|
|
||||||
when dividing large clock rates").
|
|
||||||
|
|
||||||
On 64 bit platforms this masks the divisor, so that only the lower
|
|
||||||
32 bit are used. Thus requesting a frequency >= 4.3GHz results
|
|
||||||
in incorrect values. For example requesting 4300000000 (4.3 GHz) will
|
|
||||||
effectively request ca. 5 MHz. Requesting clk_round_rate(clk, ULONG_MAX)
|
|
||||||
is a bit of a special case, since that still returns correct values as
|
|
||||||
long as the parent clock is below 8.5 GHz.
|
|
||||||
|
|
||||||
Fix this by switching to DIV_ROUND_UP_NO_OVERFLOW, which cannot
|
|
||||||
overflow. This avoids any requirements on the arguments (except
|
|
||||||
that divisor should not be 0 obviously).
|
|
||||||
|
|
||||||
Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
|
|
||||||
---
|
|
||||||
drivers/clk/clk-divider.c | 6 +++---
|
|
||||||
1 file changed, 3 insertions(+), 3 deletions(-)
|
|
||||||
|
|
||||||
--- a/drivers/clk/clk-divider.c
|
|
||||||
+++ b/drivers/clk/clk-divider.c
|
|
||||||
@@ -220,7 +220,7 @@ static int _div_round_up(const struct cl
|
|
||||||
unsigned long parent_rate, unsigned long rate,
|
|
||||||
unsigned long flags)
|
|
||||||
{
|
|
||||||
- int div = DIV_ROUND_UP_ULL((u64)parent_rate, rate);
|
|
||||||
+ int div = DIV_ROUND_UP_NO_OVERFLOW(parent_rate, rate);
|
|
||||||
|
|
||||||
if (flags & CLK_DIVIDER_POWER_OF_TWO)
|
|
||||||
div = __roundup_pow_of_two(div);
|
|
||||||
@@ -237,7 +237,7 @@ static int _div_round_closest(const stru
|
|
||||||
int up, down;
|
|
||||||
unsigned long up_rate, down_rate;
|
|
||||||
|
|
||||||
- up = DIV_ROUND_UP_ULL((u64)parent_rate, rate);
|
|
||||||
+ up = DIV_ROUND_UP_NO_OVERFLOW(parent_rate, rate);
|
|
||||||
down = parent_rate / rate;
|
|
||||||
|
|
||||||
if (flags & CLK_DIVIDER_POWER_OF_TWO) {
|
|
||||||
@@ -473,7 +473,7 @@ int divider_get_val(unsigned long rate,
|
|
||||||
{
|
|
||||||
unsigned int div, value;
|
|
||||||
|
|
||||||
- div = DIV_ROUND_UP_ULL((u64)parent_rate, rate);
|
|
||||||
+ div = DIV_ROUND_UP_NO_OVERFLOW(parent_rate, rate);
|
|
||||||
|
|
||||||
if (!_is_valid_div(table, div, flags))
|
|
||||||
return -EINVAL;
|
|
||||||
@ -0,0 +1,42 @@
|
|||||||
|
From: Sebastian Reichel <sebastian.reichel@collabora.com>
|
||||||
|
To: Michael Turquette <mturquette@baylibre.com>,
|
||||||
|
Stephen Boyd <sboyd@kernel.org>,
|
||||||
|
linux-clk@vger.kernel.org
|
||||||
|
Cc: Elaine Zhang <zhangqing@rock-chips.com>,
|
||||||
|
Kever Yang <kever.yang@rock-chips.com>,
|
||||||
|
Heiko Stuebner <heiko@sntech.de>,
|
||||||
|
Rob Herring <robh+dt@kernel.org>,
|
||||||
|
Krzysztof Kozlowski <krzysztof.kozlowski+dt@linaro.org>,
|
||||||
|
Conor Dooley <conor+dt@kernel.org>,
|
||||||
|
huangtao@rock-chips.com, andy.yan@rock-chips.com,
|
||||||
|
Michal Tomek <mtdev79b@gmail.com>, Ilya K <me@0upti.me>,
|
||||||
|
Chad LeClair <leclair@gmail.com>,
|
||||||
|
devicetree@vger.kernel.org, linux-rockchip@lists.infradead.org,
|
||||||
|
Sebastian Reichel <sebastian.reichel@collabora.com>,
|
||||||
|
kernel@collabora.com
|
||||||
|
Subject: [PATCH v9 2/7] clk: rockchip: handle missing clocks with -EPROBE_DEFER
|
||||||
|
Date: Mon, 25 Mar 2024 20:33:33 +0100 [thread overview]
|
||||||
|
Message-ID: <20240325193609.237182-3-sebastian.reichel@collabora.com> (raw)
|
||||||
|
In-Reply-To: <20240325193609.237182-1-sebastian.reichel@collabora.com>
|
||||||
|
|
||||||
|
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(-)
|
||||||
|
|
||||||
|
--- a/drivers/clk/rockchip/clk.c
|
||||||
|
+++ b/drivers/clk/rockchip/clk.c
|
||||||
|
@@ -376,7 +376,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] = ERR_PTR(-EPROBE_DEFER);
|
||||||
|
|
||||||
|
ctx->reg_base = base;
|
||||||
|
ctx->clk_data.clks = clk_table;
|
||||||
@ -0,0 +1,157 @@
|
|||||||
|
From: Sebastian Reichel <sebastian.reichel@collabora.com>
|
||||||
|
To: Michael Turquette <mturquette@baylibre.com>,
|
||||||
|
Stephen Boyd <sboyd@kernel.org>,
|
||||||
|
linux-clk@vger.kernel.org
|
||||||
|
Cc: Elaine Zhang <zhangqing@rock-chips.com>,
|
||||||
|
Kever Yang <kever.yang@rock-chips.com>,
|
||||||
|
Heiko Stuebner <heiko@sntech.de>,
|
||||||
|
Rob Herring <robh+dt@kernel.org>,
|
||||||
|
Krzysztof Kozlowski <krzysztof.kozlowski+dt@linaro.org>,
|
||||||
|
Conor Dooley <conor+dt@kernel.org>,
|
||||||
|
huangtao@rock-chips.com, andy.yan@rock-chips.com,
|
||||||
|
Michal Tomek <mtdev79b@gmail.com>, Ilya K <me@0upti.me>,
|
||||||
|
Chad LeClair <leclair@gmail.com>,
|
||||||
|
devicetree@vger.kernel.org, linux-rockchip@lists.infradead.org,
|
||||||
|
Sebastian Reichel <sebastian.reichel@collabora.com>,
|
||||||
|
kernel@collabora.com
|
||||||
|
Subject: [PATCH v9 3/7] clk: rockchip: rk3588: register GATE_LINK later
|
||||||
|
Date: Mon, 25 Mar 2024 20:33:34 +0100 [thread overview]
|
||||||
|
Message-ID: <20240325193609.237182-4-sebastian.reichel@collabora.com> (raw)
|
||||||
|
In-Reply-To: <20240325193609.237182-1-sebastian.reichel@collabora.com>
|
||||||
|
|
||||||
|
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(-)
|
||||||
|
|
||||||
|
--- 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,14 +2457,18 @@ 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__);
|
||||||
|
@@ -2473,6 +2481,7 @@ static void __init rk3588_clk_init(struc
|
||||||
|
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(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);
|
||||||
|
-
|
||||||
|
+ 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);
|
||||||
@ -0,0 +1,104 @@
|
|||||||
|
From: Sebastian Reichel <sebastian.reichel@collabora.com>
|
||||||
|
To: Michael Turquette <mturquette@baylibre.com>,
|
||||||
|
Stephen Boyd <sboyd@kernel.org>,
|
||||||
|
linux-clk@vger.kernel.org
|
||||||
|
Cc: Elaine Zhang <zhangqing@rock-chips.com>,
|
||||||
|
Kever Yang <kever.yang@rock-chips.com>,
|
||||||
|
Heiko Stuebner <heiko@sntech.de>,
|
||||||
|
Rob Herring <robh+dt@kernel.org>,
|
||||||
|
Krzysztof Kozlowski <krzysztof.kozlowski+dt@linaro.org>,
|
||||||
|
Conor Dooley <conor+dt@kernel.org>,
|
||||||
|
huangtao@rock-chips.com, andy.yan@rock-chips.com,
|
||||||
|
Michal Tomek <mtdev79b@gmail.com>, Ilya K <me@0upti.me>,
|
||||||
|
Chad LeClair <leclair@gmail.com>,
|
||||||
|
devicetree@vger.kernel.org, linux-rockchip@lists.infradead.org,
|
||||||
|
Sebastian Reichel <sebastian.reichel@collabora.com>,
|
||||||
|
kernel@collabora.com
|
||||||
|
Subject: [PATCH v9 4/7] clk: rockchip: expose rockchip_clk_set_lookup
|
||||||
|
Date: Mon, 25 Mar 2024 20:33:35 +0100 [thread overview]
|
||||||
|
Message-ID: <20240325193609.237182-5-sebastian.reichel@collabora.com> (raw)
|
||||||
|
In-Reply-To: <20240325193609.237182-1-sebastian.reichel@collabora.com>
|
||||||
|
|
||||||
|
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(-)
|
||||||
|
|
||||||
|
--- 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) {
|
||||||
|
@@ -424,7 +418,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);
|
||||||
|
@@ -585,7 +579,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);
|
||||||
|
@@ -609,7 +603,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
|
||||||
|
@@ -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,
|
||||||
@ -0,0 +1,49 @@
|
|||||||
|
From: Sebastian Reichel <sebastian.reichel@collabora.com>
|
||||||
|
To: Michael Turquette <mturquette@baylibre.com>,
|
||||||
|
Stephen Boyd <sboyd@kernel.org>,
|
||||||
|
linux-clk@vger.kernel.org
|
||||||
|
Cc: Elaine Zhang <zhangqing@rock-chips.com>,
|
||||||
|
Kever Yang <kever.yang@rock-chips.com>,
|
||||||
|
Heiko Stuebner <heiko@sntech.de>,
|
||||||
|
Rob Herring <robh+dt@kernel.org>,
|
||||||
|
Krzysztof Kozlowski <krzysztof.kozlowski+dt@linaro.org>,
|
||||||
|
Conor Dooley <conor+dt@kernel.org>,
|
||||||
|
huangtao@rock-chips.com, andy.yan@rock-chips.com,
|
||||||
|
Michal Tomek <mtdev79b@gmail.com>, Ilya K <me@0upti.me>,
|
||||||
|
Chad LeClair <leclair@gmail.com>,
|
||||||
|
devicetree@vger.kernel.org, linux-rockchip@lists.infradead.org,
|
||||||
|
Sebastian Reichel <sebastian.reichel@collabora.com>,
|
||||||
|
kernel@collabora.com
|
||||||
|
Subject: [PATCH v9 5/7] clk: rockchip: fix error for unknown clocks
|
||||||
|
Date: Mon, 25 Mar 2024 20:33:36 +0100 [thread overview]
|
||||||
|
Message-ID: <20240325193609.237182-6-sebastian.reichel@collabora.com> (raw)
|
||||||
|
In-Reply-To: <20240325193609.237182-1-sebastian.reichel@collabora.com>
|
||||||
|
|
||||||
|
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(-)
|
||||||
|
|
||||||
|
--- a/drivers/clk/rockchip/clk.c
|
||||||
|
+++ b/drivers/clk/rockchip/clk.c
|
||||||
|
@@ -444,12 +444,13 @@ void rockchip_clk_register_branches(stru
|
||||||
|
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) {
|
||||||
@ -0,0 +1,342 @@
|
|||||||
|
From: Sebastian Reichel <sebastian.reichel@collabora.com>
|
||||||
|
To: Michael Turquette <mturquette@baylibre.com>,
|
||||||
|
Stephen Boyd <sboyd@kernel.org>,
|
||||||
|
linux-clk@vger.kernel.org
|
||||||
|
Cc: Elaine Zhang <zhangqing@rock-chips.com>,
|
||||||
|
Kever Yang <kever.yang@rock-chips.com>,
|
||||||
|
Heiko Stuebner <heiko@sntech.de>,
|
||||||
|
Rob Herring <robh+dt@kernel.org>,
|
||||||
|
Krzysztof Kozlowski <krzysztof.kozlowski+dt@linaro.org>,
|
||||||
|
Conor Dooley <conor+dt@kernel.org>,
|
||||||
|
huangtao@rock-chips.com, andy.yan@rock-chips.com,
|
||||||
|
Michal Tomek <mtdev79b@gmail.com>, Ilya K <me@0upti.me>,
|
||||||
|
Chad LeClair <leclair@gmail.com>,
|
||||||
|
devicetree@vger.kernel.org, linux-rockchip@lists.infradead.org,
|
||||||
|
Sebastian Reichel <sebastian.reichel@collabora.com>,
|
||||||
|
kernel@collabora.com
|
||||||
|
Subject: [PATCH v9 6/7] clk: rockchip: implement linked gate clock support
|
||||||
|
Date: Mon, 25 Mar 2024 20:33:37 +0100 [thread overview]
|
||||||
|
Message-ID: <20240325193609.237182-7-sebastian.reichel@collabora.com> (raw)
|
||||||
|
In-Reply-To: <20240325193609.237182-1-sebastian.reichel@collabora.com>
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
--- 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));
|
||||||
|
|
||||||
|
rk3588_rst_init(np, ctx->reg_base);
|
||||||
|
rockchip_register_restart_notifier(ctx, RK3588_GLB_SRST_FST, NULL);
|
||||||
|
--- 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_
|
||||||
|
}
|
||||||
|
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(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 */
|
||||||
|
@@ -585,6 +612,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
|
||||||
|
@@ -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_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);
|
||||||
|
void rockchip_clk_of_add_provider(struct device_node *np,
|
||||||
|
@@ -990,6 +1011,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,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);
|
||||||
@ -0,0 +1,126 @@
|
|||||||
|
From: Sebastian Reichel <sebastian.reichel@collabora.com>
|
||||||
|
To: Michael Turquette <mturquette@baylibre.com>,
|
||||||
|
Stephen Boyd <sboyd@kernel.org>,
|
||||||
|
linux-clk@vger.kernel.org
|
||||||
|
Cc: Elaine Zhang <zhangqing@rock-chips.com>,
|
||||||
|
Kever Yang <kever.yang@rock-chips.com>,
|
||||||
|
Heiko Stuebner <heiko@sntech.de>,
|
||||||
|
Rob Herring <robh+dt@kernel.org>,
|
||||||
|
Krzysztof Kozlowski <krzysztof.kozlowski+dt@linaro.org>,
|
||||||
|
Conor Dooley <conor+dt@kernel.org>,
|
||||||
|
huangtao@rock-chips.com, andy.yan@rock-chips.com,
|
||||||
|
Michal Tomek <mtdev79b@gmail.com>, Ilya K <me@0upti.me>,
|
||||||
|
Chad LeClair <leclair@gmail.com>,
|
||||||
|
devicetree@vger.kernel.org, linux-rockchip@lists.infradead.org,
|
||||||
|
Sebastian Reichel <sebastian.reichel@collabora.com>,
|
||||||
|
kernel@collabora.com
|
||||||
|
Subject: [PATCH v9 7/7] clk: rockchip: rk3588: drop RK3588_LINKED_CLK
|
||||||
|
Date: Mon, 25 Mar 2024 20:33:38 +0100 [thread overview]
|
||||||
|
Message-ID: <20240325193609.237182-8-sebastian.reichel@collabora.com> (raw)
|
||||||
|
In-Reply-To: <20240325193609.237182-1-sebastian.reichel@collabora.com>
|
||||||
|
|
||||||
|
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(-)
|
||||||
|
|
||||||
|
--- 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),
|
||||||
@ -1,435 +0,0 @@
|
|||||||
From: Sebastian Reichel <sebastian.reichel@collabora.com>
|
|
||||||
To: Michael Turquette <mturquette@baylibre.com>,
|
|
||||||
Stephen Boyd <sboyd@kernel.org>,
|
|
||||||
linux-clk@vger.kernel.org
|
|
||||||
Cc: Elaine Zhang <zhangqing@rock-chips.com>,
|
|
||||||
Kever Yang <kever.yang@rock-chips.com>,
|
|
||||||
Heiko Stuebner <heiko@sntech.de>,
|
|
||||||
Rob Herring <robh+dt@kernel.org>,
|
|
||||||
Krzysztof Kozlowski <krzysztof.kozlowski+dt@linaro.org>,
|
|
||||||
Conor Dooley <conor+dt@kernel.org>,
|
|
||||||
huangtao@rock-chips.com, andy.yan@rock-chips.com,
|
|
||||||
devicetree@vger.kernel.org, linux-rockchip@lists.infradead.org,
|
|
||||||
Sebastian Reichel <sebastian.reichel@collabora.com>,
|
|
||||||
kernel@collabora.com
|
|
||||||
Subject: [PATCH v8 7/7] clk: rockchip: implement proper GATE_LINK support
|
|
||||||
Date: Fri, 26 Jan 2024 19:18:28 +0100 [thread overview]
|
|
||||||
Message-ID: <20240126182919.48402-8-sebastian.reichel@collabora.com> (raw)
|
|
||||||
In-Reply-To: <20240126182919.48402-1-sebastian.reichel@collabora.com>
|
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
GATE_LINK type clocks handle the second parent via 'linkedclk' by using
|
|
||||||
runtime PM clocks. To make that possible a new platform device is created
|
|
||||||
for every clock handled in this way.
|
|
||||||
|
|
||||||
Note, that before this patch clk_rk3588_probe() has never been called,
|
|
||||||
because CLK_OF_DECLARE marks the DT node as processed. This patch replaces
|
|
||||||
that with CLK_OF_DECLARE_DRIVER and thus the probe function is used now.
|
|
||||||
This is necessary to have 'struct device' available.
|
|
||||||
|
|
||||||
Also instead of builtin_platform_driver_probe, the driver has been
|
|
||||||
switched to use core_initcall, since it should be fully probed before
|
|
||||||
the Rockchip PM domain driver (and that is using postcore_initcall).
|
|
||||||
|
|
||||||
Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
|
|
||||||
---
|
|
||||||
drivers/clk/rockchip/clk-rk3588.c | 122 +++++++++++++-----------------
|
|
||||||
drivers/clk/rockchip/clk.c | 69 ++++++++++++++++-
|
|
||||||
drivers/clk/rockchip/clk.h | 16 ++++
|
|
||||||
3 files changed, 138 insertions(+), 69 deletions(-)
|
|
||||||
|
|
||||||
--- a/drivers/clk/rockchip/clk-rk3588.c
|
|
||||||
+++ b/drivers/clk/rockchip/clk-rk3588.c
|
|
||||||
@@ -12,28 +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
|
|
||||||
-
|
|
||||||
-
|
|
||||||
#define RK3588_GRF_SOC_STATUS0 0x600
|
|
||||||
#define RK3588_PHYREF_ALT_GATE 0xc38
|
|
||||||
|
|
||||||
@@ -266,6 +244,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 +674,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
|
|
||||||
*/
|
|
||||||
@@ -1456,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,
|
|
||||||
@@ -1685,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,
|
|
||||||
@@ -1742,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,
|
|
||||||
@@ -1754,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,
|
|
||||||
@@ -1927,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,
|
|
||||||
@@ -2428,10 +2408,12 @@ 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),
|
|
||||||
+ 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),
|
|
||||||
@@ -2443,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),
|
|
||||||
@@ -2453,14 +2435,18 @@ 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__);
|
|
||||||
@@ -2473,6 +2459,7 @@ static void __init rk3588_clk_init(struc
|
|
||||||
iounmap(reg_base);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
+ early_ctx = ctx;
|
|
||||||
|
|
||||||
rockchip_clk_register_plls(ctx, rk3588_pll_clks,
|
|
||||||
ARRAY_SIZE(rk3588_pll_clks),
|
|
||||||
@@ -2491,54 +2478,53 @@ 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);
|
|
||||||
-
|
|
||||||
+ 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);
|
|
||||||
-}
|
|
||||||
-
|
|
||||||
-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,
|
|
||||||
-};
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
||||||
|
|
||||||
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 = {
|
|
||||||
+ .probe = clk_rk3588_probe,
|
|
||||||
.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);
|
|
||||||
+
|
|
||||||
+static int __init rockchip_clk_rk3588_drv_register(void)
|
|
||||||
+{
|
|
||||||
+ return platform_driver_register(&clk_rk3588_driver);
|
|
||||||
+}
|
|
||||||
+core_initcall(rockchip_clk_rk3588_drv_register);
|
|
||||||
--- a/drivers/clk/rockchip/clk.c
|
|
||||||
+++ b/drivers/clk/rockchip/clk.c
|
|
||||||
@@ -19,8 +19,12 @@
|
|
||||||
#include <linux/clk-provider.h>
|
|
||||||
#include <linux/io.h>
|
|
||||||
#include <linux/mfd/syscon.h>
|
|
||||||
+#include <linux/of_platform.h>
|
|
||||||
+#include <linux/pm_clock.h>
|
|
||||||
+#include <linux/pm_runtime.h>
|
|
||||||
#include <linux/regmap.h>
|
|
||||||
#include <linux/reboot.h>
|
|
||||||
+#include <linux/platform_device.h>
|
|
||||||
|
|
||||||
#include "../clk-fractional-divider.h"
|
|
||||||
#include "clk.h"
|
|
||||||
@@ -376,7 +380,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] = ERR_PTR(-EPROBE_DEFER);
|
|
||||||
|
|
||||||
ctx->reg_base = base;
|
|
||||||
ctx->clk_data.clks = clk_table;
|
|
||||||
@@ -446,6 +450,66 @@ unsigned long rockchip_clk_find_max_clk_
|
|
||||||
}
|
|
||||||
EXPORT_SYMBOL_GPL(rockchip_clk_find_max_clk_id);
|
|
||||||
|
|
||||||
+static struct platform_device *rockchip_clk_register_pdev(
|
|
||||||
+ struct platform_device *parent,
|
|
||||||
+ const char *name,
|
|
||||||
+ struct device_node *np)
|
|
||||||
+{
|
|
||||||
+ struct platform_device_info pdevinfo = {
|
|
||||||
+ .parent = &parent->dev,
|
|
||||||
+ .name = name,
|
|
||||||
+ .fwnode = of_fwnode_handle(np),
|
|
||||||
+ .of_node_reused = true,
|
|
||||||
+ };
|
|
||||||
+
|
|
||||||
+ return platform_device_register_full(&pdevinfo);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static struct clk *rockchip_clk_register_linked_gate(
|
|
||||||
+ struct rockchip_clk_provider *ctx,
|
|
||||||
+ struct rockchip_clk_branch *clkbr)
|
|
||||||
+{
|
|
||||||
+ struct clk *linked_clk = ctx->clk_data.clks[clkbr->linked_clk_id];
|
|
||||||
+ unsigned long flags = clkbr->flags | CLK_SET_RATE_PARENT;
|
|
||||||
+ struct device_node *np = ctx->cru_node;
|
|
||||||
+ struct platform_device *parent, *pdev;
|
|
||||||
+ struct device *dev = NULL;
|
|
||||||
+ int ret;
|
|
||||||
+
|
|
||||||
+ parent = of_find_device_by_node(np);
|
|
||||||
+ if (!parent) {
|
|
||||||
+ pr_err("failed to find device for %pOF\n", np);
|
|
||||||
+ goto exit;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ pdev = rockchip_clk_register_pdev(parent, clkbr->name, np);
|
|
||||||
+ put_device(&parent->dev);
|
|
||||||
+ if (!pdev) {
|
|
||||||
+ pr_err("failed to register device for clock %s\n", clkbr->name);
|
|
||||||
+ goto exit;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ dev = &pdev->dev;
|
|
||||||
+ pm_runtime_enable(dev);
|
|
||||||
+ ret = pm_clk_create(dev);
|
|
||||||
+ if (ret) {
|
|
||||||
+ pr_err("failed to create PM clock list for %s\n", clkbr->name);
|
|
||||||
+ goto exit;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ ret = pm_clk_add_clk(dev, linked_clk);
|
|
||||||
+ if (ret) {
|
|
||||||
+ pr_err("failed to setup linked clock for %s\n", clkbr->name);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+exit:
|
|
||||||
+ return 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);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
void rockchip_clk_register_branches(struct rockchip_clk_provider *ctx,
|
|
||||||
struct rockchip_clk_branch *list,
|
|
||||||
unsigned int nr_clk)
|
|
||||||
@@ -526,6 +590,9 @@ void rockchip_clk_register_branches(stru
|
|
||||||
ctx->reg_base + list->gate_offset,
|
|
||||||
list->gate_shift, list->gate_flags, &ctx->lock);
|
|
||||||
break;
|
|
||||||
+ case branch_linked_gate:
|
|
||||||
+ clk = rockchip_clk_register_linked_gate(ctx, list);
|
|
||||||
+ break;
|
|
||||||
case branch_composite:
|
|
||||||
clk = rockchip_clk_register_branch(list->name,
|
|
||||||
list->parent_names, list->num_parents,
|
|
||||||
--- 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;
|
|
||||||
};
|
|
||||||
|
|
||||||
@@ -838,6 +840,20 @@ struct rockchip_clk_branch {
|
|
||||||
.num_parents = 1, \
|
|
||||||
.flags = f, \
|
|
||||||
.gate_offset = o, \
|
|
||||||
+ .gate_shift = b, \
|
|
||||||
+ .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, \
|
|
||||||
}
|
|
||||||
Loading…
Reference in New Issue
Block a user