• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 /*
3  * Copyright (c) 2016 Maxime Ripard. All rights reserved.
4  */
5 
6 #ifndef _CCU_MP_H_
7 #define _CCU_MP_H_
8 
9 #include <linux/bitops.h>
10 #include <linux/clk-provider.h>
11 
12 #include "ccu_common.h"
13 #include "ccu_div.h"
14 #include "ccu_mult.h"
15 #include "ccu_mux.h"
16 
17 /*
18  * struct ccu_mp - Definition of an M-P clock
19  *
20  * Clocks based on the formula parent >> P / M
21  */
22 struct ccu_mp {
23 	u32			enable;
24 
25 	struct ccu_div_internal		m;
26 	struct ccu_div_internal		p;
27 	struct ccu_mux_internal	mux;
28 
29 	unsigned int		fixed_post_div;
30 
31 	struct ccu_common	common;
32 };
33 
34 #define SUNXI_CCU_MP_WITH_MUX_GATE_NO_INDEX(_struct, _name, _parents, _reg, \
35 					   _mshift, _mwidth,		\
36 					   _pshift, _pwidth,		\
37 					   _muxshift, _muxwidth,	\
38 					   _gate, _flags)		\
39 	struct ccu_mp _struct = {					\
40 		.enable	= _gate,					\
41 		.m	= _SUNXI_CCU_DIV(_mshift, _mwidth),		\
42 		.p	= _SUNXI_CCU_DIV(_pshift, _pwidth),		\
43 		.mux	= _SUNXI_CCU_MUX(_muxshift, _muxwidth),		\
44 		.common	= {						\
45 			.reg		= _reg,				\
46 			.features	= CCU_FEATURE_MP_NO_INDEX_MODE,	\
47 			.hw.init	= CLK_HW_INIT_PARENTS(_name,	\
48 							      _parents, \
49 							      &ccu_mp_ops, \
50 							      _flags),	\
51 		}							\
52 	}
53 
54 #define SUNXI_CCU_MP_WITH_MUX_GATE_POSTDIV(_struct, _name, _parents, _reg, \
55 					   _mshift, _mwidth,		\
56 					   _pshift, _pwidth,		\
57 					   _muxshift, _muxwidth,	\
58 					   _gate, _postdiv, _flags)	\
59 	struct ccu_mp _struct = {					\
60 		.enable	= _gate,					\
61 		.m	= _SUNXI_CCU_DIV(_mshift, _mwidth),		\
62 		.p	= _SUNXI_CCU_DIV(_pshift, _pwidth),		\
63 		.mux	= _SUNXI_CCU_MUX(_muxshift, _muxwidth),		\
64 		.fixed_post_div	= _postdiv,				\
65 		.common	= {						\
66 			.reg		= _reg,				\
67 			.features	= CCU_FEATURE_FIXED_POSTDIV,	\
68 			.hw.init	= CLK_HW_INIT_PARENTS(_name,	\
69 							      _parents, \
70 							      &ccu_mp_ops, \
71 							      _flags),	\
72 		}							\
73 	}
74 
75 #define SUNXI_CCU_MP_WITH_MUX_GATE(_struct, _name, _parents, _reg,	\
76 				   _mshift, _mwidth,			\
77 				   _pshift, _pwidth,			\
78 				   _muxshift, _muxwidth,		\
79 				   _gate, _flags)			\
80 	struct ccu_mp _struct = {					\
81 		.enable	= _gate,					\
82 		.m	= _SUNXI_CCU_DIV(_mshift, _mwidth),		\
83 		.p	= _SUNXI_CCU_DIV(_pshift, _pwidth),		\
84 		.mux	= _SUNXI_CCU_MUX(_muxshift, _muxwidth),		\
85 		.common	= {						\
86 			.reg		= _reg,				\
87 			.hw.init	= CLK_HW_INIT_PARENTS(_name,	\
88 							      _parents, \
89 							      &ccu_mp_ops, \
90 							      _flags),	\
91 		}							\
92 	}
93 
94 #define SUNXI_CCU_MP_WITH_MUX(_struct, _name, _parents, _reg,		\
95 			      _mshift, _mwidth,				\
96 			      _pshift, _pwidth,				\
97 			      _muxshift, _muxwidth,			\
98 			      _flags)					\
99 	SUNXI_CCU_MP_WITH_MUX_GATE(_struct, _name, _parents, _reg,	\
100 				   _mshift, _mwidth,			\
101 				   _pshift, _pwidth,			\
102 				   _muxshift, _muxwidth,		\
103 				   0, _flags)
104 
hw_to_ccu_mp(struct clk_hw * hw)105 static inline struct ccu_mp *hw_to_ccu_mp(struct clk_hw *hw)
106 {
107 	struct ccu_common *common = hw_to_ccu_common(hw);
108 
109 	return container_of(common, struct ccu_mp, common);
110 }
111 
112 extern const struct clk_ops ccu_mp_ops;
113 
114 /*
115  * Special class of M-P clock that supports MMC timing modes
116  *
117  * Since the MMC clock registers all follow the same layout, we can
118  * simplify the macro for this particular case. In addition, as
119  * switching modes also affects the output clock rate, we need to
120  * have CLK_GET_RATE_NOCACHE for all these types of clocks.
121  */
122 
123 #define SUNXI_CCU_MP_MMC_WITH_MUX_GATE(_struct, _name, _parents, _reg,	\
124 				       _flags)				\
125 	struct ccu_mp _struct = {					\
126 		.enable	= BIT(31),					\
127 		.m	= _SUNXI_CCU_DIV(0, 4),				\
128 		.p	= _SUNXI_CCU_DIV(16, 2),			\
129 		.mux	= _SUNXI_CCU_MUX(24, 2),			\
130 		.common	= {						\
131 			.reg		= _reg,				\
132 			.features	= CCU_FEATURE_MMC_TIMING_SWITCH, \
133 			.hw.init	= CLK_HW_INIT_PARENTS(_name,	\
134 							      _parents, \
135 							      &ccu_mp_mmc_ops, \
136 							      CLK_GET_RATE_NOCACHE | \
137 							      _flags),	\
138 		}							\
139 	}
140 
141 extern const struct clk_ops ccu_mp_mmc_ops;
142 
143 #endif /* _CCU_MP_H_ */
144