summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRafaël Carré <rafael.carre@gmail.com>2011-12-13 20:38:57 +0000
committerRafaël Carré <rafael.carre@gmail.com>2011-12-13 20:38:57 +0000
commita60463e636d62015af48ca865359e6535e691a6f (patch)
tree4a070317900f02eb24eda62e09a2d111b1f49aea
parent9e8590ad23e9e40a6adcb34df80fc11f75cfb0cf (diff)
downloadrockbox-a60463e636d62015af48ca865359e6535e691a6f.tar.gz
rockbox-a60463e636d62015af48ca865359e6535e691a6f.zip
usb-drv-as3525v2.c: simplify
don't interrupt on unhandled events git-svn-id: svn://svn.rockbox.org/rockbox/trunk@31232 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--firmware/target/arm/as3525/usb-drv-as3525v2.c172
1 files changed, 50 insertions, 122 deletions
diff --git a/firmware/target/arm/as3525/usb-drv-as3525v2.c b/firmware/target/arm/as3525/usb-drv-as3525v2.c
index 3836825114..c6bade6574 100644
--- a/firmware/target/arm/as3525/usb-drv-as3525v2.c
+++ b/firmware/target/arm/as3525/usb-drv-as3525v2.c
@@ -89,7 +89,6 @@ static enum ep0state ep0_state;
89 89
90void usb_attach(void) 90void usb_attach(void)
91{ 91{
92 logf("%s", __func__);
93 /* Nothing to do */ 92 /* Nothing to do */
94} 93}
95 94
@@ -108,68 +107,13 @@ static void flush_tx_fifos(void)
108 107
109static void prepare_setup_ep0(void) 108static void prepare_setup_ep0(void)
110{ 109{
111 logf("%s", __func__);
112 /* setup DMA */
113 DEPDMA(0, true) = (void*)AS3525_PHYSICAL_ADDR(&_ep0_setup_pkt); 110 DEPDMA(0, true) = (void*)AS3525_PHYSICAL_ADDR(&_ep0_setup_pkt);
114
115 /* Setup EP0 OUT with the following parameters:
116 * packet count = 1
117 * setup packet count = 1
118 * transfer size = 8 (setup packet)
119 */
120 DEPTSIZ(0, true) = (1 << DEPTSIZ0_supcnt_bitp) 111 DEPTSIZ(0, true) = (1 << DEPTSIZ0_supcnt_bitp)
121 | (1 << DEPTSIZ0_pkcnt_bitp) 112 | (1 << DEPTSIZ0_pkcnt_bitp)
122 | 8; 113 | 8;
123
124 /* Enable endpoint, clear nak */
125 ep0_state = EP0_WAIT_SETUP;
126 DEPCTL(0, true) |= DEPCTL_epena | DEPCTL_cnak; 114 DEPCTL(0, true) |= DEPCTL_epena | DEPCTL_cnak;
127}
128 115
129static void handle_ep0_complete(bool is_ack) 116 ep0_state = EP0_WAIT_SETUP;
130{
131 switch(ep0_state)
132 {
133 case EP0_WAIT_SETUP:
134 panicf("usb-drv: EP0 completion while waiting for SETUP");
135 case EP0_WAIT_ACK:
136 if(is_ack)
137 /* everything is done, prepare next setup */
138 prepare_setup_ep0();
139 else
140 panicf("usb-drv: EP0 data completion while waiting for ACK");
141 break;
142 case EP0_WAIT_DATA:
143 if(is_ack)
144 panicf("usb-drv: EP0 ACK while waiting for data completion");
145 else
146 /* everything is done, prepare next setup */
147 prepare_setup_ep0();
148 break;
149 case EP0_WAIT_DATA_ACK:
150 ep0_state = is_ack ? EP0_WAIT_DATA : EP0_WAIT_ACK;
151 break;
152 default:
153 panicf("usb-drv: invalid EP0 state");
154 }
155 logf("usb-drv: EP0 state updated to %d", ep0_state);
156}
157
158static void handle_ep0_setup(void)
159{
160 if(ep0_state != EP0_WAIT_SETUP)
161 {
162 logf("usb-drv: EP0 SETUP while in state %d", ep0_state);
163 return;
164 }
165 /* determine is there is a data phase */
166 if(ep0_setup_pkt->wLength == 0)
167 /* no: wait for ack */
168 ep0_state = EP0_WAIT_ACK;
169 else
170 /* yes: wait ack and data */
171 ep0_state = EP0_WAIT_DATA_ACK;
172 logf("usb-drv: EP0 state updated to %d", ep0_state);
173} 117}
174 118
175static void reset_endpoints(void) 119static void reset_endpoints(void)
@@ -200,11 +144,12 @@ static void reset_endpoints(void)
200 int next_ep = in_ep_list[(i + 1) % sizeof(in_ep_list)]; 144 int next_ep = in_ep_list[(i + 1) % sizeof(in_ep_list)];
201 DEPCTL(ep, false) = (DEPCTL(ep, false) & ~bitm(DEPCTL, nextep)) | (next_ep << DEPCTL_nextep_bitp); 145 DEPCTL(ep, false) = (DEPCTL(ep, false) & ~bitm(DEPCTL, nextep)) | (next_ep << DEPCTL_nextep_bitp);
202 } 146 }
147
148 prepare_setup_ep0();
203} 149}
204 150
205static void cancel_all_transfers(bool cancel_ep0) 151static void cancel_all_transfers(bool cancel_ep0)
206{ 152{
207 logf("%s", __func__);
208 int flags = disable_irq_save(); 153 int flags = disable_irq_save();
209 154
210 for (int dir = 0; dir < 2; dir++) 155 for (int dir = 0; dir < 2; dir++)
@@ -244,11 +189,10 @@ void usb_drv_init(void)
244 GRXFSIZ = 512; 189 GRXFSIZ = 512;
245 GNPTXFSIZ = MAKE_FIFOSIZE_DATA(512); 190 GNPTXFSIZ = MAKE_FIFOSIZE_DATA(512);
246 191
247 /* fixme: the current code is for internal DMA only, the clip+ architecture 192 /* FIXME: the current code is for internal DMA only, the clip+ architecture
248 * define the internal DMA model */ 193 * defines the internal DMA model */
249 /* Set burstlen and enable DMA*/
250 GAHBCFG = (GAHBCFG_INT_DMA_BURST_INCR << GAHBCFG_hburstlen_bitp) 194 GAHBCFG = (GAHBCFG_INT_DMA_BURST_INCR << GAHBCFG_hburstlen_bitp)
251 | GAHBCFG_dma_enable; 195 | GAHBCFG_dma_enable | GAHBCFG_glblintrmsk;
252 196
253 /* Select UTMI+ 16 */ 197 /* Select UTMI+ 16 */
254 GUSBCFG = GUSBCFG_force_device_mode | GUSBCFG_phy_if | 7 << GUSBCFG_toutcal_bitp; 198 GUSBCFG = GUSBCFG_force_device_mode | GUSBCFG_phy_if | 7 << GUSBCFG_toutcal_bitp;
@@ -291,26 +235,17 @@ void usb_drv_init(void)
291 235
292 reset_endpoints(); 236 reset_endpoints();
293 237
294 prepare_setup_ep0();
295
296 GINTMSK = GINTMSK_usbreset 238 GINTMSK = GINTMSK_usbreset
297 | GINTMSK_enumdone 239 | GINTMSK_enumdone
298 | GINTMSK_inepintr 240 | GINTMSK_inepintr
299 | GINTMSK_outepintr 241 | GINTMSK_outepintr
300 | GINTMSK_disconnect 242 | GINTMSK_disconnect;
301 | GINTMSK_usbsuspend
302 | GINTMSK_wkupintr
303 | GINTMSK_otgintr;
304 243
305 VIC_INT_ENABLE = INTERRUPT_USB; 244 VIC_INT_ENABLE = INTERRUPT_USB;
306 GAHBCFG |= GAHBCFG_glblintrmsk;
307} 245}
308 246
309void usb_drv_exit(void) 247void usb_drv_exit(void)
310{ 248{
311 logf("%s", __func__);
312
313 GAHBCFG &= ~GAHBCFG_glblintrmsk;
314 VIC_INT_EN_CLEAR = INTERRUPT_USB; 249 VIC_INT_EN_CLEAR = INTERRUPT_USB;
315 250
316 DCTL = DCTL_pwronprgdone | DCTL_sftdiscon; 251 DCTL = DCTL_pwronprgdone | DCTL_sftdiscon;
@@ -335,9 +270,25 @@ static void handle_ep_int(int ep, bool out)
335 /* works even for EP0 */ 270 /* works even for EP0 */
336 int size = (DEPTSIZ(ep, out) & DEPTSIZ_xfersize_bits); 271 int size = (DEPTSIZ(ep, out) & DEPTSIZ_xfersize_bits);
337 int transfered = endpoint->len - size; 272 int transfered = endpoint->len - size;
338 /* handle EP0 state if necessary, this is a ack if length is 0 */
339 if(ep == 0) 273 if(ep == 0)
340 handle_ep0_complete(endpoint->len == 0); 274 {
275 bool is_ack = endpoint->len == 0;
276 switch(ep0_state)
277 {
278 case EP0_WAIT_SETUP:
279 panicf("usb-drv: EP0 completion while waiting for SETUP");
280 case EP0_WAIT_DATA_ACK:
281 ep0_state = is_ack ? EP0_WAIT_DATA : EP0_WAIT_ACK;
282 break;
283 case EP0_WAIT_ACK:
284 case EP0_WAIT_DATA:
285 if((!is_ack && ep0_state == EP0_WAIT_ACK) || (is_ack && ep0_state == EP0_WAIT_DATA))
286 panicf("usb-drv: bad EP0 state");
287
288 prepare_setup_ep0();
289 break;
290 }
291 }
341 if (!out) 292 if (!out)
342 endpoint->len = size; 293 endpoint->len = size;
343 usb_core_transfer_complete(ep, out ? USB_DIR_OUT : USB_DIR_IN, 0, transfered); 294 usb_core_transfer_complete(ep, out ? USB_DIR_OUT : USB_DIR_IN, 0, transfered);
@@ -371,81 +322,63 @@ static void handle_ep_int(int ep, bool out)
371 } 322 }
372 else 323 else
373 { 324 {
374 /* handle EP0 state */ 325 if(ep0_state == EP0_WAIT_SETUP)
375 handle_ep0_setup(); 326 {
327 bool data_phase = ep0_setup_pkt->wLength != 0;
328 ep0_state = data_phase ? EP0_WAIT_DATA_ACK : EP0_WAIT_ACK;
329 }
330
376 logf(" rt=%x r=%x", ep0_setup_pkt->bRequestType, ep0_setup_pkt->bRequest); 331 logf(" rt=%x r=%x", ep0_setup_pkt->bRequestType, ep0_setup_pkt->bRequest);
377 /* handle set address */ 332
378 if(ep0_setup_pkt->bRequestType == USB_TYPE_STANDARD && 333 if(ep0_setup_pkt->bRequestType == USB_TYPE_STANDARD &&
379 ep0_setup_pkt->bRequest == USB_REQ_SET_ADDRESS) 334 ep0_setup_pkt->bRequest == USB_REQ_SET_ADDRESS)
380 { 335 {
381 /* Set address now */ 336 /* Set address */
382 DCFG = (DCFG & ~bitm(DCFG, devadr)) | (ep0_setup_pkt->wValue << DCFG_devadr_bitp); 337 DCFG = (DCFG & ~bitm(DCFG, devadr)) | (ep0_setup_pkt->wValue << DCFG_devadr_bitp);
383 } 338 }
384 usb_core_control_request(ep0_setup_pkt); 339 usb_core_control_request(ep0_setup_pkt);
385 } 340 }
386 } 341 }
387 342
388 /* clear interrupts */
389 DEPINT(ep, out) = sts; 343 DEPINT(ep, out) = sts;
390} 344}
391 345
392static void handle_ep_ints(void)
393{
394 logf("usb-drv: ep int");
395
396 unsigned long daint = DAINT;
397
398 for (int i = 0; i < USB_NUM_ENDPOINTS; i++)
399 {
400 if (daint & DAINT_IN_EP(i))
401 handle_ep_int(i, false);
402 if (daint & DAINT_OUT_EP(i))
403 handle_ep_int(i, true);
404 }
405
406 /* write back to clear status */
407 DAINT = daint;
408}
409
410/* interrupt service routine */
411void INT_USB(void) 346void INT_USB(void)
412{ 347{
413 /* some bits in GINTSTS can be set even though we didn't enable the interrupt source 348 /* some bits in GINTSTS can be set even though we didn't enable the interrupt source
414 * so AND it with the actual mask */ 349 * so AND it with the actual mask */
415 unsigned long sts = GINTSTS & GINTMSK; 350 unsigned long sts = GINTSTS & GINTMSK;
351 logf("usb-drv: INT 0x%lx", sts);
416 352
417 if(sts & GINTMSK_usbreset) 353 if(sts & GINTMSK_usbreset)
418 { 354 {
419 logf("usb-drv: bus reset");
420
421 /* Clear the Remote Wakeup Signalling */
422 DCTL &= ~DCTL_rmtwkupsig; 355 DCTL &= ~DCTL_rmtwkupsig;
423 356
424 flush_tx_fifos(); 357 flush_tx_fifos();
425 358
426 /* Flush the Learning Queue */
427 GRSTCTL = GRSTCTL_intknqflsh; 359 GRSTCTL = GRSTCTL_intknqflsh;
428 360
429 /* Reset Device Address */
430 DCFG &= ~bitm(DCFG, devadr); 361 DCFG &= ~bitm(DCFG, devadr);
431 362
432 reset_endpoints(); 363 reset_endpoints();
433 prepare_setup_ep0();
434 364
435 usb_core_bus_reset(); 365 usb_core_bus_reset();
436 } 366 }
437 367
438 if(sts & GINTMSK_enumdone) 368 if(sts & (GINTMSK_outepintr | GINTMSK_inepintr))
439 logf("usb-drv: enum done: speed %cS", usb_drv_port_speed() ? 'H' : 'F');
440
441 if(sts & GINTMSK_otgintr)
442 { 369 {
443 logf("usb-drv: otg int"); 370 unsigned long daint = DAINT;
444 GOTGINT = 0xffffffff;
445 }
446 371
447 if(sts & (GINTMSK_outepintr | GINTMSK_inepintr)) 372 for (int i = 0; i < USB_NUM_ENDPOINTS; i++)
448 handle_ep_ints(); 373 {
374 if (daint & DAINT_IN_EP(i))
375 handle_ep_int(i, false);
376 if (daint & DAINT_OUT_EP(i))
377 handle_ep_int(i, true);
378 }
379
380 DAINT = daint;
381 }
449 382
450 if(sts & GINTMSK_disconnect) 383 if(sts & GINTMSK_disconnect)
451 cancel_all_transfers(true); 384 cancel_all_transfers(true);
@@ -484,8 +417,6 @@ static unsigned long usb_drv_mps_by_type(int type)
484 417
485int usb_drv_request_endpoint(int type, int dir) 418int usb_drv_request_endpoint(int type, int dir)
486{ 419{
487 logf("usb-drv: request endpoint (type=%d,dir=%s)", type, dir == USB_DIR_IN ? "IN" : "OUT");
488
489 for (unsigned i = 1; i < sizeof((dir == USB_DIR_IN) ? in_ep_list : out_ep_list); i++) 420 for (unsigned i = 1; i < sizeof((dir == USB_DIR_IN) ? in_ep_list : out_ep_list); i++)
490 { 421 {
491 int ep = ((dir == USB_DIR_IN) ? in_ep_list : out_ep_list)[i]; 422 int ep = ((dir == USB_DIR_IN) ? in_ep_list : out_ep_list)[i];
@@ -499,13 +430,11 @@ int usb_drv_request_endpoint(int type, int dir)
499 return ep | dir; 430 return ep | dir;
500 } 431 }
501 432
502 logf("usb-drv: request failed");
503 return -1; 433 return -1;
504} 434}
505 435
506void usb_drv_release_endpoint(int ep) 436void usb_drv_release_endpoint(int ep)
507{ 437{
508 logf("usb-drv: release EP%d %s", EP_NUM(ep), EP_DIR(ep) == USB_DIR_IN ? "IN" : "OUT");
509 endpoints[EP_NUM(ep)][EP_DIR(ep)].active = false; 438 endpoints[EP_NUM(ep)][EP_DIR(ep)].active = false;
510} 439}
511 440
@@ -516,10 +445,9 @@ void usb_drv_cancel_all_transfers()
516 445
517static void usb_drv_transfer(int ep, void *ptr, int len, bool dir_in) 446static void usb_drv_transfer(int ep, void *ptr, int len, bool dir_in)
518{ 447{
519 ep = EP_NUM(ep);
520 struct usb_endpoint *endpoint = &endpoints[ep][dir_in]; 448 struct usb_endpoint *endpoint = &endpoints[ep][dir_in];
521 449
522 logf("usb-drv: xfer EP%d, len=%d, dir_in=%d, busy=%d", ep, len, dir_in, endpoint->busy); 450 logf("%s(%d, %d, %d) busy=%d", __func__, ep, len, dir_in, endpoint->busy);
523 451
524 /* disable interrupts to avoid any race */ 452 /* disable interrupts to avoid any race */
525 int oldlevel = disable_irq_save(); 453 int oldlevel = disable_irq_save();
@@ -554,12 +482,13 @@ static void usb_drv_transfer(int ep, void *ptr, int len, bool dir_in)
554 482
555int usb_drv_recv(int ep, void *ptr, int len) 483int usb_drv_recv(int ep, void *ptr, int len)
556{ 484{
557 usb_drv_transfer(ep, ptr, len, false); 485 usb_drv_transfer(EP_NUM(ep), ptr, len, false);
558 return 0; 486 return 0;
559} 487}
560 488
561int usb_drv_send(int ep, void *ptr, int len) 489int usb_drv_send(int ep, void *ptr, int len)
562{ 490{
491 ep = EP_NUM(ep);
563 struct usb_endpoint *endpoint = &endpoints[ep][1]; 492 struct usb_endpoint *endpoint = &endpoints[ep][1];
564 endpoint->done = false; 493 endpoint->done = false;
565 usb_drv_transfer(ep, ptr, len, true); 494 usb_drv_transfer(ep, ptr, len, true);
@@ -570,7 +499,7 @@ int usb_drv_send(int ep, void *ptr, int len)
570 499
571int usb_drv_send_nonblocking(int ep, void *ptr, int len) 500int usb_drv_send_nonblocking(int ep, void *ptr, int len)
572{ 501{
573 usb_drv_transfer(ep, ptr, len, true); 502 usb_drv_transfer(EP_NUM(ep), ptr, len, true);
574 return 0; 503 return 0;
575} 504}
576 505
@@ -589,7 +518,6 @@ void usb_drv_set_address(int address)
589 518
590void usb_drv_stall(int ep, bool stall, bool in) 519void usb_drv_stall(int ep, bool stall, bool in)
591{ 520{
592 logf("usb-drv: %sstall EP%d %s", stall ? "" : "un", ep, in ? "IN" : "OUT");
593 if (stall) 521 if (stall)
594 DEPCTL(ep, !in) |= DEPCTL_stall; 522 DEPCTL(ep, !in) |= DEPCTL_stall;
595 else 523 else