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 version 2 as
6 * published by the Free Software Foundation.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License along
14 * with this program; if not, write to the Free Software Foundation, Inc.,
15 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
18 #include <linux/kernel.h>
19 #include <linux/init.h>
20 #include <linux/list.h>
21 #include <linux/math64.h>
22 #include <linux/err.h>
23 #include <linux/clk.h>
26 #include <asm/clkdev.h>
28 #include <mach/clock.h>
29 #include <mach/hardware.h>
30 #include <mach/common.h>
32 #define IO_ADDR_CCM(off) (MX1_IO_ADDRESS(MX1_CCM_BASE_ADDR + (off)))
34 /* CCM register addresses */
35 #define CCM_CSCR IO_ADDR_CCM(0x0)
36 #define CCM_MPCTL0 IO_ADDR_CCM(0x4)
37 #define CCM_SPCTL0 IO_ADDR_CCM(0xc)
38 #define CCM_PCDR IO_ADDR_CCM(0x20)
40 #define CCM_CSCR_CLKO_OFFSET 29
41 #define CCM_CSCR_CLKO_MASK (0x7 << 29)
42 #define CCM_CSCR_USB_OFFSET 26
43 #define CCM_CSCR_USB_MASK (0x7 << 26)
44 #define CCM_CSCR_OSC_EN_SHIFT 17
45 #define CCM_CSCR_SYSTEM_SEL (1 << 16)
46 #define CCM_CSCR_BCLK_OFFSET 10
47 #define CCM_CSCR_BCLK_MASK (0xf << 10)
48 #define CCM_CSCR_PRESC (1 << 15)
50 #define CCM_PCDR_PCLK3_OFFSET 16
51 #define CCM_PCDR_PCLK3_MASK (0x7f << 16)
52 #define CCM_PCDR_PCLK2_OFFSET 4
53 #define CCM_PCDR_PCLK2_MASK (0xf << 4)
54 #define CCM_PCDR_PCLK1_OFFSET 0
55 #define CCM_PCDR_PCLK1_MASK 0xf
57 #define IO_ADDR_SCM(off) (MX1_IO_ADDRESS(MX1_SCM_BASE_ADDR + (off)))
59 /* SCM register addresses */
60 #define SCM_GCCR IO_ADDR_SCM(0xc)
62 #define SCM_GCCR_DMA_CLK_EN_OFFSET 3
63 #define SCM_GCCR_CSI_CLK_EN_OFFSET 2
64 #define SCM_GCCR_MMA_CLK_EN_OFFSET 1
65 #define SCM_GCCR_USBD_CLK_EN_OFFSET 0
67 static int _clk_enable(struct clk
*clk
)
71 reg
= __raw_readl(clk
->enable_reg
);
72 reg
|= 1 << clk
->enable_shift
;
73 __raw_writel(reg
, clk
->enable_reg
);
78 static void _clk_disable(struct clk
*clk
)
82 reg
= __raw_readl(clk
->enable_reg
);
83 reg
&= ~(1 << clk
->enable_shift
);
84 __raw_writel(reg
, clk
->enable_reg
);
87 static int _clk_can_use_parent(const struct clk
*clk_arr
[], unsigned int size
,
92 for (i
= 0; i
< size
; i
++)
93 if (parent
== clk_arr
[i
])
100 _clk_simple_round_rate(struct clk
*clk
, unsigned long rate
, unsigned int limit
)
103 unsigned long parent_rate
;
105 parent_rate
= clk_get_rate(clk
->parent
);
107 div
= parent_rate
/ rate
;
108 if (parent_rate
% rate
)
114 return parent_rate
/ div
;
117 static unsigned long _clk_parent_round_rate(struct clk
*clk
, unsigned long rate
)
119 return clk
->parent
->round_rate(clk
->parent
, rate
);
122 static int _clk_parent_set_rate(struct clk
*clk
, unsigned long rate
)
124 return clk
->parent
->set_rate(clk
->parent
, rate
);
127 static unsigned long clk16m_get_rate(struct clk
*clk
)
132 static struct clk clk16m
= {
133 .get_rate
= clk16m_get_rate
,
134 .enable
= _clk_enable
,
135 .enable_reg
= CCM_CSCR
,
136 .enable_shift
= CCM_CSCR_OSC_EN_SHIFT
,
137 .disable
= _clk_disable
,
141 static unsigned long clk32_rate
;
143 static unsigned long clk32_get_rate(struct clk
*clk
)
148 static struct clk clk32
= {
149 .get_rate
= clk32_get_rate
,
152 static unsigned long clk32_premult_get_rate(struct clk
*clk
)
154 return clk_get_rate(clk
->parent
) * 512;
157 static struct clk clk32_premult
= {
159 .get_rate
= clk32_premult_get_rate
,
162 static const struct clk
*prem_clk_clocks
[] = {
167 static int prem_clk_set_parent(struct clk
*clk
, struct clk
*parent
)
170 unsigned int reg
= __raw_readl(CCM_CSCR
);
172 i
= _clk_can_use_parent(prem_clk_clocks
, ARRAY_SIZE(prem_clk_clocks
),
177 reg
&= ~CCM_CSCR_SYSTEM_SEL
;
180 reg
|= CCM_CSCR_SYSTEM_SEL
;
186 __raw_writel(reg
, CCM_CSCR
);
191 static struct clk prem_clk
= {
192 .set_parent
= prem_clk_set_parent
,
195 static unsigned long system_clk_get_rate(struct clk
*clk
)
197 return mxc_decode_pll(__raw_readl(CCM_SPCTL0
),
198 clk_get_rate(clk
->parent
));
201 static struct clk system_clk
= {
203 .get_rate
= system_clk_get_rate
,
206 static unsigned long mcu_clk_get_rate(struct clk
*clk
)
208 return mxc_decode_pll(__raw_readl(CCM_MPCTL0
),
209 clk_get_rate(clk
->parent
));
212 static struct clk mcu_clk
= {
213 .parent
= &clk32_premult
,
214 .get_rate
= mcu_clk_get_rate
,
217 static unsigned long fclk_get_rate(struct clk
*clk
)
219 unsigned long fclk
= clk_get_rate(clk
->parent
);
221 if (__raw_readl(CCM_CSCR
) & CCM_CSCR_PRESC
)
227 static struct clk fclk
= {
229 .get_rate
= fclk_get_rate
,
233 * get hclk ( SDRAM, CSI, Memory Stick, I2C, DMA )
235 static unsigned long hclk_get_rate(struct clk
*clk
)
237 return clk_get_rate(clk
->parent
) / (((__raw_readl(CCM_CSCR
) &
238 CCM_CSCR_BCLK_MASK
) >> CCM_CSCR_BCLK_OFFSET
) + 1);
241 static unsigned long hclk_round_rate(struct clk
*clk
, unsigned long rate
)
243 return _clk_simple_round_rate(clk
, rate
, 16);
246 static int hclk_set_rate(struct clk
*clk
, unsigned long rate
)
250 unsigned long parent_rate
;
252 parent_rate
= clk_get_rate(clk
->parent
);
254 div
= parent_rate
/ rate
;
256 if (div
> 16 || div
< 1 || ((parent_rate
/ div
) != rate
))
261 reg
= __raw_readl(CCM_CSCR
);
262 reg
&= ~CCM_CSCR_BCLK_MASK
;
263 reg
|= div
<< CCM_CSCR_BCLK_OFFSET
;
264 __raw_writel(reg
, CCM_CSCR
);
269 static struct clk hclk
= {
270 .parent
= &system_clk
,
271 .get_rate
= hclk_get_rate
,
272 .round_rate
= hclk_round_rate
,
273 .set_rate
= hclk_set_rate
,
276 static unsigned long clk48m_get_rate(struct clk
*clk
)
278 return clk_get_rate(clk
->parent
) / (((__raw_readl(CCM_CSCR
) &
279 CCM_CSCR_USB_MASK
) >> CCM_CSCR_USB_OFFSET
) + 1);
282 static unsigned long clk48m_round_rate(struct clk
*clk
, unsigned long rate
)
284 return _clk_simple_round_rate(clk
, rate
, 8);
287 static int clk48m_set_rate(struct clk
*clk
, unsigned long rate
)
291 unsigned long parent_rate
;
293 parent_rate
= clk_get_rate(clk
->parent
);
295 div
= parent_rate
/ rate
;
297 if (div
> 8 || div
< 1 || ((parent_rate
/ div
) != rate
))
302 reg
= __raw_readl(CCM_CSCR
);
303 reg
&= ~CCM_CSCR_USB_MASK
;
304 reg
|= div
<< CCM_CSCR_USB_OFFSET
;
305 __raw_writel(reg
, CCM_CSCR
);
310 static struct clk clk48m
= {
311 .parent
= &system_clk
,
312 .get_rate
= clk48m_get_rate
,
313 .round_rate
= clk48m_round_rate
,
314 .set_rate
= clk48m_set_rate
,
318 * get peripheral clock 1 ( UART[12], Timer[12], PWM )
320 static unsigned long perclk1_get_rate(struct clk
*clk
)
322 return clk_get_rate(clk
->parent
) / (((__raw_readl(CCM_PCDR
) &
323 CCM_PCDR_PCLK1_MASK
) >> CCM_PCDR_PCLK1_OFFSET
) + 1);
326 static unsigned long perclk1_round_rate(struct clk
*clk
, unsigned long rate
)
328 return _clk_simple_round_rate(clk
, rate
, 16);
331 static int perclk1_set_rate(struct clk
*clk
, unsigned long rate
)
335 unsigned long parent_rate
;
337 parent_rate
= clk_get_rate(clk
->parent
);
339 div
= parent_rate
/ rate
;
341 if (div
> 16 || div
< 1 || ((parent_rate
/ div
) != rate
))
346 reg
= __raw_readl(CCM_PCDR
);
347 reg
&= ~CCM_PCDR_PCLK1_MASK
;
348 reg
|= div
<< CCM_PCDR_PCLK1_OFFSET
;
349 __raw_writel(reg
, CCM_PCDR
);
355 * get peripheral clock 2 ( LCD, SD, SPI[12] )
357 static unsigned long perclk2_get_rate(struct clk
*clk
)
359 return clk_get_rate(clk
->parent
) / (((__raw_readl(CCM_PCDR
) &
360 CCM_PCDR_PCLK2_MASK
) >> CCM_PCDR_PCLK2_OFFSET
) + 1);
363 static unsigned long perclk2_round_rate(struct clk
*clk
, unsigned long rate
)
365 return _clk_simple_round_rate(clk
, rate
, 16);
368 static int perclk2_set_rate(struct clk
*clk
, unsigned long rate
)
372 unsigned long parent_rate
;
374 parent_rate
= clk_get_rate(clk
->parent
);
376 div
= parent_rate
/ rate
;
378 if (div
> 16 || div
< 1 || ((parent_rate
/ div
) != rate
))
383 reg
= __raw_readl(CCM_PCDR
);
384 reg
&= ~CCM_PCDR_PCLK2_MASK
;
385 reg
|= div
<< CCM_PCDR_PCLK2_OFFSET
;
386 __raw_writel(reg
, CCM_PCDR
);
392 * get peripheral clock 3 ( SSI )
394 static unsigned long perclk3_get_rate(struct clk
*clk
)
396 return clk_get_rate(clk
->parent
) / (((__raw_readl(CCM_PCDR
) &
397 CCM_PCDR_PCLK3_MASK
) >> CCM_PCDR_PCLK3_OFFSET
) + 1);
400 static unsigned long perclk3_round_rate(struct clk
*clk
, unsigned long rate
)
402 return _clk_simple_round_rate(clk
, rate
, 128);
405 static int perclk3_set_rate(struct clk
*clk
, unsigned long rate
)
409 unsigned long parent_rate
;
411 parent_rate
= clk_get_rate(clk
->parent
);
413 div
= parent_rate
/ rate
;
415 if (div
> 128 || div
< 1 || ((parent_rate
/ div
) != rate
))
420 reg
= __raw_readl(CCM_PCDR
);
421 reg
&= ~CCM_PCDR_PCLK3_MASK
;
422 reg
|= div
<< CCM_PCDR_PCLK3_OFFSET
;
423 __raw_writel(reg
, CCM_PCDR
);
428 static struct clk perclk
[] = {
431 .parent
= &system_clk
,
432 .get_rate
= perclk1_get_rate
,
433 .round_rate
= perclk1_round_rate
,
434 .set_rate
= perclk1_set_rate
,
437 .parent
= &system_clk
,
438 .get_rate
= perclk2_get_rate
,
439 .round_rate
= perclk2_round_rate
,
440 .set_rate
= perclk2_set_rate
,
443 .parent
= &system_clk
,
444 .get_rate
= perclk3_get_rate
,
445 .round_rate
= perclk3_round_rate
,
446 .set_rate
= perclk3_set_rate
,
450 static const struct clk
*clko_clocks
[] = {
459 static int clko_set_parent(struct clk
*clk
, struct clk
*parent
)
464 i
= _clk_can_use_parent(clko_clocks
, ARRAY_SIZE(clko_clocks
), parent
);
468 reg
= __raw_readl(CCM_CSCR
) & ~CCM_CSCR_CLKO_MASK
;
469 reg
|= i
<< CCM_CSCR_CLKO_OFFSET
;
470 __raw_writel(reg
, CCM_CSCR
);
472 if (clko_clocks
[i
]->set_rate
&& clko_clocks
[i
]->round_rate
) {
473 clk
->set_rate
= _clk_parent_set_rate
;
474 clk
->round_rate
= _clk_parent_round_rate
;
476 clk
->set_rate
= NULL
;
477 clk
->round_rate
= NULL
;
483 static struct clk clko_clk
= {
484 .set_parent
= clko_set_parent
,
487 static struct clk dma_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_DMA_CLK_EN_OFFSET
,
494 .disable
= _clk_disable
,
497 static struct clk csi_clk
= {
499 .round_rate
= _clk_parent_round_rate
,
500 .set_rate
= _clk_parent_set_rate
,
501 .enable
= _clk_enable
,
502 .enable_reg
= SCM_GCCR
,
503 .enable_shift
= SCM_GCCR_CSI_CLK_EN_OFFSET
,
504 .disable
= _clk_disable
,
507 static struct clk mma_clk
= {
509 .round_rate
= _clk_parent_round_rate
,
510 .set_rate
= _clk_parent_set_rate
,
511 .enable
= _clk_enable
,
512 .enable_reg
= SCM_GCCR
,
513 .enable_shift
= SCM_GCCR_MMA_CLK_EN_OFFSET
,
514 .disable
= _clk_disable
,
517 static struct clk usbd_clk
= {
519 .round_rate
= _clk_parent_round_rate
,
520 .set_rate
= _clk_parent_set_rate
,
521 .enable
= _clk_enable
,
522 .enable_reg
= SCM_GCCR
,
523 .enable_shift
= SCM_GCCR_USBD_CLK_EN_OFFSET
,
524 .disable
= _clk_disable
,
527 static struct clk gpt_clk
= {
528 .parent
= &perclk
[0],
529 .round_rate
= _clk_parent_round_rate
,
530 .set_rate
= _clk_parent_set_rate
,
533 static struct clk uart_clk
= {
534 .parent
= &perclk
[0],
535 .round_rate
= _clk_parent_round_rate
,
536 .set_rate
= _clk_parent_set_rate
,
539 static struct clk i2c_clk
= {
541 .round_rate
= _clk_parent_round_rate
,
542 .set_rate
= _clk_parent_set_rate
,
545 static struct clk spi_clk
= {
546 .parent
= &perclk
[1],
547 .round_rate
= _clk_parent_round_rate
,
548 .set_rate
= _clk_parent_set_rate
,
551 static struct clk sdhc_clk
= {
552 .parent
= &perclk
[1],
553 .round_rate
= _clk_parent_round_rate
,
554 .set_rate
= _clk_parent_set_rate
,
557 static struct clk lcdc_clk
= {
558 .parent
= &perclk
[1],
559 .round_rate
= _clk_parent_round_rate
,
560 .set_rate
= _clk_parent_set_rate
,
563 static struct clk mshc_clk
= {
565 .round_rate
= _clk_parent_round_rate
,
566 .set_rate
= _clk_parent_set_rate
,
569 static struct clk ssi_clk
= {
570 .parent
= &perclk
[2],
571 .round_rate
= _clk_parent_round_rate
,
572 .set_rate
= _clk_parent_set_rate
,
575 static struct clk rtc_clk
= {
579 #define _REGISTER_CLOCK(d, n, c) \
585 static struct clk_lookup lookups
[] __initdata
= {
586 _REGISTER_CLOCK(NULL
, "dma", dma_clk
)
587 _REGISTER_CLOCK("mx1-camera.0", NULL
, csi_clk
)
588 _REGISTER_CLOCK(NULL
, "mma", mma_clk
)
589 _REGISTER_CLOCK("imx_udc.0", NULL
, usbd_clk
)
590 _REGISTER_CLOCK(NULL
, "gpt", gpt_clk
)
591 _REGISTER_CLOCK("imx-uart.0", NULL
, uart_clk
)
592 _REGISTER_CLOCK("imx-uart.1", NULL
, uart_clk
)
593 _REGISTER_CLOCK("imx-uart.2", NULL
, uart_clk
)
594 _REGISTER_CLOCK("imx-i2c.0", NULL
, i2c_clk
)
595 _REGISTER_CLOCK("spi_imx.0", NULL
, spi_clk
)
596 _REGISTER_CLOCK("imx-mmc.0", NULL
, sdhc_clk
)
597 _REGISTER_CLOCK("imx-fb.0", NULL
, lcdc_clk
)
598 _REGISTER_CLOCK(NULL
, "mshc", mshc_clk
)
599 _REGISTER_CLOCK(NULL
, "ssi", ssi_clk
)
600 _REGISTER_CLOCK("mxc_rtc.0", NULL
, rtc_clk
)
603 int __init
mx1_clocks_init(unsigned long fref
)
607 /* disable clocks we are able to */
608 __raw_writel(0, SCM_GCCR
);
611 reg
= __raw_readl(CCM_CSCR
);
613 /* detect clock reference for system PLL */
614 if (reg
& CCM_CSCR_SYSTEM_SEL
) {
615 prem_clk
.parent
= &clk16m
;
617 /* ensure that oscillator is disabled */
618 reg
&= ~(1 << CCM_CSCR_OSC_EN_SHIFT
);
619 __raw_writel(reg
, CCM_CSCR
);
620 prem_clk
.parent
= &clk32_premult
;
623 /* detect reference for CLKO */
624 reg
= (reg
& CCM_CSCR_CLKO_MASK
) >> CCM_CSCR_CLKO_OFFSET
;
625 clko_clk
.parent
= (struct clk
*)clko_clocks
[reg
];
627 clkdev_add_table(lookups
, ARRAY_SIZE(lookups
));
632 mxc_timer_init(&gpt_clk
, MX1_IO_ADDRESS(MX1_TIM1_BASE_ADDR
),