1/*-
2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
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 * $FreeBSD$
28 */
29
30#ifndef	IMX6_CCM_CLK_H
31#define	IMX6_CCM_CLK_H
32
33#include <dev/extres/clk/clk.h>
34#include <dev/extres/clk/clk_div.h>
35#include <dev/extres/clk/clk_fixed.h>
36#include <dev/extres/clk/clk_gate.h>
37#include <dev/extres/clk/clk_link.h>
38
39enum imx_clk_type {
40	IMX_CLK_UNDEFINED = 0,
41	IMX_CLK_FIXED,
42	IMX_CLK_LINK,
43	IMX_CLK_MUX,
44	IMX_CLK_GATE,
45	IMX_CLK_COMPOSITE,
46	IMX_CLK_SSCG_PLL,
47	IMX_CLK_FRAC_PLL,
48	IMX_CLK_DIV,
49};
50
51struct imx_clk {
52	enum imx_clk_type	type;
53	union {
54		struct clk_fixed_def		*fixed;
55		struct clk_link_def		*link;
56		struct imx_clk_mux_def		*mux;
57		struct imx_clk_gate_def		*gate;
58		struct imx_clk_composite_def	*composite;
59		struct imx_clk_sscg_pll_def	*sscg_pll;
60		struct imx_clk_frac_pll_def	*frac_pll;
61		struct clk_div_def		*div;
62	} clk;
63};
64
65/* Linked clock. */
66#define	LINK(_id, _name)						\
67{									\
68	.type = IMX_CLK_LINK,						\
69	.clk.link = &(struct clk_link_def) {				\
70		.clkdef.id = _id,					\
71		.clkdef.name = _name,					\
72		.clkdef.parent_names = NULL,				\
73		.clkdef.parent_cnt = 0,					\
74		.clkdef.flags = CLK_NODE_STATIC_STRINGS,		\
75	},								\
76}
77
78/* Complex clock without divider (multiplexer only). */
79#define MUX(_id, _name, _pn, _f,  _mo, _ms, _mw)			\
80{									\
81	.type = IMX_CLK_MUX,						\
82	.clk.mux = &(struct imx_clk_mux_def) {				\
83		.clkdef.id = _id,					\
84		.clkdef.name = _name,					\
85		.clkdef.parent_names = _pn,				\
86		.clkdef.parent_cnt = nitems(_pn),			\
87		.clkdef.flags = CLK_NODE_STATIC_STRINGS,		\
88		.offset = _mo,						\
89		.shift = _ms,						\
90		.width = _mw,						\
91		.mux_flags = _f, 					\
92	},								\
93}
94
95/* Fixed frequency clock */
96#define	FIXED(_id, _name, _freq)					\
97{									\
98	.type = IMX_CLK_FIXED,						\
99	.clk.fixed = &(struct clk_fixed_def) {				\
100		.clkdef.id = _id,					\
101		.clkdef.name = _name,					\
102		.clkdef.flags = CLK_NODE_STATIC_STRINGS,		\
103		.freq = _freq,						\
104	},								\
105}
106
107/* Fixed factor multipier/divider. */
108#define	FFACT(_id, _name, _pname, _mult, _div)				\
109{									\
110	.type = IMX_CLK_FIXED,						\
111	.clk.fixed = &(struct clk_fixed_def) {				\
112		.clkdef.id = _id,					\
113		.clkdef.name = _name,					\
114		.clkdef.parent_names = (const char *[]){_pname},	\
115		.clkdef.parent_cnt = 1,					\
116		.clkdef.flags = CLK_NODE_STATIC_STRINGS,		\
117		.mult = _mult,						\
118		.div = _div,						\
119	},								\
120}
121
122/* Clock gate */
123#define	GATE(_id, _name, _pname, _o, _shift)				\
124{									\
125	.type = IMX_CLK_GATE,						\
126	.clk.gate = &(struct imx_clk_gate_def) {			\
127		.clkdef.id = _id,					\
128		.clkdef.name = _name,					\
129		.clkdef.parent_names = (const char *[]){_pname},	\
130		.clkdef.parent_cnt = 1,					\
131		.clkdef.flags = CLK_NODE_STATIC_STRINGS,		\
132		.offset = _o,						\
133		.shift = _shift,					\
134		.mask = 1,						\
135	},								\
136}
137
138/* Root clock gate */
139#define	ROOT_GATE(_id, _name, _pname, _reg)				\
140{									\
141	.type = IMX_CLK_GATE,						\
142	.clk.gate = &(struct imx_clk_gate_def) {			\
143		.clkdef.id = _id,					\
144		.clkdef.name = _name,					\
145		.clkdef.parent_names = (const char *[]){_pname},	\
146		.clkdef.parent_cnt = 1,					\
147		.clkdef.flags = CLK_NODE_STATIC_STRINGS,		\
148		.offset = _reg,						\
149		.shift = 0,						\
150		.mask = 3,						\
151	},								\
152}
153
154/* Composite clock with GATE, MUX, PRE_DIV, and POST_DIV */
155#define COMPOSITE(_id, _name, _pn, _o, _flags)				\
156{									\
157	.type = IMX_CLK_COMPOSITE,					\
158	.clk.composite = &(struct imx_clk_composite_def) {		\
159		.clkdef.id = _id,					\
160		.clkdef.name = _name,					\
161		.clkdef.parent_names = _pn,				\
162		.clkdef.parent_cnt = nitems(_pn),			\
163		.clkdef.flags = CLK_NODE_STATIC_STRINGS,		\
164		.offset = _o,						\
165		.flags = _flags,					\
166	},								\
167}
168
169/* SSCG PLL */
170#define SSCG_PLL(_id, _name, _pn, _o)					\
171{									\
172	.type = IMX_CLK_SSCG_PLL,					\
173	.clk.composite = &(struct imx_clk_composite_def) {		\
174		.clkdef.id = _id,					\
175		.clkdef.name = _name,					\
176		.clkdef.parent_names = _pn,				\
177		.clkdef.parent_cnt = nitems(_pn),			\
178		.clkdef.flags = CLK_NODE_STATIC_STRINGS,		\
179		.offset = _o,						\
180	},								\
181}
182
183/* Fractional PLL */
184#define FRAC_PLL(_id, _name, _pname, _o)				\
185{									\
186	.type = IMX_CLK_FRAC_PLL,					\
187	.clk.frac_pll = &(struct imx_clk_frac_pll_def) {		\
188		.clkdef.id = _id,					\
189		.clkdef.name = _name,					\
190		.clkdef.parent_names = (const char *[]){_pname},	\
191		.clkdef.parent_cnt = 1,					\
192		.clkdef.flags = CLK_NODE_STATIC_STRINGS,		\
193		.offset = _o,						\
194	},								\
195}
196
197#define DIV(_id, _name, _pname, _o, _shift, _width)			\
198{									\
199	.type = IMX_CLK_DIV,						\
200	.clk.div = &(struct clk_div_def) {				\
201		.clkdef.id = _id,					\
202		.clkdef.name = _name,					\
203		.clkdef.parent_names = (const char *[]){_pname},	\
204		.clkdef.parent_cnt = 1,					\
205		.clkdef.flags = CLK_NODE_STATIC_STRINGS,		\
206		.offset = _o,						\
207		.i_shift = _shift,					\
208		.i_width = _width,					\
209	},								\
210}
211
212#endif
213