18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Atheros AR71XX/AR724X/AR913X common routines 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 2010-2011 Jaiganesh Narayanan <jnarayanan@atheros.com> 68c2ecf20Sopenharmony_ci * Copyright (C) 2011 Gabor Juhos <juhosg@openwrt.org> 78c2ecf20Sopenharmony_ci * 88c2ecf20Sopenharmony_ci * Parts of this file are based on Atheros' 2.6.15/2.6.31 BSP 98c2ecf20Sopenharmony_ci */ 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_ci#include <linux/kernel.h> 128c2ecf20Sopenharmony_ci#include <linux/init.h> 138c2ecf20Sopenharmony_ci#include <linux/io.h> 148c2ecf20Sopenharmony_ci#include <linux/err.h> 158c2ecf20Sopenharmony_ci#include <linux/clk.h> 168c2ecf20Sopenharmony_ci#include <linux/clkdev.h> 178c2ecf20Sopenharmony_ci#include <linux/clk-provider.h> 188c2ecf20Sopenharmony_ci#include <linux/of.h> 198c2ecf20Sopenharmony_ci#include <linux/of_address.h> 208c2ecf20Sopenharmony_ci#include <dt-bindings/clock/ath79-clk.h> 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_ci#include <asm/div64.h> 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_ci#include <asm/mach-ath79/ath79.h> 258c2ecf20Sopenharmony_ci#include <asm/mach-ath79/ar71xx_regs.h> 268c2ecf20Sopenharmony_ci#include "common.h" 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_ci#define AR71XX_BASE_FREQ 40000000 298c2ecf20Sopenharmony_ci#define AR724X_BASE_FREQ 40000000 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_cistatic struct clk *clks[ATH79_CLK_END]; 328c2ecf20Sopenharmony_cistatic struct clk_onecell_data clk_data = { 338c2ecf20Sopenharmony_ci .clks = clks, 348c2ecf20Sopenharmony_ci .clk_num = ARRAY_SIZE(clks), 358c2ecf20Sopenharmony_ci}; 368c2ecf20Sopenharmony_ci 378c2ecf20Sopenharmony_cistatic const char * const clk_names[ATH79_CLK_END] = { 388c2ecf20Sopenharmony_ci [ATH79_CLK_CPU] = "cpu", 398c2ecf20Sopenharmony_ci [ATH79_CLK_DDR] = "ddr", 408c2ecf20Sopenharmony_ci [ATH79_CLK_AHB] = "ahb", 418c2ecf20Sopenharmony_ci [ATH79_CLK_REF] = "ref", 428c2ecf20Sopenharmony_ci [ATH79_CLK_MDIO] = "mdio", 438c2ecf20Sopenharmony_ci}; 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_cistatic const char * __init ath79_clk_name(int type) 468c2ecf20Sopenharmony_ci{ 478c2ecf20Sopenharmony_ci BUG_ON(type >= ARRAY_SIZE(clk_names) || !clk_names[type]); 488c2ecf20Sopenharmony_ci return clk_names[type]; 498c2ecf20Sopenharmony_ci} 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_cistatic void __init __ath79_set_clk(int type, const char *name, struct clk *clk) 528c2ecf20Sopenharmony_ci{ 538c2ecf20Sopenharmony_ci if (IS_ERR(clk)) 548c2ecf20Sopenharmony_ci panic("failed to allocate %s clock structure", clk_names[type]); 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_ci clks[type] = clk; 578c2ecf20Sopenharmony_ci clk_register_clkdev(clk, name, NULL); 588c2ecf20Sopenharmony_ci} 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_cistatic struct clk * __init ath79_set_clk(int type, unsigned long rate) 618c2ecf20Sopenharmony_ci{ 628c2ecf20Sopenharmony_ci const char *name = ath79_clk_name(type); 638c2ecf20Sopenharmony_ci struct clk *clk; 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_ci clk = clk_register_fixed_rate(NULL, name, NULL, 0, rate); 668c2ecf20Sopenharmony_ci __ath79_set_clk(type, name, clk); 678c2ecf20Sopenharmony_ci return clk; 688c2ecf20Sopenharmony_ci} 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_cistatic struct clk * __init ath79_set_ff_clk(int type, const char *parent, 718c2ecf20Sopenharmony_ci unsigned int mult, unsigned int div) 728c2ecf20Sopenharmony_ci{ 738c2ecf20Sopenharmony_ci const char *name = ath79_clk_name(type); 748c2ecf20Sopenharmony_ci struct clk *clk; 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_ci clk = clk_register_fixed_factor(NULL, name, parent, 0, mult, div); 778c2ecf20Sopenharmony_ci __ath79_set_clk(type, name, clk); 788c2ecf20Sopenharmony_ci return clk; 798c2ecf20Sopenharmony_ci} 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_cistatic unsigned long __init ath79_setup_ref_clk(unsigned long rate) 828c2ecf20Sopenharmony_ci{ 838c2ecf20Sopenharmony_ci struct clk *clk = clks[ATH79_CLK_REF]; 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_ci if (clk) 868c2ecf20Sopenharmony_ci rate = clk_get_rate(clk); 878c2ecf20Sopenharmony_ci else 888c2ecf20Sopenharmony_ci clk = ath79_set_clk(ATH79_CLK_REF, rate); 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_ci return rate; 918c2ecf20Sopenharmony_ci} 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_cistatic void __init ar71xx_clocks_init(void __iomem *pll_base) 948c2ecf20Sopenharmony_ci{ 958c2ecf20Sopenharmony_ci unsigned long ref_rate; 968c2ecf20Sopenharmony_ci unsigned long cpu_rate; 978c2ecf20Sopenharmony_ci unsigned long ddr_rate; 988c2ecf20Sopenharmony_ci unsigned long ahb_rate; 998c2ecf20Sopenharmony_ci u32 pll; 1008c2ecf20Sopenharmony_ci u32 freq; 1018c2ecf20Sopenharmony_ci u32 div; 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_ci ref_rate = ath79_setup_ref_clk(AR71XX_BASE_FREQ); 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_ci pll = __raw_readl(pll_base + AR71XX_PLL_REG_CPU_CONFIG); 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_ci div = ((pll >> AR71XX_PLL_FB_SHIFT) & AR71XX_PLL_FB_MASK) + 1; 1088c2ecf20Sopenharmony_ci freq = div * ref_rate; 1098c2ecf20Sopenharmony_ci 1108c2ecf20Sopenharmony_ci div = ((pll >> AR71XX_CPU_DIV_SHIFT) & AR71XX_CPU_DIV_MASK) + 1; 1118c2ecf20Sopenharmony_ci cpu_rate = freq / div; 1128c2ecf20Sopenharmony_ci 1138c2ecf20Sopenharmony_ci div = ((pll >> AR71XX_DDR_DIV_SHIFT) & AR71XX_DDR_DIV_MASK) + 1; 1148c2ecf20Sopenharmony_ci ddr_rate = freq / div; 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_ci div = (((pll >> AR71XX_AHB_DIV_SHIFT) & AR71XX_AHB_DIV_MASK) + 1) * 2; 1178c2ecf20Sopenharmony_ci ahb_rate = cpu_rate / div; 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_ci ath79_set_clk(ATH79_CLK_CPU, cpu_rate); 1208c2ecf20Sopenharmony_ci ath79_set_clk(ATH79_CLK_DDR, ddr_rate); 1218c2ecf20Sopenharmony_ci ath79_set_clk(ATH79_CLK_AHB, ahb_rate); 1228c2ecf20Sopenharmony_ci} 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_cistatic void __init ar724x_clocks_init(void __iomem *pll_base) 1258c2ecf20Sopenharmony_ci{ 1268c2ecf20Sopenharmony_ci u32 mult, div, ddr_div, ahb_div; 1278c2ecf20Sopenharmony_ci u32 pll; 1288c2ecf20Sopenharmony_ci 1298c2ecf20Sopenharmony_ci ath79_setup_ref_clk(AR71XX_BASE_FREQ); 1308c2ecf20Sopenharmony_ci 1318c2ecf20Sopenharmony_ci pll = __raw_readl(pll_base + AR724X_PLL_REG_CPU_CONFIG); 1328c2ecf20Sopenharmony_ci 1338c2ecf20Sopenharmony_ci mult = ((pll >> AR724X_PLL_FB_SHIFT) & AR724X_PLL_FB_MASK); 1348c2ecf20Sopenharmony_ci div = ((pll >> AR724X_PLL_REF_DIV_SHIFT) & AR724X_PLL_REF_DIV_MASK) * 2; 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_ci ddr_div = ((pll >> AR724X_DDR_DIV_SHIFT) & AR724X_DDR_DIV_MASK) + 1; 1378c2ecf20Sopenharmony_ci ahb_div = (((pll >> AR724X_AHB_DIV_SHIFT) & AR724X_AHB_DIV_MASK) + 1) * 2; 1388c2ecf20Sopenharmony_ci 1398c2ecf20Sopenharmony_ci ath79_set_ff_clk(ATH79_CLK_CPU, "ref", mult, div); 1408c2ecf20Sopenharmony_ci ath79_set_ff_clk(ATH79_CLK_DDR, "ref", mult, div * ddr_div); 1418c2ecf20Sopenharmony_ci ath79_set_ff_clk(ATH79_CLK_AHB, "ref", mult, div * ahb_div); 1428c2ecf20Sopenharmony_ci} 1438c2ecf20Sopenharmony_ci 1448c2ecf20Sopenharmony_cistatic void __init ar933x_clocks_init(void __iomem *pll_base) 1458c2ecf20Sopenharmony_ci{ 1468c2ecf20Sopenharmony_ci unsigned long ref_rate; 1478c2ecf20Sopenharmony_ci u32 clock_ctrl; 1488c2ecf20Sopenharmony_ci u32 ref_div; 1498c2ecf20Sopenharmony_ci u32 ninit_mul; 1508c2ecf20Sopenharmony_ci u32 out_div; 1518c2ecf20Sopenharmony_ci 1528c2ecf20Sopenharmony_ci u32 cpu_div; 1538c2ecf20Sopenharmony_ci u32 ddr_div; 1548c2ecf20Sopenharmony_ci u32 ahb_div; 1558c2ecf20Sopenharmony_ci u32 t; 1568c2ecf20Sopenharmony_ci 1578c2ecf20Sopenharmony_ci t = ath79_reset_rr(AR933X_RESET_REG_BOOTSTRAP); 1588c2ecf20Sopenharmony_ci if (t & AR933X_BOOTSTRAP_REF_CLK_40) 1598c2ecf20Sopenharmony_ci ref_rate = (40 * 1000 * 1000); 1608c2ecf20Sopenharmony_ci else 1618c2ecf20Sopenharmony_ci ref_rate = (25 * 1000 * 1000); 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_ci ath79_setup_ref_clk(ref_rate); 1648c2ecf20Sopenharmony_ci 1658c2ecf20Sopenharmony_ci clock_ctrl = __raw_readl(pll_base + AR933X_PLL_CLOCK_CTRL_REG); 1668c2ecf20Sopenharmony_ci if (clock_ctrl & AR933X_PLL_CLOCK_CTRL_BYPASS) { 1678c2ecf20Sopenharmony_ci ref_div = 1; 1688c2ecf20Sopenharmony_ci ninit_mul = 1; 1698c2ecf20Sopenharmony_ci out_div = 1; 1708c2ecf20Sopenharmony_ci 1718c2ecf20Sopenharmony_ci cpu_div = 1; 1728c2ecf20Sopenharmony_ci ddr_div = 1; 1738c2ecf20Sopenharmony_ci ahb_div = 1; 1748c2ecf20Sopenharmony_ci } else { 1758c2ecf20Sopenharmony_ci u32 cpu_config; 1768c2ecf20Sopenharmony_ci u32 t; 1778c2ecf20Sopenharmony_ci 1788c2ecf20Sopenharmony_ci cpu_config = __raw_readl(pll_base + AR933X_PLL_CPU_CONFIG_REG); 1798c2ecf20Sopenharmony_ci 1808c2ecf20Sopenharmony_ci t = (cpu_config >> AR933X_PLL_CPU_CONFIG_REFDIV_SHIFT) & 1818c2ecf20Sopenharmony_ci AR933X_PLL_CPU_CONFIG_REFDIV_MASK; 1828c2ecf20Sopenharmony_ci ref_div = t; 1838c2ecf20Sopenharmony_ci 1848c2ecf20Sopenharmony_ci ninit_mul = (cpu_config >> AR933X_PLL_CPU_CONFIG_NINT_SHIFT) & 1858c2ecf20Sopenharmony_ci AR933X_PLL_CPU_CONFIG_NINT_MASK; 1868c2ecf20Sopenharmony_ci 1878c2ecf20Sopenharmony_ci t = (cpu_config >> AR933X_PLL_CPU_CONFIG_OUTDIV_SHIFT) & 1888c2ecf20Sopenharmony_ci AR933X_PLL_CPU_CONFIG_OUTDIV_MASK; 1898c2ecf20Sopenharmony_ci if (t == 0) 1908c2ecf20Sopenharmony_ci t = 1; 1918c2ecf20Sopenharmony_ci 1928c2ecf20Sopenharmony_ci out_div = (1 << t); 1938c2ecf20Sopenharmony_ci 1948c2ecf20Sopenharmony_ci cpu_div = ((clock_ctrl >> AR933X_PLL_CLOCK_CTRL_CPU_DIV_SHIFT) & 1958c2ecf20Sopenharmony_ci AR933X_PLL_CLOCK_CTRL_CPU_DIV_MASK) + 1; 1968c2ecf20Sopenharmony_ci 1978c2ecf20Sopenharmony_ci ddr_div = ((clock_ctrl >> AR933X_PLL_CLOCK_CTRL_DDR_DIV_SHIFT) & 1988c2ecf20Sopenharmony_ci AR933X_PLL_CLOCK_CTRL_DDR_DIV_MASK) + 1; 1998c2ecf20Sopenharmony_ci 2008c2ecf20Sopenharmony_ci ahb_div = ((clock_ctrl >> AR933X_PLL_CLOCK_CTRL_AHB_DIV_SHIFT) & 2018c2ecf20Sopenharmony_ci AR933X_PLL_CLOCK_CTRL_AHB_DIV_MASK) + 1; 2028c2ecf20Sopenharmony_ci } 2038c2ecf20Sopenharmony_ci 2048c2ecf20Sopenharmony_ci ath79_set_ff_clk(ATH79_CLK_CPU, "ref", ninit_mul, 2058c2ecf20Sopenharmony_ci ref_div * out_div * cpu_div); 2068c2ecf20Sopenharmony_ci ath79_set_ff_clk(ATH79_CLK_DDR, "ref", ninit_mul, 2078c2ecf20Sopenharmony_ci ref_div * out_div * ddr_div); 2088c2ecf20Sopenharmony_ci ath79_set_ff_clk(ATH79_CLK_AHB, "ref", ninit_mul, 2098c2ecf20Sopenharmony_ci ref_div * out_div * ahb_div); 2108c2ecf20Sopenharmony_ci} 2118c2ecf20Sopenharmony_ci 2128c2ecf20Sopenharmony_cistatic u32 __init ar934x_get_pll_freq(u32 ref, u32 ref_div, u32 nint, u32 nfrac, 2138c2ecf20Sopenharmony_ci u32 frac, u32 out_div) 2148c2ecf20Sopenharmony_ci{ 2158c2ecf20Sopenharmony_ci u64 t; 2168c2ecf20Sopenharmony_ci u32 ret; 2178c2ecf20Sopenharmony_ci 2188c2ecf20Sopenharmony_ci t = ref; 2198c2ecf20Sopenharmony_ci t *= nint; 2208c2ecf20Sopenharmony_ci do_div(t, ref_div); 2218c2ecf20Sopenharmony_ci ret = t; 2228c2ecf20Sopenharmony_ci 2238c2ecf20Sopenharmony_ci t = ref; 2248c2ecf20Sopenharmony_ci t *= nfrac; 2258c2ecf20Sopenharmony_ci do_div(t, ref_div * frac); 2268c2ecf20Sopenharmony_ci ret += t; 2278c2ecf20Sopenharmony_ci 2288c2ecf20Sopenharmony_ci ret /= (1 << out_div); 2298c2ecf20Sopenharmony_ci return ret; 2308c2ecf20Sopenharmony_ci} 2318c2ecf20Sopenharmony_ci 2328c2ecf20Sopenharmony_cistatic void __init ar934x_clocks_init(void __iomem *pll_base) 2338c2ecf20Sopenharmony_ci{ 2348c2ecf20Sopenharmony_ci unsigned long ref_rate; 2358c2ecf20Sopenharmony_ci unsigned long cpu_rate; 2368c2ecf20Sopenharmony_ci unsigned long ddr_rate; 2378c2ecf20Sopenharmony_ci unsigned long ahb_rate; 2388c2ecf20Sopenharmony_ci u32 pll, out_div, ref_div, nint, nfrac, frac, clk_ctrl, postdiv; 2398c2ecf20Sopenharmony_ci u32 cpu_pll, ddr_pll; 2408c2ecf20Sopenharmony_ci u32 bootstrap; 2418c2ecf20Sopenharmony_ci void __iomem *dpll_base; 2428c2ecf20Sopenharmony_ci 2438c2ecf20Sopenharmony_ci dpll_base = ioremap(AR934X_SRIF_BASE, AR934X_SRIF_SIZE); 2448c2ecf20Sopenharmony_ci 2458c2ecf20Sopenharmony_ci bootstrap = ath79_reset_rr(AR934X_RESET_REG_BOOTSTRAP); 2468c2ecf20Sopenharmony_ci if (bootstrap & AR934X_BOOTSTRAP_REF_CLK_40) 2478c2ecf20Sopenharmony_ci ref_rate = 40 * 1000 * 1000; 2488c2ecf20Sopenharmony_ci else 2498c2ecf20Sopenharmony_ci ref_rate = 25 * 1000 * 1000; 2508c2ecf20Sopenharmony_ci 2518c2ecf20Sopenharmony_ci ref_rate = ath79_setup_ref_clk(ref_rate); 2528c2ecf20Sopenharmony_ci 2538c2ecf20Sopenharmony_ci pll = __raw_readl(dpll_base + AR934X_SRIF_CPU_DPLL2_REG); 2548c2ecf20Sopenharmony_ci if (pll & AR934X_SRIF_DPLL2_LOCAL_PLL) { 2558c2ecf20Sopenharmony_ci out_div = (pll >> AR934X_SRIF_DPLL2_OUTDIV_SHIFT) & 2568c2ecf20Sopenharmony_ci AR934X_SRIF_DPLL2_OUTDIV_MASK; 2578c2ecf20Sopenharmony_ci pll = __raw_readl(dpll_base + AR934X_SRIF_CPU_DPLL1_REG); 2588c2ecf20Sopenharmony_ci nint = (pll >> AR934X_SRIF_DPLL1_NINT_SHIFT) & 2598c2ecf20Sopenharmony_ci AR934X_SRIF_DPLL1_NINT_MASK; 2608c2ecf20Sopenharmony_ci nfrac = pll & AR934X_SRIF_DPLL1_NFRAC_MASK; 2618c2ecf20Sopenharmony_ci ref_div = (pll >> AR934X_SRIF_DPLL1_REFDIV_SHIFT) & 2628c2ecf20Sopenharmony_ci AR934X_SRIF_DPLL1_REFDIV_MASK; 2638c2ecf20Sopenharmony_ci frac = 1 << 18; 2648c2ecf20Sopenharmony_ci } else { 2658c2ecf20Sopenharmony_ci pll = __raw_readl(pll_base + AR934X_PLL_CPU_CONFIG_REG); 2668c2ecf20Sopenharmony_ci out_div = (pll >> AR934X_PLL_CPU_CONFIG_OUTDIV_SHIFT) & 2678c2ecf20Sopenharmony_ci AR934X_PLL_CPU_CONFIG_OUTDIV_MASK; 2688c2ecf20Sopenharmony_ci ref_div = (pll >> AR934X_PLL_CPU_CONFIG_REFDIV_SHIFT) & 2698c2ecf20Sopenharmony_ci AR934X_PLL_CPU_CONFIG_REFDIV_MASK; 2708c2ecf20Sopenharmony_ci nint = (pll >> AR934X_PLL_CPU_CONFIG_NINT_SHIFT) & 2718c2ecf20Sopenharmony_ci AR934X_PLL_CPU_CONFIG_NINT_MASK; 2728c2ecf20Sopenharmony_ci nfrac = (pll >> AR934X_PLL_CPU_CONFIG_NFRAC_SHIFT) & 2738c2ecf20Sopenharmony_ci AR934X_PLL_CPU_CONFIG_NFRAC_MASK; 2748c2ecf20Sopenharmony_ci frac = 1 << 6; 2758c2ecf20Sopenharmony_ci } 2768c2ecf20Sopenharmony_ci 2778c2ecf20Sopenharmony_ci cpu_pll = ar934x_get_pll_freq(ref_rate, ref_div, nint, 2788c2ecf20Sopenharmony_ci nfrac, frac, out_div); 2798c2ecf20Sopenharmony_ci 2808c2ecf20Sopenharmony_ci pll = __raw_readl(dpll_base + AR934X_SRIF_DDR_DPLL2_REG); 2818c2ecf20Sopenharmony_ci if (pll & AR934X_SRIF_DPLL2_LOCAL_PLL) { 2828c2ecf20Sopenharmony_ci out_div = (pll >> AR934X_SRIF_DPLL2_OUTDIV_SHIFT) & 2838c2ecf20Sopenharmony_ci AR934X_SRIF_DPLL2_OUTDIV_MASK; 2848c2ecf20Sopenharmony_ci pll = __raw_readl(dpll_base + AR934X_SRIF_DDR_DPLL1_REG); 2858c2ecf20Sopenharmony_ci nint = (pll >> AR934X_SRIF_DPLL1_NINT_SHIFT) & 2868c2ecf20Sopenharmony_ci AR934X_SRIF_DPLL1_NINT_MASK; 2878c2ecf20Sopenharmony_ci nfrac = pll & AR934X_SRIF_DPLL1_NFRAC_MASK; 2888c2ecf20Sopenharmony_ci ref_div = (pll >> AR934X_SRIF_DPLL1_REFDIV_SHIFT) & 2898c2ecf20Sopenharmony_ci AR934X_SRIF_DPLL1_REFDIV_MASK; 2908c2ecf20Sopenharmony_ci frac = 1 << 18; 2918c2ecf20Sopenharmony_ci } else { 2928c2ecf20Sopenharmony_ci pll = __raw_readl(pll_base + AR934X_PLL_DDR_CONFIG_REG); 2938c2ecf20Sopenharmony_ci out_div = (pll >> AR934X_PLL_DDR_CONFIG_OUTDIV_SHIFT) & 2948c2ecf20Sopenharmony_ci AR934X_PLL_DDR_CONFIG_OUTDIV_MASK; 2958c2ecf20Sopenharmony_ci ref_div = (pll >> AR934X_PLL_DDR_CONFIG_REFDIV_SHIFT) & 2968c2ecf20Sopenharmony_ci AR934X_PLL_DDR_CONFIG_REFDIV_MASK; 2978c2ecf20Sopenharmony_ci nint = (pll >> AR934X_PLL_DDR_CONFIG_NINT_SHIFT) & 2988c2ecf20Sopenharmony_ci AR934X_PLL_DDR_CONFIG_NINT_MASK; 2998c2ecf20Sopenharmony_ci nfrac = (pll >> AR934X_PLL_DDR_CONFIG_NFRAC_SHIFT) & 3008c2ecf20Sopenharmony_ci AR934X_PLL_DDR_CONFIG_NFRAC_MASK; 3018c2ecf20Sopenharmony_ci frac = 1 << 10; 3028c2ecf20Sopenharmony_ci } 3038c2ecf20Sopenharmony_ci 3048c2ecf20Sopenharmony_ci ddr_pll = ar934x_get_pll_freq(ref_rate, ref_div, nint, 3058c2ecf20Sopenharmony_ci nfrac, frac, out_div); 3068c2ecf20Sopenharmony_ci 3078c2ecf20Sopenharmony_ci clk_ctrl = __raw_readl(pll_base + AR934X_PLL_CPU_DDR_CLK_CTRL_REG); 3088c2ecf20Sopenharmony_ci 3098c2ecf20Sopenharmony_ci postdiv = (clk_ctrl >> AR934X_PLL_CPU_DDR_CLK_CTRL_CPU_POST_DIV_SHIFT) & 3108c2ecf20Sopenharmony_ci AR934X_PLL_CPU_DDR_CLK_CTRL_CPU_POST_DIV_MASK; 3118c2ecf20Sopenharmony_ci 3128c2ecf20Sopenharmony_ci if (clk_ctrl & AR934X_PLL_CPU_DDR_CLK_CTRL_CPU_PLL_BYPASS) 3138c2ecf20Sopenharmony_ci cpu_rate = ref_rate; 3148c2ecf20Sopenharmony_ci else if (clk_ctrl & AR934X_PLL_CPU_DDR_CLK_CTRL_CPUCLK_FROM_CPUPLL) 3158c2ecf20Sopenharmony_ci cpu_rate = cpu_pll / (postdiv + 1); 3168c2ecf20Sopenharmony_ci else 3178c2ecf20Sopenharmony_ci cpu_rate = ddr_pll / (postdiv + 1); 3188c2ecf20Sopenharmony_ci 3198c2ecf20Sopenharmony_ci postdiv = (clk_ctrl >> AR934X_PLL_CPU_DDR_CLK_CTRL_DDR_POST_DIV_SHIFT) & 3208c2ecf20Sopenharmony_ci AR934X_PLL_CPU_DDR_CLK_CTRL_DDR_POST_DIV_MASK; 3218c2ecf20Sopenharmony_ci 3228c2ecf20Sopenharmony_ci if (clk_ctrl & AR934X_PLL_CPU_DDR_CLK_CTRL_DDR_PLL_BYPASS) 3238c2ecf20Sopenharmony_ci ddr_rate = ref_rate; 3248c2ecf20Sopenharmony_ci else if (clk_ctrl & AR934X_PLL_CPU_DDR_CLK_CTRL_DDRCLK_FROM_DDRPLL) 3258c2ecf20Sopenharmony_ci ddr_rate = ddr_pll / (postdiv + 1); 3268c2ecf20Sopenharmony_ci else 3278c2ecf20Sopenharmony_ci ddr_rate = cpu_pll / (postdiv + 1); 3288c2ecf20Sopenharmony_ci 3298c2ecf20Sopenharmony_ci postdiv = (clk_ctrl >> AR934X_PLL_CPU_DDR_CLK_CTRL_AHB_POST_DIV_SHIFT) & 3308c2ecf20Sopenharmony_ci AR934X_PLL_CPU_DDR_CLK_CTRL_AHB_POST_DIV_MASK; 3318c2ecf20Sopenharmony_ci 3328c2ecf20Sopenharmony_ci if (clk_ctrl & AR934X_PLL_CPU_DDR_CLK_CTRL_AHB_PLL_BYPASS) 3338c2ecf20Sopenharmony_ci ahb_rate = ref_rate; 3348c2ecf20Sopenharmony_ci else if (clk_ctrl & AR934X_PLL_CPU_DDR_CLK_CTRL_AHBCLK_FROM_DDRPLL) 3358c2ecf20Sopenharmony_ci ahb_rate = ddr_pll / (postdiv + 1); 3368c2ecf20Sopenharmony_ci else 3378c2ecf20Sopenharmony_ci ahb_rate = cpu_pll / (postdiv + 1); 3388c2ecf20Sopenharmony_ci 3398c2ecf20Sopenharmony_ci ath79_set_clk(ATH79_CLK_CPU, cpu_rate); 3408c2ecf20Sopenharmony_ci ath79_set_clk(ATH79_CLK_DDR, ddr_rate); 3418c2ecf20Sopenharmony_ci ath79_set_clk(ATH79_CLK_AHB, ahb_rate); 3428c2ecf20Sopenharmony_ci 3438c2ecf20Sopenharmony_ci clk_ctrl = __raw_readl(pll_base + AR934X_PLL_SWITCH_CLOCK_CONTROL_REG); 3448c2ecf20Sopenharmony_ci if (clk_ctrl & AR934X_PLL_SWITCH_CLOCK_CONTROL_MDIO_CLK_SEL) 3458c2ecf20Sopenharmony_ci ath79_set_clk(ATH79_CLK_MDIO, 100 * 1000 * 1000); 3468c2ecf20Sopenharmony_ci 3478c2ecf20Sopenharmony_ci iounmap(dpll_base); 3488c2ecf20Sopenharmony_ci} 3498c2ecf20Sopenharmony_ci 3508c2ecf20Sopenharmony_cistatic void __init qca953x_clocks_init(void __iomem *pll_base) 3518c2ecf20Sopenharmony_ci{ 3528c2ecf20Sopenharmony_ci unsigned long ref_rate; 3538c2ecf20Sopenharmony_ci unsigned long cpu_rate; 3548c2ecf20Sopenharmony_ci unsigned long ddr_rate; 3558c2ecf20Sopenharmony_ci unsigned long ahb_rate; 3568c2ecf20Sopenharmony_ci u32 pll, out_div, ref_div, nint, frac, clk_ctrl, postdiv; 3578c2ecf20Sopenharmony_ci u32 cpu_pll, ddr_pll; 3588c2ecf20Sopenharmony_ci u32 bootstrap; 3598c2ecf20Sopenharmony_ci 3608c2ecf20Sopenharmony_ci bootstrap = ath79_reset_rr(QCA953X_RESET_REG_BOOTSTRAP); 3618c2ecf20Sopenharmony_ci if (bootstrap & QCA953X_BOOTSTRAP_REF_CLK_40) 3628c2ecf20Sopenharmony_ci ref_rate = 40 * 1000 * 1000; 3638c2ecf20Sopenharmony_ci else 3648c2ecf20Sopenharmony_ci ref_rate = 25 * 1000 * 1000; 3658c2ecf20Sopenharmony_ci 3668c2ecf20Sopenharmony_ci ref_rate = ath79_setup_ref_clk(ref_rate); 3678c2ecf20Sopenharmony_ci 3688c2ecf20Sopenharmony_ci pll = __raw_readl(pll_base + QCA953X_PLL_CPU_CONFIG_REG); 3698c2ecf20Sopenharmony_ci out_div = (pll >> QCA953X_PLL_CPU_CONFIG_OUTDIV_SHIFT) & 3708c2ecf20Sopenharmony_ci QCA953X_PLL_CPU_CONFIG_OUTDIV_MASK; 3718c2ecf20Sopenharmony_ci ref_div = (pll >> QCA953X_PLL_CPU_CONFIG_REFDIV_SHIFT) & 3728c2ecf20Sopenharmony_ci QCA953X_PLL_CPU_CONFIG_REFDIV_MASK; 3738c2ecf20Sopenharmony_ci nint = (pll >> QCA953X_PLL_CPU_CONFIG_NINT_SHIFT) & 3748c2ecf20Sopenharmony_ci QCA953X_PLL_CPU_CONFIG_NINT_MASK; 3758c2ecf20Sopenharmony_ci frac = (pll >> QCA953X_PLL_CPU_CONFIG_NFRAC_SHIFT) & 3768c2ecf20Sopenharmony_ci QCA953X_PLL_CPU_CONFIG_NFRAC_MASK; 3778c2ecf20Sopenharmony_ci 3788c2ecf20Sopenharmony_ci cpu_pll = nint * ref_rate / ref_div; 3798c2ecf20Sopenharmony_ci cpu_pll += frac * (ref_rate >> 6) / ref_div; 3808c2ecf20Sopenharmony_ci cpu_pll /= (1 << out_div); 3818c2ecf20Sopenharmony_ci 3828c2ecf20Sopenharmony_ci pll = __raw_readl(pll_base + QCA953X_PLL_DDR_CONFIG_REG); 3838c2ecf20Sopenharmony_ci out_div = (pll >> QCA953X_PLL_DDR_CONFIG_OUTDIV_SHIFT) & 3848c2ecf20Sopenharmony_ci QCA953X_PLL_DDR_CONFIG_OUTDIV_MASK; 3858c2ecf20Sopenharmony_ci ref_div = (pll >> QCA953X_PLL_DDR_CONFIG_REFDIV_SHIFT) & 3868c2ecf20Sopenharmony_ci QCA953X_PLL_DDR_CONFIG_REFDIV_MASK; 3878c2ecf20Sopenharmony_ci nint = (pll >> QCA953X_PLL_DDR_CONFIG_NINT_SHIFT) & 3888c2ecf20Sopenharmony_ci QCA953X_PLL_DDR_CONFIG_NINT_MASK; 3898c2ecf20Sopenharmony_ci frac = (pll >> QCA953X_PLL_DDR_CONFIG_NFRAC_SHIFT) & 3908c2ecf20Sopenharmony_ci QCA953X_PLL_DDR_CONFIG_NFRAC_MASK; 3918c2ecf20Sopenharmony_ci 3928c2ecf20Sopenharmony_ci ddr_pll = nint * ref_rate / ref_div; 3938c2ecf20Sopenharmony_ci ddr_pll += frac * (ref_rate >> 6) / (ref_div << 4); 3948c2ecf20Sopenharmony_ci ddr_pll /= (1 << out_div); 3958c2ecf20Sopenharmony_ci 3968c2ecf20Sopenharmony_ci clk_ctrl = __raw_readl(pll_base + QCA953X_PLL_CLK_CTRL_REG); 3978c2ecf20Sopenharmony_ci 3988c2ecf20Sopenharmony_ci postdiv = (clk_ctrl >> QCA953X_PLL_CLK_CTRL_CPU_POST_DIV_SHIFT) & 3998c2ecf20Sopenharmony_ci QCA953X_PLL_CLK_CTRL_CPU_POST_DIV_MASK; 4008c2ecf20Sopenharmony_ci 4018c2ecf20Sopenharmony_ci if (clk_ctrl & QCA953X_PLL_CLK_CTRL_CPU_PLL_BYPASS) 4028c2ecf20Sopenharmony_ci cpu_rate = ref_rate; 4038c2ecf20Sopenharmony_ci else if (clk_ctrl & QCA953X_PLL_CLK_CTRL_CPUCLK_FROM_CPUPLL) 4048c2ecf20Sopenharmony_ci cpu_rate = cpu_pll / (postdiv + 1); 4058c2ecf20Sopenharmony_ci else 4068c2ecf20Sopenharmony_ci cpu_rate = ddr_pll / (postdiv + 1); 4078c2ecf20Sopenharmony_ci 4088c2ecf20Sopenharmony_ci postdiv = (clk_ctrl >> QCA953X_PLL_CLK_CTRL_DDR_POST_DIV_SHIFT) & 4098c2ecf20Sopenharmony_ci QCA953X_PLL_CLK_CTRL_DDR_POST_DIV_MASK; 4108c2ecf20Sopenharmony_ci 4118c2ecf20Sopenharmony_ci if (clk_ctrl & QCA953X_PLL_CLK_CTRL_DDR_PLL_BYPASS) 4128c2ecf20Sopenharmony_ci ddr_rate = ref_rate; 4138c2ecf20Sopenharmony_ci else if (clk_ctrl & QCA953X_PLL_CLK_CTRL_DDRCLK_FROM_DDRPLL) 4148c2ecf20Sopenharmony_ci ddr_rate = ddr_pll / (postdiv + 1); 4158c2ecf20Sopenharmony_ci else 4168c2ecf20Sopenharmony_ci ddr_rate = cpu_pll / (postdiv + 1); 4178c2ecf20Sopenharmony_ci 4188c2ecf20Sopenharmony_ci postdiv = (clk_ctrl >> QCA953X_PLL_CLK_CTRL_AHB_POST_DIV_SHIFT) & 4198c2ecf20Sopenharmony_ci QCA953X_PLL_CLK_CTRL_AHB_POST_DIV_MASK; 4208c2ecf20Sopenharmony_ci 4218c2ecf20Sopenharmony_ci if (clk_ctrl & QCA953X_PLL_CLK_CTRL_AHB_PLL_BYPASS) 4228c2ecf20Sopenharmony_ci ahb_rate = ref_rate; 4238c2ecf20Sopenharmony_ci else if (clk_ctrl & QCA953X_PLL_CLK_CTRL_AHBCLK_FROM_DDRPLL) 4248c2ecf20Sopenharmony_ci ahb_rate = ddr_pll / (postdiv + 1); 4258c2ecf20Sopenharmony_ci else 4268c2ecf20Sopenharmony_ci ahb_rate = cpu_pll / (postdiv + 1); 4278c2ecf20Sopenharmony_ci 4288c2ecf20Sopenharmony_ci ath79_set_clk(ATH79_CLK_CPU, cpu_rate); 4298c2ecf20Sopenharmony_ci ath79_set_clk(ATH79_CLK_DDR, ddr_rate); 4308c2ecf20Sopenharmony_ci ath79_set_clk(ATH79_CLK_AHB, ahb_rate); 4318c2ecf20Sopenharmony_ci} 4328c2ecf20Sopenharmony_ci 4338c2ecf20Sopenharmony_cistatic void __init qca955x_clocks_init(void __iomem *pll_base) 4348c2ecf20Sopenharmony_ci{ 4358c2ecf20Sopenharmony_ci unsigned long ref_rate; 4368c2ecf20Sopenharmony_ci unsigned long cpu_rate; 4378c2ecf20Sopenharmony_ci unsigned long ddr_rate; 4388c2ecf20Sopenharmony_ci unsigned long ahb_rate; 4398c2ecf20Sopenharmony_ci u32 pll, out_div, ref_div, nint, frac, clk_ctrl, postdiv; 4408c2ecf20Sopenharmony_ci u32 cpu_pll, ddr_pll; 4418c2ecf20Sopenharmony_ci u32 bootstrap; 4428c2ecf20Sopenharmony_ci 4438c2ecf20Sopenharmony_ci bootstrap = ath79_reset_rr(QCA955X_RESET_REG_BOOTSTRAP); 4448c2ecf20Sopenharmony_ci if (bootstrap & QCA955X_BOOTSTRAP_REF_CLK_40) 4458c2ecf20Sopenharmony_ci ref_rate = 40 * 1000 * 1000; 4468c2ecf20Sopenharmony_ci else 4478c2ecf20Sopenharmony_ci ref_rate = 25 * 1000 * 1000; 4488c2ecf20Sopenharmony_ci 4498c2ecf20Sopenharmony_ci ref_rate = ath79_setup_ref_clk(ref_rate); 4508c2ecf20Sopenharmony_ci 4518c2ecf20Sopenharmony_ci pll = __raw_readl(pll_base + QCA955X_PLL_CPU_CONFIG_REG); 4528c2ecf20Sopenharmony_ci out_div = (pll >> QCA955X_PLL_CPU_CONFIG_OUTDIV_SHIFT) & 4538c2ecf20Sopenharmony_ci QCA955X_PLL_CPU_CONFIG_OUTDIV_MASK; 4548c2ecf20Sopenharmony_ci ref_div = (pll >> QCA955X_PLL_CPU_CONFIG_REFDIV_SHIFT) & 4558c2ecf20Sopenharmony_ci QCA955X_PLL_CPU_CONFIG_REFDIV_MASK; 4568c2ecf20Sopenharmony_ci nint = (pll >> QCA955X_PLL_CPU_CONFIG_NINT_SHIFT) & 4578c2ecf20Sopenharmony_ci QCA955X_PLL_CPU_CONFIG_NINT_MASK; 4588c2ecf20Sopenharmony_ci frac = (pll >> QCA955X_PLL_CPU_CONFIG_NFRAC_SHIFT) & 4598c2ecf20Sopenharmony_ci QCA955X_PLL_CPU_CONFIG_NFRAC_MASK; 4608c2ecf20Sopenharmony_ci 4618c2ecf20Sopenharmony_ci cpu_pll = nint * ref_rate / ref_div; 4628c2ecf20Sopenharmony_ci cpu_pll += frac * ref_rate / (ref_div * (1 << 6)); 4638c2ecf20Sopenharmony_ci cpu_pll /= (1 << out_div); 4648c2ecf20Sopenharmony_ci 4658c2ecf20Sopenharmony_ci pll = __raw_readl(pll_base + QCA955X_PLL_DDR_CONFIG_REG); 4668c2ecf20Sopenharmony_ci out_div = (pll >> QCA955X_PLL_DDR_CONFIG_OUTDIV_SHIFT) & 4678c2ecf20Sopenharmony_ci QCA955X_PLL_DDR_CONFIG_OUTDIV_MASK; 4688c2ecf20Sopenharmony_ci ref_div = (pll >> QCA955X_PLL_DDR_CONFIG_REFDIV_SHIFT) & 4698c2ecf20Sopenharmony_ci QCA955X_PLL_DDR_CONFIG_REFDIV_MASK; 4708c2ecf20Sopenharmony_ci nint = (pll >> QCA955X_PLL_DDR_CONFIG_NINT_SHIFT) & 4718c2ecf20Sopenharmony_ci QCA955X_PLL_DDR_CONFIG_NINT_MASK; 4728c2ecf20Sopenharmony_ci frac = (pll >> QCA955X_PLL_DDR_CONFIG_NFRAC_SHIFT) & 4738c2ecf20Sopenharmony_ci QCA955X_PLL_DDR_CONFIG_NFRAC_MASK; 4748c2ecf20Sopenharmony_ci 4758c2ecf20Sopenharmony_ci ddr_pll = nint * ref_rate / ref_div; 4768c2ecf20Sopenharmony_ci ddr_pll += frac * ref_rate / (ref_div * (1 << 10)); 4778c2ecf20Sopenharmony_ci ddr_pll /= (1 << out_div); 4788c2ecf20Sopenharmony_ci 4798c2ecf20Sopenharmony_ci clk_ctrl = __raw_readl(pll_base + QCA955X_PLL_CLK_CTRL_REG); 4808c2ecf20Sopenharmony_ci 4818c2ecf20Sopenharmony_ci postdiv = (clk_ctrl >> QCA955X_PLL_CLK_CTRL_CPU_POST_DIV_SHIFT) & 4828c2ecf20Sopenharmony_ci QCA955X_PLL_CLK_CTRL_CPU_POST_DIV_MASK; 4838c2ecf20Sopenharmony_ci 4848c2ecf20Sopenharmony_ci if (clk_ctrl & QCA955X_PLL_CLK_CTRL_CPU_PLL_BYPASS) 4858c2ecf20Sopenharmony_ci cpu_rate = ref_rate; 4868c2ecf20Sopenharmony_ci else if (clk_ctrl & QCA955X_PLL_CLK_CTRL_CPUCLK_FROM_CPUPLL) 4878c2ecf20Sopenharmony_ci cpu_rate = ddr_pll / (postdiv + 1); 4888c2ecf20Sopenharmony_ci else 4898c2ecf20Sopenharmony_ci cpu_rate = cpu_pll / (postdiv + 1); 4908c2ecf20Sopenharmony_ci 4918c2ecf20Sopenharmony_ci postdiv = (clk_ctrl >> QCA955X_PLL_CLK_CTRL_DDR_POST_DIV_SHIFT) & 4928c2ecf20Sopenharmony_ci QCA955X_PLL_CLK_CTRL_DDR_POST_DIV_MASK; 4938c2ecf20Sopenharmony_ci 4948c2ecf20Sopenharmony_ci if (clk_ctrl & QCA955X_PLL_CLK_CTRL_DDR_PLL_BYPASS) 4958c2ecf20Sopenharmony_ci ddr_rate = ref_rate; 4968c2ecf20Sopenharmony_ci else if (clk_ctrl & QCA955X_PLL_CLK_CTRL_DDRCLK_FROM_DDRPLL) 4978c2ecf20Sopenharmony_ci ddr_rate = cpu_pll / (postdiv + 1); 4988c2ecf20Sopenharmony_ci else 4998c2ecf20Sopenharmony_ci ddr_rate = ddr_pll / (postdiv + 1); 5008c2ecf20Sopenharmony_ci 5018c2ecf20Sopenharmony_ci postdiv = (clk_ctrl >> QCA955X_PLL_CLK_CTRL_AHB_POST_DIV_SHIFT) & 5028c2ecf20Sopenharmony_ci QCA955X_PLL_CLK_CTRL_AHB_POST_DIV_MASK; 5038c2ecf20Sopenharmony_ci 5048c2ecf20Sopenharmony_ci if (clk_ctrl & QCA955X_PLL_CLK_CTRL_AHB_PLL_BYPASS) 5058c2ecf20Sopenharmony_ci ahb_rate = ref_rate; 5068c2ecf20Sopenharmony_ci else if (clk_ctrl & QCA955X_PLL_CLK_CTRL_AHBCLK_FROM_DDRPLL) 5078c2ecf20Sopenharmony_ci ahb_rate = ddr_pll / (postdiv + 1); 5088c2ecf20Sopenharmony_ci else 5098c2ecf20Sopenharmony_ci ahb_rate = cpu_pll / (postdiv + 1); 5108c2ecf20Sopenharmony_ci 5118c2ecf20Sopenharmony_ci ath79_set_clk(ATH79_CLK_CPU, cpu_rate); 5128c2ecf20Sopenharmony_ci ath79_set_clk(ATH79_CLK_DDR, ddr_rate); 5138c2ecf20Sopenharmony_ci ath79_set_clk(ATH79_CLK_AHB, ahb_rate); 5148c2ecf20Sopenharmony_ci} 5158c2ecf20Sopenharmony_ci 5168c2ecf20Sopenharmony_cistatic void __init qca956x_clocks_init(void __iomem *pll_base) 5178c2ecf20Sopenharmony_ci{ 5188c2ecf20Sopenharmony_ci unsigned long ref_rate; 5198c2ecf20Sopenharmony_ci unsigned long cpu_rate; 5208c2ecf20Sopenharmony_ci unsigned long ddr_rate; 5218c2ecf20Sopenharmony_ci unsigned long ahb_rate; 5228c2ecf20Sopenharmony_ci u32 pll, out_div, ref_div, nint, hfrac, lfrac, clk_ctrl, postdiv; 5238c2ecf20Sopenharmony_ci u32 cpu_pll, ddr_pll; 5248c2ecf20Sopenharmony_ci u32 bootstrap; 5258c2ecf20Sopenharmony_ci 5268c2ecf20Sopenharmony_ci /* 5278c2ecf20Sopenharmony_ci * QCA956x timer init workaround has to be applied right before setting 5288c2ecf20Sopenharmony_ci * up the clock. Else, there will be no jiffies 5298c2ecf20Sopenharmony_ci */ 5308c2ecf20Sopenharmony_ci u32 misc; 5318c2ecf20Sopenharmony_ci 5328c2ecf20Sopenharmony_ci misc = ath79_reset_rr(AR71XX_RESET_REG_MISC_INT_ENABLE); 5338c2ecf20Sopenharmony_ci misc |= MISC_INT_MIPS_SI_TIMERINT_MASK; 5348c2ecf20Sopenharmony_ci ath79_reset_wr(AR71XX_RESET_REG_MISC_INT_ENABLE, misc); 5358c2ecf20Sopenharmony_ci 5368c2ecf20Sopenharmony_ci bootstrap = ath79_reset_rr(QCA956X_RESET_REG_BOOTSTRAP); 5378c2ecf20Sopenharmony_ci if (bootstrap & QCA956X_BOOTSTRAP_REF_CLK_40) 5388c2ecf20Sopenharmony_ci ref_rate = 40 * 1000 * 1000; 5398c2ecf20Sopenharmony_ci else 5408c2ecf20Sopenharmony_ci ref_rate = 25 * 1000 * 1000; 5418c2ecf20Sopenharmony_ci 5428c2ecf20Sopenharmony_ci ref_rate = ath79_setup_ref_clk(ref_rate); 5438c2ecf20Sopenharmony_ci 5448c2ecf20Sopenharmony_ci pll = __raw_readl(pll_base + QCA956X_PLL_CPU_CONFIG_REG); 5458c2ecf20Sopenharmony_ci out_div = (pll >> QCA956X_PLL_CPU_CONFIG_OUTDIV_SHIFT) & 5468c2ecf20Sopenharmony_ci QCA956X_PLL_CPU_CONFIG_OUTDIV_MASK; 5478c2ecf20Sopenharmony_ci ref_div = (pll >> QCA956X_PLL_CPU_CONFIG_REFDIV_SHIFT) & 5488c2ecf20Sopenharmony_ci QCA956X_PLL_CPU_CONFIG_REFDIV_MASK; 5498c2ecf20Sopenharmony_ci 5508c2ecf20Sopenharmony_ci pll = __raw_readl(pll_base + QCA956X_PLL_CPU_CONFIG1_REG); 5518c2ecf20Sopenharmony_ci nint = (pll >> QCA956X_PLL_CPU_CONFIG1_NINT_SHIFT) & 5528c2ecf20Sopenharmony_ci QCA956X_PLL_CPU_CONFIG1_NINT_MASK; 5538c2ecf20Sopenharmony_ci hfrac = (pll >> QCA956X_PLL_CPU_CONFIG1_NFRAC_H_SHIFT) & 5548c2ecf20Sopenharmony_ci QCA956X_PLL_CPU_CONFIG1_NFRAC_H_MASK; 5558c2ecf20Sopenharmony_ci lfrac = (pll >> QCA956X_PLL_CPU_CONFIG1_NFRAC_L_SHIFT) & 5568c2ecf20Sopenharmony_ci QCA956X_PLL_CPU_CONFIG1_NFRAC_L_MASK; 5578c2ecf20Sopenharmony_ci 5588c2ecf20Sopenharmony_ci cpu_pll = nint * ref_rate / ref_div; 5598c2ecf20Sopenharmony_ci cpu_pll += (lfrac * ref_rate) / ((ref_div * 25) << 13); 5608c2ecf20Sopenharmony_ci cpu_pll += (hfrac >> 13) * ref_rate / ref_div; 5618c2ecf20Sopenharmony_ci cpu_pll /= (1 << out_div); 5628c2ecf20Sopenharmony_ci 5638c2ecf20Sopenharmony_ci pll = __raw_readl(pll_base + QCA956X_PLL_DDR_CONFIG_REG); 5648c2ecf20Sopenharmony_ci out_div = (pll >> QCA956X_PLL_DDR_CONFIG_OUTDIV_SHIFT) & 5658c2ecf20Sopenharmony_ci QCA956X_PLL_DDR_CONFIG_OUTDIV_MASK; 5668c2ecf20Sopenharmony_ci ref_div = (pll >> QCA956X_PLL_DDR_CONFIG_REFDIV_SHIFT) & 5678c2ecf20Sopenharmony_ci QCA956X_PLL_DDR_CONFIG_REFDIV_MASK; 5688c2ecf20Sopenharmony_ci pll = __raw_readl(pll_base + QCA956X_PLL_DDR_CONFIG1_REG); 5698c2ecf20Sopenharmony_ci nint = (pll >> QCA956X_PLL_DDR_CONFIG1_NINT_SHIFT) & 5708c2ecf20Sopenharmony_ci QCA956X_PLL_DDR_CONFIG1_NINT_MASK; 5718c2ecf20Sopenharmony_ci hfrac = (pll >> QCA956X_PLL_DDR_CONFIG1_NFRAC_H_SHIFT) & 5728c2ecf20Sopenharmony_ci QCA956X_PLL_DDR_CONFIG1_NFRAC_H_MASK; 5738c2ecf20Sopenharmony_ci lfrac = (pll >> QCA956X_PLL_DDR_CONFIG1_NFRAC_L_SHIFT) & 5748c2ecf20Sopenharmony_ci QCA956X_PLL_DDR_CONFIG1_NFRAC_L_MASK; 5758c2ecf20Sopenharmony_ci 5768c2ecf20Sopenharmony_ci ddr_pll = nint * ref_rate / ref_div; 5778c2ecf20Sopenharmony_ci ddr_pll += (lfrac * ref_rate) / ((ref_div * 25) << 13); 5788c2ecf20Sopenharmony_ci ddr_pll += (hfrac >> 13) * ref_rate / ref_div; 5798c2ecf20Sopenharmony_ci ddr_pll /= (1 << out_div); 5808c2ecf20Sopenharmony_ci 5818c2ecf20Sopenharmony_ci clk_ctrl = __raw_readl(pll_base + QCA956X_PLL_CLK_CTRL_REG); 5828c2ecf20Sopenharmony_ci 5838c2ecf20Sopenharmony_ci postdiv = (clk_ctrl >> QCA956X_PLL_CLK_CTRL_CPU_POST_DIV_SHIFT) & 5848c2ecf20Sopenharmony_ci QCA956X_PLL_CLK_CTRL_CPU_POST_DIV_MASK; 5858c2ecf20Sopenharmony_ci 5868c2ecf20Sopenharmony_ci if (clk_ctrl & QCA956X_PLL_CLK_CTRL_CPU_PLL_BYPASS) 5878c2ecf20Sopenharmony_ci cpu_rate = ref_rate; 5888c2ecf20Sopenharmony_ci else if (clk_ctrl & QCA956X_PLL_CLK_CTRL_CPU_DDRCLK_FROM_CPUPLL) 5898c2ecf20Sopenharmony_ci cpu_rate = ddr_pll / (postdiv + 1); 5908c2ecf20Sopenharmony_ci else 5918c2ecf20Sopenharmony_ci cpu_rate = cpu_pll / (postdiv + 1); 5928c2ecf20Sopenharmony_ci 5938c2ecf20Sopenharmony_ci postdiv = (clk_ctrl >> QCA956X_PLL_CLK_CTRL_DDR_POST_DIV_SHIFT) & 5948c2ecf20Sopenharmony_ci QCA956X_PLL_CLK_CTRL_DDR_POST_DIV_MASK; 5958c2ecf20Sopenharmony_ci 5968c2ecf20Sopenharmony_ci if (clk_ctrl & QCA956X_PLL_CLK_CTRL_DDR_PLL_BYPASS) 5978c2ecf20Sopenharmony_ci ddr_rate = ref_rate; 5988c2ecf20Sopenharmony_ci else if (clk_ctrl & QCA956X_PLL_CLK_CTRL_CPU_DDRCLK_FROM_DDRPLL) 5998c2ecf20Sopenharmony_ci ddr_rate = cpu_pll / (postdiv + 1); 6008c2ecf20Sopenharmony_ci else 6018c2ecf20Sopenharmony_ci ddr_rate = ddr_pll / (postdiv + 1); 6028c2ecf20Sopenharmony_ci 6038c2ecf20Sopenharmony_ci postdiv = (clk_ctrl >> QCA956X_PLL_CLK_CTRL_AHB_POST_DIV_SHIFT) & 6048c2ecf20Sopenharmony_ci QCA956X_PLL_CLK_CTRL_AHB_POST_DIV_MASK; 6058c2ecf20Sopenharmony_ci 6068c2ecf20Sopenharmony_ci if (clk_ctrl & QCA956X_PLL_CLK_CTRL_AHB_PLL_BYPASS) 6078c2ecf20Sopenharmony_ci ahb_rate = ref_rate; 6088c2ecf20Sopenharmony_ci else if (clk_ctrl & QCA956X_PLL_CLK_CTRL_AHBCLK_FROM_DDRPLL) 6098c2ecf20Sopenharmony_ci ahb_rate = ddr_pll / (postdiv + 1); 6108c2ecf20Sopenharmony_ci else 6118c2ecf20Sopenharmony_ci ahb_rate = cpu_pll / (postdiv + 1); 6128c2ecf20Sopenharmony_ci 6138c2ecf20Sopenharmony_ci ath79_set_clk(ATH79_CLK_CPU, cpu_rate); 6148c2ecf20Sopenharmony_ci ath79_set_clk(ATH79_CLK_DDR, ddr_rate); 6158c2ecf20Sopenharmony_ci ath79_set_clk(ATH79_CLK_AHB, ahb_rate); 6168c2ecf20Sopenharmony_ci} 6178c2ecf20Sopenharmony_ci 6188c2ecf20Sopenharmony_cistatic void __init ath79_clocks_init_dt(struct device_node *np) 6198c2ecf20Sopenharmony_ci{ 6208c2ecf20Sopenharmony_ci struct clk *ref_clk; 6218c2ecf20Sopenharmony_ci void __iomem *pll_base; 6228c2ecf20Sopenharmony_ci 6238c2ecf20Sopenharmony_ci ref_clk = of_clk_get(np, 0); 6248c2ecf20Sopenharmony_ci if (!IS_ERR(ref_clk)) 6258c2ecf20Sopenharmony_ci clks[ATH79_CLK_REF] = ref_clk; 6268c2ecf20Sopenharmony_ci 6278c2ecf20Sopenharmony_ci pll_base = of_iomap(np, 0); 6288c2ecf20Sopenharmony_ci if (!pll_base) { 6298c2ecf20Sopenharmony_ci pr_err("%pOF: can't map pll registers\n", np); 6308c2ecf20Sopenharmony_ci goto err_clk; 6318c2ecf20Sopenharmony_ci } 6328c2ecf20Sopenharmony_ci 6338c2ecf20Sopenharmony_ci if (of_device_is_compatible(np, "qca,ar7100-pll")) 6348c2ecf20Sopenharmony_ci ar71xx_clocks_init(pll_base); 6358c2ecf20Sopenharmony_ci else if (of_device_is_compatible(np, "qca,ar7240-pll") || 6368c2ecf20Sopenharmony_ci of_device_is_compatible(np, "qca,ar9130-pll")) 6378c2ecf20Sopenharmony_ci ar724x_clocks_init(pll_base); 6388c2ecf20Sopenharmony_ci else if (of_device_is_compatible(np, "qca,ar9330-pll")) 6398c2ecf20Sopenharmony_ci ar933x_clocks_init(pll_base); 6408c2ecf20Sopenharmony_ci else if (of_device_is_compatible(np, "qca,ar9340-pll")) 6418c2ecf20Sopenharmony_ci ar934x_clocks_init(pll_base); 6428c2ecf20Sopenharmony_ci else if (of_device_is_compatible(np, "qca,qca9530-pll")) 6438c2ecf20Sopenharmony_ci qca953x_clocks_init(pll_base); 6448c2ecf20Sopenharmony_ci else if (of_device_is_compatible(np, "qca,qca9550-pll")) 6458c2ecf20Sopenharmony_ci qca955x_clocks_init(pll_base); 6468c2ecf20Sopenharmony_ci else if (of_device_is_compatible(np, "qca,qca9560-pll")) 6478c2ecf20Sopenharmony_ci qca956x_clocks_init(pll_base); 6488c2ecf20Sopenharmony_ci 6498c2ecf20Sopenharmony_ci if (!clks[ATH79_CLK_MDIO]) 6508c2ecf20Sopenharmony_ci clks[ATH79_CLK_MDIO] = clks[ATH79_CLK_REF]; 6518c2ecf20Sopenharmony_ci 6528c2ecf20Sopenharmony_ci if (of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data)) { 6538c2ecf20Sopenharmony_ci pr_err("%pOF: could not register clk provider\n", np); 6548c2ecf20Sopenharmony_ci goto err_iounmap; 6558c2ecf20Sopenharmony_ci } 6568c2ecf20Sopenharmony_ci 6578c2ecf20Sopenharmony_ci return; 6588c2ecf20Sopenharmony_ci 6598c2ecf20Sopenharmony_cierr_iounmap: 6608c2ecf20Sopenharmony_ci iounmap(pll_base); 6618c2ecf20Sopenharmony_ci 6628c2ecf20Sopenharmony_cierr_clk: 6638c2ecf20Sopenharmony_ci clk_put(ref_clk); 6648c2ecf20Sopenharmony_ci} 6658c2ecf20Sopenharmony_ci 6668c2ecf20Sopenharmony_ciCLK_OF_DECLARE(ar7100_clk, "qca,ar7100-pll", ath79_clocks_init_dt); 6678c2ecf20Sopenharmony_ciCLK_OF_DECLARE(ar7240_clk, "qca,ar7240-pll", ath79_clocks_init_dt); 6688c2ecf20Sopenharmony_ciCLK_OF_DECLARE(ar9130_clk, "qca,ar9130-pll", ath79_clocks_init_dt); 6698c2ecf20Sopenharmony_ciCLK_OF_DECLARE(ar9330_clk, "qca,ar9330-pll", ath79_clocks_init_dt); 6708c2ecf20Sopenharmony_ciCLK_OF_DECLARE(ar9340_clk, "qca,ar9340-pll", ath79_clocks_init_dt); 6718c2ecf20Sopenharmony_ciCLK_OF_DECLARE(ar9530_clk, "qca,qca9530-pll", ath79_clocks_init_dt); 6728c2ecf20Sopenharmony_ciCLK_OF_DECLARE(ar9550_clk, "qca,qca9550-pll", ath79_clocks_init_dt); 6738c2ecf20Sopenharmony_ciCLK_OF_DECLARE(ar9560_clk, "qca,qca9560-pll", ath79_clocks_init_dt); 674