diff options
author | Saul Wold <Saul.Wold@intel.com> | 2010-09-24 15:36:24 -0700 |
---|---|---|
committer | Saul Wold <Saul.Wold@intel.com> | 2010-09-24 16:43:21 -0700 |
commit | 239a368d5715d8f5b7733f9400339c2350c49369 (patch) | |
tree | 2953f12b45e590d9e14b6f72f8e4ee7188e41508 /meta-moblin/packages/linux/linux-moblin-2.6.33.2/linux-2.6.34-pch-usbdev.patch | |
parent | c5b9525263dac6844d152e40acf8cee4d27b60bc (diff) | |
download | openembedded-core-239a368d5715d8f5b7733f9400339c2350c49369.tar.gz openembedded-core-239a368d5715d8f5b7733f9400339c2350c49369.tar.bz2 openembedded-core-239a368d5715d8f5b7733f9400339c2350c49369.tar.xz openembedded-core-239a368d5715d8f5b7733f9400339c2350c49369.zip |
netbook: Correct netbook build by moving netbook configuration from moblin to meta
Signed-off-by: Saul Wold <Saul.Wold@intel.com>
Diffstat (limited to 'meta-moblin/packages/linux/linux-moblin-2.6.33.2/linux-2.6.34-pch-usbdev.patch')
-rw-r--r-- | meta-moblin/packages/linux/linux-moblin-2.6.33.2/linux-2.6.34-pch-usbdev.patch | 7018 |
1 files changed, 0 insertions, 7018 deletions
diff --git a/meta-moblin/packages/linux/linux-moblin-2.6.33.2/linux-2.6.34-pch-usbdev.patch b/meta-moblin/packages/linux/linux-moblin-2.6.33.2/linux-2.6.34-pch-usbdev.patch deleted file mode 100644 index f9ea573a7..000000000 --- a/meta-moblin/packages/linux/linux-moblin-2.6.33.2/linux-2.6.34-pch-usbdev.patch +++ /dev/null @@ -1,7018 +0,0 @@ -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)®s->epctl); -+ /* set NAK */ -+ IOH_WRITE32(1 << UDC_EPCTL_SNAK , (u32)®s->epctl); -+ -+ IOH_SET_ADDR_BIT((u32)®s->epsts, 1 << UDC_EPSTS_IN); -+ } else { -+ /* set NAK */ -+ IOH_WRITE32(1 << UDC_EPCTL_SNAK , (u32)®s->epctl); -+ } -+ /* reset desc pointer */ -+ IOH_WRITE32(0, (u32)®s->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 */ |