rockchip: import pending clk patches for rk3588
Signed-off-by: Tianling Shen <cnsztl@immortalwrt.org>
This commit is contained in:
@@ -0,0 +1,33 @@
|
||||
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,6 +1,6 @@
|
||||
From 80094450f857ce8e5e00c1952f072eede3902f64 Mon Sep 17 00:00:00 2001
|
||||
From b55f69688803c3c7d8fd51d8c833002591dd271b Mon Sep 17 00:00:00 2001
|
||||
From: Sebastian Reichel <sebastian.reichel@collabora.com>
|
||||
Date: Thu, 18 May 2023 05:19:48 +0200
|
||||
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
|
||||
@@ -19,16 +19,14 @@ 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 introducing a new helper, which avoids the overflow
|
||||
by using a modulo operation instead of math tricks. This avoids
|
||||
any requirements on the arguments (except that divisor should not
|
||||
be 0 obviously).
|
||||
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 +++---
|
||||
include/linux/math.h | 11 +++++++++++
|
||||
2 files changed, 14 insertions(+), 3 deletions(-)
|
||||
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
|
||||
@@ -59,23 +57,3 @@ Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
|
||||
|
||||
if (!_is_valid_div(table, div, flags))
|
||||
return -EINVAL;
|
||||
--- 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; })
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
From a5946bf5ce48ed73fffb1542be606e7b8659b017 Mon Sep 17 00:00:00 2001
|
||||
From: Sebastian Reichel <sebastian.reichel@collabora.com>
|
||||
Date: Wed, 13 Dec 2023 18:58:43 +0100
|
||||
Subject: [PATCH] clk: rockchip: rk3588: fix CLK_NR_CLKS usage
|
||||
|
||||
CLK_NR_CLKS is not part of the DT bindings and needs to be removed
|
||||
from it, just like it recently happened for other platforms. This
|
||||
takes care of it by introducing a new function identifying the
|
||||
maximum used clock ID at runtime.
|
||||
|
||||
Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
|
||||
---
|
||||
drivers/clk/rockchip/clk-rk3588.c | 5 ++++-
|
||||
drivers/clk/rockchip/clk.c | 17 +++++++++++++++++
|
||||
drivers/clk/rockchip/clk.h | 2 ++
|
||||
3 files changed, 23 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/clk/rockchip/clk-rk3588.c
|
||||
+++ b/drivers/clk/rockchip/clk-rk3588.c
|
||||
@@ -2458,15 +2458,18 @@ static struct rockchip_clk_branch rk3588
|
||||
static void __init rk3588_clk_init(struct device_node *np)
|
||||
{
|
||||
struct rockchip_clk_provider *ctx;
|
||||
+ unsigned long clk_nr_clks;
|
||||
void __iomem *reg_base;
|
||||
|
||||
+ clk_nr_clks = rockchip_clk_find_max_clk_id(rk3588_clk_branches,
|
||||
+ ARRAY_SIZE(rk3588_clk_branches)) + 1;
|
||||
reg_base = of_iomap(np, 0);
|
||||
if (!reg_base) {
|
||||
pr_err("%s: could not map cru region\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
- ctx = rockchip_clk_init(np, reg_base, CLK_NR_CLKS);
|
||||
+ ctx = rockchip_clk_init(np, reg_base, clk_nr_clks);
|
||||
if (IS_ERR(ctx)) {
|
||||
pr_err("%s: rockchip clk init failed\n", __func__);
|
||||
iounmap(reg_base);
|
||||
--- a/drivers/clk/rockchip/clk.c
|
||||
+++ b/drivers/clk/rockchip/clk.c
|
||||
@@ -430,6 +430,23 @@ void rockchip_clk_register_plls(struct r
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rockchip_clk_register_plls);
|
||||
|
||||
+unsigned long rockchip_clk_find_max_clk_id(struct rockchip_clk_branch *list,
|
||||
+ unsigned int nr_clk)
|
||||
+{
|
||||
+ unsigned int idx;
|
||||
+ unsigned long max;
|
||||
+
|
||||
+ for (idx = 0; idx < nr_clk; idx++, list++) {
|
||||
+ if (list->id > max)
|
||||
+ max = list->id;
|
||||
+ if (list->child && list->child->id > max)
|
||||
+ max = list->id;
|
||||
+ }
|
||||
+
|
||||
+ return max;
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(rockchip_clk_find_max_clk_id);
|
||||
+
|
||||
void rockchip_clk_register_branches(struct rockchip_clk_provider *ctx,
|
||||
struct rockchip_clk_branch *list,
|
||||
unsigned int nr_clk)
|
||||
--- a/drivers/clk/rockchip/clk.h
|
||||
+++ b/drivers/clk/rockchip/clk.h
|
||||
@@ -973,6 +973,8 @@ struct rockchip_clk_provider *rockchip_c
|
||||
void __iomem *base, unsigned long nr_clks);
|
||||
void rockchip_clk_of_add_provider(struct device_node *np,
|
||||
struct rockchip_clk_provider *ctx);
|
||||
+unsigned long rockchip_clk_find_max_clk_id(struct rockchip_clk_branch *list,
|
||||
+ unsigned int nr_clk);
|
||||
void rockchip_clk_register_branches(struct rockchip_clk_provider *ctx,
|
||||
struct rockchip_clk_branch *list,
|
||||
unsigned int nr_clk);
|
||||
@@ -0,0 +1,23 @@
|
||||
From fb7ba4ede6ab6c37bc1146f7fa1f07a7810439ab Mon Sep 17 00:00:00 2001
|
||||
From: Sebastian Reichel <sebastian.reichel@collabora.com>
|
||||
Date: Wed, 13 Dec 2023 19:02:57 +0100
|
||||
Subject: [PATCH] dt-bindings: clock: rk3588: add missing PCLK_VO1GRF
|
||||
|
||||
Add PCLK_VO1GRF to complement PCLK_VO0GRF. This will be needed
|
||||
for HDMI support.
|
||||
|
||||
Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
|
||||
---
|
||||
include/dt-bindings/clock/rockchip,rk3588-cru.h | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
--- a/include/dt-bindings/clock/rockchip,rk3588-cru.h
|
||||
+++ b/include/dt-bindings/clock/rockchip,rk3588-cru.h
|
||||
@@ -733,6 +733,7 @@
|
||||
#define ACLK_AV1_PRE 718
|
||||
#define PCLK_AV1_PRE 719
|
||||
#define HCLK_SDIO_PRE 720
|
||||
+#define PCLK_VO1GRF 721
|
||||
|
||||
#define CLK_NR_CLKS (HCLK_SDIO_PRE + 1)
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
From a8dc483b1653a2b99f9b63803b4575ba4a91d8d8 Mon Sep 17 00:00:00 2001
|
||||
From 8824bba8426bab1a05b2f285283bc0e99de678d1 Mon Sep 17 00:00:00 2001
|
||||
From: Sebastian Reichel <sebastian.reichel@collabora.com>
|
||||
Date: Tue, 13 Jun 2023 16:45:05 +0200
|
||||
Date: Wed, 13 Dec 2023 19:06:30 +0100
|
||||
Subject: [PATCH] clk: rockchip: rk3588: fix pclk_vo0grf and pclk_vo1grf
|
||||
|
||||
Currently pclk_vo1grf is not exposed, but it should be referenced
|
||||
from the vo1_grf syscon, which needs it enabled. That syscon will
|
||||
be required for HDMI-RX functionality among other things.
|
||||
from the vo1_grf syscon, which needs it enabled. That syscon is
|
||||
required for HDMI RX and TX functionality among other things.
|
||||
|
||||
Apart from that pclk_vo0grf and pclk_vo1grf are both linked gates
|
||||
and need the VO's hclk enabled in addition to their parent clock.
|
||||
@@ -15,9 +15,8 @@ is not yet upstream anyways.
|
||||
|
||||
Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
|
||||
---
|
||||
drivers/clk/rockchip/clk-rk3588.c | 11 +++++------
|
||||
include/dt-bindings/clock/rockchip,rk3588-cru.h | 3 ++-
|
||||
2 files changed, 7 insertions(+), 7 deletions(-)
|
||||
drivers/clk/rockchip/clk-rk3588.c | 10 ++++------
|
||||
1 file changed, 4 insertions(+), 6 deletions(-)
|
||||
|
||||
--- a/drivers/clk/rockchip/clk-rk3588.c
|
||||
+++ b/drivers/clk/rockchip/clk-rk3588.c
|
||||
@@ -39,7 +38,7 @@ Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
|
||||
GATE(PCLK_S_EDP0, "pclk_s_edp0", "pclk_vo1_s_root", 0,
|
||||
RK3588_CLKGATE_CON(59), 14, GFLAGS),
|
||||
GATE(PCLK_S_EDP1, "pclk_s_edp1", "pclk_vo1_s_root", 0,
|
||||
@@ -2447,12 +2443,15 @@ static struct rockchip_clk_branch rk3588
|
||||
@@ -2447,12 +2443,14 @@ 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),
|
||||
@@ -53,20 +52,6 @@ Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
|
||||
GATE_LINK(HCLK_SDIO_PRE, "hclk_sdio_pre", "hclk_sdio_root", "hclk_nvm", 0, RK3588_CLKGATE_CON(75), 1, GFLAGS),
|
||||
+ GATE_LINK(PCLK_VO0GRF, "pclk_vo0grf", "pclk_vo0_root", "hclk_vo0", CLK_IGNORE_UNUSED, RK3588_CLKGATE_CON(55), 10, GFLAGS),
|
||||
+ 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)
|
||||
--- a/include/dt-bindings/clock/rockchip,rk3588-cru.h
|
||||
+++ b/include/dt-bindings/clock/rockchip,rk3588-cru.h
|
||||
@@ -733,8 +733,9 @@
|
||||
#define ACLK_AV1_PRE 718
|
||||
#define PCLK_AV1_PRE 719
|
||||
#define HCLK_SDIO_PRE 720
|
||||
+#define PCLK_VO1GRF 721
|
||||
|
||||
-#define CLK_NR_CLKS (HCLK_SDIO_PRE + 1)
|
||||
+#define CLK_NR_CLKS (PCLK_VO1GRF + 1)
|
||||
|
||||
/* scmi-clocks indices */
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
From 1d45059214265717c8bc1fd32b966896e91ec51d Mon Sep 17 00:00:00 2001
|
||||
From: Sebastian Reichel <sebastian.reichel@collabora.com>
|
||||
Date: Tue, 21 Nov 2023 17:52:54 +0100
|
||||
Subject: [PATCH] clk: rockchip: rk3588: fix indent
|
||||
|
||||
pclk_mailbox2 is the only RK3588 clock indented with one tab instead of
|
||||
two tabs. Let's fix this.
|
||||
|
||||
Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
|
||||
---
|
||||
drivers/clk/rockchip/clk-rk3588.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/clk/rockchip/clk-rk3588.c
|
||||
+++ b/drivers/clk/rockchip/clk-rk3588.c
|
||||
@@ -1004,7 +1004,7 @@ static struct rockchip_clk_branch rk3588
|
||||
GATE(PCLK_MAILBOX1, "pclk_mailbox1", "pclk_top_root", 0,
|
||||
RK3588_CLKGATE_CON(16), 12, GFLAGS),
|
||||
GATE(PCLK_MAILBOX2, "pclk_mailbox2", "pclk_top_root", 0,
|
||||
- RK3588_CLKGATE_CON(16), 13, GFLAGS),
|
||||
+ RK3588_CLKGATE_CON(16), 13, GFLAGS),
|
||||
GATE(PCLK_PMU2, "pclk_pmu2", "pclk_top_root", CLK_IS_CRITICAL,
|
||||
RK3588_CLKGATE_CON(19), 3, GFLAGS),
|
||||
GATE(PCLK_PMUCM0_INTMUX, "pclk_pmucm0_intmux", "pclk_top_root", CLK_IS_CRITICAL,
|
||||
@@ -0,0 +1,76 @@
|
||||
From 923c6fa62da49b895fc110e2bad8d6e812b37d1a Mon Sep 17 00:00:00 2001
|
||||
From: Sebastian Reichel <sebastian.reichel@collabora.com>
|
||||
Date: Wed, 22 Nov 2023 19:23:13 +0100
|
||||
Subject: [PATCH] clk: rockchip: rk3588: use linked clock ID for GATE_LINK
|
||||
|
||||
In preparation for properly supporting GATE_LINK switch the unused
|
||||
linked clock argument from the clock's name to its ID. This allows
|
||||
easy and fast lookup of the 'struct clk'.
|
||||
|
||||
Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
|
||||
---
|
||||
drivers/clk/rockchip/clk-rk3588.c | 46 +++++++++++++++----------------
|
||||
1 file changed, 23 insertions(+), 23 deletions(-)
|
||||
|
||||
--- a/drivers/clk/rockchip/clk-rk3588.c
|
||||
+++ b/drivers/clk/rockchip/clk-rk3588.c
|
||||
@@ -29,7 +29,7 @@
|
||||
* power, but avoids leaking implementation details into DT or hanging the
|
||||
* system.
|
||||
*/
|
||||
-#define GATE_LINK(_id, cname, pname, linkname, f, o, b, gf) \
|
||||
+#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
|
||||
|
||||
@@ -2429,28 +2429,28 @@ static struct rockchip_clk_branch rk3588
|
||||
GATE(ACLK_AV1, "aclk_av1", "aclk_av1_pre", 0,
|
||||
RK3588_CLKGATE_CON(68), 2, GFLAGS),
|
||||
|
||||
- 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(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),
|
||||
- GATE_LINK(ACLK_VDPU_LOW_PRE, "aclk_vdpu_low_pre", "aclk_vdpu_low_root", "aclk_vdpu_root", 0, RK3588_CLKGATE_CON(44), 5, GFLAGS),
|
||||
- GATE_LINK(ACLK_RKVENC1_PRE, "aclk_rkvenc1_pre", "aclk_rkvenc1_root", "aclk_rkvenc0", 0, RK3588_CLKGATE_CON(48), 3, GFLAGS),
|
||||
- GATE_LINK(HCLK_RKVENC1_PRE, "hclk_rkvenc1_pre", "hclk_rkvenc1_root", "hclk_rkvenc0", 0, RK3588_CLKGATE_CON(48), 2, GFLAGS),
|
||||
- GATE_LINK(HCLK_RKVDEC0_PRE, "hclk_rkvdec0_pre", "hclk_rkvdec0_root", "hclk_vdpu_root", 0, RK3588_CLKGATE_CON(40), 5, GFLAGS),
|
||||
- GATE_LINK(ACLK_RKVDEC0_PRE, "aclk_rkvdec0_pre", "aclk_rkvdec0_root", "aclk_vdpu_root", 0, RK3588_CLKGATE_CON(40), 6, GFLAGS),
|
||||
- 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(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(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),
|
||||
- GATE_LINK(PCLK_VO0GRF, "pclk_vo0grf", "pclk_vo0_root", "hclk_vo0", CLK_IGNORE_UNUSED, RK3588_CLKGATE_CON(55), 10, GFLAGS),
|
||||
- GATE_LINK(PCLK_VO1GRF, "pclk_vo1grf", "pclk_vo1_root", "hclk_vo1", CLK_IGNORE_UNUSED, RK3588_CLKGATE_CON(59), 12, GFLAGS),
|
||||
+ 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(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),
|
||||
+ GATE_LINK(ACLK_VDPU_LOW_PRE, "aclk_vdpu_low_pre", "aclk_vdpu_low_root", ACLK_VDPU_ROOT, 0, RK3588_CLKGATE_CON(44), 5, GFLAGS),
|
||||
+ GATE_LINK(ACLK_RKVENC1_PRE, "aclk_rkvenc1_pre", "aclk_rkvenc1_root", ACLK_RKVENC0, 0, RK3588_CLKGATE_CON(48), 3, GFLAGS),
|
||||
+ GATE_LINK(HCLK_RKVENC1_PRE, "hclk_rkvenc1_pre", "hclk_rkvenc1_root", HCLK_RKVENC0, 0, RK3588_CLKGATE_CON(48), 2, GFLAGS),
|
||||
+ GATE_LINK(HCLK_RKVDEC0_PRE, "hclk_rkvdec0_pre", "hclk_rkvdec0_root", HCLK_VDPU_ROOT, 0, RK3588_CLKGATE_CON(40), 5, GFLAGS),
|
||||
+ GATE_LINK(ACLK_RKVDEC0_PRE, "aclk_rkvdec0_pre", "aclk_rkvdec0_root", ACLK_VDPU_ROOT, 0, RK3588_CLKGATE_CON(40), 6, GFLAGS),
|
||||
+ 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(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(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),
|
||||
+ GATE_LINK(PCLK_VO0GRF, "pclk_vo0grf", "pclk_vo0_root", HCLK_VO0, CLK_IGNORE_UNUSED, RK3588_CLKGATE_CON(55), 10, GFLAGS),
|
||||
+ 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)
|
||||
@@ -0,0 +1,422 @@
|
||||
From 42987730c377951c90e9cfe55652e812db4a9ac9 Mon Sep 17 00:00:00 2001
|
||||
From: Sebastian Reichel <sebastian.reichel@collabora.com>
|
||||
Date: Thu, 23 Nov 2023 17:58:21 +0100
|
||||
Subject: [PATCH] clk: rockchip: implement proper GATE_LINK support
|
||||
|
||||
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,9 +19,13 @@
|
||||
#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/rational.h>
|
||||
+#include <linux/platform_device.h>
|
||||
|
||||
#include "../clk-fractional-divider.h"
|
||||
#include "clk.h"
|
||||
@@ -377,7 +381,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;
|
||||
@@ -447,6 +451,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)
|
||||
@@ -527,6 +591,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, \
|
||||
}
|
||||
Reference in New Issue
Block a user