]>
Commit | Line | Data |
---|---|---|
83d290c5 | 1 | // SPDX-License-Identifier: GPL-2.0+ |
52f69f81 VZ |
2 | /* |
3 | * Copyright (C) 2011 by Vladimir Zapolskiy <vz@mleia.com> | |
52f69f81 VZ |
4 | */ |
5 | ||
d678a59d | 6 | #include <common.h> |
d96c2604 | 7 | #include <clock_legacy.h> |
52f69f81 VZ |
8 | #include <div64.h> |
9 | #include <asm/arch/cpu.h> | |
10 | #include <asm/arch/clk.h> | |
11 | #include <asm/io.h> | |
12 | ||
13 | static struct clk_pm_regs *clk = (struct clk_pm_regs *)CLK_PM_BASE; | |
14 | ||
15 | unsigned int get_sys_clk_rate(void) | |
16 | { | |
17 | if (readl(&clk->sysclk_ctrl) & CLK_SYSCLK_PLL397) | |
18 | return RTC_CLK_FREQUENCY * 397; | |
19 | else | |
20 | return OSC_CLK_FREQUENCY; | |
21 | } | |
22 | ||
23 | unsigned int get_hclk_pll_rate(void) | |
24 | { | |
25 | unsigned long long fin, fref, fcco, fout; | |
26 | u32 val, m_div, n_div, p_div; | |
27 | ||
28 | /* | |
29 | * Valid frequency ranges: | |
30 | * 1 * 10^6 <= Fin <= 20 * 10^6 | |
31 | * 1 * 10^6 <= Fref <= 27 * 10^6 | |
32 | * 156 * 10^6 <= Fcco <= 320 * 10^6 | |
33 | */ | |
34 | ||
35 | fref = fin = get_sys_clk_rate(); | |
36 | if (fin > 20000000ULL || fin < 1000000ULL) | |
37 | return 0; | |
38 | ||
39 | val = readl(&clk->hclkpll_ctrl); | |
40 | m_div = ((val & CLK_HCLK_PLL_FEEDBACK_DIV_MASK) >> 1) + 1; | |
41 | n_div = ((val & CLK_HCLK_PLL_PREDIV_MASK) >> 9) + 1; | |
42 | if (val & CLK_HCLK_PLL_DIRECT) | |
43 | p_div = 0; | |
44 | else | |
45 | p_div = ((val & CLK_HCLK_PLL_POSTDIV_MASK) >> 11) + 1; | |
46 | p_div = 1 << p_div; | |
47 | ||
48 | if (val & CLK_HCLK_PLL_BYPASS) { | |
49 | do_div(fin, p_div); | |
50 | return fin; | |
51 | } | |
52 | ||
53 | do_div(fref, n_div); | |
54 | if (fref > 27000000ULL || fref < 1000000ULL) | |
55 | return 0; | |
56 | ||
4c902345 VZ |
57 | fcco = fref * m_div; |
58 | fout = fcco; | |
59 | if (val & CLK_HCLK_PLL_FEEDBACK) | |
60 | fcco *= p_div; | |
61 | else | |
52f69f81 | 62 | do_div(fout, p_div); |
52f69f81 VZ |
63 | |
64 | if (fcco > 320000000ULL || fcco < 156000000ULL) | |
65 | return 0; | |
66 | ||
67 | return fout; | |
68 | } | |
69 | ||
70 | unsigned int get_hclk_clk_div(void) | |
71 | { | |
72 | u32 val; | |
73 | ||
74 | val = readl(&clk->hclkdiv_ctrl) & CLK_HCLK_ARM_PLL_DIV_MASK; | |
75 | ||
76 | return 1 << val; | |
77 | } | |
78 | ||
79 | unsigned int get_hclk_clk_rate(void) | |
80 | { | |
81 | return get_hclk_pll_rate() / get_hclk_clk_div(); | |
82 | } | |
83 | ||
84 | unsigned int get_periph_clk_div(void) | |
85 | { | |
86 | u32 val; | |
87 | ||
88 | val = readl(&clk->hclkdiv_ctrl) & CLK_HCLK_PERIPH_DIV_MASK; | |
89 | ||
90 | return (val >> 2) + 1; | |
91 | } | |
92 | ||
93 | unsigned int get_periph_clk_rate(void) | |
94 | { | |
95 | if (!(readl(&clk->pwr_ctrl) & CLK_PWR_NORMAL_RUN)) | |
96 | return get_sys_clk_rate(); | |
97 | ||
98 | return get_hclk_pll_rate() / get_periph_clk_div(); | |
99 | } | |
100 | ||
412ae53a AA |
101 | unsigned int get_sdram_clk_rate(void) |
102 | { | |
103 | unsigned int src_clk; | |
104 | ||
105 | if (!(readl(&clk->pwr_ctrl) & CLK_PWR_NORMAL_RUN)) | |
106 | return get_sys_clk_rate(); | |
107 | ||
108 | src_clk = get_hclk_pll_rate(); | |
109 | ||
110 | if (readl(&clk->sdramclk_ctrl) & CLK_SDRAM_DDR_SEL) { | |
111 | /* using DDR */ | |
112 | switch (readl(&clk->hclkdiv_ctrl) & CLK_HCLK_DDRAM_MASK) { | |
113 | case CLK_HCLK_DDRAM_HALF: | |
114 | return src_clk/2; | |
115 | case CLK_HCLK_DDRAM_NOMINAL: | |
116 | return src_clk; | |
117 | default: | |
118 | return 0; | |
119 | } | |
120 | } else { | |
121 | /* using SDR */ | |
122 | switch (readl(&clk->hclkdiv_ctrl) & CLK_HCLK_ARM_PLL_DIV_MASK) { | |
123 | case CLK_HCLK_ARM_PLL_DIV_4: | |
124 | return src_clk/4; | |
125 | case CLK_HCLK_ARM_PLL_DIV_2: | |
126 | return src_clk/2; | |
127 | case CLK_HCLK_ARM_PLL_DIV_1: | |
128 | return src_clk; | |
129 | default: | |
130 | return 0; | |
131 | } | |
132 | } | |
133 | } | |
134 | ||
52f69f81 VZ |
135 | int get_serial_clock(void) |
136 | { | |
137 | return get_periph_clk_rate(); | |
138 | } |