]>
Commit | Line | Data |
---|---|---|
83d290c5 | 1 | // SPDX-License-Identifier: GPL-2.0+ |
ee7bb5be WW |
2 | /* |
3 | * Copyright (C) 2015-2016 Wills Wang <wills.wang@live.com> | |
ee7bb5be WW |
4 | */ |
5 | ||
6 | #include <common.h> | |
7 | #include <asm/io.h> | |
8 | #include <asm/addrspace.h> | |
9 | #include <asm/types.h> | |
10 | #include <mach/ar71xx_regs.h> | |
37523917 | 11 | #include <mach/ath79.h> |
ee7bb5be WW |
12 | |
13 | DECLARE_GLOBAL_DATA_PTR; | |
14 | ||
15 | static u32 ar933x_get_xtal(void) | |
16 | { | |
17 | u32 val; | |
18 | ||
37523917 | 19 | val = ath79_get_bootstrap(); |
ee7bb5be WW |
20 | if (val & AR933X_BOOTSTRAP_REF_CLK_40) |
21 | return 40000000; | |
22 | else | |
23 | return 25000000; | |
24 | } | |
25 | ||
26 | int get_serial_clock(void) | |
27 | { | |
28 | return ar933x_get_xtal(); | |
29 | } | |
30 | ||
31 | int get_clocks(void) | |
32 | { | |
33 | void __iomem *regs; | |
34 | u32 val, xtal, pll, div; | |
35 | ||
36 | regs = map_physmem(AR71XX_PLL_BASE, AR71XX_PLL_SIZE, | |
37 | MAP_NOCACHE); | |
38 | xtal = ar933x_get_xtal(); | |
39 | val = readl(regs + AR933X_PLL_CPU_CONFIG_REG); | |
40 | ||
41 | /* VCOOUT = XTAL * DIV_INT */ | |
42 | div = (val >> AR933X_PLL_CPU_CONFIG_REFDIV_SHIFT) | |
43 | & AR933X_PLL_CPU_CONFIG_REFDIV_MASK; | |
44 | pll = xtal / div; | |
45 | ||
46 | /* PLLOUT = VCOOUT * (1/2^OUTDIV) */ | |
47 | div = (val >> AR933X_PLL_CPU_CONFIG_NINT_SHIFT) | |
48 | & AR933X_PLL_CPU_CONFIG_NINT_MASK; | |
49 | pll *= div; | |
50 | div = (val >> AR933X_PLL_CPU_CONFIG_OUTDIV_SHIFT) | |
51 | & AR933X_PLL_CPU_CONFIG_OUTDIV_MASK; | |
52 | if (!div) | |
53 | div = 1; | |
54 | pll >>= div; | |
55 | ||
56 | val = readl(regs + AR933X_PLL_CLK_CTRL_REG); | |
57 | ||
58 | /* CPU_CLK = PLLOUT / CPU_POST_DIV */ | |
59 | div = ((val >> AR933X_PLL_CLK_CTRL_CPU_POST_DIV_SHIFT) | |
60 | & AR933X_PLL_CLK_CTRL_CPU_POST_DIV_MASK) + 1; | |
61 | gd->cpu_clk = pll / div; | |
62 | ||
63 | /* DDR_CLK = PLLOUT / DDR_POST_DIV */ | |
64 | div = ((val >> AR933X_PLL_CLK_CTRL_DDR_POST_DIV_SHIFT) | |
65 | & AR933X_PLL_CLK_CTRL_DDR_POST_DIV_MASK) + 1; | |
66 | gd->mem_clk = pll / div; | |
67 | ||
68 | /* AHB_CLK = PLLOUT / AHB_POST_DIV */ | |
69 | div = ((val >> AR933X_PLL_CLK_CTRL_AHB_POST_DIV_SHIFT) | |
70 | & AR933X_PLL_CLK_CTRL_AHB_POST_DIV_MASK) + 1; | |
71 | gd->bus_clk = pll / div; | |
72 | ||
73 | return 0; | |
74 | } | |
75 | ||
76 | ulong get_bus_freq(ulong dummy) | |
77 | { | |
78 | if (!gd->bus_clk) | |
79 | get_clocks(); | |
80 | return gd->bus_clk; | |
81 | } | |
82 | ||
83 | ulong get_ddr_freq(ulong dummy) | |
84 | { | |
85 | if (!gd->mem_clk) | |
86 | get_clocks(); | |
87 | return gd->mem_clk; | |
88 | } |