summaryrefslogtreecommitdiff
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
parentad4deec074ad071db216049b796b74a3820bc481 (diff)
downloadrockbox-f3834a46262a548051d882db813f4d408939989b.tar.gz
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
-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);
33void usb_drv_int(void); /* Call from target INT handler */ 33void usb_drv_int(void); /* Call from target INT handler */
34void usb_drv_stall(int endpoint, bool stall,bool in); 34void usb_drv_stall(int endpoint, bool stall,bool in);
35bool usb_drv_stalled(int endpoint,bool in); 35bool usb_drv_stalled(int endpoint,bool in);
36int usb_drv_send(int endpoint, void* ptr, int length); 36int usb_drv_send(int endpoint, const void* ptr, int length);
37int usb_drv_send_nonblocking(int endpoint, void* ptr, int length); 37int usb_drv_send_nonblocking(int endpoint, const void* ptr, int length);
38int usb_drv_recv(int endpoint, void* ptr, int length); 38int usb_drv_recv(int endpoint, void* ptr, int length);
39void usb_drv_ack(struct usb_ctrlrequest* req); 39void usb_drv_ack(struct usb_ctrlrequest* req);
40void usb_drv_set_address(int address); 40void 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)
148 while (GRSTCTL & 1); /* Wait for OTG to ack reset */ 148 while (GRSTCTL & 1); /* Wait for OTG to ack reset */
149 while (!(GRSTCTL & 0x80000000)); /* Wait for OTG AHB master idle */ 149 while (!(GRSTCTL & 0x80000000)); /* Wait for OTG AHB master idle */
150 150
151 GRXFSIZ = 0x00000200; /* RX FIFO: 512 bytes */
152 GNPTXFSIZ = 0x02000200; /* Non-periodic TX FIFO: 512 bytes */
151 GAHBCFG = 0x27; /* OTG AHB config: Unmask ints, burst length 4, DMA on */ 153 GAHBCFG = 0x27; /* OTG AHB config: Unmask ints, burst length 4, DMA on */
152 GUSBCFG = 0x1408; /* OTG: 16bit PHY and some reserved bits */ 154 GUSBCFG = 0x1408; /* OTG: 16bit PHY and some reserved bits */
153 155
@@ -155,6 +157,7 @@ static void usb_reset(void)
155 DCTL = 0x800; /* Soft Reconnect */ 157 DCTL = 0x800; /* Soft Reconnect */
156 DIEPMSK = 0x0D; /* IN EP interrupt mask */ 158 DIEPMSK = 0x0D; /* IN EP interrupt mask */
157 DOEPMSK = 0x0D; /* IN EP interrupt mask */ 159 DOEPMSK = 0x0D; /* IN EP interrupt mask */
160 DAINTMSK = 0xFFFFFFFF; /* Enable interrupts on all endpoints */
158 GINTMSK = 0xC3000; /* Interrupt mask: IN event, OUT event, bus reset */ 161 GINTMSK = 0xC3000; /* Interrupt mask: IN event, OUT event, bus reset */
159 162
160 reset_endpoints(1); 163 reset_endpoints(1);
@@ -164,14 +167,16 @@ static void usb_reset(void)
164void INT_USB_FUNC(void) 167void INT_USB_FUNC(void)
165{ 168{
166 int i; 169 int i;
167 if (GINTSTS & 0x1000) /* bus reset */ 170 uint32_t ints = GINTSTS;
171 uint32_t epints;
172 if (ints & 0x1000) /* bus reset */
168 { 173 {
169 DCFG = 4; /* Address 0 */ 174 DCFG = 4; /* Address 0 */
170 reset_endpoints(1); 175 reset_endpoints(1);
171 usb_core_bus_reset(); 176 usb_core_bus_reset();
172 } 177 }
173 178
174 if (GINTSTS & 0x2000) /* enumeration done, we now know the speed */ 179 if (ints & 0x2000) /* enumeration done, we now know the speed */
175 { 180 {
176 /* Set up the maximum packet sizes accordingly */ 181 /* Set up the maximum packet sizes accordingly */
177 uint32_t maxpacket = usb_drv_port_speed() ? 512 : 64; 182 uint32_t maxpacket = usb_drv_port_speed() ? 512 : 64;
@@ -181,11 +186,11 @@ void INT_USB_FUNC(void)
181 DOEPCTL4 = (DOEPCTL4 & ~0x000003FF) | maxpacket; 186 DOEPCTL4 = (DOEPCTL4 & ~0x000003FF) | maxpacket;
182 } 187 }
183 188
184 if (GINTSTS & 0x40000) /* IN EP event */ 189 if (ints & 0x40000) /* IN EP event */
185 for (i = 0; i < 5; i ++) 190 for (i = 0; i < 4; i += i + 1) // 0, 1, 3
186 if (i != 2 && i != 4 && DIEPINT(i)) 191 if ((epints = DIEPINT(i)))
187 { 192 {
188 if (DIEPINT(i) & 1) /* Transfer completed */ 193 if (epints & 1) /* Transfer completed */
189 { 194 {
190 invalidate_dcache(); 195 invalidate_dcache();
191 int bytes = endpoints[i].size - (DIEPTSIZ(i) & 0x3FFFF); 196 int bytes = endpoints[i].size - (DIEPTSIZ(i) & 0x3FFFF);
@@ -198,9 +203,9 @@ void INT_USB_FUNC(void)
198 wakeup_signal(&endpoints[i].complete); 203 wakeup_signal(&endpoints[i].complete);
199 } 204 }
200 } 205 }
201 if (DIEPINT(i) & 4) /* AHB error */ 206 if (epints & 4) /* AHB error */
202 panicf("USB: AHB error on IN EP%d", i); 207 panicf("USB: AHB error on IN EP%d", i);
203 if (DIEPINT(i) & 8) /* Timeout */ 208 if (epints & 8) /* Timeout */
204 { 209 {
205 if (endpoints[i].busy) 210 if (endpoints[i].busy)
206 { 211 {
@@ -210,14 +215,14 @@ void INT_USB_FUNC(void)
210 wakeup_signal(&endpoints[i].complete); 215 wakeup_signal(&endpoints[i].complete);
211 } 216 }
212 } 217 }
213 DIEPINT(i) = DIEPINT(i); 218 DIEPINT(i) = epints;
214 } 219 }
215 220
216 if (GINTSTS & 0x80000) /* OUT EP event */ 221 if (ints & 0x80000) /* OUT EP event */
217 for (i = 0; i < 5; i += 2) 222 for (i = 0; i < 5; i += 2)
218 if (DOEPINT(i)) 223 if ((epints = DOEPINT(i)))
219 { 224 {
220 if (DOEPINT(i) & 1) /* Transfer completed */ 225 if (epints & 1) /* Transfer completed */
221 { 226 {
222 invalidate_dcache(); 227 invalidate_dcache();
223 int bytes = endpoints[i].size - (DOEPTSIZ(i) & 0x3FFFF); 228 int bytes = endpoints[i].size - (DOEPTSIZ(i) & 0x3FFFF);
@@ -230,9 +235,9 @@ void INT_USB_FUNC(void)
230 wakeup_signal(&endpoints[i].complete); 235 wakeup_signal(&endpoints[i].complete);
231 } 236 }
232 } 237 }
233 if (DOEPINT(i) & 4) /* AHB error */ 238 if (epints & 4) /* AHB error */
234 panicf("USB: AHB error on OUT EP%d", i); 239 panicf("USB: AHB error on OUT EP%d", i);
235 if (DOEPINT(i) & 8) /* SETUP phase done */ 240 if (epints & 8) /* SETUP phase done */
236 { 241 {
237 invalidate_dcache(); 242 invalidate_dcache();
238 if (i == 0) 243 if (i == 0)
@@ -255,10 +260,10 @@ void INT_USB_FUNC(void)
255 DOEPDMA0 = (uint32_t)&ctrlreq; 260 DOEPDMA0 = (uint32_t)&ctrlreq;
256 DOEPCTL0 |= 0x84000000; 261 DOEPCTL0 |= 0x84000000;
257 } 262 }
258 DOEPINT(i) = DOEPINT(i); 263 DOEPINT(i) = epints;
259 } 264 }
260 265
261 GINTSTS = GINTSTS; 266 GINTSTS = ints;
262} 267}
263 268
264void usb_drv_set_address(int address) 269void usb_drv_set_address(int address)
@@ -270,7 +275,7 @@ void usb_drv_set_address(int address)
270 into the USB core, which will then call this dummy function. */ 275 into the USB core, which will then call this dummy function. */
271} 276}
272 277
273static void ep_send(int ep, void *ptr, int length) 278static void ep_send(int ep, const void *ptr, int length)
274{ 279{
275 endpoints[ep].busy = true; 280 endpoints[ep].busy = true;
276 endpoints[ep].size = length; 281 endpoints[ep].size = length;
@@ -313,7 +318,7 @@ static void ep_recv(int ep, void *ptr, int length)
313 DOEPCTL(ep) |= 0x84000000; /* EPx OUT ENABLE CLEARNAK */ 318 DOEPCTL(ep) |= 0x84000000; /* EPx OUT ENABLE CLEARNAK */
314} 319}
315 320
316int usb_drv_send(int endpoint, void *ptr, int length) 321int usb_drv_send(int endpoint, const void *ptr, int length)
317{ 322{
318 endpoint &= 0x7f; 323 endpoint &= 0x7f;
319 endpoints[endpoint].done = false; 324 endpoints[endpoint].done = false;
@@ -323,7 +328,7 @@ int usb_drv_send(int endpoint, void *ptr, int length)
323 return endpoints[endpoint].rc; 328 return endpoints[endpoint].rc;
324} 329}
325 330
326int usb_drv_send_nonblocking(int endpoint, void *ptr, int length) 331int usb_drv_send_nonblocking(int endpoint, const void *ptr, int length)
327{ 332{
328 ep_send(endpoint & 0x7f, ptr, length); 333 ep_send(endpoint & 0x7f, ptr, length);
329 return 0; 334 return 0;