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