zte's code,first commit
Change-Id: I9a04da59e459a9bc0d67f101f700d9d7dc8d681b
diff --git a/boot/common/src/uboot/drivers/usb_drv/Makefile b/boot/common/src/uboot/drivers/usb_drv/Makefile
new file mode 100644
index 0000000..f54ebee
--- /dev/null
+++ b/boot/common/src/uboot/drivers/usb_drv/Makefile
@@ -0,0 +1,48 @@
+#
+# (C) Copyright 2000-2007
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+include $(TOPDIR)/config.mk
+
+LIB := $(obj)libusb_dwc.o
+
+# new USB gadget layer dependencies
+
+COBJS-y +=dwc_otg_cil.o dwc_otg_cil_intr.o dwc_otg_dev_test.o dwc_otg_pcd.o dwc_otg_pcd_intr.o global.o
+
+COBJS := $(COBJS-y)
+SRCS := $(COBJS:.o=.c)
+OBJS := $(addprefix $(obj),$(COBJS))
+
+all: $(LIB)
+
+$(LIB): $(obj).depend $(OBJS)
+ $(call cmd_link_o_target, $(OBJS))
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/boot/common/src/uboot/drivers/usb_drv/dwc_otg_cil.c b/boot/common/src/uboot/drivers/usb_drv/dwc_otg_cil.c
new file mode 100644
index 0000000..1243a53
--- /dev/null
+++ b/boot/common/src/uboot/drivers/usb_drv/dwc_otg_cil.c
@@ -0,0 +1,1191 @@
+/* ==========================================================================
+ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_cil.c $
+ * $Revision: #191 $
+ * $Date: 2012/08/10 $
+ * $Change: 2047372 $
+ *
+ * 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 <usb/global.h>
+#include <usb/dwc_otg_regs.h>
+#include <usb/dwc_otg_cil.h>
+#include <usb/dwc_otg_driver.h>
+
+
+
+static int dwc_otg_setup_params(dwc_otg_core_if_t * core_if);
+
+void DWC_MODIFY_REG32(uint32_t volatile *reg, uint32_t clear_mask, uint32_t set_mask)
+{
+ DWC_WRITE_REG32(reg,(DWC_READ_REG32(reg) & ~clear_mask) | set_mask);
+}
+
+dwc_otg_core_if_t *dwc_otg_cil_init(const uint32_t * reg_base_addr)
+{
+ dwc_otg_core_if_t *core_if = (&global.core_if_t);
+ dwc_otg_dev_if_t *dev_if = (&global.dev_if_t);
+ uint8_t *pt_core_if = ( uint8_t *)(&global.core_if_t);
+ uint8_t *pt_dev_if = ( uint8_t *)(&global.dev_if_t);
+ uint8_t *reg_base = (uint8_t *) reg_base_addr;
+ int i = 0;
+ for(i= 0;i<sizeof(global.core_if_t);i++)
+ {
+ pt_core_if[i] = 0;
+ }
+ core_if->core_global_regs = (dwc_otg_core_global_regs_t *) reg_base;
+
+ for(i= 0;i<sizeof(global.dev_if_t);i++)
+ {
+ pt_dev_if[i] = 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));
+
+ core_if->data_fifo[i] =(uint32_t *) (reg_base + DWC_OTG_DATA_FIFO_OFFSET +(i * DWC_OTG_DATA_FIFO_SIZE));
+ }
+
+ dev_if->speed = 0;
+
+ core_if->dev_if = dev_if;
+
+ core_if->pcgcctl = (uint32_t *) (reg_base + DWC_OTG_PCGCCTL_OFFSET);
+
+ 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);
+ 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);
+
+ core_if->dcfg.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg);
+
+ dwc_otg_setup_params(core_if);
+
+
+ return core_if;
+}
+
+/**
+ * Initializes the DevSpd field of the DCFG register depending on the PHY type
+ * and the enumeration speed of the device.
+ */
+void init_devspd(dwc_otg_core_if_t * core_if,uint8_t speed)
+{
+ uint32_t val;
+ dcfg_data_t dcfg;
+
+ val = speed;
+ dcfg.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg);
+ dcfg.b.devspd = val;
+ if(global.g_enum == NEED_ENUM)
+ {
+ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dcfg, dcfg.d32);
+ }
+}
+
+/**
+ * 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)
+ {
+ 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;
+ gotgctl_data_t gotgctl;
+
+ gusbcfg_data_t usbcfg;
+ ahbcfg.d32 = 0;
+ usbcfg.d32 = 0;
+ gotgctl.d32 = 0;
+
+
+ usbcfg.d32 = DWC_READ_REG32(&global_regs->gusbcfg);
+ if(global.g_enum == NEED_ENUM)
+ {
+
+#if !USE_ASIC
+ usbcfg.b.ulpi_ext_vbus_drv =(core_if->core_params->phy_ulpi_ext_vbus == DWC_PHY_ULPI_EXTERNAL_VBUS) ? 1 : 0;
+
+ usbcfg.b.term_sel_dl_pulse = (core_if->core_params->ts_dline == 1) ? 1 : 0;
+
+
+ DWC_WRITE_REG32(&global_regs->gusbcfg, usbcfg.d32);
+#endif
+ dwc_otg_core_reset(core_if);
+ }
+
+
+ dev_if->num_in_eps = 2;//calc_num_in_eps(core_if);
+ dev_if->num_out_eps = 2;//calc_num_out_eps(core_if);
+
+ 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;
+ {
+ /* High speed PHY. */
+ if (!core_if->phy_init_done)
+ {
+ core_if->phy_init_done = 1;
+ /* HS PHY parameters. These parameters are preserved
+ * during soft reset so only program the first time. Do
+ * a soft reset immediately after setting phyif. */
+ #if !USE_ASIC
+ if (core_if->core_params->phy_type == 2)
+ {
+ /* ULPI interface */
+ usbcfg.b.ulpi_utmi_sel = 1;
+ usbcfg.b.phyif = 0;
+ usbcfg.b.ddrsel = core_if->core_params->phy_ulpi_ddr;
+ }
+ #else
+ if (core_if->core_params->phy_type == 1)
+ {
+ /* UTMI+ interface */
+ usbcfg.b.ulpi_utmi_sel = 0;
+ if (core_if->core_params->phy_utmi_width == 16)
+ {
+ usbcfg.b.phyif = 1;
+
+ }
+ else
+ {
+ usbcfg.b.phyif = 0;
+ }
+ }
+ #endif
+ if(global.g_enum == NEED_ENUM)
+ {
+ DWC_WRITE_REG32(&global_regs->gusbcfg, usbcfg.d32);
+ /* Reset after setting the PHY parameters */
+ dwc_otg_core_reset(core_if);
+ }
+ }
+ }
+ if(global.g_enum == NEED_ENUM)
+ {
+#if !USE_ASIC
+ if ((core_if->hwcfg2.b.hs_phy_type == 2) &&(core_if->hwcfg2.b.fs_phy_type == 1) &&(core_if->core_params->ulpi_fs_ls))
+ {
+ 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
+ {
+ 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);
+ }
+#endif
+ }
+
+
+ ahbcfg.b.nptxfemplvl_txfemplvl = DWC_GAHBCFG_TXFEMPTYLVL_HALFEMPTY;
+ ahbcfg.b.ptxfemplvl = DWC_GAHBCFG_TXFEMPTYLVL_HALFEMPTY;
+
+
+ ahbcfg.b.dmaenable = 0;
+ // ÅäÖÃÈ«¿ÕFIFO²úÉúÖжÏ
+ ahbcfg.b.nptxfemplvl_txfemplvl = DWC_GAHBCFG_TXFEMPTYLVL_EMPTY ;
+ if(global.g_enum == NEED_ENUM)
+ {
+
+ DWC_WRITE_REG32(&global_regs->gahbcfg, ahbcfg.d32);
+ }
+
+
+ core_if->en_multiple_tx_fifo = core_if->hwcfg4.b.ded_fifo_en;
+
+ core_if->pti_enh_enable = core_if->core_params->pti_enable != 0;
+ core_if->multiproc_int_enable = dwc_param_mpi_enable_default;//core_if->core_params->mpi_enable;
+ /*
+ * Program the GUSBCFG register.
+ */
+ usbcfg.d32 = DWC_READ_REG32(&global_regs->gusbcfg);
+ usbcfg.b.hnpcap = 0;
+ usbcfg.b.srpcap = 0;
+
+ if(global.g_enum == NEED_ENUM)
+ {
+ DWC_WRITE_REG32(&global_regs->gusbcfg, usbcfg.d32);
+ }
+ {
+ gotgctl.b.otgver = core_if->core_params->otg_ver;
+ if(global.g_enum == NEED_ENUM)
+ {
+ DWC_MODIFY_REG32(&core_if->core_global_regs->gotgctl, 0, gotgctl.d32);
+ }
+ /* Set OTG version supported */
+ core_if->otg_ver = core_if->core_params->otg_ver;
+ }
+ if(global.g_enum == NEED_ENUM)
+ {
+ dwc_otg_core_dev_init(core_if);
+ }
+
+ }
+
+
+/**
+ * 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 ;
+
+ dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
+ intr_mask.d32 = 0;
+ /* 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 */
+ intr_mask.b.rxstsqlvl = 1;
+ intr_mask.b.usbsuspend = 1;
+ DWC_WRITE_REG32(&global_regs->gintmsk, intr_mask.d32);
+
+ intr_mask.d32 = 0x1e3400;
+ DWC_MODIFY_REG32(&global_regs->gintmsk, intr_mask.d32, intr_mask.d32);
+
+}
+
+/**
+ * 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_dev_if_t *dev_if = core_if->dev_if;
+ dcfg_data_t dcfg;
+ grstctl_t resetctl;
+ dctl_data_t dctl;
+ diepmsk_data_t msk;
+ dcfg.d32 = 0;
+ resetctl.d32 = 0;
+ dctl.d32 = 0;
+ msk.d32 = 0;
+ /* Restart the Phy Clock */
+ DWC_WRITE_REG32(core_if->pcgcctl, 0);
+
+ /* Device configuration register */
+ init_devspd(core_if,0);//ĬÈÏÅäÖóɸßËÙ
+ dcfg.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->dcfg);
+ dcfg.b.descdma = 0;
+ dcfg.b.perfrint = DWC_DCFG_FRAME_INTERVAL_80;
+
+ DWC_WRITE_REG32(&dev_if->dev_global_regs->dcfg, dcfg.d32);
+
+ /* Flush the FIFOs */
+ dwc_otg_flush_tx_fifo(core_if, 0x10); /* all Tx FIFOs */
+ dwc_otg_flush_rx_fifo(core_if);
+
+ /* Flush the Learning Queue. */
+ resetctl.b.intknqflsh = 1;
+ DWC_WRITE_REG32(&core_if->core_global_regs->grstctl, resetctl.d32);
+ /* Clear all pending Device Interrupts */
+ /** @todo - if the condition needed to be checked
+ * or in any case all pending interrutps should be cleared?
+ */
+ DWC_WRITE_REG32(&dev_if->dev_global_regs->diepmsk, 0);
+ DWC_WRITE_REG32(&dev_if->dev_global_regs->doepmsk, 0);
+ DWC_WRITE_REG32(&dev_if->dev_global_regs->daint, 0xFFFFFFFF);
+ DWC_WRITE_REG32(&dev_if->dev_global_regs->daintmsk, 0);
+
+ for (i = 0; i <= dev_if->num_in_eps; i++)
+ {
+ DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->diepctl,0);
+
+ DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->dieptsiz, 0);
+ DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->diepdma, 0);
+ DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->diepint, 0xFF);
+
+ DWC_WRITE_REG32(&dev_if->out_ep_regs[i]->doepctl,0);
+
+ DWC_WRITE_REG32(&dev_if->out_ep_regs[i]->doeptsiz, 0);
+ DWC_WRITE_REG32(&dev_if->out_ep_regs[i]->doepdma, 0);
+ DWC_WRITE_REG32(&dev_if->out_ep_regs[i]->doepint, 0xFF);
+ }
+ //ÓÃÓÚhsic
+ if(1==global.g_USB_MODE)
+ {
+ DWC_WRITE_REG32(&core_if->core_global_regs->glpmcfg, 0x40000000);
+ }
+ dwc_otg_enable_device_interrupts(core_if);
+ msk.b.txfifoundrn = 1;
+ DWC_MODIFY_REG32(&dev_if->dev_global_regs->diepmsk,msk.d32, msk.d32);
+ dctl.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->dctl);
+ dctl.b.sftdiscon = 0;
+ DWC_WRITE_REG32(&dev_if->dev_global_regs->dctl, dctl.d32);
+
+}
+
+void dwc_otg_core_dev_disconnet(dwc_otg_core_if_t * core_if)
+{
+ dctl_data_t dctl;
+ dwc_otg_dev_if_t *dev_if = core_if->dev_if;
+ dctl.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->dctl);
+ dctl.b.sftdiscon = 1;
+ DWC_WRITE_REG32(&dev_if->dev_global_regs->dctl, dctl.d32);
+}
+/**
+ * This function reads a setup packet from the Rx FIFO into the destination
+ * buffer. This function is called from the Rx Status Queue Level (RxStsQLvl)
+ * Interrupt routine when a SETUP packet has been received in Slave mode.
+ *
+ * @param core_if Programming view of DWC_otg controller.
+ * @param dest Destination buffer for packet data.
+ */
+void dwc_otg_read_setup_packet(dwc_otg_core_if_t * core_if, uint32_t * dest)
+{
+ dest[0] = DWC_READ_REG32(core_if->data_fifo[0]);
+ dest[1] = DWC_READ_REG32(core_if->data_fifo[0]);
+
+}
+
+/**
+ * This function enables EP0 OUT to receive SETUP packets and configures EP0
+ * IN for transmitting packets. It is normally called when the
+ * "Enumeration Done" interrupt occurs.
+ *
+ * @param core_if Programming view of DWC_otg controller.
+ * @param ep The EP0 data.
+ */
+void dwc_otg_ep0_activate(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
+{
+ dwc_otg_dev_if_t *dev_if = core_if->dev_if;
+ dsts_data_t dsts;
+ depctl_data_t diepctl;
+ dctl_data_t dctl;
+ ep->stp_rollover = 0;
+ dctl.d32 = 0;
+
+ /* Read the Device Status and Endpoint 0 Control registers */
+ dsts.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->dsts);
+ diepctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[0]->diepctl);
+
+ /* Set the MPS of the IN EP based on the enumeration speed */
+ switch (dsts.b.enumspd)
+ {
+ case DWC_DSTS_ENUMSPD_HS_PHY_30MHZ_OR_60MHZ:
+ case DWC_DSTS_ENUMSPD_FS_PHY_30MHZ_OR_60MHZ:
+ case DWC_DSTS_ENUMSPD_FS_PHY_48MHZ:
+ diepctl.b.mps = DWC_DEP0CTL_MPS_64;
+ break;
+ }
+
+ DWC_WRITE_REG32(&dev_if->in_ep_regs[0]->diepctl, diepctl.d32);
+ dctl.b.cgnpinnak = 1;
+
+ DWC_MODIFY_REG32(&dev_if->dev_global_regs->dctl, dctl.d32, dctl.d32);
+
+}
+
+/**
+ * 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.
+ *
+ * @param core_if Programming view of DWC_otg controller.
+ * @param ep The EP to activate.
+ */
+void dwc_otg_ep_activate(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
+{
+ dwc_otg_dev_if_t *dev_if = core_if->dev_if;
+ depctl_data_t depctl;
+ volatile uint32_t *addr;
+ daint_data_t daintmsk;
+
+ 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);
+ }
+ {
+
+ DWC_MODIFY_REG32(&dev_if->dev_global_regs->daintmsk,0, daintmsk.d32);
+ }
+
+ ep->stall_clear_flag = 0;
+
+ return;
+}
+/**
+ * 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. the ISR.
+ *
+ * @param core_if Programming view of DWC_otg controller.
+ * @param ep The EP to start the transfer on.
+ */
+
+void dwc_otg_ep_start_transfer(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
+{
+ //printf("#########start transfer#######\n");
+ depctl_data_t depctl;
+ deptsiz_data_t deptsiz;
+
+ if (ep->is_in == 1)
+ {
+ //printf("#########ep->is_in == 1 INÐÍ´«Êä#######\n");
+ dwc_otg_dev_in_ep_regs_t *in_regs = core_if->dev_if->in_ep_regs[ep->num];
+
+ depctl.d32 = DWC_READ_REG32(&(in_regs->diepctl));
+ deptsiz.d32 = DWC_READ_REG32(&(in_regs->dieptsiz));
+
+ if (ep->maxpacket > (ep->maxxfer / MAX_PKT_CNT))
+ {
+ //printf("#########ep->maxpacket > (ep->maxxfer / MAX_PKT_CNT)#######\n");
+ ep->xfer_len += (ep->maxxfer < (ep->total_len - ep->xfer_len)) ?\
+ ep->maxxfer : (ep->total_len - ep->xfer_len);
+ }
+ else
+ {
+ //printf("#########ep->maxpacket <= (ep->maxxfer / MAX_PKT_CNT)#######\n");
+ ep->xfer_len += (MAX_PKT_CNT * ep->maxpacket < (ep->total_len - ep->xfer_len)) ?\
+ MAX_PKT_CNT * ep->maxpacket : (ep->total_len - ep->xfer_len);
+ }
+
+
+ /* Zero Length Packet? */
+ if ((ep->xfer_len - ep->xfer_count) == 0)
+ {
+ //printf("########(ep->xfer_len - ep->xfer_count) == 0########\n");
+ deptsiz.b.xfersize = 0;
+ deptsiz.b.pktcnt = 1;
+ }
+ else
+ {
+ //printf("########(ep->xfer_len - ep->xfer_count) != 0########\n");
+ deptsiz.b.xfersize = ep->xfer_len - ep->xfer_count;
+ deptsiz.b.pktcnt = (ep->xfer_len - ep->xfer_count - 1 + ep->maxpacket) / ep->maxpacket;
+ #if 0/*unsigned the max value is 1023*/
+ if (deptsiz.b.pktcnt > MAX_PKT_CNT)
+ {
+ // printf("########deptsiz.b.pktcnt > MAX_PKT_CNT########\n");
+ deptsiz.b.pktcnt = MAX_PKT_CNT;
+ deptsiz.b.xfersize = deptsiz.b.pktcnt * ep->maxpacket;
+ }
+ #endif
+ }
+
+ if((ep->xfer_len - ep->xfer_count)% ep->maxpacket== 0)
+ {
+ printf("sent_zlp = 1\n");
+ ep->sent_zlp = 1;
+ }
+
+ DWC_WRITE_REG32(&in_regs->dieptsiz, deptsiz.d32);
+
+ if (ep->xfer_len > 0)
+ {
+ // printf("########ep->xfer_len > 0########\n");
+ uint32_t fifoemptymsk = 0;
+ fifoemptymsk = 1 << ep->num;
+ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dtknqr4_fifoemptymsk,0, fifoemptymsk);
+
+ }
+
+ /* EP enable, IN data in FIFO */
+ depctl.b.cnak = 1;
+ depctl.b.epena = 1;
+ //printf("EP enable, IN data in FIFO\n");
+ DWC_WRITE_REG32(&in_regs->diepctl, depctl.d32);
+#if SIM_EN == EMULATION
+ REG32(ARM_PORTA)=0x82;
+#endif
+
+ }
+ else
+ {
+ /* OUT endpoint */
+ //printf("#########ep->is_in ==0 OUTÐÍ´«Êä#######\n");
+ dwc_otg_dev_out_ep_regs_t *out_regs = core_if->dev_if->out_ep_regs[ep->num];
+
+ depctl.d32 = DWC_READ_REG32(&(out_regs->doepctl));
+ deptsiz.d32 = DWC_READ_REG32(&(out_regs->doeptsiz));
+
+
+ if (ep->maxpacket > (ep->maxxfer / MAX_PKT_CNT))
+ {
+ //printf("#########ep->maxpacket > (ep->maxxfer / MAX_PKT_CNT)#######\n");
+ ep->xfer_len += (ep->maxxfer < (ep->total_len - ep->xfer_len)) ? ep->maxxfer : (ep->total_len - ep->xfer_len);
+ }
+ else
+ {
+ //printf("#########ep->maxpacket <= (ep->maxxfer / MAX_PKT_CNT)#######\n");
+ ep->xfer_len += (MAX_PKT_CNT * ep->maxpacket < (ep->total_len - ep->xfer_len)) ? MAX_PKT_CNT * ep->maxpacket : (ep->total_len - ep->xfer_len);
+ }
+
+
+ if ((ep->xfer_len - ep->xfer_count) == 0)
+ {
+ //printf("#########(ep->xfer_len - ep->xfer_count) == 0#######\n");
+ deptsiz.b.xfersize = ep->maxpacket;
+ deptsiz.b.pktcnt = 1;
+ }
+ else
+ {
+ //printf("#########(ep->xfer_len - ep->xfer_count) != 0#######\n");
+ deptsiz.b.pktcnt = (ep->xfer_len - ep->xfer_count + (ep->maxpacket - 1)) / ep->maxpacket;
+
+#if 0/*unsigned the max value is 1023*/
+ if (deptsiz.b.pktcnt > MAX_PKT_CNT)
+ {
+ //printf("usbusbdeptsiz.b.pktcnt > MAX_PKT_CNT#######\n");
+ deptsiz.b.pktcnt = MAX_PKT_CNT;
+ }
+#endif
+ ep->xfer_len = deptsiz.b.pktcnt * ep->maxpacket + ep->xfer_count;
+ deptsiz.b.xfersize = ep->xfer_len - ep->xfer_count;
+ }
+
+ {
+
+ DWC_WRITE_REG32(&out_regs->doeptsiz, deptsiz.d32);
+ }
+ /* EP enable */
+ depctl.b.cnak = 1;
+ depctl.b.epena = 1;
+ DWC_WRITE_REG32(&out_regs->doepctl, depctl.d32);
+#if SIM_EN == EMULATION
+ REG32(ARM_PORTA)=0x80;
+#endif
+
+ }
+}
+
+/**
+ * This function setup a zero length transfer in Buffer DMA and
+ * Slave modes for usb requests with zero field set
+ *
+ * @param core_if Programming view of DWC_otg controller.
+ * @param ep The EP to start the transfer on.
+ *
+ */
+void dwc_otg_ep_start_zl_transfer(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
+{
+
+ depctl_data_t depctl;
+ deptsiz_data_t deptsiz;
+
+ /* IN endpoint */
+ if (ep->is_in == 1)
+ {
+ dwc_otg_dev_in_ep_regs_t *in_regs = core_if->dev_if->in_ep_regs[ep->num];
+
+ depctl.d32 = DWC_READ_REG32(&(in_regs->diepctl));
+ deptsiz.d32 = DWC_READ_REG32(&(in_regs->dieptsiz));
+
+ deptsiz.b.xfersize = 0;
+ deptsiz.b.pktcnt = 1;
+ {
+ DWC_WRITE_REG32(&in_regs->dieptsiz, deptsiz.d32);
+ {
+ /* Enable the Tx FIFO Empty Interrupt for this EP */
+ if (ep->xfer_len > 0)
+ {
+ uint32_t fifoemptymsk = 0;
+ fifoemptymsk = 1 << ep->num;
+ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dtknqr4_fifoemptymsk,0, fifoemptymsk);
+ }
+ }
+ }
+
+ /* EP enable, IN data in FIFO */
+ depctl.b.cnak = 1;
+ depctl.b.epena = 1;
+ DWC_WRITE_REG32(&in_regs->diepctl, depctl.d32);
+
+ }
+ else
+ {
+ /* OUT endpoint */
+ dwc_otg_dev_out_ep_regs_t *out_regs = core_if->dev_if->out_ep_regs[ep->num];
+
+ depctl.d32 = DWC_READ_REG32(&(out_regs->doepctl));
+ deptsiz.d32 = DWC_READ_REG32(&(out_regs->doeptsiz));
+
+ /* Zero Length Packet */
+ deptsiz.b.xfersize = ep->maxpacket;
+ deptsiz.b.pktcnt = 1;
+ {
+ DWC_WRITE_REG32(&out_regs->doeptsiz, deptsiz.d32);
+ }
+
+ /* 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.
+ *
+ * @param core_if Programming view of DWC_otg controller.
+ * @param ep The EP0 data.
+ */
+void dwc_otg_ep0_start_transfer(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
+{
+ depctl_data_t depctl;
+ deptsiz0_data_t deptsiz;
+ uint32_t fifoemptymsk;
+
+ ep->total_len = ep->xfer_len;
+
+ /* IN endpoint */
+ if (ep->is_in == 1)
+ {
+ //printf("ep0 tx data\n");
+ dwc_otg_dev_in_ep_regs_t *in_regs = core_if->dev_if->in_ep_regs[0];
+ depctl.d32 = DWC_READ_REG32(&in_regs->diepctl);
+ if (depctl.b.epena)
+ return;
+
+
+ /* If dedicated FIFO every time flush fifo before enable ep*/
+ dwc_otg_flush_tx_fifo(core_if, ep->tx_fifo_num);
+
+ depctl.d32 = DWC_READ_REG32(&in_regs->diepctl);
+ deptsiz.d32 = DWC_READ_REG32(&in_regs->dieptsiz);
+
+ /* Zero Length Packet? */
+ if (ep->xfer_len == 0)
+ {
+ 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);
+ }
+
+ /* EP enable, IN data in FIFO */
+ depctl.b.cnak = 1;
+ depctl.b.epena = 1;
+ DWC_WRITE_REG32(&in_regs->diepctl, depctl.d32);
+
+ /**
+ * Enable the Non-Periodic Tx FIFO empty interrupt, the
+ * data will be written into the fifo by the ISR.
+ */
+
+ /* Enable the Tx FIFO Empty Interrupt for this EP */
+ if (ep->xfer_len > 0)
+ {
+ fifoemptymsk = 0;
+ fifoemptymsk |= 1 << ep->num;
+ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dtknqr4_fifoemptymsk,0, fifoemptymsk);
+ }
+
+ }
+ else
+ {
+ /* OUT endpoint */
+ dwc_otg_dev_out_ep_regs_t *out_regs = core_if->dev_if->out_ep_regs[0];
+
+ 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 */
+ /* Zero Length Packet */
+ deptsiz.b.xfersize = ep->maxpacket;
+ deptsiz.b.pktcnt = 1;
+ deptsiz.b.supcnt = 3;
+ DWC_WRITE_REG32(&out_regs->doeptsiz, deptsiz.d32);
+
+ /* EP enable */
+ depctl.b.cnak = 1;
+ depctl.b.epena = 1;
+ DWC_WRITE_REG32(&(out_regs->doepctl), depctl.d32);
+
+ }
+}
+
+/**
+ * This function continues control IN transfers started by
+ * dwc_otg_ep0_start_transfer, when the transfer does not fit in a
+ * single packet. NOTE: The DIEPCTL0/DOEPCTL0 registers only have one
+ * bit for the packet count.
+ *
+ * @param core_if Programming view of DWC_otg controller.
+ * @param ep The EP0 data.
+ */
+void dwc_otg_ep0_continue_transfer(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
+{
+ depctl_data_t depctl;
+ deptsiz0_data_t deptsiz;
+
+ if (ep->is_in == 1)
+ {
+ dwc_otg_dev_in_ep_regs_t *in_regs = core_if->dev_if->in_ep_regs[0];
+
+ depctl.d32 = DWC_READ_REG32(&in_regs->diepctl);
+ deptsiz.d32 = DWC_READ_REG32(&in_regs->dieptsiz);
+
+ deptsiz.b.xfersize = (ep->total_len - ep->xfer_count) > ep->maxpacket ? ep->maxpacket : (ep->total_len - ep->xfer_count);
+ deptsiz.b.pktcnt = 1;
+
+ ep->xfer_len += deptsiz.b.xfersize;
+
+ DWC_WRITE_REG32(&in_regs->dieptsiz, deptsiz.d32);
+
+
+ depctl.b.cnak = 1;
+ depctl.b.epena = 1;
+ DWC_WRITE_REG32(&in_regs->diepctl, depctl.d32);
+
+ /**
+ * Enable the Non-Periodic Tx FIFO empty interrupt, the
+ * data will be written into the fifo by the ISR.
+ */
+
+ /* Enable the Tx FIFO Empty Interrupt for this EP */
+ if (ep->xfer_len > 0)
+ {
+ uint32_t fifoemptymsk = 0;
+ fifoemptymsk |= 1 << ep->num;
+ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dtknqr4_fifoemptymsk,0, fifoemptymsk);
+ }
+
+ }
+ else
+ {
+ dwc_otg_dev_out_ep_regs_t *out_regs = core_if->dev_if->out_ep_regs[0];
+
+ depctl.d32 = DWC_READ_REG32(&out_regs->doepctl);
+ deptsiz.d32 = DWC_READ_REG32(&out_regs->doeptsiz);
+
+ deptsiz.b.xfersize = ep->maxpacket;
+ deptsiz.b.pktcnt = 1;
+ DWC_WRITE_REG32(&out_regs->doeptsiz, deptsiz.d32);
+ depctl.b.cnak = 1;
+ depctl.b.epena = 1;
+ DWC_WRITE_REG32(&out_regs->doepctl, depctl.d32);
+
+ }
+}
+
+
+/**
+ * This function writes a packet into the Tx FIFO associated with the
+ * EP. For non-periodic EPs the non-periodic Tx FIFO is written. For
+ * periodic EPs the periodic Tx FIFO associated with the EP is written
+ * with all packets for the next micro-frame.
+ *
+ * @param core_if Programming view of DWC_otg controller.
+ * @param ep The EP to write packet for.
+ * @param dma Indicates if DMA is being used.
+ */
+void dwc_otg_ep_write_packet(dwc_otg_core_if_t * core_if, dwc_ep_t * ep,
+ int dma)
+{
+ uint32_t i;
+ uint32_t byte_count;
+ uint32_t dword_count;
+ uint32_t *fifo;
+ uint32_t *data_buff = (uint32_t *) ep->xfer_buff;
+
+ if (ep->xfer_count >= ep->xfer_len)
+ {
+ return;
+ }
+
+ /* Find the byte length of the packet either short packet or MPS */
+ if ((ep->xfer_len - ep->xfer_count) < ep->maxpacket)
+ {
+ byte_count = ep->xfer_len - ep->xfer_count;
+ }
+ else
+ {
+ byte_count = ep->maxpacket;
+ }
+
+ /* Find the DWORD length, padded by extra bytes as neccessary if MPS
+ * is not a multiple of DWORD */
+ dword_count = (byte_count + 3) / 4;
+
+ /**@todo NGS Where are the Periodic Tx FIFO addresses
+ * intialized? What should this be? */
+ //printf("fifo = core_if->data_fifo[ep->num];\n");
+ fifo = core_if->data_fifo[ep->num];
+ for (i = 0; i < dword_count; i++, data_buff++)
+ {
+ DWC_WRITE_REG32(fifo, *data_buff);
+
+ }
+
+
+ ep->xfer_count += byte_count;
+ ep->xfer_buff += byte_count;
+}
+
+/**
+ * Set the EP STALL.
+ *
+ * @param core_if Programming view of DWC_otg controller.
+ * @param ep The EP to set the stall on.
+ */
+void dwc_otg_ep_set_stall(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
+{
+ depctl_data_t depctl;
+ volatile uint32_t *depctl_addr;
+ if (ep->is_in == 1)
+ {
+ 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);
+
+ depctl.b.stall = 1;
+ DWC_WRITE_REG32(depctl_addr, depctl.d32);
+ }
+
+ return;
+}
+
+/**
+ * Clear the EP STALL.
+ *
+ * @param core_if Programming view of DWC_otg controller.
+ * @param ep The EP to clear stall from.
+ */
+void dwc_otg_ep_clear_stall(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
+{
+ depctl_data_t depctl;
+ volatile uint32_t *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);
+ return;
+}
+
+/**
+ * This function reads a packet from the Rx FIFO into the destination
+ * buffer. To read SETUP data use dwc_otg_read_setup_packet.
+ *
+ * @param core_if Programming view of DWC_otg controller.
+ * @param dest Destination buffer for the packet.
+ * @param bytes Number of bytes to copy to the destination.
+ */
+void dwc_otg_read_packet(dwc_otg_core_if_t * core_if,
+ uint8_t * dest, uint16_t bytes)
+{
+ int i;
+ int word_count = (bytes + 3) / 4;
+
+ volatile uint32_t *fifo = core_if->data_fifo[0];
+ uint32_t *data_buff = (uint32_t *) dest;
+
+
+ for (i = 0; i < word_count; i++, data_buff++)
+ {
+ *data_buff = DWC_READ_REG32(fifo);
+ }
+
+ return;
+}
+
+/**
+ * Flush a Tx FIFO.
+ *
+ * @param core_if Programming view of DWC_otg controller.
+ * @param num Tx FIFO to flush.
+ */
+void dwc_otg_flush_tx_fifo(dwc_otg_core_if_t * core_if, const int num)
+{
+ dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
+ volatile grstctl_t greset;
+ int count = 0;
+ greset.d32 = 0;
+
+ greset.b.txfflsh = 1;
+ greset.b.txfnum = num;
+if(global.g_enum == NEED_ENUM)
+{
+ DWC_WRITE_REG32(&global_regs->grstctl, greset.d32);
+
+ do
+ {
+ greset.d32 = DWC_READ_REG32(&global_regs->grstctl);
+ if (++count > 10000)
+ {
+ break;
+ }
+ usdelay(10);
+ }
+ while (greset.b.txfflsh == 1);
+
+ /* Wait for 3 PHY Clocks */
+ usdelay(10);
+}
+
+}
+
+/**
+ * Flush Rx FIFO.
+ *
+ * @param core_if Programming view of DWC_otg controller.
+ */
+void dwc_otg_flush_rx_fifo(dwc_otg_core_if_t * core_if)
+{
+ dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
+ volatile grstctl_t greset;
+ int count = 0;
+ greset.d32 = 0;
+ greset.b.rxfflsh = 1;
+if(global.g_enum == NEED_ENUM)
+{
+ DWC_WRITE_REG32(&global_regs->grstctl, greset.d32);
+
+ do
+ {
+ greset.d32 = DWC_READ_REG32(&global_regs->grstctl);
+ if (++count > 10000)
+ {
+ break;
+ }
+ usdelay(10);
+ }
+ while (greset.b.rxfflsh == 1);
+
+ /* Wait for 3 PHY Clocks */
+
+ usdelay(10);
+}
+}
+
+/**
+ * Do core a soft reset of the core. Be careful with this because it
+ * resets all the internal state machines of the core.
+ */
+void dwc_otg_core_reset(dwc_otg_core_if_t * core_if)
+{
+ dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
+ volatile grstctl_t greset;
+ int count = 0;
+ greset.d32 =0;
+ /* Wait for AHB master IDLE state. */
+ do
+ {
+ usdelay(10);
+ greset.d32 = DWC_READ_REG32(&global_regs->grstctl);
+ if (++count > 100000)
+ {
+ return;
+ }
+ }
+ while (greset.b.ahbidle == 0);
+
+ /* Core Soft Reset */
+ count = 0;
+ greset.b.csftrst = 1;
+ DWC_WRITE_REG32(&global_regs->grstctl, greset.d32);
+ do
+ {
+ greset.d32 = DWC_READ_REG32(&global_regs->grstctl);
+ if (++count > 10000)
+ {
+ break;
+ }
+ usdelay(10);
+ }
+ while (greset.b.csftrst == 1);
+/* Wait for 3 PHY Clocks */
+ usdelay(10);
+}
+
+static int dwc_otg_setup_params(dwc_otg_core_if_t * core_if)
+{
+ int i;
+ core_if->core_params = &global.g_core_params;
+ core_if->core_params->otg_cap = DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE;
+ #if USB_PHY == ULPI
+ core_if->core_params->phy_type = DWC_PHY_TYPE_PARAM_ULPI;
+ #elif USB_PHY == UTMI
+ core_if->core_params->phy_type = DWC_PHY_TYPE_PARAM_UTMI;
+ #endif
+
+ core_if->core_params->speed = DWC_SPEED_PARAM_HIGH;//DWC_SPEED_PARAM_FULL
+ core_if->core_params->phy_ulpi_ddr = dwc_param_phy_ulpi_ddr_default;
+ core_if->core_params->phy_ulpi_ext_vbus = dwc_param_phy_ulpi_ext_vbus_default;
+ //fpga use 30M,16bit width asic use 60M,8bit width add tj
+ core_if->core_params->phy_utmi_width = 8;
+
+ core_if->core_params->ts_dline = dwc_param_ts_dline_default;
+ core_if->core_params->ulpi_fs_ls = dwc_param_ulpi_fs_ls_default;
+ core_if->core_params->en_multiple_tx_fifo = dwc_param_en_multiple_tx_fifo_default;
+ for (i = 0; i < 15; i++)
+ {
+ core_if->core_params->dev_tx_fifo_size[i] = dwc_param_dev_tx_fifo_size_default;
+ }
+ core_if->core_params->otg_ver = 1;
+ return 0;
+}
+
+
+
+
+
+
+
diff --git a/boot/common/src/uboot/drivers/usb_drv/dwc_otg_cil_intr.c b/boot/common/src/uboot/drivers/usb_drv/dwc_otg_cil_intr.c
new file mode 100644
index 0000000..1e50cf1
--- /dev/null
+++ b/boot/common/src/uboot/drivers/usb_drv/dwc_otg_cil_intr.c
@@ -0,0 +1,69 @@
+/* ==========================================================================
+ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_cil_intr.c $
+ * $Revision: #32 $
+ * $Date: 2012/08/10 $
+ * $Change: 2047372 $
+ *
+ * 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.
+ *
+ * This file contains the Common Interrupt handlers.
+ */
+
+#include <usb/dwc_otg_regs.h>
+#include <usb/dwc_otg_cil.h>
+#include <usb/dwc_otg_driver.h>
+#include <usb/dwc_otg_pcd.h>
+/**
+ * This interrupt indicates that SUSPEND state has been detected on
+ * the USB.
+ *
+ * For HNP the USB Suspend interrupt signals the change from
+ * "a_peripheral" to "a_host".
+ *
+ * When power management is enabled the core will be put in low power
+ * mode.
+ */
+int32_t dwc_otg_handle_usb_suspend_intr(dwc_otg_core_if_t * core_if)
+{
+ gintsts_data_t gintsts;
+ printk("Suspend\n");
+
+ /* Clear interrupt */
+ gintsts.d32 = 0;
+ gintsts.b.usbsuspend = 1;
+ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);
+
+ return 1;
+}
+
diff --git a/boot/common/src/uboot/drivers/usb_drv/dwc_otg_dev_test.c b/boot/common/src/uboot/drivers/usb_drv/dwc_otg_dev_test.c
new file mode 100755
index 0000000..b25466c
--- /dev/null
+++ b/boot/common/src/uboot/drivers/usb_drv/dwc_otg_dev_test.c
@@ -0,0 +1,732 @@
+/******************************************************************/
+#include <usb/global.h>
+#include <usb/dwc_otg_driver.h>
+#include <usb/drv_usb3slave.h>
+#include <asm/arch/cpu.h>
+#include <asm/io.h>
+#include <config.h>
+
+
+#define SYS_SOC_MOD_CLKSEL (SYS_SOC_CRM_BASE+0x54)
+#define SYS_SOC_MOD_RSTEN (SYS_SOC_CRM_BASE+0x8c)
+#define SYS_SOC_MOD_USBSTATECTRL (SYS_SOC_CRM_BASE+0x90)
+
+#define ST_WAIT_SYNC_FLAG (0x0)
+#define ST_WAIT_REG_CONFIG (0x1)
+#define ST_REG_CONFIG (0x2)
+#define ST_WAIT_DOWNLOAD (0x3)
+#define ST_DOWNLOAD_HEAD (0x4)
+#define ST_DOWNLOAD_DATA (0x5)
+#define ST_DOWNLOAD_ADDR (0x6)
+
+#define SYNC_FLAG (0x5a) // "Z"
+#define REG_CONFIG_FLAG (0x6a) // ""
+#define DOWNLOAD_FLAG (0x7a) // "z"
+#define RUN_FLAG (0x8a) // ""
+#define GET_ID (0x9a) // new added
+
+WORD32 Para_Section SyncACK=0xa5;
+__align(4) BYTE Para_Section CHIP_ID[8]={'Z','X','7','5','2','0','V','2'};
+WORD32 Para_Section UsbACK = 0;
+
+extern void udelay(unsigned long usec);
+void USB_isr(WORD32 dwIntNo,WORD32 dwPara);
+
+void Out_callback( WORD32 dwPara, WORD32 dwCause, WORD32 dwDone, WORD32 dwLen);
+
+
+void In_callback( WORD32 dwPara, WORD32 dwCause, WORD32 dwDone, WORD32 dwLen);
+
+
+
+void usdelay(unsigned us)
+{
+ udelay(us);
+}
+
+static inline void delay0(unsigned long loops)
+{
+ /*
+ __asm__ volatile ("1:\n" "subs %0, %1, #1\n"
+ "bne 1b":"=r" (loops):"0"(loops));
+ */
+}
+static inline void udelay0(unsigned long us)
+{
+ delay0(us * 200); /* approximate */
+}
+
+void usbdelay(unsigned us)
+{
+ udelay0(us);
+}
+
+void USB_TstDev_Isr(void)
+{
+ USB_isr(0,0); //´¦ÀíÖжϷþÎñ
+}
+
+
+WORD32 USB_RecvOutData(WORD32 dwEPNo, BYTE *pchBuf, WORD32 dwLen, F_USB_CB fnUsbCb, void *pPara)
+{
+ dwc_otg_pcd_ep_t *ep = NULL;
+ ep = &(global.g_dwc_otg_dev_t.pcd->out_ep[dwEPNo-1]);
+ ep->dwc_ep.is_in = 0;
+ ep->dwc_ep.num = dwEPNo;
+ ep->dwc_ep.data_pid_start = 0;
+ ep->dwc_ep.tx_fifo_num = dwEPNo;
+ ep->dwc_ep.start_xfer_buff = pchBuf;
+ ep->dwc_ep.xfer_buff = pchBuf;
+ ep->dwc_ep.xfer_len = 0;
+ ep->dwc_ep.xfer_count = 0;
+ ep->dwc_ep.fnUsbCb = fnUsbCb;
+ ep->dwc_ep.pPara = pPara;
+ ep->dwc_ep.total_len = dwLen;
+ dwc_otg_ep_start_transfer(global.g_dwc_otg_dev_t.core_if,&ep->dwc_ep);
+ return 0;
+}
+
+WORD32 USB_SendInData(WORD32 dwEPNo, BYTE *pchBuf, WORD32 dwLen, F_USB_CB fnUsbCb, void *pPara)
+{
+ dwc_otg_pcd_ep_t *ep = NULL;
+ ep = &(global.g_dwc_otg_dev_t.pcd->in_ep[dwEPNo-1]);
+ ep->dwc_ep.is_in = 1;
+ ep->dwc_ep.num = dwEPNo;
+ ep->dwc_ep.data_pid_start = 0;
+ ep->dwc_ep.tx_fifo_num = dwEPNo;
+ ep->dwc_ep.start_xfer_buff = pchBuf;
+ ep->dwc_ep.xfer_buff = pchBuf;
+ ep->dwc_ep.fnUsbCb = fnUsbCb;
+ ep->dwc_ep.pPara = pPara;
+ ep->dwc_ep.xfer_len = 0;
+ ep->dwc_ep.xfer_count = 0;
+ ep->dwc_ep.total_len = dwLen;
+ dwc_otg_ep_start_transfer(global.g_dwc_otg_dev_t.core_if,&ep->dwc_ep);
+ return 0;
+}
+
+
+WORD32 usb_read(WORD32 dwLen, BYTE *pchBuf)
+{
+ WORD32 dwDone;
+
+ global.dwRxQuit=0;
+ USB_RecvOutData( 1,(BYTE *)pchBuf,dwLen,Out_callback,(void *)&dwDone);
+ while(!global.dwRxQuit)
+ {
+ USB_TstDev_Isr();
+ }
+ return dwDone;
+}
+
+
+WORD32 usb_write(WORD32 dwLen, BYTE *pchBuf)
+{
+ WORD32 dwDone;
+
+ global.dwTxQuit=0;
+ USB_SendInData(1,pchBuf, dwLen, In_callback,(void *)&dwDone);
+ while(!global.dwTxQuit)
+ {
+
+ USB_TstDev_Isr();
+ }
+
+ return dwDone;
+}
+
+#if 0
+WORD32 USB_Check_Sync(BYTE *pchBuf, WORD32 dwLen)
+{
+ WORD32 dwDone;
+ WORD32 dwCount = 0;
+
+ global.dwRxQuit=0;
+ printf("########USB_RecvOutData start##########\n");
+ USB_RecvOutData( 1,(BYTE *)pchBuf,dwLen,Out_callback,(void *)&dwDone);
+ printf("########USB_RecvOutData end##########\n");
+ dwCount=0;
+ while(1)
+ {
+ USB_TstDev_Isr();
+ if(0==global.dwRxQuit)
+ {
+ dwCount++;
+ if(dwCount>(200*global.g_USB_TIMEOUT))
+ {
+ //return 0;
+ }
+#if SIM_EN
+ //usbdelay(5000);
+#else
+ usbdelay(1);
+#endif
+ }
+ else
+ {
+ printf("global.dwRxQuit == 1 \n");
+ break;
+ }
+ }
+ printf("########5a##########\n");
+ if(0x5A!=*pchBuf)
+ {
+ printf("0x5A!=*pchBuf \n");
+ return 0;
+ }
+ printf("########end 5a##########\n");
+ return dwDone;
+}
+#endif
+
+#if 0
+char the_write_data;
+void Boot_Process(BYTE *pkt,int len)
+{
+ int i=0;
+ static int count=0;
+ static int addr;
+ static int value;
+ char cTmp=0;
+ //WORD32 SyncACK=0xa5;
+ int case_state;
+ if(0==len)
+ return ;
+ while(i<len)
+ {
+ cTmp=pkt[i++];
+ the_write_data=cTmp;
+ printf("usb_booting 0 \n");
+ case_state = global.g_State;
+ if( ST_WAIT_SYNC_FLAG == case_state)
+ {
+ printf("usb_booting 1 \n");
+ if(SYNC_FLAG==cTmp)
+ {
+ printf("get 5A \n");
+ global.g_State=ST_WAIT_DOWNLOAD;
+#if CFG_USB
+ printf("usb_write A5\n");
+ usb_write(1,(BYTE *)&SyncACK);
+ printf("usb_write A5 over\n");
+#else
+ printf(" CFG_USB ==0 \n");
+ UART_Write((BYTE *)&SyncACK,1);
+#endif
+ }
+ }
+ else if(GET_ID==cTmp)//¶ÁȡоƬID
+ {
+#if CFG_USB
+ usb_write(8,(BYTE*)CHIP_ID);
+#else
+ UART_Write((BYTE *)CHIP_ID,8);
+#endif
+ }
+ else if(ST_REG_CONFIG ==case_state)
+ {
+ if(count<4) // 4 bytes addr
+ {
+ addr<<=8;
+ addr|=cTmp;
+ }
+ else if(count<8) // 4 byte data
+ {
+ value<<=8;
+ value|=cTmp;
+ }
+
+ count++;
+
+ if(4==count)
+ {
+ if(0==addr)
+ {
+ global.g_State=ST_WAIT_DOWNLOAD;
+ UsbACK=0xA6;
+#if CFG_USB
+ usb_write(1,&UsbACK);
+#else
+ UART_Write(&UsbACK,1);
+#endif
+ }
+ }
+ else if(8==count)
+ {
+ REG32(addr)=value;
+ count=0;
+ }
+
+ }
+ else if (ST_WAIT_DOWNLOAD==case_state)
+ {
+ if(REG_CONFIG_FLAG==cTmp)
+ {
+ global.g_State=ST_REG_CONFIG;
+ count=0;
+ }
+ else if(DOWNLOAD_FLAG==cTmp)
+ {
+ global.g_State=ST_DOWNLOAD_HEAD;
+ count=0;
+ value=0;
+ }
+ else if(RUN_FLAG==cTmp) //Ö§³Ö¶à´ÎÏÂÔØ0818
+ {
+ global.g_State=ST_DOWNLOAD_ADDR;
+ count=0;
+ value=0;
+ }
+ }
+ else if( ST_DOWNLOAD_HEAD==case_state)
+ {
+ if(count<4) // 4 byte addr
+ {
+ addr<<=8;
+ addr|=cTmp;
+ }
+ else if(count<8) // 4 byte size
+ {
+ value<<=8;
+ value|=cTmp;
+ }
+
+ count++;
+
+ if(count==8)
+ {
+ count=0;
+ global.g_bootaddr=addr; //µØÖ·
+ global.g_bootsize=value;//³¤¶È
+ global.g_State=ST_DOWNLOAD_DATA;
+ UsbACK=0xA1;
+ usb_write(1,&UsbACK);
+ }
+ }
+ else if( ST_DOWNLOAD_DATA==case_state)
+ {
+ if(global.g_bootsize==len)
+ {
+ if(global.g_bootaddr==(int)pkt)
+ {
+ global.g_State=ST_WAIT_DOWNLOAD;//Ö§³Ö¶à´ÎÏÂÔØ0818
+ UsbACK=0xA7;
+ usb_write(1,&UsbACK);
+ return;
+ }
+ }
+ else
+ {
+ global.g_bootaddr+=len;
+ global.g_bootsize-=len;
+ return ;
+ }
+ }
+ else if( ST_DOWNLOAD_ADDR==case_state)
+ {
+ if(count<4) // 4 byte addr
+ {
+ addr<<=8;
+ addr|=cTmp;
+ }
+
+ count++;
+
+ if(count==4)
+ {
+ count=0;
+ global.g_bootaddr=addr;
+ global.g_bootfinish=1;
+ UsbACK=0xA8;
+ usb_write(1,&UsbACK);
+ return ;
+ }
+ }
+ else
+ {
+
+ }
+
+ }
+
+}
+#endif
+
+__align(4) BYTE Para_Section tmp[64]={0};
+
+
+#if 0 //loaderϵ÷Óã»
+void USB_Boot(void)
+{
+ WORD32 dwLen;
+ WORD32 dwMaxLen;
+ BYTE *pbyBuf;
+ printf("######enter USB_Boot#####\n");
+ global.g_State = ST_WAIT_SYNC_FLAG;
+ pbyBuf = (BYTE*)tmp;
+
+ for(dwMaxLen = 0; dwMaxLen < 64; dwMaxLen++)
+ {
+ tmp[dwMaxLen] = 0;
+ }
+
+ dwMaxLen = 512; //¿ØÖÆÆ÷ÓÐÒªÇóbulk outʱ£¬½ÓÊÕ³¤¶È´óÓÚµÈÓÚ512
+/* µ±usb_mode =1ʱ£¬ÓÃÓÚHSIC,µ±usb_mode =0ʱ£¬ÓÃÓÚUSB */
+ if(global.g_USB_MODE == 0)
+ {
+ printf("########USB_Check_Sync##########\n");
+ dwLen=USB_Check_Sync(pbyBuf,dwMaxLen);
+
+ if(0==dwLen)
+ {
+ return ;
+ }
+ printf("0!=dwLen,enter boot_process\n");
+
+ Boot_Process(pbyBuf,dwLen);
+ }
+ printf("########globalfinish##########\n");
+ while(0 == global.g_bootfinish)
+ {
+ //dwLen=usb_read(pbyBuf,dwMaxLen);
+ dwLen=usb_read(dwMaxLen,pbyBuf);
+
+ Boot_Process(pbyBuf,dwLen);
+
+ if((ST_DOWNLOAD_DATA==global.g_State)&&(global.g_bootaddr!=0))
+ {
+ pbyBuf=(BYTE *)global.g_bootaddr;
+ dwMaxLen=512;//global.g_bootsize;
+ }
+ else
+ {
+ pbyBuf=tmp;
+ dwMaxLen=512;//½ÓÊÕµØÖ·£¬³¤¶ÈÐÅÏ¢
+ }
+
+ }
+
+ if(1==global.g_bootfinish)
+ {
+ #if 0 /*shield dma function*/
+ dwc_otg_core_dev_disconnet(global.g_dwc_otg_pcd_tp.core_if);
+ printf("disconnect usb controller\n");
+ #endif
+ writel(0xE59ff000, SYS_IRAM1_BASE); /* Ìø×ªµ½r7Ö´ÐÐtboot */
+ writel(global.g_bootaddr, SYS_IRAM1_BASE + 8);
+ printf("Starting the t-boot ...\n");
+ writel(0xf, CPU_A9_SUBSYS_CFG);
+ }
+}
+#endif
+
+void usb_boot(WORD32 USB_ADDR)
+{
+ global.g_USB_TIMEOUT = 0xff;
+
+ //printf( "#######tsp_usb_init...\n");
+ tsp_usb_init(); /*ÅäÖÃÍâΧ»·¾³£¬Ã¶¾ÙTLOADERµÄUSB¶Ë¿Ú*/
+ //printf("tsp_usb_init...end\n");
+
+ //USB_Boot(); /*usb bootÏÂÔØÄ£Ê½*/
+}
+
+
+void USB_isr(WORD32 dwIntNo,WORD32 dwPara)
+{
+ dwc_otg_pcd_handle_intr(global.g_dwc_otg_dev_t.pcd);
+}
+
+#if 0
+void USB_Pll_Clk_Rst_InitEnv(void)
+{
+
+#if ((SIM_EN == ASIC)||(SIM_EN == EMULATION))
+
+ WORD32 i;
+ if(0 == global.g_pll_cfg)
+ {
+ //add pll config
+ REG32(SYS_SOC_CRM_BASE+0x30) = 0x1ffff; //pll_MAIN lock need delay time
+ REG32(SYS_SOC_CRM_BASE+0x34) = 0x1ffff; //pll_U lock need delay time for HSIC
+ //open pll_624_MainPll
+ REG32(SYS_SOC_CRM_BASE+0x14) &= 0xffffffff;
+ REG32(SYS_SOC_CRM_BASE+0x10) &= 0x7fffffff;
+
+ i = 0;
+ do
+ {
+ i++;
+ usdelay(PLL_8X(40));
+ if(i>50000)
+ {
+ printk("E1");
+ break;
+ }
+ }while((REG32(SYS_SOC_CRM_BASE+0x10)&0x40000000) ==0);
+
+ //HSIC need pll_480
+ if(1 == global.g_USB_MODE)
+ {
+ //open pll_480
+ REG32(SYS_SOC_CRM_BASE+0x24) &= 0xffffffff;
+ REG32(SYS_SOC_CRM_BASE+0x20) &= 0x7fffffff;
+
+ i = 0;
+ do
+ {
+ i++;
+ usdelay(PLL_8X(40));
+ if(i>50000)
+ {
+ printk("E2");
+ break;
+ }
+ }while((REG32(SYS_SOC_CRM_BASE+0x20)&0x40000000) ==0);
+ }
+
+ // m0 and axi clk sel config ,M0 208M,axi 156M
+ REG32(SYS_SOC_CRM_BASE+0x50) &= (~0x7); //0:m0 sel pll_208 1:mclk
+ REG32(SYS_STD_CRM_BASE+0x0) &= (~0x7); //0:axi sel 156m 1:mclk
+
+#if SIM_EN == EMULATION
+ /* 1.pin mux*/
+ REG32(SYS_PAD_CTRL0_BASE+0x7c)&= 0x3ff00000;
+ REG32(SYS_PAD_CTRL0_BASE+0x80)&= (~0x3ff);
+ REG32(SYS_PAD_CTRL0_BASE+0x84)&= 0x3ff00000;
+ REG32(SYS_PAD_CTRL0_BASE+0x74)&= 0xc00ffc00;
+ REG32(SYS_PAD_CTRL0_BASE+0x88)&= (~0xffc00);
+
+ /* 2.out or in enable*/
+ REG32(0x145000)&=0xff00; //in
+ REG32(0x145000+0x40)|=0xff; //out
+#endif
+ }
+ if(0 == global.g_USB_MODE)
+ {
+
+ REG32(SYS_SOC_MOD_RSTEN)|=(0x3<<5);
+ usdelay(10);
+ //select bus clk early
+ REG32(SYS_SOC_MOD_CLKSEL) &= ~0x3;
+ //release usb phy reset
+ usdelay(10);
+ REG32(SYS_SOC_MOD_RSTEN) |= 1<<4;
+ }
+ else if(1 == global.g_USB_MODE)
+ {
+ REG32(SYS_SOC_MOD_RSTEN)|=(0x3<<1);
+ usdelay(10);
+ //select bus clk early
+ REG32(SYS_SOC_MOD_CLKSEL) &= ~0x3; /*0:156M*/
+ usdelay(10);
+ //release usb hsic phy reset
+ REG32(SYS_SOC_MOD_RSTEN) |= 0x1;
+ usdelay(100);
+ i = 0;
+ while((REG32(SYS_SOC_MOD_USBSTATECTRL)&0x1) == 0)
+ {
+ i++;
+ usdelay(20);
+ if(i>250000)
+ {
+ printk("E4");
+ break;
+ }
+ }
+#if SIM_EN == EMULATION
+ usdelay(20);
+ REG32(REG_GPIO_OUT)=1;
+// while(REG32(REG_GPIO_IN)!=0xFF);
+ usdelay(1);
+ REG32(REG_GPIO_OUT)=0;
+#endif
+
+ }
+ else if(2 == global.g_USB_MODE)
+ {
+ REG32(SYS_LSP_CRM_BASE+0x28) &= (~(0x7<<4)); /*0:104M 1:26M,2:52M,4:156M*/
+ usdelay(10);
+ REG32(SYS_STD_CRM_BASE+0x4)&= ~0x3; /*div 0:1 1:2 4:4*/
+ usdelay(10);
+ }
+
+#elif (SIM_EN == FPGA)
+ if(0 == global.g_USB_MODE)
+ {
+
+ REG32(SYS_SOC_MOD_RSTEN)|=(0x3<<5);
+ usdelay(10);
+ //select bus clk early
+ REG32(SYS_SOC_MOD_CLKSEL) &= ~0x3;
+ //release usb phy reset
+ usdelay(10);
+ REG32(SYS_SOC_MOD_RSTEN) |= 1<<4;
+ }
+
+#endif
+}
+#endif
+
+T_USB_ENUM USB_Need_Enum(WORD32 USB_ADDR)
+{
+ WORD32 temp = 0;
+ temp = DWC_READ_REG32(USB_ADDR+0x14);
+ if(((temp>>13)|1)==1)
+ {
+ return DONOT_NEED_ENUM;
+ }
+ return NEED_ENUM;
+}
+unsigned int g_testVal = 0;
+
+WORD32 USB_CDC_Enum(WORD32 USB_ADDR)
+{
+ WORD32 dwCount=0;
+ WORD32 dwCount1=0;
+ if(NEED_ENUM == global.g_enum)
+ {
+ global.g_Connet = 0;
+ }
+ else
+ {
+ global.g_Connet = 1;
+ }
+
+ global.g_USB_TIMEOUT = 10;
+
+ g_testVal = 20/5;
+ dwc_otg_driver_probe(USB_ADDR);
+ if(global.g_enum == NEED_ENUM)
+ {
+ //printk("enuming\n");
+ while (1)
+ {
+ //poll mode or interrupt mode
+ USB_TstDev_Isr();
+#if SYNC_SETADDRESS
+ if (global.g_dwc_otg_dev_t.pcd->request_config == 2)
+ break;
+#else
+ //µÈ´ý½øÈëÅäÖÃ̬
+ if (global.g_dwc_otg_dev_t.pcd->request_config == 1)
+ break;
+#endif
+/* µ±usb_mode =1ʱ£¬ÓÃÓÚHSIC,µ±usb_mode =0ʱ£¬ÓÃÓÚUSB */
+ if(global.g_USB_MODE == 0)
+ {
+ if(0==global.g_Connet)
+ {
+ dwCount++;
+#if SIM_EN
+ usbdelay(5000);
+#else
+ usbdelay(1);
+#endif
+ if(dwCount>(400*global.g_USB_TIMEOUT))
+ {
+ //return 1;
+ }
+ }
+#if SYNC_SETADDRESS
+ else if(global.g_dwc_otg_dev_t.pcd->request_config == 2)
+#else
+ else if(global.g_dwc_otg_dev_t.pcd->request_config == 1)
+#endif
+ {
+ break;
+ }
+ else
+ {
+ dwCount1++;
+#if SIM_EN
+ //usbdelay(5000);
+#else
+ usbdelay(1);
+#endif
+ if(dwCount1>(200*global.g_USB_TIMEOUT))
+ {
+ //return 1; huhuahong
+ }
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+void Out_callback( WORD32 dwPara, WORD32 dwCause, WORD32 dwDone, WORD32 dwLen)
+{
+ *((WORD32 *)dwPara) = dwDone;
+ global.dwRxQuit = 1;
+#if SIM_EN == EMULATION
+ REG32(ARM_PORTA)=0x81;
+#endif
+
+}
+
+void In_callback( WORD32 dwPara, WORD32 dwCause, WORD32 dwDone, WORD32 dwLen)
+{
+ *((WORD32 *)dwPara) = dwDone;
+ global.dwTxQuit = 1;
+#if SIM_EN == EMULATION
+ REG32(ARM_PORTA)=0x83;
+#endif
+}
+
+
+//tangjian:µ÷ÓÃusb3.0µÄÊý¾Ý¶ÁºÍдº¯Êý
+extern WORD32 USB3_RecvOutData(WORD32 dwEPNo, BYTE *pchBuf, WORD32 dwLen, F_USB_CB fnUsbCb, void *pPara);
+extern WORD32 USB3_SendInData(WORD32 dwEPNo, BYTE *pchBuf, WORD32 dwLen, F_USB_CB fnUsbCb, void *pPara);
+extern void USB3Slave_ISR(u32 udIntNo,u32 udPara);
+extern u32 USB3Slave_IsNeedZero(u32 dwLen);
+
+
+
+
+
+
+
+
+
+int dwc_otg_driver_probe(WORD32 USB_ADDR)
+{
+ uint32_t udj = 0;
+ uint32_t *ptbase = (uint32_t *)USB_ADDR;
+ uint8_t* ptg_dwc_otg_dev_t = (uint8_t* )(&global.g_dwc_otg_dev_t);
+
+ for(udj= 0;udj<sizeof(global.g_dwc_otg_dev_t);udj++)
+ {
+ ptg_dwc_otg_dev_t[udj] = 0;
+ }
+ global.g_dwc_otg_dev_t.core_if = dwc_otg_cil_init(ptbase);
+
+ /*
+ * Initialize the DWC_otg core.
+ */
+ dwc_otg_core_init(global.g_dwc_otg_dev_t.core_if);
+ /*
+ * Initialize the PCD,½«pcd_initÕª³öÀ´
+ */
+ global.g_dwc_otg_dev_t.pcd = dwc_otg_pcd_init(global.g_dwc_otg_dev_t.core_if);
+
+#if SYNC_USB_CTRL
+ REG32(ARM_PORTA)=0x22;
+#endif
+
+#if SIM_EN == EMULATION
+ //for hsic
+ REG32(REG_GPIO_OUT)=2;
+ //while(REG32(REG_GPIO_IN)!=0xFF);
+ usdelay(1);
+ REG32(REG_GPIO_OUT)=0;
+#endif
+ global.g_dwc_otg_dev_t.pcd->otg_dev = (&global.g_dwc_otg_dev_t);
+ if(global.g_enum == NEED_ENUM)
+ {
+ DWC_MODIFY_REG32(&global.g_dwc_otg_dev_t.core_if->core_global_regs->gahbcfg, 0, 1);
+ }
+ return 0;
+}
+
+
diff --git a/boot/common/src/uboot/drivers/usb_drv/dwc_otg_pcd.c b/boot/common/src/uboot/drivers/usb_drv/dwc_otg_pcd.c
new file mode 100644
index 0000000..bf93b71
--- /dev/null
+++ b/boot/common/src/uboot/drivers/usb_drv/dwc_otg_pcd.c
@@ -0,0 +1,327 @@
+/* ==========================================================================
+ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_pcd.c $
+ * $Revision: #101 $
+ * $Date: 2012/08/10 $
+ * $Change: 2047372 $
+ *
+ * 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.
+ * ========================================================================== */
+#ifndef DWC_HOST_ONLY
+
+/** @file
+ * This file implements PCD Core. All code in this file is portable and doesn't
+ * use any OS specific functions.
+ * PCD Core provides Interface, defined in <code><dwc_otg_pcd_if.h></code>
+ * header file, which can be used to implement OS specific PCD interface.
+ *
+ * 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.
+ *
+ * @todo Add Device Mode test modes (Test J mode, Test K mode, etc).
+ * @todo Does it work when the request size is greater than DEPTSIZ
+ * transfer size
+ *
+ */
+#include <usb/global.h>
+#include <usb/dwc_otg_pcd.h>
+
+__align(4) dwc_device_descriptor_t device_desc =
+{
+ sizeof(dwc_device_descriptor_t),
+ DEVICE_DESCRIPTOR,
+ 0x0200, // usb 2.0
+ 0x00,
+ 0x00,
+ 0x00,
+ CONTROL_64, // ×î´ó°ü8×Ö½Ú
+ USB_VENDOR_ID,
+ USB_PRODUCT_ID,
+ PRODUCT_RELEASE_NUMBER,
+ 0x01, // manufacturer descriptionË÷ÒýºÅ
+ 0x02, // product descriptionË÷ÒýºÅ
+ 0x00, //tj 0:host¸ù¾ÝusbÎïÀí¿ÚÀ´±£Ö¤USBÉ豸Ψһ 3:¸ù¾ÝϵÁкÅÀ´±£Ö¤USBÉ豸Ψһ
+ // serial number descriptionË÷ÒýºÅ
+ 0x01 // ÅäÖÃÊý
+};
+
+__align(4) dwc_dev_qual_descriptor_t dev_qual_desc =
+{
+ sizeof(dwc_dev_qual_descriptor_t),
+ 0x06,
+ 0x0110, // usb 1.1
+ VERDOR_SPECIFIC,
+ 0x00,
+ 0x00,
+ 64,
+ 0x01, // ÅäÖÃÊý
+ 0x0
+};
+
+
+
+__align(4) dwc_langid_descriptor_t tLanguage=
+{
+ STRING_DESCRIPTOR_SIZE(1),
+ STRING_DESCRIPTOR,
+ LANGID_US_ENGLISH
+};
+
+__align(4) dwc_string_descriptor_t tManufacture=
+{
+ STRING_DESCRIPTOR_SIZE(11),
+ STRING_DESCRIPTOR,
+ {UNICODE('Z'), UNICODE('T'), UNICODE('E'), UNICODE(' '), UNICODE('C'),
+ UNICODE('o'), UNICODE(','), UNICODE('L'), UNICODE('t'), UNICODE('d'),
+ UNICODE('.'),}
+};
+
+__align(4) dwc_string_descriptor_t tProduct=
+{
+ STRING_DESCRIPTOR_SIZE(14),
+ STRING_DESCRIPTOR,
+ {UNICODE('Z'), UNICODE('T'), UNICODE('E'), UNICODE(' '), UNICODE('B'),
+ UNICODE('o'), UNICODE('o'), UNICODE('t'), UNICODE('L'), UNICODE('o'),
+ UNICODE('a'), UNICODE('d'), UNICODE('e'), UNICODE('r')}
+};
+
+__align(4) dwc_string_descriptor_t tSN=
+{
+ STRING_DESCRIPTOR_SIZE(16),
+ STRING_DESCRIPTOR,
+ {UNICODE('z'), UNICODE('t'), UNICODE('e'), UNICODE('&'), UNICODE('u'),
+ UNICODE('s'), UNICODE('b'), UNICODE('B'), UNICODE('o'), UNICODE('o'),
+ UNICODE('t'), UNICODE('l'), UNICODE('o'), UNICODE('d'), UNICODE('e'),
+ UNICODE('r')}
+};
+
+__align(4) dwc_string_descriptor_t tIfc0Name=
+{
+ STRING_DESCRIPTOR_SIZE(9),
+ STRING_DESCRIPTOR,
+ {UNICODE('B'), UNICODE('o'), UNICODE('o'), UNICODE('t'), UNICODE('l'),
+ UNICODE('o'), UNICODE('d'), UNICODE('e'), UNICODE('r')}
+};
+
+__align(4) dwc_string_descriptor_t tIfc1Name=
+{
+ STRING_DESCRIPTOR_SIZE(6),
+ STRING_DESCRIPTOR,
+ {UNICODE('S'), UNICODE('e'), UNICODE('r'), UNICODE('i'), UNICODE('a'),
+ UNICODE('l')}
+};
+
+__align(4) dwc_string_descriptor_t * pStrDescIdx[]=
+{
+ (dwc_string_descriptor_t *)(&tLanguage),
+ (dwc_string_descriptor_t *)&tManufacture,
+ (dwc_string_descriptor_t *)&tProduct,
+ (dwc_string_descriptor_t *)&tSN,
+ (dwc_string_descriptor_t *)&tIfc0Name,
+ (dwc_string_descriptor_t *)&tIfc1Name,
+};
+
+
+static void do_get_descriptor(dwc_otg_pcd_t * pcd,uint32_t *buff,uint32_t len)
+{
+
+ dwc_otg_pcd_ep_t *ep0 = &pcd->ep0;
+ pcd->ep0_pending = 1;
+ ep0->dwc_ep.start_xfer_buff =(uint8_t*) buff;
+ ep0->dwc_ep.xfer_buff =(uint8_t*)buff;
+ ep0->dwc_ep.xfer_len = len;
+ ep0->dwc_ep.xfer_count = 0;
+ ep0->dwc_ep.total_len = ep0->dwc_ep.xfer_len;
+ dwc_otg_ep0_start_transfer(GET_CORE_IF(pcd), &ep0->dwc_ep);
+
+}
+
+extern void ep0_do_stall(dwc_otg_pcd_t * pcd, const int err_val);
+
+int dwc_setup(dwc_otg_pcd_t * pcd, usb_device_request_t * ctrl)
+{
+ uint8_t byIdx;
+ uint32_t len = 0;
+ uint16_t temp = 0;
+ byIdx = (uint8_t)(ctrl->wValue &0xff);
+ temp = ctrl->wValue>>8;
+ if(USB_DT_DEVICE == temp)
+ {
+ len = MIN( sizeof(dwc_device_descriptor_t), ctrl->wLength);
+ do_get_descriptor(pcd,(uint32_t*)&device_desc,len);
+ }
+ else if(USB_DT_CONFIG == temp)
+ {
+ len = MIN( sizeof(dwc_config_all_t), ctrl->wLength);
+ do_get_descriptor(pcd,(uint32_t*)&g_config_desc,len);
+ }
+
+ else if( USB_DT_STRING== temp)
+ {
+ if(byIdx > 5)
+ byIdx = 5;
+ len = MIN(((dwc_string_descriptor_t*)(pStrDescIdx[byIdx]))->bLength, ctrl->wLength);
+ do_get_descriptor(pcd,(uint32_t*)pStrDescIdx[byIdx],len);
+
+ }
+
+ else if( USB_DT_DEVICE_QUALIFIER == temp)
+ {
+ len = MIN(sizeof(dwc_dev_qual_descriptor_t),ctrl->wLength);
+ do_get_descriptor(pcd,(uint32_t*)&dev_qual_desc,len);
+ }
+ else
+ {
+ ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED);
+ }
+ return 0;
+}
+
+
+static void dwc_otg_pcd_init_ep(dwc_otg_pcd_t * pcd, dwc_otg_pcd_ep_t * pcd_ep,
+ uint32_t is_in, uint32_t ep_num)
+{
+ /* Init EP structure */
+ pcd_ep->desc = 0;
+ pcd_ep->pcd = pcd;
+ pcd_ep->stopped = 1;
+ pcd_ep->queue_sof = 0;
+
+ /* Init DWC ep structure */
+ pcd_ep->dwc_ep.is_in = is_in;
+ pcd_ep->dwc_ep.num = ep_num;
+ pcd_ep->dwc_ep.active = 0;
+ pcd_ep->dwc_ep.tx_fifo_num = 0;
+ /* Control until ep is actvated */
+ pcd_ep->dwc_ep.type = DWC_OTG_EP_TYPE_BULK;
+ pcd_ep->dwc_ep.maxpacket = 512;
+ pcd_ep->dwc_ep.maxxfer = 65536;
+
+ pcd_ep->dwc_ep.start_xfer_buff = 0;
+ pcd_ep->dwc_ep.xfer_buff = 0;
+ pcd_ep->dwc_ep.xfer_len = 0;
+ pcd_ep->dwc_ep.xfer_count = 0;
+ pcd_ep->dwc_ep.sent_zlp = 0;
+ pcd_ep->dwc_ep.total_len = 0;
+}
+
+/**
+ * Initialize ep's
+ */
+static void dwc_otg_pcd_reinit(dwc_otg_pcd_t * pcd)
+{
+ int i;
+ uint32_t hwcfg1;
+ dwc_otg_pcd_ep_t *ep;
+ int in_ep_cntr, out_ep_cntr;
+ uint32_t num_in_eps = (GET_CORE_IF(pcd))->dev_if->num_in_eps;
+ uint32_t num_out_eps = (GET_CORE_IF(pcd))->dev_if->num_out_eps;
+
+ /**
+ * Initialize the EP0 structure.
+ */
+ pcd->ep0.dwc_ep.pPara = (void*)(&global.g_in_pPara[1]);
+
+ ep = &pcd->ep0;
+ dwc_otg_pcd_init_ep(pcd, ep, 0, 0);
+
+ 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) == 0)
+ {
+ pcd->in_ep[in_ep_cntr].dwc_ep.pPara = (void*)(&global.g_in_pPara[in_ep_cntr]);
+ ep = &pcd->in_ep[in_ep_cntr];
+ in_ep_cntr++;
+ /**
+ * @todo NGS: Add direction to EP, based on contents
+ * of HWCFG1. Need a copy of HWCFG1 in pcd structure?
+ * sprintf(";r
+ */
+ dwc_otg_pcd_init_ep(pcd, ep, 1 /* IN */ , i);
+ }
+ 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) == 0)
+ {
+ pcd->out_ep[out_ep_cntr].dwc_ep.pPara = (void*)(&global.g_out_pPara[out_ep_cntr]);
+ ep = &pcd->out_ep[out_ep_cntr];
+ out_ep_cntr++;
+ /**
+ * @todo NGS: Add direction to EP, based on contents
+ * of HWCFG1. Need a copy of HWCFG1 in pcd structure?
+ * sprintf(";r
+ */
+ dwc_otg_pcd_init_ep(pcd, ep, 0 /* OUT */ , i);
+ }
+ hwcfg1 >>= 2;
+ }
+ if(NEED_ENUM == global.g_enum)
+ {
+ pcd->ep0state = EP0_DISCONNECT;
+ }
+ else
+ {
+ pcd->ep0state = EP0_IDLE;
+ }
+ pcd->ep0.dwc_ep.maxpacket = MAX_EP0_SIZE;
+ pcd->ep0.dwc_ep.type = 0;
+}
+
+/**
+ * This function initialized the PCD portion of the driver.
+ *
+ */
+dwc_otg_pcd_t *dwc_otg_pcd_init(dwc_otg_core_if_t * core_if)
+{
+ dwc_otg_pcd_t *pcd = (dwc_otg_pcd_t *)&global.g_dwc_otg_pcd_tp;
+ int i;
+ uint8_t* pt_dwc_otg_pcd_t = (uint8_t*)&global.g_dwc_otg_pcd_tp;
+ for(i = 0;i<sizeof(dwc_otg_pcd_t);i++)
+ {
+ pt_dwc_otg_pcd_t[i] = 0;
+ }
+
+ pcd->core_if = core_if;
+
+ pcd->setup_pkt = global.g_u_setup_pkt;
+ pcd->status_buf = &global.g_status_buf;
+ dwc_otg_pcd_reinit(pcd);
+
+ return pcd;
+}
+
+
+/******************************************************************************/
+
+#endif /* DWC_HOST_ONLY */
diff --git a/boot/common/src/uboot/drivers/usb_drv/dwc_otg_pcd_intr.c b/boot/common/src/uboot/drivers/usb_drv/dwc_otg_pcd_intr.c
new file mode 100644
index 0000000..29fd262
--- /dev/null
+++ b/boot/common/src/uboot/drivers/usb_drv/dwc_otg_pcd_intr.c
@@ -0,0 +1,1517 @@
+/* ==========================================================================
+ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_pcd_intr.c $
+ * $Revision: #116 $
+ * $Date: 2012/08/10 $
+ * $Change: 2047372 $
+ *
+ * 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.
+ * ========================================================================== */
+#ifndef DWC_HOST_ONLY
+#include <usb/dwc_otg_pcd.h>
+
+#ifdef DWC_UTE_CFI
+#include <usb/dwc_otg_cfi.h>
+#endif
+
+#include <usb/global.h>
+
+
+#if 1
+/**
+ * This function returns the Core Interrupt register.
+ */
+static uint32_t dwc_otg_read_core_intr(dwc_otg_core_if_t * core_if)
+{
+ return (DWC_READ_REG32(&core_if->core_global_regs->gintsts) &
+ DWC_READ_REG32(&core_if->core_global_regs->gintmsk));
+}
+
+
+/**
+ * This function reads the Device All Endpoints Interrupt register and
+ * returns the IN endpoint interrupt bits.
+ */
+static uint32_t dwc_otg_read_dev_all_in_ep_intr(dwc_otg_core_if_t *
+ core_if)
+{
+
+ uint32_t v;
+ {
+ v = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->daint) &
+ DWC_READ_REG32(&core_if->dev_if->dev_global_regs->daintmsk);
+ }
+ return (v & 0xffff);
+}
+
+/**
+ * This function reads the Device All Endpoints Interrupt register and
+ * returns the OUT endpoint interrupt bits.
+ */
+static uint32_t dwc_otg_read_dev_all_out_ep_intr(dwc_otg_core_if_t *
+ core_if)
+{
+ uint32_t v;
+
+ {
+ v = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->daint) &
+ DWC_READ_REG32(&core_if->dev_if->dev_global_regs->daintmsk);
+ }
+
+ return ((v & 0xffff0000) >> 16);
+}
+
+/**
+ * This function returns the Device IN EP Interrupt register
+ */
+static uint32_t dwc_otg_read_dev_in_ep_intr(dwc_otg_core_if_t * core_if,
+ dwc_ep_t * ep)
+{
+ dwc_otg_dev_if_t *dev_if = core_if->dev_if;
+ uint32_t v, msk, emp;
+
+ {
+ msk = DWC_READ_REG32(&dev_if->dev_global_regs->diepmsk);
+ emp = DWC_READ_REG32(&dev_if->dev_global_regs->dtknqr4_fifoemptymsk);
+ msk |= ((emp >> ep->num) & 0x1) << 7;
+ v = DWC_READ_REG32(&dev_if->in_ep_regs[ep->num]->diepint) & msk;
+ }
+
+ return v;
+}
+
+/**
+ * This function returns the Device OUT EP Interrupt register
+ */
+static uint32_t dwc_otg_read_dev_out_ep_intr(dwc_otg_core_if_t *_core_if, dwc_ep_t * _ep)
+{
+ dwc_otg_dev_if_t *dev_if = _core_if->dev_if;
+ uint32_t v;
+ doepmsk_data_t msk;
+ msk.d32 = 0;
+ {
+ msk.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->doepmsk);
+ if (_core_if->pti_enh_enable)
+ {
+ msk.b.pktdrpsts = 1;
+ }
+ v = DWC_READ_REG32(&dev_if->out_ep_regs[_ep->num]->doepint) & msk.d32;
+ }
+ return v;
+}
+#endif
+
+/**
+ * This function returns pointer to in ep struct with number ep_num
+ */
+static dwc_otg_pcd_ep_t *get_in_ep(dwc_otg_pcd_t * pcd, uint32_t ep_num)
+{
+ int i;
+ int num_in_eps = GET_CORE_IF(pcd)->dev_if->num_in_eps;
+ if (ep_num == 0)
+ {
+ return &pcd->ep0;
+ }
+ else
+ {
+ for (i = 0; i < num_in_eps; ++i)
+ {
+ if (pcd->in_ep[i].dwc_ep.num == ep_num)
+ return &pcd->in_ep[i];
+ }
+ return 0;
+ }
+}
+
+/**
+ * This function returns pointer to out ep struct with number ep_num
+ */
+static dwc_otg_pcd_ep_t *get_out_ep(dwc_otg_pcd_t * pcd, uint32_t ep_num)
+{
+ int i;
+ int num_out_eps = GET_CORE_IF(pcd)->dev_if->num_out_eps;
+ if (ep_num == 0)
+ {
+ return &pcd->ep0;
+ }
+ else
+ {
+ for (i = 0; i < num_out_eps; ++i)
+ {
+ if (pcd->out_ep[i].dwc_ep.num == ep_num)
+ return &pcd->out_ep[i];
+ }
+ return 0;
+ }
+}
+
+/**
+ * This functions gets a pointer to an EP from the wIndex address
+ * value of the control request.
+ */
+dwc_otg_pcd_ep_t *get_ep_by_addr(dwc_otg_pcd_t * pcd, uint16_t wIndex)
+{
+ dwc_otg_pcd_ep_t *ep;
+ uint32_t ep_num = UE_GET_ADDR(wIndex);
+
+ if (ep_num == 0)
+ {
+ ep = &pcd->ep0;
+ }
+ else if (UE_GET_DIR(wIndex) == UE_DIR_IN)
+ { /* in ep */
+ ep = &pcd->in_ep[ep_num - 1];
+ }
+ else
+ {
+ ep = &pcd->out_ep[ep_num - 1];
+ }
+
+ return ep;
+}
+/**
+ * This function handles the Rx Status Queue Level Interrupt, which
+ * indicates that there is a least one packet in the Rx FIFO. The
+ * packets are moved from the FIFO to memory, where they will be
+ * processed when the Endpoint Interrupt Register indicates Transfer
+ * Complete or SETUP Phase Done.
+ *
+ * Repeat the following until the Rx Status Queue is empty:
+ * -# Read the Receive Status Pop Register (GRXSTSP) to get Packet
+ * info
+ * -# If Receive FIFO is empty then skip to step Clear the interrupt
+ * and exit
+ * -# If SETUP Packet call dwc_otg_read_setup_packet to copy the
+ * SETUP data to the buffer
+ * -# If OUT Data Packet call dwc_otg_read_packet to copy the data
+ * to the destination buffer
+ */
+int32_t dwc_otg_pcd_handle_rx_status_q_level_intr(dwc_otg_pcd_t * pcd)
+{
+ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
+ dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
+ gintmsk_data_t gintmask;
+ device_grxsts_data_t status;
+ dwc_otg_pcd_ep_t *ep;
+ gintsts_data_t gintsts;
+ gintmask.d32 = 0;
+
+ /* Disable the Rx Status Queue Level interrupt */
+ gintmask.b.rxstsqlvl = 1;
+ DWC_MODIFY_REG32(&global_regs->gintmsk, gintmask.d32, 0);
+
+ /* Get the Status from the top of the FIFO */
+ status.d32 = DWC_READ_REG32(&global_regs->grxstsp);
+
+ /* Get pointer to EP structure */
+ ep = get_out_ep(pcd, status.b.epnum);
+ if(0==ep)
+ return -1;
+
+ switch (status.b.pktsts)
+ {
+ case DWC_DSTS_GOUT_NAK:
+ break;
+ case DWC_STS_DATA_UPDT:
+ if (status.b.bcnt && ep->dwc_ep.xfer_buff)
+ {
+ /** @todo NGS Check for buffer overflow? */
+ dwc_otg_read_packet(core_if, ep->dwc_ep.xfer_buff,status.b.bcnt);
+ ep->dwc_ep.xfer_count += status.b.bcnt;
+ ep->dwc_ep.xfer_buff += status.b.bcnt;
+ }
+ break;
+ case DWC_STS_XFER_COMP:
+ break;
+ case DWC_DSTS_SETUP_COMP:
+ break;
+ case DWC_DSTS_SETUP_UPDT:
+ dwc_otg_read_setup_packet(core_if, pcd->setup_pkt->d32);
+ ep->dwc_ep.xfer_count += status.b.bcnt;
+
+ #if SIM_EN == EMULATION
+ if(pcd->setup_pkt->req.bRequest == 0x05)
+ {
+ REG32(REG_GPIO_OUT)=0x9;
+// while(REG32(REG_GPIO_IN)!=0xFF);
+ usdelay(1);
+ REG32(REG_GPIO_OUT)=0;
+ }
+ #endif
+
+ break;
+ default:
+ break;
+ }
+
+ /* Enable the Rx Status Queue Level interrupt */
+ DWC_MODIFY_REG32(&global_regs->gintmsk, 0, gintmask.d32);
+ /* Clear interrupt */
+ gintsts.d32 = 0;
+ gintsts.b.rxstsqlvl = 1;
+ DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
+
+ return 1;
+}
+
+/**
+ * This function examines the Device IN Token Learning Queue to
+ * determine the EP number of the last IN token received. This
+ * implementation is for the Mass Storage device where there are only
+ * 2 IN EPs (Control-IN and BULK-IN).
+ *
+ * The EP numbers for the first six IN Tokens are in DTKNQR1 and there
+ * are 8 EP Numbers in each of the other possible DTKNQ Registers.
+ *
+ * @param core_if Programming view of DWC_otg controller.
+ *
+ */
+/**
+ * This function is called when dedicated Tx FIFO Empty interrupt occurs.
+ * The active request is checked for the next packet to be loaded into
+ * apropriate Tx FIFO.
+ */
+static int32_t write_empty_tx_fifo(dwc_otg_pcd_t * pcd, uint32_t epnum)
+{
+ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
+ dwc_otg_dev_if_t *dev_if = core_if->dev_if;
+ dtxfsts_data_t txstatus;
+ dwc_otg_pcd_ep_t *ep = 0;
+ uint32_t len = 0;
+ int dwords;
+ txstatus.d32 = 0;
+
+ if(epnum >= MAX_EPS_CHANNELS)
+ return -1;
+
+ ep = get_in_ep(pcd, epnum);
+ if(0==ep)
+ return -1;
+
+ len = ep->dwc_ep.xfer_len - ep->dwc_ep.xfer_count;
+
+ if (len > ep->dwc_ep.maxpacket)
+ {
+ len = ep->dwc_ep.maxpacket;
+ }
+
+ dwords = (len + 3) / 4;
+
+ /* While there is space in the queue and space in the FIFO and
+ * More data to tranfer, Write packets to the Tx FIFO */
+ txstatus.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->dtxfsts);
+ while (txstatus.b.txfspcavail > dwords &&
+ ep->dwc_ep.xfer_count < ep->dwc_ep.xfer_len &&
+ ep->dwc_ep.xfer_len != 0)
+ {
+ /* Write the FIFO */
+ dwc_otg_ep_write_packet(core_if, &ep->dwc_ep, 0);
+
+ len = ep->dwc_ep.xfer_len - ep->dwc_ep.xfer_count;
+ if (len > ep->dwc_ep.maxpacket)
+ {
+ len = ep->dwc_ep.maxpacket;
+ }
+
+ dwords = (len + 3) / 4;
+ txstatus.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->dtxfsts);
+ }
+
+
+ return 1;
+}
+
+/**
+ * This function configures EPO to receive SETUP packets.
+ *
+ * @todo NGS: Update the comments from the HW FS.
+ *
+ * -# Program the following fields in the endpoint specific registers
+ * for Control OUT EP 0, in order to receive a setup packet
+ * - DOEPTSIZ0.Packet Count = 3 (To receive up to 3 back to back
+ * setup packets)
+ * - DOEPTSIZE0.Transfer Size = 24 Bytes (To receive up to 3 back
+ * to back setup packets)
+ * - In DMA mode, DOEPDMA0 Register with a memory address to
+ * store any setup packets received
+ *
+ * @param core_if Programming view of DWC_otg controller.
+ * @param pcd Programming view of the PCD.
+ */
+static void ep0_out_start(dwc_otg_core_if_t * core_if,
+ dwc_otg_pcd_t * pcd)
+{
+ dwc_otg_dev_if_t *dev_if = core_if->dev_if;
+ deptsiz0_data_t doeptsize0;
+ depctl_data_t doepctl;
+ doepctl.d32 = 0;
+ doeptsize0.d32 =0;
+
+
+ doepctl.d32 = DWC_READ_REG32(&dev_if->out_ep_regs[0]->doepctl);
+ if (doepctl.b.epena)
+ {
+ return;
+ }
+
+ doeptsize0.b.supcnt = 3;
+ doeptsize0.b.pktcnt = 1;
+ doeptsize0.b.xfersize = 8 * 3;
+
+ /** put here as for Hermes mode deptisz register should not be written */
+ DWC_WRITE_REG32(&dev_if->out_ep_regs[0]->doeptsiz,doeptsize0.d32);
+
+ /** DOEPCTL0 Register write cnak will be set after setup interrupt */
+ doepctl.d32 = 0;
+ doepctl.b.epena = 1;
+
+ DWC_MODIFY_REG32(&dev_if->out_ep_regs[0]->doepctl, 0, doepctl.d32);
+
+}
+
+
+void USB_Recovercfg(dwc_otg_pcd_t *pcd)
+{
+ int i = 0;
+ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
+ dwc_otg_dev_if_t *dev_if = core_if->dev_if;
+ depctl_data_t doepctl;
+ depctl_data_t diepctl;
+ doepctl.d32 = 0;
+ diepctl.d32 = 0;
+
+ for (i = 0; i <= dev_if->num_out_eps; i++)
+ {
+ doepctl.d32= DWC_READ_REG32(&dev_if->out_ep_regs[i+1]->doepctl);
+ doepctl.b.eptype = pcd->out_ep[i].dwc_ep.type;
+ doepctl.b.mps = pcd->out_ep[i].dwc_ep.maxpacket;
+ DWC_WRITE_REG32(&dev_if->out_ep_regs[i+1]->doepctl, doepctl.d32);
+
+ diepctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[i+1]->diepctl);
+ diepctl.b.eptype = pcd->in_ep[i].dwc_ep.type;
+ diepctl.b.mps = pcd->in_ep[i].dwc_ep.maxpacket;
+ DWC_WRITE_REG32(&dev_if->in_ep_regs[i+1]->diepctl, diepctl.d32);
+ }
+
+}
+int32_t dwc_otg_pcd_handle_usb_reset_intr(dwc_otg_pcd_t * pcd)
+{
+ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
+ dwc_otg_dev_if_t *dev_if = core_if->dev_if;
+ depctl_data_t doepctl;
+ daint_data_t daintmsk;
+ doepmsk_data_t doepmsk;
+ diepmsk_data_t diepmsk ;
+ dcfg_data_t dcfg ;
+ grstctl_t resetctl;
+ dctl_data_t dctl;
+ int i = 0;
+ gintsts_data_t gintsts;
+ pcgcctl_data_t power;
+ doepctl.d32 = 0;
+ daintmsk.d32 = 0;
+ doepmsk.d32 = 0;
+ diepmsk.d32 = 0;
+ dcfg.d32 = 0;
+ resetctl.d32 = 0;
+ dctl.d32 = 0;
+ power.d32 = 0;
+
+ power.d32 = DWC_READ_REG32(core_if->pcgcctl);
+ if (power.b.stoppclk)
+ {
+ power.d32 = 0;
+ power.b.stoppclk = 1;
+ DWC_MODIFY_REG32(core_if->pcgcctl, power.d32, 0);
+
+ power.b.pwrclmp = 1;
+ DWC_MODIFY_REG32(core_if->pcgcctl, power.d32, 0);
+
+ power.b.rstpdwnmodule = 1;
+ DWC_MODIFY_REG32(core_if->pcgcctl, power.d32, 0);
+ }
+
+ printk("Reset\n");
+
+ /* Clear the Remote Wakeup Signalling */
+ dctl.b.rmtwkupsig = 1;
+ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32, 0);
+
+ /* Set NAK for all OUT EPs */
+ doepctl.b.snak = 1;
+ for (i = 0; i <= dev_if->num_out_eps; i++)
+ {
+ DWC_WRITE_REG32(&dev_if->out_ep_regs[i]->doepctl, doepctl.d32);
+ }
+
+ /* Flush the NP Tx FIFO */
+ dwc_otg_flush_tx_fifo(core_if, 0x10);
+ /* Flush the Learning Queue */
+ resetctl.b.intknqflsh = 1;
+ DWC_WRITE_REG32(&core_if->core_global_regs->grstctl, resetctl.d32);
+ {
+ daintmsk.b.inep0 = 1;
+ daintmsk.b.outep0 = 1;
+ DWC_WRITE_REG32(&dev_if->dev_global_regs->daintmsk,daintmsk.d32);
+
+ doepmsk.b.setup = 1;
+ doepmsk.b.xfercompl = 1;
+ doepmsk.b.ahberr = 1;
+ doepmsk.b.epdisabled = 1;
+ DWC_WRITE_REG32(&dev_if->dev_global_regs->doepmsk, doepmsk.d32);
+
+ diepmsk.b.xfercompl = 1;
+ diepmsk.b.timeout = 1;
+ diepmsk.b.epdisabled = 1;
+ diepmsk.b.ahberr = 1;
+
+ DWC_WRITE_REG32(&dev_if->dev_global_regs->diepmsk, diepmsk.d32);
+ }
+
+ /* Reset Device Address */
+ dcfg.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->dcfg);
+ dcfg.b.devaddr = 0;
+ DWC_WRITE_REG32(&dev_if->dev_global_regs->dcfg, dcfg.d32);
+
+ /* Clear interrupt */
+ gintsts.d32 = 0;
+ gintsts.b.usbreset = 1;
+ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);
+
+ USB_Recovercfg(pcd);
+
+ return 1;
+}
+
+/**
+ * Get the device speed from the device status register and convert it
+ * to USB speed constant.
+ *
+ * @param core_if Programming view of DWC_otg controller.
+ */
+static int get_device_speed(dwc_otg_core_if_t * core_if)
+{
+ dsts_data_t dsts;
+ int speed = 0;
+ dsts.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dsts);
+
+ switch (dsts.b.enumspd)
+ {
+ case DWC_DSTS_ENUMSPD_HS_PHY_30MHZ_OR_60MHZ:
+ speed = USB_SPEED_HIGH;
+ break;
+ case DWC_DSTS_ENUMSPD_FS_PHY_30MHZ_OR_60MHZ:
+ case DWC_DSTS_ENUMSPD_FS_PHY_48MHZ:
+ speed = USB_SPEED_FULL;
+ break;
+
+ case DWC_DSTS_ENUMSPD_LS_PHY_6MHZ:
+ speed = USB_SPEED_LOW;
+ break;
+ }
+
+ return speed;
+}
+
+/**
+ * Read the device status register and set the device speed in the
+ * data structure.
+ * Set up EP0 to receive SETUP packets by calling dwc_ep0_activate.
+ */
+//extern void init_devspd(dwc_otg_core_if_t * core_if,uint8_t speed);
+
+
+int32_t dwc_otg_pcd_handle_enum_done_intr(dwc_otg_pcd_t * pcd)
+{
+ dwc_otg_pcd_ep_t *ep0 = &pcd->ep0;
+ gintsts_data_t gintsts;
+ gusbcfg_data_t gusbcfg;
+ dwc_otg_core_global_regs_t *global_regs = GET_CORE_IF(pcd)->core_global_regs;
+ uint8_t utmi16b, utmi8b;
+ int speed;
+ printk("D");
+
+ utmi16b = 5; //utmi phy use 5 add by tj
+ utmi8b = 9;
+ dwc_otg_ep0_activate(GET_CORE_IF(pcd), &ep0->dwc_ep);
+ ep0_out_start(GET_CORE_IF(pcd), pcd);
+#if SIM_EN == EMULATION
+
+ REG32(REG_GPIO_OUT)=5;
+// while(REG32(REG_GPIO_IN)!=0xFF);
+ usdelay(1);
+ REG32(REG_GPIO_OUT)=0;
+
+ REG32(REG_GPIO_OUT)=6;
+// while(REG32(REG_GPIO_IN)!=0xFF);
+ usdelay(1);
+ REG32(REG_GPIO_OUT)=0;
+
+ REG32(REG_GPIO_OUT)=7;
+// while(REG32(REG_GPIO_IN)!=0xFF);
+ usdelay(1);
+ REG32(REG_GPIO_OUT)=0;
+
+ REG32(REG_GPIO_OUT)=8;
+// while(REG32(REG_GPIO_IN)!=0xFF);
+ usdelay(1);
+ REG32(REG_GPIO_OUT)=0;
+
+#endif
+ if (pcd->ep0state == EP0_DISCONNECT)
+ {
+ pcd->ep0state = EP0_IDLE;
+ }
+ else if (pcd->ep0state == EP0_STALL)
+ {
+ pcd->ep0state = EP0_IDLE;
+ }
+
+ ep0->stopped = 0;
+
+ speed = get_device_speed(GET_CORE_IF(pcd));
+ /* Set USB turnaround time based on device speed and PHY interface. */
+ gusbcfg.d32 = DWC_READ_REG32(&global_regs->gusbcfg);
+ if (speed == USB_SPEED_HIGH)
+ {
+
+ if (GET_CORE_IF(pcd)->hwcfg2.b.hs_phy_type == DWC_HWCFG2_HS_PHY_TYPE_UTMI_ULPI)
+ {
+ /* UTMI+ OR ULPI interface */
+ if (gusbcfg.b.ulpi_utmi_sel == 1)
+ {
+ /* ULPI interface */
+ gusbcfg.b.usbtrdtim = 9;
+ }
+ else
+ {
+ /* UTMI+ interface */
+ if (GET_CORE_IF(pcd)->core_params->phy_utmi_width == 16)
+ {
+ gusbcfg.b.usbtrdtim = utmi16b;
+ }
+ else
+ {
+ gusbcfg.b.usbtrdtim = utmi8b;
+ }
+ }
+ }
+
+ printk("2\n");
+ pcd->out_ep[0].dwc_ep.maxpacket = 512;
+ pcd->in_ep[0].dwc_ep.maxpacket = 512;
+ pcd->out_ep[1].dwc_ep.maxpacket = 512;
+ pcd->in_ep[1].dwc_ep.maxpacket = 512;
+ g_config_desc.atTxEP[0].wMaxPacketSize = USB_HIGHSPEED_BULK_MAXSIZE;
+ g_config_desc.atRxEP[0].wMaxPacketSize = USB_HIGHSPEED_BULK_MAXSIZE;
+ g_config_desc.atTxEP1[0].wMaxPacketSize = USB_HIGHSPEED_BULK_MAXSIZE;
+ g_config_desc.atRxEP1[0].wMaxPacketSize = USB_HIGHSPEED_BULK_MAXSIZE;
+
+ }
+ else
+ {
+ printk("1\n");
+ pcd->out_ep[0].dwc_ep.maxpacket = 64;
+ pcd->in_ep[0].dwc_ep.maxpacket = 64;
+ pcd->out_ep[1].dwc_ep.maxpacket = 64;
+ pcd->in_ep[1].dwc_ep.maxpacket = 64;
+ // desc.atTxEP[0].wMaxPacketSize = USB_FULLSPEED_BULK_MAXSIZE;
+ // desc.atRxEP[0].wMaxPacketSize = USB_FULLSPEED_BULK_MAXSIZE;
+ // desc.atTxEP1[0].wMaxPacketSize = USB_FULLSPEED_BULK_MAXSIZE;
+ // desc.atRxEP1[0].wMaxPacketSize = USB_FULLSPEED_BULK_MAXSIZE;
+ /* Full or low speed */
+ g_config_desc.atTxEP[0].wMaxPacketSize = USB_FULLSPEED_BULK_MAXSIZE;
+ g_config_desc.atRxEP[0].wMaxPacketSize = USB_FULLSPEED_BULK_MAXSIZE;
+ g_config_desc.atTxEP1[0].wMaxPacketSize = USB_FULLSPEED_BULK_MAXSIZE;
+ g_config_desc.atRxEP1[0].wMaxPacketSize = USB_FULLSPEED_BULK_MAXSIZE;
+ gusbcfg.b.usbtrdtim = 9;
+ }
+ DWC_WRITE_REG32(&global_regs->gusbcfg, gusbcfg.d32);
+
+ /* Clear interrupt */
+ gintsts.d32 = 0;
+ gintsts.b.enumdone = 1;
+ DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintsts,gintsts.d32);
+ return 1;
+}
+
+
+
+/**
+ * This funcion stalls EP0.
+ */
+void ep0_do_stall(dwc_otg_pcd_t * pcd, const int err_val)
+{
+ dwc_otg_pcd_ep_t *ep0 = &pcd->ep0;
+
+ ep0->dwc_ep.is_in = 1;
+ dwc_otg_ep_set_stall(GET_CORE_IF(pcd), &ep0->dwc_ep);
+ pcd->ep0.stopped = 1;
+ pcd->ep0state = EP0_IDLE;
+ ep0_out_start(GET_CORE_IF(pcd), pcd);
+}
+
+static void do_setup_in_out_status_phase(dwc_otg_pcd_t * pcd,s8 udir)
+{
+ dwc_otg_pcd_ep_t *ep0 = &pcd->ep0;
+ if (pcd->ep0state == EP0_STALL)
+ {
+ return;
+ }
+
+ if(udir)
+ {
+ pcd->ep0state = EP0_IN_STATUS_PHASE;
+ }
+ else
+ {
+ pcd->ep0state = EP0_OUT_STATUS_PHASE;
+ }
+
+ /* Prepare for more SETUP Packets */
+ ep0->dwc_ep.xfer_len = 0;
+ ep0->dwc_ep.xfer_count = 0;
+ ep0->dwc_ep.is_in = udir;
+ dwc_otg_ep0_start_transfer(GET_CORE_IF(pcd), &ep0->dwc_ep);
+}
+
+
+/**
+ * Clear the EP halt (STALL) and if pending requests start the
+ * transfer.
+ */
+static void pcd_clear_halt(dwc_otg_pcd_t * pcd, dwc_otg_pcd_ep_t * ep)
+{
+ if (ep->dwc_ep.stall_clear_flag == 0)
+ dwc_otg_ep_clear_stall(GET_CORE_IF(pcd), &ep->dwc_ep);
+
+ /* Reactive the EP */
+ dwc_otg_ep_activate(GET_CORE_IF(pcd), &ep->dwc_ep);
+ if (ep->stopped)
+ {
+ ep->stopped = 0;
+ /* If there is a request in the EP queue start it */
+
+ /** @todo FIXME: this causes an EP mismatch in DMA mode.
+ * epmismatch not yet implemented. */
+
+ /*
+ * Above fixme is solved by implmenting a tasklet to call the
+ * start_next_request(), outside of interrupt context at some
+ * time after the current time, after a clear-halt setup packet.
+ * Still need to implement ep mismatch in the future if a gadget
+ * ever uses more than one endpoint at once
+ */
+ ep->queue_sof = 1;
+ }
+ /* Start Control Status Phase */
+ do_setup_in_out_status_phase(pcd,1);
+}
+
+/**
+ * This function process the GET_STATUS Setup Commands.
+ */
+static void do_get_status(dwc_otg_pcd_t * pcd)
+{
+ usb_device_request_t ctrl = pcd->setup_pkt->req;
+ dwc_otg_pcd_ep_t *ep;
+ dwc_otg_pcd_ep_t *ep0 = &pcd->ep0;
+ uint16_t *status = pcd->status_buf;
+
+ switch (UT_GET_RECIPIENT(ctrl.bmRequestType))
+ {
+ case UT_INTERFACE:
+ *status = 0;
+ break;
+
+ case UT_ENDPOINT:
+ ep = get_ep_by_addr(pcd, ctrl.wIndex);
+ if (ep == 0 || ctrl.wLength > 2)
+ {
+ ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED);
+ return;
+ }
+ /** @todo check for EP stall */
+ *status = ep->stopped;
+ break;
+ }
+ pcd->ep0_pending = 1;
+ ep0->dwc_ep.start_xfer_buff = (uint8_t *) status;
+ ep0->dwc_ep.xfer_buff = (uint8_t *) status;
+ ep0->dwc_ep.xfer_len = 2;
+ ep0->dwc_ep.xfer_count = 0;
+ ep0->dwc_ep.total_len = ep0->dwc_ep.xfer_len;
+ dwc_otg_ep0_start_transfer(GET_CORE_IF(pcd), &ep0->dwc_ep);
+}
+
+
+static void do_clear_feature(dwc_otg_pcd_t * pcd)
+{
+ usb_device_request_t ctrl = pcd->setup_pkt->req;
+ dwc_otg_pcd_ep_t *ep = 0;
+ switch (UT_GET_RECIPIENT(ctrl.bmRequestType))
+ {
+ case UT_ENDPOINT:
+ ep = get_ep_by_addr(pcd, ctrl.wIndex);
+ if (ep == 0)
+ {
+ ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED);
+ return;
+ }
+
+ pcd_clear_halt(pcd, ep);
+
+ break;
+
+ }
+}
+
+/**
+ * This function process the SET_ADDRESS Setup Commands.
+ */
+static void do_set_address(dwc_otg_pcd_t * pcd)
+{
+ dwc_otg_dev_if_t *dev_if = GET_CORE_IF(pcd)->dev_if;
+ usb_device_request_t ctrl = pcd->setup_pkt->req;
+ dcfg_data_t dcfg;
+ dcfg.d32 = 0;
+
+ if (ctrl.bmRequestType == UT_DEVICE)
+ {
+
+ dcfg.b.devaddr = ctrl.wValue;
+ DWC_MODIFY_REG32(&dev_if->dev_global_regs->dcfg, 0, dcfg.d32);
+#if SIM_EN == EMULATION
+ REG32(REG_GPIO_OUT)=0xa;
+// while(REG32(REG_GPIO_IN)!=0xFF);
+ usdelay(1);
+ REG32(REG_GPIO_OUT)=0;
+
+ REG32(REG_GPIO_OUT)=0xb;
+// while(REG32(REG_GPIO_IN)!=0xFF);
+ usdelay(1);
+ REG32(REG_GPIO_OUT)=0;
+
+#endif
+ do_setup_in_out_status_phase(pcd,1);
+#if SIM_EN == EMULATION
+ if(pcd->setup_pkt->req.bRequest == 0x05)
+ {
+ REG32(REG_GPIO_OUT)=0x9;
+// while(REG32(REG_GPIO_IN)!=0xFF);
+ usdelay(10);
+ REG32(REG_GPIO_OUT)=0;
+ }
+#endif
+ }
+}
+
+/**
+ * This function processes SETUP commands. In Linux, the USB Command
+ * processing is done in two places - the first being the PCD and the
+ * second in the Gadget Driver (for example, the File-Backed Storage
+ * Gadget Driver).
+ *
+ * <table>
+ * <tr><td>Command </td><td>Driver </td><td>Description</td></tr>
+ *
+ * <tr><td>GET_STATUS </td><td>PCD </td><td>Command is processed as
+ * defined in chapter 9 of the USB 2.0 Specification chapter 9
+ * </td></tr>
+ *
+ * <tr><td>CLEAR_FEATURE </td><td>PCD </td><td>The Device and Endpoint
+ * requests are the ENDPOINT_HALT feature is procesed, all others the
+ * interface requests are ignored.</td></tr>
+ *
+ * <tr><td>SET_FEATURE </td><td>PCD </td><td>The Device and Endpoint
+ * requests are processed by the PCD. Interface requests are passed
+ * to the Gadget Driver.</td></tr>
+ *
+ * <tr><td>SET_ADDRESS </td><td>PCD </td><td>Program the DCFG reg,
+ * with device address received </td></tr>
+ *
+ * <tr><td>GET_DESCRIPTOR </td><td>Gadget Driver </td><td>Return the
+ * requested descriptor</td></tr>
+ *
+ * <tr><td>SET_DESCRIPTOR </td><td>Gadget Driver </td><td>Optional -
+ * not implemented by any of the existing Gadget Drivers.</td></tr>
+ *
+ * <tr><td>SET_CONFIGURATION </td><td>Gadget Driver </td><td>Disable
+ * all EPs and enable EPs for new configuration.</td></tr>
+ *
+ * <tr><td>GET_CONFIGURATION </td><td>Gadget Driver </td><td>Return
+ * the current configuration</td></tr>
+ *
+ * <tr><td>SET_INTERFACE </td><td>Gadget Driver </td><td>Disable all
+ * EPs and enable EPs for new configuration.</td></tr>
+ *
+ * <tr><td>GET_INTERFACE </td><td>Gadget Driver </td><td>Return the
+ * current interface.</td></tr>
+ *
+ * <tr><td>SYNC_FRAME </td><td>PCD </td><td>Display debug
+ * message.</td></tr>
+ * </table>
+ *
+ * When the SETUP Phase Done interrupt occurs, the PCD SETUP commands are
+ * processed by pcd_setup. Calling the Function Driver's setup function from
+ * pcd_setup processes the gadget SETUP commands.
+ */
+void active_allep(dwc_otg_pcd_t * pcd)
+{
+ int i = 0;
+ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
+ dwc_otg_dev_if_t *dev_if = core_if->dev_if;
+ for (i = 0; i <dev_if->num_out_eps; i++)
+ {
+ dwc_otg_ep_activate(pcd->core_if,&pcd->out_ep[i].dwc_ep);
+ dwc_otg_ep_activate(pcd->core_if,&pcd->in_ep[i].dwc_ep);
+ }
+
+}
+
+extern int dwc_setup(dwc_otg_pcd_t * pcd, usb_device_request_t * ctrl);
+
+static void pcd_setup(dwc_otg_pcd_t * pcd)
+{
+ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
+ usb_device_request_t ctrl = pcd->setup_pkt->req;
+ dwc_otg_pcd_ep_t *ep0 = &pcd->ep0;
+
+ ep0->stopped = 0;
+
+ if (ctrl.bmRequestType & UE_DIR_IN)
+ {
+ ep0->dwc_ep.is_in = 1;
+ pcd->ep0state = EP0_IN_DATA_PHASE;
+ }
+ else
+ {
+ ep0->dwc_ep.is_in = 0;
+ pcd->ep0state = EP0_OUT_DATA_PHASE;
+ }
+
+ if (ctrl.wLength == 0)
+ {
+ ep0->dwc_ep.is_in = 1;
+ pcd->ep0state = EP0_IN_STATUS_PHASE;
+ }
+ /*tj Ôö¼Ó´¦Àí·Ç±ê×¼ÃüÁî*/
+ if(UT_GET_TYPE(ctrl.bmRequestType)!=UT_STANDARD)
+ {
+ ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED);
+ return;
+ }
+
+ switch (ctrl.bRequest)
+ {
+ case UR_GET_STATUS:
+ do_get_status(pcd);
+ break;
+
+ case UR_CLEAR_FEATURE:
+ do_clear_feature(pcd);
+ break;
+
+ case UR_SET_FEATURE:
+ break;
+
+ case UR_SET_ADDRESS:
+ do_set_address(pcd);
+ break;
+
+ case UR_GET_DESCRIPTOR:
+ dwc_setup(pcd, &ctrl);
+ break;
+
+ case UR_SET_CONFIG:
+ pcd->request_config = 1;
+ active_allep(pcd);
+ do_setup_in_out_status_phase(pcd,1);
+ ep0_out_start(core_if, pcd);
+ break;
+ default:
+ ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED);
+ break;
+ }
+}
+
+/**
+ * This function completes the ep0 control transfer.
+ */
+static int32_t ep0_complete_request(dwc_otg_pcd_ep_t * ep)
+{
+ dwc_otg_core_if_t *core_if = GET_CORE_IF(ep->pcd);
+ dwc_otg_dev_if_t *dev_if = core_if->dev_if;
+ dwc_otg_dev_in_ep_regs_t *in_ep_regs =
+ dev_if->in_ep_regs[ep->dwc_ep.num];
+
+ deptsiz0_data_t deptsiz;
+ int is_last = 0;
+ dwc_otg_pcd_t *pcd = ep->pcd;
+
+ if (pcd->ep0_pending)
+ {
+ if (ep->dwc_ep.is_in)
+ {
+
+ do_setup_in_out_status_phase(pcd,0);
+ }
+ else
+ {
+ do_setup_in_out_status_phase(pcd,1);
+ }
+ pcd->ep0_pending = 0;
+ return 1;
+ }
+
+ if (pcd->ep0state == EP0_OUT_STATUS_PHASE
+ || pcd->ep0state == EP0_IN_STATUS_PHASE)
+ {
+ is_last = 1;
+ }
+ else if (ep->dwc_ep.is_in)
+ {
+ deptsiz.d32 = DWC_READ_REG32(&in_ep_regs->dieptsiz);
+
+ if (deptsiz.b.xfersize == 0)
+ {
+ do_setup_in_out_status_phase(pcd,0);
+ }
+ }
+ else
+ {
+
+ ep0_out_start(core_if, pcd);
+
+ }
+
+ /* Complete the request */
+ if (is_last)
+ {
+ ep->dwc_ep.start_xfer_buff = 0;
+ ep->dwc_ep.xfer_buff = 0;
+ ep->dwc_ep.xfer_len = 0;
+ return 1;
+ }
+ return 0;
+}
+
+/**
+ * This function completes the request for the EP. If there are
+ * additional requests for the EP in the queue they will be started.
+ */
+static void complete_ep(dwc_otg_pcd_ep_t * ep)
+{
+ dwc_otg_core_if_t *core_if = GET_CORE_IF(ep->pcd);
+ dwc_otg_dev_if_t *dev_if = core_if->dev_if;
+ dwc_otg_dev_in_ep_regs_t *in_ep_regs = dev_if->in_ep_regs[ep->dwc_ep.num];
+ deptsiz_data_t deptsiz;
+
+ if (ep->dwc_ep.is_in)
+ {
+ deptsiz.d32 = DWC_READ_REG32(&in_ep_regs->dieptsiz);
+ {
+ if (deptsiz.b.xfersize == 0 && deptsiz.b.pktcnt == 0)
+ {
+ /* Check if the whole transfer was completed,
+ * if no, setup transfer for next portion of data
+ */
+ if (ep->dwc_ep.xfer_len < ep->dwc_ep.total_len)
+ {
+ dwc_otg_ep_start_transfer(core_if,&ep->dwc_ep);
+ }
+ else if (ep->dwc_ep.sent_zlp)
+ {
+ /*
+ * This fragment of code should initiate 0
+ * length trasfer in case if it is queued
+ * a trasfer with size divisible to EPs max
+ * packet size and with usb_request zero field
+ * is set, which means that after data is transfered,
+ * it is also should be transfered
+ * a 0 length packet at the end. For Slave and
+ * Buffer DMA modes in this case SW has
+ * to initiate 2 transfers one with transfer size,
+ * and the second with 0 size. For Desriptor
+ * DMA mode SW is able to initiate a transfer,
+ * which will handle all the packets including
+ * the last 0 legth.
+ */
+ ep->dwc_ep.sent_zlp = 0;
+ dwc_otg_ep_start_zl_transfer(core_if,
+ &ep->dwc_ep);
+ }
+ else
+ {
+
+ if (ep->dwc_ep.fnUsbCb)
+ ep->dwc_ep.fnUsbCb( (WORD32)(ep->dwc_ep.pPara), 0, ep->dwc_ep.xfer_count, ep->dwc_ep.total_len);
+
+ }
+ }
+ }
+ }
+ // OUT EP
+ else
+ {
+ dwc_otg_dev_out_ep_regs_t *out_ep_regs = dev_if->out_ep_regs[ep->dwc_ep.num];
+ {
+ deptsiz.d32 = 0;
+ deptsiz.d32 = DWC_READ_REG32(&out_ep_regs->doeptsiz);
+ if (deptsiz.b.xfersize>0)
+ {
+
+ if (ep->dwc_ep.fnUsbCb)
+ ep->dwc_ep.fnUsbCb( (WORD32)(ep->dwc_ep.pPara), 0, ep->dwc_ep.xfer_count, ep->dwc_ep.total_len);
+
+ }
+ else
+ {
+ dwc_otg_ep_start_transfer(core_if,&ep->dwc_ep);
+ }
+ }
+
+
+ }
+
+}
+
+/**
+ * This function handles EP0 Control transfers.
+ *
+ * The state of the control transfers are tracked in
+ * <code>ep0state</code>.
+ */
+static void handle_ep0(dwc_otg_pcd_t * pcd)
+{
+ dwc_otg_pcd_ep_t *ep0 = &pcd->ep0;
+
+ switch (pcd->ep0state)
+ {
+ case EP0_DISCONNECT:
+ break;
+
+ case EP0_IDLE:
+ pcd->request_config = 0;
+
+ pcd_setup(pcd);
+
+ break;
+
+ case EP0_IN_DATA_PHASE:
+ if (ep0->dwc_ep.xfer_count < ep0->dwc_ep.total_len)
+ {
+ dwc_otg_ep0_continue_transfer(GET_CORE_IF(pcd),&ep0->dwc_ep);
+ }
+ else if (ep0->dwc_ep.sent_zlp)
+ {
+ dwc_otg_ep0_continue_transfer(GET_CORE_IF(pcd),&ep0->dwc_ep);
+ ep0->dwc_ep.sent_zlp = 0;
+ }
+ else
+ {
+ ep0_complete_request(ep0);
+ }
+ break;
+ case EP0_OUT_DATA_PHASE:
+ if (ep0->dwc_ep.xfer_count < ep0->dwc_ep.total_len)
+ {
+ dwc_otg_ep0_continue_transfer(GET_CORE_IF(pcd),
+ &ep0->dwc_ep);
+ }
+ else if (ep0->dwc_ep.sent_zlp)
+ {
+ dwc_otg_ep0_continue_transfer(GET_CORE_IF(pcd), &ep0->dwc_ep);
+ ep0->dwc_ep.sent_zlp = 0;
+ }
+ else
+ {
+ ep0_complete_request(ep0);
+ }
+ break;
+
+ case EP0_IN_STATUS_PHASE:
+ case EP0_OUT_STATUS_PHASE:
+ ep0_complete_request(ep0);
+ pcd->ep0state = EP0_IDLE;
+ ep0->stopped = 1;
+ ep0->dwc_ep.is_in = 0; /* OUT for next SETUP */
+ break;
+
+ case EP0_STALL:
+ break;
+ }
+
+}
+
+/**
+ * Handler for the IN EP NAK interrupt.
+ */
+
+/**
+ * Handler for the OUT EP NAK interrupt.
+ */
+static int32_t handle_out_ep_nak_intr(dwc_otg_pcd_t * pcd,
+ const uint32_t epnum)
+{
+ /** @todo implement ISR */
+ dwc_otg_core_if_t *core_if;
+ doepmsk_data_t intr_mask;
+ intr_mask.d32 = 0;
+
+ core_if = GET_CORE_IF(pcd);
+ intr_mask.b.nak = 1;
+ {
+ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->doepmsk,intr_mask.d32, 0);
+ }
+
+ return 1;
+}
+
+/**
+ * Handler for the OUT EP NYET interrupt.
+ */
+static int32_t handle_out_ep_nyet_intr(dwc_otg_pcd_t * pcd,
+ const uint32_t epnum)
+{
+ /** @todo implement ISR */
+ dwc_otg_core_if_t *core_if;
+ doepmsk_data_t intr_mask;
+ intr_mask.d32 = 0 ;
+
+ core_if = GET_CORE_IF(pcd);
+ intr_mask.b.nyet = 1;
+ {
+ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->doepmsk, intr_mask.d32, 0);
+ }
+
+ return 1;
+}
+
+/**
+ * This interrupt indicates that an IN EP has a pending Interrupt.
+ * The sequence for handling the IN EP interrupt is shown below:
+ * -# Read the Device All Endpoint Interrupt register
+ * -# Repeat the following for each IN EP interrupt bit set (from
+ * LSB to MSB).
+ * -# Read the Device Endpoint Interrupt (DIEPINTn) register
+ * -# If "Transfer Complete" call the request complete function
+ * -# If "Endpoint Disabled" complete the EP disable procedure.
+ * -# If "AHB Error Interrupt" log error
+ * -# If "Time-out Handshake" log error
+ * -# If "IN Token Received when TxFIFO Empty" write packet to Tx
+ * FIFO.
+ * -# If "IN Token EP Mismatch" (disable, this is handled by EP
+ * Mismatch Interrupt)
+ */
+static int32_t dwc_otg_pcd_handle_in_ep_intr(dwc_otg_pcd_t * pcd)
+{
+
+ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
+ dwc_otg_dev_if_t *dev_if = core_if->dev_if;
+ diepint_data_t diepint;
+ depctl_data_t depctl;
+ uint32_t ep_intr;
+ uint32_t epnum = 0;
+ dwc_otg_pcd_ep_t *ep;
+ dwc_ep_t *dwc_ep;
+ diepmsk_data_t diepmsk;
+ uint32_t fifoemptymsk;
+ diepint.d32 = 0;
+ depctl.d32 = 0;
+ diepmsk.d32 = 0;
+
+ ep_intr = dwc_otg_read_dev_all_in_ep_intr(core_if);
+ /* Service the Device IN interrupts for each endpoint */
+ while (ep_intr&&(epnum<MAX_EPS_CHANNELS))
+ {
+ if (ep_intr & 0x1)
+ {
+
+ /* Get EP pointer */
+ ep = get_in_ep(pcd, epnum);
+ dwc_ep = &ep->dwc_ep;
+ depctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->diepctl);
+ diepint.d32 = dwc_otg_read_dev_in_ep_intr(core_if, dwc_ep);
+ /* Transfer complete */
+ if (diepint.b.xfercompl)
+ {
+ {
+ /* Disable the Tx FIFO Empty Interrupt for this EP */
+ fifoemptymsk = 0x1 << dwc_ep->num;
+ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dtknqr4_fifoemptymsk,fifoemptymsk, 0);
+ }
+ /* Clear the bit in DIEPINTn for this interrupt */
+ CLEAR_IN_EP_INTR(core_if, epnum, xfercompl);
+
+ /* Complete the transfer */
+ if (epnum == 0)
+ {
+ handle_ep0(pcd);
+
+ }
+ else
+ {
+
+ complete_ep(ep);
+ if (diepint.b.nak)
+ CLEAR_IN_EP_INTR(core_if, epnum, nak);
+ }
+ }
+ /* Endpoint disable */
+ if (diepint.b.epdisabled)
+ {
+
+ CLEAR_IN_EP_INTR(core_if, epnum, epdisabled);
+ }
+
+ /* TimeOUT Handshake (non-ISOC IN EPs) */
+ if (diepint.b.timeout)
+ {
+ CLEAR_IN_EP_INTR(core_if, epnum, timeout);
+ }
+ /** IN Token received with TxF Empty */
+ if (diepint.b.intktxfemp)
+ {
+ if (!ep->stopped && epnum != 0)
+ {
+ diepmsk.b.intktxfemp = 1;
+ {
+ DWC_MODIFY_REG32
+ (&dev_if->dev_global_regs->diepmsk,
+ diepmsk.d32, 0);
+ }
+ }
+ CLEAR_IN_EP_INTR(core_if, epnum, intktxfemp);
+ }
+
+ /** IN Endpoint NAK Effective */
+ if (diepint.b.inepnakeff)
+ {
+ /* Periodic EP */
+ if (ep->disabling)
+ {
+ depctl.d32 = 0;
+ depctl.b.snak = 1;
+ depctl.b.epdis = 1;
+ DWC_MODIFY_REG32(&dev_if->in_ep_regs
+ [epnum]->diepctl,
+ depctl.d32,
+ depctl.d32);
+ }
+ CLEAR_IN_EP_INTR(core_if, epnum, inepnakeff);
+
+ }
+
+ /** IN EP Tx FIFO Empty Intr */
+ if (diepint.b.emptyintr)
+ {
+ write_empty_tx_fifo(pcd, epnum);
+
+ CLEAR_IN_EP_INTR(core_if, epnum, emptyintr);
+
+ }
+ /* NAK Interrutp */
+ if (diepint.b.nak)
+ {
+ CLEAR_IN_EP_INTR(core_if, epnum, nak);
+ }
+ }
+ epnum++;
+ ep_intr >>= 1;
+ }
+
+ return 1;
+#undef CLEAR_IN_EP_INTR
+}
+
+/**
+ * This interrupt indicates that an OUT EP has a pending Interrupt.
+ * The sequence for handling the OUT EP interrupt is shown below:
+ * -# Read the Device All Endpoint Interrupt register
+ * -# Repeat the following for each OUT EP interrupt bit set (from
+ * LSB to MSB).
+ * -# Read the Device Endpoint Interrupt (DOEPINTn) register
+ * -# If "Transfer Complete" call the request complete function
+ * -# If "Endpoint Disabled" complete the EP disable procedure.
+ * -# If "AHB Error Interrupt" log error
+ * -# If "Setup Phase Done" process Setup Packet (See Standard USB
+ * Command Processing)
+ */
+static int32_t dwc_otg_pcd_handle_out_ep_intr(dwc_otg_pcd_t * pcd)
+{
+
+ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
+ uint32_t ep_intr;
+ doepint_data_t doepint;
+ doepint_data_t doepint1;
+ uint32_t epnum = 0;
+ dwc_otg_pcd_ep_t *ep;
+ dwc_ep_t *dwc_ep;
+
+ doepint.d32 = 0;
+ doepint1.d32 = 0;
+
+
+ ep_intr = dwc_otg_read_dev_all_out_ep_intr(core_if);
+ while (ep_intr)
+ {
+ if (ep_intr & 0x1)
+ {
+ /* Get EP pointer */
+ ep = get_out_ep(pcd, epnum);
+ dwc_ep = &ep->dwc_ep;
+ doepint.d32 = dwc_otg_read_dev_out_ep_intr(core_if, dwc_ep);
+ /* Transfer complete */
+ if (doepint.b.xfercompl)
+ {
+ if (epnum == 0)
+ {
+ /* Clear the bit in DOEPINTn for this interrupt */
+ CLEAR_OUT_EP_INTR(core_if, epnum, xfercompl);
+ doepint1.d32 = DWC_READ_REG32(&core_if->dev_if->out_ep_regs[0]->doepint);
+ if (pcd->ep0state == EP0_IDLE && doepint1.b.sr)
+ {
+ CLEAR_OUT_EP_INTR(core_if, epnum, sr);
+ }
+ else if(pcd->ep0state != EP0_IDLE)
+ {
+ handle_ep0(pcd);
+ }
+ }
+ else
+ {
+ /* Clear the bit in DOEPINTn for this interrupt */
+ CLEAR_OUT_EP_INTR(core_if, epnum,xfercompl);
+ complete_ep(ep);
+ }
+
+ }
+
+ /* Endpoint disable */
+ if (doepint.b.epdisabled)
+ {
+ /* Clear the bit in DOEPINTn for this interrupt */
+ CLEAR_OUT_EP_INTR(core_if, epnum, epdisabled);
+ }
+ if (doepint.b.setup)
+ {
+ CLEAR_OUT_EP_INTR(core_if, epnum, setup);
+
+ handle_ep0(pcd);
+
+ }
+ if (doepint.b.outtknepdis)
+ {
+ CLEAR_OUT_EP_INTR(core_if, epnum, outtknepdis);
+ }
+
+ /* NAK Interrutp */
+ if (doepint.b.nak)
+ {
+ handle_out_ep_nak_intr(pcd, epnum);
+
+ CLEAR_OUT_EP_INTR(core_if, epnum, nak);
+ }
+
+ /* NYET Interrutp */
+ if (doepint.b.nyet)
+ {
+ handle_out_ep_nyet_intr(pcd, epnum);
+
+ CLEAR_OUT_EP_INTR(core_if, epnum, nyet);
+ }
+ }
+
+ epnum++;
+ ep_intr >>= 1;
+ }
+
+ return 1;
+
+#undef CLEAR_OUT_EP_INTR
+}
+
+/**
+ * PCD interrupt handler.
+ *
+ * The PCD handles the device interrupts. Many conditions can cause a
+ * device interrupt. When an interrupt occurs, the device interrupt
+ * service routine determines the cause of the interrupt and
+ * dispatches handling to the appropriate function. These interrupt
+ * handling functions are described below.
+ *
+ * All interrupt registers are processed from LSB to MSB.
+ *
+ */
+
+extern int32_t dwc_otg_handle_usb_suspend_intr(dwc_otg_core_if_t * core_if);
+
+int32_t dwc_otg_pcd_handle_intr(dwc_otg_pcd_t * pcd)
+{
+ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
+
+ gintsts_data_t gintr_status;
+ int32_t retval = 0;
+ gintr_status.d32 = dwc_otg_read_core_intr(core_if);
+
+ if (gintr_status.b.rxstsqlvl)
+ {
+ retval |=
+ dwc_otg_pcd_handle_rx_status_q_level_intr(pcd);
+ }
+ //½«Á½¸öÖжϺϳÉÒ»¸ö
+ if (gintr_status.b.usbsuspend)
+ {
+ retval |= dwc_otg_handle_usb_suspend_intr(pcd->core_if);
+ }
+ if (gintr_status.b.usbreset)
+ {
+ retval |= dwc_otg_pcd_handle_usb_reset_intr(pcd);
+ global.g_Connet =1;
+ }
+ if (gintr_status.b.enumdone)
+ {
+ retval |= dwc_otg_pcd_handle_enum_done_intr(pcd);
+ }
+ if (gintr_status.b.inepint)
+ {
+ if (!core_if->multiproc_int_enable)
+ {
+ retval |= dwc_otg_pcd_handle_in_ep_intr(pcd);
+ }
+ }
+ if (gintr_status.b.outepintr)
+ {
+ if (!core_if->multiproc_int_enable)
+ {
+ retval |= dwc_otg_pcd_handle_out_ep_intr(pcd);
+ }
+ }
+ return retval;
+}
+
+#endif /* DWC_HOST_ONLY */
diff --git a/boot/common/src/uboot/drivers/usb_drv/global.c b/boot/common/src/uboot/drivers/usb_drv/global.c
new file mode 100644
index 0000000..4438c79
--- /dev/null
+++ b/boot/common/src/uboot/drivers/usb_drv/global.c
@@ -0,0 +1,101 @@
+#include <usb/global.h>
+
+__align(4) dwc_config_all_t desc =
+{
+//T_CONFIG_DESCRIPTOR
+{
+ sizeof(dwc_config_descriptor_t), //bLength
+ CONFIG_DESCRIPTOR, //bDescriptorType
+ sizeof(dwc_config_all_t),
+ 2, //bNumInterfaces
+ 1, //bConfigurationValue
+ 0, //iConfiguration×Ö·û´®ÃèÊöµÄË÷Òý
+ ATTR_D7 |ATTR_SELF_POWERED , //bmAttributes
+ POWER_MA(500), //
+},
+
+
+//T_INTERFACE_DESCRIPTOR
+{
+ sizeof(dwc_interface_descriptor_t), //bLength
+ INTERFACE_DESCRIPTOR, //bDescriptorType
+ 0, //bInterfaceNumber
+ 0, //bAlternateSetting
+ 0x02, //bNumEndpoints
+ VERDOR_SPECIFIC, //bInterfaceClass
+ 0xff, //bInterfaceSubClass
+ 0xff, //bInterfaceProtocol
+ 0x04, //iInterface×Ö·û´®ÃèÊöµÄË÷Òý
+},
+{
+ {
+ sizeof(dwc_ep_descriptor_t), //bLength
+ ENDPOINT_DESCRIPTOR, //bDescriptorType
+ EP_ADDRESS_DIRECTION_IN |0x1, //bEndpointAddress
+ EP_ATTR_TRANSFER_TYPE_BULK, //bmAttributes
+ USB_HIGHSPEED_BULK_MAXSIZE, //wMaxPacketSize
+ 0, //bInterval
+ }
+},
+{
+ {
+ sizeof(dwc_ep_descriptor_t), //bLength
+ ENDPOINT_DESCRIPTOR, //bDescriptorType
+ 0x1, //bEndpointAddress
+ EP_ATTR_TRANSFER_TYPE_BULK, //bmAttributes
+ USB_HIGHSPEED_BULK_MAXSIZE, //wMaxPacketSize
+ 0, //bInterval
+ }
+},
+//T_INTERFACE_DESCRIPTOR
+{
+ sizeof(dwc_interface_descriptor_t), //bLength
+ INTERFACE_DESCRIPTOR, //bDescriptorType
+ 1, //bInterfaceNumber
+ 0, //bAlternateSetting
+ 0x02, //bNumEndpoints
+ VERDOR_SPECIFIC, //bInterfaceClass
+ 0xff, //bInterfaceSubClass
+ 0xff, //bInterfaceProtocol
+ 0x05, //iInterface×Ö·û´®ÃèÊöµÄË÷Òý
+},
+{
+ {
+ sizeof(dwc_ep_descriptor_t), //bLength
+ ENDPOINT_DESCRIPTOR, //bDescriptorType
+ EP_ADDRESS_DIRECTION_IN |0x2, //bEndpointAddress
+ EP_ATTR_TRANSFER_TYPE_BULK, //bmAttributes
+ USB_HIGHSPEED_BULK_MAXSIZE, //wMaxPacketSize
+ 0, //bInterval
+ }
+},
+{
+ {
+ sizeof(dwc_ep_descriptor_t), //bLength
+ ENDPOINT_DESCRIPTOR, //bDescriptorType
+ 0x2, //bEndpointAddress
+ EP_ATTR_TRANSFER_TYPE_BULK, //bmAttributes
+ USB_HIGHSPEED_BULK_MAXSIZE, //wMaxPacketSize
+ 0, //bInterval
+ }
+},
+};
+
+struct g_data global;
+
+__align(4) dwc_config_all_t g_config_desc ;
+
+void data_init(void)
+{
+ int i;
+ char *src = (char*)&desc;
+ char *dst = (char*)&g_config_desc;
+
+ for(i = 0; i < sizeof(dwc_config_all_t); i++)
+ {
+ *dst++ = *src++;
+ }
+}
+
+
+