xref: /openbmc/linux/drivers/clk/sunxi-ng/ccu_div.h (revision c900529f3d9161bfde5cca0754f83b4d3c3e0220)
19c92ab61SThomas Gleixner /* SPDX-License-Identifier: GPL-2.0-only */
2e9b93213SMaxime Ripard /*
3e9b93213SMaxime Ripard  * Copyright (c) 2016 Maxime Ripard. All rights reserved.
4e9b93213SMaxime Ripard  */
5e9b93213SMaxime Ripard 
6e9b93213SMaxime Ripard #ifndef _CCU_DIV_H_
7e9b93213SMaxime Ripard #define _CCU_DIV_H_
8e9b93213SMaxime Ripard 
9e9b93213SMaxime Ripard #include <linux/clk-provider.h>
10e9b93213SMaxime Ripard 
11e9b93213SMaxime Ripard #include "ccu_common.h"
12e9b93213SMaxime Ripard #include "ccu_mux.h"
13e9b93213SMaxime Ripard 
14e9c959a6SMaxime Ripard /**
15a501a14eSMaxime Ripard  * struct ccu_div_internal - Internal divider description
16e9c959a6SMaxime Ripard  * @shift: Bit offset of the divider in its register
17e9c959a6SMaxime Ripard  * @width: Width of the divider field in its register
1887ba9e59SMaxime Ripard  * @max: Maximum value allowed for that divider. This is the
1987ba9e59SMaxime Ripard  *       arithmetic value, not the maximum value to be set in the
2087ba9e59SMaxime Ripard  *       register.
21e9c959a6SMaxime Ripard  * @flags: clk_divider flags to apply on this divider
22e9c959a6SMaxime Ripard  * @table: Divider table pointer (if applicable)
23e9c959a6SMaxime Ripard  *
24e9c959a6SMaxime Ripard  * That structure represents a single divider, and is meant to be
25e9c959a6SMaxime Ripard  * embedded in other structures representing the various clock
26e9c959a6SMaxime Ripard  * classes.
27e9c959a6SMaxime Ripard  *
28e9c959a6SMaxime Ripard  * It is basically a wrapper around the clk_divider functions
29e9c959a6SMaxime Ripard  * arguments.
30e9c959a6SMaxime Ripard  */
31a501a14eSMaxime Ripard struct ccu_div_internal {
32e9b93213SMaxime Ripard 	u8			shift;
33e9b93213SMaxime Ripard 	u8			width;
34e9b93213SMaxime Ripard 
3587ba9e59SMaxime Ripard 	u32			max;
36e66f81bbSMaxime Ripard 	u32			offset;
3787ba9e59SMaxime Ripard 
38e9b93213SMaxime Ripard 	u32			flags;
39e9b93213SMaxime Ripard 
40e9b93213SMaxime Ripard 	struct clk_div_table	*table;
41e9b93213SMaxime Ripard };
42e9b93213SMaxime Ripard 
43e9b93213SMaxime Ripard #define _SUNXI_CCU_DIV_TABLE_FLAGS(_shift, _width, _table, _flags)	\
44e9b93213SMaxime Ripard 	{								\
45e9b93213SMaxime Ripard 		.shift	= _shift,					\
46e9b93213SMaxime Ripard 		.width	= _width,					\
47e9b93213SMaxime Ripard 		.flags	= _flags,					\
48e9b93213SMaxime Ripard 		.table	= _table,					\
49e9b93213SMaxime Ripard 	}
50e9b93213SMaxime Ripard 
51e9b93213SMaxime Ripard #define _SUNXI_CCU_DIV_TABLE(_shift, _width, _table)			\
52e9b93213SMaxime Ripard 	_SUNXI_CCU_DIV_TABLE_FLAGS(_shift, _width, _table, 0)
53e9b93213SMaxime Ripard 
54e66f81bbSMaxime Ripard #define _SUNXI_CCU_DIV_OFFSET_MAX_FLAGS(_shift, _width, _off, _max, _flags) \
5587ba9e59SMaxime Ripard 	{								\
5687ba9e59SMaxime Ripard 		.shift	= _shift,					\
5787ba9e59SMaxime Ripard 		.width	= _width,					\
5887ba9e59SMaxime Ripard 		.flags	= _flags,					\
5987ba9e59SMaxime Ripard 		.max	= _max,						\
60e66f81bbSMaxime Ripard 		.offset	= _off,						\
6187ba9e59SMaxime Ripard 	}
6287ba9e59SMaxime Ripard 
63e66f81bbSMaxime Ripard #define _SUNXI_CCU_DIV_MAX_FLAGS(_shift, _width, _max, _flags)		\
64e66f81bbSMaxime Ripard 	_SUNXI_CCU_DIV_OFFSET_MAX_FLAGS(_shift, _width, 1, _max, _flags)
65e66f81bbSMaxime Ripard 
6687ba9e59SMaxime Ripard #define _SUNXI_CCU_DIV_FLAGS(_shift, _width, _flags)			\
6787ba9e59SMaxime Ripard 	_SUNXI_CCU_DIV_MAX_FLAGS(_shift, _width, 0, _flags)
6887ba9e59SMaxime Ripard 
6987ba9e59SMaxime Ripard #define _SUNXI_CCU_DIV_MAX(_shift, _width, _max)			\
7087ba9e59SMaxime Ripard 	_SUNXI_CCU_DIV_MAX_FLAGS(_shift, _width, _max, 0)
7187ba9e59SMaxime Ripard 
72e66f81bbSMaxime Ripard #define _SUNXI_CCU_DIV_OFFSET(_shift, _width, _offset)			\
73e66f81bbSMaxime Ripard 	_SUNXI_CCU_DIV_OFFSET_MAX_FLAGS(_shift, _width, _offset, 0, 0)
74e66f81bbSMaxime Ripard 
75e9b93213SMaxime Ripard #define _SUNXI_CCU_DIV(_shift, _width)					\
7687ba9e59SMaxime Ripard 	_SUNXI_CCU_DIV_FLAGS(_shift, _width, 0)
77e9b93213SMaxime Ripard 
78e9b93213SMaxime Ripard struct ccu_div {
79e9b93213SMaxime Ripard 	u32			enable;
80e9b93213SMaxime Ripard 
81a501a14eSMaxime Ripard 	struct ccu_div_internal	div;
82e9b93213SMaxime Ripard 	struct ccu_mux_internal	mux;
83e9b93213SMaxime Ripard 	struct ccu_common	common;
84721353c0SPriit Laes 	unsigned int		fixed_post_div;
85e9b93213SMaxime Ripard };
86e9b93213SMaxime Ripard 
87e9b93213SMaxime Ripard #define SUNXI_CCU_DIV_TABLE_WITH_GATE(_struct, _name, _parent, _reg,	\
88e9b93213SMaxime Ripard 				      _shift, _width,			\
89e9b93213SMaxime Ripard 				      _table, _gate, _flags)		\
90e9b93213SMaxime Ripard 	struct ccu_div _struct = {					\
91e9b93213SMaxime Ripard 		.div		= _SUNXI_CCU_DIV_TABLE(_shift, _width,	\
92e9b93213SMaxime Ripard 						       _table),		\
93e9b93213SMaxime Ripard 		.enable		= _gate,				\
94e9b93213SMaxime Ripard 		.common	= {						\
95e9b93213SMaxime Ripard 			.reg		= _reg,				\
96e9b93213SMaxime Ripard 			.hw.init	= CLK_HW_INIT(_name,		\
97e9b93213SMaxime Ripard 						      _parent,		\
98e9b93213SMaxime Ripard 						      &ccu_div_ops,	\
99e9b93213SMaxime Ripard 						      _flags),		\
100e9b93213SMaxime Ripard 		}							\
101e9b93213SMaxime Ripard 	}
102e9b93213SMaxime Ripard 
103e9b93213SMaxime Ripard 
104e9b93213SMaxime Ripard #define SUNXI_CCU_DIV_TABLE(_struct, _name, _parent, _reg,		\
105e9b93213SMaxime Ripard 			    _shift, _width,				\
106e9b93213SMaxime Ripard 			    _table, _flags)				\
107e9b93213SMaxime Ripard 	SUNXI_CCU_DIV_TABLE_WITH_GATE(_struct, _name, _parent, _reg,	\
108e9b93213SMaxime Ripard 				      _shift, _width, _table, 0,	\
109e9b93213SMaxime Ripard 				      _flags)
110e9b93213SMaxime Ripard 
1113317cb17SSamuel Holland #define SUNXI_CCU_DIV_TABLE_HW(_struct, _name, _parent, _reg,		\
1123317cb17SSamuel Holland 			       _shift, _width,				\
1133317cb17SSamuel Holland 			       _table, _flags)				\
1143317cb17SSamuel Holland 	struct ccu_div _struct = {					\
1153317cb17SSamuel Holland 		.div		= _SUNXI_CCU_DIV_TABLE(_shift, _width,	\
1163317cb17SSamuel Holland 						       _table),		\
1173317cb17SSamuel Holland 		.common	= {						\
1183317cb17SSamuel Holland 			.reg		= _reg,				\
1193317cb17SSamuel Holland 			.hw.init	= CLK_HW_INIT_HW(_name,		\
1203317cb17SSamuel Holland 							 _parent,	\
1213317cb17SSamuel Holland 							 &ccu_div_ops,	\
1223317cb17SSamuel Holland 							 _flags),	\
1233317cb17SSamuel Holland 		}							\
1243317cb17SSamuel Holland 	}
1253317cb17SSamuel Holland 
1263317cb17SSamuel Holland 
1276f91c601SMaxime Ripard #define SUNXI_CCU_M_WITH_MUX_TABLE_GATE(_struct, _name,			\
1286f91c601SMaxime Ripard 					_parents, _table,		\
1296f91c601SMaxime Ripard 					_reg,				\
1306f91c601SMaxime Ripard 					_mshift, _mwidth,		\
1316f91c601SMaxime Ripard 					_muxshift, _muxwidth,		\
132e9b93213SMaxime Ripard 					_gate, _flags)			\
133e9b93213SMaxime Ripard 	struct ccu_div _struct = {					\
134e9b93213SMaxime Ripard 		.enable	= _gate,					\
135e9b93213SMaxime Ripard 		.div	= _SUNXI_CCU_DIV(_mshift, _mwidth),		\
1366f91c601SMaxime Ripard 		.mux	= _SUNXI_CCU_MUX_TABLE(_muxshift, _muxwidth, _table), \
137e9b93213SMaxime Ripard 		.common	= {						\
138e9b93213SMaxime Ripard 			.reg		= _reg,				\
139e9b93213SMaxime Ripard 			.hw.init	= CLK_HW_INIT_PARENTS(_name,	\
140e9b93213SMaxime Ripard 							      _parents, \
141e9b93213SMaxime Ripard 							      &ccu_div_ops, \
142e9b93213SMaxime Ripard 							      _flags),	\
143e9b93213SMaxime Ripard 		},							\
144e9b93213SMaxime Ripard 	}
145e9b93213SMaxime Ripard 
146*253795abSFrank Oltmanns #define SUNXI_CCU_M_WITH_MUX_TABLE_GATE_CLOSEST(_struct, _name,		\
147*253795abSFrank Oltmanns 						_parents, _table,	\
148*253795abSFrank Oltmanns 						_reg,			\
149*253795abSFrank Oltmanns 						_mshift, _mwidth,	\
150*253795abSFrank Oltmanns 						_muxshift, _muxwidth,	\
151*253795abSFrank Oltmanns 						_gate, _flags)		\
152*253795abSFrank Oltmanns 	struct ccu_div _struct = {					\
153*253795abSFrank Oltmanns 		.enable	= _gate,					\
154*253795abSFrank Oltmanns 		.div	= _SUNXI_CCU_DIV_FLAGS(_mshift, _mwidth, CLK_DIVIDER_ROUND_CLOSEST), \
155*253795abSFrank Oltmanns 		.mux	= _SUNXI_CCU_MUX_TABLE(_muxshift, _muxwidth, _table), \
156*253795abSFrank Oltmanns 		.common	= {						\
157*253795abSFrank Oltmanns 			.reg		= _reg,				\
158*253795abSFrank Oltmanns 			.hw.init	= CLK_HW_INIT_PARENTS(_name,	\
159*253795abSFrank Oltmanns 							      _parents, \
160*253795abSFrank Oltmanns 							      &ccu_div_ops, \
161*253795abSFrank Oltmanns 							      _flags),	\
162*253795abSFrank Oltmanns 			.features	= CCU_FEATURE_CLOSEST_RATE,	\
163*253795abSFrank Oltmanns 		},							\
164*253795abSFrank Oltmanns 	}
165*253795abSFrank Oltmanns 
1666f91c601SMaxime Ripard #define SUNXI_CCU_M_WITH_MUX_GATE(_struct, _name, _parents, _reg,	\
1676f91c601SMaxime Ripard 				  _mshift, _mwidth, _muxshift, _muxwidth, \
1686f91c601SMaxime Ripard 				  _gate, _flags)			\
1696f91c601SMaxime Ripard 	SUNXI_CCU_M_WITH_MUX_TABLE_GATE(_struct, _name,			\
1706f91c601SMaxime Ripard 					_parents, NULL,			\
1716f91c601SMaxime Ripard 					_reg, _mshift, _mwidth,		\
1726f91c601SMaxime Ripard 					_muxshift, _muxwidth,		\
1736f91c601SMaxime Ripard 					_gate, _flags)
1746f91c601SMaxime Ripard 
175*253795abSFrank Oltmanns #define SUNXI_CCU_M_WITH_MUX_GATE_CLOSEST(_struct, _name, _parents,	\
176*253795abSFrank Oltmanns 					  _reg, _mshift, _mwidth,	\
177*253795abSFrank Oltmanns 					  _muxshift, _muxwidth,		\
178*253795abSFrank Oltmanns 					  _gate, _flags)		\
179*253795abSFrank Oltmanns 	SUNXI_CCU_M_WITH_MUX_TABLE_GATE_CLOSEST(_struct, _name,		\
180*253795abSFrank Oltmanns 						_parents, NULL,		\
181*253795abSFrank Oltmanns 						_reg, _mshift, _mwidth,	\
182*253795abSFrank Oltmanns 						_muxshift, _muxwidth,	\
183*253795abSFrank Oltmanns 						_gate, _flags)
184*253795abSFrank Oltmanns 
185e9b93213SMaxime Ripard #define SUNXI_CCU_M_WITH_MUX(_struct, _name, _parents, _reg,		\
186e9b93213SMaxime Ripard 			     _mshift, _mwidth, _muxshift, _muxwidth,	\
187e9b93213SMaxime Ripard 			     _flags)					\
1886f91c601SMaxime Ripard 	SUNXI_CCU_M_WITH_MUX_TABLE_GATE(_struct, _name,			\
1896f91c601SMaxime Ripard 					_parents, NULL,			\
1906f91c601SMaxime Ripard 					_reg, _mshift, _mwidth,		\
1916f91c601SMaxime Ripard 					_muxshift, _muxwidth,		\
192e9b93213SMaxime Ripard 					0, _flags)
193e9b93213SMaxime Ripard 
194e9b93213SMaxime Ripard 
195e9b93213SMaxime Ripard #define SUNXI_CCU_M_WITH_GATE(_struct, _name, _parent, _reg,		\
196e9b93213SMaxime Ripard 			      _mshift, _mwidth,	_gate,			\
197e9b93213SMaxime Ripard 			      _flags)					\
198e9b93213SMaxime Ripard 	struct ccu_div _struct = {					\
199e9b93213SMaxime Ripard 		.enable	= _gate,					\
200e9b93213SMaxime Ripard 		.div	= _SUNXI_CCU_DIV(_mshift, _mwidth),		\
201e9b93213SMaxime Ripard 		.common	= {						\
202e9b93213SMaxime Ripard 			.reg		= _reg,				\
203e9b93213SMaxime Ripard 			.hw.init	= CLK_HW_INIT(_name,		\
204e9b93213SMaxime Ripard 						      _parent,		\
205e9b93213SMaxime Ripard 						      &ccu_div_ops,	\
206e9b93213SMaxime Ripard 						      _flags),		\
207e9b93213SMaxime Ripard 		},							\
208e9b93213SMaxime Ripard 	}
209e9b93213SMaxime Ripard 
210e9b93213SMaxime Ripard #define SUNXI_CCU_M(_struct, _name, _parent, _reg, _mshift, _mwidth,	\
211e9b93213SMaxime Ripard 		    _flags)						\
212e9b93213SMaxime Ripard 	SUNXI_CCU_M_WITH_GATE(_struct, _name, _parent, _reg,		\
213e9b93213SMaxime Ripard 			      _mshift, _mwidth, 0, _flags)
214e9b93213SMaxime Ripard 
2153317cb17SSamuel Holland #define SUNXI_CCU_M_DATA_WITH_MUX_GATE(_struct, _name, _parents, _reg,	\
2163317cb17SSamuel Holland 				       _mshift, _mwidth,		\
2173317cb17SSamuel Holland 				       _muxshift, _muxwidth,		\
2183317cb17SSamuel Holland 				       _gate, _flags)			\
2193317cb17SSamuel Holland 	struct ccu_div _struct = {					\
2203317cb17SSamuel Holland 		.enable	= _gate,					\
2213317cb17SSamuel Holland 		.div	= _SUNXI_CCU_DIV(_mshift, _mwidth),		\
2223317cb17SSamuel Holland 		.mux	= _SUNXI_CCU_MUX(_muxshift, _muxwidth),		\
2233317cb17SSamuel Holland 		.common	= {						\
2243317cb17SSamuel Holland 			.reg		= _reg,				\
2253317cb17SSamuel Holland 			.hw.init	= CLK_HW_INIT_PARENTS_DATA(_name, \
2263317cb17SSamuel Holland 								   _parents, \
2273317cb17SSamuel Holland 								   &ccu_div_ops, \
2283317cb17SSamuel Holland 								   _flags), \
2293317cb17SSamuel Holland 		},							\
2303317cb17SSamuel Holland 	}
2313317cb17SSamuel Holland 
2323317cb17SSamuel Holland #define SUNXI_CCU_M_DATA_WITH_MUX(_struct, _name, _parents, _reg,	\
2333317cb17SSamuel Holland 				  _mshift, _mwidth,			\
2343317cb17SSamuel Holland 				  _muxshift, _muxwidth,			\
2353317cb17SSamuel Holland 				  _flags)				\
2363317cb17SSamuel Holland 	SUNXI_CCU_M_DATA_WITH_MUX_GATE(_struct, _name, _parents, _reg,  \
2373317cb17SSamuel Holland 				       _mshift, _mwidth,		\
2383317cb17SSamuel Holland 				       _muxshift, _muxwidth,		\
2393317cb17SSamuel Holland 				       0, _flags)
2403317cb17SSamuel Holland 
2413317cb17SSamuel Holland #define SUNXI_CCU_M_HW_WITH_MUX_GATE(_struct, _name, _parents, _reg,	\
2423317cb17SSamuel Holland 				     _mshift, _mwidth, _muxshift, _muxwidth, \
2433317cb17SSamuel Holland 				     _gate, _flags)			\
2443317cb17SSamuel Holland 	struct ccu_div _struct = {					\
2453317cb17SSamuel Holland 		.enable	= _gate,					\
2463317cb17SSamuel Holland 		.div	= _SUNXI_CCU_DIV(_mshift, _mwidth),		\
2473317cb17SSamuel Holland 		.mux	= _SUNXI_CCU_MUX(_muxshift, _muxwidth),		\
2483317cb17SSamuel Holland 		.common	= {						\
2493317cb17SSamuel Holland 			.reg		= _reg,				\
2503317cb17SSamuel Holland 			.hw.init	= CLK_HW_INIT_PARENTS_HW(_name,	\
2513317cb17SSamuel Holland 								 _parents, \
2523317cb17SSamuel Holland 								 &ccu_div_ops, \
2533317cb17SSamuel Holland 								 _flags), \
2543317cb17SSamuel Holland 		},							\
2553317cb17SSamuel Holland 	}
2563317cb17SSamuel Holland 
2573317cb17SSamuel Holland #define SUNXI_CCU_M_HWS_WITH_GATE(_struct, _name, _parent, _reg,	\
2583317cb17SSamuel Holland 				  _mshift, _mwidth, _gate,		\
2593317cb17SSamuel Holland 				  _flags)				\
2603317cb17SSamuel Holland 	struct ccu_div _struct = {					\
2613317cb17SSamuel Holland 		.enable	= _gate,					\
2623317cb17SSamuel Holland 		.div	= _SUNXI_CCU_DIV(_mshift, _mwidth),		\
2633317cb17SSamuel Holland 		.common	= {						\
2643317cb17SSamuel Holland 			.reg		= _reg,				\
2653317cb17SSamuel Holland 			.hw.init	= CLK_HW_INIT_HWS(_name,	\
2663317cb17SSamuel Holland 							  _parent,	\
2673317cb17SSamuel Holland 							  &ccu_div_ops,	\
2683317cb17SSamuel Holland 							  _flags),	\
2693317cb17SSamuel Holland 		},							\
2703317cb17SSamuel Holland 	}
2713317cb17SSamuel Holland 
2723317cb17SSamuel Holland #define SUNXI_CCU_M_HWS(_struct, _name, _parent, _reg, _mshift,		\
2733317cb17SSamuel Holland 			_mwidth, _flags)				\
2743317cb17SSamuel Holland 	SUNXI_CCU_M_HWS_WITH_GATE(_struct, _name, _parent, _reg,	\
2753317cb17SSamuel Holland 				  _mshift, _mwidth, 0, _flags)
2763317cb17SSamuel Holland 
hw_to_ccu_div(struct clk_hw * hw)277e9b93213SMaxime Ripard static inline struct ccu_div *hw_to_ccu_div(struct clk_hw *hw)
278e9b93213SMaxime Ripard {
279e9b93213SMaxime Ripard 	struct ccu_common *common = hw_to_ccu_common(hw);
280e9b93213SMaxime Ripard 
281e9b93213SMaxime Ripard 	return container_of(common, struct ccu_div, common);
282e9b93213SMaxime Ripard }
283e9b93213SMaxime Ripard 
284e9b93213SMaxime Ripard extern const struct clk_ops ccu_div_ops;
285e9b93213SMaxime Ripard 
286e9b93213SMaxime Ripard #endif /* _CCU_DIV_H_ */
287