]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - cpu/arm_cortexa8/omap3/clock.c
imported Ka-Ro specific additions to U-Boot 2009.08 for TX28
[karo-tx-uboot.git] / cpu / arm_cortexa8 / omap3 / clock.c
1 /*
2  * (C) Copyright 2008
3  * Texas Instruments, <www.ti.com>
4  *
5  * Author :
6  *      Manikandan Pillai <mani.pillai@ti.com>
7  *
8  * Derived from Beagle Board and OMAP3 SDP code by
9  *      Richard Woodruff <r-woodruff2@ti.com>
10  *      Syed Mohammed Khasim <khasim@ti.com>
11  *
12  * This program is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU General Public License as
14  * published by the Free Software Foundation; either version 2 of
15  * the License, or (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
25  * MA 02111-1307 USA
26  */
27
28 #include <common.h>
29 #include <asm/io.h>
30 #include <asm/arch/clocks.h>
31 #include <asm/arch/clocks_omap3.h>
32 #include <asm/arch/mem.h>
33 #include <asm/arch/sys_proto.h>
34 #include <environment.h>
35 #include <command.h>
36
37 /******************************************************************************
38  * get_sys_clk_speed() - determine reference oscillator speed
39  *                       based on known 32kHz clock and gptimer.
40  *****************************************************************************/
41 u32 get_osc_clk_speed(void)
42 {
43         u32 start, cstart, cend, cdiff, val;
44         struct prcm *prcm_base = (struct prcm *)PRCM_BASE;
45         struct prm *prm_base = (struct prm *)PRM_BASE;
46         struct gptimer *gpt1_base = (struct gptimer *)OMAP34XX_GPT1;
47         struct s32ktimer *s32k_base = (struct s32ktimer *)SYNC_32KTIMER_BASE;
48
49         val = readl(&prm_base->clksrc_ctrl);
50
51         /* If SYS_CLK is being divided by 2, remove for now */
52         val = (val & (~SYSCLKDIV_2)) | SYSCLKDIV_1;
53         writel(val, &prm_base->clksrc_ctrl);
54
55         /* enable timer2 */
56         val = readl(&prcm_base->clksel_wkup) | CLKSEL_GPT1;
57
58         /* select sys_clk for GPT1 */
59         writel(val, &prcm_base->clksel_wkup);
60
61         /* Enable I and F Clocks for GPT1 */
62         val = readl(&prcm_base->iclken_wkup) | EN_GPT1 | EN_32KSYNC;
63         writel(val, &prcm_base->iclken_wkup);
64         val = readl(&prcm_base->fclken_wkup) | EN_GPT1;
65         writel(val, &prcm_base->fclken_wkup);
66
67         writel(0, &gpt1_base->tldr);            /* start counting at 0 */
68         writel(GPT_EN, &gpt1_base->tclr);       /* enable clock */
69
70         /* enable 32kHz source, determine sys_clk via gauging */
71
72         /* start time in 20 cycles */
73         start = 20 + readl(&s32k_base->s32k_cr);
74
75         /* dead loop till start time */
76         while (readl(&s32k_base->s32k_cr) < start);
77
78         /* get start sys_clk count */
79         cstart = readl(&gpt1_base->tcrr);
80
81         /* wait for 40 cycles */
82         while (readl(&s32k_base->s32k_cr) < (start + 20)) ;
83         cend = readl(&gpt1_base->tcrr);         /* get end sys_clk count */
84         cdiff = cend - cstart;                  /* get elapsed ticks */
85
86         /* based on number of ticks assign speed */
87         if (cdiff > 19000)
88                 return S38_4M;
89         else if (cdiff > 15200)
90                 return S26M;
91         else if (cdiff > 13000)
92                 return S24M;
93         else if (cdiff > 9000)
94                 return S19_2M;
95         else if (cdiff > 7600)
96                 return S13M;
97         else
98                 return S12M;
99 }
100
101 /******************************************************************************
102  * get_sys_clkin_sel() - returns the sys_clkin_sel field value based on
103  *                       input oscillator clock frequency.
104  *****************************************************************************/
105 void get_sys_clkin_sel(u32 osc_clk, u32 *sys_clkin_sel)
106 {
107         switch(osc_clk) {
108         case S38_4M:
109                 *sys_clkin_sel = 4;
110                 break;
111         case S26M:
112                 *sys_clkin_sel = 3;
113                 break;
114         case S19_2M:
115                 *sys_clkin_sel = 2;
116                 break;
117         case S13M:
118                 *sys_clkin_sel = 1;
119                 break;
120         case S12M:
121         default:
122                 *sys_clkin_sel = 0;
123         }
124 }
125
126 /******************************************************************************
127  * prcm_init() - inits clocks for PRCM as defined in clocks.h
128  *               called from SRAM, or Flash (using temp SRAM stack).
129  *****************************************************************************/
130 void prcm_init(void)
131 {
132         void (*f_lock_pll) (u32, u32, u32, u32);
133         int xip_safe, p0, p1, p2, p3;
134         u32 osc_clk = 0, sys_clkin_sel;
135         u32 clk_index, sil_index = 0;
136         struct prm *prm_base = (struct prm *)PRM_BASE;
137         struct prcm *prcm_base = (struct prcm *)PRCM_BASE;
138         dpll_param *dpll_param_p;
139
140         f_lock_pll = (void *) ((u32) &_end_vect - (u32) &_start +
141                                 SRAM_VECT_CODE);
142
143         xip_safe = is_running_in_sram();
144
145         /*
146          * Gauge the input clock speed and find out the sys_clkin_sel
147          * value corresponding to the input clock.
148          */
149         osc_clk = get_osc_clk_speed();
150         get_sys_clkin_sel(osc_clk, &sys_clkin_sel);
151
152         /* set input crystal speed */
153         sr32(&prm_base->clksel, 0, 3, sys_clkin_sel);
154
155         /* If the input clock is greater than 19.2M always divide/2 */
156         if (sys_clkin_sel > 2) {
157                 /* input clock divider */
158                 sr32(&prm_base->clksrc_ctrl, 6, 2, 2);
159                 clk_index = sys_clkin_sel / 2;
160         } else {
161                 /* input clock divider */
162                 sr32(&prm_base->clksrc_ctrl, 6, 2, 1);
163                 clk_index = sys_clkin_sel;
164         }
165
166         /*
167          * The DPLL tables are defined according to sysclk value and
168          * silicon revision. The clk_index value will be used to get
169          * the values for that input sysclk from the DPLL param table
170          * and sil_index will get the values for that SysClk for the
171          * appropriate silicon rev.
172          */
173         if (get_cpu_rev())
174                 sil_index = 1;
175
176         /* Unlock MPU DPLL (slows things down, and needed later) */
177         sr32(&prcm_base->clken_pll_mpu, 0, 3, PLL_LOW_POWER_BYPASS);
178         wait_on_value(ST_MPU_CLK, 0, &prcm_base->idlest_pll_mpu, LDELAY);
179
180         /* Getting the base address of Core DPLL param table */
181         dpll_param_p = (dpll_param *) get_core_dpll_param();
182
183         /* Moving it to the right sysclk and ES rev base */
184         dpll_param_p = dpll_param_p + 3 * clk_index + sil_index;
185         if (xip_safe) {
186                 /*
187                  * CORE DPLL
188                  * sr32(CM_CLKSEL2_EMU) set override to work when asleep
189                  */
190                 sr32(&prcm_base->clken_pll, 0, 3, PLL_FAST_RELOCK_BYPASS);
191                 wait_on_value(ST_CORE_CLK, 0, &prcm_base->idlest_ckgen,
192                                 LDELAY);
193
194                 /*
195                  * For OMAP3 ES1.0 Errata 1.50, default value directly doesn't
196                  * work. write another value and then default value.
197                  */
198
199                 /* m3x2 */
200                 sr32(&prcm_base->clksel1_emu, 16, 5, CORE_M3X2 + 1);
201                 /* m3x2 */
202                 sr32(&prcm_base->clksel1_emu, 16, 5, CORE_M3X2);
203                 /* Set M2 */
204                 sr32(&prcm_base->clksel1_pll, 27, 2, dpll_param_p->m2);
205                 /* Set M */
206                 sr32(&prcm_base->clksel1_pll, 16, 11, dpll_param_p->m);
207                 /* Set N */
208                 sr32(&prcm_base->clksel1_pll, 8, 7, dpll_param_p->n);
209                 /* 96M Src */
210                 sr32(&prcm_base->clksel1_pll, 6, 1, 0);
211                 /* ssi */
212                 sr32(&prcm_base->clksel_core, 8, 4, CORE_SSI_DIV);
213                 /* fsusb */
214                 sr32(&prcm_base->clksel_core, 4, 2, CORE_FUSB_DIV);
215                 /* l4 */
216                 sr32(&prcm_base->clksel_core, 2, 2, CORE_L4_DIV);
217                 /* l3 */
218                 sr32(&prcm_base->clksel_core, 0, 2, CORE_L3_DIV);
219                 /* gfx */
220                 sr32(&prcm_base->clksel_gfx, 0, 3, GFX_DIV);
221                 /* reset mgr */
222                 sr32(&prcm_base->clksel_wkup, 1, 2, WKUP_RSM);
223                 /* FREQSEL */
224                 sr32(&prcm_base->clken_pll, 4, 4, dpll_param_p->fsel);
225                 /* lock mode */
226                 sr32(&prcm_base->clken_pll, 0, 3, PLL_LOCK);
227
228                 wait_on_value(ST_CORE_CLK, 1, &prcm_base->idlest_ckgen,
229                                 LDELAY);
230         } else if (is_running_in_flash()) {
231                 /*
232                  * if running from flash, jump to small relocated code
233                  * area in SRAM.
234                  */
235                 p0 = readl(&prcm_base->clken_pll);
236                 sr32(&p0, 0, 3, PLL_FAST_RELOCK_BYPASS);
237                 sr32(&p0, 4, 4, dpll_param_p->fsel);    /* FREQSEL */
238
239                 p1 = readl(&prcm_base->clksel1_pll);
240                 sr32(&p1, 27, 2, dpll_param_p->m2);     /* Set M2 */
241                 sr32(&p1, 16, 11, dpll_param_p->m);     /* Set M */
242                 sr32(&p1, 8, 7, dpll_param_p->n);               /* Set N */
243                 sr32(&p1, 6, 1, 0);     /* set source for 96M */
244
245                 p2 = readl(&prcm_base->clksel_core);
246                 sr32(&p2, 8, 4, CORE_SSI_DIV);  /* ssi */
247                 sr32(&p2, 4, 2, CORE_FUSB_DIV); /* fsusb */
248                 sr32(&p2, 2, 2, CORE_L4_DIV);   /* l4 */
249                 sr32(&p2, 0, 2, CORE_L3_DIV);   /* l3 */
250
251                 p3 = (u32)&prcm_base->idlest_ckgen;
252
253                 (*f_lock_pll) (p0, p1, p2, p3);
254         }
255
256         /* PER DPLL */
257         sr32(&prcm_base->clken_pll, 16, 3, PLL_STOP);
258         wait_on_value(ST_PERIPH_CLK, 0, &prcm_base->idlest_ckgen, LDELAY);
259
260         /* Getting the base address to PER DPLL param table */
261
262         /* Set N */
263         dpll_param_p = (dpll_param *) get_per_dpll_param();
264
265         /* Moving it to the right sysclk base */
266         dpll_param_p = dpll_param_p + clk_index;
267
268         /*
269          * Errata 1.50 Workaround for OMAP3 ES1.0 only
270          * If using default divisors, write default divisor + 1
271          * and then the actual divisor value
272          */
273         sr32(&prcm_base->clksel1_emu, 24, 5, PER_M6X2 + 1);     /* set M6 */
274         sr32(&prcm_base->clksel1_emu, 24, 5, PER_M6X2);         /* set M6 */
275         sr32(&prcm_base->clksel_cam, 0, 5, PER_M5X2 + 1);       /* set M5 */
276         sr32(&prcm_base->clksel_cam, 0, 5, PER_M5X2);           /* set M5 */
277         sr32(&prcm_base->clksel_dss, 0, 5, PER_M4X2 + 1);       /* set M4 */
278         sr32(&prcm_base->clksel_dss, 0, 5, PER_M4X2);           /* set M4 */
279         sr32(&prcm_base->clksel_dss, 8, 5, PER_M3X2 + 1);       /* set M3 */
280         sr32(&prcm_base->clksel_dss, 8, 5, PER_M3X2);           /* set M3 */
281         sr32(&prcm_base->clksel3_pll, 0, 5, dpll_param_p->m2 + 1); /* set M2 */
282         sr32(&prcm_base->clksel3_pll, 0, 5, dpll_param_p->m2);  /* set M2 */
283         /* Workaround end */
284
285         sr32(&prcm_base->clksel2_pll, 8, 11, dpll_param_p->m);  /* set m */
286         sr32(&prcm_base->clksel2_pll, 0, 7, dpll_param_p->n);   /* set n */
287         sr32(&prcm_base->clken_pll, 20, 4, dpll_param_p->fsel); /* FREQSEL */
288         sr32(&prcm_base->clken_pll, 16, 3, PLL_LOCK);           /* lock mode */
289         wait_on_value(ST_PERIPH_CLK, 2, &prcm_base->idlest_ckgen, LDELAY);
290
291         /* Getting the base address to MPU DPLL param table */
292         dpll_param_p = (dpll_param *) get_mpu_dpll_param();
293
294         /* Moving it to the right sysclk and ES rev base */
295         dpll_param_p = dpll_param_p + 3 * clk_index + sil_index;
296
297         /* MPU DPLL (unlocked already) */
298
299         /* Set M2 */
300         sr32(&prcm_base->clksel2_pll_mpu, 0, 5, dpll_param_p->m2);
301         /* Set M */
302         sr32(&prcm_base->clksel1_pll_mpu, 8, 11, dpll_param_p->m);
303         /* Set N */
304         sr32(&prcm_base->clksel1_pll_mpu, 0, 7, dpll_param_p->n);
305         /* FREQSEL */
306         sr32(&prcm_base->clken_pll_mpu, 4, 4, dpll_param_p->fsel);
307         /* lock mode */
308         sr32(&prcm_base->clken_pll_mpu, 0, 3, PLL_LOCK);
309         wait_on_value(ST_MPU_CLK, 1, &prcm_base->idlest_pll_mpu, LDELAY);
310
311         /* Getting the base address to IVA DPLL param table */
312         dpll_param_p = (dpll_param *) get_iva_dpll_param();
313
314         /* Moving it to the right sysclk and ES rev base */
315         dpll_param_p = dpll_param_p + 3 * clk_index + sil_index;
316
317         /* IVA DPLL (set to 12*20=240MHz) */
318         sr32(&prcm_base->clken_pll_iva2, 0, 3, PLL_STOP);
319         wait_on_value(ST_IVA2_CLK, 0, &prcm_base->idlest_pll_iva2, LDELAY);
320         /* set M2 */
321         sr32(&prcm_base->clksel2_pll_iva2, 0, 5, dpll_param_p->m2);
322         /* set M */
323         sr32(&prcm_base->clksel1_pll_iva2, 8, 11, dpll_param_p->m);
324         /* set N */
325         sr32(&prcm_base->clksel1_pll_iva2, 0, 7, dpll_param_p->n);
326         /* FREQSEL */
327         sr32(&prcm_base->clken_pll_iva2, 4, 4, dpll_param_p->fsel);
328         /* lock mode */
329         sr32(&prcm_base->clken_pll_iva2, 0, 3, PLL_LOCK);
330         wait_on_value(ST_IVA2_CLK, 1, &prcm_base->idlest_pll_iva2, LDELAY);
331
332         /* Set up GPTimers to sys_clk source only */
333         sr32(&prcm_base->clksel_per, 0, 8, 0xff);
334         sr32(&prcm_base->clksel_wkup, 0, 1, 1);
335
336         sdelay(5000);
337 }
338
339 /******************************************************************************
340  * peripheral_enable() - Enable the clks & power for perifs (GPT2, UART1,...)
341  *****************************************************************************/
342 void per_clocks_enable(void)
343 {
344         struct prcm *prcm_base = (struct prcm *)PRCM_BASE;
345
346         /* Enable GP2 timer. */
347         sr32(&prcm_base->clksel_per, 0, 1, 0x1);        /* GPT2 = sys clk */
348         sr32(&prcm_base->iclken_per, 3, 1, 0x1);        /* ICKen GPT2 */
349         sr32(&prcm_base->fclken_per, 3, 1, 0x1);        /* FCKen GPT2 */
350
351 #ifdef CONFIG_SYS_NS16550
352         /* Enable UART1 clocks */
353         sr32(&prcm_base->fclken1_core, 13, 1, 0x1);
354         sr32(&prcm_base->iclken1_core, 13, 1, 0x1);
355
356         /* UART 3 Clocks */
357         sr32(&prcm_base->fclken_per, 11, 1, 0x1);
358         sr32(&prcm_base->iclken_per, 11, 1, 0x1);
359 #endif
360
361 #ifdef CONFIG_OMAP3_GPIO_2
362         sr32(&prcm_base->fclken_per, 13, 1, 1);
363         sr32(&prcm_base->iclken_per, 13, 1, 1);
364 #endif
365 #ifdef CONFIG_OMAP3_GPIO_3
366         sr32(&prcm_base->fclken_per, 14, 1, 1);
367         sr32(&prcm_base->iclken_per, 14, 1, 1);
368 #endif
369 #ifdef CONFIG_OMAP3_GPIO_4
370         sr32(&prcm_base->fclken_per, 15, 1, 1);
371         sr32(&prcm_base->iclken_per, 15, 1, 1);
372 #endif
373 #ifdef CONFIG_OMAP3_GPIO_5
374         sr32(&prcm_base->fclken_per, 16, 1, 1);
375         sr32(&prcm_base->iclken_per, 16, 1, 1);
376 #endif
377 #ifdef CONFIG_OMAP3_GPIO_6
378         sr32(&prcm_base->fclken_per, 17, 1, 1);
379         sr32(&prcm_base->iclken_per, 17, 1, 1);
380 #endif
381
382 #ifdef CONFIG_DRIVER_OMAP34XX_I2C
383         /* Turn on all 3 I2C clocks */
384         sr32(&prcm_base->fclken1_core, 15, 3, 0x7);
385         sr32(&prcm_base->iclken1_core, 15, 3, 0x7);     /* I2C1,2,3 = on */
386 #endif
387         /* Enable the ICLK for 32K Sync Timer as its used in udelay */
388         sr32(&prcm_base->iclken_wkup, 2, 1, 0x1);
389
390         sr32(&prcm_base->fclken_iva2, 0, 32, FCK_IVA2_ON);
391         sr32(&prcm_base->fclken1_core, 0, 32, FCK_CORE1_ON);
392         sr32(&prcm_base->iclken1_core, 0, 32, ICK_CORE1_ON);
393         sr32(&prcm_base->iclken2_core, 0, 32, ICK_CORE2_ON);
394         sr32(&prcm_base->fclken_wkup, 0, 32, FCK_WKUP_ON);
395         sr32(&prcm_base->iclken_wkup, 0, 32, ICK_WKUP_ON);
396         sr32(&prcm_base->fclken_dss, 0, 32, FCK_DSS_ON);
397         sr32(&prcm_base->iclken_dss, 0, 32, ICK_DSS_ON);
398         sr32(&prcm_base->fclken_cam, 0, 32, FCK_CAM_ON);
399         sr32(&prcm_base->iclken_cam, 0, 32, ICK_CAM_ON);
400         sr32(&prcm_base->fclken_per, 0, 32, FCK_PER_ON);
401         sr32(&prcm_base->iclken_per, 0, 32, ICK_PER_ON);
402
403         sdelay(1000);
404 }