common: Drop init.h from common header
[pandora-u-boot.git] / arch / arm / mach-omap2 / am33xx / clock.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * clock.c
4  *
5  * Clock initialization for AM33XX boards.
6  * Derived from OMAP4 boards
7  *
8  * Copyright (C) 2013, Texas Instruments, Incorporated - http://www.ti.com/
9  */
10 #include <common.h>
11 #include <hang.h>
12 #include <init.h>
13 #include <asm/arch/cpu.h>
14 #include <asm/arch/clock.h>
15 #include <asm/arch/hardware.h>
16 #include <asm/arch/sys_proto.h>
17 #include <asm/io.h>
18
19 static void setup_post_dividers(const struct dpll_regs *dpll_regs,
20                          const struct dpll_params *params)
21 {
22         /* Setup post-dividers */
23         if (params->m2 >= 0)
24                 writel(params->m2, dpll_regs->cm_div_m2_dpll);
25         if (params->m3 >= 0)
26                 writel(params->m3, dpll_regs->cm_div_m3_dpll);
27         if (params->m4 >= 0)
28                 writel(params->m4, dpll_regs->cm_div_m4_dpll);
29         if (params->m5 >= 0)
30                 writel(params->m5, dpll_regs->cm_div_m5_dpll);
31         if (params->m6 >= 0)
32                 writel(params->m6, dpll_regs->cm_div_m6_dpll);
33 }
34
35 static inline void do_lock_dpll(const struct dpll_regs *dpll_regs)
36 {
37         clrsetbits_le32(dpll_regs->cm_clkmode_dpll,
38                         CM_CLKMODE_DPLL_DPLL_EN_MASK,
39                         DPLL_EN_LOCK << CM_CLKMODE_DPLL_EN_SHIFT);
40 }
41
42 static inline void wait_for_lock(const struct dpll_regs *dpll_regs)
43 {
44         if (!wait_on_value(ST_DPLL_CLK_MASK, ST_DPLL_CLK_MASK,
45                            (void *)dpll_regs->cm_idlest_dpll, LDELAY)) {
46                 printf("DPLL locking failed for 0x%x\n",
47                        dpll_regs->cm_clkmode_dpll);
48                 hang();
49         }
50 }
51
52 static inline void do_bypass_dpll(const struct dpll_regs *dpll_regs)
53 {
54         clrsetbits_le32(dpll_regs->cm_clkmode_dpll,
55                         CM_CLKMODE_DPLL_DPLL_EN_MASK,
56                         DPLL_EN_MN_BYPASS << CM_CLKMODE_DPLL_EN_SHIFT);
57 }
58
59 static inline void wait_for_bypass(const struct dpll_regs *dpll_regs)
60 {
61         if (!wait_on_value(ST_DPLL_CLK_MASK, 0,
62                            (void *)dpll_regs->cm_idlest_dpll, LDELAY)) {
63                 printf("Bypassing DPLL failed 0x%x\n",
64                        dpll_regs->cm_clkmode_dpll);
65         }
66 }
67
68 static void bypass_dpll(const struct dpll_regs *dpll_regs)
69 {
70         do_bypass_dpll(dpll_regs);
71         wait_for_bypass(dpll_regs);
72 }
73
74 void do_setup_dpll(const struct dpll_regs *dpll_regs,
75                    const struct dpll_params *params)
76 {
77         u32 temp;
78
79         if (!params)
80                 return;
81
82         temp = readl(dpll_regs->cm_clksel_dpll);
83
84         bypass_dpll(dpll_regs);
85
86         /* Set M & N */
87         temp &= ~CM_CLKSEL_DPLL_M_MASK;
88         temp |= (params->m << CM_CLKSEL_DPLL_M_SHIFT) & CM_CLKSEL_DPLL_M_MASK;
89
90         temp &= ~CM_CLKSEL_DPLL_N_MASK;
91         temp |= (params->n << CM_CLKSEL_DPLL_N_SHIFT) & CM_CLKSEL_DPLL_N_MASK;
92
93         writel(temp, dpll_regs->cm_clksel_dpll);
94
95         setup_post_dividers(dpll_regs, params);
96
97         /* Wait till the DPLL locks */
98         do_lock_dpll(dpll_regs);
99         wait_for_lock(dpll_regs);
100 }
101
102 static void setup_dplls(void)
103 {
104         const struct dpll_params *params;
105
106         params = get_dpll_core_params();
107         do_setup_dpll(&dpll_core_regs, params);
108
109         params = get_dpll_mpu_params();
110         do_setup_dpll(&dpll_mpu_regs, params);
111
112         params = get_dpll_per_params();
113         do_setup_dpll(&dpll_per_regs, params);
114         writel(0x300, &cmwkup->clkdcoldodpllper);
115
116         params = get_dpll_ddr_params();
117         do_setup_dpll(&dpll_ddr_regs, params);
118 }
119
120 static inline void wait_for_clk_enable(u32 *clkctrl_addr)
121 {
122         u32 clkctrl, idlest = MODULE_CLKCTRL_IDLEST_DISABLED;
123         u32 bound = LDELAY;
124
125         while ((idlest == MODULE_CLKCTRL_IDLEST_DISABLED) ||
126                 (idlest == MODULE_CLKCTRL_IDLEST_TRANSITIONING)) {
127                 clkctrl = readl(clkctrl_addr);
128                 idlest = (clkctrl & MODULE_CLKCTRL_IDLEST_MASK) >>
129                          MODULE_CLKCTRL_IDLEST_SHIFT;
130                 if (--bound == 0) {
131                         printf("Clock enable failed for 0x%p idlest 0x%x\n",
132                                clkctrl_addr, clkctrl);
133                         return;
134                 }
135         }
136 }
137
138 static inline void enable_clock_module(u32 *const clkctrl_addr, u32 enable_mode,
139                                        u32 wait_for_enable)
140 {
141         clrsetbits_le32(clkctrl_addr, MODULE_CLKCTRL_MODULEMODE_MASK,
142                         enable_mode << MODULE_CLKCTRL_MODULEMODE_SHIFT);
143         debug("Enable clock module - %p\n", clkctrl_addr);
144         if (wait_for_enable)
145                 wait_for_clk_enable(clkctrl_addr);
146 }
147
148 static inline void wait_for_clk_disable(u32 *clkctrl_addr)
149 {
150         u32 clkctrl, idlest = MODULE_CLKCTRL_IDLEST_FULLY_FUNCTIONAL;
151         u32 bound = LDELAY;
152
153         while ((idlest != MODULE_CLKCTRL_IDLEST_DISABLED)) {
154                 clkctrl = readl(clkctrl_addr);
155                 idlest = (clkctrl & MODULE_CLKCTRL_IDLEST_MASK) >>
156                           MODULE_CLKCTRL_IDLEST_SHIFT;
157                 if (--bound == 0) {
158                         printf("Clock disable failed for 0x%p idlest 0x%x\n",
159                                clkctrl_addr, clkctrl);
160                          return;
161                 }
162         }
163 }
164 static inline void disable_clock_module(u32 *const clkctrl_addr,
165                                         u32 wait_for_disable)
166 {
167         clrsetbits_le32(clkctrl_addr, MODULE_CLKCTRL_MODULEMODE_MASK,
168                         MODULE_CLKCTRL_MODULEMODE_SW_DISABLE <<
169                         MODULE_CLKCTRL_MODULEMODE_SHIFT);
170         debug("Disable clock module - %p\n", clkctrl_addr);
171         if (wait_for_disable)
172                 wait_for_clk_disable(clkctrl_addr);
173 }
174
175 static inline void enable_clock_domain(u32 *const clkctrl_reg, u32 enable_mode)
176 {
177         clrsetbits_le32(clkctrl_reg, CD_CLKCTRL_CLKTRCTRL_MASK,
178                         enable_mode << CD_CLKCTRL_CLKTRCTRL_SHIFT);
179         debug("Enable clock domain - %p\n", clkctrl_reg);
180 }
181
182 static inline void disable_clock_domain(u32 *const clkctrl_reg)
183 {
184         clrsetbits_le32(clkctrl_reg, CD_CLKCTRL_CLKTRCTRL_MASK,
185                         CD_CLKCTRL_CLKTRCTRL_SW_SLEEP <<
186                         CD_CLKCTRL_CLKTRCTRL_SHIFT);
187         debug("Disable clock domain - %p\n", clkctrl_reg);
188 }
189
190 void do_enable_clocks(u32 *const *clk_domains,
191                       u32 *const *clk_modules_explicit_en, u8 wait_for_enable)
192 {
193         u32 i, max = 100;
194
195         /* Put the clock domains in SW_WKUP mode */
196         for (i = 0; (i < max) && clk_domains[i]; i++) {
197                 enable_clock_domain(clk_domains[i],
198                                     CD_CLKCTRL_CLKTRCTRL_SW_WKUP);
199         }
200
201         /* Clock modules that need to be put in SW_EXPLICIT_EN mode */
202         for (i = 0; (i < max) && clk_modules_explicit_en[i]; i++) {
203                 enable_clock_module(clk_modules_explicit_en[i],
204                                     MODULE_CLKCTRL_MODULEMODE_SW_EXPLICIT_EN,
205                                     wait_for_enable);
206         };
207 }
208
209 void do_disable_clocks(u32 *const *clk_domains,
210                         u32 *const *clk_modules_disable,
211                         u8 wait_for_disable)
212 {
213         u32 i, max = 100;
214
215
216         /* Clock modules that need to be put in SW_DISABLE */
217         for (i = 0; (i < max) && clk_modules_disable[i]; i++)
218                 disable_clock_module(clk_modules_disable[i],
219                                      wait_for_disable);
220
221         /* Put the clock domains in SW_SLEEP mode */
222         for (i = 0; (i < max) && clk_domains[i]; i++)
223                 disable_clock_domain(clk_domains[i]);
224 }
225
226 /*
227  * Before scaling up the clocks we need to have the PMIC scale up the
228  * voltages first.  This will be dependent on which PMIC is in use
229  * and in some cases we may not be scaling things up at all and thus not
230  * need to do anything here.
231  */
232 __weak void scale_vcores(void)
233 {
234 }
235
236 void setup_early_clocks(void)
237 {
238         setup_clocks_for_console();
239         enable_basic_clocks();
240         timer_init();
241 }
242
243 void prcm_init(void)
244 {
245         scale_vcores();
246         setup_dplls();
247 }
248
249 void rtc_only_prcm_init(void)
250 {
251         const struct dpll_params *params;
252
253         rtc_only_enable_basic_clocks();
254
255         params = get_dpll_ddr_params();
256         do_setup_dpll(&dpll_ddr_regs, params);
257 }