2 * PRCMU clock implementation for ux500 platform.
4 * Copyright (C) 2012 ST-Ericsson SA
5 * Author: Ulf Hansson <ulf.hansson@linaro.org>
7 * License terms: GNU General Public License (GPL) version 2
10 #include <linux/clk-provider.h>
11 #include <linux/clk-private.h>
12 #include <linux/mfd/dbx500-prcmu.h>
13 #include <linux/slab.h>
15 #include <linux/err.h>
18 #define to_clk_prcmu(_hw) container_of(_hw, struct clk_prcmu, hw)
28 /* PRCMU clock operations. */
30 static int clk_prcmu_prepare(struct clk_hw
*hw
)
33 struct clk_prcmu
*clk
= to_clk_prcmu(hw
);
35 ret
= prcmu_request_clock(clk
->cg_sel
, true);
42 static void clk_prcmu_unprepare(struct clk_hw
*hw
)
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
));
52 static int clk_prcmu_is_prepared(struct clk_hw
*hw
)
54 struct clk_prcmu
*clk
= to_clk_prcmu(hw
);
55 return clk
->is_prepared
;
58 static int clk_prcmu_enable(struct clk_hw
*hw
)
60 struct clk_prcmu
*clk
= to_clk_prcmu(hw
);
65 static void clk_prcmu_disable(struct clk_hw
*hw
)
67 struct clk_prcmu
*clk
= to_clk_prcmu(hw
);
71 static int clk_prcmu_is_enabled(struct clk_hw
*hw
)
73 struct clk_prcmu
*clk
= to_clk_prcmu(hw
);
74 return clk
->is_enabled
;
77 static unsigned long clk_prcmu_recalc_rate(struct clk_hw
*hw
,
78 unsigned long parent_rate
)
80 struct clk_prcmu
*clk
= to_clk_prcmu(hw
);
81 return prcmu_clock_rate(clk
->cg_sel
);
84 static long clk_prcmu_round_rate(struct clk_hw
*hw
, unsigned long rate
,
85 unsigned long *parent_rate
)
87 struct clk_prcmu
*clk
= to_clk_prcmu(hw
);
88 return prcmu_round_clock_rate(clk
->cg_sel
, rate
);
91 static int clk_prcmu_set_rate(struct clk_hw
*hw
, unsigned long rate
,
92 unsigned long parent_rate
)
94 struct clk_prcmu
*clk
= to_clk_prcmu(hw
);
95 return prcmu_set_clock_rate(clk
->cg_sel
, rate
);
98 static int clk_prcmu_opp_prepare(struct clk_hw
*hw
)
101 struct clk_prcmu
*clk
= to_clk_prcmu(hw
);
103 if (!clk
->opp_requested
) {
104 err
= prcmu_qos_add_requirement(PRCMU_QOS_APE_OPP
,
105 (char *)__clk_get_name(hw
->clk
),
108 pr_err("clk_prcmu: %s fail req APE OPP for %s.\n",
109 __func__
, __clk_get_name(hw
->clk
));
112 clk
->opp_requested
= 1;
115 err
= prcmu_request_clock(clk
->cg_sel
, true);
117 prcmu_qos_remove_requirement(PRCMU_QOS_APE_OPP
,
118 (char *)__clk_get_name(hw
->clk
));
119 clk
->opp_requested
= 0;
123 clk
->is_prepared
= 1;
127 static void clk_prcmu_opp_unprepare(struct clk_hw
*hw
)
129 struct clk_prcmu
*clk
= to_clk_prcmu(hw
);
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
));
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;
143 clk
->is_prepared
= 0;
146 static int clk_prcmu_opp_volt_prepare(struct clk_hw
*hw
)
149 struct clk_prcmu
*clk
= to_clk_prcmu(hw
);
151 if (!clk
->opp_requested
) {
152 err
= prcmu_request_ape_opp_100_voltage(true);
154 pr_err("clk_prcmu: %s fail req APE OPP VOLT for %s.\n",
155 __func__
, __clk_get_name(hw
->clk
));
158 clk
->opp_requested
= 1;
161 err
= prcmu_request_clock(clk
->cg_sel
, true);
163 prcmu_request_ape_opp_100_voltage(false);
164 clk
->opp_requested
= 0;
168 clk
->is_prepared
= 1;
172 static void clk_prcmu_opp_volt_unprepare(struct clk_hw
*hw
)
174 struct clk_prcmu
*clk
= to_clk_prcmu(hw
);
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
));
182 if (clk
->opp_requested
) {
183 prcmu_request_ape_opp_100_voltage(false);
184 clk
->opp_requested
= 0;
187 clk
->is_prepared
= 0;
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
,
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
,
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
,
219 static struct clk_ops clk_prcmu_rate_ops
= {
220 .is_enabled
= clk_prcmu_is_enabled
,
221 .recalc_rate
= clk_prcmu_recalc_rate
,
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
,
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
,
246 static struct clk
*clk_reg_prcmu(const char *name
,
247 const char *parent_name
,
251 struct clk_ops
*clk_prcmu_ops
)
253 struct clk_prcmu
*clk
;
254 struct clk_init_data clk_prcmu_init
;
258 pr_err("clk_prcmu: %s invalid arguments passed\n", __func__
);
259 return ERR_PTR(-EINVAL
);
262 clk
= kzalloc(sizeof(struct clk_prcmu
), GFP_KERNEL
);
264 pr_err("clk_prcmu: %s could not allocate clk\n", __func__
);
265 return ERR_PTR(-ENOMEM
);
268 clk
->cg_sel
= cg_sel
;
269 clk
->is_prepared
= 1;
271 clk
->opp_requested
= 0;
272 /* "rate" can be used for changing the initial frequency */
274 prcmu_set_clock_rate(cg_sel
, rate
);
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
;
283 clk_reg
= clk_register(NULL
, &clk
->hw
);
284 if (IS_ERR_OR_NULL(clk_reg
))
291 pr_err("clk_prcmu: %s failed to register clk\n", __func__
);
292 return ERR_PTR(-ENOMEM
);
295 struct clk
*clk_reg_prcmu_scalable(const char *name
,
296 const char *parent_name
,
301 return clk_reg_prcmu(name
, parent_name
, cg_sel
, rate
, flags
,
302 &clk_prcmu_scalable_ops
);
305 struct clk
*clk_reg_prcmu_gate(const char *name
,
306 const char *parent_name
,
310 return clk_reg_prcmu(name
, parent_name
, cg_sel
, 0, flags
,
311 &clk_prcmu_gate_ops
);
314 struct clk
*clk_reg_prcmu_scalable_rate(const char *name
,
315 const char *parent_name
,
320 return clk_reg_prcmu(name
, parent_name
, cg_sel
, rate
, flags
,
321 &clk_prcmu_scalable_rate_ops
);
324 struct clk
*clk_reg_prcmu_rate(const char *name
,
325 const char *parent_name
,
329 return clk_reg_prcmu(name
, parent_name
, cg_sel
, 0, flags
,
330 &clk_prcmu_rate_ops
);
333 struct clk
*clk_reg_prcmu_opp_gate(const char *name
,
334 const char *parent_name
,
338 return clk_reg_prcmu(name
, parent_name
, cg_sel
, 0, flags
,
339 &clk_prcmu_opp_gate_ops
);
342 struct clk
*clk_reg_prcmu_opp_volt_scalable(const char *name
,
343 const char *parent_name
,
348 return clk_reg_prcmu(name
, parent_name
, cg_sel
, rate
, flags
,
349 &clk_prcmu_opp_volt_scalable_ops
);