aboutsummaryrefslogtreecommitdiff
path: root/drivers/usb
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/core/message.c14
-rw-r--r--drivers/usb/core/usb.c2
-rw-r--r--drivers/usb/gadget/dwc_otg/dwc_otg_cil.c14
-rw-r--r--drivers/usb/gadget/dwc_otg/dwc_otg_cil.c.org3237
-rw-r--r--drivers/usb/gadget/dwc_otg/dwc_otg_hcd.c138
-rw-r--r--drivers/usb/gadget/dwc_otg/dwc_otg_hcd.c.org2900
-rw-r--r--drivers/usb/gadget/dwc_otg/dwc_otg_hcd.h31
-rw-r--r--drivers/usb/gadget/dwc_otg/dwc_otg_hcd.h.org660
-rw-r--r--drivers/usb/gadget/dwc_otg/dwc_otg_hcd_intr.c48
-rw-r--r--drivers/usb/gadget/dwc_otg/dwc_otg_hcd_intr.c.org1746
-rw-r--r--drivers/usb/gadget/dwc_otg/dwc_otg_hcd_queue.c233
-rw-r--r--drivers/usb/gadget/dwc_otg/dwc_otg_hcd_queue.c.org696
-rw-r--r--drivers/usb/gadget/dwc_otg/dwc_otg_pcd.c13
-rw-r--r--drivers/usb/gadget/dwc_otg/dwc_otg_pcd.c.org1408
-rw-r--r--drivers/usb/gadget/dwc_otg/linux/dwc_otg_plat.h4
-rw-r--r--drivers/usb/gadget/dwc_otg/linux/dwc_otg_plat.h.org304
-rw-r--r--drivers/usb/gadget/dwc_otg/ppc4xx_dma.h2
-rw-r--r--drivers/usb/gadget/dwc_otg/ppc4xx_dma.h.org620
-rw-r--r--drivers/usb/gadget/dwc_otg/sdiff/dwc_otg_hcd.c.sdiff2944
-rw-r--r--drivers/usb/gadget/dwc_otg/sdiff/dwc_otg_hcd.h.sdiff675
-rw-r--r--drivers/usb/gadget/dwc_otg/sdiff/dwc_otg_hcd_intr.c.sdiff1763
-rw-r--r--drivers/usb/gadget/dwc_otg/sdiff/dwc_otg_hcd_queue.c.sdiff821
22 files changed, 18100 insertions, 173 deletions
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
index 980a8d27fa5..5f7ae254f0b 100644
--- a/drivers/usb/core/message.c
+++ b/drivers/usb/core/message.c
@@ -1185,13 +1185,6 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0)
{
int i;
- dev_dbg(&dev->dev, "%s nuking %s URBs\n", __func__,
- skip_ep0 ? "non-ep0" : "all");
- for (i = skip_ep0; i < 16; ++i) {
- usb_disable_endpoint(dev, i, true);
- usb_disable_endpoint(dev, i + USB_DIR_IN, true);
- }
-
/* getting rid of interfaces will disconnect
* any drivers bound to them (a key side effect)
*/
@@ -1221,6 +1214,13 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0)
if (dev->state == USB_STATE_CONFIGURED)
usb_set_device_state(dev, USB_STATE_ADDRESS);
}
+
+ dev_dbg(&dev->dev, "%s nuking %s URBs\n", __func__,
+ skip_ep0 ? "non-ep0" : "all");
+ for (i = skip_ep0; i < 16; ++i) {
+ usb_disable_endpoint(dev, i, true);
+ usb_disable_endpoint(dev, i + USB_DIR_IN, true);
+ }
}
/**
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
index ab2d3e7c3f2..7d6510a0895 100644
--- a/drivers/usb/core/usb.c
+++ b/drivers/usb/core/usb.c
@@ -448,6 +448,8 @@ struct usb_device *usb_alloc_dev(struct usb_device *parent,
return dev;
}
+
+EXPORT_SYMBOL_GPL(usb_alloc_dev);
/**
* usb_get_dev - increments the reference count of the usb device structure
* @dev: the device being referenced
diff --git a/drivers/usb/gadget/dwc_otg/dwc_otg_cil.c b/drivers/usb/gadget/dwc_otg/dwc_otg_cil.c
index 61a8879fc10..1ba37fe7eba 100644
--- a/drivers/usb/gadget/dwc_otg/dwc_otg_cil.c
+++ b/drivers/usb/gadget/dwc_otg/dwc_otg_cil.c
@@ -1838,7 +1838,7 @@ void ppc4xx_start_plb_dma(dwc_otg_core_if_t *_core_if, void *src, void *dst, uns
mtdcr(DCRN_DMACR0 + (dma_ch * 8), control);
-#ifdef OTG_PLB_DMA_DBG
+#ifdef CONFIG_OTG_PLB_DMA_DBG
ppc4xx_dump_dma(dma_ch);
#endif
ppc4xx_enable_dma(dma_ch);
@@ -1917,7 +1917,7 @@ void dwc_otg_hc_write_packet(dwc_otg_core_if_t * _core_if, dwc_hc_t * _hc)
while (mfdcr(DCRN_DMACR0 + (PLB_DMA_CH*8)) & DMA_CE_ENABLE) {
}
dma_sts = (uint32_t)ppc4xx_get_dma_status();
-#ifdef OTG_PLB_DMA_DBG
+#ifdef CONFIG_OTG_PLB_DMA_DBG
if (!(dma_sts & DMA_CS0)) {
printk("Status (Terminal Count not occured) 0x%08x\n", mfdcr(DCRN_DMASR));
}
@@ -1926,7 +1926,7 @@ void dwc_otg_hc_write_packet(dwc_otg_core_if_t * _core_if, dwc_hc_t * _hc)
printk("Status (Channel Error) 0x%08x\n", mfdcr(DCRN_DMASR));
}
ppc4xx_clr_dma_status(PLB_DMA_CH);
-#ifdef OTG_PLB_DMA_DBG
+#ifdef CONFIG_OTG_PLB_DMA_DBG
printk("%32s DMA Status =0x%08x\n", __FUNCTION__, mfdcr(DCRN_DMASR)); /* vj_dbg */
#endif
@@ -2687,7 +2687,7 @@ void dwc_otg_ep_write_packet(dwc_otg_core_if_t * _core_if, dwc_ep_t * _ep,
while (mfdcr(DCRN_DMACR0 + (DMA_CH0*8)) & DMA_CE_ENABLE) {
}
dma_sts = (uint32_t)ppc4xx_get_dma_status();
-#ifdef OTG_PLB_DMA_DBG
+#ifdef CONFIG_OTG_PLB_DMA_DBG
if (!(dma_sts & DMA_CS0)) {
printk("DMA Status (Terminal Count not occured) 0x%08x\n", mfdcr(DCRN_DMASR));
}
@@ -2696,7 +2696,7 @@ void dwc_otg_ep_write_packet(dwc_otg_core_if_t * _core_if, dwc_ep_t * _ep,
printk("DMA Status (Channel 0 Error) 0x%08x\n", mfdcr(DCRN_DMASR));
}
ppc4xx_clr_dma_status(PLB_DMA_CH);
-#ifdef OTG_PLB_DMA_DBG
+#ifdef CONFIG_OTG_PLB_DMA_DBG
printk("%32s DMA Status =0x%08x\n", __FUNCTION__, mfdcr(DCRN_DMASR)); /* vj_dbg */
#endif
#endif /* CONFIG_OTG_PLB_DMA_TASKLET */
@@ -2841,7 +2841,7 @@ void dwc_otg_read_packet(dwc_otg_core_if_t * _core_if,
while (mfdcr(DCRN_DMACR0 + (DMA_CH0*8)) & DMA_CE_ENABLE) {
}
dma_sts = (uint32_t)ppc4xx_get_dma_status();
-#ifdef OTG_PLB_DMA_DBG
+#ifdef CONFIG_OTG_PLB_DMA_DBG
if (!(dma_sts & DMA_CS0)) {
printk("DMA Status (Terminal Count not occured) 0x%08x\n", mfdcr(DCRN_DMASR));
}
@@ -2850,7 +2850,7 @@ void dwc_otg_read_packet(dwc_otg_core_if_t * _core_if,
printk("DMA Status (Channel 0 Error) 0x%08x\n", mfdcr(DCRN_DMASR));
}
ppc4xx_clr_dma_status(PLB_DMA_CH);
-#ifdef OTG_PLB_DMA_DBG
+#ifdef CONFIG_OTG_PLB_DMA_DBG
printk("%32s DMA Status =0x%08x\n", __FUNCTION__, mfdcr(DCRN_DMASR));
printk(" Rxed buffer \n");
for( i=0; i< _bytes; i++) {
diff --git a/drivers/usb/gadget/dwc_otg/dwc_otg_cil.c.org b/drivers/usb/gadget/dwc_otg/dwc_otg_cil.c.org
new file mode 100644
index 00000000000..61a8879fc10
--- /dev/null
+++ b/drivers/usb/gadget/dwc_otg/dwc_otg_cil.c.org
@@ -0,0 +1,3237 @@
+/* ==========================================================================
+ * $File: //dwh/usb_iip/dev/software/otg_ipmate/linux/drivers/dwc_otg_cil.c $
+ * $Revision: #24 $
+ * $Date: 2007/02/07 $
+ * $Change: 791271 $
+ *
+ * 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.
+ * ========================================================================== */
+
+
+/** @file
+ *
+ * The Core Interface Layer provides basic services for accessing and
+ * managing the DWC_otg hardware. These services are used by both the
+ * Host Controller Driver and the Peripheral Controller Driver.
+ *
+ * The CIL manages the memory map for the core so that the HCD and PCD
+ * don't have to do this separately. It also handles basic tasks like
+ * reading/writing the registers and data FIFOs in the controller.
+ * Some of the data access functions provide encapsulation of several
+ * operations required to perform a task, such as writing multiple
+ * registers to start a transfer. Finally, the CIL performs basic
+ * services that are not specific to either the host or device modes
+ * of operation. These services include management of the OTG Host
+ * Negotiation Protocol (HNP) and Session Request Protocol (SRP). A
+ * Diagnostic API is also provided to allow testing of the controller
+ * hardware.
+ *
+ * The Core Interface Layer has the following requirements:
+ * - Provides basic controller operations.
+ * - Minimal use of OS services.
+ * - The OS services used will be abstracted by using inline functions
+ * or macros.
+ *
+ */
+#include <asm/unaligned.h>
+#ifdef CONFIG_DWC_DEBUG
+#include <linux/jiffies.h>
+#endif /* */
+
+#include <asm/dcr.h>
+
+#include "linux/dwc_otg_plat.h"
+#include "dwc_otg_regs.h"
+#include "dwc_otg_cil.h"
+
+#ifdef CONFIG_OTG_PLB_DMA_TASKLET
+atomic_t release_later = ATOMIC_INIT(0);
+#endif
+/**
+ * This function is called to initialize the DWC_otg CSR data
+ * structures. The register addresses in the device and host
+ * structures are initialized from the base address supplied by the
+ * caller. The calling function must make the OS calls to get the
+ * base address of the DWC_otg controller registers. The core_params
+ * argument holds the parameters that specify how the core should be
+ * configured.
+ *
+ * @param[in] _reg_base_addr Base address of DWC_otg core registers
+ * @param[in] _core_params Pointer to the core configuration parameters
+ *
+ */
+dwc_otg_core_if_t * dwc_otg_cil_init(const uint32_t * _reg_base_addr,
+ dwc_otg_core_params_t *_core_params)
+{
+ dwc_otg_core_if_t * core_if = 0;
+ dwc_otg_dev_if_t * dev_if = 0;
+ dwc_otg_host_if_t * host_if = 0;
+ uint8_t * reg_base = (uint8_t *) _reg_base_addr;
+ int i = 0;
+ DWC_DEBUGPL(DBG_CILV, "%s(%p,%p)\n", __func__, _reg_base_addr,
+ _core_params);
+ core_if = kmalloc(sizeof(dwc_otg_core_if_t), GFP_KERNEL);
+ if (core_if == 0) {
+ DWC_DEBUGPL(DBG_CIL,"Allocation of dwc_otg_core_if_t failed\n");
+ return 0;
+ }
+ memset(core_if, 0, sizeof(dwc_otg_core_if_t));
+ core_if->core_params = _core_params;
+ core_if->core_global_regs = (dwc_otg_core_global_regs_t *) reg_base;
+
+ /*
+ * Allocate the Device Mode structures.
+ */
+ dev_if = kmalloc(sizeof(dwc_otg_dev_if_t), GFP_KERNEL);
+ if (dev_if == 0) {
+ DWC_DEBUGPL(DBG_CIL,"Allocation of dwc_otg_dev_if_t failed\n");
+ kfree(core_if);
+ return 0;
+ }
+ dev_if->dev_global_regs = (dwc_otg_device_global_regs_t *)(reg_base +
+ DWC_DEV_GLOBAL_REG_OFFSET);
+ for (i = 0; i < MAX_EPS_CHANNELS; i++) {
+ dev_if->in_ep_regs[i] = (dwc_otg_dev_in_ep_regs_t *)
+ (reg_base + DWC_DEV_IN_EP_REG_OFFSET + (i * DWC_EP_REG_OFFSET));
+ dev_if->out_ep_regs[i] = (dwc_otg_dev_out_ep_regs_t *)
+ (reg_base + DWC_DEV_OUT_EP_REG_OFFSET + (i * DWC_EP_REG_OFFSET));
+ DWC_DEBUGPL(DBG_CILV, "in_ep_regs[%d]->diepctl=%p\n", i,
+ &dev_if->in_ep_regs[i]->diepctl);
+ DWC_DEBUGPL(DBG_CILV, "out_ep_regs[%d]->doepctl=%p\n", i,
+ &dev_if->out_ep_regs[i]->doepctl);
+ }
+ dev_if->speed = 0; // unknown
+ core_if->dev_if = dev_if;
+
+ /*
+ * Allocate the Host Mode structures.
+ */
+ host_if = kmalloc(sizeof(dwc_otg_host_if_t), GFP_KERNEL);
+ if (host_if == 0) {
+ DWC_DEBUGPL(DBG_CIL,"Allocation of dwc_otg_host_if_t failed\n");
+ kfree(dev_if);
+ kfree(core_if);
+ return 0;
+ }
+ host_if->host_global_regs = (dwc_otg_host_global_regs_t *)
+ (reg_base + DWC_OTG_HOST_GLOBAL_REG_OFFSET);
+ host_if->hprt0 = (uint32_t *) (reg_base + DWC_OTG_HOST_PORT_REGS_OFFSET);
+
+ for (i = 0; i < MAX_EPS_CHANNELS; i++) {
+ host_if->hc_regs[i] = (dwc_otg_hc_regs_t *)
+ (reg_base + DWC_OTG_HOST_CHAN_REGS_OFFSET + (i * DWC_OTG_CHAN_REGS_OFFSET));
+ DWC_DEBUGPL(DBG_CILV, "hc_reg[%d]->hcchar=%p\n", i,&host_if->hc_regs[i]->hcchar);
+ }
+
+ host_if->num_host_channels = MAX_EPS_CHANNELS;
+ core_if->host_if = host_if;
+ for (i = 0; i < MAX_EPS_CHANNELS; i++) {
+ core_if->data_fifo[i] =
+ (uint32_t *) (reg_base + DWC_OTG_DATA_FIFO_OFFSET +
+ (i * DWC_OTG_DATA_FIFO_SIZE));
+ DWC_DEBUGPL(DBG_CILV, "data_fifo[%d]=0x%08x\n", i,
+ (unsigned)core_if->data_fifo[i]);
+ }
+ core_if->pcgcctl = (uint32_t *) (reg_base + DWC_OTG_PCGCCTL_OFFSET);
+
+ /*
+ * Store the contents of the hardware configuration registers here for
+ * easy access later.
+ */
+ core_if->hwcfg1.d32 = dwc_read_reg32(&core_if->core_global_regs->ghwcfg1);
+ core_if->hwcfg2.d32 = dwc_read_reg32(&core_if->core_global_regs->ghwcfg2);
+#ifdef CONFIG_DWC_SLAVE
+ core_if->hwcfg2.b.architecture = DWC_SLAVE_ONLY_ARCH;
+#endif
+ core_if->hwcfg3.d32 = dwc_read_reg32(&core_if->core_global_regs->ghwcfg3);
+ core_if->hwcfg4.d32 = dwc_read_reg32(&core_if->core_global_regs->ghwcfg4);
+ DWC_DEBUGPL(DBG_CILV, "hwcfg1=%08x\n", core_if->hwcfg1.d32);
+ DWC_DEBUGPL(DBG_CILV, "hwcfg2=%08x\n", core_if->hwcfg2.d32);
+ DWC_DEBUGPL(DBG_CILV, "hwcfg3=%08x\n", core_if->hwcfg3.d32);
+ DWC_DEBUGPL(DBG_CILV, "hwcfg4=%08x\n", core_if->hwcfg4.d32);
+ DWC_DEBUGPL(DBG_CILV, "op_mode=%0x\n", core_if->hwcfg2.b.op_mode);
+ DWC_DEBUGPL(DBG_CILV, "arch=%0x\n", core_if->hwcfg2.b.architecture);
+ DWC_DEBUGPL(DBG_CILV, "num_dev_ep=%d\n",core_if->hwcfg2.b.num_dev_ep + 1);
+ DWC_DEBUGPL(DBG_CILV, "num_host_chan=%d\n",core_if->hwcfg2.b.num_host_chan);
+ DWC_DEBUGPL(DBG_CILV, "nonperio_tx_q_depth=0x%0x\n",
+ core_if->hwcfg2.b.nonperio_tx_q_depth);
+ DWC_DEBUGPL(DBG_CILV, "host_perio_tx_q_depth=0x%0x\n",
+ core_if->hwcfg2.b.host_perio_tx_q_depth);
+ DWC_DEBUGPL(DBG_CILV, "dev_token_q_depth=0x%0x\n",
+ core_if->hwcfg2.b.dev_token_q_depth);
+ DWC_DEBUGPL(DBG_CILV, "Total FIFO SZ=%d\n",
+ core_if->hwcfg3.b.dfifo_depth);
+ DWC_DEBUGPL(DBG_CILV, "xfer_size_cntr_width=%0x\n",
+ core_if->hwcfg3.b.xfer_size_cntr_width);
+
+ /*
+ * Set the SRP sucess bit for FS-I2c
+ */
+ core_if->srp_success = 0;
+ core_if->srp_timer_started = 0;
+ return core_if;
+}
+
+
+/**
+ * This function frees the structures allocated by dwc_otg_cil_init().
+ *
+ * @param[in] _core_if The core interface pointer returned from
+ * dwc_otg_cil_init().
+ *
+ */
+void dwc_otg_cil_remove(dwc_otg_core_if_t * _core_if)
+{
+ /* Disable all interrupts */
+ dwc_modify_reg32(&_core_if->core_global_regs->gahbcfg, 1, 0);
+ dwc_write_reg32(&_core_if->core_global_regs->gintmsk, 0);
+ if (_core_if->dev_if) {
+ kfree(_core_if->dev_if);
+ }
+ if (_core_if->host_if) {
+ kfree(_core_if->host_if);
+ }
+ kfree(_core_if);
+}
+
+
+/**
+ * This function enables the controller's Global Interrupt in the AHB Config
+ * register.
+ *
+ * @param[in] _core_if Programming view of DWC_otg controller.
+ */
+extern void dwc_otg_enable_global_interrupts(dwc_otg_core_if_t * _core_if)
+{
+ gahbcfg_data_t ahbcfg = {.d32 = 0};
+ ahbcfg.b.glblintrmsk = 1; /* Enable interrupts */
+ dwc_modify_reg32(&_core_if->core_global_regs->gahbcfg, 0, ahbcfg.d32);
+}
+
+/**
+ * This function disables the controller's Global Interrupt in the AHB Config
+ * register.
+ *
+ * @param[in] _core_if Programming view of DWC_otg controller.
+ */
+extern void dwc_otg_disable_global_interrupts(dwc_otg_core_if_t * _core_if)
+{
+ gahbcfg_data_t ahbcfg = {.d32 = 0};
+ ahbcfg.b.glblintrmsk = 1; /* Enable interrupts */
+ dwc_modify_reg32(&_core_if->core_global_regs->gahbcfg, ahbcfg.d32, 0);
+}
+
+/**
+ * This function initializes the commmon interrupts, used in both
+ * device and host modes.
+ *
+ * @param[in] _core_if Programming view of the DWC_otg controller
+ *
+ */
+static void dwc_otg_enable_common_interrupts(dwc_otg_core_if_t * _core_if)
+{
+ dwc_otg_core_global_regs_t * global_regs = _core_if->core_global_regs;
+ gintmsk_data_t intr_mask = {.d32 = 0};
+
+ /* Clear any pending OTG Interrupts */
+ dwc_write_reg32(&global_regs->gotgint, 0xFFFFFFFF);
+
+ /* Clear any pending interrupts */
+ dwc_write_reg32(&global_regs->gintsts, 0xFFFFFFFF);
+
+ /*
+ * Enable the interrupts in the GINTMSK.
+ */
+ intr_mask.b.modemismatch = 1;
+ intr_mask.b.otgintr = 1;
+ if (!_core_if->dma_enable) {
+ intr_mask.b.rxstsqlvl = 1;
+ }
+ intr_mask.b.conidstschng = 1;
+ intr_mask.b.wkupintr = 1;
+ intr_mask.b.disconnect = 1;
+ intr_mask.b.usbsuspend = 1;
+ intr_mask.b.sessreqintr = 1;
+ dwc_write_reg32(&global_regs->gintmsk, intr_mask.d32);
+}
+
+
+/**
+ * Initializes the FSLSPClkSel field of the HCFG register depending on the PHY
+ * type.
+ */
+static void init_fslspclksel(dwc_otg_core_if_t * _core_if)
+{
+ uint32_t val;
+ hcfg_data_t hcfg;
+ if (((_core_if->hwcfg2.b.hs_phy_type == 2) &&
+ (_core_if->hwcfg2.b.fs_phy_type == 1) &&
+ (_core_if->core_params->ulpi_fs_ls)) ||
+ (_core_if->core_params->phy_type == DWC_PHY_TYPE_PARAM_FS)) {
+ /* Full speed PHY */
+ val = DWC_HCFG_48_MHZ;
+ } else {
+ /* High speed PHY running at full speed or high speed */
+ val = DWC_HCFG_30_60_MHZ;
+ }
+ DWC_DEBUGPL(DBG_CIL, "Initializing HCFG.FSLSPClkSel to 0x%1x\n", val);
+ hcfg.d32 = dwc_read_reg32(&_core_if->host_if->host_global_regs->hcfg);
+ hcfg.b.fslspclksel = val;
+ dwc_write_reg32(&_core_if->host_if->host_global_regs->hcfg, hcfg.d32);
+}
+
+
+/**
+ * Initializes the DevSpd field of the DCFG register depending on the PHY type
+ * and the enumeration speed of the device.
+ */
+static void init_devspd(dwc_otg_core_if_t * _core_if)
+{
+ uint32_t val;
+ dcfg_data_t dcfg;
+ if (((_core_if->hwcfg2.b.hs_phy_type == 2) &&
+ (_core_if->hwcfg2.b.fs_phy_type == 1) &&
+ (_core_if->core_params->ulpi_fs_ls)) ||
+ (_core_if->core_params->phy_type == DWC_PHY_TYPE_PARAM_FS)) {
+ /* Full speed PHY */
+ val = 0x3;
+ } else if (_core_if->core_params->speed == DWC_SPEED_PARAM_FULL) {
+ /* High speed PHY running at full speed */
+ val = 0x1;
+ } else {
+ /* High speed PHY running at high speed */
+ val = 0x0;
+ }
+ DWC_DEBUGPL(DBG_CIL, "Initializing DCFG.DevSpd to 0x%1x\n", val);
+ dcfg.d32 = dwc_read_reg32(&_core_if->dev_if->dev_global_regs->dcfg);
+ dcfg.b.devspd = val;
+ dwc_write_reg32(&_core_if->dev_if->dev_global_regs->dcfg, dcfg.d32);
+}
+
+
+/**
+ * This function calculates the number of IN EPS
+ * using GHWCFG1 and GHWCFG2 registers values
+ *
+ * @param _pcd the pcd structure.
+ */
+static uint32_t calc_num_in_eps(dwc_otg_core_if_t * _core_if)
+{
+ uint32_t num_in_eps = 0;
+ uint32_t num_eps = _core_if->hwcfg2.b.num_dev_ep;
+ uint32_t hwcfg1 = _core_if->hwcfg1.d32 >> 2;
+ uint32_t num_tx_fifos = _core_if->hwcfg4.b.num_in_eps;
+ int i;
+ for (i = 0; i < num_eps; ++i) {
+ if (!(hwcfg1 & 0x1))
+ num_in_eps++;
+ hwcfg1 >>= 2;
+ }
+ if (_core_if->hwcfg4.b.ded_fifo_en) {
+ num_in_eps = (num_in_eps > num_tx_fifos) ? num_tx_fifos : num_in_eps;
+ }
+ return num_in_eps;
+}
+
+
+/**
+ * This function calculates the number of OUT EPS
+ * using GHWCFG1 and GHWCFG2 registers values
+ *
+ * @param _pcd the pcd structure.
+ */
+static uint32_t calc_num_out_eps(dwc_otg_core_if_t * _core_if)
+{
+ uint32_t num_out_eps = 0;
+ uint32_t num_eps = _core_if->hwcfg2.b.num_dev_ep;
+ uint32_t hwcfg1 = _core_if->hwcfg1.d32 >> 2;
+ int i;
+ for (i = 0; i < num_eps; ++i) {
+ if (!(hwcfg1 & 0x2))
+ num_out_eps++;
+ hwcfg1 >>= 2;
+ }
+ return num_out_eps;
+}
+
+
+/**
+ * This function initializes the DWC_otg controller registers and
+ * prepares the core for device mode or host mode operation.
+ *
+ * @param _core_if Programming view of the DWC_otg controller
+ *
+ */
+void dwc_otg_core_init(dwc_otg_core_if_t * _core_if)
+{
+ int i = 0;
+ dwc_otg_core_global_regs_t * global_regs = _core_if->core_global_regs;
+ dwc_otg_dev_if_t * dev_if = _core_if->dev_if;
+ gahbcfg_data_t ahbcfg = {.d32 = 0};
+ gusbcfg_data_t usbcfg = {.d32 = 0};
+ gi2cctl_data_t i2cctl = {.d32 = 0};
+ DWC_DEBUGPL(DBG_CILV, "dwc_otg_core_init(%p)\n", _core_if);
+
+ /* Common Initialization */
+ usbcfg.d32 = dwc_read_reg32(&global_regs->gusbcfg);
+ DWC_DEBUGPL(DBG_CIL, "USB config register: 0x%08x\n", usbcfg.d32);
+
+ /* Program the ULPI External VBUS bit if needed */
+#if defined(OTG_EXT_CHG_PUMP) || defined(CONFIG_460EX) || defined(CONFIG_APM82181)
+ usbcfg.b.ulpi_ext_vbus_drv = 1;
+#else
+ //usbcfg.b.ulpi_ext_vbus_drv = 0;
+ usbcfg.b.ulpi_ext_vbus_drv =
+ (_core_if->core_params->phy_ulpi_ext_vbus ==
+ DWC_PHY_ULPI_EXTERNAL_VBUS) ? 1 : 0;
+#endif
+
+ /* Set external TS Dline pulsing */
+ usbcfg.b.term_sel_dl_pulse = (_core_if->core_params->ts_dline == 1) ? 1 : 0;
+ dwc_write_reg32(&global_regs->gusbcfg, usbcfg.d32);
+
+ /* Reset the Controller */
+ dwc_otg_core_reset(_core_if);
+
+ /* Initialize parameters from Hardware configuration registers. */
+ dev_if->num_in_eps = calc_num_in_eps(_core_if);
+ dev_if->num_out_eps = calc_num_out_eps(_core_if);
+ DWC_DEBUGPL(DBG_CIL, "num_dev_perio_in_ep=%d\n",
+ _core_if->hwcfg4.b.num_dev_perio_in_ep);
+ DWC_DEBUGPL(DBG_CIL, "Is power optimization enabled? %s\n",
+ _core_if->hwcfg4.b.power_optimiz ? "Yes" : "No");
+ DWC_DEBUGPL(DBG_CIL, "vbus_valid filter enabled? %s\n",
+ _core_if->hwcfg4.b.vbus_valid_filt_en ? "Yes" : "No");
+ DWC_DEBUGPL(DBG_CIL, "iddig filter enabled? %s\n",
+ _core_if->hwcfg4.b.iddig_filt_en ? "Yes" : "No");
+
+ for (i = 0; i < _core_if->hwcfg4.b.num_dev_perio_in_ep; i++) {
+ dev_if->perio_tx_fifo_size[i] =
+ dwc_read_reg32(&global_regs->dptxfsiz_dieptxf[i]) >> 16;
+ DWC_DEBUGPL(DBG_CIL, "Periodic Tx FIFO SZ #%d=0x%0x\n", i,
+ dev_if->perio_tx_fifo_size[i]);
+ }
+ for (i = 0; i < _core_if->hwcfg4.b.num_in_eps; i++) {
+ dev_if->tx_fifo_size[i] =
+ dwc_read_reg32(&global_regs->dptxfsiz_dieptxf[i]) >> 16;
+ DWC_DEBUGPL(DBG_CIL, "Tx FIFO SZ #%d=0x%0x\n", i,
+ dev_if->perio_tx_fifo_size[i]);
+ }
+ _core_if->total_fifo_size = _core_if->hwcfg3.b.dfifo_depth;
+ _core_if->rx_fifo_size = dwc_read_reg32(&global_regs->grxfsiz);
+ _core_if->nperio_tx_fifo_size = dwc_read_reg32(&global_regs->gnptxfsiz) >> 16;
+ DWC_DEBUGPL(DBG_CIL, "Total FIFO SZ=%d\n", _core_if->total_fifo_size);
+ DWC_DEBUGPL(DBG_CIL, "Rx FIFO SZ=%d\n", _core_if->rx_fifo_size);
+ DWC_DEBUGPL(DBG_CIL, "NP Tx FIFO SZ=%d\n",_core_if->nperio_tx_fifo_size);
+
+ /* This programming sequence needs to happen in FS mode before any other
+ * programming occurs */
+ if ((_core_if->core_params->speed == DWC_SPEED_PARAM_FULL) &&
+ (_core_if->core_params->phy_type == DWC_PHY_TYPE_PARAM_FS)) {
+
+ /* If FS mode with FS PHY */
+
+ /* core_init() is now called on every switch so only call the
+ * following for the first time through.
+ */
+ if (!_core_if->phy_init_done) {
+ _core_if->phy_init_done = 1;
+ DWC_DEBUGPL(DBG_CIL, "FS_PHY detected\n");
+ usbcfg.d32 = dwc_read_reg32(&global_regs->gusbcfg);
+ usbcfg.b.physel = 1;
+ dwc_write_reg32(&global_regs->gusbcfg, usbcfg.d32);
+
+ /* Reset after a PHY select */
+ dwc_otg_core_reset(_core_if);
+ }
+
+ /* Program DCFG.DevSpd or HCFG.FSLSPclkSel to 48Mhz in FS. Also
+ * do this on HNP Dev/Host mode switches (done in dev_init and
+ * host_init).
+ */
+ if (dwc_otg_is_host_mode(_core_if)) {
+ DWC_DEBUGPL(DBG_CIL, "host mode\n");
+ init_fslspclksel(_core_if);
+ } else {
+ DWC_DEBUGPL(DBG_CIL, "device mode\n");
+ init_devspd(_core_if);
+ }
+
+ if (_core_if->core_params->i2c_enable) {
+ DWC_DEBUGPL(DBG_CIL, "FS_PHY Enabling I2c\n");
+
+ /* Program GUSBCFG.OtgUtmifsSel to I2C */
+ usbcfg.d32 = dwc_read_reg32(&global_regs->gusbcfg);
+ usbcfg.b.otgutmifssel = 1;
+ dwc_write_reg32(&global_regs->gusbcfg, usbcfg.d32);
+
+ /* Program GI2CCTL.I2CEn */
+ i2cctl.d32 = dwc_read_reg32(&global_regs->gi2cctl);
+ i2cctl.b.i2cdevaddr = 1;
+ i2cctl.b.i2cen = 0;
+ dwc_write_reg32(&global_regs->gi2cctl, i2cctl.d32);
+ i2cctl.b.i2cen = 1;
+ dwc_write_reg32(&global_regs->gi2cctl, i2cctl.d32);
+ }
+ } /* endif speed == DWC_SPEED_PARAM_FULL */
+ else {
+ /* High speed PHY. */
+ if (!_core_if->phy_init_done) {
+ _core_if->phy_init_done = 1;
+ DWC_DEBUGPL(DBG_CIL, "High spped PHY\n");
+ /* HS PHY parameters. These parameters are preserved
+ * during soft reset so only program the first time. Do
+ * a soft reset immediately after setting phyif.
+ */
+ // test-only: in AMCC 460EX code not used!!!???
+ usbcfg.b.ulpi_utmi_sel = _core_if->core_params->phy_type;
+ if (usbcfg.b.ulpi_utmi_sel == 1) {
+ DWC_DEBUGPL(DBG_CIL, "ULPI\n");
+ /* ULPI interface */
+ usbcfg.b.phyif = 0;
+ usbcfg.b.ddrsel = _core_if->core_params->phy_ulpi_ddr;
+ } else {
+ /* UTMI+ interface */
+ if (_core_if->core_params->phy_utmi_width == 16) {
+ usbcfg.b.phyif = 1;
+ DWC_DEBUGPL(DBG_CIL, "UTMI+ 16\n");
+ } else {
+ DWC_DEBUGPL(DBG_CIL, "UTMI+ 8\n");
+ usbcfg.b.phyif = 0;
+ }
+ }
+ dwc_write_reg32(&global_regs->gusbcfg, usbcfg.d32);
+ /* Reset after setting the PHY parameters */
+ dwc_otg_core_reset(_core_if);
+ }
+ }
+ if ((_core_if->hwcfg2.b.hs_phy_type == 2) &&
+ (_core_if->hwcfg2.b.fs_phy_type == 1) &&
+ (_core_if->core_params->ulpi_fs_ls)) {
+ DWC_DEBUGPL(DBG_CIL, "Setting ULPI FSLS\n");
+ usbcfg.d32 = dwc_read_reg32(&global_regs->gusbcfg);
+ usbcfg.b.ulpi_fsls = 1;
+ usbcfg.b.ulpi_clk_sus_m = 1;
+ dwc_write_reg32(&global_regs->gusbcfg, usbcfg.d32);
+ } else {
+ DWC_DEBUGPL(DBG_CIL, "Setting ULPI FSLS=0\n");
+ usbcfg.d32 = dwc_read_reg32(&global_regs->gusbcfg);
+ usbcfg.b.ulpi_fsls = 0;
+ usbcfg.b.ulpi_clk_sus_m = 0;
+ dwc_write_reg32(&global_regs->gusbcfg, usbcfg.d32);
+ }
+
+ /* Program the GAHBCFG Register. */
+ switch (_core_if->hwcfg2.b.architecture) {
+ case DWC_SLAVE_ONLY_ARCH:
+ DWC_DEBUGPL(DBG_CIL, "Slave Only Mode\n");
+ ahbcfg.b.nptxfemplvl_txfemplvl = DWC_GAHBCFG_TXFEMPTYLVL_HALFEMPTY;
+ ahbcfg.b.ptxfemplvl = DWC_GAHBCFG_TXFEMPTYLVL_HALFEMPTY;
+ _core_if->dma_enable = 0;
+ break;
+ case DWC_EXT_DMA_ARCH:
+ DWC_DEBUGPL(DBG_CIL, "External DMA Mode\n");
+ ahbcfg.b.hburstlen = _core_if->core_params->dma_burst_size;
+ _core_if->dma_enable = (_core_if->core_params->dma_enable != 0);
+ break;
+ case DWC_INT_DMA_ARCH:
+ DWC_DEBUGPL(DBG_CIL, "Internal DMA Mode\n");
+ #if defined(CONFIG_APM82181)
+ /* Avoid system hang during concurrently using USB and SATA */
+ ahbcfg.b.hburstlen = DWC_GAHBCFG_INT_DMA_BURST_INCR16;
+ #else
+ ahbcfg.b.hburstlen = DWC_GAHBCFG_INT_DMA_BURST_INCR;
+ #endif
+ _core_if->dma_enable = (_core_if->core_params->dma_enable != 0);
+ break;
+ }
+ ahbcfg.b.dmaenable = _core_if->dma_enable;
+ dwc_write_reg32(&global_regs->gahbcfg, ahbcfg.d32);
+ _core_if->en_multiple_tx_fifo = _core_if->hwcfg4.b.ded_fifo_en;
+
+ /*
+ * Program the GUSBCFG register.
+ */
+ usbcfg.d32 = dwc_read_reg32(&global_regs->gusbcfg);
+ switch (_core_if->hwcfg2.b.op_mode) {
+ case DWC_MODE_HNP_SRP_CAPABLE:
+ usbcfg.b.hnpcap = (_core_if->core_params->otg_cap ==
+ DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE);
+ usbcfg.b.srpcap = (_core_if->core_params->otg_cap !=
+ DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE);
+ break;
+ case DWC_MODE_SRP_ONLY_CAPABLE:
+ usbcfg.b.hnpcap = 0;
+ usbcfg.b.srpcap = (_core_if->core_params->otg_cap !=
+ DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE);
+ break;
+ case DWC_MODE_NO_HNP_SRP_CAPABLE:
+ usbcfg.b.hnpcap = 0;
+ usbcfg.b.srpcap = 0;
+ break;
+ case DWC_MODE_SRP_CAPABLE_DEVICE:
+ usbcfg.b.hnpcap = 0;
+ usbcfg.b.srpcap = (_core_if->core_params->otg_cap !=
+ DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE);
+ break;
+ case DWC_MODE_NO_SRP_CAPABLE_DEVICE:
+ usbcfg.b.hnpcap = 0;
+ usbcfg.b.srpcap = 0;
+ break;
+ case DWC_MODE_SRP_CAPABLE_HOST:
+ usbcfg.b.hnpcap = 0;
+ usbcfg.b.srpcap = (_core_if->core_params->otg_cap !=
+ DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE);
+ break;
+ case DWC_MODE_NO_SRP_CAPABLE_HOST:
+ usbcfg.b.hnpcap = 0;
+ usbcfg.b.srpcap = 0;
+ break;
+ }
+ dwc_write_reg32(&global_regs->gusbcfg, usbcfg.d32);
+
+ /* Enable common interrupts */
+ dwc_otg_enable_common_interrupts(_core_if);
+
+ /* Do device or host intialization based on mode during PCD
+ * and HCD initialization
+ */
+ if (dwc_otg_is_host_mode(_core_if)) {
+ DWC_DEBUGPL(DBG_ANY, "Host Mode\n");
+ _core_if->op_state = A_HOST;
+ } else {
+ DWC_DEBUGPL(DBG_ANY, "Device Mode\n");
+ _core_if->op_state = B_PERIPHERAL;
+#ifdef CONFIG_DWC_DEVICE_ONLY
+ dwc_otg_core_dev_init(_core_if);
+#endif /* */
+ }
+}
+
+
+/**
+ * This function enables the Device mode interrupts.
+ *
+ * @param _core_if Programming view of DWC_otg controller
+ */
+void dwc_otg_enable_device_interrupts(dwc_otg_core_if_t * _core_if)
+{
+ gintmsk_data_t intr_mask = {.d32 = 0};
+ dwc_otg_core_global_regs_t * global_regs = _core_if->core_global_regs;
+ DWC_DEBUGPL(DBG_CIL, "%s()\n", __func__);
+
+ /* Disable all interrupts. */
+ dwc_write_reg32(&global_regs->gintmsk, 0);
+
+ /* Clear any pending interrupts */
+ dwc_write_reg32(&global_regs->gintsts, 0xFFFFFFFF);
+
+ /* Enable the common interrupts */
+ dwc_otg_enable_common_interrupts(_core_if);
+
+ /* Enable interrupts */
+ intr_mask.b.usbreset = 1;
+ intr_mask.b.enumdone = 1;
+ intr_mask.b.inepintr = 1;
+ intr_mask.b.outepintr = 1;
+ intr_mask.b.erlysuspend = 1;
+ if (_core_if->en_multiple_tx_fifo == 0) {
+ intr_mask.b.epmismatch = 1;
+ }
+
+ /** @todo NGS: Should this be a module parameter? */
+#ifdef USE_PERIODIC_EP
+ intr_mask.b.isooutdrop = 1;
+ intr_mask.b.eopframe = 1;
+ intr_mask.b.incomplisoin = 1;
+ intr_mask.b.incomplisoout = 1;
+#endif /* */
+ dwc_modify_reg32(&global_regs->gintmsk, intr_mask.d32,
+ intr_mask.d32);
+
+ DWC_DEBUGPL(DBG_CIL, "%s() gintmsk=%0x\n", __func__,
+ dwc_read_reg32(&global_regs->gintmsk));
+}
+
+
+/**
+ * This function initializes the DWC_otg controller registers for
+ * device mode.
+ *
+ * @param _core_if Programming view of DWC_otg controller
+ *
+ */
+void dwc_otg_core_dev_init(dwc_otg_core_if_t * _core_if)
+{
+ int i;
+ dwc_otg_core_global_regs_t * global_regs = _core_if->core_global_regs;
+ dwc_otg_dev_if_t * dev_if = _core_if->dev_if;
+ dwc_otg_core_params_t * params = _core_if->core_params;
+ dcfg_data_t dcfg = {.d32 = 0};
+ grstctl_t resetctl = {.d32 = 0};
+ uint32_t rx_fifo_size;
+ fifosize_data_t nptxfifosize;
+ fifosize_data_t txfifosize;
+ dthrctl_data_t dthrctl;
+ fifosize_data_t ptxfifosize;
+
+ /* Restart the Phy Clock */
+ dwc_write_reg32(_core_if->pcgcctl, 0);
+
+ /* Device configuration register */
+ init_devspd(_core_if);
+ dcfg.d32 = dwc_read_reg32(&dev_if->dev_global_regs->dcfg);
+ dcfg.b.perfrint = DWC_DCFG_FRAME_INTERVAL_80;
+ dwc_write_reg32(&dev_if->dev_global_regs->dcfg, dcfg.d32);
+
+ /* Configure data FIFO sizes */
+ if (_core_if->hwcfg2.b.dynamic_fifo && params->enable_dynamic_fifo) {
+ DWC_DEBUGPL(DBG_CIL, "Total FIFO Size=%d\n",
+ _core_if->total_fifo_size);
+ DWC_DEBUGPL(DBG_CIL, "Rx FIFO Size=%d\n",
+ params->dev_rx_fifo_size);
+ DWC_DEBUGPL(DBG_CIL, "NP Tx FIFO Size=%d\n",
+ params->dev_nperio_tx_fifo_size);
+
+ /* Rx FIFO */
+ DWC_DEBUGPL(DBG_CIL, "initial grxfsiz=%08x\n",
+ dwc_read_reg32(&global_regs->grxfsiz));
+ rx_fifo_size = params->dev_rx_fifo_size;
+ dwc_write_reg32(&global_regs->grxfsiz, rx_fifo_size);
+ DWC_DEBUGPL(DBG_CIL, "new grxfsiz=%08x\n",
+ dwc_read_reg32(&global_regs->grxfsiz));
+
+ /** Set Periodic Tx FIFO Mask all bits 0 */
+ _core_if->p_tx_msk = 0;
+
+ /** Set Tx FIFO Mask all bits 0 */