A nexus node is some kind of parent device abstracting the outer
connections. They are particularly useful for describing connectors-like
interfaces but not only. Certain IP blocks will typically include inner
blocks and distribute resources to them.

In the case of clocks, there is already the concept of clock controller,
but this usually indicates some kind of control over the said clock,
ie. gate or rate control. When there is none of this, an existing
approach is to reference the upper clock, which is wrong from a hardware
point of view.

Nexus nodes are already part of the device-tree specification and clocks
are already mentioned:
https://github.com/devicetree-org/devicetree-specification/blob/v0.4/source/chapter2-devicetree-basics.rst#nexus-nodes-and-specifier-mapping

Following the introductions of nexus nodes support for interrupts, gpios
and pwms, here is the same logic applied again to the clk subsystem,
just by transitioning from of_parse_phandle_with_args() to
of_parse_phandle_with_args_map():

* Nexus OF support:
commit bd6f2fd5a1d5 ("of: Support parsing phandle argument lists through a 
nexus node")
* GPIO adoption:
commit c11e6f0f04db ("gpio: Support gpio nexus dt bindings")
* PWM adoption:
commit e71e46a6f19c ("pwm: Add support for pwm nexus dt bindings")

Only expected Nexus property:
- clock-map: maps inner clocks to inlet clocks
(the other properties have been judged not relevant for clocks)

Here is an example:

Example:
    soc_clk: clock-controller {
        #clock-cells = <1>;
    };

    container: container {
        #clock-cells = <1>;
        clock-map = <0 &soc_clk 2>,
                    <1 &soc_clk 6>;

        child-device {
            clocks = <&container 1>;
            /* This is equivalent to <&soc_clk 6> */
        };
    };

The child device does not need to know about the outer implementation,
and only knows about what the nexus provides. The nexus acts as a
pass-through, with no extra control.

Signed-off-by: Miquel Raynal (Schneider Electric) <[email protected]>
Reviewed-by: Herve Codina <[email protected]>
Reviewed-by: Brian Masney <[email protected]>
---
 drivers/clk/clk-conf.c | 12 ++++++------
 drivers/clk/clk.c      |  4 ++--
 2 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/drivers/clk/clk-conf.c b/drivers/clk/clk-conf.c
index 303a0bb26e54..5380d43b56a4 100644
--- a/drivers/clk/clk-conf.c
+++ b/drivers/clk/clk-conf.c
@@ -25,8 +25,8 @@ static int __set_clk_parents(struct device_node *node, bool 
clk_supplier)
                       node);
 
        for (index = 0; index < num_parents; index++) {
-               rc = of_parse_phandle_with_args(node, "assigned-clock-parents",
-                                       "#clock-cells", index, &clkspec);
+               rc = of_parse_phandle_with_args_map(node, 
"assigned-clock-parents",
+                                                   "clock", index, &clkspec);
                if (rc < 0) {
                        /* skip empty (null) phandles */
                        if (rc == -ENOENT)
@@ -47,8 +47,8 @@ static int __set_clk_parents(struct device_node *node, bool 
clk_supplier)
                        return PTR_ERR(pclk);
                }
 
-               rc = of_parse_phandle_with_args(node, "assigned-clocks",
-                                       "#clock-cells", index, &clkspec);
+               rc = of_parse_phandle_with_args_map(node, "assigned-clocks",
+                                                   "clock", index, &clkspec);
                if (rc < 0)
                        goto err;
                if (clkspec.np == node && !clk_supplier) {
@@ -121,8 +121,8 @@ static int __set_clk_rates(struct device_node *node, bool 
clk_supplier)
                        rate = rates[index];
 
                if (rate) {
-                       rc = of_parse_phandle_with_args(node, "assigned-clocks",
-                                       "#clock-cells", index, &clkspec);
+                       rc = of_parse_phandle_with_args_map(node, 
"assigned-clocks",
+                                                           "clock", index, 
&clkspec);
                        if (rc < 0) {
                                /* skip empty (null) phandles */
                                if (rc == -ENOENT)
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index dad4bac10ad4..73ddd9a6aa2e 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -5207,8 +5207,8 @@ static int of_parse_clkspec(const struct device_node *np, 
int index,
                 */
                if (name)
                        index = of_property_match_string(np, "clock-names", 
name);
-               ret = of_parse_phandle_with_args(np, "clocks", "#clock-cells",
-                                                index, out_args);
+               ret = of_parse_phandle_with_args_map(np, "clocks", "clock",
+                                                    index, out_args);
                if (!ret)
                        break;
                if (name && index >= 0)

-- 
2.54.0


Reply via email to