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

This patch adds basic mach support for the mx2 processor family, based
on the original freescale code and adapted to mainline kernel coding
style.

TODO:

 - split into i.MX21/i.MX27 specific parts
 - 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           |   11 
 arch/arm/mach-mx2/Makefile          |    9 
 arch/arm/mach-mx2/Makefile.boot     |    3 
 arch/arm/mach-mx2/clock.c           | 1556 ++++++++++++++++++++++++++++++++++++
 arch/arm/mach-mx2/cpu_imx27.c       |   62 +
 arch/arm/mach-mx2/crm_regs.h        |  272 ++++++
 arch/arm/mach-mx2/dma.c             |  503 +++++++++++
 arch/arm/mach-mx2/generic.c         |   74 +
 arch/arm/mach-mx2/serial.c          |  308 +++++++
 arch/arm/mach-mx2/serial.h          |  170 +++
 arch/arm/mach-mx2/system.c          |   62 +
 arch/arm/mm/Kconfig                 |    4 
 arch/arm/plat-mxc/Kconfig           |    1 
 include/asm-arm/arch-mxc/hardware.h |    3 
 include/asm-arm/arch-mxc/mxc.h      |    3 
 16 files changed, 3040 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
 
 ifeq ($(CONFIG_ARCH_EBSA110),y)
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_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_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_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_NS9XXX || ARCH_DAVINCI || ARCH_MX2
 	select CPU_32v5
 	select CPU_ABRT_EV5TJ
 	select CPU_CACHE_VIVT
Index: arch/arm/mach-mx2/cpu_imx27.c
===================================================================
--- /dev/null
+++ arch/arm/mach-mx2/cpu_imx27.c
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2007 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2008 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.
+ */
+
+/*
+ * i.MX27 specific CPU detection code
+ */
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include "crm_regs.h"
+
+static int cpu_silicon_rev = -1;
+static int cpu_partnumber;
+
+static void query_silicon_parameter(void)
+{
+	u32 val;
+	/*
+	 * now we have access to the IO registers. As we need
+	 * the silicon revision very early we read it here to
+	 * avoid any further hooks
+	*/
+	val = __raw_readl(IO_ADDRESS(SYSCTRL_BASE_ADDR) + SYS_CHIP_ID);
+
+	cpu_silicon_rev = (int)(val >> 28);
+	cpu_partnumber = (int)((val >> 12) & 0xFFFF);
+}
+
+/*
+ * Create inline functions to test for cpu revision
+ * Function name is cpu_is_<cpu name>_rev(rev)
+ *
+ * Returns:
+ *	 0 - not the cpu queried
+ *	 1 - cpu and revision match
+ *	 2 - cpu matches, but cpu revision is greater than queried rev
+ *	-1 - cpu matches, but cpu revision is less than queried rev
+ */
+int cpu_is_mx27_rev(int test_rev)
+{
+	if (cpu_silicon_rev == -1)
+		query_silicon_parameter();
+
+	if (cpu_partnumber != 0x8821)
+		return 0;
+
+	return test_rev == cpu_silicon_rev ? 1 : test_rev < cpu_silicon_rev ? -1 : 2;
+}
Index: arch/arm/mach-mx2/clock.c
===================================================================
--- /dev/null
+++ arch/arm/mach-mx2/clock.c
@@ -0,0 +1,1556 @@
+/*
+ * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2008 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.
+ */
+
+#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"
+
+/* TODO find a header file for it */
+extern void propagate_rate(struct clk *tclk);
+
+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
+	 */
+
+	if (cpu_is_mx27_rev(CHIP_REV_2_0) == 1 && clk->id == 1)
+		clk->rate = 2 * clk->parent->rate / 3;
+	else
+		clk->rate = clk->parent->rate;
+}
+
+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;
+}
+
+/*
+ * the high frequency external clock reference
+ * Default case is 26MHz. Could be changed at runtime
+ * with a call to change_external_high_reference()
+ */
+static struct clk ckih_clk = {
+	.name = "ckih",
+	.rate = 26000000,
+	.flags = RATE_PROPAGATES,
+};
+
+/*
+ * the low frequency external clock reference
+ * Default case is 32.768kHz Could be changed at runtime
+ * with a call to change_external_low_reference()
+ */
+static struct clk ckil_clk = {
+	.name = "ckil",
+	.rate = 32768,
+	.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,
+};
+
+void __init change_external_high_reference(unsigned long new_ref)
+{
+	ckih_clk.rate = new_ref;
+}
+
+void __init change_external_low_reference(unsigned long new_ref)
+{
+	ckih_clk.rate = new_ref;
+}
+
+unsigned long __init clk_early_get_timer_rate(void)
+{
+	return per_clk[0].rate;
+}
+
+static void __init 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;
+	}
+}
+
+/*
+ * must be called very early to get information about the
+ * available clock rate when the timer framework starts
+ */
+int __init mxc_clocks_init(void)
+{
+	u32 cscr;
+	struct clk **clkp;
+
+	/* detect clock reference for both system PLL */
+	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;
+	}
+
+	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]);
+
+	for (clkp = mxc_clks; clkp < mxc_clks + ARRAY_SIZE(mxc_clks); clkp++)
+		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);
+
+	/* 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,272 @@
+/*
+ * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2008 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.
+ */
+
+#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,503 @@
+/*
+ * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2008 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.
+ */
+
+/*
+ * 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/Kconfig
===================================================================
--- /dev/null
+++ arch/arm/mach-mx2/Kconfig
@@ -0,0 +1,11 @@
+comment "MX2 family CPU support"
+	depends on ARCH_MX2
+
+config MACH_MX27
+	bool "i.MX27 support"
+	depends on ARCH_MX2
+	help
+	  This enables support for Freescale's MX2 based i.MX27 processor.
+
+comment "MX2 Platforms"
+	depends on ARCH_MX2
Index: arch/arm/mach-mx2/Makefile
===================================================================
--- /dev/null
+++ arch/arm/mach-mx2/Makefile
@@ -0,0 +1,9 @@
+#
+# Makefile for the linux kernel.
+#
+
+# Object file lists.
+
+obj-y	:=  dma.o gpio_mux.o clock.o devices.o serial.o system.o generic.o
+
+obj-$(CONFIG_MACH_MX27) += cpu_imx27.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/system.c
===================================================================
--- /dev/null
+++ arch/arm/mach-mx2/system.c
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 1999 ARM Limited
+ * Copyright (C) 2000 Deep Blue Solutions Ltd
+ * Copyright 2006-2007 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2008 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/kernel.h>
+#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");
+	if (!clk) {
+		printk("Cannot activate the watchdog. Giving up\n");
+		return;
+	}
+
+	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,170 @@
+/*
+ * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2008 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.
+ */
+
+#ifndef __ARCH_ARM_MACH_MX2_SERIAL_H__
+#define __ARCH_ARM_MACH_MX2_SERIAL_H__
+
+#include <asm/arch/imx_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,308 @@
+/*
+ * Copyright 2006-2007 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2008 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.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/serial.h>
+#include <asm/hardware.h>
+#include <asm/arch/imx_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 struct 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},
+	       .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},
+	       .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},
+	       .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},
+	       .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},
+	       .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},
+	       .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, unsigned int flags,
+	int (*init)(struct platform_device *pdev),
+	int (*exit)(struct platform_device *pdev))
+{
+	mxc_ports[uart_no].flags = flags;
+	mxc_ports[uart_no].init = init;
+	mxc_ports[uart_no].exit = exit;
+
+	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
@@ -26,6 +26,9 @@
 #endif
 
 #ifdef CONFIG_ARCH_MX2
+# ifdef CONFIG_MACH_MX27
+#  include <asm/arch/mx27.h>
+# endif
 #endif
 
 #include <asm/arch/mxc.h>
Index: arch/arm/mach-mx2/generic.c
===================================================================
--- /dev/null
+++ arch/arm/mach-mx2/generic.c
@@ -0,0 +1,74 @@
+/*
+ * generic.c
+ *
+ * Copyright (C) 2008 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.
+ */
+
+#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 = {
+	/*
+	 * this fixed mapping covers:
+	 * - AIPI1
+	 * - AIPI2
+	 * - AITC
+	 * - ROM Patch
+	 * - and some reserved space
+	 */
+	{
+		.virtual = AIPI_BASE_ADDR_VIRT,
+		.pfn = __phys_to_pfn(AIPI_BASE_ADDR),
+		.length = AIPI_SIZE,
+		.type = MT_DEVICE
+	},
+	/*
+	 * this fixed mapping covers:
+	 * - CSI
+	 * - ATA
+	 */
+	{
+		.virtual = SAHB1_BASE_ADDR_VIRT,
+		.pfn = __phys_to_pfn(SAHB1_BASE_ADDR),
+		.length = SAHB1_SIZE,
+		.type = MT_DEVICE
+	},
+	/*
+	 * this fixed mapping covers:
+	 * - EMI
+	 */
+	{
+		.virtual = X_MEMC_BASE_ADDR_VIRT,
+		.pfn = __phys_to_pfn(X_MEMC_BASE_ADDR),
+		.length = X_MEMC_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 imx_map_io(void)
+{
+	iotable_init(mxc_io_desc, ARRAY_SIZE(mxc_io_desc));
+
+}
Index: include/asm-arm/arch-mxc/mxc.h
===================================================================
--- include/asm-arm/arch-mxc/mxc.h.orig
+++ include/asm-arm/arch-mxc/mxc.h
@@ -29,6 +29,9 @@
 #endif
 
 #ifdef CONFIG_ARCH_MX2
+# ifndef CONFIG_MACH_MX27
+#  define cpu_is_mx27() (0)
+# endif
 #endif
 
 /*
