zte's code,first commit

Change-Id: I9a04da59e459a9bc0d67f101f700d9d7dc8d681b
diff --git a/boot/common/src/loader/drivers/dwc_otg_cil.c b/boot/common/src/loader/drivers/dwc_otg_cil.c
new file mode 100644
index 0000000..22fd410
--- /dev/null
+++ b/boot/common/src/loader/drivers/dwc_otg_cil.c
@@ -0,0 +1,1174 @@
+/* ==========================================================================
+ * $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 <common.h>
+ 
+#include "global.h"
+#include "dwc_otg_regs.h"
+#include "dwc_otg_cil.h"
+#include "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)
+{
+    depctl_data_t depctl;
+    deptsiz_data_t deptsiz;
+
+    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));
+
+        if (ep->maxpacket > (ep->maxxfer / MAX_PKT_CNT))
+            ep->xfer_len += (ep->maxxfer < (ep->total_len - ep->xfer_len)) ?\
+                            ep->maxxfer : (ep->total_len - ep->xfer_len);
+        else
+            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)
+        {
+            deptsiz.b.xfersize = 0;
+            deptsiz.b.pktcnt = 1;
+        }
+        else
+        {
+            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)
+            {
+                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)
+        {
+            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);
+#if SYNC_USB_CTRL
+        REG32(ARM_PORTA)=0x87;
+#endif
+
+    }
+    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));
+
+
+        if (ep->maxpacket > (ep->maxxfer / MAX_PKT_CNT))
+            ep->xfer_len += (ep->maxxfer < (ep->total_len - ep->xfer_len)) ? ep->maxxfer : (ep->total_len - ep->xfer_len);
+        else
+            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)
+        {
+            deptsiz.b.xfersize = ep->maxpacket;
+            deptsiz.b.pktcnt = 1;
+        }
+        else
+        {
+            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)
+            {
+                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 SYNC_USB_CTRL
+        REG32(ARM_PORTA)=0x76;
+#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? */
+
+    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 !USE_ASIC
+    core_if->core_params->phy_type = DWC_PHY_TYPE_PARAM_ULPI;
+    #else
+    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;
+    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;
+}
+
+
+
+
+
+
+