xref: /linux/arch/mips/ath79/clock.c (revision 411520af8ec9456886359b42628e583ac58e7e44)
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