blob: 69691c4a04ccd914083f1a039368de4709fb6f88 [file] [log] [blame]
Sean Andersonf9c7d4f2020-06-24 06:41:11 -04001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright (C) 2019-20 Sean Anderson <seanga2@gmail.com>
4 */
Sean Andersonaf9f9972021-06-11 00:16:09 -04005#define LOG_CATEGORY UCLASS_CLK
Sean Andersonf9c7d4f2020-06-24 06:41:11 -04006
Sean Anderson609bd602021-06-11 00:16:08 -04007#include <common.h>
Sean Andersonaf9f9972021-06-11 00:16:09 -04008#include <clk.h>
9#include <clk-uclass.h>
10#include <div64.h>
Sean Andersonf9c7d4f2020-06-24 06:41:11 -040011#include <dm.h>
12#include <log.h>
13#include <mapmem.h>
Sean Andersonaf9f9972021-06-11 00:16:09 -040014#include <serial.h>
15#include <dt-bindings/clock/k210-sysctl.h>
16#include <dt-bindings/mfd/k210-sysctl.h>
Sean Andersonf9c7d4f2020-06-24 06:41:11 -040017#include <kendryte/pll.h>
Sean Andersonaf9f9972021-06-11 00:16:09 -040018#include <linux/bitfield.h>
19
Sean Anderson29e30672021-06-11 00:16:11 -040020DECLARE_GLOBAL_DATA_PTR;
21
Sean Andersonaf9f9972021-06-11 00:16:09 -040022/**
23 * struct k210_clk_priv - K210 clock driver private data
24 * @base: The base address of the sysctl device
25 * @in0: The "in0" external oscillator
26 */
27struct k210_clk_priv {
28 void __iomem *base;
29 struct clk in0;
30};
Sean Andersonf9c7d4f2020-06-24 06:41:11 -040031
Sean Andersonf9c7d4f2020-06-24 06:41:11 -040032/*
33 * All parameters for different sub-clocks are collected into parameter arrays.
34 * These parameters are then initialized by the clock which uses them during
35 * probe. To save space, ids are automatically generated for each sub-clock by
36 * using an enum. Instead of storing a parameter struct for each clock, even for
37 * those clocks which don't use a particular type of sub-clock, we can just
38 * store the parameters for the clocks which need them.
39 *
40 * So why do it like this? Arranging all the sub-clocks together makes it very
41 * easy to find bugs in the code.
42 */
43
Sean Anderson609bd602021-06-11 00:16:08 -040044/**
45 * enum k210_clk_div_type - The type of divider
46 * @K210_DIV_ONE: freq = parent / (reg + 1)
47 * @K210_DIV_EVEN: freq = parent / 2 / (reg + 1)
48 * @K210_DIV_POWER: freq = parent / (2 << reg)
49 * @K210_DIV_FIXED: freq = parent / factor
50 */
51enum k210_clk_div_type {
52 K210_DIV_ONE,
53 K210_DIV_EVEN,
54 K210_DIV_POWER,
55 K210_DIV_FIXED,
56};
57
58/**
59 * struct k210_div_params - Parameters for dividing clocks
60 * @type: An &enum k210_clk_div_type specifying the dividing formula
61 * @off: The offset of the divider from the sysctl base address
62 * @shift: The offset of the LSB of the divider
63 * @width: The number of bits in the divider
64 * @div: The fixed divisor for this divider
65 */
66struct k210_div_params {
67 u8 type;
68 union {
69 struct {
70 u8 off;
71 u8 shift;
72 u8 width;
73 };
74 u8 div;
75 };
76};
77
Sean Andersonf9c7d4f2020-06-24 06:41:11 -040078#define DIV_LIST \
Sean Anderson609bd602021-06-11 00:16:08 -040079 DIV(K210_CLK_ACLK, K210_SYSCTL_SEL0, 1, 2, K210_DIV_POWER) \
80 DIV(K210_CLK_APB0, K210_SYSCTL_SEL0, 3, 3, K210_DIV_ONE) \
81 DIV(K210_CLK_APB1, K210_SYSCTL_SEL0, 6, 3, K210_DIV_ONE) \
82 DIV(K210_CLK_APB2, K210_SYSCTL_SEL0, 9, 3, K210_DIV_ONE) \
83 DIV(K210_CLK_SRAM0, K210_SYSCTL_THR0, 0, 4, K210_DIV_ONE) \
84 DIV(K210_CLK_SRAM1, K210_SYSCTL_THR0, 4, 4, K210_DIV_ONE) \
85 DIV(K210_CLK_AI, K210_SYSCTL_THR0, 8, 4, K210_DIV_ONE) \
86 DIV(K210_CLK_DVP, K210_SYSCTL_THR0, 12, 4, K210_DIV_ONE) \
87 DIV(K210_CLK_ROM, K210_SYSCTL_THR0, 16, 4, K210_DIV_ONE) \
88 DIV(K210_CLK_SPI0, K210_SYSCTL_THR1, 0, 8, K210_DIV_EVEN) \
89 DIV(K210_CLK_SPI1, K210_SYSCTL_THR1, 8, 8, K210_DIV_EVEN) \
90 DIV(K210_CLK_SPI2, K210_SYSCTL_THR1, 16, 8, K210_DIV_EVEN) \
91 DIV(K210_CLK_SPI3, K210_SYSCTL_THR1, 24, 8, K210_DIV_EVEN) \
92 DIV(K210_CLK_TIMER0, K210_SYSCTL_THR2, 0, 8, K210_DIV_EVEN) \
93 DIV(K210_CLK_TIMER1, K210_SYSCTL_THR2, 8, 8, K210_DIV_EVEN) \
94 DIV(K210_CLK_TIMER2, K210_SYSCTL_THR2, 16, 8, K210_DIV_EVEN) \
95 DIV(K210_CLK_I2S0, K210_SYSCTL_THR3, 0, 16, K210_DIV_EVEN) \
96 DIV(K210_CLK_I2S1, K210_SYSCTL_THR3, 16, 16, K210_DIV_EVEN) \
97 DIV(K210_CLK_I2S2, K210_SYSCTL_THR4, 0, 16, K210_DIV_EVEN) \
98 DIV(K210_CLK_I2S0_M, K210_SYSCTL_THR4, 16, 8, K210_DIV_EVEN) \
99 DIV(K210_CLK_I2S1_M, K210_SYSCTL_THR4, 24, 8, K210_DIV_EVEN) \
100 DIV(K210_CLK_I2S2_M, K210_SYSCTL_THR4, 0, 8, K210_DIV_EVEN) \
101 DIV(K210_CLK_I2C0, K210_SYSCTL_THR5, 8, 8, K210_DIV_EVEN) \
102 DIV(K210_CLK_I2C1, K210_SYSCTL_THR5, 16, 8, K210_DIV_EVEN) \
103 DIV(K210_CLK_I2C2, K210_SYSCTL_THR5, 24, 8, K210_DIV_EVEN) \
104 DIV(K210_CLK_WDT0, K210_SYSCTL_THR6, 0, 8, K210_DIV_EVEN) \
105 DIV(K210_CLK_WDT1, K210_SYSCTL_THR6, 8, 8, K210_DIV_EVEN) \
106 DIV_FIXED(K210_CLK_CLINT, 50) \
Sean Andersonf9c7d4f2020-06-24 06:41:11 -0400107
108#define _DIVIFY(id) K210_CLK_DIV_##id
109#define DIVIFY(id) _DIVIFY(id)
110
Sean Anderson609bd602021-06-11 00:16:08 -0400111enum k210_div_id {
112#define DIV(id, ...) DIVIFY(id),
113#define DIV_FIXED DIV
Sean Andersonf9c7d4f2020-06-24 06:41:11 -0400114 DIV_LIST
Sean Anderson609bd602021-06-11 00:16:08 -0400115#undef DIV
116#undef DIV_FIXED
117 K210_CLK_DIV_NONE,
Sean Andersonf9c7d4f2020-06-24 06:41:11 -0400118};
119
120static const struct k210_div_params k210_divs[] = {
Sean Anderson609bd602021-06-11 00:16:08 -0400121#define DIV(id, _off, _shift, _width, _type) \
Sean Andersonf9c7d4f2020-06-24 06:41:11 -0400122 [DIVIFY(id)] = { \
Sean Anderson609bd602021-06-11 00:16:08 -0400123 .type = (_type), \
Sean Andersonf9c7d4f2020-06-24 06:41:11 -0400124 .off = (_off), \
125 .shift = (_shift), \
126 .width = (_width), \
Sean Anderson609bd602021-06-11 00:16:08 -0400127 },
128#define DIV_FIXED(id, _div) \
129 [DIVIFY(id)] = { \
130 .type = K210_DIV_FIXED, \
131 .div = (_div) \
Sean Andersonf9c7d4f2020-06-24 06:41:11 -0400132 },
133 DIV_LIST
Sean Anderson609bd602021-06-11 00:16:08 -0400134#undef DIV
135#undef DIV_FIXED
Sean Andersonf9c7d4f2020-06-24 06:41:11 -0400136};
137
138#undef DIV
139#undef DIV_LIST
140
Sean Anderson609bd602021-06-11 00:16:08 -0400141/**
142 * struct k210_gate_params - Parameters for gated clocks
143 * @off: The offset of the gate from the sysctl base address
144 * @bit_idx: The index of the bit within the register
145 */
146struct k210_gate_params {
147 u8 off;
148 u8 bit_idx;
149};
150
Sean Andersonf9c7d4f2020-06-24 06:41:11 -0400151#define GATE_LIST \
152 GATE(K210_CLK_CPU, K210_SYSCTL_EN_CENT, 0) \
153 GATE(K210_CLK_SRAM0, K210_SYSCTL_EN_CENT, 1) \
154 GATE(K210_CLK_SRAM1, K210_SYSCTL_EN_CENT, 2) \
155 GATE(K210_CLK_APB0, K210_SYSCTL_EN_CENT, 3) \
156 GATE(K210_CLK_APB1, K210_SYSCTL_EN_CENT, 4) \
157 GATE(K210_CLK_APB2, K210_SYSCTL_EN_CENT, 5) \
158 GATE(K210_CLK_ROM, K210_SYSCTL_EN_PERI, 0) \
159 GATE(K210_CLK_DMA, K210_SYSCTL_EN_PERI, 1) \
160 GATE(K210_CLK_AI, K210_SYSCTL_EN_PERI, 2) \
161 GATE(K210_CLK_DVP, K210_SYSCTL_EN_PERI, 3) \
162 GATE(K210_CLK_FFT, K210_SYSCTL_EN_PERI, 4) \
163 GATE(K210_CLK_GPIO, K210_SYSCTL_EN_PERI, 5) \
164 GATE(K210_CLK_SPI0, K210_SYSCTL_EN_PERI, 6) \
165 GATE(K210_CLK_SPI1, K210_SYSCTL_EN_PERI, 7) \
166 GATE(K210_CLK_SPI2, K210_SYSCTL_EN_PERI, 8) \
167 GATE(K210_CLK_SPI3, K210_SYSCTL_EN_PERI, 9) \
168 GATE(K210_CLK_I2S0, K210_SYSCTL_EN_PERI, 10) \
169 GATE(K210_CLK_I2S1, K210_SYSCTL_EN_PERI, 11) \
170 GATE(K210_CLK_I2S2, K210_SYSCTL_EN_PERI, 12) \
171 GATE(K210_CLK_I2C0, K210_SYSCTL_EN_PERI, 13) \
172 GATE(K210_CLK_I2C1, K210_SYSCTL_EN_PERI, 14) \
173 GATE(K210_CLK_I2C2, K210_SYSCTL_EN_PERI, 15) \
174 GATE(K210_CLK_UART1, K210_SYSCTL_EN_PERI, 16) \
175 GATE(K210_CLK_UART2, K210_SYSCTL_EN_PERI, 17) \
176 GATE(K210_CLK_UART3, K210_SYSCTL_EN_PERI, 18) \
177 GATE(K210_CLK_AES, K210_SYSCTL_EN_PERI, 19) \
178 GATE(K210_CLK_FPIOA, K210_SYSCTL_EN_PERI, 20) \
179 GATE(K210_CLK_TIMER0, K210_SYSCTL_EN_PERI, 21) \
180 GATE(K210_CLK_TIMER1, K210_SYSCTL_EN_PERI, 22) \
181 GATE(K210_CLK_TIMER2, K210_SYSCTL_EN_PERI, 23) \
182 GATE(K210_CLK_WDT0, K210_SYSCTL_EN_PERI, 24) \
183 GATE(K210_CLK_WDT1, K210_SYSCTL_EN_PERI, 25) \
184 GATE(K210_CLK_SHA, K210_SYSCTL_EN_PERI, 26) \
185 GATE(K210_CLK_OTP, K210_SYSCTL_EN_PERI, 27) \
186 GATE(K210_CLK_RTC, K210_SYSCTL_EN_PERI, 29)
187
188#define _GATEIFY(id) K210_CLK_GATE_##id
189#define GATEIFY(id) _GATEIFY(id)
190
Sean Anderson609bd602021-06-11 00:16:08 -0400191enum k210_gate_id {
Sean Andersonf9c7d4f2020-06-24 06:41:11 -0400192#define GATE(id, ...) GATEIFY(id),
193 GATE_LIST
194#undef GATE
Sean Anderson609bd602021-06-11 00:16:08 -0400195 K210_CLK_GATE_NONE,
Sean Andersonf9c7d4f2020-06-24 06:41:11 -0400196};
197
198static const struct k210_gate_params k210_gates[] = {
199#define GATE(id, _off, _idx) \
200 [GATEIFY(id)] = { \
201 .off = (_off), \
202 .bit_idx = (_idx), \
203 },
204 GATE_LIST
205#undef GATE
206};
207
208#undef GATE_LIST
209
Sean Anderson609bd602021-06-11 00:16:08 -0400210/* The most parents is PLL2 */
211#define K210_CLK_MAX_PARENTS 3
212
213/**
214 * struct k210_mux_params - Parameters for muxed clocks
215 * @parents: A list of parent clock ids
216 * @num_parents: The number of parent clocks
217 * @off: The offset of the mux from the base sysctl address
218 * @shift: The offset of the LSB of the mux selector
219 * @width: The number of bits in the mux selector
220 */
221struct k210_mux_params {
222 u8 parents[K210_CLK_MAX_PARENTS];
223 u8 num_parents;
224 u8 off;
225 u8 shift;
226 u8 width;
227};
228
Sean Andersonf9c7d4f2020-06-24 06:41:11 -0400229#define MUX(id, reg, shift, width) \
Sean Anderson609bd602021-06-11 00:16:08 -0400230 MUX_PARENTS(id, reg, shift, width, K210_CLK_IN0, K210_CLK_PLL0)
Sean Andersonf9c7d4f2020-06-24 06:41:11 -0400231#define MUX_LIST \
Sean Anderson609bd602021-06-11 00:16:08 -0400232 MUX_PARENTS(K210_CLK_PLL2, K210_SYSCTL_PLL2, 26, 2, \
233 K210_CLK_IN0, K210_CLK_PLL0, K210_CLK_PLL1) \
234 MUX(K210_CLK_ACLK, K210_SYSCTL_SEL0, 0, 1) \
Sean Andersonf9c7d4f2020-06-24 06:41:11 -0400235 MUX(K210_CLK_SPI3, K210_SYSCTL_SEL0, 12, 1) \
236 MUX(K210_CLK_TIMER0, K210_SYSCTL_SEL0, 13, 1) \
237 MUX(K210_CLK_TIMER1, K210_SYSCTL_SEL0, 14, 1) \
238 MUX(K210_CLK_TIMER2, K210_SYSCTL_SEL0, 15, 1)
239
240#define _MUXIFY(id) K210_CLK_MUX_##id
241#define MUXIFY(id) _MUXIFY(id)
242
Sean Anderson609bd602021-06-11 00:16:08 -0400243enum k210_mux_id {
Sean Andersonf9c7d4f2020-06-24 06:41:11 -0400244#define MUX_PARENTS(id, ...) MUXIFY(id),
245 MUX_LIST
246#undef MUX_PARENTS
247 K210_CLK_MUX_NONE,
248};
249
Sean Andersonf9c7d4f2020-06-24 06:41:11 -0400250static const struct k210_mux_params k210_muxes[] = {
Sean Anderson609bd602021-06-11 00:16:08 -0400251#define MUX_PARENTS(id, _off, _shift, _width, ...) \
Sean Andersonf9c7d4f2020-06-24 06:41:11 -0400252 [MUXIFY(id)] = { \
Sean Anderson609bd602021-06-11 00:16:08 -0400253 .parents = { __VA_ARGS__ }, \
254 .num_parents = __count_args(__VA_ARGS__), \
Sean Andersonf9c7d4f2020-06-24 06:41:11 -0400255 .off = (_off), \
256 .shift = (_shift), \
257 .width = (_width), \
258 },
259 MUX_LIST
260#undef MUX_PARENTS
261};
262
263#undef MUX
264#undef MUX_LIST
265
Sean Anderson609bd602021-06-11 00:16:08 -0400266/**
Sean Andersonaf9f9972021-06-11 00:16:09 -0400267 * struct k210_pll_params - K210 PLL parameters
268 * @off: The offset of the PLL from the base sysctl address
269 * @shift: The offset of the LSB of the lock status
270 * @width: The number of bits in the lock status
271 */
272struct k210_pll_params {
273 u8 off;
274 u8 shift;
275 u8 width;
276};
277
278static const struct k210_pll_params k210_plls[] = {
279#define PLL(_off, _shift, _width) { \
280 .off = (_off), \
281 .shift = (_shift), \
282 .width = (_width), \
283}
284 [0] = PLL(K210_SYSCTL_PLL0, 0, 2),
285 [1] = PLL(K210_SYSCTL_PLL1, 8, 1),
286 [2] = PLL(K210_SYSCTL_PLL2, 16, 1),
287#undef PLL
288};
289
290/**
Sean Anderson609bd602021-06-11 00:16:08 -0400291 * enum k210_clk_flags - The type of a K210 clock
292 * @K210_CLKF_MUX: This clock has a mux and not a static parent
293 * @K210_CLKF_PLL: This clock is a PLL
294 */
295enum k210_clk_flags {
296 K210_CLKF_MUX = BIT(0),
297 K210_CLKF_PLL = BIT(1),
Sean Andersonf9c7d4f2020-06-24 06:41:11 -0400298};
299
Sean Anderson609bd602021-06-11 00:16:08 -0400300/**
301 * struct k210_clk_params - The parameters defining a K210 clock
302 * @name: The name of the clock
303 * @flags: A set of &enum k210_clk_flags defining which fields are valid
304 * @mux: An &enum k210_mux_id of this clock's mux
305 * @parent: The clock id of this clock's parent
306 * @pll: The id of the PLL (if this clock is a PLL)
307 * @div: An &enum k210_div_id of this clock's divider
308 * @gate: An &enum k210_gate_id of this clock's gate
309 */
310struct k210_clk_params {
311#if CONFIG_IS_ENABLED(CMD_CLK)
312 const char *name;
313#endif
314 u8 flags;
315 union {
316 u8 parent;
317 u8 mux;
318 };
319 union {
320 u8 pll;
321 struct {
322 u8 div;
323 u8 gate;
324 };
325 };
Sean Andersonf9c7d4f2020-06-24 06:41:11 -0400326};
327
Sean Anderson609bd602021-06-11 00:16:08 -0400328static const struct k210_clk_params k210_clks[] = {
329#if CONFIG_IS_ENABLED(CMD_CLK)
330#define NAME(_name) .name = (_name),
331#else
332#define NAME(name)
333#endif
334#define CLK(id, _name, _parent, _div, _gate) \
335 [id] = { \
336 NAME(_name) \
337 .parent = (_parent), \
338 .div = (_div), \
339 .gate = (_gate), \
340 }
341#define CLK_MUX(id, _name, _mux, _div, _gate) \
342 [id] = { \
343 NAME(_name) \
344 .flags = K210_CLKF_MUX, \
Sean Andersonf9c7d4f2020-06-24 06:41:11 -0400345 .mux = (_mux), \
346 .div = (_div), \
347 .gate = (_gate), \
Sean Anderson609bd602021-06-11 00:16:08 -0400348 }
349#define CLK_PLL(id, _pll, _parent) \
350 [id] = { \
351 NAME("pll" #_pll) \
352 .flags = K210_CLKF_PLL, \
353 .parent = (_parent), \
354 .pll = (_pll), \
355 }
356#define CLK_FULL(id, name) \
357 CLK_MUX(id, name, MUXIFY(id), DIVIFY(id), GATEIFY(id))
358#define CLK_NOMUX(id, name, parent) \
359 CLK(id, name, parent, DIVIFY(id), GATEIFY(id))
360#define CLK_DIV(id, name, parent) \
361 CLK(id, name, parent, DIVIFY(id), K210_CLK_GATE_NONE)
362#define CLK_GATE(id, name, parent) \
363 CLK(id, name, parent, K210_CLK_DIV_NONE, GATEIFY(id))
364 CLK_PLL(K210_CLK_PLL0, 0, K210_CLK_IN0),
365 CLK_PLL(K210_CLK_PLL1, 1, K210_CLK_IN0),
366 [K210_CLK_PLL2] = {
367 NAME("pll2")
368 .flags = K210_CLKF_MUX | K210_CLKF_PLL,
369 .mux = MUXIFY(K210_CLK_PLL2),
370 .pll = 2,
Sean Andersonf9c7d4f2020-06-24 06:41:11 -0400371 },
Sean Anderson609bd602021-06-11 00:16:08 -0400372 CLK_MUX(K210_CLK_ACLK, "aclk", MUXIFY(K210_CLK_ACLK),
373 DIVIFY(K210_CLK_ACLK), K210_CLK_GATE_NONE),
374 CLK_FULL(K210_CLK_SPI3, "spi3"),
375 CLK_FULL(K210_CLK_TIMER0, "timer0"),
376 CLK_FULL(K210_CLK_TIMER1, "timer1"),
377 CLK_FULL(K210_CLK_TIMER2, "timer2"),
378 CLK_NOMUX(K210_CLK_SRAM0, "sram0", K210_CLK_ACLK),
379 CLK_NOMUX(K210_CLK_SRAM1, "sram1", K210_CLK_ACLK),
380 CLK_NOMUX(K210_CLK_ROM, "rom", K210_CLK_ACLK),
381 CLK_NOMUX(K210_CLK_DVP, "dvp", K210_CLK_ACLK),
382 CLK_NOMUX(K210_CLK_APB0, "apb0", K210_CLK_ACLK),
383 CLK_NOMUX(K210_CLK_APB1, "apb1", K210_CLK_ACLK),
384 CLK_NOMUX(K210_CLK_APB2, "apb2", K210_CLK_ACLK),
385 CLK_NOMUX(K210_CLK_AI, "ai", K210_CLK_PLL1),
386 CLK_NOMUX(K210_CLK_I2S0, "i2s0", K210_CLK_PLL2),
387 CLK_NOMUX(K210_CLK_I2S1, "i2s1", K210_CLK_PLL2),
388 CLK_NOMUX(K210_CLK_I2S2, "i2s2", K210_CLK_PLL2),
389 CLK_NOMUX(K210_CLK_WDT0, "wdt0", K210_CLK_IN0),
390 CLK_NOMUX(K210_CLK_WDT1, "wdt1", K210_CLK_IN0),
391 CLK_NOMUX(K210_CLK_SPI0, "spi0", K210_CLK_PLL0),
392 CLK_NOMUX(K210_CLK_SPI1, "spi1", K210_CLK_PLL0),
393 CLK_NOMUX(K210_CLK_SPI2, "spi2", K210_CLK_PLL0),
394 CLK_NOMUX(K210_CLK_I2C0, "i2c0", K210_CLK_PLL0),
395 CLK_NOMUX(K210_CLK_I2C1, "i2c1", K210_CLK_PLL0),
396 CLK_NOMUX(K210_CLK_I2C2, "i2c2", K210_CLK_PLL0),
397 CLK_DIV(K210_CLK_I2S0_M, "i2s0_m", K210_CLK_PLL2),
398 CLK_DIV(K210_CLK_I2S1_M, "i2s1_m", K210_CLK_PLL2),
399 CLK_DIV(K210_CLK_I2S2_M, "i2s2_m", K210_CLK_PLL2),
400 CLK_DIV(K210_CLK_CLINT, "clint", K210_CLK_ACLK),
401 CLK_GATE(K210_CLK_CPU, "cpu", K210_CLK_ACLK),
402 CLK_GATE(K210_CLK_DMA, "dma", K210_CLK_ACLK),
403 CLK_GATE(K210_CLK_FFT, "fft", K210_CLK_ACLK),
404 CLK_GATE(K210_CLK_GPIO, "gpio", K210_CLK_APB0),
405 CLK_GATE(K210_CLK_UART1, "uart1", K210_CLK_APB0),
406 CLK_GATE(K210_CLK_UART2, "uart2", K210_CLK_APB0),
407 CLK_GATE(K210_CLK_UART3, "uart3", K210_CLK_APB0),
408 CLK_GATE(K210_CLK_FPIOA, "fpioa", K210_CLK_APB0),
409 CLK_GATE(K210_CLK_SHA, "sha", K210_CLK_APB0),
410 CLK_GATE(K210_CLK_AES, "aes", K210_CLK_APB1),
411 CLK_GATE(K210_CLK_OTP, "otp", K210_CLK_APB1),
412 CLK_GATE(K210_CLK_RTC, "rtc", K210_CLK_IN0),
413#undef NAME
414#undef CLK_PLL
415#undef CLK
416#undef CLK_FULL
417#undef CLK_NOMUX
418#undef CLK_DIV
419#undef CLK_GATE
420#undef CLK_LIST
Sean Andersonf9c7d4f2020-06-24 06:41:11 -0400421};
422
Sean Andersonaf9f9972021-06-11 00:16:09 -0400423#define K210_PLL_CLKR GENMASK(3, 0)
424#define K210_PLL_CLKF GENMASK(9, 4)
425#define K210_PLL_CLKOD GENMASK(13, 10) /* Output Divider */
426#define K210_PLL_BWADJ GENMASK(19, 14) /* BandWidth Adjust */
427#define K210_PLL_RESET BIT(20)
428#define K210_PLL_PWRD BIT(21) /* PoWeReD */
429#define K210_PLL_INTFB BIT(22) /* Internal FeedBack */
430#define K210_PLL_BYPASS BIT(23)
431#define K210_PLL_TEST BIT(24)
432#define K210_PLL_EN BIT(25)
433#define K210_PLL_TEST_EN BIT(26)
434
435#define K210_PLL_LOCK 0
436#define K210_PLL_CLEAR_SLIP 2
437#define K210_PLL_TEST_OUT 3
438
439#ifdef CONFIG_CLK_K210_SET_RATE
440static int k210_pll_enable(struct k210_clk_priv *priv, int id);
441static int k210_pll_disable(struct k210_clk_priv *priv, int id);
442static ulong k210_pll_get_rate(struct k210_clk_priv *priv, int id, ulong rate_in);
443
444/*
445 * The PLL included with the Kendryte K210 appears to be a True Circuits, Inc.
446 * General-Purpose PLL. The logical layout of the PLL with internal feedback is
447 * approximately the following:
448 *
449 * +---------------+
450 * |reference clock|
451 * +---------------+
452 * |
453 * v
454 * +--+
455 * |/r|
456 * +--+
457 * |
458 * v
459 * +-------------+
460 * |divided clock|
461 * +-------------+
462 * |
463 * v
464 * +--------------+
465 * |phase detector|<---+
466 * +--------------+ |
467 * | |
468 * v +--------------+
469 * +---+ |feedback clock|
470 * |VCO| +--------------+
471 * +---+ ^
472 * | +--+ |
473 * +--->|/f|---+
474 * | +--+
475 * v
476 * +---+
477 * |/od|
478 * +---+
479 * |
480 * v
481 * +------+
482 * |output|
483 * +------+
484 *
485 * The k210 PLLs have three factors: r, f, and od. Because of the feedback mode,
486 * the effect of the division by f is to multiply the input frequency. The
487 * equation for the output rate is
488 * rate = (rate_in * f) / (r * od).
489 * Moving knowns to one side of the equation, we get
490 * rate / rate_in = f / (r * od)
491 * Rearranging slightly,
492 * abs_error = abs((rate / rate_in) - (f / (r * od))).
493 * To get relative, error, we divide by the expected ratio
494 * error = abs((rate / rate_in) - (f / (r * od))) / (rate / rate_in).
495 * Simplifying,
496 * error = abs(1 - f / (r * od)) / (rate / rate_in)
497 * error = abs(1 - (f * rate_in) / (r * od * rate))
498 * Using the constants ratio = rate / rate_in and inv_ratio = rate_in / rate,
499 * error = abs((f * inv_ratio) / (r * od) - 1)
500 * This is the error used in evaluating parameters.
501 *
502 * r and od are four bits each, while f is six bits. Because r and od are
503 * multiplied together, instead of the full 256 values possible if both bits
504 * were used fully, there are only 97 distinct products. Combined with f, there
505 * are 6208 theoretical settings for the PLL. However, most of these settings
506 * can be ruled out immediately because they do not have the correct ratio.
507 *
508 * In addition to the constraint of approximating the desired ratio, parameters
509 * must also keep internal pll frequencies within acceptable ranges. The divided
510 * clock's minimum and maximum frequencies have a ratio of around 128. This
511 * leaves fairly substantial room to work with, especially since the only
512 * affected parameter is r. The VCO's minimum and maximum frequency have a ratio
513 * of 5, which is considerably more restrictive.
514 *
515 * The r and od factors are stored in a table. This is to make it easy to find
516 * the next-largest product. Some products have multiple factorizations, but
517 * only when one factor has at least a 2.5x ratio to the factors of the other
518 * factorization. This is because any smaller ratio would not make a difference
519 * when ensuring the VCO's frequency is within spec.
520 *
521 * Throughout the calculation function, fixed point arithmetic is used. Because
522 * the range of rate and rate_in may be up to 1.75 GHz, or around 2^30, 64-bit
523 * 32.32 fixed-point numbers are used to represent ratios. In general, to
524 * implement division, the numerator is first multiplied by 2^32. This gives a
525 * result where the whole number part is in the upper 32 bits, and the fraction
526 * is in the lower 32 bits.
527 *
528 * In general, rounding is done to the closest integer. This helps find the best
529 * approximation for the ratio. Rounding in one direction (e.g down) could cause
530 * the function to miss a better ratio with one of the parameters increased by
531 * one.
532 */
533
534/*
535 * The factors table was generated with the following python code:
536 *
537 * def p(x, y):
538 * return (1.0*x/y > 2.5) or (1.0*y/x > 2.5)
539 *
540 * factors = {}
541 * for i in range(1, 17):
542 * for j in range(1, 17):
543 * fs = factors.get(i*j) or []
544 * if fs == [] or all([
545 * (p(i, x) and p(i, y)) or (p(j, x) and p(j, y))
546 * for (x, y) in fs]):
547 * fs.append((i, j))
548 * factors[i*j] = fs
549 *
550 * for k, l in sorted(factors.items()):
551 * for v in l:
552 * print("PACK(%s, %s)," % v)
553 */
554#define PACK(r, od) (((((r) - 1) & 0xF) << 4) | (((od) - 1) & 0xF))
555#define UNPACK_R(val) ((((val) >> 4) & 0xF) + 1)
556#define UNPACK_OD(val) (((val) & 0xF) + 1)
557static const u8 factors[] = {
558 PACK(1, 1),
559 PACK(1, 2),
560 PACK(1, 3),
561 PACK(1, 4),
562 PACK(1, 5),
563 PACK(1, 6),
564 PACK(1, 7),
565 PACK(1, 8),
566 PACK(1, 9),
567 PACK(3, 3),
568 PACK(1, 10),
569 PACK(1, 11),
570 PACK(1, 12),
571 PACK(3, 4),
572 PACK(1, 13),
573 PACK(1, 14),
574 PACK(1, 15),
575 PACK(3, 5),
576 PACK(1, 16),
577 PACK(4, 4),
578 PACK(2, 9),
579 PACK(2, 10),
580 PACK(3, 7),
581 PACK(2, 11),
582 PACK(2, 12),
583 PACK(5, 5),
584 PACK(2, 13),
585 PACK(3, 9),
586 PACK(2, 14),
587 PACK(2, 15),
588 PACK(2, 16),
589 PACK(3, 11),
590 PACK(5, 7),
591 PACK(3, 12),
592 PACK(3, 13),
593 PACK(4, 10),
594 PACK(3, 14),
595 PACK(4, 11),
596 PACK(3, 15),
597 PACK(3, 16),
598 PACK(7, 7),
599 PACK(5, 10),
600 PACK(4, 13),
601 PACK(6, 9),
602 PACK(5, 11),
603 PACK(4, 14),
604 PACK(4, 15),
605 PACK(7, 9),
606 PACK(4, 16),
607 PACK(5, 13),
608 PACK(6, 11),
609 PACK(5, 14),
610 PACK(6, 12),
611 PACK(5, 15),
612 PACK(7, 11),
613 PACK(6, 13),
614 PACK(5, 16),
615 PACK(9, 9),
616 PACK(6, 14),
617 PACK(8, 11),
618 PACK(6, 15),
619 PACK(7, 13),
620 PACK(6, 16),
621 PACK(7, 14),
622 PACK(9, 11),
623 PACK(10, 10),
624 PACK(8, 13),
625 PACK(7, 15),
626 PACK(9, 12),
627 PACK(10, 11),
628 PACK(7, 16),
629 PACK(9, 13),
630 PACK(8, 15),
631 PACK(11, 11),
632 PACK(9, 14),
633 PACK(8, 16),
634 PACK(10, 13),
635 PACK(11, 12),
636 PACK(9, 15),
637 PACK(10, 14),
638 PACK(11, 13),
639 PACK(9, 16),
640 PACK(10, 15),
641 PACK(11, 14),
642 PACK(12, 13),
643 PACK(10, 16),
644 PACK(11, 15),
645 PACK(12, 14),
646 PACK(13, 13),
647 PACK(11, 16),
648 PACK(12, 15),
649 PACK(13, 14),
650 PACK(12, 16),
651 PACK(13, 15),
652 PACK(14, 14),
653 PACK(13, 16),
654 PACK(14, 15),
655 PACK(14, 16),
656 PACK(15, 15),
657 PACK(15, 16),
658 PACK(16, 16),
659};
660
661TEST_STATIC int k210_pll_calc_config(u32 rate, u32 rate_in,
662 struct k210_pll_config *best)
663{
664 int i;
665 s64 error, best_error;
666 u64 ratio, inv_ratio; /* fixed point 32.32 ratio of the rates */
667 u64 max_r;
668 u64 r, f, od;
669
670 /*
671 * Can't go over 1.75 GHz or under 21.25 MHz due to limitations on the
672 * VCO frequency. These are not the same limits as below because od can
673 * reduce the output frequency by 16.
674 */
675 if (rate > 1750000000 || rate < 21250000)
676 return -EINVAL;
677
678 /* Similar restrictions on the input rate */
679 if (rate_in > 1750000000 || rate_in < 13300000)
680 return -EINVAL;
681
682 ratio = DIV_ROUND_CLOSEST_ULL((u64)rate << 32, rate_in);
683 inv_ratio = DIV_ROUND_CLOSEST_ULL((u64)rate_in << 32, rate);
684 /* Can't increase by more than 64 or reduce by more than 256 */
685 if (rate > rate_in && ratio > (64ULL << 32))
686 return -EINVAL;
687 else if (rate <= rate_in && inv_ratio > (256ULL << 32))
688 return -EINVAL;
689
690 /*
691 * The divided clock (rate_in / r) must stay between 1.75 GHz and 13.3
692 * MHz. There is no minimum, since the only way to get a higher input
693 * clock than 26 MHz is to use a clock generated by a PLL. Because PLLs
694 * cannot output frequencies greater than 1.75 GHz, the minimum would
695 * never be greater than one.
696 */
697 max_r = DIV_ROUND_DOWN_ULL(rate_in, 13300000);
698
699 /* Variables get immediately incremented, so start at -1th iteration */
700 i = -1;
701 f = 0;
702 r = 0;
703 od = 0;
704 best_error = S64_MAX;
705 error = best_error;
706 /* do-while here so we always try at least one ratio */
707 do {
708 /*
709 * Whether we swapped r and od while enforcing frequency limits
710 */
711 bool swapped = false;
Sean Anderson49708742021-09-11 13:20:01 -0400712 /*
713 * Whether the intermediate frequencies are out-of-spec
714 */
715 bool out_of_spec;
Sean Andersonaf9f9972021-06-11 00:16:09 -0400716 u64 last_od = od;
717 u64 last_r = r;
718
719 /*
720 * Try the next largest value for f (or r and od) and
721 * recalculate the other parameters based on that
722 */
723 if (rate > rate_in) {
724 /*
725 * Skip factors of the same product if we already tried
726 * out that product
727 */
728 do {
729 i++;
730 r = UNPACK_R(factors[i]);
731 od = UNPACK_OD(factors[i]);
732 } while (i + 1 < ARRAY_SIZE(factors) &&
733 r * od == last_r * last_od);
734
735 /* Round close */
736 f = (r * od * ratio + BIT(31)) >> 32;
737 if (f > 64)
738 f = 64;
739 } else {
740 u64 tmp = ++f * inv_ratio;
741 bool round_up = !!(tmp & BIT(31));
742 u32 goal = (tmp >> 32) + round_up;
743 u32 err, last_err;
744
745 /* Get the next r/od pair in factors */
746 while (r * od < goal && i + 1 < ARRAY_SIZE(factors)) {
747 i++;
748 r = UNPACK_R(factors[i]);
749 od = UNPACK_OD(factors[i]);
750 }
751
752 /*
753 * This is a case of double rounding. If we rounded up
754 * above, we need to round down (in cases of ties) here.
755 * This prevents off-by-one errors resulting from
756 * choosing X+2 over X when X.Y rounds up to X+1 and
757 * there is no r * od = X+1. For the converse, when X.Y
758 * is rounded down to X, we should choose X+1 over X-1.
759 */
760 err = abs(r * od - goal);
761 last_err = abs(last_r * last_od - goal);
762 if (last_err < err || (round_up && last_err == err)) {
763 i--;
764 r = last_r;
765 od = last_od;
766 }
767 }
768
769 /*
770 * Enforce limits on internal clock frequencies. If we
771 * aren't in spec, try swapping r and od. If everything is
772 * in-spec, calculate the relative error.
773 */
Sean Anderson49708742021-09-11 13:20:01 -0400774again:
775 out_of_spec = false;
776 if (r > max_r) {
777 out_of_spec = true;
778 } else {
Sean Andersonaf9f9972021-06-11 00:16:09 -0400779 /*
Sean Anderson49708742021-09-11 13:20:01 -0400780 * There is no way to only divide once; we need
781 * to examine the frequency with and without the
782 * effect of od.
Sean Andersonaf9f9972021-06-11 00:16:09 -0400783 */
Sean Anderson49708742021-09-11 13:20:01 -0400784 u64 vco = DIV_ROUND_CLOSEST_ULL(rate_in * f, r);
Sean Andersonaf9f9972021-06-11 00:16:09 -0400785
Sean Anderson49708742021-09-11 13:20:01 -0400786 if (vco > 1750000000 || vco < 340000000)
Sean Andersonaf9f9972021-06-11 00:16:09 -0400787 out_of_spec = true;
Sean Anderson49708742021-09-11 13:20:01 -0400788 }
Sean Andersonaf9f9972021-06-11 00:16:09 -0400789
Sean Anderson49708742021-09-11 13:20:01 -0400790 if (out_of_spec) {
791 u64 new_r, new_od;
792
793 if (!swapped) {
794 u64 tmp = r;
795
796 r = od;
797 od = tmp;
798 swapped = true;
799 goto again;
Sean Andersonaf9f9972021-06-11 00:16:09 -0400800 }
801
Sean Anderson49708742021-09-11 13:20:01 -0400802 /*
803 * Try looking ahead to see if there are additional
804 * factors for the same product.
805 */
806 if (i + 1 < ARRAY_SIZE(factors)) {
807 i++;
808 new_r = UNPACK_R(factors[i]);
809 new_od = UNPACK_OD(factors[i]);
810 if (r * od == new_r * new_od) {
811 r = new_r;
812 od = new_od;
813 swapped = false;
814 goto again;
Sean Andersonaf9f9972021-06-11 00:16:09 -0400815 }
Sean Anderson49708742021-09-11 13:20:01 -0400816 i--;
Sean Andersonaf9f9972021-06-11 00:16:09 -0400817 }
818
Sean Anderson49708742021-09-11 13:20:01 -0400819 /* We ran out of things to try */
820 continue;
821 }
Sean Andersonaf9f9972021-06-11 00:16:09 -0400822
Sean Anderson49708742021-09-11 13:20:01 -0400823 error = DIV_ROUND_CLOSEST_ULL(f * inv_ratio, r * od);
824 /* The lower 16 bits are spurious */
825 error = abs((error - BIT(32))) >> 16;
826
827 if (error < best_error) {
828 best->r = r;
829 best->f = f;
830 best->od = od;
831 best_error = error;
Sean Andersonaf9f9972021-06-11 00:16:09 -0400832 }
833 } while (f < 64 && i + 1 < ARRAY_SIZE(factors) && error != 0);
834
Sean Anderson49708742021-09-11 13:20:01 -0400835 log_debug("best error %lld\n", best_error);
Sean Andersonaf9f9972021-06-11 00:16:09 -0400836 if (best_error == S64_MAX)
837 return -EINVAL;
838
Sean Andersonaf9f9972021-06-11 00:16:09 -0400839 return 0;
840}
841
842static ulong k210_pll_set_rate(struct k210_clk_priv *priv, int id, ulong rate,
843 ulong rate_in)
844{
845 int err;
846 const struct k210_pll_params *pll = &k210_plls[id];
847 struct k210_pll_config config = {};
848 u32 reg;
Sean Andersondf79e2b2021-06-11 00:16:12 -0400849 ulong calc_rate;
Sean Andersonaf9f9972021-06-11 00:16:09 -0400850
Sean Andersonaf9f9972021-06-11 00:16:09 -0400851 err = k210_pll_calc_config(rate, rate_in, &config);
852 if (err)
853 return err;
854 log_debug("Got r=%u f=%u od=%u\n", config.r, config.f, config.od);
855
Sean Andersondf79e2b2021-06-11 00:16:12 -0400856 /* Don't bother setting the rate if we're already at that rate */
857 calc_rate = DIV_ROUND_DOWN_ULL(((u64)rate_in) * config.f,
858 config.r * config.od);
859 if (calc_rate == k210_pll_get_rate(priv, id, rate))
860 return calc_rate;
861
Sean Andersonaf9f9972021-06-11 00:16:09 -0400862 k210_pll_disable(priv, id);
863
864 reg = readl(priv->base + pll->off);
865 reg &= ~K210_PLL_CLKR
866 & ~K210_PLL_CLKF
867 & ~K210_PLL_CLKOD
868 & ~K210_PLL_BWADJ;
869 reg |= FIELD_PREP(K210_PLL_CLKR, config.r - 1)
870 | FIELD_PREP(K210_PLL_CLKF, config.f - 1)
871 | FIELD_PREP(K210_PLL_CLKOD, config.od - 1)
872 | FIELD_PREP(K210_PLL_BWADJ, config.f - 1);
873 writel(reg, priv->base + pll->off);
874
Sean Andersondf79e2b2021-06-11 00:16:12 -0400875 k210_pll_enable(priv, id);
Sean Andersonaf9f9972021-06-11 00:16:09 -0400876
877 serial_setbrg();
878 return k210_pll_get_rate(priv, id, rate);
879}
880#else
881static ulong k210_pll_set_rate(struct k210_clk_priv *priv, int id, ulong rate,
882 ulong rate_in)
883{
884 return -ENOSYS;
885}
886#endif /* CONFIG_CLK_K210_SET_RATE */
887
888static ulong k210_pll_get_rate(struct k210_clk_priv *priv, int id,
889 ulong rate_in)
890{
891 u64 r, f, od;
892 u32 reg = readl(priv->base + k210_plls[id].off);
893
Sean Anderson54d5d2d2021-09-11 13:20:00 -0400894 if (reg & K210_PLL_BYPASS)
Sean Andersonaf9f9972021-06-11 00:16:09 -0400895 return rate_in;
896
897 if (!(reg & K210_PLL_PWRD))
898 return 0;
899
900 r = FIELD_GET(K210_PLL_CLKR, reg) + 1;
901 f = FIELD_GET(K210_PLL_CLKF, reg) + 1;
902 od = FIELD_GET(K210_PLL_CLKOD, reg) + 1;
903
904 return DIV_ROUND_DOWN_ULL(((u64)rate_in) * f, r * od);
905}
906
907/*
908 * Wait for the PLL to be locked. If the PLL is not locked, try clearing the
909 * slip before retrying
910 */
911static void k210_pll_waitfor_lock(struct k210_clk_priv *priv, int id)
912{
913 const struct k210_pll_params *pll = &k210_plls[id];
914 u32 mask = (BIT(pll->width) - 1) << pll->shift;
915
916 while (true) {
917 u32 reg = readl(priv->base + K210_SYSCTL_PLL_LOCK);
918
919 if ((reg & mask) == mask)
920 break;
921
922 reg |= BIT(pll->shift + K210_PLL_CLEAR_SLIP);
923 writel(reg, priv->base + K210_SYSCTL_PLL_LOCK);
924 }
925}
926
Sean Anderson612a8332021-06-11 00:16:10 -0400927static bool k210_pll_enabled(u32 reg)
928{
929 return (reg & K210_PLL_PWRD) && (reg & K210_PLL_EN) &&
930 !(reg & K210_PLL_RESET);
931}
932
Sean Andersonaf9f9972021-06-11 00:16:09 -0400933/* Adapted from sysctl_pll_enable */
934static int k210_pll_enable(struct k210_clk_priv *priv, int id)
935{
936 const struct k210_pll_params *pll = &k210_plls[id];
937 u32 reg = readl(priv->base + pll->off);
938
Sean Anderson612a8332021-06-11 00:16:10 -0400939 if (k210_pll_enabled(reg))
Sean Andersonaf9f9972021-06-11 00:16:09 -0400940 return 0;
941
942 reg |= K210_PLL_PWRD;
943 writel(reg, priv->base + pll->off);
944
945 /* Ensure reset is low before asserting it */
946 reg &= ~K210_PLL_RESET;
947 writel(reg, priv->base + pll->off);
948 reg |= K210_PLL_RESET;
949 writel(reg, priv->base + pll->off);
950 nop();
951 nop();
952 reg &= ~K210_PLL_RESET;
953 writel(reg, priv->base + pll->off);
954
955 k210_pll_waitfor_lock(priv, id);
956
957 reg &= ~K210_PLL_BYPASS;
958 reg |= K210_PLL_EN;
959 writel(reg, priv->base + pll->off);
960
961 return 0;
962}
963
964static int k210_pll_disable(struct k210_clk_priv *priv, int id)
965{
966 const struct k210_pll_params *pll = &k210_plls[id];
967 u32 reg = readl(priv->base + pll->off);
968
969 /*
970 * Bypassing before powering off is important so child clocks don't stop
971 * working. This is especially important for pll0, the indirect parent
972 * of the cpu clock.
973 */
974 reg |= K210_PLL_BYPASS;
975 writel(reg, priv->base + pll->off);
976
977 reg &= ~K210_PLL_PWRD;
978 reg &= ~K210_PLL_EN;
979 writel(reg, priv->base + pll->off);
980 return 0;
981}
982
Sean Anderson609bd602021-06-11 00:16:08 -0400983static u32 k210_clk_readl(struct k210_clk_priv *priv, u8 off, u8 shift,
984 u8 width)
Sean Andersonf9c7d4f2020-06-24 06:41:11 -0400985{
Sean Anderson609bd602021-06-11 00:16:08 -0400986 u32 reg = readl(priv->base + off);
Sean Andersonf9c7d4f2020-06-24 06:41:11 -0400987
Sean Anderson609bd602021-06-11 00:16:08 -0400988 return (reg >> shift) & (BIT(width) - 1);
Sean Andersonf9c7d4f2020-06-24 06:41:11 -0400989}
990
Sean Anderson609bd602021-06-11 00:16:08 -0400991static void k210_clk_writel(struct k210_clk_priv *priv, u8 off, u8 shift,
992 u8 width, u32 val)
Sean Andersonf9c7d4f2020-06-24 06:41:11 -0400993{
Sean Anderson609bd602021-06-11 00:16:08 -0400994 u32 reg = readl(priv->base + off);
995 u32 mask = (BIT(width) - 1) << shift;
Sean Andersonf9c7d4f2020-06-24 06:41:11 -0400996
Sean Anderson609bd602021-06-11 00:16:08 -0400997 reg &= ~mask;
998 reg |= mask & (val << shift);
999 writel(reg, priv->base + off);
Sean Andersonf9c7d4f2020-06-24 06:41:11 -04001000}
1001
Sean Anderson609bd602021-06-11 00:16:08 -04001002static int k210_clk_get_parent(struct k210_clk_priv *priv, int id)
Sean Andersonf9c7d4f2020-06-24 06:41:11 -04001003{
Sean Anderson609bd602021-06-11 00:16:08 -04001004 u32 sel;
1005 const struct k210_mux_params *mux;
Sean Andersonf9c7d4f2020-06-24 06:41:11 -04001006
Sean Anderson609bd602021-06-11 00:16:08 -04001007 if (!(k210_clks[id].flags & K210_CLKF_MUX))
1008 return k210_clks[id].parent;
1009 mux = &k210_muxes[k210_clks[id].mux];
Sean Andersonf9c7d4f2020-06-24 06:41:11 -04001010
Sean Anderson609bd602021-06-11 00:16:08 -04001011 sel = k210_clk_readl(priv, mux->off, mux->shift, mux->width);
1012 assert(sel < mux->num_parents);
1013 return mux->parents[sel];
Sean Andersonf9c7d4f2020-06-24 06:41:11 -04001014}
1015
Sean Anderson609bd602021-06-11 00:16:08 -04001016static ulong do_k210_clk_get_rate(struct k210_clk_priv *priv, int id)
Sean Andersonf9c7d4f2020-06-24 06:41:11 -04001017{
Sean Anderson609bd602021-06-11 00:16:08 -04001018 int parent;
1019 u32 val;
1020 ulong parent_rate;
1021 const struct k210_div_params *div;
Sean Andersonf9c7d4f2020-06-24 06:41:11 -04001022
Sean Anderson609bd602021-06-11 00:16:08 -04001023 if (id == K210_CLK_IN0)
1024 return clk_get_rate(&priv->in0);
Sean Andersonf9c7d4f2020-06-24 06:41:11 -04001025
Sean Anderson609bd602021-06-11 00:16:08 -04001026 parent = k210_clk_get_parent(priv, id);
1027 parent_rate = do_k210_clk_get_rate(priv, parent);
Sean Anderson54d5d2d2021-09-11 13:20:00 -04001028 if (IS_ERR_VALUE(parent_rate))
1029 return parent_rate;
Sean Andersonf9c7d4f2020-06-24 06:41:11 -04001030
Sean Anderson609bd602021-06-11 00:16:08 -04001031 if (k210_clks[id].flags & K210_CLKF_PLL)
1032 return k210_pll_get_rate(priv, k210_clks[id].pll, parent_rate);
1033
1034 if (k210_clks[id].div == K210_CLK_DIV_NONE)
1035 return parent_rate;
1036 div = &k210_divs[k210_clks[id].div];
1037
1038 if (div->type == K210_DIV_FIXED)
1039 return parent_rate / div->div;
1040
1041 val = k210_clk_readl(priv, div->off, div->shift, div->width);
1042 switch (div->type) {
1043 case K210_DIV_ONE:
1044 return parent_rate / (val + 1);
1045 case K210_DIV_EVEN:
1046 return parent_rate / 2 / (val + 1);
1047 case K210_DIV_POWER:
1048 /* This is ACLK, which has no divider on IN0 */
1049 if (parent == K210_CLK_IN0)
1050 return parent_rate;
1051 return parent_rate / (2 << val);
1052 default:
1053 assert(false);
1054 return -EINVAL;
1055 };
Sean Andersonf9c7d4f2020-06-24 06:41:11 -04001056}
1057
Sean Anderson609bd602021-06-11 00:16:08 -04001058static ulong k210_clk_get_rate(struct clk *clk)
Sean Andersonf9c7d4f2020-06-24 06:41:11 -04001059{
Sean Anderson609bd602021-06-11 00:16:08 -04001060 return do_k210_clk_get_rate(dev_get_priv(clk->dev), clk->id);
1061}
Sean Andersonf9c7d4f2020-06-24 06:41:11 -04001062
Sean Anderson609bd602021-06-11 00:16:08 -04001063static int do_k210_clk_set_parent(struct k210_clk_priv *priv, int id, int new)
1064{
1065 int i;
1066 const struct k210_mux_params *mux;
Sean Andersonf9c7d4f2020-06-24 06:41:11 -04001067
Sean Anderson609bd602021-06-11 00:16:08 -04001068 if (!(k210_clks[id].flags & K210_CLKF_MUX))
1069 return -ENOSYS;
1070 mux = &k210_muxes[k210_clks[id].mux];
1071
1072 for (i = 0; i < mux->num_parents; i++) {
1073 if (mux->parents[i] == new) {
1074 k210_clk_writel(priv, mux->off, mux->shift, mux->width,
1075 i);
1076 return 0;
1077 }
1078 }
1079 return -EINVAL;
1080}
1081
1082static int k210_clk_set_parent(struct clk *clk, struct clk *parent)
1083{
1084 return do_k210_clk_set_parent(dev_get_priv(clk->dev), clk->id,
1085 parent->id);
1086}
1087
Sean Anderson29e30672021-06-11 00:16:11 -04001088static ulong k210_clk_set_rate(struct clk *clk, unsigned long rate)
1089{
1090 int parent, ret, err;
1091 ulong rate_in, val;
1092 const struct k210_div_params *div;
1093 struct k210_clk_priv *priv = dev_get_priv(clk->dev);
1094
1095 if (clk->id == K210_CLK_IN0)
1096 return clk_set_rate(&priv->in0, rate);
1097
1098 parent = k210_clk_get_parent(priv, clk->id);
1099 rate_in = do_k210_clk_get_rate(priv, parent);
Sean Anderson54d5d2d2021-09-11 13:20:00 -04001100 if (IS_ERR_VALUE(rate_in))
1101 return rate_in;
Sean Anderson29e30672021-06-11 00:16:11 -04001102
1103 log_debug("id=%ld rate=%lu rate_in=%lu\n", clk->id, rate, rate_in);
1104
1105 if (clk->id == K210_CLK_PLL0) {
1106 /* Bypass ACLK so the CPU keeps going */
1107 ret = do_k210_clk_set_parent(priv, K210_CLK_ACLK, K210_CLK_IN0);
1108 if (ret)
1109 return ret;
1110 } else if (clk->id == K210_CLK_PLL1 && gd->flags & GD_FLG_RELOC) {
1111 /*
1112 * We can't bypass the AI clock like we can ACLK, and after
1113 * relocation we are using the AI ram.
1114 */
1115 return -EPERM;
1116 }
1117
1118 if (k210_clks[clk->id].flags & K210_CLKF_PLL) {
1119 ret = k210_pll_set_rate(priv, k210_clks[clk->id].pll, rate,
1120 rate_in);
1121 if (!IS_ERR_VALUE(ret) && clk->id == K210_CLK_PLL0) {
1122 /*
1123 * This may have the side effect of reparenting ACLK,
1124 * but I don't really want to keep track of what the old
1125 * parent was.
1126 */
1127 err = do_k210_clk_set_parent(priv, K210_CLK_ACLK,
1128 K210_CLK_PLL0);
1129 if (err)
1130 return err;
1131 }
1132 return ret;
1133 }
1134
1135 if (k210_clks[clk->id].div == K210_CLK_DIV_NONE)
1136 return -ENOSYS;
1137 div = &k210_divs[k210_clks[clk->id].div];
1138
1139 switch (div->type) {
1140 case K210_DIV_ONE:
1141 val = DIV_ROUND_CLOSEST_ULL((u64)rate_in, rate);
1142 val = val ? val - 1 : 0;
1143 break;
1144 case K210_DIV_EVEN:
1145 val = DIV_ROUND_CLOSEST_ULL((u64)rate_in, 2 * rate);
1146 break;
1147 case K210_DIV_POWER:
1148 /* This is ACLK, which has no divider on IN0 */
1149 if (parent == K210_CLK_IN0)
1150 return -ENOSYS;
1151
1152 val = DIV_ROUND_CLOSEST_ULL((u64)rate_in, rate);
1153 val = __ffs(val);
1154 break;
1155 default:
1156 assert(false);
1157 return -EINVAL;
1158 };
1159
1160 val = val ? val - 1 : 0;
1161 k210_clk_writel(priv, div->off, div->shift, div->width, val);
1162 return do_k210_clk_get_rate(priv, clk->id);
1163}
1164
Sean Anderson609bd602021-06-11 00:16:08 -04001165static int k210_clk_endisable(struct k210_clk_priv *priv, int id, bool enable)
1166{
1167 int parent = k210_clk_get_parent(priv, id);
1168 const struct k210_gate_params *gate;
1169
1170 if (id == K210_CLK_IN0) {
1171 if (enable)
1172 return clk_enable(&priv->in0);
1173 else
1174 return clk_disable(&priv->in0);
Sean Andersonf9c7d4f2020-06-24 06:41:11 -04001175 }
1176
Sean Anderson609bd602021-06-11 00:16:08 -04001177 /* Only recursively enable clocks since we don't track refcounts */
1178 if (enable) {
1179 int ret = k210_clk_endisable(priv, parent, true);
1180
1181 if (ret && ret != -ENOSYS)
1182 return ret;
Sean Andersonf9c7d4f2020-06-24 06:41:11 -04001183 }
1184
Sean Anderson609bd602021-06-11 00:16:08 -04001185 if (k210_clks[id].flags & K210_CLKF_PLL) {
1186 if (enable)
1187 return k210_pll_enable(priv, k210_clks[id].pll);
1188 else
1189 return k210_pll_disable(priv, k210_clks[id].pll);
Sean Andersonf9c7d4f2020-06-24 06:41:11 -04001190 }
1191
Sean Anderson609bd602021-06-11 00:16:08 -04001192 if (k210_clks[id].gate == K210_CLK_GATE_NONE)
1193 return -ENOSYS;
1194 gate = &k210_gates[k210_clks[id].gate];
Sean Andersonf9c7d4f2020-06-24 06:41:11 -04001195
Sean Anderson609bd602021-06-11 00:16:08 -04001196 k210_clk_writel(priv, gate->off, gate->bit_idx, 1, enable);
Sean Anderson09ad08f2021-04-08 22:13:08 -04001197 return 0;
1198}
Sean Andersonf9c7d4f2020-06-24 06:41:11 -04001199
Sean Anderson609bd602021-06-11 00:16:08 -04001200static int k210_clk_enable(struct clk *clk)
1201{
1202 return k210_clk_endisable(dev_get_priv(clk->dev), clk->id, true);
1203}
1204
1205static int k210_clk_disable(struct clk *clk)
1206{
1207 return k210_clk_endisable(dev_get_priv(clk->dev), clk->id, false);
1208}
1209
1210static int k210_clk_request(struct clk *clk)
1211{
1212 if (clk->id >= ARRAY_SIZE(k210_clks))
1213 return -EINVAL;
1214 return 0;
1215}
1216
1217static const struct clk_ops k210_clk_ops = {
1218 .request = k210_clk_request,
1219 .set_rate = k210_clk_set_rate,
1220 .get_rate = k210_clk_get_rate,
1221 .set_parent = k210_clk_set_parent,
1222 .enable = k210_clk_enable,
1223 .disable = k210_clk_disable,
1224};
1225
Sean Andersonf9c7d4f2020-06-24 06:41:11 -04001226static int k210_clk_probe(struct udevice *dev)
1227{
1228 int ret;
Sean Anderson609bd602021-06-11 00:16:08 -04001229 struct k210_clk_priv *priv = dev_get_priv(dev);
Sean Andersonf9c7d4f2020-06-24 06:41:11 -04001230
Sean Anderson609bd602021-06-11 00:16:08 -04001231 priv->base = dev_read_addr_ptr(dev_get_parent(dev));
1232 if (!priv->base)
Simon Glass9042bf62021-03-25 10:26:08 +13001233 return -EINVAL;
Sean Andersonf9c7d4f2020-06-24 06:41:11 -04001234
Sean Anderson609bd602021-06-11 00:16:08 -04001235 ret = clk_get_by_index(dev, 0, &priv->in0);
Sean Andersonf9c7d4f2020-06-24 06:41:11 -04001236 if (ret)
1237 return ret;
Sean Andersona952c3a2020-09-28 10:52:27 -04001238
Sean Anderson29e30672021-06-11 00:16:11 -04001239 /*
1240 * Force setting defaults, even before relocation. This is so we can
1241 * set the clock rate for PLL1 before we relocate into aisram.
1242 */
1243 if (!(gd->flags & GD_FLG_RELOC))
1244 clk_set_defaults(dev, CLK_DEFAULTS_POST_FORCE);
1245
Sean Andersonf9c7d4f2020-06-24 06:41:11 -04001246 return 0;
1247}
1248
1249static const struct udevice_id k210_clk_ids[] = {
1250 { .compatible = "kendryte,k210-clk" },
1251 { },
1252};
1253
1254U_BOOT_DRIVER(k210_clk) = {
1255 .name = "k210_clk",
1256 .id = UCLASS_CLK,
1257 .of_match = k210_clk_ids,
1258 .ops = &k210_clk_ops,
Sean Andersonf9c7d4f2020-06-24 06:41:11 -04001259 .probe = k210_clk_probe,
Sean Anderson609bd602021-06-11 00:16:08 -04001260 .priv_auto = sizeof(struct k210_clk_priv),
Sean Andersonf9c7d4f2020-06-24 06:41:11 -04001261};
Sean Anderson612a8332021-06-11 00:16:10 -04001262
1263#if CONFIG_IS_ENABLED(CMD_CLK)
1264static char show_enabled(struct k210_clk_priv *priv, int id)
1265{
1266 bool enabled;
1267
1268 if (k210_clks[id].flags & K210_CLKF_PLL) {
1269 const struct k210_pll_params *pll =
1270 &k210_plls[k210_clks[id].pll];
1271
1272 enabled = k210_pll_enabled(readl(priv->base + pll->off));
1273 } else if (k210_clks[id].gate == K210_CLK_GATE_NONE) {
1274 return '-';
1275 } else {
1276 const struct k210_gate_params *gate =
1277 &k210_gates[k210_clks[id].gate];
1278
1279 enabled = k210_clk_readl(priv, gate->off, gate->bit_idx, 1);
1280 }
1281
1282 return enabled ? 'y' : 'n';
1283}
1284
1285static void show_clks(struct k210_clk_priv *priv, int id, int depth)
1286{
1287 int i;
1288
1289 for (i = 0; i < ARRAY_SIZE(k210_clks); i++) {
1290 if (k210_clk_get_parent(priv, i) != id)
1291 continue;
1292
1293 printf(" %-9lu %-7c %*s%s\n", do_k210_clk_get_rate(priv, i),
1294 show_enabled(priv, i), depth * 4, "",
1295 k210_clks[i].name);
1296
1297 show_clks(priv, i, depth + 1);
1298 }
1299}
1300
1301int soc_clk_dump(void)
1302{
1303 int ret;
1304 struct udevice *dev;
1305 struct k210_clk_priv *priv;
1306
1307 ret = uclass_get_device_by_driver(UCLASS_CLK, DM_DRIVER_GET(k210_clk),
1308 &dev);
1309 if (ret)
1310 return ret;
1311 priv = dev_get_priv(dev);
1312
1313 puts(" Rate Enabled Name\n");
1314 puts("------------------------\n");
1315 printf(" %-9lu %-7c %*s%s\n", clk_get_rate(&priv->in0), 'y', 0, "",
1316 priv->in0.dev->name);
1317 show_clks(priv, K210_CLK_IN0, 1);
1318 return 0;
1319}
1320#endif