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)
26 /* PRCMU clock operations. */
28 static int clk_prcmu_prepare(struct clk_hw
*hw
)
30 struct clk_prcmu
*clk
= to_clk_prcmu(hw
);
31 return prcmu_request_clock(clk
->cg_sel
, true);
34 static void clk_prcmu_unprepare(struct clk_hw
*hw
)
36 struct clk_prcmu
*clk
= to_clk_prcmu(hw
);
37 if (prcmu_request_clock(clk
->cg_sel
, false))
38 pr_err("clk_prcmu: %s failed to disable %s.\n", __func__
,
42 static int clk_prcmu_enable(struct clk_hw
*hw
)
44 struct clk_prcmu
*clk
= to_clk_prcmu(hw
);
49 static void clk_prcmu_disable(struct clk_hw
*hw
)
51 struct clk_prcmu
*clk
= to_clk_prcmu(hw
);
55 static int clk_prcmu_is_enabled(struct clk_hw
*hw
)
57 struct clk_prcmu
*clk
= to_clk_prcmu(hw
);
58 return clk
->is_enabled
;
61 static unsigned long clk_prcmu_recalc_rate(struct clk_hw
*hw
,
62 unsigned long parent_rate
)
64 struct clk_prcmu
*clk
= to_clk_prcmu(hw
);
65 return prcmu_clock_rate(clk
->cg_sel
);
68 static long clk_prcmu_round_rate(struct clk_hw
*hw
, unsigned long rate
,
69 unsigned long *parent_rate
)
71 struct clk_prcmu
*clk
= to_clk_prcmu(hw
);
72 return prcmu_round_clock_rate(clk
->cg_sel
, rate
);
75 static int clk_prcmu_set_rate(struct clk_hw
*hw
, unsigned long rate
,
76 unsigned long parent_rate
)
78 struct clk_prcmu
*clk
= to_clk_prcmu(hw
);
79 return prcmu_set_clock_rate(clk
->cg_sel
, rate
);
82 static int request_ape_opp100(bool enable
)
89 err
= prcmu_qos_add_requirement(PRCMU_QOS_APE_OPP
,
96 prcmu_qos_remove_requirement(PRCMU_QOS_APE_OPP
,
102 static int clk_prcmu_opp_prepare(struct clk_hw
*hw
)
105 struct clk_prcmu
*clk
= to_clk_prcmu(hw
);
107 err
= request_ape_opp100(true);
109 pr_err("clk_prcmu: %s failed to request APE OPP100 for %s.\n",
110 __func__
, hw
->init
->name
);
114 err
= prcmu_request_clock(clk
->cg_sel
, true);
116 request_ape_opp100(false);
121 static void clk_prcmu_opp_unprepare(struct clk_hw
*hw
)
123 struct clk_prcmu
*clk
= to_clk_prcmu(hw
);
125 if (prcmu_request_clock(clk
->cg_sel
, false))
127 if (request_ape_opp100(false))
132 pr_err("clk_prcmu: %s failed to disable %s.\n", __func__
,
136 static int clk_prcmu_opp_volt_prepare(struct clk_hw
*hw
)
139 struct clk_prcmu
*clk
= to_clk_prcmu(hw
);
141 err
= prcmu_request_ape_opp_100_voltage(true);
143 pr_err("clk_prcmu: %s failed to request APE OPP VOLT for %s.\n",
144 __func__
, hw
->init
->name
);
148 err
= prcmu_request_clock(clk
->cg_sel
, true);
150 prcmu_request_ape_opp_100_voltage(false);
155 static void clk_prcmu_opp_volt_unprepare(struct clk_hw
*hw
)
157 struct clk_prcmu
*clk
= to_clk_prcmu(hw
);
159 if (prcmu_request_clock(clk
->cg_sel
, false))
161 if (prcmu_request_ape_opp_100_voltage(false))
166 pr_err("clk_prcmu: %s failed to disable %s.\n", __func__
,
170 static struct clk_ops clk_prcmu_scalable_ops
= {
171 .prepare
= clk_prcmu_prepare
,
172 .unprepare
= clk_prcmu_unprepare
,
173 .enable
= clk_prcmu_enable
,
174 .disable
= clk_prcmu_disable
,
175 .is_enabled
= clk_prcmu_is_enabled
,
176 .recalc_rate
= clk_prcmu_recalc_rate
,
177 .round_rate
= clk_prcmu_round_rate
,
178 .set_rate
= clk_prcmu_set_rate
,
181 static struct clk_ops clk_prcmu_gate_ops
= {
182 .prepare
= clk_prcmu_prepare
,
183 .unprepare
= clk_prcmu_unprepare
,
184 .enable
= clk_prcmu_enable
,
185 .disable
= clk_prcmu_disable
,
186 .is_enabled
= clk_prcmu_is_enabled
,
187 .recalc_rate
= clk_prcmu_recalc_rate
,
190 static struct clk_ops clk_prcmu_scalable_rate_ops
= {
191 .is_enabled
= clk_prcmu_is_enabled
,
192 .recalc_rate
= clk_prcmu_recalc_rate
,
193 .round_rate
= clk_prcmu_round_rate
,
194 .set_rate
= clk_prcmu_set_rate
,
197 static struct clk_ops clk_prcmu_rate_ops
= {
198 .is_enabled
= clk_prcmu_is_enabled
,
199 .recalc_rate
= clk_prcmu_recalc_rate
,
202 static struct clk_ops clk_prcmu_opp_gate_ops
= {
203 .prepare
= clk_prcmu_opp_prepare
,
204 .unprepare
= clk_prcmu_opp_unprepare
,
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_opp_volt_scalable_ops
= {
212 .prepare
= clk_prcmu_opp_volt_prepare
,
213 .unprepare
= clk_prcmu_opp_volt_unprepare
,
214 .enable
= clk_prcmu_enable
,
215 .disable
= clk_prcmu_disable
,
216 .is_enabled
= clk_prcmu_is_enabled
,
217 .recalc_rate
= clk_prcmu_recalc_rate
,
218 .round_rate
= clk_prcmu_round_rate
,
219 .set_rate
= clk_prcmu_set_rate
,
222 static struct clk
*clk_reg_prcmu(const char *name
,
223 const char *parent_name
,
227 struct clk_ops
*clk_prcmu_ops
)
229 struct clk_prcmu
*clk
;
230 struct clk_init_data clk_prcmu_init
;
234 pr_err("clk_prcmu: %s invalid arguments passed\n", __func__
);
235 return ERR_PTR(-EINVAL
);
238 clk
= kzalloc(sizeof(struct clk_prcmu
), GFP_KERNEL
);
240 pr_err("clk_prcmu: %s could not allocate clk\n", __func__
);
241 return ERR_PTR(-ENOMEM
);
244 clk
->cg_sel
= cg_sel
;
246 /* "rate" can be used for changing the initial frequency */
248 prcmu_set_clock_rate(cg_sel
, rate
);
250 clk_prcmu_init
.name
= name
;
251 clk_prcmu_init
.ops
= clk_prcmu_ops
;
252 clk_prcmu_init
.flags
= flags
;
253 clk_prcmu_init
.parent_names
= (parent_name
? &parent_name
: NULL
);
254 clk_prcmu_init
.num_parents
= (parent_name
? 1 : 0);
255 clk
->hw
.init
= &clk_prcmu_init
;
257 clk_reg
= clk_register(NULL
, &clk
->hw
);
258 if (IS_ERR_OR_NULL(clk_reg
))
265 pr_err("clk_prcmu: %s failed to register clk\n", __func__
);
266 return ERR_PTR(-ENOMEM
);
269 struct clk
*clk_reg_prcmu_scalable(const char *name
,
270 const char *parent_name
,
275 return clk_reg_prcmu(name
, parent_name
, cg_sel
, rate
, flags
,
276 &clk_prcmu_scalable_ops
);
279 struct clk
*clk_reg_prcmu_gate(const char *name
,
280 const char *parent_name
,
284 return clk_reg_prcmu(name
, parent_name
, cg_sel
, 0, flags
,
285 &clk_prcmu_gate_ops
);
288 struct clk
*clk_reg_prcmu_scalable_rate(const char *name
,
289 const char *parent_name
,
294 return clk_reg_prcmu(name
, parent_name
, cg_sel
, rate
, flags
,
295 &clk_prcmu_scalable_rate_ops
);
298 struct clk
*clk_reg_prcmu_rate(const char *name
,
299 const char *parent_name
,
303 return clk_reg_prcmu(name
, parent_name
, cg_sel
, 0, flags
,
304 &clk_prcmu_rate_ops
);
307 struct clk
*clk_reg_prcmu_opp_gate(const char *name
,
308 const char *parent_name
,
312 return clk_reg_prcmu(name
, parent_name
, cg_sel
, 0, flags
,
313 &clk_prcmu_opp_gate_ops
);
316 struct clk
*clk_reg_prcmu_opp_volt_scalable(const char *name
,
317 const char *parent_name
,
322 return clk_reg_prcmu(name
, parent_name
, cg_sel
, rate
, flags
,
323 &clk_prcmu_opp_volt_scalable_ops
);