From f3834a46262a548051d882db813f4d408939989b Mon Sep 17 00:00:00 2001 From: Michael Sparmann Date: Thu, 12 Aug 2010 08:35:43 +0000 Subject: emBIOS backports part one: Fix an annoying race condition in the Synopsys OTG driver, and a bit of const correctness. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@27779 a1c6a512-1295-4272-9138-f99709370657 --- firmware/export/usb_drv.h | 4 ++-- firmware/target/arm/usb-s3c6400x.c | 43 +++++++++++++++++++++----------------- 2 files changed, 26 insertions(+), 21 deletions(-) (limited to 'firmware') diff --git a/firmware/export/usb_drv.h b/firmware/export/usb_drv.h index fad9c79c10..c29d2892d6 100644 --- a/firmware/export/usb_drv.h +++ b/firmware/export/usb_drv.h @@ -33,8 +33,8 @@ void usb_drv_attach(void); void usb_drv_int(void); /* Call from target INT handler */ void usb_drv_stall(int endpoint, bool stall,bool in); bool usb_drv_stalled(int endpoint,bool in); -int usb_drv_send(int endpoint, void* ptr, int length); -int usb_drv_send_nonblocking(int endpoint, void* ptr, int length); +int usb_drv_send(int endpoint, const void* ptr, int length); +int usb_drv_send_nonblocking(int endpoint, const void* ptr, int length); int usb_drv_recv(int endpoint, void* ptr, int length); void usb_drv_ack(struct usb_ctrlrequest* req); void usb_drv_set_address(int address); diff --git a/firmware/target/arm/usb-s3c6400x.c b/firmware/target/arm/usb-s3c6400x.c index 6fbf453cd1..8755eabdf9 100644 --- a/firmware/target/arm/usb-s3c6400x.c +++ b/firmware/target/arm/usb-s3c6400x.c @@ -148,6 +148,8 @@ static void usb_reset(void) while (GRSTCTL & 1); /* Wait for OTG to ack reset */ while (!(GRSTCTL & 0x80000000)); /* Wait for OTG AHB master idle */ + GRXFSIZ = 0x00000200; /* RX FIFO: 512 bytes */ + GNPTXFSIZ = 0x02000200; /* Non-periodic TX FIFO: 512 bytes */ GAHBCFG = 0x27; /* OTG AHB config: Unmask ints, burst length 4, DMA on */ GUSBCFG = 0x1408; /* OTG: 16bit PHY and some reserved bits */ @@ -155,6 +157,7 @@ static void usb_reset(void) DCTL = 0x800; /* Soft Reconnect */ DIEPMSK = 0x0D; /* IN EP interrupt mask */ DOEPMSK = 0x0D; /* IN EP interrupt mask */ + DAINTMSK = 0xFFFFFFFF; /* Enable interrupts on all endpoints */ GINTMSK = 0xC3000; /* Interrupt mask: IN event, OUT event, bus reset */ reset_endpoints(1); @@ -164,14 +167,16 @@ static void usb_reset(void) void INT_USB_FUNC(void) { int i; - if (GINTSTS & 0x1000) /* bus reset */ + uint32_t ints = GINTSTS; + uint32_t epints; + if (ints & 0x1000) /* bus reset */ { DCFG = 4; /* Address 0 */ reset_endpoints(1); usb_core_bus_reset(); } - if (GINTSTS & 0x2000) /* enumeration done, we now know the speed */ + if (ints & 0x2000) /* enumeration done, we now know the speed */ { /* Set up the maximum packet sizes accordingly */ uint32_t maxpacket = usb_drv_port_speed() ? 512 : 64; @@ -181,11 +186,11 @@ void INT_USB_FUNC(void) DOEPCTL4 = (DOEPCTL4 & ~0x000003FF) | maxpacket; } - if (GINTSTS & 0x40000) /* IN EP event */ - for (i = 0; i < 5; i ++) - if (i != 2 && i != 4 && DIEPINT(i)) + if (ints & 0x40000) /* IN EP event */ + for (i = 0; i < 4; i += i + 1) // 0, 1, 3 + if ((epints = DIEPINT(i))) { - if (DIEPINT(i) & 1) /* Transfer completed */ + if (epints & 1) /* Transfer completed */ { invalidate_dcache(); int bytes = endpoints[i].size - (DIEPTSIZ(i) & 0x3FFFF); @@ -198,9 +203,9 @@ void INT_USB_FUNC(void) wakeup_signal(&endpoints[i].complete); } } - if (DIEPINT(i) & 4) /* AHB error */ + if (epints & 4) /* AHB error */ panicf("USB: AHB error on IN EP%d", i); - if (DIEPINT(i) & 8) /* Timeout */ + if (epints & 8) /* Timeout */ { if (endpoints[i].busy) { @@ -210,14 +215,14 @@ void INT_USB_FUNC(void) wakeup_signal(&endpoints[i].complete); } } - DIEPINT(i) = DIEPINT(i); + DIEPINT(i) = epints; } - if (GINTSTS & 0x80000) /* OUT EP event */ + if (ints & 0x80000) /* OUT EP event */ for (i = 0; i < 5; i += 2) - if (DOEPINT(i)) + if ((epints = DOEPINT(i))) { - if (DOEPINT(i) & 1) /* Transfer completed */ + if (epints & 1) /* Transfer completed */ { invalidate_dcache(); int bytes = endpoints[i].size - (DOEPTSIZ(i) & 0x3FFFF); @@ -230,9 +235,9 @@ void INT_USB_FUNC(void) wakeup_signal(&endpoints[i].complete); } } - if (DOEPINT(i) & 4) /* AHB error */ + if (epints & 4) /* AHB error */ panicf("USB: AHB error on OUT EP%d", i); - if (DOEPINT(i) & 8) /* SETUP phase done */ + if (epints & 8) /* SETUP phase done */ { invalidate_dcache(); if (i == 0) @@ -255,10 +260,10 @@ void INT_USB_FUNC(void) DOEPDMA0 = (uint32_t)&ctrlreq; DOEPCTL0 |= 0x84000000; } - DOEPINT(i) = DOEPINT(i); + DOEPINT(i) = epints; } - GINTSTS = GINTSTS; + GINTSTS = ints; } void usb_drv_set_address(int address) @@ -270,7 +275,7 @@ void usb_drv_set_address(int address) into the USB core, which will then call this dummy function. */ } -static void ep_send(int ep, void *ptr, int length) +static void ep_send(int ep, const void *ptr, int length) { endpoints[ep].busy = true; endpoints[ep].size = length; @@ -313,7 +318,7 @@ static void ep_recv(int ep, void *ptr, int length) DOEPCTL(ep) |= 0x84000000; /* EPx OUT ENABLE CLEARNAK */ } -int usb_drv_send(int endpoint, void *ptr, int length) +int usb_drv_send(int endpoint, const void *ptr, int length) { endpoint &= 0x7f; endpoints[endpoint].done = false; @@ -323,7 +328,7 @@ int usb_drv_send(int endpoint, void *ptr, int length) return endpoints[endpoint].rc; } -int usb_drv_send_nonblocking(int endpoint, void *ptr, int length) +int usb_drv_send_nonblocking(int endpoint, const void *ptr, int length) { ep_send(endpoint & 0x7f, ptr, length); return 0; -- cgit