📄 dwc_otg_cil.c
字号:
for (i = 1; i < _core_if->hwcfg4.b.num_dev_perio_in_ep; i++) { txfifosize.b.depth = params->dev_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 - 1], txfifosize.d32); DWC_DEBUGPL(DBG_CIL, "new dptxfsiz_dieptxf[%d]=%08x\n", i, dwc_read_reg32(&global_regs->dptxfsiz_dieptxf[i - 1])); txfifosize.b.startaddr += txfifosize.b.depth; } } } /* Flush the FIFOs */ dwc_otg_flush_tx_fifo(_core_if, 0x10); /* all Tx FIFOs */ dwc_otg_flush_rx_fifo(_core_if); /* Flush the Learning Queue. */ resetctl.b.intknqflsh = 1; dwc_write_reg32(&_core_if->core_global_regs->grstctl, resetctl.d32); /* Clear all pending Device Interrupts */ dwc_write_reg32(&dev_if->dev_global_regs->diepmsk, 0); dwc_write_reg32(&dev_if->dev_global_regs->doepmsk, 0); dwc_write_reg32(&dev_if->dev_global_regs->daint, 0xFFFFFFFF); dwc_write_reg32(&dev_if->dev_global_regs->daintmsk, 0); for (i = 0; i <= dev_if->num_in_eps; i++) { depctl_data_t depctl; depctl.d32 = dwc_read_reg32(&dev_if->in_ep_regs[i]->diepctl); if (depctl.b.epena) { depctl.d32 = 0; depctl.b.epdis = 1; depctl.b.snak = 1; } else { depctl.d32 = 0; } dwc_write_reg32(&dev_if->in_ep_regs[i]->diepctl, depctl.d32); dwc_write_reg32(&dev_if->in_ep_regs[i]->dieptsiz, 0); dwc_write_reg32(&dev_if->in_ep_regs[i]->diepdma, 0); dwc_write_reg32(&dev_if->in_ep_regs[i]->diepint, 0xFF); } for (i = 0; i <= dev_if->num_out_eps; i++) { depctl_data_t depctl; depctl.d32 = dwc_read_reg32(&dev_if->out_ep_regs[i]->doepctl); if (depctl.b.epena) { depctl.d32 = 0; depctl.b.epdis = 1; depctl.b.snak = 1; } else { depctl.d32 = 0; } dwc_write_reg32(&dev_if->out_ep_regs[i]->doepctl, depctl.d32); dwc_write_reg32(&dev_if->out_ep_regs[i]->doeptsiz, 0); dwc_write_reg32(&dev_if->out_ep_regs[i]->doepdma, 0); dwc_write_reg32(&dev_if->out_ep_regs[i]->doepint, 0xFF); } if (_core_if->en_multiple_tx_fifo && _core_if->dma_enable) { dev_if->non_iso_tx_thr_en = _core_if->core_params->thr_ctl & 0x1; dev_if->iso_tx_thr_en = (_core_if->core_params->thr_ctl >> 1) & 0x1; dev_if->rx_thr_en = (_core_if->core_params->thr_ctl >> 2) & 0x1; dev_if->rx_thr_length = _core_if->core_params->rx_thr_length; dev_if->tx_thr_length = _core_if->core_params->tx_thr_length; dev_if->setup_desc_index = 0; dthrctl.d32 = 0; dthrctl.b.non_iso_thr_en = dev_if->non_iso_tx_thr_en; dthrctl.b.iso_thr_en = dev_if->iso_tx_thr_en; dthrctl.b.tx_thr_len = dev_if->tx_thr_length; dthrctl.b.rx_thr_en = dev_if->rx_thr_en; dthrctl.b.rx_thr_len = dev_if->rx_thr_length; dwc_write_reg32(&dev_if->dev_global_regs->dtknqr3_dthrctl, dthrctl.d32); DWC_DEBUGPL(DBG_CIL, "Non ISO Tx Thr - %d\nISO Tx Thr - %d\nRx Thr - %d\nTx Thr Len - %d\nRx Thr Len - %d\n", dthrctl.b.non_iso_thr_en, dthrctl.b.iso_thr_en, dthrctl.b.rx_thr_en, dthrctl.b.tx_thr_len, dthrctl.b.rx_thr_len); } dwc_otg_enable_device_interrupts(_core_if); { diepmsk_data_t msk = {.d32 = 0 }; msk.b.txfifoundrn = 1; dwc_modify_reg32(&dev_if->dev_global_regs->diepmsk, msk.d32, msk.d32); }}/** * This function enables the Host mode interrupts. * * @param _core_if Programming view of DWC_otg controller */void dwc_otg_enable_host_interrupts(dwc_otg_core_if_t * _core_if){ dwc_otg_core_global_regs_t *global_regs = _core_if->core_global_regs; gintmsk_data_t intr_mask = {.d32 = 0 }; 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 host mode interrupts without disturbing common * interrupts. */ intr_mask.b.sofintr = 1; intr_mask.b.portintr = 1; intr_mask.b.hcintr = 1; dwc_modify_reg32(&global_regs->gintmsk, intr_mask.d32, intr_mask.d32);}/** * This function disables the Host Mode interrupts. * * @param _core_if Programming view of DWC_otg controller */void dwc_otg_disable_host_interrupts(dwc_otg_core_if_t * _core_if){ dwc_otg_core_global_regs_t *global_regs = _core_if->core_global_regs; gintmsk_data_t intr_mask = {.d32 = 0 }; DWC_DEBUGPL(DBG_CILV, "%s()\n", __func__); /* * Disable host mode interrupts without disturbing common * interrupts. */ intr_mask.b.sofintr = 1; intr_mask.b.portintr = 1; intr_mask.b.hcintr = 1; intr_mask.b.ptxfempty = 1; intr_mask.b.nptxfempty = 1; dwc_modify_reg32(&global_regs->gintmsk, intr_mask.d32, 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 _core_if Programming view of DWC_otg controller * */void dwc_otg_core_host_init(dwc_otg_core_if_t * _core_if){ dwc_otg_core_global_regs_t *global_regs = _core_if->core_global_regs; dwc_otg_host_if_t *host_if = _core_if->host_if; dwc_otg_core_params_t *params = _core_if->core_params; hprt0_data_t hprt0 = {.d32 = 0 }; fifosize_data_t nptxfifosize; fifosize_data_t ptxfifosize; int i; hcchar_data_t hcchar; hcfg_data_t hcfg; dwc_otg_hc_regs_t *hc_regs; int num_channels; gotgctl_data_t gotgctl = {.d32 = 0 }; DWC_DEBUGPL(DBG_CILV, "%s(%p)\n", __func__, _core_if); /* Restart the Phy Clock */ dwc_write_reg32(_core_if->pcgcctl, 0); /* Initialize Host Configuration Register */ init_fslspclksel(_core_if); if (_core_if->core_params->speed == DWC_SPEED_PARAM_FULL) { hcfg.d32 = dwc_read_reg32(&host_if->host_global_regs->hcfg); hcfg.b.fslssupp = 1; dwc_write_reg32(&host_if->host_global_regs->hcfg, hcfg.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->host_rx_fifo_size); DWC_DEBUGPL(DBG_CIL, "NP Tx FIFO Size=%d\n", params->host_nperio_tx_fifo_size); DWC_DEBUGPL(DBG_CIL, "P Tx FIFO Size=%d\n", params->host_perio_tx_fifo_size); /* Rx FIFO */ DWC_DEBUGPL(DBG_CIL, "initial grxfsiz=%08x\n", dwc_read_reg32(&global_regs->grxfsiz)); dwc_write_reg32(&global_regs->grxfsiz, params->host_rx_fifo_size); DWC_DEBUGPL(DBG_CIL, "new grxfsiz=%08x\n", dwc_read_reg32(&global_regs->grxfsiz)); /* Non-periodic Tx FIFO */ DWC_DEBUGPL(DBG_CIL, "initial gnptxfsiz=%08x\n", dwc_read_reg32(&global_regs->gnptxfsiz)); nptxfifosize.b.depth = params->host_nperio_tx_fifo_size; nptxfifosize.b.startaddr = params->host_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)); /* Periodic Tx FIFO */ DWC_DEBUGPL(DBG_CIL, "initial hptxfsiz=%08x\n", dwc_read_reg32(&global_regs->hptxfsiz)); ptxfifosize.b.depth = params->host_perio_tx_fifo_size; ptxfifosize.b.startaddr = nptxfifosize.b.startaddr + nptxfifosize.b.depth; dwc_write_reg32(&global_regs->hptxfsiz, ptxfifosize.d32); DWC_DEBUGPL(DBG_CIL, "new hptxfsiz=%08x\n", dwc_read_reg32(&global_regs->hptxfsiz)); } /* Clear Host Set HNP Enable in the OTG Control Register */ gotgctl.b.hstsethnpen = 1; dwc_modify_reg32(&global_regs->gotgctl, gotgctl.d32, 0); /* Make sure the FIFOs are flushed. */ dwc_otg_flush_tx_fifo(_core_if, 0x10 /* all Tx FIFOs */ ); dwc_otg_flush_rx_fifo(_core_if); /* Flush out any leftover queued requests. */ num_channels = _core_if->core_params->host_channels; for (i = 0; i < num_channels; i++) { hc_regs = _core_if->host_if->hc_regs[i]; hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); hcchar.b.chen = 0; hcchar.b.chdis = 1; hcchar.b.epdir = 0; dwc_write_reg32(&hc_regs->hcchar, hcchar.d32); } /* Halt all channels to put them into a known state. */ for (i = 0; i < num_channels; i++) { int count = 0; hc_regs = _core_if->host_if->hc_regs[i]; hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); hcchar.b.chen = 1; hcchar.b.chdis = 1; hcchar.b.epdir = 0; dwc_write_reg32(&hc_regs->hcchar, hcchar.d32); DWC_DEBUGPL(DBG_HCDV, "%s: Halt channel %d\n", __func__, i); do { hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); if (++count > 1000) { DWC_ERROR("%s: Unable to clear halt on channel %d\n", __func__, i); break; } } while (hcchar.b.chen); } /* Turn on the vbus power. */ DWC_PRINT("Init: Port Power? op_state=%d\n", _core_if->op_state); if (_core_if->op_state == A_HOST) { hprt0.d32 = dwc_otg_read_hprt0(_core_if); DWC_PRINT("Init: Power Port (%d)\n", hprt0.b.prtpwr); if (hprt0.b.prtpwr == 0) { hprt0.b.prtpwr = 1; dwc_write_reg32(host_if->hprt0, hprt0.d32); } } dwc_otg_enable_host_interrupts(_core_if);}/** * Prepares a host channel for transferring packets to/from a specific * endpoint. The HCCHARn register is set up with the characteristics specified * in _hc. Host channel interrupts that may need to be serviced while this * transfer is in progress are enabled. * * @param _core_if Programming view of DWC_otg controller * @param _hc Information needed to initialize the host channel */void dwc_otg_hc_init(dwc_otg_core_if_t * _core_if, dwc_hc_t * _hc){ uint32_t intr_enable; hcintmsk_data_t hc_intr_mask; gintmsk_data_t gintmsk = {.d32 = 0 }; hcchar_data_t hcchar; hcsplt_data_t hcsplt; uint8_t hc_num = _hc->hc_num; dwc_otg_host_if_t *host_if = _core_if->host_if; dwc_otg_hc_regs_t *hc_regs = host_if->hc_regs[hc_num]; /* Clear old interrupt conditions for this host channel. */ hc_intr_mask.d32 = 0xFFFFFFFF; hc_intr_mask.b.reserved = 0; dwc_write_reg32(&hc_regs->hcint, hc_intr_mask.d32); /* Enable channel interrupts required for this transfer. */ hc_intr_mask.d32 = 0; hc_intr_mask.b.chhltd = 1; if (_core_if->dma_enable) { hc_intr_mask.b.ahberr = 1; if (_hc->error_state && !_hc->do_split && _hc->ep_type != DWC_OTG_EP_TYPE_ISOC) { hc_intr_mask.b.ack = 1; if (_hc->ep_is_in) { hc_intr_mask.b.datatglerr = 1; if (_hc->ep_type != DWC_OTG_EP_TYPE_INTR) { hc_intr_mask.b.nak = 1; } } } } else { switch (_hc->ep_type) { case DWC_OTG_EP_TYPE_CONTROL: case DWC_OTG_EP_TYPE_BULK: hc_intr_mask.b.xfercompl = 1; hc_intr_mask.b.stall = 1; hc_intr_mask.b.xacterr = 1; hc_intr_mask.b.datatglerr = 1; if (_hc->ep_is_in) { hc_intr_mask.b.bblerr = 1; } else { hc_intr_mask.b.nak = 1; hc_intr_mask.b.nyet = 1; if (_hc->do_ping) { hc_intr_mask.b.ack = 1; } } if (_hc->do_split) { hc_intr_mask.b.nak = 1; if (_hc->complete_split) { hc_intr_mask.b.nyet = 1; } else { hc_intr_mask.b.ack = 1; } } if (_hc->error_state) { hc_intr_mask.b.ack = 1; } break; case DWC_OTG_EP_TYPE_INTR: hc_intr_mask.b.xfercompl = 1; hc_intr_mask.b.nak = 1; hc_intr_mask.b.stall = 1; hc_intr_mask.b.xacterr = 1; hc_intr_mask.b.datatglerr = 1; hc_intr_mask.b.frmovrun = 1; if (_hc->ep_is_in) { hc_intr_mask.b.bblerr = 1; } if (_hc->error_state) { hc_intr_mask.b.ack = 1; } if (_hc->do_split) { if (_hc->complete_split) { hc_intr_mask.b.nyet = 1; } else { hc_intr_mask.b.ack = 1; } } break; case DWC_OTG_EP_TYPE_ISOC: hc_intr_mask.b.xfercompl = 1; hc_intr_mask.b.frmovrun = 1; hc_intr_mask.b.ack = 1; if (_hc->ep_is_in) { hc_intr_mask.b.xacterr = 1; hc_intr_mask.b.bblerr = 1; } break; } } dwc_write_reg32(&hc_regs->hcintmsk, hc_intr_mask.d32); /* Enable the top level host channel interrupt. */ intr_enable = (1 << hc_num); dwc_modify_reg32(&host_if->host_global_regs->haintmsk, 0, intr_enable); /* Make sure host channel interrupts are enabled. */ gintmsk.b.hcintr = 1; dwc_modify_reg32(&_core_if->core_global_regs->gintmsk, 0, gintmsk.d32); /* * Program the HCCHARn register with the endpoint characteristics for * the current transfer. */ hcchar.d32 = 0; hcchar.b.devaddr = _hc->dev_addr; hcchar.b.epnum = _hc->ep_num; hcchar.b.epdir = _hc->ep_is_in;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -