1/* SPDX-License-Identifier: GPL-2.0 */
2/*
3 * Copyright (C) 2023 Inochi Amaoto <inochiama@outlook.com>
4 */
5
6#ifndef _CLK_SOPHGO_CV1800_IP_H_
7#define _CLK_SOPHGO_CV1800_IP_H_
8
9#include "clk-cv18xx-common.h"
10
11struct cv1800_clk_gate {
12	struct cv1800_clk_common	common;
13	struct cv1800_clk_regbit	gate;
14};
15
16struct cv1800_clk_div_data {
17	u32		reg;
18	u32		mask;
19	u32		width;
20	u32		init;
21	u32		flags;
22};
23
24struct cv1800_clk_div {
25	struct cv1800_clk_common	common;
26	struct cv1800_clk_regbit	gate;
27	struct cv1800_clk_regfield	div;
28};
29
30struct cv1800_clk_bypass_div {
31	struct cv1800_clk_div		div;
32	struct cv1800_clk_regbit	bypass;
33};
34
35struct cv1800_clk_mux {
36	struct cv1800_clk_common	common;
37	struct cv1800_clk_regbit	gate;
38	struct cv1800_clk_regfield	div;
39	struct cv1800_clk_regfield	mux;
40};
41
42struct cv1800_clk_bypass_mux {
43	struct cv1800_clk_mux		mux;
44	struct cv1800_clk_regbit	bypass;
45};
46
47struct cv1800_clk_mmux {
48	struct cv1800_clk_common	common;
49	struct cv1800_clk_regbit	gate;
50	struct cv1800_clk_regfield	div[2];
51	struct cv1800_clk_regfield	mux[2];
52	struct cv1800_clk_regbit	bypass;
53	struct cv1800_clk_regbit	clk_sel;
54	const s8			*parent2sel;
55	const u8			*sel2parent[2];
56};
57
58struct cv1800_clk_audio {
59	struct cv1800_clk_common	common;
60	struct cv1800_clk_regbit	src_en;
61	struct cv1800_clk_regbit	output_en;
62	struct cv1800_clk_regbit	div_en;
63	struct cv1800_clk_regbit	div_up;
64	struct cv1800_clk_regfield	m;
65	struct cv1800_clk_regfield	n;
66	u32				target_rate;
67};
68
69#define CV1800_GATE(_name, _parent, _gate_reg, _gate_shift, _flags)	\
70	struct cv1800_clk_gate _name = {				\
71		.common	= CV1800_CLK_COMMON(#_name, _parent,		\
72					    &cv1800_clk_gate_ops,	\
73					    _flags),			\
74		.gate	= CV1800_CLK_BIT(_gate_reg, _gate_shift),	\
75	}
76
77#define _CV1800_DIV(_name, _parent, _gate_reg, _gate_shift,		\
78		    _div_reg, _div_shift, _div_width, _div_init,	\
79		    _div_flag, _ops, _flags)				\
80	{								\
81		.common		= CV1800_CLK_COMMON(#_name, _parent,	\
82						    _ops, _flags),	\
83		.gate		= CV1800_CLK_BIT(_gate_reg,		\
84						 _gate_shift),		\
85		.div		= CV1800_CLK_REG(_div_reg, _div_shift,	\
86						 _div_width, _div_init,	\
87						 _div_flag),		\
88	}
89
90#define _CV1800_FIXED_DIV_FLAG	\
91	(CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ROUND_CLOSEST)
92
93#define _CV1800_FIXED_DIV(_name, _parent, _gate_reg, _gate_shift,	\
94			  _fix_div, _ops, _flags)			\
95	{								\
96		.common		= CV1800_CLK_COMMON(#_name, _parent,	\
97						    _ops, _flags),	\
98		.gate		= CV1800_CLK_BIT(_gate_reg,		\
99						 _gate_shift),		\
100		.div		= CV1800_CLK_REG(0, 0, 0,		\
101						 _fix_div,		\
102						 _CV1800_FIXED_DIV_FLAG),\
103	}
104
105#define CV1800_DIV(_name, _parent, _gate_reg, _gate_shift,		\
106		   _div_reg, _div_shift, _div_width, _div_init,		\
107		   _div_flag, _flags)					\
108	struct cv1800_clk_div _name =					\
109		_CV1800_DIV(_name, _parent, _gate_reg, _gate_shift,	\
110			    _div_reg, _div_shift, _div_width, _div_init,\
111			    _div_flag, &cv1800_clk_div_ops, _flags)
112
113#define CV1800_BYPASS_DIV(_name, _parent, _gate_reg, _gate_shift,	\
114			  _div_reg, _div_shift, _div_width, _div_init,	\
115			  _div_flag, _bypass_reg, _bypass_shift, _flags)\
116	struct cv1800_clk_bypass_div _name = {				\
117		.div	= _CV1800_DIV(_name, _parent,			\
118				      _gate_reg, _gate_shift,		\
119				      _div_reg, _div_shift,		\
120				      _div_width, _div_init, _div_flag,	\
121				      &cv1800_clk_bypass_div_ops,	\
122				      _flags),				\
123		.bypass	= CV1800_CLK_BIT(_bypass_reg, _bypass_shift),	\
124	}
125
126#define CV1800_FIXED_DIV(_name, _parent, _gate_reg, _gate_shift,	\
127			 _fix_div, _flags)				\
128	struct cv1800_clk_div _name =					\
129		_CV1800_FIXED_DIV(_name, _parent,			\
130				  _gate_reg, _gate_shift,		\
131				  _fix_div,				\
132				  &cv1800_clk_div_ops, _flags)		\
133
134#define CV1800_BYPASS_FIXED_DIV(_name, _parent, _gate_reg, _gate_shift,	\
135				_fix_div, _bypass_reg, _bypass_shift,	\
136				_flags)					\
137	struct cv1800_clk_bypass_div _name = {				\
138		.div	= _CV1800_FIXED_DIV(_name, _parent,		\
139					    _gate_reg, _gate_shift,	\
140					    _fix_div,			\
141					    &cv1800_clk_bypass_div_ops,	\
142					    _flags),			\
143		.bypass	= CV1800_CLK_BIT(_bypass_reg, _bypass_shift),	\
144	}
145
146#define _CV1800_MUX(_name, _parent, _gate_reg, _gate_shift,		\
147		    _div_reg, _div_shift, _div_width, _div_init,	\
148		    _div_flag,						\
149		    _mux_reg, _mux_shift, _mux_width,			\
150		    _ops, _flags)					\
151	{								\
152		.common		= CV1800_CLK_COMMON(#_name, _parent,	\
153						    _ops, _flags),	\
154		.gate		= CV1800_CLK_BIT(_gate_reg,		\
155						 _gate_shift),		\
156		.div		= CV1800_CLK_REG(_div_reg, _div_shift,	\
157						 _div_width, _div_init,	\
158						 _div_flag),		\
159		.mux		= CV1800_CLK_REG(_mux_reg, _mux_shift,	\
160						 _mux_width, 0, 0),	\
161	}
162
163#define CV1800_MUX(_name, _parent, _gate_reg, _gate_shift,		\
164		   _div_reg, _div_shift, _div_width, _div_init,		\
165		   _div_flag,						\
166		   _mux_reg, _mux_shift, _mux_width, _flags)		\
167	struct cv1800_clk_mux _name =					\
168		_CV1800_MUX(_name, _parent, _gate_reg, _gate_shift,	\
169			    _div_reg, _div_shift, _div_width, _div_init,\
170			    _div_flag, _mux_reg, _mux_shift, _mux_width,\
171			    &cv1800_clk_mux_ops, _flags)
172
173#define CV1800_BYPASS_MUX(_name, _parent, _gate_reg, _gate_shift,	\
174			  _div_reg, _div_shift, _div_width, _div_init,	\
175			  _div_flag,					\
176			  _mux_reg, _mux_shift, _mux_width,		\
177			  _bypass_reg, _bypass_shift, _flags)		\
178	struct cv1800_clk_bypass_mux _name = {				\
179		.mux	= _CV1800_MUX(_name, _parent,			\
180				      _gate_reg, _gate_shift,		\
181				      _div_reg, _div_shift, _div_width,	\
182				      _div_init, _div_flag,		\
183				      _mux_reg, _mux_shift, _mux_width,	\
184				      &cv1800_clk_bypass_mux_ops,	\
185				      _flags),				\
186		.bypass	= CV1800_CLK_BIT(_bypass_reg, _bypass_shift),	\
187	}
188
189#define CV1800_MMUX(_name, _parent, _gate_reg, _gate_shift,		\
190		    _div0_reg, _div0_shift, _div0_width, _div0_init,	\
191		    _div0_flag,						\
192		    _div1_reg, _div1_shift, _div1_width, _div1_init,	\
193		    _div1_flag,						\
194		    _mux0_reg, _mux0_shift, _mux0_width,		\
195		    _mux1_reg, _mux1_shift, _mux1_width,		\
196		    _bypass_reg, _bypass_shift,				\
197		    _clk_sel_reg, _clk_sel_shift,			\
198		    _parent2sel, _sel2parent0, _sel2parent1, _flags)	\
199	struct cv1800_clk_mmux _name = {				\
200		.common		= CV1800_CLK_COMMON(#_name, _parent,	\
201						    &cv1800_clk_mmux_ops,\
202						    _flags),		\
203		.gate		= CV1800_CLK_BIT(_gate_reg, _gate_shift),\
204		.div		= {					\
205			CV1800_CLK_REG(_div0_reg, _div0_shift,		\
206				       _div0_width, _div0_init,		\
207				       _div0_flag),			\
208			CV1800_CLK_REG(_div1_reg, _div1_shift,		\
209				       _div1_width, _div1_init,		\
210				       _div1_flag),			\
211		},							\
212		.mux		= {					\
213			CV1800_CLK_REG(_mux0_reg, _mux0_shift,		\
214				       _mux0_width, 0, 0),		\
215			CV1800_CLK_REG(_mux1_reg, _mux1_shift,		\
216				       _mux1_width, 0, 0),		\
217		},							\
218		.bypass		= CV1800_CLK_BIT(_bypass_reg,		\
219						 _bypass_shift),	\
220		.clk_sel	= CV1800_CLK_BIT(_clk_sel_reg,		\
221						 _clk_sel_shift),	\
222		.parent2sel	= _parent2sel,				\
223		.sel2parent	= { _sel2parent0, _sel2parent1 },	\
224	}
225
226#define CV1800_ACLK(_name, _parent,					\
227		    _src_en_reg, _src_en_reg_shift,			\
228		    _output_en_reg, _output_en_shift,			\
229		    _div_en_reg, _div_en_reg_shift,			\
230		    _div_up_reg, _div_up_reg_shift,			\
231		    _m_reg, _m_shift, _m_width, _m_flag,		\
232		    _n_reg, _n_shift, _n_width, _n_flag,		\
233		    _target_rate, _flags)				\
234	struct cv1800_clk_audio _name = {				\
235		.common		= CV1800_CLK_COMMON(#_name, _parent,	\
236						    &cv1800_clk_audio_ops,\
237						    _flags),		\
238		.src_en		= CV1800_CLK_BIT(_src_en_reg,		\
239						 _src_en_reg_shift),	\
240		.output_en	= CV1800_CLK_BIT(_output_en_reg,	\
241						 _output_en_shift),	\
242		.div_en		= CV1800_CLK_BIT(_div_en_reg,		\
243						 _div_en_reg_shift),	\
244		.div_up		= CV1800_CLK_BIT(_div_up_reg,		\
245						 _div_up_reg_shift),	\
246		.m		= CV1800_CLK_REG(_m_reg, _m_shift,	\
247						 _m_width, 0, _m_flag),	\
248		.n		= CV1800_CLK_REG(_n_reg, _n_shift,	\
249						 _n_width, 0, _n_flag),	\
250		.target_rate	= _target_rate,				\
251	}
252
253extern const struct clk_ops cv1800_clk_gate_ops;
254extern const struct clk_ops cv1800_clk_div_ops;
255extern const struct clk_ops cv1800_clk_bypass_div_ops;
256extern const struct clk_ops cv1800_clk_mux_ops;
257extern const struct clk_ops cv1800_clk_bypass_mux_ops;
258extern const struct clk_ops cv1800_clk_mmux_ops;
259extern const struct clk_ops cv1800_clk_audio_ops;
260
261#endif // _CLK_SOPHGO_CV1800_IP_H_
262