clk: ti: Improve clksel clock bit parsing for reg property
authorTony Lindgren <tony@atomide.com>
Tue, 13 Feb 2024 10:48:52 +0000 (12:48 +0200)
committerTony Lindgren <tony@atomide.com>
Mon, 26 Feb 2024 11:08:45 +0000 (13:08 +0200)
Because of legacy reasons, the TI clksel composite clocks can have
overlapping reg properties, and use a custom ti,bit-shift property.

For the clksel clocks we can start using of the standard reg property
instead of the custom ti,bit-shift property.

To do this, let's add a ti_clk_get_legacy_bit_shift() helper, and make
ti_clk_get_reg_addr() populate the clock bit offset.

This makes it possible to update the devicetree files to use the reg
property one clock at a time.

Acked-by: Stephen Boyd <sboyd@kernel.org>
Signed-off-by: Tony Lindgren <tony@atomide.com>
drivers/clk/ti/apll.c
drivers/clk/ti/clk.c
drivers/clk/ti/clock.h
drivers/clk/ti/divider.c
drivers/clk/ti/gate.c
drivers/clk/ti/interface.c
drivers/clk/ti/mux.c
include/linux/clk/ti.h

index 93183287c58db78cad885de7ae96a058705da817..43514e6f3b78001a64984e75ba3bd55d8740fdae 100644 (file)
@@ -376,14 +376,9 @@ static void __init of_omap2_apll_setup(struct device_node *node)
        }
        clk_hw->fixed_rate = val;
 
-       if (of_property_read_u32(node, "ti,bit-shift", &val)) {
-               pr_err("%pOFn missing bit-shift\n", node);
-               goto cleanup;
-       }
-
-       clk_hw->enable_bit = val;
-       ad->enable_mask = 0x3 << val;
-       ad->autoidle_mask = 0x3 << val;
+       clk_hw->enable_bit = ti_clk_get_legacy_bit_shift(node);
+       ad->enable_mask = 0x3 << clk_hw->enable_bit;
+       ad->autoidle_mask = 0x3 << clk_hw->enable_bit;
 
        if (of_property_read_u32(node, "ti,idlest-shift", &val)) {
                pr_err("%pOFn missing idlest-shift\n", node);
index 53173bb250da9f4170c36831ea9ec167ddb5068a..f2117fef7c7d66e9ff7cfecbd63e814c99550d3e 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/list.h>
+#include <linux/minmax.h>
 #include <linux/regmap.h>
 #include <linux/string_helpers.h>
 #include <linux/memblock.h>
@@ -307,8 +308,9 @@ int __init ti_clk_retry_init(struct device_node *node, void *user,
 int ti_clk_get_reg_addr(struct device_node *node, int index,
                        struct clk_omap_reg *reg)
 {
-       u32 val;
-       int i;
+       u32 clksel_addr, val;
+       bool is_clksel = false;
+       int i, err;
 
        for (i = 0; i < CLK_MAX_MEMMAPS; i++) {
                if (clocks_node_ptr[i] == node->parent)
@@ -324,21 +326,62 @@ int ti_clk_get_reg_addr(struct device_node *node, int index,
 
        reg->index = i;
 
-       if (of_property_read_u32_index(node, "reg", index, &val)) {
-               if (of_property_read_u32_index(node->parent, "reg",
-                                              index, &val)) {
-                       pr_err("%pOFn or parent must have reg[%d]!\n",
-                              node, index);
+       if (of_device_is_compatible(node->parent, "ti,clksel")) {
+               err = of_property_read_u32_index(node->parent, "reg", index, &clksel_addr);
+               if (err) {
+                       pr_err("%pOFn parent clksel must have reg[%d]!\n", node, index);
                        return -EINVAL;
                }
+               is_clksel = true;
+       }
+
+       err = of_property_read_u32_index(node, "reg", index, &val);
+       if (err && is_clksel) {
+               /* Legacy clksel with no reg and a possible ti,bit-shift property */
+               reg->offset = clksel_addr;
+               reg->bit = ti_clk_get_legacy_bit_shift(node);
+               reg->ptr = NULL;
+
+               return 0;
        }
 
+       /* Updated clksel clock with a proper reg property */
+       if (is_clksel) {
+               reg->offset = clksel_addr;
+               reg->bit = val;
+               reg->ptr = NULL;
+               return 0;
+       }
+
+       /* Other clocks that may or may not have ti,bit-shift property  */
        reg->offset = val;
+       reg->bit = ti_clk_get_legacy_bit_shift(node);
        reg->ptr = NULL;
 
        return 0;
 }
 
+/**
+ * ti_clk_get_legacy_bit_shift - get bit shift for a clock register
+ * @node: device node for the clock
+ *
+ * Gets the clock register bit shift using the legacy ti,bit-shift
+ * property. Only needed for legacy clock, and can be eventually
+ * dropped once all the composite clocks use a clksel node with a
+ * proper reg property.
+ */
+int ti_clk_get_legacy_bit_shift(struct device_node *node)
+{
+       int err;
+       u32 val;
+
+       err = of_property_read_u32(node, "ti,bit-shift", &val);
+       if (!err && in_range(val, 0, 32))
+               return val;
+
+       return 0;
+}
+
 void ti_clk_latch(struct clk_omap_reg *reg, s8 shift)
 {
        u32 latch;
index 16a9f7c2280a57016a55373d8d706c331974ece1..2de7acea1ea0503790754a5d4b9bcfe42da701d3 100644 (file)
@@ -216,6 +216,7 @@ int ti_clk_parse_divider_data(int *div_table, int num_dividers, int max_div,
 
 int ti_clk_get_reg_addr(struct device_node *node, int index,
                        struct clk_omap_reg *reg);
+int ti_clk_get_legacy_bit_shift(struct device_node *node);
 void ti_dt_clocks_register(struct ti_dt_clk *oclks);
 int ti_clk_retry_init(struct device_node *node, void *user,
                      ti_of_clk_init_cb_t func);
index 5d5bb123ba9494c01e918e69e377784890c1edd5..ade99ab6cfa9b18e5bcfb616273b5c06637035c1 100644 (file)
@@ -477,10 +477,7 @@ static int __init ti_clk_divider_populate(struct device_node *node,
        if (ret)
                return ret;
 
-       if (!of_property_read_u32(node, "ti,bit-shift", &val))
-               div->shift = val;
-       else
-               div->shift = 0;
+       div->shift = div->reg.bit;
 
        if (!of_property_read_u32(node, "ti,latch-bit", &val))
                div->latch = val;
index 8e477d50d0fdbfabc67ec4bfbe162864a1559ad5..a9febd6356b826cf3b853f2426acc82d6a2562c7 100644 (file)
@@ -132,7 +132,6 @@ static void __init _of_ti_gate_clk_setup(struct device_node *node,
        struct clk_omap_reg reg;
        const char *name;
        u8 enable_bit = 0;
-       u32 val;
        u32 flags = 0;
        u8 clk_gate_flags = 0;
 
@@ -140,8 +139,7 @@ static void __init _of_ti_gate_clk_setup(struct device_node *node,
                if (ti_clk_get_reg_addr(node, 0, &reg))
                        return;
 
-               if (!of_property_read_u32(node, "ti,bit-shift", &val))
-                       enable_bit = val;
+               enable_bit = reg.bit;
        }
 
        if (of_clk_get_parent_count(node) != 1) {
@@ -170,7 +168,6 @@ _of_ti_composite_gate_clk_setup(struct device_node *node,
                                const struct clk_hw_omap_ops *hw_ops)
 {
        struct clk_hw_omap *gate;
-       u32 val = 0;
 
        gate = kzalloc(sizeof(*gate), GFP_KERNEL);
        if (!gate)
@@ -179,9 +176,7 @@ _of_ti_composite_gate_clk_setup(struct device_node *node,
        if (ti_clk_get_reg_addr(node, 0, &gate->enable_reg))
                goto cleanup;
 
-       of_property_read_u32(node, "ti,bit-shift", &val);
-
-       gate->enable_bit = val;
+       gate->enable_bit = gate->enable_reg.bit;
        gate->ops = hw_ops;
 
        if (!ti_clk_add_component(node, &gate->hw, CLK_COMPONENT_TYPE_GATE))
index 172301c646f85a62b400f7993caa86ff53cd0425..3eb35c87c0ed5e706ff0f7761f74c179758a847d 100644 (file)
@@ -66,13 +66,11 @@ static void __init _of_ti_interface_clk_setup(struct device_node *node,
        struct clk_omap_reg reg;
        u8 enable_bit = 0;
        const char *name;
-       u32 val;
 
        if (ti_clk_get_reg_addr(node, 0, &reg))
                return;
 
-       if (!of_property_read_u32(node, "ti,bit-shift", &val))
-               enable_bit = val;
+       enable_bit = reg.bit;
 
        parent_name = of_clk_get_parent_name(node, 0);
        if (!parent_name) {
index 1ebafa386be6150be385ad9172b682eacc9c109b..216d85d6aac6c5e2adf3bfa3d7beed3299afe66a 100644 (file)
@@ -189,7 +189,7 @@ static void of_mux_clk_setup(struct device_node *node)
        if (ti_clk_get_reg_addr(node, 0, &reg))
                goto cleanup;
 
-       of_property_read_u32(node, "ti,bit-shift", &shift);
+       shift = reg.bit;
 
        of_property_read_u32(node, "ti,latch-bit", &latch);
 
@@ -252,7 +252,6 @@ static void __init of_ti_composite_mux_clk_setup(struct device_node *node)
 {
        struct clk_omap_mux *mux;
        unsigned int num_parents;
-       u32 val;
 
        mux = kzalloc(sizeof(*mux), GFP_KERNEL);
        if (!mux)
@@ -261,8 +260,7 @@ static void __init of_ti_composite_mux_clk_setup(struct device_node *node)
        if (ti_clk_get_reg_addr(node, 0, &mux->reg))
                goto cleanup;
 
-       if (!of_property_read_u32(node, "ti,bit-shift", &val))
-               mux->shift = val;
+       mux->shift = mux->reg.bit;
 
        if (of_property_read_bool(node, "ti,index-starts-at-one"))
                mux->flags |= CLK_MUX_INDEX_ONE;
index cbfcbf186ce33069a28e1a8afad337f4c5b03a69..e656f63efdcee77ee3e8bc55e763423686cee06f 100644 (file)
 /**
  * struct clk_omap_reg - OMAP register declaration
  * @offset: offset from the master IP module base address
+ * @bit: register bit offset
  * @index: index of the master IP module
+ * @flags: flags
  */
 struct clk_omap_reg {
        void __iomem *ptr;
        u16 offset;
+       u8 bit;
        u8 index;
        u8 flags;
 };