From: David Brownell <dbrownell@xxxxxxxxxxxxxxxxxxxxx> Update the at91_udc driver to improve at91sam9g20 support. This is a sped-up at91sam9260; the CPU is twice as fast, but clocking for peripheralsl won't change much. - Its endpoint FIFOs have the same larger sizes as the '9260. - It's more open to races with data still on its way to the USB peripheral, while the driver acts as if it already got there. Fix the former by adding the relevant cpu_is_*() check, and the latter by updating some FIFO read/write paths so they wait until the CPU's write buffer drains ... that's a bit cheaper than just issuing a controller read. Problem noted by Manuel Sahm <Manuel.Sahm@xxxxxxx>, who also provided a patch for this. One race could be the same as one noted by Anti Sullin <anti.sullin@xxxxxxxxxxxxxx> after a GCC upgrade on a sam9261 board. Cc: Manuel Sahm <Manuel.Sahm@xxxxxxx> Cc: Nicolas Ferre <nicolas.ferre@xxxxxxxxxxxxx> Signed-off-by: David Brownell <dbrownell@xxxxxxxxxxxxxxxxxxxxx> --- drivers/usb/gadget/at91_udc.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) --- a/drivers/usb/gadget/at91_udc.c +++ b/drivers/usb/gadget/at91_udc.c @@ -82,6 +82,11 @@ static const char ep0name[] = "ep0"; #define at91_udp_write(dev, reg, val) \ __raw_writel((val), (dev)->udp_baseaddr + (reg)) +static inline int drain_write_buffer(void) +{ + asm("mcr p15, 0, r0, c7, c10, 4 @ drain write buffer\n"); +} + /*-------------------------------------------------------------------------*/ #ifdef CONFIG_USB_GADGET_DEBUG_FILES @@ -350,6 +355,7 @@ rescan: } else csr &= ~(SET_FX | AT91_UDP_RX_DATA_BK0); __raw_writel(csr, creg); + drain_write_buffer(); req->req.actual += count; is_done = (count < ep->ep.maxpacket); @@ -434,6 +440,8 @@ static int write_fifo(struct at91_ep *ep csr &= ~SET_FX; csr |= CLR_FX | AT91_UDP_TXPKTRDY; __raw_writel(csr, creg); + drain_write_buffer(); + req->req.actual += count; PACKET("%s %p in/%d%s\n", ep->ep.name, &req->req, count, @@ -669,6 +677,7 @@ ep0_in_status: tmp &= ~SET_FX; tmp |= CLR_FX | AT91_UDP_TXPKTRDY; __raw_writel(tmp, ep->creg); + drain_write_buffer(); dev->req_pending = 0; goto done; } @@ -1687,7 +1696,7 @@ static int __init at91udc_probe(struct p } /* newer chips have more FIFO memory than rm9200 */ - if (cpu_is_at91sam9260()) { + if (cpu_is_at91sam9260() || cpu_is_at91sam9g20()) { udc->ep[0].maxpacket = 64; udc->ep[3].maxpacket = 64; udc->ep[4].maxpacket = 512; -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html