// SPDX-License-Identifier: GPL-2.0 /* * Copyright (c) 2019 MediaTek Inc. * Author: Weiyi Lu */ #include #include #include "clkdbg.h" #define DUMP_INIT_STATE 0 /* * clkdbg dump_regs */ enum { topckgen, infracfg, pericfg, scpsys, apmixed, fhctl, mfgsys, mmsys, imgsys, bdpsys, vdecsys, vencsys, jpgdecsys, }; #define REGBASE_V(_phys, _id_name) { .phys = _phys, .name = #_id_name } /* * checkpatch.pl ERROR:COMPLEX_MACRO * * #define REGBASE(_phys, _id_name) [_id_name] = REGBASE_V(_phys, _id_name) */ static struct regbase rb[] = { [topckgen] = REGBASE_V(0x10000000, topckgen), [infracfg] = REGBASE_V(0x10001000, infracfg), [pericfg] = REGBASE_V(0x10003000, pericfg), [scpsys] = REGBASE_V(0x10006000, scpsys), [apmixed] = REGBASE_V(0x10209000, apmixed), [fhctl] = REGBASE_V(0x10209e00, fhctl), [mfgsys] = REGBASE_V(0x13000000, mfgsys), [mmsys] = REGBASE_V(0x14000000, mmsys), [imgsys] = REGBASE_V(0x15000000, imgsys), [bdpsys] = REGBASE_V(0x15010000, bdpsys), [vdecsys] = REGBASE_V(0x16000000, vdecsys), [vencsys] = REGBASE_V(0x18000000, vencsys), [jpgdecsys] = REGBASE_V(0x19000000, jpgdecsys), }; #define REGNAME(_base, _ofs, _name) \ { .base = &rb[_base], .ofs = _ofs, .name = #_name } static struct regname rn[] = { REGNAME(topckgen, 0x040, CLK_CFG_0), REGNAME(topckgen, 0x050, CLK_CFG_1), REGNAME(topckgen, 0x060, CLK_CFG_2), REGNAME(topckgen, 0x070, CLK_CFG_3), REGNAME(topckgen, 0x080, CLK_CFG_4), REGNAME(topckgen, 0x090, CLK_CFG_5), REGNAME(topckgen, 0x0a0, CLK_CFG_6), REGNAME(topckgen, 0x0b0, CLK_CFG_7), REGNAME(topckgen, 0x0c0, CLK_CFG_8), REGNAME(topckgen, 0x0d0, CLK_CFG_9), REGNAME(topckgen, 0x134, CLK_AUDDIV_4), REGNAME(topckgen, 0x500, CLK_CFG_10), REGNAME(topckgen, 0x510, CLK_CFG_11), REGNAME(topckgen, 0x520, CLK_CFG_12), REGNAME(topckgen, 0x530, CLK_CFG_13), REGNAME(topckgen, 0x540, CLK_CFG_14), REGNAME(topckgen, 0x550, CLK_CFG_15), REGNAME(topckgen, 0x560, CLK_CFG_16), REGNAME(topckgen, 0x570, CLK_CFG_17), REGNAME(scpsys, 0x210, SPM_VDE_PWR_CON), REGNAME(scpsys, 0x214, SPM_MFG_PWR_CON), REGNAME(scpsys, 0x230, SPM_VEN_PWR_CON), REGNAME(scpsys, 0x238, SPM_ISP_PWR_CON), REGNAME(scpsys, 0x23c, SPM_DIS_PWR_CON), REGNAME(scpsys, 0x29c, SPM_AUDIO_PWR_CON), REGNAME(scpsys, 0x2cc, SPM_USB_PWR_CON), REGNAME(scpsys, 0x2d4, SPM_USB2_PWR_CON), REGNAME(scpsys, 0x60c, SPM_PWR_STATUS), REGNAME(scpsys, 0x610, SPM_PWR_STATUS_2ND), REGNAME(apmixed, 0x004, AP_PLL_CON1), REGNAME(apmixed, 0x008, AP_PLL_CON2), REGNAME(apmixed, 0x100, ARMCA35PLL_CON0), REGNAME(apmixed, 0x104, ARMCA35PLL_CON1), REGNAME(apmixed, 0x110, ARMCA35PLL_PWR_CON0), REGNAME(apmixed, 0x210, ARMCA72PLL_CON0), REGNAME(apmixed, 0x214, ARMCA72PLL_CON1), REGNAME(apmixed, 0x210, ARMCA72PLL_PWR_CON0), REGNAME(apmixed, 0x230, MAINPLL_CON0), REGNAME(apmixed, 0x234, MAINPLL_CON1), REGNAME(apmixed, 0x23c, MAINPLL_PWR_CON0), REGNAME(apmixed, 0x240, UNIVPLL_CON0), REGNAME(apmixed, 0x244, UNIVPLL_CON1), REGNAME(apmixed, 0x24c, UNIVPLL_PWR_CON0), REGNAME(apmixed, 0x250, MMPLL_CON0), REGNAME(apmixed, 0x254, MMPLL_CON1), REGNAME(apmixed, 0x260, MMPLL_PWR_CON0), REGNAME(apmixed, 0x270, MSDCPLL_CON0), REGNAME(apmixed, 0x274, MSDCPLL_CON1), REGNAME(apmixed, 0x27c, MSDCPLL_PWR_CON0), REGNAME(apmixed, 0x280, VENCPLL_CON0), REGNAME(apmixed, 0x284, VENCPLL_CON1), REGNAME(apmixed, 0x28c, VENCPLL_PWR_CON0), REGNAME(apmixed, 0x290, TVDPLL_CON0), REGNAME(apmixed, 0x294, TVDPLL_CON1), REGNAME(apmixed, 0x29c, TVDPLL_PWR_CON0), REGNAME(apmixed, 0x300, ETHERPLL_CON0), REGNAME(apmixed, 0x304, ETHERPLL_CON1), REGNAME(apmixed, 0x30c, ETHERPLL_PWR_CON0), REGNAME(apmixed, 0x320, VCODECPLL_CON0), REGNAME(apmixed, 0x324, VCODECPLL_CON1), REGNAME(apmixed, 0x32c, VCODECPLL_PWR_CON0), REGNAME(apmixed, 0x330, APLL1_CON0), REGNAME(apmixed, 0x334, APLL1_CON1), REGNAME(apmixed, 0x340, APLL1_PWR_CON0), REGNAME(apmixed, 0x350, APLL2_CON0), REGNAME(apmixed, 0x354, APLL2_CON1), REGNAME(apmixed, 0x360, APLL2_PWR_CON0), REGNAME(apmixed, 0x370, LVDSPLL_CON0), REGNAME(apmixed, 0x374, LVDSPLL_CON1), REGNAME(apmixed, 0x37c, LVDSPLL_PWR_CON0), REGNAME(apmixed, 0x390, LVDSPLL2_CON0), REGNAME(apmixed, 0x394, LVDSPLL2_CON1), REGNAME(apmixed, 0x39c, LVDSPLL2_PWR_CON0), REGNAME(apmixed, 0x410, MSDCPLL2_CON0), REGNAME(apmixed, 0x414, MSDCPLL2_CON1), REGNAME(apmixed, 0x41c, MSDCPLL2_PWR_CON0), REGNAME(topckgen, 0x120, CLK_AUDDIV_0), REGNAME(infracfg, 0x040, INFRA_PDN_STA), REGNAME(pericfg, 0x018, PERI_PDN0_STA), REGNAME(pericfg, 0x01c, PERI_PDN1_STA), REGNAME(pericfg, 0x42c, PERI_MSDC_CLK_EN), REGNAME(mfgsys, 0x000, MFG_CG_STA), REGNAME(mmsys, 0x100, MMSYS_CG0_STA), REGNAME(mmsys, 0x110, MMSYS_CG1_STA), REGNAME(mmsys, 0x220, MMSYS_CG2_STA), REGNAME(imgsys, 0x000, IMG_CG), REGNAME(bdpsys, 0x100, BDP_DISPSYS_CG_CON0), REGNAME(vdecsys, 0x000, VDEC_CKEN_SET), REGNAME(vdecsys, 0x008, VDEC_LARB1_CKEN_STA), REGNAME(vencsys, 0x000, VENC_CG_STA), REGNAME(jpgdecsys, 0x000, JPGDEC_CG_STA), {} }; static const struct regname *get_all_regnames(void) { return rn; } static void __init init_regbase(void) { size_t i; for (i = 0; i < ARRAY_SIZE(rb); i++) rb[i].virt = ioremap(rb[i].phys, PAGE_SIZE); } /* * clkdbg fmeter */ #include #ifndef GENMASK #define GENMASK(h, l) (((1U << ((h) - (l) + 1)) - 1) << (l)) #endif #define ALT_BITS(o, h, l, v) \ (((o) & ~GENMASK(h, l)) | (((v) << (l)) & GENMASK(h, l))) #define clk_readl(addr) readl(addr) #define clk_writel(addr, val) \ do { writel(val, addr); wmb(); } while (0) /* sync write */ #define clk_writel_mask(addr, mask, val) \ clk_writel(addr, (clk_readl(addr) & ~(mask)) | (val)) #define ABS_DIFF(a, b) ((a) > (b) ? (a) - (b) : (b) - (a)) #define FMCLK(_t, _i, _n) { .type = _t, .id = _i, .name = _n } static const struct fmeter_clk fclks[] = { FMCLK(ABIST, 2, "AD_ARMCA35PLL_600M_CORE_CK"), FMCLK(ABIST, 3, "AD_ARMCA35PLL_400M_CORE_CK"), FMCLK(ABIST, 4, "AD_MAIN_H546M_CK"), FMCLK(ABIST, 5, "AD_MAIN_H364M_CK"), FMCLK(ABIST, 6, "AD_MAIN_H218P4M_CK"), FMCLK(ABIST, 7, "AD_MAIN_H156M_CK"), FMCLK(ABIST, 8, "AD_UNIV_178P3M_CK"), FMCLK(ABIST, 9, "AD_UNIVPLL_UNIV_48M_CK"), FMCLK(ABIST, 10, "AD_UNIV_624M_CK"), FMCLK(ABIST, 11, "AD_UNIV_416M_CK"), FMCLK(ABIST, 12, "AD_UNIV_249P6M_CK"), FMCLK(ABIST, 13, "AD_APLL1_CK"), FMCLK(ABIST, 14, "AD_APLL2_CK"), FMCLK(ABIST, 15, "AD_LTEPLL_FS26M_CK"), FMCLK(ABIST, 16, "rtc32k_ck_i"), FMCLK(ABIST, 17, "AD_MMPLL_500M_CK"), FMCLK(ABIST, 18, "AD_VENCPLL_380M_CK"), FMCLK(ABIST, 19, "AD_VCODEPLL_442M_CK"), FMCLK(ABIST, 20, "AD_TVDPLL_572M_CK"), FMCLK(ABIST, 21, "AD_LVDSPLL_150M_CK"), FMCLK(ABIST, 22, "AD_MSDCPLL_400M_CK"), FMCLK(ABIST, 23, "AD_ETHERPLL_50M_CK"), FMCLK(ABIST, 24, "clkph_MCK_o"), FMCLK(ABIST, 25, "AD_USB_48M_CK"), FMCLK(ABIST, 26, "AD_MSDCPLL2_400M_CK"), FMCLK(ABIST, 27, "AD_CVBSADC_CKOUTA"), FMCLK(ABIST, 30, "AD_TVDPLL_429M_CK"), FMCLK(ABIST, 33, "AD_LVDSPLL2_150M_CK"), FMCLK(ABIST, 34, "AD_ETHERPLL_125M_CK"), FMCLK(ABIST, 35, "AD_MIPI_26M_CK_CKSYS"), FMCLK(ABIST, 36, "AD_LTEPLL_ARMPLL26M_CK_CKSYS"), FMCLK(ABIST, 37, "AD_LETPLL_SSUSB26M_CK_CKSYS"), FMCLK(ABIST, 38, "AD_DSI2_LNTC_DSICLK_CKSYS"), FMCLK(ABIST, 39, "AD_DSI3_LNTC_DSICLK_CKSYS"), FMCLK(ABIST, 40, "AD_DSI2_MPPLL_TST_CK_CKSYS"), FMCLK(ABIST, 41, "AD_DSI3_MPPLL_TST_CK_CKSYS"), FMCLK(ABIST, 42, "AD_LVDSTX3_MONCLK"), FMCLK(ABIST, 43, "AD_PLLGP_TST_CK_CKSYS"), FMCLK(ABIST, 44, "AD_SSUSB_48M_CK_CKSYS"), FMCLK(ABIST, 45, "AD_MONREF3_CK"), FMCLK(ABIST, 46, "AD_MONFBK3_CK"), FMCLK(ABIST, 47, "big_clkmon_o"), FMCLK(ABIST, 48, "DA_ARMCPU_MON_CK"), FMCLK(ABIST, 49, "AD_CSI0_LNRC_BYTE_CLK"), FMCLK(ABIST, 50, "AD_CSI1_LNRC_BYTE_CLK"), FMCLK(ABIST, 51, "AD_CSI0_LNRC_4X_CLK"), FMCLK(ABIST, 52, "AD_CSI1_LNRC_4X_CLK"), FMCLK(ABIST, 53, "AD_CSI0_CAL_CLK"), FMCLK(ABIST, 54, "AD_CSI1_CAL_CLK"), FMCLK(ABIST, 55, "AD_UNIVPL_1248M_CK"), FMCLK(ABIST, 56, "AD_MAINPLL_1092_CORE_CK"), FMCLK(ABIST, 57, "AD_ARMCA15PLL_2002M_CORE_CK"), FMCLK(ABIST, 58, "mcusys_arm_clk_out_all"), FMCLK(ABIST, 59, "AD_ARMCA7PLL_1508M_CORE_CK"), FMCLK(ABIST, 61, "AD_UNIVPLL_USB20_48M_CK"), FMCLK(ABIST, 62, "AD_UNIVPLL_USB20_48M_CK1"), FMCLK(ABIST, 63, "AD_UNIVPLL_USB20_48M_CK2"), FMCLK(ABIST, 65, "AD_UNIVPLL_USB20_48M_CK3"), FMCLK(ABIST, 77, "AD_LVDSTX1_MONCLK"), FMCLK(ABIST, 78, "AD_MONREF1_CK"), FMCLK(ABIST, 79, "AD_MONFBK1_CK"), FMCLK(ABIST, 85, "trng_freq_debug_out0"), FMCLK(ABIST, 86, "trng_freq_debug_out1"), FMCLK(ABIST, 87, "AD_DSI0_LNTC_DSICLK_CKSYS"), FMCLK(ABIST, 88, "AD_DSI0_MPLL_TST_CK_CKSYS"), FMCLK(ABIST, 89, "AD_DSI1_LNTC_DSICLK_CKSYS"), FMCLK(ABIST, 90, "AD_DSI1_MPLL_TST_CK_CKSYS"), FMCLK(ABIST, 91, "ddr_clk_freq_meter[0]"), FMCLK(ABIST, 92, "ddr_clk_freq_meter[1]"), FMCLK(ABIST, 93, "ddr_clk_freq_meter[2]"), FMCLK(ABIST, 94, "ddr_clk_freq_meter[3]"), FMCLK(ABIST, 95, "ddr_clk_freq_meter[4]"), FMCLK(ABIST, 96, "ddr_clk_freq_meter[5]"), FMCLK(ABIST, 97, "ddr_clk_freq_meter[6]"), FMCLK(ABIST, 98, "ddr_clk_freq_meter[7]"), FMCLK(ABIST, 99, "ddr_clk_freq_meter[8]"), FMCLK(ABIST, 100, "ddr_clk_freq_meter[9]"), FMCLK(ABIST, 101, "ddr_clk_freq_meter[10]"), FMCLK(ABIST, 102, "ddr_clk_freq_meter[11]"), FMCLK(ABIST, 103, "ddr_clk_freq_meter[12]"), FMCLK(ABIST, 104, "ddr_clk_freq_meter[13]"), FMCLK(ABIST, 105, "ddr_clk_freq_meter[14]"), FMCLK(ABIST, 106, "ddr_clk_freq_meter[15]"), FMCLK(ABIST, 107, "ddr_clk_freq_meter[16]"), FMCLK(ABIST, 108, "ddr_clk_freq_meter[17]"), FMCLK(ABIST, 109, "ddr_clk_freq_meter[18]"), FMCLK(ABIST, 110, "ddr_clk_freq_meter[19]"), FMCLK(ABIST, 111, "ddr_clk_freq_meter[20]"), FMCLK(ABIST, 112, "ddr_clk_freq_meter[21]"), FMCLK(ABIST, 113, "ddr_clk_freq_meter[22]"), FMCLK(ABIST, 114, "ddr_clk_freq_meter[23]"), FMCLK(ABIST, 115, "ddr_clk_freq_meter[24]"), FMCLK(ABIST, 116, "ddr_clk_freq_meter[25]"), FMCLK(ABIST, 117, "ddr_clk_freq_meter[26]"), FMCLK(ABIST, 118, "ddr_clk_freq_meter[27]"), FMCLK(ABIST, 119, "ddr_clk_freq_meter[28]"), FMCLK(ABIST, 120, "ddr_clk_freq_meter[29]"), FMCLK(ABIST, 121, "ddr_clk_freq_meter[30]"), FMCLK(ABIST, 122, "ddr_clk_freq_meter[31]"), FMCLK(ABIST, 123, "ddr_clk_freq_meter[32]"), FMCLK(ABIST, 124, "ddr_clk_freq_meter[33]"), FMCLK(ABIST, 125, "ddr_clk_freq_meter[34]"), FMCLK(CKGEN, 1, "hf_faxi_ck"), FMCLK(CKGEN, 2, "hd_faxi_ck"), FMCLK(CKGEN, 3, "hf_fscam_ck"), FMCLK(CKGEN, 5, "hf_fmm_ck"), FMCLK(CKGEN, 6, "f_fpwm_ck"), FMCLK(CKGEN, 7, "hf_fvdec_ck"), FMCLK(CKGEN, 8, "hf_fvenc_ck"), FMCLK(CKGEN, 9, "hf_fmfg_ck"), FMCLK(CKGEN, 10, "hf_fcamtg_ck"), FMCLK(CKGEN, 11, "f_fuart_ck"), FMCLK(CKGEN, 12, "hf_fspi_ck"), FMCLK(CKGEN, 13, "f_fusb20_ck"), FMCLK(CKGEN, 14, "f_fusb30_ck"), FMCLK(CKGEN, 15, "hf_fmsdc50_0_hclk_ck"), FMCLK(CKGEN, 16, "hf_fmsdc50_0_ck"), FMCLK(CKGEN, 17, "hf_fmsdc30_1_ck"), FMCLK(CKGEN, 18, "hf_fmsdc30_2_ck"), FMCLK(CKGEN, 19, "hf_fmsdc30_3_ck"), FMCLK(CKGEN, 20, "hf_faudio_ck"), FMCLK(CKGEN, 21, "hf_faud_intbus_ck"), FMCLK(CKGEN, 22, "hf_fpmicspi_ck"), FMCLK(CKGEN, 23, "hf_fdpilvds1_ck"), FMCLK(CKGEN, 24, "hf_fatb_ck"), FMCLK(CKGEN, 25, "hf_fnr_ck"), FMCLK(CKGEN, 26, "hf_firda_ck"), FMCLK(CKGEN, 27, "hf_fcci400_ck"), FMCLK(CKGEN, 28, "hf_faud_1_ck"), FMCLK(CKGEN, 29, "hf_faud_2_ck"), FMCLK(CKGEN, 30, "hf_fmem_mfg_in_as_ck"), FMCLK(CKGEN, 31, "hf_faxi_mfg_in_as_ck"), FMCLK(CKGEN, 32, "f_frtc_ck"), FMCLK(CKGEN, 33, "f_f26m_ck"), FMCLK(CKGEN, 34, "f_f32k_md1_ck"), FMCLK(CKGEN, 35, "f_frtc_conn_ck"), FMCLK(CKGEN, 36, "hg_fmipicfg_ck"), FMCLK(CKGEN, 37, "hd_haxi_nli_ck"), FMCLK(CKGEN, 38, "hd_qaxidcm_ck"), FMCLK(CKGEN, 39, "f_ffpc_ck"), FMCLK(CKGEN, 40, "f_fckbus_ck_scan"), FMCLK(CKGEN, 41, "f_fckrtc_ck_scan"), FMCLK(CKGEN, 42, "hf_flvds_pxl_ck"), FMCLK(CKGEN, 43, "hf_flvds_cts_ck"), FMCLK(CKGEN, 44, "hf_fdpilvds_ck"), FMCLK(CKGEN, 45, "hf_flvds1_pxl_ck"), FMCLK(CKGEN, 46, "hf_flvds1_cts_ck"), FMCLK(CKGEN, 47, "hf_fhdcp_ck"), FMCLK(CKGEN, 48, "hf_fmsdc50_3_hclk_ck"), FMCLK(CKGEN, 49, "hf_fhdcp_24m_ck"), FMCLK(CKGEN, 50, "hf_fmsdc0p_aes_ck"), FMCLK(CKGEN, 51, "hf_fgcpu_ck"), FMCLK(CKGEN, 52, "hf_fmem_ck"), FMCLK(CKGEN, 53, "hf_fi2so1_mck"), FMCLK(CKGEN, 54, "hf_fcam2tg_ck"), FMCLK(CKGEN, 55, "hf_fether_125m_ck"), FMCLK(CKGEN, 56, "hf_fapll2_ck"), FMCLK(CKGEN, 57, "hf_fa2sys_hp_ck"), FMCLK(CKGEN, 58, "hf_fasm_l_ck"), FMCLK(CKGEN, 59, "hf_fspislv_ck"), FMCLK(CKGEN, 60, "hf_ftdmo1_mck"), FMCLK(CKGEN, 61, "hf_fasm_h_ck"), FMCLK(CKGEN, 62, "hf_ftdmo0_mck"), FMCLK(CKGEN, 63, "hf_fa1sys_hp_ck"), FMCLK(CKGEN, 65, "hf_fasm_m_ck"), FMCLK(CKGEN, 66, "hf_fapll_ck"), FMCLK(CKGEN, 67, "hf_fspinor_ck"), FMCLK(CKGEN, 68, "hf_fpe2_mac_p0_ck"), FMCLK(CKGEN, 69, "hf_fjpgdec_ck"), FMCLK(CKGEN, 70, "hf_fpwm_infra_ck"), FMCLK(CKGEN, 71, "hf_fnfiecc_ck"), FMCLK(CKGEN, 72, "hf_fether_50m_rmii_ck"), FMCLK(CKGEN, 73, "hf_fi2c_ck"), FMCLK(CKGEN, 74, "hf_fcmsys_ck"), FMCLK(CKGEN, 75, "hf_fpe2_mac_p1_ck"), FMCLK(CKGEN, 76, "hf_fdi_ck"), FMCLK(CKGEN, 77, "hf_fi2si3_mck"), FMCLK(CKGEN, 78, "hf_fether_50m_ck"), FMCLK(CKGEN, 79, "hf_fi2si2_mck"), FMCLK(CKGEN, 80, "hf_fi2so3_mck"), FMCLK(CKGEN, 81, "hf_ftvd_ck"), FMCLK(CKGEN, 82, "hf_fnfi2x_ck"), FMCLK(CKGEN, 83, "hf_fi2si1_mck"), FMCLK(CKGEN, 84, "hf_fi2so2_mck"), {} }; #define FHCTL_HP_EN (rb[fhctl].virt + 0x000) #define CLK_CFG_M0 (rb[topckgen].virt + 0x100) #define CLK_CFG_M1 (rb[topckgen].virt + 0x104) #define CLK_MISC_CFG_1 (rb[topckgen].virt + 0x214) #define CLK_MISC_CFG_2 (rb[topckgen].virt + 0x218) #define CLK26CALI_0 (rb[topckgen].virt + 0x220) #define CLK26CALI_1 (rb[topckgen].virt + 0x224) #define CLK26CALI_2 (rb[topckgen].virt + 0x228) #define PLL_TEST_CON0 (rb[apmixed].virt + 0x040) #define CVBSPLL_CON1 (rb[apmixed].virt + 0x314) #define CVBSREFPLL_CON1 (rb[apmixed].virt + 0x31c) #define RG_FRMTR_WINDOW 1023U static void set_fmeter_divider_ca35(u32 k1) { u32 val = clk_readl(CLK_MISC_CFG_1); val = ALT_BITS(val, 15, 8, k1); clk_writel(CLK_MISC_CFG_1, val); } static void set_fmeter_divider_ca72(u32 k1) { u32 val = clk_readl(CLK_MISC_CFG_2); val = ALT_BITS(val, 7, 0, k1); clk_writel(CLK_MISC_CFG_2, val); } static void set_fmeter_divider(u32 k1) { u32 val = clk_readl(CLK_MISC_CFG_1); val = ALT_BITS(val, 7, 0, k1); val = ALT_BITS(val, 31, 24, k1); clk_writel(CLK_MISC_CFG_1, val); } static u8 wait_fmeter_done(u32 tri_bit) { static int max_wait_count; int wait_count = (max_wait_count > 0) ? (max_wait_count * 2 + 2) : 100; int i; /* wait fmeter */ for (i = 0; i < wait_count && (clk_readl(CLK26CALI_0) & tri_bit) != 0U; i++) udelay(20); if ((clk_readl(CLK26CALI_0) & tri_bit) == 0U) { max_wait_count = max(max_wait_count, i); return 1; } return 0; } static u32 fmeter_freq(enum FMETER_TYPE type, u32 k1, u32 clk) { void __iomem *clk_cfg_reg = (type == CKGEN) ? CLK_CFG_M1 : CLK_CFG_M0; void __iomem *cnt_reg = (type == CKGEN) ? CLK26CALI_2 : CLK26CALI_1; u32 cksw_mask = (type == CKGEN) ? GENMASK(22, 16) : GENMASK(14, 8); u32 cksw_val = (type == CKGEN) ? (clk << 16) : (clk << 8); u32 tri_bit = (type == CKGEN) ? BIT(4) : BIT(0); u32 clk_exc = (type == CKGEN) ? BIT(5) : BIT(2); u32 clk_misc_cfg_1, clk_misc_cfg_2, clk_cfg_val, cnt, freq = 0; /* setup fmeter */ clk_setl(CLK26CALI_0, BIT(7)); /* enable fmeter_en */ clk_clrl(CLK26CALI_0, clk_exc); /* set clk_exc */ /* load_cnt */ clk_writel_mask(cnt_reg, GENMASK(25, 16), RG_FRMTR_WINDOW << 16); /* backup CLK_MISC_CFG_1 value */ clk_misc_cfg_1 = clk_readl(CLK_MISC_CFG_1); /* backup CLK_MISC_CFG_2 value */ clk_misc_cfg_2 = clk_readl(CLK_MISC_CFG_2); /* backup clk_cfg_reg value */ clk_cfg_val = clk_readl(clk_cfg_reg); set_fmeter_divider(k1); /* set divider (0 = /1) */ set_fmeter_divider_ca35(k1); set_fmeter_divider_ca72(k1); /* select cksw */ clk_writel_mask(clk_cfg_reg, cksw_mask, cksw_val); clk_setl(CLK26CALI_0, tri_bit); /* start fmeter */ if (wait_fmeter_done(tri_bit) == 1U) { cnt = clk_readl(cnt_reg) & 0xFFFF; /* (KHz) ; freq = counter * 26M / 1024 */ freq = (cnt * 26000U) * (k1 + 1U) / (RG_FRMTR_WINDOW + 1U); } /* restore register settings */ clk_writel(clk_cfg_reg, clk_cfg_val); clk_writel(CLK_MISC_CFG_2, clk_misc_cfg_2); clk_writel(CLK_MISC_CFG_1, clk_misc_cfg_1); clk_clrl(CLK26CALI_0, BIT(7)); /* disable fmeter_en */ return freq; } static u32 measure_stable_fmeter_freq(enum FMETER_TYPE type, u32 k1, u32 clk) { u32 last_freq = 0; u32 freq = fmeter_freq(type, k1, clk); u32 maxfreq = max(freq, last_freq); while (maxfreq != 0U && ABS_DIFF(freq, last_freq) * 100U / maxfreq > 10U) { last_freq = freq; freq = fmeter_freq(type, k1, clk); maxfreq = max(freq, last_freq); } return freq; } static const struct fmeter_clk *get_all_fmeter_clks(void) { return fclks; } struct bak { u32 fhctl_hp_en; }; static void *prepare_fmeter(void) { static struct bak regs; regs.fhctl_hp_en = clk_readl(FHCTL_HP_EN); clk_writel(FHCTL_HP_EN, 0x0); /* disable PLL hopping */ udelay(10); /* use AD_PLLGP_TST_CK_CKSYS to measure CVBSPLL */ /* [9:8]:TST_SEL, [3:0]:TSTOD_EN, A2DCK_EN, TSTCK_EN, TST_EN */ clk_setl(PLL_TEST_CON0, 0x30F); /* [4]:CVBS_MONCK_EN, [3:0]:CVBSREFPLL_TESTMUX */ clk_setl(CVBSREFPLL_CON1, 0x11); clk_setl(CVBSPLL_CON1, 0x20); /* [5]: CVBSPLL_MONCK_EN */ return ®s; } static void unprepare_fmeter(void *data) { struct bak *regs = data; /* [9:8]:TST_SEL, [3:0]:TSTOD_EN, A2DCK_EN, TSTCK_EN, TST_EN */ clk_clrl(PLL_TEST_CON0, 0x30F); /* [4]:CVBS_MONCK_EN, [3:0]:CVBSREFPLL_TESTMUX */ clk_clrl(CVBSREFPLL_CON1, 0x11); clk_clrl(CVBSPLL_CON1, 0x20); /* [5]: CVBSPLL_MONCK_EN */ /* restore old setting */ clk_writel(FHCTL_HP_EN, regs->fhctl_hp_en); } static u32 fmeter_freq_op(const struct fmeter_clk *fclk) { if (fclk->type != FT_NULL) return measure_stable_fmeter_freq(fclk->type, 0, fclk->id); return 0; } /* * clkdbg dump_state */ static const char * const *get_all_clk_names(void) { static const char * const clks[] = { /* plls */ "mainpll", "univpll", "vcodecpll", "vencpll", "apll1", "apll2", "lvdspll", "lvdspll2", "msdcpll", "msdcpll2", "tvdpll", "mmpll", "armca35pll", "armca72pll", "etherpll", "cvbspll", /* topckgen */ "armca35pll_ck", "armca35pll_600m", "armca35pll_400m", "armca72pll_ck", "syspll_ck", "syspll_d2", "syspll1_d2", "syspll1_d4", "syspll1_d8", "syspll1_d16", "syspll_d3", "syspll2_d2", "syspll2_d4", "syspll_d5", "syspll3_d2", "syspll3_d4", "syspll_d7", "syspll4_d2", "syspll4_d4", "univpll_ck", "univpll_d7", "univpll_d26", "univpll_d52", "univpll_d104", "univpll_d208", "univpll_d2", "univpll1_d2", "univpll1_d4", "univpll1_d8", "univpll_d3", "univpll2_d2", "univpll2_d4", "univpll2_d8", "univpll_d5", "univpll3_d2", "univpll3_d4", "univpll3_d8", "f_mp0_pll1_ck", "f_mp0_pll2_ck", "f_big_pll1_ck", "f_big_pll2_ck", "f_bus_pll1_ck", "f_bus_pll2_ck", "apll1_ck", "apll1_d2", "apll1_d3", "apll1_d4", "apll1_d8", "apll1_d16", "apll2_ck", "apll2_d2", "apll2_d4", "apll2_d8", "apll2_d16", "lvdspll_ck", "lvdspll_d2", "lvdspll_d4", "lvdspll_d8", "lvdspll2_ck", "lvdspll2_d2", "lvdspll2_d4", "lvdspll2_d8", "etherpll_125m", "etherpll_50m", "cvbs", "cvbs_d2", "sys_26m", "mmpll_ck", "mmpll_d2", "vencpll_ck", "vencpll_d2", "vcodecpll_ck", "vcodecpll_d2", "tvdpll_ck", "tvdpll_d2", "tvdpll_d4", "tvdpll_d8", "tvdpll_429m", "tvdpll_429m_d2", "tvdpll_429m_d4", "msdcpll_ck", "msdcpll_d2", "msdcpll_d4", "msdcpll2_ck", "msdcpll2_d2", "msdcpll2_d4", "clk26m_d2", "d2a_ulclk_6p5m", "vpll3_dpix", "vpll_dpix", "ltepll_fs26m", "dmpll_ck", "dsi0_lntc", "dsi1_lntc", "lvdstx3", "lvdstx", "clkrtc_ext", "clkrtc_int", "csi0", "apll_div0", "apll_div1", "apll_div2", "apll_div3", "apll_div4", "apll_div5", "apll_div6", "apll_div7", "apll_div_pdn0", "apll_div_pdn1", "apll_div_pdn2", "apll_div_pdn3", "apll_div_pdn4", "apll_div_pdn5", "apll_div_pdn6", "apll_div_pdn7", "nfi2x_en", "nfiecc_en", "nfi1x_ck_en", "axi_sel", "mem_sel", "mm_sel", "pwm_sel", "vdec_sel", "venc_sel", "mfg_sel", "camtg_sel", "uart_sel", "spi_sel", "usb20_sel", "usb30_sel", "msdc50_0_h_sel", "msdc50_0_sel", "msdc30_1_sel", "msdc30_2_sel", "msdc30_3_sel", "audio_sel", "aud_intbus_sel", "pmicspi_sel", "dpilvds1_sel", "atb_sel", "nr_sel", "nfi2x_sel", "irda_sel", "cci400_sel", "aud_1_sel", "aud_2_sel", "mem_mfg_sel", "axi_mfg_sel", "scam_sel", "nfiecc_sel", "pe2_mac_p0_sel", "pe2_mac_p1_sel", "dpilvds_sel", "msdc50_3_h_sel", "hdcp_sel", "hdcp_24m_sel", "rtc_sel", "spinor_sel", "apll_sel", "apll2_sel", "a1sys_hp_sel", "a2sys_hp_sel", "asm_l_sel", "asm_m_sel", "asm_h_sel", "i2so1_sel", "i2so2_sel", "i2so3_sel", "tdmo0_sel", "tdmo1_sel", "i2si1_sel", "i2si2_sel", "i2si3_sel", "ether_125m_sel", "ether_50m_sel", "jpgdec_sel", "spislv_sel", "ether_sel", "cam2tg_sel", "di_sel", "tvd_sel", "i2c_sel", "pwm_infra_sel", "msdc0p_aes_sel", "cmsys_sel", "gcpu_sel", "aud_apll1_sel", "aud_apll2_sel", "apll1_ref_sel", "apll2_ref_sel", "audull_vtx_sel", /* mcucfg */ "mcu_mp0_sel", "mcu_mp2_sel", "mcu_bus_sel", /* bdpsys */ "bdp_bridge_b", "bdp_bridge_d", "bdp_larb_d", "bdp_vdi_pxl", "bdp_vdi_d", "bdp_vdi_b", "bdp_fmt_b", "bdp_27m", "bdp_27m_vdout", "bdp_27_74_74", "bdp_2fs", "bdp_2fs74_148", "bdp_b", "bdp_vdo_d", "bdp_vdo_2fs", "bdp_vdo_b", "bdp_di_pxl", "bdp_di_d", "bdp_di_b", "bdp_nr_agent", "bdp_nr_d", "bdp_nr_b", "bdp_bridge_rt_b", "bdp_bridge_rt_d", "bdp_larb_rt_d", "bdp_tvd_tdc", "bdp_tvd_clk_54", "bdp_tvd_cbus", /* infracfg */ "infra_dbgclk", "infra_gce", "infra_m4u", "infra_kp", "infra_ao_spi0", "infra_ao_spi1", "infra_ao_uart5", /* imgsys */ "img_smi_larb2", "img_scam_en", "img_cam_en", "img_cam_sv_en", "img_cam_sv1_en", "img_cam_sv2_en", /* jpgdecsys */ "jpgdec_jpgdec1", "jpgdec_jpgdec", /* mfgcfg */ "mfg_bg3d", /* mmsys */ "mm_smi_common", "mm_smi_larb0", "mm_cam_mdp", "mm_mdp_rdma0", "mm_mdp_rdma1", "mm_mdp_rsz0", "mm_mdp_rsz1", "mm_mdp_rsz2", "mm_mdp_tdshp0", "mm_mdp_tdshp1", "mm_mdp_crop", "mm_mdp_wdma", "mm_mdp_wrot0", "mm_mdp_wrot1", "mm_fake_eng", "mm_mutex_32k", "mm_disp_ovl0", "mm_disp_ovl1", "mm_disp_rdma0", "mm_disp_rdma1", "mm_disp_rdma2", "mm_disp_wdma0", "mm_disp_wdma1", "mm_disp_color0", "mm_disp_color1", "mm_disp_aal", "mm_disp_gamma", "mm_disp_ufoe", "mm_disp_split0", "mm_disp_od", "mm_pwm0_mm", "mm_pwm0_26m", "mm_pwm1_mm", "mm_pwm1_26m", "mm_dsi0_engine", "mm_dsi0_digital", "mm_dsi1_engine", "mm_dsi1_digital", "mm_dpi_pixel", "mm_dpi_engine", "mm_dpi1_pixel", "mm_dpi1_engine", "mm_lvds_pixel", "mm_lvds_cts", "mm_smi_larb4", "mm_smi_common1", "mm_smi_larb5", "mm_mdp_rdma2", "mm_mdp_tdshp2", "mm_disp_ovl2", "mm_disp_wdma2", "mm_disp_color2", "mm_disp_aal1", "mm_disp_od1", "mm_lvds1_pixel", "mm_lvds1_cts", "mm_smi_larb7", "mm_mdp_rdma3", "mm_mdp_wrot2", "mm_dsi2", "mm_dsi2_digital", "mm_dsi3", "mm_dsi3_digital", /* pericfg */ "per_nfi", "per_therm", "per_pwm0", "per_pwm1", "per_pwm2", "per_pwm3", "per_pwm4", "per_pwm5", "per_pwm6", "per_pwm7", "per_pwm", "per_ap_dma", "per_msdc30_0", "per_msdc30_1", "per_msdc30_2", "per_msdc30_3", "per_uart0", "per_uart1", "per_uart2", "per_uart3", "per_i2c0", "per_i2c1", "per_i2c2", "per_i2c3", "per_i2c4", "per_auxadc", "per_spi0", "per_spi", "per_i2c5", "per_spi2", "per_spi3", "per_spi5", "per_uart4", "per_sflash", "per_gmac", "per_pcie0", "per_pcie1", "per_gmac_pclk", "per_msdc50_0_en", "per_msdc30_1_en", "per_msdc30_2_en", "per_msdc30_3_en", "per_msdc50_0_h", "per_msdc50_3_h", "per_msdc30_0_q", "per_msdc30_3_q", /* vdecsys */ "vdec_cken", "vdec_larb1_cken", "vdec_imgrz_cken", /* vencsys */ "venc_smi", "venc_venc", "venc_smi_larb6", /* end */ NULL }; return clks; } /* * clkdbg pwr_status */ static const char * const *get_pwr_names(void) { static const char * const pwr_names[] = { [0] = "MD", [1] = "CONN", [2] = "DDRPHY0", [3] = "DISP", [4] = "MFG", [5] = "ISP", [6] = "INFRA", [7] = "VDEC", [8] = "MP0_CPUTOP", [9] = "MP0_CPU0", [10] = "MP0_CPU1", [11] = "MP0_CPU2", [12] = "MP0_CPU3", [13] = "", [14] = "MCUSYS", [15] = "MP1_CPUTOP", [16] = "MP1_CPU0", [17] = "MP1_CPU1", [18] = "", [19] = "USB2", [20] = "", [21] = "VENC", [22] = "MFG_SC1", [23] = "MFG_SC2", [24] = "AUDIO", [25] = "USB", [26] = "", [27] = "DDRPHY1", [28] = "DDRPHY2", [29] = "DDRPHY3", [30] = "MFG_SC3", [31] = "", }; return pwr_names; } /* * clkdbg dump_clks */ static void setup_provider_clk(struct provider_clk *pvdck) { static const struct { const char *pvdname; u32 pwr_mask; } pvd_pwr_mask[] = { {"mfgcfg", BIT(4)}, {"mmsys", BIT(3)}, {"imgsys", BIT(3) | BIT(5)}, {"bdpsys", BIT(3) | BIT(5)}, {"vdecsys", BIT(3) | BIT(7)}, {"vencsys", BIT(3) | BIT(21)}, {"jpgdecsys", BIT(3) | BIT(21)}, {"audsys", BIT(24)}, }; size_t i; const char *pvdname = pvdck->provider_name; if (pvdname == NULL) return; for (i = 0; i < ARRAY_SIZE(pvd_pwr_mask); i++) { if (strcmp(pvdname, pvd_pwr_mask[i].pvdname) == 0) { pvdck->pwr_mask = pvd_pwr_mask[i].pwr_mask; return; } } } /* * init functions */ static struct clkdbg_ops clkdbg_mt2712_ops = { .get_all_fmeter_clks = get_all_fmeter_clks, .prepare_fmeter = prepare_fmeter, .unprepare_fmeter = unprepare_fmeter, .fmeter_freq = fmeter_freq_op, .get_all_regnames = get_all_regnames, .get_all_clk_names = get_all_clk_names, .get_pwr_names = get_pwr_names, .setup_provider_clk = setup_provider_clk, }; static void __init init_custom_cmds(void) { static const struct cmd_fn cmds[] = { {} }; set_custom_cmds(cmds); } static int __init clkdbg_mt2712_init(void) { if (of_machine_is_compatible("mediatek,mt2712") == 0) return -ENODEV; init_regbase(); init_custom_cmds(); set_clkdbg_ops(&clkdbg_mt2712_ops); #if DUMP_INIT_STATE print_regs(); print_fmeter_all(); #endif /* DUMP_INIT_STATE */ return 0; } device_initcall(clkdbg_mt2712_init);