xref: /netbsd-src/sys/arch/arm/rockchip/rk_cru.h (revision 4fb053697f9d68002b95c174d5a1bc8eedbd6977)
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@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