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