[U-Boot] [PATCH v5 02/19] usb: dwc2: Use separate input and output buffers
Marek Vasut
marex at denx.de
Sat Apr 1 20:15:27 UTC 2017
On 04/01/2017 08:05 PM, Simon Glass wrote:
> 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.
What do you think of this patch:
[U-Boot] usb: dwc2: invalidate the dcache before starting the DMA
> 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 */
>
--
Best regards,
Marek Vasut
More information about the U-Boot
mailing list