Преглед изворни кода

Merge branch 'test' of ../test/linux-2.6-lpc2 into wells/lpc32xx-arch_v2

Kevin Wells пре 15 година
родитељ
комит
cccf59abea

+ 15 - 0
arch/arm/Kconfig

@@ -482,6 +482,19 @@ config ARCH_LOKI
 	help
 	  Support for the Marvell Loki (88RC8480) SoC.
 
+config ARCH_LPC32XX
+	bool "NXP LPC32XX"
+	select CPU_ARM926T
+	select ARCH_REQUIRE_GPIOLIB
+	select HAVE_IDE
+	select ARM_AMBA
+	select USB_ARCH_HAS_OHCI
+	select COMMON_CLKDEV
+	select GENERIC_TIME
+	select GENERIC_CLOCKEVENTS
+	help
+	  Support for the NXP LPC32XX family of processors
+
 config ARCH_MV78XX0
 	bool "Marvell MV78xx0"
 	select CPU_FEROCEON
@@ -845,6 +858,8 @@ source "arch/arm/mach-lh7a40x/Kconfig"
 
 source "arch/arm/mach-loki/Kconfig"
 
+source "arch/arm/mach-lpc32xx/Kconfig"
+
 source "arch/arm/mach-msm/Kconfig"
 
 source "arch/arm/mach-mv78xx0/Kconfig"

+ 1 - 0
arch/arm/Makefile

@@ -142,6 +142,7 @@ machine-$(CONFIG_ARCH_KS8695)		:= ks8695
 machine-$(CONFIG_ARCH_L7200)		:= l7200
 machine-$(CONFIG_ARCH_LH7A40X)		:= lh7a40x
 machine-$(CONFIG_ARCH_LOKI) 		:= loki
+machine-$(CONFIG_ARCH_LPC32XX)		:= lpc32xx
 machine-$(CONFIG_ARCH_MMP)		:= mmp
 machine-$(CONFIG_ARCH_MSM)		:= msm
 machine-$(CONFIG_ARCH_MV78XX0)		:= mv78xx0

+ 33 - 0
arch/arm/mach-lpc32xx/Kconfig

@@ -0,0 +1,33 @@
+if ARCH_LPC32XX
+
+menu "Individual UART enable selections"
+
+config ARCH_LPC32XX_UART3_SELECT
+	bool "Add support for standard UART3"
+	help
+	 Adds support for standard UART 3 when the 8250 serial support
+	 is enabled.
+
+config ARCH_LPC32XX_UART4_SELECT
+	bool "Add support for standard UART4"
+	help
+	 Adds support for standard UART 4 when the 8250 serial support
+	 is enabled.
+
+config ARCH_LPC32XX_UART5_SELECT
+	bool "Add support for standard UART5"
+	default y
+	help
+	 Adds support for standard UART 5 when the 8250 serial support
+	 is enabled.
+
+config ARCH_LPC32XX_UART6_SELECT
+	bool "Add support for standard UART6"
+	help
+	 Adds support for standard UART 6 when the 8250 serial support
+	 is enabled.
+
+endmenu
+
+endif
+

+ 8 - 0
arch/arm/mach-lpc32xx/Makefile

@@ -0,0 +1,8 @@
+#
+# Makefile for the linux kernel.
+#
+
+obj-y	:= timer.o irq.o common.o serial.o clock.o
+obj-y	+= gpiolib.o pm.o suspend.o
+obj-y	+= phy3250.o
+

+ 4 - 0
arch/arm/mach-lpc32xx/Makefile.boot

@@ -0,0 +1,4 @@
+   zreladdr-y	:= 0x80008000
+params_phys-y	:= 0x80000100
+initrd_phys-y	:= 0x82000000
+

+ 1137 - 0
arch/arm/mach-lpc32xx/clock.c

@@ -0,0 +1,1137 @@
+/*
+ * arch/arm/mach-lpc32xx/clock.c
+ *
+ * Author: Kevin Wells <kevin.wells@nxp.com>
+ *
+ * Copyright (C) 2010 NXP Semiconductors
+ *
+ * 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.
+ */
+
+/*
+ * LPC32xx clock management driver overview
+ *
+ * The LPC32XX contains a number of high level system clocks that can be
+ * generated from different sources. These system clocks are used to
+ * generate the CPU and bus rates and the individual peripheral clocks in
+ * the system. When Linux is started by the boot loader, the system
+ * clocks are already running. Stopping a system clock during normal
+ * Linux operation should never be attempted, as peripherals that require
+ * those clocks will quit working (ie, DRAM).
+ *
+ * The LPC32xx high level clock tree looks as follows. Clocks marked with
+ * an asterisk are always on and cannot be disabled. Clocks marked with
+ * an ampersand can only be disabled in CPU suspend mode. Clocks marked
+ * with a caret are always on if it is the selected clock for the SYSCLK
+ * source. The clock that isn't used for SYSCLK can be enabled and
+ * disabled normally.
+ *                               32KHz oscillator*
+ *                               /      |      \
+ *                             RTC*   PLL397^ TOUCH
+ *                                     /
+ *               Main oscillator^     /
+ *                   |        \      /
+ *                   |         SYSCLK&
+ *                   |            \
+ *                   |             \
+ *                USB_PLL       HCLK_PLL&
+ *                   |           |    |
+ *            USB host/device  PCLK&  |
+ *                               |    |
+ *                             Peripherals
+ *
+ * The CPU and chip bus rates are derived from the HCLK PLL, which can
+ * generate various clock rates up to 266MHz and beyond. The internal bus
+ * rates (PCLK and HCLK) are generated from dividers based on the HCLK
+ * PLL rate. HCLK can be a ratio of 1:1, 1:2, or 1:4 or HCLK PLL rate,
+ * while PCLK can be 1:1 to 1:32 of HCLK PLL rate. Most peripherals high
+ * level clocks are based on either HCLK or PCLK, but have their own
+ * dividers as part of the IP itself. Because of this, the system clock
+ * rates should not be changed.
+ *
+ * The HCLK PLL is clocked from SYSCLK, which can be derived from the
+ * main oscillator or PLL397. PLL397 generates a rate that is 397 times
+ * the 32KHz oscillator rate. The main oscillator runs at the selected
+ * oscillator/crystal rate on the mosc_in pin of the LPC32xx. This rate
+ * is normally 13MHz, but depends on the selection of external crystals
+ * or oscillators. If USB operation is required, the main oscillator must
+ * be used in the system.
+ *
+ * Switching SYSCLK between sources during normal Linux operation is not
+ * supported. SYSCLK is preset in the bootloader. Because of the
+ * complexities of clock management during clock frequency changes,
+ * there are some limitations to the clock driver explained below:
+ * - The PLL397 and main oscillator can be enabled and disabled by the
+ *   clk_enable() and clk_disable() functions unless SYSCLK is based
+ *   on that clock. This allows the other oscillator that isn't driving
+ *   the HCLK PLL to be used as another system clock that can be routed
+ *   to an external pin.
+ * - The muxed SYSCLK input and HCLK_PLL rate cannot be changed with
+ *   this driver.
+ * - HCLK and PCLK rates cannot be changed as part of this driver.
+ * - Most peripherals have their own dividers are part of the peripheral
+ *   block. Changing SYSCLK, HCLK PLL, HCLK, or PCLK sources or rates
+ *   will also impact the individual peripheral rates.
+ */
+
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/errno.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/amba/bus.h>
+#include <linux/amba/clcd.h>
+
+#include <mach/hardware.h>
+#include <asm/clkdev.h>
+#include <mach/clkdev.h>
+#include <mach/platform.h>
+#include "clock.h"
+#include "common.h"
+
+static struct clk clk_armpll;
+static struct clk clk_usbpll;
+static DEFINE_MUTEX(clkm_lock);
+
+/*
+ * Post divider values for PLLs based on selected register value
+ */
+static const u32 pll_postdivs[4] = {1, 2, 4, 8};
+
+static unsigned long local_return_parent_rate(struct clk *clk)
+{
+	/*
+	 * If a clock has a rate of 0, then it inherits it's parent
+	 * clock rate
+	 */
+	while (clk->rate == 0)
+		clk = clk->parent;
+
+	return clk->rate;
+}
+
+/* 32KHz clock has a fixed rate and is not stoppable */
+static struct clk osc_32KHz = {
+	.rate		= LPC32XX_CLOCK_OSC_FREQ,
+	.get_rate	= local_return_parent_rate,
+};
+
+static int local_pll397_enable(struct clk *clk, int enable)
+{
+	u32 reg;
+	unsigned long timeout = 1 + msecs_to_jiffies(10);
+
+	reg = __raw_readl(LPC32XX_CLKPWR_PLL397_CTRL);
+
+	if (enable == 0) {
+		reg |= LPC32XX_CLKPWR_SYSCTRL_PLL397_DIS;
+		__raw_writel(reg, LPC32XX_CLKPWR_PLL397_CTRL);
+	} else {
+		/* Enable PLL397 */
+		reg &= ~LPC32XX_CLKPWR_SYSCTRL_PLL397_DIS;
+		__raw_writel(reg, LPC32XX_CLKPWR_PLL397_CTRL);
+
+		/* Wait for PLL397 lock */
+		while (((__raw_readl(LPC32XX_CLKPWR_PLL397_CTRL) &
+			LPC32XX_CLKPWR_SYSCTRL_PLL397_STS) == 0) &&
+			(timeout > jiffies))
+			cpu_relax();
+
+		if ((__raw_readl(LPC32XX_CLKPWR_PLL397_CTRL) &
+			LPC32XX_CLKPWR_SYSCTRL_PLL397_STS) == 0)
+			return -ENODEV;
+	}
+
+	return 0;
+}
+
+static int local_oscmain_enable(struct clk *clk, int enable)
+{
+	u32 reg;
+	unsigned long timeout = 1 + msecs_to_jiffies(10);
+
+	reg = __raw_readl(LPC32XX_CLKPWR_MAIN_OSC_CTRL);
+
+	if (enable == 0) {
+		reg |= LPC32XX_CLKPWR_MOSC_DISABLE;
+		__raw_writel(reg, LPC32XX_CLKPWR_MAIN_OSC_CTRL);
+	} else {
+		/* Enable main oscillator */
+		reg &= ~LPC32XX_CLKPWR_MOSC_DISABLE;
+		__raw_writel(reg, LPC32XX_CLKPWR_MAIN_OSC_CTRL);
+
+		/* Wait for main oscillator to start */
+		while (((__raw_readl(LPC32XX_CLKPWR_MAIN_OSC_CTRL) &
+			LPC32XX_CLKPWR_MOSC_DISABLE) != 0) &&
+			(timeout > jiffies))
+			cpu_relax();
+
+		if ((__raw_readl(LPC32XX_CLKPWR_MAIN_OSC_CTRL) &
+			LPC32XX_CLKPWR_MOSC_DISABLE) != 0)
+			return -ENODEV;
+	}
+
+	return 0;
+}
+
+static struct clk osc_pll397 = {
+	.parent		= &osc_32KHz,
+	.enable		= local_pll397_enable,
+	.rate		= LPC32XX_CLOCK_OSC_FREQ * 397,
+	.get_rate	= local_return_parent_rate,
+};
+
+static struct clk osc_main = {
+	.enable		= local_oscmain_enable,
+	.rate		= LPC32XX_MAIN_OSC_FREQ,
+	.get_rate	= local_return_parent_rate,
+};
+
+static struct clk clk_sys;
+
+/*
+ * Convert a PLL register value to a PLL output frequency
+ */
+u32 clk_get_pllrate_from_reg(u32 inputclk, u32 regval)
+{
+	struct clk_pll_setup pllcfg;
+
+	pllcfg.cco_bypass_b15 = 0;
+	pllcfg.direct_output_b14 = 0;
+	pllcfg.fdbk_div_ctrl_b13 = 0;
+	if ((regval & LPC32XX_CLKPWR_HCLKPLL_CCO_BYPASS) != 0)
+		pllcfg.cco_bypass_b15 = 1;
+	if ((regval & LPC32XX_CLKPWR_HCLKPLL_POSTDIV_BYPASS) != 0)
+		pllcfg.direct_output_b14 = 1;
+	if ((regval & LPC32XX_CLKPWR_HCLKPLL_FDBK_SEL_FCLK) != 0)
+		pllcfg.fdbk_div_ctrl_b13 = 1;
+	pllcfg.pll_m = 1 + ((regval >> 1) & 0xFF);
+	pllcfg.pll_n = 1 + ((regval >> 9) & 0x3);
+	pllcfg.pll_p = pll_postdivs[((regval >> 11) & 0x3)];
+
+	return clk_check_pll_setup(inputclk, &pllcfg);
+}
+
+/*
+ * Setup the HCLK PLL with a PLL structure
+ */
+static u32 local_clk_pll_setup(struct clk_pll_setup *PllSetup)
+{
+	u32 tv, tmp = 0;
+
+	if (PllSetup->analog_on != 0)
+		tmp |= LPC32XX_CLKPWR_HCLKPLL_POWER_UP;
+	if (PllSetup->cco_bypass_b15 != 0)
+		tmp |= LPC32XX_CLKPWR_HCLKPLL_CCO_BYPASS;
+	if (PllSetup->direct_output_b14 != 0)
+		tmp |= LPC32XX_CLKPWR_HCLKPLL_POSTDIV_BYPASS;
+	if (PllSetup->fdbk_div_ctrl_b13 != 0)
+		tmp |= LPC32XX_CLKPWR_HCLKPLL_FDBK_SEL_FCLK;
+
+	tv = ffs(PllSetup->pll_p) - 1;
+	if ((!is_power_of_2(PllSetup->pll_p)) || (tv > 3))
+		return 0;
+
+	tmp |= LPC32XX_CLKPWR_HCLKPLL_POSTDIV_2POW(tv);
+	tmp |= LPC32XX_CLKPWR_HCLKPLL_PREDIV_PLUS1(PllSetup->pll_n - 1);
+	tmp |= LPC32XX_CLKPWR_HCLKPLL_PLLM(PllSetup->pll_m - 1);
+
+	return tmp;
+}
+
+/*
+ * Update the ARM core PLL frequency rate variable from the actual PLL setting
+ */
+static void local_update_armpll_rate(void)
+{
+	u32 clkin, pllreg;
+
+	clkin = clk_armpll.parent->rate;
+	pllreg = __raw_readl(LPC32XX_CLKPWR_HCLKPLL_CTRL) & 0x1FFFF;
+
+	clk_armpll.rate = clk_get_pllrate_from_reg(clkin, pllreg);
+}
+
+/*
+ * Find a PLL configuration for the selected input frequency
+ */
+static u32 local_clk_find_pll_cfg(u32 pllin_freq, u32 target_freq,
+	struct clk_pll_setup *pllsetup)
+{
+	u32 ifreq, freqtol, m, n, p, fclkout;
+
+	/* Determine frequency tolerance limits */
+	freqtol = target_freq / 250;
+	ifreq = pllin_freq;
+
+	/* Is direct bypass mode possible? */
+	if (abs(pllin_freq - target_freq) <= freqtol) {
+		pllsetup->analog_on = 0;
+		pllsetup->cco_bypass_b15 = 1;
+		pllsetup->direct_output_b14 = 1;
+		pllsetup->fdbk_div_ctrl_b13 = 1;
+		pllsetup->pll_p = pll_postdivs[0];
+		pllsetup->pll_n = 1;
+		pllsetup->pll_m = 1;
+		return clk_check_pll_setup(ifreq, pllsetup);
+	} else if (target_freq <= ifreq) {
+		pllsetup->analog_on = 0;
+		pllsetup->cco_bypass_b15 = 1;
+		pllsetup->direct_output_b14 = 0;
+		pllsetup->fdbk_div_ctrl_b13 = 1;
+		pllsetup->pll_n = 1;
+		pllsetup->pll_m = 1;
+		for (p = 0; p <= 3; p++) {
+			pllsetup->pll_p = pll_postdivs[p];
+			fclkout = clk_check_pll_setup(ifreq, pllsetup);
+			if (abs(target_freq - fclkout) <= freqtol)
+				return fclkout;
+		}
+	}
+
+	/* Is direct mode possible? */
+	pllsetup->analog_on = 1;
+	pllsetup->cco_bypass_b15 = 0;
+	pllsetup->direct_output_b14 = 1;
+	pllsetup->fdbk_div_ctrl_b13 = 0;
+	pllsetup->pll_p = pll_postdivs[0];
+	for (m = 1; m <= 256; m++) {
+		for (n = 1; n <= 4; n++) {
+			/* Compute output frequency for this value */
+			pllsetup->pll_n = n;
+			pllsetup->pll_m = m;
+			fclkout = clk_check_pll_setup(ifreq,
+				pllsetup);
+			if (abs(target_freq - fclkout) <=
+				freqtol)
+				return fclkout;
+		}
+	}
+
+	/* Is integer mode possible? */
+	pllsetup->analog_on = 1;
+	pllsetup->cco_bypass_b15 = 0;
+	pllsetup->direct_output_b14 = 0;
+	pllsetup->fdbk_div_ctrl_b13 = 1;
+	for (m = 1; m <= 256; m++) {
+		for (n = 1; n <= 4; n++) {
+			for (p = 0; p < 4; p++) {
+				/* Compute output frequency */
+				pllsetup->pll_p = pll_postdivs[p];
+				pllsetup->pll_n = n;
+				pllsetup->pll_m = m;
+				fclkout = clk_check_pll_setup(
+					ifreq, pllsetup);
+				if (abs(target_freq - fclkout) <= freqtol)
+					return fclkout;
+			}
+		}
+	}
+
+	/* Try non-integer mode */
+	pllsetup->analog_on = 1;
+	pllsetup->cco_bypass_b15 = 0;
+	pllsetup->direct_output_b14 = 0;
+	pllsetup->fdbk_div_ctrl_b13 = 0;
+	for (m = 1; m <= 256; m++) {
+		for (n = 1; n <= 4; n++) {
+			for (p = 0; p < 4; p++) {
+				/* Compute output frequency */
+				pllsetup->pll_p = pll_postdivs[p];
+				pllsetup->pll_n = n;
+				pllsetup->pll_m = m;
+				fclkout = clk_check_pll_setup(
+					ifreq, pllsetup);
+				if (abs(target_freq - fclkout) <= freqtol)
+					return fclkout;
+			}
+		}
+	}
+
+	return 0;
+}
+
+static struct clk clk_armpll = {
+	.parent		= &clk_sys,
+	.get_rate	= local_return_parent_rate,
+};
+
+/*
+ * Setup the USB PLL with a PLL structure
+ */
+static u32 local_clk_usbpll_setup(struct clk_pll_setup *pHCLKPllSetup)
+{
+	u32 reg, tmp = local_clk_pll_setup(pHCLKPllSetup);
+
+	reg = __raw_readl(LPC32XX_CLKPWR_USB_CTRL) & ~0x1FFFF;
+	reg |= tmp;
+	__raw_writel(reg, LPC32XX_CLKPWR_USB_CTRL);
+
+	return clk_check_pll_setup(clk_usbpll.parent->rate,
+		pHCLKPllSetup);
+}
+
+static int local_usbpll_enable(struct clk *clk, int enable)
+{
+	u32 reg;
+	int ret = -ENODEV;
+	unsigned long timeout = 1 + msecs_to_jiffies(10);
+
+	reg = __raw_readl(LPC32XX_CLKPWR_USB_CTRL);
+
+	if (enable == 0) {
+		reg &= ~(LPC32XX_CLKPWR_USBCTRL_CLK_EN1 |
+			LPC32XX_CLKPWR_USBCTRL_CLK_EN2);
+		__raw_writel(reg, LPC32XX_CLKPWR_USB_CTRL);
+	} else if (reg & LPC32XX_CLKPWR_USBCTRL_PLL_PWRUP) {
+		reg |= LPC32XX_CLKPWR_USBCTRL_CLK_EN1;
+		__raw_writel(reg, LPC32XX_CLKPWR_USB_CTRL);
+
+		/* Wait for PLL lock */
+		while ((timeout > jiffies) & (ret == -ENODEV)) {
+			reg = __raw_readl(LPC32XX_CLKPWR_USB_CTRL);
+			if (reg & LPC32XX_CLKPWR_USBCTRL_PLL_STS)
+				ret = 0;
+		}
+
+		if (ret == 0) {
+			reg |= LPC32XX_CLKPWR_USBCTRL_CLK_EN2;
+			__raw_writel(reg, LPC32XX_CLKPWR_USB_CTRL);
+		}
+	}
+
+	return ret;
+}
+
+static unsigned long local_usbpll_round_rate(struct clk *clk,
+	unsigned long rate)
+{
+	u32 clkin, usbdiv;
+	struct clk_pll_setup pllsetup;
+
+	/*
+	 * Unlike other clocks, this clock has a KHz input rate, so bump
+	 * it up to work with the PLL function
+	 */
+	rate = rate * 1000;
+
+	clkin = clk->parent->rate;
+	usbdiv = (__raw_readl(LPC32XX_CLKPWR_USBCLK_PDIV) &
+		LPC32XX_CLKPWR_USBPDIV_PLL_MASK) + 1;
+	clkin = clkin / usbdiv;
+
+	/* Try to find a good rate setup */
+	if (local_clk_find_pll_cfg(clkin, rate, &pllsetup) == 0)
+		return 0;
+
+	return clk_check_pll_setup(clkin, &pllsetup);
+}
+
+static int local_usbpll_set_rate(struct clk *clk, unsigned long rate)
+{
+	u32 clkin, reg, usbdiv;
+	struct clk_pll_setup pllsetup;
+
+	/*
+	 * Unlike other clocks, this clock has a KHz input rate, so bump
+	 * it up to work with the PLL function
+	 */
+	rate = rate * 1000;
+
+	clkin = clk->get_rate(clk);
+	usbdiv = (__raw_readl(LPC32XX_CLKPWR_USBCLK_PDIV) &
+		LPC32XX_CLKPWR_USBPDIV_PLL_MASK) + 1;
+	clkin = clkin / usbdiv;
+
+	/* Try to find a good rate setup */
+	if (local_clk_find_pll_cfg(clkin, rate, &pllsetup) == 0)
+		return -EINVAL;
+
+	local_usbpll_enable(clk, 0);
+
+	reg = __raw_readl(LPC32XX_CLKPWR_USB_CTRL);
+	reg |= LPC32XX_CLKPWR_USBCTRL_CLK_EN1;
+	__raw_writel(reg, LPC32XX_CLKPWR_USB_CTRL);
+
+	pllsetup.analog_on = 1;
+	local_clk_usbpll_setup(&pllsetup);
+
+	clk->rate = clk_check_pll_setup(clkin, &pllsetup);
+
+	reg = __raw_readl(LPC32XX_CLKPWR_USB_CTRL);
+	reg |= LPC32XX_CLKPWR_USBCTRL_CLK_EN2;
+	__raw_writel(reg, LPC32XX_CLKPWR_USB_CTRL);
+
+	return 0;
+}
+
+static struct clk clk_usbpll = {
+	.parent		= &osc_main,
+	.set_rate	= local_usbpll_set_rate,
+	.enable		= local_usbpll_enable,
+	.rate		= 48000, /* In KHz */
+	.get_rate	= local_return_parent_rate,
+	.round_rate	= local_usbpll_round_rate,
+};
+
+static u32 clk_get_hclk_div(void)
+{
+	static const u32 hclkdivs[4] = {1, 2, 4, 4};
+	return hclkdivs[LPC32XX_CLKPWR_HCLKDIV_DIV_2POW(
+		__raw_readl(LPC32XX_CLKPWR_HCLK_DIV))];
+}
+
+static struct clk clk_hclk = {
+	.parent		= &clk_armpll,
+	.get_rate	= local_return_parent_rate,
+};
+
+static struct clk clk_pclk = {
+	.parent		= &clk_armpll,
+	.get_rate	= local_return_parent_rate,
+};
+
+static int local_onoff_enable(struct clk *clk, int enable)
+{
+	u32 tmp;
+
+	tmp = __raw_readl(clk->enable_reg);
+
+	if (enable == 0)
+		tmp &= ~clk->enable_mask;
+	else
+		tmp |= clk->enable_mask;
+
+	__raw_writel(tmp, clk->enable_reg);
+
+	return 0;
+}
+
+/* Peripheral clock sources */
+static struct clk clk_timer0 = {
+	.parent		= &clk_pclk,
+	.enable		= local_onoff_enable,
+	.enable_reg	= LPC32XX_CLKPWR_TIMERS_PWMS_CLK_CTRL_1,
+	.enable_mask	= LPC32XX_CLKPWR_TMRPWMCLK_TIMER0_EN,
+	.get_rate	= local_return_parent_rate,
+};
+static struct clk clk_timer1 = {
+	.parent		= &clk_pclk,
+	.enable		= local_onoff_enable,
+	.enable_reg	= LPC32XX_CLKPWR_TIMERS_PWMS_CLK_CTRL_1,
+	.enable_mask	= LPC32XX_CLKPWR_TMRPWMCLK_TIMER1_EN,
+	.get_rate	= local_return_parent_rate,
+};
+static struct clk clk_timer2 = {
+	.parent		= &clk_pclk,
+	.enable		= local_onoff_enable,
+	.enable_reg	= LPC32XX_CLKPWR_TIMERS_PWMS_CLK_CTRL_1,
+	.enable_mask	= LPC32XX_CLKPWR_TMRPWMCLK_TIMER2_EN,
+	.get_rate	= local_return_parent_rate,
+};
+static struct clk clk_timer3 = {
+	.parent		= &clk_pclk,
+	.enable		= local_onoff_enable,
+	.enable_reg	= LPC32XX_CLKPWR_TIMERS_PWMS_CLK_CTRL_1,
+	.enable_mask	= LPC32XX_CLKPWR_TMRPWMCLK_TIMER3_EN,
+	.get_rate	= local_return_parent_rate,
+};
+static struct clk clk_wdt = {
+	.parent		= &clk_pclk,
+	.enable		= local_onoff_enable,
+	.enable_reg	= LPC32XX_CLKPWR_TIMER_CLK_CTRL,
+	.enable_mask	= LPC32XX_CLKPWR_PWMCLK_WDOG_EN,
+	.get_rate	= local_return_parent_rate,
+};
+static struct clk clk_vfp9 = {
+	.parent		= &clk_pclk,
+	.enable		= local_onoff_enable,
+	.enable_reg	= LPC32XX_CLKPWR_DEBUG_CTRL,
+	.enable_mask	= LPC32XX_CLKPWR_VFP_CLOCK_ENABLE_BIT,
+	.get_rate	= local_return_parent_rate,
+};
+static struct clk clk_dma = {
+	.parent		= &clk_hclk,
+	.enable		= local_onoff_enable,
+	.enable_reg	= LPC32XX_CLKPWR_DMA_CLK_CTRL,
+	.enable_mask	= LPC32XX_CLKPWR_DMACLKCTRL_CLK_EN,
+	.get_rate	= local_return_parent_rate,
+};
+
+static struct clk clk_uart3 = {
+	.parent		= &clk_pclk,
+	.enable		= local_onoff_enable,
+	.enable_reg	= LPC32XX_CLKPWR_UART_CLK_CTRL,
+	.enable_mask	= LPC32XX_CLKPWR_UARTCLKCTRL_UART3_EN,
+	.get_rate	= local_return_parent_rate,
+};
+
+static struct clk clk_uart4 = {
+	.parent		= &clk_pclk,
+	.enable		= local_onoff_enable,
+	.enable_reg	= LPC32XX_CLKPWR_UART_CLK_CTRL,
+	.enable_mask	= LPC32XX_CLKPWR_UARTCLKCTRL_UART4_EN,
+	.get_rate	= local_return_parent_rate,
+};
+
+static struct clk clk_uart5 = {
+	.parent		= &clk_pclk,
+	.enable		= local_onoff_enable,
+	.enable_reg	= LPC32XX_CLKPWR_UART_CLK_CTRL,
+	.enable_mask	= LPC32XX_CLKPWR_UARTCLKCTRL_UART5_EN,
+	.get_rate	= local_return_parent_rate,
+};
+
+static struct clk clk_uart6 = {
+	.parent		= &clk_pclk,
+	.enable		= local_onoff_enable,
+	.enable_reg	= LPC32XX_CLKPWR_UART_CLK_CTRL,
+	.enable_mask	= LPC32XX_CLKPWR_UARTCLKCTRL_UART6_EN,
+	.get_rate	= local_return_parent_rate,
+};
+
+static struct clk clk_i2c0 = {
+	.parent		= &clk_hclk,
+	.enable		= local_onoff_enable,
+	.enable_reg	= LPC32XX_CLKPWR_I2C_CLK_CTRL,
+	.enable_mask	= LPC32XX_CLKPWR_I2CCLK_I2C1CLK_EN,
+	.get_rate	= local_return_parent_rate,
+};
+
+static struct clk clk_i2c1 = {
+	.parent		= &clk_hclk,
+	.enable		= local_onoff_enable,
+	.enable_reg	= LPC32XX_CLKPWR_I2C_CLK_CTRL,
+	.enable_mask	= LPC32XX_CLKPWR_I2CCLK_I2C2CLK_EN,
+	.get_rate	= local_return_parent_rate,
+};
+
+static struct clk clk_i2c2 = {
+	.parent		= &clk_pclk,
+	.enable		= local_onoff_enable,
+	.enable_reg	= io_p2v(LPC32XX_USB_BASE + 0xFF4),
+	.enable_mask	= 0x4,
+	.get_rate	= local_return_parent_rate,
+};
+
+static struct clk clk_ssp0 = {
+	.parent		= &clk_hclk,
+	.enable		= local_onoff_enable,
+	.enable_reg	= LPC32XX_CLKPWR_SSP_CLK_CTRL,
+	.enable_mask	= LPC32XX_CLKPWR_SSPCTRL_SSPCLK0_EN,
+	.get_rate	= local_return_parent_rate,
+};
+
+static struct clk clk_ssp1 = {
+	.parent		= &clk_hclk,
+	.enable		= local_onoff_enable,
+	.enable_reg	= LPC32XX_CLKPWR_SSP_CLK_CTRL,
+	.enable_mask	= LPC32XX_CLKPWR_SSPCTRL_SSPCLK1_EN,
+	.get_rate	= local_return_parent_rate,
+};
+
+static struct clk clk_kscan = {
+	.parent		= &osc_32KHz,
+	.enable		= local_onoff_enable,
+	.enable_reg	= LPC32XX_CLKPWR_KEY_CLK_CTRL,
+	.enable_mask	= LPC32XX_CLKPWR_KEYCLKCTRL_CLK_EN,
+	.get_rate	= local_return_parent_rate,
+};
+
+static struct clk clk_nand = {
+	.parent		= &clk_hclk,
+	.enable		= local_onoff_enable,
+	.enable_reg	= LPC32XX_CLKPWR_NAND_CLK_CTRL,
+	.enable_mask	= LPC32XX_CLKPWR_NANDCLK_SLCCLK_EN,
+	.get_rate	= local_return_parent_rate,
+};
+
+static struct clk clk_i2s0 = {
+	.parent		= &clk_hclk,
+	.enable		= local_onoff_enable,
+	.enable_reg	= LPC32XX_CLKPWR_I2S_CLK_CTRL,
+	.enable_mask	= LPC32XX_CLKPWR_I2SCTRL_I2SCLK0_EN,
+	.get_rate	= local_return_parent_rate,
+};
+
+static struct clk clk_i2s1 = {
+	.parent		= &clk_hclk,
+	.enable		= local_onoff_enable,
+	.enable_reg	= LPC32XX_CLKPWR_I2S_CLK_CTRL,
+	.enable_mask	= LPC32XX_CLKPWR_I2SCTRL_I2SCLK1_EN,
+	.get_rate	= local_return_parent_rate,
+};
+
+static struct clk clk_net = {
+	.parent		= &clk_hclk,
+	.enable		= local_onoff_enable,
+	.enable_reg	= LPC32XX_CLKPWR_MACCLK_CTRL,
+	.enable_mask	= (LPC32XX_CLKPWR_MACCTRL_DMACLK_EN |
+		LPC32XX_CLKPWR_MACCTRL_MMIOCLK_EN |
+		LPC32XX_CLKPWR_MACCTRL_HRCCLK_EN),
+	.get_rate	= local_return_parent_rate,
+};
+
+static struct clk clk_rtc = {
+	.parent		= &osc_32KHz,
+	.rate		= 1, /* 1 Hz */
+	.get_rate	= local_return_parent_rate,
+};
+
+static struct clk clk_usbd = {
+	.parent		= &clk_usbpll,
+	.enable		= local_onoff_enable,
+	.enable_reg	= LPC32XX_CLKPWR_USB_CTRL,
+	.enable_mask	= LPC32XX_CLKPWR_USBCTRL_HCLK_EN,
+	.get_rate	= local_return_parent_rate,
+};
+
+static int tsc_onoff_enable(struct clk *clk, int enable)
+{
+	u32 tmp;
+
+	/* Make sure 32KHz clock is the selected clock */
+	tmp = __raw_readl(LPC32XX_CLKPWR_ADC_CLK_CTRL_1);
+	tmp &= ~LPC32XX_CLKPWR_ADCCTRL1_PCLK_SEL;
+	__raw_writel(tmp, LPC32XX_CLKPWR_ADC_CLK_CTRL_1);
+
+	if (enable == 0)
+		__raw_writel(0, clk->enable_reg);
+	else
+		__raw_writel(clk->enable_mask, clk->enable_reg);
+
+	return 0;
+}
+
+static struct clk clk_tsc = {
+	.parent		= &osc_32KHz,
+	.enable		= tsc_onoff_enable,
+	.enable_reg	= LPC32XX_CLKPWR_ADC_CLK_CTRL,
+	.enable_mask	= LPC32XX_CLKPWR_ADC32CLKCTRL_CLK_EN,
+	.get_rate	= local_return_parent_rate,
+};
+
+static int mmc_onoff_enable(struct clk *clk, int enable)
+{
+	u32 tmp;
+
+	tmp = __raw_readl(LPC32XX_CLKPWR_MS_CTRL) &
+		~LPC32XX_CLKPWR_MSCARD_SDCARD_EN;
+
+	/* If rate is 0, disable clock */
+	if (enable != 0)
+		tmp |= LPC32XX_CLKPWR_MSCARD_SDCARD_EN;
+
+	__raw_writel(tmp, LPC32XX_CLKPWR_MS_CTRL);
+
+	return 0;
+}
+
+static unsigned long mmc_get_rate(struct clk *clk)
+{
+	u32 div, rate, oldclk;
+
+	/* The MMC clock must be on when accessing an MMC register */
+	oldclk = __raw_readl(LPC32XX_CLKPWR_MS_CTRL);
+	__raw_writel(oldclk | LPC32XX_CLKPWR_MSCARD_SDCARD_EN,
+		LPC32XX_CLKPWR_MS_CTRL);
+	div = __raw_readl(LPC32XX_CLKPWR_MS_CTRL);
+	__raw_writel(oldclk, LPC32XX_CLKPWR_MS_CTRL);
+
+	/* Get the parent clock rate */
+	rate = clk->parent->get_rate(clk->parent);
+
+	/* Get the MMC controller clock divider value */
+	div = div & LPC32XX_CLKPWR_MSCARD_SDCARD_DIV(0xf);
+
+	if (!div)
+		div = 1;
+
+	return rate / div;
+}
+
+static unsigned long mmc_round_rate(struct clk *clk, unsigned long rate)
+{
+	unsigned long div, prate;
+
+	/* Get the parent clock rate */
+	prate = clk->parent->get_rate(clk->parent);
+
+	if (rate >= prate)
+		return prate;
+
+	div = prate / rate;
+	if (div > 0xf)
+		div = 0xf;
+
+	return prate / div;
+}
+
+static int mmc_set_rate(struct clk *clk, unsigned long rate)
+{
+	u32 oldclk, tmp;
+	unsigned long prate, div, crate = mmc_round_rate(clk, rate);
+
+	prate = clk->parent->get_rate(clk->parent);
+
+	div = prate / crate;
+
+	/* The MMC clock must be on when accessing an MMC register */
+	oldclk = __raw_readl(LPC32XX_CLKPWR_MS_CTRL);
+	__raw_writel(oldclk | LPC32XX_CLKPWR_MSCARD_SDCARD_EN,
+		LPC32XX_CLKPWR_MS_CTRL);
+	tmp = __raw_readl(LPC32XX_CLKPWR_MS_CTRL) &
+		~LPC32XX_CLKPWR_MSCARD_SDCARD_DIV(0xf);
+	tmp |= LPC32XX_CLKPWR_MSCARD_SDCARD_DIV(div);
+	__raw_writel(tmp, LPC32XX_CLKPWR_MS_CTRL);
+
+	__raw_writel(oldclk, LPC32XX_CLKPWR_MS_CTRL);
+
+	return 0;
+}
+
+static struct clk clk_mmc = {
+	.parent		= &clk_armpll,
+	.set_rate	= mmc_set_rate,
+	.get_rate	= mmc_get_rate,
+	.round_rate	= mmc_round_rate,
+	.enable		= mmc_onoff_enable,
+	.enable_reg	= LPC32XX_CLKPWR_MS_CTRL,
+	.enable_mask	= LPC32XX_CLKPWR_MSCARD_SDCARD_EN,
+};
+
+static unsigned long clcd_get_rate(struct clk *clk)
+{
+	u32 tmp, div, rate, oldclk;
+
+	/* The LCD clock must be on when accessing an LCD register */
+	oldclk = __raw_readl(LPC32XX_CLKPWR_LCDCLK_CTRL);
+	__raw_writel(oldclk | LPC32XX_CLKPWR_LCDCTRL_CLK_EN,
+		LPC32XX_CLKPWR_LCDCLK_CTRL);
+	tmp = __raw_readl(io_p2v(LPC32XX_LCD_BASE + CLCD_TIM2));
+	__raw_writel(oldclk, LPC32XX_CLKPWR_LCDCLK_CTRL);
+
+	rate = clk->parent->get_rate(clk->parent);
+
+	/* Only supports internal clocking */
+	if (tmp & TIM2_BCD)
+		return rate;
+
+	div = (tmp & 0x1F) | ((tmp & 0xF8) >> 22);
+	tmp = rate / (2 + div);
+
+	return tmp;
+}
+
+static int clcd_set_rate(struct clk *clk, unsigned long rate)
+{
+	u32 tmp, prate, div, oldclk;
+
+	/* The LCD clock must be on when accessing an LCD register */
+	oldclk = __raw_readl(LPC32XX_CLKPWR_LCDCLK_CTRL);
+	__raw_writel(oldclk | LPC32XX_CLKPWR_LCDCTRL_CLK_EN,
+		LPC32XX_CLKPWR_LCDCLK_CTRL);
+
+	tmp = __raw_readl(io_p2v(LPC32XX_LCD_BASE + CLCD_TIM2)) | TIM2_BCD;
+	prate = clk->parent->get_rate(clk->parent);
+
+	if (rate < prate) {
+		/* Find closest divider */
+		div = prate / rate;
+		if (div >= 2) {
+			div -= 2;
+			tmp &= ~TIM2_BCD;
+		}
+
+		tmp &= ~(0xF800001F);
+		tmp |= (div & 0x1F);
+		tmp |= (((div >> 5) & 0x1F) << 27);
+	}
+
+	__raw_writel(tmp, io_p2v(LPC32XX_LCD_BASE + CLCD_TIM2));
+	__raw_writel(oldclk, LPC32XX_CLKPWR_LCDCLK_CTRL);
+
+	return 0;
+}
+
+static unsigned long clcd_round_rate(struct clk *clk, unsigned long rate)
+{
+	u32 prate, div;
+
+	prate = clk->parent->get_rate(clk->parent);
+
+	if (rate >= prate)
+		rate = prate;
+	else {
+		div = prate / rate;
+		if (div > 0x3ff)
+			div = 0x3ff;
+
+		rate = prate / div;
+	}
+
+	return rate;
+}
+
+static struct clk clk_lcd = {
+	.parent		= &clk_hclk,
+	.set_rate	= clcd_set_rate,
+	.get_rate	= clcd_get_rate,
+	.round_rate	= clcd_round_rate,
+	.enable		= local_onoff_enable,
+	.enable_reg	= LPC32XX_CLKPWR_LCDCLK_CTRL,
+	.enable_mask	= LPC32XX_CLKPWR_LCDCTRL_CLK_EN,
+};
+
+static inline void clk_lock(void)
+{
+	mutex_lock(&clkm_lock);
+}
+
+static inline void clk_unlock(void)
+{
+	mutex_unlock(&clkm_lock);
+}
+
+static void local_clk_disable(struct clk *clk)
+{
+	WARN_ON(clk->usecount == 0);
+
+	/* Don't attempt to disable clock if it has no users */
+	if (clk->usecount > 0) {
+		clk->usecount--;
+
+		/* Only disable clock when it has no more users */
+		if ((clk->usecount == 0) && (clk->enable))
+			clk->enable(clk, 0);
+
+		/* Check parent clocks, they may need to be disabled too */
+		if (clk->parent)
+			local_clk_disable(clk->parent);
+	}
+}
+
+static int local_clk_enable(struct clk *clk)
+{
+	int ret = 0;
+
+	/* Enable parent clocks first and update use counts */
+	if (clk->parent)
+		ret = local_clk_enable(clk->parent);
+
+	if (!ret) {
+		/* Only enable clock if it's currently disabled */
+		if ((clk->usecount == 0) && (clk->enable))
+			ret = clk->enable(clk, 1);
+
+		if (!ret)
+			clk->usecount++;
+		else if (clk->parent)
+			local_clk_disable(clk->parent);
+	}
+
+	return ret;
+}
+
+/*
+ * clk_enable - inform the system when the clock source should be running.
+ */
+int clk_enable(struct clk *clk)
+{
+	int ret;
+
+	clk_lock();
+	ret = local_clk_enable(clk);
+	clk_unlock();
+
+	return ret;
+}
+EXPORT_SYMBOL(clk_enable);
+
+/*
+ * clk_disable - inform the system when the clock source is no longer required
+ */
+void clk_disable(struct clk *clk)
+{
+	clk_lock();
+	local_clk_disable(clk);
+	clk_unlock();
+}
+EXPORT_SYMBOL(clk_disable);
+
+/*
+ * clk_get_rate - obtain the current clock rate (in Hz) for a clock source
+ */
+unsigned long clk_get_rate(struct clk *clk)
+{
+	unsigned long rate;
+
+	clk_lock();
+	rate = clk->get_rate(clk);
+	clk_unlock();
+
+	return rate;
+}
+EXPORT_SYMBOL(clk_get_rate);
+
+/*
+ * clk_set_rate - set the clock rate for a clock source
+ */
+int clk_set_rate(struct clk *clk, unsigned long rate)
+{
+	int ret = -EINVAL;
+
+	/*
+	 * Most system clocks can only be enabled or disabled, with
+	 * the actual rate set as part of the peripheral dividers
+	 * instead of high level clock control
+	 */
+	if (clk->set_rate) {
+		clk_lock();
+		ret = clk->set_rate(clk, rate);
+		clk_unlock();
+	}
+
+	return ret;
+}
+EXPORT_SYMBOL(clk_set_rate);
+
+/*
+ * clk_round_rate - adjust a rate to the exact rate a clock can provide
+ */
+long clk_round_rate(struct clk *clk, unsigned long rate)
+{
+	clk_lock();
+
+	if (clk->round_rate)
+		rate = clk->round_rate(clk, rate);
+	else
+		rate = clk->get_rate(clk);
+
+	clk_unlock();
+
+	return rate;
+}
+EXPORT_SYMBOL(clk_round_rate);
+
+/*
+ * clk_set_parent - set the parent clock source for this clock
+ */
+int clk_set_parent(struct clk *clk, struct clk *parent)
+{
+	/* Clock re-parenting is not supported */
+	return -EINVAL;
+}
+EXPORT_SYMBOL(clk_set_parent);
+
+/*
+ * clk_get_parent - get the parent clock source for this clock
+ */
+struct clk *clk_get_parent(struct clk *clk)
+{
+	return clk->parent;
+}
+EXPORT_SYMBOL(clk_get_parent);
+
+#define _REGISTER_CLOCK(d, n, c) \
+	{ \
+		.dev_id = (d), \
+		.con_id = (n), \
+		.clk = &(c), \
+	},
+
+static struct clk_lookup lookups[] = {
+	_REGISTER_CLOCK(NULL, "osc_32KHz", osc_32KHz)
+	_REGISTER_CLOCK(NULL, "osc_pll397", osc_pll397)
+	_REGISTER_CLOCK(NULL, "osc_main", osc_main)
+	_REGISTER_CLOCK(NULL, "sys_ck", clk_sys)
+	_REGISTER_CLOCK(NULL, "arm_pll_ck", clk_armpll)
+	_REGISTER_CLOCK(NULL, "ck_pll5", clk_usbpll)
+	_REGISTER_CLOCK(NULL, "hclk_ck", clk_hclk)
+	_REGISTER_CLOCK(NULL, "pclk_ck", clk_pclk)
+	_REGISTER_CLOCK(NULL, "timer0_ck", clk_timer0)
+	_REGISTER_CLOCK(NULL, "timer1_ck", clk_timer1)
+	_REGISTER_CLOCK(NULL, "timer2_ck", clk_timer2)
+	_REGISTER_CLOCK(NULL, "timer3_ck", clk_timer3)
+	_REGISTER_CLOCK(NULL, "vfp9_ck", clk_vfp9)
+	_REGISTER_CLOCK(NULL, "clk_dmac", clk_dma)
+	_REGISTER_CLOCK("pnx4008-watchdog", NULL, clk_wdt)
+	_REGISTER_CLOCK(NULL, "uart3_ck", clk_uart3)
+	_REGISTER_CLOCK(NULL, "uart4_ck", clk_uart4)
+	_REGISTER_CLOCK(NULL, "uart5_ck", clk_uart5)
+	_REGISTER_CLOCK(NULL, "uart6_ck", clk_uart6)
+	_REGISTER_CLOCK("pnx-i2c.0", NULL, clk_i2c0)
+	_REGISTER_CLOCK("pnx-i2c.1", NULL, clk_i2c1)
+	_REGISTER_CLOCK("pnx-i2c.2", NULL, clk_i2c2)
+	_REGISTER_CLOCK("dev:ssp0", NULL, clk_ssp0)
+	_REGISTER_CLOCK("dev:ssp1", NULL, clk_ssp1)
+	_REGISTER_CLOCK("lpc32xx_keys.0", NULL, clk_kscan)
+	_REGISTER_CLOCK("lpc32xx-nand.0", "nand_ck", clk_nand)
+	_REGISTER_CLOCK("tbd", "i2s0_ck", clk_i2s0)
+	_REGISTER_CLOCK("tbd", "i2s1_ck", clk_i2s1)
+	_REGISTER_CLOCK("lpc32xx-ts", NULL, clk_tsc)
+	_REGISTER_CLOCK("dev:mmc0", "MCLK", clk_mmc)
+	_REGISTER_CLOCK("lpc-net.0", NULL, clk_net)
+	_REGISTER_CLOCK("dev:clcd", NULL, clk_lcd)
+	_REGISTER_CLOCK("lpc32xx_udc", "ck_usbd", clk_usbd)
+	_REGISTER_CLOCK("lpc32xx_rtc", NULL, clk_rtc)
+};
+
+static int __init clk_init(void)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(lookups); i++)
+		clkdev_add(&lookups[i]);
+
+	/*
+	 * Setup muxed SYSCLK for HCLK PLL base -this selects the
+	 * parent clock used for the ARM PLL and is used to derive
+	 * the many system clock rates in the device.
+	 */
+	if (clk_is_sysclk_mainosc() != 0)
+		clk_sys.parent = &osc_main;
+	else
+		clk_sys.parent = &osc_pll397;
+
+	clk_sys.rate = clk_sys.parent->rate;
+
+	/* Compute the current ARM PLL and USB PLL frequencies */
+	local_update_armpll_rate();
+
+	/* Compute HCLK and PCLK bus rates */
+	clk_hclk.rate = clk_hclk.parent->rate / clk_get_hclk_div();
+	clk_pclk.rate = clk_pclk.parent->rate / clk_get_pclk_div();
+
+	/*
+	 * Enable system clocks - this step is somewhat formal, as the
+	 * clocks are already running, but it does get the clock data
+	 * inline with the actual system state. Never disable these
+	 * clocks as they will only stop if the system is going to sleep.
+	 * In that case, the chip/system power management functions will
+	 * handle clock gating.
+	 */
+	if (clk_enable(&clk_hclk) || clk_enable(&clk_pclk))
+		printk(KERN_ERR "Error enabling system HCLK and PCLK\n");
+
+	/*
+	 * Timers 0 and 1 were enabled and are being used by the high
+	 * resolution tick function prior to this driver being initialized.
+	 * Tag them now as used.
+	 */
+	if (clk_enable(&clk_timer0) || clk_enable(&clk_timer1))
+		printk(KERN_ERR "Error enabling timer tick clocks\n");
+
+	return 0;
+}
+core_initcall(clk_init);
+

+ 38 - 0
arch/arm/mach-lpc32xx/clock.h

@@ -0,0 +1,38 @@
+/*
+ * arch/arm/mach-lpc32xx/clock.h
+ *
+ * Author: Kevin Wells <kevin.wells@nxp.com>
+ *
+ * Copyright (C) 2010 NXP Semiconductors
+ *
+ * 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.
+ */
+
+#ifndef __LPC32XX_CLOCK_H
+#define __LPC32XX_CLOCK_H
+
+struct clk {
+	struct list_head node;
+	struct clk *parent;
+	u32 rate;
+	u32 usecount;
+
+	int (*set_rate) (struct clk *, unsigned long);
+	unsigned long (*round_rate) (struct clk *, unsigned long);
+	unsigned long (*get_rate) (struct clk *clk);
+	int (*enable) (struct clk *, int);
+
+	/* Register address and bit mask for simple clocks */
+	void __iomem *enable_reg;
+	u32 enable_mask;
+};
+
+#endif

+ 271 - 0
arch/arm/mach-lpc32xx/common.c

@@ -0,0 +1,271 @@
+/*
+ * arch/arm/mach-lpc32xx/common.c
+ *
+ * Author: Kevin Wells <kevin.wells@nxp.com>
+ *
+ * Copyright (C) 2010 NXP Semiconductors
+ *
+ * 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.
+ */
+
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/i2c-pnx.h>
+#include <linux/io.h>
+
+#include <asm/mach/map.h>
+
+#include <mach/i2c.h>
+#include <mach/hardware.h>
+#include <mach/platform.h>
+#include "common.h"
+
+/*
+ * Watchdog timer
+ */
+static struct resource watchdog_resources[] = {
+	[0] = {
+		.start = LPC32XX_WDTIM_BASE,
+		.end = LPC32XX_WDTIM_BASE + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+	},
+};
+
+struct platform_device lpc32xx_watchdog_device = {
+	.name = "pnx4008-watchdog",
+	.id = -1,
+	.num_resources = ARRAY_SIZE(watchdog_resources),
+	.resource = watchdog_resources,
+};
+
+/*
+ * I2C busses
+ */
+static struct i2c_pnx_data i2c0_data = {
+	.name = I2C_CHIP_NAME "1",
+	.base = LPC32XX_I2C1_BASE,
+	.irq = IRQ_LPC32XX_I2C_1,
+};
+
+static struct i2c_pnx_data i2c1_data = {
+	.name = I2C_CHIP_NAME "2",
+	.base = LPC32XX_I2C2_BASE,
+	.irq = IRQ_LPC32XX_I2C_2,
+};
+
+static struct i2c_pnx_data i2c2_data = {
+	.name = "USB-I2C",
+	.base = LPC32XX_OTG_I2C_BASE,
+	.irq = IRQ_LPC32XX_USB_I2C,
+};
+
+struct platform_device lpc32xx_i2c0_device = {
+	.name = "pnx-i2c",
+	.id = 0,
+	.dev = {
+		.platform_data = &i2c0_data,
+	},
+};
+
+struct platform_device lpc32xx_i2c1_device = {
+	.name = "pnx-i2c",
+	.id = 1,
+	.dev = {
+		.platform_data = &i2c1_data,
+	},
+};
+
+struct platform_device lpc32xx_i2c2_device = {
+	.name = "pnx-i2c",
+	.id = 2,
+	.dev = {
+		.platform_data = &i2c2_data,
+	},
+};
+
+/*
+ * Returns the unique ID for the device
+ */
+void lpc32xx_get_uid(u32 devid[4])
+{
+	int i;
+
+	for (i = 0; i < 4; i++)
+		devid[i] = __raw_readl(LPC32XX_CLKPWR_DEVID(i << 2));
+}
+
+/*
+ * Returns SYSCLK source
+ * 0 = PLL397, 1 = main oscillator
+ */
+int clk_is_sysclk_mainosc(void)
+{
+	if ((__raw_readl(LPC32XX_CLKPWR_SYSCLK_CTRL) &
+		LPC32XX_CLKPWR_SYSCTRL_SYSCLKMUX) == 0)
+		return 1;
+
+	return 0;
+}
+
+/*
+ * System reset via the watchdog timer
+ */
+void lpc32xx_watchdog_reset(void)
+{
+	/* Make sure WDT clocks are enabled */
+	__raw_writel(LPC32XX_CLKPWR_PWMCLK_WDOG_EN,
+		LPC32XX_CLKPWR_TIMER_CLK_CTRL);
+
+	/* Instant assert of RESETOUT_N with pulse length 1mS */
+	__raw_writel(13000, io_p2v(LPC32XX_WDTIM_BASE + 0x18));
+	__raw_writel(0x70, io_p2v(LPC32XX_WDTIM_BASE + 0xC));
+}
+
+/*
+ * Detects and returns IRAM size for the device variation
+ */
+#define LPC32XX_IRAM_BANK_SIZE SZ_128K
+static u32 iram_size;
+u32 lpc32xx_return_iram_size(void)
+{
+	if (iram_size == 0) {
+		u32 savedval1, savedval2;
+		void __iomem *iramptr1, *iramptr2;
+
+		iramptr1 = io_p2v(LPC32XX_IRAM_BASE);
+		iramptr2 = io_p2v(LPC32XX_IRAM_BASE + LPC32XX_IRAM_BANK_SIZE);
+		savedval1 = __raw_readl(iramptr1);
+		savedval2 = __raw_readl(iramptr2);
+
+		if (savedval1 == savedval2) {
+			__raw_writel(savedval2 + 1, iramptr2);
+			if (__raw_readl(iramptr1) == savedval2 + 1)
+				iram_size = LPC32XX_IRAM_BANK_SIZE;
+			else
+				iram_size = LPC32XX_IRAM_BANK_SIZE * 2;
+			__raw_writel(savedval2, iramptr2);
+		} else
+			iram_size = LPC32XX_IRAM_BANK_SIZE * 2;
+	}
+
+	return iram_size;
+}
+
+/*
+ * Computes PLL rate from PLL register and input clock
+ */
+u32 clk_check_pll_setup(u32 ifreq, struct clk_pll_setup *pllsetup)
+{
+	u32 ilfreq, p, m, n, fcco, fref, cfreq;
+	int mode;
+
+	/*
+	 * PLL requirements
+	 * ifreq must be >= 1MHz and <= 20MHz
+	 * FCCO must be >= 156MHz and <= 320MHz
+	 * FREF must be >= 1MHz and <= 27MHz
+	 * Assume the passed input data is not valid
+	 */
+
+	ilfreq = ifreq;
+	m = pllsetup->pll_m;
+	n = pllsetup->pll_n;
+	p = pllsetup->pll_p;
+
+	mode = (pllsetup->cco_bypass_b15 << 2) |
+		(pllsetup->direct_output_b14 << 1) |
+	pllsetup->fdbk_div_ctrl_b13;
+
+	switch (mode) {
+	case 0x0: /* Non-integer mode */
+		cfreq = (m * ilfreq) / (2 * p * n);
+		fcco = (m * ilfreq) / n;
+		fref = ilfreq / n;
+		break;
+
+	case 0x1: /* integer mode */
+		cfreq = (m * ilfreq) / n;
+		fcco = (m * ilfreq) / (n * 2 * p);
+		fref = ilfreq / n;
+		break;
+
+	case 0x2:
+	case 0x3: /* Direct mode */
+		cfreq = (m * ilfreq) / n;
+		fcco = cfreq;
+		fref = ilfreq / n;
+		break;
+
+	case 0x4:
+	case 0x5: /* Bypass mode */
+		cfreq = ilfreq / (2 * p);
+		fcco = 156000000;
+		fref = 1000000;
+		break;
+
+	case 0x6:
+	case 0x7: /* Direct bypass mode */
+	default:
+		cfreq = ilfreq;
+		fcco = 156000000;
+		fref = 1000000;
+		break;
+	}
+
+	if (fcco < 156000000 || fcco > 320000000)
+		cfreq = 0;
+
+	if (fref < 1000000 || fref > 27000000)
+		cfreq = 0;
+
+	return (u32) cfreq;
+}
+
+u32 clk_get_pclk_div(void)
+{
+	return 1 + ((__raw_readl(LPC32XX_CLKPWR_HCLK_DIV) >> 2) & 0x1F);
+}
+
+static struct map_desc lpc32xx_io_desc[] __initdata = {
+	{
+		.virtual	= IO_ADDRESS(LPC32XX_AHB0_START),
+		.pfn		= __phys_to_pfn(LPC32XX_AHB0_START),
+		.length		= LPC32XX_AHB0_SIZE,
+		.type		= MT_DEVICE
+	},
+	{
+		.virtual	= IO_ADDRESS(LPC32XX_AHB1_START),
+		.pfn		= __phys_to_pfn(LPC32XX_AHB1_START),
+		.length		= LPC32XX_AHB1_SIZE,
+		.type		= MT_DEVICE
+	},
+	{
+		.virtual	= IO_ADDRESS(LPC32XX_FABAPB_START),
+		.pfn		= __phys_to_pfn(LPC32XX_FABAPB_START),
+		.length		= LPC32XX_FABAPB_SIZE,
+		.type		= MT_DEVICE
+	},
+	{
+		.virtual	= IO_ADDRESS(LPC32XX_IRAM_BASE),
+		.pfn		= __phys_to_pfn(LPC32XX_IRAM_BASE),
+		.length		= (LPC32XX_IRAM_BANK_SIZE * 2),
+		.type		= MT_DEVICE
+	},
+};
+
+void __init lpc32xx_map_io(void)
+{
+	iotable_init(lpc32xx_io_desc, ARRAY_SIZE(lpc32xx_io_desc));
+}

+ 73 - 0
arch/arm/mach-lpc32xx/common.h

@@ -0,0 +1,73 @@
+/*
+ * arch/arm/mach-lpc32xx/common.h
+ *
+ * Author: Kevin Wells <kevin.wells@nxp.com>
+ *
+ * Copyright (C) 2009-2010 NXP Semiconductors
+ *
+ * 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.
+ */
+
+#ifndef __LPC32XX_COMMON_H
+#define __LPC32XX_COMMON_H
+
+#include <linux/platform_device.h>
+
+/*
+ * Arch specific platform device structures
+ */
+extern struct platform_device lpc32xx_watchdog_device;
+extern struct platform_device lpc32xx_i2c0_device;
+extern struct platform_device lpc32xx_i2c1_device;
+extern struct platform_device lpc32xx_i2c2_device;
+
+/*
+ * Other arch specific structures and functions
+ */
+extern struct sys_timer lpc32xx_timer;
+extern void __init lpc32xx_init_irq(void);
+extern void __init lpc32xx_map_io(void);
+extern void __init lpc32xx_serial_init(void);
+extern void __init lpc32xx_gpio_init(void);
+
+/*
+ * Structure used for setting up and querying the PLLS
+ */
+struct clk_pll_setup {
+	int analog_on;
+	int cco_bypass_b15;
+	int direct_output_b14;
+	int fdbk_div_ctrl_b13;
+	int pll_p;
+	int pll_n;
+	u32 pll_m;
+};
+
+extern int clk_is_sysclk_mainosc(void);
+extern u32 clk_check_pll_setup(u32 ifreq, struct clk_pll_setup *pllsetup);
+extern u32 clk_get_pllrate_from_reg(u32 inputclk, u32 regval);
+extern u32 clk_get_pclk_div(void);
+
+/*
+ * Returns the LPC32xx unique 128-bit chip ID
+ */
+extern void lpc32xx_get_uid(u32 devid[4]);
+
+extern void lpc32xx_watchdog_reset(void);
+extern u32 lpc32xx_return_iram_size(void);
+
+/*
+ * Pointers used for sizing and copying suspend function data
+ */
+extern int lpc32xx_sys_suspend(void);
+extern int lpc32xx_sys_suspend_sz;
+
+#endif

+ 446 - 0
arch/arm/mach-lpc32xx/gpiolib.c

@@ -0,0 +1,446 @@
+/*
+ * arch/arm/mach-lpc32xx/gpiolib.c
+ *
+ * Author: Kevin Wells <kevin.wells@nxp.com>
+ *
+ * Copyright (C) 2010 NXP Semiconductors
+ *
+ * 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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/errno.h>
+#include <linux/gpio.h>
+
+#include <mach/hardware.h>
+#include <mach/platform.h>
+#include "common.h"
+
+#define LPC32XX_GPIO_P3_INP_STATE		_GPREG(0x000)
+#define LPC32XX_GPIO_P3_OUTP_SET		_GPREG(0x004)
+#define LPC32XX_GPIO_P3_OUTP_CLR		_GPREG(0x008)
+#define LPC32XX_GPIO_P3_OUTP_STATE		_GPREG(0x00C)
+#define LPC32XX_GPIO_P2_DIR_SET			_GPREG(0x010)
+#define LPC32XX_GPIO_P2_DIR_CLR			_GPREG(0x014)
+#define LPC32XX_GPIO_P2_DIR_STATE		_GPREG(0x018)
+#define LPC32XX_GPIO_P2_INP_STATE		_GPREG(0x01C)
+#define LPC32XX_GPIO_P2_OUTP_SET		_GPREG(0x020)
+#define LPC32XX_GPIO_P2_OUTP_CLR		_GPREG(0x024)
+#define LPC32XX_GPIO_P2_MUX_SET			_GPREG(0x028)
+#define LPC32XX_GPIO_P2_MUX_CLR			_GPREG(0x02C)
+#define LPC32XX_GPIO_P2_MUX_STATE		_GPREG(0x030)
+#define LPC32XX_GPIO_P0_INP_STATE		_GPREG(0x040)
+#define LPC32XX_GPIO_P0_OUTP_SET		_GPREG(0x044)
+#define LPC32XX_GPIO_P0_OUTP_CLR		_GPREG(0x048)
+#define LPC32XX_GPIO_P0_OUTP_STATE		_GPREG(0x04C)
+#define LPC32XX_GPIO_P0_DIR_SET			_GPREG(0x050)
+#define LPC32XX_GPIO_P0_DIR_CLR			_GPREG(0x054)
+#define LPC32XX_GPIO_P0_DIR_STATE		_GPREG(0x058)
+#define LPC32XX_GPIO_P1_INP_STATE		_GPREG(0x060)
+#define LPC32XX_GPIO_P1_OUTP_SET		_GPREG(0x064)
+#define LPC32XX_GPIO_P1_OUTP_CLR		_GPREG(0x068)
+#define LPC32XX_GPIO_P1_OUTP_STATE		_GPREG(0x06C)
+#define LPC32XX_GPIO_P1_DIR_SET			_GPREG(0x070)
+#define LPC32XX_GPIO_P1_DIR_CLR			_GPREG(0x074)
+#define LPC32XX_GPIO_P1_DIR_STATE		_GPREG(0x078)
+
+#define GPIO012_PIN_TO_BIT(x)			(1 << (x))
+#define GPIO3_PIN_TO_BIT(x)			(1 << ((x) + 25))
+#define GPO3_PIN_TO_BIT(x)			(1 << (x))
+#define GPIO012_PIN_IN_SEL(x, y)		(((x) >> (y)) & 1)
+#define GPIO3_PIN_IN_SHIFT(x)			((x) == 5 ? 24 : 10 + (x))
+#define GPIO3_PIN_IN_SEL(x, y)			((x) >> GPIO3_PIN_IN_SHIFT(y))
+#define GPIO3_PIN5_IN_SEL(x)			(((x) >> 24) & 1)
+#define GPI3_PIN_IN_SEL(x, y)			(((x) >> (y)) & 1)
+
+struct gpio_regs {
+	void __iomem *inp_state;
+	void __iomem *outp_set;
+	void __iomem *outp_clr;
+	void __iomem *dir_set;
+	void __iomem *dir_clr;
+};
+
+/*
+ * GPIO names
+ */
+static const char *gpio_p0_names[LPC32XX_GPIO_P0_MAX] = {
+	"p0.0", "p0.1", "p0.2", "p0.3",
+	"p0.4", "p0.5", "p0.6", "p0.7"
+};
+
+static const char *gpio_p1_names[LPC32XX_GPIO_P1_MAX] = {
+	"p1.0", "p1.1", "p1.2", "p1.3",
+	"p1.4", "p1.5", "p1.6", "p1.7",
+	"p1.8", "p1.9", "p1.10", "p1.11",
+	"p1.12", "p1.13", "p1.14", "p1.15",
+	"p1.16", "p1.17", "p1.18", "p1.19",
+	"p1.20", "p1.21", "p1.22", "p1.23",
+};
+
+static const char *gpio_p2_names[LPC32XX_GPIO_P2_MAX] = {
+	"p2.0", "p2.1", "p2.2", "p2.3",
+	"p2.4", "p2.5", "p2.6", "p2.7",
+	"p2.8", "p2.9", "p2.10", "p2.11",
+	"p2.12"
+};
+
+static const char *gpio_p3_names[LPC32XX_GPIO_P3_MAX] = {
+	"gpi000", "gpio01", "gpio02", "gpio03",
+	"gpio04", "gpio05"
+};
+
+static const char *gpi_p3_names[LPC32XX_GPI_P3_MAX] = {
+	"gpi00", "gpi01", "gpi02", "gpi03",
+	"gpi04", "gpi05", "gpi06", "gpi07",
+	"gpi08", "gpi09",  NULL,    NULL,
+	 NULL,    NULL,    NULL,   "gpi15",
+	"gpi16", "gpi17", "gpi18", "gpi19",
+	"gpi20", "gpi21", "gpi22", "gpi23",
+	"gpi24", "gpi25", "gpi26", "gpi27"
+};
+
+static const char *gpo_p3_names[LPC32XX_GPO_P3_MAX] = {
+	"gpo00", "gpo01", "gpo02", "gpo03",
+	"gpo04", "gpo05", "gpo06", "gpo07",
+	"gpo08", "gpo09", "gpo10", "gpo11",
+	"gpo12", "gpo13", "gpo14", "gpo15",
+	"gpo16", "gpo17", "gpo18", "gpo19",
+	"gpo20", "gpo21", "gpo22", "gpo23"
+};
+
+static struct gpio_regs gpio_grp_regs_p0 = {
+	.inp_state	= LPC32XX_GPIO_P0_INP_STATE,
+	.outp_set	= LPC32XX_GPIO_P0_OUTP_SET,
+	.outp_clr	= LPC32XX_GPIO_P0_OUTP_CLR,
+	.dir_set	= LPC32XX_GPIO_P0_DIR_SET,
+	.dir_clr	= LPC32XX_GPIO_P0_DIR_CLR,
+};
+
+static struct gpio_regs gpio_grp_regs_p1 = {
+	.inp_state	= LPC32XX_GPIO_P1_INP_STATE,
+	.outp_set	= LPC32XX_GPIO_P1_OUTP_SET,
+	.outp_clr	= LPC32XX_GPIO_P1_OUTP_CLR,
+	.dir_set	= LPC32XX_GPIO_P1_DIR_SET,
+	.dir_clr	= LPC32XX_GPIO_P1_DIR_CLR,
+};
+
+static struct gpio_regs gpio_grp_regs_p2 = {
+	.inp_state	= LPC32XX_GPIO_P2_INP_STATE,
+	.outp_set	= LPC32XX_GPIO_P2_OUTP_SET,
+	.outp_clr	= LPC32XX_GPIO_P2_OUTP_CLR,
+	.dir_set	= LPC32XX_GPIO_P2_DIR_SET,
+	.dir_clr	= LPC32XX_GPIO_P2_DIR_CLR,
+};
+
+static struct gpio_regs gpio_grp_regs_p3 = {
+	.inp_state	= LPC32XX_GPIO_P3_INP_STATE,
+	.outp_set	= LPC32XX_GPIO_P3_OUTP_SET,
+	.outp_clr	= LPC32XX_GPIO_P3_OUTP_CLR,
+	.dir_set	= LPC32XX_GPIO_P2_DIR_SET,
+	.dir_clr	= LPC32XX_GPIO_P2_DIR_CLR,
+};
+
+struct lpc32xx_gpio_chip {
+	struct gpio_chip	chip;
+	struct gpio_regs	*gpio_grp;
+};
+
+static inline struct lpc32xx_gpio_chip *to_lpc32xx_gpio(
+	struct gpio_chip *gpc)
+{
+	return container_of(gpc, struct lpc32xx_gpio_chip, chip);
+}
+
+static void __set_gpio_dir_p012(struct lpc32xx_gpio_chip *group,
+	unsigned pin, int input)
+{
+	if (input)
+		__raw_writel(GPIO012_PIN_TO_BIT(pin),
+			group->gpio_grp->dir_clr);
+	else
+		__raw_writel(GPIO012_PIN_TO_BIT(pin),
+			group->gpio_grp->dir_set);
+}
+
+static void __set_gpio_dir_p3(struct lpc32xx_gpio_chip *group,
+	unsigned pin, int input)
+{
+	u32 u = GPIO3_PIN_TO_BIT(pin);
+
+	if (input)
+		__raw_writel(u, group->gpio_grp->dir_clr);
+	else
+		__raw_writel(u, group->gpio_grp->dir_set);
+}
+
+static void __set_gpio_level_p012(struct lpc32xx_gpio_chip *group,
+	unsigned pin, int high)
+{
+	if (high)
+		__raw_writel(GPIO012_PIN_TO_BIT(pin),
+			group->gpio_grp->outp_set);
+	else
+		__raw_writel(GPIO012_PIN_TO_BIT(pin),
+			group->gpio_grp->outp_clr);
+}
+
+static void __set_gpio_level_p3(struct lpc32xx_gpio_chip *group,
+	unsigned pin, int high)
+{
+	u32 u = GPIO3_PIN_TO_BIT(pin);
+
+	if (high)
+		__raw_writel(u, group->gpio_grp->outp_set);
+	else
+		__raw_writel(u, group->gpio_grp->outp_clr);
+}
+
+static void __set_gpo_level_p3(struct lpc32xx_gpio_chip *group,
+	unsigned pin, int high)
+{
+	if (high)
+		__raw_writel(GPO3_PIN_TO_BIT(pin), group->gpio_grp->outp_set);
+	else
+		__raw_writel(GPO3_PIN_TO_BIT(pin), group->gpio_grp->outp_clr);
+}
+
+static int __get_gpio_state_p012(struct lpc32xx_gpio_chip *group,
+	unsigned pin)
+{
+	return GPIO012_PIN_IN_SEL(__raw_readl(group->gpio_grp->inp_state),
+		pin);
+}
+
+static int __get_gpio_state_p3(struct lpc32xx_gpio_chip *group,
+	unsigned pin)
+{
+	int state = __raw_readl(group->gpio_grp->inp_state);
+
+	/*
+	 * P3 GPIO pin input mapping is not contiguous, GPIOP3-0..4 is mapped
+	 * to bits 10..14, while GPIOP3-5 is mapped to bit 24.
+	 */
+	return GPIO3_PIN_IN_SEL(state, pin);
+}
+
+static int __get_gpi_state_p3(struct lpc32xx_gpio_chip *group,
+	unsigned pin)
+{
+	return GPI3_PIN_IN_SEL(__raw_readl(group->gpio_grp->inp_state), pin);
+}
+
+/*
+ * GENERIC_GPIO primitives.
+ */
+static int lpc32xx_gpio_dir_input_p012(struct gpio_chip *chip,
+	unsigned pin)
+{
+	struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip);
+
+	__set_gpio_dir_p012(group, pin, 1);
+
+	return 0;
+}
+
+static int lpc32xx_gpio_dir_input_p3(struct gpio_chip *chip,
+	unsigned pin)
+{
+	struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip);
+
+	__set_gpio_dir_p3(group, pin, 1);
+
+	return 0;
+}
+
+static int lpc32xx_gpio_dir_in_always(struct gpio_chip *chip,
+	unsigned pin)
+{
+	return 0;
+}
+
+static int lpc32xx_gpio_get_value_p012(struct gpio_chip *chip, unsigned pin)
+{
+	struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip);
+
+	return __get_gpio_state_p012(group, pin);
+}
+
+static int lpc32xx_gpio_get_value_p3(struct gpio_chip *chip, unsigned pin)
+{
+	struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip);
+
+	return __get_gpio_state_p3(group, pin);
+}
+
+static int lpc32xx_gpi_get_value(struct gpio_chip *chip, unsigned pin)
+{
+	struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip);
+
+	return __get_gpi_state_p3(group, pin);
+}
+
+static int lpc32xx_gpio_dir_output_p012(struct gpio_chip *chip, unsigned pin,
+	int value)
+{
+	struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip);
+
+	__set_gpio_dir_p012(group, pin, 0);
+
+	return 0;
+}
+
+static int lpc32xx_gpio_dir_output_p3(struct gpio_chip *chip, unsigned pin,
+	int value)
+{
+	struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip);
+
+	__set_gpio_dir_p3(group, pin, 0);
+
+	return 0;
+}
+
+static int lpc32xx_gpio_dir_out_always(struct gpio_chip *chip, unsigned pin,
+	int value)
+{
+	return 0;
+}
+
+static void lpc32xx_gpio_set_value_p012(struct gpio_chip *chip, unsigned pin,
+	int value)
+{
+	struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip);
+
+	__set_gpio_level_p012(group, pin, value);
+}
+
+static void lpc32xx_gpio_set_value_p3(struct gpio_chip *chip, unsigned pin,
+	int value)
+{
+	struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip);
+
+	__set_gpio_level_p3(group, pin, value);
+}
+
+static void lpc32xx_gpo_set_value(struct gpio_chip *chip, unsigned pin,
+	int value)
+{
+	struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip);
+
+	__set_gpo_level_p3(group, pin, value);
+}
+
+static int lpc32xx_gpio_request(struct gpio_chip *chip, unsigned pin)
+{
+	if (pin < chip->ngpio)
+		return 0;
+
+	return -EINVAL;
+}
+
+static struct lpc32xx_gpio_chip lpc32xx_gpiochip[] = {
+	{
+		.chip = {
+			.label			= "gpio_p0",
+			.direction_input	= lpc32xx_gpio_dir_input_p012,
+			.get			= lpc32xx_gpio_get_value_p012,
+			.direction_output	= lpc32xx_gpio_dir_output_p012,
+			.set			= lpc32xx_gpio_set_value_p012,
+			.request		= lpc32xx_gpio_request,
+			.base			= LPC32XX_GPIO_P0_GRP,
+			.ngpio			= LPC32XX_GPIO_P0_MAX,
+			.names			= gpio_p0_names,
+			.can_sleep		= 0,
+		},
+		.gpio_grp = &gpio_grp_regs_p0,
+	},
+	{
+		.chip = {
+			.label			= "gpio_p1",
+			.direction_input	= lpc32xx_gpio_dir_input_p012,
+			.get			= lpc32xx_gpio_get_value_p012,
+			.direction_output	= lpc32xx_gpio_dir_output_p012,
+			.set			= lpc32xx_gpio_set_value_p012,
+			.request		= lpc32xx_gpio_request,
+			.base			= LPC32XX_GPIO_P1_GRP,
+			.ngpio			= LPC32XX_GPIO_P1_MAX,
+			.names			= gpio_p1_names,
+			.can_sleep		= 0,
+		},
+		.gpio_grp = &gpio_grp_regs_p1,
+	},
+	{
+		.chip = {
+			.label			= "gpio_p2",
+			.direction_input	= lpc32xx_gpio_dir_input_p012,
+			.get			= lpc32xx_gpio_get_value_p012,
+			.direction_output	= lpc32xx_gpio_dir_output_p012,
+			.set			= lpc32xx_gpio_set_value_p012,
+			.request		= lpc32xx_gpio_request,
+			.base			= LPC32XX_GPIO_P2_GRP,
+			.ngpio			= LPC32XX_GPIO_P2_MAX,
+			.names			= gpio_p2_names,
+			.can_sleep		= 0,
+		},
+		.gpio_grp = &gpio_grp_regs_p2,
+	},
+	{
+		.chip = {
+			.label			= "gpio_p3",
+			.direction_input	= lpc32xx_gpio_dir_input_p3,
+			.get			= lpc32xx_gpio_get_value_p3,
+			.direction_output	= lpc32xx_gpio_dir_output_p3,
+			.set			= lpc32xx_gpio_set_value_p3,
+			.request		= lpc32xx_gpio_request,
+			.base			= LPC32XX_GPIO_P3_GRP,
+			.ngpio			= LPC32XX_GPIO_P3_MAX,
+			.names			= gpio_p3_names,
+			.can_sleep		= 0,
+		},
+		.gpio_grp = &gpio_grp_regs_p3,
+	},
+	{
+		.chip = {
+			.label			= "gpi_p3",
+			.direction_input	= lpc32xx_gpio_dir_in_always,
+			.get			= lpc32xx_gpi_get_value,
+			.request		= lpc32xx_gpio_request,
+			.base			= LPC32XX_GPI_P3_GRP,
+			.ngpio			= LPC32XX_GPI_P3_MAX,
+			.names			= gpi_p3_names,
+			.can_sleep		= 0,
+		},
+		.gpio_grp = &gpio_grp_regs_p3,
+	},
+	{
+		.chip = {
+			.label			= "gpo_p3",
+			.direction_output	= lpc32xx_gpio_dir_out_always,
+			.set			= lpc32xx_gpo_set_value,
+			.request		= lpc32xx_gpio_request,
+			.base			= LPC32XX_GPO_P3_GRP,
+			.ngpio			= LPC32XX_GPO_P3_MAX,
+			.names			= gpo_p3_names,
+			.can_sleep		= 0,
+		},
+		.gpio_grp = &gpio_grp_regs_p3,
+	},
+};
+
+void __init lpc32xx_gpio_init(void)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(lpc32xx_gpiochip); i++)
+		gpiochip_add(&lpc32xx_gpiochip[i].chip);
+}

+ 25 - 0
arch/arm/mach-lpc32xx/include/mach/clkdev.h

@@ -0,0 +1,25 @@
+/*
+ * arch/arm/mach-lpc32xx/include/mach/clkdev.h
+ *
+ * Author: Kevin Wells <kevin.wells@nxp.com>
+ *
+ * Copyright (C) 2010 NXP Semiconductors
+ *
+ * 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.
+ */
+
+#ifndef __ASM_ARCH_CLKDEV_H
+#define __ASM_ARCH_CLKDEV_H
+
+#define __clk_get(clk) ({ 1; })
+#define __clk_put(clk) do { } while (0)
+
+#endif

+ 31 - 0
arch/arm/mach-lpc32xx/include/mach/debug-macro.S

@@ -0,0 +1,31 @@
+/*
+ * arch/arm/mach-lpc32xx/include/mach/debug-macro.S
+ *
+ * Author: Kevin Wells <kevin.wells@nxp.com>
+ *
+ * Copyright (C) 2010 NXP Semiconductors
+ *
+ * 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.
+ */
+
+/*
+ * Debug output is hardcoded to standard UART 5
+*/
+
+	.macro	addruart,rx, tmp
+	mrc	p15, 0, \rx, c1, c0
+	tst	\rx, #1				@ MMU enabled?
+	ldreq	\rx, =0x40090000
+	ldrne	\rx, =0xF4090000
+	.endm
+
+#define UART_SHIFT	2
+#include <asm/hardware/debug-8250.S>

+ 47 - 0
arch/arm/mach-lpc32xx/include/mach/entry-macro.S

@@ -0,0 +1,47 @@
+/*
+ * arch/arm/mach-lpc32xx/include/mach/entry-macro.S
+ *
+ * Author: Kevin Wells <kevin.wells@nxp.com>
+ *
+ * Copyright (C) 2010 NXP Semiconductors
+ *
+ * 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.
+ */
+
+#include <mach/hardware.h>
+#include <mach/platform.h>
+
+#define LPC32XX_INTC_MASKED_STATUS_OFS	0x8
+
+	.macro	disable_fiq
+	.endm
+
+	.macro  get_irqnr_preamble, base, tmp
+	ldr	\base, =IO_ADDRESS(LPC32XX_MIC_BASE)
+	.endm
+
+	.macro  arch_ret_to_user, tmp1, tmp2
+	.endm
+
+/*
+ * Return IRQ number in irqnr. Also return processor Z flag status in CPSR
+ * as set if an interrupt is pending.
+ */
+	.macro	get_irqnr_and_base, irqnr, irqstat, base, tmp
+	ldr	\irqstat, [\base, #LPC32XX_INTC_MASKED_STATUS_OFS]
+	clz	\irqnr, \irqstat
+	rsb	\irqnr, \irqnr, #31
+	teq	\irqstat, #0
+	.endm
+
+	.macro	irq_prio_table
+	.endm
+

+ 74 - 0
arch/arm/mach-lpc32xx/include/mach/gpio.h

@@ -0,0 +1,74 @@
+/*
+ * arch/arm/mach-lpc32xx/include/mach/gpio.h
+ *
+ * Author: Kevin Wells <kevin.wells@nxp.com>
+ *
+ * Copyright (C) 2010 NXP Semiconductors
+ *
+ * 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.
+ */
+
+#ifndef __ASM_ARCH_GPIO_H
+#define __ASM_ARCH_GPIO_H
+
+#include <asm-generic/gpio.h>
+
+/*
+ * Note!
+ * Muxed GP pins need to be setup to the GP state in the board level
+ * code prior to using this driver.
+ * GPI pins : 28xP3 group
+ * GPO pins : 24xP3 group
+ * GPIO pins: 8xP0 group, 24xP1 group, 13xP2 group, 6xP3 group
+ */
+
+#define LPC32XX_GPIO_P0_MAX 8
+#define LPC32XX_GPIO_P1_MAX 24
+#define LPC32XX_GPIO_P2_MAX 13
+#define LPC32XX_GPIO_P3_MAX 6
+#define LPC32XX_GPI_P3_MAX 28
+#define LPC32XX_GPO_P3_MAX 24
+
+#define LPC32XX_GPIO_P0_GRP 0
+#define LPC32XX_GPIO_P1_GRP (LPC32XX_GPIO_P0_GRP + LPC32XX_GPIO_P0_MAX)
+#define LPC32XX_GPIO_P2_GRP (LPC32XX_GPIO_P1_GRP + LPC32XX_GPIO_P1_MAX)
+#define LPC32XX_GPIO_P3_GRP (LPC32XX_GPIO_P2_GRP + LPC32XX_GPIO_P2_MAX)
+#define LPC32XX_GPI_P3_GRP (LPC32XX_GPIO_P3_GRP + LPC32XX_GPIO_P3_MAX)
+#define LPC32XX_GPO_P3_GRP (LPC32XX_GPI_P3_GRP + LPC32XX_GPI_P3_MAX)
+
+/*
+ * A specific GPIO can be selected with this macro
+ * ie, GPIO_05 can be selected with LPC32XX_GPIO(LPC32XX_GPIO_P3_GRP, 5)
+ * See the LPC32x0 User's guide for GPIO group numbers
+ */
+#define LPC32XX_GPIO(x, y) ((x) + (y))
+
+static inline int gpio_get_value(unsigned gpio)
+{
+	return __gpio_get_value(gpio);
+}
+
+static inline void gpio_set_value(unsigned gpio, int value)
+{
+	__gpio_set_value(gpio, value);
+}
+
+static inline int gpio_cansleep(unsigned gpio)
+{
+	return __gpio_cansleep(gpio);
+}
+
+static inline int gpio_to_irq(unsigned gpio)
+{
+	return __gpio_to_irq(gpio);
+}
+
+#endif

+ 34 - 0
arch/arm/mach-lpc32xx/include/mach/hardware.h

@@ -0,0 +1,34 @@
+/*
+ * arch/arm/mach-lpc32xx/include/mach/hardware.h
+ *
+ * Copyright (c) 2005 MontaVista Software, Inc. <source@mvista.com>
+ *
+ * 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.
+ */
+
+#ifndef __ASM_ARCH_HARDWARE_H
+#define __ASM_ARCH_HARDWARE_H
+
+/*
+ * Start of virtual addresses for IO devices
+ */
+#define IO_BASE		0xF0000000
+
+/*
+ * This macro relies on fact that for all HW i/o addresses bits 20-23 are 0
+ */
+#define IO_ADDRESS(x)	(((((x) & 0xff000000) >> 4) | ((x) & 0xfffff)) |\
+			 IO_BASE)
+
+#define io_p2v(x)	((void __iomem *) (unsigned long) IO_ADDRESS(x))
+#define io_v2p(x)	((((x) & 0x0ff00000) << 4) | ((x) & 0x000fffff))
+
+#endif

+ 63 - 0
arch/arm/mach-lpc32xx/include/mach/i2c.h

@@ -0,0 +1,63 @@
+/*
+ * PNX4008-specific tweaks for I2C IP3204 block
+ *
+ * Author: Vitaly Wool <vwool@ru.mvista.com>
+ *
+ * 2005 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#ifndef __ASM_ARCH_I2C_H
+#define __ASM_ARCH_I2C_H
+
+enum {
+	mstatus_tdi = 0x00000001,
+	mstatus_afi = 0x00000002,
+	mstatus_nai = 0x00000004,
+	mstatus_drmi = 0x00000008,
+	mstatus_active = 0x00000020,
+	mstatus_scl = 0x00000040,
+	mstatus_sda = 0x00000080,
+	mstatus_rff = 0x00000100,
+	mstatus_rfe = 0x00000200,
+	mstatus_tff = 0x00000400,
+	mstatus_tfe = 0x00000800,
+};
+
+enum {
+	mcntrl_tdie = 0x00000001,
+	mcntrl_afie = 0x00000002,
+	mcntrl_naie = 0x00000004,
+	mcntrl_drmie = 0x00000008,
+	mcntrl_daie = 0x00000020,
+	mcntrl_rffie = 0x00000040,
+	mcntrl_tffie = 0x00000080,
+	mcntrl_reset = 0x00000100,
+	mcntrl_cdbmode = 0x00000400,
+};
+
+enum {
+	rw_bit = 1 << 0,
+	start_bit = 1 << 8,
+	stop_bit = 1 << 9,
+};
+
+#define I2C_REG_RX(a)	((a)->ioaddr)		/* Rx FIFO reg (RO) */
+#define I2C_REG_TX(a)	((a)->ioaddr)		/* Tx FIFO reg (WO) */
+#define I2C_REG_STS(a)	((a)->ioaddr + 0x04)	/* Status reg (RO) */
+#define I2C_REG_CTL(a)	((a)->ioaddr + 0x08)	/* Ctl reg */
+#define I2C_REG_CKL(a)	((a)->ioaddr + 0x0c)	/* Clock divider low */
+#define I2C_REG_CKH(a)	((a)->ioaddr + 0x10)	/* Clock divider high */
+#define I2C_REG_ADR(a)	((a)->ioaddr + 0x14)	/* I2C address */
+#define I2C_REG_RFL(a)	((a)->ioaddr + 0x18)	/* Rx FIFO level (RO) */
+#define I2C_REG_TFL(a)	((a)->ioaddr + 0x1c)	/* Tx FIFO level (RO) */
+#define I2C_REG_RXB(a)	((a)->ioaddr + 0x20)	/* Num of bytes Rx-ed (RO) */
+#define I2C_REG_TXB(a)	((a)->ioaddr + 0x24)	/* Num of bytes Tx-ed (RO) */
+#define I2C_REG_TXS(a)	((a)->ioaddr + 0x28)	/* Tx slave FIFO (RO) */
+#define I2C_REG_STFL(a)	((a)->ioaddr + 0x2c)	/* Tx slave FIFO level (RO) */
+
+#define I2C_CHIP_NAME		"PNX4008-I2C"
+
+#endif				/* __ASM_ARCH_I2C_H */

+ 27 - 0
arch/arm/mach-lpc32xx/include/mach/io.h

@@ -0,0 +1,27 @@
+/*
+ * arch/arm/mach-lpc32xx/include/mach/io.h
+ *
+ * Author: Kevin Wells <kevin.wells@nxp.com>
+ *
+ * Copyright (C) 2010 NXP Semiconductors
+ *
+ * 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.
+ */
+
+#ifndef __ASM_ARM_ARCH_IO_H
+#define __ASM_ARM_ARCH_IO_H
+
+#define IO_SPACE_LIMIT	0xffffffff
+
+#define __io(a)		__typesafe_io(a)
+#define __mem_pci(a)	(a)
+
+#endif

+ 117 - 0
arch/arm/mach-lpc32xx/include/mach/irqs.h

@@ -0,0 +1,117 @@
+/*
+ * arch/arm/mach-lpc32xx/include/mach/irqs.h
+ *
+ * Author: Kevin Wells <kevin.wells@nxp.com>
+ *
+ * Copyright (C) 2010 NXP Semiconductors
+ *
+ * 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.
+ */
+
+#ifndef __ASM_ARM_ARCH_IRQS_H
+#define __ASM_ARM_ARCH_IRQS_H
+
+#define LPC32XX_SIC1_IRQ(n)		(32 + (n))
+#define LPC32XX_SIC2_IRQ(n)		(64 + (n))
+
+/*
+ * MIC interrupts
+ */
+#define IRQ_LPC32XX_SUB1IRQ		0
+#define IRQ_LPC32XX_SUB2IRQ		1
+#define IRQ_LPC32XX_PWM3		3
+#define IRQ_LPC32XX_PWM4		4
+#define IRQ_LPC32XX_HSTIMER		5
+#define IRQ_LPC32XX_WATCH		6
+#define IRQ_LPC32XX_UART_IIR3		7
+#define IRQ_LPC32XX_UART_IIR4		8
+#define IRQ_LPC32XX_UART_IIR5		9
+#define IRQ_LPC32XX_UART_IIR6		10
+#define IRQ_LPC32XX_FLASH		11
+#define IRQ_LPC32XX_SD1			13
+#define IRQ_LPC32XX_LCD			14
+#define IRQ_LPC32XX_SD0			15
+#define IRQ_LPC32XX_TIMER0		16
+#define IRQ_LPC32XX_TIMER1		17
+#define IRQ_LPC32XX_TIMER2		18
+#define IRQ_LPC32XX_TIMER3		19
+#define IRQ_LPC32XX_SSP0		20
+#define IRQ_LPC32XX_SSP1		21
+#define IRQ_LPC32XX_I2S0		22
+#define IRQ_LPC32XX_I2S1		23
+#define IRQ_LPC32XX_UART_IIR7		24
+#define IRQ_LPC32XX_UART_IIR2		25
+#define IRQ_LPC32XX_UART_IIR1		26
+#define IRQ_LPC32XX_MSTIMER		27
+#define IRQ_LPC32XX_DMA			28
+#define IRQ_LPC32XX_ETHERNET		29
+#define IRQ_LPC32XX_SUB1FIQ		30
+#define IRQ_LPC32XX_SUB2FIQ		31
+
+/*
+ * SIC1 interrupts start at offset 32
+ */
+#define IRQ_LPC32XX_JTAG_COMM_TX	LPC32XX_SIC1_IRQ(1)
+#define IRQ_LPC32XX_JTAG_COMM_RX	LPC32XX_SIC1_IRQ(2)
+#define IRQ_LPC32XX_GPI_11		LPC32XX_SIC1_IRQ(4)
+#define IRQ_LPC32XX_TS_P		LPC32XX_SIC1_IRQ(6)
+#define IRQ_LPC32XX_TS_IRQ		LPC32XX_SIC1_IRQ(7)
+#define IRQ_LPC32XX_TS_AUX		LPC32XX_SIC1_IRQ(8)
+#define IRQ_LPC32XX_SPI2		LPC32XX_SIC1_IRQ(12)
+#define IRQ_LPC32XX_PLLUSB		LPC32XX_SIC1_IRQ(13)
+#define IRQ_LPC32XX_PLLHCLK		LPC32XX_SIC1_IRQ(14)
+#define IRQ_LPC32XX_PLL397		LPC32XX_SIC1_IRQ(17)
+#define IRQ_LPC32XX_I2C_2		LPC32XX_SIC1_IRQ(18)
+#define IRQ_LPC32XX_I2C_1		LPC32XX_SIC1_IRQ(19)
+#define IRQ_LPC32XX_RTC			LPC32XX_SIC1_IRQ(20)
+#define IRQ_LPC32XX_KEY			LPC32XX_SIC1_IRQ(22)
+#define IRQ_LPC32XX_SPI1		LPC32XX_SIC1_IRQ(23)
+#define IRQ_LPC32XX_SW			LPC32XX_SIC1_IRQ(24)
+#define IRQ_LPC32XX_USB_OTG_TIMER	LPC32XX_SIC1_IRQ(25)
+#define IRQ_LPC32XX_USB_OTG_ATX		LPC32XX_SIC1_IRQ(26)
+#define IRQ_LPC32XX_USB_HOST		LPC32XX_SIC1_IRQ(27)
+#define IRQ_LPC32XX_USB_DEV_DMA		LPC32XX_SIC1_IRQ(28)
+#define IRQ_LPC32XX_USB_DEV_LP		LPC32XX_SIC1_IRQ(29)
+#define IRQ_LPC32XX_USB_DEV_HP		LPC32XX_SIC1_IRQ(30)
+#define IRQ_LPC32XX_USB_I2C		LPC32XX_SIC1_IRQ(31)
+
+/*
+ * SIC2 interrupts start at offset 64
+ */
+#define IRQ_LPC32XX_GPIO_00		LPC32XX_SIC2_IRQ(0)
+#define IRQ_LPC32XX_GPIO_01		LPC32XX_SIC2_IRQ(1)
+#define IRQ_LPC32XX_GPIO_02		LPC32XX_SIC2_IRQ(2)
+#define IRQ_LPC32XX_GPIO_03		LPC32XX_SIC2_IRQ(3)
+#define IRQ_LPC32XX_GPIO_04		LPC32XX_SIC2_IRQ(4)
+#define IRQ_LPC32XX_GPIO_05		LPC32XX_SIC2_IRQ(5)
+#define IRQ_LPC32XX_SPI2_DATAIN		LPC32XX_SIC2_IRQ(6)
+#define IRQ_LPC32XX_U2_HCTS		LPC32XX_SIC2_IRQ(7)
+#define IRQ_LPC32XX_P0_P1_IRQ		LPC32XX_SIC2_IRQ(8)
+#define IRQ_LPC32XX_GPI_08		LPC32XX_SIC2_IRQ(9)
+#define IRQ_LPC32XX_GPI_09		LPC32XX_SIC2_IRQ(10)
+#define IRQ_LPC32XX_GPI_19		LPC32XX_SIC2_IRQ(11)
+#define IRQ_LPC32XX_U7_HCTS		LPC32XX_SIC2_IRQ(12)
+#define IRQ_LPC32XX_GPI_07		LPC32XX_SIC2_IRQ(15)
+#define IRQ_LPC32XX_SDIO		LPC32XX_SIC2_IRQ(18)
+#define IRQ_LPC32XX_U5_RX		LPC32XX_SIC2_IRQ(19)
+#define IRQ_LPC32XX_SPI1_DATAIN		LPC32XX_SIC2_IRQ(20)
+#define IRQ_LPC32XX_GPI_00		LPC32XX_SIC2_IRQ(22)
+#define IRQ_LPC32XX_GPI_01		LPC32XX_SIC2_IRQ(23)
+#define IRQ_LPC32XX_GPI_02		LPC32XX_SIC2_IRQ(24)
+#define IRQ_LPC32XX_GPI_03		LPC32XX_SIC2_IRQ(25)
+#define IRQ_LPC32XX_GPI_04		LPC32XX_SIC2_IRQ(26)
+#define IRQ_LPC32XX_GPI_05		LPC32XX_SIC2_IRQ(27)
+#define IRQ_LPC32XX_GPI_06		LPC32XX_SIC2_IRQ(28)
+#define IRQ_LPC32XX_SYSCLK		LPC32XX_SIC2_IRQ(31)
+
+#define NR_IRQS				96
+
+#endif

+ 27 - 0
arch/arm/mach-lpc32xx/include/mach/memory.h

@@ -0,0 +1,27 @@
+/*
+ * arch/arm/mach-lpc32xx/include/mach/memory.h
+ *
+ * Author: Kevin Wells <kevin.wells@nxp.com>
+ *
+ * Copyright (C) 2010 NXP Semiconductors
+ *
+ * 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.
+ */
+
+#ifndef __ASM_ARCH_MEMORY_H
+#define __ASM_ARCH_MEMORY_H
+
+/*
+ * Physical DRAM offset of bank 0
+ */
+#define PHYS_OFFSET	UL(0x80000000)
+
+#endif

+ 694 - 0
arch/arm/mach-lpc32xx/include/mach/platform.h

@@ -0,0 +1,694 @@
+/*
+ * arch/arm/mach-lpc32xx/include/mach/platform.h
+ *
+ * Author: Kevin Wells <kevin.wells@nxp.com>
+ *
+ * Copyright (C) 2010 NXP Semiconductors
+ *
+ * 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.
+ */
+
+#ifndef __ASM_ARCH_PLATFORM_H
+#define __ASM_ARCH_PLATFORM_H
+
+#define _SBF(f, v)				((v) << (f))
+#define _BIT(n)					_SBF(n, 1)
+
+/*
+ * AHB 0 physical base addresses
+ */
+#define LPC32XX_SLC_BASE			0x20020000
+#define LPC32XX_SSP0_BASE			0x20084000
+#define LPC32XX_SPI1_BASE			0x20088000
+#define LPC32XX_SSP1_BASE			0x2008C000
+#define LPC32XX_SPI2_BASE			0x20090000
+#define LPC32XX_I2S0_BASE			0x20094000
+#define LPC32XX_SD_BASE				0x20098000
+#define LPC32XX_I2S1_BASE			0x2009C000
+#define LPC32XX_MLC_BASE			0x200A8000
+#define LPC32XX_AHB0_START			LPC32XX_SLC_BASE
+#define LPC32XX_AHB0_SIZE			0x00089000
+
+/*
+ * AHB 1 physical base addresses
+ */
+#define LPC32XX_DMA_BASE			0x31000000
+#define LPC32XX_USB_BASE			0x31020000
+#define LPC32XX_USBH_BASE			0x31020000
+#define LPC32XX_USB_OTG_BASE			0x31020000
+#define LPC32XX_OTG_I2C_BASE			0x31020300
+#define LPC32XX_LCD_BASE			0x31040000
+#define LPC32XX_ETHERNET_BASE			0x31060000
+#define LPC32XX_EMC_BASE			0x31080000
+#define LPC32XX_ETB_CFG_BASE			0x310C0000
+#define LPC32XX_ETB_DATA_BASE			0x310E0000
+#define LPC32XX_AHB1_START			LPC32XX_DMA_BASE
+#define LPC32XX_AHB1_SIZE			0x000E1000
+
+/*
+ * FAB physical base addresses
+ */
+#define LPC32XX_CLK_PM_BASE			0x40004000
+#define LPC32XX_MIC_BASE			0x40008000
+#define LPC32XX_SIC1_BASE			0x4000C000
+#define LPC32XX_SIC2_BASE			0x40010000
+#define LPC32XX_HS_UART1_BASE			0x40014000
+#define LPC32XX_HS_UART2_BASE			0x40018000
+#define LPC32XX_HS_UART7_BASE			0x4001C000
+#define LPC32XX_RTC_BASE			0x40024000
+#define LPC32XX_RTC_RAM_BASE			0x40024080
+#define LPC32XX_GPIO_BASE			0x40028000
+#define LPC32XX_PWM3_BASE			0x4002C000
+#define LPC32XX_PWM4_BASE			0x40030000
+#define LPC32XX_MSTIM_BASE			0x40034000
+#define LPC32XX_HSTIM_BASE			0x40038000
+#define LPC32XX_WDTIM_BASE			0x4003C000
+#define LPC32XX_DEBUG_CTRL_BASE			0x40040000
+#define LPC32XX_TIMER0_BASE			0x40044000
+#define LPC32XX_ADC_BASE			0x40048000
+#define LPC32XX_TIMER1_BASE			0x4004C000
+#define LPC32XX_KSCAN_BASE			0x40050000
+#define LPC32XX_UART_CTRL_BASE			0x40054000
+#define LPC32XX_TIMER2_BASE			0x40058000
+#define LPC32XX_PWM1_BASE			0x4005C000
+#define LPC32XX_PWM2_BASE			0x4005C004
+#define LPC32XX_TIMER3_BASE			0x40060000
+
+/*
+ * APB physical base addresses
+ */
+#define LPC32XX_UART3_BASE			0x40080000
+#define LPC32XX_UART4_BASE			0x40088000
+#define LPC32XX_UART5_BASE			0x40090000
+#define LPC32XX_UART6_BASE			0x40098000
+#define LPC32XX_I2C1_BASE			0x400A0000
+#define LPC32XX_I2C2_BASE			0x400A8000
+
+/*
+ * FAB and APB base and sizing
+ */
+#define LPC32XX_FABAPB_START			LPC32XX_CLK_PM_BASE
+#define LPC32XX_FABAPB_SIZE			0x000A5000
+
+/*
+ * Internal memory bases and sizes
+ */
+#define LPC32XX_IRAM_BASE			0x08000000
+#define LPC32XX_IROM_BASE			0x0C000000
+
+/*
+ * External Static Memory Bank Address Space Bases
+ */
+#define LPC32XX_EMC_CS0_BASE			0xE0000000
+#define LPC32XX_EMC_CS1_BASE			0xE1000000
+#define LPC32XX_EMC_CS2_BASE			0xE2000000
+#define LPC32XX_EMC_CS3_BASE			0xE3000000
+
+/*
+ * External SDRAM Memory Bank Address Space Bases
+ */
+#define LPC32XX_EMC_DYCS0_BASE			0x80000000
+#define LPC32XX_EMC_DYCS1_BASE			0xA0000000
+
+/*
+ * Clock and crystal information
+ */
+#define LPC32XX_MAIN_OSC_FREQ			13000000
+#define LPC32XX_CLOCK_OSC_FREQ			32768
+
+/*
+ * Clock and Power control register offsets
+ */
+#define _PMREG(x)				io_p2v(LPC32XX_CLK_PM_BASE +\
+						(x))
+#define LPC32XX_CLKPWR_DEBUG_CTRL		_PMREG(0x000)
+#define LPC32XX_CLKPWR_BOOTMAP			_PMREG(0x014)
+#define LPC32XX_CLKPWR_P01_ER			_PMREG(0x018)
+#define LPC32XX_CLKPWR_USBCLK_PDIV		_PMREG(0x01C)
+#define LPC32XX_CLKPWR_INT_ER			_PMREG(0x020)
+#define LPC32XX_CLKPWR_INT_RS			_PMREG(0x024)
+#define LPC32XX_CLKPWR_INT_SR			_PMREG(0x028)
+#define LPC32XX_CLKPWR_INT_AP			_PMREG(0x02C)
+#define LPC32XX_CLKPWR_PIN_ER			_PMREG(0x030)
+#define LPC32XX_CLKPWR_PIN_RS			_PMREG(0x034)
+#define LPC32XX_CLKPWR_PIN_SR			_PMREG(0x038)
+#define LPC32XX_CLKPWR_PIN_AP			_PMREG(0x03C)
+#define LPC32XX_CLKPWR_HCLK_DIV			_PMREG(0x040)
+#define LPC32XX_CLKPWR_PWR_CTRL			_PMREG(0x044)
+#define LPC32XX_CLKPWR_PLL397_CTRL		_PMREG(0x048)
+#define LPC32XX_CLKPWR_MAIN_OSC_CTRL		_PMREG(0x04C)
+#define LPC32XX_CLKPWR_SYSCLK_CTRL		_PMREG(0x050)
+#define LPC32XX_CLKPWR_LCDCLK_CTRL		_PMREG(0x054)
+#define LPC32XX_CLKPWR_HCLKPLL_CTRL		_PMREG(0x058)
+#define LPC32XX_CLKPWR_ADC_CLK_CTRL_1		_PMREG(0x060)
+#define LPC32XX_CLKPWR_USB_CTRL			_PMREG(0x064)
+#define LPC32XX_CLKPWR_SDRAMCLK_CTRL		_PMREG(0x068)
+#define LPC32XX_CLKPWR_DDR_LAP_NOM		_PMREG(0x06C)
+#define LPC32XX_CLKPWR_DDR_LAP_COUNT		_PMREG(0x070)
+#define LPC32XX_CLKPWR_DDR_LAP_DELAY		_PMREG(0x074)
+#define LPC32XX_CLKPWR_SSP_CLK_CTRL		_PMREG(0x078)
+#define LPC32XX_CLKPWR_I2S_CLK_CTRL		_PMREG(0x07C)
+#define LPC32XX_CLKPWR_MS_CTRL			_PMREG(0x080)
+#define LPC32XX_CLKPWR_MACCLK_CTRL		_PMREG(0x090)
+#define LPC32XX_CLKPWR_TEST_CLK_SEL		_PMREG(0x0A4)
+#define LPC32XX_CLKPWR_SFW_INT			_PMREG(0x0A8)
+#define LPC32XX_CLKPWR_I2C_CLK_CTRL		_PMREG(0x0AC)
+#define LPC32XX_CLKPWR_KEY_CLK_CTRL		_PMREG(0x0B0)
+#define LPC32XX_CLKPWR_ADC_CLK_CTRL		_PMREG(0x0B4)
+#define LPC32XX_CLKPWR_PWM_CLK_CTRL		_PMREG(0x0B8)
+#define LPC32XX_CLKPWR_TIMER_CLK_CTRL		_PMREG(0x0BC)
+#define LPC32XX_CLKPWR_TIMERS_PWMS_CLK_CTRL_1	_PMREG(0x0C0)
+#define LPC32XX_CLKPWR_SPI_CLK_CTRL		_PMREG(0x0C4)
+#define LPC32XX_CLKPWR_NAND_CLK_CTRL		_PMREG(0x0C8)
+#define LPC32XX_CLKPWR_UART3_CLK_CTRL		_PMREG(0x0D0)
+#define LPC32XX_CLKPWR_UART4_CLK_CTRL		_PMREG(0x0D4)
+#define LPC32XX_CLKPWR_UART5_CLK_CTRL		_PMREG(0x0D8)
+#define LPC32XX_CLKPWR_UART6_CLK_CTRL		_PMREG(0x0DC)
+#define LPC32XX_CLKPWR_IRDA_CLK_CTRL		_PMREG(0x0E0)
+#define LPC32XX_CLKPWR_UART_CLK_CTRL		_PMREG(0x0E4)
+#define LPC32XX_CLKPWR_DMA_CLK_CTRL		_PMREG(0x0E8)
+#define LPC32XX_CLKPWR_AUTOCLOCK		_PMREG(0x0EC)
+#define LPC32XX_CLKPWR_DEVID(x)			_PMREG(0x130 + (x))
+
+/*
+ * clkpwr_debug_ctrl register definitions
+*/
+#define LPC32XX_CLKPWR_VFP_CLOCK_ENABLE_BIT	_BIT(4)
+
+/*
+ * clkpwr_bootmap register definitions
+ */
+#define LPC32XX_CLKPWR_BOOTMAP_SEL_BIT		_BIT(1)
+
+/*
+ * clkpwr_start_gpio register bit definitions
+ */
+#define LPC32XX_CLKPWR_GPIOSRC_P1IO23_BIT	_BIT(31)
+#define LPC32XX_CLKPWR_GPIOSRC_P1IO22_BIT	_BIT(30)
+#define LPC32XX_CLKPWR_GPIOSRC_P1IO21_BIT	_BIT(29)
+#define LPC32XX_CLKPWR_GPIOSRC_P1IO20_BIT	_BIT(28)
+#define LPC32XX_CLKPWR_GPIOSRC_P1IO19_BIT	_BIT(27)
+#define LPC32XX_CLKPWR_GPIOSRC_P1IO18_BIT	_BIT(26)
+#define LPC32XX_CLKPWR_GPIOSRC_P1IO17_BIT	_BIT(25)
+#define LPC32XX_CLKPWR_GPIOSRC_P1IO16_BIT	_BIT(24)
+#define LPC32XX_CLKPWR_GPIOSRC_P1IO15_BIT	_BIT(23)
+#define LPC32XX_CLKPWR_GPIOSRC_P1IO14_BIT	_BIT(22)
+#define LPC32XX_CLKPWR_GPIOSRC_P1IO13_BIT	_BIT(21)
+#define LPC32XX_CLKPWR_GPIOSRC_P1IO12_BIT	_BIT(20)
+#define LPC32XX_CLKPWR_GPIOSRC_P1IO11_BIT	_BIT(19)
+#define LPC32XX_CLKPWR_GPIOSRC_P1IO10_BIT	_BIT(18)
+#define LPC32XX_CLKPWR_GPIOSRC_P1IO9_BIT	_BIT(17)
+#define LPC32XX_CLKPWR_GPIOSRC_P1IO8_BIT	_BIT(16)
+#define LPC32XX_CLKPWR_GPIOSRC_P1IO7_BIT	_BIT(15)
+#define LPC32XX_CLKPWR_GPIOSRC_P1IO6_BIT	_BIT(14)
+#define LPC32XX_CLKPWR_GPIOSRC_P1IO5_BIT	_BIT(13)
+#define LPC32XX_CLKPWR_GPIOSRC_P1IO4_BIT	_BIT(12)
+#define LPC32XX_CLKPWR_GPIOSRC_P1IO3_BIT	_BIT(11)
+#define LPC32XX_CLKPWR_GPIOSRC_P1IO2_BIT	_BIT(10)
+#define LPC32XX_CLKPWR_GPIOSRC_P1IO1_BIT	_BIT(9)
+#define LPC32XX_CLKPWR_GPIOSRC_P1IO0_BIT	_BIT(8)
+#define LPC32XX_CLKPWR_GPIOSRC_P0IO7_BIT	_BIT(7)
+#define LPC32XX_CLKPWR_GPIOSRC_P0IO6_BIT	_BIT(6)
+#define LPC32XX_CLKPWR_GPIOSRC_P0IO5_BIT	_BIT(5)
+#define LPC32XX_CLKPWR_GPIOSRC_P0IO4_BIT	_BIT(4)
+#define LPC32XX_CLKPWR_GPIOSRC_P0IO3_BIT	_BIT(3)
+#define LPC32XX_CLKPWR_GPIOSRC_P0IO2_BIT	_BIT(2)
+#define LPC32XX_CLKPWR_GPIOSRC_P0IO1_BIT	_BIT(1)
+#define LPC32XX_CLKPWR_GPIOSRC_P0IO0_BIT	_BIT(0)
+
+/*
+ * clkpwr_usbclk_pdiv register definitions
+ */
+#define LPC32XX_CLKPWR_USBPDIV_PLL_MASK		0xF
+
+/*
+ * clkpwr_start_int, clkpwr_start_raw_sts_int, clkpwr_start_sts_int,
+ * clkpwr_start_pol_int, register bit definitions
+ */
+#define LPC32XX_CLKPWR_INTSRC_ADC_BIT		_BIT(31)
+#define LPC32XX_CLKPWR_INTSRC_TS_P_BIT		_BIT(30)
+#define LPC32XX_CLKPWR_INTSRC_TS_AUX_BIT	_BIT(29)
+#define LPC32XX_CLKPWR_INTSRC_USBAHNEEDCLK_BIT	_BIT(26)
+#define LPC32XX_CLKPWR_INTSRC_MSTIMER_BIT	_BIT(25)
+#define LPC32XX_CLKPWR_INTSRC_RTC_BIT		_BIT(24)
+#define LPC32XX_CLKPWR_INTSRC_USBNEEDCLK_BIT	_BIT(23)
+#define LPC32XX_CLKPWR_INTSRC_USB_BIT		_BIT(22)
+#define LPC32XX_CLKPWR_INTSRC_I2C_BIT		_BIT(21)
+#define LPC32XX_CLKPWR_INTSRC_USBOTGTIMER_BIT	_BIT(20)
+#define LPC32XX_CLKPWR_INTSRC_USBATXINT_BIT	_BIT(19)
+#define LPC32XX_CLKPWR_INTSRC_KEY_BIT		_BIT(16)
+#define LPC32XX_CLKPWR_INTSRC_MAC_BIT		_BIT(7)
+#define LPC32XX_CLKPWR_INTSRC_P0P1_BIT		_BIT(6)
+#define LPC32XX_CLKPWR_INTSRC_GPIO_05_BIT	_BIT(5)
+#define LPC32XX_CLKPWR_INTSRC_GPIO_04_BIT	_BIT(4)
+#define LPC32XX_CLKPWR_INTSRC_GPIO_03_BIT	_BIT(3)
+#define LPC32XX_CLKPWR_INTSRC_GPIO_02_BIT	_BIT(2)
+#define LPC32XX_CLKPWR_INTSRC_GPIO_01_BIT	_BIT(1)
+#define LPC32XX_CLKPWR_INTSRC_GPIO_00_BIT	_BIT(0)
+
+/*
+ * clkpwr_start_pin, clkpwr_start_raw_sts_pin, clkpwr_start_sts_pin,
+ * clkpwr_start_pol_pin register bit definitions
+ */
+#define LPC32XX_CLKPWR_EXTSRC_U7_RX_BIT		_BIT(31)
+#define LPC32XX_CLKPWR_EXTSRC_U7_HCTS_BIT	_BIT(30)
+#define LPC32XX_CLKPWR_EXTSRC_U6_IRRX_BIT	_BIT(28)
+#define LPC32XX_CLKPWR_EXTSRC_U5_RX_BIT		_BIT(26)
+#define LPC32XX_CLKPWR_EXTSRC_GPI_28_BIT	_BIT(25)
+#define LPC32XX_CLKPWR_EXTSRC_U3_RX_BIT		_BIT(24)
+#define LPC32XX_CLKPWR_EXTSRC_U2_HCTS_BIT	_BIT(23)
+#define LPC32XX_CLKPWR_EXTSRC_U2_RX_BIT		_BIT(22)
+#define LPC32XX_CLKPWR_EXTSRC_U1_RX_BIT		_BIT(21)
+#define LPC32XX_CLKPWR_EXTSRC_MSDIO_INT_BIT	_BIT(18)
+#define LPC32XX_CLKPWR_EXTSRC_MSDIO_SRT_BIT	_BIT(17)
+#define LPC32XX_CLKPWR_EXTSRC_GPI_06_BIT	_BIT(16)
+#define LPC32XX_CLKPWR_EXTSRC_GPI_05_BIT	_BIT(15)
+#define LPC32XX_CLKPWR_EXTSRC_GPI_04_BIT	_BIT(14)
+#define LPC32XX_CLKPWR_EXTSRC_GPI_03_BIT	_BIT(13)
+#define LPC32XX_CLKPWR_EXTSRC_GPI_02_BIT	_BIT(12)
+#define LPC32XX_CLKPWR_EXTSRC_GPI_01_BIT	_BIT(11)
+#define LPC32XX_CLKPWR_EXTSRC_GPI_00_BIT	_BIT(10)
+#define LPC32XX_CLKPWR_EXTSRC_SYSCLKEN_BIT	_BIT(9)
+#define LPC32XX_CLKPWR_EXTSRC_SPI1_DATIN_BIT	_BIT(8)
+#define LPC32XX_CLKPWR_EXTSRC_GPI_07_BIT	_BIT(7)
+#define LPC32XX_CLKPWR_EXTSRC_SPI2_DATIN_BIT	_BIT(6)
+#define LPC32XX_CLKPWR_EXTSRC_GPI_19_BIT	_BIT(5)
+#define LPC32XX_CLKPWR_EXTSRC_GPI_09_BIT	_BIT(4)
+#define LPC32XX_CLKPWR_EXTSRC_GPI_08_BIT	_BIT(3)
+
+/*
+ * clkpwr_hclk_div register definitions
+ */
+#define LPC32XX_CLKPWR_HCLKDIV_DDRCLK_STOP	(0x0 << 7)
+#define LPC32XX_CLKPWR_HCLKDIV_DDRCLK_NORM	(0x1 << 7)
+#define LPC32XX_CLKPWR_HCLKDIV_DDRCLK_HALF	(0x2 << 7)
+#define LPC32XX_CLKPWR_HCLKDIV_PCLK_DIV(n)	(((n) & 0x1F) << 2)
+#define LPC32XX_CLKPWR_HCLKDIV_DIV_2POW(n)	((n) & 0x3)
+
+/*
+ * clkpwr_pwr_ctrl register definitions
+ */
+#define LPC32XX_CLKPWR_CTRL_FORCE_PCLK		_BIT(10)
+#define LPC32XX_CLKPWR_SDRAM_SELF_RFSH		_BIT(9)
+#define LPC32XX_CLKPWR_UPD_SDRAM_SELF_RFSH	_BIT(8)
+#define LPC32XX_CLKPWR_AUTO_SDRAM_SELF_RFSH	_BIT(7)
+#define LPC32XX_CLKPWR_HIGHCORE_STATE_BIT	_BIT(5)
+#define LPC32XX_CLKPWR_SYSCLKEN_STATE_BIT	_BIT(4)
+#define LPC32XX_CLKPWR_SYSCLKEN_GPIO_EN		_BIT(3)
+#define LPC32XX_CLKPWR_SELECT_RUN_MODE		_BIT(2)
+#define LPC32XX_CLKPWR_HIGHCORE_GPIO_EN		_BIT(1)
+#define LPC32XX_CLKPWR_STOP_MODE_CTRL		_BIT(0)
+
+/*
+ * clkpwr_pll397_ctrl register definitions
+ */
+#define LPC32XX_CLKPWR_PLL397_MSLOCK_STS	_BIT(10)
+#define LPC32XX_CLKPWR_PLL397_BYPASS		_BIT(9)
+#define LPC32XX_CLKPWR_PLL397_BIAS_NORM		0x000
+#define LPC32XX_CLKPWR_PLL397_BIAS_N12_5	0x040
+#define LPC32XX_CLKPWR_PLL397_BIAS_N25		0x080
+#define LPC32XX_CLKPWR_PLL397_BIAS_N37_5	0x0C0
+#define LPC32XX_CLKPWR_PLL397_BIAS_P12_5	0x100
+#define LPC32XX_CLKPWR_PLL397_BIAS_P25		0x140
+#define LPC32XX_CLKPWR_PLL397_BIAS_P37_5	0x180
+#define LPC32XX_CLKPWR_PLL397_BIAS_P50		0x1C0
+#define LPC32XX_CLKPWR_PLL397_BIAS_MASK		0x1C0
+#define LPC32XX_CLKPWR_SYSCTRL_PLL397_DIS	_BIT(1)
+#define LPC32XX_CLKPWR_SYSCTRL_PLL397_STS	_BIT(0)
+
+/*
+ * clkpwr_main_osc_ctrl register definitions
+ */
+#define LPC32XX_CLKPWR_MOSC_ADD_CAP(n)		(((n) & 0x7F) << 2)
+#define LPC32XX_CLKPWR_MOSC_CAP_MASK		(0x7F << 2)
+#define LPC32XX_CLKPWR_TEST_MODE		_BIT(1)
+#define LPC32XX_CLKPWR_MOSC_DISABLE		_BIT(0)
+
+/*
+ * clkpwr_sysclk_ctrl register definitions
+ */
+#define LPC32XX_CLKPWR_SYSCTRL_BP_TRIG(n)	(((n) & 0x3FF) << 2)
+#define LPC32XX_CLKPWR_SYSCTRL_BP_MASK		(0x3FF << 2)
+#define LPC32XX_CLKPWR_SYSCTRL_USEPLL397	_BIT(1)
+#define LPC32XX_CLKPWR_SYSCTRL_SYSCLKMUX	_BIT(0)
+
+/*
+ * clkpwr_lcdclk_ctrl register definitions
+ */
+#define LPC32XX_CLKPWR_LCDCTRL_LCDTYPE_TFT12	0x000
+#define LPC32XX_CLKPWR_LCDCTRL_LCDTYPE_TFT16	0x040
+#define LPC32XX_CLKPWR_LCDCTRL_LCDTYPE_TFT15	0x080
+#define LPC32XX_CLKPWR_LCDCTRL_LCDTYPE_TFT24	0x0C0
+#define LPC32XX_CLKPWR_LCDCTRL_LCDTYPE_STN4M	0x100
+#define LPC32XX_CLKPWR_LCDCTRL_LCDTYPE_STN8C	0x140
+#define LPC32XX_CLKPWR_LCDCTRL_LCDTYPE_DSTN4M	0x180
+#define LPC32XX_CLKPWR_LCDCTRL_LCDTYPE_DSTN8C	0x1C0
+#define LPC32XX_CLKPWR_LCDCTRL_LCDTYPE_MSK	0x01C0
+#define LPC32XX_CLKPWR_LCDCTRL_CLK_EN		0x020
+#define LPC32XX_CLKPWR_LCDCTRL_SET_PSCALE(n)	((n - 1) & 0x1F)
+#define LPC32XX_CLKPWR_LCDCTRL_PSCALE_MSK	0x001F
+
+/*
+ * clkpwr_hclkpll_ctrl register definitions
+ */
+#define LPC32XX_CLKPWR_HCLKPLL_POWER_UP		_BIT(16)
+#define LPC32XX_CLKPWR_HCLKPLL_CCO_BYPASS	_BIT(15)
+#define LPC32XX_CLKPWR_HCLKPLL_POSTDIV_BYPASS	_BIT(14)
+#define LPC32XX_CLKPWR_HCLKPLL_FDBK_SEL_FCLK	_BIT(13)
+#define LPC32XX_CLKPWR_HCLKPLL_POSTDIV_2POW(n)	(((n) & 0x3) << 11)
+#define LPC32XX_CLKPWR_HCLKPLL_PREDIV_PLUS1(n)	(((n) & 0x3) << 9)
+#define LPC32XX_CLKPWR_HCLKPLL_PLLM(n)		(((n) & 0xFF) << 1)
+#define LPC32XX_CLKPWR_HCLKPLL_PLL_STS		_BIT(0)
+
+/*
+ * clkpwr_adc_clk_ctrl_1 register definitions
+ */
+#define LPC32XX_CLKPWR_ADCCTRL1_RTDIV(n)	(((n) & 0xFF) << 0)
+#define LPC32XX_CLKPWR_ADCCTRL1_PCLK_SEL	_BIT(8)
+
+/*
+ * clkpwr_usb_ctrl register definitions
+ */
+#define LPC32XX_CLKPWR_USBCTRL_HCLK_EN		_BIT(24)
+#define LPC32XX_CLKPWR_USBCTRL_USBI2C_EN	_BIT(23)
+#define LPC32XX_CLKPWR_USBCTRL_USBDVND_EN	_BIT(22)
+#define LPC32XX_CLKPWR_USBCTRL_USBHSTND_EN	_BIT(21)
+#define LPC32XX_CLKPWR_USBCTRL_PU_ADD		(0x0 << 19)
+#define LPC32XX_CLKPWR_USBCTRL_BUS_KEEPER	(0x1 << 19)
+#define LPC32XX_CLKPWR_USBCTRL_PD_ADD		(0x3 << 19)
+#define LPC32XX_CLKPWR_USBCTRL_CLK_EN2		_BIT(18)
+#define LPC32XX_CLKPWR_USBCTRL_CLK_EN1		_BIT(17)
+#define LPC32XX_CLKPWR_USBCTRL_PLL_PWRUP	_BIT(16)
+#define LPC32XX_CLKPWR_USBCTRL_CCO_BYPASS	_BIT(15)
+#define LPC32XX_CLKPWR_USBCTRL_POSTDIV_BYPASS	_BIT(14)
+#define LPC32XX_CLKPWR_USBCTRL_FDBK_SEL_FCLK	_BIT(13)
+#define LPC32XX_CLKPWR_USBCTRL_POSTDIV_2POW(n)	(((n) & 0x3) << 11)
+#define LPC32XX_CLKPWR_USBCTRL_PREDIV_PLUS1(n)	(((n) & 0x3) << 9)
+#define LPC32XX_CLKPWR_USBCTRL_FDBK_PLUS1(n)	(((n) & 0xFF) << 1)
+#define LPC32XX_CLKPWR_USBCTRL_PLL_STS		_BIT(0)
+
+/*
+ * clkpwr_sdramclk_ctrl register definitions
+ */
+#define LPC32XX_CLKPWR_SDRCLK_FASTSLEW_CLK	_BIT(22)
+#define LPC32XX_CLKPWR_SDRCLK_FASTSLEW		_BIT(21)
+#define LPC32XX_CLKPWR_SDRCLK_FASTSLEW_DAT	_BIT(20)
+#define LPC32XX_CLKPWR_SDRCLK_SW_DDR_RESET	_BIT(19)
+#define LPC32XX_CLKPWR_SDRCLK_HCLK_DLY(n)	(((n) & 0x1F) << 14)
+#define LPC32XX_CLKPWR_SDRCLK_DLY_ADDR_STS	_BIT(13)
+#define LPC32XX_CLKPWR_SDRCLK_SENS_FACT(n)	(((n) & 0x7) << 10)
+#define LPC32XX_CLKPWR_SDRCLK_USE_CAL		_BIT(9)
+#define LPC32XX_CLKPWR_SDRCLK_DO_CAL		_BIT(8)
+#define LPC32XX_CLKPWR_SDRCLK_CAL_ON_RTC	_BIT(7)
+#define LPC32XX_CLKPWR_SDRCLK_DQS_DLY(n)	(((n) & 0x1F) << 2)
+#define LPC32XX_CLKPWR_SDRCLK_USE_DDR		_BIT(1)
+#define LPC32XX_CLKPWR_SDRCLK_CLK_DIS		_BIT(0)
+
+/*
+ * clkpwr_ssp_blk_ctrl register definitions
+ */
+#define LPC32XX_CLKPWR_SSPCTRL_DMA_SSP1RX	_BIT(5)
+#define LPC32XX_CLKPWR_SSPCTRL_DMA_SSP1TX	_BIT(4)
+#define LPC32XX_CLKPWR_SSPCTRL_DMA_SSP0RX	_BIT(3)
+#define LPC32XX_CLKPWR_SSPCTRL_DMA_SSP0TX	_BIT(2)
+#define LPC32XX_CLKPWR_SSPCTRL_SSPCLK1_EN	_BIT(1)
+#define LPC32XX_CLKPWR_SSPCTRL_SSPCLK0_EN	_BIT(0)
+
+/*
+ * clkpwr_i2s_clk_ctrl register definitions
+ */
+#define LPC32XX_CLKPWR_I2SCTRL_I2S1_RX_FOR_TX	_BIT(6)
+#define LPC32XX_CLKPWR_I2SCTRL_I2S1_TX_FOR_RX	_BIT(5)
+#define LPC32XX_CLKPWR_I2SCTRL_I2S1_USE_DMA	_BIT(4)
+#define LPC32XX_CLKPWR_I2SCTRL_I2S0_RX_FOR_TX	_BIT(3)
+#define LPC32XX_CLKPWR_I2SCTRL_I2S0_TX_FOR_RX	_BIT(2)
+#define LPC32XX_CLKPWR_I2SCTRL_I2SCLK1_EN	_BIT(1)
+#define LPC32XX_CLKPWR_I2SCTRL_I2SCLK0_EN	_BIT(0)
+
+/*
+ * clkpwr_ms_ctrl register definitions
+ */
+#define LPC32XX_CLKPWR_MSCARD_MSDIO_PIN_DIS	_BIT(10)
+#define LPC32XX_CLKPWR_MSCARD_MSDIO_PU_EN	_BIT(9)
+#define LPC32XX_CLKPWR_MSCARD_MSDIO23_DIS	_BIT(8)
+#define LPC32XX_CLKPWR_MSCARD_MSDIO1_DIS	_BIT(7)
+#define LPC32XX_CLKPWR_MSCARD_MSDIO0_DIS	_BIT(6)
+#define LPC32XX_CLKPWR_MSCARD_SDCARD_EN		_BIT(5)
+#define LPC32XX_CLKPWR_MSCARD_SDCARD_DIV(n)	((n) & 0xF)
+
+/*
+ * clkpwr_macclk_ctrl register definitions
+ */
+#define LPC32XX_CLKPWR_MACCTRL_NO_ENET_PIS	0x00
+#define LPC32XX_CLKPWR_MACCTRL_USE_MII_PINS	0x08
+#define LPC32XX_CLKPWR_MACCTRL_USE_RMII_PINS	0x18
+#define LPC32XX_CLKPWR_MACCTRL_PINS_MSK		0x18
+#define LPC32XX_CLKPWR_MACCTRL_DMACLK_EN	_BIT(2)
+#define LPC32XX_CLKPWR_MACCTRL_MMIOCLK_EN	_BIT(1)
+#define LPC32XX_CLKPWR_MACCTRL_HRCCLK_EN	_BIT(0)
+
+/*
+ * clkpwr_test_clk_sel register definitions
+ */
+#define LPC32XX_CLKPWR_TESTCLK1_SEL_PERCLK	(0x0 << 5)
+#define LPC32XX_CLKPWR_TESTCLK1_SEL_RTC		(0x1 << 5)
+#define LPC32XX_CLKPWR_TESTCLK1_SEL_MOSC	(0x2 << 5)
+#define LPC32XX_CLKPWR_TESTCLK1_SEL_MASK	(0x3 << 5)
+#define LPC32XX_CLKPWR_TESTCLK_TESTCLK1_EN	_BIT(4)
+#define LPC32XX_CLKPWR_TESTCLK2_SEL_HCLK	(0x0 << 1)
+#define LPC32XX_CLKPWR_TESTCLK2_SEL_PERCLK	(0x1 << 1)
+#define LPC32XX_CLKPWR_TESTCLK2_SEL_USBCLK	(0x2 << 1)
+#define LPC32XX_CLKPWR_TESTCLK2_SEL_MOSC	(0x5 << 1)
+#define LPC32XX_CLKPWR_TESTCLK2_SEL_PLL397	(0x7 << 1)
+#define LPC32XX_CLKPWR_TESTCLK2_SEL_MASK	(0x7 << 1)
+#define LPC32XX_CLKPWR_TESTCLK_TESTCLK2_EN	_BIT(0)
+
+/*
+ * clkpwr_sw_int register definitions
+ */
+#define LPC32XX_CLKPWR_SW_INT(n)		(_BIT(0) | (((n) & 0x7F) << 1))
+#define LPC32XX_CLKPWR_SW_GET_ARG(n)		(((n) & 0xFE) >> 1)
+
+/*
+ * clkpwr_i2c_clk_ctrl register definitions
+ */
+#define LPC32XX_CLKPWR_I2CCLK_USBI2CHI_DRIVE	_BIT(4)
+#define LPC32XX_CLKPWR_I2CCLK_I2C2HI_DRIVE	_BIT(3)
+#define LPC32XX_CLKPWR_I2CCLK_I2C1HI_DRIVE	_BIT(2)
+#define LPC32XX_CLKPWR_I2CCLK_I2C2CLK_EN	_BIT(1)
+#define LPC32XX_CLKPWR_I2CCLK_I2C1CLK_EN	_BIT(0)
+
+/*
+ * clkpwr_key_clk_ctrl register definitions
+ */
+#define LPC32XX_CLKPWR_KEYCLKCTRL_CLK_EN	0x1
+
+/*
+ * clkpwr_adc_clk_ctrl register definitions
+ */
+#define LPC32XX_CLKPWR_ADC32CLKCTRL_CLK_EN	0x1
+
+/*
+ * clkpwr_pwm_clk_ctrl register definitions
+ */
+#define LPC32XX_CLKPWR_PWMCLK_PWM2_DIV(n)	(((n) & 0xF) << 8)
+#define LPC32XX_CLKPWR_PWMCLK_PWM1_DIV(n)	(((n) & 0xF) << 4)
+#define LPC32XX_CLKPWR_PWMCLK_PWM2SEL_PCLK	0x8
+#define LPC32XX_CLKPWR_PWMCLK_PWM2CLK_EN	0x4
+#define LPC32XX_CLKPWR_PWMCLK_PWM1SEL_PCLK	0x2
+#define LPC32XX_CLKPWR_PWMCLK_PWM1CLK_EN	0x1
+
+/*
+ * clkpwr_timer_clk_ctrl register definitions
+ */
+#define LPC32XX_CLKPWR_PWMCLK_HSTIMER_EN	0x2
+#define LPC32XX_CLKPWR_PWMCLK_WDOG_EN		0x1
+
+/*
+ * clkpwr_timers_pwms_clk_ctrl_1 register definitions
+ */
+#define LPC32XX_CLKPWR_TMRPWMCLK_TIMER3_EN	0x20
+#define LPC32XX_CLKPWR_TMRPWMCLK_TIMER2_EN	0x10
+#define LPC32XX_CLKPWR_TMRPWMCLK_TIMER1_EN	0x08
+#define LPC32XX_CLKPWR_TMRPWMCLK_TIMER0_EN	0x04
+#define LPC32XX_CLKPWR_TMRPWMCLK_PWM4_EN	0x02
+#define LPC32XX_CLKPWR_TMRPWMCLK_PWM3_EN	0x01
+
+/*
+ * clkpwr_spi_clk_ctrl register definitions
+ */
+#define LPC32XX_CLKPWR_SPICLK_SET_SPI2DATIO	0x80
+#define LPC32XX_CLKPWR_SPICLK_SET_SPI2CLK	0x40
+#define LPC32XX_CLKPWR_SPICLK_USE_SPI2		0x20
+#define LPC32XX_CLKPWR_SPICLK_SPI2CLK_EN	0x10
+#define LPC32XX_CLKPWR_SPICLK_SET_SPI1DATIO	0x08
+#define LPC32XX_CLKPWR_SPICLK_SET_SPI1CLK	0x04
+#define LPC32XX_CLKPWR_SPICLK_USE_SPI1		0x02
+#define LPC32XX_CLKPWR_SPICLK_SPI1CLK_EN	0x01
+
+/*
+ * clkpwr_nand_clk_ctrl register definitions
+ */
+#define LPC32XX_CLKPWR_NANDCLK_INTSEL_MLC	0x20
+#define LPC32XX_CLKPWR_NANDCLK_DMA_RNB		0x10
+#define LPC32XX_CLKPWR_NANDCLK_DMA_INT		0x08
+#define LPC32XX_CLKPWR_NANDCLK_SEL_SLC		0x04
+#define LPC32XX_CLKPWR_NANDCLK_MLCCLK_EN	0x02
+#define LPC32XX_CLKPWR_NANDCLK_SLCCLK_EN	0x01
+
+/*
+ * clkpwr_uart3_clk_ctrl, clkpwr_uart4_clk_ctrl, clkpwr_uart5_clk_ctrl
+ * and clkpwr_uart6_clk_ctrl register definitions
+ */
+#define LPC32XX_CLKPWR_UART_Y_DIV(y)		((y) & 0xFF)
+#define LPC32XX_CLKPWR_UART_X_DIV(x)		(((x) & 0xFF) << 8)
+#define LPC32XX_CLKPWR_UART_USE_HCLK		_BIT(16)
+
+/*
+ * clkpwr_irda_clk_ctrl register definitions
+ */
+#define LPC32XX_CLKPWR_IRDA_Y_DIV(y)		((y) & 0xFF)
+#define LPC32XX_CLKPWR_IRDA_X_DIV(x)		(((x) & 0xFF) << 8)
+
+/*
+ * clkpwr_uart_clk_ctrl register definitions
+ */
+#define LPC32XX_CLKPWR_UARTCLKCTRL_UART6_EN	_BIT(3)
+#define LPC32XX_CLKPWR_UARTCLKCTRL_UART5_EN	_BIT(2)
+#define LPC32XX_CLKPWR_UARTCLKCTRL_UART4_EN	_BIT(1)
+#define LPC32XX_CLKPWR_UARTCLKCTRL_UART3_EN	_BIT(0)
+
+/*
+ * clkpwr_dmaclk_ctrl register definitions
+ */
+#define LPC32XX_CLKPWR_DMACLKCTRL_CLK_EN	0x1
+
+/*
+ * clkpwr_autoclock register definitions
+ */
+#define LPC32XX_CLKPWR_AUTOCLK_USB_EN		0x40
+#define LPC32XX_CLKPWR_AUTOCLK_IRAM_EN		0x02
+#define LPC32XX_CLKPWR_AUTOCLK_IROM_EN		0x01
+
+/*
+ * Interrupt controller register offsets
+ */
+#define LPC32XX_INTC_MASK(x)			io_p2v((x) + 0x00)
+#define LPC32XX_INTC_RAW_STAT(x)		io_p2v((x) + 0x04)
+#define LPC32XX_INTC_STAT(x)			io_p2v((x) + 0x08)
+#define LPC32XX_INTC_POLAR(x)			io_p2v((x) + 0x0C)
+#define LPC32XX_INTC_ACT_TYPE(x)		io_p2v((x) + 0x10)
+#define LPC32XX_INTC_TYPE(x)			io_p2v((x) + 0x14)
+
+/*
+ * Timer/counter register offsets
+ */
+#define LCP32XX_TIMER_IR(x)			io_p2v((x) + 0x00)
+#define LCP32XX_TIMER_TCR(x)			io_p2v((x) + 0x04)
+#define LCP32XX_TIMER_TC(x)			io_p2v((x) + 0x08)
+#define LCP32XX_TIMER_PR(x)			io_p2v((x) + 0x0C)
+#define LCP32XX_TIMER_PC(x)			io_p2v((x) + 0x10)
+#define LCP32XX_TIMER_MCR(x)			io_p2v((x) + 0x14)
+#define LCP32XX_TIMER_MR0(x)			io_p2v((x) + 0x18)
+#define LCP32XX_TIMER_MR1(x)			io_p2v((x) + 0x1C)
+#define LCP32XX_TIMER_MR2(x)			io_p2v((x) + 0x20)
+#define LCP32XX_TIMER_MR3(x)			io_p2v((x) + 0x24)
+#define LCP32XX_TIMER_CCR(x)			io_p2v((x) + 0x28)
+#define LCP32XX_TIMER_CR0(x)			io_p2v((x) + 0x2C)
+#define LCP32XX_TIMER_CR1(x)			io_p2v((x) + 0x30)
+#define LCP32XX_TIMER_CR2(x)			io_p2v((x) + 0x34)
+#define LCP32XX_TIMER_CR3(x)			io_p2v((x) + 0x38)
+#define LCP32XX_TIMER_EMR(x)			io_p2v((x) + 0x3C)
+#define LCP32XX_TIMER_CTCR(x)			io_p2v((x) + 0x70)
+
+/*
+ * ir register definitions
+ */
+#define LCP32XX_TIMER_CNTR_MTCH_BIT(n)		(1 << ((n) & 0x3))
+#define LCP32XX_TIMER_CNTR_CAPT_BIT(n)		(1 << (4 + ((n) & 0x3)))
+
+/*
+ * tcr register definitions
+ */
+#define LCP32XX_TIMER_CNTR_TCR_EN		0x1
+#define LCP32XX_TIMER_CNTR_TCR_RESET		0x2
+
+/*
+ * mcr register definitions
+ */
+#define LCP32XX_TIMER_CNTR_MCR_MTCH(n)		(0x1 << ((n) * 3))
+#define LCP32XX_TIMER_CNTR_MCR_RESET(n)		(0x1 << (((n) * 3) + 1))
+#define LCP32XX_TIMER_CNTR_MCR_STOP(n)		(0x1 << (((n) * 3) + 2))
+
+/*
+ * Standard UART register offsets
+ */
+#define LPC32XX_UART_DLL_FIFO(x)		io_p2v((x) + 0x00)
+#define LPC32XX_UART_DLM_IER(x)			io_p2v((x) + 0x04)
+#define LPC32XX_UART_IIR_FCR(x)			io_p2v((x) + 0x08)
+#define LPC32XX_UART_LCR(x)			io_p2v((x) + 0x0C)
+#define LPC32XX_UART_MODEM_CTRL(x)		io_p2v((x) + 0x10)
+#define LPC32XX_UART_LSR(x)			io_p2v((x) + 0x14)
+#define LPC32XX_UART_MODEM_STATUS(x)		io_p2v((x) + 0x18)
+#define LPC32XX_UART_RXLEV(x)			io_p2v((x) + 0x1C)
+
+/*
+ * UART control structure offsets
+ */
+#define _UCREG(x)				io_p2v(\
+						LPC32XX_UART_CTRL_BASE + (x))
+#define LPC32XX_UARTCTL_CTRL			_UCREG(0x00)
+#define LPC32XX_UARTCTL_CLKMODE			_UCREG(0x04)
+#define LPC32XX_UARTCTL_CLOOP			_UCREG(0x08)
+
+/*
+ * ctrl register definitions
+ */
+#define LPC32XX_UART_U3_MD_CTRL_EN		_BIT(11)
+#define LPC32XX_UART_IRRX6_INV_EN		_BIT(10)
+#define LPC32XX_UART_HDPX_EN			_BIT(9)
+#define LPC32XX_UART_UART6_IRDAMOD_BYPASS	_BIT(5)
+#define LPC32XX_RT_IRTX6_INV_EN			_BIT(4)
+#define LPC32XX_RT_IRTX6_INV_MIR_EN		_BIT(3)
+#define LPC32XX_RT_RX_IRPULSE_3_16_115K		_BIT(2)
+#define LPC32XX_RT_TX_IRPULSE_3_16_115K		_BIT(1)
+#define LPC32XX_UART_U5_ROUTE_TO_USB		_BIT(0)
+
+/*
+ * clkmode register definitions
+ */
+#define LPC32XX_UART_ENABLED_CLOCKS(n)		(((n) >> 16) & 0x7F)
+#define LPC32XX_UART_ENABLED_CLOCK(n, u)	(((n) >> (16 + (u))) & 0x1)
+#define LPC32XX_UART_ENABLED_CLKS_ANY		_BIT(14)
+#define LPC32XX_UART_CLKMODE_OFF		0x0
+#define LPC32XX_UART_CLKMODE_ON			0x1
+#define LPC32XX_UART_CLKMODE_AUTO		0x2
+#define LPC32XX_UART_CLKMODE_MASK(u)		(0x3 << ((((u) - 3) * 2) + 4))
+#define LPC32XX_UART_CLKMODE_LOAD(m, u)		((m) << ((((u) - 3) * 2) + 4))
+
+/*
+ * GPIO Module Register offsets
+ */
+#define _GPREG(x)				io_p2v(LPC32XX_GPIO_BASE + (x))
+#define LPC32XX_GPIO_P_MUX_SET			_GPREG(0x100)
+#define LPC32XX_GPIO_P_MUX_CLR			_GPREG(0x104)
+#define LPC32XX_GPIO_P_MUX_STATE		_GPREG(0x108)
+#define LPC32XX_GPIO_P3_MUX_SET			_GPREG(0x110)
+#define LPC32XX_GPIO_P3_MUX_CLR			_GPREG(0x114)
+#define LPC32XX_GPIO_P3_MUX_STATE		_GPREG(0x118)
+#define LPC32XX_GPIO_P0_MUX_SET			_GPREG(0x120)
+#define LPC32XX_GPIO_P0_MUX_CLR			_GPREG(0x124)
+#define LPC32XX_GPIO_P0_MUX_STATE		_GPREG(0x128)
+#define LPC32XX_GPIO_P1_MUX_SET			_GPREG(0x130)
+#define LPC32XX_GPIO_P1_MUX_CLR			_GPREG(0x134)
+#define LPC32XX_GPIO_P1_MUX_STATE		_GPREG(0x138)
+
+#endif

+ 52 - 0
arch/arm/mach-lpc32xx/include/mach/system.h

@@ -0,0 +1,52 @@
+/*
+ * arch/arm/mach-lpc32xx/include/mach/system.h
+ *
+ * Author: Kevin Wells <kevin.wells@nxp.com>
+ *
+ * Copyright (C) 2010 NXP Semiconductors
+ *
+ * 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.
+ */
+
+#ifndef __ASM_ARCH_SYSTEM_H
+#define __ASM_ARCH_SYSTEM_H
+
+static void arch_idle(void)
+{
+	cpu_do_idle();
+}
+
+static inline void arch_reset(char mode, const char *cmd)
+{
+	extern void lpc32xx_watchdog_reset(void);
+
+	switch (mode) {
+	case 's':
+	case 'h':
+		printk(KERN_CRIT "RESET: Rebooting system\n");
+
+		/* Disable interrupts */
+		local_irq_disable();
+
+		lpc32xx_watchdog_reset();
+		break;
+
+	default:
+		/* Do nothing */
+		break;
+	}
+
+	/* Wait for watchdog to reset system */
+	while (1)
+		;
+}
+
+#endif

+ 28 - 0
arch/arm/mach-lpc32xx/include/mach/timex.h

@@ -0,0 +1,28 @@
+/*
+ * arch/arm/mach-lpc32xx/include/mach/timex.h
+ *
+ * Author: Kevin Wells <kevin.wells@nxp.com>
+ *
+ * Copyright (C) 2010 NXP Semiconductors
+ *
+ * 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.
+ */
+
+#ifndef __ASM_ARCH_TIMEX_H
+#define __ASM_ARCH_TIMEX_H
+
+/*
+ * Rate in Hz of the main system oscillator. This value should match
+ * the value 'MAIN_OSC_FREQ' in platform.h
+ */
+#define CLOCK_TICK_RATE	13000000
+
+#endif

+ 60 - 0
arch/arm/mach-lpc32xx/include/mach/uncompress.h

@@ -0,0 +1,60 @@
+/*
+ * arch/arm/mach-lpc32xx/include/mach/uncompress.h
+ *
+ * Author: Kevin Wells <kevin.wells@nxp.com>
+ *
+ * Copyright (C) 2010 NXP Semiconductors
+ *
+ * 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.
+ */
+
+#ifndef __ASM_ARM_ARCH_UNCOMPRESS_H
+#define __ASM_ARM_ARCH_UNCOMPRESS_H
+
+#include <linux/io.h>
+
+#include <mach/hardware.h>
+#include <mach/platform.h>
+
+/*
+ * Uncompress output is hardcoded to standard UART 5
+ */
+
+#define UART_FIFO_CTL_TX_RESET	(1 << 2)
+#define UART_STATUS_TX_MT	(1 << 6)
+
+#define _UARTREG(x)		(void __iomem *)(LPC32XX_UART5_BASE + (x))
+
+#define LPC32XX_UART_DLLFIFO_O	0x00
+#define LPC32XX_UART_IIRFCR_O	0x08
+#define LPC32XX_UART_LSR_O	0x14
+
+static inline void putc(int ch)
+{
+	/* Wait for transmit FIFO to empty */
+	while ((__raw_readl(_UARTREG(LPC32XX_UART_LSR_O)) &
+		UART_STATUS_TX_MT) == 0)
+		;
+
+	__raw_writel((u32) ch, _UARTREG(LPC32XX_UART_DLLFIFO_O));
+}
+
+static inline void flush(void)
+{
+	__raw_writel(__raw_readl(_UARTREG(LPC32XX_UART_IIRFCR_O)) |
+		UART_FIFO_CTL_TX_RESET, _UARTREG(LPC32XX_UART_IIRFCR_O));
+}
+
+/* NULL functions; we don't presently need them */
+#define arch_decomp_setup()
+#define arch_decomp_wdog()
+
+#endif

+ 24 - 0
arch/arm/mach-lpc32xx/include/mach/vmalloc.h

@@ -0,0 +1,24 @@
+/*
+ * arch/arm/mach-lpc32xx/include/mach/vmalloc.h
+ *
+ * Author: Kevin Wells <kevin.wells@nxp.com>
+ *
+ * Copyright (C) 2010 NXP Semiconductors
+ *
+ * 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.
+ */
+
+#ifndef __ASM_ARCH_VMALLOC_H
+#define __ASM_ARCH_VMALLOC_H
+
+#define VMALLOC_END	0xF0000000
+
+#endif

+ 432 - 0
arch/arm/mach-lpc32xx/irq.c

@@ -0,0 +1,432 @@
+/*
+ * arch/arm/mach-lpc32xx/irq.c
+ *
+ * Author: Kevin Wells <kevin.wells@nxp.com>
+ *
+ * Copyright (C) 2010 NXP Semiconductors
+ *
+ * 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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/err.h>
+#include <linux/io.h>
+
+#include <mach/irqs.h>
+#include <mach/hardware.h>
+#include <mach/platform.h>
+#include "common.h"
+
+/*
+ * Default value representing the Activation polarity of all internal
+ * interrupt sources
+ */
+#define MIC_APR_DEFAULT		0x3FF0EFE0
+#define SIC1_APR_DEFAULT	0xFBD27186
+#define SIC2_APR_DEFAULT	0x801810C0
+
+/*
+ * Default value representing the Activation Type of all internal
+ * interrupt sources. All are level sensitive.
+ */
+#define MIC_ATR_DEFAULT		0x00000000
+#define SIC1_ATR_DEFAULT	0x00026000
+#define SIC2_ATR_DEFAULT	0x00000000
+
+struct lpc32xx_event_group_regs {
+	void __iomem *enab_reg;
+	void __iomem *edge_reg;
+	void __iomem *maskstat_reg;
+	void __iomem *rawstat_reg;
+};
+
+static const struct lpc32xx_event_group_regs lpc32xx_event_int_regs = {
+	.enab_reg = LPC32XX_CLKPWR_INT_ER,
+	.edge_reg = LPC32XX_CLKPWR_INT_AP,
+	.maskstat_reg = LPC32XX_CLKPWR_INT_SR,
+	.rawstat_reg = LPC32XX_CLKPWR_INT_RS,
+};
+
+static const struct lpc32xx_event_group_regs lpc32xx_event_pin_regs = {
+	.enab_reg = LPC32XX_CLKPWR_PIN_ER,
+	.edge_reg = LPC32XX_CLKPWR_PIN_AP,
+	.maskstat_reg = LPC32XX_CLKPWR_PIN_SR,
+	.rawstat_reg = LPC32XX_CLKPWR_PIN_RS,
+};
+
+struct lpc32xx_event_info {
+	const struct lpc32xx_event_group_regs *event_group;
+	u32 mask;
+};
+
+/*
+ * Maps an IRQ number to and event mask and register
+ */
+static const struct lpc32xx_event_info lpc32xx_events[NR_IRQS] = {
+	[IRQ_LPC32XX_GPI_08] = {
+		.event_group = &lpc32xx_event_pin_regs,
+		.mask = LPC32XX_CLKPWR_EXTSRC_GPI_08_BIT,
+	},
+	[IRQ_LPC32XX_GPI_09] = {
+		.event_group = &lpc32xx_event_pin_regs,
+		.mask = LPC32XX_CLKPWR_EXTSRC_GPI_09_BIT,
+	},
+	[IRQ_LPC32XX_GPI_19] = {
+		.event_group = &lpc32xx_event_pin_regs,
+		.mask = LPC32XX_CLKPWR_EXTSRC_GPI_19_BIT,
+	},
+	[IRQ_LPC32XX_GPI_07] = {
+		.event_group = &lpc32xx_event_pin_regs,
+		.mask = LPC32XX_CLKPWR_EXTSRC_GPI_07_BIT,
+	},
+	[IRQ_LPC32XX_GPI_00] = {
+		.event_group = &lpc32xx_event_pin_regs,
+		.mask = LPC32XX_CLKPWR_EXTSRC_GPI_00_BIT,
+	},
+	[IRQ_LPC32XX_GPI_01] = {
+		.event_group = &lpc32xx_event_pin_regs,
+		.mask = LPC32XX_CLKPWR_EXTSRC_GPI_01_BIT,
+	},
+	[IRQ_LPC32XX_GPI_02] = {
+		.event_group = &lpc32xx_event_pin_regs,
+		.mask = LPC32XX_CLKPWR_EXTSRC_GPI_02_BIT,
+	},
+	[IRQ_LPC32XX_GPI_03] = {
+		.event_group = &lpc32xx_event_pin_regs,
+		.mask = LPC32XX_CLKPWR_EXTSRC_GPI_03_BIT,
+	},
+	[IRQ_LPC32XX_GPI_04] = {
+		.event_group = &lpc32xx_event_pin_regs,
+		.mask = LPC32XX_CLKPWR_EXTSRC_GPI_04_BIT,
+	},
+	[IRQ_LPC32XX_GPI_05] = {
+		.event_group = &lpc32xx_event_pin_regs,
+		.mask = LPC32XX_CLKPWR_EXTSRC_GPI_05_BIT,
+	},
+	[IRQ_LPC32XX_GPI_06] = {
+		.event_group = &lpc32xx_event_pin_regs,
+		.mask = LPC32XX_CLKPWR_EXTSRC_GPI_06_BIT,
+	},
+	[IRQ_LPC32XX_GPIO_00] = {
+		.event_group = &lpc32xx_event_int_regs,
+		.mask = LPC32XX_CLKPWR_INTSRC_GPIO_00_BIT,
+	},
+	[IRQ_LPC32XX_GPIO_01] = {
+		.event_group = &lpc32xx_event_int_regs,
+		.mask = LPC32XX_CLKPWR_INTSRC_GPIO_01_BIT,
+	},
+	[IRQ_LPC32XX_GPIO_02] = {
+		.event_group = &lpc32xx_event_int_regs,
+		.mask = LPC32XX_CLKPWR_INTSRC_GPIO_02_BIT,
+	},
+	[IRQ_LPC32XX_GPIO_03] = {
+		.event_group = &lpc32xx_event_int_regs,
+		.mask = LPC32XX_CLKPWR_INTSRC_GPIO_03_BIT,
+	},
+	[IRQ_LPC32XX_GPIO_04] = {
+		.event_group = &lpc32xx_event_int_regs,
+		.mask = LPC32XX_CLKPWR_INTSRC_GPIO_04_BIT,
+	},
+	[IRQ_LPC32XX_GPIO_05] = {
+		.event_group = &lpc32xx_event_int_regs,
+		.mask = LPC32XX_CLKPWR_INTSRC_GPIO_05_BIT,
+	},
+	[IRQ_LPC32XX_KEY] = {
+		.event_group = &lpc32xx_event_int_regs,
+		.mask = LPC32XX_CLKPWR_INTSRC_KEY_BIT,
+	},
+	[IRQ_LPC32XX_USB_OTG_ATX] = {
+		.event_group = &lpc32xx_event_int_regs,
+		.mask = LPC32XX_CLKPWR_INTSRC_USBATXINT_BIT,
+	},
+	[IRQ_LPC32XX_USB_HOST] = {
+		.event_group = &lpc32xx_event_int_regs,
+		.mask = LPC32XX_CLKPWR_INTSRC_USB_BIT,
+	},
+	[IRQ_LPC32XX_RTC] = {
+		.event_group = &lpc32xx_event_int_regs,
+		.mask = LPC32XX_CLKPWR_INTSRC_RTC_BIT,
+	},
+	[IRQ_LPC32XX_MSTIMER] = {
+		.event_group = &lpc32xx_event_int_regs,
+		.mask = LPC32XX_CLKPWR_INTSRC_MSTIMER_BIT,
+	},
+	[IRQ_LPC32XX_TS_AUX] = {
+		.event_group = &lpc32xx_event_int_regs,
+		.mask = LPC32XX_CLKPWR_INTSRC_TS_AUX_BIT,
+	},
+	[IRQ_LPC32XX_TS_P] = {
+		.event_group = &lpc32xx_event_int_regs,
+		.mask = LPC32XX_CLKPWR_INTSRC_TS_P_BIT,
+	},
+	[IRQ_LPC32XX_TS_IRQ] = {
+		.event_group = &lpc32xx_event_int_regs,
+		.mask = LPC32XX_CLKPWR_INTSRC_ADC_BIT,
+	},
+};
+
+static void get_controller(unsigned int irq, unsigned int *base,
+	unsigned int *irqbit)
+{
+	if (irq < 32) {
+		*base = LPC32XX_MIC_BASE;
+		*irqbit = 1 << irq;
+	} else if (irq < 64) {
+		*base = LPC32XX_SIC1_BASE;
+		*irqbit = 1 << (irq - 32);
+	} else {
+		*base = LPC32XX_SIC2_BASE;
+		*irqbit = 1 << (irq - 64);
+	}
+}
+
+static void lpc32xx_mask_irq(unsigned int irq)
+{
+	unsigned int reg, ctrl, mask;
+
+	get_controller(irq, &ctrl, &mask);
+
+	reg = __raw_readl(LPC32XX_INTC_MASK(ctrl)) & ~mask;
+	__raw_writel(reg, LPC32XX_INTC_MASK(ctrl));
+}
+
+static void lpc32xx_unmask_irq(unsigned int irq)
+{
+	unsigned int reg, ctrl, mask;
+
+	get_controller(irq, &ctrl, &mask);
+
+	reg = __raw_readl(LPC32XX_INTC_MASK(ctrl)) | mask;
+	__raw_writel(reg, LPC32XX_INTC_MASK(ctrl));
+}
+
+static void lpc32xx_ack_irq(unsigned int irq)
+{
+	unsigned int ctrl, mask;
+
+	get_controller(irq, &ctrl, &mask);
+
+	__raw_writel(mask, LPC32XX_INTC_RAW_STAT(ctrl));
+
+	/* Also need to clear pending wake event */
+	if (lpc32xx_events[irq].mask != 0)
+		__raw_writel(lpc32xx_events[irq].mask,
+			lpc32xx_events[irq].event_group->rawstat_reg);
+}
+
+static void __lpc32xx_set_irq_type(unsigned int irq, int use_high_level,
+	int use_edge)
+{
+	unsigned int reg, ctrl, mask;
+
+	get_controller(irq, &ctrl, &mask);
+
+	/* Activation level, high or low */
+	reg = __raw_readl(LPC32XX_INTC_POLAR(ctrl));
+	if (use_high_level)
+		reg |= mask;
+	else
+		reg &= ~mask;
+	__raw_writel(reg, LPC32XX_INTC_POLAR(ctrl));
+
+	/* Activation type, edge or level */
+	reg = __raw_readl(LPC32XX_INTC_ACT_TYPE(ctrl));
+	if (use_edge)
+		reg |= mask;
+	else
+		reg &= ~mask;
+	__raw_writel(reg, LPC32XX_INTC_ACT_TYPE(ctrl));
+
+	/* Use same polarity for the wake events */
+	if (lpc32xx_events[irq].mask != 0) {
+		reg = __raw_readl(lpc32xx_events[irq].event_group->edge_reg);
+
+		if (use_high_level)
+			reg |= lpc32xx_events[irq].mask;
+		else
+			reg &= ~lpc32xx_events[irq].mask;
+
+		__raw_writel(reg, lpc32xx_events[irq].event_group->edge_reg);
+	}
+}
+
+static int lpc32xx_set_irq_type(unsigned int irq, unsigned int type)
+{
+	switch (type) {
+	case IRQ_TYPE_EDGE_RISING:
+		/* Rising edge sensitive */
+		__lpc32xx_set_irq_type(irq, 1, 1);
+		break;
+
+	case IRQ_TYPE_EDGE_FALLING:
+		/* Falling edge sensitive */
+		__lpc32xx_set_irq_type(irq, 0, 1);
+		break;
+
+	case IRQ_TYPE_LEVEL_LOW:
+		/* Low level sensitive */
+		__lpc32xx_set_irq_type(irq, 0, 0);
+		break;
+
+	case IRQ_TYPE_LEVEL_HIGH:
+		/* High level sensitive */
+		__lpc32xx_set_irq_type(irq, 1, 0);
+		break;
+
+	/* Other modes are not supported */
+	default:
+		return -EINVAL;
+	}
+
+	/* Ok to use the level handler for all types */
+	set_irq_handler(irq, handle_level_irq);
+
+	return 0;
+}
+
+static int lpc32xx_irq_wake(unsigned int irqno, unsigned int state)
+{
+	unsigned long eventreg;
+
+	if (lpc32xx_events[irqno].mask != 0) {
+		eventreg = __raw_readl(lpc32xx_events[irqno].
+			event_group->enab_reg);
+
+		if (state)
+			eventreg |= lpc32xx_events[irqno].mask;
+		else
+			eventreg &= ~lpc32xx_events[irqno].mask;
+
+		__raw_writel(eventreg,
+			lpc32xx_events[irqno].event_group->enab_reg);
+
+		return 0;
+	}
+
+	/* Clear event */
+	__raw_writel(lpc32xx_events[irqno].mask,
+		lpc32xx_events[irqno].event_group->rawstat_reg);
+
+	return -ENODEV;
+}
+
+static void __init lpc32xx_set_default_mappings(unsigned int apr,
+	unsigned int atr, unsigned int offset)
+{
+	unsigned int i;
+
+	/* Set activation levels for each interrupt */
+	i = 0;
+	while (i < 32) {
+		__lpc32xx_set_irq_type(offset + i, ((apr >> i) & 0x1),
+			((atr >> i) & 0x1));
+		i++;
+	}
+}
+
+static struct irq_chip lpc32xx_irq_chip = {
+	.ack = lpc32xx_ack_irq,
+	.mask = lpc32xx_mask_irq,
+	.unmask = lpc32xx_unmask_irq,
+	.set_type = lpc32xx_set_irq_type,
+	.set_wake = lpc32xx_irq_wake
+};
+
+static void lpc32xx_sic1_handler(unsigned int irq, struct irq_desc *desc)
+{
+	unsigned long ints = __raw_readl(LPC32XX_INTC_STAT(LPC32XX_SIC1_BASE));
+
+	while (ints != 0) {
+		int irqno = fls(ints) - 1;
+
+		ints &= ~(1 << irqno);
+
+		generic_handle_irq(LPC32XX_SIC1_IRQ(irqno));
+	}
+}
+
+static void lpc32xx_sic2_handler(unsigned int irq, struct irq_desc *desc)
+{
+	unsigned long ints = __raw_readl(LPC32XX_INTC_STAT(LPC32XX_SIC2_BASE));
+
+	while (ints != 0) {
+		int irqno = fls(ints) - 1;
+
+		ints &= ~(1 << irqno);
+
+		generic_handle_irq(LPC32XX_SIC2_IRQ(irqno));
+	}
+}
+
+void __init lpc32xx_init_irq(void)
+{
+	unsigned int i;
+
+	/* Setup MIC */
+	__raw_writel(0, LPC32XX_INTC_MASK(LPC32XX_MIC_BASE));
+	__raw_writel(MIC_APR_DEFAULT, LPC32XX_INTC_POLAR(LPC32XX_MIC_BASE));
+	__raw_writel(MIC_ATR_DEFAULT, LPC32XX_INTC_ACT_TYPE(LPC32XX_MIC_BASE));
+
+	/* Setup SIC1 */
+	__raw_writel(0, LPC32XX_INTC_MASK(LPC32XX_SIC1_BASE));
+	__raw_writel(MIC_APR_DEFAULT, LPC32XX_INTC_POLAR(LPC32XX_SIC1_BASE));
+	__raw_writel(MIC_ATR_DEFAULT, LPC32XX_INTC_ACT_TYPE(LPC32XX_SIC1_BASE));
+
+	/* Setup SIC2 */
+	__raw_writel(0, LPC32XX_INTC_MASK(LPC32XX_SIC2_BASE));
+	__raw_writel(MIC_APR_DEFAULT, LPC32XX_INTC_POLAR(LPC32XX_SIC2_BASE));
+	__raw_writel(MIC_ATR_DEFAULT, LPC32XX_INTC_ACT_TYPE(LPC32XX_SIC2_BASE));
+
+	/* Configure supported IRQ's */
+	for (i = 0; i < NR_IRQS; i++) {
+		set_irq_chip(i, &lpc32xx_irq_chip);
+		set_irq_handler(i, handle_level_irq);
+		set_irq_flags(i, IRQF_VALID);
+	}
+
+	/* Set default mappings */
+	lpc32xx_set_default_mappings(MIC_APR_DEFAULT, MIC_ATR_DEFAULT, 0);
+	lpc32xx_set_default_mappings(SIC1_APR_DEFAULT, SIC1_ATR_DEFAULT, 32);
+	lpc32xx_set_default_mappings(SIC2_APR_DEFAULT, SIC2_ATR_DEFAULT, 64);
+
+	/* mask all interrupts except SUBIRQ */
+	__raw_writel(0, LPC32XX_INTC_MASK(LPC32XX_MIC_BASE));
+	__raw_writel(0, LPC32XX_INTC_MASK(LPC32XX_SIC1_BASE));
+	__raw_writel(0, LPC32XX_INTC_MASK(LPC32XX_SIC2_BASE));
+
+	/* MIC SUBIRQx interrupts will route handling to the chain handlers */
+	set_irq_chained_handler(IRQ_LPC32XX_SUB1IRQ, lpc32xx_sic1_handler);
+	set_irq_chained_handler(IRQ_LPC32XX_SUB2IRQ, lpc32xx_sic2_handler);
+
+	/* Initially disable all wake events */
+	__raw_writel(0, LPC32XX_CLKPWR_P01_ER);
+	__raw_writel(0, LPC32XX_CLKPWR_INT_ER);
+	__raw_writel(0, LPC32XX_CLKPWR_PIN_ER);
+
+	/*
+	 * Default wake activation polarities, all pin sources are low edge
+	 * triggered
+	 */
+	__raw_writel(LPC32XX_CLKPWR_INTSRC_TS_P_BIT |
+		LPC32XX_CLKPWR_INTSRC_MSTIMER_BIT |
+		LPC32XX_CLKPWR_INTSRC_RTC_BIT,
+		LPC32XX_CLKPWR_INT_AP);
+	__raw_writel(0, LPC32XX_CLKPWR_PIN_AP);
+
+	/* Clear latched wake event states */
+	__raw_writel(__raw_readl(LPC32XX_CLKPWR_PIN_RS),
+		LPC32XX_CLKPWR_PIN_RS);
+	__raw_writel(__raw_readl(LPC32XX_CLKPWR_INT_RS),
+		LPC32XX_CLKPWR_INT_RS);
+}

+ 397 - 0
arch/arm/mach-lpc32xx/phy3250.c

@@ -0,0 +1,397 @@
+/*
+ * arch/arm/mach-lpc32xx/phy3250.c
+ *
+ * Author: Kevin Wells <kevin.wells@nxp.com>
+ *
+ * Copyright (C) 2010 NXP Semiconductors
+ *
+ * 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.
+ */
+
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/sysdev.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/dma-mapping.h>
+#include <linux/device.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/eeprom.h>
+#include <linux/leds.h>
+#include <linux/gpio.h>
+#include <linux/amba/bus.h>
+#include <linux/amba/clcd.h>
+#include <linux/amba/pl022.h>
+
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+
+#include <mach/hardware.h>
+#include <mach/platform.h>
+#include "common.h"
+
+/*
+ * Mapped GPIOLIB GPIOs
+ */
+#define SPI0_CS_GPIO	LPC32XX_GPIO(LPC32XX_GPIO_P3_GRP, 5)
+#define LCD_POWER_GPIO	LPC32XX_GPIO(LPC32XX_GPO_P3_GRP, 0)
+#define BKL_POWER_GPIO	LPC32XX_GPIO(LPC32XX_GPO_P3_GRP, 4)
+#define LED_GPIO	LPC32XX_GPIO(LPC32XX_GPO_P3_GRP, 1)
+
+/*
+ * AMBA LCD controller
+ */
+static struct clcd_panel conn_lcd_panel = {
+	.mode		= {
+		.name		= "QVGA portrait",
+		.refresh	= 60,
+		.xres		= 240,
+		.yres		= 320,
+		.pixclock	= 191828,
+		.left_margin	= 22,
+		.right_margin	= 11,
+		.upper_margin	= 2,
+		.lower_margin	= 1,
+		.hsync_len	= 5,
+		.vsync_len	= 2,
+		.sync		= 0,
+		.vmode		= FB_VMODE_NONINTERLACED,
+	},
+	.width		= -1,
+	.height		= -1,
+	.tim2		= (TIM2_IVS | TIM2_IHS),
+	.cntl		= (CNTL_BGR | CNTL_LCDTFT | CNTL_LCDVCOMP(1) |
+				CNTL_LCDBPP16_565),
+	.bpp		= 16,
+};
+#define PANEL_SIZE (3 * SZ_64K)
+
+static int lpc32xx_clcd_setup(struct clcd_fb *fb)
+{
+	dma_addr_t dma;
+
+	fb->fb.screen_base = dma_alloc_writecombine(&fb->dev->dev,
+		PANEL_SIZE, &dma, GFP_KERNEL);
+	if (!fb->fb.screen_base) {
+		printk(KERN_ERR "CLCD: unable to map framebuffer\n");
+		return -ENOMEM;
+	}
+
+	fb->fb.fix.smem_start = dma;
+	fb->fb.fix.smem_len = PANEL_SIZE;
+	fb->panel = &conn_lcd_panel;
+
+	if (gpio_request(LCD_POWER_GPIO, "LCD power"))
+		printk(KERN_ERR "Error requesting gpio %u",
+			LCD_POWER_GPIO);
+	else if (gpio_direction_output(LCD_POWER_GPIO, 1))
+		printk(KERN_ERR "Error setting gpio %u to output",
+			LCD_POWER_GPIO);
+
+	if (gpio_request(BKL_POWER_GPIO, "LCD backlight power"))
+		printk(KERN_ERR "Error requesting gpio %u",
+			BKL_POWER_GPIO);
+	else if (gpio_direction_output(BKL_POWER_GPIO, 1))
+		printk(KERN_ERR "Error setting gpio %u to output",
+			BKL_POWER_GPIO);
+
+	return 0;
+}
+
+static int lpc32xx_clcd_mmap(struct clcd_fb *fb, struct vm_area_struct *vma)
+{
+	return dma_mmap_writecombine(&fb->dev->dev, vma,
+		fb->fb.screen_base, fb->fb.fix.smem_start,
+		fb->fb.fix.smem_len);
+}
+
+static void lpc32xx_clcd_remove(struct clcd_fb *fb)
+{
+	dma_free_writecombine(&fb->dev->dev, fb->fb.fix.smem_len,
+		fb->fb.screen_base, fb->fb.fix.smem_start);
+}
+
+/*
+ * On some early LCD modules (1307.0), the backlight logic is inverted.
+ * For those board variants, swap the disable and enable states for
+ * BKL_POWER_GPIO.
+*/
+static void clcd_disable(struct clcd_fb *fb)
+{
+	gpio_set_value(BKL_POWER_GPIO, 0);
+	gpio_set_value(LCD_POWER_GPIO, 0);
+}
+
+static void clcd_enable(struct clcd_fb *fb)
+{
+	gpio_set_value(BKL_POWER_GPIO, 1);
+	gpio_set_value(LCD_POWER_GPIO, 1);
+}
+
+static struct clcd_board lpc32xx_clcd_data = {
+	.name		= "Phytec LCD",
+	.check		= clcdfb_check,
+	.decode		= clcdfb_decode,
+	.disable	= clcd_disable,
+	.enable		= clcd_enable,
+	.setup		= lpc32xx_clcd_setup,
+	.mmap		= lpc32xx_clcd_mmap,
+	.remove		= lpc32xx_clcd_remove,
+};
+
+static struct amba_device lpc32xx_clcd_device = {
+	.dev				= {
+		.coherent_dma_mask	= ~0,
+		.init_name		= "dev:clcd",
+		.platform_data		= &lpc32xx_clcd_data,
+	},
+	.res				= {
+		.start			= LPC32XX_LCD_BASE,
+		.end			= (LPC32XX_LCD_BASE + SZ_4K - 1),
+		.flags			= IORESOURCE_MEM,
+	},
+	.dma_mask			= ~0,
+	.irq				= {IRQ_LPC32XX_LCD, NO_IRQ},
+};
+
+/*
+ * AMBA SSP (SPI)
+ */
+static void phy3250_spi_cs_set(u32 control)
+{
+	gpio_set_value(SPI0_CS_GPIO, (int) control);
+}
+
+static struct pl022_config_chip spi0_chip_info = {
+	.lbm			= LOOPBACK_DISABLED,
+	.com_mode		= INTERRUPT_TRANSFER,
+	.iface			= SSP_INTERFACE_MOTOROLA_SPI,
+	.hierarchy		= SSP_MASTER,
+	.slave_tx_disable	= 0,
+	.endian_tx		= SSP_TX_LSB,
+	.endian_rx		= SSP_RX_LSB,
+	.data_size		= SSP_DATA_BITS_8,
+	.rx_lev_trig		= SSP_RX_4_OR_MORE_ELEM,
+	.tx_lev_trig		= SSP_TX_4_OR_MORE_EMPTY_LOC,
+	.clk_phase		= SSP_CLK_FIRST_EDGE,
+	.clk_pol		= SSP_CLK_POL_IDLE_LOW,
+	.ctrl_len		= SSP_BITS_8,
+	.wait_state		= SSP_MWIRE_WAIT_ZERO,
+	.duplex			= SSP_MICROWIRE_CHANNEL_FULL_DUPLEX,
+	.cs_control		= phy3250_spi_cs_set,
+};
+
+static struct pl022_ssp_controller lpc32xx_ssp0_data = {
+	.bus_id			= 0,
+	.num_chipselect		= 1,
+	.enable_dma		= 0,
+};
+
+static struct amba_device lpc32xx_ssp0_device = {
+	.dev				= {
+		.coherent_dma_mask	= ~0,
+		.init_name		= "dev:ssp0",
+		.platform_data		= &lpc32xx_ssp0_data,
+	},
+	.res				= {
+		.start			= LPC32XX_SSP0_BASE,
+		.end			= (LPC32XX_SSP0_BASE + SZ_4K - 1),
+		.flags			= IORESOURCE_MEM,
+	},
+	.dma_mask			= ~0,
+	.irq				= {IRQ_LPC32XX_SSP0, NO_IRQ},
+};
+
+/* AT25 driver registration */
+static int __init phy3250_spi_board_register(void)
+{
+#if defined(CONFIG_SPI_SPIDEV) || defined(CONFIG_SPI_SPIDEV_MODULE)
+	static struct spi_board_info info[] = {
+		{
+			.modalias = "spidev",
+			.max_speed_hz = 5000000,
+			.bus_num = 0,
+			.chip_select = 0,
+			.controller_data = &spi0_chip_info,
+		},
+	};
+
+#else
+	static struct spi_eeprom eeprom = {
+		.name = "at25256a",
+		.byte_len = 0x8000,
+		.page_size = 64,
+		.flags = EE_ADDR2,
+	};
+
+	static struct spi_board_info info[] = {
+		{
+			.modalias = "at25",
+			.max_speed_hz = 5000000,
+			.bus_num = 0,
+			.chip_select = 0,
+			.platform_data = &eeprom,
+			.controller_data = &spi0_chip_info,
+		},
+	};
+#endif
+	return spi_register_board_info(info, ARRAY_SIZE(info));
+}
+arch_initcall(phy3250_spi_board_register);
+
+static struct i2c_board_info __initdata phy3250_i2c_board_info[] = {
+	{
+		I2C_BOARD_INFO("pcf8563", 0x51),
+	},
+};
+
+static struct gpio_led phy_leds[] = {
+	{
+		.name			= "led0",
+		.gpio			= LED_GPIO,
+		.active_low		= 1,
+		.default_trigger	= "heartbeat",
+	},
+};
+
+static struct gpio_led_platform_data led_data = {
+	.leds = phy_leds,
+	.num_leds = ARRAY_SIZE(phy_leds),
+};
+
+static struct platform_device lpc32xx_gpio_led_device = {
+	.name			= "leds-gpio",
+	.id			= -1,
+	.dev.platform_data	= &led_data,
+};
+
+static struct platform_device *phy3250_devs[] __initdata = {
+	&lpc32xx_i2c0_device,
+	&lpc32xx_i2c1_device,
+	&lpc32xx_i2c2_device,
+	&lpc32xx_watchdog_device,
+	&lpc32xx_gpio_led_device,
+};
+
+static struct amba_device *amba_devs[] __initdata = {
+	&lpc32xx_clcd_device,
+	&lpc32xx_ssp0_device,
+};
+
+/*
+ * Board specific functions
+ */
+static void __init phy3250_board_init(void)
+{
+	u32 tmp;
+	int i;
+
+	lpc32xx_gpio_init();
+
+	/* Register GPIOs used on this board */
+	if (gpio_request(SPI0_CS_GPIO, "spi0 cs"))
+		printk(KERN_ERR "Error requesting gpio %u",
+			SPI0_CS_GPIO);
+	else if (gpio_direction_output(SPI0_CS_GPIO, 1))
+		printk(KERN_ERR "Error setting gpio %u to output",
+			SPI0_CS_GPIO);
+
+	/* Setup network interface for RMII mode */
+	tmp = __raw_readl(LPC32XX_CLKPWR_MACCLK_CTRL);
+	tmp &= ~LPC32XX_CLKPWR_MACCTRL_PINS_MSK;
+	tmp |= LPC32XX_CLKPWR_MACCTRL_USE_RMII_PINS;
+	__raw_writel(tmp, LPC32XX_CLKPWR_MACCLK_CTRL);
+
+	/* Setup SLC NAND controller muxing */
+	__raw_writel(LPC32XX_CLKPWR_NANDCLK_SEL_SLC,
+		LPC32XX_CLKPWR_NAND_CLK_CTRL);
+
+	/* Setup LCD muxing to RGB565 */
+	tmp = __raw_readl(LPC32XX_CLKPWR_LCDCLK_CTRL) &
+		~(LPC32XX_CLKPWR_LCDCTRL_LCDTYPE_MSK |
+		LPC32XX_CLKPWR_LCDCTRL_PSCALE_MSK);
+	tmp |= LPC32XX_CLKPWR_LCDCTRL_LCDTYPE_TFT16;
+	__raw_writel(tmp, LPC32XX_CLKPWR_LCDCLK_CTRL);
+
+	/* Set up I2C pull levels */
+	tmp = __raw_readl(LPC32XX_CLKPWR_I2C_CLK_CTRL);
+	tmp |= LPC32XX_CLKPWR_I2CCLK_USBI2CHI_DRIVE |
+		LPC32XX_CLKPWR_I2CCLK_I2C2HI_DRIVE;
+	__raw_writel(tmp, LPC32XX_CLKPWR_I2C_CLK_CTRL);
+
+	/* Disable IrDA pulsing support on UART6 */
+	tmp = __raw_readl(LPC32XX_UARTCTL_CTRL);
+	tmp |= LPC32XX_UART_UART6_IRDAMOD_BYPASS;
+	__raw_writel(tmp, LPC32XX_UARTCTL_CTRL);
+
+	/* Enable DMA for I2S1 channel */
+	tmp = __raw_readl(LPC32XX_CLKPWR_I2S_CLK_CTRL);
+	tmp = LPC32XX_CLKPWR_I2SCTRL_I2S1_USE_DMA;
+	__raw_writel(tmp, LPC32XX_CLKPWR_I2S_CLK_CTRL);
+
+	lpc32xx_serial_init();
+
+	/*
+	 * AMBA peripheral clocks need to be enabled prior to AMBA device
+	 * detection or a data fault will occur, so enable the clocks
+	 * here. However, we don't want to enable them if the peripheral
+	 * isn't included in the image
+	 */
+#ifdef CONFIG_FB_ARMCLCD
+	tmp = __raw_readl(LPC32XX_CLKPWR_LCDCLK_CTRL);
+	__raw_writel((tmp | LPC32XX_CLKPWR_LCDCTRL_CLK_EN),
+		LPC32XX_CLKPWR_LCDCLK_CTRL);
+#endif
+#ifdef CONFIG_SPI_PL022
+	tmp = __raw_readl(LPC32XX_CLKPWR_SSP_CLK_CTRL);
+	__raw_writel((tmp | LPC32XX_CLKPWR_SSPCTRL_SSPCLK0_EN),
+		LPC32XX_CLKPWR_SSP_CLK_CTRL);
+#endif
+
+	platform_add_devices(phy3250_devs, ARRAY_SIZE(phy3250_devs));
+	for (i = 0; i < ARRAY_SIZE(amba_devs); i++) {
+		struct amba_device *d = amba_devs[i];
+		amba_device_register(d, &iomem_resource);
+	}
+
+	/* Test clock needed for UDA1380 initial init */
+	__raw_writel(LPC32XX_CLKPWR_TESTCLK2_SEL_MOSC |
+		LPC32XX_CLKPWR_TESTCLK_TESTCLK2_EN,
+		LPC32XX_CLKPWR_TEST_CLK_SEL);
+
+	i2c_register_board_info(0, phy3250_i2c_board_info,
+		ARRAY_SIZE(phy3250_i2c_board_info));
+}
+
+static int __init lpc32xx_display_uid(void)
+{
+	u32 uid[4];
+
+	lpc32xx_get_uid(uid);
+
+	printk(KERN_INFO "LPC32XX unique ID: %08x%08x%08x%08x\n",
+		uid[3], uid[2], uid[1], uid[0]);
+
+	return 1;
+}
+arch_initcall(lpc32xx_display_uid);
+
+MACHINE_START(PHY3250, "Phytec 3250 board with the LPC3250 Microcontroller")
+	/* Maintainer: Kevin Wells, NXP Semiconductors */
+	.phys_io	= LPC32XX_UART5_BASE,
+	.io_pg_offst	= ((IO_ADDRESS(LPC32XX_UART5_BASE))>>18) & 0xfffc,
+	.boot_params	= 0x80000100,
+	.map_io		= lpc32xx_map_io,
+	.init_irq	= lpc32xx_init_irq,
+	.timer		= &lpc32xx_timer,
+	.init_machine	= phy3250_board_init,
+MACHINE_END

+ 146 - 0
arch/arm/mach-lpc32xx/pm.c

@@ -0,0 +1,146 @@
+/*
+ * arch/arm/mach-lpc32xx/pm.c
+ *
+ * Original authors: Vitaly Wool, Dmitry Chigirev <source@mvista.com>
+ * Modified by Kevin Wells <kevin.wells@nxp.com>
+ *
+ * 2005 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+/*
+ * LPC32XX CPU and system power management
+ *
+ * The LCP32XX has three CPU modes for controlling system power: run,
+ * direct-run, and halt modes. When switching between halt and run modes,
+ * the CPU transistions through direct-run mode. For Linux, direct-run
+ * mode is not used in normal operation. Halt mode is used when the
+ * system is fully suspended.
+ *
+ * Run mode:
+ * The ARM CPU clock (HCLK_PLL), HCLK bus clock, and PCLK bus clocks are
+ * derived from the HCLK PLL. The HCLK and PCLK bus rates are divided from
+ * the HCLK_PLL rate. Linux runs in this mode.
+ *
+ * Direct-run mode:
+ * The ARM CPU clock, HCLK bus clock, and PCLK bus clocks are driven from
+ * SYSCLK. SYSCLK is usually around 13MHz, but may vary based on SYSCLK
+ * source or the frequency of the main oscillator. In this mode, the
+ * HCLK_PLL can be safely enabled, changed, or disabled.
+ *
+ * Halt mode:
+ * SYSCLK is gated off and the CPU and system clocks are halted.
+ * Peripherals based on the 32KHz oscillator clock (ie, RTC, touch,
+ * key scanner, etc.) still operate if enabled. In this state, an enabled
+ * system event (ie, GPIO state change, RTC match, key press, etc.) will
+ * wake the system up back into direct-run mode.
+ *
+ * DRAM refresh
+ * DRAM clocking and refresh are slightly different for systems with DDR
+ * DRAM or regular SDRAM devices. If SDRAM is used in the system, the
+ * SDRAM will still be accessible in direct-run mode. In DDR based systems,
+ * a transistion to direct-run mode will stop all DDR accesses (no clocks).
+ * Because of this, the code to switch power modes and the code to enter
+ * and exit DRAM self-refresh modes must not be executed in DRAM. A small
+ * section of IRAM is used instead for this.
+ *
+ * Suspend is handled with the following logic:
+ *  Backup a small area of IRAM used for the suspend code
+ *  Copy suspend code to IRAM
+ *  Transfer control to code in IRAM
+ *  Places DRAMs in self-refresh mode
+ *  Enter direct-run mode
+ *  Save state of HCLK_PLL PLL
+ *  Disable HCLK_PLL PLL
+ *  Enter halt mode - CPU and buses will stop
+ *  System enters direct-run mode when an enabled event occurs
+ *  HCLK PLL state is restored
+ *  Run mode is entered
+ *  DRAMS are placed back into normal mode
+ *  Code execution returns from IRAM
+ *  IRAM code are used for suspend is restored
+ *  Suspend mode is exited
+ */
+
+#include <linux/suspend.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+
+#include <asm/cacheflush.h>
+
+#include <mach/hardware.h>
+#include <mach/platform.h>
+#include "common.h"
+#include "clock.h"
+
+#define TEMP_IRAM_AREA  IO_ADDRESS(LPC32XX_IRAM_BASE)
+
+/*
+ * Both STANDBY and MEM suspend states are handled the same with no
+ * loss of CPU or memory state
+ */
+static int lpc32xx_pm_enter(suspend_state_t state)
+{
+	int (*lpc32xx_suspend_ptr) (void);
+	void *iram_swap_area;
+
+	/* Allocate some space for temporary IRAM storage */
+	iram_swap_area = kmalloc(lpc32xx_sys_suspend_sz, GFP_KERNEL);
+	if (!iram_swap_area) {
+		printk(KERN_ERR
+		       "PM Suspend: cannot allocate memory to save portion "
+			"of SRAM\n");
+		return -ENOMEM;
+	}
+
+	/* Backup a small area of IRAM used for the suspend code */
+	memcpy(iram_swap_area, (void *) TEMP_IRAM_AREA,
+		lpc32xx_sys_suspend_sz);
+
+	/*
+	 * Copy code to suspend system into IRAM. The suspend code
+	 * needs to run from IRAM as DRAM may no longer be available
+	 * when the PLL is stopped.
+	 */
+	memcpy((void *) TEMP_IRAM_AREA, &lpc32xx_sys_suspend,
+		lpc32xx_sys_suspend_sz);
+	flush_icache_range((unsigned long)TEMP_IRAM_AREA,
+		(unsigned long)(TEMP_IRAM_AREA) + lpc32xx_sys_suspend_sz);
+
+	/* Transfer to suspend code in IRAM */
+	lpc32xx_suspend_ptr = (void *) TEMP_IRAM_AREA;
+	flush_cache_all();
+	(void) lpc32xx_suspend_ptr();
+
+	/* Restore original IRAM contents */
+	memcpy((void *) TEMP_IRAM_AREA, iram_swap_area,
+		lpc32xx_sys_suspend_sz);
+
+	kfree(iram_swap_area);
+
+	return 0;
+}
+
+static struct platform_suspend_ops lpc32xx_pm_ops = {
+	.valid	= suspend_valid_only_mem,
+	.enter	= lpc32xx_pm_enter,
+};
+
+#define EMC_DYN_MEM_CTRL_OFS 0x20
+#define EMC_SRMMC           (1 << 3)
+#define EMC_CTRL_REG io_p2v(LPC32XX_EMC_BASE + EMC_DYN_MEM_CTRL_OFS)
+static int __init lpc32xx_pm_init(void)
+{
+	/*
+	 * Setup SDRAM self-refresh clock to automatically disable o
+	 * start of self-refresh. This only needs to be done once.
+	 */
+	__raw_writel(__raw_readl(EMC_CTRL_REG) | EMC_SRMMC, EMC_CTRL_REG);
+
+	suspend_set_ops(&lpc32xx_pm_ops);
+
+	return 0;
+}
+arch_initcall(lpc32xx_pm_init);

+ 190 - 0
arch/arm/mach-lpc32xx/serial.c

@@ -0,0 +1,190 @@
+/*
+ * arch/arm/mach-lpc32xx/serial.c
+ *
+ * Author: Kevin Wells <kevin.wells@nxp.com>
+ *
+ * Copyright (C) 2010 NXP Semiconductors
+ *
+ * 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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/serial.h>
+#include <linux/serial_core.h>
+#include <linux/serial_reg.h>
+#include <linux/serial_8250.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+
+#include <mach/hardware.h>
+#include <mach/platform.h>
+#include "common.h"
+
+#define LPC32XX_SUART_FIFO_SIZE	64
+
+/* Standard 8250/16550 compatible serial ports */
+static struct plat_serial8250_port serial_std_platform_data[] = {
+#ifdef CONFIG_ARCH_LPC32XX_UART5_SELECT
+	{
+		.membase        = io_p2v(LPC32XX_UART5_BASE),
+		.mapbase        = LPC32XX_UART5_BASE,
+		.irq		= IRQ_LPC32XX_UART_IIR5,
+		.uartclk	= LPC32XX_MAIN_OSC_FREQ,
+		.regshift	= 2,
+		.iotype		= UPIO_MEM32,
+		.flags		= UPF_BOOT_AUTOCONF | UPF_BUGGY_UART |
+					UPF_SKIP_TEST,
+	},
+#endif
+#ifdef CONFIG_ARCH_LPC32XX_UART3_SELECT
+	{
+		.membase	= io_p2v(LPC32XX_UART3_BASE),
+		.mapbase        = LPC32XX_UART3_BASE,
+		.irq		= IRQ_LPC32XX_UART_IIR3,
+		.uartclk	= LPC32XX_MAIN_OSC_FREQ,
+		.regshift	= 2,
+		.iotype		= UPIO_MEM32,
+		.flags		= UPF_BOOT_AUTOCONF | UPF_BUGGY_UART |
+					UPF_SKIP_TEST,
+	},
+#endif
+#ifdef CONFIG_ARCH_LPC32XX_UART4_SELECT
+	{
+		.membase	= io_p2v(LPC32XX_UART4_BASE),
+		.mapbase        = LPC32XX_UART4_BASE,
+		.irq		= IRQ_LPC32XX_UART_IIR4,
+		.uartclk	= LPC32XX_MAIN_OSC_FREQ,
+		.regshift	= 2,
+		.iotype		= UPIO_MEM32,
+		.flags		= UPF_BOOT_AUTOCONF | UPF_BUGGY_UART |
+					UPF_SKIP_TEST,
+	},
+#endif
+#ifdef CONFIG_ARCH_LPC32XX_UART6_SELECT
+	{
+		.membase	= io_p2v(LPC32XX_UART6_BASE),
+		.mapbase        = LPC32XX_UART6_BASE,
+		.irq		= IRQ_LPC32XX_UART_IIR6,
+		.uartclk	= LPC32XX_MAIN_OSC_FREQ,
+		.regshift	= 2,
+		.iotype		= UPIO_MEM32,
+		.flags		= UPF_BOOT_AUTOCONF | UPF_BUGGY_UART |
+					UPF_SKIP_TEST,
+	},
+#endif
+	{ },
+};
+
+struct uartinit {
+	char *uart_ck_name;
+	u32 ck_mode_mask;
+	void __iomem *pdiv_clk_reg;
+};
+
+static struct uartinit uartinit_data[] __initdata = {
+#ifdef CONFIG_ARCH_LPC32XX_UART5_SELECT
+	{
+		.uart_ck_name = "uart5_ck",
+		.ck_mode_mask =
+			LPC32XX_UART_CLKMODE_LOAD(LPC32XX_UART_CLKMODE_ON, 5),
+		.pdiv_clk_reg = LPC32XX_CLKPWR_UART5_CLK_CTRL,
+	},
+#endif
+#ifdef CONFIG_ARCH_LPC32XX_UART3_SELECT
+	{
+		.uart_ck_name = "uart3_ck",
+		.ck_mode_mask =
+			LPC32XX_UART_CLKMODE_LOAD(LPC32XX_UART_CLKMODE_ON, 3),
+		.pdiv_clk_reg = LPC32XX_CLKPWR_UART3_CLK_CTRL,
+	},
+#endif
+#ifdef CONFIG_ARCH_LPC32XX_UART4_SELECT
+	{
+		.uart_ck_name = "uart4_ck",
+		.ck_mode_mask =
+			LPC32XX_UART_CLKMODE_LOAD(LPC32XX_UART_CLKMODE_ON, 4),
+		.pdiv_clk_reg = LPC32XX_CLKPWR_UART4_CLK_CTRL,
+	},
+#endif
+#ifdef CONFIG_ARCH_LPC32XX_UART6_SELECT
+	{
+		.uart_ck_name = "uart6_ck",
+		.ck_mode_mask =
+			LPC32XX_UART_CLKMODE_LOAD(LPC32XX_UART_CLKMODE_ON, 6),
+		.pdiv_clk_reg = LPC32XX_CLKPWR_UART6_CLK_CTRL,
+	},
+#endif
+};
+
+static struct platform_device serial_std_platform_device = {
+	.name			= "serial8250",
+	.id			= 0,
+	.dev			= {
+		.platform_data	= serial_std_platform_data,
+	},
+};
+
+static struct platform_device *lpc32xx_serial_devs[] __initdata = {
+	&serial_std_platform_device,
+};
+
+void __init lpc32xx_serial_init(void)
+{
+	u32 tmp, clkmodes = 0;
+	struct clk *clk;
+	unsigned int puart;
+	int i, j;
+
+	/* UART clocks are off, let clock driver manage them */
+	__raw_writel(0, LPC32XX_CLKPWR_UART_CLK_CTRL);
+
+	for (i = 0; i < ARRAY_SIZE(uartinit_data); i++) {
+		clk = clk_get(NULL, uartinit_data[i].uart_ck_name);
+		if (!IS_ERR(clk)) {
+			clk_enable(clk);
+			serial_std_platform_data[i].uartclk =
+				clk_get_rate(clk);
+		}
+
+		/* Fall back on main osc rate if clock rate return fails */
+		if (serial_std_platform_data[i].uartclk == 0)
+			serial_std_platform_data[i].uartclk =
+				LPC32XX_MAIN_OSC_FREQ;
+
+		/* Setup UART clock modes for all UARTs, disable autoclock */
+		clkmodes |= uartinit_data[i].ck_mode_mask;
+
+		/* pre-UART clock divider set to 1 */
+		__raw_writel(0x0101, uartinit_data[i].pdiv_clk_reg);
+	}
+
+	/* This needs to be done after all UART clocks are setup */
+	__raw_writel(clkmodes, LPC32XX_UARTCTL_CLKMODE);
+	for (i = 0; i < ARRAY_SIZE(uartinit_data) - 1; i++) {
+		/* Force a flush of the RX FIFOs to work around a HW bug */
+		puart = serial_std_platform_data[i].mapbase;
+		__raw_writel(0xC1, LPC32XX_UART_IIR_FCR(puart));
+		__raw_writel(0x00, LPC32XX_UART_DLL_FIFO(puart));
+		j = LPC32XX_SUART_FIFO_SIZE;
+		while (j--)
+			tmp = __raw_readl(LPC32XX_UART_DLL_FIFO(puart));
+		__raw_writel(0, LPC32XX_UART_IIR_FCR(puart));
+	}
+
+	/* Disable UART5->USB transparent mode or USB won't work */
+	tmp = __raw_readl(LPC32XX_UARTCTL_CTRL);
+	tmp &= ~LPC32XX_UART_U5_ROUTE_TO_USB;
+	__raw_writel(tmp, LPC32XX_UARTCTL_CTRL);
+
+	platform_add_devices(lpc32xx_serial_devs,
+		ARRAY_SIZE(lpc32xx_serial_devs));
+}

+ 151 - 0
arch/arm/mach-lpc32xx/suspend.S

@@ -0,0 +1,151 @@
+/*
+ * arch/arm/mach-lpc32xx/suspend.S
+ *
+ * Original authors: Dmitry Chigirev, Vitaly Wool <source@mvista.com>
+ * Modified by Kevin Wells <kevin.wells@nxp.com>
+ *
+ * 2005 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+#include <mach/platform.h>
+#include <mach/hardware.h>
+
+/* Using named register defines makes the code easier to follow */
+#define WORK1_REG			r0
+#define WORK2_REG			r1
+#define SAVED_HCLK_DIV_REG		r2
+#define SAVED_HCLK_PLL_REG		r3
+#define SAVED_DRAM_CLKCTRL_REG		r4
+#define SAVED_PWR_CTRL_REG		r5
+#define CLKPWRBASE_REG			r6
+#define EMCBASE_REG			r7
+
+#define LPC32XX_EMC_STATUS_OFFS		0x04
+#define LPC32XX_EMC_STATUS_BUSY		0x1
+#define LPC32XX_EMC_STATUS_SELF_RFSH	0x4
+
+#define LPC32XX_CLKPWR_PWR_CTRL_OFFS	0x44
+#define LPC32XX_CLKPWR_HCLK_DIV_OFFS	0x40
+#define LPC32XX_CLKPWR_HCLKPLL_CTRL_OFFS 0x58
+
+#define CLKPWR_PCLK_DIV_MASK		0xFFFFFE7F
+
+	.text
+
+ENTRY(lpc32xx_sys_suspend)
+	@ Save a copy of the used registers in IRAM, r0 is corrupted
+	adr	r0, tmp_stack_end
+	stmfd	r0!, {r3 - r7, sp, lr}
+
+	@ Load a few common register addresses
+	adr	WORK1_REG, reg_bases
+	ldr	CLKPWRBASE_REG, [WORK1_REG, #0]
+	ldr	EMCBASE_REG, [WORK1_REG, #4]
+
+	ldr	SAVED_PWR_CTRL_REG, [CLKPWRBASE_REG,\
+		#LPC32XX_CLKPWR_PWR_CTRL_OFFS]
+	orr	WORK1_REG, SAVED_PWR_CTRL_REG, #LPC32XX_CLKPWR_SDRAM_SELF_RFSH
+
+	@ Wait for SDRAM busy status to go busy and then idle
+	@ This guarantees a small windows where DRAM isn't busy
+1:
+	ldr	WORK2_REG, [EMCBASE_REG, #LPC32XX_EMC_STATUS_OFFS]
+	and	WORK2_REG, WORK2_REG, #LPC32XX_EMC_STATUS_BUSY
+	cmp	WORK2_REG, #LPC32XX_EMC_STATUS_BUSY
+	bne	1b @ Branch while idle
+2:
+	ldr	WORK2_REG, [EMCBASE_REG, #LPC32XX_EMC_STATUS_OFFS]
+	and	WORK2_REG, WORK2_REG, #LPC32XX_EMC_STATUS_BUSY
+	cmp	WORK2_REG, #LPC32XX_EMC_STATUS_BUSY
+	beq	2b @ Branch until idle
+
+	@ Setup self-refresh with support for manual exit of
+	@ self-refresh mode
+	str	WORK1_REG, [CLKPWRBASE_REG, #LPC32XX_CLKPWR_PWR_CTRL_OFFS]
+	orr	WORK2_REG, WORK1_REG, #LPC32XX_CLKPWR_UPD_SDRAM_SELF_RFSH
+	str	WORK2_REG, [CLKPWRBASE_REG, #LPC32XX_CLKPWR_PWR_CTRL_OFFS]
+	str	WORK1_REG, [CLKPWRBASE_REG, #LPC32XX_CLKPWR_PWR_CTRL_OFFS]
+
+	@ Wait for self-refresh acknowledge, clocks to the DRAM device
+	@ will automatically stop on start of self-refresh
+3:
+	ldr	WORK2_REG, [EMCBASE_REG, #LPC32XX_EMC_STATUS_OFFS]
+	and	WORK2_REG, WORK2_REG, #LPC32XX_EMC_STATUS_SELF_RFSH
+	cmp	WORK2_REG, #LPC32XX_EMC_STATUS_SELF_RFSH
+	bne	3b @ Branch until self-refresh mode starts
+
+	@ Enter direct-run mode from run mode
+	bic	WORK1_REG, WORK1_REG, #LPC32XX_CLKPWR_SELECT_RUN_MODE
+	str	WORK1_REG, [CLKPWRBASE_REG, #LPC32XX_CLKPWR_PWR_CTRL_OFFS]
+
+	@ Safe disable of DRAM clock in EMC block, prevents DDR sync
+	@ issues on restart
+	ldr	SAVED_HCLK_DIV_REG, [CLKPWRBASE_REG,\
+		#LPC32XX_CLKPWR_HCLK_DIV_OFFS]
+	and	WORK2_REG, SAVED_HCLK_DIV_REG, #CLKPWR_PCLK_DIV_MASK
+	str	WORK2_REG, [CLKPWRBASE_REG, #LPC32XX_CLKPWR_HCLK_DIV_OFFS]
+
+	@ Save HCLK PLL state and disable HCLK PLL
+	ldr	SAVED_HCLK_PLL_REG, [CLKPWRBASE_REG,\
+		#LPC32XX_CLKPWR_HCLKPLL_CTRL_OFFS]
+	bic	WORK2_REG, SAVED_HCLK_PLL_REG, #LPC32XX_CLKPWR_HCLKPLL_POWER_UP
+	str	WORK2_REG, [CLKPWRBASE_REG, #LPC32XX_CLKPWR_HCLKPLL_CTRL_OFFS]
+
+	@ Enter stop mode until an enabled event occurs
+	orr	WORK1_REG, WORK1_REG, #LPC32XX_CLKPWR_STOP_MODE_CTRL
+	str	WORK1_REG, [CLKPWRBASE_REG, #LPC32XX_CLKPWR_PWR_CTRL_OFFS]
+	.rept 9
+	nop
+	.endr
+
+	@ Clear stop status
+	bic	WORK1_REG, WORK1_REG, #LPC32XX_CLKPWR_STOP_MODE_CTRL
+
+	@ Restore original HCLK PLL value and wait for PLL lock
+	str	SAVED_HCLK_PLL_REG, [CLKPWRBASE_REG,\
+		#LPC32XX_CLKPWR_HCLKPLL_CTRL_OFFS]
+4:
+	ldr	WORK2_REG, [CLKPWRBASE_REG, #LPC32XX_CLKPWR_HCLKPLL_CTRL_OFFS]
+	and	WORK2_REG, WORK2_REG, #LPC32XX_CLKPWR_HCLKPLL_PLL_STS
+	bne	4b
+
+	@ Re-enter run mode with self-refresh flag cleared, but no DRAM
+	@ update yet. DRAM is still in self-refresh
+	str	SAVED_PWR_CTRL_REG, [CLKPWRBASE_REG,\
+		#LPC32XX_CLKPWR_PWR_CTRL_OFFS]
+
+	@ Restore original DRAM clock mode to restore DRAM clocks
+	str	SAVED_HCLK_DIV_REG, [CLKPWRBASE_REG,\
+		#LPC32XX_CLKPWR_HCLK_DIV_OFFS]
+
+	@ Clear self-refresh mode
+	orr	WORK1_REG, SAVED_PWR_CTRL_REG,\
+		#LPC32XX_CLKPWR_UPD_SDRAM_SELF_RFSH
+	str	WORK1_REG, [CLKPWRBASE_REG, #LPC32XX_CLKPWR_PWR_CTRL_OFFS]
+	str	SAVED_PWR_CTRL_REG, [CLKPWRBASE_REG,\
+		#LPC32XX_CLKPWR_PWR_CTRL_OFFS]
+
+	@ Wait for EMC to clear self-refresh mode
+5:
+	ldr	WORK2_REG, [EMCBASE_REG, #LPC32XX_EMC_STATUS_OFFS]
+	and	WORK2_REG, WORK2_REG, #LPC32XX_EMC_STATUS_SELF_RFSH
+	bne	5b @ Branch until self-refresh has exited
+
+	@ restore regs and return
+	adr	r0, tmp_stack
+	ldmfd	r0!, {r3 - r7, sp, pc}
+
+reg_bases:
+	.long	IO_ADDRESS(LPC32XX_CLK_PM_BASE)
+	.long	IO_ADDRESS(LPC32XX_EMC_BASE)
+
+tmp_stack:
+	.long	0, 0, 0, 0, 0, 0, 0
+tmp_stack_end:
+
+ENTRY(lpc32xx_sys_suspend_sz)
+	.word	. - lpc32xx_sys_suspend

+ 182 - 0
arch/arm/mach-lpc32xx/timer.c

@@ -0,0 +1,182 @@
+/*
+ * arch/arm/mach-lpc32xx/timer.c
+ *
+ * Author: Kevin Wells <kevin.wells@nxp.com>
+ *
+ * Copyright (C) 2009 - 2010 NXP Semiconductors
+ * Copyright (C) 2009 Fontys University of Applied Sciences, Eindhoven
+ *                    Ed Schouten <e.schouten@fontys.nl>
+ *                    Laurens Timmermans <l.timmermans@fontys.nl>
+ *
+ * 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.
+ */
+
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/time.h>
+#include <linux/err.h>
+#include <linux/clockchips.h>
+
+#include <asm/mach/time.h>
+
+#include <mach/hardware.h>
+#include <mach/platform.h>
+#include "common.h"
+
+static cycle_t lpc32xx_clksrc_read(struct clocksource *cs)
+{
+	return (cycle_t)__raw_readl(LCP32XX_TIMER_TC(LPC32XX_TIMER1_BASE));
+}
+
+static struct clocksource lpc32xx_clksrc = {
+	.name	= "lpc32xx_clksrc",
+	.shift	= 24,
+	.rating	= 300,
+	.read	= lpc32xx_clksrc_read,
+	.mask	= CLOCKSOURCE_MASK(32),
+	.flags	= CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+static int lpc32xx_clkevt_next_event(unsigned long delta,
+    struct clock_event_device *dev)
+{
+	__raw_writel(LCP32XX_TIMER_CNTR_TCR_RESET,
+		LCP32XX_TIMER_TCR(LPC32XX_TIMER0_BASE));
+	__raw_writel(delta, LCP32XX_TIMER_PR(LPC32XX_TIMER0_BASE));
+	__raw_writel(LCP32XX_TIMER_CNTR_TCR_EN,
+		LCP32XX_TIMER_TCR(LPC32XX_TIMER0_BASE));
+
+	return 0;
+}
+
+static void lpc32xx_clkevt_mode(enum clock_event_mode mode,
+    struct clock_event_device *dev)
+{
+	switch (mode) {
+	case CLOCK_EVT_MODE_PERIODIC:
+		WARN_ON(1);
+		break;
+
+	case CLOCK_EVT_MODE_ONESHOT:
+	case CLOCK_EVT_MODE_SHUTDOWN:
+		/*
+		 * Disable the timer. When using oneshot, we must also
+		 * disable the timer to wait for the first call to
+		 * set_next_event().
+		 */
+		__raw_writel(0, LCP32XX_TIMER_TCR(LPC32XX_TIMER0_BASE));
+		break;
+
+	case CLOCK_EVT_MODE_UNUSED:
+	case CLOCK_EVT_MODE_RESUME:
+		break;
+	}
+}
+
+static struct clock_event_device lpc32xx_clkevt = {
+	.name		= "lpc32xx_clkevt",
+	.features	= CLOCK_EVT_FEAT_ONESHOT,
+	.shift		= 32,
+	.rating		= 300,
+	.set_next_event	= lpc32xx_clkevt_next_event,
+	.set_mode	= lpc32xx_clkevt_mode,
+};
+
+static irqreturn_t lpc32xx_timer_interrupt(int irq, void *dev_id)
+{
+	struct clock_event_device *evt = &lpc32xx_clkevt;
+
+	/* Clear match */
+	__raw_writel(LCP32XX_TIMER_CNTR_MTCH_BIT(0),
+		LCP32XX_TIMER_IR(LPC32XX_TIMER0_BASE));
+
+	evt->event_handler(evt);
+
+	return IRQ_HANDLED;
+}
+
+static struct irqaction lpc32xx_timer_irq = {
+	.name		= "LPC32XX Timer Tick",
+	.flags		= IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
+	.handler	= lpc32xx_timer_interrupt,
+};
+
+/*
+ * The clock management driver isn't initialized at this point, so the
+ * clocks need to be enabled here manually and then tagged as used in
+ * the clock driver initialization
+ */
+static void __init lpc32xx_timer_init(void)
+{
+	u32 clkrate, pllreg;
+
+	/* Enable timer clock */
+	__raw_writel(LPC32XX_CLKPWR_TMRPWMCLK_TIMER0_EN |
+		LPC32XX_CLKPWR_TMRPWMCLK_TIMER1_EN,
+		LPC32XX_CLKPWR_TIMERS_PWMS_CLK_CTRL_1);
+
+	/*
+	 * The clock driver isn't initialized at this point. So determine if
+	 * the SYSCLK is driven from the PLL397 or main oscillator and then use
+	 * it to compute the PLL frequency and the PCLK divider to get the base
+	 * timer rates. This rate is needed to compute the tick rate.
+	 */
+	if (clk_is_sysclk_mainosc() != 0)
+		clkrate = LPC32XX_MAIN_OSC_FREQ;
+	else
+		clkrate = 397 * LPC32XX_CLOCK_OSC_FREQ;
+
+	/* Get ARM HCLKPLL register and convert it into a frequency */
+	pllreg = __raw_readl(LPC32XX_CLKPWR_HCLKPLL_CTRL) & 0x1FFFF;
+	clkrate = clk_get_pllrate_from_reg(clkrate, pllreg);
+
+	/* Get PCLK divider and divide ARM PLL clock by it to get timer rate */
+	clkrate = clkrate / clk_get_pclk_div();
+
+	/* Initial timer setup */
+	__raw_writel(0, LCP32XX_TIMER_TCR(LPC32XX_TIMER0_BASE));
+	__raw_writel(LCP32XX_TIMER_CNTR_MTCH_BIT(0),
+		LCP32XX_TIMER_IR(LPC32XX_TIMER0_BASE));
+	__raw_writel(1, LCP32XX_TIMER_MR0(LPC32XX_TIMER0_BASE));
+	__raw_writel(LCP32XX_TIMER_CNTR_MCR_MTCH(0) |
+		LCP32XX_TIMER_CNTR_MCR_STOP(0) |
+		LCP32XX_TIMER_CNTR_MCR_RESET(0),
+		LCP32XX_TIMER_MCR(LPC32XX_TIMER0_BASE));
+
+	/* Setup tick interrupt */
+	setup_irq(IRQ_LPC32XX_TIMER0, &lpc32xx_timer_irq);
+
+	/* Setup the clockevent structure. */
+	lpc32xx_clkevt.mult = div_sc(clkrate, NSEC_PER_SEC,
+		lpc32xx_clkevt.shift);
+	lpc32xx_clkevt.max_delta_ns = clockevent_delta2ns(-1,
+		&lpc32xx_clkevt);
+	lpc32xx_clkevt.min_delta_ns = clockevent_delta2ns(1,
+		&lpc32xx_clkevt) + 1;
+	lpc32xx_clkevt.cpumask = cpumask_of(0);
+	clockevents_register_device(&lpc32xx_clkevt);
+
+	/* Use timer1 as clock source. */
+	__raw_writel(LCP32XX_TIMER_CNTR_TCR_RESET,
+		LCP32XX_TIMER_TCR(LPC32XX_TIMER1_BASE));
+	__raw_writel(0, LCP32XX_TIMER_PR(LPC32XX_TIMER1_BASE));
+	__raw_writel(0, LCP32XX_TIMER_MCR(LPC32XX_TIMER1_BASE));
+	__raw_writel(LCP32XX_TIMER_CNTR_TCR_EN,
+		LCP32XX_TIMER_TCR(LPC32XX_TIMER1_BASE));
+	lpc32xx_clksrc.mult = clocksource_hz2mult(clkrate,
+		lpc32xx_clksrc.shift);
+	clocksource_register(&lpc32xx_clksrc);
+}
+
+struct sys_timer lpc32xx_timer = {
+	.init		= &lpc32xx_timer_init,
+};
+