Ver Fonte

add usbh_deinitialize api

sakumisu há 2 anos atrás
pai
commit
f68a86ea89

+ 32 - 0
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",

+ 3 - 0
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

+ 7 - 0
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.
  *

+ 1 - 0
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);
 

+ 5 - 0
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;

+ 1 - 0
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);

+ 5 - 0
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;

+ 5 - 0
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));

+ 5 - 0
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));

+ 51 - 0
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);

+ 48 - 0
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
     }
 

+ 16 - 0
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;