imx_ccm.h revision 1.1 1 1.1 skrll /* $NetBSD: imx_ccm.h,v 1.1 2020/12/23 14:42:38 skrll Exp $ */
2 1.1 skrll
3 1.1 skrll /*-
4 1.1 skrll * Copyright (c) 2020 Jared McNeill <jmcneill (at) invisible.ca>
5 1.1 skrll * All rights reserved.
6 1.1 skrll *
7 1.1 skrll * Redistribution and use in source and binary forms, with or without
8 1.1 skrll * modification, are permitted provided that the following conditions
9 1.1 skrll * are met:
10 1.1 skrll * 1. Redistributions of source code must retain the above copyright
11 1.1 skrll * notice, this list of conditions and the following disclaimer.
12 1.1 skrll * 2. Redistributions in binary form must reproduce the above copyright
13 1.1 skrll * notice, this list of conditions and the following disclaimer in the
14 1.1 skrll * documentation and/or other materials provided with the distribution.
15 1.1 skrll *
16 1.1 skrll * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 1.1 skrll * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 1.1 skrll * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 1.1 skrll * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 1.1 skrll * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21 1.1 skrll * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 1.1 skrll * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 1.1 skrll * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 1.1 skrll * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 1.1 skrll * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 1.1 skrll * SUCH DAMAGE.
27 1.1 skrll */
28 1.1 skrll
29 1.1 skrll #ifndef _ARM_IMX_CCM_H
30 1.1 skrll #define _ARM_IMX_CCM_H
31 1.1 skrll
32 1.1 skrll #include <dev/clk/clk_backend.h>
33 1.1 skrll #include <dev/fdt/syscon.h>
34 1.1 skrll
35 1.1 skrll struct imx_ccm_softc;
36 1.1 skrll struct imx_ccm_clk;
37 1.1 skrll
38 1.1 skrll /*
39 1.1 skrll * Clocks
40 1.1 skrll */
41 1.1 skrll
42 1.1 skrll enum imx_ccm_clktype {
43 1.1 skrll IMX_CCM_UNKNOWN,
44 1.1 skrll IMX_CCM_EXTCLK,
45 1.1 skrll IMX_CCM_GATE,
46 1.1 skrll IMX_CCM_COMPOSITE,
47 1.1 skrll IMX_CCM_PLL,
48 1.1 skrll IMX_CCM_FIXED,
49 1.1 skrll IMX_CCM_FIXED_FACTOR,
50 1.1 skrll IMX_CCM_MUX,
51 1.1 skrll IMX_CCM_DIV,
52 1.1 skrll };
53 1.1 skrll
54 1.1 skrll /* External clocks */
55 1.1 skrll
56 1.1 skrll int imx_ccm_extclk_enable(struct imx_ccm_softc *, struct imx_ccm_clk *, int);
57 1.1 skrll u_int imx_ccm_extclk_get_rate(struct imx_ccm_softc *, struct imx_ccm_clk *);
58 1.1 skrll int imx_ccm_extclk_set_rate(struct imx_ccm_softc *, struct imx_ccm_clk *, u_int);
59 1.1 skrll const char *imx_ccm_extclk_get_parent(struct imx_ccm_softc *, struct imx_ccm_clk *);
60 1.1 skrll
61 1.1 skrll #define IMX_EXTCLK(_id, _name) \
62 1.1 skrll { \
63 1.1 skrll .id = (_id), \
64 1.1 skrll .type = IMX_CCM_EXTCLK, \
65 1.1 skrll .base.name = (_name), \
66 1.1 skrll .base.flags = 0, \
67 1.1 skrll .u.extclk = (_name), \
68 1.1 skrll .enable = imx_ccm_extclk_enable, \
69 1.1 skrll .get_rate = imx_ccm_extclk_get_rate, \
70 1.1 skrll .set_rate = imx_ccm_extclk_set_rate, \
71 1.1 skrll .get_parent = imx_ccm_extclk_get_parent, \
72 1.1 skrll }
73 1.1 skrll
74 1.1 skrll /* Gate clocks */
75 1.1 skrll
76 1.1 skrll struct imx_ccm_gate {
77 1.1 skrll bus_size_t reg;
78 1.1 skrll uint32_t mask;
79 1.1 skrll const char *parent;
80 1.1 skrll };
81 1.1 skrll
82 1.1 skrll int imx_ccm_gate_enable(struct imx_ccm_softc *,
83 1.1 skrll struct imx_ccm_clk *, int);
84 1.1 skrll const char *imx_ccm_gate_get_parent(struct imx_ccm_softc *,
85 1.1 skrll struct imx_ccm_clk *);
86 1.1 skrll
87 1.1 skrll #define IMX_GATE(_id, _name, _pname, _reg, _mask) \
88 1.1 skrll IMX_GATE_INDEX(_id, 0, _name, _pname, _reg, _mask)
89 1.1 skrll #define IMX_GATE_INDEX(_id, _regidx, _name, _pname, _reg, _mask) \
90 1.1 skrll { \
91 1.1 skrll .id = (_id), \
92 1.1 skrll .regidx = (_regidx), \
93 1.1 skrll .type = IMX_CCM_GATE, \
94 1.1 skrll .base.name = (_name), \
95 1.1 skrll .base.flags = CLK_SET_RATE_PARENT, \
96 1.1 skrll .u.gate.parent = (_pname), \
97 1.1 skrll .u.gate.reg = (_reg), \
98 1.1 skrll .u.gate.mask = (_mask), \
99 1.1 skrll .enable = imx_ccm_gate_enable, \
100 1.1 skrll .get_parent = imx_ccm_gate_get_parent, \
101 1.1 skrll }
102 1.1 skrll #define IMX_ROOT_GATE(_id, _name, _pname, _reg) \
103 1.1 skrll IMX_ROOT_GATE_INDEX(_id, 0, _name, _pname, _reg)
104 1.1 skrll #define IMX_ROOT_GATE_INDEX(_id, _regidx, _name, _pname, _reg) \
105 1.1 skrll IMX_GATE_INDEX(_id, _regidx, _name, _pname, _reg, __BITS(1,0))
106 1.1 skrll
107 1.1 skrll /* Composite clocks */
108 1.1 skrll
109 1.1 skrll struct imx_ccm_composite {
110 1.1 skrll bus_size_t reg;
111 1.1 skrll const char **parents;
112 1.1 skrll u_int nparents;
113 1.1 skrll u_int flags;
114 1.1 skrll #define IMX_COMPOSITE_ROUND_DOWN 0x01
115 1.1 skrll #define IMX_COMPOSITE_SET_RATE_PARENT 0x02
116 1.1 skrll };
117 1.1 skrll
118 1.1 skrll int imx_ccm_composite_enable(struct imx_ccm_softc *, struct imx_ccm_clk *, int);
119 1.1 skrll u_int imx_ccm_composite_get_rate(struct imx_ccm_softc *, struct imx_ccm_clk *);
120 1.1 skrll int imx_ccm_composite_set_rate(struct imx_ccm_softc *, struct imx_ccm_clk *, u_int);
121 1.1 skrll const char *imx_ccm_composite_get_parent(struct imx_ccm_softc *, struct imx_ccm_clk *);
122 1.1 skrll int imx_ccm_composite_set_parent(struct imx_ccm_softc *, struct imx_ccm_clk *, const char *);
123 1.1 skrll
124 1.1 skrll #define IMX_COMPOSITE(_id, _name, _parents, _reg, _flags) \
125 1.1 skrll IMX_COMPOSITE_INDEX(_id, 0, _name, _parents, _reg, _flags)
126 1.1 skrll
127 1.1 skrll #define IMX_COMPOSITE_INDEX(_id, _regidx, _name, _parents, _reg, _flags) \
128 1.1 skrll { \
129 1.1 skrll .id = (_id), \
130 1.1 skrll .regidx = (_regidx), \
131 1.1 skrll .type = IMX_CCM_COMPOSITE, \
132 1.1 skrll .base.name = (_name), \
133 1.1 skrll .base.flags = 0, \
134 1.1 skrll .u.composite.parents = (_parents), \
135 1.1 skrll .u.composite.nparents = __arraycount(_parents), \
136 1.1 skrll .u.composite.reg = (_reg), \
137 1.1 skrll .u.composite.flags = (_flags), \
138 1.1 skrll .enable = imx_ccm_composite_enable, \
139 1.1 skrll .get_rate = imx_ccm_composite_get_rate, \
140 1.1 skrll .set_rate = imx_ccm_composite_set_rate, \
141 1.1 skrll .set_parent = imx_ccm_composite_set_parent, \
142 1.1 skrll .get_parent = imx_ccm_composite_get_parent, \
143 1.1 skrll }
144 1.1 skrll
145 1.1 skrll /* PLLs */
146 1.1 skrll
147 1.1 skrll struct imx_ccm_pll {
148 1.1 skrll bus_size_t reg;
149 1.1 skrll const char *parent;
150 1.1 skrll uint32_t div_mask;
151 1.1 skrll u_int flags;
152 1.1 skrll #define IMX_PLL_ARM __BIT(0)
153 1.1 skrll #define IMX_PLL_480M_528M __BIT(1)
154 1.1 skrll #define IMX_PLL_ENET __BIT(2)
155 1.1 skrll };
156 1.1 skrll
157 1.1 skrll int imx_ccm_pll_enable(struct imx_ccm_softc *, struct imx_ccm_clk *, int);
158 1.1 skrll u_int imx_ccm_pll_get_rate(struct imx_ccm_softc *, struct imx_ccm_clk *);
159 1.1 skrll const char *imx_ccm_pll_get_parent(struct imx_ccm_softc *, struct imx_ccm_clk *);
160 1.1 skrll
161 1.1 skrll #define IMX_PLL(_id, _name, _parent, _reg, _div_mask, _flags) \
162 1.1 skrll IMX_PLL_INDEX(_id, 0, _name, _parent, _reg, _div_mask, _flags)
163 1.1 skrll #define IMX_PLL_INDEX(_id, _regidx, _name, _parent, _reg, _div_mask, _flags) \
164 1.1 skrll { \
165 1.1 skrll .id = (_id), \
166 1.1 skrll .regidx = (_regidx), \
167 1.1 skrll .type = IMX_CCM_PLL, \
168 1.1 skrll .base.name = (_name), \
169 1.1 skrll .base.flags = 0, \
170 1.1 skrll .u.pll.parent = (_parent), \
171 1.1 skrll .u.pll.reg = (_reg), \
172 1.1 skrll .u.pll.div_mask = (_div_mask), \
173 1.1 skrll .u.pll.flags = (_flags), \
174 1.1 skrll .enable = imx_ccm_pll_enable, \
175 1.1 skrll .get_rate = imx_ccm_pll_get_rate, \
176 1.1 skrll .get_parent = imx_ccm_pll_get_parent, \
177 1.1 skrll }
178 1.1 skrll
179 1.1 skrll /* Fixed clocks */
180 1.1 skrll
181 1.1 skrll struct imx_ccm_fixed {
182 1.1 skrll u_int rate;
183 1.1 skrll };
184 1.1 skrll
185 1.1 skrll u_int imx_ccm_fixed_get_rate(struct imx_ccm_softc *, struct imx_ccm_clk *);
186 1.1 skrll
187 1.1 skrll #define IMX_FIXED(_id, _name, _rate) \
188 1.1 skrll { \
189 1.1 skrll .id = (_id), \
190 1.1 skrll .type = IMX_CCM_FIXED, \
191 1.1 skrll .base.name = (_name), \
192 1.1 skrll .base.flags = 0, \
193 1.1 skrll .u.fixed.rate = (_rate), \
194 1.1 skrll .get_rate = imx_ccm_fixed_get_rate, \
195 1.1 skrll }
196 1.1 skrll
197 1.1 skrll /* Fixed factor clocks */
198 1.1 skrll
199 1.1 skrll struct imx_ccm_fixed_factor {
200 1.1 skrll const char *parent;
201 1.1 skrll u_int mult;
202 1.1 skrll u_int div;
203 1.1 skrll };
204 1.1 skrll
205 1.1 skrll u_int imx_ccm_fixed_factor_get_rate(struct imx_ccm_softc *, struct imx_ccm_clk *);
206 1.1 skrll int imx_ccm_fixed_factor_set_rate(struct imx_ccm_softc *, struct imx_ccm_clk *, u_int);
207 1.1 skrll const char *imx_ccm_fixed_factor_get_parent(struct imx_ccm_softc *, struct imx_ccm_clk *);
208 1.1 skrll
209 1.1 skrll #define IMX_FIXED_FACTOR(_id, _name, _parent, _mult, _div) \
210 1.1 skrll { \
211 1.1 skrll .id = (_id), \
212 1.1 skrll .type = IMX_CCM_FIXED_FACTOR, \
213 1.1 skrll .base.name = (_name), \
214 1.1 skrll .base.flags = 0, \
215 1.1 skrll .u.fixed_factor.parent = (_parent), \
216 1.1 skrll .u.fixed_factor.mult = (_mult), \
217 1.1 skrll .u.fixed_factor.div = (_div), \
218 1.1 skrll .get_rate = imx_ccm_fixed_factor_get_rate, \
219 1.1 skrll .set_rate = imx_ccm_fixed_factor_set_rate, \
220 1.1 skrll .get_parent = imx_ccm_fixed_factor_get_parent, \
221 1.1 skrll }
222 1.1 skrll
223 1.1 skrll /* Mux clocks */
224 1.1 skrll
225 1.1 skrll struct imx_ccm_mux {
226 1.1 skrll bus_size_t reg;
227 1.1 skrll const char **parents;
228 1.1 skrll u_int nparents;
229 1.1 skrll uint32_t sel;
230 1.1 skrll };
231 1.1 skrll
232 1.1 skrll const char *imx_ccm_mux_get_parent(struct imx_ccm_softc *, struct imx_ccm_clk *);
233 1.1 skrll int imx_ccm_mux_set_parent(struct imx_ccm_softc *, struct imx_ccm_clk *, const char *);
234 1.1 skrll
235 1.1 skrll #define IMX_MUX(_id, _name, _parents, _reg, _sel) \
236 1.1 skrll IMX_MUX_INDEX(_id, 0, _name, _parents, _reg, _sel)
237 1.1 skrll
238 1.1 skrll #define IMX_MUX_INDEX(_id, _regidx, _name, _parents, _reg, _sel) \
239 1.1 skrll { \
240 1.1 skrll .id = (_id), \
241 1.1 skrll .regidx = (_regidx), \
242 1.1 skrll .type = IMX_CCM_MUX, \
243 1.1 skrll .base.name = (_name), \
244 1.1 skrll .base.flags = CLK_SET_RATE_PARENT, \
245 1.1 skrll .u.mux.parents = (_parents), \
246 1.1 skrll .u.mux.nparents = __arraycount(_parents), \
247 1.1 skrll .u.mux.reg = (_reg), \
248 1.1 skrll .u.mux.sel = (_sel), \
249 1.1 skrll .get_parent = imx_ccm_mux_get_parent, \
250 1.1 skrll .set_parent = imx_ccm_mux_set_parent, \
251 1.1 skrll }
252 1.1 skrll
253 1.1 skrll /* Divider clocks */
254 1.1 skrll
255 1.1 skrll struct imx_ccm_div {
256 1.1 skrll bus_size_t reg;
257 1.1 skrll const char *parent;
258 1.1 skrll uint32_t mask;
259 1.1 skrll u_int flags;
260 1.1 skrll #define IMX_DIV_SET_RATE_PARENT __BIT(0)
261 1.1 skrll #define IMX_DIV_ROUND_DOWN __BIT(1)
262 1.1 skrll };
263 1.1 skrll
264 1.1 skrll u_int imx_ccm_div_get_rate(struct imx_ccm_softc *, struct imx_ccm_clk *);
265 1.1 skrll int imx_ccm_div_set_rate(struct imx_ccm_softc *, struct imx_ccm_clk *, u_int);
266 1.1 skrll const char *imx_ccm_div_get_parent(struct imx_ccm_softc *, struct imx_ccm_clk *);
267 1.1 skrll
268 1.1 skrll #define IMX_DIV(_id, _name, _parent, _reg, _mask, _flags) \
269 1.1 skrll IMX_DIV_INDEX(_id, 0, _name, _parent, _reg, _mask, _flags)
270 1.1 skrll #define IMX_DIV_INDEX(_id, _regidx, _name, _parent, _reg, _mask, _flags) \
271 1.1 skrll { \
272 1.1 skrll .id = (_id), \
273 1.1 skrll .regidx = (_regidx), \
274 1.1 skrll .type = IMX_CCM_DIV, \
275 1.1 skrll .base.name = (_name), \
276 1.1 skrll .base.flags = 0, \
277 1.1 skrll .u.div.parent = (_parent), \
278 1.1 skrll .u.div.reg = (_reg), \
279 1.1 skrll .u.div.mask = (_mask), \
280 1.1 skrll .u.div.flags = (_flags), \
281 1.1 skrll .get_rate = imx_ccm_div_get_rate, \
282 1.1 skrll .set_rate = imx_ccm_div_set_rate, \
283 1.1 skrll .get_parent = imx_ccm_div_get_parent, \
284 1.1 skrll }
285 1.1 skrll
286 1.1 skrll /*
287 1.1 skrll * IMX clock definition
288 1.1 skrll */
289 1.1 skrll
290 1.1 skrll struct imx_ccm_clk {
291 1.1 skrll struct clk base;
292 1.1 skrll u_int id;
293 1.1 skrll u_int regidx;
294 1.1 skrll enum imx_ccm_clktype type;
295 1.1 skrll union {
296 1.1 skrll struct imx_ccm_gate gate;
297 1.1 skrll struct imx_ccm_composite composite;
298 1.1 skrll struct imx_ccm_pll pll;
299 1.1 skrll struct imx_ccm_fixed fixed;
300 1.1 skrll struct imx_ccm_fixed_factor fixed_factor;
301 1.1 skrll struct imx_ccm_mux mux;
302 1.1 skrll struct imx_ccm_div div;
303 1.1 skrll const char *extclk;
304 1.1 skrll } u;
305 1.1 skrll
306 1.1 skrll int (*enable)(struct imx_ccm_softc *,
307 1.1 skrll struct imx_ccm_clk *, int);
308 1.1 skrll u_int (*get_rate)(struct imx_ccm_softc *,
309 1.1 skrll struct imx_ccm_clk *);
310 1.1 skrll int (*set_rate)(struct imx_ccm_softc *,
311 1.1 skrll struct imx_ccm_clk *, u_int);
312 1.1 skrll u_int (*round_rate)(struct imx_ccm_softc *,
313 1.1 skrll struct imx_ccm_clk *, u_int);
314 1.1 skrll const char * (*get_parent)(struct imx_ccm_softc *,
315 1.1 skrll struct imx_ccm_clk *);
316 1.1 skrll int (*set_parent)(struct imx_ccm_softc *,
317 1.1 skrll struct imx_ccm_clk *,
318 1.1 skrll const char *);
319 1.1 skrll };
320 1.1 skrll
321 1.1 skrll /*
322 1.1 skrll * Driver state
323 1.1 skrll */
324 1.1 skrll
325 1.1 skrll struct imx_ccm_softc {
326 1.1 skrll device_t sc_dev;
327 1.1 skrll int sc_phandle;
328 1.1 skrll bus_space_tag_t sc_bst;
329 1.1 skrll bus_space_handle_t sc_bsh[2];
330 1.1 skrll
331 1.1 skrll bus_addr_t sc_baseaddr;
332 1.1 skrll
333 1.1 skrll struct clk_domain sc_clkdom;
334 1.1 skrll
335 1.1 skrll struct imx_ccm_clk *sc_clks;
336 1.1 skrll u_int sc_nclks;
337 1.1 skrll };
338 1.1 skrll
339 1.1 skrll int imx_ccm_attach(struct imx_ccm_softc *);
340 1.1 skrll struct imx_ccm_clk *imx_ccm_clock_find(struct imx_ccm_softc *,
341 1.1 skrll const char *);
342 1.1 skrll void imx_ccm_print(struct imx_ccm_softc *);
343 1.1 skrll
344 1.1 skrll extern const struct clk_funcs imx_ccm_clock_funcs;
345 1.1 skrll
346 1.1 skrll #define CCM_READ(sc, idx, reg) \
347 1.1 skrll bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh[idx], (reg))
348 1.1 skrll #define CCM_WRITE(sc, idx, reg, val) \
349 1.1 skrll bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh[idx], (reg), (val))
350 1.1 skrll
351 1.1 skrll #endif /* _ARM_IMX_CCM_H */
352