xref: /freebsd-13-stable/sys/arm64/rockchip/clk/rk_cru.h (revision f8167e0404dab9ffeaca95853dd237ab7c587f82)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause
3  *
4  * Copyright (c) 2018 Emmanuel Vadot <manu@freebsd.org>
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
20  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
22  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  */
27 
28 #ifndef __RK_CRU_H__
29 #define __RK_CRU_H__
30 
31 #include <dev/extres/clk/clk.h>
32 #include <dev/extres/clk/clk_div.h>
33 #include <dev/extres/clk/clk_gate.h>
34 #include <dev/extres/clk/clk_fixed.h>
35 #include <dev/extres/clk/clk_link.h>
36 
37 #include <arm64/rockchip/clk/rk_clk_armclk.h>
38 #include <arm64/rockchip/clk/rk_clk_composite.h>
39 #include <arm64/rockchip/clk/rk_clk_fract.h>
40 #include <arm64/rockchip/clk/rk_clk_gate.h>
41 #include <arm64/rockchip/clk/rk_clk_mux.h>
42 #include <arm64/rockchip/clk/rk_clk_pll.h>
43 
44 /* Macro for defining various types of clocks. */
45 /* Pure gate */
46 #define	GATE(_idx, _clkname, _pname, _o, _s)				\
47 {									\
48 	.id = _idx,							\
49 	.name = _clkname,						\
50 	.parent_name = _pname,						\
51 	.offset = CRU_CLKGATE_CON(_o),					\
52 	.shift = _s,							\
53 }
54 
55 /* Fixed rate clock. */
56 #define	FRATE(_id, _name, _freq)					\
57 {									\
58 	.type = RK_CLK_FIXED,						\
59 	.clk.fixed = &(struct clk_fixed_def) {				\
60 		.clkdef.id = _id,					\
61 		.clkdef.name = _name,					\
62 		.clkdef.parent_names = NULL,				\
63 		.clkdef.parent_cnt = 0,					\
64 		.clkdef.flags = CLK_NODE_STATIC_STRINGS,		\
65 		.freq = _freq,						\
66 	},								\
67 }
68 
69 /* Fixed factor multipier/divider. */
70 #define	FFACT(_id, _name, _pname, _mult, _div)				\
71 {									\
72 	.type = RK_CLK_FIXED,						\
73 	.clk.fixed = &(struct clk_fixed_def) {				\
74 		.clkdef.id = _id,					\
75 		.clkdef.name = _name,					\
76 		.clkdef.parent_names = (const char *[]){_pname},	\
77 		.clkdef.parent_cnt = 1,					\
78 		.clkdef.flags = CLK_NODE_STATIC_STRINGS,		\
79 		.mult = _mult,						\
80 		.div = _div,						\
81 	},								\
82 }
83 
84 /* Linked clock. */
85 #define	LINK(_name)							\
86 {									\
87 	.type = RK_CLK_LINK,						\
88 	.clk.link = &(struct clk_link_def) {				\
89 		.clkdef.id = 0,						\
90 		.clkdef.name = _name,					\
91 		.clkdef.parent_names = NULL,				\
92 		.clkdef.parent_cnt = 0,					\
93 		.clkdef.flags = CLK_NODE_STATIC_STRINGS,		\
94 	},								\
95 }
96 
97 /* Complex clock fo ARM cores. */
98 #define ARMDIV(_id, _name, _pn, _r, _o, _ds, _dw, _ms, _mw, _mp, _ap)	\
99 {									\
100 	.type = RK_CLK_ARMCLK,						\
101 	.clk.armclk = &(struct rk_clk_armclk_def) {			\
102 		.clkdef.id = _id,					\
103 		.clkdef.name = _name,					\
104 		.clkdef.parent_names = _pn,				\
105 		.clkdef.parent_cnt = nitems(_pn),			\
106 		.clkdef.flags = CLK_NODE_STATIC_STRINGS,		\
107 		.muxdiv_offset = CRU_CLKSEL_CON(_o),			\
108 		.mux_shift = _ms,					\
109 		.mux_width = _mw,					\
110 		.div_shift = _ds,					\
111 		.div_width = _dw,					\
112 		.main_parent = _mp,					\
113 		.alt_parent = _ap,					\
114 		.rates = _r,						\
115 		.nrates = nitems(_r),					\
116 	},								\
117 }
118 
119 /* Fractional rate multipier/divider. */
120 #define	FRACT(_id, _name, _pname, _f, _o)				\
121 {									\
122 	.type = RK_CLK_FRACT,						\
123 	.clk.fract = &(struct rk_clk_fract_def) {			\
124 		.clkdef.id = _id,					\
125 		.clkdef.name = _name,					\
126 		.clkdef.parent_names = (const char *[]){_pname},	\
127 		.clkdef.parent_cnt = 1,					\
128 		.clkdef.flags = CLK_NODE_STATIC_STRINGS,		\
129 		.offset = CRU_CLKSEL_CON(_o),				\
130 		.flags = _f,						\
131 	},								\
132 }
133 
134 /* Full composite clock. */
135 #define COMP(_id, _name, _pnames, _f,  _o,  _ds, _dw,  _ms, _mw)	\
136 {									\
137 	.type = RK_CLK_COMPOSITE,					\
138 	.clk.composite = &(struct rk_clk_composite_def) {		\
139 		.clkdef.id = _id,					\
140 		.clkdef.name = _name,					\
141 		.clkdef.parent_names = _pnames,				\
142 		.clkdef.parent_cnt = nitems(_pnames),			\
143 		.clkdef.flags = CLK_NODE_STATIC_STRINGS,		\
144 		.muxdiv_offset = CRU_CLKSEL_CON(_o),			\
145 		.mux_shift = _ms,					\
146 		.mux_width = _mw,					\
147 		.div_shift = _ds,					\
148 		.div_width = _dw,					\
149 		.flags = RK_CLK_COMPOSITE_HAVE_MUX | _f, 		\
150 	},								\
151 }
152 
153 /* Composite clock without mux (divider only). */
154 #define CDIV(_id, _name, _pname, _f, _o, _ds, _dw)			\
155 {									\
156 	.type = RK_CLK_COMPOSITE,					\
157 	.clk.composite = &(struct rk_clk_composite_def) {		\
158 		.clkdef.id = _id,					\
159 		.clkdef.name = _name,					\
160 		.clkdef.parent_names = (const char *[]){_pname},	\
161 		.clkdef.parent_cnt = 1,					\
162 		.clkdef.flags = CLK_NODE_STATIC_STRINGS,		\
163 		.muxdiv_offset = CRU_CLKSEL_CON(_o),			\
164 		.div_shift = _ds,					\
165 		.div_width = _dw,					\
166 		.flags =  _f,						\
167 	},								\
168 }
169 
170 /* Complex clock without divider (multiplexer only). */
171 #define MUXRAW(_id, _name, _pn, _f,  _mo, _ms, _mw)			\
172 {									\
173 	.type = RK_CLK_MUX,						\
174 	.clk.mux = &(struct rk_clk_mux_def) {				\
175 		.clkdef.id = _id,					\
176 		.clkdef.name = _name,					\
177 		.clkdef.parent_names = _pn,				\
178 		.clkdef.parent_cnt = nitems(_pn),			\
179 		.clkdef.flags = CLK_NODE_STATIC_STRINGS,		\
180 		.offset = _mo,						\
181 		.shift = _ms,						\
182 		.width = _mw,						\
183 		.mux_flags = _f,					\
184 	},								\
185 }
186 
187 #define MUX(_id, _name, _pn, _f,  _mo, _ms, _mw)			\
188 	MUXRAW(_id, _name, _pn, _f, CRU_CLKSEL_CON(_mo), _ms, _mw)
189 
190 /* Complex clock without divider (multiplexer only in GRF). */
191 #define MUXGRF(_id, _name, _pn, _f,  _mo, _ms, _mw)			\
192 {									\
193 	.type = RK_CLK_MUX,						\
194 	.clk.mux = &(struct rk_clk_mux_def) {				\
195 		.clkdef.id = _id,					\
196 		.clkdef.name = _name,					\
197 		.clkdef.parent_names = _pn,				\
198 		.clkdef.parent_cnt = nitems(_pn),			\
199 		.clkdef.flags = CLK_NODE_STATIC_STRINGS,		\
200 		.offset = _mo,						\
201 		.shift = _ms,						\
202 		.width = _mw,						\
203 		.mux_flags = RK_CLK_MUX_GRF | _f,			\
204 	},								\
205 }
206 
207 struct rk_cru_gate {
208 	const char	*name;
209 	const char	*parent_name;
210 	uint32_t	id;
211 	uint32_t	offset;
212 	uint32_t	shift;
213 };
214 
215 #define	CRU_GATE(idx, clkname, pname, o, s)	\
216 	{				\
217 		.id = idx,			\
218 		.name = clkname,		\
219 		.parent_name = pname,		\
220 		.offset = o,			\
221 		.shift = s,			\
222 	},
223 
224 enum rk_clk_type {
225 	RK_CLK_UNDEFINED = 0,
226 	RK3066_CLK_PLL,
227 	RK3328_CLK_PLL,
228 	RK3399_CLK_PLL,
229 	RK_CLK_COMPOSITE,
230 	RK_CLK_FIXED,
231 	RK_CLK_FRACT,
232 	RK_CLK_MUX,
233 	RK_CLK_ARMCLK,
234 	RK_CLK_LINK,
235 };
236 
237 struct rk_clk {
238 	enum rk_clk_type	type;
239 	union {
240 		struct rk_clk_pll_def		*pll;
241 		struct rk_clk_composite_def	*composite;
242 		struct rk_clk_mux_def		*mux;
243 		struct rk_clk_armclk_def	*armclk;
244 		struct clk_fixed_def		*fixed;
245 		struct rk_clk_fract_def		*fract;
246 		struct clk_link_def		*link;
247 	} clk;
248 };
249 
250 struct rk_cru_softc {
251 	device_t		dev;
252 	struct resource		*res;
253 	struct clkdom		*clkdom;
254 	struct mtx		mtx;
255 	int			type;
256 	uint32_t		reset_offset;
257 	uint32_t		reset_num;
258 	struct rk_cru_gate	*gates;
259 	int			ngates;
260 	struct rk_clk		*clks;
261 	int			nclks;
262 	struct rk_clk_armclk_def	*armclk;
263 	struct rk_clk_armclk_rates	*armclk_rates;
264 	int			narmclk_rates;
265 };
266 
267 DECLARE_CLASS(rk_cru_driver);
268 
269 int	rk_cru_attach(device_t dev);
270 
271 #endif /* __RK_CRU_H__ */
272