1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (c) 2013 NVIDIA CORPORATION. All rights reserved.
6 #include <linux/clk-provider.h>
7 #include <linux/device.h>
9 #include <linux/slab.h>
11 static u8
clk_composite_get_parent(struct clk_hw
*hw
)
13 struct clk_composite
*composite
= to_clk_composite(hw
);
14 const struct clk_ops
*mux_ops
= composite
->mux_ops
;
15 struct clk_hw
*mux_hw
= composite
->mux_hw
;
17 __clk_hw_set_clk(mux_hw
, hw
);
19 return mux_ops
->get_parent(mux_hw
);
22 static int clk_composite_set_parent(struct clk_hw
*hw
, u8 index
)
24 struct clk_composite
*composite
= to_clk_composite(hw
);
25 const struct clk_ops
*mux_ops
= composite
->mux_ops
;
26 struct clk_hw
*mux_hw
= composite
->mux_hw
;
28 __clk_hw_set_clk(mux_hw
, hw
);
30 return mux_ops
->set_parent(mux_hw
, index
);
33 static unsigned long clk_composite_recalc_rate(struct clk_hw
*hw
,
34 unsigned long parent_rate
)
36 struct clk_composite
*composite
= to_clk_composite(hw
);
37 const struct clk_ops
*rate_ops
= composite
->rate_ops
;
38 struct clk_hw
*rate_hw
= composite
->rate_hw
;
40 __clk_hw_set_clk(rate_hw
, hw
);
42 return rate_ops
->recalc_rate(rate_hw
, parent_rate
);
45 static int clk_composite_determine_rate(struct clk_hw
*hw
,
46 struct clk_rate_request
*req
)
48 struct clk_composite
*composite
= to_clk_composite(hw
);
49 const struct clk_ops
*rate_ops
= composite
->rate_ops
;
50 const struct clk_ops
*mux_ops
= composite
->mux_ops
;
51 struct clk_hw
*rate_hw
= composite
->rate_hw
;
52 struct clk_hw
*mux_hw
= composite
->mux_hw
;
53 struct clk_hw
*parent
;
54 unsigned long parent_rate
;
55 long tmp_rate
, best_rate
= 0;
56 unsigned long rate_diff
;
57 unsigned long best_rate_diff
= ULONG_MAX
;
61 if (rate_hw
&& rate_ops
&& rate_ops
->determine_rate
) {
62 __clk_hw_set_clk(rate_hw
, hw
);
63 return rate_ops
->determine_rate(rate_hw
, req
);
64 } else if (rate_hw
&& rate_ops
&& rate_ops
->round_rate
&&
65 mux_hw
&& mux_ops
&& mux_ops
->set_parent
) {
66 req
->best_parent_hw
= NULL
;
68 if (clk_hw_get_flags(hw
) & CLK_SET_RATE_NO_REPARENT
) {
69 parent
= clk_hw_get_parent(mux_hw
);
70 req
->best_parent_hw
= parent
;
71 req
->best_parent_rate
= clk_hw_get_rate(parent
);
73 rate
= rate_ops
->round_rate(rate_hw
, req
->rate
,
74 &req
->best_parent_rate
);
82 for (i
= 0; i
< clk_hw_get_num_parents(mux_hw
); i
++) {
83 parent
= clk_hw_get_parent_by_index(mux_hw
, i
);
87 parent_rate
= clk_hw_get_rate(parent
);
89 tmp_rate
= rate_ops
->round_rate(rate_hw
, req
->rate
,
94 rate_diff
= abs(req
->rate
- tmp_rate
);
96 if (!rate_diff
|| !req
->best_parent_hw
97 || best_rate_diff
> rate_diff
) {
98 req
->best_parent_hw
= parent
;
99 req
->best_parent_rate
= parent_rate
;
100 best_rate_diff
= rate_diff
;
101 best_rate
= tmp_rate
;
108 req
->rate
= best_rate
;
110 } else if (mux_hw
&& mux_ops
&& mux_ops
->determine_rate
) {
111 __clk_hw_set_clk(mux_hw
, hw
);
112 return mux_ops
->determine_rate(mux_hw
, req
);
114 pr_err("clk: clk_composite_determine_rate function called, but no mux or rate callback set!\n");
119 static long clk_composite_round_rate(struct clk_hw
*hw
, unsigned long rate
,
120 unsigned long *prate
)
122 struct clk_composite
*composite
= to_clk_composite(hw
);
123 const struct clk_ops
*rate_ops
= composite
->rate_ops
;
124 struct clk_hw
*rate_hw
= composite
->rate_hw
;
126 __clk_hw_set_clk(rate_hw
, hw
);
128 return rate_ops
->round_rate(rate_hw
, rate
, prate
);
131 static int clk_composite_set_rate(struct clk_hw
*hw
, unsigned long rate
,
132 unsigned long parent_rate
)
134 struct clk_composite
*composite
= to_clk_composite(hw
);
135 const struct clk_ops
*rate_ops
= composite
->rate_ops
;
136 struct clk_hw
*rate_hw
= composite
->rate_hw
;
138 __clk_hw_set_clk(rate_hw
, hw
);
140 return rate_ops
->set_rate(rate_hw
, rate
, parent_rate
);
143 static int clk_composite_set_rate_and_parent(struct clk_hw
*hw
,
145 unsigned long parent_rate
,
148 struct clk_composite
*composite
= to_clk_composite(hw
);
149 const struct clk_ops
*rate_ops
= composite
->rate_ops
;
150 const struct clk_ops
*mux_ops
= composite
->mux_ops
;
151 struct clk_hw
*rate_hw
= composite
->rate_hw
;
152 struct clk_hw
*mux_hw
= composite
->mux_hw
;
153 unsigned long temp_rate
;
155 __clk_hw_set_clk(rate_hw
, hw
);
156 __clk_hw_set_clk(mux_hw
, hw
);
158 temp_rate
= rate_ops
->recalc_rate(rate_hw
, parent_rate
);
159 if (temp_rate
> rate
) {
160 rate_ops
->set_rate(rate_hw
, rate
, parent_rate
);
161 mux_ops
->set_parent(mux_hw
, index
);
163 mux_ops
->set_parent(mux_hw
, index
);
164 rate_ops
->set_rate(rate_hw
, rate
, parent_rate
);
170 static int clk_composite_is_enabled(struct clk_hw
*hw
)
172 struct clk_composite
*composite
= to_clk_composite(hw
);
173 const struct clk_ops
*gate_ops
= composite
->gate_ops
;
174 struct clk_hw
*gate_hw
= composite
->gate_hw
;
176 __clk_hw_set_clk(gate_hw
, hw
);
178 return gate_ops
->is_enabled(gate_hw
);
181 static int clk_composite_enable(struct clk_hw
*hw
)
183 struct clk_composite
*composite
= to_clk_composite(hw
);
184 const struct clk_ops
*gate_ops
= composite
->gate_ops
;
185 struct clk_hw
*gate_hw
= composite
->gate_hw
;
187 __clk_hw_set_clk(gate_hw
, hw
);
189 return gate_ops
->enable(gate_hw
);
192 static void clk_composite_disable(struct clk_hw
*hw
)
194 struct clk_composite
*composite
= to_clk_composite(hw
);
195 const struct clk_ops
*gate_ops
= composite
->gate_ops
;
196 struct clk_hw
*gate_hw
= composite
->gate_hw
;
198 __clk_hw_set_clk(gate_hw
, hw
);
200 gate_ops
->disable(gate_hw
);
203 static struct clk_hw
*__clk_hw_register_composite(struct device
*dev
,
204 const char *name
, const char * const *parent_names
,
205 const struct clk_parent_data
*pdata
, int num_parents
,
206 struct clk_hw
*mux_hw
, const struct clk_ops
*mux_ops
,
207 struct clk_hw
*rate_hw
, const struct clk_ops
*rate_ops
,
208 struct clk_hw
*gate_hw
, const struct clk_ops
*gate_ops
,
212 struct clk_init_data init
= {};
213 struct clk_composite
*composite
;
214 struct clk_ops
*clk_composite_ops
;
217 composite
= kzalloc(sizeof(*composite
), GFP_KERNEL
);
219 return ERR_PTR(-ENOMEM
);
224 init
.parent_names
= parent_names
;
226 init
.parent_data
= pdata
;
227 init
.num_parents
= num_parents
;
230 clk_composite_ops
= &composite
->ops
;
232 if (mux_hw
&& mux_ops
) {
233 if (!mux_ops
->get_parent
) {
234 hw
= ERR_PTR(-EINVAL
);
238 composite
->mux_hw
= mux_hw
;
239 composite
->mux_ops
= mux_ops
;
240 clk_composite_ops
->get_parent
= clk_composite_get_parent
;
241 if (mux_ops
->set_parent
)
242 clk_composite_ops
->set_parent
= clk_composite_set_parent
;
243 if (mux_ops
->determine_rate
)
244 clk_composite_ops
->determine_rate
= clk_composite_determine_rate
;
247 if (rate_hw
&& rate_ops
) {
248 if (!rate_ops
->recalc_rate
) {
249 hw
= ERR_PTR(-EINVAL
);
252 clk_composite_ops
->recalc_rate
= clk_composite_recalc_rate
;
254 if (rate_ops
->determine_rate
)
255 clk_composite_ops
->determine_rate
=
256 clk_composite_determine_rate
;
257 else if (rate_ops
->round_rate
)
258 clk_composite_ops
->round_rate
=
259 clk_composite_round_rate
;
261 /* .set_rate requires either .round_rate or .determine_rate */
262 if (rate_ops
->set_rate
) {
263 if (rate_ops
->determine_rate
|| rate_ops
->round_rate
)
264 clk_composite_ops
->set_rate
=
265 clk_composite_set_rate
;
267 WARN(1, "%s: missing round_rate op is required\n",
271 composite
->rate_hw
= rate_hw
;
272 composite
->rate_ops
= rate_ops
;
275 if (mux_hw
&& mux_ops
&& rate_hw
&& rate_ops
) {
276 if (mux_ops
->set_parent
&& rate_ops
->set_rate
)
277 clk_composite_ops
->set_rate_and_parent
=
278 clk_composite_set_rate_and_parent
;
281 if (gate_hw
&& gate_ops
) {
282 if (!gate_ops
->is_enabled
|| !gate_ops
->enable
||
283 !gate_ops
->disable
) {
284 hw
= ERR_PTR(-EINVAL
);
288 composite
->gate_hw
= gate_hw
;
289 composite
->gate_ops
= gate_ops
;
290 clk_composite_ops
->is_enabled
= clk_composite_is_enabled
;
291 clk_composite_ops
->enable
= clk_composite_enable
;
292 clk_composite_ops
->disable
= clk_composite_disable
;
295 init
.ops
= clk_composite_ops
;
296 composite
->hw
.init
= &init
;
298 ret
= clk_hw_register(dev
, hw
);
304 if (composite
->mux_hw
)
305 composite
->mux_hw
->clk
= hw
->clk
;
307 if (composite
->rate_hw
)
308 composite
->rate_hw
->clk
= hw
->clk
;
310 if (composite
->gate_hw
)
311 composite
->gate_hw
->clk
= hw
->clk
;
320 struct clk_hw
*clk_hw_register_composite(struct device
*dev
, const char *name
,
321 const char * const *parent_names
, int num_parents
,
322 struct clk_hw
*mux_hw
, const struct clk_ops
*mux_ops
,
323 struct clk_hw
*rate_hw
, const struct clk_ops
*rate_ops
,
324 struct clk_hw
*gate_hw
, const struct clk_ops
*gate_ops
,
327 return __clk_hw_register_composite(dev
, name
, parent_names
, NULL
,
328 num_parents
, mux_hw
, mux_ops
,
329 rate_hw
, rate_ops
, gate_hw
,
332 EXPORT_SYMBOL_GPL(clk_hw_register_composite
);
334 struct clk_hw
*clk_hw_register_composite_pdata(struct device
*dev
,
336 const struct clk_parent_data
*parent_data
,
338 struct clk_hw
*mux_hw
, const struct clk_ops
*mux_ops
,
339 struct clk_hw
*rate_hw
, const struct clk_ops
*rate_ops
,
340 struct clk_hw
*gate_hw
, const struct clk_ops
*gate_ops
,
343 return __clk_hw_register_composite(dev
, name
, NULL
, parent_data
,
344 num_parents
, mux_hw
, mux_ops
,
345 rate_hw
, rate_ops
, gate_hw
,
349 struct clk
*clk_register_composite(struct device
*dev
, const char *name
,
350 const char * const *parent_names
, int num_parents
,
351 struct clk_hw
*mux_hw
, const struct clk_ops
*mux_ops
,
352 struct clk_hw
*rate_hw
, const struct clk_ops
*rate_ops
,
353 struct clk_hw
*gate_hw
, const struct clk_ops
*gate_ops
,
358 hw
= clk_hw_register_composite(dev
, name
, parent_names
, num_parents
,
359 mux_hw
, mux_ops
, rate_hw
, rate_ops
, gate_hw
, gate_ops
,
366 struct clk
*clk_register_composite_pdata(struct device
*dev
, const char *name
,
367 const struct clk_parent_data
*parent_data
,
369 struct clk_hw
*mux_hw
, const struct clk_ops
*mux_ops
,
370 struct clk_hw
*rate_hw
, const struct clk_ops
*rate_ops
,
371 struct clk_hw
*gate_hw
, const struct clk_ops
*gate_ops
,
376 hw
= clk_hw_register_composite_pdata(dev
, name
, parent_data
,
377 num_parents
, mux_hw
, mux_ops
, rate_hw
, rate_ops
,
378 gate_hw
, gate_ops
, flags
);
384 void clk_unregister_composite(struct clk
*clk
)
386 struct clk_composite
*composite
;
389 hw
= __clk_get_hw(clk
);
393 composite
= to_clk_composite(hw
);
399 void clk_hw_unregister_composite(struct clk_hw
*hw
)
401 struct clk_composite
*composite
;
403 composite
= to_clk_composite(hw
);
405 clk_hw_unregister(hw
);
408 EXPORT_SYMBOL_GPL(clk_hw_unregister_composite
);
410 static void devm_clk_hw_release_composite(struct device
*dev
, void *res
)
412 clk_hw_unregister_composite(*(struct clk_hw
**)res
);
415 static struct clk_hw
*__devm_clk_hw_register_composite(struct device
*dev
,
416 const char *name
, const char * const *parent_names
,
417 const struct clk_parent_data
*pdata
, int num_parents
,
418 struct clk_hw
*mux_hw
, const struct clk_ops
*mux_ops
,
419 struct clk_hw
*rate_hw
, const struct clk_ops
*rate_ops
,
420 struct clk_hw
*gate_hw
, const struct clk_ops
*gate_ops
,
423 struct clk_hw
**ptr
, *hw
;
425 ptr
= devres_alloc(devm_clk_hw_release_composite
, sizeof(*ptr
),
428 return ERR_PTR(-ENOMEM
);
430 hw
= __clk_hw_register_composite(dev
, name
, parent_names
, pdata
,
431 num_parents
, mux_hw
, mux_ops
, rate_hw
,
432 rate_ops
, gate_hw
, gate_ops
, flags
);
436 devres_add(dev
, ptr
);
444 struct clk_hw
*devm_clk_hw_register_composite_pdata(struct device
*dev
,
446 const struct clk_parent_data
*parent_data
,
448 struct clk_hw
*mux_hw
, const struct clk_ops
*mux_ops
,
449 struct clk_hw
*rate_hw
, const struct clk_ops
*rate_ops
,
450 struct clk_hw
*gate_hw
, const struct clk_ops
*gate_ops
,
453 return __devm_clk_hw_register_composite(dev
, name
, NULL
, parent_data
,
454 num_parents
, mux_hw
, mux_ops
,
455 rate_hw
, rate_ops
, gate_hw
,