Commit | Line | Data |
---|---|---|
b2441318 | 1 | /* SPDX-License-Identifier: GPL-2.0 */ |
2a65ed42 MR |
2 | #ifndef _CCU_MUX_H_ |
3 | #define _CCU_MUX_H_ | |
4 | ||
5 | #include <linux/clk-provider.h> | |
6 | ||
7 | #include "ccu_common.h" | |
8 | ||
ff5294db CYT |
9 | struct ccu_mux_fixed_prediv { |
10 | u8 index; | |
11 | u16 div; | |
12 | }; | |
13 | ||
13e0dde8 CYT |
14 | struct ccu_mux_var_prediv { |
15 | u8 index; | |
16 | u8 shift; | |
17 | u8 width; | |
18 | }; | |
19 | ||
2a65ed42 | 20 | struct ccu_mux_internal { |
2b9c875c CYT |
21 | u8 shift; |
22 | u8 width; | |
23 | const u8 *table; | |
2a65ed42 | 24 | |
ff5294db CYT |
25 | const struct ccu_mux_fixed_prediv *fixed_predivs; |
26 | u8 n_predivs; | |
2a65ed42 | 27 | |
13e0dde8 CYT |
28 | const struct ccu_mux_var_prediv *var_predivs; |
29 | u8 n_var_predivs; | |
2a65ed42 MR |
30 | }; |
31 | ||
2b9c875c CYT |
32 | #define _SUNXI_CCU_MUX_TABLE(_shift, _width, _table) \ |
33 | { \ | |
34 | .shift = _shift, \ | |
35 | .width = _width, \ | |
36 | .table = _table, \ | |
2a65ed42 MR |
37 | } |
38 | ||
2b9c875c CYT |
39 | #define _SUNXI_CCU_MUX(_shift, _width) \ |
40 | _SUNXI_CCU_MUX_TABLE(_shift, _width, NULL) | |
41 | ||
2a65ed42 | 42 | struct ccu_mux { |
2a65ed42 MR |
43 | u32 enable; |
44 | ||
45 | struct ccu_mux_internal mux; | |
46 | struct ccu_common common; | |
47 | }; | |
48 | ||
13e91e45 MR |
49 | #define SUNXI_CCU_MUX_TABLE_WITH_GATE(_struct, _name, _parents, _table, \ |
50 | _reg, _shift, _width, _gate, \ | |
51 | _flags) \ | |
2a65ed42 | 52 | struct ccu_mux _struct = { \ |
13e91e45 MR |
53 | .enable = _gate, \ |
54 | .mux = _SUNXI_CCU_MUX_TABLE(_shift, _width, _table), \ | |
2a65ed42 MR |
55 | .common = { \ |
56 | .reg = _reg, \ | |
57 | .hw.init = CLK_HW_INIT_PARENTS(_name, \ | |
58 | _parents, \ | |
59 | &ccu_mux_ops, \ | |
60 | _flags), \ | |
61 | } \ | |
62 | } | |
63 | ||
64 | #define SUNXI_CCU_MUX_WITH_GATE(_struct, _name, _parents, _reg, \ | |
65 | _shift, _width, _gate, _flags) \ | |
13e91e45 MR |
66 | SUNXI_CCU_MUX_TABLE_WITH_GATE(_struct, _name, _parents, NULL, \ |
67 | _reg, _shift, _width, _gate, \ | |
68 | _flags) | |
69 | ||
70 | #define SUNXI_CCU_MUX(_struct, _name, _parents, _reg, _shift, _width, \ | |
71 | _flags) \ | |
72 | SUNXI_CCU_MUX_TABLE_WITH_GATE(_struct, _name, _parents, NULL, \ | |
73 | _reg, _shift, _width, 0, _flags) | |
2a65ed42 | 74 | |
8107c859 SH |
75 | #define SUNXI_CCU_MUX_DATA_WITH_GATE(_struct, _name, _parents, _reg, \ |
76 | _shift, _width, _gate, _flags) \ | |
77 | struct ccu_mux _struct = { \ | |
78 | .enable = _gate, \ | |
79 | .mux = _SUNXI_CCU_MUX(_shift, _width), \ | |
80 | .common = { \ | |
81 | .reg = _reg, \ | |
82 | .hw.init = CLK_HW_INIT_PARENTS_DATA(_name, \ | |
83 | _parents, \ | |
84 | &ccu_mux_ops, \ | |
85 | _flags), \ | |
86 | } \ | |
87 | } | |
88 | ||
89 | #define SUNXI_CCU_MUX_DATA(_struct, _name, _parents, _reg, \ | |
90 | _shift, _width, _flags) \ | |
91 | SUNXI_CCU_MUX_DATA_WITH_GATE(_struct, _name, _parents, _reg, \ | |
92 | _shift, _width, 0, _flags) | |
93 | ||
94 | #define SUNXI_CCU_MUX_HW_WITH_GATE(_struct, _name, _parents, _reg, \ | |
95 | _shift, _width, _gate, _flags) \ | |
96 | struct ccu_mux _struct = { \ | |
97 | .enable = _gate, \ | |
98 | .mux = _SUNXI_CCU_MUX(_shift, _width), \ | |
99 | .common = { \ | |
100 | .reg = _reg, \ | |
101 | .hw.init = CLK_HW_INIT_PARENTS_HW(_name, \ | |
102 | _parents, \ | |
103 | &ccu_mux_ops, \ | |
104 | _flags), \ | |
105 | } \ | |
106 | } | |
107 | ||
2a65ed42 MR |
108 | static inline struct ccu_mux *hw_to_ccu_mux(struct clk_hw *hw) |
109 | { | |
110 | struct ccu_common *common = hw_to_ccu_common(hw); | |
111 | ||
112 | return container_of(common, struct ccu_mux, common); | |
113 | } | |
114 | ||
115 | extern const struct clk_ops ccu_mux_ops; | |
116 | ||
d754b159 MR |
117 | unsigned long ccu_mux_helper_apply_prediv(struct ccu_common *common, |
118 | struct ccu_mux_internal *cm, | |
119 | int parent_index, | |
120 | unsigned long parent_rate); | |
2a65ed42 MR |
121 | int ccu_mux_helper_determine_rate(struct ccu_common *common, |
122 | struct ccu_mux_internal *cm, | |
123 | struct clk_rate_request *req, | |
124 | unsigned long (*round)(struct ccu_mux_internal *, | |
10a8d9b9 MR |
125 | struct clk_hw *, |
126 | unsigned long *, | |
2a65ed42 MR |
127 | unsigned long, |
128 | void *), | |
129 | void *data); | |
130 | u8 ccu_mux_helper_get_parent(struct ccu_common *common, | |
131 | struct ccu_mux_internal *cm); | |
132 | int ccu_mux_helper_set_parent(struct ccu_common *common, | |
133 | struct ccu_mux_internal *cm, | |
134 | u8 index); | |
135 | ||
8adfb086 CYT |
136 | struct ccu_mux_nb { |
137 | struct notifier_block clk_nb; | |
138 | struct ccu_common *common; | |
139 | struct ccu_mux_internal *cm; | |
140 | ||
141 | u32 delay_us; /* How many us to wait after reparenting */ | |
142 | u8 bypass_index; /* Which parent to temporarily use */ | |
143 | u8 original_index; /* This is set by the notifier callback */ | |
144 | }; | |
145 | ||
146 | #define to_ccu_mux_nb(_nb) container_of(_nb, struct ccu_mux_nb, clk_nb) | |
147 | ||
148 | int ccu_mux_notifier_register(struct clk *clk, struct ccu_mux_nb *mux_nb); | |
149 | ||
2a65ed42 | 150 | #endif /* _CCU_MUX_H_ */ |