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;
+}
+
+
+
+
+
+
+