rk_cru.h revision 1.10 1 /* $NetBSD: rk_cru.h,v 1.10 2022/08/23 05:33:39 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 u_int refdiv;
56 u_int fbdiv;
57 u_int postdiv1;
58 u_int postdiv2;
59 u_int dsmpd;
60 u_int fracdiv;
61 };
62
63 #define RK_PLL_RATE(_rate, _refdiv, _fbdiv, _postdiv1, _postdiv2, _dsmpd, _fracdiv) \
64 { \
65 .rate = (_rate), \
66 .refdiv = (_refdiv), \
67 .fbdiv = (_fbdiv), \
68 .postdiv1 = (_postdiv1), \
69 .postdiv2 = (_postdiv2), \
70 .dsmpd = (_dsmpd), \
71 .fracdiv = (_fracdiv), \
72 }
73
74 struct rk_cru_pll {
75 bus_size_t con_base;
76 bus_size_t mode_reg;
77 uint32_t mode_mask;
78 uint32_t lock_mask;
79 const struct rk_cru_pll_rate *rates;
80 u_int nrates;
81 const char **parents;
82 u_int nparents;
83 u_int flags;
84 #define RK_PLL_RK3288 0x01
85 };
86
87 u_int rk_cru_pll_get_rate(struct rk_cru_softc *, struct rk_cru_clk *);
88 int rk_cru_pll_set_rate(struct rk_cru_softc *, struct rk_cru_clk *, u_int);
89 const char *rk_cru_pll_get_parent(struct rk_cru_softc *, struct rk_cru_clk *);
90
91 #define RK_PLL_FLAGS(_id, _name, _parents, _con_base, _mode_reg, _mode_mask, _lock_mask, _rates, _flags) \
92 { \
93 .id = (_id), \
94 .type = RK_CRU_PLL, \
95 .base.name = (_name), \
96 .base.flags = 0, \
97 .u.pll.parents = (_parents), \
98 .u.pll.nparents = __arraycount(_parents), \
99 .u.pll.con_base = (_con_base), \
100 .u.pll.mode_reg = (_mode_reg), \
101 .u.pll.mode_mask = (_mode_mask), \
102 .u.pll.lock_mask = (_lock_mask), \
103 .u.pll.rates = (_rates), \
104 .u.pll.nrates = __arraycount(_rates), \
105 .u.pll.flags = _flags, \
106 .get_rate = rk_cru_pll_get_rate, \
107 .set_rate = rk_cru_pll_set_rate, \
108 .get_parent = rk_cru_pll_get_parent, \
109 }
110
111 #define RK_PLL(_id, _name, _parents, _con_base, _mode_reg, _mode_mask, _lock_mask, _rates) \
112 RK_PLL_FLAGS(_id, _name, _parents, _con_base, _mode_reg, _mode_mask, _lock_mask, _rates, 0)
113
114 #define RK3288_PLL(_id, _name, _parents, _con_base, _mode_reg, _mode_mask, _lock_mask, _rates) \
115 RK_PLL_FLAGS(_id, _name, _parents, _con_base, _mode_reg, _mode_mask, _lock_mask, _rates, RK_PLL_RK3288)
116
117 /* ARM clocks */
118
119 struct rk_cru_arm_rate {
120 u_int rate;
121 u_int div;
122 };
123
124 #define RK_ARM_RATE(_rate, _div) \
125 { \
126 .rate = (_rate), \
127 .div = (_div), \
128 }
129
130 struct rk_regmaskval {
131 bus_size_t reg;
132 uint32_t mask;
133 uint32_t val;
134 };
135
136 struct rk_cru_cpu_rate {
137 u_int rate;
138 struct rk_regmaskval divs[2];
139 };
140
141 struct rk_regmask {
142 bus_size_t reg;
143 uint32_t mask;
144 };
145
146 struct rk_cru_arm {
147 bus_size_t mux_reg;
148 uint32_t mux_mask;
149 u_int mux_main;
150 u_int mux_alt;
151 struct rk_regmask divs[1];
152 const char **parents;
153 u_int nparents;
154 const struct rk_cru_arm_rate *rates;
155 const struct rk_cru_cpu_rate *cpurates;
156 u_int nrates;
157 };
158
159 u_int rk_cru_arm_get_rate(struct rk_cru_softc *, struct rk_cru_clk *);
160 int rk_cru_arm_set_rate(struct rk_cru_softc *, struct rk_cru_clk *, u_int);
161 int rk_cru_arm_set_rate(struct rk_cru_softc *, struct rk_cru_clk *, u_int);
162 const char *rk_cru_arm_get_parent(struct rk_cru_softc *, struct rk_cru_clk *);
163 int rk_cru_arm_set_parent(struct rk_cru_softc *, struct rk_cru_clk *, const char *);
164
165 #define RK_ARM(_id, _name, _parents, _reg, _mux_mask, _mux_main, _mux_alt, _div_mask, _rates) \
166 { \
167 .id = (_id), \
168 .type = RK_CRU_ARM, \
169 .base.name = (_name), \
170 .base.flags = 0, \
171 .u.arm.parents = (_parents), \
172 .u.arm.nparents = __arraycount(_parents), \
173 .u.arm.mux_reg = (_reg), \
174 .u.arm.mux_mask = (_mux_mask), \
175 .u.arm.mux_main = (_mux_main), \
176 .u.arm.mux_alt = (_mux_alt), \
177 .u.arm.divs[0].reg = (_reg), \
178 .u.arm.divs[0].mask = (_div_mask), \
179 .u.arm.rates = (_rates), \
180 .u.arm.nrates = __arraycount(_rates), \
181 .get_rate = rk_cru_arm_get_rate, \
182 .set_rate = rk_cru_arm_set_rate, \
183 .get_parent = rk_cru_arm_get_parent, \
184 .set_parent = rk_cru_arm_set_parent, \
185 }
186
187 #define _RK_CPU_COMMON_INITIALIZER(_id, _name, _parents, \
188 _mux_reg, _mux_mask, _mux_main, _mux_alt, _cpurates) \
189 .id = (_id), \
190 .type = RK_CRU_ARM, \
191 .base.name = (_name), \
192 .base.flags = 0, \
193 .u.arm.parents = (_parents), \
194 .u.arm.nparents = __arraycount(_parents), \
195 .u.arm.mux_reg = (_mux_reg), \
196 .u.arm.mux_mask = (_mux_mask), \
197 .u.arm.mux_main = (_mux_main), \
198 .u.arm.mux_alt = (_mux_alt), \
199 .u.arm.cpurates = (_cpurates), \
200 .u.arm.nrates = __arraycount(_cpurates), \
201 .get_rate = rk_cru_arm_get_rate, \
202 .set_rate = rk_cru_arm_set_rate, \
203 .get_parent = rk_cru_arm_get_parent, \
204 .set_parent = rk_cru_arm_set_parent
205
206 #define RK_CPU(_id, _name, _parents, _mux_reg, _mux_mask, _mux_main, _mux_alt, \
207 _div_reg, _div_mask, _cpurates) \
208 { \
209 _RK_CPU_COMMON_INITIALIZER(_id, _name, _parents, \
210 _mux_reg, _mux_mask, _mux_main, _mux_alt,_cpurates),\
211 .u.arm.divs[0].reg = (_div_reg), \
212 .u.arm.divs[0].mask = (_div_mask), \
213 }
214
215 /* Composite clocks */
216
217 struct rk_cru_composite {
218 bus_size_t muxdiv_reg;
219 uint32_t mux_mask;
220 uint32_t div_mask;
221 bus_size_t gate_reg;
222 uint32_t gate_mask;
223 bus_size_t frac_reg;
224 const char **parents;
225 u_int nparents;
226 u_int flags;
227 #define RK_COMPOSITE_ROUND_DOWN 0x01
228 #define RK_COMPOSITE_SET_RATE_PARENT 0x02
229 #define RK_COMPOSITE_FRACDIV 0x04
230 #define RK_COMPOSITE_POW2 0x08
231 };
232
233 int rk_cru_composite_enable(struct rk_cru_softc *, struct rk_cru_clk *, int);
234 u_int rk_cru_composite_get_rate(struct rk_cru_softc *, struct rk_cru_clk *);
235 int rk_cru_composite_set_rate(struct rk_cru_softc *, struct rk_cru_clk *, u_int);
236 const char *rk_cru_composite_get_parent(struct rk_cru_softc *, struct rk_cru_clk *);
237 int rk_cru_composite_set_parent(struct rk_cru_softc *, struct rk_cru_clk *, const char *);
238
239 #define _RK_COMPOSITE_INIT(_id, _name, _parents, _muxdiv_reg, _mux_mask, _div_mask, _gate_reg, _gate_mask, _frac_reg, _flags) \
240 { \
241 .id = (_id), \
242 .type = RK_CRU_COMPOSITE, \
243 .base.name = (_name), \
244 .base.flags = 0, \
245 .u.composite.parents = (_parents), \
246 .u.composite.nparents = __arraycount(_parents), \
247 .u.composite.muxdiv_reg = (_muxdiv_reg), \
248 .u.composite.mux_mask = (_mux_mask), \
249 .u.composite.div_mask = (_div_mask), \
250 .u.composite.gate_reg = (_gate_reg), \
251 .u.composite.gate_mask = (_gate_mask), \
252 .u.composite.frac_reg = (_frac_reg), \
253 .u.composite.flags = (_flags), \
254 .enable = rk_cru_composite_enable, \
255 .get_rate = rk_cru_composite_get_rate, \
256 .set_rate = rk_cru_composite_set_rate, \
257 .get_parent = rk_cru_composite_get_parent, \
258 .set_parent = rk_cru_composite_set_parent, \
259 }
260
261 #define RK_COMPOSITE(_id, _name, _parents, _muxdiv_reg, _mux_mask, _div_mask, _gate_reg, _gate_mask, _flags) \
262 _RK_COMPOSITE_INIT(_id, _name, _parents, _muxdiv_reg, _mux_mask, _div_mask, _gate_reg, _gate_mask, 0, _flags)
263
264 #define RK_COMPOSITE_NOMUX(_id, _name, _parent, _div_reg, _div_mask, _gate_reg, _gate_mask, _flags) \
265 _RK_COMPOSITE_INIT(_id, _name, (const char *[]){ _parent }, _div_reg, 0, _div_mask, _gate_reg, _gate_mask, 0, _flags)
266
267 #define RK_COMPOSITE_NOGATE(_id, _name, _parents, _muxdiv_reg, _mux_mask, _div_mask, _flags) \
268 _RK_COMPOSITE_INIT(_id, _name, _parents, _muxdiv_reg, _mux_mask, _div_mask, 0, 0, 0, _flags)
269
270 #define RK_COMPOSITE_FRAC(_id, _name, _parent, _frac_reg, _flags) \
271 _RK_COMPOSITE_INIT(_id, _name, (const char *[]){ _parent }, 0, 0, 0, 0, 0, _frac_reg, (_flags) | RK_COMPOSITE_FRACDIV)
272
273 #define RK_DIV(_id, _name, _parent, _div_reg, _div_mask, _flags) \
274 _RK_COMPOSITE_INIT(_id, _name, (const char *[]){ _parent }, _div_reg, 0, _div_mask, 0, 0, 0, _flags)
275
276 /* Gate clocks */
277
278 struct rk_cru_gate {
279 bus_size_t reg;
280 uint32_t mask;
281 const char *parent;
282 };
283
284 int rk_cru_gate_enable(struct rk_cru_softc *,
285 struct rk_cru_clk *, int);
286 const char *rk_cru_gate_get_parent(struct rk_cru_softc *,
287 struct rk_cru_clk *);
288
289 #define RK_GATE(_id, _name, _pname, _reg, _bit) \
290 { \
291 .id = (_id), \
292 .type = RK_CRU_GATE, \
293 .base.name = (_name), \
294 .base.flags = CLK_SET_RATE_PARENT, \
295 .u.gate.parent = (_pname), \
296 .u.gate.reg = (_reg), \
297 .u.gate.mask = __BIT(_bit), \
298 .enable = rk_cru_gate_enable, \
299 .get_parent = rk_cru_gate_get_parent, \
300 }
301
302 #define RK_SECURE_GATE(_id, _name, _pname) \
303 { \
304 .id = (_id), \
305 .type = RK_CRU_GATE, \
306 .base.name = (_name), \
307 .u.gate.parent = (_pname), \
308 .get_parent = rk_cru_gate_get_parent, \
309 }
310
311 /* Mux clocks */
312
313 struct rk_cru_mux {
314 bus_size_t reg;
315 uint32_t mask;
316 const char **parents;
317 u_int nparents;
318 u_int flags;
319 #define RK_MUX_GRF 0x01
320 };
321
322 const char *rk_cru_mux_get_parent(struct rk_cru_softc *, struct rk_cru_clk *);
323 int rk_cru_mux_set_parent(struct rk_cru_softc *, struct rk_cru_clk *, const char *);
324
325 #define RK_MUX_FLAGS(_id, _name, _parents, _reg, _mask, _flags) \
326 { \
327 .id = (_id), \
328 .type = RK_CRU_MUX, \
329 .base.name = (_name), \
330 .base.flags = CLK_SET_RATE_PARENT, \
331 .u.mux.parents = (_parents), \
332 .u.mux.nparents = __arraycount(_parents), \
333 .u.mux.reg = (_reg), \
334 .u.mux.mask = (_mask), \
335 .u.mux.flags = (_flags), \
336 .set_parent = rk_cru_mux_set_parent, \
337 .get_parent = rk_cru_mux_get_parent, \
338 }
339 #define RK_MUX(_id, _name, _parents, _reg, _mask) \
340 RK_MUX_FLAGS(_id, _name, _parents, _reg, _mask, 0)
341 #define RK_MUXGRF(_id, _name, _parents, _reg, _mask) \
342 RK_MUX_FLAGS(_id, _name, _parents, _reg, _mask, RK_MUX_GRF)
343
344 /*
345 * Rockchip clock definition
346 */
347
348 struct rk_cru_clk {
349 struct clk base;
350 u_int id;
351 enum rk_cru_clktype type;
352 union {
353 struct rk_cru_pll pll;
354 struct rk_cru_arm arm;
355 struct rk_cru_composite composite;
356 struct rk_cru_gate gate;
357 struct rk_cru_mux mux;
358 } u;
359
360 int (*enable)(struct rk_cru_softc *,
361 struct rk_cru_clk *, int);
362 u_int (*get_rate)(struct rk_cru_softc *,
363 struct rk_cru_clk *);
364 int (*set_rate)(struct rk_cru_softc *,
365 struct rk_cru_clk *, u_int);
366 u_int (*round_rate)(struct rk_cru_softc *,
367 struct rk_cru_clk *, u_int);
368 const char * (*get_parent)(struct rk_cru_softc *,
369 struct rk_cru_clk *);
370 int (*set_parent)(struct rk_cru_softc *,
371 struct rk_cru_clk *,
372 const char *);
373 };
374
375 /*
376 * Driver state
377 */
378
379 struct rk_cru_softc {
380 device_t sc_dev;
381 int sc_phandle;
382 bus_space_tag_t sc_bst;
383 bus_space_handle_t sc_bsh;
384 struct syscon *sc_grf;
385
386 struct clk_domain sc_clkdom;
387
388 struct rk_cru_clk *sc_clks;
389 u_int sc_nclks;
390
391 bus_size_t sc_grf_soc_status; /* for PLL lock */
392 bus_size_t sc_softrst_base;
393 };
394
395 int rk_cru_attach(struct rk_cru_softc *);
396 struct rk_cru_clk *rk_cru_clock_find(struct rk_cru_softc *,
397 const char *);
398 void rk_cru_print(struct rk_cru_softc *);
399
400 #define CRU_READ(sc, reg) \
401 bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, (reg))
402 #define CRU_WRITE(sc, reg, val) \
403 bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, (reg), (val))
404
405 #define HAS_GRF(sc) ((sc)->sc_grf != NULL)
406
407 #endif /* _ARM_RK_CRU_H */
408