2 * Copyright (C) 2008 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 #include <linux/kernel.h>
20 #include <linux/init.h>
21 #include <linux/math64.h>
22 #include <linux/err.h>
23 #include <linux/clk.h>
26 #include <mach/clock.h>
27 #include <mach/hardware.h>
28 #include <mach/common.h>
31 static int _clk_enable(struct clk
*clk
)
35 reg
= __raw_readl(clk
->enable_reg
);
36 reg
|= 1 << clk
->enable_shift
;
37 __raw_writel(reg
, clk
->enable_reg
);
42 static void _clk_disable(struct clk
*clk
)
46 reg
= __raw_readl(clk
->enable_reg
);
47 reg
&= ~(1 << clk
->enable_shift
);
48 __raw_writel(reg
, clk
->enable_reg
);
51 static int _clk_can_use_parent(const struct clk
*clk_arr
[], unsigned int size
,
56 for (i
= 0; i
< size
; i
++)
57 if (parent
== clk_arr
[i
])
64 _clk_simple_round_rate(struct clk
*clk
, unsigned long rate
, unsigned int limit
)
67 unsigned long parent_rate
;
69 parent_rate
= clk_get_rate(clk
->parent
);
71 div
= parent_rate
/ rate
;
72 if (parent_rate
% rate
)
78 return parent_rate
/ div
;
81 static unsigned long _clk_parent_round_rate(struct clk
*clk
, unsigned long rate
)
83 return clk
->parent
->round_rate(clk
->parent
, rate
);
86 static int _clk_parent_set_rate(struct clk
*clk
, unsigned long rate
)
88 return clk
->parent
->set_rate(clk
->parent
, rate
);
91 static unsigned long clk16m_get_rate(struct clk
*clk
)
96 static struct clk clk16m
= {
98 .get_rate
= clk16m_get_rate
,
99 .enable
= _clk_enable
,
100 .enable_reg
= CCM_CSCR
,
101 .enable_shift
= CCM_CSCR_OSC_EN_SHIFT
,
102 .disable
= _clk_disable
,
106 static unsigned long clk32_rate
;
108 static unsigned long clk32_get_rate(struct clk
*clk
)
113 static struct clk clk32
= {
115 .get_rate
= clk32_get_rate
,
118 static unsigned long clk32_premult_get_rate(struct clk
*clk
)
120 return clk_get_rate(clk
->parent
) * 512;
123 static struct clk clk32_premult
= {
124 .name
= "CLK32_premultiplier",
126 .get_rate
= clk32_premult_get_rate
,
129 static const struct clk
*prem_clk_clocks
[] = {
134 static int prem_clk_set_parent(struct clk
*clk
, struct clk
*parent
)
137 unsigned int reg
= __raw_readl(CCM_CSCR
);
139 i
= _clk_can_use_parent(prem_clk_clocks
, ARRAY_SIZE(prem_clk_clocks
),
144 reg
&= ~CCM_CSCR_SYSTEM_SEL
;
147 reg
|= CCM_CSCR_SYSTEM_SEL
;
153 __raw_writel(reg
, CCM_CSCR
);
158 static struct clk prem_clk
= {
160 .set_parent
= prem_clk_set_parent
,
163 static unsigned long system_clk_get_rate(struct clk
*clk
)
165 return mxc_decode_pll(__raw_readl(CCM_SPCTL0
),
166 clk_get_rate(clk
->parent
));
169 static struct clk system_clk
= {
170 .name
= "system_clk",
172 .get_rate
= system_clk_get_rate
,
175 static unsigned long mcu_clk_get_rate(struct clk
*clk
)
177 return mxc_decode_pll(__raw_readl(CCM_MPCTL0
),
178 clk_get_rate(clk
->parent
));
181 static struct clk mcu_clk
= {
183 .parent
= &clk32_premult
,
184 .get_rate
= mcu_clk_get_rate
,
187 static unsigned long fclk_get_rate(struct clk
*clk
)
189 unsigned long fclk
= clk_get_rate(clk
->parent
);
191 if (__raw_readl(CCM_CSCR
) & CCM_CSCR_PRESC
)
197 static struct clk fclk
= {
200 .get_rate
= fclk_get_rate
,
204 * get hclk ( SDRAM, CSI, Memory Stick, I2C, DMA )
206 static unsigned long hclk_get_rate(struct clk
*clk
)
208 return clk_get_rate(clk
->parent
) / (((__raw_readl(CCM_CSCR
) &
209 CCM_CSCR_BCLK_MASK
) >> CCM_CSCR_BCLK_OFFSET
) + 1);
212 static unsigned long hclk_round_rate(struct clk
*clk
, unsigned long rate
)
214 return _clk_simple_round_rate(clk
, rate
, 16);
217 static int hclk_set_rate(struct clk
*clk
, unsigned long rate
)
221 unsigned long parent_rate
;
223 parent_rate
= clk_get_rate(clk
->parent
);
225 div
= parent_rate
/ rate
;
227 if (div
> 16 || div
< 1 || ((parent_rate
/ div
) != rate
))
232 reg
= __raw_readl(CCM_CSCR
);
233 reg
&= ~CCM_CSCR_BCLK_MASK
;
234 reg
|= div
<< CCM_CSCR_BCLK_OFFSET
;
235 __raw_writel(reg
, CCM_CSCR
);
240 static struct clk hclk
= {
242 .parent
= &system_clk
,
243 .get_rate
= hclk_get_rate
,
244 .round_rate
= hclk_round_rate
,
245 .set_rate
= hclk_set_rate
,
248 static unsigned long clk48m_get_rate(struct clk
*clk
)
250 return clk_get_rate(clk
->parent
) / (((__raw_readl(CCM_CSCR
) &
251 CCM_CSCR_USB_MASK
) >> CCM_CSCR_USB_OFFSET
) + 1);
254 static unsigned long clk48m_round_rate(struct clk
*clk
, unsigned long rate
)
256 return _clk_simple_round_rate(clk
, rate
, 8);
259 static int clk48m_set_rate(struct clk
*clk
, unsigned long rate
)
263 unsigned long parent_rate
;
265 parent_rate
= clk_get_rate(clk
->parent
);
267 div
= parent_rate
/ rate
;
269 if (div
> 8 || div
< 1 || ((parent_rate
/ div
) != rate
))
274 reg
= __raw_readl(CCM_CSCR
);
275 reg
&= ~CCM_CSCR_USB_MASK
;
276 reg
|= div
<< CCM_CSCR_USB_OFFSET
;
277 __raw_writel(reg
, CCM_CSCR
);
282 static struct clk clk48m
= {
284 .parent
= &system_clk
,
285 .get_rate
= clk48m_get_rate
,
286 .round_rate
= clk48m_round_rate
,
287 .set_rate
= clk48m_set_rate
,
291 * get peripheral clock 1 ( UART[12], Timer[12], PWM )
293 static unsigned long perclk1_get_rate(struct clk
*clk
)
295 return clk_get_rate(clk
->parent
) / (((__raw_readl(CCM_PCDR
) &
296 CCM_PCDR_PCLK1_MASK
) >> CCM_PCDR_PCLK1_OFFSET
) + 1);
299 static unsigned long perclk1_round_rate(struct clk
*clk
, unsigned long rate
)
301 return _clk_simple_round_rate(clk
, rate
, 16);
304 static int perclk1_set_rate(struct clk
*clk
, unsigned long rate
)
308 unsigned long parent_rate
;
310 parent_rate
= clk_get_rate(clk
->parent
);
312 div
= parent_rate
/ rate
;
314 if (div
> 16 || div
< 1 || ((parent_rate
/ div
) != rate
))
319 reg
= __raw_readl(CCM_PCDR
);
320 reg
&= ~CCM_PCDR_PCLK1_MASK
;
321 reg
|= div
<< CCM_PCDR_PCLK1_OFFSET
;
322 __raw_writel(reg
, CCM_PCDR
);
328 * get peripheral clock 2 ( LCD, SD, SPI[12] )
330 static unsigned long perclk2_get_rate(struct clk
*clk
)
332 return clk_get_rate(clk
->parent
) / (((__raw_readl(CCM_PCDR
) &
333 CCM_PCDR_PCLK2_MASK
) >> CCM_PCDR_PCLK2_OFFSET
) + 1);
336 static unsigned long perclk2_round_rate(struct clk
*clk
, unsigned long rate
)
338 return _clk_simple_round_rate(clk
, rate
, 16);
341 static int perclk2_set_rate(struct clk
*clk
, unsigned long rate
)
345 unsigned long parent_rate
;
347 parent_rate
= clk_get_rate(clk
->parent
);
349 div
= parent_rate
/ rate
;
351 if (div
> 16 || div
< 1 || ((parent_rate
/ div
) != rate
))
356 reg
= __raw_readl(CCM_PCDR
);
357 reg
&= ~CCM_PCDR_PCLK2_MASK
;
358 reg
|= div
<< CCM_PCDR_PCLK2_OFFSET
;
359 __raw_writel(reg
, CCM_PCDR
);
365 * get peripheral clock 3 ( SSI )
367 static unsigned long perclk3_get_rate(struct clk
*clk
)
369 return clk_get_rate(clk
->parent
) / (((__raw_readl(CCM_PCDR
) &
370 CCM_PCDR_PCLK3_MASK
) >> CCM_PCDR_PCLK3_OFFSET
) + 1);
373 static unsigned long perclk3_round_rate(struct clk
*clk
, unsigned long rate
)
375 return _clk_simple_round_rate(clk
, rate
, 128);
378 static int perclk3_set_rate(struct clk
*clk
, unsigned long rate
)
382 unsigned long parent_rate
;
384 parent_rate
= clk_get_rate(clk
->parent
);
386 div
= parent_rate
/ rate
;
388 if (div
> 128 || div
< 1 || ((parent_rate
/ div
) != rate
))
393 reg
= __raw_readl(CCM_PCDR
);
394 reg
&= ~CCM_PCDR_PCLK3_MASK
;
395 reg
|= div
<< CCM_PCDR_PCLK3_OFFSET
;
396 __raw_writel(reg
, CCM_PCDR
);
401 static struct clk perclk
[] = {
405 .parent
= &system_clk
,
406 .get_rate
= perclk1_get_rate
,
407 .round_rate
= perclk1_round_rate
,
408 .set_rate
= perclk1_set_rate
,
412 .parent
= &system_clk
,
413 .get_rate
= perclk2_get_rate
,
414 .round_rate
= perclk2_round_rate
,
415 .set_rate
= perclk2_set_rate
,
419 .parent
= &system_clk
,
420 .get_rate
= perclk3_get_rate
,
421 .round_rate
= perclk3_round_rate
,
422 .set_rate
= perclk3_set_rate
,
426 static const struct clk
*clko_clocks
[] = {
435 static int clko_set_parent(struct clk
*clk
, struct clk
*parent
)
440 i
= _clk_can_use_parent(clko_clocks
, ARRAY_SIZE(clko_clocks
), parent
);
444 reg
= __raw_readl(CCM_CSCR
) & ~CCM_CSCR_CLKO_MASK
;
445 reg
|= i
<< CCM_CSCR_CLKO_OFFSET
;
446 __raw_writel(reg
, CCM_CSCR
);
448 if (clko_clocks
[i
]->set_rate
&& clko_clocks
[i
]->round_rate
) {
449 clk
->set_rate
= _clk_parent_set_rate
;
450 clk
->round_rate
= _clk_parent_round_rate
;
452 clk
->set_rate
= NULL
;
453 clk
->round_rate
= NULL
;
459 static struct clk clko_clk
= {
461 .set_parent
= clko_set_parent
,
464 static struct clk dma_clk
= {
467 .round_rate
= _clk_parent_round_rate
,
468 .set_rate
= _clk_parent_set_rate
,
469 .enable
= _clk_enable
,
470 .enable_reg
= SCM_GCCR
,
471 .enable_shift
= SCM_GCCR_DMA_CLK_EN_OFFSET
,
472 .disable
= _clk_disable
,
475 static struct clk csi_clk
= {
478 .round_rate
= _clk_parent_round_rate
,
479 .set_rate
= _clk_parent_set_rate
,
480 .enable
= _clk_enable
,
481 .enable_reg
= SCM_GCCR
,
482 .enable_shift
= SCM_GCCR_CSI_CLK_EN_OFFSET
,
483 .disable
= _clk_disable
,
486 static struct clk mma_clk
= {
489 .round_rate
= _clk_parent_round_rate
,
490 .set_rate
= _clk_parent_set_rate
,
491 .enable
= _clk_enable
,
492 .enable_reg
= SCM_GCCR
,
493 .enable_shift
= SCM_GCCR_MMA_CLK_EN_OFFSET
,
494 .disable
= _clk_disable
,
497 static struct clk usbd_clk
= {
500 .round_rate
= _clk_parent_round_rate
,
501 .set_rate
= _clk_parent_set_rate
,
502 .enable
= _clk_enable
,
503 .enable_reg
= SCM_GCCR
,
504 .enable_shift
= SCM_GCCR_USBD_CLK_EN_OFFSET
,
505 .disable
= _clk_disable
,
508 static struct clk gpt_clk
= {
510 .parent
= &perclk
[0],
511 .round_rate
= _clk_parent_round_rate
,
512 .set_rate
= _clk_parent_set_rate
,
515 static struct clk uart_clk
= {
517 .parent
= &perclk
[0],
518 .round_rate
= _clk_parent_round_rate
,
519 .set_rate
= _clk_parent_set_rate
,
522 static struct clk i2c_clk
= {
525 .round_rate
= _clk_parent_round_rate
,
526 .set_rate
= _clk_parent_set_rate
,
529 static struct clk spi_clk
= {
531 .parent
= &perclk
[1],
532 .round_rate
= _clk_parent_round_rate
,
533 .set_rate
= _clk_parent_set_rate
,
536 static struct clk sdhc_clk
= {
538 .parent
= &perclk
[1],
539 .round_rate
= _clk_parent_round_rate
,
540 .set_rate
= _clk_parent_set_rate
,
543 static struct clk lcdc_clk
= {
545 .parent
= &perclk
[1],
546 .round_rate
= _clk_parent_round_rate
,
547 .set_rate
= _clk_parent_set_rate
,
550 static struct clk mshc_clk
= {
553 .round_rate
= _clk_parent_round_rate
,
554 .set_rate
= _clk_parent_set_rate
,
557 static struct clk ssi_clk
= {
559 .parent
= &perclk
[2],
560 .round_rate
= _clk_parent_round_rate
,
561 .set_rate
= _clk_parent_set_rate
,
564 static struct clk rtc_clk
= {
569 static struct clk
*mxc_clks
[] = {
598 int __init
mx1_clocks_init(unsigned long fref
)
603 /* disable clocks we are able to */
604 __raw_writel(0, SCM_GCCR
);
607 reg
= __raw_readl(CCM_CSCR
);
609 /* detect clock reference for system PLL */
610 if (reg
& CCM_CSCR_SYSTEM_SEL
) {
611 prem_clk
.parent
= &clk16m
;
613 /* ensure that oscillator is disabled */
614 reg
&= ~(1 << CCM_CSCR_OSC_EN_SHIFT
);
615 __raw_writel(reg
, CCM_CSCR
);
616 prem_clk
.parent
= &clk32_premult
;
619 /* detect reference for CLKO */
620 reg
= (reg
& CCM_CSCR_CLKO_MASK
) >> CCM_CSCR_CLKO_OFFSET
;
621 clko_clk
.parent
= (struct clk
*)clko_clocks
[reg
];
623 for (clkp
= mxc_clks
; clkp
< mxc_clks
+ ARRAY_SIZE(mxc_clks
); clkp
++)
629 mxc_timer_init(&gpt_clk
);