blob: 08470504a088915f1cd0eea8e7ca1a3b25a41e32 [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>
Jean-Christop PLAGNIOL-VILLARD6d803ba2010-11-17 10:04:33 +010017#include <linux/clkdev.h>
Shawn Guo73d2b4c2011-10-17 08:42:16 +080018#include <linux/of.h>
Amit Kucheriaa329b482010-02-04 12:21:53 -080019
Dinh Nguyen17807f92010-04-13 14:05:08 -050020#include <asm/div64.h>
Amit Kucheriaa329b482010-02-04 12:21:53 -080021
22#include <mach/hardware.h>
23#include <mach/common.h>
24#include <mach/clock.h>
25
Sascha Hauer784a90c2011-11-07 12:36:48 +010026#include "crm-regs-imx5.h"
Amit Kucheriaa329b482010-02-04 12:21:53 -080027
28/* External clock values passed-in by the board code */
29static unsigned long external_high_reference, external_low_reference;
30static unsigned long oscillator_reference, ckih2_reference;
31
32static struct clk osc_clk;
33static struct clk pll1_main_clk;
34static struct clk pll1_sw_clk;
35static struct clk pll2_sw_clk;
36static struct clk pll3_sw_clk;
Dinh Nguyenc0abefd2010-11-15 11:29:59 -060037static struct clk mx53_pll4_sw_clk;
Amit Kucheriaa329b482010-02-04 12:21:53 -080038static struct clk lp_apm_clk;
39static struct clk periph_apm_clk;
40static struct clk ahb_clk;
41static struct clk ipg_clk;
Dinh Nguyenc79504e2010-05-10 13:45:58 -050042static struct clk usboh3_clk;
Sascha Hauerb8481692010-12-06 09:13:21 +010043static struct clk emi_fast_clk;
44static struct clk ipu_clk;
45static struct clk mipi_hsc1_clk;
Richard Zhu35921902011-02-28 19:32:03 +080046static struct clk esdhc1_clk;
47static struct clk esdhc2_clk;
48static struct clk esdhc3_mx53_clk;
Amit Kucheriaa329b482010-02-04 12:21:53 -080049
50#define MAX_DPLL_WAIT_TRIES 1000 /* 1000 * udelay(1) = 1ms */
51
Eric Bénard6a001b82010-10-11 17:59:47 +020052/* calculate best pre and post dividers to get the required divider */
53static void __calc_pre_post_dividers(u32 div, u32 *pre, u32 *post,
54 u32 max_pre, u32 max_post)
55{
56 if (div >= max_pre * max_post) {
57 *pre = max_pre;
58 *post = max_post;
59 } else if (div >= max_pre) {
60 u32 min_pre, temp_pre, old_err, err;
61 min_pre = DIV_ROUND_UP(div, max_post);
62 old_err = max_pre;
63 for (temp_pre = max_pre; temp_pre >= min_pre; temp_pre--) {
64 err = div % temp_pre;
65 if (err == 0) {
66 *pre = temp_pre;
67 break;
68 }
69 err = temp_pre - err;
70 if (err < old_err) {
71 old_err = err;
72 *pre = temp_pre;
73 }
74 }
75 *post = DIV_ROUND_UP(div, *pre);
76 } else {
77 *pre = div;
78 *post = 1;
79 }
80}
81
Uwe Kleine-König79901472010-09-10 16:58:42 +020082static void _clk_ccgr_setclk(struct clk *clk, unsigned mode)
83{
84 u32 reg = __raw_readl(clk->enable_reg);
85
86 reg &= ~(MXC_CCM_CCGRx_CG_MASK << clk->enable_shift);
87 reg |= mode << clk->enable_shift;
88
89 __raw_writel(reg, clk->enable_reg);
90}
91
Amit Kucheriaa329b482010-02-04 12:21:53 -080092static int _clk_ccgr_enable(struct clk *clk)
93{
Uwe Kleine-König79901472010-09-10 16:58:42 +020094 _clk_ccgr_setclk(clk, MXC_CCM_CCGRx_MOD_ON);
Amit Kucheriaa329b482010-02-04 12:21:53 -080095 return 0;
96}
97
98static void _clk_ccgr_disable(struct clk *clk)
99{
Uwe Kleine-König79901472010-09-10 16:58:42 +0200100 _clk_ccgr_setclk(clk, MXC_CCM_CCGRx_MOD_OFF);
101}
Amit Kucheriaa329b482010-02-04 12:21:53 -0800102
Uwe Kleine-König79901472010-09-10 16:58:42 +0200103static int _clk_ccgr_enable_inrun(struct clk *clk)
104{
105 _clk_ccgr_setclk(clk, MXC_CCM_CCGRx_MOD_IDLE);
106 return 0;
Amit Kucheriaa329b482010-02-04 12:21:53 -0800107}
108
109static void _clk_ccgr_disable_inwait(struct clk *clk)
110{
Uwe Kleine-König79901472010-09-10 16:58:42 +0200111 _clk_ccgr_setclk(clk, MXC_CCM_CCGRx_MOD_IDLE);
Amit Kucheriaa329b482010-02-04 12:21:53 -0800112}
113
114/*
115 * For the 4-to-1 muxed input clock
116 */
117static inline u32 _get_mux(struct clk *parent, struct clk *m0,
118 struct clk *m1, struct clk *m2, struct clk *m3)
119{
120 if (parent == m0)
121 return 0;
122 else if (parent == m1)
123 return 1;
124 else if (parent == m2)
125 return 2;
126 else if (parent == m3)
127 return 3;
128 else
129 BUG();
130
131 return -EINVAL;
132}
133
Yong Shen644b1d52011-01-04 14:22:55 +0800134static inline void __iomem *_mx51_get_pll_base(struct clk *pll)
Amit Kucheriaa329b482010-02-04 12:21:53 -0800135{
136 if (pll == &pll1_main_clk)
137 return MX51_DPLL1_BASE;
138 else if (pll == &pll2_sw_clk)
139 return MX51_DPLL2_BASE;
140 else if (pll == &pll3_sw_clk)
141 return MX51_DPLL3_BASE;
142 else
143 BUG();
144
145 return NULL;
146}
147
Yong Shen644b1d52011-01-04 14:22:55 +0800148static inline void __iomem *_mx53_get_pll_base(struct clk *pll)
149{
150 if (pll == &pll1_main_clk)
151 return MX53_DPLL1_BASE;
152 else if (pll == &pll2_sw_clk)
153 return MX53_DPLL2_BASE;
154 else if (pll == &pll3_sw_clk)
155 return MX53_DPLL3_BASE;
Dinh Nguyenc0abefd2010-11-15 11:29:59 -0600156 else if (pll == &mx53_pll4_sw_clk)
157 return MX53_DPLL4_BASE;
Amit Kucheriaa329b482010-02-04 12:21:53 -0800158 else
159 BUG();
160
161 return NULL;
162}
163
Yong Shen644b1d52011-01-04 14:22:55 +0800164static inline void __iomem *_get_pll_base(struct clk *pll)
165{
166 if (cpu_is_mx51())
167 return _mx51_get_pll_base(pll);
168 else
169 return _mx53_get_pll_base(pll);
170}
171
Amit Kucheriaa329b482010-02-04 12:21:53 -0800172static unsigned long clk_pll_get_rate(struct clk *clk)
173{
174 long mfi, mfn, mfd, pdf, ref_clk, mfn_abs;
175 unsigned long dp_op, dp_mfd, dp_mfn, dp_ctl, pll_hfsm, dbl;
176 void __iomem *pllbase;
177 s64 temp;
178 unsigned long parent_rate;
179
180 parent_rate = clk_get_rate(clk->parent);
181
182 pllbase = _get_pll_base(clk);
183
184 dp_ctl = __raw_readl(pllbase + MXC_PLL_DP_CTL);
185 pll_hfsm = dp_ctl & MXC_PLL_DP_CTL_HFSM;
186 dbl = dp_ctl & MXC_PLL_DP_CTL_DPDCK0_2_EN;
187
188 if (pll_hfsm == 0) {
189 dp_op = __raw_readl(pllbase + MXC_PLL_DP_OP);
190 dp_mfd = __raw_readl(pllbase + MXC_PLL_DP_MFD);
191 dp_mfn = __raw_readl(pllbase + MXC_PLL_DP_MFN);
192 } else {
193 dp_op = __raw_readl(pllbase + MXC_PLL_DP_HFS_OP);
194 dp_mfd = __raw_readl(pllbase + MXC_PLL_DP_HFS_MFD);
195 dp_mfn = __raw_readl(pllbase + MXC_PLL_DP_HFS_MFN);
196 }
197 pdf = dp_op & MXC_PLL_DP_OP_PDF_MASK;
198 mfi = (dp_op & MXC_PLL_DP_OP_MFI_MASK) >> MXC_PLL_DP_OP_MFI_OFFSET;
199 mfi = (mfi <= 5) ? 5 : mfi;
200 mfd = dp_mfd & MXC_PLL_DP_MFD_MASK;
201 mfn = mfn_abs = dp_mfn & MXC_PLL_DP_MFN_MASK;
202 /* Sign extend to 32-bits */
203 if (mfn >= 0x04000000) {
204 mfn |= 0xFC000000;
205 mfn_abs = -mfn;
206 }
207
208 ref_clk = 2 * parent_rate;
209 if (dbl != 0)
210 ref_clk *= 2;
211
212 ref_clk /= (pdf + 1);
213 temp = (u64) ref_clk * mfn_abs;
214 do_div(temp, mfd + 1);
215 if (mfn < 0)
216 temp = -temp;
217 temp = (ref_clk * mfi) + temp;
218
219 return temp;
220}
221
222static int _clk_pll_set_rate(struct clk *clk, unsigned long rate)
223{
224 u32 reg;
225 void __iomem *pllbase;
226
227 long mfi, pdf, mfn, mfd = 999999;
228 s64 temp64;
229 unsigned long quad_parent_rate;
230 unsigned long pll_hfsm, dp_ctl;
231 unsigned long parent_rate;
232
233 parent_rate = clk_get_rate(clk->parent);
234
235 pllbase = _get_pll_base(clk);
236
237 quad_parent_rate = 4 * parent_rate;
238 pdf = mfi = -1;
239 while (++pdf < 16 && mfi < 5)
240 mfi = rate * (pdf+1) / quad_parent_rate;
241 if (mfi > 15)
242 return -EINVAL;
243 pdf--;
244
245 temp64 = rate * (pdf+1) - quad_parent_rate * mfi;
246 do_div(temp64, quad_parent_rate/1000000);
247 mfn = (long)temp64;
248
249 dp_ctl = __raw_readl(pllbase + MXC_PLL_DP_CTL);
250 /* use dpdck0_2 */
251 __raw_writel(dp_ctl | 0x1000L, pllbase + MXC_PLL_DP_CTL);
252 pll_hfsm = dp_ctl & MXC_PLL_DP_CTL_HFSM;
253 if (pll_hfsm == 0) {
254 reg = mfi << 4 | pdf;
255 __raw_writel(reg, pllbase + MXC_PLL_DP_OP);
256 __raw_writel(mfd, pllbase + MXC_PLL_DP_MFD);
257 __raw_writel(mfn, pllbase + MXC_PLL_DP_MFN);
258 } else {
259 reg = mfi << 4 | pdf;
260 __raw_writel(reg, pllbase + MXC_PLL_DP_HFS_OP);
261 __raw_writel(mfd, pllbase + MXC_PLL_DP_HFS_MFD);
262 __raw_writel(mfn, pllbase + MXC_PLL_DP_HFS_MFN);
263 }
264
265 return 0;
266}
267
268static int _clk_pll_enable(struct clk *clk)
269{
270 u32 reg;
271 void __iomem *pllbase;
272 int i = 0;
273
274 pllbase = _get_pll_base(clk);
Jason Liue1b96ad2011-08-05 23:34:32 +0800275 reg = __raw_readl(pllbase + MXC_PLL_DP_CTL);
276 if (reg & MXC_PLL_DP_CTL_UPEN)
277 return 0;
278
279 reg |= MXC_PLL_DP_CTL_UPEN;
Amit Kucheriaa329b482010-02-04 12:21:53 -0800280 __raw_writel(reg, pllbase + MXC_PLL_DP_CTL);
281
282 /* Wait for lock */
283 do {
284 reg = __raw_readl(pllbase + MXC_PLL_DP_CTL);
285 if (reg & MXC_PLL_DP_CTL_LRF)
286 break;
287
288 udelay(1);
289 } while (++i < MAX_DPLL_WAIT_TRIES);
290
291 if (i == MAX_DPLL_WAIT_TRIES) {
292 pr_err("MX5: pll locking failed\n");
293 return -EINVAL;
294 }
295
296 return 0;
297}
298
299static void _clk_pll_disable(struct clk *clk)
300{
301 u32 reg;
302 void __iomem *pllbase;
303
304 pllbase = _get_pll_base(clk);
305 reg = __raw_readl(pllbase + MXC_PLL_DP_CTL) & ~MXC_PLL_DP_CTL_UPEN;
306 __raw_writel(reg, pllbase + MXC_PLL_DP_CTL);
307}
308
309static int _clk_pll1_sw_set_parent(struct clk *clk, struct clk *parent)
310{
311 u32 reg, step;
312
313 reg = __raw_readl(MXC_CCM_CCSR);
314
315 /* When switching from pll_main_clk to a bypass clock, first select a
316 * multiplexed clock in 'step_sel', then shift the glitchless mux
317 * 'pll1_sw_clk_sel'.
318 *
319 * When switching back, do it in reverse order
320 */
321 if (parent == &pll1_main_clk) {
322 /* Switch to pll1_main_clk */
323 reg &= ~MXC_CCM_CCSR_PLL1_SW_CLK_SEL;
324 __raw_writel(reg, MXC_CCM_CCSR);
325 /* step_clk mux switched to lp_apm, to save power. */
326 reg = __raw_readl(MXC_CCM_CCSR);
327 reg &= ~MXC_CCM_CCSR_STEP_SEL_MASK;
328 reg |= (MXC_CCM_CCSR_STEP_SEL_LP_APM <<
329 MXC_CCM_CCSR_STEP_SEL_OFFSET);
330 } else {
331 if (parent == &lp_apm_clk) {
332 step = MXC_CCM_CCSR_STEP_SEL_LP_APM;
333 } else if (parent == &pll2_sw_clk) {
334 step = MXC_CCM_CCSR_STEP_SEL_PLL2_DIVIDED;
335 } else if (parent == &pll3_sw_clk) {
336 step = MXC_CCM_CCSR_STEP_SEL_PLL3_DIVIDED;
337 } else
338 return -EINVAL;
339
340 reg &= ~MXC_CCM_CCSR_STEP_SEL_MASK;
341 reg |= (step << MXC_CCM_CCSR_STEP_SEL_OFFSET);
342
343 __raw_writel(reg, MXC_CCM_CCSR);
344 /* Switch to step_clk */
345 reg = __raw_readl(MXC_CCM_CCSR);
346 reg |= MXC_CCM_CCSR_PLL1_SW_CLK_SEL;
347 }
348 __raw_writel(reg, MXC_CCM_CCSR);
349 return 0;
350}
351
352static unsigned long clk_pll1_sw_get_rate(struct clk *clk)
353{
354 u32 reg, div;
355 unsigned long parent_rate;
356
357 parent_rate = clk_get_rate(clk->parent);
358
359 reg = __raw_readl(MXC_CCM_CCSR);
360
361 if (clk->parent == &pll2_sw_clk) {
362 div = ((reg & MXC_CCM_CCSR_PLL2_PODF_MASK) >>
363 MXC_CCM_CCSR_PLL2_PODF_OFFSET) + 1;
364 } else if (clk->parent == &pll3_sw_clk) {
365 div = ((reg & MXC_CCM_CCSR_PLL3_PODF_MASK) >>
366 MXC_CCM_CCSR_PLL3_PODF_OFFSET) + 1;
367 } else
368 div = 1;
369 return parent_rate / div;
370}
371
372static int _clk_pll2_sw_set_parent(struct clk *clk, struct clk *parent)
373{
374 u32 reg;
375
376 reg = __raw_readl(MXC_CCM_CCSR);
377
378 if (parent == &pll2_sw_clk)
379 reg &= ~MXC_CCM_CCSR_PLL2_SW_CLK_SEL;
380 else
381 reg |= MXC_CCM_CCSR_PLL2_SW_CLK_SEL;
382
383 __raw_writel(reg, MXC_CCM_CCSR);
384 return 0;
385}
386
387static int _clk_lp_apm_set_parent(struct clk *clk, struct clk *parent)
388{
389 u32 reg;
390
391 if (parent == &osc_clk)
392 reg = __raw_readl(MXC_CCM_CCSR) & ~MXC_CCM_CCSR_LP_APM_SEL;
393 else
394 return -EINVAL;
395
396 __raw_writel(reg, MXC_CCM_CCSR);
397
398 return 0;
399}
400
Yong Shen64f102b2010-10-21 21:18:59 +0800401static unsigned long clk_cpu_get_rate(struct clk *clk)
Amit Kucheriaa329b482010-02-04 12:21:53 -0800402{
403 u32 cacrr, div;
404 unsigned long parent_rate;
405
406 parent_rate = clk_get_rate(clk->parent);
407 cacrr = __raw_readl(MXC_CCM_CACRR);
408 div = (cacrr & MXC_CCM_CACRR_ARM_PODF_MASK) + 1;
409
410 return parent_rate / div;
411}
412
Yong Shen64f102b2010-10-21 21:18:59 +0800413static int clk_cpu_set_rate(struct clk *clk, unsigned long rate)
414{
415 u32 reg, cpu_podf;
416 unsigned long parent_rate;
417
418 parent_rate = clk_get_rate(clk->parent);
419 cpu_podf = parent_rate / rate - 1;
420 /* use post divider to change freq */
421 reg = __raw_readl(MXC_CCM_CACRR);
422 reg &= ~MXC_CCM_CACRR_ARM_PODF_MASK;
423 reg |= cpu_podf << MXC_CCM_CACRR_ARM_PODF_OFFSET;
424 __raw_writel(reg, MXC_CCM_CACRR);
425
426 return 0;
427}
428
Amit Kucheriaa329b482010-02-04 12:21:53 -0800429static int _clk_periph_apm_set_parent(struct clk *clk, struct clk *parent)
430{
431 u32 reg, mux;
432 int i = 0;
433
434 mux = _get_mux(parent, &pll1_sw_clk, &pll3_sw_clk, &lp_apm_clk, NULL);
435
436 reg = __raw_readl(MXC_CCM_CBCMR) & ~MXC_CCM_CBCMR_PERIPH_CLK_SEL_MASK;
437 reg |= mux << MXC_CCM_CBCMR_PERIPH_CLK_SEL_OFFSET;
438 __raw_writel(reg, MXC_CCM_CBCMR);
439
440 /* Wait for lock */
441 do {
442 reg = __raw_readl(MXC_CCM_CDHIPR);
443 if (!(reg & MXC_CCM_CDHIPR_PERIPH_CLK_SEL_BUSY))
444 break;
445
446 udelay(1);
447 } while (++i < MAX_DPLL_WAIT_TRIES);
448
449 if (i == MAX_DPLL_WAIT_TRIES) {
450 pr_err("MX5: Set parent for periph_apm clock failed\n");
451 return -EINVAL;
452 }
453
454 return 0;
455}
456
457static int _clk_main_bus_set_parent(struct clk *clk, struct clk *parent)
458{
459 u32 reg;
460
461 reg = __raw_readl(MXC_CCM_CBCDR);
462
463 if (parent == &pll2_sw_clk)
464 reg &= ~MXC_CCM_CBCDR_PERIPH_CLK_SEL;
465 else if (parent == &periph_apm_clk)
466 reg |= MXC_CCM_CBCDR_PERIPH_CLK_SEL;
467 else
468 return -EINVAL;
469
470 __raw_writel(reg, MXC_CCM_CBCDR);
471
472 return 0;
473}
474
475static struct clk main_bus_clk = {
476 .parent = &pll2_sw_clk,
477 .set_parent = _clk_main_bus_set_parent,
478};
479
480static unsigned long clk_ahb_get_rate(struct clk *clk)
481{
482 u32 reg, div;
483 unsigned long parent_rate;
484
485 parent_rate = clk_get_rate(clk->parent);
486
487 reg = __raw_readl(MXC_CCM_CBCDR);
488 div = ((reg & MXC_CCM_CBCDR_AHB_PODF_MASK) >>
489 MXC_CCM_CBCDR_AHB_PODF_OFFSET) + 1;
490 return parent_rate / div;
491}
492
493
494static int _clk_ahb_set_rate(struct clk *clk, unsigned long rate)
495{
496 u32 reg, div;
497 unsigned long parent_rate;
498 int i = 0;
499
500 parent_rate = clk_get_rate(clk->parent);
501
502 div = parent_rate / rate;
503 if (div > 8 || div < 1 || ((parent_rate / div) != rate))
504 return -EINVAL;
505
506 reg = __raw_readl(MXC_CCM_CBCDR);
507 reg &= ~MXC_CCM_CBCDR_AHB_PODF_MASK;
508 reg |= (div - 1) << MXC_CCM_CBCDR_AHB_PODF_OFFSET;
509 __raw_writel(reg, MXC_CCM_CBCDR);
510
511 /* Wait for lock */
512 do {
513 reg = __raw_readl(MXC_CCM_CDHIPR);
514 if (!(reg & MXC_CCM_CDHIPR_AHB_PODF_BUSY))
515 break;
516
517 udelay(1);
518 } while (++i < MAX_DPLL_WAIT_TRIES);
519
520 if (i == MAX_DPLL_WAIT_TRIES) {
521 pr_err("MX5: clk_ahb_set_rate failed\n");
522 return -EINVAL;
523 }
524
525 return 0;
526}
527
528static unsigned long _clk_ahb_round_rate(struct clk *clk,
529 unsigned long rate)
530{
531 u32 div;
532 unsigned long parent_rate;
533
534 parent_rate = clk_get_rate(clk->parent);
535
536 div = parent_rate / rate;
537 if (div > 8)
538 div = 8;
539 else if (div == 0)
540 div++;
541 return parent_rate / div;
542}
543
544
545static int _clk_max_enable(struct clk *clk)
546{
547 u32 reg;
548
549 _clk_ccgr_enable(clk);
550
551 /* Handshake with MAX when LPM is entered. */
552 reg = __raw_readl(MXC_CCM_CLPCR);
Dinh Nguyenc0abefd2010-11-15 11:29:59 -0600553 if (cpu_is_mx51())
554 reg &= ~MX51_CCM_CLPCR_BYPASS_MAX_LPM_HS;
555 else if (cpu_is_mx53())
556 reg &= ~MX53_CCM_CLPCR_BYPASS_MAX_LPM_HS;
Amit Kucheriaa329b482010-02-04 12:21:53 -0800557 __raw_writel(reg, MXC_CCM_CLPCR);
558
559 return 0;
560}
561
562static void _clk_max_disable(struct clk *clk)
563{
564 u32 reg;
565
566 _clk_ccgr_disable_inwait(clk);
567
568 /* No Handshake with MAX when LPM is entered as its disabled. */
569 reg = __raw_readl(MXC_CCM_CLPCR);
Dinh Nguyenc0abefd2010-11-15 11:29:59 -0600570 if (cpu_is_mx51())
571 reg |= MX51_CCM_CLPCR_BYPASS_MAX_LPM_HS;
572 else if (cpu_is_mx53())
573 reg &= ~MX53_CCM_CLPCR_BYPASS_MAX_LPM_HS;
Amit Kucheriaa329b482010-02-04 12:21:53 -0800574 __raw_writel(reg, MXC_CCM_CLPCR);
575}
576
577static unsigned long clk_ipg_get_rate(struct clk *clk)
578{
579 u32 reg, div;
580 unsigned long parent_rate;
581
582 parent_rate = clk_get_rate(clk->parent);
583
584 reg = __raw_readl(MXC_CCM_CBCDR);
585 div = ((reg & MXC_CCM_CBCDR_IPG_PODF_MASK) >>
586 MXC_CCM_CBCDR_IPG_PODF_OFFSET) + 1;
587
588 return parent_rate / div;
589}
590
591static unsigned long clk_ipg_per_get_rate(struct clk *clk)
592{
593 u32 reg, prediv1, prediv2, podf;
594 unsigned long parent_rate;
595
596 parent_rate = clk_get_rate(clk->parent);
597
598 if (clk->parent == &main_bus_clk || clk->parent == &lp_apm_clk) {
599 /* the main_bus_clk is the one before the DVFS engine */
600 reg = __raw_readl(MXC_CCM_CBCDR);
601 prediv1 = ((reg & MXC_CCM_CBCDR_PERCLK_PRED1_MASK) >>
602 MXC_CCM_CBCDR_PERCLK_PRED1_OFFSET) + 1;
603 prediv2 = ((reg & MXC_CCM_CBCDR_PERCLK_PRED2_MASK) >>
604 MXC_CCM_CBCDR_PERCLK_PRED2_OFFSET) + 1;
605 podf = ((reg & MXC_CCM_CBCDR_PERCLK_PODF_MASK) >>
606 MXC_CCM_CBCDR_PERCLK_PODF_OFFSET) + 1;
607 return parent_rate / (prediv1 * prediv2 * podf);
608 } else if (clk->parent == &ipg_clk)
609 return parent_rate;
610 else
611 BUG();
612}
613
614static int _clk_ipg_per_set_parent(struct clk *clk, struct clk *parent)
615{
616 u32 reg;
617
618 reg = __raw_readl(MXC_CCM_CBCMR);
619
620 reg &= ~MXC_CCM_CBCMR_PERCLK_LP_APM_CLK_SEL;
621 reg &= ~MXC_CCM_CBCMR_PERCLK_IPG_CLK_SEL;
622
623 if (parent == &ipg_clk)
624 reg |= MXC_CCM_CBCMR_PERCLK_IPG_CLK_SEL;
625 else if (parent == &lp_apm_clk)
626 reg |= MXC_CCM_CBCMR_PERCLK_LP_APM_CLK_SEL;
627 else if (parent != &main_bus_clk)
628 return -EINVAL;
629
630 __raw_writel(reg, MXC_CCM_CBCMR);
631
632 return 0;
633}
634
Sascha Hauer2b82e642010-08-03 11:59:07 +0200635#define clk_nfc_set_parent NULL
636
637static unsigned long clk_nfc_get_rate(struct clk *clk)
638{
639 unsigned long rate;
640 u32 reg, div;
641
642 reg = __raw_readl(MXC_CCM_CBCDR);
643 div = ((reg & MXC_CCM_CBCDR_NFC_PODF_MASK) >>
644 MXC_CCM_CBCDR_NFC_PODF_OFFSET) + 1;
645 rate = clk_get_rate(clk->parent) / div;
646 WARN_ON(rate == 0);
647 return rate;
648}
649
650static unsigned long clk_nfc_round_rate(struct clk *clk,
651 unsigned long rate)
652{
653 u32 div;
654 unsigned long parent_rate = clk_get_rate(clk->parent);
655
656 if (!rate)
657 return -EINVAL;
658
659 div = parent_rate / rate;
660
661 if (parent_rate % rate)
662 div++;
663
664 if (div > 8)
665 return -EINVAL;
666
667 return parent_rate / div;
668
669}
670
671static int clk_nfc_set_rate(struct clk *clk, unsigned long rate)
672{
673 u32 reg, div;
674
675 div = clk_get_rate(clk->parent) / rate;
676 if (div == 0)
677 div++;
678 if (((clk_get_rate(clk->parent) / div) != rate) || (div > 8))
679 return -EINVAL;
680
681 reg = __raw_readl(MXC_CCM_CBCDR);
682 reg &= ~MXC_CCM_CBCDR_NFC_PODF_MASK;
683 reg |= (div - 1) << MXC_CCM_CBCDR_NFC_PODF_OFFSET;
684 __raw_writel(reg, MXC_CCM_CBCDR);
685
686 while (__raw_readl(MXC_CCM_CDHIPR) &
687 MXC_CCM_CDHIPR_NFC_IPG_INT_MEM_PODF_BUSY){
688 }
689
690 return 0;
691}
692
Amit Kucheriaa329b482010-02-04 12:21:53 -0800693static unsigned long get_high_reference_clock_rate(struct clk *clk)
694{
695 return external_high_reference;
696}
697
698static unsigned long get_low_reference_clock_rate(struct clk *clk)
699{
700 return external_low_reference;
701}
702
703static unsigned long get_oscillator_reference_clock_rate(struct clk *clk)
704{
705 return oscillator_reference;
706}
707
708static unsigned long get_ckih2_reference_clock_rate(struct clk *clk)
709{
710 return ckih2_reference;
711}
712
Sascha Hauer2b82e642010-08-03 11:59:07 +0200713static unsigned long clk_emi_slow_get_rate(struct clk *clk)
714{
715 u32 reg, div;
716
717 reg = __raw_readl(MXC_CCM_CBCDR);
718 div = ((reg & MXC_CCM_CBCDR_EMI_PODF_MASK) >>
719 MXC_CCM_CBCDR_EMI_PODF_OFFSET) + 1;
720
721 return clk_get_rate(clk->parent) / div;
722}
723
Sascha Hauerb8481692010-12-06 09:13:21 +0100724static unsigned long _clk_ddr_hf_get_rate(struct clk *clk)
725{
726 unsigned long rate;
727 u32 reg, div;
728
729 reg = __raw_readl(MXC_CCM_CBCDR);
730 div = ((reg & MXC_CCM_CBCDR_DDR_PODF_MASK) >>
731 MXC_CCM_CBCDR_DDR_PODF_OFFSET) + 1;
732 rate = clk_get_rate(clk->parent) / div;
733
734 return rate;
735}
736
Amit Kucheriaa329b482010-02-04 12:21:53 -0800737/* External high frequency clock */
738static struct clk ckih_clk = {
739 .get_rate = get_high_reference_clock_rate,
740};
741
742static struct clk ckih2_clk = {
743 .get_rate = get_ckih2_reference_clock_rate,
744};
745
746static struct clk osc_clk = {
747 .get_rate = get_oscillator_reference_clock_rate,
748};
749
750/* External low frequency (32kHz) clock */
751static struct clk ckil_clk = {
752 .get_rate = get_low_reference_clock_rate,
753};
754
755static struct clk pll1_main_clk = {
756 .parent = &osc_clk,
757 .get_rate = clk_pll_get_rate,
758 .enable = _clk_pll_enable,
759 .disable = _clk_pll_disable,
760};
761
762/* Clock tree block diagram (WIP):
763 * CCM: Clock Controller Module
764 *
765 * PLL output -> |
766 * | CCM Switcher -> CCM_CLK_ROOT_GEN ->
767 * PLL bypass -> |
768 *
769 */
770
771/* PLL1 SW supplies to ARM core */
772static struct clk pll1_sw_clk = {
773 .parent = &pll1_main_clk,
774 .set_parent = _clk_pll1_sw_set_parent,
775 .get_rate = clk_pll1_sw_get_rate,
776};
777
778/* PLL2 SW supplies to AXI/AHB/IP buses */
779static struct clk pll2_sw_clk = {
780 .parent = &osc_clk,
781 .get_rate = clk_pll_get_rate,
782 .set_rate = _clk_pll_set_rate,
783 .set_parent = _clk_pll2_sw_set_parent,
784 .enable = _clk_pll_enable,
785 .disable = _clk_pll_disable,
786};
787
788/* PLL3 SW supplies to serial clocks like USB, SSI, etc. */
789static struct clk pll3_sw_clk = {
790 .parent = &osc_clk,
791 .set_rate = _clk_pll_set_rate,
792 .get_rate = clk_pll_get_rate,
793 .enable = _clk_pll_enable,
794 .disable = _clk_pll_disable,
795};
796
Dinh Nguyenc0abefd2010-11-15 11:29:59 -0600797/* PLL4 SW supplies to LVDS Display Bridge(LDB) */
798static struct clk mx53_pll4_sw_clk = {
799 .parent = &osc_clk,
800 .set_rate = _clk_pll_set_rate,
801 .enable = _clk_pll_enable,
802 .disable = _clk_pll_disable,
803};
804
Amit Kucheriaa329b482010-02-04 12:21:53 -0800805/* Low-power Audio Playback Mode clock */
806static struct clk lp_apm_clk = {
807 .parent = &osc_clk,
808 .set_parent = _clk_lp_apm_set_parent,
809};
810
811static struct clk periph_apm_clk = {
812 .parent = &pll1_sw_clk,
813 .set_parent = _clk_periph_apm_set_parent,
814};
815
816static struct clk cpu_clk = {
817 .parent = &pll1_sw_clk,
Yong Shen64f102b2010-10-21 21:18:59 +0800818 .get_rate = clk_cpu_get_rate,
819 .set_rate = clk_cpu_set_rate,
Amit Kucheriaa329b482010-02-04 12:21:53 -0800820};
821
822static struct clk ahb_clk = {
823 .parent = &main_bus_clk,
824 .get_rate = clk_ahb_get_rate,
825 .set_rate = _clk_ahb_set_rate,
826 .round_rate = _clk_ahb_round_rate,
827};
828
Dinh Nguyen9ab46502010-11-15 11:30:01 -0600829static struct clk iim_clk = {
830 .parent = &ipg_clk,
831 .enable_reg = MXC_CCM_CCGR0,
832 .enable_shift = MXC_CCM_CCGRx_CG15_OFFSET,
833};
834
Amit Kucheriaa329b482010-02-04 12:21:53 -0800835/* Main IP interface clock for access to registers */
836static struct clk ipg_clk = {
837 .parent = &ahb_clk,
838 .get_rate = clk_ipg_get_rate,
839};
840
841static struct clk ipg_perclk = {
842 .parent = &lp_apm_clk,
843 .get_rate = clk_ipg_per_get_rate,
844 .set_parent = _clk_ipg_per_set_parent,
845};
846
Amit Kucheriaa329b482010-02-04 12:21:53 -0800847static struct clk ahb_max_clk = {
848 .parent = &ahb_clk,
849 .enable_reg = MXC_CCM_CCGR0,
850 .enable_shift = MXC_CCM_CCGRx_CG14_OFFSET,
851 .enable = _clk_max_enable,
852 .disable = _clk_max_disable,
853};
854
855static struct clk aips_tz1_clk = {
856 .parent = &ahb_clk,
857 .secondary = &ahb_max_clk,
858 .enable_reg = MXC_CCM_CCGR0,
859 .enable_shift = MXC_CCM_CCGRx_CG12_OFFSET,
860 .enable = _clk_ccgr_enable,
861 .disable = _clk_ccgr_disable_inwait,
862};
863
864static struct clk aips_tz2_clk = {
865 .parent = &ahb_clk,
866 .secondary = &ahb_max_clk,
867 .enable_reg = MXC_CCM_CCGR0,
868 .enable_shift = MXC_CCM_CCGRx_CG13_OFFSET,
869 .enable = _clk_ccgr_enable,
870 .disable = _clk_ccgr_disable_inwait,
871};
872
Dinh Nguyenb6e89b22011-03-21 16:30:36 -0500873static struct clk gpc_dvfs_clk = {
874 .enable_reg = MXC_CCM_CCGR5,
875 .enable_shift = MXC_CCM_CCGRx_CG12_OFFSET,
876 .enable = _clk_ccgr_enable,
877 .disable = _clk_ccgr_disable,
878};
879
Amit Kucheriaa329b482010-02-04 12:21:53 -0800880static struct clk gpt_32k_clk = {
881 .id = 0,
882 .parent = &ckil_clk,
883};
884
Fabio Estevam7f77f912010-12-06 16:38:33 -0200885static struct clk dummy_clk = {
886 .id = 0,
887};
888
Sascha Hauer2b82e642010-08-03 11:59:07 +0200889static struct clk emi_slow_clk = {
890 .parent = &pll2_sw_clk,
891 .enable_reg = MXC_CCM_CCGR5,
892 .enable_shift = MXC_CCM_CCGRx_CG8_OFFSET,
893 .enable = _clk_ccgr_enable,
894 .disable = _clk_ccgr_disable_inwait,
895 .get_rate = clk_emi_slow_get_rate,
896};
897
Sascha Hauerb8481692010-12-06 09:13:21 +0100898static int clk_ipu_enable(struct clk *clk)
899{
900 u32 reg;
901
902 _clk_ccgr_enable(clk);
903
904 /* Enable handshake with IPU when certain clock rates are changed */
905 reg = __raw_readl(MXC_CCM_CCDR);
906 reg &= ~MXC_CCM_CCDR_IPU_HS_MASK;
907 __raw_writel(reg, MXC_CCM_CCDR);
908
909 /* Enable handshake with IPU when LPM is entered */
910 reg = __raw_readl(MXC_CCM_CLPCR);
911 reg &= ~MXC_CCM_CLPCR_BYPASS_IPU_LPM_HS;
912 __raw_writel(reg, MXC_CCM_CLPCR);
913
914 return 0;
915}
916
917static void clk_ipu_disable(struct clk *clk)
918{
919 u32 reg;
920
921 _clk_ccgr_disable(clk);
922
923 /* Disable handshake with IPU whe dividers are changed */
924 reg = __raw_readl(MXC_CCM_CCDR);
925 reg |= MXC_CCM_CCDR_IPU_HS_MASK;
926 __raw_writel(reg, MXC_CCM_CCDR);
927
928 /* Disable handshake with IPU when LPM is entered */
929 reg = __raw_readl(MXC_CCM_CLPCR);
930 reg |= MXC_CCM_CLPCR_BYPASS_IPU_LPM_HS;
931 __raw_writel(reg, MXC_CCM_CLPCR);
932}
933
934static struct clk ahbmux1_clk = {
935 .parent = &ahb_clk,
936 .secondary = &ahb_max_clk,
937 .enable_reg = MXC_CCM_CCGR0,
938 .enable_shift = MXC_CCM_CCGRx_CG8_OFFSET,
939 .enable = _clk_ccgr_enable,
940 .disable = _clk_ccgr_disable_inwait,
941};
942
943static struct clk ipu_sec_clk = {
944 .parent = &emi_fast_clk,
945 .secondary = &ahbmux1_clk,
946};
947
948static struct clk ddr_hf_clk = {
949 .parent = &pll1_sw_clk,
950 .get_rate = _clk_ddr_hf_get_rate,
951};
952
953static struct clk ddr_clk = {
954 .parent = &ddr_hf_clk,
955};
956
957/* clock definitions for MIPI HSC unit which has been removed
958 * from documentation, but not from hardware
959 */
960static int _clk_hsc_enable(struct clk *clk)
961{
962 u32 reg;
963
964 _clk_ccgr_enable(clk);
965 /* Handshake with IPU when certain clock rates are changed. */
966 reg = __raw_readl(MXC_CCM_CCDR);
967 reg &= ~MXC_CCM_CCDR_HSC_HS_MASK;
968 __raw_writel(reg, MXC_CCM_CCDR);
969
970 reg = __raw_readl(MXC_CCM_CLPCR);
971 reg &= ~MXC_CCM_CLPCR_BYPASS_HSC_LPM_HS;
972 __raw_writel(reg, MXC_CCM_CLPCR);
973
974 return 0;
975}
976
977static void _clk_hsc_disable(struct clk *clk)
978{
979 u32 reg;
980
981 _clk_ccgr_disable(clk);
982 /* No handshake with HSC as its not enabled. */
983 reg = __raw_readl(MXC_CCM_CCDR);
984 reg |= MXC_CCM_CCDR_HSC_HS_MASK;
985 __raw_writel(reg, MXC_CCM_CCDR);
986
987 reg = __raw_readl(MXC_CCM_CLPCR);
988 reg |= MXC_CCM_CLPCR_BYPASS_HSC_LPM_HS;
989 __raw_writel(reg, MXC_CCM_CLPCR);
990}
991
992static struct clk mipi_hsp_clk = {
993 .parent = &ipu_clk,
994 .enable_reg = MXC_CCM_CCGR4,
995 .enable_shift = MXC_CCM_CCGRx_CG6_OFFSET,
996 .enable = _clk_hsc_enable,
997 .disable = _clk_hsc_disable,
998 .secondary = &mipi_hsc1_clk,
999};
1000
Eric Bénard7e5a7472010-10-12 12:26:32 +02001001#define DEFINE_CLOCK_CCGR(name, i, er, es, pfx, p, s) \
Sascha Hauer2b82e642010-08-03 11:59:07 +02001002 static struct clk name = { \
1003 .id = i, \
1004 .enable_reg = er, \
1005 .enable_shift = es, \
1006 .get_rate = pfx##_get_rate, \
1007 .set_rate = pfx##_set_rate, \
1008 .round_rate = pfx##_round_rate, \
1009 .set_parent = pfx##_set_parent, \
1010 .enable = _clk_ccgr_enable, \
1011 .disable = _clk_ccgr_disable, \
1012 .parent = p, \
1013 .secondary = s, \
1014 }
1015
Eric Bénard6a001b82010-10-11 17:59:47 +02001016#define DEFINE_CLOCK_MAX(name, i, er, es, pfx, p, s) \
1017 static struct clk name = { \
1018 .id = i, \
1019 .enable_reg = er, \
1020 .enable_shift = es, \
1021 .get_rate = pfx##_get_rate, \
1022 .set_rate = pfx##_set_rate, \
1023 .set_parent = pfx##_set_parent, \
1024 .enable = _clk_max_enable, \
1025 .disable = _clk_max_disable, \
1026 .parent = p, \
1027 .secondary = s, \
1028 }
1029
Eric Bénard00762322010-10-11 21:55:24 +02001030#define CLK_GET_RATE(name, nr, bitsname) \
1031static unsigned long clk_##name##_get_rate(struct clk *clk) \
1032{ \
1033 u32 reg, pred, podf; \
1034 \
1035 reg = __raw_readl(MXC_CCM_CSCDR##nr); \
1036 pred = (reg & MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_MASK) \
1037 >> MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_OFFSET; \
1038 podf = (reg & MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_MASK) \
1039 >> MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_OFFSET; \
1040 \
1041 return DIV_ROUND_CLOSEST(clk_get_rate(clk->parent), \
1042 (pred + 1) * (podf + 1)); \
1043}
1044
1045#define CLK_SET_PARENT(name, nr, bitsname) \
1046static int clk_##name##_set_parent(struct clk *clk, struct clk *parent) \
1047{ \
1048 u32 reg, mux; \
1049 \
1050 mux = _get_mux(parent, &pll1_sw_clk, &pll2_sw_clk, \
1051 &pll3_sw_clk, &lp_apm_clk); \
1052 reg = __raw_readl(MXC_CCM_CSCMR##nr) & \
1053 ~MXC_CCM_CSCMR##nr##_##bitsname##_CLK_SEL_MASK; \
1054 reg |= mux << MXC_CCM_CSCMR##nr##_##bitsname##_CLK_SEL_OFFSET; \
1055 __raw_writel(reg, MXC_CCM_CSCMR##nr); \
1056 \
1057 return 0; \
1058}
1059
Eric Bénard6a001b82010-10-11 17:59:47 +02001060#define CLK_SET_RATE(name, nr, bitsname) \
1061static int clk_##name##_set_rate(struct clk *clk, unsigned long rate) \
1062{ \
1063 u32 reg, div, parent_rate; \
1064 u32 pre = 0, post = 0; \
1065 \
1066 parent_rate = clk_get_rate(clk->parent); \
1067 div = parent_rate / rate; \
1068 \
1069 if ((parent_rate / div) != rate) \
1070 return -EINVAL; \
1071 \
1072 __calc_pre_post_dividers(div, &pre, &post, \
1073 (MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_MASK >> \
1074 MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_OFFSET) + 1, \
1075 (MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_MASK >> \
1076 MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_OFFSET) + 1);\
1077 \
1078 /* Set sdhc1 clock divider */ \
1079 reg = __raw_readl(MXC_CCM_CSCDR##nr) & \
1080 ~(MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_MASK \
1081 | MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_MASK); \
1082 reg |= (post - 1) << \
1083 MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_OFFSET; \
1084 reg |= (pre - 1) << \
1085 MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_OFFSET; \
1086 __raw_writel(reg, MXC_CCM_CSCDR##nr); \
1087 \
1088 return 0; \
1089}
1090
Eric Bénard00762322010-10-11 21:55:24 +02001091/* UART */
1092CLK_GET_RATE(uart, 1, UART)
1093CLK_SET_PARENT(uart, 1, UART)
1094
1095static struct clk uart_root_clk = {
1096 .parent = &pll2_sw_clk,
1097 .get_rate = clk_uart_get_rate,
1098 .set_parent = clk_uart_set_parent,
1099};
1100
1101/* USBOH3 */
1102CLK_GET_RATE(usboh3, 1, USBOH3)
1103CLK_SET_PARENT(usboh3, 1, USBOH3)
1104
1105static struct clk usboh3_clk = {
1106 .parent = &pll2_sw_clk,
1107 .get_rate = clk_usboh3_get_rate,
1108 .set_parent = clk_usboh3_set_parent,
Arnaud Patard (Rtp)711669e2010-12-20 16:48:58 +01001109 .enable = _clk_ccgr_enable,
1110 .disable = _clk_ccgr_disable,
1111 .enable_reg = MXC_CCM_CCGR2,
1112 .enable_shift = MXC_CCM_CCGRx_CG14_OFFSET,
1113};
1114
1115static struct clk usb_ahb_clk = {
1116 .parent = &ipg_clk,
1117 .enable = _clk_ccgr_enable,
1118 .disable = _clk_ccgr_disable,
1119 .enable_reg = MXC_CCM_CCGR2,
1120 .enable_shift = MXC_CCM_CCGRx_CG13_OFFSET,
1121};
1122
1123static int clk_usb_phy1_set_parent(struct clk *clk, struct clk *parent)
1124{
1125 u32 reg;
1126
1127 reg = __raw_readl(MXC_CCM_CSCMR1) & ~MXC_CCM_CSCMR1_USB_PHY_CLK_SEL;
1128
1129 if (parent == &pll3_sw_clk)
1130 reg |= 1 << MXC_CCM_CSCMR1_USB_PHY_CLK_SEL_OFFSET;
1131
1132 __raw_writel(reg, MXC_CCM_CSCMR1);
1133
1134 return 0;
1135}
1136
1137static struct clk usb_phy1_clk = {
1138 .parent = &pll3_sw_clk,
1139 .set_parent = clk_usb_phy1_set_parent,
1140 .enable = _clk_ccgr_enable,
1141 .enable_reg = MXC_CCM_CCGR2,
1142 .enable_shift = MXC_CCM_CCGRx_CG0_OFFSET,
1143 .disable = _clk_ccgr_disable,
Eric Bénard00762322010-10-11 21:55:24 +02001144};
1145
Jason Wang8d83db82010-09-02 15:52:00 +08001146/* eCSPI */
Eric Bénard00762322010-10-11 21:55:24 +02001147CLK_GET_RATE(ecspi, 2, CSPI)
1148CLK_SET_PARENT(ecspi, 1, CSPI)
Jason Wang8d83db82010-09-02 15:52:00 +08001149
1150static struct clk ecspi_main_clk = {
1151 .parent = &pll3_sw_clk,
1152 .get_rate = clk_ecspi_get_rate,
1153 .set_parent = clk_ecspi_set_parent,
1154};
1155
Eric Bénard6a001b82010-10-11 17:59:47 +02001156/* eSDHC */
1157CLK_GET_RATE(esdhc1, 1, ESDHC1_MSHC1)
1158CLK_SET_PARENT(esdhc1, 1, ESDHC1_MSHC1)
1159CLK_SET_RATE(esdhc1, 1, ESDHC1_MSHC1)
1160
Richard Zhu35921902011-02-28 19:32:03 +08001161/* mx51 specific */
Eric Bénard6a001b82010-10-11 17:59:47 +02001162CLK_GET_RATE(esdhc2, 1, ESDHC2_MSHC2)
1163CLK_SET_PARENT(esdhc2, 1, ESDHC2_MSHC2)
1164CLK_SET_RATE(esdhc2, 1, ESDHC2_MSHC2)
1165
Richard Zhu35921902011-02-28 19:32:03 +08001166static int clk_esdhc3_set_parent(struct clk *clk, struct clk *parent)
1167{
1168 u32 reg;
1169
1170 reg = __raw_readl(MXC_CCM_CSCMR1);
1171 if (parent == &esdhc1_clk)
1172 reg &= ~MXC_CCM_CSCMR1_ESDHC3_CLK_SEL;
1173 else if (parent == &esdhc2_clk)
1174 reg |= MXC_CCM_CSCMR1_ESDHC3_CLK_SEL;
1175 else
1176 return -EINVAL;
1177 __raw_writel(reg, MXC_CCM_CSCMR1);
1178
1179 return 0;
1180}
1181
1182static int clk_esdhc4_set_parent(struct clk *clk, struct clk *parent)
1183{
1184 u32 reg;
1185
1186 reg = __raw_readl(MXC_CCM_CSCMR1);
1187 if (parent == &esdhc1_clk)
1188 reg &= ~MXC_CCM_CSCMR1_ESDHC4_CLK_SEL;
1189 else if (parent == &esdhc2_clk)
1190 reg |= MXC_CCM_CSCMR1_ESDHC4_CLK_SEL;
1191 else
1192 return -EINVAL;
1193 __raw_writel(reg, MXC_CCM_CSCMR1);
1194
1195 return 0;
1196}
1197
1198/* mx53 specific */
1199static int clk_esdhc2_mx53_set_parent(struct clk *clk, struct clk *parent)
1200{
1201 u32 reg;
1202
1203 reg = __raw_readl(MXC_CCM_CSCMR1);
1204 if (parent == &esdhc1_clk)
1205 reg &= ~MXC_CCM_CSCMR1_ESDHC2_MSHC2_MX53_CLK_SEL;
1206 else if (parent == &esdhc3_mx53_clk)
1207 reg |= MXC_CCM_CSCMR1_ESDHC2_MSHC2_MX53_CLK_SEL;
1208 else
1209 return -EINVAL;
1210 __raw_writel(reg, MXC_CCM_CSCMR1);
1211
1212 return 0;
1213}
1214
1215CLK_GET_RATE(esdhc3_mx53, 1, ESDHC3_MX53)
1216CLK_SET_PARENT(esdhc3_mx53, 1, ESDHC3_MX53)
1217CLK_SET_RATE(esdhc3_mx53, 1, ESDHC3_MX53)
1218
1219static int clk_esdhc4_mx53_set_parent(struct clk *clk, struct clk *parent)
1220{
1221 u32 reg;
1222
1223 reg = __raw_readl(MXC_CCM_CSCMR1);
1224 if (parent == &esdhc1_clk)
1225 reg &= ~MXC_CCM_CSCMR1_ESDHC4_CLK_SEL;
1226 else if (parent == &esdhc3_mx53_clk)
1227 reg |= MXC_CCM_CSCMR1_ESDHC4_CLK_SEL;
1228 else
1229 return -EINVAL;
1230 __raw_writel(reg, MXC_CCM_CSCMR1);
1231
1232 return 0;
1233}
1234
Uwe Kleine-König74d99f32010-09-10 17:01:26 +02001235#define DEFINE_CLOCK_FULL(name, i, er, es, gr, sr, e, d, p, s) \
1236 static struct clk name = { \
1237 .id = i, \
1238 .enable_reg = er, \
1239 .enable_shift = es, \
1240 .get_rate = gr, \
1241 .set_rate = sr, \
1242 .enable = e, \
1243 .disable = d, \
1244 .parent = p, \
1245 .secondary = s, \
Amit Kucheriaa329b482010-02-04 12:21:53 -08001246 }
1247
Uwe Kleine-König74d99f32010-09-10 17:01:26 +02001248#define DEFINE_CLOCK(name, i, er, es, gr, sr, p, s) \
1249 DEFINE_CLOCK_FULL(name, i, er, es, gr, sr, _clk_ccgr_enable, _clk_ccgr_disable, p, s)
Amit Kucheriaa329b482010-02-04 12:21:53 -08001250
1251/* Shared peripheral bus arbiter */
1252DEFINE_CLOCK(spba_clk, 0, MXC_CCM_CCGR5, MXC_CCM_CCGRx_CG0_OFFSET,
1253 NULL, NULL, &ipg_clk, NULL);
1254
1255/* UART */
Amit Kucheriaa329b482010-02-04 12:21:53 -08001256DEFINE_CLOCK(uart1_ipg_clk, 0, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG3_OFFSET,
1257 NULL, NULL, &ipg_clk, &aips_tz1_clk);
1258DEFINE_CLOCK(uart2_ipg_clk, 1, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG5_OFFSET,
1259 NULL, NULL, &ipg_clk, &aips_tz1_clk);
1260DEFINE_CLOCK(uart3_ipg_clk, 2, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG7_OFFSET,
1261 NULL, NULL, &ipg_clk, &spba_clk);
Fabio Estevamfce43f92011-06-27 17:12:08 -03001262DEFINE_CLOCK(uart4_ipg_clk, 3, MXC_CCM_CCGR7, MXC_CCM_CCGRx_CG4_OFFSET,
1263 NULL, NULL, &ipg_clk, &spba_clk);
1264DEFINE_CLOCK(uart5_ipg_clk, 4, MXC_CCM_CCGR7, MXC_CCM_CCGRx_CG6_OFFSET,
1265 NULL, NULL, &ipg_clk, &spba_clk);
Sascha Hauer8f6e9002010-08-25 11:56:26 +02001266DEFINE_CLOCK(uart1_clk, 0, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG4_OFFSET,
1267 NULL, NULL, &uart_root_clk, &uart1_ipg_clk);
1268DEFINE_CLOCK(uart2_clk, 1, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG6_OFFSET,
1269 NULL, NULL, &uart_root_clk, &uart2_ipg_clk);
1270DEFINE_CLOCK(uart3_clk, 2, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG8_OFFSET,
1271 NULL, NULL, &uart_root_clk, &uart3_ipg_clk);
Fabio Estevamfce43f92011-06-27 17:12:08 -03001272DEFINE_CLOCK(uart4_clk, 3, MXC_CCM_CCGR7, MXC_CCM_CCGRx_CG5_OFFSET,
1273 NULL, NULL, &uart_root_clk, &uart4_ipg_clk);
1274DEFINE_CLOCK(uart5_clk, 4, MXC_CCM_CCGR7, MXC_CCM_CCGRx_CG7_OFFSET,
1275 NULL, NULL, &uart_root_clk, &uart5_ipg_clk);
Amit Kucheriaa329b482010-02-04 12:21:53 -08001276
1277/* GPT */
Amit Kucheriaa329b482010-02-04 12:21:53 -08001278DEFINE_CLOCK(gpt_ipg_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG10_OFFSET,
1279 NULL, NULL, &ipg_clk, NULL);
Sascha Hauer8f6e9002010-08-25 11:56:26 +02001280DEFINE_CLOCK(gpt_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG9_OFFSET,
1281 NULL, NULL, &ipg_clk, &gpt_ipg_clk);
Amit Kucheriaa329b482010-02-04 12:21:53 -08001282
Arnaud Patard (Rtp)dd027b02011-01-13 12:26:40 +01001283DEFINE_CLOCK(pwm1_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG6_OFFSET,
Richard Zhaof1dfaef2011-11-08 09:59:34 +08001284 NULL, NULL, &ipg_perclk, NULL);
Arnaud Patard (Rtp)dd027b02011-01-13 12:26:40 +01001285DEFINE_CLOCK(pwm2_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG8_OFFSET,
Richard Zhaof1dfaef2011-11-08 09:59:34 +08001286 NULL, NULL, &ipg_perclk, NULL);
Arnaud Patard (Rtp)dd027b02011-01-13 12:26:40 +01001287
Dinh Nguyen71c2e512010-05-27 10:45:04 -05001288/* I2C */
1289DEFINE_CLOCK(i2c1_clk, 0, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG9_OFFSET,
Lothar Waßmann9d7324242011-07-04 15:52:17 +02001290 NULL, NULL, &ipg_perclk, NULL);
Dinh Nguyen71c2e512010-05-27 10:45:04 -05001291DEFINE_CLOCK(i2c2_clk, 1, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG10_OFFSET,
Lothar Waßmann9d7324242011-07-04 15:52:17 +02001292 NULL, NULL, &ipg_perclk, NULL);
Dinh Nguyen71c2e512010-05-27 10:45:04 -05001293DEFINE_CLOCK(hsi2c_clk, 0, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG11_OFFSET,
1294 NULL, NULL, &ipg_clk, NULL);
Andre Silvab6a14472011-06-22 16:33:04 -03001295DEFINE_CLOCK(i2c3_mx53_clk, 0, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG11_OFFSET,
1296 NULL, NULL, &ipg_perclk, NULL);
Dinh Nguyen71c2e512010-05-27 10:45:04 -05001297
Amit Kucheriaa329b482010-02-04 12:21:53 -08001298/* FEC */
1299DEFINE_CLOCK(fec_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG12_OFFSET,
1300 NULL, NULL, &ipg_clk, NULL);
1301
Sascha Hauer2b82e642010-08-03 11:59:07 +02001302/* NFC */
Eric Bénard7e5a7472010-10-12 12:26:32 +02001303DEFINE_CLOCK_CCGR(nfc_clk, 0, MXC_CCM_CCGR5, MXC_CCM_CCGRx_CG10_OFFSET,
Sascha Hauer2b82e642010-08-03 11:59:07 +02001304 clk_nfc, &emi_slow_clk, NULL);
1305
Sascha Hauerb8618662010-08-20 16:43:54 +02001306/* SSI */
1307DEFINE_CLOCK(ssi1_ipg_clk, 0, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG8_OFFSET,
1308 NULL, NULL, &ipg_clk, NULL);
1309DEFINE_CLOCK(ssi1_clk, 0, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG9_OFFSET,
1310 NULL, NULL, &pll3_sw_clk, &ssi1_ipg_clk);
1311DEFINE_CLOCK(ssi2_ipg_clk, 1, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG10_OFFSET,
1312 NULL, NULL, &ipg_clk, NULL);
1313DEFINE_CLOCK(ssi2_clk, 1, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG11_OFFSET,
1314 NULL, NULL, &pll3_sw_clk, &ssi2_ipg_clk);
Peter Hortonf2597222010-12-03 17:07:28 +00001315DEFINE_CLOCK(ssi3_ipg_clk, 2, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG12_OFFSET,
1316 NULL, NULL, &ipg_clk, NULL);
1317DEFINE_CLOCK(ssi3_clk, 2, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG13_OFFSET,
1318 NULL, NULL, &pll3_sw_clk, &ssi3_ipg_clk);
Sascha Hauerb8618662010-08-20 16:43:54 +02001319
Jason Wang8d83db82010-09-02 15:52:00 +08001320/* eCSPI */
1321DEFINE_CLOCK_FULL(ecspi1_ipg_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG9_OFFSET,
1322 NULL, NULL, _clk_ccgr_enable_inrun, _clk_ccgr_disable,
1323 &ipg_clk, &spba_clk);
1324DEFINE_CLOCK(ecspi1_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG10_OFFSET,
1325 NULL, NULL, &ecspi_main_clk, &ecspi1_ipg_clk);
1326DEFINE_CLOCK_FULL(ecspi2_ipg_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG11_OFFSET,
1327 NULL, NULL, _clk_ccgr_enable_inrun, _clk_ccgr_disable,
1328 &ipg_clk, &aips_tz2_clk);
1329DEFINE_CLOCK(ecspi2_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG12_OFFSET,
1330 NULL, NULL, &ecspi_main_clk, &ecspi2_ipg_clk);
1331
1332/* CSPI */
1333DEFINE_CLOCK(cspi_ipg_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG9_OFFSET,
1334 NULL, NULL, &ipg_clk, &aips_tz2_clk);
1335DEFINE_CLOCK(cspi_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG13_OFFSET,
1336 NULL, NULL, &ipg_clk, &cspi_ipg_clk);
1337
Uwe Kleine-König8a8d2062010-10-08 16:00:11 +02001338/* SDMA */
1339DEFINE_CLOCK(sdma_clk, 1, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG15_OFFSET,
1340 NULL, NULL, &ahb_clk, NULL);
1341
Eric Bénard6a001b82010-10-11 17:59:47 +02001342/* eSDHC */
1343DEFINE_CLOCK_FULL(esdhc1_ipg_clk, 0, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG0_OFFSET,
1344 NULL, NULL, _clk_max_enable, _clk_max_disable, &ipg_clk, NULL);
1345DEFINE_CLOCK_MAX(esdhc1_clk, 0, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG1_OFFSET,
1346 clk_esdhc1, &pll2_sw_clk, &esdhc1_ipg_clk);
1347DEFINE_CLOCK_FULL(esdhc2_ipg_clk, 1, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG2_OFFSET,
1348 NULL, NULL, _clk_max_enable, _clk_max_disable, &ipg_clk, NULL);
Richard Zhu35921902011-02-28 19:32:03 +08001349DEFINE_CLOCK_FULL(esdhc3_ipg_clk, 2, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG4_OFFSET,
1350 NULL, NULL, _clk_max_enable, _clk_max_disable, &ipg_clk, NULL);
1351DEFINE_CLOCK_FULL(esdhc4_ipg_clk, 3, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG6_OFFSET,
1352 NULL, NULL, _clk_max_enable, _clk_max_disable, &ipg_clk, NULL);
1353
1354/* mx51 specific */
Eric Bénard6a001b82010-10-11 17:59:47 +02001355DEFINE_CLOCK_MAX(esdhc2_clk, 1, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG3_OFFSET,
1356 clk_esdhc2, &pll2_sw_clk, &esdhc2_ipg_clk);
1357
Richard Zhu35921902011-02-28 19:32:03 +08001358static struct clk esdhc3_clk = {
1359 .id = 2,
1360 .parent = &esdhc1_clk,
1361 .set_parent = clk_esdhc3_set_parent,
1362 .enable_reg = MXC_CCM_CCGR3,
1363 .enable_shift = MXC_CCM_CCGRx_CG5_OFFSET,
1364 .enable = _clk_max_enable,
1365 .disable = _clk_max_disable,
1366 .secondary = &esdhc3_ipg_clk,
1367};
1368static struct clk esdhc4_clk = {
1369 .id = 3,
1370 .parent = &esdhc1_clk,
1371 .set_parent = clk_esdhc4_set_parent,
1372 .enable_reg = MXC_CCM_CCGR3,
1373 .enable_shift = MXC_CCM_CCGRx_CG7_OFFSET,
1374 .enable = _clk_max_enable,
1375 .disable = _clk_max_disable,
1376 .secondary = &esdhc4_ipg_clk,
1377};
1378
1379/* mx53 specific */
1380static struct clk esdhc2_mx53_clk = {
1381 .id = 2,
1382 .parent = &esdhc1_clk,
1383 .set_parent = clk_esdhc2_mx53_set_parent,
1384 .enable_reg = MXC_CCM_CCGR3,
1385 .enable_shift = MXC_CCM_CCGRx_CG3_OFFSET,
1386 .enable = _clk_max_enable,
1387 .disable = _clk_max_disable,
1388 .secondary = &esdhc3_ipg_clk,
1389};
1390
1391DEFINE_CLOCK_MAX(esdhc3_mx53_clk, 2, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG5_OFFSET,
1392 clk_esdhc3_mx53, &pll2_sw_clk, &esdhc2_ipg_clk);
1393
1394static struct clk esdhc4_mx53_clk = {
1395 .id = 3,
1396 .parent = &esdhc1_clk,
1397 .set_parent = clk_esdhc4_mx53_set_parent,
1398 .enable_reg = MXC_CCM_CCGR3,
1399 .enable_shift = MXC_CCM_CCGRx_CG7_OFFSET,
1400 .enable = _clk_max_enable,
1401 .disable = _clk_max_disable,
1402 .secondary = &esdhc4_ipg_clk,
1403};
1404
Richard Zhu97915bd2011-09-28 15:41:53 +08001405static struct clk sata_clk = {
1406 .parent = &ipg_clk,
1407 .enable = _clk_max_enable,
1408 .enable_reg = MXC_CCM_CCGR4,
1409 .enable_shift = MXC_CCM_CCGRx_CG1_OFFSET,
1410 .disable = _clk_max_disable,
1411};
1412
1413static struct clk ahci_phy_clk = {
1414 .parent = &usb_phy1_clk,
1415};
1416
1417static struct clk ahci_dma_clk = {
1418 .parent = &ahb_clk,
1419};
1420
Sascha Hauerb8481692010-12-06 09:13:21 +01001421DEFINE_CLOCK(mipi_esc_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG5_OFFSET, NULL, NULL, NULL, &pll2_sw_clk);
1422DEFINE_CLOCK(mipi_hsc2_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG4_OFFSET, NULL, NULL, &mipi_esc_clk, &pll2_sw_clk);
1423DEFINE_CLOCK(mipi_hsc1_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG3_OFFSET, NULL, NULL, &mipi_hsc2_clk, &pll2_sw_clk);
1424
1425/* IPU */
1426DEFINE_CLOCK_FULL(ipu_clk, 0, MXC_CCM_CCGR5, MXC_CCM_CCGRx_CG5_OFFSET,
1427 NULL, NULL, clk_ipu_enable, clk_ipu_disable, &ahb_clk, &ipu_sec_clk);
1428
1429DEFINE_CLOCK_FULL(emi_fast_clk, 0, MXC_CCM_CCGR5, MXC_CCM_CCGRx_CG7_OFFSET,
1430 NULL, NULL, _clk_ccgr_enable, _clk_ccgr_disable_inwait,
1431 &ddr_clk, NULL);
1432
1433DEFINE_CLOCK(ipu_di0_clk, 0, MXC_CCM_CCGR6, MXC_CCM_CCGRx_CG5_OFFSET,
1434 NULL, NULL, &pll3_sw_clk, NULL);
1435DEFINE_CLOCK(ipu_di1_clk, 0, MXC_CCM_CCGR6, MXC_CCM_CCGRx_CG6_OFFSET,
1436 NULL, NULL, &pll3_sw_clk, NULL);
1437
Arnaud Patard (Rtp)5bc59bf2011-07-26 16:54:26 +02001438/* PATA */
1439DEFINE_CLOCK(pata_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG0_OFFSET,
1440 NULL, NULL, &ipg_clk, &spba_clk);
1441
Amit Kucheriaa329b482010-02-04 12:21:53 -08001442#define _REGISTER_CLOCK(d, n, c) \
1443 { \
1444 .dev_id = d, \
1445 .con_id = n, \
1446 .clk = &c, \
1447 },
1448
Dinh Nguyenc0abefd2010-11-15 11:29:59 -06001449static struct clk_lookup mx51_lookups[] = {
Shawn Guofe6b5402011-06-25 02:04:33 +08001450 /* i.mx51 has the i.mx21 type uart */
1451 _REGISTER_CLOCK("imx21-uart.0", NULL, uart1_clk)
1452 _REGISTER_CLOCK("imx21-uart.1", NULL, uart2_clk)
1453 _REGISTER_CLOCK("imx21-uart.2", NULL, uart3_clk)
Amit Kucheriaa329b482010-02-04 12:21:53 -08001454 _REGISTER_CLOCK(NULL, "gpt", gpt_clk)
Shawn Guo0ca1e292011-07-01 18:11:22 +08001455 /* i.mx51 has the i.mx27 type fec */
1456 _REGISTER_CLOCK("imx27-fec.0", NULL, fec_clk)
Arnaud Patard (Rtp)dd027b02011-01-13 12:26:40 +01001457 _REGISTER_CLOCK("mxc_pwm.0", "pwm", pwm1_clk)
1458 _REGISTER_CLOCK("mxc_pwm.1", "pwm", pwm2_clk)
Dinh Nguyen71c2e512010-05-27 10:45:04 -05001459 _REGISTER_CLOCK("imx-i2c.0", NULL, i2c1_clk)
1460 _REGISTER_CLOCK("imx-i2c.1", NULL, i2c2_clk)
1461 _REGISTER_CLOCK("imx-i2c.2", NULL, hsi2c_clk)
Dinh Nguyenc53bdf12010-04-30 15:48:24 -05001462 _REGISTER_CLOCK("mxc-ehci.0", "usb", usboh3_clk)
Arnaud Patard (Rtp)711669e2010-12-20 16:48:58 +01001463 _REGISTER_CLOCK("mxc-ehci.0", "usb_ahb", usb_ahb_clk)
1464 _REGISTER_CLOCK("mxc-ehci.0", "usb_phy1", usb_phy1_clk)
Dinh Nguyenc53bdf12010-04-30 15:48:24 -05001465 _REGISTER_CLOCK("mxc-ehci.1", "usb", usboh3_clk)
Arnaud Patard (Rtp)711669e2010-12-20 16:48:58 +01001466 _REGISTER_CLOCK("mxc-ehci.1", "usb_ahb", usb_ahb_clk)
1467 _REGISTER_CLOCK("mxc-ehci.2", "usb", usboh3_clk)
1468 _REGISTER_CLOCK("mxc-ehci.2", "usb_ahb", usb_ahb_clk)
Dinh Nguyen2ba5a2c2010-05-10 13:45:59 -05001469 _REGISTER_CLOCK("fsl-usb2-udc", "usb", usboh3_clk)
1470 _REGISTER_CLOCK("fsl-usb2-udc", "usb_ahb", ahb_clk)
Fabio Estevambb58b3e2011-01-19 10:27:33 -02001471 _REGISTER_CLOCK("imx-keypad", NULL, dummy_clk)
Sascha Hauer2b82e642010-08-03 11:59:07 +02001472 _REGISTER_CLOCK("mxc_nand", NULL, nfc_clk)
Sascha Hauerb8618662010-08-20 16:43:54 +02001473 _REGISTER_CLOCK("imx-ssi.0", NULL, ssi1_clk)
1474 _REGISTER_CLOCK("imx-ssi.1", NULL, ssi2_clk)
Peter Hortonf2597222010-12-03 17:07:28 +00001475 _REGISTER_CLOCK("imx-ssi.2", NULL, ssi3_clk)
Shawn Guo62550cd2011-07-13 21:33:17 +08001476 /* i.mx51 has the i.mx35 type sdma */
1477 _REGISTER_CLOCK("imx35-sdma", NULL, sdma_clk)
Sascha Hauer8f6e9002010-08-25 11:56:26 +02001478 _REGISTER_CLOCK(NULL, "ckih", ckih_clk)
1479 _REGISTER_CLOCK(NULL, "ckih2", ckih2_clk)
1480 _REGISTER_CLOCK(NULL, "gpt_32k", gpt_32k_clk)
Jason Wang8d83db82010-09-02 15:52:00 +08001481 _REGISTER_CLOCK("imx51-ecspi.0", NULL, ecspi1_clk)
1482 _REGISTER_CLOCK("imx51-ecspi.1", NULL, ecspi2_clk)
Shawn Guo04ee5852011-07-10 01:16:39 +08001483 /* i.mx51 has the i.mx35 type cspi */
1484 _REGISTER_CLOCK("imx35-cspi.0", NULL, cspi_clk)
Shawn Guo57ed3312011-06-30 09:24:26 +08001485 _REGISTER_CLOCK("sdhci-esdhc-imx51.0", NULL, esdhc1_clk)
1486 _REGISTER_CLOCK("sdhci-esdhc-imx51.1", NULL, esdhc2_clk)
1487 _REGISTER_CLOCK("sdhci-esdhc-imx51.2", NULL, esdhc3_clk)
1488 _REGISTER_CLOCK("sdhci-esdhc-imx51.3", NULL, esdhc4_clk)
Yong Shen64f102b2010-10-21 21:18:59 +08001489 _REGISTER_CLOCK(NULL, "cpu_clk", cpu_clk)
Dinh Nguyen9ab46502010-11-15 11:30:01 -06001490 _REGISTER_CLOCK(NULL, "iim_clk", iim_clk)
Fabio Estevam2c1f4672010-12-07 14:16:04 -02001491 _REGISTER_CLOCK("imx2-wdt.0", NULL, dummy_clk)
1492 _REGISTER_CLOCK("imx2-wdt.1", NULL, dummy_clk)
Sascha Hauerb8481692010-12-06 09:13:21 +01001493 _REGISTER_CLOCK(NULL, "mipi_hsp", mipi_hsp_clk)
1494 _REGISTER_CLOCK("imx-ipuv3", NULL, ipu_clk)
1495 _REGISTER_CLOCK("imx-ipuv3", "di0", ipu_di0_clk)
1496 _REGISTER_CLOCK("imx-ipuv3", "di1", ipu_di1_clk)
Dinh Nguyenb6e89b22011-03-21 16:30:36 -05001497 _REGISTER_CLOCK(NULL, "gpc_dvfs", gpc_dvfs_clk)
Arnaud Patard (Rtp)5bc59bf2011-07-26 16:54:26 +02001498 _REGISTER_CLOCK("pata_imx", NULL, pata_clk)
Amit Kucheriaa329b482010-02-04 12:21:53 -08001499};
1500
Dinh Nguyenc0abefd2010-11-15 11:29:59 -06001501static struct clk_lookup mx53_lookups[] = {
Shawn Guofe6b5402011-06-25 02:04:33 +08001502 /* i.mx53 has the i.mx21 type uart */
1503 _REGISTER_CLOCK("imx21-uart.0", NULL, uart1_clk)
1504 _REGISTER_CLOCK("imx21-uart.1", NULL, uart2_clk)
1505 _REGISTER_CLOCK("imx21-uart.2", NULL, uart3_clk)
1506 _REGISTER_CLOCK("imx21-uart.3", NULL, uart4_clk)
1507 _REGISTER_CLOCK("imx21-uart.4", NULL, uart5_clk)
Dinh Nguyenc0abefd2010-11-15 11:29:59 -06001508 _REGISTER_CLOCK(NULL, "gpt", gpt_clk)
Shawn Guo0ca1e292011-07-01 18:11:22 +08001509 /* i.mx53 has the i.mx25 type fec */
1510 _REGISTER_CLOCK("imx25-fec.0", NULL, fec_clk)
Dinh Nguyen9ab46502010-11-15 11:30:01 -06001511 _REGISTER_CLOCK(NULL, "iim_clk", iim_clk)
Yong Shen0d7671e2011-01-07 12:25:33 +08001512 _REGISTER_CLOCK("imx-i2c.0", NULL, i2c1_clk)
1513 _REGISTER_CLOCK("imx-i2c.1", NULL, i2c2_clk)
Andre Silvab6a14472011-06-22 16:33:04 -03001514 _REGISTER_CLOCK("imx-i2c.2", NULL, i2c3_mx53_clk)
Shawn Guo04ee5852011-07-10 01:16:39 +08001515 /* i.mx53 has the i.mx51 type ecspi */
1516 _REGISTER_CLOCK("imx51-ecspi.0", NULL, ecspi1_clk)
1517 _REGISTER_CLOCK("imx51-ecspi.1", NULL, ecspi2_clk)
1518 /* i.mx53 has the i.mx25 type cspi */
1519 _REGISTER_CLOCK("imx35-cspi.0", NULL, cspi_clk)
Shawn Guo57ed3312011-06-30 09:24:26 +08001520 _REGISTER_CLOCK("sdhci-esdhc-imx53.0", NULL, esdhc1_clk)
1521 _REGISTER_CLOCK("sdhci-esdhc-imx53.1", NULL, esdhc2_mx53_clk)
1522 _REGISTER_CLOCK("sdhci-esdhc-imx53.2", NULL, esdhc3_mx53_clk)
1523 _REGISTER_CLOCK("sdhci-esdhc-imx53.3", NULL, esdhc4_mx53_clk)
Fabio Estevam78c73592011-02-17 18:09:52 -02001524 _REGISTER_CLOCK("imx2-wdt.0", NULL, dummy_clk)
1525 _REGISTER_CLOCK("imx2-wdt.1", NULL, dummy_clk)
Shawn Guo62550cd2011-07-13 21:33:17 +08001526 /* i.mx53 has the i.mx35 type sdma */
1527 _REGISTER_CLOCK("imx35-sdma", NULL, sdma_clk)
Fabio Estevame1fb61e2011-06-27 17:12:09 -03001528 _REGISTER_CLOCK("imx-ssi.0", NULL, ssi1_clk)
1529 _REGISTER_CLOCK("imx-ssi.1", NULL, ssi2_clk)
1530 _REGISTER_CLOCK("imx-ssi.2", NULL, ssi3_clk)
Fabio Estevam22785de2011-06-27 17:12:11 -03001531 _REGISTER_CLOCK("imx-keypad", NULL, dummy_clk)
Fabio Estevam03b20b02011-08-23 17:18:07 -03001532 _REGISTER_CLOCK("pata_imx", NULL, pata_clk)
Richard Zhu97915bd2011-09-28 15:41:53 +08001533 _REGISTER_CLOCK("imx53-ahci.0", "ahci", sata_clk)
1534 _REGISTER_CLOCK("imx53-ahci.0", "ahci_phy", ahci_phy_clk)
1535 _REGISTER_CLOCK("imx53-ahci.0", "ahci_dma", ahci_dma_clk)
Amit Kucheriaa329b482010-02-04 12:21:53 -08001536};
1537
1538static void clk_tree_init(void)
1539{
1540 u32 reg;
1541
1542 ipg_perclk.set_parent(&ipg_perclk, &lp_apm_clk);
1543
1544 /*
1545 * Initialise the IPG PER CLK dividers to 3. IPG_PER_CLK should be at
1546 * 8MHz, its derived from lp_apm.
1547 *
1548 * FIXME: Verify if true for all boards
1549 */
1550 reg = __raw_readl(MXC_CCM_CBCDR);
1551 reg &= ~MXC_CCM_CBCDR_PERCLK_PRED1_MASK;
1552 reg &= ~MXC_CCM_CBCDR_PERCLK_PRED2_MASK;
1553 reg &= ~MXC_CCM_CBCDR_PERCLK_PODF_MASK;
1554 reg |= (2 << MXC_CCM_CBCDR_PERCLK_PRED1_OFFSET);
1555 __raw_writel(reg, MXC_CCM_CBCDR);
1556}
1557
1558int __init mx51_clocks_init(unsigned long ckil, unsigned long osc,
1559 unsigned long ckih1, unsigned long ckih2)
1560{
1561 int i;
1562
1563 external_low_reference = ckil;
1564 external_high_reference = ckih1;
1565 ckih2_reference = ckih2;
1566 oscillator_reference = osc;
1567
Dinh Nguyenc0abefd2010-11-15 11:29:59 -06001568 for (i = 0; i < ARRAY_SIZE(mx51_lookups); i++)
1569 clkdev_add(&mx51_lookups[i]);
Amit Kucheriaa329b482010-02-04 12:21:53 -08001570
1571 clk_tree_init();
1572
1573 clk_enable(&cpu_clk);
1574 clk_enable(&main_bus_clk);
1575
Dinh Nguyen9ab46502010-11-15 11:30:01 -06001576 clk_enable(&iim_clk);
Jason Liuc52c9832011-08-26 13:35:23 +08001577 imx_print_silicon_rev("i.MX51", mx51_revision());
Dinh Nguyen9ab46502010-11-15 11:30:01 -06001578 clk_disable(&iim_clk);
1579
Arnaud Patard (Rtp)711669e2010-12-20 16:48:58 +01001580 /* move usb_phy_clk to 24MHz */
1581 clk_set_parent(&usb_phy1_clk, &osc_clk);
1582
Dinh Nguyenc79504e2010-05-10 13:45:58 -05001583 /* set the usboh3_clk parent to pll2_sw_clk */
1584 clk_set_parent(&usboh3_clk, &pll2_sw_clk);
1585
Eric Bénard6a001b82010-10-11 17:59:47 +02001586 /* Set SDHC parents to be PLL2 */
1587 clk_set_parent(&esdhc1_clk, &pll2_sw_clk);
1588 clk_set_parent(&esdhc2_clk, &pll2_sw_clk);
1589
1590 /* set SDHC root clock as 166.25MHZ*/
1591 clk_set_rate(&esdhc1_clk, 166250000);
1592 clk_set_rate(&esdhc2_clk, 166250000);
1593
Amit Kucheriaa329b482010-02-04 12:21:53 -08001594 /* System timer */
1595 mxc_timer_init(&gpt_clk, MX51_IO_ADDRESS(MX51_GPT1_BASE_ADDR),
Uwe Kleine-König1a195272011-07-25 12:05:09 +02001596 MX51_INT_GPT);
Amit Kucheriaa329b482010-02-04 12:21:53 -08001597 return 0;
1598}
Dinh Nguyenc0abefd2010-11-15 11:29:59 -06001599
1600int __init mx53_clocks_init(unsigned long ckil, unsigned long osc,
1601 unsigned long ckih1, unsigned long ckih2)
1602{
1603 int i;
1604
1605 external_low_reference = ckil;
1606 external_high_reference = ckih1;
1607 ckih2_reference = ckih2;
1608 oscillator_reference = osc;
1609
1610 for (i = 0; i < ARRAY_SIZE(mx53_lookups); i++)
1611 clkdev_add(&mx53_lookups[i]);
1612
1613 clk_tree_init();
1614
Yong Shen2cad26a2011-01-10 20:08:54 +08001615 clk_set_parent(&uart_root_clk, &pll3_sw_clk);
Dinh Nguyenc0abefd2010-11-15 11:29:59 -06001616 clk_enable(&cpu_clk);
1617 clk_enable(&main_bus_clk);
1618
Dinh Nguyen9ab46502010-11-15 11:30:01 -06001619 clk_enable(&iim_clk);
Jason Liuc52c9832011-08-26 13:35:23 +08001620 imx_print_silicon_rev("i.MX53", mx53_revision());
Dinh Nguyen9ab46502010-11-15 11:30:01 -06001621 clk_disable(&iim_clk);
1622
Richard Zhu35921902011-02-28 19:32:03 +08001623 /* Set SDHC parents to be PLL2 */
1624 clk_set_parent(&esdhc1_clk, &pll2_sw_clk);
1625 clk_set_parent(&esdhc3_mx53_clk, &pll2_sw_clk);
1626
1627 /* set SDHC root clock as 200MHZ*/
1628 clk_set_rate(&esdhc1_clk, 200000000);
1629 clk_set_rate(&esdhc3_mx53_clk, 200000000);
1630
Dinh Nguyenc0abefd2010-11-15 11:29:59 -06001631 /* System timer */
1632 mxc_timer_init(&gpt_clk, MX53_IO_ADDRESS(MX53_GPT1_BASE_ADDR),
1633 MX53_INT_GPT);
1634 return 0;
1635}
Shawn Guo73d2b4c2011-10-17 08:42:16 +08001636
Jason Liu188d7c62011-11-03 17:31:27 +08001637#ifdef CONFIG_OF
Shawn Guo73d2b4c2011-10-17 08:42:16 +08001638static void __init clk_get_freq_dt(unsigned long *ckil, unsigned long *osc,
1639 unsigned long *ckih1, unsigned long *ckih2)
1640{
1641 struct device_node *np;
1642
1643 /* retrieve the freqency of fixed clocks from device tree */
1644 for_each_compatible_node(np, NULL, "fixed-clock") {
1645 u32 rate;
1646 if (of_property_read_u32(np, "clock-frequency", &rate))
1647 continue;
1648
1649 if (of_device_is_compatible(np, "fsl,imx-ckil"))
1650 *ckil = rate;
1651 else if (of_device_is_compatible(np, "fsl,imx-osc"))
1652 *osc = rate;
1653 else if (of_device_is_compatible(np, "fsl,imx-ckih1"))
1654 *ckih1 = rate;
1655 else if (of_device_is_compatible(np, "fsl,imx-ckih2"))
1656 *ckih2 = rate;
1657 }
1658}
1659
Shawn Guo9daaf312011-10-17 08:42:17 +08001660int __init mx51_clocks_init_dt(void)
1661{
1662 unsigned long ckil, osc, ckih1, ckih2;
1663
1664 clk_get_freq_dt(&ckil, &osc, &ckih1, &ckih2);
1665 return mx51_clocks_init(ckil, osc, ckih1, ckih2);
1666}
1667
Shawn Guo73d2b4c2011-10-17 08:42:16 +08001668int __init mx53_clocks_init_dt(void)
1669{
1670 unsigned long ckil, osc, ckih1, ckih2;
1671
1672 clk_get_freq_dt(&ckil, &osc, &ckih1, &ckih2);
1673 return mx53_clocks_init(ckil, osc, ckih1, ckih2);
1674}
Jason Liu188d7c62011-11-03 17:31:27 +08001675#endif