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);