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> 20*411520afSAlban Bedel #include <linux/clk-provider.h> 21d4a67d9dSGabor Juhos 2297541ccfSGabor Juhos #include <asm/div64.h> 2397541ccfSGabor Juhos 24d4a67d9dSGabor Juhos #include <asm/mach-ath79/ath79.h> 25d4a67d9dSGabor Juhos #include <asm/mach-ath79/ar71xx_regs.h> 26d4a67d9dSGabor Juhos #include "common.h" 27d4a67d9dSGabor Juhos 28d4a67d9dSGabor Juhos #define AR71XX_BASE_FREQ 40000000 29d4a67d9dSGabor Juhos #define AR724X_BASE_FREQ 5000000 30d4a67d9dSGabor Juhos #define AR913X_BASE_FREQ 5000000 31d4a67d9dSGabor Juhos 322c4f1ac5SGabor Juhos static void __init ath79_add_sys_clkdev(const char *id, unsigned long rate) 332c4f1ac5SGabor Juhos { 342c4f1ac5SGabor Juhos struct clk *clk; 352c4f1ac5SGabor Juhos int err; 362c4f1ac5SGabor Juhos 37*411520afSAlban Bedel clk = clk_register_fixed_rate(NULL, id, NULL, CLK_IS_ROOT, rate); 382c4f1ac5SGabor Juhos if (!clk) 392c4f1ac5SGabor Juhos panic("failed to allocate %s clock structure", id); 402c4f1ac5SGabor Juhos 412c4f1ac5SGabor Juhos err = clk_register_clkdev(clk, id, NULL); 422c4f1ac5SGabor Juhos if (err) 432c4f1ac5SGabor Juhos panic("unable to register %s clock device", id); 442c4f1ac5SGabor Juhos } 45d4a67d9dSGabor Juhos 46d4a67d9dSGabor Juhos static void __init ar71xx_clocks_init(void) 47d4a67d9dSGabor Juhos { 486612a688SGabor Juhos unsigned long ref_rate; 496612a688SGabor Juhos unsigned long cpu_rate; 506612a688SGabor Juhos unsigned long ddr_rate; 516612a688SGabor Juhos unsigned long ahb_rate; 52d4a67d9dSGabor Juhos u32 pll; 53d4a67d9dSGabor Juhos u32 freq; 54d4a67d9dSGabor Juhos u32 div; 55d4a67d9dSGabor Juhos 566612a688SGabor Juhos ref_rate = AR71XX_BASE_FREQ; 57d4a67d9dSGabor Juhos 58d4a67d9dSGabor Juhos pll = ath79_pll_rr(AR71XX_PLL_REG_CPU_CONFIG); 59d4a67d9dSGabor Juhos 60626a0695SAlban Bedel div = ((pll >> AR71XX_PLL_FB_SHIFT) & AR71XX_PLL_FB_MASK) + 1; 616612a688SGabor Juhos freq = div * ref_rate; 62d4a67d9dSGabor Juhos 63d4a67d9dSGabor Juhos div = ((pll >> AR71XX_CPU_DIV_SHIFT) & AR71XX_CPU_DIV_MASK) + 1; 646612a688SGabor Juhos cpu_rate = freq / div; 65d4a67d9dSGabor Juhos 66d4a67d9dSGabor Juhos div = ((pll >> AR71XX_DDR_DIV_SHIFT) & AR71XX_DDR_DIV_MASK) + 1; 676612a688SGabor Juhos ddr_rate = freq / div; 68d4a67d9dSGabor Juhos 69d4a67d9dSGabor Juhos div = (((pll >> AR71XX_AHB_DIV_SHIFT) & AR71XX_AHB_DIV_MASK) + 1) * 2; 706612a688SGabor Juhos ahb_rate = cpu_rate / div; 716612a688SGabor Juhos 722c4f1ac5SGabor Juhos ath79_add_sys_clkdev("ref", ref_rate); 732c4f1ac5SGabor Juhos ath79_add_sys_clkdev("cpu", cpu_rate); 742c4f1ac5SGabor Juhos ath79_add_sys_clkdev("ddr", ddr_rate); 752c4f1ac5SGabor Juhos ath79_add_sys_clkdev("ahb", ahb_rate); 76d4a67d9dSGabor Juhos 772c4f1ac5SGabor Juhos clk_add_alias("wdt", NULL, "ahb", NULL); 782c4f1ac5SGabor Juhos clk_add_alias("uart", NULL, "ahb", NULL); 79d4a67d9dSGabor Juhos } 80d4a67d9dSGabor Juhos 81d4a67d9dSGabor Juhos static void __init ar724x_clocks_init(void) 82d4a67d9dSGabor Juhos { 836612a688SGabor Juhos unsigned long ref_rate; 846612a688SGabor Juhos unsigned long cpu_rate; 856612a688SGabor Juhos unsigned long ddr_rate; 866612a688SGabor Juhos unsigned long ahb_rate; 87d4a67d9dSGabor Juhos u32 pll; 88d4a67d9dSGabor Juhos u32 freq; 89d4a67d9dSGabor Juhos u32 div; 90d4a67d9dSGabor Juhos 916612a688SGabor Juhos ref_rate = AR724X_BASE_FREQ; 92d4a67d9dSGabor Juhos pll = ath79_pll_rr(AR724X_PLL_REG_CPU_CONFIG); 93d4a67d9dSGabor Juhos 94626a0695SAlban Bedel div = ((pll >> AR724X_PLL_FB_SHIFT) & AR724X_PLL_FB_MASK); 956612a688SGabor Juhos freq = div * ref_rate; 96d4a67d9dSGabor Juhos 97d4a67d9dSGabor Juhos div = ((pll >> AR724X_PLL_REF_DIV_SHIFT) & AR724X_PLL_REF_DIV_MASK); 98d4a67d9dSGabor Juhos freq *= div; 99d4a67d9dSGabor Juhos 1006612a688SGabor Juhos cpu_rate = freq; 101d4a67d9dSGabor Juhos 102d4a67d9dSGabor Juhos div = ((pll >> AR724X_DDR_DIV_SHIFT) & AR724X_DDR_DIV_MASK) + 1; 1036612a688SGabor Juhos ddr_rate = freq / div; 104d4a67d9dSGabor Juhos 105d4a67d9dSGabor Juhos div = (((pll >> AR724X_AHB_DIV_SHIFT) & AR724X_AHB_DIV_MASK) + 1) * 2; 1066612a688SGabor Juhos ahb_rate = cpu_rate / div; 1076612a688SGabor Juhos 1082c4f1ac5SGabor Juhos ath79_add_sys_clkdev("ref", ref_rate); 1092c4f1ac5SGabor Juhos ath79_add_sys_clkdev("cpu", cpu_rate); 1102c4f1ac5SGabor Juhos ath79_add_sys_clkdev("ddr", ddr_rate); 1112c4f1ac5SGabor Juhos ath79_add_sys_clkdev("ahb", ahb_rate); 112d4a67d9dSGabor Juhos 1132c4f1ac5SGabor Juhos clk_add_alias("wdt", NULL, "ahb", NULL); 1142c4f1ac5SGabor Juhos clk_add_alias("uart", NULL, "ahb", NULL); 115d4a67d9dSGabor Juhos } 116d4a67d9dSGabor Juhos 117d4a67d9dSGabor Juhos static void __init ar913x_clocks_init(void) 118d4a67d9dSGabor Juhos { 1196612a688SGabor Juhos unsigned long ref_rate; 1206612a688SGabor Juhos unsigned long cpu_rate; 1216612a688SGabor Juhos unsigned long ddr_rate; 1226612a688SGabor Juhos unsigned long ahb_rate; 123d4a67d9dSGabor Juhos u32 pll; 124d4a67d9dSGabor Juhos u32 freq; 125d4a67d9dSGabor Juhos u32 div; 126d4a67d9dSGabor Juhos 1276612a688SGabor Juhos ref_rate = AR913X_BASE_FREQ; 128d4a67d9dSGabor Juhos pll = ath79_pll_rr(AR913X_PLL_REG_CPU_CONFIG); 129d4a67d9dSGabor Juhos 130626a0695SAlban Bedel div = ((pll >> AR913X_PLL_FB_SHIFT) & AR913X_PLL_FB_MASK); 1316612a688SGabor Juhos freq = div * ref_rate; 132d4a67d9dSGabor Juhos 1336612a688SGabor Juhos cpu_rate = freq; 134d4a67d9dSGabor Juhos 135d4a67d9dSGabor Juhos div = ((pll >> AR913X_DDR_DIV_SHIFT) & AR913X_DDR_DIV_MASK) + 1; 1366612a688SGabor Juhos ddr_rate = freq / div; 137d4a67d9dSGabor Juhos 138d4a67d9dSGabor Juhos div = (((pll >> AR913X_AHB_DIV_SHIFT) & AR913X_AHB_DIV_MASK) + 1) * 2; 1396612a688SGabor Juhos ahb_rate = cpu_rate / div; 1406612a688SGabor Juhos 1412c4f1ac5SGabor Juhos ath79_add_sys_clkdev("ref", ref_rate); 1422c4f1ac5SGabor Juhos ath79_add_sys_clkdev("cpu", cpu_rate); 1432c4f1ac5SGabor Juhos ath79_add_sys_clkdev("ddr", ddr_rate); 1442c4f1ac5SGabor Juhos ath79_add_sys_clkdev("ahb", ahb_rate); 145d4a67d9dSGabor Juhos 1462c4f1ac5SGabor Juhos clk_add_alias("wdt", NULL, "ahb", NULL); 1472c4f1ac5SGabor Juhos clk_add_alias("uart", NULL, "ahb", NULL); 148d4a67d9dSGabor Juhos } 149d4a67d9dSGabor Juhos 15004225e1dSGabor Juhos static void __init ar933x_clocks_init(void) 15104225e1dSGabor Juhos { 1526612a688SGabor Juhos unsigned long ref_rate; 1536612a688SGabor Juhos unsigned long cpu_rate; 1546612a688SGabor Juhos unsigned long ddr_rate; 1556612a688SGabor Juhos unsigned long ahb_rate; 15604225e1dSGabor Juhos u32 clock_ctrl; 15704225e1dSGabor Juhos u32 cpu_config; 15804225e1dSGabor Juhos u32 freq; 15904225e1dSGabor Juhos u32 t; 16004225e1dSGabor Juhos 16104225e1dSGabor Juhos t = ath79_reset_rr(AR933X_RESET_REG_BOOTSTRAP); 16204225e1dSGabor Juhos if (t & AR933X_BOOTSTRAP_REF_CLK_40) 1636612a688SGabor Juhos ref_rate = (40 * 1000 * 1000); 16404225e1dSGabor Juhos else 1656612a688SGabor Juhos ref_rate = (25 * 1000 * 1000); 16604225e1dSGabor Juhos 16704225e1dSGabor Juhos clock_ctrl = ath79_pll_rr(AR933X_PLL_CLOCK_CTRL_REG); 16804225e1dSGabor Juhos if (clock_ctrl & AR933X_PLL_CLOCK_CTRL_BYPASS) { 1696612a688SGabor Juhos cpu_rate = ref_rate; 1706612a688SGabor Juhos ahb_rate = ref_rate; 1716612a688SGabor Juhos ddr_rate = ref_rate; 17204225e1dSGabor Juhos } else { 17304225e1dSGabor Juhos cpu_config = ath79_pll_rr(AR933X_PLL_CPU_CONFIG_REG); 17404225e1dSGabor Juhos 17504225e1dSGabor Juhos t = (cpu_config >> AR933X_PLL_CPU_CONFIG_REFDIV_SHIFT) & 17604225e1dSGabor Juhos AR933X_PLL_CPU_CONFIG_REFDIV_MASK; 1776612a688SGabor Juhos freq = ref_rate / t; 17804225e1dSGabor Juhos 17904225e1dSGabor Juhos t = (cpu_config >> AR933X_PLL_CPU_CONFIG_NINT_SHIFT) & 18004225e1dSGabor Juhos AR933X_PLL_CPU_CONFIG_NINT_MASK; 18104225e1dSGabor Juhos freq *= t; 18204225e1dSGabor Juhos 18304225e1dSGabor Juhos t = (cpu_config >> AR933X_PLL_CPU_CONFIG_OUTDIV_SHIFT) & 18404225e1dSGabor Juhos AR933X_PLL_CPU_CONFIG_OUTDIV_MASK; 18504225e1dSGabor Juhos if (t == 0) 18604225e1dSGabor Juhos t = 1; 18704225e1dSGabor Juhos 18804225e1dSGabor Juhos freq >>= t; 18904225e1dSGabor Juhos 19004225e1dSGabor Juhos t = ((clock_ctrl >> AR933X_PLL_CLOCK_CTRL_CPU_DIV_SHIFT) & 19104225e1dSGabor Juhos AR933X_PLL_CLOCK_CTRL_CPU_DIV_MASK) + 1; 1926612a688SGabor Juhos cpu_rate = freq / t; 19304225e1dSGabor Juhos 19404225e1dSGabor Juhos t = ((clock_ctrl >> AR933X_PLL_CLOCK_CTRL_DDR_DIV_SHIFT) & 19504225e1dSGabor Juhos AR933X_PLL_CLOCK_CTRL_DDR_DIV_MASK) + 1; 1966612a688SGabor Juhos ddr_rate = freq / t; 19704225e1dSGabor Juhos 19804225e1dSGabor Juhos t = ((clock_ctrl >> AR933X_PLL_CLOCK_CTRL_AHB_DIV_SHIFT) & 19904225e1dSGabor Juhos AR933X_PLL_CLOCK_CTRL_AHB_DIV_MASK) + 1; 2006612a688SGabor Juhos ahb_rate = freq / t; 20104225e1dSGabor Juhos } 20204225e1dSGabor Juhos 2032c4f1ac5SGabor Juhos ath79_add_sys_clkdev("ref", ref_rate); 2042c4f1ac5SGabor Juhos ath79_add_sys_clkdev("cpu", cpu_rate); 2052c4f1ac5SGabor Juhos ath79_add_sys_clkdev("ddr", ddr_rate); 2062c4f1ac5SGabor Juhos ath79_add_sys_clkdev("ahb", ahb_rate); 2076612a688SGabor Juhos 2082c4f1ac5SGabor Juhos clk_add_alias("wdt", NULL, "ahb", NULL); 2092c4f1ac5SGabor Juhos clk_add_alias("uart", NULL, "ref", NULL); 21004225e1dSGabor Juhos } 21104225e1dSGabor Juhos 21297541ccfSGabor Juhos static u32 __init ar934x_get_pll_freq(u32 ref, u32 ref_div, u32 nint, u32 nfrac, 21397541ccfSGabor Juhos u32 frac, u32 out_div) 21497541ccfSGabor Juhos { 21597541ccfSGabor Juhos u64 t; 21697541ccfSGabor Juhos u32 ret; 21797541ccfSGabor Juhos 218837f036cSGabor Juhos t = ref; 21997541ccfSGabor Juhos t *= nint; 22097541ccfSGabor Juhos do_div(t, ref_div); 22197541ccfSGabor Juhos ret = t; 22297541ccfSGabor Juhos 223837f036cSGabor Juhos t = ref; 22497541ccfSGabor Juhos t *= nfrac; 22597541ccfSGabor Juhos do_div(t, ref_div * frac); 22697541ccfSGabor Juhos ret += t; 22797541ccfSGabor Juhos 22897541ccfSGabor Juhos ret /= (1 << out_div); 22997541ccfSGabor Juhos return ret; 23097541ccfSGabor Juhos } 23197541ccfSGabor Juhos 2328889612bSGabor Juhos static void __init ar934x_clocks_init(void) 2338889612bSGabor Juhos { 2346612a688SGabor Juhos unsigned long ref_rate; 2356612a688SGabor Juhos unsigned long cpu_rate; 2366612a688SGabor Juhos unsigned long ddr_rate; 2376612a688SGabor Juhos unsigned long ahb_rate; 23897541ccfSGabor Juhos u32 pll, out_div, ref_div, nint, nfrac, frac, clk_ctrl, postdiv; 2398889612bSGabor Juhos u32 cpu_pll, ddr_pll; 2408889612bSGabor Juhos u32 bootstrap; 24197541ccfSGabor Juhos void __iomem *dpll_base; 24297541ccfSGabor Juhos 24397541ccfSGabor Juhos dpll_base = ioremap(AR934X_SRIF_BASE, AR934X_SRIF_SIZE); 2448889612bSGabor Juhos 2458889612bSGabor Juhos bootstrap = ath79_reset_rr(AR934X_RESET_REG_BOOTSTRAP); 2468889612bSGabor Juhos if (bootstrap & AR934X_BOOTSTRAP_REF_CLK_40) 2476612a688SGabor Juhos ref_rate = 40 * 1000 * 1000; 2488889612bSGabor Juhos else 2496612a688SGabor Juhos ref_rate = 25 * 1000 * 1000; 2508889612bSGabor Juhos 25197541ccfSGabor Juhos pll = __raw_readl(dpll_base + AR934X_SRIF_CPU_DPLL2_REG); 25297541ccfSGabor Juhos if (pll & AR934X_SRIF_DPLL2_LOCAL_PLL) { 25397541ccfSGabor Juhos out_div = (pll >> AR934X_SRIF_DPLL2_OUTDIV_SHIFT) & 25497541ccfSGabor Juhos AR934X_SRIF_DPLL2_OUTDIV_MASK; 25597541ccfSGabor Juhos pll = __raw_readl(dpll_base + AR934X_SRIF_CPU_DPLL1_REG); 25697541ccfSGabor Juhos nint = (pll >> AR934X_SRIF_DPLL1_NINT_SHIFT) & 25797541ccfSGabor Juhos AR934X_SRIF_DPLL1_NINT_MASK; 25897541ccfSGabor Juhos nfrac = pll & AR934X_SRIF_DPLL1_NFRAC_MASK; 25997541ccfSGabor Juhos ref_div = (pll >> AR934X_SRIF_DPLL1_REFDIV_SHIFT) & 26097541ccfSGabor Juhos AR934X_SRIF_DPLL1_REFDIV_MASK; 26197541ccfSGabor Juhos frac = 1 << 18; 26297541ccfSGabor Juhos } else { 2638889612bSGabor Juhos pll = ath79_pll_rr(AR934X_PLL_CPU_CONFIG_REG); 2648889612bSGabor Juhos out_div = (pll >> AR934X_PLL_CPU_CONFIG_OUTDIV_SHIFT) & 2658889612bSGabor Juhos AR934X_PLL_CPU_CONFIG_OUTDIV_MASK; 2668889612bSGabor Juhos ref_div = (pll >> AR934X_PLL_CPU_CONFIG_REFDIV_SHIFT) & 2678889612bSGabor Juhos AR934X_PLL_CPU_CONFIG_REFDIV_MASK; 2688889612bSGabor Juhos nint = (pll >> AR934X_PLL_CPU_CONFIG_NINT_SHIFT) & 2698889612bSGabor Juhos AR934X_PLL_CPU_CONFIG_NINT_MASK; 27097541ccfSGabor Juhos nfrac = (pll >> AR934X_PLL_CPU_CONFIG_NFRAC_SHIFT) & 2718889612bSGabor Juhos AR934X_PLL_CPU_CONFIG_NFRAC_MASK; 27297541ccfSGabor Juhos frac = 1 << 6; 27397541ccfSGabor Juhos } 2748889612bSGabor Juhos 2756612a688SGabor Juhos cpu_pll = ar934x_get_pll_freq(ref_rate, ref_div, nint, 27697541ccfSGabor Juhos nfrac, frac, out_div); 2778889612bSGabor Juhos 27897541ccfSGabor Juhos pll = __raw_readl(dpll_base + AR934X_SRIF_DDR_DPLL2_REG); 27997541ccfSGabor Juhos if (pll & AR934X_SRIF_DPLL2_LOCAL_PLL) { 28097541ccfSGabor Juhos out_div = (pll >> AR934X_SRIF_DPLL2_OUTDIV_SHIFT) & 28197541ccfSGabor Juhos AR934X_SRIF_DPLL2_OUTDIV_MASK; 28297541ccfSGabor Juhos pll = __raw_readl(dpll_base + AR934X_SRIF_DDR_DPLL1_REG); 28397541ccfSGabor Juhos nint = (pll >> AR934X_SRIF_DPLL1_NINT_SHIFT) & 28497541ccfSGabor Juhos AR934X_SRIF_DPLL1_NINT_MASK; 28597541ccfSGabor Juhos nfrac = pll & AR934X_SRIF_DPLL1_NFRAC_MASK; 28697541ccfSGabor Juhos ref_div = (pll >> AR934X_SRIF_DPLL1_REFDIV_SHIFT) & 28797541ccfSGabor Juhos AR934X_SRIF_DPLL1_REFDIV_MASK; 28897541ccfSGabor Juhos frac = 1 << 18; 28997541ccfSGabor Juhos } else { 2908889612bSGabor Juhos pll = ath79_pll_rr(AR934X_PLL_DDR_CONFIG_REG); 2918889612bSGabor Juhos out_div = (pll >> AR934X_PLL_DDR_CONFIG_OUTDIV_SHIFT) & 2928889612bSGabor Juhos AR934X_PLL_DDR_CONFIG_OUTDIV_MASK; 2938889612bSGabor Juhos ref_div = (pll >> AR934X_PLL_DDR_CONFIG_REFDIV_SHIFT) & 2948889612bSGabor Juhos AR934X_PLL_DDR_CONFIG_REFDIV_MASK; 2958889612bSGabor Juhos nint = (pll >> AR934X_PLL_DDR_CONFIG_NINT_SHIFT) & 2968889612bSGabor Juhos AR934X_PLL_DDR_CONFIG_NINT_MASK; 29797541ccfSGabor Juhos nfrac = (pll >> AR934X_PLL_DDR_CONFIG_NFRAC_SHIFT) & 2988889612bSGabor Juhos AR934X_PLL_DDR_CONFIG_NFRAC_MASK; 29997541ccfSGabor Juhos frac = 1 << 10; 30097541ccfSGabor Juhos } 3018889612bSGabor Juhos 3026612a688SGabor Juhos ddr_pll = ar934x_get_pll_freq(ref_rate, ref_div, nint, 30397541ccfSGabor Juhos nfrac, frac, out_div); 3048889612bSGabor Juhos 3058889612bSGabor Juhos clk_ctrl = ath79_pll_rr(AR934X_PLL_CPU_DDR_CLK_CTRL_REG); 3068889612bSGabor Juhos 3078889612bSGabor Juhos postdiv = (clk_ctrl >> AR934X_PLL_CPU_DDR_CLK_CTRL_CPU_POST_DIV_SHIFT) & 3088889612bSGabor Juhos AR934X_PLL_CPU_DDR_CLK_CTRL_CPU_POST_DIV_MASK; 3098889612bSGabor Juhos 3108889612bSGabor Juhos if (clk_ctrl & AR934X_PLL_CPU_DDR_CLK_CTRL_CPU_PLL_BYPASS) 3116612a688SGabor Juhos cpu_rate = ref_rate; 3128889612bSGabor Juhos else if (clk_ctrl & AR934X_PLL_CPU_DDR_CLK_CTRL_CPUCLK_FROM_CPUPLL) 3136612a688SGabor Juhos cpu_rate = cpu_pll / (postdiv + 1); 3148889612bSGabor Juhos else 3156612a688SGabor Juhos cpu_rate = ddr_pll / (postdiv + 1); 3168889612bSGabor Juhos 3178889612bSGabor Juhos postdiv = (clk_ctrl >> AR934X_PLL_CPU_DDR_CLK_CTRL_DDR_POST_DIV_SHIFT) & 3188889612bSGabor Juhos AR934X_PLL_CPU_DDR_CLK_CTRL_DDR_POST_DIV_MASK; 3198889612bSGabor Juhos 3208889612bSGabor Juhos if (clk_ctrl & AR934X_PLL_CPU_DDR_CLK_CTRL_DDR_PLL_BYPASS) 3216612a688SGabor Juhos ddr_rate = ref_rate; 3228889612bSGabor Juhos else if (clk_ctrl & AR934X_PLL_CPU_DDR_CLK_CTRL_DDRCLK_FROM_DDRPLL) 3236612a688SGabor Juhos ddr_rate = ddr_pll / (postdiv + 1); 3248889612bSGabor Juhos else 3256612a688SGabor Juhos ddr_rate = cpu_pll / (postdiv + 1); 3268889612bSGabor Juhos 3278889612bSGabor Juhos postdiv = (clk_ctrl >> AR934X_PLL_CPU_DDR_CLK_CTRL_AHB_POST_DIV_SHIFT) & 3288889612bSGabor Juhos AR934X_PLL_CPU_DDR_CLK_CTRL_AHB_POST_DIV_MASK; 3298889612bSGabor Juhos 3308889612bSGabor Juhos if (clk_ctrl & AR934X_PLL_CPU_DDR_CLK_CTRL_AHB_PLL_BYPASS) 3316612a688SGabor Juhos ahb_rate = ref_rate; 3328889612bSGabor Juhos else if (clk_ctrl & AR934X_PLL_CPU_DDR_CLK_CTRL_AHBCLK_FROM_DDRPLL) 3336612a688SGabor Juhos ahb_rate = ddr_pll / (postdiv + 1); 3348889612bSGabor Juhos else 3356612a688SGabor Juhos ahb_rate = cpu_pll / (postdiv + 1); 3366612a688SGabor Juhos 3372c4f1ac5SGabor Juhos ath79_add_sys_clkdev("ref", ref_rate); 3382c4f1ac5SGabor Juhos ath79_add_sys_clkdev("cpu", cpu_rate); 3392c4f1ac5SGabor Juhos ath79_add_sys_clkdev("ddr", ddr_rate); 3402c4f1ac5SGabor Juhos ath79_add_sys_clkdev("ahb", ahb_rate); 3418889612bSGabor Juhos 3422c4f1ac5SGabor Juhos clk_add_alias("wdt", NULL, "ref", NULL); 3432c4f1ac5SGabor Juhos clk_add_alias("uart", NULL, "ref", NULL); 34497541ccfSGabor Juhos 34597541ccfSGabor Juhos iounmap(dpll_base); 3468889612bSGabor Juhos } 3478889612bSGabor Juhos 34841583c05SGabor Juhos static void __init qca955x_clocks_init(void) 34941583c05SGabor Juhos { 3506612a688SGabor Juhos unsigned long ref_rate; 3516612a688SGabor Juhos unsigned long cpu_rate; 3526612a688SGabor Juhos unsigned long ddr_rate; 3536612a688SGabor Juhos unsigned long ahb_rate; 35441583c05SGabor Juhos u32 pll, out_div, ref_div, nint, frac, clk_ctrl, postdiv; 35541583c05SGabor Juhos u32 cpu_pll, ddr_pll; 35641583c05SGabor Juhos u32 bootstrap; 35741583c05SGabor Juhos 35841583c05SGabor Juhos bootstrap = ath79_reset_rr(QCA955X_RESET_REG_BOOTSTRAP); 35941583c05SGabor Juhos if (bootstrap & QCA955X_BOOTSTRAP_REF_CLK_40) 3606612a688SGabor Juhos ref_rate = 40 * 1000 * 1000; 36141583c05SGabor Juhos else 3626612a688SGabor Juhos ref_rate = 25 * 1000 * 1000; 36341583c05SGabor Juhos 36441583c05SGabor Juhos pll = ath79_pll_rr(QCA955X_PLL_CPU_CONFIG_REG); 36541583c05SGabor Juhos out_div = (pll >> QCA955X_PLL_CPU_CONFIG_OUTDIV_SHIFT) & 36641583c05SGabor Juhos QCA955X_PLL_CPU_CONFIG_OUTDIV_MASK; 36741583c05SGabor Juhos ref_div = (pll >> QCA955X_PLL_CPU_CONFIG_REFDIV_SHIFT) & 36841583c05SGabor Juhos QCA955X_PLL_CPU_CONFIG_REFDIV_MASK; 36941583c05SGabor Juhos nint = (pll >> QCA955X_PLL_CPU_CONFIG_NINT_SHIFT) & 37041583c05SGabor Juhos QCA955X_PLL_CPU_CONFIG_NINT_MASK; 37141583c05SGabor Juhos frac = (pll >> QCA955X_PLL_CPU_CONFIG_NFRAC_SHIFT) & 37241583c05SGabor Juhos QCA955X_PLL_CPU_CONFIG_NFRAC_MASK; 37341583c05SGabor Juhos 3746612a688SGabor Juhos cpu_pll = nint * ref_rate / ref_div; 3756612a688SGabor Juhos cpu_pll += frac * ref_rate / (ref_div * (1 << 6)); 37641583c05SGabor Juhos cpu_pll /= (1 << out_div); 37741583c05SGabor Juhos 37841583c05SGabor Juhos pll = ath79_pll_rr(QCA955X_PLL_DDR_CONFIG_REG); 37941583c05SGabor Juhos out_div = (pll >> QCA955X_PLL_DDR_CONFIG_OUTDIV_SHIFT) & 38041583c05SGabor Juhos QCA955X_PLL_DDR_CONFIG_OUTDIV_MASK; 38141583c05SGabor Juhos ref_div = (pll >> QCA955X_PLL_DDR_CONFIG_REFDIV_SHIFT) & 38241583c05SGabor Juhos QCA955X_PLL_DDR_CONFIG_REFDIV_MASK; 38341583c05SGabor Juhos nint = (pll >> QCA955X_PLL_DDR_CONFIG_NINT_SHIFT) & 38441583c05SGabor Juhos QCA955X_PLL_DDR_CONFIG_NINT_MASK; 38541583c05SGabor Juhos frac = (pll >> QCA955X_PLL_DDR_CONFIG_NFRAC_SHIFT) & 38641583c05SGabor Juhos QCA955X_PLL_DDR_CONFIG_NFRAC_MASK; 38741583c05SGabor Juhos 3886612a688SGabor Juhos ddr_pll = nint * ref_rate / ref_div; 3896612a688SGabor Juhos ddr_pll += frac * ref_rate / (ref_div * (1 << 10)); 39041583c05SGabor Juhos ddr_pll /= (1 << out_div); 39141583c05SGabor Juhos 39241583c05SGabor Juhos clk_ctrl = ath79_pll_rr(QCA955X_PLL_CLK_CTRL_REG); 39341583c05SGabor Juhos 39441583c05SGabor Juhos postdiv = (clk_ctrl >> QCA955X_PLL_CLK_CTRL_CPU_POST_DIV_SHIFT) & 39541583c05SGabor Juhos QCA955X_PLL_CLK_CTRL_CPU_POST_DIV_MASK; 39641583c05SGabor Juhos 39741583c05SGabor Juhos if (clk_ctrl & QCA955X_PLL_CLK_CTRL_CPU_PLL_BYPASS) 3986612a688SGabor Juhos cpu_rate = ref_rate; 39941583c05SGabor Juhos else if (clk_ctrl & QCA955X_PLL_CLK_CTRL_CPUCLK_FROM_CPUPLL) 4006612a688SGabor Juhos cpu_rate = ddr_pll / (postdiv + 1); 40141583c05SGabor Juhos else 4026612a688SGabor Juhos cpu_rate = cpu_pll / (postdiv + 1); 40341583c05SGabor Juhos 40441583c05SGabor Juhos postdiv = (clk_ctrl >> QCA955X_PLL_CLK_CTRL_DDR_POST_DIV_SHIFT) & 40541583c05SGabor Juhos QCA955X_PLL_CLK_CTRL_DDR_POST_DIV_MASK; 40641583c05SGabor Juhos 40741583c05SGabor Juhos if (clk_ctrl & QCA955X_PLL_CLK_CTRL_DDR_PLL_BYPASS) 4086612a688SGabor Juhos ddr_rate = ref_rate; 40941583c05SGabor Juhos else if (clk_ctrl & QCA955X_PLL_CLK_CTRL_DDRCLK_FROM_DDRPLL) 4106612a688SGabor Juhos ddr_rate = cpu_pll / (postdiv + 1); 41141583c05SGabor Juhos else 4126612a688SGabor Juhos ddr_rate = ddr_pll / (postdiv + 1); 41341583c05SGabor Juhos 41441583c05SGabor Juhos postdiv = (clk_ctrl >> QCA955X_PLL_CLK_CTRL_AHB_POST_DIV_SHIFT) & 41541583c05SGabor Juhos QCA955X_PLL_CLK_CTRL_AHB_POST_DIV_MASK; 41641583c05SGabor Juhos 41741583c05SGabor Juhos if (clk_ctrl & QCA955X_PLL_CLK_CTRL_AHB_PLL_BYPASS) 4186612a688SGabor Juhos ahb_rate = ref_rate; 41941583c05SGabor Juhos else if (clk_ctrl & QCA955X_PLL_CLK_CTRL_AHBCLK_FROM_DDRPLL) 4206612a688SGabor Juhos ahb_rate = ddr_pll / (postdiv + 1); 42141583c05SGabor Juhos else 4226612a688SGabor Juhos ahb_rate = cpu_pll / (postdiv + 1); 4236612a688SGabor Juhos 4242c4f1ac5SGabor Juhos ath79_add_sys_clkdev("ref", ref_rate); 4252c4f1ac5SGabor Juhos ath79_add_sys_clkdev("cpu", cpu_rate); 4262c4f1ac5SGabor Juhos ath79_add_sys_clkdev("ddr", ddr_rate); 4272c4f1ac5SGabor Juhos ath79_add_sys_clkdev("ahb", ahb_rate); 42841583c05SGabor Juhos 4292c4f1ac5SGabor Juhos clk_add_alias("wdt", NULL, "ref", NULL); 4302c4f1ac5SGabor Juhos clk_add_alias("uart", NULL, "ref", NULL); 43141583c05SGabor Juhos } 43241583c05SGabor Juhos 433d4a67d9dSGabor Juhos void __init ath79_clocks_init(void) 434d4a67d9dSGabor Juhos { 435d4a67d9dSGabor Juhos if (soc_is_ar71xx()) 436d4a67d9dSGabor Juhos ar71xx_clocks_init(); 437d4a67d9dSGabor Juhos else if (soc_is_ar724x()) 438d4a67d9dSGabor Juhos ar724x_clocks_init(); 439d4a67d9dSGabor Juhos else if (soc_is_ar913x()) 440d4a67d9dSGabor Juhos ar913x_clocks_init(); 44104225e1dSGabor Juhos else if (soc_is_ar933x()) 44204225e1dSGabor Juhos ar933x_clocks_init(); 4438889612bSGabor Juhos else if (soc_is_ar934x()) 4448889612bSGabor Juhos ar934x_clocks_init(); 44541583c05SGabor Juhos else if (soc_is_qca955x()) 44641583c05SGabor Juhos qca955x_clocks_init(); 447d4a67d9dSGabor Juhos else 448d4a67d9dSGabor Juhos BUG(); 449d4a67d9dSGabor Juhos } 450d4a67d9dSGabor Juhos 45123107802SGabor Juhos unsigned long __init 45223107802SGabor Juhos ath79_get_sys_clk_rate(const char *id) 45323107802SGabor Juhos { 45423107802SGabor Juhos struct clk *clk; 45523107802SGabor Juhos unsigned long rate; 45623107802SGabor Juhos 45723107802SGabor Juhos clk = clk_get(NULL, id); 45823107802SGabor Juhos if (IS_ERR(clk)) 45923107802SGabor Juhos panic("unable to get %s clock, err=%d", id, (int) PTR_ERR(clk)); 46023107802SGabor Juhos 46123107802SGabor Juhos rate = clk_get_rate(clk); 46223107802SGabor Juhos clk_put(clk); 46323107802SGabor Juhos 46423107802SGabor Juhos return rate; 46523107802SGabor Juhos } 466