1d4a67d9dSGabor Juhos /* 2d4a67d9dSGabor Juhos * Atheros AR71XX/AR724X/AR913X common routines 3d4a67d9dSGabor Juhos * 48889612bSGabor Juhos * Copyright (C) 2010-2011 Jaiganesh Narayanan <jnarayanan@atheros.com> 5d4a67d9dSGabor Juhos * Copyright (C) 2011 Gabor Juhos <juhosg@openwrt.org> 6d4a67d9dSGabor Juhos * 78889612bSGabor Juhos * Parts of this file are based on Atheros' 2.6.15/2.6.31 BSP 88889612bSGabor Juhos * 9d4a67d9dSGabor Juhos * This program is free software; you can redistribute it and/or modify it 10d4a67d9dSGabor Juhos * under the terms of the GNU General Public License version 2 as published 11d4a67d9dSGabor Juhos * by the Free Software Foundation. 12d4a67d9dSGabor Juhos */ 13d4a67d9dSGabor Juhos 14d4a67d9dSGabor Juhos #include <linux/kernel.h> 15d4a67d9dSGabor Juhos #include <linux/module.h> 16d4a67d9dSGabor Juhos #include <linux/init.h> 17d4a67d9dSGabor Juhos #include <linux/err.h> 18d4a67d9dSGabor Juhos #include <linux/clk.h> 192c4f1ac5SGabor Juhos #include <linux/clkdev.h> 20411520afSAlban Bedel #include <linux/clk-provider.h> 21*af5ad0deSAntony Pavlov #include <dt-bindings/clock/ath79-clk.h> 22d4a67d9dSGabor Juhos 2397541ccfSGabor Juhos #include <asm/div64.h> 2497541ccfSGabor Juhos 25d4a67d9dSGabor Juhos #include <asm/mach-ath79/ath79.h> 26d4a67d9dSGabor Juhos #include <asm/mach-ath79/ar71xx_regs.h> 27d4a67d9dSGabor Juhos #include "common.h" 28d4a67d9dSGabor Juhos 29d4a67d9dSGabor Juhos #define AR71XX_BASE_FREQ 40000000 30c338d59dSWeijie Gao #define AR724X_BASE_FREQ 40000000 31d4a67d9dSGabor Juhos 32*af5ad0deSAntony Pavlov static struct clk *clks[ATH79_CLK_END]; 336451af02SAlban Bedel static struct clk_onecell_data clk_data = { 346451af02SAlban Bedel .clks = clks, 356451af02SAlban Bedel .clk_num = ARRAY_SIZE(clks), 366451af02SAlban Bedel }; 376451af02SAlban Bedel 386451af02SAlban Bedel static struct clk *__init ath79_add_sys_clkdev( 396451af02SAlban Bedel const char *id, unsigned long rate) 402c4f1ac5SGabor Juhos { 412c4f1ac5SGabor Juhos struct clk *clk; 422c4f1ac5SGabor Juhos int err; 432c4f1ac5SGabor Juhos 44411520afSAlban Bedel clk = clk_register_fixed_rate(NULL, id, NULL, CLK_IS_ROOT, rate); 452c4f1ac5SGabor Juhos if (!clk) 462c4f1ac5SGabor Juhos panic("failed to allocate %s clock structure", id); 472c4f1ac5SGabor Juhos 482c4f1ac5SGabor Juhos err = clk_register_clkdev(clk, id, NULL); 492c4f1ac5SGabor Juhos if (err) 502c4f1ac5SGabor Juhos panic("unable to register %s clock device", id); 516451af02SAlban Bedel 526451af02SAlban Bedel return clk; 532c4f1ac5SGabor Juhos } 54d4a67d9dSGabor Juhos 55d4a67d9dSGabor Juhos static void __init ar71xx_clocks_init(void) 56d4a67d9dSGabor Juhos { 576612a688SGabor Juhos unsigned long ref_rate; 586612a688SGabor Juhos unsigned long cpu_rate; 596612a688SGabor Juhos unsigned long ddr_rate; 606612a688SGabor Juhos unsigned long ahb_rate; 61d4a67d9dSGabor Juhos u32 pll; 62d4a67d9dSGabor Juhos u32 freq; 63d4a67d9dSGabor Juhos u32 div; 64d4a67d9dSGabor Juhos 656612a688SGabor Juhos ref_rate = AR71XX_BASE_FREQ; 66d4a67d9dSGabor Juhos 67d4a67d9dSGabor Juhos pll = ath79_pll_rr(AR71XX_PLL_REG_CPU_CONFIG); 68d4a67d9dSGabor Juhos 69626a0695SAlban Bedel div = ((pll >> AR71XX_PLL_FB_SHIFT) & AR71XX_PLL_FB_MASK) + 1; 706612a688SGabor Juhos freq = div * ref_rate; 71d4a67d9dSGabor Juhos 72d4a67d9dSGabor Juhos div = ((pll >> AR71XX_CPU_DIV_SHIFT) & AR71XX_CPU_DIV_MASK) + 1; 736612a688SGabor Juhos cpu_rate = freq / div; 74d4a67d9dSGabor Juhos 75d4a67d9dSGabor Juhos div = ((pll >> AR71XX_DDR_DIV_SHIFT) & AR71XX_DDR_DIV_MASK) + 1; 766612a688SGabor Juhos ddr_rate = freq / div; 77d4a67d9dSGabor Juhos 78d4a67d9dSGabor Juhos div = (((pll >> AR71XX_AHB_DIV_SHIFT) & AR71XX_AHB_DIV_MASK) + 1) * 2; 796612a688SGabor Juhos ahb_rate = cpu_rate / div; 806612a688SGabor Juhos 812c4f1ac5SGabor Juhos ath79_add_sys_clkdev("ref", ref_rate); 82*af5ad0deSAntony Pavlov clks[ATH79_CLK_CPU] = ath79_add_sys_clkdev("cpu", cpu_rate); 83*af5ad0deSAntony Pavlov clks[ATH79_CLK_DDR] = ath79_add_sys_clkdev("ddr", ddr_rate); 84*af5ad0deSAntony Pavlov clks[ATH79_CLK_AHB] = ath79_add_sys_clkdev("ahb", ahb_rate); 85d4a67d9dSGabor Juhos 862c4f1ac5SGabor Juhos clk_add_alias("wdt", NULL, "ahb", NULL); 872c4f1ac5SGabor Juhos clk_add_alias("uart", NULL, "ahb", NULL); 88d4a67d9dSGabor Juhos } 89d4a67d9dSGabor Juhos 90d4a67d9dSGabor Juhos static void __init ar724x_clocks_init(void) 91d4a67d9dSGabor Juhos { 926612a688SGabor Juhos unsigned long ref_rate; 936612a688SGabor Juhos unsigned long cpu_rate; 946612a688SGabor Juhos unsigned long ddr_rate; 956612a688SGabor Juhos unsigned long ahb_rate; 96d4a67d9dSGabor Juhos u32 pll; 97d4a67d9dSGabor Juhos u32 freq; 98d4a67d9dSGabor Juhos u32 div; 99d4a67d9dSGabor Juhos 1006612a688SGabor Juhos ref_rate = AR724X_BASE_FREQ; 101d4a67d9dSGabor Juhos pll = ath79_pll_rr(AR724X_PLL_REG_CPU_CONFIG); 102d4a67d9dSGabor Juhos 103626a0695SAlban Bedel div = ((pll >> AR724X_PLL_FB_SHIFT) & AR724X_PLL_FB_MASK); 1046612a688SGabor Juhos freq = div * ref_rate; 105d4a67d9dSGabor Juhos 106c338d59dSWeijie Gao div = ((pll >> AR724X_PLL_REF_DIV_SHIFT) & AR724X_PLL_REF_DIV_MASK) * 2; 107c338d59dSWeijie Gao freq /= div; 108d4a67d9dSGabor Juhos 1096612a688SGabor Juhos cpu_rate = freq; 110d4a67d9dSGabor Juhos 111d4a67d9dSGabor Juhos div = ((pll >> AR724X_DDR_DIV_SHIFT) & AR724X_DDR_DIV_MASK) + 1; 1126612a688SGabor Juhos ddr_rate = freq / div; 113d4a67d9dSGabor Juhos 114d4a67d9dSGabor Juhos div = (((pll >> AR724X_AHB_DIV_SHIFT) & AR724X_AHB_DIV_MASK) + 1) * 2; 1156612a688SGabor Juhos ahb_rate = cpu_rate / div; 1166612a688SGabor Juhos 1172c4f1ac5SGabor Juhos ath79_add_sys_clkdev("ref", ref_rate); 118*af5ad0deSAntony Pavlov clks[ATH79_CLK_CPU] = ath79_add_sys_clkdev("cpu", cpu_rate); 119*af5ad0deSAntony Pavlov clks[ATH79_CLK_DDR] = ath79_add_sys_clkdev("ddr", ddr_rate); 120*af5ad0deSAntony Pavlov clks[ATH79_CLK_AHB] = ath79_add_sys_clkdev("ahb", ahb_rate); 121d4a67d9dSGabor Juhos 1222c4f1ac5SGabor Juhos clk_add_alias("wdt", NULL, "ahb", NULL); 1232c4f1ac5SGabor Juhos clk_add_alias("uart", NULL, "ahb", NULL); 124d4a67d9dSGabor Juhos } 125d4a67d9dSGabor Juhos 12604225e1dSGabor Juhos static void __init ar933x_clocks_init(void) 12704225e1dSGabor Juhos { 1286612a688SGabor Juhos unsigned long ref_rate; 1296612a688SGabor Juhos unsigned long cpu_rate; 1306612a688SGabor Juhos unsigned long ddr_rate; 1316612a688SGabor Juhos unsigned long ahb_rate; 13204225e1dSGabor Juhos u32 clock_ctrl; 13304225e1dSGabor Juhos u32 cpu_config; 13404225e1dSGabor Juhos u32 freq; 13504225e1dSGabor Juhos u32 t; 13604225e1dSGabor Juhos 13704225e1dSGabor Juhos t = ath79_reset_rr(AR933X_RESET_REG_BOOTSTRAP); 13804225e1dSGabor Juhos if (t & AR933X_BOOTSTRAP_REF_CLK_40) 1396612a688SGabor Juhos ref_rate = (40 * 1000 * 1000); 14004225e1dSGabor Juhos else 1416612a688SGabor Juhos ref_rate = (25 * 1000 * 1000); 14204225e1dSGabor Juhos 14304225e1dSGabor Juhos clock_ctrl = ath79_pll_rr(AR933X_PLL_CLOCK_CTRL_REG); 14404225e1dSGabor Juhos if (clock_ctrl & AR933X_PLL_CLOCK_CTRL_BYPASS) { 1456612a688SGabor Juhos cpu_rate = ref_rate; 1466612a688SGabor Juhos ahb_rate = ref_rate; 1476612a688SGabor Juhos ddr_rate = ref_rate; 14804225e1dSGabor Juhos } else { 14904225e1dSGabor Juhos cpu_config = ath79_pll_rr(AR933X_PLL_CPU_CONFIG_REG); 15004225e1dSGabor Juhos 15104225e1dSGabor Juhos t = (cpu_config >> AR933X_PLL_CPU_CONFIG_REFDIV_SHIFT) & 15204225e1dSGabor Juhos AR933X_PLL_CPU_CONFIG_REFDIV_MASK; 1536612a688SGabor Juhos freq = ref_rate / t; 15404225e1dSGabor Juhos 15504225e1dSGabor Juhos t = (cpu_config >> AR933X_PLL_CPU_CONFIG_NINT_SHIFT) & 15604225e1dSGabor Juhos AR933X_PLL_CPU_CONFIG_NINT_MASK; 15704225e1dSGabor Juhos freq *= t; 15804225e1dSGabor Juhos 15904225e1dSGabor Juhos t = (cpu_config >> AR933X_PLL_CPU_CONFIG_OUTDIV_SHIFT) & 16004225e1dSGabor Juhos AR933X_PLL_CPU_CONFIG_OUTDIV_MASK; 16104225e1dSGabor Juhos if (t == 0) 16204225e1dSGabor Juhos t = 1; 16304225e1dSGabor Juhos 16404225e1dSGabor Juhos freq >>= t; 16504225e1dSGabor Juhos 16604225e1dSGabor Juhos t = ((clock_ctrl >> AR933X_PLL_CLOCK_CTRL_CPU_DIV_SHIFT) & 16704225e1dSGabor Juhos AR933X_PLL_CLOCK_CTRL_CPU_DIV_MASK) + 1; 1686612a688SGabor Juhos cpu_rate = freq / t; 16904225e1dSGabor Juhos 17004225e1dSGabor Juhos t = ((clock_ctrl >> AR933X_PLL_CLOCK_CTRL_DDR_DIV_SHIFT) & 17104225e1dSGabor Juhos AR933X_PLL_CLOCK_CTRL_DDR_DIV_MASK) + 1; 1726612a688SGabor Juhos ddr_rate = freq / t; 17304225e1dSGabor Juhos 17404225e1dSGabor Juhos t = ((clock_ctrl >> AR933X_PLL_CLOCK_CTRL_AHB_DIV_SHIFT) & 17504225e1dSGabor Juhos AR933X_PLL_CLOCK_CTRL_AHB_DIV_MASK) + 1; 1766612a688SGabor Juhos ahb_rate = freq / t; 17704225e1dSGabor Juhos } 17804225e1dSGabor Juhos 1792c4f1ac5SGabor Juhos ath79_add_sys_clkdev("ref", ref_rate); 180*af5ad0deSAntony Pavlov clks[ATH79_CLK_CPU] = ath79_add_sys_clkdev("cpu", cpu_rate); 181*af5ad0deSAntony Pavlov clks[ATH79_CLK_DDR] = ath79_add_sys_clkdev("ddr", ddr_rate); 182*af5ad0deSAntony Pavlov clks[ATH79_CLK_AHB] = ath79_add_sys_clkdev("ahb", ahb_rate); 1836612a688SGabor Juhos 1842c4f1ac5SGabor Juhos clk_add_alias("wdt", NULL, "ahb", NULL); 1852c4f1ac5SGabor Juhos clk_add_alias("uart", NULL, "ref", NULL); 18604225e1dSGabor Juhos } 18704225e1dSGabor Juhos 18897541ccfSGabor Juhos static u32 __init ar934x_get_pll_freq(u32 ref, u32 ref_div, u32 nint, u32 nfrac, 18997541ccfSGabor Juhos u32 frac, u32 out_div) 19097541ccfSGabor Juhos { 19197541ccfSGabor Juhos u64 t; 19297541ccfSGabor Juhos u32 ret; 19397541ccfSGabor Juhos 194837f036cSGabor Juhos t = ref; 19597541ccfSGabor Juhos t *= nint; 19697541ccfSGabor Juhos do_div(t, ref_div); 19797541ccfSGabor Juhos ret = t; 19897541ccfSGabor Juhos 199837f036cSGabor Juhos t = ref; 20097541ccfSGabor Juhos t *= nfrac; 20197541ccfSGabor Juhos do_div(t, ref_div * frac); 20297541ccfSGabor Juhos ret += t; 20397541ccfSGabor Juhos 20497541ccfSGabor Juhos ret /= (1 << out_div); 20597541ccfSGabor Juhos return ret; 20697541ccfSGabor Juhos } 20797541ccfSGabor Juhos 2088889612bSGabor Juhos static void __init ar934x_clocks_init(void) 2098889612bSGabor Juhos { 2106612a688SGabor Juhos unsigned long ref_rate; 2116612a688SGabor Juhos unsigned long cpu_rate; 2126612a688SGabor Juhos unsigned long ddr_rate; 2136612a688SGabor Juhos unsigned long ahb_rate; 21497541ccfSGabor Juhos u32 pll, out_div, ref_div, nint, nfrac, frac, clk_ctrl, postdiv; 2158889612bSGabor Juhos u32 cpu_pll, ddr_pll; 2168889612bSGabor Juhos u32 bootstrap; 21797541ccfSGabor Juhos void __iomem *dpll_base; 21897541ccfSGabor Juhos 21997541ccfSGabor Juhos dpll_base = ioremap(AR934X_SRIF_BASE, AR934X_SRIF_SIZE); 2208889612bSGabor Juhos 2218889612bSGabor Juhos bootstrap = ath79_reset_rr(AR934X_RESET_REG_BOOTSTRAP); 2228889612bSGabor Juhos if (bootstrap & AR934X_BOOTSTRAP_REF_CLK_40) 2236612a688SGabor Juhos ref_rate = 40 * 1000 * 1000; 2248889612bSGabor Juhos else 2256612a688SGabor Juhos ref_rate = 25 * 1000 * 1000; 2268889612bSGabor Juhos 22797541ccfSGabor Juhos pll = __raw_readl(dpll_base + AR934X_SRIF_CPU_DPLL2_REG); 22897541ccfSGabor Juhos if (pll & AR934X_SRIF_DPLL2_LOCAL_PLL) { 22997541ccfSGabor Juhos out_div = (pll >> AR934X_SRIF_DPLL2_OUTDIV_SHIFT) & 23097541ccfSGabor Juhos AR934X_SRIF_DPLL2_OUTDIV_MASK; 23197541ccfSGabor Juhos pll = __raw_readl(dpll_base + AR934X_SRIF_CPU_DPLL1_REG); 23297541ccfSGabor Juhos nint = (pll >> AR934X_SRIF_DPLL1_NINT_SHIFT) & 23397541ccfSGabor Juhos AR934X_SRIF_DPLL1_NINT_MASK; 23497541ccfSGabor Juhos nfrac = pll & AR934X_SRIF_DPLL1_NFRAC_MASK; 23597541ccfSGabor Juhos ref_div = (pll >> AR934X_SRIF_DPLL1_REFDIV_SHIFT) & 23697541ccfSGabor Juhos AR934X_SRIF_DPLL1_REFDIV_MASK; 23797541ccfSGabor Juhos frac = 1 << 18; 23897541ccfSGabor Juhos } else { 2398889612bSGabor Juhos pll = ath79_pll_rr(AR934X_PLL_CPU_CONFIG_REG); 2408889612bSGabor Juhos out_div = (pll >> AR934X_PLL_CPU_CONFIG_OUTDIV_SHIFT) & 2418889612bSGabor Juhos AR934X_PLL_CPU_CONFIG_OUTDIV_MASK; 2428889612bSGabor Juhos ref_div = (pll >> AR934X_PLL_CPU_CONFIG_REFDIV_SHIFT) & 2438889612bSGabor Juhos AR934X_PLL_CPU_CONFIG_REFDIV_MASK; 2448889612bSGabor Juhos nint = (pll >> AR934X_PLL_CPU_CONFIG_NINT_SHIFT) & 2458889612bSGabor Juhos AR934X_PLL_CPU_CONFIG_NINT_MASK; 24697541ccfSGabor Juhos nfrac = (pll >> AR934X_PLL_CPU_CONFIG_NFRAC_SHIFT) & 2478889612bSGabor Juhos AR934X_PLL_CPU_CONFIG_NFRAC_MASK; 24897541ccfSGabor Juhos frac = 1 << 6; 24997541ccfSGabor Juhos } 2508889612bSGabor Juhos 2516612a688SGabor Juhos cpu_pll = ar934x_get_pll_freq(ref_rate, ref_div, nint, 25297541ccfSGabor Juhos nfrac, frac, out_div); 2538889612bSGabor Juhos 25497541ccfSGabor Juhos pll = __raw_readl(dpll_base + AR934X_SRIF_DDR_DPLL2_REG); 25597541ccfSGabor Juhos if (pll & AR934X_SRIF_DPLL2_LOCAL_PLL) { 25697541ccfSGabor Juhos out_div = (pll >> AR934X_SRIF_DPLL2_OUTDIV_SHIFT) & 25797541ccfSGabor Juhos AR934X_SRIF_DPLL2_OUTDIV_MASK; 25897541ccfSGabor Juhos pll = __raw_readl(dpll_base + AR934X_SRIF_DDR_DPLL1_REG); 25997541ccfSGabor Juhos nint = (pll >> AR934X_SRIF_DPLL1_NINT_SHIFT) & 26097541ccfSGabor Juhos AR934X_SRIF_DPLL1_NINT_MASK; 26197541ccfSGabor Juhos nfrac = pll & AR934X_SRIF_DPLL1_NFRAC_MASK; 26297541ccfSGabor Juhos ref_div = (pll >> AR934X_SRIF_DPLL1_REFDIV_SHIFT) & 26397541ccfSGabor Juhos AR934X_SRIF_DPLL1_REFDIV_MASK; 26497541ccfSGabor Juhos frac = 1 << 18; 26597541ccfSGabor Juhos } else { 2668889612bSGabor Juhos pll = ath79_pll_rr(AR934X_PLL_DDR_CONFIG_REG); 2678889612bSGabor Juhos out_div = (pll >> AR934X_PLL_DDR_CONFIG_OUTDIV_SHIFT) & 2688889612bSGabor Juhos AR934X_PLL_DDR_CONFIG_OUTDIV_MASK; 2698889612bSGabor Juhos ref_div = (pll >> AR934X_PLL_DDR_CONFIG_REFDIV_SHIFT) & 2708889612bSGabor Juhos AR934X_PLL_DDR_CONFIG_REFDIV_MASK; 2718889612bSGabor Juhos nint = (pll >> AR934X_PLL_DDR_CONFIG_NINT_SHIFT) & 2728889612bSGabor Juhos AR934X_PLL_DDR_CONFIG_NINT_MASK; 27397541ccfSGabor Juhos nfrac = (pll >> AR934X_PLL_DDR_CONFIG_NFRAC_SHIFT) & 2748889612bSGabor Juhos AR934X_PLL_DDR_CONFIG_NFRAC_MASK; 27597541ccfSGabor Juhos frac = 1 << 10; 27697541ccfSGabor Juhos } 2778889612bSGabor Juhos 2786612a688SGabor Juhos ddr_pll = ar934x_get_pll_freq(ref_rate, ref_div, nint, 27997541ccfSGabor Juhos nfrac, frac, out_div); 2808889612bSGabor Juhos 2818889612bSGabor Juhos clk_ctrl = ath79_pll_rr(AR934X_PLL_CPU_DDR_CLK_CTRL_REG); 2828889612bSGabor Juhos 2838889612bSGabor Juhos postdiv = (clk_ctrl >> AR934X_PLL_CPU_DDR_CLK_CTRL_CPU_POST_DIV_SHIFT) & 2848889612bSGabor Juhos AR934X_PLL_CPU_DDR_CLK_CTRL_CPU_POST_DIV_MASK; 2858889612bSGabor Juhos 2868889612bSGabor Juhos if (clk_ctrl & AR934X_PLL_CPU_DDR_CLK_CTRL_CPU_PLL_BYPASS) 2876612a688SGabor Juhos cpu_rate = ref_rate; 2888889612bSGabor Juhos else if (clk_ctrl & AR934X_PLL_CPU_DDR_CLK_CTRL_CPUCLK_FROM_CPUPLL) 2896612a688SGabor Juhos cpu_rate = cpu_pll / (postdiv + 1); 2908889612bSGabor Juhos else 2916612a688SGabor Juhos cpu_rate = ddr_pll / (postdiv + 1); 2928889612bSGabor Juhos 2938889612bSGabor Juhos postdiv = (clk_ctrl >> AR934X_PLL_CPU_DDR_CLK_CTRL_DDR_POST_DIV_SHIFT) & 2948889612bSGabor Juhos AR934X_PLL_CPU_DDR_CLK_CTRL_DDR_POST_DIV_MASK; 2958889612bSGabor Juhos 2968889612bSGabor Juhos if (clk_ctrl & AR934X_PLL_CPU_DDR_CLK_CTRL_DDR_PLL_BYPASS) 2976612a688SGabor Juhos ddr_rate = ref_rate; 2988889612bSGabor Juhos else if (clk_ctrl & AR934X_PLL_CPU_DDR_CLK_CTRL_DDRCLK_FROM_DDRPLL) 2996612a688SGabor Juhos ddr_rate = ddr_pll / (postdiv + 1); 3008889612bSGabor Juhos else 3016612a688SGabor Juhos ddr_rate = cpu_pll / (postdiv + 1); 3028889612bSGabor Juhos 3038889612bSGabor Juhos postdiv = (clk_ctrl >> AR934X_PLL_CPU_DDR_CLK_CTRL_AHB_POST_DIV_SHIFT) & 3048889612bSGabor Juhos AR934X_PLL_CPU_DDR_CLK_CTRL_AHB_POST_DIV_MASK; 3058889612bSGabor Juhos 3068889612bSGabor Juhos if (clk_ctrl & AR934X_PLL_CPU_DDR_CLK_CTRL_AHB_PLL_BYPASS) 3076612a688SGabor Juhos ahb_rate = ref_rate; 3088889612bSGabor Juhos else if (clk_ctrl & AR934X_PLL_CPU_DDR_CLK_CTRL_AHBCLK_FROM_DDRPLL) 3096612a688SGabor Juhos ahb_rate = ddr_pll / (postdiv + 1); 3108889612bSGabor Juhos else 3116612a688SGabor Juhos ahb_rate = cpu_pll / (postdiv + 1); 3126612a688SGabor Juhos 3132c4f1ac5SGabor Juhos ath79_add_sys_clkdev("ref", ref_rate); 314*af5ad0deSAntony Pavlov clks[ATH79_CLK_CPU] = ath79_add_sys_clkdev("cpu", cpu_rate); 315*af5ad0deSAntony Pavlov clks[ATH79_CLK_DDR] = ath79_add_sys_clkdev("ddr", ddr_rate); 316*af5ad0deSAntony Pavlov clks[ATH79_CLK_AHB] = ath79_add_sys_clkdev("ahb", ahb_rate); 3178889612bSGabor Juhos 3182c4f1ac5SGabor Juhos clk_add_alias("wdt", NULL, "ref", NULL); 3192c4f1ac5SGabor Juhos clk_add_alias("uart", NULL, "ref", NULL); 32097541ccfSGabor Juhos 32197541ccfSGabor Juhos iounmap(dpll_base); 3228889612bSGabor Juhos } 3238889612bSGabor Juhos 32441583c05SGabor Juhos static void __init qca955x_clocks_init(void) 32541583c05SGabor Juhos { 3266612a688SGabor Juhos unsigned long ref_rate; 3276612a688SGabor Juhos unsigned long cpu_rate; 3286612a688SGabor Juhos unsigned long ddr_rate; 3296612a688SGabor Juhos unsigned long ahb_rate; 33041583c05SGabor Juhos u32 pll, out_div, ref_div, nint, frac, clk_ctrl, postdiv; 33141583c05SGabor Juhos u32 cpu_pll, ddr_pll; 33241583c05SGabor Juhos u32 bootstrap; 33341583c05SGabor Juhos 33441583c05SGabor Juhos bootstrap = ath79_reset_rr(QCA955X_RESET_REG_BOOTSTRAP); 33541583c05SGabor Juhos if (bootstrap & QCA955X_BOOTSTRAP_REF_CLK_40) 3366612a688SGabor Juhos ref_rate = 40 * 1000 * 1000; 33741583c05SGabor Juhos else 3386612a688SGabor Juhos ref_rate = 25 * 1000 * 1000; 33941583c05SGabor Juhos 34041583c05SGabor Juhos pll = ath79_pll_rr(QCA955X_PLL_CPU_CONFIG_REG); 34141583c05SGabor Juhos out_div = (pll >> QCA955X_PLL_CPU_CONFIG_OUTDIV_SHIFT) & 34241583c05SGabor Juhos QCA955X_PLL_CPU_CONFIG_OUTDIV_MASK; 34341583c05SGabor Juhos ref_div = (pll >> QCA955X_PLL_CPU_CONFIG_REFDIV_SHIFT) & 34441583c05SGabor Juhos QCA955X_PLL_CPU_CONFIG_REFDIV_MASK; 34541583c05SGabor Juhos nint = (pll >> QCA955X_PLL_CPU_CONFIG_NINT_SHIFT) & 34641583c05SGabor Juhos QCA955X_PLL_CPU_CONFIG_NINT_MASK; 34741583c05SGabor Juhos frac = (pll >> QCA955X_PLL_CPU_CONFIG_NFRAC_SHIFT) & 34841583c05SGabor Juhos QCA955X_PLL_CPU_CONFIG_NFRAC_MASK; 34941583c05SGabor Juhos 3506612a688SGabor Juhos cpu_pll = nint * ref_rate / ref_div; 3516612a688SGabor Juhos cpu_pll += frac * ref_rate / (ref_div * (1 << 6)); 35241583c05SGabor Juhos cpu_pll /= (1 << out_div); 35341583c05SGabor Juhos 35441583c05SGabor Juhos pll = ath79_pll_rr(QCA955X_PLL_DDR_CONFIG_REG); 35541583c05SGabor Juhos out_div = (pll >> QCA955X_PLL_DDR_CONFIG_OUTDIV_SHIFT) & 35641583c05SGabor Juhos QCA955X_PLL_DDR_CONFIG_OUTDIV_MASK; 35741583c05SGabor Juhos ref_div = (pll >> QCA955X_PLL_DDR_CONFIG_REFDIV_SHIFT) & 35841583c05SGabor Juhos QCA955X_PLL_DDR_CONFIG_REFDIV_MASK; 35941583c05SGabor Juhos nint = (pll >> QCA955X_PLL_DDR_CONFIG_NINT_SHIFT) & 36041583c05SGabor Juhos QCA955X_PLL_DDR_CONFIG_NINT_MASK; 36141583c05SGabor Juhos frac = (pll >> QCA955X_PLL_DDR_CONFIG_NFRAC_SHIFT) & 36241583c05SGabor Juhos QCA955X_PLL_DDR_CONFIG_NFRAC_MASK; 36341583c05SGabor Juhos 3646612a688SGabor Juhos ddr_pll = nint * ref_rate / ref_div; 3656612a688SGabor Juhos ddr_pll += frac * ref_rate / (ref_div * (1 << 10)); 36641583c05SGabor Juhos ddr_pll /= (1 << out_div); 36741583c05SGabor Juhos 36841583c05SGabor Juhos clk_ctrl = ath79_pll_rr(QCA955X_PLL_CLK_CTRL_REG); 36941583c05SGabor Juhos 37041583c05SGabor Juhos postdiv = (clk_ctrl >> QCA955X_PLL_CLK_CTRL_CPU_POST_DIV_SHIFT) & 37141583c05SGabor Juhos QCA955X_PLL_CLK_CTRL_CPU_POST_DIV_MASK; 37241583c05SGabor Juhos 37341583c05SGabor Juhos if (clk_ctrl & QCA955X_PLL_CLK_CTRL_CPU_PLL_BYPASS) 3746612a688SGabor Juhos cpu_rate = ref_rate; 37541583c05SGabor Juhos else if (clk_ctrl & QCA955X_PLL_CLK_CTRL_CPUCLK_FROM_CPUPLL) 3766612a688SGabor Juhos cpu_rate = ddr_pll / (postdiv + 1); 37741583c05SGabor Juhos else 3786612a688SGabor Juhos cpu_rate = cpu_pll / (postdiv + 1); 37941583c05SGabor Juhos 38041583c05SGabor Juhos postdiv = (clk_ctrl >> QCA955X_PLL_CLK_CTRL_DDR_POST_DIV_SHIFT) & 38141583c05SGabor Juhos QCA955X_PLL_CLK_CTRL_DDR_POST_DIV_MASK; 38241583c05SGabor Juhos 38341583c05SGabor Juhos if (clk_ctrl & QCA955X_PLL_CLK_CTRL_DDR_PLL_BYPASS) 3846612a688SGabor Juhos ddr_rate = ref_rate; 38541583c05SGabor Juhos else if (clk_ctrl & QCA955X_PLL_CLK_CTRL_DDRCLK_FROM_DDRPLL) 3866612a688SGabor Juhos ddr_rate = cpu_pll / (postdiv + 1); 38741583c05SGabor Juhos else 3886612a688SGabor Juhos ddr_rate = ddr_pll / (postdiv + 1); 38941583c05SGabor Juhos 39041583c05SGabor Juhos postdiv = (clk_ctrl >> QCA955X_PLL_CLK_CTRL_AHB_POST_DIV_SHIFT) & 39141583c05SGabor Juhos QCA955X_PLL_CLK_CTRL_AHB_POST_DIV_MASK; 39241583c05SGabor Juhos 39341583c05SGabor Juhos if (clk_ctrl & QCA955X_PLL_CLK_CTRL_AHB_PLL_BYPASS) 3946612a688SGabor Juhos ahb_rate = ref_rate; 39541583c05SGabor Juhos else if (clk_ctrl & QCA955X_PLL_CLK_CTRL_AHBCLK_FROM_DDRPLL) 3966612a688SGabor Juhos ahb_rate = ddr_pll / (postdiv + 1); 39741583c05SGabor Juhos else 3986612a688SGabor Juhos ahb_rate = cpu_pll / (postdiv + 1); 3996612a688SGabor Juhos 4002c4f1ac5SGabor Juhos ath79_add_sys_clkdev("ref", ref_rate); 401*af5ad0deSAntony Pavlov clks[ATH79_CLK_CPU] = ath79_add_sys_clkdev("cpu", cpu_rate); 402*af5ad0deSAntony Pavlov clks[ATH79_CLK_DDR] = ath79_add_sys_clkdev("ddr", ddr_rate); 403*af5ad0deSAntony Pavlov clks[ATH79_CLK_AHB] = ath79_add_sys_clkdev("ahb", ahb_rate); 40441583c05SGabor Juhos 4052c4f1ac5SGabor Juhos clk_add_alias("wdt", NULL, "ref", NULL); 4062c4f1ac5SGabor Juhos clk_add_alias("uart", NULL, "ref", NULL); 40741583c05SGabor Juhos } 40841583c05SGabor Juhos 409d4a67d9dSGabor Juhos void __init ath79_clocks_init(void) 410d4a67d9dSGabor Juhos { 411d4a67d9dSGabor Juhos if (soc_is_ar71xx()) 412d4a67d9dSGabor Juhos ar71xx_clocks_init(); 413f4c87b7aSAlban Bedel else if (soc_is_ar724x() || soc_is_ar913x()) 414d4a67d9dSGabor Juhos ar724x_clocks_init(); 41504225e1dSGabor Juhos else if (soc_is_ar933x()) 41604225e1dSGabor Juhos ar933x_clocks_init(); 4178889612bSGabor Juhos else if (soc_is_ar934x()) 4188889612bSGabor Juhos ar934x_clocks_init(); 41941583c05SGabor Juhos else if (soc_is_qca955x()) 42041583c05SGabor Juhos qca955x_clocks_init(); 421d4a67d9dSGabor Juhos else 422d4a67d9dSGabor Juhos BUG(); 4236451af02SAlban Bedel 4246451af02SAlban Bedel of_clk_init(NULL); 425d4a67d9dSGabor Juhos } 426d4a67d9dSGabor Juhos 42723107802SGabor Juhos unsigned long __init 42823107802SGabor Juhos ath79_get_sys_clk_rate(const char *id) 42923107802SGabor Juhos { 43023107802SGabor Juhos struct clk *clk; 43123107802SGabor Juhos unsigned long rate; 43223107802SGabor Juhos 43323107802SGabor Juhos clk = clk_get(NULL, id); 43423107802SGabor Juhos if (IS_ERR(clk)) 43523107802SGabor Juhos panic("unable to get %s clock, err=%d", id, (int) PTR_ERR(clk)); 43623107802SGabor Juhos 43723107802SGabor Juhos rate = clk_get_rate(clk); 43823107802SGabor Juhos clk_put(clk); 43923107802SGabor Juhos 44023107802SGabor Juhos return rate; 44123107802SGabor Juhos } 4426451af02SAlban Bedel 4436451af02SAlban Bedel #ifdef CONFIG_OF 4446451af02SAlban Bedel static void __init ath79_clocks_init_dt(struct device_node *np) 4456451af02SAlban Bedel { 4466451af02SAlban Bedel of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data); 4476451af02SAlban Bedel } 4486451af02SAlban Bedel 4496451af02SAlban Bedel CLK_OF_DECLARE(ar7100, "qca,ar7100-pll", ath79_clocks_init_dt); 4506451af02SAlban Bedel CLK_OF_DECLARE(ar7240, "qca,ar7240-pll", ath79_clocks_init_dt); 4516451af02SAlban Bedel CLK_OF_DECLARE(ar9130, "qca,ar9130-pll", ath79_clocks_init_dt); 4526451af02SAlban Bedel CLK_OF_DECLARE(ar9330, "qca,ar9330-pll", ath79_clocks_init_dt); 4536451af02SAlban Bedel CLK_OF_DECLARE(ar9340, "qca,ar9340-pll", ath79_clocks_init_dt); 4546451af02SAlban Bedel CLK_OF_DECLARE(ar9550, "qca,qca9550-pll", ath79_clocks_init_dt); 4556451af02SAlban Bedel #endif 456