blob: ba9432c8f84303dc182e78ee9e2e07d580023967 [file] [log] [blame]
Amit Kucheriaa329b482010-02-04 12:21:53 -08001/*
2 * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
3 * Copyright (C) 2009-2010 Amit Kucheria <amit.kucheria@canonical.com>
4 *
5 * The code contained herein is licensed under the GNU General Public
6 * License. You may obtain a copy of the GNU General Public License
7 * Version 2 or later at the following locations:
8 *
9 * http://www.opensource.org/licenses/gpl-license.html
10 * http://www.gnu.org/copyleft/gpl.html
11 */
12
13#include <linux/mm.h>
14#include <linux/delay.h>
15#include <linux/clk.h>
16#include <linux/io.h>
17
18#include <asm/clkdev.h>
Dinh Nguyen17807f92010-04-13 14:05:08 -050019#include <asm/div64.h>
Amit Kucheriaa329b482010-02-04 12:21:53 -080020
21#include <mach/hardware.h>
22#include <mach/common.h>
23#include <mach/clock.h>
24
25#include "crm_regs.h"
26
27/* External clock values passed-in by the board code */
28static unsigned long external_high_reference, external_low_reference;
29static unsigned long oscillator_reference, ckih2_reference;
30
31static struct clk osc_clk;
32static struct clk pll1_main_clk;
33static struct clk pll1_sw_clk;
34static struct clk pll2_sw_clk;
35static struct clk pll3_sw_clk;
Dinh Nguyenc0abefd2010-11-15 11:29:59 -060036static struct clk mx53_pll4_sw_clk;
Amit Kucheriaa329b482010-02-04 12:21:53 -080037static struct clk lp_apm_clk;
38static struct clk periph_apm_clk;
39static struct clk ahb_clk;
40static struct clk ipg_clk;
Dinh Nguyenc79504e2010-05-10 13:45:58 -050041static struct clk usboh3_clk;
Sascha Hauerb8481692010-12-06 09:13:21 +010042static struct clk emi_fast_clk;
43static struct clk ipu_clk;
44static struct clk mipi_hsc1_clk;
Amit Kucheriaa329b482010-02-04 12:21:53 -080045
46#define MAX_DPLL_WAIT_TRIES 1000 /* 1000 * udelay(1) = 1ms */
47
Eric Bénard6a001b82010-10-11 17:59:47 +020048/* calculate best pre and post dividers to get the required divider */
49static void __calc_pre_post_dividers(u32 div, u32 *pre, u32 *post,
50 u32 max_pre, u32 max_post)
51{
52 if (div >= max_pre * max_post) {
53 *pre = max_pre;
54 *post = max_post;
55 } else if (div >= max_pre) {
56 u32 min_pre, temp_pre, old_err, err;
57 min_pre = DIV_ROUND_UP(div, max_post);
58 old_err = max_pre;
59 for (temp_pre = max_pre; temp_pre >= min_pre; temp_pre--) {
60 err = div % temp_pre;
61 if (err == 0) {
62 *pre = temp_pre;
63 break;
64 }
65 err = temp_pre - err;
66 if (err < old_err) {
67 old_err = err;
68 *pre = temp_pre;
69 }
70 }
71 *post = DIV_ROUND_UP(div, *pre);
72 } else {
73 *pre = div;
74 *post = 1;
75 }
76}
77
Uwe Kleine-König79901472010-09-10 16:58:42 +020078static void _clk_ccgr_setclk(struct clk *clk, unsigned mode)
79{
80 u32 reg = __raw_readl(clk->enable_reg);
81
82 reg &= ~(MXC_CCM_CCGRx_CG_MASK << clk->enable_shift);
83 reg |= mode << clk->enable_shift;
84
85 __raw_writel(reg, clk->enable_reg);
86}
87
Amit Kucheriaa329b482010-02-04 12:21:53 -080088static int _clk_ccgr_enable(struct clk *clk)
89{
Uwe Kleine-König79901472010-09-10 16:58:42 +020090 _clk_ccgr_setclk(clk, MXC_CCM_CCGRx_MOD_ON);
Amit Kucheriaa329b482010-02-04 12:21:53 -080091 return 0;
92}
93
94static void _clk_ccgr_disable(struct clk *clk)
95{
Uwe Kleine-König79901472010-09-10 16:58:42 +020096 _clk_ccgr_setclk(clk, MXC_CCM_CCGRx_MOD_OFF);
97}
Amit Kucheriaa329b482010-02-04 12:21:53 -080098
Uwe Kleine-König79901472010-09-10 16:58:42 +020099static int _clk_ccgr_enable_inrun(struct clk *clk)
100{
101 _clk_ccgr_setclk(clk, MXC_CCM_CCGRx_MOD_IDLE);
102 return 0;
Amit Kucheriaa329b482010-02-04 12:21:53 -0800103}
104
105static void _clk_ccgr_disable_inwait(struct clk *clk)
106{
Uwe Kleine-König79901472010-09-10 16:58:42 +0200107 _clk_ccgr_setclk(clk, MXC_CCM_CCGRx_MOD_IDLE);
Amit Kucheriaa329b482010-02-04 12:21:53 -0800108}
109
110/*
111 * For the 4-to-1 muxed input clock
112 */
113static inline u32 _get_mux(struct clk *parent, struct clk *m0,
114 struct clk *m1, struct clk *m2, struct clk *m3)
115{
116 if (parent == m0)
117 return 0;
118 else if (parent == m1)
119 return 1;
120 else if (parent == m2)
121 return 2;
122 else if (parent == m3)
123 return 3;
124 else
125 BUG();
126
127 return -EINVAL;
128}
129
130static inline void __iomem *_get_pll_base(struct clk *pll)
131{
132 if (pll == &pll1_main_clk)
133 return MX51_DPLL1_BASE;
134 else if (pll == &pll2_sw_clk)
135 return MX51_DPLL2_BASE;
136 else if (pll == &pll3_sw_clk)
137 return MX51_DPLL3_BASE;
Dinh Nguyenc0abefd2010-11-15 11:29:59 -0600138 else if (pll == &mx53_pll4_sw_clk)
139 return MX53_DPLL4_BASE;
Amit Kucheriaa329b482010-02-04 12:21:53 -0800140 else
141 BUG();
142
143 return NULL;
144}
145
146static unsigned long clk_pll_get_rate(struct clk *clk)
147{
148 long mfi, mfn, mfd, pdf, ref_clk, mfn_abs;
149 unsigned long dp_op, dp_mfd, dp_mfn, dp_ctl, pll_hfsm, dbl;
150 void __iomem *pllbase;
151 s64 temp;
152 unsigned long parent_rate;
153
154 parent_rate = clk_get_rate(clk->parent);
155
156 pllbase = _get_pll_base(clk);
157
158 dp_ctl = __raw_readl(pllbase + MXC_PLL_DP_CTL);
159 pll_hfsm = dp_ctl & MXC_PLL_DP_CTL_HFSM;
160 dbl = dp_ctl & MXC_PLL_DP_CTL_DPDCK0_2_EN;
161
162 if (pll_hfsm == 0) {
163 dp_op = __raw_readl(pllbase + MXC_PLL_DP_OP);
164 dp_mfd = __raw_readl(pllbase + MXC_PLL_DP_MFD);
165 dp_mfn = __raw_readl(pllbase + MXC_PLL_DP_MFN);
166 } else {
167 dp_op = __raw_readl(pllbase + MXC_PLL_DP_HFS_OP);
168 dp_mfd = __raw_readl(pllbase + MXC_PLL_DP_HFS_MFD);
169 dp_mfn = __raw_readl(pllbase + MXC_PLL_DP_HFS_MFN);
170 }
171 pdf = dp_op & MXC_PLL_DP_OP_PDF_MASK;
172 mfi = (dp_op & MXC_PLL_DP_OP_MFI_MASK) >> MXC_PLL_DP_OP_MFI_OFFSET;
173 mfi = (mfi <= 5) ? 5 : mfi;
174 mfd = dp_mfd & MXC_PLL_DP_MFD_MASK;
175 mfn = mfn_abs = dp_mfn & MXC_PLL_DP_MFN_MASK;
176 /* Sign extend to 32-bits */
177 if (mfn >= 0x04000000) {
178 mfn |= 0xFC000000;
179 mfn_abs = -mfn;
180 }
181
182 ref_clk = 2 * parent_rate;
183 if (dbl != 0)
184 ref_clk *= 2;
185
186 ref_clk /= (pdf + 1);
187 temp = (u64) ref_clk * mfn_abs;
188 do_div(temp, mfd + 1);
189 if (mfn < 0)
190 temp = -temp;
191 temp = (ref_clk * mfi) + temp;
192
193 return temp;
194}
195
196static int _clk_pll_set_rate(struct clk *clk, unsigned long rate)
197{
198 u32 reg;
199 void __iomem *pllbase;
200
201 long mfi, pdf, mfn, mfd = 999999;
202 s64 temp64;
203 unsigned long quad_parent_rate;
204 unsigned long pll_hfsm, dp_ctl;
205 unsigned long parent_rate;
206
207 parent_rate = clk_get_rate(clk->parent);
208
209 pllbase = _get_pll_base(clk);
210
211 quad_parent_rate = 4 * parent_rate;
212 pdf = mfi = -1;
213 while (++pdf < 16 && mfi < 5)
214 mfi = rate * (pdf+1) / quad_parent_rate;
215 if (mfi > 15)
216 return -EINVAL;
217 pdf--;
218
219 temp64 = rate * (pdf+1) - quad_parent_rate * mfi;
220 do_div(temp64, quad_parent_rate/1000000);
221 mfn = (long)temp64;
222
223 dp_ctl = __raw_readl(pllbase + MXC_PLL_DP_CTL);
224 /* use dpdck0_2 */
225 __raw_writel(dp_ctl | 0x1000L, pllbase + MXC_PLL_DP_CTL);
226 pll_hfsm = dp_ctl & MXC_PLL_DP_CTL_HFSM;
227 if (pll_hfsm == 0) {
228 reg = mfi << 4 | pdf;
229 __raw_writel(reg, pllbase + MXC_PLL_DP_OP);
230 __raw_writel(mfd, pllbase + MXC_PLL_DP_MFD);
231 __raw_writel(mfn, pllbase + MXC_PLL_DP_MFN);
232 } else {
233 reg = mfi << 4 | pdf;
234 __raw_writel(reg, pllbase + MXC_PLL_DP_HFS_OP);
235 __raw_writel(mfd, pllbase + MXC_PLL_DP_HFS_MFD);
236 __raw_writel(mfn, pllbase + MXC_PLL_DP_HFS_MFN);
237 }
238
239 return 0;
240}
241
242static int _clk_pll_enable(struct clk *clk)
243{
244 u32 reg;
245 void __iomem *pllbase;
246 int i = 0;
247
248 pllbase = _get_pll_base(clk);
249 reg = __raw_readl(pllbase + MXC_PLL_DP_CTL) | MXC_PLL_DP_CTL_UPEN;
250 __raw_writel(reg, pllbase + MXC_PLL_DP_CTL);
251
252 /* Wait for lock */
253 do {
254 reg = __raw_readl(pllbase + MXC_PLL_DP_CTL);
255 if (reg & MXC_PLL_DP_CTL_LRF)
256 break;
257
258 udelay(1);
259 } while (++i < MAX_DPLL_WAIT_TRIES);
260
261 if (i == MAX_DPLL_WAIT_TRIES) {
262 pr_err("MX5: pll locking failed\n");
263 return -EINVAL;
264 }
265
266 return 0;
267}
268
269static void _clk_pll_disable(struct clk *clk)
270{
271 u32 reg;
272 void __iomem *pllbase;
273
274 pllbase = _get_pll_base(clk);
275 reg = __raw_readl(pllbase + MXC_PLL_DP_CTL) & ~MXC_PLL_DP_CTL_UPEN;
276 __raw_writel(reg, pllbase + MXC_PLL_DP_CTL);
277}
278
279static int _clk_pll1_sw_set_parent(struct clk *clk, struct clk *parent)
280{
281 u32 reg, step;
282
283 reg = __raw_readl(MXC_CCM_CCSR);
284
285 /* When switching from pll_main_clk to a bypass clock, first select a
286 * multiplexed clock in 'step_sel', then shift the glitchless mux
287 * 'pll1_sw_clk_sel'.
288 *
289 * When switching back, do it in reverse order
290 */
291 if (parent == &pll1_main_clk) {
292 /* Switch to pll1_main_clk */
293 reg &= ~MXC_CCM_CCSR_PLL1_SW_CLK_SEL;
294 __raw_writel(reg, MXC_CCM_CCSR);
295 /* step_clk mux switched to lp_apm, to save power. */
296 reg = __raw_readl(MXC_CCM_CCSR);
297 reg &= ~MXC_CCM_CCSR_STEP_SEL_MASK;
298 reg |= (MXC_CCM_CCSR_STEP_SEL_LP_APM <<
299 MXC_CCM_CCSR_STEP_SEL_OFFSET);
300 } else {
301 if (parent == &lp_apm_clk) {
302 step = MXC_CCM_CCSR_STEP_SEL_LP_APM;
303 } else if (parent == &pll2_sw_clk) {
304 step = MXC_CCM_CCSR_STEP_SEL_PLL2_DIVIDED;
305 } else if (parent == &pll3_sw_clk) {
306 step = MXC_CCM_CCSR_STEP_SEL_PLL3_DIVIDED;
307 } else
308 return -EINVAL;
309
310 reg &= ~MXC_CCM_CCSR_STEP_SEL_MASK;
311 reg |= (step << MXC_CCM_CCSR_STEP_SEL_OFFSET);
312
313 __raw_writel(reg, MXC_CCM_CCSR);
314 /* Switch to step_clk */
315 reg = __raw_readl(MXC_CCM_CCSR);
316 reg |= MXC_CCM_CCSR_PLL1_SW_CLK_SEL;
317 }
318 __raw_writel(reg, MXC_CCM_CCSR);
319 return 0;
320}
321
322static unsigned long clk_pll1_sw_get_rate(struct clk *clk)
323{
324 u32 reg, div;
325 unsigned long parent_rate;
326
327 parent_rate = clk_get_rate(clk->parent);
328
329 reg = __raw_readl(MXC_CCM_CCSR);
330
331 if (clk->parent == &pll2_sw_clk) {
332 div = ((reg & MXC_CCM_CCSR_PLL2_PODF_MASK) >>
333 MXC_CCM_CCSR_PLL2_PODF_OFFSET) + 1;
334 } else if (clk->parent == &pll3_sw_clk) {
335 div = ((reg & MXC_CCM_CCSR_PLL3_PODF_MASK) >>
336 MXC_CCM_CCSR_PLL3_PODF_OFFSET) + 1;
337 } else
338 div = 1;
339 return parent_rate / div;
340}
341
342static int _clk_pll2_sw_set_parent(struct clk *clk, struct clk *parent)
343{
344 u32 reg;
345
346 reg = __raw_readl(MXC_CCM_CCSR);
347
348 if (parent == &pll2_sw_clk)
349 reg &= ~MXC_CCM_CCSR_PLL2_SW_CLK_SEL;
350 else
351 reg |= MXC_CCM_CCSR_PLL2_SW_CLK_SEL;
352
353 __raw_writel(reg, MXC_CCM_CCSR);
354 return 0;
355}
356
357static int _clk_lp_apm_set_parent(struct clk *clk, struct clk *parent)
358{
359 u32 reg;
360
361 if (parent == &osc_clk)
362 reg = __raw_readl(MXC_CCM_CCSR) & ~MXC_CCM_CCSR_LP_APM_SEL;
363 else
364 return -EINVAL;
365
366 __raw_writel(reg, MXC_CCM_CCSR);
367
368 return 0;
369}
370
Yong Shen64f102b2010-10-21 21:18:59 +0800371static unsigned long clk_cpu_get_rate(struct clk *clk)
Amit Kucheriaa329b482010-02-04 12:21:53 -0800372{
373 u32 cacrr, div;
374 unsigned long parent_rate;
375
376 parent_rate = clk_get_rate(clk->parent);
377 cacrr = __raw_readl(MXC_CCM_CACRR);
378 div = (cacrr & MXC_CCM_CACRR_ARM_PODF_MASK) + 1;
379
380 return parent_rate / div;
381}
382
Yong Shen64f102b2010-10-21 21:18:59 +0800383static int clk_cpu_set_rate(struct clk *clk, unsigned long rate)
384{
385 u32 reg, cpu_podf;
386 unsigned long parent_rate;
387
388 parent_rate = clk_get_rate(clk->parent);
389 cpu_podf = parent_rate / rate - 1;
390 /* use post divider to change freq */
391 reg = __raw_readl(MXC_CCM_CACRR);
392 reg &= ~MXC_CCM_CACRR_ARM_PODF_MASK;
393 reg |= cpu_podf << MXC_CCM_CACRR_ARM_PODF_OFFSET;
394 __raw_writel(reg, MXC_CCM_CACRR);
395
396 return 0;
397}
398
Amit Kucheriaa329b482010-02-04 12:21:53 -0800399static int _clk_periph_apm_set_parent(struct clk *clk, struct clk *parent)
400{
401 u32 reg, mux;
402 int i = 0;
403
404 mux = _get_mux(parent, &pll1_sw_clk, &pll3_sw_clk, &lp_apm_clk, NULL);
405
406 reg = __raw_readl(MXC_CCM_CBCMR) & ~MXC_CCM_CBCMR_PERIPH_CLK_SEL_MASK;
407 reg |= mux << MXC_CCM_CBCMR_PERIPH_CLK_SEL_OFFSET;
408 __raw_writel(reg, MXC_CCM_CBCMR);
409
410 /* Wait for lock */
411 do {
412 reg = __raw_readl(MXC_CCM_CDHIPR);
413 if (!(reg & MXC_CCM_CDHIPR_PERIPH_CLK_SEL_BUSY))
414 break;
415
416 udelay(1);
417 } while (++i < MAX_DPLL_WAIT_TRIES);
418
419 if (i == MAX_DPLL_WAIT_TRIES) {
420 pr_err("MX5: Set parent for periph_apm clock failed\n");
421 return -EINVAL;
422 }
423
424 return 0;
425}
426
427static int _clk_main_bus_set_parent(struct clk *clk, struct clk *parent)
428{
429 u32 reg;
430
431 reg = __raw_readl(MXC_CCM_CBCDR);
432
433 if (parent == &pll2_sw_clk)
434 reg &= ~MXC_CCM_CBCDR_PERIPH_CLK_SEL;
435 else if (parent == &periph_apm_clk)
436 reg |= MXC_CCM_CBCDR_PERIPH_CLK_SEL;
437 else
438 return -EINVAL;
439
440 __raw_writel(reg, MXC_CCM_CBCDR);
441
442 return 0;
443}
444
445static struct clk main_bus_clk = {
446 .parent = &pll2_sw_clk,
447 .set_parent = _clk_main_bus_set_parent,
448};
449
450static unsigned long clk_ahb_get_rate(struct clk *clk)
451{
452 u32 reg, div;
453 unsigned long parent_rate;
454
455 parent_rate = clk_get_rate(clk->parent);
456
457 reg = __raw_readl(MXC_CCM_CBCDR);
458 div = ((reg & MXC_CCM_CBCDR_AHB_PODF_MASK) >>
459 MXC_CCM_CBCDR_AHB_PODF_OFFSET) + 1;
460 return parent_rate / div;
461}
462
463
464static int _clk_ahb_set_rate(struct clk *clk, unsigned long rate)
465{
466 u32 reg, div;
467 unsigned long parent_rate;
468 int i = 0;
469
470 parent_rate = clk_get_rate(clk->parent);
471
472 div = parent_rate / rate;
473 if (div > 8 || div < 1 || ((parent_rate / div) != rate))
474 return -EINVAL;
475
476 reg = __raw_readl(MXC_CCM_CBCDR);
477 reg &= ~MXC_CCM_CBCDR_AHB_PODF_MASK;
478 reg |= (div - 1) << MXC_CCM_CBCDR_AHB_PODF_OFFSET;
479 __raw_writel(reg, MXC_CCM_CBCDR);
480
481 /* Wait for lock */
482 do {
483 reg = __raw_readl(MXC_CCM_CDHIPR);
484 if (!(reg & MXC_CCM_CDHIPR_AHB_PODF_BUSY))
485 break;
486
487 udelay(1);
488 } while (++i < MAX_DPLL_WAIT_TRIES);
489
490 if (i == MAX_DPLL_WAIT_TRIES) {
491 pr_err("MX5: clk_ahb_set_rate failed\n");
492 return -EINVAL;
493 }
494
495 return 0;
496}
497
498static unsigned long _clk_ahb_round_rate(struct clk *clk,
499 unsigned long rate)
500{
501 u32 div;
502 unsigned long parent_rate;
503
504 parent_rate = clk_get_rate(clk->parent);
505
506 div = parent_rate / rate;
507 if (div > 8)
508 div = 8;
509 else if (div == 0)
510 div++;
511 return parent_rate / div;
512}
513
514
515static int _clk_max_enable(struct clk *clk)
516{
517 u32 reg;
518
519 _clk_ccgr_enable(clk);
520
521 /* Handshake with MAX when LPM is entered. */
522 reg = __raw_readl(MXC_CCM_CLPCR);
Dinh Nguyenc0abefd2010-11-15 11:29:59 -0600523 if (cpu_is_mx51())
524 reg &= ~MX51_CCM_CLPCR_BYPASS_MAX_LPM_HS;
525 else if (cpu_is_mx53())
526 reg &= ~MX53_CCM_CLPCR_BYPASS_MAX_LPM_HS;
Amit Kucheriaa329b482010-02-04 12:21:53 -0800527 __raw_writel(reg, MXC_CCM_CLPCR);
528
529 return 0;
530}
531
532static void _clk_max_disable(struct clk *clk)
533{
534 u32 reg;
535
536 _clk_ccgr_disable_inwait(clk);
537
538 /* No Handshake with MAX when LPM is entered as its disabled. */
539 reg = __raw_readl(MXC_CCM_CLPCR);
Dinh Nguyenc0abefd2010-11-15 11:29:59 -0600540 if (cpu_is_mx51())
541 reg |= MX51_CCM_CLPCR_BYPASS_MAX_LPM_HS;
542 else if (cpu_is_mx53())
543 reg &= ~MX53_CCM_CLPCR_BYPASS_MAX_LPM_HS;
Amit Kucheriaa329b482010-02-04 12:21:53 -0800544 __raw_writel(reg, MXC_CCM_CLPCR);
545}
546
547static unsigned long clk_ipg_get_rate(struct clk *clk)
548{
549 u32 reg, div;
550 unsigned long parent_rate;
551
552 parent_rate = clk_get_rate(clk->parent);
553
554 reg = __raw_readl(MXC_CCM_CBCDR);
555 div = ((reg & MXC_CCM_CBCDR_IPG_PODF_MASK) >>
556 MXC_CCM_CBCDR_IPG_PODF_OFFSET) + 1;
557
558 return parent_rate / div;
559}
560
561static unsigned long clk_ipg_per_get_rate(struct clk *clk)
562{
563 u32 reg, prediv1, prediv2, podf;
564 unsigned long parent_rate;
565
566 parent_rate = clk_get_rate(clk->parent);
567
568 if (clk->parent == &main_bus_clk || clk->parent == &lp_apm_clk) {
569 /* the main_bus_clk is the one before the DVFS engine */
570 reg = __raw_readl(MXC_CCM_CBCDR);
571 prediv1 = ((reg & MXC_CCM_CBCDR_PERCLK_PRED1_MASK) >>
572 MXC_CCM_CBCDR_PERCLK_PRED1_OFFSET) + 1;
573 prediv2 = ((reg & MXC_CCM_CBCDR_PERCLK_PRED2_MASK) >>
574 MXC_CCM_CBCDR_PERCLK_PRED2_OFFSET) + 1;
575 podf = ((reg & MXC_CCM_CBCDR_PERCLK_PODF_MASK) >>
576 MXC_CCM_CBCDR_PERCLK_PODF_OFFSET) + 1;
577 return parent_rate / (prediv1 * prediv2 * podf);
578 } else if (clk->parent == &ipg_clk)
579 return parent_rate;
580 else
581 BUG();
582}
583
584static int _clk_ipg_per_set_parent(struct clk *clk, struct clk *parent)
585{
586 u32 reg;
587
588 reg = __raw_readl(MXC_CCM_CBCMR);
589
590 reg &= ~MXC_CCM_CBCMR_PERCLK_LP_APM_CLK_SEL;
591 reg &= ~MXC_CCM_CBCMR_PERCLK_IPG_CLK_SEL;
592
593 if (parent == &ipg_clk)
594 reg |= MXC_CCM_CBCMR_PERCLK_IPG_CLK_SEL;
595 else if (parent == &lp_apm_clk)
596 reg |= MXC_CCM_CBCMR_PERCLK_LP_APM_CLK_SEL;
597 else if (parent != &main_bus_clk)
598 return -EINVAL;
599
600 __raw_writel(reg, MXC_CCM_CBCMR);
601
602 return 0;
603}
604
Sascha Hauer2b82e642010-08-03 11:59:07 +0200605#define clk_nfc_set_parent NULL
606
607static unsigned long clk_nfc_get_rate(struct clk *clk)
608{
609 unsigned long rate;
610 u32 reg, div;
611
612 reg = __raw_readl(MXC_CCM_CBCDR);
613 div = ((reg & MXC_CCM_CBCDR_NFC_PODF_MASK) >>
614 MXC_CCM_CBCDR_NFC_PODF_OFFSET) + 1;
615 rate = clk_get_rate(clk->parent) / div;
616 WARN_ON(rate == 0);
617 return rate;
618}
619
620static unsigned long clk_nfc_round_rate(struct clk *clk,
621 unsigned long rate)
622{
623 u32 div;
624 unsigned long parent_rate = clk_get_rate(clk->parent);
625
626 if (!rate)
627 return -EINVAL;
628
629 div = parent_rate / rate;
630
631 if (parent_rate % rate)
632 div++;
633
634 if (div > 8)
635 return -EINVAL;
636
637 return parent_rate / div;
638
639}
640
641static int clk_nfc_set_rate(struct clk *clk, unsigned long rate)
642{
643 u32 reg, div;
644
645 div = clk_get_rate(clk->parent) / rate;
646 if (div == 0)
647 div++;
648 if (((clk_get_rate(clk->parent) / div) != rate) || (div > 8))
649 return -EINVAL;
650
651 reg = __raw_readl(MXC_CCM_CBCDR);
652 reg &= ~MXC_CCM_CBCDR_NFC_PODF_MASK;
653 reg |= (div - 1) << MXC_CCM_CBCDR_NFC_PODF_OFFSET;
654 __raw_writel(reg, MXC_CCM_CBCDR);
655
656 while (__raw_readl(MXC_CCM_CDHIPR) &
657 MXC_CCM_CDHIPR_NFC_IPG_INT_MEM_PODF_BUSY){
658 }
659
660 return 0;
661}
662
Amit Kucheriaa329b482010-02-04 12:21:53 -0800663static unsigned long get_high_reference_clock_rate(struct clk *clk)
664{
665 return external_high_reference;
666}
667
668static unsigned long get_low_reference_clock_rate(struct clk *clk)
669{
670 return external_low_reference;
671}
672
673static unsigned long get_oscillator_reference_clock_rate(struct clk *clk)
674{
675 return oscillator_reference;
676}
677
678static unsigned long get_ckih2_reference_clock_rate(struct clk *clk)
679{
680 return ckih2_reference;
681}
682
Sascha Hauer2b82e642010-08-03 11:59:07 +0200683static unsigned long clk_emi_slow_get_rate(struct clk *clk)
684{
685 u32 reg, div;
686
687 reg = __raw_readl(MXC_CCM_CBCDR);
688 div = ((reg & MXC_CCM_CBCDR_EMI_PODF_MASK) >>
689 MXC_CCM_CBCDR_EMI_PODF_OFFSET) + 1;
690
691 return clk_get_rate(clk->parent) / div;
692}
693
Sascha Hauerb8481692010-12-06 09:13:21 +0100694static unsigned long _clk_ddr_hf_get_rate(struct clk *clk)
695{
696 unsigned long rate;
697 u32 reg, div;
698
699 reg = __raw_readl(MXC_CCM_CBCDR);
700 div = ((reg & MXC_CCM_CBCDR_DDR_PODF_MASK) >>
701 MXC_CCM_CBCDR_DDR_PODF_OFFSET) + 1;
702 rate = clk_get_rate(clk->parent) / div;
703
704 return rate;
705}
706
Amit Kucheriaa329b482010-02-04 12:21:53 -0800707/* External high frequency clock */
708static struct clk ckih_clk = {
709 .get_rate = get_high_reference_clock_rate,
710};
711
712static struct clk ckih2_clk = {
713 .get_rate = get_ckih2_reference_clock_rate,
714};
715
716static struct clk osc_clk = {
717 .get_rate = get_oscillator_reference_clock_rate,
718};
719
720/* External low frequency (32kHz) clock */
721static struct clk ckil_clk = {
722 .get_rate = get_low_reference_clock_rate,
723};
724
725static struct clk pll1_main_clk = {
726 .parent = &osc_clk,
727 .get_rate = clk_pll_get_rate,
728 .enable = _clk_pll_enable,
729 .disable = _clk_pll_disable,
730};
731
732/* Clock tree block diagram (WIP):
733 * CCM: Clock Controller Module
734 *
735 * PLL output -> |
736 * | CCM Switcher -> CCM_CLK_ROOT_GEN ->
737 * PLL bypass -> |
738 *
739 */
740
741/* PLL1 SW supplies to ARM core */
742static struct clk pll1_sw_clk = {
743 .parent = &pll1_main_clk,
744 .set_parent = _clk_pll1_sw_set_parent,
745 .get_rate = clk_pll1_sw_get_rate,
746};
747
748/* PLL2 SW supplies to AXI/AHB/IP buses */
749static struct clk pll2_sw_clk = {
750 .parent = &osc_clk,
751 .get_rate = clk_pll_get_rate,
752 .set_rate = _clk_pll_set_rate,
753 .set_parent = _clk_pll2_sw_set_parent,
754 .enable = _clk_pll_enable,
755 .disable = _clk_pll_disable,
756};
757
758/* PLL3 SW supplies to serial clocks like USB, SSI, etc. */
759static struct clk pll3_sw_clk = {
760 .parent = &osc_clk,
761 .set_rate = _clk_pll_set_rate,
762 .get_rate = clk_pll_get_rate,
763 .enable = _clk_pll_enable,
764 .disable = _clk_pll_disable,
765};
766
Dinh Nguyenc0abefd2010-11-15 11:29:59 -0600767/* PLL4 SW supplies to LVDS Display Bridge(LDB) */
768static struct clk mx53_pll4_sw_clk = {
769 .parent = &osc_clk,
770 .set_rate = _clk_pll_set_rate,
771 .enable = _clk_pll_enable,
772 .disable = _clk_pll_disable,
773};
774
Amit Kucheriaa329b482010-02-04 12:21:53 -0800775/* Low-power Audio Playback Mode clock */
776static struct clk lp_apm_clk = {
777 .parent = &osc_clk,
778 .set_parent = _clk_lp_apm_set_parent,
779};
780
781static struct clk periph_apm_clk = {
782 .parent = &pll1_sw_clk,
783 .set_parent = _clk_periph_apm_set_parent,
784};
785
786static struct clk cpu_clk = {
787 .parent = &pll1_sw_clk,
Yong Shen64f102b2010-10-21 21:18:59 +0800788 .get_rate = clk_cpu_get_rate,
789 .set_rate = clk_cpu_set_rate,
Amit Kucheriaa329b482010-02-04 12:21:53 -0800790};
791
792static struct clk ahb_clk = {
793 .parent = &main_bus_clk,
794 .get_rate = clk_ahb_get_rate,
795 .set_rate = _clk_ahb_set_rate,
796 .round_rate = _clk_ahb_round_rate,
797};
798
Dinh Nguyen9ab46502010-11-15 11:30:01 -0600799static struct clk iim_clk = {
800 .parent = &ipg_clk,
801 .enable_reg = MXC_CCM_CCGR0,
802 .enable_shift = MXC_CCM_CCGRx_CG15_OFFSET,
803};
804
Amit Kucheriaa329b482010-02-04 12:21:53 -0800805/* Main IP interface clock for access to registers */
806static struct clk ipg_clk = {
807 .parent = &ahb_clk,
808 .get_rate = clk_ipg_get_rate,
809};
810
811static struct clk ipg_perclk = {
812 .parent = &lp_apm_clk,
813 .get_rate = clk_ipg_per_get_rate,
814 .set_parent = _clk_ipg_per_set_parent,
815};
816
Amit Kucheriaa329b482010-02-04 12:21:53 -0800817static struct clk ahb_max_clk = {
818 .parent = &ahb_clk,
819 .enable_reg = MXC_CCM_CCGR0,
820 .enable_shift = MXC_CCM_CCGRx_CG14_OFFSET,
821 .enable = _clk_max_enable,
822 .disable = _clk_max_disable,
823};
824
825static struct clk aips_tz1_clk = {
826 .parent = &ahb_clk,
827 .secondary = &ahb_max_clk,
828 .enable_reg = MXC_CCM_CCGR0,
829 .enable_shift = MXC_CCM_CCGRx_CG12_OFFSET,
830 .enable = _clk_ccgr_enable,
831 .disable = _clk_ccgr_disable_inwait,
832};
833
834static struct clk aips_tz2_clk = {
835 .parent = &ahb_clk,
836 .secondary = &ahb_max_clk,
837 .enable_reg = MXC_CCM_CCGR0,
838 .enable_shift = MXC_CCM_CCGRx_CG13_OFFSET,
839 .enable = _clk_ccgr_enable,
840 .disable = _clk_ccgr_disable_inwait,
841};
842
843static struct clk gpt_32k_clk = {
844 .id = 0,
845 .parent = &ckil_clk,
846};
847
Jason Wanga7ebd932010-07-14 21:24:53 +0800848static struct clk kpp_clk = {
849 .id = 0,
850};
851
Fabio Estevam7f77f912010-12-06 16:38:33 -0200852static struct clk dummy_clk = {
853 .id = 0,
854};
855
Sascha Hauer2b82e642010-08-03 11:59:07 +0200856static struct clk emi_slow_clk = {
857 .parent = &pll2_sw_clk,
858 .enable_reg = MXC_CCM_CCGR5,
859 .enable_shift = MXC_CCM_CCGRx_CG8_OFFSET,
860 .enable = _clk_ccgr_enable,
861 .disable = _clk_ccgr_disable_inwait,
862 .get_rate = clk_emi_slow_get_rate,
863};
864
Sascha Hauerb8481692010-12-06 09:13:21 +0100865static int clk_ipu_enable(struct clk *clk)
866{
867 u32 reg;
868
869 _clk_ccgr_enable(clk);
870
871 /* Enable handshake with IPU when certain clock rates are changed */
872 reg = __raw_readl(MXC_CCM_CCDR);
873 reg &= ~MXC_CCM_CCDR_IPU_HS_MASK;
874 __raw_writel(reg, MXC_CCM_CCDR);
875
876 /* Enable handshake with IPU when LPM is entered */
877 reg = __raw_readl(MXC_CCM_CLPCR);
878 reg &= ~MXC_CCM_CLPCR_BYPASS_IPU_LPM_HS;
879 __raw_writel(reg, MXC_CCM_CLPCR);
880
881 return 0;
882}
883
884static void clk_ipu_disable(struct clk *clk)
885{
886 u32 reg;
887
888 _clk_ccgr_disable(clk);
889
890 /* Disable handshake with IPU whe dividers are changed */
891 reg = __raw_readl(MXC_CCM_CCDR);
892 reg |= MXC_CCM_CCDR_IPU_HS_MASK;
893 __raw_writel(reg, MXC_CCM_CCDR);
894
895 /* Disable handshake with IPU when LPM is entered */
896 reg = __raw_readl(MXC_CCM_CLPCR);
897 reg |= MXC_CCM_CLPCR_BYPASS_IPU_LPM_HS;
898 __raw_writel(reg, MXC_CCM_CLPCR);
899}
900
901static struct clk ahbmux1_clk = {
902 .parent = &ahb_clk,
903 .secondary = &ahb_max_clk,
904 .enable_reg = MXC_CCM_CCGR0,
905 .enable_shift = MXC_CCM_CCGRx_CG8_OFFSET,
906 .enable = _clk_ccgr_enable,
907 .disable = _clk_ccgr_disable_inwait,
908};
909
910static struct clk ipu_sec_clk = {
911 .parent = &emi_fast_clk,
912 .secondary = &ahbmux1_clk,
913};
914
915static struct clk ddr_hf_clk = {
916 .parent = &pll1_sw_clk,
917 .get_rate = _clk_ddr_hf_get_rate,
918};
919
920static struct clk ddr_clk = {
921 .parent = &ddr_hf_clk,
922};
923
924/* clock definitions for MIPI HSC unit which has been removed
925 * from documentation, but not from hardware
926 */
927static int _clk_hsc_enable(struct clk *clk)
928{
929 u32 reg;
930
931 _clk_ccgr_enable(clk);
932 /* Handshake with IPU when certain clock rates are changed. */
933 reg = __raw_readl(MXC_CCM_CCDR);
934 reg &= ~MXC_CCM_CCDR_HSC_HS_MASK;
935 __raw_writel(reg, MXC_CCM_CCDR);
936
937 reg = __raw_readl(MXC_CCM_CLPCR);
938 reg &= ~MXC_CCM_CLPCR_BYPASS_HSC_LPM_HS;
939 __raw_writel(reg, MXC_CCM_CLPCR);
940
941 return 0;
942}
943
944static void _clk_hsc_disable(struct clk *clk)
945{
946 u32 reg;
947
948 _clk_ccgr_disable(clk);
949 /* No handshake with HSC as its not enabled. */
950 reg = __raw_readl(MXC_CCM_CCDR);
951 reg |= MXC_CCM_CCDR_HSC_HS_MASK;
952 __raw_writel(reg, MXC_CCM_CCDR);
953
954 reg = __raw_readl(MXC_CCM_CLPCR);
955 reg |= MXC_CCM_CLPCR_BYPASS_HSC_LPM_HS;
956 __raw_writel(reg, MXC_CCM_CLPCR);
957}
958
959static struct clk mipi_hsp_clk = {
960 .parent = &ipu_clk,
961 .enable_reg = MXC_CCM_CCGR4,
962 .enable_shift = MXC_CCM_CCGRx_CG6_OFFSET,
963 .enable = _clk_hsc_enable,
964 .disable = _clk_hsc_disable,
965 .secondary = &mipi_hsc1_clk,
966};
967
Eric Bénard7e5a7472010-10-12 12:26:32 +0200968#define DEFINE_CLOCK_CCGR(name, i, er, es, pfx, p, s) \
Sascha Hauer2b82e642010-08-03 11:59:07 +0200969 static struct clk name = { \
970 .id = i, \
971 .enable_reg = er, \
972 .enable_shift = es, \
973 .get_rate = pfx##_get_rate, \
974 .set_rate = pfx##_set_rate, \
975 .round_rate = pfx##_round_rate, \
976 .set_parent = pfx##_set_parent, \
977 .enable = _clk_ccgr_enable, \
978 .disable = _clk_ccgr_disable, \
979 .parent = p, \
980 .secondary = s, \
981 }
982
Eric Bénard6a001b82010-10-11 17:59:47 +0200983#define DEFINE_CLOCK_MAX(name, i, er, es, pfx, p, s) \
984 static struct clk name = { \
985 .id = i, \
986 .enable_reg = er, \
987 .enable_shift = es, \
988 .get_rate = pfx##_get_rate, \
989 .set_rate = pfx##_set_rate, \
990 .set_parent = pfx##_set_parent, \
991 .enable = _clk_max_enable, \
992 .disable = _clk_max_disable, \
993 .parent = p, \
994 .secondary = s, \
995 }
996
Eric Bénard00762322010-10-11 21:55:24 +0200997#define CLK_GET_RATE(name, nr, bitsname) \
998static unsigned long clk_##name##_get_rate(struct clk *clk) \
999{ \
1000 u32 reg, pred, podf; \
1001 \
1002 reg = __raw_readl(MXC_CCM_CSCDR##nr); \
1003 pred = (reg & MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_MASK) \
1004 >> MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_OFFSET; \
1005 podf = (reg & MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_MASK) \
1006 >> MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_OFFSET; \
1007 \
1008 return DIV_ROUND_CLOSEST(clk_get_rate(clk->parent), \
1009 (pred + 1) * (podf + 1)); \
1010}
1011
1012#define CLK_SET_PARENT(name, nr, bitsname) \
1013static int clk_##name##_set_parent(struct clk *clk, struct clk *parent) \
1014{ \
1015 u32 reg, mux; \
1016 \
1017 mux = _get_mux(parent, &pll1_sw_clk, &pll2_sw_clk, \
1018 &pll3_sw_clk, &lp_apm_clk); \
1019 reg = __raw_readl(MXC_CCM_CSCMR##nr) & \
1020 ~MXC_CCM_CSCMR##nr##_##bitsname##_CLK_SEL_MASK; \
1021 reg |= mux << MXC_CCM_CSCMR##nr##_##bitsname##_CLK_SEL_OFFSET; \
1022 __raw_writel(reg, MXC_CCM_CSCMR##nr); \
1023 \
1024 return 0; \
1025}
1026
Eric Bénard6a001b82010-10-11 17:59:47 +02001027#define CLK_SET_RATE(name, nr, bitsname) \
1028static int clk_##name##_set_rate(struct clk *clk, unsigned long rate) \
1029{ \
1030 u32 reg, div, parent_rate; \
1031 u32 pre = 0, post = 0; \
1032 \
1033 parent_rate = clk_get_rate(clk->parent); \
1034 div = parent_rate / rate; \
1035 \
1036 if ((parent_rate / div) != rate) \
1037 return -EINVAL; \
1038 \
1039 __calc_pre_post_dividers(div, &pre, &post, \
1040 (MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_MASK >> \
1041 MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_OFFSET) + 1, \
1042 (MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_MASK >> \
1043 MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_OFFSET) + 1);\
1044 \
1045 /* Set sdhc1 clock divider */ \
1046 reg = __raw_readl(MXC_CCM_CSCDR##nr) & \
1047 ~(MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_MASK \
1048 | MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_MASK); \
1049 reg |= (post - 1) << \
1050 MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_OFFSET; \
1051 reg |= (pre - 1) << \
1052 MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_OFFSET; \
1053 __raw_writel(reg, MXC_CCM_CSCDR##nr); \
1054 \
1055 return 0; \
1056}
1057
Eric Bénard00762322010-10-11 21:55:24 +02001058/* UART */
1059CLK_GET_RATE(uart, 1, UART)
1060CLK_SET_PARENT(uart, 1, UART)
1061
1062static struct clk uart_root_clk = {
1063 .parent = &pll2_sw_clk,
1064 .get_rate = clk_uart_get_rate,
1065 .set_parent = clk_uart_set_parent,
1066};
1067
1068/* USBOH3 */
1069CLK_GET_RATE(usboh3, 1, USBOH3)
1070CLK_SET_PARENT(usboh3, 1, USBOH3)
1071
1072static struct clk usboh3_clk = {
1073 .parent = &pll2_sw_clk,
1074 .get_rate = clk_usboh3_get_rate,
1075 .set_parent = clk_usboh3_set_parent,
Arnaud Patard (Rtp)711669e2010-12-20 16:48:58 +01001076 .enable = _clk_ccgr_enable,
1077 .disable = _clk_ccgr_disable,
1078 .enable_reg = MXC_CCM_CCGR2,
1079 .enable_shift = MXC_CCM_CCGRx_CG14_OFFSET,
1080};
1081
1082static struct clk usb_ahb_clk = {
1083 .parent = &ipg_clk,
1084 .enable = _clk_ccgr_enable,
1085 .disable = _clk_ccgr_disable,
1086 .enable_reg = MXC_CCM_CCGR2,
1087 .enable_shift = MXC_CCM_CCGRx_CG13_OFFSET,
1088};
1089
1090static int clk_usb_phy1_set_parent(struct clk *clk, struct clk *parent)
1091{
1092 u32 reg;
1093
1094 reg = __raw_readl(MXC_CCM_CSCMR1) & ~MXC_CCM_CSCMR1_USB_PHY_CLK_SEL;
1095
1096 if (parent == &pll3_sw_clk)
1097 reg |= 1 << MXC_CCM_CSCMR1_USB_PHY_CLK_SEL_OFFSET;
1098
1099 __raw_writel(reg, MXC_CCM_CSCMR1);
1100
1101 return 0;
1102}
1103
1104static struct clk usb_phy1_clk = {
1105 .parent = &pll3_sw_clk,
1106 .set_parent = clk_usb_phy1_set_parent,
1107 .enable = _clk_ccgr_enable,
1108 .enable_reg = MXC_CCM_CCGR2,
1109 .enable_shift = MXC_CCM_CCGRx_CG0_OFFSET,
1110 .disable = _clk_ccgr_disable,
Eric Bénard00762322010-10-11 21:55:24 +02001111};
1112
Jason Wang8d83db82010-09-02 15:52:00 +08001113/* eCSPI */
Eric Bénard00762322010-10-11 21:55:24 +02001114CLK_GET_RATE(ecspi, 2, CSPI)
1115CLK_SET_PARENT(ecspi, 1, CSPI)
Jason Wang8d83db82010-09-02 15:52:00 +08001116
1117static struct clk ecspi_main_clk = {
1118 .parent = &pll3_sw_clk,
1119 .get_rate = clk_ecspi_get_rate,
1120 .set_parent = clk_ecspi_set_parent,
1121};
1122
Eric Bénard6a001b82010-10-11 17:59:47 +02001123/* eSDHC */
1124CLK_GET_RATE(esdhc1, 1, ESDHC1_MSHC1)
1125CLK_SET_PARENT(esdhc1, 1, ESDHC1_MSHC1)
1126CLK_SET_RATE(esdhc1, 1, ESDHC1_MSHC1)
1127
1128CLK_GET_RATE(esdhc2, 1, ESDHC2_MSHC2)
1129CLK_SET_PARENT(esdhc2, 1, ESDHC2_MSHC2)
1130CLK_SET_RATE(esdhc2, 1, ESDHC2_MSHC2)
1131
Uwe Kleine-König74d99f32010-09-10 17:01:26 +02001132#define DEFINE_CLOCK_FULL(name, i, er, es, gr, sr, e, d, p, s) \
1133 static struct clk name = { \
1134 .id = i, \
1135 .enable_reg = er, \
1136 .enable_shift = es, \
1137 .get_rate = gr, \
1138 .set_rate = sr, \
1139 .enable = e, \
1140 .disable = d, \
1141 .parent = p, \
1142 .secondary = s, \
Amit Kucheriaa329b482010-02-04 12:21:53 -08001143 }
1144
Uwe Kleine-König74d99f32010-09-10 17:01:26 +02001145#define DEFINE_CLOCK(name, i, er, es, gr, sr, p, s) \
1146 DEFINE_CLOCK_FULL(name, i, er, es, gr, sr, _clk_ccgr_enable, _clk_ccgr_disable, p, s)
Amit Kucheriaa329b482010-02-04 12:21:53 -08001147
1148/* Shared peripheral bus arbiter */
1149DEFINE_CLOCK(spba_clk, 0, MXC_CCM_CCGR5, MXC_CCM_CCGRx_CG0_OFFSET,
1150 NULL, NULL, &ipg_clk, NULL);
1151
1152/* UART */
Amit Kucheriaa329b482010-02-04 12:21:53 -08001153DEFINE_CLOCK(uart1_ipg_clk, 0, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG3_OFFSET,
1154 NULL, NULL, &ipg_clk, &aips_tz1_clk);
1155DEFINE_CLOCK(uart2_ipg_clk, 1, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG5_OFFSET,
1156 NULL, NULL, &ipg_clk, &aips_tz1_clk);
1157DEFINE_CLOCK(uart3_ipg_clk, 2, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG7_OFFSET,
1158 NULL, NULL, &ipg_clk, &spba_clk);
Sascha Hauer8f6e9002010-08-25 11:56:26 +02001159DEFINE_CLOCK(uart1_clk, 0, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG4_OFFSET,
1160 NULL, NULL, &uart_root_clk, &uart1_ipg_clk);
1161DEFINE_CLOCK(uart2_clk, 1, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG6_OFFSET,
1162 NULL, NULL, &uart_root_clk, &uart2_ipg_clk);
1163DEFINE_CLOCK(uart3_clk, 2, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG8_OFFSET,
1164 NULL, NULL, &uart_root_clk, &uart3_ipg_clk);
Amit Kucheriaa329b482010-02-04 12:21:53 -08001165
1166/* GPT */
Amit Kucheriaa329b482010-02-04 12:21:53 -08001167DEFINE_CLOCK(gpt_ipg_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG10_OFFSET,
1168 NULL, NULL, &ipg_clk, NULL);
Sascha Hauer8f6e9002010-08-25 11:56:26 +02001169DEFINE_CLOCK(gpt_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG9_OFFSET,
1170 NULL, NULL, &ipg_clk, &gpt_ipg_clk);
Amit Kucheriaa329b482010-02-04 12:21:53 -08001171
Dinh Nguyen71c2e512010-05-27 10:45:04 -05001172/* I2C */
1173DEFINE_CLOCK(i2c1_clk, 0, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG9_OFFSET,
1174 NULL, NULL, &ipg_clk, NULL);
1175DEFINE_CLOCK(i2c2_clk, 1, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG10_OFFSET,
1176 NULL, NULL, &ipg_clk, NULL);
1177DEFINE_CLOCK(hsi2c_clk, 0, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG11_OFFSET,
1178 NULL, NULL, &ipg_clk, NULL);
1179
Amit Kucheriaa329b482010-02-04 12:21:53 -08001180/* FEC */
1181DEFINE_CLOCK(fec_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG12_OFFSET,
1182 NULL, NULL, &ipg_clk, NULL);
1183
Sascha Hauer2b82e642010-08-03 11:59:07 +02001184/* NFC */
Eric Bénard7e5a7472010-10-12 12:26:32 +02001185DEFINE_CLOCK_CCGR(nfc_clk, 0, MXC_CCM_CCGR5, MXC_CCM_CCGRx_CG10_OFFSET,
Sascha Hauer2b82e642010-08-03 11:59:07 +02001186 clk_nfc, &emi_slow_clk, NULL);
1187
Sascha Hauerb8618662010-08-20 16:43:54 +02001188/* SSI */
1189DEFINE_CLOCK(ssi1_ipg_clk, 0, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG8_OFFSET,
1190 NULL, NULL, &ipg_clk, NULL);
1191DEFINE_CLOCK(ssi1_clk, 0, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG9_OFFSET,
1192 NULL, NULL, &pll3_sw_clk, &ssi1_ipg_clk);
1193DEFINE_CLOCK(ssi2_ipg_clk, 1, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG10_OFFSET,
1194 NULL, NULL, &ipg_clk, NULL);
1195DEFINE_CLOCK(ssi2_clk, 1, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG11_OFFSET,
1196 NULL, NULL, &pll3_sw_clk, &ssi2_ipg_clk);
Peter Hortonf2597222010-12-03 17:07:28 +00001197DEFINE_CLOCK(ssi3_ipg_clk, 2, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG12_OFFSET,
1198 NULL, NULL, &ipg_clk, NULL);
1199DEFINE_CLOCK(ssi3_clk, 2, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG13_OFFSET,
1200 NULL, NULL, &pll3_sw_clk, &ssi3_ipg_clk);
Sascha Hauerb8618662010-08-20 16:43:54 +02001201
Jason Wang8d83db82010-09-02 15:52:00 +08001202/* eCSPI */
1203DEFINE_CLOCK_FULL(ecspi1_ipg_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG9_OFFSET,
1204 NULL, NULL, _clk_ccgr_enable_inrun, _clk_ccgr_disable,
1205 &ipg_clk, &spba_clk);
1206DEFINE_CLOCK(ecspi1_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG10_OFFSET,
1207 NULL, NULL, &ecspi_main_clk, &ecspi1_ipg_clk);
1208DEFINE_CLOCK_FULL(ecspi2_ipg_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG11_OFFSET,
1209 NULL, NULL, _clk_ccgr_enable_inrun, _clk_ccgr_disable,
1210 &ipg_clk, &aips_tz2_clk);
1211DEFINE_CLOCK(ecspi2_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG12_OFFSET,
1212 NULL, NULL, &ecspi_main_clk, &ecspi2_ipg_clk);
1213
1214/* CSPI */
1215DEFINE_CLOCK(cspi_ipg_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG9_OFFSET,
1216 NULL, NULL, &ipg_clk, &aips_tz2_clk);
1217DEFINE_CLOCK(cspi_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG13_OFFSET,
1218 NULL, NULL, &ipg_clk, &cspi_ipg_clk);
1219
Uwe Kleine-König8a8d2062010-10-08 16:00:11 +02001220/* SDMA */
1221DEFINE_CLOCK(sdma_clk, 1, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG15_OFFSET,
1222 NULL, NULL, &ahb_clk, NULL);
1223
Eric Bénard6a001b82010-10-11 17:59:47 +02001224/* eSDHC */
1225DEFINE_CLOCK_FULL(esdhc1_ipg_clk, 0, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG0_OFFSET,
1226 NULL, NULL, _clk_max_enable, _clk_max_disable, &ipg_clk, NULL);
1227DEFINE_CLOCK_MAX(esdhc1_clk, 0, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG1_OFFSET,
1228 clk_esdhc1, &pll2_sw_clk, &esdhc1_ipg_clk);
1229DEFINE_CLOCK_FULL(esdhc2_ipg_clk, 1, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG2_OFFSET,
1230 NULL, NULL, _clk_max_enable, _clk_max_disable, &ipg_clk, NULL);
1231DEFINE_CLOCK_MAX(esdhc2_clk, 1, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG3_OFFSET,
1232 clk_esdhc2, &pll2_sw_clk, &esdhc2_ipg_clk);
1233
Sascha Hauerb8481692010-12-06 09:13:21 +01001234DEFINE_CLOCK(mipi_esc_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG5_OFFSET, NULL, NULL, NULL, &pll2_sw_clk);
1235DEFINE_CLOCK(mipi_hsc2_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG4_OFFSET, NULL, NULL, &mipi_esc_clk, &pll2_sw_clk);
1236DEFINE_CLOCK(mipi_hsc1_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG3_OFFSET, NULL, NULL, &mipi_hsc2_clk, &pll2_sw_clk);
1237
1238/* IPU */
1239DEFINE_CLOCK_FULL(ipu_clk, 0, MXC_CCM_CCGR5, MXC_CCM_CCGRx_CG5_OFFSET,
1240 NULL, NULL, clk_ipu_enable, clk_ipu_disable, &ahb_clk, &ipu_sec_clk);
1241
1242DEFINE_CLOCK_FULL(emi_fast_clk, 0, MXC_CCM_CCGR5, MXC_CCM_CCGRx_CG7_OFFSET,
1243 NULL, NULL, _clk_ccgr_enable, _clk_ccgr_disable_inwait,
1244 &ddr_clk, NULL);
1245
1246DEFINE_CLOCK(ipu_di0_clk, 0, MXC_CCM_CCGR6, MXC_CCM_CCGRx_CG5_OFFSET,
1247 NULL, NULL, &pll3_sw_clk, NULL);
1248DEFINE_CLOCK(ipu_di1_clk, 0, MXC_CCM_CCGR6, MXC_CCM_CCGRx_CG6_OFFSET,
1249 NULL, NULL, &pll3_sw_clk, NULL);
1250
Amit Kucheriaa329b482010-02-04 12:21:53 -08001251#define _REGISTER_CLOCK(d, n, c) \
1252 { \
1253 .dev_id = d, \
1254 .con_id = n, \
1255 .clk = &c, \
1256 },
1257
Dinh Nguyenc0abefd2010-11-15 11:29:59 -06001258static struct clk_lookup mx51_lookups[] = {
Amit Kucheriaa329b482010-02-04 12:21:53 -08001259 _REGISTER_CLOCK("imx-uart.0", NULL, uart1_clk)
1260 _REGISTER_CLOCK("imx-uart.1", NULL, uart2_clk)
1261 _REGISTER_CLOCK("imx-uart.2", NULL, uart3_clk)
1262 _REGISTER_CLOCK(NULL, "gpt", gpt_clk)
1263 _REGISTER_CLOCK("fec.0", NULL, fec_clk)
Dinh Nguyen71c2e512010-05-27 10:45:04 -05001264 _REGISTER_CLOCK("imx-i2c.0", NULL, i2c1_clk)
1265 _REGISTER_CLOCK("imx-i2c.1", NULL, i2c2_clk)
1266 _REGISTER_CLOCK("imx-i2c.2", NULL, hsi2c_clk)
Dinh Nguyenc53bdf12010-04-30 15:48:24 -05001267 _REGISTER_CLOCK("mxc-ehci.0", "usb", usboh3_clk)
Arnaud Patard (Rtp)711669e2010-12-20 16:48:58 +01001268 _REGISTER_CLOCK("mxc-ehci.0", "usb_ahb", usb_ahb_clk)
1269 _REGISTER_CLOCK("mxc-ehci.0", "usb_phy1", usb_phy1_clk)
Dinh Nguyenc53bdf12010-04-30 15:48:24 -05001270 _REGISTER_CLOCK("mxc-ehci.1", "usb", usboh3_clk)
Arnaud Patard (Rtp)711669e2010-12-20 16:48:58 +01001271 _REGISTER_CLOCK("mxc-ehci.1", "usb_ahb", usb_ahb_clk)
1272 _REGISTER_CLOCK("mxc-ehci.2", "usb", usboh3_clk)
1273 _REGISTER_CLOCK("mxc-ehci.2", "usb_ahb", usb_ahb_clk)
Dinh Nguyen2ba5a2c2010-05-10 13:45:59 -05001274 _REGISTER_CLOCK("fsl-usb2-udc", "usb", usboh3_clk)
1275 _REGISTER_CLOCK("fsl-usb2-udc", "usb_ahb", ahb_clk)
Jason Wanga7ebd932010-07-14 21:24:53 +08001276 _REGISTER_CLOCK("imx-keypad.0", NULL, kpp_clk)
Sascha Hauer2b82e642010-08-03 11:59:07 +02001277 _REGISTER_CLOCK("mxc_nand", NULL, nfc_clk)
Sascha Hauerb8618662010-08-20 16:43:54 +02001278 _REGISTER_CLOCK("imx-ssi.0", NULL, ssi1_clk)
1279 _REGISTER_CLOCK("imx-ssi.1", NULL, ssi2_clk)
Peter Hortonf2597222010-12-03 17:07:28 +00001280 _REGISTER_CLOCK("imx-ssi.2", NULL, ssi3_clk)
Uwe Kleine-König8a8d2062010-10-08 16:00:11 +02001281 _REGISTER_CLOCK("imx-sdma", NULL, sdma_clk)
Sascha Hauer8f6e9002010-08-25 11:56:26 +02001282 _REGISTER_CLOCK(NULL, "ckih", ckih_clk)
1283 _REGISTER_CLOCK(NULL, "ckih2", ckih2_clk)
1284 _REGISTER_CLOCK(NULL, "gpt_32k", gpt_32k_clk)
Jason Wang8d83db82010-09-02 15:52:00 +08001285 _REGISTER_CLOCK("imx51-ecspi.0", NULL, ecspi1_clk)
1286 _REGISTER_CLOCK("imx51-ecspi.1", NULL, ecspi2_clk)
1287 _REGISTER_CLOCK("imx51-cspi.0", NULL, cspi_clk)
Eric Bénard6a001b82010-10-11 17:59:47 +02001288 _REGISTER_CLOCK("sdhci-esdhc-imx.0", NULL, esdhc1_clk)
1289 _REGISTER_CLOCK("sdhci-esdhc-imx.1", NULL, esdhc2_clk)
Yong Shen64f102b2010-10-21 21:18:59 +08001290 _REGISTER_CLOCK(NULL, "cpu_clk", cpu_clk)
Dinh Nguyen9ab46502010-11-15 11:30:01 -06001291 _REGISTER_CLOCK(NULL, "iim_clk", iim_clk)
Fabio Estevam2c1f4672010-12-07 14:16:04 -02001292 _REGISTER_CLOCK("imx2-wdt.0", NULL, dummy_clk)
1293 _REGISTER_CLOCK("imx2-wdt.1", NULL, dummy_clk)
Sascha Hauerb8481692010-12-06 09:13:21 +01001294 _REGISTER_CLOCK(NULL, "mipi_hsp", mipi_hsp_clk)
1295 _REGISTER_CLOCK("imx-ipuv3", NULL, ipu_clk)
1296 _REGISTER_CLOCK("imx-ipuv3", "di0", ipu_di0_clk)
1297 _REGISTER_CLOCK("imx-ipuv3", "di1", ipu_di1_clk)
Amit Kucheriaa329b482010-02-04 12:21:53 -08001298};
1299
Dinh Nguyenc0abefd2010-11-15 11:29:59 -06001300static struct clk_lookup mx53_lookups[] = {
1301 _REGISTER_CLOCK("imx-uart.0", NULL, uart1_clk)
1302 _REGISTER_CLOCK("imx-uart.1", NULL, uart2_clk)
1303 _REGISTER_CLOCK("imx-uart.2", NULL, uart3_clk)
1304 _REGISTER_CLOCK(NULL, "gpt", gpt_clk)
1305 _REGISTER_CLOCK("fec.0", NULL, fec_clk)
Dinh Nguyen9ab46502010-11-15 11:30:01 -06001306 _REGISTER_CLOCK(NULL, "iim_clk", iim_clk)
Dinh Nguyenc0abefd2010-11-15 11:29:59 -06001307};
1308
Amit Kucheriaa329b482010-02-04 12:21:53 -08001309static void clk_tree_init(void)
1310{
1311 u32 reg;
1312
1313 ipg_perclk.set_parent(&ipg_perclk, &lp_apm_clk);
1314
1315 /*
1316 * Initialise the IPG PER CLK dividers to 3. IPG_PER_CLK should be at
1317 * 8MHz, its derived from lp_apm.
1318 *
1319 * FIXME: Verify if true for all boards
1320 */
1321 reg = __raw_readl(MXC_CCM_CBCDR);
1322 reg &= ~MXC_CCM_CBCDR_PERCLK_PRED1_MASK;
1323 reg &= ~MXC_CCM_CBCDR_PERCLK_PRED2_MASK;
1324 reg &= ~MXC_CCM_CBCDR_PERCLK_PODF_MASK;
1325 reg |= (2 << MXC_CCM_CBCDR_PERCLK_PRED1_OFFSET);
1326 __raw_writel(reg, MXC_CCM_CBCDR);
1327}
1328
1329int __init mx51_clocks_init(unsigned long ckil, unsigned long osc,
1330 unsigned long ckih1, unsigned long ckih2)
1331{
1332 int i;
1333
1334 external_low_reference = ckil;
1335 external_high_reference = ckih1;
1336 ckih2_reference = ckih2;
1337 oscillator_reference = osc;
1338
Dinh Nguyenc0abefd2010-11-15 11:29:59 -06001339 for (i = 0; i < ARRAY_SIZE(mx51_lookups); i++)
1340 clkdev_add(&mx51_lookups[i]);
Amit Kucheriaa329b482010-02-04 12:21:53 -08001341
1342 clk_tree_init();
1343
1344 clk_enable(&cpu_clk);
1345 clk_enable(&main_bus_clk);
1346
Dinh Nguyen9ab46502010-11-15 11:30:01 -06001347 clk_enable(&iim_clk);
1348 mx51_revision();
1349 clk_disable(&iim_clk);
1350
Arnaud Patard (Rtp)711669e2010-12-20 16:48:58 +01001351 /* move usb_phy_clk to 24MHz */
1352 clk_set_parent(&usb_phy1_clk, &osc_clk);
1353
Dinh Nguyenc79504e2010-05-10 13:45:58 -05001354 /* set the usboh3_clk parent to pll2_sw_clk */
1355 clk_set_parent(&usboh3_clk, &pll2_sw_clk);
1356
Eric Bénard6a001b82010-10-11 17:59:47 +02001357 /* Set SDHC parents to be PLL2 */
1358 clk_set_parent(&esdhc1_clk, &pll2_sw_clk);
1359 clk_set_parent(&esdhc2_clk, &pll2_sw_clk);
1360
1361 /* set SDHC root clock as 166.25MHZ*/
1362 clk_set_rate(&esdhc1_clk, 166250000);
1363 clk_set_rate(&esdhc2_clk, 166250000);
1364
Amit Kucheriaa329b482010-02-04 12:21:53 -08001365 /* System timer */
1366 mxc_timer_init(&gpt_clk, MX51_IO_ADDRESS(MX51_GPT1_BASE_ADDR),
1367 MX51_MXC_INT_GPT);
1368 return 0;
1369}
Dinh Nguyenc0abefd2010-11-15 11:29:59 -06001370
1371int __init mx53_clocks_init(unsigned long ckil, unsigned long osc,
1372 unsigned long ckih1, unsigned long ckih2)
1373{
1374 int i;
1375
1376 external_low_reference = ckil;
1377 external_high_reference = ckih1;
1378 ckih2_reference = ckih2;
1379 oscillator_reference = osc;
1380
1381 for (i = 0; i < ARRAY_SIZE(mx53_lookups); i++)
1382 clkdev_add(&mx53_lookups[i]);
1383
1384 clk_tree_init();
1385
1386 clk_enable(&cpu_clk);
1387 clk_enable(&main_bus_clk);
1388
Dinh Nguyen9ab46502010-11-15 11:30:01 -06001389 clk_enable(&iim_clk);
1390 mx53_revision();
1391 clk_disable(&iim_clk);
1392
Dinh Nguyenc0abefd2010-11-15 11:29:59 -06001393 /* System timer */
1394 mxc_timer_init(&gpt_clk, MX53_IO_ADDRESS(MX53_GPT1_BASE_ADDR),
1395 MX53_INT_GPT);
1396 return 0;
1397}