From: Jerome Brunet Date: Mon, 23 Jun 2025 16:37:37 +0000 (+0200) Subject: clk: amlogic: get regmap with clk_regmap_init X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=21ed19d1186314940d4300c39bf54fe0a410ee44;p=thirdparty%2Flinux.git clk: amlogic: get regmap with clk_regmap_init Add clk_regmap_init() and use it with all clock types which derive from clk_regmap. This helps initialise clk_regmap clocks without requiring tables to keep track of the clock using this type. The way it is done couples clk_regmap with the controllers, which is not ideal. This is a temporary solution to get rid of the tables. The situation will eventually be improved. Link: https://lore.kernel.org/r/20250623-amlogic-clk-drop-clk-regmap-tables-v4-1-ff04918211cc@baylibre.com Signed-off-by: Jerome Brunet --- diff --git a/drivers/clk/meson/Kconfig b/drivers/clk/meson/Kconfig index 5c669b2e2f268..7197d23543b8b 100644 --- a/drivers/clk/meson/Kconfig +++ b/drivers/clk/meson/Kconfig @@ -5,6 +5,7 @@ menu "Clock support for Amlogic platforms" config COMMON_CLK_MESON_REGMAP tristate select REGMAP + select MFD_SYSCON config COMMON_CLK_MESON_DUALDIV tristate diff --git a/drivers/clk/meson/clk-cpu-dyndiv.c b/drivers/clk/meson/clk-cpu-dyndiv.c index cb043b52b65d8..83aedbfd2891d 100644 --- a/drivers/clk/meson/clk-cpu-dyndiv.c +++ b/drivers/clk/meson/clk-cpu-dyndiv.c @@ -61,6 +61,7 @@ static int meson_clk_cpu_dyndiv_set_rate(struct clk_hw *hw, unsigned long rate, }; const struct clk_ops meson_clk_cpu_dyndiv_ops = { + .init = clk_regmap_init, .recalc_rate = meson_clk_cpu_dyndiv_recalc_rate, .determine_rate = meson_clk_cpu_dyndiv_determine_rate, .set_rate = meson_clk_cpu_dyndiv_set_rate, diff --git a/drivers/clk/meson/clk-dualdiv.c b/drivers/clk/meson/clk-dualdiv.c index c896cf29b318c..787df6cdf8416 100644 --- a/drivers/clk/meson/clk-dualdiv.c +++ b/drivers/clk/meson/clk-dualdiv.c @@ -126,6 +126,7 @@ static int meson_clk_dualdiv_set_rate(struct clk_hw *hw, unsigned long rate, } const struct clk_ops meson_clk_dualdiv_ops = { + .init = clk_regmap_init, .recalc_rate = meson_clk_dualdiv_recalc_rate, .determine_rate = meson_clk_dualdiv_determine_rate, .set_rate = meson_clk_dualdiv_set_rate, @@ -133,6 +134,7 @@ const struct clk_ops meson_clk_dualdiv_ops = { EXPORT_SYMBOL_NS_GPL(meson_clk_dualdiv_ops, "CLK_MESON"); const struct clk_ops meson_clk_dualdiv_ro_ops = { + .init = clk_regmap_init, .recalc_rate = meson_clk_dualdiv_recalc_rate, }; EXPORT_SYMBOL_NS_GPL(meson_clk_dualdiv_ro_ops, "CLK_MESON"); diff --git a/drivers/clk/meson/clk-mpll.c b/drivers/clk/meson/clk-mpll.c index ee91e32b4050b..7f8dada66e16f 100644 --- a/drivers/clk/meson/clk-mpll.c +++ b/drivers/clk/meson/clk-mpll.c @@ -128,6 +128,11 @@ static int mpll_init(struct clk_hw *hw) { struct clk_regmap *clk = to_clk_regmap(hw); struct meson_clk_mpll_data *mpll = meson_clk_mpll_data(clk); + int ret; + + ret = clk_regmap_init(hw); + if (ret) + return ret; if (mpll->init_count) regmap_multi_reg_write(clk->map, mpll->init_regs, @@ -151,6 +156,7 @@ static int mpll_init(struct clk_hw *hw) } const struct clk_ops meson_clk_mpll_ro_ops = { + .init = clk_regmap_init, .recalc_rate = mpll_recalc_rate, .determine_rate = mpll_determine_rate, }; diff --git a/drivers/clk/meson/clk-phase.c b/drivers/clk/meson/clk-phase.c index 7012111206107..58dd982e6878a 100644 --- a/drivers/clk/meson/clk-phase.c +++ b/drivers/clk/meson/clk-phase.c @@ -58,6 +58,7 @@ static int meson_clk_phase_set_phase(struct clk_hw *hw, int degrees) } const struct clk_ops meson_clk_phase_ops = { + .init = clk_regmap_init, .get_phase = meson_clk_phase_get_phase, .set_phase = meson_clk_phase_set_phase, }; @@ -83,6 +84,11 @@ static int meson_clk_triphase_sync(struct clk_hw *hw) struct clk_regmap *clk = to_clk_regmap(hw); struct meson_clk_triphase_data *tph = meson_clk_triphase_data(clk); unsigned int val; + int ret; + + ret = clk_regmap_init(hw); + if (ret) + return ret; /* Get phase 0 and sync it to phase 1 and 2 */ val = meson_parm_read(clk->map, &tph->ph0); @@ -142,6 +148,11 @@ static int meson_sclk_ws_inv_sync(struct clk_hw *hw) struct clk_regmap *clk = to_clk_regmap(hw); struct meson_sclk_ws_inv_data *tph = meson_sclk_ws_inv_data(clk); unsigned int val; + int ret; + + ret = clk_regmap_init(hw); + if (ret) + return ret; /* Get phase and sync the inverted value to ws */ val = meson_parm_read(clk->map, &tph->ph); diff --git a/drivers/clk/meson/clk-pll.c b/drivers/clk/meson/clk-pll.c index e8e53855b00a8..1ea6579a760f3 100644 --- a/drivers/clk/meson/clk-pll.c +++ b/drivers/clk/meson/clk-pll.c @@ -311,6 +311,11 @@ static int meson_clk_pll_init(struct clk_hw *hw) { struct clk_regmap *clk = to_clk_regmap(hw); struct meson_clk_pll_data *pll = meson_clk_pll_data(clk); + int ret; + + ret = clk_regmap_init(hw); + if (ret) + return ret; /* * Keep the clock running, which was already initialized and enabled @@ -468,6 +473,7 @@ static int meson_clk_pll_set_rate(struct clk_hw *hw, unsigned long rate, * the other ops except set_rate since the rate is fixed. */ const struct clk_ops meson_clk_pcie_pll_ops = { + .init = clk_regmap_init, .recalc_rate = meson_clk_pll_recalc_rate, .determine_rate = meson_clk_pll_determine_rate, .is_enabled = meson_clk_pll_is_enabled, @@ -488,6 +494,7 @@ const struct clk_ops meson_clk_pll_ops = { EXPORT_SYMBOL_NS_GPL(meson_clk_pll_ops, "CLK_MESON"); const struct clk_ops meson_clk_pll_ro_ops = { + .init = clk_regmap_init, .recalc_rate = meson_clk_pll_recalc_rate, .is_enabled = meson_clk_pll_is_enabled, }; diff --git a/drivers/clk/meson/clk-regmap.c b/drivers/clk/meson/clk-regmap.c index f3e504f675715..1ed56fe63caed 100644 --- a/drivers/clk/meson/clk-regmap.c +++ b/drivers/clk/meson/clk-regmap.c @@ -4,9 +4,52 @@ * Author: Jerome Brunet */ +#include #include +#include #include "clk-regmap.h" +int clk_regmap_init(struct clk_hw *hw) +{ + struct clk_regmap *clk = to_clk_regmap(hw); + struct device_node *np, *parent_np; + struct device *dev; + + /* Allow regmap to be preset as it was historically done */ + if (clk->map) + return 0; + + /* + * FIXME: what follows couples the controller implementation + * and clk_regmap clock type. This situation is not desirable + * but temporary, until the controller is able to register + * a hook to initialize a clock type + */ + + /* Check the usual dev enabled controller with an basic IO regmap */ + dev = clk_hw_get_dev(hw); + if (dev) { + clk->map = dev_get_regmap(dev, NULL); + if (clk->map) + return 0; + } + + /* Move on to early and syscon based controllers */ + np = clk_hw_get_of_node(hw); + if (np) { + parent_np = of_get_parent(np); + clk->map = syscon_node_to_regmap(parent_np); + of_node_put(parent_np); + + if (!IS_ERR_OR_NULL(clk->map)) + return 0; + } + + /* Bail out if regmap can't be found */ + return -EINVAL; +} +EXPORT_SYMBOL_NS_GPL(clk_regmap_init, "CLK_MESON"); + static int clk_regmap_gate_endisable(struct clk_hw *hw, int enable) { struct clk_regmap *clk = to_clk_regmap(hw); @@ -45,6 +88,7 @@ static int clk_regmap_gate_is_enabled(struct clk_hw *hw) } const struct clk_ops clk_regmap_gate_ops = { + .init = clk_regmap_init, .enable = clk_regmap_gate_enable, .disable = clk_regmap_gate_disable, .is_enabled = clk_regmap_gate_is_enabled, @@ -52,6 +96,7 @@ const struct clk_ops clk_regmap_gate_ops = { EXPORT_SYMBOL_NS_GPL(clk_regmap_gate_ops, "CLK_MESON"); const struct clk_ops clk_regmap_gate_ro_ops = { + .init = clk_regmap_init, .is_enabled = clk_regmap_gate_is_enabled, }; EXPORT_SYMBOL_NS_GPL(clk_regmap_gate_ro_ops, "CLK_MESON"); @@ -121,6 +166,7 @@ static int clk_regmap_div_set_rate(struct clk_hw *hw, unsigned long rate, /* Would prefer clk_regmap_div_ro_ops but clashes with qcom */ const struct clk_ops clk_regmap_divider_ops = { + .init = clk_regmap_init, .recalc_rate = clk_regmap_div_recalc_rate, .determine_rate = clk_regmap_div_determine_rate, .set_rate = clk_regmap_div_set_rate, @@ -128,6 +174,7 @@ const struct clk_ops clk_regmap_divider_ops = { EXPORT_SYMBOL_NS_GPL(clk_regmap_divider_ops, "CLK_MESON"); const struct clk_ops clk_regmap_divider_ro_ops = { + .init = clk_regmap_init, .recalc_rate = clk_regmap_div_recalc_rate, .determine_rate = clk_regmap_div_determine_rate, }; @@ -170,6 +217,7 @@ static int clk_regmap_mux_determine_rate(struct clk_hw *hw, } const struct clk_ops clk_regmap_mux_ops = { + .init = clk_regmap_init, .get_parent = clk_regmap_mux_get_parent, .set_parent = clk_regmap_mux_set_parent, .determine_rate = clk_regmap_mux_determine_rate, @@ -177,6 +225,7 @@ const struct clk_ops clk_regmap_mux_ops = { EXPORT_SYMBOL_NS_GPL(clk_regmap_mux_ops, "CLK_MESON"); const struct clk_ops clk_regmap_mux_ro_ops = { + .init = clk_regmap_init, .get_parent = clk_regmap_mux_get_parent, }; EXPORT_SYMBOL_NS_GPL(clk_regmap_mux_ro_ops, "CLK_MESON"); diff --git a/drivers/clk/meson/clk-regmap.h b/drivers/clk/meson/clk-regmap.h index e365312da54ec..f8cac2df5755b 100644 --- a/drivers/clk/meson/clk-regmap.h +++ b/drivers/clk/meson/clk-regmap.h @@ -7,6 +7,7 @@ #ifndef __CLK_REGMAP_H #define __CLK_REGMAP_H +#include #include #include @@ -31,6 +32,9 @@ static inline struct clk_regmap *to_clk_regmap(struct clk_hw *hw) return container_of(hw, struct clk_regmap, hw); } +/* clk_regmap init op to get and cache regmap from the controllers */ +int clk_regmap_init(struct clk_hw *hw); + /** * struct clk_regmap_gate_data - regmap backed gate specific data * diff --git a/drivers/clk/meson/sclk-div.c b/drivers/clk/meson/sclk-div.c index 9c4945234f268..4ba3d82810e8f 100644 --- a/drivers/clk/meson/sclk-div.c +++ b/drivers/clk/meson/sclk-div.c @@ -222,6 +222,11 @@ static int sclk_div_init(struct clk_hw *hw) struct clk_regmap *clk = to_clk_regmap(hw); struct meson_sclk_div_data *sclk = meson_sclk_div_data(clk); unsigned int val; + int ret; + + ret = clk_regmap_init(hw); + if (ret) + return ret; val = meson_parm_read(clk->map, &sclk->div); diff --git a/drivers/clk/meson/vclk.c b/drivers/clk/meson/vclk.c index 6a167ebdc8d74..009bd11930427 100644 --- a/drivers/clk/meson/vclk.c +++ b/drivers/clk/meson/vclk.c @@ -45,6 +45,7 @@ static int meson_vclk_gate_is_enabled(struct clk_hw *hw) } const struct clk_ops meson_vclk_gate_ops = { + .init = clk_regmap_init, .enable = meson_vclk_gate_enable, .disable = meson_vclk_gate_disable, .is_enabled = meson_vclk_gate_is_enabled, @@ -127,6 +128,7 @@ static int meson_vclk_div_is_enabled(struct clk_hw *hw) } const struct clk_ops meson_vclk_div_ops = { + .init = clk_regmap_init, .recalc_rate = meson_vclk_div_recalc_rate, .determine_rate = meson_vclk_div_determine_rate, .set_rate = meson_vclk_div_set_rate, diff --git a/drivers/clk/meson/vid-pll-div.c b/drivers/clk/meson/vid-pll-div.c index 965ed7281f57e..2a3cdbe6d86a8 100644 --- a/drivers/clk/meson/vid-pll-div.c +++ b/drivers/clk/meson/vid-pll-div.c @@ -90,6 +90,7 @@ static unsigned long meson_vid_pll_div_recalc_rate(struct clk_hw *hw, } const struct clk_ops meson_vid_pll_div_ro_ops = { + .init = clk_regmap_init, .recalc_rate = meson_vid_pll_div_recalc_rate, }; EXPORT_SYMBOL_NS_GPL(meson_vid_pll_div_ro_ops, "CLK_MESON");