aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephen Boyd <sboyd@kernel.org>2018-12-19 13:59:55 -0500
committerStephen Boyd <sboyd@kernel.org>2019-03-01 14:17:22 -0500
commit4472287a3b2f52f4aa53f294ccb74392dde4e07d (patch)
tree77f40e0f7e08c1394275664a624628d64cddb064
parent2447883934a03c80a85d92cd313ea1d10e330158 (diff)
clk: Introduce of_clk_get_hw_from_clkspec()
We want to get struct clk_hw pointers from a DT clk specifier (i.e. a clocks property) so that we can find parent clks without searching for globally unique clk names. This should save time by avoiding the global string search for clks that are external to the clock controller providing the clk and let us move away from string comparisons in general. Introduce of_clk_get_hw_from_clkspec() which is largely the DT parsing part of finding clks implemented in clkdev.c and have that return a clk_hw pointer instead of converting that into a clk pointer. This lets us push up the clk pointer creation to the caller in clk_get() and avoids the need to push the dev_id and con_id throughout the DT parsing code. Cc: Miquel Raynal <miquel.raynal@bootlin.com> Cc: Jerome Brunet <jbrunet@baylibre.com> Cc: Russell King <linux@armlinux.org.uk> Cc: Michael Turquette <mturquette@baylibre.com> Cc: Jeffrey Hugo <jhugo@codeaurora.org> Cc: Chen-Yu Tsai <wens@csie.org> Signed-off-by: Stephen Boyd <sboyd@kernel.org>
-rw-r--r--drivers/clk/clk.c46
-rw-r--r--drivers/clk/clk.h5
-rw-r--r--drivers/clk/clkdev.c83
3 files changed, 69 insertions, 65 deletions
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index d46e8b9b9c9f..04288063847b 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -4065,6 +4065,42 @@ void devm_of_clk_del_provider(struct device *dev)
4065} 4065}
4066EXPORT_SYMBOL(devm_of_clk_del_provider); 4066EXPORT_SYMBOL(devm_of_clk_del_provider);
4067 4067
4068int of_parse_clkspec(const struct device_node *np, int index, const char *name,
4069 struct of_phandle_args *out_args)
4070{
4071 int ret = -ENOENT;
4072
4073 /* Walk up the tree of devices looking for a clock property that matches */
4074 while (np) {
4075 /*
4076 * For named clocks, first look up the name in the
4077 * "clock-names" property. If it cannot be found, then index
4078 * will be an error code and of_parse_phandle_with_args() will
4079 * return -EINVAL.
4080 */
4081 if (name)
4082 index = of_property_match_string(np, "clock-names", name);
4083 ret = of_parse_phandle_with_args(np, "clocks", "#clock-cells",
4084 index, out_args);
4085 if (!ret)
4086 break;
4087 if (name && index >= 0)
4088 break;
4089
4090 /*
4091 * No matching clock found on this node. If the parent node
4092 * has a "clock-ranges" property, then we can try one of its
4093 * clocks.
4094 */
4095 np = np->parent;
4096 if (np && !of_get_property(np, "clock-ranges", NULL))
4097 break;
4098 index = 0;
4099 }
4100
4101 return ret;
4102}
4103
4068static struct clk_hw * 4104static struct clk_hw *
4069__of_clk_get_hw_from_provider(struct of_clk_provider *provider, 4105__of_clk_get_hw_from_provider(struct of_clk_provider *provider,
4070 struct of_phandle_args *clkspec) 4106 struct of_phandle_args *clkspec)
@@ -4080,8 +4116,7 @@ __of_clk_get_hw_from_provider(struct of_clk_provider *provider,
4080 return __clk_get_hw(clk); 4116 return __clk_get_hw(clk);
4081} 4117}
4082 4118
4083struct clk *__of_clk_get_from_provider(struct of_phandle_args *clkspec, 4119struct clk_hw *of_clk_get_hw_from_clkspec(struct of_phandle_args *clkspec)
4084 const char *dev_id, const char *con_id)
4085{ 4120{
4086 struct of_clk_provider *provider; 4121 struct of_clk_provider *provider;
4087 struct clk_hw *hw = ERR_PTR(-EPROBE_DEFER); 4122 struct clk_hw *hw = ERR_PTR(-EPROBE_DEFER);
@@ -4089,7 +4124,6 @@ struct clk *__of_clk_get_from_provider(struct of_phandle_args *clkspec,
4089 if (!clkspec) 4124 if (!clkspec)
4090 return ERR_PTR(-EINVAL); 4125 return ERR_PTR(-EINVAL);
4091 4126
4092 /* Check if we have such a provider in our array */
4093 mutex_lock(&of_clk_mutex); 4127 mutex_lock(&of_clk_mutex);
4094 list_for_each_entry(provider, &of_clk_providers, link) { 4128 list_for_each_entry(provider, &of_clk_providers, link) {
4095 if (provider->node == clkspec->np) { 4129 if (provider->node == clkspec->np) {
@@ -4100,7 +4134,7 @@ struct clk *__of_clk_get_from_provider(struct of_phandle_args *clkspec,
4100 } 4134 }
4101 mutex_unlock(&of_clk_mutex); 4135 mutex_unlock(&of_clk_mutex);
4102 4136
4103 return clk_hw_create_clk(hw, dev_id, con_id); 4137 return hw;
4104} 4138}
4105 4139
4106/** 4140/**
@@ -4113,7 +4147,9 @@ struct clk *__of_clk_get_from_provider(struct of_phandle_args *clkspec,
4113 */ 4147 */
4114struct clk *of_clk_get_from_provider(struct of_phandle_args *clkspec) 4148struct clk *of_clk_get_from_provider(struct of_phandle_args *clkspec)
4115{ 4149{
4116 return __of_clk_get_from_provider(clkspec, NULL, __func__); 4150 struct clk_hw *hw = of_clk_get_hw_from_clkspec(clkspec);
4151
4152 return clk_hw_create_clk(hw, NULL, __func__);
4117} 4153}
4118EXPORT_SYMBOL_GPL(of_clk_get_from_provider); 4154EXPORT_SYMBOL_GPL(of_clk_get_from_provider);
4119 4155
diff --git a/drivers/clk/clk.h b/drivers/clk/clk.h
index 4cdf30b0008c..5a0ca0e3c1f1 100644
--- a/drivers/clk/clk.h
+++ b/drivers/clk/clk.h
@@ -7,8 +7,9 @@
7struct clk_hw; 7struct clk_hw;
8 8
9#if defined(CONFIG_OF) && defined(CONFIG_COMMON_CLK) 9#if defined(CONFIG_OF) && defined(CONFIG_COMMON_CLK)
10struct clk *__of_clk_get_from_provider(struct of_phandle_args *clkspec, 10int of_parse_clkspec(const struct device_node *np, int index, const char *name,
11 const char *dev_id, const char *con_id); 11 struct of_phandle_args *out_args);
12struct clk_hw *of_clk_get_hw_from_clkspec(struct of_phandle_args *clkspec);
12#endif 13#endif
13 14
14#ifdef CONFIG_COMMON_CLK 15#ifdef CONFIG_COMMON_CLK
diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c
index bdeaffc950ae..5ebb2119c0b9 100644
--- a/drivers/clk/clkdev.c
+++ b/drivers/clk/clkdev.c
@@ -28,69 +28,37 @@ static LIST_HEAD(clocks);
28static DEFINE_MUTEX(clocks_mutex); 28static DEFINE_MUTEX(clocks_mutex);
29 29
30#if defined(CONFIG_OF) && defined(CONFIG_COMMON_CLK) 30#if defined(CONFIG_OF) && defined(CONFIG_COMMON_CLK)
31static struct clk *__of_clk_get(struct device_node *np, int index, 31static struct clk_hw *of_clk_get_hw(struct device_node *np,
32 const char *dev_id, const char *con_id) 32 int index, const char *con_id)
33{ 33{
34 int ret;
35 struct clk_hw *hw;
34 struct of_phandle_args clkspec; 36 struct of_phandle_args clkspec;
35 struct clk *clk;
36 int rc;
37 37
38 rc = of_parse_phandle_with_args(np, "clocks", "#clock-cells", index, 38 ret = of_parse_clkspec(np, index, con_id, &clkspec);
39 &clkspec); 39 if (ret)
40 if (rc) 40 return ERR_PTR(ret);
41 return ERR_PTR(rc);
42 41
43 clk = __of_clk_get_from_provider(&clkspec, dev_id, con_id); 42 hw = of_clk_get_hw_from_clkspec(&clkspec);
44 of_node_put(clkspec.np); 43 of_node_put(clkspec.np);
45 44
46 return clk; 45 return hw;
47} 46}
48 47
49struct clk *of_clk_get(struct device_node *np, int index) 48static struct clk *__of_clk_get(struct device_node *np,
49 int index, const char *dev_id,
50 const char *con_id)
50{ 51{
51 return __of_clk_get(np, index, np->full_name, NULL); 52 struct clk_hw *hw = of_clk_get_hw(np, index, con_id);
53
54 return clk_hw_create_clk(hw, dev_id, con_id);
52} 55}
53EXPORT_SYMBOL(of_clk_get);
54 56
55static struct clk *__of_clk_get_by_name(struct device_node *np, 57struct clk *of_clk_get(struct device_node *np, int index)
56 const char *dev_id,
57 const char *name)
58{ 58{
59 struct clk *clk = ERR_PTR(-ENOENT); 59 return __of_clk_get(np, index, np->full_name, NULL);
60
61 /* Walk up the tree of devices looking for a clock that matches */
62 while (np) {
63 int index = 0;
64
65 /*
66 * For named clocks, first look up the name in the
67 * "clock-names" property. If it cannot be found, then
68 * index will be an error code, and of_clk_get() will fail.
69 */
70 if (name)
71 index = of_property_match_string(np, "clock-names", name);
72 clk = __of_clk_get(np, index, dev_id, name);
73 if (!IS_ERR(clk)) {
74 break;
75 } else if (name && index >= 0) {
76 if (PTR_ERR(clk) != -EPROBE_DEFER)
77 pr_err("ERROR: could not get clock %pOF:%s(%i)\n",
78 np, name ? name : "", index);
79 return clk;
80 }
81
82 /*
83 * No matching clock found on this node. If the parent node
84 * has a "clock-ranges" property, then we can try one of its
85 * clocks.
86 */
87 np = np->parent;
88 if (np && !of_get_property(np, "clock-ranges", NULL))
89 break;
90 }
91
92 return clk;
93} 60}
61EXPORT_SYMBOL(of_clk_get);
94 62
95/** 63/**
96 * of_clk_get_by_name() - Parse and lookup a clock referenced by a device node 64 * of_clk_get_by_name() - Parse and lookup a clock referenced by a device node
@@ -106,15 +74,14 @@ struct clk *of_clk_get_by_name(struct device_node *np, const char *name)
106 if (!np) 74 if (!np)
107 return ERR_PTR(-ENOENT); 75 return ERR_PTR(-ENOENT);
108 76
109 return __of_clk_get_by_name(np, np->full_name, name); 77 return __of_clk_get(np, -1, np->full_name, name);
110} 78}
111EXPORT_SYMBOL(of_clk_get_by_name); 79EXPORT_SYMBOL(of_clk_get_by_name);
112 80
113#else /* defined(CONFIG_OF) && defined(CONFIG_COMMON_CLK) */ 81#else /* defined(CONFIG_OF) && defined(CONFIG_COMMON_CLK) */
114 82
115static struct clk *__of_clk_get_by_name(struct device_node *np, 83static struct clk_hw *of_clk_get_hw(struct device_node *np,
116 const char *dev_id, 84 int index, const char *con_id)
117 const char *name)
118{ 85{
119 return ERR_PTR(-ENOENT); 86 return ERR_PTR(-ENOENT);
120} 87}
@@ -187,12 +154,12 @@ EXPORT_SYMBOL(clk_get_sys);
187struct clk *clk_get(struct device *dev, const char *con_id) 154struct clk *clk_get(struct device *dev, const char *con_id)
188{ 155{
189 const char *dev_id = dev ? dev_name(dev) : NULL; 156 const char *dev_id = dev ? dev_name(dev) : NULL;
190 struct clk *clk; 157 struct clk_hw *hw;
191 158
192 if (dev && dev->of_node) { 159 if (dev && dev->of_node) {
193 clk = __of_clk_get_by_name(dev->of_node, dev_id, con_id); 160 hw = of_clk_get_hw(dev->of_node, 0, con_id);
194 if (!IS_ERR(clk) || PTR_ERR(clk) == -EPROBE_DEFER) 161 if (!IS_ERR(hw) || PTR_ERR(hw) == -EPROBE_DEFER)
195 return clk; 162 return clk_hw_create_clk(hw, dev_id, con_id);
196 } 163 }
197 164
198 return clk_get_sys(dev_id, con_id); 165 return clk_get_sys(dev_id, con_id);