1 // SPDX-License-Identifier: GPL-2.0-only
3 * PRCMU clock implementation for ux500 platform.
5 * Copyright (C) 2012 ST-Ericsson SA
6 * Author: Ulf Hansson <ulf.hansson@linaro.org>
9 #include <linux/clk-provider.h>
10 #include <linux/mfd/dbx500-prcmu.h>
11 #include <linux/slab.h>
13 #include <linux/err.h>
16 #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
)
31 struct clk_prcmu
*clk
= to_clk_prcmu(hw
);
33 ret
= prcmu_request_clock(clk
->cg_sel
, true);
40 static void clk_prcmu_unprepare(struct clk_hw
*hw
)
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__
,
50 static int clk_prcmu_is_prepared(struct clk_hw
*hw
)
52 struct clk_prcmu
*clk
= to_clk_prcmu(hw
);
53 return clk
->is_prepared
;
56 static int clk_prcmu_enable(struct clk_hw
*hw
)
58 struct clk_prcmu
*clk
= to_clk_prcmu(hw
);
63 static void clk_prcmu_disable(struct clk_hw
*hw
)
65 struct clk_prcmu
*clk
= to_clk_prcmu(hw
);
69 static int clk_prcmu_is_enabled(struct clk_hw
*hw
)
71 struct clk_prcmu
*clk
= to_clk_prcmu(hw
);
72 return clk
->is_enabled
;
75 static unsigned long clk_prcmu_recalc_rate(struct clk_hw
*hw
,
76 unsigned long parent_rate
)
78 struct clk_prcmu
*clk
= to_clk_prcmu(hw
);
79 return prcmu_clock_rate(clk
->cg_sel
);
82 static long clk_prcmu_round_rate(struct clk_hw
*hw
, unsigned long rate
,
83 unsigned long *parent_rate
)
85 struct clk_prcmu
*clk
= to_clk_prcmu(hw
);
86 return prcmu_round_clock_rate(clk
->cg_sel
, rate
);
89 static int clk_prcmu_set_rate(struct clk_hw
*hw
, unsigned long rate
,
90 unsigned long parent_rate
)
92 struct clk_prcmu
*clk
= to_clk_prcmu(hw
);
93 return prcmu_set_clock_rate(clk
->cg_sel
, rate
);
96 static int clk_prcmu_opp_prepare(struct clk_hw
*hw
)
99 struct clk_prcmu
*clk
= to_clk_prcmu(hw
);
101 if (!clk
->opp_requested
) {
102 err
= prcmu_qos_add_requirement(PRCMU_QOS_APE_OPP
,
103 (char *)clk_hw_get_name(hw
),
106 pr_err("clk_prcmu: %s fail req APE OPP for %s.\n",
107 __func__
, clk_hw_get_name(hw
));
110 clk
->opp_requested
= 1;
113 err
= prcmu_request_clock(clk
->cg_sel
, true);
115 prcmu_qos_remove_requirement(PRCMU_QOS_APE_OPP
,
116 (char *)clk_hw_get_name(hw
));
117 clk
->opp_requested
= 0;
121 clk
->is_prepared
= 1;
125 static void clk_prcmu_opp_unprepare(struct clk_hw
*hw
)
127 struct clk_prcmu
*clk
= to_clk_prcmu(hw
);
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
));
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;
141 clk
->is_prepared
= 0;
144 static int clk_prcmu_opp_volt_prepare(struct clk_hw
*hw
)
147 struct clk_prcmu
*clk
= to_clk_prcmu(hw
);
149 if (!clk
->opp_requested
) {
150 err
= prcmu_request_ape_opp_100_voltage(true);
152 pr_err("clk_prcmu: %s fail req APE OPP VOLT for %s.\n",
153 __func__
, clk_hw_get_name(hw
));
156 clk
->opp_requested
= 1;
159 err
= prcmu_request_clock(clk
->cg_sel
, true);
161 prcmu_request_ape_opp_100_voltage(false);
162 clk
->opp_requested
= 0;
166 clk
->is_prepared
= 1;
170 static void clk_prcmu_opp_volt_unprepare(struct clk_hw
*hw
)
172 struct clk_prcmu
*clk
= to_clk_prcmu(hw
);
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
));
180 if (clk
->opp_requested
) {
181 prcmu_request_ape_opp_100_voltage(false);
182 clk
->opp_requested
= 0;
185 clk
->is_prepared
= 0;
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
,
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
,
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
,
217 static const struct clk_ops clk_prcmu_rate_ops
= {
218 .is_enabled
= clk_prcmu_is_enabled
,
219 .recalc_rate
= clk_prcmu_recalc_rate
,
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
,
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
,
244 static struct clk
*clk_reg_prcmu(const char *name
,
245 const char *parent_name
,
249 const struct clk_ops
*clk_prcmu_ops
)
251 struct clk_prcmu
*clk
;
252 struct clk_init_data clk_prcmu_init
;
256 pr_err("clk_prcmu: %s invalid arguments passed\n", __func__
);
257 return ERR_PTR(-EINVAL
);
260 clk
= kzalloc(sizeof(*clk
), GFP_KERNEL
);
262 return ERR_PTR(-ENOMEM
);
264 clk
->cg_sel
= cg_sel
;
265 clk
->is_prepared
= 1;
267 clk
->opp_requested
= 0;
268 /* "rate" can be used for changing the initial frequency */
270 prcmu_set_clock_rate(cg_sel
, rate
);
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
;
279 clk_reg
= clk_register(NULL
, &clk
->hw
);
280 if (IS_ERR_OR_NULL(clk_reg
))
287 pr_err("clk_prcmu: %s failed to register clk\n", __func__
);
288 return ERR_PTR(-ENOMEM
);
291 struct clk
*clk_reg_prcmu_scalable(const char *name
,
292 const char *parent_name
,
297 return clk_reg_prcmu(name
, parent_name
, cg_sel
, rate
, flags
,
298 &clk_prcmu_scalable_ops
);
301 struct clk
*clk_reg_prcmu_gate(const char *name
,
302 const char *parent_name
,
306 return clk_reg_prcmu(name
, parent_name
, cg_sel
, 0, flags
,
307 &clk_prcmu_gate_ops
);
310 struct clk
*clk_reg_prcmu_scalable_rate(const char *name
,
311 const char *parent_name
,
316 return clk_reg_prcmu(name
, parent_name
, cg_sel
, rate
, flags
,
317 &clk_prcmu_scalable_rate_ops
);
320 struct clk
*clk_reg_prcmu_rate(const char *name
,
321 const char *parent_name
,
325 return clk_reg_prcmu(name
, parent_name
, cg_sel
, 0, flags
,
326 &clk_prcmu_rate_ops
);
329 struct clk
*clk_reg_prcmu_opp_gate(const char *name
,
330 const char *parent_name
,
334 return clk_reg_prcmu(name
, parent_name
, cg_sel
, 0, flags
,
335 &clk_prcmu_opp_gate_ops
);
338 struct clk
*clk_reg_prcmu_opp_volt_scalable(const char *name
,
339 const char *parent_name
,
344 return clk_reg_prcmu(name
, parent_name
, cg_sel
, rate
, flags
,
345 &clk_prcmu_opp_volt_scalable_ops
);