FreeBSD/Linux Kernel Cross Reference
sys/arm/mv/clk/periph.h
1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3 *
4 * Copyright (c) 2021 Semihalf.
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 * $FreeBSD$
28 *
29 */
30
31 #ifndef _PERIPH_H_
32 #define _PERIPH_H_
33
34 #include <dev/extres/clk/clk.h>
35 #include <dev/extres/clk/clk_mux.h>
36 #include <dev/extres/clk/clk_div.h>
37 #include <dev/extres/clk/clk_gate.h>
38
39 #define TBG_SEL 0x0
40 #define DIV_SEL0 0x4
41 #define DIV_SEL1 0x8
42 #define DIV_SEL2 0xC
43 #define CLK_SEL 0x10
44 #define CLK_DIS 0x14
45 #define DIV_MASK 0x7
46
47 #define MUX_POS 1
48 #define DIV1_POS 2
49 #define DIV2_POS 3
50 #define GATE_POS 4
51 #define FIXED1_POS 5
52 #define FIXED2_POS 6
53 #define CLK_MUX_POS 7
54
55 #define RD4(_clk, offset, val) \
56 CLKDEV_READ_4(clknode_get_device(_clk), offset, val)
57
58 #define A37x0_INTERNAL_CLK_ID(_base, _pos) \
59 ((_base * 10) + (_pos))
60
61 #define CLK_FULL_DD(_name, _id, _gate_shift, _tbg_mux_shift, \
62 _clk_mux_shift, _div1_reg, _div2_reg, _div1_shift, _div2_shift, \
63 _tbg_mux_name, _div1_name, _div2_name, _clk_mux_name) \
64 { \
65 .type = CLK_FULL_DD, \
66 .common_def.device_name = _name, \
67 .common_def.device_id = _id, \
68 .clk_def.full_dd.tbg_mux.clkdef.name = _tbg_mux_name, \
69 .clk_def.full_dd.tbg_mux.offset = TBG_SEL, \
70 .clk_def.full_dd.tbg_mux.shift = _tbg_mux_shift, \
71 .clk_def.full_dd.tbg_mux.width = 0x2, \
72 .clk_def.full_dd.tbg_mux.mux_flags = 0x0, \
73 .clk_def.full_dd.div1.clkdef.name = _div1_name, \
74 .clk_def.full_dd.div1.offset = _div1_reg, \
75 .clk_def.full_dd.div1.i_shift = _div1_shift, \
76 .clk_def.full_dd.div1.i_width = 0x3, \
77 .clk_def.full_dd.div1.f_shift = 0x0, \
78 .clk_def.full_dd.div1.f_width = 0x0, \
79 .clk_def.full_dd.div1.div_flags = 0x0, \
80 .clk_def.full_dd.div1.div_table = NULL, \
81 .clk_def.full_dd.div2.clkdef.name = _div2_name, \
82 .clk_def.full_dd.div2.offset = _div2_reg, \
83 .clk_def.full_dd.div2.i_shift = _div2_shift, \
84 .clk_def.full_dd.div2.i_width = 0x3, \
85 .clk_def.full_dd.div2.f_shift = 0x0, \
86 .clk_def.full_dd.div2.f_width = 0x0, \
87 .clk_def.full_dd.div2.div_flags = 0x0, \
88 .clk_def.full_dd.div2.div_table = NULL, \
89 .clk_def.full_dd.clk_mux.clkdef.name = _clk_mux_name, \
90 .clk_def.full_dd.clk_mux.offset = CLK_SEL, \
91 .clk_def.full_dd.clk_mux.shift = _clk_mux_shift, \
92 .clk_def.full_dd.clk_mux.width = 0x1, \
93 .clk_def.full_dd.clk_mux.mux_flags = 0x0, \
94 .clk_def.full_dd.gate.clkdef.name = _name, \
95 .clk_def.full_dd.gate.offset = CLK_DIS, \
96 .clk_def.full_dd.gate.shift = _gate_shift, \
97 .clk_def.full_dd.gate.on_value = 0, \
98 .clk_def.full_dd.gate.off_value = 1, \
99 .clk_def.full_dd.gate.mask = 0x1, \
100 .clk_def.full_dd.gate.gate_flags = 0x0 \
101 }
102
103 #define CLK_FULL(_name, _id, _gate_shift, _tbg_mux_shift, \
104 _clk_mux_shift, _div1_reg, _div1_shift, _div_table, _tbg_mux_name, \
105 _div1_name, _clk_mux_name) \
106 { \
107 .type = CLK_FULL, \
108 .common_def.device_name = _name, \
109 .common_def.device_id = _id, \
110 .clk_def.full_d.tbg_mux.clkdef.name = _tbg_mux_name, \
111 .clk_def.full_d.tbg_mux.offset = TBG_SEL, \
112 .clk_def.full_d.tbg_mux.shift = _tbg_mux_shift, \
113 .clk_def.full_d.tbg_mux.width = 0x2, \
114 .clk_def.full_d.tbg_mux.mux_flags = 0x0, \
115 .clk_def.full_d.div.clkdef.name = _div1_name, \
116 .clk_def.full_d.div.offset = _div1_reg, \
117 .clk_def.full_d.div.i_shift = _div1_shift, \
118 .clk_def.full_d.div.i_width = 0x3, \
119 .clk_def.full_d.div.f_shift = 0x0, \
120 .clk_def.full_d.div.f_width = 0x0, \
121 .clk_def.full_d.div.div_flags = 0x0, \
122 .clk_def.full_d.div.div_table = _div_table, \
123 .clk_def.full_d.clk_mux.clkdef.name = _clk_mux_name, \
124 .clk_def.full_d.clk_mux.offset = CLK_SEL, \
125 .clk_def.full_d.clk_mux.shift = _clk_mux_shift, \
126 .clk_def.full_d.clk_mux.width = 0x1, \
127 .clk_def.full_d.clk_mux.mux_flags = 0x0, \
128 .clk_def.full_d.gate.clkdef.name = _name, \
129 .clk_def.full_d.gate.offset = CLK_DIS, \
130 .clk_def.full_d.gate.shift = _gate_shift, \
131 .clk_def.full_d.gate.on_value = 0, \
132 .clk_def.full_d.gate.off_value = 1, \
133 .clk_def.full_d.gate.mask = 0x1, \
134 .clk_def.full_d.gate.gate_flags = 0x0 \
135 }
136
137 #define CLK_CPU(_name, _id, _tbg_mux_shift, _clk_mux_shift, _div1_reg, \
138 _div1_shift, _div_table, _tbg_mux_name, _div1_name) \
139 { \
140 .type = CLK_CPU, \
141 .common_def.device_name = _name, \
142 .common_def.device_id = _id, \
143 .clk_def.cpu.tbg_mux.clkdef.name = _tbg_mux_name, \
144 .clk_def.cpu.tbg_mux.offset = TBG_SEL, \
145 .clk_def.cpu.tbg_mux.shift = _tbg_mux_shift, \
146 .clk_def.cpu.tbg_mux.width = 0x2, \
147 .clk_def.cpu.tbg_mux.mux_flags = 0x0, \
148 .clk_def.cpu.div.clkdef.name = _div1_name, \
149 .clk_def.cpu.div.offset = _div1_reg, \
150 .clk_def.cpu.div.i_shift = _div1_shift, \
151 .clk_def.cpu.div.i_width = 0x3, \
152 .clk_def.cpu.div.f_shift = 0x0, \
153 .clk_def.cpu.div.f_width = 0x0, \
154 .clk_def.cpu.div.div_flags = 0x0, \
155 .clk_def.cpu.div.div_table = _div_table, \
156 .clk_def.cpu.clk_mux.clkdef.name = _name, \
157 .clk_def.cpu.clk_mux.offset = CLK_SEL, \
158 .clk_def.cpu.clk_mux.shift = _clk_mux_shift, \
159 .clk_def.cpu.clk_mux.width = 0x1, \
160 .clk_def.cpu.clk_mux.mux_flags = 0x0, \
161 }
162
163 #define CLK_GATE(_name, _id, _gate_shift, _pname) \
164 { \
165 .type = CLK_GATE, \
166 .common_def.device_name = _name, \
167 .common_def.device_id = _id, \
168 .common_def.pname = _pname, \
169 .clk_def.gate.gate.clkdef.name = _name, \
170 .clk_def.gate.gate.clkdef.parent_cnt = 1, \
171 .clk_def.gate.gate.offset = CLK_DIS, \
172 .clk_def.gate.gate.shift = _gate_shift, \
173 .clk_def.gate.gate.on_value = 0, \
174 .clk_def.gate.gate.off_value = 1, \
175 .clk_def.gate.gate.mask = 0x1, \
176 .clk_def.gate.gate.gate_flags = 0x0 \
177 }
178
179 #define CLK_MDD(_name, _id, _tbg_mux_shift, _clk_mux_shift, _div1_reg, \
180 _div2_reg, _div1_shift, _div2_shift, _tbg_mux_name, _div1_name, \
181 _div2_name) \
182 { \
183 .type = CLK_MDD, \
184 .common_def.device_name = _name, \
185 .common_def.device_id = _id, \
186 .clk_def.mdd.tbg_mux.clkdef.name = _tbg_mux_name, \
187 .clk_def.mdd.tbg_mux.offset = TBG_SEL, \
188 .clk_def.mdd.tbg_mux.shift = _tbg_mux_shift, \
189 .clk_def.mdd.tbg_mux.width = 0x2, \
190 .clk_def.mdd.tbg_mux.mux_flags = 0x0, \
191 .clk_def.mdd.div1.clkdef.name = _div1_name, \
192 .clk_def.mdd.div1.offset = _div1_reg, \
193 .clk_def.mdd.div1.i_shift = _div1_shift, \
194 .clk_def.mdd.div1.i_width = 0x3, \
195 .clk_def.mdd.div1.f_shift = 0x0, \
196 .clk_def.mdd.div1.f_width = 0x0, \
197 .clk_def.mdd.div1.div_flags = 0x0, \
198 .clk_def.mdd.div1.div_table = NULL, \
199 .clk_def.mdd.div2.clkdef.name = _div2_name, \
200 .clk_def.mdd.div2.offset = _div2_reg, \
201 .clk_def.mdd.div2.i_shift = _div2_shift, \
202 .clk_def.mdd.div2.i_width = 0x3, \
203 .clk_def.mdd.div2.f_shift = 0x0, \
204 .clk_def.mdd.div2.f_width = 0x0, \
205 .clk_def.mdd.div2.div_flags = 0x0, \
206 .clk_def.mdd.div2.div_table = NULL, \
207 .clk_def.mdd.clk_mux.clkdef.name = _name, \
208 .clk_def.mdd.clk_mux.offset = CLK_SEL, \
209 .clk_def.mdd.clk_mux.shift = _clk_mux_shift, \
210 .clk_def.mdd.clk_mux.width = 0x1, \
211 .clk_def.mdd.clk_mux.mux_flags = 0x0 \
212 }
213
214 #define CLK_MUX_GATE(_name, _id, _gate_shift, _mux_shift, _pname, \
215 _mux_name, _fixed_name) \
216 { \
217 .type = CLK_MUX_GATE, \
218 .common_def.device_name = _name, \
219 .common_def.device_id = _id, \
220 .common_def.pname = _pname, \
221 .clk_def.mux_gate.mux.clkdef.name = _mux_name, \
222 .clk_def.mux_gate.mux.offset = TBG_SEL, \
223 .clk_def.mux_gate.mux.shift = _mux_shift, \
224 .clk_def.mux_gate.mux.width = 0x1, \
225 .clk_def.mux_gate.mux.mux_flags = 0x0, \
226 .clk_def.mux_gate.gate.clkdef.name = _name, \
227 .clk_def.mux_gate.gate.offset = CLK_DIS, \
228 .clk_def.mux_gate.gate.shift = _gate_shift, \
229 .clk_def.mux_gate.gate.on_value = 0, \
230 .clk_def.mux_gate.gate.off_value = 1, \
231 .clk_def.mux_gate.gate.mask = 0x1, \
232 .clk_def.mux_gate.gate.gate_flags = 0x0, \
233 .clk_def.mux_gate.fixed.clkdef.name = _fixed_name \
234 }
235
236 #define CLK_MUX_GATE_FIXED(_name, _id, _gate_shift, _mux_shift, \
237 _mux_name, _gate_name, _fixed1_name) \
238 { \
239 .type = CLK_MUX_GATE_FIXED, \
240 .common_def.device_name = _name, \
241 .common_def.device_id = _id, \
242 .clk_def.mux_gate_fixed.mux.clkdef.name = _mux_name, \
243 .clk_def.mux_gate_fixed.mux.offset = TBG_SEL, \
244 .clk_def.mux_gate_fixed.mux.shift = _mux_shift, \
245 .clk_def.mux_gate_fixed.mux.width = 0x1, \
246 .clk_def.mux_gate_fixed.mux.mux_flags = 0x0, \
247 .clk_def.mux_gate_fixed.gate.clkdef.name = _gate_name, \
248 .clk_def.mux_gate_fixed.gate.offset = CLK_DIS, \
249 .clk_def.mux_gate_fixed.gate.shift = _gate_shift, \
250 .clk_def.mux_gate_fixed.gate.on_value = 0, \
251 .clk_def.mux_gate_fixed.gate.off_value = 1, \
252 .clk_def.mux_gate_fixed.gate.mask = 0x1, \
253 .clk_def.mux_gate_fixed.gate.gate_flags = 0x0, \
254 .clk_def.mux_gate_fixed.fixed1.clkdef.name = _fixed1_name, \
255 .clk_def.mux_gate_fixed.fixed2.clkdef.name = _name \
256 }
257
258 #define CLK_FIXED(_name, _id, _gate_shift, _mux_shift, _mux_name, \
259 _fixed_name) \
260 { \
261 .type = CLK_FIXED, \
262 .common_def.device_name = _name, \
263 .common_def.device_id = _id, \
264 .clk_def.fixed.mux.clkdef.name = _mux_name, \
265 .clk_def.fixed.mux.offset = TBG_SEL, \
266 .clk_def.fixed.mux.shift = _mux_shift, \
267 .clk_def.fixed.mux.width = 0x1, \
268 .clk_def.fixed.mux.mux_flags = 0x0, \
269 .clk_def.fixed.gate.clkdef.name = _name, \
270 .clk_def.fixed.gate.offset = CLK_DIS, \
271 .clk_def.fixed.gate.shift = _gate_shift, \
272 .clk_def.fixed.gate.on_value = 0, \
273 .clk_def.fixed.gate.off_value = 1, \
274 .clk_def.fixed.gate.mask = 0x1, \
275 .clk_def.fixed.gate.gate_flags = 0x0, \
276 .clk_def.fixed.fixed.clkdef.name = _fixed_name \
277 }
278
279 struct a37x0_periph_clk_softc {
280 device_t dev;
281 struct resource *res;
282 struct clkdom *clkdom;
283 struct mtx mtx;
284 struct a37x0_periph_clknode_def *devices;
285 int device_count;
286 };
287
288 struct a37x0_periph_clk_dd_def {
289 struct clk_mux_def tbg_mux;
290 struct clk_div_def div1;
291 struct clk_div_def div2;
292 struct clk_mux_def clk_mux;
293 struct clk_gate_def gate;
294 };
295
296 struct a37x0_periph_clk_cpu_def {
297 struct clk_mux_def tbg_mux;
298 struct clk_div_def div;
299 struct clk_mux_def clk_mux;
300 };
301
302 struct a37x0_periph_clk_d_def {
303 struct clk_mux_def tbg_mux;
304 struct clk_div_def div;
305 struct clk_mux_def clk_mux;
306 struct clk_gate_def gate;
307 };
308
309 struct a37x0_periph_clk_fixed_def {
310 struct clk_mux_def mux;
311 struct clk_fixed_def fixed;
312 struct clk_gate_def gate;
313 };
314
315 struct a37x0_periph_clk_gate_def {
316 struct clk_gate_def gate;
317 };
318
319 struct a37x0_periph_clk_mux_dd_def {
320 struct clk_mux_def tbg_mux;
321 struct clk_div_def div1;
322 struct clk_div_def div2;
323 struct clk_mux_def clk_mux;
324 };
325
326 struct a37x0_periph_clk_mux_div_def {
327 struct clk_mux_def mux;
328 struct clk_div_def div;
329 };
330
331 struct a37x0_periph_clk_mux_gate_def {
332 struct clk_mux_def mux;
333 struct clk_fixed_def fixed;
334 struct clk_gate_def gate;
335 };
336
337 struct a37x0_periph_clk_mux_gate_fixed_def {
338 struct clk_fixed_def fixed1;
339 struct clk_mux_def mux;
340 struct clk_gate_def gate;
341 struct clk_fixed_def fixed2;
342 };
343
344 enum a37x0_periph_clk_type {
345 /* Double divider clock */
346 CLK_FULL_DD,
347 /* Single divider clock */
348 CLK_FULL,
349 /* Gate clock */
350 CLK_GATE,
351 /* Mux, gate clock */
352 CLK_MUX_GATE,
353 /* CPU clock */
354 CLK_CPU,
355 /* Clock with fixed frequency divider */
356 CLK_FIXED,
357 /* Clock with double divider, without gate */
358 CLK_MDD,
359 /* Clock with two fixed frequency dividers */
360 CLK_MUX_GATE_FIXED
361 };
362
363 struct a37x0_periph_common_defs {
364 char *device_name;
365 int device_id;
366 int tbg_cnt;
367 const char *pname;
368 const char **tbgs;
369 const char *xtal;
370 };
371
372 union a37x0_periph_clocks_defs {
373 struct a37x0_periph_clk_dd_def full_dd;
374 struct a37x0_periph_clk_d_def full_d;
375 struct a37x0_periph_clk_gate_def gate;
376 struct a37x0_periph_clk_mux_gate_def mux_gate;
377 struct a37x0_periph_clk_cpu_def cpu;
378 struct a37x0_periph_clk_fixed_def fixed;
379 struct a37x0_periph_clk_mux_dd_def mdd;
380 struct a37x0_periph_clk_mux_gate_fixed_def mux_gate_fixed;
381 };
382
383 struct a37x0_periph_clknode_def {
384 enum a37x0_periph_clk_type type;
385 struct a37x0_periph_common_defs common_def;
386 union a37x0_periph_clocks_defs clk_def;
387 };
388
389 int a37x0_periph_create_mux(struct clkdom *,
390 struct clk_mux_def *, int);
391 int a37x0_periph_create_div(struct clkdom *,
392 struct clk_div_def *, int);
393 int a37x0_periph_create_gate(struct clkdom *,
394 struct clk_gate_def *, int);
395 void a37x0_periph_set_props(struct clknode_init_def *, const char **,
396 unsigned int);
397 int a37x0_periph_d_register_full_clk_dd(struct clkdom *,
398 struct a37x0_periph_clknode_def *);
399 int a37x0_periph_d_register_full_clk(struct clkdom *,
400 struct a37x0_periph_clknode_def *);
401 int a37x0_periph_d_register_periph_cpu(struct clkdom *,
402 struct a37x0_periph_clknode_def *);
403 int a37x0_periph_fixed_register_fixed(struct clkdom*,
404 struct a37x0_periph_clknode_def *);
405 int a37x0_periph_gate_register_gate(struct clkdom *,
406 struct a37x0_periph_clknode_def *);
407 int a37x0_periph_d_register_mdd(struct clkdom *,
408 struct a37x0_periph_clknode_def *);
409 int a37x0_periph_d_register_mux_div_clk(struct clkdom *,
410 struct a37x0_periph_clknode_def *);
411 int a37x0_periph_register_mux_gate(struct clkdom *,
412 struct a37x0_periph_clknode_def *);
413 int a37x0_periph_register_mux_gate_fixed(struct clkdom *,
414 struct a37x0_periph_clknode_def *);
415
416 int a37x0_periph_clk_read_4(device_t, bus_addr_t, uint32_t *);
417 void a37x0_periph_clk_device_unlock(device_t);
418 void a37x0_periph_clk_device_lock(device_t);
419 int a37x0_periph_clk_attach(device_t);
420 int a37x0_periph_clk_detach(device_t);
421
422 #endif
Cache object: 4bd15553e3d028be306ab829cf7eff80
|