2 * Atheros AR71XX/AR724X/AR913X common routines
4 * Copyright (C) 2010-2011 Jaiganesh Narayanan <jnarayanan@atheros.com>
5 * Copyright (C) 2011 Gabor Juhos <juhosg@openwrt.org>
7 * Parts of this file are based on Atheros' 2.6.15/2.6.31 BSP
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License version 2 as published
11 * by the Free Software Foundation.
14 #include <linux/kernel.h>
15 #include <linux/module.h>
16 #include <linux/init.h>
17 #include <linux/err.h>
18 #include <linux/clk.h>
20 #include <asm/div64.h>
22 #include <asm/mach-ath79/ath79.h>
23 #include <asm/mach-ath79/ar71xx_regs.h>
26 #define AR71XX_BASE_FREQ 40000000
27 #define AR724X_BASE_FREQ 5000000
28 #define AR913X_BASE_FREQ 5000000
34 static struct clk ath79_ref_clk
;
35 static struct clk ath79_cpu_clk
;
36 static struct clk ath79_ddr_clk
;
37 static struct clk ath79_ahb_clk
;
38 static struct clk ath79_wdt_clk
;
39 static struct clk ath79_uart_clk
;
41 static void __init
ar71xx_clocks_init(void)
47 ath79_ref_clk
.rate
= AR71XX_BASE_FREQ
;
49 pll
= ath79_pll_rr(AR71XX_PLL_REG_CPU_CONFIG
);
51 div
= ((pll
>> AR71XX_PLL_DIV_SHIFT
) & AR71XX_PLL_DIV_MASK
) + 1;
52 freq
= div
* ath79_ref_clk
.rate
;
54 div
= ((pll
>> AR71XX_CPU_DIV_SHIFT
) & AR71XX_CPU_DIV_MASK
) + 1;
55 ath79_cpu_clk
.rate
= freq
/ div
;
57 div
= ((pll
>> AR71XX_DDR_DIV_SHIFT
) & AR71XX_DDR_DIV_MASK
) + 1;
58 ath79_ddr_clk
.rate
= freq
/ div
;
60 div
= (((pll
>> AR71XX_AHB_DIV_SHIFT
) & AR71XX_AHB_DIV_MASK
) + 1) * 2;
61 ath79_ahb_clk
.rate
= ath79_cpu_clk
.rate
/ div
;
63 ath79_wdt_clk
.rate
= ath79_ahb_clk
.rate
;
64 ath79_uart_clk
.rate
= ath79_ahb_clk
.rate
;
67 static void __init
ar724x_clocks_init(void)
73 ath79_ref_clk
.rate
= AR724X_BASE_FREQ
;
74 pll
= ath79_pll_rr(AR724X_PLL_REG_CPU_CONFIG
);
76 div
= ((pll
>> AR724X_PLL_DIV_SHIFT
) & AR724X_PLL_DIV_MASK
);
77 freq
= div
* ath79_ref_clk
.rate
;
79 div
= ((pll
>> AR724X_PLL_REF_DIV_SHIFT
) & AR724X_PLL_REF_DIV_MASK
);
82 ath79_cpu_clk
.rate
= freq
;
84 div
= ((pll
>> AR724X_DDR_DIV_SHIFT
) & AR724X_DDR_DIV_MASK
) + 1;
85 ath79_ddr_clk
.rate
= freq
/ div
;
87 div
= (((pll
>> AR724X_AHB_DIV_SHIFT
) & AR724X_AHB_DIV_MASK
) + 1) * 2;
88 ath79_ahb_clk
.rate
= ath79_cpu_clk
.rate
/ div
;
90 ath79_wdt_clk
.rate
= ath79_ahb_clk
.rate
;
91 ath79_uart_clk
.rate
= ath79_ahb_clk
.rate
;
94 static void __init
ar913x_clocks_init(void)
100 ath79_ref_clk
.rate
= AR913X_BASE_FREQ
;
101 pll
= ath79_pll_rr(AR913X_PLL_REG_CPU_CONFIG
);
103 div
= ((pll
>> AR913X_PLL_DIV_SHIFT
) & AR913X_PLL_DIV_MASK
);
104 freq
= div
* ath79_ref_clk
.rate
;
106 ath79_cpu_clk
.rate
= freq
;
108 div
= ((pll
>> AR913X_DDR_DIV_SHIFT
) & AR913X_DDR_DIV_MASK
) + 1;
109 ath79_ddr_clk
.rate
= freq
/ div
;
111 div
= (((pll
>> AR913X_AHB_DIV_SHIFT
) & AR913X_AHB_DIV_MASK
) + 1) * 2;
112 ath79_ahb_clk
.rate
= ath79_cpu_clk
.rate
/ div
;
114 ath79_wdt_clk
.rate
= ath79_ahb_clk
.rate
;
115 ath79_uart_clk
.rate
= ath79_ahb_clk
.rate
;
118 static void __init
ar933x_clocks_init(void)
125 t
= ath79_reset_rr(AR933X_RESET_REG_BOOTSTRAP
);
126 if (t
& AR933X_BOOTSTRAP_REF_CLK_40
)
127 ath79_ref_clk
.rate
= (40 * 1000 * 1000);
129 ath79_ref_clk
.rate
= (25 * 1000 * 1000);
131 clock_ctrl
= ath79_pll_rr(AR933X_PLL_CLOCK_CTRL_REG
);
132 if (clock_ctrl
& AR933X_PLL_CLOCK_CTRL_BYPASS
) {
133 ath79_cpu_clk
.rate
= ath79_ref_clk
.rate
;
134 ath79_ahb_clk
.rate
= ath79_ref_clk
.rate
;
135 ath79_ddr_clk
.rate
= ath79_ref_clk
.rate
;
137 cpu_config
= ath79_pll_rr(AR933X_PLL_CPU_CONFIG_REG
);
139 t
= (cpu_config
>> AR933X_PLL_CPU_CONFIG_REFDIV_SHIFT
) &
140 AR933X_PLL_CPU_CONFIG_REFDIV_MASK
;
141 freq
= ath79_ref_clk
.rate
/ t
;
143 t
= (cpu_config
>> AR933X_PLL_CPU_CONFIG_NINT_SHIFT
) &
144 AR933X_PLL_CPU_CONFIG_NINT_MASK
;
147 t
= (cpu_config
>> AR933X_PLL_CPU_CONFIG_OUTDIV_SHIFT
) &
148 AR933X_PLL_CPU_CONFIG_OUTDIV_MASK
;
154 t
= ((clock_ctrl
>> AR933X_PLL_CLOCK_CTRL_CPU_DIV_SHIFT
) &
155 AR933X_PLL_CLOCK_CTRL_CPU_DIV_MASK
) + 1;
156 ath79_cpu_clk
.rate
= freq
/ t
;
158 t
= ((clock_ctrl
>> AR933X_PLL_CLOCK_CTRL_DDR_DIV_SHIFT
) &
159 AR933X_PLL_CLOCK_CTRL_DDR_DIV_MASK
) + 1;
160 ath79_ddr_clk
.rate
= freq
/ t
;
162 t
= ((clock_ctrl
>> AR933X_PLL_CLOCK_CTRL_AHB_DIV_SHIFT
) &
163 AR933X_PLL_CLOCK_CTRL_AHB_DIV_MASK
) + 1;
164 ath79_ahb_clk
.rate
= freq
/ t
;
167 ath79_wdt_clk
.rate
= ath79_ref_clk
.rate
;
168 ath79_uart_clk
.rate
= ath79_ref_clk
.rate
;
171 static u32 __init
ar934x_get_pll_freq(u32 ref
, u32 ref_div
, u32 nint
, u32 nfrac
,
172 u32 frac
, u32 out_div
)
177 t
= ath79_ref_clk
.rate
;
182 t
= ath79_ref_clk
.rate
;
184 do_div(t
, ref_div
* frac
);
187 ret
/= (1 << out_div
);
191 static void __init
ar934x_clocks_init(void)
193 u32 pll
, out_div
, ref_div
, nint
, nfrac
, frac
, clk_ctrl
, postdiv
;
194 u32 cpu_pll
, ddr_pll
;
196 void __iomem
*dpll_base
;
198 dpll_base
= ioremap(AR934X_SRIF_BASE
, AR934X_SRIF_SIZE
);
200 bootstrap
= ath79_reset_rr(AR934X_RESET_REG_BOOTSTRAP
);
201 if (bootstrap
& AR934X_BOOTSTRAP_REF_CLK_40
)
202 ath79_ref_clk
.rate
= 40 * 1000 * 1000;
204 ath79_ref_clk
.rate
= 25 * 1000 * 1000;
206 pll
= __raw_readl(dpll_base
+ AR934X_SRIF_CPU_DPLL2_REG
);
207 if (pll
& AR934X_SRIF_DPLL2_LOCAL_PLL
) {
208 out_div
= (pll
>> AR934X_SRIF_DPLL2_OUTDIV_SHIFT
) &
209 AR934X_SRIF_DPLL2_OUTDIV_MASK
;
210 pll
= __raw_readl(dpll_base
+ AR934X_SRIF_CPU_DPLL1_REG
);
211 nint
= (pll
>> AR934X_SRIF_DPLL1_NINT_SHIFT
) &
212 AR934X_SRIF_DPLL1_NINT_MASK
;
213 nfrac
= pll
& AR934X_SRIF_DPLL1_NFRAC_MASK
;
214 ref_div
= (pll
>> AR934X_SRIF_DPLL1_REFDIV_SHIFT
) &
215 AR934X_SRIF_DPLL1_REFDIV_MASK
;
218 pll
= ath79_pll_rr(AR934X_PLL_CPU_CONFIG_REG
);
219 out_div
= (pll
>> AR934X_PLL_CPU_CONFIG_OUTDIV_SHIFT
) &
220 AR934X_PLL_CPU_CONFIG_OUTDIV_MASK
;
221 ref_div
= (pll
>> AR934X_PLL_CPU_CONFIG_REFDIV_SHIFT
) &
222 AR934X_PLL_CPU_CONFIG_REFDIV_MASK
;
223 nint
= (pll
>> AR934X_PLL_CPU_CONFIG_NINT_SHIFT
) &
224 AR934X_PLL_CPU_CONFIG_NINT_MASK
;
225 nfrac
= (pll
>> AR934X_PLL_CPU_CONFIG_NFRAC_SHIFT
) &
226 AR934X_PLL_CPU_CONFIG_NFRAC_MASK
;
230 cpu_pll
= ar934x_get_pll_freq(ath79_ref_clk
.rate
, ref_div
, nint
,
231 nfrac
, frac
, out_div
);
233 pll
= __raw_readl(dpll_base
+ AR934X_SRIF_DDR_DPLL2_REG
);
234 if (pll
& AR934X_SRIF_DPLL2_LOCAL_PLL
) {
235 out_div
= (pll
>> AR934X_SRIF_DPLL2_OUTDIV_SHIFT
) &
236 AR934X_SRIF_DPLL2_OUTDIV_MASK
;
237 pll
= __raw_readl(dpll_base
+ AR934X_SRIF_DDR_DPLL1_REG
);
238 nint
= (pll
>> AR934X_SRIF_DPLL1_NINT_SHIFT
) &
239 AR934X_SRIF_DPLL1_NINT_MASK
;
240 nfrac
= pll
& AR934X_SRIF_DPLL1_NFRAC_MASK
;
241 ref_div
= (pll
>> AR934X_SRIF_DPLL1_REFDIV_SHIFT
) &
242 AR934X_SRIF_DPLL1_REFDIV_MASK
;
245 pll
= ath79_pll_rr(AR934X_PLL_DDR_CONFIG_REG
);
246 out_div
= (pll
>> AR934X_PLL_DDR_CONFIG_OUTDIV_SHIFT
) &
247 AR934X_PLL_DDR_CONFIG_OUTDIV_MASK
;
248 ref_div
= (pll
>> AR934X_PLL_DDR_CONFIG_REFDIV_SHIFT
) &
249 AR934X_PLL_DDR_CONFIG_REFDIV_MASK
;
250 nint
= (pll
>> AR934X_PLL_DDR_CONFIG_NINT_SHIFT
) &
251 AR934X_PLL_DDR_CONFIG_NINT_MASK
;
252 nfrac
= (pll
>> AR934X_PLL_DDR_CONFIG_NFRAC_SHIFT
) &
253 AR934X_PLL_DDR_CONFIG_NFRAC_MASK
;
257 ddr_pll
= ar934x_get_pll_freq(ath79_ref_clk
.rate
, ref_div
, nint
,
258 nfrac
, frac
, out_div
);
260 clk_ctrl
= ath79_pll_rr(AR934X_PLL_CPU_DDR_CLK_CTRL_REG
);
262 postdiv
= (clk_ctrl
>> AR934X_PLL_CPU_DDR_CLK_CTRL_CPU_POST_DIV_SHIFT
) &
263 AR934X_PLL_CPU_DDR_CLK_CTRL_CPU_POST_DIV_MASK
;
265 if (clk_ctrl
& AR934X_PLL_CPU_DDR_CLK_CTRL_CPU_PLL_BYPASS
)
266 ath79_cpu_clk
.rate
= ath79_ref_clk
.rate
;
267 else if (clk_ctrl
& AR934X_PLL_CPU_DDR_CLK_CTRL_CPUCLK_FROM_CPUPLL
)
268 ath79_cpu_clk
.rate
= cpu_pll
/ (postdiv
+ 1);
270 ath79_cpu_clk
.rate
= ddr_pll
/ (postdiv
+ 1);
272 postdiv
= (clk_ctrl
>> AR934X_PLL_CPU_DDR_CLK_CTRL_DDR_POST_DIV_SHIFT
) &
273 AR934X_PLL_CPU_DDR_CLK_CTRL_DDR_POST_DIV_MASK
;
275 if (clk_ctrl
& AR934X_PLL_CPU_DDR_CLK_CTRL_DDR_PLL_BYPASS
)
276 ath79_ddr_clk
.rate
= ath79_ref_clk
.rate
;
277 else if (clk_ctrl
& AR934X_PLL_CPU_DDR_CLK_CTRL_DDRCLK_FROM_DDRPLL
)
278 ath79_ddr_clk
.rate
= ddr_pll
/ (postdiv
+ 1);
280 ath79_ddr_clk
.rate
= cpu_pll
/ (postdiv
+ 1);
282 postdiv
= (clk_ctrl
>> AR934X_PLL_CPU_DDR_CLK_CTRL_AHB_POST_DIV_SHIFT
) &
283 AR934X_PLL_CPU_DDR_CLK_CTRL_AHB_POST_DIV_MASK
;
285 if (clk_ctrl
& AR934X_PLL_CPU_DDR_CLK_CTRL_AHB_PLL_BYPASS
)
286 ath79_ahb_clk
.rate
= ath79_ref_clk
.rate
;
287 else if (clk_ctrl
& AR934X_PLL_CPU_DDR_CLK_CTRL_AHBCLK_FROM_DDRPLL
)
288 ath79_ahb_clk
.rate
= ddr_pll
/ (postdiv
+ 1);
290 ath79_ahb_clk
.rate
= cpu_pll
/ (postdiv
+ 1);
292 ath79_wdt_clk
.rate
= ath79_ref_clk
.rate
;
293 ath79_uart_clk
.rate
= ath79_ref_clk
.rate
;
298 void __init
ath79_clocks_init(void)
301 ar71xx_clocks_init();
302 else if (soc_is_ar724x())
303 ar724x_clocks_init();
304 else if (soc_is_ar913x())
305 ar913x_clocks_init();
306 else if (soc_is_ar933x())
307 ar933x_clocks_init();
308 else if (soc_is_ar934x())
309 ar934x_clocks_init();
313 pr_info("Clocks: CPU:%lu.%03luMHz, DDR:%lu.%03luMHz, AHB:%lu.%03luMHz, "
315 ath79_cpu_clk
.rate
/ 1000000,
316 (ath79_cpu_clk
.rate
/ 1000) % 1000,
317 ath79_ddr_clk
.rate
/ 1000000,
318 (ath79_ddr_clk
.rate
/ 1000) % 1000,
319 ath79_ahb_clk
.rate
/ 1000000,
320 (ath79_ahb_clk
.rate
/ 1000) % 1000,
321 ath79_ref_clk
.rate
/ 1000000,
322 (ath79_ref_clk
.rate
/ 1000) % 1000);
328 struct clk
*clk_get(struct device
*dev
, const char *id
)
330 if (!strcmp(id
, "ref"))
331 return &ath79_ref_clk
;
333 if (!strcmp(id
, "cpu"))
334 return &ath79_cpu_clk
;
336 if (!strcmp(id
, "ddr"))
337 return &ath79_ddr_clk
;
339 if (!strcmp(id
, "ahb"))
340 return &ath79_ahb_clk
;
342 if (!strcmp(id
, "wdt"))
343 return &ath79_wdt_clk
;
345 if (!strcmp(id
, "uart"))
346 return &ath79_uart_clk
;
348 return ERR_PTR(-ENOENT
);
350 EXPORT_SYMBOL(clk_get
);
352 int clk_enable(struct clk
*clk
)
356 EXPORT_SYMBOL(clk_enable
);
358 void clk_disable(struct clk
*clk
)
361 EXPORT_SYMBOL(clk_disable
);
363 unsigned long clk_get_rate(struct clk
*clk
)
367 EXPORT_SYMBOL(clk_get_rate
);
369 void clk_put(struct clk
*clk
)
372 EXPORT_SYMBOL(clk_put
);