| // SPDX-License-Identifier: GPL-2.0 |
| |
| /* |
| |
| * Copyright (c) 2019 MediaTek Inc. |
| |
| */ |
| |
| #include <linux/clk-provider.h> |
| |
| #include <dt-bindings/power/mt6890-power.h> |
| |
| #define TAG "[scpchk] " |
| #define BUG_ON_CHK_ENABLE 0 |
| |
| /* |
| * The clk names in Mediatek CCF. |
| */ |
| /* audiosys */ |
| struct scpsys_check_swcg audiosys_swcgs[] = { |
| SWCG("aud_afe"), |
| SWCG("aud_22m"), |
| SWCG("aud_24m"), |
| SWCG("aud_apll2_tuner"), |
| SWCG("aud_apll_tuner"), |
| SWCG("aud_tdm_ck"), |
| SWCG("aud_adc"), |
| SWCG("aud_dac"), |
| SWCG("aud_dac_predis"), |
| SWCG("aud_tml"), |
| SWCG("aud_i2s0_bclk"), |
| SWCG("aud_i2s1_bclk"), |
| SWCG("aud_i2s2_bclk"), |
| SWCG("aud_i2s4_bclk"), |
| SWCG("aud_i2s5_bclk"), |
| SWCG("aud_i2s6_bclk"), |
| SWCG("aud_general1_asrc"), |
| SWCG("aud_general2_asrc"), |
| SWCG("aud_adda6_adc"), |
| SWCG("aud_connsys_i2s_asrc"), |
| SWCG("aud_afe_src_pcm_tx"), |
| SWCG("aud_afe_src_pcm_tx2"), |
| SWCG("aud_afe_src_pcm_tx3"), |
| SWCG("aud_afe_src_pcm_rx"), |
| SWCG("aud_afe_src_i2sin"), |
| SWCG("aud_afe_src_i2sout"), |
| SWCG(NULL), |
| }; |
| /* mfgsys */ |
| struct scpsys_check_swcg mfgsys_swcgs[] = { |
| SWCG("mfgcfg_bg3d"), |
| SWCG(NULL), |
| }; |
| |
| struct subsys_cgs_check mtk_subsys_check[] = { |
| {MT6890_POWER_DOMAIN_AUDIO, audiosys_swcgs}, |
| }; |
| |
| static unsigned int check_cg_state(struct scpsys_check_swcg *swcg) |
| { |
| int enable_count = 0; |
| |
| if (!swcg) |
| return 0; |
| |
| while (swcg->name) { |
| if (!IS_ERR_OR_NULL(swcg->c)) { |
| if (__clk_get_enable_count(swcg->c) > 0) { |
| pr_notice("%s[%-17s: %3d]\n", |
| __func__, |
| __clk_get_name(swcg->c), |
| __clk_get_enable_count(swcg->c)); |
| enable_count++; |
| } |
| } |
| swcg++; |
| } |
| |
| return enable_count; |
| } |
| |
| void mtk_check_subsys_swcg(enum subsys_id id) |
| { |
| int i; |
| unsigned int ret = 0; |
| |
| for (i = 0; i < ARRAY_SIZE(mtk_subsys_check); i++) { |
| if (mtk_subsys_check[i].id != id) |
| continue; |
| |
| /* check if Subsys CGs are still on */ |
| ret = check_cg_state(mtk_subsys_check[i].swcgs); |
| if (ret) |
| pr_notice("%s:(%d) warning!\n", __func__, id); |
| } |
| |
| if (ret) { |
| pr_err("%s(%d): %d\n", __func__, id, ret); |
| #if BUG_ON_CHK_ENABLE |
| BUG_ON(1); |
| #endif |
| } |
| } |
| |
| static void __init scpsys_check_swcg_init_common(struct scpsys_check_swcg *swcg) |
| { |
| if (!swcg) |
| return; |
| |
| while (swcg->name) { |
| struct clk *c = __clk_lookup(swcg->name); |
| |
| if (IS_ERR_OR_NULL(c)) |
| pr_notice("[%17s: NULL]\n", swcg->name); |
| else |
| swcg->c = c; |
| swcg++; |
| } |
| } |
| |
| static int __init scpchk_init(void) |
| { |
| /* fill the 'struct clk *' ptr of every CGs*/ |
| int i; |
| |
| if (!of_machine_is_compatible("mediatek,MT6890")) |
| return -ENODEV; |
| |
| for (i = 0; i < ARRAY_SIZE(mtk_subsys_check); i++) |
| scpsys_check_swcg_init_common(mtk_subsys_check[i].swcgs); |
| |
| return 0; |
| } |
| subsys_initcall(scpchk_init); |