1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (C) 2023 Inochi Amaoto <inochiama@outlook.com>
6 #include <linux/clk-provider.h>
8 #include <linux/limits.h>
9 #include <linux/spinlock.h>
11 #include "clk-cv18xx-pll.h"
13 static inline struct cv1800_clk_pll
*hw_to_cv1800_clk_pll(struct clk_hw
*hw
)
15 struct cv1800_clk_common
*common
= hw_to_cv1800_clk_common(hw
);
17 return container_of(common
, struct cv1800_clk_pll
, common
);
20 static unsigned long ipll_calc_rate(unsigned long parent_rate
,
21 unsigned long pre_div_sel
,
22 unsigned long div_sel
,
23 unsigned long post_div_sel
)
25 uint64_t rate
= parent_rate
;
28 do_div(rate
, pre_div_sel
* post_div_sel
);
33 static unsigned long ipll_recalc_rate(struct clk_hw
*hw
,
34 unsigned long parent_rate
)
36 struct cv1800_clk_pll
*pll
= hw_to_cv1800_clk_pll(hw
);
39 value
= readl(pll
->common
.base
+ pll
->pll_reg
);
41 return ipll_calc_rate(parent_rate
,
42 PLL_GET_PRE_DIV_SEL(value
),
43 PLL_GET_DIV_SEL(value
),
44 PLL_GET_POST_DIV_SEL(value
));
47 static int ipll_find_rate(const struct cv1800_clk_pll_limit
*limit
,
48 unsigned long prate
, unsigned long *rate
,
51 unsigned long best_rate
= 0;
52 unsigned long trate
= *rate
;
53 unsigned long pre_div_sel
= 0, div_sel
= 0, post_div_sel
= 0;
54 unsigned long pre
, div
, post
;
55 u32 detected
= *value
;
58 for_each_pll_limit_range(pre
, &limit
->pre_div
) {
59 for_each_pll_limit_range(div
, &limit
->div
) {
60 for_each_pll_limit_range(post
, &limit
->post_div
) {
61 tmp
= ipll_calc_rate(prate
, pre
, div
, post
);
66 if ((trate
- tmp
) < (trate
- best_rate
)) {
77 detected
= PLL_SET_PRE_DIV_SEL(detected
, pre_div_sel
);
78 detected
= PLL_SET_POST_DIV_SEL(detected
, post_div_sel
);
79 detected
= PLL_SET_DIV_SEL(detected
, div_sel
);
88 static int ipll_determine_rate(struct clk_hw
*hw
, struct clk_rate_request
*req
)
91 struct cv1800_clk_pll
*pll
= hw_to_cv1800_clk_pll(hw
);
93 return ipll_find_rate(pll
->pll_limit
, req
->best_parent_rate
,
97 static void pll_get_mode_ctrl(unsigned long div_sel
,
98 bool (*mode_ctrl_check
)(unsigned long,
101 const struct cv1800_clk_pll_limit
*limit
,
104 unsigned long ictrl
= 0, mode
= 0;
105 u32 detected
= *value
;
107 for_each_pll_limit_range(mode
, &limit
->mode
) {
108 for_each_pll_limit_range(ictrl
, &limit
->ictrl
) {
109 if (mode_ctrl_check(div_sel
, ictrl
, mode
)) {
110 detected
= PLL_SET_SEL_MODE(detected
, mode
);
111 detected
= PLL_SET_ICTRL(detected
, ictrl
);
119 static bool ipll_check_mode_ctrl_restrict(unsigned long div_sel
,
123 unsigned long left_rest
= 20 * div_sel
;
124 unsigned long right_rest
= 35 * div_sel
;
125 unsigned long test
= 184 * (1 + mode
) * (1 + ictrl
) / 2;
127 return test
> left_rest
&& test
<= right_rest
;
130 static int ipll_set_rate(struct clk_hw
*hw
, unsigned long rate
,
131 unsigned long parent_rate
)
133 u32 regval
, detected
= 0;
135 struct cv1800_clk_pll
*pll
= hw_to_cv1800_clk_pll(hw
);
137 ipll_find_rate(pll
->pll_limit
, parent_rate
, &rate
, &detected
);
138 pll_get_mode_ctrl(PLL_GET_DIV_SEL(detected
),
139 ipll_check_mode_ctrl_restrict
,
140 pll
->pll_limit
, &detected
);
142 spin_lock_irqsave(pll
->common
.lock
, flags
);
144 regval
= readl(pll
->common
.base
+ pll
->pll_reg
);
145 regval
= PLL_COPY_REG(regval
, detected
);
147 writel(regval
, pll
->common
.base
+ pll
->pll_reg
);
149 spin_unlock_irqrestore(pll
->common
.lock
, flags
);
151 cv1800_clk_wait_for_lock(&pll
->common
, pll
->pll_status
.reg
,
152 BIT(pll
->pll_status
.shift
));
157 static int pll_enable(struct clk_hw
*hw
)
159 struct cv1800_clk_pll
*pll
= hw_to_cv1800_clk_pll(hw
);
161 return cv1800_clk_clearbit(&pll
->common
, &pll
->pll_pwd
);
164 static void pll_disable(struct clk_hw
*hw
)
166 struct cv1800_clk_pll
*pll
= hw_to_cv1800_clk_pll(hw
);
168 cv1800_clk_setbit(&pll
->common
, &pll
->pll_pwd
);
171 static int pll_is_enable(struct clk_hw
*hw
)
173 struct cv1800_clk_pll
*pll
= hw_to_cv1800_clk_pll(hw
);
175 return cv1800_clk_checkbit(&pll
->common
, &pll
->pll_pwd
) == 0;
178 const struct clk_ops cv1800_clk_ipll_ops
= {
179 .disable
= pll_disable
,
180 .enable
= pll_enable
,
181 .is_enabled
= pll_is_enable
,
183 .recalc_rate
= ipll_recalc_rate
,
184 .determine_rate
= ipll_determine_rate
,
185 .set_rate
= ipll_set_rate
,
188 #define PLL_SYN_FACTOR_DOT_POS 26
189 #define PLL_SYN_FACTOR_MINIMUM ((4 << PLL_SYN_FACTOR_DOT_POS) + 1)
191 static bool fpll_is_factional_mode(struct cv1800_clk_pll
*pll
)
193 return cv1800_clk_checkbit(&pll
->common
, &pll
->pll_syn
->en
);
196 static unsigned long fpll_calc_rate(unsigned long parent_rate
,
197 unsigned long pre_div_sel
,
198 unsigned long div_sel
,
199 unsigned long post_div_sel
,
200 unsigned long ssc_syn_set
,
203 u64 dividend
= parent_rate
* div_sel
;
204 u64 factor
= ssc_syn_set
* pre_div_sel
* post_div_sel
;
207 dividend
<<= PLL_SYN_FACTOR_DOT_POS
- 1;
208 rate
= div64_u64_rem(dividend
, factor
, ÷nd
);
210 if (is_full_parent
) {
215 rate
+= DIV64_U64_ROUND_CLOSEST(dividend
, factor
);
220 static unsigned long fpll_recalc_rate(struct clk_hw
*hw
,
221 unsigned long parent_rate
)
223 struct cv1800_clk_pll
*pll
= hw_to_cv1800_clk_pll(hw
);
228 if (!fpll_is_factional_mode(pll
))
229 return ipll_recalc_rate(hw
, parent_rate
);
231 syn_set
= readl(pll
->common
.base
+ pll
->pll_syn
->set
);
236 clk_full
= cv1800_clk_checkbit(&pll
->common
,
237 &pll
->pll_syn
->clk_half
);
239 value
= readl(pll
->common
.base
+ pll
->pll_reg
);
241 return fpll_calc_rate(parent_rate
,
242 PLL_GET_PRE_DIV_SEL(value
),
243 PLL_GET_DIV_SEL(value
),
244 PLL_GET_POST_DIV_SEL(value
),
248 static unsigned long fpll_find_synthesizer(unsigned long parent
,
250 unsigned long pre_div
,
252 unsigned long post_div
,
256 u32 test_max
= U32_MAX
, test_min
= PLL_SYN_FACTOR_MINIMUM
;
259 while (test_min
< test_max
) {
260 u32 tssc
= (test_max
+ test_min
) / 2;
262 trate
= fpll_calc_rate(parent
, pre_div
, div
, post_div
,
263 tssc
, is_full_parent
);
277 *ssc_syn_set
= test_min
;
282 static int fpll_find_rate(struct cv1800_clk_pll
*pll
,
283 const struct cv1800_clk_pll_limit
*limit
,
286 u32
*value
, u32
*ssc_syn_set
)
288 unsigned long best_rate
= 0;
289 unsigned long pre_div_sel
= 0, div_sel
= 0, post_div_sel
= 0;
290 unsigned long pre
, div
, post
;
291 unsigned long trate
= *rate
;
292 u32 detected
= *value
;
294 bool clk_full
= cv1800_clk_checkbit(&pll
->common
,
295 &pll
->pll_syn
->clk_half
);
297 for_each_pll_limit_range(pre
, &limit
->pre_div
) {
298 for_each_pll_limit_range(post
, &limit
->post_div
) {
299 for_each_pll_limit_range(div
, &limit
->div
) {
300 tmp
= fpll_find_synthesizer(prate
, trate
,
305 if ((trate
- tmp
) < (trate
- best_rate
)) {
316 detected
= PLL_SET_PRE_DIV_SEL(detected
, pre_div_sel
);
317 detected
= PLL_SET_POST_DIV_SEL(detected
, post_div_sel
);
318 detected
= PLL_SET_DIV_SEL(detected
, div_sel
);
327 static int fpll_determine_rate(struct clk_hw
*hw
, struct clk_rate_request
*req
)
329 struct cv1800_clk_pll
*pll
= hw_to_cv1800_clk_pll(hw
);
330 u32 val
, ssc_syn_set
;
332 if (!fpll_is_factional_mode(pll
))
333 return ipll_determine_rate(hw
, req
);
335 fpll_find_rate(pll
, &pll
->pll_limit
[2], req
->best_parent_rate
,
336 &req
->rate
, &val
, &ssc_syn_set
);
341 static bool fpll_check_mode_ctrl_restrict(unsigned long div_sel
,
345 unsigned long left_rest
= 10 * div_sel
;
346 unsigned long right_rest
= 24 * div_sel
;
347 unsigned long test
= 184 * (1 + mode
) * (1 + ictrl
) / 2;
349 return test
> left_rest
&& test
<= right_rest
;
352 static int fpll_set_rate(struct clk_hw
*hw
, unsigned long rate
,
353 unsigned long parent_rate
)
356 u32 detected
= 0, detected_ssc
= 0;
358 struct cv1800_clk_pll
*pll
= hw_to_cv1800_clk_pll(hw
);
360 if (!fpll_is_factional_mode(pll
))
361 return ipll_set_rate(hw
, rate
, parent_rate
);
363 fpll_find_rate(pll
, &pll
->pll_limit
[2], parent_rate
,
364 &rate
, &detected
, &detected_ssc
);
365 pll_get_mode_ctrl(PLL_GET_DIV_SEL(detected
),
366 fpll_check_mode_ctrl_restrict
,
367 pll
->pll_limit
, &detected
);
369 spin_lock_irqsave(pll
->common
.lock
, flags
);
371 writel(detected_ssc
, pll
->common
.base
+ pll
->pll_syn
->set
);
373 regval
= readl(pll
->common
.base
+ pll
->pll_reg
);
374 regval
= PLL_COPY_REG(regval
, detected
);
376 writel(regval
, pll
->common
.base
+ pll
->pll_reg
);
378 spin_unlock_irqrestore(pll
->common
.lock
, flags
);
380 cv1800_clk_wait_for_lock(&pll
->common
, pll
->pll_status
.reg
,
381 BIT(pll
->pll_status
.shift
));
386 static u8
fpll_get_parent(struct clk_hw
*hw
)
388 struct cv1800_clk_pll
*pll
= hw_to_cv1800_clk_pll(hw
);
390 if (fpll_is_factional_mode(pll
))
396 static int fpll_set_parent(struct clk_hw
*hw
, u8 index
)
398 struct cv1800_clk_pll
*pll
= hw_to_cv1800_clk_pll(hw
);
401 cv1800_clk_setbit(&pll
->common
, &pll
->pll_syn
->en
);
403 cv1800_clk_clearbit(&pll
->common
, &pll
->pll_syn
->en
);
408 const struct clk_ops cv1800_clk_fpll_ops
= {
409 .disable
= pll_disable
,
410 .enable
= pll_enable
,
411 .is_enabled
= pll_is_enable
,
413 .recalc_rate
= fpll_recalc_rate
,
414 .determine_rate
= fpll_determine_rate
,
415 .set_rate
= fpll_set_rate
,
417 .set_parent
= fpll_set_parent
,
418 .get_parent
= fpll_get_parent
,