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>
30 static int _clk_enable(struct clk *clk)
34 reg = __raw_readl(clk->enable_reg);
35 reg |= 1 << clk->enable_shift;
36 __raw_writel(reg, clk->enable_reg);
41 static void _clk_disable(struct clk *clk)
45 reg = __raw_readl(clk->enable_reg);
46 reg &= ~(1 << clk->enable_shift);
47 __raw_writel(reg, clk->enable_reg);
50 static int _clk_can_use_parent(const struct clk *clk_arr[], unsigned int size,
55 for (i = 0; i < size; i++)
56 if (parent == clk_arr[i])
63 _clk_simple_round_rate(struct clk *clk, unsigned long rate, unsigned int limit)
66 unsigned long parent_rate;
68 parent_rate = clk_get_rate(clk->parent);
70 div = parent_rate / rate;
71 if (parent_rate % rate)
77 return parent_rate / div;
80 static unsigned long _clk_parent_round_rate(struct clk *clk, unsigned long rate)
82 return clk->parent->round_rate(clk->parent, rate);
85 static int _clk_parent_set_rate(struct clk *clk, unsigned long rate)
87 return clk->parent->set_rate(clk->parent, rate);
90 static unsigned long clk16m_get_rate(struct clk *clk)
95 static struct clk clk16m = {
97 .get_rate = clk16m_get_rate,
98 .enable = _clk_enable,
99 .enable_reg = CCM_CSCR,
100 .enable_shift = CCM_CSCR_OSC_EN_SHIFT,
101 .disable = _clk_disable,
105 static unsigned long clk32_rate;
107 static unsigned long clk32_get_rate(struct clk *clk)
112 static struct clk clk32 = {
114 .get_rate = clk32_get_rate,
117 static unsigned long clk32_premult_get_rate(struct clk *clk)
119 return clk_get_rate(clk->parent) * 512;
122 static struct clk clk32_premult = {
123 .name = "CLK32_premultiplier",
125 .get_rate = clk32_premult_get_rate,
128 static const struct clk *prem_clk_clocks[] = {
133 static int prem_clk_set_parent(struct clk *clk, struct clk *parent)
136 unsigned int reg = __raw_readl(CCM_CSCR);
138 i = _clk_can_use_parent(prem_clk_clocks, ARRAY_SIZE(prem_clk_clocks),
143 reg &= ~CCM_CSCR_SYSTEM_SEL;
146 reg |= CCM_CSCR_SYSTEM_SEL;
152 __raw_writel(reg, CCM_CSCR);
157 static struct clk prem_clk = {
159 .set_parent = prem_clk_set_parent,
162 static unsigned long system_clk_get_rate(struct clk *clk)
164 return mxc_decode_pll(__raw_readl(CCM_SPCTL0),
165 clk_get_rate(clk->parent));
168 static struct clk system_clk = {
169 .name = "system_clk",
171 .get_rate = system_clk_get_rate,
174 static unsigned long mcu_clk_get_rate(struct clk *clk)
176 return mxc_decode_pll(__raw_readl(CCM_MPCTL0),
177 clk_get_rate(clk->parent));
180 static struct clk mcu_clk = {
182 .parent = &clk32_premult,
183 .get_rate = mcu_clk_get_rate,
186 static unsigned long fclk_get_rate(struct clk *clk)
188 unsigned long fclk = clk_get_rate(clk->parent);
190 if (__raw_readl(CCM_CSCR) & CCM_CSCR_PRESC)
196 static struct clk fclk = {
199 .get_rate = fclk_get_rate,
203 * get hclk ( SDRAM, CSI, Memory Stick, I2C, DMA )
205 static unsigned long hclk_get_rate(struct clk *clk)
207 return clk_get_rate(clk->parent) / (((__raw_readl(CCM_CSCR) &
208 CCM_CSCR_BCLK_MASK) >> CCM_CSCR_BCLK_OFFSET) + 1);
211 static unsigned long hclk_round_rate(struct clk *clk, unsigned long rate)
213 return _clk_simple_round_rate(clk, rate, 16);
216 static int hclk_set_rate(struct clk *clk, unsigned long rate)
220 unsigned long parent_rate;
222 parent_rate = clk_get_rate(clk->parent);
224 div = parent_rate / rate;
226 if (div > 16 || div < 1 || ((parent_rate / div) != rate))
231 reg = __raw_readl(CCM_CSCR);
232 reg &= ~CCM_CSCR_BCLK_MASK;
233 reg |= div << CCM_CSCR_BCLK_OFFSET;
234 __raw_writel(reg, CCM_CSCR);
239 static struct clk hclk = {
241 .parent = &system_clk,
242 .get_rate = hclk_get_rate,
243 .round_rate = hclk_round_rate,
244 .set_rate = hclk_set_rate,
247 static unsigned long clk48m_get_rate(struct clk *clk)
249 return clk_get_rate(clk->parent) / (((__raw_readl(CCM_CSCR) &
250 CCM_CSCR_USB_MASK) >> CCM_CSCR_USB_OFFSET) + 1);
253 static unsigned long clk48m_round_rate(struct clk *clk, unsigned long rate)
255 return _clk_simple_round_rate(clk, rate, 8);
258 static int clk48m_set_rate(struct clk *clk, unsigned long rate)
262 unsigned long parent_rate;
264 parent_rate = clk_get_rate(clk->parent);
266 div = parent_rate / rate;
268 if (div > 8 || div < 1 || ((parent_rate / div) != rate))
273 reg = __raw_readl(CCM_CSCR);
274 reg &= ~CCM_CSCR_USB_MASK;
275 reg |= div << CCM_CSCR_USB_OFFSET;
276 __raw_writel(reg, CCM_CSCR);
281 static struct clk clk48m = {
283 .parent = &system_clk,
284 .get_rate = clk48m_get_rate,
285 .round_rate = clk48m_round_rate,
286 .set_rate = clk48m_set_rate,
290 * get peripheral clock 1 ( UART[12], Timer[12], PWM )
292 static unsigned long perclk1_get_rate(struct clk *clk)
294 return clk_get_rate(clk->parent) / (((__raw_readl(CCM_PCDR) &
295 CCM_PCDR_PCLK1_MASK) >> CCM_PCDR_PCLK1_OFFSET) + 1);
298 static unsigned long perclk1_round_rate(struct clk *clk, unsigned long rate)
300 return _clk_simple_round_rate(clk, rate, 16);
303 static int perclk1_set_rate(struct clk *clk, unsigned long rate)
307 unsigned long parent_rate;
309 parent_rate = clk_get_rate(clk->parent);
311 div = parent_rate / rate;
313 if (div > 16 || div < 1 || ((parent_rate / div) != rate))
318 reg = __raw_readl(CCM_PCDR);
319 reg &= ~CCM_PCDR_PCLK1_MASK;
320 reg |= div << CCM_PCDR_PCLK1_OFFSET;
321 __raw_writel(reg, CCM_PCDR);
327 * get peripheral clock 2 ( LCD, SD, SPI[12] )
329 static unsigned long perclk2_get_rate(struct clk *clk)
331 return clk_get_rate(clk->parent) / (((__raw_readl(CCM_PCDR) &
332 CCM_PCDR_PCLK2_MASK) >> CCM_PCDR_PCLK2_OFFSET) + 1);
335 static unsigned long perclk2_round_rate(struct clk *clk, unsigned long rate)
337 return _clk_simple_round_rate(clk, rate, 16);
340 static int perclk2_set_rate(struct clk *clk, unsigned long rate)
344 unsigned long parent_rate;
346 parent_rate = clk_get_rate(clk->parent);
348 div = parent_rate / rate;
350 if (div > 16 || div < 1 || ((parent_rate / div) != rate))
355 reg = __raw_readl(CCM_PCDR);
356 reg &= ~CCM_PCDR_PCLK2_MASK;
357 reg |= div << CCM_PCDR_PCLK2_OFFSET;
358 __raw_writel(reg, CCM_PCDR);
364 * get peripheral clock 3 ( SSI )
366 static unsigned long perclk3_get_rate(struct clk *clk)
368 return clk_get_rate(clk->parent) / (((__raw_readl(CCM_PCDR) &
369 CCM_PCDR_PCLK3_MASK) >> CCM_PCDR_PCLK3_OFFSET) + 1);
372 static unsigned long perclk3_round_rate(struct clk *clk, unsigned long rate)
374 return _clk_simple_round_rate(clk, rate, 128);
377 static int perclk3_set_rate(struct clk *clk, unsigned long rate)
381 unsigned long parent_rate;
383 parent_rate = clk_get_rate(clk->parent);
385 div = parent_rate / rate;
387 if (div > 128 || div < 1 || ((parent_rate / div) != rate))
392 reg = __raw_readl(CCM_PCDR);
393 reg &= ~CCM_PCDR_PCLK3_MASK;
394 reg |= div << CCM_PCDR_PCLK3_OFFSET;
395 __raw_writel(reg, CCM_PCDR);
400 static struct clk perclk[] = {
404 .parent = &system_clk,
405 .get_rate = perclk1_get_rate,
406 .round_rate = perclk1_round_rate,
407 .set_rate = perclk1_set_rate,
411 .parent = &system_clk,
412 .get_rate = perclk2_get_rate,
413 .round_rate = perclk2_round_rate,
414 .set_rate = perclk2_set_rate,
418 .parent = &system_clk,
419 .get_rate = perclk3_get_rate,
420 .round_rate = perclk3_round_rate,
421 .set_rate = perclk3_set_rate,
425 static const struct clk *clko_clocks[] = {
434 static int clko_set_parent(struct clk *clk, struct clk *parent)
439 i = _clk_can_use_parent(clko_clocks, ARRAY_SIZE(clko_clocks), parent);
443 reg = __raw_readl(CCM_CSCR) & ~CCM_CSCR_CLKO_MASK;
444 reg |= i << CCM_CSCR_CLKO_OFFSET;
445 __raw_writel(reg, CCM_CSCR);
447 if (clko_clocks[i]->set_rate && clko_clocks[i]->round_rate) {
448 clk->set_rate = _clk_parent_set_rate;
449 clk->round_rate = _clk_parent_round_rate;
451 clk->set_rate = NULL;
452 clk->round_rate = NULL;
458 static struct clk clko_clk = {
460 .set_parent = clko_set_parent,
463 static struct clk dma_clk = {
466 .round_rate = _clk_parent_round_rate,
467 .set_rate = _clk_parent_set_rate,
468 .enable = _clk_enable,
469 .enable_reg = SCM_GCCR,
470 .enable_shift = SCM_GCCR_DMA_CLK_EN_OFFSET,
471 .disable = _clk_disable,
474 static struct clk csi_clk = {
477 .round_rate = _clk_parent_round_rate,
478 .set_rate = _clk_parent_set_rate,
479 .enable = _clk_enable,
480 .enable_reg = SCM_GCCR,
481 .enable_shift = SCM_GCCR_CSI_CLK_EN_OFFSET,
482 .disable = _clk_disable,
485 static struct clk mma_clk = {
488 .round_rate = _clk_parent_round_rate,
489 .set_rate = _clk_parent_set_rate,
490 .enable = _clk_enable,
491 .enable_reg = SCM_GCCR,
492 .enable_shift = SCM_GCCR_MMA_CLK_EN_OFFSET,
493 .disable = _clk_disable,
496 static struct clk usbd_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_USBD_CLK_EN_OFFSET,
504 .disable = _clk_disable,
507 static struct clk gpt_clk = {
509 .parent = &perclk[0],
510 .round_rate = _clk_parent_round_rate,
511 .set_rate = _clk_parent_set_rate,
514 static struct clk uart_clk = {
516 .parent = &perclk[0],
517 .round_rate = _clk_parent_round_rate,
518 .set_rate = _clk_parent_set_rate,
521 static struct clk i2c_clk = {
524 .round_rate = _clk_parent_round_rate,
525 .set_rate = _clk_parent_set_rate,
528 static struct clk spi_clk = {
530 .parent = &perclk[1],
531 .round_rate = _clk_parent_round_rate,
532 .set_rate = _clk_parent_set_rate,
535 static struct clk sdhc_clk = {
537 .parent = &perclk[1],
538 .round_rate = _clk_parent_round_rate,
539 .set_rate = _clk_parent_set_rate,
542 static struct clk lcdc_clk = {
544 .parent = &perclk[1],
545 .round_rate = _clk_parent_round_rate,
546 .set_rate = _clk_parent_set_rate,
549 static struct clk mshc_clk = {
552 .round_rate = _clk_parent_round_rate,
553 .set_rate = _clk_parent_set_rate,
556 static struct clk ssi_clk = {
558 .parent = &perclk[2],
559 .round_rate = _clk_parent_round_rate,
560 .set_rate = _clk_parent_set_rate,
563 static struct clk rtc_clk = {
568 static struct clk *mxc_clks[] = {
597 int __init mxc_clocks_init(unsigned long fref)
602 /* disable clocks we are able to */
603 __raw_writel(0, SCM_GCCR);
606 reg = __raw_readl(CCM_CSCR);
608 /* detect clock reference for system PLL */
609 if (reg & CCM_CSCR_SYSTEM_SEL) {
610 prem_clk.parent = &clk16m;
612 /* ensure that oscillator is disabled */
613 reg &= ~(1 << CCM_CSCR_OSC_EN_SHIFT);
614 __raw_writel(reg, CCM_CSCR);
615 prem_clk.parent = &clk32_premult;
618 /* detect reference for CLKO */
619 reg = (reg & CCM_CSCR_CLKO_MASK) >> CCM_CSCR_CLKO_OFFSET;
620 clko_clk.parent = (struct clk *)clko_clocks[reg];
622 for (clkp = mxc_clks; clkp < mxc_clks + ARRAY_SIZE(mxc_clks); clkp++)