4 * clocks for AM33XX based boards
6 * Copyright (C) 2011, Texas Instruments, Incorporated - http://www.ti.com/
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.
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.
20 #include <asm/arch/cpu.h>
21 #include <asm/arch/clock.h>
22 #include <asm/arch/hardware.h>
25 #define PRCM_MOD_EN 0x2
26 #define PRCM_FORCE_WAKEUP 0x2
28 #define PRCM_EMIF_CLK_ACTIVITY BIT(2)
29 #define PRCM_L3_GCLK_ACTIVITY BIT(4)
31 #define PLL_BYPASS_MODE 0x4
32 #define ST_MN_BYPASS 0x00000100
33 #define ST_DPLL_CLK 0x00000001
34 #define CLK_SEL_MASK 0x7ffff
35 #define CLK_DIV_MASK 0x1f
36 #define CLK_DIV2_MASK 0x7f
37 #define CLK_SEL_SHIFT 0x8
38 #define CLK_MODE_MASK 0x7
39 #define CLK_MODE_SEL 0x7
42 const struct cm_perpll *cmper = (struct cm_perpll *)CM_PER;
43 const struct cm_wkuppll *cmwkup = (struct cm_wkuppll *)CM_WKUP;
44 const struct cm_dpll *cmdpll = (struct cm_dpll *)CM_DPLL;
46 #ifdef CONFIG_SPL_BUILD
47 #define enable_clk(reg, val) __enable_clk(#reg, ®, val)
49 static void __enable_clk(const char *name, const void *reg, u32 mask)
51 unsigned long timeout = 10000000;
54 while (readl(reg) != mask)
55 /* poor man's timeout, since timers not initialized */
57 /* no error message, since console not yet available */
61 static void enable_interface_clocks(void)
63 /* Enable all the Interconnect Modules */
64 enable_clk(cmper->l3clkctrl, PRCM_MOD_EN);
65 enable_clk(cmper->l4lsclkctrl, PRCM_MOD_EN);
66 enable_clk(cmper->l4fwclkctrl, PRCM_MOD_EN);
67 enable_clk(cmwkup->wkl4wkclkctrl, PRCM_MOD_EN);
68 enable_clk(cmper->l3instrclkctrl, PRCM_MOD_EN);
69 enable_clk(cmper->l4hsclkctrl, PRCM_MOD_EN);
70 #ifdef CONFIG_HW_WATCHDOG
71 enable_clk(cmwkup->wdtimer1ctrl, PRCM_MOD_EN);
74 enable_clk(cmwkup->gpio0clkctrl, PRCM_MOD_EN);
78 * Force power domain wake up transition
79 * Ensure that the corresponding interface clock is active before
80 * using the peripheral
82 static void power_domain_wkup_transition(void)
84 writel(PRCM_FORCE_WAKEUP, &cmper->l3clkstctrl);
85 writel(PRCM_FORCE_WAKEUP, &cmper->l4lsclkstctrl);
86 writel(PRCM_FORCE_WAKEUP, &cmwkup->wkclkstctrl);
87 writel(PRCM_FORCE_WAKEUP, &cmper->l4fwclkstctrl);
88 writel(PRCM_FORCE_WAKEUP, &cmper->l3sclkstctrl);
92 * Enable the peripheral clock for required peripherals
94 static void enable_per_clocks(void)
96 /* Enable the control module though RBL would have done it*/
97 enable_clk(cmwkup->wkctrlclkctrl, PRCM_MOD_EN);
98 /* Enable the timer2 clock */
99 enable_clk(cmper->timer2clkctrl, PRCM_MOD_EN);
100 /* Select the Master osc 24 MHZ as Timer2 clock source */
101 writel(0x1, &cmdpll->clktimer2clk);
103 #ifdef CONFIG_SYS_NS16550_COM1
105 enable_clk(cmwkup->wkup_uart0ctrl, PRCM_MOD_EN);
107 #ifdef CONFIG_SYS_NS16550_COM2
108 enable_clk(cmper->uart1clkctrl, PRCM_MOD_EN);
110 #ifdef CONFIG_SYS_NS16550_COM3
111 enable_clk(cmper->uart2clkctrl, PRCM_MOD_EN);
113 #ifdef CONFIG_SYS_NS16550_COM4
114 enable_clk(cmper->uart3clkctrl, PRCM_MOD_EN);
116 #ifdef CONFIG_SYS_NS16550_COM5
117 enable_clk(cmper->uart4clkctrl, PRCM_MOD_EN);
119 #ifdef CONFIG_SYS_NS16550_COM6
120 enable_clk(cmper->uart5clkctrl, PRCM_MOD_EN);
123 enable_clk(cmper->gpmcclkctrl, PRCM_MOD_EN);
126 enable_clk(cmper->elmclkctrl, PRCM_MOD_EN);
129 enable_clk(cmper->cpswclkctrl, PRCM_MOD_EN);
130 enable_clk(cmper->cpgmac0clkctrl, PRCM_MOD_EN);
133 #ifndef CONFIG_OMAP_MMC_DEV_0
134 enable_clk(cmper->mmc0clkctrl, PRCM_MOD_EN);
136 #ifdef CONFIG_OMAP_MMC_DEV_1
137 enable_clk(cmper->mmc1clkctrl, PRCM_MOD_EN);
140 enable_clk(cmper->lcdcclkctrl, PRCM_MOD_EN);
143 enable_clk(cmwkup->wkup_i2c0ctrl, PRCM_MOD_EN);
146 enable_clk(cmper->gpio1clkctrl, PRCM_MOD_EN);
147 enable_clk(cmper->gpio2clkctrl, PRCM_MOD_EN);
148 enable_clk(cmper->gpio3clkctrl, PRCM_MOD_EN);
151 static void mpu_pll_config(void)
153 u32 clkmode, clksel, div_m2;
155 clkmode = readl(&cmwkup->clkmoddpllmpu);
156 clksel = readl(&cmwkup->clkseldpllmpu);
157 div_m2 = readl(&cmwkup->divm2dpllmpu);
159 /* Set the PLL to bypass Mode */
160 writel(PLL_BYPASS_MODE, &cmwkup->clkmoddpllmpu);
161 while (readl(&cmwkup->idlestdpllmpu) != ST_MN_BYPASS)
164 clksel &= ~CLK_SEL_MASK;
165 clksel |= (MPUPLL_M << CLK_SEL_SHIFT) | MPUPLL_N;
166 writel(clksel, &cmwkup->clkseldpllmpu);
168 div_m2 &= ~CLK_DIV_MASK;
170 writel(div_m2, &cmwkup->divm2dpllmpu);
172 clkmode &= ~CLK_MODE_MASK;
173 clkmode |= CLK_MODE_SEL;
174 writel(clkmode, &cmwkup->clkmoddpllmpu);
176 while (readl(&cmwkup->idlestdpllmpu) != ST_DPLL_CLK)
180 static void core_pll_config(void)
182 u32 clkmode, clksel, div_m4, div_m5, div_m6;
184 clkmode = readl(&cmwkup->clkmoddpllcore);
185 clksel = readl(&cmwkup->clkseldpllcore);
186 div_m4 = readl(&cmwkup->divm4dpllcore);
187 div_m5 = readl(&cmwkup->divm5dpllcore);
188 div_m6 = readl(&cmwkup->divm6dpllcore);
190 /* Set the PLL to bypass Mode */
191 writel(PLL_BYPASS_MODE, &cmwkup->clkmoddpllcore);
193 while (readl(&cmwkup->idlestdpllcore) != ST_MN_BYPASS)
196 clksel &= ~CLK_SEL_MASK;
197 clksel |= ((COREPLL_M << CLK_SEL_SHIFT) | COREPLL_N);
198 writel(clksel, &cmwkup->clkseldpllcore);
200 div_m4 &= ~CLK_DIV_MASK;
201 div_m4 |= COREPLL_M4;
202 writel(div_m4, &cmwkup->divm4dpllcore);
204 div_m5 &= ~CLK_DIV_MASK;
205 div_m5 |= COREPLL_M5;
206 writel(div_m5, &cmwkup->divm5dpllcore);
208 div_m6 &= ~CLK_DIV_MASK;
209 div_m6 |= COREPLL_M6;
210 writel(div_m6, &cmwkup->divm6dpllcore);
212 clkmode &= ~CLK_MODE_MASK;
213 clkmode |= CLK_MODE_SEL;
214 writel(clkmode, &cmwkup->clkmoddpllcore);
216 while (readl(&cmwkup->idlestdpllcore) != ST_DPLL_CLK)
220 static void per_pll_config(void)
222 u32 clkmode, clksel, div_m2;
224 clkmode = readl(&cmwkup->clkmoddpllper);
225 clksel = readl(&cmwkup->clkseldpllper);
226 div_m2 = readl(&cmwkup->divm2dpllper);
228 /* Set the PLL to bypass Mode */
229 writel(PLL_BYPASS_MODE, &cmwkup->clkmoddpllper);
231 while (readl(&cmwkup->idlestdpllper) != ST_MN_BYPASS)
234 clksel &= ~CLK_SEL_MASK;
235 clksel |= (PERPLL_M << CLK_SEL_SHIFT) | PERPLL_N;
236 writel(clksel, &cmwkup->clkseldpllper);
238 div_m2 &= ~CLK_DIV2_MASK;
240 writel(div_m2, &cmwkup->divm2dpllper);
242 clkmode &= ~CLK_MODE_MASK;
243 clkmode |= CLK_MODE_SEL;
244 writel(clkmode, &cmwkup->clkmoddpllper);
246 while (readl(&cmwkup->idlestdpllper) != ST_DPLL_CLK)
250 static void disp_pll_config(void)
253 u32 clkmode, clksel, div_m2;
255 clkmode = readl(&cmwkup->clkmoddplldisp);
256 clksel = readl(&cmwkup->clkseldplldisp);
257 div_m2 = readl(&cmwkup->divm2dplldisp);
259 /* Set the PLL to bypass Mode */
260 writel(PLL_BYPASS_MODE, &cmwkup->clkmoddplldisp);
262 while (!(readl(&cmwkup->idlestdplldisp) & ST_MN_BYPASS))
265 clksel &= ~CLK_SEL_MASK;
266 clksel |= (DISPPLL_M << CLK_SEL_SHIFT) | DISPPLL_N;
267 writel(clksel, &cmwkup->clkseldplldisp);
269 div_m2 &= ~CLK_DIV2_MASK;
270 div_m2 |= DISPPLL_M2;
271 writel(div_m2, &cmwkup->divm2dplldisp);
273 clkmode &= ~CLK_MODE_MASK;
274 clkmode |= CLK_MODE_SEL;
275 writel(clkmode, &cmwkup->clkmoddplldisp);
277 while (!(readl(&cmwkup->idlestdplldisp) & ST_DPLL_CLK))
282 static void ddr_pll_config(void)
284 u32 clkmode, clksel, div_m2;
286 clkmode = readl(&cmwkup->clkmoddpllddr);
287 clksel = readl(&cmwkup->clkseldpllddr);
288 div_m2 = readl(&cmwkup->divm2dpllddr);
290 /* Set the PLL to bypass Mode */
291 clkmode &= ~CLK_MODE_MASK;
292 clkmode |= PLL_BYPASS_MODE;
293 writel(clkmode, &cmwkup->clkmoddpllddr);
295 /* Wait till bypass mode is enabled */
296 while (!(readl(&cmwkup->idlestdpllddr) & ST_MN_BYPASS))
299 clksel &= ~CLK_SEL_MASK;
300 clksel |= (DDRPLL_M << CLK_SEL_SHIFT) | DDRPLL_N;
301 writel(clksel, &cmwkup->clkseldpllddr);
303 div_m2 &= ~CLK_DIV_MASK;
305 writel(div_m2, &cmwkup->divm2dpllddr);
307 clkmode &= ~CLK_MODE_MASK;
308 clkmode |= CLK_MODE_SEL;
309 writel(clkmode, &cmwkup->clkmoddpllddr);
311 /* Wait till dpll is locked */
312 while ((readl(&cmwkup->idlestdpllddr) & ST_DPLL_CLK) != ST_DPLL_CLK)
316 void enable_emif_clocks(void)
318 /* Enable the EMIF_FW Functional clock */
319 writel(PRCM_MOD_EN, &cmper->emiffwclkctrl);
320 /* Enable EMIF0 Clock */
321 writel(PRCM_MOD_EN, &cmper->emifclkctrl);
322 /* Poll for emif_gclk & L3_G clock are active */
323 while ((readl(&cmper->l3clkstctrl) & (PRCM_EMIF_CLK_ACTIVITY |
324 PRCM_L3_GCLK_ACTIVITY)) != (PRCM_EMIF_CLK_ACTIVITY |
325 PRCM_L3_GCLK_ACTIVITY))
327 /* Poll if module is functional */
328 while ((readl(&cmper->emifclkctrl)) != PRCM_MOD_EN)
333 * Configure the PLL/PRCM for necessary peripherals
343 /* Enable the required interconnect clocks */
344 enable_interface_clocks();
346 /* Power domain wake up transition */
347 power_domain_wkup_transition();
349 /* Enable the required peripherals */
354 #define M(mn) (((mn) & CLK_SEL_MASK) >> CLK_SEL_SHIFT)
355 #define N(mn) ((mn) & CLK_DIV2_MASK)
357 unsigned long __clk_get_rate(u32 m_n, u32 div_m2)
361 div_m2 &= CLK_DIV_MASK;
362 debug("M=%u N=%u M2=%u\n", M(m_n), N(m_n), div_m2);
363 rate = V_OSCK / 1000 * M(m_n) / (N(m_n) + 1) / div_m2;
364 debug("CLK = %lu.%03luMHz\n", rate / 1000, rate % 1000);
368 unsigned long lcdc_clk_rate(void)
370 return clk_get_rate(cmwkup, disp);