Commit | Line | Data |
---|---|---|
c6ca7616 DLM |
1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* | |
3 | * Copyright (C) 2019-20 Sean Anderson <seanga2@gmail.com> | |
4 | * Copyright (c) 2019 Western Digital Corporation or its affiliates. | |
5 | */ | |
6 | #define pr_fmt(fmt) "k210-clk: " fmt | |
7 | ||
8 | #include <linux/io.h> | |
9 | #include <linux/slab.h> | |
10 | #include <linux/spinlock.h> | |
11 | #include <linux/platform_device.h> | |
12 | #include <linux/of.h> | |
13 | #include <linux/of_clk.h> | |
14 | #include <linux/of_platform.h> | |
15 | #include <linux/of_address.h> | |
16 | #include <linux/clk-provider.h> | |
17 | #include <linux/bitfield.h> | |
18 | #include <linux/delay.h> | |
19 | #include <soc/canaan/k210-sysctl.h> | |
20 | ||
21 | #include <dt-bindings/clock/k210-clk.h> | |
22 | ||
23 | struct k210_sysclk; | |
24 | ||
25 | struct k210_clk { | |
26 | int id; | |
27 | struct k210_sysclk *ksc; | |
28 | struct clk_hw hw; | |
29 | }; | |
30 | ||
31 | struct k210_clk_cfg { | |
32 | const char *name; | |
33 | u8 gate_reg; | |
34 | u8 gate_bit; | |
35 | u8 div_reg; | |
36 | u8 div_shift; | |
37 | u8 div_width; | |
38 | u8 div_type; | |
39 | u8 mux_reg; | |
40 | u8 mux_bit; | |
41 | }; | |
42 | ||
43 | enum k210_clk_div_type { | |
44 | K210_DIV_NONE, | |
45 | K210_DIV_ONE_BASED, | |
46 | K210_DIV_DOUBLE_ONE_BASED, | |
47 | K210_DIV_POWER_OF_TWO, | |
48 | }; | |
49 | ||
50 | #define K210_GATE(_reg, _bit) \ | |
51 | .gate_reg = (_reg), \ | |
52 | .gate_bit = (_bit) | |
53 | ||
54 | #define K210_DIV(_reg, _shift, _width, _type) \ | |
55 | .div_reg = (_reg), \ | |
56 | .div_shift = (_shift), \ | |
57 | .div_width = (_width), \ | |
58 | .div_type = (_type) | |
59 | ||
60 | #define K210_MUX(_reg, _bit) \ | |
61 | .mux_reg = (_reg), \ | |
62 | .mux_bit = (_bit) | |
63 | ||
64 | static struct k210_clk_cfg k210_clk_cfgs[K210_NUM_CLKS] = { | |
65 | /* Gated clocks, no mux, no divider */ | |
66 | [K210_CLK_CPU] = { | |
67 | .name = "cpu", | |
68 | K210_GATE(K210_SYSCTL_EN_CENT, 0) | |
69 | }, | |
70 | [K210_CLK_DMA] = { | |
71 | .name = "dma", | |
72 | K210_GATE(K210_SYSCTL_EN_PERI, 1) | |
73 | }, | |
74 | [K210_CLK_FFT] = { | |
75 | .name = "fft", | |
76 | K210_GATE(K210_SYSCTL_EN_PERI, 4) | |
77 | }, | |
78 | [K210_CLK_GPIO] = { | |
79 | .name = "gpio", | |
80 | K210_GATE(K210_SYSCTL_EN_PERI, 5) | |
81 | }, | |
82 | [K210_CLK_UART1] = { | |
83 | .name = "uart1", | |
84 | K210_GATE(K210_SYSCTL_EN_PERI, 16) | |
85 | }, | |
86 | [K210_CLK_UART2] = { | |
87 | .name = "uart2", | |
88 | K210_GATE(K210_SYSCTL_EN_PERI, 17) | |
89 | }, | |
90 | [K210_CLK_UART3] = { | |
91 | .name = "uart3", | |
92 | K210_GATE(K210_SYSCTL_EN_PERI, 18) | |
93 | }, | |
94 | [K210_CLK_FPIOA] = { | |
95 | .name = "fpioa", | |
96 | K210_GATE(K210_SYSCTL_EN_PERI, 20) | |
97 | }, | |
98 | [K210_CLK_SHA] = { | |
99 | .name = "sha", | |
100 | K210_GATE(K210_SYSCTL_EN_PERI, 26) | |
101 | }, | |
102 | [K210_CLK_AES] = { | |
103 | .name = "aes", | |
104 | K210_GATE(K210_SYSCTL_EN_PERI, 19) | |
105 | }, | |
106 | [K210_CLK_OTP] = { | |
107 | .name = "otp", | |
108 | K210_GATE(K210_SYSCTL_EN_PERI, 27) | |
109 | }, | |
110 | [K210_CLK_RTC] = { | |
111 | .name = "rtc", | |
112 | K210_GATE(K210_SYSCTL_EN_PERI, 29) | |
113 | }, | |
114 | ||
115 | /* Gated divider clocks */ | |
116 | [K210_CLK_SRAM0] = { | |
117 | .name = "sram0", | |
118 | K210_GATE(K210_SYSCTL_EN_CENT, 1), | |
119 | K210_DIV(K210_SYSCTL_THR0, 0, 4, K210_DIV_ONE_BASED) | |
120 | }, | |
121 | [K210_CLK_SRAM1] = { | |
122 | .name = "sram1", | |
123 | K210_GATE(K210_SYSCTL_EN_CENT, 2), | |
124 | K210_DIV(K210_SYSCTL_THR0, 4, 4, K210_DIV_ONE_BASED) | |
125 | }, | |
126 | [K210_CLK_ROM] = { | |
127 | .name = "rom", | |
128 | K210_GATE(K210_SYSCTL_EN_PERI, 0), | |
129 | K210_DIV(K210_SYSCTL_THR0, 16, 4, K210_DIV_ONE_BASED) | |
130 | }, | |
131 | [K210_CLK_DVP] = { | |
132 | .name = "dvp", | |
133 | K210_GATE(K210_SYSCTL_EN_PERI, 3), | |
134 | K210_DIV(K210_SYSCTL_THR0, 12, 4, K210_DIV_ONE_BASED) | |
135 | }, | |
136 | [K210_CLK_APB0] = { | |
137 | .name = "apb0", | |
138 | K210_GATE(K210_SYSCTL_EN_CENT, 3), | |
139 | K210_DIV(K210_SYSCTL_SEL0, 3, 3, K210_DIV_ONE_BASED) | |
140 | }, | |
141 | [K210_CLK_APB1] = { | |
142 | .name = "apb1", | |
143 | K210_GATE(K210_SYSCTL_EN_CENT, 4), | |
144 | K210_DIV(K210_SYSCTL_SEL0, 6, 3, K210_DIV_ONE_BASED) | |
145 | }, | |
146 | [K210_CLK_APB2] = { | |
147 | .name = "apb2", | |
148 | K210_GATE(K210_SYSCTL_EN_CENT, 5), | |
149 | K210_DIV(K210_SYSCTL_SEL0, 9, 3, K210_DIV_ONE_BASED) | |
150 | }, | |
151 | [K210_CLK_AI] = { | |
152 | .name = "ai", | |
153 | K210_GATE(K210_SYSCTL_EN_PERI, 2), | |
154 | K210_DIV(K210_SYSCTL_THR0, 8, 4, K210_DIV_ONE_BASED) | |
155 | }, | |
156 | [K210_CLK_SPI0] = { | |
157 | .name = "spi0", | |
158 | K210_GATE(K210_SYSCTL_EN_PERI, 6), | |
159 | K210_DIV(K210_SYSCTL_THR1, 0, 8, K210_DIV_DOUBLE_ONE_BASED) | |
160 | }, | |
161 | [K210_CLK_SPI1] = { | |
162 | .name = "spi1", | |
163 | K210_GATE(K210_SYSCTL_EN_PERI, 7), | |
164 | K210_DIV(K210_SYSCTL_THR1, 8, 8, K210_DIV_DOUBLE_ONE_BASED) | |
165 | }, | |
166 | [K210_CLK_SPI2] = { | |
167 | .name = "spi2", | |
168 | K210_GATE(K210_SYSCTL_EN_PERI, 8), | |
169 | K210_DIV(K210_SYSCTL_THR1, 16, 8, K210_DIV_DOUBLE_ONE_BASED) | |
170 | }, | |
171 | [K210_CLK_I2C0] = { | |
172 | .name = "i2c0", | |
173 | K210_GATE(K210_SYSCTL_EN_PERI, 13), | |
174 | K210_DIV(K210_SYSCTL_THR5, 8, 8, K210_DIV_DOUBLE_ONE_BASED) | |
175 | }, | |
176 | [K210_CLK_I2C1] = { | |
177 | .name = "i2c1", | |
178 | K210_GATE(K210_SYSCTL_EN_PERI, 14), | |
179 | K210_DIV(K210_SYSCTL_THR5, 16, 8, K210_DIV_DOUBLE_ONE_BASED) | |
180 | }, | |
181 | [K210_CLK_I2C2] = { | |
182 | .name = "i2c2", | |
183 | K210_GATE(K210_SYSCTL_EN_PERI, 15), | |
184 | K210_DIV(K210_SYSCTL_THR5, 24, 8, K210_DIV_DOUBLE_ONE_BASED) | |
185 | }, | |
186 | [K210_CLK_WDT0] = { | |
187 | .name = "wdt0", | |
188 | K210_GATE(K210_SYSCTL_EN_PERI, 24), | |
189 | K210_DIV(K210_SYSCTL_THR6, 0, 8, K210_DIV_DOUBLE_ONE_BASED) | |
190 | }, | |
191 | [K210_CLK_WDT1] = { | |
192 | .name = "wdt1", | |
193 | K210_GATE(K210_SYSCTL_EN_PERI, 25), | |
194 | K210_DIV(K210_SYSCTL_THR6, 8, 8, K210_DIV_DOUBLE_ONE_BASED) | |
195 | }, | |
196 | [K210_CLK_I2S0] = { | |
197 | .name = "i2s0", | |
198 | K210_GATE(K210_SYSCTL_EN_PERI, 10), | |
199 | K210_DIV(K210_SYSCTL_THR3, 0, 16, K210_DIV_DOUBLE_ONE_BASED) | |
200 | }, | |
201 | [K210_CLK_I2S1] = { | |
202 | .name = "i2s1", | |
203 | K210_GATE(K210_SYSCTL_EN_PERI, 11), | |
204 | K210_DIV(K210_SYSCTL_THR3, 16, 16, K210_DIV_DOUBLE_ONE_BASED) | |
205 | }, | |
206 | [K210_CLK_I2S2] = { | |
207 | .name = "i2s2", | |
208 | K210_GATE(K210_SYSCTL_EN_PERI, 12), | |
209 | K210_DIV(K210_SYSCTL_THR4, 0, 16, K210_DIV_DOUBLE_ONE_BASED) | |
210 | }, | |
211 | ||
212 | /* Divider clocks, no gate, no mux */ | |
213 | [K210_CLK_I2S0_M] = { | |
214 | .name = "i2s0_m", | |
215 | K210_DIV(K210_SYSCTL_THR4, 16, 8, K210_DIV_DOUBLE_ONE_BASED) | |
216 | }, | |
217 | [K210_CLK_I2S1_M] = { | |
218 | .name = "i2s1_m", | |
219 | K210_DIV(K210_SYSCTL_THR4, 24, 8, K210_DIV_DOUBLE_ONE_BASED) | |
220 | }, | |
221 | [K210_CLK_I2S2_M] = { | |
222 | .name = "i2s2_m", | |
223 | K210_DIV(K210_SYSCTL_THR4, 0, 8, K210_DIV_DOUBLE_ONE_BASED) | |
224 | }, | |
225 | ||
226 | /* Muxed gated divider clocks */ | |
227 | [K210_CLK_SPI3] = { | |
228 | .name = "spi3", | |
229 | K210_GATE(K210_SYSCTL_EN_PERI, 9), | |
230 | K210_DIV(K210_SYSCTL_THR1, 24, 8, K210_DIV_DOUBLE_ONE_BASED), | |
231 | K210_MUX(K210_SYSCTL_SEL0, 12) | |
232 | }, | |
233 | [K210_CLK_TIMER0] = { | |
234 | .name = "timer0", | |
235 | K210_GATE(K210_SYSCTL_EN_PERI, 21), | |
236 | K210_DIV(K210_SYSCTL_THR2, 0, 8, K210_DIV_DOUBLE_ONE_BASED), | |
237 | K210_MUX(K210_SYSCTL_SEL0, 13) | |
238 | }, | |
239 | [K210_CLK_TIMER1] = { | |
240 | .name = "timer1", | |
241 | K210_GATE(K210_SYSCTL_EN_PERI, 22), | |
242 | K210_DIV(K210_SYSCTL_THR2, 8, 8, K210_DIV_DOUBLE_ONE_BASED), | |
243 | K210_MUX(K210_SYSCTL_SEL0, 14) | |
244 | }, | |
245 | [K210_CLK_TIMER2] = { | |
246 | .name = "timer2", | |
247 | K210_GATE(K210_SYSCTL_EN_PERI, 23), | |
248 | K210_DIV(K210_SYSCTL_THR2, 16, 8, K210_DIV_DOUBLE_ONE_BASED), | |
249 | K210_MUX(K210_SYSCTL_SEL0, 15) | |
250 | }, | |
251 | }; | |
252 | ||
253 | /* | |
254 | * PLL control register bits. | |
255 | */ | |
256 | #define K210_PLL_CLKR GENMASK(3, 0) | |
257 | #define K210_PLL_CLKF GENMASK(9, 4) | |
258 | #define K210_PLL_CLKOD GENMASK(13, 10) | |
259 | #define K210_PLL_BWADJ GENMASK(19, 14) | |
260 | #define K210_PLL_RESET (1 << 20) | |
261 | #define K210_PLL_PWRD (1 << 21) | |
262 | #define K210_PLL_INTFB (1 << 22) | |
263 | #define K210_PLL_BYPASS (1 << 23) | |
264 | #define K210_PLL_TEST (1 << 24) | |
265 | #define K210_PLL_EN (1 << 25) | |
266 | #define K210_PLL_SEL GENMASK(27, 26) /* PLL2 only */ | |
267 | ||
268 | /* | |
269 | * PLL lock register bits. | |
270 | */ | |
271 | #define K210_PLL_LOCK 0 | |
272 | #define K210_PLL_CLEAR_SLIP 2 | |
273 | #define K210_PLL_TEST_OUT 3 | |
274 | ||
275 | /* | |
276 | * Clock selector register bits. | |
277 | */ | |
278 | #define K210_ACLK_SEL BIT(0) | |
279 | #define K210_ACLK_DIV GENMASK(2, 1) | |
280 | ||
281 | /* | |
282 | * PLLs. | |
283 | */ | |
284 | enum k210_pll_id { | |
285 | K210_PLL0, K210_PLL1, K210_PLL2, K210_PLL_NUM | |
286 | }; | |
287 | ||
288 | struct k210_pll { | |
289 | enum k210_pll_id id; | |
290 | struct k210_sysclk *ksc; | |
291 | void __iomem *base; | |
292 | void __iomem *reg; | |
293 | void __iomem *lock; | |
294 | u8 lock_shift; | |
295 | u8 lock_width; | |
296 | struct clk_hw hw; | |
297 | }; | |
298 | #define to_k210_pll(_hw) container_of(_hw, struct k210_pll, hw) | |
299 | ||
300 | /* | |
301 | * PLLs configuration: by default PLL0 runs at 780 MHz and PLL1 at 299 MHz. | |
302 | * The first 2 SRAM banks depend on ACLK/CPU clock which is by default PLL0 | |
303 | * rate divided by 2. Set PLL1 to 390 MHz so that the third SRAM bank has the | |
304 | * same clock as the first 2. | |
305 | */ | |
306 | struct k210_pll_cfg { | |
307 | u32 reg; | |
308 | u8 lock_shift; | |
309 | u8 lock_width; | |
310 | u32 r; | |
311 | u32 f; | |
312 | u32 od; | |
313 | u32 bwadj; | |
314 | }; | |
315 | ||
316 | static struct k210_pll_cfg k210_plls_cfg[] = { | |
317 | { K210_SYSCTL_PLL0, 0, 2, 0, 59, 1, 59 }, /* 780 MHz */ | |
318 | { K210_SYSCTL_PLL1, 8, 1, 0, 59, 3, 59 }, /* 390 MHz */ | |
319 | { K210_SYSCTL_PLL2, 16, 1, 0, 22, 1, 22 }, /* 299 MHz */ | |
320 | }; | |
321 | ||
322 | /** | |
323 | * struct k210_sysclk - sysclk driver data | |
324 | * @regs: system controller registers start address | |
325 | * @clk_lock: clock setting spinlock | |
326 | * @plls: SoC PLLs descriptors | |
327 | * @aclk: ACLK clock | |
328 | * @clks: All other clocks | |
329 | */ | |
330 | struct k210_sysclk { | |
331 | void __iomem *regs; | |
332 | spinlock_t clk_lock; | |
333 | struct k210_pll plls[K210_PLL_NUM]; | |
334 | struct clk_hw aclk; | |
335 | struct k210_clk clks[K210_NUM_CLKS]; | |
336 | }; | |
337 | ||
338 | #define to_k210_sysclk(_hw) container_of(_hw, struct k210_sysclk, aclk) | |
339 | ||
340 | /* | |
341 | * Set ACLK parent selector: 0 for IN0, 1 for PLL0. | |
342 | */ | |
343 | static void k210_aclk_set_selector(void __iomem *regs, u8 sel) | |
344 | { | |
345 | u32 reg = readl(regs + K210_SYSCTL_SEL0); | |
346 | ||
347 | if (sel) | |
348 | reg |= K210_ACLK_SEL; | |
349 | else | |
350 | reg &= K210_ACLK_SEL; | |
351 | writel(reg, regs + K210_SYSCTL_SEL0); | |
352 | } | |
353 | ||
354 | static void k210_init_pll(void __iomem *regs, enum k210_pll_id pllid, | |
355 | struct k210_pll *pll) | |
356 | { | |
357 | pll->id = pllid; | |
358 | pll->reg = regs + k210_plls_cfg[pllid].reg; | |
359 | pll->lock = regs + K210_SYSCTL_PLL_LOCK; | |
360 | pll->lock_shift = k210_plls_cfg[pllid].lock_shift; | |
361 | pll->lock_width = k210_plls_cfg[pllid].lock_width; | |
362 | } | |
363 | ||
364 | static void k210_pll_wait_for_lock(struct k210_pll *pll) | |
365 | { | |
366 | u32 reg, mask = GENMASK(pll->lock_shift + pll->lock_width - 1, | |
367 | pll->lock_shift); | |
368 | ||
369 | while (true) { | |
370 | reg = readl(pll->lock); | |
371 | if ((reg & mask) == mask) | |
372 | break; | |
373 | ||
374 | reg |= BIT(pll->lock_shift + K210_PLL_CLEAR_SLIP); | |
375 | writel(reg, pll->lock); | |
376 | } | |
377 | } | |
378 | ||
379 | static bool k210_pll_hw_is_enabled(struct k210_pll *pll) | |
380 | { | |
381 | u32 reg = readl(pll->reg); | |
382 | u32 mask = K210_PLL_PWRD | K210_PLL_EN; | |
383 | ||
384 | if (reg & K210_PLL_RESET) | |
385 | return false; | |
386 | ||
387 | return (reg & mask) == mask; | |
388 | } | |
389 | ||
390 | static void k210_pll_enable_hw(void __iomem *regs, struct k210_pll *pll) | |
391 | { | |
392 | struct k210_pll_cfg *pll_cfg = &k210_plls_cfg[pll->id]; | |
393 | u32 reg; | |
394 | ||
395 | if (k210_pll_hw_is_enabled(pll)) | |
396 | return; | |
397 | ||
398 | /* | |
399 | * For PLL0, we need to re-parent ACLK to IN0 to keep the CPU cores and | |
400 | * SRAM running. | |
401 | */ | |
402 | if (pll->id == K210_PLL0) | |
403 | k210_aclk_set_selector(regs, 0); | |
404 | ||
405 | /* Set PLL factors */ | |
406 | reg = readl(pll->reg); | |
407 | reg &= ~GENMASK(19, 0); | |
408 | reg |= FIELD_PREP(K210_PLL_CLKR, pll_cfg->r); | |
409 | reg |= FIELD_PREP(K210_PLL_CLKF, pll_cfg->f); | |
410 | reg |= FIELD_PREP(K210_PLL_CLKOD, pll_cfg->od); | |
411 | reg |= FIELD_PREP(K210_PLL_BWADJ, pll_cfg->bwadj); | |
412 | reg |= K210_PLL_PWRD; | |
413 | writel(reg, pll->reg); | |
414 | ||
415 | /* | |
416 | * Reset the PLL: ensure reset is low before asserting it. | |
417 | * The magic NOPs come from the Kendryte reference SDK. | |
418 | */ | |
419 | reg &= ~K210_PLL_RESET; | |
420 | writel(reg, pll->reg); | |
421 | reg |= K210_PLL_RESET; | |
422 | writel(reg, pll->reg); | |
423 | nop(); | |
424 | nop(); | |
425 | reg &= ~K210_PLL_RESET; | |
426 | writel(reg, pll->reg); | |
427 | ||
428 | k210_pll_wait_for_lock(pll); | |
429 | ||
430 | reg &= ~K210_PLL_BYPASS; | |
431 | reg |= K210_PLL_EN; | |
432 | writel(reg, pll->reg); | |
433 | ||
434 | if (pll->id == K210_PLL0) | |
435 | k210_aclk_set_selector(regs, 1); | |
436 | } | |
437 | ||
438 | static int k210_pll_enable(struct clk_hw *hw) | |
439 | { | |
440 | struct k210_pll *pll = to_k210_pll(hw); | |
441 | struct k210_sysclk *ksc = pll->ksc; | |
442 | unsigned long flags; | |
443 | ||
444 | spin_lock_irqsave(&ksc->clk_lock, flags); | |
445 | ||
446 | k210_pll_enable_hw(ksc->regs, pll); | |
447 | ||
448 | spin_unlock_irqrestore(&ksc->clk_lock, flags); | |
449 | ||
450 | return 0; | |
451 | } | |
452 | ||
453 | static void k210_pll_disable(struct clk_hw *hw) | |
454 | { | |
455 | struct k210_pll *pll = to_k210_pll(hw); | |
456 | struct k210_sysclk *ksc = pll->ksc; | |
457 | unsigned long flags; | |
458 | u32 reg; | |
459 | ||
460 | /* | |
461 | * Bypassing before powering off is important so child clocks do not | |
462 | * stop working. This is especially important for pll0, the indirect | |
463 | * parent of the cpu clock. | |
464 | */ | |
465 | spin_lock_irqsave(&ksc->clk_lock, flags); | |
466 | reg = readl(pll->reg); | |
467 | reg |= K210_PLL_BYPASS; | |
468 | writel(reg, pll->reg); | |
469 | ||
470 | reg &= ~K210_PLL_PWRD; | |
471 | reg &= ~K210_PLL_EN; | |
472 | writel(reg, pll->reg); | |
473 | spin_unlock_irqrestore(&ksc->clk_lock, flags); | |
474 | } | |
475 | ||
476 | static int k210_pll_is_enabled(struct clk_hw *hw) | |
477 | { | |
478 | return k210_pll_hw_is_enabled(to_k210_pll(hw)); | |
479 | } | |
480 | ||
481 | static unsigned long k210_pll_get_rate(struct clk_hw *hw, | |
482 | unsigned long parent_rate) | |
483 | { | |
484 | struct k210_pll *pll = to_k210_pll(hw); | |
485 | u32 reg = readl(pll->reg); | |
486 | u32 r, f, od; | |
487 | ||
488 | if (reg & K210_PLL_BYPASS) | |
489 | return parent_rate; | |
490 | ||
491 | if (!(reg & K210_PLL_PWRD)) | |
492 | return 0; | |
493 | ||
494 | r = FIELD_GET(K210_PLL_CLKR, reg) + 1; | |
495 | f = FIELD_GET(K210_PLL_CLKF, reg) + 1; | |
496 | od = FIELD_GET(K210_PLL_CLKOD, reg) + 1; | |
497 | ||
498 | return (u64)parent_rate * f / (r * od); | |
499 | } | |
500 | ||
501 | static const struct clk_ops k210_pll_ops = { | |
502 | .enable = k210_pll_enable, | |
503 | .disable = k210_pll_disable, | |
504 | .is_enabled = k210_pll_is_enabled, | |
505 | .recalc_rate = k210_pll_get_rate, | |
506 | }; | |
507 | ||
508 | static int k210_pll2_set_parent(struct clk_hw *hw, u8 index) | |
509 | { | |
510 | struct k210_pll *pll = to_k210_pll(hw); | |
511 | struct k210_sysclk *ksc = pll->ksc; | |
512 | unsigned long flags; | |
513 | u32 reg; | |
514 | ||
515 | spin_lock_irqsave(&ksc->clk_lock, flags); | |
516 | ||
517 | reg = readl(pll->reg); | |
518 | reg &= ~K210_PLL_SEL; | |
519 | reg |= FIELD_PREP(K210_PLL_SEL, index); | |
520 | writel(reg, pll->reg); | |
521 | ||
522 | spin_unlock_irqrestore(&ksc->clk_lock, flags); | |
523 | ||
524 | return 0; | |
525 | } | |
526 | ||
527 | static u8 k210_pll2_get_parent(struct clk_hw *hw) | |
528 | { | |
529 | struct k210_pll *pll = to_k210_pll(hw); | |
530 | u32 reg = readl(pll->reg); | |
531 | ||
532 | return FIELD_GET(K210_PLL_SEL, reg); | |
533 | } | |
534 | ||
535 | static const struct clk_ops k210_pll2_ops = { | |
536 | .enable = k210_pll_enable, | |
537 | .disable = k210_pll_disable, | |
538 | .is_enabled = k210_pll_is_enabled, | |
539 | .recalc_rate = k210_pll_get_rate, | |
540 | .set_parent = k210_pll2_set_parent, | |
541 | .get_parent = k210_pll2_get_parent, | |
542 | }; | |
543 | ||
544 | static int __init k210_register_pll(struct device_node *np, | |
545 | struct k210_sysclk *ksc, | |
546 | enum k210_pll_id pllid, const char *name, | |
547 | int num_parents, const struct clk_ops *ops) | |
548 | { | |
549 | struct k210_pll *pll = &ksc->plls[pllid]; | |
550 | struct clk_init_data init = {}; | |
551 | const struct clk_parent_data parent_data[] = { | |
552 | { /* .index = 0 for in0 */ }, | |
553 | { .hw = &ksc->plls[K210_PLL0].hw }, | |
554 | { .hw = &ksc->plls[K210_PLL1].hw }, | |
555 | }; | |
556 | ||
557 | init.name = name; | |
558 | init.parent_data = parent_data; | |
559 | init.num_parents = num_parents; | |
560 | init.ops = ops; | |
561 | ||
562 | pll->hw.init = &init; | |
563 | pll->ksc = ksc; | |
564 | ||
565 | return of_clk_hw_register(np, &pll->hw); | |
566 | } | |
567 | ||
568 | static int __init k210_register_plls(struct device_node *np, | |
569 | struct k210_sysclk *ksc) | |
570 | { | |
571 | int i, ret; | |
572 | ||
573 | for (i = 0; i < K210_PLL_NUM; i++) | |
574 | k210_init_pll(ksc->regs, i, &ksc->plls[i]); | |
575 | ||
576 | /* PLL0 and PLL1 only have IN0 as parent */ | |
577 | ret = k210_register_pll(np, ksc, K210_PLL0, "pll0", 1, &k210_pll_ops); | |
578 | if (ret) { | |
579 | pr_err("%pOFP: register PLL0 failed\n", np); | |
580 | return ret; | |
581 | } | |
582 | ret = k210_register_pll(np, ksc, K210_PLL1, "pll1", 1, &k210_pll_ops); | |
583 | if (ret) { | |
584 | pr_err("%pOFP: register PLL1 failed\n", np); | |
585 | return ret; | |
586 | } | |
587 | ||
588 | /* PLL2 has IN0, PLL0 and PLL1 as parents */ | |
589 | ret = k210_register_pll(np, ksc, K210_PLL2, "pll2", 3, &k210_pll2_ops); | |
590 | if (ret) { | |
591 | pr_err("%pOFP: register PLL2 failed\n", np); | |
592 | return ret; | |
593 | } | |
594 | ||
595 | return 0; | |
596 | } | |
597 | ||
598 | static int k210_aclk_set_parent(struct clk_hw *hw, u8 index) | |
599 | { | |
600 | struct k210_sysclk *ksc = to_k210_sysclk(hw); | |
601 | unsigned long flags; | |
602 | ||
603 | spin_lock_irqsave(&ksc->clk_lock, flags); | |
604 | ||
605 | k210_aclk_set_selector(ksc->regs, index); | |
606 | ||
607 | spin_unlock_irqrestore(&ksc->clk_lock, flags); | |
608 | ||
609 | return 0; | |
610 | } | |
611 | ||
612 | static u8 k210_aclk_get_parent(struct clk_hw *hw) | |
613 | { | |
614 | struct k210_sysclk *ksc = to_k210_sysclk(hw); | |
615 | u32 sel; | |
616 | ||
617 | sel = readl(ksc->regs + K210_SYSCTL_SEL0) & K210_ACLK_SEL; | |
618 | ||
619 | return sel ? 1 : 0; | |
620 | } | |
621 | ||
622 | static unsigned long k210_aclk_get_rate(struct clk_hw *hw, | |
623 | unsigned long parent_rate) | |
624 | { | |
625 | struct k210_sysclk *ksc = to_k210_sysclk(hw); | |
626 | u32 reg = readl(ksc->regs + K210_SYSCTL_SEL0); | |
627 | unsigned int shift; | |
628 | ||
629 | if (!(reg & 0x1)) | |
630 | return parent_rate; | |
631 | ||
632 | shift = FIELD_GET(K210_ACLK_DIV, reg); | |
633 | ||
634 | return parent_rate / (2UL << shift); | |
635 | } | |
636 | ||
637 | static const struct clk_ops k210_aclk_ops = { | |
638 | .set_parent = k210_aclk_set_parent, | |
639 | .get_parent = k210_aclk_get_parent, | |
640 | .recalc_rate = k210_aclk_get_rate, | |
641 | }; | |
642 | ||
643 | /* | |
644 | * ACLK has IN0 and PLL0 as parents. | |
645 | */ | |
646 | static int __init k210_register_aclk(struct device_node *np, | |
647 | struct k210_sysclk *ksc) | |
648 | { | |
649 | struct clk_init_data init = {}; | |
650 | const struct clk_parent_data parent_data[] = { | |
651 | { /* .index = 0 for in0 */ }, | |
652 | { .hw = &ksc->plls[K210_PLL0].hw }, | |
653 | }; | |
654 | int ret; | |
655 | ||
656 | init.name = "aclk"; | |
657 | init.parent_data = parent_data; | |
658 | init.num_parents = 2; | |
659 | init.ops = &k210_aclk_ops; | |
660 | ksc->aclk.init = &init; | |
661 | ||
662 | ret = of_clk_hw_register(np, &ksc->aclk); | |
663 | if (ret) { | |
664 | pr_err("%pOFP: register aclk failed\n", np); | |
665 | return ret; | |
666 | } | |
667 | ||
668 | return 0; | |
669 | } | |
670 | ||
671 | #define to_k210_clk(_hw) container_of(_hw, struct k210_clk, hw) | |
672 | ||
673 | static int k210_clk_enable(struct clk_hw *hw) | |
674 | { | |
675 | struct k210_clk *kclk = to_k210_clk(hw); | |
676 | struct k210_sysclk *ksc = kclk->ksc; | |
677 | struct k210_clk_cfg *cfg = &k210_clk_cfgs[kclk->id]; | |
678 | unsigned long flags; | |
679 | u32 reg; | |
680 | ||
681 | if (!cfg->gate_reg) | |
682 | return 0; | |
683 | ||
684 | spin_lock_irqsave(&ksc->clk_lock, flags); | |
685 | reg = readl(ksc->regs + cfg->gate_reg); | |
686 | reg |= BIT(cfg->gate_bit); | |
687 | writel(reg, ksc->regs + cfg->gate_reg); | |
688 | spin_unlock_irqrestore(&ksc->clk_lock, flags); | |
689 | ||
690 | return 0; | |
691 | } | |
692 | ||
693 | static void k210_clk_disable(struct clk_hw *hw) | |
694 | { | |
695 | struct k210_clk *kclk = to_k210_clk(hw); | |
696 | struct k210_sysclk *ksc = kclk->ksc; | |
697 | struct k210_clk_cfg *cfg = &k210_clk_cfgs[kclk->id]; | |
698 | unsigned long flags; | |
699 | u32 reg; | |
700 | ||
701 | if (!cfg->gate_reg) | |
702 | return; | |
703 | ||
704 | spin_lock_irqsave(&ksc->clk_lock, flags); | |
705 | reg = readl(ksc->regs + cfg->gate_reg); | |
706 | reg &= ~BIT(cfg->gate_bit); | |
707 | writel(reg, ksc->regs + cfg->gate_reg); | |
708 | spin_unlock_irqrestore(&ksc->clk_lock, flags); | |
709 | } | |
710 | ||
711 | static int k210_clk_set_parent(struct clk_hw *hw, u8 index) | |
712 | { | |
713 | struct k210_clk *kclk = to_k210_clk(hw); | |
714 | struct k210_sysclk *ksc = kclk->ksc; | |
715 | struct k210_clk_cfg *cfg = &k210_clk_cfgs[kclk->id]; | |
716 | unsigned long flags; | |
717 | u32 reg; | |
718 | ||
719 | spin_lock_irqsave(&ksc->clk_lock, flags); | |
720 | reg = readl(ksc->regs + cfg->mux_reg); | |
721 | if (index) | |
722 | reg |= BIT(cfg->mux_bit); | |
723 | else | |
724 | reg &= ~BIT(cfg->mux_bit); | |
faa0e307 | 725 | writel(reg, ksc->regs + cfg->mux_reg); |
c6ca7616 DLM |
726 | spin_unlock_irqrestore(&ksc->clk_lock, flags); |
727 | ||
728 | return 0; | |
729 | } | |
730 | ||
731 | static u8 k210_clk_get_parent(struct clk_hw *hw) | |
732 | { | |
733 | struct k210_clk *kclk = to_k210_clk(hw); | |
734 | struct k210_sysclk *ksc = kclk->ksc; | |
735 | struct k210_clk_cfg *cfg = &k210_clk_cfgs[kclk->id]; | |
736 | unsigned long flags; | |
737 | u32 reg, idx; | |
738 | ||
739 | spin_lock_irqsave(&ksc->clk_lock, flags); | |
740 | reg = readl(ksc->regs + cfg->mux_reg); | |
741 | idx = (reg & BIT(cfg->mux_bit)) ? 1 : 0; | |
742 | spin_unlock_irqrestore(&ksc->clk_lock, flags); | |
743 | ||
744 | return idx; | |
745 | } | |
746 | ||
747 | static unsigned long k210_clk_get_rate(struct clk_hw *hw, | |
748 | unsigned long parent_rate) | |
749 | { | |
750 | struct k210_clk *kclk = to_k210_clk(hw); | |
751 | struct k210_sysclk *ksc = kclk->ksc; | |
752 | struct k210_clk_cfg *cfg = &k210_clk_cfgs[kclk->id]; | |
753 | u32 reg, div_val; | |
754 | ||
755 | if (!cfg->div_reg) | |
756 | return parent_rate; | |
757 | ||
758 | reg = readl(ksc->regs + cfg->div_reg); | |
759 | div_val = (reg >> cfg->div_shift) & GENMASK(cfg->div_width - 1, 0); | |
760 | ||
761 | switch (cfg->div_type) { | |
762 | case K210_DIV_ONE_BASED: | |
763 | return parent_rate / (div_val + 1); | |
764 | case K210_DIV_DOUBLE_ONE_BASED: | |
765 | return parent_rate / ((div_val + 1) * 2); | |
766 | case K210_DIV_POWER_OF_TWO: | |
767 | return parent_rate / (2UL << div_val); | |
768 | case K210_DIV_NONE: | |
769 | default: | |
770 | return 0; | |
771 | } | |
772 | } | |
773 | ||
774 | static const struct clk_ops k210_clk_mux_ops = { | |
775 | .enable = k210_clk_enable, | |
776 | .disable = k210_clk_disable, | |
777 | .set_parent = k210_clk_set_parent, | |
778 | .get_parent = k210_clk_get_parent, | |
779 | .recalc_rate = k210_clk_get_rate, | |
780 | }; | |
781 | ||
782 | static const struct clk_ops k210_clk_ops = { | |
783 | .enable = k210_clk_enable, | |
784 | .disable = k210_clk_disable, | |
785 | .recalc_rate = k210_clk_get_rate, | |
786 | }; | |
787 | ||
788 | static void __init k210_register_clk(struct device_node *np, | |
789 | struct k210_sysclk *ksc, int id, | |
790 | const struct clk_parent_data *parent_data, | |
791 | int num_parents, unsigned long flags) | |
792 | { | |
793 | struct k210_clk *kclk = &ksc->clks[id]; | |
794 | struct clk_init_data init = {}; | |
795 | int ret; | |
796 | ||
797 | init.name = k210_clk_cfgs[id].name; | |
798 | init.flags = flags; | |
799 | init.parent_data = parent_data; | |
800 | init.num_parents = num_parents; | |
801 | if (num_parents > 1) | |
802 | init.ops = &k210_clk_mux_ops; | |
803 | else | |
804 | init.ops = &k210_clk_ops; | |
805 | ||
806 | kclk->id = id; | |
807 | kclk->ksc = ksc; | |
808 | kclk->hw.init = &init; | |
809 | ||
810 | ret = of_clk_hw_register(np, &kclk->hw); | |
811 | if (ret) { | |
812 | pr_err("%pOFP: register clock %s failed\n", | |
813 | np, k210_clk_cfgs[id].name); | |
814 | kclk->id = -1; | |
815 | } | |
816 | } | |
817 | ||
818 | /* | |
819 | * All muxed clocks have IN0 and PLL0 as parents. | |
820 | */ | |
821 | static inline void __init k210_register_mux_clk(struct device_node *np, | |
822 | struct k210_sysclk *ksc, int id) | |
823 | { | |
824 | const struct clk_parent_data parent_data[2] = { | |
825 | { /* .index = 0 for in0 */ }, | |
826 | { .hw = &ksc->plls[K210_PLL0].hw } | |
827 | }; | |
828 | ||
829 | k210_register_clk(np, ksc, id, parent_data, 2, 0); | |
830 | } | |
831 | ||
832 | static inline void __init k210_register_in0_child(struct device_node *np, | |
833 | struct k210_sysclk *ksc, int id) | |
834 | { | |
835 | const struct clk_parent_data parent_data = { | |
836 | /* .index = 0 for in0 */ | |
837 | }; | |
838 | ||
839 | k210_register_clk(np, ksc, id, &parent_data, 1, 0); | |
840 | } | |
841 | ||
842 | static inline void __init k210_register_pll_child(struct device_node *np, | |
843 | struct k210_sysclk *ksc, int id, | |
844 | enum k210_pll_id pllid, | |
845 | unsigned long flags) | |
846 | { | |
847 | const struct clk_parent_data parent_data = { | |
848 | .hw = &ksc->plls[pllid].hw, | |
849 | }; | |
850 | ||
851 | k210_register_clk(np, ksc, id, &parent_data, 1, flags); | |
852 | } | |
853 | ||
854 | static inline void __init k210_register_aclk_child(struct device_node *np, | |
855 | struct k210_sysclk *ksc, int id, | |
856 | unsigned long flags) | |
857 | { | |
858 | const struct clk_parent_data parent_data = { | |
859 | .hw = &ksc->aclk, | |
860 | }; | |
861 | ||
862 | k210_register_clk(np, ksc, id, &parent_data, 1, flags); | |
863 | } | |
864 | ||
865 | static inline void __init k210_register_clk_child(struct device_node *np, | |
866 | struct k210_sysclk *ksc, int id, | |
867 | int parent_id) | |
868 | { | |
869 | const struct clk_parent_data parent_data = { | |
870 | .hw = &ksc->clks[parent_id].hw, | |
871 | }; | |
872 | ||
873 | k210_register_clk(np, ksc, id, &parent_data, 1, 0); | |
874 | } | |
875 | ||
876 | static struct clk_hw *k210_clk_hw_onecell_get(struct of_phandle_args *clkspec, | |
877 | void *data) | |
878 | { | |
879 | struct k210_sysclk *ksc = data; | |
880 | unsigned int idx = clkspec->args[0]; | |
881 | ||
882 | if (idx >= K210_NUM_CLKS) | |
883 | return ERR_PTR(-EINVAL); | |
884 | ||
885 | return &ksc->clks[idx].hw; | |
886 | } | |
887 | ||
888 | static void __init k210_clk_init(struct device_node *np) | |
889 | { | |
890 | struct device_node *sysctl_np; | |
891 | struct k210_sysclk *ksc; | |
892 | int i, ret; | |
893 | ||
894 | ksc = kzalloc(sizeof(*ksc), GFP_KERNEL); | |
895 | if (!ksc) | |
896 | return; | |
897 | ||
898 | spin_lock_init(&ksc->clk_lock); | |
899 | sysctl_np = of_get_parent(np); | |
900 | ksc->regs = of_iomap(sysctl_np, 0); | |
901 | of_node_put(sysctl_np); | |
902 | if (!ksc->regs) { | |
903 | pr_err("%pOFP: failed to map registers\n", np); | |
904 | return; | |
905 | } | |
906 | ||
907 | ret = k210_register_plls(np, ksc); | |
908 | if (ret) | |
909 | return; | |
910 | ||
911 | ret = k210_register_aclk(np, ksc); | |
912 | if (ret) | |
913 | return; | |
914 | ||
915 | /* | |
916 | * Critical clocks: there are no consumers of the SRAM clocks, | |
917 | * including the AI clock for the third SRAM bank. The CPU clock | |
918 | * is only referenced by the uarths serial device and so would be | |
919 | * disabled if the serial console is disabled to switch to another | |
920 | * console. Mark all these clocks as critical so that they are never | |
921 | * disabled by the core clock management. | |
922 | */ | |
923 | k210_register_aclk_child(np, ksc, K210_CLK_CPU, CLK_IS_CRITICAL); | |
924 | k210_register_aclk_child(np, ksc, K210_CLK_SRAM0, CLK_IS_CRITICAL); | |
925 | k210_register_aclk_child(np, ksc, K210_CLK_SRAM1, CLK_IS_CRITICAL); | |
926 | k210_register_pll_child(np, ksc, K210_CLK_AI, K210_PLL1, | |
927 | CLK_IS_CRITICAL); | |
928 | ||
929 | /* Clocks with aclk as source */ | |
930 | k210_register_aclk_child(np, ksc, K210_CLK_DMA, 0); | |
931 | k210_register_aclk_child(np, ksc, K210_CLK_FFT, 0); | |
932 | k210_register_aclk_child(np, ksc, K210_CLK_ROM, 0); | |
933 | k210_register_aclk_child(np, ksc, K210_CLK_DVP, 0); | |
934 | k210_register_aclk_child(np, ksc, K210_CLK_APB0, 0); | |
935 | k210_register_aclk_child(np, ksc, K210_CLK_APB1, 0); | |
936 | k210_register_aclk_child(np, ksc, K210_CLK_APB2, 0); | |
937 | ||
938 | /* Clocks with PLL0 as source */ | |
939 | k210_register_pll_child(np, ksc, K210_CLK_SPI0, K210_PLL0, 0); | |
940 | k210_register_pll_child(np, ksc, K210_CLK_SPI1, K210_PLL0, 0); | |
941 | k210_register_pll_child(np, ksc, K210_CLK_SPI2, K210_PLL0, 0); | |
942 | k210_register_pll_child(np, ksc, K210_CLK_I2C0, K210_PLL0, 0); | |
943 | k210_register_pll_child(np, ksc, K210_CLK_I2C1, K210_PLL0, 0); | |
944 | k210_register_pll_child(np, ksc, K210_CLK_I2C2, K210_PLL0, 0); | |
945 | ||
946 | /* Clocks with PLL2 as source */ | |
947 | k210_register_pll_child(np, ksc, K210_CLK_I2S0, K210_PLL2, 0); | |
948 | k210_register_pll_child(np, ksc, K210_CLK_I2S1, K210_PLL2, 0); | |
949 | k210_register_pll_child(np, ksc, K210_CLK_I2S2, K210_PLL2, 0); | |
950 | k210_register_pll_child(np, ksc, K210_CLK_I2S0_M, K210_PLL2, 0); | |
951 | k210_register_pll_child(np, ksc, K210_CLK_I2S1_M, K210_PLL2, 0); | |
952 | k210_register_pll_child(np, ksc, K210_CLK_I2S2_M, K210_PLL2, 0); | |
953 | ||
954 | /* Clocks with IN0 as source */ | |
955 | k210_register_in0_child(np, ksc, K210_CLK_WDT0); | |
956 | k210_register_in0_child(np, ksc, K210_CLK_WDT1); | |
957 | k210_register_in0_child(np, ksc, K210_CLK_RTC); | |
958 | ||
959 | /* Clocks with APB0 as source */ | |
960 | k210_register_clk_child(np, ksc, K210_CLK_GPIO, K210_CLK_APB0); | |
961 | k210_register_clk_child(np, ksc, K210_CLK_UART1, K210_CLK_APB0); | |
962 | k210_register_clk_child(np, ksc, K210_CLK_UART2, K210_CLK_APB0); | |
963 | k210_register_clk_child(np, ksc, K210_CLK_UART3, K210_CLK_APB0); | |
964 | k210_register_clk_child(np, ksc, K210_CLK_FPIOA, K210_CLK_APB0); | |
965 | k210_register_clk_child(np, ksc, K210_CLK_SHA, K210_CLK_APB0); | |
966 | ||
967 | /* Clocks with APB1 as source */ | |
968 | k210_register_clk_child(np, ksc, K210_CLK_AES, K210_CLK_APB1); | |
969 | k210_register_clk_child(np, ksc, K210_CLK_OTP, K210_CLK_APB1); | |
970 | ||
971 | /* Mux clocks with in0 or pll0 as source */ | |
972 | k210_register_mux_clk(np, ksc, K210_CLK_SPI3); | |
973 | k210_register_mux_clk(np, ksc, K210_CLK_TIMER0); | |
974 | k210_register_mux_clk(np, ksc, K210_CLK_TIMER1); | |
975 | k210_register_mux_clk(np, ksc, K210_CLK_TIMER2); | |
976 | ||
977 | /* Check for registration errors */ | |
978 | for (i = 0; i < K210_NUM_CLKS; i++) { | |
979 | if (ksc->clks[i].id != i) | |
980 | return; | |
981 | } | |
982 | ||
983 | ret = of_clk_add_hw_provider(np, k210_clk_hw_onecell_get, ksc); | |
984 | if (ret) { | |
985 | pr_err("%pOFP: add clock provider failed %d\n", np, ret); | |
986 | return; | |
987 | } | |
988 | ||
989 | pr_info("%pOFP: CPU running at %lu MHz\n", | |
990 | np, clk_hw_get_rate(&ksc->clks[K210_CLK_CPU].hw) / 1000000); | |
991 | } | |
992 | ||
993 | CLK_OF_DECLARE(k210_clk, "canaan,k210-clk", k210_clk_init); | |
994 | ||
995 | /* | |
996 | * Enable PLL1 to be able to use the AI SRAM. | |
997 | */ | |
998 | void __init k210_clk_early_init(void __iomem *regs) | |
999 | { | |
1000 | struct k210_pll pll1; | |
1001 | ||
1002 | /* Make sure ACLK selector is set to PLL0 */ | |
1003 | k210_aclk_set_selector(regs, 1); | |
1004 | ||
1005 | /* Startup PLL1 to enable the aisram bank for general memory use */ | |
1006 | k210_init_pll(regs, K210_PLL1, &pll1); | |
1007 | k210_pll_enable_hw(regs, &pll1); | |
1008 | } |