e3c4fd89f32e37b72af4a44a9150d5b686104d32
[oweals/u-boot.git] / arch / arm / cpu / armv7 / am33xx / clock.c
1 /*
2  * clock.c
3  *
4  * clocks for AM33XX based boards
5  *
6  * Copyright (C) 2011, Texas Instruments, Incorporated - http://www.ti.com/
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License as
10  * published by the Free Software Foundation; either version 2 of
11  * the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR /PURPOSE.  See the
16  * GNU General Public License for more details.
17  */
18
19 #include <common.h>
20 #include <asm/arch/cpu.h>
21 #include <asm/arch/clock.h>
22 #include <asm/arch/hardware.h>
23 #include <asm/io.h>
24
25 #define PRCM_MOD_EN             0x2
26 #define PRCM_FORCE_WAKEUP       0x2
27 #define PRCM_FUNCTL             0x0
28
29 #define PRCM_EMIF_CLK_ACTIVITY  BIT(2)
30 #define PRCM_L3_GCLK_ACTIVITY   BIT(4)
31
32 #define PLL_BYPASS_MODE         0x4
33 #define ST_MN_BYPASS            0x00000100
34 #define ST_DPLL_CLK             0x00000001
35 #define CLK_SEL_MASK            0x7ffff
36 #define CLK_DIV_MASK            0x1f
37 #define CLK_DIV2_MASK           0x7f
38 #define CLK_SEL_SHIFT           0x8
39 #define CLK_MODE_SEL            0x7
40 #define CLK_MODE_MASK           0xfffffff8
41 #define CLK_DIV_SEL             0xFFFFFFE0
42 #define CPGMAC0_IDLE            0x30000
43
44 const struct cm_perpll *cmper = (struct cm_perpll *)CM_PER;
45 const struct cm_wkuppll *cmwkup = (struct cm_wkuppll *)CM_WKUP;
46 const struct cm_dpll *cmdpll = (struct cm_dpll *)CM_DPLL;
47
48 static void enable_interface_clocks(void)
49 {
50         /* Enable all the Interconnect Modules */
51         writel(PRCM_MOD_EN, &cmper->l3clkctrl);
52         while (readl(&cmper->l3clkctrl) != PRCM_MOD_EN)
53                 ;
54
55         writel(PRCM_MOD_EN, &cmper->l4lsclkctrl);
56         while (readl(&cmper->l4lsclkctrl) != PRCM_MOD_EN)
57                 ;
58
59         writel(PRCM_MOD_EN, &cmper->l4fwclkctrl);
60         while (readl(&cmper->l4fwclkctrl) != PRCM_MOD_EN)
61                 ;
62
63         writel(PRCM_MOD_EN, &cmwkup->wkl4wkclkctrl);
64         while (readl(&cmwkup->wkl4wkclkctrl) != PRCM_MOD_EN)
65                 ;
66
67         writel(PRCM_MOD_EN, &cmper->l3instrclkctrl);
68         while (readl(&cmper->l3instrclkctrl) != PRCM_MOD_EN)
69                 ;
70
71         writel(PRCM_MOD_EN, &cmper->l4hsclkctrl);
72         while (readl(&cmper->l4hsclkctrl) != PRCM_MOD_EN)
73                 ;
74 }
75
76 /*
77  * Force power domain wake up transition
78  * Ensure that the corresponding interface clock is active before
79  * using the peripheral
80  */
81 static void power_domain_wkup_transition(void)
82 {
83         writel(PRCM_FORCE_WAKEUP, &cmper->l3clkstctrl);
84         writel(PRCM_FORCE_WAKEUP, &cmper->l4lsclkstctrl);
85         writel(PRCM_FORCE_WAKEUP, &cmwkup->wkclkstctrl);
86         writel(PRCM_FORCE_WAKEUP, &cmper->l4fwclkstctrl);
87         writel(PRCM_FORCE_WAKEUP, &cmper->l3sclkstctrl);
88 }
89
90 /*
91  * Enable the peripheral clock for required peripherals
92  */
93 static void enable_per_clocks(void)
94 {
95         /* Enable the control module though RBL would have done it*/
96         writel(PRCM_MOD_EN, &cmwkup->wkctrlclkctrl);
97         while (readl(&cmwkup->wkctrlclkctrl) != PRCM_MOD_EN)
98                 ;
99
100         /* Enable the module clock */
101         writel(PRCM_MOD_EN, &cmper->timer2clkctrl);
102         while (readl(&cmper->timer2clkctrl) != PRCM_MOD_EN)
103                 ;
104
105         /* Select the Master osc 24 MHZ as Timer2 clock source */
106         writel(0x1, &cmdpll->clktimer2clk);
107
108         /* UART0 */
109         writel(PRCM_MOD_EN, &cmwkup->wkup_uart0ctrl);
110         while (readl(&cmwkup->wkup_uart0ctrl) != PRCM_MOD_EN)
111                 ;
112
113         /* MMC0*/
114         writel(PRCM_MOD_EN, &cmper->mmc0clkctrl);
115         while (readl(&cmper->mmc0clkctrl) != PRCM_MOD_EN)
116                 ;
117
118         /* i2c0 */
119         writel(PRCM_MOD_EN, &cmwkup->wkup_i2c0ctrl);
120         while (readl(&cmwkup->wkup_i2c0ctrl) != PRCM_MOD_EN)
121                 ;
122
123         /* gpio1 module */
124         writel(PRCM_MOD_EN, &cmper->gpio1clkctrl);
125         while (readl(&cmper->gpio1clkctrl) != PRCM_MOD_EN)
126                 ;
127
128         /* gpio2 module */
129         writel(PRCM_MOD_EN, &cmper->gpio2clkctrl);
130         while (readl(&cmper->gpio2clkctrl) != PRCM_MOD_EN)
131                 ;
132
133         /* gpio3 module */
134         writel(PRCM_MOD_EN, &cmper->gpio3clkctrl);
135         while (readl(&cmper->gpio3clkctrl) != PRCM_MOD_EN)
136                 ;
137
138         /* i2c1 */
139         writel(PRCM_MOD_EN, &cmper->i2c1clkctrl);
140         while (readl(&cmper->i2c1clkctrl) != PRCM_MOD_EN)
141                 ;
142
143         /* Ethernet */
144         writel(PRCM_MOD_EN, &cmper->cpgmac0clkctrl);
145         while ((readl(&cmper->cpgmac0clkctrl) & CPGMAC0_IDLE) != PRCM_FUNCTL)
146                 ;
147 }
148
149 static void mpu_pll_config(void)
150 {
151         u32 clkmode, clksel, div_m2;
152
153         clkmode = readl(&cmwkup->clkmoddpllmpu);
154         clksel = readl(&cmwkup->clkseldpllmpu);
155         div_m2 = readl(&cmwkup->divm2dpllmpu);
156
157         /* Set the PLL to bypass Mode */
158         writel(PLL_BYPASS_MODE, &cmwkup->clkmoddpllmpu);
159         while (readl(&cmwkup->idlestdpllmpu) != ST_MN_BYPASS)
160                 ;
161
162         clksel = clksel & (~CLK_SEL_MASK);
163         clksel = clksel | ((MPUPLL_M << CLK_SEL_SHIFT) | MPUPLL_N);
164         writel(clksel, &cmwkup->clkseldpllmpu);
165
166         div_m2 = div_m2 & ~CLK_DIV_MASK;
167         div_m2 = div_m2 | MPUPLL_M2;
168         writel(div_m2, &cmwkup->divm2dpllmpu);
169
170         clkmode = clkmode | CLK_MODE_SEL;
171         writel(clkmode, &cmwkup->clkmoddpllmpu);
172
173         while (readl(&cmwkup->idlestdpllmpu) != ST_DPLL_CLK)
174                 ;
175 }
176
177 static void core_pll_config(void)
178 {
179         u32 clkmode, clksel, div_m4, div_m5, div_m6;
180
181         clkmode = readl(&cmwkup->clkmoddpllcore);
182         clksel = readl(&cmwkup->clkseldpllcore);
183         div_m4 = readl(&cmwkup->divm4dpllcore);
184         div_m5 = readl(&cmwkup->divm5dpllcore);
185         div_m6 = readl(&cmwkup->divm6dpllcore);
186
187         /* Set the PLL to bypass Mode */
188         writel(PLL_BYPASS_MODE, &cmwkup->clkmoddpllcore);
189
190         while (readl(&cmwkup->idlestdpllcore) != ST_MN_BYPASS)
191                 ;
192
193         clksel = clksel & (~CLK_SEL_MASK);
194         clksel = clksel | ((COREPLL_M << CLK_SEL_SHIFT) | COREPLL_N);
195         writel(clksel, &cmwkup->clkseldpllcore);
196
197         div_m4 = div_m4 & ~CLK_DIV_MASK;
198         div_m4 = div_m4 | COREPLL_M4;
199         writel(div_m4, &cmwkup->divm4dpllcore);
200
201         div_m5 = div_m5 & ~CLK_DIV_MASK;
202         div_m5 = div_m5 | COREPLL_M5;
203         writel(div_m5, &cmwkup->divm5dpllcore);
204
205         div_m6 = div_m6 & ~CLK_DIV_MASK;
206         div_m6 = div_m6 | COREPLL_M6;
207         writel(div_m6, &cmwkup->divm6dpllcore);
208
209         clkmode = clkmode | CLK_MODE_SEL;
210         writel(clkmode, &cmwkup->clkmoddpllcore);
211
212         while (readl(&cmwkup->idlestdpllcore) != ST_DPLL_CLK)
213                 ;
214 }
215
216 static void per_pll_config(void)
217 {
218         u32 clkmode, clksel, div_m2;
219
220         clkmode = readl(&cmwkup->clkmoddpllper);
221         clksel = readl(&cmwkup->clkseldpllper);
222         div_m2 = readl(&cmwkup->divm2dpllper);
223
224         /* Set the PLL to bypass Mode */
225         writel(PLL_BYPASS_MODE, &cmwkup->clkmoddpllper);
226
227         while (readl(&cmwkup->idlestdpllper) != ST_MN_BYPASS)
228                 ;
229
230         clksel = clksel & (~CLK_SEL_MASK);
231         clksel = clksel | ((PERPLL_M << CLK_SEL_SHIFT) | PERPLL_N);
232         writel(clksel, &cmwkup->clkseldpllper);
233
234         div_m2 = div_m2 & ~CLK_DIV2_MASK;
235         div_m2 = div_m2 | PERPLL_M2;
236         writel(div_m2, &cmwkup->divm2dpllper);
237
238         clkmode = clkmode | CLK_MODE_SEL;
239         writel(clkmode, &cmwkup->clkmoddpllper);
240
241         while (readl(&cmwkup->idlestdpllper) != ST_DPLL_CLK)
242                 ;
243 }
244
245 static void ddr_pll_config(void)
246 {
247         u32 clkmode, clksel, div_m2;
248
249         clkmode = readl(&cmwkup->clkmoddpllddr);
250         clksel = readl(&cmwkup->clkseldpllddr);
251         div_m2 = readl(&cmwkup->divm2dpllddr);
252
253         /* Set the PLL to bypass Mode */
254         clkmode = (clkmode & CLK_MODE_MASK) | PLL_BYPASS_MODE;
255         writel(clkmode, &cmwkup->clkmoddpllddr);
256
257         /* Wait till bypass mode is enabled */
258         while ((readl(&cmwkup->idlestdpllddr) & ST_MN_BYPASS)
259                                 != ST_MN_BYPASS)
260                 ;
261
262         clksel = clksel & (~CLK_SEL_MASK);
263         clksel = clksel | ((DDRPLL_M << CLK_SEL_SHIFT) | DDRPLL_N);
264         writel(clksel, &cmwkup->clkseldpllddr);
265
266         div_m2 = div_m2 & CLK_DIV_SEL;
267         div_m2 = div_m2 | DDRPLL_M2;
268         writel(div_m2, &cmwkup->divm2dpllddr);
269
270         clkmode = (clkmode & CLK_MODE_MASK) | CLK_MODE_SEL;
271         writel(clkmode, &cmwkup->clkmoddpllddr);
272
273         /* Wait till dpll is locked */
274         while ((readl(&cmwkup->idlestdpllddr) & ST_DPLL_CLK) != ST_DPLL_CLK)
275                 ;
276 }
277
278 void enable_emif_clocks(void)
279 {
280         /* Enable the  EMIF_FW Functional clock */
281         writel(PRCM_MOD_EN, &cmper->emiffwclkctrl);
282         /* Enable EMIF0 Clock */
283         writel(PRCM_MOD_EN, &cmper->emifclkctrl);
284         /* Poll for emif_gclk  & L3_G clock  are active */
285         while ((readl(&cmper->l3clkstctrl) & (PRCM_EMIF_CLK_ACTIVITY |
286                         PRCM_L3_GCLK_ACTIVITY)) != (PRCM_EMIF_CLK_ACTIVITY |
287                         PRCM_L3_GCLK_ACTIVITY))
288                 ;
289         /* Poll if module is functional */
290         while ((readl(&cmper->emifclkctrl)) != PRCM_MOD_EN)
291                 ;
292 }
293
294 /*
295  * Configure the PLL/PRCM for necessary peripherals
296  */
297 void pll_init()
298 {
299         mpu_pll_config();
300         core_pll_config();
301         per_pll_config();
302         ddr_pll_config();
303
304         /* Enable the required interconnect clocks */
305         enable_interface_clocks();
306
307         /* Power domain wake up transition */
308         power_domain_wkup_transition();
309
310         /* Enable the required peripherals */
311         enable_per_clocks();
312 }