diff --git a/drivers/serial/usbtty.h b/drivers/serial/usbtty.h
index eb670da..bd3bcbc 100644
--- a/drivers/serial/usbtty.h
+++ b/drivers/serial/usbtty.h
@@ -35,6 +35,8 @@
 #include <usb/pxa27x_udc.h>
 #elif defined(CONFIG_DW_UDC)
 #include <usb/designware_udc.h>
+#elif defined(CONFIG_DW_OTG)
+#include <usb/designware_otg.h>
 #endif
 
 #include <version.h>
diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile
index 040eaba..30ab931 100644
--- a/drivers/usb/gadget/Makefile
+++ b/drivers/usb/gadget/Makefile
@@ -43,6 +43,7 @@ ifdef CONFIG_USB_DEVICE
 COBJS-y += core.o
 COBJS-y += ep0.o
 COBJS-$(CONFIG_DW_UDC) += designware_udc.o
+COBJS-$(CONFIG_DW_OTG) += designware_otg.o
 COBJS-$(CONFIG_OMAP1510) += omap1510_udc.o
 COBJS-$(CONFIG_OMAP1610) += omap1510_udc.o
 COBJS-$(CONFIG_MPC885_FAMILY) += mpc8xx_udc.o
diff --git a/drivers/usb/gadget/designware_otg.c b/drivers/usb/gadget/designware_otg.c
new file mode 100644
index 0000000..57f6f15
--- /dev/null
+++ b/drivers/usb/gadget/designware_otg.c
@@ -0,0 +1,1063 @@
+/*
+ * Based on drivers/usb/gadget/designware_otg.c
+ * Synopsys DW OTG Device bus interface driver
+ *
+ * (C) Copyright 2011
+ * Pratyush Anand, ST Micoelectronics, pratyush.anand@st.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>
+#include <asm/io.h>
+#include <usbdevice.h>
+#include "ep0.h"
+#include <usb/designware_otg.h>
+#include <asm/arch/hardware.h>
+
+#define UDC_INIT_MDELAY		80	/* Device settle delay */
+
+/* Some kind of debugging output... */
+#ifndef DEBUG_DWUSBTTY
+#define UDCDBG(str)
+#define UDCDBGA(fmt, args...)
+#else
+#define UDCDBG(str) serial_printf(str "\n")
+#define UDCDBGA(fmt, args...) serial_printf(fmt "\n", ##args)
+#endif
+
+static struct urb *ep0_urb;
+static struct usb_device_instance *udc_device;
+
+static struct device_if	device_if_mem;
+static struct device_if	*dev_if = &device_if_mem;
+#if defined(CONFIG_USBD_HS)
+#define CONFIG_USBD_SERIAL_BULK_PKTSIZE	UDC_BULK_HS_PACKET_SIZE
+#endif
+
+static void udc_set_addr_ctrl(u32 address);
+static void udc_set_cfg_ctrl(u32 config);
+
+static struct usb_endpoint_instance *dw_find_ep(int ep)
+{
+	int i;
+
+	for (i = 0; i < udc_device->bus->max_endpoints; i++) {
+		if ((udc_device->bus->endpoint_array[i].endpoint_address &
+					USB_ENDPOINT_NUMBER_MASK) == ep)
+			return &udc_device->bus->endpoint_array[i];
+	}
+	return NULL;
+}
+
+/*
+ * This function reads a packet from the Rx FIFO into the destination buffer.
+ * To read SETUP data use dwc_otg_read_setup_packet.
+ */
+void dwc_otg_read_packet(struct dwc_ep *ep, u16 _bytes)
+{
+	u32 i;
+	int word_count = (_bytes + 3) / 4;
+	u32 *fifo = dev_if->data_fifo[0];
+	u32 *data_buff = (u32 *) ep->xfer_buff;
+	u32 unaligned;
+	/*
+	 * This requires reading data from the FIFO into a u32 temp buffer,
+	 * then moving it into the data buffer.
+	 */
+	if ((_bytes < 4) && (_bytes > 0)) {
+		unaligned = readl(fifo);
+		memcpy(data_buff, &unaligned, _bytes);
+	} else {
+		for (i = 0; i < word_count; i++, data_buff++)
+			*data_buff = readl(fifo);
+	}
+}
+
+/* Handle RX transaction on non-ISO endpoint. */
+static void dw_udc_epn_rx(struct dwc_ep *ep, int bcnt)
+{
+	struct urb *urb;
+	struct usb_endpoint_instance *endpoint = dw_find_ep(ep->num);
+
+	if (endpoint) {
+		urb = endpoint->rcv_urb;
+
+		if (urb) {
+			ep->xfer_buff = urb->buffer + urb->actual_length;
+			dwc_otg_read_packet(ep, bcnt);
+			usbd_rcv_complete(endpoint, bcnt, 0);
+		}
+	}
+}
+
+/*
+ * This function writes a packet into the Tx FIFO associated with the EP.
+ * The buffer is padded to DWORD on a per packet basis in
+ * slave/dma mode if the MPS is not DWORD aligned. The last packet, if
+ * short, is also padded to a multiple of DWORD.
+ *
+ * ep->xfer_buff always starts DWORD aligned in memory and is a
+ * multiple of DWORD in length
+ *
+ * ep->xfer_len can be any number of bytes
+ *
+ * FIFO access is DWORD
+ */
+static void dwc_otg_ep_write_packet(struct dwc_ep *ep)
+{
+	u32 i;
+	u32 dword_count;
+	u32 *fifo;
+	u32 *data_buff = (u32 *) ep->xfer_buff;
+	u32 temp, unaligned;
+	struct device_in_ep_regs *in_ep_regs = dev_if->in_ep_regs[ep->num];
+	struct core_global_regs *core_global_regs = dev_if->core_global_regs;
+
+	/*
+	 * Find the DWORD length, padded by extra bytes as neccessary if MPS
+	 * is not a multiple of DWORD
+	 */
+	dword_count = (ep->xfer_len + 3) / 4;
+	fifo = dev_if->data_fifo[ep->num];
+
+	/* program pkt count */
+	temp = ep->xfer_len;
+	temp |= (1 << PKTCNT_SHIFT);
+	writel(temp, &in_ep_regs->dieptsiz);
+
+	/* enable EP*/
+	temp = readl(&in_ep_regs->diepctl);
+	temp |= (EPENA | CNAK);
+	writel(temp, &in_ep_regs->diepctl);
+
+	/* clear TX Fifo Empty intr*/
+	writel(NPTXFEMPTY, &core_global_regs->gintsts);
+
+	temp = readl(&core_global_regs->gintmsk);
+	temp |= NPTXFEMPTY;
+	writel(temp, &core_global_regs->gintmsk);
+
+	while (!(readl(&core_global_regs->gintsts) & NPTXFEMPTY))
+		;
+
+	/* write to fifo */
+	if ((ep->xfer_len < 4) && (ep->xfer_len > 0)) {
+		memcpy(&unaligned, data_buff, ep->xfer_len);
+		*fifo = unaligned;
+	} else {
+		for (i = 0; i < dword_count; i++, data_buff++)
+			*fifo = *data_buff;
+	}
+
+	writel(NPTXFEMPTY, &core_global_regs->gintsts);
+
+	/* check for transfer completion*/
+	while (!(readl(&in_ep_regs->diepint) & XFERCOMPL))
+		;
+
+	writel(XFERCOMPL, &in_ep_regs->diepint);
+
+	temp = readl(&core_global_regs->gintmsk);
+	temp &= ~NPTXFEMPTY;
+	writel(temp, &core_global_regs->gintmsk);
+}
+
+/* Handle TX transaction on non-ISO endpoint. */
+static void dw_udc_epn_tx(struct dwc_ep *ep)
+{
+	struct usb_endpoint_instance *endpoint = dw_find_ep(ep->num);
+	struct urb *urb = endpoint->tx_urb;
+	int align;
+
+	if (!endpoint)
+		return;
+
+	/*
+	 * We need to transmit a terminating zero-length packet now if
+	 * we have sent all of the data in this URB and the transfer
+	 * size was an exact multiple of the packet size.
+	 */
+	if (urb && (endpoint->last == endpoint->tx_packetSize) &&
+			(urb->actual_length - endpoint->sent -
+			 endpoint->last == 0)) {
+		/* handle zero length packet here */
+		ep->xfer_len = 0;
+		dwc_otg_ep_write_packet(ep);
+	}
+
+	if (urb && urb->actual_length) {
+		/* retire the data that was just sent */
+		usbd_tx_complete(endpoint);
+		/*
+		 * Check to see if we have more data ready to transmit
+		 * now.
+		 */
+		if (urb && urb->actual_length) {
+			/* write data to FIFO */
+			ep->xfer_len = MIN(urb->actual_length - endpoint->sent,
+					endpoint->tx_packetSize);
+
+			if (ep->xfer_len) {
+				ep->xfer_buff = urb->buffer + endpoint->sent;
+
+				/*
+				 * This ensures that USBD packet fifo is
+				 * accessed through word aligned pointer or
+				 * through non word aligned pointer but only
+				 * with a max length to make the next packet
+				 * word aligned
+				 */
+
+				align = ((ulong)ep->xfer_buff % sizeof(int));
+				if (align)
+					ep->xfer_len = MIN(ep->xfer_len,
+							sizeof(int) - align);
+
+				dwc_otg_ep_write_packet(ep);
+			}
+			endpoint->last = ep->xfer_len;
+
+		} else if (urb && (urb->actual_length == 0)) {
+			/* udc_set_nak(ep); */
+		}
+	}
+}
+
+/* This function returns pointer to out ep struct with number num */
+struct dwc_ep *get_out_ep(u32 num)
+{
+	u32 i;
+	int num_out_eps = MAX_EPS_CHANNELS;
+	struct dwc_pcd *pcd = &dev_if->pcd;
+
+	if (num == 0) {
+		return &pcd->ep0;
+	} else {
+		for (i = 0; i < num_out_eps; ++i) {
+			if (pcd->out_ep[i].num == num)
+				return &pcd->out_ep[i];
+		}
+	}
+	return 0;
+}
+
+/* This function returns pointer to in ep struct with number num */
+struct dwc_ep *get_in_ep(u32 num)
+{
+	u32 i;
+	int num_out_eps = MAX_EPS_CHANNELS;
+	struct dwc_pcd *pcd = &dev_if->pcd;
+
+	if (num == 0) {
+		return &pcd->ep0;
+	} else {
+		for (i = 0; i < num_out_eps; ++i) {
+			if (pcd->in_ep[i].num == num)
+				return &pcd->in_ep[i];
+		}
+	}
+	return 0;
+}
+
+/*
+ * This function reads the 8 bytes of the setup packet from the Rx FIFO into the
+ * destination buffer. It is called from the Rx Status Queue Level (RxStsQLvl)
+ * interrupt routine when a SETUP packet has been received in Slave mode.
+ */
+static void dwc_otg_read_setup_packet(u32 *dest)
+{
+	dest[0] = readl(dev_if->data_fifo[0]);
+	dest[1] = readl(dev_if->data_fifo[0]);
+}
+
+/*
+ * This function handles the Rx Status Queue Level Interrupt, which
+ * indicates that there is a least one packet in the Rx FIFO. The
+ * packets are moved from the FIFO to memory, where they will be
+ * processed when the Endpoint Interrupt Register indicates Transfer
+ * Complete or SETUP Phase Done.
+ *
+ * Repeat the following until the Rx Status Queue is empty:
+ *	 -# Read the Receive Status Pop Register (GRXSTSP) to get Packet
+ *		info
+ *	 -# If Receive FIFO is empty then skip to step Clear the interrupt
+ *		and exit
+ *	 -# If SETUP Packet call dwc_otg_read_setup_packet to copy the
+ *		SETUP data to the buffer
+ *	 -# If OUT Data Packet call dwc_otg_read_packet to copy the data
+ *		to the destination buffer
+ */
+static int dwc_otg_pcd_handle_rx_status_q_level_intr(void)
+{
+	struct core_global_regs *global_regs = dev_if->core_global_regs;
+	struct dwc_pcd *pcd = &dev_if->pcd;
+	u32	gintmsk;
+	u32	status;
+	struct dwc_ep *ep;
+	u32	bcnt;
+
+	/* Disable the Rx Status Queue Level interrupt */
+	gintmsk = readl(&global_regs->gintmsk);
+	gintmsk &= ~RXSTSQLVL;
+	writel(gintmsk, &global_regs->gintmsk);
+
+	/* Get the Status from the top of the FIFO */
+	status = readl(&global_regs->grxstsp);
+	/* Get pointer to EP structure */
+	ep = get_out_ep((status & EPNUMMSK) >> EPNUM_SHIFT);
+	bcnt = (status & BCNTMSK) >> BCNT_SHIFT;
+
+	switch ((status & PKTSTSMSK) >> PKTSTS_SHIFT) {
+	case DWC_DSTS_GOUT_NAK:
+		break;
+	case DWC_STS_DATA_UPDT:
+		if (bcnt)
+			dw_udc_epn_rx(ep, bcnt);
+		break;
+	case DWC_STS_XFER_COMP:
+		break;
+	case DWC_DSTS_SETUP_COMP:
+		break;
+	case DWC_DSTS_SETUP_UPDT:
+		dwc_otg_read_setup_packet((u32 *)pcd->req);
+		break;
+	default:
+		break;
+	}
+
+	/* Enable the Rx Status Queue Level interrupt */
+	gintmsk = readl(&global_regs->gintmsk);
+	gintmsk |= RXSTSQLVL;
+	writel(gintmsk, &global_regs->gintmsk);
+
+	/* Clear interrupt */
+	writel(RXSTSQLVL, &global_regs->gintsts);
+
+	return 1;
+}
+
+/*
+ * This function starts the Zero-Length Packet for the IN status phase
+ * of a 2 stage control transfer.
+ */
+static void do_setup_in_status_phase(struct device_if *dev_if)
+{
+	struct device_out_ep_regs *out_regs =
+		dev_if->out_ep_regs[0];
+	u32 doepctl, doeptsiz;
+	doeptsiz = 0;
+	doeptsiz |= (1 << PKTCNT_SHIFT);
+	writel(doeptsiz, &out_regs->doeptsiz);
+	doepctl = readl(&out_regs->doepctl);
+	doepctl |= (CNAK | EPENA);
+	writel(doepctl, &out_regs->doepctl);
+}
+
+static void udc_set_stall(int epid, int dir)
+{
+	if (dir)
+		writel(readl(&dev_if->in_ep_regs[epid]->diepctl) | SSTALL,
+			&dev_if->in_ep_regs[epid]->diepctl);
+	else
+		writel(readl(&dev_if->out_ep_regs[epid]->doepctl) | SSTALL,
+			&dev_if->out_ep_regs[epid]->doepctl);
+}
+
+/*
+ * This function handles EP0 Control transfers.
+ *
+ * The state of the control tranfers are tracked in ep0state
+ *
+ * A flag set indicates that it is not the first packet, so do not
+ * process setup data now. it has alreday been processed, just send the
+ * next data packet
+ */
+void handle_ep0(int in_flag)
+{
+	struct dwc_pcd *pcd = &dev_if->pcd;
+	struct dwc_ep *ep0 = &pcd->ep0;
+	struct usb_device_request *ctrl = pcd->req;
+
+	/* handle inepint, only when more than 64 bytes to transfer*/
+	if (in_flag & !ep0_urb->actual_length)
+		return;
+
+	if (!ep0_urb->actual_length) {
+		if (ep0_recv_setup(ep0_urb)) {
+			udc_set_stall(0, ctrl->bmRequestType & USB_DIR_IN);
+			return;
+		}
+		if (ep0_urb->device->address)
+			udc_set_addr_ctrl(ep0_urb->device->address);
+
+		if (ep0_urb->device->configuration)
+			udc_set_cfg_ctrl(ep0_urb->device->configuration);
+
+		ep0->xfer_buff = (u8 *)ep0_urb->buffer;
+	} else
+		ep0->xfer_buff += EP0_MAX_PACKET_SIZE;
+
+	if (ep0_urb->actual_length <= EP0_MAX_PACKET_SIZE) {
+		ep0->xfer_len = ep0_urb->actual_length;
+		ep0_urb->actual_length = 0;
+	} else {
+		ep0->xfer_len = EP0_MAX_PACKET_SIZE;
+		ep0_urb->actual_length -= EP0_MAX_PACKET_SIZE;
+	}
+
+	if (ctrl->bmRequestType & USB_DIR_IN) {
+		dwc_otg_ep_write_packet(ep0);
+		if (!ep0_urb->actual_length)
+			do_setup_in_status_phase(dev_if);
+	} else {
+		if (!ctrl->wLength)
+			dwc_otg_ep_write_packet(ep0);
+		else
+			udc_set_stall(0, ctrl->bmRequestType & USB_DIR_OUT);
+	}
+}
+
+/*
+ * This function reads the Device All Endpoints Interrupt register and
+ * returns the OUT endpoint interrupt bits.
+ */
+static u32 dwc_otg_read_dev_all_out_ep_intr(void)
+{
+	u32 v;
+
+	v = readl(&dev_if->dev_global_regs->daint) &
+		readl(&dev_if->dev_global_regs->daintmsk);
+	return v >> 16;
+}
+
+/*
+ * This function reads the Device All Endpoints Interrupt register and
+ * returns the IN endpoint interrupt bits.
+ */
+static u32 dwc_otg_read_dev_all_in_ep_intr(void)
+{
+	u32 v;
+
+	v = readl(&dev_if->dev_global_regs->daint) &
+		readl(&dev_if->dev_global_regs->daintmsk);
+	return v & 0xffff;
+}
+
+/* This function returns the Device OUT EP Interrupt register */
+static u32 dwc_otg_read_doep_intr(struct dwc_ep *ep)
+{
+	u32 v;
+
+	v = readl(&dev_if->out_ep_regs[ep->num]->doepint) &
+		readl(&dev_if->dev_global_regs->doepmsk);
+	return v;
+}
+
+/*This function returns the Device IN EP Interrupt register */
+static u32 dwc_otg_read_diep_intr(struct dwc_ep *ep)
+{
+	u32 v;
+
+	v = readl(&dev_if->in_ep_regs[ep->num]->diepint) &
+		readl(&dev_if->dev_global_regs->diepmsk);
+	return v;
+}
+
+/*
+ * This function configures EPO to receive SETUP packets.
+ *
+ * Program the following fields in the endpoint specific registers for Control
+ * OUT EP 0, in order to receive a setup packet:
+ *
+ * - DOEPTSIZ0.Packet Count = 3 (To receive up to 3 back to back setup packets)
+ *
+ * - DOEPTSIZE0.Transfer Size = 24 Bytes (To receive up to 3 back to back setup
+ * packets)
+ *
+ * In DMA mode, DOEPDMA0 Register with a memory address to store any setup
+ * packets received
+ */
+static void ep0_out_start(void)
+{
+	u32 temp;
+
+	/* program transfer size*/
+	temp = 8 * 3;
+	/* program packet count*/
+	temp |= PKTCNT;
+	/* program setup packet count */
+	temp |= (3 << SUPCNT_SHIFT);
+	writel(temp, &dev_if->out_ep_regs[0]->doeptsiz);
+}
+
+/* should be called after set address is received */
+static void udc_set_addr_ctrl(u32 address)
+{
+	u32 dcfg;
+
+	dcfg = readl(&dev_if->dev_global_regs->dcfg);
+	dcfg &= ~DEVADDRMSK;
+	dcfg |= address << DEVADDR_SHIFT;
+	writel(dcfg, &dev_if->dev_global_regs->dcfg);
+
+	usbd_device_event_irq(udc_device, DEVICE_ADDRESS_ASSIGNED, 0);
+}
+
+/* should be called after set configuration is received */
+static void dwc_otg_bulk_out_activate(void)
+{
+	struct device_out_ep_regs *out_regs =
+		dev_if->out_ep_regs[UDC_OUT_ENDPOINT];
+	struct device_global_regs *dev_global_regs
+		= dev_if->dev_global_regs;
+	u32 doepctl, doeptsiz, daint;
+
+	daint = readl(&dev_global_regs->daintmsk);
+	daint |= 1 << (UDC_OUT_ENDPOINT + DAINTMASK_OUT_SHIFT);
+	writel(daint, &dev_global_regs->daintmsk);
+	doeptsiz = CONFIG_USBD_SERIAL_BULK_PKTSIZE;
+	doeptsiz |= (1 << PKTCNT_SHIFT);
+	writel(doeptsiz, &out_regs->doeptsiz);
+	doepctl = readl(&out_regs->doepctl);
+	doepctl &= ~DOEPCTL_MPSMSK;
+	doepctl &= ~EPTYPEMSK;
+	doepctl |= (CONFIG_USBD_SERIAL_BULK_PKTSIZE |
+			CNAK | EPENA | USBACTEP | DATA0PID
+			| (EPTYPE_BULK << EPTYPE_SHIFT));
+	writel(doepctl, &out_regs->doepctl);
+}
+
+/* should be called after set configuration is received */
+static void dwc_otg_bulk_in_activate(void)
+{
+	struct device_in_ep_regs *in_regs =
+		dev_if->in_ep_regs[UDC_IN_ENDPOINT];
+	struct device_global_regs *dev_global_regs
+		= dev_if->dev_global_regs;
+	u32 diepctl, daint;
+
+	daint = readl(&dev_global_regs->daintmsk);
+	daint |= 1 << (UDC_IN_ENDPOINT + DAINTMASK_IN_SHIFT);
+	writel(daint, &dev_global_regs->daintmsk);
+
+	diepctl = readl(&in_regs->diepctl);
+	diepctl &= ~DIEPCTL_MPSMSK;
+	diepctl &= ~EPTYPEMSK;
+	diepctl |= (CONFIG_USBD_SERIAL_BULK_PKTSIZE
+			| USBACTEP | DATA0PID
+			| (EPTYPE_BULK << EPTYPE_SHIFT));
+	writel(diepctl, &in_regs->diepctl);
+}
+
+static void dwc_otg_int_in_activate(void)
+{
+	struct device_in_ep_regs *in_regs =
+		dev_if->in_ep_regs[UDC_INT_ENDPOINT];
+	struct device_global_regs *dev_global_regs
+		= dev_if->dev_global_regs;
+	u32 diepctl, daint;
+
+	daint = readl(&dev_global_regs->daintmsk);
+	daint |= 1 << (UDC_INT_ENDPOINT + DAINTMASK_IN_SHIFT);
+	writel(daint, &dev_global_regs->daintmsk);
+
+	diepctl = readl(&in_regs->diepctl);
+	diepctl &= ~DIEPCTL_MPSMSK;
+	diepctl &= ~EPTYPEMSK;
+	diepctl |= (UDC_INT_PACKET_SIZE
+			| USBACTEP | DATA0PID
+			| (EPTYPE_INT << EPTYPE_SHIFT));
+	writel(diepctl, &in_regs->diepctl);
+}
+
+/* should be called after set configuration is received */
+static void udc_set_cfg_ctrl(u32 config)
+{
+	dwc_otg_bulk_out_activate();
+	dwc_otg_bulk_in_activate();
+	dwc_otg_int_in_activate();
+	usbd_device_event_irq(udc_device, DEVICE_CONFIGURED, 0);
+}
+
+/* should be called to receive next packet */
+static void dwc_otg_bulk_out_enable(void)
+{
+	struct device_out_ep_regs *out_regs =
+		dev_if->out_ep_regs[UDC_OUT_ENDPOINT];
+	u32 doepctl, doeptsiz;
+
+	doeptsiz = CONFIG_USBD_SERIAL_BULK_PKTSIZE;
+	doeptsiz |= (1 << PKTCNT_SHIFT);
+	writel(doeptsiz, &out_regs->doeptsiz);
+	doepctl = readl(&out_regs->doepctl);
+	doepctl |= CNAK | EPENA;
+	writel(doepctl, &out_regs->doepctl);
+}
+
+/* This interrupt indicates that an OUT EP has a pending Interrupt. */
+
+static int dwc_otg_pcd_handle_out_ep_intr(void)
+{
+	u32 ep_intr;
+	u32 doepint;
+	u32 epnum = 0;
+	struct dwc_ep *dwc_ep;
+	struct device_out_ep_regs **out_ep_regs
+		= dev_if->out_ep_regs;
+
+	/* Read in the device interrupt bits */
+	ep_intr = dwc_otg_read_dev_all_out_ep_intr();
+	while (ep_intr) {
+		if (ep_intr & 0x1) {
+			dwc_ep = get_out_ep(epnum);
+			doepint = dwc_otg_read_doep_intr(dwc_ep);
+
+			/* Transfer complete */
+			if (doepint & XFERCOMPL) {
+				/* Clear xfercompl */
+				writel(XFERCOMPL, &out_ep_regs[epnum]->doepint);
+				if (!epnum)
+					ep0_out_start();
+				else if (epnum == UDC_OUT_ENDPOINT)
+					dwc_otg_bulk_out_enable();
+			}
+			/* Setup Phase Done (control EPs) */
+			if (doepint & SETUP) {
+				writel(SETUP, &out_ep_regs[epnum]->doepint);
+				handle_ep0(0);
+			}
+		}
+		epnum++;
+		ep_intr >>= 1;
+	}
+	return 1;
+}
+
+/* This interrupt indicates that an IN EP has a pending Interrupt. */
+
+static int dwc_otg_pcd_handle_in_ep_intr(void)
+{
+	u32 ep_intr;
+	u32 diepint;
+	u32 epnum = 0;
+	struct dwc_ep *dwc_ep;
+	struct device_in_ep_regs **in_ep_regs
+		= dev_if->in_ep_regs;
+
+	/* Read in the device interrupt bits */
+	ep_intr = dwc_otg_read_dev_all_in_ep_intr();
+	while (ep_intr) {
+		if (ep_intr & 0x1) {
+			dwc_ep = get_in_ep(epnum);
+			diepint = dwc_otg_read_diep_intr(dwc_ep);
+
+			/* IN token received when txfifo empty */
+			if (diepint & INTKNTXFEMP) {
+				/* Clear xfercompl */
+				writel(INTKNTXFEMP,
+						&in_ep_regs[epnum]->diepint);
+				if (!epnum)
+					handle_ep0(1);
+				else if (epnum == UDC_IN_ENDPOINT)
+					dw_udc_epn_tx(dwc_ep);
+			}
+		}
+		epnum++;
+		ep_intr >>= 1;
+	}
+	return 1;
+}
+
+static void dwc_otg_flush_tx_fifo(const int num)
+{
+	struct core_global_regs *global_regs = dev_if->core_global_regs;
+	u32 val = 0;
+	int count = 0;
+
+	val = readl(&global_regs->grstctl);
+	val |= TXFFLSH;
+	val &= ~TXFNUM;
+	val |= (num << TXFNUM_SHIFT);
+	writel(val, &global_regs->grstctl);
+
+	do {
+		val = readl(&global_regs->grstctl);
+		if (++count > 10000)
+			break;
+		udelay(1);
+	} while (val & TXFFLSH);
+
+	/* Wait for 3 PHY Clocks */
+	udelay(1);
+}
+
+static void dwc_otg_flush_rx_fifo(void)
+{
+	struct core_global_regs *global_regs = dev_if->core_global_regs;
+	int count = 0;
+	u32 val = 0;
+
+	val = readl(&global_regs->grstctl);
+	val |= RXFFLSH;
+	writel(val, &global_regs->grstctl);
+
+	do {
+		val = readl(&global_regs->grstctl);
+		if (++count > 10000)
+			break;
+		udelay(1);
+	} while (val & RXFFLSH);
+
+	/* Wait for 3 PHY Clocks */
+	udelay(1);
+}
+
+/*
+ * This interrupt occurs when a USB Reset is detected. When the USB Reset
+ * Interrupt occurs the device state is set to DEFAULT and the EP0 state is set
+ * to IDLE.
+ *
+ */
+static int dwc_otg_pcd_handle_usb_reset_intr(void)
+{
+	u32 temp;
+	u32 i;
+	u32 gintmsk;
+	struct device_out_ep_regs **out_ep_regs
+		= dev_if->out_ep_regs;
+	struct device_global_regs *dev_global_regs
+		= dev_if->dev_global_regs;
+	struct core_global_regs *core_global_regs
+		= dev_if->core_global_regs;
+	/* Set NAK for all OUT EPs */
+	for (i = 0; i < MAX_EPS_CHANNELS; i++) {
+		temp = readl(&out_ep_regs[i]->doepctl);
+		temp |= SNAK;
+		writel(temp, &out_ep_regs[i]->doepctl);
+	}
+
+	/* Flush the NP Tx FIFO */
+	dwc_otg_flush_tx_fifo(DWC_GRSTCTL_TXFNUM_ALL);
+	dwc_otg_flush_rx_fifo();
+	writel((1 << (DAINTMASK_IN_SHIFT + 0))
+				| (1 << (DAINTMASK_OUT_SHIFT + 0)),
+				&dev_global_regs->daintmsk);
+
+	writel(SETUPMSK | XFERCOMPLMSK | AHBERRMSK | EPDISABLEDMSK,
+			&dev_global_regs->doepmsk);
+
+	writel(INTKNTXFEMP, &dev_global_regs->diepmsk);
+
+	gintmsk = readl(&core_global_regs->gintmsk);
+	gintmsk |= GOUTNAKEFF;
+	writel(gintmsk, &core_global_regs->gintmsk);
+
+	/* program fifo size for ep0 */
+
+	writel(0x200, &core_global_regs->grxfsiz);
+
+	temp = readl(&dev_if->in_ep_regs[0]->diepctl);
+	temp &= 0xFFC3FFFF; /* TxFNumBF = 0, bits 25:22 */
+	writel(temp, &dev_if->in_ep_regs[0]->diepctl);
+
+	temp = readl(&core_global_regs->gnptxfsiz);
+
+	writel(0x2000000, &core_global_regs->gnptxfsiz);
+
+	/* Reset Device Address */
+	temp = readl(&dev_global_regs->dcfg);
+	temp &= ~DEVADDRMSK;
+	writel(temp, &dev_global_regs->dcfg);
+
+	/* setup EP0 to receive SETUP packets */
+	ep0_out_start();
+
+	/* Clear interrupt */
+	writel(USBRESET, &core_global_regs->gintsts);
+
+	UDCDBG("device reset in progess");
+	usbd_device_event_irq(udc_device, DEVICE_HUB_CONFIGURED, 0);
+	usbd_device_event_irq(udc_device, DEVICE_RESET, 0);
+
+	return 1;
+}
+
+/*
+ * This function enables EP0 OUT to receive SETUP packets and configures EP0
+ * IN for transmitting packets. It is normally called when the "Enumeration
+ * Done" interrupt occurs.
+ */
+static void dwc_otg_ep0_activate(void)
+{
+	u32 temp;
+	struct device_in_ep_regs *in_ep_regs = dev_if->in_ep_regs[0];
+	struct device_out_ep_regs *out_ep_regs = dev_if->out_ep_regs[0];
+
+	/* Read the Device Status and Endpoint 0 Control registers */
+	temp = readl(&in_ep_regs->diepctl);
+	temp &= ~MPSMSK0;
+	temp |= DWC_DEP0CTL_MPS_64;
+	writel(temp, &in_ep_regs->diepctl);
+
+	temp = readl(&out_ep_regs->doepctl);
+	/* Enable OUT EP for receive */
+	temp |= EPENA;
+	writel(temp, &out_ep_regs->doepctl);
+}
+
+/*
+ * Read the device status register and set the device speed in the
+ * data structure.
+ * Set up EP0 to receive SETUP packets by calling dwc_ep0_activate.
+ */
+static int dwc_otg_pcd_handle_enum_done_intr(void)
+{
+	u32 gusbcfg;
+	struct core_global_regs *global_regs = dev_if->core_global_regs;
+	dwc_otg_ep0_activate();
+
+	gusbcfg = readl(&global_regs->gusbcfg);
+	gusbcfg &= ~USBTRDTIMMSK;
+	gusbcfg |= PHYIF_16BIT;
+	gusbcfg |= (9 << USBTRDTIM_SHIFT);
+	writel(gusbcfg, &global_regs->gusbcfg);
+	/* Clear interrupt */
+	writel(ENUMDONE, &global_regs->gintsts);
+
+	return 1;
+}
+
+static u32 dwc_otg_read_core_intr(void)
+{
+	return readl(&dev_if->core_global_regs->gintsts) &
+		readl(&dev_if->core_global_regs->gintmsk);
+}
+
+static void dwc_otg_init(const void *reg_base)
+{
+	struct dwc_pcd *pcd = &dev_if->pcd;
+	u32 offset;
+	u32 i;
+
+	dev_if->core_global_regs = (struct core_global_regs *) reg_base;
+	dev_if->dev_global_regs = (struct device_global_regs *) ((u32)reg_base +
+			DWC_DEV_GLOBAL_REG_OFFSET);
+
+	for (i = 0; i < MAX_EPS_CHANNELS; i++) {
+		offset = i * DWC_EP_REG_OFFSET;
+
+		dev_if->in_ep_regs[i] = (struct device_in_ep_regs *)
+			((u32)reg_base + DWC_DEV_IN_EP_REG_OFFSET + offset);
+
+		dev_if->out_ep_regs[i] = (struct device_out_ep_regs *)
+			((u32)reg_base + DWC_DEV_OUT_EP_REG_OFFSET + offset);
+	}
+
+	for (i = 0; i < MAX_EPS_CHANNELS; i++) {
+		dev_if->data_fifo[i] =
+			(u32 *) ((u32)reg_base + DWC_OTG_DATA_FIFO_OFFSET +
+					(i * DWC_OTG_DATA_FIFO_SIZE));
+	}
+
+	dev_if->speed = 0;	/* unknown */
+	for (i = 0; i < MAX_EPS_CHANNELS; i++) {
+		pcd->in_ep[i].num = i;
+		pcd->out_ep[i].num = i;
+	}
+}
+
+/*
+ * This function initializes the DWC_otg controller registers and prepares the
+ * core for device mode
+ */
+static void dwc_otg_core_init(void)
+{
+	struct core_global_regs *global_regs = dev_if->core_global_regs;
+	u32 ahbcfg, gintmsk, usbcfg;
+	/* Step 1: Program the GAHBCFG Register. */
+	ahbcfg = DWC_NPTXEMPTYLVL_EMPTY | DWC_PTXEMPTYLVL_EMPTY;
+	writel(ahbcfg, &global_regs->gahbcfg);
+
+	/* Step 2: write usbcfg regs*/
+	usbcfg = readl(&global_regs->gusbcfg);
+	usbcfg |= SRPCAP | HNPCAP;
+	writel(usbcfg, &global_regs->gusbcfg);
+
+	/* step3: write int_msk reg*/
+	gintmsk = USBRESET | ENUMDONE | RXSTSQLVL | OUTEPINTR | INEPINTR;
+	writel(gintmsk, &global_regs->gintmsk);
+}
+
+/* Switch on the UDC */
+static void usbotg_init(void)
+{
+	udc_device = NULL;
+	dwc_otg_init((void *)CONFIG_SYS_USBD_BASE);
+
+	/* Initialize the DWC_otg core.	*/
+	dwc_otg_core_init();
+
+}
+
+void udc_irq(void)
+{
+	u32 status;
+
+	status = dwc_otg_read_core_intr();
+	while (status) {
+		if (status & USBRESET)
+			dwc_otg_pcd_handle_usb_reset_intr();
+		if (status & ENUMDONE)
+			dwc_otg_pcd_handle_enum_done_intr();
+		if (status & RXSTSQLVL)
+			dwc_otg_pcd_handle_rx_status_q_level_intr();
+		if (status & OUTEPINTR)
+			dwc_otg_pcd_handle_out_ep_intr();
+		if (status & INEPINTR)
+			dwc_otg_pcd_handle_in_ep_intr();
+		status = dwc_otg_read_core_intr();
+	}
+
+}
+
+void udc_set_nak(int epid)
+{
+	writel(readl(&dev_if->out_ep_regs[epid]->doepctl) | SNAK,
+			&dev_if->out_ep_regs[epid]->doepctl);
+	writel(readl(&dev_if->in_ep_regs[epid]->diepctl) | SNAK,
+			&dev_if->in_ep_regs[epid]->diepctl);
+}
+
+void udc_unset_nak(int epid)
+{
+	writel(readl(&dev_if->out_ep_regs[epid]->doepctl) | CNAK,
+			&dev_if->out_ep_regs[epid]->doepctl);
+	writel(readl(&dev_if->in_ep_regs[epid]->diepctl) | CNAK,
+			&dev_if->in_ep_regs[epid]->diepctl);
+}
+
+int udc_endpoint_write(struct usb_endpoint_instance *endpoint)
+{
+	udc_unset_nak(endpoint->endpoint_address & USB_ENDPOINT_NUMBER_MASK);
+	return 0;
+}
+
+static void udc_enable(struct usb_device_instance *device)
+{
+	struct dwc_pcd *pcd = &dev_if->pcd;
+
+	UDCDBGA("enable device %p, status %d", device, device->status);
+
+	/* Save the device structure pointer */
+	udc_device = device;
+
+	/* Setup ep0 urb */
+	if (!ep0_urb) {
+		ep0_urb =
+			usbd_alloc_urb(udc_device,
+					udc_device->bus->endpoint_array);
+		pcd->req =
+			(struct usb_device_request *)&ep0_urb->device_request;
+		pcd->ep0.xfer_buff = (u8 *)ep0_urb->buffer;
+	} else {
+		serial_printf("udc_enable: ep0_urb already allocated %p\n",
+				ep0_urb);
+	}
+}
+
+void udc_connect(void)
+{
+	struct device_global_regs *dev_regs = dev_if->dev_global_regs;
+	u32 dcfg;
+
+	/* remove soft disconnect */
+	dcfg = readl(&dev_regs->dctl);
+	dcfg &= ~SFTDISCON;
+	writel(dcfg, &dev_regs->dctl);
+}
+
+void udc_disconnect(void)
+{
+	struct device_global_regs *dev_regs = dev_if->dev_global_regs;
+	u32 dcfg;
+
+	/* soft disconnect */
+	dcfg = readl(&dev_regs->dctl);
+	dcfg |= SFTDISCON;
+	writel(dcfg, &dev_regs->dctl);
+	udelay(150);
+}
+
+void udc_startup_events(struct usb_device_instance *device)
+{
+	/* The DEVICE_INIT event puts the USB device in the state STATE_INIT. */
+	usbd_device_event_irq(device, DEVICE_INIT, 0);
+
+	/*
+	 * The DEVICE_CREATE event puts the USB device in the state
+	 * STATE_ATTACHED.
+	 */
+	usbd_device_event_irq(device, DEVICE_CREATE, 0);
+
+	/*
+	 * Some USB controller driver implementations signal
+	 * DEVICE_HUB_CONFIGURED and DEVICE_RESET events here.
+	 * DEVICE_HUB_CONFIGURED causes a transition to the state STATE_POWERED,
+	 * and DEVICE_RESET causes a transition to the state STATE_DEFAULT.
+	 * The DW USB client controller has the capability to detect when the
+	 * USB cable is connected to a powered USB bus, so we will defer the
+	 * DEVICE_HUB_CONFIGURED and DEVICE_RESET events until later.
+	 */
+
+	udc_enable(device);
+
+}
+
+void udc_setup_ep(struct usb_device_instance *device, unsigned int ep,
+		struct usb_endpoint_instance *endpoint)
+{
+	/*
+	 * Nothing to do here. Hob of this function has laready been
+	 * done during init.
+	 */
+}
+
+int is_usbd_high_speed(void)
+{
+	struct device_global_regs *dev_regs = dev_if->dev_global_regs;
+	u32 dsts;
+
+	dsts = readl(&dev_regs->dsts);
+	dsts &= ENUMSPDMSK;
+	if (dsts == DWC_DSTS_ENUMSPD_HS_PHY_30MHZ_OR_60MHZ)
+		return 1;
+	else
+		return 0;
+}
+
+int udc_init(void)
+{
+#if defined(CONFIG_DW_OTG_PHYINIT)
+	udc_phy_init();
+#endif
+	udc_disconnect();
+	usbotg_init();
+	return 0;
+}
diff --git a/include/usb/designware_otg.h b/include/usb/designware_otg.h
new file mode 100644
index 0000000..98d016e
--- /dev/null
+++ b/include/usb/designware_otg.h
@@ -0,0 +1,500 @@
+/*
+ * (C) Copyright 2011
+ * Pratyush Anand, ST Micoelectronics, pratyush.anand@st.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
+ */
+
+#ifndef __DW_OTG_H
+#define __DW_OTG_H
+
+#include "usbdevice.h"
+
+/* USBTTY definitions */
+#define  EP0_MAX_PACKET_SIZE		64
+#define  UDC_INT_ENDPOINT		1
+#define  UDC_INT_PACKET_SIZE		64
+#define  UDC_OUT_ENDPOINT		2
+#define  UDC_BULK_PACKET_SIZE		512
+#if defined(CONFIG_USBD_HS)
+#define  UDC_BULK_HS_PACKET_SIZE	512
+#endif
+#define  UDC_IN_ENDPOINT		3
+#define  UDC_OUT_PACKET_SIZE		64
+#define  UDC_IN_PACKET_SIZE		64
+
+/* UDC endpoint definitions */
+#define  UDC_EP0			0
+#define  UDC_EP1			1
+#define  UDC_EP2			2
+#define  UDC_EP3			3
+
+/* OTG Register Definitions */
+
+/*
+ * The application interfaces with the HS OTG core by reading from and
+ * writing to the Control and Status Register (CSR) space through the
+ * AHB Slave interface. These registers are 32 bits wide, and the
+ * addresses are 32-bit-block aligned.
+ * CSRs are classified as follows:
+ * - Core Global Registers
+ * - Device Mode Registers
+ * - Device Global Registers
+ * - Device Endpoint Specific Registers
+ * - Host Mode Registers
+ * - Host Global Registers
+ * - Host Port CSRs
+ * - Host Channel Specific Registers
+ *
+ * Only the Core Global registers can be accessed in both Device and
+ * Host modes. When the HS OTG core is operating in one mode, either
+ * Device or Host, the application must not access registers from the
+ * other mode. When the core switches from one mode to another, the
+ * registers in the new mode of operation must be reprogrammed as they
+ * would be after a power-on reset.
+ */
+
+/*
+ * DWC_otg Core registers. The core_global_regs structure defines the
+ * size and relative field offsets for the Core Global registers.
+ */
+struct core_global_regs {
+	/* OTG Control and Status Register.		Offset: 000h */
+	u32 gotgctl;
+	/* OTG Interrupt Register.			Offset: 004h */
+	u32 gotgint;
+	/* Core AHB Configuration Register.		Offset: 008h */
+	u32 gahbcfg;
+
+#define DWC_GLBINTRMASK				0x0001
+#define DWC_DMAENABLE				0x0020
+#define DWC_NPTXEMPTYLVL_EMPTY			0x0080
+#define DWC_NPTXEMPTYLVL_HALFEMPTY		0x0000
+#define DWC_PTXEMPTYLVL_EMPTY			0x0100
+#define DWC_PTXEMPTYLVL_HALFEMPTY		0x0000
+
+	/* Core USB Configuration Register.		Offset: 00Ch */
+	u32 gusbcfg;
+#define PHYIF_16BIT				(1 << 3)
+#define SRPCAP					(1 << 8)
+#define HNPCAP					(1 << 9)
+#define TERM_SEL_DL_PULSE			(1 << 22)
+#define USBTRDTIM_SHIFT				10
+#define USBTRDTIMMSK				(0xF << USBTRDTIM_SHIFT)
+	/* Core Reset Register.				Offset: 010h */
+	u32 grstctl;
+#define DWC_GRSTCTL_TXFNUM_ALL			0x10
+#define CSFTRST					(1 << 0)
+#define INTKNQFLSH				(1 << 3)
+#define RXFFLSH					(1 << 4)
+#define	TXFFLSH					(1 << 5)
+#define TXFNUM_SHIFT				6
+#define TXFNUM					(0x1F << TXFNUM_SHIFT)
+#define AHBIDLE					((u32)1 << 31)
+	/* Core Interrupt Register.			Offset: 014h */
+	u32 gintsts;
+#define RXSTSQLVL				(1 << 4)
+#define NPTXFEMPTY				(1 << 5)
+#define GOUTNAKEFF				(1 << 7)
+#define USBRESET				(1 << 12)
+#define ENUMDONE				(1 << 13)
+#define INEPINTR				(1 << 18)
+#define OUTEPINTR				(1 << 19)
+	/* Core Interrupt Mask Register.		Offset: 018h */
+	u32 gintmsk;
+	/*
+	 * Receive Status Queue Read Register
+	 * (Read Only)					Offset: 01Ch
+	 */
+	u32 grxstsr;
+	/*
+	 * Receive Status Queue Read & POP Register
+	 * (Read Only)					Offset: 020h
+	 */
+	u32 grxstsp;
+#define DWC_STS_DATA_UPDT		0x2 /* OUT Data Packet */
+#define DWC_STS_XFER_COMP		0x3 /* OUT Data Transfer Complete */
+#define DWC_DSTS_GOUT_NAK		0x1 /* Global OUT NAK */
+#define DWC_DSTS_SETUP_COMP		0x4 /* Setup Phase Complete */
+#define DWC_DSTS_SETUP_UPDT		0x6 /* SETUP Packet */
+#define EPNUM_SHIFT					0
+#define EPNUMMSK					(0xF << EPNUM_SHIFT)
+#define BCNT_SHIFT					4
+#define BCNTMSK						(0x7FF << BCNT_SHIFT)
+#define PKTSTS_SHIFT					17
+#define PKTSTSMSK					(0xF << PKTSTS_SHIFT)
+	/* Receive FIFO Size Register.			Offset: 024h */
+	u32 grxfsiz;
+#define dwc_param_dev_rx_fifo_size_default		1064
+	/* Non Periodic Transmit FIFO Size Register.	Offset: 028h */
+	u32 gnptxfsiz;
+#define dwc_param_dev_nperio_tx_fifo_size_default	1024
+	/*
+	 * Non Periodic Transmit FIFO/Queue Status Register
+	 * (Read Only).					Offset: 02Ch
+	 */
+	u32 gnptxsts;
+#define NPTXQSPCAVAIL_SHIFT			16
+#define NPTXQSPCAVAILMSK			(0xFF << NPTXQSPCAVAIL_SHIFT)
+#define NPTXFSPCAVAIL_SHIFT			0
+#define NPTXFSPCAVAILMSK			(0xFFFF << NPTXFSPCAVAIL_SHIFT)
+	/* I2C Access Register.				Offset: 030h */
+	u32 gi2cctl;
+	/* PHY Vendor Control Register.			Offset: 034h */
+	u32 gpvndctl;
+	/* General Purpose Input/Output Register.	Offset: 038h */
+	u32 ggpio;
+	/* User ID Register.				Offset: 03Ch */
+	u32 guid;
+	/* Synopsys ID Register (Read Only).		Offset: 040h */
+	u32 gsnpsid;
+	/* User HW Config1 Register (Read Only).	Offset: 044h */
+	u32 ghwcfg1;
+	/* User HW Config2 Register (Read Only).	Offset: 048h */
+
+	u32 ghwcfg2;
+#define DWC_SLAVE_ONLY_ARCH			0
+#define DWC_EXT_DMA_ARCH			1
+#define DWC_INT_DMA_ARCH			2
+
+#define DWC_MODE_HNP_SRP_CAPABLE		0
+#define DWC_MODE_SRP_ONLY_CAPABLE		1
+#define DWC_MODE_NO_HNP_SRP_CAPABLE		2
+#define DWC_MODE_SRP_CAPABLE_DEVICE		3
+#define DWC_MODE_NO_SRP_CAPABLE_DEVICE		4
+#define DWC_MODE_SRP_CAPABLE_HOST		5
+#define DWC_MODE_NO_SRP_CAPABLE_HOST		6
+#define DYNAMIC_FIFO				(1 << 19)
+#define	NUM_DEV_EP_SHIFT	10
+#define	NUM_DEV_EP	(0xF << NUM_DEV_EP_SHIFT)
+#define HSPHYTYPE_SHIFT				6
+#define HSPHYTYPEMSK				(3 << HSPHYTYPE_SHIFT)
+#define DWC_HWCFG2_HS_PHY_TYPE_NOT_SUPPORTED		0
+#define DWC_HWCFG2_HS_PHY_TYPE_UTMI			1
+#define DWC_HWCFG2_HS_PHY_TYPE_ULPI			2
+#define DWC_HWCFG2_HS_PHY_TYPE_UTMI_ULPI		3
+#define TKNQDEPTH_SHIFT					26
+#define TKNQDEPTHMSK				(0x1F << TKNQDEPTH_SHIFT)
+
+	/* User HW Config3 Register (Read Only).	Offset: 04Ch */
+	u32 ghwcfg3;
+#define	DFIFO_DEPTH_SHIFT	16
+#define DFIFO_DEPTH	((u32)0xFFFF << DFIFO_DEPTH_SHIFT)
+	/* User HW Config4 Register (Read Only).	Offset: 050h */
+	u32 ghwcfg4;
+#define NUM_DEV_PERIO_IN_EP_SHIFT	0
+#define NUM_DEV_PERIO_IN_EP (0xF << NUM_DEV_PERIO_IN_EP_SHIFT)
+#define DED_FIFO_EN	(1 << 25)
+#define NUM_IN_EPS_SHIFT	26
+#define NUM_IN_EPS	(0xF << NUM_IN_EPS_SHIFT)
+#define UTMI_PHY_DATA_WIDTH_SHIFT	14
+#define UTMI_PHY_DATA_WIDTH	(0x3 << UTMI_PHY_DATA_WIDTH_SHIFT)
+	/* Reserved					Offset: 054h-0FFh */
+	u32 reserved[43];
+	/* Host Periodic Transmit FIFO Size Register.	Offset: 100h */
+	u32 hptxfsiz;
+
+	/*
+	 * Device Periodic Transmit FIFO#n Register, if dedicated fifos are
+	 * disabled. Otherwise Device Transmit FIFO#n Register.
+	 *
+	 * Offset: 104h + (FIFO_Number-1)*04h, 1 <= FIFO Number <= 15 (1<=n<=15)
+	 */
+	u32 dptxfsiz_dieptxf[15];
+#define dwc_param_dev_tx_fifo_size_default	256
+#define dwc_param_dev_perio_tx_fifo_size_default	256
+};
+
+/*
+ * Device Global Registers. Offsets 800h-BFFh
+ *
+ * The following structures define the size and relative field offsets for the
+ * Device Mode Registers.
+ *
+ * These registers are visible only in Device mode and must not be accessed in
+ * Host mode, as the results are unknown.
+ */
+struct device_global_regs {		/* CONFIG_DWC_OTG_REG_LE */
+	/* Device Configuration Register.			Offset: 800h */
+	u32 dcfg;
+#define DWC_DCFG_FRAME_INTERVAL_80		0
+#define DWC_DCFG_FRAME_INTERVAL_85		1
+#define DWC_DCFG_FRAME_INTERVAL_90		2
+#define DWC_DCFG_FRAME_INTERVAL_95		3
+#define DWC_DCFG_FRAME_INTERVAL_MASK		3
+#define	PERFRINT_SHIFT				11
+#define DEVSPDMSK				(0x3 << 0)
+#define DEVADDR_SHIFT				4
+#define DEVADDRMSK				(0x7F << DEVADDR_SHIFT)
+#define NZSTSOUTHSHK				(1 << 2)
+	/* Device Control Register.				Offset: 804h */
+	u32 dctl;
+#define RMTWKUPSIG	(1 << 0)
+#define SFTDISCON	(1 << 1)
+#define CGNPINNAK	(1 << 7)
+	/* Device Status Register (Read Only).			Offset: 808h */
+	u32 dsts;
+#define ENUMSPD_SHIFT				1
+#define ENUMSPDMSK				(3 << ENUMSPD_SHIFT)
+#define DWC_DSTS_ENUMSPD_HS_PHY_30MHZ_OR_60MHZ		0
+#define DWC_DSTS_ENUMSPD_FS_PHY_30MHZ_OR_60MHZ		1
+#define DWC_DSTS_ENUMSPD_LS_PHY_6MHZ			2
+#define DWC_DSTS_ENUMSPD_FS_PHY_48MHZ			3
+	/* Reserved.						Offset: 80Ch */
+	u32 unused;
+	/* Device IN Endpoint Common Interrupt Mask Register.	Offset: 810h */
+	u32 diepmsk;
+#define TIMEOUTMSK				(1 << 3)
+#define INTKNTXFEMP				(1 << 4)
+#define INTKNEPMISMSK				(1 << 5)
+#define INEPNAKEFFMSK				(1 << 6)
+#define TXFIFOUNDRN				(1 << 8)
+	/* Device OUT Endpoint Common Interrupt Mask Register.	Offset: 814h */
+	u32 doepmsk;
+#define XFERCOMPLMSK				(1 << 0)
+#define EPDISABLEDMSK				(1 << 1)
+#define AHBERRMSK				(1 << 2)
+#define SETUPMSK				(1 << 3)
+#define INTKNTXFEMPMSK				(1 << 4)
+	/* Device All Endpoints Interrupt Register.		Offset: 818h */
+	u32 daint;
+	/* Device All Endpoints Interrupt Mask Register.	Offset: 81Ch */
+	u32 daintmsk;
+#define DAINTMASK_IN_SHIFT	0
+#define DAINTMASK_OUT_SHIFT	16
+	/* Device IN Token Queue Read Register-1 (Read Only).	Offset: 820h */
+	u32 dtknqr1;
+#define EPTK0_5_SHIFT				8
+#define EPTK0_5MSK				((u32)0xFFFFFF << EPTK0_5_SHIFT)
+#define INTKNWPTR_SHIFT				0
+#define INTKNWPTRMSK				((u32)0x1F << INTKNWPTR_SHIFT)
+	/* Device IN Token Queue Read Register-2 (Read Only).	Offset: 824h */
+	u32 dtknqr2;
+	/* Device VBUS discharge Register.			Offset: 828h */
+	u32 dvbusdis;
+	/* Device VBUS Pulse Register.				Offset: 82Ch */
+	u32 dvbuspulse;
+	/* Device IN Token Queue Read Register-3 (Read Only).	Offset: 830h */
+	u32 dtknqr3_dthrctl;
+	/* Device IN Token Queue Read Register-4 (Read Only).	Offset: 834h */
+	u32 dtknqr4_fifoemptymsk;
+};
+/*
+ * Device Logical IN Endpoint-Specific Registers. Offsets 900h-AFCh
+ *
+ * There will be one set of endpoint registers per logical endpoint implemented.
+ *
+ * These registers are visible only in Device mode and must not be accessed in
+ * Host mode, as the results are unknown.
+ */
+struct device_in_ep_regs {
+	/*
+	 * Device IN Endpoint Control Register.
+	 * Offset:900h + (ep_num * 20h) + 00h
+	 */
+	u32 diepctl;
+#define	EPENA				((u32)1 << 31)
+#define EPDIS				(1 << 30)
+#define	SNAK				(1 << 27)
+#define	CNAK				(1 << 26)
+#define	SSTALL				(1 << 21)
+#define MPS_SHIFT			0
+#define MPSMSK0				(3 << MPS_SHIFT)
+#define DWC_DEP0CTL_MPS_64			0
+#define DWC_DEP0CTL_MPS_32			1
+#define DWC_DEP0CTL_MPS_16			2
+#define DWC_DEP0CTL_MPS_8			3
+#define DIEPCTL_MPSMSK				(0x7FF << MPS_SHIFT)
+	/* Reserved. Offset:900h + (ep_num * 20h) + 04h */
+	u32 reserved04;
+	/*
+	 * Device IN Endpoint Interrupt Register.
+	 * Offset:900h + (ep_num * 20h) + 08h
+	 */
+	u32 diepint;
+#define TXFEMP				(1 << 7)
+#define INTKNTXFEMP			(1 << 4)
+#define XFERCOMPL			(1 << 0)
+	/* Reserved. Offset:900h + (ep_num * 20h) + 0Ch */
+	u32 reserved0C;
+	/* Device IN Endpoint Transfer Size Register.
+	 * Offset:900h + (ep_num * 20h) + 10h
+	 */
+	u32 dieptsiz;
+#define PKTCNT_SHIFT	19
+	/*
+	 * Device IN Endpoint DMA Address Register.
+	 * Offset:900h + (ep_num * 20h) + 14h
+	 */
+	u32 diepdma;
+	/* Reserved.
+	 * Offset:900h + (ep_num * 20h) + 18h - 900h + (ep_num * 20h) + 1Ch
+	 */
+	u32 dtxfsts;
+	/*
+	 * Reserved.
+	 * Offset:900h + (ep_num * 20h) + 1Ch - 900h + (ep_num * 20h) + 1Ch
+	 */
+	u32 reserved18;
+};
+
+/*
+ * Device Logical OUT Endpoint-Specific Registers. Offsets: B00h-CFCh
+ *
+ * There will be one set of endpoint registers per logical endpoint implemented.
+ *
+ * These registers are visible only in Device mode and must not be accessed in
+ * Host mode, as the results are unknown.
+ */
+struct device_out_ep_regs {
+	/*
+	 * Device OUT Endpoint Control Register.
+	 * Offset:B00h + (ep_num * 20h) + 00h
+	 */
+	u32 doepctl;
+#define DOEPCTL_MPSMSK		0x7FF
+#define USBACTEP		(1 << 15)
+#define EPTYPE_SHIFT		18
+#define EPTYPEMSK		(0x3 << EPTYPE_SHIFT)
+#define EPTYPE_BULK		0x2
+#define EPTYPE_INT		0x3
+#define DATA0PID		(1 << 28)
+#define DATA1PID		(1 << 29)
+#define DPIDMSK			(1 << 16)
+	/*
+	 * Device OUT Endpoint Frame number Register.
+	 * Offset: B00h + (ep_num * 20h) + 04h
+	 */
+	u32 doepfn;
+	/*
+	 * Device OUT Endpoint Interrupt Register.
+	 * Offset:B00h + (ep_num * 20h) + 08h
+	 */
+	u32 doepint;
+#define XFERCOMPL			(1 << 0)
+#define EPDISBLD			(1 << 1)
+#define AHBERR				(1 << 2)
+#define SETUP				(1 << 3)
+	/* Reserved. Offset:B00h + (ep_num * 20h) + 0Ch */
+	u32 reserved0C;
+	/*
+	 * Device OUT Endpoint Transfer Size Register.
+	 * Offset: B00h + (ep_num * 20h) + 10h
+	 */
+	u32 doeptsiz;
+#define XFERSIZE_SHIFT			0
+#define XFERSIZEMSK			0x3F
+#define PKTCNT_SHIFT			19
+#define PKTCNT				(3 << 19)
+#define SUPCNT_SHIFT			29
+#define SUPCNTMSK			(3 << SUPCNT_SHIFT)
+	/*
+	 * Device OUT Endpoint DMA Address Register.
+	 * Offset:B00h + (ep_num * 20h) + 14h
+	 */
+	u32 doepdma;
+	/*
+	 * Reserved.
+	 * Offset:B00h + (ep_num * 20h) + 18h - B00h + (ep_num * 20h) + 1Ch
+	 */
+	u32 unused[2];
+};
+#define MAX_EPS_CHANNELS 4
+
+/*
+ * The dwc_ep structure represents the state of a single endpoint when acting in
+ * device mode. It contains the data items needed for an endpoint to be
+ * activated and transfer packets.
+ */
+struct dwc_ep {
+	/* EP number used for register address lookup */
+	u8	 num;
+	/* pointer to the transfer buffer */
+	u8 *xfer_buff;
+	/* Number of bytes to transfer */
+	u32 xfer_len;
+};
+
+/*
+ * DWC_otg PCD Structure.
+ * This structure encapsulates the data for the dwc_otg PCD.
+ */
+struct dwc_pcd {
+	struct usb_device_request *req;
+	/* Array of EPs. */
+	struct dwc_ep ep0;
+	/* Array of IN EPs. */
+	struct dwc_ep in_ep[MAX_EPS_CHANNELS];
+	/* Array of OUT EPs. */
+	struct dwc_ep out_ep[MAX_EPS_CHANNELS];
+};
+
+/*
+ * The device_if structure contains information needed to manage the DWC_otg
+ * controller acting in device mode. It represents the programming view of the
+ * device-specific aspects of the controller.
+ */
+struct device_if {
+	struct core_global_regs *core_global_regs;
+	/* Common configuration information */
+
+	/* Device Global Registers starting at offset 800h */
+	struct device_global_regs *dev_global_regs;
+#define DWC_DEV_GLOBAL_REG_OFFSET		0x800
+
+	/* Device Logical IN Endpoint-Specific Registers 900h-AFCh */
+	struct device_in_ep_regs *in_ep_regs[MAX_EPS_CHANNELS];
+#define DWC_DEV_IN_EP_REG_OFFSET		0x900
+#define DWC_EP_REG_OFFSET			0x20
+
+	/* Device Logical OUT Endpoint-Specific Registers B00h-CFCh */
+	struct device_out_ep_regs *out_ep_regs[MAX_EPS_CHANNELS];
+#define DWC_DEV_OUT_EP_REG_OFFSET		0xB00
+
+	/* Push/pop addresses for endpoints or host channels.*/
+	u32 *data_fifo[MAX_EPS_CHANNELS];
+#define DWC_OTG_DATA_FIFO_OFFSET		0x1000
+#define DWC_OTG_DATA_FIFO_SIZE			0x1000
+
+	struct dwc_pcd pcd;
+	int speed;
+};
+
+
+/* Function declarations */
+
+void phy_init(void);
+void udc_irq(void);
+
+void udc_set_nak(int epid);
+void udc_unset_nak(int epid);
+int udc_endpoint_write(struct usb_endpoint_instance *endpoint);
+int udc_init(void);
+/* void udc_enable(struct usb_device_instance *device);*/
+void udc_disable(void);
+void udc_connect(void);
+void udc_disconnect(void);
+#if defined(CONFIG_DW_OTG_PHYINIT)
+void udc_phy_init(void);
+#endif
+void udc_startup_events(struct usb_device_instance *device);
+void udc_setup_ep(struct usb_device_instance *device, unsigned int ep,
+		  struct usb_endpoint_instance *endpoint);
+
+#endif /* __DW_OTG_H */
