#include <asm/arch/imx-regs.h>
#include <asm/arch/sys_proto.h>
#include <asm/io.h>
-#include <clk.h>
-#include <clk-uclass.h>
-#include <dt-bindings/clock/imx8mm-clock.h>
#include <div64.h>
#include <errno.h>
void enable_ocotp_clk(unsigned char enable)
{
- struct clk *clkp;
- int ret;
-
- ret = clk_get_by_id(IMX8MM_CLK_OCOTP_ROOT, &clkp);
- if (ret) {
- printf("%s: err: %d\n", __func__, ret);
- return;
- }
-
- enable ? clk_enable(clkp) : clk_disable(clkp);
+ clock_enable(CCGR_OCOTP, !!enable);
}
int enable_i2c_clk(unsigned char enable, unsigned i2c_num)
{
- struct clk *clkp;
- int ret;
+ /* 0 - 3 is valid i2c num */
+ if (i2c_num > 3)
+ return -EINVAL;
- ret = clk_get_by_id(IMX8MM_CLK_I2C1_ROOT + i2c_num, &clkp);
- if (ret) {
- printf("%s: err: %d\n", __func__, ret);
- return ret;
- }
+ clock_enable(CCGR_I2C1 + i2c_num, !!enable);
- return enable ? clk_enable(clkp) : clk_disable(clkp);
+ return 0;
}
#ifdef CONFIG_SPL_BUILD
return 24000000U;
}
+u32 decode_intpll(enum clk_root_src intpll)
+{
+ u32 pll_gnrl_ctl, pll_div_ctl, pll_clke_mask;
+ u32 main_div, pre_div, post_div, div;
+ u64 freq;
+
+ switch (intpll) {
+ case ARM_PLL_CLK:
+ pll_gnrl_ctl = readl(&ana_pll->arm_pll_gnrl_ctl);
+ pll_div_ctl = readl(&ana_pll->arm_pll_div_ctl);
+ break;
+ case GPU_PLL_CLK:
+ pll_gnrl_ctl = readl(&ana_pll->gpu_pll_gnrl_ctl);
+ pll_div_ctl = readl(&ana_pll->gpu_pll_div_ctl);
+ break;
+ case VPU_PLL_CLK:
+ pll_gnrl_ctl = readl(&ana_pll->vpu_pll_gnrl_ctl);
+ pll_div_ctl = readl(&ana_pll->vpu_pll_div_ctl);
+ break;
+ case SYSTEM_PLL1_800M_CLK:
+ case SYSTEM_PLL1_400M_CLK:
+ case SYSTEM_PLL1_266M_CLK:
+ case SYSTEM_PLL1_200M_CLK:
+ case SYSTEM_PLL1_160M_CLK:
+ case SYSTEM_PLL1_133M_CLK:
+ case SYSTEM_PLL1_100M_CLK:
+ case SYSTEM_PLL1_80M_CLK:
+ case SYSTEM_PLL1_40M_CLK:
+ pll_gnrl_ctl = readl(&ana_pll->sys_pll1_gnrl_ctl);
+ pll_div_ctl = readl(&ana_pll->sys_pll1_div_ctl);
+ break;
+ case SYSTEM_PLL2_1000M_CLK:
+ case SYSTEM_PLL2_500M_CLK:
+ case SYSTEM_PLL2_333M_CLK:
+ case SYSTEM_PLL2_250M_CLK:
+ case SYSTEM_PLL2_200M_CLK:
+ case SYSTEM_PLL2_166M_CLK:
+ case SYSTEM_PLL2_125M_CLK:
+ case SYSTEM_PLL2_100M_CLK:
+ case SYSTEM_PLL2_50M_CLK:
+ pll_gnrl_ctl = readl(&ana_pll->sys_pll2_gnrl_ctl);
+ pll_div_ctl = readl(&ana_pll->sys_pll2_div_ctl);
+ break;
+ case SYSTEM_PLL3_CLK:
+ pll_gnrl_ctl = readl(&ana_pll->sys_pll3_gnrl_ctl);
+ pll_div_ctl = readl(&ana_pll->sys_pll3_div_ctl);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* Only support SYS_XTAL 24M, PAD_CLK not take into consideration */
+ if ((pll_gnrl_ctl & INTPLL_REF_CLK_SEL_MASK) != 0)
+ return 0;
+
+ if ((pll_gnrl_ctl & INTPLL_RST_MASK) == 0)
+ return 0;
+
+ /*
+ * When BYPASS is equal to 1, PLL enters the bypass mode
+ * regardless of the values of RESETB
+ */
+ if (pll_gnrl_ctl & INTPLL_BYPASS_MASK)
+ return 24000000u;
+
+ if (!(pll_gnrl_ctl & INTPLL_LOCK_MASK)) {
+ puts("pll not locked\n");
+ return 0;
+ }
+
+ switch (intpll) {
+ case ARM_PLL_CLK:
+ case GPU_PLL_CLK:
+ case VPU_PLL_CLK:
+ case SYSTEM_PLL3_CLK:
+ case SYSTEM_PLL1_800M_CLK:
+ case SYSTEM_PLL2_1000M_CLK:
+ pll_clke_mask = INTPLL_CLKE_MASK;
+ div = 1;
+ break;
+
+ case SYSTEM_PLL1_400M_CLK:
+ case SYSTEM_PLL2_500M_CLK:
+ pll_clke_mask = INTPLL_DIV2_CLKE_MASK;
+ div = 2;
+ break;
+
+ case SYSTEM_PLL1_266M_CLK:
+ case SYSTEM_PLL2_333M_CLK:
+ pll_clke_mask = INTPLL_DIV3_CLKE_MASK;
+ div = 3;
+ break;
+
+ case SYSTEM_PLL1_200M_CLK:
+ case SYSTEM_PLL2_250M_CLK:
+ pll_clke_mask = INTPLL_DIV4_CLKE_MASK;
+ div = 4;
+ break;
+
+ case SYSTEM_PLL1_160M_CLK:
+ case SYSTEM_PLL2_200M_CLK:
+ pll_clke_mask = INTPLL_DIV5_CLKE_MASK;
+ div = 5;
+ break;
+
+ case SYSTEM_PLL1_133M_CLK:
+ case SYSTEM_PLL2_166M_CLK:
+ pll_clke_mask = INTPLL_DIV6_CLKE_MASK;
+ div = 6;
+ break;
+
+ case SYSTEM_PLL1_100M_CLK:
+ case SYSTEM_PLL2_125M_CLK:
+ pll_clke_mask = INTPLL_DIV8_CLKE_MASK;
+ div = 8;
+ break;
+
+ case SYSTEM_PLL1_80M_CLK:
+ case SYSTEM_PLL2_100M_CLK:
+ pll_clke_mask = INTPLL_DIV10_CLKE_MASK;
+ div = 10;
+ break;
+
+ case SYSTEM_PLL1_40M_CLK:
+ case SYSTEM_PLL2_50M_CLK:
+ pll_clke_mask = INTPLL_DIV20_CLKE_MASK;
+ div = 20;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if ((pll_gnrl_ctl & pll_clke_mask) == 0)
+ return 0;
+
+ main_div = (pll_div_ctl & INTPLL_MAIN_DIV_MASK) >>
+ INTPLL_MAIN_DIV_SHIFT;
+ pre_div = (pll_div_ctl & INTPLL_PRE_DIV_MASK) >>
+ INTPLL_PRE_DIV_SHIFT;
+ post_div = (pll_div_ctl & INTPLL_POST_DIV_MASK) >>
+ INTPLL_POST_DIV_SHIFT;
+
+ /* FFVCO = (m * FFIN) / p, FFOUT = (m * FFIN) / (p * 2^s) */
+ freq = 24000000ULL * main_div;
+ return lldiv(freq, pre_div * (1 << post_div) * div);
+}
+
+u32 decode_fracpll(enum clk_root_src frac_pll)
+{
+ u32 pll_gnrl_ctl, pll_fdiv_ctl0, pll_fdiv_ctl1;
+ u32 main_div, pre_div, post_div, k;
+
+ switch (frac_pll) {
+ case DRAM_PLL1_CLK:
+ pll_gnrl_ctl = readl(&ana_pll->dram_pll_gnrl_ctl);
+ pll_fdiv_ctl0 = readl(&ana_pll->dram_pll_fdiv_ctl0);
+ pll_fdiv_ctl1 = readl(&ana_pll->dram_pll_fdiv_ctl1);
+ break;
+ case AUDIO_PLL1_CLK:
+ pll_gnrl_ctl = readl(&ana_pll->audio_pll1_gnrl_ctl);
+ pll_fdiv_ctl0 = readl(&ana_pll->audio_pll1_fdiv_ctl0);
+ pll_fdiv_ctl1 = readl(&ana_pll->audio_pll1_fdiv_ctl1);
+ break;
+ case AUDIO_PLL2_CLK:
+ pll_gnrl_ctl = readl(&ana_pll->audio_pll2_gnrl_ctl);
+ pll_fdiv_ctl0 = readl(&ana_pll->audio_pll2_fdiv_ctl0);
+ pll_fdiv_ctl1 = readl(&ana_pll->audio_pll2_fdiv_ctl1);
+ break;
+ case VIDEO_PLL_CLK:
+ pll_gnrl_ctl = readl(&ana_pll->video_pll1_gnrl_ctl);
+ pll_fdiv_ctl0 = readl(&ana_pll->video_pll1_fdiv_ctl0);
+ pll_fdiv_ctl1 = readl(&ana_pll->video_pll1_fdiv_ctl1);
+ break;
+ default:
+ printf("Not supported\n");
+ return 0;
+ }
+
+ /* Only support SYS_XTAL 24M, PAD_CLK not take into consideration */
+ if ((pll_gnrl_ctl & INTPLL_REF_CLK_SEL_MASK) != 0)
+ return 0;
+
+ if ((pll_gnrl_ctl & INTPLL_RST_MASK) == 0)
+ return 0;
+ /*
+ * When BYPASS is equal to 1, PLL enters the bypass mode
+ * regardless of the values of RESETB
+ */
+ if (pll_gnrl_ctl & INTPLL_BYPASS_MASK)
+ return 24000000u;
+
+ if (!(pll_gnrl_ctl & INTPLL_LOCK_MASK)) {
+ puts("pll not locked\n");
+ return 0;
+ }
+
+ if (!(pll_gnrl_ctl & INTPLL_CLKE_MASK))
+ return 0;
+
+ main_div = (pll_fdiv_ctl0 & INTPLL_MAIN_DIV_MASK) >>
+ INTPLL_MAIN_DIV_SHIFT;
+ pre_div = (pll_fdiv_ctl0 & INTPLL_PRE_DIV_MASK) >>
+ INTPLL_PRE_DIV_SHIFT;
+ post_div = (pll_fdiv_ctl0 & INTPLL_POST_DIV_MASK) >>
+ INTPLL_POST_DIV_SHIFT;
+
+ k = pll_fdiv_ctl1 & GENMASK(15, 0);
+
+ return lldiv((main_div * 65536 + k) * 24000000ULL,
+ 65536 * pre_div * (1 << post_div));
+}
+
+u32 get_root_src_clk(enum clk_root_src root_src)
+{
+ switch (root_src) {
+ case OSC_24M_CLK:
+ return 24000000u;
+ case OSC_HDMI_CLK:
+ return 26000000u;
+ case OSC_32K_CLK:
+ return 32000u;
+ case ARM_PLL_CLK:
+ case GPU_PLL_CLK:
+ case VPU_PLL_CLK:
+ case SYSTEM_PLL1_800M_CLK:
+ case SYSTEM_PLL1_400M_CLK:
+ case SYSTEM_PLL1_266M_CLK:
+ case SYSTEM_PLL1_200M_CLK:
+ case SYSTEM_PLL1_160M_CLK:
+ case SYSTEM_PLL1_133M_CLK:
+ case SYSTEM_PLL1_100M_CLK:
+ case SYSTEM_PLL1_80M_CLK:
+ case SYSTEM_PLL1_40M_CLK:
+ case SYSTEM_PLL2_1000M_CLK:
+ case SYSTEM_PLL2_500M_CLK:
+ case SYSTEM_PLL2_333M_CLK:
+ case SYSTEM_PLL2_250M_CLK:
+ case SYSTEM_PLL2_200M_CLK:
+ case SYSTEM_PLL2_166M_CLK:
+ case SYSTEM_PLL2_125M_CLK:
+ case SYSTEM_PLL2_100M_CLK:
+ case SYSTEM_PLL2_50M_CLK:
+ case SYSTEM_PLL3_CLK:
+ return decode_intpll(root_src);
+ case DRAM_PLL1_CLK:
+ case AUDIO_PLL1_CLK:
+ case AUDIO_PLL2_CLK:
+ case VIDEO_PLL_CLK:
+ return decode_fracpll(root_src);
+ default:
+ return 0;
+ }
+
+ return 0;
+}
+
+u32 get_root_clk(enum clk_root_index clock_id)
+{
+ enum clk_root_src root_src;
+ u32 post_podf, pre_podf, root_src_clk;
+
+ if (clock_root_enabled(clock_id) <= 0)
+ return 0;
+
+ if (clock_get_prediv(clock_id, &pre_podf) < 0)
+ return 0;
+
+ if (clock_get_postdiv(clock_id, &post_podf) < 0)
+ return 0;
+
+ if (clock_get_src(clock_id, &root_src) < 0)
+ return 0;
+
+ root_src_clk = get_root_src_clk(root_src);
+
+ return root_src_clk / (post_podf + 1) / (pre_podf + 1);
+}
+
u32 mxc_get_clock(enum mxc_clock clk)
{
- struct clk *clkp;
- int ret;
+ u32 val;
switch (clk) {
- case MXC_IPG_CLK:
- ret = clk_get_by_id(IMX8MM_CLK_IPG_ROOT, &clkp);
- if (ret)
- return 0;
- return clk_get_rate(clkp);
case MXC_ARM_CLK:
- ret = clk_get_by_id(IMX8MM_CLK_A53_DIV, &clkp);
- if (ret)
- return 0;
- return clk_get_rate(clkp);
+ return get_root_clk(ARM_A53_CLK_ROOT);
+ case MXC_IPG_CLK:
+ clock_get_target_val(IPG_CLK_ROOT, &val);
+ val = val & 0x3;
+ return get_root_clk(AHB_CLK_ROOT) / 2 / (val + 1);
+ case MXC_CSPI_CLK:
+ return get_root_clk(ECSPI1_CLK_ROOT);
+ case MXC_ESDHC_CLK:
+ return get_root_clk(USDHC1_CLK_ROOT);
+ case MXC_ESDHC2_CLK:
+ return get_root_clk(USDHC2_CLK_ROOT);
+ case MXC_ESDHC3_CLK:
+ return get_root_clk(USDHC3_CLK_ROOT);
+ case MXC_I2C_CLK:
+ return get_root_clk(I2C1_CLK_ROOT);
+ case MXC_UART_CLK:
+ return get_root_clk(UART1_CLK_ROOT);
+ case MXC_QSPI_CLK:
+ return get_root_clk(QSPI_CLK_ROOT);
default:
- printf("%s: %d not supported\n", __func__, clk);
+ printf("Unsupported mxc_clock %d\n", clk);
+ break;
}
return 0;