From: Masayuki Ohtake <masa-korg@dsn.okisemi.com>
Subject: OKI Semiconductor PCH USB Gadget driver

This driver implements PCH Gadget controls for PCH.

Signed-off-by: Masayuki Ohtake <masa-korg@dsn.okisemi.com>
Acked-by: Wang Qi <qi.wang@intel.com>

---
 drivers/usb/gadget/gadget_chips.h              | 8 ++
 drivers/usb/gadget/Kconfig                     | 16
 drivers/usb/gadget/Makefile                    | 6
 drivers/usb/gadget/pch_common.h                | 146
 drivers/usb/gadget/pch_debug.h                 | 160
 drivers/usb/gadget/pch_udc.c                   | 2530
 drivers/usb/gadget/pch_udc.h                   | 172
 drivers/usb/gadget/pch_udc_hal.c               | 1110
 drivers/usb/gadget/pch_udc_hal.h               | 1829
 drivers/usb/gadget/pch_udc_intr.c              | 396
 drivers/usb/gadget/pch_udc_pci.c               | 549
 drivers/usb/gadget/pch_udc_pci.h               | 97
+++++++++++++++++++++++++++++++ 12 files changed, zz insertions(+)
---
 drivers/usb/gadget/Kconfig        |   16 
 drivers/usb/gadget/Makefile       |    6 
 drivers/usb/gadget/gadget_chips.h |   12 
 drivers/usb/gadget/pch_common.h   |  146 ++
 drivers/usb/gadget/pch_debug.h    |   60 
 drivers/usb/gadget/pch_udc.c      | 2530 ++++++++++++++++++++++++++++++++++++++
 drivers/usb/gadget/pch_udc.h      |  172 ++
 drivers/usb/gadget/pch_udc_hal.c  | 1110 ++++++++++++++++
 drivers/usb/gadget/pch_udc_hal.h  | 1829 +++++++++++++++++++++++++++
 drivers/usb/gadget/pch_udc_intr.c |  396 +++++
 drivers/usb/gadget/pch_udc_pci.c  |  549 ++++++++
 drivers/usb/gadget/pch_udc_pci.h  |   97 +
 12 files changed, 6923 insertions(+)

--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -220,6 +220,22 @@ config USB_OTG
 
 	   Select this only if your OMAP board has a Mini-AB connector.
 
+config USB_GADGET_PCH
+	boolean "PCH USB Dev"
+	depends on PCI
+	select USB_GADGET_DUALSPEED
+	help
+	   PCH USB device is a PCI based USB peripheral controller which
+	   supports both full and high speed USB 2.0 data transfers.
+
+config PCH_USBDEV
+	tristate
+	depends on USB_GADGET_PCH
+	default USB_GADGET
+	select USB_GADGET_SELECTED
+
+
+
 config USB_GADGET_PXA25X
 	boolean "PXA 25x or IXP 4xx"
 	depends on (ARCH_PXA && PXA25x) || ARCH_IXP4XX
--- a/drivers/usb/gadget/Makefile
+++ b/drivers/usb/gadget/Makefile
@@ -58,3 +58,9 @@ obj-$(CONFIG_USB_CDC_COMPOSITE) += g_cdc
 obj-$(CONFIG_USB_G_MULTI)	+= g_multi.o
 obj-$(CONFIG_USB_STILL_IMAGE)	+= g_still_image.o
 
+ifeq ($(CONFIG_USB_GADGET_DEBUG),y)
+        EXTRA_CFLAGS += -DDMA_PPB_MODE
+endif
+obj-$(CONFIG_PCH_USBDEV) += pch_usbdev.o
+pch_usbdev-objs := pch_udc_pci.o pch_udc.o pch_udc_hal.o pch_udc_intr.o
+
--- a/drivers/usb/gadget/gadget_chips.h
+++ b/drivers/usb/gadget/gadget_chips.h
@@ -180,6 +180,14 @@
 #endif
 
 
+#ifdef CONFIG_USB_GADGET_PCH
+#define	gadget_is_ioh(g)	(!strcmp("ioh_udc", (g)->name))
+#else
+#define	gadget_is_ioh(g)	0
+#endif
+
+
+
 /**
  * usb_gadget_controller_number - support bcdDevice id convention
  * @gadget: the controller being driven
@@ -247,6 +255,10 @@ static inline int usb_gadget_controller_
 		return 0x24;
 	else if (gadget_is_r8a66597(gadget))
 		return 0x25;
+
+	else if (gadget_is_ioh(gadget))
+		return 0x26;
+
 	return -ENOENT;
 }
 
--- /dev/null
+++ b/drivers/usb/gadget/pch_common.h
@@ -0,0 +1,146 @@
+/*!
+ * @file ioh_common.h
+ * @brief Provides the macro definitions used by all files.
+ * @version 1.0.0.0
+ * @section
+ * 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; version 2 of the License.
+ *
+ * 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.
+ */
+
+/*
+ * History:
+ * Copyright (C) 2008 OKI SEMICONDUCTOR Co., LTD.
+ * All rights reserved.
+ *
+ * created:
+ *	WIPRO 03/07/2009
+ * modified:
+ *	WIPRO 05/08/2009
+ *
+ */
+
+#ifndef __IOH_COMMON_H__
+#define __IOH_COMMON_H__
+
+/*! @ingroup	Global
+@def		    IOH_WRITE8
+@brief			Macro for writing 8 bit data to an io/mem address
+*/
+#define IOH_WRITE8(val, addr)   iowrite8((val), (void __iomem *)(addr))
+/*! @ingroup	Global
+@def		    IOH_LOG
+@brief			Macro for writing 16 bit data to an io/mem address
+*/
+#define IOH_WRITE16(val, addr)  iowrite16((val), (void __iomem *)(addr))
+/*! @ingroup	Global
+@def		    IOH_LOG
+@brief			Macro for writing 32 bit data to an io/mem address
+*/
+#define IOH_WRITE32(val, addr)  iowrite32((val), (void __iomem *)(addr))
+
+/*! @ingroup	Global
+@def		    IOH_READ8
+@brief			Macro for reading 8 bit data from an io/mem address
+*/
+#define IOH_READ8(addr)   ioread8((void __iomem *)(addr))
+/*! @ingroup	Global
+@def		    IOH_READ16
+@brief			Macro for reading 16 bit data from an io/mem address
+*/
+#define IOH_READ16(addr)  ioread16((void __iomem *)(addr))
+/*! @ingroup	Global
+@def		    IOH_READ32
+@brief			Macro for reading 32 bit data from an io/mem address
+*/
+#define IOH_READ32(addr)  ioread32((void __iomem *)(addr))
+/*! @ingroup	Global
+@def		    IOH_WRITE32_F
+@brief			Macro for writing 32 bit data to an io/mem address
+*/
+#define IOH_WRITE32_F(val, addr) do \
+	{ IOH_WRITE32((val), (addr)); (void)IOH_READ32((addr)); } while (0);
+
+/*! @ingroup	Global
+@def		    IOH_WRITE_BYTE
+@brief			Macro for writing 1 byte data to an io/mem address
+*/
+#define IOH_WRITE_BYTE IOH_WRITE8
+/*! @ingroup	Global
+@def		    IOH_WRITE_WORD
+@brief			Macro for writing 1 word data to an io/mem address
+*/
+#define IOH_WRITE_WORD IOH_WRITE16
+/*! @ingroup	Global
+@def		    IOH_WRITE_LONG
+@brief			Macro for writing long data to an io/mem address
+*/
+#define IOH_WRITE_LONG IOH_WRITE32
+
+/*! @ingroup	Global
+@def		    IOH_READ_BYTE
+@brief			Macro for reading 1 byte data from an io/mem address
+*/
+#define IOH_READ_BYTE  IOH_READ8
+/*! @ingroup	Global
+@def		    IOH_READ_WORD
+@brief			Macro for reading 1 word data from an io/mem address
+*/
+#define IOH_READ_WORD  IOH_READ16
+/*! @ingroup	Global
+@def		    IOH_READ_LONG
+@brief			Macro for reading long data from an io/mem address
+*/
+#define IOH_READ_LONG  IOH_READ32
+
+/* Bit Manipulation Macros */
+
+/*! @ingroup	Global
+@def		    IOH_READ_LONG
+@brief			macro to set a specified bit(mask) at the
+			specified address
+*/
+#define IOH_SET_ADDR_BIT(addr, bitmask) IOH_WRITE_LONG((IOH_READ_LONG(addr) |\
+							 (bitmask)), (addr))
+
+/*! @ingroup	Global
+@def	    IOH_READ_LONG
+@brief		macro to clear a specified bit(mask) at the specified address
+*/
+#define IOH_CLR_ADDR_BIT(addr, bitmask) IOH_WRITE_LONG((IOH_READ_LONG(addr) &\
+							 ~(bitmask)), (addr))
+
+/*! @ingroup	Global
+@def		    IOH_READ_LONG
+@brief			macro to set a specified bitmask for a variable
+*/
+#define IOH_SET_BITMSK(var, bitmask) ((var) |= (bitmask))
+
+/*! @ingroup	Global
+@def		    IOH_READ_LONG
+@brief			macro to clear a specified bitmask for a variable
+*/
+#define IOH_CLR_BITMSK(var, bitmask) ((var) &= (~(bitmask)))
+
+/*! @ingroup	Global
+@def		    IOH_READ_LONG
+@brief			macro to set a specified bit for a variable
+*/
+#define IOH_SET_BIT(var, bit) ((var) |= (1<<(bit)))
+
+/*! @ingroup	Global
+@def		    IOH_READ_LONG
+@brief			macro to clear a specified bit for a variable
+*/
+#define IOH_CLR_BIT(var, bit) ((var) &= ~(1<<(bit)))
+
+#endif
--- /dev/null
+++ b/drivers/usb/gadget/pch_debug.h
@@ -0,0 +1,60 @@
+/*!
+ * @file ioh_debug.h
+ * @brief Provides the macro definitions used for debugging.
+ * @version 1.0.0.0
+ * @section
+ * 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; version 2 of the License.
+ *
+ * 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.
+ */
+
+/*
+ * History:
+ * Copyright (C) 2008 OKI SEMICONDUCTOR Co., LTD.
+ * All rights reserved.
+ *
+ * created:
+ *	WIPRO 03/07/2009
+ * modified:
+ *	WIPRO 05/08/2009
+ *
+ */
+
+#ifndef __IOH_DEBUG_H__
+#define __IOH_DEBUG_H__
+
+#ifdef MODULE
+#define IOH_LOG(level, fmt, args...) printk(level "%s:" fmt "\n",\
+						 THIS_MODULE->name, ##args)
+#else
+#define IOH_LOG(level, fmt, args...) printk(level "%s:" fmt "\n" ,\
+							 __FILE__, ##args)
+#endif
+
+
+#ifdef DEBUG
+	#define IOH_DEBUG(fmt, args...) IOH_LOG(KERN_DEBUG, fmt, ##args)
+#else
+	#define IOH_DEBUG(fmt, args...)
+#endif
+
+#ifdef IOH_TRACE_ENABLED
+	#define IOH_TRACE IOH_DEBUG
+#else
+	#define IOH_TRACE(fmt, args...)
+#endif
+
+#define IOH_TRACE_ENTER IOH_TRACE("Enter %s", __func__)
+#define IOH_TRACE_EXIT 	IOH_TRACE("Exit %s", __func__)
+
+
+#endif
--- /dev/null
+++ b/drivers/usb/gadget/pch_udc.c
@@ -0,0 +1,2530 @@
+ /*!
+ *@file ioh_udc.c
+ *@brief This file contains the definitions for IOH UDC driver APIs.
+ *
+ *The IOH UDC is a USB High speed DMA capable USB device controller.
+ *It provides 4 IN and 4 OUT endpoints (control, bulk isochronous or interrupt
+ * type).
+ *
+ *The IOH USB device controller driver provides required interface
+ *to the USB gadget framework for accessing the IOH USB device hardware.
+ *
+ *@version 0.96
+ *
+ *@section
+ *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; version 2 of the License.
+ *
+ *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.
+ */
+
+ /*
+ *History:
+ *Copyright (C) 2009 OKI SEMICONDUCTOR Co., LTD.
+ *All rights reserved.
+ *
+ *created:
+ *  OKI SEMICONDUCTOR 2/26/2010
+ *modified:
+ *
+ */
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/list.h>
+#include <linux/smp_lock.h>
+#include <linux/device.h>
+#include <linux/pci.h>
+#include <linux/usb/ch9.h>
+#include <linux/usb/gadget.h>
+
+#include "pch_common.h"
+#include "pch_debug.h"
+
+#include "pch_udc_hal.h"
+#include "pch_udc.h"
+
+#if 0	/* statis as static */
+#define static
+#endif
+
+/* stall spin lock */
+static DEFINE_SPINLOCK(udc_stall_spinlock);
+
+/* function prototypes */
+static int ioh_udc_pcd_get_frame(struct usb_gadget *gadget);
+static int ioh_udc_pcd_wakeup(struct usb_gadget *gadget);
+static int ioh_udc_pcd_selfpowered(struct usb_gadget *gadget, int value);
+static int ioh_udc_pcd_pullup(struct usb_gadget *gadget, int is_on);
+static int ioh_udc_pcd_vbus_session(struct usb_gadget *gadget, int is_active);
+static int ioh_udc_pcd_vbus_draw(struct usb_gadget *gadget, unsigned int mA);
+static void ioh_udc_pcd_reinit(struct ioh_udc_dev *dev);
+static void complete_req(struct ioh_udc_ep *ep, struct ioh_udc_request *req,
+								int status);
+static int ioh_udc_pcd_ep_enable(struct usb_ep *usbep,
+				 const struct usb_endpoint_descriptor *desc);
+static int ioh_udc_pcd_ep_disable(struct usb_ep *usbep);
+static struct usb_request *ioh_udc_alloc_request(struct usb_ep *uep, gfp_t gfp);
+static int ioh_udc_free_dma_chain(struct ioh_udc_dev *dev,
+						 struct ioh_udc_request *req);
+static int ioh_udc_create_dma_chain(struct ioh_udc_ep *ep,
+				 struct ioh_udc_request *req,
+				 unsigned long buf_len, gfp_t gfp_flags);
+static void ioh_udc_free_request(struct usb_ep *uep, struct usb_request *req);
+static int prepare_dma(struct ioh_udc_ep *ep,
+				 struct ioh_udc_request *req, gfp_t gfp);
+static void process_zlp(struct ioh_udc_ep *ep, struct ioh_udc_request *req);
+static int ioh_udc_pcd_queue(struct usb_ep *usbep, struct usb_request *usbreq,
+				 gfp_t gfp);
+static int ioh_udc_pcd_dequeue(struct usb_ep *usbep,
+				 struct usb_request *usbreq);
+static int ioh_udc_pcd_set_halt(struct usb_ep *usbep, int halt);
+static int ioh_udc_pcd_set_wedge(struct usb_ep *usbep);
+static void ioh_udc_pcd_fifo_flush(struct usb_ep *usbep);
+static void ioh_udc_svc_data_out(struct ioh_udc_dev *dev, int ep_num);
+static void ioh_udc_svc_control_in(struct ioh_udc_dev *dev);
+static void ioh_udc_svc_control_out(struct ioh_udc_dev *dev);
+static void ioh_udc_svc_data_in(struct ioh_udc_dev *dev, int ep_num);
+static void ioh_udc_read_all_epstatus(struct ioh_udc_dev *dev, u32 ep_intr);
+static void ioh_udc_setup_ep0(struct ioh_udc_dev *dev);
+static void ioh_udc_init_setup_buff(struct ioh_udc_stp_dma_desc *td_stp);
+static void ioh_udc_complete_transfer(struct ioh_udc_ep	*ep);
+static void ioh_udc_complete_receiver(struct ioh_udc_ep	*ep);
+static void ioh_udc_start_next_txrequest(struct ioh_udc_ep	*ep);
+static void ioh_udc_start_rxrequest(struct ioh_udc_ep *ep,
+					 struct ioh_udc_request *req);
+static void ioh_udc_postsvc_epinters(struct ioh_udc_dev *dev, int ep_num);
+
+/* gadget operations */
+/*!@ingroup	UDC_InterfaceLayer
+ *@struct	ioh_udc_ops
+ *@brief	specifies gadget operations possible
+ */
+const struct usb_gadget_ops ioh_udc_ops = {
+	.get_frame		= ioh_udc_pcd_get_frame,
+	.wakeup			= ioh_udc_pcd_wakeup,
+	.set_selfpowered = ioh_udc_pcd_selfpowered,
+	.pullup			= ioh_udc_pcd_pullup,
+	.vbus_session	= ioh_udc_pcd_vbus_session,
+	.vbus_draw		= ioh_udc_pcd_vbus_draw,
+};
+
+
+/* endpoint interface */
+/*!@ingroup	UDC_InterfaceLayer
+ *@struct	usb_ep_ops ioh_udc_ep_ops
+ *@brief	specifies endpoint operations possible
+ */
+static const struct usb_ep_ops ioh_udc_ep_ops = {
+	.enable			= ioh_udc_pcd_ep_enable,
+	.disable		= ioh_udc_pcd_ep_disable,
+	.alloc_request	= ioh_udc_alloc_request,
+	.free_request	= ioh_udc_free_request,
+	.queue			= ioh_udc_pcd_queue,
+	.dequeue		= ioh_udc_pcd_dequeue,
+	.set_halt		= ioh_udc_pcd_set_halt,
+	.set_wedge  	= ioh_udc_pcd_set_wedge,
+	.fifo_status	= NULL,
+	.fifo_flush		= ioh_udc_pcd_fifo_flush,
+};
+
+/* received setup data */
+static union ioh_udc_setup_data setup_data;
+static unsigned long ep0out_buf[64];
+static dma_addr_t dma_addr;
+
+
+/*!@ingroup	UDC_InterfaceLayerAPI
+ *@fn		static int ioh_udc_pcd_get_frame(struct usb_gadget *gadget)
+ *@brief	This API is invoked to get the current frame number
+ *@remarks	The following actions are performed:
+ *			- If the argument is NULL, return -EINVAL
+ *			- Return the frame number by invoking HAL API
+ * 						ioh_udc_get_frame
+ *@param	gadget	Reference to the gadget driver
+ *@return	int [ the frame number ] -EINVAL [Invalid Arguments]
+ *@see
+ *			- ioh_udc_get_frame
+ */
+static int ioh_udc_pcd_get_frame(struct usb_gadget *gadget)
+{
+	struct ioh_udc_dev		*dev;
+
+	IOH_DEBUG("ioh_udc_pcd_get_frame: enter");
+	if (gadget == NULL) {
+		IOH_DEBUG("ioh_udc_pcd_get_frame: exit -EINVAL");
+		return -EINVAL;
+	}
+
+	dev = container_of(gadget, struct ioh_udc_dev, gadget);
+
+	IOH_DEBUG("ioh_udc_pcd_get_frame: exit");
+	return ioh_udc_get_frame(dev->regs);
+}
+
+/*!@ingroup	UDC_InterfaceLayerAPI
+ *@fn		static int ioh_udc_pcd_wakeup(struct usb_gadget *gadget)
+ *@brief	This API is invoked to initiate a remote wakeup
+ *@remarks	The following actions are performed:
+ *			- If the argument is NULL, return -EINVAL
+ *			- Invoke HAL API ioh_udc_rmt_wakeup to start
+ * 							remote signaling
+ *@param	gadget	Reference to the gadget driver
+ *@return	int [ 0 on success and linux error number on failure ]
+ *@see
+ *			- ioh_udc_rmt_wakeup
+ */
+static int ioh_udc_pcd_wakeup(struct usb_gadget *gadget)
+{
+	struct ioh_udc_dev		*dev;
+	unsigned long			flags;
+
+	IOH_DEBUG("ioh_udc_pcd_wakeup: enter");
+	if (gadget == NULL) {
+		IOH_DEBUG("ioh_udc_pcd_wakeup: exit -EINVAL");
+		return -EINVAL;
+	}
+
+	dev = container_of(gadget, struct ioh_udc_dev, gadget);
+
+	IOH_DEBUG("ioh_udc_pcd_wakeup: initiate remote wakeup");
+	spin_lock_irqsave(&dev->lock, flags);
+	ioh_udc_rmt_wakeup(dev->regs);
+	spin_unlock_irqrestore(&dev->lock, flags);
+
+	IOH_DEBUG("ioh_udc_pcd_wakeup: exit");
+	return 0;
+}
+
+/*!@ingroup	UDC_InterfaceLayerAPI
+ *@fn		static int ioh_udc_pcd_selfpowered (struct usb_gadget *gadget,
+ * 								 int value)
+ *@brief	This API is invoked to specify whether the device is self
+ * 								 powered or not
+ *@remarks	The following actions are performed:
+ *- if value is 0, invoke HAL API ioh_udc_clear_selfpowered to clear the self
+ *							powered feature
+ *-  otherwise, invoke ioh_udc_set_selfpowered to set the self powered
+ * 							feature for the device
+ *@param	gadget	Reference to the gadget driver
+ *@param	value		specifies self powered or not
+ *@return	int [ 0 on success and linux error number on failure ]
+ *@see
+ *			- ioh_udc_set_selfpowered
+ *			- ioh_udc_clear_selfpowered
+ */
+static int ioh_udc_pcd_selfpowered(struct usb_gadget *gadget, int value)
+{
+	struct ioh_udc_dev		*dev;
+
+	IOH_DEBUG("ioh_udc_pcd_selfpowered: enter");
+	if (gadget == NULL) {
+		IOH_DEBUG("ioh_udc_pcd_selfpowered: exit -EINVAL");
+		return -EINVAL;
+	}
+
+	dev = container_of(gadget, struct ioh_udc_dev, gadget);
+	if (value == 0)
+		ioh_udc_clear_selfpowered(dev->regs);
+	else
+		ioh_udc_set_selfpowered(dev->regs);
+
+	IOH_DEBUG("ioh_udc_pcd_selfpowered: exit value=%d", value);
+	return 0;
+}
+
+/*!@ingroup	UDC_InterfaceLayerAPI
+ *@fn		static int ioh_udc_pcd_pullup (struct usb_gadget *gadget,
+ * 								 int is_on)
+ *@brief This API is invoked to make the device visible/invisible to the host
+ *@remarks	The following actions are performed:
+ *			- If gadget passed is NULL, return -EINVAL
+ *			- If is_on is TRUE, call ioh_udc_clear_disconnect()
+ * 					to make the device visible to the host
+ *			- Otherwise call the HAL API ioh_udc_set_disconnect()
+ * 				 to make the device unavailable to the host
+ *@param	gadget	Reference to the gadget driver
+ *@param	is_on		specifies whether the pull up is made active
+ * 								 or inactive
+ *@return	int [ 0 on success and linux error number on failure ]
+ *@see
+ *			- ioh_udc_clear_disconnect
+ *			- ioh_udc_set_disconnect
+ */
+static int ioh_udc_pcd_pullup(struct usb_gadget *gadget, int is_on)
+{
+	struct ioh_udc_dev		*dev;
+
+	IOH_DEBUG("ioh_udc_pcd_pullup: enter");
+	if (gadget == NULL) {
+		IOH_DEBUG("ioh_udc_pcd_pullup: exit -EINVAL");
+		return -EINVAL;
+	}
+
+	dev = container_of(gadget, struct ioh_udc_dev, gadget);
+	if (is_on == 0)
+		ioh_udc_set_disconnect(dev->regs);
+	else
+		ioh_udc_clear_disconnect(dev->regs);
+
+	IOH_DEBUG("ioh_udc_pcd_pullup: exit is_on=%d", is_on);
+	return 0;
+}
+
+/*!@ingroup	UDC_InterfaceLayerAPI
+ *@fn		static int ioh_udc_pcd_vbus_session (struct usb_gadget *gadget,
+ * 								 int is_active)
+ *@brief	This API is used by a driver for an external transceiver
+ *								 (or GPIO) that
+ *			detects a VBUS power session starting/ending
+ *@remarks	The following actions are performed:
+ *			- If the gadget passed is NULL, return -EINVAL
+ *			- Invoke the HAL API ioh_udc_vbus_session to notify
+ * 					 the start/end of the vbus power
+ *@param	gadget	Reference to the gadget driver
+ *@param	is_active specifies whether the session is starting or ending
+ *@return	int [ 0 on success and linux error number on failure ]
+ *@see
+ *			- ioh_udc_vbus_session
+ */
+static int ioh_udc_pcd_vbus_session(struct usb_gadget *gadget, int is_active)
+{
+	struct ioh_udc_dev	*dev;
+
+	IOH_DEBUG("ioh_udc_pcd_vbus_session: enter");
+	if (gadget == NULL) {
+		IOH_DEBUG("ioh_udc_pcd_vbus_session: exit -EINVAL");
+		return -EINVAL;
+	}
+	dev = container_of(gadget, struct ioh_udc_dev, gadget);
+
+	ioh_udc_vbus_session(dev->regs, is_active);
+	IOH_DEBUG("ioh_udc_pcd_vbus_session: exit");
+	return 0;
+}
+
+/*!@ingroup	UDC_InterfaceLayerAPI
+ *@fn		static int ioh_udc_pcd_vbus_draw (struct usb_gadget *gadget,
+ *							 unsigned int mA)
+ *@brief	This API is used by gadget drivers during SET_CONFIGURATION
+ * 								calls to
+ *			specify how much power the device can consume
+ *@remarks	The following actions are performed:
+ *			- If the gadget passed is NULL, return -EINVAL
+ *			-  Return -EOPNOTSUPP
+ *@param	gadget	Reference to the gadget driver
+ *@param	mA		specifies the current limit in 2mA unit
+ *@return	int [ 0 on success and linux error number on failure ]
+ */
+static int ioh_udc_pcd_vbus_draw(struct usb_gadget *gadget, unsigned int mA)
+{
+	IOH_DEBUG("ioh_udc_pcd_vbus_draw: enter");
+	if ((gadget == NULL) || (mA > 250)) { /* Max is 250 in 2mA unit */
+		IOH_DEBUG("ioh_udc_pcd_vbus_draw: exit -EINVAL");
+		return -EINVAL;
+	}
+	IOH_DEBUG("ioh_udc_pcd_vbus_draw: exit -EOPNOTSUPP");
+
+	/* Could not find any regs where we can set the limit	*/
+	return -EOPNOTSUPP;
+}
+
+const char	ep0_string[] = "ep0in";
+/*!@ingroup	UDC_UtilitiesAPI
+ *@fn		static void ioh_udc_pcd_reinit(struct ioh_udc_dev *dev)
+ *@brief	This API initializes the endpoint structures
+ *@remarks	The following actions are performed:
+ *- Initialize gadgets speed as unknown
+ *- Initialize the gadget endpoint list (ep_list)
+ *- Assign name for each endpoint and their reference to endpoint operations
+ *	to ioh_udc_ep_ops
+ *- Add all endpoints other than ep0 IN and ep0 OUT to the gadgete ep_list
+ *@param	dev	Reference to the driver structure
+ *@return	none
+ */
+static void ioh_udc_pcd_reinit(struct ioh_udc_dev *dev)
+{
+	static const char *ep_string[] = {
+		ep0_string, "ep0out",
+		"ep1in", "ep1out",
+		"ep2in", "ep2out",
+		"ep3in", "ep3out",
+		"ep4in", "ep4out",
+		"ep5in", "ep5out",
+		"ep6in", "ep6out",
+		"ep7in", "ep7out",
+		"ep8in", "ep8out",
+		"ep9in", "ep9out",
+		"ep10in", "ep10out",
+		"ep11in", "ep11out",
+		"ep12in", "ep12out",
+		"ep13in", "ep13out",
+		"ep14in", "ep14out",
+		"ep15in", "ep15out",
+	};
+	int i;
+
+	IOH_DEBUG("ioh_udc_pcd_reinit: enter");
+
+	dev->gadget.speed = USB_SPEED_UNKNOWN;
+	INIT_LIST_HEAD(&dev->gadget.ep_list);
+
+	/* Initialize the endpoints structures */
+	for (i = 0; i < IOH_UDC_EP_NUM; i++) {
+		struct ioh_udc_ep *ep = &dev->ep[i];
+		memset(ep, 0, sizeof(*ep));
+
+		ep->desc = NULL;
+		ep->dev = dev;
+		ep->halted = 1;
+		ep->num = i / 2;
+		ep->in = ((i & 1) == 0) ? 1 : 0;
+
+		ep->ep.name = ep_string[i];
+		ep->ep.ops = &ioh_udc_ep_ops;
+		if (ep->in)
+			ep->regs = (struct ioh_udc_ep_regs *)\
+				 ((int)dev->ep_regs + ep->num * UDC_EP_REG_OFS);
+		else
+			ep->regs = (struct ioh_udc_ep_regs *)\
+				 ((int)dev->ep_regs + \
+				(UDC_EPINT_OUT_EP0 + ep->num) * UDC_EP_REG_OFS);
+
+		ep->dma = &ep->regs->epctl;
+		/* need to set ep->ep.maxpacket and set Default Configuration?*/
+		ep->ep.maxpacket = UDC_BULK_MAX_PKT_SIZE;
+		list_add_tail(&ep->ep.ep_list, &dev->gadget.ep_list);
+		INIT_LIST_HEAD(&ep->queue);
+	}
+	dev->ep[UDC_EP0IN_IDX].ep.maxpacket = UDC_EP0IN_MAX_PKT_SIZE;
+	dev->ep[UDC_EP0OUT_IDX].ep.maxpacket = UDC_EP0OUT_MAX_PKT_SIZE;
+
+	dma_addr = pci_map_single(dev->pdev, ep0out_buf,
+						 256, PCI_DMA_FROMDEVICE);
+
+	/* remove ep0 in and out from the list.  They have own pointer */
+	list_del_init(&dev->ep[UDC_EP0IN_IDX].ep.ep_list);
+	list_del_init(&dev->ep[UDC_EP0OUT_IDX].ep.ep_list);
+
+	dev->gadget.ep0 = &dev->ep[UDC_EP0IN_IDX].ep;
+	INIT_LIST_HEAD(&dev->gadget.ep0->ep_list);
+	IOH_DEBUG("ioh_udc_pcd_reinit: exit");
+}
+
+/*!@ingroup	UDC_UtilitiesAPI
+ *@fn		int ioh_udc_pcd_init(struct ioh_udc_dev *dev)
+ *@brief	This API initializes the driver structure
+ *@remarks	The following actions are performed:
+ *- Set udc csr register base in dev->csr
+ *- Set Device Configuration Register base in dev->regs
+ *- Set Endpoint-specific CSR base in dev->ep_regs
+ *- Invoke ioh_udc_init to initialize registers, interrupts
+ *- Invoke ioh_udc_pcd_reinit to perform initialization of the endpoint
+ * 								 structures
+ *- Return Success (0)
+ *@param	dev Reference to the driver structure
+ *@return	success
+ *@see
+ *			- ioh_udc_init
+ *			- ioh_udc_pcd_reinit
+ */
+int ioh_udc_pcd_init(struct ioh_udc_dev *dev)
+{
+	IOH_DEBUG("ioh_udc_pcd_init: enter");
+
+	/* udc csr registers base */
+	dev->csr = dev->virt_addr + UDC_CSR_ADDR;
+	/* dev registers base */
+	dev->regs = dev->virt_addr + UDC_DEVCFG_ADDR;
+	/* ep registers base */
+	dev->ep_regs = dev->virt_addr + UDC_EPREGS_ADDR;
+
+	/* init registers, interrupts, ... */
+	ioh_udc_init(dev->regs);
+#ifdef IOH_PRINT_REG
+	ioh_udc_print_regs((u32)dev->virt_addr);
+#endif
+	ioh_udc_pcd_reinit(dev);
+	IOH_DEBUG("ioh_udc_pcd_init: exit");
+	return 0;
+}
+
+/*!@ingroup	UDC_InterfaceLayerAPI
+ *@fn		int usb_gadget_register_driver(struct usb_gadget_driver *driver)
+ *@brief	This API is used to make this driver available to the Linux USB
+ *							 gadget framework
+ *@remarks	The following actions are performed:
+ *- If the argument is NULL or if it doesnt have necessary callbacks,
+ *								 return -EINVAL
+ *- If any class driver is already bound, return -EBUSY
+ *- If drivers structure is not allocated, return -ENODEV
+ *- Hook up the gadget driver by invoking the drivers bind routine
+ *- Invoke ioh_udc_setup_ep0 to get ready for endpoint 0 traffic
+ *- Enable the host detection and resume signaling on USB
+ *@param	driver 	Reference to the USB gadget driver structure
+ *@return	int [ 0 on success and linux error number on failure ]
+ *@see
+ *			- ioh_udc_setup_ep0
+ *			- ioh_udc_clear_disconnect
+ */
+int usb_gadget_register_driver(struct usb_gadget_driver *driver)
+{
+	struct ioh_udc_dev	*dev = ioh_udc;
+	int			retval;
+
+	IOH_DEBUG("usb_gadget_register_driver: enter");
+	if ((driver == NULL) || (driver->speed == USB_SPEED_UNKNOWN) ||
+		(driver->bind == NULL) || (driver->setup == NULL) ||
+		(driver->unbind == NULL) || (driver->disconnect == NULL)) {
+		IOH_LOG(KERN_ERR, "usb_gadget_register_driver: invalid\
+							 driver parameter");
+		return -EINVAL;
+	}
+
+	if (dev == NULL)
+		return -ENODEV;
+
+	if (dev->driver != NULL) {
+		IOH_LOG(KERN_ERR, "usb_gadget_register_driver: already bound");
+		return -EBUSY;
+	}
+	driver->driver.bus = NULL;
+	dev->driver = driver;
+	dev->gadget.dev.driver = &driver->driver;
+
+	/* Invoke the bind routine of the gadget driver */
+	retval = driver->bind(&dev->gadget);
+
+	if (retval != 0) {
+		IOH_LOG(KERN_ERR, "usb_gadget_register_driver: binding to\
+							 %s returning %d",
+						driver->driver.name, retval);
+		dev->driver = NULL;
+		dev->gadget.dev.driver = NULL;
+		return retval;
+	}
+	/* get ready for ep0 traffic */
+	ioh_udc_setup_ep0(dev);
+
+	/* clear SD */
+	ioh_udc_clear_disconnect(dev->regs);
+
+	dev->connected = 1;
+
+	IOH_DEBUG("usb_gadget_register_driver: exit");
+	return 0;
+}
+EXPORT_SYMBOL(usb_gadget_register_driver);
+
+/*!@ingroup	UDC_InterfaceLayerAPI
+ *@fn	int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
+ *@brief	This API is used to make this driver unavailable to the Linux
+ *							 USB gadget framework
+ *@remarks	The following actions are performed:
+ *			- If the argument is NULL or if it doesnt match
+ *				 with the driver already bound, return -EINVAL
+ *			- Call the function drivers unbind method
+ *			- Disable the host detection and stop signaling
+ *@param	driver 	Reference to the USB gadget driver structure
+ *@return	int [ 0 on success and linux error number on failure ]
+ *@see
+ *			- ioh_udc_set_disconnect
+ */
+int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
+{
+	struct ioh_udc_dev	*dev = ioh_udc;
+
+	IOH_DEBUG("usb_gadget_unregister_driver: enter");
+	if (dev == NULL)
+		return -ENODEV;
+
+	if ((driver == NULL) || (driver != dev->driver)) {
+		IOH_LOG(KERN_ERR, "usb_gadget_unregister_driver: invalid\
+							 driver parameter");
+		return -EINVAL;
+	}
+
+	ioh_udc_disable_interrupts(dev->regs, UDC_DEVINT_MSK);
+
+	/* Assues that there are no pending requets with this driver */
+	driver->unbind(&dev->gadget);
+	dev->gadget.dev.driver = NULL;
+	dev->driver = NULL;
+	dev->connected = 0;
+
+	/* set SD */
+	ioh_udc_set_disconnect(dev->regs);
+
+	IOH_DEBUG("usb_gadget_unregister_driver: %s: unregistered",
+					driver->driver.name);
+
+	IOH_DEBUG("usb_gadget_unregister_driver: exit");
+	return 0;
+}
+EXPORT_SYMBOL(usb_gadget_unregister_driver);
+
+/* Completes request packet ... caller MUST hold lock */
+/*!@ingroup	UDC_UtilitiesAPI
+ *@fn		static void complete_req(struct ioh_udc_ep *ep, struct
+ *					 ioh_udc_request *req, int status)
+ *@brief	This API is invoked from the driver when processing of a
+ *							 request is complete
+ *@remarks	The main functions performed by this function include:
+	- Delete the request from the endpoints request queue
+	- Update the requests status with the status passed
+	- Unmap the requests buffer
+	- Reset DMA mapping status
+	- Set endpoint halted status
+	- Invoke the requests completion handler specified by the gadget driver
+ *@param	ep 	Reference to the endpoint structure
+ *@param	req 	Reference to the request structure
+ *@param	status 	indicates the success/failure of completion
+ *@return	none
+ */
+static void complete_req(struct ioh_udc_ep *ep, struct ioh_udc_request *req,
+								 int status)
+{
+	struct ioh_udc_dev	*dev;
+	unsigned halted = ep->halted;
+
+	list_del_init(&req->queue);
+
+	/* set new status if pending */
+	if (req->req.status == -EINPROGRESS)
+		req->req.status = status;
+	else
+		status = req->req.status;
+
+
+	dev = ep->dev;
+	if (req->dma_mapped) {
+		if (ep->in) {
+			pci_unmap_single(dev->pdev, req->req.dma,
+					 req->req.length,
+					PCI_DMA_TODEVICE);
+		} else {
+			pci_unmap_single(dev->pdev, req->req.dma,
+					 req->req.length,
+					PCI_DMA_FROMDEVICE);
+		}
+		req->dma_mapped = 0;
+		req->req.dma = DMA_ADDR_INVALID;
+	}
+	ep->halted = 1;
+
+	IOH_DEBUG("complete %s req %p status %d len %u",
+		ep->ep.name, &req->req, status, req->req.length);
+	IOH_DEBUG("complete %s ioh-req 0x%08x req->queue 0x%08x",
+		ep->ep.name, (u32)req, (u32)(&(req->queue)));
+	spin_unlock(&dev->lock);
+	if (!ep->in)
+		ioh_udc_ep_clear_rrdy(ep->regs);
+
+	req->req.complete(&ep->ep, &req->req);
+
+	spin_lock(&dev->lock);
+	ep->halted = halted;
+}
+
+/* Empty request queue of an endpoint; caller holds spinlock */
+/*!@ingroup	UDC_UtilitiesAPI
+ *@fn		void empty_req_queue(struct ioh_udc_ep *ep)
+ *@brief	This API empties the request queue of an endpoint
+ *@remarks	The following actions are performed:
+ *			- Set endpoint halted status as 1 in ep->halted
+ *			- For each request in the endpoints queue, invoke
+ *			 the completion handler specified by the gadget driver
+ *@param	ep 	Reference to the endpoint structure
+ *@return	none
+ *@see
+ *			- complete_req
+ */
+void empty_req_queue(struct ioh_udc_ep *ep)
+{
+	struct ioh_udc_request	*req;
+
+	ep->halted = 1;
+	while (!list_empty(&ep->queue)) {
+		req = list_entry(ep->queue.next, struct ioh_udc_request, queue);
+		IOH_DEBUG("empty_req_queue: complete_req  ep%d%s", ep->num,
+						 (ep->in ? "in" : "out"));
+		complete_req(ep, req, -ESHUTDOWN);
+	}
+}
+
+/*!@ingroup	UDC_InterfaceLayerAPI
+ *@fn		static int ioh_udc_pcd_ep_enable(struct usb_ep *usbep,
+ * 				const struct usb_endpoint_descriptor *desc)
+ *@brief	This API enables the endpoint. It is called from gadget driver
+ *@remarks	The following actions are performed:
+ *			- If usbep or descriptor is NULL or the endpoint is 0,
+ * 							 return error -EINVAL
+ *			- If packet size not specified in the descriptor,
+ *								 return -ERANGE
+ *			- Configure the endpoint by invoking ioh_udc_ep_enable()
+ *			- Enable Endpoint interrupts by invoking
+ *						 ioh_udc_enable_ep_interrupts
+ *@param	usbep 	Reference to the USB endpoint structure
+ *@param	desc 	Reference to the USB endpoint descriptor structure
+ *@return	int [ 0 on success and linux error number on failure ]
+ *@see
+ *			- ioh_udc_ep_enable
+ *			- ioh_udc_enable_ep_interrupts
+ */
+static int ioh_udc_pcd_ep_enable(struct usb_ep *usbep,
+			 const struct usb_endpoint_descriptor *desc)
+{
+	struct ioh_udc_ep	*ep;
+	struct ioh_udc_dev	*dev;
+	unsigned long		iflags;
+
+	if ((usbep == NULL) || (usbep->name == ep0_string) || (desc == NULL) ||
+		(desc->bDescriptorType != USB_DT_ENDPOINT) ||
+						 (desc->wMaxPacketSize == 0)) {
+		return -EINVAL;
+	}
+
+	ep = container_of(usbep, struct ioh_udc_ep, ep);
+	dev = ep->dev;
+
+	IOH_DEBUG("ioh_udc_pcd_ep_enable ep %d", ep->num);
+	if ((dev->driver == NULL) || (dev->gadget.speed == USB_SPEED_UNKNOWN))
+		return -ESHUTDOWN;
+
+
+	spin_lock_irqsave(&dev->lock, iflags);
+	ep->desc = desc;
+	ep->halted = 0;
+	ioh_udc_ep_enable(ep->regs, &ep->dev->cfg_data, desc);
+	ep->ep.maxpacket = le16_to_cpu(desc->wMaxPacketSize);
+	ioh_udc_enable_ep_interrupts(ep->dev->regs,
+			1 << (ep->in ? ep->num : ep->num + UDC_EPINT_OUT_EP0));
+
+	IOH_DEBUG("ioh_udc_pcd_ep_enable: %s enabled", usbep->name);
+
+	spin_unlock_irqrestore(&dev->lock, iflags);
+	return 0;
+}
+
+/*!@ingroup	UDC_InterfaceLayerAPI
+ *@fn		static int ioh_udc_pcd_ep_disable(struct usb_ep *usbep)
+ *@brief	This API disables endpoint and is called from gadget driver
+ *@remarks	The following actions are performed:
+ *- If usbep or endpoints descriptor is NULL, return error -EINVAL
+ *- Empty request queue using empty_req_queue API
+ *- Un-configure the endpoint by invoking the HAL API ioh_udc_ep_disable API
+ *- Disable interrupts using ioh_udc_disable_ep_interrupts API
+ *- Set usb endpoint descriptor for the endpoint to NULL
+ *- Set ops method for endpoint request to ioh_udc_ep_ops
+ *- Initialize endpoint queue head using INIT_LIST_HEAD API
+ *@param	usbep 	Reference to the USB endpoint structure
+ *@return	int [ 0 on success and linux error number on failure ]
+ *@see
+ *			- empty_req_queue
+ *			- ioh_udc_ep_disable
+ *			- ioh_udc_disable_ep_interrupts
+ */
+static int ioh_udc_pcd_ep_disable(struct usb_ep *usbep)
+{
+	struct ioh_udc_ep	*ep = NULL;
+	unsigned long	iflags;
+
+	if (usbep == NULL)
+		return -EINVAL;
+
+
+	ep = container_of(usbep, struct ioh_udc_ep, ep);
+	if ((usbep->name == ep0_string) || (ep->desc == NULL))
+		return -EINVAL;
+
+
+	IOH_DEBUG("ioh_udc_pcd_ep_disable: ep%d%s", ep->num,
+						 (ep->in ? "in" : "out"));
+	spin_lock_irqsave(&ep->dev->lock, iflags);
+	empty_req_queue(ep);
+	ep->halted = 1;
+	ioh_udc_ep_disable(ep->regs);
+
+	/* disable interrupt */
+	ioh_udc_disable_ep_interrupts(ep->dev->regs,
+			1 << (ep->in ? ep->num : ep->num + UDC_EPINT_OUT_EP0));
+	ep->desc = NULL;
+	ep->ep.ops = &ioh_udc_ep_ops;
+	INIT_LIST_HEAD(&ep->queue);
+
+	spin_unlock_irqrestore(&ep->dev->lock, iflags);
+
+	return 0;
+}
+
+/*!@ingroup	UDC_InterfaceLayerAPI
+ *@fn		static struct usb_request *ioh_udc_alloc_request
+ *					(struct usb_ep *usbep, gfp_t gfp)
+ *@brief This function allocates request structure. It iscalled by gadget driver
+ *@remarks	The following actions are performed:
+ *- If usbep is NULL, return NULL
+ *- Allocate and initialize memory for request structure
+ *- If allocation fails, return NULL
+ *- Initialize the linked list usbep->queue
+ *- If DMA mode is enabled, create data pool for EP0 IN requests. If it fails,
+ *				release memory allocated for request structure
+ *- Set DMA descriptor status as HOST BUSY to prevent its usage
+ *@param	usbep 	Reference to the USB endpoint structure
+ *@param	gfp		Flag to be used while allocating memory
+ *@return struct usb_request *
+ *			[ NULL on failure and allocated address on success ]
+ *@see
+ *			- pci_pool_alloc
+ */
+static struct usb_request *ioh_udc_alloc_request(struct usb_ep *usbep,
+								 gfp_t gfp)
+{
+	struct ioh_udc_request	*req;
+	struct ioh_udc_ep		*ep;
+
+	if (usbep == NULL)
+		return NULL;
+
+	ep = container_of(usbep, struct ioh_udc_ep, ep);
+	IOH_DEBUG("ioh_udc_alloc_request: ep %s", usbep->name);
+	req = kzalloc(sizeof(struct ioh_udc_request), gfp);
+	if (req == NULL) {
+		IOH_DEBUG("ioh_udc_alloc_request: no memory for request");
+		return NULL;
+	}
+	memset(req, 0, sizeof(struct ioh_udc_request));
+	req->req.dma = DMA_ADDR_INVALID;
+	INIT_LIST_HEAD(&req->queue);
+
+	if (ep->dma != NULL) {
+		struct ioh_udc_data_dma_desc	*dma_desc;
+
+		/* ep0 in requests are allocated from data pool here */
+		dma_desc = pci_pool_alloc(ep->dev->data_requests, gfp,
+							 &req->td_data_phys);
+		if (NULL == dma_desc) {
+			kfree(req);
+			return NULL;
+		}
+
+		IOH_DEBUG("ioh_udc_alloc_request: req = 0x%p dma_desc = 0x%p, "
+			"td_phys = 0x%08lx",
+			req, dma_desc, (unsigned long)req->td_data_phys);
+
+		/* prevent from using desc. - set HOST BUSY */
+		dma_desc->status |= IOH_UDC_BS_HST_BSY;
+		dma_desc->dataptr = __constant_cpu_to_le32(DMA_ADDR_INVALID);
+		req->td_data = dma_desc;
+		req->td_data_last = dma_desc;
+		req->chain_len = 1;
+	}
+
+	return &req->req;
+}
+
+/* frees pci pool descriptors of a DMA chain */
+/*!@ingroup	UDC_InterfaceLayerAPI
+ *@fn		static int ioh_udc_free_dma_chain(struct ioh_udc_dev *dev,
+ *						 struct ioh_udc_request *req)
+ *@brief	This function frees the DMA chain created for the request
+ *@remarks	The following actions are performed:
+ *- Get the virtual address of second DMA descriptor,
+ *						 of the chain using phys_to_virt
+ *- Release the allocated block back into PCI pool using pci_pool_free
+ *- Get the virtual address of next DMA descriptor,
+ *						 of the chain using phys_to_virt
+ *- Repeat steps 2, 3 for the chain length
+ *@param	dev		Reference to the driver structure
+ *@param	req		Reference to the request to be freed
+ *@return	success
+ */
+static int ioh_udc_free_dma_chain(struct ioh_udc_dev *dev,
+						 struct ioh_udc_request *req)
+{
+	int ret_val = 0;
+	struct ioh_udc_data_dma_desc	*td;
+	struct ioh_udc_data_dma_desc	*td_last = NULL;
+	unsigned int i;
+
+	/* do not free first desc., will be done by free for request */
+	td_last = req->td_data;
+	td = phys_to_virt(td_last->next);
+
+	for (i = 1; i < req->chain_len; i++) {
+		pci_pool_free(dev->data_requests, td,
+				(dma_addr_t) td_last->next);
+		td_last = td;
+		td = phys_to_virt(td_last->next);
+	}
+
+	return ret_val;
+}
+
+/*!@ingroup	UDC_InterfaceLayerAPI
+ *@fn		static int ioh_udc_create_dma_chain(struct ioh_udc_ep *ep,
+ *	struct ioh_udc_request *req, unsigned long buf_len, gfp_t gfp_flags)
+ *@brief	This function creates or reinitializes a DMA chain
+ *@remarks	The following actions are performed:
+ *- If the endpoint is output, set the first descriptor status as HOST_BUSY
+ *- Calculate the new chain length from the requested length and the maximum
+ *	packet size available on the end point
+ *- Check if a shorter chain is already allocated (req->chain_len > 1).
+ *	If TRUE, invoke ioh_udc_free_dma_chain to free the DMA chain.
+ *- Generate the required number of buffers and descriptors as follows:
+ *- Invoke pci_pool_alloc with the following arguments:
+ *			DMA pool for data requests (ep->dev->data_requests),
+ *			gfp_flags and a pointer to the DMA address.
+ *- If pci_pool_alloc fails, return -ENOMEM.
+ *- If the descriptor is valid, assign the DMA address corresponding
+ *	to 'buf' in the current descriptors dataptr field (buffer descriptor).
+ *- Link the descriptor and assign the bytes to be transferred.
+ *- Set the byte count as well as the status (HOST_BUSY) for
+ *		input endpoints. For Output endpoint, set the status alone.
+ *- For the last descriptor, set the last bit in the status field
+ *				and update the next field to point to itself.
+ *- Return with IOH_UDC_SUCCESS
+ *@param	ep		Reference to the endpoint structure
+ *@param	req		Reference to the request
+ *@param	buf_len		The buffer length
+ *@param	gfp_flags	Flags to be used while mapping the data buffer
+ *@return	success, -ENOMEM (pci_pool_alloc invocation fails)
+ *@see
+ *			- ioh_udc_free_dma_chain
+ */
+static int ioh_udc_create_dma_chain(struct ioh_udc_ep *ep,
+			struct ioh_udc_request *req,
+			 unsigned long buf_len, gfp_t gfp_flags)
+{
+	unsigned long bytes = req->req.length;
+	unsigned int i;
+	dma_addr_t dma_addr;
+	struct ioh_udc_data_dma_desc	*td = NULL;
+	struct ioh_udc_data_dma_desc	*last = NULL;
+	unsigned long txbytes;
+	unsigned len;
+
+	IOH_DEBUG("ioh_udc_create_dma_chain: bytes = %ld buf_len = %ld",
+							 bytes, buf_len);
+	/* unset L bit in first desc for OUT */
+	if (!ep->in)
+		req->td_data->status = IOH_UDC_BS_HST_BSY;
+
+
+	/* alloc only new desc's if not already available */
+	len = req->req.length / buf_len;
+	if (req->req.length % buf_len)
+		len++;
+
+	/* shorter chain already allocated before */
+	if (req->chain_len > 1)
+		ioh_udc_free_dma_chain(ep->dev, req);
+
+	req->chain_len = len;
+
+	td = req->td_data;
+	/* gen. required number of descriptors and buffers */
+	for (i = buf_len; i < bytes; i += buf_len) {
+		dma_addr = DMA_ADDR_INVALID;
+		/* create or determine next desc. */
+		td = pci_pool_alloc(ep->dev->data_requests, gfp_flags,
+								 &dma_addr);
+		if (td == NULL)
+			return -ENOMEM;
+
+		td->status = 0;
+		td->dataptr = req->req.dma + i; /* assign buffer */
+
+		if ((bytes - i) >= buf_len) {
+			txbytes = buf_len;
+		} else { /* short packet */
+			txbytes = bytes - i;
+		}
+		/* link td and assign tx bytes */
+		if (i == buf_len) {
+			req->td_data->next = dma_addr;
+			/* set the count bytes */
+			if (ep->in) {
+				req->td_data->status = IOH_UDC_BS_HST_BSY |
+								 buf_len;
+				/* second desc */
+				td->status = IOH_UDC_BS_HST_BSY | txbytes;
+			} else {
+				td->status = IOH_UDC_BS_HST_BSY;
+			}
+		} else {
+			last->next = dma_addr;
+			if (ep->in)
+				td->status = IOH_UDC_BS_HST_BSY | txbytes;
+			else
+				td->status = IOH_UDC_BS_HST_BSY;
+
+		}
+		last = td;
+	}
+	/* set last bit */
+	if (td) {
+		td->status |= IOH_UDC_DMA_LAST;
+		/* last desc. points to itself */
+		req->td_data_last = td;
+		td->next = req->td_data_phys;
+	}
+	return 0;
+}
+/*!@ingroup	UDC_InterfaceLayerAPI
+ *@fn		static void ioh_udc_free_request(struct usb_ep *usbep,
+ *						 struct usb_request *usbreq)
+ *@brief This function frees request structure. It is called by gadget driver
+ *@remarks	The following actions are performed:
+ *	- If any of the argument is NULL, return
+ *	- Warn if req->queue is empty
+ *	- Otherwise, if the chain length is greater than 1,
+ *		invoke ioh_udc_free_dma_chain to free the DMA chain.
+ *	- If the chain length is less than 1,
+ *		release memory allocated for request structure and data pool
+ *		by invoking pci_pool_free
+ *@param	usbep 	Reference to the USB endpoint structure
+ *@param	usbreq	Reference to the USB request
+ *@return	int [ 0 on success and linux error number on failure ]
+ *@see
+ *			- ioh_udc_free_dma_chain
+ */
+static void ioh_udc_free_request(struct usb_ep *usbep,
+						 struct usb_request *usbreq)
+{
+	struct ioh_udc_ep		*ep;
+	struct ioh_udc_request	*req;
+
+	if ((usbep == NULL) || (usbreq == NULL))
+		return;
+
+
+	ep = container_of(usbep, struct ioh_udc_ep, ep);
+	req = container_of(usbreq, struct ioh_udc_request, req);
+	IOH_DEBUG("ioh_udc_free_request: %s  req = 0x%p", usbep->name, req);
+
+	if (!list_empty(&req->queue))
+		IOH_LOG(KERN_ERR, "ioh_udc_free_request: %s  req = 0x%p\
+					 queue not empty", usbep->name, req);
+
+	if (req->td_data != NULL) {
+		if (req->chain_len > 1)
+			ioh_udc_free_dma_chain(ep->dev, req);
+		else
+			pci_pool_free(ep->dev->data_requests, req->td_data,
+							 req->td_data_phys);
+
+	}
+	kfree(req);
+}
+
+/*!@ingroup	UDC_UtilitiesAPI
+ *@fn		static int prepare_dma(struct ioh_udc_ep *ep,
+ *					 struct ioh_udc_request *req, gfp_t gfp)
+ *@brief This function creates and initializes the DMA chain for the request
+ *@remarks	The following actions are performed:
+ *- Set buffer pointer in req->td_data->dataptr and last descriptor
+ *	indication status in req->td_data->status.
+ *- Allocate and create a DMA chain using ioh_udc_create_dma_chain.
+ *- If the allocation fails, return -ENOMEM.
+ *- If the request is on an IN endpoint, update the count in the first
+ *descriptors status and mark the status (req->td_data->status) as host busy
+ *	- Return success
+ *@param	ep		Reference to the endpoint structure
+ *@param	req		Reference to the request
+ *@param	gfp		Flag to be used while mapping the data buffer
+ *@return	int [ 0 on success and linux error number on failure ]
+ *@see
+ *			- ioh_udc_create_dma_chain
+ */
+static int prepare_dma(struct ioh_udc_ep *ep, struct ioh_udc_request *req,
+								 gfp_t gfp)
+{
+	int	retval = 0;
+	IOH_DEBUG("prepare_dma: enter  req->req.dma = 0x%08x", req->req.dma);
+
+	/* set buffer pointer */
+	req->td_data->dataptr = req->req.dma;
+	/* set last bit */
+	req->td_data->status |= IOH_UDC_DMA_LAST;
+
+	/* Allocate and create a DMA chain */
+	retval = ioh_udc_create_dma_chain(ep, req, ep->ep.maxpacket, gfp);
+	if (retval != 0) {
+		if (retval == -ENOMEM)
+			IOH_LOG(KERN_ERR, "prepare_dma: Out of DMA memory");
+
+		return retval;
+	}
+	if (ep->in) {
+		if (req->req.length <= ep->ep.maxpacket) {
+			/* write tx bytes */
+			req->td_data->status = IOH_UDC_DMA_LAST |
+					 IOH_UDC_BS_HST_BSY | req->req.length;
+		}
+	}
+
+	if (ep->in) {
+		/* if bytes < max packet then tx bytes must
+		 *be written in packet per buffer mode
+		 */
+		if ((req->req.length < ep->ep.maxpacket) || (ep->num == 0)) {
+			/* write the count */
+			req->td_data->status = (req->td_data->status &
+							 ~IOH_UDC_RXTX_BYTES) |
+								req->req.length;
+		}
+		/* set HOST BUSY */
+		req->td_data->status = (req->td_data->status &
+							 ~IOH_UDC_BUFF_STS) |
+							IOH_UDC_BS_HST_BSY;
+	}
+	return retval;
+}
+
+/*!@ingroup	UDC_UtilitiesAPI
+ *@fn		static void process_zlp(struct ioh_udc_ep *ep,
+ *						 struct ioh_udc_request *req)
+ *@brief	This function process zero length packets from the gadget driver
+ *@remarks	The following actions are performed:
+ *- Invoke the requests completion routine
+ *- If there is a set config or set interface request that is not
+ *	acknowledged, set CSR_DONE using ioh_udc_set_csr_done API.
+ *	Reset dev->set_cfg_not_acked to 0.
+ *- If there is a setup request waiting for acknowledgement,
+ *clear the NAK on EP0 IN using ioh_udc_ep_clear_nak API and set the
+ *naking status as 0 in dev->ep[UDC_EP0IN_IDX].naking. Reset dev->
+ *							waiting_zlp_ack to 0
+ *@param	ep		Reference to the endpoint structure
+ *@param	req		Reference to the request
+ *@return	none
+ *@see
+ *			- complete_req
+ *			- ioh_udc_set_csr_done
+ *			- ioh_udc_ep_clear_nak
+ */
+static void process_zlp(struct ioh_udc_ep *ep, struct ioh_udc_request *req)
+{
+	struct ioh_udc_dev	*dev = ep->dev;
+
+	IOH_DEBUG("process_zlp: enter  ep%d%s",
+					 ep->num, (ep->in ? "in" : "out"));
+	/* IN zlp's are handled by hardware */
+	complete_req(ep, req, 0);
+
+	/* if set_config or set_intf is waiting for ack by zlp
+	 *then set CSR_DONE
+	 */
+	if (dev->set_cfg_not_acked) {
+		IOH_DEBUG("process_zlp: csr done");
+		ioh_udc_set_csr_done(dev->regs);
+		dev->set_cfg_not_acked = 0;
+	}
+	/* setup command is ACK'ed now by zlp */
+	if (!dev->stall) {
+		if (dev->waiting_zlp_ack) {
+			/* clear NAK by writing CNAK in EP0_IN */
+			ioh_udc_ep_clear_nak(dev->ep[UDC_EP0IN_IDX].regs);
+			dev->waiting_zlp_ack = 0;
+		}
+	}
+	IOH_DEBUG("process_zlp: exit");
+}
+
+/*!@ingroup	UDC_InterfaceLayerAPI
+ *@fn		static int ioh_udc_pcd_queue(struct usb_ep *usbep,
+ *					 struct usb_request *usbreq, gfp_t gfp)
+ *@brief This function queues a request packet. It is called by gadget driver
+ *@remarks	The following actions are performed:
+ *	- If any of the argument is NULL or the request has NULL buffer
+ *		or NULL completion handler, return -EINVAL
+ *	- Verify if the endpoint is enabled before trying to queue. if not,
+ *								 return -EINVAL
+ *	- Verify if the request queue is non empty. If so, return -EINVAL
+ *	- If the gadget is not bound or invalid, return -ESHUTDOWN
+ *	- Setup a DMA mapping for the request buffer and
+ *		allocate the DMA descriptors
+ *	- If usbeps request queue is empty
+ *		- If length of data equals 0, call process_zlp API
+ *			and return IOH_UDC_SUCCESS
+ *		- if there are no IN endpoints,
+ *			- Start the receive request by invoking
+ *							 ioh_udc_start_rxrequest
+ *		- Oterwise
+ *			- Wait till STALL bit in endpoint control register
+ *								 is cleared
+ *			- Clear NAK by invoking ioh_udc_ep_clear_nak.
+ *			- Enable endpoint interrupts for out endpoint
+ *			- Enable TX DMA by invoking ioh_udc_set_dma
+ *	- If request queue not empty,
+ *		- Add the request to end of usbeps queue
+ *	- Return with IOH_UDC_SUCCESS
+ *@param	usbep 	Reference to the USB endpoint structure
+ *@param	usbreq	Reference to the USB request
+ *@param	gfp		Flag to be used while mapping the data buffer
+ *@return	int [ 0 on success and linux error number on failure ]
+ *@see
+ *			- prepare_dma
+ *			- process_zlp
+ *			- ioh_udc_start_rxrequest
+ *			- ioh_udc_read_ep_control
+ *			- ioh_udc_ep_clear_nak
+ *			- ioh_udc_enable_ep_interrupts
+ *			- ioh_udc_set_dma
+ */
+static int ioh_udc_pcd_queue(struct usb_ep *usbep, struct usb_request *usbreq,
+								 gfp_t gfp)
+{
+	int retval = 0;
+	struct ioh_udc_ep	*ep;
+	struct ioh_udc_dev	*dev;
+	struct ioh_udc_request	*req;
+	unsigned long	iflags;
+
+	IOH_DEBUG("ioh_udc_pcd_queue: enter");
+	if ((usbep == NULL) || (usbreq == NULL) || (usbreq->complete == NULL) ||
+						 (usbreq->buf == NULL)) {
+		IOH_DEBUG("ioh_udc_pcd_queue: Invalid end point OR request");
+		return -EINVAL;
+	}
+
+	ep = container_of(usbep, struct ioh_udc_ep, ep);
+	if ((ep->desc == NULL) && (ep->num != 0)) {
+		IOH_DEBUG("ioh_udc_pcd_queue: Trying to queue before before\
+					 enabling the end point %d", ep->num);
+		/* Don't let non-control ep queue before enable */
+		return -EINVAL;
+	}
+	req = container_of(usbreq, struct ioh_udc_request, req);
+	IOH_DEBUG("ioh_udc_pcd_queue: ep%d%s  req = 0x%08x", ep->num,
+					 (ep->in ? "in" : "out"), (u32)req);
+	if (!list_empty(&req->queue)) {
+		IOH_DEBUG("list_empty error: req->queue = 0x%08x\
+			  ioh-req = 0x%08x", (u32)(&(req->queue)), (u32)req);
+		return -EINVAL;
+	}
+	dev = ep->dev;
+	if ((dev->driver == NULL) || (dev->gadget.speed == USB_SPEED_UNKNOWN)) {
+		IOH_DEBUG("ioh_udc_pcd_queue: Gadget not bound/invalid");
+		IOH_DEBUG("dev->driver = 0x%p  speed = 0x%x", dev->driver,
+							 dev->gadget.speed);
+		return -ESHUTDOWN;
+	}
+	spin_lock_irqsave(&ep->dev->lock, iflags);
+	/* map the buffer for dma */
+	if ((usbreq->length != 0) &&
+		((usbreq->dma == DMA_ADDR_INVALID) || (usbreq->dma == 0))) {
+		if (ep->in) {
+			usbreq->dma = pci_map_single(dev->pdev, usbreq->buf,
+					usbreq->length, PCI_DMA_TODEVICE);
+		} else {
+			usbreq->dma = pci_map_single(dev->pdev, usbreq->buf,
+					usbreq->length, PCI_DMA_FROMDEVICE);
+		}
+		req->dma_mapped = 1;
+	}
+
+	if (usbreq->length > 0) { /* setup the descriptors */
+		retval = prepare_dma(ep, req, gfp);
+		if (retval != 0) {
+			/* Need to unmap before returning? ...
+							 req->dma_mapped = 1; */
+			spin_unlock_irqrestore(&dev->lock, iflags);
+			return retval;
+		}
+	}
+
+	usbreq->actual = 0;
+	usbreq->status = -EINPROGRESS;
+	req->dma_done = 0;
+
+	if (list_empty(&ep->queue) && !ep->halted) {
+		/* no pending transfer, so start this req */
+		if ((usbreq->length == 0)) {
+			process_zlp(ep, req);
+			spin_unlock_irqrestore(&dev->lock, iflags);
+			return 0;
+		}
+		if (!ep->in) {
+			ioh_udc_start_rxrequest(ep, req);
+		} else {
+			/*
+			* For IN trfr the descriptors will be programmed and
+			* P bit will be set when
+			* we get an IN token
+			*/
+
+			while (ioh_udc_read_ep_control(ep->regs) &
+							 (1 << UDC_EPCTL_S))
+				udelay(100);
+
+			ioh_udc_ep_clear_nak(ep->regs);
+			ioh_udc_enable_ep_interrupts(ep->dev->regs,
+							 (1 << ep->num));
+			/* enable DMA */
+			ioh_udc_set_dma(dev->regs, DMA_DIR_TX);
+		}
+	}
+	IOH_DEBUG("ioh_udc_pcd_queue:  desc[stat:0x%08x  dptr:0x%08x\
+								  next:0x%08x]",
+				 req->td_data->status, req->td_data->dataptr,
+							 req->td_data->next);
+	/* Now add this request to the ep's pending requests */
+	if (req != NULL)
+		list_add_tail(&req->queue, &ep->queue);
+
+#ifdef IOH_PRINT_REG
+	ioh_udc_print_regs((u32)dev->virt_addr);
+#endif
+	spin_unlock_irqrestore(&dev->lock, iflags);
+	return retval;
+}
+
+/*!@ingroup	UDC_InterfaceLayerAPI
+ *@fn		static int ioh_udc_pcd_dequeue(struct usb_ep *usbep,
+ *						 struct usb_request *usbreq)
+ *@brief	This function de-queues a request packet. It is called
+ *							 by gadget driver
+ *@remarks	The following actions are performed:
+ *			- If any of the argument is NULL, return -EINVAL
+ *			- If the request is not in usbeps queue, return -EINVAL
+ *			- Set the NAK bit
+ *			- If the request is not in processing , call its\
+ *							 completion handler
+ *@param	usbep 	Reference to the USB endpoint structure
+ *@param	usbreq	Reference to the USB request
+ *@return	int [ 0 on success and linux error number on failure ]
+ *@see
+ *			- ioh_udc_ep_set_nak
+ *			- complete_req
+ */
+static int ioh_udc_pcd_dequeue(struct usb_ep *usbep, struct usb_request *usbreq)
+{
+	struct ioh_udc_ep		*ep;
+	struct ioh_udc_request	*req;
+	unsigned long			flags;
+
+	ep = container_of(usbep, struct ioh_udc_ep, ep);
+	if ((usbep == NULL) || (usbreq == NULL) ||
+			((ep->desc == NULL) && (ep->num != 0))) {
+		return -EINVAL;
+	}
+	IOH_DEBUG("ioh_udc_pcd_dequeue: enter  ep%d%s", ep->num,
+						 (ep->in ? "in" : "out"));
+	req = container_of(usbreq, struct ioh_udc_request, req);
+	spin_lock_irqsave(&ep->dev->lock, flags);
+	/* make sure it's still queued on this endpoint */
+	list_for_each_entry(req, &ep->queue, queue) {
+		if (&req->req == usbreq)
+			break;
+
+	}
+
+	if (&req->req != usbreq) {
+		spin_unlock_irqrestore(&ep->dev->lock, flags);
+		return -EINVAL;
+	}
+	ioh_udc_ep_set_nak(ep->regs);
+	if (!list_empty(&req->queue))
+		complete_req(ep, req, -ECONNRESET);
+
+	spin_unlock_irqrestore(&ep->dev->lock, flags);
+	return 0;
+}
+
+/*!@ingroup	UDC_InterfaceLayerAPI
+ *@fn		static int ioh_udc_pcd_set_halt(struct usb_ep *usbep, int halt)
+ *@brief	This function Sets or clear the endpoint halt feature
+ *@remarks	The following actions are performed:
+ *			- If the ep->desc is NULL and ep->num is 0,
+ *								 return -EINVAL.
+ *			- If ep->dev->driver is NULL and speed is unknown,
+ *							 return -ESHUTDOWN
+ *			- If there are pending transfers, return -EAGAIN
+ *			- If halt is 0, Clear the STALL for the endpoint
+ *			- Otherwise,
+ *				- Set the STALL for the endpoint
+ *				- Enable endpoint interrupts for out endpoint
+ *@param	usbep 	Reference to the USB endpoint structure
+ *@param	halt 	Specifies whether to set or clear the feature
+ *@return	int [ 0 on success and linux error number on failure ]
+ *@see
+ *			- ioh_udc_ep_clear_stall
+ *			- ioh_udc_ep_set_stall
+ *			- ioh_udc_enable_ep_interrupts
+ */
+static int ioh_udc_pcd_set_halt(struct usb_ep *usbep, int halt)
+{
+	struct ioh_udc_ep	*ep;
+	unsigned long iflags;
+
+	if (usbep == NULL)
+		return -EINVAL;
+
+
+	IOH_DEBUG("ioh_udc_pcd_set_halt: %s: halt=%d", usbep->name, halt);
+
+	ep = container_of(usbep, struct ioh_udc_ep, ep);
+
+	if ((ep->desc == NULL) && (ep->num == 0)) {
+		IOH_DEBUG("ioh_udc_pcd_set_halt: ep->desc = 0x%x:\
+				 ep->num = 0x%x", (u32)(ep->desc), ep->num);
+		return -EINVAL;
+	}
+	if ((ep->dev->driver == NULL) || (ep->dev->gadget.speed\
+						 == USB_SPEED_UNKNOWN)) {
+		IOH_DEBUG("ioh_udc_pcd_set_halt: ep->dev->driver = 0x%x:\
+			 ep->dev->gadget.speed = 0x%x", (u32)(ep->dev->driver),
+			 ep->dev->gadget.speed);
+		return -ESHUTDOWN;
+	}
+
+	spin_lock_irqsave(&udc_stall_spinlock, iflags);
+
+	if (!list_empty(&ep->queue)) {
+		IOH_DEBUG("ioh_udc_pcd_set_halt: list not empty");
+		spin_unlock_irqrestore(&udc_stall_spinlock, iflags);
+		return -EAGAIN;
+	}
+	/* halt or clear halt */
+	if (halt == 0) {
+			ioh_udc_ep_clear_stall(ep->regs);
+	} else {
+		if (ep->num == IOH_UDC_EP0)
+			ep->dev->stall = 1;
+
+		ioh_udc_ep_set_stall(ep->regs);
+		ioh_udc_enable_ep_interrupts(ep->dev->regs,
+			1 << (ep->in ? ep->num : ep->num + UDC_EPINT_OUT_EP0));
+	}
+	spin_unlock_irqrestore(&udc_stall_spinlock, iflags);
+	return 0;
+}
+
+/*!@ingroup	UDC_InterfaceLayerAPI
+ *@fn		static int ioh_udc_pcd_set_wedge(struct usb_ep *usbep)
+ *@brief	This function Sets or clear the endpoint halt feature
+ *@param	usbep 	Reference to the USB endpoint structure
+ *@param	halt 	Specifies whether to set or clear the feature
+ *@return	int [ 0 on success and linux error number on failure ]
+ */
+static int ioh_udc_pcd_set_wedge(struct usb_ep *usbep)
+{
+	struct ioh_udc_ep	*ep;
+	unsigned long iflags;
+
+	if (usbep == NULL)
+		return -EINVAL;
+
+
+	IOH_DEBUG("ioh_udc_pcd_set_wedge: %s:", usbep->name);
+
+	ep = container_of(usbep, struct ioh_udc_ep, ep);
+
+	if ((ep->desc == NULL) && (ep->num == 0)) {
+		IOH_DEBUG("ioh_udc_pcd_set_wedge: ep->desc = 0x%x:\
+				 ep->num = 0x%x", (u32)(ep->desc), ep->num);
+		return -EINVAL;
+	}
+	if ((ep->dev->driver == NULL) || (ep->dev->gadget.speed ==\
+							 USB_SPEED_UNKNOWN)) {
+		IOH_DEBUG("ioh_udc_pcd_set_wedge: ep->dev->driver = 0x%x:\
+			 ep->dev->gadget.speed = 0x%x", (u32)(ep->dev->driver),
+			 ep->dev->gadget.speed);
+		return -ESHUTDOWN;
+	}
+
+	spin_lock_irqsave(&udc_stall_spinlock, iflags);
+
+	if (!list_empty(&ep->queue)) {
+		IOH_DEBUG("ioh_udc_pcd_set_wedge: list not empty");
+		spin_unlock_irqrestore(&udc_stall_spinlock, iflags);
+		return -EAGAIN;
+	}
+	/* halt */
+	if (ep->num == IOH_UDC_EP0)
+		ep->dev->stall = 1;
+
+	ioh_udc_ep_set_stall(ep->regs);
+	ioh_udc_enable_ep_interrupts(ep->dev->regs,
+		1 << (ep->in ? ep->num : ep->num + UDC_EPINT_OUT_EP0));
+
+	ep->dev->prot_stall = 1;
+	spin_unlock_irqrestore(&udc_stall_spinlock, iflags);
+	return 0;
+}
+
+/*!@ingroup	UDC_InterfaceLayerAPI
+ *@fn		static void ioh_udc_pcd_fifo_flush(struct usb_ep *usbep)
+ *@brief	This function Flush the FIFO of specified endpoint
+ *@remarks	The following actions are performed:
+ *		- Depending on the endpoint direction, flush the TX or RX FIFO
+ *@param	usbep 		Reference to the USB endpoint structure
+ *@return	none
+ *@see
+ *			- ioh_udc_ep_fifo_flush
+ */
+static void ioh_udc_pcd_fifo_flush(struct usb_ep *usbep)
+{
+	struct ioh_udc_ep	*ep;
+
+	if (usbep == NULL)
+		return;
+
+
+	IOH_DEBUG("ioh_udc_pcd_fifo_flush: %s", usbep->name);
+
+	ep = container_of(usbep, struct ioh_udc_ep, ep);
+	if ((ep->desc == NULL) && (ep->num != 0))
+		return;
+
+
+	ioh_udc_ep_fifo_flush(ep->regs, ep->in);
+}
+
+/*!@ingroup	UDC_UtilitiesAPI
+ *@fn		static void ioh_udc_svc_data_out(struct ioh_udc_dev *dev,
+ *								 int ep_num)
+ *@brief	Handles interrupts from OUT endpoint
+ *@remarks	The following actions are performed:
+ *- Depending on the endpoint direction, flush the TX or RX FIFO
+ *- If the interrupt is BNA and request queue is not empty, get next request
+ *	- If DMA state is DONE and dma_going flag is not set, start receive
+ *								 request.
+ *- If the interrupt is HE, log the error message
+ *- If the interrupt is RSS,
+ * 	- Set STALL useig ioh_udc_ep_set_stall API.
+ * 	- Enable endpoint interrupts for out endpoint
+ *- If the interrupt is RCS,
+ * 	- If the protocol stall flag not set,
+ * 		- Clear stall useing ioh_udc_ep_clear_stall API.
+ * 	- Otherwise
+ * 		- Set STALL using ioh_udc_ep_set_stall API.
+ * 		- Enable endpoint interrupts for out endpoint
+ *- If the interrupt is OUT_DATA,
+ * 	- If the protocol stall flag is set,
+ * 		- Set STALL using ioh_udc_ep_set_stall API.
+ * 		- Enable endpoint interrupts for out endpoint
+ * 	- Otherwise
+ * 		- invoke the completion routine using ioh_udc_complete_receiver
+ *- If request queue is empty,
+ * 	- Enable DMA using ioh_udc_set_dma API
+ *@param	dev 	Reference to the device structure
+ *@param	ep_num 	Endpoint that generated the interrupt
+ *@return	none
+ *@see
+ *			- ioh_udc_start_rxrequest
+ *			- ioh_udc_ep_set_stall
+ *			- ioh_udc_enable_ep_interrupts
+ *			- ioh_udc_ep_clear_stall
+ *			- ioh_udc_complete_receiver
+ *			- ioh_udc_set_dma
+ */
+static void ioh_udc_svc_data_out(struct ioh_udc_dev *dev, int ep_num)
+{
+	u32			epsts;
+	struct ioh_udc_ep		*ep;
+	struct ioh_udc_request		*req = NULL;
+
+	ep = &dev->ep[2*ep_num + 1];
+	epsts = ep->epsts;
+	ep->epsts = 0;
+
+	IOH_DEBUG("ioh_udc_svc_data_out: ep%d%s status = 0x%08x", ep->num,
+					 (ep->in ? "in" : "out"), epsts);
+	if (epsts & (1 << UDC_EPSTS_BNA)) { /* Just log it; only in DMA mode */
+		if (!list_empty(&ep->queue)) {
+			/* next request */
+			req = list_entry(ep->queue.next, struct ioh_udc_request,
+									 queue);
+			IOH_DEBUG("BNA on ep%dout occured", ep->num);
+			if ((req->td_data_last->status & IOH_UDC_BUFF_STS) !=
+							 IOH_UDC_BS_DMA_DONE) {
+				if (req->dma_going == 0)
+					ioh_udc_start_rxrequest(ep, req);
+
+				return;
+			}
+		}
+	}
+	if (epsts & (1 << UDC_EPSTS_HE)) {  /* Host error - Just log it */
+		IOH_DEBUG("Host Error on ep%dout occured", ep->num);
+		return;
+	}
+	if (epsts & (1 << UDC_EPSTS_RSS)) {
+		IOH_DEBUG("ioh_udc_svc_data_out: RSS");
+		ioh_udc_ep_set_stall(ep->regs);
+		ioh_udc_enable_ep_interrupts(ep->dev->regs,
+			1 << (ep->in ? ep->num : ep->num + UDC_EPINT_OUT_EP0));
+	}
+	if (epsts & (1 << UDC_EPSTS_RCS)) {
+		IOH_DEBUG("ioh_udc_svc_data_out: RCS  prot_stall = %d",
+							 dev->prot_stall);
+		if (dev->prot_stall == 0) {
+			ioh_udc_ep_clear_stall(ep->regs);
+		} else {
+			ioh_udc_ep_set_stall(ep->regs);
+			ioh_udc_enable_ep_interrupts(ep->dev->regs,
+				1 << (ep->in ? ep->num : ep->num +
+							 UDC_EPINT_OUT_EP0));
+		}
+	}
+	if (((epsts & UDC_EPSTS_OUT_MASK) >> UDC_EPSTS_OUT_OFS) ==
+						 UDC_EPSTS_OUT_DATA) {
+		if (ep->dev->prot_stall == 1) {
+			ioh_udc_ep_set_stall(ep->regs);
+			ioh_udc_enable_ep_interrupts(ep->dev->regs,
+				1 << (ep->in ? ep->num : ep->num +
+							 UDC_EPINT_OUT_EP0));
+		} else {
+			ioh_udc_complete_receiver(ep);
+		}
+	}
+
+	if (list_empty(&ep->queue)) {
+		/* enable DMA */
+		ioh_udc_set_dma(dev->regs, DMA_DIR_RX);
+	}
+}
+/*!@ingroup	UDC_UtilitiesAPI
+ *@fn		static void ioh_udc_svc_control_in(struct ioh_udc_dev *dev)
+ *@brief	Handle Control IN endpoint interrupts
+ *@remarks	The following actions are performed:
+ *		- if the interrupt is TDC [DMA completed] or XFERDONE or TXEMPTY
+ *			or ISOINDONE or HE or BNA, log the status.
+ *		- If there is an TDC token
+ *			- Invoke the requests completion routine.
+ *		- If there is an IN token
+ *			- Invoke the next request start routine.
+ *@param	dev 		Reference to the device structure
+ *@return	none
+ *@see
+ *			- ioh_udc_complete_transfer
+ *			- ioh_udc_start_next_txrequest
+ */
+static void ioh_udc_svc_control_in(struct ioh_udc_dev *dev)
+{
+	u32	epsts;
+	struct ioh_udc_ep	*ep;
+
+	ep = &dev->ep[UDC_EP0IN_IDX];
+	epsts = ep->epsts;
+	ep->epsts = 0;
+
+	IOH_DEBUG("ioh_udc_ep0_in intr status 0x%x", epsts);
+
+	if ((epsts & ((1 << UDC_EPSTS_IN) | (1 << UDC_EPSTS_BNA)  |
+						 (1 << UDC_EPSTS_HE) |
+			 (1 << UDC_EPSTS_TDC) | (1 << UDC_EPSTS_RCS) |
+						 (1 << UDC_EPSTS_TXEMPTY) |
+			 (1 << UDC_EPSTS_XFERDONE))) == 0) {
+		IOH_DEBUG("Non interrupt request ep%din status %x",
+							 ep->num, epsts);
+		return;
+	}
+	if ((epsts & (1 << UDC_EPSTS_BNA))) { /* Just log it */
+		IOH_DEBUG("BNA on ep%din occured", ep->num);
+		return;
+	}
+	if (epsts & (1 << UDC_EPSTS_HE)) {
+		IOH_DEBUG("Host Error on ep%din occured", ep->num);
+		return;
+	}
+	if (epsts & (1 << UDC_EPSTS_TXEMPTY)) { /* Tx empty */
+		IOH_DEBUG("ioh_udc_ep0_in intr: TXEMPTY");
+	}
+	if ((epsts & (1 << UDC_EPSTS_TDC)) && (!dev->stall)) {
+		/* DMA completed */
+		IOH_DEBUG("TDC on ep%din", ep->num);
+		ioh_udc_complete_transfer(ep);
+	}
+	/* On IN interrupt, provide data if we have any */
+	if ((epsts & (1 << UDC_EPSTS_IN)) &&
+		 ((epsts & (1 << UDC_EPSTS_TDC)) == 0) &&
+		 ((epsts & (1 << UDC_EPSTS_TXEMPTY)) == 0))	{
+		ioh_udc_start_next_txrequest(ep);
+	}
+}
+
+/*!@ingroup	UDC_UtilitiesAPI
+ *@fn		static void ioh_udc_svc_control_out(struct ioh_udc_dev *dev)
+ *@brief	Routine that handle Control OUT endpoint interrupts
+ *@param	dev 		Reference to the device structure
+ *@return	none
+ *@remarks	The following actions are performed:
+ *			- If Buffer NOT Available, log a debug message
+ *			- If setup data present
+ *- Set device stall status to False
+ *- Invoke ioh_udc_ep_set_nak API to set SNAK field of IN endpoint register
+ *- Get the data from setup data descriptor
+ * Initialize setup data descriptor using ioh_udc_fifo_read API
+ *- Disable the TX DMA using ioh_udc_clear_dma API
+ *- Make the gadget's ep0 point to appropriate endpoint
+ *						 structure (ep0 IN or OUT)
+ *  based on the request type
+ *- If the receive data is "Mass storage Reset", clear the protocol stall flag.
+ *- Invoke the gadget driver's setup routine with data received
+ *- if the setup routine returns a value between 0 and maximum packet size
+ *  (ep0 in returns data on IN phase),
+ *	- Invoke ioh_udc_ep_clear_nak API to clear NAK for In endpoint 0.
+ *	- Enable DMA for RX using ioh_udc_set_dma API.
+ *	- Invoke ioh_udc_ep_clear_nak API to clear NAK for In endpoint 0.
+ *- If the setup routine fails (returns < 0),
+ *	- Stall the device using ioh_udc_ep_set_stall API
+ *	- Enable the interrupt endpoint
+ *	- Enable DMA for RX using ioh_udc_set_dma API.
+ *- Otherwise
+ *	- Set 'waiting for zlp ACK' status as TRUE
+ *- If data is present
+ *- If request queue is empty,
+ *	- Set the descriptor status as HOST_BUSY
+ *	- Enable DMA for RX using ioh_udc_set_dma API.
+ *- Otherwise
+ *	- Invoke ioh_udc_svc_data_out to handle the request.
+ *	- Re-program the data descriptor using ioh_udc_ep_set_ddptr API
+ *	- Enable Rx DMA using ioh_udc_set_dma API
+ *@see
+ *			- ioh_udc_ep_set_nak
+ *			- ioh_udc_init_setup_buff
+ *			- ioh_udc_clear_dma
+ *			- ioh_udc_ep_fifo_flush
+ *			- ioh_udc_ep_clear_nak
+ *			- ioh_udc_set_dma
+ *			- ioh_udc_ep_set_stall
+ *			- ioh_udc_enable_ep_interrupts
+ *			- ioh_udc_svc_data_out
+ *			- ioh_udc_ep_set_ddptr
+ *			- ioh_udc_ep_set_rrdy
+ */
+static void ioh_udc_svc_control_out(struct ioh_udc_dev *dev)
+{
+	u32	stat;
+	int setup_supported;
+	struct ioh_udc_ep	*ep;
+
+	IOH_DEBUG("ioh_udc_ep0_out");
+	ep = &dev->ep[UDC_EP0OUT_IDX];
+	stat = ep->epsts;
+	ep->epsts = 0;
+
+	if (stat & (1 << UDC_EPSTS_BNA)) {
+		IOH_DEBUG("EP0: BNA");
+		/* When we get a request, we will populate the descriptors. */
+		/* Anything else to do? */
+	}
+	/* If setup data */
+	if (((stat & UDC_EPSTS_OUT_MASK) >> UDC_EPSTS_OUT_OFS) ==
+							 UDC_EPSTS_OUT_SETUP) {
+		dev->stall = 0;
+		dev->ep[UDC_EP0IN_IDX].halted = 0;
+		dev->ep[UDC_EP0OUT_IDX].halted = 0;
+		/* In data not ready */
+		ioh_udc_ep_set_nak(dev->ep[UDC_EP0IN_IDX].regs);
+		setup_data.data[0] = ep->td_stp->data12;
+		setup_data.data[1] = ep->td_stp->data34;
+		IOH_DEBUG("EP0 setup data12: 0x%x data34:0x%x",
+				 ep->td_stp->data12, ep->td_stp->data34);
+		ioh_udc_init_setup_buff(ep->td_stp);
+		ioh_udc_clear_dma(dev->regs, DMA_DIR_TX);
+		ioh_udc_ep_fifo_flush(dev->ep[UDC_EP0IN_IDX].regs,
+						 dev->ep[UDC_EP0IN_IDX].in);
+		if ((setup_data.request.bRequestType & USB_DIR_IN) != 0) {
+			dev->gadget.ep0 = &dev->ep[UDC_EP0IN_IDX].ep;
+		} else { /*	OUT */
+			dev->gadget.ep0 = &ep->ep;
+		}
+		IOH_DEBUG("EP0 setup data: 0x%x 0x%x", setup_data.data[0],
+							 setup_data.data[1]);
+		spin_unlock(&dev->lock);
+		/* Mass storage Reset */
+		if ((setup_data.data[0] == 0x0000ff21) && (setup_data.data[1] ==
+								 0x00000000)) {
+			dev->prot_stall = 0;
+			IOH_DEBUG("Mass storage reset  prot_stall = %d",
+							 dev->prot_stall);
+		}
+		/* call gadget with setup data received */
+		setup_supported = dev->driver->setup(&dev->gadget,
+							 &setup_data.request);
+		spin_lock(&dev->lock);
+
+		/* ep0 in returns data on IN phase */
+		if (setup_supported >= 0 && setup_supported <
+						 UDC_EP0IN_MAX_PKT_SIZE) {
+			ioh_udc_ep_clear_nak(dev->ep[UDC_EP0IN_IDX].regs);
+			/* Gadget would have queued a request when
+							 we called the setup */
+			ioh_udc_set_dma(dev->regs, DMA_DIR_RX);
+			ioh_udc_ep_clear_nak(ep->regs);
+		} else if (setup_supported < 0) {
+			/* if unsupported request, then stall */
+			IOH_DEBUG("EP0 setup unsupported: ep0_set_stall");
+			ioh_udc_ep_set_stall(dev->ep[UDC_EP0IN_IDX].regs);
+			ioh_udc_enable_ep_interrupts(ep->dev->regs,
+				1 << (ep->in ? ep->num : ep->num +
+							 UDC_EPINT_OUT_EP0));
+			dev->stall = 0;
+			ioh_udc_set_dma(dev->regs, DMA_DIR_RX);
+		} else {
+			dev->waiting_zlp_ack = 1;
+		}
+	} else if ((((stat & UDC_EPSTS_OUT_MASK) >> UDC_EPSTS_OUT_OFS) ==
+				 UDC_EPSTS_OUT_DATA) && (dev->stall == 0)) {
+		if (list_empty(&ep->queue)) {
+			IOH_LOG(KERN_ERR, "control_out: ZLP");
+			/* If no requests, reactivate */
+			ep->td_data->status =
+					(ep->td_data->status &
+							 ~IOH_UDC_BUFF_STS) |
+							IOH_UDC_BS_HST_RDY;
+			/* Enable RDE */
+			ioh_udc_set_dma(dev->regs, DMA_DIR_RX);
+		} else {
+			/* control write */
+			ioh_udc_svc_data_out(dev, UDC_EP0OUT_IDX);
+			/* re-program desc. pointer for possible ZLPs */
+			ioh_udc_ep_set_ddptr(ep->regs,
+					ep->td_data_phys);
+			/* Enable RDE */
+			ioh_udc_set_dma(dev->regs, DMA_DIR_RX);
+		}
+	}
+	ioh_udc_ep_set_rrdy(ep->regs);
+}
+
+/*!@ingroup	UDC_UtilitiesAPI
+ *@fn	static void ioh_udc_svc_data_in(struct ioh_udc_dev *dev, int ep_num)
+ *@brief	This function process endpoint interrupts for IN endpoints
+ *@param	dev 	Reference to the device structure
+ *@param	ep_num	Endpoint that generated the interrupt
+ *@return	none
+ *@remarks The interrupts are processed as follows:
+ *- If the interrupt is HE, log the error message
+ *- If the interrupt is RSS,
+ *	- Set STALL useig ioh_udc_ep_set_stall API
+ *	- Enable endpoint interrupts for out endpoint
+ *- If the interrupt is RCS,
+ *	- If the protocol stall flag not set,
+ *		- Clear stall useing ioh_udc_ep_clear_stall API
+ *	- Otherwise
+ *		- Set STALL using ioh_udc_ep_set_stall API.
+ *		- Enable endpoint interrupts for out endpoint
+ *- If the interrupt is TDC,
+ *	- Invoke the completion routine using ioh_udc_complete_receiver API
+ *- If the interrupt is IN, and is not RSS/TDC/TXEMPTY
+ *	- Start the next transmit request using ioh_udc_start_next_txrequest API
+ *@see
+ *			- ioh_udc_ep_set_stall
+ *			- ioh_udc_enable_ep_interrupts
+ *			- ioh_udc_ep_clear_stall
+ *			- ioh_udc_complete_transfer
+ *			- ioh_udc_start_next_txrequest
+ */
+static void ioh_udc_svc_data_in(struct ioh_udc_dev *dev, int ep_num)
+{
+	u32	epsts;
+	struct ioh_udc_ep	*ep;
+	ep = &dev->ep[2*ep_num];
+	epsts = ep->epsts;
+	ep->epsts = 0;
+
+	IOH_DEBUG("ioh_udc_svc_data_in: ep%d%s status = 0x%08x", ep->num,
+					 (ep->in ? "in" : "out"), epsts);
+
+	if ((epsts & ((1 << UDC_EPSTS_IN) | (1 << UDC_EPSTS_BNA)  |
+						 (1 << UDC_EPSTS_HE) |
+			 (1 << UDC_EPSTS_TDC) | (1 << UDC_EPSTS_RCS) |
+						 (1 << UDC_EPSTS_TXEMPTY) |
+			 (1 << UDC_EPSTS_RSS) |
+			 (1 << UDC_EPSTS_XFERDONE))) == 0) {
+		IOH_DEBUG("Non interrupt request ep%din status %x",
+							 ep->num, epsts);
+		return;
+	}
+	if ((epsts & (1 << UDC_EPSTS_BNA))) { /* Just log it */
+		IOH_DEBUG("BNA on ep%din occured", ep->num);
+		return;
+	}
+	if (epsts & (1 << UDC_EPSTS_HE)) {
+		IOH_DEBUG("Host Error on ep%din occured", ep->num);
+		return;
+	}
+	if (epsts & (1 << UDC_EPSTS_RSS)) {
+		IOH_DEBUG("ioh_udc_svc_data_in: RSS");
+		ioh_udc_ep_set_stall(ep->regs);
+		ioh_udc_enable_ep_interrupts(ep->dev->regs,
+			1 << (ep->in ? ep->num : ep->num + UDC_EPINT_OUT_EP0));
+	}
+	if (epsts & (1 << UDC_EPSTS_RCS)) {
+		IOH_DEBUG("ioh_udc_svc_data_in: RCS  prot_stall = %d",
+							 dev->prot_stall);
+		if (dev->prot_stall == 0) {
+			ioh_udc_ep_clear_stall(ep->regs);
+		} else {
+			ioh_udc_ep_set_stall(ep->regs);
+			ioh_udc_enable_ep_interrupts(ep->dev->regs,
+				1 << (ep->in ? ep->num : ep->num +
+							 UDC_EPINT_OUT_EP0));
+		}
+	}
+	if (epsts & (1 << UDC_EPSTS_TDC)) { /* DMA completed */
+		ioh_udc_complete_transfer(ep);
+	}
+	/* On IN interrupt, provide data if we have any */
+	if ((epsts & (1 << UDC_EPSTS_IN)) &&
+		 ((epsts & (1 << UDC_EPSTS_RSS)) == 0) &&
+		 ((epsts & (1 << UDC_EPSTS_TDC)) == 0) &&
+		 ((epsts & (1 << UDC_EPSTS_TXEMPTY)) == 0)) {
+		ioh_udc_start_next_txrequest(ep);
+	}
+	IOH_DEBUG("ioh_udc_ep_in intr ep ctrl = 0x%x",
+					 IOH_READ32((u32)&ep->regs->epctl));
+}
+
+/*!@ingroup	UDC_InterfaceLayerAPI
+ *@fn		static void ioh_udc_complete_transfer(struct ioh_udc_ep	*ep)
+ *@brief	This function completes a transfer
+ *@param	ep 		Reference to the endpoint structure
+ *@remarks	The following actions are performed:
+ * - Get the request from the queue
+ * - If the request is valid, do the following
+ *- Get the last dma descriptor. if the DMA transfer is completed,
+ *	- update the request length as actual
+ *- If the actual length has been updated,
+ *	- update the status field of the last request
+ *	- complete the request using complete_req function
+ *	- set dma in progress status as false
+ *	- if there are pending requests, clear NAK using ioh_udc_ep_clear_nak
+ *								 and enable
+ *		endpoint interrupts
+ *		- if there are no pending requests, set DMA in progress status
+ *							 as false and disable
+ *				endpoint interrupts
+ *@return none
+ *@see
+ *			- complete_req
+ *			- ioh_udc_read_ep_control
+ *			- ioh_udc_ep_clear_nak
+ *			- ioh_udc_enable_ep_interrupts
+ *			- ioh_udc_disable_ep_interrupts
+ */
+static void ioh_udc_complete_transfer(struct ioh_udc_ep	*ep)
+{
+	struct ioh_udc_request *req;
+
+	IOH_DEBUG("ioh_udc_complete_transfer");
+
+	if (!list_empty(&ep->queue)) {
+		IOH_DEBUG("list_entry");
+		req = list_entry(ep->queue.next, struct ioh_udc_request, queue);
+		if (req && ((req->td_data_last->status & IOH_UDC_BUFF_STS) ==
+							 IOH_UDC_BS_DMA_DONE)) {
+#ifdef DMA_PPB_WITH_DESC_UPDATE
+			struct ioh_udc_data_dma_desc *td_data = req->td_data;
+			for (i = 0; i < req->chain_len; i++) {
+				if ((td_data->status & IOH_UDC_RXTX_STS) !=
+							 IOH_UDC_RTS_SUCC) {
+					IOH_LOG(KERN_ERR, "Invalid RXTX status\
+						 (0x%08x) epstatus=0x%08x\n",
+							(td_data->status &
+							 IOH_UDC_RXTX_STS),
+							 (int)(ep->epsts));
+					return;
+				}
+				td_data = (struct ioh_udc_data_dma_desc *)
+						 phys_to_virt(td_data->next);
+			}
+#else
+			if ((req->td_data_last->status & IOH_UDC_RXTX_STS) !=
+							 IOH_UDC_RTS_SUCC) {
+				IOH_LOG(KERN_ERR, "Invalid RXTX status (0x%08x)\
+							 epstatus=0x%08x\n",
+						(req->td_data_last->status &
+						 IOH_UDC_RXTX_STS),
+						 (int)(ep->epsts));
+				return;
+			}
+#endif
+			req->req.actual = req->req.length;
+			req->td_data_last->status = IOH_UDC_BS_HST_BSY |
+							 IOH_UDC_DMA_LAST;
+			req->td_data->status = IOH_UDC_BS_HST_BSY |
+							 IOH_UDC_DMA_LAST;
+			/* complete req */
+			complete_req(ep, req, 0);
+			req->dma_going = 0;
+			if (!list_empty(&ep->queue)) {
+				while (ioh_udc_read_ep_control(ep->regs) &
+							 (1 << UDC_EPCTL_S))
+					udelay(100);
+
+				ioh_udc_ep_clear_nak(ep->regs);
+				ioh_udc_enable_ep_interrupts(ep->dev->regs,
+					1 << (ep->in ? ep->num : ep->num +
+							 UDC_EPINT_OUT_EP0));
+			} else {
+				ioh_udc_disable_ep_interrupts(ep->dev->regs,
+					1 << (ep->in ? ep->num : ep->num +
+							 UDC_EPINT_OUT_EP0));
+			}
+		}
+	}
+}
+
+/*!@ingroup	UDC_InterfaceLayerAPI
+ *@fn		static void ioh_udc_complete_receiver(struct ioh_udc_ep	*ep)
+ *@brief	This function completes a receiver
+ *@param	ep 		Reference to the endpoint structure
+ *@remarks	The following actions are performed:
+ *			 - If request queue is not empty, get next request
+ *			 - If buffer status is DMA Done
+ *				- Disable DMA using ioh_udc_clear_dma API
+ *				- Get size of Rx bytes
+ *				- Set the descriptor status
+ *				- Complete the request using complete_req API
+ *				- If there is a new/failed requests try that
+ *					now using ioh_udc_start_rxrequest API
+ *			 - Otherwise
+ *				- Set receive ready using ioh_udc_ep_set_rrdy
+ *@return none
+ *@see
+ *			- ioh_udc_clear_dma
+ *			- complete_req
+ *			- ioh_udc_start_rxrequest
+ *			- ioh_udc_ep_set_rrdy
+ */
+static void ioh_udc_complete_receiver(struct ioh_udc_ep	*ep)
+{
+	struct ioh_udc_request *req;
+	unsigned int count;
+
+	IOH_DEBUG("ioh_udc_complete_receiver");
+
+	if (!list_empty(&ep->queue)) {
+		/* next request */
+		req = list_entry(ep->queue.next, struct ioh_udc_request, queue);
+		if (req && (req->td_data_last->status & IOH_UDC_BUFF_STS) ==
+							IOH_UDC_BS_DMA_DONE) {
+			IOH_DEBUG("ioh_udc_complete_receiver: ep%d%s  DMA Done",
+					 ep->num, (ep->in ? "in" : "out"));
+			/* Disable DMA */
+			ioh_udc_clear_dma(ep->dev->regs, DMA_DIR_RX);
+#ifdef DMA_PPB_WITH_DESC_UPDATE
+{
+			/* Get Rx bytes */
+			struct ioh_udc_data_dma_desc *td_data = req->td_data;
+			for (i = 0, count = 0; i < req->chain_len; i++) {
+				if ((td_data->status & IOH_UDC_RXTX_STS) !=
+							 IOH_UDC_RTS_SUCC) {
+					IOH_LOG(KERN_ERR, "Invalid RXTX status\
+						 (0x%08x) epstatus=0x%08x\n",
+							(td_data->status &
+							 IOH_UDC_RXTX_STS),
+							 (int)(ep->epsts));
+					return;
+				}
+				count += td_data->status & IOH_UDC_RXTX_BYTES;
+				td_data = (struct ioh_udc_data_dma_desc *)\
+						 phys_to_virt(td_data->next);
+			}
+}
+#else
+			if ((req->td_data_last->status & IOH_UDC_RXTX_STS) !=
+							 IOH_UDC_RTS_SUCC) {
+				IOH_LOG(KERN_ERR, "Invalid RXTX status (0x%08x)\
+							 epstatus=0x%08x\n",
+						(req->td_data_last->status &
+						 IOH_UDC_RXTX_STS),
+						 (int)(ep->epsts));
+				return;
+			}
+			count = req->td_data_last->status & IOH_UDC_RXTX_BYTES;
+#endif
+			if ((count == 0) && (req->req.length ==
+						 UDC_DMA_MAXPACKET)) {
+				/* on 64k packets the RXBYTES field is zero */
+				count = UDC_DMA_MAXPACKET;
+			}
+
+			/* Set the descriptor status */
+			req->td_data->status |= IOH_UDC_DMA_LAST;
+			req->td_data_last->status |= IOH_UDC_BS_HST_BSY;
+
+			req->dma_going = 0;
+			/* complete request */
+			req->req.actual = count;
+			complete_req(ep, req, 0);
+
+			/* If there is a new/failed requests try that now */
+			if (!list_empty(&ep->queue)) {
+				req = list_entry(ep->queue.next,
+						 struct ioh_udc_request, queue);
+				ioh_udc_start_rxrequest(ep, req);
+			}
+		}
+#ifdef DMA_PPB_WITH_DESC_UPDATE
+		else {
+			IOH_DEBUG("ioh_udc_complete_receiver: ep%d%s  \
+			DMA not Done", ep->num, (ep->in ? "in" : "out"));
+			ioh_udc_ep_set_rrdy(ep->regs);
+		}
+#endif
+	}
+}
+
+/*!@ingroup	UDC_InterfaceLayerAPI
+ *@fn		static void ioh_udc_start_next_txrequest(struct ioh_udc_ep *ep)
+ *@brief	This function starts the next transmission requirement
+ *@param	ep 		Reference to the endpoint structure
+ *@remarks	The following actions are performed:
+ *- If poll demand bit is set, return
+ *- If request queue is not empty, get next request from the queue
+ *- If the DMA going flag of next request queue is 1, invoke the following
+ *								 actions.
+ *	- Clear the descriptor pointer
+ *	- Set the all descriptor status to "Host ready"
+ *	- Write the descriptor pointer
+ *	- Enable the Tx DMA
+ *	- Set the poll demand bit
+ *	- Enable the interrupts of endpoint
+ *	- Clear the status of NAK
+ *@see
+ *			- ioh_udc_read_ep_control
+ *			- ioh_udc_ep_set_ddptr
+ *			- ioh_udc_set_dma
+ *			- ioh_udc_ep_set_pd
+ *			- ioh_udc_enable_ep_interrupts
+ *			- ioh_udc_ep_clear_nak
+ */
+static void ioh_udc_start_next_txrequest(struct ioh_udc_ep	*ep)
+{
+	struct ioh_udc_request *req;
+	IOH_DEBUG("ioh_udc_start_next_txrequest: enter");
+	if (ioh_udc_read_ep_control(ep->regs) & (1 << UDC_EPCTL_P))
+		return;
+
+	if (!list_empty(&ep->queue)) {
+		/* next request */
+		req = list_entry(ep->queue.next, struct ioh_udc_request, queue);
+		if (req && !req->dma_going) {
+			IOH_DEBUG("Set request: req=%p req->td_data=%p", req,
+								 req->td_data);
+			if (req->td_data) {
+				struct ioh_udc_data_dma_desc *td_data;
+
+				while (ioh_udc_read_ep_control(ep->regs) &
+							 (1 << UDC_EPCTL_S))
+					udelay(100);
+
+				req->dma_going = 1;
+				/* Clear the descriptor pointer */
+				ioh_udc_ep_set_ddptr(ep->regs, 0);
+
+				td_data = req->td_data;
+				while (1) {
+					td_data->status = (td_data->status &
+						 ~IOH_UDC_BUFF_STS) |
+						 IOH_UDC_BS_HST_RDY;
+					if ((td_data->status &
+						 IOH_UDC_DMA_LAST) ==
+						 IOH_UDC_DMA_LAST)
+						break;
+
+					td_data =
+					(struct ioh_udc_data_dma_desc *)\
+					phys_to_virt(td_data->next);
+				}
+				/* Write the descriptor pointer */
+				ioh_udc_ep_set_ddptr(ep->regs,
+							 req->td_data_phys);
+				/* Enable the Tx DMA */
+				ioh_udc_set_dma(ep->dev->regs, DMA_DIR_TX);
+				/* Set the poll demand bit */
+				ioh_udc_ep_set_pd(ep->regs);
+				/* Enable the interrupts of endpoint */
+				ioh_udc_enable_ep_interrupts(ep->dev->regs,
+						1 << (ep->in ? ep->num :\
+						 ep->num + UDC_EPINT_OUT_EP0));
+				/* Clear NAK */
+				ioh_udc_ep_clear_nak(ep->regs);
+			}
+		}
+	}
+}
+/*!@ingroup	UDC_InterfaceLayerAPI
+ *@fn		static void ioh_udc_start_rxrequest(struct ioh_udc_ep *ep,
+ *						 struct ioh_udc_request *req)
+ *@brief	This function starts the receive requirement.
+ *@param	ep 		Reference to the endpoint structure
+ *@param	req 	Reference to the request structure
+ *@remarks	The following actions are performed:
+ *			- Disable the Rx DMA
+ *			- Set the status bits for all descriptors
+ *			- Write the descriptor pointer
+ *			- Enable the interrupts of endpoint
+ *			- Enable the Rx DMA
+ *			- Clear NAK
+ *			- Set the receive ready
+ *@see
+ *			- ioh_udc_clear_dma
+ *			- ioh_udc_ep_set_ddptr
+ *			- ioh_udc_enable_ep_interrupts
+ *			- ioh_udc_set_dma
+ *			- ioh_udc_ep_clear_nak
+ *			- ioh_udc_ep_set_rrdy
+ */
+static void ioh_udc_start_rxrequest(struct ioh_udc_ep *ep,
+						 struct ioh_udc_request *req)
+{
+	struct ioh_udc_data_dma_desc *td_data;
+
+	IOH_DEBUG("ioh_udc_start_request: enter");
+	/* Disable Rx DMA */
+	ioh_udc_clear_dma(ep->dev->regs, DMA_DIR_RX);
+	td_data = req->td_data;
+	ep->td_data = req->td_data;
+	/* Set the status bits for all descriptors */
+	while (1) {
+		td_data->status = (td_data->status & ~IOH_UDC_BUFF_STS) |
+							 IOH_UDC_BS_HST_RDY;
+		if ((td_data->status & IOH_UDC_DMA_LAST) ==  IOH_UDC_DMA_LAST)
+			break;
+
+		td_data = (struct ioh_udc_data_dma_desc *) \
+						phys_to_virt(td_data->next);
+	}
+	/* Write the descriptor pointer */
+	ioh_udc_ep_set_ddptr(ep->regs, req->td_data_phys);
+	req->dma_going = 1;
+	/* Enable endpoint interrupts */
+	ioh_udc_enable_ep_interrupts(ep->dev->regs, 1 <<
+						 (ep->num + UDC_EPINT_OUT_EP0));
+	/* Enable Rx DMA */
+	ioh_udc_set_dma(ep->dev->regs, DMA_DIR_RX);
+	/* Clear NAK */
+	ioh_udc_ep_clear_nak(ep->regs);
+	/* Set receive ready */
+	ioh_udc_ep_set_rrdy(ep->regs);
+}
+
+/*!@ingroup	UDC_InterfaceLayerAPI
+ *@fn		static void ioh_udc_postsvc_epinters(struct ioh_udc_dev *dev,
+ *								 int ep_num)
+ *@brief	This function enables end point interrupts and clears NAK status
+ *@param	dev 		Reference to the device structure
+ *@param	ep_num    End point number
+ *@return	none
+ *@remarks	The following actions are performed:
+ *			- If the end point request queue is not empty,
+ *			- Enable  the endpoint interrupts using
+ *						 ioh_udc_enable_ep_interrupts
+ *			- Clear Endpoint NAK status using ioh_udc_ep_clear_nak
+ *@see
+ *			- ioh_udc_enable_ep_interrupts
+ *			- ioh_udc_ep_clear_nak
+ */
+static void ioh_udc_postsvc_epinters(struct ioh_udc_dev *dev, int ep_num)
+{
+	struct ioh_udc_ep	*ep;
+	struct ioh_udc_request *req;
+	ep = &dev->ep[2*ep_num];
+
+	if (!list_empty(&ep->queue)) {
+		req = list_entry(ep->queue.next, struct ioh_udc_request, queue);
+		ioh_udc_enable_ep_interrupts(ep->dev->regs,
+			1 << (ep->in ? ep->num : ep->num + UDC_EPINT_OUT_EP0));
+		ioh_udc_ep_clear_nak(ep->regs);
+	}
+}
+
+/* Interrupt Service Routine */
+/*!@ingroup	UDC_InterfaceLayerAPI
+ *@fn		irqreturn_t ioh_udc_isr(int irq, void *pdev)
+ *@brief	This function handles interrupts from the IOH USB Device
+ *@param	irq 		Interrupt request number
+ *@param	dev 		Reference to the device structure
+ *@return	none
+ *@remarks	The following actions are performed:
+ *- Read the device and endpoint interrupt registers
+ *- Clear the device and endpoint interrupts using
+ *					ioh_udc_write_device_interrupts
+ *	and ioh_udc_write_ep_interrupts APIs respectively
+ *- If there are no interrupts, return IRQ_NONE
+ *- If there are any device interrupt(s), invoke ioh_udc_dev_isr
+ *							 to process those
+ *- Invoke ioh_udc_read_all_epstatus to read endpoint interrupts status
+ *- If there is interrupt asserted on EP0 IN,
+ *  invoke ioh_udc_svc_control_in and ioh_udc_postsvc_epinters.
+ *- If there is interrupt asserted on EP0 OUT, invoke ioh_udc_svc_control_out
+ *- For all other IN end points for which the interrupt bit is set,
+ *  invoke ioh_udc_svc_data_in and ioh_udc_postsvc_epinters.
+ *- For all other OUT end points for which the interrupt bit is set,
+ *  invoke ioh_udc_svc_data_out
+ *- Return IRQ_HANDLED
+ *@see
+ *			- ioh_udc_read_device_interrupts
+ *			- ioh_udc_read_ep_interrupts
+ *			- ioh_udc_write_device_interrupts
+ *			- ioh_udc_write_ep_interrupts
+ *			- ioh_udc_dev_isr
+ *			- ioh_udc_svc_control_out
+ *			- ioh_udc_svc_control_in
+ *			- ioh_udc_svc_data_out
+ *			- ioh_udc_svc_data_in
+ *			- ioh_udc_read_all_epstatus
+ *			- ioh_udc_postsvc_epinters
+ */
+irqreturn_t ioh_udc_isr(int irq, void *pdev)
+{
+	struct ioh_udc_dev *dev;
+	u32 dev_intr, ep_intr;
+	int i;
+
+	IOH_DEBUG("ioh_udc_isr: enter");
+	dev = (struct ioh_udc_dev *) pdev;
+	dev_intr = ioh_udc_read_device_interrupts(dev->regs);
+	ep_intr = ioh_udc_read_ep_interrupts(dev->regs);
+
+	if (dev_intr != 0) {
+		/* Clear device interrupts */
+		ioh_udc_write_device_interrupts(dev->regs, dev_intr);
+	}
+	if (ep_intr != 0) {
+		/* Clear ep interrupts */
+		ioh_udc_write_ep_interrupts(dev->regs, ep_intr);
+	}
+	if ((dev_intr == 0) && (ep_intr == 0)) {
+		IOH_DEBUG("ioh_udc_isr: exit IRQ_NONE");
+		return IRQ_NONE;
+	}
+	spin_lock(&dev->lock);
+
+	if (dev_intr != 0) {
+		IOH_DEBUG("ioh_udc_isr: device intr 0x%x", dev_intr);
+		ioh_udc_dev_isr(dev, dev_intr);
+	}
+
+	if (ep_intr != 0) {
+		IOH_DEBUG("ioh_udc_isr: ep intr 0x%x", ep_intr);
+		ioh_udc_read_all_epstatus(dev, ep_intr);
+
+		/* Process Control In interrupts, if present */
+		if (ep_intr & (1 << UDC_EPINT_IN_EP0)) {
+			ioh_udc_svc_control_in(dev);
+			ioh_udc_postsvc_epinters(dev, 0);
+		}
+		/* Process Control Out interrupts, if present */
+		if (ep_intr & (1 << UDC_EPINT_OUT_EP0))
+			ioh_udc_svc_control_out(dev);
+
+		/* Process data in end point interrupts */
+		for (i = 1; i < IOH_UDC_USED_EP_NUM; i++) {
+			if (ep_intr & (1 <<  i)) {
+				ioh_udc_svc_data_in(dev, i);
+				ioh_udc_postsvc_epinters(dev, i);
+			}
+		}
+		/* Process data out end point interrupts */
+		for (i = UDC_EPINT_OUT_EP1; i < (UDC_EPINT_OUT_EP0 +
+						 IOH_UDC_USED_EP_NUM); i++) {
+			if (ep_intr & (1 <<  i))
+				ioh_udc_svc_data_out(dev, i -
+							 UDC_EPINT_OUT_EP0);
+		}
+	}
+	spin_unlock(&dev->lock);
+	IOH_DEBUG("ioh_udc_isr: exit IRQ_HANDLED");
+
+	return IRQ_HANDLED;
+}
+
+/*!@ingroup	UDC_UtilitiesAPI
+ *@fn		void ioh_udc_activate_control_ep(struct ioh_udc_dev *dev)
+ *@brief This function enables the control endpoints for traffic after a reset
+ *@param	dev 		Reference to the device structure
+ *@return	none
+ *@remarks	The following actions are performed:
+ *- Setup IN endpoint,
+ *	- Flush the TX FIFO using ioh_udc_ep_fifo_flush API
+ *	- Set the buffer size for TXFIFO entries of EP0_IN using
+ *						 ioh_udc_ep_set_bufsz API
+ *	- Set max packet size of EP0 IN using ioh_udc_ep_set_maxpkt API
+ *	- Initialize the IN EP Descriptor
+ *- Setup OUT endpoint,
+ *	- Flush the RX FIFO using ioh_udc_ep_fifo_flush API
+ *	- Set max packet size of EP0 OUT using ioh_udc_ep_set_maxpkt.
+ *	- Set max packet size of EP0 OUT UDC CSR
+ *	- Initialize the SETUP buffer
+ *	- Write the DMA Descriptor address
+ *	- Write the Setup Descriptor address
+ *	- Initialize the DMA descriptor
+ *	- Clear NAK
+ *@see
+ *			- ioh_udc_clear_ep_control
+ *			- ioh_udc_ep_fifo_flush
+ *			- ioh_udc_ep_set_bufsz
+ *			- ioh_udc_ep_set_maxpkt
+ *			- ioh_udc_write_csr
+ *			- ioh_udc_init_setup_buff
+ *			- ioh_udc_ep_set_subptr
+ *			- ioh_udc_ep_set_ddptr
+ *			- ioh_udc_ep_clear_nak
+ */
+void ioh_udc_activate_control_ep(struct ioh_udc_dev *dev)
+{
+	struct ioh_udc_ep	*ep;
+	u32 val;
+	/* Setup IN endpoint ----------------------------- */
+	ep = &dev->ep[UDC_EP0IN_IDX];
+
+	/* Flush TX fifo */
+	ioh_udc_clear_ep_control(ep->regs);
+	ioh_udc_ep_fifo_flush(ep->regs, ep->in);
+
+	/* Set buffer size (tx fifo entries) of EP0_IN  */
+	ioh_udc_ep_set_bufsz(ep->regs, UDC_EP0IN_BUFF_SIZE, ep->in);
+
+	/* Set max packet size of EP0_IN */
+	ioh_udc_ep_set_maxpkt(ep->regs, UDC_EP0IN_MAX_PKT_SIZE);
+
+	/* Initialize the IN EP Descriptor */
+	ep->td_data      = NULL;
+	ep->td_stp       = NULL;
+	ep->td_data_phys = 0;
+	ep->td_stp_phys  = 0;
+
+	/* Setup OUT endpoint ----------------------------- */
+	ep = &dev->ep[UDC_EP0OUT_IDX];
+
+	/* Flush RX fifo */
+	ioh_udc_clear_ep_control(ep->regs);
+	ioh_udc_ep_fifo_flush(ep->regs, ep->in);
+
+	/* Set buffer size (rx fifo entries) of EP0_OUT  */
+	ioh_udc_ep_set_bufsz(ep->regs, UDC_EP0OUT_BUFF_SIZE, ep->in);
+
+	/* Set max packet size of EP0_OUT */
+	ioh_udc_ep_set_maxpkt(ep->regs, UDC_EP0OUT_MAX_PKT_SIZE);
+
+	/* Set max packet size of EP0 OUT UDC CSR */
+	val = UDC_EP0OUT_MAX_PKT_SIZE << UDC_CSR_NE_MAX_PKT_OFS;
+	ioh_udc_write_csr(val, (u32) (&dev->csr->ne[UDC_EP0OUT_IDX]));
+
+	/* Initialize the SETUP buffer */
+	ioh_udc_init_setup_buff(ep->td_stp);
+
+	/* Write dma desc address */
+	ioh_udc_ep_set_subptr(ep->regs, ep->td_stp_phys);
+
+	/* Write Setup desc address */
+	ioh_udc_ep_set_ddptr(ep->regs, ep->td_data_phys);
+
+	/* Initialize dma descriptor */
+	ep->td_data->status  = IOH_UDC_DMA_LAST;
+	ep->td_data->dataptr = dma_addr;
+	ep->td_data->next    = ep->td_data_phys;
+
+	/* Clear NAK */
+	ioh_udc_ep_clear_nak(ep->regs);
+}
+
+/*!@ingroup	UDC_UtilitiesAPI
+ *@fn		ioh_udc_read_all_epstatus(struct ioh_udc_dev *dev, u32 ep_intr)
+ *@brief	This function read all endpoint status
+ *@param	dev 		Reference to the device structure
+ *@param	ep_intr 	Status of endpoint interrupt
+ *@return	none
+ *@remarks	The following actions are performed:
+ *			-  For each of the used endpoints,
+ *				- Read the endpoint status using
+ *							 ioh_udc_read_ep_status
+ *				-  Invoke ioh_udc_clear_ep_status to clear
+ *								 the status
+ *@see
+ *			- ioh_udc_read_ep_status
+ *			- ioh_udc_clear_ep_status
+ */
+static void ioh_udc_read_all_epstatus(struct ioh_udc_dev *dev, u32 ep_intr)
+{
+	int i;
+	struct ioh_udc_ep	*ep;
+
+	for (i = 0; i < IOH_UDC_USED_EP_NUM; i++) {
+		/* IN */
+		if (ep_intr & (0x1 << i)) {
+			ep = &dev->ep[2*i];
+			ep->epsts = ioh_udc_read_ep_status(ep->regs);
+			ioh_udc_clear_ep_status(ep->regs, ep->epsts);
+		}
+		/* OUT */
+		if (ep_intr & (0x10000 << i)) {
+			ep = &dev->ep[2*i+1];
+			ep->epsts = ioh_udc_read_ep_status(ep->regs);
+			ioh_udc_clear_ep_status(ep->regs, ep->epsts);
+		}
+	}
+	return;
+}
+
+/*!@ingroup	UDC_UtilitiesAPI
+ *@fn		static void ioh_udc_setup_ep0(struct ioh_udc_dev *dev)
+ *@brief	This function enables control endpoint for traffic
+ *@remarks	The following actions are performed:
+ *			- Enable ep0 interrupts using
+ *					 ioh_udc_enable_ep_interrupts API.
+ *			- Enable device interrupts (Set configuration command
+ *								 interrupt,
+ *				Set interface command interrupt, ENUM interrupt,
+ *							 USB Reset interrupt)
+ *				using ioh_udc_enable_interrupts API
+ *@param	dev 		Reference to the device structure
+ *@return	none
+ *@see
+ *			- ioh_udc_enable_ep_interrupts
+ *			- ioh_udc_enable_interrupts
+ */
+static void ioh_udc_setup_ep0(struct ioh_udc_dev *dev)
+{
+	/* enable ep0 interrupts */
+	ioh_udc_enable_ep_interrupts(dev->regs, 1 << UDC_EPINT_IN_EP0 |
+						 1 << UDC_EPINT_OUT_EP0);
+
+	/* enable device interrupts */
+	ioh_udc_enable_interrupts(dev->regs, (1 << UDC_DEVINT_UR) |
+			(1 << UDC_DEVINT_US) |	(1 << UDC_DEVINT_ES) |
+			(1 << UDC_DEVINT_ENUM) | (1 << UDC_DEVINT_SI) |
+						 (1 << UDC_DEVINT_SC));
+	IOH_DEBUG("Dev intr mask set to %x",
+				 IOH_READ32((u32 *)&(dev->regs->devirqmsk)));
+	IOH_DEBUG("Ep intr mask set to %x",
+				 IOH_READ32((u32 *)&(dev->regs->epirqmsk)));
+}
+
+/*!@ingroup	UDC_UtilitiesAPI
+ *@fn		ioh_udc_init_setup_buff(struct ioh_udc_stp_dma_desc *td_stp)
+ *@brief	This function initializes the SETUP buffer
+ *@param	td_stp 		Reference to the SETP buffer structure
+ *@return	none
+ */
+static void ioh_udc_init_setup_buff(struct ioh_udc_stp_dma_desc *td_stp)
+{
+	static u32	pky_marker;
+	IOH_DEBUG("ioh_udc_init_setup_buff");
+
+	if (td_stp == NULL) {
+		IOH_DEBUG("SETUP BUFF == NULL");
+		return;
+	}
+	td_stp->reserved = ++pky_marker;
+	td_stp->data12 = 0xFFFFFFFF;
+	td_stp->data34 = 0xFFFFFFFF;
+	td_stp->status = IOH_UDC_BS_HST_RDY;
+}
+
--- /dev/null
+++ b/drivers/usb/gadget/pch_udc.h
@@ -0,0 +1,172 @@
+ /*!
+ * @file ioh_udc.h
+ * @brief
+ * The IOH UDC is a USB High speed DMA capable USB device controller.
+ * It provides 4 IN and 4 OUT endpoints (control, bulk isochronous or
+ *							interrupt type).
+ *
+ * The IOH USB device controller driver provides required interface
+ * to the USB gadget framework for accessing the IOH USB device hardware.
+ *
+ * @version 0.96
+ *
+ * @section
+ * 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; version 2 of the License.
+ *
+ * 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.
+ */
+
+ /*
+ * History:
+ * Copyright (C) 2009 OKI SEMICONDUCTOR Co., LTD.
+ * All rights reserved.
+ *
+ * created:
+ *   OKI SEMICONDUCTOR 2/26/2010
+ * modified:
+ *
+ */
+
+#ifndef _IOH_UDC_H_
+#include <linux/types.h>
+#include <linux/irq.h>
+
+extern const struct usb_gadget_ops ioh_udc_ops;
+extern struct ioh_udc_dev *ioh_udc;
+
+extern irqreturn_t ioh_udc_isr(int irq, void *pdev);
+extern int ioh_udc_pcd_init(struct ioh_udc_dev *dev);
+extern void ioh_udc_dev_isr(struct ioh_udc_dev *dev, u32 dev_intr);
+
+/*!@ingroup		UDC_Global
+ * @struct		ioh_udc_request
+ * @brief		Structure holding a IOH USB device request
+ */
+struct ioh_udc_request /* request packet */
+{
+	struct usb_request		req;	/**< embedded ep request */
+	dma_addr_t			td_data_phys;	/**< phys. address */
+	struct ioh_udc_data_dma_desc	*td_data;/*< first dma desc. of chain */
+	struct ioh_udc_data_dma_desc	*td_data_last;/**< last dma desc.
+								 of chain */
+	struct list_head		queue;	/**< associated queue */
+
+	/* flags */
+	unsigned		dma_going:1,/**< DMA in progress for request */
+				dma_mapped:1,/**< DMA memory mapped
+								 for request */
+				dma_done:1;	/**< DMA completed
+								 for request */
+	unsigned		chain_len;		/**< chain length */
+};
+
+/*!@ingroup		UDC_Global
+ * @struct		ioh_udc_ep
+ * @brief		Structure holding a IOH USB device Endpoint information
+ */
+struct ioh_udc_ep {
+	struct usb_ep			ep;	/**< embedded ep request */
+	dma_addr_t			td_stp_phys;/**< for setup request */
+	dma_addr_t			td_data_phys;/**< for data request */
+	struct ioh_udc_stp_dma_desc	*td_stp; /**< for setup request */
+	struct ioh_udc_data_dma_desc	*td_data;	/**< for data request */
+
+	struct ioh_udc_dev	*dev;	/**< reference to device struct */
+	struct ioh_udc_ep_regs __iomem	*regs;
+	u32 __iomem		*dma;	/**< dma enabled or not */
+	const struct usb_endpoint_descriptor	*desc;	/**< for this ep */
+
+	/* queue for requests */
+	struct list_head	queue;
+
+	unsigned			num:5;	/**< endpoint number */
+	unsigned			in:1;		/**< endpoint is IN */
+	unsigned			halted;		/**< endpoint halted? */
+	unsigned long		epsts;		/**< Endpoint status */
+};
+
+
+/*!@ingroup		UDC_Global
+ * @struct		ioh_udc_dev
+ * @brief		Structure holding complete information of the
+								IOH USB device
+ */
+struct ioh_udc_dev {
+	struct usb_gadget		gadget;	/**< gadget driver data */
+	struct usb_gadget_driver	*driver;/**< reference to gadget
+								 driver bound */
+	struct pci_dev			*pdev;	/**< reference to the
+								 PCI device */
+
+	/* all endpoints */
+	struct ioh_udc_ep		ep[IOH_UDC_EP_NUM];	/**< array of
+								 endpoints */
+	spinlock_t			lock;		/* protects all state */
+	/* operational flags */
+	unsigned	active:1,		/**< enabled the PCI device */
+			stall:1,			/**< stall requested */
+			prot_stall:1,	/**< protcol stall requested */
+			irq_registered:1, /**< irq registered with system */
+			mem_region:1,		/**< device memory mapped */
+			registered:1,	/**< driver regsitered with system */
+			suspended:1,	/**< driver in suspended state */
+			connected:1,	/**< gadget driver associated */
+			set_cfg_not_acked:1,/**< pending acknowledgement
+								 4 setup */
+			waiting_zlp_ack:1;/**< pending acknowledgement 4 ZLP */
+
+	/* registers */
+	struct ioh_udc_csrs __iomem	*csr;	/**< address of config & status
+								 registers */
+	struct ioh_udc_regs __iomem	*regs; /**< address of device
+								 registers */
+	struct ioh_udc_ep_regs __iomem	*ep_regs;	/**< address of endpoint
+								 registers */
+
+	/* DMA desc pools */
+	struct pci_pool			*data_requests;	/**< DMA pool for
+							 data requests */
+	struct pci_pool			*stp_requests;	/**< DMA pool for
+							 setup requests */
+
+	/* device data */
+	unsigned long			phys_addr;	/**< of device memory */
+	void __iomem			*virt_addr;/**< for mapped device
+								 memory */
+	unsigned			irq;	/**< IRQ line for the device */
+
+	struct ioh_udc_cfg_data		cfg_data;/**< current cfg, intf,
+							 and alt in use */
+};
+
+/*!@ingroup		UDC_Global
+ * @struct		ioh_udc_ep
+ * @brief		Structure holding setup request data
+ */
+union ioh_udc_setup_data {
+	u32		data[2];	/**< 8 bytes of setup data  */
+	struct usb_ctrlrequest	request; /**< setup request for gadget driver */
+};
+
+/*!@ingroup		UDC_UtilitiesAPI
+ * @fn			ioh_udc_activate_control_ep(struct ioh_udc_dev *dev)
+ * @brief		Performs necessary operations to enable endpoint 0
+ */
+extern void ioh_udc_activate_control_ep(struct ioh_udc_dev *dev);
+
+/*!@ingroup		UDC_UtilitiesAPI
+ * @fn			empty_req_queue(struct ioh_udc_ep *ep)
+ * @brief		Removes all requests queued on the endpoint
+ */
+extern void empty_req_queue(struct ioh_udc_ep *ep);
+
+#endif	/* _IOH_UDC_H_ */
--- /dev/null
+++ b/drivers/usb/gadget/pch_udc_hal.c
@@ -0,0 +1,1110 @@
+ /*!
+ * @file ioh_udc_hal.c
+ * @brief
+ * The IOH UDC is a USB High speed DMA capable USB device controller.
+ * It provides 4 IN and 4 OUT endpoints (control, bulk isochronous or
+ *								interrupt type).
+ *
+ * The IOH USB device controller driver provides required interface
+ * to the USB gadget framework for accessing the IOH USB device hardware.
+ *
+ * @version 0.96
+ *
+ * @section
+ * 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; version 2 of the License.
+ *
+ * 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.
+ */
+
+ /*
+ * History:
+ * Copyright (C) 2009 OKI SEMICONDUCTOR Co., LTD.
+ * All rights reserved.
+ *
+ * created:
+ *   OKI SEMICONDUCTOR 2/26/2010
+ * modified:
+ *
+ */
+
+#include <linux/types.h>
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+/*#include <asm/io.h>*/
+#include <linux/io.h>
+#include "pch_common.h"
+#include "pch_debug.h"
+
+#include <linux/usb/ch9.h>
+#include "pch_udc_hal.h"
+
+#define INLINE	inline
+static u32 ioh_udc_base;
+
+#define MAX_LOOP	200
+
+/*!@ingroup	UDC_HALLayerAPI
+ * @fn 		inline void ioh_udc_write_csr(unsigned long val, unsigned long
+ *									 addr)
+ * @remarks	The following actions are performed:
+ * 			- Wait for any ongoing access to config registers to
+ *					 complete, by polling the CSR busy flag.
+ * 			- Write the value to the CSR register.
+ * 			- Wait till the write gets completed by polling the
+ *								 CSR busy flag.
+ * @param	val		[IN]	value to be written to CSR register
+ * @param	addr	[IN]	address of CSR register
+ * @retval	none
+ */
+INLINE void ioh_udc_write_csr(unsigned long val, unsigned long addr)
+{
+	int count = MAX_LOOP;
+
+	/* Wait till idle */
+	while ((count > 0) &&\
+	(IOH_READ32((unsigned long *)(IOH_UDC_CSR_BUSY_ADDR + ioh_udc_base)) &
+	IOH_UDC_CSR_BUSY))
+		count--;
+
+	if (count < 0)
+		IOH_DEBUG("ioh_udc_write_csr: wait error; count = %x", count);
+
+	iowrite32(val, (unsigned long *)addr);
+	/* Wait till idle */
+	count = MAX_LOOP;
+	while ((count > 0) &&
+	(IOH_READ32((unsigned long *)(IOH_UDC_CSR_BUSY_ADDR + ioh_udc_base)) &
+	IOH_UDC_CSR_BUSY))
+		count--;
+
+	if (count < 0)
+		IOH_DEBUG("ioh_udc_write_csr: wait error; count = %x", count);
+
+}
+
+/*!@ingroup	UDC_HALLayerAPI
+ * @fn		ioh_udc_read_csr(unsigned long addr)
+ * @remarks	The main tasks performed by this method are:
+ * 			- This function waits for any access to internal
+ * 						 USB_DEVICE registers to
+ * 				complete and then reads the config register
+ * @param	addr	[IN]	address of CSR register
+ * @retval	u32 - content of CSR register
+ */
+INLINE u32 ioh_udc_read_csr(unsigned long addr)
+{
+	int count = MAX_LOOP;
+
+	/* Wait till idle */
+	while ((count > 0) &&
+	 (IOH_READ32((unsigned long *)(IOH_UDC_CSR_BUSY_ADDR + ioh_udc_base)) &
+	 IOH_UDC_CSR_BUSY))
+		count--;
+
+	if (count < 0)
+		IOH_DEBUG("ioh_udc_read_csr: wait error; count = %x", count);
+	/* Dummy read */
+	IOH_READ32((unsigned long *)addr);
+	count = MAX_LOOP;
+	/* Wait till idle */
+	while ((count > 0) &&
+	 (IOH_READ32((unsigned long *)(IOH_UDC_CSR_BUSY_ADDR + ioh_udc_base)) &
+	 IOH_UDC_CSR_BUSY))
+		count--;
+	/* actual read */
+	if (count < 0)
+		IOH_DEBUG("ioh_udc_read_csr: wait error; count = %x", count);
+
+	return IOH_READ32((unsigned long *)addr);
+}
+
+/* Prints UDC device registers and endpoint irq registers */
+/*!@ingroup	UDC_HALLayerAPI
+ * @fn		ioh_udc_print_regs(u32 base)
+ * @remarks	The main tasks performed by this method are:
+ *	- Read UDC device registers and endpoint registers and print them
+ * @param	base	[IN]	the remapped base address
+ */
+void ioh_udc_print_regs(u32 base)
+{
+	struct ioh_udc_data_dma_desc	*data_desc;
+	struct ioh_udc_stp_dma_desc	*stp_desc;
+	u32	*regs = (u32 *) (base + UDC_DEVCFG_ADDR);
+	u32 ddp, stp;
+	int i;
+
+	IOH_DEBUG("print_regs: base %x", base);
+	IOH_DEBUG("------- Device registers ---------");
+	IOH_DEBUG("dev config     = %08x",
+			IOH_READ32((u32)&((struct ioh_udc_regs *)
+								regs)->devcfg));
+	IOH_DEBUG("dev control    = %08x",
+			IOH_READ32((u32)&((struct ioh_udc_regs *)
+								regs)->devctl));
+	IOH_DEBUG("dev status     = %08x",
+			IOH_READ32((u32)&((struct ioh_udc_regs *)
+								regs)->devsts));
+	IOH_DEBUG("dev int's      = %08x",
+			IOH_READ32((u32)&((struct ioh_udc_regs *)
+							regs)->devirqsts));
+	IOH_DEBUG("dev intmask    = %08x",
+			IOH_READ32((u32)&((struct ioh_udc_regs *)
+							 regs)->devirqmsk));
+	IOH_DEBUG("dev ep int's   = %08x",
+			IOH_READ32((u32)&((struct ioh_udc_regs *)
+							regs)->epirqsts));
+	IOH_DEBUG("dev ep intmask = %08x",
+			IOH_READ32((u32)&((struct ioh_udc_regs *)
+							 regs)->epirqmsk));
+
+	regs = (u32 *) (base + UDC_EPIN_REGS_ADDR);
+	IOH_DEBUG("------- Endpoint registers -------");
+	for (i = 0; i < IOH_UDC_USED_EP_NUM; i++) {
+		IOH_DEBUG("Endpoint IN %1d ----------", i);
+		IOH_DEBUG("Ep control    = %08x",
+			IOH_READ32((u32)&((struct ioh_udc_ep_regs *)
+								 regs)->epctl));
+		IOH_DEBUG("Ep status     = %08x",
+			IOH_READ32((u32)&((struct ioh_udc_ep_regs *)
+								 regs)->epsts));
+		IOH_DEBUG("Buffer size   = %08x",
+			IOH_READ32((u32)&((struct ioh_udc_ep_regs *)
+						 regs)->bufin_framenum));
+		IOH_DEBUG("Max packet    = %08x",
+			IOH_READ32((u32)&((struct ioh_udc_ep_regs *)
+							 regs)->bufout_maxpkt));
+		ddp = IOH_READ32((u32)&((struct ioh_udc_ep_regs *)
+							 regs)->desptr);
+		IOH_DEBUG("Data Desc Ptr = %08x", ddp);
+
+		if ((ddp != 0) && (ddp != 0xFFFFFFFF)) {
+			data_desc = phys_to_virt(ddp);
+			IOH_DEBUG("  |- status   = %08x", data_desc->status);
+			IOH_DEBUG("  |- reserved = %08x", data_desc->reserved);
+			IOH_DEBUG("  |- dataptr  = %08x", data_desc->dataptr);
+			IOH_DEBUG("  +- next     = %08x", data_desc->next);
+		}
+		regs += UDC_EP_REG_OFS / sizeof regs;
+	}
+	regs = (u32 *) (base + UDC_EPOUT_REGS_ADDR);
+	for (i = 0; i < IOH_UDC_USED_EP_NUM; i++) {
+		IOH_DEBUG("Endpoint OUT %1d ---------", i);
+		IOH_DEBUG("Ep control    = %08x",
+			IOH_READ32((u32)&((struct ioh_udc_ep_regs *)
+								 regs)->epctl));
+		IOH_DEBUG("Ep status     = %08x",
+			IOH_READ32((u32)&((struct ioh_udc_ep_regs *)
+								 regs)->epsts));
+		IOH_DEBUG("Frame Number  = %08x",
+			IOH_READ32((u32)&((struct ioh_udc_ep_regs *)
+						 regs)->bufin_framenum));
+		IOH_DEBUG("Buf / Max pkt = %08x",
+			IOH_READ32((u32)&((struct ioh_udc_ep_regs *)
+							 regs)->bufout_maxpkt));
+		stp = IOH_READ32((u32)&((struct ioh_udc_ep_regs *)
+								 regs)->subptr);
+		IOH_DEBUG("Setup buf ptr = %08x", stp);
+
+		if ((stp != 0) && (stp != 0xFFFFFFFF)) {
+			stp_desc = phys_to_virt(stp);
+			IOH_DEBUG("  |- status   = %08x", stp_desc->status);
+			IOH_DEBUG("  |- reserved = %08x", stp_desc->reserved);
+			IOH_DEBUG("  |- data12   = %08x", stp_desc->data12);
+			IOH_DEBUG("  +- data34   = %08x", stp_desc->data34);
+		}
+
+		ddp = IOH_READ32((u32)&((struct ioh_udc_ep_regs *)
+							 regs)->desptr);
+		IOH_DEBUG("Data Desc Ptr = %08x", ddp);
+		if ((ddp != 0) && (ddp != 0xFFFFFFFF)) {
+			data_desc = phys_to_virt(ddp);
+			IOH_DEBUG("  |- status   = %08x", data_desc->status);
+			IOH_DEBUG("  |- reserved = %08x", data_desc->reserved);
+			IOH_DEBUG("  |- dataptr  = %08x", data_desc->dataptr);
+			IOH_DEBUG("  +- next     = %08x", data_desc->next);
+		}
+		regs += UDC_EP_REG_OFS / sizeof regs;
+	}
+	regs = (u32 *) (base + UDC_CSR_ADDR);
+	IOH_DEBUG("------- Endpoint Configuration ---");
+	for (i = 0; i < IOH_UDC_USED_EP_NUM * 2; i++) {
+		IOH_DEBUG("EP config%d    = %08x", i,
+			ioh_udc_read_csr((u32)&((struct ioh_udc_csrs *)
+								 regs)->ne[i]));
+	}
+}
+
+/*!@ingroup	UDC_HALLayerAPI
+ * @fn		ioh_udc_init(struct ioh_udc_regs *dev)
+ * @remarks	The main tasks performed by this method are:
+ *	- If argument passed is NULL, return.
+ *	- Set the base address for USB device registers
+ *	- Invoke soft reset and PHY reset
+ *	- Disable and clear the Device and endpoint interrupts
+ *	- Enable dynamic CSR programming, set self powered and configure device
+ *		speed in the Device Config register
+ *	- Enable TX DMA, BURST and THRESHOLD modes
+ *		and set BURST and THRESHOLD length.
+ *	- Put the device in soft disconnect mode
+ * @param	dev		[IN]	reference to ioh_udc_regs structure
+ * @retval	none
+ */
+void ioh_udc_init(struct ioh_udc_regs *dev)
+{
+	u32 reset_reg;
+
+	IOH_DEBUG("ioh_udc_init: enter");
+	if (NULL == dev) {
+		IOH_LOG(KERN_ERR, "ioh_udc_init: Invalid address");
+		return;
+	}
+	/* Set the UDC_Global variable */
+	ioh_udc_base = (u32) dev - UDC_DEVCFG_ADDR;
+	/* Soft Reset and Reset PHY */
+	reset_reg = (ioh_udc_base + IOH_UDC_SRST_ADDR);
+	IOH_WRITE32((1 << IOH_UDC_SRST), (u32 *)(reset_reg));
+	IOH_WRITE32((1 << IOH_UDC_SRST) | (1 << IOH_UDC_PSRST),
+							 (u32 *)(reset_reg));
+	mdelay(1);
+	IOH_WRITE32((1 << IOH_UDC_SRST), (u32 *)(reset_reg));
+	IOH_WRITE32(0x00, (u32 *)(reset_reg));
+	mdelay(1);
+
+	/* mask and clear all device interrupts */
+	IOH_SET_ADDR_BIT((u32)&dev->devirqmsk, UDC_DEVINT_MSK);
+	IOH_SET_ADDR_BIT((u32)&dev->devirqsts, UDC_DEVINT_MSK);
+
+	/* mask and clear all ep interrupts */
+	IOH_SET_ADDR_BIT((u32)&dev->epirqmsk, UDC_EPINT_MSK_DISABLE_ALL);
+	IOH_SET_ADDR_BIT((u32)&dev->epirqsts, UDC_EPINT_MSK_DISABLE_ALL);
+
+	/* enable dynamic CSR programmingi, self powered and device speed */
+	if (speed_fs) {
+		IOH_SET_ADDR_BIT((u32)&dev->devcfg, (1 << UDC_DEVCFG_CSR_PRG) |
+			(1 << UDC_DEVCFG_SP) | /* set self powered */
+			UDC_DEVCFG_SPD_FS); /* program speed - full speed */
+	} else { /* defaul high speed */
+		IOH_SET_ADDR_BIT((u32)&dev->devcfg, (1 << UDC_DEVCFG_CSR_PRG) |
+			(1 << UDC_DEVCFG_SP) | /* set self powered */
+			UDC_DEVCFG_SPD_HS); /* program speed - high speed */
+	}
+#ifdef DMA_PPB_WITH_DESC_UPDATE
+	IOH_SET_ADDR_BIT((u32)&dev->devctl,
+			 (IOH_UDC_THLEN << UDC_DEVCTL_THLEN_OFS) |
+			(IOH_UDC_BRLEN << UDC_DEVCTL_BRLEN_OFS) |
+			(1 << UDC_DEVCTL_MODE) | (1 << UDC_DEVCTL_BREN) |
+			(1 << UDC_DEVCTL_DU) |
+			(1 << UDC_DEVCTL_THE));
+#else
+	IOH_SET_ADDR_BIT((u32)&dev->devctl,
+			 (IOH_UDC_THLEN << UDC_DEVCTL_THLEN_OFS) |
+			(IOH_UDC_BRLEN << UDC_DEVCTL_BRLEN_OFS) |
+			(1 << UDC_DEVCTL_MODE) | (1 << UDC_DEVCTL_BREN) |
+			(1 << UDC_DEVCTL_THE));
+#endif
+	IOH_DEBUG("ioh_udc_init: exit");
+}
+
+/*!@ingroup	UDC_HALLayerAPI
+ * @fn		ioh_udc_exit(struct ioh_udc_regs *dev)
+ * @remarks	The main tasks performed by this method are:
+ *			- Put the device in soft disconnect mode
+ *			- Clear the device and endpoint interrupts
+ *  		  and disable them
+ * @param	dev		[IN]	Reference to ioh_udc_regs structure
+ * @retval	none
+ */
+void ioh_udc_exit(struct ioh_udc_regs *dev)
+{
+	IOH_DEBUG("ioh_udc_exit: enter");
+	/* mask all device interrupts */
+	IOH_SET_ADDR_BIT((u32)&dev->devirqmsk, UDC_DEVINT_MSK);
+
+	/* mask all ep interrupts */
+	IOH_SET_ADDR_BIT((u32)&dev->epirqmsk, UDC_EPINT_MSK_DISABLE_ALL);
+
+	/* put device in disconnected state */
+	ioh_udc_set_disconnect(dev);
+	IOH_DEBUG("ioh_udc_exit: exit");
+}
+
+/* Initiates a remote wakeup */
+/*!@ingroup	UDC_HALLayerAPI
+ * @fn		ioh_udc_rmt_wakeup(struct ioh_udc_regs *dev)
+ * @remarks	The main tasks performed by this method are:
+ * 			- Set the RES (bit 1) of the device control register
+ * 			- Wait for 1 msec
+ * 			- Clear the RES bit
+ * @param	dev     [IN]    Reference to ioh_udc_regs structure
+ * @retval	none
+ */
+void ioh_udc_rmt_wakeup(struct ioh_udc_regs *dev)
+{
+	IOH_DEBUG("ioh_udc_rmt_wakeup: enter");
+	IOH_SET_ADDR_BIT((u32)&dev->devctl, 1 << UDC_DEVCTL_RES);
+	mdelay(1);
+	IOH_CLR_ADDR_BIT((u32)&dev->devctl, 1 << UDC_DEVCTL_RES);
+	IOH_DEBUG("ioh_udc_rmt_wakeup: exit");
+}
+
+/*!@ingroup	UDC_HALLayerAPI
+ * @fn		ioh_udc_get_frame(struct ioh_udc_regs *dev)
+ * @remarks	The main tasks performed by this method are:
+ *			- Retrieve the current frame from device status register
+ * @param	dev		[IN]    Reference to ioh_udc_regs structure
+ * @retval	int
+ *			- current frame
+ */
+int ioh_udc_get_frame(struct ioh_udc_regs *dev)
+{
+	u32 frame;
+
+	IOH_DEBUG("ioh_udc_get_frame: enter");
+	frame = IOH_READ32((u32)&dev->devsts);
+	IOH_DEBUG("ioh_udc_get_frame: exit");
+	return (frame & UDC_DEVSTS_TS_MASK) >> UDC_DEVSTS_TS_OFS;
+}
+
+/*!@ingroup	UDC_HALLayerAPI
+ * @fn		ioh_udc_clear_selfpowered (struct ioh_udc_regs __iomem *dev)
+ * @remarks	The main tasks performed by this method are:
+ *		- Clear the 'SP' bit (bit 3) of the device config register
+ * @param	dev     [IN]    Reference to ioh_udc_regs structure
+ * @retval	none
+ */
+void ioh_udc_clear_selfpowered(struct ioh_udc_regs __iomem *dev)
+{
+	IOH_CLR_ADDR_BIT((u32)&dev->devcfg, 1 << UDC_DEVCFG_SP);
+}
+
+/*!@ingroup	UDC_HALLayerAPI
+ * @fn		ioh_udc_set_selfpowered (struct ioh_udc_regs __iomem *dev)
+ * @remarks	The main tasks performed by this method are:
+ *			- Set the 'SP' bit (bit 3) of the device config register
+ * @param	dev     [IN]    Reference to ioh_udc_regs structure
+ * @retval	none
+ */
+void ioh_udc_set_selfpowered(struct ioh_udc_regs __iomem *dev)
+{
+	IOH_SET_ADDR_BIT((u32)&dev->devcfg, 1 << UDC_DEVCFG_SP);
+}
+
+/*!@ingroup	UDC_HALLayerAPI
+ * @fn		ioh_udc_set_disconnect (struct ioh_udc_regs __iomem *dev)
+ * @remarks	The main tasks performed by this method are:
+ *			- Set the SD bit (bit 10) of device control register
+ * @param	dev     [IN]    Reference to ioh_udc_regs structure
+ * @retval	none
+ */
+void ioh_udc_set_disconnect(struct ioh_udc_regs __iomem *dev)
+{
+	IOH_SET_ADDR_BIT((u32)&dev->devctl, 1 << UDC_DEVCTL_SD);
+}
+
+/*!@ingroup	UDC_HALLayerAPI
+ * @fn		ioh_udc_get_speed (struct ioh_udc_regs __iomem *dev)
+ * @remarks	The main tasks performed by this method are:
+ *	- Return the speed from Device status register ENUMSPD (bit 13, 14)
+ * @param	dev     [IN]    Reference to ioh_udc_regs structure
+ * @retval	int
+ * 			- The speed(LOW=1, FULL=2, HIGH=3)
+ */
+int ioh_udc_get_speed(struct ioh_udc_regs __iomem *dev)
+{
+	u32 val;
+
+	val = IOH_READ32((u32)&dev->devsts);
+	return (val & UDC_DEVSTS_ENUM_SPEED_MASK) >> UDC_DEVSTS_ENUM_SPEED_OFS;
+}
+
+/*!@ingroup	UDC_HALLayerAPI
+ * @fn		ioh_udc_clear_disconnect (struct ioh_udc_regs __iomem *dev)
+ * @remarks	The main tasks performed by this method are
+ *			- Clear the SD bit (bit 10) and set the RES bit (bit 1)
+ *  		  of the device control register
+ *			- After 1msec, clear the RES bit (bit 1) of the device
+ *  		  control register
+ * @param	dev     [IN]    Reference to ioh_udc_regs structure
+ * @retval	none
+ */
+void ioh_udc_clear_disconnect(struct ioh_udc_regs __iomem *dev)
+{
+	/* Clear the disconnect */
+	IOH_SET_ADDR_BIT((u32)&dev->devctl, 1 << UDC_DEVCTL_RES);
+	IOH_CLR_ADDR_BIT((u32)&dev->devctl, 1 << UDC_DEVCTL_SD);
+	mdelay(1);
+	/* Resume USB signalling */
+	IOH_CLR_ADDR_BIT((u32)&dev->devctl, 1 << UDC_DEVCTL_RES);
+}
+
+/*!@ingroup	UDC_HALLayerAPI
+ * @fn	ioh_udc_vbus_session (struct ioh_udc_regs __iomem *dev, int is_active)
+ * @remarks	The main tasks performed by this method are:
+ *			- If 'is_active' invoke ioh_udc_clear_disconnect to make
+ *			  this device available to host
+ *			- Otherwise invoke ioh_udc_set_disconnect to make the
+ *			  device unavailable
+ * @param	dev     	[IN]    Reference to ioh_udc_regs structure
+ * @param	is_active	[IN]	Parameter specifying the action
+ *			- is_active = 0   indicating VBUS power is ending
+ *			- is_active != 0  indicating VBUS power is starting
+ * @retval	none
+ */
+void ioh_udc_vbus_session(struct ioh_udc_regs __iomem *dev, int is_active)
+{
+	if (is_active == 0)
+		ioh_udc_set_disconnect(dev);
+	else
+		ioh_udc_clear_disconnect(dev);
+
+}
+
+/* Stall or clear stall of endpoint */
+/*!@ingroup	UDC_HALLayerAPI
+ * @fn		ioh_udc_ep_set_stall(struct ioh_udc_ep_regs __iomem *ep)
+ * @remarks	The main tasks performed by this method are:
+ *			- If this is a IN endpoint, flush the TX FIFO ( F bit)
+ *				of the endpoint control register
+ *			- Set the bit 0 (S bit) of the endpoint control register
+ * @param	ep		[IN]	reference to structure of type
+ *							 ioh_udc_ep_regs
+ * @retval	none
+ */
+void ioh_udc_ep_set_stall(struct ioh_udc_ep_regs __iomem *ep)
+{
+	if (EP_IS_IN(ep)) {	/* flush fifo */
+		IOH_SET_ADDR_BIT((u32)&ep->epctl, 1 << UDC_EPCTL_F);
+		IOH_SET_ADDR_BIT((u32)&ep->epctl, 1 << UDC_EPCTL_S);
+	} else {
+		IOH_SET_ADDR_BIT((u32)&ep->epctl, 1 << UDC_EPCTL_S);
+	}
+}
+
+/* Halt or clear halt of endpoint */
+/*!@ingroup	UDC_HALLayerAPI
+ * @fn		ioh_udc_ep_clear_stall(struct ioh_udc_ep_regs __iomem *ep)
+ * @remarks	The main tasks performed by this method are:
+ *		- Clear the bit 0 (S bit) of the endpoint control register
+ *		- Set the bit 8 (CNAK bit) of the endpoint control register
+ * @param	ep      [IN]    reference to structure of type ioh_udc_ep_regs
+ * @retval	none
+ */
+void ioh_udc_ep_clear_stall(struct ioh_udc_ep_regs __iomem *ep)
+{
+	/* Clear the stall */
+	IOH_CLR_ADDR_BIT((u32)&ep->epctl, 1 << UDC_EPCTL_S);
+
+	/* clear NAK by writing CNAK */
+	IOH_SET_ADDR_BIT((u32)&ep->epctl, 1 << UDC_EPCTL_CNAK);
+}
+
+
+/* Set the transfer type of endpoint */
+/*!@ingroup	UDC_HALLayerAPI
+ * @fn	ioh_udc_ep_set_trfr_type(struct ioh_udc_ep_regs __iomem *ep, u8 type)
+ * @remarks	The main tasks performed by this method are:
+ *			- Set the transfer type of endpoint
+ * @param	ep	[IN]	reference to structure of type ioh_udc_ep_regs
+ * @param	type	[IN]	type of endpoint
+ * @retval	none
+ */
+void ioh_udc_ep_set_trfr_type(struct ioh_udc_ep_regs __iomem *ep, u8 type)
+{
+	IOH_WRITE32(((type << UDC_EPCTL_ET_OFS) & UDC_EPCTL_ET_MASK) ,
+							 (u32)&ep->epctl);
+}
+
+/*!@ingroup	UDC_HALLayerAPI
+ * @fn		ioh_udc_ep_set_bufsz(struct ioh_udc_ep_regs __iomem *ep,
+ *								 u32 buf_size)
+ * @remarks	The main task performed by this method is:
+ *			- Set the maximum packet size for the endpoint
+ * @param	ep      	[IN]    reference to structure of
+ *							 type ioh_udc_ep_regs
+ * @param	buf_size	[IN]	the buffer size
+ * @retval	none
+ */
+void ioh_udc_ep_set_bufsz(struct ioh_udc_ep_regs __iomem *ep,
+						 u32 buf_size, u32 ep_in)
+{
+	u32 data;
+	if (ep_in) {
+		data = IOH_READ32((u32)&ep->bufin_framenum);
+		data = (data & 0xffff0000) | (buf_size & 0xffff);
+		IOH_WRITE32(data, (u32)&ep->bufin_framenum);
+	} else {
+		data = IOH_READ32((u32)&ep->bufout_maxpkt);
+		data = (buf_size << 16) | (data & 0xffff);
+		IOH_WRITE32(data, (u32)&ep->bufout_maxpkt);
+	}
+}
+
+/*!@ingroup	UDC_HALLayerAPI
+ * @fn		ioh_udc_ep_set_maxpkt(struct ioh_udc_ep_regs __iomem *ep,
+ *								 u32 pkt_size)
+ * @remarks	Set the Max packet size for the endpoint
+ * @param	ep          [IN] reference to structure of type ioh_udc_ep_regs
+ * @param	pkt_size    [IN] the packet size
+ * @retval	none
+ */
+/* Set the Max packet size for the endpoint */
+void ioh_udc_ep_set_maxpkt(struct ioh_udc_ep_regs __iomem *ep, u32 pkt_size)
+{
+	u32 data;
+	data = IOH_READ32((u32)&ep->bufout_maxpkt);
+	data = (data & 0xffff0000) | (pkt_size & 0xffff);
+	IOH_WRITE32(data, (u32)&ep->bufout_maxpkt);
+}
+
+/* Set the Setup buffer pointer for the endpoint */
+/*!@ingroup	UDC_HALLayerAPI
+ * @fn	ioh_udc_ep_set_subptr(struct ioh_udc_ep_regs __iomem *ep, u32 addr)
+ * @remarks	Set the Setup buffer pointer for the endpoint
+ * @param	ep	[IN]	reference to structure of type ioh_udc_ep_regs
+ * @param	addr	[IN]	address of the register
+ * @retval	none
+ */
+INLINE void ioh_udc_ep_set_subptr(struct ioh_udc_ep_regs __iomem *ep, u32 addr)
+{
+	IOH_WRITE32(addr, (u32)&ep->subptr);
+}
+
+/* Set the Data descriptor pointer for the endpoint */
+/*!@ingroup	UDC_HALLayerAPI
+ * @fn	ioh_udc_ep_set_ddptr(struct ioh_udc_ep_regs __iomem *ep, u32 addr)
+ * @remarks	Set the Data descriptor pointer for the endpoint
+ * @param	ep	[IN]    reference to structure of type ioh_udc_ep_regs
+ * @param	addr	[IN]    address of the register
+ * @retval  none
+ */
+INLINE void ioh_udc_ep_set_ddptr(struct ioh_udc_ep_regs __iomem *ep, u32 addr)
+{
+	IOH_WRITE32(addr, (u32)&ep->desptr);
+}
+
+/* Set the poll demand bit for the endpoint */
+/*!@ingroup	UDC_HALLayerAPI
+ * @fn		ioh_udc_ep_set_pd(struct ioh_udc_ep_regs __iomem *ep)
+ * @remarks	Set the poll demand bit for the endpoint
+ * @param	ep	[IN]    reference to structure of type ioh_udc_ep_regs
+ * @retval	none
+ */
+INLINE void ioh_udc_ep_set_pd(struct ioh_udc_ep_regs __iomem *ep)
+{
+	IOH_SET_ADDR_BIT((u32)&ep->epctl, 1 << UDC_EPCTL_P);
+}
+
+/* Set the receive ready bit for the endpoint */
+/*!@ingroup	UDC_HALLayerAPI
+ * @fn		ioh_udc_ep_set_rrdy(struct ioh_udc_ep_regs __iomem *ep)
+ * @remarks	Set the receive ready bit for the endpoint
+ * @param	ep	[IN]    reference to structure of type ioh_udc_ep_regs
+ * @retval	none
+ */
+INLINE void ioh_udc_ep_set_rrdy(struct ioh_udc_ep_regs __iomem *ep)
+{
+	IOH_DEBUG("ioh_udc_ep_set_rrdy: ep%d%s", EP_NUM(ep),
+					 (EP_IS_IN(ep) ? "in" : "out"));
+	IOH_SET_ADDR_BIT((u32)&ep->epctl, 1 << UDC_EPCTL_RRDY);
+}
+
+/* Clear the receive ready bit for the endpoint */
+/*!@ingroup	UDC_HALLayerAPI
+ * @fn		ioh_udc_ep_clear_rrdy(struct ioh_udc_ep_regs __iomem *ep)
+ * @remarks	Clear the receive ready bit for the endpoint
+ * @param	ep	[IN]    reference to structure of type ioh_udc_ep_regs
+ * @retval	none
+ */
+INLINE void ioh_udc_ep_clear_rrdy(struct ioh_udc_ep_regs __iomem *ep)
+{
+	IOH_CLR_ADDR_BIT((u32)&ep->epctl, 1 << UDC_EPCTL_RRDY);
+}
+
+/* Enabling RX/TX DMA */
+/*!@ingroup	UDC_HALLayerAPI
+ * @fn		ioh_udc_set_dma(struct ioh_udc_regs __iomem *dev, int dir)
+ * @remarks	Set the 'TDE' or RDE bit of device control register depending
+ *						 on the direction specified
+ * @param	dev	[IN]	reference to structure of type ioh_udc_regs
+ * @param	dir	[IN]	whether Tx or Rx
+ *			- dir = DMA_DIR_RX Receive
+ *			- dir = DMA_DIR_TX Transmit
+ * @retval	none
+ */
+INLINE void ioh_udc_set_dma(struct ioh_udc_regs __iomem *dev, int dir)
+{
+	if (dir == DMA_DIR_RX)
+		IOH_SET_ADDR_BIT((u32)&dev->devctl, 1 << UDC_DEVCTL_RDE);
+	else if (dir == DMA_DIR_TX)
+		IOH_SET_ADDR_BIT((u32)&dev->devctl, (1 << UDC_DEVCTL_TDE));
+
+}
+
+/* Disable RX/TX DMA */
+/*!@ingroup	UDC_HALLayerAPI
+ * @fn		ioh_udc_clear_dma(struct ioh_udc_regs __iomem *dev, int dir)
+ * @remarks	Clear the 'TDE' or RDE bit of device control
+ *				 register depending on the direction specified
+ * @param	dev	[IN]	reference to structure of type ioh_udc_regs
+ * @param	dir	[IN]	whether Tx or Rx
+ *			- dir = DMA_DIR_RX Receive
+ *			- dir = DMA_DIR_TX Transmit
+ * @retval	none
+ */
+void ioh_udc_clear_dma(struct ioh_udc_regs __iomem *dev, int dir)
+{
+	if (dir == DMA_DIR_RX)
+		IOH_CLR_ADDR_BIT((u32)&dev->devctl, 1 << UDC_DEVCTL_RDE); /*
+								clear RDE */
+	else if (dir == DMA_DIR_TX)
+		IOH_CLR_ADDR_BIT((u32)&dev->devctl, 1 << UDC_DEVCTL_TDE);
+
+}
+
+/* Set CSR done */
+/*!@ingroup	UDC_HALLayerAPI
+ * @fn		ioh_udc_set_csr_done(struct ioh_udc_regs __iomem *dev)
+ * @remarks	Set the device control register CSR done field (bit 13)
+ * @param	dev     [IN]    reference to structure of type ioh_udc_regs
+ * @retval	none
+ */
+void ioh_udc_set_csr_done(struct ioh_udc_regs __iomem *dev)
+{
+	/* set CSR Done */
+	IOH_SET_ADDR_BIT((u32)&dev->devctl, 1 << UDC_DEVCTL_CSR_DONE);
+}
+
+/* Set Burst length */
+/*!@ingroup	UDC_HALLayerAPI
+ * @fn	ioh_udc_set_burst_length(struct ioh_udc_regs __iomem *dev, u8 len)
+ * @remarks	The main tasks done by this method are:
+ *			- Set the device control register burst length field
+ *			- Enable the bust mode
+ * @param	dev     [IN]	reference to structure of type ioh_udc_regs
+ * @param	len     [IN]	burst length
+ * @retval	none
+ */
+void ioh_udc_set_burst_length(struct ioh_udc_regs __iomem *dev, u8 len)
+{
+	IOH_CLR_ADDR_BIT((u32)&dev->devctl, (0xff << UDC_DEVCTL_BRLEN_OFS));
+	/* set Burst length  and enable burst mode*/
+	IOH_SET_ADDR_BIT((u32)&dev->devctl, (len << UDC_DEVCTL_BRLEN_OFS) |
+		(1 << UDC_DEVCTL_BREN));
+}
+
+/* Set Threshold length */
+/*!@ingroup	UDC_HALLayerAPI
+ * @fn	ioh_udc_set_threshold_length(struct ioh_udc_regs __iomem *dev, u8 len)
+ * @remarks	- Set the device control register threshold
+ *			  length field
+ *			- Enable the threshold mode
+ * @param	dev     [IN]    reference to structure of type ioh_udc_regs
+ * @param	len     [IN]    burst length
+ * @retval	none
+ */
+void ioh_udc_set_threshold_length(struct ioh_udc_regs __iomem *dev, u8 len)
+{
+	IOH_CLR_ADDR_BIT((u32)&dev->devctl, (0xff << UDC_DEVCTL_THLEN_OFS));
+	/* set Burst Threshold length and enable threshold mode*/
+	IOH_SET_ADDR_BIT((u32)&dev->devctl, (len << UDC_DEVCTL_THLEN_OFS) |
+		(1 << UDC_DEVCTL_THE));
+}
+
+/* Disable device interrupts */
+/*!@ingroup	UDC_HALLayerAPI
+ * @fn	ioh_udc_disable_interrupts(struct ioh_udc_regs __iomem *dev, u32 mask)
+ * @remarks	Disables the specified interrupts
+ * @param	dev     [IN]    reference to structure of type ioh_udc_regs
+ * @param	mask	[IN]	mask to disable interrupts
+ * @retval	none
+ */
+void ioh_udc_disable_interrupts(struct ioh_udc_regs __iomem *dev, u32 mask)
+{
+	/* set the mask */
+	IOH_SET_ADDR_BIT((u32)&dev->devirqmsk, mask);
+	IOH_DEBUG("Interrupt mask reg     = %08x",
+					 IOH_READ32((u32)&dev->devirqmsk));
+}
+
+/* Enable device interrupts */
+/*!@ingroup	UDC_HALLayerAPI
+ * @fn		ioh_udc_enable_interrupts(struct ioh_udc_regs __iomem *dev,
+ *								 u32 mask)
+ * @remarks	Enable the specified interrupts
+ * @param	dev     [IN]    reference to structure of type ioh_udc_regs
+ * @param	mask    [IN]    mask to enable interrupts
+ * @retval	none
+ */
+void ioh_udc_enable_interrupts(struct ioh_udc_regs __iomem *dev, u32 mask)
+{
+	/* set the mask */
+	IOH_CLR_ADDR_BIT((u32)&dev->devirqmsk, mask);
+	IOH_DEBUG("Interrupt mask reg     = %08x",
+					 IOH_READ32((u32)&dev->devirqmsk));
+}
+
+/* Disable Ep interrupts */
+/*!@ingroup	UDC_HALLayerAPI
+ * @fn		ioh_udc_disable_ep_interrupts(struct ioh_udc_regs __iomem *dev,
+ *								 u32 mask)
+ * @remarks	Disable endpoint interrupts
+ * @param	dev     [IN]    reference to structure of type ioh_udc_regs
+ * @param	mask    [IN]    mask to disable interrupts
+ * @retval	none
+ */
+void ioh_udc_disable_ep_interrupts(struct ioh_udc_regs __iomem *dev, u32 mask)
+{
+	/* set the mask */
+	IOH_SET_ADDR_BIT((u32)&dev->epirqmsk, mask);
+	IOH_DEBUG("Interrupt ep mask reg     = %08x",
+					 IOH_READ32((u32)&dev->epirqmsk));
+}
+
+/* Enable Ep interrupts */
+/*!@ingroup	UDC_HALLayerAPI
+ * @fn		ioh_udc_enable_ep_interrupts(struct ioh_udc_regs __iomem *dev,
+ *								 u32 mask)
+ * @remarks	Enable endpoint interrupts
+ * @param	dev     [IN]    reference to structure of type ioh_udc_regs
+ * @param	mask    [IN]    mask to enable interrupts
+ * @retval	none
+ */
+void ioh_udc_enable_ep_interrupts(struct ioh_udc_regs __iomem *dev, u32 mask)
+{
+	/* set the mask */
+	IOH_CLR_ADDR_BIT((u32)&dev->epirqmsk, mask);
+	IOH_DEBUG("Interrupt ep mask reg     = %08x",
+					 IOH_READ32((u32)&dev->epirqmsk));
+}
+
+/*!@ingroup	UDC_HALLayerAPI
+ * @fn		ioh_udc_read_device_interrupts(struct ioh_udc_regs __iomem *dev)
+ * @remarks	Read the device interrupts
+ * @param	dev     [IN]    reference to structure of type ioh_udc_regs
+ * @retval	u32
+ *			- The device interrupts
+ */
+INLINE u32 ioh_udc_read_device_interrupts(struct ioh_udc_regs __iomem *dev)
+{
+	return IOH_READ32((u32)&dev->devirqsts);
+}
+
+/*!@ingroup	UDC_HALLayerAPI
+ * @fn		ioh_udc_write_device_interrupts
+ *				(struct ioh_udc_regs __iomem *dev, u32 val)
+ * @remarks	Write device interrupts
+ * @param	dev     [IN]    reference to structure of type ioh_udc_regs
+ * @param	val	[IN]	the value to be written to interrupt register
+ * @retval	none
+ */
+INLINE void ioh_udc_write_device_interrupts(struct ioh_udc_regs __iomem *dev,
+								 u32 val)
+{
+	IOH_WRITE32(val, (u32)&dev->devirqsts);
+}
+
+/*!@ingroup	UDC_HALLayerAPI
+ * @fn		ioh_udc_read_ep_interrupts(struct ioh_udc_regs __iomem *dev)
+ * @remarks	Read the endpoint interrupts
+ * @param	dev     [IN]    reference to structure of type ioh_udc_regs
+ * @retval	u32
+ *			- the endpoint interrupt
+ */
+INLINE u32 ioh_udc_read_ep_interrupts(struct ioh_udc_regs __iomem *dev)
+{
+	return IOH_READ32((u32)&dev->epirqsts);
+}
+
+/*!@ingroup	UDC_HALLayerAPI
+ * @fn		ioh_udc_write_ep_interrupts
+ * @remarks	Clear endpoint interupts
+ * @param	dev	[IN]	reference to structure of type ioh_udc_regs
+ * @param	val	[IN]	the value to be written to interrupt register
+ * @retval	none
+ */
+INLINE void ioh_udc_write_ep_interrupts(struct ioh_udc_regs __iomem *dev,
+								 u32 val)
+{
+	IOH_WRITE32(val, (u32)&dev->epirqsts);
+}
+
+/*!@ingroup	UDC_HALLayerAPI
+ * @fn		ioh_udc_read_device_status
+ * @remarks	Read the device status
+ * @param	dev     [IN]    reference to structure of type ioh_udc_regs
+ * @retval	u32
+ *			- the device status
+ */
+INLINE u32 ioh_udc_read_device_status(struct ioh_udc_regs __iomem *dev)
+{
+	return IOH_READ32((u32)&dev->devsts);
+}
+
+/*!@ingroup	UDC_HALLayerAPI
+ * @fn		ioh_udc_read_ep_control(struct ioh_udc_ep_regs __iomem *ep)
+ * @remarks	Read the endpoint control
+ * @param	ep	[IN]	reference to structure of type ioh_udc_ep_regs
+ * @retval	u32
+ *			- the endpoint control register value
+ */
+INLINE u32 ioh_udc_read_ep_control(struct ioh_udc_ep_regs __iomem *ep)
+{
+	return IOH_READ32((u32)&ep->epctl);
+}
+
+/*!@ingroup	UDC_HALLayerAPI
+ * @fn		ioh_udc_clear_ep_control(struct ioh_udc_ep_regs __iomem *ep)
+ * @remarks	Clear the endpoint control register
+ * @param	ep	[IN]	reference to structure of type ioh_udc_ep_regs
+ * @retval	u32
+ * 			- the endpoint control register value
+ */
+INLINE void ioh_udc_clear_ep_control(struct ioh_udc_ep_regs __iomem *ep)
+{
+	return IOH_WRITE32(0, (u32)&ep->epctl);
+}
+
+/*!@ingroup	UDC_HALLayerAPI
+ * @fn		ioh_udc_read_ep_status(struct ioh_udc_ep_regs __iomem *ep)
+ * @remarks	Read the endpoint status
+ * @param	ep	[IN]	reference to structure of type ioh_udc_ep_regs
+ * @retval	u32
+ * 			- the endpoint status
+ */
+INLINE u32 ioh_udc_read_ep_status(struct ioh_udc_ep_regs __iomem *ep)
+{
+	return IOH_READ32((u32)&ep->epsts);
+}
+
+/*!@ingroup	UDC_HALLayerAPI
+ * @fn		ioh_udc_clear_ep_status(struct ioh_udc_ep_regs __iomem *ep,
+ *								 u32 stat)
+ * @remarks	Clear the endpoint status
+ * @param	ep  	[IN]    reference to structure of type ioh_udc_ep_regs
+ * @param	stat	[IN]	endpoint status
+ * @retval	none
+ */
+INLINE void ioh_udc_clear_ep_status(struct ioh_udc_ep_regs __iomem *ep,
+								 u32 stat)
+{
+	return IOH_WRITE32(stat, (u32)&ep->epsts);
+}
+
+/*!@ingroup	UDC_HALLayerAPI
+ * @fn		ioh_udc_ep_set_nak(struct ioh_udc_ep_regs __iomem *ep)
+ * @remarks	Set the bit 7 (SNAK field) of the endpoint control register
+ * @param	ep      [IN]    reference to structure of type ioh_udc_ep_regs
+ * @retval	none
+ */
+void ioh_udc_ep_set_nak(struct ioh_udc_ep_regs __iomem *ep)
+{
+	IOH_SET_ADDR_BIT((u32)&ep->epctl, 1 << UDC_EPCTL_SNAK);
+}
+
+/*!@ingroup	UDC_HALLayerAPI
+ * @fn		ioh_udc_ep_clear_nak(struct ioh_udc_ep_regs __iomem *ep)
+ * @remarks	Set the bit 8 (CNAK field) of the endpoint control register
+ * @param	ep      [IN]    reference to structure of type ioh_udc_ep_regs
+ * @retval	none
+ */
+void ioh_udc_ep_clear_nak(struct ioh_udc_ep_regs __iomem *ep)
+{
+	unsigned int loopcnt = 0;
+
+	if (IOH_READ32((u32)&ep->epctl) & (1 << UDC_EPCTL_NAK)) {
+		if (!(EP_IS_IN(ep))) {
+			while ((ioh_udc_read_ep_status(ep) &
+					 (1 << UDC_EPSTS_MRXFIFO_EMP)) == 0) {
+				if (loopcnt++ > 100000) {
+					IOH_DEBUG("RxFIFO not Empty loop \
+							count = %d", loopcnt);
+					break;
+				}
+				udelay(100);
+			}
+		}
+		while (IOH_READ32((u32)&ep->epctl) & (1 << UDC_EPCTL_NAK)) {
+			IOH_SET_ADDR_BIT((u32)&ep->epctl, 1 << UDC_EPCTL_CNAK);
+			udelay(5);
+			if (loopcnt++ >= 25) {
+				IOH_DEBUG("Clear NAK not set for ep%d%s:\
+					 counter=%d",
+					 EP_NUM(ep), (EP_IS_IN(ep) ? \
+					"in" : "out"), loopcnt);
+				break;
+			}
+		}
+	}
+}
+
+/*!@ingroup	UDC_HALLayerAPI
+ * @fn	ioh_udc_ep_fifo_flush(struct ioh_udc_ep_regs __iomem *ep, int dir)
+ * @remarks	The main tasks performed by this method are:
+ *- If the endpoint is IN,
+ *	- set the bit 1 (F) of endpoint control register
+ *- Otherwise
+ *	- If the Rx FIFO is not empty,
+ *		- Set bit 12 (MRX FLUSH) of EP control register
+ *		- Wait till MRXFIFO EMPTY (bit 8) is set in EP status register
+ *		- Clear bit 12 (MRX FLUSH) of EP control register
+ * @param	ep      [IN]    reference to structure of type ioh_udc_ep_regs
+ * @param	dir		[IN]	direction of endpoint
+ *			- dir = 0 endpoint is OUT
+ *			- dir != 0 endpoint is IN
+ * @retval	none
+ */
+void ioh_udc_ep_fifo_flush(struct ioh_udc_ep_regs __iomem *ep, int dir)
+{
+	unsigned int loopcnt = 0;
+
+	IOH_DEBUG("ioh_udc_ep_fifo_flush: ep%d%s", EP_NUM(ep),
+						 (EP_IS_IN(ep) ? "in" : "out"));
+	if (dir) {	/* IN ep */
+		IOH_SET_ADDR_BIT((u32)&ep->epctl, 1 << UDC_EPCTL_F);
+	} else {
+		if ((ioh_udc_read_ep_status(ep) &
+					 (1 << UDC_EPSTS_MRXFIFO_EMP)) == 0) {
+			IOH_SET_ADDR_BIT((u32)&ep->epctl, 1 <<
+							 UDC_EPCTL_MRXFLUSH);
+			/* Wait for RxFIFO Empty */
+			while ((ioh_udc_read_ep_status(ep) &
+					 (1 << UDC_EPSTS_MRXFIFO_EMP)) == 0) {
+				if (loopcnt++ > 1000000) {
+					IOH_DEBUG("RxFIFO not Empty loop\
+							 count = %d", loopcnt);
+					break;
+				}
+				udelay(100);
+			}
+			IOH_CLR_ADDR_BIT((u32)&ep->epctl, 1 <<
+							 UDC_EPCTL_MRXFLUSH);
+		}
+	}
+}
+
+/* Enables endpoint */
+/*!@ingroup	UDC_HALLayerAPI
+ * @fn		ioh_udc_ep_enable(struct ioh_udc_ep_regs __iomem *regs,
+ *						 struct ioh_udc_cfg_data *cfg,
+ *			const struct usb_endpoint_descriptor *desc)
+ * @remarks	The following actions are performed:
+ *- Set transfer type of the endpoint using ioh_udc_ep_set_trfr_type
+ *	API passing desc->bmAttributes
+ *- Set Buffer size for the endpoint by ioh_udc_ep_set_bufsz
+ *- Set Maximum packet size for the endpoint using ioh_udc_ep_set_maxpkt
+ *	API, passing desc->wMaxPacketSize
+ *- Flush FIFO of the endpoint by ioh_udc_ep_fifo_flush
+ *- Set NAK of the endpoint by ioh_udc_ep_set_nak
+ *- Calculate the endpoint configuration value from the following parameters
+ *	and update the same in corresponding register [based on endpoint
+ *	direction]using ioh_udc_write_csr API:
+ *	- endpoint (ep) number
+ *	- ep direction
+ *	- ep transfer type mask
+ *	- cfg->cur_cfg
+ *	- cfg->cur_intf
+ *	- cfg->cur_intf
+ *	- desc->wMaxPacketSize
+ * @param	regs	[IN]	Reference to structure ioh_udc_ep_regs
+ * @param	desc	[IN]	endpoint descriptor
+ * @retval	none
+ * @see
+ *			- ioh_udc_ep_set_trfr_type
+ *			- ioh_udc_ep_set_bufsz
+ *			- ioh_udc_ep_set_maxpkt
+ *			- ioh_udc_ep_set_nak
+ *			- ioh_udc_ep_fifo_flush
+ *			- ioh_udc_write_csr
+ */
+void ioh_udc_ep_enable(struct ioh_udc_ep_regs __iomem *regs,
+				 struct ioh_udc_cfg_data *cfg,
+				const struct usb_endpoint_descriptor *desc)
+{
+	u32 ep_num = EP_NUM(regs);
+	u32 ep_in = EP_IS_IN(regs);
+	u32 val = 0;
+	u32 buff_size = 0;
+
+	IOH_DEBUG("ioh_udc_ep_enable: ep%x%s  bmAttributes = %d\
+			 wMaxPacketSize = %d",
+			 ep_num, (ep_in ? "in" : "out"), desc->bmAttributes,
+			 desc->wMaxPacketSize);
+	/* set traffic type */
+	ioh_udc_ep_set_trfr_type(regs, desc->bmAttributes);
+	/* Set buff size */
+	if (ep_in)
+		buff_size = UDC_EPIN_BUFF_SIZE;
+	else
+		buff_size = UDC_EPOUT_BUFF_SIZE;
+
+	ioh_udc_ep_set_bufsz(regs, buff_size, ep_in);
+	/* Set max packet size */
+	ioh_udc_ep_set_maxpkt(regs, le16_to_cpu(desc->wMaxPacketSize));
+	/* Set NAK */
+	ioh_udc_ep_set_nak(regs);
+	/* Flush fifo */
+	ioh_udc_ep_fifo_flush(regs, ep_in);
+	/* Configure the endpoint */
+	val = ep_num << UDC_CSR_NE_NUM_OFS | ep_in << UDC_CSR_NE_DIR_OFS |
+			((desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) <<
+			 UDC_CSR_NE_TYPE_OFS) |
+			(cfg->cur_cfg << UDC_CSR_NE_CFG_OFS) |
+			(cfg->cur_intf << UDC_CSR_NE_INTF_OFS) |
+			(cfg->cur_alt << UDC_CSR_NE_ALT_OFS) |
+			le16_to_cpu(desc->wMaxPacketSize) <<
+			 UDC_CSR_NE_MAX_PKT_OFS;
+
+	if (ep_in)
+		ioh_udc_write_csr(val, (u32) (ioh_udc_base + UDC_CSR_ADDR +
+							 (ep_num * 2) * 4));
+	else
+		ioh_udc_write_csr(val, (u32) (ioh_udc_base + UDC_CSR_ADDR +
+							 (ep_num * 2 + 1) * 4));
+
+	IOH_DEBUG("ioh_udc_ep_enable: Endpoint register = 0x%08x", val);
+}
+
+/* Resets endpoint */
+/*!@ingroup	UDC_HALLayerAPI
+ * @fn		ioh_udc_ep_disable(struct ioh_udc_ep_regs __iomem *regs)
+ * @remarks	The following actions are performed:
+ *- If the endpoint is IN,
+ *	- Set the bit 1 (Flush field) and clear other bit of endpoint control
+ *								 register
+ *	- Set the bit 7 (SNAK field) and clear other bit of the endpoint control
+ *								 register
+ *	- Set the bit 6 (IN field) of the endpoint status register
+ *- Otherwise
+ *	- Set the bit 7 (SNAK field) and clear other bit of the endpoint control
+ *								 register
+ *- Initialize the data descriptor pointer to 0 using
+ *				ioh_udc_ep_set_ddptr API
+ * @param	regs    [IN]    Reference to structure ioh_udc_ep_regs
+ * @retval	none
+ */
+void ioh_udc_ep_disable(struct ioh_udc_ep_regs __iomem *regs)
+{
+	if (EP_IS_IN(regs)) {
+		/* flush the fifo */
+		IOH_WRITE32(1 << UDC_EPCTL_F , (u32)&regs->epctl);
+		/* set NAK */
+		IOH_WRITE32(1 << UDC_EPCTL_SNAK , (u32)&regs->epctl);
+
+		IOH_SET_ADDR_BIT((u32)&regs->epsts, 1 << UDC_EPSTS_IN);
+	} else {
+		/* set NAK */
+		IOH_WRITE32(1 << UDC_EPCTL_SNAK , (u32)&regs->epctl);
+	}
+	/* reset desc pointer */
+	IOH_WRITE32(0, (u32)&regs->desptr);
+}
--- /dev/null
+++ b/drivers/usb/gadget/pch_udc_hal.h
@@ -0,0 +1,1829 @@
+ /*!
+ * @file ioh_udc_hal.h
+ * @brief	This file contains the declarations for all HAL layer APIs.
+ *									It also
+ *			lists the various macros used by HAL layer.
+ *
+ * The IOH UDC is a USB High speed DMA capable USB device controller.
+ * It provides 4 IN and 4 OUT endpoints (control, bulk isochronous or
+ *							 interrupt type).
+ *
+ * The IOH USB device controller driver provides required interface
+ * to the USB gadget framework for accessing the IOH USB device hardware.
+ *
+ * @version 0.96
+ *
+ * @section
+ * 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; version 2 of the License.
+ *
+ * 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.
+ */
+
+ /*
+ * History:
+ * Copyright (C) 2009 OKI SEMICONDUCTOR Co., LTD.
+ * All rights reserved.
+ *
+ * created:
+ *   OKI SEMICONDUCTOR 2/26/2010
+ * modified:
+ *
+ */
+
+#ifndef _IOH_UDC_HAL_H_
+#define _IOH_UDC_HAL_H_
+
+#include <linux/types.h>
+
+/*! @defgroup UDC */
+
+/*! @defgroup   UDC_Global
+@ingroup        UDC
+@brief          This group describes the global entities within
+		the module.
+@remarks        This group includes all the global data structures
+		used within the modules. These are mainly used to
+		store the device related information, so that it can
+		be used by other functions of the modules.
+<hr>
+*/
+
+/*! @defgroup   UDC_PCILayer
+@ingroup        UDC
+@brief          This group describes the PCI layer interface
+		functionalities.
+@remarks        This group contains the functions and data structures
+		that are used to interface the module with PCI Layer
+		subsystem of the Kernel.
+<hr>
+*/
+
+/*! @defgroup   UDC_InterfaceLayer
+@ingroup        UDC
+@brief          This group describes the Driver interface functionalities.
+@remarks        This group contains the data structures and functions used
+		to interface the module driver with the kernel subsystem.
+<hr>
+*/
+
+/*! @defgroup   UDC_HALLayer
+@ingroup        UDC
+@brief          This group describes the hardware specific functionalities.
+@remarks        This group contains the functions and data structures used
+		by the module to communicate with the hardware. These
+		functions are device specific and designed according to the
+		device specifications.
+<hr>
+*/
+
+/*! @defgroup   UDC_Utilities
+@ingroup        UDC
+@brief          This group describes the utility functionalities.
+@remarks        This group contains the functions and data structures used
+		to assist the other functionalities in their operations.
+<hr>
+*/
+
+/*! @defgroup   UDC_PCILayerAPI
+@ingroup        UDC_PCILayer
+@brief          This group contains the API(functions) used as the PCI
+		interface between the Kernel subsystem and the module.
+<hr>
+*/
+
+/*! @defgroup   UDC_PCILayerFacilitators
+@ingroup        UDC_PCILayer
+@brief          This group contains the data structures used by the PCI
+		Layer APIs for their functionalities.
+<hr>
+*/
+
+/*! @defgroup   UDC_InterfaceLayerAPI
+@ingroup        UDC_InterfaceLayer
+@brief          This group contains the API(functions) used as the Driver
+
+<hr>
+*/
+
+/*! @defgroup   UDC_InterfaceLayerFacilitators
+@ingroup        UDC_InterfaceLayer
+@brief          This group contains the data structures used by the Driver
+		interface APIs for their functionalities.
+<hr>
+*/
+
+/*! @defgroup   UDC_HALLayerAPI
+@ingroup        UDC_HALLayer
+@brief          This group contains the APIs(functions) used to interact with
+		the hardware. These APIs act as an interface between the
+		hardware and the other driver functions.
+<hr>
+*/
+
+/*! @defgroup   UDC_UtilitiesAPI
+@ingroup        UDC_Utilities
+@brief          This group contains the APIs(functions) used by other functions
+		in their operations.
+<hr>
+*/
+
+
+/* Device Config Register */
+/*! @ingroup    UDC_HALLayer
+@def			UDC_DEVCFG_ADDR
+@brief			Address offset of Device Configuration Register
+*/
+#define UDC_DEVCFG_ADDR				0x400
+
+/*! @ingroup    UDC_HALLayer
+@def			UDC_DEVCFG_SET_DESC
+@brief			Bit position of SET_DESC field in
+				Device configuration register
+*/
+#define UDC_DEVCFG_SET_DESC			18
+
+/*! @ingroup	UDC_HALLayer
+@def			UDC_DEVCFG_CSR_PRG
+@brief			Bit position of CSR_PRG field in
+		Device configuration register
+*/
+
+#define UDC_DEVCFG_CSR_PRG			17
+
+/*! @ingroup	UDC_HALLayer
+@def			UDC_DEVCFG_HALT_STATUS
+@brief			Bit position of HALT_STATUS field in
+				Device configuration register.
+*/
+#define UDC_DEVCFG_HALT_STATUS		16
+
+/*! @ingroup	UDC_HALLayer
+@def			UDC_DEVCFG_STATUS1
+@brief          Bit position of STATUS1 field in
+		Device configuration register.
+*/
+#define UDC_DEVCFG_STATUS1			8
+
+/*! @ingroup    UDC_HALLayer
+@def			UDC_DEVCFG_STATUS
+@brief			Bit position of STATUS field in
+				Device configuration register.
+*/
+#define UDC_DEVCFG_STATUS			7
+
+/*! @ingroup    UDC_HALLayer
+@def			UDC_DEVCFG_DIR
+@brief          Bit position of DIR field in
+		Device configuration register.
+*/
+#define UDC_DEVCFG_DIR				6
+
+/*! @ingroup    UDC_HALLayer
+@def			UDC_DEVCFG_PI
+@brief          Bit position of PI field in
+		Device configuration register.
+*/
+#define UDC_DEVCFG_PI				5
+
+/*! @ingroup    UDC_HALLayer
+@def			UDC_DEVCFG_SS
+@brief			Bit position of SS field in
+		Device configuration register.
+*/
+#define UDC_DEVCFG_SS				4
+
+/*! @ingroup    UDC_HALLayer
+@def			UDC_DEVCFG_SP
+@brief          Bit position of SP field in
+		Device configuration register.
+*/
+#define UDC_DEVCFG_SP				3
+
+/*! @ingroup    UDC_HALLayer
+@def			UDC_DEVCFG_RWKP
+@brief          Bit position of RWKP field in
+		Device configuration register.
+*/
+#define UDC_DEVCFG_RWKP				2
+
+/*! @ingroup    UDC_HALLayer
+@def			UDC_DEVCFG_SPD_MASK
+@brief          Mask for SPD bits in
+				Device configuration register.
+*/
+#define UDC_DEVCFG_SPD_MASK			0x3
+
+/*! @ingroup    UDC_HALLayer
+@def			UDC_DEVCFG_SPD_OFS
+*/
+#define UDC_DEVCFG_SPD_OFS			0
+
+/*! @ingroup    UDC_HALLayer
+@def			UDC_DEVCFG_SPD_HS
+*/
+#define UDC_DEVCFG_SPD_HS			0x0
+
+/*! @ingroup    UDC_HALLayer
+@def			UDC_DEVCFG_SPD_FS
+*/
+#define UDC_DEVCFG_SPD_FS			0x1
+
+/*! @ingroup    UDC_HALLayer
+@def			UDC_DEVCFG_SPD_LS
+*/
+#define UDC_DEVCFG_SPD_LS			0x2
+/*#define UDC_DEVCFG_SPD_FS			0x3*/
+
+/* Device Control Register */
+
+/*! @ingroup    UDC_HALLayer
+@def			UDC_DEVCTL_ADDR
+@brief			Address offset for Device control register
+*/
+#define UDC_DEVCTL_ADDR				0x404
+
+/*! @ingroup    UDC_HALLayer
+@def			UDC_DEVCTL_THLEN_MASK
+@brief			Mask for Threshold length field of
+				Device control register.
+*/
+#define UDC_DEVCTL_THLEN_MASK			0xff000000
+
+/*! @ingroup    UDC_HALLayer
+@def			UDC_DEVCTL_THLEN_OFS
+*/
+#define UDC_DEVCTL_THLEN_OFS			24
+
+/*! @ingroup    UDC_HALLayer
+@def			UDC_DEVCTL_BRLEN_MASK
+@brief			Mask for Burst length field of
+				Device control register.
+*/
+#define UDC_DEVCTL_BRLEN_MASK			0x00ff0000
+
+/*! @ingroup    UDC_HALLayer
+@def			UDC_DEVCTL_BRLEN_OFS
+@brief			Starting bit position of
+				Burst length field in Device
+				control register.
+*/
+#define UDC_DEVCTL_BRLEN_OFS			16
+
+/*! @ingroup    UDC_HALLayer
+@def			UDC_DEVCTL_CSR_DONE
+@brief			The bit position of CSR_DONE
+				field in Device control register.
+*/
+#define UDC_DEVCTL_CSR_DONE			13
+
+/*! @ingroup    UDC_HALLayer
+@def			UDC_DEVCTL_DEVNAK
+@brief			The bit position of DEVNAK
+				field in Device control register.
+*/
+#define UDC_DEVCTL_DEVNAK			12
+
+/*! @ingroup    UDC_HALLayer
+@def			UDC_DEVCTL_SD
+@brief			The bit position of SD field in
+				Device control register.
+*/
+#define UDC_DEVCTL_SD				10
+
+/*! @ingroup    UDC_HALLayer
+@def			UDC_DEVCTL_MODE
+@brief          The bit position of MODE
+				field in Device control register.
+*/
+#define UDC_DEVCTL_MODE				9
+
+/*! @ingroup    UDC_HALLayer
+@def			UDC_DEVCTL_BREN
+@brief			The bit position of BREN
+		field in Device control register.
+*/
+#define UDC_DEVCTL_BREN				8
+
+/*! @ingroup    UDC_HALLayer
+@def            UDC_DEVCTL_THE
+@brief          The bit position of THE
+		field in Device control register.
+*/
+#define UDC_DEVCTL_THE				7
+
+/*! @ingroup    UDC_HALLayer
+@def			UDC_DEVCTL_BF
+@brief          The bit position of BF
+		field in Device control register.
+*/
+#define UDC_DEVCTL_BF				6
+
+/*! @ingroup    UDC_HALLayer
+@def			UDC_DEVCTL_BE
+@brief			The bit position of BE
+		field in Device control register.
+*/
+#define UDC_DEVCTL_BE				5
+
+/*! @ingroup    UDC_HALLayer
+@def			UDC_DEVCTL_DU
+@brief          The bit position of DU
+		field in Device control register.
+*/
+#define UDC_DEVCTL_DU				4
+
+/*! @ingroup    UDC_HALLayer
+@def			UDC_DEVCTL_TDE
+@brief          The bit position of TDE
+		field in Device control register.
+*/
+#define UDC_DEVCTL_TDE				3
+
+/*! @ingroup    UDC_HALLayer
+@def			UDC_DEVCTL_RDE
+@brief          The bit position of RDE
+		field in Device control register.
+*/
+#define UDC_DEVCTL_RDE				2
+
+/*! @ingroup    UDC_HALLayer
+@def			UDC_DEVCTL_RES
+@brief          The bit position of RES
+		field in Device control register.
+*/
+#define UDC_DEVCTL_RES				0
+
+/*! @ingroup    UDC_HALLayer
+@def			IOH_UDC_BRLEN
+@brief			Specifies the Burst Length
+*/
+#define IOH_UDC_BRLEN				0xF	/* Burst length */
+
+/*! @ingroup    UDC_HALLayer
+@def			IOH_UDC_THLEN
+@brief          Specifies the Threshold Length
+*/
+#define IOH_UDC_THLEN				0x1F	/* Threshold length */
+
+/*! @ingroup    UDC_HALLayer
+@def			DMA_DIR_RX
+@brief			Specifies DMA for data receive
+*/
+#define DMA_DIR_RX	1
+
+/*! @ingroup    UDC_HALLayer
+@def			DMA_DIR_TX
+@brief			Specifies DMA for data transmit
+*/
+#define DMA_DIR_TX	2
+
+/*! @ingroup    UDC_HALLayer
+@def			UDC_DMA_MAXPACKET
+@brief			Specifies maximum packet size for DMA
+*/
+#define UDC_DMA_MAXPACKET	65536
+
+/* Device Status Register */
+/*! @ingroup    UDC_HALLayer
+@def			UDC_DEVSTS_ADDR
+@brief			The address offset for Device Status register.
+*/
+#define UDC_DEVSTS_ADDR				0x408
+
+/*! @ingroup    UDC_HALLayer
+@def			UDC_DEVSTS_TS_MASK
+@brief			Mask for TS field of
+				Device status register
+*/
+#define UDC_DEVSTS_TS_MASK			0xfffc0000
+
+/*! @ingroup    UDC_HALLayer
+@def			UDC_DEVSTS_TS_OFS
+@brief			Starting bit position of TS field of
+				Device status register
+*/
+#define UDC_DEVSTS_TS_OFS			18
+
+/*! @ingroup    UDC_HALLayer
+@def			UDC_DEVSTS_RWKPST
+@brief			Bit position of RWKPST field of
+				Device status register
+*/
+#define UDC_DEVSTS_RWKPST				17
+
+/*! @ingroup    UDC_HALLayer
+@def			UDC_DEVSTS_PHY_ERROR
+@brief			Bit position of PHY_ERROR field of
+				Device status register
+*/
+#define UDC_DEVSTS_PHY_ERROR			16
+
+/*! @ingroup    UDC_HALLayer
+@def			UDC_DEVSTS_RXFIFO_EMPTY
+@brief			Bit position of RXFIFO_EMPTY field of
+		Device status register
+*/
+#define UDC_DEVSTS_RXFIFO_EMPTY			15
+
+/*! @ingroup    UDC_HALLayer
+@def			UDC_DEVSTS_ENUM_SPEED_MASK
+@brief			Mask for SPEED field of
+				Device status register
+*/
+#define UDC_DEVSTS_ENUM_SPEED_MASK		0x00006000
+
+/*! @ingroup    UDC_HALLayer
+@def			UDC_DEVSTS_ENUM_SPEED_OFS
+@brief			Starting bit position of SPEED field
+				of  Device status register
+*/
+#define UDC_DEVSTS_ENUM_SPEED_OFS		13
+
+/*! @ingroup    UDC_HALLayer
+@def			UDC_DEVSTS_ENUM_SPEED_FULL
+@brief			Specifies value for maximum speed for
+				SPEED field of Device status register
+*/
+#define UDC_DEVSTS_ENUM_SPEED_FULL		1
+
+/*! @ingroup    UDC_HALLayer
+@def			UDC_DEVSTS_ENUM_SPEED_HIGH
+@brief			Specifies value for high speed for
+				SPEED field of Device status register
+*/
+#define UDC_DEVSTS_ENUM_SPEED_HIGH		0
+
+/*! @ingroup    UDC_HALLayer
+@def			UDC_DEVSTS_ENUM_SPEED_LOW
+@brief			Specifies value for low speed for
+				SPEED field of Device status register
+*/
+#define UDC_DEVSTS_ENUM_SPEED_LOW		2
+
+/*! @ingroup    UDC_HALLayer
+@def			UDC_DEVSTS_ENUM_SPEED_FULLX
+@brief			Specifies value for full speed for
+				SPEED field of Device status register
+*/
+#define UDC_DEVSTS_ENUM_SPEED_FULLX		3
+
+/*! @ingroup    UDC_HALLayer
+@def			UDC_DEVSTS_SUSP
+@brief			Bit position of SUSP field of
+				Device status register.
+*/
+#define UDC_DEVSTS_SUSP				12
+
+/*! @ingroup    UDC_HALLayer
+@def			UDC_DEVSTS_ALT_MASK
+@brief			Mask for ALT field of
+				Device status register.
+*/
+#define UDC_DEVSTS_ALT_MASK			0x00000f00
+
+/*! @ingroup    UDC_HALLayer
+@def			UDC_DEVSTS_ALT_OFS
+@brief			Starting bit position of
+				ALT field of Device status register.
+*/
+#define UDC_DEVSTS_ALT_OFS			8
+
+/*! @ingroup    UDC_HALLayer
+@def			UDC_DEVSTS_INTF_MASK
+@brief			Mask for INTF field of
+				Device status register.
+*/
+#define UDC_DEVSTS_INTF_MASK			0x000000f0
+
+/*! @ingroup    UDC_HALLayer
+@def			UDC_DEVSTS_INTF_OFS
+@brief			The starting bit position for INTF field
+				in Device status register.
+*/
+#define UDC_DEVSTS_INTF_OFS			4
+
+/*! @ingroup    UDC_HALLayer
+@def			UDC_DEVSTS_CFG_MASK
+@brief			Mask for CFG field in
+				Device status register.
+*/
+#define UDC_DEVSTS_CFG_MASK			0x0000000f
+
+/*! @ingroup    UDC_HALLayer
+@def			UDC_DEVSTS_CFG_OFS
+@brief			Starting bit position for CFG field
+				in Device status register.
+*/
+#define UDC_DEVSTS_CFG_OFS			0
+
+
+/* Device Interrupt Register */
+/*! @ingroup    UDC_HALLayer
+@def			UDC_DEVINT_ADDR
+@brief			The address offset for
+				Device interrupt register
+*/
+#define UDC_DEVINT_ADDR				0x40c
+/*! @ingroup    UDC_HALLayer
+@def			UDC_DEVINT_RWKP
+@brief			The bit position for
+				RWKP field in Device interrupt register
+*/
+#define UDC_DEVINT_RWKP				7
+
+/*! @ingroup    UDC_HALLayer
+@def			UDC_DEVINT_ENUM
+@brief			Bit position for ENUM field in
+				Device interrupt register
+*/
+#define UDC_DEVINT_ENUM				6
+
+/*! @ingroup    UDC_HALLayer
+@def			UDC_DEVINT_SOF
+@brief			Bit position for SOF field in
+				Device interrupt register
+*/
+#define UDC_DEVINT_SOF				5
+
+/*! @ingroup    UDC_HALLayer
+@def			UDC_DEVINT_US
+@brief			Bit position for US field in
+				Device interrupt register
+*/
+#define UDC_DEVINT_US				4
+
+/*! @ingroup    UDC_HALLayer
+@def			UDC_DEVINT_UR
+@brief			Bit position for UR field in
+				Device interrupt register
+*/
+#define UDC_DEVINT_UR				3
+
+/*! @ingroup    UDC_HALLayer
+@def			UDC_DEVINT_ES
+@brief			Bit position for ES field in
+				Device interrupt register
+*/
+#define UDC_DEVINT_ES				2
+
+/*! @ingroup    UDC_HALLayer
+@def			UDC_DEVINT_SI
+@brief			Bit position for SI field in
+				Device interrupt register
+*/
+#define UDC_DEVINT_SI				1
+
+/*! @ingroup    UDC_HALLayer
+@def			UDC_DEVINT_SC
+@brief			Bit position for SC field in
+				Device interrupt register
+*/
+#define UDC_DEVINT_SC				0
+
+/* Device Interrupt Mask Register */
+/*! @ingroup    UDC_HALLayer
+@def			UDC_DEVINT_MASK_ADDR
+@brief			The address offset for
+				Device interrupt mask register
+*/
+#define UDC_DEVINT_MSK_ADDR			0x410
+
+/*! @ingroup    UDC_HALLayer
+@def			UDC_DEVINT_MSK
+@brief			Interrupt Mask
+*/
+#define UDC_DEVINT_MSK				0x7f
+
+/* Endpoint Interrupt Register */
+/*! @ingroup    UDC_HALLayer
+@def			UDC_EPINT_ADDR
+@brief			The address offset for
+				Endpoint interrupt register
+*/
+#define UDC_EPINT_ADDR				0x414
+
+/*! @ingroup    UDC_HALLayer
+@def			UDC_EPINT_OUT_MASK
+@brief			Mask for OUT field in
+				Endpoint interrupt register
+*/
+#define UDC_EPINT_OUT_MASK			0xffff0000
+
+/*! @ingroup    UDC_HALLayer
+@def			UDC_EPINT_OUT_OFS
+@brief			Starting bit position for OUT field of
+				Endpoint interrupt register
+*/
+#define UDC_EPINT_OUT_OFS			16
+
+/*! @ingroup    UDC_HALLayer
+@def			UDC_EPINT_IN_MASK
+@brief			Mask for IN field in
+				Endpoint interrupt register
+*/
+#define UDC_EPINT_IN_MASK			0x0000ffff
+/*! @ingroup    UDC_HALLayer
+@def			UDC_EPINT_IN_OFS
+@brief			Starting bit position for IN field of
+				Endpoint interrupt register
+*/
+#define UDC_EPINT_IN_OFS			0
+
+/*! @ingroup    UDC_HALLayer
+@def			UDC_EPINT_IN_EP0
+@brief			Bit position for IN_EP0 field in
+				Endpoint interrupt register
+*/
+#define UDC_EPINT_IN_EP0			0
+
+/*! @ingroup    UDC_HALLayer
+@def			UDC_EPINT_IN_EP1
+@brief			Bit position for IN_EP1 field in
+				Endpoint interrupt register
+*/
+#define UDC_EPINT_IN_EP1			1
+
+/*! @ingroup    UDC_HALLayer
+@def			UDC_EPINT_IN_EP2
+@brief			Bit position for IN_EP2 field in
+				Endpoint interrupt register
+*/
+#define UDC_EPINT_IN_EP2			2
+
+/*! @ingroup    UDC_HALLayer
+@def			UDC_EPINT_IN_EP3
+@brief			Bit position for IN_EP3 field in
+				Endpoint interrupt register
+*/
+#define UDC_EPINT_IN_EP3			3
+
+/*! @ingroup    UDC_HALLayer
+@def			UDC_EPINT_OUT_EP0
+@brief			Bit position for OUT_EP0 field in
+				Endpoint interrupt register
+*/
+#define UDC_EPINT_OUT_EP0			16
+
+/*! @ingroup    UDC_HALLayer
+@def			UDC_EPINT_OUT_EP1
+@brief			Bit position for OUT_EP1 field in
+				Endpoint interrupt register
+*/
+#define UDC_EPINT_OUT_EP1			17
+
+/*! @ingroup    UDC_HALLayer
+@def			UDC_EPINT_OUT_EP2
+@brief			Bit position for OUT_EP2 field in
+				Endpoint interrupt register
+*/
+#define UDC_EPINT_OUT_EP2			18
+
+/*! @ingroup    UDC_HALLayer
+@def			UDC_EPINT_OUT_EP3
+@brief			Bit position for OUT_EP3 field in
+				Endpoint interrupt register
+*/
+#define UDC_EPINT_OUT_EP3			19
+
+/*! @ingroup    UDC_HALLayer
+@def			UDC_EPINT_EP0_ENABLE_MSK
+@brief			Mask to enable EP0 interrupt in
+				Endpoint interrupt register
+*/
+#define UDC_EPINT_EP0_ENABLE_MSK		0x000e000e
+
+/* Endpoint Interrupt Mask Register -----------------------------------------*/
+/*! @ingroup    UDC_HALLayer
+@def			UDC_EPINT_MSK_ADDR
+@brief			Address offset for 	Endpoint Interrupt Mask Register
+*/
+#define UDC_EPINT_MSK_ADDR			0x418
+
+/*! @ingroup    UDC_HALLayer
+@def			UDC_EPINT_OUT_MSK_MASK
+@brief			Mask for OUT_MSK field of
+				Endpoint Interrupt Mask Register
+*/
+#define UDC_EPINT_OUT_MSK_MASK			0xffff0000
+
+/*! @ingroup    UDC_HALLayer
+@def			UDC_EPINT_OUT_MSK_OFS
+@brief			Starting bit position for OUT_MSK field of
+				Endpoint Interrupt Mask Register
+*/
+#define UDC_EPINT_OUT_MSK_OFS			16
+
+/*! @ingroup    UDC_HALLayer
+@def			UDC_EPINT_IN_MSK_MASK
+@brief			Mask for IN_MSK field of
+				Endpoint Interrupt Mask Register
+*/
+#define UDC_EPINT_IN_MSK_MASK			0x0000ffff
+
+/*! @ingroup    UDC_HALLayer
+@def			UDC_EPINT_IN_MSK_MASK
+@brief			Starting bit position for IN_MSK field of
+				Endpoint Interrupt Mask Register
+*/
+#define UDC_EPINT_IN_MSK_OFS			0
+
+/*! @ingroup    UDC_HALLayer
+@def			UDC_EPINT_IN_MSK_MASK
+@brief			Mask to disable all interrupts in
+				Endpoint Interrupt Mask Register
+*/
+#define UDC_EPINT_MSK_DISABLE_ALL		0xffffffff
+
+/* mask non-EP0 endpoints */
+/*! @ingroup    UDC_HALLayer
+@def			UDC_EPDATAINT_MSK_DISABLE
+@brief			mask non-EP0 endpoints
+*/
+#define UDC_EPDATAINT_MSK_DISABLE		0xfffefffe
+
+/* mask all dev interrupts */
+/*! @ingroup    UDC_HALLayer
+@def			UDC_DEV_MSK_DISABLE
+@brief			mask all dev interrupts
+*/
+#define UDC_DEV_MSK_DISABLE			0x7f
+
+/* UDC CSR Busy status Register -----------------------------------------*/
+/*!@ingroup		UDC_HALLayer
+@def			IOH_UDC_CSR_BUSY_ADDR
+@brief			Address offset for UDC CSR Busy status Register
+*/
+#define IOH_UDC_CSR_BUSY_ADDR			0x4f0
+
+/*!@ingroup		UDC_HALLayer
+@def			IOH_UDC_CSR_BUSY
+@brief			Bit position of CSR field in
+				UDC CSR Busy status Register
+*/
+#define IOH_UDC_CSR_BUSY				1
+
+/* SOFT RESET Register ------------------------------------------------------*/
+/*!@ingroup		UDC_HALLayer
+@def			IOH_UDC_SRST_ADDR
+@brief			Address offset for UDC Soft reset Register
+*/
+#define IOH_UDC_SRST_ADDR			0x4fc
+
+/*!@ingroup		UDC_HALLayer
+@def			IOH_UDC_PHY_RESET
+@brief			Bit position of PSRST field in
+				UDC Soft Reset Register
+*/
+#define IOH_UDC_PSRST				1
+
+/*!@ingroup		UDC_HALLayer
+@def			IOH_UDC_SOFT_RESET
+@brief			Bit position of SRST field in
+				UDC Soft Reset Register
+*/
+#define IOH_UDC_SRST				0
+
+/* Endpoint-specific CSR's --------------------------------------------------*/
+
+/*!@ingroup       UDC_HALLayer
+@def			UDC_EPREGS_ADDR
+@brief			address offset for Endpoint-specific CSR
+*/
+#define UDC_EPREGS_ADDR				0x0
+
+/*!@ingroup       UDC_HALLayer
+@def			UDC_EPIN_REGS_ADDR
+@brief			address offset for EPIN register
+*/
+#define UDC_EPIN_REGS_ADDR			0x0
+
+/*!@ingroup       UDC_HALLayer
+@def			UDC_EPOUT_REGS_ADDR
+@brief			address offset for EPOUT register
+*/
+#define UDC_EPOUT_REGS_ADDR			0x200
+
+/*!@ingroup       UDC_HALLayer
+@def			EP_IS_IN(ep)
+*/
+#define EP_IS_IN(ep)	(((u32)(ep)) < (ioh_udc_base + UDC_EPOUT_REGS_ADDR))
+
+/*!@ingroup       UDC_HALLayer
+@def			EP_NUM(ep)
+*/
+#define EP_NUM(ep)	((((u32)(ep) - (ioh_udc_base +\
+					 UDC_EPREGS_ADDR)) / 0x20) & 0xf)
+
+/* Endpoint Control Registers */
+/*!@ingroup       UDC_HALLayer
+@def			UDC_EPCTL_ADDR
+@brief			Address offset for Endpoint Control Register
+*/
+#define UDC_EPCTL_ADDR				0x0
+
+/*!@ingroup       UDC_HALLayer
+@def			UDC_EPCTL_RRDY
+@brief			Bit position of RRDY field in
+				Endpoint Control Register
+*/
+#define UDC_EPCTL_RRDY				9
+
+/*!@ingroup       UDC_HALLayer
+@def			UDC_EPCTL_CNAK
+@brief			Bit position of CNAK field in
+				Endpoint Control Register
+*/
+#define UDC_EPCTL_CNAK				8
+
+/*!@ingroup       UDC_HALLayer
+@def			UDC_EPCTL_SNAK
+@brief			Bit position of SNAK field in
+				Endpoint Control Register
+*/
+#define UDC_EPCTL_SNAK				7
+
+/*!@ingroup       UDC_HALLayer
+@def			UDC_EPCTL_NAK
+@brief			Bit position of NAK field in
+				Endpoint Control Register
+*/
+#define UDC_EPCTL_NAK				6
+
+/*!@ingroup       UDC_HALLayer
+@def			UDC_EPCTL_ET_MASK
+@brief			Mask for ET field in
+				Endpoint Control Register
+*/
+#define UDC_EPCTL_ET_MASK			0x00000030
+
+/*!@ingroup       UDC_HALLayer
+@def			UDC_EPCTL_ET_OFS
+@brief			Starting bit position for ET field in
+				Endpoint Control Register
+*/
+#define UDC_EPCTL_ET_OFS			4
+
+/*!@ingroup       UDC_HALLayer
+@def			UDC_EPCTL_ET_CONTROL
+@brief			Value for ET field in
+				Endpoint Control Register
+*/
+#define UDC_EPCTL_ET_CONTROL			0
+
+/*!@ingroup       UDC_HALLayer
+@def			UDC_EPCTL_ET_ISO
+@brief			Value for ET field in
+				Endpoint Control Register
+*/
+#define UDC_EPCTL_ET_ISO			1
+
+/*!@ingroup       UDC_HALLayer
+@def			UDC_EPCTL_ET_BULK
+@brief			Value for ET field in
+				Endpoint Control Register
+*/
+#define UDC_EPCTL_ET_BULK			2
+
+/*!@ingroup       UDC_HALLayer
+@def			UDC_EPCTL_ET_INTERRUPT
+@brief			Value for ET field in
+				Endpoint Control Register
+*/
+#define UDC_EPCTL_ET_INTERRUPT			3
+
+/*!@ingroup       UDC_HALLayer
+@def			UDC_EPCTL_MRXFLUSH
+@brief			Bit position for MRXFLUSH in
+				Endpoint Control Register
+*/
+#define UDC_EPCTL_MRXFLUSH			12
+
+/*!@ingroup       UDC_HALLayer
+@def			UDC_EPCTL_P
+@brief			Bit position for P in
+				Endpoint Control Register
+*/
+#define UDC_EPCTL_P				3
+
+/*!@ingroup       UDC_HALLayer
+@def			UDC_EPCTL_SN
+@brief			Bit position for SN in
+				Endpoint Control Register
+*/
+#define UDC_EPCTL_SN				2
+
+/*!@ingroup       UDC_HALLayer
+@def			UDC_EPCTL_F
+@brief			Bit position for F in
+				Endpoint Control Register
+*/
+#define UDC_EPCTL_F				1
+
+/*!@ingroup       UDC_HALLayer
+@def			UDC_EPCTL_S
+@brief			Bit position for S in
+				Endpoint Control Register
+*/
+#define UDC_EPCTL_S				0
+
+/* Endpoint Status Registers */
+
+/*!@ingroup       UDC_HALLayer
+@def			UDC_EPSTS_ADDR
+@brief			Address offset for Endpoint Status Register
+*/
+#define UDC_EPSTS_ADDR				0x4
+
+/*!@ingroup       UDC_HALLayer
+@def		    UDC_EPSTS_XFERDONE
+@brief			Bit position for XFERDONE in
+				Endpoint Status Register
+*/
+#define UDC_EPSTS_XFERDONE			27
+
+/*!@ingroup       UDC_HALLayer
+@def		    UDC_EPSTS_RSS
+@brief			Bit position for RSS in
+				Endpoint Status Register
+*/
+#define UDC_EPSTS_RSS				26
+
+/*!@ingroup       UDC_HALLayer
+@def		    UDC_EPSTS_RCS
+@brief			Bit position for RCS in
+				Endpoint Status Register
+*/
+#define UDC_EPSTS_RCS				25
+
+/*!@ingroup       UDC_HALLayer
+@def		    UDC_EPSTS_TXEMPTY
+@brief			Bit position for TXEMPTY in
+				Endpoint Status Register
+*/
+#define UDC_EPSTS_TXEMPTY			24
+
+/*!@ingroup       UDC_HALLayer
+@def		    UDC_EPSTS_ISOINDONE
+@brief			Bit position for ISOINDONE in
+				Endpoint Status Register
+*/
+#define UDC_EPSTS_ISOINDONE			23
+
+/*!@ingroup       UDC_HALLayer
+@def		    UDC_EPSTS_RX_PKT_SIZE_MASK
+@brief			Mask for RX_PKT_SIZE field in
+				Endpoint Status Register
+*/
+#define UDC_EPSTS_RX_PKT_SIZE_MASK		0x007ff800
+
+/*!@ingroup       UDC_HALLayer
+@def		    UDC_EPSTS_RX_PKT_SIZE_OFS
+@brief			Starting offset for RX_PKT_SIZE field in
+				Endpoint Status Register
+*/
+#define UDC_EPSTS_RX_PKT_SIZE_OFS		11
+
+/*!@ingroup       UDC_HALLayer
+@def		    UDC_EPSTS_TDC
+@brief			Bit position for TDC field in
+				Endpoint Status Register
+*/
+#define UDC_EPSTS_TDC				10
+
+/*!@ingroup       UDC_HALLayer
+@def		    UDC_EPSTS_HE
+@brief			Bit position for HE field in
+				Endpoint Status Register
+*/
+#define UDC_EPSTS_HE				9
+
+/*!@ingroup       UDC_HALLayer
+@def		    UDC_EPSTS_MRXFIFO_EMP
+@brief			Bit position for MRXFIFO EMPTY field in
+				Endpoint Status Register
+*/
+#define UDC_EPSTS_MRXFIFO_EMP			8
+
+/*!@ingroup       UDC_HALLayer
+@def		    UDC_EPSTS_BNA
+@brief			Bit position for BNA field in
+				Endpoint Status Register
+*/
+#define UDC_EPSTS_BNA				7
+
+/*!@ingroup       UDC_HALLayer
+@def		    UDC_EPSTS_IN
+@brief			Bit position for IN field in
+				Endpoint Status Register
+*/
+#define UDC_EPSTS_IN				6
+
+/*!@ingroup       UDC_HALLayer
+@def		    UDC_EPSTS_OUT_MASK
+@brief			Mask for OUT field in
+				Endpoint Status Register
+*/
+#define UDC_EPSTS_OUT_MASK			0x00000030
+
+/*!@ingroup       UDC_HALLayer
+@def		    UDC_EPSTS_OUT_OFS
+@brief			Starting bit position for OUT field in
+				Endpoint Status Register
+*/
+#define UDC_EPSTS_OUT_OFS			4
+
+/*!@ingroup       UDC_HALLayer
+@def		    UDC_EPSTS_OUT_DATA
+@brief			Value for OUT field in
+				Endpoint Status Register
+*/
+#define UDC_EPSTS_OUT_DATA			1
+
+/*!@ingroup       UDC_HALLayer
+@def		    UDC_EPSTS_OUT_DATA_CLEAR
+@brief			Clear OUT field in
+				Endpoint Status Register
+*/
+#define UDC_EPSTS_OUT_DATA_CLEAR		0x10
+
+/*!@ingroup       UDC_HALLayer
+@def		    UDC_EPSTS_OUT_DATA_CLEAR
+@brief			Clear OUT field in
+				Endpoint Status Register
+*/
+#define UDC_EPSTS_OUT_SETUP			2
+
+/*!@ingroup       UDC_HALLayer
+@def		    UDC_EPSTS_OUT_DATA_SETUP_CLEAR
+*/
+#define UDC_EPSTS_OUT_SETUP_CLEAR		0x20
+
+/*!@ingroup       UDC_HALLayer
+@def		    UDC_EPSTS_OUT_CLEAR
+*/
+#define UDC_EPSTS_OUT_CLEAR			0x30
+
+/* Endpoint Buffer Size IN/ Receive Packet Frame Number OUT Registers */
+/*!@ingroup       UDC_HALLayer
+@def			UDC_EPIN_BUFF_SIZE_ADDR
+@brief			Address offset for Endpoint Buffer Size IN register
+*/
+#define UDC_EPIN_BUFF_SIZE_ADDR			0x8
+
+/*!@ingroup       UDC_HALLayer
+@def		UDC_EPOUT_FRAME_NUMBER_ADDR
+@brief		Address offset for Receive Packet Frame Number OUT Register
+*/
+#define UDC_EPOUT_FRAME_NUMBER_ADDR		0x8
+
+/*!@ingroup       UDC_HALLayer
+@def			UDC_EPIN_BUFF_SIZE_MASK
+@brief			Mask for EPIN buffer size field in
+				Endpoint Buffer Size IN register
+*/
+#define UDC_EPIN_BUFF_SIZE_MASK			0x0000ffff
+
+/*!@ingroup       UDC_HALLayer
+@def			UDC_EPIN_BUFF_SIZE_OFS
+@brief			Starting bit position for EPIN buffer size field in
+				Endpoint Buffer Size IN register
+*/
+#define UDC_EPIN_BUFF_SIZE_OFS			0
+/* EP0in txfifo = 256 bytes*/
+/*!@ingroup       UDC_HALLayer
+@def			UDC_EP0IN_BUFF_SIZE
+@brief			EPIN0 Buffer Size
+*/
+#define UDC_EP0IN_BUFF_SIZE			64
+
+/* EP0in fullspeed txfifo = 128 bytes*/
+/*!@ingroup       UDC_HALLayer
+@def			UDC_FS_EPIN0_BUFF_SIZE
+@brief			EPIN0 Buffer Size
+*/
+#define UDC_FS_EPIN0_BUFF_SIZE			32
+
+/* fifo size mult = fifo size / max packet */
+/*!@ingroup       UDC_HALLayer
+@def			UDC_EPIN0_BUFF_SIZE_MULT
+*/
+#define UDC_EPIN_BUFF_SIZE_MULT			2
+
+/* EPin data fifo size = 2048 bytes DOUBLE BUFFERING */
+/*!@ingroup       UDC_HALLayer
+@def			UDC_EPIN_BUFF_SIZE
+@brief			Buffer size
+*/
+#define UDC_EPIN_BUFF_SIZE			512
+/* EPin small INT data fifo size = 128 bytes */
+/*!@ingroup       UDC_HALLayer
+@def			UDC_EPIN_SMALLINT_BUFF_SIZE
+@brief			Buffer size
+*/
+#define UDC_EPIN_SMALLINT_BUFF_SIZE		32
+
+/* EPin fullspeed data fifo size = 128 bytes DOUBLE BUFFERING */
+/*!@ingroup       UDC_HALLayer
+@def			UDC_FS_EPIN_BUFF_SIZE
+@brief			Buffer size
+*/
+#define UDC_FS_EPIN_BUFF_SIZE			32
+
+/*!@ingroup       UDC_HALLayer
+@def			UDC_EPOUT_FRAME_NUMBER_MASK
+@brief			Mask for frame number
+*/
+#define UDC_EPOUT_FRAME_NUMBER_MASK		0x0000ffff
+
+/*!@ingroup       UDC_HALLayer
+@def			UDC_EPOUT_FRAME_NUMBER_OFS
+@brief			Starting bit position for frame number
+*/
+#define UDC_EPOUT_FRAME_NUMBER_OFS		0
+
+/* Endpoint Buffer Size OUT/Max Packet Size Registers -----------------------*/
+
+/*!@ingroup       UDC_HALLayer
+@def			UDC_EPOUT_BUFF_SIZE_ADDR
+@brief			Address offset for Endpoint Buffer Size OUT Register
+*/
+#define UDC_EPOUT_BUFF_SIZE_ADDR		0x0c
+
+/*!@ingroup       UDC_HALLayer
+@def			UDC_EP_MAX_PKT_SIZE_ADDR
+@brief			Address offset for Max Packet Size Register
+*/
+#define UDC_EP_MAX_PKT_SIZE_ADDR		0x0c
+
+/*!@ingroup       UDC_HALLayer
+@def			UDC_EPOUT_BUFF_SIZE_MASK
+@brief			Mask for EPOUT buffer size field
+*/
+#define UDC_EPOUT_BUFF_SIZE_MASK		0xffff0000
+
+/*!@ingroup       UDC_HALLayer
+@def			UDC_EPOUT_BUFF_SIZE_OFS
+@brief			Starting bit position for EPOUT buffer size field
+*/
+#define UDC_EPOUT_BUFF_SIZE_OFS			16
+
+/* EP0out rxfifo = 256 bytes*/
+/*!@ingroup       UDC_HALLayer
+@def			UDC_EP0OUT_BUFF_SIZE
+@brief			EP0 OUT Buffer Size
+*/
+#define UDC_EP0OUT_BUFF_SIZE			64
+
+/* EPout data fifo size = 2048 bytes DOUBLE BUFFERING */
+/*!@ingroup       UDC_HALLayer
+@def			UDC_EPOUT_BUFF_SIZE
+@brief			Buffer size
+*/
+#define UDC_EPOUT_BUFF_SIZE			512
+
+/* EPout fullspeed data fifo size = 128 bytes DOUBLE BUFFERING */
+/*!@ingroup       UDC_HALLayer
+@def			UDC_FS_EPOUT_BUFF_SIZE
+@brief			Buffer size
+*/
+#define UDC_FS_EPOUT_BUFF_SIZE			32
+
+/*!@ingroup       UDC_HALLayer
+@def			UDC_EP_MAX_PKT_SIZE_MASK
+@brief			Mask for EP maximum packet size
+*/
+#define UDC_EP_MAX_PKT_SIZE_MASK		0x0000ffff
+
+/*!@ingroup       UDC_HALLayer
+@def			UDC_EP_MAX_PKT_SIZE_OFS
+@brief			Starting bit position for EP maximum packet size
+*/
+#define UDC_EP_MAX_PKT_SIZE_OFS			0
+/* EP0in max packet size = 64 bytes */
+/*!@ingroup       UDC_HALLayer
+@def			UDC_EP0IN_MAX_PKT_SIZE
+@brief			EP0 IN maximum packet size
+*/
+#define UDC_EP0IN_MAX_PKT_SIZE			64
+/* EP0out max packet size = 64 bytes */
+/*!@ingroup       UDC_HALLayer
+@def			UDC_EP0OUT_MAX_PKT_SIZE
+@brief			EP0 OUT maximum packet size
+*/
+#define UDC_EP0OUT_MAX_PKT_SIZE			64
+
+/* Bulk max packet size = 512 bytes */
+/*!@ingroup       UDC_HALLayer
+@def			UDC_BULK_MAX_PKT_SIZE
+@brief			BULK maximum packet size
+*/
+#define UDC_BULK_MAX_PKT_SIZE			512
+
+/* EP0in fullspeed max packet size = 64 bytes */
+/*!@ingroup       UDC_HALLayer
+@def			UDC_FS_EP0IN_MAX_PKT_SIZE
+@brief			Full speed EP0 IN maximum packet size
+*/
+#define UDC_FS_EP0IN_MAX_PKT_SIZE		64
+/* EP0out fullspeed max packet size = 64 bytes */
+/*!@ingroup       UDC_HALLayer
+@def			UDC_FS_EP0OUT_MAX_PKT_SIZE
+@brief			Full speed EP0 OUT maximum packet size
+*/
+#define UDC_FS_EP0OUT_MAX_PKT_SIZE		64
+
+/* Offset to next EP registers */
+/*!@ingroup       UDC_HALLayer
+@def			UDC_EP_REG_OFS
+@brief			Offset to next EP registers
+*/
+#define UDC_EP_REG_OFS	0x20
+
+/* UDC_Global CSR's */
+/*!@ingroup       UDC_HALLayer
+@def			UDC_CSR_ADD
+@brief			Offset of CSR register
+*/
+#define UDC_CSR_ADDR				0x500
+
+/* EP NE bits */
+/* EP number */
+/*!@ingroup       UDC_HALLayer
+@def			UDC_CSR_NE_NUM_MASK
+*/
+#define UDC_CSR_NE_NUM_MASK			0x0000000f
+
+/*!@ingroup       UDC_HALLayer
+@def			UDC_CSR_NE_NUM_OFS
+*/
+#define UDC_CSR_NE_NUM_OFS			0
+
+/* EP direction */
+/*!@ingroup       UDC_HALLayer
+@def			UDC_CSR_NE_DIR_MASK
+@brief			EP direction mask
+*/
+#define UDC_CSR_NE_DIR_MASK			0x00000010
+
+/*!@ingroup       UDC_HALLayer
+@def			UDC_CSR_NE_DIR_OFS
+@brief			Offset for EP direction bits
+*/
+#define UDC_CSR_NE_DIR_OFS			4
+
+/* EP type */
+/*!@ingroup       UDC_HALLayer
+@def			UDC_CSR_NE_TYPE_MASK
+@brief			Mask for EP type
+*/
+#define UDC_CSR_NE_TYPE_MASK			0x00000060
+
+/*!@ingroup       UDC_HALLayer
+@def			UDC_CSR_NE_TYPE_OFS
+@brief			Offset for EP type bits
+*/
+#define UDC_CSR_NE_TYPE_OFS			5
+
+/* EP config number */
+
+/*!@ingroup       UDC_HALLayer
+@def			UDC_CSR_NE_CFG_MASK
+@brief			Mask for EP config number
+*/
+#define UDC_CSR_NE_CFG_MASK			0x00000780
+
+/*!@ingroup       UDC_HALLayer
+@def			UDC_CSR_NE_CFG_OFS
+@brief			Offset for EP config number bits
+*/
+#define UDC_CSR_NE_CFG_OFS			7
+
+/* EP interface number */
+/*!@ingroup       UDC_HALLayer
+@def			UDC_CSR_NE_INTF_MASK
+@brief			Mask for EP interface number bits
+*/
+#define UDC_CSR_NE_INTF_MASK			0x00007800
+
+/*!@ingroup       UDC_HALLayer
+@def			UDC_CSR_NE_INTF_OFS
+@brief			Offset for EP interface number bits
+*/
+#define UDC_CSR_NE_INTF_OFS			11
+
+/* EP alt setting */
+/*!@ingroup       UDC_HALLayer
+@def			UDC_CSR_NE_ALT_MASK
+@brief			Mask for EP alt setting
+*/
+#define UDC_CSR_NE_ALT_MASK			0x00078000
+
+/*!@ingroup       UDC_HALLayer
+@def			UDC_CSR_NE_ALT_OFS
+@brief			Offset for EP alt bits
+*/
+#define UDC_CSR_NE_ALT_OFS			15
+
+/* max pkt */
+/*!@ingroup       UDC_HALLayer
+@def			UDC_CSR_NE_MAX_PKT_MASK
+@brief			Mask for max packet bits
+*/
+#define UDC_CSR_NE_MAX_PKT_MASK			0x3ff80000
+
+/*!@ingroup       UDC_HALLayer
+@def			UDC_CSR_NE_MAX_PKT_OFS
+@brief			Offset for max packet bits
+*/
+#define UDC_CSR_NE_MAX_PKT_OFS			19
+
+/*!@ingroup       UDC_HALLayer
+@def			IOH_UDC_EP_NUM
+@brief			Total number of EPs
+*/
+#define IOH_UDC_EP_NUM		32	/* 16 IN and 16 OUT	*/
+/* EP number of EP's really used */
+
+/*!@ingroup       UDC_HALLayer
+@def			IOH_UDC_USED_EP_NUM
+@brief			number of EPs used
+*/
+#define IOH_UDC_USED_EP_NUM	4
+
+/*!@ingroup       UDC_HALLayer
+@def			UDC_EP0IN_IDX
+@brief			Control IN ep index
+*/
+#define UDC_EP0IN_IDX	0
+
+/*!@ingroup       UDC_HALLayer
+@def			UDC_EP0UT_IDX
+@brief			Control OUT ep index
+*/
+#define UDC_EP0OUT_IDX	1
+
+/*!@ingroup       UDC_HALLayer
+@def			IOH_UDC_EP0
+@brief			number of EP0
+*/
+#define IOH_UDC_EP0		0
+
+/*!@ingroup       UDC_HALLayer
+@def			IOH_UDC_EP1
+@brief			number of EP1
+*/
+#define IOH_UDC_EP1		1
+
+/*!@ingroup       UDC_HALLayer
+@def			IOH_UDC_EP2
+@brief			number of EP2
+*/
+#define IOH_UDC_EP2		2
+
+/*!@ingroup       UDC_HALLayer
+@def			IOH_UDC_EP3
+@brief			number of EP3
+*/
+#define IOH_UDC_EP3		3
+
+/* Rx fifo address and size = 2k -------------------------------------------*/
+/*!@ingroup       UDC_HALLayer
+@def			UDC_RXFIFO_ADDR
+@brief			Address offset of Rx FIFO
+*/
+#define UDC_RXFIFO_ADDR				0x800
+
+/*!@ingroup       UDC_HALLayer
+@def			UDC_RXFIFO_SIZE
+@brief			Rx FIFO size
+*/
+#define UDC_RXFIFO_SIZE				0x800
+
+/* Tx fifo address and size = 4k -----------------------------------------*/
+
+/*!@ingroup       UDC_HALLayer
+@def			UDC_TXFIFO_ADDR
+@brief			Address offset of Tx FIFO
+*/
+#define UDC_TXFIFO_ADDR				0x1000
+
+/*!@ingroup       UDC_HALLayer
+@def			UDC_TXFIFO_SIZE
+@brief			Tx FIFO size
+*/
+#define UDC_TXFIFO_SIZE				0x1000
+
+/* general constants */
+
+/*!@ingroup       UDC_HALLayer
+@def			UDC_DWORD_BYTES
+@brief			Bytes in DWORD
+*/
+#define UDC_DWORD_BYTES				4
+
+/*!@ingroup       UDC_HALLayer
+@def			UDC_BITS_PER_BYTE
+@brief			Bits in a byte
+*/
+#define UDC_BITS_PER_BYTE			8
+
+/*!@ingroup       UDC_HALLayer
+@def			UDC_BITS_PER_BYTE_SHIFT
+*/
+#define UDC_BITS_PER_BYTE_SHIFT		3
+
+/*!@ingroup       UDC_HALLayer
+@def			UDC_BYTE_MASK
+@brief			Mask to get lower byte
+*/
+#define UDC_BYTE_MASK				0xff
+
+/* Endpoint configuration regsisters */
+/*!@ingroup       UDC_HALLayer
+@struct			ioh_udc_csrs_
+@brief			Structure to Endpoint configuration registers
+*/
+struct ioh_udc_csrs {
+	u32  ne[IOH_UDC_USED_EP_NUM * 2];
+};
+
+/* UDC_Global registers */
+/*!@ingroup		UDC_Global
+@struct			ioh_udc_regs_
+@brief			Structure holding values of configuration registers
+*/
+struct ioh_udc_regs {
+	u32  devcfg;       	/**< Device configuration register  */
+	u32  devctl;        /**< Device control register  */
+	u32  devsts;        /**< Device status register  */
+	u32  devirqsts;     /**< Device irq status register  */
+	u32  devirqmsk;     /**< Device irq mask register  */
+	u32  epirqsts;      /**< Endpoint irq status register  */
+	u32  epirqmsk;      /**< Endpoint irq mask register  */
+	u32  devlpm;        /**< LPM control/status register  */
+};
+
+/*!@ingroup		UDC_Global
+@struct			ioh_udc_ep_regs__
+@brief			Structure holding values of ep configuration registers
+*/
+struct ioh_udc_ep_regs {
+	u32  epctl;        		/**< Endpoint control register  */
+	u32  epsts;       		/**< Endpoint status register  */
+	u32  bufin_framenum; 	/**< buffer size in / frame number out  */
+	u32  bufout_maxpkt;  	/**< buffer size out / maxpkt in  */
+	u32  subptr;     		/**< setup buffer pointer  */
+	u32  desptr;     		/**< Data descriptor pointer  */
+	u32  confirm;    /**< Write/Read confirmation  for slave mode only */
+};
+
+#define DMA_ADDR_INVALID	(~(dma_addr_t)0)
+
+/*!@ingroup		UDC_Global
+@struct			ioh_udc_data_dma_desc_
+@brief			Structure to hold DMA descriptor information for data
+*/
+struct ioh_udc_data_dma_desc {
+	u32  status;       /**< status quadlet */
+	u32  reserved;
+	u32  dataptr;      /**< buffer descriptor  */
+	u32  next;         /**< next descriptor  */
+};
+
+/*!@ingroup		UDC_Global
+@struct			struct ioh_udc_stp_dma_desc_
+@brief		Structure to hold DMA descriptor information for control data
+*/
+struct ioh_udc_stp_dma_desc {
+	u32  status;
+	u32  reserved;
+	u32  data12;         /**< first setup word  */
+	u32  data34;         /**< second setup word  */
+};
+
+/*!@ingroup		UDC_Global
+@struct			ioh_udc_cfg_data
+@brief	Structure to hold current configuration and interface information
+*/
+struct ioh_udc_cfg_data {
+	u16		cur_cfg; /**< current configuration in use */
+	u16		cur_intf; /**< current interface in use */
+	u16		cur_alt; /**< current alt interface in use */
+};
+
+/* DMA status definitions */
+#define IOH_UDC_BUFF_STS 	0xC0000000	/**< Buffer status mask */
+#define IOH_UDC_BS_HST_RDY	0x00000000	/**< 2'b00 : Host Ready */
+#define IOH_UDC_BS_DMA_BSY	0x40000000 	/**< 2'b01 : DMA Busy */
+#define IOH_UDC_BS_DMA_DONE	0x80000000	/**< 2'b10 : DMA Done */
+#define IOH_UDC_BS_HST_BSY	0xC0000000	/**< 2'b11 : HOST busy */
+
+#define IOH_UDC_RXTX_STS	0x30000000	/**<  Rx/Tx Status Mask */
+#define IOH_UDC_RTS_SUCC	0x00000000	/**< Success */
+#define IOH_UDC_RTS_DESERR	0x10000000	/**< Descriptor Error */
+#define IOH_UDC_RTS_BUFERR	0x30000000	/**< Buffer Error */
+
+#define IOH_UDC_DMA_LAST	0x08000000 /**< Last Descriptor Indication */
+#define IOH_UDC_RXTX_BYTES	0x0000ffff /**< Number of Rx/Tx Bytes Mask */
+
+/*!@ingroup		UDC_HALLayerAPI
+@fn				ioh_udc_print_regs(u32 base)
+@brief			Prints UDC device registers and endpoint irq registers
+*/
+extern void ioh_udc_print_regs(u32 base);
+
+/*!@ingroup       UDC_HALLayerAPI
+@fn				ioh_udc_init(struct ioh_udc_regs *dev)
+@brief			Initializes the UDC hardware
+*/
+extern void ioh_udc_init(struct ioh_udc_regs *dev);
+
+/*!@ingroup       UDC_HALLayerAPI
+@fn		ioh_udc_exit(struct ioh_udc_regs *dev)
+@brief	This API will do any cleanup required for the USB device hardware.
+*/
+extern void ioh_udc_exit(struct ioh_udc_regs *dev);
+
+/*!@ingroup       UDC_HALLayerAPI
+@fn		ioh_udc_write_csr(unsigned long val, unsigned long addr)
+@brief			Write to CSR register
+*/
+extern void ioh_udc_write_csr(unsigned long val, unsigned long addr);
+
+/*!@ingroup       UDC_HALLayerAPI
+@fn				ioh_udc_read_csr(unsigned long addr)
+@brief			Read the content of CSR
+*/
+extern u32 ioh_udc_read_csr(unsigned long addr);
+
+/*!@ingroup       UDC_HALLayerAPI
+@fn	ioh_udc_ep_enable(struct ioh_udc_ep_regs __iomem *regs,
+	struct ioh_udc_cfg_data *cfg, struct usb_endpoint_descriptor *desc);
+@brief			Enables endpoint
+*/
+extern void ioh_udc_ep_enable(struct ioh_udc_ep_regs __iomem *regs,
+				 struct ioh_udc_cfg_data *cfg,
+				const struct usb_endpoint_descriptor *desc);
+
+/*!@ingroup       UDC_HALLayerAPI
+@fn			ioh_udc_ep_disable(struct ioh_udc_ep_regs __iomem *regs)
+@brief			Disables endpoint
+*/
+extern void ioh_udc_ep_disable(struct ioh_udc_ep_regs __iomem *regs);
+
+/*!@ingroup       UDC_HALLayerAPI
+@fn			ioh_udc_get_frame(struct ioh_udc_regs __iomem *dev)
+@brief			This API will return the current frame number
+*/
+extern int ioh_udc_get_frame(struct ioh_udc_regs __iomem *dev);
+
+/*!@ingroup       UDC_HALLayerAPI
+@fn			ioh_udc_set_dma(struct ioh_udc_regs *dev, int dir)
+@brief			Enables Tx/Rx DMA
+*/
+extern void ioh_udc_set_dma(struct ioh_udc_regs *dev, int dir);
+
+/*!@ingroup       UDC_HALLayerAPI
+@fn			ioh_udc_clear_dma(struct ioh_udc_regs *dev, int dir)
+@brief			Disable Tx/Rx DMA
+*/
+extern void ioh_udc_clear_dma(struct ioh_udc_regs *dev, int dir);
+
+/*!@ingroup       UDC_HALLayerAPI
+@fn			ioh_udc_rmt_wakeup(struct ioh_udc_regs __iomem *dev)
+@brief			Initiates a remote wakeup
+*/
+extern void ioh_udc_rmt_wakeup(struct ioh_udc_regs __iomem *dev);
+
+/*!@ingroup       UDC_HALLayerAPI
+@fn		ioh_udc_clear_selfpowered (struct ioh_udc_regs __iomem *dev)
+@brief	This API will clear the self powered feature of the device
+*/
+extern void ioh_udc_clear_selfpowered(struct ioh_udc_regs __iomem *dev);
+
+/*!@ingroup       UDC_HALLayerAPI
+@fn		ioh_udc_set_selfpowered (struct ioh_udc_regs __iomem *dev)
+@brief		This API will set the self powered feature of the device
+*/
+extern void ioh_udc_set_selfpowered(struct ioh_udc_regs __iomem *dev);
+
+/*!@ingroup       UDC_HALLayerAPI
+@fn		ioh_udc_set_disconnect (struct ioh_udc_regs __iomem *dev)
+@brief		This API will cause the device to enter soft disconnect state
+*/
+extern void ioh_udc_set_disconnect(struct ioh_udc_regs __iomem *dev);
+
+/*!@ingroup       UDC_HALLayerAPI
+@fn		ioh_udc_clear_disconnect (struct ioh_udc_regs __iomem *dev)
+@brief		This API will get the device out of soft disconnect state.
+*/
+extern void ioh_udc_clear_disconnect(struct ioh_udc_regs __iomem *dev);
+
+/*!@ingroup       UDC_HALLayerAPI
+@fn	ioh_udc_vbus_session (struct ioh_udc_regs __iomem *dev, int is_active)
+@brief	This API will be called when VBUS power is made active for the device.
+*/
+extern void ioh_udc_vbus_session(struct ioh_udc_regs __iomem *dev,
+								 int is_active);
+
+/*!@ingroup       UDC_HALLayerAPI
+@fn		ioh_udc_ep_clear_stall(struct ioh_udc_ep_regs __iomem *ep)
+@brief This API will clear the STALL handshake feature of the specified endpoint
+*/
+extern void ioh_udc_ep_clear_stall(struct ioh_udc_ep_regs __iomem *ep);
+
+/*!@ingroup       UDC_HALLayerAPI
+@fn			ioh_udc_ep_set_stall(struct ioh_udc_ep_regs __iomem *ep)
+@brief	This API will set the STALL handshake feature of the specified endpoint.
+*/
+extern void ioh_udc_ep_set_stall(struct ioh_udc_ep_regs __iomem *ep);
+
+/*!@ingroup       UDC_HALLayerAPI
+@fn			ioh_udc_ep_clear_nak(struct ioh_udc_ep_regs __iomem *ep)
+@brief		This API will stop the endpoint from issuing NAK packets.
+*/
+extern void ioh_udc_ep_clear_nak(struct ioh_udc_ep_regs __iomem *ep);
+
+/*!@ingroup       UDC_HALLayerAPI
+@fn			ioh_udc_ep_set_nak(struct ioh_udc_ep_regs __iomem *ep)
+@brief			This API will cause the endpoint to issue NAK packets.
+*/
+extern void ioh_udc_ep_set_nak(struct ioh_udc_ep_regs __iomem *ep);
+
+/*!@ingroup       UDC_HALLayerAPI
+@fn	ioh_udc_ep_fifo_flush(struct ioh_udc_ep_regs __iomem *ep, int dir)
+@brief		This API will flush the FIFO of the specified endpoint.
+*/
+extern void ioh_udc_ep_fifo_flush(struct ioh_udc_ep_regs __iomem *ep, int dir);
+
+/*!@ingroup       UDC_HALLayerAPI
+@fn		ioh_udc_disable_interrupts(struct ioh_udc_regs *dev, u32 mask)
+@brief		This API will disable the specified device interrupts
+*/
+extern void ioh_udc_disable_interrupts(struct ioh_udc_regs *dev, u32 mask);
+
+/*!@ingroup       UDC_HALLayerAPI
+@fn		ioh_udc_enable_interrupts(struct ioh_udc_regs *dev, u32 mask)
+@brief		This API will enable specified device interrupts
+*/
+extern void ioh_udc_enable_interrupts(struct ioh_udc_regs *dev, u32 mask);
+
+/*!@ingroup       UDC_HALLayerAPI
+@fn	ioh_udc_disable_ep_interrupts(struct ioh_udc_regs *dev, u32 mask)
+@brief		This API will disable the interrupts from specific endpoint.
+*/
+extern void ioh_udc_disable_ep_interrupts(struct ioh_udc_regs *dev, u32 mask);
+
+/*!@ingroup       UDC_HALLayerAPI
+@fn		ioh_udc_enable_ep_interrupts(struct ioh_udc_regs *dev, u32 mask)
+@brief		This API will enable the interrupts from specific endpoint.
+*/
+extern void ioh_udc_enable_ep_interrupts(struct ioh_udc_regs *dev, u32 mask);
+
+/*!@ingroup       UDC_HALLayerAPI
+@fn				ioh_udc_set_csr_done(struct ioh_udc_regs *dev)
+@brief			This API will inform the device the completion of
+				USB device programming.
+*/
+extern void ioh_udc_set_csr_done(struct ioh_udc_regs *dev);
+
+/*!@ingroup       UDC_HALLayerAPI
+@fn		ioh_udc_set_burst_length(struct ioh_udc_regs *dev, u8 len)
+@brief			This API will set the length of 32bit words on a
+				single burst of DMA .
+*/
+extern void ioh_udc_set_burst_length(struct ioh_udc_regs *dev, u8 len);
+
+/*!@ingroup       UDC_HALLayerAPI
+@fn		ioh_udc_set_threshold_length(struct ioh_udc_regs *dev, u8 len)
+@brief			This API will set the length of 32bit words after
+				which DMA can start
+*/
+extern void ioh_udc_set_threshold_length(struct ioh_udc_regs *dev, u8 len);
+
+/*!@ingroup       UDC_HALLayerAPI
+@fn			ioh_udc_get_speed (struct ioh_udc_regs __iomem *dev
+@brief			This API will return the current speed
+*/
+extern int ioh_udc_get_speed(struct ioh_udc_regs __iomem *dev);
+
+/*!@ingroup       UDC_HALLayerAPI
+@fn	ioh_udc_ep_set_trfr_type(struct ioh_udc_ep_regs __iomem *ep, u8 type)
+@brief	This API will set the endpoint type in the endpoint control register.
+*/
+extern void ioh_udc_ep_set_trfr_type(struct ioh_udc_ep_regs __iomem *ep,
+								 u8 type);
+
+/*!@ingroup       UDC_HALLayerAPI
+@fn	ioh_udc_ep_set_maxpkt(struct ioh_udc_ep_regs __iomem *ep, u32 pkt_size)
+@brief		This API will set the maximum packet size for the endpoint.
+*/
+extern void ioh_udc_ep_set_maxpkt(struct ioh_udc_ep_regs __iomem *ep,
+								 u32 pkt_size);
+
+/*!@ingroup       UDC_HALLayerAPI
+@fn ioh_udc_ep_set_bufsz(struct ioh_udc_ep_regs __iomem *ep,
+						 u32 buf_size, u32 ep_in)
+@brief			Sets buffer size for the endpoint
+*/
+extern void ioh_udc_ep_set_bufsz(struct ioh_udc_ep_regs __iomem *ep,
+						 u32 buf_size, u32 ep_in);
+
+/*!@ingroup       UDC_HALLayerAPI
+@fn		ioh_udc_ep_set_ddptr(struct ioh_udc_ep_regs __iomem *ep,
+								 u32 addr)
+@brief		This API will set the data descriptor pointer for the endpoint.
+*/
+extern void ioh_udc_ep_set_ddptr(struct ioh_udc_ep_regs __iomem *ep, u32 addr);
+
+/*!@ingroup       UDC_HALLayerAPI
+@fn	ioh_udc_ep_set_subptr(struct ioh_udc_ep_regs __iomem *ep, u32 addr)
+@brief			Set the Setup buffer pointer for the endpoint
+*/
+extern void ioh_udc_ep_set_subptr(struct ioh_udc_ep_regs __iomem *ep, u32 addr);
+
+/*!@ingroup       UDC_HALLayerAPI
+@fn		ioh_udc_read_device_interrupts(struct ioh_udc_regs __iomem *dev)
+@brief			Returns the interrupt status
+*/
+extern u32 ioh_udc_read_device_interrupts(struct ioh_udc_regs __iomem *dev);
+
+/*!@ingroup       UDC_HALLayerAPI
+@fn ioh_udc_write_device_interrupts(struct ioh_udc_regs __iomem *dev, u32 val);
+@brief			Writes Interrupts
+*/
+extern void ioh_udc_write_device_interrupts(struct ioh_udc_regs __iomem *dev,
+								 u32 val);
+
+/*!@ingroup       UDC_HALLayerAPI
+@fn		ioh_udc_read_ep_interrupts(struct ioh_udc_regs __iomem *ep)
+@brief			Reads endpoint interrupts
+*/
+extern u32 ioh_udc_read_ep_interrupts(struct ioh_udc_regs __iomem *ep);
+
+/*!@ingroup       UDC_HALLayerAPI
+@fn	ioh_udc_write_ep_interrupts(struct ioh_udc_regs __iomem *ep, u32 val)
+@brief	Writes endpoint interrupts
+*/
+extern void ioh_udc_write_ep_interrupts(struct ioh_udc_regs __iomem *ep,
+								 u32 val);
+
+/*!@ingroup       UDC_HALLayerAPI
+@fn		ioh_udc_read_device_status(struct ioh_udc_regs __iomem *dev)
+@brief	Reads device status register
+*/
+extern u32 ioh_udc_read_device_status(struct ioh_udc_regs __iomem *dev);
+
+/*!@ingroup       UDC_HALLayerAPI
+@fn		ioh_udc_read_ep_control(struct ioh_udc_ep_regs __iomem *dev)
+@brief		Reads the endpoint status registers.
+*/
+extern u32 ioh_udc_read_ep_control(struct ioh_udc_ep_regs __iomem *dev);
+
+/*!@ingroup       UDC_HALLayerAPI
+@fn		ioh_udc_clear_ep_control(struct ioh_udc_ep_regs __iomem *dev)
+@brief		Clear the endpoint status registers.
+*/
+extern void ioh_udc_clear_ep_control(struct ioh_udc_ep_regs __iomem *ep);
+
+/*!@ingroup       UDC_HALLayerAPI
+@fn		ioh_udc_read_ep_status(struct ioh_udc_ep_regs __iomem *dev)
+@brief		Reads the endpoint status registers.
+*/
+extern u32 ioh_udc_read_ep_status(struct ioh_udc_ep_regs __iomem *dev);
+
+/*!@ingroup       UDC_HALLayerAPI
+@fn			ioh_udc_ep_set_pd(struct ioh_udc_ep_regs __iomem *ep)
+@brief			Set the poll demand bit for the endpoint
+*/
+extern void ioh_udc_ep_set_pd(struct ioh_udc_ep_regs __iomem *ep);
+
+/*!@ingroup       UDC_HALLayerAPI
+@fn			ioh_udc_ep_set_rrdy(struct ioh_udc_ep_regs __iomem *ep)
+@brief			Set the receive ready bit for the endpoint
+*/
+extern void ioh_udc_ep_set_rrdy(struct ioh_udc_ep_regs __iomem *ep);
+
+/*!@ingroup       UDC_HALLayerAPI
+@fn		ioh_udc_ep_clear_rrdy(struct ioh_udc_ep_regs __iomem *ep)
+@brief		Clear the receive ready bit for the endpoint
+*/
+extern void ioh_udc_ep_clear_rrdy(struct ioh_udc_ep_regs __iomem *ep);
+
+/*!@ingroup       UDC_HALLayerAPI
+@fn	ioh_udc_clear_ep_status(struct ioh_udc_ep_regs __iomem *ep, u32 stat)
+@brief			Clears endpoint status register
+*/
+extern void ioh_udc_clear_ep_status(struct ioh_udc_ep_regs __iomem *ep,
+								 u32 stat);
+extern int speed_fs;
+#endif	/* IOH_UDC_HAL_H_ */
--- /dev/null
+++ b/drivers/usb/gadget/pch_udc_intr.c
@@ -0,0 +1,396 @@
+ /*!
+ * @file ioh_udc_intr.c
+ * @brief
+ * The IOH UDC is a USB High speed DMA capable USB device controller.
+ * It provides 4 IN and 4 OUT endpoints (control, bulk isochronous or
+ *							 interrupt type).
+ *
+ * The IOH USB device controller driver provides required interface
+ * to the USB gadget framework for accessing the IOH USB device hardware.
+ *
+ * @version 0.96
+ *
+ * @section
+ * 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; version 2 of the License.
+ *
+ * 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.
+ */
+
+ /*
+ * History:
+ * Copyright (C) 2009 OKI SEMICONDUCTOR Co., LTD.
+ * All rights reserved.
+ *
+ * created:
+ *   OKI SEMICONDUCTOR 2/26/2010
+ * modified:
+ *
+ */
+
+#include <linux/types.h>
+#include <linux/irq.h>
+#include <linux/device.h>
+#include <linux/usb/ch9.h>
+#include <linux/usb/gadget.h>
+/*#include <asm/io.h>*/
+#include <linux/io.h>
+#include "pch_common.h"
+#include "pch_debug.h"
+
+#include "pch_udc_hal.h"
+#include "pch_udc.h"
+
+/* received setup data */
+static union ioh_udc_setup_data setup_data;
+
+/*! @ingroup UDC_UtilitiesAPI
+ * @fn		void ioh_udc_svc_ur_interrupt(struct ioh_udc_dev *dev)
+ * @brief	This function handles a USB reset interrupt
+ * @param	dev    [@ref IN]   reference to driver structure
+ * @return	none
+ * @remarks	The following actions are performed:
+ *- Disable Rx/TX DMA using ioh_udc_clear_dma API
+ *- Mask all endpoint interrupts by invoking ioh_udc_disable_ep_interrupts API
+ *- Clear all endpoint interrupts by invoking ioh_udc_write_ep_interrupts API
+ *- Clear all endpoint status register invoking ioh_udc_clear_ep_status API
+ *- Clear all endpoint control register by invoking ioh_udc_clear_ep_control API
+ *- Clear all endpoint Data descriptor pointer register by invoking
+ *							ioh_udc_ep_set_ddptr API
+ *- Clear all endpoint UDC Endpoint register by invoking ioh_udc_write_csr API
+ *- Clear status flags
+ *- Set the all endpoint's NAK by invoking ioh_udc_ep_set_nak API
+ *- Flush the all endpoint's Tx/RxFIFO by invoking ioh_udc_ep_fifo_flush API
+ *- Disable ep0 to empty request queue by invoking empty_req_queue API
+ *- Invoke the gadget driver's fs disconnect method
+- Empty EP0 IN request queue using empty_req_queue API
+ * @see
+ *			- ioh_udc_clear_dma
+ *			- ioh_udc_disable_ep_interrupts
+ *			- ioh_udc_write_ep_interrupts
+ *			- ioh_udc_clear_ep_status
+ *			- ioh_udc_clear_ep_control
+ *			- ioh_udc_ep_set_ddptr
+ *			- ioh_udc_write_csr
+ *			- ioh_udc_ep_set_nak
+ *			- ioh_udc_ep_fifo_flush
+ *			- empty_req_queue
+ */
+void ioh_udc_svc_ur_interrupt(struct ioh_udc_dev *dev)
+{
+	struct ioh_udc_ep	*ep;
+	int i;
+
+	IOH_DEBUG("USB_RESET Enter");
+
+#ifdef IOH_PRINT_REG
+	ioh_udc_print_regs((u32)dev->virt_addr);
+#endif
+
+	/* Disable DMA */
+	ioh_udc_clear_dma(dev->regs, DMA_DIR_TX);
+	ioh_udc_clear_dma(dev->regs, DMA_DIR_RX);
+	/* Mask all endpoint interrupts */
+	ioh_udc_disable_ep_interrupts(dev->regs, UDC_EPINT_MSK_DISABLE_ALL);
+	/* clear all endpoint interrupts */
+	ioh_udc_write_ep_interrupts(dev->regs, UDC_EPINT_MSK_DISABLE_ALL);
+
+	for (i = 0; i < IOH_UDC_EP_NUM; i++) {
+		ep = &dev->ep[i];
+		ioh_udc_clear_ep_status(ep->regs, 0x1F0006F0);
+		ioh_udc_clear_ep_control(ep->regs);
+		ioh_udc_ep_set_ddptr(ep->regs, 0);
+		ioh_udc_write_csr(0x00, (u32) (&dev->csr->ne[i]));
+	}
+
+	dev->stall = 0;
+	dev->prot_stall = 0;
+	dev->waiting_zlp_ack = 0;
+	dev->set_cfg_not_acked = 0;
+
+	/* disable ep to empty req queue. Skip the control EP's */
+	for (i = 0; i < (IOH_UDC_USED_EP_NUM*2); i++) {
+		ep = &dev->ep[i];
+		/* Set NAK */
+		ioh_udc_ep_set_nak(ep->regs);
+		/* Flush fifo */
+		ioh_udc_ep_fifo_flush(ep->regs , ep->in);
+		/* Complete request queue */
+		empty_req_queue(ep);
+	}
+	if (dev->driver && dev->driver->disconnect)
+		dev->driver->disconnect(&dev->gadget);
+
+	IOH_DEBUG("USB_RESET Exit");
+}
+
+/*! @ingroup UDC_UtilitiesAPI
+ * @fn		ioh_udc_svc_enum_interrupt(struct ioh_udc_dev *dev)
+ * @brief	This function handles a USB speed enumeration done interrupt
+ * @param	dev    [@ref IN]   reference to driver structure
+ * @return	none
+ * @remarks	The following actions are performed:
+ *	- Read the device status using ioh_udc_read_device_status API
+ *	- Set the speed element in device structure.
+ *	- Activate control endpoint using ioh_udc_activate_control_ep API
+ *	- Enable EP0 interrupts using ioh_udc_enable_ep_interrupts API
+ *	- Enable Rx/TX DMA using ioh_udc_set_dma API
+ *	- Set receive ready using ioh_udc_ep_set_rrdy API
+ * @see
+ *			- ioh_udc_read_device_status
+ *			- ioh_udc_activate_control_ep
+ *			- ioh_udc_enable_ep_interrupts
+ *			- ioh_udc_set_dma
+ *			- ioh_udc_ep_set_rrdy
+ */
+void
+ioh_udc_svc_enum_interrupt(struct ioh_udc_dev *dev)
+{
+	u32 dev_stat, dev_speed;
+	u32 speed = USB_SPEED_FULL;
+
+	dev_stat = ioh_udc_read_device_status(dev->regs);
+	dev_speed = (dev_stat & UDC_DEVSTS_ENUM_SPEED_MASK) >>
+						 UDC_DEVSTS_ENUM_SPEED_OFS;
+
+	IOH_DEBUG("ioh_udc_svc_enum_interrupt: dev_speed = 0x%08x", dev_speed);
+
+	if (dev_speed == UDC_DEVSTS_ENUM_SPEED_HIGH) {
+		IOH_DEBUG("HighSpeed");
+		speed = USB_SPEED_HIGH;
+	} else if (dev_speed == UDC_DEVSTS_ENUM_SPEED_FULL) {
+		IOH_DEBUG("FullSpeed");
+		speed = USB_SPEED_FULL;
+	} else if (dev_speed == UDC_DEVSTS_ENUM_SPEED_LOW) {
+		IOH_DEBUG("LowSpeed?");
+		speed = USB_SPEED_LOW;
+	} else {
+		IOH_DEBUG("FullSpeed?");
+	}
+	dev->gadget.speed = speed;
+
+	ioh_udc_activate_control_ep(dev);
+
+	/* enable ep0 interrupts */
+	ioh_udc_enable_ep_interrupts(dev->regs, 1 << UDC_EPINT_IN_EP0 |
+							1 << UDC_EPINT_OUT_EP0);
+
+	/* enable DMA */
+	ioh_udc_set_dma(dev->regs, DMA_DIR_TX);
+	ioh_udc_set_dma(dev->regs, DMA_DIR_RX);
+	ioh_udc_ep_set_rrdy(dev->ep[UDC_EP0OUT_IDX].regs);
+
+#ifdef IOH_PRINT_REG
+	ioh_udc_print_regs((u32)dev->virt_addr);
+#endif
+
+	IOH_DEBUG("EP mask set to %x",
+				 IOH_READ32((u32 *)&(dev->regs->epirqmsk)));
+	IOH_DEBUG("USB_SPEED_ENUM Exit");
+}
+
+/*! @ingroup UDC_UtilitiesAPI
+ * @fn		ioh_udc_svc_intf_interrupt(struct ioh_udc_dev *dev)
+ * @brief	This function handles a set interface interrupt
+ * @param	dev    [@ref IN]   reference to driver structure
+ * @return	none
+ * @remarks	The following actions are performed:
+ *	- Read the device status using ioh_udc_read_device_status API
+ *	- Update current interface in use and current alternate interface
+ *		in use status from the device status information
+ *	- Set device "Set Config Not ACKed" status as TRUE
+ *	- Construct the usb request for gadget driver and inform it
+ *	- Program the Endpoint configuration registers using ioh_udc_read_csr
+ *		and ioh_udc_write_csr APIs
+ *	- Clear stall bit status using ioh_udc_ep_clear_stall
+ *	- Call gadget with setup data received
+ * @see
+ *	- ioh_udc_read_device_status
+ *	- ioh_udc_read_csr
+ *	- ioh_udc_write_csr
+ *	- ioh_udc_ep_clear_stall
+ */
+void
+ioh_udc_svc_intf_interrupt(struct ioh_udc_dev *dev)
+{
+	u32 reg, dev_stat = 0;
+	int i, ret;
+
+	IOH_DEBUG("SI");
+	dev_stat = ioh_udc_read_device_status(dev->regs);
+	dev->cfg_data.cur_intf = (dev_stat & UDC_DEVSTS_INTF_MASK) >>
+							 UDC_DEVSTS_INTF_OFS;
+	dev->cfg_data.cur_alt = (dev_stat & UDC_DEVSTS_ALT_MASK) >>
+							 UDC_DEVSTS_ALT_OFS;
+	IOH_DEBUG("DVSTATUS=%08x, cfg=%d, intf=%d, alt=%d", dev_stat,
+			(dev_stat & UDC_CSR_NE_CFG_MASK) >> UDC_CSR_NE_CFG_OFS,
+			dev->cfg_data.cur_intf, dev->cfg_data.cur_alt);
+
+	dev->set_cfg_not_acked = 1;
+
+	/* Construct the usb request for gadget driver and inform it */
+	memset(&setup_data, 0 , sizeof setup_data);
+	setup_data.request.bRequest = USB_REQ_SET_INTERFACE;
+	setup_data.request.bRequestType = USB_RECIP_INTERFACE;
+	setup_data.request.wValue = cpu_to_le16(dev->cfg_data.cur_alt);
+	setup_data.request.wIndex = cpu_to_le16(dev->cfg_data.cur_intf);
+
+	/* programm the Endpoint Cfg registers */
+	for (i = 0; i < IOH_UDC_USED_EP_NUM * 2; i++) {
+		if (i == 1) { /* Only one end point cfg register */
+			reg = ioh_udc_read_csr((u32) (&dev->csr->ne[i]));
+			reg = (reg & ~UDC_CSR_NE_INTF_MASK) |
+			 (dev->cfg_data.cur_intf << UDC_CSR_NE_INTF_OFS);
+			reg = (reg & ~UDC_CSR_NE_ALT_MASK) |
+			 (dev->cfg_data.cur_alt << UDC_CSR_NE_ALT_OFS);
+			ioh_udc_write_csr(reg, (u32) (&dev->csr->ne[i]));
+		}
+		/* clear stall bits */
+		ioh_udc_ep_clear_stall(dev->ep[i].regs);
+		dev->ep[i].halted = 0;
+	}
+	dev->stall = 0;
+	spin_unlock(&dev->lock);
+	ret = dev->driver->setup(&dev->gadget, &setup_data.request);
+	spin_lock(&dev->lock);
+
+	IOH_DEBUG("EXIT -- SI");
+}
+
+/*! @ingroup UDC_UtilitiesAPI
+ * @fn		ioh_udc_svc_cfg_interrupt(struct ioh_udc_dev *dev)
+ * @brief	This function handles a set configuration interrupt
+ * @param	dev    [@ref IN]   reference to driver structure
+ * @return	none
+ * @remarks	The following actions are performed:
+ *		- Read the device status using ioh_udc_read_device_status API
+ *		- Set the set_cfg_not_acked element in device structure to 1.
+ *		- Update "current configuration in use" status based on the
+ *			device status
+ *		- Construct a usb request for gadget driver
+ *		- Program the Endpoint configuration registers using
+ *			ioh_udc_read_csr and ioh_udc_write_csr APIs
+ *		- Clear stall bit status using ioh_udc_ep_clear_stall
+ *		- Call gadget with setup data received
+ * @see
+ *			- ioh_udc_read_device_status
+ *			- ioh_udc_read_csr
+ *			- ioh_udc_write_csr
+ *			- ioh_udc_ep_clear_stall
+ */
+void
+ioh_udc_svc_cfg_interrupt(struct ioh_udc_dev *dev)
+{
+	int i, ret;
+	u32 reg, dev_stat = 0;
+
+	IOH_DEBUG("SC");
+	dev_stat = ioh_udc_read_device_status(dev->regs);
+	IOH_DEBUG("DVSTATUS=%08x, cfg=%d, intf=%d, alt=%d", dev_stat,
+		(dev_stat & UDC_DEVSTS_CFG_MASK) >> UDC_DEVSTS_CFG_OFS,
+		(dev_stat & UDC_DEVSTS_INTF_MASK) >> UDC_DEVSTS_INTF_OFS,
+		(dev_stat & UDC_DEVSTS_ALT_MASK) >> UDC_DEVSTS_ALT_OFS);
+
+	dev->set_cfg_not_acked = 1;
+
+	dev->cfg_data.cur_cfg = (dev_stat & UDC_DEVSTS_CFG_MASK) >>
+							 UDC_DEVSTS_CFG_OFS;
+	/* make usb request for gadget driver */
+	memset(&setup_data, 0 , sizeof setup_data);
+	setup_data.request.bRequest = USB_REQ_SET_CONFIGURATION;
+	setup_data.request.wValue = cpu_to_le16(dev->cfg_data.cur_cfg);
+
+	/* program the NE registers */
+	for (i = 0; i < IOH_UDC_USED_EP_NUM * 2; i++) {
+		if (i == 1) {
+			reg = ioh_udc_read_csr((u32) (&dev->csr->ne[i]));
+			reg = (reg & ~UDC_CSR_NE_CFG_MASK) |
+				 (dev->cfg_data.cur_cfg << UDC_CSR_NE_CFG_OFS);
+			ioh_udc_write_csr(reg, (u32) (&dev->csr->ne[i]));
+		}
+		/* clear stall bits */
+		ioh_udc_ep_clear_stall(dev->ep[i].regs);
+		dev->ep[i].halted = 0;
+	}
+	dev->stall = 0;
+
+	/* call gadget zero with setup data received */
+	spin_unlock(&dev->lock);
+	ret = dev->driver->setup(&dev->gadget, &setup_data.request);
+	spin_lock(&dev->lock);
+
+	IOH_DEBUG("SC Exit...ret %d", ret);
+}
+
+/*! @ingroup UDC_UtilitiesAPI
+ * @fn		void ioh_udc_dev_isr(struct ioh_udc_dev *dev, u32 dev_intr)
+ * @brief This function services device interrupts by invoking appropriate
+ *								 routines.
+ * @remarks	The following actions are performed:
+ *- If USB reset interrupt status is received, invoke ioh_udc_svc_ur_interrupt
+ *								 function
+ *- If Enumeration done interrupt is received, invoke ioh_udc_svc_enum_interrupt
+ *								 function
+ *- If Set Interface interrupt is received, invoke ioh_udc_svc_intf_interrupt
+ *								 function
+ *- If Set Config interrupt is received, invoke ioh_udc_svc_cfg_interrupt
+ *								 function
+ *- If USB suspend interrupt or ES interrupt is received, invoke the
+ *							 API ioh_udc_rmt_wakeup
+ *- For the following interrupts, log a message in the system log:
+ *		- USB Suspend interrupt
+ *		- SOF token detection interrupt
+ *		- ES interrupt, (IDLE > 3ms on the USB)
+ *		- RWKP interrupt (Remote Wakeup)
+ * @param 	dev 		Reference to the device structure
+ * @param 	dev_intr 	The Device interrupt status.
+ * @see
+ *			- ioh_udc_svc_ur_interrupt
+ *			- ioh_udc_svc_enum_interrupt
+ *			- ioh_udc_svc_intf_interrupt
+ *			- ioh_udc_svc_cfg_interrupt
+ * @return none
+ */
+void ioh_udc_dev_isr(struct ioh_udc_dev *dev, u32 dev_intr)
+{
+	/* USB Reset Interrupt */
+	if (dev_intr & (1 << UDC_DEVINT_UR))
+		ioh_udc_svc_ur_interrupt(dev);
+
+	/* Enumeration Done Interrupt */
+	if (dev_intr & (1 << UDC_DEVINT_ENUM))
+		ioh_udc_svc_enum_interrupt(dev);
+
+	/* Set Interface Interrupt */
+	if (dev_intr & (1 << UDC_DEVINT_SI))
+		ioh_udc_svc_intf_interrupt(dev);
+
+	/* Set Config Interrupt */
+	if (dev_intr & (1 << UDC_DEVINT_SC))
+		ioh_udc_svc_cfg_interrupt(dev);
+
+	/* USB Suspend interrupt */
+	if (dev_intr & (1 << UDC_DEVINT_US))
+		IOH_DEBUG("USB_SUSPEND");
+
+	/* Clear the SOF interrupt, if enabled */
+	if (dev_intr & (1 << UDC_DEVINT_SOF))
+		IOH_DEBUG("SOF");
+
+	/* ES interrupt, IDLE > 3ms on the USB */
+	if (dev_intr & (1 << UDC_DEVINT_ES))
+		IOH_DEBUG("ES");
+
+	/* RWKP interrupt */
+	if (dev_intr & (1 << UDC_DEVINT_RWKP))
+		IOH_DEBUG("RWKP");
+
+}
--- /dev/null
+++ b/drivers/usb/gadget/pch_udc_pci.c
@@ -0,0 +1,549 @@
+/*!
+ * @file ioh_udc_pci.c
+ * @brief
+ * The IOH UDC is a USB High speed DMA capable USB device controller.
+ * It provides 4 IN and 4 OUT endpoints (control, bulk isochronous or
+ *							 interrupt type).
+ *
+ * The IOH USB device controller driver provides required interface
+ * to the USB gadget framework for accessing the IOH USB device hardware.
+ *
+ * @version 0.96
+ *
+ * @section
+ * 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; version 2 of the License.
+ *
+ * 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.
+ */
+
+ /*
+ * History:
+ * Copyright (C) 2009 OKI SEMICONDUCTOR Co., LTD.
+ * All rights reserved.
+ *
+ * created:
+ *   OKI SEMICONDUCTOR 2/26/2010
+ * modified:
+ *
+ */
+
+/*
+ * ioh_udc_pci.c -- IOH UDC high/full speed USB device controller
+ *
+ */
+
+
+/*!@ingroup	UDC_PCILayer
+ * @def		UDC_MOD_DESCRIPTION
+ * @brief	USB device controller driver description.
+ */
+#define UDC_MOD_DESCRIPTION	"OKISEMI IOH UDC - USB Device Controller"
+
+/*!@ingroup	UDC_PCILayer
+ * @def		IOH_UDC_PCI_BAR
+ * @brief	Number of PCI BAR.
+ */
+#define IOH_UDC_PCI_BAR                 1
+
+/* udc specific */
+#include "pch_common.h"
+#include "pch_debug.h"
+#include "pch_udc_pci.h"
+#include "pch_udc.h"
+
+static int ioh_udc_probe(struct pci_dev *pdev, const struct pci_device_id *id);
+static void ioh_udc_remove(struct pci_dev *pdev);
+static void ioh_udc_shutdown(struct pci_dev *pdev);
+static int ioh_udc_suspend(struct pci_dev *pdev, pm_message_t state);
+static int ioh_udc_resume(struct pci_dev *pdev);
+
+/* description */
+static const char mod_desc[] = UDC_MOD_DESCRIPTION;
+static const char name[] = "ioh_udc";
+
+/* pointer to device object */
+/*!@ingroup	UDC_Global
+ * @brief	pointer to device object
+ */
+struct ioh_udc_dev *ioh_udc;
+
+/* Speed selection flag */
+/*!@ingroup	UDC_Global
+ * @brief	Specifies operation speed (High or FULL) - passed as module parameter
+ */
+int speed_fs;
+
+/* module parameters */
+module_param_named(speed_fs, speed_fs, bool, S_IRUGO);
+MODULE_PARM_DESC(speed_fs, "true for Full speed operation");
+
+/* Tears down device */
+/*!@ingroup	UDC_PCILayerAPI
+ * @fn		static void gadget_release(struct device *pdev)
+ * @brief	Free the gadget driver private data
+ * @remarks	The main tasks performed by this method are:
+ *         - Retrieve the pointer to the private data using dev_get_drvdata API.
+ *         - Free the memory allocated for the device structure using kfree API.
+ * @param	pdev    [@ref IN]   reference to struct pci_dev
+ * @return	none
+ */
+static void gadget_release(struct device *pdev)
+{
+	struct ioh_udc_dev *dev = dev_get_drvdata(pdev);
+	kfree(dev);
+}
+
+/*!@ingroup UDC_PCILayerAPI
+ * @fn		static void ioh_udc_remove(struct pci_dev *pdev)
+ * @brief	Implements the remove routine for IOH USB device controller driver
+ * @param	pdev    [@ref IN]   reference to struct pci_dev
+ * @remarks	The main tasks performed by this method are:
+ *			- Deallocate any PCI memory pool created
+ *			- Release IRQ
+ *			- Unmap device memory
+ *			- Disable the PCI device
+ *			- Unregister the device from system
+ * @return	none
+ */
+static void ioh_udc_remove(struct pci_dev *pdev)
+{
+	struct ioh_udc_dev	*dev = pci_get_drvdata(pdev);
+
+	IOH_DEBUG("ioh_udc_remove enter");
+	/* gadget driver must not be registered */
+	if (dev->driver != NULL)
+		IOH_LOG(KERN_ERR, "udc_pci_remove: gadget driver\
+							 still bound!!!");
+
+	/* dma pool cleanup */
+	if (dev->data_requests != NULL)
+		pci_pool_destroy(dev->data_requests);
+
+
+	if (dev->stp_requests != NULL) {
+		/* cleanup DMA desc's for ep0in */
+		if (dev->ep[UDC_EP0OUT_IDX].td_stp != NULL) {
+			pci_pool_free(dev->stp_requests,
+				dev->ep[UDC_EP0OUT_IDX].td_stp,
+				dev->ep[UDC_EP0OUT_IDX].td_stp_phys);
+		}
+		if (dev->ep[UDC_EP0OUT_IDX].td_data != NULL) {
+			pci_pool_free(dev->stp_requests,
+				dev->ep[UDC_EP0OUT_IDX].td_data,
+				dev->ep[UDC_EP0OUT_IDX].td_data_phys);
+		}
+		pci_pool_destroy(dev->stp_requests);
+	}
+
+	ioh_udc_exit(dev->regs);
+
+	if (dev->irq_registered)
+		free_irq(pdev->irq, dev);
+
+	if (dev->virt_addr != NULL)
+		iounmap(dev->virt_addr);
+
+	if (dev->mem_region)
+		release_mem_region(dev->phys_addr, pci_resource_len(pdev,
+							 IOH_UDC_PCI_BAR));
+
+	if (dev->active)
+		pci_disable_device(pdev);
+
+	if (dev->registered)
+		device_unregister(&dev->gadget.dev);
+	else
+		kfree(dev);
+
+	pci_set_drvdata(pdev, NULL);
+}
+
+/*!@ingroup UDC_UtilitiesAPI
+ * @fn		static int init_dma_pools(struct ioh_udc_dev *dev)
+ * @brief	create dma pools during initialization
+ * @param	pdev    [@ref IN]   reference to struct pci_dev
+ * @remarks	The following actions are performed:
+ *- Create a PCI memory pool of DMA descriptors for handling data requests
+ *						 using pci_pool_create API
+ *- If failed to create the pool, return -ENOMEM
+ *- Create a PCI memory pool of DMA descriptors for handling setup requests
+ *						 using pci_pool_create API
+ *- If failed to create the pool, return -ENOMEM
+ *- Allocate one entry from setup pool to be used for setup requests using
+ *							 pci_pool_alloc API
+ *- If failed to allocate, return -ENOMEM
+ *- Allocate one entry from setup pool to be used for control IN requests
+ *						 using pci_pool_alloc API
+ *- If failed to allocate, return -ENOMEM
+ * @return none
+ */
+static int init_dma_pools(struct ioh_udc_dev *dev)
+{
+	struct ioh_udc_stp_dma_desc	*td_stp;
+	struct ioh_udc_data_dma_desc	*td_data;
+
+	/* DMA setup */
+	dev->data_requests = pci_pool_create("data_requests", dev->pdev,
+		sizeof(struct ioh_udc_data_dma_desc), 0, 0);
+	if (dev->data_requests == NULL) {
+		IOH_LOG(KERN_ERR, "init_dma_pools: can't get request\
+								 data pool");
+		return -ENOMEM;
+	}
+
+	/* dma desc for setup data */
+	dev->stp_requests = pci_pool_create("setup requests", dev->pdev,
+		sizeof(struct ioh_udc_stp_dma_desc), 0, 0);
+	if (dev->stp_requests == NULL) {
+		IOH_LOG(KERN_ERR, "init_dma_pools: can't get setup\
+							 request pool");
+		return -ENOMEM;
+	}
+	/* setup */
+	td_stp = pci_pool_alloc(dev->stp_requests, GFP_KERNEL,
+				&dev->ep[UDC_EP0OUT_IDX].td_stp_phys);
+	if (td_stp == NULL) {
+		IOH_LOG(KERN_ERR, "init_dma_pools: can't allocate setup\
+							 dma descriptor");
+		return -ENOMEM;
+	}
+	dev->ep[UDC_EP0OUT_IDX].td_stp = td_stp;
+
+	/* data: 0 packets !? */
+	td_data = pci_pool_alloc(dev->data_requests, GFP_KERNEL,
+				&dev->ep[UDC_EP0OUT_IDX].td_data_phys);
+	if (td_data == NULL) {
+		IOH_LOG(KERN_ERR, "init_dma_pools: can't allocate data dma\
+								 descriptor");
+		return -ENOMEM;
+	}
+	dev->ep[UDC_EP0OUT_IDX].td_data = td_data;
+	dev->ep[UDC_EP0IN_IDX].td_stp = NULL;
+	dev->ep[UDC_EP0IN_IDX].td_stp_phys = 0;
+	dev->ep[UDC_EP0IN_IDX].td_data = NULL;
+	dev->ep[UDC_EP0IN_IDX].td_data_phys = 0;
+	return 0;
+}
+
+
+
+/* Called by pci bus driver to init pci context */
+/*!@ingroup UDC_PCILayerAPI
+ * @fn		static int ioh_udc_probe(struct pci_dev *pdev,
+ * 						const struct pci_device_id *id)
+ * @brief Implements the Probe routine for IOH USB device controller driver
+ * @param	pdev [@ref IN]   reference to struct pci_dev
+ * @param	id   [@ref IN]   reference to struct pci_device_id table
+ * @return	int  [ 0 on Success and linux error number on failure ]
+ * @remarks	The following actions are performed:
+ *- Allocate and initialize the device driver data structures
+ *- Enable the PCI device and set driver private data
+ *- Do PCI resource allocation for the device
+ *- Request memory region for the device
+ *- Map PCI device memory to kernel virtual space
+ *- Initialize the HAL layer by invoking ioh_udc_pcd_init API
+ *- Register the interrupt handler ioh_udc_isr
+ *- Enable Bus mastering for the device using pci_set_master API.
+ *- Enable memory write invalidate PCI transaction using pci_try_set_mwi API.
+ *- Set up device structure and ops structure and initialize the gadget driver
+ * 							 data structure
+ *- If using DMA (specified during module loading), initialize DMA pools using
+ *							 init_dma_pools API
+ *- Register the device with the system using device_register API
+ *- Put the device in disconnected state till a driver is bound, using
+ *						 ioh_udc_set_disconnect API
+ *- Invoke ioh_udc_remove to perform clean-up on any error.
+ */
+static int ioh_udc_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+{
+	unsigned long		resource;
+	unsigned long		len;
+	int					retval = 0;
+	struct ioh_udc_dev	*dev;
+
+	IOH_DEBUG("ioh_udc_probe: enter");
+	/* one udc only */
+	if (ioh_udc != NULL) {
+		IOH_LOG(KERN_ERR, "ioh_udc_probe: already probed");
+		return -EBUSY;
+	}
+
+	/* init */
+	dev = kzalloc(sizeof(struct ioh_udc_dev), GFP_KERNEL);
+	if (dev == NULL) {
+		IOH_LOG(KERN_ERR, "ioh_udc_probe: no memory for device\
+								 structure");
+		return -ENOMEM;
+	}
+	memset(dev, 0, sizeof(struct ioh_udc_dev));
+	/* pci setup */
+	if (pci_enable_device(pdev) < 0) {
+		kfree(dev);
+		IOH_LOG(KERN_ERR, "ioh_udc_probe: pci_enable_device failed");
+		return -ENODEV;
+	}
+	dev->active = 1;
+	pci_set_drvdata(pdev, dev);
+
+	/* PCI resource allocation */
+	resource = pci_resource_start(pdev, 1);
+	len = pci_resource_len(pdev, 1);
+	IOH_DEBUG("ioh_udc_probe: resource %lx, len %ld", resource, len);
+
+	if (request_mem_region(resource, len, name) == NULL) {
+		IOH_LOG(KERN_ERR, "ioh_udc_probe: pci device used already");
+		retval = -EBUSY;
+		goto finished;
+	}
+	dev->phys_addr = resource;
+	dev->mem_region = 1;
+
+	dev->virt_addr = ioremap_nocache(resource, len);
+	if (dev->virt_addr == NULL) {
+		IOH_LOG(KERN_ERR, "ioh_udc_probe: device memory cannot be\
+								 mapped");
+		retval = -ENOMEM;
+		goto finished;
+	}
+	IOH_DEBUG("ioh_udc_probe: device memory mapped at %x",
+						 (int)dev->virt_addr);
+
+	if (pdev->irq == 0) {
+		IOH_LOG(KERN_ERR, "ioh_udc_probe: irq not set");
+		retval = -ENODEV;
+		goto finished;
+	}
+
+	ioh_udc = dev;
+
+	/* initialize the hardware */
+	if (ioh_udc_pcd_init(dev) != 0)
+		goto finished;
+
+
+	if (request_irq(pdev->irq, ioh_udc_isr, IRQF_SHARED, name, dev) != 0) {
+		IOH_LOG(KERN_ERR, "ioh_udc_probe: request_irq(%d) fail",
+								 pdev->irq);
+		retval = -ENODEV;
+		goto finished;
+	}
+	dev->irq = pdev->irq;
+	dev->irq_registered = 1;
+
+	pci_set_master(pdev);
+	pci_try_set_mwi(pdev);
+
+	/* device struct setup */
+	spin_lock_init(&dev->lock);
+	dev->pdev = pdev;
+	dev->gadget.ops = &ioh_udc_ops;
+
+	/* init dma pools */
+	retval = init_dma_pools(dev);
+	if (retval != 0)
+		goto finished;
+
+/*	strcpy(dev->gadget.dev.bus_id, "gadget");*/
+	dev_set_name(&dev->gadget.dev, "gadget");
+	dev->gadget.dev.parent = &pdev->dev;
+	dev->gadget.dev.dma_mask = pdev->dev.dma_mask;
+	dev->gadget.dev.release = gadget_release;
+	dev->gadget.name = name;
+	dev->gadget.is_dualspeed = 1;
+
+	retval = device_register(&dev->gadget.dev);
+	if (retval != 0)
+		goto finished;
+
+	dev->registered = 1;
+
+	/* Put the device in disconnected state till a driver is bound */
+	ioh_udc_set_disconnect(dev->regs);
+
+#ifdef IOH_PRINT_REG
+	/* print dev register info */
+	ioh_udc_print_regs((u32)dev->virt_addr);
+#endif
+	return 0;
+
+finished:
+	ioh_udc_remove(pdev);
+	return retval;
+}
+
+/*!@ingroup UDC_PCILayerAPI
+ * @fn		static void ioh_udc_shutdown(struct pci_dev *pdev)
+ * @brief	This routine makes sure that the device is quiescent.
+ * @param	pdev    [@ref IN]   reference to struct pci_dev
+ * @return	none
+ * @remarks	The main tasks performed by this method are:
+ *			- Disable interrupts from the device
+ *			- Put the PCI device in soft disconnect mode
+ */
+static void ioh_udc_shutdown(struct pci_dev *pdev)
+{
+	struct ioh_udc_dev *dev = pci_get_drvdata(pdev);
+
+	IOH_DEBUG("ioh_udc_shutdown enter");
+
+	ioh_udc_disable_interrupts(dev->regs, UDC_DEVINT_MSK);
+	ioh_udc_disable_ep_interrupts(dev->regs, UDC_EPINT_MSK_DISABLE_ALL);
+
+	/* disable the pullup so the host will think we're gone */
+	ioh_udc_set_disconnect(dev->regs);
+}
+
+/*!@ingroup UDC_PCILayerAPI
+ * @fn	static int ioh_udc_suspend(struct pci_dev *pdev, pm_message_t state)
+ * @brief Implements the Suspend functionality for IOH USB device controller
+ * 									 driver
+ * @param pdev    [@ref IN]   reference to struct pci_dev
+ * @param state   [@ref IN]   specifies new PM state to which to transition to
+ * @return int [ 0 on Success and linux error number on failure ]
+ * @remarks The main tasks performed by this method are:
+ *			- Disable interrupts from the device
+ *			- Disable the PCI device
+ *			- Save the PCI state
+ *			- Transition to new power state
+ */
+static int ioh_udc_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+	struct ioh_udc_dev *dev = pci_get_drvdata(pdev);
+
+	IOH_DEBUG("ioh_udc_suspend enter");
+
+	ioh_udc_disable_interrupts(dev->regs, UDC_DEVINT_MSK);
+	ioh_udc_disable_ep_interrupts(dev->regs, UDC_EPINT_MSK_DISABLE_ALL);
+
+	pci_disable_device(pdev);
+	pci_enable_wake(pdev, PCI_D3hot, 0);
+
+	if (pci_save_state(pdev) != 0) {
+		IOH_LOG(KERN_ERR, "ioh_udc_suspend: could not save PCI config\
+								 state");
+		return -ENOMEM;
+	}
+
+	if (pci_set_power_state(pdev, pci_choose_state(pdev, state)) == -EIO)
+		IOH_DEBUG("ioh_udc_suspend: does not support PM cpabilities");
+
+
+	return 0;
+}
+
+/*!@ingroup UDC_PCILayerAPI
+ * @fn		static int ioh_udc_resume(struct pci_dev *pdev)
+ * @brief	Implements the Resume functionality for IOH USB device
+ *							 controller driver
+ * @param	pdev    [@ref IN]   reference to struct pci_dev
+ * @return	int [ 0 on Success and linux error number on failure ]
+ * @remarks	The main tasks performed by this method are:
+ *            - Set power state to PCI_D0 using pci_set_power_state
+ *            - Restore the device state using pci_restore_state
+ *            - Enable the device using pci_enable_device
+ *            - Enable the bus mastering using pci_set_master
+ *            - Disable the PM notifications using pci_enable_wake
+ */
+static int ioh_udc_resume(struct pci_dev *pdev)
+{
+	int ret;
+
+	ret = pci_set_power_state(pdev, PCI_D0);
+	if (ret != 0)
+		IOH_DEBUG("ioh_udc_resume: does not support PM cpabilities");
+
+
+	ret = pci_restore_state(pdev);
+	if (ret != 0) {
+		IOH_LOG(KERN_ERR, "ioh_udc_resume: pci_restore_state failed");
+		return ret;
+	}
+
+	ret = pci_enable_device(pdev);
+
+	if (ret != 0) {
+		IOH_LOG(KERN_ERR, "ioh_udc_resume: pci_enable_device failed");
+		return ret;
+	}
+	pci_enable_wake(pdev, PCI_D3hot, 0);
+
+	return 0;
+}
+
+/* PCI device parameters */
+/*!@ingroup	UDC_InterfaceLayer
+ * @struct	ioh_udc_pcidev_id
+ * @brief	This is an instance of pci_device_id structure which holds
+ *								 information
+ *			about the PCI USB device that are supported by this
+ *								 driver.
+ */
+static const struct pci_device_id ioh_udc_pcidev_id[] = {
+	{
+		PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOH1_UDC),
+		.class = (PCI_CLASS_SERIAL_USB << 8) | 0xfe,
+		.class_mask = 0xffffffff,
+	},
+	{
+		PCI_DEVICE(PCI_VENDOR_ID_ROHM, PCI_DEVICE_ID_ROHM_IOH2_UDC),
+		.class = (PCI_CLASS_SERIAL_USB << 8) | 0xfe,
+		.class_mask = 0xffffffff,
+	},
+	{ 0 },
+};
+
+MODULE_DEVICE_TABLE(pci, ioh_udc_pcidev_id);
+
+/* PCI functions */
+/*!@ingroup UDC_InterfaceLayer
+ * @struct	ioh_udc_driver
+ * @brief	Linux pci_driver structure which provides the reference to
+ *						 PCI methods of this driver
+ */
+static struct pci_driver ioh_udc_driver = {
+	.name =		(char *) name,
+	.id_table =	ioh_udc_pcidev_id,
+	.probe =	ioh_udc_probe,
+	.remove =	ioh_udc_remove,
+	.suspend =	ioh_udc_suspend,
+	.resume =	ioh_udc_resume,
+	.shutdown =	ioh_udc_shutdown,
+};
+
+/* Initialize the driver */
+/*!@ingroup UDC_InterfaceLayerAPI
+ * @fn		static int __init ioh_udc_pci_init(void)
+ * @brief	This function is the entry point for the driver
+ * @param	none
+ * @return	int [ 0 on success and <0 on failure ]
+ */
+static int __init ioh_udc_pci_init(void)
+{
+	return pci_register_driver(&ioh_udc_driver);
+}
+module_init(ioh_udc_pci_init);
+
+/* Cleans driver */
+/*!@ingroup UDC_InterfaceLayerAPI
+ * @fn		static void __exit ioh_udc_pci_exit(void)
+ * @brief	This function is the exit point for the driver
+ * @param	none
+ * @return	none
+ */
+static void __exit ioh_udc_pci_exit(void)
+{
+	pci_unregister_driver(&ioh_udc_driver);
+}
+module_exit(ioh_udc_pci_exit);
+
+MODULE_DESCRIPTION(UDC_MOD_DESCRIPTION);
+MODULE_LICENSE("GPL");
--- /dev/null
+++ b/drivers/usb/gadget/pch_udc_pci.h
@@ -0,0 +1,97 @@
+ /*!
+ * @file ioh_udc_pci.h
+ * @brief
+ * The IOH UDC is a USB High speed DMA capable USB device controller.
+ * It provides 4 IN and 4 OUT endpoints (control, bulk isochronous or interrupt
+ *  type).
+ *
+ * The IOH USB device controller driver provides required interface
+ * to the USB gadget framework for accessing the IOH USB device hardware.
+ *
+ * @version 0.96
+ *
+ * @section
+ * 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; version 2 of the License.
+ *
+ * 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.
+ */
+
+ /*
+ * History:
+ * Copyright (C) 2009 OKI SEMICONDUCTOR Co., LTD.
+ * All rights reserved.
+ *
+ * created:
+ *   OKI SEMICONDUCTOR 2/26/2010
+ * modified:
+ *
+ */
+
+#ifndef IOH_UDC_PCI_H
+#define IOH_UDC_PCI_H
+
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/ioport.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/smp_lock.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/timer.h>
+#include <linux/list.h>
+#include <linux/interrupt.h>
+#include <linux/ioctl.h>
+#include <linux/fs.h>
+#include <linux/dmapool.h>
+#include <linux/moduleparam.h>
+#include <linux/device.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+
+#include <asm/byteorder.h>
+#include <asm/system.h>
+#include <asm/unaligned.h>
+
+/* gadget stack */
+#include <linux/usb/ch9.h>
+#include <linux/usb/gadget.h>
+#include "pch_udc_hal.h"
+
+/*!@ingroup UDC_InterfaceLayer
+ * @def PCI_VENDOR_ID_INTEL
+ * @brief PCI Vendor ID for Intel.
+ */
+#define PCI_VENDOR_ID_INTEL 0x8086
+/*!@ingroup UDC_InterfaceLayer
+ * @def PCI_VENDOR_ID_ROHM
+ * @brief PCI Vendor ID for ROHM.
+ */
+#define PCI_VENDOR_ID_ROHM 0x10db
+
+/*!@ingroup UDC_InterfaceLayer
+ * @def PCI_DEVICE_ID_INTEL_IOH1_UDC
+ * @brief Outlines the PCI Device ID for Intel IOH GE UDC device.
+ */
+#define PCI_DEVICE_ID_INTEL_IOH1_UDC 0x8808 /*Device Id for GE device*/
+
+/*!@ingroup UDC_InterfaceLayer
+ * @def PCI_DEVICE_ID_INTEL_IOH1_UDC
+ * @brief Outlines the PCI Device ID for ROHM IOH IVI UDC device.
+ */
+#define PCI_DEVICE_ID_ROHM_IOH2_UDC 0x801D /* Device ID for IVI*/
+
+extern u32 ioh_udc_base;
+#endif /* #ifdef IOH_UDC_PCI_H */
