Subject: [@num@/@total@] i.MX2 family: Adding basic mach support
From: Juergen Beisert <j.beisert@pengutronix.de>

This patch adds basic mach support for the mx2 family of procesors.

TODO:
 - Clean arch/arm/mach-mx2/devices.c
 - split into i.MX21/i.MX27 specific parts
 - find regular way to call mxc_cpu_common_init() very early
 - how to include board specific header files everywhere instead in hardware.h
 - how to register only those devices that are really useable at the specific
   board
 - get a sign from freescale for the patch

Signed-off-by: Juergen Beisert <j.beisert@pengutronix.de>

---

 arch/arm/Makefile                   |    1
 arch/arm/mach-mx2/Kconfig           |   20
 arch/arm/mach-mx2/Makefile          |    7
 arch/arm/mach-mx2/Makefile.boot     |    3
 arch/arm/mach-mx2/clock.c           | 1552 ++++++++++++++++++++++++++++++++++++
 arch/arm/mach-mx2/cpu.c             |   99 ++
 arch/arm/mach-mx2/crm_regs.h        |  267 ++++++
 arch/arm/mach-mx2/devices.c         |  600 +++++++++++++
 arch/arm/mach-mx2/devices.h         |   18
 arch/arm/mach-mx2/dma.c             |  499 +++++++++++
 arch/arm/mach-mx2/mm.c              |   56 +
 arch/arm/mach-mx2/serial.c          |  314 +++++++
 arch/arm/mach-mx2/serial.h          |  165 +++
 arch/arm/mach-mx2/system.c          |   55 +
 arch/arm/mach-mx2/time.c            |  205 ++++
 arch/arm/mm/Kconfig                 |    4
 arch/arm/plat-mxc/Kconfig           |    1
 include/asm-arm/arch-mxc/hardware.h |   21
 18 files changed, 3885 insertions(+), 2 deletions(-)

Index: arch/arm/Makefile
===================================================================
--- arch/arm/Makefile.orig
+++ arch/arm/Makefile
@@ -138,6 +138,7 @@ endif
  machine-$(CONFIG_ARCH_DAVINCI)	   := davinci
  machine-$(CONFIG_ARCH_KS8695)     := ks8695
   incdir-$(CONFIG_ARCH_MXC)	   := mxc
+ machine-$(CONFIG_ARCH_MX2)	   := mx2
  machine-$(CONFIG_ARCH_MX3)	   := mx3
  machine-$(CONFIG_ARCH_ORION)	   := orion
  machine-$(CONFIG_ARCH_MSM7X00A)   := msm
Index: arch/arm/mm/Kconfig
===================================================================
--- arch/arm/mm/Kconfig.orig
+++ arch/arm/mm/Kconfig
@@ -171,8 +171,8 @@ config CPU_ARM925T
 # ARM926T
 config CPU_ARM926T
 	bool "Support ARM926T processor"
-	depends on ARCH_INTEGRATOR || ARCH_VERSATILE_PB || MACH_VERSATILE_AB || ARCH_OMAP730 || ARCH_OMAP16XX || MACH_REALVIEW_EB || ARCH_PNX4008 || ARCH_NETX || CPU_S3C2412 || ARCH_AT91SAM9260 || ARCH_AT91SAM9261 || ARCH_AT91SAM9263 || ARCH_AT91SAM9RL || ARCH_AT91CAP9 || ARCH_NS9XXX || ARCH_DAVINCI
-	default y if ARCH_VERSATILE_PB || MACH_VERSATILE_AB || ARCH_OMAP730 || ARCH_OMAP16XX || ARCH_PNX4008 || ARCH_NETX || CPU_S3C2412 || ARCH_AT91SAM9260 || ARCH_AT91SAM9261 || ARCH_AT91SAM9263 || ARCH_AT91SAM9RL || ARCH_AT91CAP9 || ARCH_NS9XXX || ARCH_DAVINCI
+	depends on ARCH_INTEGRATOR || ARCH_VERSATILE_PB || MACH_VERSATILE_AB || ARCH_OMAP730 || ARCH_OMAP16XX || MACH_REALVIEW_EB || ARCH_PNX4008 || ARCH_NETX || CPU_S3C2412 || ARCH_AT91SAM9260 || ARCH_AT91SAM9261 || ARCH_AT91SAM9263 || ARCH_AT91SAM9RL || ARCH_AT91CAP9 || ARCH_NS9XXX || ARCH_DAVINCI || ARCH_MX2
+	default y if ARCH_VERSATILE_PB || MACH_VERSATILE_AB || ARCH_OMAP730 || ARCH_OMAP16XX || ARCH_PNX4008 || ARCH_NETX || CPU_S3C2412 || ARCH_AT91SAM9260 || ARCH_AT91SAM9261 || ARCH_AT91SAM9263 || ARCH_AT91SAM9RL || ARCH_AT91CAP9 || ARCH_NS9XXX || ARCH_DAVINCI || ARCH_MX2
 	select CPU_32v5
 	select CPU_ABRT_EV5TJ
 	select CPU_CACHE_VIVT
Index: arch/arm/mach-mx2/cpu.c
===================================================================
--- /dev/null
+++ arch/arm/mach-mx2/cpu.c
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2007 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+/*
+ * CPU initialization code.
+ */
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <asm/setup.h>
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include "crm_regs.h"
+
+#define SYS_CHIP_VERSION_OFFSET 28
+#define SYS_CHIP_VERSION_MASK   (0xF<<28)
+
+static const u32 system_rev_tbl[SYSTEM_REV_NUM][2] = {
+	/* SREV, own defined ver */
+	{0x00, CHIP_REV_1_0},	/* MX27 TO1 */
+	{0x01, CHIP_REV_2_0},	/* MX27 TO2 */
+};
+
+static int system_rev_updated = 0;
+
+static void __init system_rev_setup(char **p)
+{
+	system_rev = simple_strtoul(*p, NULL, 16);
+	system_rev_updated = 1;
+}
+
+/* system_rev=0x00 for TO1; 0x01 for TO2; etc */
+__early_param("system_rev=", system_rev_setup);
+
+/*
+ * FIXME: i.MX27 TO2 has the private rule to indicate the version of chip
+ * This functions reads the CHIP ID register and returns the system revision
+ * number.
+ */
+static u32 read_system_rev(void)
+{
+	u32 val;
+	u32 i;
+
+	val = __raw_readl(IO_ADDRESS(SYSCTRL_BASE_ADDR) + SYS_CHIP_ID);
+	val = (val & SYS_CHIP_VERSION_MASK) >> SYS_CHIP_VERSION_OFFSET;
+	for (i = 0; i < SYSTEM_REV_NUM; i++) {
+		if (val == system_rev_tbl[i][0]) {
+			return system_rev_tbl[i][1];
+		}
+	}
+	if (i == SYSTEM_REV_NUM) {
+		val = system_rev_tbl[SYSTEM_REV_NUM - 1][1];
+		printk(KERN_ALERT "WARNING: Can't find valid system rev\n");
+		printk(KERN_ALERT "Assuming last known system_rev=0x%x\n", val);
+		return val;
+	}
+	return 0;
+}
+
+/*
+ * Update the system_rev value.
+ * If no system_rev is passed in through the command line, it gets the value
+ * from the IIM module. Otherwise, it uses the pass-in value.
+ */
+static void system_rev_update(void)
+{
+	int i;
+
+	if (!system_rev_updated) {
+		/* means NO value passed-in through command line */
+		system_rev = read_system_rev();
+		pr_info("system_rev is: 0x%x\n", system_rev);
+	} else {
+		pr_info("Command line passed system_rev: 0x%x\n", system_rev);
+		for (i = 0; i < SYSTEM_REV_NUM; i++) {
+			if (system_rev == system_rev_tbl[i][1]) {
+				break;
+			}
+		}
+		/* Reach here only the SREV value unknown. Maybe due to new tapeout? */
+		if (i == SYSTEM_REV_NUM) {
+			panic("Command system_rev is unknown\n");
+		}
+	}
+}
+
+void mxc_cpu_common_init(void)
+{
+	system_rev_update();
+}
Index: arch/arm/mach-mx2/time.c
===================================================================
--- /dev/null
+++ arch/arm/mach-mx2/time.c
@@ -0,0 +1,205 @@
+/*
+ * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/* System Timer Interrupt reconfigured to run in free-run mode.
+ * Author: Vitaly Wool
+ * Copyright 2004 MontaVista Software Inc.
+ */
+
+/*
+ * OS tick implementations.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/clocksource.h>
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/mach/time.h>
+
+#include <asm/arch/hardware.h>
+
+#ifndef __noinstrument
+#define __noinstrument
+#endif
+
+extern unsigned long clk_early_get_timer_rate(void);
+
+/* OS tick defines */
+#define MXC_GPT_INT_TICK		INT_GPT
+#define MXC_GPT_TCMP_TICK		MXC_GPT_TCMP(MXC_TIMER_GPT1)
+#define MXC_GPT_TSTAT_TICK		MXC_GPT_TSTAT(MXC_TIMER_GPT1)
+#define MXC_GPT_TCTL_TICK		MXC_GPT_TCTL(MXC_TIMER_GPT1)
+#define MXC_GPT_TPRER_TICK		MXC_GPT_TPRER(MXC_TIMER_GPT1)
+#define MXC_GPT_TCN_TICK		MXC_GPT_TCN(MXC_TIMER_GPT1)
+/* High resolution timer defines */
+#define MXC_GPT_INT_HRT			INT_GPT2
+#define MXC_GPT_TCMP_HRT		MXC_GPT_TCMP(MXC_TIMER_GPT2)
+#define MXC_GPT_TSTAT_HRT		MXC_GPT_TSTAT(MXC_TIMER_GPT2)
+#define MXC_GPT_TCTL_HRT		MXC_GPT_TCTL(MXC_TIMER_GPT2)
+#define MXC_GPT_TPRER_HRT		MXC_GPT_TPRER(MXC_TIMER_GPT2)
+#define MXC_GPT_TCN_HRT			MXC_GPT_TCN(MXC_TIMER_GPT2)
+
+/* This is the timer interrupt service routine to do required tasks. */
+static irqreturn_t mxc_timer_interrupt(int irq, void *dev_id)
+{
+	unsigned int next_match;
+
+	write_seqlock(&xtime_lock);
+
+	do {
+		timer_tick();
+		next_match = __raw_readl(MXC_GPT_TCMP_TICK) + LATCH;
+		__raw_writel(GPT_TSTAT_COMP, MXC_GPT_TSTAT_TICK);
+		__raw_writel(next_match, MXC_GPT_TCMP_TICK);
+	} while ((signed long)(next_match - __raw_readl(MXC_GPT_TCN_TICK)) <=
+		 0);
+
+	write_sequnlock(&xtime_lock);
+
+	return IRQ_HANDLED;
+}
+
+#ifndef CONFIG_GENERIC_TIME
+/* This function is used to obtain the number of microseconds since the last
+ * timer interrupt. Note that interrupts is disabled by do_gettimeofday(). */
+static unsigned long __noinstrument mxc_gettimeoffset(void)
+{
+	long ticks_to_match, elapsed, usec;
+
+	/* Get ticks before next timer match */
+	ticks_to_match =
+	    __raw_readl(MXC_GPT_TCMP_TICK) - __raw_readl(MXC_GPT_TCN_TICK);
+
+	/* We need elapsed ticks since last match */
+	elapsed = LATCH - ticks_to_match;
+
+	/* Now convert them to usec */
+	usec = (unsigned long)(elapsed * (tick_nsec / 1000)) / LATCH;
+
+	return usec;
+}
+#endif /* CONFIG_GENERIC_TIME */
+
+cycle_t mx27_hrt_get_cycles(void)
+{
+	unsigned long t = __raw_readl(MXC_GPT_TCN_HRT);
+	return t;
+}
+
+static struct clocksource clocksource_mx27_hrt = {
+	.name 		= "mx27_hrt",
+	.rating		= 200,
+	.read		= mx27_hrt_get_cycles,
+	.mask		= CLOCKSOURCE_MASK(32),
+	/*
+	 * Choose a shift value for the denominator that
+	 * will give the lowest error when converting
+	 * the 13.3 MHz clock to nanoseconds.  A value of
+	 * 22 results in an error of about .000317 Hz,
+	 * which is far less than the crystal stability.
+	 */
+	.shift 		= 22,
+	.flags		= CLOCK_SOURCE_IS_CONTINUOUS
+};
+
+static int __init mx27_hrt_clocksource_init(void)
+{
+	int ret;
+	u32 reg, v;
+
+	__raw_writel(0, MXC_GPT_TCTL_HRT);
+	__raw_writel(GPT_TCTL_SWR, MXC_GPT_TCTL_HRT);
+
+	while ((__raw_readl(MXC_GPT_TCTL_HRT) & GPT_TCTL_SWR) != 0) {
+		mb();
+	}
+	__raw_writel(GPT_TCTL_FRR | GPT_TCTL_COMPEN | GPT_TCTL_SRC_PER1,
+		     MXC_GPT_TCTL_HRT);
+
+	v = clk_early_get_timer_rate();
+	__raw_writel((v / CLOCK_TICK_RATE) - 1, MXC_GPT_TPRER_HRT);
+
+	if ((v % CLOCK_TICK_RATE) != 0) {
+		pr_info("\nWARNING1: Can't generate HRT CLOCK_TICK_RATE at %d Hz\n",
+			CLOCK_TICK_RATE);
+	}
+	pr_info("Actual HRT CLOCK_TICK_RATE is %d Hz\n",
+		v / ((__raw_readl(MXC_GPT_TPRER_HRT) & 0x7FF) + 1));
+
+	clocksource_mx27_hrt.mult =
+		clocksource_hz2mult(CLOCK_TICK_RATE,
+				    clocksource_mx27_hrt.shift);
+	ret = clocksource_register(&clocksource_mx27_hrt);
+
+	reg = __raw_readl(MXC_GPT_TCTL_HRT) | GPT_TCTL_TEN;
+	__raw_writel(reg, MXC_GPT_TCTL_HRT);
+
+	return ret;
+}
+
+static struct irqaction timer_irq = {
+	.name = "MXC Timer Tick",
+	.flags = IRQF_DISABLED | IRQF_TIMER,
+	.handler = mxc_timer_interrupt
+};
+
+/*
+ * Used to initialize the GPT to produce an interrupt every 10 msec.
+ * It is called by the start_kernel() during system startup.
+ */
+void __init mxc_init_time(void)
+{
+	u32 reg, v;
+
+	__raw_writel(0, MXC_GPT_TCTL_TICK);
+	__raw_writel(GPT_TCTL_SWR, MXC_GPT_TCTL_TICK);
+
+	while ((__raw_readl(MXC_GPT_TCTL_TICK) & GPT_TCTL_SWR) != 0)
+		mb();
+
+	reg = GPT_TCTL_FRR | GPT_TCTL_COMPEN | GPT_TCTL_SRC_PER1;
+
+	__raw_writel(reg, MXC_GPT_TCTL_TICK);
+
+	v = clk_early_get_timer_rate();
+	__raw_writel((v / CLOCK_TICK_RATE) - 1, MXC_GPT_TPRER_TICK);
+
+	if ((v % CLOCK_TICK_RATE) != 0) {
+		pr_info("\nWARNING: Can't generate CLOCK_TICK_RATE at %d Hz\n",
+			CLOCK_TICK_RATE);
+	}
+	pr_info("Actual CLOCK_TICK_RATE is %d Hz\n",
+		v / ((__raw_readl(MXC_GPT_TPRER_TICK) & 0x7FF) + 1));
+
+	reg = __raw_readl(MXC_GPT_TCN_TICK);
+	reg += LATCH;
+	__raw_writel(reg, MXC_GPT_TCMP_TICK);
+
+	setup_irq(MXC_GPT_INT_TICK, &timer_irq);
+
+	reg = __raw_readl(MXC_GPT_TCTL_TICK) | GPT_TCTL_TEN;
+	__raw_writel(reg, MXC_GPT_TCTL_TICK);
+
+	mx27_hrt_clocksource_init();
+
+}
+
+struct sys_timer mxc_timer = {
+	.init = mxc_init_time,
+#ifndef CONFIG_GENERIC_TIME
+	.offset = mxc_gettimeoffset,
+#endif
+};
Index: arch/arm/mach-mx2/clock.c
===================================================================
--- /dev/null
+++ arch/arm/mach-mx2/clock.c
@@ -0,0 +1,1549 @@
+/*
+ * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/clk.h>
+#include <asm/io.h>
+#include <asm/arch/common.h>
+#include <asm/mach-types.h>
+#include <asm/arch/clock.h>
+#include "crm_regs.h"
+
+#define CKIL_CLK_FREQ           32768	/* 32.768k oscillator in */
+
+static struct clk ckil_clk;
+static struct clk mpll_clk;
+static struct clk mpll_main_clk[];
+static struct clk spll_clk;
+
+static int _clk_enable(struct clk *clk)
+{
+	unsigned long reg;
+
+	reg = __raw_readl(clk->enable_reg);
+	reg |= 1 << clk->enable_shift;
+	__raw_writel(reg, clk->enable_reg);
+
+	return 0;
+}
+
+static void _clk_disable(struct clk *clk)
+{
+	unsigned long reg;
+
+	reg = __raw_readl(clk->enable_reg);
+	reg &= ~(1 << clk->enable_shift);
+	__raw_writel(reg, clk->enable_reg);
+}
+
+static int _clk_spll_enable(struct clk *clk)
+{
+	unsigned long reg;
+
+	reg = __raw_readl(CCM_CSCR);
+	reg |= CCM_CSCR_SPEN;
+	__raw_writel(reg, CCM_CSCR);
+
+	while ((__raw_readl(CCM_SPCTL1) & CCM_SPCTL1_LF) == 0) ;
+
+	return 0;
+}
+
+static void _clk_spll_disable(struct clk *clk)
+{
+	unsigned long reg;
+
+	reg = __raw_readl(CCM_CSCR);
+	reg &= ~CCM_CSCR_SPEN;
+	__raw_writel(reg, CCM_CSCR);
+}
+
+static void _clk_pccr01_enable(unsigned long mask0, unsigned long mask1)
+{
+	unsigned long reg;
+
+	reg = __raw_readl(CCM_PCCR0);
+	reg |= mask0;
+	__raw_writel(reg, CCM_PCCR0);
+
+	reg = __raw_readl(CCM_PCCR1);
+	reg |= mask1;
+	__raw_writel(reg, CCM_PCCR1);
+
+}
+
+static void _clk_pccr01_disable(unsigned long mask0, unsigned long mask1)
+{
+	unsigned long reg;
+
+	reg = __raw_readl(CCM_PCCR0);
+	reg &= ~mask0;
+	__raw_writel(reg, CCM_PCCR0);
+
+	reg = __raw_readl(CCM_PCCR1);
+	reg &= ~mask1;
+	__raw_writel(reg, CCM_PCCR1);
+}
+
+static void _clk_pccr10_enable(unsigned long mask1, unsigned long mask0)
+{
+	unsigned long reg;
+
+	reg = __raw_readl(CCM_PCCR1);
+	reg |= mask1;
+	__raw_writel(reg, CCM_PCCR1);
+
+	reg = __raw_readl(CCM_PCCR0);
+	reg |= mask0;
+	__raw_writel(reg, CCM_PCCR0);
+}
+
+static void _clk_pccr10_disable(unsigned long mask1, unsigned long mask0)
+{
+	unsigned long reg;
+
+	reg = __raw_readl(CCM_PCCR1);
+	reg &= ~mask1;
+	__raw_writel(reg, CCM_PCCR1);
+
+	reg = __raw_readl(CCM_PCCR0);
+	reg &= ~mask0;
+	__raw_writel(reg, CCM_PCCR0);
+}
+
+static int _clk_dma_enable(struct clk *clk)
+{
+	_clk_pccr01_enable(CCM_PCCR0_DMA_MASK, CCM_PCCR1_HCLK_DMA_MASK);
+
+	return 0;
+}
+
+static void _clk_dma_disable(struct clk *clk)
+{
+	_clk_pccr01_disable(CCM_PCCR0_DMA_MASK, CCM_PCCR1_HCLK_DMA_MASK);
+}
+
+static int _clk_rtic_enable(struct clk *clk)
+{
+	_clk_pccr01_enable(CCM_PCCR0_RTIC_MASK, CCM_PCCR1_HCLK_RTIC_MASK);
+
+	return 0;
+}
+
+static void _clk_rtic_disable(struct clk *clk)
+{
+	_clk_pccr01_disable(CCM_PCCR0_RTIC_MASK, CCM_PCCR1_HCLK_RTIC_MASK);
+}
+
+static int _clk_emma_enable(struct clk *clk)
+{
+	_clk_pccr01_enable(CCM_PCCR0_EMMA_MASK, CCM_PCCR1_HCLK_EMMA_MASK);
+
+	return 0;
+}
+
+static void _clk_emma_disable(struct clk *clk)
+{
+	_clk_pccr01_disable(CCM_PCCR0_EMMA_MASK, CCM_PCCR1_HCLK_EMMA_MASK);
+}
+
+static int _clk_slcdc_enable(struct clk *clk)
+{
+	_clk_pccr01_enable(CCM_PCCR0_SLCDC_MASK, CCM_PCCR1_HCLK_SLCDC_MASK);
+
+	return 0;
+}
+
+static void _clk_slcdc_disable(struct clk *clk)
+{
+	_clk_pccr01_disable(CCM_PCCR0_SLCDC_MASK, CCM_PCCR1_HCLK_SLCDC_MASK);
+}
+
+static int _clk_fec_enable(struct clk *clk)
+{
+	_clk_pccr01_enable(CCM_PCCR0_FEC_MASK, CCM_PCCR1_HCLK_FEC_MASK);
+
+	return 0;
+}
+
+static void _clk_fec_disable(struct clk *clk)
+{
+	_clk_pccr01_disable(CCM_PCCR0_FEC_MASK, CCM_PCCR1_HCLK_FEC_MASK);
+}
+
+static int _clk_vpu_enable(struct clk *clk)
+{
+	unsigned long reg;
+
+	reg = __raw_readl(CCM_PCCR1);
+	reg |= CCM_PCCR1_VPU_BAUD_MASK | CCM_PCCR1_HCLK_VPU_MASK;
+	__raw_writel(reg, CCM_PCCR1);
+
+	return 0;
+}
+
+static void _clk_vpu_disable(struct clk *clk)
+{
+	unsigned long reg;
+
+	reg = __raw_readl(CCM_PCCR1);
+	reg &= ~(CCM_PCCR1_VPU_BAUD_MASK | CCM_PCCR1_HCLK_VPU_MASK);
+	__raw_writel(reg, CCM_PCCR1);
+}
+
+static int _clk_sahara2_enable(struct clk *clk)
+{
+	_clk_pccr01_enable(CCM_PCCR0_SAHARA_MASK, CCM_PCCR1_HCLK_SAHARA_MASK);
+
+	return 0;
+}
+
+static void _clk_sahara2_disable(struct clk *clk)
+{
+	_clk_pccr01_disable(CCM_PCCR0_SAHARA_MASK, CCM_PCCR1_HCLK_SAHARA_MASK);
+}
+
+static int _clk_mstick1_enable(struct clk *clk)
+{
+	_clk_pccr10_enable(CCM_PCCR1_MSHC_BAUD_MASK, CCM_PCCR0_MSHC_MASK);
+
+	return 0;
+}
+
+static void _clk_mstick1_disable(struct clk *clk)
+{
+	_clk_pccr10_disable(CCM_PCCR1_MSHC_BAUD_MASK, CCM_PCCR0_MSHC_MASK);
+}
+
+#define CSCR() (__raw_readl(CCM_CSCR))
+#define PCDR0() (__raw_readl(CCM_PCDR0))
+#define PCDR1() (__raw_readl(CCM_PCDR1))
+
+static void _clk_pll_recalc(struct clk *clk)
+{
+	unsigned long mfi = 0, mfn = 0, mfd = 0, pdf = 0;
+	unsigned long ref_clk;
+	unsigned long reg;
+	unsigned long long temp;
+
+	ref_clk = clk->parent->rate;
+	if (clk->parent == &ckil_clk) {
+		ref_clk *= 1024;
+	}
+
+	if (clk == &mpll_clk) {
+		reg = __raw_readl(CCM_MPCTL0);
+		pdf = (reg & CCM_MPCTL0_PD_MASK) >> CCM_MPCTL0_PD_OFFSET;
+		mfd = (reg & CCM_MPCTL0_MFD_MASK) >> CCM_MPCTL0_MFD_OFFSET;
+		mfi = (reg & CCM_MPCTL0_MFI_MASK) >> CCM_MPCTL0_MFI_OFFSET;
+		mfn = (reg & CCM_MPCTL0_MFN_MASK) >> CCM_MPCTL0_MFN_OFFSET;
+	} else if (clk == &spll_clk) {
+		reg = __raw_readl(CCM_SPCTL0);
+		/*TODO: This is TO2 Bug */
+		if (cpu_is_mx27_rev(CHIP_REV_2_0) == 1) {
+			__raw_writel(reg, CCM_SPCTL0);
+		}
+		pdf = (reg & CCM_SPCTL0_PD_MASK) >> CCM_SPCTL0_PD_OFFSET;
+		mfd = (reg & CCM_SPCTL0_MFD_MASK) >> CCM_SPCTL0_MFD_OFFSET;
+		mfi = (reg & CCM_SPCTL0_MFI_MASK) >> CCM_SPCTL0_MFI_OFFSET;
+		mfn = (reg & CCM_SPCTL0_MFN_MASK) >> CCM_SPCTL0_MFN_OFFSET;
+	} else {
+		BUG();		/* oops */
+	}
+
+	mfi = (mfi <= 5) ? 5 : mfi;
+	temp = 2LL * ref_clk * mfn;
+	do_div(temp, mfd + 1);
+	temp = 2LL * ref_clk * mfi + temp;
+	do_div(temp, pdf + 1);
+
+	clk->rate = temp;
+}
+
+static void _clk_mpll_main_recalc(struct clk *clk)
+{
+	/* i.MX27 TO2:
+	 * clk->id == 0: arm clock source path 1 which is from 2*MPLL/DIV_2
+	 * clk->id == 1: arm clock source path 2 which is from 2*MPLL/DIV_3
+	 */
+	switch (clk->id) {
+	case 0:
+		clk->rate = clk->parent->rate;
+		break;
+	case 1:
+		clk->rate = 2 * clk->parent->rate / 3;
+	}
+}
+
+static int _clk_cpu_set_parent(struct clk *clk, struct clk *parent)
+{
+	int cscr = CSCR();
+
+	if (clk->parent == parent)
+		return 0;
+
+	if (cpu_is_mx27_rev(CHIP_REV_2_0) > 0) {
+		if (parent == &mpll_main_clk[0]) {
+			cscr |= CCM_CSCR_ARM_SRC;
+		} else {
+			if (parent == &mpll_main_clk[1]) {
+				cscr &= ~CCM_CSCR_ARM_SRC;
+			} else {
+				return -EINVAL;
+			}
+		}
+		__raw_writel(CCM_CSCR, cscr);
+	} else {
+		return -ENODEV;
+	}
+	clk->parent = parent;
+	return 0;
+}
+
+static unsigned long _clk_cpu_round_rate(struct clk *clk, unsigned long rate)
+{
+	int div;
+	div = clk->parent->rate / rate;
+	if (clk->parent->rate % rate) {
+		div++;
+	}
+
+	if (div > 4) {
+		div = 4;
+	}
+	return clk->parent->rate / div;
+}
+
+static int _clk_cpu_set_rate(struct clk *clk, unsigned long rate)
+{
+	int div, reg;
+	div = clk->parent->rate / rate;
+
+	if (div > 4 || div < 1 || ((clk->parent->rate / div) != rate)) {
+		return -EINVAL;
+	}
+	div--;
+
+	reg = (CSCR() & ~CCM_CSCR_ARM_MASK) | (div << CCM_CSCR_ARM_OFFSET);
+	__raw_writel(CCM_CSCR, reg);
+	clk->rate = rate;
+	return 0;
+}
+
+static void _clk_cpu_recalc(struct clk *clk)
+{
+	unsigned long div;
+
+	if (cpu_is_mx27_rev(CHIP_REV_2_0) > 0) {
+		div = (CSCR() & CCM_CSCR_ARM_MASK) >> CCM_CSCR_ARM_OFFSET;
+	} else {
+		div = (CSCR() & CCM_CSCR_PRESC_MASK) >> CCM_CSCR_PRESC_OFFSET;
+	}
+
+	clk->rate = clk->parent->rate / (div + 1);
+}
+
+static void _clk_ahb_recalc(struct clk *clk)
+{
+	unsigned long bclk_pdf;
+
+	if (cpu_is_mx27_rev(CHIP_REV_2_0) > 0) {
+		bclk_pdf = (CSCR() & CCM_CSCR_AHB_MASK) >> CCM_CSCR_AHB_OFFSET;
+	} else {
+		bclk_pdf =
+		    (CSCR() & CCM_CSCR_BCLK_MASK) >> CCM_CSCR_BCLK_OFFSET;
+	}
+	clk->rate = clk->parent->rate / (bclk_pdf + 1);
+}
+
+static void _clk_perclkx_recalc(struct clk *clk)
+{
+	unsigned long perclk_pdf;
+
+	if (clk->id < 0 || clk->id > 3)
+		return;
+
+	perclk_pdf = (PCDR1() >> (clk->id << 3)) & CCM_PCDR1_PERDIV1_MASK;
+
+	clk->rate = clk->parent->rate / (perclk_pdf + 1);
+}
+
+static unsigned long _clk_perclkx_round_rate(struct clk *clk,
+					     unsigned long rate)
+{
+	u32 div;
+
+	div = clk->parent->rate / rate;
+	if (clk->parent->rate % rate)
+		div++;
+
+	if (div > 64) {
+		div = 64;
+	}
+
+	return clk->parent->rate / div;
+}
+
+static int _clk_perclkx_set_rate(struct clk *clk, unsigned long rate)
+{
+	u32 reg;
+	u32 div;
+
+	if (clk->id < 0 || clk->id > 3)
+		return -EINVAL;
+
+	div = clk->parent->rate / rate;
+	if (div > 64 || div < 1 || ((clk->parent->rate / div) != rate)) {
+		return -EINVAL;
+	}
+	div--;
+
+	reg =
+	    __raw_readl(CCM_PCDR1) & ~(CCM_PCDR1_PERDIV1_MASK <<
+				       (clk->id << 3));
+	reg |= div << (clk->id << 3);
+	__raw_writel(reg, CCM_PCDR1);
+
+	clk->rate = rate;
+
+	return 0;
+}
+
+static void _clk_usb_recalc(struct clk *clk)
+{
+	unsigned long usb_pdf;
+
+	usb_pdf = (CSCR() & CCM_CSCR_USB_MASK) >> CCM_CSCR_USB_OFFSET;
+
+	clk->rate = clk->parent->rate / (usb_pdf + 1);
+}
+
+static void _clk_ssi1_recalc(struct clk *clk)
+{
+	unsigned long ssi1_pdf;
+
+	ssi1_pdf = (PCDR0() & CCM_PCDR0_SSI1BAUDDIV_MASK) >>
+	    CCM_PCDR0_SSI1BAUDDIV_OFFSET;
+
+	if (cpu_is_mx27_rev(CHIP_REV_2_0) > 0) {
+		ssi1_pdf += 4;
+	} else {
+		ssi1_pdf = (ssi1_pdf < 2) ? 124 : ssi1_pdf;
+	}
+
+	clk->rate = 2 * clk->parent->rate / ssi1_pdf;
+}
+
+static void _clk_ssi2_recalc(struct clk *clk)
+{
+	unsigned long ssi2_pdf;
+
+	ssi2_pdf = (PCDR0() & CCM_PCDR0_SSI2BAUDDIV_MASK) >>
+	    CCM_PCDR0_SSI2BAUDDIV_OFFSET;
+
+	if (cpu_is_mx27_rev(CHIP_REV_2_0) > 0) {
+		ssi2_pdf += 4;
+	} else {
+		ssi2_pdf = (ssi2_pdf < 2) ? 124 : ssi2_pdf;
+	}
+
+	clk->rate = 2 * clk->parent->rate / ssi2_pdf;
+}
+
+static void _clk_nfc_recalc(struct clk *clk)
+{
+	unsigned long nfc_pdf;
+
+	if (cpu_is_mx27_rev(CHIP_REV_2_0) > 0) {
+		nfc_pdf =
+		    (PCDR0() & CCM_PCDR0_NFCDIV2_MASK) >>
+		    CCM_PCDR0_NFCDIV2_OFFSET;
+	} else {
+		nfc_pdf =
+		    (PCDR0() & CCM_PCDR0_NFCDIV_MASK) >>
+		    CCM_PCDR0_NFCDIV_OFFSET;
+	}
+
+	clk->rate = clk->parent->rate / (nfc_pdf + 1);
+}
+
+static void _clk_vpu_recalc(struct clk *clk)
+{
+	unsigned long vpu_pdf;
+
+	if (cpu_is_mx27_rev(CHIP_REV_2_0) > 0) {
+		vpu_pdf =
+		    (PCDR0() & CCM_PCDR0_VPUDIV2_MASK) >>
+		    CCM_PCDR0_VPUDIV2_OFFSET;
+		vpu_pdf += 4;
+	} else {
+		vpu_pdf =
+		    (PCDR0() & CCM_PCDR0_VPUDIV_MASK) >>
+		    CCM_PCDR0_VPUDIV_OFFSET;
+		vpu_pdf = (vpu_pdf < 2) ? 124 : vpu_pdf;
+	}
+	clk->rate = 2 * clk->parent->rate / vpu_pdf;
+}
+
+static void _clk_ipg_recalc(struct clk *clk)
+{
+	unsigned long ipg_pdf;
+
+	if (cpu_is_mx27_rev(CHIP_REV_2_0) > 0) {
+		ipg_pdf = 1;
+	} else {
+		ipg_pdf = (CSCR() & CCM_CSCR_IPDIV) >> CCM_CSCR_IPDIV_OFFSET;
+	}
+
+	clk->rate = clk->parent->rate / (ipg_pdf + 1);
+}
+
+static unsigned long _clk_parent_round_rate(struct clk *clk, unsigned long rate)
+{
+	return clk->parent->round_rate(clk->parent, rate);
+}
+
+static int _clk_parent_set_rate(struct clk *clk, unsigned long rate)
+{
+	int ret;
+	if ((ret = clk->parent->set_rate(clk->parent, rate)) == 0)
+		clk->rate = rate;
+	return ret;
+}
+
+static struct clk ckih_clk = {
+	.name = "ckih",
+	.rate = 0,		/* determined at boot time (26 or 27 MHz) */
+	.flags = RATE_PROPAGATES,
+};
+
+static struct clk ckil_clk = {
+	.name = "ckil",
+	.rate = CKIL_CLK_FREQ,
+	.flags = RATE_PROPAGATES,
+};
+
+static struct clk mpll_clk = {
+	.name = "mpll",
+	.parent = &ckih_clk,
+	.recalc = _clk_pll_recalc,
+	.flags = RATE_PROPAGATES,
+};
+
+static struct clk mpll_main_clk[] = {
+	{
+	 /* For i.MX27 TO2, it is the MPLL path 1 of ARM core
+	  * It provide the clock source whose rate is same as MPLL
+	  */
+	 .name = "mpll_main",
+	 .id = 0,
+	 .parent = &mpll_clk,
+	 .recalc = _clk_mpll_main_recalc,},
+	{
+	 /* For i.MX27 TO2, it is the MPLL path 1 of ARM core
+	  * It provide the clock source whose rate is same as MPLL
+	  */
+	 .name = "mpll_main",
+	 .id = 1,
+	 .parent = &mpll_clk,
+	 .recalc = _clk_mpll_main_recalc,}
+};
+
+static struct clk spll_clk = {
+	.name = "spll",
+	.parent = &ckih_clk,
+	.recalc = _clk_pll_recalc,
+	.enable = _clk_spll_enable,
+	.disable = _clk_spll_disable,
+	.flags = RATE_PROPAGATES,
+};
+
+static struct clk cpu_clk = {
+	.name = "cpu_clk",
+	.parent = &mpll_main_clk[1],
+	.set_parent = _clk_cpu_set_parent,
+	.round_rate = _clk_cpu_round_rate,
+	.set_rate = _clk_cpu_set_rate,
+	.recalc = _clk_cpu_recalc,
+	.flags = RATE_PROPAGATES,
+};
+
+static struct clk ahb_clk = {
+	.name = "ahb_clk",
+	.parent = &mpll_main_clk[1],
+	.recalc = _clk_ahb_recalc,
+	.flags = RATE_PROPAGATES,
+};
+
+static struct clk ipg_clk = {
+	.name = "ipg_clk",
+	.parent = &ahb_clk,
+	.recalc = _clk_ipg_recalc,
+	.flags = RATE_PROPAGATES,
+};
+
+static struct clk per_clk[] = {
+	{
+	 .name = "per_clk",
+	 .id = 0,
+	 .parent = &mpll_main_clk[1],
+	 .recalc = _clk_perclkx_recalc,
+	 .enable = _clk_enable,
+	 .enable_reg = CCM_PCCR1,
+	 .enable_shift = CCM_PCCR1_PERCLK1_OFFSET,
+	 .disable = _clk_disable,
+	 .flags = RATE_PROPAGATES,},
+	{
+	 .name = "per_clk",
+	 .id = 1,
+	 .parent = &mpll_main_clk[1],
+	 .recalc = _clk_perclkx_recalc,
+	 .enable = _clk_enable,
+	 .enable_reg = CCM_PCCR1,
+	 .enable_shift = CCM_PCCR1_PERCLK2_OFFSET,
+	 .disable = _clk_disable,
+	 .flags = RATE_PROPAGATES,},
+	{
+	 .name = "per_clk",
+	 .id = 2,
+	 .parent = &mpll_main_clk[1],
+	 .round_rate = _clk_perclkx_round_rate,
+	 .set_rate = _clk_perclkx_set_rate,
+	 .recalc = _clk_perclkx_recalc,
+	 .enable = _clk_enable,
+	 .enable_reg = CCM_PCCR1,
+	 .enable_shift = CCM_PCCR1_PERCLK3_OFFSET,
+	 .disable = _clk_disable,
+	 .flags = RATE_PROPAGATES,},
+	{
+	 .name = "per_clk",
+	 .id = 3,
+	 .parent = &mpll_main_clk[1],
+	 .round_rate = _clk_perclkx_round_rate,
+	 .set_rate = _clk_perclkx_set_rate,
+	 .recalc = _clk_perclkx_recalc,
+	 .enable = _clk_enable,
+	 .enable_reg = CCM_PCCR1,
+	 .enable_shift = CCM_PCCR1_PERCLK4_OFFSET,
+	 .disable = _clk_disable,
+	 .flags = RATE_PROPAGATES,},
+};
+
+struct clk uart1_clk[] = {
+	{
+	 .name = "uart_clk",
+	 .id = 0,
+	 .parent = &per_clk[0],
+	 .secondary = &uart1_clk[1],},
+	{
+	 .name = "uart_ipg_clk",
+	 .id = 0,
+	 .parent = &ipg_clk,
+	 .enable = _clk_enable,
+	 .enable_reg = CCM_PCCR1,
+	 .enable_shift = CCM_PCCR1_UART1_OFFSET,
+	 .disable = _clk_disable,},
+};
+
+struct clk uart2_clk[] = {
+	{
+	 .name = "uart_clk",
+	 .id = 1,
+	 .parent = &per_clk[0],
+	 .secondary = &uart2_clk[1],},
+	{
+	 .name = "uart_ipg_clk",
+	 .id = 1,
+	 .parent = &ipg_clk,
+	 .enable = _clk_enable,
+	 .enable_reg = CCM_PCCR1,
+	 .enable_shift = CCM_PCCR1_UART2_OFFSET,
+	 .disable = _clk_disable,},
+};
+
+struct clk uart3_clk[] = {
+	{
+	 .name = "uart_clk",
+	 .id = 2,
+	 .parent = &per_clk[0],
+	 .secondary = &uart3_clk[1],},
+	{
+	 .name = "uart_ipg_clk",
+	 .id = 2,
+	 .parent = &ipg_clk,
+	 .enable = _clk_enable,
+	 .enable_reg = CCM_PCCR1,
+	 .enable_shift = CCM_PCCR1_UART3_OFFSET,
+	 .disable = _clk_disable,},
+};
+
+struct clk uart4_clk[] = {
+	{
+	 .name = "uart_clk",
+	 .id = 3,
+	 .parent = &per_clk[0],
+	 .secondary = &uart4_clk[1],},
+	{
+	 .name = "uart_ipg_clk",
+	 .id = 3,
+	 .parent = &ipg_clk,
+	 .enable = _clk_enable,
+	 .enable_reg = CCM_PCCR1,
+	 .enable_shift = CCM_PCCR1_UART4_OFFSET,
+	 .disable = _clk_disable,},
+};
+
+struct clk uart5_clk[] = {
+	{
+	 .name = "uart_clk",
+	 .id = 4,
+	 .parent = &per_clk[0],
+	 .secondary = &uart5_clk[1],},
+	{
+	 .name = "uart_ipg_clk",
+	 .id = 4,
+	 .parent = &ipg_clk,
+	 .enable = _clk_enable,
+	 .enable_reg = CCM_PCCR1,
+	 .enable_shift = CCM_PCCR1_UART5_OFFSET,
+	 .disable = _clk_disable,},
+};
+
+struct clk uart6_clk[] = {
+	{
+	 .name = "uart_clk",
+	 .id = 5,
+	 .parent = &per_clk[0],
+	 .secondary = &uart6_clk[1],},
+	{
+	 .name = "uart_ipg_clk",
+	 .id = 5,
+	 .parent = &ipg_clk,
+	 .enable = _clk_enable,
+	 .enable_reg = CCM_PCCR1,
+	 .enable_shift = CCM_PCCR1_UART6_OFFSET,
+	 .disable = _clk_disable,},
+};
+
+static struct clk gpt1_clk[] = {
+	{
+	 .name = "gpt_clk",
+	 .id = 0,
+	 .parent = &per_clk[0],
+	 .secondary = &gpt1_clk[1],},
+	{
+	 .name = "gpt_ipg_clk",
+	 .id = 0,
+	 .parent = &ipg_clk,
+	 .enable = _clk_enable,
+	 .enable_reg = CCM_PCCR0,
+	 .enable_shift = CCM_PCCR0_GPT1_OFFSET,
+	 .disable = _clk_disable,},
+};
+
+static struct clk gpt2_clk[] = {
+	{
+	 .name = "gpt_clk",
+	 .id = 1,
+	 .parent = &per_clk[0],
+	 .secondary = &gpt2_clk[1],},
+	{
+	 .name = "gpt_ipg_clk",
+	 .id = 1,
+	 .parent = &ipg_clk,
+	 .enable = _clk_enable,
+	 .enable_reg = CCM_PCCR0,
+	 .enable_shift = CCM_PCCR0_GPT2_OFFSET,
+	 .disable = _clk_disable,},
+};
+
+static struct clk gpt3_clk[] = {
+	{
+	 .name = "gpt_clk",
+	 .id = 2,
+	 .parent = &per_clk[0],
+	 .secondary = &gpt3_clk[1],},
+	{
+	 .name = "gpt_ipg_clk",
+	 .id = 2,
+	 .parent = &ipg_clk,
+	 .enable = _clk_enable,
+	 .enable_reg = CCM_PCCR0,
+	 .enable_shift = CCM_PCCR0_GPT3_OFFSET,
+	 .disable = _clk_disable,},
+};
+
+static struct clk gpt4_clk[] = {
+	{
+	 .name = "gpt_clk",
+	 .id = 3,
+	 .parent = &per_clk[0],
+	 .secondary = &gpt4_clk[1],},
+	{
+	 .name = "gpt_ipg_clk",
+	 .id = 3,
+	 .parent = &ipg_clk,
+	 .enable = _clk_enable,
+	 .enable_reg = CCM_PCCR0,
+	 .enable_shift = CCM_PCCR0_GPT4_OFFSET,
+	 .disable = _clk_disable,},
+};
+
+static struct clk gpt5_clk[] = {
+	{
+	 .name = "gpt_clk",
+	 .id = 4,
+	 .parent = &per_clk[0],
+	 .secondary = &gpt5_clk[1],},
+	{
+	 .name = "gpt_ipg_clk",
+	 .id = 4,
+	 .parent = &ipg_clk,
+	 .enable = _clk_enable,
+	 .enable_reg = CCM_PCCR0,
+	 .enable_shift = CCM_PCCR0_GPT5_OFFSET,
+	 .disable = _clk_disable,},
+};
+
+static struct clk gpt6_clk[] = {
+	{
+	 .name = "gpt_clk",
+	 .id = 5,
+	 .parent = &per_clk[0],
+	 .secondary = &gpt6_clk[1],},
+	{
+	 .name = "gpt_ipg_clk",
+	 .id = 5,
+	 .parent = &ipg_clk,
+	 .enable = _clk_enable,
+	 .enable_reg = CCM_PCCR0,
+	 .enable_shift = CCM_PCCR0_GPT6_OFFSET,
+	 .disable = _clk_disable,},
+};
+
+static struct clk pwm_clk[] = {
+	{
+	 .name = "pwm_clk",
+	 .parent = &per_clk[0],
+	 .secondary = &pwm_clk[1],},
+	{
+	 .name = "pwm_clk",
+	 .parent = &ipg_clk,
+	 .enable = _clk_enable,
+	 .enable_reg = CCM_PCCR0,
+	 .enable_shift = CCM_PCCR0_PWM_OFFSET,
+	 .disable = _clk_disable,},
+};
+
+static struct clk sdhc1_clk[] = {
+	{
+	 .name = "sdhc_clk",
+	 .id = 0,
+	 .parent = &per_clk[1],
+	 .secondary = &sdhc1_clk[1],},
+	{
+	 .name = "sdhc_ipg_clk",
+	 .id = 0,
+	 .parent = &ipg_clk,
+	 .enable = _clk_enable,
+	 .enable_reg = CCM_PCCR0,
+	 .enable_shift = CCM_PCCR0_SDHC1_OFFSET,
+	 .disable = _clk_disable,},
+};
+
+static struct clk sdhc2_clk[] = {
+	{
+	 .name = "sdhc_clk",
+	 .id = 1,
+	 .parent = &per_clk[1],
+	 .secondary = &sdhc2_clk[1],},
+	{
+	 .name = "sdhc_ipg_clk",
+	 .id = 1,
+	 .parent = &ipg_clk,
+	 .enable = _clk_enable,
+	 .enable_reg = CCM_PCCR0,
+	 .enable_shift = CCM_PCCR0_SDHC2_OFFSET,
+	 .disable = _clk_disable,},
+};
+
+static struct clk sdhc3_clk[] = {
+	{
+	 .name = "sdhc_clk",
+	 .id = 2,
+	 .parent = &per_clk[1],
+	 .secondary = &sdhc3_clk[1],},
+	{
+	 .name = "sdhc_ipg_clk",
+	 .id = 2,
+	 .parent = &ipg_clk,
+	 .enable = _clk_enable,
+	 .enable_reg = CCM_PCCR0,
+	 .enable_shift = CCM_PCCR0_SDHC3_OFFSET,
+	 .disable = _clk_disable,},
+};
+
+static struct clk cspi1_clk[] = {
+	{
+	 .name = "cspi_clk",
+	 .id = 0,
+	 .parent = &per_clk[1],
+	 .secondary = &cspi1_clk[1],},
+	{
+	 .name = "cspi_ipg_clk",
+	 .id = 0,
+	 .parent = &ipg_clk,
+	 .enable = _clk_enable,
+	 .enable_reg = CCM_PCCR0,
+	 .enable_shift = CCM_PCCR0_CSPI1_OFFSET,
+	 .disable = _clk_disable,},
+};
+
+static struct clk cspi2_clk[] = {
+	{
+	 .name = "cspi_clk",
+	 .id = 1,
+	 .parent = &per_clk[1],
+	 .secondary = &cspi2_clk[1],},
+	{
+	 .name = "cspi_ipg_clk",
+	 .id = 1,
+	 .parent = &ipg_clk,
+	 .enable = _clk_enable,
+	 .enable_reg = CCM_PCCR0,
+	 .enable_shift = CCM_PCCR0_CSPI2_OFFSET,
+	 .disable = _clk_disable,},
+};
+
+static struct clk cspi3_clk[] = {
+	{
+	 .name = "cspi_clk",
+	 .id = 2,
+	 .parent = &per_clk[1],
+	 .secondary = &cspi3_clk[1],},
+	{
+	 .name = "cspi_ipg_clk",
+	 .id = 2,
+	 .parent = &ipg_clk,
+	 .enable = _clk_enable,
+	 .enable_reg = CCM_PCCR0,
+	 .enable_shift = CCM_PCCR0_CSPI3_OFFSET,
+	 .disable = _clk_disable,},
+};
+
+static struct clk lcdc_clk[] = {
+	{
+	 .name = "lcdc_clk",
+	 .parent = &per_clk[2],
+	 .secondary = &lcdc_clk[1],
+	 .round_rate = _clk_parent_round_rate,
+	 .set_rate = _clk_parent_set_rate,},
+	{
+	 .name = "lcdc_ipg_clk",
+	 .parent = &ipg_clk,
+	 .secondary = &lcdc_clk[2],
+	 .enable = _clk_enable,
+	 .enable_reg = CCM_PCCR0,
+	 .enable_shift = CCM_PCCR0_LCDC_OFFSET,
+	 .disable = _clk_disable,},
+	{
+	 .name = "lcdc_ahb_clk",
+	 .parent = &ahb_clk,
+	 .enable = _clk_enable,
+	 .enable_reg = CCM_PCCR1,
+	 .enable_shift = CCM_PCCR1_HCLK_LCDC_OFFSET,
+	 .disable = _clk_disable,},
+};
+
+static struct clk csi_clk[] = {
+	{
+	 .name = "csi_perclk",
+	 .parent = &per_clk[3],
+	 .secondary = &csi_clk[1],
+	 .round_rate = _clk_parent_round_rate,
+	 .set_rate = _clk_parent_set_rate,},
+	{
+	 .name = "csi_ahb_clk",
+	 .parent = &ahb_clk,
+	 .enable = _clk_enable,
+	 .enable_reg = CCM_PCCR1,
+	 .enable_shift = CCM_PCCR1_HCLK_CSI_OFFSET,
+	 .disable = _clk_disable,},
+};
+
+static struct clk usb_clk[] = {
+	{
+	 .name = "usb_clk",
+	 .parent = &spll_clk,
+	 .recalc = _clk_usb_recalc,
+	 .enable = _clk_enable,
+	 .enable_reg = CCM_PCCR1,
+	 .enable_shift = CCM_PCCR1_USBOTG_OFFSET,
+	 .disable = _clk_disable,},
+	{
+	 .name = "usb_ahb_clk",
+	 .parent = &ahb_clk,
+	 .enable = _clk_enable,
+	 .enable_reg = CCM_PCCR1,
+	 .enable_shift = CCM_PCCR1_HCLK_USBOTG_OFFSET,
+	 .disable = _clk_disable,}
+};
+
+static struct clk ssi1_clk[] = {
+	{
+	 .name = "ssi_clk",
+	 .id = 0,
+	 .parent = &mpll_main_clk[1],
+	 .secondary = &ssi1_clk[1],
+	 .recalc = _clk_ssi1_recalc,
+	 .enable = _clk_enable,
+	 .enable_reg = CCM_PCCR1,
+	 .enable_shift = CCM_PCCR1_SSI1_BAUD_OFFSET,
+	 .disable = _clk_disable,},
+	{
+	 .name = "ssi_ipg_clk",
+	 .id = 0,
+	 .parent = &ipg_clk,
+	 .enable = _clk_enable,
+	 .enable_reg = CCM_PCCR0,
+	 .enable_shift = CCM_PCCR0_SSI1_IPG_OFFSET,
+	 .disable = _clk_disable,},
+};
+
+static struct clk ssi2_clk[] = {
+	{
+	 .name = "ssi_clk",
+	 .id = 1,
+	 .parent = &mpll_main_clk[1],
+	 .secondary = &ssi2_clk[1],
+	 .recalc = _clk_ssi2_recalc,
+	 .enable = _clk_enable,
+	 .enable_reg = CCM_PCCR1,
+	 .enable_shift = CCM_PCCR1_SSI2_BAUD_OFFSET,
+	 .disable = _clk_disable,},
+	{
+	 .name = "ssi_ipg_clk",
+	 .id = 1,
+	 .parent = &ipg_clk,
+	 .enable = _clk_enable,
+	 .enable_reg = CCM_PCCR0,
+	 .enable_shift = CCM_PCCR0_SSI2_IPG_OFFSET,
+	 .disable = _clk_disable,},
+};
+
+static struct clk nfc_clk = {
+	.name = "nfc_clk",
+	.parent = &cpu_clk,
+	.recalc = _clk_nfc_recalc,
+	.enable = _clk_enable,
+	.enable_reg = CCM_PCCR1,
+	.enable_shift = CCM_PCCR1_NFC_BAUD_OFFSET,
+	.disable = _clk_disable,
+};
+
+static struct clk vpu_clk = {
+	.name = "vpu_clk",
+	.parent = &mpll_main_clk[1],
+	.recalc = _clk_vpu_recalc,
+	.enable = _clk_vpu_enable,
+	.disable = _clk_vpu_disable,
+};
+
+static struct clk dma_clk = {
+	.name = "dma_clk",
+	.parent = &ahb_clk,
+	.enable = _clk_dma_enable,
+	.disable = _clk_dma_disable,
+};
+
+static struct clk rtic_clk = {
+	.name = "rtic_clk",
+	.parent = &ahb_clk,
+	.enable = _clk_rtic_enable,
+	.disable = _clk_rtic_disable,
+};
+
+static struct clk brom_clk = {
+	.name = "brom_clk",
+	.parent = &ahb_clk,
+	.enable = _clk_enable,
+	.enable_reg = CCM_PCCR1,
+	.enable_shift = CCM_PCCR1_HCLK_BROM_OFFSET,
+	.disable = _clk_disable,
+};
+
+static struct clk emma_clk = {
+	.name = "emma_clk",
+	.parent = &ahb_clk,
+	.enable = _clk_emma_enable,
+	.disable = _clk_emma_disable,
+};
+
+static struct clk slcdc_clk = {
+	.name = "slcdc_clk",
+	.parent = &ahb_clk,
+	.enable = _clk_slcdc_enable,
+	.disable = _clk_slcdc_disable,
+};
+
+static struct clk fec_clk = {
+	.name = "fec_clk",
+	.parent = &ahb_clk,
+	.enable = _clk_fec_enable,
+	.disable = _clk_fec_disable,
+};
+
+static struct clk emi_clk = {
+	.name = "emi_clk",
+	.parent = &ahb_clk,
+	.enable = _clk_enable,
+	.enable_reg = CCM_PCCR1,
+	.enable_shift = CCM_PCCR1_HCLK_EMI_OFFSET,
+	.disable = _clk_disable,
+};
+
+static struct clk sahara2_clk = {
+	.name = "sahara_clk",
+	.parent = &ahb_clk,
+	.enable = _clk_sahara2_enable,
+	.disable = _clk_sahara2_disable,
+};
+
+static struct clk ata_clk = {
+	.name = "ata_clk",
+	.parent = &ahb_clk,
+	.enable = _clk_enable,
+	.enable_reg = CCM_PCCR1,
+	.enable_shift = CCM_PCCR1_HCLK_ATA_OFFSET,
+	.disable = _clk_disable,
+};
+
+static struct clk mstick1_clk = {
+	.name = "mstick1_clk",
+	.parent = &ipg_clk,
+	.enable = _clk_mstick1_enable,
+	.disable = _clk_mstick1_disable,
+};
+
+static struct clk wdog_clk = {
+	.name = "wdog_clk",
+	.parent = &ipg_clk,
+	.enable = _clk_enable,
+	.enable_reg = CCM_PCCR1,
+	.enable_shift = CCM_PCCR1_WDT_OFFSET,
+	.disable = _clk_disable,
+};
+
+static struct clk gpio_clk = {
+	.name = "gpio_clk",
+	.parent = &ipg_clk,
+	.enable = _clk_enable,
+	.enable_reg = CCM_PCCR1,
+	.enable_shift = CCM_PCCR0_GPIO_OFFSET,
+	.disable = _clk_disable,
+};
+
+static struct clk i2c_clk[] = {
+	{
+	 .name = "i2c_clk",
+	 .id = 0,
+	 .parent = &ipg_clk,
+	 .enable = _clk_enable,
+	 .enable_reg = CCM_PCCR0,
+	 .enable_shift = CCM_PCCR0_I2C1_OFFSET,
+	 .disable = _clk_disable,},
+	{
+	 .name = "i2c_clk",
+	 .id = 1,
+	 .parent = &ipg_clk,
+	 .enable = _clk_enable,
+	 .enable_reg = CCM_PCCR0,
+	 .enable_shift = CCM_PCCR0_I2C2_OFFSET,
+	 .disable = _clk_disable,},
+};
+
+static struct clk iim_clk = {
+	.name = "iim_clk",
+	.parent = &ipg_clk,
+	.enable = _clk_enable,
+	.enable_reg = CCM_PCCR0,
+	.enable_shift = CCM_PCCR0_IIM_OFFSET,
+	.disable = _clk_disable,
+};
+
+static struct clk kpp_clk = {
+	.name = "kpp_clk",
+	.parent = &ipg_clk,
+	.enable = _clk_enable,
+	.enable_reg = CCM_PCCR0,
+	.enable_shift = CCM_PCCR0_KPP_OFFSET,
+	.disable = _clk_disable,
+};
+
+static struct clk owire_clk = {
+	.name = "owire_clk",
+	.parent = &ipg_clk,
+	.enable = _clk_enable,
+	.enable_reg = CCM_PCCR0,
+	.enable_shift = CCM_PCCR0_OWIRE_OFFSET,
+	.disable = _clk_disable,
+};
+
+static struct clk rtc_clk = {
+	.name = "rtc_clk",
+	.parent = &ipg_clk,
+	.enable = _clk_enable,
+	.enable_reg = CCM_PCCR0,
+	.enable_shift = CCM_PCCR0_RTC_OFFSET,
+	.disable = _clk_disable,
+};
+
+static struct clk scc_clk = {
+	.name = "scc_clk",
+	.parent = &ipg_clk,
+	.enable = _clk_enable,
+	.enable_reg = CCM_PCCR0,
+	.enable_shift = CCM_PCCR0_SCC_OFFSET,
+	.disable = _clk_disable,
+};
+
+static unsigned long _clk_clko_round_rate(struct clk *clk, unsigned long rate)
+{
+	u32 div;
+
+	div = clk->parent->rate / rate;
+	if (clk->parent->rate % rate)
+		div++;
+
+	if (div > 8) {
+		div = 8;
+	}
+
+	return clk->parent->rate / div;
+}
+
+static int _clk_clko_set_rate(struct clk *clk, unsigned long rate)
+{
+	u32 reg;
+	u32 div;
+
+	div = clk->parent->rate / rate;
+
+	if (div > 8 || div < 1 || ((clk->parent->rate / div) != rate)) {
+		return -EINVAL;
+	}
+	div--;
+
+	reg = __raw_readl(CCM_PCDR0) & ~CCM_PCDR0_CLKODIV_MASK;
+	reg |= div << CCM_PCDR0_CLKODIV_OFFSET;
+	__raw_writel(reg, CCM_PCDR0);
+
+	clk->rate = rate;
+
+	return 0;
+}
+
+static void _clk_clko_recalc(struct clk *clk)
+{
+	u32 div;
+
+	div = __raw_readl(CCM_PCDR0) & CCM_PCDR0_CLKODIV_MASK >>
+	    CCM_PCDR0_CLKODIV_OFFSET;
+	div++;
+
+	clk->rate = clk->parent->rate / div;
+}
+
+static int _clk_clko_set_parent(struct clk *clk, struct clk *parent)
+{
+	u32 reg;
+
+	reg = __raw_readl(CCM_CCSR) & ~CCM_CCSR_CLKOSEL_MASK;
+
+	if (parent == &ckil_clk) {
+		reg |= 0 << CCM_CCSR_CLKOSEL_OFFSET;
+	} else if (parent == &ckih_clk) {
+		reg |= 2 << CCM_CCSR_CLKOSEL_OFFSET;
+	} else if (parent == mpll_clk.parent) {
+		reg |= 3 << CCM_CCSR_CLKOSEL_OFFSET;
+	} else if (parent == spll_clk.parent) {
+		reg |= 4 << CCM_CCSR_CLKOSEL_OFFSET;
+	} else if (parent == &mpll_clk) {
+		reg |= 5 << CCM_CCSR_CLKOSEL_OFFSET;
+	} else if (parent == &spll_clk) {
+		reg |= 6 << CCM_CCSR_CLKOSEL_OFFSET;
+	} else if (parent == &cpu_clk) {
+		reg |= 7 << CCM_CCSR_CLKOSEL_OFFSET;
+	} else if (parent == &ahb_clk) {
+		reg |= 8 << CCM_CCSR_CLKOSEL_OFFSET;
+	} else if (parent == &ipg_clk) {
+		reg |= 9 << CCM_CCSR_CLKOSEL_OFFSET;
+	} else if (parent == &per_clk[0]) {
+		reg |= 0xA << CCM_CCSR_CLKOSEL_OFFSET;
+	} else if (parent == &per_clk[1]) {
+		reg |= 0xB << CCM_CCSR_CLKOSEL_OFFSET;
+	} else if (parent == &per_clk[2]) {
+		reg |= 0xC << CCM_CCSR_CLKOSEL_OFFSET;
+	} else if (parent == &per_clk[3]) {
+		reg |= 0xD << CCM_CCSR_CLKOSEL_OFFSET;
+	} else if (parent == &ssi1_clk[0]) {
+		reg |= 0xE << CCM_CCSR_CLKOSEL_OFFSET;
+	} else if (parent == &ssi2_clk[0]) {
+		reg |= 0xF << CCM_CCSR_CLKOSEL_OFFSET;
+	} else if (parent == &nfc_clk) {
+		reg |= 0x10 << CCM_CCSR_CLKOSEL_OFFSET;
+	} else if (parent == &mstick1_clk) {
+		reg |= 0x11 << CCM_CCSR_CLKOSEL_OFFSET;
+	} else if (parent == &vpu_clk) {
+		reg |= 0x12 << CCM_CCSR_CLKOSEL_OFFSET;
+	} else if (parent == &usb_clk[0]) {
+		reg |= 0x15 << CCM_CCSR_CLKOSEL_OFFSET;
+	} else {
+		return -EINVAL;
+	}
+
+	__raw_writel(reg, CCM_CCSR);
+
+	return 0;
+}
+
+static int _clk_clko_enable(struct clk *clk)
+{
+	u32 reg;
+
+	reg = __raw_readl(CCM_PCDR0) | CCM_PCDR0_CLKO_EN;
+	__raw_writel(reg, CCM_PCDR0);
+
+	return 0;
+}
+
+static void _clk_clko_disable(struct clk *clk)
+{
+	u32 reg;
+
+	reg = __raw_readl(CCM_PCDR0) & ~CCM_PCDR0_CLKO_EN;
+	__raw_writel(reg, CCM_PCDR0);
+}
+
+static struct clk clko_clk = {
+	.name = "clko_clk",
+	.recalc = _clk_clko_recalc,
+	.set_rate = _clk_clko_set_rate,
+	.round_rate = _clk_clko_round_rate,
+	.set_parent = _clk_clko_set_parent,
+	.enable = _clk_clko_enable,
+	.disable = _clk_clko_disable,
+};
+
+static struct clk *mxc_clks[] = {
+	&ckih_clk,
+	&ckil_clk,
+	&mpll_clk,
+	&mpll_main_clk[0],
+	&mpll_main_clk[1],
+	&spll_clk,
+	&cpu_clk,
+	&ahb_clk,
+	&ipg_clk,
+	&per_clk[0],
+	&per_clk[1],
+	&per_clk[2],
+	&per_clk[3],
+	&clko_clk,
+	&uart1_clk[0],
+	&uart1_clk[1],
+	&uart2_clk[0],
+	&uart2_clk[1],
+	&uart3_clk[0],
+	&uart3_clk[1],
+	&uart4_clk[0],
+	&uart4_clk[1],
+	&uart5_clk[0],
+	&uart5_clk[1],
+	&uart6_clk[0],
+	&uart6_clk[1],
+	&gpt1_clk[0],
+	&gpt1_clk[1],
+	&gpt2_clk[0],
+	&gpt2_clk[1],
+	&gpt3_clk[0],
+	&gpt3_clk[1],
+	&gpt4_clk[0],
+	&gpt4_clk[1],
+	&gpt5_clk[0],
+	&gpt5_clk[1],
+	&gpt6_clk[0],
+	&gpt6_clk[1],
+	&pwm_clk[0],
+	&pwm_clk[1],
+	&sdhc1_clk[0],
+	&sdhc1_clk[1],
+	&sdhc2_clk[0],
+	&sdhc2_clk[1],
+	&sdhc3_clk[0],
+	&sdhc3_clk[1],
+	&cspi1_clk[0],
+	&cspi1_clk[1],
+	&cspi2_clk[0],
+	&cspi2_clk[1],
+	&cspi3_clk[0],
+	&cspi3_clk[1],
+	&lcdc_clk[0],
+	&lcdc_clk[1],
+	&lcdc_clk[2],
+	&csi_clk[0],
+	&csi_clk[1],
+	&usb_clk[0],
+	&usb_clk[1],
+	&ssi1_clk[0],
+	&ssi1_clk[1],
+	&ssi2_clk[0],
+	&ssi2_clk[1],
+	&nfc_clk,
+	&vpu_clk,
+	&dma_clk,
+	&rtic_clk,
+	&brom_clk,
+	&emma_clk,
+	&slcdc_clk,
+	&fec_clk,
+	&emi_clk,
+	&sahara2_clk,
+	&ata_clk,
+	&mstick1_clk,
+	&wdog_clk,
+	&gpio_clk,
+	&i2c_clk[0],
+	&i2c_clk[1],
+	&iim_clk,
+	&kpp_clk,
+	&owire_clk,
+	&rtc_clk,
+	&scc_clk,
+};
+
+static void probe_mxc_clocks(void)
+{
+	int i;
+
+	if (cpu_is_mx27_rev(CHIP_REV_2_0) > 0) {
+		if (CSCR() & 0x8000) {
+			cpu_clk.parent = &mpll_main_clk[0];
+		}
+
+		if (!(CSCR() & 0x00800000)) {
+			ssi2_clk[0].parent = &spll_clk;
+		}
+
+		if (!(CSCR() & 0x00400000)) {
+			ssi1_clk[0].parent = &spll_clk;
+		}
+
+		if (!(CSCR() & 0x00200000)) {
+			vpu_clk.parent = &spll_clk;
+		}
+	} else {
+		cpu_clk.parent = &mpll_clk;
+		cpu_clk.set_parent = NULL;
+		cpu_clk.round_rate = NULL;
+		cpu_clk.set_rate = NULL;
+		ahb_clk.parent = &mpll_clk;
+
+		for (i = 0; i < sizeof(per_clk) / sizeof(per_clk[0]); i++) {
+			per_clk[i].parent = &mpll_clk;
+		}
+
+		ssi1_clk[0].parent = &mpll_clk;
+		ssi2_clk[0].parent = &mpll_clk;
+
+		vpu_clk.parent = &mpll_clk;
+	}
+}
+
+/*
+ * Get timer clock rate early in boot process before clock tree is
+ * initialized.
+ */
+unsigned long __init clk_early_get_timer_rate(void)
+{
+	mxc_cpu_common_init();	/* FIXME Seems more like a hack alert */
+
+	if (CSCR() & CCM_CSCR_MCU) {
+		mpll_clk.parent = &ckih_clk;
+	} else {
+		mpll_clk.parent = &ckil_clk;
+	}
+
+	/* Determine which high frequency clock source is coming in */
+	ckih_clk.rate = board_get_ckih_rate();
+
+	probe_mxc_clocks();
+	mpll_clk.recalc(&mpll_clk);
+	if (cpu_is_mx27_rev(CHIP_REV_2_0) > 0) {
+		mpll_main_clk[0].recalc(&mpll_main_clk[0]);
+		mpll_main_clk[1].recalc(&mpll_main_clk[1]);
+	}
+	per_clk[0].recalc(&per_clk[0]);
+	per_clk[0].enable(&per_clk[0]);
+	gpt1_clk[1].enable(&gpt1_clk[1]);
+	return per_clk[0].rate;
+}
+
+extern void propagate_rate(struct clk *tclk);
+
+int __init mxc_clocks_init(void)
+{
+	u32 cscr;
+	struct clk **clkp;
+
+	for (clkp = mxc_clks; clkp < mxc_clks + ARRAY_SIZE(mxc_clks); clkp++) {
+		if (*clkp == &mpll_main_clk[0] || *clkp == &mpll_main_clk[1]) {
+			if (cpu_is_mx27_rev(CHIP_REV_1_0) == 1)
+				continue;
+		}
+		clk_register(*clkp);
+	}
+
+	/* Turn off all possible clocks */
+	__raw_writel(CCM_PCCR0_GPT1_MASK, CCM_PCCR0);
+	__raw_writel(CCM_PCCR1_PERCLK1_MASK | CCM_PCCR1_HCLK_EMI_MASK,
+		     CCM_PCCR1);
+	spll_clk.disable(&spll_clk);
+
+	cscr = CSCR();
+	if (cscr & CCM_CSCR_MCU) {
+		mpll_clk.parent = &ckih_clk;
+	} else {
+		mpll_clk.parent = &ckil_clk;
+	}
+
+	if (cscr & CCM_CSCR_SP) {
+		spll_clk.parent = &ckih_clk;
+	} else {
+		spll_clk.parent = &ckil_clk;
+	}
+
+	pr_info("Clock input source is %ld\n", ckih_clk.rate);
+
+	/* This will propagate to all children and init all the clock rates */
+	propagate_rate(&ckih_clk);
+	propagate_rate(&ckil_clk);
+
+	clk_enable(&emi_clk);
+	clk_enable(&gpio_clk);
+	clk_enable(&iim_clk);
+	clk_enable(&gpt1_clk[0]);
+
+	return 0;
+}
Index: arch/arm/mach-mx2/crm_regs.h
===================================================================
--- /dev/null
+++ arch/arm/mach-mx2/crm_regs.h
@@ -0,0 +1,267 @@
+/*
+ * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#ifndef __ARCH_ARM_MACH_MX2_CRM_REGS_H__
+#define __ARCH_ARM_MACH_MX2_CRM_REGS_H__
+
+#include <asm/arch/hardware.h>
+
+/* Register offsets */
+#define CCM_CSCR                (IO_ADDRESS(CCM_BASE_ADDR) + 0x0)
+#define CCM_MPCTL0              (IO_ADDRESS(CCM_BASE_ADDR) + 0x4)
+#define CCM_MPCTL1              (IO_ADDRESS(CCM_BASE_ADDR) + 0x8)
+#define CCM_SPCTL0              (IO_ADDRESS(CCM_BASE_ADDR) + 0xC)
+#define CCM_SPCTL1              (IO_ADDRESS(CCM_BASE_ADDR) + 0x10)
+#define CCM_OSC26MCTL           (IO_ADDRESS(CCM_BASE_ADDR) + 0x14)
+#define CCM_PCDR0               (IO_ADDRESS(CCM_BASE_ADDR) + 0x18)
+#define CCM_PCDR1               (IO_ADDRESS(CCM_BASE_ADDR) + 0x1c)
+#define CCM_PCCR0               (IO_ADDRESS(CCM_BASE_ADDR) + 0x20)
+#define CCM_PCCR1               (IO_ADDRESS(CCM_BASE_ADDR) + 0x24)
+#define CCM_CCSR                (IO_ADDRESS(CCM_BASE_ADDR) + 0x28)
+#define CCM_PMCTL               (IO_ADDRESS(CCM_BASE_ADDR) + 0x2c)
+#define CCM_PMCOUNT             (IO_ADDRESS(CCM_BASE_ADDR) + 0x30)
+#define CCM_WKGDCTL             (IO_ADDRESS(CCM_BASE_ADDR) + 0x34)
+
+#define CCM_CSCR_USB_OFFSET     28
+#define CCM_CSCR_USB_MASK       (0x7 << 28)
+#define CCM_CSCR_SD_OFFSET      24
+#define CCM_CSCR_SD_MASK        (0x3 << 24)
+#define CCM_CSCR_SSI2           (1 << 23)
+#define CCM_CSCR_SSI2_OFFSET    23
+#define CCM_CSCR_SSI1           (1 << 22)
+#define CCM_CSCR_SSI1_OFFSET    22
+#define CCM_CSCR_VPU           (1 << 21)
+#define CCM_CSCR_VPU_OFFSET    21
+#define CCM_CSCR_MSHC           (1 << 20)
+#define CCM_CSCR_SPLLRES        (1 << 19)
+#define CCM_CSCR_MPLLRES        (1 << 18)
+#define CCM_CSCR_SP             (1 << 17)
+#define CCM_CSCR_MCU            (1 << 16)
+/* CCM_CSCR_ARM_xxx just be avaliable on i.MX27 TO2*/
+#define CCM_CSCR_ARM_SRC        (1 << 15)
+#define CCM_CSCR_ARM_OFFSET     12
+#define CCM_CSCR_ARM_MASK       (0x3 << 12)
+/* CCM_CSCR_ARM_xxx just be avaliable on i.MX27 TO2*/
+#define CCM_CSCR_PRESC_OFFSET   13
+#define CCM_CSCR_PRESC_MASK     (0x7 << 13)
+#define CCM_CSCR_BCLK_OFFSET    9
+#define CCM_CSCR_BCLK_MASK      (0xf << 9)
+#define CCM_CSCR_IPDIV_OFFSET   8
+#define CCM_CSCR_IPDIV          (1 << 8)
+/* CCM_CSCR_AHB_xxx just be avaliable on i.MX27 TO2*/
+#define CCM_CSCR_AHB_OFFSET     8
+#define CCM_CSCR_AHB_MASK       (0x3 << 8)
+/* CCM_CSCR_AHB_xxx just be avaliable on i.MX27 TO2*/
+#define CCM_CSCR_OSC26MDIV      (1 << 4)
+#define CCM_CSCR_OSC26M         (1 << 3)
+#define CCM_CSCR_FPM            (1 << 2)
+#define CCM_CSCR_SPEN           (1 << 1)
+#define CCM_CSCR_MPEN           1
+
+#define CCM_MPCTL0_CPLM         (1 << 31)
+#define CCM_MPCTL0_PD_OFFSET    26
+#define CCM_MPCTL0_PD_MASK      (0xf << 26)
+#define CCM_MPCTL0_MFD_OFFSET   16
+#define CCM_MPCTL0_MFD_MASK     (0x3ff << 16)
+#define CCM_MPCTL0_MFI_OFFSET   10
+#define CCM_MPCTL0_MFI_MASK     (0xf << 10)
+#define CCM_MPCTL0_MFN_OFFSET   0
+#define CCM_MPCTL0_MFN_MASK     0x3ff
+
+#define CCM_MPCTL1_LF           (1 << 15)
+#define CCM_MPCTL1_BRMO         (1 << 6)
+
+#define CCM_SPCTL0_CPLM         (1 << 31)
+#define CCM_SPCTL0_PD_OFFSET    26
+#define CCM_SPCTL0_PD_MASK      (0xf << 26)
+#define CCM_SPCTL0_MFD_OFFSET   16
+#define CCM_SPCTL0_MFD_MASK     (0x3ff << 16)
+#define CCM_SPCTL0_MFI_OFFSET   10
+#define CCM_SPCTL0_MFI_MASK     (0xf << 10)
+#define CCM_SPCTL0_MFN_OFFSET   0
+#define CCM_SPCTL0_MFN_MASK     0x3ff
+
+#define CCM_SPCTL1_LF           (1 << 15)
+#define CCM_SPCTL1_BRMO         (1 << 6)
+
+#define CCM_OSC26MCTL_PEAK_OFFSET       16
+#define CCM_OSC26MCTL_PEAK_MASK         (0x3 << 16)
+#define CCM_OSC26MCTL_AGC_OFFSET        8
+#define CCM_OSC26MCTL_AGC_MASK          (0x3f << 8)
+#define CCM_OSC26MCTL_ANATEST_OFFSET    0
+#define CCM_OSC26MCTL_ANATEST_MASK      0x3f
+
+#define CCM_PCDR0_SSI2BAUDDIV_OFFSET    26
+#define CCM_PCDR0_SSI2BAUDDIV_MASK      (0x3f << 26)
+#define CCM_PCDR0_CLKO_EN               25
+#define CCM_PCDR0_CLKODIV_OFFSET        22
+#define CCM_PCDR0_CLKODIV_MASK          (0x7 << 22)
+#define CCM_PCDR0_SSI1BAUDDIV_OFFSET    16
+#define CCM_PCDR0_SSI1BAUDDIV_MASK      (0x3f << 16)
+/*The difinition for i.MX27 TO2*/
+#define CCM_PCDR0_VPUDIV2_OFFSET        10
+#define CCM_PCDR0_VPUDIV2_MASK          (0x3f << 10)
+#define CCM_PCDR0_NFCDIV2_OFFSET         6
+#define CCM_PCDR0_NFCDIV2_MASK           (0xf << 6)
+#define CCM_PCDR0_MSHCDIV2_MASK          0x3f
+/*The difinition for i.MX27 TO2*/
+#define CCM_PCDR0_NFCDIV_OFFSET         12
+#define CCM_PCDR0_NFCDIV_MASK           (0xf << 12)
+#define CCM_PCDR0_VPUDIV_OFFSET        8
+#define CCM_PCDR0_VPUDIV_MASK          (0xf << 8)
+#define CCM_PCDR0_MSHCDIV_OFFSET        0
+#define CCM_PCDR0_MSHCDIV_MASK          0x1f
+
+#define CCM_PCDR1_PERDIV4_OFFSET        24
+#define CCM_PCDR1_PERDIV4_MASK          (0x3f << 24)
+#define CCM_PCDR1_PERDIV3_OFFSET        16
+#define CCM_PCDR1_PERDIV3_MASK          (0x3f << 16)
+#define CCM_PCDR1_PERDIV2_OFFSET        8
+#define CCM_PCDR1_PERDIV2_MASK          (0x3f << 8)
+#define CCM_PCDR1_PERDIV1_OFFSET        0
+#define CCM_PCDR1_PERDIV1_MASK          0x3f
+
+#define CCM_PCCR0_CSPI1_OFFSET          31
+#define CCM_PCCR0_CSPI1_MASK            (1 << 31)
+#define CCM_PCCR0_CSPI2_OFFSET          30
+#define CCM_PCCR0_CSPI2_MASK            (1 << 30)
+#define CCM_PCCR0_CSPI3_OFFSET          29
+#define CCM_PCCR0_CSPI3_MASK            (1 << 29)
+#define CCM_PCCR0_DMA_OFFSET            28
+#define CCM_PCCR0_DMA_MASK              (1 << 28)
+#define CCM_PCCR0_EMMA_OFFSET           27
+#define CCM_PCCR0_EMMA_MASK             (1 << 27)
+#define CCM_PCCR0_FEC_OFFSET            26
+#define CCM_PCCR0_FEC_MASK              (1 << 26)
+#define CCM_PCCR0_GPIO_OFFSET           25
+#define CCM_PCCR0_GPIO_MASK             (1 << 25)
+#define CCM_PCCR0_GPT1_OFFSET           24
+#define CCM_PCCR0_GPT1_MASK             (1 << 24)
+#define CCM_PCCR0_GPT2_OFFSET           23
+#define CCM_PCCR0_GPT2_MASK             (1 << 23)
+#define CCM_PCCR0_GPT3_OFFSET           22
+#define CCM_PCCR0_GPT3_MASK             (1 << 22)
+#define CCM_PCCR0_GPT4_OFFSET           21
+#define CCM_PCCR0_GPT4_MASK             (1 << 21)
+#define CCM_PCCR0_GPT5_OFFSET           20
+#define CCM_PCCR0_GPT5_MASK             (1 << 20)
+#define CCM_PCCR0_GPT6_OFFSET           19
+#define CCM_PCCR0_GPT6_MASK             (1 << 19)
+#define CCM_PCCR0_I2C1_OFFSET           18
+#define CCM_PCCR0_I2C1_MASK             (1 << 18)
+#define CCM_PCCR0_I2C2_OFFSET           17
+#define CCM_PCCR0_I2C2_MASK             (1 << 17)
+#define CCM_PCCR0_IIM_OFFSET            16
+#define CCM_PCCR0_IIM_MASK              (1 << 16)
+#define CCM_PCCR0_KPP_OFFSET            15
+#define CCM_PCCR0_KPP_MASK              (1 << 15)
+#define CCM_PCCR0_LCDC_OFFSET           14
+#define CCM_PCCR0_LCDC_MASK             (1 << 14)
+#define CCM_PCCR0_MSHC_OFFSET           13
+#define CCM_PCCR0_MSHC_MASK             (1 << 13)
+#define CCM_PCCR0_OWIRE_OFFSET          12
+#define CCM_PCCR0_OWIRE_MASK            (1 << 12)
+#define CCM_PCCR0_PWM_OFFSET            11
+#define CCM_PCCR0_PWM_MASK              (1 << 11)
+#define CCM_PCCR0_RTC_OFFSET            9
+#define CCM_PCCR0_RTC_MASK              (1 << 9)
+#define CCM_PCCR0_RTIC_OFFSET           8
+#define CCM_PCCR0_RTIC_MASK             (1 << 8)
+#define CCM_PCCR0_SAHARA_OFFSET         7
+#define CCM_PCCR0_SAHARA_MASK           (1 << 7)
+#define CCM_PCCR0_SCC_OFFSET            6
+#define CCM_PCCR0_SCC_MASK              (1 << 6)
+#define CCM_PCCR0_SDHC1_OFFSET          5
+#define CCM_PCCR0_SDHC1_MASK            (1 << 5)
+#define CCM_PCCR0_SDHC2_OFFSET          4
+#define CCM_PCCR0_SDHC2_MASK            (1 << 4)
+#define CCM_PCCR0_SDHC3_OFFSET          3
+#define CCM_PCCR0_SDHC3_MASK            (1 << 3)
+#define CCM_PCCR0_SLCDC_OFFSET          2
+#define CCM_PCCR0_SLCDC_MASK            (1 << 2)
+#define CCM_PCCR0_SSI1_IPG_OFFSET       1
+#define CCM_PCCR0_SSI1_IPG_MASK         (1 << 1)
+#define CCM_PCCR0_SSI2_IPG_OFFSET       0
+#define CCM_PCCR0_SSI2_IPG_MASK         (1 << 0)
+
+#define CCM_PCCR1_UART1_OFFSET          31
+#define CCM_PCCR1_UART1_MASK            (1 << 31)
+#define CCM_PCCR1_UART2_OFFSET          30
+#define CCM_PCCR1_UART2_MASK            (1 << 30)
+#define CCM_PCCR1_UART3_OFFSET          29
+#define CCM_PCCR1_UART3_MASK            (1 << 29)
+#define CCM_PCCR1_UART4_OFFSET          28
+#define CCM_PCCR1_UART4_MASK            (1 << 28)
+#define CCM_PCCR1_UART5_OFFSET          27
+#define CCM_PCCR1_UART5_MASK            (1 << 27)
+#define CCM_PCCR1_UART6_OFFSET          26
+#define CCM_PCCR1_UART6_MASK            (1 << 26)
+#define CCM_PCCR1_USBOTG_OFFSET         25
+#define CCM_PCCR1_USBOTG_MASK           (1 << 25)
+#define CCM_PCCR1_WDT_OFFSET            24
+#define CCM_PCCR1_WDT_MASK              (1 << 24)
+#define CCM_PCCR1_HCLK_ATA_OFFSET       23
+#define CCM_PCCR1_HCLK_ATA_MASK         (1 << 23)
+#define CCM_PCCR1_HCLK_BROM_OFFSET      22
+#define CCM_PCCR1_HCLK_BROM_MASK        (1 << 22)
+#define CCM_PCCR1_HCLK_CSI_OFFSET       21
+#define CCM_PCCR1_HCLK_CSI_MASK         (1 << 21)
+#define CCM_PCCR1_HCLK_DMA_OFFSET       20
+#define CCM_PCCR1_HCLK_DMA_MASK         (1 << 20)
+#define CCM_PCCR1_HCLK_EMI_OFFSET       19
+#define CCM_PCCR1_HCLK_EMI_MASK         (1 << 19)
+#define CCM_PCCR1_HCLK_EMMA_OFFSET      18
+#define CCM_PCCR1_HCLK_EMMA_MASK        (1 << 18)
+#define CCM_PCCR1_HCLK_FEC_OFFSET       17
+#define CCM_PCCR1_HCLK_FEC_MASK         (1 << 17)
+#define CCM_PCCR1_HCLK_VPU_OFFSET       16
+#define CCM_PCCR1_HCLK_VPU_MASK         (1 << 16)
+#define CCM_PCCR1_HCLK_LCDC_OFFSET      15
+#define CCM_PCCR1_HCLK_LCDC_MASK        (1 << 15)
+#define CCM_PCCR1_HCLK_RTIC_OFFSET      14
+#define CCM_PCCR1_HCLK_RTIC_MASK        (1 << 14)
+#define CCM_PCCR1_HCLK_SAHARA_OFFSET    13
+#define CCM_PCCR1_HCLK_SAHARA_MASK      (1 << 13)
+#define CCM_PCCR1_HCLK_SLCDC_OFFSET     12
+#define CCM_PCCR1_HCLK_SLCDC_MASK       (1 << 12)
+#define CCM_PCCR1_HCLK_USBOTG_OFFSET    11
+#define CCM_PCCR1_HCLK_USBOTG_MASK      (1 << 11)
+#define CCM_PCCR1_PERCLK1_OFFSET        10
+#define CCM_PCCR1_PERCLK1_MASK          (1 << 10)
+#define CCM_PCCR1_PERCLK2_OFFSET        9
+#define CCM_PCCR1_PERCLK2_MASK          (1 << 9)
+#define CCM_PCCR1_PERCLK3_OFFSET        8
+#define CCM_PCCR1_PERCLK3_MASK          (1 << 8)
+#define CCM_PCCR1_PERCLK4_OFFSET        7
+#define CCM_PCCR1_PERCLK4_MASK          (1 << 7)
+#define CCM_PCCR1_VPU_BAUD_OFFSET       6
+#define CCM_PCCR1_VPU_BAUD_MASK         (1 << 6)
+#define CCM_PCCR1_SSI1_BAUD_OFFSET      5
+#define CCM_PCCR1_SSI1_BAUD_MASK        (1 << 5)
+#define CCM_PCCR1_SSI2_BAUD_OFFSET      4
+#define CCM_PCCR1_SSI2_BAUD_MASK        (1 << 4)
+#define CCM_PCCR1_NFC_BAUD_OFFSET       3
+#define CCM_PCCR1_NFC_BAUD_MASK         (1 << 3)
+#define CCM_PCCR1_MSHC_BAUD_OFFSET      2
+#define CCM_PCCR1_MSHC_BAUD_MASK        (1 << 2)
+
+#define CCM_CCSR_32KSR          (1 << 15)
+#define CCM_CCSR_CLKMODE1       (1 << 9)
+#define CCM_CCSR_CLKMODE0       (1 << 8)
+#define CCM_CCSR_CLKOSEL_OFFSET 0
+#define CCM_CCSR_CLKOSEL_MASK   0x1f
+
+#define SYS_FMCR                0x14	/*  Functional Muxing Control Reg */
+#define SYS_CHIP_ID             0x00	/* The offset of CHIP ID register */
+
+#endif /* __ARCH_ARM_MACH_MX2_CRM_REGS_H__ */
Index: arch/arm/mach-mx2/dma.c
===================================================================
--- /dev/null
+++ arch/arm/mach-mx2/dma.c
@@ -0,0 +1,499 @@
+/*
+ * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/*
+ * platform dependend DMA parameter
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <asm/dma.h>
+
+#define MXC_SOUND_PLAYBACK_CHAIN_DMA 1
+#define MXC_SOUND_CAPTURE_CHAIN_DMA 1
+
+/* the structure stored device_id and dma_info pointer */
+typedef struct dma_info_entry_s {
+	mxc_dma_device_t device;
+	/* if there are two dma_info , first is for reading, another is for writing */
+	mx2_dma_info_t *info;
+} dma_info_entry_t;
+
+/* dma_info from memory to memory for dma testing */
+static mx2_dma_info_t ram2ram_dma_info = {
+	.dma_chan = MXC_DMA_DYNAMIC_CHANNEL,
+	.mode = 0,
+	.rto_en = 0,
+	.dir = 0,
+	.dma_chaining = 0,.ren = 0,
+	.burstLength = 4,.request = 0,.busuntils = 0,
+	.sourceType = DMA_TYPE_LINEAR,.sourcePort = TRANSFER_32BIT,
+	.destType = DMA_TYPE_LINEAR,.destPort = TRANSFER_32BIT,
+	.M2D_Valid = 0
+};
+
+/* dma_info from 2D memory to 2D memory for dma testing */
+static mx2_dma_info_t ram2d2ram2d_dma_info = {
+	.dma_chan = MXC_DMA_DYNAMIC_CHANNEL,
+	.mode = 0,
+	.rto_en = 0,
+	.dir = 0,
+	.rto_en = 0,
+	.dma_chaining = 0,.ren = 0,
+	.burstLength = 4,.request = 0,.busuntils = 0,
+	.sourceType = DMA_TYPE_2D,.sourcePort = TRANSFER_32BIT,
+	.destType = DMA_TYPE_2D,.destPort = TRANSFER_32BIT,
+	.M2D_Valid = 1,.msel = 0,.W = 0x80,.X = 0x40,.Y = 0x10
+};
+
+/* dma_info from memory to 2D memory for dma testing */
+static mx2_dma_info_t ram2ram2d_dma_info = {
+	.dma_chan = MXC_DMA_DYNAMIC_CHANNEL,
+	.mode = 0,
+	.rto_en = 0,
+	.dir = 0,
+	.dma_chaining = 0,.ren = 0,
+	.burstLength = 4,.request = 0,.busuntils = 0,
+	.sourceType = DMA_TYPE_LINEAR,.sourcePort = TRANSFER_32BIT,
+	.destType = DMA_TYPE_2D,.destPort = TRANSFER_32BIT,
+	.M2D_Valid = 1,.msel = 0,.W = 0x100,.X = 0x80,.Y = 0x10
+};
+
+/* dma_info from 2D memory to memory for dma testing */
+static mx2_dma_info_t ram2d2ram_dma_info = {
+	.dma_chan = MXC_DMA_DYNAMIC_CHANNEL,
+	.mode = 0,
+	.rto_en = 0,
+	.dir = 0,
+	.dma_chaining = 0,.ren = 0,
+	.burstLength = 4,.request = 0,.busuntils = 0,
+	.sourceType = DMA_TYPE_2D,.sourcePort = TRANSFER_32BIT,
+	.destType = DMA_TYPE_LINEAR,.destPort = TRANSFER_32BIT,
+	.M2D_Valid = 1,.msel = 0,.W = 0x100,.X = 0x100,.Y = 0x10
+};
+
+/* dma_info with dma chaining feature for dma testing */
+static mx2_dma_info_t hw_chaining_dma_info = {
+	.dma_chan = MXC_DMA_DYNAMIC_CHANNEL,
+	.mode = 0,
+	.rto_en = 0,
+	.dir = 0,
+	.dma_chaining = 1,.ren = 0,
+	.burstLength = 4,.request = 0,.busuntils = 0,
+	.sourceType = DMA_TYPE_LINEAR,.sourcePort = TRANSFER_32BIT,
+	.destType = DMA_TYPE_LINEAR,.destPort = TRANSFER_32BIT,
+	.M2D_Valid = 0,
+};
+
+/* dma_info without dma chaining feature for dma testing */
+static mx2_dma_info_t sw_chaining_dma_info = {
+	.dma_chan = MXC_DMA_DYNAMIC_CHANNEL,
+	.mode = 0,
+	.rto_en = 0,
+	.dir = 0,
+	.dma_chaining = 0,.ren = 0,
+	.burstLength = 4,.request = 0,.busuntils = 0,
+	.sourceType = DMA_TYPE_LINEAR,.sourcePort = TRANSFER_32BIT,
+	.destType = DMA_TYPE_LINEAR,.destPort = TRANSFER_32BIT,
+	.M2D_Valid = 0,
+};
+
+/* dma_info for ATA recieveing */
+static mx2_dma_info_t ata_rx_dma_info = {
+	.dma_chan = MXC_DMA_DYNAMIC_CHANNEL,
+	.mode = 0,
+	.rto_en = 0,
+	.dir = 0,
+	.dma_chaining = 0,.ren = 1,
+	.burstLength = 32,.request = 29,.busuntils = 0,
+	.sourceType = DMA_TYPE_FIFO,.sourcePort = TRANSFER_32BIT,
+	.destType = DMA_TYPE_LINEAR,.destPort = TRANSFER_32BIT,
+	.per_address = (ATA_BASE_ADDR + 0x18),
+	.M2D_Valid = 0,
+};
+
+/* dma_info for ATA transmitting */
+static mx2_dma_info_t ata_tx_dma_info = {
+	.dma_chan = MXC_DMA_DYNAMIC_CHANNEL,
+	.mode = 1,
+	.rto_en = 0,
+	.dir = 0,
+	.dma_chaining = 0,.ren = 1,
+	.burstLength = 32,.request = 28,.busuntils = 0,
+	.sourceType = DMA_TYPE_FIFO,.sourcePort = TRANSFER_32BIT,
+	.destType = DMA_TYPE_LINEAR,.destPort = TRANSFER_32BIT,
+	.per_address = (ATA_BASE_ADDR + 0x18),
+	.M2D_Valid = 0,
+};
+
+/* dma_info for UART1 recieveing */
+static mx2_dma_info_t uart1_rx_dma_info = {
+	.dma_chan = MXC_DMA_DYNAMIC_CHANNEL,
+	.mode = 0,
+	.rto_en = 1,
+	.dir = 0,
+	.dma_chaining = 0,.ren = 1,
+	.burstLength = 1,.request = 26,.busuntils = 8,
+	.sourceType = DMA_TYPE_FIFO,.sourcePort = TRANSFER_8BIT,
+	.destType = DMA_TYPE_LINEAR,.destPort = TRANSFER_8BIT,
+	.per_address = (UART1_BASE_ADDR),
+	.M2D_Valid = 0,
+};
+
+/* dma_info for UART1 transmitting */
+static mx2_dma_info_t uart1_tx_dma_info = {
+	.dma_chan = MXC_DMA_DYNAMIC_CHANNEL,
+	.mode = 1,
+	.rto_en = 0,
+	.dir = 0,
+	.dma_chaining = 0,.ren = 1,
+	.burstLength = 1,.request = 27,.busuntils = 0,
+	.sourceType = DMA_TYPE_FIFO,.sourcePort = TRANSFER_8BIT,
+	.destType = DMA_TYPE_LINEAR,.destPort = TRANSFER_8BIT,
+	.per_address = (UART1_BASE_ADDR + 0x40),
+	.M2D_Valid = 0,
+};
+
+/* dma_info for UART2 recieveing */
+static mx2_dma_info_t uart2_rx_dma_info = {
+	.dma_chan = MXC_DMA_DYNAMIC_CHANNEL,
+	.mode = 0,
+	.rto_en = 0,
+	.dir = 0,
+	.dma_chaining = 0,.ren = 1,
+	.burstLength = 1,.request = 24,.busuntils = 0,
+	.sourceType = DMA_TYPE_FIFO,.sourcePort = TRANSFER_8BIT,
+	.destType = DMA_TYPE_LINEAR,.destPort = TRANSFER_8BIT,
+	.per_address = (UART2_BASE_ADDR),
+	.M2D_Valid = 0,
+};
+
+/* dma_info for UART2 transmitting */
+static mx2_dma_info_t uart2_tx_dma_info = {
+	.dma_chan = MXC_DMA_DYNAMIC_CHANNEL,
+	.mode = 1,
+	.rto_en = 0,
+	.dir = 0,
+	.dma_chaining = 0,.ren = 1,
+	.burstLength = 1,.request = 25,.busuntils = 0,
+	.sourceType = DMA_TYPE_FIFO,.sourcePort = TRANSFER_8BIT,
+	.destType = DMA_TYPE_LINEAR,.destPort = TRANSFER_8BIT,
+	.per_address = (UART2_BASE_ADDR + 0x40),
+	.M2D_Valid = 0,
+};
+
+/* dma_info for UART3 recieveing */
+static mx2_dma_info_t uart3_rx_dma_info = {
+	.dma_chan = MXC_DMA_DYNAMIC_CHANNEL,
+	.mode = 0,
+	.rto_en = 0,
+	.dir = 0,
+	.dma_chaining = 0,.ren = 1,
+	.burstLength = 1,.request = 22,.busuntils = 0,
+	.sourceType = DMA_TYPE_FIFO,.sourcePort = TRANSFER_8BIT,
+	.destType = DMA_TYPE_LINEAR,.destPort = TRANSFER_8BIT,
+	.per_address = (UART3_BASE_ADDR),
+	.M2D_Valid = 0,
+};
+
+/* dma_info for UART3 transmitting */
+static mx2_dma_info_t uart3_tx_dma_info = {
+	.dma_chan = MXC_DMA_DYNAMIC_CHANNEL,
+	.mode = 1,
+	.rto_en = 0,
+	.dir = 0,
+	.dma_chaining = 0,.ren = 1,
+	.burstLength = 1,.request = 23,.busuntils = 0,
+	.sourceType = DMA_TYPE_FIFO,.sourcePort = TRANSFER_8BIT,
+	.destType = DMA_TYPE_LINEAR,.destPort = TRANSFER_8BIT,
+	.per_address = (UART3_BASE_ADDR + 0x40),
+	.M2D_Valid = 0,
+};
+
+/* dma_info for UART4 recieveing */
+static mx2_dma_info_t uart4_rx_dma_info = {
+	.dma_chan = MXC_DMA_DYNAMIC_CHANNEL,
+	.mode = 0,
+	.rto_en = 0,
+	.dir = 0,
+	.dma_chaining = 0,.ren = 1,
+	.burstLength = 1,.request = 20,.busuntils = 0,
+	.sourceType = DMA_TYPE_FIFO,.sourcePort = TRANSFER_8BIT,
+	.destType = DMA_TYPE_LINEAR,.destPort = TRANSFER_8BIT,
+	.per_address = (UART4_BASE_ADDR),
+	.M2D_Valid = 0,
+};
+
+/* dma_info for UART4transmitting */
+static mx2_dma_info_t uart4_tx_dma_info = {
+	.dma_chan = MXC_DMA_DYNAMIC_CHANNEL,
+	.mode = 1,
+	.rto_en = 0,
+	.dir = 0,
+	.dma_chaining = 0,.ren = 1,
+	.burstLength = 1,.request = 21,.busuntils = 0,
+	.sourceType = DMA_TYPE_FIFO,.sourcePort = TRANSFER_8BIT,
+	.destType = DMA_TYPE_LINEAR,.destPort = TRANSFER_8BIT,
+	.per_address = (UART4_BASE_ADDR + 0x40),
+	.M2D_Valid = 0,
+};
+
+/* dma_info for UART5 recieveing */
+static mx2_dma_info_t uart5_rx_dma_info = {
+	.dma_chan = MXC_DMA_DYNAMIC_CHANNEL,
+	.mode = 0,
+	.rto_en = 0,
+	.dir = 0,
+	.dma_chaining = 0,.ren = 1,
+	.burstLength = 1,.request = 32,.busuntils = 0,
+	.sourceType = DMA_TYPE_FIFO,.sourcePort = TRANSFER_8BIT,
+	.destType = DMA_TYPE_LINEAR,.destPort = TRANSFER_8BIT,
+	.per_address = (UART5_BASE_ADDR),
+	.M2D_Valid = 0,
+};
+
+/* dma_info for UART5 transmitting */
+static mx2_dma_info_t uart5_tx_dma_info = {
+	.dma_chan = MXC_DMA_DYNAMIC_CHANNEL,
+	.mode = 1,
+	.rto_en = 0,
+	.dir = 0,
+	.dma_chaining = 0,.ren = 1,
+	.burstLength = 1,.request = 33,.busuntils = 0,
+	.sourceType = DMA_TYPE_FIFO,.sourcePort = TRANSFER_8BIT,
+	.destType = DMA_TYPE_LINEAR,.destPort = TRANSFER_8BIT,
+	.per_address = (UART5_BASE_ADDR + 0x40),
+	.M2D_Valid = 0,
+};
+
+/* dma_info for UART6 recieveing */
+static mx2_dma_info_t uart6_rx_dma_info = {
+	.dma_chan = MXC_DMA_DYNAMIC_CHANNEL,
+	.mode = 0,
+	.rto_en = 0,
+	.dir = 0,
+	.dma_chaining = 0,.ren = 1,
+	.burstLength = 1,.request = 34,.busuntils = 0,
+	.sourceType = DMA_TYPE_FIFO,.sourcePort = TRANSFER_8BIT,
+	.destType = DMA_TYPE_LINEAR,.destPort = TRANSFER_8BIT,
+	.per_address = (UART6_BASE_ADDR),
+	.M2D_Valid = 0,
+};
+
+/* dma_info for UART6 transmitting */
+static mx2_dma_info_t uart6_tx_dma_info = {
+	.dma_chan = MXC_DMA_DYNAMIC_CHANNEL,
+	.mode = 1,
+	.rto_en = 0,
+	.dir = 0,
+	.dma_chaining = 0,.ren = 1,
+	.burstLength = 1,.request = 35,.busuntils = 0,
+	.sourceType = DMA_TYPE_FIFO,.sourcePort = TRANSFER_8BIT,
+	.destType = DMA_TYPE_LINEAR,.destPort = TRANSFER_8BIT,
+	.per_address = (UART6_BASE_ADDR + 0x40),
+	.M2D_Valid = 0,
+};
+
+static mx2_dma_info_t ssi1_16bit_rx0_dma_info = {
+	.dma_chan = MXC_DMA_DYNAMIC_CHANNEL,
+	.mode = 0,
+	.rto_en = 0,
+	.dir = 0,
+	.dma_chaining = MXC_SOUND_CAPTURE_CHAIN_DMA,.ren = 1,
+	.burstLength = 8,.request = DMA_REQ_SSI1_RX0,.busuntils = 0,
+	.sourceType = DMA_TYPE_FIFO,.sourcePort = DMA_MEM_SIZE_16,
+	.destType = DMA_TYPE_LINEAR,.destPort = DMA_MEM_SIZE_32,
+	.per_address = (SSI1_BASE_ADDR + 0x08),
+	.M2D_Valid = 0,
+};
+
+static mx2_dma_info_t ssi1_16bit_tx0_dma_info = {
+	.dma_chan = MXC_DMA_DYNAMIC_CHANNEL,
+	.mode = 1,
+	.rto_en = 0,
+	.dir = 0,
+	.dma_chaining = MXC_SOUND_PLAYBACK_CHAIN_DMA,.ren = 1,
+	.burstLength = 8,.request = DMA_REQ_SSI1_TX0,.busuntils = 0,
+	.sourceType = DMA_TYPE_FIFO,.sourcePort = DMA_MEM_SIZE_16,
+	.destType = DMA_TYPE_LINEAR,.destPort = DMA_MEM_SIZE_32,
+	.per_address = (SSI1_BASE_ADDR),
+	.M2D_Valid = 0,
+};
+
+static mx2_dma_info_t ssi2_16bit_rx0_dma_info = {
+	.dma_chan = MXC_DMA_DYNAMIC_CHANNEL,
+	.mode = 0,
+	.rto_en = 0,
+	.dir = 0,
+	.dma_chaining = MXC_SOUND_CAPTURE_CHAIN_DMA,.ren = 1,
+	.burstLength = 8,.request = DMA_REQ_SSI2_RX0,.busuntils = 0,
+	.sourceType = DMA_TYPE_FIFO,.sourcePort = DMA_MEM_SIZE_16,
+	.destType = DMA_TYPE_LINEAR,.destPort = DMA_MEM_SIZE_32,
+	.per_address = (SSI2_BASE_ADDR + 0x08),
+	.M2D_Valid = 0,
+};
+
+static mx2_dma_info_t ssi2_16bit_tx0_dma_info = {
+	.dma_chan = MXC_DMA_DYNAMIC_CHANNEL,
+	.mode = 1,
+	.rto_en = 0,
+	.dir = 0,
+	.dma_chaining = MXC_SOUND_PLAYBACK_CHAIN_DMA,.ren = 1,
+	.burstLength = 8,.request = DMA_REQ_SSI2_TX0,.busuntils = 0,
+	.sourceType = DMA_TYPE_FIFO,.sourcePort = DMA_MEM_SIZE_16,
+	.destType = DMA_TYPE_LINEAR,.destPort = DMA_MEM_SIZE_32,
+	.per_address = (SSI2_BASE_ADDR),
+	.M2D_Valid = 0,
+};
+
+static mx2_dma_info_t mmc1_width1_dma_info = {
+	.dma_chan = MXC_DMA_DYNAMIC_CHANNEL,
+	.mode = 0,
+	.rto_en = 0,
+	.dir = 0,
+	.dma_chaining = 0,.ren = 1,
+	.burstLength = 16,.request = DMA_REQ_SDHC1,.busuntils = 0,
+	.sourceType = DMA_TYPE_FIFO,.sourcePort = DMA_MEM_SIZE_32,
+	.destType = DMA_TYPE_LINEAR,.destPort = DMA_MEM_SIZE_32,
+	.per_address = (SDHC1_BASE_ADDR + 0x38),
+	.M2D_Valid = 0,
+};
+
+static mx2_dma_info_t mmc1_width4_dma_info = {
+	.dma_chan = MXC_DMA_DYNAMIC_CHANNEL,
+	.mode = 0,
+	.rto_en = 0,
+	.dir = 0,
+	.dma_chaining = 0,.ren = 1,
+	.burstLength = 0,.request = DMA_REQ_SDHC1,.busuntils = 0,
+	.sourceType = DMA_TYPE_FIFO,.sourcePort = DMA_MEM_SIZE_32,
+	.destType = DMA_TYPE_LINEAR,.destPort = DMA_MEM_SIZE_32,
+	.per_address = (SDHC1_BASE_ADDR + 0x38),
+	.M2D_Valid = 0,
+};
+
+static mx2_dma_info_t mmc2_width1_dma_info = {
+	.dma_chan = MXC_DMA_DYNAMIC_CHANNEL,
+	.mode = 0,
+	.rto_en = 0,
+	.dir = 0,
+	.dma_chaining = 0,.ren = 1,
+	.burstLength = 16,.request = DMA_REQ_SDHC2,.busuntils = 0,
+	.sourceType = DMA_TYPE_FIFO,.sourcePort = DMA_MEM_SIZE_32,
+	.destType = DMA_TYPE_LINEAR,.destPort = DMA_MEM_SIZE_32,
+	.per_address = (SDHC2_BASE_ADDR + 0x38),
+	.M2D_Valid = 0,
+};
+
+static mx2_dma_info_t mmc2_width4_dma_info = {
+	.dma_chan = MXC_DMA_DYNAMIC_CHANNEL,
+	.mode = 0,
+	.rto_en = 0,
+	.dir = 0,
+	.dma_chaining = 0,.ren = 1,
+	.burstLength = 0,.request = DMA_REQ_SDHC2,.busuntils = 0,
+	.sourceType = DMA_TYPE_FIFO,.sourcePort = DMA_MEM_SIZE_32,
+	.destType = DMA_TYPE_LINEAR,.destPort = DMA_MEM_SIZE_32,
+	.per_address = (SDHC2_BASE_ADDR + 0x38),
+	.M2D_Valid = 0,
+};
+
+static mx2_dma_info_t csi_rx_dma_info = {
+	.dma_chan = MXC_DMA_DYNAMIC_CHANNEL,
+	.mode = 0,
+	.rto_en = 0,
+	.dir = 0,
+	.dma_chaining = 1,.ren = 1,
+	.burstLength = 64,.request = DMA_REQ_CSI_RX,.busuntils = 0,
+	.sourceType = DMA_TYPE_FIFO,.sourcePort = DMA_MEM_SIZE_32,
+	.destType = DMA_TYPE_LINEAR,.destPort = DMA_MEM_SIZE_32,
+	.per_address = (CSI_BASE_ADDR + 0x10),
+	.M2D_Valid = 0,
+};
+
+/*
+ * dma info array which is actived
+ *    DEVICE_ID  RX/(RX&TX)	TX
+ */
+static dma_info_entry_t active_dma_info[] = {
+	{MXC_DMA_TEST_RAM2RAM, &ram2ram_dma_info},
+	{MXC_DMA_TEST_RAM2D2RAM2D, &ram2d2ram2d_dma_info},
+	{MXC_DMA_TEST_RAM2RAM2D, &ram2ram2d_dma_info},
+	{MXC_DMA_TEST_RAM2D2RAM, &ram2d2ram_dma_info},
+	{MXC_DMA_TEST_HW_CHAINING, &hw_chaining_dma_info},
+	{MXC_DMA_TEST_SW_CHAINING, &sw_chaining_dma_info},
+	{MXC_DMA_ATA_RX, &ata_rx_dma_info},
+	{MXC_DMA_ATA_TX, &ata_tx_dma_info},
+	{MXC_DMA_UART1_RX, &uart1_rx_dma_info},
+	{MXC_DMA_UART1_TX, &uart1_tx_dma_info},
+	{MXC_DMA_UART2_RX, &uart2_rx_dma_info},
+	{MXC_DMA_UART2_TX, &uart2_tx_dma_info},
+	{MXC_DMA_UART3_RX, &uart3_rx_dma_info},
+	{MXC_DMA_UART3_TX, &uart3_tx_dma_info},
+	{MXC_DMA_UART4_RX, &uart4_rx_dma_info},
+	{MXC_DMA_UART4_TX, &uart4_tx_dma_info},
+	{MXC_DMA_UART5_RX, &uart5_rx_dma_info},
+	{MXC_DMA_UART5_TX, &uart5_tx_dma_info},
+	{MXC_DMA_UART6_RX, &uart6_rx_dma_info},
+	{MXC_DMA_UART6_TX, &uart6_tx_dma_info},
+	{MXC_DMA_SSI1_16BIT_RX0, &ssi1_16bit_rx0_dma_info},
+	{MXC_DMA_SSI1_16BIT_TX0, &ssi1_16bit_tx0_dma_info},
+	{MXC_DMA_SSI2_16BIT_RX0, &ssi2_16bit_rx0_dma_info},
+	{MXC_DMA_SSI2_16BIT_TX0, &ssi2_16bit_tx0_dma_info},
+	{MXC_DMA_MMC1_WIDTH_1, &mmc1_width1_dma_info},
+	{MXC_DMA_MMC1_WIDTH_4, &mmc1_width4_dma_info},
+	{MXC_DMA_MMC2_WIDTH_1, &mmc2_width1_dma_info},
+	{MXC_DMA_MMC2_WIDTH_4, &mmc2_width4_dma_info},
+	{MXC_DMA_CSI_RX, &csi_rx_dma_info},
+};
+
+/* get the dma info by channel_id */
+mx2_dma_info_t *mxc_dma_get_info(mxc_dma_device_t channel_id)
+{
+	dma_info_entry_t *p = active_dma_info;
+	int i;
+	for (i = 0; i < ARRAY_SIZE(active_dma_info); i++, p++) {
+		if (p->device == channel_id)
+			return p->info;
+	}
+	return NULL;
+}
+EXPORT_SYMBOL(mxc_dma_get_info);
+
+/* scan dma parameter list . And collect information about which
+ * channels are dynamic */
+void mxc_dma_load_info(mxc_dma_channel_t * dma)
+{
+	int i, idx;
+	dma_info_entry_t *p = active_dma_info;
+
+	BUG_ON(dma == NULL);
+	BUG_ON(p == NULL);
+
+	for (i = 0; i < MXC_DMA_CHANNELS; i++) {
+		dma[i].dynamic = 1;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(active_dma_info); i++, p++) {
+		BUG_ON((p->info == NULL));
+
+		idx = p->info->dma_chan;
+
+		BUG_ON(((idx >= MAX_DMA_CHANNELS)
+			&& (idx != MXC_DMA_DYNAMIC_CHANNEL)));
+		if ((idx < 0) || (idx == MXC_DMA_DYNAMIC_CHANNEL))
+			continue;
+		dma[idx].dynamic = 0;
+	}
+}
+EXPORT_SYMBOL(mxc_dma_load_info);
Index: arch/arm/mach-mx2/devices.c
===================================================================
--- /dev/null
+++ arch/arm/mach-mx2/devices.c
@@ -0,0 +1,587 @@
+/*
+ * Author: MontaVista Software, Inc.
+ *       <source@mvista.com>
+ *
+ * Based on the OMAP devices.c
+ *
+ * 2005 (c) MontaVista Software, Inc. This file is licensed under the
+ * terms of the GNU General Public License version 2. This program is
+ * licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ *
+ * Copyright 2006-2007 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+
+#include <linux/spi/spi.h>
+
+#include <asm/hardware.h>
+
+#if defined(CONFIG_W1_MASTER_MXC) || defined(CONFIG_W1_MASTER_MXC_MODULE)
+static struct mxc_w1_config mxc_w1_data = {
+	.search_rom_accelerator = 0,
+};
+
+static struct platform_device mxc_w1_devices = {
+	.name = "mxc_w1",
+	.dev = {
+		.release = mxc_nop_release,
+		.platform_data = &mxc_w1_data,
+		},
+	.id = 0
+};
+
+static void mxc_init_owire(void)
+{
+	(void)platform_device_register(&mxc_w1_devices);
+}
+#else
+static inline void mxc_init_owire(void)
+{
+}
+#endif
+
+#if defined(CONFIG_MXC_RTC) || defined(CONFIG_MXC_RTC_MODULE)
+
+static struct platform_device mxc_rtc_device = {
+	.name = "mxc_rtc",
+	.id = 0,
+};
+static void mxc_init_rtc(void)
+{
+	(void)platform_device_register(&mxc_rtc_device);
+}
+#else
+static inline void mxc_init_rtc(void)
+{
+}
+#endif
+#if defined(CONFIG_MXC_WATCHDOG) || defined(CONFIG_MXC_WATCHDOG_MODULE)
+
+static struct resource wdt_resources[] = {
+	{
+	 .start = WDOG_BASE_ADDR,
+	 .end = WDOG_BASE_ADDR + 0x30,
+	 .flags = IORESOURCE_MEM,
+	 },
+};
+
+static struct platform_device mxc_wdt_device = {
+	.name = "mxc_wdt",
+	.id = 0,
+	.dev = {
+		.release = mxc_nop_release,
+		},
+	.num_resources = ARRAY_SIZE(wdt_resources),
+	.resource = wdt_resources,
+};
+
+static void mxc_init_wdt(void)
+{
+	(void)platform_device_register(&mxc_wdt_device);
+}
+#else
+static inline void mxc_init_wdt(void)
+{
+}
+#endif
+
+/* MMC device data */
+
+#if defined(CONFIG_MMC_MXC) || defined(CONFIG_MMC_MXC_MODULE)
+
+extern unsigned int sdhc_get_card_det_status(struct device *dev);
+extern int sdhc_init_card_det(int id);
+
+static struct mxc_mmc_platform_data mmc_data = {
+	.ocr_mask = MMC_VDD_27_28 | MMC_VDD_28_29 | MMC_VDD_29_30,
+	.min_clk = 150000,
+	.max_clk = 25000000,
+	.card_inserted_state = 0,
+	.status = sdhc_get_card_det_status,
+};
+
+/*!
+ * Resource definition for the SDHC1
+ */
+static struct resource mxcsdhc1_resources[] = {
+	[0] = {
+	       .start = SDHC1_BASE_ADDR,
+	       .end = SDHC1_BASE_ADDR + SZ_4K - 1,
+	       .flags = IORESOURCE_MEM,
+	       },
+	[1] = {
+	       .start = INT_SDHC1,
+	       .end = INT_SDHC1,
+	       .flags = IORESOURCE_IRQ,
+	       },
+	[2] = {
+	       .start = 0,
+	       .end = 0,
+	       .flags = IORESOURCE_IRQ,
+	       },
+	[3] = {
+	       .start = MXC_SDIO1_CARD_IRQ,
+	       .end = MXC_SDIO1_CARD_IRQ,
+	       .flags = IORESOURCE_IRQ,
+	       },
+};
+
+/*!
+ * Resource definition for the SDHC2
+ */
+static struct resource mxcsdhc2_resources[] = {
+	[0] = {
+	       .start = SDHC2_BASE_ADDR,
+	       .end = SDHC2_BASE_ADDR + SZ_4K - 1,
+	       .flags = IORESOURCE_MEM,
+	       },
+	[1] = {
+	       .start = INT_SDHC2,
+	       .end = INT_SDHC2,
+	       .flags = IORESOURCE_IRQ,
+	       },
+	[2] = {
+	       .start = 0,
+	       .end = 0,
+	       .flags = IORESOURCE_IRQ,
+	       },
+	[3] = {
+	       .start = MXC_SDIO2_CARD_IRQ,
+	       .end = MXC_SDIO2_CARD_IRQ,
+	       .flags = IORESOURCE_IRQ,
+	       },
+};
+
+/*! Device Definition for MXC SDHC1 */
+static struct platform_device mxcsdhc1_device = {
+	.name = "mxcmci",
+	.id = 0,
+	.dev = {
+		.release = mxc_nop_release,
+		.platform_data = &mmc_data,
+		},
+	.num_resources = ARRAY_SIZE(mxcsdhc1_resources),
+	.resource = mxcsdhc1_resources,
+};
+
+/*! Device Definition for MXC SDHC2 */
+static struct platform_device mxcsdhc2_device = {
+	.name = "mxcmci",
+	.id = 1,
+	.dev = {
+		.release = mxc_nop_release,
+		.platform_data = &mmc_data,
+		},
+	.num_resources = ARRAY_SIZE(mxcsdhc2_resources),
+	.resource = mxcsdhc2_resources,
+};
+
+#ifdef CONFIG_MXC_SDHC3
+/*!
+ * Resource definition for the SDHC3
+ */
+static struct resource mxcsdhc3_resources[] = {
+	[0] = {
+	       .start = SDHC3_BASE_ADDR,
+	       .end = SDHC3_BASE_ADDR + SZ_4K - 1,
+	       .flags = IORESOURCE_MEM,
+	       },
+	[1] = {
+	       .start = INT_SDHC3,
+	       .end = INT_SDHC3,
+	       .flags = IORESOURCE_IRQ,
+	       },
+	[2] = {
+	       .start = 0,
+	       .end = 0,
+	       .flags = IORESOURCE_IRQ,
+	       },
+	[3] = {
+	       .start = MXC_SDIO3_CARD_IRQ,
+	       .end = MXC_SDIO3_CARD_IRQ,
+	       .flags = IORESOURCE_IRQ,
+	       },
+};
+
+/*! Device Definition for MXC SDHC3 */
+static struct platform_device mxcsdhc3_device = {
+	.name = "mxcmci",
+	.id = 2,
+	.dev = {
+		.release = mxc_nop_release,
+		.platform_data = &mmc_data,
+		},
+	.num_resources = ARRAY_SIZE(mxcsdhc3_resources),
+	.resource = mxcsdhc3_resources,
+};
+#endif
+
+static inline void mxc_init_mmc(void)
+{
+	int cd_irq;
+
+	cd_irq = sdhc_init_card_det(0);
+	if (cd_irq) {
+		mxcsdhc1_device.resource[2].start = cd_irq;
+		mxcsdhc1_device.resource[2].end = cd_irq;
+	}
+	cd_irq = sdhc_init_card_det(1);
+	if (cd_irq) {
+		mxcsdhc2_device.resource[2].start = cd_irq;
+		mxcsdhc2_device.resource[2].end = cd_irq;
+	}
+
+	(void)platform_device_register(&mxcsdhc1_device);
+	(void)platform_device_register(&mxcsdhc2_device);
+#ifdef CONFIG_MXC_SDHC3
+	(void)platform_device_register(&mxcsdhc3_device);
+#endif
+}
+#else
+static inline void mxc_init_mmc(void)
+{
+}
+#endif
+
+/* SPI controller and device data */
+#if defined(CONFIG_SPI_MXC) || defined(CONFIG_SPI_MXC_MODULE)
+
+#ifdef CONFIG_SPI_MXC_SELECT1
+/*!
+ * Resource definition for the CSPI1
+ */
+static struct resource mxcspi1_resources[] = {
+	[0] = {
+	       .start = CSPI1_BASE_ADDR,
+	       .end = CSPI1_BASE_ADDR + SZ_4K - 1,
+	       .flags = IORESOURCE_MEM,
+	       },
+	[1] = {
+	       .start = INT_CSPI1,
+	       .end = INT_CSPI1,
+	       .flags = IORESOURCE_IRQ,
+	       },
+};
+
+/*! Platform Data for MXC CSPI1 */
+static struct mxc_spi_master mxcspi1_data = {
+	.maxchipselect = 4,
+	.spi_version = 0,
+};
+
+/*! Device Definition for MXC CSPI1 */
+static struct platform_device mxcspi1_device = {
+	.name = "mxc_spi",
+	.id = 0,
+	.dev = {
+		.release = mxc_nop_release,
+		.platform_data = &mxcspi1_data,
+		},
+	.num_resources = ARRAY_SIZE(mxcspi1_resources),
+	.resource = mxcspi1_resources,
+};
+
+#endif				/* CONFIG_SPI_MXC_SELECT1 */
+
+#ifdef CONFIG_SPI_MXC_SELECT2
+/*!
+ * Resource definition for the CSPI2
+ */
+static struct resource mxcspi2_resources[] = {
+	[0] = {
+	       .start = CSPI2_BASE_ADDR,
+	       .end = CSPI2_BASE_ADDR + SZ_4K - 1,
+	       .flags = IORESOURCE_MEM,
+	       },
+	[1] = {
+	       .start = INT_CSPI2,
+	       .end = INT_CSPI2,
+	       .flags = IORESOURCE_IRQ,
+	       },
+};
+
+/*! Platform Data for MXC CSPI2 */
+static struct mxc_spi_master mxcspi2_data = {
+	.maxchipselect = 4,
+	.spi_version = 0,
+};
+
+/*! Device Definition for MXC CSPI2 */
+static struct platform_device mxcspi2_device = {
+	.name = "mxc_spi",
+	.id = 1,
+	.dev = {
+		.release = mxc_nop_release,
+		.platform_data = &mxcspi2_data,
+		},
+	.num_resources = ARRAY_SIZE(mxcspi2_resources),
+	.resource = mxcspi2_resources,
+};
+#endif				/* CONFIG_SPI_MXC_SELECT2 */
+
+#ifdef CONFIG_SPI_MXC_SELECT3
+/*!
+ * Resource definition for the CSPI3
+ */
+static struct resource mxcspi3_resources[] = {
+	[0] = {
+	       .start = CSPI3_BASE_ADDR,
+	       .end = CSPI3_BASE_ADDR + SZ_4K - 1,
+	       .flags = IORESOURCE_MEM,
+	       },
+	[1] = {
+	       .start = INT_CSPI3,
+	       .end = INT_CSPI3,
+	       .flags = IORESOURCE_IRQ,
+	       },
+};
+
+/*! Platform Data for MXC CSPI3 */
+static struct mxc_spi_master mxcspi3_data = {
+	.maxchipselect = 4,
+	.spi_version = 0,
+};
+
+/*! Device Definition for MXC CSPI3 */
+static struct platform_device mxcspi3_device = {
+	.name = "mxc_spi",
+	.id = 2,
+	.dev = {
+		.release = mxc_nop_release,
+		.platform_data = &mxcspi3_data,
+		},
+	.num_resources = ARRAY_SIZE(mxcspi3_resources),
+	.resource = mxcspi3_resources,
+};
+#endif				/* CONFIG_SPI_MXC_SELECT3 */
+
+static inline void mxc_init_spi(void)
+{
+#ifdef CONFIG_SPI_MXC_SELECT1
+	if (platform_device_register(&mxcspi1_device) < 0)
+		printk(KERN_ERR "Registering the SPI Controller_1\n");
+#endif				/* CONFIG_SPI_MXC_SELECT1 */
+#ifdef CONFIG_SPI_MXC_SELECT2
+	if (platform_device_register(&mxcspi2_device) < 0)
+		printk(KERN_ERR "Registering the SPI Controller_2\n");
+#endif				/* CONFIG_SPI_MXC_SELECT2 */
+#ifdef CONFIG_SPI_MXC_SELECT3
+	if (platform_device_register(&mxcspi3_device) < 0)
+		printk(KERN_ERR "Registering the SPI Controller_3\n");
+#endif				/* CONFIG_SPI_MXC_SELECT3 */
+}
+#else
+static inline void mxc_init_spi(void)
+{
+}
+#endif
+
+/* I2C controller and device data */
+#if defined(CONFIG_I2C_MXC) || defined(CONFIG_I2C_MXC_MODULE)
+
+#ifdef CONFIG_I2C_MXC_SELECT1
+/*!
+ * Resource definition for the I2C1
+ */
+static struct resource mxci2c1_resources[] = {
+	[0] = {
+	       .start = I2C_BASE_ADDR,
+	       .end = I2C_BASE_ADDR + SZ_4K - 1,
+	       .flags = IORESOURCE_MEM,
+	       },
+	[1] = {
+	       .start = INT_I2C,
+	       .end = INT_I2C,
+	       .flags = IORESOURCE_IRQ,
+	       },
+};
+
+/*! Platform Data for MXC I2C */
+static struct mxc_i2c_platform_data mxci2c1_data = {
+	.i2c_clk = 100000,
+};
+#endif
+
+#ifdef CONFIG_I2C_MXC_SELECT2
+/*!
+ * Resource definition for the I2C2
+ */
+static struct resource mxci2c2_resources[] = {
+	[0] = {
+	       .start = I2C2_BASE_ADDR,
+	       .end = I2C2_BASE_ADDR + SZ_4K - 1,
+	       .flags = IORESOURCE_MEM,
+	       },
+	[1] = {
+	       .start = INT_I2C2,
+	       .end = INT_I2C2,
+	       .flags = IORESOURCE_IRQ,
+	       },
+};
+
+/*! Platform Data for MXC I2C */
+static struct mxc_i2c_platform_data mxci2c2_data = {
+	.i2c_clk = 100000,
+};
+#endif
+
+/*! Device Definition for MXC I2C */
+static struct platform_device mxci2c_devices[] = {
+#ifdef CONFIG_I2C_MXC_SELECT1
+	{
+	 .name = "mxc_i2c",
+	 .id = 0,
+	 .dev = {
+		 .release = mxc_nop_release,
+		 .platform_data = &mxci2c1_data,
+		 },
+	 .num_resources = ARRAY_SIZE(mxci2c1_resources),
+	 .resource = mxci2c1_resources,},
+#endif
+#ifdef CONFIG_I2C_MXC_SELECT2
+	{
+	 .name = "mxc_i2c",
+	 .id = 1,
+	 .dev = {
+		 .release = mxc_nop_release,
+		 .platform_data = &mxci2c2_data,
+		 },
+	 .num_resources = ARRAY_SIZE(mxci2c2_resources),
+	 .resource = mxci2c2_resources,},
+#endif
+};
+
+static inline void mxc_init_i2c(void)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(mxci2c_devices); i++) {
+		if (platform_device_register(&mxci2c_devices[i]) < 0)
+			dev_err(&mxci2c_devices[i].dev,
+				"Unable to register I2C device\n");
+	}
+}
+#else
+static inline void mxc_init_i2c(void)
+{
+}
+#endif
+
+#ifdef	CONFIG_MXC_VPU
+/*! Platform Data for MXC VPU */
+static struct platform_device mxcvpu_device = {
+	.name = "mxc_vpu",
+	.dev = {
+		.release = mxc_nop_release,
+		},
+	.id = 0,
+};
+
+static inline void mxc_init_vpu(void)
+{
+	if (platform_device_register(&mxcvpu_device) < 0)
+		printk(KERN_ERR "Error: Registering the VPU.\n");
+}
+#else
+static inline void mxc_init_vpu(void)
+{
+}
+#endif
+
+#ifdef  CONFIG_MXC_IRDA
+/*
+ * Resource definition for the MXC IrDA
+ */
+static struct resource mxcirda_resources[] = {
+	[0] = {
+		.start   = UART3_BASE_ADDR,
+		.end     = UART3_BASE_ADDR + SZ_4K - 1,
+		.flags   = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start   = INT_UART3,
+		.end     = INT_UART3,
+		.flags   = IORESOURCE_IRQ,
+	},
+};
+
+/* Platform Data for MXC IrDA */
+static struct platform_device mxcirda_device = {
+	.name = "mxc_irda",
+	.dev = {
+		.release = mxc_nop_release,
+	},
+	.id = 0,
+	.num_resources = ARRAY_SIZE(mxcirda_resources),
+	.resource = mxcirda_resources,
+};
+
+static inline void mxc_init_irda(void)
+{
+	if (platform_device_register(&mxcirda_device) < 0)
+		printk(KERN_ERR "Error: Registering the MXC IrDA.\n");
+	printk("IrDA: MXC IrDA registered\n");
+}
+#else
+static inline void mxc_init_irda(void)
+{
+}
+#endif
+
+struct mxc_gpio_port mxc_gpio_ports[GPIO_PORT_NUM] = {
+	{
+	 .num = 0,
+	 .base = IO_ADDRESS(GPIO_BASE_ADDR),
+	 .irq = INT_GPIO,
+	 .virtual_irq_start = MXC_GPIO_BASE,
+	 },
+	{
+	 .num = 1,
+	 .base = IO_ADDRESS(GPIO_BASE_ADDR) + 0x100,
+	 .irq = INT_GPIO,
+	 .virtual_irq_start = MXC_GPIO_BASE + GPIO_NUM_PIN,
+	 },
+	{
+	 .num = 2,
+	 .base = IO_ADDRESS(GPIO_BASE_ADDR) + 0x200,
+	 .irq = INT_GPIO,
+	 .virtual_irq_start = MXC_GPIO_BASE + GPIO_NUM_PIN * 2,
+	 },
+	{
+	 .num = 3,
+	 .base = IO_ADDRESS(GPIO_BASE_ADDR) + 0x300,
+	 .irq = INT_GPIO,
+	 .virtual_irq_start = MXC_GPIO_BASE + GPIO_NUM_PIN * 3,
+	 },
+	{
+	 .num = 4,
+	 .base = IO_ADDRESS(GPIO_BASE_ADDR) + 0x400,
+	 .irq = INT_GPIO,
+	 .virtual_irq_start = MXC_GPIO_BASE + GPIO_NUM_PIN * 4,
+	 },
+	{
+	 .num = 5,
+	 .base = IO_ADDRESS(GPIO_BASE_ADDR) + 0x500,
+	 .irq = INT_GPIO,
+	 .virtual_irq_start = MXC_GPIO_BASE + GPIO_NUM_PIN * 5,
+	 },
+};
+
+static int __init mxc_init_devices(void)
+{
+	mxc_init_wdt();
+	mxc_init_mmc();
+	mxc_init_spi();
+	mxc_init_i2c();
+	mxc_init_rtc();
+	mxc_init_owire();
+	mxc_init_vpu();
+	mxc_init_irda();
+	return 0;
+}
+
+arch_initcall(mxc_init_devices);
Index: arch/arm/mach-mx2/Kconfig
===================================================================
--- /dev/null
+++ arch/arm/mach-mx2/Kconfig
@@ -0,0 +1,20 @@
+comment "MX2 Options"
+	depends on ARCH_MX2
+
+choice
+	prompt "CPU type"
+	depends on ARCH_MX2
+	default MACH_MX27
+
+config MACH_MX27
+	bool "i.MX27"
+	help
+	  This enables support for Freescale's MX2 based i.MX27 processor.
+
+endchoice
+
+choice
+	prompt "MX2 Platforms"
+	depends on ARCH_MX2
+
+endchoice
Index: arch/arm/mach-mx2/Makefile
===================================================================
--- /dev/null
+++ arch/arm/mach-mx2/Makefile
@@ -0,0 +1,7 @@
+#
+# Makefile for the linux kernel.
+#
+
+# Object file lists.
+
+obj-y		:= mm.o time.o dma.o gpio_mux.o clock.o devices.o serial.o system.o cpu.o
Index: arch/arm/mach-mx2/Makefile.boot
===================================================================
--- /dev/null
+++ arch/arm/mach-mx2/Makefile.boot
@@ -0,0 +1,3 @@
+   zreladdr-y	:= 0xA0008000
+params_phys-y	:= 0xA0000100
+initrd_phys-y	:= 0xA0800000
Index: arch/arm/mach-mx2/mm.c
===================================================================
--- /dev/null
+++ arch/arm/mach-mx2/mm.c
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/*
+ * Creates static mapping between physical to virtual memory.
+ */
+#include <linux/mm.h>
+#include <linux/init.h>
+#include <asm/hardware.h>
+#include <asm/pgtable.h>
+#include <asm/mach/map.h>
+
+
+/* MX27 memory map definition */
+static struct map_desc mxc_io_desc[] __initdata = {
+	{
+	 .virtual = AIPI_BASE_ADDR_VIRT,
+	 .pfn = __phys_to_pfn(AIPI_BASE_ADDR),
+	 .length = AIPI_SIZE,
+	 .type = MT_DEVICE},
+	{
+	 .virtual = SAHB1_BASE_ADDR_VIRT,
+	 .pfn = __phys_to_pfn(SAHB1_BASE_ADDR),
+	 .length = SAHB1_SIZE,
+	 .type = MT_DEVICE},
+	{
+	 .virtual = X_MEMC_BASE_ADDR_VIRT,
+	 .pfn = __phys_to_pfn(X_MEMC_BASE_ADDR),
+	 .length = X_MEMC_SIZE,
+	 .type = MT_DEVICE},
+	{
+	 .virtual = CS4_BASE_ADDR_VIRT,
+	 .pfn = __phys_to_pfn(CS4_BASE_ADDR),
+	 .length = CS4_SIZE,
+	 .type = MT_DEVICE}
+};
+
+/*
+ * Initialize the memory map. It is called during the
+ * system startup to create static physical to virtual
+ * memory map for the IO modules.
+ */
+void __init mxc_map_io(void)
+{
+	iotable_init(mxc_io_desc, ARRAY_SIZE(mxc_io_desc));
+}
Index: arch/arm/mach-mx2/system.c
===================================================================
--- /dev/null
+++ arch/arm/mach-mx2/system.c
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 1999 ARM Limited
+ * Copyright (C) 2000 Deep Blue Solutions Ltd
+ * Copyright 2006-2007 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/clk.h>
+#include <asm/io.h>
+#include <asm/arch/hardware.h>
+#include <asm/proc-fns.h>
+#include <asm/system.h>
+
+/*
+ * Put the CPU into idle mode. It is called by default_idle()
+ * in process.c file.
+ */
+void arch_idle(void)
+{
+	/*
+	 * This should do all the clock switching
+	 * and wait for interrupt tricks.
+	 */
+	cpu_do_idle();
+}
+
+#define WDOG_WCR_REG                    IO_ADDRESS(WDOG_BASE_ADDR)
+#define WDOG_WCR_SRS                    (1 << 4)
+
+/*
+ * Reset the system. It is called by machine_restart().
+ */
+void arch_reset(char mode)
+{
+	struct clk *clk;
+
+	clk = clk_get(NULL, "wdog_clk");
+	clk_enable(clk);
+
+	/* Assert SRS signal */
+	__raw_writew(__raw_readw(WDOG_WCR_REG) & ~WDOG_WCR_SRS, WDOG_WCR_REG);
+}
Index: arch/arm/mach-mx2/serial.h
===================================================================
--- /dev/null
+++ arch/arm/mach-mx2/serial.h
@@ -0,0 +1,165 @@
+/*
+ * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#ifndef __ARCH_ARM_MACH_MX2_SERIAL_H__
+#define __ARCH_ARM_MACH_MX2_SERIAL_H__
+
+#include <asm/arch/mxc_uart.h>
+
+/*
+ * This option allows to choose either an interrupt-driven software controlled
+ * hardware flow control (set this option to 0) or hardware-driven hardware
+ * flow control (set this option to 1).
+ */
+#define UART1_HW_FLOW           1
+/*
+ * This specifies the threshold at which the CTS pin is deasserted by the
+ * RXFIFO. Set this value in Decimal to anything from 0 to 32 for
+ * hardware-driven hardware flow control. Read the HW spec while specifying
+ * this value. When using interrupt-driven software controlled hardware
+ * flow control set this option to -1.
+ */
+#define UART1_UCR4_CTSTL        16
+/*
+ * This is option to enable (set this option to 1) or disable DMA data transfer
+ */
+#define UART1_DMA_ENABLE        0
+/*
+ * Specify the size of the DMA receive buffer. The buffer size should be same with
+ * sub buffer size which is defined in mxc_uart.c for all data can be transfered.
+ */
+#define UART1_DMA_RXBUFSIZE     128
+/*
+ * Specify the MXC UART's Receive Trigger Level. This controls the threshold at
+ * which a maskable interrupt is generated by the RxFIFO. Set this value in
+ * Decimal to anything from 0 to 32. Read the HW spec while specifying this
+ * value.
+ */
+#define UART1_UFCR_RXTL         16
+/*
+ * Specify the MXC UART's Transmit Trigger Level. This controls the threshold at
+ * which a maskable interrupt is generated by the TxFIFO. Set this value in
+ * Decimal to anything from 0 to 32. Read the HW spec while specifying this
+ * value.
+ */
+#define UART1_UFCR_TXTL         16
+/* UART 2 configuration */
+#define UART2_HW_FLOW           1
+#define UART2_UCR4_CTSTL        16
+#define UART2_DMA_ENABLE        0
+#define UART2_DMA_RXBUFSIZE     512
+#define UART2_UFCR_RXTL         16
+#define UART2_UFCR_TXTL         16
+/* UART 3 configuration */
+#define UART3_HW_FLOW           0
+#define UART3_UCR4_CTSTL        -1
+#define UART3_DMA_ENABLE        0
+#define UART3_DMA_RXBUFSIZE     512
+#define UART3_UFCR_RXTL         16
+#define UART3_UFCR_TXTL         16
+/* UART 4 configuration */
+#define UART4_HW_FLOW           1
+#define UART4_UCR4_CTSTL        16
+#define UART4_DMA_ENABLE        0
+#define UART4_DMA_RXBUFSIZE     512
+#define UART4_UFCR_RXTL         16
+#define UART4_UFCR_TXTL         16
+/* UART 5 configuration */
+#define UART5_HW_FLOW           1
+#define UART5_UCR4_CTSTL        16
+#define UART5_DMA_ENABLE        0
+#define UART5_DMA_RXBUFSIZE     512
+#define UART5_UFCR_RXTL         16
+#define UART5_UFCR_TXTL         16
+/* UART 6 configuration */
+#define UART6_HW_FLOW           1
+#define UART6_UCR4_CTSTL        16
+#define UART6_DMA_ENABLE        0
+#define UART6_DMA_RXBUFSIZE     512
+#define UART6_UFCR_RXTL         16
+#define UART6_UFCR_TXTL         16
+/*
+ * UART Chip level Configuration that a user may not have to edit. These
+ * configuration vary depending on how the UART module is integrated with
+ * the ARM core
+ */
+/*
+ * Is the MUXED interrupt output sent to the ARM core
+ */
+#define INTS_NOTMUXED           0
+#define INTS_MUXED              1
+
+/* UART 1 configuration */
+/*
+ * This define specifies whether the muxed ANDed interrupt line or the
+ * individual interrupts from the UART port is integrated with the ARM core.
+ * There exists a define like this for each UART port. Valid values that can
+ * be used are \b INTS_NOTMUXED or \b INTS_MUXED.
+ */
+#define UART1_MUX_INTS          INTS_MUXED
+/*
+ * This define specifies the transmitter interrupt number or the interrupt
+ * number of the ANDed interrupt in case the interrupts are muxed. There exists
+ * a define like this for each UART port.
+ */
+#define UART1_INT1              INT_UART1
+/*
+ * This define specifies the receiver interrupt number. If the interrupts of
+ * the UART are muxed, then we specify here a dummy value -1. There exists a
+ * define like this for each UART port.
+ */
+#define UART1_INT2              -1
+/*
+ * This specifies the master interrupt number. If the interrupts of the UART
+ * are muxed, then we specify here a dummy value of -1. There exists a define
+ * like this for each UART port.
+ */
+#define UART1_INT3              -1
+/*
+ * This specifies if the UART is a shared peripheral. It holds the shared
+ * peripheral number if it is shared or -1 if it is not shared. There exists
+ * a define like this for each UART port.
+ */
+#define UART1_SHARED_PERI       -1
+/* UART 2 configuration */
+#define UART2_MUX_INTS          INTS_MUXED
+#define UART2_INT1              INT_UART2
+#define UART2_INT2              -1
+#define UART2_INT3              -1
+#define UART2_SHARED_PERI       -1
+/* UART 3 configuration */
+#define UART3_MUX_INTS          INTS_MUXED
+#define UART3_INT1              INT_UART3
+#define UART3_INT2              -1
+#define UART3_INT3              -1
+#define UART3_SHARED_PERI       -1
+/* UART 4 configuration */
+#define UART4_MUX_INTS          INTS_MUXED
+#define UART4_INT1              INT_UART4
+#define UART4_INT2              -1
+#define UART4_INT3              -1
+#define UART4_SHARED_PERI       -1
+/* UART 5 configuration */
+#define UART5_MUX_INTS          INTS_MUXED
+#define UART5_INT1              INT_UART5
+#define UART5_INT2              -1
+#define UART5_INT3              -1
+#define UART5_SHARED_PERI       -1
+/* UART 6 configuration */
+#define UART6_MUX_INTS          INTS_MUXED
+#define UART6_INT1              INT_UART6
+#define UART6_INT2              -1
+#define UART6_INT3              -1
+#define UART6_SHARED_PERI       -1
+
+#endif /* __ARCH_ARM_MACH_MX2_SERIAL_H__ */
Index: arch/arm/mach-mx2/serial.c
===================================================================
--- /dev/null
+++ arch/arm/mach-mx2/serial.c
@@ -0,0 +1,314 @@
+/*
+ * Copyright 2006-2007 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/serial.h>
+#include <asm/hardware.h>
+#include <asm/arch/mxc_uart.h>
+#include "serial.h"
+#include "devices.h"
+
+/*
+ * This is an array where each element holds information about a UART port,
+ * like base address of the UART, interrupt numbers etc. This structure is
+ * passed to the serial_core.c file. Based on which UART is used, the core file
+ * passes back the appropriate port structure as an argument to the control
+ * functions.
+ */
+static uart_mxc_port mxc_ports[6] = {
+	[0] = {
+	       .port = {
+			.membase = (void *)IO_ADDRESS(UART1_BASE_ADDR),
+			.mapbase = UART1_BASE_ADDR,
+			.iotype = SERIAL_IO_MEM,
+			.irq = UART1_INT1,
+			.fifosize = 32,
+			.flags = ASYNC_BOOT_AUTOCONF,
+			.line = 0,
+		},
+	       .ints_muxed = UART1_MUX_INTS,
+	       .irqs = {UART1_INT2, UART1_INT3},
+	       .mode = UART1_MODE,
+	       .ir_mode = UART1_IR,
+	       .enabled = UART1_ENABLED,
+	       .hardware_flow = UART1_HW_FLOW,
+	       .cts_threshold = UART1_UCR4_CTSTL,
+	       .dma_enabled = UART1_DMA_ENABLE,
+	       .dma_rxbuf_size = UART1_DMA_RXBUFSIZE,
+	       .rx_threshold = UART1_UFCR_RXTL,
+	       .tx_threshold = UART1_UFCR_TXTL,
+	       .shared = UART1_SHARED_PERI,
+	       .dma_tx_id = MXC_DMA_UART1_TX,
+	       .dma_rx_id = MXC_DMA_UART1_RX,
+	       .rxd_mux = MXC_UART_RXDMUX,
+	       },
+	[1] = {
+	       .port = {
+			.membase = (void *)IO_ADDRESS(UART2_BASE_ADDR),
+			.mapbase = UART2_BASE_ADDR,
+			.iotype = SERIAL_IO_MEM,
+			.irq = UART2_INT1,
+			.fifosize = 32,
+			.flags = ASYNC_BOOT_AUTOCONF,
+			.line = 1,
+		},
+	       .ints_muxed = UART2_MUX_INTS,
+	       .irqs = {UART2_INT2, UART2_INT3},
+	       .mode = UART2_MODE,
+	       .ir_mode = UART2_IR,
+	       .enabled = UART2_ENABLED,
+	       .hardware_flow = UART2_HW_FLOW,
+	       .cts_threshold = UART2_UCR4_CTSTL,
+	       .dma_enabled = UART2_DMA_ENABLE,
+	       .dma_rxbuf_size = UART2_DMA_RXBUFSIZE,
+	       .rx_threshold = UART2_UFCR_RXTL,
+	       .tx_threshold = UART2_UFCR_TXTL,
+	       .shared = UART2_SHARED_PERI,
+	       .dma_tx_id = MXC_DMA_UART2_TX,
+	       .dma_rx_id = MXC_DMA_UART2_RX,
+	       .rxd_mux = MXC_UART_RXDMUX,
+	       },
+	[2] = {
+	       .port = {
+			.membase = (void *)IO_ADDRESS(UART3_BASE_ADDR),
+			.mapbase = UART3_BASE_ADDR,
+			.iotype = SERIAL_IO_MEM,
+			.irq = UART3_INT1,
+			.fifosize = 32,
+			.flags = ASYNC_BOOT_AUTOCONF,
+			.line = 2,
+		},
+	       .ints_muxed = UART3_MUX_INTS,
+	       .irqs = {UART3_INT2, UART3_INT3},
+	       .mode = UART3_MODE,
+	       .ir_mode = UART3_IR,
+	       .enabled = UART3_ENABLED,
+	       .hardware_flow = UART3_HW_FLOW,
+	       .cts_threshold = UART3_UCR4_CTSTL,
+	       .dma_enabled = UART3_DMA_ENABLE,
+	       .dma_rxbuf_size = UART3_DMA_RXBUFSIZE,
+	       .rx_threshold = UART3_UFCR_RXTL,
+	       .tx_threshold = UART3_UFCR_TXTL,
+	       .shared = UART3_SHARED_PERI,
+	       .dma_tx_id = MXC_DMA_UART3_TX,
+	       .dma_rx_id = MXC_DMA_UART3_RX,
+	       .rxd_mux = MXC_UART_IR_RXDMUX,
+	       },
+	[3] = {
+	       .port = {
+			.membase = (void *)IO_ADDRESS(UART4_BASE_ADDR),
+			.mapbase = UART4_BASE_ADDR,
+			.iotype = SERIAL_IO_MEM,
+			.irq = UART4_INT1,
+			.fifosize = 32,
+			.flags = ASYNC_BOOT_AUTOCONF,
+			.line = 3,
+		},
+	       .ints_muxed = UART4_MUX_INTS,
+	       .irqs = {UART4_INT2, UART4_INT3},
+	       .mode = UART4_MODE,
+	       .ir_mode = UART4_IR,
+	       .enabled = UART4_ENABLED,
+	       .hardware_flow = UART4_HW_FLOW,
+	       .cts_threshold = UART4_UCR4_CTSTL,
+	       .dma_enabled = UART4_DMA_ENABLE,
+	       .dma_rxbuf_size = UART4_DMA_RXBUFSIZE,
+	       .rx_threshold = UART4_UFCR_RXTL,
+	       .tx_threshold = UART4_UFCR_TXTL,
+	       .shared = UART4_SHARED_PERI,
+	       .dma_tx_id = MXC_DMA_UART4_TX,
+	       .dma_rx_id = MXC_DMA_UART4_RX,
+	       .rxd_mux = MXC_UART_RXDMUX,
+	       },
+	[4] = {
+	       .port = {
+			.membase = (void *)IO_ADDRESS(UART5_BASE_ADDR),
+			.mapbase = UART5_BASE_ADDR,
+			.iotype = SERIAL_IO_MEM,
+			.irq = UART5_INT1,
+			.fifosize = 32,
+			.flags = ASYNC_BOOT_AUTOCONF,
+			.line = 4,
+		},
+	       .ints_muxed = UART5_MUX_INTS,
+	       .irqs = {UART5_INT2, UART5_INT3},
+	       .mode = UART5_MODE,
+	       .ir_mode = UART5_IR,
+	       .enabled = UART5_ENABLED,
+	       .hardware_flow = UART5_HW_FLOW,
+	       .cts_threshold = UART5_UCR4_CTSTL,
+	       .dma_enabled = UART5_DMA_ENABLE,
+	       .dma_rxbuf_size = UART5_DMA_RXBUFSIZE,
+	       .rx_threshold = UART5_UFCR_RXTL,
+	       .tx_threshold = UART5_UFCR_TXTL,
+	       .shared = UART5_SHARED_PERI,
+	       .dma_tx_id = MXC_DMA_UART5_TX,
+	       .dma_rx_id = MXC_DMA_UART5_RX,
+	       .rxd_mux = MXC_UART_RXDMUX,
+	       },
+	[5] = {
+	       .port = {
+			.membase = (void *)IO_ADDRESS(UART6_BASE_ADDR),
+			.mapbase = UART6_BASE_ADDR,
+			.iotype = SERIAL_IO_MEM,
+			.irq = UART6_INT1,
+			.fifosize = 32,
+			.flags = ASYNC_BOOT_AUTOCONF,
+			.line = 5,
+		},
+	       .ints_muxed = UART6_MUX_INTS,
+	       .irqs = {UART6_INT2, UART6_INT3},
+	       .mode = UART6_MODE,
+	       .ir_mode = UART6_IR,
+	       .enabled = UART6_ENABLED,
+	       .hardware_flow = UART6_HW_FLOW,
+	       .cts_threshold = UART6_UCR4_CTSTL,
+	       .dma_enabled = UART6_DMA_ENABLE,
+	       .dma_rxbuf_size = UART6_DMA_RXBUFSIZE,
+	       .rx_threshold = UART6_UFCR_RXTL,
+	       .tx_threshold = UART6_UFCR_TXTL,
+	       .shared = UART6_SHARED_PERI,
+	       .dma_tx_id = MXC_DMA_UART6_TX,
+	       .dma_rx_id = MXC_DMA_UART6_RX,
+	       .rxd_mux = MXC_UART_RXDMUX,
+	       },
+};
+
+static struct resource uart0 = {
+	.start = UART1_BASE_ADDR,
+	.end = UART1_BASE_ADDR + 0x0B5,
+	.flags = IORESOURCE_MEM
+};
+
+static struct platform_device mxc_uart_device0 = {
+	.name = "mxcintuart",
+	.id = 0,
+	.resource = &uart0,
+	.num_resources = 1,
+	.dev = {
+		.platform_data = &mxc_ports[0],
+	},
+};
+
+static struct resource uart1 = {
+	.start = UART2_BASE_ADDR,
+	.end = UART2_BASE_ADDR + 0x0B5,
+	.flags = IORESOURCE_MEM
+};
+
+static struct platform_device mxc_uart_device1 = {
+	.name = "mxcintuart",
+	.id = 1,
+	.resource = &uart1,
+	.num_resources = 1,
+	.dev = {
+		.platform_data = &mxc_ports[1],
+	},
+};
+
+static struct resource uart2 = {
+	.start = UART3_BASE_ADDR,
+	.end = UART3_BASE_ADDR + 0x0B5,
+	.flags = IORESOURCE_MEM
+};
+
+static struct platform_device mxc_uart_device2 = {
+	.name = "mxcintuart",
+	.id = 2,
+	.resource = &uart2,
+	.num_resources = 1,
+	.dev = {
+		.platform_data = &mxc_ports[2],
+	},
+};
+
+static struct resource uart3 = {
+	.start = UART4_BASE_ADDR,
+	.end = UART4_BASE_ADDR + 0x0B5,
+	.flags = IORESOURCE_MEM
+};
+
+static struct platform_device mxc_uart_device3 = {
+	.name = "mxcintuart",
+	.id = 3,
+	.resource = &uart3,
+	.num_resources = 1,
+	.dev = {
+		.platform_data = &mxc_ports[3],
+	},
+};
+
+static struct resource uart4 = {
+	.start = UART5_BASE_ADDR,
+	.end = UART5_BASE_ADDR + 0x0B5,
+	.flags = IORESOURCE_MEM
+};
+
+static struct platform_device mxc_uart_device4 = {
+	.name = "mxcintuart",
+	.id = 4,
+	.resource = &uart4,
+	.num_resources = 1,
+	.dev = {
+		.platform_data = &mxc_ports[4],
+	},
+};
+
+static struct resource uart5 = {
+	.start = UART6_BASE_ADDR,
+	.end = UART6_BASE_ADDR + 0x0B5,
+	.flags = IORESOURCE_MEM
+};
+
+static struct platform_device mxc_uart_device5 = {
+	.name = "mxcintuart",
+	.id = 5,
+	.resource = &uart5,
+	.num_resources = 1,
+	.dev = {
+		.platform_data = &mxc_ports[5],
+	},
+};
+
+/*
+ * Register only those UARTs that physically exists
+ */
+int __init mxc_init_uart(int uart_no)
+{
+	switch (uart_no) {
+	case 0:
+		platform_device_register(&mxc_uart_device0);
+		break;
+	case 1:
+		platform_device_register(&mxc_uart_device1);
+		break;
+#ifndef CONFIG_MXC_IRDA
+	case 2:
+		platform_device_register(&mxc_uart_device2);
+		break;
+#endif
+	case 3:
+		platform_device_register(&mxc_uart_device3);
+		break;
+	case 4:
+		platform_device_register(&mxc_uart_device4);
+		break;
+	case 5:
+		platform_device_register(&mxc_uart_device5);
+		break;
+	default:
+		return -ENODEV;
+	}
+
+	return 0;
+}
Index: arch/arm/plat-mxc/Kconfig
===================================================================
--- arch/arm/plat-mxc/Kconfig.orig
+++ arch/arm/plat-mxc/Kconfig
@@ -18,6 +18,7 @@ config ARCH_MX3
 
 endchoice
 
+source "arch/arm/mach-mx2/Kconfig"
 source "arch/arm/mach-mx3/Kconfig"
 
 endmenu
Index: include/asm-arm/arch-mxc/hardware.h
===================================================================
--- include/asm-arm/arch-mxc/hardware.h.orig
+++ include/asm-arm/arch-mxc/hardware.h
@@ -52,6 +52,28 @@
 #define cpu_is_mx31()		(0)
 #endif
 
+#ifdef CONFIG_ARCH_MX2
+# ifdef CONFIG_MACH_MX27
+#  include <asm/arch/mx27.h>
+#  define cpu_is_mx27()		(1)
+# else
+#  define cpu_is_mx27()		(0)
+# endif
+#else
+# define cpu_is_mx27()		(0)
+#endif
+
+/*
+ * device <-> GPIO handling used in all i.MX drivers.
+ * Implementation is platform specific.
+ */
+#ifndef __ASSEMBLY__
+extern void gpio_uart_active(int, int);
+extern void gpio_uart_inactive(int, int);
+extern void gpio_fec_active(void);
+extern void gpio_fec_inactive(void);
+#endif
+
 #if !defined(__ASSEMBLY__) && !defined(__MXC_BOOT_UNCOMPRESS)
 extern unsigned int system_rev;
 #define _is_rev(rev) ((system_rev == rev) ? 1 : ((system_rev < rev) ? -1 : 2))
@@ -72,6 +94,7 @@ static inline int type## _rev (int rev)	
  *	 2 - cpu matches, but cpu revision is greater than queried rev
  *	-1 - cpu matches, but cpu revision is less than queried rev
  */
+MXC_REV(cpu_is_mx27);
 MXC_REV(cpu_is_mx31);
 #endif
 
Index: arch/arm/mach-mx2/devices.h
===================================================================
--- /dev/null
+++ arch/arm/mach-mx2/devices.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) 2008 by Juergen Beisert <kernel@pengutronix.de>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+extern int __init mxc_init_uart(int);
