blob: 7432ae8f0642b1722e9efd42ae3d9351c643904d [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>
Damien Le Moalfd426b32022-03-01 10:35:39 +000017#include <k210/pll.h>
Sean Andersonaf9f9972021-06-11 00:16:09 -040018#include <linux/bitfield.h>
Tom Rinid563bb52023-10-26 14:31:36 -040019#include <asm/barrier.h>
Sean Andersonaf9f9972021-06-11 00:16:09 -040020
Sean Anderson29e30672021-06-11 00:16:11 -040021DECLARE_GLOBAL_DATA_PTR;
22
Sean Andersonaf9f9972021-06-11 00:16:09 -040023/**
24 * struct k210_clk_priv - K210 clock driver private data
25 * @base: The base address of the sysctl device
26 * @in0: The "in0" external oscillator
27 */
28struct k210_clk_priv {
29 void __iomem *base;
30 struct clk in0;
31};
Sean Andersonf9c7d4f2020-06-24 06:41:11 -040032
Sean Andersonf9c7d4f2020-06-24 06:41:11 -040033/*
34 * All parameters for different sub-clocks are collected into parameter arrays.
35 * These parameters are then initialized by the clock which uses them during
36 * probe. To save space, ids are automatically generated for each sub-clock by
37 * using an enum. Instead of storing a parameter struct for each clock, even for
38 * those clocks which don't use a particular type of sub-clock, we can just
39 * store the parameters for the clocks which need them.
40 *
41 * So why do it like this? Arranging all the sub-clocks together makes it very
42 * easy to find bugs in the code.
43 */
44
Sean Anderson609bd602021-06-11 00:16:08 -040045/**
46 * enum k210_clk_div_type - The type of divider
47 * @K210_DIV_ONE: freq = parent / (reg + 1)
48 * @K210_DIV_EVEN: freq = parent / 2 / (reg + 1)
49 * @K210_DIV_POWER: freq = parent / (2 << reg)
50 * @K210_DIV_FIXED: freq = parent / factor
51 */
52enum k210_clk_div_type {
53 K210_DIV_ONE,
54 K210_DIV_EVEN,
55 K210_DIV_POWER,
56 K210_DIV_FIXED,
57};
58
59/**
60 * struct k210_div_params - Parameters for dividing clocks
61 * @type: An &enum k210_clk_div_type specifying the dividing formula
62 * @off: The offset of the divider from the sysctl base address
63 * @shift: The offset of the LSB of the divider
64 * @width: The number of bits in the divider
65 * @div: The fixed divisor for this divider
66 */
67struct k210_div_params {
68 u8 type;
69 union {
70 struct {
71 u8 off;
72 u8 shift;
73 u8 width;
74 };
75 u8 div;
76 };
77};
78
Sean Andersonf9c7d4f2020-06-24 06:41:11 -040079#define DIV_LIST \
Sean Anderson609bd602021-06-11 00:16:08 -040080 DIV(K210_CLK_ACLK, K210_SYSCTL_SEL0, 1, 2, K210_DIV_POWER) \
81 DIV(K210_CLK_APB0, K210_SYSCTL_SEL0, 3, 3, K210_DIV_ONE) \
82 DIV(K210_CLK_APB1, K210_SYSCTL_SEL0, 6, 3, K210_DIV_ONE) \
83 DIV(K210_CLK_APB2, K210_SYSCTL_SEL0, 9, 3, K210_DIV_ONE) \
84 DIV(K210_CLK_SRAM0, K210_SYSCTL_THR0, 0, 4, K210_DIV_ONE) \
85 DIV(K210_CLK_SRAM1, K210_SYSCTL_THR0, 4, 4, K210_DIV_ONE) \
86 DIV(K210_CLK_AI, K210_SYSCTL_THR0, 8, 4, K210_DIV_ONE) \
87 DIV(K210_CLK_DVP, K210_SYSCTL_THR0, 12, 4, K210_DIV_ONE) \
88 DIV(K210_CLK_ROM, K210_SYSCTL_THR0, 16, 4, K210_DIV_ONE) \
89 DIV(K210_CLK_SPI0, K210_SYSCTL_THR1, 0, 8, K210_DIV_EVEN) \
90 DIV(K210_CLK_SPI1, K210_SYSCTL_THR1, 8, 8, K210_DIV_EVEN) \
91 DIV(K210_CLK_SPI2, K210_SYSCTL_THR1, 16, 8, K210_DIV_EVEN) \
92 DIV(K210_CLK_SPI3, K210_SYSCTL_THR1, 24, 8, K210_DIV_EVEN) \
93 DIV(K210_CLK_TIMER0, K210_SYSCTL_THR2, 0, 8, K210_DIV_EVEN) \
94 DIV(K210_CLK_TIMER1, K210_SYSCTL_THR2, 8, 8, K210_DIV_EVEN) \
95 DIV(K210_CLK_TIMER2, K210_SYSCTL_THR2, 16, 8, K210_DIV_EVEN) \
96 DIV(K210_CLK_I2S0, K210_SYSCTL_THR3, 0, 16, K210_DIV_EVEN) \
97 DIV(K210_CLK_I2S1, K210_SYSCTL_THR3, 16, 16, K210_DIV_EVEN) \
98 DIV(K210_CLK_I2S2, K210_SYSCTL_THR4, 0, 16, K210_DIV_EVEN) \
99 DIV(K210_CLK_I2S0_M, K210_SYSCTL_THR4, 16, 8, K210_DIV_EVEN) \
100 DIV(K210_CLK_I2S1_M, K210_SYSCTL_THR4, 24, 8, K210_DIV_EVEN) \
101 DIV(K210_CLK_I2S2_M, K210_SYSCTL_THR4, 0, 8, K210_DIV_EVEN) \
102 DIV(K210_CLK_I2C0, K210_SYSCTL_THR5, 8, 8, K210_DIV_EVEN) \
103 DIV(K210_CLK_I2C1, K210_SYSCTL_THR5, 16, 8, K210_DIV_EVEN) \
104 DIV(K210_CLK_I2C2, K210_SYSCTL_THR5, 24, 8, K210_DIV_EVEN) \
105 DIV(K210_CLK_WDT0, K210_SYSCTL_THR6, 0, 8, K210_DIV_EVEN) \
106 DIV(K210_CLK_WDT1, K210_SYSCTL_THR6, 8, 8, K210_DIV_EVEN) \
107 DIV_FIXED(K210_CLK_CLINT, 50) \
Sean Andersonf9c7d4f2020-06-24 06:41:11 -0400108
109#define _DIVIFY(id) K210_CLK_DIV_##id
110#define DIVIFY(id) _DIVIFY(id)
111
Sean Anderson609bd602021-06-11 00:16:08 -0400112enum k210_div_id {
113#define DIV(id, ...) DIVIFY(id),
114#define DIV_FIXED DIV
Sean Andersonf9c7d4f2020-06-24 06:41:11 -0400115 DIV_LIST
Sean Anderson609bd602021-06-11 00:16:08 -0400116#undef DIV
117#undef DIV_FIXED
118 K210_CLK_DIV_NONE,
Sean Andersonf9c7d4f2020-06-24 06:41:11 -0400119};
120
121static const struct k210_div_params k210_divs[] = {
Sean Anderson609bd602021-06-11 00:16:08 -0400122#define DIV(id, _off, _shift, _width, _type) \
Sean Andersonf9c7d4f2020-06-24 06:41:11 -0400123 [DIVIFY(id)] = { \
Sean Anderson609bd602021-06-11 00:16:08 -0400124 .type = (_type), \
Sean Andersonf9c7d4f2020-06-24 06:41:11 -0400125 .off = (_off), \
126 .shift = (_shift), \
127 .width = (_width), \
Sean Anderson609bd602021-06-11 00:16:08 -0400128 },
129#define DIV_FIXED(id, _div) \
130 [DIVIFY(id)] = { \
131 .type = K210_DIV_FIXED, \
132 .div = (_div) \
Sean Andersonf9c7d4f2020-06-24 06:41:11 -0400133 },
134 DIV_LIST
Sean Anderson609bd602021-06-11 00:16:08 -0400135#undef DIV
136#undef DIV_FIXED
Sean Andersonf9c7d4f2020-06-24 06:41:11 -0400137};
138
139#undef DIV
140#undef DIV_LIST
141
Sean Anderson609bd602021-06-11 00:16:08 -0400142/**
143 * struct k210_gate_params - Parameters for gated clocks
144 * @off: The offset of the gate from the sysctl base address
145 * @bit_idx: The index of the bit within the register
146 */
147struct k210_gate_params {
148 u8 off;
149 u8 bit_idx;
150};
151
Sean Andersonf9c7d4f2020-06-24 06:41:11 -0400152#define GATE_LIST \
153 GATE(K210_CLK_CPU, K210_SYSCTL_EN_CENT, 0) \
154 GATE(K210_CLK_SRAM0, K210_SYSCTL_EN_CENT, 1) \
155 GATE(K210_CLK_SRAM1, K210_SYSCTL_EN_CENT, 2) \
156 GATE(K210_CLK_APB0, K210_SYSCTL_EN_CENT, 3) \
157 GATE(K210_CLK_APB1, K210_SYSCTL_EN_CENT, 4) \
158 GATE(K210_CLK_APB2, K210_SYSCTL_EN_CENT, 5) \
159 GATE(K210_CLK_ROM, K210_SYSCTL_EN_PERI, 0) \
160 GATE(K210_CLK_DMA, K210_SYSCTL_EN_PERI, 1) \
161 GATE(K210_CLK_AI, K210_SYSCTL_EN_PERI, 2) \
162 GATE(K210_CLK_DVP, K210_SYSCTL_EN_PERI, 3) \
163 GATE(K210_CLK_FFT, K210_SYSCTL_EN_PERI, 4) \
164 GATE(K210_CLK_GPIO, K210_SYSCTL_EN_PERI, 5) \
165 GATE(K210_CLK_SPI0, K210_SYSCTL_EN_PERI, 6) \
166 GATE(K210_CLK_SPI1, K210_SYSCTL_EN_PERI, 7) \
167 GATE(K210_CLK_SPI2, K210_SYSCTL_EN_PERI, 8) \
168 GATE(K210_CLK_SPI3, K210_SYSCTL_EN_PERI, 9) \
169 GATE(K210_CLK_I2S0, K210_SYSCTL_EN_PERI, 10) \
170 GATE(K210_CLK_I2S1, K210_SYSCTL_EN_PERI, 11) \
171 GATE(K210_CLK_I2S2, K210_SYSCTL_EN_PERI, 12) \
172 GATE(K210_CLK_I2C0, K210_SYSCTL_EN_PERI, 13) \
173 GATE(K210_CLK_I2C1, K210_SYSCTL_EN_PERI, 14) \
174 GATE(K210_CLK_I2C2, K210_SYSCTL_EN_PERI, 15) \
175 GATE(K210_CLK_UART1, K210_SYSCTL_EN_PERI, 16) \
176 GATE(K210_CLK_UART2, K210_SYSCTL_EN_PERI, 17) \
177 GATE(K210_CLK_UART3, K210_SYSCTL_EN_PERI, 18) \
178 GATE(K210_CLK_AES, K210_SYSCTL_EN_PERI, 19) \
179 GATE(K210_CLK_FPIOA, K210_SYSCTL_EN_PERI, 20) \
180 GATE(K210_CLK_TIMER0, K210_SYSCTL_EN_PERI, 21) \
181 GATE(K210_CLK_TIMER1, K210_SYSCTL_EN_PERI, 22) \
182 GATE(K210_CLK_TIMER2, K210_SYSCTL_EN_PERI, 23) \
183 GATE(K210_CLK_WDT0, K210_SYSCTL_EN_PERI, 24) \
184 GATE(K210_CLK_WDT1, K210_SYSCTL_EN_PERI, 25) \
185 GATE(K210_CLK_SHA, K210_SYSCTL_EN_PERI, 26) \
186 GATE(K210_CLK_OTP, K210_SYSCTL_EN_PERI, 27) \
187 GATE(K210_CLK_RTC, K210_SYSCTL_EN_PERI, 29)
188
189#define _GATEIFY(id) K210_CLK_GATE_##id
190#define GATEIFY(id) _GATEIFY(id)
191
Sean Anderson609bd602021-06-11 00:16:08 -0400192enum k210_gate_id {
Sean Andersonf9c7d4f2020-06-24 06:41:11 -0400193#define GATE(id, ...) GATEIFY(id),
194 GATE_LIST
195#undef GATE
Sean Anderson609bd602021-06-11 00:16:08 -0400196 K210_CLK_GATE_NONE,
Sean Andersonf9c7d4f2020-06-24 06:41:11 -0400197};
198
199static const struct k210_gate_params k210_gates[] = {
200#define GATE(id, _off, _idx) \
201 [GATEIFY(id)] = { \
202 .off = (_off), \
203 .bit_idx = (_idx), \
204 },
205 GATE_LIST
206#undef GATE
207};
208
209#undef GATE_LIST
210
Sean Anderson609bd602021-06-11 00:16:08 -0400211/* The most parents is PLL2 */
212#define K210_CLK_MAX_PARENTS 3
213
214/**
215 * struct k210_mux_params - Parameters for muxed clocks
216 * @parents: A list of parent clock ids
217 * @num_parents: The number of parent clocks
218 * @off: The offset of the mux from the base sysctl address
219 * @shift: The offset of the LSB of the mux selector
220 * @width: The number of bits in the mux selector
221 */
222struct k210_mux_params {
223 u8 parents[K210_CLK_MAX_PARENTS];
224 u8 num_parents;
225 u8 off;
226 u8 shift;
227 u8 width;
228};
229
Sean Andersonf9c7d4f2020-06-24 06:41:11 -0400230#define MUX(id, reg, shift, width) \
Sean Anderson609bd602021-06-11 00:16:08 -0400231 MUX_PARENTS(id, reg, shift, width, K210_CLK_IN0, K210_CLK_PLL0)
Sean Andersonf9c7d4f2020-06-24 06:41:11 -0400232#define MUX_LIST \
Sean Anderson609bd602021-06-11 00:16:08 -0400233 MUX_PARENTS(K210_CLK_PLL2, K210_SYSCTL_PLL2, 26, 2, \
234 K210_CLK_IN0, K210_CLK_PLL0, K210_CLK_PLL1) \
235 MUX(K210_CLK_ACLK, K210_SYSCTL_SEL0, 0, 1) \
Sean Andersonf9c7d4f2020-06-24 06:41:11 -0400236 MUX(K210_CLK_SPI3, K210_SYSCTL_SEL0, 12, 1) \
237 MUX(K210_CLK_TIMER0, K210_SYSCTL_SEL0, 13, 1) \
238 MUX(K210_CLK_TIMER1, K210_SYSCTL_SEL0, 14, 1) \
239 MUX(K210_CLK_TIMER2, K210_SYSCTL_SEL0, 15, 1)
240
241#define _MUXIFY(id) K210_CLK_MUX_##id
242#define MUXIFY(id) _MUXIFY(id)
243
Sean Anderson609bd602021-06-11 00:16:08 -0400244enum k210_mux_id {
Sean Andersonf9c7d4f2020-06-24 06:41:11 -0400245#define MUX_PARENTS(id, ...) MUXIFY(id),
246 MUX_LIST
247#undef MUX_PARENTS
248 K210_CLK_MUX_NONE,
249};
250
Sean Andersonf9c7d4f2020-06-24 06:41:11 -0400251static const struct k210_mux_params k210_muxes[] = {
Sean Anderson609bd602021-06-11 00:16:08 -0400252#define MUX_PARENTS(id, _off, _shift, _width, ...) \
Sean Andersonf9c7d4f2020-06-24 06:41:11 -0400253 [MUXIFY(id)] = { \
Sean Anderson609bd602021-06-11 00:16:08 -0400254 .parents = { __VA_ARGS__ }, \
255 .num_parents = __count_args(__VA_ARGS__), \
Sean Andersonf9c7d4f2020-06-24 06:41:11 -0400256 .off = (_off), \
257 .shift = (_shift), \
258 .width = (_width), \
259 },
260 MUX_LIST
261#undef MUX_PARENTS
262};
263
264#undef MUX
265#undef MUX_LIST
266
Sean Anderson609bd602021-06-11 00:16:08 -0400267/**
Sean Andersonaf9f9972021-06-11 00:16:09 -0400268 * struct k210_pll_params - K210 PLL parameters
269 * @off: The offset of the PLL from the base sysctl address
270 * @shift: The offset of the LSB of the lock status
271 * @width: The number of bits in the lock status
272 */
273struct k210_pll_params {
274 u8 off;
275 u8 shift;
276 u8 width;
277};
278
279static const struct k210_pll_params k210_plls[] = {
280#define PLL(_off, _shift, _width) { \
281 .off = (_off), \
282 .shift = (_shift), \
283 .width = (_width), \
284}
285 [0] = PLL(K210_SYSCTL_PLL0, 0, 2),
286 [1] = PLL(K210_SYSCTL_PLL1, 8, 1),
287 [2] = PLL(K210_SYSCTL_PLL2, 16, 1),
288#undef PLL
289};
290
291/**
Sean Anderson609bd602021-06-11 00:16:08 -0400292 * enum k210_clk_flags - The type of a K210 clock
293 * @K210_CLKF_MUX: This clock has a mux and not a static parent
294 * @K210_CLKF_PLL: This clock is a PLL
295 */
296enum k210_clk_flags {
297 K210_CLKF_MUX = BIT(0),
298 K210_CLKF_PLL = BIT(1),
Sean Andersonf9c7d4f2020-06-24 06:41:11 -0400299};
300
Sean Anderson609bd602021-06-11 00:16:08 -0400301/**
302 * struct k210_clk_params - The parameters defining a K210 clock
303 * @name: The name of the clock
304 * @flags: A set of &enum k210_clk_flags defining which fields are valid
305 * @mux: An &enum k210_mux_id of this clock's mux
306 * @parent: The clock id of this clock's parent
307 * @pll: The id of the PLL (if this clock is a PLL)
308 * @div: An &enum k210_div_id of this clock's divider
309 * @gate: An &enum k210_gate_id of this clock's gate
310 */
311struct k210_clk_params {
Simon Glass8dd86202023-02-05 15:36:26 -0700312#if IS_ENABLED(CONFIG_CMD_CLK)
Sean Anderson609bd602021-06-11 00:16:08 -0400313 const char *name;
314#endif
315 u8 flags;
316 union {
317 u8 parent;
318 u8 mux;
319 };
320 union {
321 u8 pll;
322 struct {
323 u8 div;
324 u8 gate;
325 };
326 };
Sean Andersonf9c7d4f2020-06-24 06:41:11 -0400327};
328
Sean Anderson609bd602021-06-11 00:16:08 -0400329static const struct k210_clk_params k210_clks[] = {
Simon Glass8dd86202023-02-05 15:36:26 -0700330#if IS_ENABLED(CONFIG_CMD_CLK)
Sean Anderson609bd602021-06-11 00:16:08 -0400331#define NAME(_name) .name = (_name),
332#else
333#define NAME(name)
334#endif
335#define CLK(id, _name, _parent, _div, _gate) \
336 [id] = { \
337 NAME(_name) \
338 .parent = (_parent), \
339 .div = (_div), \
340 .gate = (_gate), \
341 }
342#define CLK_MUX(id, _name, _mux, _div, _gate) \
343 [id] = { \
344 NAME(_name) \
345 .flags = K210_CLKF_MUX, \
Sean Andersonf9c7d4f2020-06-24 06:41:11 -0400346 .mux = (_mux), \
347 .div = (_div), \
348 .gate = (_gate), \
Sean Anderson609bd602021-06-11 00:16:08 -0400349 }
350#define CLK_PLL(id, _pll, _parent) \
351 [id] = { \
352 NAME("pll" #_pll) \
353 .flags = K210_CLKF_PLL, \
354 .parent = (_parent), \
355 .pll = (_pll), \
356 }
357#define CLK_FULL(id, name) \
358 CLK_MUX(id, name, MUXIFY(id), DIVIFY(id), GATEIFY(id))
359#define CLK_NOMUX(id, name, parent) \
360 CLK(id, name, parent, DIVIFY(id), GATEIFY(id))
361#define CLK_DIV(id, name, parent) \
362 CLK(id, name, parent, DIVIFY(id), K210_CLK_GATE_NONE)
363#define CLK_GATE(id, name, parent) \
364 CLK(id, name, parent, K210_CLK_DIV_NONE, GATEIFY(id))
365 CLK_PLL(K210_CLK_PLL0, 0, K210_CLK_IN0),
366 CLK_PLL(K210_CLK_PLL1, 1, K210_CLK_IN0),
367 [K210_CLK_PLL2] = {
368 NAME("pll2")
369 .flags = K210_CLKF_MUX | K210_CLKF_PLL,
370 .mux = MUXIFY(K210_CLK_PLL2),
371 .pll = 2,
Sean Andersonf9c7d4f2020-06-24 06:41:11 -0400372 },
Sean Anderson609bd602021-06-11 00:16:08 -0400373 CLK_MUX(K210_CLK_ACLK, "aclk", MUXIFY(K210_CLK_ACLK),
374 DIVIFY(K210_CLK_ACLK), K210_CLK_GATE_NONE),
375 CLK_FULL(K210_CLK_SPI3, "spi3"),
376 CLK_FULL(K210_CLK_TIMER0, "timer0"),
377 CLK_FULL(K210_CLK_TIMER1, "timer1"),
378 CLK_FULL(K210_CLK_TIMER2, "timer2"),
379 CLK_NOMUX(K210_CLK_SRAM0, "sram0", K210_CLK_ACLK),
380 CLK_NOMUX(K210_CLK_SRAM1, "sram1", K210_CLK_ACLK),
381 CLK_NOMUX(K210_CLK_ROM, "rom", K210_CLK_ACLK),
382 CLK_NOMUX(K210_CLK_DVP, "dvp", K210_CLK_ACLK),
383 CLK_NOMUX(K210_CLK_APB0, "apb0", K210_CLK_ACLK),
384 CLK_NOMUX(K210_CLK_APB1, "apb1", K210_CLK_ACLK),
385 CLK_NOMUX(K210_CLK_APB2, "apb2", K210_CLK_ACLK),
386 CLK_NOMUX(K210_CLK_AI, "ai", K210_CLK_PLL1),
387 CLK_NOMUX(K210_CLK_I2S0, "i2s0", K210_CLK_PLL2),
388 CLK_NOMUX(K210_CLK_I2S1, "i2s1", K210_CLK_PLL2),
389 CLK_NOMUX(K210_CLK_I2S2, "i2s2", K210_CLK_PLL2),
390 CLK_NOMUX(K210_CLK_WDT0, "wdt0", K210_CLK_IN0),
391 CLK_NOMUX(K210_CLK_WDT1, "wdt1", K210_CLK_IN0),
392 CLK_NOMUX(K210_CLK_SPI0, "spi0", K210_CLK_PLL0),
393 CLK_NOMUX(K210_CLK_SPI1, "spi1", K210_CLK_PLL0),
394 CLK_NOMUX(K210_CLK_SPI2, "spi2", K210_CLK_PLL0),
395 CLK_NOMUX(K210_CLK_I2C0, "i2c0", K210_CLK_PLL0),
396 CLK_NOMUX(K210_CLK_I2C1, "i2c1", K210_CLK_PLL0),
397 CLK_NOMUX(K210_CLK_I2C2, "i2c2", K210_CLK_PLL0),
398 CLK_DIV(K210_CLK_I2S0_M, "i2s0_m", K210_CLK_PLL2),
399 CLK_DIV(K210_CLK_I2S1_M, "i2s1_m", K210_CLK_PLL2),
400 CLK_DIV(K210_CLK_I2S2_M, "i2s2_m", K210_CLK_PLL2),
401 CLK_DIV(K210_CLK_CLINT, "clint", K210_CLK_ACLK),
402 CLK_GATE(K210_CLK_CPU, "cpu", K210_CLK_ACLK),
403 CLK_GATE(K210_CLK_DMA, "dma", K210_CLK_ACLK),
404 CLK_GATE(K210_CLK_FFT, "fft", K210_CLK_ACLK),
405 CLK_GATE(K210_CLK_GPIO, "gpio", K210_CLK_APB0),
406 CLK_GATE(K210_CLK_UART1, "uart1", K210_CLK_APB0),
407 CLK_GATE(K210_CLK_UART2, "uart2", K210_CLK_APB0),
408 CLK_GATE(K210_CLK_UART3, "uart3", K210_CLK_APB0),
409 CLK_GATE(K210_CLK_FPIOA, "fpioa", K210_CLK_APB0),
410 CLK_GATE(K210_CLK_SHA, "sha", K210_CLK_APB0),
411 CLK_GATE(K210_CLK_AES, "aes", K210_CLK_APB1),
412 CLK_GATE(K210_CLK_OTP, "otp", K210_CLK_APB1),
413 CLK_GATE(K210_CLK_RTC, "rtc", K210_CLK_IN0),
414#undef NAME
415#undef CLK_PLL
416#undef CLK
417#undef CLK_FULL
418#undef CLK_NOMUX
419#undef CLK_DIV
420#undef CLK_GATE
421#undef CLK_LIST
Sean Andersonf9c7d4f2020-06-24 06:41:11 -0400422};
423
Sean Andersonaf9f9972021-06-11 00:16:09 -0400424#define K210_PLL_CLKR GENMASK(3, 0)
425#define K210_PLL_CLKF GENMASK(9, 4)
426#define K210_PLL_CLKOD GENMASK(13, 10) /* Output Divider */
427#define K210_PLL_BWADJ GENMASK(19, 14) /* BandWidth Adjust */
428#define K210_PLL_RESET BIT(20)
429#define K210_PLL_PWRD BIT(21) /* PoWeReD */
430#define K210_PLL_INTFB BIT(22) /* Internal FeedBack */
431#define K210_PLL_BYPASS BIT(23)
432#define K210_PLL_TEST BIT(24)
433#define K210_PLL_EN BIT(25)
434#define K210_PLL_TEST_EN BIT(26)
435
436#define K210_PLL_LOCK 0
437#define K210_PLL_CLEAR_SLIP 2
438#define K210_PLL_TEST_OUT 3
439
440#ifdef CONFIG_CLK_K210_SET_RATE
441static int k210_pll_enable(struct k210_clk_priv *priv, int id);
442static int k210_pll_disable(struct k210_clk_priv *priv, int id);
443static ulong k210_pll_get_rate(struct k210_clk_priv *priv, int id, ulong rate_in);
444
445/*
446 * The PLL included with the Kendryte K210 appears to be a True Circuits, Inc.
447 * General-Purpose PLL. The logical layout of the PLL with internal feedback is
448 * approximately the following:
449 *
450 * +---------------+
451 * |reference clock|
452 * +---------------+
453 * |
454 * v
455 * +--+
456 * |/r|
457 * +--+
458 * |
459 * v
460 * +-------------+
461 * |divided clock|
462 * +-------------+
463 * |
464 * v
465 * +--------------+
466 * |phase detector|<---+
467 * +--------------+ |
468 * | |
469 * v +--------------+
470 * +---+ |feedback clock|
471 * |VCO| +--------------+
472 * +---+ ^
473 * | +--+ |
474 * +--->|/f|---+
475 * | +--+
476 * v
477 * +---+
478 * |/od|
479 * +---+
480 * |
481 * v
482 * +------+
483 * |output|
484 * +------+
485 *
486 * The k210 PLLs have three factors: r, f, and od. Because of the feedback mode,
487 * the effect of the division by f is to multiply the input frequency. The
488 * equation for the output rate is
489 * rate = (rate_in * f) / (r * od).
490 * Moving knowns to one side of the equation, we get
491 * rate / rate_in = f / (r * od)
492 * Rearranging slightly,
493 * abs_error = abs((rate / rate_in) - (f / (r * od))).
494 * To get relative, error, we divide by the expected ratio
495 * error = abs((rate / rate_in) - (f / (r * od))) / (rate / rate_in).
496 * Simplifying,
497 * error = abs(1 - f / (r * od)) / (rate / rate_in)
498 * error = abs(1 - (f * rate_in) / (r * od * rate))
499 * Using the constants ratio = rate / rate_in and inv_ratio = rate_in / rate,
500 * error = abs((f * inv_ratio) / (r * od) - 1)
501 * This is the error used in evaluating parameters.
502 *
503 * r and od are four bits each, while f is six bits. Because r and od are
504 * multiplied together, instead of the full 256 values possible if both bits
505 * were used fully, there are only 97 distinct products. Combined with f, there
506 * are 6208 theoretical settings for the PLL. However, most of these settings
507 * can be ruled out immediately because they do not have the correct ratio.
508 *
509 * In addition to the constraint of approximating the desired ratio, parameters
510 * must also keep internal pll frequencies within acceptable ranges. The divided
511 * clock's minimum and maximum frequencies have a ratio of around 128. This
512 * leaves fairly substantial room to work with, especially since the only
513 * affected parameter is r. The VCO's minimum and maximum frequency have a ratio
514 * of 5, which is considerably more restrictive.
515 *
516 * The r and od factors are stored in a table. This is to make it easy to find
517 * the next-largest product. Some products have multiple factorizations, but
518 * only when one factor has at least a 2.5x ratio to the factors of the other
519 * factorization. This is because any smaller ratio would not make a difference
520 * when ensuring the VCO's frequency is within spec.
521 *
522 * Throughout the calculation function, fixed point arithmetic is used. Because
523 * the range of rate and rate_in may be up to 1.75 GHz, or around 2^30, 64-bit
524 * 32.32 fixed-point numbers are used to represent ratios. In general, to
525 * implement division, the numerator is first multiplied by 2^32. This gives a
526 * result where the whole number part is in the upper 32 bits, and the fraction
527 * is in the lower 32 bits.
528 *
529 * In general, rounding is done to the closest integer. This helps find the best
530 * approximation for the ratio. Rounding in one direction (e.g down) could cause
531 * the function to miss a better ratio with one of the parameters increased by
532 * one.
533 */
534
535/*
536 * The factors table was generated with the following python code:
537 *
538 * def p(x, y):
539 * return (1.0*x/y > 2.5) or (1.0*y/x > 2.5)
540 *
541 * factors = {}
542 * for i in range(1, 17):
543 * for j in range(1, 17):
544 * fs = factors.get(i*j) or []
545 * if fs == [] or all([
546 * (p(i, x) and p(i, y)) or (p(j, x) and p(j, y))
547 * for (x, y) in fs]):
548 * fs.append((i, j))
549 * factors[i*j] = fs
550 *
551 * for k, l in sorted(factors.items()):
552 * for v in l:
553 * print("PACK(%s, %s)," % v)
554 */
555#define PACK(r, od) (((((r) - 1) & 0xF) << 4) | (((od) - 1) & 0xF))
556#define UNPACK_R(val) ((((val) >> 4) & 0xF) + 1)
557#define UNPACK_OD(val) (((val) & 0xF) + 1)
558static const u8 factors[] = {
559 PACK(1, 1),
560 PACK(1, 2),
561 PACK(1, 3),
562 PACK(1, 4),
563 PACK(1, 5),
564 PACK(1, 6),
565 PACK(1, 7),
566 PACK(1, 8),
567 PACK(1, 9),
568 PACK(3, 3),
569 PACK(1, 10),
570 PACK(1, 11),
571 PACK(1, 12),
572 PACK(3, 4),
573 PACK(1, 13),
574 PACK(1, 14),
575 PACK(1, 15),
576 PACK(3, 5),
577 PACK(1, 16),
578 PACK(4, 4),
579 PACK(2, 9),
580 PACK(2, 10),
581 PACK(3, 7),
582 PACK(2, 11),
583 PACK(2, 12),
584 PACK(5, 5),
585 PACK(2, 13),
586 PACK(3, 9),
587 PACK(2, 14),
588 PACK(2, 15),
589 PACK(2, 16),
590 PACK(3, 11),
591 PACK(5, 7),
592 PACK(3, 12),
593 PACK(3, 13),
594 PACK(4, 10),
595 PACK(3, 14),
596 PACK(4, 11),
597 PACK(3, 15),
598 PACK(3, 16),
599 PACK(7, 7),
600 PACK(5, 10),
601 PACK(4, 13),
602 PACK(6, 9),
603 PACK(5, 11),
604 PACK(4, 14),
605 PACK(4, 15),
606 PACK(7, 9),
607 PACK(4, 16),
608 PACK(5, 13),
609 PACK(6, 11),
610 PACK(5, 14),
611 PACK(6, 12),
612 PACK(5, 15),
613 PACK(7, 11),
614 PACK(6, 13),
615 PACK(5, 16),
616 PACK(9, 9),
617 PACK(6, 14),
618 PACK(8, 11),
619 PACK(6, 15),
620 PACK(7, 13),
621 PACK(6, 16),
622 PACK(7, 14),
623 PACK(9, 11),
624 PACK(10, 10),
625 PACK(8, 13),
626 PACK(7, 15),
627 PACK(9, 12),
628 PACK(10, 11),
629 PACK(7, 16),
630 PACK(9, 13),
631 PACK(8, 15),
632 PACK(11, 11),
633 PACK(9, 14),
634 PACK(8, 16),
635 PACK(10, 13),
636 PACK(11, 12),
637 PACK(9, 15),
638 PACK(10, 14),
639 PACK(11, 13),
640 PACK(9, 16),
641 PACK(10, 15),
642 PACK(11, 14),
643 PACK(12, 13),
644 PACK(10, 16),
645 PACK(11, 15),
646 PACK(12, 14),
647 PACK(13, 13),
648 PACK(11, 16),
649 PACK(12, 15),
650 PACK(13, 14),
651 PACK(12, 16),
652 PACK(13, 15),
653 PACK(14, 14),
654 PACK(13, 16),
655 PACK(14, 15),
656 PACK(14, 16),
657 PACK(15, 15),
658 PACK(15, 16),
659 PACK(16, 16),
660};
661
662TEST_STATIC int k210_pll_calc_config(u32 rate, u32 rate_in,
663 struct k210_pll_config *best)
664{
665 int i;
666 s64 error, best_error;
667 u64 ratio, inv_ratio; /* fixed point 32.32 ratio of the rates */
668 u64 max_r;
669 u64 r, f, od;
670
671 /*
672 * Can't go over 1.75 GHz or under 21.25 MHz due to limitations on the
673 * VCO frequency. These are not the same limits as below because od can
674 * reduce the output frequency by 16.
675 */
676 if (rate > 1750000000 || rate < 21250000)
677 return -EINVAL;
678
679 /* Similar restrictions on the input rate */
680 if (rate_in > 1750000000 || rate_in < 13300000)
681 return -EINVAL;
682
683 ratio = DIV_ROUND_CLOSEST_ULL((u64)rate << 32, rate_in);
684 inv_ratio = DIV_ROUND_CLOSEST_ULL((u64)rate_in << 32, rate);
685 /* Can't increase by more than 64 or reduce by more than 256 */
686 if (rate > rate_in && ratio > (64ULL << 32))
687 return -EINVAL;
688 else if (rate <= rate_in && inv_ratio > (256ULL << 32))
689 return -EINVAL;
690
691 /*
692 * The divided clock (rate_in / r) must stay between 1.75 GHz and 13.3
693 * MHz. There is no minimum, since the only way to get a higher input
694 * clock than 26 MHz is to use a clock generated by a PLL. Because PLLs
695 * cannot output frequencies greater than 1.75 GHz, the minimum would
696 * never be greater than one.
697 */
698 max_r = DIV_ROUND_DOWN_ULL(rate_in, 13300000);
699
700 /* Variables get immediately incremented, so start at -1th iteration */
701 i = -1;
702 f = 0;
703 r = 0;
704 od = 0;
705 best_error = S64_MAX;
706 error = best_error;
707 /* do-while here so we always try at least one ratio */
708 do {
709 /*
710 * Whether we swapped r and od while enforcing frequency limits
711 */
712 bool swapped = false;
Sean Anderson49708742021-09-11 13:20:01 -0400713 /*
714 * Whether the intermediate frequencies are out-of-spec
715 */
716 bool out_of_spec;
Sean Andersonaf9f9972021-06-11 00:16:09 -0400717 u64 last_od = od;
718 u64 last_r = r;
719
720 /*
721 * Try the next largest value for f (or r and od) and
722 * recalculate the other parameters based on that
723 */
724 if (rate > rate_in) {
725 /*
726 * Skip factors of the same product if we already tried
727 * out that product
728 */
729 do {
730 i++;
731 r = UNPACK_R(factors[i]);
732 od = UNPACK_OD(factors[i]);
733 } while (i + 1 < ARRAY_SIZE(factors) &&
734 r * od == last_r * last_od);
735
736 /* Round close */
737 f = (r * od * ratio + BIT(31)) >> 32;
738 if (f > 64)
739 f = 64;
740 } else {
741 u64 tmp = ++f * inv_ratio;
742 bool round_up = !!(tmp & BIT(31));
743 u32 goal = (tmp >> 32) + round_up;
744 u32 err, last_err;
745
746 /* Get the next r/od pair in factors */
747 while (r * od < goal && i + 1 < ARRAY_SIZE(factors)) {
748 i++;
749 r = UNPACK_R(factors[i]);
750 od = UNPACK_OD(factors[i]);
751 }
752
753 /*
754 * This is a case of double rounding. If we rounded up
755 * above, we need to round down (in cases of ties) here.
756 * This prevents off-by-one errors resulting from
757 * choosing X+2 over X when X.Y rounds up to X+1 and
758 * there is no r * od = X+1. For the converse, when X.Y
759 * is rounded down to X, we should choose X+1 over X-1.
760 */
761 err = abs(r * od - goal);
762 last_err = abs(last_r * last_od - goal);
763 if (last_err < err || (round_up && last_err == err)) {
764 i--;
765 r = last_r;
766 od = last_od;
767 }
768 }
769
770 /*
771 * Enforce limits on internal clock frequencies. If we
772 * aren't in spec, try swapping r and od. If everything is
773 * in-spec, calculate the relative error.
774 */
Sean Anderson49708742021-09-11 13:20:01 -0400775again:
776 out_of_spec = false;
777 if (r > max_r) {
778 out_of_spec = true;
779 } else {
Sean Andersonaf9f9972021-06-11 00:16:09 -0400780 /*
Sean Anderson49708742021-09-11 13:20:01 -0400781 * There is no way to only divide once; we need
782 * to examine the frequency with and without the
783 * effect of od.
Sean Andersonaf9f9972021-06-11 00:16:09 -0400784 */
Sean Anderson49708742021-09-11 13:20:01 -0400785 u64 vco = DIV_ROUND_CLOSEST_ULL(rate_in * f, r);
Sean Andersonaf9f9972021-06-11 00:16:09 -0400786
Sean Anderson49708742021-09-11 13:20:01 -0400787 if (vco > 1750000000 || vco < 340000000)
Sean Andersonaf9f9972021-06-11 00:16:09 -0400788 out_of_spec = true;
Sean Anderson49708742021-09-11 13:20:01 -0400789 }
Sean Andersonaf9f9972021-06-11 00:16:09 -0400790
Sean Anderson49708742021-09-11 13:20:01 -0400791 if (out_of_spec) {
792 u64 new_r, new_od;
793
794 if (!swapped) {
795 u64 tmp = r;
796
797 r = od;
798 od = tmp;
799 swapped = true;
800 goto again;
Sean Andersonaf9f9972021-06-11 00:16:09 -0400801 }
802
Sean Anderson49708742021-09-11 13:20:01 -0400803 /*
804 * Try looking ahead to see if there are additional
805 * factors for the same product.
806 */
807 if (i + 1 < ARRAY_SIZE(factors)) {
808 i++;
809 new_r = UNPACK_R(factors[i]);
810 new_od = UNPACK_OD(factors[i]);
811 if (r * od == new_r * new_od) {
812 r = new_r;
813 od = new_od;
814 swapped = false;
815 goto again;
Sean Andersonaf9f9972021-06-11 00:16:09 -0400816 }
Sean Anderson49708742021-09-11 13:20:01 -0400817 i--;
Sean Andersonaf9f9972021-06-11 00:16:09 -0400818 }
819
Sean Anderson425c08f2021-09-11 13:20:03 -0400820 /*
821 * Try looking back to see if there is a worse ratio
822 * that we could try anyway
823 */
824 while (i > 0) {
825 i--;
826 new_r = UNPACK_R(factors[i]);
827 new_od = UNPACK_OD(factors[i]);
828 /*
829 * Don't loop over factors for the same product
830 * to avoid getting stuck because of the above
831 * clause
832 */
833 if (r * od != new_r * new_od) {
834 if (new_r * new_od > last_r * last_od) {
835 r = new_r;
836 od = new_od;
837 swapped = false;
838 goto again;
839 }
840 break;
841 }
842 }
843
Sean Anderson49708742021-09-11 13:20:01 -0400844 /* We ran out of things to try */
845 continue;
846 }
Sean Andersonaf9f9972021-06-11 00:16:09 -0400847
Sean Anderson49708742021-09-11 13:20:01 -0400848 error = DIV_ROUND_CLOSEST_ULL(f * inv_ratio, r * od);
849 /* The lower 16 bits are spurious */
Heinrich Schuchardte77ef0b2022-10-16 18:12:32 +0200850 error = abs64((error - BIT_ULL(32))) >> 16;
Sean Anderson49708742021-09-11 13:20:01 -0400851
852 if (error < best_error) {
853 best->r = r;
854 best->f = f;
855 best->od = od;
856 best_error = error;
Sean Andersonaf9f9972021-06-11 00:16:09 -0400857 }
858 } while (f < 64 && i + 1 < ARRAY_SIZE(factors) && error != 0);
859
Sean Anderson49708742021-09-11 13:20:01 -0400860 log_debug("best error %lld\n", best_error);
Sean Andersonaf9f9972021-06-11 00:16:09 -0400861 if (best_error == S64_MAX)
862 return -EINVAL;
863
Sean Andersonaf9f9972021-06-11 00:16:09 -0400864 return 0;
865}
866
867static ulong k210_pll_set_rate(struct k210_clk_priv *priv, int id, ulong rate,
868 ulong rate_in)
869{
870 int err;
871 const struct k210_pll_params *pll = &k210_plls[id];
872 struct k210_pll_config config = {};
873 u32 reg;
Sean Andersondf79e2b2021-06-11 00:16:12 -0400874 ulong calc_rate;
Sean Andersonaf9f9972021-06-11 00:16:09 -0400875
Sean Andersonaf9f9972021-06-11 00:16:09 -0400876 err = k210_pll_calc_config(rate, rate_in, &config);
877 if (err)
878 return err;
879 log_debug("Got r=%u f=%u od=%u\n", config.r, config.f, config.od);
880
Sean Andersondf79e2b2021-06-11 00:16:12 -0400881 /* Don't bother setting the rate if we're already at that rate */
882 calc_rate = DIV_ROUND_DOWN_ULL(((u64)rate_in) * config.f,
883 config.r * config.od);
884 if (calc_rate == k210_pll_get_rate(priv, id, rate))
885 return calc_rate;
886
Sean Andersonaf9f9972021-06-11 00:16:09 -0400887 k210_pll_disable(priv, id);
888
889 reg = readl(priv->base + pll->off);
890 reg &= ~K210_PLL_CLKR
891 & ~K210_PLL_CLKF
892 & ~K210_PLL_CLKOD
893 & ~K210_PLL_BWADJ;
894 reg |= FIELD_PREP(K210_PLL_CLKR, config.r - 1)
895 | FIELD_PREP(K210_PLL_CLKF, config.f - 1)
896 | FIELD_PREP(K210_PLL_CLKOD, config.od - 1)
897 | FIELD_PREP(K210_PLL_BWADJ, config.f - 1);
898 writel(reg, priv->base + pll->off);
899
Sean Andersondf79e2b2021-06-11 00:16:12 -0400900 k210_pll_enable(priv, id);
Sean Andersonaf9f9972021-06-11 00:16:09 -0400901
902 serial_setbrg();
903 return k210_pll_get_rate(priv, id, rate);
904}
905#else
906static ulong k210_pll_set_rate(struct k210_clk_priv *priv, int id, ulong rate,
907 ulong rate_in)
908{
909 return -ENOSYS;
910}
911#endif /* CONFIG_CLK_K210_SET_RATE */
912
913static ulong k210_pll_get_rate(struct k210_clk_priv *priv, int id,
914 ulong rate_in)
915{
916 u64 r, f, od;
917 u32 reg = readl(priv->base + k210_plls[id].off);
918
Sean Anderson54d5d2d2021-09-11 13:20:00 -0400919 if (reg & K210_PLL_BYPASS)
Sean Andersonaf9f9972021-06-11 00:16:09 -0400920 return rate_in;
921
922 if (!(reg & K210_PLL_PWRD))
923 return 0;
924
925 r = FIELD_GET(K210_PLL_CLKR, reg) + 1;
926 f = FIELD_GET(K210_PLL_CLKF, reg) + 1;
927 od = FIELD_GET(K210_PLL_CLKOD, reg) + 1;
928
929 return DIV_ROUND_DOWN_ULL(((u64)rate_in) * f, r * od);
930}
931
932/*
933 * Wait for the PLL to be locked. If the PLL is not locked, try clearing the
934 * slip before retrying
935 */
936static void k210_pll_waitfor_lock(struct k210_clk_priv *priv, int id)
937{
938 const struct k210_pll_params *pll = &k210_plls[id];
939 u32 mask = (BIT(pll->width) - 1) << pll->shift;
940
941 while (true) {
942 u32 reg = readl(priv->base + K210_SYSCTL_PLL_LOCK);
943
944 if ((reg & mask) == mask)
945 break;
946
947 reg |= BIT(pll->shift + K210_PLL_CLEAR_SLIP);
948 writel(reg, priv->base + K210_SYSCTL_PLL_LOCK);
949 }
950}
951
Sean Anderson612a8332021-06-11 00:16:10 -0400952static bool k210_pll_enabled(u32 reg)
953{
954 return (reg & K210_PLL_PWRD) && (reg & K210_PLL_EN) &&
955 !(reg & K210_PLL_RESET);
956}
957
Sean Andersonaf9f9972021-06-11 00:16:09 -0400958/* Adapted from sysctl_pll_enable */
959static int k210_pll_enable(struct k210_clk_priv *priv, int id)
960{
961 const struct k210_pll_params *pll = &k210_plls[id];
962 u32 reg = readl(priv->base + pll->off);
963
Sean Anderson612a8332021-06-11 00:16:10 -0400964 if (k210_pll_enabled(reg))
Sean Andersonaf9f9972021-06-11 00:16:09 -0400965 return 0;
966
967 reg |= K210_PLL_PWRD;
968 writel(reg, priv->base + pll->off);
969
970 /* Ensure reset is low before asserting it */
971 reg &= ~K210_PLL_RESET;
972 writel(reg, priv->base + pll->off);
973 reg |= K210_PLL_RESET;
974 writel(reg, priv->base + pll->off);
975 nop();
976 nop();
977 reg &= ~K210_PLL_RESET;
978 writel(reg, priv->base + pll->off);
979
980 k210_pll_waitfor_lock(priv, id);
981
982 reg &= ~K210_PLL_BYPASS;
983 reg |= K210_PLL_EN;
984 writel(reg, priv->base + pll->off);
985
986 return 0;
987}
988
989static int k210_pll_disable(struct k210_clk_priv *priv, int id)
990{
991 const struct k210_pll_params *pll = &k210_plls[id];
992 u32 reg = readl(priv->base + pll->off);
993
994 /*
995 * Bypassing before powering off is important so child clocks don't stop
996 * working. This is especially important for pll0, the indirect parent
997 * of the cpu clock.
998 */
999 reg |= K210_PLL_BYPASS;
1000 writel(reg, priv->base + pll->off);
1001
1002 reg &= ~K210_PLL_PWRD;
1003 reg &= ~K210_PLL_EN;
1004 writel(reg, priv->base + pll->off);
1005 return 0;
1006}
1007
Sean Anderson609bd602021-06-11 00:16:08 -04001008static u32 k210_clk_readl(struct k210_clk_priv *priv, u8 off, u8 shift,
1009 u8 width)
Sean Andersonf9c7d4f2020-06-24 06:41:11 -04001010{
Sean Anderson609bd602021-06-11 00:16:08 -04001011 u32 reg = readl(priv->base + off);
Sean Andersonf9c7d4f2020-06-24 06:41:11 -04001012
Sean Anderson609bd602021-06-11 00:16:08 -04001013 return (reg >> shift) & (BIT(width) - 1);
Sean Andersonf9c7d4f2020-06-24 06:41:11 -04001014}
1015
Sean Anderson609bd602021-06-11 00:16:08 -04001016static void k210_clk_writel(struct k210_clk_priv *priv, u8 off, u8 shift,
1017 u8 width, u32 val)
Sean Andersonf9c7d4f2020-06-24 06:41:11 -04001018{
Sean Anderson609bd602021-06-11 00:16:08 -04001019 u32 reg = readl(priv->base + off);
1020 u32 mask = (BIT(width) - 1) << shift;
Sean Andersonf9c7d4f2020-06-24 06:41:11 -04001021
Sean Anderson609bd602021-06-11 00:16:08 -04001022 reg &= ~mask;
1023 reg |= mask & (val << shift);
1024 writel(reg, priv->base + off);
Sean Andersonf9c7d4f2020-06-24 06:41:11 -04001025}
1026
Sean Anderson609bd602021-06-11 00:16:08 -04001027static int k210_clk_get_parent(struct k210_clk_priv *priv, int id)
Sean Andersonf9c7d4f2020-06-24 06:41:11 -04001028{
Sean Anderson609bd602021-06-11 00:16:08 -04001029 u32 sel;
1030 const struct k210_mux_params *mux;
Sean Andersonf9c7d4f2020-06-24 06:41:11 -04001031
Sean Anderson609bd602021-06-11 00:16:08 -04001032 if (!(k210_clks[id].flags & K210_CLKF_MUX))
1033 return k210_clks[id].parent;
1034 mux = &k210_muxes[k210_clks[id].mux];
Sean Andersonf9c7d4f2020-06-24 06:41:11 -04001035
Sean Anderson609bd602021-06-11 00:16:08 -04001036 sel = k210_clk_readl(priv, mux->off, mux->shift, mux->width);
1037 assert(sel < mux->num_parents);
1038 return mux->parents[sel];
Sean Andersonf9c7d4f2020-06-24 06:41:11 -04001039}
1040
Sean Anderson609bd602021-06-11 00:16:08 -04001041static ulong do_k210_clk_get_rate(struct k210_clk_priv *priv, int id)
Sean Andersonf9c7d4f2020-06-24 06:41:11 -04001042{
Sean Anderson609bd602021-06-11 00:16:08 -04001043 int parent;
1044 u32 val;
1045 ulong parent_rate;
1046 const struct k210_div_params *div;
Sean Andersonf9c7d4f2020-06-24 06:41:11 -04001047
Sean Anderson609bd602021-06-11 00:16:08 -04001048 if (id == K210_CLK_IN0)
1049 return clk_get_rate(&priv->in0);
Sean Andersonf9c7d4f2020-06-24 06:41:11 -04001050
Sean Anderson609bd602021-06-11 00:16:08 -04001051 parent = k210_clk_get_parent(priv, id);
1052 parent_rate = do_k210_clk_get_rate(priv, parent);
Sean Anderson54d5d2d2021-09-11 13:20:00 -04001053 if (IS_ERR_VALUE(parent_rate))
1054 return parent_rate;
Sean Andersonf9c7d4f2020-06-24 06:41:11 -04001055
Sean Anderson609bd602021-06-11 00:16:08 -04001056 if (k210_clks[id].flags & K210_CLKF_PLL)
1057 return k210_pll_get_rate(priv, k210_clks[id].pll, parent_rate);
1058
1059 if (k210_clks[id].div == K210_CLK_DIV_NONE)
1060 return parent_rate;
1061 div = &k210_divs[k210_clks[id].div];
1062
1063 if (div->type == K210_DIV_FIXED)
1064 return parent_rate / div->div;
1065
1066 val = k210_clk_readl(priv, div->off, div->shift, div->width);
1067 switch (div->type) {
1068 case K210_DIV_ONE:
1069 return parent_rate / (val + 1);
1070 case K210_DIV_EVEN:
1071 return parent_rate / 2 / (val + 1);
1072 case K210_DIV_POWER:
1073 /* This is ACLK, which has no divider on IN0 */
1074 if (parent == K210_CLK_IN0)
1075 return parent_rate;
1076 return parent_rate / (2 << val);
1077 default:
1078 assert(false);
1079 return -EINVAL;
1080 };
Sean Andersonf9c7d4f2020-06-24 06:41:11 -04001081}
1082
Sean Anderson609bd602021-06-11 00:16:08 -04001083static ulong k210_clk_get_rate(struct clk *clk)
Sean Andersonf9c7d4f2020-06-24 06:41:11 -04001084{
Sean Anderson609bd602021-06-11 00:16:08 -04001085 return do_k210_clk_get_rate(dev_get_priv(clk->dev), clk->id);
1086}
Sean Andersonf9c7d4f2020-06-24 06:41:11 -04001087
Sean Anderson609bd602021-06-11 00:16:08 -04001088static int do_k210_clk_set_parent(struct k210_clk_priv *priv, int id, int new)
1089{
1090 int i;
1091 const struct k210_mux_params *mux;
Sean Andersonf9c7d4f2020-06-24 06:41:11 -04001092
Sean Anderson609bd602021-06-11 00:16:08 -04001093 if (!(k210_clks[id].flags & K210_CLKF_MUX))
1094 return -ENOSYS;
1095 mux = &k210_muxes[k210_clks[id].mux];
1096
1097 for (i = 0; i < mux->num_parents; i++) {
1098 if (mux->parents[i] == new) {
1099 k210_clk_writel(priv, mux->off, mux->shift, mux->width,
1100 i);
1101 return 0;
1102 }
1103 }
1104 return -EINVAL;
1105}
1106
1107static int k210_clk_set_parent(struct clk *clk, struct clk *parent)
1108{
1109 return do_k210_clk_set_parent(dev_get_priv(clk->dev), clk->id,
1110 parent->id);
1111}
1112
Sean Anderson29e30672021-06-11 00:16:11 -04001113static ulong k210_clk_set_rate(struct clk *clk, unsigned long rate)
1114{
1115 int parent, ret, err;
1116 ulong rate_in, val;
1117 const struct k210_div_params *div;
1118 struct k210_clk_priv *priv = dev_get_priv(clk->dev);
1119
1120 if (clk->id == K210_CLK_IN0)
1121 return clk_set_rate(&priv->in0, rate);
1122
1123 parent = k210_clk_get_parent(priv, clk->id);
1124 rate_in = do_k210_clk_get_rate(priv, parent);
Sean Anderson54d5d2d2021-09-11 13:20:00 -04001125 if (IS_ERR_VALUE(rate_in))
1126 return rate_in;
Sean Anderson29e30672021-06-11 00:16:11 -04001127
1128 log_debug("id=%ld rate=%lu rate_in=%lu\n", clk->id, rate, rate_in);
1129
1130 if (clk->id == K210_CLK_PLL0) {
1131 /* Bypass ACLK so the CPU keeps going */
1132 ret = do_k210_clk_set_parent(priv, K210_CLK_ACLK, K210_CLK_IN0);
1133 if (ret)
1134 return ret;
1135 } else if (clk->id == K210_CLK_PLL1 && gd->flags & GD_FLG_RELOC) {
1136 /*
1137 * We can't bypass the AI clock like we can ACLK, and after
1138 * relocation we are using the AI ram.
1139 */
1140 return -EPERM;
1141 }
1142
1143 if (k210_clks[clk->id].flags & K210_CLKF_PLL) {
1144 ret = k210_pll_set_rate(priv, k210_clks[clk->id].pll, rate,
1145 rate_in);
1146 if (!IS_ERR_VALUE(ret) && clk->id == K210_CLK_PLL0) {
1147 /*
1148 * This may have the side effect of reparenting ACLK,
1149 * but I don't really want to keep track of what the old
1150 * parent was.
1151 */
1152 err = do_k210_clk_set_parent(priv, K210_CLK_ACLK,
1153 K210_CLK_PLL0);
1154 if (err)
1155 return err;
1156 }
1157 return ret;
1158 }
1159
1160 if (k210_clks[clk->id].div == K210_CLK_DIV_NONE)
1161 return -ENOSYS;
1162 div = &k210_divs[k210_clks[clk->id].div];
1163
1164 switch (div->type) {
1165 case K210_DIV_ONE:
1166 val = DIV_ROUND_CLOSEST_ULL((u64)rate_in, rate);
1167 val = val ? val - 1 : 0;
1168 break;
1169 case K210_DIV_EVEN:
1170 val = DIV_ROUND_CLOSEST_ULL((u64)rate_in, 2 * rate);
1171 break;
1172 case K210_DIV_POWER:
1173 /* This is ACLK, which has no divider on IN0 */
1174 if (parent == K210_CLK_IN0)
1175 return -ENOSYS;
1176
1177 val = DIV_ROUND_CLOSEST_ULL((u64)rate_in, rate);
1178 val = __ffs(val);
1179 break;
1180 default:
1181 assert(false);
1182 return -EINVAL;
1183 };
1184
1185 val = val ? val - 1 : 0;
1186 k210_clk_writel(priv, div->off, div->shift, div->width, val);
1187 return do_k210_clk_get_rate(priv, clk->id);
1188}
1189
Sean Anderson609bd602021-06-11 00:16:08 -04001190static int k210_clk_endisable(struct k210_clk_priv *priv, int id, bool enable)
1191{
1192 int parent = k210_clk_get_parent(priv, id);
1193 const struct k210_gate_params *gate;
1194
1195 if (id == K210_CLK_IN0) {
1196 if (enable)
1197 return clk_enable(&priv->in0);
1198 else
1199 return clk_disable(&priv->in0);
Sean Andersonf9c7d4f2020-06-24 06:41:11 -04001200 }
1201
Sean Anderson609bd602021-06-11 00:16:08 -04001202 /* Only recursively enable clocks since we don't track refcounts */
1203 if (enable) {
1204 int ret = k210_clk_endisable(priv, parent, true);
1205
1206 if (ret && ret != -ENOSYS)
1207 return ret;
Sean Andersonf9c7d4f2020-06-24 06:41:11 -04001208 }
1209
Sean Anderson609bd602021-06-11 00:16:08 -04001210 if (k210_clks[id].flags & K210_CLKF_PLL) {
1211 if (enable)
1212 return k210_pll_enable(priv, k210_clks[id].pll);
1213 else
1214 return k210_pll_disable(priv, k210_clks[id].pll);
Sean Andersonf9c7d4f2020-06-24 06:41:11 -04001215 }
1216
Sean Anderson609bd602021-06-11 00:16:08 -04001217 if (k210_clks[id].gate == K210_CLK_GATE_NONE)
1218 return -ENOSYS;
1219 gate = &k210_gates[k210_clks[id].gate];
Sean Andersonf9c7d4f2020-06-24 06:41:11 -04001220
Sean Anderson609bd602021-06-11 00:16:08 -04001221 k210_clk_writel(priv, gate->off, gate->bit_idx, 1, enable);
Sean Anderson09ad08f2021-04-08 22:13:08 -04001222 return 0;
1223}
Sean Andersonf9c7d4f2020-06-24 06:41:11 -04001224
Sean Anderson609bd602021-06-11 00:16:08 -04001225static int k210_clk_enable(struct clk *clk)
1226{
1227 return k210_clk_endisable(dev_get_priv(clk->dev), clk->id, true);
1228}
1229
1230static int k210_clk_disable(struct clk *clk)
1231{
1232 return k210_clk_endisable(dev_get_priv(clk->dev), clk->id, false);
1233}
1234
1235static int k210_clk_request(struct clk *clk)
1236{
1237 if (clk->id >= ARRAY_SIZE(k210_clks))
1238 return -EINVAL;
1239 return 0;
1240}
1241
Simon Glass8dd86202023-02-05 15:36:26 -07001242#if IS_ENABLED(CONFIG_CMD_CLK)
Sean Anderson612a8332021-06-11 00:16:10 -04001243static char show_enabled(struct k210_clk_priv *priv, int id)
1244{
1245 bool enabled;
1246
1247 if (k210_clks[id].flags & K210_CLKF_PLL) {
1248 const struct k210_pll_params *pll =
1249 &k210_plls[k210_clks[id].pll];
1250
1251 enabled = k210_pll_enabled(readl(priv->base + pll->off));
1252 } else if (k210_clks[id].gate == K210_CLK_GATE_NONE) {
1253 return '-';
1254 } else {
1255 const struct k210_gate_params *gate =
1256 &k210_gates[k210_clks[id].gate];
1257
1258 enabled = k210_clk_readl(priv, gate->off, gate->bit_idx, 1);
1259 }
1260
1261 return enabled ? 'y' : 'n';
1262}
1263
1264static void show_clks(struct k210_clk_priv *priv, int id, int depth)
1265{
1266 int i;
1267
1268 for (i = 0; i < ARRAY_SIZE(k210_clks); i++) {
1269 if (k210_clk_get_parent(priv, i) != id)
1270 continue;
1271
1272 printf(" %-9lu %-7c %*s%s\n", do_k210_clk_get_rate(priv, i),
1273 show_enabled(priv, i), depth * 4, "",
1274 k210_clks[i].name);
1275
1276 show_clks(priv, i, depth + 1);
1277 }
1278}
1279
Igor Prusovbc3e3132023-11-09 13:55:15 +03001280static void k210_clk_dump(struct udevice *dev)
Sean Anderson612a8332021-06-11 00:16:10 -04001281{
Sean Anderson612a8332021-06-11 00:16:10 -04001282 struct k210_clk_priv *priv;
1283
Sean Anderson612a8332021-06-11 00:16:10 -04001284 priv = dev_get_priv(dev);
1285
1286 puts(" Rate Enabled Name\n");
1287 puts("------------------------\n");
1288 printf(" %-9lu %-7c %*s%s\n", clk_get_rate(&priv->in0), 'y', 0, "",
1289 priv->in0.dev->name);
1290 show_clks(priv, K210_CLK_IN0, 1);
Sean Anderson612a8332021-06-11 00:16:10 -04001291}
1292#endif
Igor Prusov77beaad2023-11-09 13:55:11 +03001293
1294static const struct clk_ops k210_clk_ops = {
1295 .request = k210_clk_request,
1296 .set_rate = k210_clk_set_rate,
1297 .get_rate = k210_clk_get_rate,
1298 .set_parent = k210_clk_set_parent,
1299 .enable = k210_clk_enable,
1300 .disable = k210_clk_disable,
Igor Prusovbc3e3132023-11-09 13:55:15 +03001301#if IS_ENABLED(CONFIG_CMD_CLK)
1302 .dump = k210_clk_dump,
1303#endif
Igor Prusov77beaad2023-11-09 13:55:11 +03001304};
1305
1306static int k210_clk_probe(struct udevice *dev)
1307{
1308 int ret;
1309 struct k210_clk_priv *priv = dev_get_priv(dev);
1310
1311 priv->base = dev_read_addr_ptr(dev_get_parent(dev));
1312 if (!priv->base)
1313 return -EINVAL;
1314
1315 ret = clk_get_by_index(dev, 0, &priv->in0);
1316 if (ret)
1317 return ret;
1318
1319 /*
1320 * Force setting defaults, even before relocation. This is so we can
1321 * set the clock rate for PLL1 before we relocate into aisram.
1322 */
1323 if (!(gd->flags & GD_FLG_RELOC))
1324 clk_set_defaults(dev, CLK_DEFAULTS_POST_FORCE);
1325
1326 return 0;
1327}
1328
1329static const struct udevice_id k210_clk_ids[] = {
1330 { .compatible = "canaan,k210-clk" },
1331 { },
1332};
1333
1334U_BOOT_DRIVER(k210_clk) = {
1335 .name = "k210_clk",
1336 .id = UCLASS_CLK,
1337 .of_match = k210_clk_ids,
1338 .ops = &k210_clk_ops,
1339 .probe = k210_clk_probe,
1340 .priv_auto = sizeof(struct k210_clk_priv),
1341};