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/mfd/dbx500-prcmu.h>
12 #include <linux/slab.h>
14 #include <linux/err.h>
17 #define to_clk_prcmu(_hw) container_of(_hw, struct clk_prcmu, hw)
27 /* PRCMU clock operations. */
29 static int clk_prcmu_prepare(struct clk_hw
*hw
)
32 struct clk_prcmu
*clk
= to_clk_prcmu(hw
);
34 ret
= prcmu_request_clock(clk
->cg_sel
, true);
41 static void clk_prcmu_unprepare(struct clk_hw
*hw
)
43 struct clk_prcmu
*clk
= to_clk_prcmu(hw
);
44 if (prcmu_request_clock(clk
->cg_sel
, false))
45 pr_err("clk_prcmu: %s failed to disable %s.\n", __func__
,
51 static int clk_prcmu_is_prepared(struct clk_hw
*hw
)
53 struct clk_prcmu
*clk
= to_clk_prcmu(hw
);
54 return clk
->is_prepared
;
57 static int clk_prcmu_enable(struct clk_hw
*hw
)
59 struct clk_prcmu
*clk
= to_clk_prcmu(hw
);
64 static void clk_prcmu_disable(struct clk_hw
*hw
)
66 struct clk_prcmu
*clk
= to_clk_prcmu(hw
);
70 static int clk_prcmu_is_enabled(struct clk_hw
*hw
)
72 struct clk_prcmu
*clk
= to_clk_prcmu(hw
);
73 return clk
->is_enabled
;
76 static unsigned long clk_prcmu_recalc_rate(struct clk_hw
*hw
,
77 unsigned long parent_rate
)
79 struct clk_prcmu
*clk
= to_clk_prcmu(hw
);
80 return prcmu_clock_rate(clk
->cg_sel
);
83 static long clk_prcmu_round_rate(struct clk_hw
*hw
, unsigned long rate
,
84 unsigned long *parent_rate
)
86 struct clk_prcmu
*clk
= to_clk_prcmu(hw
);
87 return prcmu_round_clock_rate(clk
->cg_sel
, rate
);
90 static int clk_prcmu_set_rate(struct clk_hw
*hw
, unsigned long rate
,
91 unsigned long parent_rate
)
93 struct clk_prcmu
*clk
= to_clk_prcmu(hw
);
94 return prcmu_set_clock_rate(clk
->cg_sel
, rate
);
97 static int clk_prcmu_opp_prepare(struct clk_hw
*hw
)
100 struct clk_prcmu
*clk
= to_clk_prcmu(hw
);
102 if (!clk
->opp_requested
) {
103 err
= prcmu_qos_add_requirement(PRCMU_QOS_APE_OPP
,
104 (char *)clk_hw_get_name(hw
),
107 pr_err("clk_prcmu: %s fail req APE OPP for %s.\n",
108 __func__
, clk_hw_get_name(hw
));
111 clk
->opp_requested
= 1;
114 err
= prcmu_request_clock(clk
->cg_sel
, true);
116 prcmu_qos_remove_requirement(PRCMU_QOS_APE_OPP
,
117 (char *)clk_hw_get_name(hw
));
118 clk
->opp_requested
= 0;
122 clk
->is_prepared
= 1;
126 static void clk_prcmu_opp_unprepare(struct clk_hw
*hw
)
128 struct clk_prcmu
*clk
= to_clk_prcmu(hw
);
130 if (prcmu_request_clock(clk
->cg_sel
, false)) {
131 pr_err("clk_prcmu: %s failed to disable %s.\n", __func__
,
132 clk_hw_get_name(hw
));
136 if (clk
->opp_requested
) {
137 prcmu_qos_remove_requirement(PRCMU_QOS_APE_OPP
,
138 (char *)clk_hw_get_name(hw
));
139 clk
->opp_requested
= 0;
142 clk
->is_prepared
= 0;
145 static int clk_prcmu_opp_volt_prepare(struct clk_hw
*hw
)
148 struct clk_prcmu
*clk
= to_clk_prcmu(hw
);
150 if (!clk
->opp_requested
) {
151 err
= prcmu_request_ape_opp_100_voltage(true);
153 pr_err("clk_prcmu: %s fail req APE OPP VOLT for %s.\n",
154 __func__
, clk_hw_get_name(hw
));
157 clk
->opp_requested
= 1;
160 err
= prcmu_request_clock(clk
->cg_sel
, true);
162 prcmu_request_ape_opp_100_voltage(false);
163 clk
->opp_requested
= 0;
167 clk
->is_prepared
= 1;
171 static void clk_prcmu_opp_volt_unprepare(struct clk_hw
*hw
)
173 struct clk_prcmu
*clk
= to_clk_prcmu(hw
);
175 if (prcmu_request_clock(clk
->cg_sel
, false)) {
176 pr_err("clk_prcmu: %s failed to disable %s.\n", __func__
,
177 clk_hw_get_name(hw
));
181 if (clk
->opp_requested
) {
182 prcmu_request_ape_opp_100_voltage(false);
183 clk
->opp_requested
= 0;
186 clk
->is_prepared
= 0;
189 static struct clk_ops clk_prcmu_scalable_ops
= {
190 .prepare
= clk_prcmu_prepare
,
191 .unprepare
= clk_prcmu_unprepare
,
192 .is_prepared
= clk_prcmu_is_prepared
,
193 .enable
= clk_prcmu_enable
,
194 .disable
= clk_prcmu_disable
,
195 .is_enabled
= clk_prcmu_is_enabled
,
196 .recalc_rate
= clk_prcmu_recalc_rate
,
197 .round_rate
= clk_prcmu_round_rate
,
198 .set_rate
= clk_prcmu_set_rate
,
201 static struct clk_ops clk_prcmu_gate_ops
= {
202 .prepare
= clk_prcmu_prepare
,
203 .unprepare
= clk_prcmu_unprepare
,
204 .is_prepared
= clk_prcmu_is_prepared
,
205 .enable
= clk_prcmu_enable
,
206 .disable
= clk_prcmu_disable
,
207 .is_enabled
= clk_prcmu_is_enabled
,
208 .recalc_rate
= clk_prcmu_recalc_rate
,
211 static struct clk_ops clk_prcmu_scalable_rate_ops
= {
212 .is_enabled
= clk_prcmu_is_enabled
,
213 .recalc_rate
= clk_prcmu_recalc_rate
,
214 .round_rate
= clk_prcmu_round_rate
,
215 .set_rate
= clk_prcmu_set_rate
,
218 static struct clk_ops clk_prcmu_rate_ops
= {
219 .is_enabled
= clk_prcmu_is_enabled
,
220 .recalc_rate
= clk_prcmu_recalc_rate
,
223 static struct clk_ops clk_prcmu_opp_gate_ops
= {
224 .prepare
= clk_prcmu_opp_prepare
,
225 .unprepare
= clk_prcmu_opp_unprepare
,
226 .is_prepared
= clk_prcmu_is_prepared
,
227 .enable
= clk_prcmu_enable
,
228 .disable
= clk_prcmu_disable
,
229 .is_enabled
= clk_prcmu_is_enabled
,
230 .recalc_rate
= clk_prcmu_recalc_rate
,
233 static struct clk_ops clk_prcmu_opp_volt_scalable_ops
= {
234 .prepare
= clk_prcmu_opp_volt_prepare
,
235 .unprepare
= clk_prcmu_opp_volt_unprepare
,
236 .is_prepared
= clk_prcmu_is_prepared
,
237 .enable
= clk_prcmu_enable
,
238 .disable
= clk_prcmu_disable
,
239 .is_enabled
= clk_prcmu_is_enabled
,
240 .recalc_rate
= clk_prcmu_recalc_rate
,
241 .round_rate
= clk_prcmu_round_rate
,
242 .set_rate
= clk_prcmu_set_rate
,
245 static struct clk
*clk_reg_prcmu(const char *name
,
246 const char *parent_name
,
250 struct clk_ops
*clk_prcmu_ops
)
252 struct clk_prcmu
*clk
;
253 struct clk_init_data clk_prcmu_init
;
257 pr_err("clk_prcmu: %s invalid arguments passed\n", __func__
);
258 return ERR_PTR(-EINVAL
);
261 clk
= kzalloc(sizeof(struct clk_prcmu
), GFP_KERNEL
);
263 pr_err("clk_prcmu: %s could not allocate clk\n", __func__
);
264 return ERR_PTR(-ENOMEM
);
267 clk
->cg_sel
= cg_sel
;
268 clk
->is_prepared
= 1;
270 clk
->opp_requested
= 0;
271 /* "rate" can be used for changing the initial frequency */
273 prcmu_set_clock_rate(cg_sel
, rate
);
275 clk_prcmu_init
.name
= name
;
276 clk_prcmu_init
.ops
= clk_prcmu_ops
;
277 clk_prcmu_init
.flags
= flags
;
278 clk_prcmu_init
.parent_names
= (parent_name
? &parent_name
: NULL
);
279 clk_prcmu_init
.num_parents
= (parent_name
? 1 : 0);
280 clk
->hw
.init
= &clk_prcmu_init
;
282 clk_reg
= clk_register(NULL
, &clk
->hw
);
283 if (IS_ERR_OR_NULL(clk_reg
))
290 pr_err("clk_prcmu: %s failed to register clk\n", __func__
);
291 return ERR_PTR(-ENOMEM
);
294 struct clk
*clk_reg_prcmu_scalable(const char *name
,
295 const char *parent_name
,
300 return clk_reg_prcmu(name
, parent_name
, cg_sel
, rate
, flags
,
301 &clk_prcmu_scalable_ops
);
304 struct clk
*clk_reg_prcmu_gate(const char *name
,
305 const char *parent_name
,
309 return clk_reg_prcmu(name
, parent_name
, cg_sel
, 0, flags
,
310 &clk_prcmu_gate_ops
);
313 struct clk
*clk_reg_prcmu_scalable_rate(const char *name
,
314 const char *parent_name
,
319 return clk_reg_prcmu(name
, parent_name
, cg_sel
, rate
, flags
,
320 &clk_prcmu_scalable_rate_ops
);
323 struct clk
*clk_reg_prcmu_rate(const char *name
,
324 const char *parent_name
,
328 return clk_reg_prcmu(name
, parent_name
, cg_sel
, 0, flags
,
329 &clk_prcmu_rate_ops
);
332 struct clk
*clk_reg_prcmu_opp_gate(const char *name
,
333 const char *parent_name
,
337 return clk_reg_prcmu(name
, parent_name
, cg_sel
, 0, flags
,
338 &clk_prcmu_opp_gate_ops
);
341 struct clk
*clk_reg_prcmu_opp_volt_scalable(const char *name
,
342 const char *parent_name
,
347 return clk_reg_prcmu(name
, parent_name
, cg_sel
, rate
, flags
,
348 &clk_prcmu_opp_volt_scalable_ops
);