diff options
| author | sakumisu <[email protected]> | 2022-08-14 12:41:44 +0800 |
|---|---|---|
| committer | sakumisu <[email protected]> | 2022-08-14 12:41:50 +0800 |
| commit | 18afd80c7fe90babb43f95ac2ca9bb1f0514fbb9 (patch) | |
| tree | 0798f555320245d369ff43d53719cfc7771f52ba | |
| parent | 2a05537705feb77069da1ec81aa031d3fb83e3f3 (diff) | |
add dcache support for hpm hcd
| -rw-r--r-- | port/hpm/usb_hc_hpm.c | 123 |
1 files changed, 76 insertions, 47 deletions
diff --git a/port/hpm/usb_hc_hpm.c b/port/hpm/usb_hc_hpm.c index a3e53620..e483777e 100644 --- a/port/hpm/usb_hc_hpm.c +++ b/port/hpm/usb_hc_hpm.c @@ -1,5 +1,8 @@ #include "usbh_core.h" #include "hpm_usb_host.h" +#include "hpm_common.h" +#include "hpm_soc.h" +#include "hpm_l1c_drv.h" #include "board.h" #define HCD_MAX_ENDPOINT 16 @@ -7,6 +10,7 @@ struct hpm_ehci_pipe { uint8_t ep_addr; uint8_t dev_addr; + uint8_t *buffer; /* for dcache invalidate */ volatile int result; /* The result of the transfer */ volatile uint32_t xfrd; /* Bytes transferred (at end of transfer) */ volatile bool waiter; /* True: Thread is waiting for a channel event */ @@ -65,6 +69,7 @@ static const hcd_controller_t _hcd_controller[] = { * Variable Definitions *---------------------------------------------------------------------*/ ATTR_PLACE_AT_NONCACHEABLE static usb_host_handle_t usb_host_handle; +ATTR_PLACE_AT_NONCACHEABLE static bool hcd_int_sta; ATTR_PLACE_AT_NONCACHEABLE_WITH_ALIGNMENT(USB_SOC_DCD_DATA_RAM_ADDRESS_ALIGNMENT) static hcd_data_t _hcd_data; @@ -255,7 +260,11 @@ static void hpm_ehci_pipe_wakeup(struct hpm_ehci_pipe *chan) if (chan->result < 0) { nbytes = chan->result; } - +#ifdef CONFIG_USB_DCACHE_ENABLE + if (((chan->ep_addr & 0x80) == 0x80) && (nbytes > 0)) { + l1c_dc_invalidate((uint32_t)chan->buffer, nbytes); + } +#endif callback(arg, nbytes); } #endif @@ -433,7 +442,9 @@ int usbh_control_transfer(usbh_epinfo_t ep, struct usb_setup_packet *setup, uint if (ret < 0) { goto error_out; } - +#ifdef CONFIG_USB_DCACHE_ENABLE + l1c_dc_writeback((uint32_t)setup, 8); +#endif usb_host_setup_send(&usb_host_handle, chan->dev_addr, (uint8_t *)setup); ret = hpm_ehci_pipe_wait(chan, CONFIG_USBHOST_CONTROL_TRANSFER_TIMEOUT); if (ret < 0) { @@ -449,7 +460,9 @@ int usbh_control_transfer(usbh_epinfo_t ep, struct usb_setup_packet *setup, uint if (ret < 0) { goto error_out; } - +#ifdef CONFIG_USB_DCACHE_ENABLE + l1c_dc_invalidate((uint32_t)buffer, setup->wLength); +#endif chan->waiter = true; chan->result = -EBUSY; usb_host_edpt_xfer(&usb_host_handle, chan->dev_addr, 0x00, NULL, 0); @@ -460,6 +473,7 @@ int usbh_control_transfer(usbh_epinfo_t ep, struct usb_setup_packet *setup, uint } else { chan->waiter = true; chan->result = -EBUSY; + l1c_dc_writeback((uint32_t)buffer, setup->wLength); usb_host_edpt_xfer(&usb_host_handle, chan->dev_addr, 0x00, buffer, setup->wLength); ret = hpm_ehci_pipe_wait(chan, CONFIG_USBHOST_CONTROL_TRANSFER_TIMEOUT); if (ret < 0) { @@ -499,6 +513,10 @@ int usbh_ep_bulk_transfer(usbh_epinfo_t ep, uint8_t *buffer, uint32_t buflen, ui chan = (struct hpm_ehci_pipe *)ep; + if (buffer && (((uint32_t)buffer) & 0x1f)) { + return -EINVAL; + } + ret = usb_osal_mutex_take(chan->exclsem); if (ret < 0) { return ret; @@ -508,12 +526,22 @@ int usbh_ep_bulk_transfer(usbh_epinfo_t ep, uint8_t *buffer, uint32_t buflen, ui if (ret < 0) { goto error_out; } - +#ifdef CONFIG_USB_DCACHE_ENABLE + if ((chan->ep_addr & 0x80) == 0x00) { + l1c_dc_writeback((uint32_t)buffer, buflen); + } +#endif + chan->buffer = buffer; usb_host_edpt_xfer(&usb_host_handle, chan->dev_addr, chan->ep_addr, buffer, buflen); ret = hpm_ehci_pipe_wait(chan, timeout); if (ret < 0) { goto error_out; } +#ifdef CONFIG_USB_DCACHE_ENABLE + if ((chan->ep_addr & 0x80) == 0x80) { + l1c_dc_invalidate((uint32_t)buffer, buflen); + } +#endif usb_osal_mutex_give(chan->exclsem); return ret; error_out: @@ -524,32 +552,7 @@ error_out: int usbh_ep_intr_transfer(usbh_epinfo_t ep, uint8_t *buffer, uint32_t buflen, uint32_t timeout) { - struct hpm_ehci_pipe *chan; - int ret; - - chan = (struct hpm_ehci_pipe *)ep; - - ret = usb_osal_mutex_take(chan->exclsem); - if (ret < 0) { - return ret; - } - - ret = hpm_ehci_pipe_waitsetup(chan); - if (ret < 0) { - goto error_out; - } - - usb_host_edpt_xfer(&usb_host_handle, chan->dev_addr, chan->ep_addr, buffer, buflen); - ret = hpm_ehci_pipe_wait(chan, timeout); - if (ret < 0) { - goto error_out; - } - usb_osal_mutex_give(chan->exclsem); - return ret; -error_out: - chan->waiter = false; - usb_osal_mutex_give(chan->exclsem); - return ret; + return usbh_ep_bulk_transfer(ep, buffer, buflen, timeout); } int usbh_ep_bulk_async_transfer(usbh_epinfo_t ep, uint8_t *buffer, uint32_t buflen, usbh_asynch_callback_t callback, void *arg) @@ -559,6 +562,10 @@ int usbh_ep_bulk_async_transfer(usbh_epinfo_t ep, uint8_t *buffer, uint32_t bufl chan = (struct hpm_ehci_pipe *)ep; + if (buffer && (((uint32_t)buffer) & 0x1f)) { + return -EINVAL; + } + ret = usb_osal_mutex_take(chan->exclsem); if (ret < 0) { return ret; @@ -568,7 +575,11 @@ int usbh_ep_bulk_async_transfer(usbh_epinfo_t ep, uint8_t *buffer, uint32_t bufl if (ret < 0) { goto error_out; } - +#ifdef CONFIG_USB_DCACHE_ENABLE + if ((chan->ep_addr & 0x80) == 0x00) { + l1c_dc_writeback((uint32_t)buffer, buflen); + } +#endif usb_host_edpt_xfer(&usb_host_handle, chan->dev_addr, chan->ep_addr, buffer, buflen); error_out: @@ -578,30 +589,48 @@ error_out: int usbh_ep_intr_async_transfer(usbh_epinfo_t ep, uint8_t *buffer, uint32_t buflen, usbh_asynch_callback_t callback, void *arg) { + return usbh_ep_bulk_async_transfer(ep, buffer, buflen, callback, arg); +} + +int usb_ep_cancel(usbh_epinfo_t ep) +{ struct hpm_ehci_pipe *chan; int ret; + size_t flags; +#ifdef CONFIG_USBHOST_ASYNCH + usbh_asynch_callback_t callback; + void *arg; +#endif chan = (struct hpm_ehci_pipe *)ep; - ret = usb_osal_mutex_take(chan->exclsem); - if (ret < 0) { - return ret; - } - - ret = hpm_ehci_pipe_asynchsetup(chan, callback, arg); - if (ret < 0) { - goto error_out; - } + flags = usb_osal_enter_critical_section(); - usb_host_edpt_xfer(&usb_host_handle, chan->dev_addr, chan->ep_addr, buffer, buflen); + chan->result = -ESHUTDOWN; +#ifdef CONFIG_USBHOST_ASYNCH + /* Extract the callback information */ + callback = chan->callback; + arg = chan->arg; + chan->callback = NULL; + chan->arg = NULL; + chan->xfrd = 0; +#endif + usb_osal_leave_critical_section(flags); -error_out: - usb_osal_mutex_give(chan->exclsem); - return ret; -} + /* Is there a thread waiting for this transfer to complete? */ -int usb_ep_cancel(usbh_epinfo_t ep) -{ + if (chan->waiter) { + /* Wake'em up! */ + chan->waiter = false; + usb_osal_sem_give(chan->waitsem); + } +#ifdef CONFIG_USBHOST_ASYNCH + /* No.. is an asynchronous callback expected when the transfer completes? */ + else if (callback) { + /* Then perform the callback */ + callback(arg, -ESHUTDOWN); + } +#endif return 0; } |
