1*83d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+ 252f69f81SVladimir Zapolskiy /* 352f69f81SVladimir Zapolskiy * Copyright (C) 2011 by Vladimir Zapolskiy <vz@mleia.com> 452f69f81SVladimir Zapolskiy */ 552f69f81SVladimir Zapolskiy 652f69f81SVladimir Zapolskiy #include <common.h> 752f69f81SVladimir Zapolskiy #include <div64.h> 852f69f81SVladimir Zapolskiy #include <asm/arch/cpu.h> 952f69f81SVladimir Zapolskiy #include <asm/arch/clk.h> 1052f69f81SVladimir Zapolskiy #include <asm/io.h> 1152f69f81SVladimir Zapolskiy 1252f69f81SVladimir Zapolskiy static struct clk_pm_regs *clk = (struct clk_pm_regs *)CLK_PM_BASE; 1352f69f81SVladimir Zapolskiy get_sys_clk_rate(void)1452f69f81SVladimir Zapolskiyunsigned int get_sys_clk_rate(void) 1552f69f81SVladimir Zapolskiy { 1652f69f81SVladimir Zapolskiy if (readl(&clk->sysclk_ctrl) & CLK_SYSCLK_PLL397) 1752f69f81SVladimir Zapolskiy return RTC_CLK_FREQUENCY * 397; 1852f69f81SVladimir Zapolskiy else 1952f69f81SVladimir Zapolskiy return OSC_CLK_FREQUENCY; 2052f69f81SVladimir Zapolskiy } 2152f69f81SVladimir Zapolskiy get_hclk_pll_rate(void)2252f69f81SVladimir Zapolskiyunsigned int get_hclk_pll_rate(void) 2352f69f81SVladimir Zapolskiy { 2452f69f81SVladimir Zapolskiy unsigned long long fin, fref, fcco, fout; 2552f69f81SVladimir Zapolskiy u32 val, m_div, n_div, p_div; 2652f69f81SVladimir Zapolskiy 2752f69f81SVladimir Zapolskiy /* 2852f69f81SVladimir Zapolskiy * Valid frequency ranges: 2952f69f81SVladimir Zapolskiy * 1 * 10^6 <= Fin <= 20 * 10^6 3052f69f81SVladimir Zapolskiy * 1 * 10^6 <= Fref <= 27 * 10^6 3152f69f81SVladimir Zapolskiy * 156 * 10^6 <= Fcco <= 320 * 10^6 3252f69f81SVladimir Zapolskiy */ 3352f69f81SVladimir Zapolskiy 3452f69f81SVladimir Zapolskiy fref = fin = get_sys_clk_rate(); 3552f69f81SVladimir Zapolskiy if (fin > 20000000ULL || fin < 1000000ULL) 3652f69f81SVladimir Zapolskiy return 0; 3752f69f81SVladimir Zapolskiy 3852f69f81SVladimir Zapolskiy val = readl(&clk->hclkpll_ctrl); 3952f69f81SVladimir Zapolskiy m_div = ((val & CLK_HCLK_PLL_FEEDBACK_DIV_MASK) >> 1) + 1; 4052f69f81SVladimir Zapolskiy n_div = ((val & CLK_HCLK_PLL_PREDIV_MASK) >> 9) + 1; 4152f69f81SVladimir Zapolskiy if (val & CLK_HCLK_PLL_DIRECT) 4252f69f81SVladimir Zapolskiy p_div = 0; 4352f69f81SVladimir Zapolskiy else 4452f69f81SVladimir Zapolskiy p_div = ((val & CLK_HCLK_PLL_POSTDIV_MASK) >> 11) + 1; 4552f69f81SVladimir Zapolskiy p_div = 1 << p_div; 4652f69f81SVladimir Zapolskiy 4752f69f81SVladimir Zapolskiy if (val & CLK_HCLK_PLL_BYPASS) { 4852f69f81SVladimir Zapolskiy do_div(fin, p_div); 4952f69f81SVladimir Zapolskiy return fin; 5052f69f81SVladimir Zapolskiy } 5152f69f81SVladimir Zapolskiy 5252f69f81SVladimir Zapolskiy do_div(fref, n_div); 5352f69f81SVladimir Zapolskiy if (fref > 27000000ULL || fref < 1000000ULL) 5452f69f81SVladimir Zapolskiy return 0; 5552f69f81SVladimir Zapolskiy 564c902345SVladimir Zapolskiy fcco = fref * m_div; 574c902345SVladimir Zapolskiy fout = fcco; 584c902345SVladimir Zapolskiy if (val & CLK_HCLK_PLL_FEEDBACK) 594c902345SVladimir Zapolskiy fcco *= p_div; 604c902345SVladimir Zapolskiy else 6152f69f81SVladimir Zapolskiy do_div(fout, p_div); 6252f69f81SVladimir Zapolskiy 6352f69f81SVladimir Zapolskiy if (fcco > 320000000ULL || fcco < 156000000ULL) 6452f69f81SVladimir Zapolskiy return 0; 6552f69f81SVladimir Zapolskiy 6652f69f81SVladimir Zapolskiy return fout; 6752f69f81SVladimir Zapolskiy } 6852f69f81SVladimir Zapolskiy get_hclk_clk_div(void)6952f69f81SVladimir Zapolskiyunsigned int get_hclk_clk_div(void) 7052f69f81SVladimir Zapolskiy { 7152f69f81SVladimir Zapolskiy u32 val; 7252f69f81SVladimir Zapolskiy 7352f69f81SVladimir Zapolskiy val = readl(&clk->hclkdiv_ctrl) & CLK_HCLK_ARM_PLL_DIV_MASK; 7452f69f81SVladimir Zapolskiy 7552f69f81SVladimir Zapolskiy return 1 << val; 7652f69f81SVladimir Zapolskiy } 7752f69f81SVladimir Zapolskiy get_hclk_clk_rate(void)7852f69f81SVladimir Zapolskiyunsigned int get_hclk_clk_rate(void) 7952f69f81SVladimir Zapolskiy { 8052f69f81SVladimir Zapolskiy return get_hclk_pll_rate() / get_hclk_clk_div(); 8152f69f81SVladimir Zapolskiy } 8252f69f81SVladimir Zapolskiy get_periph_clk_div(void)8352f69f81SVladimir Zapolskiyunsigned int get_periph_clk_div(void) 8452f69f81SVladimir Zapolskiy { 8552f69f81SVladimir Zapolskiy u32 val; 8652f69f81SVladimir Zapolskiy 8752f69f81SVladimir Zapolskiy val = readl(&clk->hclkdiv_ctrl) & CLK_HCLK_PERIPH_DIV_MASK; 8852f69f81SVladimir Zapolskiy 8952f69f81SVladimir Zapolskiy return (val >> 2) + 1; 9052f69f81SVladimir Zapolskiy } 9152f69f81SVladimir Zapolskiy get_periph_clk_rate(void)9252f69f81SVladimir Zapolskiyunsigned int get_periph_clk_rate(void) 9352f69f81SVladimir Zapolskiy { 9452f69f81SVladimir Zapolskiy if (!(readl(&clk->pwr_ctrl) & CLK_PWR_NORMAL_RUN)) 9552f69f81SVladimir Zapolskiy return get_sys_clk_rate(); 9652f69f81SVladimir Zapolskiy 9752f69f81SVladimir Zapolskiy return get_hclk_pll_rate() / get_periph_clk_div(); 9852f69f81SVladimir Zapolskiy } 9952f69f81SVladimir Zapolskiy get_sdram_clk_rate(void)100412ae53aSAlbert ARIBAUD \(3ADEV\)unsigned int get_sdram_clk_rate(void) 101412ae53aSAlbert ARIBAUD \(3ADEV\) { 102412ae53aSAlbert ARIBAUD \(3ADEV\) unsigned int src_clk; 103412ae53aSAlbert ARIBAUD \(3ADEV\) 104412ae53aSAlbert ARIBAUD \(3ADEV\) if (!(readl(&clk->pwr_ctrl) & CLK_PWR_NORMAL_RUN)) 105412ae53aSAlbert ARIBAUD \(3ADEV\) return get_sys_clk_rate(); 106412ae53aSAlbert ARIBAUD \(3ADEV\) 107412ae53aSAlbert ARIBAUD \(3ADEV\) src_clk = get_hclk_pll_rate(); 108412ae53aSAlbert ARIBAUD \(3ADEV\) 109412ae53aSAlbert ARIBAUD \(3ADEV\) if (readl(&clk->sdramclk_ctrl) & CLK_SDRAM_DDR_SEL) { 110412ae53aSAlbert ARIBAUD \(3ADEV\) /* using DDR */ 111412ae53aSAlbert ARIBAUD \(3ADEV\) switch (readl(&clk->hclkdiv_ctrl) & CLK_HCLK_DDRAM_MASK) { 112412ae53aSAlbert ARIBAUD \(3ADEV\) case CLK_HCLK_DDRAM_HALF: 113412ae53aSAlbert ARIBAUD \(3ADEV\) return src_clk/2; 114412ae53aSAlbert ARIBAUD \(3ADEV\) case CLK_HCLK_DDRAM_NOMINAL: 115412ae53aSAlbert ARIBAUD \(3ADEV\) return src_clk; 116412ae53aSAlbert ARIBAUD \(3ADEV\) default: 117412ae53aSAlbert ARIBAUD \(3ADEV\) return 0; 118412ae53aSAlbert ARIBAUD \(3ADEV\) } 119412ae53aSAlbert ARIBAUD \(3ADEV\) } else { 120412ae53aSAlbert ARIBAUD \(3ADEV\) /* using SDR */ 121412ae53aSAlbert ARIBAUD \(3ADEV\) switch (readl(&clk->hclkdiv_ctrl) & CLK_HCLK_ARM_PLL_DIV_MASK) { 122412ae53aSAlbert ARIBAUD \(3ADEV\) case CLK_HCLK_ARM_PLL_DIV_4: 123412ae53aSAlbert ARIBAUD \(3ADEV\) return src_clk/4; 124412ae53aSAlbert ARIBAUD \(3ADEV\) case CLK_HCLK_ARM_PLL_DIV_2: 125412ae53aSAlbert ARIBAUD \(3ADEV\) return src_clk/2; 126412ae53aSAlbert ARIBAUD \(3ADEV\) case CLK_HCLK_ARM_PLL_DIV_1: 127412ae53aSAlbert ARIBAUD \(3ADEV\) return src_clk; 128412ae53aSAlbert ARIBAUD \(3ADEV\) default: 129412ae53aSAlbert ARIBAUD \(3ADEV\) return 0; 130412ae53aSAlbert ARIBAUD \(3ADEV\) } 131412ae53aSAlbert ARIBAUD \(3ADEV\) } 132412ae53aSAlbert ARIBAUD \(3ADEV\) } 133412ae53aSAlbert ARIBAUD \(3ADEV\) get_serial_clock(void)13452f69f81SVladimir Zapolskiyint get_serial_clock(void) 13552f69f81SVladimir Zapolskiy { 13652f69f81SVladimir Zapolskiy return get_periph_clk_rate(); 13752f69f81SVladimir Zapolskiy } 138