Initial 2.6.34 kernel release for the LPC32xx linux-2.6.34_lpc32x0_v1.00
authorKevin Wells <wellsk40@gmail.com>
Mon, 12 Jul 2010 15:14:55 +0000 (08:14 -0700)
committerKevin Wells <wellsk40@gmail.com>
Mon, 12 Jul 2010 15:14:55 +0000 (08:14 -0700)
81 files changed:
arch/arm/Kconfig
arch/arm/Makefile
arch/arm/mach-lpc32xx/Kconfig [new file with mode: 0644]
arch/arm/mach-lpc32xx/Makefile [new file with mode: 0644]
arch/arm/mach-lpc32xx/Makefile.boot [new file with mode: 0644]
arch/arm/mach-lpc32xx/clock.c [new file with mode: 0644]
arch/arm/mach-lpc32xx/clock.h [new file with mode: 0644]
arch/arm/mach-lpc32xx/common.c [new file with mode: 0644]
arch/arm/mach-lpc32xx/common.h [new file with mode: 0644]
arch/arm/mach-lpc32xx/dma.c [new file with mode: 0644]
arch/arm/mach-lpc32xx/ea3250.c [new file with mode: 0644]
arch/arm/mach-lpc32xx/gpiolib.c [new file with mode: 0644]
arch/arm/mach-lpc32xx/include/mach/board.h [new file with mode: 0644]
arch/arm/mach-lpc32xx/include/mach/clkdev.h [new file with mode: 0644]
arch/arm/mach-lpc32xx/include/mach/debug-macro.S [new file with mode: 0644]
arch/arm/mach-lpc32xx/include/mach/dma.h [new file with mode: 0644]
arch/arm/mach-lpc32xx/include/mach/dmac.h [new file with mode: 0644]
arch/arm/mach-lpc32xx/include/mach/entry-macro.S [new file with mode: 0644]
arch/arm/mach-lpc32xx/include/mach/gpio.h [new file with mode: 0644]
arch/arm/mach-lpc32xx/include/mach/hardware.h [new file with mode: 0644]
arch/arm/mach-lpc32xx/include/mach/i2c.h [new file with mode: 0644]
arch/arm/mach-lpc32xx/include/mach/i2s.h [new file with mode: 0644]
arch/arm/mach-lpc32xx/include/mach/io.h [new file with mode: 0644]
arch/arm/mach-lpc32xx/include/mach/irqs.h [new file with mode: 0644]
arch/arm/mach-lpc32xx/include/mach/memory.h [new file with mode: 0644]
arch/arm/mach-lpc32xx/include/mach/platform.h [new file with mode: 0644]
arch/arm/mach-lpc32xx/include/mach/sdcard.h [new file with mode: 0644]
arch/arm/mach-lpc32xx/include/mach/slcnand.h [new file with mode: 0644]
arch/arm/mach-lpc32xx/include/mach/system.h [new file with mode: 0644]
arch/arm/mach-lpc32xx/include/mach/timex.h [new file with mode: 0644]
arch/arm/mach-lpc32xx/include/mach/uncompress.h [new file with mode: 0644]
arch/arm/mach-lpc32xx/include/mach/usbd.h [new file with mode: 0644]
arch/arm/mach-lpc32xx/include/mach/vmalloc.h [new file with mode: 0644]
arch/arm/mach-lpc32xx/irq.c [new file with mode: 0644]
arch/arm/mach-lpc32xx/phy3250.c [new file with mode: 0644]
arch/arm/mach-lpc32xx/pm.c [new file with mode: 0644]
arch/arm/mach-lpc32xx/serial.c [new file with mode: 0644]
arch/arm/mach-lpc32xx/suspend.S [new file with mode: 0644]
arch/arm/mach-lpc32xx/timer.c [new file with mode: 0644]
drivers/i2c/busses/Kconfig
drivers/input/keyboard/Kconfig
drivers/input/keyboard/Makefile
drivers/input/keyboard/lpc32xx_keys.c [new file with mode: 0644]
drivers/input/touchscreen/Kconfig
drivers/input/touchscreen/Makefile
drivers/input/touchscreen/lpc32xx_ts.c [new file with mode: 0644]
drivers/mmc/host/mmci.c
drivers/mtd/nand/Kconfig
drivers/mtd/nand/Makefile
drivers/mtd/nand/lpc32xx_nand.c [new file with mode: 0644]
drivers/net/Kconfig
drivers/net/Makefile
drivers/net/lpc_eth.c [new file with mode: 0644]
drivers/net/lpc_eth.h [new file with mode: 0644]
drivers/rtc/Kconfig
drivers/rtc/Makefile
drivers/rtc/rtc-lpc32xx.c [new file with mode: 0644]
drivers/serial/8250.c
drivers/serial/Kconfig
drivers/serial/Makefile
drivers/serial/lpc32xx_hs.c [new file with mode: 0644]
drivers/usb/gadget/Kconfig
drivers/usb/gadget/Makefile
drivers/usb/gadget/gadget_chips.h
drivers/usb/gadget/lpc32xx_udc.c [new file with mode: 0644]
drivers/usb/gadget/lpc32xx_udc.h [new file with mode: 0644]
drivers/usb/host/ohci-hcd.c
drivers/usb/host/ohci-pnx4008.c
drivers/watchdog/Kconfig
sound/soc/Kconfig
sound/soc/Makefile
sound/soc/codecs/uda1380.c
sound/soc/codecs/uda1380.h
sound/soc/lpc3xxx/Kconfig [new file with mode: 0644]
sound/soc/lpc3xxx/Makefile [new file with mode: 0644]
sound/soc/lpc3xxx/lpc3xxx-i2s.c [new file with mode: 0644]
sound/soc/lpc3xxx/lpc3xxx-i2s.h [new file with mode: 0644]
sound/soc/lpc3xxx/lpc3xxx-pcm.c [new file with mode: 0644]
sound/soc/lpc3xxx/lpc3xxx-pcm.h [new file with mode: 0644]
sound/soc/lpc3xxx/lpc3xxx-uda1380.c [new file with mode: 0644]
sound/soc/soc-core.c

index 92622eb..a6e6b08 100644 (file)
@@ -484,6 +484,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
@@ -851,6 +864,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"
index ed820e7..a098692 100644 (file)
@@ -139,6 +139,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
diff --git a/arch/arm/mach-lpc32xx/Kconfig b/arch/arm/mach-lpc32xx/Kconfig
new file mode 100644 (file)
index 0000000..898f953
--- /dev/null
@@ -0,0 +1,103 @@
+if ARCH_LPC32XX
+
+choice
+    prompt "LPC32XX SoC based board implementations"
+    default MACH_PHY3250
+    help
+        This menu selects the LPC3250 board to support for this build
+
+    config MACH_PHY3250
+        bool "Phytec 3250 development board"
+        help
+            Support for the Phytec 3250 development board
+
+    config MACH_EA3250
+        bool "Embedded Artists LPC3250 Developer's Kit"
+        help
+            Support for the Embedded Artists LPC3250 Developer's Kit
+
+endchoice
+
+menu "Embedded Artists Display Selection"
+       depends on MACH_EA3250
+
+config EA3250_QVGA_3_2_LCD
+       bool "3.2 inch QVGA LCD display (RGB565)"
+       help
+         Use 3.2 inch QVGA LCD display
+
+config EA3250_QVGA_2_8_OLED
+       bool "2.8 inch QVGA OLED display (RGB565)"
+       help
+         Use 2.8 inch QVGA OLED display
+
+endmenu
+
+menu "Standard UARTS"
+
+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
+
+menu "High speed UARTS"
+
+config ARCH_LPC32XX_HSUART1_SELECT
+        bool "Add support for high speed UART1"
+        help
+                Enables high speed UART1 as a TTYSx device
+
+config ARCH_LPC32XX_HSUART2_SELECT
+        bool "Add support for high speed UART2"
+        help
+                Enables high speed UART2 as a TTYSx device
+
+config ARCH_LPC32XX_HSUART7_SELECT
+        bool "Add support for high speed UART7"
+        help
+                Enables high speed UART7 as a TTYSx device
+
+endmenu
+
+menu "LPC32XX chip components"
+
+config ARCH_LPC32XX_IRAM_FOR_NET
+        bool "Use IRAM for network buffers"
+        help
+          If the total combined required buffer sizes is larger than the
+          size of IRAM, then SDRAM will be used instead.
+
+config ARCH_LPC32XX_MII_SUPPORT
+        bool "Check to enable MII support or leave disabled for RMII support"
+        default FALSE
+        help
+          Say Y here to enable MII support, or N to RMII support. Regardless of
+          which support is selected, the ethernet interface driver needs to be
+          selected in the device driver networking section.
+
+endmenu
+
+endif
+
diff --git a/arch/arm/mach-lpc32xx/Makefile b/arch/arm/mach-lpc32xx/Makefile
new file mode 100644 (file)
index 0000000..cc4c3af
--- /dev/null
@@ -0,0 +1,9 @@
+#
+# Makefile for the linux kernel.
+#
+
+obj-y  := timer.o irq.o common.o serial.o clock.o
+obj-y  +=  dma.o gpiolib.o pm.o suspend.o
+obj-$(CONFIG_MACH_PHY3250)     += phy3250.o
+obj-$(CONFIG_MACH_EA3250)      += ea3250.o
+
diff --git a/arch/arm/mach-lpc32xx/Makefile.boot b/arch/arm/mach-lpc32xx/Makefile.boot
new file mode 100644 (file)
index 0000000..b796b41
--- /dev/null
@@ -0,0 +1,4 @@
+   zreladdr-y  := 0x80008000
+params_phys-y  := 0x80000100
+initrd_phys-y  := 0x82000000
+
diff --git a/arch/arm/mach-lpc32xx/clock.c b/arch/arm/mach-lpc32xx/clock.c
new file mode 100644 (file)
index 0000000..182d2a6
--- /dev/null
@@ -0,0 +1,1172 @@
+/*
+ * 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/delay.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 int usb_pll_enable, usb_pll_valid;
+
+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 = jiffies + 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 = jiffies + 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 = 0;
+       unsigned long timeout = jiffies + msecs_to_jiffies(20);
+
+       reg = __raw_readl(LPC32XX_CLKPWR_USB_CTRL);
+
+       __raw_writel(reg & ~(LPC32XX_CLKPWR_USBCTRL_CLK_EN2 |
+               LPC32XX_CLKPWR_USBCTRL_PLL_PWRUP),
+               LPC32XX_CLKPWR_USB_CTRL);
+       __raw_writel(reg & ~LPC32XX_CLKPWR_USBCTRL_CLK_EN1,
+               LPC32XX_CLKPWR_USB_CTRL);
+
+       if (enable && usb_pll_valid && usb_pll_enable) {
+               ret = -ENODEV;
+               /*
+                * If the PLL rate has been previously set, then the rate
+                * in the PLL register is valid and can be enabled here.
+                * Otherwise, it needs to be enabled as part of setrate.
+                */
+
+               /*
+                * Gate clock into PLL
+                */
+               reg |= LPC32XX_CLKPWR_USBCTRL_CLK_EN1;
+               __raw_writel(reg, LPC32XX_CLKPWR_USB_CTRL);
+
+               /*
+                * Enable PLL
+                */
+               reg |= LPC32XX_CLKPWR_USBCTRL_PLL_PWRUP;
+               __raw_writel(reg, LPC32XX_CLKPWR_USB_CTRL);
+
+               /*
+                * Wait for PLL to lock
+                */
+               while ((timeout > jiffies) && (ret == -ENODEV)) {
+                       reg = __raw_readl(LPC32XX_CLKPWR_USB_CTRL);
+                       if (reg & LPC32XX_CLKPWR_USBCTRL_PLL_STS)
+                               ret = 0;
+                       else
+                               udelay(10);
+               }
+
+               /*
+                * Gate clock from PLL if PLL is locked
+                */
+               if (ret == 0)
+                       __raw_writel(reg | LPC32XX_CLKPWR_USBCTRL_CLK_EN2,
+                               LPC32XX_CLKPWR_USB_CTRL);
+               else
+                       __raw_writel(reg & ~(LPC32XX_CLKPWR_USBCTRL_CLK_EN1 |
+                               LPC32XX_CLKPWR_USBCTRL_PLL_PWRUP),
+                               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->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 0;
+
+       return clk_check_pll_setup(clkin, &pllsetup);
+}
+
+static int local_usbpll_set_rate(struct clk *clk, unsigned long rate)
+{
+       int ret = -ENODEV;
+       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->get_rate(clk->parent);
+       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;
+
+       usb_pll_valid = 1;
+       usb_pll_enable = 1;
+
+       /*
+        * Disable PLL clocks during PLL change
+        */
+       local_usbpll_enable(clk, 0);
+       pllsetup.analog_on = 0;
+       local_clk_usbpll_setup(&pllsetup);
+
+       /*
+        * Start USB PLL and check PLL status
+        */
+       usb_pll_enable = 1;
+       ret = local_usbpll_enable(clk, 1);
+       if (ret >= 0)
+               clk->rate = clk_check_pll_setup(clkin, &pllsetup);
+
+       return ret;
+}
+
+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(NULL, "i2s0_ck", clk_i2s0)
+       _REGISTER_CLOCK(NULL, "i2s1_ck", clk_i2s1)
+       _REGISTER_CLOCK("lpc32xx-ts", NULL, clk_tsc)
+       _REGISTER_CLOCK("dev:mmc0", NULL, 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);
+
diff --git a/arch/arm/mach-lpc32xx/clock.h b/arch/arm/mach-lpc32xx/clock.h
new file mode 100644 (file)
index 0000000..c0a8434
--- /dev/null
@@ -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
diff --git a/arch/arm/mach-lpc32xx/common.c b/arch/arm/mach-lpc32xx/common.c
new file mode 100644 (file)
index 0000000..c0ebb97
--- /dev/null
@@ -0,0 +1,397 @@
+/*
+ * 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 <mach/board.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,
+};
+
+/*
+ * Real Time Clock
+ */
+static struct resource rtc_resources[] = {
+        [0] = {
+                .start = LPC32XX_RTC_BASE,
+                .end = LPC32XX_RTC_BASE + SZ_4K - 1,
+                .flags = IORESOURCE_MEM,
+        },
+        [1] = {
+                .start = IRQ_LPC32XX_RTC,
+                .flags = IORESOURCE_IRQ,
+        },
+};
+
+struct platform_device lpc32xx_rtc_device = {
+        .name =  "rtc-lpc32xx",
+        .id = -1,
+        .num_resources = ARRAY_SIZE(rtc_resources),
+        .resource = rtc_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,
+       },
+};
+
+/*
+ * Touch Screen support
+ */
+static struct resource tsc_resources[] = {
+       [0] = {
+               .start = LPC32XX_ADC_BASE,
+               .end = LPC32XX_ADC_BASE + SZ_4K - 1,
+               .flags = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start = IRQ_LPC32XX_TS_IRQ,
+               .flags = IORESOURCE_IRQ,
+       },
+};
+struct platform_device lpc32xx_tsc_device = {
+       .name =  "lpc32xx-ts",
+       .id = -1,
+       .num_resources = ARRAY_SIZE(tsc_resources),
+       .resource = tsc_resources,
+};
+
+#if defined (CONFIG_USB_OHCI_HCD)
+/* The dmamask must be set for OHCI to work */
+static u64 ohci_dmamask = ~(u32) 0;
+static struct resource ohci_resources[] = {
+        {
+                .start = IO_ADDRESS(LPC32XX_USB_BASE),
+                .end = IO_ADDRESS(LPC32XX_USB_BASE + 0x100),
+                .flags = IORESOURCE_MEM,
+        }, {
+                .start = IRQ_LPC32XX_USB_HOST,
+                .flags = IORESOURCE_IRQ,
+        },
+};
+struct platform_device lpc32xx_ohci_device = {
+        .name = "usb-ohci",
+        .id = -1,
+        .dev = {
+                .dma_mask = &ohci_dmamask,
+                .coherent_dma_mask = 0xFFFFFFFF,
+                },
+        .num_resources = ARRAY_SIZE(ohci_resources),
+        .resource = ohci_resources,
+};
+#endif
+
+
+#if defined(CONFIG_USB_GADGET_LPC32XX)
+static void phy3250_usbd_conn_chg(int conn) {
+    /* Do nothing, it might be nice to enable an LED
+ *        based on conn state being !0 */
+}
+
+static void phy3250_usbd_susp_chg(int susp) {
+    /* Device suspend if susp != 0 */
+}
+
+static void phy3250_rmwkup_chg(int remote_wakup_enable) {
+    /* Enable or disable USB remote wakeup */
+}
+
+struct lpc32xx_usbd_cfg lpc32xx_usbddata = {
+    .vbus_drv_pol = 1,
+    .conn_chgb = &phy3250_usbd_conn_chg,
+    .susp_chgb = &phy3250_usbd_susp_chg,
+    .rmwk_chgb = &phy3250_rmwkup_chg,
+};
+
+/* The dmamask must be set for OHCI to work, align to 128 bytes */
+static u64 usbd_dmamask = ~(u32) 0x7F;
+static struct resource usbd_resources[] = {
+        {
+                .start = LPC32XX_USB_BASE,
+                .end = LPC32XX_USB_BASE + 0x100,
+                .flags = IORESOURCE_MEM,
+        }, {
+                .start = IRQ_LPC32XX_USB_DEV_LP,
+                .flags = IORESOURCE_IRQ,
+        }, {
+                .start = IRQ_LPC32XX_USB_DEV_HP,
+                .flags = IORESOURCE_IRQ,
+        }, {
+                .start = IRQ_LPC32XX_USB_DEV_DMA,
+                .flags = IORESOURCE_IRQ,
+        }, {
+                .start = IRQ_LPC32XX_USB_OTG_ATX,
+                .flags = IORESOURCE_IRQ,
+        },
+};
+
+struct platform_device lpc32xx_usbd_device = {
+        .name = "lpc32xx_udc",
+        .id = -1,
+        .dev = {
+                .dma_mask = &usbd_dmamask,
+                .coherent_dma_mask = 0xFFFFFFFF,
+                .platform_data  = &lpc32xx_usbddata,
+                },
+        .num_resources = ARRAY_SIZE(usbd_resources),
+        .resource = usbd_resources,
+};
+#endif
+
+/*
+ * 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));
+}
diff --git a/arch/arm/mach-lpc32xx/common.h b/arch/arm/mach-lpc32xx/common.h
new file mode 100644 (file)
index 0000000..5802935
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * 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;
+extern struct platform_device lpc32xx_tsc_device;
+extern struct platform_device lpc32xx_rtc_device;
+extern struct platform_device lpc32xx_ohci_device;
+extern struct platform_device lpc32xx_usbd_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
diff --git a/arch/arm/mach-lpc32xx/dma.c b/arch/arm/mach-lpc32xx/dma.c
new file mode 100644 (file)
index 0000000..926fe26
--- /dev/null
@@ -0,0 +1,661 @@
+/*
+ *  linux/arch/arm/mach-lpc32xx/ma-lpc32xx.c
+ *
+ *  Copyright (C) 2008 NXP Semiconductors
+ *  (Based on parts of the PNX4008 DMA driver)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/dma-mapping.h>
+#include <linux/clk.h>
+
+#include <asm/system.h>
+#include <mach/hardware.h>
+#include <mach/platform.h>
+#include <asm/dma-mapping.h>
+#include <asm/io.h>
+#include <mach/dma.h>
+#include <mach/dmac.h>
+
+#define DMAIOBASE io_p2v(LPC32XX_DMA_BASE)
+#define VALID_CHANNEL(c) (((c) >= 0) && ((c) < MAX_DMA_CHANNELS))
+
+static DEFINE_SPINLOCK(dma_lock);
+
+struct dma_linked_list {
+       u32 src;
+       u32 dest;
+       u32 next_lli;
+       u32 ctrl;
+};
+
+/* For DMA linked list operation, a linked list of DMA descriptors
+   is maintained along with some data to manage the list in software. */
+struct dma_list_ctrl {
+       struct dma_linked_list dmall; /* DMA list descriptor */
+       struct dma_list_ctrl *next_list_addr;   /* Virtual address to next list entry */
+        struct dma_list_ctrl *prev_list_addr;   /* Virtual address to previous list entry */
+       u32 next_list_phy;    /* Physical address to next list entry */
+        u32 prev_list_phy;    /* Physical address to previous list entry */
+};
+
+/* Each DMA channel has one of these structures */
+struct dma_channel {
+       char *name;
+       void (*irq_handler) (int, int, void *);
+       void *data;
+       struct dma_config *dmacfg;
+       u32 control;
+       u32 config;
+       u32 config_int_mask;
+
+       int list_entries; /* Number of list entries */
+       u32 list_size; /* Total size of allocated list in bytes */
+       u32 list_vstart; /* Allocated (virtual) address of list */
+       u32 list_pstart; /* Allocated (physical) address of list */
+       int free_entries; /* Number of free descriptors */
+       struct dma_list_ctrl *list_head, *list_tail;
+};
+
+struct dma_control {
+       struct clk *clk;
+       int num_clks;
+       struct dma_channel dma_channels[MAX_DMA_CHANNELS];
+};
+static struct dma_control dma_ctrl;
+
+static inline void __dma_regs_lock(void)
+{
+       spin_lock_irq(&dma_lock);
+}
+
+static inline void __dma_regs_unlock(void)
+{
+       spin_unlock_irq(&dma_lock);
+}
+
+static inline void __dma_enable(int ch) {
+       u32 ch_cfg = __raw_readl(DMACH_CONFIG_CH(DMAIOBASE, ch));
+       ch_cfg |= DMAC_CHAN_ENABLE;
+       __raw_writel(ch_cfg, DMACH_CONFIG_CH(DMAIOBASE, ch));
+}
+
+static inline void __dma_disable(int ch) {
+       u32 ch_cfg = __raw_readl(DMACH_CONFIG_CH(DMAIOBASE, ch));
+       ch_cfg &= ~DMAC_CHAN_ENABLE;
+       __raw_writel(ch_cfg, DMACH_CONFIG_CH(DMAIOBASE, ch));
+}
+
+static void dma_clocks_up(void)
+{
+       /* Enable DMA clock if needed */
+       if (dma_ctrl.num_clks == 0)
+       {
+               clk_enable(dma_ctrl.clk);
+               __raw_writel(DMAC_CTRL_ENABLE, DMA_CONFIG(DMAIOBASE));
+       }
+
+       dma_ctrl.num_clks++;
+}
+
+static void dma_clocks_down(void)
+{
+       dma_ctrl.num_clks--;
+
+       /* Disable DMA clock if needed */
+       if (dma_ctrl.num_clks == 0)
+       {
+               __raw_writel(0, DMA_CONFIG(DMAIOBASE));
+               clk_disable(dma_ctrl.clk);
+       }
+}
+
+static int lpc32xx_ch_setup(struct dma_config *dmachcfg)
+{
+       u32 tmpctrl, tmpcfg, tmp;
+       int ch = dmachcfg->ch;
+
+       /* Channel control setup */
+       tmpctrl = 0;
+       switch (dmachcfg->src_size)
+       {
+               case 1:
+                       tmpctrl |= DMAC_CHAN_SRC_WIDTH_8;
+                       break;
+
+               case 2:
+                       tmpctrl |= DMAC_CHAN_SRC_WIDTH_16;
+                       break;
+
+               case 4:
+                       tmpctrl |= DMAC_CHAN_SRC_WIDTH_32;
+                       break;
+
+               default:
+                       return -EINVAL;
+       }
+       switch (dmachcfg->dst_size)
+       {
+               case 1:
+                       tmpctrl |= DMAC_CHAN_DEST_WIDTH_8;
+                       break;
+
+               case 2:
+                       tmpctrl |= DMAC_CHAN_DEST_WIDTH_16;
+                       break;
+
+               case 4:
+                       tmpctrl |= DMAC_CHAN_DEST_WIDTH_32;
+                       break;
+
+               default:
+                       return -EINVAL;
+       }
+       if (dmachcfg->src_inc != 0)
+       {
+               tmpctrl |= DMAC_CHAN_SRC_AUTOINC;
+       }
+       if (dmachcfg->dst_inc != 0)
+       {
+               tmpctrl |= DMAC_CHAN_DEST_AUTOINC;
+       }
+       if (dmachcfg->src_ahb1 != 0)
+       {
+               tmpctrl |= DMAC_CHAN_SRC_AHB1;
+       }
+       if (dmachcfg->dst_ahb1 != 0)
+       {
+               tmpctrl |= DMAC_CHAN_DEST_AHB1;
+       }
+       if (dmachcfg->tc_inten != 0)
+       {
+               tmpctrl |= DMAC_CHAN_INT_TC_EN;
+       }
+       tmpctrl |= dmachcfg->src_bsize | dmachcfg->dst_bsize;
+       dma_ctrl.dma_channels[ch].control = tmpctrl;
+
+       /* Channel config setup */
+       tmpcfg = dmachcfg->src_prph | dmachcfg->dst_prph |
+               dmachcfg->flowctrl;
+       dma_ctrl.dma_channels[ch].config = tmpcfg;
+
+       dma_ctrl.dma_channels[ch].config_int_mask = 0;
+       if (dmachcfg->err_inten != 0)
+       {
+               dma_ctrl.dma_channels[ch].config_int_mask |=
+                       DMAC_CHAN_IE;
+       }
+       if (dmachcfg->tc_inten != 0)
+       {
+               dma_ctrl.dma_channels[ch].config_int_mask |=
+                       DMAC_CHAN_ITC;
+       }
+
+       tmp = __raw_readl(DMACH_CONFIG_CH(DMAIOBASE, ch));
+       tmp &= ~DMAC_CHAN_ENABLE;
+       __raw_writel(tmp, DMACH_CONFIG_CH(DMAIOBASE, ch));
+
+       /* Clear interrupts for channel */
+       __raw_writel((1 << ch), DMA_INT_TC_CLEAR(DMAIOBASE));
+       __raw_writel((1 << ch), DMA_INT_ERR_CLEAR(DMAIOBASE));
+
+       /* Write control and config words */
+       __raw_writel(tmpctrl, DMACH_CONTROL(DMAIOBASE, ch));
+       __raw_writel(tmpcfg, DMACH_CONFIG_CH(DMAIOBASE, ch));
+
+       return 0;
+}
+
+int lpc32xx_dma_ch_enable(int ch)
+{
+       if (!VALID_CHANNEL(ch) || !dma_ctrl.dma_channels[ch].name)
+               return -EINVAL;
+
+       __dma_regs_lock();
+       __dma_enable(ch);
+       __dma_regs_unlock();
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(lpc32xx_dma_ch_enable);
+
+int lpc32xx_dma_ch_disable(int ch)
+{
+       if (!VALID_CHANNEL(ch) || !dma_ctrl.dma_channels[ch].name)
+               return -EINVAL;
+
+       __dma_regs_lock();
+       __dma_disable(ch);
+       __dma_regs_unlock();
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(lpc32xx_dma_ch_disable);
+
+int lpc32xx_dma_ch_get(struct dma_config *dmachcfg, char *name,
+               void *irq_handler, void *data) {
+       int ret;
+
+       if (!VALID_CHANNEL(dmachcfg->ch))
+               return -EINVAL;
+
+       /* If the channel is already enabled, return */
+       if (dma_ctrl.dma_channels[dmachcfg->ch].name != NULL)
+               return -ENODEV;
+
+       /* Save channel data */
+       dma_ctrl.dma_channels[dmachcfg->ch].dmacfg = dmachcfg;
+       dma_ctrl.dma_channels[dmachcfg->ch].name = name;
+       dma_ctrl.dma_channels[dmachcfg->ch].irq_handler = irq_handler;
+       dma_ctrl.dma_channels[dmachcfg->ch].data = data;
+
+       /* Setup channel */
+       __dma_regs_lock();
+       dma_clocks_up();
+       ret = lpc32xx_ch_setup(dmachcfg);
+       __dma_regs_unlock();
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(lpc32xx_dma_ch_get);
+
+int lpc32xx_dma_ch_put(int ch)
+{
+       u32 tmp;
+
+       if (!VALID_CHANNEL(ch))
+               return -EINVAL;
+
+       /* If the channel is already disabled, return */
+       if (dma_ctrl.dma_channels[ch].name == NULL)
+               return -EINVAL;
+
+       tmp = __raw_readl(DMACH_CONFIG_CH(DMAIOBASE, ch));
+       tmp &= ~DMAC_CHAN_ENABLE;
+       __raw_writel(tmp, DMACH_CONFIG_CH(DMAIOBASE, ch));
+
+       __dma_regs_lock();
+       lpc32xx_dma_ch_disable(ch);
+       dma_clocks_down();
+       __dma_regs_unlock();
+
+       dma_ctrl.dma_channels[ch].name = NULL;
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(lpc32xx_dma_ch_put);
+
+int lpc32xx_dma_ch_pause_unpause(int ch, int pause) {
+       u32 tmp;
+
+       if (!VALID_CHANNEL(ch))
+               return -EINVAL;
+
+       /* If the channel is already disabled, return */
+       if (dma_ctrl.dma_channels[ch].name == NULL)
+               return -EINVAL;
+
+       tmp = __raw_readl(DMACH_CONFIG_CH(DMAIOBASE, ch));
+       if (pause) {
+               tmp |= DMAC_CHAN_HALT;
+       }
+       else {
+               tmp &= ~DMAC_CHAN_HALT;
+       }
+       __raw_writel(tmp, DMACH_CONFIG_CH(DMAIOBASE, ch));
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(lpc32xx_dma_ch_pause_unpause);
+
+int lpc32xx_dma_start_pflow_xfer(int ch,
+                               void *src,
+                               void *dst,
+                               int enable)
+{
+       u32 tmp;
+
+       if ((!VALID_CHANNEL(ch)) || (dma_ctrl.dma_channels[ch].name == NULL))
+               return -EINVAL;
+
+       /* When starting a DMA transfer where the peripheral is the flow
+          controller, DMA must be previously disabled */
+       tmp = __raw_readl(DMACH_CONFIG_CH(DMAIOBASE, ch));
+       if (tmp & DMAC_CHAN_ENABLE)
+               return -EBUSY;
+
+       __dma_regs_lock();
+       __raw_writel((u32) src, DMACH_SRC_ADDR(DMAIOBASE, ch));
+       __raw_writel((u32) dst, DMACH_DEST_ADDR(DMAIOBASE, ch));
+       __raw_writel(0, DMACH_LLI(DMAIOBASE, ch));
+       __raw_writel(dma_ctrl.dma_channels[ch].control, DMACH_CONTROL(DMAIOBASE, ch));
+
+       tmp = dma_ctrl.dma_channels[ch].config |
+               dma_ctrl.dma_channels[ch].config_int_mask;
+       if (enable != 0)
+               tmp |= DMAC_CHAN_ENABLE;
+       __raw_writel(tmp, DMACH_CONFIG_CH(DMAIOBASE, ch));
+
+       __dma_regs_unlock();
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(lpc32xx_dma_start_pflow_xfer);
+
+extern u32 lpc32xx_dma_llist_v_to_p(int ch,
+                                   u32 vlist) {
+       u32 pptr;
+
+       if ((!VALID_CHANNEL(ch)) || (dma_ctrl.dma_channels[ch].name == NULL) ||
+               (dma_ctrl.dma_channels[ch].list_vstart == 0))
+               return 0;
+
+       pptr = vlist - dma_ctrl.dma_channels[ch].list_vstart;
+       pptr += dma_ctrl.dma_channels[ch].list_pstart;
+
+       return pptr;
+}
+EXPORT_SYMBOL_GPL(lpc32xx_dma_llist_v_to_p);
+
+u32 lpc32xx_dma_llist_p_to_v(int ch,
+                            u32 plist) {
+       u32 vptr;
+
+       if ((!VALID_CHANNEL(ch)) || (dma_ctrl.dma_channels[ch].name == NULL) ||
+               (dma_ctrl.dma_channels[ch].list_vstart == 0))
+               return 0;
+
+       vptr = plist - dma_ctrl.dma_channels[ch].list_pstart;
+       vptr += dma_ctrl.dma_channels[ch].list_vstart;
+
+       return vptr;
+}
+EXPORT_SYMBOL_GPL(lpc32xx_dma_llist_p_to_v);
+
+u32 lpc32xx_dma_alloc_llist(int ch,
+                            int entries) {
+       int i;
+       dma_addr_t dma_handle;
+       struct dma_list_ctrl *pdmalist, *pdmalistst;
+
+       if ((!VALID_CHANNEL(ch)) || (dma_ctrl.dma_channels[ch].name == NULL))
+               return 0;
+
+       /* Limit number of list entries */
+       if (entries < 2) {
+               entries = 2;
+       }
+       if (entries > 64) {
+               entries = 64;
+       }
+
+       /* Save list information */
+       dma_ctrl.dma_channels[ch].list_entries = entries;
+       dma_ctrl.dma_channels[ch].list_size = (entries * sizeof(struct dma_list_ctrl));
+       dma_ctrl.dma_channels[ch].list_vstart = (u32) dma_alloc_coherent(NULL,
+               dma_ctrl.dma_channels[ch].list_size, &dma_handle, GFP_KERNEL);
+       if (dma_ctrl.dma_channels[ch].list_vstart == 0) {
+               /* No allocated DMA space */
+               return 0;
+       }
+       dma_ctrl.dma_channels[ch].list_pstart = (u32) dma_handle;
+
+       /* Setup list tail and head pointers */
+       pdmalist = pdmalistst = (struct dma_list_ctrl *) dma_ctrl.dma_channels[ch].list_vstart;
+       for (i = 0; i < entries; i++) {
+               pdmalistst->next_list_addr = pdmalistst + 1;
+               pdmalistst->prev_list_addr = pdmalistst - 1;
+               pdmalistst->next_list_phy = lpc32xx_dma_llist_v_to_p(ch, (u32) pdmalistst->next_list_addr);
+               pdmalistst->prev_list_phy = lpc32xx_dma_llist_v_to_p(ch, (u32) pdmalistst->prev_list_addr);
+               pdmalistst++;
+       }
+       pdmalist[entries - 1].next_list_addr = pdmalist;
+       pdmalist[entries - 1].next_list_phy = lpc32xx_dma_llist_v_to_p(ch,
+               (u32) pdmalist[entries - 1].next_list_addr);
+       pdmalist->prev_list_addr = &pdmalist[entries - 1];
+       pdmalist->prev_list_phy = lpc32xx_dma_llist_v_to_p(ch, (u32) pdmalist->prev_list_addr);
+
+       /* Save current free descriptors and current head/tail */
+       dma_ctrl.dma_channels[ch].free_entries = entries;
+       dma_ctrl.dma_channels[ch].list_head = pdmalist;
+       dma_ctrl.dma_channels[ch].list_tail = pdmalist;
+
+       return dma_ctrl.dma_channels[ch].list_vstart;
+}
+EXPORT_SYMBOL_GPL(lpc32xx_dma_alloc_llist);
+
+void lpc32xx_dma_dealloc_llist(int ch) {
+
+       if ((!VALID_CHANNEL(ch)) || (dma_ctrl.dma_channels[ch].name == NULL) ||
+               (dma_ctrl.dma_channels[ch].list_vstart == 0))
+               return;
+
+       dma_free_coherent(NULL, dma_ctrl.dma_channels[ch].list_size,
+               (void *) dma_ctrl.dma_channels[ch].list_vstart,
+               (dma_addr_t) dma_ctrl.dma_channels[ch].list_pstart);
+       dma_ctrl.dma_channels[ch].list_head = 0;
+       dma_ctrl.dma_channels[ch].list_tail = 0;
+       dma_ctrl.dma_channels[ch].list_entries = 0;
+       dma_ctrl.dma_channels[ch].free_entries = 0;
+       dma_ctrl.dma_channels[ch].list_vstart = 0;
+}
+EXPORT_SYMBOL_GPL(lpc32xx_dma_dealloc_llist);
+
+extern u32 lpc32xx_dma_get_llist_head(int ch) {
+       if ((!VALID_CHANNEL(ch)) || (dma_ctrl.dma_channels[ch].name == NULL) ||
+               (dma_ctrl.dma_channels[ch].list_vstart == 0))
+               return 0;
+
+       /* Return the current list pointer (virtual) for the
+          DMA channel */
+       return lpc32xx_dma_llist_p_to_v(ch,
+               __raw_readl(DMACH_LLI(DMAIOBASE, ch)));
+}
+EXPORT_SYMBOL_GPL(lpc32xx_dma_get_llist_head);
+
+extern void lpc32xx_dma_flush_llist(int ch) {
+       if ((!VALID_CHANNEL(ch)) || (dma_ctrl.dma_channels[ch].name == NULL) ||
+               (dma_ctrl.dma_channels[ch].list_vstart == 0))
+               return;
+
+       /* Disable channel and clear LLI */
+       __dma_regs_lock();
+       __dma_disable(ch);
+       __raw_writel(0, DMACH_LLI(DMAIOBASE, ch));
+       __dma_regs_unlock();
+
+       dma_ctrl.dma_channels[ch].list_head = (struct dma_list_ctrl *)
+               dma_ctrl.dma_channels[ch].list_vstart;
+       dma_ctrl.dma_channels[ch].list_tail = (struct dma_list_ctrl *)
+               dma_ctrl.dma_channels[ch].list_vstart;
+       dma_ctrl.dma_channels[ch].free_entries =
+               dma_ctrl.dma_channels[ch].list_entries;
+}
+EXPORT_SYMBOL_GPL(lpc32xx_dma_flush_llist);
+
+u32 lpc32xx_dma_queue_llist_entry(int ch,
+                                 void *src,
+                                 void *dst,
+                                 int size) {
+       struct dma_list_ctrl *plhead;
+       u32 ctrl, cfg;
+
+       if ((!VALID_CHANNEL(ch)) || (dma_ctrl.dma_channels[ch].name == NULL) ||
+               (dma_ctrl.dma_channels[ch].list_vstart == 0))
+               return 0;
+
+       /* Exit if all the buffers are used */
+       if (dma_ctrl.dma_channels[ch].free_entries == 0) {
+               return 0;
+       }
+
+       /* Next available DMA link descriptor */
+       plhead = dma_ctrl.dma_channels[ch].list_head;
+
+       /* Adjust size to number of transfers (vs bytes) */
+       size = size / dma_ctrl.dma_channels[ch].dmacfg->dst_size;
+
+       /* Setup control and config words */
+       ctrl = dma_ctrl.dma_channels[ch].control | size;
+       cfg = dma_ctrl.dma_channels[ch].config | DMAC_CHAN_ENABLE |
+               dma_ctrl.dma_channels[ch].config_int_mask;
+
+       /* Populate DMA linked data structure */
+       plhead->dmall.src = (u32) src;
+       plhead->dmall.dest = (u32) dst;
+       plhead->dmall.next_lli = 0;
+       plhead->dmall.ctrl = ctrl;
+
+       __dma_regs_lock();
+
+       /* Append this link to the end of the previous link */
+       plhead->prev_list_addr->dmall.next_lli = lpc32xx_dma_llist_v_to_p(ch, (u32) plhead);
+
+       /* Decrement available buffers */
+       dma_ctrl.dma_channels[ch].free_entries--;
+
+       /* If the DMA channel is idle, then the buffer needs to be placed directly into
+          the DMA registers */
+       if ((__raw_readl(DMACH_CONFIG_CH(DMAIOBASE, ch)) & DMAC_CHAN_ENABLE) == 0) {
+               /* DMA is disabled, so move the current buffer into the
+                  channel registers and start transfer */
+               __raw_writel((u32) src, DMACH_SRC_ADDR(DMAIOBASE, ch));
+               __raw_writel((u32) dst, DMACH_DEST_ADDR(DMAIOBASE, ch));
+               __raw_writel(0, DMACH_LLI(DMAIOBASE, ch));
+               __raw_writel(ctrl, DMACH_CONTROL(DMAIOBASE, ch));
+               __raw_writel(cfg, DMACH_CONFIG_CH(DMAIOBASE, ch));
+       }
+
+       /* Process next link on next call */
+       dma_ctrl.dma_channels[ch].list_head = plhead->next_list_addr;
+
+       __dma_regs_unlock();
+
+       return (u32) plhead;
+}
+EXPORT_SYMBOL_GPL(lpc32xx_dma_queue_llist_entry);
+
+extern u32 lpc32xx_get_free_llist_entry(int ch) {
+       struct dma_list_ctrl *pltail;
+
+       if ((!VALID_CHANNEL(ch)) || (dma_ctrl.dma_channels[ch].name == NULL) ||
+               (dma_ctrl.dma_channels[ch].list_vstart == 0))
+               return 0;
+
+       /* Exit if no entries to free */
+       if (dma_ctrl.dma_channels[ch].free_entries ==
+               dma_ctrl.dma_channels[ch].list_entries) {
+               return 0;
+       }
+
+       /* Get tail pointer */
+       pltail = dma_ctrl.dma_channels[ch].list_tail;
+
+       /* Next tail */
+       dma_ctrl.dma_channels[ch].list_tail = pltail->next_list_addr;
+
+       /* Increment available buffers */
+       dma_ctrl.dma_channels[ch].free_entries++;
+
+       return (u32) pltail;
+}
+EXPORT_SYMBOL_GPL(lpc32xx_get_free_llist_entry);
+
+static irqreturn_t dma_irq_handler(int irq, void *dev_id)
+{
+       int i;
+       unsigned long dint = __raw_readl(DMA_INT_STAT(DMAIOBASE));
+       unsigned long tcint = __raw_readl(DMA_INT_TC_STAT(DMAIOBASE));
+       unsigned long eint = __raw_readl(DMA_INT_ERR_STAT(DMAIOBASE));
+       unsigned long i_bit;
+
+       for (i = MAX_DMA_CHANNELS - 1; i >= 0; i--) {
+               i_bit = 1 << i;
+               if (dint & i_bit) {
+                       struct dma_channel *channel = &dma_ctrl.dma_channels[i];
+
+                       if (channel->name && channel->irq_handler) {
+                               int cause = 0;
+
+                               if (eint & i_bit) {
+                                       __raw_writel(i_bit, DMA_INT_ERR_CLEAR(DMAIOBASE));
+                                       cause |= DMA_ERR_INT;
+                               }
+                               if (tcint & i_bit) {
+                                       __raw_writel(i_bit, DMA_INT_TC_CLEAR(DMAIOBASE));
+                                       cause |= DMA_TC_INT;
+                               }
+
+                               channel->irq_handler(i, cause, channel->data);
+                       } else {
+                               /*
+                                * IRQ for an unregistered DMA channel
+                                */
+                               __raw_writel(i_bit, DMA_INT_ERR_CLEAR(DMAIOBASE));
+                               __raw_writel(i_bit, DMA_INT_TC_CLEAR(DMAIOBASE));
+                               printk(KERN_WARNING
+                                      "spurious IRQ for DMA channel %d\n", i);
+                       }
+               }
+       }
+
+       return IRQ_HANDLED;
+}
+
+static int __init lpc32xx_dma_init(void)
+{
+       int ret;
+
+       printk(KERN_INFO "LPC32XX DMA driver\n");
+
+       ret = request_irq(IRQ_LPC32XX_DMA, dma_irq_handler, 0, "DMA", NULL);
+       if (ret) {
+               printk(KERN_CRIT "Wow!  Can't register IRQ for DMA\n");
+               goto out;
+       }
+
+       /* Get DMA clock */
+       dma_ctrl.clk = clk_get(NULL, "clk_dmac");
+       if (IS_ERR(dma_ctrl.clk)) {
+               ret = -ENODEV;
+               goto errout;
+       }
+       clk_enable(dma_ctrl.clk);
+
+       /* Clear DMA controller */
+       __raw_writel(1, DMA_CONFIG(DMAIOBASE));
+       __raw_writel(0xFF, DMA_INT_TC_CLEAR(DMAIOBASE));
+       __raw_writel(0xFF, DMA_INT_ERR_CLEAR(DMAIOBASE));
+
+       /* Clock is only enabled when needed to save power */
+       clk_disable(dma_ctrl.clk);
+
+       return 0;
+
+errout:
+       free_irq(IRQ_LPC32XX_DMA, NULL);
+
+out:
+       return ret;
+}
+arch_initcall(lpc32xx_dma_init);
+
+
diff --git a/arch/arm/mach-lpc32xx/ea3250.c b/arch/arm/mach-lpc32xx/ea3250.c
new file mode 100644 (file)
index 0000000..e2ffd36
--- /dev/null
@@ -0,0 +1,892 @@
+/*
+ * arch/arm/mach-lpc32xx/ea3250.c
+ *
+ * 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/delay.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/eeprom.h>
+#include <linux/leds.h>
+#include <linux/gpio.h>
+#include <linux/input.h>
+#include <linux/amba/bus.h>
+#include <linux/amba/clcd.h>
+#include <linux/amba/pl022.h>
+#include <linux/amba/mmci.h>
+
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+
+#include <mach/hardware.h>
+#include <mach/platform.h>
+#include <mach/board.h>
+#include "common.h"
+
+#include <linux/spi/ads7846.h>
+
+#define I2C_PCA9532_ADDR 0x60
+#define I2C_24LC256_ADDR 0x50
+
+/*
+ * Mapped GPIOLIB GPIOs
+ */
+#define        LED_GPIO        LPC32XX_GPIO(LPC32XX_GPIO_P2_GRP, 1)
+#define        SPI0_CS_GPIO    LPC32XX_GPIO(LPC32XX_GPO_P3_GRP, 11)
+#define        ADS_TS_GPIO     LPC32XX_GPIO(LPC32XX_GPIO_P3_GRP, 0)
+#define        NAND_WP_GPIO    LPC32XX_GPIO(LPC32XX_GPO_P3_GRP, 19)
+#define        LCD_CS_GPIO     LPC32XX_GPIO(LPC32XX_GPO_P3_GRP, 4)
+#define        LCD_RS_GPIO     LPC32XX_GPIO(LPC32XX_GPO_P3_GRP, 5)
+#define        BKL_POW_GPIO    LPC32XX_GPIO(LPC32XX_GPO_P3_GRP, 14)
+
+/*
+ * LCD controller functions
+ */
+#define SET_RS         (gpio_set_value(LCD_RS_GPIO, 1))
+#define RESET_RS       (gpio_set_value(LCD_RS_GPIO, 0))
+#define PANEL_SIZE     (3 * SZ_64K)
+
+/* SPI LCDC device structure */
+struct spi_device *ea3250_spi_lcd_dev = NULL;
+
+/*
+ * Tick LED
+ */
+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,
+};
+
+/*
+ * AMBA SSP (SPI)
+ */
+static struct pl022_ssp_controller lpc32xx_ssp0_data = {
+       .bus_id                 = 0,
+       .num_chipselect         = 2,
+       .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},
+};
+
+/*
+ * Touchscreen device
+ */
+/* Touch screen chip select function */
+static void ea3250_spi_cs_set(u32 control)
+{
+       gpio_set_value(SPI0_CS_GPIO, (int) control);
+}
+
+/* Touch screen SPI parameters */
+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             = ea3250_spi_cs_set,
+};
+
+/* Touch screen interrupt status function */
+static int ea3250_ads7846_pendown_state(void)
+{
+       u32 tmp = gpio_get_value(ADS_TS_GPIO);
+       return (tmp == 0);
+}
+
+/* Touch screen platform data */
+static struct ads7846_platform_data ea_ads7846_platform_data __initdata = {
+       .debounce_max   = 10,
+       .debounce_tol   = 3,
+       .pressure_max   = 1024,
+       .get_pendown_state = ea3250_ads7846_pendown_state,
+};
+
+/*
+ * SPI based LCDC data
+ */
+/* LCDC chip select function */
+static void ea3250_spi_lcdc_cs_set(u32 control)
+{
+       gpio_set_value(LCD_CS_GPIO, (int) control);
+}
+
+/* LCDC SPI parameters */
+static struct pl022_config_chip spi0_chip_info1 = {
+       .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             = ea3250_spi_lcdc_cs_set,
+};
+
+/* SPI devices registration */
+static int __init ea3250_spi_devices_register(void)
+{
+#if defined(CONFIG_SPI_SPIDEV) || defined(CONFIG_SPI_SPIDEV_MODULE)
+       static struct spi_board_info info[] = {
+               {
+                       .modalias = "spidev",
+                       .max_speed_hz = 2500000,
+                       .bus_num = 0,
+                       .chip_select = 0,
+                       .controller_data = &spi0_chip_info,
+               },
+       };
+#else
+       struct spi_board_info info[] = {
+               {
+                       .modalias      = "ads7846",
+                       .max_speed_hz  = 2500000,
+                       .chip_select   = 0,
+                       .irq           = IRQ_LPC32XX_GPIO_00,
+                       .platform_data = &ea_ads7846_platform_data,
+                       .controller_data = &spi0_chip_info,
+               },
+               {
+                       .modalias      = "ea3250_lcdc",
+                       .max_speed_hz  = 10000000,
+                       .chip_select   = 1,
+                       .controller_data = &spi0_chip_info1,
+               },
+       };
+#endif
+
+       /* Configure ADS TS INT GPIO pin as input */
+       if (gpio_request(ADS_TS_GPIO, "ADS7846 TS INT"))
+               return -EIO;
+       if(gpio_direction_input(ADS_TS_GPIO))
+               return -EIO;
+
+       /* Configure LCDC CS GPIO pin */
+       if (gpio_request(LCD_CS_GPIO, "LCDC CS"))
+               return -EIO;
+       if(gpio_direction_output(LCD_CS_GPIO, 1))
+               return -EIO;
+
+       return spi_register_board_info(info, ARRAY_SIZE(info));
+}
+arch_initcall(ea3250_spi_devices_register);
+
+/*
+ * LCDC AMBA Driver Board Functions
+ */
+#if defined (CONFIG_EA3250_QVGA_3_2_LCD)
+/*
+ * Support for Embedded Artists 3.2 inch QVGA LCD panel
+ */
+static struct clcd_panel conn_lcd_panel = {
+        .mode           = {
+                .name           = "QVGA portrait",
+                .refresh        = 60,
+                .xres           = 240,
+                .yres           = 320,
+                .pixclock       = 121654,
+                .left_margin    = 28,
+                .right_margin   = 10,
+                .upper_margin   = 2,
+                .lower_margin   = 2,
+                .hsync_len      = 2,
+                .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,
+};
+
+#elif defined (CONFIG_EA3250_QVGA_2_8_OLED)
+/*
+ * Support for Embedded Artists 2.8 inch QVGA OLED panel
+*/
+static struct clcd_panel conn_lcd_panel = {
+        .mode           = {
+                .name           = "QVGA portrait",
+                .refresh        = 60,
+                .xres           = 240,
+                .yres           = 320,
+                .pixclock       = 176366,
+                .left_margin    = 33,
+                .right_margin   = 26,
+                .upper_margin   = 3,
+                .lower_margin   = 8,
+                .hsync_len      = 32,
+                .vsync_len      = 4,
+                .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,
+};
+#endif
+
+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;
+
+        /* Configure LCDC RS GPIO pin */
+        if (gpio_request(LCD_RS_GPIO, "LCDC RS"))
+                return -EIO;
+
+        if(gpio_direction_output(LCD_RS_GPIO, 1))
+                return -EIO;
+
+        /* Configure LCDC Backlight GPIO pin */
+        if (gpio_request(BKL_POW_GPIO, "LCDC BKL"))
+                return -EIO;
+
+#if defined (CONFIG_EA3250_QVGA_3_2_LCD)
+        if(gpio_direction_output(BKL_POW_GPIO, 0)) {
+#else
+        if(gpio_direction_output(BKL_POW_GPIO, 1)) {
+#endif
+                return -EIO;
+        }
+
+        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);
+}
+
+static void spiSend(u8 *buf, size_t len)
+{
+        BUG_ON(ea3250_spi_lcd_dev == NULL);
+        spi_write(ea3250_spi_lcd_dev, buf, len);
+}
+
+#if defined (CONFIG_EA3250_QVGA_2_8_OLED)
+static void writeToDisp(u16 data)
+{
+        u8 buf[3];
+
+        /* Initiliase buffer */
+        buf[0] = 0x72;
+        buf[1] = data >> 8;
+        buf[2] = data & 0xff;
+        spiSend(buf, 3);
+}
+#endif
+
+static void writeToReg(u16 addr, u16 data)
+{
+        u8 buf[3];
+
+#if defined (CONFIG_EA3250_QVGA_3_2_LCD)
+        RESET_RS;
+        buf[0] = 0x00;
+        buf[1] = addr & 0xff;
+        spiSend(buf, 2);
+
+        SET_RS;
+        buf[0] = data >> 8;
+        buf[1] = data & 0xff;
+        spiSend(buf, 2);
+
+        RESET_RS;
+        buf[0] = 0x00;
+        buf[1] = 0x22;
+        spiSend(buf, 2);
+#elif defined (CONFIG_EA3250_QVGA_2_8_OLED)
+        buf[0] = 0x70;
+        buf[1] = data >> 8;
+        buf[2] = data & 0xff;
+        spiSend(buf, 3);
+#endif
+
+}
+
+static void clcd_display_init(void)
+{
+        u32 tmp;
+
+        /* setup MUX register to use SSP0 */
+        __raw_writel(( _BIT(12) | _BIT(10) | _BIT(9) ), LPC32XX_GPIO_P_MUX_SET);
+        tmp = __raw_readl(LPC32XX_GPIO_P_MUX_SET);
+
+#if defined (CONFIG_EA3250_QVGA_3_2_LCD)
+
+        writeToReg (0x00,0x0001);
+        mdelay(20);
+        writeToReg (0x03,0xA2A4);
+        writeToReg (0x0C,0x0004);
+        writeToReg (0x0D,0x0308);
+        writeToReg (0x0E,0x3000);
+        mdelay(50);
+        writeToReg (0x1E,0x00AF);
+        writeToReg (0x01,0x2B3F);
+        writeToReg (0x02,0x0600);
+        writeToReg (0x10,0x0000);
+        writeToReg (0x07,0x0233);
+        writeToReg (0x0B,0x0039);
+        writeToReg (0x0F,0x0000);
+        mdelay(50);
+
+        writeToReg (0x30,0x0707);
+        writeToReg (0x31,0x0204);
+        writeToReg (0x32,0x0204);
+        writeToReg (0x33,0x0502);
+        writeToReg (0x34,0x0507);
+        writeToReg (0x35,0x0204);
+        writeToReg (0x36,0x0204);
+        writeToReg (0x37,0x0502);
+        writeToReg (0x3A,0x0302);
+        writeToReg (0x3B,0x0302);
+
+        writeToReg (0x23,0x0000);
+        writeToReg (0x24,0x0000);
+
+        writeToReg (0x48,0x0000);
+        writeToReg (0x49,0x013F);
+        writeToReg (0x4A,0x0000);
+        writeToReg (0x4B,0x0000);
+
+        writeToReg (0x41,0x0000);
+        writeToReg (0x42,0x0000);
+
+        writeToReg (0x44,0xEF00);
+        writeToReg (0x45,0x0000);
+        writeToReg (0x46,0x013F);
+        mdelay(50);
+
+        writeToReg (0x44,0xEF00);
+        writeToReg (0x45,0x0000);
+        writeToReg (0x4E,0x0000);
+        writeToReg (0x4F,0x0000);
+        writeToReg (0x46,0x013F);
+
+#elif defined (CONFIG_EA3250_QVGA_2_8_OLED)
+
+        writeToReg(0,0x02);
+        writeToDisp(0x0192);
+
+        writeToReg(0,0x03);
+        writeToDisp(0x0130);
+
+        /* set standby off */
+        writeToReg(0,0x10);
+        writeToDisp(0x0000);
+
+        mdelay(100);
+
+        /* set display on */
+        writeToReg(0,0x05);
+        writeToDisp(0x0001);
+
+        /* enable image data transfer */
+        writeToReg(0,0x22);
+#endif
+}
+
+void clcd_disable(struct clcd_fb *fb)
+{
+        /* Disable the backlight */
+#if defined (CONFIG_EA3250_QVGA_3_2_LCD)
+        gpio_set_value(BKL_POW_GPIO, 1);
+#elif defined (CONFIG_EA3250_QVGA_2_8_OLED)
+        gpio_set_value(BKL_POW_GPIO, 0);
+#endif
+}
+
+void clcd_enable(struct clcd_fb *fb)
+{
+        clcd_display_init();
+
+        /* Enable the backlight */
+#if defined (CONFIG_EA3250_QVGA_3_2_LCD)
+        gpio_set_value(BKL_POW_GPIO, 0);
+#elif defined (CONFIG_EA3250_QVGA_2_8_OLED)
+        gpio_set_value(BKL_POW_GPIO, 1);
+#endif
+
+}
+
+struct clcd_board lpc32xx_clcd_data = {
+#if defined (CONFIG_EA3250_QVGA_3_2_LCD)
+        .name           = "Embedded Artists 3.2 inch LCD",
+#elif defined (CONFIG_EA3250_QVGA_2_8_OLED)
+        .name           = "Embedded Artists 2.8 inch OLED",
+#else
+        .name           = "Unknown Display",
+#endif
+        .check          = clcdfb_check,
+        .decode         = clcdfb_decode,
+        .disable        = clcd_disable,
+        .enable         = clcd_enable,
+        .setup          = lpc32xx_clcd_setup,
+        .mmap           = lpc32xx_clcd_mmap,
+        .remove         = lpc32xx_clcd_remove,
+};
+
+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},
+};
+
+/*
+ * SPI LCDC Driver Probe function
+ */
+static int ea3250_spi_lcdc_probe(struct spi_device *spi)
+{
+        int err;
+
+        spi->mode = SPI_MODE_0;
+       ea3250_spi_lcd_dev = spi;
+
+        /* SPI settings */
+        err = spi_setup(spi);
+        if (err < 0) {
+                dev_err(&spi->dev, "Err in setting SPI \n");
+                return err;
+        }
+        return 0;
+}
+
+/*
+ *  * SPI LCDC Driver remove function
+ *   * */
+static int ea3250_spi_lcdc_remove(struct spi_device *spi)
+{
+        return 0;
+}
+
+static struct spi_driver ea3250_spi_lcdc_driver = {
+        .driver = {
+                .name   = "ea3250_lcdc",
+                .bus    = &spi_bus_type,
+                .owner  = THIS_MODULE,
+        },
+        .probe  = ea3250_spi_lcdc_probe,
+        .remove = __devexit_p(ea3250_spi_lcdc_remove),
+};
+
+void __init ea3250_spi_lcdc_drv_init(void)
+{
+        spi_register_driver(&ea3250_spi_lcdc_driver);
+}
+
+/* AMBA based devices list */
+static struct amba_device *amba_devs[] __initdata = {
+       &lpc32xx_ssp0_device,
+       &lpc32xx_clcd_device,
+};
+
+/*
+ * Register AMBA BUS Devices.
+ * Call AMBA device restration after SPI driver probe(),
+ * as LCD controller uses SPI driver for initialization
+ */
+static int __init ea3250_amba_devices_register(void)
+{
+       u32 i = 0;
+
+       /* Add AMBA devices */
+       for (i = 0; i < ARRAY_SIZE(amba_devs); i++) {
+               struct amba_device *d = amba_devs[i];
+               amba_device_register(d, &iomem_resource);
+       }
+       
+       return 0;
+}
+device_initcall_sync(ea3250_amba_devices_register);
+
+#if defined(CONFIG_MTD_NAND_SLC_LPC32XX)
+/*
+ *  * Board specific NAND setup data
+ *   */
+static int nandwp_enable(int enable)
+{
+        if (enable != 0)
+               gpio_set_value(NAND_WP_GPIO,0);
+        else
+               gpio_set_value(NAND_WP_GPIO,1);
+
+        return 1;
+}
+#define BLK_SIZE (1024 * 128)
+static struct mtd_partition __initdata ea3250_nand_partition[] = {
+        {
+                .name   = "ea3250-boot",
+                .offset = 0,
+                .size   = (BLK_SIZE * 7)
+        },
+        {
+                .name   = "ea3250-ubt-prms",
+                .offset = MTDPART_OFS_APPEND,
+                .size   = (BLK_SIZE * 1)
+        },
+        {
+                .name   = "ea3250-kernel",
+                .offset = MTDPART_OFS_APPEND,
+                .size   = (BLK_SIZE * 32)
+        },
+        {
+                .name   = "ea3250-rootfs",
+                .offset = MTDPART_OFS_APPEND,
+                .size   = (BLK_SIZE * 40)
+        },
+        {
+                .name   = "ea3250-jffs2",
+                .offset = MTDPART_OFS_APPEND,
+                .size   = MTDPART_SIZ_FULL
+        },
+};
+static struct mtd_partition * __init ea3250_nand_partitions(int size, int *num_partitions)
+{
+        *num_partitions = ARRAY_SIZE(ea3250_nand_partition);
+        return ea3250_nand_partition;
+}
+struct lpc32XX_nand_cfg lpc32xx_nandcfg =
+{
+        .wdr_clks               = 14,
+        .wwidth                 = 260000000,
+        .whold                  = 104000000,
+        .wsetup                 = 200000000,
+        .rdr_clks               = 14,
+        .rwidth                 = 34666666,
+        .rhold                  = 104000000,
+        .rsetup                 = 200000000,
+        .use16bus               = 0,
+        .enable_write_prot      = nandwp_enable,
+        .partition_info         = ea3250_nand_partitions,
+};
+
+/*
+ *  * SLC NAND resources
+ *   */
+static struct resource slc_nand_resources[] = {
+        [0] = {
+                .start  = LPC32XX_SLC_BASE,
+                .end    = LPC32XX_SLC_BASE + SZ_4K - 1,
+                .flags  = IORESOURCE_MEM,
+        },
+
+        [1] = {
+                .start  = IRQ_LPC32XX_FLASH,
+                .end    = IRQ_LPC32XX_FLASH,
+                .flags  = IORESOURCE_IRQ,
+        },
+
+};
+static struct platform_device lpc32xx_slc_nand_device = {
+        .name           = "lpc32xx-nand",
+        .id             = 0,
+        .dev            = {
+                                .platform_data  = &lpc32xx_nandcfg,
+        },
+        .num_resources  = ARRAY_SIZE(slc_nand_resources),
+        .resource       = slc_nand_resources,
+};
+#endif
+
+/*
+ * Network Support
+ */
+static struct lpc_net_cfg lpc32xx_netdata =
+{
+        .phy_irq        = -1,
+        .phy_mask       = 0xFFFFFFF0,
+};
+
+static struct resource net_resources[] = {
+        [0] = {
+                .start  = LPC32XX_ETHERNET_BASE,
+                .end    = LPC32XX_ETHERNET_BASE + SZ_4K - 1,
+                .flags  = IORESOURCE_MEM,
+        },
+
+        [1] = {
+                .start  = IRQ_LPC32XX_ETHERNET,
+                .end    = IRQ_LPC32XX_ETHERNET,
+                .flags  = IORESOURCE_IRQ,
+        },
+
+};
+
+static u64 lpc32xx_mac_dma_mask = 0xffffffffUL;
+static struct platform_device lpc32xx_net_device = {
+        .name           = "lpc-net",
+        .id             = 0,
+        .dev            = {
+                .dma_mask = &lpc32xx_mac_dma_mask,
+                .coherent_dma_mask = 0xffffffffUL,
+                .platform_data  = &lpc32xx_netdata,
+        },
+        .num_resources  = ARRAY_SIZE(net_resources),
+        .resource       = net_resources,
+};
+
+/*
+ * I2C devices support
+ */
+#if defined (CONFIG_SENSORS_PCA9532) || defined (CONFIG_AT24)
+       static struct i2c_board_info __initdata ea3250_i2c_board_info [] = {
+#if defined (CONFIG_SENSORS_PCA9532)
+               {
+                       I2C_BOARD_INFO("pca9532", I2C_PCA9532_ADDR),
+
+               },
+#endif
+#if defined (CONFIG_AT24)
+               {
+                       I2C_BOARD_INFO("24c256", I2C_24LC256_ADDR),
+               },
+#endif
+       };
+#endif
+
+static struct platform_device* ea3250_devs[] __initdata = {
+       &lpc32xx_i2c0_device,
+       &lpc32xx_i2c1_device,
+       &lpc32xx_i2c2_device,
+       &lpc32xx_watchdog_device,
+       &lpc32xx_gpio_led_device,
+       &lpc32xx_rtc_device,
+       &lpc32xx_net_device,
+#if defined(CONFIG_MTD_NAND_SLC_LPC32XX)
+       &lpc32xx_slc_nand_device,
+#endif
+#if defined(CONFIG_USB_OHCI_HCD)
+       &lpc32xx_ohci_device,
+#endif
+#if defined(CONFIG_USB_GADGET_LPC32XX)
+        &lpc32xx_usbd_device,
+#endif
+};
+
+extern void __init ea3250_spi_lcdc_drv_init(void);
+
+/*
+ * Board specific functions
+ */
+void __init ea3250_board_init(void)
+{
+       u32 tmp;
+
+       /* Intiliase GPIO */
+       lpc32xx_gpio_init();
+
+       /* Set SPI CS GPIO to output */
+       gpio_request(SPI0_CS_GPIO, "spi0 cs");
+       gpio_direction_output(SPI0_CS_GPIO, 1);
+
+       /* 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 */
+       __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);
+
+       /* 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);
+
+       /* Initalise Serial device */
+       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
+        */
+       /* Initialise SSP clock */
+       tmp = __raw_readl(LPC32XX_CLKPWR_SSP_CLK_CTRL);
+       __raw_writel((tmp | LPC32XX_CLKPWR_SSPCTRL_SSPCLK0_EN),
+                       LPC32XX_CLKPWR_SSP_CLK_CTRL);
+
+       /* Initialise LCD clock */
+       tmp = __raw_readl(LPC32XX_CLKPWR_LCDCLK_CTRL);
+       __raw_writel((tmp | LPC32XX_CLKPWR_LCDCTRL_CLK_EN),
+                       LPC32XX_CLKPWR_LCDCLK_CTRL);
+
+       /* Enable SD card clock so AMBA driver will work correctly. The
+          AMBA driver needs the clock before the SD card controller
+          driver initializes it. The clock will turn off once the driver
+          has been initialized. */
+       tmp = __raw_readl(LPC32XX_CLKPWR_MS_CTRL);
+       tmp |= LPC32XX_CLKPWR_MSCARD_SDCARD_EN |
+               LPC32XX_CLKPWR_MSCARD_MSDIO_PU_EN;
+       __raw_writel(tmp, LPC32XX_CLKPWR_MS_CTRL);
+
+       /* 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);
+
+       /* Add platform devcies */
+       platform_add_devices(ea3250_devs, ARRAY_SIZE(ea3250_devs));
+
+       /* Register SPI driver */
+       ea3250_spi_lcdc_drv_init();
+       
+       /* Test clock needed for UDA1380 initial init */
+       __raw_writel(LPC32XX_CLKPWR_TESTCLK2_SEL_MOSC |
+                       LPC32XX_CLKPWR_TESTCLK_TESTCLK2_EN,
+                       LPC32XX_CLKPWR_TEST_CLK_SEL);
+
+#if defined (CONFIG_SENSORS_PCA9532) || defined (CONFIG_AT24)
+       i2c_register_board_info(0, ea3250_i2c_board_info,
+                       ARRAY_SIZE(ea3250_i2c_board_info));
+#endif
+}
+
+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 (EA3250, "Embedded Artists LPC3250 OEM board with the LPC3250 Microcontroller")
+       /* Maintainer: Embedded Artists */
+       .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   = ea3250_board_init,
+       MACHINE_END
+
+/* For backwards compatibility with older bootloaders only */
+MACHINE_START (LPC3XXX, "Embedded Artists LPC3250 OEM board with the LPC3250 Microcontroller")
+       /* Maintainer: Embedded Artists */
+       .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   = ea3250_board_init,
+       MACHINE_END
diff --git a/arch/arm/mach-lpc32xx/gpiolib.c b/arch/arm/mach-lpc32xx/gpiolib.c
new file mode 100644 (file)
index 0000000..2f60faf
--- /dev/null
@@ -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 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 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 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 char *gpio_p3_names[LPC32XX_GPIO_P3_MAX] = {
+       "gpi000", "gpio01", "gpio02", "gpio03",
+       "gpio04", "gpio05"
+};
+
+static 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 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);
+}
diff --git a/arch/arm/mach-lpc32xx/include/mach/board.h b/arch/arm/mach-lpc32xx/include/mach/board.h
new file mode 100644 (file)
index 0000000..d87574d
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * arm/arch/mach-lpc32xx/include/mach/board.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_BOARD_H
+#define __ASM_ARCH_BOARD_H
+
+#include "platform.h"
+#include <linux/mtd/partitions.h>
+
+/*
+ * NAND platform configuration structure
+*/
+typedef int (*en_wp)(int);
+struct lpc32XX_nand_cfg
+{
+        u32             wdr_clks;
+        u32             wwidth;
+        u32             whold;
+        u32             wsetup;
+        u32             rdr_clks;
+        u32             rwidth;
+        u32             rhold;
+        u32             rsetup;
+        int             use16bus; /* 0 = 8-bit, !0 = not support */
+        en_wp           enable_write_prot;
+        struct mtd_partition* (*partition_info)(int, int*);
+};
+
+/*
+ * Key scanner platform configuration structure
+ */
+struct lpc32XX_kscan_cfg {
+       u32     matrix_sz;      /* Size of matrix in XxY, ie. 3 = 3x3 */
+       int     *keymap;        /* Pointer to key map for the scan matrix */
+       u32     deb_clks;       /* Debounce clocks (based on 32KHz clock) */
+       u32     scan_delay;     /* Scan delay (based on 32KHz clock) */
+};
+
+/*
+ * Network configuration structure
+ */
+struct lpc_net_cfg {
+       int     phy_irq;        /* PHY IRQ number, or -1 for polling */
+       u32     phy_mask;       /* PHY mask value */
+};
+
+/*
+ * USB device configuration structure
+ */
+typedef void (*usc_chg_event)(int);
+struct lpc32xx_usbd_cfg
+{
+        int     vbus_drv_pol;   /* 0=active low drive for VBUS via ISP1301 */
+        usc_chg_event conn_chgb; /* Connection change event callback (optional) */
+        usc_chg_event susp_chgb; /* Suspend/resume event callback (optional) */
+        usc_chg_event rmwk_chgb; /* Enable/disable remote wakeup */
+};
+
+
+#endif /* __ASM_ARCH_BOARD_H */
+
diff --git a/arch/arm/mach-lpc32xx/include/mach/clkdev.h b/arch/arm/mach-lpc32xx/include/mach/clkdev.h
new file mode 100644 (file)
index 0000000..9bf0637
--- /dev/null
@@ -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
diff --git a/arch/arm/mach-lpc32xx/include/mach/debug-macro.S b/arch/arm/mach-lpc32xx/include/mach/debug-macro.S
new file mode 100644 (file)
index 0000000..621744d
--- /dev/null
@@ -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>
diff --git a/arch/arm/mach-lpc32xx/include/mach/dma.h b/arch/arm/mach-lpc32xx/include/mach/dma.h
new file mode 100644 (file)
index 0000000..840163c
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+ * asm-arm/arch-lpc32xx/dma.h
+ *
+ * Author: Kevin Wells <kevin.wells@nxp.com>
+ *
+ * Copyright (C) 2008 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef __ASM_ARCH_DMA_H
+#define __ASM_ARCH_DMA_H
+
+#include <mach/platform.h>
+
+#define MAX_DMA_CHANNELS 8
+
+#define DMA_CH_SDCARD_TX 0
+#define DMA_CH_SDCARD_RX 1
+#define DMA_CH_I2S_TX 2
+#define DMA_CH_I2S_RX 3
+
+enum {
+       DMA_INT_UNKNOWN = 0,
+       DMA_ERR_INT = 1,
+       DMA_TC_INT = 2,
+};
+
+/*
+ * DMA channel control structure
+ */
+struct dma_config {
+       int ch;         /* Channel # to use */
+       int tc_inten;   /* !0 = Enable TC interrupts for this channel */
+       int err_inten;  /* !0 = Enable error interrupts for this channel */
+       int src_size;   /* Source xfer size - must be 1, 2, or 4 */
+       int src_inc;    /* !0 = Enable source address increment */
+       int src_ahb1;   /* !0 = Use AHB1 for source transfer */
+       int src_bsize;  /* Source burst size (ie, DMAC_CHAN_SRC_BURST_xxx) */
+       u32 src_prph;   /* Source peripheral (ie, DMA_PERID_xxxx) */
+       int dst_size;   /* Destination xfer size - must be 1, 2, or 4 */
+       int dst_inc;    /* !0 = Enable destination address increment */
+       int dst_ahb1;   /* !0 = Use AHB1 for destination transfer */
+       int dst_bsize;  /* Destination burst size (ie, DMAC_CHAN_DEST_BURST_xxx) */
+       u32 dst_prph;   /* Destination peripheral (ie, DMA_PERID_xxxx) */
+       u32 flowctrl;   /* Flow control (ie, DMAC_CHAN_FLOW_xxxxxx) */
+};
+
+/*
+ * Channel enable and disable functions
+ */
+extern int lpc32xx_dma_ch_enable(int ch);
+extern int lpc32xx_dma_ch_disable(int ch);
+
+/*
+ * Channel allocation and deallocation functions
+ */
+extern int lpc32xx_dma_ch_get(struct dma_config *dmachcfg,
+                               char *name,
+                               void *irq_handler,
+                               void *data);
+extern int lpc32xx_dma_ch_put(int ch);
+extern int lpc32xx_dma_ch_pause_unpause(int ch, int pause);
+
+/*
+ * Setup or start an unbound DMA transfer
+ */
+extern int lpc32xx_dma_start_pflow_xfer(int ch,
+                                       void *src,
+                                       void *dst,
+                                       int enable);
+
+/*
+ * DMA linked list support
+ */
+extern u32 lpc32xx_dma_alloc_llist(int ch,
+                                  int entries);
+extern void lpc32xx_dma_dealloc_llist(int ch);
+extern u32 lpc32xx_dma_llist_v_to_p(int ch,
+                                   u32 vlist);
+extern u32 lpc32xx_dma_llist_p_to_v(int ch,
+                                   u32 plist);
+extern u32 lpc32xx_dma_get_llist_head(int ch);
+extern void lpc32xx_dma_flush_llist(int ch);
+extern u32 lpc32xx_dma_queue_llist_entry(int ch,
+                                        void *src,
+                                        void *dst,
+                                        int size);
+extern u32 lpc32xx_get_free_llist_entry(int ch);
+
+#endif /* _ASM_ARCH_DMA_H */
+
diff --git a/arch/arm/mach-lpc32xx/include/mach/dmac.h b/arch/arm/mach-lpc32xx/include/mach/dmac.h
new file mode 100644 (file)
index 0000000..e7d82a7
--- /dev/null
@@ -0,0 +1,285 @@
+/*
+ * asm-arm/arch-lpc32xx/dmac.h
+ *
+ * Author: Kevin Wells <kevin.wells@nxp.com>
+ *
+ * Copyright (C) 2008 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef __ASM_ARCH_DMAC_H
+#define __ASM_ARCH_DMAC_H
+
+/**********************************************************************
+* DMA register offsets
+**********************************************************************/
+
+/* DMA controller register structures */
+#define DMA_INT_STAT(x)                        (x + 0x00)
+#define DMA_INT_TC_STAT(x)             (x + 0x04)
+#define DMA_INT_TC_CLEAR(x)            (x + 0x08)
+#define DMA_INT_ERR_STAT(x)            (x + 0x0C)
+#define DMA_INT_ERR_CLEAR(x)           (x + 0x10)
+#define DMA_RAW_TC_STAT(x)             (x + 0x14)
+#define DMA_RAW_ERR_STAT(x)            (x + 0x18)
+#define DMA_CH_ENABLE(x)               (x + 0x1C)
+#define DMA_SW_BURST_REQ(x)            (x + 0x20)
+#define DMA_SW_SINGLE_REQ(x)           (x + 0x24)
+#define DMA_SW_LAST_BURST_REQ(x)       (x + 0x28)
+#define DMA_SW_LAST_SINGLE_REQ(x)      (x + 0x2C)
+#define DMA_CONFIG(x)                  (x + 0x30)
+#define DMA_SYNC(x)                    (x + 0x34)
+
+/* DMA controller channel register structure */
+#define DMA_CH_OFFS(c)                 ((c * 0x20) + 0x100)
+#define DMACH_SRC_ADDR(x, c)           (x + DMA_CH_OFFS(c) + 0x00)
+#define DMACH_DEST_ADDR(x, c)          (x + DMA_CH_OFFS(c) + 0x04)
+#define DMACH_LLI(x, c)                        (x + DMA_CH_OFFS(c) + 0x08)
+#define DMACH_CONTROL(x, c)            (x + DMA_CH_OFFS(c) + 0x0C)
+#define DMACH_CONFIG_CH(x, c)          (x + DMA_CH_OFFS(c) + 0x10)
+
+/* DMA linked list structure */
+#define DMA_LL_SRC(x)                  (x + 0x0)
+#define DMA_LL_DEST(x)                 (x + 0x4)
+#define DMA_LL_NEXT_LLI(x)             (x + 0x8)
+#define DMA_LL_NEXT_CTRL(x)            (x + 0xC)
+
+#define DMA_LL_SIZE 16
+
+/**********************************************************************
+* int_stat, int_tc_stat, int_tc_clear, int_err_stat, raw_tc_stat,
+* raw_err_stat, and chan_enable register definitions
+**********************************************************************/
+/* Macro for determining a bit position for a channel */
+#define DMAC_GET_CHAN_POS(chan)     (0x1 << ((chan) & 0x7))
+
+/**********************************************************************
+* sw_burst_req, sw_single_req, sw_last_burst_req, sw_last_single_req,
+* and sync register definitions
+**********************************************************************/
+/* Peripheral DMA bit position for I2S0 DMA0 */
+#define DMA_PER_I2S0_DMA0           _BIT(0)
+
+/* Peripheral DMA bit position for NAND FLASH (same as 12) */
+#define DMA_PER_NAND1               _BIT(1)
+
+/* Peripheral DMA bit position for I2S1 DMA0 */
+#define DMA_PER_I2S1_DMA0           _BIT(2)
+
+/* Peripheral DMA bit position for SPI2 (RX and TX) */
+#define DMA_PER_SPI2_TXRX           _BIT(3)
+
+/* Peripheral DMA bit position for SSP1 (RX) */
+#define DMA_PER_SSP1_RX             _BIT(3)
+
+/* Peripheral DMA bit position for SD card */
+#define DMA_PER_SDCARD              _BIT(4)
+
+/* Peripheral DMA bit position for HSUART1 TX */
+#define DMA_PER_HSUART1_TX          _BIT(5)
+
+/* Peripheral DMA bit position for HSUART1 RX */
+#define DMA_PER_HSUART1_RX          _BIT(6)
+
+/* Peripheral DMA bit position for HSUART2 TX */
+#define DMA_PER_HSUART2_TX          _BIT(7)
+
+/* Peripheral DMA bit position for HSUART2 RX */
+#define DMA_PER_HSUART2_RX          _BIT(8)
+
+/* Peripheral DMA bit position for HSUART7 TX */
+#define DMA_PER_HSUART7_TX          _BIT(9)
+
+/* Peripheral DMA bit position for HSUART7 RX */
+#define DMA_PER_HSUART7_RX          _BIT(10)
+
+/* Peripheral DMA bit position for I2S1 DMA1 */
+#define DMA_PER_I2S1_DMA1           _BIT(10)
+
+/* Peripheral DMA bit position for SPI1 (RX and TX) */
+#define DMA_PER_SPI1_TXRX           _BIT(11)
+
+/* Peripheral DMA bit position for SSP1 (TX) */
+#define DMA_PER_SSP1_TX             _BIT(11)
+
+/* Peripheral DMA bit position for NAND FLASH (same as 1) */
+#define DMA_PER_NAND2               _BIT(12)
+
+/* Peripheral DMA bit position for I2S0 DMA1 */
+#define DMA_PER_I2S0_DMA1           _BIT(13)
+
+/* Peripheral DMA bit position for SSP0 (RX) */
+#define DMA_PER_SSP0_RX             _BIT(14)
+
+/* Peripheral DMA bit position for SSP0 (TX) */
+#define DMA_PER_SSP0_TX             _BIT(15)
+
+/**********************************************************************
+* config register definitions
+**********************************************************************/
+/* Bit for enabling big endian mode on AHB 1 */
+#define DMAC_BIG_ENDIAN_AHB1        _BIT(2)
+
+/* Bit for enabling big endian mode on AHB 0 */
+#define DMAC_BIG_ENDIAN_AHB0        _BIT(1)
+
+/* Bit for enabling the DMA controller */
+#define DMAC_CTRL_ENABLE            _BIT(0)
+
+/**********************************************************************
+* lli register definitions
+**********************************************************************/
+/* Bit for selecting AHB0 (0) or AHB1 (1) */
+#define DMAC_CHAN_LLI_SEL_AHB1      _BIT(0)
+
+/**********************************************************************
+* control register definitions
+**********************************************************************/
+/* Bit for enabling a channel terminal count interrupt */
+#define DMAC_CHAN_INT_TC_EN         _BIT(31)
+
+/* Bit for indicating address is cacheable */
+#define DMAC_CHAN_PROT3             _BIT(30)
+
+/* Bit for indicating address is bufferable */
+#define DMAC_CHAN_PROT2             _BIT(29)
+
+/* Bit for indicating address is privelaged mode (1) or user
+   mode (0) */
+#define DMAC_CHAN_PROT1             _BIT(28)
+
+/* Bit for enabling automatic destination increment */
+#define DMAC_CHAN_DEST_AUTOINC      _BIT(27)
+
+/* Bit for enabling automatic source increment */
+#define DMAC_CHAN_SRC_AUTOINC       _BIT(26)
+
+/* Bit for using AHB1 master for destination transfer */
+#define DMAC_CHAN_DEST_AHB1         _BIT(25)
+
+/* Bit for using AHB1 master for source transfer */
+#define DMAC_CHAN_SRC_AHB1          _BIT(24)
+
+/* Destination data width selection defines */
+#define DMAC_CHAN_DEST_WIDTH_8      0x0
+#define DMAC_CHAN_DEST_WIDTH_16     _BIT(21)
+#define DMAC_CHAN_DEST_WIDTH_32     _BIT(22)
+
+/* Source data width selection defines */
+#define DMAC_CHAN_SRC_WIDTH_8       0x0
+#define DMAC_CHAN_SRC_WIDTH_16      _BIT(18)
+#define DMAC_CHAN_SRC_WIDTH_32      _BIT(19)
+
+/* Destination data burst size defines (in transfer width) */
+#define DMAC_CHAN_DEST_BURST_1      0
+#define DMAC_CHAN_DEST_BURST_4      _BIT(15)
+#define DMAC_CHAN_DEST_BURST_8      _BIT(16)
+#define DMAC_CHAN_DEST_BURST_16     (_BIT(16) | _BIT(15))
+#define DMAC_CHAN_DEST_BURST_32     _BIT(17)
+#define DMAC_CHAN_DEST_BURST_64     (_BIT(17) | _BIT(15))
+#define DMAC_CHAN_DEST_BURST_128    (_BIT(17) | _BIT(16))
+#define DMAC_CHAN_DEST_BURST_256    (_BIT(17) | _BIT(16) | _BIT(15))
+
+/* Macro for direct loading of destination burst size field */
+#define DMAC_CHAN_DEST_BURST_LOAD(n) (((n) & 0x7) << 15)
+
+/* Source data burst size defines (in transfer width) */
+#define DMAC_CHAN_SRC_BURST_1       0
+#define DMAC_CHAN_SRC_BURST_4       _BIT(12)
+#define DMAC_CHAN_SRC_BURST_8       _BIT(13)
+#define DMAC_CHAN_SRC_BURST_16      (_BIT(13) | _BIT(12))
+#define DMAC_CHAN_SRC_BURST_32      _BIT(14)
+#define DMAC_CHAN_SRC_BURST_64      (_BIT(14) | _BIT(12))
+#define DMAC_CHAN_SRC_BURST_128     (_BIT(14) | _BIT(13))
+#define DMAC_CHAN_SRC_BURST_256     (_BIT(14) | _BIT(13) | _BIT(12))
+
+/* Macro for direct loading of source burst size field */
+#define DMAC_CHAN_SRC_BURST_LOAD(n) (((n) & 0x7) << 12)
+
+/* Macro for loading transfer size */
+#define DMAC_CHAN_TRANSFER_SIZE(n)  ((n) & 0xFFF)
+
+/**********************************************************************
+* config_ch register definitions
+**********************************************************************/
+/* Bit for halting a DMA transfer */
+#define DMAC_CHAN_HALT              _BIT(18)
+
+/* Bit for checking active status of the DMA channel */
+#define DMAC_CHAN_ACTIVE            _BIT(17)
+
+/* Bit for enabling locked transfers */
+#define DMAC_CHAN_LOCK              _BIT(16)
+
+/* Terminal count interrupt mask bit */
+#define DMAC_CHAN_ITC               _BIT(15)
+
+/* Interrupt error mask bit */
+#define DMAC_CHAN_IE                _BIT(14)
+
+/* Defines for flow control with DMA as the controller */
+#define DMAC_CHAN_FLOW_D_M2M        (0x0 << 11)
+#define DMAC_CHAN_FLOW_D_M2P        (0x1 << 11)
+#define DMAC_CHAN_FLOW_D_P2M        (0x2 << 11)
+#define DMAC_CHAN_FLOW_D_SP2DP      (0x3 << 11)
+
+/* Defines for flow control with destination peripheral as the
+   controller */
+#define DMAC_CHAN_FLOW_DP_SP2DP     (0x4 << 11)
+
+/* Defines for flow control with peripheral as the controller */
+#define DMAC_CHAN_FLOW_P_M2P        (0x5 << 11)
+#define DMAC_CHAN_FLOW_P_P2M        (0x6 << 11)
+
+/* Defines for flow control with source peripheral as the
+   controller */
+#define DMAC_CHAN_FLOW_SP_SP2DP     (0x7 << 11)
+
+/* Macro for loading destination peripheral */
+#define DMAC_DEST_PERIP(n)          (((n) & 0x1F) << 6)
+
+/* Macro for loading source peripheral */
+#define DMAC_SRC_PERIP(n)           (((n) & 0x1F) << 1)
+
+/* Channel enable bit */
+#define DMAC_CHAN_ENABLE            _BIT(0)
+
+/**********************************************************************
+* config_ch register definitions (source and destination
+* peripheral ID numbers). These can be used with the DMAC_DEST_PERIP
+* and DMAC_SRC_PERIP macros.
+**********************************************************************/
+#define DMA_PERID_I2S0_DMA0         0
+#define DMA_PERID_NAND1             1
+#define DMA_PERID_I2S1_DMA0         2
+#define DMA_PERID_SPI2_TXRX         3
+#define DMA_PERID_SSP1_RX           3
+#define DMA_PERID_SDCARD            4
+#define DMA_PERID_HSUART1_TX        5
+#define DMA_PERID_HSUART1_RX        6
+#define DMA_PERID_HSUART2_TX        7
+#define DMA_PERID_HSUART2_RX        8
+#define DMA_PERID_HSUART7_TX        9
+#define DMA_PERID_HSUART7_RX        10
+#define DMA_PERID_I2S1_DMA1         10
+#define DMA_PERID_SPI1_TXRX         11
+#define DMA_PERID_SSP1_TX           11
+#define DMA_PERID_NAND2             12
+#define DMA_PERID_I2S0_DMA1         13
+#define DMA_PERID_SSP0_RX           14
+#define DMA_PERID_SSP0_TX           15
+
+#endif /* __ASM_ARCH_DMAC_H */
diff --git a/arch/arm/mach-lpc32xx/include/mach/entry-macro.S b/arch/arm/mach-lpc32xx/include/mach/entry-macro.S
new file mode 100644 (file)
index 0000000..870227c
--- /dev/null
@@ -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
+
diff --git a/arch/arm/mach-lpc32xx/include/mach/gpio.h b/arch/arm/mach-lpc32xx/include/mach/gpio.h
new file mode 100644 (file)
index 0000000..67d03da
--- /dev/null
@@ -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
diff --git a/arch/arm/mach-lpc32xx/include/mach/hardware.h b/arch/arm/mach-lpc32xx/include/mach/hardware.h
new file mode 100644 (file)
index 0000000..33e1dde
--- /dev/null
@@ -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
diff --git a/arch/arm/mach-lpc32xx/include/mach/i2c.h b/arch/arm/mach-lpc32xx/include/mach/i2c.h
new file mode 100644 (file)
index 0000000..034dc92
--- /dev/null
@@ -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 */
diff --git a/arch/arm/mach-lpc32xx/include/mach/i2s.h b/arch/arm/mach-lpc32xx/include/mach/i2s.h
new file mode 100644 (file)
index 0000000..63ec790
--- /dev/null
@@ -0,0 +1,156 @@
+/*
+ * asm-arm/arch-lpc32xx/i2c.h
+ *
+ * Author: Kevin Wells <kevin.wells@nxp.com>
+ *
+ * Copyright (C) 2008 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef  __ASM_ARCH_I2S_H
+#define  __ASM_ARCH_I2S_H
+
+/**********************************************************************
+* I2S controller register offsets
+**********************************************************************/
+
+#define I2S_DAO(x)                     (x + 0x00)
+#define I2S_DAI(x)                     (x + 0x04)
+#define I2S_TX_FIFO(x)                 (x + 0x08)
+#define I2S_RX_FIFO(x)                 (x + 0x0C)
+#define I2S_STAT(x)                    (x + 0x10)
+#define I2S_DMA0(x)                    (x + 0x14)
+#define I2S_DMA1(x)                    (x + 0x18)
+#define I2S_IRQ(x)                     (x + 0x1C)
+#define I2S_TX_RATE(x)                 (x + 0x20)
+#define I2S_RX_RATE(x)                 (x + 0x24)
+
+/**********************************************************************
+* i2s_daO i2s_dai register definitions
+**********************************************************************/
+#define I2S_WW8      _SBF(0,0) /* Word width is 8bit*/
+#define I2S_WW16     _SBF(0,1) /* Word width is 16bit*/
+#define I2S_WW32     _SBF(0,3) /* Word width is 32bit*/
+#define I2S_MONO     _BIT(2)   /* Mono */
+#define I2S_STOP     _BIT(3)   /* Stop, diables the access to FIFO, 
+                                  mutes the channel */
+#define I2S_RESET    _BIT(4)   /* Reset the channel */
+#define I2S_WS_SEL   _BIT(5)   /* Channel Master(0) or slave(1) 
+                                  mode select*/
+#define I2S_WS_HP(s) _SBF(6,s) /* Word select half period - 1 */
+
+#define I2S_MUTE     _BIT(15)  /* Mute the channel, 
+                                  Transmit channel only */
+
+#define I2S_WW32_HP  0x1f /* Word select half period for 32bit 
+                             word width */
+#define I2S_WW16_HP  0x0f /* Word select half period for 16bit 
+                             word width */
+#define I2S_WW8_HP   0x7  /* Word select half period for 8bit
+                             word width */
+
+#define WSMASK_HP        0X7FC /* Mask for WS half period bits */
+
+/**********************************************************************
+* i2s_tx_fifo register definitions
+**********************************************************************/
+#define I2S_FIFO_TX_WRITE(d)              (d)
+
+/**********************************************************************
+* i2s_rx_fifo register definitions
+**********************************************************************/
+#define I2S_FIFO_RX_WRITE(d)              (d)
+
+/**********************************************************************
+* i2s_stat register definitions
+**********************************************************************/
+#define I2S_IRQ_STAT     _BIT(0)
+#define I2S_DMA0_REQ     _BIT(1)
+#define I2S_DMA1_REQ     _BIT(2)
+
+#define I2S_RX_STATE_MASK      0x0000ff00
+#define I2S_TX_STATE_MASK      0x00ff0000
+
+/**********************************************************************
+* i2s_dma0 Configuration register definitions
+**********************************************************************/
+#define I2S_DMA0_RX_EN     _BIT(0)       /* Enable RX DMA1*/
+#define I2S_DMA0_TX_EN     _BIT(1)       /* Enable TX DMA1*/
+#define I2S_DMA0_RX_DEPTH(s)  _SBF(8,s)  /* Set the level for DMA1 
+                                            RX Request */
+#define I2S_DMA0_TX_DEPTH(s)  _SBF(16,s) /* Set the level for DMA1 
+                                            TX Request */
+
+/**********************************************************************
+* i2s_dma1 Configuration register definitions
+**********************************************************************/
+#define I2S_DMA1_RX_EN     _BIT(0)       /* Enable RX DMA1*/
+#define I2S_DMA1_TX_EN     _BIT(1)       /* Enable TX DMA1*/
+#define I2S_DMA1_RX_DEPTH(s)  _SBF(8,s)         /* Set the level for DMA1 
+                                            RX Request */
+#define I2S_DMA1_TX_DEPTH(s)  _SBF(16,s) /* Set the level for DMA1 
+                                            TX Request */
+
+/**********************************************************************
+* i2s_irq register definitions
+**********************************************************************/
+#define I2S_RX_IRQ_EN     _BIT(0)       /* Enable RX IRQ*/
+#define I2S_TX_IRQ_EN     _BIT(1)       /* Enable TX IRQ*/
+#define I2S_IRQ_RX_DEPTH(s)  _SBF(8,s)  /* valid values ar 0 to 7 */
+#define I2S_IRQ_TX_DEPTH(s)  _SBF(16,s) /* valid values ar 0 to 7 */
+
+/**********************************************************************
+* define audio rates for i2s_tx_rate/i2s_rx_rate register definitions
+**********************************************************************/
+
+#define A96KHZ104MHZ8BIT 0x7ed  // 7, 237
+#define A48KHZ104MHZ8BIT 0x3cb  // 3, 203
+#define A44KHZ104MHZ8BIT 0x14a  // 1, 74
+#define A32KHZ104MHZ8BIT 0x5fe // 5, 254
+#define A22KHZ104MHZ8BIT 0x194  // 1, 148
+#define A16KHZ104MHZ8BIT 0x1cb // 1, 203
+
+#define A96KHZ104MHZ16BIT 0xeed        //  14, 237
+#define A48KHZ104MHZ16BIT 0x7ED //  7, 237
+#define A44KHZ104MHZ16BIT 0x6dd //  6, 221     
+#define A32KHZ104MHZ16BIT 0x5fe //  5, 254
+#define A22KHZ104MHZ16BIT 0x14a //  1, 74
+#define A16KHZ104MHZ16BIT 0x2cb //  2, 203
+
+#define A96KHZ104MHZ32BIT 0x1ced// 28, 237
+#define A48KHZ104MHZ32BIT 0xeed // 14, 237 
+#define A44KHZ104MHZ32BIT 0xdf0 // 13, 240 
+#define A32KHZ104MHZ32BIT 0x57f        // 5, 127
+#define A22KHZ104MHZ32BIT 0x125 // 1, 37 
+#define A16KHZ104MHZ32BIT 0x5fe // 5, 254 
+
+/**********************************************************************
+* i2s_tx_rate register definitions
+**********************************************************************/
+#define I2S_SET_TX_RATE(d)          (d)
+
+/**********************************************************************
+* i2s_rx_rate register definitions
+**********************************************************************/
+#define I2S_SET_RX_RATE(d)          (d)
+
+/**********************************************************************
+* i2s channel select
+**********************************************************************/
+#define I2S_CH0        0
+#define I2S_CH1        1
+
+#endif /*  __ASM_ARCH_I2S_H */
diff --git a/arch/arm/mach-lpc32xx/include/mach/io.h b/arch/arm/mach-lpc32xx/include/mach/io.h
new file mode 100644 (file)
index 0000000..9b59ab5
--- /dev/null
@@ -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
diff --git a/arch/arm/mach-lpc32xx/include/mach/irqs.h b/arch/arm/mach-lpc32xx/include/mach/irqs.h
new file mode 100644 (file)
index 0000000..2667f52
--- /dev/null
@@ -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
diff --git a/arch/arm/mach-lpc32xx/include/mach/memory.h b/arch/arm/mach-lpc32xx/include/mach/memory.h
new file mode 100644 (file)
index 0000000..044e1ac
--- /dev/null
@@ -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
diff --git a/arch/arm/mach-lpc32xx/include/mach/platform.h b/arch/arm/mach-lpc32xx/include/mach/platform.h
new file mode 100644 (file)
index 0000000..14ea8d1
--- /dev/null
@@ -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
diff --git a/arch/arm/mach-lpc32xx/include/mach/sdcard.h b/arch/arm/mach-lpc32xx/include/mach/sdcard.h
new file mode 100644 (file)
index 0000000..cc4a6af
--- /dev/null
@@ -0,0 +1,177 @@
+/*
+ * asm-arm/arch-lpc32xx/sdcard.h
+ *
+ * Author: Kevin Wells <kevin.wells@nxp.com>
+ *
+ * Copyright (C) 2008 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef __ASM_ARCH_SDCARD_H
+#define __ASM_ARCH_SDCARD_H
+
+/**********************************************************************
+* SD Card controller register offsets
+**********************************************************************/
+
+#define SD_POWER(x)                    (x + 0x00)
+#define SD_CLOCK(x)                    (x + 0x04)
+#define SD_ARG(x)                      (x + 0x08)
+#define SD_CMD(x)                      (x + 0x10)
+#define SD_RESPCMD(x)                  (x + 0x14)
+#define SD_RESP(x)                     (x + 0x18)
+#define SD_DTIMER(x)                   (x + 0x28)
+#define SD_DLEN(x)                     (x + 0x2C)
+#define SD_DCTRL(x)                    (x + 0x30)
+#define SD_DCNT(x)                     (x + 0x34)
+#define SD_STATUS(x)                   (x + 0x38)
+#define SD_CLEAR(x)                    (x + 0x3C)
+#define SD_MASK0(x)                    (x + 0x40)
+#define SD_MASK1(x)                    (x + 0x44)
+#define SD_FIFOCNT(x)                  (x + 0x4C)
+#define SD_FIFO(x)                     (x + 0x80)
+
+/**********************************************************************
+* sd_power register definitions
+**********************************************************************/
+/* SD bit for enabling open drain mode (1) or pushpull mode (0) */
+#define SD_OPENDRAIN_EN            _BIT(6)
+/* SD power control mode: power off */
+#define SD_POWER_OFF_MODE          0x0
+/* SD power control mode: power up */
+#define SD_POWER_UP_MODE           0x2
+/* SD power control mode: power on */
+#define SD_POWER_ON_MODE           0x3
+/* SD power control mode mask */
+#define SD_POWER_MODE_MASK         0x3
+
+/**********************************************************************
+* sd_clock register definitions
+**********************************************************************/
+/* SD bit for enabling side bus mode */
+#define SD_WIDEBUSMODE_EN          _BIT(11)
+/* SD bit for enabling SDCLK clock bypass */
+#define SD_SDCLK_BYPASS            _BIT(10)
+/* SD bit for enabling clock throttling during idle states */
+#define SD_SDCLK_PWRSAVE           _BIT(9)
+/* SD bit for enabling the SD clock */
+#define SD_SDCLK_EN                _BIT(8)
+/* SD clock divider bit mask */
+#define SD_CLKDIV_MASK             0xFF
+
+/**********************************************************************
+* sd_cmd register definitions
+**********************************************************************/
+/* SD bit for enabling command path state machine */
+#define SD_CPST_EN                 _BIT(10)
+/* SD bit for wait for CMDPEND prior to sending command */
+#define SD_CMDPEND_WAIT            _BIT(9)
+/* SD bit for enabling card interrupt request (without timeout) */
+#define SD_INTERRUPT_EN            _BIT(8)
+/* SD bit for enabling 136-bit response support */
+#define SD_LONGRESP_EN             _BIT(7)
+/* SD bit for enabling response support */
+#define SD_RESPONSE                _BIT(6)
+/* SD command mask */
+#define SD_CMD_MASK                0x3F
+
+/**********************************************************************
+* sd_dctrl register definitions
+**********************************************************************/
+/* SD data transfer blocksize of 1 byte */
+#define SD_BLKSIZE_1BYTE           0x00
+/* SD data transfer blocksize of 2 bytes */
+#define SD_BLKSIZE_2BYTES          0x10
+/* SD data transfer blocksize of 4 bytes */
+#define SD_BLKSIZE_4BYTES          0x20
+/* SD data transfer blocksize of 8 bytes */
+#define SD_BLKSIZE_8BYTES          0x30
+/* SD data transfer blocksize of 16 bytes */
+#define SD_BLKSIZE_16BYTES         0x40
+/* SD data transfer blocksize of 32 bytes */
+#define SD_BLKSIZE_32BYTES         0x50
+/* SD data transfer blocksize of 64 bytes */
+#define SD_BLKSIZE_64BYTES         0x60
+/* SD data transfer blocksize of 128 bytes */
+#define SD_BLKSIZE_128BYTES        0x70
+/* SD data transfer blocksize of 256 bytes */
+#define SD_BLKSIZE_256BYTES        0x80
+/* SD data transfer blocksize of 512 bytes */
+#define SD_BLKSIZE_512BYTES        0x90
+/* SD data transfer blocksize of 1024 bytes */
+#define SD_BLKSIZE_1024BYTES       0xA0
+/* SD data transfer blocksize of 2048 bytes */
+#define SD_BLKSIZE_2048BYTES       0xB0
+/* SD bit for enabling DMA */
+#define SD_DMA_EN                  _BIT(3)
+/* SD bit for enabling a stream transfer */
+#define SD_STREAM_EN               _BIT(2)
+/* SD direction bit (1 = receive, 0 = transmit) */
+#define SD_DIR_FROMCARD            _BIT(1)
+/* SD data transfer enable bit */
+#define SD_DATATRANSFER_EN         _BIT(0)
+
+/**********************************************************************
+* sd_status register definitions
+* sd_clear register definitions (bits 0..10 only)
+* sd_mask0, sd_mask1 register definitions
+**********************************************************************/
+/* SD bit for data receive FIFO NOT empty status */
+#define SD_FIFO_RXDATA_AVAIL       _BIT(21)
+/* SD bit for data transmit FIFO NOT empty status */
+#define SD_FIFO_TXDATA_AVAIL       _BIT(20)
+/* SD bit for data receive FIFO empty status */
+#define SD_FIFO_RXDATA_EMPTY       _BIT(19)
+/* SD bit for data transmit FIFO empty status */
+#define SD_FIFO_TXDATA_EMPTY       _BIT(18)
+/* SD bit for data receive FIFO full status */
+#define SD_FIFO_RXDATA_FULL        _BIT(17)
+/* SD bit for data transmit FIFO full status */
+#define SD_FIFO_TXDATA_FULL        _BIT(16)
+/* SD bit for data receive FIFO half-full status */
+#define SD_FIFO_RXDATA_HFULL       _BIT(15)
+/* SD bit for data transmit FIFO half-empty status */
+#define SD_FIFO_TXDATA_HEMPTY      _BIT(14)
+/* SD bit for data receive in progress status */
+#define SD_RX_INPROGRESS           _BIT(13)
+/* SD bit for data transmit in progress status */
+#define SD_TX_INPROGRESS           _BIT(12)
+/* SD bit for command transfer in progress status */
+#define SD_CMD_INPROGRESS          _BIT(11)
+/* SD bit for data block send/received complete (CRC good) status */
+#define SD_DATABLK_END             _BIT(10)
+/* SD bit for start bit detection error status */
+#define SD_STARTBIT_ERR            _BIT(9)
+/* SD bit for data end (data counter is 0) status */
+#define SD_DATA_END                _BIT(8)
+/* SD bit for command sent status */
+#define SD_CMD_SENT                _BIT(7)
+/* SD bit for command response received (CRC good) status */
+#define SD_CMD_RESP_RECEIVED       _BIT(6)
+/* SD bit for data receive FIFO overflow status */
+#define SD_FIFO_RXDATA_OFLOW       _BIT(5)
+/* SD bit for data transmit FIFO underflow status */
+#define SD_FIFO_TXDATA_UFLOW       _BIT(4)
+/* SD bit for data timeout status */
+#define SD_DATA_TIMEOUT            _BIT(3)
+/* SD bit for command timeout status */
+#define SD_CMD_TIMEOUT             _BIT(2)
+/* SD bit for data CRC failure status */
+#define SD_DATA_CRC_FAIL           _BIT(1)
+/* SD bit for command CRC failure status */
+#define SD_CMD_CRC_FAIL            _BIT(0)
+
+#endif /* __ASM_ARCH_SDCARD_H */
diff --git a/arch/arm/mach-lpc32xx/include/mach/slcnand.h b/arch/arm/mach-lpc32xx/include/mach/slcnand.h
new file mode 100644 (file)
index 0000000..6d9c896
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+ * asm-arm/arch-lpc32xx/slcnand.h
+ *
+ * Author: Kevin Wells <kevin.wells@nxp.com>
+ *
+ * Copyright (C) 2008 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef __ASM_ARCH_SLCNAND_H
+#define __ASM_ARCH_SLCNAND_H
+
+/**********************************************************************
+* SLC NAND controller register offsets
+**********************************************************************/
+
+#define SLC_DATA(x)                    (x + 0x000)
+#define SLC_ADDR(x)                    (x + 0x004)
+#define SLC_CMD(x)                     (x + 0x008)
+#define SLC_STOP(x)                    (x + 0x00C)
+#define SLC_CTRL(x)                    (x + 0x010)
+#define SLC_CFG(x)                     (x + 0x014)
+#define SLC_STAT(x)                    (x + 0x018)
+#define SLC_INT_STAT(x)                        (x + 0x01C)
+#define SLC_IEN(x)                     (x + 0x020)
+#define SLC_ISR(x)                     (x + 0x024)
+#define SLC_ICR(x)                     (x + 0x028)
+#define SLC_TAC(x)                     (x + 0x02C)
+#define SLC_TC(x)                      (x + 0x030)
+#define SLC_ECC(x)                     (x + 0x034)
+#define SLC_DMA_DATA(x)                        (x + 0x038)
+
+/**********************************************************************
+* slc_ctrl register definitions
+**********************************************************************/
+#define SLCCTRL_SW_RESET    _BIT(2) /* Reset the NAND controller bit */
+#define SLCCTRL_ECC_CLEAR   _BIT(1) /* Reset ECC bit */
+#define SLCCTRL_DMA_START   _BIT(0) /* Start DMA channel bit */
+
+/**********************************************************************
+* slc_cfg register definitions
+**********************************************************************/
+#define SLCCFG_CE_LOW       _BIT(5) /* Force CE low bit */
+#define SLCCFG_DMA_ECC      _BIT(4) /* Enable DMA ECC bit */
+#define SLCCFG_ECC_EN       _BIT(3) /* ECC enable bit */
+#define SLCCFG_DMA_BURST    _BIT(2) /* DMA burst bit */
+#define SLCCFG_DMA_DIR      _BIT(1) /* DMA write(0)/read(1) bit */
+#define SLCCFG_WIDTH        _BIT(0) /* External device width, 0=8bit */
+
+/**********************************************************************
+* slc_stat register definitions
+**********************************************************************/
+#define SLCSTAT_DMA_FIFO    _BIT(2) /* DMA FIFO has data bit */
+#define SLCSTAT_SLC_FIFO    _BIT(1) /* SLC FIFO has data bit */
+#define SLCSTAT_NAND_READY  _BIT(0) /* NAND device is ready bit */
+
+/**********************************************************************
+* slc_int_stat, slc_ien, slc_isr, and slc_icr register definitions
+**********************************************************************/
+#define SLCSTAT_INT_TC      _BIT(1) /* Transfer count bit */
+#define SLCSTAT_INT_RDY_EN  _BIT(0) /* Ready interrupt bit */
+
+/**********************************************************************
+* slc_tac register definitions
+**********************************************************************/
+/* Clock setting for RDY write sample wait time in 2*n clocks */
+#define SLCTAC_WDR(n)       (((n) & 0xF) << 28)
+/* Write pulse width in clocks cycles, 1 to 16 clocks */
+#define SLCTAC_WWIDTH(n)    (((n) & 0xF) << 24)
+/* Write hold time of control and data signals, 1 to 16 clocks */
+#define SLCTAC_WHOLD(n)     (((n) & 0xF) << 20)
+/* Write setup time of control and data signals, 1 to 16 clocks */
+#define SLCTAC_WSETUP(n)    (((n) & 0xF) << 16)
+/* Clock setting for RDY read sample wait time in 2*n clocks */
+#define SLCTAC_RDR(n)       (((n) & 0xF) << 12)
+/* Read pulse width in clocks cycles, 1 to 16 clocks */
+#define SLCTAC_RWIDTH(n)    (((n) & 0xF) << 8)
+/* Read hold time of control and data signals, 1 to 16 clocks */
+#define SLCTAC_RHOLD(n)     (((n) & 0xF) << 4)
+/* Read setup time of control and data signals, 1 to 16 clocks */
+#define SLCTAC_RSETUP(n)    (((n) & 0xF) << 0)
+
+/**********************************************************************
+* slc_ecc register definitions
+**********************************************************************/
+/* ECC line party fetch macro */
+#define SLCECC_TO_LINEPAR(n) (((n) >> 6) & 0x7FFF)
+#define SLCECC_TO_COLPAR(n)  ((n) & 0x3F)
+
+#endif /* __ASM_ARCH_SLCNAND_H */
diff --git a/arch/arm/mach-lpc32xx/include/mach/system.h b/arch/arm/mach-lpc32xx/include/mach/system.h
new file mode 100644 (file)
index 0000000..df3b0de
--- /dev/null
@@ -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
diff --git a/arch/arm/mach-lpc32xx/include/mach/timex.h b/arch/arm/mach-lpc32xx/include/mach/timex.h
new file mode 100644 (file)
index 0000000..8d4066b
--- /dev/null
@@ -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
diff --git a/arch/arm/mach-lpc32xx/include/mach/uncompress.h b/arch/arm/mach-lpc32xx/include/mach/uncompress.h
new file mode 100644 (file)
index 0000000..c142487
--- /dev/null
@@ -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
diff --git a/arch/arm/mach-lpc32xx/include/mach/usbd.h b/arch/arm/mach-lpc32xx/include/mach/usbd.h
new file mode 100644 (file)
index 0000000..f10efae
--- /dev/null
@@ -0,0 +1,291 @@
+/*
+ * asm-arm/arch-lpc32xx/usbd.h
+ *
+ * Author: Kevin Wells <kevin.wells@nxp.com>
+ *
+ * Copyright (C) 2008 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef __ASM_ARCH_USBD_H
+#define __ASM_ARCH_USBD_H
+
+/**********************************************************************
+* USE device controller register offsets
+**********************************************************************/
+
+#define USBD_DEVINTST(x)       (x + 0x200)
+#define USBD_DEVINTEN(x)       (x + 0x204)
+#define USBD_DEVINTCLR(x)      (x + 0x208)
+#define USBD_DEVINTSET(x)      (x + 0x20C)
+#define USBD_CMDCODE(x)                (x + 0x210)
+#define USBD_CMDDATA(x)                (x + 0x214)
+#define USBD_RXDATA(x)         (x + 0x218)
+#define USBD_TXDATA(x)         (x + 0x21C)
+#define USBD_RXPLEN(x)         (x + 0x220)
+#define USBD_TXPLEN(x)         (x + 0x224)
+#define USBD_CTRL(x)           (x + 0x228)
+#define USBD_DEVINTPRI(x)      (x + 0x22C)
+#define USBD_EPINTST(x)                (x + 0x230)
+#define USBD_EPINTEN(x)                (x + 0x234)
+#define USBD_EPINTCLR(x)       (x + 0x238)
+#define USBD_EPINTSET(x)       (x + 0x23C)
+#define USBD_EPINTPRI(x)       (x + 0x240)
+#define USBD_REEP(x)           (x + 0x244)
+#define USBD_EPIND(x)          (x + 0x248)
+#define USBD_EPMAXPSIZE(x)     (x + 0x24C)
+/* DMA support registers only below */
+/* Set, clear, or get enabled state of the DMA request status. If
+   enabled, an IN or OUT token will start a DMA transfer for the EP */
+#define USBD_DMARST(x)         (x + 0x250)
+#define USBD_DMARCLR(x)                (x + 0x254)
+#define USBD_DMARSET(x)                (x + 0x258)
+/* DMA UDCA head pointer */
+#define USBD_UDCAH(x)          (x + 0x280)
+/* EP DMA status, enable, and disable. This is used to specifically
+   enabled or disable DMA for a specific EP */
+#define USBD_EPDMAST(x)                (x + 0x284)
+#define USBD_EPDMAEN(x)                (x + 0x288)
+#define USBD_EPDMADIS(x)       (x + 0x28C)
+/* DMA master interrupts enable and pending interrupts */
+#define USBD_DMAINTST(x)       (x + 0x290)
+#define USBD_DMAINTEN(x)       (x + 0x294)
+/* DMA end of transfer interrupt enable, disable, status */
+#define USBD_EOTINTST(x)       (x + 0x2A0)
+#define USBD_EOTINTCLR(x)      (x + 0x2A4)
+#define USBD_EOTINTSET(x)      (x + 0x2A8)
+/* New DD request interrupt enable, disable, status */
+#define USBD_NDDRTINTST(x)     (x + 0x2AC)
+#define USBD_NDDRTINTCLR(x)    (x + 0x2B0)
+#define USBD_NDDRTINTSET(x)    (x + 0x2B4)
+/* DMA error interrupt enable, disable, status */
+#define USBD_SYSERRTINTST(x)   (x + 0x2B8)
+#define USBD_SYSERRTINTCLR(x)  (x + 0x2BC)
+#define USBD_SYSERRTINTSET(x)  (x + 0x2C0)
+
+/**********************************************************************
+* USBD_DEVINTST/USBD_DEVINTEN/USBD_DEVINTCLR/USBD_DEVINTSET/
+* USBD_DEVINTPRI register definitions
+**********************************************************************/
+#define USBD_ERR_INT               (1 << 9)
+#define USBD_EP_RLZED              (1 << 8)
+#define USBD_TXENDPKT              (1 << 7)
+#define USBD_RXENDPKT              (1 << 6)
+#define USBD_CDFULL                (1 << 5)
+#define USBD_CCEMPTY               (1 << 4)
+#define USBD_DEV_STAT              (1 << 3)
+#define USBD_EP_SLOW               (1 << 2)
+#define USBD_EP_FAST               (1 << 1)
+#define USBD_FRAME                 (1 << 0)
+
+/**********************************************************************
+* USBD_EPINTST/USBD_EPINTEN/USBD_EPINTCLR/USBD_EPINTSET/
+* USBD_EPINTPRI register definitions
+**********************************************************************/
+/* End point selection macro (RX) */
+#define USBD_RX_EP_SEL(e)          (1 << ((e) << 1))
+
+/* End point selection macro (TX) */
+#define USBD_TX_EP_SEL(e)          (1 << (((e) << 1) + 1))
+
+/**********************************************************************
+* USBD_REEP/USBD_DMARST/USBD_DMARCLR/USBD_DMARSET/USBD_EPDMAST/
+* USBD_EPDMAEN/USBD_EPDMADIS/
+* USBD_NDDRTINTST/USBD_NDDRTINTCLR/USBD_NDDRTINTSET/
+* USBD_EOTINTST/USBD_EOTINTCLR/USBD_EOTINTSET/
+* USBD_SYSERRTINTST/USBD_SYSERRTINTCLR/USBD_SYSERRTINTSET
+* register definitions
+**********************************************************************/
+/* Endpoint selection macro */
+#define USBD_EP_SEL(e)              (1 << (e))
+
+/**********************************************************************
+SBD_DMAINTST/USBD_DMAINTEN
+**********************************************************************/
+#define USBD_SYS_ERR_INT            (1 << 2)
+#define USBD_NEW_DD_INT             (1 << 1)
+#define USBD_EOT_INT                (1 << 0)
+
+/**********************************************************************
+* USBD_RXPLEN register definitions
+**********************************************************************/
+#define USBD_PKT_RDY               (1 << 11)
+#define USBD_DV                    (1 << 10)
+#define USBD_PK_LEN_MASK           0x3FF
+
+/**********************************************************************
+* USBD_CTRL register definitions
+**********************************************************************/
+#define USBD_LOG_ENDPOINT(e)      ((e) << 2)
+#define USBD_WR_EN                (1 << 1)
+#define USBD_RD_EN                (1 << 0)
+
+/**********************************************************************
+* USBD_CMDCODE register definitions
+**********************************************************************/
+#define USBD_CMD_CODE(c)          ((c) << 16)
+#define USBD_CMD_PHASE(p)         ((p) << 8)
+
+/**********************************************************************
+* USBD_DMARST/USBD_DMARCLR/USBD_DMARSET register definitions
+**********************************************************************/
+#define USBD_DMAEP(e)             (1 << (e))
+
+/* DD (DMA Descriptor) structure, requires word alignment */
+struct lpc32xx_usbd_dd
+{
+       u32 *dd_next;
+       u32 dd_setup;
+       u32 dd_buffer_addr;
+       u32 dd_status;
+       u32 dd_iso_ps_mem_addr;
+};
+
+/* dd_setup bit defines */
+#define DD_SETUP_ATLE_DMA_MODE 0x01
+#define DD_SETUP_NEXT_DD_VALID 0x04
+#define DD_SETUP_ISO_EP        0x10
+#define DD_SETUP_PACKETLEN(n)  (((n) & 0x7FF) << 5)
+#define DD_SETUP_DMALENBYTES(n)(((n) & 0xFFFF) << 16)
+
+/* dd_status bit defines */
+#define DD_STATUS_DD_RETIRED   0x01
+#define DD_STATUS_STS_MASK     0x1E
+#define DD_STATUS_STS_NS       0x00 /* Not serviced */
+#define DD_STATUS_STS_BS       0x02 /* Being serviced */
+#define DD_STATUS_STS_NC       0x04 /* Normal completion */
+#define DD_STATUS_STS_DUR      0x06 /* Data underrun (short packet) */
+#define DD_STATUS_STS_DOR      0x08 /* Data overrun */
+#define DD_STATUS_STS_SE       0x12 /* System error */
+#define DD_STATUS_PKT_VAL      0x20 /* Packet valid */
+#define DD_STATUS_LSB_EX       0x40 /* LS byte extracted (ATLE) */
+#define DD_STATUS_MSB_EX       0x80 /* MS byte extracted (ATLE) */
+#define DD_STATUS_MLEN(n)      (((n) >> 8) & 0x3F)
+#define DD_STATUS_CURDMACNT(n) (((n) >> 16) & 0xFFFF)
+
+/*
+ *
+ * Protocol engine bits below
+ *
+ */
+/* Device Interrupt Bit Definitions */
+#define FRAME_INT           0x00000001
+#define EP_FAST_INT         0x00000002
+#define EP_SLOW_INT         0x00000004
+#define DEV_STAT_INT        0x00000008
+#define CCEMTY_INT          0x00000010
+#define CDFULL_INT          0x00000020
+#define RxENDPKT_INT        0x00000040
+#define TxENDPKT_INT        0x00000080
+#define EP_RLZED_INT        0x00000100
+#define ERR_INT             0x00000200
+
+/* Rx & Tx Packet Length Definitions */
+#define PKT_LNGTH_MASK      0x000003FF
+#define PKT_DV              0x00000400
+#define PKT_RDY             0x00000800
+
+/* USB Control Definitions */
+#define CTRL_RD_EN          0x00000001
+#define CTRL_WR_EN          0x00000002
+
+/* Command Codes */
+#define CMD_SET_ADDR        0x00D00500
+#define CMD_CFG_DEV         0x00D80500
+#define CMD_SET_MODE        0x00F30500
+#define CMD_RD_FRAME        0x00F50500
+#define DAT_RD_FRAME        0x00F50200
+#define CMD_RD_TEST         0x00FD0500
+#define DAT_RD_TEST         0x00FD0200
+#define CMD_SET_DEV_STAT    0x00FE0500
+#define CMD_GET_DEV_STAT    0x00FE0500
+#define DAT_GET_DEV_STAT    0x00FE0200
+#define CMD_GET_ERR_CODE    0x00FF0500
+#define DAT_GET_ERR_CODE    0x00FF0200
+#define CMD_RD_ERR_STAT     0x00FB0500
+#define DAT_RD_ERR_STAT     0x00FB0200
+#define DAT_WR_BYTE(x)     (0x00000100 | ((x) << 16))
+#define CMD_SEL_EP(x)      (0x00000500 | ((x) << 16))
+#define DAT_SEL_EP(x)      (0x00000200 | ((x) << 16))
+#define CMD_SEL_EP_CLRI(x) (0x00400500 | ((x) << 16))
+#define DAT_SEL_EP_CLRI(x) (0x00400200 | ((x) << 16))
+#define CMD_SET_EP_STAT(x) (0x00400500 | ((x) << 16))
+#define CMD_CLR_BUF         0x00F20500
+#define DAT_CLR_BUF         0x00F20200
+#define CMD_VALID_BUF       0x00FA0500
+
+/* Device Address Register Definitions */
+#define DEV_ADDR_MASK       0x7F
+#define DEV_EN              0x80
+
+/* Device Configure Register Definitions */
+#define CONF_DVICE          0x01
+
+/* Device Mode Register Definitions */
+#define AP_CLK              0x01
+#define INAK_CI             0x02
+#define INAK_CO             0x04
+#define INAK_II             0x08
+#define INAK_IO             0x10
+#define INAK_BI             0x20
+#define INAK_BO             0x40
+
+/* Device Status Register Definitions */
+#define DEV_CON             0x01
+#define DEV_CON_CH          0x02
+#define DEV_SUS             0x04
+#define DEV_SUS_CH          0x08
+#define DEV_RST             0x10
+
+/* Error Code Register Definitions */
+#define ERR_EC_MASK         0x0F
+#define ERR_EA              0x10
+
+/* Error Status Register Definitions */
+#define ERR_PID             0x01
+#define ERR_UEPKT           0x02
+#define ERR_DCRC            0x04
+#define ERR_TIMOUT          0x08
+#define ERR_EOP             0x10
+#define ERR_B_OVRN          0x20
+#define ERR_BTSTF           0x40
+#define ERR_TGL             0x80
+
+/* Endpoint Select Register Definitions */
+#define EP_SEL_F            0x01
+#define EP_SEL_ST           0x02
+#define EP_SEL_STP          0x04
+#define EP_SEL_PO           0x08
+#define EP_SEL_EPN          0x10
+#define EP_SEL_B_1_FULL     0x20
+#define EP_SEL_B_2_FULL     0x40
+
+/* Endpoint Status Register Definitions */
+#define EP_STAT_ST          0x01
+#define EP_STAT_DA          0x20
+#define EP_STAT_RF_MO       0x40
+#define EP_STAT_CND_ST      0x80
+
+/* Clear Buffer Register Definitions */
+#define CLR_BUF_PO          0x01
+
+/* DMA Interrupt Bit Definitions */
+#define EOT_INT             0x01
+#define NDD_REQ_INT         0x02
+#define SYS_ERR_INT         0x04
+
+
+#endif /* __ASM_ARCH_USBD_H */
diff --git a/arch/arm/mach-lpc32xx/include/mach/vmalloc.h b/arch/arm/mach-lpc32xx/include/mach/vmalloc.h
new file mode 100644 (file)
index 0000000..d1d936c
--- /dev/null
@@ -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
diff --git a/arch/arm/mach-lpc32xx/irq.c b/arch/arm/mach-lpc32xx/irq.c
new file mode 100644 (file)
index 0000000..c7df879
--- /dev/null
@@ -0,0 +1,429 @@
+/*
+ * 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;
+       }
+
+       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);
+}
diff --git a/arch/arm/mach-lpc32xx/phy3250.c b/arch/arm/mach-lpc32xx/phy3250.c
new file mode 100644 (file)
index 0000000..56f24f8
--- /dev/null
@@ -0,0 +1,670 @@
+/*
+ * 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/input.h>
+#include <linux/amba/bus.h>
+#include <linux/amba/clcd.h>
+#include <linux/amba/pl022.h>
+#include <linux/amba/mmci.h>
+#include <sound/uda1380.h>
+
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+
+#include <mach/hardware.h>
+#include <mach/platform.h>
+#include <mach/board.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)
+#define NAND_WP_GPIO           LPC32XX_GPIO(LPC32XX_GPO_P3_GRP, 19)
+#define        MMC_PWR_ENABLE_GPIO     LPC32XX_GPIO(LPC32XX_GPO_P3_GRP, 5)
+#define        MMC_STATUS_GPIO         LPC32XX_GPIO(LPC32XX_GPIO_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);
+
+/*
+ * Platform Data for UDA1380 Audiocodec.
+ * As there are no GPIOs for codec power & reset pins,
+ * dummy GPIO numbers are used.
+ */
+static struct uda1380_platform_data uda1380_info = {
+        .gpio_power = LPC32XX_GPIO(LPC32XX_GPO_P3_GRP,10),
+        .gpio_reset = LPC32XX_GPIO(LPC32XX_GPO_P3_GRP,2),
+        .dac_clk    = UDA1380_DAC_CLK_WSPLL,
+};
+
+static struct i2c_board_info __initdata phy3250_i2c_board_info[] = {
+       {
+               I2C_BOARD_INFO("pcf8563", 0x51),
+       },
+        {
+                I2C_BOARD_INFO("uda1380", 0x18),
+                .platform_data = &uda1380_info,
+        },
+};
+
+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,
+};
+
+/*
+ * Board specific key scanner driver data
+ */
+#define PHY3250_KMATRIX_SIZE 1
+static int lpc32xx_keymaps[] = {
+       KEY_1,  /* 1, 1 */
+};
+
+static struct lpc32XX_kscan_cfg lpc32xx_kscancfg = {
+       .matrix_sz      = PHY3250_KMATRIX_SIZE,
+       .keymap         = lpc32xx_keymaps,
+       /* About a 30Hz scan rate based on a 32KHz clock */
+       .deb_clks       = 3,
+       .scan_delay     = 34,
+};
+
+static struct resource kscan_resources[] = {
+       [0] = {
+               .start  = LPC32XX_KSCAN_BASE,
+               .end    = LPC32XX_KSCAN_BASE + SZ_4K - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = IRQ_LPC32XX_KEY,
+               .end    = IRQ_LPC32XX_KEY,
+               .flags  = IORESOURCE_IRQ,
+       },
+
+};
+
+static struct platform_device lpc32xx_kscan_device = {
+       .name           = "lpc32xx_keys",
+       .id             = 0,
+       .dev            = {
+               .platform_data  = &lpc32xx_kscancfg,
+       },
+       .num_resources  = ARRAY_SIZE(kscan_resources),
+       .resource       = kscan_resources,
+};
+
+#if defined (CONFIG_MMC_ARMMMCI)
+/*
+ * Returns 0 when card is removed, !0 when installed
+ */
+unsigned int mmc_status(struct device *dev)
+{
+       return gpio_get_value(MMC_STATUS_GPIO) & 1;
+}
+
+/*
+ * Enable or disable SD slot power
+ */
+void mmc_power_enable(int enable)
+{
+       if (enable != 0)
+               gpio_set_value(MMC_PWR_ENABLE_GPIO,1);
+       else
+               gpio_set_value(MMC_PWR_ENABLE_GPIO,0);
+}
+
+/*
+ * Board specific MMC driver data
+ */
+struct mmci_platform_data lpc32xx_plat_data = {
+        .ocr_mask       = MMC_VDD_30_31|MMC_VDD_31_32|MMC_VDD_32_33|MMC_VDD_33_34,
+        .status         = mmc_status,
+       .capabilities   = MMC_CAP_4_BIT_DATA,
+        .gpio_wp        = -1,
+        .gpio_cd        = -1,
+};
+
+/*
+ * SD card controller resources
+ */
+struct amba_device lpc32xx_mmc_device = {
+        .dev                            = {
+                .coherent_dma_mask      = ~0,
+                .init_name                 = "dev:mmc0",
+                .platform_data          = &lpc32xx_plat_data,
+        },
+        .res                            = {
+                .start                  = LPC32XX_SD_BASE,
+                .end                    = (LPC32XX_SD_BASE + SZ_4K - 1),
+                .flags                  = IORESOURCE_MEM,
+        },
+        .dma_mask                       = ~0,
+        .irq                            = {IRQ_LPC32XX_SD0, IRQ_LPC32XX_SD1},
+};
+#endif
+
+
+#if defined(CONFIG_MTD_NAND_SLC_LPC32XX)
+/*
+ * Board specific NAND setup data
+ */
+static int nandwp_enable(int enable)
+{
+        if (enable != 0)
+               gpio_set_value(NAND_WP_GPIO,0);
+        else 
+               gpio_set_value(NAND_WP_GPIO,1);
+
+        return 1;
+}
+#define BLK_SIZE (512 * 32)
+static struct mtd_partition __initdata phy3250_nand_partition[] = {
+        {
+                .name   = "phy3250-boot",
+                .offset = 0,
+                .size   = (BLK_SIZE * 90)
+        },
+        {
+                .name   = "phy3250-ubt-prms",
+                .offset = MTDPART_OFS_APPEND,
+                .size   = (BLK_SIZE * 10)
+        },
+        {
+                .name   = "phy3250-kernel",
+                .offset = MTDPART_OFS_APPEND,
+                .size   = (BLK_SIZE * 256)
+        },
+        {
+                .name   = "phy3250-rootfs",
+                .offset = MTDPART_OFS_APPEND,
+                .size   = MTDPART_SIZ_FULL
+        },
+};
+static struct mtd_partition * __init phy3250_nand_partitions(int size, int *num_partitions)
+{
+        *num_partitions = ARRAY_SIZE(phy3250_nand_partition);
+        return phy3250_nand_partition;
+}
+struct lpc32XX_nand_cfg lpc32xx_nandcfg =
+{
+        .wdr_clks               = 3,
+        .wwidth                 = 28571428,
+        .whold                  = 100000000,
+        .wsetup                 = 66666666,
+        .rdr_clks               = 3,
+        .rwidth                 = 28571428,
+        .rhold                  = 100000000,
+        .rsetup                 = 66666666,
+        .use16bus               = 0,
+        .enable_write_prot      = nandwp_enable,
+        .partition_info         = phy3250_nand_partitions,
+};
+
+/*
+ * SLC NAND resources
+ */
+static struct resource slc_nand_resources[] = {
+        [0] = {
+                .start  = LPC32XX_SLC_BASE,
+                .end    = LPC32XX_SLC_BASE + SZ_4K - 1,
+                .flags  = IORESOURCE_MEM,
+        },
+
+        [1] = {
+                .start  = IRQ_LPC32XX_FLASH,
+                .end    = IRQ_LPC32XX_FLASH,
+                .flags  = IORESOURCE_IRQ,
+        },
+
+};
+static struct platform_device lpc32xx_slc_nand_device = {
+        .name           = "lpc32xx-nand",
+        .id             = 0,
+        .dev            = {
+                                .platform_data  = &lpc32xx_nandcfg,
+        },
+        .num_resources  = ARRAY_SIZE(slc_nand_resources),
+        .resource       = slc_nand_resources,
+};
+#endif
+
+/*
+ * Network Support
+ */
+static struct lpc_net_cfg lpc32xx_netdata =
+{
+       .phy_irq        = -1,
+       .phy_mask       = 0xFFFFFFF0,
+};
+
+static struct resource net_resources[] = {
+       [0] = {
+               .start  = LPC32XX_ETHERNET_BASE,
+               .end    = LPC32XX_ETHERNET_BASE + SZ_4K - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+
+       [1] = {
+               .start  = IRQ_LPC32XX_ETHERNET,
+               .end    = IRQ_LPC32XX_ETHERNET,
+               .flags  = IORESOURCE_IRQ,
+       },
+
+};
+
+static u64 lpc32xx_mac_dma_mask = 0xffffffffUL;
+static struct platform_device lpc32xx_net_device = {
+       .name           = "lpc-net",
+       .id             = 0,
+       .dev            = {
+               .dma_mask = &lpc32xx_mac_dma_mask,
+               .coherent_dma_mask = 0xffffffffUL,
+               .platform_data  = &lpc32xx_netdata,
+       },
+       .num_resources  = ARRAY_SIZE(net_resources),
+       .resource       = net_resources,
+};
+
+static struct platform_device *phy3250_devs[] __initdata = {
+       &lpc32xx_i2c0_device,
+       &lpc32xx_i2c1_device,
+       &lpc32xx_i2c2_device,
+       &lpc32xx_watchdog_device,
+       &lpc32xx_gpio_led_device,
+       &lpc32xx_rtc_device,
+       &lpc32xx_tsc_device,
+       &lpc32xx_kscan_device,
+       &lpc32xx_net_device,
+#if defined(CONFIG_MTD_NAND_SLC_LPC32XX)
+       &lpc32xx_slc_nand_device,
+#endif
+#if defined(CONFIG_USB_OHCI_HCD)
+       &lpc32xx_ohci_device,
+#endif
+#if defined(CONFIG_USB_GADGET_LPC32XX)
+       &lpc32xx_usbd_device,
+#endif
+};
+
+static struct amba_device *amba_devs[] __initdata = {
+       &lpc32xx_clcd_device,
+       &lpc32xx_ssp0_device,
+#if defined(CONFIG_MMC_ARMMMCI)
+       &lpc32xx_mmc_device,
+#endif
+};
+
+/*
+ * 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);
+
+#if defined (CONFIG_MMC_ARMMMCI)
+        /* Enable SD slot power */
+        mmc_power_enable(1);
+#endif
+
+       /* 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
+        */
+#if defined(CONFIG_MMC_ARMMMCI)
+        tmp = __raw_readl(LPC32XX_CLKPWR_MS_CTRL);
+        tmp |= LPC32XX_CLKPWR_MSCARD_SDCARD_EN | LPC32XX_CLKPWR_MSCARD_MSDIO_PU_EN;
+        __raw_writel(tmp, LPC32XX_CLKPWR_MS_CTRL);
+#endif
+
+#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
+
+/* For backwards compatibility with older bootloaders only */
+MACHINE_START(LPC3XXX, "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
diff --git a/arch/arm/mach-lpc32xx/pm.c b/arch/arm/mach-lpc32xx/pm.c
new file mode 100644 (file)
index 0000000..a6e2aed
--- /dev/null
@@ -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);
diff --git a/arch/arm/mach-lpc32xx/serial.c b/arch/arm/mach-lpc32xx/serial.c
new file mode 100644 (file)
index 0000000..a0e9ab4
--- /dev/null
@@ -0,0 +1,241 @@
+/*
+ * 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,
+       },
+};
+
+/* High speed serial ports */
+static struct uart_port serial_hspd_platform_data[] = {
+#ifdef CONFIG_ARCH_LPC32XX_HSUART1_SELECT
+       {
+               .membase        = io_p2v(LPC32XX_HS_UART1_BASE),
+               .mapbase        = LPC32XX_HS_UART1_BASE,
+               .irq            = IRQ_LPC32XX_UART_IIR1,
+               .uartclk        = LPC32XX_MAIN_OSC_FREQ,
+               .regshift       = 2,
+               .iotype         = UPIO_MEM32,
+               .flags          = UPF_BOOT_AUTOCONF,
+       },
+#endif
+#ifdef CONFIG_ARCH_LPC32XX_HSUART2_SELECT
+       {
+               .membase        = io_p2v(LPC32XX_HS_UART2_BASE),
+               .mapbase        = LPC32XX_HS_UART2_BASE,
+               .irq            = IRQ_LPC32XX_UART_IIR2,
+               .uartclk        = LPC32XX_MAIN_OSC_FREQ,
+               .regshift       = 2,
+               .iotype         = UPIO_MEM32,
+               .flags          = UPF_BOOT_AUTOCONF,
+       },
+#endif
+#ifdef CONFIG_ARCH_LPC32XX_HSUART7_SELECT
+       {
+               .membase        = io_p2v(LPC32XX_HS_UART7_BASE),
+               .mapbase        = LPC32XX_HS_UART7_BASE,
+               .irq            = IRQ_LPC32XX_UART_IIR7,
+               .uartclk        = LPC32XX_MAIN_OSC_FREQ,
+               .regshift       = 2,
+               .iotype         = UPIO_MEM32,
+               .flags          = UPF_BOOT_AUTOCONF,
+       },
+#endif
+       { },
+};
+
+static struct platform_device serial_hspd_platform_device = {
+       .name                   = "lpc32xx_hsuart",
+       .id                     = 0,
+       .dev                    = {
+               .platform_data  = serial_hspd_platform_data,
+       },
+};
+
+static struct platform_device *lpc32xx_serial_devs[] __initdata = {
+       &serial_std_platform_device,
+       &serial_hspd_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));
+       }
+
+        /* Setup of HSUART devices */
+        for (i = 0; i < ARRAY_SIZE(serial_hspd_platform_data); i++)
+                serial_hspd_platform_data[i].line = i;
+
+       /* 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));
+}
diff --git a/arch/arm/mach-lpc32xx/suspend.S b/arch/arm/mach-lpc32xx/suspend.S
new file mode 100644 (file)
index 0000000..374f9f0
--- /dev/null
@@ -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
diff --git a/arch/arm/mach-lpc32xx/timer.c b/arch/arm/mach-lpc32xx/timer.c
new file mode 100644 (file)
index 0000000..630dd4a
--- /dev/null
@@ -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,
+};
+
index 9c6170c..1f76dd4 100644 (file)
@@ -477,7 +477,7 @@ config I2C_PASEMI
 
 config I2C_PNX
        tristate "I2C bus support for Philips PNX targets"
-       depends on ARCH_PNX4008
+       depends on ARCH_PNX4008 || ARCH_LPC32XX
        help
          This driver supports the Philips IP3204 I2C IP block master and/or
          slave controller
index 64c1023..69fcf0b 100644 (file)
@@ -273,6 +273,15 @@ config KEYBOARD_LOCOMO
          To compile this driver as a module, choose M here: the
          module will be called locomokbd.
 
+config KEYBOARD_LPC32XX
+        tristate "LPC32XX matrix key scanner support"
+        depends on ARCH_LPC32XX
+        help
+          Say Y here if you want to use the LPC32XX keyscanner interface.
+
+          To compile this driver as a module, choose M here: the
+          module will be called lpc32xx_keys.
+
 config KEYBOARD_MAPLE
        tristate "Maple bus keyboard"
        depends on SH_DREAMCAST && MAPLE
index 706c6b5..34b079f 100644 (file)
@@ -23,6 +23,7 @@ obj-$(CONFIG_KEYBOARD_HP7XX)          += jornada720_kbd.o
 obj-$(CONFIG_KEYBOARD_LKKBD)           += lkkbd.o
 obj-$(CONFIG_KEYBOARD_LM8323)          += lm8323.o
 obj-$(CONFIG_KEYBOARD_LOCOMO)          += locomokbd.o
+obj-$(CONFIG_KEYBOARD_LPC32XX)          += lpc32xx_keys.o
 obj-$(CONFIG_KEYBOARD_MAPLE)           += maple_keyb.o
 obj-$(CONFIG_KEYBOARD_MATRIX)          += matrix_keypad.o
 obj-$(CONFIG_KEYBOARD_MAX7359)         += max7359_keypad.o
diff --git a/drivers/input/keyboard/lpc32xx_keys.c b/drivers/input/keyboard/lpc32xx_keys.c
new file mode 100644 (file)
index 0000000..3eb37ac
--- /dev/null
@@ -0,0 +1,293 @@
+/*
+ * linux/drivers/input/keyboard/lpc32xx-keys.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/module.h>
+#include <linux/interrupt.h>
+#include <linux/slab.h>
+#include <linux/irq.h>
+#include <linux/pm.h>
+#include <linux/platform_device.h>
+#include <linux/input.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+
+#include <mach/board.h>
+
+/*
+ * Key scanner register offsets
+ */
+#define LPC32XX_KS_DEB(x)                      ((x) + 0x00)
+#define LPC32XX_KS_STATE_COND(x)               ((x) + 0x04)
+#define LPC32XX_KS_IRQ(x)                      ((x) + 0x08)
+#define LPC32XX_KS_SCAN_CTL(x)                 ((x) + 0x0C)
+#define LPC32XX_KS_FAST_TST(x)                 ((x) + 0x10)
+#define LPC32XX_KS_MATRIX_DIM(x)               ((x) + 0x14)
+#define LPC32XX_KS_DATA(x, y)                  ((x) + 0x40 + (y  << 2))
+
+#define LPC32XX_KSCAN_DEB_NUM_DEB_PASS(n)      ((n) & 0xFF)
+
+#define LPC32XX_KSCAN_SCOND_IN_IDLE            0x0
+#define LPC32XX_KSCAN_SCOND_IN_SCANONCE                0x1
+#define LPC32XX_KSCAN_SCOND_IN_IRQGEN          0x2
+#define LPC32XX_KSCAN_SCOND_IN_SCAN_MATRIX     0x3
+
+#define LPC32XX_KSCAN_IRQ_PENDING_CLR          0x1
+
+#define LPC32XX_KSCAN_SCTRL_SCAN_DELAY(n)      ((n) & 0xFF)
+
+#define LPC32XX_KSCAN_FTST_FORCESCANONCE       0x1
+#define LPC32XX_KSCAN_FTST_USE32K_CLK          0x2
+
+#define LPC32XX_KSCAN_MSEL_SELECT(n)           ((n) & 0xF)
+
+struct lpc32xx_kscan_drv {
+       struct input_dev *input;
+       struct lpc32XX_kscan_cfg *kscancfg;
+       struct clk *clk;
+       void __iomem *kscan_base;
+       int irq;
+       u8 lastkeystates[8];
+};
+
+static void lpc32xx_mod_states(struct lpc32xx_kscan_drv *kscandat, int off)
+{
+       u8 st, key;
+       int j, scancode, keycode;
+
+       key = (u8) __raw_readl(LPC32XX_KS_DATA(kscandat->kscan_base, off));
+       if (key != kscandat->lastkeystates[off]) {
+               for (j = 0; j < kscandat->kscancfg->matrix_sz; j++) {
+                       st = key & (1 << j);
+                       if (st != (kscandat->lastkeystates[off] & (1 << j))) {
+                               /* Key state changed, signal an event */
+                               scancode = (int) (j *
+                                       kscandat->kscancfg->matrix_sz) + off;
+                               keycode =
+                                       kscandat->kscancfg->keymap[scancode];
+                               input_report_key(kscandat->input, keycode,
+                                       (st != 0));
+                       }
+               }
+
+               kscandat->lastkeystates[off] = key;
+       }
+}
+
+static irqreturn_t lpc32xx_kscan_irq(int irq, void *dev_id)
+{
+       int i;
+       struct lpc32xx_kscan_drv *kscandat =
+               (struct lpc32xx_kscan_drv *) dev_id;
+
+       for (i = 0; i < kscandat->kscancfg->matrix_sz; i++)
+               lpc32xx_mod_states(kscandat, i);
+
+       __raw_writel(1, LPC32XX_KS_IRQ(kscandat->kscan_base));
+
+       input_sync(kscandat->input);
+
+       return IRQ_HANDLED;
+}
+
+static int __devinit lpc32xx_kscan_probe(struct platform_device *pdev)
+{
+       struct lpc32xx_kscan_drv *kscandat;
+       struct resource *res;
+       int retval, i;
+
+       kscandat = kzalloc(sizeof(struct lpc32xx_kscan_drv), GFP_KERNEL);
+       if (unlikely(!kscandat)) {
+               dev_err(&pdev->dev, "failed to allocate memory\n");
+               return -ENOMEM;
+       }
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (res == NULL) {
+               dev_err(&pdev->dev, "failed to get platform I/O memory\n");
+               retval = -EBUSY;
+               goto err_nores;
+       }
+
+       res = request_mem_region(res->start, resource_size(res), pdev->name);
+       if (res == NULL) {
+               dev_err(&pdev->dev, "failed to request I/O memory\n");
+               retval = -EBUSY;
+               goto err_nores;
+       }
+
+       kscandat->kscan_base = ioremap(res->start, res->end - res->start + 1);
+       if (kscandat->kscan_base == NULL) {
+               dev_err(&pdev->dev, "failed to remap I/O memory\n");
+               retval = -EBUSY;
+               goto err_noremap;
+       }
+
+       /* Get the key scanner clock */
+       kscandat->clk = clk_get(&pdev->dev, NULL);
+       if (IS_ERR(kscandat->clk)) {
+               dev_err(&pdev->dev, "failed to get clock\n");
+               retval = -ENODEV;
+               goto err_noclk;
+       }
+       clk_enable(kscandat->clk);
+
+       kscandat->irq = platform_get_irq(pdev, 0);
+       if ((kscandat->irq < 0) || (kscandat->irq >= NR_IRQS)) {
+               dev_err(&pdev->dev, "failed to get platform irq\n");
+               retval = -EINVAL;
+               goto err_noirq;
+       }
+       retval = request_irq(kscandat->irq, lpc32xx_kscan_irq,
+               0, pdev->name, kscandat);
+       if (retval) {
+               dev_err(&pdev->dev, "failed to request irq\n");
+               goto err_noirq;
+       }
+
+       kscandat->input = input_allocate_device();
+       if (kscandat->input == NULL) {
+               dev_err(&pdev->dev, "failed to allocate device\n");
+               retval = -ENOMEM;
+               goto err_noalloc;
+       }
+
+       kscandat->kscancfg = (struct lpc32XX_kscan_cfg *)
+               pdev->dev.platform_data;
+       platform_set_drvdata(pdev, kscandat);
+
+       /* Setup key input */
+       kscandat->input->evbit[0]       = BIT_MASK(EV_KEY);
+       kscandat->input->name           = pdev->name;
+       kscandat->input->phys           = "matrix-keys/input0";
+       kscandat->input->dev.parent     =  &pdev->dev;
+       kscandat->input->id.vendor      = 0x0001;
+       kscandat->input->id.product     = 0x0001;
+       kscandat->input->id.version     = 0x0100;
+       for (i = 0; i < kscandat->kscancfg->matrix_sz; i++)
+               __set_bit(kscandat->kscancfg->keymap[i],
+                       kscandat->input->keybit);
+
+       input_set_capability(kscandat->input, EV_MSC, MSC_SCAN);
+
+       retval = input_register_device(kscandat->input);
+       if (retval) {
+               dev_err(&pdev->dev, "failed to register input device\n");
+               goto err_notregistered;
+       }
+
+       /* Configure the key scanner */
+       __raw_writel(kscandat->kscancfg->deb_clks,
+               LPC32XX_KS_DEB(kscandat->kscan_base));
+       __raw_writel(kscandat->kscancfg->scan_delay,
+               LPC32XX_KS_SCAN_CTL(kscandat->kscan_base));
+       __raw_writel(LPC32XX_KSCAN_FTST_USE32K_CLK,
+               LPC32XX_KS_FAST_TST(kscandat->kscan_base));
+       __raw_writel(kscandat->kscancfg->matrix_sz,
+               LPC32XX_KS_MATRIX_DIM(kscandat->kscan_base));
+       __raw_writel(1, LPC32XX_KS_IRQ(kscandat->kscan_base));
+
+       return 0;
+
+err_notregistered:
+       input_free_device(kscandat->input);
+err_noalloc:
+       free_irq(kscandat->irq, pdev);
+err_noirq:
+       clk_put(kscandat->clk);
+err_noclk:
+       iounmap(kscandat->kscan_base);
+err_noremap:
+       release_mem_region(res->start, resource_size(res));
+err_nores:
+       kfree(kscandat);
+
+       return retval;
+}
+
+static int __devexit lpc32xx_kscan_remove(struct platform_device *pdev)
+{
+       struct resource *res;
+       struct lpc32xx_kscan_drv *kscandat = platform_get_drvdata(pdev);
+
+       free_irq(kscandat->irq, pdev);
+       input_unregister_device(kscandat->input);
+       clk_put(kscandat->clk);
+       iounmap(kscandat->kscan_base);
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       release_mem_region(res->start, resource_size(res));
+
+       kfree(kscandat);
+
+       return 0;
+}
+
+#ifdef CONFIG_PM
+static int lpc32xx_kscan_suspend(struct platform_device *pdev,
+       pm_message_t state)
+{
+       struct lpc32xx_kscan_drv *kscandat = platform_get_drvdata(pdev);
+
+       /* Clear IRQ and disable clock */
+       __raw_writel(1, LPC32XX_KS_IRQ(kscandat->kscan_base));
+       clk_disable(kscandat->clk);
+
+       return 0;
+}
+
+static int lpc32xx_kscan_resume(struct platform_device *pdev)
+{
+       struct lpc32xx_kscan_drv *kscandat = platform_get_drvdata(pdev);
+
+       /* Enable clock and clear IRQ */
+       clk_enable(kscandat->clk);
+       __raw_writel(1, LPC32XX_KS_IRQ(kscandat->kscan_base));
+
+       return 0;
+}
+#else
+#define lpc32xx_kscan_suspend  NULL
+#define lpc32xx_kscan_resume   NULL
+#endif
+
+static struct platform_driver lpc32xx_kscan_driver = {
+       .probe          = lpc32xx_kscan_probe,
+       .remove         = __devexit_p(lpc32xx_kscan_remove),
+       .suspend        = lpc32xx_kscan_suspend,
+       .resume         = lpc32xx_kscan_resume,
+       .driver         = {
+               .name   = "lpc32xx_keys",
+       }
+};
+
+static int __init lpc32xx_kscan_init(void)
+{
+       return platform_driver_register(&lpc32xx_kscan_driver);
+}
+
+static void __exit lpc32xx_kscan_exit(void)
+{
+       platform_driver_unregister(&lpc32xx_kscan_driver);
+}
+
+module_init(lpc32xx_kscan_init);
+module_exit(lpc32xx_kscan_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Kevin Wells <kevin.wells@nxp.com>");
+MODULE_DESCRIPTION("Key scanner driver for LPC32XX devices");
index 8a8fa4d..fad7e73 100644 (file)
@@ -205,6 +205,16 @@ config TOUCHSCREEN_WACOM_W8001
          To compile this driver as a module, choose M here: the
          module will be called wacom_w8001.
 
+config TOUCHSCREEN_LPC32XX
+        tristate "LPC32XX touchscreen controller"
+        depends on ARCH_LPC32XX
+        help
+          Say Y here if you have a LPC32XX device and want
+          to support the built-in touchscreen.
+
+          To compile this driver as a module, choose M here: the
+          module will be called lpc32xx_ts.
+
 config TOUCHSCREEN_MCS5000
        tristate "MELFAS MCS-5000 touchscreen"
        depends on I2C
index 7fef7d5..21fb334 100644 (file)
@@ -37,6 +37,7 @@ obj-$(CONFIG_TOUCHSCREEN_TOUCHWIN)    += touchwin.o
 obj-$(CONFIG_TOUCHSCREEN_TSC2007)      += tsc2007.o
 obj-$(CONFIG_TOUCHSCREEN_UCB1400)      += ucb1400_ts.o
 obj-$(CONFIG_TOUCHSCREEN_WACOM_W8001)  += wacom_w8001.o
+obj-$(CONFIG_TOUCHSCREEN_LPC32XX)       += lpc32xx_ts.o
 obj-$(CONFIG_TOUCHSCREEN_WM97XX)       += wm97xx-ts.o
 obj-$(CONFIG_TOUCHSCREEN_DA9034)       += da9034-ts.o
 wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9705) += wm9705.o
diff --git a/drivers/input/touchscreen/lpc32xx_ts.c b/drivers/input/touchscreen/lpc32xx_ts.c
new file mode 100644 (file)
index 0000000..d29a7e3
--- /dev/null
@@ -0,0 +1,327 @@
+/*
+ * drivers/input/touchscreen/lpc32xx_tsc.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/platform_device.h>
+#include <linux/init.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+
+/*
+ * Touchscreen controller register offsets
+ */
+#define LPC32XX_TSC_STAT(x)                    ((x) + 0x00)
+#define LPC32XX_TSC_SEL(x)                     ((x) + 0x04)
+#define LPC32XX_TSC_CON(x)                     ((x) + 0x08)
+#define LPC32XX_TSC_FIFO(x)                    ((x) + 0x0C)
+#define LPC32XX_TSC_DTR(x)                     ((x) + 0x10)
+#define LPC32XX_TSC_RTR(x)                     ((x) + 0x14)
+#define LPC32XX_TSC_UTR(x)                     ((x) + 0x18)
+#define LPC32XX_TSC_TTR(x)                     ((x) + 0x1C)
+#define LPC32XX_TSC_DXP(x)                     ((x) + 0x20)
+#define LPC32XX_TSC_MIN_X(x)                   ((x) + 0x24)
+#define LPC32XX_TSC_MAX_X(x)                   ((x) + 0x28)
+#define LPC32XX_TSC_MIN_Y(x)                   ((x) + 0x2C)
+#define LPC32XX_TSC_MAX_Y(x)                   ((x) + 0x30)
+#define LPC32XX_TSC_AUX_UTR(x)                 ((x) + 0x34)
+#define LPC32XX_TSC_AUX_MIN(x)                 ((x) + 0x38)
+#define LPC32XX_TSC_AUX_MAX(x)                 ((x) + 0x3C)
+
+#define LPC32XX_TSC_STAT_FIFO_OVRRN            (1 << 8)
+#define LPC32XX_TSC_STAT_FIFO_EMPTY            (1 << 7)
+
+#define LPC32XX_TSC_ADCCON_IRQ_TO_FIFO_4       (0x1 << 11)
+#define LPC32XX_TSC_ADCCON_X_SAMPLE_SIZE(s)    ((10 - s) << 7)
+#define LPC32XX_TSC_ADCCON_Y_SAMPLE_SIZE(s)    ((10 - s) << 4)
+#define LPC32XX_TSC_ADCCON_POWER_UP            (1 << 2)
+#define LPC32XX_TSC_ADCCON_AUTO_EN             (1 << 0)
+
+#define LPC32XX_TSC_FIFO_TS_P_LEVEL            (1 << 31)
+#define LPC32XX_TSC_FIFO_NORMALIZE_X_VAL(x)    (((x) & 0x03FF0000) >> 16)
+#define LPC32XX_TSC_FIFO_NORMALIZE_Y_VAL(y)&