xref: /freebsd/sys/arm64/freescale/imx/imx_ccm.h (revision b59017c5cad90d0f09a59e68c00457b7faf93e7c)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause
3  *
4  * Copyright (c) 2020 Oleksandr Tymoshenko <gonzo@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 AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, 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	IMX8_CCM_H
29 #define	IMX8_CCM_H
30 
31 #include <dev/clk/clk.h>
32 #include <dev/clk/clk_div.h>
33 #include <dev/clk/clk_fixed.h>
34 #include <dev/clk/clk_gate.h>
35 #include <dev/clk/clk_link.h>
36 
37 int imx_ccm_attach(device_t);
38 int imx_ccm_detach(device_t);
39 
40 struct imx_ccm_softc {
41 	device_t		dev;
42 	struct resource		*mem_res;
43 	struct clkdom		*clkdom;
44 	struct mtx		mtx;
45 	struct imx_clk		*clks;
46 	int			nclks;
47 };
48 
49 DECLARE_CLASS(imx_ccm_driver);
50 
51 enum imx_clk_type {
52 	IMX_CLK_UNDEFINED = 0,
53 	IMX_CLK_FIXED,
54 	IMX_CLK_LINK,
55 	IMX_CLK_MUX,
56 	IMX_CLK_GATE,
57 	IMX_CLK_COMPOSITE,
58 	IMX_CLK_SSCG_PLL,
59 	IMX_CLK_FRAC_PLL,
60 	IMX_CLK_DIV,
61 };
62 
63 struct imx_clk {
64 	enum imx_clk_type	type;
65 	union {
66 		struct clk_fixed_def		*fixed;
67 		struct clk_link_def		*link;
68 		struct imx_clk_mux_def		*mux;
69 		struct imx_clk_gate_def		*gate;
70 		struct imx_clk_composite_def	*composite;
71 		struct imx_clk_sscg_pll_def	*sscg_pll;
72 		struct imx_clk_frac_pll_def	*frac_pll;
73 		struct clk_div_def		*div;
74 	} clk;
75 };
76 
77 /* Linked clock. */
78 #define	LINK(_id, _name)						\
79 {									\
80 	.type = IMX_CLK_LINK,						\
81 	.clk.link = &(struct clk_link_def) {				\
82 		.clkdef.id = _id,					\
83 		.clkdef.name = _name,					\
84 		.clkdef.parent_names = NULL,				\
85 		.clkdef.parent_cnt = 0,					\
86 		.clkdef.flags = CLK_NODE_STATIC_STRINGS,		\
87 	},								\
88 }
89 
90 /* Complex clock without divider (multiplexer only). */
91 #define MUX(_id, _name, _pn, _f,  _mo, _ms, _mw)			\
92 {									\
93 	.type = IMX_CLK_MUX,						\
94 	.clk.mux = &(struct imx_clk_mux_def) {				\
95 		.clkdef.id = _id,					\
96 		.clkdef.name = _name,					\
97 		.clkdef.parent_names = _pn,				\
98 		.clkdef.parent_cnt = nitems(_pn),			\
99 		.clkdef.flags = CLK_NODE_STATIC_STRINGS,		\
100 		.offset = _mo,						\
101 		.shift = _ms,						\
102 		.width = _mw,						\
103 		.mux_flags = _f, 					\
104 	},								\
105 }
106 
107 /* Fixed frequency clock */
108 #define	FIXED(_id, _name, _freq)					\
109 {									\
110 	.type = IMX_CLK_FIXED,						\
111 	.clk.fixed = &(struct clk_fixed_def) {				\
112 		.clkdef.id = _id,					\
113 		.clkdef.name = _name,					\
114 		.clkdef.flags = CLK_NODE_STATIC_STRINGS,		\
115 		.freq = _freq,						\
116 	},								\
117 }
118 
119 /* Fixed factor multipier/divider. */
120 #define	FFACT(_id, _name, _pname, _mult, _div)				\
121 {									\
122 	.type = IMX_CLK_FIXED,						\
123 	.clk.fixed = &(struct clk_fixed_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 		.mult = _mult,						\
130 		.div = _div,						\
131 	},								\
132 }
133 
134 /* Clock gate */
135 #define	GATE(_id, _name, _pname, _o, _shift)				\
136 {									\
137 	.type = IMX_CLK_GATE,						\
138 	.clk.gate = &(struct imx_clk_gate_def) {			\
139 		.clkdef.id = _id,					\
140 		.clkdef.name = _name,					\
141 		.clkdef.parent_names = (const char *[]){_pname},	\
142 		.clkdef.parent_cnt = 1,					\
143 		.clkdef.flags = CLK_NODE_STATIC_STRINGS,		\
144 		.offset = _o,						\
145 		.shift = _shift,					\
146 		.mask = 1,						\
147 	},								\
148 }
149 
150 /* Root clock gate */
151 #define	ROOT_GATE(_id, _name, _pname, _reg)				\
152 {									\
153 	.type = IMX_CLK_GATE,						\
154 	.clk.gate = &(struct imx_clk_gate_def) {			\
155 		.clkdef.id = _id,					\
156 		.clkdef.name = _name,					\
157 		.clkdef.parent_names = (const char *[]){_pname},	\
158 		.clkdef.parent_cnt = 1,					\
159 		.clkdef.flags = CLK_NODE_STATIC_STRINGS,		\
160 		.offset = _reg,						\
161 		.shift = 0,						\
162 		.mask = 3,						\
163 	},								\
164 }
165 
166 /* Composite clock with GATE, MUX, PRE_DIV, and POST_DIV */
167 #define COMPOSITE(_id, _name, _pn, _o, _flags)				\
168 {									\
169 	.type = IMX_CLK_COMPOSITE,					\
170 	.clk.composite = &(struct imx_clk_composite_def) {		\
171 		.clkdef.id = _id,					\
172 		.clkdef.name = _name,					\
173 		.clkdef.parent_names = _pn,				\
174 		.clkdef.parent_cnt = nitems(_pn),			\
175 		.clkdef.flags = CLK_NODE_STATIC_STRINGS,		\
176 		.offset = _o,						\
177 		.flags = _flags,					\
178 	},								\
179 }
180 
181 /* SSCG PLL */
182 #define SSCG_PLL(_id, _name, _pn, _o)					\
183 {									\
184 	.type = IMX_CLK_SSCG_PLL,					\
185 	.clk.composite = &(struct imx_clk_composite_def) {		\
186 		.clkdef.id = _id,					\
187 		.clkdef.name = _name,					\
188 		.clkdef.parent_names = _pn,				\
189 		.clkdef.parent_cnt = nitems(_pn),			\
190 		.clkdef.flags = CLK_NODE_STATIC_STRINGS,		\
191 		.offset = _o,						\
192 	},								\
193 }
194 
195 /* Fractional PLL */
196 #define FRAC_PLL(_id, _name, _pname, _o)				\
197 {									\
198 	.type = IMX_CLK_FRAC_PLL,					\
199 	.clk.frac_pll = &(struct imx_clk_frac_pll_def) {		\
200 		.clkdef.id = _id,					\
201 		.clkdef.name = _name,					\
202 		.clkdef.parent_names = (const char *[]){_pname},	\
203 		.clkdef.parent_cnt = 1,					\
204 		.clkdef.flags = CLK_NODE_STATIC_STRINGS,		\
205 		.offset = _o,						\
206 	},								\
207 }
208 
209 #define DIV(_id, _name, _pname, _o, _shift, _width)			\
210 {									\
211 	.type = IMX_CLK_DIV,						\
212 	.clk.div = &(struct clk_div_def) {				\
213 		.clkdef.id = _id,					\
214 		.clkdef.name = _name,					\
215 		.clkdef.parent_names = (const char *[]){_pname},	\
216 		.clkdef.parent_cnt = 1,					\
217 		.clkdef.flags = CLK_NODE_STATIC_STRINGS,		\
218 		.offset = _o,						\
219 		.i_shift = _shift,					\
220 		.i_width = _width,					\
221 	},								\
222 }
223 
224 #endif	/* IMX8_CCM_H */
225