Linux-libre 3.17.4-gnu
[librecmc/linux-libre.git] / drivers / clk / ux500 / clk-prcmu.c
1 /*
2  * PRCMU clock implementation for ux500 platform.
3  *
4  * Copyright (C) 2012 ST-Ericsson SA
5  * Author: Ulf Hansson <ulf.hansson@linaro.org>
6  *
7  * License terms: GNU General Public License (GPL) version 2
8  */
9
10 #include <linux/clk-provider.h>
11 #include <linux/clk-private.h>
12 #include <linux/mfd/dbx500-prcmu.h>
13 #include <linux/slab.h>
14 #include <linux/io.h>
15 #include <linux/err.h>
16 #include "clk.h"
17
18 #define to_clk_prcmu(_hw) container_of(_hw, struct clk_prcmu, hw)
19
20 struct clk_prcmu {
21         struct clk_hw hw;
22         u8 cg_sel;
23         int is_prepared;
24         int is_enabled;
25         int opp_requested;
26 };
27
28 /* PRCMU clock operations. */
29
30 static int clk_prcmu_prepare(struct clk_hw *hw)
31 {
32         int ret;
33         struct clk_prcmu *clk = to_clk_prcmu(hw);
34
35         ret = prcmu_request_clock(clk->cg_sel, true);
36         if (!ret)
37                 clk->is_prepared = 1;
38
39         return ret;
40 }
41
42 static void clk_prcmu_unprepare(struct clk_hw *hw)
43 {
44         struct clk_prcmu *clk = to_clk_prcmu(hw);
45         if (prcmu_request_clock(clk->cg_sel, false))
46                 pr_err("clk_prcmu: %s failed to disable %s.\n", __func__,
47                         __clk_get_name(hw->clk));
48         else
49                 clk->is_prepared = 0;
50 }
51
52 static int clk_prcmu_is_prepared(struct clk_hw *hw)
53 {
54         struct clk_prcmu *clk = to_clk_prcmu(hw);
55         return clk->is_prepared;
56 }
57
58 static int clk_prcmu_enable(struct clk_hw *hw)
59 {
60         struct clk_prcmu *clk = to_clk_prcmu(hw);
61         clk->is_enabled = 1;
62         return 0;
63 }
64
65 static void clk_prcmu_disable(struct clk_hw *hw)
66 {
67         struct clk_prcmu *clk = to_clk_prcmu(hw);
68         clk->is_enabled = 0;
69 }
70
71 static int clk_prcmu_is_enabled(struct clk_hw *hw)
72 {
73         struct clk_prcmu *clk = to_clk_prcmu(hw);
74         return clk->is_enabled;
75 }
76
77 static unsigned long clk_prcmu_recalc_rate(struct clk_hw *hw,
78                                            unsigned long parent_rate)
79 {
80         struct clk_prcmu *clk = to_clk_prcmu(hw);
81         return prcmu_clock_rate(clk->cg_sel);
82 }
83
84 static long clk_prcmu_round_rate(struct clk_hw *hw, unsigned long rate,
85                                  unsigned long *parent_rate)
86 {
87         struct clk_prcmu *clk = to_clk_prcmu(hw);
88         return prcmu_round_clock_rate(clk->cg_sel, rate);
89 }
90
91 static int clk_prcmu_set_rate(struct clk_hw *hw, unsigned long rate,
92                               unsigned long parent_rate)
93 {
94         struct clk_prcmu *clk = to_clk_prcmu(hw);
95         return prcmu_set_clock_rate(clk->cg_sel, rate);
96 }
97
98 static int clk_prcmu_opp_prepare(struct clk_hw *hw)
99 {
100         int err;
101         struct clk_prcmu *clk = to_clk_prcmu(hw);
102
103         if (!clk->opp_requested) {
104                 err = prcmu_qos_add_requirement(PRCMU_QOS_APE_OPP,
105                                                 (char *)__clk_get_name(hw->clk),
106                                                 100);
107                 if (err) {
108                         pr_err("clk_prcmu: %s fail req APE OPP for %s.\n",
109                                 __func__, __clk_get_name(hw->clk));
110                         return err;
111                 }
112                 clk->opp_requested = 1;
113         }
114
115         err = prcmu_request_clock(clk->cg_sel, true);
116         if (err) {
117                 prcmu_qos_remove_requirement(PRCMU_QOS_APE_OPP,
118                                         (char *)__clk_get_name(hw->clk));
119                 clk->opp_requested = 0;
120                 return err;
121         }
122
123         clk->is_prepared = 1;
124         return 0;
125 }
126
127 static void clk_prcmu_opp_unprepare(struct clk_hw *hw)
128 {
129         struct clk_prcmu *clk = to_clk_prcmu(hw);
130
131         if (prcmu_request_clock(clk->cg_sel, false)) {
132                 pr_err("clk_prcmu: %s failed to disable %s.\n", __func__,
133                         __clk_get_name(hw->clk));
134                 return;
135         }
136
137         if (clk->opp_requested) {
138                 prcmu_qos_remove_requirement(PRCMU_QOS_APE_OPP,
139                                         (char *)__clk_get_name(hw->clk));
140                 clk->opp_requested = 0;
141         }
142
143         clk->is_prepared = 0;
144 }
145
146 static int clk_prcmu_opp_volt_prepare(struct clk_hw *hw)
147 {
148         int err;
149         struct clk_prcmu *clk = to_clk_prcmu(hw);
150
151         if (!clk->opp_requested) {
152                 err = prcmu_request_ape_opp_100_voltage(true);
153                 if (err) {
154                         pr_err("clk_prcmu: %s fail req APE OPP VOLT for %s.\n",
155                                 __func__, __clk_get_name(hw->clk));
156                         return err;
157                 }
158                 clk->opp_requested = 1;
159         }
160
161         err = prcmu_request_clock(clk->cg_sel, true);
162         if (err) {
163                 prcmu_request_ape_opp_100_voltage(false);
164                 clk->opp_requested = 0;
165                 return err;
166         }
167
168         clk->is_prepared = 1;
169         return 0;
170 }
171
172 static void clk_prcmu_opp_volt_unprepare(struct clk_hw *hw)
173 {
174         struct clk_prcmu *clk = to_clk_prcmu(hw);
175
176         if (prcmu_request_clock(clk->cg_sel, false)) {
177                 pr_err("clk_prcmu: %s failed to disable %s.\n", __func__,
178                         __clk_get_name(hw->clk));
179                 return;
180         }
181
182         if (clk->opp_requested) {
183                 prcmu_request_ape_opp_100_voltage(false);
184                 clk->opp_requested = 0;
185         }
186
187         clk->is_prepared = 0;
188 }
189
190 static struct clk_ops clk_prcmu_scalable_ops = {
191         .prepare = clk_prcmu_prepare,
192         .unprepare = clk_prcmu_unprepare,
193         .is_prepared = clk_prcmu_is_prepared,
194         .enable = clk_prcmu_enable,
195         .disable = clk_prcmu_disable,
196         .is_enabled = clk_prcmu_is_enabled,
197         .recalc_rate = clk_prcmu_recalc_rate,
198         .round_rate = clk_prcmu_round_rate,
199         .set_rate = clk_prcmu_set_rate,
200 };
201
202 static struct clk_ops clk_prcmu_gate_ops = {
203         .prepare = clk_prcmu_prepare,
204         .unprepare = clk_prcmu_unprepare,
205         .is_prepared = clk_prcmu_is_prepared,
206         .enable = clk_prcmu_enable,
207         .disable = clk_prcmu_disable,
208         .is_enabled = clk_prcmu_is_enabled,
209         .recalc_rate = clk_prcmu_recalc_rate,
210 };
211
212 static struct clk_ops clk_prcmu_scalable_rate_ops = {
213         .is_enabled = clk_prcmu_is_enabled,
214         .recalc_rate = clk_prcmu_recalc_rate,
215         .round_rate = clk_prcmu_round_rate,
216         .set_rate = clk_prcmu_set_rate,
217 };
218
219 static struct clk_ops clk_prcmu_rate_ops = {
220         .is_enabled = clk_prcmu_is_enabled,
221         .recalc_rate = clk_prcmu_recalc_rate,
222 };
223
224 static struct clk_ops clk_prcmu_opp_gate_ops = {
225         .prepare = clk_prcmu_opp_prepare,
226         .unprepare = clk_prcmu_opp_unprepare,
227         .is_prepared = clk_prcmu_is_prepared,
228         .enable = clk_prcmu_enable,
229         .disable = clk_prcmu_disable,
230         .is_enabled = clk_prcmu_is_enabled,
231         .recalc_rate = clk_prcmu_recalc_rate,
232 };
233
234 static struct clk_ops clk_prcmu_opp_volt_scalable_ops = {
235         .prepare = clk_prcmu_opp_volt_prepare,
236         .unprepare = clk_prcmu_opp_volt_unprepare,
237         .is_prepared = clk_prcmu_is_prepared,
238         .enable = clk_prcmu_enable,
239         .disable = clk_prcmu_disable,
240         .is_enabled = clk_prcmu_is_enabled,
241         .recalc_rate = clk_prcmu_recalc_rate,
242         .round_rate = clk_prcmu_round_rate,
243         .set_rate = clk_prcmu_set_rate,
244 };
245
246 static struct clk *clk_reg_prcmu(const char *name,
247                                  const char *parent_name,
248                                  u8 cg_sel,
249                                  unsigned long rate,
250                                  unsigned long flags,
251                                  struct clk_ops *clk_prcmu_ops)
252 {
253         struct clk_prcmu *clk;
254         struct clk_init_data clk_prcmu_init;
255         struct clk *clk_reg;
256
257         if (!name) {
258                 pr_err("clk_prcmu: %s invalid arguments passed\n", __func__);
259                 return ERR_PTR(-EINVAL);
260         }
261
262         clk = kzalloc(sizeof(struct clk_prcmu), GFP_KERNEL);
263         if (!clk) {
264                 pr_err("clk_prcmu: %s could not allocate clk\n", __func__);
265                 return ERR_PTR(-ENOMEM);
266         }
267
268         clk->cg_sel = cg_sel;
269         clk->is_prepared = 1;
270         clk->is_enabled = 1;
271         clk->opp_requested = 0;
272         /* "rate" can be used for changing the initial frequency */
273         if (rate)
274                 prcmu_set_clock_rate(cg_sel, rate);
275
276         clk_prcmu_init.name = name;
277         clk_prcmu_init.ops = clk_prcmu_ops;
278         clk_prcmu_init.flags = flags;
279         clk_prcmu_init.parent_names = (parent_name ? &parent_name : NULL);
280         clk_prcmu_init.num_parents = (parent_name ? 1 : 0);
281         clk->hw.init = &clk_prcmu_init;
282
283         clk_reg = clk_register(NULL, &clk->hw);
284         if (IS_ERR_OR_NULL(clk_reg))
285                 goto free_clk;
286
287         return clk_reg;
288
289 free_clk:
290         kfree(clk);
291         pr_err("clk_prcmu: %s failed to register clk\n", __func__);
292         return ERR_PTR(-ENOMEM);
293 }
294
295 struct clk *clk_reg_prcmu_scalable(const char *name,
296                                    const char *parent_name,
297                                    u8 cg_sel,
298                                    unsigned long rate,
299                                    unsigned long flags)
300 {
301         return clk_reg_prcmu(name, parent_name, cg_sel, rate, flags,
302                         &clk_prcmu_scalable_ops);
303 }
304
305 struct clk *clk_reg_prcmu_gate(const char *name,
306                                const char *parent_name,
307                                u8 cg_sel,
308                                unsigned long flags)
309 {
310         return clk_reg_prcmu(name, parent_name, cg_sel, 0, flags,
311                         &clk_prcmu_gate_ops);
312 }
313
314 struct clk *clk_reg_prcmu_scalable_rate(const char *name,
315                                         const char *parent_name,
316                                         u8 cg_sel,
317                                         unsigned long rate,
318                                         unsigned long flags)
319 {
320         return clk_reg_prcmu(name, parent_name, cg_sel, rate, flags,
321                         &clk_prcmu_scalable_rate_ops);
322 }
323
324 struct clk *clk_reg_prcmu_rate(const char *name,
325                                const char *parent_name,
326                                u8 cg_sel,
327                                unsigned long flags)
328 {
329         return clk_reg_prcmu(name, parent_name, cg_sel, 0, flags,
330                         &clk_prcmu_rate_ops);
331 }
332
333 struct clk *clk_reg_prcmu_opp_gate(const char *name,
334                                    const char *parent_name,
335                                    u8 cg_sel,
336                                    unsigned long flags)
337 {
338         return clk_reg_prcmu(name, parent_name, cg_sel, 0, flags,
339                         &clk_prcmu_opp_gate_ops);
340 }
341
342 struct clk *clk_reg_prcmu_opp_volt_scalable(const char *name,
343                                             const char *parent_name,
344                                             u8 cg_sel,
345                                             unsigned long rate,
346                                             unsigned long flags)
347 {
348         return clk_reg_prcmu(name, parent_name, cg_sel, rate, flags,
349                         &clk_prcmu_opp_volt_scalable_ops);
350 }