Add i.MX25 support

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index c877d6d..95ba3c5 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -135,6 +135,7 @@
 machine-$(CONFIG_ARCH_MV78XX0)		:= mv78xx0
 machine-$(CONFIG_ARCH_MX1)		:= mx1
 machine-$(CONFIG_ARCH_MX2)		:= mx2
+machine-$(CONFIG_ARCH_MX25)		:= mx25
 machine-$(CONFIG_ARCH_MX3)		:= mx3
 machine-$(CONFIG_ARCH_NETX)		:= netx
 machine-$(CONFIG_ARCH_NS9XXX)		:= ns9xxx
diff --git a/arch/arm/mach-mx25/Kconfig b/arch/arm/mach-mx25/Kconfig
new file mode 100644
index 0000000..14c918b
--- /dev/null
+++ b/arch/arm/mach-mx25/Kconfig
@@ -0,0 +1,5 @@
+if ARCH_MX25
+
+comment "MX25 platforms:"
+
+endif
diff --git a/arch/arm/mach-mx25/Makefile b/arch/arm/mach-mx25/Makefile
new file mode 100644
index 0000000..5471086
--- /dev/null
+++ b/arch/arm/mach-mx25/Makefile
@@ -0,0 +1,2 @@
+obj-y				:= mm.o devices.o
+obj-$(CONFIG_ARCH_MX25)		+= clock.o
diff --git a/arch/arm/mach-mx25/Makefile.boot b/arch/arm/mach-mx25/Makefile.boot
new file mode 100644
index 0000000..e1dd366
--- /dev/null
+++ b/arch/arm/mach-mx25/Makefile.boot
@@ -0,0 +1,3 @@
+   zreladdr-y	:= 0x80008000
+params_phys-y	:= 0x80000100
+initrd_phys-y	:= 0x80800000
diff --git a/arch/arm/mach-mx25/clock.c b/arch/arm/mach-mx25/clock.c
new file mode 100644
index 0000000..ef26951
--- /dev/null
+++ b/arch/arm/mach-mx25/clock.c
@@ -0,0 +1,219 @@
+/*
+ * Copyright (C) 2009 by Sascha Hauer, Pengutronix
+ *
+ * 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/kernel.h>
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+
+#include <asm/clkdev.h>
+
+#include <mach/clock.h>
+#include <mach/hardware.h>
+#include <mach/common.h>
+#include <mach/mx25.h>
+
+#define CRM_BASE	MX25_IO_ADDRESS(MX25_CRM_BASE_ADDR)
+
+#define CCM_MPCTL	0x00
+#define CCM_UPCTL	0x04
+#define CCM_CCTL	0x08
+#define CCM_CGCR0	0x0C
+#define CCM_CGCR1	0x10
+#define CCM_CGCR2	0x14
+#define CCM_PCDR0	0x18
+#define CCM_PCDR1	0x1C
+#define CCM_PCDR2	0x20
+#define CCM_PCDR3	0x24
+#define CCM_RCSR	0x28
+#define CCM_CRDR	0x2C
+#define CCM_DCVR0	0x30
+#define CCM_DCVR1	0x34
+#define CCM_DCVR2	0x38
+#define CCM_DCVR3	0x3c
+#define CCM_LTR0	0x40
+#define CCM_LTR1	0x44
+#define CCM_LTR2	0x48
+#define CCM_LTR3	0x4c
+
+static unsigned long get_rate_mpll(void)
+{
+	ulong mpctl = __raw_readl(CRM_BASE + CCM_MPCTL);
+
+	return mxc_decode_pll(mpctl, 24000000);
+}
+
+static unsigned long get_rate_upll(void)
+{
+	ulong mpctl = __raw_readl(CRM_BASE + CCM_UPCTL);
+
+	return mxc_decode_pll(mpctl, 24000000);
+}
+
+unsigned long get_rate_arm(struct clk *clk)
+{
+	unsigned long cctl = readl(CRM_BASE + CCM_CCTL);
+	unsigned long rate = get_rate_mpll();
+
+	if (cctl & (1 << 14))
+		rate = (rate * 3) >> 1;
+
+	return rate / ((cctl >> 30) + 1);
+}
+
+static unsigned long get_rate_ahb(struct clk *clk)
+{
+	unsigned long cctl = readl(CRM_BASE + CCM_CCTL);
+
+	return get_rate_arm(NULL) / (((cctl >> 28) & 0x3) + 1);
+}
+
+static unsigned long get_rate_ipg(struct clk *clk)
+{
+	return get_rate_ahb(NULL) >> 1;
+}
+
+static unsigned long get_rate_per(int per)
+{
+	unsigned long ofs = (per & 0x3) * 8;
+	unsigned long reg = per & ~0x3;
+	unsigned long val = (readl(CRM_BASE + CCM_PCDR0 + reg) >> ofs) & 0x3f;
+	unsigned long fref;
+
+	if (readl(CRM_BASE + 0x64) & (1 << per))
+		fref = get_rate_upll();
+	else
+		fref = get_rate_ipg(NULL);
+
+	return fref / (val + 1);
+}
+
+static unsigned long get_rate_uart(struct clk *clk)
+{
+	return get_rate_per(15);
+}
+
+static unsigned long get_rate_i2c(struct clk *clk)
+{
+	return get_rate_per(6);
+}
+
+static unsigned long get_rate_nfc(struct clk *clk)
+{
+	return get_rate_per(8);
+}
+
+static unsigned long get_rate_otg(struct clk *clk)
+{
+	return 48000000; /* FIXME */
+}
+
+static int clk_cgcr_enable(struct clk *clk)
+{
+	u32 reg;
+
+	reg = __raw_readl(clk->enable_reg);
+	reg |= 1 << clk->enable_shift;
+	__raw_writel(reg, clk->enable_reg);
+
+	return 0;
+}
+
+static void clk_cgcr_disable(struct clk *clk)
+{
+	u32 reg;
+
+	reg = __raw_readl(clk->enable_reg);
+	reg &= ~(1 << clk->enable_shift);
+	__raw_writel(reg, clk->enable_reg);
+}
+
+#define DEFINE_CLOCK(name, i, er, es, gr, sr)		\
+	static struct clk name = {			\
+		.id		= i,			\
+		.enable_reg	= CRM_BASE + er,	\
+		.enable_shift	= es,			\
+		.get_rate	= gr,			\
+		.set_rate	= sr,			\
+		.enable		= clk_cgcr_enable,	\
+		.disable	= clk_cgcr_disable,	\
+	}
+
+DEFINE_CLOCK(gpt_clk,    0, CCM_CGCR0,  5, get_rate_ipg, NULL);
+DEFINE_CLOCK(cspi1_clk,  0, CCM_CGCR1,  5, get_rate_ipg, NULL);
+DEFINE_CLOCK(cspi2_clk,  0, CCM_CGCR1,  6, get_rate_ipg, NULL);
+DEFINE_CLOCK(cspi3_clk,  0, CCM_CGCR1,  7, get_rate_ipg, NULL);
+DEFINE_CLOCK(uart1_clk,  0, CCM_CGCR2, 14, get_rate_uart, NULL);
+DEFINE_CLOCK(uart2_clk,  0, CCM_CGCR2, 15, get_rate_uart, NULL);
+DEFINE_CLOCK(uart3_clk,  0, CCM_CGCR2, 16, get_rate_uart, NULL);
+DEFINE_CLOCK(uart4_clk,  0, CCM_CGCR2, 17, get_rate_uart, NULL);
+DEFINE_CLOCK(uart5_clk,  0, CCM_CGCR2, 18, get_rate_uart, NULL);
+DEFINE_CLOCK(nfc_clk,    0, CCM_CGCR0,  8, get_rate_nfc, NULL);
+DEFINE_CLOCK(usbotg_clk, 0, CCM_CGCR0, 28, get_rate_otg, NULL);
+DEFINE_CLOCK(pwm1_clk,	 0, CCM_CGCR1, 31, get_rate_ipg, NULL);
+DEFINE_CLOCK(pwm2_clk,	 0, CCM_CGCR2,  0, get_rate_ipg, NULL);
+DEFINE_CLOCK(pwm3_clk,	 0, CCM_CGCR2,  1, get_rate_ipg, NULL);
+DEFINE_CLOCK(pwm4_clk,	 0, CCM_CGCR2,  2, get_rate_ipg, NULL);
+DEFINE_CLOCK(kpp_clk,	 0, CCM_CGCR1, 28, get_rate_ipg, NULL);
+DEFINE_CLOCK(tsc_clk,	 0, CCM_CGCR2, 13, get_rate_ipg, NULL);
+DEFINE_CLOCK(i2c_clk,	 0, CCM_CGCR0,  6, get_rate_i2c, NULL);
+
+#define _REGISTER_CLOCK(d, n, c)	\
+	{				\
+		.dev_id = d,		\
+		.con_id = n,		\
+		.clk = &c,		\
+	},
+
+static struct clk_lookup lookups[] = {
+	_REGISTER_CLOCK("imx-uart.0", NULL, uart1_clk)
+	_REGISTER_CLOCK("imx-uart.1", NULL, uart2_clk)
+	_REGISTER_CLOCK("imx-uart.2", NULL, uart3_clk)
+	_REGISTER_CLOCK("imx-uart.3", NULL, uart4_clk)
+	_REGISTER_CLOCK("imx-uart.4", NULL, uart5_clk)
+	_REGISTER_CLOCK("mxc-ehci.0", "usb", usbotg_clk)
+	_REGISTER_CLOCK("mxc-ehci.1", "usb", usbotg_clk)
+	_REGISTER_CLOCK("mxc-ehci.2", "usb", usbotg_clk)
+	_REGISTER_CLOCK("fsl-usb2-udc", "usb", usbotg_clk)
+	_REGISTER_CLOCK("mxc_nand.0", NULL, nfc_clk)
+	_REGISTER_CLOCK("spi_imx.0", NULL, cspi1_clk)
+	_REGISTER_CLOCK("spi_imx.1", NULL, cspi2_clk)
+	_REGISTER_CLOCK("spi_imx.2", NULL, cspi3_clk)
+	_REGISTER_CLOCK("mxc_pwm.0", NULL, pwm1_clk)
+	_REGISTER_CLOCK("mxc_pwm.1", NULL, pwm2_clk)
+	_REGISTER_CLOCK("mxc_pwm.2", NULL, pwm3_clk)
+	_REGISTER_CLOCK("mxc_pwm.3", NULL, pwm4_clk)
+	_REGISTER_CLOCK("mxc-keypad", NULL, kpp_clk)
+	_REGISTER_CLOCK("mx25-adc", NULL, tsc_clk)
+	_REGISTER_CLOCK("imx-i2c.0", NULL, i2c_clk)
+	_REGISTER_CLOCK("imx-i2c.1", NULL, i2c_clk)
+	_REGISTER_CLOCK("imx-i2c.2", NULL, i2c_clk)
+};
+
+int __init mx25_clocks_init(unsigned long fref)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(lookups); i++)
+		clkdev_add(&lookups[i]);
+
+	mxc_timer_init(&gpt_clk, MX25_IO_ADDRESS(MX25_GPT1_BASE_ADDR), 54);
+
+	return 0;
+}
diff --git a/arch/arm/mach-mx25/devices.c b/arch/arm/mach-mx25/devices.c
new file mode 100644
index 0000000..eb12de1
--- /dev/null
+++ b/arch/arm/mach-mx25/devices.c
@@ -0,0 +1,402 @@
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+#include <mach/mx25.h>
+#include <mach/irqs.h>
+
+static struct resource uart0[] = {
+	{
+		.start = 0x43f90000,
+		.end = 0x43f93fff,
+		.flags = IORESOURCE_MEM,
+	}, {
+		.start = 45,
+		.end = 45,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+struct platform_device mxc_uart_device0 = {
+	.name = "imx-uart",
+	.id = 0,
+	.resource = uart0,
+	.num_resources = ARRAY_SIZE(uart0),
+};
+
+static struct resource uart1[] = {
+	{
+		.start = 0x43f94000,
+		.end = 0x43f97fff,
+		.flags = IORESOURCE_MEM,
+	}, {
+		.start = 32,
+		.end = 32,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+struct platform_device mxc_uart_device1 = {
+	.name = "imx-uart",
+	.id = 1,
+	.resource = uart1,
+	.num_resources = ARRAY_SIZE(uart1),
+};
+
+static struct resource uart2[] = {
+	{
+		.start = 0x5000c000,
+		.end = 0x5000ffff,
+		.flags = IORESOURCE_MEM,
+	}, {
+		.start = 18,
+		.end = 18,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+struct platform_device mxc_uart_device2 = {
+	.name = "imx-uart",
+	.id = 2,
+	.resource = uart2,
+	.num_resources = ARRAY_SIZE(uart2),
+};
+
+static struct resource uart3[] = {
+	{
+		.start = 0x50008000,
+		.end = 0x5000bfff,
+		.flags = IORESOURCE_MEM,
+	}, {
+		.start = 5,
+		.end = 5,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+struct platform_device mxc_uart_device3 = {
+	.name = "imx-uart",
+	.id = 3,
+	.resource = uart3,
+	.num_resources = ARRAY_SIZE(uart3),
+};
+
+static struct resource uart4[] = {
+	{
+		.start = 0x5002c000,
+		.end = 0x5002ffff,
+		.flags = IORESOURCE_MEM,
+	}, {
+		.start = 40,
+		.end = 40,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+struct platform_device mxc_uart_device4 = {
+	.name = "imx-uart",
+	.id = 4,
+	.resource = uart4,
+	.num_resources = ARRAY_SIZE(uart4),
+};
+
+#define MX25_OTG_BASE_ADDR 0x53FF4000
+
+static u64 otg_dmamask = DMA_BIT_MASK(32);
+
+static struct resource mxc_otg_resources[] = {
+	{
+		.start = MX25_OTG_BASE_ADDR,
+		.end = MX25_OTG_BASE_ADDR + 0x1ff,
+		.flags = IORESOURCE_MEM,
+	}, {
+		.start = 37,
+		.end = 37,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+struct platform_device mxc_otg = {
+	.name = "mxc-ehci",
+	.id = 0,
+	.dev = {
+		.coherent_dma_mask = 0xffffffff,
+		.dma_mask = &otg_dmamask,
+	},
+	.resource = mxc_otg_resources,
+	.num_resources = ARRAY_SIZE(mxc_otg_resources),
+};
+
+/* OTG gadget device */
+struct platform_device otg_udc_device = {
+	.name = "fsl-usb2-udc",
+	.id   = -1,
+	.dev  = {
+		.dma_mask          = &otg_dmamask,
+		.coherent_dma_mask = 0xffffffff,
+	},
+	.resource = mxc_otg_resources,
+	.num_resources = ARRAY_SIZE(mxc_otg_resources),
+};
+
+static u64 usbh2_dmamask = DMA_BIT_MASK(32);
+
+static struct resource mxc_usbh2_resources[] = {
+	{
+		.start = MX25_OTG_BASE_ADDR + 0x400,
+		.end = MX25_OTG_BASE_ADDR + 0x5ff,
+		.flags = IORESOURCE_MEM,
+	}, {
+		.start = 35,
+		.end = 35,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+struct platform_device mxc_usbh2 = {
+	.name = "mxc-ehci",
+	.id = 1,
+	.dev = {
+		.coherent_dma_mask = 0xffffffff,
+		.dma_mask = &usbh2_dmamask,
+	},
+	.resource = mxc_usbh2_resources,
+	.num_resources = ARRAY_SIZE(mxc_usbh2_resources),
+};
+
+static struct resource mxc_spi_resources0[] = {
+	{
+	       .start = 0x43fa4000,
+	       .end = 0x43fa7fff,
+	       .flags = IORESOURCE_MEM,
+	}, {
+	       .start = 14,
+	       .end = 14,
+	       .flags = IORESOURCE_IRQ,
+	},
+};
+
+struct platform_device mxc_spi_device0 = {
+	.name = "spi_imx",
+	.id = 0,
+	.num_resources = ARRAY_SIZE(mxc_spi_resources0),
+	.resource = mxc_spi_resources0,
+};
+
+static struct resource mxc_spi_resources1[] = {
+	{
+	       .start = 0x50010000,
+	       .end = 0x50013fff,
+	       .flags = IORESOURCE_MEM,
+	}, {
+	       .start = 13,
+	       .end = 13,
+	       .flags = IORESOURCE_IRQ,
+	},
+};
+
+struct platform_device mxc_spi_device1 = {
+	.name = "spi_imx",
+	.id = 1,
+	.num_resources = ARRAY_SIZE(mxc_spi_resources1),
+	.resource = mxc_spi_resources1,
+};
+
+static struct resource mxc_spi_resources2[] = {
+	{
+	       .start = 0x50004000,
+	       .end = 0x50007fff,
+	       .flags = IORESOURCE_MEM,
+	}, {
+	       .start = 0,
+	       .end = 0,
+	       .flags = IORESOURCE_IRQ,
+	},
+};
+
+struct platform_device mxc_spi_device2 = {
+	.name = "spi_imx",
+	.id = 2,
+	.num_resources = ARRAY_SIZE(mxc_spi_resources2),
+	.resource = mxc_spi_resources2,
+};
+
+static struct resource mxc_pwm_resources0[] = {
+	{
+		.start	= 0x53fe0000,
+		.end	= 0x53fe3fff,
+		.flags	= IORESOURCE_MEM,
+	}, {
+		.start   = 26,
+		.end     = 26,
+		.flags   = IORESOURCE_IRQ,
+	}
+};
+
+struct platform_device mxc_pwm_device0 = {
+	.name = "mxc_pwm",
+	.id = 0,
+	.num_resources = ARRAY_SIZE(mxc_pwm_resources0),
+	.resource = mxc_pwm_resources0,
+};
+
+static struct resource mxc_pwm_resources1[] = {
+	{
+		.start	= 0x53fa0000,
+		.end	= 0x53fa3fff,
+		.flags	= IORESOURCE_MEM,
+	}, {
+		.start   = 36,
+		.end     = 36,
+		.flags   = IORESOURCE_IRQ,
+	}
+};
+
+struct platform_device mxc_pwm_device1 = {
+	.name = "mxc_pwm",
+	.id = 1,
+	.num_resources = ARRAY_SIZE(mxc_pwm_resources1),
+	.resource = mxc_pwm_resources1,
+};
+
+static struct resource mxc_pwm_resources2[] = {
+	{
+		.start	= 0x53fa8000,
+		.end	= 0x53fabfff,
+		.flags	= IORESOURCE_MEM,
+	}, {
+		.start   = 41,
+		.end     = 41,
+		.flags   = IORESOURCE_IRQ,
+	}
+};
+
+struct platform_device mxc_pwm_device2 = {
+	.name = "mxc_pwm",
+	.id = 2,
+	.num_resources = ARRAY_SIZE(mxc_pwm_resources2),
+	.resource = mxc_pwm_resources2,
+};
+
+static struct resource mxc_keypad_resources[] = {
+	{
+		.start	= 0x43fa8000,
+		.end	= 0x43fabfff,
+		.flags	= IORESOURCE_MEM,
+	}, {
+		.start   = 24,
+		.end     = 24,
+		.flags   = IORESOURCE_IRQ,
+	}
+};
+
+struct platform_device mxc_keypad_device = {
+	.name = "mxc-keypad",
+	.id = -1,
+	.num_resources = ARRAY_SIZE(mxc_keypad_resources),
+	.resource = mxc_keypad_resources,
+};
+
+static struct resource mxc_pwm_resources3[] = {
+	{
+		.start	= 0x53fc8000,
+		.end	= 0x53fcbfff,
+		.flags	= IORESOURCE_MEM,
+	}, {
+		.start   = 42,
+		.end     = 42,
+		.flags   = IORESOURCE_IRQ,
+	}
+};
+
+struct platform_device mxc_pwm_device3 = {
+	.name = "mxc_pwm",
+	.id = 3,
+	.num_resources = ARRAY_SIZE(mxc_pwm_resources3),
+	.resource = mxc_pwm_resources3,
+};
+
+static struct resource mxc_i2c_1_resources[] = {
+	{
+		.start	= 0x43f80000,
+		.end	= 0x43f83fff,
+		.flags	= IORESOURCE_MEM,
+	}, {
+		.start	= 3,
+		.end	= 3,
+		.flags	= IORESOURCE_IRQ,
+	}
+};
+
+struct platform_device mxc_i2c_device0 = {
+	.name = "imx-i2c",
+	.id = 0,
+	.num_resources = ARRAY_SIZE(mxc_i2c_1_resources),
+	.resource = mxc_i2c_1_resources,
+};
+
+static struct resource mxc_i2c_2_resources[] = {
+	{
+		.start	= 0x43f98000,
+		.end	= 0x43f9bfff,
+		.flags	= IORESOURCE_MEM,
+	}, {
+		.start	= 4,
+		.end	= 4,
+		.flags	= IORESOURCE_IRQ,
+	}
+};
+
+struct platform_device mxc_i2c_device1 = {
+	.name = "imx-i2c",
+	.id = 1,
+	.num_resources = ARRAY_SIZE(mxc_i2c_2_resources),
+	.resource = mxc_i2c_2_resources,
+};
+
+static struct resource mxc_i2c_3_resources[] = {
+	{
+		.start	= 0x43f84000,
+		.end	= 0x43f87fff,
+		.flags	= IORESOURCE_MEM,
+	}, {
+		.start	= 10,
+		.end	= 10,
+		.flags	= IORESOURCE_IRQ,
+	}
+};
+
+struct platform_device mxc_i2c_device2 = {
+	.name = "imx-i2c",
+	.id = 2,
+	.num_resources = ARRAY_SIZE(mxc_i2c_3_resources),
+	.resource = mxc_i2c_3_resources,
+};
+
+static struct mxc_gpio_port imx_gpio_ports[] = {
+	{
+		.chip.label = "gpio-0",
+		.base = (void __iomem *)MX25_GPIO1_BASE_ADDR_VIRT,
+		.irq = 52,
+		.virtual_irq_start = MXC_GPIO_IRQ_START,
+	}, {
+		.chip.label = "gpio-1",
+		.base = (void __iomem *)MX25_GPIO2_BASE_ADDR_VIRT,
+		.irq = 51,
+		.virtual_irq_start = MXC_GPIO_IRQ_START + 32,
+	}, {
+		.chip.label = "gpio-2",
+		.base = (void __iomem *)MX25_GPIO3_BASE_ADDR_VIRT,
+		.irq = 16,
+		.virtual_irq_start = MXC_GPIO_IRQ_START + 64,
+	}, {
+		.chip.label = "gpio-3",
+		.base = (void __iomem *)MX25_GPIO4_BASE_ADDR_VIRT,
+		.irq = 23,
+		.virtual_irq_start = MXC_GPIO_IRQ_START + 96,
+	}
+};
+
+int __init mxc_register_gpios(void)
+{
+	return mxc_gpio_init(imx_gpio_ports, ARRAY_SIZE(imx_gpio_ports));
+}
+
diff --git a/arch/arm/mach-mx25/devices.h b/arch/arm/mach-mx25/devices.h
new file mode 100644
index 0000000..fe6bf88
--- /dev/null
+++ b/arch/arm/mach-mx25/devices.h
@@ -0,0 +1,19 @@
+extern struct platform_device mxc_uart_device0;
+extern struct platform_device mxc_uart_device1;
+extern struct platform_device mxc_uart_device2;
+extern struct platform_device mxc_uart_device3;
+extern struct platform_device mxc_uart_device4;
+extern struct platform_device mxc_otg;
+extern struct platform_device otg_udc_device;
+extern struct platform_device mxc_usbh2;
+extern struct platform_device mxc_spi_device0;
+extern struct platform_device mxc_spi_device1;
+extern struct platform_device mxc_spi_device2;
+extern struct platform_device mxc_pwm_device0;
+extern struct platform_device mxc_pwm_device1;
+extern struct platform_device mxc_pwm_device2;
+extern struct platform_device mxc_pwm_device3;
+extern struct platform_device mxc_keypad_device;
+extern struct platform_device mxc_i2c_device0;
+extern struct platform_device mxc_i2c_device1;
+extern struct platform_device mxc_i2c_device2;
diff --git a/arch/arm/mach-mx25/mm.c b/arch/arm/mach-mx25/mm.c
new file mode 100644
index 0000000..a7e587f
--- /dev/null
+++ b/arch/arm/mach-mx25/mm.c
@@ -0,0 +1,76 @@
+/*
+ *  Copyright (C) 1999,2000 Arm Limited
+ *  Copyright (C) 2000 Deep Blue Solutions Ltd
+ *  Copyright (C) 2002 Shane Nay (shane@minirl.com)
+ *  Copyright 2005-2007 Freescale Semiconductor, Inc. All Rights Reserved.
+ *    - add MX31 specific definitions
+ *
+ * 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/mm.h>
+#include <linux/init.h>
+#include <linux/err.h>
+
+#include <asm/pgtable.h>
+#include <asm/mach/map.h>
+
+#include <mach/common.h>
+#include <mach/hardware.h>
+#include <mach/mx25.h>
+#include <mach/iomux-v3.h>
+
+/*
+ * This table defines static virtual address mappings for I/O regions.
+ * These are the mappings common across all MX3 boards.
+ */
+static struct map_desc mxc_io_desc[] __initdata = {
+	{
+		.virtual	= MX25_AVIC_BASE_ADDR_VIRT,
+		.pfn		= __phys_to_pfn(MX25_AVIC_BASE_ADDR),
+		.length		= MX25_AVIC_SIZE,
+		.type		= MT_DEVICE_NONSHARED
+	}, {
+		.virtual	= MX25_AIPS1_BASE_ADDR_VIRT,
+		.pfn		= __phys_to_pfn(MX25_AIPS1_BASE_ADDR),
+		.length		= MX25_AIPS1_SIZE,
+		.type		= MT_DEVICE_NONSHARED
+	}, {
+		.virtual	= MX25_AIPS2_BASE_ADDR_VIRT,
+		.pfn		= __phys_to_pfn(MX25_AIPS2_BASE_ADDR),
+		.length		= MX25_AIPS2_SIZE,
+		.type		= MT_DEVICE_NONSHARED
+	},
+};
+
+/*
+ * This function initializes the memory map. It is called during the
+ * system startup to create static physical to virtual memory mappings
+ * for the IO modules.
+ */
+void __init mx25_map_io(void)
+{
+	mxc_set_cpu_type(MXC_CPU_MX25);
+	mxc_iomux_v3_init(MX25_IO_ADDRESS(MX25_IOMUXC_BASE_ADDR));
+	mxc_arch_reset_init(MX25_IO_ADDRESS(MX25_WDOG_BASE_ADDR));
+
+	iotable_init(mxc_io_desc, ARRAY_SIZE(mxc_io_desc));
+}
+
+void __init mx25_init_irq(void)
+{
+	mxc_init_irq((void __iomem *)MX25_AVIC_BASE_ADDR_VIRT);
+}
+
diff --git a/arch/arm/plat-mxc/Kconfig b/arch/arm/plat-mxc/Kconfig
index 0617c19..e342a2e 100644
--- a/arch/arm/plat-mxc/Kconfig
+++ b/arch/arm/plat-mxc/Kconfig
@@ -20,6 +20,13 @@
 	help
 	  This enables support for systems based on the Freescale i.MX2 family
 
+config ARCH_MX25
+	bool "MX25-based"
+	select CPU_ARM926T
+	select COMMON_CLKDEV
+	help
+	  This enables support for systems based on the Freescale i.MX25 family
+
 config ARCH_MX3
 	bool "MX3-based"
 	select CPU_V6
@@ -32,6 +39,7 @@
 source "arch/arm/mach-mx1/Kconfig"
 source "arch/arm/mach-mx2/Kconfig"
 source "arch/arm/mach-mx3/Kconfig"
+source "arch/arm/mach-mx25/Kconfig"
 
 endmenu
 
diff --git a/arch/arm/plat-mxc/gpio.c b/arch/arm/plat-mxc/gpio.c
index f0315ed..cfc4a8b 100644
--- a/arch/arm/plat-mxc/gpio.c
+++ b/arch/arm/plat-mxc/gpio.c
@@ -297,7 +297,7 @@
 		/* its a serious configuration bug when it fails */
 		BUG_ON( gpiochip_add(&port[i].chip) < 0 );
 
-		if (cpu_is_mx1() || cpu_is_mx3()) {
+		if (cpu_is_mx1() || cpu_is_mx3() || cpu_is_mx25()) {
 			/* setup one handler for each entry */
 			set_irq_chained_handler(port[i].irq, mx3_gpio_irq_handler);
 			set_irq_data(port[i].irq, &port[i]);
diff --git a/arch/arm/plat-mxc/include/mach/common.h b/arch/arm/plat-mxc/include/mach/common.h
index cd8f215..4e7af74 100644
--- a/arch/arm/plat-mxc/include/mach/common.h
+++ b/arch/arm/plat-mxc/include/mach/common.h
@@ -16,18 +16,21 @@
 
 extern void mx1_map_io(void);
 extern void mx21_map_io(void);
+extern void mx25_map_io(void);
 extern void mx27_map_io(void);
 extern void mx31_map_io(void);
 extern void mx35_map_io(void);
 extern void mxc_init_irq(void __iomem *);
 extern void mx1_init_irq(void);
 extern void mx21_init_irq(void);
+extern void mx25_init_irq(void);
 extern void mx27_init_irq(void);
 extern void mx31_init_irq(void);
 extern void mx35_init_irq(void);
 extern void mxc_timer_init(struct clk *timer_clk, void __iomem *, int);
 extern int mx1_clocks_init(unsigned long fref);
 extern int mx21_clocks_init(unsigned long lref, unsigned long fref);
+extern int mx25_clocks_init(unsigned long fref);
 extern int mx27_clocks_init(unsigned long fref);
 extern int mx31_clocks_init(unsigned long fref);
 extern int mx35_clocks_init(void);
diff --git a/arch/arm/plat-mxc/include/mach/debug-macro.S b/arch/arm/plat-mxc/include/mach/debug-macro.S
index 4f85acd..bf683de 100644
--- a/arch/arm/plat-mxc/include/mach/debug-macro.S
+++ b/arch/arm/plat-mxc/include/mach/debug-macro.S
@@ -17,6 +17,15 @@
 #define UART_VADDR	IO_ADDRESS(UART1_BASE_ADDR)
 #endif
 
+#ifdef CONFIG_ARCH_MX25
+#ifdef UART_PADDR
+#error "CONFIG_DEBUG_LL is incompatible with multiple archs"
+#endif
+#include <mach/mx25.h>
+#define UART_PADDR	UART1_BASE_ADDR
+#define UART_VADDR	MX25_AIPS1_IO_ADDRESS(UART1_BASE_ADDR)
+#endif
+
 #ifdef CONFIG_ARCH_MX2
 #ifdef UART_PADDR
 #error "CONFIG_DEBUG_LL is incompatible with multiple archs"
diff --git a/arch/arm/plat-mxc/include/mach/hardware.h b/arch/arm/plat-mxc/include/mach/hardware.h
index 42e4ee3..569af32 100644
--- a/arch/arm/plat-mxc/include/mach/hardware.h
+++ b/arch/arm/plat-mxc/include/mach/hardware.h
@@ -42,6 +42,10 @@
 # include <mach/mx1.h>
 #endif
 
+#ifdef CONFIG_ARCH_MX25
+# include <mach/mx25.h>
+#endif
+
 #include <mach/mxc.h>
 
 #endif /* __ASM_ARCH_MXC_HARDWARE_H__ */
diff --git a/arch/arm/plat-mxc/include/mach/irqs.h b/arch/arm/plat-mxc/include/mach/irqs.h
index 518a365..f39e016 100644
--- a/arch/arm/plat-mxc/include/mach/irqs.h
+++ b/arch/arm/plat-mxc/include/mach/irqs.h
@@ -24,6 +24,8 @@
 #define MXC_GPIO_IRQS		(32 * 6)
 #elif defined CONFIG_ARCH_MX3
 #define MXC_GPIO_IRQS		(32 * 3)
+#elif defined CONFIG_ARCH_MX25
+#define MXC_GPIO_IRQS		(32 * 4)
 #endif
 
 /*
diff --git a/arch/arm/plat-mxc/include/mach/memory.h b/arch/arm/plat-mxc/include/mach/memory.h
index 6065e00..42db739 100644
--- a/arch/arm/plat-mxc/include/mach/memory.h
+++ b/arch/arm/plat-mxc/include/mach/memory.h
@@ -22,6 +22,8 @@
 #endif
 #elif defined CONFIG_ARCH_MX3
 #define PHYS_OFFSET		UL(0x80000000)
+#elif defined CONFIG_ARCH_MX25
+#define PHYS_OFFSET		UL(0x80000000)
 #endif
 
 #if defined(CONFIG_MX1_VIDEO)
diff --git a/arch/arm/plat-mxc/include/mach/mx25.h b/arch/arm/plat-mxc/include/mach/mx25.h
new file mode 100644
index 0000000..ec64bd9
--- /dev/null
+++ b/arch/arm/plat-mxc/include/mach/mx25.h
@@ -0,0 +1,44 @@
+#ifndef __MACH_MX25_H__
+#define __MACH_MX25_H__
+
+#define MX25_AIPS1_BASE_ADDR		0x43F00000
+#define MX25_AIPS1_BASE_ADDR_VIRT	0xFC000000
+#define MX25_AIPS1_SIZE			SZ_1M
+#define MX25_AIPS2_BASE_ADDR		0x53F00000
+#define MX25_AIPS2_BASE_ADDR_VIRT	0xFC200000
+#define MX25_AIPS2_SIZE			SZ_1M
+#define MX25_AVIC_BASE_ADDR		0x68000000
+#define MX25_AVIC_BASE_ADDR_VIRT	0xFC400000
+#define MX25_AVIC_SIZE			SZ_1M
+
+#define MX25_IOMUXC_BASE_ADDR		(MX25_AIPS1_BASE_ADDR + 0xac000)
+
+#define MX25_CRM_BASE_ADDR		(MX25_AIPS2_BASE_ADDR + 0x80000)
+#define MX25_GPT1_BASE_ADDR		(MX25_AIPS2_BASE_ADDR + 0x90000)
+#define MX25_WDOG_BASE_ADDR		(MX25_AIPS2_BASE_ADDR + 0xdc000)
+
+#define MX25_GPIO1_BASE_ADDR_VIRT	(MX25_AIPS2_BASE_ADDR_VIRT + 0xcc000)
+#define MX25_GPIO2_BASE_ADDR_VIRT	(MX25_AIPS2_BASE_ADDR_VIRT + 0xd0000)
+#define MX25_GPIO3_BASE_ADDR_VIRT	(MX25_AIPS2_BASE_ADDR_VIRT + 0xa4000)
+#define MX25_GPIO4_BASE_ADDR_VIRT	(MX25_AIPS2_BASE_ADDR_VIRT + 0x9c000)
+
+#define MX25_AIPS1_IO_ADDRESS(x)  \
+	(((x) - MX25_AIPS1_BASE_ADDR) + MX25_AIPS1_BASE_ADDR_VIRT)
+#define MX25_AIPS2_IO_ADDRESS(x)  \
+	(((x) - MX25_AIPS2_BASE_ADDR) + MX25_AIPS2_BASE_ADDR_VIRT)
+#define MX25_AVIC_IO_ADDRESS(x)  \
+	(((x) - MX25_AVIC_BASE_ADDR) + MX25_AVIC_BASE_ADDR_VIRT)
+
+#define __in_range(addr, name)	((addr) >= name##_BASE_ADDR && (addr) < name##_BASE_ADDR + name##_SIZE)
+
+#define MX25_IO_ADDRESS(x)					\
+	(void __force __iomem *)				\
+	(__in_range(x, MX25_AIPS1) ? MX25_AIPS1_IO_ADDRESS(x) :	\
+	__in_range(x, MX25_AIPS2) ? MX25_AIPS2_IO_ADDRESS(x) :	\
+	__in_range(x, MX25_AVIC) ? MX25_AVIC_IO_ADDRESS(x) :	\
+	0xDEADBEEF)
+
+#define UART1_BASE_ADDR			0x43f90000
+#define UART2_BASE_ADDR			0x43f94000
+
+#endif /* __MACH_MX25_H__ */
diff --git a/arch/arm/plat-mxc/include/mach/mxc.h b/arch/arm/plat-mxc/include/mach/mxc.h
index 5fa2a07..882b816 100644
--- a/arch/arm/plat-mxc/include/mach/mxc.h
+++ b/arch/arm/plat-mxc/include/mach/mxc.h
@@ -26,6 +26,7 @@
 
 #define MXC_CPU_MX1		1
 #define MXC_CPU_MX21		21
+#define MXC_CPU_MX25		25
 #define MXC_CPU_MX27		27
 #define MXC_CPU_MX31		31
 #define MXC_CPU_MX35		35
@@ -58,6 +59,18 @@
 # define cpu_is_mx21()		(0)
 #endif
 
+#ifdef CONFIG_ARCH_MX25
+# ifdef mxc_cpu_type
+#  undef mxc_cpu_type
+#  define mxc_cpu_type __mxc_cpu_type
+# else
+#  define mxc_cpu_type MXC_CPU_MX25
+# endif
+# define cpu_is_mx25()		(mxc_cpu_type == MXC_CPU_MX25)
+#else
+# define cpu_is_mx25()		(0)
+#endif
+
 #ifdef CONFIG_MACH_MX27
 # ifdef mxc_cpu_type
 #  undef mxc_cpu_type
diff --git a/arch/arm/plat-mxc/include/mach/timex.h b/arch/arm/plat-mxc/include/mach/timex.h
index 07b4a73..0707b7d 100644
--- a/arch/arm/plat-mxc/include/mach/timex.h
+++ b/arch/arm/plat-mxc/include/mach/timex.h
@@ -26,6 +26,8 @@
 #define CLOCK_TICK_RATE		13300000
 #elif defined CONFIG_ARCH_MX3
 #define CLOCK_TICK_RATE		16625000
+#elif defined CONFIG_ARCH_MX25
+#define CLOCK_TICK_RATE		16000000
 #endif
 
 #endif				/* __ASM_ARCH_MXC_TIMEX_H__ */
diff --git a/arch/arm/plat-mxc/include/mach/uncompress.h b/arch/arm/plat-mxc/include/mach/uncompress.h
index 98c8a602..b6650e7 100644
--- a/arch/arm/plat-mxc/include/mach/uncompress.h
+++ b/arch/arm/plat-mxc/include/mach/uncompress.h
@@ -63,6 +63,7 @@
 #define flush() do { } while (0)
 
 #define MX1_UART1_BASE_ADDR	0x00206000
+#define MX25_UART1_BASE_ADDR	0x43f90000
 #define MX2X_UART1_BASE_ADDR	0x1000a000
 #define MX3X_UART1_BASE_ADDR	0x43F90000