aboutsummaryrefslogtreecommitdiff
path: root/nuttx/arch/arm/src/lpc214x
diff options
context:
space:
mode:
authorpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2012-09-17 18:18:44 +0000
committerpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2012-09-17 18:18:44 +0000
commit57623d42ebb04f0a0b9e6eb7c0847a3ece2aa0ff (patch)
tree25d07d14e920d31c0b1947c9ca586f2a01fc32d8 /nuttx/arch/arm/src/lpc214x
downloadpx4-firmware-57623d42ebb04f0a0b9e6eb7c0847a3ece2aa0ff.tar.gz
px4-firmware-57623d42ebb04f0a0b9e6eb7c0847a3ece2aa0ff.tar.bz2
px4-firmware-57623d42ebb04f0a0b9e6eb7c0847a3ece2aa0ff.zip
Resync new repository with old repo r5166
git-svn-id: http://svn.code.sf.net/p/nuttx/code/trunk@5153 42af7a65-404d-4744-a932-0658087f49c3
Diffstat (limited to 'nuttx/arch/arm/src/lpc214x')
-rw-r--r--nuttx/arch/arm/src/lpc214x/Kconfig6
-rw-r--r--nuttx/arch/arm/src/lpc214x/Make.defs57
-rw-r--r--nuttx/arch/arm/src/lpc214x/README.txt61
-rw-r--r--nuttx/arch/arm/src/lpc214x/chip.h349
-rw-r--r--nuttx/arch/arm/src/lpc214x/lpc214x_apb.h72
-rw-r--r--nuttx/arch/arm/src/lpc214x/lpc214x_decodeirq.c177
-rw-r--r--nuttx/arch/arm/src/lpc214x/lpc214x_head.S634
-rw-r--r--nuttx/arch/arm/src/lpc214x/lpc214x_i2c.h141
-rw-r--r--nuttx/arch/arm/src/lpc214x/lpc214x_irq.c224
-rw-r--r--nuttx/arch/arm/src/lpc214x/lpc214x_lowputc.S209
-rw-r--r--nuttx/arch/arm/src/lpc214x/lpc214x_pinsel.h259
-rw-r--r--nuttx/arch/arm/src/lpc214x/lpc214x_pll.h105
-rw-r--r--nuttx/arch/arm/src/lpc214x/lpc214x_power.h90
-rw-r--r--nuttx/arch/arm/src/lpc214x/lpc214x_serial.c842
-rw-r--r--nuttx/arch/arm/src/lpc214x/lpc214x_spi.h166
-rw-r--r--nuttx/arch/arm/src/lpc214x/lpc214x_timer.h152
-rw-r--r--nuttx/arch/arm/src/lpc214x/lpc214x_timerisr.c170
-rw-r--r--nuttx/arch/arm/src/lpc214x/lpc214x_uart.h142
-rw-r--r--nuttx/arch/arm/src/lpc214x/lpc214x_usbdev.c3375
-rw-r--r--nuttx/arch/arm/src/lpc214x/lpc214x_usbdev.h346
-rw-r--r--nuttx/arch/arm/src/lpc214x/lpc214x_vic.h70
21 files changed, 7647 insertions, 0 deletions
diff --git a/nuttx/arch/arm/src/lpc214x/Kconfig b/nuttx/arch/arm/src/lpc214x/Kconfig
new file mode 100644
index 000000000..a26483ed9
--- /dev/null
+++ b/nuttx/arch/arm/src/lpc214x/Kconfig
@@ -0,0 +1,6 @@
+#
+# For a description of the syntax of this configuration file,
+# see misc/tools/kconfig-language.txt.
+#
+
+comment "LPC214x Configuration Options"
diff --git a/nuttx/arch/arm/src/lpc214x/Make.defs b/nuttx/arch/arm/src/lpc214x/Make.defs
new file mode 100644
index 000000000..41dc0911c
--- /dev/null
+++ b/nuttx/arch/arm/src/lpc214x/Make.defs
@@ -0,0 +1,57 @@
+##############################################################################
+# lpc214x/Make.defs
+#
+# Copyright (C) 2007, 2008 Gregory Nutt. All rights reserved.
+# Author: Gregory Nutt <gnutt@nuttx.org>
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# 3. Neither the name NuttX nor the names of its contributors may be
+# used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+##############################################################################
+
+HEAD_ASRC = lpc214x_head.S
+
+CMN_ASRCS = up_saveusercontext.S up_fullcontextrestore.S up_vectors.S
+CMN_CSRCS = up_allocateheap.c up_assert.c up_blocktask.c up_copystate.c \
+ up_createstack.c up_dataabort.c up_mdelay.c up_udelay.c \
+ up_exit.c up_idle.c up_initialize.c up_initialstate.c \
+ up_interruptcontext.c up_prefetchabort.c up_releasepending.c \
+ up_releasestack.c up_reprioritizertr.c up_syscall.c up_unblocktask.c \
+ up_undefinedinsn.c up_usestack.c up_lowputs.c
+
+ifneq ($(CONFIG_DISABLE_SIGNALS),y)
+CMN_CSRCS += up_schedulesigaction.c up_sigdeliver.c
+endif
+
+CHIP_ASRCS = lpc214x_lowputc.S
+CHIP_CSRCS = lpc214x_decodeirq.c lpc214x_irq.c lpc214x_timerisr.c \
+ lpc214x_serial.c
+
+ifeq ($(CONFIG_USBDEV),y)
+CHIP_CSRCS += lpc214x_usbdev.c
+endif
+
diff --git a/nuttx/arch/arm/src/lpc214x/README.txt b/nuttx/arch/arm/src/lpc214x/README.txt
new file mode 100644
index 000000000..9cfc99593
--- /dev/null
+++ b/nuttx/arch/arm/src/lpc214x/README.txt
@@ -0,0 +1,61 @@
+General Description
+^^^^^^^^^^^^^^^^^^^
+
+http://www.nxp.com/pip/LPC2141FBD64.html:
+
+The LPC2141/42/44/46/48 microcontrollers are based on a 16-bit/32-bit ARM7TDMI-S
+CPU with real-time emulation and embedded trace support, that combine
+microcontroller with embedded high-speed flash memory ranging from 32 kB to
+512 kB. A 128-bit wide memory interface and a unique accelerator architecture
+enable 32-bit code execution at the maximum clock rate. For critical code size
+applications, the alternative 16-bit Thumb mode reduces code by more than 30 pct
+with minimal performance penalty.
+
+Due to their tiny size and low power consumption, LPC2141/42/44/46/48 are ideal
+for applications where miniaturization is a key requirement, such as access
+control and point-of-sale. Serial communications interfaces ranging from a USB 2.0
+Full-speed device, multiple UARTs, SPI, SSP to I2C-bus and on-chip SRAM of 8 kB
+up to 40 kB, make these devices very well suited for communication gateways and
+protocol converters, soft modems, voice recognition and low end imaging, providing
+both large buffer size and high processing power. Various 32-bit timers, single
+or dual 10-bit ADC(s), 10-bit DAC, PWM channels and 45 fast GPIO lines with up
+to nine edge or level sensitive external interrupt pins make these microcontrollers
+suitable for industrial control and medical systems.
+
+
+Features
+^^^^^^^^
+
+o 16-bit/32-bit ARM7TDMI-S microcontroller in a tiny LQFP64 package.
+o 8 kB to 40 kB of on-chip static RAM and 32 kB to 512 kB of on-chip flash memory.
+ 128-bit wide interface/accelerator enables high-speed 60 MHz operation.
+o In-System Programming/In-Application Programming (ISP/IAP) via on-chip boot
+ loader software. Single flash sector or full chip erase in 400 ms and programming
+ of 256 B in 1 ms.
+o EmbeddedICE RT and Embedded Trace interfaces offer real-time debugging with the
+ on-chip RealMonitor software and high-speed tracing of instruction execution.
+o USB 2.0 Full-speed compliant device controller with 2 kB of endpoint RAM. In addition,
+ the LPC2146/48 provides 8 kB of on-chip RAM accessible to USB by DMA.
+o One or two (LPC2141/42 vs. LPC2144/46/48) 10-bit ADCs provide a total of 6/14 analog
+ inputs, with conversion times as low as 2.44 us per channel.
+o Single 10-bit DAC provides variable analog output (LPC2142/44/46/48 only).
+o Two 32-bit timers/external event counters (with four capture and four compare
+ channels each), PWM unit (six outputs) and watchdog.
+o Low power Real-Time Clock (RTC) with independent power and 32 kHz clock input.
+o Multiple serial interfaces including two UARTs (16C550), two Fast I2C-bus (400
+ kbit/s), SPI and SSP with buffering and variable data length capabilities.
+o Vectored Interrupt Controller (VIC) with configurable priorities and vector addresses.
+o Up to 45 of 5 V tolerant fast general purpose I/O pins in a tiny LQFP64 package.
+o Up to 21 external interrupt pins available.
+o 60 MHz maximum CPU clock available from programmable on-chip PLL with settling
+ time of 100 us.
+o On-chip integrated oscillator operates with an external crystal from 1 MHz to 25 MHz.
+o Power saving modes include Idle and Power-down.
+o Individual enable/disable of peripheral functions as well as peripheral clock scaling
+ for additional power optimization.
+o Processor wake-up from Power-down mode via external interrupt or BOD.
+o Single power supply chip with POR and BOD circuits:
+o CPU operating voltage range of 3.0 V to 3.6 V (3.3 V +- 10 pct) with 5 V tolerant
+ I/O pads.
+
+
diff --git a/nuttx/arch/arm/src/lpc214x/chip.h b/nuttx/arch/arm/src/lpc214x/chip.h
new file mode 100644
index 000000000..d469aae8b
--- /dev/null
+++ b/nuttx/arch/arm/src/lpc214x/chip.h
@@ -0,0 +1,349 @@
+/****************************************************************************************************
+ * arch/arm/src/lpc214x/chip.h
+ *
+ * Copyright (C) 2007, 2008 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************************************/
+
+#ifndef __LPC214X_CHIP_H
+#define __LPC214X_CHIP_H
+
+/****************************************************************************************************
+ * Included Files
+ ****************************************************************************************************/
+
+/****************************************************************************************************
+ * Definitions
+ ****************************************************************************************************/
+
+/* Memory Map ***************************************************************************************/
+
+#define LPC214X_FLASH_BASE 0x00000000
+#define LPC214X_FIO_BASE 0x3fffc000
+#define LPC214X_ONCHIP_RAM_BASE 0x40000000
+#define LPC214X_USBDMA_RAM_BASE 0x7fd00000
+#define LPC214X_BOOT_BLOCK 0x7fffd000
+#define LPC214X_EXTMEM_BASE 0x80000000
+#define LPC214X_APB_BASE 0xe0000000
+#define LPC214X_AHB_BASE 0xf0000000
+
+/* Peripheral Registers ****************************************************************************/
+
+/* FIO Register block base addresses */
+
+#define LPC214X_FIO0_BASE 0x3fffc000 /* Fast I/O 0 base address */
+#define LPC214X_FIO1_BASE 0x3fffc020 /* Fast I/O 1 base address */
+
+/* APB Register block base addresses */
+
+#define LPC214X_WD_BASE 0xe0000000 /* Watchdog base address */
+#define LPC214X_TMR0_BASE 0xe0004000 /* Timer 0 base address*/
+#define LPC214X_TMR1_BASE 0xe0008000 /* Timer 1 base address */
+#define LPC214X_UART0_BASE 0xe000c000 /* UART0 base address */
+#define LPC214X_UART1_BASE 0xe0010000 /* UART1 base address */
+#define LPC214X_PWM_BASE 0xe0014000 /* Pulse width modulator (PWM) base address */
+#define LPC214X_I2C0_BASE 0xe001c000 /* I2C0 base address */
+#define LPC214X_SPI0_BASE 0xe0020000 /* Serial Peripheral Interface 0 (SPI0) base */
+#define LPC214X_RTC_BASE 0xe0024000 /* Real Time Clock (RTC) base address */
+#define LPC214X_GPIO0_BASE 0xe0028000 /* General Purpose I/O (GPIO) 0 base address */
+#define LPC214X_GPIO1_BASE 0xe0028010 /* General Purpose I/O (GPIO) 0 base address */
+#define LPC214X_PINSEL_BASE 0xe002c000 /* Pin function select registers */
+#define LPC214X_AD0_BASE 0xe0034000 /* Analog to Digital Converter 0 base address*/
+#define LPC214X_I2C1_BASE 0xe005c000 /* I2C1 base address */
+#define LPC214X_AD1_BASE 0xe0060000 /* Analog to Digital Converter 1 base address */
+#define LPC214X_SPI1_BASE 0xe0068000 /* Serial Peripheral Interface 1 (SPI1) base */
+#define LPC214X_DAC_BASE 0xe0090000 /* DAC base address */
+#define LPC214X_USB_BASE 0xe0090000 /* USB base address */
+
+#define LPC214X_SCB_BASE 0xe01fc000 /* System Control Block (SBC) base address */
+#define LPC214X_MAM_BASE 0xe01fc000 /* Memory Accelerator Module (MAM) base address */
+#define LPC214X_SCS 0xe01fc1a0 /* System Control and Status flags (SCS) */
+#define LPC214X_MEMMAP 0xe01fc040 /* Memory Mapping Control */
+#define LPC214X_PLL_BASE 0xe01fc080 /* Phase Locked Loop (PLL) base address */
+#define LPC214X_PCON_BASE 0xe01fc0c0 /* Power Control (PCON) base address */
+#define LPC214X_APBDIV 0xe01fc100 /* APBDIV Address */
+#define LPC214X_EXT_BASE 0xe01fc140 /* External Interrupt base address */
+
+/* AHB Register block base addresses */
+
+#define LPC214X_EMC_BASE 0xffe00000 /* External Memory Controller (EMC) base address */
+#define LPC214X_VIC_BASE 0xfffff000 /* Vectored Interrupt Controller (VIC) Base */
+
+/* Watchdog Register Offsets */
+
+#define LPC214X_WD_MOD_OFFSET 0x00 /* Watchdog Mode Register */
+#define LPC214X_WD_TC_OFFSET 0x04 /* Watchdog Time Constant Register */
+#define LPC214X_WD_FEED_OFFSET 0x08 /* Watchdog Feed Register */
+#define LPC214X_WD_TV_OFFSET 0x0C /* Watchdog Time Value Register */
+
+/* Timer 0/1 register offsets */
+
+#define LPC214X_TMR_IR_OFFSET 0x00 /* RW:Interrupt Register */
+#define LPC214X_TMR_TCR_OFFSET 0x04 /* RW: Timer Control Register */
+#define LPC214X_TMR_TC_OFFSET 0x08 /* RW: Timer Counter */
+#define LPC214X_TMR_PR_OFFSET 0x0c /* RW: Prescale Register */
+#define LPC214X_TMR_PC_OFFSET 0x10 /* RW: Prescale Counter Register */
+#define LPC214X_TMR_MCR_OFFSET 0x14 /* RW: Match Control Register */
+#define LPC214X_TMR_MR0_OFFSET 0x18 /* RW: Match Register 0 */
+#define LPC214X_TMR_MR1_OFFSET 0x1c /* RW: Match Register 1 */
+#define LPC214X_TMR_MR2_OFFSET 0x20 /* RW: Match Register 2 */
+#define LPC214X_TMR_MR3_OFFSET 0x24 /* RW: Match Register 3 */
+#define LPC214X_TMR_CCR_OFFSET 0x28 /* RW: Capture Control Register */
+#define LPC214X_TMR_CR0_OFFSET 0x2c /* R: Capture Register 0 */
+#define LPC214X_TMR_CR1_OFFSET 0x30 /* R: Capture Register 1 */
+#define LPC214X_TMR_CR2_OFFSET 0x34 /* R: Capture Register 2 */
+#define LPC214X_TMR_CR3_OFFSET 0x38 /* RW: Capture Register 3 */
+#define LPC214X_TMR_EMR_OFFSET 0x3c /* RW: External Match Register */
+
+#define LPC214X_TMR_CTCR_OFFSET 0x70 /* RW: Count Control Register */
+
+/* UART0/1 Register Offsets */
+
+#define LPC214X_UART_RBR_OFFSET 0x00 /* R: Receive Buffer Register (DLAB=0) */
+#define LPC214X_UART_THR_OFFSET 0x00 /* W: Transmit Holding Register (DLAB=0) */
+#define LPC214X_UART_DLL_OFFSET 0x00 /* W: Divisor Latch Register (LSB, DLAB=1) */
+#define LPC214X_UART_IER_OFFSET 0x04 /* W: Interrupt Enable Register (DLAB=0) */
+#define LPC214X_UART_DLM_OFFSET 0x04 /* RW: Divisor Latch Register (MSB, DLAB=1) */
+#define LPC214X_UART_IIR_OFFSET 0x08 /* R: Interrupt ID Register */
+#define LPC214X_UART_FCR_OFFSET 0x08 /* W: FIFO Control Register */
+#define LPC214X_UART_LCR_OFFSET 0x0c /* RW: Line Control Register */
+#define LPC214X_UART_MCR_OFFSET 0x10 /* RW: Modem Control REgister (2146/6/8 UART1 Only) */
+#define LPC214X_UART_LSR_OFFSET 0x14 /* R: Scratch Pad Register */
+#define LPC214X_UART_MSR_OFFSET 0x18 /* RW: MODEM Status Register (2146/6/8 UART1 Only) */
+#define LPC214X_UART_SCR_OFFSET 0x1c /* RW: Line Status Register */
+#define LPC214X_UART_ACR_OFFSET 0x20 /* RW: Autobaud Control Register */
+#define LPC214X_UART_FDR_OFFSET 0x28 /* RW: Fractional Divider Register */
+#define LPC214X_UART_TER_OFFSET 0x30 /* RW: Transmit Enable Register */
+
+/* PWM register offsets */
+
+#define LPC214X_PWM_IR_OFFSET 0x00 /* Interrupt Register */
+#define LPC214X_PWM_TCR_OFFSET 0x04 /* Timer Control Register */
+#define LPC214X_PWM_TC_OFFSET 0x08 /* Timer Counter */
+#define LPC214X_PWM_PR_OFFSET 0x0c /* Prescale Register */
+#define LPC214X_PWM_PC_OFFSET 0x10 /* Prescale Counter Register */
+#define LPC214X_PWM_MCR_OFFSET 0x14 /* Match Control Register */
+#define LPC214X_PWM_MR0_OFFSET 0x18 /* Match Register 0 */
+#define LPC214X_PWM_MR1_OFFSET 0x1c /* Match Register 1 */
+#define LPC214X_PWM_MR2_OFFSET 0x20 /* Match Register 2 */
+#define LPC214X_PWM_MR3_OFFSET 0x24 /* Match Register 3 */
+#define LPC214X_PWM_MR4_OFFSET 0x40 /* Match Register 4 */
+#define LPC214X_PWM_MR5_OFFSET 0x44 /* Match Register 5 */
+#define LPC214X_PWM_MR6_OFFSET 0x48 /* Match Register 6 */
+#define LPC214X_PWM_PCR_OFFSET 0x4c /* Control Register */
+#define LPC214X_PWM_LER_OFFSET 0x50 /* Latch Enable Register */
+
+/* I2C register offsets */
+
+#define LPC214X_I2C_CONSET_OFFSET 0x00 /* Control Set Register */
+#define LPC214X_I2C_STAT_OFFSET 0x04 /* Status Register */
+#define LPC214X_I2C_DAT_OFFSET 0x08 /* Data Register */
+#define LPC214X_I2C_ADR_OFFSET 0x0c /* Slave Address Register */
+#define LPC214X_I2C_SCLH_OFFSET 0x10 /* SCL Duty Cycle Register (high half word) */
+#define LPC214X_I2C_SCLL_OFFSET 0x14 /* SCL Duty Cycle Register (low half word) */
+#define LPC214X_I2C_CONCLR_OFFSET 0x18 /* Control Clear Register */
+
+/* Pin function select register offsets */
+
+#define LPC214X_PINSEL0_OFFSET 0x00 /* Pin function select register 0 */
+#define LPC214X_PINSEL1_OFFSET 0x04 /* Pin function select register 1 */
+#define LPC214X_PINSEL2_OFFSET 0x14 /* Pin function select register 2 */
+
+/* Analog to Digital (AD) Converter registger offsets */
+
+#define LPC214X_AD_ADCR_OFFSET 0x00 /* A/D Control Register */
+#define LPC214X_AD_ADGDR_OFFSET 0x04 /* A/D Global Data Register (only one common register!) */
+#define LPC214X_AD_ADGSR_OFFSET 0x08 /* A/D Global Start Register */
+#define LPC214X_AD_ADINTEN_OFFSET 0x0c /* A/D Interrupt Enable Register */
+#define LPC214X_AD_ADDR0_OFFSET 0x10 /* A/D Chanel 0 Data Register */
+#define LPC214X_AD_ADDR1_OFFSET 0x14 /* A/D Chanel 0 Data Register */
+#define LPC214X_AD_ADDR2_OFFSET 0x18 /* A/D Chanel 0 Data Register */
+#define LPC214X_AD_ADDR3_OFFSET 0x1c /* A/D Chanel 0 Data Register */
+#define LPC214X_AD_ADDR4_OFFSET 0x20 /* A/D Chanel 0 Data Register */
+#define LPC214X_AD_ADDR5_OFFSET 0x24 /* A/D Chanel 0 Data Register */
+#define LPC214X_AD_ADDR6_OFFSET 0x28 /* A/D Chanel 0 Data Register */
+#define LPC214X_AD_ADDR7_OFFSET 0x2c /* A/D Chanel 0 Data Register */
+#define LPC214X_AD_ADSTAT_OFFSET 0x30 /* A/D Status Register */
+
+/* SPI0 register offsets */
+
+#define LPC214X_SPI0_CR_OFFSET 0x00 /* Control Register 0 */
+#define LPC214X_SPI0_SR_OFFSET 0x04 /* Control Register 1 */
+#define LPC214X_SPI0_DR_OFFSET 0x08 /* Data Register */
+#define LPC214X_SPI0_CCR_OFFSET 0x0c /* Status Register */
+#define LPC214X_SPI0_INT_OFFSET 0x1c /* Clock Pre-Scale Regisrer */
+
+/* SPI1 register offsets */
+
+#define LPC214X_SPI1_CR0_OFFSET 0x00 /* Control Register 0 */
+#define LPC214X_SPI1_CR1_OFFSET 0x04 /* Control Register 1 */
+#define LPC214X_SPI1_DR_OFFSET 0x08 /* Data Register */
+#define LPC214X_SPI1_SR_OFFSET 0x0c /* Status Register */
+#define LPC214X_SPI1_CPSR_OFFSET 0x10 /* Clock Pre-Scale Regisrer */
+#define LPC214X_SPI1_IMSC_OFFSET 0x14 /* Interrupt Mask Set and Clear Register */
+#define LPC214X_SPI1_RIS_OFFSET 0x18 /* Raw Interrupt Status Register */
+#define LPC214X_SPI1_MIS_OFFSET 0x1c /* Masked Interrupt Status Register */
+#define LPC214X_SPI1_ICR_OFFSET 0x20 /* Interrupt Clear Register */
+
+/* RTC register offsets */
+
+#define LPC214X_RTC_ILR_OFFSET 0x00 /* Interrupt Location Register */
+#define LPC214X_RTC_CTC_OFFSET 0x04 /* Clock Tick Counter */
+#define LPC214X_RTC_CCR_OFFSET 0x08 /* Clock Control Register */
+#define LPC214X_RTC_CIIR_OFFSET 0x0c /* Counter Increment Interrupt Register */
+#define LPC214X_RTC_AMR_OFFSET 0x10 /* Alarm Mask Register */
+#define LPC214X_RTC_CTIME0_OFFSET 0x14 /* Consolidated Time Register 0 */
+#define LPC214X_RTC_CTIME1_OFFSET 0x18 /* Consolidated Time Register 1 */
+#define LPC214X_RTC_CTIME2_OFFSET 0x1c /* Consolidated Time Register 2 */
+#define LPC214X_RTC_SEC_OFFSET 0x20 /* Seconds Register */
+#define LPC214X_RTC_MIN_OFFSET 0x24 /* Minutes Register */
+#define LPC214X_RTC_HOUR_OFFSET 0x28 /* Hours Register */
+#define LPC214X_RTC_DOM_OFFSET 0x2c /* Day Of Month Register */
+#define LPC214X_RTC_DOW_OFFSET 0x30 /* Day Of Week Register */
+#define LPC214X_RTC_DOY_OFFSET 0x34 /* Day Of Year Register */
+#define LPC214X_RTC_MONTH_OFFSET 0x38 /* Months Register */
+#define LPC214X_RTC_YEAR_OFFSET 0x3c /* Years Register */
+
+#define LPC214X_RTC_ALSEC_OFFSET 0x60 /* Alarm Seconds Register */
+#define LPC214X_RTC_ALMIN_OFFSET 0x64 /* Alarm Minutes Register */
+#define LPC214X_RTC_ALHOUR_OFFSET 0x68 /* Alarm Hours Register */
+#define LPC214X_RTC_ALDOM_OFFSET 0x6c /* Alarm Day Of Month Register */
+#define LPC214X_RTC_ALDOW_OFFSET 0x70 /* Alarm Day Of Week Register */
+#define LPC214X_RTC_ALDOY_OFFSET 0x74 /* Alarm Day Of Year Register */
+#define LPC214X_RTC_ALMON_OFFSET 0x78 /* Alarm Months Register */
+#define LPC214X_RTC_ALYEAR_OFFSET 0x7c /* Alarm Years Register */
+#define LPC214X_RTC_PREINT_OFFSET 0x80 /* Prescale Value Register (integer) */
+#define LPC214X_RTC_PREFRAC_OFFSET 0x84 /* Prescale Value Register (fraction) */
+
+/* GPIO register offsets */
+
+#define LPC214X_GPIO_PIN_OFFSET 0x00 /* Pin Value Register */
+#define LPC214X_GPIO_SET_OFFSET 0x04 /* Pin Output Set Register */
+#define LPC214X_GPIO_DIR_OFFSET 0x08 /* Pin Direction Register */
+#define LPC214X_GPIO_CLR_OFFSET 0x0c /* Pin Output Clear Register */
+
+/* FIO register offsets */
+
+#define LPC214X_FIO_DIR_OFFSET 0x00 /* Fast GPIO Port Direction Register */
+#define LPC214X_FIO_MASK_OFFSET 0x10 /* Fast GPIO Mask Register */
+#define LPC214X_FIO_PIN_OFFSET 0x14 /* Fast GPIO Pin Value Register */
+#define LPC214X_FIO_SET_OFFSET 0x18 /* Fast GPIO Port Output Set Register */
+#define LPC214X_FIO_CLR_OFFSET 0x1c /* Fast GPIO Port Output Clear Register */
+
+/* Memory Accelerator Module (MAM) Regiser Offsets */
+
+#define LPC214X_MAM_CR_OFFSET 0x00 /* MAM Control Offset*/
+#define LPC214x_MAM_TIM_OFFSET 0x04 /* MAM Timing Offset */
+
+/* Phase Locked Loop (PLL) Register Offsets */
+
+#define LPC214X_PLL_CON_OFFSET 0x00 /* PLL Control Offset*/
+#define LPC214X_PLL_CFG_OFFSET 0x04 /* PLL Configuration Offset */
+#define LPC214X_PLL_STAT_OFFSET 0x08 /* PLL Status Offset */
+#define LPC214X_PLL_FEED_OFFSET 0x0c /* PLL Feed Offset */
+
+/* Power Control register offsets */
+
+#define LPC214X_PCON_OFFSET 0x00 /* Control Register */
+#define LPC214X_PCONP_OFFSET 0x04 /* Peripherals Register */
+
+/* External Interrupt register offsets */
+
+#define LPC214X_EXT_INT_OFFSET 0x00 /* Flag Register */
+#define LPC214X_EXT_WAKE_OFFSET 0x04 /* Wakeup Register */
+#define LPC214X_EXT_MODE_OFFSET 0x08 /* Mode Register */
+#define LPC214X_EXT_POLAR_OFFSET 0x0c /* Polarity Register */
+
+/* External Memory Controller (EMC) definitions */
+
+#define LPC214X_BCFG0_OFFSET 0x00 /* BCFG0 Offset */
+#define LPC214X_BCFG1_OFFSET 0x04 /* BCFG1 Offset */
+#define LPC214X_BCFG2_OFFSET 0x08 /* BCFG2 Offset */
+#define LPC214X_BCFG3_OFFSET 0x0c /* BCFG3 Offset */
+
+/* Vectored Interrupt Controller (VIC) register offsets */
+
+#define LPC214X_VIC_IRQSTATUS_OFFSET 0x00 /* R: IRQ Status Register */
+#define LPC214X_VIC_FIQSTATUS_OFFSET 0x04 /* R: FIQ Status Register */
+#define LPC214X_VIC_RAWINTR_OFFSET 0x08 /* R: Raw Interrupt Status Register */
+#define LPC214X_VIC_INTSELECT_OFFSET 0x0c /* RW: Interrupt Select Register */
+#define LPC214X_VIC_INTENABLE_OFFSET 0x10 /* RW: Interrupt Enable Register */
+#define LPC214X_VIC_INTENCLEAR_OFFSET 0x14 /* W: Interrupt Enable Clear Register */
+#define LPC214X_VIC_SOFTINT_OFFSET 0x18 /* RW: Software Interrupt Register */
+#define LPC214X_VIC_SOFTINTCLEAR_OFFSET 0x1c /* W: Software Interrupt Clear Register */
+#define LPC214X_VIC_PROTECTION_OFFSET 0x20 /* Protection Enable Register */
+
+#define LPC214X_VIC_VECTADDR_OFFSET 0x30 /* RW: Vector Address Register */
+#define LPC214X_VIC_DEFVECTADDR_OFFSET 0x34 /* RW: Default Vector Address Register */
+
+#define LPC214X_VIC_VECTADDR0_OFFSET 0x100 /* RW: Vector Address 0 Register */
+#define LPC214X_VIC_VECTADDR1_OFFSET 0x104 /* RW: Vector Address 1 Register */
+#define LPC214X_VIC_VECTADDR2_OFFSET 0x108 /* RW: Vector Address 2 Register */
+#define LPC214X_VIC_VECTADDR3_OFFSET 0x10c /* RW: Vector Address 3 Register */
+#define LPC214X_VIC_VECTADDR4_OFFSET 0x110 /* RW: Vector Address 4 Register */
+#define LPC214X_VIC_VECTADDR5_OFFSET 0x114 /* RW: Vector Address 5 Register */
+#define LPC214X_VIC_VECTADDR6_OFFSET 0x118 /* RW: Vector Address 6 Register */
+#define LPC214X_VIC_VECTADDR7_OFFSET 0x11c /* RW: Vector Address 7 Register */
+#define LPC214X_VIC_VECTADDR8_OFFSET 0x120 /* RW: Vector Address 8 Register */
+#define LPC214X_VIC_VECTADDR9_OFFSET 0x124 /* RW: Vector Address 9 Register */
+#define LPC214X_VIC_VECTADDR10_OFFSET 0x128 /* RW: Vector Address 10 Register */
+#define LPC214X_VIC_VECTADDR11_OFFSET 0x12c /* RW: Vector Address 11 Register */
+#define LPC214X_VIC_VECTADDR12_OFFSET 0x130 /* RW: Vector Address 12 Register */
+#define LPC214X_VIC_VECTADDR13_OFFSET 0x134 /* RW: Vector Address 13 Register */
+#define LPC214X_VIC_VECTADDR14_OFFSET 0x138 /* RW: Vector Address 14 Register */
+#define LPC214X_VIC_VECTADDR15_OFFSET 0x13c /* RW: Vector Address 15 Register */
+
+#define LPC214X_VIC_VECTCNTL0_OFFSET 0x200 /* RW: Vector Control 0 Register */
+#define LPC214X_VIC_VECTCNTL1_OFFSET 0x204 /* RW: Vector Control 1 Register */
+#define LPC214X_VIC_VECTCNTL2_OFFSET 0x208 /* RW: Vector Control 2 Register */
+#define LPC214X_VIC_VECTCNTL3_OFFSET 0x20c /* RW: Vector Control 3 Register */
+#define LPC214X_VIC_VECTCNTL4_OFFSET 0x210 /* RW: Vector Control 4 Register */
+#define LPC214X_VIC_VECTCNTL5_OFFSET 0x214 /* RW: Vector Control 5 Register */
+#define LPC214X_VIC_VECTCNTL6_OFFSET 0x218 /* RW: Vector Control 6 Register */
+#define LPC214X_VIC_VECTCNTL7_OFFSET 0x21c /* RW: Vector Control 7 Register */
+#define LPC214X_VIC_VECTCNTL8_OFFSET 0x220 /* RW: Vector Control 8 Register */
+#define LPC214X_VIC_VECTCNTL9_OFFSET 0x224 /* RW: Vector Control 9 Register */
+#define LPC214X_VIC_VECTCNTL10_OFFSET 0x228 /* RW: Vector Control 10 Register */
+#define LPC214X_VIC_VECTCNTL11_OFFSET 0x22c /* RW: Vector Control 11 Register */
+#define LPC214X_VIC_VECTCNTL12_OFFSET 0x230 /* RW: Vector Control 12 Register */
+#define LPC214X_VIC_VECTCNTL13_OFFSET 0x234 /* RW: Vector Control 13 Register */
+#define LPC214X_VIC_VECTCNTL14_OFFSET 0x238 /* RW: Vector Control 14 Register */
+#define LPC214X_VIC_VECTCNTL15_OFFSET 0x23c /* RW: Vector Control 15 Register */
+
+/****************************************************************************************************
+ * Inline Functions
+ ****************************************************************************************************/
+
+/****************************************************************************************************
+ * Global Function Prototypes
+ ****************************************************************************************************/
+
+#endif /* __LPC214X_CHIP_H */
diff --git a/nuttx/arch/arm/src/lpc214x/lpc214x_apb.h b/nuttx/arch/arm/src/lpc214x/lpc214x_apb.h
new file mode 100644
index 000000000..2d41ab106
--- /dev/null
+++ b/nuttx/arch/arm/src/lpc214x/lpc214x_apb.h
@@ -0,0 +1,72 @@
+/************************************************************************************
+ * arch/arm/src/lpc214x/lpc214x_apb.h
+ *
+ * Copyright (C) 2008 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ************************************************************************************/
+
+#ifndef _ARCH_ARM_SRC_LPC214X_APB_H
+#define _ARCH_ARM_SRC_LPC214X_APB_H
+
+/************************************************************************************
+ * Included Files
+ ************************************************************************************/
+
+/************************************************************************************
+ * Definitions
+ ************************************************************************************/
+
+/* Register address definitions *****************************************************/
+
+#define LPC214X_APB_APBDIV (0xe01fc100) /* 8-bit R/W APB divider register */
+
+/* Register bit definitions *********************************************************/
+
+/* APB divider register */
+
+#define LPC214X_APBDIV_MASK (0x03) /* Bit 0:1: APB divider value */
+#define LPC214X_APBDIV_DIV4 (0x00) /* Bit 0:1=00: APB=PCLK/4 */
+#define LPC214X_APBDIV_DIV1 (0x01) /* Bit 0:1=01: APB=PCLK */
+#define LPC214X_APBDIV_DIV2 (0x02) /* Bit 0:1=10: APB=PCLK/2 */
+
+/************************************************************************************
+ * Public Types
+ ************************************************************************************/
+
+/************************************************************************************
+ * Inline Functions
+ ************************************************************************************/
+
+/************************************************************************************
+ * Public Function Prototypes
+ ************************************************************************************/
+
+#endif /* _ARCH_ARM_SRC_LPC214X_APB_H */
diff --git a/nuttx/arch/arm/src/lpc214x/lpc214x_decodeirq.c b/nuttx/arch/arm/src/lpc214x/lpc214x_decodeirq.c
new file mode 100644
index 000000000..652fe4d61
--- /dev/null
+++ b/nuttx/arch/arm/src/lpc214x/lpc214x_decodeirq.c
@@ -0,0 +1,177 @@
+/********************************************************************************
+ * arch/arm/src/lpc214x/lpc214x_decodeirq.c
+ *
+ * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ********************************************************************************/
+
+/********************************************************************************
+ * Included Files
+ ********************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <stdint.h>
+#include <nuttx/irq.h>
+#include <nuttx/arch.h>
+#include <assert.h>
+#include <debug.h>
+
+#include "chip.h"
+#include "up_arch.h"
+#include "os_internal.h"
+#include "up_internal.h"
+
+#include "lpc214x_vic.h"
+
+/********************************************************************************
+ * Definitions
+ ********************************************************************************/
+
+/********************************************************************************
+ * Private Types
+ ********************************************************************************/
+
+/********************************************************************************
+ * Public Data
+ ********************************************************************************/
+
+/********************************************************************************
+ * Private Data
+ ********************************************************************************/
+
+/* This array maps 4 bits into the bit number of the lowest bit that it set */
+
+#ifndef CONFIG_SUPPRESS_INTERRUPTS
+static uint8_t g_nibblemap[16] = { 0, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0 };
+#endif
+
+/********************************************************************************
+ * Private Functions
+ ********************************************************************************/
+
+/********************************************************************************
+ * Public Funstions
+ ********************************************************************************/
+
+/********************************************************************************
+ * up_decodeirq() and/or lpc214x_decodeirq()
+ *
+ * Description:
+ * The vectored interrupt controller (VIC) takes 32 interrupt request inputs
+ * and programmatically assigns them into 3 categories: FIQ, vectored IRQ,
+ * and non-vectored IRQ.
+ *
+ * - FIQs have the highest priority. There is a single FIQ vector, but multiple
+ * interrupt sources can be ORed to this FIQ vector.
+ *
+ * - Vectored IRQs have the middle priority. Any 16 of the 32 interrupt sources
+ * can be assigned to vectored IRQs.
+ *
+ * - Non-vectored IRQs have the lowest priority.
+ *
+ * The general flow of IRQ processing is to simply read the VIC vector address
+ * and jump to the address of the vector provided in the register. The VIC will
+ * provide the address of the highest priority vectored IRQ. If a non-vectored
+ * IRQ is requesting, the address of a default handler is provided.
+ *
+ ********************************************************************************/
+
+#ifndef CONFIG_VECTORED_INTERRUPTS
+void up_decodeirq(uint32_t *regs)
+#else
+static void lpc214x_decodeirq( uint32_t *regs)
+#endif
+{
+#ifdef CONFIG_SUPPRESS_INTERRUPTS
+ lib_lowprintf("Unexpected IRQ\n");
+ current_regs = regs;
+ PANIC(OSERR_ERREXCEPTION);
+#else
+
+ /* Decode the interrupt. We have to do this by search for the lowest numbered
+ * non-zero bit in the interrupt status register.
+ */
+
+ uint32_t pending = vic_getreg(LPC214X_VIC_IRQSTATUS_OFFSET) & 0x007fffff;
+ unsigned int nibble;
+ unsigned int irq_base;
+ unsigned int irq = NR_IRQS;
+
+ /* Search in groups of four bits. For 22 sources, this is at most six
+ * times through the loop.
+ */
+
+ for (nibble = pending & 0x0f, irq_base = 0;
+ pending && irq_base < NR_IRQS;
+ pending >>= 4, nibble = pending & 0x0f, irq_base += 4)
+ {
+ if (nibble)
+ {
+ irq = irq_base + g_nibblemap[nibble];
+ break;
+ }
+ }
+
+ /* Verify that the resulting IRQ number is valid */
+
+ if (irq < NR_IRQS)
+ {
+ uint32_t *savestate;
+
+ /* Current regs non-zero indicates that we are processing an interrupt;
+ * current_regs is also used to manage interrupt level context switches.
+ */
+
+ savestate = (uint32_t*)current_regs;
+ current_regs = regs;
+
+ /* Deliver the IRQ */
+
+ irq_dispatch(irq, regs);
+
+ /* Restore the previous value of current_regs. NULL would indicate that
+ * we are no longer in an interrupt handler. It will be non-NULL if we
+ * are returning from a nested interrupt.
+ */
+
+ current_regs = savestate;
+ }
+#endif
+}
+
+#ifdef CONFIG_VECTORED_INTERRUPTS
+void up_decodeirq(uint32_t *regs)
+{
+ vic_vector_t vector = (vic_vector_t)vic_getreg(LPC214X_VIC_VECTADDR_OFFSET);
+ vector(regs);
+}
+#endif
diff --git a/nuttx/arch/arm/src/lpc214x/lpc214x_head.S b/nuttx/arch/arm/src/lpc214x/lpc214x_head.S
new file mode 100644
index 000000000..678481154
--- /dev/null
+++ b/nuttx/arch/arm/src/lpc214x/lpc214x_head.S
@@ -0,0 +1,634 @@
+/*****************************************************************************
+ * arch/arm/src/lpc214x/lpc214x_head.S
+ *
+ * Copyright (C) 2007-2009, 2012 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Included Files
+ *****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <arch/board/board.h>
+
+#include "arm.h"
+#include "chip.h"
+#include "lpc214x_pll.h"
+#include "lpc214x_apb.h"
+#include "lpc214x_pinsel.h"
+#include "up_internal.h"
+#include "up_arch.h"
+
+/*****************************************************************************
+ * Definitions
+ *****************************************************************************/
+
+/* This file holds the NuttX start logic that runs when the LPC2148
+ * is reset. This logic must be located at address 0x0000:0000 in
+ * flash but may be linked to run at different locations based on
+ * the selected mode:
+ *
+ * default: Executes from 0x0000:0000. In non-default modes, the
+ * MEMAP register is set override the settings of the CPU configuration
+ * pins.
+ *
+ * CONFIG_EXTMEM_MODE: Code executes from external memory starting at
+ * address 0x8000:0000.
+ *
+ * CONFIG_RAM_MODE: Code executes from on-chip RAM at address
+ * 0x4000:0000.
+ *
+ * Starupt Code must be linked to run at the correct address
+ * corresponding to the selected mode.
+ */
+
+#if defined(CONFIG_EXTMEM_MODE)
+# if CONFIG_CODE_BASE != LPC214X_EXTMEM_BASE
+# error "CONFIG_CODE_BASE must be 0x80000000 in EXTMEM mode"
+# endif
+#elif defined(CONFIG_RAM_MODE)
+# if CONFIG_CODE_BASE != LPC214X_ONCHIP_RAM_BASE
+# error "CONFIG_CODE_BASE must be 0x40000000 in EXTMEM mode"
+# endif
+#else
+# if CONFIG_CODE_BASE != LPC214X_FLASH_BASE
+# error "CONFIG_CODE_BASE must be 0x00000000 in default mode"
+# endif
+#endif
+
+/* Phase Locked Loop (PLL) initialization values
+ *
+ * Bit 0:4 MSEL: PLL Multiplier "M" Value
+ * CCLK = M * Fosc
+ * Bit 5:6 PSEL: PLL Divider "P" Value
+ * Fcco = CCLK * 2 * P
+ * 156MHz <= Fcco <= 320MHz
+ */
+
+/* PLL0 provides CCLK and must always be configured */
+
+#ifndef CONFIG_PLLCFG_VALUE /* board.h values can be supeceded config file */
+# ifdef LPC214X_PLL_M
+# define CONFIG_PLLCFG_MSEL (LPC214X_PLL_M-1)
+# else
+# warning "PLL_M not specified"
+# define CONFIG_PLLCFG_MSEL (5-1)
+# endif
+# ifdef LPC214X_PLL_P
+# if LPC214X_PLL_P == 1
+# define CONFIG_PLLCFG_PSEL LPC214X_PLL_CFG_PSEL1
+# elif LPC214X_PLL_P == 2
+# define CONFIG_PLLCFG_PSEL LPC214X_PLL_CFG_PSEL2
+# elif LPC214X_PLL_P == 4
+# define CONFIG_PLLCFG_PSEL LPC214X_PLL_CFG_PSEL4
+# elif LPC214X_PLL_P == 8
+# define CONFIG_PLLCFG_PSEL LPC214X_PLL_CFG_PSEL8
+# else
+# error "Unrecognized value for PLL_P"
+# endif
+# else
+# warning "PLL_P not specified"
+# define CONFIG_PLLCFG_PSEL LPC214X_PLL_CFG_PSEL2
+# endif
+# define CONFIG_PLLCFG_VALUE (CONFIG_PLLCFG_PSEL|CONFIG_PLLCFG_MSEL)
+#endif
+
+/* If USB is enabled, PLL1 must be configured for 48MHz to provide USB clocking */
+
+#ifdef CONFIG_USBDEV
+# ifndef CONFIG_USBPLLCFG_VALUE /* board.h values can be supeceded config file */
+# ifdef LPC214X_USBPLL_M
+# define LPC214X_USBPLLCFG_MSEL (LPC214X_USBPLL_M-1)
+# else
+# warning "PLL_M not specified"
+# define LPC214X_USBPLLCFG_MSEL 0x00000004
+# endif
+# ifdef LPC214X_USBPLL_P
+# if LPC214X_USBPLL_P == 1
+# define LPC214X_USBPLLCFG_PSEL 0x00000000
+# elif LPC214X_USBPLL_P == 2
+# define LPC214X_USBPLLCFG_PSEL 0x00000020
+# elif LPC214X_USBPLL_P == 4
+# define LPC214X_USBPLLCFG_PSEL 0x00000040
+# elif LPC214X_USBPLL_P == 8
+# define LPC214X_USBPLLCFG_PSEL 0x00000060
+# else
+# error "Unrecognized value for PLL_P"
+# endif
+# endif
+# define CONFIG_USBPLLCFG_VALUE (LPC214X_USBPLLCFG_PSEL|LPC214X_USBPLLCFG_MSEL)
+# endif
+#endif
+
+/* Memory Accelerator Module (MAM) initialization values
+ *
+ * MAM Control Register
+ * Bit 0:1 Mode
+ * 0 = Disabled
+ * 1 = Partially Enabled
+ * 2 = Fully Enabled
+ * MAM Timing Register
+ * Bit 0:2 Fetch Cycles
+ * 0 = Reserved
+ * 1 = 1
+ * 2 = 2
+ * 3 = 3
+ * 4 = 4
+ * 5 = 5
+ * 6 = 6
+ * 7 = 7
+ */
+
+#ifndef CONFIG_MAMCR_VALUE /* Can be selected from config file */
+# define CONFIG_MAMCR_VALUE 0x00000002
+#endif
+
+#ifndef CONFIG_MAMTIM_VALUE /* Can be selected from config file */
+# define CONFIG_MAMTIM_VALUE 0x00000004
+#endif
+
+/* APBDIV initialization values
+ *
+ * Bits 0:1 APB Peripheral Bus Clock Rate
+ * 0 = APB Clock = CPU Clock / 4
+ * 1 = APB Clock = CPU Clock
+ * 2 = APB Clock = CPU Clock / 2
+ */
+
+#ifndef CONFIG_APBDIV_VALUE /* Can be selected from config file */
+# ifdef LPC214X_APB_DIV
+# if LPC214X_APB_DIV == 1
+# define CONFIG_APBDIV_VALUE LPC214X_APBDIV_DIV1
+# elif LPC214X_APB_DIV == 2
+# define CONFIG_APBDIV_VALUE LPC214X_APBDIV_DIV2
+# elif LPC214X_APB_DIV == 4
+# define CONFIG_APBDIV_VALUE LPC214X_APBDIV_DIV4
+# else
+# error "Unrecognized value for APBDIV"
+# endif
+# else
+# define CONFIG_APBDIV_VALUE LPC214X_APBDIV_DIV1
+# endif
+#endif
+
+/* External Memory Controller (EMC) initialization values
+ *
+ * Bank Configuration n (BCFG0..3)
+ * Bit 0:3 IDCY: Idle Cycles (0-15)
+ * Bit 5:9 WST1: Wait States 1 (0-31)
+ * Bit 11:15 WST2: Wait States 2 (0-31)
+ * Bit 10 RBLE: Read Byte Lane Enable
+ * Bit 26 WP: Write Protect
+ * Bit 27 BM: Burst ROM
+ * Bit 28:29 MW: Memory Width (0=8-bit 1=16-bit 2=32-bit 3=Reserved)
+ */
+
+#ifndef CONFIG_BCFG0_VALUE /* Can be selected from config file */
+# define CONFIG_BCFG0_VALUE 0x0000fbef
+#endif
+
+#ifndef CONFIG_BCFG1_VALUE /* Can be selected from config file */
+# define CONFIG_BCFG1_VALUE 0x0000fbef
+#endif
+
+#ifndef CONFIG_BCFG2_VALUE /* Can be selected from config file */
+# define CONFIG_BCFG2_VALUE 0x0000fbef
+#endif
+
+#ifndef CONFIG_BCFG3_VALUE /* Can be selected from config file */
+# define CONFIG_BCFG3_VALUE 0x0000fbef
+#endif
+
+/* The following are used to configure the ADC/DAC */
+#ifndef CONFIG_AD0CR_VALUE
+# define CONFIG_AD0CR_VALUE 0x00200402; /* Setup A/D: 10-bit AIN0 @ 3MHz */
+#endif
+
+/* GIO Pin Selection Register settings
+ *
+ * PINSEL0 configures GPIO 0.0 through 0.15
+ */
+
+#ifndef CONFIG_PINSEL0_VALUE /* Can be selected from config file */
+# define CONFIG_PINSEL0_VALUE 0x00000000 /* Reset value */
+#endif
+
+/* PINSEL1 configures GPIO 0.16 through 0.30 and GPO */
+
+#ifndef CONFIG_PINSEL1_VALUE /* Can be selected from the config file */
+# ifdef CONFIG_ADC_SETUP
+# define CONFIG_PINSEL1_ADC 0x01000000 /* Enable DAC */
+# else
+# define CONFIG_PINSEL1_ADC 0x00000000 /* Reset value */
+# endif
+# ifdef CONFIG_USBDEV
+# define CONFIG_PINSEL1_USBDEV 0x80004000 /* Enable Vbus and Connect LED */
+# else
+# define CONFIG_PINSEL1_USBDEV 0x00000000 /* Reset value */
+# endif
+# define CONFIG_PINSEL1_VALUE (CONFIG_PINSEL1_ADC|CONFIG_PINSEL1_USBDEV)
+#endif
+
+/* External Memory Pins definitions
+ * Bit 0:1 Reserved
+ * Bit 2 GPIO/DEBUG
+ * Bit 3 GPIO/TRACE
+ * Bit 31:4 Reserved
+ * CS0..3, OE, WE, BLS0..3, D0..31, A2..23, JTAG Pins
+ */
+
+#ifndef CONFIG_PINSEL2_VALUE /* Can be selected from config file */
+# define CONFIG_PINSEL2_VALUE 0x0e6149e4
+#endif
+
+/*****************************************************************************
+ * Macros
+ *****************************************************************************/
+
+/* Print a character on the UART to show boot status. This macro will
+ * modify r0, r1, r2 and r14
+ */
+
+ .macro showprogress, code
+#ifdef CONFIG_DEBUG
+ mov r0, #\code
+ bl up_lowputc
+#endif
+ .endm
+
+/* Configured the PINSEL2 register if EXTMEM mode is selected */
+
+ .macro configpinsel2, base, val
+#ifdef CONFIG_EXTMEM_MODE
+ ldr \base, =LPC214X_PINSEL2
+ ldr \val, =CONFIG_PINSEL2_VALUE
+ str \val, [\base]
+#endif
+ .endm
+
+/* Configure the external memory controller */
+
+ .macro configemc, base, val
+#ifdef CONFIG_EMC_SETUP
+ ldr \base, =LPC214X_EMC_BASE
+
+#ifdef CONFIG_BCFG0_SETUP
+ ldr \val, =CONFIG_BCFG0_VALUE
+ str \val, [\base, #LPC214X_BCFG0_OFFSET]
+#endif
+
+#ifdef CONFIG_BCFG1_SETUP
+ ldr \val, =CONFIG_BCFG1_VALUE
+ str \val, [\base, #LPC214X_BCFG1_OFFSET]
+#endif
+
+#ifdef CONFIG_BCFG2_SETUP
+ ldr \val, =CONFIG_BCFG2_VALUE
+ str \val, [\base, #LPC214X_BCFG2_OFFSET]
+#endif
+
+#ifdef CONFIG_BCFG3_SETUP
+ ldr \val, =CONFIG_BCFG3_VALUE
+ str \val, [\base, #LPC214X_BCFG3_OFFSET]
+#endif
+#endif
+ .endm
+
+/* Configure APBDIV */
+
+ .macro configapbdiv, base, val
+#ifdef CONFIG_APBDIV_SETUP
+ ldr \base, =LPC214X_APBDIV
+ ldr \val, =CONFIG_APBDIV_VALUE
+ strb \val, [\base]
+#endif
+ .endm
+
+/* Configure the PLL */
+
+ .macro configpll, base, val1, val2, val3
+#ifdef CONFIG_PLL_SETUP
+ ldr \base, =LPC214X_PLL0_BASE
+ mov \val1, #LPC214X_PLL_FEED1
+ mov \val2, #LPC214X_PLL_FEED2
+
+ /* Configure and Enable PLL */
+
+ mov \val3, #CONFIG_PLLCFG_VALUE
+ str \val3, [\base, #LPC214X_PLL_CFG_OFFSET]
+ mov \val3, #LPC214X_PLL_CON_PLLE
+ str \val3, [\base, #LPC214X_PLL_CON_OFFSET]
+ str \val1, [\base, #LPC214X_PLL_FEED_OFFSET]
+ str \val2, [\base, #LPC214X_PLL_FEED_OFFSET]
+
+ /* Wait until PLL Locked */
+1:
+ ldr \val3, [\base, #LPC214X_PLL_STAT_OFFSET]
+ ands \val3, \val3, #LPC214X_PLL_STAT_PLOCK
+ beq 1b
+
+ /* Switch to PLL Clock */
+
+ mov \val3, #(LPC214X_PLL_CON_PLLE | LPC214X_PLL_CON_PLLC)
+ str \val3, [\base, #LPC214X_PLL_CON_OFFSET]
+ str \val1, [\base, #LPC214X_PLL_FEED_OFFSET]
+ str \val2, [\base, #LPC214X_PLL_FEED_OFFSET]
+#endif
+ .endm
+
+ .macro configusbpll, base, val1, val2, val3
+#ifdef CONFIG_USBDEV
+ ldr \base, =LPC214X_PLL1_BASE
+ mov \val1, #LPC214X_PLL_FEED1
+ mov \val2, #LPC214X_PLL_FEED2
+
+ /* Configure and Enable PLL */
+
+ mov \val3, #CONFIG_USBPLLCFG_VALUE
+ str \val3, [\base, #LPC214X_PLL_CFG_OFFSET]
+ mov \val3, #LPC214X_PLL_CON_PLLE
+ str \val3, [\base, #LPC214X_PLL_CON_OFFSET]
+ str \val1, [\base, #LPC214X_PLL_FEED_OFFSET]
+ str \val2, [\base, #LPC214X_PLL_FEED_OFFSET]
+
+ /* Wait until PLL Locked */
+1:
+ ldr \val3, [\base, #LPC214X_PLL_STAT_OFFSET]
+ ands \val3, \val3, #LPC214X_PLL_STAT_PLOCK
+ beq 1b
+
+ /* Switch to PLL Clock */
+
+ mov \val3, #(LPC214X_PLL_CON_PLLE | LPC214X_PLL_CON_PLLC)
+ str \val3, [\base, #LPC214X_PLL_CON_OFFSET]
+ str \val1, [\base, #LPC214X_PLL_FEED_OFFSET]
+ str \val2, [\base, #LPC214X_PLL_FEED_OFFSET]
+#endif
+ .endm
+
+
+/* Configure the Memory Accelerator Module (MAM) */
+
+ .macro configmam, base, val
+#ifdef CONFIG_MAM_SETUP
+ ldr \base, =LPC214X_MAM_BASE
+ mov \val, #CONFIG_MAMTIM_VALUE
+ str \val, [\base, #LPC214x_MAM_TIM_OFFSET]
+ mov \val, #CONFIG_MAMCR_VALUE
+ str \val, [\base, #LPC214X_MAM_CR_OFFSET]
+#endif
+ .endm
+
+/* Setup MEMMAP for the selected mode of operation */
+
+ .macro configmemmap, base, val
+ ldr \base, =LPC214X_MEMMAP
+#if defined(CONFIG_EXTMEM_MODE)
+ mov \val, #3
+#elif defined(CONFIG_RAM_MODE)
+ mov \val, #2
+#else /* Setting the default should not be necessary */
+ mov \val, #1
+#endif
+ str \val, [\base]
+ .endm
+
+ .macro configdac, base, tmp
+#ifdef CONFIG_ADC_SETUP
+ ldr \base, =LPC214X_AD0_BASE
+ ldr \tmp, =CONFIG_AD0CR_VALUE
+ str \tmp, [\base, #LPC214X_AD_ADCR_OFFSET]
+
+ ldr \base,=LPC214X_PINSEL1
+ ldr \tmp, =CONFIG_PINSEL1_VALUE
+ str \tmp, [\base]
+#endif
+ .endm
+
+ .macro configfastport, base, tmp
+#ifdef CONFIG_LPC214x_FIO
+ ldr \base, =LPC214X_SCS
+ mov \tmp, #0x03
+ str \tmp,[\base]
+#endif
+ .endm
+
+/*****************************************************************************
+ * Text
+ *****************************************************************************/
+
+ .text
+
+/*****************************************************************************
+ * Name: _vector_table
+ *
+ * Description:
+ * Interrrupt vector table. This must be located at the beginning
+ * of the memory space (at CONFIG_CODE_BASE). The first entry in
+ * the vector table is the reset vector and this is the code that
+ * will execute whn the processor is reset.
+ *
+ *****************************************************************************/
+
+ .globl _vector_table
+ .type _vector_table, %function
+_vector_table:
+ ldr pc, .Lresethandler /* 0x00: Reset */
+ ldr pc, .Lundefinedhandler /* 0x04: Undefined instruction */
+ ldr pc, .Lswihandler /* 0x08: Software interrupt */
+ ldr pc, .Lprefetchaborthandler /* 0x0c: Prefetch abort */
+ ldr pc, .Ldataaborthandler /* 0x10: Data abort */
+ .long 0 /* 0x14: Vector checksum */
+ ldr pc, .Lirqhandler /* 0x18: IRQ */
+ ldr pc, .Lfiqhandler /* 0x1c: FIQ */
+
+ .globl __start
+ .globl up_vectorundefinsn
+ .globl up_vectorswi
+ .globl up_vectorprefetch
+ .globl up_vectordata
+ .globl up_vectorirq
+ .globl up_vectorfiq
+
+.Lresethandler:
+ .long __start
+.Lundefinedhandler:
+ .long up_vectorundefinsn
+.Lswihandler:
+ .long up_vectorswi
+.Lprefetchaborthandler:
+ .long up_vectorprefetch
+.Ldataaborthandler:
+ .long up_vectordata
+.Lirqhandler:
+ .long up_vectorirq
+.Lfiqhandler:
+ .long up_vectorfiq
+ .size _vector_table, . - _vector_table
+
+/*****************************************************************************
+ * Name: __start
+ *
+ * Description:
+ * Reset entry point. This is the first function to execute when
+ * the processor is reset. It initializes hardware and then gives
+ * control to NuttX.
+ *
+ *****************************************************************************/
+
+ .global __start
+ .type __start, #function
+
+__start:
+ /* Setup the initial processor mode */
+
+ mov r0, #(SVC_MODE | PSR_I_BIT | PSR_F_BIT )
+ msr cpsr, r0
+
+ /* Set up external memory mode (if so selected) */
+
+ configpinsel2 r0, r1
+
+ /* Setup the External Memory Controllor (EMC) as configured */
+
+ configemc r0, r1
+
+ /* Configure APBDIV */
+
+ configapbdiv r0, r1
+
+ /* Configure the PLL(s) */
+
+ configpll r0, r1, r2, r3
+ configusbpll r0, r1, r2, r3
+
+ /* Configure the Memory Accelerator Module (MAM) */
+
+ configmam r0, r1
+
+ /* Setup MEMMAP for the selected mode of operation */
+
+ configmemmap r0, r1
+
+ /* Configure the DAC and ADC */
+
+ configdac r0, r1
+
+ /* Configure Fast GPIO Port */
+
+ configfastport r0, r1
+
+ /* Configure the uart so that we can get debug output as soon
+ * as possible. Modifies r0, r1, r2, and r14.
+ */
+
+ bl up_lowsetup
+ showprogress 'A'
+
+ /* Setup system stack (and get the BSS range) */
+
+ adr r0, LC0
+ ldmia r0, {r4, r5, sp}
+
+ /* Clear system BSS section */
+
+ mov r0, #0
+1: cmp r4, r5
+ strcc r0, [r4], #4
+ bcc 1b
+
+ showprogress 'B'
+
+ /* Copy system .data sections to new home in RAM. */
+
+ adr r3, LC2
+ ldmia r3, {r0, r1, r2}
+
+1: ldmia r0!, {r3 - r10}
+ stmia r1!, {r3 - r10}
+ cmp r1, r2
+ blt 1b
+
+ /* Perform early serial initialization */
+
+ mov fp, #0
+#ifdef USE_EARLYSERIALINIT
+ bl up_earlyserialinit
+#endif
+
+ showprogress 'C'
+ showprogress '\n'
+
+ /* Initialize onboard LEDs */
+
+#ifdef CONFIG_ARCH_LEDS
+ bl up_ledinit
+#endif
+
+ /* Then jump to OS entry */
+
+ b os_start
+
+ /* Variables:
+ * _sbss is the start of the BSS region (see ld.script)
+ * _ebss is the end of the BSS regsion (see ld.script)
+ * The idle task stack starts at the end of BSS and is
+ * of size CONFIG_IDLETHREAD_STACKSIZE. The heap continues
+ * from there until the end of memory. See g_heapbase
+ * below.
+ */
+
+LC0: .long _sbss
+ .long _ebss
+ .long _ebss+CONFIG_IDLETHREAD_STACKSIZE-4
+
+LC2: .long _eronly /* Where .data defaults are stored in FLASH */
+ .long _sdata /* Where .data needs to reside in SDRAM */
+ .long _edata
+ .size __start, .-__start
+
+ /* This global variable is unsigned long g_heapbase and is
+ * exported from here only because of its coupling to LCO
+ * above.
+ */
+
+ .data
+ .align 4
+ .globl g_heapbase
+ .type g_heapbase, object
+g_heapbase:
+ .long _ebss+CONFIG_IDLETHREAD_STACKSIZE
+ .size g_heapbase, .-g_heapbase
+
+ .end
+
diff --git a/nuttx/arch/arm/src/lpc214x/lpc214x_i2c.h b/nuttx/arch/arm/src/lpc214x/lpc214x_i2c.h
new file mode 100644
index 000000000..a66399968
--- /dev/null
+++ b/nuttx/arch/arm/src/lpc214x/lpc214x_i2c.h
@@ -0,0 +1,141 @@
+/************************************************************************************
+ * arch/arm/src/lpc214x/lpc214x_i2c.h
+ *
+ * Copyright (C) 2009 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ************************************************************************************/
+
+#ifndef _ARCH_ARM_SRC_LPC214X_I2C_H
+#define _ARCH_ARM_SRC_LPC214X_I2C_H
+
+/************************************************************************************
+ * Included Files
+ ************************************************************************************/
+
+#include "chip.h"
+
+/************************************************************************************
+ * Definitions
+ ************************************************************************************/
+
+/* Register address Offsets *********************************************************/
+
+/* Defined in chip.h */
+
+/* Register Address Definitions *****************************************************/
+
+#define LPC214X_I2C0_CONSET (LPC214X_I2C0_BASE + LPC214X_I2C_ONSET_OFFSET)
+#define LPC214X_I2C0_STAT (LPC214X_I2C0_BASE + LPC214X_I2C_STAT_OFFSET)
+#define LPC214X_I2C0_DAT (LPC214X_I2C0_BASE + LPC214X_I2C_DAT_OFFSET)
+#define LPC214X_I2C0_ADR (LPC214X_I2C0_BASE + LPC214X_I2C_ADR_OFFSET)
+#define LPC214X_I2C0_SCLH (LPC214X_I2C0_BASE + LPC214X_I2C_SCLH_OFFSET)
+#define LPC214X_I2C0_SCLL (LPC214X_I2C0_BASE + LPC214X_I2C_SCLL_OFFSET)
+#define LPC214X_I2C0_CONCLR (LPC214X_I2C0_BASE + LPC214X_I2C_ONCLR_OFFSET)
+
+#define LPC214X_I2C1_CONSET (LPC214X_I2C1_BASE + LPC214X_I2C_ONSET_OFFSET)
+#define LPC214X_I2C1_STAT (LPC214X_I2C1_BASE + LPC214X_I2C_STAT_OFFSET)
+#define LPC214X_I2C1_DAT (LPC214X_I2C1_BASE + LPC214X_I2C_DAT_OFFSET)
+#define LPC214X_I2C1_ADR (LPC214X_I2C1_BASE + LPC214X_I2C_ADR_OFFSET)
+#define LPC214X_I2C1_SCLH (LPC214X_I2C1_BASE + LPC214X_I2C_SCLH_OFFSET)
+#define LPC214X_I2C1_SCLL (LPC214X_I2C1_BASE + LPC214X_I2C_SCLL_OFFSET)
+#define LPC214X_I2C1_CONCLR (LPC214X_I2C1_BASE + LPC214X_I2C_ONCLR_OFFSET)
+
+/* I2C register bit definitions *****************************************************/
+
+/* Control Set Register (CONSET) */
+
+#define I2C_CONSET_AA (1 << 2) /* Bit 2: Assert acknowledge flag */
+#define I2C_CONSET_SI (1 << 3) /* Bit 3: I2C interrrupt flag */
+#define I2C_CONSET_STO (1 << 4) /* Bit 4: STOP flag */
+#define I2C_CONSET_STA (1 << 5) /* Bit 5: START flag */
+#define I2C_CONSET_I2EN (1 << 6) /* Bit 6: I2C interface enable */
+
+/* Control Clear Register (CONCLR) */
+
+#define I2C_CONCLR_AAC (1 << 2) /* Bit 2: Assert acknowledge Clear bit */
+#define I2C_CONCLR_SIC (1 << 3) /* Bit 3: I2C interrupt Clear bit */
+#define I2C_CONCLR_STAC (1 << 5) /* Bit 5: START flag Clear bit */
+#define I2C_CONCLR_I2ENC (1 << 6) /* Bit 6: I2C interface Disable bit */
+
+/* Status Register (STAT) */
+
+#define I2C_STAT_SHIFT (1 << 3) /* Bits 3-7: Status bits */
+#define I2C_STAT_MASK (0xff << I2C_STAT_SHIFT)
+
+/* Master transmit mode */
+
+# define I2C_STAT_MXSTART (0 << I2C_STAT_SHIFT) /* Start transmitted */
+# define I2C_STAT_MXRSTART (2 << I2C_STAT_SHIFT) /* Repeated start transmitted */
+# define I2C_STAT_MXSLAWACK (3 << I2C_STAT_SHIFT) /* SLA+W tranmitted + ACK received */
+# define I2C_STAT_MXSLAWNAK (4 << I2C_STAT_SHIFT) /* SLA+W tranmitted + NAK received */
+# define I2C_STAT_MXDATAACK (5 << I2C_STAT_SHIFT) /* Data tranmitted + ACK received */
+# define I2C_STAT_MXDATANAK (6 << I2C_STAT_SHIFT) /* Data tranmitted + NAK received */
+# define I2C_STAT_MXARBLOST (7 << I2C_STAT_SHIFT) /* Abritration lost in SLA+W or data */
+
+/* Master receive mode */
+
+# define I2C_STAT_MRSTART (0 << I2C_STAT_SHIFT) /* Start transmitted */
+# define I2C_STAT_MRRSTART (2 << I2C_STAT_SHIFT) /* Repeated start transmitted */
+# define I2C_STAT_MRARBLOST (7 << I2C_STAT_SHIFT) /* Abritration lost in NAK bit */
+# define I2C_STAT_MRSLARACK (8 << I2C_STAT_SHIFT) /* SLA+R tranmitted + ACK received */
+# define I2C_STAT_MRSLARNAK (9 << I2C_STAT_SHIFT) /* SLA+R tranmitted + NAK received */
+# define I2C_STAT_MRDATAACK (10 << I2C_STAT_SHIFT) /* Data received + send ACK */
+# define I2C_STAT_MRDATANAK (11 << I2C_STAT_SHIFT) /* Data received + send NAK */
+
+/* Slave receive mode -- to be provided */
+
+/* Slave receive mode -- to be provided */
+
+/* Data Register (DAT) -- 8-bits of data */
+
+/* Slave Address Register (ADR) */
+
+#define I2C_ADR_GCA (1 << 0) /* Bit 0: General call enable */
+#define I2C_ADR_SHIFT 1 /* Bits 7-1: address */
+#define I2C_ADR_MASK (0x7f << I2C_ADR_SHIFT)
+
+/* SCL Duty Cycle Register (high half word - SCLH) - 16-bits of data */
+
+/* SCL Duty Cycle Register (low half word - SCLL) - 16-bits of data */
+
+/************************************************************************************
+ * Public Types
+ ************************************************************************************/
+
+/************************************************************************************
+ * Inline Functions
+ ************************************************************************************/
+
+/************************************************************************************
+ * Public Function Prototypes
+ ************************************************************************************/
+
+#endif /* _ARCH_ARM_SRC_LPC214X_I2C_H */
diff --git a/nuttx/arch/arm/src/lpc214x/lpc214x_irq.c b/nuttx/arch/arm/src/lpc214x/lpc214x_irq.c
new file mode 100644
index 000000000..cb0f6e12f
--- /dev/null
+++ b/nuttx/arch/arm/src/lpc214x/lpc214x_irq.c
@@ -0,0 +1,224 @@
+/****************************************************************************
+ * arch/arm/src/lpc214x/lpc214x_irq.c
+ *
+ * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <stdint.h>
+#include <debug.h>
+#include <nuttx/irq.h>
+
+#include "arm.h"
+#include "chip.h"
+#include "up_arch.h"
+#include "os_internal.h"
+#include "up_internal.h"
+
+#include "lpc214x_vic.h"
+
+/****************************************************************************
+ * Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+volatile uint32_t *current_regs;
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: up_irqinitialize
+ ****************************************************************************/
+
+void up_irqinitialize(void)
+{
+ int reg;
+
+ /* Disable all interrupts. We do this by writing zero to the IntEnable
+ * register. This is equivalent to writing all ones to the IntClearEnable
+ * register.
+ */
+
+ vic_putreg(0, LPC214X_VIC_INTENABLE_OFFSET);
+
+ /* Select all IRQs, no FIQs */
+
+ vic_putreg(0, LPC214X_VIC_INTSELECT_OFFSET);
+
+ /* Set the default vector */
+
+ vic_putreg((uint32_t)up_decodeirq, LPC214X_VIC_DEFVECTADDR_OFFSET);
+
+ /* Disable all vectored interrupts */
+
+ for (reg = LPC214X_VIC_VECTCNTL0_OFFSET;
+ reg <= LPC214X_VIC_VECTCNTL15_OFFSET;
+ reg += 4)
+ {
+ vic_putreg(0, reg);
+ }
+
+ /* currents_regs is non-NULL only while processing an interrupt */
+
+ current_regs = NULL;
+
+ /* And finally, enable interrupts */
+
+#ifndef CONFIG_SUPPRESS_INTERRUPTS
+ irqrestore(SVC_MODE | PSR_F_BIT);
+#endif
+}
+
+/****************************************************************************
+ * Name: up_disable_irq
+ *
+ * Description:
+ * Disable the IRQ specified by 'irq'
+ *
+ ****************************************************************************/
+
+void up_disable_irq(int irq)
+{
+ /* Verify that the IRQ number is within range */
+
+ if (irq < NR_IRQS)
+ {
+ /* Disable the irq by setting the corresponding bit in the VIC
+ * Interrupt Enable Clear register.
+ */
+
+ vic_putreg((1 << irq), LPC214X_VIC_INTENCLEAR_OFFSET);
+ }
+}
+
+/****************************************************************************
+ * Name: up_enable_irq
+ *
+ * Description:
+ * Enable the IRQ specified by 'irq'
+ *
+ ****************************************************************************/
+
+void up_enable_irq(int irq)
+{
+ /* Verify that the IRQ number is within range */
+
+ if (irq < NR_IRQS)
+ {
+ /* Disable all interrupts */
+
+ irqstate_t flags = irqsave();
+
+ /* Enable the irq by setting the corresponding bit in the VIC
+ * Interrupt Enable register.
+ */
+
+ uint32_t val = vic_getreg(LPC214X_VIC_INTENABLE_OFFSET);
+ vic_putreg(val | (1 << irq), LPC214X_VIC_INTENABLE_OFFSET);
+ irqrestore(flags);
+ }
+}
+
+/****************************************************************************
+ * Name: up_attach_vector
+ *
+ * Description:
+ * Attach a user-supplied handler to a vectored interrupt
+ *
+ ****************************************************************************/
+
+#ifndef CONFIG_VECTORED_INTERRUPTS
+void up_attach_vector(int irq, int vector, vic_vector_t handler)
+{
+ /* Verify that the IRQ number and vector number are within range */
+
+ if (irq < NR_IRQS && vector < 16 && handler)
+ {
+ int offset = vector << 2;
+
+ /* Disable all interrupts */
+
+ irqstate_t flags = irqsave();
+
+ /* Save the vector address */
+
+ vic_putreg((uint32_t)handler, LPC214X_VIC_VECTADDR0_OFFSET + offset);
+
+ /* Enable the vectored interrupt */
+
+ vic_putreg(((irq << LPC214X_VECTCNTL_IRQSHIFT) | LPC214X_VECTCNTL_ENABLE),
+ LPC214X_VIC_VECTCNTL0_OFFSET + offset);
+ irqrestore(flags);
+ }
+}
+#endif
+
+/****************************************************************************
+ * Name: up_detach_vector
+ *
+ * Description:
+ * Detach a user-supplied handler from a vectored interrupt
+ *
+ ****************************************************************************/
+
+#ifndef CONFIG_VECTORED_INTERRUPTS
+void up_detach_vector(int vector)
+{
+ /* Verify that the vector number is within range */
+
+ if (vector < 16)
+ {
+ /* Disable the vectored interrupt */
+
+ int offset = vector << 2;
+ vic_putreg(0, LPC214X_VIC_VECTCNTL0_OFFSET + offset);
+ }
+}
+#endif
diff --git a/nuttx/arch/arm/src/lpc214x/lpc214x_lowputc.S b/nuttx/arch/arm/src/lpc214x/lpc214x_lowputc.S
new file mode 100644
index 000000000..b53e7aa78
--- /dev/null
+++ b/nuttx/arch/arm/src/lpc214x/lpc214x_lowputc.S
@@ -0,0 +1,209 @@
+/**************************************************************************
+ * arch/arm/src/lpc214x/lpc214X_lowputc.S
+ *
+ * Copyright (C) 2007, 2008 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ **************************************************************************/
+
+/**************************************************************************
+ * Included Files
+ **************************************************************************/
+
+#include <nuttx/config.h>
+
+#include "chip.h"
+#include "up_arch.h"
+#include "up_internal.h"
+
+#include "lpc214x_pinsel.h"
+#include "lpc214x_uart.h"
+
+/**************************************************************************
+ * Private Definitions
+ **************************************************************************/
+
+#if defined(CONFIG_UART0_SERIAL_CONSOLE)
+# define LPC214X_UART_BASE LPC214X_UART0_BASE
+# define LPC214X_UART_PINSEL LPC214X_UART0_PINSEL
+# define LPC214X_UART_PINMASK LPC214X_UART0_PINMASK
+# define LPC214X_UART_BAUD CONFIG_UART0_BAUD
+# define LPC214X_UART_BITS CONFIG_UART0_BITS
+# define LPC214X_UART_PARITY CONFIG_UART0_PARITY
+# define LPC214X_UART_2STOP CONFIG_UART0_2STOP
+#elif defined(CONFIG_UART1_SERIAL_CONSOLE)
+# define LPC214X_UART_BASE LPC214X_UART1_BASE
+# define LPC214X_UART_PINSEL LPC214X_UART1_PINSEL
+# define LPC214X_UART_PINMASK LPC214X_UART1_PINMASK
+# define LPC214X_UART_BAUD CONFIG_UART1_BAUD
+# define LPC214X_UART_BITS CONFIG_UART1_BITS
+# define LPC214X_UART_PARITY CONFIG_UART1_PARITY
+# define LPC214X_UART_2STOP CONFIG_UART1_2STOP
+#else
+# error "No CONFIG_UARTn_SERIAL_CONSOLE Setting"
+#endif
+
+#if LPC214X_UART_BITS == 5
+# define LPC214X_LCR_CHAR LPC214X_LCR_CHAR_5
+#elif LPC214X_UART_BITS == 6
+# define LPC214X_LCR_CHAR LPC214X_LCR_CHAR_6
+#elif LPC214X_UART_BITS == 7
+# define LPC214X_LCR_CHAR LPC214X_LCR_CHAR_7
+#elif LPC214X_UART_BITS == 8
+# define LPC214X_LCR_CHAR LPC214X_LCR_CHAR_8
+#else
+# error "No CONFIG_UARTn_BITS Setting"
+#endif
+
+#if LPC214X_UART_PARITY == 0
+# define LPC214X_LCR_PAR LPC214X_LCR_PAR_NONE
+#elif LPC214X_UART_PARITY == 1
+# define LPC214X_LCR_PAR LPC214X_LCR_PAR_ODD
+#elif LPC214X_UART_PARITY == 2
+# define LPC214X_LCR_PAR LPC214X_LCR_PAR_EVEN
+#elif LPC214X_UART_PARITY == 3
+# define LPC214X_LCR_PAR LPC214X_LCR_PAR_MARK
+#elif LPC214X_UART_PARITY == 4
+# define LPC214X_LCR_PAR LPC214X_LCR_PAR_SPACE
+#else
+# error "No CONFIG_UARTn_PARITY Setting"
+#endif
+
+#if LPC214X_UART_2STOP != 0
+# define LPC214X_LCR_STOP LPC214X_LCR_STOP_2
+#else
+# define LPC214X_LCR_STOP LPC214X_LCR_STOP_1
+#endif
+
+#define LPC214X_LCR_VALUE (LPC214X_LCR_CHAR | LPC214X_LCR_PAR | LPC214X_LCR_STOP)
+#define LPC214X_FCR_VALUE (LPC214X_FCR_FIFO_TRIG8 | LPC214X_FCR_TX_FIFO_RESET |\
+ LPC214X_FCR_RX_FIFO_RESET | LPC214X_FCR_FIFO_ENABLE)
+
+/**************************************************************************
+ * Private Types
+ **************************************************************************/
+
+/**************************************************************************
+ * Private Function Prototypes
+ **************************************************************************/
+
+/**************************************************************************
+ * Global Variables
+ **************************************************************************/
+
+/**************************************************************************
+ * Private Variables
+ **************************************************************************/
+
+/**************************************************************************
+ * Private Functions
+ **************************************************************************/
+
+/**************************************************************************
+ * Public Functions
+ **************************************************************************/
+
+/**************************************************************************
+ * Name: up_lowputc
+ **************************************************************************/
+
+/* This assembly language version has the advantage that it can does not
+ * require a C stack and uses only r0-r1. Hence it can be used during
+ * early boot phases.
+ */
+
+ .text
+ .global up_lowputc
+ .type up_lowputc, function
+up_lowputc:
+ /* On entry, r0 holds the character to be printed */
+
+ ldr r1, =LPC214X_UART_BASE
+ strb r0, [r1, #LPC214X_UART_THR_OFFSET]
+
+ /* Wait for the byte to be transferred */
+
+1: ldr r0, [r1, #LPC214X_UART_LSR_OFFSET]
+ ands r0, #LPC214X_LSR_TEMT /* Transmitter empty */
+ beq 1b
+
+ /* And return */
+
+ mov pc, lr
+ .size up_lowputc, . - up_lowputc
+
+/* This performs basic initialization of the UART. This can be called very
+ * early in initialization because it does not depend on having a stack. It
+ * modifies r0-r2 and r14.
+ */
+
+ .text
+ .globl up_lowsetup
+ .type up_lowsetup, function
+up_lowsetup:
+ /* Configure PINSEL0 */
+
+ ldr r0, =LPC214X_PINSEL0
+ ldr r1, [r0]
+ ldr r2, =~LPC214X_UART_PINMASK
+ and r1, r2
+ ldr r2, =LPC214X_UART_PINSEL
+ orr r1, r2
+ str r1, [r0]
+
+ /* Configure parity, data bits, stop bits and set DLAB=1 */
+
+ ldr r0, =LPC214X_UART_BASE
+ mov r1, #(LPC214X_LCR_VALUE | LPC214X_LCR_DLAB_ENABLE)
+ strb r1, [r0, #LPC214X_UART_LCR_OFFSET]
+
+ /* Set the BAUD divisor */
+
+ mov r1, #(UART_BAUD(LPC214X_UART_BAUD) >> 8)
+ strb r1, [r0, #LPC214X_UART_DLM_OFFSET]
+
+ mov r1, #(UART_BAUD(LPC214X_UART_BAUD) & 0xff)
+ strb r1, [r0, #LPC214X_UART_DLL_OFFSET]
+
+ /* Clear DLAB */
+
+ mov r1, #LPC214X_LCR_VALUE
+ strb r1, [r0, #LPC214X_UART_LCR_OFFSET]
+
+ /* Configure the FIFOs */
+
+ mov r1, #LPC214X_FCR_VALUE
+ strb r1, [r0, #LPC214X_UART_FCR_OFFSET]
+
+ /* And return */
+
+ mov pc, lr
+ .size up_lowsetup, . - up_lowsetup
+ .end
diff --git a/nuttx/arch/arm/src/lpc214x/lpc214x_pinsel.h b/nuttx/arch/arm/src/lpc214x/lpc214x_pinsel.h
new file mode 100644
index 000000000..b34eb86b6
--- /dev/null
+++ b/nuttx/arch/arm/src/lpc214x/lpc214x_pinsel.h
@@ -0,0 +1,259 @@
+/************************************************************************************
+ * arch/arm/src/lpc214x/lpc214x_pinsl.h
+ *
+ * Copyright (C) 2008 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ************************************************************************************/
+
+#ifndef _ARCH_ARM_SRC_LPC214X_PINSEL_H
+#define _ARCH_ARM_SRC_LPC214X_PINSEL_H
+
+/************************************************************************************
+ * Included Files
+ ************************************************************************************/
+
+/************************************************************************************
+ * Definitions
+ ************************************************************************************/
+
+/* Register address definitions *****************************************************/
+
+#define LPC214X_PINSEL0 (LPC214X_PINSEL_BASE + LPC214X_PINSEL0_OFFSET)
+#define LPC214X_PINSEL1 (LPC214X_PINSEL_BASE + LPC214X_PINSEL1_OFFSET)
+#define LPC214X_PINSEL2 (LPC214X_PINSEL_BASE + LPC214X_PINSEL2_OFFSET)
+
+/* Register bit definitions *********************************************************/
+
+#define LPC214X_PINSEL0_P00_GPIO (0x00000000)
+#define LPC214X_PINSEL0_P00_TXD0 (0x00000001)
+#define LPC214X_PINSEL0_P00_PWM1 (0x00000002)
+#define LPC214X_PINSEL0_P00_RSVD3 (0x00000003)
+#define LPC214X_PINSEL0_P00_MASK (0x00000003)
+
+#define LPC214X_PINSEL0_P01_GPIO (0x00000000)
+#define LPC214X_PINSEL0_P01_RXD0 (0x00000004)
+#define LPC214X_PINSEL0_P01_PWM3 (0x00000008)
+#define LPC214X_PINSEL0_P01_EINT0 (0x0000000c)
+#define LPC214X_PINSEL0_P01_MASK (0x0000000c)
+
+#define LPC214X_PINSEL0_P02_GPIO (0x00000000)
+#define LPC214X_PINSEL0_P02_SCL0 (0x00000010)
+#define LPC214X_PINSEL0_P02_CAP00 (0x00000020)
+#define LPC214X_PINSEL0_P02_RSVD3 (0x00000030)
+#define LPC214X_PINSEL0_P02_MASK (0x00000030)
+
+#define LPC214X_PINSEL0_P03_GPIO (0x00000000)
+#define LPC214X_PINSEL0_P03_SDA0 (0x00000040)
+#define LPC214X_PINSEL0_P03_MAT00 (0x00000080)
+#define LPC214X_PINSEL0_P03_EINT1 (0x000000c0)
+#define LPC214X_PINSEL0_P03_MASK (0x000000c0)
+
+#define LPC214X_PINSEL0_P04_GPIO (0x00000000)
+#define LPC214X_PINSEL0_P04_SCK0 (0x00000100)
+#define LPC214X_PINSEL0_P04_CAP01 (0x00000200)
+#define LPC214X_PINSEL0_P04_RSVD3 (0x00000300)
+#define LPC214X_PINSEL0_P04_MASK (0x00000300)
+
+#define LPC214X_PINSEL0_P05_GPIO (0x00000000)
+#define LPC214X_PINSEL0_P05_MISO0 (0x00000400)
+#define LPC214X_PINSEL0_P05_MAT01 (0x00000800)
+#define LPC214X_PINSEL0_P05_AD06 (0x00000c00)
+#define LPC214X_PINSEL0_P05_MASK (0x00000c00)
+
+#define LPC214X_PINSEL0_P06_GPIO (0x00000000)
+#define LPC214X_PINSEL0_P06_MOSI0 (0x00001000)
+#define LPC214X_PINSEL0_P06_CAP02 (0x00002000)
+#define LPC214X_PINSEL0_P06_AD10 (0x00003000)
+#define LPC214X_PINSEL0_P06_MASK (0x00003000)
+
+#define LPC214X_PINSEL0_P07_GPIO (0x00000000)
+#define LPC214X_PINSEL0_P07_SSEL0 (0x00004000)
+#define LPC214X_PINSEL0_P07_PWM2 (0x00008000)
+#define LPC214X_PINSEL0_P07_EINT2 (0x0000c000)
+#define LPC214X_PINSEL0_P07_MASK (0x0000c000)
+
+#define LPC214X_PINSEL0_P08_GPIO (0x00000000)
+#define LPC214X_PINSEL0_P08_TXD1 (0x00010000)
+#define LPC214X_PINSEL0_P08_PWM4 (0x00020000)
+#define LPC214X_PINSEL0_P08_AD11 (0x00030000)
+#define LPC214X_PINSEL0_P08_MASK (0x00030000)
+
+#define LPC214X_PINSEL0_P09_GPIO (0x00000000)
+#define LPC214X_PINSEL0_P09_RXD1 (0x00040000)
+#define LPC214X_PINSEL0_P09_PWM6 (0x00080000)
+#define LPC214X_PINSEL0_P09_EINT3 (0x000c0000)
+#define LPC214X_PINSEL0_P09_MASK (0x000c0000)
+
+#define LPC214X_PINSEL0_P010_GPIO (0x00000000)
+#define LPC214X_PINSEL0_P010_RTS1 (0x00100000)
+#define LPC214X_PINSEL0_P010_CAP10 (0x00200000)
+#define LPC214X_PINSEL0_P010_AD12 (0x00300000)
+#define LPC214X_PINSEL0_P010_MASK (0x00300000)
+
+#define LPC214X_PINSEL0_P011_GPIO (0x00000000)
+#define LPC214X_PINSEL0_P011_CTS1 (0x00400000)
+#define LPC214X_PINSEL0_P011_CAP11 (0x00800000)
+#define LPC214X_PINSEL0_P011_SCL1 (0x00c00000)
+#define LPC214X_PINSEL0_P011_MASK (0x00c00000)
+
+#define LPC214X_PINSEL0_P012_GPIO (0x00000000)
+#define LPC214X_PINSEL0_P012_DSR1 (0x01000000)
+#define LPC214X_PINSEL0_P012_MAT10 (0x02000000)
+#define LPC214X_PINSEL0_P012_AD13 (0x03000000)
+#define LPC214X_PINSEL0_P012_MASK (0x03000000)
+
+#define LPC214X_PINSEL0_P013_GPIO (0x00000000)
+#define LPC214X_PINSEL0_P013_DTR1 (0x04000000)
+#define LPC214X_PINSEL0_P013_MAT11 (0x08000000)
+#define LPC214X_PINSEL0_P013_AD14 (0x0c000000)
+#define LPC214X_PINSEL0_P013_MASK (0x0c000000)
+
+#define LPC214X_PINSEL0_P014_GPIO (0x00000000)
+#define LPC214X_PINSEL0_P014_DCD1 (0x10000000)
+#define LPC214X_PINSEL0_P014_EINT1 (0x20000000)
+#define LPC214X_PINSEL0_P014_SDA1 (0x30000000)
+#define LPC214X_PINSEL0_P014_MASK (0x30000000)
+
+#define LPC214X_PINSEL0_P015_GPIO (0x00000000)
+#define LPC214X_PINSEL0_P015_RI1 (0x40000000)
+#define LPC214X_PINSEL0_P015_EINT2 (0x80000000)
+#define LPC214X_PINSEL0_P015_AD15 (0xc0000000)
+#define LPC214X_PINSEL0_P015_MASK (0xc0000000)
+
+#define LPC214X_PINSEL1_P016_GPIO (0x00000000)
+#define LPC214X_PINSEL1_P016_EINT0 (0x00000001)
+#define LPC214X_PINSEL1_P016_MAT02 (0x00000002)
+#define LPC214X_PINSEL1_P016_CAP02 (0x00000003)
+#define LPC214X_PINSEL1_P016_MASK (0x00000003)
+
+#define LPC214X_PINSEL1_P017_GPIO (0x00000000)
+#define LPC214X_PINSEL1_P017_CAP12 (0x00000004)
+#define LPC214X_PINSEL1_P017_SCK1 (0x00000008)
+#define LPC214X_PINSEL1_P017_MAT12 (0x0000000c)
+#define LPC214X_PINSEL1_P017_MASK (0x0000000c)
+
+#define LPC214X_PINSEL1_P018_GPIO (0x00000000)
+#define LPC214X_PINSEL1_P018_CAP13 (0x00000010)
+#define LPC214X_PINSEL1_P018_MISO1 (0x00000020)
+#define LPC214X_PINSEL1_P018_MAT13 (0x00000030)
+#define LPC214X_PINSEL1_P018_MASK (0x00000030)
+
+#define LPC214X_PINSEL1_P019_GPIO (0x00000000)
+#define LPC214X_PINSEL1_P019_MAT12 (0x00000040)
+#define LPC214X_PINSEL1_P019_MOSI1 (0x00000080)
+#define LPC214X_PINSEL1_P019_CAP12 (0x000000c0)
+#define LPC214X_PINSEL1_P019_MASK (0x000000c0)
+
+#define LPC214X_PINSEL1_P020_GPIO (0x00000000)
+#define LPC214X_PINSEL1_P020_MAT13 (0x00000100)
+#define LPC214X_PINSEL1_P020_SSEL1 (0x00000200)
+#define LPC214X_PINSEL1_P020_EINT3 (0x00000300)
+#define LPC214X_PINSEL1_P020_MASK (0x00000300)
+
+#define LPC214X_PINSEL1_P021_GPIO (0x00000000)
+#define LPC214X_PINSEL1_P021_PWM5 (0x00000400)
+#define LPC214X_PINSEL1_P021_AD16 (0x00000800)
+#define LPC214X_PINSEL1_P021_CAP13 (0x00000c00)
+#define LPC214X_PINSEL1_P021_MASK (0x00000c00)
+
+#define LPC214X_PINSEL1_P022_GPIO (0x00000000)
+#define LPC214X_PINSEL1_P022_AD17 (0x00001000)
+#define LPC214X_PINSEL1_P022_CAP00 (0x00002000)
+#define LPC214X_PINSEL1_P022_MAT00 (0x00003000)
+#define LPC214X_PINSEL1_P022_MASK (0x00003000)
+
+#define LPC214X_PINSEL1_P023_GPIO (0x00000000)
+#define LPC214X_PINSEL1_P023_VBUS (0x00004000)
+#define LPC214X_PINSEL1_P023_RSVD2 (0x00008000)
+#define LPC214X_PINSEL1_P023_RSVD3 (0x0000c000)
+#define LPC214X_PINSEL1_P023_MASK (0x0000c000)
+
+#define LPC214X_PINSEL1_P024_RSVD0 (0x00000000)
+#define LPC214X_PINSEL1_P024_RSVD1 (0x00010000)
+#define LPC214X_PINSEL1_P024_RSVD2 (0x00020000)
+#define LPC214X_PINSEL1_P024_RSVD3 (0x00030000)
+#define LPC214X_PINSEL1_P024_MASK (0x00030000)
+
+#define LPC214X_PINSEL1_P025_GPIO (0x00000000)
+#define LPC214X_PINSEL1_P025_AD04 (0x00040000)
+#define LPC214X_PINSEL1_P025_AOUT (0x00080000)
+#define LPC214X_PINSEL1_P025_RSVD3 (0x000c0000)
+#define LPC214X_PINSEL1_P025_MASK (0x000c0000)
+
+#define LPC214X_PINSEL1_P026_RSVD0 (0x00000000)
+#define LPC214X_PINSEL1_P026_RSVD1 (0x00100000)
+#define LPC214X_PINSEL1_P026_RSVD2 (0x00200000)
+#define LPC214X_PINSEL1_P026_RSVD3 (0x00300000)
+#define LPC214X_PINSEL1_P026_MASK (0x00300000)
+
+#define LPC214X_PINSEL1_P027_RSVD0 (0x00000000)
+#define LPC214X_PINSEL1_P027_RSVD1 (0x00400000)
+#define LPC214X_PINSEL1_P027_RSVD2 (0x00800000)
+#define LPC214X_PINSEL1_P027_RSVD3 (0x00c00000)
+#define LPC214X_PINSEL1_P027_MASK (0x00c00000)
+
+#define LPC214X_PINSEL1_P028_GPIO (0x00000000)
+#define LPC214X_PINSEL1_P028_AD01 (0x01000000)
+#define LPC214X_PINSEL1_P028_CAP02 (0x02000000)
+#define LPC214X_PINSEL1_P028_MAT02 (0x03000000)
+#define LPC214X_PINSEL1_P028_MASK (0x03000000)
+
+#define LPC214X_PINSEL1_P029_GPIO (0x00000000)
+#define LPC214X_PINSEL1_P029_AD02 (0x04000000)
+#define LPC214X_PINSEL1_P029_CAP03 (0x08000000)
+#define LPC214X_PINSEL1_P029_MAT03 (0x0c000000)
+#define LPC214X_PINSEL1_P029_MASK (0x0c000000)
+
+#define LPC214X_PINSEL1_P030_GPIO (0x00000000)
+#define LPC214X_PINSEL1_P030_AD03 (0x10000000)
+#define LPC214X_PINSEL1_P030_EINT3 (0x20000000)
+#define LPC214X_PINSEL1_P030_CAP00 (0x30000000)
+#define LPC214X_PINSEL1_P030_MASK (0x30000000)
+
+#define LPC214X_PINSEL1_P031_GPIO (0x00000000)
+#define LPC214X_PINSEL1_P031_UPLED (0x40000000)
+#define LPC214X_PINSEL1_P031_CONNECT (0x80000000)
+#define LPC214X_PINSEL1_P031_RSVD3 (0xc0000000)
+#define LPC214X_PINSEL1_P031_MASK (0xc0000000)
+
+/************************************************************************************
+ * Public Types
+ ************************************************************************************/
+
+/************************************************************************************
+ * Inline Functions
+ ************************************************************************************/
+
+/************************************************************************************
+ * Public Function Prototypes
+ ************************************************************************************/
+
+#endif /* _ARCH_ARM_SRC_LPC214X_PINSEL_H */
diff --git a/nuttx/arch/arm/src/lpc214x/lpc214x_pll.h b/nuttx/arch/arm/src/lpc214x/lpc214x_pll.h
new file mode 100644
index 000000000..bea923e43
--- /dev/null
+++ b/nuttx/arch/arm/src/lpc214x/lpc214x_pll.h
@@ -0,0 +1,105 @@
+/****************************************************************************************************
+ * arch/arm/src/lpc214x/lpc214x_pll.h
+ *
+ * Copyright (C) 2008 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************************************/
+
+#ifndef _ARCH_ARM_SRC_LPC214X_PLL_H
+#define _ARCH_ARM_SRC_LPC214X_PLL_H
+
+/****************************************************************************************************
+ * Included Files
+ ****************************************************************************************************/
+
+#include <chip.h>
+
+/****************************************************************************************************
+ * Definitions
+ ****************************************************************************************************/
+
+/* PLL bass addresses *******************************************************************************/
+
+/* There are two PLLs: PLL0 generates CCLK and PLL1 is configured to provide the 48MHx USB clock */
+
+#define LPC214X_PLL0_BASE (LPC214X_PLL_BASE)
+#define LPC214X_PLL1_BASE (LPC214X_PLL_BASE + 0x00000020)
+
+/* PLL registers ************************************************************************************/
+
+#define LPC214x_PLL0_CON (LPC214X_PLL0_BASE+LPC214X_PLL_CON_OFFSET)
+#define LPC214x_PLL0_CFG (LPC214X_PLL0_BASE+LPC214X_PLL_CFG_OFFSET)
+#define LPC214x_PLL0_STAT (LPC214X_PLL0_BASE+LPC214X_PLL_STAT_OFFSET)
+#define LPC214x_PLL0_FEED (LPC214X_PLL0_BASE+LPC214X_PLL_FEED_OFFSET)
+
+#define LPC214x_PLL1_CON (LPC214X_PLL1_BASE+LPC214X_PLL_CON_OFFSET)
+#define LPC214x_PLL1_CFG (LPC214X_PLL1_BASE+LPC214X_PLL_CFG_OFFSET)
+#define LPC214x_PLL1_STAT (LPC214X_PLL1_BASE+LPC214X_PLL_STAT_OFFSET)
+#define LPC214x_PLL1_FEED (LPC214X_PLL1_BASE+LPC214X_PLL_FEED_OFFSET)
+
+/* Register bit settings ****************************************************************************/
+
+/* PLL Control Register Bit Settings */
+
+#define LPC214X_PLL_CON_PLLE (1 << 0) /* PLL Enable */
+#define LPC214X_PLL_CON_PLLC (1 << 1) /* PLL Connect */
+
+/* PLL Configuration Register Bit Settings */
+
+#define LPC214X_PLL_CFG_MSEL (0x1f << 0) /* PLL Multiplier (minus 1) */
+#define LPC214X_PLL_CFG_PSEL (0x03 << 5) /* PLL Divider (encoded) */
+#define LPC214X_PLL_CFG_PSEL1 (0x00 << 5)
+#define LPC214X_PLL_CFG_PSEL2 (0x01 << 5)
+#define LPC214X_PLL_CFG_PSEL4 (0x02 << 5)
+#define LPC214X_PLL_CFG_PSEL8 (0x03 << 5)
+
+/* PLL Status Register Bit Settings */
+
+#define LPC214X_PLL_STAT_MSEL (0x1f << 0) /* PLL Multiplier Readback */
+#define LPC214X_PLL_STAT_PSEL (0x03 << 5) /* PLL Divider Readback */
+#define LPC214X_PLL_STAT_PLLE (1 << 8) /* PLL Enable Readback */
+#define LPC214X_PLL_STAT_PLLC (1 << 9) /* PLL Connect Readback */
+#define LPC214X_PLL_STAT_PLOCK (1 << 10) /* PLL Lock Status */
+
+/* PLL Feed Register values */
+
+#define LPC214X_PLL_FEED1 0xaa
+#define LPC214X_PLL_FEED2 0x55
+
+/****************************************************************************************************
+ * Inline Functions
+ ****************************************************************************************************/
+
+/****************************************************************************************************
+ * Global Function Prototypes
+ ****************************************************************************************************/
+
+#endif /* _ARCH_ARM_SRC_LPC214X_PLL_H */
diff --git a/nuttx/arch/arm/src/lpc214x/lpc214x_power.h b/nuttx/arch/arm/src/lpc214x/lpc214x_power.h
new file mode 100644
index 000000000..7eb253160
--- /dev/null
+++ b/nuttx/arch/arm/src/lpc214x/lpc214x_power.h
@@ -0,0 +1,90 @@
+/************************************************************************************
+ * arch/arm/src/lpc214x/lpc214x_power.h
+ *
+ * Copyright (C) 2008 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ************************************************************************************/
+
+#ifndef _ARCH_ARM_SRC_LPC214X_POWER_H
+#define _ARCH_ARM_SRC_LPC214X_POWER_H
+
+/************************************************************************************
+ * Included Files
+ ************************************************************************************/
+
+/************************************************************************************
+ * Definitions
+ ************************************************************************************/
+
+/* Register address definitions *****************************************************/
+
+#define LPC214X_PCON_PCON (0xe01fc0c0) /* Power control register */
+#define LPC214X_PCON_PCONP (0xe01fc0c4) /* Power controls for peripherals register */
+
+/* Register bit definitions *********************************************************/
+
+/* Power control register */
+
+#define LPC214X_PCON_IDL (0x01) /* Bit 0=1: Idle mode ON */
+#define LPC214X_PCON_PD (0x02) /* Bit 1=1: Power down mode ON */
+#define LPC214X_PCON_BODPDM (0x04) /* Bit 2=1: Brown out power down mode ON */
+#define LPC214X_PCON_BOGD (0x08) /* Bit 3=1: Brown out global disable */
+#define LPC214X_PCON_BORD (0x10) /* Bit 4=1: Brown out reset disable */
+
+/* Peripheral power control register */
+
+#define LPC214X_PCONP_PCTIM0 (0x00000002) /* Bit 1=1: Timer/counter0 control */
+#define LPC214X_PCONP_PCTIM1 (0x00000004) /* Bit 2=1: Timer/counter1 control */
+#define LPC214X_PCONP_PCUART0 (0x00000008) /* Bit 3=1: UART0 control */
+#define LPC214X_PCONP_PCUART1 (0x00000010) /* Bit 4=1: UART1 control */
+#define LPC214X_PCONP_PCWM0 (0x00000020) /* Bit 5=1: PWM0 control */
+#define LPC214X_PCONP_PCI2C0 (0x00000080) /* Bit 7=1: I2C0 control */
+#define LPC214X_PCONP_PCSPI0 (0x00000100) /* Bit 8=1: SPI0 control */
+#define LPC214X_PCONP_PCRTC (0x00000200) /* Bit 9=1: RTCcontrol */
+#define LPC214X_PCONP_PCSPI1 (0x00000400) /* Bit 10=1: SPI1 control */
+#define LPC214X_PCONP_PCAD0 (0x00001000) /* Bit 12=1: A/C converter 0 control */
+#define LPC214X_PCONP_PCI2C1 (0x00080000) /* Bit 19=1: I2C1 control */
+#define LPC214X_PCONP_PCAD1 (0x00100000) /* Bit 20=1: A/C converter 1 control */
+#define LPC214X_PCONP_PCUSB (0x80000000) /* Bit 31=1: USB power/clock control */
+
+/************************************************************************************
+ * Public Types
+ ************************************************************************************/
+
+/************************************************************************************
+ * Inline Functions
+ ************************************************************************************/
+
+/************************************************************************************
+ * Public Function Prototypes
+ ************************************************************************************/
+
+#endif /* _ARCH_ARM_SRC_LPC214X_POWER_H */
diff --git a/nuttx/arch/arm/src/lpc214x/lpc214x_serial.c b/nuttx/arch/arm/src/lpc214x/lpc214x_serial.c
new file mode 100644
index 000000000..691adfa75
--- /dev/null
+++ b/nuttx/arch/arm/src/lpc214x/lpc214x_serial.c
@@ -0,0 +1,842 @@
+/****************************************************************************
+ * arch/arm/src/lpc214x/lpc214x_serial.c
+ *
+ * Copyright (C) 2007-2009, 2012 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <sys/types.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <unistd.h>
+#include <semaphore.h>
+#include <string.h>
+#include <errno.h>
+#include <debug.h>
+#include <nuttx/irq.h>
+#include <nuttx/arch.h>
+#include <nuttx/serial/serial.h>
+#include <arch/serial.h>
+
+#include "chip.h"
+#include "up_arch.h"
+#include "os_internal.h"
+#include "up_internal.h"
+
+#include "lpc214x_pinsel.h"
+#include "lpc214x_uart.h"
+
+#ifdef USE_SERIALDRIVER
+
+/****************************************************************************
+ * Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct up_dev_s
+{
+ uint32_t uartbase; /* Base address of UART registers */
+ uint32_t baud; /* Configured baud */
+ uint8_t ier; /* Saved IER value */
+ uint8_t irq; /* IRQ associated with this UART */
+ uint8_t parity; /* 0=none, 1=odd, 2=even */
+ uint8_t bits; /* Number of bits (7 or 8) */
+ bool stopbits2; /* true: Configure with 2 stop bits instead of 1 */
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+static int up_setup(struct uart_dev_s *dev);
+static void up_shutdown(struct uart_dev_s *dev);
+static int up_attach(struct uart_dev_s *dev);
+static void up_detach(struct uart_dev_s *dev);
+static int up_interrupt(int irq, void *context);
+static int up_ioctl(struct file *filep, int cmd, unsigned long arg);
+static int up_receive(struct uart_dev_s *dev, uint32_t *status);
+static void up_rxint(struct uart_dev_s *dev, bool enable);
+static bool up_rxavailable(struct uart_dev_s *dev);
+static void up_send(struct uart_dev_s *dev, int ch);
+static void up_txint(struct uart_dev_s *dev, bool enable);
+static bool up_txready(struct uart_dev_s *dev);
+static bool up_txempty(struct uart_dev_s *dev);
+
+/****************************************************************************
+ * Private Variables
+ ****************************************************************************/
+
+struct uart_ops_s g_uart_ops =
+{
+ .setup = up_setup,
+ .shutdown = up_shutdown,
+ .attach = up_attach,
+ .detach = up_detach,
+ .ioctl = up_ioctl,
+ .receive = up_receive,
+ .rxint = up_rxint,
+ .rxavailable = up_rxavailable,
+ .send = up_send,
+ .txint = up_txint,
+ .txready = up_txready,
+ .txempty = up_txempty,
+};
+
+/* I/O buffers */
+
+static char g_uart0rxbuffer[CONFIG_UART0_RXBUFSIZE];
+static char g_uart0txbuffer[CONFIG_UART0_TXBUFSIZE];
+static char g_uart1rxbuffer[CONFIG_UART1_RXBUFSIZE];
+static char g_uart1txbuffer[CONFIG_UART1_TXBUFSIZE];
+
+/* This describes the state of the LPC214X uart0 port. */
+
+static struct up_dev_s g_uart0priv =
+{
+ .uartbase = LPC214X_UART0_BASE,
+ .baud = CONFIG_UART0_BAUD,
+ .irq = LPC214X_UART0_IRQ,
+ .parity = CONFIG_UART0_PARITY,
+ .bits = CONFIG_UART0_BITS,
+ .stopbits2 = CONFIG_UART0_2STOP,
+};
+
+static uart_dev_t g_uart0port =
+{
+ .recv =
+ {
+ .size = CONFIG_UART0_RXBUFSIZE,
+ .buffer = g_uart0rxbuffer,
+ },
+ .xmit =
+ {
+ .size = CONFIG_UART0_TXBUFSIZE,
+ .buffer = g_uart0txbuffer,
+ },
+ .ops = &g_uart_ops,
+ .priv = &g_uart0priv,
+};
+
+/* This describes the state of the LPC214X uart1 port. */
+
+static struct up_dev_s g_uart1priv =
+{
+ .uartbase = LPC214X_UART1_BASE,
+ .baud = CONFIG_UART1_BAUD,
+ .irq = LPC214X_UART1_IRQ,
+ .parity = CONFIG_UART1_PARITY,
+ .bits = CONFIG_UART1_BITS,
+ .stopbits2 = CONFIG_UART1_2STOP,
+};
+
+static uart_dev_t g_uart1port =
+{
+ .recv =
+ {
+ .size = CONFIG_UART1_RXBUFSIZE,
+ .buffer = g_uart1rxbuffer,
+ },
+ .xmit =
+ {
+ .size = CONFIG_UART1_TXBUFSIZE,
+ .buffer = g_uart1txbuffer,
+ },
+ .ops = &g_uart_ops,
+ .priv = &g_uart1priv,
+};
+
+/* Now, which one with be tty0/console and which tty1? */
+
+#if defined(CONFIG_UART0_SERIAL_CONSOLE)
+# define CONSOLE_DEV g_uart0port
+# define TTYS0_DEV g_uart0port
+# define TTYS1_DEV g_uart1port
+#elif defined(CONFIG_UART1_SERIAL_CONSOLE)
+# define CONSOLE_DEV g_uart1port
+# define TTYS0_DEV g_uart1port
+# define TTYS1_DEV g_uart0port
+#else
+# error "No CONFIG_UARTn_SERIAL_CONSOLE Setting"
+#endif
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: up_serialin
+ ****************************************************************************/
+
+static inline uint8_t up_serialin(struct up_dev_s *priv, int offset)
+{
+ return getreg8(priv->uartbase + offset);
+}
+
+/****************************************************************************
+ * Name: up_serialout
+ ****************************************************************************/
+
+static inline void up_serialout(struct up_dev_s *priv, int offset, uint8_t value)
+{
+ putreg8(value, priv->uartbase + offset);
+}
+
+/****************************************************************************
+ * Name: up_disableuartint
+ ****************************************************************************/
+
+static inline void up_disableuartint(struct up_dev_s *priv, uint8_t *ier)
+{
+ if (ier)
+ {
+ *ier = priv->ier & LPC214X_IER_ALLIE;
+ }
+
+ priv->ier &= ~LPC214X_IER_ALLIE;
+ up_serialout(priv, LPC214X_UART_IER_OFFSET, priv->ier);
+}
+
+/****************************************************************************
+ * Name: up_restoreuartint
+ ****************************************************************************/
+
+static inline void up_restoreuartint(struct up_dev_s *priv, uint8_t ier)
+{
+ priv->ier |= ier & LPC214X_IER_ALLIE;
+ up_serialout(priv, LPC214X_UART_IER_OFFSET, priv->ier);
+}
+
+/****************************************************************************
+ * Name: up_waittxready
+ ****************************************************************************/
+
+static inline void up_waittxready(struct up_dev_s *priv)
+{
+ int tmp;
+
+ /* Limit how long we will wait for the TX available condition */
+ for (tmp = 1000 ; tmp > 0 ; tmp--)
+ {
+ /* Check if the tranmitter holding register (THR) is empty */
+ if ((up_serialin(priv, LPC214X_UART_LSR_OFFSET) & LPC214X_LSR_THRE) != 0)
+ {
+ /* The THR is empty, return */
+ break;
+ }
+ }
+}
+
+/****************************************************************************
+ * Name: up_enablebreaks
+ ****************************************************************************/
+
+static inline void up_enablebreaks(struct up_dev_s *priv, bool enable)
+{
+ uint8_t lcr = up_serialin(priv, LPC214X_UART_LCR_OFFSET);
+ if (enable)
+ {
+ lcr |= LPC214X_LCR_BREAK_ENABLE;
+ }
+ else
+ {
+ lcr &= ~LPC214X_LCR_BREAK_ENABLE;
+ }
+ up_serialout(priv, LPC214X_UART_LCR_OFFSET, lcr);
+}
+
+/****************************************************************************
+ * Name: up_setup
+ *
+ * Description:
+ * Configure the UART baud, bits, parity, fifos, etc. This
+ * method is called the first time that the serial port is
+ * opened.
+ *
+ ****************************************************************************/
+
+static int up_setup(struct uart_dev_s *dev)
+{
+#ifndef CONFIG_SUPPRESS_LPC214X_UART_CONFIG
+ struct up_dev_s *priv = (struct up_dev_s*)dev->priv;
+ uint16_t baud;
+ uint8_t lcr;
+
+ /* Clear fifos */
+
+ up_serialout(priv, LPC214X_UART_FCR_OFFSET,
+ (LPC214X_FCR_RX_FIFO_RESET|LPC214X_FCR_TX_FIFO_RESET));
+
+ /* Set trigger */
+
+ up_serialout(priv, LPC214X_UART_FCR_OFFSET,
+ (LPC214X_FCR_FIFO_ENABLE|LPC214X_FCR_FIFO_TRIG14));
+
+ /* Set up the IER */
+
+ priv->ier = up_serialin(priv, LPC214X_UART_IER_OFFSET);
+
+ /* Set up the LCR */
+
+ lcr = 0;
+
+ if (priv->bits == 7)
+ {
+ lcr |= LPC214X_LCR_CHAR_7;
+ }
+ else
+ {
+ lcr |= LPC214X_LCR_CHAR_8;
+ }
+
+ if (priv->stopbits2)
+ {
+ lcr |= LPC214X_LCR_STOP_2;
+ }
+
+ if (priv->parity == 1)
+ {
+ lcr |= LPC214X_LCR_PAR_ODD;
+ }
+ else if (priv->parity == 2)
+ {
+ lcr |= LPC214X_LCR_PAR_EVEN;
+ }
+
+ /* Enter DLAB=1 */
+
+ up_serialout(priv, LPC214X_UART_LCR_OFFSET,
+ (lcr | LPC214X_LCR_DLAB_ENABLE));
+
+ /* Set the BAUD divisor */
+
+ baud = UART_BAUD(priv->baud);
+ up_serialout(priv, LPC214X_UART_DLM_OFFSET, baud >> 8);
+ up_serialout(priv, LPC214X_UART_DLL_OFFSET, baud & 0xff);
+
+ /* Clear DLAB */
+
+ up_serialout(priv, LPC214X_UART_LCR_OFFSET, lcr);
+
+ /* Configure the FIFOs */
+
+ up_serialout(priv, LPC214X_UART_FCR_OFFSET,
+ (LPC214X_FCR_FIFO_TRIG8|LPC214X_FCR_TX_FIFO_RESET|\
+ LPC214X_FCR_RX_FIFO_RESET|LPC214X_FCR_FIFO_ENABLE));
+
+ /* The NuttX serial driver waits for the first THRE interrrupt before
+ * sending serial data... However, it appears that the lpc214x hardware
+ * does not generate that interrupt until a transition from not-empty
+ * to empty. So, the current kludge here is to send one NULL at
+ * startup to kick things off.
+ */
+
+ up_serialout(priv, LPC214X_UART_THR_OFFSET, '\0');
+#endif
+ return OK;
+}
+
+/****************************************************************************
+ * Name: up_shutdown
+ *
+ * Description:
+ * Disable the UART. This method is called when the serial
+ * port is closed
+ *
+ ****************************************************************************/
+
+static void up_shutdown(struct uart_dev_s *dev)
+{
+ struct up_dev_s *priv = (struct up_dev_s*)dev->priv;
+ up_disableuartint(priv, NULL);
+}
+
+/****************************************************************************
+ * Name: up_attach
+ *
+ * Description:
+ * Configure the UART to operation in interrupt driven mode. This method is
+ * called when the serial port is opened. Normally, this is just after the
+ * the setup() method is called, however, the serial console may operate in
+ * a non-interrupt driven mode during the boot phase.
+ *
+ * RX and TX interrupts are not enabled when by the attach method (unless the
+ * hardware supports multiple levels of interrupt enabling). The RX and TX
+ * interrupts are not enabled until the txint() and rxint() methods are called.
+ *
+ ****************************************************************************/
+
+static int up_attach(struct uart_dev_s *dev)
+{
+ struct up_dev_s *priv = (struct up_dev_s*)dev->priv;
+ int ret;
+
+ /* Attach and enable the IRQ */
+
+ ret = irq_attach(priv->irq, up_interrupt);
+ if (ret == OK)
+ {
+ /* Enable the interrupt (RX and TX interrupts are still disabled
+ * in the UART
+ */
+
+ up_enable_irq(priv->irq);
+ }
+ return ret;
+}
+
+/****************************************************************************
+ * Name: up_detach
+ *
+ * Description:
+ * Detach UART interrupts. This method is called when the serial port is
+ * closed normally just before the shutdown method is called. The exception is
+ * the serial console which is never shutdown.
+ *
+ ****************************************************************************/
+
+static void up_detach(struct uart_dev_s *dev)
+{
+ struct up_dev_s *priv = (struct up_dev_s*)dev->priv;
+ up_disable_irq(priv->irq);
+ irq_detach(priv->irq);
+}
+
+/****************************************************************************
+ * Name: up_interrupt
+ *
+ * Description:
+ * This is the UART interrupt handler. It will be invoked
+ * when an interrupt received on the 'irq' It should call
+ * uart_transmitchars or uart_receivechar to perform the
+ * appropriate data transfers. The interrupt handling logic\
+ * must be able to map the 'irq' number into the approprite
+ * uart_dev_s structure in order to call these functions.
+ *
+ ****************************************************************************/
+
+static int up_interrupt(int irq, void *context)
+{
+ struct uart_dev_s *dev = NULL;
+ struct up_dev_s *priv;
+ uint8_t status;
+ int passes;
+
+ if (g_uart1priv.irq == irq)
+ {
+ dev = &g_uart1port;
+ }
+ else if (g_uart0priv.irq == irq)
+ {
+ dev = &g_uart0port;
+ }
+ else
+ {
+ PANIC(OSERR_INTERNAL);
+ }
+ priv = (struct up_dev_s*)dev->priv;
+
+ /* Loop until there are no characters to be transferred or,
+ * until we have been looping for a long time.
+ */
+
+ for (passes = 0; passes < 256; passes++)
+ {
+ /* Get the current UART status and check for loop
+ * termination conditions
+ */
+
+ status = up_serialin(priv, LPC214X_UART_IIR_OFFSET);
+
+ /* The NO INTERRUPT should be zero if there are pending
+ * interrupts
+ */
+
+ if ((status & LPC214X_IIR_NO_INT) != 0)
+ {
+ /* Break out of the loop when there is no longer a
+ * pending interrupt
+ */
+
+ break;
+ }
+
+ /* Handle the interrupt by its interrupt ID field */
+
+ switch (status & LPC214X_IIR_MASK)
+ {
+ /* Handle incoming, receive bytes (with or without timeout) */
+
+ case LPC214X_IIR_RDA_INT:
+ case LPC214X_IIR_CTI_INT:
+ {
+ uart_recvchars(dev);
+ break;
+ }
+
+ /* Handle outgoing, transmit bytes */
+
+ case LPC214X_IIR_THRE_INT:
+ {
+ uart_xmitchars(dev);
+ break;
+ }
+
+ /* Just clear modem status interrupts (UART1 only) */
+
+ case LPC214X_IIR_MS_INT:
+ {
+ /* Read the modem status register (MSR) to clear */
+
+ status = up_serialin(priv, LPC214X_UART_MSR_OFFSET);
+ vdbg("MSR: %02x\n", status);
+ break;
+ }
+
+ /* Just clear any line status interrupts */
+
+ case LPC214X_IIR_RLS_INT:
+ {
+ /* Read the line status register (LSR) to clear */
+
+ status = up_serialin(priv, LPC214X_UART_LSR_OFFSET);
+ vdbg("LSR: %02x\n", status);
+ break;
+ }
+
+ /* There should be no other values */
+
+ default:
+ {
+ dbg("Unexpected IIR: %02x\n", status);
+ break;
+ }
+ }
+ }
+ return OK;
+}
+
+/****************************************************************************
+ * Name: up_ioctl
+ *
+ * Description:
+ * All ioctl calls will be routed through this method
+ *
+ ****************************************************************************/
+
+static int up_ioctl(struct file *filep, int cmd, unsigned long arg)
+{
+ struct inode *inode = filep->f_inode;
+ struct uart_dev_s *dev = inode->i_private;
+ struct up_dev_s *priv = (struct up_dev_s*)dev->priv;
+ int ret = OK;
+
+ switch (cmd)
+ {
+ case TIOCSERGSTRUCT:
+ {
+ struct up_dev_s *user = (struct up_dev_s*)arg;
+ if (!user)
+ {
+ ret = -EINVAL;
+ }
+ else
+ {
+ memcpy(user, dev, sizeof(struct up_dev_s));
+ }
+ }
+ break;
+
+ case TIOCSBRK: /* BSD compatibility: Turn break on, unconditionally */
+ {
+ irqstate_t flags = irqsave();
+ up_enablebreaks(priv, true);
+ irqrestore(flags);
+ }
+ break;
+
+ case TIOCCBRK: /* BSD compatibility: Turn break off, unconditionally */
+ {
+ irqstate_t flags;
+ flags = irqsave();
+ up_enablebreaks(priv, false);
+ irqrestore(flags);
+ }
+ break;
+
+ default:
+ ret = -ENOTTY;
+ break;
+ }
+
+ return ret;
+}
+
+/****************************************************************************
+ * Name: up_receive
+ *
+ * Description:
+ * Called (usually) from the interrupt level to receive one
+ * character from the UART. Error bits associated with the
+ * receipt are provided in the return 'status'.
+ *
+ ****************************************************************************/
+
+static int up_receive(struct uart_dev_s *dev, uint32_t *status)
+{
+ struct up_dev_s *priv = (struct up_dev_s*)dev->priv;
+ uint8_t rbr;
+
+ *status = up_serialin(priv, LPC214X_UART_LSR_OFFSET);
+ rbr = up_serialin(priv, LPC214X_UART_RBR_OFFSET);
+ return rbr;
+}
+
+/****************************************************************************
+ * Name: up_rxint
+ *
+ * Description:
+ * Call to enable or disable RX interrupts
+ *
+ ****************************************************************************/
+
+static void up_rxint(struct uart_dev_s *dev, bool enable)
+{
+ struct up_dev_s *priv = (struct up_dev_s*)dev->priv;
+ if (enable)
+ {
+#ifndef CONFIG_SUPPRESS_SERIAL_INTS
+ priv->ier |= LPC214X_IER_ERBFI;
+#endif
+ }
+ else
+ {
+ priv->ier &= ~LPC214X_IER_ERBFI;
+ }
+ up_serialout(priv, LPC214X_UART_IER_OFFSET, priv->ier);
+}
+
+/****************************************************************************
+ * Name: up_rxavailable
+ *
+ * Description:
+ * Return true if the receive fifo is not empty
+ *
+ ****************************************************************************/
+
+static bool up_rxavailable(struct uart_dev_s *dev)
+{
+ struct up_dev_s *priv = (struct up_dev_s*)dev->priv;
+ return ((up_serialin(priv, LPC214X_UART_LSR_OFFSET) & LPC214X_LSR_RDR) != 0);
+}
+
+/****************************************************************************
+ * Name: up_send
+ *
+ * Description:
+ * This method will send one byte on the UART
+ *
+ ****************************************************************************/
+
+static void up_send(struct uart_dev_s *dev, int ch)
+{
+ struct up_dev_s *priv = (struct up_dev_s*)dev->priv;
+ up_serialout(priv, LPC214X_UART_THR_OFFSET, (uint8_t)ch);
+}
+
+/****************************************************************************
+ * Name: up_txint
+ *
+ * Description:
+ * Call to enable or disable TX interrupts
+ *
+ ****************************************************************************/
+
+static void up_txint(struct uart_dev_s *dev, bool enable)
+{
+ struct up_dev_s *priv = (struct up_dev_s*)dev->priv;
+ if (enable)
+ {
+#ifndef CONFIG_SUPPRESS_SERIAL_INTS
+ priv->ier |= LPC214X_IER_ETBEI;
+#endif
+ }
+ else
+ {
+ priv->ier &= ~LPC214X_IER_ETBEI;
+ }
+ up_serialout(priv, LPC214X_UART_IER_OFFSET, priv->ier);
+}
+
+/****************************************************************************
+ * Name: up_txready
+ *
+ * Description:
+ * Return true if the tranmsit fifo is not full
+ *
+ ****************************************************************************/
+
+static bool up_txready(struct uart_dev_s *dev)
+{
+ struct up_dev_s *priv = (struct up_dev_s*)dev->priv;
+ return ((up_serialin(priv, LPC214X_UART_LSR_OFFSET) & LPC214X_LSR_THRE) != 0);
+}
+
+/****************************************************************************
+ * Name: up_txempty
+ *
+ * Description:
+ * Return true if the transmit fifo is empty
+ *
+ ****************************************************************************/
+
+static bool up_txempty(struct uart_dev_s *dev)
+{
+ struct up_dev_s *priv = (struct up_dev_s*)dev->priv;
+ return ((up_serialin(priv, LPC214X_UART_LSR_OFFSET) & LPC214X_LSR_THRE) != 0);
+}
+
+/****************************************************************************
+ * Public Funtions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: up_serialinit
+ *
+ * Description:
+ * Performs the low level UART initialization early in
+ * debug so that the serial console will be available
+ * during bootup. This must be called before up_serialinit.
+ *
+ ****************************************************************************/
+
+void up_earlyserialinit(void)
+{
+ /* Enable UART0 and 1 */
+
+ uint32_t pinsel = getreg32(LPC214X_PINSEL0);
+ pinsel &= ~(LPC214X_UART0_PINMASK|LPC214X_UART1_PINMASK);
+ pinsel |= (LPC214X_UART0_PINSEL|LPC214X_UART1_PINSEL);
+ putreg32(pinsel, LPC214X_PINSEL0);
+
+ /* Disable both UARTS */
+
+ up_disableuartint(TTYS0_DEV.priv, NULL);
+ up_disableuartint(TTYS1_DEV.priv, NULL);
+
+ /* Configuration whichever one is the console */
+
+ CONSOLE_DEV.isconsole = true;
+ up_setup(&CONSOLE_DEV);
+}
+
+/****************************************************************************
+ * Name: up_serialinit
+ *
+ * Description:
+ * Register serial console and serial ports. This assumes
+ * that up_earlyserialinit was called previously.
+ *
+ ****************************************************************************/
+
+void up_serialinit(void)
+{
+ (void)uart_register("/dev/console", &CONSOLE_DEV);
+ (void)uart_register("/dev/ttyS0", &TTYS0_DEV);
+ (void)uart_register("/dev/ttyS1", &TTYS1_DEV);
+}
+
+/****************************************************************************
+ * Name: up_putc
+ *
+ * Description:
+ * Provide priority, low-level access to support OS debug writes
+ *
+ ****************************************************************************/
+
+int up_putc(int ch)
+{
+ struct up_dev_s *priv = (struct up_dev_s*)CONSOLE_DEV.priv;
+ uint8_t ier;
+
+ up_disableuartint(priv, &ier);
+ up_waittxready(priv);
+ up_serialout(priv, LPC214X_UART_THR_OFFSET, (uint8_t)ch);
+
+ /* Check for LF */
+
+ if (ch == '\n')
+ {
+ /* Add CR */
+
+ up_waittxready(priv);
+ up_serialout(priv, LPC214X_UART_THR_OFFSET, '\r');
+ }
+
+ up_waittxready(priv);
+ up_restoreuartint(priv, ier);
+ return ch;
+}
+
+#else /* USE_SERIALDRIVER */
+
+/****************************************************************************
+ * Name: up_putc
+ *
+ * Description:
+ * Provide priority, low-level access to support OS debug writes
+ *
+ ****************************************************************************/
+
+int up_putc(int ch)
+{
+ /* Check for LF */
+
+ if (ch == '\n')
+ {
+ /* Add CR */
+
+ up_lowputc('\r');
+ }
+
+ up_lowputc(ch);
+ return ch;
+}
+
+#endif /* USE_SERIALDRIVER */
diff --git a/nuttx/arch/arm/src/lpc214x/lpc214x_spi.h b/nuttx/arch/arm/src/lpc214x/lpc214x_spi.h
new file mode 100644
index 000000000..ce6a03db9
--- /dev/null
+++ b/nuttx/arch/arm/src/lpc214x/lpc214x_spi.h
@@ -0,0 +1,166 @@
+/************************************************************************************
+ * arch/arm/src/lpc214x/lpc214x_spi.h
+ *
+ * Copyright (C) 2008 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ************************************************************************************/
+
+#ifndef _ARCH_ARM_SRC_LPC214X_SPI_H
+#define _ARCH_ARM_SRC_LPC214X_SPI_H
+
+/************************************************************************************
+ * Included Files
+ ************************************************************************************/
+
+#include "chip.h"
+
+/************************************************************************************
+ * Definitions
+ ************************************************************************************/
+
+/* Register address definitions *****************************************************/
+
+/* SPI absolute register addresses */
+
+#define LPC214X_SPI0_CR (LPC214X_SPI0_BASE+LPC214X_SPI0_CR_OFFSET) /* 16-bits wide */
+#define LPC214X_SPI0_SR (LPC214X_SPI0_BASE+LPC214X_SPI0_SR_OFFSET) /* 8-bits wide */
+#define LPC214X_SPI0_DR (LPC214X_SPI0_BASE+LPC214X_SPI0_DR_OFFSET) /* 16-bits wide */
+#define LPC214X_SPI0_CCR (LPC214X_SPI0_BASE+LPC214X_SPI0_CCR_OFFSET) /* 8-bits wide */
+#define LPC214X_SPI0_INT (LPC214X_SPI0_BASE+LPC214X_SPI0_INT_OFFSET) /* 8-bits wide */
+
+#define LPC214X_SPI1_CR0 (LPC214X_SPI1_BASE+LPC214X_SPI1_CR0_OFFSET) /* 16-bits wide */
+#define LPC214X_SPI1_CR1 (LPC214X_SPI1_BASE+LPC214X_SPI1_CR1_OFFSET) /* 8-bits wide */
+#define LPC214X_SPI1_DR (LPC214X_SPI1_BASE+LPC214X_SPI1_DR_OFFSET) /* 16-bits wide */
+#define LPC214X_SPI1_SR (LPC214X_SPI1_BASE+LPC214X_SPI1_SR_OFFSET) /* 8-bits wide */
+#define LPC214X_SPI1_CPSR (LPC214X_SPI1_BASE+LPC214X_SPI1_IMSC_OFFSET) /* 8-bits wide */
+#define LPC214X_SPI1_IMSC (LPC214X_SPI1_BASE+LPC214X_SPI1_IMSC_OFFSET) /* 8-bits wide */
+#define LPC214X_SPI1_RIS (LPC214X_SPI1_BASE+LPC214X_SPI1_RIS_OFFSET) /* 8-bits wide */
+#define LPC214X_SPI1_MIS (LPC214X_SPI1_BASE+LPC214X_SPI1_ICR_OFFSET) /* 8-bits wide */
+#define LPC214X_SPI1_ICR (LPC214X_SPI1_BASE+LPC214X_SPI1_ICR_OFFSET) /* 8-bits wide */
+
+/* SPI0 register bit definitions ****************************************************/
+
+/* Control Register (CR) for SPI0 */
+
+#define LPC214X_SPI0CR0_BITSENB (0x0004) /* Bit 2=0: 8-bits, else see bits 8-11 */
+#define LPC214X_SPI0CR0_CPHA (0x0008) /* Bit 3: Clock phase control */
+#define LPC214X_SPI0CR0_CPOL (0x0010) /* Bit 4: Clock polarity control */
+#define LPC214X_SPI0CR0_MSTR (0x0020) /* Bit 5=1: Master 0: Slave */
+#define LPC214X_SPI0CR0_LSBF (0x0040) /* Bit 6=1: Shift LSB first */
+#define LPC214X_SPI0CR0_SPIE (0x0080) /* Bit 7=1: SPI interrupt enable */
+#define LPC214X_SPI0CR0_BITSMASK (0x0f00) /* Bits 8-11: Number of bits per transfer */
+#define LPC214X_SPI0CR0_BITS8 (0x0800) /* 8-bits per transfer */
+#define LPC214X_SPI0CR0_BITS9 (0x0900) /* 9-bits per transfer */
+#define LPC214X_SPI0CR0_BITS10 (0x0a00) /* 10-bits per transfer */
+#define LPC214X_SPI0CR0_BITS11 (0x0b00) /* 11-bits per transfer */
+#define LPC214X_SPI0CR0_BITS12 (0x0c00) /* 12-bits per transfer */
+#define LPC214X_SPI0CR0_BITS13 (0x0d00) /* 13-bits per transfer */
+#define LPC214X_SPI0CR0_BITS14 (0x0e00) /* 14-bits per transfer */
+#define LPC214X_SPI0CR0_BITS15 (0x0f00) /* 15-bits per transfer */
+#define LPC214X_SPI0CR0_BITS16 (0x0000) /* 16-bits per transfer */
+
+/* Status Regiser (SR) for SPI0 */
+
+#define LPC214X_SPI0SR_ABRT (0x08) /* Bit 3=1: Slave abort */
+#define LPC214X_SPI0SR_MODF (0x10) /* Bit 4=1: Mode fault */
+#define LPC214X_SPI0SR_ROVR (0x20) /* Bit 5=1: Read overrun */
+#define LPC214X_SPI0SR_WCOL (0x40) /* Bit 6=1: Write collision */
+#define LPC214X_SPI0SR_SPIF (0x80) /* Bit 7=1: SPI transfer complete */
+
+/* Interrupt Register for SPI0 */
+
+#define LPC214X_SPO0INT_SPI (0x01) /* Bit 0=1: SPI interrupt */
+
+/* SPI1 register bit definitions ****************************************************/
+
+/* Control Register 0 (CR0) for SPI1 */
+
+#define LPC214X_SPI1CR0_DSSMASK (0x000f) /* Bits 0-3: Data size select mask */
+#define LPC214X_SPI1CR0_DSS4BIT (0x0003) /* 4-bit transfer */
+#define LPC214X_SPI1CR0_DSS5BIT (0x0004) /* 5-bit transfer */
+#define LPC214X_SPI1CR0_DSS6BIT (0x0005) /* 6-bit transfer */
+#define LPC214X_SPI1CR0_DSS7BIT (0x0006) /* 7-bit transfer */
+#define LPC214X_SPI1CR0_DSS8BIT (0x0007) /* 8-bit transfer */
+#define LPC214X_SPI1CR0_DSS9BIT (0x0008) /* 9-bit transfer */
+#define LPC214X_SPI1CR0_DSS10BIT (0x0009) /* 10-bit transfer */
+#define LPC214X_SPI1CR0_DSS11BIT (0x000a) /* 11-bit transfer */
+#define LPC214X_SPI1CR0_DSS12BIT (0x000b) /* 12-bit transfer */
+#define LPC214X_SPI1CR0_DSS13BIT (0x000c) /* 13-bit transfer */
+#define LPC214X_SPI1CR0_DSS14BIT (0x000d) /* 14-bit transfer */
+#define LPC214X_SPI1CR0_DSS15BIT (0x000e) /* 15-bit transfer */
+#define LPC214X_SPI1CR0_DSS16BIT (0x000f) /* 16-bit transfer */
+#define LPC214X_SPI1CR0_FRFMASK (0x0030) /* Bits 4-5: Frame format mask */
+#define LPC214X_SPI1CR0_FRFSPI (0x0000) /* SPI */
+#define LPC214X_SPI1CR0_FRFSSI (0x0010) /* SSI */
+#define LPC214X_SPI1CR0_FRFMW (0x0020) /* Microwire */
+#define LPC214X_SPI1CR0_CPOL (0x0040) /* Bit 6: Clock polarity control */
+#define LPC214X_SPI1CR0_CPHA (0x0080) /* Bit 7: Clock phase control */
+#define LPC214X_SPI1CR0_SCR (0xff00) /* Bits 8-15: Serial clock reate */
+
+/* Control Register 1 (CR1) */
+
+#define LPC214X_SPI1CR1_LBM (0x01) /* Bit 0: 1=Loopback mode */
+#define LPC214X_SPI1CR1_SSE (0x02) /* Bit 1: 1=SSP enable */
+#define LPC214X_SPI1CR1_MS (0x04) /* Bit 2: 1=Controller is slave */
+#define LPC214X_SPI1CR1_SOD (0x08) /* Bit 3: 1=Slave output disable */
+
+/* SSP Status Register (SR) */
+
+#define LPC214X_SPI1SR_TFE (0x01) /* Bit 0: 1=Transmit FIFO Empty */
+#define LPC214X_SPI1SR_TNF (0x02) /* Bit 1: 1=Transmit FIFO not full */
+#define LPC214X_SPI1SR_RNE (0x04) /* Bit 2: 1=Receive FIFO not empty */
+#define LPC214X_SPI1SR_RFF (0x08) /* Bit 3: 1=Receive FIFO full */
+#define LPC214X_SPI1SR_BSY (0x10) /* Bit 4: 1=Busy */
+
+/* Interrupt set/clear/status/mask registers (can't clear RXIM or TXIM) */
+
+#define LPC214X_SP1INT_ROR (0x01) /* Bit 0: 1=Recieve Overrun */
+#define LPC214X_SP1INT_RTIM (0x02) /* Bit 1: 1=Recieve Timeout */
+#define LPC214X_SP1INT_RXIM (0x04) /* Bit 2: 1=RX FIFO at least half full */
+#define LPC214X_SP1INT_TXIM (0x08) /* Bit 3: 1=TX FIFO at least half empty */
+
+/* SPI1 supports an 8-frame FIFO */
+
+#define LPC214X_SPI1_FIFOSZ (8)
+
+/************************************************************************************
+ * Public Types
+ ************************************************************************************/
+
+/************************************************************************************
+ * Inline Functions
+ ************************************************************************************/
+
+/************************************************************************************
+ * Public Function Prototypes
+ ************************************************************************************/
+
+#endif /* _ARCH_ARM_SRC_LPC214X_SPI_H */
diff --git a/nuttx/arch/arm/src/lpc214x/lpc214x_timer.h b/nuttx/arch/arm/src/lpc214x/lpc214x_timer.h
new file mode 100644
index 000000000..6c239f10c
--- /dev/null
+++ b/nuttx/arch/arm/src/lpc214x/lpc214x_timer.h
@@ -0,0 +1,152 @@
+/************************************************************************************
+ * arch/arm/src/lpc214x/lpc214x_timer.h
+ *
+ * Copyright (C) 2007, 2008 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ************************************************************************************/
+
+#ifndef __LPC214X_TIMER_H
+#define __LPC214X_TIMER_H
+
+/************************************************************************************
+ * Included Files
+ ************************************************************************************/
+
+/************************************************************************************
+ * Definitions
+ ************************************************************************************/
+
+/* Timer registers are 8-, 16-bit and 32-bits wide */
+
+/* Timer Interrupt Register Bit Definitions (8-bit) */
+
+#define LPC214X_TMR_IR_MR0I (1 << 0) /* Interrupt flag for match channel 0 */
+#define LPC214X_TMR_IR_MR1I (1 << 1) /* Interrupt flag for match channel 1 */
+#define LPC214X_TMR_IR_MR2I (1 << 2) /* Interrupt flag for match channel 2 */
+#define LPC214X_TMR_IR_MR3I (1 << 3) /* Interrupt flag for match channel 3 */
+#define LPC214X_TMR_IR_CR0I (1 << 4) /* Interrupt flag for capture channel 0 event */
+#define LPC214X_TMR_IR_CR1I (1 << 5) /* Interrupt flag for capture channel 1 event */
+#define LPC214X_TMR_IR_CR2I (1 << 6) /* Interrupt flag for capture channel 2 event */
+#define LPC214X_TMR_IR_CR3I (1 << 7) /* Interrupt flag for capture channel 3 event */
+#define LPC214X_TMR_IR_ALLI (0xff) /* All timer interrupts */
+
+/* Timer Control Register Bit Definitions (8-bits) */
+
+#define LPC214X_TMR_CR_ENABLE (1 << 0) /* Counter Enable */
+#define LPC214X_TMR_CR_RESET (1 << 1) /* Countger Reset */
+
+/* Timer Counter (32-bits, no bit fields) */
+
+/* Timer Prescale Register Bit Definitions (32-bits, no bit fields) */
+
+/* Timer Prescale Counter Register Bit Definitions */
+
+/* Timer Match Control Register Bit Definitions (16-bit) */
+
+#define LPC214X_TMR_MCR_MR0I (1 << 0) /* Enable Interrupt when MR0 matches TC */
+#define LPC214X_TMR_MCR_MR0R (1 << 1) /* Enable Reset of TC upon MR0 match */
+#define LPC214X_TMR_MCR_MR0S (1 << 2) /* Enable Stop of TC upon MR0 match */
+#define LPC214X_TMR_MCR_MR1I (1 << 3) /* Enable Interrupt when MR1 matches TC */
+#define LPC214X_TMR_MCR_MR1R (1 << 4) /* Enable Reset of TC upon MR1 match */
+#define LPC214X_TMR_MCR_MR1S (1 << 5) /* Enable Stop of TC upon MR1 match */
+#define LPC214X_TMR_MCR_MR2I (1 << 6) /* Enable Interrupt when MR2 matches TC */
+#define LPC214X_TMR_MCR_MR2R (1 << 7) /* Enable Reset of TC upon MR2 match */
+#define LPC214X_TMR_MCR_MR2S (1 << 8) /* Enable Stop of TC upon MR2 match */
+#define LPC214X_TMR_MCR_MR3I (1 << 9) /* Enable Interrupt when MR3 matches TC */
+#define LPC214X_TMR_MCR_MR3R (1 << 10) /* Enable Reset of TC upon MR3 match */
+#define LPC214X_TMR_MCR_MR3S (1 << 11) /* Enable Stop of TC upon MR3 match */
+
+/* Timer Match Register 0/1/2/3 (32-bits, no bit fields) */
+
+/* Timer Capture Control Register Bit Definitions */
+
+#define LPC214X_TMR_CCR_CAP0RE (1 << 0) /* Enable Rising edge on CAPn.0 will load TC to CR0 */
+#define LPC214X_TMR_CCR_CAP0FE (1 << 1) /* Enable Falling edge on CAPn.0 will load TC to CR0 */
+#define LPC214X_TMR_CCR_CAP0I (1 << 2) /* Enable Interrupt on load of CR0 */
+#define LPC214X_TMR_CCR_CAP1RE (1 << 3) /* Enable Rising edge on CAPn.1 will load TC to CR1 */
+#define LPC214X_TMR_CCR_CAP1FE (1 << 4) /* Enable Falling edge on CAPn.1 will load TC to CR1 */
+#define LPC214X_TMR_CCR_CAP1I (1 << 5) /* Enable Interrupt on load of CR1 */
+#define LPC214X_TMR_CCR_CAP2RE (1 << 6) /* Enable Rising edge on CAPn.2 will load TC to CR2 */
+#define LPC214X_TMR_CCR_CAP2FE (1 << 7) /* Enable Falling edge on CAPn.2 will load TC to CR2 */
+#define LPC214X_TMR_CCR_CAP2I (1 << 8) /* Enable Interrupt on load of CR2 */
+#define LPC214X_TMR_CCR_CAP3RE (1 << 9) /* Enable Rising edge on CAPn.3 will load TC to CR3 */
+#define LPC214X_TMR_CCR_CAP3FE (1 << 10) /* Enable Falling edge on CAPn.3 will load TC to CR3 */
+#define LPC214X_TMR_CCR_CAP3I (1 << 11) /* Enable Interrupt on load of CR3 */
+
+/* Timer Capture Register 0/1/2/3 (32-bits, no bit fields) */
+
+/* Timer External Match Register Bit Definitions */
+
+#define LPC214X_TMR_EMR_EM0 (1 << 0) /* External Match 0 */
+#define LPC214X_TMR_EMR_EM1 (1 << 1) /* External Match 1 */
+#define LPC214X_TMR_EMR_EM2 (1 << 2) /* External Match 2 */
+#define LPC214X_TMR_EMR_EM3 (1 << 3) /* External Match 3 */
+
+#define LPC214X_TMR_EMR_EMC0(b) ((b) << 4) /* External match control 0 (see below) */
+#define LPC214X_TMR_EMR_EMC1(b) ((b) << 6) /* External match control 1 (see below) */
+#define LPC214X_TMR_EMR_EMC2(b) ((b) << 8) /* External match control 2 (see below) */
+#define LPC214X_TMR_EMR_EMC3(b) ((b) << 10) /* External match control 3 (see below) */
+
+/* EMR External Match Control (EMCn) Field Falues */
+
+#define LPC214X_TMR_EMR_MASK (3) /* Mask for all bits */
+#define LPC214X_TMR_EMR_NOOP (0) /* Do nothing */
+#define LPC214X_TMR_EMR_CLEAR (1) /* Clear corresponding EMn bit/output to 0 */
+#define LPC214X_TMR_EMR_SET (2) /* Set corresponding EMn bit/output to 1 */
+#define LPC214X_TMR_EMR_TOGGLE (3) /* Toggle corresponding EMn bit/output */
+
+/* Timer Count Control Register Bit Definitions (8-bit) */
+
+#define LPC214X_TMR_
+#define LPC214X_TMR_CTCR_MODE_MASK (3 << 0) /* Counter/Timer Mode */
+#define LPC214X_TMR_CTCR_PCLK (0 << 0) /* Rising edge of PCLK */
+#define LPC214X_TMR_CTCR_RISING (1 << 0) /* Rising edge of CAP input */
+#define LPC214X_TMR_CTDR_FALLING (2 << 0) /* Failing edge of CAP input */
+#define LPC214X_TMR_CTCR_BOTH (3 << 0) /* Both edges of CAP input */
+#define LPC214X_TMR_CTCR_INPUT_MASK (3 << 2) /* Counter Input Select */
+#define LPC214X_TMR_CTCR_CR0 (0 << 2) /* CAPn.0 */
+#define LPC214X_TMR_CTCR_CR1 (1 << 2) /* CAPn.1 */
+#define LPC214X_TMR_CTCR_CR2 (2 << 2) /* CAPn.2 */
+#define LPC214X_TMR_CTCR_CR3 (3 << 2) /* CAPn.3 */
+
+/************************************************************************************
+ * Public Types
+ ************************************************************************************/
+
+/************************************************************************************
+ * Inline Functions
+ ************************************************************************************/
+
+/************************************************************************************
+ * Public Function Prototypes
+ ************************************************************************************/
+
+#endif /* __LPC214X_TIMER_H */
diff --git a/nuttx/arch/arm/src/lpc214x/lpc214x_timerisr.c b/nuttx/arch/arm/src/lpc214x/lpc214x_timerisr.c
new file mode 100644
index 000000000..99d1d118f
--- /dev/null
+++ b/nuttx/arch/arm/src/lpc214x/lpc214x_timerisr.c
@@ -0,0 +1,170 @@
+/****************************************************************************
+ * arch/arm/src/lpc214x/lpc214x_timerisr.c
+ *
+ * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <stdint.h>
+#include <debug.h>
+#include <nuttx/arch.h>
+#include <arch/board/board.h>
+
+#include "chip.h"
+#include "up_arch.h"
+#include "clock_internal.h"
+#include "up_internal.h"
+
+#include "lpc214x_timer.h"
+#include "lpc214x_vic.h"
+
+/****************************************************************************
+ * Definitions
+ ****************************************************************************/
+
+/* The timers count at the rate of PCLK which is determined by PLL_M and
+ * and APBDIV:
+ */
+
+#define LPC214X_CCLKFREQ (LPC214X_FOSC*LPC214X_PLL_M)
+#define LPC214X_PCLKFREQ (LPC214X_CCLKFREQ/LPC214X_APB_DIV)
+
+#define tmr_getreg8(o) getreg8(LPC214X_TMR0_BASE+(o))
+#define tmr_getreg16(o) getreg16(LPC214X_TMR0_BASE+(o))
+#define tmr_getreg32(o) getreg32(LPC214X_TMR0_BASE+(o))
+
+#define tmr_putreg8(v,o) putreg8((v), LPC214X_TMR0_BASE+(o))
+#define tmr_putreg16(v,o) putreg16((v), LPC214X_TMR0_BASE+(o))
+#define tmr_putreg32(v,o) putreg32((v), LPC214X_TMR0_BASE+(o))
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+/****************************************************************************
+ * Global Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Function: up_timerisr
+ *
+ * Description:
+ * The timer ISR will perform a variety of services for
+ * various portions of the systems.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_VECTORED_INTERRUPTS
+int up_timerisr(uint32_t *regs)
+#else
+int up_timerisr(int irq, uint32_t *regs)
+#endif
+{
+ /* Process timer interrupt */
+
+ sched_process_timer();
+
+ /* Clear the MR0 match interrupt */
+
+ tmr_putreg8(LPC214X_TMR_IR_MR0I, LPC214X_TMR_IR_OFFSET);
+
+ /* Reset the VIC as well */
+
+#ifdef CONFIG_VECTORED_INTERRUPTS
+ vic_putreg(0, LPC214X_VIC_VECTADDR_OFFSET);
+#endif
+ return 0;
+}
+
+/****************************************************************************
+ * Function: up_timerinit
+ *
+ * Description:
+ * This function is called during start-up to initialize
+ * the timer interrupt.
+ *
+ ****************************************************************************/
+
+void up_timerinit(void)
+{
+ uint16_t mcr;
+
+ /* Clear all match and capture event interrupts */
+
+ tmr_putreg8(LPC214X_TMR_IR_ALLI, LPC214X_TMR_IR_OFFSET);
+
+ /* Clear the timer counter */
+
+ tmr_putreg32(0, LPC214X_TMR_TC_OFFSET);
+
+ /* No pre-scaler */
+
+ tmr_putreg32(0, LPC214X_TMR_PR_OFFSET);
+
+ /* Set timer match registger to get a TICK_PER_SEC rate
+ * See arch/board.h and sched/os_internal.h
+ */
+
+ tmr_putreg32(LPC214X_PCLKFREQ/TICK_PER_SEC, LPC214X_TMR_MR0_OFFSET);
+
+ /* Reset timer counter regiser and interrupt on match */
+
+ mcr = tmr_getreg16(LPC214X_TMR_MCR_OFFSET);
+ mcr &= ~LPC214X_TMR_MCR_MR1I;
+ mcr |= (LPC214X_TMR_MCR_MR0I | LPC214X_TMR_MCR_MR0R);
+ tmr_putreg16(mcr, LPC214X_TMR_MCR_OFFSET);
+
+ /* Enable counting */
+
+ tmr_putreg8(LPC214X_TMR_CR_ENABLE, LPC214X_TMR_TCR_OFFSET);
+
+ /* Attach the timer interrupt vector */
+
+#ifdef CONFIG_VECTORED_INTERRUPTS
+ up_attach_vector(LPC214X_IRQ_SYSTIMER, LPC214X_SYSTIMER_VEC, (vic_vector_t)up_timerisr);
+#else
+ (void)irq_attach(LPC214X_IRQ_SYSTIMER, (xcpt_t)up_timerisr);
+#endif
+
+ /* And enable the timer interrupt */
+
+ up_enable_irq(LPC214X_IRQ_SYSTIMER);
+}
diff --git a/nuttx/arch/arm/src/lpc214x/lpc214x_uart.h b/nuttx/arch/arm/src/lpc214x/lpc214x_uart.h
new file mode 100644
index 000000000..fd634a816
--- /dev/null
+++ b/nuttx/arch/arm/src/lpc214x/lpc214x_uart.h
@@ -0,0 +1,142 @@
+/************************************************************************************
+ * arch/arm/src/lpc214x/uart.h
+ *
+ * Copyright (C) 2007, 2008 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ************************************************************************************/
+
+#ifndef __LPC214X_UART_H
+#define __LPC214X_UART_H
+
+/************************************************************************************
+ * Included Files
+ ************************************************************************************/
+
+#include <arch/board/board.h> /* For clock settings */
+
+/************************************************************************************
+ * Definitions
+ ************************************************************************************/
+
+/* PINSEL0 bit definitions for UART0/1 */
+
+#define LPC214X_UART0_PINSEL 0x00000005 /* PINSEL0 value for UART0 */
+#define LPC214X_UART0_PINMASK 0x0000000f /* PINSEL0 mask for UART0 */
+
+#define LPC214X_UART1_PINSEL 0x00050000 /* PINSEL0 value for UART1 */
+#define LPC214X_UART1_PINMASK 0x000f0000 /* PINSEL0 mask for UART1 */
+
+/* Derive baud divisor setting from clock settings (see board.h) */
+
+#define UART_BAUD(baud) ((LPC214X_FOSC * LPC214X_PLL_M) / (baud * 16))
+
+/* Interrupt Enable Register (IER) bit definitions */
+
+#define LPC214X_IER_ERBFI (1 << 0) /* Enable receive data available int */
+#define LPC214X_IER_ETBEI (1 << 1) /* Enable THR empty Interrupt */
+#define LPC214X_IER_ELSI (1 << 2) /* Enable receive line status int */
+#define LPC214X_IER_EDSSI (1 << 3) /* Enable MODEM atatus interrupt (2146/6/8 UART1 Only) */
+#define LPC214X_IER_ALLIE 0x0f /* All interrupts */
+
+/* Interrupt ID Register(IIR) bit definitions */
+
+#define LPC214X_IIR_NO_INT (1 << 0) /* No interrupts pending */
+#define LPC214X_IIR_MS_INT (0 << 1) /* MODEM Status (UART1 only) */
+#define LPC214X_IIR_THRE_INT (1 << 1) /* Transmit Holding Register Empty */
+#define LPC214X_IIR_RDA_INT (2 << 1) /* Receive Data Available */
+#define LPC214X_IIR_RLS_INT (3 << 1) /* Receive Line Status */
+#define LPC214X_IIR_CTI_INT (6 << 1) /* Character Timeout Indicator */
+#define LPC214X_IIR_MASK 0x0e
+
+/* FIFO Control Register (FCR) bit definitions */
+
+#define LPC214X_FCR_FIFO_ENABLE (1 << 0) /* FIFO enable */
+#define LPC214X_FCR_RX_FIFO_RESET (1 << 1) /* Reset receive FIFO */
+#define LPC214X_FCR_TX_FIFO_RESET (1 << 2) /* Reset transmit FIFO */
+#define LPC214X_FCR_FIFO_TRIG1 (0 << 6) /* Trigger @1 character in FIFO */
+#define LPC214X_FCR_FIFO_TRIG4 (1 << 6) /* Trigger @4 characters in FIFO */
+#define LPC214X_FCR_FIFO_TRIG8 (2 << 6) /* Trigger @8 characters in FIFO */
+#define LPC214X_FCR_FIFO_TRIG14 (3 << 6) /* Trigger @14 characters in FIFO */
+
+/* Line Control Register (LCR) bit definitions */
+
+#define LPC214X_LCR_CHAR_5 (0 << 0) /* 5-bit character length */
+#define LPC214X_LCR_CHAR_6 (1 << 0) /* 6-bit character length */
+#define LPC214X_LCR_CHAR_7 (2 << 0) /* 7-bit character length */
+#define LPC214X_LCR_CHAR_8 (3 << 0) /* 8-bit character length */
+#define LPC214X_LCR_STOP_1 (0 << 2) /* 1 stop bit */
+#define LPC214X_LCR_STOP_2 (1 << 2) /* 2 stop bits */
+#define LPC214X_LCR_PAR_NONE (0 << 3) /* No parity */
+#define LPC214X_LCR_PAR_ODD (1 << 3) /* Odd parity */
+#define LPC214X_LCR_PAR_EVEN (3 << 3) /* Even parity */
+#define LPC214X_LCR_PAR_MARK (5 << 3) /* Mark "1" parity */
+#define LPC214X_LCR_PAR_SPACE (7 << 3) /* Space "0" parity */
+#define LPC214X_LCR_BREAK_ENABLE (1 << 6) /* Output BREAK */
+#define LPC214X_LCR_DLAB_ENABLE (1 << 7) /* Enable divisor latch access */
+
+/* Modem Control Register (MCR) bit definitions */
+
+#define LPC214X_MCR_DTR (1 << 0) /* Data terminal ready */
+#define LPC214X_MCR_RTS (1 << 1) /* Request to send */
+#define LPC214X_MCR_LB (1 << 4) /* Loopback */
+
+/* Line Status Register (LSR) bit definitions */
+
+#define LPC214X_LSR_RDR (1 << 0) /* Receive data ready */
+#define LPC214X_LSR_OE (1 << 1) /* Overrun error */
+#define LPC214X_LSR_PE (1 << 2) /* Parity error */
+#define LPC214X_LSR_FE (1 << 3) /* Framing error */
+#define LPC214X_LSR_BI (1 << 4) /* Break interrupt */
+#define LPC214X_LSR_THRE (1 << 5) /* THR empty */
+#define LPC214X_LSR_TEMT (1 << 6) /* Transmitter empty */
+#define LPC214X_LSR_RXFE (1 << 7) /* Error in receive FIFO */
+#define LPC214X_LSR_ERR_MASK 0x1e
+
+/* Modem Status Register (MSR) bit definitions */
+
+#define LPC214X_MSR_DCTS (1 << 0) /* Delta clear to send */
+#define LPC214X_MSR_DDSR (1 << 1) /* Delta data set ready */
+#define LPC214X_MSR_TERI (1 << 2) /* Trailing edge ring indicator */
+#define LPC214X_MSR_DDCD (1 << 3) /* Delta data carrier detect */
+#define LPC214X_MSR_CTS (1 << 4) /* Clear to send */
+#define LPC214X_MSR_DSR (1 << 5) /* Data set ready */
+#define LPC214X_MSR_RI (1 << 6) /* Ring indicator */
+#define LPC214X_MSR_DCD (1 << 7) /* Data carrier detect */
+
+/************************************************************************************
+ * Inline Functions
+ ************************************************************************************/
+
+/************************************************************************************
+ * Global Function Prototypes
+ ************************************************************************************/
+
+#endif /* __LPC214X_UART_H */
diff --git a/nuttx/arch/arm/src/lpc214x/lpc214x_usbdev.c b/nuttx/arch/arm/src/lpc214x/lpc214x_usbdev.c
new file mode 100644
index 000000000..78a5fe1c3
--- /dev/null
+++ b/nuttx/arch/arm/src/lpc214x/lpc214x_usbdev.c
@@ -0,0 +1,3375 @@
+/*******************************************************************************
+ * arch/arm/src/lpc214x/lpc214x_usbdev.c
+ *
+ * Copyright (C) 2008-2010, 2012 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ *******************************************************************************/
+
+/*******************************************************************************
+ * Included Files
+ *******************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <sys/types.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <debug.h>
+
+#include <nuttx/arch.h>
+#include <nuttx/usb/usb.h>
+#include <nuttx/usb/usbdev.h>
+#include <nuttx/usb/usbdev_trace.h>
+
+#include <arch/irq.h>
+#include <arch/board/board.h>
+
+#include "chip.h"
+#include "up_arch.h"
+#include "up_internal.h"
+
+#include "lpc214x_usbdev.h"
+#include "lpc214x_pll.h"
+#include "lpc214x_power.h"
+
+/*******************************************************************************
+ * Definitions
+ *******************************************************************************/
+
+/* Configuration ***************************************************************/
+
+#ifndef CONFIG_USBDEV_EP0_MAXSIZE
+# define CONFIG_USBDEV_EP0_MAXSIZE 64
+#endif
+
+#ifndef CONFIG_USBDEV_MAXPOWER
+# define CONFIG_USBDEV_MAXPOWER 100 /* mA */
+#endif
+
+#define USB_SLOW_INT USBDEV_DEVINT_EPSLOW
+#define USB_DEVSTATUS_INT USBDEV_DEVINT_DEVSTAT
+
+#ifdef CONFIG_LPC214X_USBDEV_EPFAST_INTERRUPT
+# define USB_FAST_INT USBDEV_DEVINT_EPFAST
+#else
+# define USB_FAST_INT 0
+#endif
+
+/* Extremely detailed register debug that you would normally never want
+ * enabled.
+ */
+
+#undef CONFIG_LPC214X_USBDEV_REGDEBUG
+
+/* Enable reading SOF from interrupt handler vs. simply reading on demand. Probably
+ * a bad idea... Unless there is some issue with sampling the SOF from hardware
+ * asynchronously.
+ */
+
+#ifdef CONFIG_LPC214X_USBDEV_FRAME_INTERRUPT
+# define USB_FRAME_INT USBDEV_DEVINT_FRAME
+#else
+# define USB_FRAME_INT 0
+#endif
+
+#ifdef CONFIG_DEBUG
+# define USB_ERROR_INT USBDEV_DEVINT_EPRINT
+#else
+# define USB_ERROR_INT 0
+#endif
+
+/* Number of DMA descriptors */
+
+#ifdef CONFIG_LPC214X_USBDEV_DMA
+# error DMA SUPPORT NOT YET FULLY IMPLEMENTED
+# ifndef CONFIG_LPC214X_USBDEV_NDMADESCRIPTORS
+# define CONFIG_LPC214X_USBDEV_NDMADESCRIPTORS 8
+# elif CONFIG_LPC214X_USBDEV_NDMADESCRIPTORS > 30
+# define CONFIG_LPC214X_USBDEV_NDMADESCRIPTORS 30
+# endif
+#endif
+
+/* Debug ***********************************************************************/
+
+/* Trace error codes */
+
+#define LPC214X_TRACEERR_ALLOCFAIL 0x0001
+#define LPC214X_TRACEERR_BADCLEARFEATURE 0x0002
+#define LPC214X_TRACEERR_BADDEVGETSTATUS 0x0003
+#define LPC214X_TRACEERR_BADEPNO 0x0004
+#define LPC214X_TRACEERR_BADEPGETSTATUS 0x0005
+#define LPC214X_TRACEERR_BADEPTYPE 0x0006
+#define LPC214X_TRACEERR_BADGETCONFIG 0x0007
+#define LPC214X_TRACEERR_BADGETSETDESC 0x0008
+#define LPC214X_TRACEERR_BADGETSTATUS 0x0009
+#define LPC214X_TRACEERR_BADSETADDRESS 0x000a
+#define LPC214X_TRACEERR_BADSETCONFIG 0x000b
+#define LPC214X_TRACEERR_BADSETFEATURE 0x000c
+#define LPC214X_TRACEERR_BINDFAILED 0x000d
+#define LPC214X_TRACEERR_DISPATCHSTALL 0x000e
+#define LPC214X_TRACEERR_DMABUSY 0x000f
+#define LPC214X_TRACEERR_DRIVER 0x0010
+#define LPC214X_TRACEERR_DRIVERREGISTERED 0x0011
+#define LPC214X_TRACEERR_EP0INSTALLED 0x0012
+#define LPC214X_TRACEERR_EP0OUTSTALLED 0x0013
+#define LPC214X_TRACEERR_EP0SETUPSTALLED 0x0014
+#define LPC214X_TRACEERR_EPINNULLPACKET 0x0015
+#define LPC214X_TRACEERR_EPOUTNULLPACKET 0x0016
+#define LPC214X_TRACEERR_EPREAD 0x0017
+#define LPC214X_TRACEERR_INVALIDCMD 0x0018
+#define LPC214X_TRACEERR_INVALIDCTRLREQ 0x0019
+#define LPC214X_TRACEERR_INVALIDPARMS 0x001a
+#define LPC214X_TRACEERR_IRQREGISTRATION 0x001b
+#define LPC214X_TRACEERR_NODMADESC 0x001c
+#define LPC214X_TRACEERR_NOEP 0x001d
+#define LPC214X_TRACEERR_NOTCONFIGURED 0x001e
+#define LPC214X_TRACEERR_REQABORTED 0x001f
+
+/* Trace interrupt codes */
+
+#define LPC214X_TRACEINTID_USB 0x0001
+#define LPC214X_TRACEINTID_CLEARFEATURE 0x0002
+#define LPC214X_TRACEINTID_CONNECTCHG 0x0003
+#define LPC214X_TRACEINTID_CONNECTED 0x0004
+#define LPC214X_TRACEINTID_DEVGETSTATUS 0x0005
+#define LPC214X_TRACEINTID_DEVRESET 0x0006
+#define LPC214X_TRACEINTID_DEVSTAT 0x0007
+#define LPC214X_TRACEINTID_DISCONNECTED 0x0008
+#define LPC214X_TRACEINTID_DISPATCH 0x0009
+#define LPC214X_TRACEINTID_EP0IN 0x000a
+#define LPC214X_TRACEINTID_EP0OUT 0x000b
+#define LPC214X_TRACEINTID_EP0SETUP 0x000c
+#define LPC214X_TRACEINTID_EPDMA 0x000d
+#define LPC214X_TRACEINTID_EPFAST 0x000e
+#define LPC214X_TRACEINTID_EPGETSTATUS 0x000f
+#define LPC214X_TRACEINTID_EPIN 0x0010
+#define LPC214X_TRACEINTID_EPINQEMPTY 0x0011
+#define LPC214X_TRACEINTID_EP0INSETADDRESS 0x0012
+#define LPC214X_TRACEINTID_EPOUT 0x0013
+#define LPC214X_TRACEINTID_EPOUTQEMPTY 0x0014
+#define LPC214X_TRACEINTID_EP0SETUPSETADDRESS 0x0015
+#define LPC214X_TRACEINTID_EPRINT 0x0016
+#define LPC214X_TRACEINTID_EPSLOW 0x0017
+#define LPC214X_TRACEINTID_FRAME 0x0018
+#define LPC214X_TRACEINTID_GETCONFIG 0x0019
+#define LPC214X_TRACEINTID_GETSETDESC 0x001a
+#define LPC214X_TRACEINTID_GETSETIF 0x001b
+#define LPC214X_TRACEINTID_GETSTATUS 0x001c
+#define LPC214X_TRACEINTID_IFGETSTATUS 0x001d
+#define LPC214X_TRACEINTID_SETCONFIG 0x001e
+#define LPC214X_TRACEINTID_SETFEATURE 0x001f
+#define LPC214X_TRACEINTID_SUSPENDCHG 0x0020
+#define LPC214X_TRACEINTID_SYNCHFRAME 0x0021
+
+/* Hardware interface **********************************************************/
+
+/* Macros for testing the device status response */
+
+#define DEVSTATUS_CONNECT(s) (((s)&USBDEV_DEVSTATUS_CONNECT)!=0)
+#define DEVSTATUS_CONNCHG(s) (((s)&USBDEV_DEVSTATUS_CONNCHG)!=0)
+#define DEVSTATUS_SUSPEND(s) (((s)&USBDEV_DEVSTATUS_SUSPEND)!=0)
+#define DEVSTATUS_SUSPCHG(s) (((s)&USBDEV_DEVSTATUS_SUSPCHG)!=0)
+#define DEVSTATUS_RESET(s) (((s)&USBDEV_DEVSTATUS_RESET)!=0)
+
+/* If this bit is set in the lpc214x_epread response, it means that the
+ * recevied packet was overwritten by a later setup packet (ep0 only).
+ */
+
+#define LPC214X_READOVERRUN_BIT (0x80000000)
+#define LPC214X_READOVERRUN(s) (((s) & LPC214X_READOVERRUN_BIT) != 0)
+
+/* USB RAM ********************************************************************
+ *
+ * UBS_UDCA is is list of 32 pointers to DMA desciptors located at the
+ * beginning of USB RAM. Each pointer points to a DMA descriptor with
+ * assocated DMA buffer.
+ */
+
+#define USB_UDCA (uint32_t*)LPC214X_USBDEV_RAMBASE)
+#define USB_USCASIZE (LPC214X_NPHYSENDPOINTS*sizeof(uint32_t))
+
+/* Each descriptor must be aligned to a 128 address boundary */
+
+#define USB_DDALIGNDOWN(a) ((a)&~0x7f)
+#define USB_DDALIGNUP(a) USB_DDALIGNDOWN((a)+0x7f)
+
+#define USB_DDSIZE USB_DDALIGNDOWN((LPC214X_USBDEV_RAMSIZE-USB_USCASIZE)/CONFIG_LPC214X_USBDEV_NDMADESCRIPTORS)
+#define USB_DDESC ((struct lpc214x_dmadesc_s*)(LPC214X_USBDEV_RAMBASE+USB_USCASIZE))
+
+#ifdef CONFIG_USBDEV_ISOCHRONOUS
+# define USB_DDESCSIZE (5*sizeof(uint32_t))
+#else
+# define USB_DDESCSIZE (4*sizeof(uint32_t))
+#endif
+
+/* Endpoints ******************************************************************/
+
+/* Number of endpoints */
+
+#define LPC214X_NLOGENDPOINTS (16) /* ep0-15 */
+#define LPC214X_NPHYSENDPOINTS (32) /* x2 for IN and OUT */
+
+/* Odd physical endpoint numbers are IN; even are out */
+
+#define LPC214X_EPPHYIN(epphy) (((epphy)&1)!=0)
+#define LPC214X_EPPHYOUT(epphy) (((epphy)&1)==0)
+
+#define LPC214X_EPPHYIN2LOG(epphy) (((uint8_t)(epphy)>>1)|USB_DIR_IN)
+#define LPC214X_EPPHYOUT2LOG(epphy) (((uint8_t)(epphy)>>1)|USB_DIR_OUT)
+
+/* Each endpoint has somewhat different characteristics */
+
+#define LPC214X_EPALLSET (0xffffffff) /* All endpoints */
+#define LPC214X_EPOUTSET (0x55555555) /* Even phy endpoint numbers are OUT EPs */
+#define LPC214X_EPINSET (0xaaaaaaaa) /* Odd endpoint numbers are IN EPs */
+#define LPC214X_EPCTRLSET (0x00000003) /* EP0 IN/OUT are control endpoints */
+#define LPC214X_EPINTRSET (0x0c30c30c) /* Interrupt endpoints */
+#define LPC214X_EPBULKSET (0xf0c30c30) /* Bulk endpoints */
+#define LPC214X_EPISOCSET (0x030c30c0) /* Isochronous endpoints */
+#define LPC214X_EPDBLBUFFER (0xf3cf3cf0) /* Double buffered endpoints */
+
+#define LPC214X_EP0MAXPACKET (64) /* EP0 max packet size (1-64) */
+#define LPC214X_BULKMAXPACKET (64) /* Bulk endpoint max packet (8/16/32/64) */
+#define LPC214X_INTRMAXPACKET (64) /* Interrupt endpoint max packet (1 to 64) */
+#define LPC214X_ISOCMAXPACKET (512) /* Acutally 1..1023 */
+
+/* EP0 status. EP0 transfers occur in a number of different contexts. A
+ * simple state machine is required to handle the various transfer complete
+ * interrupt responses. The following values are the various states:
+ */
+ /*** INTERRUPT CAUSE ***/
+#define LPC214X_EP0REQUEST (0) /* Normal request handling */
+#define LPC214X_EP0STATUSIN (1) /* Status sent */
+#define LPC214X_EP0STATUSOUT (2) /* Status received */
+#define LPC214X_EP0SHORTWRITE (3) /* Short data sent with no request */
+#define LPC214X_EP0SHORTWRSENT (4) /* Short data write complete */
+#define LPC214X_EP0SETADDRESS (5) /* Set address received */
+#define LPC214X_EP0WRITEREQUEST (6) /* EP0 write request sent */
+
+/* Request queue operations ****************************************************/
+
+#define lpc214x_rqempty(ep) ((ep)->head == NULL)
+#define lpc214x_rqpeek(ep) ((ep)->head)
+
+/*******************************************************************************
+ * Private Types
+ *******************************************************************************/
+
+/* A container for a request so that the request make be retained in a list */
+
+struct lpc214x_req_s
+{
+ struct usbdev_req_s req; /* Standard USB request */
+ struct lpc214x_req_s *flink; /* Supports a singly linked list */
+};
+
+/* This is the internal representation of an endpoint */
+
+struct lpc214x_ep_s
+{
+ /* Common endpoint fields. This must be the first thing defined in the
+ * structure so that it is possible to simply cast from struct usbdev_ep_s
+ * to struct lpc214x_ep_s.
+ */
+
+ struct usbdev_ep_s ep; /* Standard endpoint structure */
+
+ /* LPC214X-specific fields */
+
+ struct lpc214x_usbdev_s *dev; /* Reference to private driver data */
+ struct lpc214x_req_s *head; /* Request list for this endpoint */
+ struct lpc214x_req_s *tail;
+ uint8_t epphy; /* Physical EP address */
+ uint8_t stalled:1; /* 1: Endpoint is stalled */
+ uint8_t halted:1; /* 1: Endpoint feature halted */
+ uint8_t txbusy:1; /* 1: TX endpoint FIFO full */
+ uint8_t txnullpkt:1; /* Null packet needed at end of transfer */
+};
+
+/* This represents a DMA descriptor */
+
+#ifdef CONFIG_LPC214X_USBDEV_DMA
+struct lpc214x_dmadesc_s
+{
+ uint32_t nextdesc; /* Address of the next DMA descripto in RAM */
+ uint32_t config; /* Misc. bit encoded configuration information */
+ uint32_t start; /* DMA start address */
+ uint32_t status; /* Misc. bit encoded status inforamation */
+#ifdef CONFIG_USBDEV_ISOCHRONOUS
+ uint32_t size; /* Isochronous packet size address */
+#endif
+ uint8_t buffer[USB_DDSIZE-USB_DDESCSIZE];
+};
+#endif
+
+/* This structure retains the state of the USB device controller */
+
+struct lpc214x_usbdev_s
+{
+ /* Common device fields. This must be the first thing defined in the
+ * structure so that it is possible to simply cast from struct usbdev_s
+ * to structlpc214x_usbdev_s.
+ */
+
+ struct usbdev_s usbdev;
+
+ /* The bound device class driver */
+
+ struct usbdevclass_driver_s *driver;
+
+ /* LPC214X-specific fields */
+
+ uint8_t devstatus; /* Last response to device status command */
+ uint8_t ep0state; /* State of certain EP0 operations */
+ uint8_t paddr; /* Address assigned by SETADDRESS */
+ uint8_t stalled:1; /* 1: Protocol stalled */
+ uint8_t selfpowered:1; /* 1: Device is self powered */
+ uint8_t paddrset:1; /* 1: Peripheral addr has been set */
+ uint8_t attached:1; /* 1: Host attached */
+ uint8_t rxpending:1; /* 1: RX pending */
+ uint32_t softprio; /* Bitset of high priority interrupts */
+ uint32_t epavail; /* Bitset of available endpoints */
+#ifdef CONFIG_LPC214X_USBDEV_FRAME_INTERRUPT
+ uint32_t sof; /* Last start-of-frame */
+#endif
+
+ /* Allocated DMA descriptor */
+
+#ifdef CONFIG_LPC214X_USBDEV_DMA
+ struct lpc214x_dmadesc_s *dmadesc;
+#endif
+
+ /* The endpoint list */
+
+ struct lpc214x_ep_s eplist[LPC214X_NPHYSENDPOINTS];
+};
+
+/*******************************************************************************
+ * Private Function Prototypes
+ *******************************************************************************/
+
+/* Register operations ********************************************************/
+
+#if defined(CONFIG_LPC214X_USBDEV_REGDEBUG) && defined(CONFIG_DEBUG)
+static uint32_t lpc214x_getreg(uint32_t addr);
+static void lpc214x_putreg(uint32_t val, uint32_t addr);
+#else
+# define lpc214x_getreg(addr) getreg32(addr)
+# define lpc214x_putreg(val,addr) putreg32(val,addr)
+#endif
+
+/* Command operations **********************************************************/
+
+static uint32_t lpc214x_usbcmd(uint16_t cmd, uint8_t data);
+
+/* Request queue operations ****************************************************/
+
+static FAR struct lpc214x_req_s *lpc214x_rqdequeue(FAR struct lpc214x_ep_s *privep);
+static void lpc214x_rqenqueue(FAR struct lpc214x_ep_s *privep,
+ FAR struct lpc214x_req_s *req);
+
+/* Low level data transfers and request operations *****************************/
+
+static void lpc214x_epwrite(uint8_t epphy, const uint8_t *data, uint32_t nbytes);
+static int lpc214x_epread(uint8_t epphy, uint8_t *data, uint32_t nbytes);
+static inline void lpc214x_abortrequest(struct lpc214x_ep_s *privep,
+ struct lpc214x_req_s *privreq, int16_t result);
+static void lpc214x_reqcomplete(struct lpc214x_ep_s *privep, int16_t result);
+static int lpc214x_wrrequest(struct lpc214x_ep_s *privep);
+static int lpc214x_rdrequest(struct lpc214x_ep_s *privep);
+static void lpc214x_cancelrequests(struct lpc214x_ep_s *privep);
+
+/* Interrupt handling **********************************************************/
+
+static struct lpc214x_ep_s *lpc214x_epfindbyaddr(struct lpc214x_usbdev_s *priv,
+ uint16_t eplog);
+static void lpc214x_eprealize(struct lpc214x_ep_s *privep, bool prio,
+ uint32_t packetsize);
+static uint8_t lpc214x_epclrinterrupt(uint8_t epphy);
+static inline void lpc214x_ep0configure(struct lpc214x_usbdev_s *priv);
+#ifdef CONFIG_LPC214X_USBDEV_DMA
+static inline void lpc214x_dmareset(uint32_t enable);
+#endif
+static void lpc214x_usbreset(struct lpc214x_usbdev_s *priv);
+static void lpc214x_dispatchrequest(struct lpc214x_usbdev_s *priv,
+ const struct usb_ctrlreq_s *ctrl);
+static inline void lpc214x_ep0setup(struct lpc214x_usbdev_s *priv);
+static inline void lpc214x_ep0dataoutinterrupt(struct lpc214x_usbdev_s *priv);
+static inline void lpc214x_ep0dataininterrupt(struct lpc214x_usbdev_s *priv);
+static int lpc214x_usbinterrupt(int irq, FAR void *context);
+
+#ifdef CONFIG_LPC214X_USBDEV_DMA
+static int lpc214x_dmasetup(struct lpc214x_usbdev_s *priv, uint8_t epphy,
+ uint32_t epmaxsize, uint32_t nbytes, uint32_t *isocpacket,
+ bool isochronous);
+static void lpc214x_dmarestart(uint8_t epphy, uint32_t descndx);
+static void lpc214x_dmadisable(uint8_t epphy);
+#endif /* CONFIG_LPC214X_USBDEV_DMA */
+
+/* Endpoint operations *********************************************************/
+
+static int lpc214x_epconfigure(FAR struct usbdev_ep_s *ep,
+ const struct usb_epdesc_s *desc, bool last);
+static int lpc214x_epdisable(FAR struct usbdev_ep_s *ep);
+static FAR struct usbdev_req_s *lpc214x_epallocreq(FAR struct usbdev_ep_s *ep);
+static void lpc214x_epfreereq(FAR struct usbdev_ep_s *ep,
+ FAR struct usbdev_req_s *);
+#ifdef CONFIG_USBDEV_DMA
+static FAR void *lpc214x_epallocbuffer(FAR struct usbdev_ep_s *ep,
+ uint16_t nbytes);
+static void lpc214x_epfreebuffer(FAR struct usbdev_ep_s *ep, void *buf);
+#endif
+static int lpc214x_epsubmit(FAR struct usbdev_ep_s *ep,
+ struct usbdev_req_s *req);
+static int lpc214x_epcancel(FAR struct usbdev_ep_s *ep,
+ struct usbdev_req_s *req);
+static int lpc214x_epstall(FAR struct usbdev_ep_s *ep, bool resume);
+
+/* USB device controller operations ********************************************/
+
+static FAR struct usbdev_ep_s *lcp214x_allocep(FAR struct usbdev_s *dev,
+ uint8_t epno, bool in, uint8_t eptype);
+static void lpc214x_freeep(FAR struct usbdev_s *dev, FAR struct usbdev_ep_s *ep);
+static int lpc214x_getframe(struct usbdev_s *dev);
+static int lpc214x_wakeup(struct usbdev_s *dev);
+static int lpc214x_selfpowered(struct usbdev_s *dev, bool selfpowered);
+static int lpc214x_pullup(struct usbdev_s *dev, bool enable);
+
+/*******************************************************************************
+ * Private Data
+ *******************************************************************************/
+
+/* Since there is only a single USB interface, all status information can be
+ * be simply retained in a single global instance.
+ */
+
+static struct lpc214x_usbdev_s g_usbdev;
+
+static const struct usbdev_epops_s g_epops =
+{
+ .configure = lpc214x_epconfigure,
+ .disable = lpc214x_epdisable,
+ .allocreq = lpc214x_epallocreq,
+ .freereq = lpc214x_epfreereq,
+#ifdef CONFIG_USBDEV_DMA
+ .allocbuffer = lpc214x_epallocbuffer,
+ .freebuffer = lpc214x_epfreebuffer,
+#endif
+ .submit = lpc214x_epsubmit,
+ .cancel = lpc214x_epcancel,
+ .stall = lpc214x_epstall,
+};
+
+static const struct usbdev_ops_s g_devops =
+{
+ .allocep = lcp214x_allocep,
+ .freeep = lpc214x_freeep,
+ .getframe = lpc214x_getframe,
+ .wakeup = lpc214x_wakeup,
+ .selfpowered = lpc214x_selfpowered,
+ .pullup = lpc214x_pullup,
+};
+
+/*******************************************************************************
+ * Public Data
+ *******************************************************************************/
+
+/*******************************************************************************
+ * Private Functions
+ *******************************************************************************/
+
+/*******************************************************************************
+ * Name: lpc214x_getreg
+ *
+ * Description:
+ * Get the contents of an LPC214x register
+ *
+ *******************************************************************************/
+
+#if defined(CONFIG_LPC214X_USBDEV_REGDEBUG) && defined(CONFIG_DEBUG)
+static uint32_t lpc214x_getreg(uint32_t addr)
+{
+ static uint32_t prevaddr = 0;
+ static uint32_t preval = 0;
+ static uint32_t count = 0;
+
+ /* Read the value from the register */
+
+ uint32_t val = getreg32(addr);
+
+ /* Is this the same value that we read from the same registe last time? Are
+ * we polling the register? If so, suppress some of the output.
+ */
+
+ if (addr == prevaddr && val == preval)
+ {
+ if (count == 0xffffffff || ++count > 3)
+ {
+ if (count == 4)
+ {
+ lldbg("...\n");
+ }
+ return val;
+ }
+ }
+
+ /* No this is a new address or value */
+
+ else
+ {
+ /* Did we print "..." for the previous value? */
+
+ if (count > 3)
+ {
+ /* Yes.. then show how many times the value repeated */
+
+ lldbg("[repeats %d more times]\n", count-3);
+ }
+
+ /* Save the new address, value, and count */
+
+ prevaddr = addr;
+ preval = val;
+ count = 1;
+ }
+
+ /* Show the register value read */
+
+ lldbg("%08x->%08x\n", addr, val);
+ return val;
+}
+#endif
+
+/*******************************************************************************
+ * Name: lpc214x_putreg
+ *
+ * Description:
+ * Set the contents of an LPC214x register to a value
+ *
+ *******************************************************************************/
+
+#if defined(CONFIG_LPC214X_USBDEV_REGDEBUG) && defined(CONFIG_DEBUG)
+static void lpc214x_putreg(uint32_t val, uint32_t addr)
+{
+ /* Show the register value being written */
+
+ lldbg("%08x<-%08x\n", addr, val);
+
+ /* Write the value */
+
+ putreg32(val, addr);
+}
+#endif
+
+/*******************************************************************************
+ * Name: lpc214x_usbcmd
+ *
+ * Description:
+ * Transmit commands to the USB engine
+ *
+ *******************************************************************************/
+
+static uint32_t lpc214x_usbcmd(uint16_t cmd, uint8_t data)
+{
+ irqstate_t flags;
+ uint32_t tmp = 0;
+
+ /* Disable interrupt and clear CDFULL and CCEMPTY interrupt status */
+
+ flags = irqsave();
+ lpc214x_putreg(USBDEV_DEVINT_CDFULL|USBDEV_DEVINT_CCEMTY, LPC214X_USBDEV_DEVINTCLR);
+
+ /* Load command + WR in command code register */
+
+ lpc214x_putreg(((cmd & 0xff) << 16) + CMD_USB_CMDWR, LPC214X_USBDEV_CMDCODE);
+
+ /* Wait until the command register is empty (CCEMPTY != 0, command is accepted) */
+
+ while ((lpc214x_getreg(LPC214X_USBDEV_DEVINTST) & USBDEV_DEVINT_CCEMTY) == 0);
+
+ /* Clear command register empty (CCEMPTY) interrupt */
+
+ lpc214x_putreg(USBDEV_DEVINT_CCEMTY, LPC214X_USBDEV_DEVINTCLR);
+
+ /* Determine next phase of the command */
+
+ switch (cmd)
+ {
+ /* Write operations (1 byte of data) */
+
+ case CMD_USB_DEV_SETADDRESS:
+ case CMD_USB_DEV_CONFIG:
+ case CMD_USB_DEV_SETMODE:
+ case CMD_USB_DEV_SETSTATUS:
+ {
+ /* Send data + WR and wait for CCEMPTY */
+
+ lpc214x_putreg((data << 16) + CMD_USB_DATAWR, LPC214X_USBDEV_CMDCODE);
+ while ((lpc214x_getreg(LPC214X_USBDEV_DEVINTST) & USBDEV_DEVINT_CCEMTY) == 0);
+ }
+ break;
+
+ /* 16 bit read operations */
+
+ case CMD_USB_DEV_READFRAMENO:
+ case CMD_USB_DEV_READTESTREG:
+ {
+ /* Send command code + RD and wait for CDFULL */
+
+ lpc214x_putreg((cmd << 16) + CMD_USB_DATARD, LPC214X_USBDEV_CMDCODE);
+ while ((lpc214x_getreg(LPC214X_USBDEV_DEVINTST) & USBDEV_DEVINT_CDFULL) == 0);
+
+ /* Clear CDFULL and read LS data */
+
+ lpc214x_putreg(USBDEV_DEVINT_CDFULL, LPC214X_USBDEV_DEVINTCLR);
+ tmp = lpc214x_getreg(LPC214X_USBDEV_CMDDATA);
+
+ /* Send command code + RD and wait for CDFULL */
+
+ lpc214x_putreg((cmd << 16) + CMD_USB_DATARD, LPC214X_USBDEV_CMDCODE);
+ while ((lpc214x_getreg(LPC214X_USBDEV_DEVINTST) & USBDEV_DEVINT_CDFULL) == 0);
+
+ /* Read MS data */
+
+ tmp |= lpc214x_getreg(LPC214X_USBDEV_CMDDATA) << 8;
+ }
+ break;
+
+ /* 8-bit read operations */
+
+ case CMD_USB_DEV_GETSTATUS:
+ case CMD_USB_DEV_GETERRORCODE:
+ case CMD_USB_DEV_READERRORSTATUS:
+ case CMD_USB_EP_CLRBUFFER:
+ {
+ /* Send command code + RD and wait for CDFULL */
+
+ lpc214x_putreg((cmd << 16) + CMD_USB_DATARD, LPC214X_USBDEV_CMDCODE);
+ while ((lpc214x_getreg(LPC214X_USBDEV_DEVINTST) & USBDEV_DEVINT_CDFULL) == 0);
+
+ /* Read data */
+
+ tmp = lpc214x_getreg(LPC214X_USBDEV_CMDDATA);
+ }
+ break;
+
+ /* No data transfer */
+
+ case CMD_USB_EP_VALIDATEBUFFER:
+ break;
+
+ default:
+ switch (cmd & 0x1e0)
+ {
+ case CMD_USB_EP_SELECT:
+ case CMD_USB_EP_SELECTCLEAR:
+ {
+ /* Send command code + RD and wait for CDFULL */
+
+ lpc214x_putreg((cmd << 16) + CMD_USB_DATARD, LPC214X_USBDEV_CMDCODE);
+ while ((lpc214x_getreg(LPC214X_USBDEV_DEVINTST) & USBDEV_DEVINT_CDFULL) == 0);
+
+ /* Read data */
+
+ tmp = lpc214x_getreg(LPC214X_USBDEV_CMDDATA);
+ }
+ break;
+
+ case CMD_USB_EP_SETSTATUS:
+ {
+ /* Send data + RD and wait for CCEMPTY */
+
+ lpc214x_putreg((data << 16) + CMD_USB_DATAWR, LPC214X_USBDEV_CMDCODE);
+ while ((lpc214x_getreg(LPC214X_USBDEV_DEVINTST) & USBDEV_DEVINT_CCEMTY) == 0);
+ }
+ break;
+
+ default:
+ usbtrace(TRACE_DEVERROR(LPC214X_TRACEERR_INVALIDCMD), 0);
+ break;
+ }
+ break;
+ }
+
+ /* Restore the interrupt flags */
+
+ irqrestore(flags);
+ return tmp;
+}
+
+/*******************************************************************************
+ * Name: lpc214x_rqdequeue
+ *
+ * Description:
+ * Remove a request from an endpoint request queue
+ *
+ *******************************************************************************/
+
+static FAR struct lpc214x_req_s *lpc214x_rqdequeue(FAR struct lpc214x_ep_s *privep)
+{
+ FAR struct lpc214x_req_s *ret = privep->head;
+
+ if (ret)
+ {
+ privep->head = ret->flink;
+ if (!privep->head)
+ {
+ privep->tail = NULL;
+ }
+
+ ret->flink = NULL;
+ }
+
+ return ret;
+}
+
+/*******************************************************************************
+ * Name: lpc214x_rqenqueue
+ *
+ * Description:
+ * Add a request from an endpoint request queue
+ *
+ *******************************************************************************/
+
+static void lpc214x_rqenqueue(FAR struct lpc214x_ep_s *privep,
+ FAR struct lpc214x_req_s *req)
+{
+ req->flink = NULL;
+ if (!privep->head)
+ {
+ privep->head = req;
+ privep->tail = req;
+ }
+ else
+ {
+ privep->tail->flink = req;
+ privep->tail = req;
+ }
+}
+
+/*******************************************************************************
+ * Name: lpc214x_epwrite
+ *
+ * Description:
+ * Endpoint write (IN)
+ *
+ *******************************************************************************/
+
+static void lpc214x_epwrite(uint8_t epphy, const uint8_t *data, uint32_t nbytes)
+{
+ uint32_t value;
+ bool aligned = (((uint32_t)data & 3) == 0);
+
+ /* Set the write enable bit for this physical EP address. Bits 2-5 are
+ * the logical endpoint number (0-15)
+ */
+
+ lpc214x_putreg(((epphy << 1) & LPC214X_USBCTRL_EPMASK) | LPC214X_USBCTRL_WREN,
+ LPC214X_USBDEV_CTRL);
+
+ /* Set the transmit packet length (nbytes must be less than 2048) */
+
+ lpc214x_putreg(nbytes, LPC214X_USBDEV_TXPLEN);
+
+ /* Transfer the packet data */
+
+ do
+ {
+ /* Zero length packets are a special case */
+
+ if (nbytes)
+ {
+ if (aligned)
+ {
+ value = *(uint32_t*)data;
+ }
+ else
+ {
+ value = (uint32_t)data[0] | ((uint32_t)data[1] << 8) |
+ ((uint32_t)data[2] << 16) | ((uint32_t)data[3] << 24);
+ }
+
+ lpc214x_putreg(value, LPC214X_USBDEV_TXDATA);
+ data += 4;
+ }
+ else
+ {
+ /* Zero length packet */
+
+ lpc214x_putreg(0, LPC214X_USBDEV_TXDATA);
+ }
+ }
+ while ((lpc214x_getreg(LPC214X_USBDEV_CTRL) & LPC214X_USBCTRL_WREN) != 0);
+
+ /* Done */
+
+ lpc214x_putreg(0, LPC214X_USBDEV_CTRL);
+ (void)lpc214x_usbcmd(CMD_USB_EP_SELECT | epphy, 0);
+ (void)lpc214x_usbcmd(CMD_USB_EP_VALIDATEBUFFER, 0);
+}
+
+/*******************************************************************************
+ * Name: lpc214x_epread
+ *
+ * Description:
+ * Endpoint read (OUT)
+ *
+ *******************************************************************************/
+
+static int lpc214x_epread(uint8_t epphy, uint8_t *data, uint32_t nbytes)
+{
+ uint32_t pktlen;
+ uint32_t result;
+ uint32_t value;
+ uint8_t aligned = 0;
+
+ /* If data is NULL, then we are being asked to read but discard the data.
+ * For most cases, the resulting buffer will be aligned and we will be
+ * able to do faster 32-bit transfers.
+ */
+
+ if (data)
+ {
+ if (((uint32_t)data & 3) == 0)
+ {
+ aligned = 1;
+ }
+ else
+ {
+ aligned = 2;
+ }
+ }
+
+ /* Set the read enable bit for this physical EP address. Bits 2-5 are
+ * the logical endpoint number (0-15).
+ */
+
+ lpc214x_putreg(((epphy << 1) & LPC214X_USBCTRL_EPMASK) | LPC214X_USBCTRL_RDEN,
+ LPC214X_USBDEV_CTRL);
+
+ /* Wait for packet buffer ready for reading */
+
+ while ((lpc214x_getreg(LPC214X_USBDEV_RXPLEN) & USBDEV_RXPLEN_PKTRDY) == 0);
+
+ /* Get the number of bytes of data to be read */
+
+ pktlen = lpc214x_getreg(LPC214X_USBDEV_RXPLEN) & USBDEV_RXPLEN_PKTLENGTH;
+
+ /* Read data from input buffer while read data is valid (DV) */
+
+ while ((lpc214x_getreg(LPC214X_USBDEV_RXPLEN) & USBDEV_RXPLEN_DV) != 0)
+ {
+ value = lpc214x_getreg(LPC214X_USBDEV_RXDATA);
+ if (aligned == 1)
+ {
+ *(uint32_t*)data = value;
+ data += 4;
+ }
+ else if (aligned == 2)
+ {
+ *data++ = (uint8_t)value;
+ *data++ = (uint8_t)(value >> 8);
+ *data++ = (uint8_t)(value >> 16);
+ *data++ = (uint8_t)(value >> 24);
+ }
+ }
+
+ /* Done */
+
+ lpc214x_putreg(0, LPC214X_USBDEV_CTRL);
+ (void)lpc214x_usbcmd(CMD_USB_EP_SELECT | epphy, 0);
+ result = lpc214x_usbcmd(CMD_USB_EP_CLRBUFFER, 0);
+
+ /* The packet overrun bit in the clear buffer response is applicable only
+ * on EP0 transfers. If set it means that the recevied packet was overwritten
+ * by a later setup packet.
+ */
+
+ if (epphy == LPC214X_EP0_OUT && (result & CMD_USB_CLRBUFFER_PO) != 0)
+ {
+ /* Pass this information in bit 31 */
+
+ pktlen |= LPC214X_READOVERRUN_BIT;
+ }
+ return pktlen;
+}
+
+/*******************************************************************************
+ * Name: lpc214x_abortrequest
+ *
+ * Description:
+ * Discard a request
+ *
+ *******************************************************************************/
+
+static inline void lpc214x_abortrequest(struct lpc214x_ep_s *privep,
+ struct lpc214x_req_s *privreq,
+ int16_t result)
+{
+ usbtrace(TRACE_DEVERROR(LPC214X_TRACEERR_REQABORTED), (uint16_t)privep->epphy);
+
+ /* Save the result in the request structure */
+
+ privreq->req.result = result;
+
+ /* Callback to the request completion handler */
+
+ privreq->req.callback(&privep->ep, &privreq->req);
+}
+
+/*******************************************************************************
+ * Name: lpc214x_reqcomplete
+ *
+ * Description:
+ * Handle termination of the request at the head of the endpoint request queue.
+ *
+ *******************************************************************************/
+
+static void lpc214x_reqcomplete(struct lpc214x_ep_s *privep, int16_t result)
+{
+ struct lpc214x_req_s *privreq;
+ int stalled = privep->stalled;
+ irqstate_t flags;
+
+ /* Remove the completed request at the head of the endpoint request list */
+
+ flags = irqsave();
+ privreq = lpc214x_rqdequeue(privep);
+ irqrestore(flags);
+
+ if (privreq)
+ {
+ /* If endpoint 0, temporarily reflect the state of protocol stalled
+ * in the callback.
+ */
+
+ if (privep->epphy == LPC214X_EP0_IN)
+ {
+ privep->stalled = privep->dev->stalled;
+ }
+
+ /* Save the result in the request structure */
+
+ privreq->req.result = result;
+
+ /* Callback to the request completion handler */
+
+ privreq->flink = NULL;
+ privreq->req.callback(&privep->ep, &privreq->req);
+
+ /* Restore the stalled indication */
+
+ privep->stalled = stalled;
+ }
+}
+
+/*******************************************************************************
+ * Name: lpc214x_wrrequest
+ *
+ * Description:
+ * Send from the next queued write request
+ *
+ *******************************************************************************/
+
+static int lpc214x_wrrequest(struct lpc214x_ep_s *privep)
+{
+ struct lpc214x_req_s *privreq;
+ uint8_t *buf;
+ int nbytes;
+ int bytesleft;
+
+ /* Check the request from the head of the endpoint request queue */
+
+ privreq = lpc214x_rqpeek(privep);
+ if (!privreq)
+ {
+ usbtrace(TRACE_INTDECODE(LPC214X_TRACEINTID_EPINQEMPTY), 0);
+ return OK;
+ }
+
+ ullvdbg("epphy=%d req=%p: len=%d xfrd=%d nullpkt=%d\n",
+ privep->epphy, privreq, privreq->req.len, privreq->req.xfrd, privep->txnullpkt);
+
+ /* Ignore any attempt to send a zero length packet on anything but EP0IN */
+
+ if (privreq->req.len == 0)
+ {
+ if (privep->epphy == LPC214X_EP0_IN)
+ {
+ lpc214x_epwrite(LPC214X_EP0_IN, NULL, 0);
+ }
+ else
+ {
+ usbtrace(TRACE_DEVERROR(LPC214X_TRACEERR_EPINNULLPACKET), 0);
+ }
+
+ /* In any event, the request is complete */
+
+ lpc214x_reqcomplete(privep, OK);
+ return OK;
+ }
+
+ /* Otherwise send the data in the packet (in the DMA on case, we
+ * may be resuming transfer already in progress.
+ */
+#warning REVISIT... If the EP supports double buffering, then we can do better
+
+ /* Get the number of bytes left to be sent in the packet */
+
+ bytesleft = privreq->req.len - privreq->req.xfrd;
+
+ /* Send the next packet if (1) there are more bytes to be sent, or
+ * (2) the last packet sent was exactly maxpacketsize (bytesleft == 0)
+ */
+
+ usbtrace(TRACE_WRITE(privep->epphy), privreq->req.xfrd);
+ if (bytesleft > 0 || privep->txnullpkt)
+ {
+ /* Indicate that there is data in the TX FIFO. This will be cleared
+ * when the EPIN interrupt is received
+ */
+
+ privep->txbusy = 1;
+
+ /* Try to send maxpacketsize -- unless we don't have that many
+ * bytes to send.
+ */
+
+ privep->txnullpkt = 0;
+ if (bytesleft > privep->ep.maxpacket)
+ {
+ nbytes = privep->ep.maxpacket;
+ }
+ else
+ {
+ nbytes = bytesleft;
+ if ((privreq->req.flags & USBDEV_REQFLAGS_NULLPKT) != 0)
+ {
+ privep->txnullpkt = (bytesleft == privep->ep.maxpacket);
+ }
+ }
+
+ /* Send the largest number of bytes that we can in this packet */
+
+ buf = privreq->req.buf + privreq->req.xfrd;
+ lpc214x_epwrite(privep->epphy, buf, nbytes);
+
+ /* Update for the next time through the loop */
+
+ privreq->req.xfrd += nbytes;
+ }
+
+ /* If all of the bytes were sent (including any final null packet)
+ * then we are finished with the transfer
+ */
+
+ if (privreq->req.xfrd >= privreq->req.len && !privep->txnullpkt)
+ {
+ usbtrace(TRACE_COMPLETE(privep->epphy), privreq->req.xfrd);
+ privep->txnullpkt = 0;
+ lpc214x_reqcomplete(privep, OK);
+ }
+
+ return OK;
+}
+
+/*******************************************************************************
+ * Name: lpc214x_rdrequest
+ *
+ * Description:
+ * Receive to the next queued read request
+ *
+ *******************************************************************************/
+
+static int lpc214x_rdrequest(struct lpc214x_ep_s *privep)
+{
+ struct lpc214x_req_s *privreq;
+ uint8_t *buf;
+ int nbytesread;
+
+ /* Check the request from the head of the endpoint request queue */
+
+ privreq = lpc214x_rqpeek(privep);
+ if (!privreq)
+ {
+ usbtrace(TRACE_INTDECODE(LPC214X_TRACEINTID_EPOUTQEMPTY), 0);
+ return OK;
+ }
+
+ ullvdbg("len=%d xfrd=%d nullpkt=%d\n",
+ privreq->req.len, privreq->req.xfrd, privep->txnullpkt);
+
+ /* Ignore any attempt to receive a zero length packet */
+
+ if (privreq->req.len == 0)
+ {
+ usbtrace(TRACE_DEVERROR(LPC214X_TRACEERR_EPOUTNULLPACKET), 0);
+ lpc214x_reqcomplete(privep, OK);
+ return OK;
+ }
+
+ usbtrace(TRACE_READ(privep->epphy), privreq->req.xfrd);
+
+ /* Receive the next packet */
+
+ buf = privreq->req.buf + privreq->req.xfrd;
+ nbytesread = lpc214x_epread(privep->epphy, buf, privep->ep.maxpacket);
+ if (nbytesread < 0)
+ {
+ usbtrace(TRACE_DEVERROR(LPC214X_TRACEERR_EPREAD), nbytesread);
+ return ERROR;
+ }
+
+ /* If the receive buffer is full or if the last packet was not full
+ * then we are finished with the transfer.
+ */
+
+ privreq->req.xfrd += nbytesread;
+ if (privreq->req.xfrd >= privreq->req.len || nbytesread < privep->ep.maxpacket)
+ {
+ usbtrace(TRACE_COMPLETE(privep->epphy), privreq->req.xfrd);
+ lpc214x_reqcomplete(privep, OK);
+ }
+
+ return OK;
+}
+
+/*******************************************************************************
+ * Name: lpc214x_cancelrequests
+ *
+ * Description:
+ * Cancel all pending requests for an endpoint
+ *
+ *******************************************************************************/
+
+static void lpc214x_cancelrequests(struct lpc214x_ep_s *privep)
+{
+ while (!lpc214x_rqempty(privep))
+ {
+ usbtrace(TRACE_COMPLETE(privep->epphy),
+ (lpc214x_rqpeek(privep))->req.xfrd);
+ lpc214x_reqcomplete(privep, -ESHUTDOWN);
+ }
+}
+
+/*******************************************************************************
+ * Name: lpc214x_epfindbyaddr
+ *
+ * Description:
+ * Find the physical endpoint structure corresponding to a logic endpoint
+ * address
+ *
+ *******************************************************************************/
+
+static struct lpc214x_ep_s *lpc214x_epfindbyaddr(struct lpc214x_usbdev_s *priv,
+ uint16_t eplog)
+{
+ struct lpc214x_ep_s *privep;
+ int i;
+
+ /* Endpoint zero is a special case */
+
+ if (USB_EPNO(eplog) == 0)
+ {
+ return &priv->eplist[0];
+ }
+
+ /* Handle the remaining */
+
+ for (i = 1; i < LPC214X_NPHYSENDPOINTS; i++)
+ {
+ privep = &priv->eplist[i];
+
+ /* Same logical endpoint number? (includes direction bit) */
+
+ if (eplog == privep->ep.eplog)
+ {
+ /* Return endpoint found */
+
+ return privep;
+ }
+ }
+
+ /* Return endpoint not found */
+
+ return NULL;
+}
+
+/*******************************************************************************
+ * Name: lpc214x_eprealize
+ *
+ * Description:
+ * Enable or disable an endpoint
+ *
+ *******************************************************************************/
+
+static void lpc214x_eprealize(struct lpc214x_ep_s *privep, bool prio, uint32_t packetsize)
+{
+ struct lpc214x_usbdev_s *priv = privep->dev;
+ uint32_t mask;
+ uint32_t reg;
+
+ /* Initialize endpoint software priority */
+
+ mask = 1 << privep->epphy;
+ if (prio)
+ {
+ priv->softprio = priv->softprio | mask;
+ }
+ else
+ {
+ priv->softprio = priv->softprio & ~mask;
+ }
+
+ /* Clear realize interrupt bit */
+
+ lpc214x_putreg(USBDEV_DEVINT_EPRLZED, LPC214X_USBDEV_DEVINTCLR);
+
+ /* Realize the endpoint */
+
+ reg = lpc214x_getreg(LPC214X_USBDEV_REEP);
+ reg |= (1 << privep->epphy);
+ lpc214x_putreg(reg, LPC214X_USBDEV_REEP);
+
+ /* Set endpoint maximum packet size */
+
+ lpc214x_putreg(privep->epphy, LPC214X_USBDEV_EPIND);
+ lpc214x_putreg(packetsize, LPC214X_USBDEV_MAXPSIZE);
+
+ /* Wait for Realize complete */
+
+ while ((lpc214x_getreg(LPC214X_USBDEV_DEVINTST) & USBDEV_DEVINT_EPRLZED) == 0);
+
+ /* Clear realize interrupt bit */
+
+ lpc214x_putreg(USBDEV_DEVINT_EPRLZED,LPC214X_USBDEV_DEVINTCLR);
+}
+
+/*******************************************************************************
+ * Name: lpc214x_epclrinterrupt
+ *
+ * Description:
+ * Clear the EP interrupt flag and return the current EP status
+ *
+ *******************************************************************************/
+
+static uint8_t lpc214x_epclrinterrupt(uint8_t epphy)
+{
+ /* Clear the endpoint interrupt */
+
+ lpc214x_putreg(1 << epphy, LPC214X_USBDEV_EPINTCLR);
+
+ /* Wait for data in the command data register */
+
+ while ((lpc214x_getreg(LPC214X_USBDEV_DEVINTST) & USBDEV_DEVINT_CDFULL) == 0);
+
+ /* Return the value of the command data register */
+
+ return lpc214x_getreg(LPC214X_USBDEV_CMDDATA);
+}
+
+/*******************************************************************************
+ * Name: lpc214x_ep0configure
+ *
+ * Description:
+ * Configure endpoint 0
+ *
+ *******************************************************************************/
+
+static inline void lpc214x_ep0configure(struct lpc214x_usbdev_s *priv)
+{
+ uint32_t inten;
+
+ /* EndPoint 0 initialization */
+
+ lpc214x_eprealize(&priv->eplist[LPC214X_CTRLEP_OUT], 0, CONFIG_USBDEV_EP0_MAXSIZE);
+ lpc214x_eprealize(&priv->eplist[LPC214X_CTRLEP_IN], 1, CONFIG_USBDEV_EP0_MAXSIZE);
+
+ /* Enable EP0 interrupts (not DMA) */
+
+ inten = lpc214x_getreg(LPC214X_USBDEV_EPINTEN);
+ inten |= 3; /* EP0 Rx and Tx */
+ lpc214x_putreg(inten, LPC214X_USBDEV_EPINTEN);
+}
+
+/*******************************************************************************
+ * Name: lpc214x_dmareset
+ *
+ * Description: Reset USB DMA
+ *
+ *******************************************************************************/
+
+#ifdef CONFIG_LPC214X_USBDEV_DMA
+static inline void lpc214x_dmareset(uint32_t enable)
+{
+ int i;
+
+ /* Disable All DMA interrupts */
+
+ lpc214x_putreg(0, LPC214X_USBDEV_DMAINTEN);
+
+ /* DMA Disable */
+
+ lpc214x_putreg(0xffffffff, LPC214X_USBDEV_EPDMADIS);
+
+ /* DMA Request clear */
+
+ putreq32(0xffffffff, LPC214X_USBDEV_DMARCLR);
+
+ /* End of Transfer Interrupt Clear */
+
+ putreq32(0xffffffff, LPC214X_USBDEV_EOTINTCLR);
+
+ /* New DD Request Interrupt Clear */
+
+ putreq32(0xffffffff, LPC214X_USBDEV_NDDRINTCLR);
+
+ /* System Error Interrupt Clear */
+
+ putreq32(0xffffffff, LPC214X_USBDEV_SYSERRINTCLR);
+
+ /* Nullify all pointers in the UDCA */
+
+ for (i = 0; i < LPC214X_NPHYSENDPOINTS; ++i)
+ {
+ USB_UDCA[i] = NULL;
+ }
+
+ /* Set USB UDCA Head register */
+
+ lpc214x_putreg((uint32_t)USB_UDCA, LPC214X_USBDEV_UDCAH);
+
+ /* Invalidate all DMA descriptors */
+
+ for (i = 0; i < CONFIG_LPC214X_USBDEV_NDMADESCRIPTORS; ++i)
+ {
+ memset(&USB_DDESC[i], 0, USB_DDESCSIZE);
+ }
+
+ /* Enable DMA interrupts */
+
+ lpc214x_putreg(enable, LPC214X_USBDEV_DMAINTEN);
+}
+#endif
+
+/*******************************************************************************
+ * Name: lpc214x_usbreset
+ *
+ * Description:
+ * Reset Usb engine
+ *
+ *******************************************************************************/
+
+static void lpc214x_usbreset(struct lpc214x_usbdev_s *priv)
+{
+ int epphy;
+
+ /* Disable all endpoint interrupts */
+
+ lpc214x_putreg(0, LPC214X_USBDEV_EPINTEN);
+
+ /* Frame is Hp interrupt */
+
+ lpc214x_putreg(1, LPC214X_USBDEV_DEVINTPRI);
+
+ /* Clear all pending interrupts */
+
+ lpc214x_putreg(0xffffffff, LPC214X_USBDEV_EPINTCLR);
+ lpc214x_putreg(0xffffffff, LPC214X_USBDEV_DEVINTCLR);
+
+ /* Periperhal address is needed */
+
+ priv->paddrset = 0;
+
+ /* Reset endpoints */
+
+ for (epphy = 0; epphy < LPC214X_NPHYSENDPOINTS; epphy++)
+ {
+ struct lpc214x_ep_s *privep = &priv->eplist[epphy];
+
+ lpc214x_cancelrequests(privep);
+
+ /* Reset endpoint status */
+
+ privep->stalled = false;
+ }
+
+ /* Tell the class driver that we are disconnected. The class
+ * driver should then accept any new configurations.
+ */
+
+ if (priv->driver)
+ {
+ CLASS_DISCONNECT(priv->driver, &priv->usbdev);
+ }
+
+ /* Endpoints not yet configured */
+
+ lpc214x_usbcmd(CMD_USB_DEV_CONFIG, 0);
+
+ /* EndPoint 0 initialization */
+
+ lpc214x_ep0configure(priv);
+
+ /* Enable End_of_Transfer_Interrupt and System_Error_Interrupt USB DMA
+ * interrupts
+ */
+
+#ifdef CONFIG_LPC214X_USBDEV_DMA
+ lpc214x_dmareset(CONFIG_LPC214X_USBDEV_DMAINTMASK);
+#endif
+
+ /* Enable Device interrupts */
+
+ lpc214x_putreg(USB_SLOW_INT|USB_DEVSTATUS_INT|USB_FAST_INT|USB_FRAME_INT|USB_ERROR_INT,
+ LPC214X_USBDEV_DEVINTEN);
+}
+
+/*******************************************************************************
+ * Name: lpc214x_dispatchrequest
+ *
+ * Description:
+ * Provide unhandled setup actions to the class driver. This is logically part
+ * of the USB interrupt handler.
+ *
+ *******************************************************************************/
+
+static void lpc214x_dispatchrequest(struct lpc214x_usbdev_s *priv,
+ const struct usb_ctrlreq_s *ctrl)
+{
+ int ret;
+
+ usbtrace(TRACE_INTDECODE(LPC214X_TRACEINTID_DISPATCH), 0);
+ if (priv && priv->driver)
+ {
+ /* Forward to the control request to the class driver implementation */
+
+ ret = CLASS_SETUP(priv->driver, &priv->usbdev, ctrl, NULL, 0);
+ if (ret < 0)
+ {
+ /* Stall on failure */
+
+ usbtrace(TRACE_DEVERROR(LPC214X_TRACEERR_DISPATCHSTALL), 0);
+ priv->stalled = 1;
+ }
+ }
+}
+
+/*******************************************************************************
+ * Name: lpc214x_ep0setup
+ *
+ * Description:
+ * USB Ctrl EP Setup Event. This is logically part of the USB interrupt
+ * handler. This event occurs when a setup packet is receive on EP0 OUT.
+ *
+ *******************************************************************************/
+
+static inline void lpc214x_ep0setup(struct lpc214x_usbdev_s *priv)
+{
+ struct lpc214x_ep_s *ep0 = &priv->eplist[LPC214X_EP0_OUT];
+ struct lpc214x_ep_s *privep;
+ struct lpc214x_req_s *privreq = lpc214x_rqpeek(ep0);
+ struct usb_ctrlreq_s ctrl;
+ uint16_t value;
+ uint16_t index;
+ uint16_t len;
+ uint8_t response[2];
+ int ret;
+
+ /* Starting a control request? */
+
+ if (priv->usbdev.speed == USB_SPEED_UNKNOWN)
+ {
+ priv->usbdev.speed = USB_SPEED_FULL;
+ lpc214x_usbcmd(CMD_USB_DEV_CONFIG, 1);
+ }
+
+ /* Terminate any pending requests */
+
+ while (!lpc214x_rqempty(ep0))
+ {
+ int16_t result = OK;
+ if (privreq->req.xfrd != privreq->req.len)
+ {
+ result = -EPROTO;
+ }
+
+ usbtrace(TRACE_COMPLETE(ep0->epphy), privreq->req.xfrd);
+ lpc214x_reqcomplete(ep0, result);
+ }
+
+ /* Assume NOT stalled */
+
+ ep0->stalled = 0;
+ priv->stalled = 0;
+
+ /* Read EP0 data */
+
+ ret = lpc214x_epread(LPC214X_EP0_OUT, (uint8_t*)&ctrl, USB_SIZEOF_CTRLREQ);
+ if (ret <= 0)
+ {
+ return;
+ }
+
+ /* And extract the little-endian 16-bit values to host order */
+
+ value = GETUINT16(ctrl.value);
+ index = GETUINT16(ctrl.index);
+ len = GETUINT16(ctrl.len);
+
+ ullvdbg("type=%02x req=%02x value=%04x index=%04x len=%04x\n",
+ ctrl.type, ctrl.req, value, index, len);
+
+ /* Dispatch any non-standard requests */
+
+ if ((ctrl.type & USB_REQ_TYPE_MASK) != USB_REQ_TYPE_STANDARD)
+ {
+ lpc214x_dispatchrequest(priv, &ctrl);
+ return;
+ }
+
+ /* Handle standard request. Pick off the things of interest to the
+ * USB device controller driver; pass what is left to the class driver
+ */
+
+ switch (ctrl.req)
+ {
+ case USB_REQ_GETSTATUS:
+ {
+ /* type: device-to-host; recipient = device, interface, endpoint
+ * value: 0
+ * index: zero interface endpoint
+ * len: 2; data = status
+ */
+
+ usbtrace(TRACE_INTDECODE(LPC214X_TRACEINTID_GETSTATUS), 0);
+ if (!priv->paddrset || len != 2 ||
+ (ctrl.type & USB_REQ_DIR_IN) == 0 || value != 0)
+ {
+ priv->stalled = 1;
+ }
+ else
+ {
+ switch (ctrl.type & USB_REQ_RECIPIENT_MASK)
+ {
+ case USB_REQ_RECIPIENT_ENDPOINT:
+ {
+ usbtrace(TRACE_INTDECODE(LPC214X_TRACEINTID_EPGETSTATUS), 0);
+ privep = lpc214x_epfindbyaddr(priv, index);
+ if (!privep)
+ {
+ usbtrace(TRACE_DEVERROR(LPC214X_TRACEERR_BADEPGETSTATUS), 0);
+ priv->stalled = 1;
+ }
+ else
+ {
+ if ((lpc214x_usbcmd(CMD_USB_EP_SELECT|privep->epphy, 0) & CMD_USB_EPSELECT_ST) != 0)
+ {
+ response[0] = 1; /* Stalled */
+ }
+ else
+ {
+ response[0] = 0; /* Not stalled */
+ }
+ response[1] = 0;
+ lpc214x_epwrite(LPC214X_EP0_IN, response, 2);
+ priv->ep0state = LPC214X_EP0SHORTWRITE;
+ }
+ }
+ break;
+
+ case USB_REQ_RECIPIENT_DEVICE:
+ {
+ if (index == 0)
+ {
+ usbtrace(TRACE_INTDECODE(LPC214X_TRACEINTID_DEVGETSTATUS), 0);
+
+ /* Features: Remote Wakeup=YES; selfpowered=? */
+
+ response[0] = (priv->selfpowered << USB_FEATURE_SELFPOWERED) |
+ (1 << USB_FEATURE_REMOTEWAKEUP);
+ response[1] = 0;
+ lpc214x_epwrite(LPC214X_EP0_IN, response, 2);
+ priv->ep0state = LPC214X_EP0SHORTWRITE;
+ }
+ else
+ {
+ usbtrace(TRACE_DEVERROR(LPC214X_TRACEERR_BADDEVGETSTATUS), 0);
+ priv->stalled = 1;
+ }
+ }
+ break;
+
+ case USB_REQ_RECIPIENT_INTERFACE:
+ {
+ usbtrace(TRACE_INTDECODE(LPC214X_TRACEINTID_IFGETSTATUS), 0);
+ response[0] = 0;
+ response[1] = 0;
+ lpc214x_epwrite(LPC214X_EP0_IN, response, 2);
+ priv->ep0state = LPC214X_EP0SHORTWRITE;
+ }
+ break;
+
+ default:
+ {
+ usbtrace(TRACE_DEVERROR(LPC214X_TRACEERR_BADGETSTATUS), 0);
+ priv->stalled = 1;
+ }
+ break;
+ }
+ }
+ }
+ break;
+
+ case USB_REQ_CLEARFEATURE:
+ {
+ /* type: host-to-device; recipient = device, interface or endpoint
+ * value: feature selector
+ * index: zero interface endpoint;
+ * len: zero, data = none
+ */
+
+ usbtrace(TRACE_INTDECODE(LPC214X_TRACEINTID_CLEARFEATURE), 0);
+ if ((ctrl.type & USB_REQ_RECIPIENT_MASK) != USB_REQ_RECIPIENT_ENDPOINT)
+ {
+ lpc214x_dispatchrequest(priv, &ctrl);
+ }
+ else if (priv->paddrset != 0 && value == USB_FEATURE_ENDPOINTHALT && len == 0 &&
+ (privep = lpc214x_epfindbyaddr(priv, index)) != NULL)
+ {
+ privep->halted = 0;
+ ret = lpc214x_epstall(&privep->ep, true);
+ lpc214x_epwrite(LPC214X_EP0_IN, NULL, 0);
+ priv->ep0state = LPC214X_EP0STATUSIN;
+ }
+ else
+ {
+ usbtrace(TRACE_DEVERROR(LPC214X_TRACEERR_BADCLEARFEATURE), 0);
+ priv->stalled = 1;
+ }
+ }
+ break;
+
+ case USB_REQ_SETFEATURE:
+ {
+ /* type: host-to-device; recipient = device, interface, endpoint
+ * value: feature selector
+ * index: zero interface endpoint;
+ * len: 0; data = none
+ */
+
+ usbtrace(TRACE_INTDECODE(LPC214X_TRACEINTID_SETFEATURE), 0);
+ if (((ctrl.type & USB_REQ_RECIPIENT_MASK) == USB_REQ_RECIPIENT_DEVICE) &&
+ value == USB_FEATURE_TESTMODE)
+ {
+ ullvdbg("test mode: %d\n", index);
+ }
+ else if ((ctrl.type & USB_REQ_RECIPIENT_MASK) != USB_REQ_RECIPIENT_ENDPOINT)
+ {
+ lpc214x_dispatchrequest(priv, &ctrl);
+ }
+ else if (priv->paddrset != 0 && value == USB_FEATURE_ENDPOINTHALT && len == 0 &&
+ (privep = lpc214x_epfindbyaddr(priv, index)) != NULL)
+ {
+ privep->halted = 1;
+ lpc214x_epwrite(LPC214X_EP0_IN, NULL, 0);
+ priv->ep0state = LPC214X_EP0STATUSIN;
+ }
+ else
+ {
+ usbtrace(TRACE_DEVERROR(LPC214X_TRACEERR_BADSETFEATURE), 0);
+ priv->stalled = 1;
+ }
+ }
+ break;
+
+ case USB_REQ_SETADDRESS:
+ {
+ /* type: host-to-device; recipient = device
+ * value: device address
+ * index: 0
+ * len: 0; data = none
+ */
+
+ usbtrace(TRACE_INTDECODE(LPC214X_TRACEINTID_EP0SETUPSETADDRESS), value);
+ if ((ctrl.type & USB_REQ_RECIPIENT_MASK) == USB_REQ_RECIPIENT_DEVICE &&
+ index == 0 && len == 0 && value < 128)
+ {
+ /* Save the address. We cannot actually change to the next address until
+ * the completion of the status phase.
+ */
+
+ priv->paddr = ctrl.value[0];
+
+ /* Note that if we send the SETADDRESS command twice, that will force the
+ * address change. Otherwise, the hardware will automatically set the
+ * address at the end of the status phase.
+ */
+
+ lpc214x_usbcmd(CMD_USB_DEV_SETADDRESS, CMD_USB_SETADDRESS_DEVEN | priv->paddr);
+
+ /* Send a NULL packet. The status phase completes when the null packet has
+ * been sent successfully.
+ */
+
+ lpc214x_epwrite(LPC214X_EP0_IN, NULL, 0);
+ priv->ep0state = LPC214X_EP0SETADDRESS;
+ }
+ else
+ {
+ usbtrace(TRACE_DEVERROR(LPC214X_TRACEERR_BADSETADDRESS), 0);
+ priv->stalled = 1;
+ }
+ }
+ break;
+
+ case USB_REQ_GETDESCRIPTOR:
+ /* type: device-to-host; recipient = device
+ * value: descriptor type and index
+ * index: 0 or language ID;
+ * len: descriptor len; data = descriptor
+ */
+ case USB_REQ_SETDESCRIPTOR:
+ /* type: host-to-device; recipient = device
+ * value: descriptor type and index
+ * index: 0 or language ID;
+ * len: descriptor len; data = descriptor
+ */
+ {
+ usbtrace(TRACE_INTDECODE(LPC214X_TRACEINTID_GETSETDESC), 0);
+ if ((ctrl.type & USB_REQ_RECIPIENT_MASK) == USB_REQ_RECIPIENT_DEVICE)
+ {
+ lpc214x_dispatchrequest(priv, &ctrl);
+ }
+ else
+ {
+ usbtrace(TRACE_DEVERROR(LPC214X_TRACEERR_BADGETSETDESC), 0);
+ priv->stalled = 1;
+ }
+ }
+ break;
+
+ case USB_REQ_GETCONFIGURATION:
+ /* type: device-to-host; recipient = device
+ * value: 0;
+ * index: 0;
+ * len: 1; data = configuration value
+ */
+ {
+ usbtrace(TRACE_INTDECODE(LPC214X_TRACEINTID_GETCONFIG), 0);
+ if (priv->paddrset && (ctrl.type & USB_REQ_RECIPIENT_MASK) == USB_REQ_RECIPIENT_DEVICE &&
+ value == 0 && index == 0 && len == 1)
+ {
+ lpc214x_dispatchrequest(priv, &ctrl);
+ }
+ else
+ {
+ usbtrace(TRACE_DEVERROR(LPC214X_TRACEERR_BADGETCONFIG), 0);
+ priv->stalled = 1;
+ }
+ }
+ break;
+
+ case USB_REQ_SETCONFIGURATION:
+ /* type: host-to-device; recipient = device
+ * value: configuration value
+ * index: 0;
+ * len: 0; data = none
+ */
+ {
+ usbtrace(TRACE_INTDECODE(LPC214X_TRACEINTID_SETCONFIG), 0);
+ if ((ctrl.type & USB_REQ_RECIPIENT_MASK) == USB_REQ_RECIPIENT_DEVICE &&
+ index == 0 && len == 0)
+ {
+ lpc214x_dispatchrequest(priv, &ctrl);
+ }
+ else
+ {
+ usbtrace(TRACE_DEVERROR(LPC214X_TRACEERR_BADSETCONFIG), 0);
+ priv->stalled = 1;
+ }
+ }
+ break;
+
+ case USB_REQ_GETINTERFACE:
+ /* type: device-to-host; recipient = interface
+ * value: 0
+ * index: interface;
+ * len: 1; data = alt interface
+ */
+ case USB_REQ_SETINTERFACE:
+ /* type: host-to-device; recipient = interface
+ * value: alternate setting
+ * index: interface;
+ * len: 0; data = none
+ */
+ {
+ usbtrace(TRACE_INTDECODE(LPC214X_TRACEINTID_GETSETIF), 0);
+ lpc214x_dispatchrequest(priv, &ctrl);
+ }
+ break;
+
+ case USB_REQ_SYNCHFRAME:
+ /* type: device-to-host; recipient = endpoint
+ * value: 0
+ * index: endpoint;
+ * len: 2; data = frame number
+ */
+ {
+ usbtrace(TRACE_INTDECODE(LPC214X_TRACEINTID_SYNCHFRAME), 0);
+ }
+ break;
+
+ default:
+ {
+ usbtrace(TRACE_DEVERROR(LPC214X_TRACEERR_INVALIDCTRLREQ), 0);
+ priv->stalled = 1;
+ }
+ break;
+ }
+
+ if (priv->stalled)
+ {
+ usbtrace(TRACE_DEVERROR(LPC214X_TRACEERR_EP0SETUPSTALLED), priv->ep0state);
+ ep0 = &priv->eplist[LPC214X_EP0_OUT];
+ lpc214x_epstall(&ep0->ep, false);
+ ep0 = &priv->eplist[LPC214X_EP0_IN];
+ lpc214x_epstall(&ep0->ep, false);
+ }
+}
+
+/*******************************************************************************
+ * Name: lpc214x_ep0dataoutinterrupt
+ *
+ * Description:
+ * USB Ctrl EP Data OUT Event. This is logically part of the USB interrupt
+ * handler. Each non-isochronous OUT endpoint gives an interrupt when they
+ * receive a packet without error.
+ *
+ *******************************************************************************/
+
+static inline void lpc214x_ep0dataoutinterrupt(struct lpc214x_usbdev_s *priv)
+{
+ struct lpc214x_ep_s *ep0;
+ uint32_t pktlen;
+
+ /* Copy new setup packet into setup buffer */
+
+ switch (priv->ep0state)
+ {
+ case LPC214X_EP0SHORTWRITE:
+ {
+ priv->ep0state = LPC214X_EP0STATUSOUT;
+ pktlen = lpc214x_epread(LPC214X_EP0_OUT, NULL, CONFIG_USBDEV_EP0_MAXSIZE);
+ if (LPC214X_READOVERRUN(pktlen))
+ {
+ lpc214x_ep0setup(priv);
+ }
+ }
+ break;
+
+ case LPC214X_EP0SHORTWRSENT:
+ {
+ priv->ep0state = LPC214X_EP0REQUEST;
+ pktlen = lpc214x_epread(LPC214X_EP0_OUT, NULL, CONFIG_USBDEV_EP0_MAXSIZE);
+ if (LPC214X_READOVERRUN(pktlen))
+ {
+ lpc214x_ep0setup(priv);
+ }
+ }
+ break;
+
+ case LPC214X_EP0REQUEST:
+ {
+ /* Process the next request action (if any) */
+
+ lpc214x_rdrequest(&priv->eplist[LPC214X_EP0_OUT]);
+ }
+ break;
+
+ default:
+ priv->stalled = 1;
+ break;
+ }
+
+ if (priv->stalled)
+ {
+ usbtrace(TRACE_DEVERROR(LPC214X_TRACEERR_EP0OUTSTALLED), priv->ep0state);
+ ep0 = &priv->eplist[LPC214X_EP0_OUT];
+ lpc214x_epstall(&ep0->ep, false);
+ ep0 = &priv->eplist[LPC214X_EP0_IN];
+ lpc214x_epstall(&ep0->ep, false);
+ }
+ return;
+}
+
+/*******************************************************************************
+ * Name: lpc214x_ep0dataininterrupt
+ *
+ * Description:
+ * USB Ctrl EP Data IN Event. This is logically part of the USB interrupt
+ * handler. All non-isochronous IN endpoints give this interrupt when a
+ * packet is successfully transmitted (OR a NAK handshake is sent on the bus
+ * provided that the interrupt on NAK feature is enabled).
+ *
+ *******************************************************************************/
+
+static inline void lpc214x_ep0dataininterrupt(struct lpc214x_usbdev_s *priv)
+{
+ struct lpc214x_ep_s *ep0;
+
+ switch (priv->ep0state)
+ {
+ case LPC214X_EP0STATUSOUT:
+ case LPC214X_EP0STATUSIN:
+ priv->ep0state = LPC214X_EP0REQUEST;
+ break;
+
+ case LPC214X_EP0SHORTWRITE:
+ priv->ep0state = LPC214X_EP0SHORTWRSENT;
+ break;
+
+ case LPC214X_EP0SETADDRESS:
+ {
+ /* If the address was set to a non-zero value, then thiscompletes the
+ * default phase, and begins the address phase (still not fully configured)
+ */
+
+ usbtrace(TRACE_INTDECODE(LPC214X_TRACEINTID_EP0INSETADDRESS), (uint16_t)priv->paddr);
+ lpc214x_usbcmd(CMD_USB_DEV_CONFIG, 0);
+ if (priv->paddr)
+ {
+ priv->paddrset = 1;
+ priv->ep0state = LPC214X_EP0REQUEST;
+ }
+ }
+ break;
+
+ case LPC214X_EP0REQUEST:
+ {
+ /* Process the next request action (if any) */
+
+ ep0 = &priv->eplist[LPC214X_EP0_IN];
+ ep0->txbusy = 0;
+ lpc214x_wrrequest(ep0);
+ }
+ break;
+
+ default:
+ priv->stalled = 1;
+ break;
+ }
+
+ if (priv->stalled)
+ {
+ usbtrace(TRACE_DEVERROR(LPC214X_TRACEERR_EP0INSTALLED), priv->ep0state);
+ ep0 = &priv->eplist[LPC214X_EP0_OUT];
+ lpc214x_epstall(&ep0->ep, false);
+ ep0 = &priv->eplist[LPC214X_EP0_IN];
+ lpc214x_epstall(&ep0->ep, false);
+ }
+}
+
+/*******************************************************************************
+ * Name: lpc214x_usbinterrupt
+ *
+ * Description:
+ * USB interrupt handler
+ *
+ *******************************************************************************/
+
+static int lpc214x_usbinterrupt(int irq, FAR void *context)
+{
+ struct lpc214x_usbdev_s *priv = &g_usbdev;
+ struct lpc214x_ep_s *privep ;
+
+ uint32_t devintstatus; /* Sampled state of the device interrupt status register */
+ uint32_t epintstatus; /* Sampled state of the endpoint interrupt status register */
+#ifdef CONFIG_LPC214X_USBDEV_DMA
+ uint32_t dmaintstatus; /* Sampled state of dma interrupt status register */
+#endif
+ uint32_t softprio; /* Current priority interrupt bitset */
+ uint32_t pending; /* Pending subset of priority interrupt bitset */
+ uint8_t epphy; /* Physical endpoint number being processed */
+ int i;
+
+ usbtrace(TRACE_INTENTRY(LPC214X_TRACEINTID_USB), 0);
+
+ /* Read the device interrupt status register */
+
+ devintstatus = lpc214x_getreg(LPC214X_USBDEV_DEVINTST);
+
+#ifdef CONFIG_LPC214X_USBDEV_DMA
+ /* Check for low priority and high priority (non-DMA) interrupts */
+
+ if ((lpc214x_getreg(LPC214X_USBDEV_INTST) & (USBDEV_INTST_REQLP|USBDEV_INTST_REQHP)) != 0)
+ {
+#endif
+#ifdef CONFIG_LPC214X_USBDEV_EPFAST_INTERRUPT
+ /* Fast EP interrupt */
+
+ if ((devintstatus & USBDEV_DEVINT_EPFAST) != 0)
+ {
+ /* Clear Fast EP interrupt */
+
+ lpc214x_putreg(USBDEV_DEVINT_EPFAST, LPC214X_USBDEV_DEVINTCLR);
+ usbtrace(TRACE_INTDECODE(LPC214X_TRACEINTID_EPFAST), 0);
+
+ /* Do what? */
+ }
+
+#endif
+
+#if CONFIG_DEBUG
+ /* USB engine error interrupt */
+
+ if ((devintstatus & USBDEV_DEVINT_EPRINT))
+ {
+ uint8_t errcode;
+
+ /* Clear the error interrupt */
+
+ lpc214x_putreg(USBDEV_DEVINT_EPRINT, LPC214X_USBDEV_DEVINTCLR);
+
+ /* And show what error occurred */
+
+ errcode = (uint8_t)lpc214x_usbcmd(CMD_USB_DEV_READERRORSTATUS, 0) & 0x0f;
+ usbtrace(TRACE_INTDECODE(LPC214X_TRACEINTID_EPRINT), (uint16_t)errcode);
+ }
+#endif
+
+#ifdef CONFIG_LPC214X_USBDEV_FRAME_INTERRUPT
+ /* Frame interrupt */
+
+ if ((devintstatus & USBDEV_DEVINT_FRAME) != 0)
+ {
+ /* Clear the frame interrupt */
+
+ lpc214x_putreg(USBDEV_DEVINT_FRAME, LPC214X_USBDEV_DEVINTCLR);
+ usbtrace(TRACE_INTDECODE(LPC214X_TRACEINTID_FRAME), 0);
+
+ /* Then read the start of frame value */
+
+ priv->sof = (uint16_t)lpc214x_usbcmd(CMD_USB_DEV_READFRAMENO, 0);
+ }
+#endif
+
+ /* Device Status interrupt */
+
+ if ((devintstatus & USBDEV_DEVINT_DEVSTAT) != 0)
+ {
+ /* Clear Device status interrupt */
+
+ lpc214x_putreg(USBDEV_DEVINT_DEVSTAT, LPC214X_USBDEV_DEVINTCLR);
+
+ /* Get device status */
+
+ g_usbdev.devstatus = (uint8_t)lpc214x_usbcmd(CMD_USB_DEV_GETSTATUS, 0);
+ usbtrace(TRACE_INTDECODE(LPC214X_TRACEINTID_DEVSTAT), (uint16_t)g_usbdev.devstatus);
+
+ /* Device connection status */
+
+ if (DEVSTATUS_CONNCHG(g_usbdev.devstatus))
+ {
+ usbtrace(TRACE_INTDECODE(LPC214X_TRACEINTID_CONNECTCHG),
+ (uint16_t)g_usbdev.devstatus);
+ if (DEVSTATUS_CONNECT(g_usbdev.devstatus))
+ {
+ /* Host is connected */
+
+ if (!priv->attached)
+ {
+ /* We have a transition from unattached to attached */
+
+ usbtrace(TRACE_INTDECODE(LPC214X_TRACEINTID_CONNECTED),
+ (uint16_t)g_usbdev.devstatus);
+ priv->usbdev.speed = USB_SPEED_UNKNOWN;
+ lpc214x_usbcmd(CMD_USB_DEV_CONFIG, 0);
+ priv->attached = 1;
+ }
+ }
+
+ /* Otherwise the host is not attached */
+
+ else if (priv->attached)
+ {
+ usbtrace(TRACE_INTDECODE(LPC214X_TRACEINTID_DISCONNECTED),
+ (uint16_t)g_usbdev.devstatus);
+ priv->usbdev.speed = USB_SPEED_UNKNOWN;
+ lpc214x_usbcmd(CMD_USB_DEV_CONFIG, 0);
+ priv->attached = 0;
+ priv->paddrset = 0;
+ }
+ }
+
+ /* Device suspend status */
+
+ if (DEVSTATUS_SUSPCHG(g_usbdev.devstatus))
+ {
+ usbtrace(TRACE_INTDECODE(LPC214X_TRACEINTID_SUSPENDCHG),
+ (uint16_t)g_usbdev.devstatus);
+ }
+
+ /* Device reset */
+
+ if (DEVSTATUS_RESET(g_usbdev.devstatus))
+ {
+ usbtrace(TRACE_INTDECODE(LPC214X_TRACEINTID_DEVRESET),
+ (uint16_t)g_usbdev.devstatus);
+ lpc214x_usbreset(priv);
+ }
+ }
+
+ /* Slow EP interrupt */
+
+ if ((devintstatus & USBDEV_DEVINT_EPSLOW) != 0)
+ {
+ /* Clear Slow EP interrupt */
+
+ lpc214x_putreg(USBDEV_DEVINT_EPSLOW, LPC214X_USBDEV_DEVINTCLR);
+ usbtrace(TRACE_INTDECODE(LPC214X_TRACEINTID_EPSLOW), 0);
+
+ do
+ {
+ /* Read the endpoint interrupt status register */
+
+ epintstatus = lpc214x_getreg(LPC214X_USBDEV_EPINTST);
+
+ /* Loop twice: Process software high priority interrupts
+ * on the first pass and low priority interrupts on the
+ * second.
+ */
+
+ softprio = priv->softprio;
+ for (i = 0; i < 2; i++, softprio = ~softprio)
+ {
+ /* On the first time through the loop, pending will be
+ * the bitset of high priority pending interrupts; on the
+ * second time throught it will be the bitset of low
+ * priority interrupts.
+ */
+
+ pending = epintstatus & softprio;
+
+ /* EP0 OUT interrupt indicated by bit0 == 1 */
+
+ if ((pending & 1) != 0)
+ {
+ /* Clear the endpoint interrupt */
+
+ uint32_t result = lpc214x_epclrinterrupt(LPC214X_CTRLEP_OUT);
+ if (result & USBDEV_EPSETUPPACKET)
+ {
+ usbtrace(TRACE_INTDECODE(LPC214X_TRACEINTID_EP0SETUP), (uint16_t)result);
+ lpc214x_ep0setup(priv);
+ }
+ else
+ {
+ usbtrace(TRACE_INTDECODE(LPC214X_TRACEINTID_EP0OUT), priv->ep0state);
+ lpc214x_ep0dataoutinterrupt(priv);
+ }
+ break;
+ }
+
+ /* EP0 IN interrupt indicated by bit1 == 1 */
+
+ if ((pending & 2) != 0)
+ {
+ /* Clear the endpoint interrupt */
+
+ usbtrace(TRACE_INTDECODE(LPC214X_TRACEINTID_EP0IN), priv->ep0state);
+ (void)lpc214x_epclrinterrupt(LPC214X_CTRLEP_IN);
+ lpc214x_ep0dataininterrupt(priv);
+ }
+ pending >>= 2;
+
+ /* All other endpoints EP 1-31 */
+
+ for (epphy = 2; pending; epphy++, pending >>= 1)
+ {
+ /* Is the endpoint interrupt pending? */
+
+ if ((pending & 1) != 0)
+ {
+ /* Yes.. clear the endpoint interrupt */
+
+ (void)lpc214x_epclrinterrupt(epphy);
+
+ /* Get the endpoint sructure corresponding to the physical
+ * endpoint number.
+ */
+
+ privep = &priv->eplist[epphy];
+
+ /* Check for complete on IN or OUT endpoint. Odd physical
+ * endpoint addresses are IN endpoints.
+ */
+
+ if ((epphy & 1) != 0)
+ {
+ /* IN: device-to-host */
+
+ usbtrace(TRACE_INTDECODE(LPC214X_TRACEINTID_EPOUT), (uint16_t)epphy);
+ if (priv->usbdev.speed == USB_SPEED_UNKNOWN)
+ {
+ priv->usbdev.speed = USB_SPEED_FULL;
+ lpc214x_usbcmd(CMD_USB_DEV_CONFIG, 1);
+ }
+
+ /* Write host data from the current write request (if any) */
+
+ privep->txbusy = 0;
+ lpc214x_wrrequest(privep);
+ }
+ else
+ {
+ /* OUT: host-to-device */
+
+ usbtrace(TRACE_INTDECODE(LPC214X_TRACEINTID_EPIN), (uint16_t)epphy);
+
+ /* Read host data into the current read request */
+
+ if (!lpc214x_rqempty(privep))
+ {
+ lpc214x_rdrequest(privep);
+ }
+ else
+ {
+ ullvdbg("Pending data on OUT endpoint\n");
+ priv->rxpending = 1;
+ }
+ }
+ }
+ }
+ }
+ }
+ while (epintstatus);
+ }
+#ifdef CONFIG_LPC214X_USBDEV_DMA
+ }
+
+ /* Check for DMA interrupts */
+
+ if ((lpc214x_getreg(LPC214X_USBDEV_INTST) & USBDEV_INTST_REQDMA) != 0)
+ {
+ /* First Software High priority and then low priority */
+
+ uint32_t tmp;
+
+ /* Collect the DMA interrupt sources */
+
+ dmaintstatus = 0;
+ tmp = lpc214x_getreg(LPC214X_USBDEV_EOTINTST);
+ if (lpc214x_getreg(LPC214X_USBDEV_DMAINTEN) & 1)
+ {
+ dmaintstatus |= tmp;
+ }
+ lpc214x_putreg(tmp, LPC214X_USBDEV_EOTINTCLR);
+
+ tmp = lpc214x_getreg(LPC214X_USBDEV_NDDRINTST);
+ if (lpc214x_getreg(LPC214X_USBDEV_DMAINTEN) & 2)
+ {
+ dmaintstatus |= tmp;
+ }
+ lpc214x_putreg(tmp, LPC214X_USBDEV_NDDRINTCLR);
+
+ tmp = lpc214x_getreg(LPC214X_USBDEV_SYSERRINTST);
+ if (lpc214x_getreg(LPC214X_USBDEV_DMAINTEN) & 4)
+ {
+ dmaintstatus |= tmp;
+ }
+ lpc214x_putreg(tmp, LPC214X_USBDEV_SYSERRINTCLR);
+
+ /* Loop twice: Process software high priority interrupts on the
+ * first pass and low priority interrupts on the second.
+ */
+
+ softprio = priv->softprio;
+ for (i = 0; i < 2; i++, softprio = ~softprio)
+ {
+ /* On the first time through the loop, pending will be
+ * the bitset of high priority pending interrupts; on the
+ * second time throught it will be the bitset of low
+ * priority interrupts. Note that EP0 IN and OUT are
+ * omitted.
+ */
+
+ pending = (dmaintstatus & softprio) >> 2;
+ for (epphy = 2; pending; epphy++, pending >>= 1)
+ {
+ if ((pending & 1) != 0)
+ {
+ usbtrace(TRACE_INTDECODE(LPC214X_TRACEINTID_EPDMA), (uint16_t)epphy);
+#warning DO WHAT?
+ }
+ }
+ }
+ }
+#endif
+ usbtrace(TRACE_INTEXIT(LPC214X_TRACEINTID_USB), 0);
+ return OK;
+}
+
+/*******************************************************************************
+ * Name: lpc214x_dmasetup
+ *
+ * Description:
+ * Setup for DMA Transfer
+ *
+ *******************************************************************************/
+
+#ifdef CONFIG_LPC214X_USBDEV_DMA
+static int lpc214x_dmasetup(struct lpc214x_usbdev_s *priv, uint8_t epphy,
+ uint32_t epmaxsize, uint32_t nbytes, uint32_t *isocpacket,
+ bool isochronous);
+{
+ struct lpc214x_dmadesc_s *dmadesc = priv;
+ uint32_t reg;
+
+#ifdef CONFIG_DEBUG
+ if (!priv || epphy < 2)
+ {
+ usbtrace(TRACE_DEVERROR(LPC214X_TRACEERR_INVALIDPARMS), 0);
+ return -EINVAL;
+ }
+#endif
+
+ /* Check if a DMA descriptor has been assigned. If not, than that indicates
+ * that we will have to do parallel I/O
+ */
+
+ if (!dmadesc)
+ {
+ usbtrace(TRACE_DEVERROR(LPC214X_TRACEERR_NODMADESC), 0);
+ return -EBUSY;
+ }
+
+ /* Verify that the DMA descriptor is available */
+
+ if ((dmadesc->status & USB_DMADESC_STATUSMASK) == USB_DMADESC_BEINGSERVICED)
+ {
+ usbtrace(TRACE_DEVERROR(LPC214X_TRACEERR_DMABUSY), 0);
+ return -EBUSY; /* Shouldn't happen */
+ }
+
+ /* Init DMA Descriptor */
+
+ dmadesc->nexdesc = 0;
+ dmadesc->config = USB_DMADESC_MODENORMAL |
+ ((epmaxsize << USB_DMADESC_PKTSIZESHIFT) & USB_DMADESC_PKTSIZEMASK) |
+ ((nbytes << USB_DMADESC_BULENSHIFT) & USB_DMADESC_BUFLENMASK);
+
+#ifdef CONFIG_USBDEV_ISOCHRONOUS
+ if (isochronous)
+ {
+ dmadesc->config |= USB_DMADESC_ISCOEP;
+ }
+#endif
+
+ dmadesc->start = (uint32_t)&dmadesc->buffer;
+ dmadesc->status = 0;
+
+#ifdef CONFIG_USBDEV_ISOCHRONOUS
+ dmadesc->size = (uint32_t)packet;
+#endif
+
+ /* Enable DMA tranfer for this endpoint */
+
+ putreq32(1 << epphy, LPC214X_USBDEV_EPDMAEN);
+
+ /* Check state of IN/OUT Ep buffer */
+
+ reg = lpc214x_usbcmd(CMD_USB_EP_SELECT | epphy, 0);
+
+ if ((LPC214X_EPPHYIN(epphy) && (reg & 0x60) == 0) ||
+ (LPC214X_EPPHYOUT(epphy) && (reg & 0x60) == 0x60))
+ {
+ /* DMA should be "being serviced" */
+
+ if ((dmadesc->status & USB_DMADESC_STATUSMASK) != USB_DMADESC_BEINGSERVICED))
+ {
+ /* Re-trigger the DMA Transfer */
+
+ putreq21(1 << epphy, LPC214X_USBDEV_DMARCLR);
+ putreq32(1 << epphy, LPC214X_USBDEV_EPDMAEN);
+ }
+ }
+ return OK;
+}
+#endif /* CONFIG_LPC214X_USBDEV_DMA */
+
+/*******************************************************************************
+ * Name: lpc214x_dmarestart
+ *
+ * Description:
+ * Restart DMA Transfer
+ *
+ *******************************************************************************/
+
+#ifdef CONFIG_LPC214X_USBDEV_DMA
+static void lpc214x_dmarestart(uint8_t epphy, uint32_t descndx)
+{
+ uint32_t reg;
+
+ /* Clear DMA descriptor status */
+
+ USB_DmaDesc[descndx].status = 0;
+
+ /* Enable DMA transfer on the endpoint */
+
+ lpc214x_putreg(1 << epph, LPC214X_USBDEV_EPDMAEN);
+
+ /* Check the state of IN/OUT EP buffer */
+
+ uint32_t reg = lpc214x_usbcmd(CMD_USB_EP_SELECT | epphy, 0);
+ if ((LPC214X_EPPHYIN(epphy) && (reg & 0x60) == 0) ||
+ (LPC214X_EPPHYIN(epphy) && (reg & 0x60) == 0x60))
+ {
+ /* Re-trigger the DMA Transfer */
+
+ putreq21(1 << epphy, LPC214X_USBDEV_DMARCLR);
+ putreq32(1 << epphy, LPC214X_USBDEV_EPDMAEN);
+ }
+}
+#endif /* CONFIG_LPC214X_USBDEV_DMA */
+
+/*******************************************************************************
+ * Name: lpc214x_dmadisable
+ *
+ * Description:
+ * Disable DMA transfer for the EP
+ *
+ *******************************************************************************/
+
+#ifdef CONFIG_LPC214X_USBDEV_DMA
+static void lpc214x_dmadisable(uint8_t epphy)
+{
+ EPDMADIS = 1 << epphy;
+}
+#endif /* CONFIG_LPC214X_USBDEV_DMA */
+
+/*******************************************************************************
+ * Endpoint operations
+ *******************************************************************************/
+
+/*******************************************************************************
+ * Name: lpc214x_epconfigure
+ *
+ * Description:
+ * Configure endpoint, making it usable
+ *
+ * Input Parameters:
+ * ep - the struct usbdev_ep_s instance obtained from allocep()
+ * desc - A struct usb_epdesc_s instance describing the endpoint
+ * last - true if this this last endpoint to be configured. Some hardware
+ * needs to take special action when all of the endpoints have been
+ * configured.
+ *
+ *******************************************************************************/
+
+static int lpc214x_epconfigure(FAR struct usbdev_ep_s *ep,
+ FAR const struct usb_epdesc_s *desc,
+ bool last)
+{
+ FAR struct lpc214x_ep_s *privep = (FAR struct lpc214x_ep_s *)ep;
+ uint32_t inten;
+
+ usbtrace(TRACE_EPCONFIGURE, privep->epphy);
+ DEBUGASSERT(desc->addr == ep->eplog);
+
+ /* Realize the endpoint */
+
+ lpc214x_eprealize(privep, 1, GETUINT16(desc->mxpacketsize));
+
+ /* Enable and reset EP -- twice */
+
+ lpc214x_usbcmd(CMD_USB_EP_SETSTATUS | privep->epphy, 0);
+ lpc214x_usbcmd(CMD_USB_EP_SETSTATUS | privep->epphy, 0);
+
+#ifdef CONFIG_LPC214X_USBDEV_DMA
+ /* Enable DMA Ep interrupt (WO) */
+
+ lpc214x_putreg(1 << privep->epphy, LPC214X_USBDEV_EPDMAEN);
+#else
+ /* Enable Ep interrupt (R/W) */
+
+ inten = lpc214x_getreg(LPC214X_USBDEV_EPINTEN);
+ inten |= (1 << privep->epphy);
+ lpc214x_putreg(inten, LPC214X_USBDEV_EPINTEN);
+#endif
+
+ /* If all of the endpoints have been configured, then tell the USB controller
+ * to enabled normal activity on all realized endpoints.
+ */
+
+ if (last)
+ {
+ lpc214x_usbcmd(CMD_USB_DEV_CONFIG, 1);
+ }
+ return OK;
+}
+
+/*******************************************************************************
+ * Name: lpc214x_epdisable
+ *
+ * Description:
+ * The endpoint will no longer be used
+ *
+ *******************************************************************************/
+
+static int lpc214x_epdisable(FAR struct usbdev_ep_s *ep)
+{
+ FAR struct lpc214x_ep_s *privep = (FAR struct lpc214x_ep_s *)ep;
+ irqstate_t flags;
+ uint32_t mask = (1 << privep->epphy);
+ uint32_t reg;
+
+#ifdef CONFIG_DEBUG
+ if (!ep)
+ {
+ usbtrace(TRACE_DEVERROR(LPC214X_TRACEERR_INVALIDPARMS), 0);
+ return -EINVAL;
+ }
+#endif
+ usbtrace(TRACE_EPDISABLE, privep->epphy);
+
+ /* Cancel any ongoing activity */
+
+ flags = irqsave();
+ lpc214x_cancelrequests(privep);
+
+ /* Disable endpoint and interrupt */
+
+ reg = lpc214x_getreg(LPC214X_USBDEV_REEP);
+ reg &= ~mask;
+ lpc214x_putreg(reg, LPC214X_USBDEV_REEP);
+
+ lpc214x_putreg(mask, LPC214X_USBDEV_EPDMADIS);
+
+ reg = lpc214x_getreg(LPC214X_USBDEV_EPINTEN);
+ reg &= ~mask;
+ lpc214x_putreg(reg, LPC214X_USBDEV_EPINTEN);
+
+ irqrestore(flags);
+ return OK;
+}
+
+/*******************************************************************************
+ * Name: lpc214x_epallocreq
+ *
+ * Description:
+ * Allocate an I/O request
+ *
+ *******************************************************************************/
+
+static FAR struct usbdev_req_s *lpc214x_epallocreq(FAR struct usbdev_ep_s *ep)
+{
+ FAR struct lpc214x_req_s *privreq;
+
+#ifdef CONFIG_DEBUG
+ if (!ep)
+ {
+ usbtrace(TRACE_DEVERROR(LPC214X_TRACEERR_INVALIDPARMS), 0);
+ return NULL;
+ }
+#endif
+ usbtrace(TRACE_EPALLOCREQ, ((FAR struct lpc214x_ep_s *)ep)->epphy);
+
+ privreq = (FAR struct lpc214x_req_s *)malloc(sizeof(struct lpc214x_req_s));
+ if (!privreq)
+ {
+ usbtrace(TRACE_DEVERROR(LPC214X_TRACEERR_ALLOCFAIL), 0);
+ return NULL;
+ }
+
+ memset(privreq, 0, sizeof(struct lpc214x_req_s));
+ return &privreq->req;
+}
+
+/*******************************************************************************
+ * Name: lpc214x_epfreereq
+ *
+ * Description:
+ * Free an I/O request
+ *
+ *******************************************************************************/
+
+static void lpc214x_epfreereq(FAR struct usbdev_ep_s *ep, FAR struct usbdev_req_s *req)
+{
+ FAR struct lpc214x_req_s *privreq = (FAR struct lpc214x_req_s *)req;
+
+#ifdef CONFIG_DEBUG
+ if (!ep || !req)
+ {
+ usbtrace(TRACE_DEVERROR(LPC214X_TRACEERR_INVALIDPARMS), 0);
+ return;
+ }
+#endif
+ usbtrace(TRACE_EPFREEREQ, ((FAR struct lpc214x_ep_s *)ep)->epphy);
+
+ free(privreq);
+}
+
+/*******************************************************************************
+ * Name: lpc214x_epallocbuffer
+ *
+ * Description:
+ * Allocate an I/O buffer
+ *
+ *******************************************************************************/
+
+#ifdef CONFIG_LPC214X_USBDEV_DMA
+static FAR void *lpc214x_epallocbuffer(FAR struct usbdev_ep_s *ep, uint16_t nbytes)
+{
+#ifdef CONFIG_USBDEV_DMA
+
+ FAR struct lpc214x_ep_s *privep = (FAR struct lpc214x_ep_s *)ep;
+ int descndx;
+
+ usbtrace(TRACE_EPALLOCBUFFER, privep->epphy);
+
+ /* Find a free DMA description */
+
+#error "LOGIC INCOMPLETE"
+
+ /* Set UDCA to the allocated DMA descriptor for this endpoint */
+
+ USB_UDCA[privep->epphy] = &USB_DDESC[descndx];
+ return &USB_DDESC[descndx]
+
+#elif defined(CONFIG_USBDEV_DMAMEMORY)
+
+ usbtrace(TRACE_EPALLOCBUFFER, privep->epphy);
+ return usbdev_dma_alloc(bytes);
+
+#else
+
+ usbtrace(TRACE_EPALLOCBUFFER, privep->epphy);
+ return malloc(bytes);
+
+#endif
+}
+#endif
+
+/*******************************************************************************
+ * Name: lpc214x_epfreebuffer
+ *
+ * Description:
+ * Free an I/O buffer
+ *
+ *******************************************************************************/
+
+#ifdef CONFIG_USBDEV_DMA
+
+static void lpc214x_epfreebuffer(FAR struct usbdev_ep_s *ep, FAR void *buf)
+{
+#ifdef CONFIG_LPC214X_USBDEV_DMA
+ FAR struct lpc214x_ep_s *privep = (FAR struct lpc214x_ep_s *)ep;
+
+ usbtrace(TRACE_EPFREEBUFFER, privep->epphy);
+
+ /* Indicate that there is no DMA descriptor associated with this endpoint */
+
+ USB_UDCA[privep->epphy] = NULL;
+
+ /* Mark the DMA descriptor as free for re-allocation */
+
+# error "LOGIC INCOMPLETE"
+
+#elif defined(CONFIG_USBDEV_DMAMEMORY)
+
+ usbtrace(TRACE_EPFREEBUFFER, privep->epphy);
+ usbdev_dma_free(buf);
+
+#else
+
+ usbtrace(TRACE_EPFREEBUFFER, privep->epphy);
+ free(buf);
+
+#endif
+}
+#endif
+
+/*******************************************************************************
+ * Name: lpc214x_epsubmit
+ *
+ * Description:
+ * Submit an I/O request to the endpoint
+ *
+ *******************************************************************************/
+
+static int lpc214x_epsubmit(FAR struct usbdev_ep_s *ep, FAR struct usbdev_req_s *req)
+{
+ FAR struct lpc214x_req_s *privreq = (FAR struct lpc214x_req_s *)req;
+ FAR struct lpc214x_ep_s *privep = (FAR struct lpc214x_ep_s *)ep;
+ FAR struct lpc214x_usbdev_s *priv;
+ irqstate_t flags;
+ int ret = OK;
+
+#ifdef CONFIG_DEBUG
+ if (!req || !req->callback || !req->buf || !ep)
+ {
+ usbtrace(TRACE_DEVERROR(LPC214X_TRACEERR_INVALIDPARMS), 0);
+ ullvdbg("req=%p callback=%p buf=%p ep=%p\n", req, req->callback, req->buf, ep);
+ return -EINVAL;
+ }
+#endif
+
+ usbtrace(TRACE_EPSUBMIT, privep->epphy);
+ priv = privep->dev;
+
+ if (!priv->driver || priv->usbdev.speed == USB_SPEED_UNKNOWN)
+ {
+ usbtrace(TRACE_DEVERROR(LPC214X_TRACEERR_NOTCONFIGURED), priv->usbdev.speed);
+ return -ESHUTDOWN;
+ }
+
+ /* Handle the request from the class driver */
+
+ req->result = -EINPROGRESS;
+ req->xfrd = 0;
+ flags = irqsave();
+
+ /* If we are stalled, then drop all requests on the floor */
+
+ if (privep->stalled)
+ {
+ lpc214x_abortrequest(privep, privreq, -EBUSY);
+ ret = -EBUSY;
+ }
+
+ /* Handle IN (device-to-host) requests */
+
+ else if (LPC214X_EPPHYIN(privep->epphy))
+ {
+ /* Add the new request to the request queue for the IN endpoint */
+
+ lpc214x_rqenqueue(privep, privreq);
+ usbtrace(TRACE_INREQQUEUED(privep->epphy), privreq->req.len);
+
+ /* If the IN endpoint FIFO is available, then transfer the data now */
+
+ if (privep->txbusy == 0)
+ {
+ ret = lpc214x_wrrequest(privep);
+ }
+ }
+
+ /* Handle OUT (host-to-device) requests */
+
+ else
+ {
+ /* Add the new request to the request queue for the OUT endpoint */
+
+ privep->txnullpkt = 0;
+ lpc214x_rqenqueue(privep, privreq);
+ usbtrace(TRACE_OUTREQQUEUED(privep->epphy), privreq->req.len);
+
+ /* This there a incoming data pending the availability of a request? */
+
+ if (priv->rxpending)
+ {
+ ret = lpc214x_rdrequest(privep);
+ priv->rxpending = 0;
+ }
+ }
+
+ irqrestore(flags);
+ return ret;
+}
+
+/*******************************************************************************
+ * Name: lpc214x_epcancel
+ *
+ * Description:
+ * Cancel an I/O request previously sent to an endpoint
+ *
+ *******************************************************************************/
+
+static int lpc214x_epcancel(FAR struct usbdev_ep_s *ep, FAR struct usbdev_req_s *req)
+{
+ FAR struct lpc214x_ep_s *privep = (FAR struct lpc214x_ep_s *)ep;
+ FAR struct lpc214x_usbdev_s *priv;
+ irqstate_t flags;
+
+#ifdef CONFIG_DEBUG
+ if (!ep || !req)
+ {
+ usbtrace(TRACE_DEVERROR(LPC214X_TRACEERR_INVALIDPARMS), 0);
+ return -EINVAL;
+ }
+#endif
+ usbtrace(TRACE_EPCANCEL, privep->epphy);
+ priv = privep->dev;
+
+ flags = irqsave();
+ lpc214x_cancelrequests(privep);
+ irqrestore(flags);
+ return OK;
+}
+
+/*******************************************************************************
+ * Name: lpc214x_epstall
+ *
+ * Description:
+ * Stall or resume and endpoint
+ *
+ *******************************************************************************/
+
+static int lpc214x_epstall(FAR struct usbdev_ep_s *ep, bool resume)
+{
+ FAR struct lpc214x_ep_s *privep = (FAR struct lpc214x_ep_s *)ep;
+ irqstate_t flags;
+
+ /* STALL or RESUME the endpoint */
+
+ flags = irqsave();
+ usbtrace(resume ? TRACE_EPRESUME : TRACE_EPSTALL, privep->epphy);
+ lpc214x_usbcmd(CMD_USB_EP_SETSTATUS | privep->epphy, (resume ? 0 : USBDEV_EPSTALL));
+
+ /* If the endpoint of was resumed, then restart any queue write requests */
+
+ if (resume)
+ {
+ (void)lpc214x_wrrequest(privep);
+ }
+ irqrestore(flags);
+ return OK;
+}
+
+/*******************************************************************************
+ * Device operations
+ *******************************************************************************/
+
+/*******************************************************************************
+ * Name: lcp214x_allocep
+ *
+ * Description:
+ * Allocate an endpoint matching the parameters.
+ *
+ * Input Parameters:
+ * eplog - 7-bit logical endpoint number (direction bit ignored). Zero means
+ * that any endpoint matching the other requirements will suffice. The
+ * assigned endpoint can be found in the eplog field.
+ * in - true: IN (device-to-host) endpoint requested
+ * eptype - Endpoint type. One of {USB_EP_ATTR_XFER_ISOC, USB_EP_ATTR_XFER_BULK,
+ * USB_EP_ATTR_XFER_INT}
+ *
+ *******************************************************************************/
+
+static FAR struct usbdev_ep_s *lcp214x_allocep(FAR struct usbdev_s *dev, uint8_t eplog,
+ bool in, uint8_t eptype)
+{
+ FAR struct lpc214x_usbdev_s *priv = (FAR struct lpc214x_usbdev_s *)dev;
+ uint32_t epset = LPC214X_EPALLSET & ~LPC214X_EPCTRLSET;
+ irqstate_t flags;
+ int epndx = 0;
+
+ usbtrace(TRACE_DEVALLOCEP, (uint16_t)eplog);
+
+ /* Ignore any direction bits in the logical address */
+
+ eplog = USB_EPNO(eplog);
+
+ /* A logical address of 0 means that any endpoint will do */
+
+ if (eplog > 0)
+ {
+ /* Otherwise, we will return the endpoint structure only for the requested
+ * 'logical' endpoint. All of the other checks will still be performed.
+ *
+ * First, verify that the logical endpoint is in the range supported by
+ * by the hardware.
+ */
+
+ if (eplog >= LPC214X_NLOGENDPOINTS)
+ {
+ usbtrace(TRACE_DEVERROR(LPC214X_TRACEERR_BADEPNO), (uint16_t)eplog);
+ return NULL;
+ }
+
+ /* Convert the logical address to a physical OUT endpoint address and
+ * remove all of the candidate endpoints from the bitset except for the
+ * the IN/OUT pair for this logical address.
+ */
+
+ epset &= 3 << (eplog << 1);
+ }
+
+ /* Get the subset matching the requested direction */
+
+ if (in)
+ {
+ epset &= LPC214X_EPINSET;
+ }
+ else
+ {
+ epset &= LPC214X_EPOUTSET;
+ }
+
+ /* Get the subset matching the requested type */
+
+ switch (eptype)
+ {
+ case USB_EP_ATTR_XFER_INT: /* Interrupt endpoint */
+ epset &= LPC214X_EPINTRSET;
+ break;
+
+ case USB_EP_ATTR_XFER_BULK: /* Bulk endpoint */
+ epset &= LPC214X_EPBULKSET;
+ break;
+
+ case USB_EP_ATTR_XFER_ISOC: /* Isochronous endpoint */
+ epset &= LPC214X_EPISOCSET;
+ break;
+
+ case USB_EP_ATTR_XFER_CONTROL: /* Control endpoint -- not a valid choice */
+ default:
+ usbtrace(TRACE_DEVERROR(LPC214X_TRACEERR_BADEPTYPE), (uint16_t)eptype);
+ return NULL;
+ }
+
+ /* Is the resulting endpoint supported by the LPC214x? */
+
+ if (epset)
+ {
+ /* Yes.. now see if any of the request endpoints are available */
+
+ flags = irqsave();
+ epset &= priv->epavail;
+ if (epset)
+ {
+ /* Select the lowest bit in the set of matching, available endpoints */
+
+ for (epndx = 2; epndx < LPC214X_NPHYSENDPOINTS; epndx++)
+ {
+ uint32_t bit = 1 << epndx;
+ if ((epset & bit) != 0)
+ {
+ /* Mark the IN/OUT endpoint no longer available */
+
+ priv->epavail &= ~(3 << (bit & ~1));
+ irqrestore(flags);
+
+ /* And return the pointer to the standard endpoint structure */
+
+ return &priv->eplist[epndx].ep;
+ }
+ }
+ /* Shouldn't get here */
+ }
+ irqrestore(flags);
+ }
+
+ usbtrace(TRACE_DEVERROR(LPC214X_TRACEERR_NOEP), (uint16_t)eplog);
+ return NULL;
+}
+
+/*******************************************************************************
+ * Name: lpc214x_freeep
+ *
+ * Description:
+ * Free the previously allocated endpoint
+ *
+ *******************************************************************************/
+
+static void lpc214x_freeep(FAR struct usbdev_s *dev, FAR struct usbdev_ep_s *ep)
+{
+ FAR struct lpc214x_usbdev_s *priv = (FAR struct lpc214x_usbdev_s *)dev;
+ FAR struct lpc214x_ep_s *privep = (FAR struct lpc214x_ep_s *)ep;
+ irqstate_t flags;
+
+ usbtrace(TRACE_DEVFREEEP, (uint16_t)privep->epphy);
+
+ if (priv && privep)
+ {
+ /* Mark the endpoint as available */
+
+ flags = irqsave();
+ priv->epavail |= (1 << privep->epphy);
+ irqrestore(flags);
+ }
+}
+
+/*******************************************************************************
+ * Name: lpc214x_getframe
+ *
+ * Description:
+ * Returns the current frame number
+ *
+ *******************************************************************************/
+
+static int lpc214x_getframe(struct usbdev_s *dev)
+{
+#ifdef CONFIG_LPC214X_USBDEV_FRAME_INTERRUPT
+ FAR struct lpc214x_usbdev_s *priv = (FAR struct lpc214x_usbdev_s *)dev;
+
+ /* Return last valid value of SOF read by the interrupt handler */
+
+ usbtrace(TRACE_DEVGETFRAME, (uint16_t)priv->sof);
+ return priv->sof;
+#else
+ /* Return the last frame number detected by the hardware */
+
+ usbtrace(TRACE_DEVGETFRAME, 0);
+ return (int)lpc214x_usbcmd(CMD_USB_DEV_READFRAMENO, 0);
+#endif
+}
+
+/*******************************************************************************
+ * Name: lpc214x_wakeup
+ *
+ * Description:
+ * Tries to wake up the host connected to this device
+ *
+ *******************************************************************************/
+
+static int lpc214x_wakeup(struct usbdev_s *dev)
+{
+ uint8_t arg = USBDEV_DEVSTATUS_SUSPEND;
+ irqstate_t flags;
+
+ usbtrace(TRACE_DEVWAKEUP, (uint16_t)g_usbdev.devstatus);
+
+ flags = irqsave();
+ if (DEVSTATUS_CONNECT(g_usbdev.devstatus))
+ {
+ arg |= USBDEV_DEVSTATUS_CONNECT;
+ }
+
+ lpc214x_usbcmd(CMD_USB_DEV_SETSTATUS, arg);
+ irqrestore(flags);
+ return OK;
+}
+
+/*******************************************************************************
+ * Name: lpc214x_selfpowered
+ *
+ * Description:
+ * Sets/clears the device selfpowered feature
+ *
+ *******************************************************************************/
+
+static int lpc214x_selfpowered(struct usbdev_s *dev, bool selfpowered)
+{
+ FAR struct lpc214x_usbdev_s *priv = (FAR struct lpc214x_usbdev_s *)dev;
+
+ usbtrace(TRACE_DEVSELFPOWERED, (uint16_t)selfpowered);
+
+#ifdef CONFIG_DEBUG
+ if (!dev)
+ {
+ usbtrace(TRACE_DEVERROR(LPC214X_TRACEERR_INVALIDPARMS), 0);
+ return -ENODEV;
+ }
+#endif
+
+ priv->selfpowered = selfpowered;
+ return OK;
+}
+
+/*******************************************************************************
+ * Name: lpc214x_pullup
+ *
+ * Description:
+ * Software-controlled connect to/disconnect from USB host
+ *
+ *******************************************************************************/
+
+static int lpc214x_pullup(struct usbdev_s *dev, bool enable)
+{
+ usbtrace(TRACE_DEVPULLUP, (uint16_t)enable);
+
+ /* The USBDEV_DEVSTATUS_CONNECT bit in the CMD_USB_DEV_SETSTATUS command
+ * controls the LPC214x SoftConnect_N output pin that is used for SoftConnect.
+ */
+
+ lpc214x_usbcmd(CMD_USB_DEV_SETSTATUS, (enable ? USBDEV_DEVSTATUS_CONNECT : 0));
+ return OK;
+}
+
+/*******************************************************************************
+ * Public Functions
+ *******************************************************************************/
+
+/*******************************************************************************
+ * Name: up_usbinitialize
+ *
+ * Description:
+ * Initialize USB hardware.
+ *
+ * Assumptions:
+ * - This function is called very early in the initialization sequence
+ * - PLL and GIO pin initialization is not performed here but should been in
+ * the low-level boot logic: PLL1 must be configured for operation at 48MHz
+ * and P0.23 and PO.31 in PINSEL1 must be configured for Vbus and USB connect
+ * LED.
+ *
+ *******************************************************************************/
+
+void up_usbinitialize(void)
+{
+ struct lpc214x_usbdev_s *priv = &g_usbdev;
+ uint32_t reg;
+ int i;
+
+ usbtrace(TRACE_DEVINIT, 0);
+
+ /* Disable USB interrupts */
+
+ lpc214x_putreg(0, LPC214X_USBDEV_INTST);
+
+ /* Initialize the device state structure */
+
+ memset(priv, 0, sizeof(struct lpc214x_usbdev_s));
+ priv->usbdev.ops = &g_devops;
+ priv->usbdev.ep0 = &priv->eplist[LPC214X_EP0_IN].ep;
+ priv->epavail = LPC214X_EPALLSET;
+
+ /* Initialize the endpoint list */
+
+ for (i = 0; i < LPC214X_NPHYSENDPOINTS; i++)
+ {
+ uint32_t bit = 1 << i;
+
+ /* Set endpoint operations, reference to driver structure (not
+ * really necessary because there is only one controller), and
+ * the physical endpoint number (which is just the index to the
+ * endpoint).
+ */
+ priv->eplist[i].ep.ops = &g_epops;
+ priv->eplist[i].dev = priv;
+
+ /* The index, i, is the physical endpoint address; Map this
+ * to a logical endpoint address usable by the class driver.
+ */
+
+ priv->eplist[i].epphy = i;
+ if (LPC214X_EPPHYIN(i))
+ {
+ priv->eplist[i].ep.eplog = LPC214X_EPPHYIN2LOG(i);
+ }
+ else
+ {
+ priv->eplist[i].ep.eplog = LPC214X_EPPHYOUT2LOG(i);
+ }
+
+ /* The maximum packet size may depend on the type of endpoint */
+
+ if ((LPC214X_EPCTRLSET & bit) != 0)
+ {
+ priv->eplist[i].ep.maxpacket = LPC214X_EP0MAXPACKET;
+ }
+ else if ((LPC214X_EPINTRSET & bit) != 0)
+ {
+ priv->eplist[i].ep.maxpacket = LPC214X_INTRMAXPACKET;
+ }
+ else if ((LPC214X_EPBULKSET & bit) != 0)
+ {
+ priv->eplist[i].ep.maxpacket = LPC214X_BULKMAXPACKET;
+ }
+ else /* if ((LPC214X_EPISOCSET & bit) != 0) */
+ {
+ priv->eplist[i].ep.maxpacket = LPC214X_ISOCMAXPACKET;
+ }
+ }
+
+ /* Turn on USB power and clocking */
+
+ reg = lpc214x_getreg(LPC214X_PCON_PCONP);
+ reg |= LPC214X_PCONP_PCUSB;
+ lpc214x_putreg(reg, LPC214X_PCON_PCONP);
+
+ /* Attach USB controller interrupt handler */
+
+ if (irq_attach(LPC214X_USB_IRQ, lpc214x_usbinterrupt) != 0)
+ {
+ usbtrace(TRACE_DEVERROR(LPC214X_TRACEERR_IRQREGISTRATION),
+ (uint16_t)LPC214X_USB_IRQ);
+ goto errout;
+ }
+
+ /* Enable USB inerrupts at the controller -- but do not disable
+ * the ARM interrupt until the device is bound to the class
+ * driver
+ */
+
+ lpc214x_putreg(USBDEV_INTST_ENUSBINTS, LPC214X_USBDEV_INTST);
+
+ /* Disconnect device */
+
+ lpc214x_pullup(&priv->usbdev, false);
+
+ /* Enable EP0 for OUT (host-to-device) */
+
+ lpc214x_usbcmd(CMD_USB_DEV_SETADDRESS, CMD_USB_SETADDRESS_DEVEN|0);
+ lpc214x_usbcmd(CMD_USB_DEV_SETADDRESS, CMD_USB_SETADDRESS_DEVEN|0);
+
+ /* Reset/Re-initialize the USB hardware */
+
+ lpc214x_usbreset(priv);
+
+ /* Init Device state structure */
+
+ priv->devstatus = lpc214x_usbcmd(CMD_USB_DEV_GETSTATUS, 0);
+ return;
+
+errout:
+ up_usbuninitialize();
+}
+
+/*******************************************************************************
+ * Name: up_usbuninitialize
+ *******************************************************************************/
+
+void up_usbuninitialize(void)
+{
+ struct lpc214x_usbdev_s *priv = &g_usbdev;
+ uint32_t reg;
+ irqstate_t flags;
+
+ usbtrace(TRACE_DEVUNINIT, 0);
+
+ if (priv->driver)
+ {
+ usbtrace(TRACE_DEVERROR(LPC214X_TRACEERR_DRIVERREGISTERED), 0);
+ usbdev_unregister(priv->driver);
+ }
+
+ /* Disconnect device */
+
+ flags = irqsave();
+ lpc214x_pullup(&priv->usbdev, false);
+ priv->usbdev.speed = USB_SPEED_UNKNOWN;
+ lpc214x_usbcmd(CMD_USB_DEV_CONFIG, 0);
+
+ /* Disable and detach IRQs */
+
+ up_disable_irq(LPC214X_USB_IRQ);
+ irq_detach(LPC214X_USB_IRQ);
+
+ /* Turn off USB power and clocking */
+
+ reg = lpc214x_getreg(LPC214X_PCON_PCONP);
+ reg &= ~LPC214X_PCONP_PCUSB;
+ lpc214x_putreg(reg, LPC214X_PCON_PCONP);
+ irqrestore(flags);
+}
+
+/*******************************************************************************
+ * Name: usbdev_register
+ *
+ * Description:
+ * Register a USB device class driver. The class driver's bind() method will be
+ * called to bind it to a USB device driver.
+ *
+ *******************************************************************************/
+
+int usbdev_register(struct usbdevclass_driver_s *driver)
+{
+ int ret;
+
+ usbtrace(TRACE_DEVREGISTER, 0);
+
+#ifdef CONFIG_DEBUG
+ if (!driver || !driver->ops->bind || !driver->ops->unbind ||
+ !driver->ops->disconnect || !driver->ops->setup)
+ {
+ usbtrace(TRACE_DEVERROR(LPC214X_TRACEERR_INVALIDPARMS), 0);
+ return -EINVAL;
+ }
+
+ if (g_usbdev.driver)
+ {
+ usbtrace(TRACE_DEVERROR(LPC214X_TRACEERR_DRIVER), 0);
+ return -EBUSY;
+ }
+#endif
+
+ /* First hook up the driver */
+
+ g_usbdev.driver = driver;
+
+ /* Then bind the class driver */
+
+ ret = CLASS_BIND(driver, &g_usbdev.usbdev);
+ if (ret)
+ {
+ usbtrace(TRACE_DEVERROR(LPC214X_TRACEERR_BINDFAILED), (uint16_t)-ret);
+ g_usbdev.driver = NULL;
+ }
+ else
+ {
+ /* Enable USB controller interrupts */
+
+ up_enable_irq(LPC214X_USB_IRQ);
+ }
+ return ret;
+}
+
+/*******************************************************************************
+ * Name: usbdev_unregister
+ *
+ * Description:
+ * Un-register usbdev class driver.If the USB device is connected to a USB host,
+ * it will first disconnect(). The driver is also requested to unbind() and clean
+ * up any device state, before this procedure finally returns.
+ *
+ *******************************************************************************/
+
+int usbdev_unregister(struct usbdevclass_driver_s *driver)
+{
+ usbtrace(TRACE_DEVUNREGISTER, 0);
+
+#ifdef CONFIG_DEBUG
+ if (driver != g_usbdev.driver)
+ {
+ usbtrace(TRACE_DEVERROR(LPC214X_TRACEERR_INVALIDPARMS), 0);
+ return -EINVAL;
+ }
+#endif
+
+ /* Unbind the class driver */
+
+ CLASS_UNBIND(driver, &g_usbdev.usbdev);
+
+ /* Disable USB controller interrupts */
+
+ up_disable_irq(LPC214X_USB_IRQ);
+
+ /* Unhook the driver */
+
+ g_usbdev.driver = NULL;
+ return OK;
+}
diff --git a/nuttx/arch/arm/src/lpc214x/lpc214x_usbdev.h b/nuttx/arch/arm/src/lpc214x/lpc214x_usbdev.h
new file mode 100644
index 000000000..814622ef5
--- /dev/null
+++ b/nuttx/arch/arm/src/lpc214x/lpc214x_usbdev.h
@@ -0,0 +1,346 @@
+/*******************************************************************************
+ * arch/arm/src/lpc214x/lpc214x_usbdev.h
+ *
+ * Copyright (C) 2008-2009 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ *******************************************************************************/
+
+#ifndef __ARCH_ARM_SRC_LPC214X_LPC214X_USBDEV_H
+#define __ARCH_ARM_SRC_LPC214X_LPC214X_USBDEV_H
+
+/*******************************************************************************
+ * Included Files
+ *******************************************************************************/
+
+#include <nuttx/config.h>
+
+/*******************************************************************************
+ * Definitions
+ *******************************************************************************/
+
+/* PINSEL1 bit definitions for UART0/1:
+ *
+ * P0.23 = 01 to enable VBus sense (bits 14-15)
+ * P0.31 = 10 to enable CONNECT (bits 30-31)
+ */
+
+#define LPC214X_USBDEV_PINSEL (0x80004000) /* PINSEL1 value for USB */
+#define LPC214X_USBDEV_PINMASK (0xc000c000) /* PINSEL1 mask for USB */
+
+/* USB RAM ********************************************************************/
+
+#define LPC214X_USBDEV_RAMBASE (0x7fd00000)
+#define LPC214X_USBDEV_RAMSIZE (8*1024)
+
+/* USB register address definitions ********************************************/
+
+#define LPC214X_USBDEV_PLLCON (0xe01fc0a0)
+#define LPC214X_USBDEV_PLLCFG (0xe01fc0a4)
+#define LPC214X_USBDEV_PLLSTAT (0xe01fc0a8)
+#define LPC214X_USBDEV_PLLFEED (0xe01fc0ac)
+
+#define LPC214X_USBDEV_INTST (0xe01fc1c0)
+
+#define LPC214X_USBDEV_DEVINTST (0xe0090000)
+#define LPC214X_USBDEV_DEVINTEN (0xe0090004)
+#define LPC214X_USBDEV_DEVINTCLR (0xe0090008)
+#define LPC214X_USBDEV_DEVINTSET (0xe009000c)
+#define LPC214X_USBDEV_CMDCODE (0xe0090010)
+#define LPC214X_USBDEV_CMDDATA (0xe0090014)
+#define LPC214X_USBDEV_RXDATA (0xe0090018)
+#define LPC214X_USBDEV_TXDATA (0xe009001c)
+#define LPC214X_USBDEV_RXPLEN (0xe0090020)
+#define LPC214X_USBDEV_TXPLEN (0xe0090024)
+#define LPC214X_USBDEV_CTRL (0xe0090028)
+#define LPC214X_USBDEV_DEVINTPRI (0xe009002c)
+#define LPC214X_USBDEV_EPINTST (0xe0090030)
+#define LPC214X_USBDEV_EPINTEN (0xe0090034)
+#define LPC214X_USBDEV_EPINTCLR (0xe0090038)
+#define LPC214X_USBDEV_EPINTSET (0xe009003c)
+#define LPC214X_USBDEV_EPINTPRI (0xe0090040)
+#define LPC214X_USBDEV_REEP (0xe0090044)
+#define LPC214X_USBDEV_EPIND (0xe0090048)
+#define LPC214X_USBDEV_MAXPSIZE (0xe009004c)
+#define LPC214X_USBDEV_DMARST (0xe0090050)
+#define LPC214X_USBDEV_DMARCLR (0xe0090054)
+#define LPC214X_USBDEV_DMARSET (0xe0090058)
+
+#define LPC214X_USBDEV_UDCAH (0xe0090080)
+#define LPC214X_USBDEV_EPDMAST (0xe0090084)
+#define LPC214X_USBDEV_EPDMAEN (0xe0090088)
+#define LPC214X_USBDEV_EPDMADIS (0xe009008c)
+#define LPC214X_USBDEV_DMAINTST (0xe0090090)
+#define LPC214X_USBDEV_DMAINTEN (0xe0090094)
+
+#define LPC214X_USBDEV_EOTINTST (0xe00900a0)
+#define LPC214X_USBDEV_EOTINTCLR (0xe00900a4)
+#define LPC214X_USBDEV_EOTINTSET (0xe00900a8)
+#define LPC214X_USBDEV_NDDRINTST (0xe00900ac)
+#define LPC214X_USBDEV_NDDRINTCLR (0xe00900b0)
+#define LPC214X_USBDEV_NDDRINTSET (0xe00900b4)
+#define LPC214X_USBDEV_SYSERRINTST (0xe00900b8)
+#define LPC214X_USBDEV_SYSERRINTCLR (0xe00900bc)
+#define LPC214X_USBDEV_SYSERRINTSET (0xe00900c0)
+
+/* USB register bit definitions ************************************************/
+
+/* INTST bit definitions */
+
+#define USBDEV_INTST_REQLP (0x00000001)
+#define USBDEV_INTST_REQHP (0x00000002)
+#define USBDEV_INTST_REQDMA (0x00000004)
+#define USBDEV_INTST_NEEDCLOCK (0x00000100)
+#define USBDEV_INTST_ENUSBINTS (0x80000000)
+#define USBDEV_INTST_MASK (0x80000107)
+
+/* DEVINTST/DEVINTEN/DEVINTCLR/DEVINTSET bit definitions */
+
+#define USBDEV_DEVINT_FRAME (0x00000001)
+#define USBDEV_DEVINT_EPFAST (0x00000002)
+#define USBDEV_DEVINT_EPSLOW (0x00000004)
+#define USBDEV_DEVINT_DEVSTAT (0x00000008)
+#define USBDEV_DEVINT_CCEMTY (0x00000010)
+#define USBDEV_DEVINT_CDFULL (0x00000020)
+#define USBDEV_DEVINT_RXENDPKT (0x00000040)
+#define USBDEV_DEVINT_TXENDPKT (0x00000080)
+#define USBDEV_DEVINT_EPRLZED (0x00000100)
+#define USBDEV_DEVINT_EPRINT (0x00000200)
+#define USBDEV_DEVINT_MASK (0x000003ff)
+
+/* DEVINTPRI bit definitions */
+
+#define USBDEV_DEVINTPRI_FRAME (0x00000001)
+#define USBDEV_DEVINTPRI_EPFAST (0x00000002)
+#define USBDEV_DEVINTPRI_MASK (0x00000003)
+
+/* RXPLEN bit definitions */
+
+#define USBDEV_RXPLEN_PKTLENGTH (0x000003ff)
+#define USBDEV_RXPLEN_PKTLENGTH_MASK (0x000003ff)
+#define USBDEV_RXPLEN_DV (0x00000400)
+#define USBDEV_RXPLEN_PKTRDY (0x00000800)
+#define USBDEV_RXPLEN_MASK (0x00000fff)
+
+/* TXPLEN bit definitions */
+
+#define USBDEV_TXPLEN_PKTLENGTH (0x000003ff)
+#define USBDEV_TXPLEN_MASK (0x000003ff)
+
+/* USBCTRL bit definitions */
+
+#define USBDEV_CTRL_RDEN (0x00000001)
+#define USBDEV_CTRL_WREN (0x00000002)
+#define USBDEV_CTRL_LOGENDPOINT (0x0000003c)
+#define USBDEV_CTRL_MASK (0x0000003f)
+
+/* CMDCODE bit definitions */
+
+#define USBDEV_CMDCODE_CMDPHASE (0x0000ff00)
+#define USBDEV_CMDCODE_CMDCODE (0x00ff0000)
+#define USBDEV_CMDCODE_MASK (0x00ffff00)
+
+/* DMAINSTST/DMAINSTEN bit defintions */
+
+#define USBDEV_DMAINST_EOT (0x00000001)
+#define USBDEV_DMAINST_NDDR (0x00000002)
+#define USBDEV_DMAINST_SE (0x00000004)
+#define USBDEV_DMAINST_MASK (0x00000007)
+
+/* Device Status Bits */
+
+#define USBDEV_EPSTALL (0x00000001)
+#define USBDEV_EPSTALLSTATUS (0x00000002)
+#define USBDEV_EPSETUPPACKET (0x00000004)
+#define USBDEV_EPPOSSTATUS (0x00000010)
+#define USBDEV_EPCONDSTALL (0x00000080)
+
+/* USB Control register bit definitions */
+
+#define LPC214X_USBCTRL_RDEN (0x00000001) /* Bit 0=1: Read is enabled */
+#define LPC214X_USBCTRL_WREN (0x00000002) /* Bit 0=1: Write is enabled */
+#define LPC214X_USBCTRL_EPMASK (0x0000003c) /* Bits 2:5: Logical endpoint 0-15 */
+
+/* Endpoints *******************************************************************/
+
+#define LPC214X_EP0_OUT 0
+#define LPC214X_EP0_IN 1
+#define LPC214X_CTRLEP_OUT LPC214X_EP0_OUT
+#define LPC214X_CTRLEP_IN LPC214X_EP0_IN
+#define LPC214X_EP1_OUT 2
+#define LPC214X_EP1_IN 3
+#define LPC214X_EP2_OUT 4
+#define LPC214X_EP2_IN 5
+#define LPC214X_EP3_OUT 6
+#define LPC214X_EP3_IN 7
+#define LPC214X_EP4_OUT 8
+#define LPC214X_EP4_IN 9
+#define LPC214X_EP5_OUT 10
+#define LPC214X_EP5_IN 11
+#define LPC214X_EP6_OUT 12
+#define LPC214X_EP6_IN 13
+#define LPC214X_EP7_OUT 14
+#define LPC214X_EP7_IN 15
+#define LPC214X_EP8_OUT 16
+#define LPC214X_EP8_IN 17
+#define LPC214X_EP9_OUT 18
+#define LPC214X_EP9_IN 19
+#define LPC214X_EP10_OUT 20
+#define LPC214X_EP10_IN 21
+#define LPC214X_EP11_OUT 22
+#define LPC214X_EP11_IN 23
+#define LPC214X_EP12_OUT 24
+#define LPC214X_EP12_IN 25
+#define LPC214X_EP13_OUT 26
+#define LPC214X_EP13_IN 27
+#define LPC214X_EP14_OUT 28
+#define LPC214X_EP14_IN 29
+#define LPC214X_EP15_OUT 30
+#define LPC214X_EP15_IN 31
+#define LPC214X_NUMEPS 32
+
+/* Commands ********************************************************************/
+
+/* USB Command Code Register -- Command phase values */
+
+#define CMD_USB_CMDWR (0x00000500)
+#define CMD_USB_DATAWR (0x00000100)
+#define CMD_USB_DATARD (0x00000200)
+
+/* Device Commands */
+
+#define CMD_USB_DEV_SETADDRESS (0x00d0)
+#define CMD_USB_DEV_CONFIG (0x00d8)
+#define CMD_USB_DEV_SETMODE (0x00f3)
+#define CMD_USB_DEV_READFRAMENO (0x00f5)
+#define CMD_USB_DEV_READTESTREG (0x00fd)
+#define CMD_USB_DEV_SETSTATUS (0x01fe)
+#define CMD_USB_DEV_GETSTATUS (0x00fe)
+#define CMD_USB_DEV_GETERRORCODE (0x00ff)
+#define CMD_USB_DEV_READERRORSTATUS (0x00fb)
+
+/* Endpoint Commands */
+
+#define CMD_USB_EP_SELECT (0x0000)
+#define CMD_USB_EP_SELECTCLEAR (0x0040)
+#define CMD_USB_EP_SETSTATUS (0x0140)
+#define CMD_USB_EP_CLRBUFFER (0x00f2)
+#define CMD_USB_EP_VALIDATEBUFFER (0x00fa)
+
+/* Command Data ****************************************************************/
+
+/* DEV SETADDRESS command bits */
+
+#define CMD_USB_SETADDRESS_DEVEN (0x80)
+
+/* Command Responses ***********************************************************/
+
+/* Device Status Bits (8-bits) */
+
+#define USBDEV_DEVSTATUS_CONNECT (0x01) /* Bit 0: Connected */
+#define USBDEV_DEVSTATUS_CONNCHG (0x02) /* Bit 1: Connect change */
+#define USBDEV_DEVSTATUS_SUSPEND (0x04) /* Bit 2: Suspend */
+#define USBDEV_DEVSTATUS_SUSPCHG (0x08) /* Bit 3: Suspend change */
+#define USBDEV_DEVSTATUS_RESET (0x10) /* Bit 4: Bus reset bit */
+
+/* EP Select response */
+
+#define CMD_USB_EPSELECT_FE (0x01) /* Bit 0=1: IN empty or OUT full */
+#define CMD_USB_EPSELECT_ST (0x02) /* Bit 1=1: Endpoint is stalled */
+#define CMD_USB_EPSELECT_STP (0x04) /* Bit 2=1: Last packet was setup */
+#define CMD_USB_EPSELECT_PO (0x05) /* Bit 3=1: Previous packet was overwritten */
+#define CMD_USB_EPSELECT_EPN (0x10) /* Bit 4=1: NAK sent */
+#define CMD_USB_EPSELECT_B1FULL (0x20) /* Bit 5=1: Buffer 1 full */
+#define CMD_USB_EPSELECT_B2FULL (0x40) /* Bit 6=1: Buffer 2 full */
+
+/* EP CLRBUFFER response */
+
+#define CMD_USB_CLRBUFFER_PO (0x00000001)
+
+/* DMA *************************************************************************/
+
+/* The DMA descriptor */
+
+#define USB_DMADESC_NEXTDDPTR 0 /* Offset 0: Next USB descriptor in RAM */
+#define USB_DMADESC_CONFIG 1 /* Offset 1: DMA configuration info. */
+#define USB_DMADESC_STARTADDR 2 /* Offset 2: DMA start address */
+#define USB_DMADESC_STATUS 3 /* Offset 3: DMA status info (read only) */
+#define USB_DMADESC_ISOCSIZEADDR 4 /* Offset 4: Isoc. packet size address */
+
+/* Bit settings for offset 1 */
+
+#define USB_DMADESC_MODENORMAL (0x00000000) /* Bits 0-1=00: Mode normal */
+#define USB_DMADESC_MODEATLE (0x00000001) /* Bits 0-1=01: ATLE normal */
+#define USB_DMADESC_NEXTDDVALID (0x00000004) /* Bit 2=1: next descriptor valid */
+#define USB_DMADESC_ISCOEP (0x00000010) /* Bit 4=1: isoc endpoint */
+#define USB_DMADESC_PKTSIZEMASK (0x0000ffe0) /* Bits 5-15: packet size */
+#define USB_DMADESC_PKTSIZESHIFT (5) /* Bits 5-15: packet size */
+#define USB_DMADESC_BUFLENMASK (0xffff0000) /* Bits 16-31: buffer length */
+#define USB_DMADESC_BULENSHIFT (16) /* Bits 16-31: buffer length */
+
+/* Bit settings for offset 3 (all must be initialized to zero) */
+
+#define USB_DMADESC_STATUSMASK (0x0000001e) /* Bits 1-4: DMA status */
+#define USB_DMADESC_NOTSERVICED (0x00000000)
+#define USB_DMADESC_BEINGSERVICED (0x00000002)
+#define USB_DMADESC_NORMALCOMPLETION (0x00000004)
+#define USB_DMADESC_DATAUNDERRUN (0x00000006)
+#define USB_DMADESC_DATAOVERRUN (0x00000010)
+#define USB_DMADESC_SYSTEMERROR (0x00000012)
+#define USB_DMADESC_PKTVALID (0x00000020) /* Bit 5=1: Packet valid */
+#define USB_DMADESC_LSBEXTRACTED (0x00000040) /* Bit 6=1: LS byte extracted */
+#define USB_DMADESC_MSBEXTRACTED (0x00000080) /* Bit 7=1: MS byte extracted */
+#define USB_DMADESC_MSGLENPOSMASK (0x00003f00) /* Bits 8-13: Message length position */
+#define USB_DMADESC_MSGLENPOSSHIFT (8) /* Bits 8-13: Message length position */
+#define USB_DMADESC_DMACOUNTMASK (0xffff0000) /* Bits 16-31: DMA count */
+#define USB_DMADESC_DMACOUNTSHIFT (16) /* Bits 16-31: DMA count */
+
+/* DMA packet size format */
+
+#define USB_DMAPKTSIZE_PKTLENMASK (0x0000ffff) /* Bits 0-15: Packet length */
+#define USB_DMAPKTSIZE_PKTLENSHIFT (0) /* Bits 0-15: Packet length */
+#define USB_DMAPKTSIZE_PKTVALID (0x00010000) /* Bit 16=1: Packet valid */
+#define USB_DMAPKTSIZE_FRAMENOMASK (0xfffe0000) /* Bit 17-31: Frame number */
+#define USB_DMAPKTSIZE_FRAMENOSHIFT (17) /* Bit 17-31: Frame number */
+
+
+/*******************************************************************************
+ * Private Types
+ *******************************************************************************/
+
+/*******************************************************************************
+ * Public Data
+ *******************************************************************************/
+
+/*******************************************************************************
+ * Public Functions
+ *******************************************************************************/
+
+#endif /* __ARCH_ARM_SRC_LPC214X_LPC214X_USBDEV_H */
diff --git a/nuttx/arch/arm/src/lpc214x/lpc214x_vic.h b/nuttx/arch/arm/src/lpc214x/lpc214x_vic.h
new file mode 100644
index 000000000..520c6037a
--- /dev/null
+++ b/nuttx/arch/arm/src/lpc214x/lpc214x_vic.h
@@ -0,0 +1,70 @@
+/************************************************************************************
+ * arch/arm/src/lpc214x/lpc214x_vic.h
+ *
+ * Copyright (C) 2007, 2008 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ************************************************************************************/
+
+#ifndef __LPC214X_VIC_H
+#define __LPC214X_VIC_H
+
+/************************************************************************************
+ * Included Files
+ ************************************************************************************/
+
+/************************************************************************************
+ * Definitions
+ ************************************************************************************/
+
+/* All VIC registers are 32-bits wide */
+
+#define vic_getreg(o) getreg32(LPC214X_VIC_BASE+(o))
+#define vic_putreg(v,o) putreg32((v),LPC214X_VIC_BASE+(o))
+
+/* Vector Control Register bit definitions */
+
+#define LPC214X_VECTCNTL_IRQMASK (0x0000001f)
+#define LPC214X_VECTCNTL_IRQSHIFT (0)
+#define LPC214X_VECTCNTL_ENABLE (1 << 5)
+
+/************************************************************************************
+ * Public Types
+ ************************************************************************************/
+
+/************************************************************************************
+ * Inline Functions
+ ************************************************************************************/
+
+/************************************************************************************
+ * Public Function Prototypes
+ ************************************************************************************/
+
+#endif /* __LPC214X_VIC_H */