kernel_samsung_a34x-permissive/drivers/clk/mediatek/clkdbg-mt2712.c
2024-04-28 15:49:01 +02:00

1066 lines
26 KiB
C
Executable file

// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2019 MediaTek Inc.
* Author: Weiyi Lu <weiyi.lu@mediatek.com>
*/
#include <linux/clk-provider.h>
#include <linux/io.h>
#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 <linux/delay.h>
#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 &regs;
}
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);