⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dwc_otg_pcd_intr.c

📁 host usb 主设备程序 支持sd卡 mouse keyboard 的最单单的驱动程序 gcc编译
💻 C
📖 第 1 页 / 共 5 页
字号:
	dwc_otg_dev_if_t* dev_if = core_if->dev_if;	dwc_otg_dev_in_ep_regs_t *ep_regs;	dtxfsts_data_t txstatus = {.d32 = 0};	dwc_otg_pcd_ep_t *ep = 0;	uint32_t len = 0;	int dwords;	ep = get_in_ep(_pcd, epnum);	DWC_DEBUGPL(DBG_PCD, "Dedicated TxFifo Empty: %s(%d) \n", ep->ep.name, epnum );	ep_regs = core_if->dev_if->in_ep_regs[epnum];	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);	DWC_DEBUGPL(DBG_PCDV, "b4 dtxfsts[%d]=0x%08x\n",epnum,txstatus.d32);	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);		DWC_DEBUGPL(DBG_PCDV,"dtxfsts[%d]=0x%08x\n", epnum, txstatus.d32);	}	DWC_DEBUGPL(DBG_PCDV, "b4 dtxfsts[%d]=0x%08x\n",epnum,dwc_read_reg32(&dev_if->in_ep_regs[epnum]->dtxfsts));	return 1;}/** * This function is called when the Device is disconnected.	 It stops * any active requests and informs the Gadget driver of the * disconnect. */void dwc_otg_pcd_stop(dwc_otg_pcd_t *_pcd){	int i, num_in_eps, num_out_eps;	dwc_otg_pcd_ep_t *ep;	gintmsk_data_t intr_mask = {.d32 = 0};	num_in_eps = GET_CORE_IF(_pcd)->dev_if->num_in_eps;	num_out_eps = GET_CORE_IF(_pcd)->dev_if->num_out_eps;	DWC_DEBUGPL(DBG_PCDV, "%s() \n", __func__ );	/* don't disconnect drivers more than once */	if (_pcd->ep0state == EP0_DISCONNECT)	{		DWC_DEBUGPL(DBG_ANY, "%s() Already Disconnected\n", __func__ );		return;	}	_pcd->ep0state = EP0_DISCONNECT;	/* Reset the OTG state. */	dwc_otg_pcd_update_otg( _pcd, 1);	/* Disable the NP Tx Fifo Empty Interrupt. */	intr_mask.b.nptxfempty = 1;	dwc_modify_reg32(&GET_CORE_IF(_pcd)->core_global_regs->gintmsk,					 intr_mask.d32, 0);	/* Flush the FIFOs */	/**@todo NGS Flush Periodic FIFOs */	dwc_otg_flush_tx_fifo( GET_CORE_IF(_pcd), 0x10);	dwc_otg_flush_rx_fifo( GET_CORE_IF(_pcd) );	/* prevent new request submissions, kill any outstanding requests  */	ep = &_pcd->ep0;	request_nuke(ep);	/* prevent new request submissions, kill any outstanding requests  */	for (i = 0; i < num_in_eps; i++)	{		dwc_otg_pcd_ep_t *ep = &_pcd->in_ep[i];		request_nuke(ep);	}	/* prevent new request submissions, kill any outstanding requests  */	for (i = 0; i < num_out_eps; i++)	{		dwc_otg_pcd_ep_t *ep = &_pcd->out_ep[i];		request_nuke(ep);	}	/* report disconnect; the driver is already quiesced */	if (_pcd->driver && _pcd->driver->disconnect)	{		SPIN_UNLOCK(&_pcd->lock);		_pcd->driver->disconnect(&_pcd->gadget);		SPIN_LOCK(&_pcd->lock);	}}/** * This interrupt indicates that ... */int32_t dwc_otg_pcd_handle_i2c_intr(dwc_otg_pcd_t *_pcd){	gintmsk_data_t intr_mask = { .d32 = 0};	gintsts_data_t gintsts;	DWC_PRINT("INTERRUPT Handler not implemented for %s\n", "i2cintr");	intr_mask.b.i2cintr = 1;	dwc_modify_reg32( &GET_CORE_IF(_pcd)->core_global_regs->gintmsk,					  intr_mask.d32, 0 );	/* Clear interrupt */	gintsts.d32 = 0;	gintsts.b.i2cintr = 1;	dwc_write_reg32 (&GET_CORE_IF(_pcd)->core_global_regs->gintsts,						 gintsts.d32);	return 1;}/** * This interrupt indicates that ... */int32_t dwc_otg_pcd_handle_early_suspend_intr(dwc_otg_pcd_t *_pcd){	gintsts_data_t gintsts;#if defined(VERBOSE)	DWC_PRINT("Early Suspend Detected\n");#endif	/* Clear interrupt */	gintsts.d32 = 0;	gintsts.b.erlysuspend = 1;	dwc_write_reg32( &GET_CORE_IF(_pcd)->core_global_regs->gintsts,						 gintsts.d32);	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 inline 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 = { .d32 = 0};	dwc_otg_dma_desc_t* dma_desc;	depctl_data_t doepctl = { .d32 = 0 };#ifdef VERBOSE	DWC_DEBUGPL(DBG_PCDV,"%s() doepctl0=%0x\n", __func__,				dwc_read_reg32(&dev_if->out_ep_regs[0]->doepctl));#endif	doeptsize0.b.supcnt = 3;	doeptsize0.b.pktcnt = 1;	doeptsize0.b.xfersize = 8*3;	if (_core_if->dma_enable)	{		if (!_core_if->dma_desc_enable)		{			/** put here as for Hermes mode deptisz register should not be written */			dwc_write_reg32( &dev_if->out_ep_regs[0]->doeptsiz,			 doeptsize0.d32 );			/** @todo dma needs to handle multiple setup packets (up to 3) */			dwc_write_reg32(&dev_if->out_ep_regs[0]->doepdma,			_pcd->setup_pkt_dma_handle);		}		else		{			dev_if->setup_desc_index = (dev_if->setup_desc_index + 1) & 1;			dma_desc = dev_if->setup_desc_addr[dev_if->setup_desc_index];			/** DMA Descriptor Setup */			dma_desc->status.b.bs = BS_HOST_BUSY;			dma_desc->status.b.l = 1;			dma_desc->status.b.ioc = 1;			dma_desc->status.b.bytes = _pcd->ep0.dwc_ep.maxpacket;			dma_desc->buf = (uint32_t*)_pcd->setup_pkt_dma_handle;			dma_desc->status.b.bs = BS_HOST_READY;			/** DOEPDMA0 Register write */			dwc_write_reg32(&dev_if->out_ep_regs[0]->doepdma, dev_if->dma_setup_desc_addr[dev_if->setup_desc_index]);		}		/** DOEPCTL0 Register write */		doepctl.b.epena = 1;		doepctl.b.cnak = 1;		dwc_write_reg32(&dev_if->out_ep_regs[0]->doepctl, doepctl.d32);	}	else	{		/** put here as for Hermes mode deptisz register should not be written */		dwc_write_reg32( &dev_if->out_ep_regs[0]->doeptsiz,					 doeptsize0.d32 );	}#ifdef VERBOSE		DWC_DEBUGPL(DBG_PCDV,"doepctl0=%0x\n",					dwc_read_reg32(&dev_if->out_ep_regs[0]->doepctl));		DWC_DEBUGPL(DBG_PCDV,"diepctl0=%0x\n",					dwc_read_reg32(&dev_if->in_ep_regs[0]->diepctl));#endif}/** * 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( 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 = { .d32 = 0};	daint_data_t daintmsk = { .d32 = 0};	doepmsk_data_t doepmsk = { .d32 = 0};	diepmsk_data_t diepmsk = { .d32 = 0};	dcfg_data_t dcfg = { .d32=0 };	grstctl_t resetctl = { .d32=0 };	dctl_data_t dctl = {.d32=0};	int i = 0;	gintsts_data_t gintsts;	DWC_PRINT("USB RESET\n");#ifdef _EN_ISOC_	for(i = 1;i < 16;++i)	{		dwc_otg_pcd_ep_t *ep;		dwc_ep_t *dwc_ep;		ep = get_in_ep(_pcd,i);		if(ep != 0){			dwc_ep = &ep->dwc_ep;			dwc_ep->next_frame = 0xffffffff;		}	}#endif /* _EN_ISOC_  */	/* reset the HNP settings */	dwc_otg_pcd_update_otg( _pcd, 1);	/* 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;	if(core_if->dma_desc_enable)	{		doepmsk.b.stsphsercvd = 1;		doepmsk.b.bna = 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;	diepmsk.b.intknepmis = 1;	if(core_if->dma_desc_enable)	{		diepmsk.b.bna = 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);	/* setup EP0 to receive SETUP packets */	ep0_out_start( core_if, _pcd );	/* Clear interrupt */	gintsts.d32 = 0;	gintsts.b.usbreset = 1;	dwc_write_reg32 (&core_if->core_global_regs->gintsts, gintsts.d32);	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;	enum usb_device_speed speed = USB_SPEED_UNKNOWN;	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. */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;	uint32_t gsnpsid = global_regs->gsnpsid;	uint8_t utmi16b, utmi8b;	DWC_DEBUGPL(DBG_PCD, "SPEED ENUM\n");	if(gsnpsid >= (uint32_t)0x4f54260a)	{		utmi16b = 6;		utmi8b = 9;	}	else	{		utmi16b = 4;		utmi8b = 8;	}	dwc_otg_ep0_activate( GET_CORE_IF(_pcd), &ep0->dwc_ep );#ifdef DEBUG_EP0	print_ep0_state(_pcd);#endif	if (_pcd->ep0state == EP0_DISCONNECT)	{		_pcd->ep0state = EP0_IDLE;	}	else if (_pcd->ep0state == EP0_STALL)	{		_pcd->ep0state = EP0_IDLE;	}	_pcd->ep0state = EP0_IDLE;	ep0->stopped = 0;	_pcd->gadget.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 (_pcd->gadget.speed == USB_SPEED_HIGH)	{		if (GET_CORE_IF(_pcd)->hwcfg2.b.hs_phy_type == DWC_HWCFG2_HS_PHY_TYPE_ULPI)		{			/* ULPI interface */			gusbcfg.b.usbtrdtim = 9;		}		if (GET_CORE_IF(_pcd)->hwcfg2.b.hs_phy_type == DWC_HWCFG2_HS_PHY_TYPE_UTMI)		{			/* UTMI+ interface */			if (GET_CORE_IF(_pcd)->hwcfg4.b.utmi_phy_data_width == 0)			{				gusbcfg.b.usbtrdtim = utmi8b;			}			else if (GET_CORE_IF(_pcd)->hwcfg4.b.utmi_phy_data_width == 1)			{//				DWC_PRINT("5555-16-1\n");				gusbcfg.b.usbtrdtim = utmi16b;			}			else if (GET_CORE_IF(_pcd)->core_params->phy_utmi_width == 8)			{				gusbcfg.b.usbtrdtim = utmi8b;			}			else			{//				DWC_PRINT("5555-16-2\n");				gusbcfg.b.usbtrdtim = utmi16b;			}		}		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)				{//					DWC_PRINT("5555-16-3\n");					gusbcfg.b.usbtrdtim = utmi16b;				}				else				{					gusbcfg.b.usbtrdtim = utmi8b;				}			}		}	}	else	{		/* Full or low speed */		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;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -