From f68a86ea89c6c9bbc3bc662b0f593dd7c850a450 Mon Sep 17 00:00:00 2001 From: sakumisu <1203593632@qq.com> Date: Sun, 24 Dec 2023 23:37:47 +0800 Subject: [PATCH] add usbh_deinitialize api --- class/hub/usbh_hub.c | 32 +++++++++++++++++++++++++ class/hub/usbh_hub.h | 3 +++ common/usb_hc.h | 7 ++++++ common/usb_osal.h | 1 + core/usbh_core.c | 5 ++++ core/usbh_core.h | 1 + osal/usb_osal_freertos.c | 5 ++++ osal/usb_osal_rtthread.c | 5 ++++ osal/usb_osal_yoc.c | 5 ++++ port/dwc2/usb_hc_dwc2.c | 51 ++++++++++++++++++++++++++++++++++++++++ port/ehci/usb_hc_ehci.c | 48 +++++++++++++++++++++++++++++++++++++ port/musb/usb_hc_musb.c | 16 +++++++++++++ 12 files changed, 179 insertions(+) diff --git a/class/hub/usbh_hub.c b/class/hub/usbh_hub.c index 5d5498aa..ef101fe8 100644 --- a/class/hub/usbh_hub.c +++ b/class/hub/usbh_hub.c @@ -647,6 +647,8 @@ static void usbh_hub_thread(void *argument) static void usbh_roothub_register(void) { + usb_slist_init(&hub_class_head); + memset(&roothub, 0, sizeof(struct usbh_hub)); roothub.connected = true; @@ -680,6 +682,36 @@ int usbh_hub_initialize(void) } return 0; } + +int usbh_hub_deinitialize(void) +{ + usb_slist_t *i; + struct usbh_hubport *hport; + size_t flags; + + flags = usb_osal_enter_critical_section(); + + usb_slist_for_each(i, &hub_class_head) + { + struct usbh_hub *hub = usb_slist_entry(i, struct usbh_hub, list); + + for (uint8_t port = 0; port < hub->hub_desc.bNbrPorts; port++) { + hport = &hub->child[port]; + + usbh_hubport_release(hport); + } + } + + usb_hc_deinit(); + + usb_osal_leave_critical_section(flags); + + usb_osal_mq_delete(hub_mq); + usb_osal_thread_delete(hub_thread); + + return 0; +} + #if CONFIG_USBHOST_MAX_EXTHUBS > 0 const struct usbh_class_driver hub_class_driver = { .driver_name = "hub", diff --git a/class/hub/usbh_hub.h b/class/hub/usbh_hub.h index d44f6bc9..007bf40e 100644 --- a/class/hub/usbh_hub.h +++ b/class/hub/usbh_hub.h @@ -23,7 +23,10 @@ int usbh_hub_set_feature(struct usbh_hub *hub, uint8_t port, uint8_t feature); int usbh_hub_clear_feature(struct usbh_hub *hub, uint8_t port, uint8_t feature); void usbh_roothub_thread_wakeup(uint8_t port); + int usbh_hub_initialize(void); +int usbh_hub_deinitialize(void); + #ifdef __cplusplus } #endif diff --git a/common/usb_hc.h b/common/usb_hc.h index c839bd84..ae50352c 100644 --- a/common/usb_hc.h +++ b/common/usb_hc.h @@ -61,6 +61,13 @@ struct usbh_urb { */ int usb_hc_init(void); +/** + * @brief usb host controller hardware deinit. + * + * @return On success will return 0, and others indicate fail. + */ +int usb_hc_deinit(void); + /** * @brief Get frame number. * diff --git a/common/usb_osal.h b/common/usb_osal.h index bf68acaa..0ae658f8 100644 --- a/common/usb_osal.h +++ b/common/usb_osal.h @@ -35,6 +35,7 @@ int usb_osal_mutex_take(usb_osal_mutex_t mutex); int usb_osal_mutex_give(usb_osal_mutex_t mutex); usb_osal_mq_t usb_osal_mq_create(uint32_t max_msgs); +void usb_osal_mq_delete(usb_osal_mq_t mq); int usb_osal_mq_send(usb_osal_mq_t mq, uintptr_t addr); int usb_osal_mq_recv(usb_osal_mq_t mq, uintptr_t *addr, uint32_t timeout); diff --git a/core/usbh_core.c b/core/usbh_core.c index 3492bc29..e7918a83 100644 --- a/core/usbh_core.c +++ b/core/usbh_core.c @@ -666,6 +666,11 @@ int usbh_initialize(void) return 0; } +int usbh_deinitialize(void) +{ + return usbh_hub_deinitialize(); +} + int usbh_control_transfer(struct usbh_hubport *hport, struct usb_setup_packet *setup, uint8_t *buffer) { struct usbh_urb *urb; diff --git a/core/usbh_core.h b/core/usbh_core.h index c56953b9..7cbcafa6 100644 --- a/core/usbh_core.h +++ b/core/usbh_core.h @@ -226,6 +226,7 @@ int usbh_get_string_desc(struct usbh_hubport *hport, uint8_t index, uint8_t *out int usbh_set_interface(struct usbh_hubport *hport, uint8_t intf, uint8_t altsetting); int usbh_initialize(void); +int usbh_deinitialize(void); void *usbh_find_class_instance(const char *devname); int lsusb(int argc, char **argv); diff --git a/osal/usb_osal_freertos.c b/osal/usb_osal_freertos.c index 3cf00dfd..69c210a5 100644 --- a/osal/usb_osal_freertos.c +++ b/osal/usb_osal_freertos.c @@ -89,6 +89,11 @@ usb_osal_mq_t usb_osal_mq_create(uint32_t max_msgs) return (usb_osal_mq_t)xQueueCreate(max_msgs, sizeof(uintptr_t)); } +void usb_osal_mq_delete(usb_osal_mq_t mq) +{ + vQueueDelete((QueueHandle_t)mq); +} + int usb_osal_mq_send(usb_osal_mq_t mq, uintptr_t addr) { BaseType_t xHigherPriorityTaskWoken = pdFALSE; diff --git a/osal/usb_osal_rtthread.c b/osal/usb_osal_rtthread.c index bab038e1..890f048c 100644 --- a/osal/usb_osal_rtthread.c +++ b/osal/usb_osal_rtthread.c @@ -91,6 +91,11 @@ usb_osal_mq_t usb_osal_mq_create(uint32_t max_msgs) return (usb_osal_mq_t)rt_mq_create("usbh_mq", sizeof(uintptr_t), max_msgs, RT_IPC_FLAG_FIFO); } +void usb_osal_mq_delete(usb_osal_mq_t mq) +{ + rt_mq_delete((rt_mq_t)mq); +} + int usb_osal_mq_send(usb_osal_mq_t mq, uintptr_t addr) { return rt_mq_send((rt_mq_t)mq, &addr, sizeof(uintptr_t)); diff --git a/osal/usb_osal_yoc.c b/osal/usb_osal_yoc.c index e87cb30c..7189a3b2 100644 --- a/osal/usb_osal_yoc.c +++ b/osal/usb_osal_yoc.c @@ -89,6 +89,11 @@ usb_osal_mq_t usb_osal_mq_create(uint32_t max_msgs) return (usb_osal_mq_t)queue; } +void usb_osal_mq_delete(usb_osal_mq_t mq) +{ + aos_queue_free((aos_queue_t)mq); +} + int usb_osal_mq_send(usb_osal_mq_t mq, uintptr_t addr) { return aos_queue_send((aos_queue_t *)&mq, &addr, sizeof(uintptr_t)); diff --git a/port/dwc2/usb_hc_dwc2.c b/port/dwc2/usb_hc_dwc2.c index 791a20d2..8fa9ce15 100644 --- a/port/dwc2/usb_hc_dwc2.c +++ b/port/dwc2/usb_hc_dwc2.c @@ -525,6 +525,57 @@ int usb_hc_init(void) return 0; } +int usb_hc_deinit(void) +{ + volatile uint32_t count = 0U; + uint32_t value; + + USB_OTG_GLB->GAHBCFG &= ~USB_OTG_GAHBCFG_GINT; + + dwc2_flush_txfifo(0x10U); + dwc2_flush_rxfifo(); + + /* Flush out any leftover queued requests. */ + for (uint32_t i = 0U; i <= 15U; i++) { + value = USB_OTG_HC(i)->HCCHAR; + value |= USB_OTG_HCCHAR_CHDIS; + value &= ~USB_OTG_HCCHAR_CHENA; + value &= ~USB_OTG_HCCHAR_EPDIR; + USB_OTG_HC(i)->HCCHAR = value; + } + + /* Halt all channels to put them into a known state. */ + for (uint32_t i = 0U; i <= 15U; i++) { + value = USB_OTG_HC(i)->HCCHAR; + value |= USB_OTG_HCCHAR_CHDIS; + value |= USB_OTG_HCCHAR_CHENA; + value &= ~USB_OTG_HCCHAR_EPDIR; + USB_OTG_HC(i)->HCCHAR = value; + + do { + if (++count > 1000U) { + return -USB_ERR_TIMEOUT; + } + } while ((USB_OTG_HC(i)->HCCHAR & USB_OTG_HCCHAR_CHENA) == USB_OTG_HCCHAR_CHENA); + } + + /* Disable all interrupts. */ + USB_OTG_GLB->GINTMSK = 0U; + + /* Clear any pending Host interrupts */ + USB_OTG_HOST->HAINT = 0xFFFFFFFFU; + USB_OTG_GLB->GINTSTS = 0xFFFFFFFFU; + + dwc2_drivebus(0); + usb_osal_msleep(200); + + for (uint8_t chidx = 0; chidx < CONFIG_USBHOST_PIPE_NUM; chidx++) { + usb_osal_sem_delete(g_dwc2_hcd.chan_pool[chidx].waitsem); + } + + return 0; +} + uint16_t usbh_get_frame_number(void) { return (USB_OTG_HOST->HFNUM & USB_OTG_HFNUM_FRNUM); diff --git a/port/ehci/usb_hc_ehci.c b/port/ehci/usb_hc_ehci.c index 475e3b33..1dc1ec01 100644 --- a/port/ehci/usb_hc_ehci.c +++ b/port/ehci/usb_hc_ehci.c @@ -906,6 +906,51 @@ int usb_hc_init(void) return 0; } +int usb_hc_deinit(void) +{ + struct ehci_qh_hw *qh; + + volatile uint32_t timeout = 0; + uint32_t regval; + + EHCI_HCOR->usbintr = 0; + + regval = EHCI_HCOR->usbcmd; + regval &= ~EHCI_USBCMD_ASEN; + regval &= ~EHCI_USBCMD_PSEN; + regval &= ~EHCI_USBCMD_RUN; + EHCI_HCOR->usbcmd = regval; + + while ((EHCI_HCOR->usbsts & (EHCI_USBSTS_PSS | EHCI_USBSTS_ASS))) { + usb_osal_msleep(1); + timeout++; + if (timeout > 100) { + return -USB_ERR_TIMEOUT; + } + } + +#ifdef CONFIG_USB_EHCI_PORT_POWER + for (uint8_t port = 0; port < CONFIG_USBHOST_MAX_RHPORTS; port++) { + regval = EHCI_HCOR->portsc[port]; + regval &= ~EHCI_PORTSC_PP; + EHCI_HCOR->portsc[port] = regval; + } +#endif + +#ifdef CONFIG_USB_EHCI_CONFIGFLAG + EHCI_HCOR->configflag = 0; +#endif + + EHCI_HCOR->usbsts = EHCI_HCOR->usbsts; + + for (uint8_t index = 0; index < CONFIG_USB_EHCI_QH_NUM; index++) { + qh = &ehci_qh_pool[index]; + usb_osal_sem_delete(qh->waitsem); + } + + return 0; +} + uint16_t usbh_get_frame_number(void) { return (((EHCI_HCOR->frindex & EHCI_FRINDEX_MASK) >> 3) & 0x3ff); @@ -1199,6 +1244,9 @@ int usbh_kill_urb(struct usbh_urb *urb) } else { #ifdef CONFIG_USB_EHCI_ISO ehci_remove_itd_urb(urb); + EHCI_HCOR->usbcmd |= (EHCI_USBCMD_PSEN | EHCI_USBCMD_ASEN); + usb_osal_leave_critical_section(flags); + return 0; #endif } diff --git a/port/musb/usb_hc_musb.c b/port/musb/usb_hc_musb.c index 9dfca355..facde085 100644 --- a/port/musb/usb_hc_musb.c +++ b/port/musb/usb_hc_musb.c @@ -470,6 +470,22 @@ int usb_hc_init(void) return 0; } +int usb_hc_deinit(void) +{ + HWREGB(USB_BASE + MUSB_IE_OFFSET) = 0; + HWREGH(USB_BASE + MUSB_TXIE_OFFSET) = 0; + HWREGH(USB_BASE + MUSB_RXIE_OFFSET) = 0; + + HWREGB(USB_BASE + MUSB_POWER_OFFSET) &= ~USB_POWER_HSENAB; + HWREGB(USB_BASE + MUSB_DEVCTL_OFFSET) &= ~USB_DEVCTL_SESSION; + + for (uint8_t i = 0; i < CONFIG_USBHOST_PIPE_NUM; i++) { + usb_osal_sem_delete(g_musb_hcd.pipe_pool[i].waitsem); + } + + return 0; +} + int usbh_roothub_control(struct usb_setup_packet *setup, uint8_t *buf) { uint8_t nports;