blob: fb3fb43dcc6b8e801b529c68f54b396f547a6196 [file] [log] [blame]
Chandan Nath4ba33452011-10-14 02:58:23 +00001/*
Matt Porter57da6662013-03-15 10:07:04 +00002 * clock_am33xx.c
Chandan Nath4ba33452011-10-14 02:58:23 +00003 *
4 * clocks for AM33XX based boards
5 *
Matt Porter57da6662013-03-15 10:07:04 +00006 * Copyright (C) 2013, Texas Instruments, Incorporated - http://www.ti.com/
Chandan Nath4ba33452011-10-14 02:58:23 +00007 *
Wolfgang Denkd79de1d2013-07-08 09:37:19 +02008 * SPDX-License-Identifier: GPL-2.0+
Chandan Nath4ba33452011-10-14 02:58:23 +00009 */
10
11#include <common.h>
12#include <asm/arch/cpu.h>
13#include <asm/arch/clock.h>
14#include <asm/arch/hardware.h>
15#include <asm/io.h>
16
17#define PRCM_MOD_EN 0x2
18#define PRCM_FORCE_WAKEUP 0x2
Chandan Nath2015c382012-07-24 12:22:17 +000019#define PRCM_FUNCTL 0x0
Chandan Nath4ba33452011-10-14 02:58:23 +000020
21#define PRCM_EMIF_CLK_ACTIVITY BIT(2)
22#define PRCM_L3_GCLK_ACTIVITY BIT(4)
23
24#define PLL_BYPASS_MODE 0x4
25#define ST_MN_BYPASS 0x00000100
26#define ST_DPLL_CLK 0x00000001
27#define CLK_SEL_MASK 0x7ffff
28#define CLK_DIV_MASK 0x1f
29#define CLK_DIV2_MASK 0x7f
30#define CLK_SEL_SHIFT 0x8
31#define CLK_MODE_SEL 0x7
32#define CLK_MODE_MASK 0xfffffff8
33#define CLK_DIV_SEL 0xFFFFFFE0
Chandan Nath2015c382012-07-24 12:22:17 +000034#define CPGMAC0_IDLE 0x30000
Ilya Yanok7aa1a6e2012-11-06 13:48:23 +000035#define DPLL_CLKDCOLDO_GATE_CTRL 0x300
Chandan Nath4ba33452011-10-14 02:58:23 +000036
Matt Porter57da6662013-03-15 10:07:04 +000037#define OSC (V_OSCK/1000000)
38
39#define MPUPLL_M CONFIG_SYS_MPUCLK
40#define MPUPLL_N (OSC-1)
41#define MPUPLL_M2 1
42
43/* Core PLL Fdll = 1 GHZ, */
44#define COREPLL_M 1000
45#define COREPLL_N (OSC-1)
46
47#define COREPLL_M4 10 /* CORE_CLKOUTM4 = 200 MHZ */
48#define COREPLL_M5 8 /* CORE_CLKOUTM5 = 250 MHZ */
49#define COREPLL_M6 4 /* CORE_CLKOUTM6 = 500 MHZ */
50
51/*
52 * USB PHY clock is 960 MHZ. Since, this comes directly from Fdll, Fdll
53 * frequency needs to be set to 960 MHZ. Hence,
54 * For clkout = 192 MHZ, Fdll = 960 MHZ, divider values are given below
55 */
56#define PERPLL_M 960
57#define PERPLL_N (OSC-1)
58#define PERPLL_M2 5
59
60/* DDR Freq is 266 MHZ for now */
61/* Set Fdll = 400 MHZ , Fdll = M * 2 * CLKINP/ N + 1; clkout = Fdll /(2 * M2) */
62#define DDRPLL_M 266
63#define DDRPLL_N (OSC-1)
64#define DDRPLL_M2 1
65
Chandan Nath4ba33452011-10-14 02:58:23 +000066const struct cm_perpll *cmper = (struct cm_perpll *)CM_PER;
67const struct cm_wkuppll *cmwkup = (struct cm_wkuppll *)CM_WKUP;
68const struct cm_dpll *cmdpll = (struct cm_dpll *)CM_DPLL;
Vaibhav Hiremath2d7da5f2012-03-08 17:15:47 +053069const struct cm_rtc *cmrtc = (struct cm_rtc *)CM_RTC;
Chandan Nath4ba33452011-10-14 02:58:23 +000070
71static void enable_interface_clocks(void)
72{
73 /* Enable all the Interconnect Modules */
74 writel(PRCM_MOD_EN, &cmper->l3clkctrl);
75 while (readl(&cmper->l3clkctrl) != PRCM_MOD_EN)
76 ;
77
78 writel(PRCM_MOD_EN, &cmper->l4lsclkctrl);
79 while (readl(&cmper->l4lsclkctrl) != PRCM_MOD_EN)
80 ;
81
82 writel(PRCM_MOD_EN, &cmper->l4fwclkctrl);
83 while (readl(&cmper->l4fwclkctrl) != PRCM_MOD_EN)
84 ;
85
86 writel(PRCM_MOD_EN, &cmwkup->wkl4wkclkctrl);
87 while (readl(&cmwkup->wkl4wkclkctrl) != PRCM_MOD_EN)
88 ;
89
90 writel(PRCM_MOD_EN, &cmper->l3instrclkctrl);
91 while (readl(&cmper->l3instrclkctrl) != PRCM_MOD_EN)
92 ;
93
94 writel(PRCM_MOD_EN, &cmper->l4hsclkctrl);
95 while (readl(&cmper->l4hsclkctrl) != PRCM_MOD_EN)
96 ;
Tom Rinif8bf6b22012-07-31 07:22:47 -070097
98 writel(PRCM_MOD_EN, &cmwkup->wkgpio0clkctrl);
99 while (readl(&cmwkup->wkgpio0clkctrl) != PRCM_MOD_EN)
100 ;
Chandan Nath4ba33452011-10-14 02:58:23 +0000101}
102
103/*
104 * Force power domain wake up transition
105 * Ensure that the corresponding interface clock is active before
106 * using the peripheral
107 */
108static void power_domain_wkup_transition(void)
109{
110 writel(PRCM_FORCE_WAKEUP, &cmper->l3clkstctrl);
111 writel(PRCM_FORCE_WAKEUP, &cmper->l4lsclkstctrl);
112 writel(PRCM_FORCE_WAKEUP, &cmwkup->wkclkstctrl);
113 writel(PRCM_FORCE_WAKEUP, &cmper->l4fwclkstctrl);
114 writel(PRCM_FORCE_WAKEUP, &cmper->l3sclkstctrl);
115}
116
117/*
118 * Enable the peripheral clock for required peripherals
119 */
120static void enable_per_clocks(void)
121{
122 /* Enable the control module though RBL would have done it*/
123 writel(PRCM_MOD_EN, &cmwkup->wkctrlclkctrl);
124 while (readl(&cmwkup->wkctrlclkctrl) != PRCM_MOD_EN)
125 ;
126
127 /* Enable the module clock */
128 writel(PRCM_MOD_EN, &cmper->timer2clkctrl);
129 while (readl(&cmper->timer2clkctrl) != PRCM_MOD_EN)
130 ;
131
Chandan Nath5b5c2122012-01-09 20:38:56 +0000132 /* Select the Master osc 24 MHZ as Timer2 clock source */
133 writel(0x1, &cmdpll->clktimer2clk);
134
Chandan Nath4ba33452011-10-14 02:58:23 +0000135 /* UART0 */
136 writel(PRCM_MOD_EN, &cmwkup->wkup_uart0ctrl);
137 while (readl(&cmwkup->wkup_uart0ctrl) != PRCM_MOD_EN)
138 ;
Chandan Nathd6e97f82012-01-09 20:38:58 +0000139
Andrew Bradfordcca45e72012-10-25 08:21:29 -0400140 /* UART1 */
141#ifdef CONFIG_SERIAL2
142 writel(PRCM_MOD_EN, &cmper->uart1clkctrl);
143 while (readl(&cmper->uart1clkctrl) != PRCM_MOD_EN)
144 ;
145#endif /* CONFIG_SERIAL2 */
146
147 /* UART2 */
148#ifdef CONFIG_SERIAL3
149 writel(PRCM_MOD_EN, &cmper->uart2clkctrl);
150 while (readl(&cmper->uart2clkctrl) != PRCM_MOD_EN)
151 ;
152#endif /* CONFIG_SERIAL3 */
153
154 /* UART3 */
155#ifdef CONFIG_SERIAL4
156 writel(PRCM_MOD_EN, &cmper->uart3clkctrl);
157 while (readl(&cmper->uart3clkctrl) != PRCM_MOD_EN)
158 ;
159#endif /* CONFIG_SERIAL4 */
160
161 /* UART4 */
162#ifdef CONFIG_SERIAL5
163 writel(PRCM_MOD_EN, &cmper->uart4clkctrl);
164 while (readl(&cmper->uart4clkctrl) != PRCM_MOD_EN)
165 ;
166#endif /* CONFIG_SERIAL5 */
167
168 /* UART5 */
169#ifdef CONFIG_SERIAL6
170 writel(PRCM_MOD_EN, &cmper->uart5clkctrl);
171 while (readl(&cmper->uart5clkctrl) != PRCM_MOD_EN)
172 ;
173#endif /* CONFIG_SERIAL6 */
174
Ilya Yanok2ebbb862012-11-06 13:06:30 +0000175 /* GPMC */
176 writel(PRCM_MOD_EN, &cmper->gpmcclkctrl);
177 while (readl(&cmper->gpmcclkctrl) != PRCM_MOD_EN)
178 ;
179
Mansoor Ahamed59e38b42012-11-06 13:06:32 +0000180 /* ELM */
181 writel(PRCM_MOD_EN, &cmper->elmclkctrl);
182 while (readl(&cmper->elmclkctrl) != PRCM_MOD_EN)
183 ;
184
Chandan Nathd6e97f82012-01-09 20:38:58 +0000185 /* MMC0*/
186 writel(PRCM_MOD_EN, &cmper->mmc0clkctrl);
187 while (readl(&cmper->mmc0clkctrl) != PRCM_MOD_EN)
188 ;
Patil, Rachna5f70c512012-01-22 23:47:01 +0000189
Tom Rini70718dc2013-04-03 08:50:01 +0000190 /* MMC1 */
191 writel(PRCM_MOD_EN, &cmper->mmc1clkctrl);
192 while (readl(&cmper->mmc1clkctrl) != PRCM_MOD_EN)
193 ;
194
Patil, Rachna5f70c512012-01-22 23:47:01 +0000195 /* i2c0 */
196 writel(PRCM_MOD_EN, &cmwkup->wkup_i2c0ctrl);
197 while (readl(&cmwkup->wkup_i2c0ctrl) != PRCM_MOD_EN)
198 ;
Steve Sakoman6229e332012-06-04 05:35:34 +0000199
200 /* gpio1 module */
201 writel(PRCM_MOD_EN, &cmper->gpio1clkctrl);
202 while (readl(&cmper->gpio1clkctrl) != PRCM_MOD_EN)
203 ;
204
205 /* gpio2 module */
206 writel(PRCM_MOD_EN, &cmper->gpio2clkctrl);
207 while (readl(&cmper->gpio2clkctrl) != PRCM_MOD_EN)
208 ;
209
210 /* gpio3 module */
211 writel(PRCM_MOD_EN, &cmper->gpio3clkctrl);
212 while (readl(&cmper->gpio3clkctrl) != PRCM_MOD_EN)
213 ;
Steve Sakoman695b1fe2012-06-22 07:45:57 +0000214
215 /* i2c1 */
216 writel(PRCM_MOD_EN, &cmper->i2c1clkctrl);
217 while (readl(&cmper->i2c1clkctrl) != PRCM_MOD_EN)
218 ;
Chandan Nath2015c382012-07-24 12:22:17 +0000219
220 /* Ethernet */
221 writel(PRCM_MOD_EN, &cmper->cpgmac0clkctrl);
222 while ((readl(&cmper->cpgmac0clkctrl) & CPGMAC0_IDLE) != PRCM_FUNCTL)
223 ;
Tom Rini470e2a22012-08-08 14:29:51 -0700224
225 /* spi0 */
226 writel(PRCM_MOD_EN, &cmper->spi0clkctrl);
227 while (readl(&cmper->spi0clkctrl) != PRCM_MOD_EN)
228 ;
Vaibhav Hiremath2d7da5f2012-03-08 17:15:47 +0530229
230 /* RTC */
231 writel(PRCM_MOD_EN, &cmrtc->rtcclkctrl);
232 while (readl(&cmrtc->rtcclkctrl) != PRCM_MOD_EN)
233 ;
Ilya Yanok7aa1a6e2012-11-06 13:48:23 +0000234
235 /* MUSB */
236 writel(PRCM_MOD_EN, &cmper->usb0clkctrl);
237 while (readl(&cmper->usb0clkctrl) != PRCM_MOD_EN)
238 ;
Chandan Nath4ba33452011-10-14 02:58:23 +0000239}
240
Heiko Schocher0ef08172013-06-04 11:01:06 +0200241void mpu_pll_config_val(int mpull_m)
Chandan Nath4ba33452011-10-14 02:58:23 +0000242{
243 u32 clkmode, clksel, div_m2;
244
245 clkmode = readl(&cmwkup->clkmoddpllmpu);
246 clksel = readl(&cmwkup->clkseldpllmpu);
247 div_m2 = readl(&cmwkup->divm2dpllmpu);
248
249 /* Set the PLL to bypass Mode */
250 writel(PLL_BYPASS_MODE, &cmwkup->clkmoddpllmpu);
251 while (readl(&cmwkup->idlestdpllmpu) != ST_MN_BYPASS)
252 ;
253
254 clksel = clksel & (~CLK_SEL_MASK);
Heiko Schocher0ef08172013-06-04 11:01:06 +0200255 clksel = clksel | ((mpull_m << CLK_SEL_SHIFT) | MPUPLL_N);
Chandan Nath4ba33452011-10-14 02:58:23 +0000256 writel(clksel, &cmwkup->clkseldpllmpu);
257
258 div_m2 = div_m2 & ~CLK_DIV_MASK;
259 div_m2 = div_m2 | MPUPLL_M2;
260 writel(div_m2, &cmwkup->divm2dpllmpu);
261
262 clkmode = clkmode | CLK_MODE_SEL;
263 writel(clkmode, &cmwkup->clkmoddpllmpu);
264
265 while (readl(&cmwkup->idlestdpllmpu) != ST_DPLL_CLK)
266 ;
267}
268
Heiko Schocher0ef08172013-06-04 11:01:06 +0200269static void mpu_pll_config(void)
270{
271 mpu_pll_config_val(CONFIG_SYS_MPUCLK);
272}
273
Chandan Nath4ba33452011-10-14 02:58:23 +0000274static void core_pll_config(void)
275{
276 u32 clkmode, clksel, div_m4, div_m5, div_m6;
277
278 clkmode = readl(&cmwkup->clkmoddpllcore);
279 clksel = readl(&cmwkup->clkseldpllcore);
280 div_m4 = readl(&cmwkup->divm4dpllcore);
281 div_m5 = readl(&cmwkup->divm5dpllcore);
282 div_m6 = readl(&cmwkup->divm6dpllcore);
283
284 /* Set the PLL to bypass Mode */
285 writel(PLL_BYPASS_MODE, &cmwkup->clkmoddpllcore);
286
287 while (readl(&cmwkup->idlestdpllcore) != ST_MN_BYPASS)
288 ;
289
290 clksel = clksel & (~CLK_SEL_MASK);
291 clksel = clksel | ((COREPLL_M << CLK_SEL_SHIFT) | COREPLL_N);
292 writel(clksel, &cmwkup->clkseldpllcore);
293
294 div_m4 = div_m4 & ~CLK_DIV_MASK;
295 div_m4 = div_m4 | COREPLL_M4;
296 writel(div_m4, &cmwkup->divm4dpllcore);
297
298 div_m5 = div_m5 & ~CLK_DIV_MASK;
299 div_m5 = div_m5 | COREPLL_M5;
300 writel(div_m5, &cmwkup->divm5dpllcore);
301
302 div_m6 = div_m6 & ~CLK_DIV_MASK;
303 div_m6 = div_m6 | COREPLL_M6;
304 writel(div_m6, &cmwkup->divm6dpllcore);
305
306 clkmode = clkmode | CLK_MODE_SEL;
307 writel(clkmode, &cmwkup->clkmoddpllcore);
308
309 while (readl(&cmwkup->idlestdpllcore) != ST_DPLL_CLK)
310 ;
311}
312
313static void per_pll_config(void)
314{
315 u32 clkmode, clksel, div_m2;
316
317 clkmode = readl(&cmwkup->clkmoddpllper);
318 clksel = readl(&cmwkup->clkseldpllper);
319 div_m2 = readl(&cmwkup->divm2dpllper);
320
321 /* Set the PLL to bypass Mode */
322 writel(PLL_BYPASS_MODE, &cmwkup->clkmoddpllper);
323
324 while (readl(&cmwkup->idlestdpllper) != ST_MN_BYPASS)
325 ;
326
327 clksel = clksel & (~CLK_SEL_MASK);
328 clksel = clksel | ((PERPLL_M << CLK_SEL_SHIFT) | PERPLL_N);
329 writel(clksel, &cmwkup->clkseldpllper);
330
331 div_m2 = div_m2 & ~CLK_DIV2_MASK;
332 div_m2 = div_m2 | PERPLL_M2;
333 writel(div_m2, &cmwkup->divm2dpllper);
334
335 clkmode = clkmode | CLK_MODE_SEL;
336 writel(clkmode, &cmwkup->clkmoddpllper);
337
338 while (readl(&cmwkup->idlestdpllper) != ST_DPLL_CLK)
339 ;
Ilya Yanok7aa1a6e2012-11-06 13:48:23 +0000340
341 writel(DPLL_CLKDCOLDO_GATE_CTRL, &cmwkup->clkdcoldodpllper);
Chandan Nath4ba33452011-10-14 02:58:23 +0000342}
343
Tom Rini034aba72012-07-03 09:20:06 -0700344void ddr_pll_config(unsigned int ddrpll_m)
Chandan Nath4ba33452011-10-14 02:58:23 +0000345{
346 u32 clkmode, clksel, div_m2;
347
348 clkmode = readl(&cmwkup->clkmoddpllddr);
349 clksel = readl(&cmwkup->clkseldpllddr);
350 div_m2 = readl(&cmwkup->divm2dpllddr);
351
352 /* Set the PLL to bypass Mode */
353 clkmode = (clkmode & CLK_MODE_MASK) | PLL_BYPASS_MODE;
354 writel(clkmode, &cmwkup->clkmoddpllddr);
355
356 /* Wait till bypass mode is enabled */
357 while ((readl(&cmwkup->idlestdpllddr) & ST_MN_BYPASS)
358 != ST_MN_BYPASS)
359 ;
360
361 clksel = clksel & (~CLK_SEL_MASK);
Tom Rini034aba72012-07-03 09:20:06 -0700362 clksel = clksel | ((ddrpll_m << CLK_SEL_SHIFT) | DDRPLL_N);
Chandan Nath4ba33452011-10-14 02:58:23 +0000363 writel(clksel, &cmwkup->clkseldpllddr);
364
365 div_m2 = div_m2 & CLK_DIV_SEL;
366 div_m2 = div_m2 | DDRPLL_M2;
367 writel(div_m2, &cmwkup->divm2dpllddr);
368
369 clkmode = (clkmode & CLK_MODE_MASK) | CLK_MODE_SEL;
370 writel(clkmode, &cmwkup->clkmoddpllddr);
371
372 /* Wait till dpll is locked */
373 while ((readl(&cmwkup->idlestdpllddr) & ST_DPLL_CLK) != ST_DPLL_CLK)
374 ;
375}
376
377void enable_emif_clocks(void)
378{
379 /* Enable the EMIF_FW Functional clock */
380 writel(PRCM_MOD_EN, &cmper->emiffwclkctrl);
381 /* Enable EMIF0 Clock */
382 writel(PRCM_MOD_EN, &cmper->emifclkctrl);
Chandan Nath4ba33452011-10-14 02:58:23 +0000383 /* Poll if module is functional */
384 while ((readl(&cmper->emifclkctrl)) != PRCM_MOD_EN)
385 ;
386}
387
388/*
389 * Configure the PLL/PRCM for necessary peripherals
390 */
391void pll_init()
392{
393 mpu_pll_config();
394 core_pll_config();
395 per_pll_config();
Chandan Nath4ba33452011-10-14 02:58:23 +0000396
397 /* Enable the required interconnect clocks */
398 enable_interface_clocks();
399
400 /* Power domain wake up transition */
401 power_domain_wkup_transition();
402
403 /* Enable the required peripherals */
404 enable_per_clocks();
405}