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

📄 dwc_otg_cil.c

📁 host usb 主设备程序 支持sd卡 mouse keyboard 的最单单的驱动程序 gcc编译
💻 C
📖 第 1 页 / 共 5 页
字号:
/** * 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){	int i = 0;	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 = {.d32 = 0 };	gusbcfg_data_t usbcfg = {.d32 = 0 };#if 0	gi2cctl_data_t i2cctl = {.d32 = 0 };#endif	dbg_otg("%s(%p)\n", __FUNCTION__, _core_if);	/* Common Initialization */	usbcfg.d32 = dwc_read_reg32(&global_regs->gusbcfg);	/* Program the ULPI External VBUS bit if needed */	usbcfg.b.ulpi_ext_vbus_drv =		(_core_if->core_params->phy_ulpi_ext_vbus == DWC_PHY_ULPI_EXTERNAL_VBUS) ? 1 : 0;	/* Set external TS Dline pulsing */	usbcfg.b.term_sel_dl_pulse = (_core_if->core_params->ts_dline == 1) ? 1 : 0;	dwc_write_reg32(&global_regs->gusbcfg, usbcfg.d32);	/* Reset the Controller */	dwc_otg_core_reset(_core_if);	/* Initialize parameters from Hardware configuration registers. */	dev_if->num_in_eps = calc_num_in_eps(_core_if);	dev_if->num_out_eps = calc_num_out_eps(_core_if);	dbg_otg("num_dev_perio_in_ep=%d\n", _core_if->hwcfg4.b.num_dev_perio_in_ep);	for (i = 0; i < _core_if->hwcfg4.b.num_dev_perio_in_ep; i++) {		dev_if->perio_tx_fifo_size[i] =			dwc_read_reg32(&global_regs->dptxfsiz_dieptxf[i]) >> 16;		dbg_otg("Periodic Tx FIFO SZ #%d=0x%0x\n",			    i, dev_if->perio_tx_fifo_size[i]);	}	for (i = 0; i < _core_if->hwcfg4.b.num_in_eps; i++) {		dev_if->tx_fifo_size[i] = dwc_read_reg32(&global_regs->dptxfsiz_dieptxf[i]) >> 16;		dbg_otg("Tx FIFO SZ #%d=0x%0x\n", i, dev_if->perio_tx_fifo_size[i]);	}	_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;	dbg_otg("Total FIFO SZ=%d\n", _core_if->total_fifo_size);	dbg_otg("Rx FIFO SZ=%d\n", _core_if->rx_fifo_size);	dbg_otg("NP Tx FIFO SZ=%d\n", _core_if->nperio_tx_fifo_size);#if 0	/* This programming sequence needs to happen in FS mode before any other	 * programming occurs */	if ((_core_if->core_params->speed == DWC_SPEED_PARAM_FULL) &&	    (_core_if->core_params->phy_type == DWC_PHY_TYPE_PARAM_FS)) {		/* If FS mode with FS PHY */		/* core_init() is now called on every switch so only call the		 * following for the first time through. */		if (!_core_if->phy_init_done) {			_core_if->phy_init_done = 1;			dbg_otg("FS_PHY detected\n");			usbcfg.d32 = dwc_read_reg32(&global_regs->gusbcfg);			usbcfg.b.physel = 1;			dwc_write_reg32(&global_regs->gusbcfg, usbcfg.d32);			/* Reset after a PHY select */			dwc_otg_core_reset(_core_if);		}		/* Program DCFG.DevSpd or HCFG.FSLSPclkSel to 48Mhz in FS.      Also		 * do this on HNP Dev/Host mode switches (done in dev_init and		 * host_init). */		if (dwc_otg_is_host_mode(_core_if)) {			init_fslspclksel(_core_if);		} else {			init_devspd(_core_if);		}		if (_core_if->core_params->i2c_enable) {			DWC_DEBUGPL(DBG_CIL, "FS_PHY Enabling I2c\n");			/* Program GUSBCFG.OtgUtmifsSel to I2C */			usbcfg.d32 = dwc_read_reg32(&global_regs->gusbcfg);			usbcfg.b.otgutmifssel = 1;			dwc_write_reg32(&global_regs->gusbcfg, usbcfg.d32);			/* Program GI2CCTL.I2CEn */			i2cctl.d32 = dwc_read_reg32(&global_regs->gi2cctl);			i2cctl.b.i2cdevaddr = 1;			i2cctl.b.i2cen = 0;			dwc_write_reg32(&global_regs->gi2cctl, i2cctl.d32);			i2cctl.b.i2cen = 1;			dwc_write_reg32(&global_regs->gi2cctl, i2cctl.d32);		}	}	/* endif speed == DWC_SPEED_PARAM_FULL */	else {		/* 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.  */			usbcfg.b.ulpi_utmi_sel = _core_if->core_params->phy_type;			if (usbcfg.b.ulpi_utmi_sel == 1) {				/* ULPI interface */				usbcfg.b.phyif = 0;				usbcfg.b.ddrsel = _core_if->core_params->phy_ulpi_ddr;			} else {				/* UTMI+ interface */				if (_core_if->core_params->phy_utmi_width == 16) {					usbcfg.b.phyif = 1;				} else {					usbcfg.b.phyif = 0;				}			}			dwc_write_reg32(&global_regs->gusbcfg, usbcfg.d32);			writel(0x340f, S3C_UDC_OTG_GUSBCFG);			/* Reset after setting the PHY parameters */			dbg_otg("2-S3C_UDC_OTG_GUSBCFG: %08x\n", readl(S3C_UDC_OTG_GUSBCFG));			dwc_otg_core_reset(_core_if);		}	}	if ((_core_if->hwcfg2.b.hs_phy_type == 2) &&	    (_core_if->hwcfg2.b.fs_phy_type == 1) && (_core_if->core_params->ulpi_fs_ls)) {		DWC_DEBUGPL(DBG_CIL, "Setting ULPI FSLS\n");		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);	}#else	writel(0x340f, S3C_UDC_OTG_GUSBCFG);	/* Reset after setting the PHY parameters */	dbg_otg("2-S3C_UDC_OTG_GUSBCFG: %08x\n", readl(S3C_UDC_OTG_GUSBCFG));	dwc_otg_core_reset(_core_if);#endif	/* Program the GAHBCFG Register. */	switch (_core_if->hwcfg2.b.architecture) {	case DWC_SLAVE_ONLY_ARCH:		dbg_otg("Slave Only Mode\n\n");		ahbcfg.b.nptxfemplvl_txfemplvl = DWC_GAHBCFG_TXFEMPTYLVL_HALFEMPTY;		ahbcfg.b.ptxfemplvl = DWC_GAHBCFG_TXFEMPTYLVL_HALFEMPTY;		_core_if->dma_enable = 0;		_core_if->dma_desc_enable = 0;		break;	case DWC_EXT_DMA_ARCH:		dbg_otg("External DMA Mode\n\n");		ahbcfg.b.hburstlen = _core_if->core_params->dma_burst_size;		_core_if->dma_enable = (_core_if->core_params->dma_enable != 0);		_core_if->dma_desc_enable = (_core_if->core_params->dma_desc_enable != 0);		break;	case DWC_INT_DMA_ARCH:		printk("Internal DMA Mode\n\n");		ahbcfg.b.hburstlen = DWC_GAHBCFG_INT_DMA_BURST_INCR;		_core_if->dma_enable = (_core_if->core_params->dma_enable != 0);		_core_if->dma_desc_enable = (_core_if->core_params->dma_desc_enable != 0);		break;	}	ahbcfg.b.dmaenable = _core_if->dma_enable;	dwc_write_reg32(&global_regs->gahbcfg, ahbcfg.d32);	_core_if->en_multiple_tx_fifo = _core_if->hwcfg4.b.ded_fifo_en;	/*	 * Program the GUSBCFG register.	 */	usbcfg.d32 = dwc_read_reg32(&global_regs->gusbcfg);	switch (_core_if->hwcfg2.b.op_mode) {	case DWC_MODE_HNP_SRP_CAPABLE:		usbcfg.b.hnpcap = (_core_if->core_params->otg_cap ==				   DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE);		usbcfg.b.srpcap = (_core_if->core_params->otg_cap !=				   DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE);		break;	case DWC_MODE_SRP_ONLY_CAPABLE:		usbcfg.b.hnpcap = 0;		usbcfg.b.srpcap = (_core_if->core_params->otg_cap !=				   DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE);		break;	case DWC_MODE_NO_HNP_SRP_CAPABLE:		usbcfg.b.hnpcap = 0;		usbcfg.b.srpcap = 0;		break;	case DWC_MODE_SRP_CAPABLE_DEVICE:		usbcfg.b.hnpcap = 0;		usbcfg.b.srpcap = (_core_if->core_params->otg_cap !=				   DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE);		break;	case DWC_MODE_NO_SRP_CAPABLE_DEVICE:		usbcfg.b.hnpcap = 0;		usbcfg.b.srpcap = 0;		break;	case DWC_MODE_SRP_CAPABLE_HOST:		usbcfg.b.hnpcap = 0;		usbcfg.b.srpcap = (_core_if->core_params->otg_cap !=				   DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE);		break;	case DWC_MODE_NO_SRP_CAPABLE_HOST:		usbcfg.b.hnpcap = 0;		usbcfg.b.srpcap = 0;		break;	}	dwc_write_reg32(&global_regs->gusbcfg, usbcfg.d32);	dbg_otg("3-S3C_UDC_OTG_GUSBCFG: %08x\n", readl(S3C_UDC_OTG_GUSBCFG));	/* Enable common interrupts */	dwc_otg_enable_common_interrupts(_core_if);	/* Do device or host intialization based on mode during PCD	 * and HCD initialization  */	if (dwc_otg_is_host_mode(_core_if)) {		printk("Host Mode\n");		_core_if->op_state = A_HOST;	} else {		printk("Device Mode\n");		_core_if->op_state = B_PERIPHERAL;#ifdef DWC_DEVICE_ONLY		dwc_otg_core_dev_init(_core_if);#endif	}}/** * 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 = {.d32 = 0 };	dwc_otg_core_global_regs_t *global_regs = _core_if->core_global_regs;	DWC_DEBUGPL(DBG_CIL, "%s()\n", __func__);	/* 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 */	dwc_otg_enable_common_interrupts(_core_if);	/* Enable interrupts */	intr_mask.b.usbreset = 1;	intr_mask.b.enumdone = 1;	intr_mask.b.inepintr = 1;	intr_mask.b.outepintr = 1;	intr_mask.b.erlysuspend = 1;	if (_core_if->en_multiple_tx_fifo == 0) {		intr_mask.b.epmismatch = 1;	}	/** @todo NGS: Should this be a module parameter? */#ifdef USE_PERIODIC_EP	intr_mask.b.isooutdrop = 1;	intr_mask.b.eopframe = 1;	intr_mask.b.incomplisoin = 1;	intr_mask.b.incomplisoout = 1;#endif	dwc_modify_reg32(&global_regs->gintmsk, intr_mask.d32, intr_mask.d32);	DWC_DEBUGPL(DBG_CIL, "%s() gintmsk=%0x\n", __func__, dwc_read_reg32(&global_regs->gintmsk));}/** * 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_core_global_regs_t *global_regs = _core_if->core_global_regs;	dwc_otg_dev_if_t *dev_if = _core_if->dev_if;	dwc_otg_core_params_t *params = _core_if->core_params;	dcfg_data_t dcfg = {.d32 = 0 };	grstctl_t resetctl = {.d32 = 0 };	uint32_t rx_fifo_size;	fifosize_data_t nptxfifosize;	fifosize_data_t txfifosize;	dthrctl_data_t dthrctl;	fifosize_data_t ptxfifosize;	/* Restart the Phy Clock */	dwc_write_reg32(_core_if->pcgcctl, 0);	/* Device configuration register */	init_devspd(_core_if);	dcfg.d32 = dwc_read_reg32(&dev_if->dev_global_regs->dcfg);	dcfg.b.descdma = (_core_if->dma_desc_enable) ? 1 : 0;	dcfg.b.perfrint = DWC_DCFG_FRAME_INTERVAL_80;	dwc_write_reg32(&dev_if->dev_global_regs->dcfg, dcfg.d32);	/* Configure data FIFO sizes */	if (_core_if->hwcfg2.b.dynamic_fifo && params->enable_dynamic_fifo) {		DWC_DEBUGPL(DBG_CIL, "Total FIFO Size=%d\n", _core_if->total_fifo_size);		DWC_DEBUGPL(DBG_CIL, "Rx FIFO Size=%d\n", params->dev_rx_fifo_size);		DWC_DEBUGPL(DBG_CIL, "NP Tx FIFO Size=%d\n", params->dev_nperio_tx_fifo_size);		/* Rx FIFO */		DWC_DEBUGPL(DBG_CIL, "initial grxfsiz=%08x\n",			    dwc_read_reg32(&global_regs->grxfsiz));		rx_fifo_size = params->dev_rx_fifo_size;		dwc_write_reg32(&global_regs->grxfsiz, rx_fifo_size);		DWC_DEBUGPL(DBG_CIL, "new grxfsiz=%08x\n", dwc_read_reg32(&global_regs->grxfsiz));		/** Set Periodic Tx FIFO Mask all bits 0 */		_core_if->p_tx_msk = 0;		/** Set Tx FIFO Mask all bits 0 */		_core_if->tx_msk = 0;		if (_core_if->en_multiple_tx_fifo == 0) {			/* Non-periodic Tx FIFO */			DWC_DEBUGPL(DBG_CIL, "initial gnptxfsiz=%08x\n",				    dwc_read_reg32(&global_regs->gnptxfsiz));			nptxfifosize.b.depth = params->dev_nperio_tx_fifo_size;			nptxfifosize.b.startaddr = params->dev_rx_fifo_size;			dwc_write_reg32(&global_regs->gnptxfsiz, nptxfifosize.d32);			DWC_DEBUGPL(DBG_CIL, "new gnptxfsiz=%08x\n",				    dwc_read_reg32(&global_regs->gnptxfsiz));			/**@todo NGS: Fix Periodic FIFO Sizing! */			/*			 * Periodic Tx FIFOs These FIFOs are numbered from 1 to 15.			 * Indexes of the FIFO size module parameters in the			 * dev_perio_tx_fifo_size array and the FIFO size registers in			 * the dptxfsiz array run from 0 to 14.			 */			/** @todo Finish debug of this */			ptxfifosize.b.startaddr = nptxfifosize.b.startaddr + nptxfifosize.b.depth;			for (i = 0; i < _core_if->hwcfg4.b.num_dev_perio_in_ep; i++) {				ptxfifosize.b.depth = params->dev_perio_tx_fifo_size[i];				DWC_DEBUGPL(DBG_CIL, "initial dptxfsiz_dieptxf[%d]=%08x\n", i,					    dwc_read_reg32(&global_regs->dptxfsiz_dieptxf[i]));				dwc_write_reg32(&global_regs->dptxfsiz_dieptxf[i], ptxfifosize.d32);				DWC_DEBUGPL(DBG_CIL, "new dptxfsiz_dieptxf[%d]=%08x\n", i,					    dwc_read_reg32(&global_regs->dptxfsiz_dieptxf[i]));				ptxfifosize.b.startaddr += ptxfifosize.b.depth;			}		} else {			/*			 * Tx FIFOs These FIFOs are numbered from 1 to 15.			 * Indexes of the FIFO size module parameters in the			 * dev_tx_fifo_size array and the FIFO size registers in			 * the dptxfsiz_dieptxf array run from 0 to 14.			 */			/* Non-periodic Tx FIFO */			DWC_DEBUGPL(DBG_CIL, "initial gnptxfsiz=%08x\n",				    dwc_read_reg32(&global_regs->gnptxfsiz));			nptxfifosize.b.depth = params->dev_nperio_tx_fifo_size;			nptxfifosize.b.startaddr = params->dev_rx_fifo_size;			dwc_write_reg32(&global_regs->gnptxfsiz, nptxfifosize.d32);			DWC_DEBUGPL(DBG_CIL, "new gnptxfsiz=%08x\n",				    dwc_read_reg32(&global_regs->gnptxfsiz));			txfifosize.b.startaddr = nptxfifosize.b.startaddr + nptxfifosize.b.depth;

⌨️ 快捷键说明

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