aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/musb/musb_gadget.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/musb/musb_gadget.c')
-rw-r--r--drivers/usb/musb/musb_gadget.c196
1 files changed, 102 insertions, 94 deletions
diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c
index 74073f9a43f0..c49b9ba025ab 100644
--- a/drivers/usb/musb/musb_gadget.c
+++ b/drivers/usb/musb/musb_gadget.c
@@ -429,112 +429,102 @@ void musb_g_tx(struct musb *musb, u8 epnum)
429 DBG(4, "<== %s, txcsr %04x\n", musb_ep->end_point.name, csr); 429 DBG(4, "<== %s, txcsr %04x\n", musb_ep->end_point.name, csr);
430 430
431 dma = is_dma_capable() ? musb_ep->dma : NULL; 431 dma = is_dma_capable() ? musb_ep->dma : NULL;
432 do { 432
433 /* REVISIT for high bandwidth, MUSB_TXCSR_P_INCOMPTX 433 /*
434 * probably rates reporting as a host error 434 * REVISIT: for high bandwidth, MUSB_TXCSR_P_INCOMPTX
435 * probably rates reporting as a host error.
436 */
437 if (csr & MUSB_TXCSR_P_SENTSTALL) {
438 csr |= MUSB_TXCSR_P_WZC_BITS;
439 csr &= ~MUSB_TXCSR_P_SENTSTALL;
440 musb_writew(epio, MUSB_TXCSR, csr);
441 return;
442 }
443
444 if (csr & MUSB_TXCSR_P_UNDERRUN) {
445 /* We NAKed, no big deal... little reason to care. */
446 csr |= MUSB_TXCSR_P_WZC_BITS;
447 csr &= ~(MUSB_TXCSR_P_UNDERRUN | MUSB_TXCSR_TXPKTRDY);
448 musb_writew(epio, MUSB_TXCSR, csr);
449 DBG(20, "underrun on ep%d, req %p\n", epnum, request);
450 }
451
452 if (dma_channel_status(dma) == MUSB_DMA_STATUS_BUSY) {
453 /*
454 * SHOULD NOT HAPPEN... has with CPPI though, after
455 * changing SENDSTALL (and other cases); harmless?
435 */ 456 */
436 if (csr & MUSB_TXCSR_P_SENTSTALL) { 457 DBG(5, "%s dma still busy?\n", musb_ep->end_point.name);
437 csr |= MUSB_TXCSR_P_WZC_BITS; 458 return;
438 csr &= ~MUSB_TXCSR_P_SENTSTALL; 459 }
439 musb_writew(epio, MUSB_TXCSR, csr); 460
440 break; 461 if (request) {
441 } 462 u8 is_dma = 0;
442 463
443 if (csr & MUSB_TXCSR_P_UNDERRUN) { 464 if (dma && (csr & MUSB_TXCSR_DMAENAB)) {
444 /* we NAKed, no big deal ... little reason to care */ 465 is_dma = 1;
445 csr |= MUSB_TXCSR_P_WZC_BITS; 466 csr |= MUSB_TXCSR_P_WZC_BITS;
446 csr &= ~(MUSB_TXCSR_P_UNDERRUN 467 csr &= ~(MUSB_TXCSR_DMAENAB | MUSB_TXCSR_P_UNDERRUN |
447 | MUSB_TXCSR_TXPKTRDY); 468 MUSB_TXCSR_TXPKTRDY);
448 musb_writew(epio, MUSB_TXCSR, csr); 469 musb_writew(epio, MUSB_TXCSR, csr);
449 DBG(20, "underrun on ep%d, req %p\n", epnum, request); 470 /* Ensure writebuffer is empty. */
471 csr = musb_readw(epio, MUSB_TXCSR);
472 request->actual += musb_ep->dma->actual_len;
473 DBG(4, "TXCSR%d %04x, DMA off, len %zu, req %p\n",
474 epnum, csr, musb_ep->dma->actual_len, request);
450 } 475 }
451 476
452 if (dma_channel_status(dma) == MUSB_DMA_STATUS_BUSY) { 477 if (is_dma || request->actual == request->length) {
453 /* SHOULD NOT HAPPEN ... has with cppi though, after 478 /*
454 * changing SENDSTALL (and other cases); harmless? 479 * First, maybe a terminating short packet. Some DMA
480 * engines might handle this by themselves.
455 */ 481 */
456 DBG(5, "%s dma still busy?\n", musb_ep->end_point.name); 482 if ((request->zero && request->length
457 break; 483 && request->length % musb_ep->packet_sz == 0)
458 }
459
460 if (request) {
461 u8 is_dma = 0;
462
463 if (dma && (csr & MUSB_TXCSR_DMAENAB)) {
464 is_dma = 1;
465 csr |= MUSB_TXCSR_P_WZC_BITS;
466 csr &= ~(MUSB_TXCSR_DMAENAB
467 | MUSB_TXCSR_P_UNDERRUN
468 | MUSB_TXCSR_TXPKTRDY);
469 musb_writew(epio, MUSB_TXCSR, csr);
470 /* ensure writebuffer is empty */
471 csr = musb_readw(epio, MUSB_TXCSR);
472 request->actual += musb_ep->dma->actual_len;
473 DBG(4, "TXCSR%d %04x, dma off, "
474 "len %zu, req %p\n",
475 epnum, csr,
476 musb_ep->dma->actual_len,
477 request);
478 }
479
480 if (is_dma || request->actual == request->length) {
481
482 /* First, maybe a terminating short packet.
483 * Some DMA engines might handle this by
484 * themselves.
485 */
486 if ((request->zero
487 && request->length
488 && (request->length
489 % musb_ep->packet_sz)
490 == 0)
491#ifdef CONFIG_USB_INVENTRA_DMA 484#ifdef CONFIG_USB_INVENTRA_DMA
492 || (is_dma && 485 || (is_dma && (!dma->desired_mode ||
493 ((!dma->desired_mode) || 486 (request->actual &
494 (request->actual & 487 (musb_ep->packet_sz - 1))))
495 (musb_ep->packet_sz - 1))))
496#endif 488#endif
497 ) { 489 ) {
498 /* on dma completion, fifo may not 490 /*
499 * be available yet ... 491 * On DMA completion, FIFO may not be
500 */ 492 * available yet...
501 if (csr & MUSB_TXCSR_TXPKTRDY)
502 break;
503
504 DBG(4, "sending zero pkt\n");
505 musb_writew(epio, MUSB_TXCSR,
506 MUSB_TXCSR_MODE
507 | MUSB_TXCSR_TXPKTRDY);
508 request->zero = 0;
509 }
510
511 /* ... or if not, then complete it */
512 musb_g_giveback(musb_ep, request, 0);
513
514 /* kickstart next transfer if appropriate;
515 * the packet that just completed might not
516 * be transmitted for hours or days.
517 * REVISIT for double buffering...
518 * FIXME revisit for stalls too...
519 */ 493 */
520 musb_ep_select(mbase, epnum); 494 if (csr & MUSB_TXCSR_TXPKTRDY)
521 csr = musb_readw(epio, MUSB_TXCSR); 495 return;
522 if (csr & MUSB_TXCSR_FIFONOTEMPTY) 496
523 break; 497 DBG(4, "sending zero pkt\n");
524 request = musb_ep->desc 498 musb_writew(epio, MUSB_TXCSR, MUSB_TXCSR_MODE
525 ? next_request(musb_ep) 499 | MUSB_TXCSR_TXPKTRDY);
526 : NULL; 500 request->zero = 0;
527 if (!request) {
528 DBG(4, "%s idle now\n",
529 musb_ep->end_point.name);
530 break;
531 }
532 } 501 }
533 502
534 txstate(musb, to_musb_request(request)); 503 /* ... or if not, then complete it. */
504 musb_g_giveback(musb_ep, request, 0);
505
506 /*
507 * Kickstart next transfer if appropriate;
508 * the packet that just completed might not
509 * be transmitted for hours or days.
510 * REVISIT for double buffering...
511 * FIXME revisit for stalls too...
512 */
513 musb_ep_select(mbase, epnum);
514 csr = musb_readw(epio, MUSB_TXCSR);
515 if (csr & MUSB_TXCSR_FIFONOTEMPTY)
516 return;
517
518 if (!musb_ep->desc) {
519 DBG(4, "%s idle now\n",
520 musb_ep->end_point.name);
521 return;
522 } else
523 request = next_request(musb_ep);
535 } 524 }
536 525
537 } while (0); 526 txstate(musb, to_musb_request(request));
527 }
538} 528}
539 529
540/* ------------------------------------------------------------ */ 530/* ------------------------------------------------------------ */
@@ -966,6 +956,7 @@ static int musb_gadget_enable(struct usb_ep *ep,
966 956
967 musb_ep->desc = desc; 957 musb_ep->desc = desc;
968 musb_ep->busy = 0; 958 musb_ep->busy = 0;
959 musb_ep->wedged = 0;
969 status = 0; 960 status = 0;
970 961
971 pr_debug("%s periph: enabled %s for %s %s, %smaxpacket %d\n", 962 pr_debug("%s periph: enabled %s for %s %s, %smaxpacket %d\n",
@@ -1220,7 +1211,7 @@ done:
1220 * 1211 *
1221 * exported to ep0 code 1212 * exported to ep0 code
1222 */ 1213 */
1223int musb_gadget_set_halt(struct usb_ep *ep, int value) 1214static int musb_gadget_set_halt(struct usb_ep *ep, int value)
1224{ 1215{
1225 struct musb_ep *musb_ep = to_musb_ep(ep); 1216 struct musb_ep *musb_ep = to_musb_ep(ep);
1226 u8 epnum = musb_ep->current_epnum; 1217 u8 epnum = musb_ep->current_epnum;
@@ -1262,7 +1253,8 @@ int musb_gadget_set_halt(struct usb_ep *ep, int value)
1262 goto done; 1253 goto done;
1263 } 1254 }
1264 } 1255 }
1265 } 1256 } else
1257 musb_ep->wedged = 0;
1266 1258
1267 /* set/clear the stall and toggle bits */ 1259 /* set/clear the stall and toggle bits */
1268 DBG(2, "%s: %s stall\n", ep->name, value ? "set" : "clear"); 1260 DBG(2, "%s: %s stall\n", ep->name, value ? "set" : "clear");
@@ -1301,6 +1293,21 @@ done:
1301 return status; 1293 return status;
1302} 1294}
1303 1295
1296/*
1297 * Sets the halt feature with the clear requests ignored
1298 */
1299static int musb_gadget_set_wedge(struct usb_ep *ep)
1300{
1301 struct musb_ep *musb_ep = to_musb_ep(ep);
1302
1303 if (!ep)
1304 return -EINVAL;
1305
1306 musb_ep->wedged = 1;
1307
1308 return usb_ep_set_halt(ep);
1309}
1310
1304static int musb_gadget_fifo_status(struct usb_ep *ep) 1311static int musb_gadget_fifo_status(struct usb_ep *ep)
1305{ 1312{
1306 struct musb_ep *musb_ep = to_musb_ep(ep); 1313 struct musb_ep *musb_ep = to_musb_ep(ep);
@@ -1371,6 +1378,7 @@ static const struct usb_ep_ops musb_ep_ops = {
1371 .queue = musb_gadget_queue, 1378 .queue = musb_gadget_queue,
1372 .dequeue = musb_gadget_dequeue, 1379 .dequeue = musb_gadget_dequeue,
1373 .set_halt = musb_gadget_set_halt, 1380 .set_halt = musb_gadget_set_halt,
1381 .set_wedge = musb_gadget_set_wedge,
1374 .fifo_status = musb_gadget_fifo_status, 1382 .fifo_status = musb_gadget_fifo_status,
1375 .fifo_flush = musb_gadget_fifo_flush 1383 .fifo_flush = musb_gadget_fifo_flush
1376}; 1384};