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*3bdf1071SAntony Pavlov #include <linux/of.h> 22*3bdf1071SAntony 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" 30*3bdf1071SAntony 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 93*3bdf1071SAntony Pavlov static struct clk * __init ath79_reg_ffclk(const char *name, 94*3bdf1071SAntony Pavlov const char *parent_name, unsigned int mult, unsigned int div) 95*3bdf1071SAntony Pavlov { 96*3bdf1071SAntony Pavlov struct clk *clk; 97*3bdf1071SAntony Pavlov 98*3bdf1071SAntony Pavlov clk = clk_register_fixed_factor(NULL, name, parent_name, 0, mult, div); 99*3bdf1071SAntony Pavlov if (!clk) 100*3bdf1071SAntony Pavlov panic("failed to allocate %s clock structure", name); 101*3bdf1071SAntony Pavlov 102*3bdf1071SAntony Pavlov return clk; 103*3bdf1071SAntony Pavlov } 104*3bdf1071SAntony Pavlov 105*3bdf1071SAntony Pavlov static void __init ar724x_clk_init(struct clk *ref_clk, void __iomem *pll_base) 106*3bdf1071SAntony Pavlov { 107*3bdf1071SAntony Pavlov u32 pll; 108*3bdf1071SAntony Pavlov u32 mult, div, ddr_div, ahb_div; 109*3bdf1071SAntony Pavlov 110*3bdf1071SAntony Pavlov pll = __raw_readl(pll_base + AR724X_PLL_REG_CPU_CONFIG); 111*3bdf1071SAntony Pavlov 112*3bdf1071SAntony Pavlov mult = ((pll >> AR724X_PLL_FB_SHIFT) & AR724X_PLL_FB_MASK); 113*3bdf1071SAntony Pavlov div = ((pll >> AR724X_PLL_REF_DIV_SHIFT) & AR724X_PLL_REF_DIV_MASK) * 2; 114*3bdf1071SAntony Pavlov 115*3bdf1071SAntony Pavlov ddr_div = ((pll >> AR724X_DDR_DIV_SHIFT) & AR724X_DDR_DIV_MASK) + 1; 116*3bdf1071SAntony Pavlov ahb_div = (((pll >> AR724X_AHB_DIV_SHIFT) & AR724X_AHB_DIV_MASK) + 1) * 2; 117*3bdf1071SAntony Pavlov 118*3bdf1071SAntony Pavlov clks[ATH79_CLK_CPU] = ath79_reg_ffclk("cpu", "ref", mult, div); 119*3bdf1071SAntony Pavlov clks[ATH79_CLK_DDR] = ath79_reg_ffclk("ddr", "ref", mult, div * ddr_div); 120*3bdf1071SAntony Pavlov clks[ATH79_CLK_AHB] = ath79_reg_ffclk("ahb", "ref", mult, div * ahb_div); 121*3bdf1071SAntony Pavlov } 122*3bdf1071SAntony Pavlov 123d4a67d9dSGabor Juhos static void __init ar724x_clocks_init(void) 124d4a67d9dSGabor Juhos { 125*3bdf1071SAntony Pavlov struct clk *ref_clk; 126d4a67d9dSGabor Juhos 127*3bdf1071SAntony Pavlov ref_clk = ath79_add_sys_clkdev("ref", AR724X_BASE_FREQ); 128d4a67d9dSGabor Juhos 129*3bdf1071SAntony Pavlov ar724x_clk_init(ref_clk, ath79_pll_base); 130d4a67d9dSGabor Juhos 131*3bdf1071SAntony Pavlov /* just make happy plat_time_init() from arch/mips/ath79/setup.c */ 132*3bdf1071SAntony Pavlov clk_register_clkdev(clks[ATH79_CLK_CPU], "cpu", NULL); 133*3bdf1071SAntony Pavlov clk_register_clkdev(clks[ATH79_CLK_DDR], "ddr", NULL); 134*3bdf1071SAntony 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 14004225e1dSGabor Juhos static void __init ar933x_clocks_init(void) 14104225e1dSGabor Juhos { 1426612a688SGabor Juhos unsigned long ref_rate; 1436612a688SGabor Juhos unsigned long cpu_rate; 1446612a688SGabor Juhos unsigned long ddr_rate; 1456612a688SGabor Juhos unsigned long ahb_rate; 14604225e1dSGabor Juhos u32 clock_ctrl; 14704225e1dSGabor Juhos u32 cpu_config; 14804225e1dSGabor Juhos u32 freq; 14904225e1dSGabor Juhos u32 t; 15004225e1dSGabor Juhos 15104225e1dSGabor Juhos t = ath79_reset_rr(AR933X_RESET_REG_BOOTSTRAP); 15204225e1dSGabor Juhos if (t & AR933X_BOOTSTRAP_REF_CLK_40) 1536612a688SGabor Juhos ref_rate = (40 * 1000 * 1000); 15404225e1dSGabor Juhos else 1556612a688SGabor Juhos ref_rate = (25 * 1000 * 1000); 15604225e1dSGabor Juhos 15704225e1dSGabor Juhos clock_ctrl = ath79_pll_rr(AR933X_PLL_CLOCK_CTRL_REG); 15804225e1dSGabor Juhos if (clock_ctrl & AR933X_PLL_CLOCK_CTRL_BYPASS) { 1596612a688SGabor Juhos cpu_rate = ref_rate; 1606612a688SGabor Juhos ahb_rate = ref_rate; 1616612a688SGabor Juhos ddr_rate = ref_rate; 16204225e1dSGabor Juhos } else { 16304225e1dSGabor Juhos cpu_config = ath79_pll_rr(AR933X_PLL_CPU_CONFIG_REG); 16404225e1dSGabor Juhos 16504225e1dSGabor Juhos t = (cpu_config >> AR933X_PLL_CPU_CONFIG_REFDIV_SHIFT) & 16604225e1dSGabor Juhos AR933X_PLL_CPU_CONFIG_REFDIV_MASK; 1676612a688SGabor Juhos freq = ref_rate / t; 16804225e1dSGabor Juhos 16904225e1dSGabor Juhos t = (cpu_config >> AR933X_PLL_CPU_CONFIG_NINT_SHIFT) & 17004225e1dSGabor Juhos AR933X_PLL_CPU_CONFIG_NINT_MASK; 17104225e1dSGabor Juhos freq *= t; 17204225e1dSGabor Juhos 17304225e1dSGabor Juhos t = (cpu_config >> AR933X_PLL_CPU_CONFIG_OUTDIV_SHIFT) & 17404225e1dSGabor Juhos AR933X_PLL_CPU_CONFIG_OUTDIV_MASK; 17504225e1dSGabor Juhos if (t == 0) 17604225e1dSGabor Juhos t = 1; 17704225e1dSGabor Juhos 17804225e1dSGabor Juhos freq >>= t; 17904225e1dSGabor Juhos 18004225e1dSGabor Juhos t = ((clock_ctrl >> AR933X_PLL_CLOCK_CTRL_CPU_DIV_SHIFT) & 18104225e1dSGabor Juhos AR933X_PLL_CLOCK_CTRL_CPU_DIV_MASK) + 1; 1826612a688SGabor Juhos cpu_rate = freq / t; 18304225e1dSGabor Juhos 18404225e1dSGabor Juhos t = ((clock_ctrl >> AR933X_PLL_CLOCK_CTRL_DDR_DIV_SHIFT) & 18504225e1dSGabor Juhos AR933X_PLL_CLOCK_CTRL_DDR_DIV_MASK) + 1; 1866612a688SGabor Juhos ddr_rate = freq / t; 18704225e1dSGabor Juhos 18804225e1dSGabor Juhos t = ((clock_ctrl >> AR933X_PLL_CLOCK_CTRL_AHB_DIV_SHIFT) & 18904225e1dSGabor Juhos AR933X_PLL_CLOCK_CTRL_AHB_DIV_MASK) + 1; 1906612a688SGabor Juhos ahb_rate = freq / t; 19104225e1dSGabor Juhos } 19204225e1dSGabor Juhos 1932c4f1ac5SGabor Juhos ath79_add_sys_clkdev("ref", ref_rate); 194af5ad0deSAntony Pavlov clks[ATH79_CLK_CPU] = ath79_add_sys_clkdev("cpu", cpu_rate); 195af5ad0deSAntony Pavlov clks[ATH79_CLK_DDR] = ath79_add_sys_clkdev("ddr", ddr_rate); 196af5ad0deSAntony Pavlov clks[ATH79_CLK_AHB] = ath79_add_sys_clkdev("ahb", ahb_rate); 1976612a688SGabor Juhos 1982c4f1ac5SGabor Juhos clk_add_alias("wdt", NULL, "ahb", NULL); 1992c4f1ac5SGabor Juhos clk_add_alias("uart", NULL, "ref", NULL); 20004225e1dSGabor Juhos } 20104225e1dSGabor Juhos 20297541ccfSGabor Juhos static u32 __init ar934x_get_pll_freq(u32 ref, u32 ref_div, u32 nint, u32 nfrac, 20397541ccfSGabor Juhos u32 frac, u32 out_div) 20497541ccfSGabor Juhos { 20597541ccfSGabor Juhos u64 t; 20697541ccfSGabor Juhos u32 ret; 20797541ccfSGabor Juhos 208837f036cSGabor Juhos t = ref; 20997541ccfSGabor Juhos t *= nint; 21097541ccfSGabor Juhos do_div(t, ref_div); 21197541ccfSGabor Juhos ret = t; 21297541ccfSGabor Juhos 213837f036cSGabor Juhos t = ref; 21497541ccfSGabor Juhos t *= nfrac; 21597541ccfSGabor Juhos do_div(t, ref_div * frac); 21697541ccfSGabor Juhos ret += t; 21797541ccfSGabor Juhos 21897541ccfSGabor Juhos ret /= (1 << out_div); 21997541ccfSGabor Juhos return ret; 22097541ccfSGabor Juhos } 22197541ccfSGabor Juhos 2228889612bSGabor Juhos static void __init ar934x_clocks_init(void) 2238889612bSGabor Juhos { 2246612a688SGabor Juhos unsigned long ref_rate; 2256612a688SGabor Juhos unsigned long cpu_rate; 2266612a688SGabor Juhos unsigned long ddr_rate; 2276612a688SGabor Juhos unsigned long ahb_rate; 22897541ccfSGabor Juhos u32 pll, out_div, ref_div, nint, nfrac, frac, clk_ctrl, postdiv; 2298889612bSGabor Juhos u32 cpu_pll, ddr_pll; 2308889612bSGabor Juhos u32 bootstrap; 23197541ccfSGabor Juhos void __iomem *dpll_base; 23297541ccfSGabor Juhos 23397541ccfSGabor Juhos dpll_base = ioremap(AR934X_SRIF_BASE, AR934X_SRIF_SIZE); 2348889612bSGabor Juhos 2358889612bSGabor Juhos bootstrap = ath79_reset_rr(AR934X_RESET_REG_BOOTSTRAP); 2368889612bSGabor Juhos if (bootstrap & AR934X_BOOTSTRAP_REF_CLK_40) 2376612a688SGabor Juhos ref_rate = 40 * 1000 * 1000; 2388889612bSGabor Juhos else 2396612a688SGabor Juhos ref_rate = 25 * 1000 * 1000; 2408889612bSGabor Juhos 24197541ccfSGabor Juhos pll = __raw_readl(dpll_base + AR934X_SRIF_CPU_DPLL2_REG); 24297541ccfSGabor Juhos if (pll & AR934X_SRIF_DPLL2_LOCAL_PLL) { 24397541ccfSGabor Juhos out_div = (pll >> AR934X_SRIF_DPLL2_OUTDIV_SHIFT) & 24497541ccfSGabor Juhos AR934X_SRIF_DPLL2_OUTDIV_MASK; 24597541ccfSGabor Juhos pll = __raw_readl(dpll_base + AR934X_SRIF_CPU_DPLL1_REG); 24697541ccfSGabor Juhos nint = (pll >> AR934X_SRIF_DPLL1_NINT_SHIFT) & 24797541ccfSGabor Juhos AR934X_SRIF_DPLL1_NINT_MASK; 24897541ccfSGabor Juhos nfrac = pll & AR934X_SRIF_DPLL1_NFRAC_MASK; 24997541ccfSGabor Juhos ref_div = (pll >> AR934X_SRIF_DPLL1_REFDIV_SHIFT) & 25097541ccfSGabor Juhos AR934X_SRIF_DPLL1_REFDIV_MASK; 25197541ccfSGabor Juhos frac = 1 << 18; 25297541ccfSGabor Juhos } else { 2538889612bSGabor Juhos pll = ath79_pll_rr(AR934X_PLL_CPU_CONFIG_REG); 2548889612bSGabor Juhos out_div = (pll >> AR934X_PLL_CPU_CONFIG_OUTDIV_SHIFT) & 2558889612bSGabor Juhos AR934X_PLL_CPU_CONFIG_OUTDIV_MASK; 2568889612bSGabor Juhos ref_div = (pll >> AR934X_PLL_CPU_CONFIG_REFDIV_SHIFT) & 2578889612bSGabor Juhos AR934X_PLL_CPU_CONFIG_REFDIV_MASK; 2588889612bSGabor Juhos nint = (pll >> AR934X_PLL_CPU_CONFIG_NINT_SHIFT) & 2598889612bSGabor Juhos AR934X_PLL_CPU_CONFIG_NINT_MASK; 26097541ccfSGabor Juhos nfrac = (pll >> AR934X_PLL_CPU_CONFIG_NFRAC_SHIFT) & 2618889612bSGabor Juhos AR934X_PLL_CPU_CONFIG_NFRAC_MASK; 26297541ccfSGabor Juhos frac = 1 << 6; 26397541ccfSGabor Juhos } 2648889612bSGabor Juhos 2656612a688SGabor Juhos cpu_pll = ar934x_get_pll_freq(ref_rate, ref_div, nint, 26697541ccfSGabor Juhos nfrac, frac, out_div); 2678889612bSGabor Juhos 26897541ccfSGabor Juhos pll = __raw_readl(dpll_base + AR934X_SRIF_DDR_DPLL2_REG); 26997541ccfSGabor Juhos if (pll & AR934X_SRIF_DPLL2_LOCAL_PLL) { 27097541ccfSGabor Juhos out_div = (pll >> AR934X_SRIF_DPLL2_OUTDIV_SHIFT) & 27197541ccfSGabor Juhos AR934X_SRIF_DPLL2_OUTDIV_MASK; 27297541ccfSGabor Juhos pll = __raw_readl(dpll_base + AR934X_SRIF_DDR_DPLL1_REG); 27397541ccfSGabor Juhos nint = (pll >> AR934X_SRIF_DPLL1_NINT_SHIFT) & 27497541ccfSGabor Juhos AR934X_SRIF_DPLL1_NINT_MASK; 27597541ccfSGabor Juhos nfrac = pll & AR934X_SRIF_DPLL1_NFRAC_MASK; 27697541ccfSGabor Juhos ref_div = (pll >> AR934X_SRIF_DPLL1_REFDIV_SHIFT) & 27797541ccfSGabor Juhos AR934X_SRIF_DPLL1_REFDIV_MASK; 27897541ccfSGabor Juhos frac = 1 << 18; 27997541ccfSGabor Juhos } else { 2808889612bSGabor Juhos pll = ath79_pll_rr(AR934X_PLL_DDR_CONFIG_REG); 2818889612bSGabor Juhos out_div = (pll >> AR934X_PLL_DDR_CONFIG_OUTDIV_SHIFT) & 2828889612bSGabor Juhos AR934X_PLL_DDR_CONFIG_OUTDIV_MASK; 2838889612bSGabor Juhos ref_div = (pll >> AR934X_PLL_DDR_CONFIG_REFDIV_SHIFT) & 2848889612bSGabor Juhos AR934X_PLL_DDR_CONFIG_REFDIV_MASK; 2858889612bSGabor Juhos nint = (pll >> AR934X_PLL_DDR_CONFIG_NINT_SHIFT) & 2868889612bSGabor Juhos AR934X_PLL_DDR_CONFIG_NINT_MASK; 28797541ccfSGabor Juhos nfrac = (pll >> AR934X_PLL_DDR_CONFIG_NFRAC_SHIFT) & 2888889612bSGabor Juhos AR934X_PLL_DDR_CONFIG_NFRAC_MASK; 28997541ccfSGabor Juhos frac = 1 << 10; 29097541ccfSGabor Juhos } 2918889612bSGabor Juhos 2926612a688SGabor Juhos ddr_pll = ar934x_get_pll_freq(ref_rate, ref_div, nint, 29397541ccfSGabor Juhos nfrac, frac, out_div); 2948889612bSGabor Juhos 2958889612bSGabor Juhos clk_ctrl = ath79_pll_rr(AR934X_PLL_CPU_DDR_CLK_CTRL_REG); 2968889612bSGabor Juhos 2978889612bSGabor Juhos postdiv = (clk_ctrl >> AR934X_PLL_CPU_DDR_CLK_CTRL_CPU_POST_DIV_SHIFT) & 2988889612bSGabor Juhos AR934X_PLL_CPU_DDR_CLK_CTRL_CPU_POST_DIV_MASK; 2998889612bSGabor Juhos 3008889612bSGabor Juhos if (clk_ctrl & AR934X_PLL_CPU_DDR_CLK_CTRL_CPU_PLL_BYPASS) 3016612a688SGabor Juhos cpu_rate = ref_rate; 3028889612bSGabor Juhos else if (clk_ctrl & AR934X_PLL_CPU_DDR_CLK_CTRL_CPUCLK_FROM_CPUPLL) 3036612a688SGabor Juhos cpu_rate = cpu_pll / (postdiv + 1); 3048889612bSGabor Juhos else 3056612a688SGabor Juhos cpu_rate = ddr_pll / (postdiv + 1); 3068889612bSGabor Juhos 3078889612bSGabor Juhos postdiv = (clk_ctrl >> AR934X_PLL_CPU_DDR_CLK_CTRL_DDR_POST_DIV_SHIFT) & 3088889612bSGabor Juhos AR934X_PLL_CPU_DDR_CLK_CTRL_DDR_POST_DIV_MASK; 3098889612bSGabor Juhos 3108889612bSGabor Juhos if (clk_ctrl & AR934X_PLL_CPU_DDR_CLK_CTRL_DDR_PLL_BYPASS) 3116612a688SGabor Juhos ddr_rate = ref_rate; 3128889612bSGabor Juhos else if (clk_ctrl & AR934X_PLL_CPU_DDR_CLK_CTRL_DDRCLK_FROM_DDRPLL) 3136612a688SGabor Juhos ddr_rate = ddr_pll / (postdiv + 1); 3148889612bSGabor Juhos else 3156612a688SGabor Juhos ddr_rate = cpu_pll / (postdiv + 1); 3168889612bSGabor Juhos 3178889612bSGabor Juhos postdiv = (clk_ctrl >> AR934X_PLL_CPU_DDR_CLK_CTRL_AHB_POST_DIV_SHIFT) & 3188889612bSGabor Juhos AR934X_PLL_CPU_DDR_CLK_CTRL_AHB_POST_DIV_MASK; 3198889612bSGabor Juhos 3208889612bSGabor Juhos if (clk_ctrl & AR934X_PLL_CPU_DDR_CLK_CTRL_AHB_PLL_BYPASS) 3216612a688SGabor Juhos ahb_rate = ref_rate; 3228889612bSGabor Juhos else if (clk_ctrl & AR934X_PLL_CPU_DDR_CLK_CTRL_AHBCLK_FROM_DDRPLL) 3236612a688SGabor Juhos ahb_rate = ddr_pll / (postdiv + 1); 3248889612bSGabor Juhos else 3256612a688SGabor Juhos ahb_rate = cpu_pll / (postdiv + 1); 3266612a688SGabor Juhos 3272c4f1ac5SGabor Juhos ath79_add_sys_clkdev("ref", ref_rate); 328af5ad0deSAntony Pavlov clks[ATH79_CLK_CPU] = ath79_add_sys_clkdev("cpu", cpu_rate); 329af5ad0deSAntony Pavlov clks[ATH79_CLK_DDR] = ath79_add_sys_clkdev("ddr", ddr_rate); 330af5ad0deSAntony Pavlov clks[ATH79_CLK_AHB] = ath79_add_sys_clkdev("ahb", ahb_rate); 3318889612bSGabor Juhos 3322c4f1ac5SGabor Juhos clk_add_alias("wdt", NULL, "ref", NULL); 3332c4f1ac5SGabor Juhos clk_add_alias("uart", NULL, "ref", NULL); 33497541ccfSGabor Juhos 33597541ccfSGabor Juhos iounmap(dpll_base); 3368889612bSGabor Juhos } 3378889612bSGabor Juhos 33841583c05SGabor Juhos static void __init qca955x_clocks_init(void) 33941583c05SGabor Juhos { 3406612a688SGabor Juhos unsigned long ref_rate; 3416612a688SGabor Juhos unsigned long cpu_rate; 3426612a688SGabor Juhos unsigned long ddr_rate; 3436612a688SGabor Juhos unsigned long ahb_rate; 34441583c05SGabor Juhos u32 pll, out_div, ref_div, nint, frac, clk_ctrl, postdiv; 34541583c05SGabor Juhos u32 cpu_pll, ddr_pll; 34641583c05SGabor Juhos u32 bootstrap; 34741583c05SGabor Juhos 34841583c05SGabor Juhos bootstrap = ath79_reset_rr(QCA955X_RESET_REG_BOOTSTRAP); 34941583c05SGabor Juhos if (bootstrap & QCA955X_BOOTSTRAP_REF_CLK_40) 3506612a688SGabor Juhos ref_rate = 40 * 1000 * 1000; 35141583c05SGabor Juhos else 3526612a688SGabor Juhos ref_rate = 25 * 1000 * 1000; 35341583c05SGabor Juhos 35441583c05SGabor Juhos pll = ath79_pll_rr(QCA955X_PLL_CPU_CONFIG_REG); 35541583c05SGabor Juhos out_div = (pll >> QCA955X_PLL_CPU_CONFIG_OUTDIV_SHIFT) & 35641583c05SGabor Juhos QCA955X_PLL_CPU_CONFIG_OUTDIV_MASK; 35741583c05SGabor Juhos ref_div = (pll >> QCA955X_PLL_CPU_CONFIG_REFDIV_SHIFT) & 35841583c05SGabor Juhos QCA955X_PLL_CPU_CONFIG_REFDIV_MASK; 35941583c05SGabor Juhos nint = (pll >> QCA955X_PLL_CPU_CONFIG_NINT_SHIFT) & 36041583c05SGabor Juhos QCA955X_PLL_CPU_CONFIG_NINT_MASK; 36141583c05SGabor Juhos frac = (pll >> QCA955X_PLL_CPU_CONFIG_NFRAC_SHIFT) & 36241583c05SGabor Juhos QCA955X_PLL_CPU_CONFIG_NFRAC_MASK; 36341583c05SGabor Juhos 3646612a688SGabor Juhos cpu_pll = nint * ref_rate / ref_div; 3656612a688SGabor Juhos cpu_pll += frac * ref_rate / (ref_div * (1 << 6)); 36641583c05SGabor Juhos cpu_pll /= (1 << out_div); 36741583c05SGabor Juhos 36841583c05SGabor Juhos pll = ath79_pll_rr(QCA955X_PLL_DDR_CONFIG_REG); 36941583c05SGabor Juhos out_div = (pll >> QCA955X_PLL_DDR_CONFIG_OUTDIV_SHIFT) & 37041583c05SGabor Juhos QCA955X_PLL_DDR_CONFIG_OUTDIV_MASK; 37141583c05SGabor Juhos ref_div = (pll >> QCA955X_PLL_DDR_CONFIG_REFDIV_SHIFT) & 37241583c05SGabor Juhos QCA955X_PLL_DDR_CONFIG_REFDIV_MASK; 37341583c05SGabor Juhos nint = (pll >> QCA955X_PLL_DDR_CONFIG_NINT_SHIFT) & 37441583c05SGabor Juhos QCA955X_PLL_DDR_CONFIG_NINT_MASK; 37541583c05SGabor Juhos frac = (pll >> QCA955X_PLL_DDR_CONFIG_NFRAC_SHIFT) & 37641583c05SGabor Juhos QCA955X_PLL_DDR_CONFIG_NFRAC_MASK; 37741583c05SGabor Juhos 3786612a688SGabor Juhos ddr_pll = nint * ref_rate / ref_div; 3796612a688SGabor Juhos ddr_pll += frac * ref_rate / (ref_div * (1 << 10)); 38041583c05SGabor Juhos ddr_pll /= (1 << out_div); 38141583c05SGabor Juhos 38241583c05SGabor Juhos clk_ctrl = ath79_pll_rr(QCA955X_PLL_CLK_CTRL_REG); 38341583c05SGabor Juhos 38441583c05SGabor Juhos postdiv = (clk_ctrl >> QCA955X_PLL_CLK_CTRL_CPU_POST_DIV_SHIFT) & 38541583c05SGabor Juhos QCA955X_PLL_CLK_CTRL_CPU_POST_DIV_MASK; 38641583c05SGabor Juhos 38741583c05SGabor Juhos if (clk_ctrl & QCA955X_PLL_CLK_CTRL_CPU_PLL_BYPASS) 3886612a688SGabor Juhos cpu_rate = ref_rate; 38941583c05SGabor Juhos else if (clk_ctrl & QCA955X_PLL_CLK_CTRL_CPUCLK_FROM_CPUPLL) 3906612a688SGabor Juhos cpu_rate = ddr_pll / (postdiv + 1); 39141583c05SGabor Juhos else 3926612a688SGabor Juhos cpu_rate = cpu_pll / (postdiv + 1); 39341583c05SGabor Juhos 39441583c05SGabor Juhos postdiv = (clk_ctrl >> QCA955X_PLL_CLK_CTRL_DDR_POST_DIV_SHIFT) & 39541583c05SGabor Juhos QCA955X_PLL_CLK_CTRL_DDR_POST_DIV_MASK; 39641583c05SGabor Juhos 39741583c05SGabor Juhos if (clk_ctrl & QCA955X_PLL_CLK_CTRL_DDR_PLL_BYPASS) 3986612a688SGabor Juhos ddr_rate = ref_rate; 39941583c05SGabor Juhos else if (clk_ctrl & QCA955X_PLL_CLK_CTRL_DDRCLK_FROM_DDRPLL) 4006612a688SGabor Juhos ddr_rate = cpu_pll / (postdiv + 1); 40141583c05SGabor Juhos else 4026612a688SGabor Juhos ddr_rate = ddr_pll / (postdiv + 1); 40341583c05SGabor Juhos 40441583c05SGabor Juhos postdiv = (clk_ctrl >> QCA955X_PLL_CLK_CTRL_AHB_POST_DIV_SHIFT) & 40541583c05SGabor Juhos QCA955X_PLL_CLK_CTRL_AHB_POST_DIV_MASK; 40641583c05SGabor Juhos 40741583c05SGabor Juhos if (clk_ctrl & QCA955X_PLL_CLK_CTRL_AHB_PLL_BYPASS) 4086612a688SGabor Juhos ahb_rate = ref_rate; 40941583c05SGabor Juhos else if (clk_ctrl & QCA955X_PLL_CLK_CTRL_AHBCLK_FROM_DDRPLL) 4106612a688SGabor Juhos ahb_rate = ddr_pll / (postdiv + 1); 41141583c05SGabor Juhos else 4126612a688SGabor Juhos ahb_rate = cpu_pll / (postdiv + 1); 4136612a688SGabor Juhos 4142c4f1ac5SGabor Juhos ath79_add_sys_clkdev("ref", ref_rate); 415af5ad0deSAntony Pavlov clks[ATH79_CLK_CPU] = ath79_add_sys_clkdev("cpu", cpu_rate); 416af5ad0deSAntony Pavlov clks[ATH79_CLK_DDR] = ath79_add_sys_clkdev("ddr", ddr_rate); 417af5ad0deSAntony Pavlov clks[ATH79_CLK_AHB] = ath79_add_sys_clkdev("ahb", ahb_rate); 41841583c05SGabor Juhos 4192c4f1ac5SGabor Juhos clk_add_alias("wdt", NULL, "ref", NULL); 4202c4f1ac5SGabor Juhos clk_add_alias("uart", NULL, "ref", NULL); 42141583c05SGabor Juhos } 42241583c05SGabor Juhos 423d4a67d9dSGabor Juhos void __init ath79_clocks_init(void) 424d4a67d9dSGabor Juhos { 425d4a67d9dSGabor Juhos if (soc_is_ar71xx()) 426d4a67d9dSGabor Juhos ar71xx_clocks_init(); 427f4c87b7aSAlban Bedel else if (soc_is_ar724x() || soc_is_ar913x()) 428d4a67d9dSGabor Juhos ar724x_clocks_init(); 42904225e1dSGabor Juhos else if (soc_is_ar933x()) 43004225e1dSGabor Juhos ar933x_clocks_init(); 4318889612bSGabor Juhos else if (soc_is_ar934x()) 4328889612bSGabor Juhos ar934x_clocks_init(); 43341583c05SGabor Juhos else if (soc_is_qca955x()) 43441583c05SGabor Juhos qca955x_clocks_init(); 435d4a67d9dSGabor Juhos else 436d4a67d9dSGabor Juhos BUG(); 437d4a67d9dSGabor Juhos } 438d4a67d9dSGabor Juhos 43923107802SGabor Juhos unsigned long __init 44023107802SGabor Juhos ath79_get_sys_clk_rate(const char *id) 44123107802SGabor Juhos { 44223107802SGabor Juhos struct clk *clk; 44323107802SGabor Juhos unsigned long rate; 44423107802SGabor Juhos 44523107802SGabor Juhos clk = clk_get(NULL, id); 44623107802SGabor Juhos if (IS_ERR(clk)) 44723107802SGabor Juhos panic("unable to get %s clock, err=%d", id, (int) PTR_ERR(clk)); 44823107802SGabor Juhos 44923107802SGabor Juhos rate = clk_get_rate(clk); 45023107802SGabor Juhos clk_put(clk); 45123107802SGabor Juhos 45223107802SGabor Juhos return rate; 45323107802SGabor Juhos } 4546451af02SAlban Bedel 4556451af02SAlban Bedel #ifdef CONFIG_OF 4566451af02SAlban Bedel static void __init ath79_clocks_init_dt(struct device_node *np) 4576451af02SAlban Bedel { 4586451af02SAlban Bedel of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data); 4596451af02SAlban Bedel } 4606451af02SAlban Bedel 4616451af02SAlban Bedel CLK_OF_DECLARE(ar7100, "qca,ar7100-pll", ath79_clocks_init_dt); 4626451af02SAlban Bedel CLK_OF_DECLARE(ar7240, "qca,ar7240-pll", ath79_clocks_init_dt); 4636451af02SAlban Bedel CLK_OF_DECLARE(ar9330, "qca,ar9330-pll", ath79_clocks_init_dt); 4646451af02SAlban Bedel CLK_OF_DECLARE(ar9340, "qca,ar9340-pll", ath79_clocks_init_dt); 4656451af02SAlban Bedel CLK_OF_DECLARE(ar9550, "qca,qca9550-pll", ath79_clocks_init_dt); 466*3bdf1071SAntony Pavlov 467*3bdf1071SAntony Pavlov static void __init ath79_clocks_init_dt_ng(struct device_node *np) 468*3bdf1071SAntony Pavlov { 469*3bdf1071SAntony Pavlov struct clk *ref_clk; 470*3bdf1071SAntony Pavlov void __iomem *pll_base; 471*3bdf1071SAntony Pavlov const char *dnfn = of_node_full_name(np); 472*3bdf1071SAntony Pavlov 473*3bdf1071SAntony Pavlov ref_clk = of_clk_get(np, 0); 474*3bdf1071SAntony Pavlov if (IS_ERR(ref_clk)) { 475*3bdf1071SAntony Pavlov pr_err("%s: of_clk_get failed\n", dnfn); 476*3bdf1071SAntony Pavlov goto err; 477*3bdf1071SAntony Pavlov } 478*3bdf1071SAntony Pavlov 479*3bdf1071SAntony Pavlov pll_base = of_iomap(np, 0); 480*3bdf1071SAntony Pavlov if (!pll_base) { 481*3bdf1071SAntony Pavlov pr_err("%s: can't map pll registers\n", dnfn); 482*3bdf1071SAntony Pavlov goto err_clk; 483*3bdf1071SAntony Pavlov } 484*3bdf1071SAntony Pavlov 485*3bdf1071SAntony Pavlov ar724x_clk_init(ref_clk, pll_base); 486*3bdf1071SAntony Pavlov 487*3bdf1071SAntony Pavlov if (of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data)) { 488*3bdf1071SAntony Pavlov pr_err("%s: could not register clk provider\n", dnfn); 489*3bdf1071SAntony Pavlov goto err_clk; 490*3bdf1071SAntony Pavlov } 491*3bdf1071SAntony Pavlov 492*3bdf1071SAntony Pavlov return; 493*3bdf1071SAntony Pavlov 494*3bdf1071SAntony Pavlov err_clk: 495*3bdf1071SAntony Pavlov clk_put(ref_clk); 496*3bdf1071SAntony Pavlov 497*3bdf1071SAntony Pavlov err: 498*3bdf1071SAntony Pavlov return; 499*3bdf1071SAntony Pavlov } 500*3bdf1071SAntony Pavlov CLK_OF_DECLARE(ar9130_clk, "qca,ar9130-pll", ath79_clocks_init_dt_ng); 5016451af02SAlban Bedel #endif 502