xref: /openbmc/linux/drivers/clk/sunxi-ng/ccu_mux.h (revision 03ab8e6297acd1bc0eedaa050e2a1635c576fd11)
1b2441318SGreg Kroah-Hartman /* SPDX-License-Identifier: GPL-2.0 */
22a65ed42SMaxime Ripard #ifndef _CCU_MUX_H_
32a65ed42SMaxime Ripard #define _CCU_MUX_H_
42a65ed42SMaxime Ripard 
52a65ed42SMaxime Ripard #include <linux/clk-provider.h>
62a65ed42SMaxime Ripard 
72a65ed42SMaxime Ripard #include "ccu_common.h"
82a65ed42SMaxime Ripard 
9ff5294dbSChen-Yu Tsai struct ccu_mux_fixed_prediv {
10ff5294dbSChen-Yu Tsai 	u8	index;
11ff5294dbSChen-Yu Tsai 	u16	div;
12ff5294dbSChen-Yu Tsai };
13ff5294dbSChen-Yu Tsai 
1413e0dde8SChen-Yu Tsai struct ccu_mux_var_prediv {
1513e0dde8SChen-Yu Tsai 	u8	index;
1613e0dde8SChen-Yu Tsai 	u8	shift;
1713e0dde8SChen-Yu Tsai 	u8	width;
1813e0dde8SChen-Yu Tsai };
1913e0dde8SChen-Yu Tsai 
202a65ed42SMaxime Ripard struct ccu_mux_internal {
212a65ed42SMaxime Ripard 	u8		shift;
222a65ed42SMaxime Ripard 	u8		width;
232b9c875cSChen-Yu Tsai 	const u8	*table;
242a65ed42SMaxime Ripard 
25ff5294dbSChen-Yu Tsai 	const struct ccu_mux_fixed_prediv	*fixed_predivs;
26ff5294dbSChen-Yu Tsai 	u8		n_predivs;
272a65ed42SMaxime Ripard 
2813e0dde8SChen-Yu Tsai 	const struct ccu_mux_var_prediv		*var_predivs;
2913e0dde8SChen-Yu Tsai 	u8		n_var_predivs;
302a65ed42SMaxime Ripard };
312a65ed42SMaxime Ripard 
322b9c875cSChen-Yu Tsai #define _SUNXI_CCU_MUX_TABLE(_shift, _width, _table)	\
332a65ed42SMaxime Ripard 	{						\
342a65ed42SMaxime Ripard 		.shift	= _shift,			\
352a65ed42SMaxime Ripard 		.width	= _width,			\
362b9c875cSChen-Yu Tsai 		.table	= _table,			\
372a65ed42SMaxime Ripard 	}
382a65ed42SMaxime Ripard 
392b9c875cSChen-Yu Tsai #define _SUNXI_CCU_MUX(_shift, _width) \
402b9c875cSChen-Yu Tsai 	_SUNXI_CCU_MUX_TABLE(_shift, _width, NULL)
412b9c875cSChen-Yu Tsai 
422a65ed42SMaxime Ripard struct ccu_mux {
432a65ed42SMaxime Ripard 	u32			enable;
442a65ed42SMaxime Ripard 
452a65ed42SMaxime Ripard 	struct ccu_mux_internal	mux;
462a65ed42SMaxime Ripard 	struct ccu_common	common;
472a65ed42SMaxime Ripard };
482a65ed42SMaxime Ripard 
4913e91e45SMaxime Ripard #define SUNXI_CCU_MUX_TABLE_WITH_GATE_FEAT(_struct, _name, _parents, _table,	\
5013e91e45SMaxime Ripard 				     _reg, _shift, _width, _gate,		\
5113e91e45SMaxime Ripard 				     _flags, _features)				\
522a65ed42SMaxime Ripard 	struct ccu_mux _struct = {						\
5313e91e45SMaxime Ripard 		.enable	= _gate,						\
5413e91e45SMaxime Ripard 		.mux	= _SUNXI_CCU_MUX_TABLE(_shift, _width, _table),		\
552a65ed42SMaxime Ripard 		.common	= {							\
562a65ed42SMaxime Ripard 			.reg		= _reg,					\
572a65ed42SMaxime Ripard 			.hw.init	= CLK_HW_INIT_PARENTS(_name,		\
582a65ed42SMaxime Ripard 							      _parents,		\
592a65ed42SMaxime Ripard 							      &ccu_mux_ops,	\
602a65ed42SMaxime Ripard 							      _flags),		\
612a65ed42SMaxime Ripard 			.features	= _features,				\
622a65ed42SMaxime Ripard 		}								\
632a65ed42SMaxime Ripard 	}
642a65ed42SMaxime Ripard 
652a65ed42SMaxime Ripard #define SUNXI_CCU_MUX_TABLE_WITH_GATE_CLOSEST(_struct, _name, _parents,	\
6613e91e45SMaxime Ripard 					      _table, _reg, _shift,	\
6713e91e45SMaxime Ripard 					      _width, _gate, _flags)	\
6813e91e45SMaxime Ripard 	SUNXI_CCU_MUX_TABLE_WITH_GATE_FEAT(_struct, _name, _parents,	\
6913e91e45SMaxime Ripard 					   _table, _reg, _shift,	\
7013e91e45SMaxime Ripard 					   _width, _gate, _flags,	\
7113e91e45SMaxime Ripard 					   CCU_FEATURE_CLOSEST_RATE)
7213e91e45SMaxime Ripard 
7313e91e45SMaxime Ripard #define SUNXI_CCU_MUX_TABLE_WITH_GATE(_struct, _name, _parents, _table,	\
742a65ed42SMaxime Ripard 				     _reg, _shift, _width, _gate,	\
75*8107c859SSamuel Holland 				     _flags)				\
76*8107c859SSamuel Holland 	SUNXI_CCU_MUX_TABLE_WITH_GATE_FEAT(_struct, _name, _parents,	\
77*8107c859SSamuel Holland 					   _table, _reg, _shift,	\
78*8107c859SSamuel Holland 					   _width, _gate, _flags, 0)
79*8107c859SSamuel Holland 
80*8107c859SSamuel Holland #define SUNXI_CCU_MUX_WITH_GATE(_struct, _name, _parents, _reg,		\
81*8107c859SSamuel Holland 				_shift, _width, _gate, _flags)		\
82*8107c859SSamuel Holland 	SUNXI_CCU_MUX_TABLE_WITH_GATE(_struct, _name, _parents, NULL,	\
83*8107c859SSamuel Holland 				      _reg, _shift, _width, _gate,	\
84*8107c859SSamuel Holland 				      _flags)
85*8107c859SSamuel Holland 
86*8107c859SSamuel Holland #define SUNXI_CCU_MUX(_struct, _name, _parents, _reg, _shift, _width,	\
87*8107c859SSamuel Holland 		      _flags)						\
88*8107c859SSamuel Holland 	SUNXI_CCU_MUX_TABLE_WITH_GATE(_struct, _name, _parents, NULL,	\
89*8107c859SSamuel Holland 				      _reg, _shift, _width, 0, _flags)
90*8107c859SSamuel Holland 
91*8107c859SSamuel Holland #define SUNXI_CCU_MUX_DATA_WITH_GATE(_struct, _name, _parents, _reg,	\
92*8107c859SSamuel Holland 				     _shift, _width, _gate, _flags)	\
93*8107c859SSamuel Holland 	struct ccu_mux _struct = {					\
94*8107c859SSamuel Holland 		.enable	= _gate,					\
95*8107c859SSamuel Holland 		.mux	= _SUNXI_CCU_MUX(_shift, _width),		\
96*8107c859SSamuel Holland 		.common	= {						\
97*8107c859SSamuel Holland 			.reg		= _reg,				\
98*8107c859SSamuel Holland 			.hw.init	= CLK_HW_INIT_PARENTS_DATA(_name, \
99*8107c859SSamuel Holland 								   _parents, \
100*8107c859SSamuel Holland 								   &ccu_mux_ops, \
101*8107c859SSamuel Holland 								   _flags), \
102*8107c859SSamuel Holland 		}							\
103*8107c859SSamuel Holland 	}
104*8107c859SSamuel Holland 
105*8107c859SSamuel Holland #define SUNXI_CCU_MUX_DATA(_struct, _name, _parents, _reg,		\
106*8107c859SSamuel Holland 		      _shift, _width, _flags)				\
107*8107c859SSamuel Holland 	SUNXI_CCU_MUX_DATA_WITH_GATE(_struct, _name, _parents, _reg,	\
1082a65ed42SMaxime Ripard 				     _shift, _width, 0, _flags)
1092a65ed42SMaxime Ripard 
1102a65ed42SMaxime Ripard #define SUNXI_CCU_MUX_HW_WITH_GATE(_struct, _name, _parents, _reg,	\
1112a65ed42SMaxime Ripard 				   _shift, _width, _gate, _flags)	\
1122a65ed42SMaxime Ripard 	struct ccu_mux _struct = {					\
1132a65ed42SMaxime Ripard 		.enable	= _gate,					\
1142a65ed42SMaxime Ripard 		.mux	= _SUNXI_CCU_MUX(_shift, _width),		\
1152a65ed42SMaxime Ripard 		.common	= {						\
1162a65ed42SMaxime Ripard 			.reg		= _reg,				\
117d754b159SMaxime Ripard 			.hw.init	= CLK_HW_INIT_PARENTS_HW(_name, \
1182a65ed42SMaxime Ripard 								 _parents, \
1192a65ed42SMaxime Ripard 								 &ccu_mux_ops, \
120d754b159SMaxime Ripard 								 _flags), \
1212a65ed42SMaxime Ripard 		}							\
1222a65ed42SMaxime Ripard 	}
1232a65ed42SMaxime Ripard 
hw_to_ccu_mux(struct clk_hw * hw)1242a65ed42SMaxime Ripard static inline struct ccu_mux *hw_to_ccu_mux(struct clk_hw *hw)
12510a8d9b9SMaxime Ripard {
12610a8d9b9SMaxime Ripard 	struct ccu_common *common = hw_to_ccu_common(hw);
1272a65ed42SMaxime Ripard 
1282a65ed42SMaxime Ripard 	return container_of(common, struct ccu_mux, common);
1292a65ed42SMaxime Ripard }
1302a65ed42SMaxime Ripard 
1312a65ed42SMaxime Ripard extern const struct clk_ops ccu_mux_ops;
1322a65ed42SMaxime Ripard 
1332a65ed42SMaxime Ripard unsigned long ccu_mux_helper_apply_prediv(struct ccu_common *common,
1342a65ed42SMaxime Ripard 					  struct ccu_mux_internal *cm,
1352a65ed42SMaxime Ripard 					  int parent_index,
1368adfb086SChen-Yu Tsai 					  unsigned long parent_rate);
1378adfb086SChen-Yu Tsai int ccu_mux_helper_determine_rate(struct ccu_common *common,
1388adfb086SChen-Yu Tsai 				  struct ccu_mux_internal *cm,
1398adfb086SChen-Yu Tsai 				  struct clk_rate_request *req,
1408adfb086SChen-Yu Tsai 				  unsigned long (*round)(struct ccu_mux_internal *,
1418adfb086SChen-Yu Tsai 							 struct clk_hw *,
1428adfb086SChen-Yu Tsai 							 unsigned long *,
1438adfb086SChen-Yu Tsai 							 unsigned long,
1448adfb086SChen-Yu Tsai 							 void *),
1458adfb086SChen-Yu Tsai 				  void *data);
1468adfb086SChen-Yu Tsai u8 ccu_mux_helper_get_parent(struct ccu_common *common,
1478adfb086SChen-Yu Tsai 			     struct ccu_mux_internal *cm);
1488adfb086SChen-Yu Tsai int ccu_mux_helper_set_parent(struct ccu_common *common,
1498adfb086SChen-Yu Tsai 			      struct ccu_mux_internal *cm,
1502a65ed42SMaxime Ripard 			      u8 index);
151 
152 struct ccu_mux_nb {
153 	struct notifier_block	clk_nb;
154 	struct ccu_common	*common;
155 	struct ccu_mux_internal	*cm;
156 
157 	u32	delay_us;	/* How many us to wait after reparenting */
158 	u8	bypass_index;	/* Which parent to temporarily use */
159 	u8	original_index;	/* This is set by the notifier callback */
160 };
161 
162 #define to_ccu_mux_nb(_nb) container_of(_nb, struct ccu_mux_nb, clk_nb)
163 
164 int ccu_mux_notifier_register(struct clk *clk, struct ccu_mux_nb *mux_nb);
165 
166 #endif /* _CCU_MUX_H_ */
167