aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-mx1
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-mx1')
-rw-r--r--arch/arm/mach-mx1/Kconfig14
-rw-r--r--arch/arm/mach-mx1/Makefile10
-rw-r--r--arch/arm/mach-mx1/Makefile.boot4
-rw-r--r--arch/arm/mach-mx1/clock.c656
-rw-r--r--arch/arm/mach-mx1/crm_regs.h55
-rw-r--r--arch/arm/mach-mx1/devices.c260
-rw-r--r--arch/arm/mach-mx1/devices.h7
-rw-r--r--arch/arm/mach-mx1/generic.c43
-rw-r--r--arch/arm/mach-mx1/mx1ads.c148
9 files changed, 1197 insertions, 0 deletions
diff --git a/arch/arm/mach-mx1/Kconfig b/arch/arm/mach-mx1/Kconfig
new file mode 100644
index 000000000000..2b59fc74784f
--- /dev/null
+++ b/arch/arm/mach-mx1/Kconfig
@@ -0,0 +1,14 @@
1if ARCH_MX1
2
3comment "MX1 Platforms"
4
5config MACH_MXLADS
6 bool
7
8config ARCH_MX1ADS
9 bool "MX1ADS platform"
10 select MACH_MXLADS
11 help
12 Say Y here if you are using Motorola MX1ADS/MXLADS boards
13
14endif
diff --git a/arch/arm/mach-mx1/Makefile b/arch/arm/mach-mx1/Makefile
new file mode 100644
index 000000000000..b969719011fa
--- /dev/null
+++ b/arch/arm/mach-mx1/Makefile
@@ -0,0 +1,10 @@
1#
2# Makefile for the linux kernel.
3#
4
5# Object file lists.
6
7obj-y += generic.o clock.o devices.o
8
9# Specific board support
10obj-$(CONFIG_ARCH_MX1ADS) += mx1ads.o
diff --git a/arch/arm/mach-mx1/Makefile.boot b/arch/arm/mach-mx1/Makefile.boot
new file mode 100644
index 000000000000..8ed1492288a2
--- /dev/null
+++ b/arch/arm/mach-mx1/Makefile.boot
@@ -0,0 +1,4 @@
1 zreladdr-y := 0x08008000
2params_phys-y := 0x08000100
3initrd_phys-y := 0x08800000
4
diff --git a/arch/arm/mach-mx1/clock.c b/arch/arm/mach-mx1/clock.c
new file mode 100644
index 000000000000..4bcd1ece55f5
--- /dev/null
+++ b/arch/arm/mach-mx1/clock.c
@@ -0,0 +1,656 @@
1/*
2 * Copyright (C) 2008 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 */
18
19#include <linux/kernel.h>
20#include <linux/init.h>
21#include <linux/math64.h>
22#include <linux/err.h>
23#include <linux/clk.h>
24#include <linux/io.h>
25
26#include <mach/clock.h>
27#include <mach/hardware.h>
28#include "crm_regs.h"
29
30static int _clk_enable(struct clk *clk)
31{
32 unsigned int reg;
33
34 reg = __raw_readl(clk->enable_reg);
35 reg |= 1 << clk->enable_shift;
36 __raw_writel(reg, clk->enable_reg);
37
38 return 0;
39}
40
41static void _clk_disable(struct clk *clk)
42{
43 unsigned int reg;
44
45 reg = __raw_readl(clk->enable_reg);
46 reg &= ~(1 << clk->enable_shift);
47 __raw_writel(reg, clk->enable_reg);
48}
49
50static int _clk_can_use_parent(const struct clk *clk_arr[], unsigned int size,
51 struct clk *parent)
52{
53 int i;
54
55 for (i = 0; i < size; i++)
56 if (parent == clk_arr[i])
57 return i;
58
59 return -EINVAL;
60}
61
62static unsigned long
63_clk_simple_round_rate(struct clk *clk, unsigned long rate, unsigned int limit)
64{
65 int div;
66 unsigned long parent_rate;
67
68 parent_rate = clk_get_rate(clk->parent);
69
70 div = parent_rate / rate;
71 if (parent_rate % rate)
72 div++;
73
74 if (div > limit)
75 div = limit;
76
77 return parent_rate / div;
78}
79
80static unsigned long _clk_parent_round_rate(struct clk *clk, unsigned long rate)
81{
82 return clk->parent->round_rate(clk->parent, rate);
83}
84
85static int _clk_parent_set_rate(struct clk *clk, unsigned long rate)
86{
87 return clk->parent->set_rate(clk->parent, rate);
88}
89
90/*
91 * get the system pll clock in Hz
92 *
93 * mfi + mfn / (mfd +1)
94 * f = 2 * f_ref * --------------------
95 * pd + 1
96 */
97static unsigned long mx1_decode_pll(unsigned int pll, u32 f_ref)
98{
99 unsigned long long ll;
100 unsigned long quot;
101
102 u32 mfi = (pll >> 10) & 0xf;
103 u32 mfn = pll & 0x3ff;
104 u32 mfd = (pll >> 16) & 0x3ff;
105 u32 pd = (pll >> 26) & 0xf;
106
107 mfi = mfi <= 5 ? 5 : mfi;
108
109 ll = 2 * (unsigned long long)f_ref *
110 ((mfi << 16) + (mfn << 16) / (mfd + 1));
111 quot = (pd + 1) * (1 << 16);
112 ll += quot / 2;
113 do_div(ll, quot);
114 return (unsigned long)ll;
115}
116
117static unsigned long clk16m_get_rate(struct clk *clk)
118{
119 return 16000000;
120}
121
122static struct clk clk16m = {
123 .name = "CLK16M",
124 .get_rate = clk16m_get_rate,
125 .enable = _clk_enable,
126 .enable_reg = CCM_CSCR,
127 .enable_shift = CCM_CSCR_OSC_EN_SHIFT,
128 .disable = _clk_disable,
129};
130
131/* in Hz */
132static unsigned long clk32_rate;
133
134static unsigned long clk32_get_rate(struct clk *clk)
135{
136 return clk32_rate;
137}
138
139static struct clk clk32 = {
140 .name = "CLK32",
141 .get_rate = clk32_get_rate,
142};
143
144static unsigned long clk32_premult_get_rate(struct clk *clk)
145{
146 return clk_get_rate(clk->parent) * 512;
147}
148
149static struct clk clk32_premult = {
150 .name = "CLK32_premultiplier",
151 .parent = &clk32,
152 .get_rate = clk32_premult_get_rate,
153};
154
155static const struct clk *prem_clk_clocks[] = {
156 &clk32_premult,
157 &clk16m,
158};
159
160static int prem_clk_set_parent(struct clk *clk, struct clk *parent)
161{
162 int i;
163 unsigned int reg = __raw_readl(CCM_CSCR);
164
165 i = _clk_can_use_parent(prem_clk_clocks, ARRAY_SIZE(prem_clk_clocks),
166 parent);
167
168 switch (i) {
169 case 0:
170 reg &= ~CCM_CSCR_SYSTEM_SEL;
171 break;
172 case 1:
173 reg |= CCM_CSCR_SYSTEM_SEL;
174 break;
175 default:
176 return i;
177 }
178
179 __raw_writel(reg, CCM_CSCR);
180
181 return 0;
182}
183
184static struct clk prem_clk = {
185 .name = "prem_clk",
186 .set_parent = prem_clk_set_parent,
187};
188
189static unsigned long system_clk_get_rate(struct clk *clk)
190{
191 return mx1_decode_pll(__raw_readl(CCM_SPCTL0),
192 clk_get_rate(clk->parent));
193}
194
195static struct clk system_clk = {
196 .name = "system_clk",
197 .parent = &prem_clk,
198 .get_rate = system_clk_get_rate,
199};
200
201static unsigned long mcu_clk_get_rate(struct clk *clk)
202{
203 return mx1_decode_pll(__raw_readl(CCM_MPCTL0),
204 clk_get_rate(clk->parent));
205}
206
207static struct clk mcu_clk = {
208 .name = "mcu_clk",
209 .parent = &clk32_premult,
210 .get_rate = mcu_clk_get_rate,
211};
212
213static unsigned long fclk_get_rate(struct clk *clk)
214{
215 unsigned long fclk = clk_get_rate(clk->parent);
216
217 if (__raw_readl(CCM_CSCR) & CCM_CSCR_PRESC)
218 fclk /= 2;
219
220 return fclk;
221}
222
223static struct clk fclk = {
224 .name = "fclk",
225 .parent = &mcu_clk,
226 .get_rate = fclk_get_rate,
227};
228
229/*
230 * get hclk ( SDRAM, CSI, Memory Stick, I2C, DMA )
231 */
232static unsigned long hclk_get_rate(struct clk *clk)
233{
234 return clk_get_rate(clk->parent) / (((__raw_readl(CCM_CSCR) &
235 CCM_CSCR_BCLK_MASK) >> CCM_CSCR_BCLK_OFFSET) + 1);
236}
237
238static unsigned long hclk_round_rate(struct clk *clk, unsigned long rate)
239{
240 return _clk_simple_round_rate(clk, rate, 16);
241}
242
243static int hclk_set_rate(struct clk *clk, unsigned long rate)
244{
245 unsigned int div;
246 unsigned int reg;
247 unsigned long parent_rate;
248
249 parent_rate = clk_get_rate(clk->parent);
250
251 div = parent_rate / rate;
252
253 if (div > 16 || div < 1 || ((parent_rate / div) != rate))
254 return -EINVAL;
255
256 div--;
257
258 reg = __raw_readl(CCM_CSCR);
259 reg &= ~CCM_CSCR_BCLK_MASK;
260 reg |= div << CCM_CSCR_BCLK_OFFSET;
261 __raw_writel(reg, CCM_CSCR);
262
263 return 0;
264}
265
266static struct clk hclk = {
267 .name = "hclk",
268 .parent = &system_clk,
269 .get_rate = hclk_get_rate,
270 .round_rate = hclk_round_rate,
271 .set_rate = hclk_set_rate,
272};
273
274static unsigned long clk48m_get_rate(struct clk *clk)
275{
276 return clk_get_rate(clk->parent) / (((__raw_readl(CCM_CSCR) &
277 CCM_CSCR_USB_MASK) >> CCM_CSCR_USB_OFFSET) + 1);
278}
279
280static unsigned long clk48m_round_rate(struct clk *clk, unsigned long rate)
281{
282 return _clk_simple_round_rate(clk, rate, 8);
283}
284
285static int clk48m_set_rate(struct clk *clk, unsigned long rate)
286{
287 unsigned int div;
288 unsigned int reg;
289 unsigned long parent_rate;
290
291 parent_rate = clk_get_rate(clk->parent);
292
293 div = parent_rate / rate;
294
295 if (div > 8 || div < 1 || ((parent_rate / div) != rate))
296 return -EINVAL;
297
298 div--;
299
300 reg = __raw_readl(CCM_CSCR);
301 reg &= ~CCM_CSCR_USB_MASK;
302 reg |= div << CCM_CSCR_USB_OFFSET;
303 __raw_writel(reg, CCM_CSCR);
304
305 return 0;
306}
307
308static struct clk clk48m = {
309 .name = "CLK48M",
310 .parent = &system_clk,
311 .get_rate = clk48m_get_rate,
312 .round_rate = clk48m_round_rate,
313 .set_rate = clk48m_set_rate,
314};
315
316/*
317 * get peripheral clock 1 ( UART[12], Timer[12], PWM )
318 */
319static unsigned long perclk1_get_rate(struct clk *clk)
320{
321 return clk_get_rate(clk->parent) / (((__raw_readl(CCM_PCDR) &
322 CCM_PCDR_PCLK1_MASK) >> CCM_PCDR_PCLK1_OFFSET) + 1);
323}
324
325static unsigned long perclk1_round_rate(struct clk *clk, unsigned long rate)
326{
327 return _clk_simple_round_rate(clk, rate, 16);
328}
329
330static int perclk1_set_rate(struct clk *clk, unsigned long rate)
331{
332 unsigned int div;
333 unsigned int reg;
334 unsigned long parent_rate;
335
336 parent_rate = clk_get_rate(clk->parent);
337
338 div = parent_rate / rate;
339
340 if (div > 16 || div < 1 || ((parent_rate / div) != rate))
341 return -EINVAL;
342
343 div--;
344
345 reg = __raw_readl(CCM_PCDR);
346 reg &= ~CCM_PCDR_PCLK1_MASK;
347 reg |= div << CCM_PCDR_PCLK1_OFFSET;
348 __raw_writel(reg, CCM_PCDR);
349
350 return 0;
351}
352
353/*
354 * get peripheral clock 2 ( LCD, SD, SPI[12] )
355 */
356static unsigned long perclk2_get_rate(struct clk *clk)
357{
358 return clk_get_rate(clk->parent) / (((__raw_readl(CCM_PCDR) &
359 CCM_PCDR_PCLK2_MASK) >> CCM_PCDR_PCLK2_OFFSET) + 1);
360}
361
362static unsigned long perclk2_round_rate(struct clk *clk, unsigned long rate)
363{
364 return _clk_simple_round_rate(clk, rate, 16);
365}
366
367static int perclk2_set_rate(struct clk *clk, unsigned long rate)
368{
369 unsigned int div;
370 unsigned int reg;
371 unsigned long parent_rate;
372
373 parent_rate = clk_get_rate(clk->parent);
374
375 div = parent_rate / rate;
376
377 if (div > 16 || div < 1 || ((parent_rate / div) != rate))
378 return -EINVAL;
379
380 div--;
381
382 reg = __raw_readl(CCM_PCDR);
383 reg &= ~CCM_PCDR_PCLK2_MASK;
384 reg |= div << CCM_PCDR_PCLK2_OFFSET;
385 __raw_writel(reg, CCM_PCDR);
386
387 return 0;
388}
389
390/*
391 * get peripheral clock 3 ( SSI )
392 */
393static unsigned long perclk3_get_rate(struct clk *clk)
394{
395 return clk_get_rate(clk->parent) / (((__raw_readl(CCM_PCDR) &
396 CCM_PCDR_PCLK3_MASK) >> CCM_PCDR_PCLK3_OFFSET) + 1);
397}
398
399static unsigned long perclk3_round_rate(struct clk *clk, unsigned long rate)
400{
401 return _clk_simple_round_rate(clk, rate, 128);
402}
403
404static int perclk3_set_rate(struct clk *clk, unsigned long rate)
405{
406 unsigned int div;
407 unsigned int reg;
408 unsigned long parent_rate;
409
410 parent_rate = clk_get_rate(clk->parent);
411
412 div = parent_rate / rate;
413
414 if (div > 128 || div < 1 || ((parent_rate / div) != rate))
415 return -EINVAL;
416
417 div--;
418
419 reg = __raw_readl(CCM_PCDR);
420 reg &= ~CCM_PCDR_PCLK3_MASK;
421 reg |= div << CCM_PCDR_PCLK3_OFFSET;
422 __raw_writel(reg, CCM_PCDR);
423
424 return 0;
425}
426
427static struct clk perclk[] = {
428 {
429 .name = "perclk",
430 .id = 0,
431 .parent = &system_clk,
432 .get_rate = perclk1_get_rate,
433 .round_rate = perclk1_round_rate,
434 .set_rate = perclk1_set_rate,
435 }, {
436 .name = "perclk",
437 .id = 1,
438 .parent = &system_clk,
439 .get_rate = perclk2_get_rate,
440 .round_rate = perclk2_round_rate,
441 .set_rate = perclk2_set_rate,
442 }, {
443 .name = "perclk",
444 .id = 2,
445 .parent = &system_clk,
446 .get_rate = perclk3_get_rate,
447 .round_rate = perclk3_round_rate,
448 .set_rate = perclk3_set_rate,
449 }
450};
451
452static const struct clk *clko_clocks[] = {
453 &perclk[0],
454 &hclk,
455 &clk48m,
456 &clk16m,
457 &prem_clk,
458 &fclk,
459};
460
461static int clko_set_parent(struct clk *clk, struct clk *parent)
462{
463 int i;
464 unsigned int reg;
465
466 i = _clk_can_use_parent(clko_clocks, ARRAY_SIZE(clko_clocks), parent);
467 if (i < 0)
468 return i;
469
470 reg = __raw_readl(CCM_CSCR) & ~CCM_CSCR_CLKO_MASK;
471 reg |= i << CCM_CSCR_CLKO_OFFSET;
472 __raw_writel(reg, CCM_CSCR);
473
474 if (clko_clocks[i]->set_rate && clko_clocks[i]->round_rate) {
475 clk->set_rate = _clk_parent_set_rate;
476 clk->round_rate = _clk_parent_round_rate;
477 } else {
478 clk->set_rate = NULL;
479 clk->round_rate = NULL;
480 }
481
482 return 0;
483}
484
485static struct clk clko_clk = {
486 .name = "clko_clk",
487 .set_parent = clko_set_parent,
488};
489
490static struct clk dma_clk = {
491 .name = "dma_clk",
492 .parent = &hclk,
493 .round_rate = _clk_parent_round_rate,
494 .set_rate = _clk_parent_set_rate,
495 .enable = _clk_enable,
496 .enable_reg = SCM_GCCR,
497 .enable_shift = SCM_GCCR_DMA_CLK_EN_OFFSET,
498 .disable = _clk_disable,
499};
500
501static struct clk csi_clk = {
502 .name = "csi_clk",
503 .parent = &hclk,
504 .round_rate = _clk_parent_round_rate,
505 .set_rate = _clk_parent_set_rate,
506 .enable = _clk_enable,
507 .enable_reg = SCM_GCCR,
508 .enable_shift = SCM_GCCR_CSI_CLK_EN_OFFSET,
509 .disable = _clk_disable,
510};
511
512static struct clk mma_clk = {
513 .name = "mma_clk",
514 .parent = &hclk,
515 .round_rate = _clk_parent_round_rate,
516 .set_rate = _clk_parent_set_rate,
517 .enable = _clk_enable,
518 .enable_reg = SCM_GCCR,
519 .enable_shift = SCM_GCCR_MMA_CLK_EN_OFFSET,
520 .disable = _clk_disable,
521};
522
523static struct clk usbd_clk = {
524 .name = "usbd_clk",
525 .parent = &clk48m,
526 .round_rate = _clk_parent_round_rate,
527 .set_rate = _clk_parent_set_rate,
528 .enable = _clk_enable,
529 .enable_reg = SCM_GCCR,
530 .enable_shift = SCM_GCCR_USBD_CLK_EN_OFFSET,
531 .disable = _clk_disable,
532};
533
534static struct clk gpt_clk = {
535 .name = "gpt_clk",
536 .parent = &perclk[0],
537 .round_rate = _clk_parent_round_rate,
538 .set_rate = _clk_parent_set_rate,
539};
540
541static struct clk uart_clk = {
542 .name = "uart_clk",
543 .parent = &perclk[0],
544 .round_rate = _clk_parent_round_rate,
545 .set_rate = _clk_parent_set_rate,
546};
547
548static struct clk i2c_clk = {
549 .name = "i2c_clk",
550 .parent = &hclk,
551 .round_rate = _clk_parent_round_rate,
552 .set_rate = _clk_parent_set_rate,
553};
554
555static struct clk spi_clk = {
556 .name = "spi_clk",
557 .parent = &perclk[1],
558 .round_rate = _clk_parent_round_rate,
559 .set_rate = _clk_parent_set_rate,
560};
561
562static struct clk sdhc_clk = {
563 .name = "sdhc_clk",
564 .parent = &perclk[1],
565 .round_rate = _clk_parent_round_rate,
566 .set_rate = _clk_parent_set_rate,
567};
568
569static struct clk lcdc_clk = {
570 .name = "lcdc_clk",
571 .parent = &perclk[1],
572 .round_rate = _clk_parent_round_rate,
573 .set_rate = _clk_parent_set_rate,
574};
575
576static struct clk mshc_clk = {
577 .name = "mshc_clk",
578 .parent = &hclk,
579 .round_rate = _clk_parent_round_rate,
580 .set_rate = _clk_parent_set_rate,
581};
582
583static struct clk ssi_clk = {
584 .name = "ssi_clk",
585 .parent = &perclk[2],
586 .round_rate = _clk_parent_round_rate,
587 .set_rate = _clk_parent_set_rate,
588};
589
590static struct clk rtc_clk = {
591 .name = "rtc_clk",
592 .parent = &clk32,
593};
594
595static struct clk *mxc_clks[] = {
596 &clk16m,
597 &clk32,
598 &clk32_premult,
599 &prem_clk,
600 &system_clk,
601 &mcu_clk,
602 &fclk,
603 &hclk,
604 &clk48m,
605 &perclk[0],
606 &perclk[1],
607 &perclk[2],
608 &clko_clk,
609 &dma_clk,
610 &csi_clk,
611 &mma_clk,
612 &usbd_clk,
613 &gpt_clk,
614 &uart_clk,
615 &i2c_clk,
616 &spi_clk,
617 &sdhc_clk,
618 &lcdc_clk,
619 &mshc_clk,
620 &ssi_clk,
621 &rtc_clk,
622};
623
624int __init mxc_clocks_init(unsigned long fref)
625{
626 struct clk **clkp;
627 unsigned int reg;
628
629 /* disable clocks we are able to */
630 __raw_writel(0, SCM_GCCR);
631
632 clk32_rate = fref;
633 reg = __raw_readl(CCM_CSCR);
634
635 /* detect clock reference for system PLL */
636 if (reg & CCM_CSCR_SYSTEM_SEL) {
637 prem_clk.parent = &clk16m;
638 } else {
639 /* ensure that oscillator is disabled */
640 reg &= ~(1 << CCM_CSCR_OSC_EN_SHIFT);
641 __raw_writel(reg, CCM_CSCR);
642 prem_clk.parent = &clk32_premult;
643 }
644
645 /* detect reference for CLKO */
646 reg = (reg & CCM_CSCR_CLKO_MASK) >> CCM_CSCR_CLKO_OFFSET;
647 clko_clk.parent = (struct clk *)clko_clocks[reg];
648
649 for (clkp = mxc_clks; clkp < mxc_clks + ARRAY_SIZE(mxc_clks); clkp++)
650 clk_register(*clkp);
651
652 clk_enable(&hclk);
653 clk_enable(&fclk);
654
655 return 0;
656}
diff --git a/arch/arm/mach-mx1/crm_regs.h b/arch/arm/mach-mx1/crm_regs.h
new file mode 100644
index 000000000000..22e866ff0c09
--- /dev/null
+++ b/arch/arm/mach-mx1/crm_regs.h
@@ -0,0 +1,55 @@
1/*
2 * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
3 * Copyright (c) 2008 Paulius Zaleckas <paulius.zaleckas@teltonika.lt>
4 *
5 * This file may be distributed under the terms of the GNU General
6 * Public License, version 2.
7 */
8
9#ifndef __ARCH_ARM_MACH_MX1_CRM_REGS_H__
10#define __ARCH_ARM_MACH_MX1_CRM_REGS_H__
11
12#define CCM_BASE IO_ADDRESS(CCM_BASE_ADDR)
13#define SCM_BASE IO_ADDRESS(SCM_BASE_ADDR)
14
15/* CCM register addresses */
16#define CCM_CSCR (CCM_BASE + 0x0)
17#define CCM_MPCTL0 (CCM_BASE + 0x4)
18#define CCM_MPCTL1 (CCM_BASE + 0x8)
19#define CCM_SPCTL0 (CCM_BASE + 0xC)
20#define CCM_SPCTL1 (CCM_BASE + 0x10)
21#define CCM_PCDR (CCM_BASE + 0x20)
22
23#define CCM_CSCR_CLKO_OFFSET 29
24#define CCM_CSCR_CLKO_MASK (0x7 << 29)
25#define CCM_CSCR_USB_OFFSET 26
26#define CCM_CSCR_USB_MASK (0x7 << 26)
27#define CCM_CSCR_SPLL_RESTART (1 << 22)
28#define CCM_CSCR_MPLL_RESTART (1 << 21)
29#define CCM_CSCR_OSC_EN_SHIFT 17
30#define CCM_CSCR_SYSTEM_SEL (1 << 16)
31#define CCM_CSCR_BCLK_OFFSET 10
32#define CCM_CSCR_BCLK_MASK (0xF << 10)
33#define CCM_CSCR_PRESC (1 << 15)
34#define CCM_CSCR_SPEN (1 << 1)
35#define CCM_CSCR_MPEN (1 << 0)
36
37#define CCM_PCDR_PCLK3_OFFSET 16
38#define CCM_PCDR_PCLK3_MASK (0x7F << 16)
39#define CCM_PCDR_PCLK2_OFFSET 4
40#define CCM_PCDR_PCLK2_MASK (0xF << 4)
41#define CCM_PCDR_PCLK1_OFFSET 0
42#define CCM_PCDR_PCLK1_MASK 0xF
43
44/* SCM register addresses */
45#define SCM_SIDR (SCM_BASE + 0x0)
46#define SCM_FMCR (SCM_BASE + 0x4)
47#define SCM_GPCR (SCM_BASE + 0x8)
48#define SCM_GCCR (SCM_BASE + 0xC)
49
50#define SCM_GCCR_DMA_CLK_EN_OFFSET 3
51#define SCM_GCCR_CSI_CLK_EN_OFFSET 2
52#define SCM_GCCR_MMA_CLK_EN_OFFSET 1
53#define SCM_GCCR_USBD_CLK_EN_OFFSET 0
54
55#endif /* __ARCH_ARM_MACH_MX2_CRM_REGS_H__ */
diff --git a/arch/arm/mach-mx1/devices.c b/arch/arm/mach-mx1/devices.c
new file mode 100644
index 000000000000..686d8d2dbb24
--- /dev/null
+++ b/arch/arm/mach-mx1/devices.c
@@ -0,0 +1,260 @@
1/*
2 * Copyright 2006-2007 Freescale Semiconductor, Inc. All Rights Reserved.
3 * Copyright 2008 Sascha Hauer, kernel@pengutronix.de
4 * Copyright (c) 2008 Paulius Zaleckas <paulius.zaleckas@teltonika.lt>
5 * Copyright (c) 2008 Darius Augulis <darius.augulis@teltonika.lt>
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
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., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
20 */
21
22#include <linux/kernel.h>
23#include <linux/init.h>
24#include <linux/platform_device.h>
25#include <linux/gpio.h>
26#include <mach/hardware.h>
27
28static struct resource imx_csi_resources[] = {
29 [0] = {
30 .start = 0x00224000,
31 .end = 0x00224010,
32 .flags = IORESOURCE_MEM,
33 },
34 [1] = {
35 .start = CSI_INT,
36 .end = CSI_INT,
37 .flags = IORESOURCE_IRQ,
38 },
39};
40
41static u64 imx_csi_dmamask = 0xffffffffUL;
42
43struct platform_device imx_csi_device = {
44 .name = "imx-csi",
45 .id = 0, /* This is used to put cameras on this interface */
46 .dev = {
47 .dma_mask = &imx_csi_dmamask,
48 .coherent_dma_mask = 0xffffffff,
49 },
50 .resource = imx_csi_resources,
51 .num_resources = ARRAY_SIZE(imx_csi_resources),
52};
53
54static struct resource imx_i2c_resources[] = {
55 [0] = {
56 .start = 0x00217000,
57 .end = 0x00217010,
58 .flags = IORESOURCE_MEM,
59 },
60 [1] = {
61 .start = I2C_INT,
62 .end = I2C_INT,
63 .flags = IORESOURCE_IRQ,
64 },
65};
66
67struct platform_device imx_i2c_device = {
68 .name = "imx-i2c",
69 .id = 0,
70 .resource = imx_i2c_resources,
71 .num_resources = ARRAY_SIZE(imx_i2c_resources),
72};
73
74static struct resource imx_uart1_resources[] = {
75 [0] = {
76 .start = UART1_BASE_ADDR,
77 .end = UART1_BASE_ADDR + 0xD0,
78 .flags = IORESOURCE_MEM,
79 },
80 [1] = {
81 .start = UART1_MINT_RX,
82 .end = UART1_MINT_RX,
83 .flags = IORESOURCE_IRQ,
84 },
85 [2] = {
86 .start = UART1_MINT_TX,
87 .end = UART1_MINT_TX,
88 .flags = IORESOURCE_IRQ,
89 },
90 [3] = {
91 .start = UART1_MINT_RTS,
92 .end = UART1_MINT_RTS,
93 .flags = IORESOURCE_IRQ,
94 },
95};
96
97struct platform_device imx_uart1_device = {
98 .name = "imx-uart",
99 .id = 0,
100 .num_resources = ARRAY_SIZE(imx_uart1_resources),
101 .resource = imx_uart1_resources,
102};
103
104static struct resource imx_uart2_resources[] = {
105 [0] = {
106 .start = UART2_BASE_ADDR,
107 .end = UART2_BASE_ADDR + 0xD0,
108 .flags = IORESOURCE_MEM,
109 },
110 [1] = {
111 .start = UART2_MINT_RX,
112 .end = UART2_MINT_RX,
113 .flags = IORESOURCE_IRQ,
114 },
115 [2] = {
116 .start = UART2_MINT_TX,
117 .end = UART2_MINT_TX,
118 .flags = IORESOURCE_IRQ,
119 },
120 [3] = {
121 .start = UART2_MINT_RTS,
122 .end = UART2_MINT_RTS,
123 .flags = IORESOURCE_IRQ,
124 },
125};
126
127struct platform_device imx_uart2_device = {
128 .name = "imx-uart",
129 .id = 1,
130 .num_resources = ARRAY_SIZE(imx_uart2_resources),
131 .resource = imx_uart2_resources,
132};
133
134static struct resource imx_rtc_resources[] = {
135 [0] = {
136 .start = 0x00204000,
137 .end = 0x00204024,
138 .flags = IORESOURCE_MEM,
139 },
140 [1] = {
141 .start = RTC_INT,
142 .end = RTC_INT,
143 .flags = IORESOURCE_IRQ,
144 },
145 [2] = {
146 .start = RTC_SAMINT,
147 .end = RTC_SAMINT,
148 .flags = IORESOURCE_IRQ,
149 },
150};
151
152struct platform_device imx_rtc_device = {
153 .name = "rtc-imx",
154 .id = 0,
155 .resource = imx_rtc_resources,
156 .num_resources = ARRAY_SIZE(imx_rtc_resources),
157};
158
159static struct resource imx_wdt_resources[] = {
160 [0] = {
161 .start = 0x00201000,
162 .end = 0x00201008,
163 .flags = IORESOURCE_MEM,
164 },
165 [1] = {
166 .start = WDT_INT,
167 .end = WDT_INT,
168 .flags = IORESOURCE_IRQ,
169 },
170};
171
172struct platform_device imx_wdt_device = {
173 .name = "imx-wdt",
174 .id = 0,
175 .resource = imx_wdt_resources,
176 .num_resources = ARRAY_SIZE(imx_wdt_resources),
177};
178
179static struct resource imx_usb_resources[] = {
180 [0] = {
181 .start = 0x00212000,
182 .end = 0x00212148,
183 .flags = IORESOURCE_MEM,
184 },
185 [1] = {
186 .start = USBD_INT0,
187 .end = USBD_INT0,
188 .flags = IORESOURCE_IRQ,
189 },
190 [2] = {
191 .start = USBD_INT1,
192 .end = USBD_INT1,
193 .flags = IORESOURCE_IRQ,
194 },
195 [3] = {
196 .start = USBD_INT2,
197 .end = USBD_INT2,
198 .flags = IORESOURCE_IRQ,
199 },
200 [4] = {
201 .start = USBD_INT3,
202 .end = USBD_INT3,
203 .flags = IORESOURCE_IRQ,
204 },
205 [5] = {
206 .start = USBD_INT4,
207 .end = USBD_INT4,
208 .flags = IORESOURCE_IRQ,
209 },
210 [6] = {
211 .start = USBD_INT5,
212 .end = USBD_INT5,
213 .flags = IORESOURCE_IRQ,
214 },
215 [7] = {
216 .start = USBD_INT6,
217 .end = USBD_INT6,
218 .flags = IORESOURCE_IRQ,
219 },
220};
221
222struct platform_device imx_usb_device = {
223 .name = "imx_udc",
224 .id = 0,
225 .num_resources = ARRAY_SIZE(imx_usb_resources),
226 .resource = imx_usb_resources,
227};
228
229/* GPIO port description */
230static struct mxc_gpio_port imx_gpio_ports[] = {
231 [0] = {
232 .chip.label = "gpio-0",
233 .base = (void __iomem *)IO_ADDRESS(GPIO_BASE_ADDR),
234 .irq = GPIO_INT_PORTA,
235 .virtual_irq_start = MXC_GPIO_IRQ_START
236 },
237 [1] = {
238 .chip.label = "gpio-1",
239 .base = (void __iomem *)IO_ADDRESS(GPIO_BASE_ADDR + 0x100),
240 .irq = GPIO_INT_PORTB,
241 .virtual_irq_start = MXC_GPIO_IRQ_START + 32
242 },
243 [2] = {
244 .chip.label = "gpio-2",
245 .base = (void __iomem *)IO_ADDRESS(GPIO_BASE_ADDR + 0x200),
246 .irq = GPIO_INT_PORTC,
247 .virtual_irq_start = MXC_GPIO_IRQ_START + 64
248 },
249 [3] = {
250 .chip.label = "gpio-3",
251 .base = (void __iomem *)IO_ADDRESS(GPIO_BASE_ADDR + 0x300),
252 .irq = GPIO_INT_PORTD,
253 .virtual_irq_start = MXC_GPIO_IRQ_START + 96
254 }
255};
256
257int __init mxc_register_gpios(void)
258{
259 return mxc_gpio_init(imx_gpio_ports, ARRAY_SIZE(imx_gpio_ports));
260}
diff --git a/arch/arm/mach-mx1/devices.h b/arch/arm/mach-mx1/devices.h
new file mode 100644
index 000000000000..0da5d7cce3a2
--- /dev/null
+++ b/arch/arm/mach-mx1/devices.h
@@ -0,0 +1,7 @@
1extern struct platform_device imx_csi_device;
2extern struct platform_device imx_i2c_device;
3extern struct platform_device imx_uart1_device;
4extern struct platform_device imx_uart2_device;
5extern struct platform_device imx_rtc_device;
6extern struct platform_device imx_wdt_device;
7extern struct platform_device imx_usb_device;
diff --git a/arch/arm/mach-mx1/generic.c b/arch/arm/mach-mx1/generic.c
new file mode 100644
index 000000000000..0dec6f300ffc
--- /dev/null
+++ b/arch/arm/mach-mx1/generic.c
@@ -0,0 +1,43 @@
1/*
2 * author: Sascha Hauer
3 * Created: april 20th, 2004
4 * Copyright: Synertronixx GmbH
5 *
6 * Common code for i.MX machines
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 *
22 */
23#include <linux/kernel.h>
24#include <linux/init.h>
25#include <linux/io.h>
26
27#include <asm/mach/map.h>
28
29#include <mach/hardware.h>
30
31static struct map_desc imx_io_desc[] __initdata = {
32 {
33 .virtual = IMX_IO_BASE,
34 .pfn = __phys_to_pfn(IMX_IO_PHYS),
35 .length = IMX_IO_SIZE,
36 .type = MT_DEVICE
37 }
38};
39
40void __init mxc_map_io(void)
41{
42 iotable_init(imx_io_desc, ARRAY_SIZE(imx_io_desc));
43}
diff --git a/arch/arm/mach-mx1/mx1ads.c b/arch/arm/mach-mx1/mx1ads.c
new file mode 100644
index 000000000000..2e4b185fe4a9
--- /dev/null
+++ b/arch/arm/mach-mx1/mx1ads.c
@@ -0,0 +1,148 @@
1/*
2 * arch/arm/mach-imx/mx1ads.c
3 *
4 * Initially based on:
5 * linux-2.6.7-imx/arch/arm/mach-imx/scb9328.c
6 * Copyright (c) 2004 Sascha Hauer <sascha@saschahauer.de>
7 *
8 * 2004 (c) MontaVista Software, Inc.
9 *
10 * This file is licensed under the terms of the GNU General Public
11 * License version 2. This program is licensed "as is" without any
12 * warranty of any kind, whether express or implied.
13 */
14
15#include <linux/kernel.h>
16#include <linux/init.h>
17#include <linux/platform_device.h>
18#include <linux/mtd/physmap.h>
19
20#include <asm/mach-types.h>
21#include <asm/mach/arch.h>
22#include <asm/mach/time.h>
23
24#include <mach/hardware.h>
25#include <mach/common.h>
26#include <mach/imx-uart.h>
27#include <mach/iomux-mx1-mx2.h>
28#include "devices.h"
29
30/*
31 * UARTs platform data
32 */
33static int mxc_uart1_pins[] = {
34 PC9_PF_UART1_CTS,
35 PC10_PF_UART1_RTS,
36 PC11_PF_UART1_TXD,
37 PC12_PF_UART1_RXD,
38};
39
40static int uart1_mxc_init(struct platform_device *pdev)
41{
42 return mxc_gpio_setup_multiple_pins(mxc_uart1_pins,
43 ARRAY_SIZE(mxc_uart1_pins), "UART1");
44}
45
46static int uart1_mxc_exit(struct platform_device *pdev)
47{
48 mxc_gpio_release_multiple_pins(mxc_uart1_pins,
49 ARRAY_SIZE(mxc_uart1_pins));
50 return 0;
51}
52
53static int mxc_uart2_pins[] = {
54 PB28_PF_UART2_CTS,
55 PB29_PF_UART2_RTS,
56 PB30_PF_UART2_TXD,
57 PB31_PF_UART2_RXD,
58};
59
60static int uart2_mxc_init(struct platform_device *pdev)
61{
62 return mxc_gpio_setup_multiple_pins(mxc_uart2_pins,
63 ARRAY_SIZE(mxc_uart2_pins), "UART2");
64}
65
66static int uart2_mxc_exit(struct platform_device *pdev)
67{
68 mxc_gpio_release_multiple_pins(mxc_uart2_pins,
69 ARRAY_SIZE(mxc_uart2_pins));
70 return 0;
71}
72
73static struct imxuart_platform_data uart_pdata[] = {
74 {
75 .init = uart1_mxc_init,
76 .exit = uart1_mxc_exit,
77 .flags = IMXUART_HAVE_RTSCTS,
78 }, {
79 .init = uart2_mxc_init,
80 .exit = uart2_mxc_exit,
81 .flags = IMXUART_HAVE_RTSCTS,
82 },
83};
84
85/*
86 * Physmap flash
87 */
88
89static struct physmap_flash_data mx1ads_flash_data = {
90 .width = 4, /* bankwidth in bytes */
91};
92
93static struct resource flash_resource = {
94 .start = IMX_CS0_PHYS,
95 .end = IMX_CS0_PHYS + SZ_32M - 1,
96 .flags = IORESOURCE_MEM,
97};
98
99static struct platform_device flash_device = {
100 .name = "physmap-flash",
101 .id = 0,
102 .resource = &flash_resource,
103 .num_resources = 1,
104};
105
106/*
107 * Board init
108 */
109static void __init mx1ads_init(void)
110{
111 /* UART */
112 mxc_register_device(&imx_uart1_device, &uart_pdata[0]);
113 mxc_register_device(&imx_uart2_device, &uart_pdata[1]);
114
115 /* Physmap flash */
116 mxc_register_device(&flash_device, &mx1ads_flash_data);
117}
118
119static void __init mx1ads_timer_init(void)
120{
121 mxc_clocks_init(32000);
122 mxc_timer_init("gpt_clk");
123}
124
125struct sys_timer mx1ads_timer = {
126 .init = mx1ads_timer_init,
127};
128
129MACHINE_START(MX1ADS, "Freescale MX1ADS")
130 /* Maintainer: Sascha Hauer, Pengutronix */
131 .phys_io = IMX_IO_PHYS,
132 .io_pg_offst = (IMX_IO_BASE >> 18) & 0xfffc,
133 .boot_params = PHYS_OFFSET + 0x100,
134 .map_io = mxc_map_io,
135 .init_irq = mxc_init_irq,
136 .timer = &mx1ads_timer,
137 .init_machine = mx1ads_init,
138MACHINE_END
139
140MACHINE_START(MXLADS, "Freescale MXLADS")
141 .phys_io = IMX_IO_PHYS,
142 .io_pg_offst = (IMX_IO_BASE >> 18) & 0xfffc,
143 .boot_params = PHYS_OFFSET + 0x100,
144 .map_io = mxc_map_io,
145 .init_irq = mxc_init_irq,
146 .timer = &mx1ads_timer,
147 .init_machine = mx1ads_init,
148MACHINE_END