summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsakumisu <[email protected]>2022-08-14 12:41:44 +0800
committersakumisu <[email protected]>2022-08-14 12:41:50 +0800
commit18afd80c7fe90babb43f95ac2ca9bb1f0514fbb9 (patch)
tree0798f555320245d369ff43d53719cfc7771f52ba
parent2a05537705feb77069da1ec81aa031d3fb83e3f3 (diff)
add dcache support for hpm hcd
-rw-r--r--port/hpm/usb_hc_hpm.c123
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;
}