/** * handle the IN EP disable interrupt. */ static void handle_in_ep_disable_intr(uint32_t _epnum) { #if 0 deptsiz_data_t dieptsiz = { 0 }; dctl_data_t dctl = { 0 }; depctl_data_t diepctl = { 0 }; dwc_ep_t *ep = &g_dwc_eps[_epnum]; if (ep->stopped) { /* Flush the Tx FIFO */ /** @todo NGS: This is not the correct FIFO */ dwc_otg_flush_tx_fifo( core_if, 0 ); /* Clear the Global IN NP NAK */ dctl.d32 = 0; dctl.b.cgnpinnak = 1; dwc_modify_reg32(&dev_if->in_ep_regs[_epnum]->diepctl, diepctl.d32, diepctl.d32); /* Restart the transaction */ if (dieptsiz.b.pktcnt != 0 || dieptsiz.b.xfersize != 0) { restart_transfer( _pcd, _epnum ); } } #endif }
/* * This function initializes the DWC_otg controller registers for * host mode. * * This function flushes the Tx and Rx FIFOs and it flushes any entries in the * request queues. Host channels are reset to ensure that they are ready for * performing transfers. * * @param regs Programming view of DWC_otg controller * */ static void dwc_otg_core_host_init(struct dwc2_core_regs *regs) { uint32_t nptxfifosize = 0; uint32_t ptxfifosize = 0; uint32_t hprt0 = 0; int i, ret, num_channels; /* Restart the Phy Clock */ writel(0, ®s->pcgcctl); /* Initialize Host Configuration Register */ init_fslspclksel(regs); #ifdef CONFIG_DWC2_DFLT_SPEED_FULL setbits_le32(®s->host_regs.hcfg, DWC2_HCFG_FSLSSUPP); #endif /* Configure data FIFO sizes */ #ifdef CONFIG_DWC2_ENABLE_DYNAMIC_FIFO if (readl(®s->ghwcfg2) & DWC2_HWCFG2_DYNAMIC_FIFO) { /* Rx FIFO */ writel(CONFIG_DWC2_HOST_RX_FIFO_SIZE, ®s->grxfsiz); /* Non-periodic Tx FIFO */ nptxfifosize |= CONFIG_DWC2_HOST_NPERIO_TX_FIFO_SIZE << DWC2_FIFOSIZE_DEPTH_OFFSET; nptxfifosize |= CONFIG_DWC2_HOST_RX_FIFO_SIZE << DWC2_FIFOSIZE_STARTADDR_OFFSET; writel(nptxfifosize, ®s->gnptxfsiz); /* Periodic Tx FIFO */ ptxfifosize |= CONFIG_DWC2_HOST_PERIO_TX_FIFO_SIZE << DWC2_FIFOSIZE_DEPTH_OFFSET; ptxfifosize |= (CONFIG_DWC2_HOST_RX_FIFO_SIZE + CONFIG_DWC2_HOST_NPERIO_TX_FIFO_SIZE) << DWC2_FIFOSIZE_STARTADDR_OFFSET; writel(ptxfifosize, ®s->hptxfsiz); } #endif /* Clear Host Set HNP Enable in the OTG Control Register */ clrbits_le32(®s->gotgctl, DWC2_GOTGCTL_HSTSETHNPEN); /* Make sure the FIFOs are flushed. */ dwc_otg_flush_tx_fifo(regs, 0x10); /* All Tx FIFOs */ dwc_otg_flush_rx_fifo(regs); /* Flush out any leftover queued requests. */ num_channels = readl(®s->ghwcfg2); num_channels &= DWC2_HWCFG2_NUM_HOST_CHAN_MASK; num_channels >>= DWC2_HWCFG2_NUM_HOST_CHAN_OFFSET; num_channels += 1; for (i = 0; i < num_channels; i++) clrsetbits_le32(®s->hc_regs[i].hcchar, DWC2_HCCHAR_CHEN | DWC2_HCCHAR_EPDIR, DWC2_HCCHAR_CHDIS); /* Halt all channels to put them into a known state. */ for (i = 0; i < num_channels; i++) { clrsetbits_le32(®s->hc_regs[i].hcchar, DWC2_HCCHAR_EPDIR, DWC2_HCCHAR_CHEN | DWC2_HCCHAR_CHDIS); ret = wait_for_bit(®s->hc_regs[i].hcchar, DWC2_HCCHAR_CHEN, 0); if (ret) printf("%s: Timeout!\n", __func__); } /* Turn on the vbus power. */ if (readl(®s->gintsts) & DWC2_GINTSTS_CURMODE_HOST) { hprt0 = readl(®s->hprt0); hprt0 &= ~(DWC2_HPRT0_PRTENA | DWC2_HPRT0_PRTCONNDET); hprt0 &= ~(DWC2_HPRT0_PRTENCHNG | DWC2_HPRT0_PRTOVRCURRCHNG); if (!(hprt0 & DWC2_HPRT0_PRTPWR)) { hprt0 |= DWC2_HPRT0_PRTPWR; writel(hprt0, ®s->hprt0); } } }
/** * This interrupt occurs when a USB Reset is detected. When the USB * Reset Interrupt occurs the device state is set to DEFAULT and the * EP0 state is set to IDLE. * -# Set the NAK bit for all OUT endpoints (DOEPCTLn.SNAK = 1) * -# Unmask the following interrupt bits * - DAINTMSK.INEP0 = 1 (Control 0 IN endpoint) * - DAINTMSK.OUTEP0 = 1 (Control 0 OUT endpoint) * - DOEPMSK.SETUP = 1 * - DOEPMSK.XferCompl = 1 * - DIEPMSK.XferCompl = 1 * - DIEPMSK.TimeOut = 1 * -# 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 * At this point, all the required initialization, except for enabling * the control 0 OUT endpoint is done, for receiving SETUP packets. */ int32_t dwc_otg_pcd_handle_usb_reset_intr(void) { depctl_data_t doepctl = { 0}; daint_data_t daintmsk = { 0}; doepmsk_data_t doepmsk = { 0}; diepmsk_data_t diepmsk = { 0}; dcfg_data_t dcfg = { 0 }; depctl_data_t diepctl = { 0}; depctl_data_t diepctl_rd = { 0}; grstctl_t resetctl = { 0 }; dctl_data_t dctl = { 0 }; int i = 0; gintsts_data_t gintsts; DBG("\nUSB RESET\n"); /* Clear the Remote Wakeup Signalling */ dctl.b.rmtwkupsig = 1; dwc_modify_reg32( DWC_REG_DCTL,dctl.d32, 0 ); /* Disable all active IN EPs */ diepctl.b.epdis = 1; diepctl.b.snak = 1; for (i=0; i < NUM_EP; i++) { diepctl_rd.d32 = dwc_read_reg32(DWC_REG_IN_EP_REG(i)); if (diepctl_rd.b.epena) { dwc_write_reg32(DWC_REG_IN_EP_REG(i),diepctl.d32 ); } } /* Set NAK for all OUT EPs */ doepctl.b.snak = 1; for (i=0; i < NUM_EP; i++) { dwc_write_reg32(DWC_REG_OUT_EP_REG(i), doepctl.d32 ); } /* Flush the NP Tx FIFO */ dwc_otg_flush_tx_fifo( 0 ); /* Flush the Learning Queue */ resetctl.b.intknqflsh = 1; dwc_write_reg32( DWC_REG_GRSTCTL, resetctl.d32); daintmsk.b.inep0 = 1; daintmsk.b.outep0 = 1; dwc_write_reg32( DWC_REG_DAINTMSK, daintmsk.d32 ); doepmsk.b.setup = 1; doepmsk.b.xfercompl = 1; doepmsk.b.ahberr = 1; doepmsk.b.epdisabled = 1; dwc_write_reg32( DWC_REG_DOEPMSK, doepmsk.d32 ); diepmsk.b.xfercompl = 1; diepmsk.b.timeout = 1; diepmsk.b.epdisabled = 1; diepmsk.b.ahberr = 1; dwc_write_reg32( DWC_REG_DIEPMSK, diepmsk.d32 ); /* Reset Device Address */ dcfg.d32 = dwc_read_reg32( DWC_REG_DCFG); dcfg.b.devaddr = 0; dwc_write_reg32( DWC_REG_DCFG, dcfg.d32); /* setup EP0 to receive SETUP packets */ ep0_out_start(); /* Clear interrupt */ gintsts.d32 = 0; gintsts.b.usbreset = 1; dwc_write_reg32 ( DWC_REG_GINTSTS, gintsts.d32); flush_cpu_cache(); return 1; }