xref: /freebsd/sys/arm/mv/clk/periph.h (revision 9768746b)
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
423