diff options
Diffstat (limited to 'arch/arm/mach-imx/clock-imx27.c')
-rw-r--r-- | arch/arm/mach-imx/clock-imx27.c | 763 |
1 files changed, 763 insertions, 0 deletions
diff --git a/arch/arm/mach-imx/clock-imx27.c b/arch/arm/mach-imx/clock-imx27.c new file mode 100644 index 000000000000..5a1aa15c8a16 --- /dev/null +++ b/arch/arm/mach-imx/clock-imx27.c | |||
@@ -0,0 +1,763 @@ | |||
1 | /* | ||
2 | * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved. | ||
3 | * Copyright 2008 Juergen Beisert, kernel@pengutronix.de | ||
4 | * Copyright 2008 Martin Fuzzey, mfuzzey@gmail.com | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License | ||
8 | * as published by the Free Software Foundation; either version 2 | ||
9 | * of the License, or (at your option) any later version. | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, | ||
18 | * MA 02110-1301, USA. | ||
19 | */ | ||
20 | |||
21 | #include <linux/clk.h> | ||
22 | #include <linux/io.h> | ||
23 | #include <linux/module.h> | ||
24 | |||
25 | #include <asm/clkdev.h> | ||
26 | #include <asm/div64.h> | ||
27 | |||
28 | #include <mach/clock.h> | ||
29 | #include <mach/common.h> | ||
30 | #include <mach/hardware.h> | ||
31 | |||
32 | #define IO_ADDR_CCM(off) (MX27_IO_ADDRESS(MX27_CCM_BASE_ADDR + (off))) | ||
33 | |||
34 | /* Register offsets */ | ||
35 | #define CCM_CSCR IO_ADDR_CCM(0x0) | ||
36 | #define CCM_MPCTL0 IO_ADDR_CCM(0x4) | ||
37 | #define CCM_MPCTL1 IO_ADDR_CCM(0x8) | ||
38 | #define CCM_SPCTL0 IO_ADDR_CCM(0xc) | ||
39 | #define CCM_SPCTL1 IO_ADDR_CCM(0x10) | ||
40 | #define CCM_OSC26MCTL IO_ADDR_CCM(0x14) | ||
41 | #define CCM_PCDR0 IO_ADDR_CCM(0x18) | ||
42 | #define CCM_PCDR1 IO_ADDR_CCM(0x1c) | ||
43 | #define CCM_PCCR0 IO_ADDR_CCM(0x20) | ||
44 | #define CCM_PCCR1 IO_ADDR_CCM(0x24) | ||
45 | #define CCM_CCSR IO_ADDR_CCM(0x28) | ||
46 | #define CCM_PMCTL IO_ADDR_CCM(0x2c) | ||
47 | #define CCM_PMCOUNT IO_ADDR_CCM(0x30) | ||
48 | #define CCM_WKGDCTL IO_ADDR_CCM(0x34) | ||
49 | |||
50 | #define CCM_CSCR_UPDATE_DIS (1 << 31) | ||
51 | #define CCM_CSCR_SSI2 (1 << 23) | ||
52 | #define CCM_CSCR_SSI1 (1 << 22) | ||
53 | #define CCM_CSCR_VPU (1 << 21) | ||
54 | #define CCM_CSCR_MSHC (1 << 20) | ||
55 | #define CCM_CSCR_SPLLRES (1 << 19) | ||
56 | #define CCM_CSCR_MPLLRES (1 << 18) | ||
57 | #define CCM_CSCR_SP (1 << 17) | ||
58 | #define CCM_CSCR_MCU (1 << 16) | ||
59 | #define CCM_CSCR_OSC26MDIV (1 << 4) | ||
60 | #define CCM_CSCR_OSC26M (1 << 3) | ||
61 | #define CCM_CSCR_FPM (1 << 2) | ||
62 | #define CCM_CSCR_SPEN (1 << 1) | ||
63 | #define CCM_CSCR_MPEN (1 << 0) | ||
64 | |||
65 | /* i.MX27 TO 2+ */ | ||
66 | #define CCM_CSCR_ARM_SRC (1 << 15) | ||
67 | |||
68 | #define CCM_SPCTL1_LF (1 << 15) | ||
69 | #define CCM_SPCTL1_BRMO (1 << 6) | ||
70 | |||
71 | static struct clk mpll_main1_clk, mpll_main2_clk; | ||
72 | |||
73 | static int clk_pccr_enable(struct clk *clk) | ||
74 | { | ||
75 | unsigned long reg; | ||
76 | |||
77 | if (!clk->enable_reg) | ||
78 | return 0; | ||
79 | |||
80 | reg = __raw_readl(clk->enable_reg); | ||
81 | reg |= 1 << clk->enable_shift; | ||
82 | __raw_writel(reg, clk->enable_reg); | ||
83 | |||
84 | return 0; | ||
85 | } | ||
86 | |||
87 | static void clk_pccr_disable(struct clk *clk) | ||
88 | { | ||
89 | unsigned long reg; | ||
90 | |||
91 | if (!clk->enable_reg) | ||
92 | return; | ||
93 | |||
94 | reg = __raw_readl(clk->enable_reg); | ||
95 | reg &= ~(1 << clk->enable_shift); | ||
96 | __raw_writel(reg, clk->enable_reg); | ||
97 | } | ||
98 | |||
99 | static int clk_spll_enable(struct clk *clk) | ||
100 | { | ||
101 | unsigned long reg; | ||
102 | |||
103 | reg = __raw_readl(CCM_CSCR); | ||
104 | reg |= CCM_CSCR_SPEN; | ||
105 | __raw_writel(reg, CCM_CSCR); | ||
106 | |||
107 | while (!(__raw_readl(CCM_SPCTL1) & CCM_SPCTL1_LF)); | ||
108 | |||
109 | return 0; | ||
110 | } | ||
111 | |||
112 | static void clk_spll_disable(struct clk *clk) | ||
113 | { | ||
114 | unsigned long reg; | ||
115 | |||
116 | reg = __raw_readl(CCM_CSCR); | ||
117 | reg &= ~CCM_CSCR_SPEN; | ||
118 | __raw_writel(reg, CCM_CSCR); | ||
119 | } | ||
120 | |||
121 | static int clk_cpu_set_parent(struct clk *clk, struct clk *parent) | ||
122 | { | ||
123 | int cscr = __raw_readl(CCM_CSCR); | ||
124 | |||
125 | if (clk->parent == parent) | ||
126 | return 0; | ||
127 | |||
128 | if (mx27_revision() >= CHIP_REV_2_0) { | ||
129 | if (parent == &mpll_main1_clk) { | ||
130 | cscr |= CCM_CSCR_ARM_SRC; | ||
131 | } else { | ||
132 | if (parent == &mpll_main2_clk) | ||
133 | cscr &= ~CCM_CSCR_ARM_SRC; | ||
134 | else | ||
135 | return -EINVAL; | ||
136 | } | ||
137 | __raw_writel(cscr, CCM_CSCR); | ||
138 | clk->parent = parent; | ||
139 | return 0; | ||
140 | } | ||
141 | return -ENODEV; | ||
142 | } | ||
143 | |||
144 | static unsigned long round_rate_cpu(struct clk *clk, unsigned long rate) | ||
145 | { | ||
146 | int div; | ||
147 | unsigned long parent_rate; | ||
148 | |||
149 | parent_rate = clk_get_rate(clk->parent); | ||
150 | |||
151 | div = parent_rate / rate; | ||
152 | if (parent_rate % rate) | ||
153 | div++; | ||
154 | |||
155 | if (div > 4) | ||
156 | div = 4; | ||
157 | |||
158 | return parent_rate / div; | ||
159 | } | ||
160 | |||
161 | static int set_rate_cpu(struct clk *clk, unsigned long rate) | ||
162 | { | ||
163 | unsigned int div; | ||
164 | uint32_t reg; | ||
165 | unsigned long parent_rate; | ||
166 | |||
167 | parent_rate = clk_get_rate(clk->parent); | ||
168 | |||
169 | div = parent_rate / rate; | ||
170 | |||
171 | if (div > 4 || div < 1 || ((parent_rate / div) != rate)) | ||
172 | return -EINVAL; | ||
173 | |||
174 | div--; | ||
175 | |||
176 | reg = __raw_readl(CCM_CSCR); | ||
177 | if (mx27_revision() >= CHIP_REV_2_0) { | ||
178 | reg &= ~(3 << 12); | ||
179 | reg |= div << 12; | ||
180 | reg &= ~(CCM_CSCR_FPM | CCM_CSCR_SPEN); | ||
181 | __raw_writel(reg | CCM_CSCR_UPDATE_DIS, CCM_CSCR); | ||
182 | } else { | ||
183 | printk(KERN_ERR "Can't set CPU frequency!\n"); | ||
184 | } | ||
185 | |||
186 | return 0; | ||
187 | } | ||
188 | |||
189 | static unsigned long round_rate_per(struct clk *clk, unsigned long rate) | ||
190 | { | ||
191 | u32 div; | ||
192 | unsigned long parent_rate; | ||
193 | |||
194 | parent_rate = clk_get_rate(clk->parent); | ||
195 | |||
196 | div = parent_rate / rate; | ||
197 | if (parent_rate % rate) | ||
198 | div++; | ||
199 | |||
200 | if (div > 64) | ||
201 | div = 64; | ||
202 | |||
203 | return parent_rate / div; | ||
204 | } | ||
205 | |||
206 | static int set_rate_per(struct clk *clk, unsigned long rate) | ||
207 | { | ||
208 | u32 reg; | ||
209 | u32 div; | ||
210 | unsigned long parent_rate; | ||
211 | |||
212 | parent_rate = clk_get_rate(clk->parent); | ||
213 | |||
214 | if (clk->id < 0 || clk->id > 3) | ||
215 | return -EINVAL; | ||
216 | |||
217 | div = parent_rate / rate; | ||
218 | if (div > 64 || div < 1 || ((parent_rate / div) != rate)) | ||
219 | return -EINVAL; | ||
220 | div--; | ||
221 | |||
222 | reg = __raw_readl(CCM_PCDR1) & ~(0x3f << (clk->id << 3)); | ||
223 | reg |= div << (clk->id << 3); | ||
224 | __raw_writel(reg, CCM_PCDR1); | ||
225 | |||
226 | return 0; | ||
227 | } | ||
228 | |||
229 | static unsigned long get_rate_usb(struct clk *clk) | ||
230 | { | ||
231 | unsigned long usb_pdf; | ||
232 | unsigned long parent_rate; | ||
233 | |||
234 | parent_rate = clk_get_rate(clk->parent); | ||
235 | |||
236 | usb_pdf = (__raw_readl(CCM_CSCR) >> 28) & 0x7; | ||
237 | |||
238 | return parent_rate / (usb_pdf + 1U); | ||
239 | } | ||
240 | |||
241 | static unsigned long get_rate_ssix(struct clk *clk, unsigned long pdf) | ||
242 | { | ||
243 | unsigned long parent_rate; | ||
244 | |||
245 | parent_rate = clk_get_rate(clk->parent); | ||
246 | |||
247 | if (mx27_revision() >= CHIP_REV_2_0) | ||
248 | pdf += 4; /* MX27 TO2+ */ | ||
249 | else | ||
250 | pdf = (pdf < 2) ? 124UL : pdf; /* MX21 & MX27 TO1 */ | ||
251 | |||
252 | return 2UL * parent_rate / pdf; | ||
253 | } | ||
254 | |||
255 | static unsigned long get_rate_ssi1(struct clk *clk) | ||
256 | { | ||
257 | return get_rate_ssix(clk, (__raw_readl(CCM_PCDR0) >> 16) & 0x3f); | ||
258 | } | ||
259 | |||
260 | static unsigned long get_rate_ssi2(struct clk *clk) | ||
261 | { | ||
262 | return get_rate_ssix(clk, (__raw_readl(CCM_PCDR0) >> 26) & 0x3f); | ||
263 | } | ||
264 | |||
265 | static unsigned long get_rate_nfc(struct clk *clk) | ||
266 | { | ||
267 | unsigned long nfc_pdf; | ||
268 | unsigned long parent_rate; | ||
269 | |||
270 | parent_rate = clk_get_rate(clk->parent); | ||
271 | |||
272 | if (mx27_revision() >= CHIP_REV_2_0) | ||
273 | nfc_pdf = (__raw_readl(CCM_PCDR0) >> 6) & 0xf; | ||
274 | else | ||
275 | nfc_pdf = (__raw_readl(CCM_PCDR0) >> 12) & 0xf; | ||
276 | |||
277 | return parent_rate / (nfc_pdf + 1); | ||
278 | } | ||
279 | |||
280 | static unsigned long get_rate_vpu(struct clk *clk) | ||
281 | { | ||
282 | unsigned long vpu_pdf; | ||
283 | unsigned long parent_rate; | ||
284 | |||
285 | parent_rate = clk_get_rate(clk->parent); | ||
286 | |||
287 | if (mx27_revision() >= CHIP_REV_2_0) { | ||
288 | vpu_pdf = (__raw_readl(CCM_PCDR0) >> 10) & 0x3f; | ||
289 | vpu_pdf += 4; | ||
290 | } else { | ||
291 | vpu_pdf = (__raw_readl(CCM_PCDR0) >> 8) & 0xf; | ||
292 | vpu_pdf = (vpu_pdf < 2) ? 124 : vpu_pdf; | ||
293 | } | ||
294 | |||
295 | return 2UL * parent_rate / vpu_pdf; | ||
296 | } | ||
297 | |||
298 | static unsigned long round_rate_parent(struct clk *clk, unsigned long rate) | ||
299 | { | ||
300 | return clk->parent->round_rate(clk->parent, rate); | ||
301 | } | ||
302 | |||
303 | static unsigned long get_rate_parent(struct clk *clk) | ||
304 | { | ||
305 | return clk_get_rate(clk->parent); | ||
306 | } | ||
307 | |||
308 | static int set_rate_parent(struct clk *clk, unsigned long rate) | ||
309 | { | ||
310 | return clk->parent->set_rate(clk->parent, rate); | ||
311 | } | ||
312 | |||
313 | /* in Hz */ | ||
314 | static unsigned long external_high_reference = 26000000; | ||
315 | |||
316 | static unsigned long get_rate_high_reference(struct clk *clk) | ||
317 | { | ||
318 | return external_high_reference; | ||
319 | } | ||
320 | |||
321 | /* in Hz */ | ||
322 | static unsigned long external_low_reference = 32768; | ||
323 | |||
324 | static unsigned long get_rate_low_reference(struct clk *clk) | ||
325 | { | ||
326 | return external_low_reference; | ||
327 | } | ||
328 | |||
329 | static unsigned long get_rate_fpm(struct clk *clk) | ||
330 | { | ||
331 | return clk_get_rate(clk->parent) * 1024; | ||
332 | } | ||
333 | |||
334 | static unsigned long get_rate_mpll(struct clk *clk) | ||
335 | { | ||
336 | return mxc_decode_pll(__raw_readl(CCM_MPCTL0), | ||
337 | clk_get_rate(clk->parent)); | ||
338 | } | ||
339 | |||
340 | static unsigned long get_rate_mpll_main(struct clk *clk) | ||
341 | { | ||
342 | unsigned long parent_rate; | ||
343 | |||
344 | parent_rate = clk_get_rate(clk->parent); | ||
345 | |||
346 | /* i.MX27 TO2: | ||
347 | * clk->id == 0: arm clock source path 1 which is from 2 * MPLL / 2 | ||
348 | * clk->id == 1: arm clock source path 2 which is from 2 * MPLL / 3 | ||
349 | */ | ||
350 | if (mx27_revision() >= CHIP_REV_2_0 && clk->id == 1) | ||
351 | return 2UL * parent_rate / 3UL; | ||
352 | |||
353 | return parent_rate; | ||
354 | } | ||
355 | |||
356 | static unsigned long get_rate_spll(struct clk *clk) | ||
357 | { | ||
358 | uint32_t reg; | ||
359 | unsigned long rate; | ||
360 | |||
361 | rate = clk_get_rate(clk->parent); | ||
362 | |||
363 | reg = __raw_readl(CCM_SPCTL0); | ||
364 | |||
365 | /* On TO2 we have to write the value back. Otherwise we | ||
366 | * read 0 from this register the next time. | ||
367 | */ | ||
368 | if (mx27_revision() >= CHIP_REV_2_0) | ||
369 | __raw_writel(reg, CCM_SPCTL0); | ||
370 | |||
371 | return mxc_decode_pll(reg, rate); | ||
372 | } | ||
373 | |||
374 | static unsigned long get_rate_cpu(struct clk *clk) | ||
375 | { | ||
376 | u32 div; | ||
377 | unsigned long rate; | ||
378 | |||
379 | if (mx27_revision() >= CHIP_REV_2_0) | ||
380 | div = (__raw_readl(CCM_CSCR) >> 12) & 0x3; | ||
381 | else | ||
382 | div = (__raw_readl(CCM_CSCR) >> 13) & 0x7; | ||
383 | |||
384 | rate = clk_get_rate(clk->parent); | ||
385 | return rate / (div + 1); | ||
386 | } | ||
387 | |||
388 | static unsigned long get_rate_ahb(struct clk *clk) | ||
389 | { | ||
390 | unsigned long rate, bclk_pdf; | ||
391 | |||
392 | if (mx27_revision() >= CHIP_REV_2_0) | ||
393 | bclk_pdf = (__raw_readl(CCM_CSCR) >> 8) & 0x3; | ||
394 | else | ||
395 | bclk_pdf = (__raw_readl(CCM_CSCR) >> 9) & 0xf; | ||
396 | |||
397 | rate = clk_get_rate(clk->parent); | ||
398 | return rate / (bclk_pdf + 1); | ||
399 | } | ||
400 | |||
401 | static unsigned long get_rate_ipg(struct clk *clk) | ||
402 | { | ||
403 | unsigned long rate, ipg_pdf; | ||
404 | |||
405 | if (mx27_revision() >= CHIP_REV_2_0) | ||
406 | return clk_get_rate(clk->parent); | ||
407 | else | ||
408 | ipg_pdf = (__raw_readl(CCM_CSCR) >> 8) & 1; | ||
409 | |||
410 | rate = clk_get_rate(clk->parent); | ||
411 | return rate / (ipg_pdf + 1); | ||
412 | } | ||
413 | |||
414 | static unsigned long get_rate_per(struct clk *clk) | ||
415 | { | ||
416 | unsigned long perclk_pdf, parent_rate; | ||
417 | |||
418 | parent_rate = clk_get_rate(clk->parent); | ||
419 | |||
420 | if (clk->id < 0 || clk->id > 3) | ||
421 | return 0; | ||
422 | |||
423 | perclk_pdf = (__raw_readl(CCM_PCDR1) >> (clk->id << 3)) & 0x3f; | ||
424 | |||
425 | return parent_rate / (perclk_pdf + 1); | ||
426 | } | ||
427 | |||
428 | /* | ||
429 | * the high frequency external clock reference | ||
430 | * Default case is 26MHz. Could be changed at runtime | ||
431 | * with a call to change_external_high_reference() | ||
432 | */ | ||
433 | static struct clk ckih_clk = { | ||
434 | .get_rate = get_rate_high_reference, | ||
435 | }; | ||
436 | |||
437 | static struct clk mpll_clk = { | ||
438 | .parent = &ckih_clk, | ||
439 | .get_rate = get_rate_mpll, | ||
440 | }; | ||
441 | |||
442 | /* For i.MX27 TO2, it is the MPLL path 1 of ARM core | ||
443 | * It provides the clock source whose rate is same as MPLL | ||
444 | */ | ||
445 | static struct clk mpll_main1_clk = { | ||
446 | .id = 0, | ||
447 | .parent = &mpll_clk, | ||
448 | .get_rate = get_rate_mpll_main, | ||
449 | }; | ||
450 | |||
451 | /* For i.MX27 TO2, it is the MPLL path 2 of ARM core | ||
452 | * It provides the clock source whose rate is same MPLL * 2 / 3 | ||
453 | */ | ||
454 | static struct clk mpll_main2_clk = { | ||
455 | .id = 1, | ||
456 | .parent = &mpll_clk, | ||
457 | .get_rate = get_rate_mpll_main, | ||
458 | }; | ||
459 | |||
460 | static struct clk ahb_clk = { | ||
461 | .parent = &mpll_main2_clk, | ||
462 | .get_rate = get_rate_ahb, | ||
463 | }; | ||
464 | |||
465 | static struct clk ipg_clk = { | ||
466 | .parent = &ahb_clk, | ||
467 | .get_rate = get_rate_ipg, | ||
468 | }; | ||
469 | |||
470 | static struct clk cpu_clk = { | ||
471 | .parent = &mpll_main2_clk, | ||
472 | .set_parent = clk_cpu_set_parent, | ||
473 | .round_rate = round_rate_cpu, | ||
474 | .get_rate = get_rate_cpu, | ||
475 | .set_rate = set_rate_cpu, | ||
476 | }; | ||
477 | |||
478 | static struct clk spll_clk = { | ||
479 | .parent = &ckih_clk, | ||
480 | .get_rate = get_rate_spll, | ||
481 | .enable = clk_spll_enable, | ||
482 | .disable = clk_spll_disable, | ||
483 | }; | ||
484 | |||
485 | /* | ||
486 | * the low frequency external clock reference | ||
487 | * Default case is 32.768kHz. | ||
488 | */ | ||
489 | static struct clk ckil_clk = { | ||
490 | .get_rate = get_rate_low_reference, | ||
491 | }; | ||
492 | |||
493 | /* Output of frequency pre multiplier */ | ||
494 | static struct clk fpm_clk = { | ||
495 | .parent = &ckil_clk, | ||
496 | .get_rate = get_rate_fpm, | ||
497 | }; | ||
498 | |||
499 | #define PCCR0 CCM_PCCR0 | ||
500 | #define PCCR1 CCM_PCCR1 | ||
501 | |||
502 | #define DEFINE_CLOCK(name, i, er, es, gr, s, p) \ | ||
503 | static struct clk name = { \ | ||
504 | .id = i, \ | ||
505 | .enable_reg = er, \ | ||
506 | .enable_shift = es, \ | ||
507 | .get_rate = gr, \ | ||
508 | .enable = clk_pccr_enable, \ | ||
509 | .disable = clk_pccr_disable, \ | ||
510 | .secondary = s, \ | ||
511 | .parent = p, \ | ||
512 | } | ||
513 | |||
514 | #define DEFINE_CLOCK1(name, i, er, es, getsetround, s, p) \ | ||
515 | static struct clk name = { \ | ||
516 | .id = i, \ | ||
517 | .enable_reg = er, \ | ||
518 | .enable_shift = es, \ | ||
519 | .get_rate = get_rate_##getsetround, \ | ||
520 | .set_rate = set_rate_##getsetround, \ | ||
521 | .round_rate = round_rate_##getsetround, \ | ||
522 | .enable = clk_pccr_enable, \ | ||
523 | .disable = clk_pccr_disable, \ | ||
524 | .secondary = s, \ | ||
525 | .parent = p, \ | ||
526 | } | ||
527 | |||
528 | /* Forward declaration to keep the following list in order */ | ||
529 | static struct clk slcdc_clk1, sahara2_clk1, rtic_clk1, fec_clk1, emma_clk1, | ||
530 | dma_clk1, lcdc_clk2, vpu_clk1; | ||
531 | |||
532 | /* All clocks we can gate through PCCRx in the order of PCCRx bits */ | ||
533 | DEFINE_CLOCK(ssi2_clk1, 1, PCCR0, 0, NULL, NULL, &ipg_clk); | ||
534 | DEFINE_CLOCK(ssi1_clk1, 0, PCCR0, 1, NULL, NULL, &ipg_clk); | ||
535 | DEFINE_CLOCK(slcdc_clk, 0, PCCR0, 2, NULL, &slcdc_clk1, &ahb_clk); | ||
536 | DEFINE_CLOCK(sdhc3_clk1, 0, PCCR0, 3, NULL, NULL, &ipg_clk); | ||
537 | DEFINE_CLOCK(sdhc2_clk1, 0, PCCR0, 4, NULL, NULL, &ipg_clk); | ||
538 | DEFINE_CLOCK(sdhc1_clk1, 0, PCCR0, 5, NULL, NULL, &ipg_clk); | ||
539 | DEFINE_CLOCK(scc_clk, 0, PCCR0, 6, NULL, NULL, &ipg_clk); | ||
540 | DEFINE_CLOCK(sahara2_clk, 0, PCCR0, 7, NULL, &sahara2_clk1, &ahb_clk); | ||
541 | DEFINE_CLOCK(rtic_clk, 0, PCCR0, 8, NULL, &rtic_clk1, &ahb_clk); | ||
542 | DEFINE_CLOCK(rtc_clk, 0, PCCR0, 9, NULL, NULL, &ipg_clk); | ||
543 | DEFINE_CLOCK(pwm_clk1, 0, PCCR0, 11, NULL, NULL, &ipg_clk); | ||
544 | DEFINE_CLOCK(owire_clk, 0, PCCR0, 12, NULL, NULL, &ipg_clk); | ||
545 | DEFINE_CLOCK(mstick_clk1, 0, PCCR0, 13, NULL, NULL, &ipg_clk); | ||
546 | DEFINE_CLOCK(lcdc_clk1, 0, PCCR0, 14, NULL, &lcdc_clk2, &ipg_clk); | ||
547 | DEFINE_CLOCK(kpp_clk, 0, PCCR0, 15, NULL, NULL, &ipg_clk); | ||
548 | DEFINE_CLOCK(iim_clk, 0, PCCR0, 16, NULL, NULL, &ipg_clk); | ||
549 | DEFINE_CLOCK(i2c2_clk, 1, PCCR0, 17, NULL, NULL, &ipg_clk); | ||
550 | DEFINE_CLOCK(i2c1_clk, 0, PCCR0, 18, NULL, NULL, &ipg_clk); | ||
551 | DEFINE_CLOCK(gpt6_clk1, 0, PCCR0, 29, NULL, NULL, &ipg_clk); | ||
552 | DEFINE_CLOCK(gpt5_clk1, 0, PCCR0, 20, NULL, NULL, &ipg_clk); | ||
553 | DEFINE_CLOCK(gpt4_clk1, 0, PCCR0, 21, NULL, NULL, &ipg_clk); | ||
554 | DEFINE_CLOCK(gpt3_clk1, 0, PCCR0, 22, NULL, NULL, &ipg_clk); | ||
555 | DEFINE_CLOCK(gpt2_clk1, 0, PCCR0, 23, NULL, NULL, &ipg_clk); | ||
556 | DEFINE_CLOCK(gpt1_clk1, 0, PCCR0, 24, NULL, NULL, &ipg_clk); | ||
557 | DEFINE_CLOCK(gpio_clk, 0, PCCR0, 25, NULL, NULL, &ipg_clk); | ||
558 | DEFINE_CLOCK(fec_clk, 0, PCCR0, 26, NULL, &fec_clk1, &ahb_clk); | ||
559 | DEFINE_CLOCK(emma_clk, 0, PCCR0, 27, NULL, &emma_clk1, &ahb_clk); | ||
560 | DEFINE_CLOCK(dma_clk, 0, PCCR0, 28, NULL, &dma_clk1, &ahb_clk); | ||
561 | DEFINE_CLOCK(cspi13_clk1, 0, PCCR0, 29, NULL, NULL, &ipg_clk); | ||
562 | DEFINE_CLOCK(cspi2_clk1, 0, PCCR0, 30, NULL, NULL, &ipg_clk); | ||
563 | DEFINE_CLOCK(cspi1_clk1, 0, PCCR0, 31, NULL, NULL, &ipg_clk); | ||
564 | |||
565 | DEFINE_CLOCK(mstick_clk, 0, PCCR1, 2, NULL, &mstick_clk1, &ipg_clk); | ||
566 | DEFINE_CLOCK(nfc_clk, 0, PCCR1, 3, get_rate_nfc, NULL, &cpu_clk); | ||
567 | DEFINE_CLOCK(ssi2_clk, 1, PCCR1, 4, get_rate_ssi2, &ssi2_clk1, &mpll_main2_clk); | ||
568 | DEFINE_CLOCK(ssi1_clk, 0, PCCR1, 5, get_rate_ssi1, &ssi1_clk1, &mpll_main2_clk); | ||
569 | DEFINE_CLOCK(vpu_clk, 0, PCCR1, 6, get_rate_vpu, &vpu_clk1, &mpll_main2_clk); | ||
570 | DEFINE_CLOCK1(per4_clk, 3, PCCR1, 7, per, NULL, &mpll_main2_clk); | ||
571 | DEFINE_CLOCK1(per3_clk, 2, PCCR1, 8, per, NULL, &mpll_main2_clk); | ||
572 | DEFINE_CLOCK1(per2_clk, 1, PCCR1, 9, per, NULL, &mpll_main2_clk); | ||
573 | DEFINE_CLOCK1(per1_clk, 0, PCCR1, 10, per, NULL, &mpll_main2_clk); | ||
574 | DEFINE_CLOCK(usb_clk1, 0, PCCR1, 11, NULL, NULL, &ahb_clk); | ||
575 | DEFINE_CLOCK(slcdc_clk1, 0, PCCR1, 12, NULL, NULL, &ahb_clk); | ||
576 | DEFINE_CLOCK(sahara2_clk1, 0, PCCR1, 13, NULL, NULL, &ahb_clk); | ||
577 | DEFINE_CLOCK(rtic_clk1, 0, PCCR1, 14, NULL, NULL, &ahb_clk); | ||
578 | DEFINE_CLOCK(lcdc_clk2, 0, PCCR1, 15, NULL, NULL, &ahb_clk); | ||
579 | DEFINE_CLOCK(vpu_clk1, 0, PCCR1, 16, NULL, NULL, &ahb_clk); | ||
580 | DEFINE_CLOCK(fec_clk1, 0, PCCR1, 17, NULL, NULL, &ahb_clk); | ||
581 | DEFINE_CLOCK(emma_clk1, 0, PCCR1, 18, NULL, NULL, &ahb_clk); | ||
582 | DEFINE_CLOCK(emi_clk, 0, PCCR1, 19, NULL, NULL, &ahb_clk); | ||
583 | DEFINE_CLOCK(dma_clk1, 0, PCCR1, 20, NULL, NULL, &ahb_clk); | ||
584 | DEFINE_CLOCK(csi_clk1, 0, PCCR1, 21, NULL, NULL, &ahb_clk); | ||
585 | DEFINE_CLOCK(brom_clk, 0, PCCR1, 22, NULL, NULL, &ahb_clk); | ||
586 | DEFINE_CLOCK(ata_clk, 0, PCCR1, 23, NULL, NULL, &ahb_clk); | ||
587 | DEFINE_CLOCK(wdog_clk, 0, PCCR1, 24, NULL, NULL, &ipg_clk); | ||
588 | DEFINE_CLOCK(usb_clk, 0, PCCR1, 25, get_rate_usb, &usb_clk1, &spll_clk); | ||
589 | DEFINE_CLOCK(uart6_clk1, 0, PCCR1, 26, NULL, NULL, &ipg_clk); | ||
590 | DEFINE_CLOCK(uart5_clk1, 0, PCCR1, 27, NULL, NULL, &ipg_clk); | ||
591 | DEFINE_CLOCK(uart4_clk1, 0, PCCR1, 28, NULL, NULL, &ipg_clk); | ||
592 | DEFINE_CLOCK(uart3_clk1, 0, PCCR1, 29, NULL, NULL, &ipg_clk); | ||
593 | DEFINE_CLOCK(uart2_clk1, 0, PCCR1, 30, NULL, NULL, &ipg_clk); | ||
594 | DEFINE_CLOCK(uart1_clk1, 0, PCCR1, 31, NULL, NULL, &ipg_clk); | ||
595 | |||
596 | /* Clocks we cannot directly gate, but drivers need their rates */ | ||
597 | DEFINE_CLOCK(cspi1_clk, 0, 0, 0, NULL, &cspi1_clk1, &per2_clk); | ||
598 | DEFINE_CLOCK(cspi2_clk, 1, 0, 0, NULL, &cspi2_clk1, &per2_clk); | ||
599 | DEFINE_CLOCK(cspi3_clk, 2, 0, 0, NULL, &cspi13_clk1, &per2_clk); | ||
600 | DEFINE_CLOCK(sdhc1_clk, 0, 0, 0, NULL, &sdhc1_clk1, &per2_clk); | ||
601 | DEFINE_CLOCK(sdhc2_clk, 1, 0, 0, NULL, &sdhc2_clk1, &per2_clk); | ||
602 | DEFINE_CLOCK(sdhc3_clk, 2, 0, 0, NULL, &sdhc3_clk1, &per2_clk); | ||
603 | DEFINE_CLOCK(pwm_clk, 0, 0, 0, NULL, &pwm_clk1, &per1_clk); | ||
604 | DEFINE_CLOCK(gpt1_clk, 0, 0, 0, NULL, &gpt1_clk1, &per1_clk); | ||
605 | DEFINE_CLOCK(gpt2_clk, 1, 0, 0, NULL, &gpt2_clk1, &per1_clk); | ||
606 | DEFINE_CLOCK(gpt3_clk, 2, 0, 0, NULL, &gpt3_clk1, &per1_clk); | ||
607 | DEFINE_CLOCK(gpt4_clk, 3, 0, 0, NULL, &gpt4_clk1, &per1_clk); | ||
608 | DEFINE_CLOCK(gpt5_clk, 4, 0, 0, NULL, &gpt5_clk1, &per1_clk); | ||
609 | DEFINE_CLOCK(gpt6_clk, 5, 0, 0, NULL, &gpt6_clk1, &per1_clk); | ||
610 | DEFINE_CLOCK(uart1_clk, 0, 0, 0, NULL, &uart1_clk1, &per1_clk); | ||
611 | DEFINE_CLOCK(uart2_clk, 1, 0, 0, NULL, &uart2_clk1, &per1_clk); | ||
612 | DEFINE_CLOCK(uart3_clk, 2, 0, 0, NULL, &uart3_clk1, &per1_clk); | ||
613 | DEFINE_CLOCK(uart4_clk, 3, 0, 0, NULL, &uart4_clk1, &per1_clk); | ||
614 | DEFINE_CLOCK(uart5_clk, 4, 0, 0, NULL, &uart5_clk1, &per1_clk); | ||
615 | DEFINE_CLOCK(uart6_clk, 5, 0, 0, NULL, &uart6_clk1, &per1_clk); | ||
616 | DEFINE_CLOCK1(lcdc_clk, 0, 0, 0, parent, &lcdc_clk1, &per3_clk); | ||
617 | DEFINE_CLOCK1(csi_clk, 0, 0, 0, parent, &csi_clk1, &per4_clk); | ||
618 | |||
619 | #define _REGISTER_CLOCK(d, n, c) \ | ||
620 | { \ | ||
621 | .dev_id = d, \ | ||
622 | .con_id = n, \ | ||
623 | .clk = &c, \ | ||
624 | }, | ||
625 | |||
626 | static struct clk_lookup lookups[] = { | ||
627 | _REGISTER_CLOCK("imx-uart.0", NULL, uart1_clk) | ||
628 | _REGISTER_CLOCK("imx-uart.1", NULL, uart2_clk) | ||
629 | _REGISTER_CLOCK("imx-uart.2", NULL, uart3_clk) | ||
630 | _REGISTER_CLOCK("imx-uart.3", NULL, uart4_clk) | ||
631 | _REGISTER_CLOCK("imx-uart.4", NULL, uart5_clk) | ||
632 | _REGISTER_CLOCK("imx-uart.5", NULL, uart6_clk) | ||
633 | _REGISTER_CLOCK(NULL, "gpt1", gpt1_clk) | ||
634 | _REGISTER_CLOCK(NULL, "gpt2", gpt2_clk) | ||
635 | _REGISTER_CLOCK(NULL, "gpt3", gpt3_clk) | ||
636 | _REGISTER_CLOCK(NULL, "gpt4", gpt4_clk) | ||
637 | _REGISTER_CLOCK(NULL, "gpt5", gpt5_clk) | ||
638 | _REGISTER_CLOCK(NULL, "gpt6", gpt6_clk) | ||
639 | _REGISTER_CLOCK("mxc_pwm.0", NULL, pwm_clk) | ||
640 | _REGISTER_CLOCK("mxc-mmc.0", NULL, sdhc1_clk) | ||
641 | _REGISTER_CLOCK("mxc-mmc.1", NULL, sdhc2_clk) | ||
642 | _REGISTER_CLOCK("mxc-mmc.2", NULL, sdhc3_clk) | ||
643 | _REGISTER_CLOCK("spi_imx.0", NULL, cspi1_clk) | ||
644 | _REGISTER_CLOCK("spi_imx.1", NULL, cspi2_clk) | ||
645 | _REGISTER_CLOCK("spi_imx.2", NULL, cspi3_clk) | ||
646 | _REGISTER_CLOCK("imx-fb.0", NULL, lcdc_clk) | ||
647 | _REGISTER_CLOCK("mx2-camera.0", NULL, csi_clk) | ||
648 | _REGISTER_CLOCK("fsl-usb2-udc", "usb", usb_clk) | ||
649 | _REGISTER_CLOCK("fsl-usb2-udc", "usb_ahb", usb_clk1) | ||
650 | _REGISTER_CLOCK("mxc-ehci.0", "usb", usb_clk) | ||
651 | _REGISTER_CLOCK("mxc-ehci.0", "usb_ahb", usb_clk1) | ||
652 | _REGISTER_CLOCK("mxc-ehci.1", "usb", usb_clk) | ||
653 | _REGISTER_CLOCK("mxc-ehci.1", "usb_ahb", usb_clk1) | ||
654 | _REGISTER_CLOCK("mxc-ehci.2", "usb", usb_clk) | ||
655 | _REGISTER_CLOCK("mxc-ehci.2", "usb_ahb", usb_clk1) | ||
656 | _REGISTER_CLOCK("imx-ssi.0", NULL, ssi1_clk) | ||
657 | _REGISTER_CLOCK("imx-ssi.1", NULL, ssi2_clk) | ||
658 | _REGISTER_CLOCK("mxc_nand.0", NULL, nfc_clk) | ||
659 | _REGISTER_CLOCK(NULL, "vpu", vpu_clk) | ||
660 | _REGISTER_CLOCK(NULL, "dma", dma_clk) | ||
661 | _REGISTER_CLOCK(NULL, "rtic", rtic_clk) | ||
662 | _REGISTER_CLOCK(NULL, "brom", brom_clk) | ||
663 | _REGISTER_CLOCK(NULL, "emma", emma_clk) | ||
664 | _REGISTER_CLOCK(NULL, "slcdc", slcdc_clk) | ||
665 | _REGISTER_CLOCK("fec.0", NULL, fec_clk) | ||
666 | _REGISTER_CLOCK(NULL, "emi", emi_clk) | ||
667 | _REGISTER_CLOCK(NULL, "sahara2", sahara2_clk) | ||
668 | _REGISTER_CLOCK(NULL, "ata", ata_clk) | ||
669 | _REGISTER_CLOCK(NULL, "mstick", mstick_clk) | ||
670 | _REGISTER_CLOCK("imx-wdt.0", NULL, wdog_clk) | ||
671 | _REGISTER_CLOCK(NULL, "gpio", gpio_clk) | ||
672 | _REGISTER_CLOCK("imx-i2c.0", NULL, i2c1_clk) | ||
673 | _REGISTER_CLOCK("imx-i2c.1", NULL, i2c2_clk) | ||
674 | _REGISTER_CLOCK(NULL, "iim", iim_clk) | ||
675 | _REGISTER_CLOCK(NULL, "kpp", kpp_clk) | ||
676 | _REGISTER_CLOCK("mxc_w1.0", NULL, owire_clk) | ||
677 | _REGISTER_CLOCK(NULL, "rtc", rtc_clk) | ||
678 | _REGISTER_CLOCK(NULL, "scc", scc_clk) | ||
679 | }; | ||
680 | |||
681 | /* Adjust the clock path for TO2 and later */ | ||
682 | static void __init to2_adjust_clocks(void) | ||
683 | { | ||
684 | unsigned long cscr = __raw_readl(CCM_CSCR); | ||
685 | |||
686 | if (mx27_revision() >= CHIP_REV_2_0) { | ||
687 | if (cscr & CCM_CSCR_ARM_SRC) | ||
688 | cpu_clk.parent = &mpll_main1_clk; | ||
689 | |||
690 | if (!(cscr & CCM_CSCR_SSI2)) | ||
691 | ssi1_clk.parent = &spll_clk; | ||
692 | |||
693 | if (!(cscr & CCM_CSCR_SSI1)) | ||
694 | ssi1_clk.parent = &spll_clk; | ||
695 | |||
696 | if (!(cscr & CCM_CSCR_VPU)) | ||
697 | vpu_clk.parent = &spll_clk; | ||
698 | } else { | ||
699 | cpu_clk.parent = &mpll_clk; | ||
700 | cpu_clk.set_parent = NULL; | ||
701 | cpu_clk.round_rate = NULL; | ||
702 | cpu_clk.set_rate = NULL; | ||
703 | ahb_clk.parent = &mpll_clk; | ||
704 | |||
705 | per1_clk.parent = &mpll_clk; | ||
706 | per2_clk.parent = &mpll_clk; | ||
707 | per3_clk.parent = &mpll_clk; | ||
708 | per4_clk.parent = &mpll_clk; | ||
709 | |||
710 | ssi1_clk.parent = &mpll_clk; | ||
711 | ssi2_clk.parent = &mpll_clk; | ||
712 | |||
713 | vpu_clk.parent = &mpll_clk; | ||
714 | } | ||
715 | } | ||
716 | |||
717 | /* | ||
718 | * must be called very early to get information about the | ||
719 | * available clock rate when the timer framework starts | ||
720 | */ | ||
721 | int __init mx27_clocks_init(unsigned long fref) | ||
722 | { | ||
723 | u32 cscr = __raw_readl(CCM_CSCR); | ||
724 | |||
725 | external_high_reference = fref; | ||
726 | |||
727 | /* detect clock reference for both system PLLs */ | ||
728 | if (cscr & CCM_CSCR_MCU) | ||
729 | mpll_clk.parent = &ckih_clk; | ||
730 | else | ||
731 | mpll_clk.parent = &fpm_clk; | ||
732 | |||
733 | if (cscr & CCM_CSCR_SP) | ||
734 | spll_clk.parent = &ckih_clk; | ||
735 | else | ||
736 | spll_clk.parent = &fpm_clk; | ||
737 | |||
738 | to2_adjust_clocks(); | ||
739 | |||
740 | clkdev_add_table(lookups, ARRAY_SIZE(lookups)); | ||
741 | |||
742 | /* Turn off all clocks we do not need */ | ||
743 | __raw_writel(0, CCM_PCCR0); | ||
744 | __raw_writel((1 << 10) | (1 << 19), CCM_PCCR1); | ||
745 | |||
746 | spll_clk.disable(&spll_clk); | ||
747 | |||
748 | /* enable basic clocks */ | ||
749 | clk_enable(&per1_clk); | ||
750 | clk_enable(&gpio_clk); | ||
751 | clk_enable(&emi_clk); | ||
752 | clk_enable(&iim_clk); | ||
753 | |||
754 | #if defined(CONFIG_DEBUG_LL) && !defined(CONFIG_DEBUG_ICEDCC) | ||
755 | clk_enable(&uart1_clk); | ||
756 | #endif | ||
757 | |||
758 | mxc_timer_init(&gpt1_clk, MX27_IO_ADDRESS(MX27_GPT1_BASE_ADDR), | ||
759 | MX27_INT_GPT1); | ||
760 | |||
761 | return 0; | ||
762 | } | ||
763 | |||