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