1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * Copyright (C) 2023 Nuvoton Technology Corp. |
4 | * Author: Chi-Fang Li <cfli0@nuvoton.com> |
5 | */ |
6 | |
7 | #include <linux/bitfield.h> |
8 | #include <linux/clk-provider.h> |
9 | #include <linux/container_of.h> |
10 | #include <linux/device.h> |
11 | #include <linux/io.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> |
17 | |
18 | #include "clk-ma35d1.h" |
19 | |
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 |
31 | |
32 | #define REG_PLL_CTL0_OFFSET 0x0 |
33 | #define REG_PLL_CTL1_OFFSET 0x4 |
34 | #define REG_PLL_CTL2_OFFSET 0x8 |
35 | |
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) |
42 | |
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) |
53 | |
54 | #define INDIV_MIN 1 |
55 | #define INDIV_MAX 63 |
56 | #define FBDIV_MIN 16 |
57 | #define FBDIV_MAX 2047 |
58 | #define FBDIV_FRAC_MIN 1600 |
59 | #define FBDIV_FRAC_MAX 204700 |
60 | #define OUTDIV_MIN 1 |
61 | #define OUTDIV_MAX 7 |
62 | |
63 | #define PLL_MODE_INT 0 |
64 | #define PLL_MODE_FRAC 1 |
65 | #define PLL_MODE_SS 2 |
66 | |
67 | struct ma35d1_clk_pll { |
68 | struct clk_hw hw; |
69 | u32 id; |
70 | u8 mode; |
71 | void __iomem *ctl0_base; |
72 | void __iomem *ctl1_base; |
73 | void __iomem *ctl2_base; |
74 | }; |
75 | |
76 | static inline struct ma35d1_clk_pll *to_ma35d1_clk_pll(struct clk_hw *_hw) |
77 | { |
78 | return container_of(_hw, struct ma35d1_clk_pll, hw); |
79 | } |
80 | |
81 | static unsigned long ma35d1_calc_smic_pll_freq(u32 pll0_ctl0, |
82 | unsigned long parent_rate) |
83 | { |
84 | u32 m, n, p, outdiv; |
85 | u64 pll_freq; |
86 | |
87 | if (pll0_ctl0 & SPLL0_CTL0_BP) |
88 | return parent_rate; |
89 | |
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); |
93 | outdiv = 1 << p; |
94 | pll_freq = (u64)parent_rate * n; |
95 | div_u64(dividend: pll_freq, divisor: m * outdiv); |
96 | return pll_freq; |
97 | } |
98 | |
99 | static unsigned long ma35d1_calc_pll_freq(u8 mode, u32 *reg_ctl, unsigned long parent_rate) |
100 | { |
101 | unsigned long pll_freq, x; |
102 | u32 m, n, p; |
103 | |
104 | if (reg_ctl[1] & PLL_CTL1_BP) |
105 | return parent_rate; |
106 | |
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]); |
110 | |
111 | if (mode == PLL_MODE_INT) { |
112 | pll_freq = (u64)parent_rate * n; |
113 | div_u64(dividend: pll_freq, divisor: m * p); |
114 | } else { |
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(dividend: parent_rate * n, divisor: 100 * m * p); |
119 | } |
120 | return pll_freq; |
121 | } |
122 | |
123 | static int ma35d1_pll_find_closest(struct ma35d1_clk_pll *pll, unsigned long rate, |
124 | unsigned long parent_rate, u32 *reg_ctl, |
125 | unsigned long *freq) |
126 | { |
127 | unsigned long min_diff = ULONG_MAX; |
128 | int fbdiv_min, fbdiv_max; |
129 | int p, m, n; |
130 | |
131 | *freq = 0; |
132 | if (rate < PLL_FCLKO_MIN_FREQ || rate > PLL_FCLKO_MAX_FREQ) |
133 | return -EINVAL; |
134 | |
135 | if (pll->mode == PLL_MODE_INT) { |
136 | fbdiv_min = FBDIV_MIN; |
137 | fbdiv_max = FBDIV_MAX; |
138 | } else { |
139 | fbdiv_min = FBDIV_FRAC_MIN; |
140 | fbdiv_max = FBDIV_FRAC_MAX; |
141 | } |
142 | |
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; |
147 | |
148 | tmp = div_u64(dividend: parent_rate, divisor: m); |
149 | if (tmp < PLL_FREF_M_MIN_FREQ || |
150 | tmp > PLL_FREF_M_MAX_FREQ) |
151 | continue; /* constrain */ |
152 | |
153 | fclk = div_u64(dividend: parent_rate * n, divisor: m); |
154 | /* for 2 decimal places */ |
155 | if (pll->mode != PLL_MODE_INT) |
156 | fclk = div_u64(dividend: fclk, divisor: 100); |
157 | |
158 | if (fclk < PLL_FCLK_MIN_FREQ || |
159 | fclk > PLL_FCLK_MAX_FREQ) |
160 | continue; /* constrain */ |
161 | |
162 | fout = div_u64(dividend: fclk, divisor: p); |
163 | if (fout < PLL_FCLKO_MIN_FREQ || |
164 | fout > PLL_FCLKO_MAX_FREQ) |
165 | continue; /* constrain */ |
166 | |
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); |
172 | *freq = fout; |
173 | min_diff = diff; |
174 | if (min_diff == 0) |
175 | break; |
176 | } |
177 | } |
178 | } |
179 | } |
180 | if (*freq == 0) |
181 | return -EINVAL; /* cannot find even one valid setting */ |
182 | return 0; |
183 | } |
184 | |
185 | static int ma35d1_clk_pll_set_rate(struct clk_hw *hw, unsigned long rate, |
186 | unsigned long parent_rate) |
187 | { |
188 | struct ma35d1_clk_pll *pll = to_ma35d1_clk_pll(hw: hw); |
189 | u32 reg_ctl[3] = { 0 }; |
190 | unsigned long pll_freq; |
191 | int ret; |
192 | |
193 | if (parent_rate < PLL_FREF_MIN_FREQ || parent_rate > PLL_FREF_MAX_FREQ) |
194 | return -EINVAL; |
195 | |
196 | ret = ma35d1_pll_find_closest(pll, rate, parent_rate, reg_ctl, freq: &pll_freq); |
197 | if (ret != 0) |
198 | return ret; |
199 | |
200 | switch (pll->mode) { |
201 | case PLL_MODE_INT: |
202 | reg_ctl[0] |= FIELD_PREP(PLL_CTL0_MODE, PLL_MODE_INT); |
203 | break; |
204 | case PLL_MODE_FRAC: |
205 | reg_ctl[0] |= FIELD_PREP(PLL_CTL0_MODE, PLL_MODE_FRAC); |
206 | break; |
207 | case PLL_MODE_SS: |
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); |
211 | break; |
212 | } |
213 | reg_ctl[1] |= PLL_CTL1_PD; |
214 | |
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); |
218 | return 0; |
219 | } |
220 | |
221 | static unsigned long ma35d1_clk_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) |
222 | { |
223 | struct ma35d1_clk_pll *pll = to_ma35d1_clk_pll(hw: hw); |
224 | u32 reg_ctl[3]; |
225 | unsigned long pll_freq; |
226 | |
227 | if (parent_rate < PLL_FREF_MIN_FREQ || parent_rate > PLL_FREF_MAX_FREQ) |
228 | return 0; |
229 | |
230 | switch (pll->id) { |
231 | case CAPLL: |
232 | reg_ctl[0] = readl_relaxed(pll->ctl0_base); |
233 | pll_freq = ma35d1_calc_smic_pll_freq(pll0_ctl0: reg_ctl[0], parent_rate); |
234 | return pll_freq; |
235 | case DDRPLL: |
236 | case APLL: |
237 | case EPLL: |
238 | case VPLL: |
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(mode: pll->mode, reg_ctl, parent_rate); |
242 | return pll_freq; |
243 | } |
244 | return 0; |
245 | } |
246 | |
247 | static long ma35d1_clk_pll_round_rate(struct clk_hw *hw, unsigned long rate, |
248 | unsigned long *parent_rate) |
249 | { |
250 | struct ma35d1_clk_pll *pll = to_ma35d1_clk_pll(hw: hw); |
251 | u32 reg_ctl[3] = { 0 }; |
252 | unsigned long pll_freq; |
253 | long ret; |
254 | |
255 | if (*parent_rate < PLL_FREF_MIN_FREQ || *parent_rate > PLL_FREF_MAX_FREQ) |
256 | return -EINVAL; |
257 | |
258 | ret = ma35d1_pll_find_closest(pll, rate, parent_rate: *parent_rate, reg_ctl, freq: &pll_freq); |
259 | if (ret < 0) |
260 | return ret; |
261 | |
262 | switch (pll->id) { |
263 | case CAPLL: |
264 | reg_ctl[0] = readl_relaxed(pll->ctl0_base); |
265 | pll_freq = ma35d1_calc_smic_pll_freq(pll0_ctl0: reg_ctl[0], parent_rate: *parent_rate); |
266 | return pll_freq; |
267 | case DDRPLL: |
268 | case APLL: |
269 | case EPLL: |
270 | case VPLL: |
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(mode: pll->mode, reg_ctl, parent_rate: *parent_rate); |
274 | return pll_freq; |
275 | } |
276 | return 0; |
277 | } |
278 | |
279 | static int ma35d1_clk_pll_is_prepared(struct clk_hw *hw) |
280 | { |
281 | struct ma35d1_clk_pll *pll = to_ma35d1_clk_pll(hw: hw); |
282 | u32 val = readl_relaxed(pll->ctl1_base); |
283 | |
284 | return !(val & PLL_CTL1_PD); |
285 | } |
286 | |
287 | static int ma35d1_clk_pll_prepare(struct clk_hw *hw) |
288 | { |
289 | struct ma35d1_clk_pll *pll = to_ma35d1_clk_pll(hw: hw); |
290 | u32 val; |
291 | |
292 | val = readl_relaxed(pll->ctl1_base); |
293 | val &= ~PLL_CTL1_PD; |
294 | writel_relaxed(val, pll->ctl1_base); |
295 | return 0; |
296 | } |
297 | |
298 | static void ma35d1_clk_pll_unprepare(struct clk_hw *hw) |
299 | { |
300 | struct ma35d1_clk_pll *pll = to_ma35d1_clk_pll(hw: hw); |
301 | u32 val; |
302 | |
303 | val = readl_relaxed(pll->ctl1_base); |
304 | val |= PLL_CTL1_PD; |
305 | writel_relaxed(val, pll->ctl1_base); |
306 | } |
307 | |
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, |
315 | }; |
316 | |
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, |
320 | }; |
321 | |
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) |
324 | { |
325 | struct clk_parent_data pdata = { .index = 0 }; |
326 | struct clk_init_data init = {}; |
327 | struct ma35d1_clk_pll *pll; |
328 | struct clk_hw *hw; |
329 | int ret; |
330 | |
331 | pll = devm_kzalloc(dev, size: sizeof(*pll), GFP_KERNEL); |
332 | if (!pll) |
333 | return ERR_PTR(error: -ENOMEM); |
334 | |
335 | pll->id = id; |
336 | pll->mode = u8mode; |
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; |
340 | |
341 | init.name = name; |
342 | init.flags = 0; |
343 | pdata.hw = parent_hw; |
344 | init.parent_data = &pdata; |
345 | init.num_parents = 1; |
346 | |
347 | if (id == CAPLL || id == DDRPLL) |
348 | init.ops = &ma35d1_clk_fixed_pll_ops; |
349 | else |
350 | init.ops = &ma35d1_clk_pll_ops; |
351 | |
352 | pll->hw.init = &init; |
353 | hw = &pll->hw; |
354 | |
355 | ret = devm_clk_hw_register(dev, hw); |
356 | if (ret) |
357 | return ERR_PTR(error: ret); |
358 | return hw; |
359 | } |
360 | EXPORT_SYMBOL_GPL(ma35d1_reg_clk_pll); |
361 | |