📄 dwc_otg_cil.c
字号:
/** * 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 + -