[U-Boot] [PATCH v5 02/19] usb: dwc2: Use separate input and output buffers
Simon Glass
sjg at chromium.org
Sat Apr 1 18:05:39 UTC 2017
On Raspberry Pi 2 and 3 a problem was noticed when enabling driver model
for USB: the cache invalidate after an incoming transfer does not seem to
work correctly.
This may be a problem with the underlying caching implementation on armv7
and armv8 but this seems very unlikely. As a work-around, use separate
buffers for input and output. This ensures that the input buffer will not
hold dirty cache data.
Signed-off-by: Simon Glass <sjg at chromium.org>
---
Changes in v5:
- Add new patch for dwc2 to se separate input and output buffers
Changes in v4: None
Changes in v3: None
drivers/usb/host/dwc2.c | 27 ++++++++++++++++++++-------
1 file changed, 20 insertions(+), 7 deletions(-)
diff --git a/drivers/usb/host/dwc2.c b/drivers/usb/host/dwc2.c
index d253b946f3..a65ed4f66c 100644
--- a/drivers/usb/host/dwc2.c
+++ b/drivers/usb/host/dwc2.c
@@ -31,10 +31,14 @@ DECLARE_GLOBAL_DATA_PTR;
struct dwc2_priv {
#ifdef CONFIG_DM_USB
- uint8_t aligned_buffer[DWC2_DATA_BUF_SIZE] __aligned(ARCH_DMA_MINALIGN);
+ uint8_t aligned_buffer_in[DWC2_DATA_BUF_SIZE]
+ __aligned(ARCH_DMA_MINALIGN);
+ uint8_t aligned_buffer_out[DWC2_DATA_BUF_SIZE]
+ __aligned(ARCH_DMA_MINALIGN);
uint8_t status_buffer[DWC2_STATUS_BUF_SIZE] __aligned(ARCH_DMA_MINALIGN);
#else
- uint8_t *aligned_buffer;
+ uint8_t *aligned_buffer_in;
+ uint8_t *aligned_buffer_out;
uint8_t *status_buffer;
#endif
u8 in_data_toggle[MAX_DEVICE][MAX_ENDPOINT];
@@ -769,10 +773,12 @@ static int dwc2_eptype[] = {
DWC2_HCCHAR_EPTYPE_BULK,
};
-static int transfer_chunk(struct dwc2_hc_regs *hc_regs, void *aligned_buffer,
- u8 *pid, int in, void *buffer, int num_packets,
- int xfer_len, int *actual_len, int odd_frame)
+static int transfer_chunk(struct dwc2_hc_regs *hc_regs, void *aligned_buffer_in,
+ void *aligned_buffer_out, u8 *pid, int in,
+ void *buffer, int num_packets, int xfer_len,
+ int *actual_len, int odd_frame)
{
+ void *aligned_buffer;
int ret = 0;
uint32_t sub;
@@ -785,11 +791,14 @@ static int transfer_chunk(struct dwc2_hc_regs *hc_regs, void *aligned_buffer,
&hc_regs->hctsiz);
if (!in && xfer_len) {
+ aligned_buffer = aligned_buffer_in;
memcpy(aligned_buffer, buffer, xfer_len);
flush_dcache_range((unsigned long)aligned_buffer,
(unsigned long)aligned_buffer +
roundup(xfer_len, ARCH_DMA_MINALIGN));
+ } else {
+ aligned_buffer = aligned_buffer_out;
}
writel(phys_to_bus((unsigned long)aligned_buffer), &hc_regs->hcdma);
@@ -901,7 +910,8 @@ int chunk_msg(struct dwc2_priv *priv, struct usb_device *dev,
odd_frame = 1;
}
- ret = transfer_chunk(hc_regs, priv->aligned_buffer, pid,
+ ret = transfer_chunk(hc_regs, priv->aligned_buffer_in,
+ priv->aligned_buffer_out, pid,
in, (char *)buffer + done, num_packets,
xfer_len, &actual_len, odd_frame);
@@ -1136,7 +1146,10 @@ int usb_lowlevel_init(int index, enum usb_init_type init, void **controller)
memset(priv, '\0', sizeof(*priv));
priv->root_hub_devnum = 0;
priv->regs = (struct dwc2_core_regs *)CONFIG_USB_DWC2_REG_ADDR;
- priv->aligned_buffer = aligned_buffer_addr;
+
+ /* We can use the same buffer for input and output */
+ priv->aligned_buffer_in = aligned_buffer_addr;
+ priv->aligned_buffer_out = aligned_buffer_addr;
priv->status_buffer = status_buffer_addr;
/* board-dependant init */
--
2.12.2.564.g063fe858b8-goog
More information about the U-Boot
mailing list