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
27 #define PRCM_FUNCTL 0x0
29 #define PRCM_EMIF_CLK_ACTIVITY BIT(2)
30 #define PRCM_L3_GCLK_ACTIVITY BIT(4)
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_MASK 0x7
40 #define CLK_MODE_SEL 0x7
41 #define DPLL_CLKDCOLDO_GATE_CTRL 0x300
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 const struct cm_rtc *cmrtc = (struct cm_rtc *)CM_RTC;
49 #ifdef CONFIG_SPL_BUILD
50 #define enable_clk(reg, val) __enable_clk(#reg, ®, val)
52 static void __enable_clk(const char *name, const void *reg, u32 mask)
54 unsigned long timeout = 10000000;
57 while (readl(reg) != mask)
58 /* poor man's timeout, since timers not initialized */
60 /* no error message, since console not yet available */
64 static void enable_interface_clocks(void)
66 /* Enable all the Interconnect Modules */
67 enable_clk(cmper->l3clkctrl, PRCM_MOD_EN);
68 enable_clk(cmper->l4lsclkctrl, PRCM_MOD_EN);
69 enable_clk(cmper->l4fwclkctrl, PRCM_MOD_EN);
70 enable_clk(cmwkup->wkl4wkclkctrl, PRCM_MOD_EN);
71 enable_clk(cmper->l3instrclkctrl, PRCM_MOD_EN);
72 enable_clk(cmper->l4hsclkctrl, PRCM_MOD_EN);
73 #ifdef CONFIG_HW_WATCHDOG
74 enable_clk(cmwkup->wdtimer1ctrl, PRCM_MOD_EN);
77 enable_clk(cmwkup->wkgpio0clkctrl, PRCM_MOD_EN);
81 * Force power domain wake up transition
82 * Ensure that the corresponding interface clock is active before
83 * using the peripheral
85 static void power_domain_wkup_transition(void)
87 writel(PRCM_FORCE_WAKEUP, &cmper->l3clkstctrl);
88 writel(PRCM_FORCE_WAKEUP, &cmper->l4lsclkstctrl);
89 writel(PRCM_FORCE_WAKEUP, &cmwkup->wkclkstctrl);
90 writel(PRCM_FORCE_WAKEUP, &cmper->l4fwclkstctrl);
91 writel(PRCM_FORCE_WAKEUP, &cmper->l3sclkstctrl);
95 * Enable the peripheral clock for required peripherals
97 static void enable_per_clocks(void)
99 /* Enable the control module though RBL would have done it*/
100 enable_clk(cmwkup->wkctrlclkctrl, PRCM_MOD_EN);
101 /* Enable the timer2 clock */
102 enable_clk(cmper->timer2clkctrl, PRCM_MOD_EN);
103 /* Select the Master osc 24 MHZ as Timer2 clock source */
104 writel(0x1, &cmdpll->clktimer2clk);
106 #ifdef CONFIG_SYS_NS16550_COM1
108 enable_clk(cmwkup->wkup_uart0ctrl, PRCM_MOD_EN);
110 #ifdef CONFIG_SYS_NS16550_COM2
111 enable_clk(cmper->uart1clkctrl, PRCM_MOD_EN);
113 #ifdef CONFIG_SYS_NS16550_COM3
114 enable_clk(cmper->uart2clkctrl, PRCM_MOD_EN);
116 #ifdef CONFIG_SYS_NS16550_COM4
117 enable_clk(cmper->uart3clkctrl, PRCM_MOD_EN);
119 #ifdef CONFIG_SYS_NS16550_COM5
120 enable_clk(cmper->uart4clkctrl, PRCM_MOD_EN);
122 #ifdef CONFIG_SYS_NS16550_COM6
123 enable_clk(cmper->uart5clkctrl, PRCM_MOD_EN);
126 enable_clk(cmper->gpmcclkctrl, PRCM_MOD_EN);
129 enable_clk(cmper->elmclkctrl, PRCM_MOD_EN);
132 enable_clk(cmper->cpswclkstctrl, PRCM_MOD_EN);
133 enable_clk(cmper->cpgmac0clkctrl, PRCM_MOD_EN);
136 #ifndef CONFIG_OMAP_MMC_DEV_0
137 enable_clk(cmper->mmc0clkctrl, PRCM_MOD_EN);
139 #ifdef CONFIG_OMAP_MMC_DEV_1
140 enable_clk(cmper->mmc1clkctrl, PRCM_MOD_EN);
143 enable_clk(cmper->lcdclkctrl, PRCM_MOD_EN);
146 enable_clk(cmwkup->wkup_i2c0ctrl, PRCM_MOD_EN);
149 enable_clk(cmper->gpio1clkctrl, PRCM_MOD_EN);
150 enable_clk(cmper->gpio2clkctrl, PRCM_MOD_EN);
151 enable_clk(cmper->gpio3clkctrl, PRCM_MOD_EN);
154 enable_clk(cmper->i2c1clkctrl, PRCM_MOD_EN);
157 enable_clk(cmper->spi0clkctrl, PRCM_MOD_EN);
160 enable_clk(cmrtc->rtcclkctrl, PRCM_MOD_EN);
163 enable_clk(cmper->usb0clkctrl, PRCM_MOD_EN);
166 static void mpu_pll_config(void)
168 u32 clkmode, clksel, div_m2;
170 clkmode = readl(&cmwkup->clkmoddpllmpu);
171 clksel = readl(&cmwkup->clkseldpllmpu);
172 div_m2 = readl(&cmwkup->divm2dpllmpu);
174 /* Set the PLL to bypass Mode */
175 writel(PLL_BYPASS_MODE, &cmwkup->clkmoddpllmpu);
176 while (readl(&cmwkup->idlestdpllmpu) != ST_MN_BYPASS)
179 clksel &= ~CLK_SEL_MASK;
180 clksel |= (MPUPLL_M << CLK_SEL_SHIFT) | MPUPLL_N;
181 writel(clksel, &cmwkup->clkseldpllmpu);
183 div_m2 &= ~CLK_DIV_MASK;
185 writel(div_m2, &cmwkup->divm2dpllmpu);
187 clkmode &= ~CLK_MODE_MASK;
188 clkmode |= CLK_MODE_SEL;
189 writel(clkmode, &cmwkup->clkmoddpllmpu);
191 while (readl(&cmwkup->idlestdpllmpu) != ST_DPLL_CLK)
195 static void core_pll_config(void)
197 u32 clkmode, clksel, div_m4, div_m5, div_m6;
199 clkmode = readl(&cmwkup->clkmoddpllcore);
200 clksel = readl(&cmwkup->clkseldpllcore);
201 div_m4 = readl(&cmwkup->divm4dpllcore);
202 div_m5 = readl(&cmwkup->divm5dpllcore);
203 div_m6 = readl(&cmwkup->divm6dpllcore);
205 /* Set the PLL to bypass Mode */
206 writel(PLL_BYPASS_MODE, &cmwkup->clkmoddpllcore);
208 while (readl(&cmwkup->idlestdpllcore) != ST_MN_BYPASS)
211 clksel &= ~CLK_SEL_MASK;
212 clksel |= ((COREPLL_M << CLK_SEL_SHIFT) | COREPLL_N);
213 writel(clksel, &cmwkup->clkseldpllcore);
215 div_m4 &= ~CLK_DIV_MASK;
216 div_m4 |= COREPLL_M4;
217 writel(div_m4, &cmwkup->divm4dpllcore);
219 div_m5 &= ~CLK_DIV_MASK;
220 div_m5 |= COREPLL_M5;
221 writel(div_m5, &cmwkup->divm5dpllcore);
223 div_m6 &= ~CLK_DIV_MASK;
224 div_m6 |= COREPLL_M6;
225 writel(div_m6, &cmwkup->divm6dpllcore);
227 clkmode &= ~CLK_MODE_MASK;
228 clkmode |= CLK_MODE_SEL;
229 writel(clkmode, &cmwkup->clkmoddpllcore);
231 while (readl(&cmwkup->idlestdpllcore) != ST_DPLL_CLK)
235 static void per_pll_config(void)
237 u32 clkmode, clksel, div_m2;
239 clkmode = readl(&cmwkup->clkmoddpllper);
240 clksel = readl(&cmwkup->clkseldpllper);
241 div_m2 = readl(&cmwkup->divm2dpllper);
243 /* Set the PLL to bypass Mode */
244 writel(PLL_BYPASS_MODE, &cmwkup->clkmoddpllper);
246 while (readl(&cmwkup->idlestdpllper) != ST_MN_BYPASS)
249 clksel &= ~CLK_SEL_MASK;
250 clksel |= (PERPLL_M << CLK_SEL_SHIFT) | PERPLL_N;
251 writel(clksel, &cmwkup->clkseldpllper);
253 div_m2 &= ~CLK_DIV2_MASK;
255 writel(div_m2, &cmwkup->divm2dpllper);
257 clkmode &= ~CLK_MODE_MASK;
258 clkmode |= CLK_MODE_SEL;
259 writel(clkmode, &cmwkup->clkmoddpllper);
261 while (readl(&cmwkup->idlestdpllper) != ST_DPLL_CLK)
264 writel(DPLL_CLKDCOLDO_GATE_CTRL, &cmwkup->clkdcoldodpllper);
267 static void disp_pll_config(void)
269 u32 clkmode, clksel, div_m2;
271 clkmode = readl(&cmwkup->clkmoddplldisp);
272 clksel = readl(&cmwkup->clkseldplldisp);
273 div_m2 = readl(&cmwkup->divm2dplldisp);
275 /* Set the PLL to bypass Mode */
276 writel(PLL_BYPASS_MODE, &cmwkup->clkmoddplldisp);
278 while (!(readl(&cmwkup->idlestdplldisp) & ST_MN_BYPASS))
281 clksel &= ~CLK_SEL_MASK;
282 clksel |= (DISPPLL_M << CLK_SEL_SHIFT) | DISPPLL_N;
283 writel(clksel, &cmwkup->clkseldplldisp);
285 div_m2 &= ~CLK_DIV2_MASK;
286 div_m2 |= DISPPLL_M2;
287 writel(div_m2, &cmwkup->divm2dplldisp);
289 clkmode &= ~CLK_MODE_MASK;
290 clkmode |= CLK_MODE_SEL;
291 writel(clkmode, &cmwkup->clkmoddplldisp);
293 while (!(readl(&cmwkup->idlestdplldisp) & ST_DPLL_CLK))
297 void ddr_pll_config(unsigned int ddrpll_m)
299 u32 clkmode, clksel, div_m2;
301 clkmode = readl(&cmwkup->clkmoddpllddr);
302 clksel = readl(&cmwkup->clkseldpllddr);
303 div_m2 = readl(&cmwkup->divm2dpllddr);
305 /* Set the PLL to bypass Mode */
306 clkmode &= ~CLK_MODE_MASK;
307 clkmode |= PLL_BYPASS_MODE;
308 writel(clkmode, &cmwkup->clkmoddpllddr);
310 /* Wait till bypass mode is enabled */
311 while (!(readl(&cmwkup->idlestdpllddr) & ST_MN_BYPASS))
314 clksel &= ~CLK_SEL_MASK;
315 clksel |= (ddrpll_m << CLK_SEL_SHIFT) | DDRPLL_N;
316 writel(clksel, &cmwkup->clkseldpllddr);
318 div_m2 &= ~CLK_DIV_MASK;
320 writel(div_m2, &cmwkup->divm2dpllddr);
322 clkmode &= ~CLK_MODE_MASK;
323 clkmode |= CLK_MODE_SEL;
324 writel(clkmode, &cmwkup->clkmoddpllddr);
326 /* Wait till dpll is locked */
327 while ((readl(&cmwkup->idlestdpllddr) & ST_DPLL_CLK) != ST_DPLL_CLK)
331 void enable_emif_clocks(void)
333 /* Enable the EMIF_FW Functional clock */
334 writel(PRCM_MOD_EN, &cmper->emiffwclkctrl);
335 /* Enable EMIF0 Clock */
336 writel(PRCM_MOD_EN, &cmper->emifclkctrl);
337 /* Poll if module is functional */
338 while ((readl(&cmper->emifclkctrl)) != PRCM_MOD_EN)
343 * Configure the PLL/PRCM for necessary peripherals
352 /* Enable the required interconnect clocks */
353 enable_interface_clocks();
355 /* Power domain wake up transition */
356 power_domain_wkup_transition();
358 /* Enable the required peripherals */
363 #define M(mn) (((mn) & CLK_SEL_MASK) >> CLK_SEL_SHIFT)
364 #define N(mn) ((mn) & CLK_DIV2_MASK)
366 unsigned long __clk_get_rate(u32 m_n, u32 div_m2)
370 div_m2 &= CLK_DIV_MASK;
371 debug("M=%u N=%u M2=%u\n", M(m_n), N(m_n), div_m2);
372 rate = V_OSCK / 1000 * M(m_n) / (N(m_n) + 1) / div_m2;
373 debug("CLK = %lu.%03luMHz\n", rate / 1000, rate % 1000);
377 unsigned long lcdc_clk_rate(void)
379 return clk_get_rate(cmwkup, disp);