On Fri, Jul 17, 2026 at 05:59:22PM +0200, Miquel Raynal (Schneider Electric) 
wrote:
> 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]>
> ---

Reviewed-by: Frank Li <[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 45f5d7a4ccc1..6acf042673c3 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