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> 213bdf1071SAntony Pavlov #include <linux/of.h> 223bdf1071SAntony Pavlov #include <linux/of_address.h> 23af5ad0deSAntony Pavlov #include <dt-bindings/clock/ath79-clk.h> 24d4a67d9dSGabor Juhos 2597541ccfSGabor Juhos #include <asm/div64.h> 2697541ccfSGabor Juhos 27d4a67d9dSGabor Juhos #include <asm/mach-ath79/ath79.h> 28d4a67d9dSGabor Juhos #include <asm/mach-ath79/ar71xx_regs.h> 29d4a67d9dSGabor Juhos #include "common.h" 303bdf1071SAntony Pavlov #include "machtypes.h" 31d4a67d9dSGabor Juhos 32d4a67d9dSGabor Juhos #define AR71XX_BASE_FREQ 40000000 33c338d59dSWeijie Gao #define AR724X_BASE_FREQ 40000000 34d4a67d9dSGabor Juhos 35af5ad0deSAntony Pavlov static struct clk *clks[ATH79_CLK_END]; 366451af02SAlban Bedel static struct clk_onecell_data clk_data = { 376451af02SAlban Bedel .clks = clks, 386451af02SAlban Bedel .clk_num = ARRAY_SIZE(clks), 396451af02SAlban Bedel }; 406451af02SAlban Bedel 416451af02SAlban Bedel static struct clk *__init ath79_add_sys_clkdev( 426451af02SAlban Bedel const char *id, unsigned long rate) 432c4f1ac5SGabor Juhos { 442c4f1ac5SGabor Juhos struct clk *clk; 452c4f1ac5SGabor Juhos int err; 462c4f1ac5SGabor Juhos 47411520afSAlban Bedel clk = clk_register_fixed_rate(NULL, id, NULL, CLK_IS_ROOT, rate); 482c4f1ac5SGabor Juhos if (!clk) 492c4f1ac5SGabor Juhos panic("failed to allocate %s clock structure", id); 502c4f1ac5SGabor Juhos 512c4f1ac5SGabor Juhos err = clk_register_clkdev(clk, id, NULL); 522c4f1ac5SGabor Juhos if (err) 532c4f1ac5SGabor Juhos panic("unable to register %s clock device", id); 546451af02SAlban Bedel 556451af02SAlban Bedel return clk; 562c4f1ac5SGabor Juhos } 57d4a67d9dSGabor Juhos 58d4a67d9dSGabor Juhos static void __init ar71xx_clocks_init(void) 59d4a67d9dSGabor Juhos { 606612a688SGabor Juhos unsigned long ref_rate; 616612a688SGabor Juhos unsigned long cpu_rate; 626612a688SGabor Juhos unsigned long ddr_rate; 636612a688SGabor Juhos unsigned long ahb_rate; 64d4a67d9dSGabor Juhos u32 pll; 65d4a67d9dSGabor Juhos u32 freq; 66d4a67d9dSGabor Juhos u32 div; 67d4a67d9dSGabor Juhos 686612a688SGabor Juhos ref_rate = AR71XX_BASE_FREQ; 69d4a67d9dSGabor Juhos 70d4a67d9dSGabor Juhos pll = ath79_pll_rr(AR71XX_PLL_REG_CPU_CONFIG); 71d4a67d9dSGabor Juhos 72626a0695SAlban Bedel div = ((pll >> AR71XX_PLL_FB_SHIFT) & AR71XX_PLL_FB_MASK) + 1; 736612a688SGabor Juhos freq = div * ref_rate; 74d4a67d9dSGabor Juhos 75d4a67d9dSGabor Juhos div = ((pll >> AR71XX_CPU_DIV_SHIFT) & AR71XX_CPU_DIV_MASK) + 1; 766612a688SGabor Juhos cpu_rate = freq / div; 77d4a67d9dSGabor Juhos 78d4a67d9dSGabor Juhos div = ((pll >> AR71XX_DDR_DIV_SHIFT) & AR71XX_DDR_DIV_MASK) + 1; 796612a688SGabor Juhos ddr_rate = freq / div; 80d4a67d9dSGabor Juhos 81d4a67d9dSGabor Juhos div = (((pll >> AR71XX_AHB_DIV_SHIFT) & AR71XX_AHB_DIV_MASK) + 1) * 2; 826612a688SGabor Juhos ahb_rate = cpu_rate / div; 836612a688SGabor Juhos 842c4f1ac5SGabor Juhos ath79_add_sys_clkdev("ref", ref_rate); 85af5ad0deSAntony Pavlov clks[ATH79_CLK_CPU] = ath79_add_sys_clkdev("cpu", cpu_rate); 86af5ad0deSAntony Pavlov clks[ATH79_CLK_DDR] = ath79_add_sys_clkdev("ddr", ddr_rate); 87af5ad0deSAntony Pavlov clks[ATH79_CLK_AHB] = ath79_add_sys_clkdev("ahb", ahb_rate); 88d4a67d9dSGabor Juhos 892c4f1ac5SGabor Juhos clk_add_alias("wdt", NULL, "ahb", NULL); 902c4f1ac5SGabor Juhos clk_add_alias("uart", NULL, "ahb", NULL); 91d4a67d9dSGabor Juhos } 92d4a67d9dSGabor Juhos 933bdf1071SAntony Pavlov static struct clk * __init ath79_reg_ffclk(const char *name, 943bdf1071SAntony Pavlov const char *parent_name, unsigned int mult, unsigned int div) 953bdf1071SAntony Pavlov { 963bdf1071SAntony Pavlov struct clk *clk; 973bdf1071SAntony Pavlov 983bdf1071SAntony Pavlov clk = clk_register_fixed_factor(NULL, name, parent_name, 0, mult, div); 993bdf1071SAntony Pavlov if (!clk) 1003bdf1071SAntony Pavlov panic("failed to allocate %s clock structure", name); 1013bdf1071SAntony Pavlov 1023bdf1071SAntony Pavlov return clk; 1033bdf1071SAntony Pavlov } 1043bdf1071SAntony Pavlov 1053bdf1071SAntony Pavlov static void __init ar724x_clk_init(struct clk *ref_clk, void __iomem *pll_base) 1063bdf1071SAntony Pavlov { 1073bdf1071SAntony Pavlov u32 pll; 1083bdf1071SAntony Pavlov u32 mult, div, ddr_div, ahb_div; 1093bdf1071SAntony Pavlov 1103bdf1071SAntony Pavlov pll = __raw_readl(pll_base + AR724X_PLL_REG_CPU_CONFIG); 1113bdf1071SAntony Pavlov 1123bdf1071SAntony Pavlov mult = ((pll >> AR724X_PLL_FB_SHIFT) & AR724X_PLL_FB_MASK); 1133bdf1071SAntony Pavlov div = ((pll >> AR724X_PLL_REF_DIV_SHIFT) & AR724X_PLL_REF_DIV_MASK) * 2; 1143bdf1071SAntony Pavlov 1153bdf1071SAntony Pavlov ddr_div = ((pll >> AR724X_DDR_DIV_SHIFT) & AR724X_DDR_DIV_MASK) + 1; 1163bdf1071SAntony Pavlov ahb_div = (((pll >> AR724X_AHB_DIV_SHIFT) & AR724X_AHB_DIV_MASK) + 1) * 2; 1173bdf1071SAntony Pavlov 1183bdf1071SAntony Pavlov clks[ATH79_CLK_CPU] = ath79_reg_ffclk("cpu", "ref", mult, div); 1193bdf1071SAntony Pavlov clks[ATH79_CLK_DDR] = ath79_reg_ffclk("ddr", "ref", mult, div * ddr_div); 1203bdf1071SAntony Pavlov clks[ATH79_CLK_AHB] = ath79_reg_ffclk("ahb", "ref", mult, div * ahb_div); 1213bdf1071SAntony Pavlov } 1223bdf1071SAntony Pavlov 123d4a67d9dSGabor Juhos static void __init ar724x_clocks_init(void) 124d4a67d9dSGabor Juhos { 1253bdf1071SAntony Pavlov struct clk *ref_clk; 126d4a67d9dSGabor Juhos 1273bdf1071SAntony Pavlov ref_clk = ath79_add_sys_clkdev("ref", AR724X_BASE_FREQ); 128d4a67d9dSGabor Juhos 1293bdf1071SAntony Pavlov ar724x_clk_init(ref_clk, ath79_pll_base); 130d4a67d9dSGabor Juhos 1313bdf1071SAntony Pavlov /* just make happy plat_time_init() from arch/mips/ath79/setup.c */ 1323bdf1071SAntony Pavlov clk_register_clkdev(clks[ATH79_CLK_CPU], "cpu", NULL); 1333bdf1071SAntony Pavlov clk_register_clkdev(clks[ATH79_CLK_DDR], "ddr", NULL); 1343bdf1071SAntony Pavlov clk_register_clkdev(clks[ATH79_CLK_AHB], "ahb", NULL); 135d4a67d9dSGabor Juhos 1362c4f1ac5SGabor Juhos clk_add_alias("wdt", NULL, "ahb", NULL); 1372c4f1ac5SGabor Juhos clk_add_alias("uart", NULL, "ahb", NULL); 138d4a67d9dSGabor Juhos } 139d4a67d9dSGabor Juhos 140*5ae5c452SAntony Pavlov static void __init ar9330_clk_init(struct clk *ref_clk, void __iomem *pll_base) 141*5ae5c452SAntony Pavlov { 142*5ae5c452SAntony Pavlov u32 clock_ctrl; 143*5ae5c452SAntony Pavlov u32 ref_div; 144*5ae5c452SAntony Pavlov u32 ninit_mul; 145*5ae5c452SAntony Pavlov u32 out_div; 146*5ae5c452SAntony Pavlov 147*5ae5c452SAntony Pavlov u32 cpu_div; 148*5ae5c452SAntony Pavlov u32 ddr_div; 149*5ae5c452SAntony Pavlov u32 ahb_div; 150*5ae5c452SAntony Pavlov 151*5ae5c452SAntony Pavlov clock_ctrl = __raw_readl(pll_base + AR933X_PLL_CLOCK_CTRL_REG); 152*5ae5c452SAntony Pavlov if (clock_ctrl & AR933X_PLL_CLOCK_CTRL_BYPASS) { 153*5ae5c452SAntony Pavlov ref_div = 1; 154*5ae5c452SAntony Pavlov ninit_mul = 1; 155*5ae5c452SAntony Pavlov out_div = 1; 156*5ae5c452SAntony Pavlov 157*5ae5c452SAntony Pavlov cpu_div = 1; 158*5ae5c452SAntony Pavlov ddr_div = 1; 159*5ae5c452SAntony Pavlov ahb_div = 1; 160*5ae5c452SAntony Pavlov } else { 161*5ae5c452SAntony Pavlov u32 cpu_config; 162*5ae5c452SAntony Pavlov u32 t; 163*5ae5c452SAntony Pavlov 164*5ae5c452SAntony Pavlov cpu_config = __raw_readl(pll_base + AR933X_PLL_CPU_CONFIG_REG); 165*5ae5c452SAntony Pavlov 166*5ae5c452SAntony Pavlov t = (cpu_config >> AR933X_PLL_CPU_CONFIG_REFDIV_SHIFT) & 167*5ae5c452SAntony Pavlov AR933X_PLL_CPU_CONFIG_REFDIV_MASK; 168*5ae5c452SAntony Pavlov ref_div = t; 169*5ae5c452SAntony Pavlov 170*5ae5c452SAntony Pavlov ninit_mul = (cpu_config >> AR933X_PLL_CPU_CONFIG_NINT_SHIFT) & 171*5ae5c452SAntony Pavlov AR933X_PLL_CPU_CONFIG_NINT_MASK; 172*5ae5c452SAntony Pavlov 173*5ae5c452SAntony Pavlov t = (cpu_config >> AR933X_PLL_CPU_CONFIG_OUTDIV_SHIFT) & 174*5ae5c452SAntony Pavlov AR933X_PLL_CPU_CONFIG_OUTDIV_MASK; 175*5ae5c452SAntony Pavlov if (t == 0) 176*5ae5c452SAntony Pavlov t = 1; 177*5ae5c452SAntony Pavlov 178*5ae5c452SAntony Pavlov out_div = (1 << t); 179*5ae5c452SAntony Pavlov 180*5ae5c452SAntony Pavlov cpu_div = ((clock_ctrl >> AR933X_PLL_CLOCK_CTRL_CPU_DIV_SHIFT) & 181*5ae5c452SAntony Pavlov AR933X_PLL_CLOCK_CTRL_CPU_DIV_MASK) + 1; 182*5ae5c452SAntony Pavlov 183*5ae5c452SAntony Pavlov ddr_div = ((clock_ctrl >> AR933X_PLL_CLOCK_CTRL_DDR_DIV_SHIFT) & 184*5ae5c452SAntony Pavlov AR933X_PLL_CLOCK_CTRL_DDR_DIV_MASK) + 1; 185*5ae5c452SAntony Pavlov 186*5ae5c452SAntony Pavlov ahb_div = ((clock_ctrl >> AR933X_PLL_CLOCK_CTRL_AHB_DIV_SHIFT) & 187*5ae5c452SAntony Pavlov AR933X_PLL_CLOCK_CTRL_AHB_DIV_MASK) + 1; 188*5ae5c452SAntony Pavlov } 189*5ae5c452SAntony Pavlov 190*5ae5c452SAntony Pavlov clks[ATH79_CLK_CPU] = ath79_reg_ffclk("cpu", "ref", 191*5ae5c452SAntony Pavlov ninit_mul, ref_div * out_div * cpu_div); 192*5ae5c452SAntony Pavlov clks[ATH79_CLK_DDR] = ath79_reg_ffclk("ddr", "ref", 193*5ae5c452SAntony Pavlov ninit_mul, ref_div * out_div * ddr_div); 194*5ae5c452SAntony Pavlov clks[ATH79_CLK_AHB] = ath79_reg_ffclk("ahb", "ref", 195*5ae5c452SAntony Pavlov ninit_mul, ref_div * out_div * ahb_div); 196*5ae5c452SAntony Pavlov } 197*5ae5c452SAntony Pavlov 19804225e1dSGabor Juhos static void __init ar933x_clocks_init(void) 19904225e1dSGabor Juhos { 200*5ae5c452SAntony Pavlov struct clk *ref_clk; 2016612a688SGabor Juhos unsigned long ref_rate; 20204225e1dSGabor Juhos u32 t; 20304225e1dSGabor Juhos 20404225e1dSGabor Juhos t = ath79_reset_rr(AR933X_RESET_REG_BOOTSTRAP); 20504225e1dSGabor Juhos if (t & AR933X_BOOTSTRAP_REF_CLK_40) 2066612a688SGabor Juhos ref_rate = (40 * 1000 * 1000); 20704225e1dSGabor Juhos else 2086612a688SGabor Juhos ref_rate = (25 * 1000 * 1000); 20904225e1dSGabor Juhos 210*5ae5c452SAntony Pavlov ref_clk = ath79_add_sys_clkdev("ref", ref_rate); 21104225e1dSGabor Juhos 212*5ae5c452SAntony Pavlov ar9330_clk_init(ref_clk, ath79_pll_base); 21304225e1dSGabor Juhos 214*5ae5c452SAntony Pavlov /* just make happy plat_time_init() from arch/mips/ath79/setup.c */ 215*5ae5c452SAntony Pavlov clk_register_clkdev(clks[ATH79_CLK_CPU], "cpu", NULL); 216*5ae5c452SAntony Pavlov clk_register_clkdev(clks[ATH79_CLK_DDR], "ddr", NULL); 217*5ae5c452SAntony Pavlov clk_register_clkdev(clks[ATH79_CLK_AHB], "ahb", NULL); 2186612a688SGabor Juhos 2192c4f1ac5SGabor Juhos clk_add_alias("wdt", NULL, "ahb", NULL); 2202c4f1ac5SGabor Juhos clk_add_alias("uart", NULL, "ref", NULL); 22104225e1dSGabor Juhos } 22204225e1dSGabor Juhos 22397541ccfSGabor Juhos static u32 __init ar934x_get_pll_freq(u32 ref, u32 ref_div, u32 nint, u32 nfrac, 22497541ccfSGabor Juhos u32 frac, u32 out_div) 22597541ccfSGabor Juhos { 22697541ccfSGabor Juhos u64 t; 22797541ccfSGabor Juhos u32 ret; 22897541ccfSGabor Juhos 229837f036cSGabor Juhos t = ref; 23097541ccfSGabor Juhos t *= nint; 23197541ccfSGabor Juhos do_div(t, ref_div); 23297541ccfSGabor Juhos ret = t; 23397541ccfSGabor Juhos 234837f036cSGabor Juhos t = ref; 23597541ccfSGabor Juhos t *= nfrac; 23697541ccfSGabor Juhos do_div(t, ref_div * frac); 23797541ccfSGabor Juhos ret += t; 23897541ccfSGabor Juhos 23997541ccfSGabor Juhos ret /= (1 << out_div); 24097541ccfSGabor Juhos return ret; 24197541ccfSGabor Juhos } 24297541ccfSGabor Juhos 2438889612bSGabor Juhos static void __init ar934x_clocks_init(void) 2448889612bSGabor Juhos { 2456612a688SGabor Juhos unsigned long ref_rate; 2466612a688SGabor Juhos unsigned long cpu_rate; 2476612a688SGabor Juhos unsigned long ddr_rate; 2486612a688SGabor Juhos unsigned long ahb_rate; 24997541ccfSGabor Juhos u32 pll, out_div, ref_div, nint, nfrac, frac, clk_ctrl, postdiv; 2508889612bSGabor Juhos u32 cpu_pll, ddr_pll; 2518889612bSGabor Juhos u32 bootstrap; 25297541ccfSGabor Juhos void __iomem *dpll_base; 25397541ccfSGabor Juhos 25497541ccfSGabor Juhos dpll_base = ioremap(AR934X_SRIF_BASE, AR934X_SRIF_SIZE); 2558889612bSGabor Juhos 2568889612bSGabor Juhos bootstrap = ath79_reset_rr(AR934X_RESET_REG_BOOTSTRAP); 2578889612bSGabor Juhos if (bootstrap & AR934X_BOOTSTRAP_REF_CLK_40) 2586612a688SGabor Juhos ref_rate = 40 * 1000 * 1000; 2598889612bSGabor Juhos else 2606612a688SGabor Juhos ref_rate = 25 * 1000 * 1000; 2618889612bSGabor Juhos 26297541ccfSGabor Juhos pll = __raw_readl(dpll_base + AR934X_SRIF_CPU_DPLL2_REG); 26397541ccfSGabor Juhos if (pll & AR934X_SRIF_DPLL2_LOCAL_PLL) { 26497541ccfSGabor Juhos out_div = (pll >> AR934X_SRIF_DPLL2_OUTDIV_SHIFT) & 26597541ccfSGabor Juhos AR934X_SRIF_DPLL2_OUTDIV_MASK; 26697541ccfSGabor Juhos pll = __raw_readl(dpll_base + AR934X_SRIF_CPU_DPLL1_REG); 26797541ccfSGabor Juhos nint = (pll >> AR934X_SRIF_DPLL1_NINT_SHIFT) & 26897541ccfSGabor Juhos AR934X_SRIF_DPLL1_NINT_MASK; 26997541ccfSGabor Juhos nfrac = pll & AR934X_SRIF_DPLL1_NFRAC_MASK; 27097541ccfSGabor Juhos ref_div = (pll >> AR934X_SRIF_DPLL1_REFDIV_SHIFT) & 27197541ccfSGabor Juhos AR934X_SRIF_DPLL1_REFDIV_MASK; 27297541ccfSGabor Juhos frac = 1 << 18; 27397541ccfSGabor Juhos } else { 2748889612bSGabor Juhos pll = ath79_pll_rr(AR934X_PLL_CPU_CONFIG_REG); 2758889612bSGabor Juhos out_div = (pll >> AR934X_PLL_CPU_CONFIG_OUTDIV_SHIFT) & 2768889612bSGabor Juhos AR934X_PLL_CPU_CONFIG_OUTDIV_MASK; 2778889612bSGabor Juhos ref_div = (pll >> AR934X_PLL_CPU_CONFIG_REFDIV_SHIFT) & 2788889612bSGabor Juhos AR934X_PLL_CPU_CONFIG_REFDIV_MASK; 2798889612bSGabor Juhos nint = (pll >> AR934X_PLL_CPU_CONFIG_NINT_SHIFT) & 2808889612bSGabor Juhos AR934X_PLL_CPU_CONFIG_NINT_MASK; 28197541ccfSGabor Juhos nfrac = (pll >> AR934X_PLL_CPU_CONFIG_NFRAC_SHIFT) & 2828889612bSGabor Juhos AR934X_PLL_CPU_CONFIG_NFRAC_MASK; 28397541ccfSGabor Juhos frac = 1 << 6; 28497541ccfSGabor Juhos } 2858889612bSGabor Juhos 2866612a688SGabor Juhos cpu_pll = ar934x_get_pll_freq(ref_rate, ref_div, nint, 28797541ccfSGabor Juhos nfrac, frac, out_div); 2888889612bSGabor Juhos 28997541ccfSGabor Juhos pll = __raw_readl(dpll_base + AR934X_SRIF_DDR_DPLL2_REG); 29097541ccfSGabor Juhos if (pll & AR934X_SRIF_DPLL2_LOCAL_PLL) { 29197541ccfSGabor Juhos out_div = (pll >> AR934X_SRIF_DPLL2_OUTDIV_SHIFT) & 29297541ccfSGabor Juhos AR934X_SRIF_DPLL2_OUTDIV_MASK; 29397541ccfSGabor Juhos pll = __raw_readl(dpll_base + AR934X_SRIF_DDR_DPLL1_REG); 29497541ccfSGabor Juhos nint = (pll >> AR934X_SRIF_DPLL1_NINT_SHIFT) & 29597541ccfSGabor Juhos AR934X_SRIF_DPLL1_NINT_MASK; 29697541ccfSGabor Juhos nfrac = pll & AR934X_SRIF_DPLL1_NFRAC_MASK; 29797541ccfSGabor Juhos ref_div = (pll >> AR934X_SRIF_DPLL1_REFDIV_SHIFT) & 29897541ccfSGabor Juhos AR934X_SRIF_DPLL1_REFDIV_MASK; 29997541ccfSGabor Juhos frac = 1 << 18; 30097541ccfSGabor Juhos } else { 3018889612bSGabor Juhos pll = ath79_pll_rr(AR934X_PLL_DDR_CONFIG_REG); 3028889612bSGabor Juhos out_div = (pll >> AR934X_PLL_DDR_CONFIG_OUTDIV_SHIFT) & 3038889612bSGabor Juhos AR934X_PLL_DDR_CONFIG_OUTDIV_MASK; 3048889612bSGabor Juhos ref_div = (pll >> AR934X_PLL_DDR_CONFIG_REFDIV_SHIFT) & 3058889612bSGabor Juhos AR934X_PLL_DDR_CONFIG_REFDIV_MASK; 3068889612bSGabor Juhos nint = (pll >> AR934X_PLL_DDR_CONFIG_NINT_SHIFT) & 3078889612bSGabor Juhos AR934X_PLL_DDR_CONFIG_NINT_MASK; 30897541ccfSGabor Juhos nfrac = (pll >> AR934X_PLL_DDR_CONFIG_NFRAC_SHIFT) & 3098889612bSGabor Juhos AR934X_PLL_DDR_CONFIG_NFRAC_MASK; 31097541ccfSGabor Juhos frac = 1 << 10; 31197541ccfSGabor Juhos } 3128889612bSGabor Juhos 3136612a688SGabor Juhos ddr_pll = ar934x_get_pll_freq(ref_rate, ref_div, nint, 31497541ccfSGabor Juhos nfrac, frac, out_div); 3158889612bSGabor Juhos 3168889612bSGabor Juhos clk_ctrl = ath79_pll_rr(AR934X_PLL_CPU_DDR_CLK_CTRL_REG); 3178889612bSGabor Juhos 3188889612bSGabor Juhos postdiv = (clk_ctrl >> AR934X_PLL_CPU_DDR_CLK_CTRL_CPU_POST_DIV_SHIFT) & 3198889612bSGabor Juhos AR934X_PLL_CPU_DDR_CLK_CTRL_CPU_POST_DIV_MASK; 3208889612bSGabor Juhos 3218889612bSGabor Juhos if (clk_ctrl & AR934X_PLL_CPU_DDR_CLK_CTRL_CPU_PLL_BYPASS) 3226612a688SGabor Juhos cpu_rate = ref_rate; 3238889612bSGabor Juhos else if (clk_ctrl & AR934X_PLL_CPU_DDR_CLK_CTRL_CPUCLK_FROM_CPUPLL) 3246612a688SGabor Juhos cpu_rate = cpu_pll / (postdiv + 1); 3258889612bSGabor Juhos else 3266612a688SGabor Juhos cpu_rate = ddr_pll / (postdiv + 1); 3278889612bSGabor Juhos 3288889612bSGabor Juhos postdiv = (clk_ctrl >> AR934X_PLL_CPU_DDR_CLK_CTRL_DDR_POST_DIV_SHIFT) & 3298889612bSGabor Juhos AR934X_PLL_CPU_DDR_CLK_CTRL_DDR_POST_DIV_MASK; 3308889612bSGabor Juhos 3318889612bSGabor Juhos if (clk_ctrl & AR934X_PLL_CPU_DDR_CLK_CTRL_DDR_PLL_BYPASS) 3326612a688SGabor Juhos ddr_rate = ref_rate; 3338889612bSGabor Juhos else if (clk_ctrl & AR934X_PLL_CPU_DDR_CLK_CTRL_DDRCLK_FROM_DDRPLL) 3346612a688SGabor Juhos ddr_rate = ddr_pll / (postdiv + 1); 3358889612bSGabor Juhos else 3366612a688SGabor Juhos ddr_rate = cpu_pll / (postdiv + 1); 3378889612bSGabor Juhos 3388889612bSGabor Juhos postdiv = (clk_ctrl >> AR934X_PLL_CPU_DDR_CLK_CTRL_AHB_POST_DIV_SHIFT) & 3398889612bSGabor Juhos AR934X_PLL_CPU_DDR_CLK_CTRL_AHB_POST_DIV_MASK; 3408889612bSGabor Juhos 3418889612bSGabor Juhos if (clk_ctrl & AR934X_PLL_CPU_DDR_CLK_CTRL_AHB_PLL_BYPASS) 3426612a688SGabor Juhos ahb_rate = ref_rate; 3438889612bSGabor Juhos else if (clk_ctrl & AR934X_PLL_CPU_DDR_CLK_CTRL_AHBCLK_FROM_DDRPLL) 3446612a688SGabor Juhos ahb_rate = ddr_pll / (postdiv + 1); 3458889612bSGabor Juhos else 3466612a688SGabor Juhos ahb_rate = cpu_pll / (postdiv + 1); 3476612a688SGabor Juhos 3482c4f1ac5SGabor Juhos ath79_add_sys_clkdev("ref", ref_rate); 349af5ad0deSAntony Pavlov clks[ATH79_CLK_CPU] = ath79_add_sys_clkdev("cpu", cpu_rate); 350af5ad0deSAntony Pavlov clks[ATH79_CLK_DDR] = ath79_add_sys_clkdev("ddr", ddr_rate); 351af5ad0deSAntony Pavlov clks[ATH79_CLK_AHB] = ath79_add_sys_clkdev("ahb", ahb_rate); 3528889612bSGabor Juhos 3532c4f1ac5SGabor Juhos clk_add_alias("wdt", NULL, "ref", NULL); 3542c4f1ac5SGabor Juhos clk_add_alias("uart", NULL, "ref", NULL); 35597541ccfSGabor Juhos 35697541ccfSGabor Juhos iounmap(dpll_base); 3578889612bSGabor Juhos } 3588889612bSGabor Juhos 35941583c05SGabor Juhos static void __init qca955x_clocks_init(void) 36041583c05SGabor Juhos { 3616612a688SGabor Juhos unsigned long ref_rate; 3626612a688SGabor Juhos unsigned long cpu_rate; 3636612a688SGabor Juhos unsigned long ddr_rate; 3646612a688SGabor Juhos unsigned long ahb_rate; 36541583c05SGabor Juhos u32 pll, out_div, ref_div, nint, frac, clk_ctrl, postdiv; 36641583c05SGabor Juhos u32 cpu_pll, ddr_pll; 36741583c05SGabor Juhos u32 bootstrap; 36841583c05SGabor Juhos 36941583c05SGabor Juhos bootstrap = ath79_reset_rr(QCA955X_RESET_REG_BOOTSTRAP); 37041583c05SGabor Juhos if (bootstrap & QCA955X_BOOTSTRAP_REF_CLK_40) 3716612a688SGabor Juhos ref_rate = 40 * 1000 * 1000; 37241583c05SGabor Juhos else 3736612a688SGabor Juhos ref_rate = 25 * 1000 * 1000; 37441583c05SGabor Juhos 37541583c05SGabor Juhos pll = ath79_pll_rr(QCA955X_PLL_CPU_CONFIG_REG); 37641583c05SGabor Juhos out_div = (pll >> QCA955X_PLL_CPU_CONFIG_OUTDIV_SHIFT) & 37741583c05SGabor Juhos QCA955X_PLL_CPU_CONFIG_OUTDIV_MASK; 37841583c05SGabor Juhos ref_div = (pll >> QCA955X_PLL_CPU_CONFIG_REFDIV_SHIFT) & 37941583c05SGabor Juhos QCA955X_PLL_CPU_CONFIG_REFDIV_MASK; 38041583c05SGabor Juhos nint = (pll >> QCA955X_PLL_CPU_CONFIG_NINT_SHIFT) & 38141583c05SGabor Juhos QCA955X_PLL_CPU_CONFIG_NINT_MASK; 38241583c05SGabor Juhos frac = (pll >> QCA955X_PLL_CPU_CONFIG_NFRAC_SHIFT) & 38341583c05SGabor Juhos QCA955X_PLL_CPU_CONFIG_NFRAC_MASK; 38441583c05SGabor Juhos 3856612a688SGabor Juhos cpu_pll = nint * ref_rate / ref_div; 3866612a688SGabor Juhos cpu_pll += frac * ref_rate / (ref_div * (1 << 6)); 38741583c05SGabor Juhos cpu_pll /= (1 << out_div); 38841583c05SGabor Juhos 38941583c05SGabor Juhos pll = ath79_pll_rr(QCA955X_PLL_DDR_CONFIG_REG); 39041583c05SGabor Juhos out_div = (pll >> QCA955X_PLL_DDR_CONFIG_OUTDIV_SHIFT) & 39141583c05SGabor Juhos QCA955X_PLL_DDR_CONFIG_OUTDIV_MASK; 39241583c05SGabor Juhos ref_div = (pll >> QCA955X_PLL_DDR_CONFIG_REFDIV_SHIFT) & 39341583c05SGabor Juhos QCA955X_PLL_DDR_CONFIG_REFDIV_MASK; 39441583c05SGabor Juhos nint = (pll >> QCA955X_PLL_DDR_CONFIG_NINT_SHIFT) & 39541583c05SGabor Juhos QCA955X_PLL_DDR_CONFIG_NINT_MASK; 39641583c05SGabor Juhos frac = (pll >> QCA955X_PLL_DDR_CONFIG_NFRAC_SHIFT) & 39741583c05SGabor Juhos QCA955X_PLL_DDR_CONFIG_NFRAC_MASK; 39841583c05SGabor Juhos 3996612a688SGabor Juhos ddr_pll = nint * ref_rate / ref_div; 4006612a688SGabor Juhos ddr_pll += frac * ref_rate / (ref_div * (1 << 10)); 40141583c05SGabor Juhos ddr_pll /= (1 << out_div); 40241583c05SGabor Juhos 40341583c05SGabor Juhos clk_ctrl = ath79_pll_rr(QCA955X_PLL_CLK_CTRL_REG); 40441583c05SGabor Juhos 40541583c05SGabor Juhos postdiv = (clk_ctrl >> QCA955X_PLL_CLK_CTRL_CPU_POST_DIV_SHIFT) & 40641583c05SGabor Juhos QCA955X_PLL_CLK_CTRL_CPU_POST_DIV_MASK; 40741583c05SGabor Juhos 40841583c05SGabor Juhos if (clk_ctrl & QCA955X_PLL_CLK_CTRL_CPU_PLL_BYPASS) 4096612a688SGabor Juhos cpu_rate = ref_rate; 41041583c05SGabor Juhos else if (clk_ctrl & QCA955X_PLL_CLK_CTRL_CPUCLK_FROM_CPUPLL) 4116612a688SGabor Juhos cpu_rate = ddr_pll / (postdiv + 1); 41241583c05SGabor Juhos else 4136612a688SGabor Juhos cpu_rate = cpu_pll / (postdiv + 1); 41441583c05SGabor Juhos 41541583c05SGabor Juhos postdiv = (clk_ctrl >> QCA955X_PLL_CLK_CTRL_DDR_POST_DIV_SHIFT) & 41641583c05SGabor Juhos QCA955X_PLL_CLK_CTRL_DDR_POST_DIV_MASK; 41741583c05SGabor Juhos 41841583c05SGabor Juhos if (clk_ctrl & QCA955X_PLL_CLK_CTRL_DDR_PLL_BYPASS) 4196612a688SGabor Juhos ddr_rate = ref_rate; 42041583c05SGabor Juhos else if (clk_ctrl & QCA955X_PLL_CLK_CTRL_DDRCLK_FROM_DDRPLL) 4216612a688SGabor Juhos ddr_rate = cpu_pll / (postdiv + 1); 42241583c05SGabor Juhos else 4236612a688SGabor Juhos ddr_rate = ddr_pll / (postdiv + 1); 42441583c05SGabor Juhos 42541583c05SGabor Juhos postdiv = (clk_ctrl >> QCA955X_PLL_CLK_CTRL_AHB_POST_DIV_SHIFT) & 42641583c05SGabor Juhos QCA955X_PLL_CLK_CTRL_AHB_POST_DIV_MASK; 42741583c05SGabor Juhos 42841583c05SGabor Juhos if (clk_ctrl & QCA955X_PLL_CLK_CTRL_AHB_PLL_BYPASS) 4296612a688SGabor Juhos ahb_rate = ref_rate; 43041583c05SGabor Juhos else if (clk_ctrl & QCA955X_PLL_CLK_CTRL_AHBCLK_FROM_DDRPLL) 4316612a688SGabor Juhos ahb_rate = ddr_pll / (postdiv + 1); 43241583c05SGabor Juhos else 4336612a688SGabor Juhos ahb_rate = cpu_pll / (postdiv + 1); 4346612a688SGabor Juhos 4352c4f1ac5SGabor Juhos ath79_add_sys_clkdev("ref", ref_rate); 436af5ad0deSAntony Pavlov clks[ATH79_CLK_CPU] = ath79_add_sys_clkdev("cpu", cpu_rate); 437af5ad0deSAntony Pavlov clks[ATH79_CLK_DDR] = ath79_add_sys_clkdev("ddr", ddr_rate); 438af5ad0deSAntony Pavlov clks[ATH79_CLK_AHB] = ath79_add_sys_clkdev("ahb", ahb_rate); 43941583c05SGabor Juhos 4402c4f1ac5SGabor Juhos clk_add_alias("wdt", NULL, "ref", NULL); 4412c4f1ac5SGabor Juhos clk_add_alias("uart", NULL, "ref", NULL); 44241583c05SGabor Juhos } 44341583c05SGabor Juhos 444d4a67d9dSGabor Juhos void __init ath79_clocks_init(void) 445d4a67d9dSGabor Juhos { 446d4a67d9dSGabor Juhos if (soc_is_ar71xx()) 447d4a67d9dSGabor Juhos ar71xx_clocks_init(); 448f4c87b7aSAlban Bedel else if (soc_is_ar724x() || soc_is_ar913x()) 449d4a67d9dSGabor Juhos ar724x_clocks_init(); 45004225e1dSGabor Juhos else if (soc_is_ar933x()) 45104225e1dSGabor Juhos ar933x_clocks_init(); 4528889612bSGabor Juhos else if (soc_is_ar934x()) 4538889612bSGabor Juhos ar934x_clocks_init(); 45441583c05SGabor Juhos else if (soc_is_qca955x()) 45541583c05SGabor Juhos qca955x_clocks_init(); 456d4a67d9dSGabor Juhos else 457d4a67d9dSGabor Juhos BUG(); 458d4a67d9dSGabor Juhos } 459d4a67d9dSGabor Juhos 46023107802SGabor Juhos unsigned long __init 46123107802SGabor Juhos ath79_get_sys_clk_rate(const char *id) 46223107802SGabor Juhos { 46323107802SGabor Juhos struct clk *clk; 46423107802SGabor Juhos unsigned long rate; 46523107802SGabor Juhos 46623107802SGabor Juhos clk = clk_get(NULL, id); 46723107802SGabor Juhos if (IS_ERR(clk)) 46823107802SGabor Juhos panic("unable to get %s clock, err=%d", id, (int) PTR_ERR(clk)); 46923107802SGabor Juhos 47023107802SGabor Juhos rate = clk_get_rate(clk); 47123107802SGabor Juhos clk_put(clk); 47223107802SGabor Juhos 47323107802SGabor Juhos return rate; 47423107802SGabor Juhos } 4756451af02SAlban Bedel 4766451af02SAlban Bedel #ifdef CONFIG_OF 4776451af02SAlban Bedel static void __init ath79_clocks_init_dt(struct device_node *np) 4786451af02SAlban Bedel { 4796451af02SAlban Bedel of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data); 4806451af02SAlban Bedel } 4816451af02SAlban Bedel 4826451af02SAlban Bedel CLK_OF_DECLARE(ar7100, "qca,ar7100-pll", ath79_clocks_init_dt); 4836451af02SAlban Bedel CLK_OF_DECLARE(ar7240, "qca,ar7240-pll", ath79_clocks_init_dt); 4846451af02SAlban Bedel CLK_OF_DECLARE(ar9340, "qca,ar9340-pll", ath79_clocks_init_dt); 4856451af02SAlban Bedel CLK_OF_DECLARE(ar9550, "qca,qca9550-pll", ath79_clocks_init_dt); 4863bdf1071SAntony Pavlov 4873bdf1071SAntony Pavlov static void __init ath79_clocks_init_dt_ng(struct device_node *np) 4883bdf1071SAntony Pavlov { 4893bdf1071SAntony Pavlov struct clk *ref_clk; 4903bdf1071SAntony Pavlov void __iomem *pll_base; 4913bdf1071SAntony Pavlov const char *dnfn = of_node_full_name(np); 4923bdf1071SAntony Pavlov 4933bdf1071SAntony Pavlov ref_clk = of_clk_get(np, 0); 4943bdf1071SAntony Pavlov if (IS_ERR(ref_clk)) { 4953bdf1071SAntony Pavlov pr_err("%s: of_clk_get failed\n", dnfn); 4963bdf1071SAntony Pavlov goto err; 4973bdf1071SAntony Pavlov } 4983bdf1071SAntony Pavlov 4993bdf1071SAntony Pavlov pll_base = of_iomap(np, 0); 5003bdf1071SAntony Pavlov if (!pll_base) { 5013bdf1071SAntony Pavlov pr_err("%s: can't map pll registers\n", dnfn); 5023bdf1071SAntony Pavlov goto err_clk; 5033bdf1071SAntony Pavlov } 5043bdf1071SAntony Pavlov 505*5ae5c452SAntony Pavlov if (of_device_is_compatible(np, "qca,ar9130-pll")) 5063bdf1071SAntony Pavlov ar724x_clk_init(ref_clk, pll_base); 507*5ae5c452SAntony Pavlov else if (of_device_is_compatible(np, "qca,ar9330-pll")) 508*5ae5c452SAntony Pavlov ar9330_clk_init(ref_clk, pll_base); 509*5ae5c452SAntony Pavlov else { 510*5ae5c452SAntony Pavlov pr_err("%s: could not find any appropriate clk_init()\n", dnfn); 511*5ae5c452SAntony Pavlov goto err_clk; 512*5ae5c452SAntony Pavlov } 5133bdf1071SAntony Pavlov 5143bdf1071SAntony Pavlov if (of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data)) { 5153bdf1071SAntony Pavlov pr_err("%s: could not register clk provider\n", dnfn); 5163bdf1071SAntony Pavlov goto err_clk; 5173bdf1071SAntony Pavlov } 5183bdf1071SAntony Pavlov 5193bdf1071SAntony Pavlov return; 5203bdf1071SAntony Pavlov 5213bdf1071SAntony Pavlov err_clk: 5223bdf1071SAntony Pavlov clk_put(ref_clk); 5233bdf1071SAntony Pavlov 5243bdf1071SAntony Pavlov err: 5253bdf1071SAntony Pavlov return; 5263bdf1071SAntony Pavlov } 5273bdf1071SAntony Pavlov CLK_OF_DECLARE(ar9130_clk, "qca,ar9130-pll", ath79_clocks_init_dt_ng); 528*5ae5c452SAntony Pavlov CLK_OF_DECLARE(ar9330_clk, "qca,ar9330-pll", ath79_clocks_init_dt_ng); 5296451af02SAlban Bedel #endif 530