]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - arch/arm/cpu/armv7/mx6/clock.c
Merge branch 'master' of git://git.denx.de/u-boot-video
[karo-tx-uboot.git] / arch / arm / cpu / armv7 / mx6 / clock.c
1 /*
2  * Copyright (C) 2010-2011 Freescale Semiconductor, Inc.
3  *
4  * See file CREDITS for list of people who contributed to this
5  * project.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License as
9  * published by the Free Software Foundation; either version 2 of
10  * the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
20  * MA 02111-1307 USA
21  */
22
23 #include <common.h>
24 #include <asm/io.h>
25 #include <asm/errno.h>
26 #include <asm/arch/imx-regs.h>
27 #include <asm/arch/crm_regs.h>
28 #include <asm/arch/clock.h>
29 #include <asm/arch/sys_proto.h>
30
31 enum pll_clocks {
32         PLL_SYS,        /* System PLL */
33         PLL_BUS,        /* System Bus PLL*/
34         PLL_USBOTG,     /* OTG USB PLL */
35         PLL_ENET,       /* ENET PLL */
36 };
37
38 struct mxc_ccm_reg *imx_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
39
40 #ifdef CONFIG_MXC_OCOTP
41 void enable_ocotp_clk(unsigned char enable)
42 {
43         u32 reg;
44
45         reg = __raw_readl(&imx_ccm->CCGR2);
46         if (enable)
47                 reg |= MXC_CCM_CCGR2_OCOTP_CTRL_MASK;
48         else
49                 reg &= ~MXC_CCM_CCGR2_OCOTP_CTRL_MASK;
50         __raw_writel(reg, &imx_ccm->CCGR2);
51 }
52 #endif
53
54 void enable_usboh3_clk(unsigned char enable)
55 {
56         u32 reg;
57
58         reg = __raw_readl(&imx_ccm->CCGR6);
59         if (enable)
60                 reg |= MXC_CCM_CCGR6_USBOH3_MASK;
61         else
62                 reg &= ~(MXC_CCM_CCGR6_USBOH3_MASK);
63         __raw_writel(reg, &imx_ccm->CCGR6);
64
65 }
66
67 #ifdef CONFIG_I2C_MXC
68 /* i2c_num can be from 0 - 2 */
69 int enable_i2c_clk(unsigned char enable, unsigned i2c_num)
70 {
71         u32 reg;
72         u32 mask;
73
74         if (i2c_num > 2)
75                 return -EINVAL;
76
77         mask = MXC_CCM_CCGR_CG_MASK
78                 << (MXC_CCM_CCGR2_I2C1_SERIAL_OFFSET + (i2c_num << 1));
79         reg = __raw_readl(&imx_ccm->CCGR2);
80         if (enable)
81                 reg |= mask;
82         else
83                 reg &= ~mask;
84         __raw_writel(reg, &imx_ccm->CCGR2);
85         return 0;
86 }
87 #endif
88
89 static u32 decode_pll(enum pll_clocks pll, u32 infreq)
90 {
91         u32 div;
92
93         switch (pll) {
94         case PLL_SYS:
95                 div = __raw_readl(&imx_ccm->analog_pll_sys);
96                 div &= BM_ANADIG_PLL_SYS_DIV_SELECT;
97
98                 return infreq * (div >> 1);
99         case PLL_BUS:
100                 div = __raw_readl(&imx_ccm->analog_pll_528);
101                 div &= BM_ANADIG_PLL_528_DIV_SELECT;
102
103                 return infreq * (20 + (div << 1));
104         case PLL_USBOTG:
105                 div = __raw_readl(&imx_ccm->analog_usb1_pll_480_ctrl);
106                 div &= BM_ANADIG_USB1_PLL_480_CTRL_DIV_SELECT;
107
108                 return infreq * (20 + (div << 1));
109         case PLL_ENET:
110                 div = __raw_readl(&imx_ccm->analog_pll_enet);
111                 div &= BM_ANADIG_PLL_ENET_DIV_SELECT;
112
113                 return (div == 3 ? 125000000 : 25000000 * (div << 1));
114         default:
115                 return 0;
116         }
117         /* NOTREACHED */
118 }
119
120 static u32 get_mcu_main_clk(void)
121 {
122         u32 reg, freq;
123
124         reg = __raw_readl(&imx_ccm->cacrr);
125         reg &= MXC_CCM_CACRR_ARM_PODF_MASK;
126         reg >>= MXC_CCM_CACRR_ARM_PODF_OFFSET;
127         freq = decode_pll(PLL_SYS, MXC_HCLK);
128
129         return freq / (reg + 1);
130 }
131
132 u32 get_periph_clk(void)
133 {
134         u32 reg, freq = 0;
135
136         reg = __raw_readl(&imx_ccm->cbcdr);
137         if (reg & MXC_CCM_CBCDR_PERIPH_CLK_SEL) {
138                 reg = __raw_readl(&imx_ccm->cbcmr);
139                 reg &= MXC_CCM_CBCMR_PERIPH_CLK2_SEL_MASK;
140                 reg >>= MXC_CCM_CBCMR_PERIPH_CLK2_SEL_OFFSET;
141
142                 switch (reg) {
143                 case 0:
144                         freq = decode_pll(PLL_USBOTG, MXC_HCLK);
145                         break;
146                 case 1:
147                 case 2:
148                         freq = MXC_HCLK;
149                         break;
150                 default:
151                         break;
152                 }
153         } else {
154                 reg = __raw_readl(&imx_ccm->cbcmr);
155                 reg &= MXC_CCM_CBCMR_PRE_PERIPH_CLK_SEL_MASK;
156                 reg >>= MXC_CCM_CBCMR_PRE_PERIPH_CLK_SEL_OFFSET;
157
158                 switch (reg) {
159                 case 0:
160                         freq = decode_pll(PLL_BUS, MXC_HCLK);
161                         break;
162                 case 1:
163                         freq = PLL2_PFD2_FREQ;
164                         break;
165                 case 2:
166                         freq = PLL2_PFD0_FREQ;
167                         break;
168                 case 3:
169                         freq = PLL2_PFD2_DIV_FREQ;
170                         break;
171                 default:
172                         break;
173                 }
174         }
175
176         return freq;
177 }
178
179 static u32 get_ipg_clk(void)
180 {
181         u32 reg, ipg_podf;
182
183         reg = __raw_readl(&imx_ccm->cbcdr);
184         reg &= MXC_CCM_CBCDR_IPG_PODF_MASK;
185         ipg_podf = reg >> MXC_CCM_CBCDR_IPG_PODF_OFFSET;
186
187         return get_ahb_clk() / (ipg_podf + 1);
188 }
189
190 static u32 get_ipg_per_clk(void)
191 {
192         u32 reg, perclk_podf;
193
194         reg = __raw_readl(&imx_ccm->cscmr1);
195         perclk_podf = reg & MXC_CCM_CSCMR1_PERCLK_PODF_MASK;
196
197         return get_ipg_clk() / (perclk_podf + 1);
198 }
199
200 static u32 get_uart_clk(void)
201 {
202         u32 reg, uart_podf;
203         u32 freq = PLL3_80M;
204         reg = __raw_readl(&imx_ccm->cscdr1);
205 #ifdef CONFIG_MX6SL
206         if (reg & MXC_CCM_CSCDR1_UART_CLK_SEL)
207                 freq = MXC_HCLK;
208 #endif
209         reg &= MXC_CCM_CSCDR1_UART_CLK_PODF_MASK;
210         uart_podf = reg >> MXC_CCM_CSCDR1_UART_CLK_PODF_OFFSET;
211
212         return freq / (uart_podf + 1);
213 }
214
215 static u32 get_cspi_clk(void)
216 {
217         u32 reg, cspi_podf;
218
219         reg = __raw_readl(&imx_ccm->cscdr2);
220         reg &= MXC_CCM_CSCDR2_ECSPI_CLK_PODF_MASK;
221         cspi_podf = reg >> MXC_CCM_CSCDR2_ECSPI_CLK_PODF_OFFSET;
222
223         return  PLL3_60M / (cspi_podf + 1);
224 }
225
226 static u32 get_axi_clk(void)
227 {
228         u32 root_freq, axi_podf;
229         u32 cbcdr =  __raw_readl(&imx_ccm->cbcdr);
230
231         axi_podf = cbcdr & MXC_CCM_CBCDR_AXI_PODF_MASK;
232         axi_podf >>= MXC_CCM_CBCDR_AXI_PODF_OFFSET;
233
234         if (cbcdr & MXC_CCM_CBCDR_AXI_SEL) {
235                 if (cbcdr & MXC_CCM_CBCDR_AXI_ALT_SEL)
236                         root_freq = PLL2_PFD2_FREQ;
237                 else
238                         root_freq = PLL3_PFD1_FREQ;
239         } else
240                 root_freq = get_periph_clk();
241
242         return  root_freq / (axi_podf + 1);
243 }
244
245 static u32 get_emi_slow_clk(void)
246 {
247         u32 emi_clk_sel, emi_slow_pof, cscmr1, root_freq = 0;
248
249         cscmr1 =  __raw_readl(&imx_ccm->cscmr1);
250         emi_clk_sel = cscmr1 & MXC_CCM_CSCMR1_ACLK_EMI_SLOW_MASK;
251         emi_clk_sel >>= MXC_CCM_CSCMR1_ACLK_EMI_SLOW_OFFSET;
252         emi_slow_pof = cscmr1 & MXC_CCM_CSCMR1_ACLK_EMI_SLOW_PODF_MASK;
253         emi_slow_pof >>= MXC_CCM_CSCMR1_ACLK_EMI_PODF_OFFSET;
254
255         switch (emi_clk_sel) {
256         case 0:
257                 root_freq = get_axi_clk();
258                 break;
259         case 1:
260                 root_freq = decode_pll(PLL_USBOTG, MXC_HCLK);
261                 break;
262         case 2:
263                 root_freq = PLL2_PFD2_FREQ;
264                 break;
265         case 3:
266                 root_freq = PLL2_PFD0_FREQ;
267                 break;
268         }
269
270         return root_freq / (emi_slow_pof + 1);
271 }
272
273 #ifdef CONFIG_MX6SL
274 static u32 get_mmdc_ch0_clk(void)
275 {
276         u32 cbcmr = __raw_readl(&imx_ccm->cbcmr);
277         u32 cbcdr = __raw_readl(&imx_ccm->cbcdr);
278         u32 freq, podf;
279
280         podf = (cbcdr & MXC_CCM_CBCDR_MMDC_CH1_PODF_MASK) \
281                         >> MXC_CCM_CBCDR_MMDC_CH1_PODF_OFFSET;
282
283         switch ((cbcmr & MXC_CCM_CBCMR_PRE_PERIPH2_CLK_SEL_MASK) >>
284                 MXC_CCM_CBCMR_PRE_PERIPH2_CLK_SEL_OFFSET) {
285         case 0:
286                 freq = decode_pll(PLL_BUS, MXC_HCLK);
287                 break;
288         case 1:
289                 freq = PLL2_PFD2_FREQ;
290                 break;
291         case 2:
292                 freq = PLL2_PFD0_FREQ;
293                 break;
294         case 3:
295                 freq = PLL2_PFD2_DIV_FREQ;
296         }
297
298         return freq / (podf + 1);
299
300 }
301 #else
302 static u32 get_mmdc_ch0_clk(void)
303 {
304         u32 cbcdr = __raw_readl(&imx_ccm->cbcdr);
305         u32 mmdc_ch0_podf = (cbcdr & MXC_CCM_CBCDR_MMDC_CH0_PODF_MASK) >>
306                                 MXC_CCM_CBCDR_MMDC_CH0_PODF_OFFSET;
307
308         return get_periph_clk() / (mmdc_ch0_podf + 1);
309 }
310 #endif
311
312 static u32 get_usdhc_clk(u32 port)
313 {
314         u32 root_freq = 0, usdhc_podf = 0, clk_sel = 0;
315         u32 cscmr1 = __raw_readl(&imx_ccm->cscmr1);
316         u32 cscdr1 = __raw_readl(&imx_ccm->cscdr1);
317
318         switch (port) {
319         case 0:
320                 usdhc_podf = (cscdr1 & MXC_CCM_CSCDR1_USDHC1_PODF_MASK) >>
321                                         MXC_CCM_CSCDR1_USDHC1_PODF_OFFSET;
322                 clk_sel = cscmr1 & MXC_CCM_CSCMR1_USDHC1_CLK_SEL;
323
324                 break;
325         case 1:
326                 usdhc_podf = (cscdr1 & MXC_CCM_CSCDR1_USDHC2_PODF_MASK) >>
327                                         MXC_CCM_CSCDR1_USDHC2_PODF_OFFSET;
328                 clk_sel = cscmr1 & MXC_CCM_CSCMR1_USDHC2_CLK_SEL;
329
330                 break;
331         case 2:
332                 usdhc_podf = (cscdr1 & MXC_CCM_CSCDR1_USDHC3_PODF_MASK) >>
333                                         MXC_CCM_CSCDR1_USDHC3_PODF_OFFSET;
334                 clk_sel = cscmr1 & MXC_CCM_CSCMR1_USDHC3_CLK_SEL;
335
336                 break;
337         case 3:
338                 usdhc_podf = (cscdr1 & MXC_CCM_CSCDR1_USDHC4_PODF_MASK) >>
339                                         MXC_CCM_CSCDR1_USDHC4_PODF_OFFSET;
340                 clk_sel = cscmr1 & MXC_CCM_CSCMR1_USDHC4_CLK_SEL;
341
342                 break;
343         default:
344                 break;
345         }
346
347         if (clk_sel)
348                 root_freq = PLL2_PFD0_FREQ;
349         else
350                 root_freq = PLL2_PFD2_FREQ;
351
352         return root_freq / (usdhc_podf + 1);
353 }
354
355 u32 imx_get_uartclk(void)
356 {
357         return get_uart_clk();
358 }
359
360 u32 imx_get_fecclk(void)
361 {
362         return decode_pll(PLL_ENET, MXC_HCLK);
363 }
364
365 int enable_sata_clock(void)
366 {
367         u32 reg = 0;
368         s32 timeout = 100000;
369         struct mxc_ccm_reg *const imx_ccm
370                 = (struct mxc_ccm_reg *) CCM_BASE_ADDR;
371
372         /* Enable sata clock */
373         reg = readl(&imx_ccm->CCGR5); /* CCGR5 */
374         reg |= MXC_CCM_CCGR5_SATA_MASK;
375         writel(reg, &imx_ccm->CCGR5);
376
377         /* Enable PLLs */
378         reg = readl(&imx_ccm->analog_pll_enet);
379         reg &= ~BM_ANADIG_PLL_SYS_POWERDOWN;
380         writel(reg, &imx_ccm->analog_pll_enet);
381         reg |= BM_ANADIG_PLL_SYS_ENABLE;
382         while (timeout--) {
383                 if (readl(&imx_ccm->analog_pll_enet) & BM_ANADIG_PLL_SYS_LOCK)
384                         break;
385         }
386         if (timeout <= 0)
387                 return -EIO;
388         reg &= ~BM_ANADIG_PLL_SYS_BYPASS;
389         writel(reg, &imx_ccm->analog_pll_enet);
390         reg |= BM_ANADIG_PLL_ENET_ENABLE_SATA;
391         writel(reg, &imx_ccm->analog_pll_enet);
392
393         return 0 ;
394 }
395
396 unsigned int mxc_get_clock(enum mxc_clock clk)
397 {
398         switch (clk) {
399         case MXC_ARM_CLK:
400                 return get_mcu_main_clk();
401         case MXC_PER_CLK:
402                 return get_periph_clk();
403         case MXC_AHB_CLK:
404                 return get_ahb_clk();
405         case MXC_IPG_CLK:
406                 return get_ipg_clk();
407         case MXC_IPG_PERCLK:
408         case MXC_I2C_CLK:
409                 return get_ipg_per_clk();
410         case MXC_UART_CLK:
411                 return get_uart_clk();
412         case MXC_CSPI_CLK:
413                 return get_cspi_clk();
414         case MXC_AXI_CLK:
415                 return get_axi_clk();
416         case MXC_EMI_SLOW_CLK:
417                 return get_emi_slow_clk();
418         case MXC_DDR_CLK:
419                 return get_mmdc_ch0_clk();
420         case MXC_ESDHC_CLK:
421                 return get_usdhc_clk(0);
422         case MXC_ESDHC2_CLK:
423                 return get_usdhc_clk(1);
424         case MXC_ESDHC3_CLK:
425                 return get_usdhc_clk(2);
426         case MXC_ESDHC4_CLK:
427                 return get_usdhc_clk(3);
428         case MXC_SATA_CLK:
429                 return get_ahb_clk();
430         default:
431                 break;
432         }
433
434         return -1;
435 }
436
437 /*
438  * Dump some core clockes.
439  */
440 int do_mx6_showclocks(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
441 {
442         u32 freq;
443         freq = decode_pll(PLL_SYS, MXC_HCLK);
444         printf("PLL_SYS    %8d MHz\n", freq / 1000000);
445         freq = decode_pll(PLL_BUS, MXC_HCLK);
446         printf("PLL_BUS    %8d MHz\n", freq / 1000000);
447         freq = decode_pll(PLL_USBOTG, MXC_HCLK);
448         printf("PLL_OTG    %8d MHz\n", freq / 1000000);
449         freq = decode_pll(PLL_ENET, MXC_HCLK);
450         printf("PLL_NET    %8d MHz\n", freq / 1000000);
451
452         printf("\n");
453         printf("IPG        %8d kHz\n", mxc_get_clock(MXC_IPG_CLK) / 1000);
454         printf("UART       %8d kHz\n", mxc_get_clock(MXC_UART_CLK) / 1000);
455 #ifdef CONFIG_MXC_SPI
456         printf("CSPI       %8d kHz\n", mxc_get_clock(MXC_CSPI_CLK) / 1000);
457 #endif
458         printf("AHB        %8d kHz\n", mxc_get_clock(MXC_AHB_CLK) / 1000);
459         printf("AXI        %8d kHz\n", mxc_get_clock(MXC_AXI_CLK) / 1000);
460         printf("DDR        %8d kHz\n", mxc_get_clock(MXC_DDR_CLK) / 1000);
461         printf("USDHC1     %8d kHz\n", mxc_get_clock(MXC_ESDHC_CLK) / 1000);
462         printf("USDHC2     %8d kHz\n", mxc_get_clock(MXC_ESDHC2_CLK) / 1000);
463         printf("USDHC3     %8d kHz\n", mxc_get_clock(MXC_ESDHC3_CLK) / 1000);
464         printf("USDHC4     %8d kHz\n", mxc_get_clock(MXC_ESDHC4_CLK) / 1000);
465         printf("EMI SLOW   %8d kHz\n", mxc_get_clock(MXC_EMI_SLOW_CLK) / 1000);
466         printf("IPG PERCLK %8d kHz\n", mxc_get_clock(MXC_IPG_PERCLK) / 1000);
467
468         return 0;
469 }
470
471 /***************************************************/
472
473 U_BOOT_CMD(
474         clocks, CONFIG_SYS_MAXARGS, 1, do_mx6_showclocks,
475         "display clocks",
476         ""
477 );