Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
1/* SPDX-License-Identifier: GPL-2.0 */
2/*
3 * Copyright (c) 2018 MediaTek Inc.
4 * Author: Owen Chen <owen.chen@mediatek.com>
5 */
6
7#ifndef __DRV_CLK_MTK_MUX_H
8#define __DRV_CLK_MTK_MUX_H
9
10#include <linux/notifier.h>
11#include <linux/spinlock.h>
12#include <linux/types.h>
13
14struct clk;
15struct clk_hw_onecell_data;
16struct clk_ops;
17struct device;
18struct device_node;
19
20struct mtk_mux {
21 int id;
22 const char *name;
23 const char * const *parent_names;
24 const u8 *parent_index;
25 unsigned int flags;
26
27 u32 mux_ofs;
28 u32 set_ofs;
29 u32 clr_ofs;
30 u32 upd_ofs;
31
32 u32 hwv_set_ofs;
33 u32 hwv_clr_ofs;
34 u32 hwv_sta_ofs;
35 u32 fenc_sta_mon_ofs;
36
37 u8 mux_shift;
38 u8 mux_width;
39 u8 gate_shift;
40 s8 upd_shift;
41 u8 fenc_shift;
42
43 const struct clk_ops *ops;
44 signed char num_parents;
45};
46
47#define __GATE_CLR_SET_UPD_FLAGS(_id, _name, _parents, _paridx, \
48 _num_parents, _mux_ofs, _mux_set_ofs, \
49 _mux_clr_ofs, _shift, _width, _gate, _upd_ofs, \
50 _upd, _flags, _ops) { \
51 .id = _id, \
52 .name = _name, \
53 .mux_ofs = _mux_ofs, \
54 .set_ofs = _mux_set_ofs, \
55 .clr_ofs = _mux_clr_ofs, \
56 .upd_ofs = _upd_ofs, \
57 .mux_shift = _shift, \
58 .mux_width = _width, \
59 .gate_shift = _gate, \
60 .upd_shift = _upd, \
61 .parent_names = _parents, \
62 .parent_index = _paridx, \
63 .num_parents = _num_parents, \
64 .flags = _flags, \
65 .ops = &_ops, \
66 }
67
68#define GATE_CLR_SET_UPD_FLAGS(_id, _name, _parents, _mux_ofs, \
69 _mux_set_ofs, _mux_clr_ofs, _shift, _width, \
70 _gate, _upd_ofs, _upd, _flags, _ops) \
71 __GATE_CLR_SET_UPD_FLAGS(_id, _name, _parents, \
72 NULL, ARRAY_SIZE(_parents), _mux_ofs, \
73 _mux_set_ofs, _mux_clr_ofs, _shift, _width, \
74 _gate, _upd_ofs, _upd, _flags, _ops) \
75
76#define GATE_CLR_SET_UPD_FLAGS_INDEXED(_id, _name, _parents, _paridx, \
77 _mux_ofs, _mux_set_ofs, _mux_clr_ofs, _shift, \
78 _width, _gate, _upd_ofs, _upd, _flags, _ops) \
79 __GATE_CLR_SET_UPD_FLAGS(_id, _name, _parents, \
80 _paridx, ARRAY_SIZE(_paridx), _mux_ofs, \
81 _mux_set_ofs, _mux_clr_ofs, _shift, _width, \
82 _gate, _upd_ofs, _upd, _flags, _ops) \
83
84extern const struct clk_ops mtk_mux_clr_set_upd_ops;
85extern const struct clk_ops mtk_mux_gate_clr_set_upd_ops;
86extern const struct clk_ops mtk_mux_gate_fenc_clr_set_upd_ops;
87extern const struct clk_ops mtk_mux_gate_hwv_fenc_clr_set_upd_ops;
88
89#define MUX_GATE_CLR_SET_UPD_FLAGS(_id, _name, _parents, _mux_ofs, \
90 _mux_set_ofs, _mux_clr_ofs, _shift, _width, \
91 _gate, _upd_ofs, _upd, _flags) \
92 GATE_CLR_SET_UPD_FLAGS(_id, _name, _parents, _mux_ofs, \
93 _mux_set_ofs, _mux_clr_ofs, _shift, _width, \
94 _gate, _upd_ofs, _upd, _flags, \
95 mtk_mux_gate_clr_set_upd_ops)
96
97#define MUX_GATE_CLR_SET_UPD_FLAGS_INDEXED(_id, _name, _parents, \
98 _paridx, _mux_ofs, _mux_set_ofs, _mux_clr_ofs, \
99 _shift, _width, _gate, _upd_ofs, _upd, _flags) \
100 GATE_CLR_SET_UPD_FLAGS_INDEXED(_id, _name, _parents, \
101 _paridx, _mux_ofs, _mux_set_ofs, _mux_clr_ofs, \
102 _shift, _width, _gate, _upd_ofs, _upd, _flags, \
103 mtk_mux_gate_clr_set_upd_ops)
104
105#define MUX_GATE_CLR_SET_UPD(_id, _name, _parents, _mux_ofs, \
106 _mux_set_ofs, _mux_clr_ofs, _shift, _width, \
107 _gate, _upd_ofs, _upd) \
108 MUX_GATE_CLR_SET_UPD_FLAGS(_id, _name, _parents, \
109 _mux_ofs, _mux_set_ofs, _mux_clr_ofs, _shift, \
110 _width, _gate, _upd_ofs, _upd, \
111 CLK_SET_RATE_PARENT)
112
113#define MUX_GATE_CLR_SET_UPD_INDEXED(_id, _name, _parents, _paridx, \
114 _mux_ofs, _mux_set_ofs, _mux_clr_ofs, _shift, \
115 _width, _gate, _upd_ofs, _upd) \
116 MUX_GATE_CLR_SET_UPD_FLAGS_INDEXED(_id, _name, \
117 _parents, _paridx, _mux_ofs, _mux_set_ofs, \
118 _mux_clr_ofs, _shift, _width, _gate, _upd_ofs, \
119 _upd, CLK_SET_RATE_PARENT)
120
121#define MUX_CLR_SET_UPD(_id, _name, _parents, _mux_ofs, \
122 _mux_set_ofs, _mux_clr_ofs, _shift, _width, \
123 _upd_ofs, _upd) \
124 GATE_CLR_SET_UPD_FLAGS(_id, _name, _parents, _mux_ofs, \
125 _mux_set_ofs, _mux_clr_ofs, _shift, _width, \
126 0, _upd_ofs, _upd, CLK_SET_RATE_PARENT, \
127 mtk_mux_clr_set_upd_ops)
128
129#define MUX_GATE_HWV_FENC_CLR_SET_UPD_FLAGS(_id, _name, _parents, \
130 _mux_ofs, _mux_set_ofs, _mux_clr_ofs, \
131 _hwv_sta_ofs, _hwv_set_ofs, _hwv_clr_ofs, \
132 _shift, _width, _gate, _upd_ofs, _upd, \
133 _fenc_sta_mon_ofs, _fenc, _flags) { \
134 .id = _id, \
135 .name = _name, \
136 .mux_ofs = _mux_ofs, \
137 .set_ofs = _mux_set_ofs, \
138 .clr_ofs = _mux_clr_ofs, \
139 .hwv_sta_ofs = _hwv_sta_ofs, \
140 .hwv_set_ofs = _hwv_set_ofs, \
141 .hwv_clr_ofs = _hwv_clr_ofs, \
142 .upd_ofs = _upd_ofs, \
143 .fenc_sta_mon_ofs = _fenc_sta_mon_ofs, \
144 .mux_shift = _shift, \
145 .mux_width = _width, \
146 .gate_shift = _gate, \
147 .upd_shift = _upd, \
148 .fenc_shift = _fenc, \
149 .parent_names = _parents, \
150 .num_parents = ARRAY_SIZE(_parents), \
151 .flags = _flags, \
152 .ops = &mtk_mux_gate_hwv_fenc_clr_set_upd_ops, \
153 }
154
155#define MUX_GATE_HWV_FENC_CLR_SET_UPD(_id, _name, _parents, \
156 _mux_ofs, _mux_set_ofs, _mux_clr_ofs, \
157 _hwv_sta_ofs, _hwv_set_ofs, _hwv_clr_ofs, \
158 _shift, _width, _gate, _upd_ofs, _upd, \
159 _fenc_sta_mon_ofs, _fenc) \
160 MUX_GATE_HWV_FENC_CLR_SET_UPD_FLAGS(_id, _name, _parents, \
161 _mux_ofs, _mux_set_ofs, _mux_clr_ofs, \
162 _hwv_sta_ofs, _hwv_set_ofs, _hwv_clr_ofs, \
163 _shift, _width, _gate, _upd_ofs, _upd, \
164 _fenc_sta_mon_ofs, _fenc, 0)
165
166#define MUX_GATE_FENC_CLR_SET_UPD_FLAGS(_id, _name, _parents, _paridx, \
167 _num_parents, _mux_ofs, _mux_set_ofs, _mux_clr_ofs, \
168 _shift, _width, _gate, _upd_ofs, _upd, \
169 _fenc_sta_mon_ofs, _fenc, _flags) { \
170 .id = _id, \
171 .name = _name, \
172 .mux_ofs = _mux_ofs, \
173 .set_ofs = _mux_set_ofs, \
174 .clr_ofs = _mux_clr_ofs, \
175 .upd_ofs = _upd_ofs, \
176 .fenc_sta_mon_ofs = _fenc_sta_mon_ofs, \
177 .mux_shift = _shift, \
178 .mux_width = _width, \
179 .gate_shift = _gate, \
180 .upd_shift = _upd, \
181 .fenc_shift = _fenc, \
182 .parent_names = _parents, \
183 .parent_index = _paridx, \
184 .num_parents = _num_parents, \
185 .flags = _flags, \
186 .ops = &mtk_mux_gate_fenc_clr_set_upd_ops, \
187 }
188
189#define MUX_GATE_FENC_CLR_SET_UPD(_id, _name, _parents, \
190 _mux_ofs, _mux_set_ofs, _mux_clr_ofs, \
191 _shift, _width, _gate, _upd_ofs, _upd, \
192 _fenc_sta_mon_ofs, _fenc) \
193 MUX_GATE_FENC_CLR_SET_UPD_FLAGS(_id, _name, _parents, \
194 NULL, ARRAY_SIZE(_parents), _mux_ofs, \
195 _mux_set_ofs, _mux_clr_ofs, _shift, \
196 _width, _gate, _upd_ofs, _upd, \
197 _fenc_sta_mon_ofs, _fenc, 0)
198
199#define MUX_GATE_FENC_CLR_SET_UPD_INDEXED(_id, _name, _parents, _paridx, \
200 _mux_ofs, _mux_set_ofs, _mux_clr_ofs, \
201 _shift, _width, _gate, _upd_ofs, _upd, \
202 _fenc_sta_mon_ofs, _fenc) \
203 MUX_GATE_FENC_CLR_SET_UPD_FLAGS(_id, _name, _parents, _paridx, \
204 ARRAY_SIZE(_paridx), _mux_ofs, _mux_set_ofs, \
205 _mux_clr_ofs, _shift, _width, _gate, _upd_ofs, _upd, \
206 _fenc_sta_mon_ofs, _fenc, 0)
207
208int mtk_clk_register_muxes(struct device *dev,
209 const struct mtk_mux *muxes,
210 int num, struct device_node *node,
211 spinlock_t *lock,
212 struct clk_hw_onecell_data *clk_data);
213
214void mtk_clk_unregister_muxes(const struct mtk_mux *muxes, int num,
215 struct clk_hw_onecell_data *clk_data);
216
217struct mtk_mux_nb {
218 struct notifier_block nb;
219 const struct clk_ops *ops;
220
221 u8 bypass_index; /* Which parent to temporarily use */
222 u8 original_index; /* Set by notifier callback */
223};
224
225#define to_mtk_mux_nb(_nb) container_of(_nb, struct mtk_mux_nb, nb)
226
227int devm_mtk_clk_mux_notifier_register(struct device *dev, struct clk *clk,
228 struct mtk_mux_nb *mux_nb);
229
230#endif /* __DRV_CLK_MTK_MUX_H */