]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
clk: amlogic: get regmap with clk_regmap_init
authorJerome Brunet <jbrunet@baylibre.com>
Mon, 23 Jun 2025 16:37:37 +0000 (18:37 +0200)
committerJerome Brunet <jbrunet@baylibre.com>
Wed, 2 Jul 2025 13:38:19 +0000 (15:38 +0200)
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 <jbrunet@baylibre.com>
drivers/clk/meson/Kconfig
drivers/clk/meson/clk-cpu-dyndiv.c
drivers/clk/meson/clk-dualdiv.c
drivers/clk/meson/clk-mpll.c
drivers/clk/meson/clk-phase.c
drivers/clk/meson/clk-pll.c
drivers/clk/meson/clk-regmap.c
drivers/clk/meson/clk-regmap.h
drivers/clk/meson/sclk-div.c
drivers/clk/meson/vclk.c
drivers/clk/meson/vid-pll-div.c

index 5c669b2e2f268c7608c8d9c64bba3c5b54da39b2..7197d23543b8bb8a9020cde316170b50bc359a6c 100644 (file)
@@ -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
index cb043b52b65d8a6ae0933935f07fb14c40855700..83aedbfd2891d1099d4fb5e25d2306a8328f29db 100644 (file)
@@ -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,
index c896cf29b318ca3debf7447a9c44be01523abe47..787df6cdf841641982f20eed7dd276669e7b7b6e 100644 (file)
@@ -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");
index ee91e32b4050bf40cf6f19c8152ae11c2ab4ec11..7f8dada66e16fd33cb5d0e628577c39fba5e4e25 100644 (file)
@@ -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,
 };
index 7012111206107a25ca77a5c51cb5b19d9755f3c1..58dd982e6878afd481cdf6634f70a69d5d2b5e5b 100644 (file)
@@ -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);
index e8e53855b00a81bc8eaa4213173948c964debc8a..1ea6579a760f35fd669b5e7260df8edfa083bf29 100644 (file)
@@ -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,
 };
index f3e504f6757152868e60d5a9fac5c5e5bf3e2e56..1ed56fe63caedc16a332b28f211d8b0a7663aaa5 100644 (file)
@@ -4,9 +4,52 @@
  * Author: Jerome Brunet <jbrunet@baylibre.com>
  */
 
+#include <linux/device.h>
 #include <linux/module.h>
+#include <linux/mfd/syscon.h>
 #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");
index e365312da54ece08098293b1a831c803415db814..f8cac2df5755b0f894570305604485f54c17ea49 100644 (file)
@@ -7,6 +7,7 @@
 #ifndef __CLK_REGMAP_H
 #define __CLK_REGMAP_H
 
+#include <linux/device.h>
 #include <linux/clk-provider.h>
 #include <linux/regmap.h>
 
@@ -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
  *
index 9c4945234f2682ea4c4e9c2fc2158fe37dc46f74..4ba3d82810e8f2f456c349b3e56e6b48e1c7290b 100644 (file)
@@ -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);
 
index 6a167ebdc8d74b9e5371100c6461ae395b7cc8af..009bd11930427f1f6465bf70acc35cd7de68d358 100644 (file)
@@ -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,
index 965ed7281f57edf3c5d550dfdbe0c61b016e4684..2a3cdbe6d86a828a31724c49c59e300ec5b1fa54 100644 (file)
@@ -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");