1ee7bb5beSWills Wang /* 2ee7bb5beSWills Wang * Copyright (C) 2015-2016 Wills Wang <wills.wang@live.com> 3ee7bb5beSWills Wang * 4ee7bb5beSWills Wang * SPDX-License-Identifier: GPL-2.0+ 5ee7bb5beSWills Wang */ 6ee7bb5beSWills Wang 7ee7bb5beSWills Wang #include <common.h> 8ee7bb5beSWills Wang #include <asm/io.h> 9ee7bb5beSWills Wang #include <asm/addrspace.h> 10ee7bb5beSWills Wang #include <asm/types.h> 11ee7bb5beSWills Wang #include <mach/ar71xx_regs.h> 12*37523917SWills Wang #include <mach/ath79.h> 13ee7bb5beSWills Wang 14ee7bb5beSWills Wang DECLARE_GLOBAL_DATA_PTR; 15ee7bb5beSWills Wang ar933x_get_xtal(void)16ee7bb5beSWills Wangstatic u32 ar933x_get_xtal(void) 17ee7bb5beSWills Wang { 18ee7bb5beSWills Wang u32 val; 19ee7bb5beSWills Wang 20*37523917SWills Wang val = ath79_get_bootstrap(); 21ee7bb5beSWills Wang if (val & AR933X_BOOTSTRAP_REF_CLK_40) 22ee7bb5beSWills Wang return 40000000; 23ee7bb5beSWills Wang else 24ee7bb5beSWills Wang return 25000000; 25ee7bb5beSWills Wang } 26ee7bb5beSWills Wang get_serial_clock(void)27ee7bb5beSWills Wangint get_serial_clock(void) 28ee7bb5beSWills Wang { 29ee7bb5beSWills Wang return ar933x_get_xtal(); 30ee7bb5beSWills Wang } 31ee7bb5beSWills Wang get_clocks(void)32ee7bb5beSWills Wangint get_clocks(void) 33ee7bb5beSWills Wang { 34ee7bb5beSWills Wang void __iomem *regs; 35ee7bb5beSWills Wang u32 val, xtal, pll, div; 36ee7bb5beSWills Wang 37ee7bb5beSWills Wang regs = map_physmem(AR71XX_PLL_BASE, AR71XX_PLL_SIZE, 38ee7bb5beSWills Wang MAP_NOCACHE); 39ee7bb5beSWills Wang xtal = ar933x_get_xtal(); 40ee7bb5beSWills Wang val = readl(regs + AR933X_PLL_CPU_CONFIG_REG); 41ee7bb5beSWills Wang 42ee7bb5beSWills Wang /* VCOOUT = XTAL * DIV_INT */ 43ee7bb5beSWills Wang div = (val >> AR933X_PLL_CPU_CONFIG_REFDIV_SHIFT) 44ee7bb5beSWills Wang & AR933X_PLL_CPU_CONFIG_REFDIV_MASK; 45ee7bb5beSWills Wang pll = xtal / div; 46ee7bb5beSWills Wang 47ee7bb5beSWills Wang /* PLLOUT = VCOOUT * (1/2^OUTDIV) */ 48ee7bb5beSWills Wang div = (val >> AR933X_PLL_CPU_CONFIG_NINT_SHIFT) 49ee7bb5beSWills Wang & AR933X_PLL_CPU_CONFIG_NINT_MASK; 50ee7bb5beSWills Wang pll *= div; 51ee7bb5beSWills Wang div = (val >> AR933X_PLL_CPU_CONFIG_OUTDIV_SHIFT) 52ee7bb5beSWills Wang & AR933X_PLL_CPU_CONFIG_OUTDIV_MASK; 53ee7bb5beSWills Wang if (!div) 54ee7bb5beSWills Wang div = 1; 55ee7bb5beSWills Wang pll >>= div; 56ee7bb5beSWills Wang 57ee7bb5beSWills Wang val = readl(regs + AR933X_PLL_CLK_CTRL_REG); 58ee7bb5beSWills Wang 59ee7bb5beSWills Wang /* CPU_CLK = PLLOUT / CPU_POST_DIV */ 60ee7bb5beSWills Wang div = ((val >> AR933X_PLL_CLK_CTRL_CPU_POST_DIV_SHIFT) 61ee7bb5beSWills Wang & AR933X_PLL_CLK_CTRL_CPU_POST_DIV_MASK) + 1; 62ee7bb5beSWills Wang gd->cpu_clk = pll / div; 63ee7bb5beSWills Wang 64ee7bb5beSWills Wang /* DDR_CLK = PLLOUT / DDR_POST_DIV */ 65ee7bb5beSWills Wang div = ((val >> AR933X_PLL_CLK_CTRL_DDR_POST_DIV_SHIFT) 66ee7bb5beSWills Wang & AR933X_PLL_CLK_CTRL_DDR_POST_DIV_MASK) + 1; 67ee7bb5beSWills Wang gd->mem_clk = pll / div; 68ee7bb5beSWills Wang 69ee7bb5beSWills Wang /* AHB_CLK = PLLOUT / AHB_POST_DIV */ 70ee7bb5beSWills Wang div = ((val >> AR933X_PLL_CLK_CTRL_AHB_POST_DIV_SHIFT) 71ee7bb5beSWills Wang & AR933X_PLL_CLK_CTRL_AHB_POST_DIV_MASK) + 1; 72ee7bb5beSWills Wang gd->bus_clk = pll / div; 73ee7bb5beSWills Wang 74ee7bb5beSWills Wang return 0; 75ee7bb5beSWills Wang } 76ee7bb5beSWills Wang get_bus_freq(ulong dummy)77ee7bb5beSWills Wangulong get_bus_freq(ulong dummy) 78ee7bb5beSWills Wang { 79ee7bb5beSWills Wang if (!gd->bus_clk) 80ee7bb5beSWills Wang get_clocks(); 81ee7bb5beSWills Wang return gd->bus_clk; 82ee7bb5beSWills Wang } 83ee7bb5beSWills Wang get_ddr_freq(ulong dummy)84ee7bb5beSWills Wangulong get_ddr_freq(ulong dummy) 85ee7bb5beSWills Wang { 86ee7bb5beSWills Wang if (!gd->mem_clk) 87ee7bb5beSWills Wang get_clocks(); 88ee7bb5beSWills Wang return gd->mem_clk; 89ee7bb5beSWills Wang } 90