Skip to contentSkip to conversation

Add support for DWC OTG HCD function.

PATCH In review Fushen Chen 4 participants 16 messages Jul 26, 2010 – Oct 7, 2010 USB

lore
Share & tools
lore
#0 lore raw

PATCH 1/2 Add support for DWC OTG HCD function.

This adds support for the USB host controller on APM SoC using Synopsys Designware IP.

---
 drivers/Makefile                        |    1 +
 drivers/usb/Kconfig                     |    2 +
 drivers/usb/dwc_otg/Kconfig             |   96 +
 drivers/usb/dwc_otg/Makefile            |   19 +
 drivers/usb/dwc_otg/dwc_otg_apmppc.c    |  408 ++++
 drivers/usb/dwc_otg/dwc_otg_cil.c       |  903 +++++++++
 drivers/usb/dwc_otg/dwc_otg_cil.h       | 1194 +++++++++++
 drivers/usb/dwc_otg/dwc_otg_cil_intr.c  |  626 ++++++
 drivers/usb/dwc_otg/dwc_otg_driver.h    |   94 +
 drivers/usb/dwc_otg/dwc_otg_hcd.c       | 2408 +++++++++++++++++++++++
 drivers/usb/dwc_otg/dwc_otg_hcd.h       |  426 ++++
 drivers/usb/dwc_otg/dwc_otg_hcd_intr.c  | 1476 ++++++++++++++
 drivers/usb/dwc_otg/dwc_otg_hcd_queue.c |  708 +++++++
 drivers/usb/dwc_otg/dwc_otg_regs.h      | 3282 +++++++++++++++++++++++++++++++
 14 files changed, 11643 insertions(+), 0 deletions(-)
 create mode 100644 drivers/usb/dwc_otg/Kconfig
 create mode 100644 drivers/usb/dwc_otg/Makefile
 create mode 100644 drivers/usb/dwc_otg/dwc_otg_apmppc.c
 create mode 100644 drivers/usb/dwc_otg/dwc_otg_cil.c
 create mode 100644 drivers/usb/dwc_otg/dwc_otg_cil.h
 create mode 100644 drivers/usb/dwc_otg/dwc_otg_cil_intr.c
 create mode 100644 drivers/usb/dwc_otg/dwc_otg_driver.h
 create mode 100644 drivers/usb/dwc_otg/dwc_otg_hcd.c
 create mode 100644 drivers/usb/dwc_otg/dwc_otg_hcd.h
 create mode 100644 drivers/usb/dwc_otg/dwc_otg_hcd_intr.c
 create mode 100644 drivers/usb/dwc_otg/dwc_otg_hcd_queue.c
 create mode 100644 drivers/usb/dwc_otg/dwc_otg_regs.h
drivers/Makefile +1 -0
index 20dcced..f3fc7c7 100644
@@ -67,6 +67,7 @@ obj-$(CONFIG_UWB)		+= uwb/
 obj-$(CONFIG_USB_OTG_UTILS)	+= usb/otg/
 obj-$(CONFIG_USB)		+= usb/
 obj-$(CONFIG_USB_MUSB_HDRC)	+= usb/musb/
+obj-$(CONFIG_USB_DWC_OTG)	+= usb/dwc_otg/
 obj-$(CONFIG_PCI)		+= usb/
 obj-$(CONFIG_USB_GADGET)	+= usb/gadget/
 obj-$(CONFIG_SERIO)		+= input/serio/
drivers/usb/Kconfig +2 -0
index 6a58cb1..f48920b 100644
@@ -113,6 +113,8 @@ source "drivers/usb/host/Kconfig"
 
 source "drivers/usb/musb/Kconfig"
 
+source "drivers/usb/dwc_otg/Kconfig"
+
 source "drivers/usb/class/Kconfig"
 
 source "drivers/usb/storage/Kconfig"
drivers/usb/dwc_otg/Kconfig new file +96 -0

96 lines not on this page · raw message

drivers/usb/dwc_otg/Makefile new file +19 -0
new file mode 100644
index 0000000..31dd5e8
@@ -0,0 +1,19 @@
+#
+# OTG infrastructure and transceiver drivers
+#
+obj-$(CONFIG_USB_DWC_OTG)	+= dwc_otg.o
+
+dwc_otg-objs := dwc_otg_cil.o dwc_otg_cil_intr.o dwc_otg_param.o
+
+ifeq ($(CONFIG_4xx_SOC),y)
+dwc_otg-objs += dwc_otg_apmppc.o
+endif
+
+ifneq ($(CONFIG_DWC_DEVICE_ONLY),y)
+dwc_otg-objs += dwc_otg_hcd.o dwc_otg_hcd_intr.o \
+		dwc_otg_hcd_queue.o
+endif
+
+ifneq ($(CONFIG_DWC_HOST_ONLY),y)
+dwc_otg-objs += dwc_otg_pcd.o dwc_otg_pcd_intr.o
+endif
drivers/usb/dwc_otg/dwc_otg_apmppc.c new file +408 -0

408 lines not on this page · raw message

drivers/usb/dwc_otg/dwc_otg_cil.c new file +903 -0

903 lines not on this page · raw message

drivers/usb/dwc_otg/dwc_otg_cil.h new file +1194 -0

1,194 lines not on this page · raw message

drivers/usb/dwc_otg/dwc_otg_cil_intr.c new file +626 -0

365 lines not on this page · raw message

drivers/usb/dwc_otg/dwc_otg_driver.h new file +94 -0

94 lines not on this page · raw message

drivers/usb/dwc_otg/dwc_otg_hcd.c new file +2408 -0

2,408 lines not on this page · raw message

drivers/usb/dwc_otg/dwc_otg_hcd.h new file +426 -0

426 lines not on this page · raw message

drivers/usb/dwc_otg/dwc_otg_hcd_intr.c new file +1476 -0

1,476 lines not on this page · raw message

drivers/usb/dwc_otg/dwc_otg_hcd_queue.c new file +708 -0

708 lines not on this page · raw message

drivers/usb/dwc_otg/dwc_otg_regs.h new file +3282 -0

3,282 lines not on this page · raw message

The rest of this diff is not shown. View the raw message.

Signature · 1 line
1.7.1

Part of the diff is not shown here. View the raw message.

#1 lore raw

PATCH 2/2 Add support for DWC OTG PCD function.

This adds support for the USB peripheral controller on APM SoC using Synopsys Designware IP.

---
 drivers/usb/dwc_otg/dwc_otg_pcd.c      | 1748 ++++++++++++++++++++++++
 drivers/usb/dwc_otg/dwc_otg_pcd.h      |  149 +++
 drivers/usb/dwc_otg/dwc_otg_pcd_intr.c | 2270 ++++++++++++++++++++++++++++++++
 drivers/usb/gadget/Kconfig             |   21 +
 drivers/usb/gadget/gadget_chips.h      |    7 +
 5 files changed, 4195 insertions(+), 0 deletions(-)
 create mode 100644 drivers/usb/dwc_otg/dwc_otg_pcd.c
 create mode 100644 drivers/usb/dwc_otg/dwc_otg_pcd.h
 create mode 100644 drivers/usb/dwc_otg/dwc_otg_pcd_intr.c
drivers/usb/dwc_otg/dwc_otg_pcd.c new file +1748 -0
new file mode 100644
index 0000000..b817ca3
@@ -0,0 +1,1748 @@
+/*
+ * DesignWare HS OTG controller driver
+ *
+ * Author: Mark Miesfeld <[email protected]>
+ *
+ * Based on versions provided by APM and Synopsis which are:
+ *	Copyright (C) 2009-2010 AppliedMicro(www.apm.com)
+ * Modified by Stefan Roese <[email protected]>, DENX Software Engineering
+ *
+ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
+ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
+ * otherwise expressly agreed to in writing between Synopsys and you.
+ *
+ * The Software IS NOT an item of Licensed Software or Licensed Product under
+ * any End User Software License Agreement or Agreement for Licensed Product
+ * with Synopsys or any supplement thereto. You are permitted to use and
+ * redistribute this Software in source and binary forms, with or without
+ * modification, provided that redistributions of source code must retain this
+ * notice. You may not view, use, disclose, copy or distribute this file or
+ * any information contained herein except pursuant to this license grant from
+ * Synopsys. If you do not agree with this notice, including the disclaimer
+ * below, then you are not authorized to use the Software.
+ *
+ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ * This file implements the Peripheral Controller Driver.
+ *
+ * The Peripheral Controller Driver (PCD) is responsible for
+ * translating requests from the Function Driver into the appropriate
+ * actions on the DWC_otg controller. It isolates the Function Driver
+ * from the specifics of the controller by providing an API to the
+ * Function Driver.
+ *
+ * The Peripheral Controller Driver for Linux will implement the
+ * Gadget API, so that the existing Gadget drivers can be used.
+ * (Gadget Driver is the Linux terminology for a Function Driver.)
+ *
+ * The Linux Gadget API is defined in the header file linux/usb/gadget.h. The
+ * USB EP operations API is defined in the structure usb_ep_ops and the USB
+ * Controller API is defined in the structure usb_gadget_ops
+ *
+ * An important function of the PCD is managing interrupts generated
+ * by the DWC_otg controller. The implementation of the DWC_otg device
+ * mode interrupt service routines is in dwc_otg_pcd_intr.c.
+ */
+
+#include <linux/dma-mapping.h>
+#include <linux/delay.h>
+
+#include "dwc_otg_pcd.h"
+
+/*
+ * Static PCD pointer for use in usb_gadget_register_driver and
+ * usb_gadget_unregister_driver.  Initialized in dwc_otg_pcd_init.
+ */
+static struct dwc_pcd *s_pcd;
+
+static inline int need_stop_srp_timer(struct core_if *core_if)
+{
+	if (core_if->core_params->phy_type != DWC_PHY_TYPE_PARAM_FS ||
+			!core_if->core_params->i2c_enable)
+		return core_if->srp_timer_started ? 1 : 0;
+	return 0;
+}
+
+/**
+ * Tests if the module is set to FS or if the PHY_TYPE is FS. If so, then the
+ * gadget should not report as dual-speed capable.
+ */
+static inline int check_is_dual_speed(struct core_if *core_if)
+{
+	if (core_if->core_params->speed == DWC_SPEED_PARAM_FULL ||
+			(core_if->hwcfg2.b.hs_phy_type == 2 &&
+			core_if->hwcfg2.b.fs_phy_type == 1 &&
+			core_if->core_params->ulpi_fs_ls))
+		return 0;
+	return 1;
+}
+
+/**
+ * Tests if driver is OTG capable.
+ */
+static inline int check_is_otg(struct core_if *core_if)
+{
+	if (core_if->hwcfg2.b.op_mode ==
+			DWC_HWCFG2_OP_MODE_NO_SRP_CAPABLE_DEVICE ||
+			core_if->hwcfg2.b.op_mode ==
+			DWC_HWCFG2_OP_MODE_NO_SRP_CAPABLE_HOST ||
+			core_if->hwcfg2.b.op_mode ==
+			DWC_HWCFG2_OP_MODE_SRP_CAPABLE_DEVICE ||
+			core_if->hwcfg2.b.op_mode ==
+			DWC_HWCFG2_OP_MODE_SRP_CAPABLE_HOST)
+		return 0;
+	return 1;
+}
+
+/**
+ * This function completes a request. It calls the request call back.
+ */
+void request_done(struct pcd_ep *ep, struct pcd_request *req, int status)
+{
+	unsigned stopped = ep->stopped;
+
+	list_del_init(&req->queue);
+	if (req->req.status == -EINPROGRESS)
+		req->req.status = status;
+	else
+		status = req->req.status;
+
+	if (GET_CORE_IF(ep->pcd)->dma_enable) {
+		if (req->mapped) {
+			dma_unmap_single(ep->pcd->gadget.dev.parent,
+				req->req.dma, req->req.length,
+				ep->dwc_ep.is_in ? DMA_TO_DEVICE :
+				DMA_FROM_DEVICE);
+			req->req.dma = DMA_ADDR_INVALID;
+			req->mapped = 0;
+		} else {
+			dma_sync_single_for_cpu(ep->pcd->gadget.dev.parent,
+				req->req.dma, req->req.length,
+				ep->dwc_ep.is_in ? DMA_TO_DEVICE :
+				DMA_FROM_DEVICE);
+		}
+	}
+
+	/* don't modify queue heads during completion callback */
+	ep->stopped = 1;
+	spin_unlock(&ep->pcd->lock);
+	req->req.complete(&ep->ep, &req->req);
+	spin_lock(&ep->pcd->lock);
+
+	if (ep->pcd->request_pending > 0)
+		--ep->pcd->request_pending;
+	ep->stopped = stopped;
+
+	/*
+	 * Added-sr: 2007-07-26
+	 *
+	 * Finally, when the current request is done, mark this endpoint
+	 * as not active, so that new requests can be processed.
+	 */
+	if (dwc_has_feature(GET_CORE_IF(ep->pcd), DWC_LIMITED_XFER))
+		ep->dwc_ep.active = 0;
+}
+
+/**
+ * This function terminates all the requsts in the EP request queue.
+ */
+void request_nuke(struct pcd_ep *ep)
+{
+	struct pcd_request *req;
+
+	ep->stopped = 1;
+
+	/* called with irqs blocked?? */
+	while (!list_empty(&ep->queue)) {
+		req = list_entry(ep->queue.next, struct pcd_request, queue);
+		request_done(ep, req, -ESHUTDOWN);
+	}
+}
+
+/*
+ * The following sections briefly describe the behavior of the Gadget
+ * API endpoint operations implemented in the DWC_otg driver
+ * software. Detailed descriptions of the generic behavior of each of
+ * these functions can be found in the Linux header file
+ * include/linux/usb_gadget.h.
+ *
+ * The Gadget API provides wrapper functions for each of the function
+ * pointers defined in usb_ep_ops. The Gadget Driver calls the wrapper
+ * function, which then calls the underlying PCD function. The
+ * following sections are named according to the wrapper
+ * functions. Within each section, the corresponding DWC_otg PCD
+ * function name is specified.
+ *
+ */
+
+/**
+ * This function assigns periodic Tx FIFO to an periodic EP in shared Tx FIFO
+ * mode
+ */
+static u32 assign_perio_tx_fifo(struct core_if *core_if)
+{
+	u32 mask = 1;
+	u32 i;
+
+	for (i = 0; i < core_if->hwcfg4.b.num_dev_perio_in_ep; ++i) {
+		if (!(mask & core_if->p_tx_msk)) {
+			core_if->p_tx_msk |= mask;
+			return i + 1;
+		}
+		mask <<= 1;
+	}
+	return 0;
+}
+
+/**
+ * This function releases periodic Tx FIFO in shared Tx FIFO mode
+ */
+static void release_perio_tx_fifo(struct core_if *core_if, u32 fifo_num)
+{
+	core_if->p_tx_msk = (core_if->p_tx_msk & (1 << (fifo_num - 1)))
+				^ core_if->p_tx_msk;
+}
+
+/**
+ * This function assigns periodic Tx FIFO to an periodic EP in shared Tx FIFO
+ * mode
+ */
+static u32 assign_tx_fifo(struct core_if *core_if)
+{
+	u32 mask = 1;
+	u32 i;
+
+	for (i = 0; i < core_if->hwcfg4.b.num_in_eps; ++i) {
+		if (!(mask & core_if->tx_msk)) {
+			core_if->tx_msk |= mask;
+			return i + 1;
+		}
+		mask <<= 1;
+	}
+	return 0;
+}
+
+/**
+ * This function releases periodic Tx FIFO in shared Tx FIFO mode
+ */
+static void release_tx_fifo(struct core_if *core_if, u32 fifo_num)
+{
+	core_if->tx_msk = (core_if->tx_msk & (1 << (fifo_num - 1)))
+				^ core_if->tx_msk;
+}
+
+/**
+ * Sets an in endpoint's tx fifo based on the hardware configuration.
+ */
+static void set_in_ep_tx_fifo(struct dwc_pcd *pcd, struct pcd_ep *ep,
+		const struct usb_endpoint_descriptor *desc)
+{
+	if (pcd->otg_dev->core_if->en_multiple_tx_fifo) {
+		ep->dwc_ep.tx_fifo_num = assign_tx_fifo(pcd->otg_dev->core_if);
+	} else {
+		ep->dwc_ep.tx_fifo_num = 0;
+
+		/* If ISOC EP then assign a Periodic Tx FIFO. */
+		if ((desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
+			USB_ENDPOINT_XFER_ISOC)
+			ep->dwc_ep.tx_fifo_num =
+				assign_perio_tx_fifo(pcd->otg_dev->core_if);
+	}
+}
+
+/**
+ * This function activates an EP.  The Device EP control register for
+ * the EP is configured as defined in the ep structure.  Note: This function is
+ * not used for EP0.
+ */
+void dwc_otg_ep_activate(struct core_if *core_if, struct dwc_ep *ep)
+{
+	struct device_if *dev_if = core_if->dev_if;
+	union depctl_data depctl;
+	u32 *addr;
+	union daint_data daintmsk = {.d32 = 0};
+
+	/* Read DEPCTLn register */
+	if (ep->is_in == 1) {
+		addr = &dev_if->in_ep_regs[ep->num]->diepctl;
+		daintmsk.ep.in = 1 << ep->num;
+	} else {
+		addr = &dev_if->out_ep_regs[ep->num]->doepctl;
+		daintmsk.ep.out = 1 << ep->num;
+	}
+
+	/* If the EP is already active don't change the EP Control register */
+	depctl.d32 = dwc_read_reg32(addr);
+	if (!depctl.b.usbactep) {
+		depctl.b.mps = ep->maxpacket;
+		depctl.b.eptype = ep->type;
+		depctl.b.txfnum = ep->tx_fifo_num;
+		depctl.b.setd0pid = 1;
+		depctl.b.usbactep = 1;
+		dwc_write_reg32(addr, depctl.d32);
+	}
+
+	/* Enable the Interrupt for this EP */
+	dwc_modify_reg32(&dev_if->dev_global_regs->daintmsk, 0, daintmsk.d32);
+
+	ep->stall_clear_flag = 0;
+}
+
+/**
+ * This function is called by the Gadget Driver for each EP to be
+ * configured for the current configuration (SET_CONFIGURATION).
+ *
+ * This function initializes the dwc_otg_ep_t data structure, and then
+ * calls dwc_otg_ep_activate.
+ */
+static int dwc_otg_pcd_ep_enable(struct usb_ep *_ep,
+	const struct usb_endpoint_descriptor *desc)
+{
+	struct pcd_ep *ep = NULL;
+	struct dwc_pcd *pcd = NULL;
+	unsigned long flags;
+
+	ep = container_of(_ep, struct pcd_ep, ep);
+	if (!_ep || !desc || ep->desc || desc->bDescriptorType !=
+			USB_DT_ENDPOINT) {
+		printk(KERN_WARNING "%s, bad ep or descriptor\n", __func__);
+		return -EINVAL;
+	}
+
+	if (ep == &ep->pcd->ep0) {
+		printk(KERN_WARNING "%s, bad ep(0)\n", __func__);
+		return -EINVAL;
+	}
+
+	/* Check FIFO size */
+	if (!desc->wMaxPacketSize) {
+		printk(KERN_WARNING "%s, bad %s maxpacket\n", __func__,
+				_ep->name);
+		return -ERANGE;
+	}
+
+	pcd = ep->pcd;
+	if (!pcd->driver || pcd->gadget.speed == USB_SPEED_UNKNOWN) {
+		printk(KERN_WARNING "%s, bogus device state\n", __func__);
+		return -ESHUTDOWN;
+	}
+
+	spin_lock_irqsave(&pcd->lock, flags);
+	ep->desc = desc;
+	ep->ep.maxpacket = le16_to_cpu(desc->wMaxPacketSize);
+
+	/* Activate the EP */
+	ep->stopped = 0;
+	ep->dwc_ep.is_in = (USB_DIR_IN & desc->bEndpointAddress) != 0;
+	ep->dwc_ep.maxpacket = ep->ep.maxpacket;
+	ep->dwc_ep.type = desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
+
+	if (ep->dwc_ep.is_in)
+		set_in_ep_tx_fifo(pcd, ep, desc);
+
+	/* Set initial data PID. */
+	if ((desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
+			USB_ENDPOINT_XFER_BULK)
+		ep->dwc_ep.data_pid_start = 0;
+
+	dwc_otg_ep_activate(GET_CORE_IF(pcd), &ep->dwc_ep);
+	spin_unlock_irqrestore(&pcd->lock, flags);
+	return 0;
+}
+
+/**
+ * This function deactivates an EP.  This is done by clearing the USB Active EP
+ * bit in the Device EP control register.  Note: This function is not used for
+ * EP0. EP0 cannot be deactivated.
+ */
+static void dwc_otg_ep_deactivate(struct core_if *core_if, struct dwc_ep *ep)
+{
+	union depctl_data depctl = {.d32 = 0};
+	u32 *addr;
+	union daint_data daintmsk = {.d32 = 0};
+
+	/* Read DEPCTLn register */
+	if (ep->is_in == 1) {
+		addr = &core_if->dev_if->in_ep_regs[ep->num]->diepctl;
+		daintmsk.ep.in = 1 << ep->num;
+	} else {
+		addr = &core_if->dev_if->out_ep_regs[ep->num]->doepctl;
+		daintmsk.ep.out = 1 << ep->num;
+	}
+
+	depctl.b.usbactep = 0;
+	dwc_write_reg32(addr, depctl.d32);
+
+	/* Disable the Interrupt for this EP */
+	dwc_modify_reg32(&core_if->dev_if->dev_global_regs->daintmsk,
+			daintmsk.d32, 0);
+}
+
+/**
+ * This function is called when an EP is disabled due to disconnect or
+ * change in configuration. Any pending requests will terminate with a
+ * status of -ESHUTDOWN.
+ *
+ * This function modifies the dwc_otg_ep_t data structure for this EP,
+ * and then calls dwc_otg_ep_deactivate.
+ */
+static int dwc_otg_pcd_ep_disable(struct usb_ep *_ep)
+{
+	struct pcd_ep *ep;
+	struct core_if *core_if;
+	unsigned long flags;
+
+	ep = container_of(_ep, struct pcd_ep, ep);
+	if (!_ep || !ep->desc)
+		return -EINVAL;
+
+	core_if = ep->pcd->otg_dev->core_if;
+
+	spin_lock_irqsave(&ep->pcd->lock, flags);
+
+	request_nuke(ep);
+	dwc_otg_ep_deactivate(core_if, &ep->dwc_ep);
+
+	ep->desc = NULL;
+	ep->stopped = 1;
+	if (ep->dwc_ep.is_in) {
+		release_perio_tx_fifo(core_if, ep->dwc_ep.tx_fifo_num);
+		release_tx_fifo(core_if, ep->dwc_ep.tx_fifo_num);
+	}
+
+	spin_unlock_irqrestore(&ep->pcd->lock, flags);
+
+	return 0;
+}
+
+/**
+ * This function allocates a request object to use with the specified
+ * endpoint.
+ */
+static struct usb_request *dwc_otg_pcd_alloc_request(struct usb_ep *_ep,
+				gfp_t gfp_flags)
+{
+	struct pcd_request *req;
+
+	if (!_ep) {
+		printk(KERN_WARNING "%s() Invalid EP\n", __func__);
+		return 0;
+	}
+
+	req = kzalloc(sizeof(struct pcd_request), gfp_flags);
+	if (!req) {
+		printk(KERN_WARNING "%s() request allocation failed\n",
+				__func__);
+		return 0;
+	}
+
+	req->req.dma = DMA_ADDR_INVALID;
+	INIT_LIST_HEAD(&req->queue);
+
+	return &req->req;
+}
+
+/**
+ * This function frees a request object.
+ */
+static void dwc_otg_pcd_free_request(struct usb_ep *_ep,
+				     struct usb_request *_req)
+{
+	struct pcd_request *req;
+
+	if (!_ep || !_req) {
+		printk(KERN_WARNING "%s() nvalid ep or req argument\n",
+			__func__);
+		return;
+	}
+
+	req = container_of(_req, struct pcd_request, req);
+	kfree(req);
+}
+
+/*
+ * In dedicated Tx FIFO mode, enable the Non-Periodic Tx FIFO empty interrupt.
+ * Otherwise, enable the Tx FIFO epmty interrupt. The data will be written into
+ * the fifo by the ISR.
+ */
+static void enable_tx_fifo_empty_intr(struct core_if *c_if, struct dwc_ep *ep)
+{
+	union gintmsk_data intr_mask = {.d32 = 0};
+	struct device_if *d_if = c_if->dev_if;
+	struct core_global_regs *glbl_regs = c_if->core_global_regs;
+
+	if (!c_if->en_multiple_tx_fifo) {
+		intr_mask.b.nptxfempty = 1;
+		dwc_modify_reg32(&glbl_regs->gintsts, intr_mask.d32, 0);
+		dwc_modify_reg32(&glbl_regs->gintmsk, intr_mask.d32,
+					intr_mask.d32);
+	} else if (ep->xfer_len) {
+		/* Enable the Tx FIFO Empty Interrupt for this EP */
+		u32 fifoemptymsk = 1 << ep->num;
+		dwc_modify_reg32(&d_if->dev_global_regs->dtknqr4_fifoemptymsk,
+					0, fifoemptymsk);
+	}
+}
+
+static void set_next_ep(struct device_if *dev_if, u8 num)
+{
+	union depctl_data depctl;
+
+	depctl.d32 = dwc_read_reg32(&dev_if->in_ep_regs[0]->diepctl);
+	depctl.b.nextep = num;
+
+	dwc_write_reg32(&dev_if->in_ep_regs[0]->diepctl, depctl.d32);
+}
+
+/**
+ * This function does the setup for a data transfer for an EP and
+ * starts the transfer.  For an IN transfer, the packets will be loaded into the
+ * appropriate Tx FIFO in the ISR. For OUT transfers, the packets are unloaded
+ * from the Rx FIFO in the ISR.
+ *
+ */
+void dwc_otg_ep_start_transfer(struct core_if *c_if, struct dwc_ep *ep)
+{
+	union depctl_data depctl;
+	union deptsiz_data deptsiz;
+	struct device_if *d_if = c_if->dev_if;
+	struct core_global_regs *glbl_regs = c_if->core_global_regs;
+
+	if (ep->is_in) {
+		struct device_in_ep_regs *in_regs = d_if->in_ep_regs[ep->num];
+		union gnptxsts_data gtxstatus;
+		gtxstatus.d32 = dwc_read_reg32(&glbl_regs->gnptxsts);
+
+		if (!c_if->en_multiple_tx_fifo && !gtxstatus.b.nptxqspcavail)
+			return;
+
+		depctl.d32 = dwc_read_reg32(&(in_regs->diepctl));
+		deptsiz.d32 = dwc_read_reg32(&(in_regs->dieptsiz));
+
+		/* Zero Length Packet? */
+		if (!ep->xfer_len) {
+			deptsiz.b.xfersize = 0;
+			deptsiz.b.pktcnt = 1;
+		} else {
+			/*
+			 * Program the transfer size and packet count as
+			 * follows:
+			 *
+			 * xfersize = N * maxpacket + short_packet
+			 * pktcnt = N + (short_packet exist ? 1 : 0)
+			 */
+
+			/*
+			 * Added-sr: 2007-07-26
+			 *
+			 * Since the 405EZ (Ultra) only support 2047 bytes as
+			 * max transfer size, we have to split up bigger
+			 * transfers into multiple transfers of 1024 bytes sized
+			 * messages. I happens often, that transfers of 4096
+			 * bytes are required (zero-gadget,
+			 * file_storage-gadget).
+			 */
+			if (dwc_has_feature(c_if, DWC_LIMITED_XFER)) {
+				if (ep->xfer_len > MAX_XFER_LEN) {
+					ep->bytes_pending = ep->xfer_len
+						- MAX_XFER_LEN;
+					ep->xfer_len = MAX_XFER_LEN;
+				}
+			}
+
+			deptsiz.b.xfersize = ep->xfer_len;
+			deptsiz.b.pktcnt = (ep->xfer_len - 1 + ep->maxpacket) /
+						ep->maxpacket;
+		}
+		dwc_write_reg32(&in_regs->dieptsiz, deptsiz.d32);
+
+		if (c_if->dma_enable)
+			dwc_write_reg32(&in_regs->diepdma, ep->dma_addr);
+		else if (ep->type != DWC_OTG_EP_TYPE_ISOC)
+			enable_tx_fifo_empty_intr(c_if, ep);
+
+		/* EP enable, IN data in FIFO */
+		depctl.b.cnak = 1;
+		depctl.b.epena = 1;
+		dwc_write_reg32(&in_regs->diepctl, depctl.d32);
+
+		if (c_if->dma_enable)
+			set_next_ep(d_if, ep->num);
+	} else {
+		struct device_out_ep_regs *out_regs =
+			d_if->out_ep_regs[ep->num];
+
+		depctl.d32 = dwc_read_reg32(&out_regs->doepctl);
+		deptsiz.d32 = dwc_read_reg32(&out_regs->doeptsiz);
+
+		/*
+		 * Program the transfer size and packet count as follows:
+		 *
+		 * pktcnt = N
+		 * xfersize = N * maxpacket
+		 */
+		if (!ep->xfer_len) {
+			deptsiz.b.xfersize = ep->maxpacket;
+			deptsiz.b.pktcnt = 1;
+		} else {
+			deptsiz.b.pktcnt = (ep->xfer_len + ep->maxpacket - 1) /
+					ep->maxpacket;
+			deptsiz.b.xfersize = deptsiz.b.pktcnt * ep->maxpacket;
+		}
+		dwc_write_reg32(&out_regs->doeptsiz, deptsiz.d32);
+
+		if (c_if->dma_enable)
+			dwc_write_reg32(&out_regs->doepdma, ep->dma_addr);
+
+		if (ep->type == DWC_OTG_EP_TYPE_ISOC) {
+			if (ep->even_odd_frame)
+				depctl.b.setd1pid = 1;
+			else
+				depctl.b.setd0pid = 1;
+		}
+
+		/* EP enable */
+		depctl.b.cnak = 1;
+		depctl.b.epena = 1;
+		dwc_write_reg32(&out_regs->doepctl, depctl.d32);
+	}
+}
+
+/**
+ * This function does the setup for a data transfer for EP0 and starts
+ * the transfer.  For an IN transfer, the packets will be loaded into
+ * the appropriate Tx FIFO in the ISR. For OUT transfers, the packets are
+ * unloaded from the Rx FIFO in the ISR.
+ */
+void dwc_otg_ep0_start_transfer(struct core_if *c_if, struct dwc_ep *ep)
+{
+	union depctl_data depctl;
+	union deptsiz0_data deptsiz;
+	struct device_if *d_if = c_if->dev_if;
+	struct core_global_regs *glbl_regs = c_if->core_global_regs;
+
+	ep->total_len = ep->xfer_len;
+
+	if (ep->is_in) {
+		struct device_in_ep_regs *in_regs = d_if->in_ep_regs[0];
+		union gnptxsts_data gtxstatus;
+
+		gtxstatus.d32 = dwc_read_reg32(&glbl_regs->gnptxsts);
+
+		if (!c_if->en_multiple_tx_fifo && !gtxstatus.b.nptxqspcavail)
+			return;
+
+		depctl.d32 = dwc_read_reg32(&in_regs->diepctl);
+		deptsiz.d32 = dwc_read_reg32(&in_regs->dieptsiz);
+
+		/* Zero Length Packet? */
+		if (!ep->xfer_len) {
+			deptsiz.b.xfersize = 0;
+			deptsiz.b.pktcnt = 1;
+		} else {
+			/*
+			 * Program the transfer size and packet count  as
+			 * follows:
+			 *
+			 *  xfersize = N * maxpacket + short_packet
+			 *  pktcnt = N + (short_packet exist ? 1 : 0)
+			 */
+			if (ep->xfer_len > ep->maxpacket) {
+				ep->xfer_len = ep->maxpacket;
+				deptsiz.b.xfersize = ep->maxpacket;
+			} else {
+				deptsiz.b.xfersize = ep->xfer_len;
+			}
+			deptsiz.b.pktcnt = 1;
+		}
+		dwc_write_reg32(&in_regs->dieptsiz, deptsiz.d32);
+
+		if (c_if->dma_enable)
+			dwc_write_reg32(&in_regs->diepdma, ep->dma_addr);
+
+		/* EP enable, IN data in FIFO */
+		depctl.b.cnak = 1;
+		depctl.b.epena = 1;
+		dwc_write_reg32(&in_regs->diepctl, depctl.d32);
+
+		if (!c_if->dma_enable)
+			enable_tx_fifo_empty_intr(c_if, ep);
+	} else {
+		struct device_out_ep_regs *out_regs =
+			d_if->out_ep_regs[ep->num];
+
+		depctl.d32 = dwc_read_reg32(&out_regs->doepctl);
+		deptsiz.d32 = dwc_read_reg32(&out_regs->doeptsiz);
+
+		/*
+		 * Program the transfer size and packet count as follows:
+		 *
+		 * xfersize = N * (maxpacket + 4 - (maxpacket % 4))
+		 * pktcnt = N
+		 */
+		if (!ep->xfer_len) {
+			deptsiz.b.xfersize = ep->maxpacket;
+			deptsiz.b.pktcnt = 1;
+		} else {
+			deptsiz.b.pktcnt = (ep->xfer_len + ep->maxpacket - 1) /
+						ep->maxpacket;
+			deptsiz.b.xfersize = deptsiz.b.pktcnt * ep->maxpacket;
+		}
+		dwc_write_reg32(&out_regs->doeptsiz, deptsiz.d32);
+
+		if (c_if->dma_enable)
+			dwc_write_reg32(&out_regs->doepdma, ep->dma_addr);
+
+		/* EP enable */
+		depctl.b.cnak = 1;
+		depctl.b.epena = 1;
+		dwc_write_reg32(&out_regs->doepctl, depctl.d32);
+	}
+}
+
+/**
+ * This function is used to submit an I/O Request to an EP.
+ *
+ *	- When the request completes the request's completion callback
+ *	  is called to return the request to the driver.
+ *	- An EP, except control EPs, may have multiple requests
+ *	  pending.
+ *	- Once submitted the request cannot be examined or modified.
+ *	- Each request is turned into one or more packets.
+ *	- A BULK EP can queue any amount of data; the transfer is
+ *	  packetized.
+ *	- Zero length Packets are specified with the request 'zero'
+ *	  flag.
+ */
+static int dwc_otg_pcd_ep_queue(struct usb_ep *_ep, struct usb_request *_req,
+				gfp_t gfp_flags)
+{
+	int prevented = 0;
+	struct pcd_request *req;
+	struct pcd_ep *ep;
+	struct dwc_pcd *pcd;
+	struct core_if *core_if;
+	unsigned long flags = 0;
+
+	req = container_of(_req, struct pcd_request, req);
+	if (!_req || !_req->complete || !_req->buf ||
+			!list_empty(&req->queue)) {
+		printk(KERN_WARNING "%s, bad params\n", __func__);
+		return -EINVAL;
+	}
+
+	ep = container_of(_ep, struct pcd_ep, ep);
+	if (!_ep || (!ep->desc && ep->dwc_ep.num != 0)) {
+		printk(KERN_WARNING "%s, bad ep\n", __func__);
+		return -EINVAL;
+	}
+
+	pcd = ep->pcd;
+	if (!pcd->driver || pcd->gadget.speed == USB_SPEED_UNKNOWN) {
+		printk(KERN_WARNING "%s, bogus device state\n", __func__);
+		return -ESHUTDOWN;
+	}
+	core_if = pcd->otg_dev->core_if;
+
+	if (!core_if->core_params->opt) {
+		if (ep->dwc_ep.num != 0) {
+			printk(KERN_ERR "%s queue req %p, len %d buf %p\n",
+				_ep->name, _req, _req->length, _req->buf);
+		}
+	}
+
+	if (GET_CORE_IF(pcd)->dma_enable) {
+		if (_req->dma == DMA_ADDR_INVALID) {
+			_req->dma = dma_map_single(pcd->gadget.dev.parent,
+				_req->buf, _req->length, ep->dwc_ep.is_in ?
+				DMA_TO_DEVICE : DMA_FROM_DEVICE);
+			req->mapped = 1;
+		} else {
+			dma_sync_single_for_device(pcd->gadget.dev.parent,
+				_req->dma, _req->length, ep->dwc_ep.is_in ?
+				DMA_TO_DEVICE : DMA_FROM_DEVICE);
+			req->mapped = 0;
+		}
+	}
+
+	spin_lock_irqsave(&ep->pcd->lock, flags);
+
+	_req->status = -EINPROGRESS;
+	_req->actual = 0;
+
+	/* Start the transfer */
+	if (list_empty(&ep->queue) && !ep->stopped) {
+		/* EP0 Transfer? */
+		if (ep->dwc_ep.num == 0) {
+			switch (pcd->ep0state) {
+			case EP0_IN_DATA_PHASE:
+				break;
+			case EP0_OUT_DATA_PHASE:
+				if (pcd->request_config) {
+					/* Complete STATUS PHASE */
+					ep->dwc_ep.is_in = 1;
+					pcd->ep0state = EP0_STATUS;
+				}
+				break;
+			default:
+				spin_unlock_irqrestore(&pcd->lock, flags);
+				return -EL2HLT;
+			}
+
+			ep->dwc_ep.dma_addr = _req->dma;
+			ep->dwc_ep.start_xfer_buff = _req->buf;
+			ep->dwc_ep.xfer_buff = _req->buf;
+			ep->dwc_ep.xfer_len = _req->length;
+			ep->dwc_ep.xfer_count = 0;
+			ep->dwc_ep.sent_zlp = 0;
+			ep->dwc_ep.total_len = ep->dwc_ep.xfer_len;
+
+			dwc_otg_ep0_start_transfer(core_if, &ep->dwc_ep);
+		} else {
+			/* Setup and start the Transfer */
+			ep->dwc_ep.dma_addr = _req->dma;
+			ep->dwc_ep.start_xfer_buff = _req->buf;
+			ep->dwc_ep.xfer_buff = _req->buf;
+			ep->dwc_ep.xfer_len = _req->length;
+			ep->dwc_ep.xfer_count = 0;
+			ep->dwc_ep.sent_zlp = 0;
+			ep->dwc_ep.total_len = ep->dwc_ep.xfer_len;
+
+			dwc_otg_ep_start_transfer(core_if, &ep->dwc_ep);
+		}
+	}
+
+	if (req || prevented) {
+		++pcd->request_pending;
+		list_add_tail(&req->queue, &ep->queue);
+
+		if (ep->dwc_ep.is_in && ep->stopped && !core_if->dma_enable) {
+			/*
+			 *  Device IN endpoint interrupt mask register is laid
+			 *  out exactly the same as the device IN endpoint
+			 *  interrupt register.
+			 */
+			union diepint_data diepmsk = {.d32 = 0};
+			diepmsk.b.intktxfemp = 1;
+
+			dwc_modify_reg32(
+				&core_if->dev_if->dev_global_regs->diepmsk,
+				0, diepmsk.d32);
+		}
+	}
+
+	spin_unlock_irqrestore(&pcd->lock, flags);
+	return 0;
+}
+
+/**
+ * This function cancels an I/O request from an EP.
+ */
+static int dwc_otg_pcd_ep_dequeue(struct usb_ep *_ep,
+				  struct usb_request *_req)
+{
+	struct pcd_request *req;
+	struct pcd_ep *ep;
+	struct dwc_pcd *pcd;
+	unsigned long flags;
+
+	ep = container_of(_ep, struct pcd_ep, ep);
+	if (!_ep || !_req || (!ep->desc && ep->dwc_ep.num != 0)) {
+		printk(KERN_WARNING "%s, bad argument\n", __func__);
+		return -EINVAL;
+	}
+
+	pcd = ep->pcd;
+	if (!pcd->driver || pcd->gadget.speed == USB_SPEED_UNKNOWN) {
+		printk(KERN_WARNING "%s, bogus device state\n", __func__);
+		return -ESHUTDOWN;
+	}
+
+	spin_lock_irqsave(&pcd->lock, flags);
+
+	/* make sure it's actually queued on this endpoint */
+	list_for_each_entry(req, &ep->queue, queue)
+		if (&req->req == _req)
+			break;
+
+	if (&req->req != _req) {
+		spin_unlock_irqrestore(&pcd->lock, flags);
+		return -EINVAL;
+	}
+
+	if (!list_empty(&req->queue))
+		request_done(ep, req, -ECONNRESET);
+	else
+		req = 0;
+
+	spin_unlock_irqrestore(&pcd->lock, flags);
+
+	return req ? 0 : -EOPNOTSUPP;
+}
+
+/**
+ * Set the EP STALL.
+ */
+void dwc_otg_ep_set_stall(struct core_if *core_if, struct dwc_ep *ep)
+{
+	union depctl_data depctl;
+	u32 *depctl_addr;
+
+	if (ep->is_in) {
+		depctl_addr = &(core_if->dev_if->in_ep_regs[ep->num]->diepctl);
+		depctl.d32 = dwc_read_reg32(depctl_addr);
+
+		/* set the disable and stall bits */
+		if (depctl.b.epena)
+			depctl.b.epdis = 1;
+		depctl.b.stall = 1;
+		dwc_write_reg32(depctl_addr, depctl.d32);
+	} else {
+		depctl_addr = &(core_if->dev_if->out_ep_regs[ep->num]->doepctl);
+		depctl.d32 = dwc_read_reg32(depctl_addr);
+
+		/* set the stall bit */
+		depctl.b.stall = 1;
+		dwc_write_reg32(depctl_addr, depctl.d32);
+	}
+}
+
+/**
+ * Clear the EP STALL.
+ */
+void dwc_otg_ep_clear_stall(struct core_if *core_if, struct dwc_ep *ep)
+{
+	union depctl_data depctl;
+	u32 *depctl_addr;
+
+	if (ep->is_in == 1)
+		depctl_addr = &(core_if->dev_if->in_ep_regs[ep->num]->diepctl);
+	else
+		depctl_addr = &(core_if->dev_if->out_ep_regs[ep->num]->doepctl);
+
+	depctl.d32 = dwc_read_reg32(depctl_addr);
+
+	/* clear the stall bits */
+	depctl.b.stall = 0;
+
+	/*
+	 * USB Spec 9.4.5: For endpoints using data toggle, regardless
+	 * of whether an endpoint has the Halt feature set, a
+	 * ClearFeature(ENDPOINT_HALT) request always results in the
+	 * data toggle being reinitialized to DATA0.
+	 */
+	if (ep->type == DWC_OTG_EP_TYPE_INTR ||
+			ep->type == DWC_OTG_EP_TYPE_BULK)
+		depctl.b.setd0pid = 1;	/* DATA0 */
+
+	dwc_write_reg32(depctl_addr, depctl.d32);
+}
+
+/**
+ * usb_ep_set_halt stalls an endpoint.
+ *
+ * usb_ep_clear_halt clears an endpoint halt and resets its data
+ * toggle.
+ *
+ * Both of these functions are implemented with the same underlying
+ * function. The behavior depends on the val argument:
+ *	- 0 means clear_halt.
+ *	- 1 means set_halt,
+ *	- 2 means clear stall lock flag.
+ *	- 3 means set  stall lock flag.
+ */
+static int dwc_otg_pcd_ep_set_halt(struct usb_ep *_ep, int val)
+{
+	int retval = 0;
+	unsigned long flags;
+	struct pcd_ep *ep = NULL;
+
+	ep = container_of(_ep, struct pcd_ep, ep);
+	if (!_ep || (!ep->desc && ep != &ep->pcd->ep0) ||
+			ep->desc->bmAttributes == USB_ENDPOINT_XFER_ISOC) {
+		printk(KERN_WARNING "%s, bad ep\n", __func__);
+		return -EINVAL;
+	}
+
+	spin_lock_irqsave(&ep->pcd->lock, flags);
+
+	if (ep->dwc_ep.is_in && !list_empty(&ep->queue)) {
+		printk(KERN_WARNING "%s() %s XFer In process\n", __func__,
+				_ep->name);
+		retval = -EAGAIN;
+	} else if (val == 0) {
+		dwc_otg_ep_clear_stall(ep->pcd->otg_dev->core_if, &ep->dwc_ep);
+	} else if (val == 1) {
+		if (ep->dwc_ep.num == 0)
+			ep->pcd->ep0state = EP0_STALL;
+
+		ep->stopped = 1;
+		dwc_otg_ep_set_stall(ep->pcd->otg_dev->core_if, &ep->dwc_ep);
+	} else if (val == 2) {
+		ep->dwc_ep.stall_clear_flag = 0;
+	} else if (val == 3) {
+		ep->dwc_ep.stall_clear_flag = 1;
+	}
+
+	spin_unlock_irqrestore(&ep->pcd->lock, flags);
+	return retval;
+}
+
+static struct usb_ep_ops dwc_otg_pcd_ep_ops = {
+	.enable = dwc_otg_pcd_ep_enable,
+	.disable = dwc_otg_pcd_ep_disable,
+	.alloc_request = dwc_otg_pcd_alloc_request,
+	.free_request = dwc_otg_pcd_free_request,
+	.queue = dwc_otg_pcd_ep_queue,
+	.dequeue = dwc_otg_pcd_ep_dequeue,
+	.set_halt = dwc_otg_pcd_ep_set_halt,
+	.fifo_status = 0,
+	.fifo_flush = 0,
+};
+
+/**
+ * Gets the current USB frame number from the DTS register. This is the frame
+ * number from the last SOF packet.
+ */
+static u32 dwc_otg_get_frame_number(struct core_if *core_if)
+{
+	union dsts_data dsts;
+	dsts.d32 = dwc_read_reg32(&core_if->dev_if->dev_global_regs->dsts);
+	return dsts.b.soffn;
+}
+/**
+ * The following gadget operations will be implemented in the DWC_otg
+ * PCD. Functions in the API that are not described below are not
+ * implemented.
+ *
+ * The Gadget API provides wrapper functions for each of the function
+ * pointers defined in usb_gadget_ops. The Gadget Driver calls the
+ * wrapper function, which then calls the underlying PCD function. The
+ * following sections are named according to the wrapper functions
+ * (except for ioctl, which doesn't have a wrapper function). Within
+ * each section, the corresponding DWC_otg PCD function name is
+ * specified.
+ *
+ */
+
+/**
+ *Gets the USB Frame number of the last SOF.
+ */
+static int dwc_otg_pcd_get_frame(struct usb_gadget *_gadget)
+{
+	struct dwc_pcd *pcd;
+
+	if (!_gadget) {
+		return -ENODEV;
+	} else {
+		pcd = container_of(_gadget, struct dwc_pcd, gadget);
+		dwc_otg_get_frame_number(GET_CORE_IF(pcd));
+	}
+
+	return 0;
+}
+
+/**
+ * This function is called when the SRP timer expires.  The SRP should complete
+ * within 6 seconds.
+ */
+static void srp_timeout(unsigned long data)
+{
+	union gotgctl_data gotgctl;
+	struct dwc_pcd *pcd = (struct dwc_pcd *)data;
+	struct core_if *core_if = pcd->otg_dev->core_if;
+	u32 *addr = otg_ctl_reg(pcd);
+
+	gotgctl.d32 = dwc_read_reg32(addr);
+	core_if->srp_timer_started = 0;
+
+	if (core_if->core_params->phy_type == DWC_PHY_TYPE_PARAM_FS &&
+			core_if->core_params->i2c_enable) {
+		printk(KERN_INFO "SRP Timeout\n");
+
+		if (core_if->srp_success && gotgctl.b.bsesvld) {
+			if (core_if->pcd_cb && core_if->pcd_cb->resume_wakeup)
+				core_if->pcd_cb->resume_wakeup(
+						core_if->pcd_cb->p);
+
+			/* Clear Session Request */
+			gotgctl.d32 = 0;
+			gotgctl.b.sesreq = 1;
+			dwc_modify_reg32(addr, gotgctl.d32, 0);
+
+			core_if->srp_success = 0;
+		} else {
+			printk(KERN_ERR "Device not connected/responding\n");
+			gotgctl.b.sesreq = 0;
+			dwc_write_reg32(addr, gotgctl.d32);
+		}
+	} else if (gotgctl.b.sesreq) {
+		printk(KERN_INFO "SRP Timeout\n");
+		printk(KERN_ERR "Device not connected/responding\n");
+
+		gotgctl.b.sesreq = 0;
+		dwc_write_reg32(addr, gotgctl.d32);
+	} else {
+		printk(KERN_INFO " SRP GOTGCTL=%0x\n", gotgctl.d32);
+	}
+}
+
+
+
+/**
+ * Start the SRP timer to detect when the SRP does not complete within
+ * 6 seconds.
+ */
+static void dwc_otg_pcd_start_srp_timer(struct dwc_pcd *pcd)
+{
+	struct timer_list *srp_timer = &pcd->srp_timer;
+
+	GET_CORE_IF(pcd)->srp_timer_started = 1;
+
+	init_timer(srp_timer);
+	srp_timer->function = srp_timeout;
+	srp_timer->data = (unsigned long)pcd;
+	srp_timer->expires = jiffies + (HZ * 6);
+
+	add_timer(srp_timer);
+}
+
+static void dwc_otg_pcd_initiate_srp(struct dwc_pcd *pcd)
+{
+	union gotgctl_data mem;
+	union gotgctl_data val;
+	u32 *addr = otg_ctl_reg(pcd);
+
+	val.d32 = dwc_read_reg32(addr);
+	if (val.b.sesreq) {
+		printk(KERN_ERR "Session Request Already active!\n");
+		return;
+	}
+
+	printk(KERN_NOTICE "Session Request Initated\n");
+	mem.d32 = dwc_read_reg32(addr);
+	mem.b.sesreq = 1;
+	dwc_write_reg32(addr, mem.d32);
+
+	/* Start the SRP timer */
+	dwc_otg_pcd_start_srp_timer(pcd);
+	return;
+}
+
+static void dwc_otg_pcd_remote_wakeup(struct dwc_pcd *pcd, int set)
+{
+	union dctl_data dctl = {.d32 = 0};
+	u32 *addr = dev_ctl_reg(pcd);
+
+	if (dwc_otg_is_device_mode(GET_CORE_IF(pcd))) {
+		if (pcd->remote_wakeup_enable) {
+			if (set) {
+				dctl.b.rmtwkupsig = 1;
+				dwc_modify_reg32(addr, 0, dctl.d32);
+				msleep(1);
+				dwc_modify_reg32(addr, dctl.d32, 0);
+			}
+		}
+	}
+}
+
+/**
+ * Initiates Session Request Protocol (SRP) to wakeup the host if no
+ * session is in progress. If a session is already in progress, but
+ * the device is suspended, remote wakeup signaling is started.
+ *
+ */
+static int dwc_otg_pcd_wakeup(struct usb_gadget *_gadget)
+{
+	unsigned long flags;
+	struct dwc_pcd *pcd;
+	union dsts_data dsts;
+	union gotgctl_data gotgctl;
+
+	if (!_gadget)
+		return -ENODEV;
+	else
+		pcd = container_of(_gadget, struct dwc_pcd, gadget);
+
+	spin_lock_irqsave(&pcd->lock, flags);
+
+	/*
+	 * This function starts the Protocol if no session is in progress. If
+	 * a session is already in progress, but the device is suspended,
+	 * remote wakeup signaling is started.
+	 */
+
+	/* Check if valid session */
+	gotgctl.d32 = dwc_read_reg32(otg_ctl_reg(pcd));
+	if (gotgctl.b.bsesvld) {
+		/* Check if suspend state */
+		dsts.d32 = dwc_read_reg32(dev_sts_reg(pcd));
+		if (dsts.b.suspsts)
+			dwc_otg_pcd_remote_wakeup(pcd, 1);
+	} else {
+		dwc_otg_pcd_initiate_srp(pcd);
+	}
+
+	spin_unlock_irqrestore(&pcd->lock, flags);
+	return 0;
+}
+
+static const struct usb_gadget_ops dwc_otg_pcd_ops = {
+	.get_frame = dwc_otg_pcd_get_frame,
+	.wakeup = dwc_otg_pcd_wakeup,
+	/* not selfpowered */
+};
+
+/**
+ * This function updates the otg values in the gadget structure.
+ */
+void dwc_otg_pcd_update_otg(struct dwc_pcd *pcd, const unsigned reset)
+{
+	if (!pcd->gadget.is_otg)
+		return;
+
+	if (reset) {
+		pcd->b_hnp_enable = 0;
+		pcd->a_hnp_support = 0;
+		pcd->a_alt_hnp_support = 0;
+	}
+
+	pcd->gadget.b_hnp_enable = pcd->b_hnp_enable;
+	pcd->gadget.a_hnp_support = pcd->a_hnp_support;
+	pcd->gadget.a_alt_hnp_support = pcd->a_alt_hnp_support;
+}
+
+/**
+ * This function is the top level PCD interrupt handler.
+ */
+static irqreturn_t dwc_otg_pcd_irq(int _irq, void *dev)
+{
+	struct dwc_pcd *pcd = dev;
+	int retval = IRQ_NONE;
+
+	retval = dwc_otg_pcd_handle_intr(pcd);
+	return IRQ_RETVAL(retval);
+}
+
+/**
+ * PCD Callback function for initializing the PCD when switching to
+ * device mode.
+ */
+static int dwc_otg_pcd_start_cb(void *_p)
+{
+	struct dwc_pcd *pcd = (struct dwc_pcd *)_p;
+
+	/* Initialize the Core for Device mode. */
+	if (dwc_otg_is_device_mode(GET_CORE_IF(pcd)))
+		dwc_otg_core_dev_init(GET_CORE_IF(pcd));
+
+	return 1;
+}
+
+/**
+ * PCD Callback function for stopping the PCD when switching to Host
+ * mode.
+ */
+static int dwc_otg_pcd_stop_cb(void *_p)
+{
+	dwc_otg_pcd_stop((struct dwc_pcd *)_p);
+	return 1;
+}
+
+/**
+ * PCD Callback function for notifying the PCD when resuming from
+ * suspend.
+ *
+ * @param _p void pointer to the <code>struct dwc_pcd</code>
+ */
+static int dwc_otg_pcd_suspend_cb(void *_p)
+{
+	struct dwc_pcd *pcd = (struct dwc_pcd *)_p;
+
+	if (pcd->driver && pcd->driver->suspend) {
+		spin_unlock(&pcd->lock);
+		pcd->driver->suspend(&pcd->gadget);
+		spin_lock(&pcd->lock);
+	}
+	return 1;
+}
+
+/**
+ * PCD Callback function for notifying the PCD when resuming from
+ * suspend.
+ */
+static int dwc_otg_pcd_resume_cb(void *_p)
+{
+	struct dwc_pcd *pcd = (struct dwc_pcd *)_p;
+	struct core_if *core_if = pcd->otg_dev->core_if;
+
+	if (pcd->driver && pcd->driver->resume) {
+		spin_unlock(&pcd->lock);
+		pcd->driver->resume(&pcd->gadget);
+		spin_lock(&pcd->lock);
+	}
+
+	/* Maybe stop the SRP timeout timer. */
+	if (need_stop_srp_timer(core_if))  {
+		core_if->srp_timer_started = 0;
+		del_timer_sync(&pcd->srp_timer);
+	}
+	return 1;
+}
+
+/**
+ * PCD Callback structure for handling mode switching.
+ */
+static struct cil_callbacks pcd_callbacks = {
+	.start = dwc_otg_pcd_start_cb,
+	.stop = dwc_otg_pcd_stop_cb,
+	.suspend = dwc_otg_pcd_suspend_cb,
+	.resume_wakeup = dwc_otg_pcd_resume_cb,
+	.p = 0, /* Set at registration */
+};
+
+/**
+ * Tasklet
+ *
+ */
+static void start_xfer_tasklet_func(unsigned long data)
+{
+	struct dwc_pcd *pcd = (struct dwc_pcd *)data;
+	union depctl_data diepctl;
+	int num = pcd->otg_dev->core_if->dev_if->num_in_eps;
+	u32 i;
+	unsigned long flags;
+
+	spin_lock_irqsave(&pcd->lock, flags);
+	diepctl.d32 = dwc_read_reg32(in_ep_ctl_reg(pcd, 0));
+
+	if (pcd->ep0.queue_sof) {
+		pcd->ep0.queue_sof = 0;
+		start_next_request(&pcd->ep0);
+	}
+
+	for (i = 0; i < num; i++) {
+		union depctl_data diepctl;
+		diepctl.d32 = dwc_read_reg32(in_ep_ctl_reg(pcd, i));
+
+		if (pcd->in_ep[i].queue_sof) {
+			pcd->in_ep[i].queue_sof = 0;
+			start_next_request(&pcd->in_ep[i]);
+		}
+	}
+	spin_unlock_irqrestore(&pcd->lock, flags);
+}
+
+static struct tasklet_struct start_xfer_tasklet = {
+	.next = NULL,
+	.state = 0,
+	.count = ATOMIC_INIT(0),
+	.func = start_xfer_tasklet_func,
+	.data = 0,
+};
+
+/**
+ * This function initialized the pcd Dp structures to there default
+ * state.
+ */
+void __devinit dwc_otg_pcd_reinit(struct dwc_pcd *pcd)
+{
+	static const char *names[] = {
+		"ep0", "ep1in", "ep2in", "ep3in", "ep4in", "ep5in",
+		"ep6in", "ep7in", "ep8in", "ep9in", "ep10in", "ep11in",
+		"ep12in", "ep13in", "ep14in", "ep15in", "ep1out", "ep2out",
+		"ep3out", "ep4out", "ep5out", "ep6out", "ep7out", "ep8out",
+		"ep9out", "ep10out", "ep11out", "ep12out", "ep13out",
+		"ep14out", "ep15out"
+	};
+
+	u32 i;
+	int in_ep_cntr, out_ep_cntr;
+	u32 hwcfg1;
+	u32 num_in_eps = (GET_CORE_IF(pcd))->dev_if->num_in_eps;
+	u32 num_out_eps = (GET_CORE_IF(pcd))->dev_if->num_out_eps;
+	struct pcd_ep *ep;
+
+	INIT_LIST_HEAD(&pcd->gadget.ep_list);
+
+	pcd->gadget.ep0 = &pcd->ep0.ep;
+	pcd->gadget.speed = USB_SPEED_UNKNOWN;
+	INIT_LIST_HEAD(&pcd->gadget.ep0->ep_list);
+
+	/* Initialize the EP0 structure. */
+	ep = &pcd->ep0;
+
+	/* Init EP structure */
+	ep->desc = NULL;
+	ep->pcd = pcd;
+	ep->stopped = 1;
+
+	/* Init DWC ep structure */
+	ep->dwc_ep.num = 0;
+	ep->dwc_ep.active = 0;
+	ep->dwc_ep.tx_fifo_num = 0;
+
+	/* Control until ep is actvated */
+	ep->dwc_ep.type = DWC_OTG_EP_TYPE_CONTROL;
+	ep->dwc_ep.maxpacket = MAX_PACKET_SIZE;
+	ep->dwc_ep.dma_addr = 0;
+	ep->dwc_ep.start_xfer_buff = 0;
+	ep->dwc_ep.xfer_buff = 0;
+	ep->dwc_ep.xfer_len = 0;
+	ep->dwc_ep.xfer_count = 0;
+	ep->dwc_ep.sent_zlp = 0;
+	ep->dwc_ep.total_len = 0;
+	ep->queue_sof = 0;
+
+	/* Init the usb_ep structure. */
+	ep->ep.name = names[0];
+	ep->ep.ops = &dwc_otg_pcd_ep_ops;
+
+	ep->ep.maxpacket = MAX_PACKET_SIZE;
+	list_add_tail(&ep->ep.ep_list, &pcd->gadget.ep_list);
+	INIT_LIST_HEAD(&ep->queue);
+
+	/* Initialize the EP structures. */
+	in_ep_cntr = 0;
+	hwcfg1 = (GET_CORE_IF(pcd))->hwcfg1.d32 >> 3;
+
+	for (i = 1; in_ep_cntr < num_in_eps; i++) {
+		if (!(hwcfg1 & 0x1)) {
+			struct pcd_ep *ep = &pcd->in_ep[in_ep_cntr];
+			in_ep_cntr++;
+
+			/* Init EP structure */
+			ep->desc = NULL;
+			ep->pcd = pcd;
+			ep->stopped = 1;
+
+			/* Init DWC ep structure */
+			ep->dwc_ep.is_in = 1;
+			ep->dwc_ep.num = i;
+			ep->dwc_ep.active = 0;
+			ep->dwc_ep.tx_fifo_num = 0;
+
+			/* Control until ep is actvated */
+			ep->dwc_ep.type = DWC_OTG_EP_TYPE_CONTROL;
+			ep->dwc_ep.maxpacket = MAX_PACKET_SIZE;
+			ep->dwc_ep.dma_addr = 0;
+			ep->dwc_ep.start_xfer_buff = 0;
+			ep->dwc_ep.xfer_buff = 0;
+			ep->dwc_ep.xfer_len = 0;
+			ep->dwc_ep.xfer_count = 0;
+			ep->dwc_ep.sent_zlp = 0;
+			ep->dwc_ep.total_len = 0;
+			ep->queue_sof = 0;
+
+			ep->ep.name = names[i];
+			ep->ep.ops = &dwc_otg_pcd_ep_ops;
+
+			ep->ep.maxpacket = MAX_PACKET_SIZE;
+			list_add_tail(&ep->ep.ep_list, &pcd->gadget.ep_list);
+			INIT_LIST_HEAD(&ep->queue);
+		}
+		hwcfg1 >>= 2;
+	}
+
+	out_ep_cntr = 0;
+	hwcfg1 = (GET_CORE_IF(pcd))->hwcfg1.d32 >> 2;
+	for (i = 1; out_ep_cntr < num_out_eps; i++) {
+		if (!(hwcfg1 & 0x1)) {
+			struct pcd_ep *ep = &pcd->out_ep[out_ep_cntr];
+			out_ep_cntr++;
+
+			/* Init EP structure */
+			ep->desc = NULL;
+			ep->pcd = pcd;
+			ep->stopped = 1;
+
+			/* Init DWC ep structure */
+			ep->dwc_ep.is_in = 0;
+			ep->dwc_ep.num = i;
+			ep->dwc_ep.active = 0;
+			ep->dwc_ep.tx_fifo_num = 0;
+
+			/* Control until ep is actvated */
+			ep->dwc_ep.type = DWC_OTG_EP_TYPE_CONTROL;
+			ep->dwc_ep.maxpacket = MAX_PACKET_SIZE;
+			ep->dwc_ep.dma_addr = 0;
+			ep->dwc_ep.start_xfer_buff = 0;
+			ep->dwc_ep.xfer_buff = 0;
+			ep->dwc_ep.xfer_len = 0;
+			ep->dwc_ep.xfer_count = 0;
+			ep->dwc_ep.sent_zlp = 0;
+			ep->dwc_ep.total_len = 0;
+			ep->queue_sof = 0;
+
+			ep->ep.name = names[15 + i];
+			ep->ep.ops = &dwc_otg_pcd_ep_ops;
+
+			ep->ep.maxpacket = MAX_PACKET_SIZE;
+			list_add_tail(&ep->ep.ep_list, &pcd->gadget.ep_list);
+			INIT_LIST_HEAD(&ep->queue);
+		}
+		hwcfg1 >>= 2;
+	}
+
+	/* remove ep0 from the list.  There is a ep0 pointer. */
+	list_del_init(&pcd->ep0.ep.ep_list);
+
+	pcd->ep0state = EP0_DISCONNECT;
+	pcd->ep0.ep.maxpacket = MAX_EP0_SIZE;
+	pcd->ep0.dwc_ep.maxpacket = MAX_EP0_SIZE;
+	pcd->ep0.dwc_ep.type = DWC_OTG_EP_TYPE_CONTROL;
+}
+
+/**
+ * This function releases the Gadget device.
+ * required by device_unregister().
+ */
+static void dwc_otg_pcd_gadget_release(struct device *dev)
+{
+	printk(KERN_INFO "%s(%p)\n", __func__, dev);
+}
+
+/**
+ * Allocates the buffers for the setup packets when the PCD portion of the
+ * driver is first initialized.
+ */
+static int __devinit init_pkt_buffs(struct device *dev, struct dwc_pcd *pcd)
+{
+	if (pcd->otg_dev->core_if->dma_enable) {
+		pcd->dwc_pool = dma_pool_create("dwc_otg_pcd", dev,
+				sizeof(*pcd->setup_pkt) * 5, 32, 0);
+		if (!pcd->dwc_pool)
+			return -ENOMEM;
+		pcd->setup_pkt = dma_pool_alloc(pcd->dwc_pool, GFP_KERNEL,
+				&pcd->setup_pkt_dma_handle);
+		if (!pcd->setup_pkt)
+			goto error;
+		pcd->status_buf = dma_pool_alloc(pcd->dwc_pool, GFP_KERNEL,
+				&pcd->status_buf_dma_handle);
+		if (!pcd->status_buf)
+			goto error1;
+	} else {
+		pcd->setup_pkt =  kmalloc(sizeof(*pcd->setup_pkt) * 5,
+			GFP_KERNEL);
+		if (!pcd->setup_pkt)
+			return -ENOMEM;
+		pcd->status_buf = kmalloc(sizeof(u16), GFP_KERNEL);
+		if (!pcd->status_buf)  {
+			kfree(pcd->setup_pkt);
+			return -ENOMEM;
+		}
+	}
+	return 0;
+
+error1:
+	dma_pool_free(pcd->dwc_pool, pcd->setup_pkt, pcd->setup_pkt_dma_handle);
+error:
+	dma_pool_destroy(pcd->dwc_pool);
+	return -ENOMEM;
+}
+
+/**
+ * This function initializes the PCD portion of the driver.
+ */
+int __devinit dwc_otg_pcd_init(struct device *dev)
+{
+	static char pcd_name[] = "dwc_otg_pcd";
+	struct dwc_pcd *pcd;
+	struct dwc_otg_device *otg_dev = dev_get_drvdata(dev);
+	struct core_if *core_if = otg_dev->core_if;
+	int retval = 0;
+
+	/* Allocate PCD structure */
+	pcd = kzalloc(sizeof(*pcd), GFP_KERNEL);
+	if (!pcd) {
+		retval = -ENOMEM;
+		goto err;
+	}
+
+	spin_lock_init(&pcd->lock);
+
+	otg_dev->pcd = pcd;
+	s_pcd = pcd;
+	pcd->gadget.name = pcd_name;
+
+	dev_set_name(&pcd->gadget.dev, "gadget");
+	pcd->otg_dev = otg_dev;
+	pcd->gadget.dev.parent = dev;
+	pcd->gadget.dev.release = dwc_otg_pcd_gadget_release;
+	pcd->gadget.ops = &dwc_otg_pcd_ops;
+
+	if (core_if->hwcfg4.b.ded_fifo_en)
+		printk(KERN_INFO "Dedicated Tx FIFOs mode\n");
+	else
+		printk(KERN_INFO "Shared Tx FIFO mode\n");
+
+	pcd->gadget.is_dualspeed = check_is_dual_speed(core_if);
+	pcd->gadget.is_otg = check_is_otg(core_if);
+
+	/* Register the gadget device */
+	retval = device_register(&pcd->gadget.dev);
+
+	/* Initialized the Core for Device mode. */
+	if (dwc_otg_is_device_mode(core_if))
+		dwc_otg_core_dev_init(core_if);
+
+	/*  Initialize EP structures */
+	dwc_otg_pcd_reinit(pcd);
+
+	/* Register the PCD Callbacks. */
+	dwc_otg_cil_register_pcd_callbacks(core_if, &pcd_callbacks, pcd);
+
+	/* Setup interupt handler */
+	retval = request_irq(otg_dev->irq, dwc_otg_pcd_irq, IRQF_SHARED,
+				pcd->gadget.name, pcd);
+	if (retval) {
+		printk(KERN_ERR "request of irq%d failed\n", otg_dev->irq);
+		retval = -EBUSY;
+		goto err_cleanup;
+	}
+
+	/* Initialize the DMA buffer for SETUP packets */
+	retval = init_pkt_buffs(dev, pcd);
+	if (retval)
+		goto err_cleanup;
+
+	/* Initialize tasklet */
+	start_xfer_tasklet.data = (unsigned long) pcd;
+	pcd->start_xfer_tasklet = &start_xfer_tasklet;
+	return 0;
+
+err_cleanup:
+	kfree(pcd);
+	otg_dev->pcd = 0;
+	s_pcd = 0;
+
+err:
+	return retval;
+}
+
+/**
+ * Cleanup the PCD.
+ */
+void __devexit dwc_otg_pcd_remove(struct device *dev)
+{
+	struct dwc_otg_device *otg_dev = dev_get_drvdata(dev);
+	struct dwc_pcd *pcd = otg_dev->pcd;
+
+	/* Free the IRQ */
+	free_irq(otg_dev->irq, pcd);
+
+	/* start with the driver above us */
+	if (pcd->driver) {
+		/* should have been done already by driver model core */
+		printk(KERN_WARNING "driver '%s' is still registered\n",
+				pcd->driver->driver.name);
+		usb_gadget_unregister_driver(pcd->driver);
+	}
+	if (pcd->start_xfer_tasklet)
+		tasklet_kill(pcd->start_xfer_tasklet);
+	tasklet_kill(&pcd->test_mode_tasklet);
+
+	device_unregister(&pcd->gadget.dev);
+	if (GET_CORE_IF(pcd)->dma_enable) {
+		dma_pool_free(pcd->dwc_pool, pcd->setup_pkt,
+				pcd->setup_pkt_dma_handle);
+		dma_pool_free(pcd->dwc_pool, pcd->status_buf,
+				pcd->status_buf_dma_handle);
+		dma_pool_destroy(pcd->dwc_pool);
+	} else {
+		kfree(pcd->setup_pkt);
+		kfree(pcd->status_buf);
+	}
+	kfree(pcd);
+	otg_dev->pcd = 0;
+}
+
+/**
+ * This function registers a gadget driver with the PCD.
+ *
+ * When a driver is successfully registered, it will receive control
+ * requests including set_configuration(), which enables non-control
+ * requests.  then usb traffic follows until a disconnect is reported.
+ * then a host may connect again, or the driver might get unbound.
+ */
+int usb_gadget_register_driver(struct usb_gadget_driver *driver)
+{
+	int retval;
+
+	if (!driver || driver->speed == USB_SPEED_UNKNOWN || !driver->bind ||
+			!driver->unbind || !driver->disconnect ||
+			!driver->setup)
+		return -EINVAL;
+
+	if (s_pcd == 0)
+		return -ENODEV;
+
+	if (s_pcd->driver != 0)
+		return -EBUSY;
+
+	/* hook up the driver */
+	s_pcd->driver = driver;
+	s_pcd->gadget.dev.driver = &driver->driver;
+
+	retval = driver->bind(&s_pcd->gadget);
+	if (retval) {
+		struct core_if *core_if;
+		printk(KERN_ERR "bind to driver %s --> error %d\n",
+			driver->driver.name, retval);
+		core_if = s_pcd->otg_dev->core_if;
+		otg_set_peripheral(core_if->xceiv, &s_pcd->gadget);
+		s_pcd->driver = 0;
+		s_pcd->gadget.dev.driver = 0;
+		return retval;
+	}
+	return 0;
+}
+EXPORT_SYMBOL(usb_gadget_register_driver);
+
+/**
+ * This function unregisters a gadget driver
+ */
+int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
+{
+	struct core_if *core_if;
+
+	if (!s_pcd)
+		return -ENODEV;
+	if (!driver || driver != s_pcd->driver)
+		return -EINVAL;
+
+	core_if = s_pcd->otg_dev->core_if;
+	core_if->xceiv->state = OTG_STATE_UNDEFINED;
+	otg_set_peripheral(core_if->xceiv, NULL);
+
+	driver->unbind(&s_pcd->gadget);
+	s_pcd->driver = 0;
+
+	return 0;
+}
+EXPORT_SYMBOL(usb_gadget_unregister_driver);
drivers/usb/dwc_otg/dwc_otg_pcd.h new file +149 -0

149 lines not on this page · raw message

drivers/usb/dwc_otg/dwc_otg_pcd_intr.c new file +2270 -0

1,103 lines not on this page · raw message

drivers/usb/gadget/Kconfig +21 -0
index dd3b251..714d521 100644

Lines of this file are not shown. View the raw message.

drivers/usb/gadget/gadget_chips.h +7 -0
index e511fec..e190844 100644

Lines of this file are not shown. View the raw message.

The rest of this diff is not shown. View the raw message.

Signature · 1 line
1.7.1

Part of the diff is not shown here. View the raw message.

#2 lore raw
In reply to Fushen Chen
Quoted 5 lines · Fushen Chen

This adds support for the USB host controller on APM SoC using Synopsys Designware IP.

Can I get some acks from the other developers who have worked on this driver to verify that this version does indeed work, and that their work has been integrated properly into the driver?

Quoted 5 lines
drivers/usb/dwc_otg/dwc_otg_apmppc.c new file +2 -0
@@ -0,0 +1,408 @@
+/*
+ * DesignWare HS OTG controller driver

drivers/usb/dwc_otg/dwc_otg_apmppc.c line 12

Quoted 10 lines
drivers/usb/dwc_otg/dwc_otg_apmppc.c new file +10 -0
+ *
+ * Author: Mark Miesfeld <[email protected]>
+ *
+ * Based on versions provided by APM and Synopsis which are:
+ *	Copyright (C) 2009-2010 AppliedMicro(www.apm.com)
+ * Modified by Stefan Roese <[email protected]>, DENX Software Engineering
+ *
+ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
+ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
+ * otherwise expressly agreed to in writing between Synopsys and you.

WTF?

Um, I think someone needs to rethink this submission, as this really doesn't look like GPL code...

Oh, and where do I go get that "writing" between me and Synopsys to fix this up? :)

drivers/usb/dwc_otg/dwc_otg_apmppc.c line 22

Quoted 9 lines
drivers/usb/dwc_otg/dwc_otg_apmppc.c new file +9 -0
+ * The Software IS NOT an item of Licensed Software or Licensed Product under
+ * any End User Software License Agreement or Agreement for Licensed Product
+ * with Synopsys or any supplement thereto. You are permitted to use and
+ * redistribute this Software in source and binary forms, with or without
+ * modification, provided that redistributions of source code must retain this
+ * notice. You may not view, use, disclose, copy or distribute this file or
+ * any information contained herein except pursuant to this license grant from
+ * Synopsys. If you do not agree with this notice, including the disclaimer
+ * below, then you are not authorized to use the Software.

Same here, what is going on?

Has someone run this through the proper legal approval to make public? If so, someone needs to go kick a lawyer. If not, they just got in big trouble...

Quoted 14 lines
drivers/usb/dwc_otg/dwc_otg_apmppc.c new file +14 -0
+ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as

drivers/usb/dwc_otg/dwc_otg_apmppc.c line 47

Quoted 10 lines
drivers/usb/dwc_otg/dwc_otg_apmppc.c new file +10 -0
+ * published by the Free Software Foundation.
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.

It's fun to just tack on the GPL boilerplate on a file, but when it conflicts with other stuff in the same file, it kind of just makes us all go crazy.

I can't take this at all, please go clean it up.

ick,

greg k-h

#3 lore raw

On 07/26/2010 02:37 PM, Greg KH wrote:
[...]

Quoted 13 lines
Quoted 4 lines

+/*
+ * DesignWare HS OTG controller driver
+ *
+ * Author: Mark Miesfeld<[email protected]>

Quoted 8 lines

+ *
+ * Based on versions provided by APM and Synopsis which are:
+ * Copyright (C) 2009-2010 AppliedMicro(www.apm.com)
+ * Modified by Stefan Roese<[email protected]>, DENX Software Engineering
+ *
+ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
+ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
+ * otherwise expressly agreed to in writing between Synopsys and you.

Quoted 2 lines

WTF?

I was not involved with this version of the patch, but is it really that bad?

Quoted 16 lines

Um, I think someone needs to rethink this submission, as this really doesn't look like GPL code...

Oh, and where do I go get that "writing" between me and Synopsys to fix this up? :)

Quoted 9 lines

+ * The Software IS NOT an item of Licensed Software or Licensed Product under
+ * any End User Software License Agreement or Agreement for Licensed Product
+ * with Synopsys or any supplement thereto. You are permitted to use and
+ * redistribute this Software in source and binary forms, with or without
+ * modification, provided that redistributions of source code must retain this
+ * notice. You may not view, use, disclose, copy or distribute this file or
+ * any information contained herein except pursuant to this license grant from
+ * Synopsys. If you do not agree with this notice, including the disclaimer
+ * below, then you are not authorized to use the Software.

Quoted 1 line

Same here, what is going on?

First of all, I am not a Lawyer, so take this with a grain of salt if you wish.

How is this different than a 3-clause BSD License? There are other instances of BSD Licensed code in the kernel (see include/linux/quota.h for example).

Quoted 31 lines

Has someone run this through the proper legal approval to make public? If so, someone needs to go kick a lawyer. If not, they just got in big trouble...

Quoted 16 lines

+ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *

Quoted 8 lines

+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.

Quoted 4 lines

It's fun to just tack on the GPL boilerplate on a file, but when it conflicts with other stuff in the same file, it kind of just makes us all go crazy.

Indeed that part does seem questionable. Could it be used with the original Synopsys license, without tacking on this GPL bit?

David Daney

#4 lore raw
Quoted 15 lines · David Daney

On 07/26/2010 02:37 PM, Greg KH wrote:
[...]

Quoted 13 lines
Quoted 12 lines

+/*
+ * DesignWare HS OTG controller driver
+ *
+ * Author: Mark Miesfeld<[email protected]>
+ *
+ * Based on versions provided by APM and Synopsis which are:
+ * Copyright (C) 2009-2010 AppliedMicro(www.apm.com)
+ * Modified by Stefan Roese<[email protected]>, DENX Software Engineering
+ *
+ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
+ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
+ * otherwise expressly agreed to in writing between Synopsys and you.

Quoted 5 lines
Quoted 2 lines

WTF?

I was not involved with this version of the patch, but is it really that bad?

You tell me, how does that interact with the GPL?

Do you want to be in charge of getting that "approval in writing" from every single user of Linux and Synopsys so that this is somehow not a "proprietary work of Synopsys, Inc."?

Quoted 16 lines
Quoted 16 lines

Um, I think someone needs to rethink this submission, as this really doesn't look like GPL code...

Oh, and where do I go get that "writing" between me and Synopsys to fix this up? :)

Quoted 9 lines

+ * The Software IS NOT an item of Licensed Software or Licensed Product under
+ * any End User Software License Agreement or Agreement for Licensed Product
+ * with Synopsys or any supplement thereto. You are permitted to use and
+ * redistribute this Software in source and binary forms, with or without
+ * modification, provided that redistributions of source code must retain this
+ * notice. You may not view, use, disclose, copy or distribute this file or
+ * any information contained herein except pursuant to this license grant from
+ * Synopsys. If you do not agree with this notice, including the disclaimer
+ * below, then you are not authorized to use the Software.

Quoted 8 lines
Quoted 1 line

Same here, what is going on?

First of all, I am not a Lawyer, so take this with a grain of salt if you wish.

How is this different than a 3-clause BSD License? There are other instances of BSD Licensed code in the kernel (see include/linux/quota.h for example).

That's wonderful, then license it under the 3-clause BSD license. Don't make up something else :)

If that's what is happening here, then document it as such.

Quoted 30 lines
Quoted 30 lines

Has someone run this through the proper legal approval to make public? If so, someone needs to go kick a lawyer. If not, they just got in big trouble...

Quoted 24 lines

+ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.

Quoted 7 lines
Quoted 4 lines

It's fun to just tack on the GPL boilerplate on a file, but when it conflicts with other stuff in the same file, it kind of just makes us all go crazy.

Indeed that part does seem questionable. Could it be used with the original Synopsys license, without tacking on this GPL bit?

Um, no.

Please, someone needs to go run this past the Synopsys lawyers (yeah, sorry, that's horrible to do, but it needs to be done to get it correct.)

Because of this, I'd like to get a lawyer's signed-off-by on the code as well just to verify that it's all ok.

Yes, that's a pain, but we gotta make sure that everyone involved knows _exactly_ what is going on here, and this mess of header garbage shows that no one knows what is happening.

thanks,

greg k-h

#5 lore raw
Quoted 6 lines · Greg KH

Please, someone needs to go run this past the Synopsys lawyers (yeah, sorry, that's horrible to do, but it needs to be done to get it correct.)

Because of this, I'd like to get a lawyer's signed-off-by on the code as well just to verify that it's all ok.

Or someone with the legal authority to verify that this is an action that Synopsys agrees with the license of the code now. This usually means a VP or some such person that can act publicly for the company.

thanks,

greg k-h

#6 lore raw

Hi Greg:

We are having our legal revisit this again. What would you advise us to do at this
point? Disclose the agreement or have someone with legal authority reply this thread.
Perhaps something in the header that states Applied Micro verified with Synopsys
to use this code for GPL purpose.

Feng Kan

Quoted 20 lines · Greg KH
Quoted 6 lines · Greg KH

Please, someone needs to go run this past the Synopsys lawyers (yeah, sorry, that's horrible to do, but it needs to be done to get it correct.)

Because of this, I'd like to get a lawyer's signed-off-by on the code as well just to verify that it's all ok.

Or someone with the legal authority to verify that this is an action that Synopsys agrees with the license of the code now. =C2=A0This usually means a VP or some such person that can act publicly for the company.

thanks,

greg k-h
_______________________________________________
Linuxppc-dev mailing list
[email protected]
https://lists.ozlabs.org/listinfo/linuxppc-dev

#7 lore raw
Quoted 4 lines · Feng Kan

Hi Greg:

We are having our legal revisit this again. What would you advise us to do at this point?

I thought I was very clear below as to what is needed.

Quoted 2 lines

Disclose the agreement or have someone with legal authority reply this thread.

Neither will resolve the end issue, right?

Quoted 2 lines

Perhaps something in the header that states Applied Micro verified with Synopsys to use this code for GPL purpose.

No, that will just make it messier. Someone needs to delete all of the mess in the file, put the proper license information for what the code is being licensed under (whatever it is), and provide a signed-off-by from a person from Synopsys and APM that can speak for the company that they agree that the code can properly be placed into the Linux kernel.

thanks,

greg k-h

#8 lore raw

Hi Greg:

We will change to a BSD 3 clause license header. Our legal counsel is talking to Synopsis to make this change. We will resubmit once this is in place. Please let me know if you have any additional concerns.

Feng Kan
Applied Micro

Quoted 11 lines · Greg KH
Quoted 4 lines · Feng Kan

Hi Greg:

We are having our legal revisit this again. What would you advise us to do at this point?

I thought I was very clear below as to what is needed.

Quoted 2 lines

Disclose the agreement or have someone with legal authority reply this thread.

Quoted 6 lines

Neither will resolve the end issue, right?

Quoted 2 lines

Perhaps something in the header that states Applied Micro verified with Synopsys to use this code for GPL purpose.

No, that will just make it messier. =C2=A0Someone needs to delete all of =

the

Quoted 9 lines

mess in the file, put the proper license information for what the code is being licensed under (whatever it is), and provide a signed-off-by from a person from Synopsys and APM that can speak for the company that they agree that the code can properly be placed into the Linux kernel.

thanks,

greg k-h

--=20
Feng Kan

#9 lore raw
Quoted 4 lines · Feng Kan

Hi Greg:

We will change to a BSD 3 clause license header. Our legal counsel is talking to Synopsis to make this change.

Why BSD? You do realize what that means when combined within the body of the kernel, right?

Are you going to be expecting others to contribute back to the code under this license, or will you accept the fact that future contributions from the community will cause the license to change?

Quoted 2 lines

We will resubmit once this is in place. Please let me know if you have any additional concerns.

My main concern is that you, and everyone else involved in the driver, never considered the license of the code in the first place and expected the kernel community to accept it as-is, placing the problem on us.

What will be done in the future to prevent this from happening again?

thanks,

greg k-h

#10 lore raw

Hi Greg:

Quoted 7 lines · Greg KH
Quoted 4 lines · Feng Kan

Hi Greg:

We will change to a BSD 3 clause license header. Our legal counsel is talking to Synopsis to make this change.

Why BSD? =C2=A0You do realize what that means when combined within the bo=

dy

Quoted 2 lines

of the kernel, right?

FKAN: We will shoot for a dual BSD/GPL license such as the one in the HP
Hil driver.

Quoted 10 lines

Are you going to be expecting others to contribute back to the code under this license, or will you accept the fact that future contributions from the community will cause the license to change?

Quoted 2 lines

We will resubmit once this is in place. Please let me know if you have any additional concerns.

My main concern is that you, and everyone else involved in the driver, never considered the license of the code in the first place and expected the kernel community to accept it as-is, placing the problem on us.

FKAN: Please don't think this is the case, we gone through this exercise
with Denx. We had legal looking into the header before submission to them and the kernel.

Quoted 2 lines

What will be done in the future to prevent this from happening again?

FKAN: agreed, once bitten .... :)

Quoted 5 lines

thanks,

greg k-h

--=20
Feng Kan

#11 lore raw
Quoted 9 lines · Feng Kan

Hi Greg:

Quoted 6 lines · Greg KH
Quoted 4 lines · Feng Kan

Hi Greg:

We will change to a BSD 3 clause license header. Our legal counsel is talking to Synopsis to make this change.

Quoted 6 lines
Quoted 3 lines

Why BSD?  You do realize what that means when combined within the body of the kernel, right?

FKAN: We will shoot for a dual BSD/GPL license such as the one in the HP
Hil driver.

What specific driver is this?

And are you sure that all of the contributors to the code agree with this licensing change? Are you going to require contributors to dual-license their changes?

If so, why keep it BSD, what does that get you?

Quoted 3 lines
Quoted 3 lines

Are you going to be expecting others to contribute back to the code under this license, or will you accept the fact that future contributions from the community will cause the license to change?

You didn't answer this question, which is a very important one before I can accept this driver.

Quoted 9 lines
Quoted 6 lines
Quoted 2 lines

We will resubmit once this is in place. Please let me know if you have any additional concerns.

My main concern is that you, and everyone else involved in the driver, never considered the license of the code in the first place and expected the kernel community to accept it as-is, placing the problem on us.

FKAN: Please don't think this is the case, we gone through this exercise
with Denx.

What is "Denx"?

Quoted 2 lines

We had legal looking into the header before submission
to them and the kernel.

Then what happened here? Just curious as to how the driver was public for so long before someone realized this.

Quoted 3 lines
Quoted 1 line

What will be done in the future to prevent this from happening again?

FKAN: agreed, once bitten .... :)

That didn't answer the question :)

thanks,

greg k-h

#12 lore raw
Quoted 11 lines · Greg KH
Quoted 10 lines · Feng Kan

Hi Greg:

Quoted 7 lines · Greg KH
Quoted 4 lines · Feng Kan

Hi Greg:

We will change to a BSD 3 clause license header. Our legal counsel is talking to Synopsis to make this change.

Why BSD? =C2=A0You do realize what that means when combined within the=

body

Quoted 7 lines
Quoted 5 lines
Quoted 2 lines

of the kernel, right?

FKAN: We will shoot for a dual BSD/GPL license such as the one in the HP =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0Hil driver.

What specific driver is this?

FKAN: this is driver/input/serio/hil_mlc.c and quite a number of others.

Quoted 6 lines

And are you sure that all of the contributors to the code agree with this licensing change? =C2=A0Are you going to require contributors to dual-license their changes?

If so, why keep it BSD, what does that get you?

FKAN: for one thing, to make it future proof on other submissions.

Quoted 8 lines
Quoted 4 lines
Quoted 4 lines

Are you going to be expecting others to contribute back to the code under this license, or will you accept the fact that future contributions from the community will cause the license to change?

You didn't answer this question, which is a very important one before I can accept this driver.

FKAN: Yes, all of the above. Our legal is working on that. I thought by def= ault
GPL defines the above statement.

Quoted 2 lines
Quoted 2 lines
Quoted 2 lines
Quoted 2 lines

We will resubmit once this is in place. Please let me know if you hav=

e

Quoted 4 lines
Quoted 4 lines
Quoted 4 lines
Quoted 1 line

any additional concerns.

My main concern is that you, and everyone else involved in the driver, never considered the license of the code in the first place and expect=

ed

Quoted 6 lines
Quoted 4 lines
Quoted 1 line

the kernel community to accept it as-is, placing the problem on us.

FKAN: Please don't think this is the case, we gone through this exercise =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 with Denx.

What is "Denx"?

FKAN: U-Boot Denx.de

Quoted 5 lines
Quoted 3 lines

We had legal looking into the header before submission =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 to them and the kernel.

Then what happened here? =C2=A0Just curious as to how the driver was publ=

ic

Quoted 2 lines

for so long before someone realized this.

FKAN: this was few years back. At the time we had the header changed
so it was BSD like to be accepted by Denx.

Quoted 5 lines
Quoted 3 lines
Quoted 1 line

What will be done in the future to prevent this from happening again?

FKAN: agreed, once bitten .... :)

That didn't answer the question :)

FKAN: we have a system of checks for every patch that goes out. I will send
out a guideline to all reviewer to make sure the header
follow kernel precedence.
Legal is quite aware of the issue now too.

Quoted 5 lines

thanks,

greg k-h

--=20
Feng Kan

#13 lore raw
Quoted 15 lines · Feng Kan
Quoted 14 lines · Greg KH
Quoted 13 lines · Feng Kan

Hi Greg:

Quoted 9 lines · Greg KH
Quoted 4 lines · Feng Kan

Hi Greg:

We will change to a BSD 3 clause license header. Our legal counsel is talking to Synopsis to make this change.

Why BSD? ??You do realize what that means when combined within the body of the kernel, right?

Quoted 6 lines
Quoted 4 lines
Quoted 2 lines

FKAN: We will shoot for a dual BSD/GPL license such as the one in the HP ?? ?? ?? ?? ?? ??Hil driver.

What specific driver is this?

FKAN: this is driver/input/serio/hil_mlc.c and quite a number of others.

Ok, thanks.

Are you _sure_ that you didn't take any existing GPL code and put it into this driver when making it? Did all contributors to the code release their contributions under both licenses?

Quoted 7 lines
Quoted 5 lines

And are you sure that all of the contributors to the code agree with this licensing change? ??Are you going to require contributors to dual-license their changes?

If so, why keep it BSD, what does that get you?

FKAN: for one thing, to make it future proof on other submissions.

What do you mean by this? What can you do with this code other than use it on a Linux system? You can't put it into any other operating system with a different license, can you?

Quoted 10 lines
Quoted 7 lines
Quoted 3 lines
Quoted 3 lines

Are you going to be expecting others to contribute back to the code under this license, or will you accept the fact that future contributions from the community will cause the license to change?

You didn't answer this question, which is a very important one before I can accept this driver.

FKAN: Yes, all of the above. Our legal is working on that. I thought by default
GPL defines the above statement.

The GPL does, but as you are trying to dual-license the code, you have to be careful about how you accept changes, and under what license. It's a lot more work than I think you realize. What process do you have in place to handle this?

Quoted 7 lines
Quoted 7 lines
Quoted 7 lines
Quoted 6 lines
Quoted 2 lines

We will resubmit once this is in place. Please let me know if you have any additional concerns.

My main concern is that you, and everyone else involved in the driver, never considered the license of the code in the first place and expected the kernel community to accept it as-is, placing the problem on us.

Quoted 6 lines
Quoted 4 lines
Quoted 2 lines

FKAN: Please don't think this is the case, we gone through this exercise ?? ?? ?? ?? ?? with Denx.

What is "Denx"?

FKAN: U-Boot Denx.de

Ah, thanks.

Quoted 12 lines
Quoted 6 lines
Quoted 2 lines

We had legal looking into the header before submission ?? ?? ?? ?? ?? to them and the kernel.

Then what happened here? ??Just curious as to how the driver was public for so long before someone realized this.

FKAN: this was few years back. At the time we had the header changed
so it was BSD like to be accepted by Denx.

Quoted 2 lines
Quoted 2 lines
Quoted 1 line

What will be done in the future to prevent this from happening again?

Quoted 7 lines
Quoted 3 lines
Quoted 1 line

FKAN: agreed, once bitten .... :)

That didn't answer the question :)

FKAN: we have a system of checks for every patch that goes out. I will send
out a guideline to all reviewer to make sure the header
follow kernel precedence.

But you took this code from a different vendor, are you able to properly identify the code contributions to this base and what license it is under and where they got it from?

Quoted 1 line

Legal is quite aware of the issue now too.

As they should be :)

Please reconsider the dual licensing unless you really are ready to handle the implications of it.

thanks,

greg k-h

#14 lore raw

Hi Greg:

We have obtained GPL 2 only header from Synopsis. We have also identified a= ll
parties that contributed to the code base and contacted them regarding license change.
Any party that we could not reach, we will remove the patch from the submis= sion.
Let me know if this is sufficient for resubmission.

Thanks
Feng

Quoted 10 lines · Greg KH
Quoted 9 lines · Feng Kan
Quoted 8 lines · Greg KH
Quoted 7 lines · Feng Kan

Hi Greg:

Quoted 4 lines · Greg KH
Quoted 3 lines · Feng Kan

Hi Greg:

We will change to a BSD 3 clause license header. Our legal counsel=

is

Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 1 line

talking to Synopsis to make this change.

Why BSD? ??You do realize what that means when combined within the =

body

Quoted 4 lines
Quoted 4 lines
Quoted 4 lines
Quoted 4 lines
Quoted 2 lines

of the kernel, right?

FKAN: We will shoot for a dual BSD/GPL license such as the one in the=

HP

Quoted 16 lines
Quoted 5 lines
Quoted 3 lines
Quoted 1 line

?? ?? ?? ?? ?? ??Hil driver.

What specific driver is this?

FKAN: this is driver/input/serio/hil_mlc.c and quite a number of others.

Ok, thanks.

Are you _sure_ that you didn't take any existing GPL code and put it into this driver when making it? =C2=A0Did all contributors to the code release their contributions under both licenses?

Quoted 4 lines
Quoted 4 lines

And are you sure that all of the contributors to the code agree with this licensing change? ??Are you going to require contributors to dual-license their changes?

Quoted 5 lines
Quoted 3 lines
Quoted 1 line

If so, why keep it BSD, what does that get you?

FKAN: for one thing, to make it future proof on other submissions.

What do you mean by this? =C2=A0What can you do with this code other than=

use

Quoted 1 line

it on a Linux system? =C2=A0You can't put it into any other operating sys=

tem

Quoted 8 lines

with a different license, can you?

Quoted 6 lines
Quoted 6 lines
Quoted 3 lines
Quoted 3 lines

Are you going to be expecting others to contribute back to the code under this license, or will you accept the fact that future contributions from the community will cause the license to change?

You didn't answer this question, which is a very important one before =

I

Quoted 3 lines
Quoted 3 lines
Quoted 1 line

can accept this driver.

FKAN: Yes, all of the above. Our legal is working on that. I thought by =

default

Quoted 1 line
Quoted 1 line

=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0GPL defines the above statement=

.

Quoted 4 lines

The GPL does, but as you are trying to dual-license the code, you have to be careful about how you accept changes, and under what license. It's a lot more work than I think you realize. =C2=A0What process do you =

have

Quoted 3 lines

in place to handle this?

Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line

We will resubmit once this is in place. Please let me know if you =

have

Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 1 line

any additional concerns.

My main concern is that you, and everyone else involved in the driv=

er,

Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line

never considered the license of the code in the first place and exp=

ected

Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 1 line

the kernel community to accept it as-is, placing the problem on us.

FKAN: Please don't think this is the case, we gone through this exerc=

ise

Quoted 12 lines
Quoted 5 lines
Quoted 3 lines
Quoted 1 line

?? ?? ?? ?? ?? with Denx.

What is "Denx"?

FKAN: U-Boot Denx.de

Ah, thanks.

Quoted 4 lines
Quoted 4 lines
Quoted 2 lines

We had legal looking into the header before submission ?? ?? ?? ?? ?? to them and the kernel.

Then what happened here? ??Just curious as to how the driver was publi=

c

Quoted 4 lines
Quoted 4 lines
Quoted 2 lines

for so long before someone realized this.

FKAN: =C2=A0this was few years back. At the time we had the header chang=

ed

Quoted 1 line
Quoted 1 line

=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0so it was BSD like to be accept=

ed by Denx.

Quoted 2 lines
Quoted 2 lines
Quoted 2 lines
Quoted 2 lines
Quoted 2 lines

What will be done in the future to prevent this from happening agai=

n?

Quoted 6 lines
Quoted 6 lines
Quoted 4 lines
Quoted 2 lines

FKAN: agreed, once bitten .... :)

That didn't answer the question :)

FKAN: we have a system of checks for every patch that goes out. I will s=

end

Quoted 1 line
Quoted 1 line

=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0out a guideline to all reviewer=

to make sure the header

Quoted 7 lines
Quoted 1 line

follow kernel precedence.

But you took this code from a different vendor, are you able to properly identify the code contributions to this base and what license it is under and where they got it from?

Quoted 1 line

=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0Legal is quite aware of the iss=

ue now too.

Quoted 10 lines

As they should be :)

Please reconsider the dual licensing unless you really are ready to handle the implications of it.

thanks,

greg k-h

#15 lore raw
Quoted 7 lines · Feng Kan

Hi Greg:

We have obtained GPL 2 only header from Synopsis. We have also identified all parties that contributed to the code base and contacted them regarding license change.
Any party that we could not reach, we will remove the patch from the submission. Let me know if this is sufficient for resubmission.

Yes, that sounds fine, thanks for doing that work.

greg k-h