ARM: dts: sama5d2: Add uart4 definition
[oweals/u-boot.git] / arch / arm / cpu / arm926ejs / lpc32xx / clk.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (C) 2011 by Vladimir Zapolskiy <vz@mleia.com>
4  */
5
6 #include <common.h>
7 #include <clock_legacy.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         fcco = fref * m_div;
58         fout = fcco;
59         if (val & CLK_HCLK_PLL_FEEDBACK)
60                 fcco *= p_div;
61         else
62                 do_div(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 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
135 int get_serial_clock(void)
136 {
137         return get_periph_clk_rate();
138 }