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