aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-mx3
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-mx3')
-rw-r--r--arch/arm/mach-mx3/Kconfig13
-rw-r--r--arch/arm/mach-mx3/Makefile4
-rw-r--r--arch/arm/mach-mx3/clock.c1147
-rw-r--r--arch/arm/mach-mx3/crm_regs.h401
-rw-r--r--arch/arm/mach-mx3/devices.c180
-rw-r--r--arch/arm/mach-mx3/iomux.c111
-rw-r--r--arch/arm/mach-mx3/mx31ads.c14
-rw-r--r--arch/arm/mach-mx3/mx31lite.c107
-rw-r--r--arch/arm/mach-mx3/pcm037.c130
-rw-r--r--arch/arm/mach-mx3/time.c148
10 files changed, 2105 insertions, 150 deletions
diff --git a/arch/arm/mach-mx3/Kconfig b/arch/arm/mach-mx3/Kconfig
index 5fe8606cac0..db9431dee1b 100644
--- a/arch/arm/mach-mx3/Kconfig
+++ b/arch/arm/mach-mx3/Kconfig
@@ -8,5 +8,18 @@ config MACH_MX31ADS
8 Include support for MX31ADS platform. This includes specific 8 Include support for MX31ADS platform. This includes specific
9 configurations for the board and its peripherals. 9 configurations for the board and its peripherals.
10 10
11config MACH_PCM037
12 bool "Support Phytec pcm037 platforms"
13 help
14 Include support for Phytec pcm037 platform. This includes
15 specific configurations for the board and its peripherals.
16
17config MACH_MX31LITE
18 bool "Support MX31 LITEKIT (LogicPD)"
19 default n
20 help
21 Include support for MX31 LITEKIT platform. This includes specific
22 configurations for the board and its peripherals.
23
11endmenu 24endmenu
12 25
diff --git a/arch/arm/mach-mx3/Makefile b/arch/arm/mach-mx3/Makefile
index cbec997f332..8b21abb71fb 100644
--- a/arch/arm/mach-mx3/Makefile
+++ b/arch/arm/mach-mx3/Makefile
@@ -4,5 +4,7 @@
4 4
5# Object file lists. 5# Object file lists.
6 6
7obj-y := mm.o time.o 7obj-y := mm.o clock.o devices.o iomux.o
8obj-$(CONFIG_MACH_MX31ADS) += mx31ads.o 8obj-$(CONFIG_MACH_MX31ADS) += mx31ads.o
9obj-$(CONFIG_MACH_MX31LITE) += mx31lite.o
10obj-$(CONFIG_MACH_PCM037) += pcm037.o
diff --git a/arch/arm/mach-mx3/clock.c b/arch/arm/mach-mx3/clock.c
new file mode 100644
index 00000000000..2f3635943e7
--- /dev/null
+++ b/arch/arm/mach-mx3/clock.c
@@ -0,0 +1,1147 @@
1/*
2 * Copyright 2005-2007 Freescale Semiconductor, Inc. All Rights Reserved.
3 * Copyright (C) 2008 by Sascha Hauer <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/spinlock.h>
22#include <linux/delay.h>
23#include <linux/clk.h>
24#include <linux/err.h>
25#include <linux/io.h>
26#include <asm/arch/clock.h>
27#include <asm/div64.h>
28
29#include "crm_regs.h"
30
31#define PRE_DIV_MIN_FREQ 10000000 /* Minimum Frequency after Predivider */
32
33static void __calc_pre_post_dividers(u32 div, u32 *pre, u32 *post)
34{
35 u32 min_pre, temp_pre, old_err, err;
36
37 if (div >= 512) {
38 *pre = 8;
39 *post = 64;
40 } else if (div >= 64) {
41 min_pre = (div - 1) / 64 + 1;
42 old_err = 8;
43 for (temp_pre = 8; temp_pre >= min_pre; temp_pre--) {
44 err = div % temp_pre;
45 if (err == 0) {
46 *pre = temp_pre;
47 break;
48 }
49 err = temp_pre - err;
50 if (err < old_err) {
51 old_err = err;
52 *pre = temp_pre;
53 }
54 }
55 *post = (div + *pre - 1) / *pre;
56 } else if (div <= 8) {
57 *pre = div;
58 *post = 1;
59 } else {
60 *pre = 1;
61 *post = div;
62 }
63}
64
65static struct clk mcu_pll_clk;
66static struct clk mcu_main_clk;
67static struct clk usb_pll_clk;
68static struct clk serial_pll_clk;
69static struct clk ipg_clk;
70static struct clk ckih_clk;
71static struct clk ahb_clk;
72
73static int _clk_enable(struct clk *clk)
74{
75 u32 reg;
76
77 reg = __raw_readl(clk->enable_reg);
78 reg |= 3 << clk->enable_shift;
79 __raw_writel(reg, clk->enable_reg);
80
81 return 0;
82}
83
84static void _clk_disable(struct clk *clk)
85{
86 u32 reg;
87
88 reg = __raw_readl(clk->enable_reg);
89 reg &= ~(3 << clk->enable_shift);
90 __raw_writel(reg, clk->enable_reg);
91}
92
93static void _clk_emi_disable(struct clk *clk)
94{
95 u32 reg;
96
97 reg = __raw_readl(clk->enable_reg);
98 reg &= ~(3 << clk->enable_shift);
99 reg |= (1 << clk->enable_shift);
100 __raw_writel(reg, clk->enable_reg);
101}
102
103static int _clk_pll_set_rate(struct clk *clk, unsigned long rate)
104{
105 u32 reg;
106 signed long pd = 1; /* Pre-divider */
107 signed long mfi; /* Multiplication Factor (Integer part) */
108 signed long mfn; /* Multiplication Factor (Integer part) */
109 signed long mfd; /* Multiplication Factor (Denominator Part) */
110 signed long tmp;
111 u32 ref_freq = clk_get_rate(clk->parent);
112
113 while (((ref_freq / pd) * 10) > rate)
114 pd++;
115
116 if ((ref_freq / pd) < PRE_DIV_MIN_FREQ)
117 return -EINVAL;
118
119 /* the ref_freq/2 in the following is to round up */
120 mfi = (((rate / 2) * pd) + (ref_freq / 2)) / ref_freq;
121 if (mfi < 5 || mfi > 15)
122 return -EINVAL;
123
124 /* pick a mfd value that will work
125 * then solve for mfn */
126 mfd = ref_freq / 50000;
127
128 /*
129 * pll_freq * pd * mfd
130 * mfn = -------------------- - (mfi * mfd)
131 * 2 * ref_freq
132 */
133 /* the tmp/2 is for rounding */
134 tmp = ref_freq / 10000;
135 mfn =
136 ((((((rate / 2) + (tmp / 2)) / tmp) * pd) * mfd) / 10000) -
137 (mfi * mfd);
138
139 mfn = mfn & 0x3ff;
140 pd--;
141 mfd--;
142
143 /* Change the Pll value */
144 reg = (mfi << MXC_CCM_PCTL_MFI_OFFSET) |
145 (mfn << MXC_CCM_PCTL_MFN_OFFSET) |
146 (mfd << MXC_CCM_PCTL_MFD_OFFSET) | (pd << MXC_CCM_PCTL_PD_OFFSET);
147
148 if (clk == &mcu_pll_clk)
149 __raw_writel(reg, MXC_CCM_MPCTL);
150 else if (clk == &usb_pll_clk)
151 __raw_writel(reg, MXC_CCM_UPCTL);
152 else if (clk == &serial_pll_clk)
153 __raw_writel(reg, MXC_CCM_SRPCTL);
154
155 return 0;
156}
157
158static unsigned long _clk_pll_get_rate(struct clk *clk)
159{
160 long mfi, mfn, mfd, pdf, ref_clk, mfn_abs;
161 unsigned long reg, ccmr;
162 s64 temp;
163 unsigned int prcs;
164
165 ccmr = __raw_readl(MXC_CCM_CCMR);
166 prcs = (ccmr & MXC_CCM_CCMR_PRCS_MASK) >> MXC_CCM_CCMR_PRCS_OFFSET;
167 if (prcs == 0x1)
168 ref_clk = CKIL_CLK_FREQ * 1024;
169 else
170 ref_clk = clk_get_rate(&ckih_clk);
171
172 if (clk == &mcu_pll_clk) {
173 if ((ccmr & MXC_CCM_CCMR_MPE) == 0)
174 return ref_clk;
175 if ((ccmr & MXC_CCM_CCMR_MDS) != 0)
176 return ref_clk;
177 reg = __raw_readl(MXC_CCM_MPCTL);
178 } else if (clk == &usb_pll_clk)
179 reg = __raw_readl(MXC_CCM_UPCTL);
180 else if (clk == &serial_pll_clk)
181 reg = __raw_readl(MXC_CCM_SRPCTL);
182 else {
183 BUG();
184 return 0;
185 }
186
187 pdf = (reg & MXC_CCM_PCTL_PD_MASK) >> MXC_CCM_PCTL_PD_OFFSET;
188 mfd = (reg & MXC_CCM_PCTL_MFD_MASK) >> MXC_CCM_PCTL_MFD_OFFSET;
189 mfi = (reg & MXC_CCM_PCTL_MFI_MASK) >> MXC_CCM_PCTL_MFI_OFFSET;
190 mfi = (mfi <= 5) ? 5 : mfi;
191 mfn = mfn_abs = reg & MXC_CCM_PCTL_MFN_MASK;
192
193 if (mfn >= 0x200) {
194 mfn |= 0xFFFFFE00;
195 mfn_abs = -mfn;
196 }
197
198 ref_clk *= 2;
199 ref_clk /= pdf + 1;
200
201 temp = (u64) ref_clk * mfn_abs;
202 do_div(temp, mfd + 1);
203 if (mfn < 0)
204 temp = -temp;
205 temp = (ref_clk * mfi) + temp;
206
207 return temp;
208}
209
210static int _clk_usb_pll_enable(struct clk *clk)
211{
212 u32 reg;
213
214 reg = __raw_readl(MXC_CCM_CCMR);
215 reg |= MXC_CCM_CCMR_UPE;
216 __raw_writel(reg, MXC_CCM_CCMR);
217
218 /* No lock bit on MX31, so using max time from spec */
219 udelay(80);
220
221 return 0;
222}
223
224static void _clk_usb_pll_disable(struct clk *clk)
225{
226 u32 reg;
227
228 reg = __raw_readl(MXC_CCM_CCMR);
229 reg &= ~MXC_CCM_CCMR_UPE;
230 __raw_writel(reg, MXC_CCM_CCMR);
231}
232
233static int _clk_serial_pll_enable(struct clk *clk)
234{
235 u32 reg;
236
237 reg = __raw_readl(MXC_CCM_CCMR);
238 reg |= MXC_CCM_CCMR_SPE;
239 __raw_writel(reg, MXC_CCM_CCMR);
240
241 /* No lock bit on MX31, so using max time from spec */
242 udelay(80);
243
244 return 0;
245}
246
247static void _clk_serial_pll_disable(struct clk *clk)
248{
249 u32 reg;
250
251 reg = __raw_readl(MXC_CCM_CCMR);
252 reg &= ~MXC_CCM_CCMR_SPE;
253 __raw_writel(reg, MXC_CCM_CCMR);
254}
255
256#define PDR0(mask, off) ((__raw_readl(MXC_CCM_PDR0) & mask) >> off)
257#define PDR1(mask, off) ((__raw_readl(MXC_CCM_PDR1) & mask) >> off)
258#define PDR2(mask, off) ((__raw_readl(MXC_CCM_PDR2) & mask) >> off)
259
260static unsigned long _clk_mcu_main_get_rate(struct clk *clk)
261{
262 u32 pmcr0 = __raw_readl(MXC_CCM_PMCR0);
263
264 if ((pmcr0 & MXC_CCM_PMCR0_DFSUP1) == MXC_CCM_PMCR0_DFSUP1_SPLL)
265 return clk_get_rate(&serial_pll_clk);
266 else
267 return clk_get_rate(&mcu_pll_clk);
268}
269
270static unsigned long _clk_hclk_get_rate(struct clk *clk)
271{
272 unsigned long max_pdf;
273
274 max_pdf = PDR0(MXC_CCM_PDR0_MAX_PODF_MASK,
275 MXC_CCM_PDR0_MAX_PODF_OFFSET);
276 return clk_get_rate(clk->parent) / (max_pdf + 1);
277}
278
279static unsigned long _clk_ipg_get_rate(struct clk *clk)
280{
281 unsigned long ipg_pdf;
282
283 ipg_pdf = PDR0(MXC_CCM_PDR0_IPG_PODF_MASK,
284 MXC_CCM_PDR0_IPG_PODF_OFFSET);
285 return clk_get_rate(clk->parent) / (ipg_pdf + 1);
286}
287
288static unsigned long _clk_nfc_get_rate(struct clk *clk)
289{
290 unsigned long nfc_pdf;
291
292 nfc_pdf = PDR0(MXC_CCM_PDR0_NFC_PODF_MASK,
293 MXC_CCM_PDR0_NFC_PODF_OFFSET);
294 return clk_get_rate(clk->parent) / (nfc_pdf + 1);
295}
296
297static unsigned long _clk_hsp_get_rate(struct clk *clk)
298{
299 unsigned long hsp_pdf;
300
301 hsp_pdf = PDR0(MXC_CCM_PDR0_HSP_PODF_MASK,
302 MXC_CCM_PDR0_HSP_PODF_OFFSET);
303 return clk_get_rate(clk->parent) / (hsp_pdf + 1);
304}
305
306static unsigned long _clk_usb_get_rate(struct clk *clk)
307{
308 unsigned long usb_pdf, usb_prepdf;
309
310 usb_pdf = PDR1(MXC_CCM_PDR1_USB_PODF_MASK,
311 MXC_CCM_PDR1_USB_PODF_OFFSET);
312 usb_prepdf = PDR1(MXC_CCM_PDR1_USB_PRDF_MASK,
313 MXC_CCM_PDR1_USB_PRDF_OFFSET);
314 return clk_get_rate(clk->parent) / (usb_prepdf + 1) / (usb_pdf + 1);
315}
316
317static unsigned long _clk_csi_get_rate(struct clk *clk)
318{
319 u32 reg, pre, post;
320
321 reg = __raw_readl(MXC_CCM_PDR0);
322 pre = (reg & MXC_CCM_PDR0_CSI_PRDF_MASK) >>
323 MXC_CCM_PDR0_CSI_PRDF_OFFSET;
324 pre++;
325 post = (reg & MXC_CCM_PDR0_CSI_PODF_MASK) >>
326 MXC_CCM_PDR0_CSI_PODF_OFFSET;
327 post++;
328 return clk_get_rate(clk->parent) / (pre * post);
329}
330
331static unsigned long _clk_csi_round_rate(struct clk *clk, unsigned long rate)
332{
333 u32 pre, post, parent = clk_get_rate(clk->parent);
334 u32 div = parent / rate;
335
336 if (parent % rate)
337 div++;
338
339 __calc_pre_post_dividers(div, &pre, &post);
340
341 return parent / (pre * post);
342}
343
344static int _clk_csi_set_rate(struct clk *clk, unsigned long rate)
345{
346 u32 reg, div, pre, post, parent = clk_get_rate(clk->parent);
347
348 div = parent / rate;
349
350 if ((parent / div) != rate)
351 return -EINVAL;
352
353 __calc_pre_post_dividers(div, &pre, &post);
354
355 /* Set CSI clock divider */
356 reg = __raw_readl(MXC_CCM_PDR0) &
357 ~(MXC_CCM_PDR0_CSI_PODF_MASK | MXC_CCM_PDR0_CSI_PRDF_MASK);
358 reg |= (post - 1) << MXC_CCM_PDR0_CSI_PODF_OFFSET;
359 reg |= (pre - 1) << MXC_CCM_PDR0_CSI_PRDF_OFFSET;
360 __raw_writel(reg, MXC_CCM_PDR0);
361
362 return 0;
363}
364
365static unsigned long _clk_per_get_rate(struct clk *clk)
366{
367 unsigned long per_pdf;
368
369 per_pdf = PDR0(MXC_CCM_PDR0_PER_PODF_MASK,
370 MXC_CCM_PDR0_PER_PODF_OFFSET);
371 return clk_get_rate(clk->parent) / (per_pdf + 1);
372}
373
374static unsigned long _clk_ssi1_get_rate(struct clk *clk)
375{
376 unsigned long ssi1_pdf, ssi1_prepdf;
377
378 ssi1_pdf = PDR1(MXC_CCM_PDR1_SSI1_PODF_MASK,
379 MXC_CCM_PDR1_SSI1_PODF_OFFSET);
380 ssi1_prepdf = PDR1(MXC_CCM_PDR1_SSI1_PRE_PODF_MASK,
381 MXC_CCM_PDR1_SSI1_PRE_PODF_OFFSET);
382 return clk_get_rate(clk->parent) / (ssi1_prepdf + 1) / (ssi1_pdf + 1);
383}
384
385static unsigned long _clk_ssi2_get_rate(struct clk *clk)
386{
387 unsigned long ssi2_pdf, ssi2_prepdf;
388
389 ssi2_pdf = PDR1(MXC_CCM_PDR1_SSI2_PODF_MASK,
390 MXC_CCM_PDR1_SSI2_PODF_OFFSET);
391 ssi2_prepdf = PDR1(MXC_CCM_PDR1_SSI2_PRE_PODF_MASK,
392 MXC_CCM_PDR1_SSI2_PRE_PODF_OFFSET);
393 return clk_get_rate(clk->parent) / (ssi2_prepdf + 1) / (ssi2_pdf + 1);
394}
395
396static unsigned long _clk_firi_get_rate(struct clk *clk)
397{
398 unsigned long firi_pdf, firi_prepdf;
399
400 firi_pdf = PDR1(MXC_CCM_PDR1_FIRI_PODF_MASK,
401 MXC_CCM_PDR1_FIRI_PODF_OFFSET);
402 firi_prepdf = PDR1(MXC_CCM_PDR1_FIRI_PRE_PODF_MASK,
403 MXC_CCM_PDR1_FIRI_PRE_PODF_OFFSET);
404 return clk_get_rate(clk->parent) / (firi_prepdf + 1) / (firi_pdf + 1);
405}
406
407static unsigned long _clk_firi_round_rate(struct clk *clk, unsigned long rate)
408{
409 u32 pre, post;
410 u32 parent = clk_get_rate(clk->parent);
411 u32 div = parent / rate;
412
413 if (parent % rate)
414 div++;
415
416 __calc_pre_post_dividers(div, &pre, &post);
417
418 return parent / (pre * post);
419
420}
421
422static int _clk_firi_set_rate(struct clk *clk, unsigned long rate)
423{
424 u32 reg, div, pre, post, parent = clk_get_rate(clk->parent);
425
426 div = parent / rate;
427
428 if ((parent / div) != rate)
429 return -EINVAL;
430
431 __calc_pre_post_dividers(div, &pre, &post);
432
433 /* Set FIRI clock divider */
434 reg = __raw_readl(MXC_CCM_PDR1) &
435 ~(MXC_CCM_PDR1_FIRI_PODF_MASK | MXC_CCM_PDR1_FIRI_PRE_PODF_MASK);
436 reg |= (pre - 1) << MXC_CCM_PDR1_FIRI_PRE_PODF_OFFSET;
437 reg |= (post - 1) << MXC_CCM_PDR1_FIRI_PODF_OFFSET;
438 __raw_writel(reg, MXC_CCM_PDR1);
439
440 return 0;
441}
442
443static unsigned long _clk_mbx_get_rate(struct clk *clk)
444{
445 return clk_get_rate(clk->parent) / 2;
446}
447
448static unsigned long _clk_mstick1_get_rate(struct clk *clk)
449{
450 unsigned long msti_pdf;
451
452 msti_pdf = PDR2(MXC_CCM_PDR2_MST1_PDF_MASK,
453 MXC_CCM_PDR2_MST1_PDF_OFFSET);
454 return clk_get_rate(clk->parent) / (msti_pdf + 1);
455}
456
457static unsigned long _clk_mstick2_get_rate(struct clk *clk)
458{
459 unsigned long msti_pdf;
460
461 msti_pdf = PDR2(MXC_CCM_PDR2_MST2_PDF_MASK,
462 MXC_CCM_PDR2_MST2_PDF_OFFSET);
463 return clk_get_rate(clk->parent) / (msti_pdf + 1);
464}
465
466static unsigned long ckih_rate;
467
468static unsigned long clk_ckih_get_rate(struct clk *clk)
469{
470 return ckih_rate;
471}
472
473static struct clk ckih_clk = {
474 .name = "ckih",
475 .get_rate = clk_ckih_get_rate,
476};
477
478static unsigned long clk_ckil_get_rate(struct clk *clk)
479{
480 return CKIL_CLK_FREQ;
481}
482
483static struct clk ckil_clk = {
484 .name = "ckil",
485 .get_rate = clk_ckil_get_rate,
486};
487
488static struct clk mcu_pll_clk = {
489 .name = "mcu_pll",
490 .parent = &ckih_clk,
491 .set_rate = _clk_pll_set_rate,
492 .get_rate = _clk_pll_get_rate,
493};
494
495static struct clk mcu_main_clk = {
496 .name = "mcu_main_clk",
497 .parent = &mcu_pll_clk,
498 .get_rate = _clk_mcu_main_get_rate,
499};
500
501static struct clk serial_pll_clk = {
502 .name = "serial_pll",
503 .parent = &ckih_clk,
504 .set_rate = _clk_pll_set_rate,
505 .get_rate = _clk_pll_get_rate,
506 .enable = _clk_serial_pll_enable,
507 .disable = _clk_serial_pll_disable,
508};
509
510static struct clk usb_pll_clk = {
511 .name = "usb_pll",
512 .parent = &ckih_clk,
513 .set_rate = _clk_pll_set_rate,
514 .get_rate = _clk_pll_get_rate,
515 .enable = _clk_usb_pll_enable,
516 .disable = _clk_usb_pll_disable,
517};
518
519static struct clk ahb_clk = {
520 .name = "ahb_clk",
521 .parent = &mcu_main_clk,
522 .get_rate = _clk_hclk_get_rate,
523};
524
525static struct clk per_clk = {
526 .name = "per_clk",
527 .parent = &usb_pll_clk,
528 .get_rate = _clk_per_get_rate,
529};
530
531static struct clk perclk_clk = {
532 .name = "perclk_clk",
533 .parent = &ipg_clk,
534};
535
536static struct clk cspi_clk[] = {
537 {
538 .name = "cspi_clk",
539 .id = 0,
540 .parent = &ipg_clk,
541 .enable = _clk_enable,
542 .enable_reg = MXC_CCM_CGR2,
543 .enable_shift = MXC_CCM_CGR2_CSPI1_OFFSET,
544 .disable = _clk_disable,},
545 {
546 .name = "cspi_clk",
547 .id = 1,
548 .parent = &ipg_clk,
549 .enable = _clk_enable,
550 .enable_reg = MXC_CCM_CGR2,
551 .enable_shift = MXC_CCM_CGR2_CSPI2_OFFSET,
552 .disable = _clk_disable,},
553 {
554 .name = "cspi_clk",
555 .id = 2,
556 .parent = &ipg_clk,
557 .enable = _clk_enable,
558 .enable_reg = MXC_CCM_CGR0,
559 .enable_shift = MXC_CCM_CGR0_CSPI3_OFFSET,
560 .disable = _clk_disable,},
561};
562
563static struct clk ipg_clk = {
564 .name = "ipg_clk",
565 .parent = &ahb_clk,
566 .get_rate = _clk_ipg_get_rate,
567};
568
569static struct clk emi_clk = {
570 .name = "emi_clk",
571 .parent = &ahb_clk,
572 .enable = _clk_enable,
573 .enable_reg = MXC_CCM_CGR2,
574 .enable_shift = MXC_CCM_CGR2_EMI_OFFSET,
575 .disable = _clk_emi_disable,
576};
577
578static struct clk gpt_clk = {
579 .name = "gpt_clk",
580 .parent = &perclk_clk,
581 .enable = _clk_enable,
582 .enable_reg = MXC_CCM_CGR0,
583 .enable_shift = MXC_CCM_CGR0_GPT_OFFSET,
584 .disable = _clk_disable,
585};
586
587static struct clk pwm_clk = {
588 .name = "pwm_clk",
589 .parent = &perclk_clk,
590 .enable = _clk_enable,
591 .enable_reg = MXC_CCM_CGR0,
592 .enable_shift = MXC_CCM_CGR1_PWM_OFFSET,
593 .disable = _clk_disable,
594};
595
596static struct clk epit_clk[] = {
597 {
598 .name = "epit_clk",
599 .id = 0,
600 .parent = &perclk_clk,
601 .enable = _clk_enable,
602 .enable_reg = MXC_CCM_CGR0,
603 .enable_shift = MXC_CCM_CGR0_EPIT1_OFFSET,
604 .disable = _clk_disable,},
605 {
606 .name = "epit_clk",
607 .id = 1,
608 .parent = &perclk_clk,
609 .enable = _clk_enable,
610 .enable_reg = MXC_CCM_CGR0,
611 .enable_shift = MXC_CCM_CGR0_EPIT2_OFFSET,
612 .disable = _clk_disable,},
613};
614
615static struct clk nfc_clk = {
616 .name = "nfc_clk",
617 .parent = &ahb_clk,
618 .get_rate = _clk_nfc_get_rate,
619};
620
621static struct clk scc_clk = {
622 .name = "scc_clk",
623 .parent = &ipg_clk,
624};
625
626static struct clk ipu_clk = {
627 .name = "ipu_clk",
628 .parent = &mcu_main_clk,
629 .get_rate = _clk_hsp_get_rate,
630 .enable = _clk_enable,
631 .enable_reg = MXC_CCM_CGR1,
632 .enable_shift = MXC_CCM_CGR1_IPU_OFFSET,
633 .disable = _clk_disable,
634};
635
636static struct clk kpp_clk = {
637 .name = "kpp_clk",
638 .parent = &ipg_clk,
639 .enable = _clk_enable,
640 .enable_reg = MXC_CCM_CGR1,
641 .enable_shift = MXC_CCM_CGR1_KPP_OFFSET,
642 .disable = _clk_disable,
643};
644
645static struct clk wdog_clk = {
646 .name = "wdog_clk",
647 .parent = &ipg_clk,
648 .enable = _clk_enable,
649 .enable_reg = MXC_CCM_CGR1,
650 .enable_shift = MXC_CCM_CGR1_WDOG_OFFSET,
651 .disable = _clk_disable,
652};
653static struct clk rtc_clk = {
654 .name = "rtc_clk",
655 .parent = &ipg_clk,
656 .enable = _clk_enable,
657 .enable_reg = MXC_CCM_CGR1,
658 .enable_shift = MXC_CCM_CGR1_RTC_OFFSET,
659 .disable = _clk_disable,
660};
661
662static struct clk usb_clk[] = {
663 {
664 .name = "usb_clk",
665 .parent = &usb_pll_clk,
666 .get_rate = _clk_usb_get_rate,},
667 {
668 .name = "usb_ahb_clk",
669 .parent = &ahb_clk,
670 .enable = _clk_enable,
671 .enable_reg = MXC_CCM_CGR1,
672 .enable_shift = MXC_CCM_CGR1_USBOTG_OFFSET,
673 .disable = _clk_disable,},
674};
675
676static struct clk csi_clk = {
677 .name = "csi_clk",
678 .parent = &serial_pll_clk,
679 .get_rate = _clk_csi_get_rate,
680 .round_rate = _clk_csi_round_rate,
681 .set_rate = _clk_csi_set_rate,
682 .enable = _clk_enable,
683 .enable_reg = MXC_CCM_CGR1,
684 .enable_shift = MXC_CCM_CGR1_CSI_OFFSET,
685 .disable = _clk_disable,
686};
687
688static struct clk uart_clk[] = {
689 {
690 .name = "uart_clk",
691 .id = 0,
692 .parent = &perclk_clk,
693 .enable = _clk_enable,
694 .enable_reg = MXC_CCM_CGR0,
695 .enable_shift = MXC_CCM_CGR0_UART1_OFFSET,
696 .disable = _clk_disable,},
697 {
698 .name = "uart_clk",
699 .id = 1,
700 .parent = &perclk_clk,
701 .enable = _clk_enable,
702 .enable_reg = MXC_CCM_CGR0,
703 .enable_shift = MXC_CCM_CGR0_UART2_OFFSET,
704 .disable = _clk_disable,},
705 {
706 .name = "uart_clk",
707 .id = 2,
708 .parent = &perclk_clk,
709 .enable = _clk_enable,
710 .enable_reg = MXC_CCM_CGR1,
711 .enable_shift = MXC_CCM_CGR1_UART3_OFFSET,
712 .disable = _clk_disable,},
713 {
714 .name = "uart_clk",
715 .id = 3,
716 .parent = &perclk_clk,
717 .enable = _clk_enable,
718 .enable_reg = MXC_CCM_CGR1,
719 .enable_shift = MXC_CCM_CGR1_UART4_OFFSET,
720 .disable = _clk_disable,},
721 {
722 .name = "uart_clk",
723 .id = 4,
724 .parent = &perclk_clk,
725 .enable = _clk_enable,
726 .enable_reg = MXC_CCM_CGR1,
727 .enable_shift = MXC_CCM_CGR1_UART5_OFFSET,
728 .disable = _clk_disable,},
729};
730
731static struct clk i2c_clk[] = {
732 {
733 .name = "i2c_clk",
734 .id = 0,
735 .parent = &perclk_clk,
736 .enable = _clk_enable,
737 .enable_reg = MXC_CCM_CGR0,
738 .enable_shift = MXC_CCM_CGR0_I2C1_OFFSET,
739 .disable = _clk_disable,},
740 {
741 .name = "i2c_clk",
742 .id = 1,
743 .parent = &perclk_clk,
744 .enable = _clk_enable,
745 .enable_reg = MXC_CCM_CGR0,
746 .enable_shift = MXC_CCM_CGR0_I2C2_OFFSET,
747 .disable = _clk_disable,},
748 {
749 .name = "i2c_clk",
750 .id = 2,
751 .parent = &perclk_clk,
752 .enable = _clk_enable,
753 .enable_reg = MXC_CCM_CGR0,
754 .enable_shift = MXC_CCM_CGR0_I2C3_OFFSET,
755 .disable = _clk_disable,},
756};
757
758static struct clk owire_clk = {
759 .name = "owire_clk",
760 .parent = &perclk_clk,
761 .enable_reg = MXC_CCM_CGR1,
762 .enable_shift = MXC_CCM_CGR1_OWIRE_OFFSET,
763 .enable = _clk_enable,
764 .disable = _clk_disable,
765};
766
767static struct clk sdhc_clk[] = {
768 {
769 .name = "sdhc_clk",
770 .id = 0,
771 .parent = &perclk_clk,
772 .enable = _clk_enable,
773 .enable_reg = MXC_CCM_CGR0,
774 .enable_shift = MXC_CCM_CGR0_SD_MMC1_OFFSET,
775 .disable = _clk_disable,},
776 {
777 .name = "sdhc_clk",
778 .id = 1,
779 .parent = &perclk_clk,
780 .enable = _clk_enable,
781 .enable_reg = MXC_CCM_CGR0,
782 .enable_shift = MXC_CCM_CGR0_SD_MMC2_OFFSET,
783 .disable = _clk_disable,},
784};
785
786static struct clk ssi_clk[] = {
787 {
788 .name = "ssi_clk",
789 .parent = &serial_pll_clk,
790 .get_rate = _clk_ssi1_get_rate,
791 .enable = _clk_enable,
792 .enable_reg = MXC_CCM_CGR0,
793 .enable_shift = MXC_CCM_CGR0_SSI1_OFFSET,
794 .disable = _clk_disable,},
795 {
796 .name = "ssi_clk",
797 .id = 1,
798 .parent = &serial_pll_clk,
799 .get_rate = _clk_ssi2_get_rate,
800 .enable = _clk_enable,
801 .enable_reg = MXC_CCM_CGR2,
802 .enable_shift = MXC_CCM_CGR2_SSI2_OFFSET,
803 .disable = _clk_disable,},
804};
805
806static struct clk firi_clk = {
807 .name = "firi_clk",
808 .parent = &usb_pll_clk,
809 .round_rate = _clk_firi_round_rate,
810 .set_rate = _clk_firi_set_rate,
811 .get_rate = _clk_firi_get_rate,
812 .enable = _clk_enable,
813 .enable_reg = MXC_CCM_CGR2,
814 .enable_shift = MXC_CCM_CGR2_FIRI_OFFSET,
815 .disable = _clk_disable,
816};
817
818static struct clk ata_clk = {
819 .name = "ata_clk",
820 .parent = &ipg_clk,
821 .enable = _clk_enable,
822 .enable_reg = MXC_CCM_CGR0,
823 .enable_shift = MXC_CCM_CGR0_ATA_OFFSET,
824 .disable = _clk_disable,
825};
826
827static struct clk mbx_clk = {
828 .name = "mbx_clk",
829 .parent = &ahb_clk,
830 .enable = _clk_enable,
831 .enable_reg = MXC_CCM_CGR2,
832 .enable_shift = MXC_CCM_CGR2_GACC_OFFSET,
833 .get_rate = _clk_mbx_get_rate,
834};
835
836static struct clk vpu_clk = {
837 .name = "vpu_clk",
838 .parent = &ahb_clk,
839 .enable = _clk_enable,
840 .enable_reg = MXC_CCM_CGR2,
841 .enable_shift = MXC_CCM_CGR2_GACC_OFFSET,
842 .get_rate = _clk_mbx_get_rate,
843};
844
845static struct clk rtic_clk = {
846 .name = "rtic_clk",
847 .parent = &ahb_clk,
848 .enable = _clk_enable,
849 .enable_reg = MXC_CCM_CGR2,
850 .enable_shift = MXC_CCM_CGR2_RTIC_OFFSET,
851 .disable = _clk_disable,
852};
853
854static struct clk rng_clk = {
855 .name = "rng_clk",
856 .parent = &ipg_clk,
857 .enable = _clk_enable,
858 .enable_reg = MXC_CCM_CGR0,
859 .enable_shift = MXC_CCM_CGR0_RNG_OFFSET,
860 .disable = _clk_disable,
861};
862
863static struct clk sdma_clk[] = {
864 {
865 .name = "sdma_ahb_clk",
866 .parent = &ahb_clk,
867 .enable = _clk_enable,
868 .enable_reg = MXC_CCM_CGR0,
869 .enable_shift = MXC_CCM_CGR0_SDMA_OFFSET,
870 .disable = _clk_disable,},
871 {
872 .name = "sdma_ipg_clk",
873 .parent = &ipg_clk,}
874};
875
876static struct clk mpeg4_clk = {
877 .name = "mpeg4_clk",
878 .parent = &ahb_clk,
879 .enable = _clk_enable,
880 .enable_reg = MXC_CCM_CGR1,
881 .enable_shift = MXC_CCM_CGR1_HANTRO_OFFSET,
882 .disable = _clk_disable,
883};
884
885static struct clk vl2cc_clk = {
886 .name = "vl2cc_clk",
887 .parent = &ahb_clk,
888 .enable = _clk_enable,
889 .enable_reg = MXC_CCM_CGR1,
890 .enable_shift = MXC_CCM_CGR1_HANTRO_OFFSET,
891 .disable = _clk_disable,
892};
893
894static struct clk mstick_clk[] = {
895 {
896 .name = "mstick_clk",
897 .id = 0,
898 .parent = &usb_pll_clk,
899 .get_rate = _clk_mstick1_get_rate,
900 .enable = _clk_enable,
901 .enable_reg = MXC_CCM_CGR1,
902 .enable_shift = MXC_CCM_CGR1_MEMSTICK1_OFFSET,
903 .disable = _clk_disable,},
904 {
905 .name = "mstick_clk",
906 .id = 1,
907 .parent = &usb_pll_clk,
908 .get_rate = _clk_mstick2_get_rate,
909 .enable = _clk_enable,
910 .enable_reg = MXC_CCM_CGR1,
911 .enable_shift = MXC_CCM_CGR1_MEMSTICK2_OFFSET,
912 .disable = _clk_disable,},
913};
914
915static struct clk iim_clk = {
916 .name = "iim_clk",
917 .parent = &ipg_clk,
918 .enable = _clk_enable,
919 .enable_reg = MXC_CCM_CGR0,
920 .enable_shift = MXC_CCM_CGR0_IIM_OFFSET,
921 .disable = _clk_disable,
922};
923
924static unsigned long _clk_cko1_round_rate(struct clk *clk, unsigned long rate)
925{
926 u32 div, parent = clk_get_rate(clk->parent);
927
928 div = parent / rate;
929 if (parent % rate)
930 div++;
931
932 if (div > 8)
933 div = 16;
934 else if (div > 4)
935 div = 8;
936 else if (div > 2)
937 div = 4;
938
939 return parent / div;
940}
941
942static int _clk_cko1_set_rate(struct clk *clk, unsigned long rate)
943{
944 u32 reg, div, parent = clk_get_rate(clk->parent);
945
946 div = parent / rate;
947
948 if (div == 16)
949 div = 4;
950 else if (div == 8)
951 div = 3;
952 else if (div == 4)
953 div = 2;
954 else if (div == 2)
955 div = 1;
956 else if (div == 1)
957 div = 0;
958 else
959 return -EINVAL;
960
961 reg = __raw_readl(MXC_CCM_COSR) & ~MXC_CCM_COSR_CLKOUTDIV_MASK;
962 reg |= div << MXC_CCM_COSR_CLKOUTDIV_OFFSET;
963 __raw_writel(reg, MXC_CCM_COSR);
964
965 return 0;
966}
967
968static unsigned long _clk_cko1_get_rate(struct clk *clk)
969{
970 u32 div;
971
972 div = __raw_readl(MXC_CCM_COSR) & MXC_CCM_COSR_CLKOUTDIV_MASK >>
973 MXC_CCM_COSR_CLKOUTDIV_OFFSET;
974
975 return clk_get_rate(clk->parent) / (1 << div);
976}
977
978static int _clk_cko1_set_parent(struct clk *clk, struct clk *parent)
979{
980 u32 reg;
981
982 reg = __raw_readl(MXC_CCM_COSR) & ~MXC_CCM_COSR_CLKOSEL_MASK;
983
984 if (parent == &mcu_main_clk)
985 reg |= 0 << MXC_CCM_COSR_CLKOSEL_OFFSET;
986 else if (parent == &ipg_clk)
987 reg |= 1 << MXC_CCM_COSR_CLKOSEL_OFFSET;
988 else if (parent == &usb_pll_clk)
989 reg |= 2 << MXC_CCM_COSR_CLKOSEL_OFFSET;
990 else if (parent == mcu_main_clk.parent)
991 reg |= 3 << MXC_CCM_COSR_CLKOSEL_OFFSET;
992 else if (parent == &ahb_clk)
993 reg |= 5 << MXC_CCM_COSR_CLKOSEL_OFFSET;
994 else if (parent == &serial_pll_clk)
995 reg |= 7 << MXC_CCM_COSR_CLKOSEL_OFFSET;
996 else if (parent == &ckih_clk)
997 reg |= 8 << MXC_CCM_COSR_CLKOSEL_OFFSET;
998 else if (parent == &emi_clk)
999 reg |= 9 << MXC_CCM_COSR_CLKOSEL_OFFSET;
1000 else if (parent == &ipu_clk)
1001 reg |= 0xA << MXC_CCM_COSR_CLKOSEL_OFFSET;
1002 else if (parent == &nfc_clk)
1003 reg |= 0xB << MXC_CCM_COSR_CLKOSEL_OFFSET;
1004 else if (parent == &uart_clk[0])
1005 reg |= 0xC << MXC_CCM_COSR_CLKOSEL_OFFSET;
1006 else
1007 return -EINVAL;
1008
1009 __raw_writel(reg, MXC_CCM_COSR);
1010
1011 return 0;
1012}
1013
1014static int _clk_cko1_enable(struct clk *clk)
1015{
1016 u32 reg;
1017
1018 reg = __raw_readl(MXC_CCM_COSR) | MXC_CCM_COSR_CLKOEN;
1019 __raw_writel(reg, MXC_CCM_COSR);
1020
1021 return 0;
1022}
1023
1024static void _clk_cko1_disable(struct clk *clk)
1025{
1026 u32 reg;
1027
1028 reg = __raw_readl(MXC_CCM_COSR) & ~MXC_CCM_COSR_CLKOEN;
1029 __raw_writel(reg, MXC_CCM_COSR);
1030}
1031
1032static struct clk cko1_clk = {
1033 .name = "cko1_clk",
1034 .get_rate = _clk_cko1_get_rate,
1035 .set_rate = _clk_cko1_set_rate,
1036 .round_rate = _clk_cko1_round_rate,
1037 .set_parent = _clk_cko1_set_parent,
1038 .enable = _clk_cko1_enable,
1039 .disable = _clk_cko1_disable,
1040};
1041
1042static struct clk *mxc_clks[] = {
1043 &ckih_clk,
1044 &ckil_clk,
1045 &mcu_pll_clk,
1046 &usb_pll_clk,
1047 &serial_pll_clk,
1048 &mcu_main_clk,
1049 &ahb_clk,
1050 &per_clk,
1051 &perclk_clk,
1052 &cko1_clk,
1053 &emi_clk,
1054 &cspi_clk[0],
1055 &cspi_clk[1],
1056 &cspi_clk[2],
1057 &ipg_clk,
1058 &gpt_clk,
1059 &pwm_clk,
1060 &wdog_clk,
1061 &rtc_clk,
1062 &epit_clk[0],
1063 &epit_clk[1],
1064 &nfc_clk,
1065 &ipu_clk,
1066 &kpp_clk,
1067 &usb_clk[0],
1068 &usb_clk[1],
1069 &csi_clk,
1070 &uart_clk[0],
1071 &uart_clk[1],
1072 &uart_clk[2],
1073 &uart_clk[3],
1074 &uart_clk[4],
1075 &i2c_clk[0],
1076 &i2c_clk[1],
1077 &i2c_clk[2],
1078 &owire_clk,
1079 &sdhc_clk[0],
1080 &sdhc_clk[1],
1081 &ssi_clk[0],
1082 &ssi_clk[1],
1083 &firi_clk,
1084 &ata_clk,
1085 &rtic_clk,
1086 &rng_clk,
1087 &sdma_clk[0],
1088 &sdma_clk[1],
1089 &mstick_clk[0],
1090 &mstick_clk[1],
1091 &scc_clk,
1092 &iim_clk,
1093};
1094
1095int __init mxc_clocks_init(unsigned long fref)
1096{
1097 u32 reg;
1098 struct clk **clkp;
1099
1100 ckih_rate = fref;
1101
1102 for (clkp = mxc_clks; clkp < mxc_clks + ARRAY_SIZE(mxc_clks); clkp++)
1103 clk_register(*clkp);
1104
1105 if (cpu_is_mx31()) {
1106 clk_register(&mpeg4_clk);
1107 clk_register(&mbx_clk);
1108 } else {
1109 clk_register(&vpu_clk);
1110 clk_register(&vl2cc_clk);
1111 }
1112
1113 /* Turn off all possible clocks */
1114 __raw_writel(MXC_CCM_CGR0_GPT_MASK, MXC_CCM_CGR0);
1115 __raw_writel(0, MXC_CCM_CGR1);
1116
1117 __raw_writel(MXC_CCM_CGR2_EMI_MASK |
1118 MXC_CCM_CGR2_IPMUX1_MASK |
1119 MXC_CCM_CGR2_IPMUX2_MASK |
1120 MXC_CCM_CGR2_MXCCLKENSEL_MASK | /* for MX32 */
1121 MXC_CCM_CGR2_CHIKCAMPEN_MASK | /* for MX32 */
1122 MXC_CCM_CGR2_OVRVPUBUSY_MASK | /* for MX32 */
1123 1 << 27 | 1 << 28, /* Bit 27 and 28 are not defined for
1124 MX32, but still required to be set */
1125 MXC_CCM_CGR2);
1126
1127 clk_disable(&cko1_clk);
1128 clk_disable(&usb_pll_clk);
1129
1130 pr_info("Clock input source is %ld\n", clk_get_rate(&ckih_clk));
1131
1132 clk_enable(&gpt_clk);
1133 clk_enable(&emi_clk);
1134 clk_enable(&iim_clk);
1135
1136 clk_enable(&serial_pll_clk);
1137
1138 if (mx31_revision() >= CHIP_REV_2_0) {
1139 reg = __raw_readl(MXC_CCM_PMCR1);
1140 /* No PLL restart on DVFS switch; enable auto EMI handshake */
1141 reg |= MXC_CCM_PMCR1_PLLRDIS | MXC_CCM_PMCR1_EMIRQ_EN;
1142 __raw_writel(reg, MXC_CCM_PMCR1);
1143 }
1144
1145 return 0;
1146}
1147
diff --git a/arch/arm/mach-mx3/crm_regs.h b/arch/arm/mach-mx3/crm_regs.h
new file mode 100644
index 00000000000..4a0e0ede23b
--- /dev/null
+++ b/arch/arm/mach-mx3/crm_regs.h
@@ -0,0 +1,401 @@
1/*
2 * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
3 * Copyright (C) 2008 by Sascha Hauer <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_MX3_CRM_REGS_H__
21#define __ARCH_ARM_MACH_MX3_CRM_REGS_H__
22
23#define CKIH_CLK_FREQ 26000000
24#define CKIH_CLK_FREQ_27MHZ 27000000
25#define CKIL_CLK_FREQ 32768
26
27#define MXC_CCM_BASE IO_ADDRESS(CCM_BASE_ADDR)
28
29/* Register addresses */
30#define MXC_CCM_CCMR (MXC_CCM_BASE + 0x00)
31#define MXC_CCM_PDR0 (MXC_CCM_BASE + 0x04)
32#define MXC_CCM_PDR1 (MXC_CCM_BASE + 0x08)
33#define MXC_CCM_RCSR (MXC_CCM_BASE + 0x0C)
34#define MXC_CCM_MPCTL (MXC_CCM_BASE + 0x10)
35#define MXC_CCM_UPCTL (MXC_CCM_BASE + 0x14)
36#define MXC_CCM_SRPCTL (MXC_CCM_BASE + 0x18)
37#define MXC_CCM_COSR (MXC_CCM_BASE + 0x1C)
38#define MXC_CCM_CGR0 (MXC_CCM_BASE + 0x20)
39#define MXC_CCM_CGR1 (MXC_CCM_BASE + 0x24)
40#define MXC_CCM_CGR2 (MXC_CCM_BASE + 0x28)
41#define MXC_CCM_WIMR (MXC_CCM_BASE + 0x2C)
42#define MXC_CCM_LDC (MXC_CCM_BASE + 0x30)
43#define MXC_CCM_DCVR0 (MXC_CCM_BASE + 0x34)
44#define MXC_CCM_DCVR1 (MXC_CCM_BASE + 0x38)
45#define MXC_CCM_DCVR2 (MXC_CCM_BASE + 0x3C)
46#define MXC_CCM_DCVR3 (MXC_CCM_BASE + 0x40)
47#define MXC_CCM_LTR0 (MXC_CCM_BASE + 0x44)
48#define MXC_CCM_LTR1 (MXC_CCM_BASE + 0x48)
49#define MXC_CCM_LTR2 (MXC_CCM_BASE + 0x4C)
50#define MXC_CCM_LTR3 (MXC_CCM_BASE + 0x50)
51#define MXC_CCM_LTBR0 (MXC_CCM_BASE + 0x54)
52#define MXC_CCM_LTBR1 (MXC_CCM_BASE + 0x58)
53#define MXC_CCM_PMCR0 (MXC_CCM_BASE + 0x5C)
54#define MXC_CCM_PMCR1 (MXC_CCM_BASE + 0x60)
55#define MXC_CCM_PDR2 (MXC_CCM_BASE + 0x64)
56
57/* Register bit definitions */
58#define MXC_CCM_CCMR_WBEN (1 << 27)
59#define MXC_CCM_CCMR_CSCS (1 << 25)
60#define MXC_CCM_CCMR_PERCS (1 << 24)
61#define MXC_CCM_CCMR_SSI1S_OFFSET 18
62#define MXC_CCM_CCMR_SSI1S_MASK (0x3 << 18)
63#define MXC_CCM_CCMR_SSI2S_OFFSET 21
64#define MXC_CCM_CCMR_SSI2S_MASK (0x3 << 21)
65#define MXC_CCM_CCMR_LPM_OFFSET 14
66#define MXC_CCM_CCMR_LPM_MASK (0x3 << 14)
67#define MXC_CCM_CCMR_FIRS_OFFSET 11
68#define MXC_CCM_CCMR_FIRS_MASK (0x3 << 11)
69#define MXC_CCM_CCMR_UPE (1 << 9)
70#define MXC_CCM_CCMR_SPE (1 << 8)
71#define MXC_CCM_CCMR_MDS (1 << 7)
72#define MXC_CCM_CCMR_SBYCS (1 << 4)
73#define MXC_CCM_CCMR_MPE (1 << 3)
74#define MXC_CCM_CCMR_PRCS_OFFSET 1
75#define MXC_CCM_CCMR_PRCS_MASK (0x3 << 1)
76
77#define MXC_CCM_PDR0_CSI_PODF_OFFSET 26
78#define MXC_CCM_PDR0_CSI_PODF_MASK (0x3F << 26)
79#define MXC_CCM_PDR0_CSI_PRDF_OFFSET 23
80#define MXC_CCM_PDR0_CSI_PRDF_MASK (0x7 << 23)
81#define MXC_CCM_PDR0_PER_PODF_OFFSET 16
82#define MXC_CCM_PDR0_PER_PODF_MASK (0x1F << 16)
83#define MXC_CCM_PDR0_HSP_PODF_OFFSET 11
84#define MXC_CCM_PDR0_HSP_PODF_MASK (0x7 << 11)
85#define MXC_CCM_PDR0_NFC_PODF_OFFSET 8
86#define MXC_CCM_PDR0_NFC_PODF_MASK (0x7 << 8)
87#define MXC_CCM_PDR0_IPG_PODF_OFFSET 6
88#define MXC_CCM_PDR0_IPG_PODF_MASK (0x3 << 6)
89#define MXC_CCM_PDR0_MAX_PODF_OFFSET 3
90#define MXC_CCM_PDR0_MAX_PODF_MASK (0x7 << 3)
91#define MXC_CCM_PDR0_MCU_PODF_OFFSET 0
92#define MXC_CCM_PDR0_MCU_PODF_MASK 0x7
93
94#define MXC_CCM_PDR0_HSP_DIV_1 (0x0 << 11)
95#define MXC_CCM_PDR0_HSP_DIV_2 (0x1 << 11)
96#define MXC_CCM_PDR0_HSP_DIV_3 (0x2 << 11)
97#define MXC_CCM_PDR0_HSP_DIV_4 (0x3 << 11)
98#define MXC_CCM_PDR0_HSP_DIV_5 (0x4 << 11)
99#define MXC_CCM_PDR0_HSP_DIV_6 (0x5 << 11)
100#define MXC_CCM_PDR0_HSP_DIV_7 (0x6 << 11)
101#define MXC_CCM_PDR0_HSP_DIV_8 (0x7 << 11)
102
103#define MXC_CCM_PDR0_IPG_DIV_1 (0x0 << 6)
104#define MXC_CCM_PDR0_IPG_DIV_2 (0x1 << 6)
105#define MXC_CCM_PDR0_IPG_DIV_3 (0x2 << 6)
106#define MXC_CCM_PDR0_IPG_DIV_4 (0x3 << 6)
107
108#define MXC_CCM_PDR0_MAX_DIV_1 (0x0 << 3)
109#define MXC_CCM_PDR0_MAX_DIV_2 (0x1 << 3)
110#define MXC_CCM_PDR0_MAX_DIV_3 (0x2 << 3)
111#define MXC_CCM_PDR0_MAX_DIV_4 (0x3 << 3)
112#define MXC_CCM_PDR0_MAX_DIV_5 (0x4 << 3)
113#define MXC_CCM_PDR0_MAX_DIV_6 (0x5 << 3)
114#define MXC_CCM_PDR0_MAX_DIV_7 (0x6 << 3)
115#define MXC_CCM_PDR0_MAX_DIV_8 (0x7 << 3)
116
117#define MXC_CCM_PDR0_NFC_DIV_1 (0x0 << 8)
118#define MXC_CCM_PDR0_NFC_DIV_2 (0x1 << 8)
119#define MXC_CCM_PDR0_NFC_DIV_3 (0x2 << 8)
120#define MXC_CCM_PDR0_NFC_DIV_4 (0x3 << 8)
121#define MXC_CCM_PDR0_NFC_DIV_5 (0x4 << 8)
122#define MXC_CCM_PDR0_NFC_DIV_6 (0x5 << 8)
123#define MXC_CCM_PDR0_NFC_DIV_7 (0x6 << 8)
124#define MXC_CCM_PDR0_NFC_DIV_8 (0x7 << 8)
125
126#define MXC_CCM_PDR0_MCU_DIV_1 0x0
127#define MXC_CCM_PDR0_MCU_DIV_2 0x1
128#define MXC_CCM_PDR0_MCU_DIV_3 0x2
129#define MXC_CCM_PDR0_MCU_DIV_4 0x3
130#define MXC_CCM_PDR0_MCU_DIV_5 0x4
131#define MXC_CCM_PDR0_MCU_DIV_6 0x5
132#define MXC_CCM_PDR0_MCU_DIV_7 0x6
133#define MXC_CCM_PDR0_MCU_DIV_8 0x7
134
135#define MXC_CCM_PDR1_USB_PRDF_OFFSET 30
136#define MXC_CCM_PDR1_USB_PRDF_MASK (0x3 << 30)
137#define MXC_CCM_PDR1_USB_PODF_OFFSET 27
138#define MXC_CCM_PDR1_USB_PODF_MASK (0x7 << 27)
139#define MXC_CCM_PDR1_FIRI_PRE_PODF_OFFSET 24
140#define MXC_CCM_PDR1_FIRI_PRE_PODF_MASK (0x7 << 24)
141#define MXC_CCM_PDR1_FIRI_PODF_OFFSET 18
142#define MXC_CCM_PDR1_FIRI_PODF_MASK (0x3F << 18)
143#define MXC_CCM_PDR1_SSI2_PRE_PODF_OFFSET 15
144#define MXC_CCM_PDR1_SSI2_PRE_PODF_MASK (0x7 << 15)
145#define MXC_CCM_PDR1_SSI2_PODF_OFFSET 9
146#define MXC_CCM_PDR1_SSI2_PODF_MASK (0x3F << 9)
147#define MXC_CCM_PDR1_SSI1_PRE_PODF_OFFSET 6
148#define MXC_CCM_PDR1_SSI1_PRE_PODF_MASK (0x7 << 6)
149#define MXC_CCM_PDR1_SSI1_PODF_OFFSET 0
150#define MXC_CCM_PDR1_SSI1_PODF_MASK 0x3F
151
152/* Bit definitions for RCSR */
153#define MXC_CCM_RCSR_NF16B 0x80000000
154
155/* Bit definitions for both MCU, USB and SR PLL control registers */
156#define MXC_CCM_PCTL_BRM 0x80000000
157#define MXC_CCM_PCTL_PD_OFFSET 26
158#define MXC_CCM_PCTL_PD_MASK (0xF << 26)
159#define MXC_CCM_PCTL_MFD_OFFSET 16
160#define MXC_CCM_PCTL_MFD_MASK (0x3FF << 16)
161#define MXC_CCM_PCTL_MFI_OFFSET 10
162#define MXC_CCM_PCTL_MFI_MASK (0xF << 10)
163#define MXC_CCM_PCTL_MFN_OFFSET 0
164#define MXC_CCM_PCTL_MFN_MASK 0x3FF
165
166#define MXC_CCM_CGR0_SD_MMC1_OFFSET 0
167#define MXC_CCM_CGR0_SD_MMC1_MASK (0x3 << 0)
168#define MXC_CCM_CGR0_SD_MMC2_OFFSET 2
169#define MXC_CCM_CGR0_SD_MMC2_MASK (0x3 << 2)
170#define MXC_CCM_CGR0_GPT_OFFSET 4
171#define MXC_CCM_CGR0_GPT_MASK (0x3 << 4)
172#define MXC_CCM_CGR0_EPIT1_OFFSET 6
173#define MXC_CCM_CGR0_EPIT1_MASK (0x3 << 6)
174#define MXC_CCM_CGR0_EPIT2_OFFSET 8
175#define MXC_CCM_CGR0_EPIT2_MASK (0x3 << 8)
176#define MXC_CCM_CGR0_IIM_OFFSET 10
177#define MXC_CCM_CGR0_IIM_MASK (0x3 << 10)
178#define MXC_CCM_CGR0_ATA_OFFSET 12
179#define MXC_CCM_CGR0_ATA_MASK (0x3 << 12)
180#define MXC_CCM_CGR0_SDMA_OFFSET 14
181#define MXC_CCM_CGR0_SDMA_MASK (0x3 << 14)
182#define MXC_CCM_CGR0_CSPI3_OFFSET 16
183#define MXC_CCM_CGR0_CSPI3_MASK (0x3 << 16)
184#define MXC_CCM_CGR0_RNG_OFFSET 18
185#define MXC_CCM_CGR0_RNG_MASK (0x3 << 18)
186#define MXC_CCM_CGR0_UART1_OFFSET 20
187#define MXC_CCM_CGR0_UART1_MASK (0x3 << 20)
188#define MXC_CCM_CGR0_UART2_OFFSET 22
189#define MXC_CCM_CGR0_UART2_MASK (0x3 << 22)
190#define MXC_CCM_CGR0_SSI1_OFFSET 24
191#define MXC_CCM_CGR0_SSI1_MASK (0x3 << 24)
192#define MXC_CCM_CGR0_I2C1_OFFSET 26
193#define MXC_CCM_CGR0_I2C1_MASK (0x3 << 26)
194#define MXC_CCM_CGR0_I2C2_OFFSET 28
195#define MXC_CCM_CGR0_I2C2_MASK (0x3 << 28)
196#define MXC_CCM_CGR0_I2C3_OFFSET 30
197#define MXC_CCM_CGR0_I2C3_MASK (0x3 << 30)
198
199#define MXC_CCM_CGR1_HANTRO_OFFSET 0
200#define MXC_CCM_CGR1_HANTRO_MASK (0x3 << 0)
201#define MXC_CCM_CGR1_MEMSTICK1_OFFSET 2
202#define MXC_CCM_CGR1_MEMSTICK1_MASK (0x3 << 2)
203#define MXC_CCM_CGR1_MEMSTICK2_OFFSET 4
204#define MXC_CCM_CGR1_MEMSTICK2_MASK (0x3 << 4)
205#define MXC_CCM_CGR1_CSI_OFFSET 6
206#define MXC_CCM_CGR1_CSI_MASK (0x3 << 6)
207#define MXC_CCM_CGR1_RTC_OFFSET 8
208#define MXC_CCM_CGR1_RTC_MASK (0x3 << 8)
209#define MXC_CCM_CGR1_WDOG_OFFSET 10
210#define MXC_CCM_CGR1_WDOG_MASK (0x3 << 10)
211#define MXC_CCM_CGR1_PWM_OFFSET 12
212#define MXC_CCM_CGR1_PWM_MASK (0x3 << 12)
213#define MXC_CCM_CGR1_SIM_OFFSET 14
214#define MXC_CCM_CGR1_SIM_MASK (0x3 << 14)
215#define MXC_CCM_CGR1_ECT_OFFSET 16
216#define MXC_CCM_CGR1_ECT_MASK (0x3 << 16)
217#define MXC_CCM_CGR1_USBOTG_OFFSET 18
218#define MXC_CCM_CGR1_USBOTG_MASK (0x3 << 18)
219#define MXC_CCM_CGR1_KPP_OFFSET 20
220#define MXC_CCM_CGR1_KPP_MASK (0x3 << 20)
221#define MXC_CCM_CGR1_IPU_OFFSET 22
222#define MXC_CCM_CGR1_IPU_MASK (0x3 << 22)
223#define MXC_CCM_CGR1_UART3_OFFSET 24
224#define MXC_CCM_CGR1_UART3_MASK (0x3 << 24)
225#define MXC_CCM_CGR1_UART4_OFFSET 26
226#define MXC_CCM_CGR1_UART4_MASK (0x3 << 26)
227#define MXC_CCM_CGR1_UART5_OFFSET 28
228#define MXC_CCM_CGR1_UART5_MASK (0x3 << 28)
229#define MXC_CCM_CGR1_OWIRE_OFFSET 30
230#define MXC_CCM_CGR1_OWIRE_MASK (0x3 << 30)
231
232#define MXC_CCM_CGR2_SSI2_OFFSET 0
233#define MXC_CCM_CGR2_SSI2_MASK (0x3 << 0)
234#define MXC_CCM_CGR2_CSPI1_OFFSET 2
235#define MXC_CCM_CGR2_CSPI1_MASK (0x3 << 2)
236#define MXC_CCM_CGR2_CSPI2_OFFSET 4
237#define MXC_CCM_CGR2_CSPI2_MASK (0x3 << 4)
238#define MXC_CCM_CGR2_GACC_OFFSET 6
239#define MXC_CCM_CGR2_GACC_MASK (0x3 << 6)
240#define MXC_CCM_CGR2_EMI_OFFSET 8
241#define MXC_CCM_CGR2_EMI_MASK (0x3 << 8)
242#define MXC_CCM_CGR2_RTIC_OFFSET 10
243#define MXC_CCM_CGR2_RTIC_MASK (0x3 << 10)
244#define MXC_CCM_CGR2_FIRI_OFFSET 12
245#define MXC_CCM_CGR2_FIRI_MASK (0x3 << 12)
246#define MXC_CCM_CGR2_IPMUX1_OFFSET 14
247#define MXC_CCM_CGR2_IPMUX1_MASK (0x3 << 14)
248#define MXC_CCM_CGR2_IPMUX2_OFFSET 16
249#define MXC_CCM_CGR2_IPMUX2_MASK (0x3 << 16)
250
251/* These new CGR2 bits are added in MX32 */
252#define MXC_CCM_CGR2_APMSYSCLKSEL_OFFSET 18
253#define MXC_CCM_CGR2_APMSYSCLKSEL_MASK (0x3 << 18)
254#define MXC_CCM_CGR2_APMSSICLKSEL_OFFSET 20
255#define MXC_CCM_CGR2_APMSSICLKSEL_MASK (0x3 << 20)
256#define MXC_CCM_CGR2_APMPERCLKSEL_OFFSET 22
257#define MXC_CCM_CGR2_APMPERCLKSEL_MASK (0x3 << 22)
258#define MXC_CCM_CGR2_MXCCLKENSEL_OFFSET 24
259#define MXC_CCM_CGR2_MXCCLKENSEL_MASK (0x1 << 24)
260#define MXC_CCM_CGR2_CHIKCAMPEN_OFFSET 25
261#define MXC_CCM_CGR2_CHIKCAMPEN_MASK (0x1 << 25)
262#define MXC_CCM_CGR2_OVRVPUBUSY_OFFSET 26
263#define MXC_CCM_CGR2_OVRVPUBUSY_MASK (0x1 << 26)
264#define MXC_CCM_CGR2_APMENA_OFFSET 30
265#define MXC_CCM_CGR2_AOMENA_MASK (0x1 << 30)
266
267/*
268 * LTR0 register offsets
269 */
270#define MXC_CCM_LTR0_DIV3CK_OFFSET 1
271#define MXC_CCM_LTR0_DIV3CK_MASK (0x3 << 1)
272#define MXC_CCM_LTR0_DNTHR_OFFSET 16
273#define MXC_CCM_LTR0_DNTHR_MASK (0x3F << 16)
274#define MXC_CCM_LTR0_UPTHR_OFFSET 22
275#define MXC_CCM_LTR0_UPTHR_MASK (0x3F << 22)
276
277/*
278 * LTR1 register offsets
279 */
280#define MXC_CCM_LTR1_PNCTHR_OFFSET 0
281#define MXC_CCM_LTR1_PNCTHR_MASK 0x3F
282#define MXC_CCM_LTR1_UPCNT_OFFSET 6
283#define MXC_CCM_LTR1_UPCNT_MASK (0xFF << 6)
284#define MXC_CCM_LTR1_DNCNT_OFFSET 14
285#define MXC_CCM_LTR1_DNCNT_MASK (0xFF << 14)
286#define MXC_CCM_LTR1_LTBRSR_MASK 0x400000
287#define MXC_CCM_LTR1_LTBRSR_OFFSET 22
288#define MXC_CCM_LTR1_LTBRSR 0x400000
289#define MXC_CCM_LTR1_LTBRSH 0x800000
290
291/*
292 * LTR2 bit definitions. x ranges from 0 for WSW9 to 6 for WSW15
293 */
294#define MXC_CCM_LTR2_WSW_OFFSET(x) (11 + (x) * 3)
295#define MXC_CCM_LTR2_WSW_MASK(x) (0x7 << \
296 MXC_CCM_LTR2_WSW_OFFSET((x)))
297#define MXC_CCM_LTR2_EMAC_OFFSET 0
298#define MXC_CCM_LTR2_EMAC_MASK 0x1FF
299
300/*
301 * LTR3 bit definitions. x ranges from 0 for WSW0 to 8 for WSW8
302 */
303#define MXC_CCM_LTR3_WSW_OFFSET(x) (5 + (x) * 3)
304#define MXC_CCM_LTR3_WSW_MASK(x) (0x7 << \
305 MXC_CCM_LTR3_WSW_OFFSET((x)))
306
307#define MXC_CCM_PMCR0_DFSUP1 0x80000000
308#define MXC_CCM_PMCR0_DFSUP1_SPLL (0 << 31)
309#define MXC_CCM_PMCR0_DFSUP1_MPLL (1 << 31)
310#define MXC_CCM_PMCR0_DFSUP0 0x40000000
311#define MXC_CCM_PMCR0_DFSUP0_PLL (0 << 30)
312#define MXC_CCM_PMCR0_DFSUP0_PDR (1 << 30)
313#define MXC_CCM_PMCR0_DFSUP_MASK (0x3 << 30)
314
315#define DVSUP_TURBO 0
316#define DVSUP_HIGH 1
317#define DVSUP_MEDIUM 2
318#define DVSUP_LOW 3
319#define MXC_CCM_PMCR0_DVSUP_TURBO (DVSUP_TURBO << 28)
320#define MXC_CCM_PMCR0_DVSUP_HIGH (DVSUP_HIGH << 28)
321#define MXC_CCM_PMCR0_DVSUP_MEDIUM (DVSUP_MEDIUM << 28)
322#define MXC_CCM_PMCR0_DVSUP_LOW (DVSUP_LOW << 28)
323#define MXC_CCM_PMCR0_DVSUP_OFFSET 28
324#define MXC_CCM_PMCR0_DVSUP_MASK (0x3 << 28)
325#define MXC_CCM_PMCR0_UDSC 0x08000000
326#define MXC_CCM_PMCR0_UDSC_MASK (1 << 27)
327#define MXC_CCM_PMCR0_UDSC_UP (1 << 27)
328#define MXC_CCM_PMCR0_UDSC_DOWN (0 << 27)
329
330#define MXC_CCM_PMCR0_VSCNT_1 (0x0 << 24)
331#define MXC_CCM_PMCR0_VSCNT_2 (0x1 << 24)
332#define MXC_CCM_PMCR0_VSCNT_3 (0x2 << 24)
333#define MXC_CCM_PMCR0_VSCNT_4 (0x3 << 24)
334#define MXC_CCM_PMCR0_VSCNT_5 (0x4 << 24)
335#define MXC_CCM_PMCR0_VSCNT_6 (0x5 << 24)
336#define MXC_CCM_PMCR0_VSCNT_7 (0x6 << 24)
337#define MXC_CCM_PMCR0_VSCNT_8 (0x7 << 24)
338#define MXC_CCM_PMCR0_VSCNT_OFFSET 24
339#define MXC_CCM_PMCR0_VSCNT_MASK (0x7 << 24)
340#define MXC_CCM_PMCR0_DVFEV 0x00800000
341#define MXC_CCM_PMCR0_DVFIS 0x00400000
342#define MXC_CCM_PMCR0_LBMI 0x00200000
343#define MXC_CCM_PMCR0_LBFL 0x00100000
344#define MXC_CCM_PMCR0_LBCF_4 (0x0 << 18)
345#define MXC_CCM_PMCR0_LBCF_8 (0x1 << 18)
346#define MXC_CCM_PMCR0_LBCF_12 (0x2 << 18)
347#define MXC_CCM_PMCR0_LBCF_16 (0x3 << 18)
348#define MXC_CCM_PMCR0_LBCF_OFFSET 18
349#define MXC_CCM_PMCR0_LBCF_MASK (0x3 << 18)
350#define MXC_CCM_PMCR0_PTVIS 0x00020000
351#define MXC_CCM_PMCR0_UPDTEN 0x00010000
352#define MXC_CCM_PMCR0_UPDTEN_MASK (0x1 << 16)
353#define MXC_CCM_PMCR0_FSVAIM 0x00008000
354#define MXC_CCM_PMCR0_FSVAI_OFFSET 13
355#define MXC_CCM_PMCR0_FSVAI_MASK (0x3 << 13)
356#define MXC_CCM_PMCR0_DPVCR 0x00001000
357#define MXC_CCM_PMCR0_DPVV 0x00000800
358#define MXC_CCM_PMCR0_WFIM 0x00000400
359#define MXC_CCM_PMCR0_DRCE3 0x00000200
360#define MXC_CCM_PMCR0_DRCE2 0x00000100
361#define MXC_CCM_PMCR0_DRCE1 0x00000080
362#define MXC_CCM_PMCR0_DRCE0 0x00000040
363#define MXC_CCM_PMCR0_DCR 0x00000020
364#define MXC_CCM_PMCR0_DVFEN 0x00000010
365#define MXC_CCM_PMCR0_PTVAIM 0x00000008
366#define MXC_CCM_PMCR0_PTVAI_OFFSET 1
367#define MXC_CCM_PMCR0_PTVAI_MASK (0x3 << 1)
368#define MXC_CCM_PMCR0_DPTEN 0x00000001
369
370#define MXC_CCM_PMCR1_DVGP_OFFSET 0
371#define MXC_CCM_PMCR1_DVGP_MASK (0xF)
372
373#define MXC_CCM_PMCR1_PLLRDIS (0x1 << 7)
374#define MXC_CCM_PMCR1_EMIRQ_EN (0x1 << 8)
375
376#define MXC_CCM_DCVR_ULV_MASK (0x3FF << 22)
377#define MXC_CCM_DCVR_ULV_OFFSET 22
378#define MXC_CCM_DCVR_LLV_MASK (0x3FF << 12)
379#define MXC_CCM_DCVR_LLV_OFFSET 12
380#define MXC_CCM_DCVR_ELV_MASK (0x3FF << 2)
381#define MXC_CCM_DCVR_ELV_OFFSET 2
382
383#define MXC_CCM_PDR2_MST2_PDF_MASK (0x3F << 7)
384#define MXC_CCM_PDR2_MST2_PDF_OFFSET 7
385#define MXC_CCM_PDR2_MST1_PDF_MASK 0x3F
386#define MXC_CCM_PDR2_MST1_PDF_OFFSET 0
387
388#define MXC_CCM_COSR_CLKOSEL_MASK 0x0F
389#define MXC_CCM_COSR_CLKOSEL_OFFSET 0
390#define MXC_CCM_COSR_CLKOUTDIV_MASK (0x07 << 6)
391#define MXC_CCM_COSR_CLKOUTDIV_OFFSET 6
392#define MXC_CCM_COSR_CLKOEN (1 << 9)
393
394/*
395 * PMCR0 register offsets
396 */
397#define MXC_CCM_PMCR0_LBFL_OFFSET 20
398#define MXC_CCM_PMCR0_DFSUP0_OFFSET 30
399#define MXC_CCM_PMCR0_DFSUP1_OFFSET 31
400
401#endif /* __ARCH_ARM_MACH_MX3_CRM_REGS_H__ */
diff --git a/arch/arm/mach-mx3/devices.c b/arch/arm/mach-mx3/devices.c
new file mode 100644
index 00000000000..5c0320fce5b
--- /dev/null
+++ b/arch/arm/mach-mx3/devices.c
@@ -0,0 +1,180 @@
1/*
2 * Copyright 2006-2007 Freescale Semiconductor, Inc. All Rights Reserved.
3 * Copyright 2008 Sascha Hauer, 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,
17 * Boston, MA 02110-1301, USA.
18 */
19
20#include <linux/module.h>
21#include <linux/platform_device.h>
22#include <linux/serial.h>
23#include <linux/gpio.h>
24#include <asm/hardware.h>
25#include <asm/arch/imx-uart.h>
26
27static struct resource uart0[] = {
28 {
29 .start = UART1_BASE_ADDR,
30 .end = UART1_BASE_ADDR + 0x0B5,
31 .flags = IORESOURCE_MEM,
32 }, {
33 .start = MXC_INT_UART1,
34 .end = MXC_INT_UART1,
35 .flags = IORESOURCE_IRQ,
36 },
37};
38
39static struct platform_device mxc_uart_device0 = {
40 .name = "imx-uart",
41 .id = 0,
42 .resource = uart0,
43 .num_resources = ARRAY_SIZE(uart0),
44};
45
46static struct resource uart1[] = {
47 {
48 .start = UART2_BASE_ADDR,
49 .end = UART2_BASE_ADDR + 0x0B5,
50 .flags = IORESOURCE_MEM,
51 }, {
52 .start = MXC_INT_UART2,
53 .end = MXC_INT_UART2,
54 .flags = IORESOURCE_IRQ,
55 },
56};
57
58static struct platform_device mxc_uart_device1 = {
59 .name = "imx-uart",
60 .id = 1,
61 .resource = uart1,
62 .num_resources = ARRAY_SIZE(uart1),
63};
64
65static struct resource uart2[] = {
66 {
67 .start = UART3_BASE_ADDR,
68 .end = UART3_BASE_ADDR + 0x0B5,
69 .flags = IORESOURCE_MEM,
70 }, {
71 .start = MXC_INT_UART3,
72 .end = MXC_INT_UART3,
73 .flags = IORESOURCE_IRQ,
74 },
75};
76
77static struct platform_device mxc_uart_device2 = {
78 .name = "imx-uart",
79 .id = 2,
80 .resource = uart2,
81 .num_resources = ARRAY_SIZE(uart2),
82};
83
84static struct resource uart3[] = {
85 {
86 .start = UART4_BASE_ADDR,
87 .end = UART4_BASE_ADDR + 0x0B5,
88 .flags = IORESOURCE_MEM,
89 }, {
90 .start = MXC_INT_UART4,
91 .end = MXC_INT_UART4,
92 .flags = IORESOURCE_IRQ,
93 },
94};
95
96static struct platform_device mxc_uart_device3 = {
97 .name = "imx-uart",
98 .id = 3,
99 .resource = uart3,
100 .num_resources = ARRAY_SIZE(uart3),
101};
102
103static struct resource uart4[] = {
104 {
105 .start = UART5_BASE_ADDR,
106 .end = UART5_BASE_ADDR + 0x0B5,
107 .flags = IORESOURCE_MEM,
108 }, {
109 .start = MXC_INT_UART5,
110 .end = MXC_INT_UART5,
111 .flags = IORESOURCE_IRQ,
112 },
113};
114
115static struct platform_device mxc_uart_device4 = {
116 .name = "imx-uart",
117 .id = 4,
118 .resource = uart4,
119 .num_resources = ARRAY_SIZE(uart4),
120};
121
122/*
123 * Register only those UARTs that physically exist
124 */
125int __init imx_init_uart(int uart_no, struct imxuart_platform_data *pdata)
126{
127 switch (uart_no) {
128 case 0:
129 mxc_uart_device0.dev.platform_data = pdata;
130 platform_device_register(&mxc_uart_device0);
131 break;
132 case 1:
133 mxc_uart_device1.dev.platform_data = pdata;
134 platform_device_register(&mxc_uart_device1);
135 break;
136 case 2:
137 mxc_uart_device2.dev.platform_data = pdata;
138 platform_device_register(&mxc_uart_device2);
139 break;
140 case 3:
141 mxc_uart_device3.dev.platform_data = pdata;
142 platform_device_register(&mxc_uart_device3);
143 break;
144 case 4:
145 mxc_uart_device4.dev.platform_data = pdata;
146 platform_device_register(&mxc_uart_device4);
147 break;
148 default:
149 return -ENODEV;
150 }
151
152 return 0;
153}
154
155/* GPIO port description */
156static struct mxc_gpio_port imx_gpio_ports[] = {
157 [0] = {
158 .chip.label = "gpio-0",
159 .base = IO_ADDRESS(GPIO1_BASE_ADDR),
160 .irq = MXC_INT_GPIO1,
161 .virtual_irq_start = MXC_GPIO_INT_BASE
162 },
163 [1] = {
164 .chip.label = "gpio-1",
165 .base = IO_ADDRESS(GPIO2_BASE_ADDR),
166 .irq = MXC_INT_GPIO2,
167 .virtual_irq_start = MXC_GPIO_INT_BASE + GPIO_NUM_PIN
168 },
169 [2] = {
170 .chip.label = "gpio-2",
171 .base = IO_ADDRESS(GPIO3_BASE_ADDR),
172 .irq = MXC_INT_GPIO3,
173 .virtual_irq_start = MXC_GPIO_INT_BASE + GPIO_NUM_PIN * 2
174 }
175};
176
177int __init mxc_register_gpios(void)
178{
179 return mxc_gpio_init(imx_gpio_ports, ARRAY_SIZE(imx_gpio_ports));
180}
diff --git a/arch/arm/mach-mx3/iomux.c b/arch/arm/mach-mx3/iomux.c
new file mode 100644
index 00000000000..adc51feefc1
--- /dev/null
+++ b/arch/arm/mach-mx3/iomux.c
@@ -0,0 +1,111 @@
1/*
2 * Copyright 2004-2006 Freescale Semiconductor, Inc. All Rights Reserved.
3 * Copyright (C) 2008 by Sascha Hauer <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/spinlock.h>
22#include <linux/io.h>
23#include <linux/gpio.h>
24#include <asm/hardware.h>
25#include <asm/arch/gpio.h>
26#include <asm/arch/iomux-mx3.h>
27
28/*
29 * IOMUX register (base) addresses
30 */
31#define IOMUX_BASE IO_ADDRESS(IOMUXC_BASE_ADDR)
32#define IOMUXINT_OBS1 (IOMUX_BASE + 0x000)
33#define IOMUXINT_OBS2 (IOMUX_BASE + 0x004)
34#define IOMUXGPR (IOMUX_BASE + 0x008)
35#define IOMUXSW_MUX_CTL (IOMUX_BASE + 0x00C)
36#define IOMUXSW_PAD_CTL (IOMUX_BASE + 0x154)
37
38static DEFINE_SPINLOCK(gpio_mux_lock);
39
40#define IOMUX_REG_MASK (IOMUX_PADNUM_MASK & ~0x3)
41/*
42 * set the mode for a IOMUX pin.
43 */
44int mxc_iomux_mode(unsigned int pin_mode)
45{
46 u32 reg, field, l, mode, ret = 0;
47
48 reg = IOMUXSW_MUX_CTL + (pin_mode & IOMUX_REG_MASK);
49 field = pin_mode & 0x3;
50 mode = (pin_mode & IOMUX_MODE_MASK) >> IOMUX_MODE_SHIFT;
51
52 pr_debug("%s: reg offset = 0x%x field = %d mode = 0x%02x\n",
53 __func__, (pin_mode & IOMUX_REG_MASK), field, mode);
54
55 spin_lock(&gpio_mux_lock);
56
57 l = __raw_readl(reg);
58 l &= ~(0xff << (field * 8));
59 l |= mode << (field * 8);
60 __raw_writel(l, reg);
61
62 spin_unlock(&gpio_mux_lock);
63
64 return ret;
65}
66EXPORT_SYMBOL(mxc_iomux_mode);
67
68/*
69 * This function configures the pad value for a IOMUX pin.
70 */
71void mxc_iomux_set_pad(enum iomux_pins pin, u32 config)
72{
73 u32 reg, field, l;
74
75 reg = IOMUXSW_PAD_CTL + (pin + 2) / 3;
76 field = (pin + 2) % 3;
77
78 pr_debug("%s: reg offset = 0x%x field = %d\n",
79 __func__, (pin + 2) / 3, field);
80
81 spin_lock(&gpio_mux_lock);
82
83 l = __raw_readl(reg);
84 l &= ~(0x1ff << (field * 9));
85 l |= config << (field * 9);
86 __raw_writel(l, reg);
87
88 spin_unlock(&gpio_mux_lock);
89}
90EXPORT_SYMBOL(mxc_iomux_set_pad);
91
92/*
93 * This function enables/disables the general purpose function for a particular
94 * signal.
95 */
96void mxc_iomux_set_gpr(enum iomux_gp_func gp, bool en)
97{
98 u32 l;
99
100 spin_lock(&gpio_mux_lock);
101 l = __raw_readl(IOMUXGPR);
102 if (en)
103 l |= gp;
104 else
105 l &= ~gp;
106
107 __raw_writel(l, IOMUXGPR);
108 spin_unlock(&gpio_mux_lock);
109}
110EXPORT_SYMBOL(mxc_iomux_set_gpr);
111
diff --git a/arch/arm/mach-mx3/mx31ads.c b/arch/arm/mach-mx3/mx31ads.c
index 7e89bdc23a9..eba3e0cd428 100644
--- a/arch/arm/mach-mx3/mx31ads.c
+++ b/arch/arm/mach-mx3/mx31ads.c
@@ -26,9 +26,11 @@
26#include <asm/hardware.h> 26#include <asm/hardware.h>
27#include <asm/mach-types.h> 27#include <asm/mach-types.h>
28#include <asm/mach/arch.h> 28#include <asm/mach/arch.h>
29#include <asm/mach/time.h>
29#include <asm/memory.h> 30#include <asm/memory.h>
30#include <asm/mach/map.h> 31#include <asm/mach/map.h>
31#include <asm/arch/common.h> 32#include <asm/arch/common.h>
33#include <asm/arch/board-mx31ads.h>
32 34
33/*! 35/*!
34 * @file mx31ads.c 36 * @file mx31ads.c
@@ -126,6 +128,16 @@ static void __init mxc_board_init(void)
126 mxc_init_extuart(); 128 mxc_init_extuart();
127} 129}
128 130
131static void __init mx31ads_timer_init(void)
132{
133 mxc_clocks_init(26000000);
134 mxc_timer_init("ipg_clk.0");
135}
136
137struct sys_timer mx31ads_timer = {
138 .init = mx31ads_timer_init,
139};
140
129/* 141/*
130 * The following uses standard kernel macros defined in arch.h in order to 142 * The following uses standard kernel macros defined in arch.h in order to
131 * initialize __mach_desc_MX31ADS data structure. 143 * initialize __mach_desc_MX31ADS data structure.
@@ -138,5 +150,5 @@ MACHINE_START(MX31ADS, "Freescale MX31ADS")
138 .map_io = mx31ads_map_io, 150 .map_io = mx31ads_map_io,
139 .init_irq = mxc_init_irq, 151 .init_irq = mxc_init_irq,
140 .init_machine = mxc_board_init, 152 .init_machine = mxc_board_init,
141 .timer = &mxc_timer, 153 .timer = &mx31ads_timer,
142MACHINE_END 154MACHINE_END
diff --git a/arch/arm/mach-mx3/mx31lite.c b/arch/arm/mach-mx3/mx31lite.c
new file mode 100644
index 00000000000..1372c1a1fc3
--- /dev/null
+++ b/arch/arm/mach-mx3/mx31lite.c
@@ -0,0 +1,107 @@
1/*
2 * Copyright (C) 2000 Deep Blue Solutions Ltd
3 * Copyright (C) 2002 Shane Nay (shane@minirl.com)
4 * Copyright 2005-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/types.h>
22#include <linux/init.h>
23#include <linux/kernel.h>
24#include <linux/memory.h>
25
26#include <asm/hardware.h>
27#include <asm/mach-types.h>
28#include <asm/mach/arch.h>
29#include <asm/mach/time.h>
30#include <asm/mach/map.h>
31#include <asm/arch/common.h>
32#include <asm/page.h>
33#include <asm/setup.h>
34#include <asm/arch/board-mx31lite.h>
35
36/*
37 * This file contains the board-specific initialization routines.
38 */
39
40/*
41 * This structure defines the MX31 memory map.
42 */
43static struct map_desc mx31lite_io_desc[] __initdata = {
44 {
45 .virtual = AIPS1_BASE_ADDR_VIRT,
46 .pfn = __phys_to_pfn(AIPS1_BASE_ADDR),
47 .length = AIPS1_SIZE,
48 .type = MT_NONSHARED_DEVICE
49 }, {
50 .virtual = SPBA0_BASE_ADDR_VIRT,
51 .pfn = __phys_to_pfn(SPBA0_BASE_ADDR),
52 .length = SPBA0_SIZE,
53 .type = MT_NONSHARED_DEVICE
54 }, {
55 .virtual = AIPS2_BASE_ADDR_VIRT,
56 .pfn = __phys_to_pfn(AIPS2_BASE_ADDR),
57 .length = AIPS2_SIZE,
58 .type = MT_NONSHARED_DEVICE
59 }, {
60 .virtual = CS4_BASE_ADDR_VIRT,
61 .pfn = __phys_to_pfn(CS4_BASE_ADDR),
62 .length = CS4_SIZE,
63 .type = MT_DEVICE
64 }
65};
66
67/*
68 * Set up static virtual mappings.
69 */
70void __init mx31lite_map_io(void)
71{
72 mxc_map_io();
73 iotable_init(mx31lite_io_desc, ARRAY_SIZE(mx31lite_io_desc));
74}
75
76/*
77 * Board specific initialization.
78 */
79static void __init mxc_board_init(void)
80{
81}
82
83static void __init mx31lite_timer_init(void)
84{
85 mxc_clocks_init(26000000);
86 mxc_timer_init("ipg_clk.0");
87}
88
89struct sys_timer mx31lite_timer = {
90 .init = mx31lite_timer_init,
91};
92
93/*
94 * The following uses standard kernel macros defined in arch.h in order to
95 * initialize __mach_desc_MX31LITE data structure.
96 */
97
98MACHINE_START(MX31LITE, "LogicPD MX31 LITEKIT")
99 /* Maintainer: Freescale Semiconductor, Inc. */
100 .phys_io = AIPS1_BASE_ADDR,
101 .io_pg_offst = ((AIPS1_BASE_ADDR_VIRT) >> 18) & 0xfffc,
102 .boot_params = PHYS_OFFSET + 0x100,
103 .map_io = mx31lite_map_io,
104 .init_irq = mxc_init_irq,
105 .init_machine = mxc_board_init,
106 .timer = &mx31lite_timer,
107MACHINE_END
diff --git a/arch/arm/mach-mx3/pcm037.c b/arch/arm/mach-mx3/pcm037.c
new file mode 100644
index 00000000000..a34ae6de266
--- /dev/null
+++ b/arch/arm/mach-mx3/pcm037.c
@@ -0,0 +1,130 @@
1/*
2 * Copyright (C) 2008 Sascha Hauer, 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/types.h>
20#include <linux/init.h>
21
22#include <linux/platform_device.h>
23#include <linux/mtd/physmap.h>
24#include <linux/memory.h>
25
26#include <asm/hardware.h>
27#include <asm/mach-types.h>
28#include <asm/mach/arch.h>
29#include <asm/mach/time.h>
30#include <asm/mach/map.h>
31#include <asm/arch/common.h>
32#include <asm/arch/imx-uart.h>
33#include <asm/arch/iomux-mx3.h>
34#include <asm/arch/board-pcm037.h>
35
36static struct physmap_flash_data pcm037_flash_data = {
37 .width = 2,
38};
39
40static struct resource pcm037_flash_resource = {
41 .start = 0xa0000000,
42 .end = 0xa1ffffff,
43 .flags = IORESOURCE_MEM,
44};
45
46static struct platform_device pcm037_flash = {
47 .name = "physmap-flash",
48 .id = 0,
49 .dev = {
50 .platform_data = &pcm037_flash_data,
51 },
52 .resource = &pcm037_flash_resource,
53 .num_resources = 1,
54};
55
56static struct imxuart_platform_data uart_pdata = {
57 .flags = 0,
58};
59
60static struct platform_device *devices[] __initdata = {
61 &pcm037_flash,
62};
63
64/*
65 * Board specific initialization.
66 */
67static void __init mxc_board_init(void)
68{
69 platform_add_devices(devices, ARRAY_SIZE(devices));
70
71 mxc_iomux_mode(MX31_PIN_CTS1__CTS1);
72 mxc_iomux_mode(MX31_PIN_RTS1__RTS1);
73 mxc_iomux_mode(MX31_PIN_TXD1__TXD1);
74 mxc_iomux_mode(MX31_PIN_RXD1__RXD1);
75
76 imx_init_uart(0, &uart_pdata);
77
78 mxc_iomux_mode(MX31_PIN_CSPI3_MOSI__RXD3);
79 mxc_iomux_mode(MX31_PIN_CSPI3_MISO__TXD3);
80
81 imx_init_uart(2, &uart_pdata);
82}
83
84/*
85 * This structure defines static mappings for the pcm037 board.
86 */
87static struct map_desc pcm037_io_desc[] __initdata = {
88 {
89 .virtual = AIPS1_BASE_ADDR_VIRT,
90 .pfn = __phys_to_pfn(AIPS1_BASE_ADDR),
91 .length = AIPS1_SIZE,
92 .type = MT_DEVICE
93 }, {
94 .virtual = AIPS2_BASE_ADDR_VIRT,
95 .pfn = __phys_to_pfn(AIPS2_BASE_ADDR),
96 .length = AIPS2_SIZE,
97 .type = MT_DEVICE
98 },
99};
100
101/*
102 * Set up static virtual mappings.
103 */
104void __init pcm037_map_io(void)
105{
106 mxc_map_io();
107 iotable_init(pcm037_io_desc, ARRAY_SIZE(pcm037_io_desc));
108}
109
110static void __init pcm037_timer_init(void)
111{
112 mxc_clocks_init(26000000);
113 mxc_timer_init("ipg_clk.0");
114}
115
116struct sys_timer pcm037_timer = {
117 .init = pcm037_timer_init,
118};
119
120MACHINE_START(PCM037, "Phytec Phycore pcm037")
121 /* Maintainer: Pengutronix */
122 .phys_io = AIPS1_BASE_ADDR,
123 .io_pg_offst = ((AIPS1_BASE_ADDR_VIRT) >> 18) & 0xfffc,
124 .boot_params = PHYS_OFFSET + 0x100,
125 .map_io = pcm037_map_io,
126 .init_irq = mxc_init_irq,
127 .init_machine = mxc_board_init,
128 .timer = &pcm037_timer,
129MACHINE_END
130
diff --git a/arch/arm/mach-mx3/time.c b/arch/arm/mach-mx3/time.c
deleted file mode 100644
index fb565c98dbf..00000000000
--- a/arch/arm/mach-mx3/time.c
+++ /dev/null
@@ -1,148 +0,0 @@
1/*
2 * System Timer Interrupt reconfigured to run in free-run mode.
3 * Author: Vitaly Wool
4 * Copyright 2004 MontaVista Software Inc.
5 * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
6 */
7
8/*
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12 */
13
14/*!
15 * @file time.c
16 * @brief This file contains OS tick and wdog timer implementations.
17 *
18 * This file contains OS tick and wdog timer implementations.
19 *
20 * @ingroup Timers
21 */
22
23#include <linux/module.h>
24#include <linux/init.h>
25#include <linux/interrupt.h>
26#include <linux/irq.h>
27#include <asm/hardware.h>
28#include <asm/mach/time.h>
29#include <asm/io.h>
30#include <asm/arch/common.h>
31
32/*!
33 * This is the timer interrupt service routine to do required tasks.
34 * It also services the WDOG timer at the frequency of twice per WDOG
35 * timeout value. For example, if the WDOG's timeout value is 4 (2
36 * seconds since the WDOG runs at 0.5Hz), it will be serviced once
37 * every 2/2=1 second.
38 *
39 * @param irq GPT interrupt source number (not used)
40 * @param dev_id this parameter is not used
41 * @return always returns \b IRQ_HANDLED as defined in
42 * include/linux/interrupt.h.
43 */
44static irqreturn_t mxc_timer_interrupt(int irq, void *dev_id)
45{
46 unsigned int next_match;
47
48 if (__raw_readl(MXC_GPT_GPTSR) & GPTSR_OF1) {
49 do {
50 timer_tick();
51 next_match = __raw_readl(MXC_GPT_GPTOCR1) + LATCH;
52 __raw_writel(GPTSR_OF1, MXC_GPT_GPTSR);
53 __raw_writel(next_match, MXC_GPT_GPTOCR1);
54 } while ((signed long)(next_match -
55 __raw_readl(MXC_GPT_GPTCNT)) <= 0);
56 }
57
58 return IRQ_HANDLED;
59}
60
61/*!
62 * This function is used to obtain the number of microseconds since the last
63 * timer interrupt. Note that interrupts is disabled by do_gettimeofday().
64 *
65 * @return the number of microseconds since the last timer interrupt.
66 */
67static unsigned long mxc_gettimeoffset(void)
68{
69 unsigned long ticks_to_match, elapsed, usec, tick_usec, i;
70
71 /* Get ticks before next timer match */
72 ticks_to_match =
73 __raw_readl(MXC_GPT_GPTOCR1) - __raw_readl(MXC_GPT_GPTCNT);
74
75 /* We need elapsed ticks since last match */
76 elapsed = LATCH - ticks_to_match;
77
78 /* Now convert them to usec */
79 /* Insure no overflow when calculating the usec below */
80 for (i = 1, tick_usec = tick_nsec / 1000;; i *= 2) {
81 tick_usec /= i;
82 if ((0xFFFFFFFF / tick_usec) > elapsed)
83 break;
84 }
85 usec = (unsigned long)(elapsed * tick_usec) / (LATCH / i);
86
87 return usec;
88}
89
90/*!
91 * The OS tick timer interrupt structure.
92 */
93static struct irqaction timer_irq = {
94 .name = "MXC Timer Tick",
95 .flags = IRQF_DISABLED | IRQF_TIMER,
96 .handler = mxc_timer_interrupt
97};
98
99/*!
100 * This function is used to initialize the GPT to produce an interrupt
101 * based on HZ. It is called by start_kernel() during system startup.
102 */
103void __init mxc_init_time(void)
104{
105 u32 reg, v;
106 reg = __raw_readl(MXC_GPT_GPTCR);
107 reg &= ~GPTCR_ENABLE;
108 __raw_writel(reg, MXC_GPT_GPTCR);
109 reg |= GPTCR_SWR;
110 __raw_writel(reg, MXC_GPT_GPTCR);
111
112 while ((__raw_readl(MXC_GPT_GPTCR) & GPTCR_SWR) != 0)
113 cpu_relax();
114
115 reg = GPTCR_FRR | GPTCR_CLKSRC_HIGHFREQ;
116 __raw_writel(reg, MXC_GPT_GPTCR);
117
118 /* TODO: get timer rate from clk driver */
119 v = 66500000;
120
121 __raw_writel((v / CLOCK_TICK_RATE) - 1, MXC_GPT_GPTPR);
122
123 if ((v % CLOCK_TICK_RATE) != 0) {
124 pr_info("\nWARNING: Can't generate CLOCK_TICK_RATE at %d Hz\n",
125 CLOCK_TICK_RATE);
126 }
127 pr_info("Actual CLOCK_TICK_RATE is %d Hz\n",
128 v / ((__raw_readl(MXC_GPT_GPTPR) & 0xFFF) + 1));
129
130 reg = __raw_readl(MXC_GPT_GPTCNT);
131 reg += LATCH;
132 __raw_writel(reg, MXC_GPT_GPTOCR1);
133
134 setup_irq(MXC_INT_GPT, &timer_irq);
135
136 reg = __raw_readl(MXC_GPT_GPTCR);
137 reg =
138 GPTCR_FRR | GPTCR_CLKSRC_HIGHFREQ | GPTCR_STOPEN | GPTCR_DOZEN |
139 GPTCR_WAITEN | GPTCR_ENMOD | GPTCR_ENABLE;
140 __raw_writel(reg, MXC_GPT_GPTCR);
141
142 __raw_writel(GPTIR_OF1IE, MXC_GPT_GPTIR);
143}
144
145struct sys_timer mxc_timer = {
146 .init = mxc_init_time,
147 .offset = mxc_gettimeoffset,
148};