kernel: bump 4.4 to 4.4.108
[openwrt/openwrt.git] / target / linux / generic / pending-4.4 / 083-0002-clk-Add-clk_hw-OF-clk-providers.patch
1 From 0861e5b8cf80038e91942f1005c8dfce79d18c38 Mon Sep 17 00:00:00 2001
2 From: Stephen Boyd <sboyd@codeaurora.org>
3 Date: Fri, 5 Feb 2016 17:38:26 -0800
4 Subject: [PATCH] clk: Add clk_hw OF clk providers
5
6 Now that we have a clk registration API that doesn't return
7 struct clks, we need to have some way to hand out struct clks via
8 the clk_get() APIs that doesn't involve associating struct clk
9 pointers with an OF node. Currently we ask the OF provider to
10 give us a struct clk pointer for some clkspec, turn that struct
11 clk into a struct clk_hw and then allocate a new struct clk to
12 return to the caller.
13
14 Let's add a clk_hw based OF provider hook that returns a struct
15 clk_hw directly, so that we skip the intermediate step of
16 converting from struct clk to struct clk_hw. Eventually when
17 we've converted all OF clk providers to struct clk_hw based APIs
18 we can remove the struct clk based ones.
19
20 It should also be noted that we change the onecell provider to
21 have a flex array instead of a pointer for the array of clk_hw
22 pointers. This allows providers to allocate one structure of the
23 correct length in one step instead of two.
24
25 Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
26 ---
27 drivers/clk/clk.c | 85 +++++++++++++++++++++++++++++++++++++++++---
28 include/linux/clk-provider.h | 30 ++++++++++++++++
29 2 files changed, 111 insertions(+), 4 deletions(-)
30
31 --- a/drivers/clk/clk.c
32 +++ b/drivers/clk/clk.c
33 @@ -3001,6 +3001,7 @@ struct of_clk_provider {
34
35 struct device_node *node;
36 struct clk *(*get)(struct of_phandle_args *clkspec, void *data);
37 + struct clk_hw *(*get_hw)(struct of_phandle_args *clkspec, void *data);
38 void *data;
39 };
40
41 @@ -3017,6 +3018,12 @@ struct clk *of_clk_src_simple_get(struct
42 }
43 EXPORT_SYMBOL_GPL(of_clk_src_simple_get);
44
45 +struct clk_hw *of_clk_hw_simple_get(struct of_phandle_args *clkspec, void *data)
46 +{
47 + return data;
48 +}
49 +EXPORT_SYMBOL_GPL(of_clk_hw_simple_get);
50 +
51 struct clk *of_clk_src_onecell_get(struct of_phandle_args *clkspec, void *data)
52 {
53 struct clk_onecell_data *clk_data = data;
54 @@ -3031,6 +3038,21 @@ struct clk *of_clk_src_onecell_get(struc
55 }
56 EXPORT_SYMBOL_GPL(of_clk_src_onecell_get);
57
58 +struct clk_hw *
59 +of_clk_hw_onecell_get(struct of_phandle_args *clkspec, void *data)
60 +{
61 + struct clk_hw_onecell_data *hw_data = data;
62 + unsigned int idx = clkspec->args[0];
63 +
64 + if (idx >= hw_data->num) {
65 + pr_err("%s: invalid index %u\n", __func__, idx);
66 + return ERR_PTR(-EINVAL);
67 + }
68 +
69 + return hw_data->hws[idx];
70 +}
71 +EXPORT_SYMBOL_GPL(of_clk_hw_onecell_get);
72 +
73 /**
74 * of_clk_add_provider() - Register a clock provider for a node
75 * @np: Device node pointer associated with clock provider
76 @@ -3067,6 +3089,41 @@ int of_clk_add_provider(struct device_no
77 EXPORT_SYMBOL_GPL(of_clk_add_provider);
78
79 /**
80 + * of_clk_add_hw_provider() - Register a clock provider for a node
81 + * @np: Device node pointer associated with clock provider
82 + * @get: callback for decoding clk_hw
83 + * @data: context pointer for @get callback.
84 + */
85 +int of_clk_add_hw_provider(struct device_node *np,
86 + struct clk_hw *(*get)(struct of_phandle_args *clkspec,
87 + void *data),
88 + void *data)
89 +{
90 + struct of_clk_provider *cp;
91 + int ret;
92 +
93 + cp = kzalloc(sizeof(*cp), GFP_KERNEL);
94 + if (!cp)
95 + return -ENOMEM;
96 +
97 + cp->node = of_node_get(np);
98 + cp->data = data;
99 + cp->get_hw = get;
100 +
101 + mutex_lock(&of_clk_mutex);
102 + list_add(&cp->link, &of_clk_providers);
103 + mutex_unlock(&of_clk_mutex);
104 + pr_debug("Added clk_hw provider from %s\n", np->full_name);
105 +
106 + ret = of_clk_set_defaults(np, true);
107 + if (ret < 0)
108 + of_clk_del_provider(np);
109 +
110 + return ret;
111 +}
112 +EXPORT_SYMBOL_GPL(of_clk_add_hw_provider);
113 +
114 +/**
115 * of_clk_del_provider() - Remove a previously registered clock provider
116 * @np: Device node pointer associated with clock provider
117 */
118 @@ -3087,11 +3144,32 @@ void of_clk_del_provider(struct device_n
119 }
120 EXPORT_SYMBOL_GPL(of_clk_del_provider);
121
122 +static struct clk_hw *
123 +__of_clk_get_hw_from_provider(struct of_clk_provider *provider,
124 + struct of_phandle_args *clkspec)
125 +{
126 + struct clk *clk;
127 + struct clk_hw *hw = ERR_PTR(-EPROBE_DEFER);
128 +
129 + if (provider->get_hw) {
130 + hw = provider->get_hw(clkspec, provider->data);
131 + } else if (provider->get) {
132 + clk = provider->get(clkspec, provider->data);
133 + if (!IS_ERR(clk))
134 + hw = __clk_get_hw(clk);
135 + else
136 + hw = ERR_CAST(clk);
137 + }
138 +
139 + return hw;
140 +}
141 +
142 struct clk *__of_clk_get_from_provider(struct of_phandle_args *clkspec,
143 const char *dev_id, const char *con_id)
144 {
145 struct of_clk_provider *provider;
146 struct clk *clk = ERR_PTR(-EPROBE_DEFER);
147 + struct clk_hw *hw = ERR_PTR(-EPROBE_DEFER);
148
149 if (!clkspec)
150 return ERR_PTR(-EINVAL);
151 @@ -3100,10 +3178,9 @@ struct clk *__of_clk_get_from_provider(s
152 mutex_lock(&of_clk_mutex);
153 list_for_each_entry(provider, &of_clk_providers, link) {
154 if (provider->node == clkspec->np)
155 - clk = provider->get(clkspec, provider->data);
156 - if (!IS_ERR(clk)) {
157 - clk = __clk_create_clk(__clk_get_hw(clk), dev_id,
158 - con_id);
159 + hw = __of_clk_get_hw_from_provider(provider, clkspec);
160 + if (!IS_ERR(hw)) {
161 + clk = __clk_create_clk(hw, dev_id, con_id);
162
163 if (!IS_ERR(clk) && !__clk_get(clk)) {
164 __clk_free_clk(clk);
165 --- a/include/linux/clk-provider.h
166 +++ b/include/linux/clk-provider.h
167 @@ -693,6 +693,11 @@ struct clk_onecell_data {
168 unsigned int clk_num;
169 };
170
171 +struct clk_hw_onecell_data {
172 + size_t num;
173 + struct clk_hw *hws[];
174 +};
175 +
176 extern struct of_device_id __clk_of_table;
177
178 #define CLK_OF_DECLARE(name, compat, fn) OF_DECLARE_1(clk, name, compat, fn)
179 @@ -702,10 +707,19 @@ int of_clk_add_provider(struct device_no
180 struct clk *(*clk_src_get)(struct of_phandle_args *args,
181 void *data),
182 void *data);
183 +int of_clk_add_hw_provider(struct device_node *np,
184 + struct clk_hw *(*get)(struct of_phandle_args *clkspec,
185 + void *data),
186 + void *data);
187 void of_clk_del_provider(struct device_node *np);
188 struct clk *of_clk_src_simple_get(struct of_phandle_args *clkspec,
189 void *data);
190 +
191 +struct clk_hw *of_clk_hw_simple_get(struct of_phandle_args *clkspec,
192 + void *data);
193 struct clk *of_clk_src_onecell_get(struct of_phandle_args *clkspec, void *data);
194 +struct clk_hw *of_clk_hw_onecell_get(struct of_phandle_args *clkspec,
195 + void *data);
196 int of_clk_get_parent_count(struct device_node *np);
197 int of_clk_parent_fill(struct device_node *np, const char **parents,
198 unsigned int size);
199 @@ -722,6 +736,13 @@ static inline int of_clk_add_provider(st
200 {
201 return 0;
202 }
203 +static inline int of_clk_add_hw_provider(struct device_node *np,
204 + struct clk_hw *(*get)(struct of_phandle_args *clkspec,
205 + void *data),
206 + void *data)
207 +{
208 + return 0;
209 +}
210 #define of_clk_del_provider(np) \
211 { while (0); }
212 static inline struct clk *of_clk_src_simple_get(
213 @@ -729,11 +750,21 @@ static inline struct clk *of_clk_src_sim
214 {
215 return ERR_PTR(-ENOENT);
216 }
217 +static inline struct clk_hw *
218 +of_clk_hw_simple_get(struct of_phandle_args *clkspec, void *data)
219 +{
220 + return ERR_PTR(-ENOENT);
221 +}
222 static inline struct clk *of_clk_src_onecell_get(
223 struct of_phandle_args *clkspec, void *data)
224 {
225 return ERR_PTR(-ENOENT);
226 }
227 +static inline struct clk_hw *
228 +of_clk_hw_onecell_get(struct of_phandle_args *clkspec, void *data)
229 +{
230 + return ERR_PTR(-ENOENT);
231 +}
232 static inline int of_clk_get_parent_count(struct device_node *np)
233 {
234 return 0;