1 /* SPDX-License-Identifier: GPL-2.0+ */
2 /*
3  * Copyright (c) 2024, Kongyang Liu <seashell11234455@gmail.com>
4  *
5  */
6 
7 #ifndef __CLK_SOPHGO_IP_H__
8 #define __CLK_SOPHGO_IP_H__
9 
10 #include <clk.h>
11 
12 #include "clk-common.h"
13 
14 struct cv1800b_mmux_parent_info {
15 	const char *name;
16 	u8 clk_sel;
17 	u8 index;
18 };
19 
20 struct cv1800b_clk_gate {
21 	struct clk clk;
22 	const char *name;
23 	const char *parent_name;
24 	void __iomem *base;
25 	struct cv1800b_clk_regbit gate;
26 };
27 
28 struct cv1800b_clk_div {
29 	struct clk clk;
30 	const char *name;
31 	const char *parent_name;
32 	void __iomem *base;
33 	struct cv1800b_clk_regbit gate;
34 	struct cv1800b_clk_regfield div;
35 	int div_init;
36 };
37 
38 struct cv1800b_clk_bypass_div {
39 	struct cv1800b_clk_div div;
40 	struct cv1800b_clk_regbit bypass;
41 };
42 
43 struct cv1800b_clk_fixed_div {
44 	struct clk clk;
45 	const char *name;
46 	const char *parent_name;
47 	void __iomem *base;
48 	struct cv1800b_clk_regbit gate;
49 	int div;
50 };
51 
52 struct cv1800b_clk_bypass_fixed_div {
53 	struct cv1800b_clk_fixed_div div;
54 	struct cv1800b_clk_regbit bypass;
55 };
56 
57 struct cv1800b_clk_mux {
58 	struct clk clk;
59 	const char *name;
60 	const char * const *parent_names;
61 	u8 num_parents;
62 	void __iomem *base;
63 	struct cv1800b_clk_regbit gate;
64 	struct cv1800b_clk_regfield div;
65 	int div_init;
66 	struct cv1800b_clk_regfield mux;
67 };
68 
69 struct cv1800b_clk_bypass_mux {
70 	struct cv1800b_clk_mux mux;
71 	struct cv1800b_clk_regbit bypass;
72 };
73 
74 struct cv1800b_clk_mmux {
75 	struct clk clk;
76 	const char *name;
77 	const struct cv1800b_mmux_parent_info *parent_infos;
78 	u8 num_parents;
79 	void __iomem *base;
80 	struct cv1800b_clk_regbit gate;
81 	struct cv1800b_clk_regfield div[2];
82 	int div_init[2];
83 	struct cv1800b_clk_regfield mux[2];
84 	struct cv1800b_clk_regbit bypass;
85 	struct cv1800b_clk_regbit clk_sel;
86 };
87 
88 struct cv1800b_clk_audio {
89 	struct clk clk;
90 	const char *name;
91 	const char *parent_name;
92 	void __iomem *base;
93 	struct cv1800b_clk_regbit src_en;
94 	struct cv1800b_clk_regbit output_en;
95 	struct cv1800b_clk_regbit div_en;
96 	struct cv1800b_clk_regbit div_up;
97 	struct cv1800b_clk_regfield m;
98 	struct cv1800b_clk_regfield n;
99 };
100 
101 #define CV1800B_GATE(_id, _name, _parent,				\
102 		     _gate_offset, _gate_shift,				\
103 		     _flags)						\
104 	{								\
105 		.clk = {						\
106 			.id = CV1800B_CLK_ID_TRANSFORM(_id),		\
107 			.flags = _flags,				\
108 		},							\
109 		.name = _name,						\
110 		.parent_name = _parent,					\
111 		.gate = CV1800B_CLK_REGBIT(_gate_offset, _gate_shift),	\
112 	}
113 
114 #define CV1800B_DIV(_id, _name, _parent,				\
115 		    _gate_offset, _gate_shift,				\
116 		    _div_offset, _div_shift, _div_width,		\
117 		    _div_init, _flags)					\
118 	{								\
119 		.clk = {						\
120 			.id = CV1800B_CLK_ID_TRANSFORM(_id),		\
121 			.flags = _flags,				\
122 		},							\
123 		.name = _name,						\
124 		.parent_name = _parent,					\
125 		.gate = CV1800B_CLK_REGBIT(_gate_offset, _gate_shift),	\
126 		.div = CV1800B_CLK_REGFIELD(_div_offset, _div_shift,	\
127 					    _div_width),		\
128 		.div_init = _div_init,					\
129 	}
130 
131 #define CV1800B_BYPASS_DIV(_id, _name, _parent,				\
132 			   _gate_offset, _gate_shift,			\
133 			   _div_offset, _div_shift,			\
134 			   _div_width, _div_init,			\
135 			   _bypass_offset, _bypass_shift,		\
136 			   _flags)					\
137 	{								\
138 		.div = CV1800B_DIV(_id, _name, _parent,			\
139 				   _gate_offset, _gate_shift,		\
140 				   _div_offset, _div_shift, _div_width,	\
141 				   _div_init, _flags),			\
142 		.bypass = CV1800B_CLK_REGBIT(_bypass_offset,		\
143 					     _bypass_shift),		\
144 	}
145 
146 #define CV1800B_FIXED_DIV(_id, _name, _parent,				\
147 			  _gate_offset, _gate_shift,			\
148 			  _div, _flags)					\
149 	{								\
150 		.clk = {						\
151 			.id = CV1800B_CLK_ID_TRANSFORM(_id),		\
152 			.flags = _flags,				\
153 		},							\
154 		.name = _name,						\
155 		.parent_name = _parent,					\
156 		.gate = CV1800B_CLK_REGBIT(_gate_offset, _gate_shift),	\
157 		.div = _div,						\
158 	}
159 
160 #define CV1800B_BYPASS_FIXED_DIV(_id, _name, _parent,			\
161 				 _gate_offset, _gate_shift,		\
162 				 _div,					\
163 				 _bypass_offset, _bypass_shift,		\
164 				 _flags)				\
165 	{								\
166 		.div = CV1800B_FIXED_DIV(_id, _name, _parent,		\
167 					 _gate_offset, _gate_shift,	\
168 					 _div, _flags),			\
169 		.bypass = CV1800B_CLK_REGBIT(_bypass_offset,		\
170 					     _bypass_shift)		\
171 	}
172 
173 #define CV1800B_MUX(_id, _name, _parents,				\
174 		    _gate_offset, _gate_shift,				\
175 		    _div_offset, _div_shift, _div_width, _div_init,	\
176 		    _mux_offset, _mux_shift, _mux_width,		\
177 		    _flags)						\
178 	{								\
179 		.clk = {						\
180 			.id = CV1800B_CLK_ID_TRANSFORM(_id),		\
181 			.flags = _flags,				\
182 		},							\
183 		.name = _name,						\
184 		.parent_names = _parents,				\
185 		.num_parents = ARRAY_SIZE(_parents),			\
186 		.gate = CV1800B_CLK_REGBIT(_gate_offset, _gate_shift),	\
187 		.div = CV1800B_CLK_REGFIELD(_div_offset, _div_shift,	\
188 					    _div_width),		\
189 		.div_init = _div_init,					\
190 		.mux = CV1800B_CLK_REGFIELD(_mux_offset, _mux_shift,	\
191 					    _mux_width),		\
192 	}
193 
194 #define CV1800B_BYPASS_MUX(_id, _name, _parents,			\
195 			   _gate_offset, _gate_shift,			\
196 			   _div_offset, _div_shift,			\
197 			   _div_width, _div_init,			\
198 			   _mux_offset, _mux_shift, _mux_width,		\
199 			   _bypass_offset, _bypass_shift,		\
200 			   _flags)					\
201 	{								\
202 		.mux = CV1800B_MUX(_id, _name, _parents,		\
203 				   _gate_offset, _gate_shift,		\
204 				   _div_offset, _div_shift,		\
205 				   _div_width, _div_init,		\
206 				   _mux_offset, _mux_shift, _mux_width,	\
207 				   _flags),				\
208 		.bypass = CV1800B_CLK_REGBIT(_bypass_offset,		\
209 					     _bypass_shift),		\
210 	}
211 
212 #define CV1800B_MMUX(_id, _name, _parents,				\
213 		     _gate_offset, _gate_shift,				\
214 		     _div0_offset, _div0_shift, _div0_width, _div0_init,\
215 		     _div1_offset, _div1_shift, _div1_width, _div1_init,\
216 		     _mux0_offset, _mux0_shift, _mux0_width,		\
217 		     _mux1_offset, _mux1_shift, _mux1_width,		\
218 		     _bypass_offset, _bypass_shift,			\
219 		     _clk_sel_offset, _clk_sel_shift,			\
220 		     _flags)						\
221 	{								\
222 		.clk = {						\
223 			.id = CV1800B_CLK_ID_TRANSFORM(_id),		\
224 			.flags = _flags,				\
225 		},							\
226 		.name = _name,						\
227 		.parent_infos = _parents,				\
228 		.num_parents = ARRAY_SIZE(_parents),			\
229 		.gate = CV1800B_CLK_REGBIT(_gate_offset, _gate_shift),	\
230 		.div = {						\
231 			CV1800B_CLK_REGFIELD(_div0_offset, _div0_shift,	\
232 					     _div0_width),		\
233 			CV1800B_CLK_REGFIELD(_div1_offset, _div1_shift,	\
234 					     _div1_width),		\
235 		},							\
236 		.div_init = { _div0_init, _div1_init },			\
237 		.mux = {						\
238 			CV1800B_CLK_REGFIELD(_mux0_offset, _mux0_shift,	\
239 					     _mux0_width),		\
240 			CV1800B_CLK_REGFIELD(_mux1_offset, _mux1_shift,	\
241 					     _mux1_width),		\
242 		},							\
243 		.bypass = CV1800B_CLK_REGBIT(_bypass_offset,		\
244 					     _bypass_shift),		\
245 		.clk_sel = CV1800B_CLK_REGBIT(_clk_sel_offset,		\
246 					      _clk_sel_shift),		\
247 	}
248 
249 #define CV1800B_AUDIO(_id, _name, _parent,				\
250 		      _src_en_offset, _src_en_shift,			\
251 		      _output_en_offset, _output_en_shift,		\
252 		      _div_en_offset, _div_en_shift,			\
253 		      _div_up_offset, _div_up_shift,			\
254 		      _m_offset, _m_shift, _m_width,			\
255 		      _n_offset, _n_shift, _n_width,			\
256 		      _flags)						\
257 	{								\
258 		.clk = {						\
259 			.id = CV1800B_CLK_ID_TRANSFORM(_id),		\
260 			.flags = _flags,				\
261 		},							\
262 		.name = _name,						\
263 		.parent_name = _parent,					\
264 		.src_en = CV1800B_CLK_REGBIT(_src_en_offset,		\
265 					     _src_en_shift),		\
266 		.output_en = CV1800B_CLK_REGBIT(_output_en_offset,	\
267 						_output_en_shift),	\
268 		.div_en = CV1800B_CLK_REGBIT(_div_en_offset,		\
269 					     _div_en_shift),		\
270 		.div_up = CV1800B_CLK_REGBIT(_div_up_offset,		\
271 					     _div_up_shift),		\
272 		.m = CV1800B_CLK_REGFIELD(_m_offset, _m_shift,		\
273 					  _m_width),			\
274 		.n = CV1800B_CLK_REGFIELD(_n_offset, _n_shift,		\
275 					  _n_width),			\
276 	}
277 
278 extern const struct clk_ops cv1800b_clk_gate_ops;
279 extern const struct clk_ops cv1800b_clk_div_ops;
280 extern const struct clk_ops cv1800b_clk_bypass_div_ops;
281 extern const struct clk_ops cv1800b_clk_fixed_div_ops;
282 extern const struct clk_ops cv1800b_clk_bypass_fixed_div_ops;
283 extern const struct clk_ops cv1800b_clk_mux_ops;
284 extern const struct clk_ops cv1800b_clk_bypass_mux_ops;
285 extern const struct clk_ops cv1800b_clk_mmux_ops;
286 extern const struct clk_ops cv1800b_clk_audio_ops;
287 
288 #endif /* __CLK_SOPHGO_IP_H__ */
289