1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * Copyright (c) 2016 MediaTek Inc. |
4 | * Author: Kevin Chen <kevin-cw.chen@mediatek.com> |
5 | */ |
6 | |
7 | #include <linux/of.h> |
8 | #include <linux/platform_device.h> |
9 | |
10 | #include "clk-gate.h" |
11 | #include "clk-mtk.h" |
12 | #include "clk-pll.h" |
13 | |
14 | #include <dt-bindings/clock/mt6797-clk.h> |
15 | |
16 | /* |
17 | * For some clocks, we don't care what their actual rates are. And these |
18 | * clocks may change their rate on different products or different scenarios. |
19 | * So we model these clocks' rate as 0, to denote it's not an actual rate. |
20 | */ |
21 | |
22 | static DEFINE_SPINLOCK(mt6797_clk_lock); |
23 | |
24 | static const struct mtk_fixed_factor top_fixed_divs[] = { |
25 | FACTOR(CLK_TOP_SYSPLL_CK, "syspll_ck" , "mainpll" , 1, 1), |
26 | FACTOR(CLK_TOP_SYSPLL_D2, "syspll_d2" , "mainpll" , 1, 2), |
27 | FACTOR(CLK_TOP_SYSPLL1_D2, "syspll1_d2" , "syspll_d2" , 1, 2), |
28 | FACTOR(CLK_TOP_SYSPLL1_D4, "syspll1_d4" , "syspll_d2" , 1, 4), |
29 | FACTOR(CLK_TOP_SYSPLL1_D8, "syspll1_d8" , "syspll_d2" , 1, 8), |
30 | FACTOR(CLK_TOP_SYSPLL1_D16, "syspll1_d16" , "syspll_d2" , 1, 16), |
31 | FACTOR(CLK_TOP_SYSPLL_D3, "syspll_d3" , "mainpll" , 1, 3), |
32 | FACTOR(CLK_TOP_SYSPLL_D3_D3, "syspll_d3_d3" , "syspll_d3" , 1, 3), |
33 | FACTOR(CLK_TOP_SYSPLL2_D2, "syspll2_d2" , "syspll_d3" , 1, 2), |
34 | FACTOR(CLK_TOP_SYSPLL2_D4, "syspll2_d4" , "syspll_d3" , 1, 4), |
35 | FACTOR(CLK_TOP_SYSPLL2_D8, "syspll2_d8" , "syspll_d3" , 1, 8), |
36 | FACTOR(CLK_TOP_SYSPLL_D5, "syspll_d5" , "mainpll" , 1, 5), |
37 | FACTOR(CLK_TOP_SYSPLL3_D2, "syspll3_d2" , "syspll_d5" , 1, 2), |
38 | FACTOR(CLK_TOP_SYSPLL3_D4, "syspll3_d4" , "syspll_d5" , 1, 4), |
39 | FACTOR(CLK_TOP_SYSPLL_D7, "syspll_d7" , "mainpll" , 1, 7), |
40 | FACTOR(CLK_TOP_SYSPLL4_D2, "syspll4_d2" , "syspll_d7" , 1, 2), |
41 | FACTOR(CLK_TOP_SYSPLL4_D4, "syspll4_d4" , "syspll_d7" , 1, 4), |
42 | FACTOR(CLK_TOP_UNIVPLL_CK, "univpll_ck" , "univpll" , 1, 1), |
43 | FACTOR(CLK_TOP_UNIVPLL_D7, "univpll_d7" , "univpll" , 1, 7), |
44 | FACTOR(CLK_TOP_UNIVPLL_D26, "univpll_d26" , "univpll" , 1, 26), |
45 | FACTOR(CLK_TOP_SSUSB_PHY_48M_CK, "ssusb_phy_48m_ck" , "univpll" , 1, 1), |
46 | FACTOR(CLK_TOP_USB_PHY48M_CK, "usb_phy48m_ck" , "univpll" , 1, 1), |
47 | FACTOR(CLK_TOP_UNIVPLL_D2, "univpll_d2" , "univpll" , 1, 2), |
48 | FACTOR(CLK_TOP_UNIVPLL1_D2, "univpll1_d2" , "univpll_d2" , 1, 2), |
49 | FACTOR(CLK_TOP_UNIVPLL1_D4, "univpll1_d4" , "univpll_d2" , 1, 4), |
50 | FACTOR(CLK_TOP_UNIVPLL1_D8, "univpll1_d8" , "univpll_d2" , 1, 8), |
51 | FACTOR(CLK_TOP_UNIVPLL_D3, "univpll_d3" , "univpll" , 1, 3), |
52 | FACTOR(CLK_TOP_UNIVPLL2_D2, "univpll2_d2" , "univpll" , 1, 2), |
53 | FACTOR(CLK_TOP_UNIVPLL2_D4, "univpll2_d4" , "univpll" , 1, 4), |
54 | FACTOR(CLK_TOP_UNIVPLL2_D8, "univpll2_d8" , "univpll" , 1, 8), |
55 | FACTOR(CLK_TOP_UNIVPLL_D5, "univpll_d5" , "univpll" , 1, 5), |
56 | FACTOR(CLK_TOP_UNIVPLL3_D2, "univpll3_d2" , "univpll_d5" , 1, 2), |
57 | FACTOR(CLK_TOP_UNIVPLL3_D4, "univpll3_d4" , "univpll_d5" , 1, 4), |
58 | FACTOR(CLK_TOP_UNIVPLL3_D8, "univpll3_d8" , "univpll_d5" , 1, 8), |
59 | FACTOR(CLK_TOP_ULPOSC_CK_ORG, "ulposc_ck_org" , "ulposc" , 1, 1), |
60 | FACTOR(CLK_TOP_ULPOSC_CK, "ulposc_ck" , "ulposc_ck_org" , 1, 3), |
61 | FACTOR(CLK_TOP_ULPOSC_D2, "ulposc_d2" , "ulposc_ck" , 1, 2), |
62 | FACTOR(CLK_TOP_ULPOSC_D3, "ulposc_d3" , "ulposc_ck" , 1, 4), |
63 | FACTOR(CLK_TOP_ULPOSC_D4, "ulposc_d4" , "ulposc_ck" , 1, 8), |
64 | FACTOR(CLK_TOP_ULPOSC_D8, "ulposc_d8" , "ulposc_ck" , 1, 10), |
65 | FACTOR(CLK_TOP_ULPOSC_D10, "ulposc_d10" , "ulposc_ck_org" , 1, 1), |
66 | FACTOR(CLK_TOP_APLL1_CK, "apll1_ck" , "apll1" , 1, 1), |
67 | FACTOR(CLK_TOP_APLL2_CK, "apll2_ck" , "apll2" , 1, 1), |
68 | FACTOR(CLK_TOP_MFGPLL_CK, "mfgpll_ck" , "mfgpll" , 1, 1), |
69 | FACTOR(CLK_TOP_MFGPLL_D2, "mfgpll_d2" , "mfgpll_ck" , 1, 2), |
70 | FACTOR(CLK_TOP_IMGPLL_CK, "imgpll_ck" , "imgpll" , 1, 1), |
71 | FACTOR(CLK_TOP_IMGPLL_D2, "imgpll_d2" , "imgpll_ck" , 1, 2), |
72 | FACTOR(CLK_TOP_IMGPLL_D4, "imgpll_d4" , "imgpll_ck" , 1, 4), |
73 | FACTOR(CLK_TOP_CODECPLL_CK, "codecpll_ck" , "codecpll" , 1, 1), |
74 | FACTOR(CLK_TOP_CODECPLL_D2, "codecpll_d2" , "codecpll_ck" , 1, 2), |
75 | FACTOR(CLK_TOP_VDECPLL_CK, "vdecpll_ck" , "vdecpll" , 1, 1), |
76 | FACTOR(CLK_TOP_TVDPLL_CK, "tvdpll_ck" , "tvdpll" , 1, 1), |
77 | FACTOR(CLK_TOP_TVDPLL_D2, "tvdpll_d2" , "tvdpll_ck" , 1, 2), |
78 | FACTOR(CLK_TOP_TVDPLL_D4, "tvdpll_d4" , "tvdpll_ck" , 1, 4), |
79 | FACTOR(CLK_TOP_TVDPLL_D8, "tvdpll_d8" , "tvdpll_ck" , 1, 8), |
80 | FACTOR(CLK_TOP_TVDPLL_D16, "tvdpll_d16" , "tvdpll_ck" , 1, 16), |
81 | FACTOR(CLK_TOP_MSDCPLL_CK, "msdcpll_ck" , "msdcpll" , 1, 1), |
82 | FACTOR(CLK_TOP_MSDCPLL_D2, "msdcpll_d2" , "msdcpll_ck" , 1, 2), |
83 | FACTOR(CLK_TOP_MSDCPLL_D4, "msdcpll_d4" , "msdcpll_ck" , 1, 4), |
84 | FACTOR(CLK_TOP_MSDCPLL_D8, "msdcpll_d8" , "msdcpll_ck" , 1, 8), |
85 | }; |
86 | |
87 | static const char * const axi_parents[] = { |
88 | "clk26m" , |
89 | "syspll_d7" , |
90 | "ulposc_axi_ck_mux" , |
91 | }; |
92 | |
93 | static const char * const ulposc_axi_ck_mux_parents[] = { |
94 | "syspll1_d4" , |
95 | "ulposc_axi_ck_mux_pre" , |
96 | }; |
97 | |
98 | static const char * const ulposc_axi_ck_mux_pre_parents[] = { |
99 | "ulposc_d2" , |
100 | "ulposc_d3" , |
101 | }; |
102 | |
103 | static const char * const ddrphycfg_parents[] = { |
104 | "clk26m" , |
105 | "syspll3_d2" , |
106 | "syspll2_d4" , |
107 | "syspll1_d8" , |
108 | }; |
109 | |
110 | static const char * const mm_parents[] = { |
111 | "clk26m" , |
112 | "imgpll_ck" , |
113 | "univpll1_d2" , |
114 | "syspll1_d2" , |
115 | }; |
116 | |
117 | static const char * const pwm_parents[] = { |
118 | "clk26m" , |
119 | "univpll2_d4" , |
120 | "ulposc_d2" , |
121 | "ulposc_d3" , |
122 | "ulposc_d8" , |
123 | "ulposc_d10" , |
124 | "ulposc_d4" , |
125 | }; |
126 | |
127 | static const char * const vdec_parents[] = { |
128 | "clk26m" , |
129 | "vdecpll_ck" , |
130 | "imgpll_ck" , |
131 | "syspll_d3" , |
132 | "univpll_d5" , |
133 | "clk26m" , |
134 | "clk26m" , |
135 | }; |
136 | |
137 | static const char * const venc_parents[] = { |
138 | "clk26m" , |
139 | "codecpll_ck" , |
140 | "syspll_d3" , |
141 | }; |
142 | |
143 | static const char * const mfg_parents[] = { |
144 | "clk26m" , |
145 | "mfgpll_ck" , |
146 | "syspll_d3" , |
147 | "univpll_d3" , |
148 | }; |
149 | |
150 | static const char * const camtg[] = { |
151 | "clk26m" , |
152 | "univpll_d26" , |
153 | "univpll2_d2" , |
154 | }; |
155 | |
156 | static const char * const uart_parents[] = { |
157 | "clk26m" , |
158 | "univpll2_d8" , |
159 | }; |
160 | |
161 | static const char * const spi_parents[] = { |
162 | "clk26m" , |
163 | "syspll3_d2" , |
164 | "syspll2_d4" , |
165 | "ulposc_spi_ck_mux" , |
166 | }; |
167 | |
168 | static const char * const ulposc_spi_ck_mux_parents[] = { |
169 | "ulposc_d2" , |
170 | "ulposc_d3" , |
171 | }; |
172 | |
173 | static const char * const usb20_parents[] = { |
174 | "clk26m" , |
175 | "univpll1_d8" , |
176 | "syspll4_d2" , |
177 | }; |
178 | |
179 | static const char * const msdc50_0_hclk_parents[] = { |
180 | "clk26m" , |
181 | "syspll1_d2" , |
182 | "syspll2_d2" , |
183 | "syspll4_d2" , |
184 | }; |
185 | |
186 | static const char * const msdc50_0_parents[] = { |
187 | "clk26m" , |
188 | "msdcpll" , |
189 | "syspll_d3" , |
190 | "univpll1_d4" , |
191 | "syspll2_d2" , |
192 | "syspll_d7" , |
193 | "msdcpll_d2" , |
194 | "univpll1_d2" , |
195 | "univpll_d3" , |
196 | }; |
197 | |
198 | static const char * const msdc30_1_parents[] = { |
199 | "clk26m" , |
200 | "univpll2_d2" , |
201 | "msdcpll_d2" , |
202 | "univpll1_d4" , |
203 | "syspll2_d2" , |
204 | "syspll_d7" , |
205 | "univpll_d7" , |
206 | }; |
207 | |
208 | static const char * const msdc30_2_parents[] = { |
209 | "clk26m" , |
210 | "univpll2_d8" , |
211 | "syspll2_d8" , |
212 | "syspll1_d8" , |
213 | "msdcpll_d8" , |
214 | "syspll3_d4" , |
215 | "univpll_d26" , |
216 | }; |
217 | |
218 | static const char * const audio_parents[] = { |
219 | "clk26m" , |
220 | "syspll3_d4" , |
221 | "syspll4_d4" , |
222 | "syspll1_d16" , |
223 | }; |
224 | |
225 | static const char * const aud_intbus_parents[] = { |
226 | "clk26m" , |
227 | "syspll1_d4" , |
228 | "syspll4_d2" , |
229 | }; |
230 | |
231 | static const char * const pmicspi_parents[] = { |
232 | "clk26m" , |
233 | "univpll_d26" , |
234 | "syspll3_d4" , |
235 | "syspll1_d8" , |
236 | "ulposc_d4" , |
237 | "ulposc_d8" , |
238 | "syspll2_d8" , |
239 | }; |
240 | |
241 | static const char * const scp_parents[] = { |
242 | "clk26m" , |
243 | "syspll_d3" , |
244 | "ulposc_ck" , |
245 | "univpll_d5" , |
246 | }; |
247 | |
248 | static const char * const atb_parents[] = { |
249 | "clk26m" , |
250 | "syspll1_d2" , |
251 | "syspll_d5" , |
252 | }; |
253 | |
254 | static const char * const mjc_parents[] = { |
255 | "clk26m" , |
256 | "imgpll_ck" , |
257 | "univpll_d5" , |
258 | "syspll1_d2" , |
259 | }; |
260 | |
261 | static const char * const dpi0_parents[] = { |
262 | "clk26m" , |
263 | "tvdpll_d2" , |
264 | "tvdpll_d4" , |
265 | "tvdpll_d8" , |
266 | "tvdpll_d16" , |
267 | "clk26m" , |
268 | "clk26m" , |
269 | }; |
270 | |
271 | static const char * const aud_1_parents[] = { |
272 | "clk26m" , |
273 | "apll1_ck" , |
274 | }; |
275 | |
276 | static const char * const aud_2_parents[] = { |
277 | "clk26m" , |
278 | "apll2_ck" , |
279 | }; |
280 | |
281 | static const char * const ssusb_top_sys_parents[] = { |
282 | "clk26m" , |
283 | "univpll3_d2" , |
284 | }; |
285 | |
286 | static const char * const spm_parents[] = { |
287 | "clk26m" , |
288 | "syspll1_d8" , |
289 | }; |
290 | |
291 | static const char * const bsi_spi_parents[] = { |
292 | "clk26m" , |
293 | "syspll_d3_d3" , |
294 | "syspll1_d4" , |
295 | "syspll_d7" , |
296 | }; |
297 | |
298 | static const char * const audio_h_parents[] = { |
299 | "clk26m" , |
300 | "apll2_ck" , |
301 | "apll1_ck" , |
302 | "univpll_d7" , |
303 | }; |
304 | |
305 | static const char * const mfg_52m_parents[] = { |
306 | "clk26m" , |
307 | "univpll2_d8" , |
308 | "univpll2_d4" , |
309 | "univpll2_d4" , |
310 | }; |
311 | |
312 | static const char * const anc_md32_parents[] = { |
313 | "clk26m" , |
314 | "syspll1_d2" , |
315 | "univpll_d5" , |
316 | }; |
317 | |
318 | /* |
319 | * Clock mux ddrphycfg is needed by the DRAM controller. We mark it as |
320 | * critical as otherwise the system will hang after boot. |
321 | */ |
322 | static const struct mtk_composite top_muxes[] = { |
323 | MUX(CLK_TOP_MUX_ULPOSC_AXI_CK_MUX_PRE, "ulposc_axi_ck_mux_pre" , |
324 | ulposc_axi_ck_mux_pre_parents, 0x0040, 3, 1), |
325 | MUX(CLK_TOP_MUX_ULPOSC_AXI_CK_MUX, "ulposc_axi_ck_mux" , |
326 | ulposc_axi_ck_mux_parents, 0x0040, 2, 1), |
327 | MUX(CLK_TOP_MUX_AXI, "axi_sel" , axi_parents, |
328 | 0x0040, 0, 2), |
329 | MUX_FLAGS(CLK_TOP_MUX_DDRPHYCFG, "ddrphycfg_sel" , ddrphycfg_parents, |
330 | 0x0040, 16, 2, CLK_IS_CRITICAL | CLK_SET_RATE_PARENT), |
331 | MUX(CLK_TOP_MUX_MM, "mm_sel" , mm_parents, |
332 | 0x0040, 24, 2), |
333 | MUX_GATE(CLK_TOP_MUX_PWM, "pwm_sel" , pwm_parents, 0x0050, 0, 3, 7), |
334 | MUX_GATE(CLK_TOP_MUX_VDEC, "vdec_sel" , vdec_parents, 0x0050, 8, 3, 15), |
335 | MUX_GATE(CLK_TOP_MUX_VENC, "venc_sel" , venc_parents, 0x0050, 16, 2, 23), |
336 | MUX_GATE(CLK_TOP_MUX_MFG, "mfg_sel" , mfg_parents, 0x0050, 24, 2, 31), |
337 | MUX_GATE(CLK_TOP_MUX_CAMTG, "camtg_sel" , camtg, 0x0060, 0, 2, 7), |
338 | MUX_GATE(CLK_TOP_MUX_UART, "uart_sel" , uart_parents, 0x0060, 8, 1, 15), |
339 | MUX_GATE(CLK_TOP_MUX_SPI, "spi_sel" , spi_parents, 0x0060, 16, 2, 23), |
340 | MUX(CLK_TOP_MUX_ULPOSC_SPI_CK_MUX, "ulposc_spi_ck_mux" , |
341 | ulposc_spi_ck_mux_parents, 0x0060, 18, 1), |
342 | MUX_GATE(CLK_TOP_MUX_USB20, "usb20_sel" , usb20_parents, |
343 | 0x0060, 24, 2, 31), |
344 | MUX(CLK_TOP_MUX_MSDC50_0_HCLK, "msdc50_0_hclk_sel" , |
345 | msdc50_0_hclk_parents, 0x0070, 8, 2), |
346 | MUX_GATE(CLK_TOP_MUX_MSDC50_0, "msdc50_0_sel" , msdc50_0_parents, |
347 | 0x0070, 16, 4, 23), |
348 | MUX_GATE(CLK_TOP_MUX_MSDC30_1, "msdc30_1_sel" , msdc30_1_parents, |
349 | 0x0070, 24, 3, 31), |
350 | MUX_GATE(CLK_TOP_MUX_MSDC30_2, "msdc30_2_sel" , msdc30_2_parents, |
351 | 0x0080, 0, 3, 7), |
352 | MUX_GATE(CLK_TOP_MUX_AUDIO, "audio_sel" , audio_parents, |
353 | 0x0080, 16, 2, 23), |
354 | MUX(CLK_TOP_MUX_AUD_INTBUS, "aud_intbus_sel" , aud_intbus_parents, |
355 | 0x0080, 24, 2), |
356 | MUX(CLK_TOP_MUX_PMICSPI, "pmicspi_sel" , pmicspi_parents, |
357 | 0x0090, 0, 3), |
358 | MUX(CLK_TOP_MUX_SCP, "scp_sel" , scp_parents, |
359 | 0x0090, 8, 2), |
360 | MUX(CLK_TOP_MUX_ATB, "atb_sel" , atb_parents, |
361 | 0x0090, 16, 2), |
362 | MUX_GATE(CLK_TOP_MUX_MJC, "mjc_sel" , mjc_parents, 0x0090, 24, 2, 31), |
363 | MUX_GATE(CLK_TOP_MUX_DPI0, "dpi0_sel" , dpi0_parents, 0x00A0, 0, 3, 7), |
364 | MUX_GATE(CLK_TOP_MUX_AUD_1, "aud_1_sel" , aud_1_parents, |
365 | 0x00A0, 16, 1, 23), |
366 | MUX_GATE(CLK_TOP_MUX_AUD_2, "aud_2_sel" , aud_2_parents, |
367 | 0x00A0, 24, 1, 31), |
368 | MUX(CLK_TOP_MUX_SSUSB_TOP_SYS, "ssusb_top_sys_sel" , |
369 | ssusb_top_sys_parents, 0x00B0, 8, 1), |
370 | MUX(CLK_TOP_MUX_SPM, "spm_sel" , spm_parents, |
371 | 0x00C0, 0, 1), |
372 | MUX(CLK_TOP_MUX_BSI_SPI, "bsi_spi_sel" , bsi_spi_parents, |
373 | 0x00C0, 8, 2), |
374 | MUX_GATE(CLK_TOP_MUX_AUDIO_H, "audio_h_sel" , audio_h_parents, |
375 | 0x00C0, 16, 2, 23), |
376 | MUX_GATE(CLK_TOP_MUX_ANC_MD32, "anc_md32_sel" , anc_md32_parents, |
377 | 0x00C0, 24, 2, 31), |
378 | MUX(CLK_TOP_MUX_MFG_52M, "mfg_52m_sel" , mfg_52m_parents, |
379 | 0x0104, 1, 2), |
380 | }; |
381 | |
382 | static int mtk_topckgen_init(struct platform_device *pdev) |
383 | { |
384 | struct clk_hw_onecell_data *clk_data; |
385 | void __iomem *base; |
386 | struct device_node *node = pdev->dev.of_node; |
387 | |
388 | base = devm_platform_ioremap_resource(pdev, index: 0); |
389 | if (IS_ERR(ptr: base)) |
390 | return PTR_ERR(ptr: base); |
391 | |
392 | clk_data = mtk_alloc_clk_data(CLK_TOP_NR); |
393 | if (!clk_data) |
394 | return -ENOMEM; |
395 | |
396 | mtk_clk_register_factors(clks: top_fixed_divs, ARRAY_SIZE(top_fixed_divs), |
397 | clk_data); |
398 | |
399 | mtk_clk_register_composites(dev: &pdev->dev, mcs: top_muxes, |
400 | ARRAY_SIZE(top_muxes), base, |
401 | lock: &mt6797_clk_lock, clk_data); |
402 | |
403 | return of_clk_add_hw_provider(np: node, get: of_clk_hw_onecell_get, data: clk_data); |
404 | } |
405 | |
406 | static const struct mtk_gate_regs infra0_cg_regs = { |
407 | .set_ofs = 0x0080, |
408 | .clr_ofs = 0x0084, |
409 | .sta_ofs = 0x0090, |
410 | }; |
411 | |
412 | static const struct mtk_gate_regs infra1_cg_regs = { |
413 | .set_ofs = 0x0088, |
414 | .clr_ofs = 0x008c, |
415 | .sta_ofs = 0x0094, |
416 | }; |
417 | |
418 | static const struct mtk_gate_regs infra2_cg_regs = { |
419 | .set_ofs = 0x00a8, |
420 | .clr_ofs = 0x00ac, |
421 | .sta_ofs = 0x00b0, |
422 | }; |
423 | |
424 | #define GATE_ICG0(_id, _name, _parent, _shift) \ |
425 | GATE_MTK(_id, _name, _parent, &infra0_cg_regs, _shift, &mtk_clk_gate_ops_setclr) |
426 | |
427 | #define GATE_ICG1(_id, _name, _parent, _shift) \ |
428 | GATE_MTK(_id, _name, _parent, &infra1_cg_regs, _shift, &mtk_clk_gate_ops_setclr) |
429 | |
430 | #define GATE_ICG1_FLAGS(_id, _name, _parent, _shift, _flags) \ |
431 | GATE_MTK_FLAGS(_id, _name, _parent, &infra1_cg_regs, _shift, \ |
432 | &mtk_clk_gate_ops_setclr, _flags) |
433 | |
434 | #define GATE_ICG2(_id, _name, _parent, _shift) \ |
435 | GATE_MTK(_id, _name, _parent, &infra2_cg_regs, _shift, &mtk_clk_gate_ops_setclr) |
436 | |
437 | #define GATE_ICG2_FLAGS(_id, _name, _parent, _shift, _flags) \ |
438 | GATE_MTK_FLAGS(_id, _name, _parent, &infra2_cg_regs, _shift, \ |
439 | &mtk_clk_gate_ops_setclr, _flags) |
440 | |
441 | /* |
442 | * Clock gates dramc and dramc_b are needed by the DRAM controller. |
443 | * We mark them as critical as otherwise the system will hang after boot. |
444 | */ |
445 | static const struct mtk_gate infra_clks[] = { |
446 | GATE_ICG0(CLK_INFRA_PMIC_TMR, "infra_pmic_tmr" , "ulposc" , 0), |
447 | GATE_ICG0(CLK_INFRA_PMIC_AP, "infra_pmic_ap" , "pmicspi_sel" , 1), |
448 | GATE_ICG0(CLK_INFRA_PMIC_MD, "infra_pmic_md" , "pmicspi_sel" , 2), |
449 | GATE_ICG0(CLK_INFRA_PMIC_CONN, "infra_pmic_conn" , "pmicspi_sel" , 3), |
450 | GATE_ICG0(CLK_INFRA_SCP, "infra_scp" , "scp_sel" , 4), |
451 | GATE_ICG0(CLK_INFRA_SEJ, "infra_sej" , "axi_sel" , 5), |
452 | GATE_ICG0(CLK_INFRA_APXGPT, "infra_apxgpt" , "axi_sel" , 6), |
453 | GATE_ICG0(CLK_INFRA_SEJ_13M, "infra_sej_13m" , "clk26m" , 7), |
454 | GATE_ICG0(CLK_INFRA_ICUSB, "infra_icusb" , "usb20_sel" , 8), |
455 | GATE_ICG0(CLK_INFRA_GCE, "infra_gce" , "axi_sel" , 9), |
456 | GATE_ICG0(CLK_INFRA_THERM, "infra_therm" , "axi_sel" , 10), |
457 | GATE_ICG0(CLK_INFRA_I2C0, "infra_i2c0" , "axi_sel" , 11), |
458 | GATE_ICG0(CLK_INFRA_I2C1, "infra_i2c1" , "axi_sel" , 12), |
459 | GATE_ICG0(CLK_INFRA_I2C2, "infra_i2c2" , "axi_sel" , 13), |
460 | GATE_ICG0(CLK_INFRA_I2C3, "infra_i2c3" , "axi_sel" , 14), |
461 | GATE_ICG0(CLK_INFRA_PWM_HCLK, "infra_pwm_hclk" , "axi_sel" , 15), |
462 | GATE_ICG0(CLK_INFRA_PWM1, "infra_pwm1" , "axi_sel" , 16), |
463 | GATE_ICG0(CLK_INFRA_PWM2, "infra_pwm2" , "axi_sel" , 17), |
464 | GATE_ICG0(CLK_INFRA_PWM3, "infra_pwm3" , "axi_sel" , 18), |
465 | GATE_ICG0(CLK_INFRA_PWM4, "infra_pwm4" , "axi_sel" , 19), |
466 | GATE_ICG0(CLK_INFRA_PWM, "infra_pwm" , "axi_sel" , 21), |
467 | GATE_ICG0(CLK_INFRA_UART0, "infra_uart0" , "uart_sel" , 22), |
468 | GATE_ICG0(CLK_INFRA_UART1, "infra_uart1" , "uart_sel" , 23), |
469 | GATE_ICG0(CLK_INFRA_UART2, "infra_uart2" , "uart_sel" , 24), |
470 | GATE_ICG0(CLK_INFRA_UART3, "infra_uart3" , "uart_sel" , 25), |
471 | GATE_ICG0(CLK_INFRA_MD2MD_CCIF_0, "infra_md2md_ccif_0" , "axi_sel" , 27), |
472 | GATE_ICG0(CLK_INFRA_MD2MD_CCIF_1, "infra_md2md_ccif_1" , "axi_sel" , 28), |
473 | GATE_ICG0(CLK_INFRA_MD2MD_CCIF_2, "infra_md2md_ccif_2" , "axi_sel" , 29), |
474 | GATE_ICG0(CLK_INFRA_FHCTL, "infra_fhctl" , "clk26m" , 30), |
475 | GATE_ICG0(CLK_INFRA_BTIF, "infra_btif" , "axi_sel" , 31), |
476 | GATE_ICG1(CLK_INFRA_MD2MD_CCIF_3, "infra_md2md_ccif_3" , "axi_sel" , 0), |
477 | GATE_ICG1(CLK_INFRA_SPI, "infra_spi" , "spi_sel" , 1), |
478 | GATE_ICG1(CLK_INFRA_MSDC0, "infra_msdc0" , "msdc50_0_sel" , 2), |
479 | GATE_ICG1(CLK_INFRA_MD2MD_CCIF_4, "infra_md2md_ccif_4" , "axi_sel" , 3), |
480 | GATE_ICG1(CLK_INFRA_MSDC1, "infra_msdc1" , "msdc30_1_sel" , 4), |
481 | GATE_ICG1(CLK_INFRA_MSDC2, "infra_msdc2" , "msdc30_2_sel" , 5), |
482 | GATE_ICG1(CLK_INFRA_MD2MD_CCIF_5, "infra_md2md_ccif_5" , "axi_sel" , 7), |
483 | GATE_ICG1(CLK_INFRA_GCPU, "infra_gcpu" , "axi_sel" , 8), |
484 | GATE_ICG1(CLK_INFRA_TRNG, "infra_trng" , "axi_sel" , 9), |
485 | GATE_ICG1(CLK_INFRA_AUXADC, "infra_auxadc" , "clk26m" , 10), |
486 | GATE_ICG1(CLK_INFRA_CPUM, "infra_cpum" , "axi_sel" , 11), |
487 | GATE_ICG1(CLK_INFRA_AP_C2K_CCIF_0, "infra_ap_c2k_ccif_0" , |
488 | "axi_sel" , 12), |
489 | GATE_ICG1(CLK_INFRA_AP_C2K_CCIF_1, "infra_ap_c2k_ccif_1" , |
490 | "axi_sel" , 13), |
491 | GATE_ICG1(CLK_INFRA_CLDMA, "infra_cldma" , "axi_sel" , 16), |
492 | GATE_ICG1(CLK_INFRA_DISP_PWM, "infra_disp_pwm" , "pwm_sel" , 17), |
493 | GATE_ICG1(CLK_INFRA_AP_DMA, "infra_ap_dma" , "axi_sel" , 18), |
494 | GATE_ICG1(CLK_INFRA_DEVICE_APC, "infra_device_apc" , "axi_sel" , 20), |
495 | GATE_ICG1(CLK_INFRA_L2C_SRAM, "infra_l2c_sram" , "mm_sel" , 22), |
496 | GATE_ICG1(CLK_INFRA_CCIF_AP, "infra_ccif_ap" , "axi_sel" , 23), |
497 | GATE_ICG1(CLK_INFRA_AUDIO, "infra_audio" , "axi_sel" , 25), |
498 | GATE_ICG1(CLK_INFRA_CCIF_MD, "infra_ccif_md" , "axi_sel" , 26), |
499 | GATE_ICG1_FLAGS(CLK_INFRA_DRAMC_F26M, "infra_dramc_f26m" , |
500 | "clk26m" , 31, CLK_IS_CRITICAL), |
501 | GATE_ICG2(CLK_INFRA_I2C4, "infra_i2c4" , "axi_sel" , 0), |
502 | GATE_ICG2(CLK_INFRA_I2C_APPM, "infra_i2c_appm" , "axi_sel" , 1), |
503 | GATE_ICG2(CLK_INFRA_I2C_GPUPM, "infra_i2c_gpupm" , "axi_sel" , 2), |
504 | GATE_ICG2(CLK_INFRA_I2C2_IMM, "infra_i2c2_imm" , "axi_sel" , 3), |
505 | GATE_ICG2(CLK_INFRA_I2C2_ARB, "infra_i2c2_arb" , "axi_sel" , 4), |
506 | GATE_ICG2(CLK_INFRA_I2C3_IMM, "infra_i2c3_imm" , "axi_sel" , 5), |
507 | GATE_ICG2(CLK_INFRA_I2C3_ARB, "infra_i2c3_arb" , "axi_sel" , 6), |
508 | GATE_ICG2(CLK_INFRA_I2C5, "infra_i2c5" , "axi_sel" , 7), |
509 | GATE_ICG2(CLK_INFRA_SYS_CIRQ, "infra_sys_cirq" , "axi_sel" , 8), |
510 | GATE_ICG2(CLK_INFRA_SPI1, "infra_spi1" , "spi_sel" , 10), |
511 | GATE_ICG2_FLAGS(CLK_INFRA_DRAMC_B_F26M, "infra_dramc_b_f26m" , |
512 | "clk26m" , 11, CLK_IS_CRITICAL), |
513 | GATE_ICG2(CLK_INFRA_ANC_MD32, "infra_anc_md32" , "anc_md32_sel" , 12), |
514 | GATE_ICG2(CLK_INFRA_ANC_MD32_32K, "infra_anc_md32_32k" , "clk26m" , 13), |
515 | GATE_ICG2(CLK_INFRA_DVFS_SPM1, "infra_dvfs_spm1" , "axi_sel" , 15), |
516 | GATE_ICG2(CLK_INFRA_AES_TOP0, "infra_aes_top0" , "axi_sel" , 16), |
517 | GATE_ICG2(CLK_INFRA_AES_TOP1, "infra_aes_top1" , "axi_sel" , 17), |
518 | GATE_ICG2(CLK_INFRA_SSUSB_BUS, "infra_ssusb_bus" , "axi_sel" , 18), |
519 | GATE_ICG2(CLK_INFRA_SPI2, "infra_spi2" , "spi_sel" , 19), |
520 | GATE_ICG2(CLK_INFRA_SPI3, "infra_spi3" , "spi_sel" , 20), |
521 | GATE_ICG2(CLK_INFRA_SPI4, "infra_spi4" , "spi_sel" , 21), |
522 | GATE_ICG2(CLK_INFRA_SPI5, "infra_spi5" , "spi_sel" , 22), |
523 | GATE_ICG2(CLK_INFRA_IRTX, "infra_irtx" , "spi_sel" , 23), |
524 | GATE_ICG2(CLK_INFRA_SSUSB_SYS, "infra_ssusb_sys" , |
525 | "ssusb_top_sys_sel" , 24), |
526 | GATE_ICG2(CLK_INFRA_SSUSB_REF, "infra_ssusb_ref" , "clk26m" , 9), |
527 | GATE_ICG2(CLK_INFRA_AUDIO_26M, "infra_audio_26m" , "clk26m" , 26), |
528 | GATE_ICG2(CLK_INFRA_AUDIO_26M_PAD_TOP, "infra_audio_26m_pad_top" , |
529 | "clk26m" , 27), |
530 | GATE_ICG2(CLK_INFRA_MODEM_TEMP_SHARE, "infra_modem_temp_share" , |
531 | "axi_sel" , 28), |
532 | GATE_ICG2(CLK_INFRA_VAD_WRAP_SOC, "infra_vad_wrap_soc" , "axi_sel" , 29), |
533 | GATE_ICG2(CLK_INFRA_DRAMC_CONF, "infra_dramc_conf" , "axi_sel" , 30), |
534 | GATE_ICG2(CLK_INFRA_DRAMC_B_CONF, "infra_dramc_b_conf" , "axi_sel" , 31), |
535 | GATE_ICG1(CLK_INFRA_MFG_VCG, "infra_mfg_vcg" , "mfg_52m_sel" , 14), |
536 | }; |
537 | |
538 | static const struct mtk_fixed_factor infra_fixed_divs[] = { |
539 | FACTOR(CLK_INFRA_13M, "clk13m" , "clk26m" , 1, 2), |
540 | }; |
541 | |
542 | static struct clk_hw_onecell_data *infra_clk_data; |
543 | |
544 | static void mtk_infrasys_init_early(struct device_node *node) |
545 | { |
546 | int r, i; |
547 | |
548 | if (!infra_clk_data) { |
549 | infra_clk_data = mtk_alloc_clk_data(CLK_INFRA_NR); |
550 | if (!infra_clk_data) |
551 | return; |
552 | |
553 | for (i = 0; i < CLK_INFRA_NR; i++) |
554 | infra_clk_data->hws[i] = ERR_PTR(error: -EPROBE_DEFER); |
555 | } |
556 | |
557 | mtk_clk_register_factors(clks: infra_fixed_divs, ARRAY_SIZE(infra_fixed_divs), |
558 | clk_data: infra_clk_data); |
559 | |
560 | r = of_clk_add_hw_provider(np: node, get: of_clk_hw_onecell_get, |
561 | data: infra_clk_data); |
562 | if (r) |
563 | pr_err("%s(): could not register clock provider: %d\n" , |
564 | __func__, r); |
565 | } |
566 | |
567 | CLK_OF_DECLARE_DRIVER(mtk_infra, "mediatek,mt6797-infracfg" , |
568 | mtk_infrasys_init_early); |
569 | |
570 | static int mtk_infrasys_init(struct platform_device *pdev) |
571 | { |
572 | int i; |
573 | struct device_node *node = pdev->dev.of_node; |
574 | |
575 | if (!infra_clk_data) { |
576 | infra_clk_data = mtk_alloc_clk_data(CLK_INFRA_NR); |
577 | if (!infra_clk_data) |
578 | return -ENOMEM; |
579 | } else { |
580 | for (i = 0; i < CLK_INFRA_NR; i++) { |
581 | if (infra_clk_data->hws[i] == ERR_PTR(error: -EPROBE_DEFER)) |
582 | infra_clk_data->hws[i] = ERR_PTR(error: -ENOENT); |
583 | } |
584 | } |
585 | |
586 | mtk_clk_register_gates(dev: &pdev->dev, node, clks: infra_clks, |
587 | ARRAY_SIZE(infra_clks), clk_data: infra_clk_data); |
588 | mtk_clk_register_factors(clks: infra_fixed_divs, ARRAY_SIZE(infra_fixed_divs), |
589 | clk_data: infra_clk_data); |
590 | |
591 | return of_clk_add_hw_provider(np: node, get: of_clk_hw_onecell_get, |
592 | data: infra_clk_data); |
593 | } |
594 | |
595 | #define MT6797_PLL_FMAX (3000UL * MHZ) |
596 | |
597 | #define CON0_MT6797_RST_BAR BIT(24) |
598 | |
599 | #define PLL_B(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, \ |
600 | _pd_reg, _pd_shift, _tuner_reg, _pcw_reg, \ |
601 | _pcw_shift, _div_table) { \ |
602 | .id = _id, \ |
603 | .name = _name, \ |
604 | .reg = _reg, \ |
605 | .pwr_reg = _pwr_reg, \ |
606 | .en_mask = _en_mask, \ |
607 | .flags = _flags, \ |
608 | .rst_bar_mask = CON0_MT6797_RST_BAR, \ |
609 | .fmax = MT6797_PLL_FMAX, \ |
610 | .pcwbits = _pcwbits, \ |
611 | .pd_reg = _pd_reg, \ |
612 | .pd_shift = _pd_shift, \ |
613 | .tuner_reg = _tuner_reg, \ |
614 | .pcw_reg = _pcw_reg, \ |
615 | .pcw_shift = _pcw_shift, \ |
616 | .div_table = _div_table, \ |
617 | } |
618 | |
619 | #define PLL(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, \ |
620 | _pd_reg, _pd_shift, _tuner_reg, _pcw_reg, \ |
621 | _pcw_shift) \ |
622 | PLL_B(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, \ |
623 | _pd_reg, _pd_shift, _tuner_reg, _pcw_reg, _pcw_shift, \ |
624 | NULL) |
625 | |
626 | static const struct mtk_pll_data plls[] = { |
627 | PLL(CLK_APMIXED_MAINPLL, "mainpll" , 0x0220, 0x022C, 0xF0000100, PLL_AO, |
628 | 21, 0x220, 4, 0x0, 0x224, 0), |
629 | PLL(CLK_APMIXED_UNIVPLL, "univpll" , 0x0230, 0x023C, 0xFE000010, 0, 7, |
630 | 0x230, 4, 0x0, 0x234, 14), |
631 | PLL(CLK_APMIXED_MFGPLL, "mfgpll" , 0x0240, 0x024C, 0x00000100, 0, 21, |
632 | 0x244, 24, 0x0, 0x244, 0), |
633 | PLL(CLK_APMIXED_MSDCPLL, "msdcpll" , 0x0250, 0x025C, 0x00000120, 0, 21, |
634 | 0x250, 4, 0x0, 0x254, 0), |
635 | PLL(CLK_APMIXED_IMGPLL, "imgpll" , 0x0260, 0x026C, 0x00000120, 0, 21, |
636 | 0x260, 4, 0x0, 0x264, 0), |
637 | PLL(CLK_APMIXED_TVDPLL, "tvdpll" , 0x0270, 0x027C, 0xC0000120, 0, 21, |
638 | 0x270, 4, 0x0, 0x274, 0), |
639 | PLL(CLK_APMIXED_CODECPLL, "codecpll" , 0x0290, 0x029C, 0x00000120, 0, 21, |
640 | 0x290, 4, 0x0, 0x294, 0), |
641 | PLL(CLK_APMIXED_VDECPLL, "vdecpll" , 0x02E4, 0x02F0, 0x00000120, 0, 21, |
642 | 0x2E4, 4, 0x0, 0x2E8, 0), |
643 | PLL(CLK_APMIXED_APLL1, "apll1" , 0x02A0, 0x02B0, 0x00000130, 0, 31, |
644 | 0x2A0, 4, 0x2A8, 0x2A4, 0), |
645 | PLL(CLK_APMIXED_APLL2, "apll2" , 0x02B4, 0x02C4, 0x00000130, 0, 31, |
646 | 0x2B4, 4, 0x2BC, 0x2B8, 0), |
647 | }; |
648 | |
649 | static int mtk_apmixedsys_init(struct platform_device *pdev) |
650 | { |
651 | struct clk_hw_onecell_data *clk_data; |
652 | struct device_node *node = pdev->dev.of_node; |
653 | |
654 | clk_data = mtk_alloc_clk_data(CLK_APMIXED_NR); |
655 | if (!clk_data) |
656 | return -ENOMEM; |
657 | |
658 | mtk_clk_register_plls(node, plls, ARRAY_SIZE(plls), clk_data); |
659 | |
660 | return of_clk_add_hw_provider(np: node, get: of_clk_hw_onecell_get, data: clk_data); |
661 | } |
662 | |
663 | static const struct of_device_id of_match_clk_mt6797[] = { |
664 | { |
665 | .compatible = "mediatek,mt6797-topckgen" , |
666 | .data = mtk_topckgen_init, |
667 | }, { |
668 | .compatible = "mediatek,mt6797-infracfg" , |
669 | .data = mtk_infrasys_init, |
670 | }, { |
671 | .compatible = "mediatek,mt6797-apmixedsys" , |
672 | .data = mtk_apmixedsys_init, |
673 | }, { |
674 | /* sentinel */ |
675 | } |
676 | }; |
677 | MODULE_DEVICE_TABLE(of, of_match_clk_mt6797); |
678 | |
679 | static int clk_mt6797_probe(struct platform_device *pdev) |
680 | { |
681 | int (*clk_init)(struct platform_device *); |
682 | int r; |
683 | |
684 | clk_init = of_device_get_match_data(dev: &pdev->dev); |
685 | if (!clk_init) |
686 | return -EINVAL; |
687 | |
688 | r = clk_init(pdev); |
689 | if (r) |
690 | dev_err(&pdev->dev, |
691 | "could not register clock provider: %s: %d\n" , |
692 | pdev->name, r); |
693 | |
694 | return r; |
695 | } |
696 | |
697 | static struct platform_driver clk_mt6797_drv = { |
698 | .probe = clk_mt6797_probe, |
699 | .driver = { |
700 | .name = "clk-mt6797" , |
701 | .of_match_table = of_match_clk_mt6797, |
702 | }, |
703 | }; |
704 | |
705 | static int __init clk_mt6797_init(void) |
706 | { |
707 | return platform_driver_register(&clk_mt6797_drv); |
708 | } |
709 | |
710 | arch_initcall(clk_mt6797_init); |
711 | MODULE_LICENSE("GPL" ); |
712 | |