[patch/rft 2.6.30] at91_udc: at91sam9g20 updates

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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

[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux