xref: /linux/drivers/clk/spacemit/ccu_mix.h (revision be1ca3ee8f97067fee87fda73ea5959d5ab75bbf)
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 /*
3  * Copyright (c) 2024 SpacemiT Technology Co. Ltd
4  * Copyright (c) 2024-2025 Haylen Chu <heylenay@4d2.org>
5  */
6 
7 #ifndef _CCU_MIX_H_
8 #define _CCU_MIX_H_
9 
10 #include <linux/clk-provider.h>
11 
12 #include "ccu_common.h"
13 
14 /**
15  * struct ccu_gate_config - Gate configuration
16  *
17  * @mask:	Mask to enable the gate. Some clocks may have more than one bit
18  *		set in this field.
19  * @inverted:	Enable bit is inverted, 1 - disable clock, 0 - enable clock
20  */
21 struct ccu_gate_config {
22 	u32 mask;
23 	bool inverted;
24 };
25 
26 struct ccu_factor_config {
27 	u32 div;
28 	u32 mul;
29 };
30 
31 struct ccu_mux_config {
32 	u8 shift;
33 	u8 width;
34 };
35 
36 struct ccu_div_config {
37 	u8 shift;
38 	u8 width;
39 };
40 
41 struct ccu_mix {
42 	struct ccu_factor_config factor;
43 	struct ccu_gate_config gate;
44 	struct ccu_div_config div;
45 	struct ccu_mux_config mux;
46 	struct ccu_common common;
47 };
48 
49 #define CCU_GATE_INIT(_mask)		{ .mask = _mask }
50 #define CCU_FACTOR_INIT(_div, _mul)	{ .div = _div, .mul = _mul }
51 #define CCU_MUX_INIT(_shift, _width)	{ .shift = _shift, .width = _width }
52 #define CCU_DIV_INIT(_shift, _width)	{ .shift = _shift, .width = _width }
53 #define CCU_GATE_FLAGS_INIT(_mask, _inverted)	{ .mask = _mask, .inverted = _inverted }
54 
55 #define CCU_PARENT_HW(_parent)		{ .hw = &_parent.common.hw }
56 #define CCU_PARENT_NAME(_name)		{ .fw_name = #_name }
57 
58 #define CCU_MIX_INITHW(_name, _parent, _ops, _flags)			\
59 	.hw.init = &(struct clk_init_data) {				\
60 		.flags		= _flags,				\
61 		.name		= #_name,				\
62 		.parent_data	= (const struct clk_parent_data[])	\
63 					{ _parent },			\
64 		.num_parents	= 1,					\
65 		.ops		= &_ops,				\
66 	}
67 
68 #define CCU_MIX_INITHW_PARENTS(_name, _parents, _ops, _flags)		\
69 	.hw.init = CLK_HW_INIT_PARENTS_DATA(#_name, _parents, &_ops, _flags)
70 
71 #define CCU_GATE_DEFINE(_name, _parent, _reg_ctrl, _mask_gate, _flags)		\
72 static struct ccu_mix _name = {							\
73 	.gate	= CCU_GATE_INIT(_mask_gate),					\
74 	.common	= {								\
75 		.reg_ctrl	= _reg_ctrl,					\
76 		CCU_MIX_INITHW(_name, _parent, spacemit_ccu_gate_ops, _flags),	\
77 	}									\
78 }
79 
80 #define CCU_FACTOR_DEFINE(_name, _parent, _div, _mul)				\
81 static struct ccu_mix _name = {							\
82 	.factor	= CCU_FACTOR_INIT(_div, _mul),					\
83 	.common = {								\
84 		CCU_MIX_INITHW(_name, _parent, spacemit_ccu_factor_ops, 0),	\
85 	}									\
86 }
87 
88 #define CCU_MUX_DEFINE(_name, _parents, _reg_ctrl, _shift, _width, _flags)	\
89 static struct ccu_mix _name = {							\
90 	.mux	= CCU_MUX_INIT(_shift, _width),					\
91 	.common = {								\
92 		.reg_ctrl	= _reg_ctrl,					\
93 		CCU_MIX_INITHW_PARENTS(_name, _parents, spacemit_ccu_mux_ops,	\
94 				       _flags),					\
95 	}									\
96 }
97 
98 #define CCU_DIV_DEFINE(_name, _parent, _reg_ctrl, _shift, _width, _flags)	\
99 static struct ccu_mix _name = {							\
100 	.div	= CCU_DIV_INIT(_shift, _width),					\
101 	.common = {								\
102 		.reg_ctrl	= _reg_ctrl,					\
103 		CCU_MIX_INITHW(_name, _parent, spacemit_ccu_div_ops, _flags)	\
104 	}									\
105 }
106 
107 #define CCU_GATE_FLAGS_DEFINE(_name, _parent, _reg_ctrl, _mask_gate, _inverted, _flags)		\
108 static struct ccu_mix _name = {							\
109 	.gate	= CCU_GATE_FLAGS_INIT(_mask_gate, _inverted),			\
110 	.common	= {								\
111 		.reg_ctrl	= _reg_ctrl,					\
112 		CCU_MIX_INITHW(_name, _parent, spacemit_ccu_gate_ops, _flags),	\
113 	}									\
114 }
115 
116 #define CCU_FACTOR_GATE_FLAGS_DEFINE(_name, _parent, _reg_ctrl, _mask_gate, _div,	\
117 			       _mul, _flags)					\
118 static struct ccu_mix _name = {							\
119 	.gate	= CCU_GATE_INIT(_mask_gate),					\
120 	.factor	= CCU_FACTOR_INIT(_div, _mul),					\
121 	.common = {								\
122 		.reg_ctrl	= _reg_ctrl,					\
123 		CCU_MIX_INITHW(_name, _parent, spacemit_ccu_factor_gate_ops, _flags)	\
124 	}									\
125 }
126 
127 #define CCU_FACTOR_GATE_DEFINE(_name, _parent, _reg_ctrl, _mask_gate, _div,	\
128 			       _mul)						\
129 	CCU_FACTOR_GATE_FLAGS_DEFINE(_name, _parent, _reg_ctrl, _mask_gate, _div,	\
130 			       _mul, 0)
131 
132 #define CCU_MUX_GATE_DEFINE(_name, _parents, _reg_ctrl, _shift, _width,		\
133 			    _mask_gate, _flags)					\
134 static struct ccu_mix _name = {							\
135 	.gate	= CCU_GATE_INIT(_mask_gate),					\
136 	.mux	= CCU_MUX_INIT(_shift, _width),					\
137 	.common = {								\
138 		.reg_ctrl	= _reg_ctrl,					\
139 		CCU_MIX_INITHW_PARENTS(_name, _parents,				\
140 				       spacemit_ccu_mux_gate_ops, _flags),	\
141 	}									\
142 }
143 
144 #define CCU_DIV_GATE_DEFINE(_name, _parent, _reg_ctrl, _shift, _width,		\
145 			    _mask_gate,	_flags)					\
146 static struct ccu_mix _name = {							\
147 	.gate	= CCU_GATE_INIT(_mask_gate),					\
148 	.div	= CCU_DIV_INIT(_shift, _width),					\
149 	.common = {								\
150 		.reg_ctrl	= _reg_ctrl,					\
151 		CCU_MIX_INITHW(_name, _parent, spacemit_ccu_div_gate_ops,	\
152 			       _flags),						\
153 	}									\
154 }
155 
156 #define CCU_MUX_DIV_GATE_DEFINE(_name, _parents, _reg_ctrl, _mshift, _mwidth,	\
157 				 _muxshift, _muxwidth, _mask_gate, _flags)	\
158 static struct ccu_mix _name = {							\
159 	.gate	= CCU_GATE_INIT(_mask_gate),					\
160 	.div	= CCU_DIV_INIT(_mshift, _mwidth),				\
161 	.mux	= CCU_MUX_INIT(_muxshift, _muxwidth),				\
162 	.common	= {								\
163 		.reg_ctrl	= _reg_ctrl,					\
164 		CCU_MIX_INITHW_PARENTS(_name, _parents,				\
165 				       spacemit_ccu_mux_div_gate_ops, _flags),	\
166 	},									\
167 }
168 
169 #define CCU_MUX_DIV_GATE_SPLIT_FC_DEFINE(_name, _parents, _reg_ctrl, _reg_fc,	\
170 					 _mshift, _mwidth, _mask_fc, _muxshift,	\
171 					 _muxwidth, _mask_gate, _flags)		\
172 static struct ccu_mix _name = {							\
173 	.gate	= CCU_GATE_INIT(_mask_gate),					\
174 	.div	= CCU_DIV_INIT(_mshift, _mwidth),				\
175 	.mux	= CCU_MUX_INIT(_muxshift, _muxwidth),				\
176 	.common = {								\
177 		.reg_ctrl	= _reg_ctrl,					\
178 		.reg_fc		= _reg_fc,					\
179 		.mask_fc	= _mask_fc,					\
180 		CCU_MIX_INITHW_PARENTS(_name, _parents,				\
181 				       spacemit_ccu_mux_div_gate_ops, _flags),	\
182 	},									\
183 }
184 
185 #define CCU_MUX_DIV_GATE_FC_DEFINE(_name, _parents, _reg_ctrl, _mshift, _mwidth,\
186 				   _mask_fc, _muxshift, _muxwidth, _mask_gate,	\
187 				   _flags)					\
188 CCU_MUX_DIV_GATE_SPLIT_FC_DEFINE(_name, _parents, _reg_ctrl, _reg_ctrl, _mshift,\
189 				 _mwidth, _mask_fc, _muxshift, _muxwidth,	\
190 				 _mask_gate, _flags)
191 
192 #define CCU_MUX_DIV_FC_DEFINE(_name, _parents, _reg_ctrl, _mshift, _mwidth,	\
193 			      _mask_fc, _muxshift, _muxwidth, _flags)		\
194 static struct ccu_mix _name = {							\
195 	.div	= CCU_DIV_INIT(_mshift, _mwidth),				\
196 	.mux	= CCU_MUX_INIT(_muxshift, _muxwidth),				\
197 	.common = {								\
198 		.reg_ctrl	= _reg_ctrl,					\
199 		.reg_fc		= _reg_ctrl,					\
200 		.mask_fc	= _mask_fc,					\
201 		CCU_MIX_INITHW_PARENTS(_name, _parents,				\
202 				       spacemit_ccu_mux_div_ops, _flags),	\
203 	},									\
204 }
205 
206 #define CCU_MUX_FC_DEFINE(_name, _parents, _reg_ctrl, _mask_fc,	_muxshift,	\
207 			  _muxwidth, _flags)					\
208 static struct ccu_mix _name = {							\
209 	.mux	= CCU_MUX_INIT(_muxshift, _muxwidth),				\
210 	.common = {								\
211 		.reg_ctrl	= _reg_ctrl,					\
212 		.reg_fc		= _reg_ctrl,					\
213 		.mask_fc	= _mask_fc,					\
214 		CCU_MIX_INITHW_PARENTS(_name, _parents, spacemit_ccu_mux_ops,	\
215 				       _flags)					\
216 	},									\
217 }
218 
219 static inline struct ccu_mix *hw_to_ccu_mix(struct clk_hw *hw)
220 {
221 	struct ccu_common *common = hw_to_ccu_common(hw);
222 
223 	return container_of(common, struct ccu_mix, common);
224 }
225 
226 extern const struct clk_ops spacemit_ccu_gate_ops;
227 extern const struct clk_ops spacemit_ccu_factor_ops;
228 extern const struct clk_ops spacemit_ccu_mux_ops;
229 extern const struct clk_ops spacemit_ccu_div_ops;
230 extern const struct clk_ops spacemit_ccu_factor_gate_ops;
231 extern const struct clk_ops spacemit_ccu_div_gate_ops;
232 extern const struct clk_ops spacemit_ccu_mux_gate_ops;
233 extern const struct clk_ops spacemit_ccu_mux_div_ops;
234 extern const struct clk_ops spacemit_ccu_mux_div_gate_ops;
235 #endif /* _CCU_MIX_H_ */
236