xref: /linux/drivers/clk/spacemit/ccu_mix.h (revision 9f32a03e3e0d372c520d829dd4da6022fe88832a)
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  */
20 struct ccu_gate_config {
21 	u32 mask;
22 };
23 
24 struct ccu_factor_config {
25 	u32 div;
26 	u32 mul;
27 };
28 
29 struct ccu_mux_config {
30 	u8 shift;
31 	u8 width;
32 };
33 
34 struct ccu_div_config {
35 	u8 shift;
36 	u8 width;
37 };
38 
39 struct ccu_mix {
40 	struct ccu_factor_config factor;
41 	struct ccu_gate_config gate;
42 	struct ccu_div_config div;
43 	struct ccu_mux_config mux;
44 	struct ccu_common common;
45 };
46 
47 #define CCU_GATE_INIT(_mask)		{ .mask = _mask }
48 #define CCU_FACTOR_INIT(_div, _mul)	{ .div = _div, .mul = _mul }
49 #define CCU_MUX_INIT(_shift, _width)	{ .shift = _shift, .width = _width }
50 #define CCU_DIV_INIT(_shift, _width)	{ .shift = _shift, .width = _width }
51 
52 #define CCU_PARENT_HW(_parent)		{ .hw = &_parent.common.hw }
53 #define CCU_PARENT_NAME(_name)		{ .fw_name = #_name }
54 
55 #define CCU_MIX_INITHW(_name, _parent, _ops, _flags)			\
56 	.hw.init = &(struct clk_init_data) {				\
57 		.flags		= _flags,				\
58 		.name		= #_name,				\
59 		.parent_data	= (const struct clk_parent_data[])	\
60 					{ _parent },			\
61 		.num_parents	= 1,					\
62 		.ops		= &_ops,				\
63 	}
64 
65 #define CCU_MIX_INITHW_PARENTS(_name, _parents, _ops, _flags)		\
66 	.hw.init = CLK_HW_INIT_PARENTS_DATA(#_name, _parents, &_ops, _flags)
67 
68 #define CCU_GATE_DEFINE(_name, _parent, _reg_ctrl, _mask_gate, _flags)		\
69 static struct ccu_mix _name = {							\
70 	.gate	= CCU_GATE_INIT(_mask_gate),					\
71 	.common	= {								\
72 		.reg_ctrl	= _reg_ctrl,					\
73 		CCU_MIX_INITHW(_name, _parent, spacemit_ccu_gate_ops, _flags),	\
74 	}									\
75 }
76 
77 #define CCU_FACTOR_DEFINE(_name, _parent, _div, _mul)				\
78 static struct ccu_mix _name = {							\
79 	.factor	= CCU_FACTOR_INIT(_div, _mul),					\
80 	.common = {								\
81 		CCU_MIX_INITHW(_name, _parent, spacemit_ccu_factor_ops, 0),	\
82 	}									\
83 }
84 
85 #define CCU_MUX_DEFINE(_name, _parents, _reg_ctrl, _shift, _width, _flags)	\
86 static struct ccu_mix _name = {							\
87 	.mux	= CCU_MUX_INIT(_shift, _width),					\
88 	.common = {								\
89 		.reg_ctrl	= _reg_ctrl,					\
90 		CCU_MIX_INITHW_PARENTS(_name, _parents, spacemit_ccu_mux_ops,	\
91 				       _flags),					\
92 	}									\
93 }
94 
95 #define CCU_DIV_DEFINE(_name, _parent, _reg_ctrl, _shift, _width, _flags)	\
96 static struct ccu_mix _name = {							\
97 	.div	= CCU_DIV_INIT(_shift, _width),					\
98 	.common = {								\
99 		.reg_ctrl	= _reg_ctrl,					\
100 		CCU_MIX_INITHW(_name, _parent, spacemit_ccu_div_ops, _flags)	\
101 	}									\
102 }
103 
104 #define CCU_FACTOR_GATE_DEFINE(_name, _parent, _reg_ctrl, _mask_gate, _div,	\
105 			       _mul)						\
106 static struct ccu_mix _name = {							\
107 	.gate	= CCU_GATE_INIT(_mask_gate),					\
108 	.factor	= CCU_FACTOR_INIT(_div, _mul),					\
109 	.common = {								\
110 		.reg_ctrl	= _reg_ctrl,					\
111 		CCU_MIX_INITHW(_name, _parent, spacemit_ccu_factor_gate_ops, 0)	\
112 	}									\
113 }
114 
115 #define CCU_MUX_GATE_DEFINE(_name, _parents, _reg_ctrl, _shift, _width,		\
116 			    _mask_gate, _flags)					\
117 static struct ccu_mix _name = {							\
118 	.gate	= CCU_GATE_INIT(_mask_gate),					\
119 	.mux	= CCU_MUX_INIT(_shift, _width),					\
120 	.common = {								\
121 		.reg_ctrl	= _reg_ctrl,					\
122 		CCU_MIX_INITHW_PARENTS(_name, _parents,				\
123 				       spacemit_ccu_mux_gate_ops, _flags),	\
124 	}									\
125 }
126 
127 #define CCU_DIV_GATE_DEFINE(_name, _parent, _reg_ctrl, _shift, _width,		\
128 			    _mask_gate,	_flags)					\
129 static struct ccu_mix _name = {							\
130 	.gate	= CCU_GATE_INIT(_mask_gate),					\
131 	.div	= CCU_DIV_INIT(_shift, _width),					\
132 	.common = {								\
133 		.reg_ctrl	= _reg_ctrl,					\
134 		CCU_MIX_INITHW(_name, _parent, spacemit_ccu_div_gate_ops,	\
135 			       _flags),						\
136 	}									\
137 }
138 
139 #define CCU_MUX_DIV_GATE_DEFINE(_name, _parents, _reg_ctrl, _mshift, _mwidth,	\
140 				 _muxshift, _muxwidth, _mask_gate, _flags)	\
141 static struct ccu_mix _name = {							\
142 	.gate	= CCU_GATE_INIT(_mask_gate),					\
143 	.div	= CCU_DIV_INIT(_mshift, _mwidth),				\
144 	.mux	= CCU_MUX_INIT(_muxshift, _muxwidth),				\
145 	.common	= {								\
146 		.reg_ctrl	= _reg_ctrl,					\
147 		CCU_MIX_INITHW_PARENTS(_name, _parents,				\
148 				       spacemit_ccu_mux_div_gate_ops, _flags),	\
149 	},									\
150 }
151 
152 #define CCU_MUX_DIV_GATE_SPLIT_FC_DEFINE(_name, _parents, _reg_ctrl, _reg_fc,	\
153 					 _mshift, _mwidth, _mask_fc, _muxshift,	\
154 					 _muxwidth, _mask_gate, _flags)		\
155 static struct ccu_mix _name = {							\
156 	.gate	= CCU_GATE_INIT(_mask_gate),					\
157 	.div	= CCU_DIV_INIT(_mshift, _mwidth),				\
158 	.mux	= CCU_MUX_INIT(_muxshift, _muxwidth),				\
159 	.common = {								\
160 		.reg_ctrl	= _reg_ctrl,					\
161 		.reg_fc		= _reg_fc,					\
162 		.mask_fc	= _mask_fc,					\
163 		CCU_MIX_INITHW_PARENTS(_name, _parents,				\
164 				       spacemit_ccu_mux_div_gate_ops, _flags),	\
165 	},									\
166 }
167 
168 #define CCU_MUX_DIV_GATE_FC_DEFINE(_name, _parents, _reg_ctrl, _mshift, _mwidth,\
169 				   _mask_fc, _muxshift, _muxwidth, _mask_gate,	\
170 				   _flags)					\
171 CCU_MUX_DIV_GATE_SPLIT_FC_DEFINE(_name, _parents, _reg_ctrl, _reg_ctrl, _mshift,\
172 				 _mwidth, _mask_fc, _muxshift, _muxwidth,	\
173 				 _mask_gate, _flags)
174 
175 #define CCU_MUX_DIV_FC_DEFINE(_name, _parents, _reg_ctrl, _mshift, _mwidth,	\
176 			      _mask_fc, _muxshift, _muxwidth, _flags)		\
177 static struct ccu_mix _name = {							\
178 	.div	= CCU_DIV_INIT(_mshift, _mwidth),				\
179 	.mux	= CCU_MUX_INIT(_muxshift, _muxwidth),				\
180 	.common = {								\
181 		.reg_ctrl	= _reg_ctrl,					\
182 		.reg_fc		= _reg_ctrl,					\
183 		.mask_fc	= _mask_fc,					\
184 		CCU_MIX_INITHW_PARENTS(_name, _parents,				\
185 				       spacemit_ccu_mux_div_ops, _flags),	\
186 	},									\
187 }
188 
189 #define CCU_MUX_FC_DEFINE(_name, _parents, _reg_ctrl, _mask_fc,	_muxshift,	\
190 			  _muxwidth, _flags)					\
191 static struct ccu_mix _name = {							\
192 	.mux	= CCU_MUX_INIT(_muxshift, _muxwidth),				\
193 	.common = {								\
194 		.reg_ctrl	= _reg_ctrl,					\
195 		.reg_fc		= _reg_ctrl,					\
196 		.mask_fc	= _mask_fc,					\
197 		CCU_MIX_INITHW_PARENTS(_name, _parents, spacemit_ccu_mux_ops,	\
198 				       _flags)					\
199 	},									\
200 }
201 
hw_to_ccu_mix(struct clk_hw * hw)202 static inline struct ccu_mix *hw_to_ccu_mix(struct clk_hw *hw)
203 {
204 	struct ccu_common *common = hw_to_ccu_common(hw);
205 
206 	return container_of(common, struct ccu_mix, common);
207 }
208 
209 extern const struct clk_ops spacemit_ccu_gate_ops;
210 extern const struct clk_ops spacemit_ccu_factor_ops;
211 extern const struct clk_ops spacemit_ccu_mux_ops;
212 extern const struct clk_ops spacemit_ccu_div_ops;
213 extern const struct clk_ops spacemit_ccu_factor_gate_ops;
214 extern const struct clk_ops spacemit_ccu_div_gate_ops;
215 extern const struct clk_ops spacemit_ccu_mux_gate_ops;
216 extern const struct clk_ops spacemit_ccu_mux_div_ops;
217 extern const struct clk_ops spacemit_ccu_mux_div_gate_ops;
218 #endif /* _CCU_DIV_H_ */
219