how to get a clock from a device tree node

1

I have the following issue: I want to define the clock a CPU should use during frequency transitions in the device tree rather than in the clock driver code (in this way it will be more generic). I want to define the "transition-clock" property in the device tree, something like:

 232         cpu: cpu@01c20050 {
 233             #clock-cells = <0>;
 234             compatible = "allwinner,sun4i-a10-cpu-clk";
 235             reg = <0x01c20050 0x4>;
-----
 243             clocks = <&osc32k>, <&osc24M>, <&pll1>, <&pll1>;
 244             transition-clock = <&osc24M>;
 245             clock-output-names = "cpu";
 246         };

I changed the file "drivers/clk/clkdev.c" to search this property so I can get a clk pointer and store it in a new property in the cpu clock structure. This is what I have managed so far (changes begin on line 78):

 59 static struct clk *__of_clk_get(struct device_node *np, int index,
 60                    const char *dev_id, const char *con_id)
 61 {
 62     struct of_phandle_args clkspec;
 63     struct clk *clk, *transition_clk;
 64     struct device_node *clock_node, *transition_clock_node;
 65     int rc;
 66     
 67     if (index < 0)
 68         return ERR_PTR(-EINVAL);
 69         
 70     rc = of_parse_phandle_with_args(np, "clocks", "#clock-cells", index,
 71                     &clkspec);
 72     if (rc)         
 73         return ERR_PTR(rc);
 74         
 75     clk = __of_clk_get_by_clkspec(&clkspec, dev_id, con_id);
 76     of_node_put(clkspec.np);
 77     
 78     clock_node = of_parse_phandle(np, "clocks", 0);
 79     pr_err("-------------------- parsing node %s\n", np->name);
 80     if (clock_node!=NULL) {
 81         pr_err("============ Clock node found %p\n", clock_node);
 82         transition_clock_node =
 83             of_parse_phandle(clock_node, "transition-clock", 0);
 84         if (transition_clock_node!=NULL) {
 85             pr_err("============ Transition clock node found %p\n",
 86                 transition_clock_node);
 87             transition_clk = clk_get(clock_node, 0);
 88             pr_err("============ Transition clock %p\n", transition_clk);
 89         }
 90     }
 91     
 92     return clk;
 93 }

I get pointers to the clock node and the transition clock node, but when I try to get a clock pointer from that, I get 0xfffffffe, which looks like an error:

[    2.540542] -------------------- parsing node cpu
[    2.540546] ============ Clock node found eeef9520
[    2.540550] ============ Transition clock node found eeef8934
[    2.540555] ============ Transition clock fffffffe

I want a clock object which I can later use in

clk_set_parent(cpu_clk, cpu_clk->transition_clk)

Any ideas are welcome :)

c
linux-kernel
embedded
linux-device-driver
device-tree
asked on Stack Overflow Jun 5, 2015 by Octav Zlatior

1 Answer

1

OK, I got it figured out in the meantime and since nobody answered I'm going to provide my solution (maybe somebody else bumps into this issue):

 81     if (clock_node != NULL) {
 82         rc = of_parse_phandle_with_args(clock_node, "transition-clock", NULL,
 83             0, &transition_clkspec);
 84         of_node_put(transition_clkspec.np);
 85 
 86         if (!rc) {
 87             transition_clock = __of_clk_get_by_clkspec(&transition_clkspec,
 88                 dev_id, con_id);
 89             clk_set_transition_parent(clk, transition_clock);
 90         }
 91     }

So, the solution is to get an object of type "of_phandle_args" and get the clock from there using __of_clk_get_by_clkspec.

(the clk_set_transition_parent function is defined somewhere else and it does exactly what it's name suggests)

answered on Stack Overflow Jun 9, 2015 by Octav Zlatior

User contributions licensed under CC BY-SA 3.0