mirror of
https://github.com/openwrt/openwrt.git
synced 2024-12-25 16:31:13 +00:00
133 lines
3.8 KiB
Diff
133 lines
3.8 KiB
Diff
|
From 126560c909f38f00c08dd5f35f50c981d5e25e1f Mon Sep 17 00:00:00 2001
|
||
|
From: Nick Hollinghurst <nick.hollinghurst@raspberrypi.com>
|
||
|
Date: Fri, 10 May 2024 15:30:44 +0100
|
||
|
Subject: [PATCH 1177/1215] clk: clk-rp1: Add "varsrc" clocks to represent MIPI
|
||
|
byte clocks
|
||
|
|
||
|
Add a new class of clocks to RP1 to represent clock sources whose
|
||
|
frequency changes at run-time as a side-effect of some other driver.
|
||
|
Specifically this is for the two MIPI DSI byte-clock sources.
|
||
|
|
||
|
Signed-off-by: Nick Hollinghurst <nick.hollinghurst@raspberrypi.com>
|
||
|
---
|
||
|
drivers/clk/clk-rp1.c | 73 +++++++++++++++++++++++++++++++++++++++++++
|
||
|
1 file changed, 73 insertions(+)
|
||
|
|
||
|
--- a/drivers/clk/clk-rp1.c
|
||
|
+++ b/drivers/clk/clk-rp1.c
|
||
|
@@ -394,6 +394,11 @@ struct rp1_clock {
|
||
|
unsigned long cached_rate;
|
||
|
};
|
||
|
|
||
|
+struct rp1_varsrc {
|
||
|
+ struct clk_hw hw;
|
||
|
+ struct rp1_clockman *clockman;
|
||
|
+ unsigned long rate;
|
||
|
+};
|
||
|
|
||
|
struct rp1_clk_change {
|
||
|
struct clk_hw *hw;
|
||
|
@@ -1414,6 +1419,34 @@ static void rp1_clk_debug_init(struct cl
|
||
|
rp1_debugfs_regset(clockman, 0, regs, i, dentry);
|
||
|
}
|
||
|
|
||
|
+static int rp1_varsrc_set_rate(struct clk_hw *hw,
|
||
|
+ unsigned long rate, unsigned long parent_rate)
|
||
|
+{
|
||
|
+ struct rp1_varsrc *varsrc = container_of(hw, struct rp1_varsrc, hw);
|
||
|
+
|
||
|
+ /*
|
||
|
+ * "varsrc" exists purely to let clock dividers know the frequency
|
||
|
+ * of an externally-managed clock source (such as MIPI DSI byte-clock)
|
||
|
+ * which may change at run-time as a side-effect of some other driver.
|
||
|
+ */
|
||
|
+ varsrc->rate = rate;
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+static unsigned long rp1_varsrc_recalc_rate(struct clk_hw *hw,
|
||
|
+ unsigned long parent_rate)
|
||
|
+{
|
||
|
+ struct rp1_varsrc *varsrc = container_of(hw, struct rp1_varsrc, hw);
|
||
|
+
|
||
|
+ return varsrc->rate;
|
||
|
+}
|
||
|
+
|
||
|
+static long rp1_varsrc_round_rate(struct clk_hw *hw, unsigned long rate,
|
||
|
+ unsigned long *parent_rate)
|
||
|
+{
|
||
|
+ return rate;
|
||
|
+}
|
||
|
+
|
||
|
static const struct clk_ops rp1_pll_core_ops = {
|
||
|
.is_prepared = rp1_pll_core_is_on,
|
||
|
.prepare = rp1_pll_core_on,
|
||
|
@@ -1464,6 +1497,12 @@ static const struct clk_ops rp1_clk_ops
|
||
|
.debug_init = rp1_clk_debug_init,
|
||
|
};
|
||
|
|
||
|
+static const struct clk_ops rp1_varsrc_ops = {
|
||
|
+ .set_rate = rp1_varsrc_set_rate,
|
||
|
+ .recalc_rate = rp1_varsrc_recalc_rate,
|
||
|
+ .round_rate = rp1_varsrc_round_rate,
|
||
|
+};
|
||
|
+
|
||
|
static bool rp1_clk_is_claimed(const char *name);
|
||
|
|
||
|
static struct clk_hw *rp1_register_pll_core(struct rp1_clockman *clockman,
|
||
|
@@ -1647,6 +1686,35 @@ static struct clk_hw *rp1_register_clock
|
||
|
return &clock->hw;
|
||
|
}
|
||
|
|
||
|
+static struct clk_hw *rp1_register_varsrc(struct rp1_clockman *clockman,
|
||
|
+ const void *data)
|
||
|
+{
|
||
|
+ const char *name = *(char const * const *)data;
|
||
|
+ struct rp1_varsrc *clock;
|
||
|
+ struct clk_init_data init;
|
||
|
+ int ret;
|
||
|
+
|
||
|
+ memset(&init, 0, sizeof(init));
|
||
|
+ init.parent_names = &ref_clock;
|
||
|
+ init.num_parents = 1;
|
||
|
+ init.name = name;
|
||
|
+ init.flags = CLK_IGNORE_UNUSED;
|
||
|
+ init.ops = &rp1_varsrc_ops;
|
||
|
+
|
||
|
+ clock = devm_kzalloc(clockman->dev, sizeof(*clock), GFP_KERNEL);
|
||
|
+ if (!clock)
|
||
|
+ return NULL;
|
||
|
+
|
||
|
+ clock->clockman = clockman;
|
||
|
+ clock->hw.init = &init;
|
||
|
+
|
||
|
+ ret = devm_clk_hw_register(clockman->dev, &clock->hw);
|
||
|
+ if (ret)
|
||
|
+ return ERR_PTR(ret);
|
||
|
+
|
||
|
+ return &clock->hw;
|
||
|
+}
|
||
|
+
|
||
|
struct rp1_clk_desc {
|
||
|
struct clk_hw *(*clk_register)(struct rp1_clockman *clockman,
|
||
|
const void *data);
|
||
|
@@ -1676,6 +1744,8 @@ struct rp1_clk_desc {
|
||
|
&(struct rp1_clock_data) \
|
||
|
{__VA_ARGS__})
|
||
|
|
||
|
+#define REGISTER_VARSRC(n) _REGISTER(&rp1_register_varsrc, &(const char *){n})
|
||
|
+
|
||
|
static const struct rp1_clk_desc clk_desc_array[] = {
|
||
|
[RP1_PLL_SYS_CORE] = REGISTER_PLL_CORE(
|
||
|
.name = "pll_sys_core",
|
||
|
@@ -2318,6 +2388,9 @@ static const struct rp1_clk_desc clk_des
|
||
|
.max_freq = 200 * MHz,
|
||
|
.fc0_src = FC_NUM(3, 6),
|
||
|
),
|
||
|
+
|
||
|
+ [RP1_CLK_MIPI0_DSI_BYTECLOCK] = REGISTER_VARSRC("clksrc_mipi0_dsi_byteclk"),
|
||
|
+ [RP1_CLK_MIPI1_DSI_BYTECLOCK] = REGISTER_VARSRC("clksrc_mipi1_dsi_byteclk"),
|
||
|
};
|
||
|
|
||
|
static bool rp1_clk_claimed[ARRAY_SIZE(clk_desc_array)];
|