]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - arch/arm/cpu/arm926ejs/lpc32xx/clk.c
Add GPL-2.0+ SPDX-License-Identifier to source files
[karo-tx-uboot.git] / arch / arm / cpu / arm926ejs / lpc32xx / clk.c
1 /*
2  * Copyright (C) 2011 by Vladimir Zapolskiy <vz@mleia.com>
3  *
4  * SPDX-License-Identifier:     GPL-2.0+
5  */
6
7 #include <common.h>
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
57         fout = fref * m_div;
58         if (val & CLK_HCLK_PLL_FEEDBACK) {
59                 fcco = fout;
60                 do_div(fout, p_div);
61         } else
62                 fcco = fout * p_div;
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
101 int get_serial_clock(void)
102 {
103         return get_periph_clk_rate();
104 }