Esempio n. 1
0
/**
 * 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
}
Esempio n. 2
0
/*
 * 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, &regs->pcgcctl);

	/* Initialize Host Configuration Register */
	init_fslspclksel(regs);
#ifdef CONFIG_DWC2_DFLT_SPEED_FULL
	setbits_le32(&regs->host_regs.hcfg, DWC2_HCFG_FSLSSUPP);
#endif

	/* Configure data FIFO sizes */
#ifdef CONFIG_DWC2_ENABLE_DYNAMIC_FIFO
	if (readl(&regs->ghwcfg2) & DWC2_HWCFG2_DYNAMIC_FIFO) {
		/* Rx FIFO */
		writel(CONFIG_DWC2_HOST_RX_FIFO_SIZE, &regs->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, &regs->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, &regs->hptxfsiz);
	}
#endif

	/* Clear Host Set HNP Enable in the OTG Control Register */
	clrbits_le32(&regs->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(&regs->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(&regs->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(&regs->hc_regs[i].hcchar,
				DWC2_HCCHAR_EPDIR,
				DWC2_HCCHAR_CHEN | DWC2_HCCHAR_CHDIS);
		ret = wait_for_bit(&regs->hc_regs[i].hcchar,
				   DWC2_HCCHAR_CHEN, 0);
		if (ret)
			printf("%s: Timeout!\n", __func__);
	}

	/* Turn on the vbus power. */
	if (readl(&regs->gintsts) & DWC2_GINTSTS_CURMODE_HOST) {
		hprt0 = readl(&regs->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, &regs->hprt0);
		}
	}
}
Esempio n. 3
0
/**
 * 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;
}