1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (C) 2023 Nuvoton Technology Corp.
4 * Author: Chi-Fang Li <cfli0@nuvoton.com>
7 #include <linux/bitfield.h>
8 #include <linux/clk-provider.h>
9 #include <linux/container_of.h>
10 #include <linux/device.h>
12 #include <linux/kernel.h>
13 #include <linux/math64.h>
14 #include <linux/slab.h>
15 #include <linux/units.h>
16 #include <dt-bindings/clock/nuvoton,ma35d1-clk.h>
18 #include "clk-ma35d1.h"
20 /* PLL frequency limits */
21 #define PLL_FREF_MAX_FREQ (200 * HZ_PER_MHZ)
22 #define PLL_FREF_MIN_FREQ (1 * HZ_PER_MHZ)
23 #define PLL_FREF_M_MAX_FREQ (40 * HZ_PER_MHZ)
24 #define PLL_FREF_M_MIN_FREQ (10 * HZ_PER_MHZ)
25 #define PLL_FCLK_MAX_FREQ (2400 * HZ_PER_MHZ)
26 #define PLL_FCLK_MIN_FREQ (600 * HZ_PER_MHZ)
27 #define PLL_FCLKO_MAX_FREQ (2400 * HZ_PER_MHZ)
28 #define PLL_FCLKO_MIN_FREQ (85700 * HZ_PER_KHZ)
29 #define PLL_SS_RATE 0x77
30 #define PLL_SLOPE 0x58CFA
32 #define REG_PLL_CTL0_OFFSET 0x0
33 #define REG_PLL_CTL1_OFFSET 0x4
34 #define REG_PLL_CTL2_OFFSET 0x8
36 /* bit fields for REG_CLK_PLL0CTL0, which is SMIC PLL design */
37 #define SPLL0_CTL0_FBDIV GENMASK(7, 0)
38 #define SPLL0_CTL0_INDIV GENMASK(11, 8)
39 #define SPLL0_CTL0_OUTDIV GENMASK(13, 12)
40 #define SPLL0_CTL0_PD BIT(16)
41 #define SPLL0_CTL0_BP BIT(17)
43 /* bit fields for REG_CLK_PLLxCTL0 ~ REG_CLK_PLLxCTL2, where x = 2 ~ 5 */
44 #define PLL_CTL0_FBDIV GENMASK(10, 0)
45 #define PLL_CTL0_INDIV GENMASK(17, 12)
46 #define PLL_CTL0_MODE GENMASK(19, 18)
47 #define PLL_CTL0_SSRATE GENMASK(30, 20)
48 #define PLL_CTL1_PD BIT(0)
49 #define PLL_CTL1_BP BIT(1)
50 #define PLL_CTL1_OUTDIV GENMASK(6, 4)
51 #define PLL_CTL1_FRAC GENMASK(31, 24)
52 #define PLL_CTL2_SLOPE GENMASK(23, 0)
57 #define FBDIV_MAX 2047
58 #define FBDIV_FRAC_MIN 1600
59 #define FBDIV_FRAC_MAX 204700
63 #define PLL_MODE_INT 0
64 #define PLL_MODE_FRAC 1
67 struct ma35d1_clk_pll
{
71 void __iomem
*ctl0_base
;
72 void __iomem
*ctl1_base
;
73 void __iomem
*ctl2_base
;
76 static inline struct ma35d1_clk_pll
*to_ma35d1_clk_pll(struct clk_hw
*_hw
)
78 return container_of(_hw
, struct ma35d1_clk_pll
, hw
);
81 static unsigned long ma35d1_calc_smic_pll_freq(u32 pll0_ctl0
,
82 unsigned long parent_rate
)
87 if (pll0_ctl0
& SPLL0_CTL0_BP
)
90 n
= FIELD_GET(SPLL0_CTL0_FBDIV
, pll0_ctl0
);
91 m
= FIELD_GET(SPLL0_CTL0_INDIV
, pll0_ctl0
);
92 p
= FIELD_GET(SPLL0_CTL0_OUTDIV
, pll0_ctl0
);
94 pll_freq
= (u64
)parent_rate
* n
;
95 div_u64(pll_freq
, m
* outdiv
);
99 static unsigned long ma35d1_calc_pll_freq(u8 mode
, u32
*reg_ctl
, unsigned long parent_rate
)
101 unsigned long pll_freq
, x
;
104 if (reg_ctl
[1] & PLL_CTL1_BP
)
107 n
= FIELD_GET(PLL_CTL0_FBDIV
, reg_ctl
[0]);
108 m
= FIELD_GET(PLL_CTL0_INDIV
, reg_ctl
[0]);
109 p
= FIELD_GET(PLL_CTL1_OUTDIV
, reg_ctl
[1]);
111 if (mode
== PLL_MODE_INT
) {
112 pll_freq
= (u64
)parent_rate
* n
;
113 div_u64(pll_freq
, m
* p
);
115 x
= FIELD_GET(PLL_CTL1_FRAC
, reg_ctl
[1]);
116 /* 2 decimal places floating to integer (ex. 1.23 to 123) */
117 n
= n
* 100 + ((x
* 100) / FIELD_MAX(PLL_CTL1_FRAC
));
118 pll_freq
= div_u64(parent_rate
* n
, 100 * m
* p
);
123 static int ma35d1_pll_find_closest(struct ma35d1_clk_pll
*pll
, unsigned long rate
,
124 unsigned long parent_rate
, u32
*reg_ctl
,
127 unsigned long min_diff
= ULONG_MAX
;
128 int fbdiv_min
, fbdiv_max
;
132 if (rate
< PLL_FCLKO_MIN_FREQ
|| rate
> PLL_FCLKO_MAX_FREQ
)
135 if (pll
->mode
== PLL_MODE_INT
) {
136 fbdiv_min
= FBDIV_MIN
;
137 fbdiv_max
= FBDIV_MAX
;
139 fbdiv_min
= FBDIV_FRAC_MIN
;
140 fbdiv_max
= FBDIV_FRAC_MAX
;
143 for (m
= INDIV_MIN
; m
<= INDIV_MAX
; m
++) {
144 for (n
= fbdiv_min
; n
<= fbdiv_max
; n
++) {
145 for (p
= OUTDIV_MIN
; p
<= OUTDIV_MAX
; p
++) {
146 unsigned long tmp
, fout
, fclk
, diff
;
148 tmp
= div_u64(parent_rate
, m
);
149 if (tmp
< PLL_FREF_M_MIN_FREQ
||
150 tmp
> PLL_FREF_M_MAX_FREQ
)
151 continue; /* constrain */
153 fclk
= div_u64(parent_rate
* n
, m
);
154 /* for 2 decimal places */
155 if (pll
->mode
!= PLL_MODE_INT
)
156 fclk
= div_u64(fclk
, 100);
158 if (fclk
< PLL_FCLK_MIN_FREQ
||
159 fclk
> PLL_FCLK_MAX_FREQ
)
160 continue; /* constrain */
162 fout
= div_u64(fclk
, p
);
163 if (fout
< PLL_FCLKO_MIN_FREQ
||
164 fout
> PLL_FCLKO_MAX_FREQ
)
165 continue; /* constrain */
167 diff
= abs(rate
- fout
);
168 if (diff
< min_diff
) {
169 reg_ctl
[0] = FIELD_PREP(PLL_CTL0_INDIV
, m
) |
170 FIELD_PREP(PLL_CTL0_FBDIV
, n
);
171 reg_ctl
[1] = FIELD_PREP(PLL_CTL1_OUTDIV
, p
);
181 return -EINVAL
; /* cannot find even one valid setting */
185 static int ma35d1_clk_pll_set_rate(struct clk_hw
*hw
, unsigned long rate
,
186 unsigned long parent_rate
)
188 struct ma35d1_clk_pll
*pll
= to_ma35d1_clk_pll(hw
);
189 u32 reg_ctl
[3] = { 0 };
190 unsigned long pll_freq
;
193 if (parent_rate
< PLL_FREF_MIN_FREQ
|| parent_rate
> PLL_FREF_MAX_FREQ
)
196 ret
= ma35d1_pll_find_closest(pll
, rate
, parent_rate
, reg_ctl
, &pll_freq
);
202 reg_ctl
[0] |= FIELD_PREP(PLL_CTL0_MODE
, PLL_MODE_INT
);
205 reg_ctl
[0] |= FIELD_PREP(PLL_CTL0_MODE
, PLL_MODE_FRAC
);
208 reg_ctl
[0] |= FIELD_PREP(PLL_CTL0_MODE
, PLL_MODE_SS
) |
209 FIELD_PREP(PLL_CTL0_SSRATE
, PLL_SS_RATE
);
210 reg_ctl
[2] = FIELD_PREP(PLL_CTL2_SLOPE
, PLL_SLOPE
);
213 reg_ctl
[1] |= PLL_CTL1_PD
;
215 writel_relaxed(reg_ctl
[0], pll
->ctl0_base
);
216 writel_relaxed(reg_ctl
[1], pll
->ctl1_base
);
217 writel_relaxed(reg_ctl
[2], pll
->ctl2_base
);
221 static unsigned long ma35d1_clk_pll_recalc_rate(struct clk_hw
*hw
, unsigned long parent_rate
)
223 struct ma35d1_clk_pll
*pll
= to_ma35d1_clk_pll(hw
);
225 unsigned long pll_freq
;
227 if (parent_rate
< PLL_FREF_MIN_FREQ
|| parent_rate
> PLL_FREF_MAX_FREQ
)
232 reg_ctl
[0] = readl_relaxed(pll
->ctl0_base
);
233 pll_freq
= ma35d1_calc_smic_pll_freq(reg_ctl
[0], parent_rate
);
239 reg_ctl
[0] = readl_relaxed(pll
->ctl0_base
);
240 reg_ctl
[1] = readl_relaxed(pll
->ctl1_base
);
241 pll_freq
= ma35d1_calc_pll_freq(pll
->mode
, reg_ctl
, parent_rate
);
247 static long ma35d1_clk_pll_round_rate(struct clk_hw
*hw
, unsigned long rate
,
248 unsigned long *parent_rate
)
250 struct ma35d1_clk_pll
*pll
= to_ma35d1_clk_pll(hw
);
251 u32 reg_ctl
[3] = { 0 };
252 unsigned long pll_freq
;
255 if (*parent_rate
< PLL_FREF_MIN_FREQ
|| *parent_rate
> PLL_FREF_MAX_FREQ
)
258 ret
= ma35d1_pll_find_closest(pll
, rate
, *parent_rate
, reg_ctl
, &pll_freq
);
264 reg_ctl
[0] = readl_relaxed(pll
->ctl0_base
);
265 pll_freq
= ma35d1_calc_smic_pll_freq(reg_ctl
[0], *parent_rate
);
271 reg_ctl
[0] = readl_relaxed(pll
->ctl0_base
);
272 reg_ctl
[1] = readl_relaxed(pll
->ctl1_base
);
273 pll_freq
= ma35d1_calc_pll_freq(pll
->mode
, reg_ctl
, *parent_rate
);
279 static int ma35d1_clk_pll_is_prepared(struct clk_hw
*hw
)
281 struct ma35d1_clk_pll
*pll
= to_ma35d1_clk_pll(hw
);
282 u32 val
= readl_relaxed(pll
->ctl1_base
);
284 return !(val
& PLL_CTL1_PD
);
287 static int ma35d1_clk_pll_prepare(struct clk_hw
*hw
)
289 struct ma35d1_clk_pll
*pll
= to_ma35d1_clk_pll(hw
);
292 val
= readl_relaxed(pll
->ctl1_base
);
294 writel_relaxed(val
, pll
->ctl1_base
);
298 static void ma35d1_clk_pll_unprepare(struct clk_hw
*hw
)
300 struct ma35d1_clk_pll
*pll
= to_ma35d1_clk_pll(hw
);
303 val
= readl_relaxed(pll
->ctl1_base
);
305 writel_relaxed(val
, pll
->ctl1_base
);
308 static const struct clk_ops ma35d1_clk_pll_ops
= {
309 .is_prepared
= ma35d1_clk_pll_is_prepared
,
310 .prepare
= ma35d1_clk_pll_prepare
,
311 .unprepare
= ma35d1_clk_pll_unprepare
,
312 .set_rate
= ma35d1_clk_pll_set_rate
,
313 .recalc_rate
= ma35d1_clk_pll_recalc_rate
,
314 .round_rate
= ma35d1_clk_pll_round_rate
,
317 static const struct clk_ops ma35d1_clk_fixed_pll_ops
= {
318 .recalc_rate
= ma35d1_clk_pll_recalc_rate
,
319 .round_rate
= ma35d1_clk_pll_round_rate
,
322 struct clk_hw
*ma35d1_reg_clk_pll(struct device
*dev
, u32 id
, u8 u8mode
, const char *name
,
323 struct clk_hw
*parent_hw
, void __iomem
*base
)
325 struct clk_parent_data pdata
= { .index
= 0 };
326 struct clk_init_data init
= {};
327 struct ma35d1_clk_pll
*pll
;
331 pll
= devm_kzalloc(dev
, sizeof(*pll
), GFP_KERNEL
);
333 return ERR_PTR(-ENOMEM
);
337 pll
->ctl0_base
= base
+ REG_PLL_CTL0_OFFSET
;
338 pll
->ctl1_base
= base
+ REG_PLL_CTL1_OFFSET
;
339 pll
->ctl2_base
= base
+ REG_PLL_CTL2_OFFSET
;
343 pdata
.hw
= parent_hw
;
344 init
.parent_data
= &pdata
;
345 init
.num_parents
= 1;
347 if (id
== CAPLL
|| id
== DDRPLL
)
348 init
.ops
= &ma35d1_clk_fixed_pll_ops
;
350 init
.ops
= &ma35d1_clk_pll_ops
;
352 pll
->hw
.init
= &init
;
355 ret
= devm_clk_hw_register(dev
, hw
);
360 EXPORT_SYMBOL_GPL(ma35d1_reg_clk_pll
);