blob: 89735471aed4e7dbc31ed84368a661c53eb9f733 [file] [log] [blame]
xjb04a4022021-11-25 15:01:52 +08001// SPDX-License-Identifier: GPL-2.0
2/*
3 * Copyright (C) 2019 MediaTek Inc.
4 */
5
6#include <linux/clk-provider.h>
7#include <linux/syscore_ops.h>
8#include <linux/version.h>
9#define WARN_ON_CHECK_FAIL 0
10#define CLKDBG_CCF_API_4_4 1
11#define TAG "[clkchk] "
12#define clk_warn(fmt, args...) pr_notice(TAG fmt, ##args)
13#if !CLKDBG_CCF_API_4_4
14/* backward compatible */
15static const char *clk_hw_get_name(const struct clk_hw *hw)
16{
17 return __clk_get_name(hw->clk);
18}
19static bool clk_hw_is_prepared(const struct clk_hw *hw)
20{
21 return __clk_is_prepared(hw->clk);
22}
23static bool clk_hw_is_enabled(const struct clk_hw *hw)
24{
25 return __clk_is_enabled(hw->clk);
26}
27#endif /* !CLKDBG_CCF_API_4_4 */
28
29void print_enabled_clks(void);
30
31static const char * const *get_all_clk_names(void)
32{
33 static const char * const clks[] = {
34 /* PLLs */
35 "univpll",
36 "mfgpll",
37 "msdcpll",
38 "mmpll",
39 "apll1",
40 "apll2",
41 "mpll",
42 "lvdspll",
43 "dsppll",
44 "apupll",
45 /* TOP */
46 "i2s0_bck",
47 "dsi0_lntc_dsick",
48 "vpll_dpix",
49 "lvdstx_dig_cts",
50 "mfgpll_ck",
51 "syspll_d2",
52 "syspll1_d4",
53 "syspll1_d16",
54 "syspll_d3",
55 "syspll2_d2",
56 "syspll2_d4",
57 "syspll2_d8",
58 "syspll_d5",
59 "syspll3_d2",
60 "syspll3_d4",
61 "syspll4_d2",
62 "syspll4_d4",
63 "univpll_d2",
64 "univpll1_d2",
65 "univpll1_d4",
66 "univpll_d3",
67 "univpll2_d2",
68 "univpll2_d4",
69 "univpll2_d8",
70 "univpll2_d32",
71 "univpll_d5",
72 "univpll3_d2",
73 "univpll3_d4",
74 "mmpll_ck",
75 "mmpll_d2",
76 "lvdspll_d2",
77 "lvdspll_d4",
78 "lvdspll_d8",
79 "lvdspll_d16",
80 "usb20_192m_ck",
81 "usb20_192m_d4",
82 "usb20_192m_d8",
83 "usb20_192m_d16",
84 "usb20_192m_d32",
85 "apll1_ck",
86 "apll1_d2",
87 "apll1_d4",
88 "apll1_d8",
89 "apll2_ck",
90 "apll2_d2",
91 "apll2_d4",
92 "apll2_d8",
93 "msdcpll_ck",
94 "msdcpll_d2",
95 "dsppll_ck",
96 "dsppll_d2",
97 "dsppll_d4",
98 "dsppll_d8",
99 "apupll_ck",
100 "mpll_d2",
101 "mpll_d4",
102 "clk26m_d52",
103 "mem_sel",
104 "mm_sel",
105 "scp_sel",
106 "mfg_sel",
107 "atb_sel",
108 "camtg_sel",
109 "camtg1_sel",
110 "spi_sel",
111 "msdc50_0_hc_sel",
112 "msdc2_2_hc_sel",
113 "msdc50_0_sel",
114 "msdc50_2_sel",
115 "msdc30_1_sel",
116 "audio_sel",
117 "aud_intbus_sel",
118 "aud_1_sel",
119 "aud_2_sel",
120 "aud_engen1_sel",
121 "aud_engen2_sel",
122 "aud_spdif_sel",
123 "disp_pwm_sel",
124 "ssusb_sys_sel",
125 "ssusb_xhci_sel",
126 "i2c_sel",
127 "pwm_sel",
128 "senif_sel",
129 "aes_fde_sel",
130 "camtm_sel",
131 "dpi0_sel",
132 "dpi1_sel",
133 "dsp_sel",
134 "nfi2x_sel",
135 "nfiecc_sel",
136 "ecc_sel",
137 "eth_sel",
138 "gcpu_sel",
139 "gcpu_cpm_sel",
140 "apu_sel",
141 "apu_if_sel",
142 "mbist_diag_sel",
143 "apll_i2s0_sel",
144 "apll_i2s1_sel",
145 "apll_i2s2_sel",
146 "apll_i2s3_sel",
147 "apll_tdmout_sel",
148 "apll_tdmin_sel",
149 "apll_spdif_sel",
150 "apll12_ck_div0",
151 "apll12_ck_div1",
152 "apll12_ck_div2",
153 "apll12_ck_div3",
154 "apll12_ck_div4",
155 "apll12_ck_div4b",
156 "apll12_ck_div5",
157 "apll12_ck_div5b",
158 "apll12_ck_div6",
159 "aud_i2s0_m_ck",
160 "aud_i2s1_m_ck",
161 "aud_i2s2_m_ck",
162 "aud_i2s3_m_ck",
163 "aud_tdmout_m_ck",
164 "aud_tdmout_b_ck",
165 "aud_tdmin_m_ck",
166 "aud_tdmin_b_ck",
167 "aud_spdif_m_ck",
168 "usb20_48m_en",
169 "univpll_48m_en",
170 "lvdstx_dig_en",
171 "vpll_dpix_en",
172 "ssusb_top_ck_en",
173 "ssusb_phy_ck_en",
174 "conn_32k",
175 "conn_26m",
176 "dsp_32k",
177 "dsp_26m",
178 /* INFRACFG */
179 "ifr_sej",
180 "ifr_apxgpt",
181 "ifr_icusb",
182 "ifr_gce",
183 "ifr_therm",
184 "ifr_pwm_hclk",
185 "ifr_pwm1",
186 "ifr_pwm2",
187 "ifr_pwm3",
188 "ifr_pwm4",
189 "ifr_pwm5",
190 "ifr_pwm",
191 "ifr_uart1",
192 "ifr_gce_26m",
193 "ifr_cq_dma_fpc",
194 "ifr_btif",
195 "ifr_spi0",
196 "ifr_msdc",
197 "ifr_msdc1",
198 "ifr_gcpu",
199 "ifr_trng",
200 "ifr_auxadc",
201 "ifr_auxadc_md",
202 "ifr_ap_dma",
203 "ifr_device_apc",
204 "ifr_audio",
205 "ifr_dramc_f26m",
206 "ifr_pwm_fbclk6",
207 "ifr_disp_pwm",
208 "ifr_aud_26m_bk",
209 "ifr_cq_dma",
210 "ifr_msdc0_sf",
211 "ifr_msdc1_sf",
212 "ifr_msdc2_sf",
213 "ifr_ap_msdc0",
214 "ifr_md_msdc0",
215 "ifr_msdc0_src",
216 "ifr_msdc1_src",
217 "ifr_msdc2_src",
218 "ifr_sej_f13m",
219 "ifr_mcu_pm_bk",
220 "ifr_irrx_26m",
221 "ifr_i2c0_axi",
222 "ifr_i2c1_axi",
223 "ifr_i2c2_axi",
224 "ifr_i2c3_axi",
225 "ifr_nic_axi",
226 "ifr_nic_slv_axi",
227 "ifr_apu_axi",
228 "ifr_nfiecc",
229 "ifr_nfiecc_bk",
230 "ifr_nfi1x_bk",
231 "ifr_nfi_bk",
232 "ifr_msdc2_ap_bk",
233 "ifr_msdc2_md_bk",
234 "ifr_msdc2_bk",
235 "ifr_susb_133_bk",
236 "ifr_susb_66_bk",
237 "ifr_ssusb_sys",
238 "ifr_ssusb_ref",
239 "ifr_ssusb_xhci",
240 /* AUDIO */
241 "aud_afe",
242 "aud_22m",
243 "aud_24m",
244 "aud_apll_tuner",
245 "aud_adc",
246 "aud_dac",
247 "aud_dac_predis",
248 "aud_tml",
249 "aud_i2s1_bclk",
250 "aud_i2s2_bclk",
251 "aud_i2s3_bclk",
252 "aud_i2s4_bclk",
253 /* CAM */
254 "cam_larb2",
255 "cam",
256 "camtg",
257 "cam_senif",
258 "camsv0",
259 "camsv1",
260 "cam_fdvt",
261 "cam_wpe",
262 /* IMG */
263 "img_larb2",
264 "img_dip",
265 "img_fdvt",
266 "img_dpe",
267 "img_rsc",
268 /* MFG */
269 "mfg_bg3d",
270 "mfg_mbist_diag",
271 /* MM */
272 "mm_mdp_rdma0",
273 "mm_mdp_ccorr0",
274 "mm_mdp_rsz0",
275 "mm_mdp_rsz1",
276 "mm_mdp_tdshp0",
277 "mm_mdp_wrot0",
278 "mm_mdp_wdma0",
279 "mm_disp_ovl0",
280 "mm_disp_ovl0_21",
281 "mm_disp_rsz0",
282 "mm_disp_rdma0",
283 "mm_disp_wdma0",
284 "mm_disp_color0",
285 "mm_disp_ccorr0",
286 "mm_disp_aal0",
287 "mm_disp_gamma0",
288 "mm_disp_dither0",
289 "mm_dsi0",
290 "mm_disp_rdma1",
291 "mm_mdp_rdma1",
292 "mm_dpi0_dpi0",
293 "mm_fake",
294 "mm_smi_common",
295 "mm_smi_larb0",
296 "mm_smi_comm0",
297 "mm_smi_comm1",
298 "mm_cam_mdp",
299 "mm_smi_img",
300 "mm_smi_cam",
301 "mm_dl_relay",
302 "mm_dl_async_top",
303 "mm_dsi0_dig_dsi",
304 "mm_f26m_hrtwt",
305 "mm_dpi0",
306 "mm_flvdstx_pxl",
307 "mm_flvdstx_cts",
308 /* VENC */
309 "venc_fvenc_ck",
310 "venc_jpgenc_ck",
311 /* VDEC */
312 "vdec_fvdec_ck",
313 "vdec_flarb1_ck",
314 /* end */
315 NULL
316 };
317 return clks;
318}
319
320static const char *ccf_state(struct clk_hw *hw)
321{
322 if (__clk_get_enable_count(hw->clk))
323 return "enabled";
324 if (clk_hw_is_prepared(hw))
325 return "prepared";
326 return "disabled";
327}
328
329void print_enabled_clks(void)
330{
331 const char * const *cn = get_all_clk_names();
332
333 clk_warn("enabled clks:\n");
334 for (; *cn; cn++) {
335 struct clk *c = __clk_lookup(*cn);
336 struct clk_hw *c_hw = __clk_get_hw(c);
337 struct clk_hw *p_hw;
338
339 if (IS_ERR_OR_NULL(c) || !c_hw)
340 continue;
341 p_hw = clk_hw_get_parent(c_hw);
342 if (!p_hw)
343 continue;
344 if (!clk_hw_is_prepared(c_hw) && !__clk_get_enable_count(c))
345 continue;
346 clk_warn("[%-17s: %8s, %3d, %3d, %10ld, %17s]\n",
347 clk_hw_get_name(c_hw),
348 ccf_state(c_hw),
349 clk_hw_is_prepared(c_hw),
350 __clk_get_enable_count(c),
351 clk_hw_get_rate(c_hw),
352 p_hw ? clk_hw_get_name(p_hw) : "- ");
353 }
354}
355
356static void check_pll_off(void)
357{
358 static const char * const off_pll_names[] = {
359 "univpll",
360 "mfgpll",
361 "apll1",
362 "apll2",
363 "mmpll",
364 "msdcpll",
365 "lvdspll",
366 "dsppll",
367 "apupll",
368 NULL
369 };
370 static struct clk *off_plls[ARRAY_SIZE(off_pll_names)];
371 struct clk **c;
372 int invalid = 0;
373 char buf[128] = {0};
374 int n = 0;
375
376 if (!off_plls[0]) {
377 const char * const *pn;
378
379 for (pn = off_pll_names, c = off_plls; *pn; pn++, c++)
380 *c = __clk_lookup(*pn);
381 }
382 for (c = off_plls; *c; c++) {
383 struct clk_hw *c_hw = __clk_get_hw(*c);
384
385 if (!c_hw)
386 continue;
387 if (!clk_hw_is_enabled(c_hw))
388 continue;
389 n += snprintf(buf + n, sizeof(buf) - n, "%s ",
390 clk_hw_get_name(c_hw));
391 invalid++;
392 }
393 if (invalid) {
394 clk_warn("suspend warning: unexpected unclosed PLL: %s\n", buf);
395 print_enabled_clks();
396#if WARN_ON_CHECK_FAIL
397 WARN_ON(1);
398#endif
399 }
400
401}
402
403void print_enabled_clks_once(void)
404{
405 static bool first_flag = true;
406
407 if (first_flag) {
408 first_flag = false;
409 print_enabled_clks();
410 }
411}
412
413static int clkchk_syscore_suspend(void)
414{
415 check_pll_off();
416 return 0;
417}
418
419static void clkchk_syscore_resume(void)
420{
421}
422
423static struct syscore_ops clkchk_syscore_ops = {
424 .suspend = clkchk_syscore_suspend,
425 .resume = clkchk_syscore_resume,
426};
427
428static int __init clkchk_init(void)
429{
430 if (!of_machine_is_compatible("mediatek,mt8168"))
431 return -ENODEV;
432 register_syscore_ops(&clkchk_syscore_ops);
433 return 0;
434}
435subsys_initcall(clkchk_init);