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