/** * @brief HCD_ResetPort * Issues the reset command to device * @param pdev : Selected device * @retval Status */ uint32_t HCD_ResetPort(USB_OTG_CORE_HANDLE *pdev) { /* Before starting to drive a USB reset, the application waits for the OTG interrupt triggered by the debounce done bit (DBCDNE bit in OTG_FS_GOTGINT), which indicates that the bus is stable again after the electrical debounce caused by the attachment of a pull-up resistor on DP (FS) or DM (LS). */ USB_OTG_ResetPort(pdev); return 0; }
/** * This function will control the roothub of susb host controller. * * @param port the port to be reset. * * @return the error code, RT_EOK on successfully. */ static rt_err_t susb_hub_control(rt_uint16_t port, rt_uint8_t cmd, void* args) { RT_ASSERT(port == 1); switch(cmd) { case RH_GET_PORT_STATUS: *(rt_uint32_t*)args = root_hub.port_status[port - 1]; break; case RH_SET_PORT_STATUS: break; case RH_CLEAR_PORT_FEATURE: switch((rt_uint32_t)args & 0xFF) { case PORT_FEAT_C_RESET: root_hub.port_status[port - 1] &= ~PORT_PRSC; ignore_disconnect = RT_FALSE; break; case PORT_FEAT_C_CONNECTION: root_hub.port_status[port - 1] &= ~PORT_CCSC; break; case PORT_FEAT_C_ENABLE: root_hub.port_status[port - 1] &= ~PORT_PESC; break; default: break; } break; case RH_SET_PORT_FEATURE: switch((rt_uint32_t)args & 0xFF) { case PORT_FEAT_POWER: root_hub.port_status[port - 1] |= PORT_PPS; break; case PORT_FEAT_RESET: ignore_disconnect = RT_TRUE; root_hub.port_status[port - 1] |= PORT_PRS; USB_OTG_ResetPort(&USB_OTG_Core); root_hub.port_status[port - 1] &= ~PORT_PRS; break; case PORT_FEAT_ENABLE: root_hub.port_status[port - 1] |= PORT_PES; break; } break; default: break; } return RT_EOK; }
/** * @brief USB_OTG_HandleOTG_ISR * handles the OTG Interrupts * @param None * @retval : status */ static uint32_t USB_OTG_HandleOTG_ISR(USB_OTG_CORE_HANDLE *pdev) { USB_OTG_GOTGINT_TypeDef gotgint; USB_OTG_GOTGCTL_TypeDef gotgctl; gotgint.d32 = 0; gotgctl.d32 = 0; gotgint.d32 = USB_OTG_READ_REG32(&pdev->regs.GREGS->GOTGINT); gotgctl.d32 = USB_OTG_READ_REG32(&pdev->regs.GREGS->GOTGCTL); if (gotgint.b.sesenddet) { gotgctl.d32 = USB_OTG_READ_REG32(&pdev->regs.GREGS->GOTGCTL); if (USB_OTG_IsDeviceMode(pdev)) { } else if (USB_OTG_IsHostMode(pdev)) { } } /* ----> SRP SUCCESS or FAILURE INTERRUPT <---- */ if (gotgint.b.sesreqsucstschng) { gotgctl.d32 = USB_OTG_READ_REG32(&pdev->regs.GREGS->GOTGCTL); if (gotgctl.b.sesreqscs) /* Session request success */ { if (USB_OTG_IsDeviceMode(pdev)) { } /* Clear Session Request */ gotgctl.d32 = 0; gotgctl.b.sesreq = 1; USB_OTG_MODIFY_REG32(&pdev->regs.GREGS->GOTGCTL, gotgctl.d32, 0); } else /* Session request failure */ { if (USB_OTG_IsDeviceMode(pdev)) { } } } /* ----> HNP SUCCESS or FAILURE INTERRUPT <---- */ if (gotgint.b.hstnegsucstschng) { gotgctl.d32 = USB_OTG_READ_REG32(&pdev->regs.GREGS->GOTGCTL); if (gotgctl.b.hstnegscs) /* Host negotiation success */ { if (USB_OTG_IsHostMode(pdev)) /* The core AUTOMATICALLY sets the Host mode */ { } } else /* Host negotiation failure */ { } gotgint.b.hstnegsucstschng = 1; /* Ack "Host Negotiation Success Status Change" interrupt. */ } /* ----> HOST NEGOTIATION DETECTED INTERRUPT <---- */ if (gotgint.b.hstnegdet) { if (USB_OTG_IsDeviceMode(pdev)) /* The core AUTOMATICALLY sets the Host mode */ { } else { } } if (gotgint.b.adevtoutchng) {} if (gotgint.b.debdone) { USB_OTG_ResetPort(pdev); } /* Clear OTG INT */ USB_OTG_WRITE_REG32(&pdev->regs.GREGS->GOTGINT, gotgint.d32); return 1; }
/** * @brief USB_OTG_USBH_handle_port_ISR * This function determines which interrupt conditions have occurred * @param pdev: Selected device * @retval status */ static uint32_t USB_OTG_USBH_handle_port_ISR(USB_OTG_CORE_HANDLE *pdev) { USB_OTG_HPRT0_TypeDef hprt0; USB_OTG_HPRT0_TypeDef hprt0_dup; USB_OTG_HCFG_TypeDef hcfg; uint32_t do_reset = 0; uint32_t retval = 0; hcfg.d32 = 0; hprt0.d32 = 0; hprt0_dup.d32 = 0; hprt0.d32 = USB_OTG_READ_REG32(pdev->regs.HPRT0); hprt0_dup.d32 = USB_OTG_READ_REG32(pdev->regs.HPRT0); /* Clear the interrupt bits in GINTSTS */ hprt0_dup.b.prtena = 0; hprt0_dup.b.prtconndet = 0; hprt0_dup.b.prtenchng = 0; hprt0_dup.b.prtovrcurrchng = 0; /* Port Connect Detected */ if (hprt0.b.prtconndet) { // pdev->host.port_cb->Connect(pdev); hprt0_dup.b.prtconndet = 1; do_reset = 1; retval |= 1; } /* Port Enable Changed */ if (hprt0.b.prtenchng) { hprt0_dup.b.prtenchng = 1; if (hprt0.b.prtena == 1) { pdev->host.ConnSts = 1; if ((hprt0.b.prtspd == HPRT0_PRTSPD_LOW_SPEED) || (hprt0.b.prtspd == HPRT0_PRTSPD_FULL_SPEED)) { hcfg.d32 = USB_OTG_READ_REG32(&pdev->regs.HREGS->HCFG); if (hprt0.b.prtspd == HPRT0_PRTSPD_LOW_SPEED) { USB_OTG_WRITE_REG32(&pdev->regs.HREGS->HFIR, 6000); if (hcfg.b.fslspclksel != HCFG_6_MHZ) { if (pdev->cfg.coreID == USB_OTG_FS_CORE_ID) { USB_OTG_InitFSLSPClkSel(pdev, HCFG_6_MHZ); } do_reset = 1; } } else { USB_OTG_WRITE_REG32(&pdev->regs.HREGS->HFIR, 48000); if (hcfg.b.fslspclksel != HCFG_48_MHZ) { USB_OTG_InitFSLSPClkSel(pdev, HCFG_48_MHZ); do_reset = 1; } } } else { do_reset = 1; } } } /* Overcurrent Change Interrupt */ if (hprt0.b.prtovrcurrchng) { hprt0_dup.b.prtovrcurrchng = 1; retval |= 1; } if (do_reset) { USB_OTG_ResetPort(pdev); } /* Clear Port Interrupts */ USB_OTG_WRITE_REG32(pdev->regs.HPRT0, hprt0_dup.d32); return retval; }
//-------------------------------------------------------------- USB_OTG_STS USB_OTG_CoreInitHost(USB_OTG_CORE_HANDLE *pdev) { USB_OTG_STS status = USB_OTG_OK; USB_OTG_FSIZ_TypeDef nptxfifosize; USB_OTG_FSIZ_TypeDef ptxfifosize; USB_OTG_HCFG_TypeDef hcfg; uint32_t i = 0; nptxfifosize.d32 = 0; ptxfifosize.d32 = 0; hcfg.d32 = 0; /* configure charge pump IO */ USB_OTG_BSP_ConfigVBUS(pdev); /* Restart the Phy Clock */ USB_OTG_WRITE_REG32(pdev->regs.PCGCCTL, 0); /* Initialize Host Configuration Register */ if (pdev->cfg.phy_itface == USB_OTG_ULPI_PHY) { USB_OTG_InitFSLSPClkSel(pdev , HCFG_30_60_MHZ); } else { USB_OTG_InitFSLSPClkSel(pdev , HCFG_48_MHZ); } USB_OTG_ResetPort(pdev); hcfg.d32 = USB_OTG_READ_REG32(&pdev->regs.HREGS->HCFG); hcfg.b.fslssupp = 0; USB_OTG_WRITE_REG32(&pdev->regs.HREGS->HCFG, hcfg.d32); /* Configure data FIFO sizes */ /* Rx FIFO */ if (pdev->cfg.coreID == USB_OTG_HS_CORE_ID) { /* set Rx FIFO size */ USB_OTG_WRITE_REG32(&pdev->regs.GREGS->GRXFSIZ, RX_FIFO_HS_SIZE); nptxfifosize.b.startaddr = RX_FIFO_HS_SIZE; nptxfifosize.b.depth = TXH_NP_HS_FIFOSIZ; USB_OTG_WRITE_REG32(&pdev->regs.GREGS->DIEPTXF0_HNPTXFSIZ, nptxfifosize.d32); ptxfifosize.b.startaddr = RX_FIFO_HS_SIZE + TXH_NP_HS_FIFOSIZ; ptxfifosize.b.depth = TXH_P_HS_FIFOSIZ; USB_OTG_WRITE_REG32(&pdev->regs.GREGS->HPTXFSIZ, ptxfifosize.d32); } /* Make sure the FIFOs are flushed. */ USB_OTG_FlushTxFifo(pdev, 0x10 ); /* all Tx FIFOs */ USB_OTG_FlushRxFifo(pdev); /* Clear all pending HC Interrupts */ for (i = 0; i < pdev->cfg.host_channels; i++) { USB_OTG_WRITE_REG32( &pdev->regs.HC_REGS[i]->HCINT, 0xFFFFFFFF ); USB_OTG_WRITE_REG32( &pdev->regs.HC_REGS[i]->HCINTMSK, 0 ); } USB_OTG_DriveVbus(pdev, 1); USB_OTG_EnableHostInt(pdev); return status; }
// This function determines which interrupt conditions have occurred static void USB_OTG_USBH_handle_port_ISR (USB_OTG_CORE_HANDLE *pdev) { USB_OTG_HPRT0_TypeDef hprt0; USB_OTG_HPRT0_TypeDef hprt0_dup; USB_OTG_HCFG_TypeDef hcfg; uint32_t do_reset = 0; hcfg.d32 = 0; hprt0.d32 = 0; hprt0_dup.d32 = 0; hprt0.d32 = USB_OTG_READ_REG32(pdev->regs.HPRT0); hprt0_dup.d32 = USB_OTG_READ_REG32(pdev->regs.HPRT0); /* Clear the interrupt bits in GINTSTS */ hprt0_dup.b.prtena = 0; hprt0_dup.b.prtconndet = 0; hprt0_dup.b.prtenchng = 0; hprt0_dup.b.prtovrcurrchng = 0; /* Port Connect Detected */ if (hprt0.b.prtconndet) { hprt0_dup.b.prtconndet = 1; USBH_HCD_INT_fops->DevConnected(pdev); } /* Port Enable Changed */ if (hprt0.b.prtenchng) { hprt0_dup.b.prtenchng = 1; if (hprt0.b.prtena == 1) { USBH_HCD_INT_fops->DevConnected(pdev); if ((hprt0.b.prtspd == HPRT0_PRTSPD_LOW_SPEED) || (hprt0.b.prtspd == HPRT0_PRTSPD_FULL_SPEED)) { hcfg.d32 = USB_OTG_READ_REG32(&pdev->regs.HREGS->HCFG); if (hprt0.b.prtspd == HPRT0_PRTSPD_LOW_SPEED) { USB_OTG_WRITE_REG32(&pdev->regs.HREGS->HFIR, 6000 ); if (hcfg.b.fslspclksel != HCFG_6_MHZ) { if(pdev->cfg.phy_itface == USB_OTG_EMBEDDED_PHY) { USB_OTG_InitFSLSPClkSel(pdev ,HCFG_6_MHZ ); } do_reset = 1; } } else { USB_OTG_WRITE_REG32(&pdev->regs.HREGS->HFIR, 48000 ); if (hcfg.b.fslspclksel != HCFG_48_MHZ) { USB_OTG_InitFSLSPClkSel(pdev ,HCFG_48_MHZ ); do_reset = 1; } } } else { do_reset = 1; } } } /* Overcurrent Change Interrupt */ if (hprt0.b.prtovrcurrchng) { hprt0_dup.b.prtovrcurrchng = 1; } if (do_reset) { USB_OTG_ResetPort(pdev); } /* Clear Port Interrupts */ USB_OTG_WRITE_REG32(pdev->regs.HPRT0, hprt0_dup.d32); }