diff options
author | Weiyi Lu <weiyi.lu@mediatek.com> | 2020-06-22 16:21:58 +0800 |
---|---|---|
committer | Hung-Te Lin <hungte@chromium.org> | 2020-10-09 15:33:00 +0000 |
commit | 26d16527152f6ed93f580c26fb5ead3bdb4117f5 (patch) | |
tree | 661a672d652f82dbd467cd40400c40f3ea7d87b9 /src/soc | |
parent | 30b854dccd1fce2d439fb70ffa15064130cad73c (diff) |
soc/mediatek: Add function to measure clock frequency of MT8192
Implement mt_fmeter_get_freq_khz() in MT8192 to measure frequency of
some pre-defined clocks by frequency meter.
Signed-off-by: Weiyi Lu <weiyi.lu@mediatek.com>
Change-Id: I75df0b040ed7ea73d25724a3c80040f4e731118f
Reviewed-on: https://review.coreboot.org/c/coreboot/+/45402
Reviewed-by: Hung-Te Lin <hungte@chromium.org>
Reviewed-by: Yu-Ping Wu <yupingso@google.com>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Diffstat (limited to 'src/soc')
-rw-r--r-- | src/soc/mediatek/common/include/soc/pll_common.h | 6 | ||||
-rw-r--r-- | src/soc/mediatek/mt8192/include/soc/pll.h | 7 | ||||
-rw-r--r-- | src/soc/mediatek/mt8192/pll.c | 62 |
3 files changed, 75 insertions, 0 deletions
diff --git a/src/soc/mediatek/common/include/soc/pll_common.h b/src/soc/mediatek/common/include/soc/pll_common.h index 0f8732fb6e..d9ba2308e9 100644 --- a/src/soc/mediatek/common/include/soc/pll_common.h +++ b/src/soc/mediatek/common/include/soc/pll_common.h @@ -60,4 +60,10 @@ int pll_set_rate(const struct pll *pll, u32 rate); void mt_pll_init(void); void mt_pll_raise_little_cpu_freq(u32 freq); +enum fmeter_type { + FMETER_ABIST = 0, + FMETER_CKGEN, +}; +u32 mt_fmeter_get_freq_khz(enum fmeter_type type, u32 id); + #endif diff --git a/src/soc/mediatek/mt8192/include/soc/pll.h b/src/soc/mediatek/mt8192/include/soc/pll.h index 43c2528994..d5a9cf9a3e 100644 --- a/src/soc/mediatek/mt8192/include/soc/pll.h +++ b/src/soc/mediatek/mt8192/include/soc/pll.h @@ -295,4 +295,11 @@ enum { DEFINE_BITFIELD(PLLGP1_LVRREF, 18, 17) DEFINE_BITFIELD(PLLGP2_LVRREF, 10, 9) +DEFINE_BITFIELD(CLK_DBG_CFG_ABIST_CK_SEL, 21, 16) +DEFINE_BITFIELD(CLK_DBG_CFG_CKGEN_CK_SEL, 13, 8) +DEFINE_BITFIELD(CLK_DBG_CFG_METER_CK_SEL, 1, 0) +DEFINE_BITFIELD(CLK_MISC_CFG_0_METER_DIV, 31, 24) +DEFINE_BITFIELD(CLK26CALI_0_TRIGGER, 4, 4) +DEFINE_BITFIELD(CLK26CALI_1_LOAD_CNT, 25, 16) + #endif /* SOC_MEDIATEK_MT8192_PLL_H */ diff --git a/src/soc/mediatek/mt8192/pll.c b/src/soc/mediatek/mt8192/pll.c index e8849df0b0..11750d20a3 100644 --- a/src/soc/mediatek/mt8192/pll.c +++ b/src/soc/mediatek/mt8192/pll.c @@ -1,8 +1,10 @@ /* SPDX-License-Identifier: GPL-2.0-only */ +#include <console/console.h> #include <device/mmio.h> #include <delay.h> #include <stddef.h> +#include <timer.h> #include <soc/addressmap.h> #include <soc/infracfg.h> @@ -459,3 +461,63 @@ void mt_pll_raise_little_cpu_freq(u32 freq) /* disable [4] intermediate clock armpll_divider_pll1_ck */ clrbits32(&mtk_topckgen->clk_misc_cfg_0, 1 << 4); } + +u32 mt_fmeter_get_freq_khz(enum fmeter_type type, u32 id) +{ + u32 output, count, clk_dbg_cfg, clk_misc_cfg_0; + + /* backup */ + clk_dbg_cfg = read32(&mtk_topckgen->clk_dbg_cfg); + clk_misc_cfg_0 = read32(&mtk_topckgen->clk_misc_cfg_0); + + /* set up frequency meter */ + if (type == FMETER_ABIST) { + SET32_BITFIELDS(&mtk_topckgen->clk_dbg_cfg, + CLK_DBG_CFG_ABIST_CK_SEL, id, + CLK_DBG_CFG_CKGEN_CK_SEL, 0, + CLK_DBG_CFG_METER_CK_SEL, 0); + SET32_BITFIELDS(&mtk_topckgen->clk_misc_cfg_0, + CLK_MISC_CFG_0_METER_DIV, 1); + } else if (type == FMETER_CKGEN) { + SET32_BITFIELDS(&mtk_topckgen->clk_dbg_cfg, + CLK_DBG_CFG_ABIST_CK_SEL, 0, + CLK_DBG_CFG_CKGEN_CK_SEL, id, + CLK_DBG_CFG_METER_CK_SEL, 1); + SET32_BITFIELDS(&mtk_topckgen->clk_misc_cfg_0, + CLK_MISC_CFG_0_METER_DIV, 0); + } else { + die("unsupport fmeter type\n"); + } + + /* enable frequency meter */ + write32(&mtk_topckgen->clk26cali_0, 0x1000); + + /* set load count = 1024-1 */ + SET32_BITFIELDS(&mtk_topckgen->clk26cali_1, CLK26CALI_1_LOAD_CNT, 0x3ff); + + /* trigger frequency meter */ + SET32_BITFIELDS(&mtk_topckgen->clk26cali_0, CLK26CALI_0_TRIGGER, 1); + + /* wait frequency meter until finished */ + if (wait_us(200, !READ32_BITFIELD(&mtk_topckgen->clk26cali_0, CLK26CALI_0_TRIGGER))) { + count = read32(&mtk_topckgen->clk26cali_1) & 0xffff; + output = (count * 26000) / 1024; /* KHz */ + } else { + printk(BIOS_WARNING, "fmeter timeout\n"); + output = 0; + } + + /* disable frequency meter */ + write32(&mtk_topckgen->clk26cali_0, 0x0000); + + /* restore */ + write32(&mtk_topckgen->clk_dbg_cfg, clk_dbg_cfg); + write32(&mtk_topckgen->clk_misc_cfg_0, clk_misc_cfg_0); + + if (type == FMETER_ABIST) + return output * 2; + else if (type == FMETER_CKGEN) + return output; + + return 0; +} |