drivers/serial : move serial drivers to drivers/serial

Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile
index 40f3d67..735c630 100644
--- a/drivers/serial/Makefile
+++ b/drivers/serial/Makefile
@@ -25,8 +25,19 @@
 
 LIB 	:= $(obj)libserial.a
 
-COBJS 	:= mcfuart.o serial_pl010.o serial_pl011.o
+COBJS-y += atmel_usart.o
+COBJS-y += mcfuart.o
+COBJS-y += ns9750_serial.o
+COBJS-y += ns16550.o
+COBJS-y += s3c4510b_uart.o
+COBJS-y += serial.o
+COBJS-y += serial_max3100.o
+COBJS-y += serial_pl010.o
+COBJS-y += serial_pl011.o
+COBJS-y += serial_xuartlite.o
+COBJS-y += usbtty.o
 
+COBJS	:= $(COBJS-y)
 SRCS 	:= $(COBJS:.o=.c)
 OBJS 	:= $(addprefix $(obj),$(COBJS))
 
diff --git a/drivers/serial/atmel_usart.c b/drivers/serial/atmel_usart.c
new file mode 100644
index 0000000..f35b997
--- /dev/null
+++ b/drivers/serial/atmel_usart.c
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2004-2006 Atmel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#include <common.h>
+
+#ifdef CONFIG_ATMEL_USART
+#include <asm/io.h>
+#include <asm/arch/clk.h>
+#include <asm/arch/memory-map.h>
+
+#if defined(CONFIG_USART0)
+# define USART_ID	0
+# define USART_BASE	USART0_BASE
+#elif defined(CONFIG_USART1)
+# define USART_ID	1
+# define USART_BASE	USART1_BASE
+#elif defined(CONFIG_USART2)
+# define USART_ID	2
+# define USART_BASE	USART2_BASE
+#elif defined(CONFIG_USART3)
+# define USART_ID	3
+# define USART_BASE	USART3_BASE
+#endif
+
+#include "atmel_usart.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+void serial_setbrg(void)
+{
+	unsigned long divisor;
+	unsigned long usart_hz;
+
+	/*
+	 *              Master Clock
+	 * Baud Rate = --------------
+	 *                16 * CD
+	 */
+	usart_hz = get_usart_clk_rate(USART_ID);
+	divisor = (usart_hz / 16 + gd->baudrate / 2) / gd->baudrate;
+	usart3_writel(BRGR, USART3_BF(CD, divisor));
+}
+
+int serial_init(void)
+{
+	usart3_writel(CR, USART3_BIT(RSTRX) | USART3_BIT(RSTTX));
+
+	serial_setbrg();
+
+	usart3_writel(CR, USART3_BIT(RXEN) | USART3_BIT(TXEN));
+	usart3_writel(MR, (USART3_BF(USART_MODE, USART3_USART_MODE_NORMAL)
+			   | USART3_BF(USCLKS, USART3_USCLKS_MCK)
+			   | USART3_BF(CHRL, USART3_CHRL_8)
+			   | USART3_BF(PAR, USART3_PAR_NONE)
+			   | USART3_BF(NBSTOP, USART3_NBSTOP_1)));
+
+	return 0;
+}
+
+void serial_putc(char c)
+{
+	if (c == '\n')
+		serial_putc('\r');
+
+	while (!(usart3_readl(CSR) & USART3_BIT(TXRDY))) ;
+	usart3_writel(THR, c);
+}
+
+void serial_puts(const char *s)
+{
+	while (*s)
+		serial_putc(*s++);
+}
+
+int serial_getc(void)
+{
+	while (!(usart3_readl(CSR) & USART3_BIT(RXRDY))) ;
+	return usart3_readl(RHR);
+}
+
+int serial_tstc(void)
+{
+	return (usart3_readl(CSR) & USART3_BIT(RXRDY)) != 0;
+}
+
+#endif /* CONFIG_ATMEL_USART */
diff --git a/drivers/serial/atmel_usart.h b/drivers/serial/atmel_usart.h
new file mode 100644
index 0000000..af3773a
--- /dev/null
+++ b/drivers/serial/atmel_usart.h
@@ -0,0 +1,314 @@
+/*
+ * Register definitions for the Atmel USART3 module.
+ *
+ * Copyright (C) 2005-2006 Atmel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#ifndef __DRIVERS_ATMEL_USART_H__
+#define __DRIVERS_ATMEL_USART_H__
+
+/* USART3 register offsets */
+#define USART3_CR				0x0000
+#define USART3_MR				0x0004
+#define USART3_IER				0x0008
+#define USART3_IDR				0x000c
+#define USART3_IMR				0x0010
+#define USART3_CSR				0x0014
+#define USART3_RHR				0x0018
+#define USART3_THR				0x001c
+#define USART3_BRGR				0x0020
+#define USART3_RTOR				0x0024
+#define USART3_TTGR				0x0028
+#define USART3_FIDI				0x0040
+#define USART3_NER				0x0044
+#define USART3_XXR				0x0048
+#define USART3_IFR				0x004c
+#define USART3_RPR				0x0100
+#define USART3_RCR				0x0104
+#define USART3_TPR				0x0108
+#define USART3_TCR				0x010c
+#define USART3_RNPR				0x0110
+#define USART3_RNCR				0x0114
+#define USART3_TNPR				0x0118
+#define USART3_TNCR				0x011c
+#define USART3_PTCR				0x0120
+#define USART3_PTSR				0x0124
+
+/* Bitfields in CR */
+#define USART3_RSTRX_OFFSET			2
+#define USART3_RSTRX_SIZE			1
+#define USART3_RSTTX_OFFSET			3
+#define USART3_RSTTX_SIZE			1
+#define USART3_RXEN_OFFSET			4
+#define USART3_RXEN_SIZE			1
+#define USART3_RXDIS_OFFSET			5
+#define USART3_RXDIS_SIZE			1
+#define USART3_TXEN_OFFSET			6
+#define USART3_TXEN_SIZE			1
+#define USART3_TXDIS_OFFSET			7
+#define USART3_TXDIS_SIZE			1
+#define USART3_RSTSTA_OFFSET			8
+#define USART3_RSTSTA_SIZE			1
+#define USART3_STTBRK_OFFSET			9
+#define USART3_STTBRK_SIZE			1
+#define USART3_STPBRK_OFFSET			10
+#define USART3_STPBRK_SIZE			1
+#define USART3_STTTO_OFFSET			11
+#define USART3_STTTO_SIZE			1
+#define USART3_SENDA_OFFSET			12
+#define USART3_SENDA_SIZE			1
+#define USART3_RSTIT_OFFSET			13
+#define USART3_RSTIT_SIZE			1
+#define USART3_RSTNACK_OFFSET			14
+#define USART3_RSTNACK_SIZE			1
+#define USART3_RETTO_OFFSET			15
+#define USART3_RETTO_SIZE			1
+#define USART3_DTREN_OFFSET			16
+#define USART3_DTREN_SIZE			1
+#define USART3_DTRDIS_OFFSET			17
+#define USART3_DTRDIS_SIZE			1
+#define USART3_RTSEN_OFFSET			18
+#define USART3_RTSEN_SIZE			1
+#define USART3_RTSDIS_OFFSET			19
+#define USART3_RTSDIS_SIZE			1
+#define USART3_COMM_TX_OFFSET			30
+#define USART3_COMM_TX_SIZE			1
+#define USART3_COMM_RX_OFFSET			31
+#define USART3_COMM_RX_SIZE			1
+
+/* Bitfields in MR */
+#define USART3_USART_MODE_OFFSET		0
+#define USART3_USART_MODE_SIZE			4
+#define USART3_USCLKS_OFFSET			4
+#define USART3_USCLKS_SIZE			2
+#define USART3_CHRL_OFFSET			6
+#define USART3_CHRL_SIZE			2
+#define USART3_SYNC_OFFSET			8
+#define USART3_SYNC_SIZE			1
+#define USART3_PAR_OFFSET			9
+#define USART3_PAR_SIZE				3
+#define USART3_NBSTOP_OFFSET			12
+#define USART3_NBSTOP_SIZE			2
+#define USART3_CHMODE_OFFSET			14
+#define USART3_CHMODE_SIZE			2
+#define USART3_MSBF_OFFSET			16
+#define USART3_MSBF_SIZE			1
+#define USART3_MODE9_OFFSET			17
+#define USART3_MODE9_SIZE			1
+#define USART3_CLKO_OFFSET			18
+#define USART3_CLKO_SIZE			1
+#define USART3_OVER_OFFSET			19
+#define USART3_OVER_SIZE			1
+#define USART3_INACK_OFFSET			20
+#define USART3_INACK_SIZE			1
+#define USART3_DSNACK_OFFSET			21
+#define USART3_DSNACK_SIZE			1
+#define USART3_MAX_ITERATION_OFFSET		24
+#define USART3_MAX_ITERATION_SIZE		3
+#define USART3_FILTER_OFFSET			28
+#define USART3_FILTER_SIZE			1
+
+/* Bitfields in CSR */
+#define USART3_RXRDY_OFFSET			0
+#define USART3_RXRDY_SIZE			1
+#define USART3_TXRDY_OFFSET			1
+#define USART3_TXRDY_SIZE			1
+#define USART3_RXBRK_OFFSET			2
+#define USART3_RXBRK_SIZE			1
+#define USART3_ENDRX_OFFSET			3
+#define USART3_ENDRX_SIZE			1
+#define USART3_ENDTX_OFFSET			4
+#define USART3_ENDTX_SIZE			1
+#define USART3_OVRE_OFFSET			5
+#define USART3_OVRE_SIZE			1
+#define USART3_FRAME_OFFSET			6
+#define USART3_FRAME_SIZE			1
+#define USART3_PARE_OFFSET			7
+#define USART3_PARE_SIZE			1
+#define USART3_TIMEOUT_OFFSET			8
+#define USART3_TIMEOUT_SIZE			1
+#define USART3_TXEMPTY_OFFSET			9
+#define USART3_TXEMPTY_SIZE			1
+#define USART3_ITERATION_OFFSET			10
+#define USART3_ITERATION_SIZE			1
+#define USART3_TXBUFE_OFFSET			11
+#define USART3_TXBUFE_SIZE			1
+#define USART3_RXBUFF_OFFSET			12
+#define USART3_RXBUFF_SIZE			1
+#define USART3_NACK_OFFSET			13
+#define USART3_NACK_SIZE			1
+#define USART3_RIIC_OFFSET			16
+#define USART3_RIIC_SIZE			1
+#define USART3_DSRIC_OFFSET			17
+#define USART3_DSRIC_SIZE			1
+#define USART3_DCDIC_OFFSET			18
+#define USART3_DCDIC_SIZE			1
+#define USART3_CTSIC_OFFSET			19
+#define USART3_CTSIC_SIZE			1
+#define USART3_RI_OFFSET			20
+#define USART3_RI_SIZE				1
+#define USART3_DSR_OFFSET			21
+#define USART3_DSR_SIZE				1
+#define USART3_DCD_OFFSET			22
+#define USART3_DCD_SIZE				1
+#define USART3_CTS_OFFSET			23
+#define USART3_CTS_SIZE				1
+
+/* Bitfields in RHR */
+#define USART3_RXCHR_OFFSET			0
+#define USART3_RXCHR_SIZE			9
+
+/* Bitfields in THR */
+#define USART3_TXCHR_OFFSET			0
+#define USART3_TXCHR_SIZE			9
+
+/* Bitfields in BRGR */
+#define USART3_CD_OFFSET			0
+#define USART3_CD_SIZE				16
+
+/* Bitfields in RTOR */
+#define USART3_TO_OFFSET			0
+#define USART3_TO_SIZE				16
+
+/* Bitfields in TTGR */
+#define USART3_TG_OFFSET			0
+#define USART3_TG_SIZE				8
+
+/* Bitfields in FIDI */
+#define USART3_FI_DI_RATIO_OFFSET		0
+#define USART3_FI_DI_RATIO_SIZE			11
+
+/* Bitfields in NER */
+#define USART3_NB_ERRORS_OFFSET			0
+#define USART3_NB_ERRORS_SIZE			8
+
+/* Bitfields in XXR */
+#define USART3_XOFF_OFFSET			0
+#define USART3_XOFF_SIZE			8
+#define USART3_XON_OFFSET			8
+#define USART3_XON_SIZE				8
+
+/* Bitfields in IFR */
+#define USART3_IRDA_FILTER_OFFSET		0
+#define USART3_IRDA_FILTER_SIZE			8
+
+/* Bitfields in RCR */
+#define USART3_RXCTR_OFFSET			0
+#define USART3_RXCTR_SIZE			16
+
+/* Bitfields in TCR */
+#define USART3_TXCTR_OFFSET			0
+#define USART3_TXCTR_SIZE			16
+
+/* Bitfields in RNCR */
+#define USART3_RXNCR_OFFSET			0
+#define USART3_RXNCR_SIZE			16
+
+/* Bitfields in TNCR */
+#define USART3_TXNCR_OFFSET			0
+#define USART3_TXNCR_SIZE			16
+
+/* Bitfields in PTCR */
+#define USART3_RXTEN_OFFSET			0
+#define USART3_RXTEN_SIZE			1
+#define USART3_RXTDIS_OFFSET			1
+#define USART3_RXTDIS_SIZE			1
+#define USART3_TXTEN_OFFSET			8
+#define USART3_TXTEN_SIZE			1
+#define USART3_TXTDIS_OFFSET			9
+#define USART3_TXTDIS_SIZE			1
+
+/* Constants for USART_MODE */
+#define USART3_USART_MODE_NORMAL		0
+#define USART3_USART_MODE_RS485			1
+#define USART3_USART_MODE_HARDWARE		2
+#define USART3_USART_MODE_MODEM			3
+#define USART3_USART_MODE_ISO7816_T0		4
+#define USART3_USART_MODE_ISO7816_T1		6
+#define USART3_USART_MODE_IRDA			8
+
+/* Constants for USCLKS */
+#define USART3_USCLKS_MCK			0
+#define USART3_USCLKS_MCK_DIV			1
+#define USART3_USCLKS_SCK			3
+
+/* Constants for CHRL */
+#define USART3_CHRL_5				0
+#define USART3_CHRL_6				1
+#define USART3_CHRL_7				2
+#define USART3_CHRL_8				3
+
+/* Constants for PAR */
+#define USART3_PAR_EVEN				0
+#define USART3_PAR_ODD				1
+#define USART3_PAR_SPACE			2
+#define USART3_PAR_MARK				3
+#define USART3_PAR_NONE				4
+#define USART3_PAR_MULTI			6
+
+/* Constants for NBSTOP */
+#define USART3_NBSTOP_1				0
+#define USART3_NBSTOP_1_5			1
+#define USART3_NBSTOP_2				2
+
+/* Constants for CHMODE */
+#define USART3_CHMODE_NORMAL			0
+#define USART3_CHMODE_ECHO			1
+#define USART3_CHMODE_LOCAL_LOOP		2
+#define USART3_CHMODE_REMOTE_LOOP		3
+
+/* Constants for MSBF */
+#define USART3_MSBF_LSBF			0
+#define USART3_MSBF_MSBF			1
+
+/* Constants for OVER */
+#define USART3_OVER_X16				0
+#define USART3_OVER_X8				1
+
+/* Constants for CD */
+#define USART3_CD_DISABLE			0
+#define USART3_CD_BYPASS			1
+
+/* Constants for TO */
+#define USART3_TO_DISABLE			0
+
+/* Constants for TG */
+#define USART3_TG_DISABLE			0
+
+/* Constants for FI_DI_RATIO */
+#define USART3_FI_DI_RATIO_DISABLE		0
+
+/* Bit manipulation macros */
+#define USART3_BIT(name)				\
+	(1 << USART3_##name##_OFFSET)
+#define USART3_BF(name,value)				\
+	(((value) & ((1 << USART3_##name##_SIZE) - 1))	\
+	 << USART3_##name##_OFFSET)
+#define USART3_BFEXT(name,value)			\
+	(((value) >> USART3_##name##_OFFSET)		\
+	 & ((1 << USART3_##name##_SIZE) - 1))
+#define USART3_BFINS(name,value,old)			\
+	(((old) & ~(((1 << USART3_##name##_SIZE) - 1)	\
+		    << USART3_##name##_OFFSET))		\
+	 | USART3_BF(name,value))
+
+/* Register access macros */
+#define usart3_readl(reg)				\
+	readl((void *)USART_BASE + USART3_##reg)
+#define usart3_writel(reg,value)			\
+	writel((value), (void *)USART_BASE + USART3_##reg)
+
+#endif /* __DRIVERS_ATMEL_USART_H__ */
diff --git a/drivers/serial/ns16550.c b/drivers/serial/ns16550.c
new file mode 100644
index 0000000..2429464
--- /dev/null
+++ b/drivers/serial/ns16550.c
@@ -0,0 +1,71 @@
+/*
+ * COM1 NS16550 support
+ * originally from linux source (arch/ppc/boot/ns16550.c)
+ * modified to use CFG_ISA_MEM and new defines
+ */
+
+#include <config.h>
+
+#ifdef CFG_NS16550
+
+#include <ns16550.h>
+
+#define LCRVAL LCR_8N1					/* 8 data, 1 stop, no parity */
+#define MCRVAL (MCR_DTR | MCR_RTS)			/* RTS/DTR */
+#define FCRVAL (FCR_FIFO_EN | FCR_RXSR | FCR_TXSR)	/* Clear & enable FIFOs */
+
+void NS16550_init (NS16550_t com_port, int baud_divisor)
+{
+	com_port->ier = 0x00;
+#ifdef CONFIG_OMAP
+	com_port->mdr1 = 0x7;	/* mode select reset TL16C750*/
+#endif
+	com_port->lcr = LCR_BKSE | LCRVAL;
+	com_port->dll = baud_divisor & 0xff;
+	com_port->dlm = (baud_divisor >> 8) & 0xff;
+	com_port->lcr = LCRVAL;
+	com_port->mcr = MCRVAL;
+	com_port->fcr = FCRVAL;
+#if defined(CONFIG_OMAP)
+#if defined(CONFIG_APTIX)
+	com_port->mdr1 = 3;	/* /13 mode so Aptix 6MHz can hit 115200 */
+#else
+	com_port->mdr1 = 0;	/* /16 is proper to hit 115200 with 48MHz */
+#endif
+#endif
+}
+
+void NS16550_reinit (NS16550_t com_port, int baud_divisor)
+{
+	com_port->ier = 0x00;
+	com_port->lcr = LCR_BKSE;
+	com_port->dll = baud_divisor & 0xff;
+	com_port->dlm = (baud_divisor >> 8) & 0xff;
+	com_port->lcr = LCRVAL;
+	com_port->mcr = MCRVAL;
+	com_port->fcr = FCRVAL;
+}
+
+void NS16550_putc (NS16550_t com_port, char c)
+{
+	while ((com_port->lsr & LSR_THRE) == 0);
+	com_port->thr = c;
+}
+
+char NS16550_getc (NS16550_t com_port)
+{
+	while ((com_port->lsr & LSR_DR) == 0) {
+#ifdef CONFIG_USB_TTY
+		extern void usbtty_poll(void);
+		usbtty_poll();
+#endif
+	}
+	return (com_port->rbr);
+}
+
+int NS16550_tstc (NS16550_t com_port)
+{
+	return ((com_port->lsr & LSR_DR) != 0);
+}
+
+#endif
diff --git a/drivers/serial/ns9750_serial.c b/drivers/serial/ns9750_serial.c
new file mode 100644
index 0000000..02c0d39
--- /dev/null
+++ b/drivers/serial/ns9750_serial.c
@@ -0,0 +1,214 @@
+/***********************************************************************
+ *
+ * Copyright (C) 2004 by FS Forth-Systeme GmbH.
+ * All rights reserved.
+ *
+ * $Id: ns9750_serial.c,v 1.1 2004/02/16 10:37:20 mpietrek Exp $
+ * @Author: Markus Pietrek
+ * @Descr: Serial driver for the NS9750. Only one UART is supported yet.
+ * @References: [1] NS9750 Hardware Reference/December 2003
+ * @TODO: Implement Character GAP Timer when chip is fixed for PLL bypass
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ ***********************************************************************/
+
+#include <common.h>
+
+#ifdef CFG_NS9750_UART
+
+#include "ns9750_bbus.h"	/* for GPIOs */
+#include "ns9750_ser.h"		/* for serial configuration */
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#if !defined(CONFIG_CONS_INDEX)
+#error "No console index specified."
+#endif
+
+#define CONSOLE CONFIG_CONS_INDEX
+
+static unsigned int calcBitrateRegister( void );
+static unsigned int calcRxCharGapRegister( void );
+
+static char cCharsAvailable; /* Numbers of chars in unCharCache */
+static unsigned int unCharCache; /* unCharCache is only valid if
+				  * cCharsAvailable > 0 */
+
+/***********************************************************************
+ * @Function: serial_init
+ * @Return: 0
+ * @Descr: configures GPIOs and UART. Requires BBUS Master Reset turned off
+ ***********************************************************************/
+
+int serial_init( void )
+{
+	unsigned int aunGPIOTxD[] = { 0, 8, 40, 44 };
+	unsigned int aunGPIORxD[] = { 1, 9, 41, 45 };
+
+	cCharsAvailable = 0;
+
+	/* configure TxD and RxD pins for their special function */
+	set_gpio_cfg_reg_val( aunGPIOTxD[ CONSOLE ],
+			      NS9750_GPIO_CFG_FUNC_0 | NS9750_GPIO_CFG_OUTPUT );
+	set_gpio_cfg_reg_val( aunGPIORxD[ CONSOLE ],
+			      NS9750_GPIO_CFG_FUNC_0 | NS9750_GPIO_CFG_INPUT );
+
+	/* configure serial engine */
+	*get_ser_reg_addr_channel( NS9750_SER_CTRL_A, CONSOLE ) =
+		NS9750_SER_CTRL_A_CE |
+		NS9750_SER_CTRL_A_STOP |
+		NS9750_SER_CTRL_A_WLS_8;
+
+	serial_setbrg();
+
+	*get_ser_reg_addr_channel( NS9750_SER_CTRL_B, CONSOLE ) =
+		NS9750_SER_CTRL_B_RCGT;
+
+	return 0;
+}
+
+/***********************************************************************
+ * @Function: serial_putc
+ * @Return: n/a
+ * @Descr: writes one character to the FIFO. Blocks until FIFO is not full
+ ***********************************************************************/
+
+void serial_putc( const char c )
+{
+	if (c == '\n')
+		serial_putc( '\r' );
+
+	while (!(*get_ser_reg_addr_channel( NS9750_SER_STAT_A, CONSOLE) &
+		 NS9750_SER_STAT_A_TRDY ) ) {
+		/* do nothing, wait for characters in FIFO sent */
+	}
+
+	*(volatile char*) get_ser_reg_addr_channel( NS9750_SER_FIFO,
+						    CONSOLE) = c;
+}
+
+/***********************************************************************
+ * @Function: serial_puts
+ * @Return: n/a
+ * @Descr: writes non-zero string to the FIFO.
+ ***********************************************************************/
+
+void serial_puts( const char *s )
+{
+	while (*s) {
+		serial_putc( *s++ );
+	}
+}
+
+/***********************************************************************
+ * @Function: serial_getc
+ * @Return: the character read
+ * @Descr: performs only 8bit accesses to the FIFO. No error handling
+ ***********************************************************************/
+
+int serial_getc( void )
+{
+	int i;
+
+	while (!serial_tstc() ) {
+		/* do nothing, wait for incoming characters */
+	}
+
+	/*  at least one character in unCharCache */
+	i = (int) (unCharCache & 0xff);
+
+	unCharCache >>= 8;
+	cCharsAvailable--;
+
+	return i;
+}
+
+/***********************************************************************
+ * @Function: serial_tstc
+ * @Return: 0 if no input available, otherwise != 0
+ * @Descr: checks for incoming FIFO not empty. Stores the incoming chars in
+ *	   unCharCache and the numbers of characters in cCharsAvailable
+ ***********************************************************************/
+
+int serial_tstc( void )
+{
+	unsigned int unRegCache;
+
+	if ( cCharsAvailable )
+		return 1;
+
+	unRegCache = *get_ser_reg_addr_channel( NS9750_SER_STAT_A,CONSOLE );
+	if( unRegCache & NS9750_SER_STAT_A_RBC ) {
+		*get_ser_reg_addr_channel( NS9750_SER_STAT_A, CONSOLE ) =
+			NS9750_SER_STAT_A_RBC;
+		unRegCache = *get_ser_reg_addr_channel( NS9750_SER_STAT_A,
+							CONSOLE );
+	}
+
+	if ( unRegCache & NS9750_SER_STAT_A_RRDY ) {
+		cCharsAvailable = (unRegCache & NS9750_SER_STAT_A_RXFDB_MA)>>20;
+		if ( !cCharsAvailable )
+			cCharsAvailable = 4;
+
+		unCharCache = *get_ser_reg_addr_channel( NS9750_SER_FIFO,
+							 CONSOLE );
+		return 1;
+	}
+
+	/* no chars available */
+	return 0;
+}
+
+void serial_setbrg( void )
+{
+	*get_ser_reg_addr_channel( NS9750_SER_BITRATE, CONSOLE ) =
+		calcBitrateRegister();
+	*get_ser_reg_addr_channel( NS9750_SER_RX_CHAR_TIMER, CONSOLE ) =
+		calcRxCharGapRegister();
+}
+
+/***********************************************************************
+ * @Function: calcBitrateRegister
+ * @Return: value for the serial bitrate register
+ * @Descr: register value depends on clock frequency and baudrate
+ ***********************************************************************/
+
+static unsigned int calcBitrateRegister( void )
+{
+	return ( NS9750_SER_BITRATE_EBIT |
+		 NS9750_SER_BITRATE_CLKMUX_BCLK |
+		 NS9750_SER_BITRATE_TMODE |
+		 NS9750_SER_BITRATE_TCDR_16 |
+		 NS9750_SER_BITRATE_RCDR_16 |
+		 ( ( ( ( CONFIG_SYS_CLK_FREQ / 8 ) / /* BBUS clock,[1] Fig. 38 */
+		       ( gd->baudrate * 16 ) ) - 1 ) &
+		   NS9750_SER_BITRATE_N_MA ) );
+}
+
+/***********************************************************************
+ * @Function: calcRxCharGapRegister
+ * @Return: value for the character gap timer register
+ * @Descr: register value depends on clock frequency and baudrate. Currently 0
+ *	   is used as there is a bug with the gap timer in PLL bypass mode.
+ ***********************************************************************/
+
+static unsigned int calcRxCharGapRegister( void )
+{
+	return NS9750_SER_RX_CHAR_TIMER_TRUN;
+}
+
+#endif /* CFG_NS9750_UART */
diff --git a/drivers/serial/s3c4510b_uart.c b/drivers/serial/s3c4510b_uart.c
new file mode 100644
index 0000000..ddcd591
--- /dev/null
+++ b/drivers/serial/s3c4510b_uart.c
@@ -0,0 +1,216 @@
+/*
+ * Copyright (c) 2004	Cucy Systems (http://www.cucy.com)
+ * Curt Brune <curt@cucy.com>
+ *
+ * (C) Copyright 2004
+ * DAVE Srl
+ * http://www.dave-tech.it
+ * http://www.wawnet.biz
+ * mailto:info@wawnet.biz
+ *
+ * (C) Copyright 2002-2004
+ * Wolfgang Denk, DENX Software Engineering, <wd@denx.de>
+ *
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Marius Groeger <mgroeger@sysgo.de>
+ *
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Alex Zuepke <azu@sysgo.de>
+ *
+ * Copyright (C) 1999 2000 2001 Erik Mouw (J.A.K.Mouw@its.tudelft.nl)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * MODULE:        $Id:$
+ * Description:   UART/Serial interface for Samsung S3C4510B SoC
+ * Runtime Env:   ARM7TDMI
+ * Change History:
+ *     03-02-04    Create (Curt Brune) curt@cucy.com
+ *
+ */
+
+#include <common.h>
+
+#ifdef CONFIG_DRIVER_S3C4510_UART
+
+#include <asm/hardware.h>
+#include "s3c4510b_uart.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static UART    *uart;
+
+/* flush serial input queue. returns 0 on success or negative error
+ * number otherwise
+ */
+static int serial_flush_input(void)
+{
+	volatile u32 tmp;
+
+	/* keep on reading as long as the receiver is not empty */
+	while( uart->m_stat.bf.rxReady) {
+		tmp = uart->m_rx;
+	}
+
+	return 0;
+}
+
+
+/* flush output queue. returns 0 on success or negative error number
+ * otherwise
+ */
+static int serial_flush_output(void)
+{
+	/* wait until the transmitter is no longer busy */
+	while( !uart->m_stat.bf.txBufEmpty);
+
+	return 0;
+}
+
+
+void serial_setbrg (void)
+{
+	UART_LINE_CTRL ulctrl;
+	UART_CTRL      uctrl;
+	UART_BAUD_DIV  ubd;
+
+	serial_flush_output();
+	serial_flush_input();
+
+	/* control register */
+	uctrl.ui = 0x0;
+	uctrl.bf.rxMode = 0x1;
+	uctrl.bf.rxIrq = 0x0;
+	uctrl.bf.txMode = 0x1;
+	uctrl.bf.DSR = 0x0;
+	uctrl.bf.sendBreak = 0x0;
+	uctrl.bf.loopBack = 0x0;
+	uart->m_ctrl.ui = uctrl.ui;
+
+	/* line control register */
+	ulctrl.ui  = 0x0;
+	ulctrl.bf.wordLen   = 0x3; /* 8 bit data */
+	ulctrl.bf.nStop     = 0x0; /* 1 stop bit */
+	ulctrl.bf.parity    = 0x0; /* no parity */
+	ulctrl.bf.clk       = 0x0; /* internal clock */
+	ulctrl.bf.infra_red = 0x0; /* no infra_red */
+	uart->m_lineCtrl.ui = ulctrl.ui;
+
+	ubd.ui = 0x0;
+
+	/* see table on page 10-15 in SAMSUNG S3C4510B manual */
+	/* get correct divisor */
+	switch(gd->baudrate) {
+	case   1200:	ubd.bf.cnt0 = 1301;	break;
+	case   2400:	ubd.bf.cnt0 =  650;	break;
+	case   4800:	ubd.bf.cnt0 =  324;	break;
+	case   9600:	ubd.bf.cnt0 =  162;	break;
+	case  19200:	ubd.bf.cnt0 =   80;	break;
+	case  38400:	ubd.bf.cnt0 =   40;	break;
+	case  57600:	ubd.bf.cnt0 =   26;	break;
+	case 115200:	ubd.bf.cnt0 =   13;	break;
+	}
+
+	uart->m_baudDiv.ui = ubd.ui;
+	uart->m_baudCnt = 0x0;
+	uart->m_baudClk = 0x0;
+
+}
+
+
+/*
+ * Initialise the serial port with the given baudrate. The settings
+ * are always 8 data bits, no parity, 1 stop bit, no start bits.
+ *
+ */
+int serial_init (void)
+{
+
+#if   CONFIG_SERIAL1 == 1
+	uart = (UART *)UART0_BASE;
+#elif CONFIG_SERIAL1 == 2
+	uart = (UART *)UART1_BASE;
+#else
+#error CONFIG_SERIAL1 not equal to 1 or 2
+#endif
+
+	serial_setbrg ();
+
+	return (0);
+}
+
+
+/*
+ * Output a single byte to the serial port.
+ */
+void serial_putc (const char c)
+{
+	/* wait for room in the transmit FIFO */
+	while( !uart->m_stat.bf.txBufEmpty);
+
+	uart->m_tx = c;
+
+	/*
+		to be polite with serial console add a line feed
+		to the carriage return character
+	*/
+	if (c=='\n')
+		serial_putc('\r');
+}
+
+/*
+ * Test if an input byte is ready from the serial port. Returns non-zero on
+ * success, 0 otherwise.
+ */
+int serial_tstc (void)
+{
+	return uart->m_stat.bf.rxReady;
+}
+
+/*
+ * Read a single byte from the serial port. Returns 1 on success, 0
+ * otherwise. When the function is succesfull, the character read is
+ * written into its argument c.
+ */
+int serial_getc (void)
+{
+	int rv;
+
+	for(;;) {
+		rv = serial_tstc();
+
+		if (rv) {
+			return uart->m_rx & 0xFF;
+		}
+	}
+}
+
+void serial_puts (const char *s)
+{
+	while (*s) {
+		serial_putc (*s++);
+	}
+
+	/* busy wait for tx complete */
+	while ( !uart->m_stat.bf.txComplete);
+
+	/* clear break */
+	uart->m_ctrl.bf.sendBreak = 0;
+
+}
+
+#endif
diff --git a/drivers/serial/s3c4510b_uart.h b/drivers/serial/s3c4510b_uart.h
new file mode 100644
index 0000000..b06c76d
--- /dev/null
+++ b/drivers/serial/s3c4510b_uart.h
@@ -0,0 +1,109 @@
+#ifndef __UART_H
+#define __UART_H
+
+/*
+ * Copyright (c) 2004	Cucy Systems (http://www.cucy.com)
+ * Curt Brune <curt@cucy.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Description:   S3C4510B UART register layout
+ */
+
+/* UART LINE CONTROL register */
+typedef struct __BF_UART_LINE_CTRL {
+	u32    wordLen: 2;
+	u32      nStop: 1;
+	u32     parity: 3;
+	u32        clk: 1;
+	u32  infra_red: 1;
+	u32     unused:24;
+} BF_UART_LINE_CTRL;
+
+typedef union _UART_LINE_CTRL {
+	u32               ui;
+	BF_UART_LINE_CTRL bf;
+} UART_LINE_CTRL;
+
+/* UART CONTROL register */
+typedef struct __BF_UART_CTRL {
+	u32     rxMode: 2;
+	u32      rxIrq: 1;
+	u32     txMode: 2;
+	u32        DSR: 1;
+	u32  sendBreak: 1;
+	u32   loopBack: 1;
+	u32     unused:24;
+} BF_UART_CTRL;
+
+typedef union _UART_CTRL {
+	u32            ui;
+	BF_UART_CTRL   bf;
+} UART_CTRL;
+
+/* UART STATUS register */
+typedef struct __BF_UART_STAT {
+	u32      overrun: 1;
+	u32       parity: 1;
+	u32        frame: 1;
+	u32     breakIrq: 1;
+	u32          DTR: 1;
+	u32      rxReady: 1;
+	u32   txBufEmpty: 1;
+	u32   txComplete: 1;
+	u32       unused:24;
+} BF_UART_STAT;
+
+typedef union _UART_STAT {
+	u32            ui;
+	BF_UART_STAT   bf;
+} UART_STAT;
+
+/* UART BAUD_DIV register */
+typedef struct __BF_UART_BAUD_DIV {
+	u32      cnt1: 4;
+	u32      cnt0:12;
+	u32    unused:16;
+} BF_UART_BAUD_DIV;
+
+typedef union _UART_BAUD_DIV {
+	u32                ui;
+	BF_UART_BAUD_DIV   bf;
+} UART_BAUD_DIV;
+
+/* UART register block */
+typedef struct __UART {
+	volatile UART_LINE_CTRL  m_lineCtrl;
+	volatile UART_CTRL           m_ctrl;
+	volatile UART_STAT           m_stat;
+	volatile u32                   m_tx;
+	volatile u32                   m_rx;
+	volatile UART_BAUD_DIV    m_baudDiv;
+	volatile u32              m_baudCnt;
+	volatile u32              m_baudClk;
+} UART;
+
+#define NL          0x0A
+#define CR          0x0D
+#define BSP         0x08
+#define ESC         0x1B
+#define CTRLZ       0x1A
+#define RUBOUT      0x7F
+
+#endif
diff --git a/drivers/serial/serial.c b/drivers/serial/serial.c
new file mode 100644
index 0000000..76425d8
--- /dev/null
+++ b/drivers/serial/serial.c
@@ -0,0 +1,326 @@
+/*
+ * (C) Copyright 2000
+ * Rob Taylor, Flying Pig Systems. robt@flyingpig.com.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+
+#ifdef CFG_NS16550_SERIAL
+
+#include <ns16550.h>
+#ifdef CFG_NS87308
+#include <ns87308.h>
+#endif
+
+#if defined (CONFIG_SERIAL_MULTI)
+#include <serial.h>
+#endif
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#if !defined(CONFIG_CONS_INDEX)
+#if defined (CONFIG_SERIAL_MULTI)
+/*   with CONFIG_SERIAL_MULTI we might have no console
+ *  on these devices
+ */
+#else
+#error	"No console index specified."
+#endif /* CONFIG_SERIAL_MULTI */
+#elif (CONFIG_CONS_INDEX < 1) || (CONFIG_CONS_INDEX > 4)
+#error	"Invalid console index value."
+#endif
+
+#if CONFIG_CONS_INDEX == 1 && !defined(CFG_NS16550_COM1)
+#error	"Console port 1 defined but not configured."
+#elif CONFIG_CONS_INDEX == 2 && !defined(CFG_NS16550_COM2)
+#error	"Console port 2 defined but not configured."
+#elif CONFIG_CONS_INDEX == 3 && !defined(CFG_NS16550_COM3)
+#error	"Console port 3 defined but not configured."
+#elif CONFIG_CONS_INDEX == 4 && !defined(CFG_NS16550_COM4)
+#error	"Console port 4 defined but not configured."
+#endif
+
+/* Note: The port number specified in the functions is 1 based.
+ *	 the array is 0 based.
+ */
+static NS16550_t serial_ports[4] = {
+#ifdef CFG_NS16550_COM1
+	(NS16550_t)CFG_NS16550_COM1,
+#else
+	NULL,
+#endif
+#ifdef CFG_NS16550_COM2
+	(NS16550_t)CFG_NS16550_COM2,
+#else
+	NULL,
+#endif
+#ifdef CFG_NS16550_COM3
+	(NS16550_t)CFG_NS16550_COM3,
+#else
+	NULL,
+#endif
+#ifdef CFG_NS16550_COM4
+	(NS16550_t)CFG_NS16550_COM4
+#else
+	NULL
+#endif
+};
+
+#define PORT	serial_ports[port-1]
+#if defined(CONFIG_CONS_INDEX)
+#define CONSOLE	(serial_ports[CONFIG_CONS_INDEX-1])
+#endif
+
+#if defined(CONFIG_SERIAL_MULTI)
+
+/* Multi serial device functions */
+#define DECLARE_ESERIAL_FUNCTIONS(port) \
+    int  eserial##port##_init (void) {\
+	int clock_divisor; \
+	clock_divisor = calc_divisor(serial_ports[port-1]); \
+	NS16550_init(serial_ports[port-1], clock_divisor); \
+	return(0);}\
+    void eserial##port##_setbrg (void) {\
+	serial_setbrg_dev(port);}\
+    int  eserial##port##_getc (void) {\
+	return serial_getc_dev(port);}\
+    int  eserial##port##_tstc (void) {\
+	return serial_tstc_dev(port);}\
+    void eserial##port##_putc (const char c) {\
+	serial_putc_dev(port, c);}\
+    void eserial##port##_puts (const char *s) {\
+	serial_puts_dev(port, s);}
+
+/* Serial device descriptor */
+#define INIT_ESERIAL_STRUCTURE(port,name,bus) {\
+	name,\
+	bus,\
+	eserial##port##_init,\
+	eserial##port##_setbrg,\
+	eserial##port##_getc,\
+	eserial##port##_tstc,\
+	eserial##port##_putc,\
+	eserial##port##_puts, }
+
+#endif /* CONFIG_SERIAL_MULTI */
+
+static int calc_divisor (NS16550_t port)
+{
+#ifdef CONFIG_OMAP1510
+	/* If can't cleanly clock 115200 set div to 1 */
+	if ((CFG_NS16550_CLK == 12000000) && (gd->baudrate == 115200)) {
+		port->osc_12m_sel = OSC_12M_SEL;	/* enable 6.5 * divisor */
+		return (1);				/* return 1 for base divisor */
+	}
+	port->osc_12m_sel = 0;			/* clear if previsouly set */
+#endif
+#ifdef CONFIG_OMAP1610
+	/* If can't cleanly clock 115200 set div to 1 */
+	if ((CFG_NS16550_CLK == 48000000) && (gd->baudrate == 115200)) {
+		return (26);		/* return 26 for base divisor */
+	}
+#endif
+
+#ifdef CONFIG_APTIX
+#define MODE_X_DIV 13
+#else
+#define MODE_X_DIV 16
+#endif
+	return (CFG_NS16550_CLK / MODE_X_DIV / gd->baudrate);
+
+}
+
+#if !defined(CONFIG_SERIAL_MULTI)
+int serial_init (void)
+{
+	int clock_divisor;
+
+#ifdef CFG_NS87308
+	initialise_ns87308();
+#endif
+
+#ifdef CFG_NS16550_COM1
+	clock_divisor = calc_divisor(serial_ports[0]);
+	NS16550_init(serial_ports[0], clock_divisor);
+#endif
+#ifdef CFG_NS16550_COM2
+	clock_divisor = calc_divisor(serial_ports[1]);
+	NS16550_init(serial_ports[1], clock_divisor);
+#endif
+#ifdef CFG_NS16550_COM3
+	clock_divisor = calc_divisor(serial_ports[2]);
+	NS16550_init(serial_ports[2], clock_divisor);
+#endif
+#ifdef CFG_NS16550_COM4
+	clock_divisor = calc_divisor(serial_ports[3]);
+	NS16550_init(serial_ports[3], clock_divisor);
+#endif
+
+	return (0);
+}
+#endif
+
+void
+_serial_putc(const char c,const int port)
+{
+	if (c == '\n')
+		NS16550_putc(PORT, '\r');
+
+	NS16550_putc(PORT, c);
+}
+
+void
+_serial_putc_raw(const char c,const int port)
+{
+	NS16550_putc(PORT, c);
+}
+
+void
+_serial_puts (const char *s,const int port)
+{
+	while (*s) {
+		_serial_putc (*s++,port);
+	}
+}
+
+
+int
+_serial_getc(const int port)
+{
+	return NS16550_getc(PORT);
+}
+
+int
+_serial_tstc(const int port)
+{
+	return NS16550_tstc(PORT);
+}
+
+void
+_serial_setbrg (const int port)
+{
+	int clock_divisor;
+
+	clock_divisor = calc_divisor(PORT);
+	NS16550_reinit(PORT, clock_divisor);
+}
+
+#if defined(CONFIG_SERIAL_MULTI)
+static inline void
+serial_putc_dev(unsigned int dev_index,const char c)
+{
+	_serial_putc(c,dev_index);
+}
+#else
+void
+serial_putc(const char c)
+{
+	_serial_putc(c,CONFIG_CONS_INDEX);
+}
+#endif
+
+#if defined(CONFIG_SERIAL_MULTI)
+static inline void
+serial_putc_raw_dev(unsigned int dev_index,const char c)
+{
+	_serial_putc_raw(c,dev_index);
+}
+#else
+void
+serial_putc_raw(const char c)
+{
+	_serial_putc_raw(c,CONFIG_CONS_INDEX);
+}
+#endif
+
+#if defined(CONFIG_SERIAL_MULTI)
+static inline void
+serial_puts_dev(unsigned int dev_index,const char *s)
+{
+	_serial_puts(s,dev_index);
+}
+#else
+void
+serial_puts(const char *s)
+{
+	_serial_puts(s,CONFIG_CONS_INDEX);
+}
+#endif
+
+#if defined(CONFIG_SERIAL_MULTI)
+static inline int
+serial_getc_dev(unsigned int dev_index)
+{
+	return _serial_getc(dev_index);
+}
+#else
+int
+serial_getc(void)
+{
+	return _serial_getc(CONFIG_CONS_INDEX);
+}
+#endif
+
+#if defined(CONFIG_SERIAL_MULTI)
+static inline int
+serial_tstc_dev(unsigned int dev_index)
+{
+	return _serial_tstc(dev_index);
+}
+#else
+int
+serial_tstc(void)
+{
+	return _serial_tstc(CONFIG_CONS_INDEX);
+}
+#endif
+
+#if defined(CONFIG_SERIAL_MULTI)
+static inline void
+serial_setbrg_dev(unsigned int dev_index)
+{
+	_serial_setbrg(dev_index);
+}
+#else
+void
+serial_setbrg(void)
+{
+	_serial_setbrg(CONFIG_CONS_INDEX);
+}
+#endif
+
+#if defined(CONFIG_SERIAL_MULTI)
+
+DECLARE_ESERIAL_FUNCTIONS(1);
+struct serial_device eserial1_device =
+	INIT_ESERIAL_STRUCTURE(1,"eserial0","EUART1");
+DECLARE_ESERIAL_FUNCTIONS(2);
+struct serial_device eserial2_device =
+	INIT_ESERIAL_STRUCTURE(2,"eserial1","EUART2");
+DECLARE_ESERIAL_FUNCTIONS(3);
+struct serial_device eserial3_device =
+	INIT_ESERIAL_STRUCTURE(3,"eserial2","EUART3");
+DECLARE_ESERIAL_FUNCTIONS(4);
+struct serial_device eserial4_device =
+	INIT_ESERIAL_STRUCTURE(4,"eserial3","EUART4");
+#endif /* CONFIG_SERIAL_MULTI */
+
+#endif
diff --git a/drivers/serial/serial_max3100.c b/drivers/serial/serial_max3100.c
new file mode 100644
index 0000000..35c5596
--- /dev/null
+++ b/drivers/serial/serial_max3100.c
@@ -0,0 +1,302 @@
+/*
+ * (C) Copyright 2003
+ *
+ * Pantelis Antoniou <panto@intracom.gr>
+ * Intracom S.A.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <watchdog.h>
+
+#ifdef CONFIG_MAX3100_SERIAL
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/**************************************************************/
+
+/* convienient macros */
+#define MAX3100_SPI_RXD() (MAX3100_SPI_RXD_PORT & MAX3100_SPI_RXD_BIT)
+
+#define MAX3100_SPI_TXD(x) \
+	do { \
+		if (x) \
+			MAX3100_SPI_TXD_PORT |=  MAX3100_SPI_TXD_BIT; \
+		else \
+			MAX3100_SPI_TXD_PORT &= ~MAX3100_SPI_TXD_BIT; \
+	} while(0)
+
+#define MAX3100_SPI_CLK(x) \
+	do { \
+		if (x) \
+			MAX3100_SPI_CLK_PORT |=  MAX3100_SPI_CLK_BIT; \
+		else \
+			MAX3100_SPI_CLK_PORT &= ~MAX3100_SPI_CLK_BIT; \
+	} while(0)
+
+#define MAX3100_SPI_CLK_TOGGLE() (MAX3100_SPI_CLK_PORT ^= MAX3100_SPI_CLK_BIT)
+
+#define MAX3100_CS(x) \
+	do { \
+		if (x) \
+			MAX3100_CS_PORT |=  MAX3100_CS_BIT; \
+		else \
+			MAX3100_CS_PORT &= ~MAX3100_CS_BIT; \
+	} while(0)
+
+/**************************************************************/
+
+/* MAX3100 definitions */
+
+#define MAX3100_WC	(3 << 14)		/* write configuration */
+#define MAX3100_RC	(1 << 14)		/* read  configuration */
+#define MAX3100_WD	(2 << 14)		/* write data          */
+#define MAX3100_RD	(0 << 14)		/* read  data          */
+
+/* configuration register bits */
+#define MAX3100_FEN	(1 << 13)		/* FIFO enable           */
+#define MAX3100_SHDN    (1 << 12)		/* shutdown bit          */
+#define MAX3100_TM	(1 << 11)		/* T bit irq mask        */
+#define MAX3100_RM	(1 << 10)		/* R bit irq mask        */
+#define MAX3100_PM	(1 <<  9)		/* P bit irq mask        */
+#define MAX3100_RAM	(1 <<  8)		/* mask for RA/FE bit    */
+#define MAX3100_IR	(1 <<  7)		/* IRDA timing mode      */
+#define MAX3100_ST	(1 <<  6)		/* transmit stop bit     */
+#define MAX3100_PE	(1 <<  5)		/* parity enable bit     */
+#define MAX3100_L	(1 <<  4)		/* Length bit            */
+#define MAX3100_B_MASK	(0x000F)		/* baud rate bits mask   */
+#define MAX3100_B(x)	((x) & 0x000F)	/* baud rate select bits */
+
+/* data register bits (write) */
+#define MAX3100_TE	(1 << 10)		/* transmit enable bit (active low)        */
+#define MAX3100_RTS	(1 <<  9)		/* request-to-send bit (inverted ~RTS pin) */
+
+/* data register bits (read) */
+#define MAX3100_RA	(1 << 10)		/* receiver activity when in shutdown mode */
+#define MAX3100_FE	(1 << 10)		/* framing error when in normal mode       */
+#define MAX3100_CTS	(1 <<  9)		/* clear-to-send bit (inverted ~CTS pin)   */
+
+/* data register bits (both directions) */
+#define MAX3100_R 	(1 << 15)		/* receive bit    */
+#define MAX3100_T	(1 << 14)		/* transmit bit   */
+#define MAX3100_P	(1 <<  8)		/* parity bit     */
+#define MAX3100_D_MASK	0x00FF                  /* data bits mask */
+#define MAX3100_D(x)	((x) & 0x00FF)		/* data bits      */
+
+/* these definitions are valid only for fOSC = 3.6864MHz */
+#define MAX3100_B_230400        MAX3100_B(0)
+#define MAX3100_B_115200        MAX3100_B(1)
+#define MAX3100_B_57600         MAX3100_B(2)
+#define MAX3100_B_38400         MAX3100_B(9)
+#define MAX3100_B_19200         MAX3100_B(10)
+#define MAX3100_B_9600          MAX3100_B(11)
+#define MAX3100_B_4800          MAX3100_B(12)
+#define MAX3100_B_2400          MAX3100_B(13)
+#define MAX3100_B_1200          MAX3100_B(14)
+#define MAX3100_B_600           MAX3100_B(15)
+
+/**************************************************************/
+
+static inline unsigned int max3100_transfer(unsigned int val)
+{
+	unsigned int rx;
+	int b;
+
+	MAX3100_SPI_CLK(0);
+	MAX3100_CS(0);
+
+	rx = 0; b = 16;
+	while (--b >= 0) {
+		MAX3100_SPI_TXD(val & 0x8000);
+		val <<= 1;
+		MAX3100_SPI_CLK_TOGGLE();
+		udelay(1);
+		rx <<= 1;
+		if (MAX3100_SPI_RXD())
+			rx |= 1;
+		MAX3100_SPI_CLK_TOGGLE();
+		udelay(1);
+	}
+
+	MAX3100_SPI_CLK(1);
+	MAX3100_CS(1);
+
+	return rx;
+}
+
+/**************************************************************/
+
+/* must be power of 2 */
+#define RXFIFO_SZ	16
+
+static int rxfifo_cnt;
+static int rxfifo_in;
+static int rxfifo_out;
+static unsigned char rxfifo_buf[16];
+
+static void max3100_putc(int c)
+{
+	unsigned int rx;
+
+	while (((rx = max3100_transfer(MAX3100_RC)) & MAX3100_T) == 0)
+		WATCHDOG_RESET();
+
+	rx = max3100_transfer(MAX3100_WD | (c & 0xff));
+	if ((rx & MAX3100_RD) != 0 && rxfifo_cnt < RXFIFO_SZ) {
+		rxfifo_cnt++;
+		rxfifo_buf[rxfifo_in++] = rx & 0xff;
+		rxfifo_in &= RXFIFO_SZ - 1;
+	}
+}
+
+static int max3100_getc(void)
+{
+	int c;
+	unsigned int rx;
+
+	while (rxfifo_cnt == 0) {
+		rx = max3100_transfer(MAX3100_RD);
+		if ((rx & MAX3100_R) != 0) {
+			do {
+				rxfifo_cnt++;
+				rxfifo_buf[rxfifo_in++] = rx & 0xff;
+				rxfifo_in &= RXFIFO_SZ - 1;
+
+				if (rxfifo_cnt >= RXFIFO_SZ)
+					break;
+			} while (((rx = max3100_transfer(MAX3100_RD)) & MAX3100_R) != 0);
+		}
+		WATCHDOG_RESET();
+	}
+
+	rxfifo_cnt--;
+	c = rxfifo_buf[rxfifo_out++];
+	rxfifo_out &= RXFIFO_SZ - 1;
+	return c;
+}
+
+static int max3100_tstc(void)
+{
+	unsigned int rx;
+
+	if (rxfifo_cnt > 0)
+		return 1;
+
+	rx = max3100_transfer(MAX3100_RD);
+	if ((rx & MAX3100_R) == 0)
+		return 0;
+
+	do {
+		rxfifo_cnt++;
+		rxfifo_buf[rxfifo_in++] = rx & 0xff;
+		rxfifo_in &= RXFIFO_SZ - 1;
+
+		if (rxfifo_cnt >= RXFIFO_SZ)
+			break;
+	} while (((rx = max3100_transfer(MAX3100_RD)) & MAX3100_R) != 0);
+
+	return 1;
+}
+
+int serial_init(void)
+{
+	unsigned int wconf, rconf;
+	int i;
+
+	wconf = 0;
+
+	/* Set baud rate */
+	switch (gd->baudrate) {
+		case 1200:
+			wconf = MAX3100_B_1200;
+			break;
+		case 2400:
+			wconf = MAX3100_B_2400;
+			break;
+		case 4800:
+			wconf = MAX3100_B_4800;
+			break;
+		case 9600:
+			wconf = MAX3100_B_9600;
+			break;
+		case 19200:
+			wconf = MAX3100_B_19200;
+			break;
+		case 38400:
+			wconf = MAX3100_B_38400;
+			break;
+		case 57600:
+			wconf = MAX3100_B_57600;
+			break;
+		default:
+		case 115200:
+			wconf = MAX3100_B_115200;
+			break;
+		case 230400:
+			wconf = MAX3100_B_230400;
+			break;
+	}
+
+	/* try for 10ms, with a 100us gap */
+	for (i = 0; i < 10000; i += 100) {
+
+		max3100_transfer(MAX3100_WC | wconf);
+		rconf = max3100_transfer(MAX3100_RC) & 0x3fff;
+
+		if (rconf == wconf)
+			break;
+		udelay(100);
+	}
+
+	rxfifo_in = rxfifo_out = rxfifo_cnt = 0;
+
+	return (0);
+}
+
+void serial_putc(const char c)
+{
+	if (c == '\n')
+		max3100_putc('\r');
+
+	max3100_putc(c);
+}
+
+void serial_puts(const char *s)
+{
+	while (*s)
+		serial_putc (*s++);
+}
+
+int serial_getc(void)
+{
+	return max3100_getc();
+}
+
+int serial_tstc(void)
+{
+	return max3100_tstc();
+}
+
+/* XXX WTF? */
+void serial_setbrg(void)
+{
+}
+
+#endif
diff --git a/drivers/serial/serial_xuartlite.c b/drivers/serial/serial_xuartlite.c
new file mode 100644
index 0000000..d678ab6
--- /dev/null
+++ b/drivers/serial/serial_xuartlite.c
@@ -0,0 +1,76 @@
+/*
+ * (C) Copyright 2004 Atmark Techno, Inc.
+ *
+ * Yasushi SHOJI <yashi@atmark-techno.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <config.h>
+
+#ifdef	CONFIG_XILINX_UARTLITE
+
+#include <asm/serial_xuartlite.h>
+
+/* FIXME: we should convert these to in32 and out32 */
+#define IO_WORD(offset)	     (*(volatile unsigned long *)(offset))
+#define IO_SERIAL(offset)    IO_WORD(CONFIG_SERIAL_BASE + (offset))
+
+#define IO_SERIAL_RX_FIFO   IO_SERIAL(XUL_RX_FIFO_OFFSET)
+#define IO_SERIAL_TX_FIFO   IO_SERIAL(XUL_TX_FIFO_OFFSET)
+#define IO_SERIAL_STATUS    IO_SERIAL(XUL_STATUS_REG_OFFSET)
+#define IO_SERIAL_CONTROL   IO_SERIAL(XUL_CONTROL_REG_OFFSET)
+
+int serial_init(void)
+{
+	/* FIXME: Nothing for now. We should initialize fifo, etc */
+	return 0;
+}
+
+void serial_setbrg(void)
+{
+	/* FIXME: what's this for? */
+}
+
+void serial_putc(const char c)
+{
+	if (c == '\n') serial_putc('\r');
+	while (IO_SERIAL_STATUS & XUL_SR_TX_FIFO_FULL);
+	IO_SERIAL_TX_FIFO = (unsigned char) (c & 0xff);
+}
+
+void serial_puts(const char * s)
+{
+	while (*s) {
+		serial_putc(*s++);
+	}
+}
+
+int serial_getc(void)
+{
+	while (!(IO_SERIAL_STATUS & XUL_SR_RX_FIFO_VALID_DATA));
+	return IO_SERIAL_RX_FIFO & 0xff;
+}
+
+int serial_tstc(void)
+{
+	return (IO_SERIAL_STATUS & XUL_SR_RX_FIFO_VALID_DATA);
+}
+
+#endif	/* CONFIG_MICROBLZE */
diff --git a/drivers/serial/usbtty.c b/drivers/serial/usbtty.c
new file mode 100644
index 0000000..a3b5013
--- /dev/null
+++ b/drivers/serial/usbtty.c
@@ -0,0 +1,1012 @@
+/*
+ * (C) Copyright 2003
+ * Gerry Hamel, geh@ti.com, Texas Instruments
+ *
+ * (C) Copyright 2006
+ * Bryan O'Donoghue, bodonoghue@codehermit.ie
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307	 USA
+ *
+ */
+
+#include <common.h>
+
+#ifdef CONFIG_USB_TTY
+
+#include <circbuf.h>
+#include <devices.h>
+#include "usbtty.h"
+#include "usb_cdc_acm.h"
+#include "usbdescriptors.h"
+#include <config.h>		/* If defined, override Linux identifiers with
+			   	 * vendor specific ones */
+
+#if 0
+#define TTYDBG(fmt,args...)\
+	serial_printf("[%s] %s %d: "fmt, __FILE__,__FUNCTION__,__LINE__,##args)
+#else
+#define TTYDBG(fmt,args...) do{}while(0)
+#endif
+
+#if 1
+#define TTYERR(fmt,args...)\
+	serial_printf("ERROR![%s] %s %d: "fmt, __FILE__,__FUNCTION__,\
+	__LINE__,##args)
+#else
+#define TTYERR(fmt,args...) do{}while(0)
+#endif
+
+/*
+ * Defines
+ */
+#define NUM_CONFIGS    1
+#define MAX_INTERFACES 2
+#define NUM_ENDPOINTS  3
+#define ACM_TX_ENDPOINT 3
+#define ACM_RX_ENDPOINT 2
+#define GSERIAL_TX_ENDPOINT 2
+#define GSERIAL_RX_ENDPOINT 1
+#define NUM_ACM_INTERFACES 2
+#define NUM_GSERIAL_INTERFACES 1
+#define CONFIG_USBD_DATA_INTERFACE_STR "Bulk Data Interface"
+#define CONFIG_USBD_CTRL_INTERFACE_STR "Control Interface"
+
+/*
+ * Buffers to hold input and output data
+ */
+#define USBTTY_BUFFER_SIZE 256
+static circbuf_t usbtty_input;
+static circbuf_t usbtty_output;
+
+
+/*
+ * Instance variables
+ */
+static device_t usbttydev;
+static struct usb_device_instance device_instance[1];
+static struct usb_bus_instance bus_instance[1];
+static struct usb_configuration_instance config_instance[NUM_CONFIGS];
+static struct usb_interface_instance interface_instance[MAX_INTERFACES];
+static struct usb_alternate_instance alternate_instance[MAX_INTERFACES];
+/* one extra for control endpoint */
+static struct usb_endpoint_instance endpoint_instance[NUM_ENDPOINTS+1];
+
+/*
+ * Global flag
+ */
+int usbtty_configured_flag = 0;
+
+/*
+ * Serial number
+ */
+static char serial_number[16];
+
+
+/*
+ * Descriptors, Strings, Local variables.
+ */
+
+/* defined and used by usbdcore_ep0.c */
+extern struct usb_string_descriptor **usb_strings;
+
+/* Indicies, References */
+static unsigned short rx_endpoint = 0;
+static unsigned short tx_endpoint = 0;
+static unsigned short interface_count = 0;
+static struct usb_string_descriptor *usbtty_string_table[STR_COUNT];
+
+/* USB Descriptor Strings */
+static u8 wstrLang[4] = {4,USB_DT_STRING,0x9,0x4};
+static u8 wstrManufacturer[2 + 2*(sizeof(CONFIG_USBD_MANUFACTURER)-1)];
+static u8 wstrProduct[2 + 2*(sizeof(CONFIG_USBD_PRODUCT_NAME)-1)];
+static u8 wstrSerial[2 + 2*(sizeof(serial_number) - 1)];
+static u8 wstrConfiguration[2 + 2*(sizeof(CONFIG_USBD_CONFIGURATION_STR)-1)];
+static u8 wstrDataInterface[2 + 2*(sizeof(CONFIG_USBD_DATA_INTERFACE_STR)-1)];
+static u8 wstrCtrlInterface[2 + 2*(sizeof(CONFIG_USBD_DATA_INTERFACE_STR)-1)];
+
+/* Standard USB Data Structures */
+static struct usb_interface_descriptor interface_descriptors[MAX_INTERFACES];
+static struct usb_endpoint_descriptor *ep_descriptor_ptrs[NUM_ENDPOINTS];
+static struct usb_configuration_descriptor	*configuration_descriptor = 0;
+static struct usb_device_descriptor device_descriptor = {
+	.bLength = sizeof(struct usb_device_descriptor),
+	.bDescriptorType =	USB_DT_DEVICE,
+	.bcdUSB = 		cpu_to_le16(USB_BCD_VERSION),
+	.bDeviceSubClass =	0x00,
+	.bDeviceProtocol =	0x00,
+	.bMaxPacketSize0 =	EP0_MAX_PACKET_SIZE,
+	.idVendor =		cpu_to_le16(CONFIG_USBD_VENDORID),
+	.bcdDevice =		cpu_to_le16(USBTTY_BCD_DEVICE),
+	.iManufacturer =	STR_MANUFACTURER,
+	.iProduct =		STR_PRODUCT,
+	.iSerialNumber =	STR_SERIAL,
+	.bNumConfigurations =	NUM_CONFIGS
+};
+
+
+/*
+ * Static CDC ACM specific descriptors
+ */
+
+struct acm_config_desc {
+	struct usb_configuration_descriptor configuration_desc;
+
+	/* Master Interface */
+	struct usb_interface_descriptor interface_desc;
+
+	struct usb_class_header_function_descriptor usb_class_header;
+	struct usb_class_call_management_descriptor usb_class_call_mgt;
+	struct usb_class_abstract_control_descriptor usb_class_acm;
+	struct usb_class_union_function_descriptor usb_class_union;
+	struct usb_endpoint_descriptor notification_endpoint;
+
+	/* Slave Interface */
+	struct usb_interface_descriptor data_class_interface;
+	struct usb_endpoint_descriptor
+		data_endpoints[NUM_ENDPOINTS-1] __attribute__((packed));
+} __attribute__((packed));
+
+static struct acm_config_desc acm_configuration_descriptors[NUM_CONFIGS] = {
+	{
+		.configuration_desc ={
+			.bLength =
+				sizeof(struct usb_configuration_descriptor),
+    			.bDescriptorType = USB_DT_CONFIG,
+			.wTotalLength =
+				cpu_to_le16(sizeof(struct acm_config_desc)),
+	    		.bNumInterfaces = NUM_ACM_INTERFACES,
+    			.bConfigurationValue = 1,
+			.iConfiguration = STR_CONFIG,
+			.bmAttributes =
+				BMATTRIBUTE_SELF_POWERED|BMATTRIBUTE_RESERVED,
+			.bMaxPower = USBTTY_MAXPOWER
+		},
+		/* Interface 1 */
+		.interface_desc = {
+			.bLength  = sizeof(struct usb_interface_descriptor),
+			.bDescriptorType = USB_DT_INTERFACE,
+			.bInterfaceNumber = 0,
+			.bAlternateSetting = 0,
+			.bNumEndpoints = 0x01,
+			.bInterfaceClass =
+				COMMUNICATIONS_INTERFACE_CLASS_CONTROL,
+			.bInterfaceSubClass = COMMUNICATIONS_ACM_SUBCLASS,
+			.bInterfaceProtocol = COMMUNICATIONS_V25TER_PROTOCOL,
+			.iInterface = STR_CTRL_INTERFACE,
+		},
+		.usb_class_header = {
+			.bFunctionLength	=
+				sizeof(struct usb_class_header_function_descriptor),
+			.bDescriptorType	= CS_INTERFACE,
+			.bDescriptorSubtype	= USB_ST_HEADER,
+			.bcdCDC	= cpu_to_le16(110),
+		},
+		.usb_class_call_mgt = {
+			.bFunctionLength	=
+				sizeof(struct usb_class_call_management_descriptor),
+			.bDescriptorType	= CS_INTERFACE,
+			.bDescriptorSubtype	= USB_ST_CMF,
+			.bmCapabilities		= 0x00,
+			.bDataInterface		= 0x01,
+		},
+		.usb_class_acm = {
+			.bFunctionLength	=
+				sizeof(struct usb_class_abstract_control_descriptor),
+			.bDescriptorType	= CS_INTERFACE,
+			.bDescriptorSubtype	= USB_ST_ACMF,
+			.bmCapabilities		= 0x00,
+		},
+		.usb_class_union = {
+			.bFunctionLength	=
+				sizeof(struct usb_class_union_function_descriptor),
+			.bDescriptorType	= CS_INTERFACE,
+			.bDescriptorSubtype	= USB_ST_UF,
+			.bMasterInterface	= 0x00,
+			.bSlaveInterface0	= 0x01,
+		},
+		.notification_endpoint = {
+			.bLength =
+				sizeof(struct usb_endpoint_descriptor),
+			.bDescriptorType	= USB_DT_ENDPOINT,
+			.bEndpointAddress	= 0x01 | USB_DIR_IN,
+			.bmAttributes		= USB_ENDPOINT_XFER_INT,
+			.wMaxPacketSize
+				= cpu_to_le16(CONFIG_USBD_SERIAL_INT_PKTSIZE),
+			.bInterval		= 0xFF,
+		},
+
+		/* Interface 2 */
+		.data_class_interface = {
+			.bLength		=
+				sizeof(struct usb_interface_descriptor),
+			.bDescriptorType	= USB_DT_INTERFACE,
+			.bInterfaceNumber	= 0x01,
+			.bAlternateSetting	= 0x00,
+			.bNumEndpoints		= 0x02,
+			.bInterfaceClass	=
+				COMMUNICATIONS_INTERFACE_CLASS_DATA,
+			.bInterfaceSubClass	= DATA_INTERFACE_SUBCLASS_NONE,
+			.bInterfaceProtocol	= DATA_INTERFACE_PROTOCOL_NONE,
+			.iInterface		= STR_DATA_INTERFACE,
+		},
+		.data_endpoints = {
+			{
+				.bLength		=
+					sizeof(struct usb_endpoint_descriptor),
+				.bDescriptorType	= USB_DT_ENDPOINT,
+				.bEndpointAddress	= 0x02 | USB_DIR_OUT,
+				.bmAttributes		=
+					USB_ENDPOINT_XFER_BULK,
+				.wMaxPacketSize		=
+					cpu_to_le16(CONFIG_USBD_SERIAL_BULK_PKTSIZE),
+				.bInterval		= 0xFF,
+			},
+			{
+				.bLength		=
+					sizeof(struct usb_endpoint_descriptor),
+				.bDescriptorType	= USB_DT_ENDPOINT,
+				.bEndpointAddress	= 0x03 | USB_DIR_IN,
+				.bmAttributes		=
+					USB_ENDPOINT_XFER_BULK,
+				.wMaxPacketSize		=
+					cpu_to_le16(CONFIG_USBD_SERIAL_BULK_PKTSIZE),
+				.bInterval		= 0xFF,
+			},
+		},
+	},
+};
+
+static struct rs232_emu rs232_desc={
+		.dter 		=  	115200,
+	   	.stop_bits	=	0x00,
+	   	.parity		=	0x00,
+		.data_bits	=	0x08
+};
+
+
+/*
+ * Static Generic Serial specific data
+ */
+
+
+struct gserial_config_desc {
+
+	struct usb_configuration_descriptor configuration_desc;
+	struct usb_interface_descriptor
+		interface_desc[NUM_GSERIAL_INTERFACES] __attribute__((packed));
+	struct usb_endpoint_descriptor
+		data_endpoints[NUM_ENDPOINTS] __attribute__((packed));
+
+} __attribute__((packed));
+
+static struct gserial_config_desc
+gserial_configuration_descriptors[NUM_CONFIGS] ={
+	{
+		.configuration_desc ={
+			.bLength = sizeof(struct usb_configuration_descriptor),
+			.bDescriptorType = USB_DT_CONFIG,
+			.wTotalLength =
+				cpu_to_le16(sizeof(struct gserial_config_desc)),
+			.bNumInterfaces = NUM_GSERIAL_INTERFACES,
+			.bConfigurationValue = 1,
+			.iConfiguration = STR_CONFIG,
+			.bmAttributes =
+				BMATTRIBUTE_SELF_POWERED|BMATTRIBUTE_RESERVED,
+			.bMaxPower = USBTTY_MAXPOWER
+		},
+		.interface_desc = {
+			{
+				.bLength  =
+					sizeof(struct usb_interface_descriptor),
+				.bDescriptorType = USB_DT_INTERFACE,
+				.bInterfaceNumber = 0,
+				.bAlternateSetting = 0,
+				.bNumEndpoints = NUM_ENDPOINTS,
+				.bInterfaceClass =
+					COMMUNICATIONS_INTERFACE_CLASS_VENDOR,
+				.bInterfaceSubClass =
+					COMMUNICATIONS_NO_SUBCLASS,
+				.bInterfaceProtocol =
+					COMMUNICATIONS_NO_PROTOCOL,
+				.iInterface = STR_DATA_INTERFACE
+			},
+  		},
+		.data_endpoints  = {
+			{
+				.bLength =
+					sizeof(struct usb_endpoint_descriptor),
+				.bDescriptorType =	USB_DT_ENDPOINT,
+				.bEndpointAddress =	0x01 | USB_DIR_OUT,
+				.bmAttributes =		USB_ENDPOINT_XFER_BULK,
+				.wMaxPacketSize =
+					cpu_to_le16(CONFIG_USBD_SERIAL_OUT_PKTSIZE),
+				.bInterval=		0xFF,
+			},
+			{
+				.bLength =
+					sizeof(struct usb_endpoint_descriptor),
+				.bDescriptorType =	USB_DT_ENDPOINT,
+				.bEndpointAddress =	0x02 | USB_DIR_IN,
+				.bmAttributes =		USB_ENDPOINT_XFER_BULK,
+				.wMaxPacketSize =
+					cpu_to_le16(CONFIG_USBD_SERIAL_IN_PKTSIZE),
+				.bInterval = 		0xFF,
+			},
+			{
+				.bLength =
+					sizeof(struct usb_endpoint_descriptor),
+				.bDescriptorType =	USB_DT_ENDPOINT,
+				.bEndpointAddress =	0x03 | USB_DIR_IN,
+				.bmAttributes =		USB_ENDPOINT_XFER_INT,
+    				.wMaxPacketSize =
+					cpu_to_le16(CONFIG_USBD_SERIAL_INT_PKTSIZE),
+				.bInterval =		0xFF,
+			},
+		},
+	},
+};
+
+/*
+ * Static Function Prototypes
+ */
+
+static void usbtty_init_strings (void);
+static void usbtty_init_instances (void);
+static void usbtty_init_endpoints (void);
+static void usbtty_init_terminal_type(short type);
+static void usbtty_event_handler (struct usb_device_instance *device,
+				usb_device_event_t event, int data);
+static int usbtty_cdc_setup(struct usb_device_request *request,
+				struct urb *urb);
+static int usbtty_configured (void);
+static int write_buffer (circbuf_t * buf);
+static int fill_buffer (circbuf_t * buf);
+
+void usbtty_poll (void);
+
+/* utility function for converting char* to wide string used by USB */
+static void str2wide (char *str, u16 * wide)
+{
+	int i;
+	for (i = 0; i < strlen (str) && str[i]; i++){
+		#if defined(__LITTLE_ENDIAN)
+			wide[i] = (u16) str[i];
+		#elif defined(__BIG_ENDIAN)
+			wide[i] = ((u16)(str[i])<<8);
+		#else
+			#error "__LITTLE_ENDIAN or __BIG_ENDIAN undefined"
+		#endif
+	}
+}
+
+/*
+ * Test whether a character is in the RX buffer
+ */
+
+int usbtty_tstc (void)
+{
+	struct usb_endpoint_instance *endpoint =
+		&endpoint_instance[rx_endpoint];
+
+	/* If no input data exists, allow more RX to be accepted */
+	if(usbtty_input.size <= 0){
+		udc_unset_nak(endpoint->endpoint_address&0x03);
+	}
+
+	usbtty_poll ();
+	return (usbtty_input.size > 0);
+}
+
+/*
+ * Read a single byte from the usb client port. Returns 1 on success, 0
+ * otherwise. When the function is succesfull, the character read is
+ * written into its argument c.
+ */
+
+int usbtty_getc (void)
+{
+	char c;
+	struct usb_endpoint_instance *endpoint =
+		&endpoint_instance[rx_endpoint];
+
+	while (usbtty_input.size <= 0) {
+		udc_unset_nak(endpoint->endpoint_address&0x03);
+		usbtty_poll ();
+	}
+
+	buf_pop (&usbtty_input, &c, 1);
+	udc_set_nak(endpoint->endpoint_address&0x03);
+
+	return c;
+}
+
+/*
+ * Output a single byte to the usb client port.
+ */
+void usbtty_putc (const char c)
+{
+	buf_push (&usbtty_output, &c, 1);
+	/* If \n, also do \r */
+	if (c == '\n')
+		buf_push (&usbtty_output, "\r", 1);
+
+	/* Poll at end to handle new data... */
+	if ((usbtty_output.size + 2) >= usbtty_output.totalsize) {
+		usbtty_poll ();
+	}
+}
+
+/* usbtty_puts() helper function for finding the next '\n' in a string */
+static int next_nl_pos (const char *s)
+{
+	int i;
+
+	for (i = 0; s[i] != '\0'; i++) {
+		if (s[i] == '\n')
+			return i;
+	}
+	return i;
+}
+
+/*
+ * Output a string to the usb client port - implementing flow control
+ */
+
+static void __usbtty_puts (const char *str, int len)
+{
+	int maxlen = usbtty_output.totalsize;
+	int space, n;
+
+	/* break str into chunks < buffer size, if needed */
+	while (len > 0) {
+		usbtty_poll ();
+
+		space = maxlen - usbtty_output.size;
+		/* Empty buffer here, if needed, to ensure space... */
+		if (space) {
+			write_buffer (&usbtty_output);
+
+			n = MIN (space, MIN (len, maxlen));
+			buf_push (&usbtty_output, str, n);
+
+			str += n;
+			len -= n;
+		}
+	}
+}
+
+void usbtty_puts (const char *str)
+{
+	int n;
+	int len = strlen (str);
+
+	/* add '\r' for each '\n' */
+	while (len > 0) {
+		n = next_nl_pos (str);
+
+		if (str[n] == '\n') {
+			__usbtty_puts (str, n + 1);
+			__usbtty_puts ("\r", 1);
+			str += (n + 1);
+			len -= (n + 1);
+		} else {
+			/* No \n found.	 All done. */
+			__usbtty_puts (str, n);
+			break;
+		}
+	}
+
+	/* Poll at end to handle new data... */
+	usbtty_poll ();
+}
+
+/*
+ * Initialize the usb client port.
+ *
+ */
+int drv_usbtty_init (void)
+{
+	int rc;
+	char * sn;
+	char * tt;
+	int snlen;
+
+	/* Ger seiral number */
+	if (!(sn = getenv("serial#"))) {
+		sn = "000000000000";
+	}
+	snlen = strlen(sn);
+	if (snlen > sizeof(serial_number) - 1) {
+		printf ("Warning: serial number %s is too long (%d > %d)\n",
+			sn, snlen, sizeof(serial_number) - 1);
+		snlen = sizeof(serial_number) - 1;
+	}
+	memcpy (serial_number, sn, snlen);
+	serial_number[snlen] = '\0';
+
+	/* Decide on which type of UDC device to be.
+	 */
+
+	if(!(tt = getenv("usbtty"))) {
+		tt = "generic";
+	}
+	usbtty_init_terminal_type(strcmp(tt,"cdc_acm"));
+
+	/* prepare buffers... */
+	buf_init (&usbtty_input, USBTTY_BUFFER_SIZE);
+	buf_init (&usbtty_output, USBTTY_BUFFER_SIZE);
+
+	/* Now, set up USB controller and infrastructure */
+	udc_init ();		/* Basic USB initialization */
+
+	usbtty_init_strings ();
+	usbtty_init_instances ();
+
+	udc_startup_events (device_instance);/* Enable dev, init udc pointers */
+	udc_connect ();		/* Enable pullup for host detection */
+
+	usbtty_init_endpoints ();
+
+	/* Device initialization */
+	memset (&usbttydev, 0, sizeof (usbttydev));
+
+	strcpy (usbttydev.name, "usbtty");
+	usbttydev.ext = 0;	/* No extensions */
+	usbttydev.flags = DEV_FLAGS_INPUT | DEV_FLAGS_OUTPUT;
+	usbttydev.tstc = usbtty_tstc;	/* 'tstc' function */
+	usbttydev.getc = usbtty_getc;	/* 'getc' function */
+	usbttydev.putc = usbtty_putc;	/* 'putc' function */
+	usbttydev.puts = usbtty_puts;	/* 'puts' function */
+
+	rc = device_register (&usbttydev);
+
+	return (rc == 0) ? 1 : rc;
+}
+
+static void usbtty_init_strings (void)
+{
+	struct usb_string_descriptor *string;
+
+	usbtty_string_table[STR_LANG] =
+		(struct usb_string_descriptor*)wstrLang;
+
+	string = (struct usb_string_descriptor *) wstrManufacturer;
+	string->bLength = sizeof(wstrManufacturer);
+	string->bDescriptorType = USB_DT_STRING;
+	str2wide (CONFIG_USBD_MANUFACTURER, string->wData);
+	usbtty_string_table[STR_MANUFACTURER]=string;
+
+
+	string = (struct usb_string_descriptor *) wstrProduct;
+	string->bLength = sizeof(wstrProduct);
+	string->bDescriptorType = USB_DT_STRING;
+	str2wide (CONFIG_USBD_PRODUCT_NAME, string->wData);
+	usbtty_string_table[STR_PRODUCT]=string;
+
+
+	string = (struct usb_string_descriptor *) wstrSerial;
+	string->bLength = sizeof(serial_number);
+	string->bDescriptorType = USB_DT_STRING;
+	str2wide (serial_number, string->wData);
+	usbtty_string_table[STR_SERIAL]=string;
+
+
+	string = (struct usb_string_descriptor *) wstrConfiguration;
+	string->bLength = sizeof(wstrConfiguration);
+	string->bDescriptorType = USB_DT_STRING;
+	str2wide (CONFIG_USBD_CONFIGURATION_STR, string->wData);
+	usbtty_string_table[STR_CONFIG]=string;
+
+
+	string = (struct usb_string_descriptor *) wstrDataInterface;
+	string->bLength = sizeof(wstrDataInterface);
+	string->bDescriptorType = USB_DT_STRING;
+	str2wide (CONFIG_USBD_DATA_INTERFACE_STR, string->wData);
+	usbtty_string_table[STR_DATA_INTERFACE]=string;
+
+	string = (struct usb_string_descriptor *) wstrCtrlInterface;
+	string->bLength = sizeof(wstrCtrlInterface);
+	string->bDescriptorType = USB_DT_STRING;
+	str2wide (CONFIG_USBD_CTRL_INTERFACE_STR, string->wData);
+	usbtty_string_table[STR_CTRL_INTERFACE]=string;
+
+	/* Now, initialize the string table for ep0 handling */
+	usb_strings = usbtty_string_table;
+}
+
+static void usbtty_init_instances (void)
+{
+	int i;
+
+	/* initialize device instance */
+	memset (device_instance, 0, sizeof (struct usb_device_instance));
+	device_instance->device_state = STATE_INIT;
+	device_instance->device_descriptor = &device_descriptor;
+	device_instance->event = usbtty_event_handler;
+	device_instance->cdc_recv_setup = usbtty_cdc_setup;
+	device_instance->bus = bus_instance;
+	device_instance->configurations = NUM_CONFIGS;
+	device_instance->configuration_instance_array = config_instance;
+
+	/* initialize bus instance */
+	memset (bus_instance, 0, sizeof (struct usb_bus_instance));
+	bus_instance->device = device_instance;
+	bus_instance->endpoint_array = endpoint_instance;
+	bus_instance->max_endpoints = 1;
+	bus_instance->maxpacketsize = 64;
+	bus_instance->serial_number_str = serial_number;
+
+	/* configuration instance */
+	memset (config_instance, 0,
+		sizeof (struct usb_configuration_instance));
+	config_instance->interfaces = interface_count;
+	config_instance->configuration_descriptor = configuration_descriptor;
+	config_instance->interface_instance_array = interface_instance;
+
+	/* interface instance */
+	memset (interface_instance, 0,
+		sizeof (struct usb_interface_instance));
+	interface_instance->alternates = 1;
+	interface_instance->alternates_instance_array = alternate_instance;
+
+	/* alternates instance */
+	memset (alternate_instance, 0,
+		sizeof (struct usb_alternate_instance));
+	alternate_instance->interface_descriptor = interface_descriptors;
+	alternate_instance->endpoints = NUM_ENDPOINTS;
+	alternate_instance->endpoints_descriptor_array = ep_descriptor_ptrs;
+
+	/* endpoint instances */
+	memset (&endpoint_instance[0], 0,
+		sizeof (struct usb_endpoint_instance));
+	endpoint_instance[0].endpoint_address = 0;
+	endpoint_instance[0].rcv_packetSize = EP0_MAX_PACKET_SIZE;
+	endpoint_instance[0].rcv_attributes = USB_ENDPOINT_XFER_CONTROL;
+	endpoint_instance[0].tx_packetSize = EP0_MAX_PACKET_SIZE;
+	endpoint_instance[0].tx_attributes = USB_ENDPOINT_XFER_CONTROL;
+	udc_setup_ep (device_instance, 0, &endpoint_instance[0]);
+
+	for (i = 1; i <= NUM_ENDPOINTS; i++) {
+		memset (&endpoint_instance[i], 0,
+			sizeof (struct usb_endpoint_instance));
+
+		endpoint_instance[i].endpoint_address =
+			ep_descriptor_ptrs[i - 1]->bEndpointAddress;
+
+		endpoint_instance[i].rcv_attributes =
+			ep_descriptor_ptrs[i - 1]->bmAttributes;
+
+		endpoint_instance[i].rcv_packetSize =
+			le16_to_cpu(ep_descriptor_ptrs[i - 1]->wMaxPacketSize);
+
+		endpoint_instance[i].tx_attributes =
+			ep_descriptor_ptrs[i - 1]->bmAttributes;
+
+		endpoint_instance[i].tx_packetSize =
+			le16_to_cpu(ep_descriptor_ptrs[i - 1]->wMaxPacketSize);
+
+		endpoint_instance[i].tx_attributes =
+			ep_descriptor_ptrs[i - 1]->bmAttributes;
+
+		urb_link_init (&endpoint_instance[i].rcv);
+		urb_link_init (&endpoint_instance[i].rdy);
+		urb_link_init (&endpoint_instance[i].tx);
+		urb_link_init (&endpoint_instance[i].done);
+
+		if (endpoint_instance[i].endpoint_address & USB_DIR_IN)
+			endpoint_instance[i].tx_urb =
+				usbd_alloc_urb (device_instance,
+						&endpoint_instance[i]);
+		else
+			endpoint_instance[i].rcv_urb =
+				usbd_alloc_urb (device_instance,
+						&endpoint_instance[i]);
+	}
+}
+
+static void usbtty_init_endpoints (void)
+{
+	int i;
+
+	bus_instance->max_endpoints = NUM_ENDPOINTS + 1;
+	for (i = 1; i <= NUM_ENDPOINTS; i++) {
+		udc_setup_ep (device_instance, i, &endpoint_instance[i]);
+	}
+}
+
+/* usbtty_init_terminal_type
+ *
+ * Do some late binding for our device type.
+ */
+static void usbtty_init_terminal_type(short type)
+{
+	switch(type){
+		/* CDC ACM */
+		case 0:
+			/* Assign endpoint descriptors */
+			ep_descriptor_ptrs[0] =
+				&acm_configuration_descriptors[0].notification_endpoint;
+			ep_descriptor_ptrs[1] =
+				&acm_configuration_descriptors[0].data_endpoints[0];
+			ep_descriptor_ptrs[2] =
+				&acm_configuration_descriptors[0].data_endpoints[1];
+
+			/* Enumerate Device Descriptor */
+			device_descriptor.bDeviceClass =
+				COMMUNICATIONS_DEVICE_CLASS;
+			device_descriptor.idProduct =
+				cpu_to_le16(CONFIG_USBD_PRODUCTID_CDCACM);
+
+			/* Assign endpoint indices */
+			tx_endpoint = ACM_TX_ENDPOINT;
+			rx_endpoint = ACM_RX_ENDPOINT;
+
+			/* Configuration Descriptor */
+			configuration_descriptor =
+				(struct usb_configuration_descriptor*)
+				&acm_configuration_descriptors;
+
+			/* Interface count */
+			interface_count = NUM_ACM_INTERFACES;
+		break;
+
+		/* BULK IN/OUT & Default */
+		case 1:
+		default:
+			/* Assign endpoint descriptors */
+			ep_descriptor_ptrs[0] =
+				&gserial_configuration_descriptors[0].data_endpoints[0];
+			ep_descriptor_ptrs[1] =
+				&gserial_configuration_descriptors[0].data_endpoints[1];
+			ep_descriptor_ptrs[2] =
+				&gserial_configuration_descriptors[0].data_endpoints[2];
+
+			/* Enumerate Device Descriptor */
+			device_descriptor.bDeviceClass = 0xFF;
+			device_descriptor.idProduct =
+				cpu_to_le16(CONFIG_USBD_PRODUCTID_GSERIAL);
+
+			/* Assign endpoint indices */
+			tx_endpoint = GSERIAL_TX_ENDPOINT;
+			rx_endpoint = GSERIAL_RX_ENDPOINT;
+
+			/* Configuration Descriptor */
+			configuration_descriptor =
+				(struct usb_configuration_descriptor*)
+				&gserial_configuration_descriptors;
+
+			/* Interface count */
+			interface_count = NUM_GSERIAL_INTERFACES;
+		break;
+	}
+}
+
+/******************************************************************************/
+
+static struct urb *next_urb (struct usb_device_instance *device,
+			     struct usb_endpoint_instance *endpoint)
+{
+	struct urb *current_urb = NULL;
+	int space;
+
+	/* If there's a queue, then we should add to the last urb */
+	if (!endpoint->tx_queue) {
+		current_urb = endpoint->tx_urb;
+	} else {
+		/* Last urb from tx chain */
+		current_urb =
+			p2surround (struct urb, link, endpoint->tx.prev);
+	}
+
+	/* Make sure this one has enough room */
+	space = current_urb->buffer_length - current_urb->actual_length;
+	if (space > 0) {
+		return current_urb;
+	} else {		/* No space here */
+		/* First look at done list */
+		current_urb = first_urb_detached (&endpoint->done);
+		if (!current_urb) {
+			current_urb = usbd_alloc_urb (device, endpoint);
+		}
+
+		urb_append (&endpoint->tx, current_urb);
+		endpoint->tx_queue++;
+	}
+	return current_urb;
+}
+
+static int write_buffer (circbuf_t * buf)
+{
+	if (!usbtty_configured ()) {
+		return 0;
+	}
+
+	struct usb_endpoint_instance *endpoint =
+			&endpoint_instance[tx_endpoint];
+	struct urb *current_urb = NULL;
+
+	current_urb = next_urb (device_instance, endpoint);
+	/* TX data still exists - send it now
+	 */
+	if(endpoint->sent < current_urb->actual_length){
+		if(udc_endpoint_write (endpoint)){
+			/* Write pre-empted by RX */
+			return -1;
+		}
+	}
+
+	if (buf->size) {
+		char *dest;
+
+		int space_avail;
+		int popnum, popped;
+		int total = 0;
+
+		/* Break buffer into urb sized pieces,
+		 * and link each to the endpoint
+		 */
+		while (buf->size > 0) {
+
+			if (!current_urb) {
+				TTYERR ("current_urb is NULL, buf->size %d\n",
+					buf->size);
+				return total;
+			}
+
+			dest = (char*)current_urb->buffer +
+				current_urb->actual_length;
+
+			space_avail =
+				current_urb->buffer_length -
+				current_urb->actual_length;
+			popnum = MIN (space_avail, buf->size);
+			if (popnum == 0)
+				break;
+
+			popped = buf_pop (buf, dest, popnum);
+			if (popped == 0)
+				break;
+			current_urb->actual_length += popped;
+			total += popped;
+
+			/* If endpoint->last == 0, then transfers have
+			 * not started on this endpoint
+			 */
+			if (endpoint->last == 0) {
+				if(udc_endpoint_write (endpoint)){
+					/* Write pre-empted by RX */
+					return -1;
+				}
+			}
+
+		}/* end while */
+		return total;
+	}
+
+	return 0;
+}
+
+static int fill_buffer (circbuf_t * buf)
+{
+	struct usb_endpoint_instance *endpoint =
+		&endpoint_instance[rx_endpoint];
+
+	if (endpoint->rcv_urb && endpoint->rcv_urb->actual_length) {
+		unsigned int nb = 0;
+		char *src = (char *) endpoint->rcv_urb->buffer;
+		unsigned int rx_avail = buf->totalsize - buf->size;
+
+		if(rx_avail >= endpoint->rcv_urb->actual_length){
+
+			nb = endpoint->rcv_urb->actual_length;
+			buf_push (buf, src, nb);
+			endpoint->rcv_urb->actual_length = 0;
+
+		}
+		return nb;
+	}
+	return 0;
+}
+
+static int usbtty_configured (void)
+{
+	return usbtty_configured_flag;
+}
+
+/******************************************************************************/
+
+static void usbtty_event_handler (struct usb_device_instance *device,
+				  usb_device_event_t event, int data)
+{
+	switch (event) {
+	case DEVICE_RESET:
+	case DEVICE_BUS_INACTIVE:
+		usbtty_configured_flag = 0;
+		break;
+	case DEVICE_CONFIGURED:
+		usbtty_configured_flag = 1;
+		break;
+
+	case DEVICE_ADDRESS_ASSIGNED:
+		usbtty_init_endpoints ();
+
+	default:
+		break;
+	}
+}
+
+/******************************************************************************/
+
+int usbtty_cdc_setup(struct usb_device_request *request, struct urb *urb)
+{
+	switch (request->bRequest){
+
+	   	case ACM_SET_CONTROL_LINE_STATE:	/* Implies DTE ready */
+			break;
+	   	case ACM_SEND_ENCAPSULATED_COMMAND :	/* Required */
+			break;
+		case ACM_SET_LINE_ENCODING :		/* DTE stop/parity bits
+							 * per character */
+			break;
+	   	case ACM_GET_ENCAPSULATED_RESPONSE :	/* request response */
+			break;
+		case ACM_GET_LINE_ENCODING :		/* request DTE rate,
+							 * stop/parity bits */
+			memcpy (urb->buffer , &rs232_desc, sizeof(rs232_desc));
+			urb->actual_length = sizeof(rs232_desc);
+
+			break;
+	 	default:
+			return 1;
+	}
+	return 0;
+}
+
+/******************************************************************************/
+
+/*
+ * Since interrupt handling has not yet been implemented, we use this function
+ * to handle polling.  This is called by the tstc,getc,putc,puts routines to
+ * update the USB state.
+ */
+void usbtty_poll (void)
+{
+	/* New interrupts? */
+	udc_irq();
+
+	/* Write any output data to host buffer
+	 * (do this before checking interrupts to avoid missing one)
+	 */
+	if (usbtty_configured ()) {
+		write_buffer (&usbtty_output);
+	}
+
+	/* New interrupts? */
+	udc_irq();
+
+	/* Check for new data from host..
+	 * (do this after checking interrupts to get latest data)
+	 */
+	if (usbtty_configured ()) {
+		fill_buffer (&usbtty_input);
+	}
+
+	/* New interrupts? */
+	udc_irq();
+
+}
+
+
+#endif
diff --git a/drivers/serial/usbtty.h b/drivers/serial/usbtty.h
new file mode 100644
index 0000000..8154e30
--- /dev/null
+++ b/drivers/serial/usbtty.h
@@ -0,0 +1,70 @@
+/*
+ * (C) Copyright 2003
+ * Gerry Hamel, geh@ti.com, Texas Instruments
+ *
+ * (C) Copyright 2006
+ * Bryan O'Donoghue, bodonoghue@codehermit.ie, CodeHermit
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307	 USA
+ *
+ */
+
+#ifndef __USB_TTY_H__
+#define __USB_TTY_H__
+
+#include "usbdcore.h"
+#if defined(CONFIG_PPC)
+#include "usbdcore_mpc8xx.h"
+#elif defined(CONFIG_ARM)
+#include "usbdcore_omap1510.h"
+#endif
+
+#include <version_autogenerated.h>
+
+/* If no VendorID/ProductID is defined in config.h, pretend to be Linux
+ * DO NOT Reuse this Vendor/Product setup with protocol incompatible devices */
+
+#define CONFIG_USBD_VENDORID 0x0525 	/* Linux/NetChip */
+#define CONFIG_USBD_PRODUCTID_GSERIAL 0xa4a6	/* gserial */
+#define CONFIG_USBD_PRODUCTID_CDCACM  0xa4a7	/* CDC ACM */
+#define CONFIG_USBD_MANUFACTURER "Das U-Boot"
+#define CONFIG_USBD_PRODUCT_NAME U_BOOT_VERSION
+
+
+#define CONFIG_USBD_CONFIGURATION_STR "TTY via USB"
+
+#define CONFIG_USBD_SERIAL_OUT_ENDPOINT UDC_OUT_ENDPOINT
+#define CONFIG_USBD_SERIAL_OUT_PKTSIZE	UDC_OUT_PACKET_SIZE
+#define CONFIG_USBD_SERIAL_IN_ENDPOINT	UDC_IN_ENDPOINT
+#define CONFIG_USBD_SERIAL_IN_PKTSIZE	UDC_IN_PACKET_SIZE
+#define CONFIG_USBD_SERIAL_INT_ENDPOINT UDC_INT_ENDPOINT
+#define CONFIG_USBD_SERIAL_INT_PKTSIZE	UDC_INT_PACKET_SIZE
+#define CONFIG_USBD_SERIAL_BULK_PKTSIZE	UDC_BULK_PACKET_SIZE
+
+#define USBTTY_DEVICE_CLASS	COMMUNICATIONS_DEVICE_CLASS
+
+#define USBTTY_BCD_DEVICE 	0x00
+#define USBTTY_MAXPOWER	  	0x00
+
+#define STR_LANG		0x00
+#define STR_MANUFACTURER	0x01
+#define STR_PRODUCT		0x02
+#define STR_SERIAL		0x03
+#define STR_CONFIG		0x04
+#define STR_DATA_INTERFACE	0x05
+#define STR_CTRL_INTERFACE	0x06
+#define STR_COUNT		0x07
+
+#endif