rk_cru.h revision 1.11 1 /* $NetBSD: rk_cru.h,v 1.11 2022/08/23 05:39:06 ryo Exp $ */
2
3 /*-
4 * Copyright (c) 2018 Jared McNeill <jmcneill (at) invisible.ca>
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29 #ifndef _ARM_RK_CRU_H
30 #define _ARM_RK_CRU_H
31
32 #include <dev/clk/clk_backend.h>
33 #include <dev/fdt/syscon.h>
34
35 struct rk_cru_softc;
36 struct rk_cru_clk;
37
38 /*
39 * Clocks
40 */
41
42 enum rk_cru_clktype {
43 RK_CRU_UNKNOWN,
44 RK_CRU_PLL,
45 RK_CRU_ARM,
46 RK_CRU_COMPOSITE,
47 RK_CRU_GATE,
48 RK_CRU_MUX,
49 };
50
51 /* PLL clocks */
52
53 struct rk_cru_pll_rate {
54 u_int rate;
55 union {
56 struct { /* RK3328,3399 */
57 u_int refdiv;
58 u_int fbdiv;
59 u_int postdiv1;
60 u_int postdiv2;
61 u_int dsmpd;
62 u_int fracdiv;
63 };
64 struct { /* RK3588 */
65 u_int p;
66 u_int m;
67 u_int s;
68 u_int k;
69 };
70 };
71 };
72
73 #define RK_PLL_RATE(_rate, _refdiv, _fbdiv, _postdiv1, _postdiv2, _dsmpd, _fracdiv) \
74 { \
75 .rate = (_rate), \
76 .refdiv = (_refdiv), \
77 .fbdiv = (_fbdiv), \
78 .postdiv1 = (_postdiv1), \
79 .postdiv2 = (_postdiv2), \
80 .dsmpd = (_dsmpd), \
81 .fracdiv = (_fracdiv), \
82 }
83
84 #define RK3588_PLL_RATE(_rate, _p, _m, _s, _k) \
85 { \
86 .rate = (_rate), \
87 .p = (_p), \
88 .m = (_m), \
89 .s = (_s), \
90 .k = (_k), \
91 }
92
93 struct rk_cru_pll {
94 bus_size_t con_base;
95 bus_size_t mode_reg;
96 uint32_t mode_mask;
97 uint32_t lock_mask;
98 const struct rk_cru_pll_rate *rates;
99 u_int nrates;
100 const char **parents;
101 u_int nparents;
102 u_int flags;
103 #define RK_PLL_RK3288 0x01
104 #define RK_PLL_RK3588 0x02
105 };
106
107 u_int rk_cru_pll_get_rate(struct rk_cru_softc *, struct rk_cru_clk *);
108 int rk_cru_pll_set_rate(struct rk_cru_softc *, struct rk_cru_clk *, u_int);
109 const char *rk_cru_pll_get_parent(struct rk_cru_softc *, struct rk_cru_clk *);
110
111 #define RK_PLL_FLAGS(_id, _name, _parents, _con_base, _mode_reg, _mode_mask, _lock_mask, _rates, _flags) \
112 { \
113 .id = (_id), \
114 .type = RK_CRU_PLL, \
115 .base.name = (_name), \
116 .base.flags = 0, \
117 .u.pll.parents = (_parents), \
118 .u.pll.nparents = __arraycount(_parents), \
119 .u.pll.con_base = (_con_base), \
120 .u.pll.mode_reg = (_mode_reg), \
121 .u.pll.mode_mask = (_mode_mask), \
122 .u.pll.lock_mask = (_lock_mask), \
123 .u.pll.rates = (_rates), \
124 .u.pll.nrates = __arraycount(_rates), \
125 .u.pll.flags = _flags, \
126 .get_rate = rk_cru_pll_get_rate, \
127 .set_rate = rk_cru_pll_set_rate, \
128 .get_parent = rk_cru_pll_get_parent, \
129 }
130
131 #define RK_PLL(_id, _name, _parents, _con_base, _mode_reg, _mode_mask, _lock_mask, _rates) \
132 RK_PLL_FLAGS(_id, _name, _parents, _con_base, _mode_reg, _mode_mask, _lock_mask, _rates, 0)
133
134 #define RK3288_PLL(_id, _name, _parents, _con_base, _mode_reg, _mode_mask, _lock_mask, _rates) \
135 RK_PLL_FLAGS(_id, _name, _parents, _con_base, _mode_reg, _mode_mask, _lock_mask, _rates, RK_PLL_RK3288)
136
137 #define RK3588_PLL(_id, _name, _parents, _con_base, _mode_reg, _mode_mask, _lock_mask, _rates) \
138 RK_PLL_FLAGS(_id, _name, _parents, _con_base, _mode_reg, _mode_mask, _lock_mask, _rates, RK_PLL_RK3588)
139
140 /* ARM clocks */
141
142 struct rk_cru_arm_rate {
143 u_int rate;
144 u_int div;
145 };
146
147 #define RK_ARM_RATE(_rate, _div) \
148 { \
149 .rate = (_rate), \
150 .div = (_div), \
151 }
152
153 struct rk_regmaskval {
154 bus_size_t reg;
155 uint32_t mask;
156 uint32_t val;
157 };
158
159 struct rk_cru_cpu_rate {
160 u_int rate;
161 struct rk_regmaskval divs[4];
162 struct rk_regmaskval pre_muxs[3];
163 struct rk_regmaskval post_muxs[3];
164 };
165
166 struct rk_regmask {
167 bus_size_t reg;
168 uint32_t mask;
169 };
170
171 struct rk_cru_arm {
172 bus_size_t mux_reg;
173 uint32_t mux_mask;
174 u_int mux_main;
175 u_int mux_alt;
176 struct rk_regmask divs[4];
177 const char **parents;
178 u_int nparents;
179 const struct rk_cru_arm_rate *rates;
180 const struct rk_cru_cpu_rate *cpurates;
181 u_int nrates;
182 };
183
184 u_int rk_cru_arm_get_rate(struct rk_cru_softc *, struct rk_cru_clk *);
185 int rk_cru_arm_set_rate(struct rk_cru_softc *, struct rk_cru_clk *, u_int);
186 int rk_cru_arm_set_rate(struct rk_cru_softc *, struct rk_cru_clk *, u_int);
187 const char *rk_cru_arm_get_parent(struct rk_cru_softc *, struct rk_cru_clk *);
188 int rk_cru_arm_set_parent(struct rk_cru_softc *, struct rk_cru_clk *, const char *);
189
190 #define RK_ARM(_id, _name, _parents, _reg, _mux_mask, _mux_main, _mux_alt, _div_mask, _rates) \
191 { \
192 .id = (_id), \
193 .type = RK_CRU_ARM, \
194 .base.name = (_name), \
195 .base.flags = 0, \
196 .u.arm.parents = (_parents), \
197 .u.arm.nparents = __arraycount(_parents), \
198 .u.arm.mux_reg = (_reg), \
199 .u.arm.mux_mask = (_mux_mask), \
200 .u.arm.mux_main = (_mux_main), \
201 .u.arm.mux_alt = (_mux_alt), \
202 .u.arm.divs[0].reg = (_reg), \
203 .u.arm.divs[0].mask = (_div_mask), \
204 .u.arm.rates = (_rates), \
205 .u.arm.nrates = __arraycount(_rates), \
206 .get_rate = rk_cru_arm_get_rate, \
207 .set_rate = rk_cru_arm_set_rate, \
208 .get_parent = rk_cru_arm_get_parent, \
209 .set_parent = rk_cru_arm_set_parent, \
210 }
211
212 #define _RK_CPU_COMMON_INITIALIZER(_id, _name, _parents, \
213 _mux_reg, _mux_mask, _mux_main, _mux_alt, _cpurates) \
214 .id = (_id), \
215 .type = RK_CRU_ARM, \
216 .base.name = (_name), \
217 .base.flags = 0, \
218 .u.arm.parents = (_parents), \
219 .u.arm.nparents = __arraycount(_parents), \
220 .u.arm.mux_reg = (_mux_reg), \
221 .u.arm.mux_mask = (_mux_mask), \
222 .u.arm.mux_main = (_mux_main), \
223 .u.arm.mux_alt = (_mux_alt), \
224 .u.arm.cpurates = (_cpurates), \
225 .u.arm.nrates = __arraycount(_cpurates), \
226 .get_rate = rk_cru_arm_get_rate, \
227 .set_rate = rk_cru_arm_set_rate, \
228 .get_parent = rk_cru_arm_get_parent, \
229 .set_parent = rk_cru_arm_set_parent
230
231 #define RK_CPU(_id, _name, _parents, _mux_reg, _mux_mask, _mux_main, _mux_alt, \
232 _div_reg, _div_mask, _cpurates) \
233 { \
234 _RK_CPU_COMMON_INITIALIZER(_id, _name, _parents, \
235 _mux_reg, _mux_mask, _mux_main, _mux_alt,_cpurates),\
236 .u.arm.divs[0].reg = (_div_reg), \
237 .u.arm.divs[0].mask = (_div_mask), \
238 }
239
240 #define RK_CPU_CORE2(_id, _name, _parents, \
241 _mux_reg, _mux_mask, _mux_main, _mux_alt, \
242 _div0_reg, _div0_mask, \
243 _div1_reg, _div1_mask, \
244 _cpurates) \
245 { \
246 _RK_CPU_COMMON_INITIALIZER(_id, _name, _parents, \
247 _mux_reg, _mux_mask, _mux_main, _mux_alt,_cpurates),\
248 .u.arm.divs[0].reg = (_div0_reg), \
249 .u.arm.divs[0].mask = (_div0_mask), \
250 .u.arm.divs[1].reg = (_div1_reg), \
251 .u.arm.divs[1].mask = (_div1_mask), \
252 }
253
254 #define RK_CPU_CORE4(_id, _name, _parents, \
255 _mux_reg, _mux_mask, _mux_main, _mux_alt, \
256 _div0_reg, _div0_mask, \
257 _div1_reg, _div1_mask, \
258 _div2_reg, _div2_mask, \
259 _div3_reg, _div3_mask, \
260 _cpurates) \
261 { \
262 _RK_CPU_COMMON_INITIALIZER(_id, _name, _parents, \
263 _mux_reg, _mux_mask, _mux_main, _mux_alt,_cpurates),\
264 .u.arm.divs[0].reg = (_div0_reg), \
265 .u.arm.divs[0].mask = (_div0_mask), \
266 .u.arm.divs[1].reg = (_div1_reg), \
267 .u.arm.divs[1].mask = (_div1_mask), \
268 .u.arm.divs[2].reg = (_div2_reg), \
269 .u.arm.divs[2].mask = (_div2_mask), \
270 .u.arm.divs[3].reg = (_div3_reg), \
271 .u.arm.divs[3].mask = (_div3_mask), \
272 }
273
274 /* Composite clocks */
275
276 struct rk_cru_composite {
277 bus_size_t muxdiv_reg;
278 uint32_t mux_mask;
279 uint32_t div_mask;
280 bus_size_t gate_reg;
281 uint32_t gate_mask;
282 bus_size_t frac_reg;
283 const char **parents;
284 u_int nparents;
285 u_int flags;
286 #define RK_COMPOSITE_ROUND_DOWN 0x01
287 #define RK_COMPOSITE_SET_RATE_PARENT 0x02
288 #define RK_COMPOSITE_FRACDIV 0x04
289 #define RK_COMPOSITE_POW2 0x08
290 #define RK_COMPOSITE_HALFDIV 0x10
291 };
292
293 int rk_cru_composite_enable(struct rk_cru_softc *, struct rk_cru_clk *, int);
294 u_int rk_cru_composite_get_rate(struct rk_cru_softc *, struct rk_cru_clk *);
295 int rk_cru_composite_set_rate(struct rk_cru_softc *, struct rk_cru_clk *, u_int);
296 const char *rk_cru_composite_get_parent(struct rk_cru_softc *, struct rk_cru_clk *);
297 int rk_cru_composite_set_parent(struct rk_cru_softc *, struct rk_cru_clk *, const char *);
298
299 #define _RK_COMPOSITE_INIT(_id, _name, _parents, _muxdiv_reg, _mux_mask, _div_mask, _gate_reg, _gate_mask, _frac_reg, _flags) \
300 { \
301 .id = (_id), \
302 .type = RK_CRU_COMPOSITE, \
303 .base.name = (_name), \
304 .base.flags = 0, \
305 .u.composite.parents = (_parents), \
306 .u.composite.nparents = __arraycount(_parents), \
307 .u.composite.muxdiv_reg = (_muxdiv_reg), \
308 .u.composite.mux_mask = (_mux_mask), \
309 .u.composite.div_mask = (_div_mask), \
310 .u.composite.gate_reg = (_gate_reg), \
311 .u.composite.gate_mask = (_gate_mask), \
312 .u.composite.frac_reg = (_frac_reg), \
313 .u.composite.flags = (_flags), \
314 .enable = rk_cru_composite_enable, \
315 .get_rate = rk_cru_composite_get_rate, \
316 .set_rate = rk_cru_composite_set_rate, \
317 .get_parent = rk_cru_composite_get_parent, \
318 .set_parent = rk_cru_composite_set_parent, \
319 }
320
321 #define RK_COMPOSITE(_id, _name, _parents, _muxdiv_reg, _mux_mask, _div_mask, _gate_reg, _gate_mask, _flags) \
322 _RK_COMPOSITE_INIT(_id, _name, _parents, _muxdiv_reg, _mux_mask, _div_mask, _gate_reg, _gate_mask, 0, _flags)
323
324 #define RK_COMPOSITE_HALF(_id, _name, _parents, _muxdiv_reg, _mux_mask, _div_mask, _gate_reg, _gate_mask, _flags) \
325 _RK_COMPOSITE_INIT(_id, _name, _parents, _muxdiv_reg, _mux_mask, _div_mask, _gate_reg, _gate_mask, 0, (_flags) | RK_COMPOSITE_HALFDIV)
326
327 #define RK_COMPOSITE_NOMUX(_id, _name, _parent, _div_reg, _div_mask, _gate_reg, _gate_mask, _flags) \
328 _RK_COMPOSITE_INIT(_id, _name, (const char *[]){ _parent }, _div_reg, 0, _div_mask, _gate_reg, _gate_mask, 0, _flags)
329
330 #define RK_COMPOSITE_NODIV(_id, _name, _parents, _muxdiv_reg, _mux_mask, _gate_reg, _gate_mask, _flags) \
331 _RK_COMPOSITE_INIT(_id, _name, _parents, _muxdiv_reg, _mux_mask, 0, _gate_reg, _gate_mask, 0, _flags)
332
333 #define RK_COMPOSITE_NOGATE(_id, _name, _parents, _muxdiv_reg, _mux_mask, _div_mask, _flags) \
334 _RK_COMPOSITE_INIT(_id, _name, _parents, _muxdiv_reg, _mux_mask, _div_mask, 0, 0, 0, _flags)
335
336 #define RK_COMPOSITE_FRAC(_id, _name, _parent, _frac_reg, _flags) \
337 _RK_COMPOSITE_INIT(_id, _name, (const char *[]){ _parent }, 0, 0, 0, 0, 0, _frac_reg, (_flags) | RK_COMPOSITE_FRACDIV)
338
339 #define RK_DIV(_id, _name, _parent, _div_reg, _div_mask, _flags) \
340 _RK_COMPOSITE_INIT(_id, _name, (const char *[]){ _parent }, _div_reg, 0, _div_mask, 0, 0, 0, _flags)
341
342 /* Gate clocks */
343
344 struct rk_cru_gate {
345 bus_size_t reg;
346 uint32_t mask;
347 const char *parent;
348 };
349
350 int rk_cru_gate_enable(struct rk_cru_softc *,
351 struct rk_cru_clk *, int);
352 const char *rk_cru_gate_get_parent(struct rk_cru_softc *,
353 struct rk_cru_clk *);
354
355 #define RK_GATE(_id, _name, _pname, _reg, _bit) \
356 { \
357 .id = (_id), \
358 .type = RK_CRU_GATE, \
359 .base.name = (_name), \
360 .base.flags = CLK_SET_RATE_PARENT, \
361 .u.gate.parent = (_pname), \
362 .u.gate.reg = (_reg), \
363 .u.gate.mask = __BIT(_bit), \
364 .enable = rk_cru_gate_enable, \
365 .get_parent = rk_cru_gate_get_parent, \
366 }
367
368 #define RK_SECURE_GATE(_id, _name, _pname) \
369 { \
370 .id = (_id), \
371 .type = RK_CRU_GATE, \
372 .base.name = (_name), \
373 .u.gate.parent = (_pname), \
374 .get_parent = rk_cru_gate_get_parent, \
375 }
376
377 /* Mux clocks */
378
379 struct rk_cru_mux {
380 bus_size_t reg;
381 uint32_t mask;
382 const char **parents;
383 u_int nparents;
384 u_int flags;
385 #define RK_MUX_GRF 0x01
386 };
387
388 const char *rk_cru_mux_get_parent(struct rk_cru_softc *, struct rk_cru_clk *);
389 int rk_cru_mux_set_parent(struct rk_cru_softc *, struct rk_cru_clk *, const char *);
390
391 #define RK_MUX_FLAGS(_id, _name, _parents, _reg, _mask, _flags) \
392 { \
393 .id = (_id), \
394 .type = RK_CRU_MUX, \
395 .base.name = (_name), \
396 .base.flags = CLK_SET_RATE_PARENT, \
397 .u.mux.parents = (_parents), \
398 .u.mux.nparents = __arraycount(_parents), \
399 .u.mux.reg = (_reg), \
400 .u.mux.mask = (_mask), \
401 .u.mux.flags = (_flags), \
402 .set_parent = rk_cru_mux_set_parent, \
403 .get_parent = rk_cru_mux_get_parent, \
404 }
405 #define RK_MUX(_id, _name, _parents, _reg, _mask) \
406 RK_MUX_FLAGS(_id, _name, _parents, _reg, _mask, 0)
407 #define RK_MUXGRF(_id, _name, _parents, _reg, _mask) \
408 RK_MUX_FLAGS(_id, _name, _parents, _reg, _mask, RK_MUX_GRF)
409
410 /*
411 * Rockchip clock definition
412 */
413
414 struct rk_cru_clk {
415 struct clk base;
416 u_int id;
417 enum rk_cru_clktype type;
418 union {
419 struct rk_cru_pll pll;
420 struct rk_cru_arm arm;
421 struct rk_cru_composite composite;
422 struct rk_cru_gate gate;
423 struct rk_cru_mux mux;
424 } u;
425
426 int (*enable)(struct rk_cru_softc *,
427 struct rk_cru_clk *, int);
428 u_int (*get_rate)(struct rk_cru_softc *,
429 struct rk_cru_clk *);
430 int (*set_rate)(struct rk_cru_softc *,
431 struct rk_cru_clk *, u_int);
432 u_int (*round_rate)(struct rk_cru_softc *,
433 struct rk_cru_clk *, u_int);
434 const char * (*get_parent)(struct rk_cru_softc *,
435 struct rk_cru_clk *);
436 int (*set_parent)(struct rk_cru_softc *,
437 struct rk_cru_clk *,
438 const char *);
439 };
440
441 /*
442 * Driver state
443 */
444
445 struct rk_cru_softc {
446 device_t sc_dev;
447 int sc_phandle;
448 bus_space_tag_t sc_bst;
449 bus_space_handle_t sc_bsh;
450 struct syscon *sc_grf;
451
452 struct clk_domain sc_clkdom;
453
454 struct rk_cru_clk *sc_clks;
455 u_int sc_nclks;
456
457 bus_size_t sc_grf_soc_status; /* for PLL lock */
458 bus_size_t sc_softrst_base;
459 };
460
461 int rk_cru_attach(struct rk_cru_softc *);
462 struct rk_cru_clk *rk_cru_clock_find(struct rk_cru_softc *,
463 const char *);
464 void rk_cru_print(struct rk_cru_softc *);
465
466 #define CRU_READ(sc, reg) \
467 bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, (reg))
468 #define CRU_WRITE(sc, reg, val) \
469 bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, (reg), (val))
470
471 #define HAS_GRF(sc) ((sc)->sc_grf != NULL)
472
473 #endif /* _ARM_RK_CRU_H */
474