aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-mx2
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-mx2')
-rw-r--r--arch/arm/mach-mx2/Kconfig39
-rw-r--r--arch/arm/mach-mx2/Makefile14
-rw-r--r--arch/arm/mach-mx2/Makefile.boot3
-rw-r--r--arch/arm/mach-mx2/clock_imx27.c1626
-rw-r--r--arch/arm/mach-mx2/cpu_imx27.c63
-rw-r--r--arch/arm/mach-mx2/crm_regs.h273
-rw-r--r--arch/arm/mach-mx2/devices.c231
-rw-r--r--arch/arm/mach-mx2/generic.c74
-rw-r--r--arch/arm/mach-mx2/mx27ads.c304
-rw-r--r--arch/arm/mach-mx2/pcm038.c204
-rw-r--r--arch/arm/mach-mx2/pcm970-baseboard.c32
-rw-r--r--arch/arm/mach-mx2/serial.c177
-rw-r--r--arch/arm/mach-mx2/system.c63
13 files changed, 3103 insertions, 0 deletions
diff --git a/arch/arm/mach-mx2/Kconfig b/arch/arm/mach-mx2/Kconfig
new file mode 100644
index 000000000000..1eaa97cb716d
--- /dev/null
+++ b/arch/arm/mach-mx2/Kconfig
@@ -0,0 +1,39 @@
1comment "MX2 family CPU support"
2 depends on ARCH_MX2
3
4config MACH_MX27
5 bool "i.MX27 support"
6 depends on ARCH_MX2
7 help
8 This enables support for Freescale's MX2 based i.MX27 processor.
9
10comment "MX2 Platforms"
11 depends on ARCH_MX2
12
13config MACH_MX27ADS
14 bool "MX27ADS platform"
15 depends on MACH_MX27
16 help
17 Include support for MX27ADS platform. This includes specific
18 configurations for the board and its peripherals.
19
20config MACH_PCM038
21 bool "Phytec phyCORE-i.MX27 CPU module (pcm038)"
22 depends on MACH_MX27
23 help
24 Include support for phyCORE-i.MX27 (aka pcm038) platform. This
25 includes specific configurations for the module and its peripherals.
26
27choice
28 prompt "Baseboard"
29 depends on MACH_PCM038
30 default MACH_PCM970_BASEBOARD
31
32config MACH_PCM970_BASEBOARD
33 prompt "PHYTEC PCM970 development board"
34 bool
35 help
36 This adds board specific devices that can be found on Phytec's
37 PCM970 evaluation board.
38
39endchoice
diff --git a/arch/arm/mach-mx2/Makefile b/arch/arm/mach-mx2/Makefile
new file mode 100644
index 000000000000..382d86080e86
--- /dev/null
+++ b/arch/arm/mach-mx2/Makefile
@@ -0,0 +1,14 @@
1#
2# Makefile for the linux kernel.
3#
4
5# Object file lists.
6
7obj-y := system.o generic.o devices.o serial.o
8
9obj-$(CONFIG_MACH_MX27) += cpu_imx27.o
10obj-$(CONFIG_MACH_MX27) += clock_imx27.o
11
12obj-$(CONFIG_MACH_MX27ADS) += mx27ads.o
13obj-$(CONFIG_MACH_PCM038) += pcm038.o
14obj-$(CONFIG_MACH_PCM970_BASEBOARD) += pcm970-baseboard.o
diff --git a/arch/arm/mach-mx2/Makefile.boot b/arch/arm/mach-mx2/Makefile.boot
new file mode 100644
index 000000000000..696831dcd485
--- /dev/null
+++ b/arch/arm/mach-mx2/Makefile.boot
@@ -0,0 +1,3 @@
1 zreladdr-y := 0xA0008000
2params_phys-y := 0xA0000100
3initrd_phys-y := 0xA0800000
diff --git a/arch/arm/mach-mx2/clock_imx27.c b/arch/arm/mach-mx2/clock_imx27.c
new file mode 100644
index 000000000000..0a29ef29c73a
--- /dev/null
+++ b/arch/arm/mach-mx2/clock_imx27.c
@@ -0,0 +1,1626 @@
1/*
2 * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
3 * Copyright 2008 Juergen Beisert, kernel@pengutronix.de
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
17 * MA 02110-1301, USA.
18 */
19
20#include <linux/clk.h>
21#include <linux/io.h>
22#include <linux/module.h>
23#include <linux/spinlock.h>
24
25#include <asm/arch/clock.h>
26#include <asm/arch/common.h>
27#include <asm/div64.h>
28#include <asm/mach-types.h>
29
30#include "crm_regs.h"
31
32static struct clk ckil_clk;
33static struct clk mpll_clk;
34static struct clk mpll_main_clk[];
35static struct clk spll_clk;
36
37static int _clk_enable(struct clk *clk)
38{
39 unsigned long reg;
40
41 reg = __raw_readl(clk->enable_reg);
42 reg |= 1 << clk->enable_shift;
43 __raw_writel(reg, clk->enable_reg);
44
45 return 0;
46}
47
48static void _clk_disable(struct clk *clk)
49{
50 unsigned long reg;
51
52 reg = __raw_readl(clk->enable_reg);
53 reg &= ~(1 << clk->enable_shift);
54 __raw_writel(reg, clk->enable_reg);
55}
56
57static int _clk_spll_enable(struct clk *clk)
58{
59 unsigned long reg;
60
61 reg = __raw_readl(CCM_CSCR);
62 reg |= CCM_CSCR_SPEN;
63 __raw_writel(reg, CCM_CSCR);
64
65 while ((__raw_readl(CCM_SPCTL1) & CCM_SPCTL1_LF) == 0)
66 ;
67
68 return 0;
69}
70
71static void _clk_spll_disable(struct clk *clk)
72{
73 unsigned long reg;
74
75 reg = __raw_readl(CCM_CSCR);
76 reg &= ~CCM_CSCR_SPEN;
77 __raw_writel(reg, CCM_CSCR);
78}
79
80static void _clk_pccr01_enable(unsigned long mask0, unsigned long mask1)
81{
82 unsigned long reg;
83
84 reg = __raw_readl(CCM_PCCR0);
85 reg |= mask0;
86 __raw_writel(reg, CCM_PCCR0);
87
88 reg = __raw_readl(CCM_PCCR1);
89 reg |= mask1;
90 __raw_writel(reg, CCM_PCCR1);
91
92}
93
94static void _clk_pccr01_disable(unsigned long mask0, unsigned long mask1)
95{
96 unsigned long reg;
97
98 reg = __raw_readl(CCM_PCCR0);
99 reg &= ~mask0;
100 __raw_writel(reg, CCM_PCCR0);
101
102 reg = __raw_readl(CCM_PCCR1);
103 reg &= ~mask1;
104 __raw_writel(reg, CCM_PCCR1);
105}
106
107static void _clk_pccr10_enable(unsigned long mask1, unsigned long mask0)
108{
109 unsigned long reg;
110
111 reg = __raw_readl(CCM_PCCR1);
112 reg |= mask1;
113 __raw_writel(reg, CCM_PCCR1);
114
115 reg = __raw_readl(CCM_PCCR0);
116 reg |= mask0;
117 __raw_writel(reg, CCM_PCCR0);
118}
119
120static void _clk_pccr10_disable(unsigned long mask1, unsigned long mask0)
121{
122 unsigned long reg;
123
124 reg = __raw_readl(CCM_PCCR1);
125 reg &= ~mask1;
126 __raw_writel(reg, CCM_PCCR1);
127
128 reg = __raw_readl(CCM_PCCR0);
129 reg &= ~mask0;
130 __raw_writel(reg, CCM_PCCR0);
131}
132
133static int _clk_dma_enable(struct clk *clk)
134{
135 _clk_pccr01_enable(CCM_PCCR0_DMA_MASK, CCM_PCCR1_HCLK_DMA_MASK);
136
137 return 0;
138}
139
140static void _clk_dma_disable(struct clk *clk)
141{
142 _clk_pccr01_disable(CCM_PCCR0_DMA_MASK, CCM_PCCR1_HCLK_DMA_MASK);
143}
144
145static int _clk_rtic_enable(struct clk *clk)
146{
147 _clk_pccr01_enable(CCM_PCCR0_RTIC_MASK, CCM_PCCR1_HCLK_RTIC_MASK);
148
149 return 0;
150}
151
152static void _clk_rtic_disable(struct clk *clk)
153{
154 _clk_pccr01_disable(CCM_PCCR0_RTIC_MASK, CCM_PCCR1_HCLK_RTIC_MASK);
155}
156
157static int _clk_emma_enable(struct clk *clk)
158{
159 _clk_pccr01_enable(CCM_PCCR0_EMMA_MASK, CCM_PCCR1_HCLK_EMMA_MASK);
160
161 return 0;
162}
163
164static void _clk_emma_disable(struct clk *clk)
165{
166 _clk_pccr01_disable(CCM_PCCR0_EMMA_MASK, CCM_PCCR1_HCLK_EMMA_MASK);
167}
168
169static int _clk_slcdc_enable(struct clk *clk)
170{
171 _clk_pccr01_enable(CCM_PCCR0_SLCDC_MASK, CCM_PCCR1_HCLK_SLCDC_MASK);
172
173 return 0;
174}
175
176static void _clk_slcdc_disable(struct clk *clk)
177{
178 _clk_pccr01_disable(CCM_PCCR0_SLCDC_MASK, CCM_PCCR1_HCLK_SLCDC_MASK);
179}
180
181static int _clk_fec_enable(struct clk *clk)
182{
183 _clk_pccr01_enable(CCM_PCCR0_FEC_MASK, CCM_PCCR1_HCLK_FEC_MASK);
184
185 return 0;
186}
187
188static void _clk_fec_disable(struct clk *clk)
189{
190 _clk_pccr01_disable(CCM_PCCR0_FEC_MASK, CCM_PCCR1_HCLK_FEC_MASK);
191}
192
193static int _clk_vpu_enable(struct clk *clk)
194{
195 unsigned long reg;
196
197 reg = __raw_readl(CCM_PCCR1);
198 reg |= CCM_PCCR1_VPU_BAUD_MASK | CCM_PCCR1_HCLK_VPU_MASK;
199 __raw_writel(reg, CCM_PCCR1);
200
201 return 0;
202}
203
204static void _clk_vpu_disable(struct clk *clk)
205{
206 unsigned long reg;
207
208 reg = __raw_readl(CCM_PCCR1);
209 reg &= ~(CCM_PCCR1_VPU_BAUD_MASK | CCM_PCCR1_HCLK_VPU_MASK);
210 __raw_writel(reg, CCM_PCCR1);
211}
212
213static int _clk_sahara2_enable(struct clk *clk)
214{
215 _clk_pccr01_enable(CCM_PCCR0_SAHARA_MASK, CCM_PCCR1_HCLK_SAHARA_MASK);
216
217 return 0;
218}
219
220static void _clk_sahara2_disable(struct clk *clk)
221{
222 _clk_pccr01_disable(CCM_PCCR0_SAHARA_MASK, CCM_PCCR1_HCLK_SAHARA_MASK);
223}
224
225static int _clk_mstick1_enable(struct clk *clk)
226{
227 _clk_pccr10_enable(CCM_PCCR1_MSHC_BAUD_MASK, CCM_PCCR0_MSHC_MASK);
228
229 return 0;
230}
231
232static void _clk_mstick1_disable(struct clk *clk)
233{
234 _clk_pccr10_disable(CCM_PCCR1_MSHC_BAUD_MASK, CCM_PCCR0_MSHC_MASK);
235}
236
237#define CSCR() (__raw_readl(CCM_CSCR))
238#define PCDR0() (__raw_readl(CCM_PCDR0))
239#define PCDR1() (__raw_readl(CCM_PCDR1))
240
241static int _clk_cpu_set_parent(struct clk *clk, struct clk *parent)
242{
243 int cscr = CSCR();
244
245 if (clk->parent == parent)
246 return 0;
247
248 if (mx27_revision() >= CHIP_REV_2_0) {
249 if (parent == &mpll_main_clk[0]) {
250 cscr |= CCM_CSCR_ARM_SRC;
251 } else {
252 if (parent == &mpll_main_clk[1])
253 cscr &= ~CCM_CSCR_ARM_SRC;
254 else
255 return -EINVAL;
256 }
257 __raw_writel(cscr, CCM_CSCR);
258 } else
259 return -ENODEV;
260
261 clk->parent = parent;
262 return 0;
263}
264
265static unsigned long _clk_cpu_round_rate(struct clk *clk, unsigned long rate)
266{
267 int div;
268 unsigned long parent_rate;
269
270 parent_rate = clk_get_rate(clk->parent);
271
272 div = parent_rate / rate;
273 if (parent_rate % rate)
274 div++;
275
276 if (div > 4)
277 div = 4;
278
279 return parent_rate / div;
280}
281
282static int _clk_cpu_set_rate(struct clk *clk, unsigned long rate)
283{
284 unsigned int div;
285 uint32_t reg;
286 unsigned long parent_rate;
287
288 parent_rate = clk_get_rate(clk->parent);
289
290 div = parent_rate / rate;
291
292 if (div > 4 || div < 1 || ((parent_rate / div) != rate))
293 return -EINVAL;
294
295 div--;
296
297 reg = __raw_readl(CCM_CSCR);
298 if (mx27_revision() >= CHIP_REV_2_0) {
299 reg &= ~CCM_CSCR_ARM_MASK;
300 reg |= div << CCM_CSCR_ARM_OFFSET;
301 reg &= ~0x06;
302 __raw_writel(reg | 0x80000000, CCM_CSCR);
303 } else {
304 printk(KERN_ERR "Cant set CPU frequency!\n");
305 }
306
307 return 0;
308}
309
310static unsigned long _clk_perclkx_round_rate(struct clk *clk,
311 unsigned long rate)
312{
313 u32 div;
314 unsigned long parent_rate;
315
316 parent_rate = clk_get_rate(clk->parent);
317
318 div = parent_rate / rate;
319 if (parent_rate % rate)
320 div++;
321
322 if (div > 64)
323 div = 64;
324
325 return parent_rate / div;
326}
327
328static int _clk_perclkx_set_rate(struct clk *clk, unsigned long rate)
329{
330 u32 reg;
331 u32 div;
332 unsigned long parent_rate;
333
334 parent_rate = clk_get_rate(clk->parent);
335
336 if (clk->id < 0 || clk->id > 3)
337 return -EINVAL;
338
339 div = parent_rate / rate;
340 if (div > 64 || div < 1 || ((parent_rate / div) != rate))
341 return -EINVAL;
342 div--;
343
344 reg =
345 __raw_readl(CCM_PCDR1) & ~(CCM_PCDR1_PERDIV1_MASK <<
346 (clk->id << 3));
347 reg |= div << (clk->id << 3);
348 __raw_writel(reg, CCM_PCDR1);
349
350 return 0;
351}
352
353static unsigned long _clk_usb_recalc(struct clk *clk)
354{
355 unsigned long usb_pdf;
356 unsigned long parent_rate;
357
358 parent_rate = clk_get_rate(clk->parent);
359
360 usb_pdf = (CSCR() & CCM_CSCR_USB_MASK) >> CCM_CSCR_USB_OFFSET;
361
362 return parent_rate / (usb_pdf + 1U);
363}
364
365static unsigned long _clk_ssi1_recalc(struct clk *clk)
366{
367 unsigned long ssi1_pdf;
368 unsigned long parent_rate;
369
370 parent_rate = clk_get_rate(clk->parent);
371
372 ssi1_pdf = (PCDR0() & CCM_PCDR0_SSI1BAUDDIV_MASK) >>
373 CCM_PCDR0_SSI1BAUDDIV_OFFSET;
374
375 if (mx27_revision() >= CHIP_REV_2_0)
376 ssi1_pdf += 4;
377 else
378 ssi1_pdf = (ssi1_pdf < 2) ? 124UL : ssi1_pdf;
379
380 return 2UL * parent_rate / ssi1_pdf;
381}
382
383static unsigned long _clk_ssi2_recalc(struct clk *clk)
384{
385 unsigned long ssi2_pdf;
386 unsigned long parent_rate;
387
388 parent_rate = clk_get_rate(clk->parent);
389
390 ssi2_pdf = (PCDR0() & CCM_PCDR0_SSI2BAUDDIV_MASK) >>
391 CCM_PCDR0_SSI2BAUDDIV_OFFSET;
392
393 if (mx27_revision() >= CHIP_REV_2_0)
394 ssi2_pdf += 4;
395 else
396 ssi2_pdf = (ssi2_pdf < 2) ? 124UL : ssi2_pdf;
397
398 return 2UL * parent_rate / ssi2_pdf;
399}
400
401static unsigned long _clk_nfc_recalc(struct clk *clk)
402{
403 unsigned long nfc_pdf;
404 unsigned long parent_rate;
405
406 parent_rate = clk_get_rate(clk->parent);
407
408 if (mx27_revision() >= CHIP_REV_2_0) {
409 nfc_pdf =
410 (PCDR0() & CCM_PCDR0_NFCDIV2_MASK) >>
411 CCM_PCDR0_NFCDIV2_OFFSET;
412 } else {
413 nfc_pdf =
414 (PCDR0() & CCM_PCDR0_NFCDIV_MASK) >>
415 CCM_PCDR0_NFCDIV_OFFSET;
416 }
417
418 return parent_rate / (nfc_pdf + 1);
419}
420
421static unsigned long _clk_vpu_recalc(struct clk *clk)
422{
423 unsigned long vpu_pdf;
424 unsigned long parent_rate;
425
426 parent_rate = clk_get_rate(clk->parent);
427
428 if (mx27_revision() >= CHIP_REV_2_0) {
429 vpu_pdf =
430 (PCDR0() & CCM_PCDR0_VPUDIV2_MASK) >>
431 CCM_PCDR0_VPUDIV2_OFFSET;
432 vpu_pdf += 4;
433 } else {
434 vpu_pdf =
435 (PCDR0() & CCM_PCDR0_VPUDIV_MASK) >>
436 CCM_PCDR0_VPUDIV_OFFSET;
437 vpu_pdf = (vpu_pdf < 2) ? 124 : vpu_pdf;
438 }
439 return 2UL * parent_rate / vpu_pdf;
440}
441
442static unsigned long _clk_parent_round_rate(struct clk *clk, unsigned long rate)
443{
444 return clk->parent->round_rate(clk->parent, rate);
445}
446
447static int _clk_parent_set_rate(struct clk *clk, unsigned long rate)
448{
449 return clk->parent->set_rate(clk->parent, rate);
450}
451
452/* in Hz */
453static unsigned long external_high_reference = 26000000;
454
455static unsigned long get_high_reference_clock_rate(struct clk *clk)
456{
457 return external_high_reference;
458}
459
460/*
461 * the high frequency external clock reference
462 * Default case is 26MHz. Could be changed at runtime
463 * with a call to change_external_high_reference()
464 */
465static struct clk ckih_clk = {
466 .name = "ckih",
467 .get_rate = get_high_reference_clock_rate,
468};
469
470/* in Hz */
471static unsigned long external_low_reference = 32768;
472
473static unsigned long get_low_reference_clock_rate(struct clk *clk)
474{
475 return external_low_reference;
476}
477
478/*
479 * the low frequency external clock reference
480 * Default case is 32.768kHz Could be changed at runtime
481 * with a call to change_external_low_reference()
482 */
483static struct clk ckil_clk = {
484 .name = "ckil",
485 .get_rate = get_low_reference_clock_rate,
486};
487
488static unsigned long get_mpll_clk(struct clk *clk)
489{
490 uint32_t reg;
491 unsigned long ref_clk;
492 unsigned long mfi = 0, mfn = 0, mfd = 0, pdf = 0;
493 unsigned long long temp;
494
495 ref_clk = clk_get_rate(clk->parent);
496
497 reg = __raw_readl(CCM_MPCTL0);
498 pdf = (reg & CCM_MPCTL0_PD_MASK) >> CCM_MPCTL0_PD_OFFSET;
499 mfd = (reg & CCM_MPCTL0_MFD_MASK) >> CCM_MPCTL0_MFD_OFFSET;
500 mfi = (reg & CCM_MPCTL0_MFI_MASK) >> CCM_MPCTL0_MFI_OFFSET;
501 mfn = (reg & CCM_MPCTL0_MFN_MASK) >> CCM_MPCTL0_MFN_OFFSET;
502
503 mfi = (mfi <= 5) ? 5 : mfi;
504 temp = 2LL * ref_clk * mfn;
505 do_div(temp, mfd + 1);
506 temp = 2LL * ref_clk * mfi + temp;
507 do_div(temp, pdf + 1);
508
509 return (unsigned long)temp;
510}
511
512static struct clk mpll_clk = {
513 .name = "mpll",
514 .parent = &ckih_clk,
515 .get_rate = get_mpll_clk,
516};
517
518static unsigned long _clk_mpll_main_get_rate(struct clk *clk)
519{
520 unsigned long parent_rate;
521
522 parent_rate = clk_get_rate(clk->parent);
523
524 /* i.MX27 TO2:
525 * clk->id == 0: arm clock source path 1 which is from 2*MPLL/DIV_2
526 * clk->id == 1: arm clock source path 2 which is from 2*MPLL/DIV_3
527 */
528
529 if (mx27_revision() >= CHIP_REV_2_0 && clk->id == 1)
530 return 2UL * parent_rate / 3UL;
531
532 return parent_rate;
533}
534
535static struct clk mpll_main_clk[] = {
536 {
537 /* For i.MX27 TO2, it is the MPLL path 1 of ARM core
538 * It provide the clock source whose rate is same as MPLL
539 */
540 .name = "mpll_main",
541 .id = 0,
542 .parent = &mpll_clk,
543 .get_rate = _clk_mpll_main_get_rate
544 }, {
545 /* For i.MX27 TO2, it is the MPLL path 2 of ARM core
546 * It provide the clock source whose rate is same MPLL * 2/3
547 */
548 .name = "mpll_main",
549 .id = 1,
550 .parent = &mpll_clk,
551 .get_rate = _clk_mpll_main_get_rate
552 }
553};
554
555static unsigned long get_spll_clk(struct clk *clk)
556{
557 uint32_t reg;
558 unsigned long ref_clk;
559 unsigned long mfi = 0, mfn = 0, mfd = 0, pdf = 0;
560 unsigned long long temp;
561
562 ref_clk = clk_get_rate(clk->parent);
563
564 reg = __raw_readl(CCM_SPCTL0);
565 /*TODO: This is TO2 Bug */
566 if (mx27_revision() >= CHIP_REV_2_0)
567 __raw_writel(reg, CCM_SPCTL0);
568
569 pdf = (reg & CCM_SPCTL0_PD_MASK) >> CCM_SPCTL0_PD_OFFSET;
570 mfd = (reg & CCM_SPCTL0_MFD_MASK) >> CCM_SPCTL0_MFD_OFFSET;
571 mfi = (reg & CCM_SPCTL0_MFI_MASK) >> CCM_SPCTL0_MFI_OFFSET;
572 mfn = (reg & CCM_SPCTL0_MFN_MASK) >> CCM_SPCTL0_MFN_OFFSET;
573
574 mfi = (mfi <= 5) ? 5 : mfi;
575 temp = 2LL * ref_clk * mfn;
576 do_div(temp, mfd + 1);
577 temp = 2LL * ref_clk * mfi + temp;
578 do_div(temp, pdf + 1);
579
580 return (unsigned long)temp;
581}
582
583static struct clk spll_clk = {
584 .name = "spll",
585 .parent = &ckih_clk,
586 .get_rate = get_spll_clk,
587 .enable = _clk_spll_enable,
588 .disable = _clk_spll_disable,
589};
590
591static unsigned long get_cpu_clk(struct clk *clk)
592{
593 u32 div;
594 unsigned long rate;
595
596 if (mx27_revision() >= CHIP_REV_2_0)
597 div = (CSCR() & CCM_CSCR_ARM_MASK) >> CCM_CSCR_ARM_OFFSET;
598 else
599 div = (CSCR() & CCM_CSCR_PRESC_MASK) >> CCM_CSCR_PRESC_OFFSET;
600
601 rate = clk_get_rate(clk->parent);
602 return rate / (div + 1);
603}
604
605static struct clk cpu_clk = {
606 .name = "cpu_clk",
607 .parent = &mpll_main_clk[1],
608 .set_parent = _clk_cpu_set_parent,
609 .round_rate = _clk_cpu_round_rate,
610 .get_rate = get_cpu_clk,
611 .set_rate = _clk_cpu_set_rate,
612};
613
614static unsigned long get_ahb_clk(struct clk *clk)
615{
616 unsigned long rate;
617 unsigned long bclk_pdf;
618
619 if (mx27_revision() >= CHIP_REV_2_0)
620 bclk_pdf = (CSCR() & CCM_CSCR_AHB_MASK)
621 >> CCM_CSCR_AHB_OFFSET;
622 else
623 bclk_pdf = (CSCR() & CCM_CSCR_BCLK_MASK)
624 >> CCM_CSCR_BCLK_OFFSET;
625
626 rate = clk_get_rate(clk->parent);
627 return rate / (bclk_pdf + 1);
628}
629
630static struct clk ahb_clk = {
631 .name = "ahb_clk",
632 .parent = &mpll_main_clk[1],
633 .get_rate = get_ahb_clk,
634};
635
636static unsigned long get_ipg_clk(struct clk *clk)
637{
638 unsigned long rate;
639 unsigned long ipg_pdf;
640
641 if (mx27_revision() >= CHIP_REV_2_0)
642 return clk_get_rate(clk->parent);
643 else
644 ipg_pdf = (CSCR() & CCM_CSCR_IPDIV) >> CCM_CSCR_IPDIV_OFFSET;
645
646 rate = clk_get_rate(clk->parent);
647 return rate / (ipg_pdf + 1);
648}
649
650static struct clk ipg_clk = {
651 .name = "ipg_clk",
652 .parent = &ahb_clk,
653 .get_rate = get_ipg_clk,
654};
655
656static unsigned long _clk_perclkx_recalc(struct clk *clk)
657{
658 unsigned long perclk_pdf;
659 unsigned long parent_rate;
660
661 parent_rate = clk_get_rate(clk->parent);
662
663 if (clk->id < 0 || clk->id > 3)
664 return 0;
665
666 perclk_pdf = (PCDR1() >> (clk->id << 3)) & CCM_PCDR1_PERDIV1_MASK;
667
668 return parent_rate / (perclk_pdf + 1);
669}
670
671static struct clk per_clk[] = {
672 {
673 .name = "per_clk",
674 .id = 0,
675 .parent = &mpll_main_clk[1],
676 .get_rate = _clk_perclkx_recalc,
677 .enable = _clk_enable,
678 .enable_reg = CCM_PCCR1,
679 .enable_shift = CCM_PCCR1_PERCLK1_OFFSET,
680 .disable = _clk_disable,
681 }, {
682 .name = "per_clk",
683 .id = 1,
684 .parent = &mpll_main_clk[1],
685 .get_rate = _clk_perclkx_recalc,
686 .enable = _clk_enable,
687 .enable_reg = CCM_PCCR1,
688 .enable_shift = CCM_PCCR1_PERCLK2_OFFSET,
689 .disable = _clk_disable,
690 }, {
691 .name = "per_clk",
692 .id = 2,
693 .parent = &mpll_main_clk[1],
694 .round_rate = _clk_perclkx_round_rate,
695 .set_rate = _clk_perclkx_set_rate,
696 .get_rate = _clk_perclkx_recalc,
697 .enable = _clk_enable,
698 .enable_reg = CCM_PCCR1,
699 .enable_shift = CCM_PCCR1_PERCLK3_OFFSET,
700 .disable = _clk_disable,
701 }, {
702 .name = "per_clk",
703 .id = 3,
704 .parent = &mpll_main_clk[1],
705 .round_rate = _clk_perclkx_round_rate,
706 .set_rate = _clk_perclkx_set_rate,
707 .get_rate = _clk_perclkx_recalc,
708 .enable = _clk_enable,
709 .enable_reg = CCM_PCCR1,
710 .enable_shift = CCM_PCCR1_PERCLK4_OFFSET,
711 .disable = _clk_disable,
712 },
713};
714
715struct clk uart1_clk[] = {
716 {
717 .name = "uart_clk",
718 .id = 0,
719 .parent = &per_clk[0],
720 .secondary = &uart1_clk[1],
721 }, {
722 .name = "uart_ipg_clk",
723 .id = 0,
724 .parent = &ipg_clk,
725 .enable = _clk_enable,
726 .enable_reg = CCM_PCCR1,
727 .enable_shift = CCM_PCCR1_UART1_OFFSET,
728 .disable = _clk_disable,
729 },
730};
731
732struct clk uart2_clk[] = {
733 {
734 .name = "uart_clk",
735 .id = 1,
736 .parent = &per_clk[0],
737 .secondary = &uart2_clk[1],
738 }, {
739 .name = "uart_ipg_clk",
740 .id = 1,
741 .parent = &ipg_clk,
742 .enable = _clk_enable,
743 .enable_reg = CCM_PCCR1,
744 .enable_shift = CCM_PCCR1_UART2_OFFSET,
745 .disable = _clk_disable,
746 },
747};
748
749struct clk uart3_clk[] = {
750 {
751 .name = "uart_clk",
752 .id = 2,
753 .parent = &per_clk[0],
754 .secondary = &uart3_clk[1],
755 }, {
756 .name = "uart_ipg_clk",
757 .id = 2,
758 .parent = &ipg_clk,
759 .enable = _clk_enable,
760 .enable_reg = CCM_PCCR1,
761 .enable_shift = CCM_PCCR1_UART3_OFFSET,
762 .disable = _clk_disable,
763 },
764};
765
766struct clk uart4_clk[] = {
767 {
768 .name = "uart_clk",
769 .id = 3,
770 .parent = &per_clk[0],
771 .secondary = &uart4_clk[1],
772 }, {
773 .name = "uart_ipg_clk",
774 .id = 3,
775 .parent = &ipg_clk,
776 .enable = _clk_enable,
777 .enable_reg = CCM_PCCR1,
778 .enable_shift = CCM_PCCR1_UART4_OFFSET,
779 .disable = _clk_disable,
780 },
781};
782
783struct clk uart5_clk[] = {
784 {
785 .name = "uart_clk",
786 .id = 4,
787 .parent = &per_clk[0],
788 .secondary = &uart5_clk[1],
789 }, {
790 .name = "uart_ipg_clk",
791 .id = 4,
792 .parent = &ipg_clk,
793 .enable = _clk_enable,
794 .enable_reg = CCM_PCCR1,
795 .enable_shift = CCM_PCCR1_UART5_OFFSET,
796 .disable = _clk_disable,
797 },
798};
799
800struct clk uart6_clk[] = {
801 {
802 .name = "uart_clk",
803 .id = 5,
804 .parent = &per_clk[0],
805 .secondary = &uart6_clk[1],
806 }, {
807 .name = "uart_ipg_clk",
808 .id = 5,
809 .parent = &ipg_clk,
810 .enable = _clk_enable,
811 .enable_reg = CCM_PCCR1,
812 .enable_shift = CCM_PCCR1_UART6_OFFSET,
813 .disable = _clk_disable,
814 },
815};
816
817static struct clk gpt1_clk[] = {
818 {
819 .name = "gpt_clk",
820 .id = 0,
821 .parent = &per_clk[0],
822 .secondary = &gpt1_clk[1],
823 }, {
824 .name = "gpt_ipg_clk",
825 .id = 0,
826 .parent = &ipg_clk,
827 .enable = _clk_enable,
828 .enable_reg = CCM_PCCR0,
829 .enable_shift = CCM_PCCR0_GPT1_OFFSET,
830 .disable = _clk_disable,
831 },
832};
833
834static struct clk gpt2_clk[] = {
835 {
836 .name = "gpt_clk",
837 .id = 1,
838 .parent = &per_clk[0],
839 .secondary = &gpt2_clk[1],
840 }, {
841 .name = "gpt_ipg_clk",
842 .id = 1,
843 .parent = &ipg_clk,
844 .enable = _clk_enable,
845 .enable_reg = CCM_PCCR0,
846 .enable_shift = CCM_PCCR0_GPT2_OFFSET,
847 .disable = _clk_disable,
848 },
849};
850
851static struct clk gpt3_clk[] = {
852 {
853 .name = "gpt_clk",
854 .id = 2,
855 .parent = &per_clk[0],
856 .secondary = &gpt3_clk[1],
857 }, {
858 .name = "gpt_ipg_clk",
859 .id = 2,
860 .parent = &ipg_clk,
861 .enable = _clk_enable,
862 .enable_reg = CCM_PCCR0,
863 .enable_shift = CCM_PCCR0_GPT3_OFFSET,
864 .disable = _clk_disable,
865 },
866};
867
868static struct clk gpt4_clk[] = {
869 {
870 .name = "gpt_clk",
871 .id = 3,
872 .parent = &per_clk[0],
873 .secondary = &gpt4_clk[1],
874 }, {
875 .name = "gpt_ipg_clk",
876 .id = 3,
877 .parent = &ipg_clk,
878 .enable = _clk_enable,
879 .enable_reg = CCM_PCCR0,
880 .enable_shift = CCM_PCCR0_GPT4_OFFSET,
881 .disable = _clk_disable,
882 },
883};
884
885static struct clk gpt5_clk[] = {
886 {
887 .name = "gpt_clk",
888 .id = 4,
889 .parent = &per_clk[0],
890 .secondary = &gpt5_clk[1],
891 }, {
892 .name = "gpt_ipg_clk",
893 .id = 4,
894 .parent = &ipg_clk,
895 .enable = _clk_enable,
896 .enable_reg = CCM_PCCR0,
897 .enable_shift = CCM_PCCR0_GPT5_OFFSET,
898 .disable = _clk_disable,
899 },
900};
901
902static struct clk gpt6_clk[] = {
903 {
904 .name = "gpt_clk",
905 .id = 5,
906 .parent = &per_clk[0],
907 .secondary = &gpt6_clk[1],
908 }, {
909 .name = "gpt_ipg_clk",
910 .id = 5,
911 .parent = &ipg_clk,
912 .enable = _clk_enable,
913 .enable_reg = CCM_PCCR0,
914 .enable_shift = CCM_PCCR0_GPT6_OFFSET,
915 .disable = _clk_disable,
916 },
917};
918
919static struct clk pwm_clk[] = {
920 {
921 .name = "pwm_clk",
922 .parent = &per_clk[0],
923 .secondary = &pwm_clk[1],
924 }, {
925 .name = "pwm_clk",
926 .parent = &ipg_clk,
927 .enable = _clk_enable,
928 .enable_reg = CCM_PCCR0,
929 .enable_shift = CCM_PCCR0_PWM_OFFSET,
930 .disable = _clk_disable,
931 },
932};
933
934static struct clk sdhc1_clk[] = {
935 {
936 .name = "sdhc_clk",
937 .id = 0,
938 .parent = &per_clk[1],
939 .secondary = &sdhc1_clk[1],
940 }, {
941 .name = "sdhc_ipg_clk",
942 .id = 0,
943 .parent = &ipg_clk,
944 .enable = _clk_enable,
945 .enable_reg = CCM_PCCR0,
946 .enable_shift = CCM_PCCR0_SDHC1_OFFSET,
947 .disable = _clk_disable,
948 },
949};
950
951static struct clk sdhc2_clk[] = {
952 {
953 .name = "sdhc_clk",
954 .id = 1,
955 .parent = &per_clk[1],
956 .secondary = &sdhc2_clk[1],
957 }, {
958 .name = "sdhc_ipg_clk",
959 .id = 1,
960 .parent = &ipg_clk,
961 .enable = _clk_enable,
962 .enable_reg = CCM_PCCR0,
963 .enable_shift = CCM_PCCR0_SDHC2_OFFSET,
964 .disable = _clk_disable,
965 },
966};
967
968static struct clk sdhc3_clk[] = {
969 {
970 .name = "sdhc_clk",
971 .id = 2,
972 .parent = &per_clk[1],
973 .secondary = &sdhc3_clk[1],
974 }, {
975 .name = "sdhc_ipg_clk",
976 .id = 2,
977 .parent = &ipg_clk,
978 .enable = _clk_enable,
979 .enable_reg = CCM_PCCR0,
980 .enable_shift = CCM_PCCR0_SDHC3_OFFSET,
981 .disable = _clk_disable,
982 },
983};
984
985static struct clk cspi1_clk[] = {
986 {
987 .name = "cspi_clk",
988 .id = 0,
989 .parent = &per_clk[1],
990 .secondary = &cspi1_clk[1],
991 }, {
992 .name = "cspi_ipg_clk",
993 .id = 0,
994 .parent = &ipg_clk,
995 .enable = _clk_enable,
996 .enable_reg = CCM_PCCR0,
997 .enable_shift = CCM_PCCR0_CSPI1_OFFSET,
998 .disable = _clk_disable,
999 },
1000};
1001
1002static struct clk cspi2_clk[] = {
1003 {
1004 .name = "cspi_clk",
1005 .id = 1,
1006 .parent = &per_clk[1],
1007 .secondary = &cspi2_clk[1],
1008 }, {
1009 .name = "cspi_ipg_clk",
1010 .id = 1,
1011 .parent = &ipg_clk,
1012 .enable = _clk_enable,
1013 .enable_reg = CCM_PCCR0,
1014 .enable_shift = CCM_PCCR0_CSPI2_OFFSET,
1015 .disable = _clk_disable,
1016 },
1017};
1018
1019static struct clk cspi3_clk[] = {
1020 {
1021 .name = "cspi_clk",
1022 .id = 2,
1023 .parent = &per_clk[1],
1024 .secondary = &cspi3_clk[1],
1025 }, {
1026 .name = "cspi_ipg_clk",
1027 .id = 2,
1028 .parent = &ipg_clk,
1029 .enable = _clk_enable,
1030 .enable_reg = CCM_PCCR0,
1031 .enable_shift = CCM_PCCR0_CSPI3_OFFSET,
1032 .disable = _clk_disable,
1033 },
1034};
1035
1036static struct clk lcdc_clk[] = {
1037 {
1038 .name = "lcdc_clk",
1039 .parent = &per_clk[2],
1040 .secondary = &lcdc_clk[1],
1041 .round_rate = _clk_parent_round_rate,
1042 .set_rate = _clk_parent_set_rate,
1043 }, {
1044 .name = "lcdc_ipg_clk",
1045 .parent = &ipg_clk,
1046 .secondary = &lcdc_clk[2],
1047 .enable = _clk_enable,
1048 .enable_reg = CCM_PCCR0,
1049 .enable_shift = CCM_PCCR0_LCDC_OFFSET,
1050 .disable = _clk_disable,
1051 }, {
1052 .name = "lcdc_ahb_clk",
1053 .parent = &ahb_clk,
1054 .enable = _clk_enable,
1055 .enable_reg = CCM_PCCR1,
1056 .enable_shift = CCM_PCCR1_HCLK_LCDC_OFFSET,
1057 .disable = _clk_disable,
1058 },
1059};
1060
1061static struct clk csi_clk[] = {
1062 {
1063 .name = "csi_perclk",
1064 .parent = &per_clk[3],
1065 .secondary = &csi_clk[1],
1066 .round_rate = _clk_parent_round_rate,
1067 .set_rate = _clk_parent_set_rate,
1068 }, {
1069 .name = "csi_ahb_clk",
1070 .parent = &ahb_clk,
1071 .enable = _clk_enable,
1072 .enable_reg = CCM_PCCR1,
1073 .enable_shift = CCM_PCCR1_HCLK_CSI_OFFSET,
1074 .disable = _clk_disable,
1075 },
1076};
1077
1078static struct clk usb_clk[] = {
1079 {
1080 .name = "usb_clk",
1081 .parent = &spll_clk,
1082 .get_rate = _clk_usb_recalc,
1083 .enable = _clk_enable,
1084 .enable_reg = CCM_PCCR1,
1085 .enable_shift = CCM_PCCR1_USBOTG_OFFSET,
1086 .disable = _clk_disable,
1087 }, {
1088 .name = "usb_ahb_clk",
1089 .parent = &ahb_clk,
1090 .enable = _clk_enable,
1091 .enable_reg = CCM_PCCR1,
1092 .enable_shift = CCM_PCCR1_HCLK_USBOTG_OFFSET,
1093 .disable = _clk_disable,
1094 }
1095};
1096
1097static struct clk ssi1_clk[] = {
1098 {
1099 .name = "ssi_clk",
1100 .id = 0,
1101 .parent = &mpll_main_clk[1],
1102 .secondary = &ssi1_clk[1],
1103 .get_rate = _clk_ssi1_recalc,
1104 .enable = _clk_enable,
1105 .enable_reg = CCM_PCCR1,
1106 .enable_shift = CCM_PCCR1_SSI1_BAUD_OFFSET,
1107 .disable = _clk_disable,
1108 }, {
1109 .name = "ssi_ipg_clk",
1110 .id = 0,
1111 .parent = &ipg_clk,
1112 .enable = _clk_enable,
1113 .enable_reg = CCM_PCCR0,
1114 .enable_shift = CCM_PCCR0_SSI1_IPG_OFFSET,
1115 .disable = _clk_disable,
1116 },
1117};
1118
1119static struct clk ssi2_clk[] = {
1120 {
1121 .name = "ssi_clk",
1122 .id = 1,
1123 .parent = &mpll_main_clk[1],
1124 .secondary = &ssi2_clk[1],
1125 .get_rate = _clk_ssi2_recalc,
1126 .enable = _clk_enable,
1127 .enable_reg = CCM_PCCR1,
1128 .enable_shift = CCM_PCCR1_SSI2_BAUD_OFFSET,
1129 .disable = _clk_disable,
1130 }, {
1131 .name = "ssi_ipg_clk",
1132 .id = 1,
1133 .parent = &ipg_clk,
1134 .enable = _clk_enable,
1135 .enable_reg = CCM_PCCR0,
1136 .enable_shift = CCM_PCCR0_SSI2_IPG_OFFSET,
1137 .disable = _clk_disable,
1138 },
1139};
1140
1141static struct clk nfc_clk = {
1142 .name = "nfc_clk",
1143 .parent = &cpu_clk,
1144 .get_rate = _clk_nfc_recalc,
1145 .enable = _clk_enable,
1146 .enable_reg = CCM_PCCR1,
1147 .enable_shift = CCM_PCCR1_NFC_BAUD_OFFSET,
1148 .disable = _clk_disable,
1149};
1150
1151static struct clk vpu_clk = {
1152 .name = "vpu_clk",
1153 .parent = &mpll_main_clk[1],
1154 .get_rate = _clk_vpu_recalc,
1155 .enable = _clk_vpu_enable,
1156 .disable = _clk_vpu_disable,
1157};
1158
1159static struct clk dma_clk = {
1160 .name = "dma_clk",
1161 .parent = &ahb_clk,
1162 .enable = _clk_dma_enable,
1163 .disable = _clk_dma_disable,
1164};
1165
1166static struct clk rtic_clk = {
1167 .name = "rtic_clk",
1168 .parent = &ahb_clk,
1169 .enable = _clk_rtic_enable,
1170 .disable = _clk_rtic_disable,
1171};
1172
1173static struct clk brom_clk = {
1174 .name = "brom_clk",
1175 .parent = &ahb_clk,
1176 .enable = _clk_enable,
1177 .enable_reg = CCM_PCCR1,
1178 .enable_shift = CCM_PCCR1_HCLK_BROM_OFFSET,
1179 .disable = _clk_disable,
1180};
1181
1182static struct clk emma_clk = {
1183 .name = "emma_clk",
1184 .parent = &ahb_clk,
1185 .enable = _clk_emma_enable,
1186 .disable = _clk_emma_disable,
1187};
1188
1189static struct clk slcdc_clk = {
1190 .name = "slcdc_clk",
1191 .parent = &ahb_clk,
1192 .enable = _clk_slcdc_enable,
1193 .disable = _clk_slcdc_disable,
1194};
1195
1196static struct clk fec_clk = {
1197 .name = "fec_clk",
1198 .parent = &ahb_clk,
1199 .enable = _clk_fec_enable,
1200 .disable = _clk_fec_disable,
1201};
1202
1203static struct clk emi_clk = {
1204 .name = "emi_clk",
1205 .parent = &ahb_clk,
1206 .enable = _clk_enable,
1207 .enable_reg = CCM_PCCR1,
1208 .enable_shift = CCM_PCCR1_HCLK_EMI_OFFSET,
1209 .disable = _clk_disable,
1210};
1211
1212static struct clk sahara2_clk = {
1213 .name = "sahara_clk",
1214 .parent = &ahb_clk,
1215 .enable = _clk_sahara2_enable,
1216 .disable = _clk_sahara2_disable,
1217};
1218
1219static struct clk ata_clk = {
1220 .name = "ata_clk",
1221 .parent = &ahb_clk,
1222 .enable = _clk_enable,
1223 .enable_reg = CCM_PCCR1,
1224 .enable_shift = CCM_PCCR1_HCLK_ATA_OFFSET,
1225 .disable = _clk_disable,
1226};
1227
1228static struct clk mstick1_clk = {
1229 .name = "mstick1_clk",
1230 .parent = &ipg_clk,
1231 .enable = _clk_mstick1_enable,
1232 .disable = _clk_mstick1_disable,
1233};
1234
1235static struct clk wdog_clk = {
1236 .name = "wdog_clk",
1237 .parent = &ipg_clk,
1238 .enable = _clk_enable,
1239 .enable_reg = CCM_PCCR1,
1240 .enable_shift = CCM_PCCR1_WDT_OFFSET,
1241 .disable = _clk_disable,
1242};
1243
1244static struct clk gpio_clk = {
1245 .name = "gpio_clk",
1246 .parent = &ipg_clk,
1247 .enable = _clk_enable,
1248 .enable_reg = CCM_PCCR1,
1249 .enable_shift = CCM_PCCR0_GPIO_OFFSET,
1250 .disable = _clk_disable,
1251};
1252
1253static struct clk i2c_clk[] = {
1254 {
1255 .name = "i2c_clk",
1256 .id = 0,
1257 .parent = &ipg_clk,
1258 .enable = _clk_enable,
1259 .enable_reg = CCM_PCCR0,
1260 .enable_shift = CCM_PCCR0_I2C1_OFFSET,
1261 .disable = _clk_disable,
1262 }, {
1263 .name = "i2c_clk",
1264 .id = 1,
1265 .parent = &ipg_clk,
1266 .enable = _clk_enable,
1267 .enable_reg = CCM_PCCR0,
1268 .enable_shift = CCM_PCCR0_I2C2_OFFSET,
1269 .disable = _clk_disable,
1270 },
1271};
1272
1273static struct clk iim_clk = {
1274 .name = "iim_clk",
1275 .parent = &ipg_clk,
1276 .enable = _clk_enable,
1277 .enable_reg = CCM_PCCR0,
1278 .enable_shift = CCM_PCCR0_IIM_OFFSET,
1279 .disable = _clk_disable,
1280};
1281
1282static struct clk kpp_clk = {
1283 .name = "kpp_clk",
1284 .parent = &ipg_clk,
1285 .enable = _clk_enable,
1286 .enable_reg = CCM_PCCR0,
1287 .enable_shift = CCM_PCCR0_KPP_OFFSET,
1288 .disable = _clk_disable,
1289};
1290
1291static struct clk owire_clk = {
1292 .name = "owire_clk",
1293 .parent = &ipg_clk,
1294 .enable = _clk_enable,
1295 .enable_reg = CCM_PCCR0,
1296 .enable_shift = CCM_PCCR0_OWIRE_OFFSET,
1297 .disable = _clk_disable,
1298};
1299
1300static struct clk rtc_clk = {
1301 .name = "rtc_clk",
1302 .parent = &ipg_clk,
1303 .enable = _clk_enable,
1304 .enable_reg = CCM_PCCR0,
1305 .enable_shift = CCM_PCCR0_RTC_OFFSET,
1306 .disable = _clk_disable,
1307};
1308
1309static struct clk scc_clk = {
1310 .name = "scc_clk",
1311 .parent = &ipg_clk,
1312 .enable = _clk_enable,
1313 .enable_reg = CCM_PCCR0,
1314 .enable_shift = CCM_PCCR0_SCC_OFFSET,
1315 .disable = _clk_disable,
1316};
1317
1318static unsigned long _clk_clko_round_rate(struct clk *clk, unsigned long rate)
1319{
1320 u32 div;
1321 unsigned long parent_rate;
1322
1323 parent_rate = clk_get_rate(clk->parent);
1324 div = parent_rate / rate;
1325 if (parent_rate % rate)
1326 div++;
1327
1328 if (div > 8)
1329 div = 8;
1330
1331 return parent_rate / div;
1332}
1333
1334static int _clk_clko_set_rate(struct clk *clk, unsigned long rate)
1335{
1336 u32 reg;
1337 u32 div;
1338 unsigned long parent_rate;
1339
1340 parent_rate = clk_get_rate(clk->parent);
1341
1342 div = parent_rate / rate;
1343
1344 if (div > 8 || div < 1 || ((parent_rate / div) != rate))
1345 return -EINVAL;
1346 div--;
1347
1348 reg = __raw_readl(CCM_PCDR0) & ~CCM_PCDR0_CLKODIV_MASK;
1349 reg |= div << CCM_PCDR0_CLKODIV_OFFSET;
1350 __raw_writel(reg, CCM_PCDR0);
1351
1352 return 0;
1353}
1354
1355static unsigned long _clk_clko_recalc(struct clk *clk)
1356{
1357 u32 div;
1358 unsigned long parent_rate;
1359
1360 parent_rate = clk_get_rate(clk->parent);
1361
1362 div = __raw_readl(CCM_PCDR0) & CCM_PCDR0_CLKODIV_MASK >>
1363 CCM_PCDR0_CLKODIV_OFFSET;
1364 div++;
1365
1366 return parent_rate / div;
1367}
1368
1369static int _clk_clko_set_parent(struct clk *clk, struct clk *parent)
1370{
1371 u32 reg;
1372
1373 reg = __raw_readl(CCM_CCSR) & ~CCM_CCSR_CLKOSEL_MASK;
1374
1375 if (parent == &ckil_clk)
1376 reg |= 0 << CCM_CCSR_CLKOSEL_OFFSET;
1377 else if (parent == &ckih_clk)
1378 reg |= 2 << CCM_CCSR_CLKOSEL_OFFSET;
1379 else if (parent == mpll_clk.parent)
1380 reg |= 3 << CCM_CCSR_CLKOSEL_OFFSET;
1381 else if (parent == spll_clk.parent)
1382 reg |= 4 << CCM_CCSR_CLKOSEL_OFFSET;
1383 else if (parent == &mpll_clk)
1384 reg |= 5 << CCM_CCSR_CLKOSEL_OFFSET;
1385 else if (parent == &spll_clk)
1386 reg |= 6 << CCM_CCSR_CLKOSEL_OFFSET;
1387 else if (parent == &cpu_clk)
1388 reg |= 7 << CCM_CCSR_CLKOSEL_OFFSET;
1389 else if (parent == &ahb_clk)
1390 reg |= 8 << CCM_CCSR_CLKOSEL_OFFSET;
1391 else if (parent == &ipg_clk)
1392 reg |= 9 << CCM_CCSR_CLKOSEL_OFFSET;
1393 else if (parent == &per_clk[0])
1394 reg |= 0xA << CCM_CCSR_CLKOSEL_OFFSET;
1395 else if (parent == &per_clk[1])
1396 reg |= 0xB << CCM_CCSR_CLKOSEL_OFFSET;
1397 else if (parent == &per_clk[2])
1398 reg |= 0xC << CCM_CCSR_CLKOSEL_OFFSET;
1399 else if (parent == &per_clk[3])
1400 reg |= 0xD << CCM_CCSR_CLKOSEL_OFFSET;
1401 else if (parent == &ssi1_clk[0])
1402 reg |= 0xE << CCM_CCSR_CLKOSEL_OFFSET;
1403 else if (parent == &ssi2_clk[0])
1404 reg |= 0xF << CCM_CCSR_CLKOSEL_OFFSET;
1405 else if (parent == &nfc_clk)
1406 reg |= 0x10 << CCM_CCSR_CLKOSEL_OFFSET;
1407 else if (parent == &mstick1_clk)
1408 reg |= 0x11 << CCM_CCSR_CLKOSEL_OFFSET;
1409 else if (parent == &vpu_clk)
1410 reg |= 0x12 << CCM_CCSR_CLKOSEL_OFFSET;
1411 else if (parent == &usb_clk[0])
1412 reg |= 0x15 << CCM_CCSR_CLKOSEL_OFFSET;
1413 else
1414 return -EINVAL;
1415
1416 __raw_writel(reg, CCM_CCSR);
1417
1418 return 0;
1419}
1420
1421static int _clk_clko_enable(struct clk *clk)
1422{
1423 u32 reg;
1424
1425 reg = __raw_readl(CCM_PCDR0) | CCM_PCDR0_CLKO_EN;
1426 __raw_writel(reg, CCM_PCDR0);
1427
1428 return 0;
1429}
1430
1431static void _clk_clko_disable(struct clk *clk)
1432{
1433 u32 reg;
1434
1435 reg = __raw_readl(CCM_PCDR0) & ~CCM_PCDR0_CLKO_EN;
1436 __raw_writel(reg, CCM_PCDR0);
1437}
1438
1439static struct clk clko_clk = {
1440 .name = "clko_clk",
1441 .get_rate = _clk_clko_recalc,
1442 .set_rate = _clk_clko_set_rate,
1443 .round_rate = _clk_clko_round_rate,
1444 .set_parent = _clk_clko_set_parent,
1445 .enable = _clk_clko_enable,
1446 .disable = _clk_clko_disable,
1447};
1448
1449static struct clk *mxc_clks[] = {
1450 &ckih_clk,
1451 &ckil_clk,
1452 &mpll_clk,
1453 &mpll_main_clk[0],
1454 &mpll_main_clk[1],
1455 &spll_clk,
1456 &cpu_clk,
1457 &ahb_clk,
1458 &ipg_clk,
1459 &per_clk[0],
1460 &per_clk[1],
1461 &per_clk[2],
1462 &per_clk[3],
1463 &clko_clk,
1464 &uart1_clk[0],
1465 &uart1_clk[1],
1466 &uart2_clk[0],
1467 &uart2_clk[1],
1468 &uart3_clk[0],
1469 &uart3_clk[1],
1470 &uart4_clk[0],
1471 &uart4_clk[1],
1472 &uart5_clk[0],
1473 &uart5_clk[1],
1474 &uart6_clk[0],
1475 &uart6_clk[1],
1476 &gpt1_clk[0],
1477 &gpt1_clk[1],
1478 &gpt2_clk[0],
1479 &gpt2_clk[1],
1480 &gpt3_clk[0],
1481 &gpt3_clk[1],
1482 &gpt4_clk[0],
1483 &gpt4_clk[1],
1484 &gpt5_clk[0],
1485 &gpt5_clk[1],
1486 &gpt6_clk[0],
1487 &gpt6_clk[1],
1488 &pwm_clk[0],
1489 &pwm_clk[1],
1490 &sdhc1_clk[0],
1491 &sdhc1_clk[1],
1492 &sdhc2_clk[0],
1493 &sdhc2_clk[1],
1494 &sdhc3_clk[0],
1495 &sdhc3_clk[1],
1496 &cspi1_clk[0],
1497 &cspi1_clk[1],
1498 &cspi2_clk[0],
1499 &cspi2_clk[1],
1500 &cspi3_clk[0],
1501 &cspi3_clk[1],
1502 &lcdc_clk[0],
1503 &lcdc_clk[1],
1504 &lcdc_clk[2],
1505 &csi_clk[0],
1506 &csi_clk[1],
1507 &usb_clk[0],
1508 &usb_clk[1],
1509 &ssi1_clk[0],
1510 &ssi1_clk[1],
1511 &ssi2_clk[0],
1512 &ssi2_clk[1],
1513 &nfc_clk,
1514 &vpu_clk,
1515 &dma_clk,
1516 &rtic_clk,
1517 &brom_clk,
1518 &emma_clk,
1519 &slcdc_clk,
1520 &fec_clk,
1521 &emi_clk,
1522 &sahara2_clk,
1523 &ata_clk,
1524 &mstick1_clk,
1525 &wdog_clk,
1526 &gpio_clk,
1527 &i2c_clk[0],
1528 &i2c_clk[1],
1529 &iim_clk,
1530 &kpp_clk,
1531 &owire_clk,
1532 &rtc_clk,
1533 &scc_clk,
1534};
1535
1536void __init change_external_low_reference(unsigned long new_ref)
1537{
1538 external_low_reference = new_ref;
1539}
1540
1541unsigned long __init clk_early_get_timer_rate(void)
1542{
1543 return clk_get_rate(&per_clk[0]);
1544}
1545
1546static void __init probe_mxc_clocks(void)
1547{
1548 int i;
1549
1550 if (mx27_revision() >= CHIP_REV_2_0) {
1551 if (CSCR() & 0x8000)
1552 cpu_clk.parent = &mpll_main_clk[0];
1553
1554 if (!(CSCR() & 0x00800000))
1555 ssi2_clk[0].parent = &spll_clk;
1556
1557 if (!(CSCR() & 0x00400000))
1558 ssi1_clk[0].parent = &spll_clk;
1559
1560 if (!(CSCR() & 0x00200000))
1561 vpu_clk.parent = &spll_clk;
1562 } else {
1563 cpu_clk.parent = &mpll_clk;
1564 cpu_clk.set_parent = NULL;
1565 cpu_clk.round_rate = NULL;
1566 cpu_clk.set_rate = NULL;
1567 ahb_clk.parent = &mpll_clk;
1568
1569 for (i = 0; i < sizeof(per_clk) / sizeof(per_clk[0]); i++)
1570 per_clk[i].parent = &mpll_clk;
1571
1572 ssi1_clk[0].parent = &mpll_clk;
1573 ssi2_clk[0].parent = &mpll_clk;
1574
1575 vpu_clk.parent = &mpll_clk;
1576 }
1577}
1578
1579/*
1580 * must be called very early to get information about the
1581 * available clock rate when the timer framework starts
1582 */
1583int __init mxc_clocks_init(unsigned long fref)
1584{
1585 u32 cscr;
1586 struct clk **clkp;
1587
1588 external_high_reference = fref;
1589
1590 /* detect clock reference for both system PLL */
1591 cscr = CSCR();
1592 if (cscr & CCM_CSCR_MCU)
1593 mpll_clk.parent = &ckih_clk;
1594 else
1595 mpll_clk.parent = &ckil_clk;
1596
1597 if (cscr & CCM_CSCR_SP)
1598 spll_clk.parent = &ckih_clk;
1599 else
1600 spll_clk.parent = &ckil_clk;
1601
1602 probe_mxc_clocks();
1603
1604 per_clk[0].enable(&per_clk[0]);
1605 gpt1_clk[1].enable(&gpt1_clk[1]);
1606
1607 for (clkp = mxc_clks; clkp < mxc_clks + ARRAY_SIZE(mxc_clks); clkp++)
1608 clk_register(*clkp);
1609
1610 /* Turn off all possible clocks */
1611 __raw_writel(CCM_PCCR0_GPT1_MASK, CCM_PCCR0);
1612 __raw_writel(CCM_PCCR1_PERCLK1_MASK | CCM_PCCR1_HCLK_EMI_MASK,
1613 CCM_PCCR1);
1614 spll_clk.disable(&spll_clk);
1615
1616 /* This will propagate to all children and init all the clock rates */
1617
1618 clk_enable(&emi_clk);
1619 clk_enable(&gpio_clk);
1620 clk_enable(&iim_clk);
1621 clk_enable(&gpt1_clk[0]);
1622#ifdef CONFIG_DEBUG_LL_CONSOLE
1623 clk_enable(&uart1_clk[0]);
1624#endif
1625 return 0;
1626}
diff --git a/arch/arm/mach-mx2/cpu_imx27.c b/arch/arm/mach-mx2/cpu_imx27.c
new file mode 100644
index 000000000000..d6b5c2e3377f
--- /dev/null
+++ b/arch/arm/mach-mx2/cpu_imx27.c
@@ -0,0 +1,63 @@
1/*
2 * Copyright 2007 Freescale Semiconductor, Inc. All Rights Reserved.
3 * Copyright 2008 Juergen Beisert, kernel@pengutronix.de
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
17 * MA 02110-1301, USA.
18 */
19
20/*
21 * i.MX27 specific CPU detection code
22 */
23
24#include <linux/io.h>
25#include <linux/module.h>
26
27#include <asm/hardware.h>
28
29#include "crm_regs.h"
30
31static int cpu_silicon_rev = -1;
32static int cpu_partnumber;
33
34static void query_silicon_parameter(void)
35{
36 u32 val;
37 /*
38 * now we have access to the IO registers. As we need
39 * the silicon revision very early we read it here to
40 * avoid any further hooks
41 */
42 val = __raw_readl(IO_ADDRESS(SYSCTRL_BASE_ADDR) + SYS_CHIP_ID);
43
44 cpu_silicon_rev = (int)(val >> 28);
45 cpu_partnumber = (int)((val >> 12) & 0xFFFF);
46}
47
48/*
49 * Returns:
50 * the silicon revision of the cpu
51 * -EINVAL - not a mx27
52 */
53int mx27_revision(void)
54{
55 if (cpu_silicon_rev == -1)
56 query_silicon_parameter();
57
58 if (cpu_partnumber != 0x8821)
59 return -EINVAL;
60
61 return cpu_silicon_rev;
62}
63EXPORT_SYMBOL(mx27_revision);
diff --git a/arch/arm/mach-mx2/crm_regs.h b/arch/arm/mach-mx2/crm_regs.h
new file mode 100644
index 000000000000..a40a9b950ce9
--- /dev/null
+++ b/arch/arm/mach-mx2/crm_regs.h
@@ -0,0 +1,273 @@
1/*
2 * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
3 * Copyright 2008 Juergen Beisert, kernel@pengutronix.de
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
17 * MA 02110-1301, USA.
18 */
19
20#ifndef __ARCH_ARM_MACH_MX2_CRM_REGS_H__
21#define __ARCH_ARM_MACH_MX2_CRM_REGS_H__
22
23#include <asm/arch/hardware.h>
24
25/* Register offsets */
26#define CCM_CSCR (IO_ADDRESS(CCM_BASE_ADDR) + 0x0)
27#define CCM_MPCTL0 (IO_ADDRESS(CCM_BASE_ADDR) + 0x4)
28#define CCM_MPCTL1 (IO_ADDRESS(CCM_BASE_ADDR) + 0x8)
29#define CCM_SPCTL0 (IO_ADDRESS(CCM_BASE_ADDR) + 0xC)
30#define CCM_SPCTL1 (IO_ADDRESS(CCM_BASE_ADDR) + 0x10)
31#define CCM_OSC26MCTL (IO_ADDRESS(CCM_BASE_ADDR) + 0x14)
32#define CCM_PCDR0 (IO_ADDRESS(CCM_BASE_ADDR) + 0x18)
33#define CCM_PCDR1 (IO_ADDRESS(CCM_BASE_ADDR) + 0x1c)
34#define CCM_PCCR0 (IO_ADDRESS(CCM_BASE_ADDR) + 0x20)
35#define CCM_PCCR1 (IO_ADDRESS(CCM_BASE_ADDR) + 0x24)
36#define CCM_CCSR (IO_ADDRESS(CCM_BASE_ADDR) + 0x28)
37#define CCM_PMCTL (IO_ADDRESS(CCM_BASE_ADDR) + 0x2c)
38#define CCM_PMCOUNT (IO_ADDRESS(CCM_BASE_ADDR) + 0x30)
39#define CCM_WKGDCTL (IO_ADDRESS(CCM_BASE_ADDR) + 0x34)
40
41#define CCM_CSCR_USB_OFFSET 28
42#define CCM_CSCR_USB_MASK (0x7 << 28)
43#define CCM_CSCR_SD_OFFSET 24
44#define CCM_CSCR_SD_MASK (0x3 << 24)
45#define CCM_CSCR_SSI2 (1 << 23)
46#define CCM_CSCR_SSI2_OFFSET 23
47#define CCM_CSCR_SSI1 (1 << 22)
48#define CCM_CSCR_SSI1_OFFSET 22
49#define CCM_CSCR_VPU (1 << 21)
50#define CCM_CSCR_VPU_OFFSET 21
51#define CCM_CSCR_MSHC (1 << 20)
52#define CCM_CSCR_SPLLRES (1 << 19)
53#define CCM_CSCR_MPLLRES (1 << 18)
54#define CCM_CSCR_SP (1 << 17)
55#define CCM_CSCR_MCU (1 << 16)
56/* CCM_CSCR_ARM_xxx just be avaliable on i.MX27 TO2*/
57#define CCM_CSCR_ARM_SRC (1 << 15)
58#define CCM_CSCR_ARM_OFFSET 12
59#define CCM_CSCR_ARM_MASK (0x3 << 12)
60/* CCM_CSCR_ARM_xxx just be avaliable on i.MX27 TO2*/
61#define CCM_CSCR_PRESC_OFFSET 13
62#define CCM_CSCR_PRESC_MASK (0x7 << 13)
63#define CCM_CSCR_BCLK_OFFSET 9
64#define CCM_CSCR_BCLK_MASK (0xf << 9)
65#define CCM_CSCR_IPDIV_OFFSET 8
66#define CCM_CSCR_IPDIV (1 << 8)
67/* CCM_CSCR_AHB_xxx just be avaliable on i.MX27 TO2*/
68#define CCM_CSCR_AHB_OFFSET 8
69#define CCM_CSCR_AHB_MASK (0x3 << 8)
70/* CCM_CSCR_AHB_xxx just be avaliable on i.MX27 TO2*/
71#define CCM_CSCR_OSC26MDIV (1 << 4)
72#define CCM_CSCR_OSC26M (1 << 3)
73#define CCM_CSCR_FPM (1 << 2)
74#define CCM_CSCR_SPEN (1 << 1)
75#define CCM_CSCR_MPEN 1
76
77#define CCM_MPCTL0_CPLM (1 << 31)
78#define CCM_MPCTL0_PD_OFFSET 26
79#define CCM_MPCTL0_PD_MASK (0xf << 26)
80#define CCM_MPCTL0_MFD_OFFSET 16
81#define CCM_MPCTL0_MFD_MASK (0x3ff << 16)
82#define CCM_MPCTL0_MFI_OFFSET 10
83#define CCM_MPCTL0_MFI_MASK (0xf << 10)
84#define CCM_MPCTL0_MFN_OFFSET 0
85#define CCM_MPCTL0_MFN_MASK 0x3ff
86
87#define CCM_MPCTL1_LF (1 << 15)
88#define CCM_MPCTL1_BRMO (1 << 6)
89
90#define CCM_SPCTL0_CPLM (1 << 31)
91#define CCM_SPCTL0_PD_OFFSET 26
92#define CCM_SPCTL0_PD_MASK (0xf << 26)
93#define CCM_SPCTL0_MFD_OFFSET 16
94#define CCM_SPCTL0_MFD_MASK (0x3ff << 16)
95#define CCM_SPCTL0_MFI_OFFSET 10
96#define CCM_SPCTL0_MFI_MASK (0xf << 10)
97#define CCM_SPCTL0_MFN_OFFSET 0
98#define CCM_SPCTL0_MFN_MASK 0x3ff
99
100#define CCM_SPCTL1_LF (1 << 15)
101#define CCM_SPCTL1_BRMO (1 << 6)
102
103#define CCM_OSC26MCTL_PEAK_OFFSET 16
104#define CCM_OSC26MCTL_PEAK_MASK (0x3 << 16)
105#define CCM_OSC26MCTL_AGC_OFFSET 8
106#define CCM_OSC26MCTL_AGC_MASK (0x3f << 8)
107#define CCM_OSC26MCTL_ANATEST_OFFSET 0
108#define CCM_OSC26MCTL_ANATEST_MASK 0x3f
109
110#define CCM_PCDR0_SSI2BAUDDIV_OFFSET 26
111#define CCM_PCDR0_SSI2BAUDDIV_MASK (0x3f << 26)
112#define CCM_PCDR0_CLKO_EN 25
113#define CCM_PCDR0_CLKODIV_OFFSET 22
114#define CCM_PCDR0_CLKODIV_MASK (0x7 << 22)
115#define CCM_PCDR0_SSI1BAUDDIV_OFFSET 16
116#define CCM_PCDR0_SSI1BAUDDIV_MASK (0x3f << 16)
117/*The difinition for i.MX27 TO2*/
118#define CCM_PCDR0_VPUDIV2_OFFSET 10
119#define CCM_PCDR0_VPUDIV2_MASK (0x3f << 10)
120#define CCM_PCDR0_NFCDIV2_OFFSET 6
121#define CCM_PCDR0_NFCDIV2_MASK (0xf << 6)
122#define CCM_PCDR0_MSHCDIV2_MASK 0x3f
123/*The difinition for i.MX27 TO2*/
124#define CCM_PCDR0_NFCDIV_OFFSET 12
125#define CCM_PCDR0_NFCDIV_MASK (0xf << 12)
126#define CCM_PCDR0_VPUDIV_OFFSET 8
127#define CCM_PCDR0_VPUDIV_MASK (0xf << 8)
128#define CCM_PCDR0_MSHCDIV_OFFSET 0
129#define CCM_PCDR0_MSHCDIV_MASK 0x1f
130
131#define CCM_PCDR1_PERDIV4_OFFSET 24
132#define CCM_PCDR1_PERDIV4_MASK (0x3f << 24)
133#define CCM_PCDR1_PERDIV3_OFFSET 16
134#define CCM_PCDR1_PERDIV3_MASK (0x3f << 16)
135#define CCM_PCDR1_PERDIV2_OFFSET 8
136#define CCM_PCDR1_PERDIV2_MASK (0x3f << 8)
137#define CCM_PCDR1_PERDIV1_OFFSET 0
138#define CCM_PCDR1_PERDIV1_MASK 0x3f
139
140#define CCM_PCCR0_CSPI1_OFFSET 31
141#define CCM_PCCR0_CSPI1_MASK (1 << 31)
142#define CCM_PCCR0_CSPI2_OFFSET 30
143#define CCM_PCCR0_CSPI2_MASK (1 << 30)
144#define CCM_PCCR0_CSPI3_OFFSET 29
145#define CCM_PCCR0_CSPI3_MASK (1 << 29)
146#define CCM_PCCR0_DMA_OFFSET 28
147#define CCM_PCCR0_DMA_MASK (1 << 28)
148#define CCM_PCCR0_EMMA_OFFSET 27
149#define CCM_PCCR0_EMMA_MASK (1 << 27)
150#define CCM_PCCR0_FEC_OFFSET 26
151#define CCM_PCCR0_FEC_MASK (1 << 26)
152#define CCM_PCCR0_GPIO_OFFSET 25
153#define CCM_PCCR0_GPIO_MASK (1 << 25)
154#define CCM_PCCR0_GPT1_OFFSET 24
155#define CCM_PCCR0_GPT1_MASK (1 << 24)
156#define CCM_PCCR0_GPT2_OFFSET 23
157#define CCM_PCCR0_GPT2_MASK (1 << 23)
158#define CCM_PCCR0_GPT3_OFFSET 22
159#define CCM_PCCR0_GPT3_MASK (1 << 22)
160#define CCM_PCCR0_GPT4_OFFSET 21
161#define CCM_PCCR0_GPT4_MASK (1 << 21)
162#define CCM_PCCR0_GPT5_OFFSET 20
163#define CCM_PCCR0_GPT5_MASK (1 << 20)
164#define CCM_PCCR0_GPT6_OFFSET 19
165#define CCM_PCCR0_GPT6_MASK (1 << 19)
166#define CCM_PCCR0_I2C1_OFFSET 18
167#define CCM_PCCR0_I2C1_MASK (1 << 18)
168#define CCM_PCCR0_I2C2_OFFSET 17
169#define CCM_PCCR0_I2C2_MASK (1 << 17)
170#define CCM_PCCR0_IIM_OFFSET 16
171#define CCM_PCCR0_IIM_MASK (1 << 16)
172#define CCM_PCCR0_KPP_OFFSET 15
173#define CCM_PCCR0_KPP_MASK (1 << 15)
174#define CCM_PCCR0_LCDC_OFFSET 14
175#define CCM_PCCR0_LCDC_MASK (1 << 14)
176#define CCM_PCCR0_MSHC_OFFSET 13
177#define CCM_PCCR0_MSHC_MASK (1 << 13)
178#define CCM_PCCR0_OWIRE_OFFSET 12
179#define CCM_PCCR0_OWIRE_MASK (1 << 12)
180#define CCM_PCCR0_PWM_OFFSET 11
181#define CCM_PCCR0_PWM_MASK (1 << 11)
182#define CCM_PCCR0_RTC_OFFSET 9
183#define CCM_PCCR0_RTC_MASK (1 << 9)
184#define CCM_PCCR0_RTIC_OFFSET 8
185#define CCM_PCCR0_RTIC_MASK (1 << 8)
186#define CCM_PCCR0_SAHARA_OFFSET 7
187#define CCM_PCCR0_SAHARA_MASK (1 << 7)
188#define CCM_PCCR0_SCC_OFFSET 6
189#define CCM_PCCR0_SCC_MASK (1 << 6)
190#define CCM_PCCR0_SDHC1_OFFSET 5
191#define CCM_PCCR0_SDHC1_MASK (1 << 5)
192#define CCM_PCCR0_SDHC2_OFFSET 4
193#define CCM_PCCR0_SDHC2_MASK (1 << 4)
194#define CCM_PCCR0_SDHC3_OFFSET 3
195#define CCM_PCCR0_SDHC3_MASK (1 << 3)
196#define CCM_PCCR0_SLCDC_OFFSET 2
197#define CCM_PCCR0_SLCDC_MASK (1 << 2)
198#define CCM_PCCR0_SSI1_IPG_OFFSET 1
199#define CCM_PCCR0_SSI1_IPG_MASK (1 << 1)
200#define CCM_PCCR0_SSI2_IPG_OFFSET 0
201#define CCM_PCCR0_SSI2_IPG_MASK (1 << 0)
202
203#define CCM_PCCR1_UART1_OFFSET 31
204#define CCM_PCCR1_UART1_MASK (1 << 31)
205#define CCM_PCCR1_UART2_OFFSET 30
206#define CCM_PCCR1_UART2_MASK (1 << 30)
207#define CCM_PCCR1_UART3_OFFSET 29
208#define CCM_PCCR1_UART3_MASK (1 << 29)
209#define CCM_PCCR1_UART4_OFFSET 28
210#define CCM_PCCR1_UART4_MASK (1 << 28)
211#define CCM_PCCR1_UART5_OFFSET 27
212#define CCM_PCCR1_UART5_MASK (1 << 27)
213#define CCM_PCCR1_UART6_OFFSET 26
214#define CCM_PCCR1_UART6_MASK (1 << 26)
215#define CCM_PCCR1_USBOTG_OFFSET 25
216#define CCM_PCCR1_USBOTG_MASK (1 << 25)
217#define CCM_PCCR1_WDT_OFFSET 24
218#define CCM_PCCR1_WDT_MASK (1 << 24)
219#define CCM_PCCR1_HCLK_ATA_OFFSET 23
220#define CCM_PCCR1_HCLK_ATA_MASK (1 << 23)
221#define CCM_PCCR1_HCLK_BROM_OFFSET 22
222#define CCM_PCCR1_HCLK_BROM_MASK (1 << 22)
223#define CCM_PCCR1_HCLK_CSI_OFFSET 21
224#define CCM_PCCR1_HCLK_CSI_MASK (1 << 21)
225#define CCM_PCCR1_HCLK_DMA_OFFSET 20
226#define CCM_PCCR1_HCLK_DMA_MASK (1 << 20)
227#define CCM_PCCR1_HCLK_EMI_OFFSET 19
228#define CCM_PCCR1_HCLK_EMI_MASK (1 << 19)
229#define CCM_PCCR1_HCLK_EMMA_OFFSET 18
230#define CCM_PCCR1_HCLK_EMMA_MASK (1 << 18)
231#define CCM_PCCR1_HCLK_FEC_OFFSET 17
232#define CCM_PCCR1_HCLK_FEC_MASK (1 << 17)
233#define CCM_PCCR1_HCLK_VPU_OFFSET 16
234#define CCM_PCCR1_HCLK_VPU_MASK (1 << 16)
235#define CCM_PCCR1_HCLK_LCDC_OFFSET 15
236#define CCM_PCCR1_HCLK_LCDC_MASK (1 << 15)
237#define CCM_PCCR1_HCLK_RTIC_OFFSET 14
238#define CCM_PCCR1_HCLK_RTIC_MASK (1 << 14)
239#define CCM_PCCR1_HCLK_SAHARA_OFFSET 13
240#define CCM_PCCR1_HCLK_SAHARA_MASK (1 << 13)
241#define CCM_PCCR1_HCLK_SLCDC_OFFSET 12
242#define CCM_PCCR1_HCLK_SLCDC_MASK (1 << 12)
243#define CCM_PCCR1_HCLK_USBOTG_OFFSET 11
244#define CCM_PCCR1_HCLK_USBOTG_MASK (1 << 11)
245#define CCM_PCCR1_PERCLK1_OFFSET 10
246#define CCM_PCCR1_PERCLK1_MASK (1 << 10)
247#define CCM_PCCR1_PERCLK2_OFFSET 9
248#define CCM_PCCR1_PERCLK2_MASK (1 << 9)
249#define CCM_PCCR1_PERCLK3_OFFSET 8
250#define CCM_PCCR1_PERCLK3_MASK (1 << 8)
251#define CCM_PCCR1_PERCLK4_OFFSET 7
252#define CCM_PCCR1_PERCLK4_MASK (1 << 7)
253#define CCM_PCCR1_VPU_BAUD_OFFSET 6
254#define CCM_PCCR1_VPU_BAUD_MASK (1 << 6)
255#define CCM_PCCR1_SSI1_BAUD_OFFSET 5
256#define CCM_PCCR1_SSI1_BAUD_MASK (1 << 5)
257#define CCM_PCCR1_SSI2_BAUD_OFFSET 4
258#define CCM_PCCR1_SSI2_BAUD_MASK (1 << 4)
259#define CCM_PCCR1_NFC_BAUD_OFFSET 3
260#define CCM_PCCR1_NFC_BAUD_MASK (1 << 3)
261#define CCM_PCCR1_MSHC_BAUD_OFFSET 2
262#define CCM_PCCR1_MSHC_BAUD_MASK (1 << 2)
263
264#define CCM_CCSR_32KSR (1 << 15)
265#define CCM_CCSR_CLKMODE1 (1 << 9)
266#define CCM_CCSR_CLKMODE0 (1 << 8)
267#define CCM_CCSR_CLKOSEL_OFFSET 0
268#define CCM_CCSR_CLKOSEL_MASK 0x1f
269
270#define SYS_FMCR 0x14 /* Functional Muxing Control Reg */
271#define SYS_CHIP_ID 0x00 /* The offset of CHIP ID register */
272
273#endif /* __ARCH_ARM_MACH_MX2_CRM_REGS_H__ */
diff --git a/arch/arm/mach-mx2/devices.c b/arch/arm/mach-mx2/devices.c
new file mode 100644
index 000000000000..a1f44c3c5315
--- /dev/null
+++ b/arch/arm/mach-mx2/devices.c
@@ -0,0 +1,231 @@
1/*
2 * Author: MontaVista Software, Inc.
3 * <source@mvista.com>
4 *
5 * Based on the OMAP devices.c
6 *
7 * 2005 (c) MontaVista Software, Inc. This file is licensed under the
8 * terms of the GNU General Public License version 2. This program is
9 * licensed "as is" without any warranty of any kind, whether express
10 * or implied.
11 *
12 * Copyright 2006-2007 Freescale Semiconductor, Inc. All Rights Reserved.
13 * Copyright 2008 Juergen Beisert, kernel@pengutronix.de
14 *
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License
17 * as published by the Free Software Foundation; either version 2
18 * of the License, or (at your option) any later version.
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
27 * MA 02110-1301, USA.
28 */
29#include <linux/module.h>
30#include <linux/kernel.h>
31#include <linux/init.h>
32#include <linux/platform_device.h>
33#include <linux/gpio.h>
34
35#include <asm/hardware.h>
36
37/*
38 * Resource definition for the MXC IrDA
39 */
40static struct resource mxc_irda_resources[] = {
41 [0] = {
42 .start = UART3_BASE_ADDR,
43 .end = UART3_BASE_ADDR + SZ_4K - 1,
44 .flags = IORESOURCE_MEM,
45 },
46 [1] = {
47 .start = MXC_INT_UART3,
48 .end = MXC_INT_UART3,
49 .flags = IORESOURCE_IRQ,
50 },
51};
52
53/* Platform Data for MXC IrDA */
54struct platform_device mxc_irda_device = {
55 .name = "mxc_irda",
56 .id = 0,
57 .num_resources = ARRAY_SIZE(mxc_irda_resources),
58 .resource = mxc_irda_resources,
59};
60
61/*
62 * General Purpose Timer
63 * - i.MX1: 2 timer (slighly different register handling)
64 * - i.MX21: 3 timer
65 * - i.MX27: 6 timer
66 */
67
68/* We use gpt0 as system timer, so do not add a device for this one */
69
70static struct resource timer1_resources[] = {
71 [0] = {
72 .start = GPT2_BASE_ADDR,
73 .end = GPT2_BASE_ADDR + 0x17,
74 .flags = IORESOURCE_MEM
75 },
76 [1] = {
77 .start = MXC_INT_GPT2,
78 .end = MXC_INT_GPT2,
79 .flags = IORESOURCE_IRQ,
80 }
81};
82
83struct platform_device mxc_gpt1 = {
84 .name = "imx_gpt",
85 .id = 1,
86 .num_resources = ARRAY_SIZE(timer1_resources),
87 .resource = timer1_resources
88};
89
90static struct resource timer2_resources[] = {
91 [0] = {
92 .start = GPT3_BASE_ADDR,
93 .end = GPT3_BASE_ADDR + 0x17,
94 .flags = IORESOURCE_MEM
95 },
96 [1] = {
97 .start = MXC_INT_GPT3,
98 .end = MXC_INT_GPT3,
99 .flags = IORESOURCE_IRQ,
100 }
101};
102
103struct platform_device mxc_gpt2 = {
104 .name = "imx_gpt",
105 .id = 2,
106 .num_resources = ARRAY_SIZE(timer2_resources),
107 .resource = timer2_resources
108};
109
110#ifdef CONFIG_MACH_MX27
111static struct resource timer3_resources[] = {
112 [0] = {
113 .start = GPT4_BASE_ADDR,
114 .end = GPT4_BASE_ADDR + 0x17,
115 .flags = IORESOURCE_MEM
116 },
117 [1] = {
118 .start = MXC_INT_GPT4,
119 .end = MXC_INT_GPT4,
120 .flags = IORESOURCE_IRQ,
121 }
122};
123
124struct platform_device mxc_gpt3 = {
125 .name = "imx_gpt",
126 .id = 3,
127 .num_resources = ARRAY_SIZE(timer3_resources),
128 .resource = timer3_resources
129};
130
131static struct resource timer4_resources[] = {
132 [0] = {
133 .start = GPT5_BASE_ADDR,
134 .end = GPT5_BASE_ADDR + 0x17,
135 .flags = IORESOURCE_MEM
136 },
137 [1] = {
138 .start = MXC_INT_GPT5,
139 .end = MXC_INT_GPT5,
140 .flags = IORESOURCE_IRQ,
141 }
142};
143
144struct platform_device mxc_gpt4 = {
145 .name = "imx_gpt",
146 .id = 4,
147 .num_resources = ARRAY_SIZE(timer4_resources),
148 .resource = timer4_resources
149};
150
151static struct resource timer5_resources[] = {
152 [0] = {
153 .start = GPT6_BASE_ADDR,
154 .end = GPT6_BASE_ADDR + 0x17,
155 .flags = IORESOURCE_MEM
156 },
157 [1] = {
158 .start = MXC_INT_GPT6,
159 .end = MXC_INT_GPT6,
160 .flags = IORESOURCE_IRQ,
161 }
162};
163
164struct platform_device mxc_gpt5 = {
165 .name = "imx_gpt",
166 .id = 5,
167 .num_resources = ARRAY_SIZE(timer5_resources),
168 .resource = timer5_resources
169};
170#endif
171
172/*
173 * Watchdog:
174 * - i.MX1
175 * - i.MX21
176 * - i.MX27
177 */
178static struct resource mxc_wdt_resources[] = {
179 {
180 .start = WDOG_BASE_ADDR,
181 .end = WDOG_BASE_ADDR + 0x30,
182 .flags = IORESOURCE_MEM,
183 },
184};
185
186struct platform_device mxc_wdt = {
187 .name = "mxc_wdt",
188 .id = 0,
189 .num_resources = ARRAY_SIZE(mxc_wdt_resources),
190 .resource = mxc_wdt_resources,
191};
192
193/* GPIO port description */
194static struct mxc_gpio_port imx_gpio_ports[] = {
195 [0] = {
196 .chip.label = "gpio-0",
197 .irq = MXC_INT_GPIO,
198 .base = (void*)(AIPI_BASE_ADDR_VIRT + 0x15000 + 0x100 * 0),
199 .virtual_irq_start = MXC_MAX_INT_LINES,
200 },
201 [1] = {
202 .chip.label = "gpio-1",
203 .base = (void*)(AIPI_BASE_ADDR_VIRT + 0x15000 + 0x100 * 1),
204 .virtual_irq_start = MXC_MAX_INT_LINES + 32,
205 },
206 [2] = {
207 .chip.label = "gpio-2",
208 .base = (void*)(AIPI_BASE_ADDR_VIRT + 0x15000 + 0x100 * 2),
209 .virtual_irq_start = MXC_MAX_INT_LINES + 64,
210 },
211 [3] = {
212 .chip.label = "gpio-3",
213 .base = (void*)(AIPI_BASE_ADDR_VIRT + 0x15000 + 0x100 * 3),
214 .virtual_irq_start = MXC_MAX_INT_LINES + 96,
215 },
216 [4] = {
217 .chip.label = "gpio-4",
218 .base = (void*)(AIPI_BASE_ADDR_VIRT + 0x15000 + 0x100 * 4),
219 .virtual_irq_start = MXC_MAX_INT_LINES + 128,
220 },
221 [5] = {
222 .chip.label = "gpio-5",
223 .base = (void*)(AIPI_BASE_ADDR_VIRT + 0x15000 + 0x100 * 5),
224 .virtual_irq_start = MXC_MAX_INT_LINES + 160,
225 }
226};
227
228int __init mxc_register_gpios(void)
229{
230 return mxc_gpio_init(imx_gpio_ports, ARRAY_SIZE(imx_gpio_ports));
231}
diff --git a/arch/arm/mach-mx2/generic.c b/arch/arm/mach-mx2/generic.c
new file mode 100644
index 000000000000..07875cf00de9
--- /dev/null
+++ b/arch/arm/mach-mx2/generic.c
@@ -0,0 +1,74 @@
1/*
2 * generic.c
3 *
4 * Copyright (C) 2008 Juergen Beisert (kernel@pengutronix.de)
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/mm.h>
22#include <linux/init.h>
23#include <asm/hardware.h>
24#include <asm/pgtable.h>
25#include <asm/mach/map.h>
26
27/* MX27 memory map definition */
28static struct map_desc mxc_io_desc[] __initdata = {
29 /*
30 * this fixed mapping covers:
31 * - AIPI1
32 * - AIPI2
33 * - AITC
34 * - ROM Patch
35 * - and some reserved space
36 */
37 {
38 .virtual = AIPI_BASE_ADDR_VIRT,
39 .pfn = __phys_to_pfn(AIPI_BASE_ADDR),
40 .length = AIPI_SIZE,
41 .type = MT_DEVICE
42 },
43 /*
44 * this fixed mapping covers:
45 * - CSI
46 * - ATA
47 */
48 {
49 .virtual = SAHB1_BASE_ADDR_VIRT,
50 .pfn = __phys_to_pfn(SAHB1_BASE_ADDR),
51 .length = SAHB1_SIZE,
52 .type = MT_DEVICE
53 },
54 /*
55 * this fixed mapping covers:
56 * - EMI
57 */
58 {
59 .virtual = X_MEMC_BASE_ADDR_VIRT,
60 .pfn = __phys_to_pfn(X_MEMC_BASE_ADDR),
61 .length = X_MEMC_SIZE,
62 .type = MT_DEVICE
63 }
64};
65
66/*
67 * Initialize the memory map. It is called during the
68 * system startup to create static physical to virtual
69 * memory map for the IO modules.
70 */
71void __init mxc_map_io(void)
72{
73 iotable_init(mxc_io_desc, ARRAY_SIZE(mxc_io_desc));
74}
diff --git a/arch/arm/mach-mx2/mx27ads.c b/arch/arm/mach-mx2/mx27ads.c
new file mode 100644
index 000000000000..a9ff01fff137
--- /dev/null
+++ b/arch/arm/mach-mx2/mx27ads.c
@@ -0,0 +1,304 @@
1/*
2 * Copyright (C) 2000 Deep Blue Solutions Ltd
3 * Copyright (C) 2002 Shane Nay (shane@minirl.com)
4 * Copyright 2006-2007 Freescale Semiconductor, Inc. All Rights Reserved.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#include <linux/platform_device.h>
22#include <linux/mtd/mtd.h>
23#include <linux/mtd/map.h>
24#include <linux/mtd/partitions.h>
25#include <linux/mtd/physmap.h>
26#include <asm/arch/common.h>
27#include <asm/hardware.h>
28#include <asm/mach-types.h>
29#include <asm/mach/arch.h>
30#include <asm/mach/time.h>
31#include <asm/mach/map.h>
32#include <asm/arch/gpio.h>
33#include <asm/arch/imx-uart.h>
34#include <asm/arch/iomux-mx1-mx2.h>
35#include <asm/arch/board-mx27ads.h>
36
37/* ADS's NOR flash */
38static struct physmap_flash_data mx27ads_flash_data = {
39 .width = 2,
40};
41
42static struct resource mx27ads_flash_resource = {
43 .start = 0xc0000000,
44 .end = 0xc0000000 + 0x02000000 - 1,
45 .flags = IORESOURCE_MEM,
46
47};
48
49static struct platform_device mx27ads_nor_mtd_device = {
50 .name = "physmap-flash",
51 .id = 0,
52 .dev = {
53 .platform_data = &mx27ads_flash_data,
54 },
55 .num_resources = 1,
56 .resource = &mx27ads_flash_resource,
57};
58
59static int mxc_uart0_pins[] = {
60 PE12_PF_UART1_TXD,
61 PE13_PF_UART1_RXD,
62 PE14_PF_UART1_CTS,
63 PE15_PF_UART1_RTS
64};
65
66static int uart_mxc_port0_init(struct platform_device *pdev)
67{
68 return mxc_gpio_setup_multiple_pins(mxc_uart0_pins,
69 ARRAY_SIZE(mxc_uart0_pins),
70 MXC_GPIO_ALLOC_MODE_NORMAL, "UART0");
71}
72
73static int uart_mxc_port0_exit(struct platform_device *pdev)
74{
75 return mxc_gpio_setup_multiple_pins(mxc_uart0_pins,
76 ARRAY_SIZE(mxc_uart0_pins),
77 MXC_GPIO_ALLOC_MODE_RELEASE, "UART0");
78}
79
80static int mxc_uart1_pins[] = {
81 PE3_PF_UART2_CTS,
82 PE4_PF_UART2_RTS,
83 PE6_PF_UART2_TXD,
84 PE7_PF_UART2_RXD
85};
86
87static int uart_mxc_port1_init(struct platform_device *pdev)
88{
89 return mxc_gpio_setup_multiple_pins(mxc_uart1_pins,
90 ARRAY_SIZE(mxc_uart1_pins),
91 MXC_GPIO_ALLOC_MODE_NORMAL, "UART1");
92}
93
94static int uart_mxc_port1_exit(struct platform_device *pdev)
95{
96 return mxc_gpio_setup_multiple_pins(mxc_uart1_pins,
97 ARRAY_SIZE(mxc_uart1_pins),
98 MXC_GPIO_ALLOC_MODE_RELEASE, "UART1");
99}
100
101static int mxc_uart2_pins[] = {
102 PE8_PF_UART3_TXD,
103 PE9_PF_UART3_RXD,
104 PE10_PF_UART3_CTS,
105 PE11_PF_UART3_RTS
106};
107
108static int uart_mxc_port2_init(struct platform_device *pdev)
109{
110 return mxc_gpio_setup_multiple_pins(mxc_uart2_pins,
111 ARRAY_SIZE(mxc_uart2_pins),
112 MXC_GPIO_ALLOC_MODE_NORMAL, "UART2");
113}
114
115static int uart_mxc_port2_exit(struct platform_device *pdev)
116{
117 return mxc_gpio_setup_multiple_pins(mxc_uart2_pins,
118 ARRAY_SIZE(mxc_uart2_pins),
119 MXC_GPIO_ALLOC_MODE_RELEASE, "UART2");
120}
121
122static int mxc_uart3_pins[] = {
123 PB26_AF_UART4_RTS,
124 PB28_AF_UART4_TXD,
125 PB29_AF_UART4_CTS,
126 PB31_AF_UART4_RXD
127};
128
129static int uart_mxc_port3_init(struct platform_device *pdev)
130{
131 return mxc_gpio_setup_multiple_pins(mxc_uart3_pins,
132 ARRAY_SIZE(mxc_uart3_pins),
133 MXC_GPIO_ALLOC_MODE_NORMAL, "UART3");
134}
135
136static int uart_mxc_port3_exit(struct platform_device *pdev)
137{
138 return mxc_gpio_setup_multiple_pins(mxc_uart3_pins,
139 ARRAY_SIZE(mxc_uart3_pins),
140 MXC_GPIO_ALLOC_MODE_RELEASE, "UART3");
141}
142
143static int mxc_uart4_pins[] = {
144 PB18_AF_UART5_TXD,
145 PB19_AF_UART5_RXD,
146 PB20_AF_UART5_CTS,
147 PB21_AF_UART5_RTS
148};
149
150static int uart_mxc_port4_init(struct platform_device *pdev)
151{
152 return mxc_gpio_setup_multiple_pins(mxc_uart4_pins,
153 ARRAY_SIZE(mxc_uart4_pins),
154 MXC_GPIO_ALLOC_MODE_NORMAL, "UART4");
155}
156
157static int uart_mxc_port4_exit(struct platform_device *pdev)
158{
159 return mxc_gpio_setup_multiple_pins(mxc_uart4_pins,
160 ARRAY_SIZE(mxc_uart4_pins),
161 MXC_GPIO_ALLOC_MODE_RELEASE, "UART4");
162}
163
164static int mxc_uart5_pins[] = {
165 PB10_AF_UART6_TXD,
166 PB12_AF_UART6_CTS,
167 PB11_AF_UART6_RXD,
168 PB13_AF_UART6_RTS
169};
170
171static int uart_mxc_port5_init(struct platform_device *pdev)
172{
173 return mxc_gpio_setup_multiple_pins(mxc_uart5_pins,
174 ARRAY_SIZE(mxc_uart5_pins),
175 MXC_GPIO_ALLOC_MODE_NORMAL, "UART5");
176}
177
178static int uart_mxc_port5_exit(struct platform_device *pdev)
179{
180 return mxc_gpio_setup_multiple_pins(mxc_uart5_pins,
181 ARRAY_SIZE(mxc_uart5_pins),
182 MXC_GPIO_ALLOC_MODE_RELEASE, "UART5");
183}
184
185static struct platform_device *platform_devices[] __initdata = {
186 &mx27ads_nor_mtd_device,
187};
188
189static int mxc_fec_pins[] = {
190 PD0_AIN_FEC_TXD0,
191 PD1_AIN_FEC_TXD1,
192 PD2_AIN_FEC_TXD2,
193 PD3_AIN_FEC_TXD3,
194 PD4_AOUT_FEC_RX_ER,
195 PD5_AOUT_FEC_RXD1,
196 PD6_AOUT_FEC_RXD2,
197 PD7_AOUT_FEC_RXD3,
198 PD8_AF_FEC_MDIO,
199 PD9_AIN_FEC_MDC,
200 PD10_AOUT_FEC_CRS,
201 PD11_AOUT_FEC_TX_CLK,
202 PD12_AOUT_FEC_RXD0,
203 PD13_AOUT_FEC_RX_DV,
204 PD14_AOUT_FEC_CLR,
205 PD15_AOUT_FEC_COL,
206 PD16_AIN_FEC_TX_ER,
207 PF23_AIN_FEC_TX_EN
208};
209
210static void gpio_fec_active(void)
211{
212 mxc_gpio_setup_multiple_pins(mxc_fec_pins,
213 ARRAY_SIZE(mxc_fec_pins),
214 MXC_GPIO_ALLOC_MODE_NORMAL, "FEC");
215}
216
217static void gpio_fec_inactive(void)
218{
219 mxc_gpio_setup_multiple_pins(mxc_fec_pins,
220 ARRAY_SIZE(mxc_fec_pins),
221 MXC_GPIO_ALLOC_MODE_RELEASE, "FEC");
222}
223
224static struct imxuart_platform_data uart_pdata[] = {
225 {
226 .init = uart_mxc_port0_init,
227 .exit = uart_mxc_port0_exit,
228 .flags = IMXUART_HAVE_RTSCTS,
229 }, {
230 .init = uart_mxc_port1_init,
231 .exit = uart_mxc_port1_exit,
232 .flags = IMXUART_HAVE_RTSCTS,
233 }, {
234 .init = uart_mxc_port2_init,
235 .exit = uart_mxc_port2_exit,
236 .flags = IMXUART_HAVE_RTSCTS,
237 }, {
238 .init = uart_mxc_port3_init,
239 .exit = uart_mxc_port3_exit,
240 .flags = IMXUART_HAVE_RTSCTS,
241 }, {
242 .init = uart_mxc_port4_init,
243 .exit = uart_mxc_port4_exit,
244 .flags = IMXUART_HAVE_RTSCTS,
245 }, {
246 .init = uart_mxc_port5_init,
247 .exit = uart_mxc_port5_exit,
248 .flags = IMXUART_HAVE_RTSCTS,
249 },
250};
251
252static void __init mx27ads_board_init(void)
253{
254 int i;
255
256 gpio_fec_active();
257
258 for (i = 0; i < 6; i++)
259 imx_init_uart(i, &uart_pdata[i]);
260
261 platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
262}
263
264static void __init mx27ads_timer_init(void)
265{
266 unsigned long fref = 26000000;
267
268 if ((__raw_readw(PBC_VERSION_REG) & CKIH_27MHZ_BIT_SET) == 0)
269 fref = 27000000;
270
271 mxc_clocks_init(fref);
272 mxc_timer_init("gpt_clk.0");
273}
274
275struct sys_timer mx27ads_timer = {
276 .init = mx27ads_timer_init,
277};
278
279static struct map_desc mx27ads_io_desc[] __initdata = {
280 {
281 .virtual = PBC_BASE_ADDRESS,
282 .pfn = __phys_to_pfn(CS4_BASE_ADDR),
283 .length = SZ_1M,
284 .type = MT_DEVICE,
285 },
286};
287
288void __init mx27ads_map_io(void)
289{
290 mxc_map_io();
291 iotable_init(mx27ads_io_desc, ARRAY_SIZE(mx27ads_io_desc));
292}
293
294MACHINE_START(MX27ADS, "Freescale i.MX27ADS")
295 /* maintainer: Freescale Semiconductor, Inc. */
296 .phys_io = AIPI_BASE_ADDR,
297 .io_pg_offst = ((AIPI_BASE_ADDR_VIRT) >> 18) & 0xfffc,
298 .boot_params = PHYS_OFFSET + 0x100,
299 .map_io = mx27ads_map_io,
300 .init_irq = mxc_init_irq,
301 .init_machine = mx27ads_board_init,
302 .timer = &mx27ads_timer,
303MACHINE_END
304
diff --git a/arch/arm/mach-mx2/pcm038.c b/arch/arm/mach-mx2/pcm038.c
new file mode 100644
index 000000000000..a9a28f58e714
--- /dev/null
+++ b/arch/arm/mach-mx2/pcm038.c
@@ -0,0 +1,204 @@
1/*
2 * Copyright 2007 Robert Schwebel <r.schwebel@pengutronix.de>, Pengutronix
3 * Copyright (C) 2008 Juergen Beisert (kernel@pengutronix.de)
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
17 * MA 02110-1301, USA.
18 */
19
20#include <linux/platform_device.h>
21#include <linux/mtd/physmap.h>
22#include <asm/mach/arch.h>
23#include <asm/mach-types.h>
24#include <asm/arch/common.h>
25#include <asm/hardware.h>
26#include <asm/arch/iomux-mx1-mx2.h>
27#include <asm/mach/time.h>
28#include <asm/arch/imx-uart.h>
29#include <asm/arch/board-pcm038.h>
30
31/*
32 * Phytec's phyCORE-i.MX27 comes with 32MiB flash,
33 * 16 bit width
34 */
35static struct physmap_flash_data pcm038_flash_data = {
36 .width = 2,
37};
38
39static struct resource pcm038_flash_resource = {
40 .start = 0xc0000000,
41 .end = 0xc1ffffff,
42 .flags = IORESOURCE_MEM,
43};
44
45static struct platform_device pcm038_nor_mtd_device = {
46 .name = "physmap-flash",
47 .id = 0,
48 .dev = {
49 .platform_data = &pcm038_flash_data,
50 },
51 .num_resources = 1,
52 .resource = &pcm038_flash_resource,
53};
54
55static int mxc_uart0_pins[] = {
56 PE12_PF_UART1_TXD,
57 PE13_PF_UART1_RXD,
58 PE14_PF_UART1_CTS,
59 PE15_PF_UART1_RTS
60};
61
62static int uart_mxc_port0_init(struct platform_device *pdev)
63{
64 return mxc_gpio_setup_multiple_pins(mxc_uart0_pins,
65 ARRAY_SIZE(mxc_uart0_pins),
66 MXC_GPIO_ALLOC_MODE_NORMAL, "UART0");
67}
68
69static int uart_mxc_port0_exit(struct platform_device *pdev)
70{
71 return mxc_gpio_setup_multiple_pins(mxc_uart0_pins,
72 ARRAY_SIZE(mxc_uart0_pins),
73 MXC_GPIO_ALLOC_MODE_RELEASE, "UART0");
74}
75
76static int mxc_uart1_pins[] = {
77 PE3_PF_UART2_CTS,
78 PE4_PF_UART2_RTS,
79 PE6_PF_UART2_TXD,
80 PE7_PF_UART2_RXD
81};
82
83static int uart_mxc_port1_init(struct platform_device *pdev)
84{
85 return mxc_gpio_setup_multiple_pins(mxc_uart1_pins,
86 ARRAY_SIZE(mxc_uart1_pins),
87 MXC_GPIO_ALLOC_MODE_NORMAL, "UART1");
88}
89
90static int uart_mxc_port1_exit(struct platform_device *pdev)
91{
92 return mxc_gpio_setup_multiple_pins(mxc_uart1_pins,
93 ARRAY_SIZE(mxc_uart1_pins),
94 MXC_GPIO_ALLOC_MODE_RELEASE, "UART1");
95}
96
97static int mxc_uart2_pins[] = { PE10_PF_UART3_CTS,
98 PE9_PF_UART3_RXD,
99 PE10_PF_UART3_CTS,
100 PE9_PF_UART3_RXD };
101
102static int uart_mxc_port2_init(struct platform_device *pdev)
103{
104 return mxc_gpio_setup_multiple_pins(mxc_uart2_pins,
105 ARRAY_SIZE(mxc_uart2_pins),
106 MXC_GPIO_ALLOC_MODE_NORMAL, "UART2");
107}
108
109static int uart_mxc_port2_exit(struct platform_device *pdev)
110{
111 return mxc_gpio_setup_multiple_pins(mxc_uart2_pins,
112 ARRAY_SIZE(mxc_uart2_pins),
113 MXC_GPIO_ALLOC_MODE_RELEASE, "UART2");
114}
115
116static struct imxuart_platform_data uart_pdata[] = {
117 {
118 .init = uart_mxc_port0_init,
119 .exit = uart_mxc_port0_exit,
120 .flags = IMXUART_HAVE_RTSCTS,
121 }, {
122 .init = uart_mxc_port1_init,
123 .exit = uart_mxc_port1_exit,
124 .flags = IMXUART_HAVE_RTSCTS,
125 }, {
126 .init = uart_mxc_port2_init,
127 .exit = uart_mxc_port2_exit,
128 .flags = IMXUART_HAVE_RTSCTS,
129 },
130};
131
132static int mxc_fec_pins[] = {
133 PD0_AIN_FEC_TXD0,
134 PD1_AIN_FEC_TXD1,
135 PD2_AIN_FEC_TXD2,
136 PD3_AIN_FEC_TXD3,
137 PD4_AOUT_FEC_RX_ER,
138 PD5_AOUT_FEC_RXD1,
139 PD6_AOUT_FEC_RXD2,
140 PD7_AOUT_FEC_RXD3,
141 PD8_AF_FEC_MDIO,
142 PD9_AIN_FEC_MDC,
143 PD10_AOUT_FEC_CRS,
144 PD11_AOUT_FEC_TX_CLK,
145 PD12_AOUT_FEC_RXD0,
146 PD13_AOUT_FEC_RX_DV,
147 PD14_AOUT_FEC_CLR,
148 PD15_AOUT_FEC_COL,
149 PD16_AIN_FEC_TX_ER,
150 PF23_AIN_FEC_TX_EN
151};
152
153static void gpio_fec_active(void)
154{
155 mxc_gpio_setup_multiple_pins(mxc_fec_pins,
156 ARRAY_SIZE(mxc_fec_pins),
157 MXC_GPIO_ALLOC_MODE_NORMAL, "FEC");
158}
159
160static void gpio_fec_inactive(void)
161{
162 mxc_gpio_setup_multiple_pins(mxc_fec_pins,
163 ARRAY_SIZE(mxc_fec_pins),
164 MXC_GPIO_ALLOC_MODE_RELEASE, "FEC");
165}
166
167static struct platform_device *platform_devices[] __initdata = {
168 &pcm038_nor_mtd_device,
169};
170
171static void __init pcm038_init(void)
172{
173 int i;
174 gpio_fec_active();
175
176 for (i = 0; i < 3; i++)
177 imx_init_uart(i, &uart_pdata[i]);
178
179 platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
180
181#ifdef CONFIG_MACH_PCM970_BASEBOARD
182 pcm970_baseboard_init();
183#endif
184}
185
186static void __init pcm038_timer_init(void)
187{
188 mxc_clocks_init(26000000);
189 mxc_timer_init("gpt_clk.0");
190}
191
192struct sys_timer pcm038_timer = {
193 .init = pcm038_timer_init,
194};
195
196MACHINE_START(PCM038, "phyCORE-i.MX27")
197 .phys_io = AIPI_BASE_ADDR,
198 .io_pg_offst = ((AIPI_BASE_ADDR_VIRT) >> 18) & 0xfffc,
199 .boot_params = PHYS_OFFSET + 0x100,
200 .map_io = mxc_map_io,
201 .init_irq = mxc_init_irq,
202 .init_machine = pcm038_init,
203 .timer = &pcm038_timer,
204MACHINE_END
diff --git a/arch/arm/mach-mx2/pcm970-baseboard.c b/arch/arm/mach-mx2/pcm970-baseboard.c
new file mode 100644
index 000000000000..028ac4d33684
--- /dev/null
+++ b/arch/arm/mach-mx2/pcm970-baseboard.c
@@ -0,0 +1,32 @@
1/*
2 * Copyright (C) 2008 Juergen Beisert (kernel@pengutronix.de)
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
16 * MA 02110-1301, USA.
17 */
18
19#include <linux/platform_device.h>
20#include <asm/hardware.h>
21#include <asm/mach-types.h>
22#include <asm/mach/arch.h>
23
24/*
25 * system init for baseboard usage. Will be called by pcm038 init.
26 *
27 * Add platform devices present on this baseboard and init
28 * them from CPU side as far as required to use them later on
29 */
30void __init pcm970_baseboard_init(void)
31{
32}
diff --git a/arch/arm/mach-mx2/serial.c b/arch/arm/mach-mx2/serial.c
new file mode 100644
index 000000000000..570c02b8e5df
--- /dev/null
+++ b/arch/arm/mach-mx2/serial.c
@@ -0,0 +1,177 @@
1/*
2 * Copyright 2006-2007 Freescale Semiconductor, Inc. All Rights Reserved.
3 * Copyright 2008 Juergen Beisert, kernel@pengutronix.de
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
17 * MA 02110-1301, USA.
18 */
19
20#include <linux/module.h>
21#include <linux/platform_device.h>
22#include <linux/serial.h>
23#include <asm/hardware.h>
24#include <asm/arch/imx-uart.h>
25
26static struct resource uart0[] = {
27 {
28 .start = UART1_BASE_ADDR,
29 .end = UART1_BASE_ADDR + 0x0B5,
30 .flags = IORESOURCE_MEM,
31 }, {
32 .start = MXC_INT_UART1,
33 .end = MXC_INT_UART1,
34 .flags = IORESOURCE_IRQ,
35 },
36};
37
38static struct platform_device mxc_uart_device0 = {
39 .name = "imx-uart",
40 .id = 0,
41 .resource = uart0,
42 .num_resources = ARRAY_SIZE(uart0),
43};
44
45static struct resource uart1[] = {
46 {
47 .start = UART2_BASE_ADDR,
48 .end = UART2_BASE_ADDR + 0x0B5,
49 .flags = IORESOURCE_MEM,
50 }, {
51 .start = MXC_INT_UART2,
52 .end = MXC_INT_UART2,
53 .flags = IORESOURCE_IRQ,
54 },
55};
56
57static struct platform_device mxc_uart_device1 = {
58 .name = "imx-uart",
59 .id = 1,
60 .resource = uart1,
61 .num_resources = ARRAY_SIZE(uart1),
62};
63
64static struct resource uart2[] = {
65 {
66 .start = UART3_BASE_ADDR,
67 .end = UART3_BASE_ADDR + 0x0B5,
68 .flags = IORESOURCE_MEM,
69 }, {
70 .start = MXC_INT_UART3,
71 .end = MXC_INT_UART3,
72 .flags = IORESOURCE_IRQ,
73 },
74};
75
76static struct platform_device mxc_uart_device2 = {
77 .name = "imx-uart",
78 .id = 2,
79 .resource = uart2,
80 .num_resources = ARRAY_SIZE(uart2),
81};
82
83static struct resource uart3[] = {
84 {
85 .start = UART4_BASE_ADDR,
86 .end = UART4_BASE_ADDR + 0x0B5,
87 .flags = IORESOURCE_MEM,
88 }, {
89 .start = MXC_INT_UART4,
90 .end = MXC_INT_UART4,
91 .flags = IORESOURCE_IRQ,
92 },
93};
94
95static struct platform_device mxc_uart_device3 = {
96 .name = "imx-uart",
97 .id = 3,
98 .resource = uart3,
99 .num_resources = ARRAY_SIZE(uart3),
100};
101
102static struct resource uart4[] = {
103 {
104 .start = UART5_BASE_ADDR,
105 .end = UART5_BASE_ADDR + 0x0B5,
106 .flags = IORESOURCE_MEM,
107 }, {
108 .start = MXC_INT_UART5,
109 .end = MXC_INT_UART5,
110 .flags = IORESOURCE_IRQ,
111 },
112};
113
114static struct platform_device mxc_uart_device4 = {
115 .name = "imx-uart",
116 .id = 4,
117 .resource = uart4,
118 .num_resources = ARRAY_SIZE(uart4),
119};
120
121static struct resource uart5[] = {
122 {
123 .start = UART6_BASE_ADDR,
124 .end = UART6_BASE_ADDR + 0x0B5,
125 .flags = IORESOURCE_MEM,
126 }, {
127 .start = MXC_INT_UART6,
128 .end = MXC_INT_UART6,
129 .flags = IORESOURCE_IRQ,
130 },
131};
132
133static struct platform_device mxc_uart_device5 = {
134 .name = "imx-uart",
135 .id = 5,
136 .resource = uart5,
137 .num_resources = ARRAY_SIZE(uart5),
138};
139
140/*
141 * Register only those UARTs that physically exists
142 */
143int __init imx_init_uart(int uart_no, struct imxuart_platform_data *pdata)
144{
145 switch (uart_no) {
146 case 0:
147 mxc_uart_device0.dev.platform_data = pdata;
148 platform_device_register(&mxc_uart_device0);
149 break;
150 case 1:
151 mxc_uart_device1.dev.platform_data = pdata;
152 platform_device_register(&mxc_uart_device1);
153 break;
154#ifndef CONFIG_MXC_IRDA
155 case 2:
156 mxc_uart_device2.dev.platform_data = pdata;
157 platform_device_register(&mxc_uart_device2);
158 break;
159#endif
160 case 3:
161 mxc_uart_device3.dev.platform_data = pdata;
162 platform_device_register(&mxc_uart_device3);
163 break;
164 case 4:
165 mxc_uart_device4.dev.platform_data = pdata;
166 platform_device_register(&mxc_uart_device4);
167 break;
168 case 5:
169 mxc_uart_device5.dev.platform_data = pdata;
170 platform_device_register(&mxc_uart_device5);
171 break;
172 default:
173 return -ENODEV;
174 }
175
176 return 0;
177}
diff --git a/arch/arm/mach-mx2/system.c b/arch/arm/mach-mx2/system.c
new file mode 100644
index 000000000000..99304645299d
--- /dev/null
+++ b/arch/arm/mach-mx2/system.c
@@ -0,0 +1,63 @@
1/*
2 * Copyright (C) 1999 ARM Limited
3 * Copyright (C) 2000 Deep Blue Solutions Ltd
4 * Copyright 2006-2007 Freescale Semiconductor, Inc. All Rights Reserved.
5 * Copyright 2008 Juergen Beisert, kernel@pengutronix.de
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21
22#include <linux/kernel.h>
23#include <linux/clk.h>
24#include <linux/io.h>
25
26#include <asm/arch/hardware.h>
27#include <asm/proc-fns.h>
28#include <asm/system.h>
29
30/*
31 * Put the CPU into idle mode. It is called by default_idle()
32 * in process.c file.
33 */
34void arch_idle(void)
35{
36 /*
37 * This should do all the clock switching
38 * and wait for interrupt tricks.
39 */
40 cpu_do_idle();
41}
42
43#define WDOG_WCR_REG IO_ADDRESS(WDOG_BASE_ADDR)
44#define WDOG_WCR_SRS (1 << 4)
45
46/*
47 * Reset the system. It is called by machine_restart().
48 */
49void arch_reset(char mode)
50{
51 struct clk *clk;
52
53 clk = clk_get(NULL, "wdog_clk");
54 if (!clk) {
55 printk(KERN_ERR"Cannot activate the watchdog. Giving up\n");
56 return;
57 }
58
59 clk_enable(clk);
60
61 /* Assert SRS signal */
62 __raw_writew(__raw_readw(WDOG_WCR_REG) & ~WDOG_WCR_SRS, WDOG_WCR_REG);
63}