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