summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsakumisu <[email protected]>2023-12-24 23:37:47 +0800
committersakumisu <[email protected]>2023-12-24 23:37:47 +0800
commitf68a86ea89c6c9bbc3bc662b0f593dd7c850a450 (patch)
tree98196016f4128e3e5f76f53cfbe9c1e2a2422267
parent8a831cdaa5a547c3e92a73f4b772c32407b21161 (diff)
add usbh_deinitialize api
-rw-r--r--class/hub/usbh_hub.c32
-rw-r--r--class/hub/usbh_hub.h3
-rw-r--r--common/usb_hc.h7
-rw-r--r--common/usb_osal.h1
-rw-r--r--core/usbh_core.c5
-rw-r--r--core/usbh_core.h1
-rw-r--r--osal/usb_osal_freertos.c5
-rw-r--r--osal/usb_osal_rtthread.c5
-rw-r--r--osal/usb_osal_yoc.c5
-rw-r--r--port/dwc2/usb_hc_dwc2.c51
-rw-r--r--port/ehci/usb_hc_ehci.c48
-rw-r--r--port/musb/usb_hc_musb.c16
12 files changed, 179 insertions, 0 deletions
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
@@ -62,6 +62,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.
*
* @return 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;