aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/clk/clkdev.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/clk/clkdev.c')
-rw-r--r--drivers/clk/clkdev.c110
1 files changed, 76 insertions, 34 deletions
diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c
index da4bda8b7fc7..043fd3633373 100644
--- a/drivers/clk/clkdev.c
+++ b/drivers/clk/clkdev.c
@@ -19,6 +19,7 @@
19#include <linux/mutex.h> 19#include <linux/mutex.h>
20#include <linux/clk.h> 20#include <linux/clk.h>
21#include <linux/clkdev.h> 21#include <linux/clkdev.h>
22#include <linux/clk-provider.h>
22#include <linux/of.h> 23#include <linux/of.h>
23 24
24#include "clk.h" 25#include "clk.h"
@@ -28,6 +29,20 @@ static DEFINE_MUTEX(clocks_mutex);
28 29
29#if defined(CONFIG_OF) && defined(CONFIG_COMMON_CLK) 30#if defined(CONFIG_OF) && defined(CONFIG_COMMON_CLK)
30 31
32static struct clk *__of_clk_get_by_clkspec(struct of_phandle_args *clkspec,
33 const char *dev_id, const char *con_id)
34{
35 struct clk *clk;
36
37 if (!clkspec)
38 return ERR_PTR(-EINVAL);
39
40 of_clk_lock();
41 clk = __of_clk_get_from_provider(clkspec, dev_id, con_id);
42 of_clk_unlock();
43 return clk;
44}
45
31/** 46/**
32 * of_clk_get_by_clkspec() - Lookup a clock form a clock provider 47 * of_clk_get_by_clkspec() - Lookup a clock form a clock provider
33 * @clkspec: pointer to a clock specifier data structure 48 * @clkspec: pointer to a clock specifier data structure
@@ -38,22 +53,11 @@ static DEFINE_MUTEX(clocks_mutex);
38 */ 53 */
39struct clk *of_clk_get_by_clkspec(struct of_phandle_args *clkspec) 54struct clk *of_clk_get_by_clkspec(struct of_phandle_args *clkspec)
40{ 55{
41 struct clk *clk; 56 return __of_clk_get_by_clkspec(clkspec, NULL, __func__);
42
43 if (!clkspec)
44 return ERR_PTR(-EINVAL);
45
46 of_clk_lock();
47 clk = __of_clk_get_from_provider(clkspec);
48
49 if (!IS_ERR(clk) && !__clk_get(clk))
50 clk = ERR_PTR(-ENOENT);
51
52 of_clk_unlock();
53 return clk;
54} 57}
55 58
56struct clk *of_clk_get(struct device_node *np, int index) 59static struct clk *__of_clk_get(struct device_node *np, int index,
60 const char *dev_id, const char *con_id)
57{ 61{
58 struct of_phandle_args clkspec; 62 struct of_phandle_args clkspec;
59 struct clk *clk; 63 struct clk *clk;
@@ -67,22 +71,21 @@ struct clk *of_clk_get(struct device_node *np, int index)
67 if (rc) 71 if (rc)
68 return ERR_PTR(rc); 72 return ERR_PTR(rc);
69 73
70 clk = of_clk_get_by_clkspec(&clkspec); 74 clk = __of_clk_get_by_clkspec(&clkspec, dev_id, con_id);
71 of_node_put(clkspec.np); 75 of_node_put(clkspec.np);
76
72 return clk; 77 return clk;
73} 78}
79
80struct clk *of_clk_get(struct device_node *np, int index)
81{
82 return __of_clk_get(np, index, np->full_name, NULL);
83}
74EXPORT_SYMBOL(of_clk_get); 84EXPORT_SYMBOL(of_clk_get);
75 85
76/** 86static struct clk *__of_clk_get_by_name(struct device_node *np,
77 * of_clk_get_by_name() - Parse and lookup a clock referenced by a device node 87 const char *dev_id,
78 * @np: pointer to clock consumer node 88 const char *name)
79 * @name: name of consumer's clock input, or NULL for the first clock reference
80 *
81 * This function parses the clocks and clock-names properties,
82 * and uses them to look up the struct clk from the registered list of clock
83 * providers.
84 */
85struct clk *of_clk_get_by_name(struct device_node *np, const char *name)
86{ 89{
87 struct clk *clk = ERR_PTR(-ENOENT); 90 struct clk *clk = ERR_PTR(-ENOENT);
88 91
@@ -97,10 +100,10 @@ struct clk *of_clk_get_by_name(struct device_node *np, const char *name)
97 */ 100 */
98 if (name) 101 if (name)
99 index = of_property_match_string(np, "clock-names", name); 102 index = of_property_match_string(np, "clock-names", name);
100 clk = of_clk_get(np, index); 103 clk = __of_clk_get(np, index, dev_id, name);
101 if (!IS_ERR(clk)) 104 if (!IS_ERR(clk)) {
102 break; 105 break;
103 else if (name && index >= 0) { 106 } else if (name && index >= 0) {
104 if (PTR_ERR(clk) != -EPROBE_DEFER) 107 if (PTR_ERR(clk) != -EPROBE_DEFER)
105 pr_err("ERROR: could not get clock %s:%s(%i)\n", 108 pr_err("ERROR: could not get clock %s:%s(%i)\n",
106 np->full_name, name ? name : "", index); 109 np->full_name, name ? name : "", index);
@@ -119,7 +122,33 @@ struct clk *of_clk_get_by_name(struct device_node *np, const char *name)
119 122
120 return clk; 123 return clk;
121} 124}
125
126/**
127 * of_clk_get_by_name() - Parse and lookup a clock referenced by a device node
128 * @np: pointer to clock consumer node
129 * @name: name of consumer's clock input, or NULL for the first clock reference
130 *
131 * This function parses the clocks and clock-names properties,
132 * and uses them to look up the struct clk from the registered list of clock
133 * providers.
134 */
135struct clk *of_clk_get_by_name(struct device_node *np, const char *name)
136{
137 if (!np)
138 return ERR_PTR(-ENOENT);
139
140 return __of_clk_get_by_name(np, np->full_name, name);
141}
122EXPORT_SYMBOL(of_clk_get_by_name); 142EXPORT_SYMBOL(of_clk_get_by_name);
143
144#else /* defined(CONFIG_OF) && defined(CONFIG_COMMON_CLK) */
145
146static struct clk *__of_clk_get_by_name(struct device_node *np,
147 const char *dev_id,
148 const char *name)
149{
150 return ERR_PTR(-ENOENT);
151}
123#endif 152#endif
124 153
125/* 154/*
@@ -168,14 +197,28 @@ static struct clk_lookup *clk_find(const char *dev_id, const char *con_id)
168struct clk *clk_get_sys(const char *dev_id, const char *con_id) 197struct clk *clk_get_sys(const char *dev_id, const char *con_id)
169{ 198{
170 struct clk_lookup *cl; 199 struct clk_lookup *cl;
200 struct clk *clk = NULL;
171 201
172 mutex_lock(&clocks_mutex); 202 mutex_lock(&clocks_mutex);
203
173 cl = clk_find(dev_id, con_id); 204 cl = clk_find(dev_id, con_id);
174 if (cl && !__clk_get(cl->clk)) 205 if (!cl)
206 goto out;
207
208 clk = __clk_create_clk(__clk_get_hw(cl->clk), dev_id, con_id);
209 if (IS_ERR(clk))
210 goto out;
211
212 if (!__clk_get(clk)) {
213 __clk_free_clk(clk);
175 cl = NULL; 214 cl = NULL;
215 goto out;
216 }
217
218out:
176 mutex_unlock(&clocks_mutex); 219 mutex_unlock(&clocks_mutex);
177 220
178 return cl ? cl->clk : ERR_PTR(-ENOENT); 221 return cl ? clk : ERR_PTR(-ENOENT);
179} 222}
180EXPORT_SYMBOL(clk_get_sys); 223EXPORT_SYMBOL(clk_get_sys);
181 224
@@ -185,10 +228,8 @@ struct clk *clk_get(struct device *dev, const char *con_id)
185 struct clk *clk; 228 struct clk *clk;
186 229
187 if (dev) { 230 if (dev) {
188 clk = of_clk_get_by_name(dev->of_node, con_id); 231 clk = __of_clk_get_by_name(dev->of_node, dev_id, con_id);
189 if (!IS_ERR(clk)) 232 if (!IS_ERR(clk) || PTR_ERR(clk) == -EPROBE_DEFER)
190 return clk;
191 if (PTR_ERR(clk) == -EPROBE_DEFER)
192 return clk; 233 return clk;
193 } 234 }
194 235
@@ -331,6 +372,7 @@ int clk_register_clkdev(struct clk *clk, const char *con_id,
331 372
332 return 0; 373 return 0;
333} 374}
375EXPORT_SYMBOL(clk_register_clkdev);
334 376
335/** 377/**
336 * clk_register_clkdevs - register a set of clk_lookup for a struct clk 378 * clk_register_clkdevs - register a set of clk_lookup for a struct clk