xref: /f-stack/freebsd/arm64/rockchip/clk/rk_cru.h (revision 22ce4aff)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3  *
4  * Copyright (c) 2018 Emmanuel Vadot <[email protected]>
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  * $FreeBSD$
28  */
29 
30 #ifndef __RK_CRU_H__
31 #define __RK_CRU_H__
32 
33 #include <dev/extres/clk/clk.h>
34 #include <dev/extres/clk/clk_div.h>
35 #include <dev/extres/clk/clk_gate.h>
36 #include <dev/extres/clk/clk_fixed.h>
37 #include <dev/extres/clk/clk_link.h>
38 
39 #include <arm64/rockchip/clk/rk_clk_armclk.h>
40 #include <arm64/rockchip/clk/rk_clk_composite.h>
41 #include <arm64/rockchip/clk/rk_clk_fract.h>
42 #include <arm64/rockchip/clk/rk_clk_gate.h>
43 #include <arm64/rockchip/clk/rk_clk_mux.h>
44 #include <arm64/rockchip/clk/rk_clk_pll.h>
45 
46 /* Macro for defining various types of clocks. */
47 /* Pure gate */
48 #define	GATE(_idx, _clkname, _pname, _o, _s)				\
49 {									\
50 	.id = _idx,							\
51 	.name = _clkname,						\
52 	.parent_name = _pname,						\
53 	.offset = CRU_CLKGATE_CON(_o),					\
54 	.shift = _s,							\
55 }
56 
57 /* Fixed rate clock. */
58 #define	FRATE(_id, _name, _freq)					\
59 {									\
60 	.type = RK_CLK_FIXED,						\
61 	.clk.fixed = &(struct clk_fixed_def) {				\
62 		.clkdef.id = _id,					\
63 		.clkdef.name = _name,					\
64 		.clkdef.parent_names = NULL,				\
65 		.clkdef.parent_cnt = 0,					\
66 		.clkdef.flags = CLK_NODE_STATIC_STRINGS,		\
67 		.freq = _freq,						\
68 	},								\
69 }
70 
71 /* Fixed factor multipier/divider. */
72 #define	FFACT(_id, _name, _pname, _mult, _div)				\
73 {									\
74 	.type = RK_CLK_FIXED,						\
75 	.clk.fixed = &(struct clk_fixed_def) {				\
76 		.clkdef.id = _id,					\
77 		.clkdef.name = _name,					\
78 		.clkdef.parent_names = (const char *[]){_pname},	\
79 		.clkdef.parent_cnt = 1,					\
80 		.clkdef.flags = CLK_NODE_STATIC_STRINGS,		\
81 		.mult = _mult,						\
82 		.div = _div,						\
83 	},								\
84 }
85 
86 /* Linked clock. */
87 #define	LINK(_name)							\
88 {									\
89 	.type = RK_CLK_LINK,						\
90 	.clk.link = &(struct clk_link_def) {				\
91 		.clkdef.id = 0,						\
92 		.clkdef.name = _name,					\
93 		.clkdef.parent_names = NULL,				\
94 		.clkdef.parent_cnt = 0,					\
95 		.clkdef.flags = CLK_NODE_STATIC_STRINGS,		\
96 	},								\
97 }
98 
99 /* Complex clock fo ARM cores. */
100 #define ARMDIV(_id, _name, _pn, _r, _o, _ds, _dw, _ms, _mw, _mp, _ap)	\
101 {									\
102 	.type = RK_CLK_ARMCLK,						\
103 	.clk.armclk = &(struct rk_clk_armclk_def) {			\
104 		.clkdef.id = _id,					\
105 		.clkdef.name = _name,					\
106 		.clkdef.parent_names = _pn,				\
107 		.clkdef.parent_cnt = nitems(_pn),			\
108 		.clkdef.flags = CLK_NODE_STATIC_STRINGS,		\
109 		.muxdiv_offset = CRU_CLKSEL_CON(_o),			\
110 		.mux_shift = _ms,					\
111 		.mux_width = _mw,					\
112 		.div_shift = _ds,					\
113 		.div_width = _dw,					\
114 		.main_parent = _mp,					\
115 		.alt_parent = _ap,					\
116 		.rates = _r,						\
117 		.nrates = nitems(_r),					\
118 	},								\
119 }
120 
121 /* Fractional rate multipier/divider. */
122 #define	FRACT(_id, _name, _pname, _f, _o)				\
123 {									\
124 	.type = RK_CLK_FRACT,						\
125 	.clk.fract = &(struct rk_clk_fract_def) {			\
126 		.clkdef.id = _id,					\
127 		.clkdef.name = _name,					\
128 		.clkdef.parent_names = (const char *[]){_pname},	\
129 		.clkdef.parent_cnt = 1,					\
130 		.clkdef.flags = CLK_NODE_STATIC_STRINGS,		\
131 		.offset = CRU_CLKSEL_CON(_o),				\
132 		.flags = _f,						\
133 	},								\
134 }
135 
136 /* Full composite clock. */
137 #define COMP(_id, _name, _pnames, _f,  _o,  _ds, _dw,  _ms, _mw)	\
138 {									\
139 	.type = RK_CLK_COMPOSITE,					\
140 	.clk.composite = &(struct rk_clk_composite_def) {		\
141 		.clkdef.id = _id,					\
142 		.clkdef.name = _name,					\
143 		.clkdef.parent_names = _pnames,				\
144 		.clkdef.parent_cnt = nitems(_pnames),			\
145 		.clkdef.flags = CLK_NODE_STATIC_STRINGS,		\
146 		.muxdiv_offset = CRU_CLKSEL_CON(_o),			\
147 		.mux_shift = _ms,					\
148 		.mux_width = _mw,					\
149 		.div_shift = _ds,					\
150 		.div_width = _dw,					\
151 		.flags = RK_CLK_COMPOSITE_HAVE_MUX | _f, 		\
152 	},								\
153 }
154 
155 /* Composite clock without mux (divider only). */
156 #define CDIV(_id, _name, _pname, _f, _o, _ds, _dw)			\
157 {									\
158 	.type = RK_CLK_COMPOSITE,					\
159 	.clk.composite = &(struct rk_clk_composite_def) {		\
160 		.clkdef.id = _id,					\
161 		.clkdef.name = _name,					\
162 		.clkdef.parent_names = (const char *[]){_pname},	\
163 		.clkdef.parent_cnt = 1,					\
164 		.clkdef.flags = CLK_NODE_STATIC_STRINGS,		\
165 		.muxdiv_offset = CRU_CLKSEL_CON(_o),			\
166 		.div_shift = _ds,					\
167 		.div_width = _dw,					\
168 		.flags =  _f,						\
169 	},								\
170 }
171 
172 /* Complex clock without divider (multiplexer only). */
173 #define MUX(_id, _name, _pn, _f,  _mo, _ms, _mw)			\
174 {									\
175 	.type = RK_CLK_MUX,						\
176 	.clk.mux = &(struct rk_clk_mux_def) {				\
177 		.clkdef.id = _id,					\
178 		.clkdef.name = _name,					\
179 		.clkdef.parent_names = _pn,				\
180 		.clkdef.parent_cnt = nitems(_pn),			\
181 		.clkdef.flags = CLK_NODE_STATIC_STRINGS,		\
182 		.offset = CRU_CLKSEL_CON(_mo),				\
183 		.shift = _ms,						\
184 		.width = _mw,						\
185 		.mux_flags = _f, 			\
186 	},								\
187 }
188 
189 struct rk_cru_gate {
190 	const char	*name;
191 	const char	*parent_name;
192 	uint32_t	id;
193 	uint32_t	offset;
194 	uint32_t	shift;
195 };
196 
197 #define	CRU_GATE(idx, clkname, pname, o, s)	\
198 	{				\
199 		.id = idx,			\
200 		.name = clkname,		\
201 		.parent_name = pname,		\
202 		.offset = o,			\
203 		.shift = s,			\
204 	},
205 
206 enum rk_clk_type {
207 	RK_CLK_UNDEFINED = 0,
208 	RK3066_CLK_PLL,
209 	RK3328_CLK_PLL,
210 	RK3399_CLK_PLL,
211 	RK_CLK_COMPOSITE,
212 	RK_CLK_FIXED,
213 	RK_CLK_FRACT,
214 	RK_CLK_MUX,
215 	RK_CLK_ARMCLK,
216 	RK_CLK_LINK,
217 };
218 
219 struct rk_clk {
220 	enum rk_clk_type	type;
221 	union {
222 		struct rk_clk_pll_def		*pll;
223 		struct rk_clk_composite_def	*composite;
224 		struct rk_clk_mux_def		*mux;
225 		struct rk_clk_armclk_def	*armclk;
226 		struct clk_fixed_def		*fixed;
227 		struct rk_clk_fract_def		*fract;
228 		struct clk_link_def		*link;
229 	} clk;
230 };
231 
232 struct rk_cru_softc {
233 	device_t		dev;
234 	struct resource		*res;
235 	struct clkdom		*clkdom;
236 	struct mtx		mtx;
237 	int			type;
238 	uint32_t		reset_offset;
239 	uint32_t		reset_num;
240 	struct rk_cru_gate	*gates;
241 	int			ngates;
242 	struct rk_clk		*clks;
243 	int			nclks;
244 	struct rk_clk_armclk_def	*armclk;
245 	struct rk_clk_armclk_rates	*armclk_rates;
246 	int			narmclk_rates;
247 };
248 
249 DECLARE_CLASS(rk_cru_driver);
250 
251 int	rk_cru_attach(device_t dev);
252 
253 #endif /* __RK_CRU_H__ */
254