summaryrefslogtreecommitdiffstats
path: root/firmware
diff options
context:
space:
mode:
authorMichael Sparmann <theseven@rockbox.org>2010-08-12 08:35:43 +0000
committerMichael Sparmann <theseven@rockbox.org>2010-08-12 08:35:43 +0000
commitf3834a46262a548051d882db813f4d408939989b (patch)
tree211337dc3b552c2d584d1bd5ed1ba4091ca03ff7 /firmware
parentad4deec074ad071db216049b796b74a3820bc481 (diff)
downloadrockbox-f3834a46262a548051d882db813f4d408939989b.tar.gz
rockbox-f3834a46262a548051d882db813f4d408939989b.tar.bz2
rockbox-f3834a46262a548051d882db813f4d408939989b.zip
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
Diffstat (limited to 'firmware')
-rw-r--r--firmware/export/usb_drv.h4
-rw-r--r--firmware/target/arm/usb-s3c6400x.c43
2 files changed, 26 insertions, 21 deletions
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;