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 
11 struct cv1800_clk_gate {
12 	struct cv1800_clk_common	common;
13 	struct cv1800_clk_regbit	gate;
14 };
15 
16 struct cv1800_clk_div_data {
17 	u32		reg;
18 	u32		mask;
19 	u32		width;
20 	u32		init;
21 	u32		flags;
22 };
23 
24 struct cv1800_clk_div {
25 	struct cv1800_clk_common	common;
26 	struct cv1800_clk_regbit	gate;
27 	struct cv1800_clk_regfield	div;
28 };
29 
30 struct cv1800_clk_bypass_div {
31 	struct cv1800_clk_div		div;
32 	struct cv1800_clk_regbit	bypass;
33 };
34 
35 struct 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 
42 struct cv1800_clk_bypass_mux {
43 	struct cv1800_clk_mux		mux;
44 	struct cv1800_clk_regbit	bypass;
45 };
46 
47 struct 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 
58 struct 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 
253 extern const struct clk_ops cv1800_clk_gate_ops;
254 extern const struct clk_ops cv1800_clk_div_ops;
255 extern const struct clk_ops cv1800_clk_bypass_div_ops;
256 extern const struct clk_ops cv1800_clk_mux_ops;
257 extern const struct clk_ops cv1800_clk_bypass_mux_ops;
258 extern const struct clk_ops cv1800_clk_mmux_ops;
259 extern const struct clk_ops cv1800_clk_audio_ops;
260 
261 #endif // _CLK_SOPHGO_CV1800_IP_H_
262