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