From mboxrd@z Thu Jan 1 00:00:00 1970 From: Marek Vasut Date: Sat, 1 Apr 2017 22:15:27 +0200 Subject: [U-Boot] [PATCH v5 02/19] usb: dwc2: Use separate input and output buffers In-Reply-To: <20170401180556.2416-3-sjg@chromium.org> References: <20170401180556.2416-1-sjg@chromium.org> <20170401180556.2416-3-sjg@chromium.org> Message-ID: <2ae9f6f1-421f-4aa8-a568-f70b3ba66408@denx.de> List-Id: MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit To: u-boot@lists.denx.de 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 > --- > > 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