aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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);