1 // SPDX-License-Identifier: GPL-2.0
3 * Zynq UltraScale+ MPSoC Divider support
5 * Copyright (C) 2016-2019 Xilinx
7 * Adjustable divider clock implementation
10 #include <linux/clk.h>
11 #include <linux/clk-provider.h>
12 #include <linux/slab.h>
13 #include "clk-zynqmp.h"
16 * DOC: basic adjustable divider clock that cannot gate
18 * Traits of this clock:
19 * prepare - clk_prepare only ensures that parents are prepared
20 * enable - clk_enable only ensures that parents are enabled
21 * rate - rate is adjustable. clk->rate = ceiling(parent->rate / divisor)
22 * parent - fixed parent. No clk_set_parent support
25 #define to_zynqmp_clk_divider(_hw) \
26 container_of(_hw, struct zynqmp_clk_divider, hw)
28 #define CLK_FRAC BIT(13) /* has a fractional parent */
29 #define CUSTOM_FLAG_CLK_FRAC BIT(0) /* has a fractional parent in custom type flag */
32 * struct zynqmp_clk_divider - adjustable divider clock
33 * @hw: handle between common and hardware-specific interfaces
34 * @flags: Hardware specific flags
35 * @is_frac: The divider is a fractional divider
36 * @clk_id: Id of clock
37 * @div_type: divisor type (TYPE_DIV1 or TYPE_DIV2)
39 struct zynqmp_clk_divider
{
48 static inline int zynqmp_divider_get_val(unsigned long parent_rate
,
49 unsigned long rate
, u16 flags
)
52 unsigned long up_rate
, down_rate
;
54 if (flags
& CLK_DIVIDER_POWER_OF_TWO
) {
55 up
= DIV_ROUND_UP_ULL((u64
)parent_rate
, rate
);
56 down
= DIV_ROUND_DOWN_ULL((u64
)parent_rate
, rate
);
58 up
= __roundup_pow_of_two(up
);
59 down
= __rounddown_pow_of_two(down
);
61 up_rate
= DIV_ROUND_UP_ULL((u64
)parent_rate
, up
);
62 down_rate
= DIV_ROUND_UP_ULL((u64
)parent_rate
, down
);
64 return (rate
- up_rate
) <= (down_rate
- rate
) ? up
: down
;
67 return DIV_ROUND_CLOSEST(parent_rate
, rate
);
72 * zynqmp_clk_divider_recalc_rate() - Recalc rate of divider clock
73 * @hw: handle between common and hardware-specific interfaces
74 * @parent_rate: rate of parent clock
76 * Return: 0 on success else error+reason
78 static unsigned long zynqmp_clk_divider_recalc_rate(struct clk_hw
*hw
,
79 unsigned long parent_rate
)
81 struct zynqmp_clk_divider
*divider
= to_zynqmp_clk_divider(hw
);
82 const char *clk_name
= clk_hw_get_name(hw
);
83 u32 clk_id
= divider
->clk_id
;
84 u32 div_type
= divider
->div_type
;
88 ret
= zynqmp_pm_clock_getdivider(clk_id
, &div
);
91 pr_warn_once("%s() get divider failed for %s, ret = %d\n",
92 __func__
, clk_name
, ret
);
94 if (div_type
== TYPE_DIV1
)
99 if (divider
->flags
& CLK_DIVIDER_POWER_OF_TWO
)
103 WARN(!(divider
->flags
& CLK_DIVIDER_ALLOW_ZERO
),
104 "%s: Zero divisor and CLK_DIVIDER_ALLOW_ZERO not set\n",
109 return DIV_ROUND_UP_ULL(parent_rate
, value
);
112 static void zynqmp_get_divider2_val(struct clk_hw
*hw
,
114 struct zynqmp_clk_divider
*divider
,
119 long error
= LONG_MAX
;
120 unsigned long div1_prate
;
121 struct clk_hw
*div1_parent_hw
;
122 struct clk_hw
*div2_parent_hw
= clk_hw_get_parent(hw
);
123 struct zynqmp_clk_divider
*pdivider
=
124 to_zynqmp_clk_divider(div2_parent_hw
);
129 div1_parent_hw
= clk_hw_get_parent(div2_parent_hw
);
133 div1_prate
= clk_hw_get_rate(div1_parent_hw
);
135 for (div1
= 1; div1
<= pdivider
->max_div
;) {
136 for (div2
= 1; div2
<= divider
->max_div
;) {
137 long new_error
= ((div1_prate
/ div1
) / div2
) - rate
;
139 if (abs(new_error
) < abs(error
)) {
143 if (divider
->flags
& CLK_DIVIDER_POWER_OF_TWO
)
148 if (pdivider
->flags
& CLK_DIVIDER_POWER_OF_TWO
)
156 * zynqmp_clk_divider_round_rate() - Round rate of divider clock
157 * @hw: handle between common and hardware-specific interfaces
158 * @rate: rate of clock to be set
159 * @prate: rate of parent clock
161 * Return: 0 on success else error+reason
163 static long zynqmp_clk_divider_round_rate(struct clk_hw
*hw
,
165 unsigned long *prate
)
167 struct zynqmp_clk_divider
*divider
= to_zynqmp_clk_divider(hw
);
168 const char *clk_name
= clk_hw_get_name(hw
);
169 u32 clk_id
= divider
->clk_id
;
170 u32 div_type
= divider
->div_type
;
174 /* if read only, just return current value */
175 if (divider
->flags
& CLK_DIVIDER_READ_ONLY
) {
176 ret
= zynqmp_pm_clock_getdivider(clk_id
, &bestdiv
);
179 pr_warn_once("%s() get divider failed for %s, ret = %d\n",
180 __func__
, clk_name
, ret
);
181 if (div_type
== TYPE_DIV1
)
182 bestdiv
= bestdiv
& 0xFFFF;
184 bestdiv
= bestdiv
>> 16;
186 if (divider
->flags
& CLK_DIVIDER_POWER_OF_TWO
)
187 bestdiv
= 1 << bestdiv
;
189 return DIV_ROUND_UP_ULL((u64
)*prate
, bestdiv
);
192 bestdiv
= zynqmp_divider_get_val(*prate
, rate
, divider
->flags
);
195 * In case of two divisors, compute best divider values and return
196 * divider2 value based on compute value. div1 will be automatically
197 * set to optimum based on required total divider value.
199 if (div_type
== TYPE_DIV2
&&
200 (clk_hw_get_flags(hw
) & CLK_SET_RATE_PARENT
)) {
201 zynqmp_get_divider2_val(hw
, rate
, divider
, &bestdiv
);
204 if ((clk_hw_get_flags(hw
) & CLK_SET_RATE_PARENT
) && divider
->is_frac
)
205 bestdiv
= rate
% *prate
? 1 : bestdiv
;
207 bestdiv
= min_t(u32
, bestdiv
, divider
->max_div
);
208 *prate
= rate
* bestdiv
;
214 * zynqmp_clk_divider_set_rate() - Set rate of divider clock
215 * @hw: handle between common and hardware-specific interfaces
216 * @rate: rate of clock to be set
217 * @parent_rate: rate of parent clock
219 * Return: 0 on success else error+reason
221 static int zynqmp_clk_divider_set_rate(struct clk_hw
*hw
, unsigned long rate
,
222 unsigned long parent_rate
)
224 struct zynqmp_clk_divider
*divider
= to_zynqmp_clk_divider(hw
);
225 const char *clk_name
= clk_hw_get_name(hw
);
226 u32 clk_id
= divider
->clk_id
;
227 u32 div_type
= divider
->div_type
;
231 value
= zynqmp_divider_get_val(parent_rate
, rate
, divider
->flags
);
232 if (div_type
== TYPE_DIV1
) {
233 div
= value
& 0xFFFF;
240 if (divider
->flags
& CLK_DIVIDER_POWER_OF_TWO
)
243 ret
= zynqmp_pm_clock_setdivider(clk_id
, div
);
246 pr_warn_once("%s() set divider failed for %s, ret = %d\n",
247 __func__
, clk_name
, ret
);
252 static const struct clk_ops zynqmp_clk_divider_ops
= {
253 .recalc_rate
= zynqmp_clk_divider_recalc_rate
,
254 .round_rate
= zynqmp_clk_divider_round_rate
,
255 .set_rate
= zynqmp_clk_divider_set_rate
,
259 * zynqmp_clk_get_max_divisor() - Get maximum supported divisor from firmware.
260 * @clk_id: Id of clock
261 * @type: Divider type
263 * Return: Maximum divisor of a clock if query data is successful
264 * U16_MAX in case of query data is not success
266 static u32
zynqmp_clk_get_max_divisor(u32 clk_id
, u32 type
)
268 struct zynqmp_pm_query_data qdata
= {0};
269 u32 ret_payload
[PAYLOAD_ARG_CNT
];
272 qdata
.qid
= PM_QID_CLOCK_GET_MAX_DIVISOR
;
275 ret
= zynqmp_pm_query_data(qdata
, ret_payload
);
277 * To maintain backward compatibility return maximum possible value
278 * (0xFFFF) if query for max divisor is not successful.
283 return ret_payload
[1];
287 * zynqmp_clk_register_divider() - Register a divider clock
288 * @name: Name of this clock
289 * @clk_id: Id of clock
290 * @parents: Name of this clock's parents
291 * @num_parents: Number of parents
292 * @nodes: Clock topology node
294 * Return: clock hardware to registered clock divider
296 struct clk_hw
*zynqmp_clk_register_divider(const char *name
,
298 const char * const *parents
,
300 const struct clock_topology
*nodes
)
302 struct zynqmp_clk_divider
*div
;
304 struct clk_init_data init
;
307 /* allocate the divider */
308 div
= kzalloc(sizeof(*div
), GFP_KERNEL
);
310 return ERR_PTR(-ENOMEM
);
313 init
.ops
= &zynqmp_clk_divider_ops
;
314 /* CLK_FRAC is not defined in the common clk framework */
315 init
.flags
= nodes
->flag
& ~CLK_FRAC
;
316 init
.parent_names
= parents
;
317 init
.num_parents
= 1;
319 /* struct clk_divider assignments */
320 div
->is_frac
= !!((nodes
->flag
& CLK_FRAC
) |
321 (nodes
->custom_type_flag
& CUSTOM_FLAG_CLK_FRAC
));
322 div
->flags
= nodes
->type_flag
;
323 div
->hw
.init
= &init
;
324 div
->clk_id
= clk_id
;
325 div
->div_type
= nodes
->type
;
328 * To achieve best possible rate, maximum limit of divider is required
331 div
->max_div
= zynqmp_clk_get_max_divisor(clk_id
, nodes
->type
);
334 ret
= clk_hw_register(NULL
, hw
);