diff options
Diffstat (limited to 'drivers/usb')
-rw-r--r-- | drivers/usb/musb/cppi_dma.c | 1 | ||||
-rw-r--r-- | drivers/usb/musb/musb_host.c | 227 |
2 files changed, 105 insertions, 123 deletions
diff --git a/drivers/usb/musb/cppi_dma.c b/drivers/usb/musb/cppi_dma.c index 30e24891ed62..1976e9b41800 100644 --- a/drivers/usb/musb/cppi_dma.c +++ b/drivers/usb/musb/cppi_dma.c | |||
@@ -579,6 +579,7 @@ cppi_next_tx_segment(struct musb *musb, struct cppi_channel *tx) | |||
579 | * trigger the "send a ZLP?" confusion. | 579 | * trigger the "send a ZLP?" confusion. |
580 | */ | 580 | */ |
581 | rndis = (maxpacket & 0x3f) == 0 | 581 | rndis = (maxpacket & 0x3f) == 0 |
582 | && length > maxpacket | ||
582 | && length < 0xffff | 583 | && length < 0xffff |
583 | && (length % maxpacket) != 0; | 584 | && (length % maxpacket) != 0; |
584 | 585 | ||
diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c index 1dfaaa6acfaf..db1b57415ec7 100644 --- a/drivers/usb/musb/musb_host.c +++ b/drivers/usb/musb/musb_host.c | |||
@@ -97,8 +97,8 @@ | |||
97 | 97 | ||
98 | 98 | ||
99 | static void musb_ep_program(struct musb *musb, u8 epnum, | 99 | static void musb_ep_program(struct musb *musb, u8 epnum, |
100 | struct urb *urb, unsigned int nOut, | 100 | struct urb *urb, int is_out, |
101 | u8 *buf, u32 len); | 101 | u8 *buf, u32 offset, u32 len); |
102 | 102 | ||
103 | /* | 103 | /* |
104 | * Clear TX fifo. Needed to avoid BABBLE errors. | 104 | * Clear TX fifo. Needed to avoid BABBLE errors. |
@@ -192,9 +192,10 @@ musb_start_urb(struct musb *musb, int is_in, struct musb_qh *qh) | |||
192 | { | 192 | { |
193 | u16 frame; | 193 | u16 frame; |
194 | u32 len; | 194 | u32 len; |
195 | void *buf; | ||
196 | void __iomem *mbase = musb->mregs; | 195 | void __iomem *mbase = musb->mregs; |
197 | struct urb *urb = next_urb(qh); | 196 | struct urb *urb = next_urb(qh); |
197 | void *buf = urb->transfer_buffer; | ||
198 | u32 offset = 0; | ||
198 | struct musb_hw_ep *hw_ep = qh->hw_ep; | 199 | struct musb_hw_ep *hw_ep = qh->hw_ep; |
199 | unsigned pipe = urb->pipe; | 200 | unsigned pipe = urb->pipe; |
200 | u8 address = usb_pipedevice(pipe); | 201 | u8 address = usb_pipedevice(pipe); |
@@ -217,7 +218,7 @@ musb_start_urb(struct musb *musb, int is_in, struct musb_qh *qh) | |||
217 | case USB_ENDPOINT_XFER_ISOC: | 218 | case USB_ENDPOINT_XFER_ISOC: |
218 | qh->iso_idx = 0; | 219 | qh->iso_idx = 0; |
219 | qh->frame = 0; | 220 | qh->frame = 0; |
220 | buf = urb->transfer_buffer + urb->iso_frame_desc[0].offset; | 221 | offset = urb->iso_frame_desc[0].offset; |
221 | len = urb->iso_frame_desc[0].length; | 222 | len = urb->iso_frame_desc[0].length; |
222 | break; | 223 | break; |
223 | default: /* bulk, interrupt */ | 224 | default: /* bulk, interrupt */ |
@@ -235,14 +236,14 @@ musb_start_urb(struct musb *musb, int is_in, struct musb_qh *qh) | |||
235 | case USB_ENDPOINT_XFER_ISOC: s = "-iso"; break; | 236 | case USB_ENDPOINT_XFER_ISOC: s = "-iso"; break; |
236 | default: s = "-intr"; break; | 237 | default: s = "-intr"; break; |
237 | }; s; }), | 238 | }; s; }), |
238 | epnum, buf, len); | 239 | epnum, buf + offset, len); |
239 | 240 | ||
240 | /* Configure endpoint */ | 241 | /* Configure endpoint */ |
241 | if (is_in || hw_ep->is_shared_fifo) | 242 | if (is_in || hw_ep->is_shared_fifo) |
242 | hw_ep->in_qh = qh; | 243 | hw_ep->in_qh = qh; |
243 | else | 244 | else |
244 | hw_ep->out_qh = qh; | 245 | hw_ep->out_qh = qh; |
245 | musb_ep_program(musb, epnum, urb, !is_in, buf, len); | 246 | musb_ep_program(musb, epnum, urb, !is_in, buf, offset, len); |
246 | 247 | ||
247 | /* transmit may have more work: start it when it is time */ | 248 | /* transmit may have more work: start it when it is time */ |
248 | if (is_in) | 249 | if (is_in) |
@@ -253,7 +254,6 @@ musb_start_urb(struct musb *musb, int is_in, struct musb_qh *qh) | |||
253 | case USB_ENDPOINT_XFER_ISOC: | 254 | case USB_ENDPOINT_XFER_ISOC: |
254 | case USB_ENDPOINT_XFER_INT: | 255 | case USB_ENDPOINT_XFER_INT: |
255 | DBG(3, "check whether there's still time for periodic Tx\n"); | 256 | DBG(3, "check whether there's still time for periodic Tx\n"); |
256 | qh->iso_idx = 0; | ||
257 | frame = musb_readw(mbase, MUSB_FRAME); | 257 | frame = musb_readw(mbase, MUSB_FRAME); |
258 | /* FIXME this doesn't implement that scheduling policy ... | 258 | /* FIXME this doesn't implement that scheduling policy ... |
259 | * or handle framecounter wrapping | 259 | * or handle framecounter wrapping |
@@ -634,14 +634,68 @@ musb_rx_reinit(struct musb *musb, struct musb_qh *qh, struct musb_hw_ep *ep) | |||
634 | ep->rx_reinit = 0; | 634 | ep->rx_reinit = 0; |
635 | } | 635 | } |
636 | 636 | ||
637 | static bool musb_tx_dma_program(struct dma_controller *dma, | ||
638 | struct musb_hw_ep *hw_ep, struct musb_qh *qh, | ||
639 | struct urb *urb, u32 offset, u32 length) | ||
640 | { | ||
641 | struct dma_channel *channel = hw_ep->tx_channel; | ||
642 | void __iomem *epio = hw_ep->regs; | ||
643 | u16 pkt_size = qh->maxpacket; | ||
644 | u16 csr; | ||
645 | u8 mode; | ||
646 | |||
647 | #ifdef CONFIG_USB_INVENTRA_DMA | ||
648 | if (length > channel->max_len) | ||
649 | length = channel->max_len; | ||
650 | |||
651 | csr = musb_readw(epio, MUSB_TXCSR); | ||
652 | if (length > pkt_size) { | ||
653 | mode = 1; | ||
654 | csr |= MUSB_TXCSR_AUTOSET | ||
655 | | MUSB_TXCSR_DMAMODE | ||
656 | | MUSB_TXCSR_DMAENAB; | ||
657 | } else { | ||
658 | mode = 0; | ||
659 | csr &= ~(MUSB_TXCSR_AUTOSET | MUSB_TXCSR_DMAMODE); | ||
660 | csr |= MUSB_TXCSR_DMAENAB; /* against programmer's guide */ | ||
661 | } | ||
662 | channel->desired_mode = mode; | ||
663 | musb_writew(epio, MUSB_TXCSR, csr); | ||
664 | #else | ||
665 | if (!is_cppi_enabled() && !tusb_dma_omap()) | ||
666 | return false; | ||
667 | |||
668 | channel->actual_len = 0; | ||
669 | |||
670 | /* | ||
671 | * TX uses "RNDIS" mode automatically but needs help | ||
672 | * to identify the zero-length-final-packet case. | ||
673 | */ | ||
674 | mode = (urb->transfer_flags & URB_ZERO_PACKET) ? 1 : 0; | ||
675 | #endif | ||
676 | |||
677 | qh->segsize = length; | ||
678 | |||
679 | if (!dma->channel_program(channel, pkt_size, mode, | ||
680 | urb->transfer_dma + offset, length)) { | ||
681 | dma->channel_release(channel); | ||
682 | hw_ep->tx_channel = NULL; | ||
683 | |||
684 | csr = musb_readw(epio, MUSB_TXCSR); | ||
685 | csr &= ~(MUSB_TXCSR_AUTOSET | MUSB_TXCSR_DMAENAB); | ||
686 | musb_writew(epio, MUSB_TXCSR, csr | MUSB_TXCSR_H_WZC_BITS); | ||
687 | return false; | ||
688 | } | ||
689 | return true; | ||
690 | } | ||
637 | 691 | ||
638 | /* | 692 | /* |
639 | * Program an HDRC endpoint as per the given URB | 693 | * Program an HDRC endpoint as per the given URB |
640 | * Context: irqs blocked, controller lock held | 694 | * Context: irqs blocked, controller lock held |
641 | */ | 695 | */ |
642 | static void musb_ep_program(struct musb *musb, u8 epnum, | 696 | static void musb_ep_program(struct musb *musb, u8 epnum, |
643 | struct urb *urb, unsigned int is_out, | 697 | struct urb *urb, int is_out, |
644 | u8 *buf, u32 len) | 698 | u8 *buf, u32 offset, u32 len) |
645 | { | 699 | { |
646 | struct dma_controller *dma_controller; | 700 | struct dma_controller *dma_controller; |
647 | struct dma_channel *dma_channel; | 701 | struct dma_channel *dma_channel; |
@@ -768,82 +822,9 @@ static void musb_ep_program(struct musb *musb, u8 epnum, | |||
768 | else | 822 | else |
769 | load_count = min((u32) packet_sz, len); | 823 | load_count = min((u32) packet_sz, len); |
770 | 824 | ||
771 | #ifdef CONFIG_USB_INVENTRA_DMA | 825 | if (dma_channel && musb_tx_dma_program(dma_controller, |
772 | if (dma_channel) { | 826 | hw_ep, qh, urb, offset, len)) |
773 | qh->segsize = min(len, dma_channel->max_len); | 827 | load_count = 0; |
774 | if (qh->segsize <= packet_sz) | ||
775 | dma_channel->desired_mode = 0; | ||
776 | else | ||
777 | dma_channel->desired_mode = 1; | ||
778 | |||
779 | if (dma_channel->desired_mode == 0) { | ||
780 | /* Against the programming guide */ | ||
781 | csr |= (MUSB_TXCSR_DMAENAB); | ||
782 | } else | ||
783 | csr |= (MUSB_TXCSR_AUTOSET | ||
784 | | MUSB_TXCSR_DMAENAB | ||
785 | | MUSB_TXCSR_DMAMODE); | ||
786 | musb_writew(epio, MUSB_TXCSR, csr); | ||
787 | |||
788 | dma_ok = dma_controller->channel_program( | ||
789 | dma_channel, packet_sz, | ||
790 | dma_channel->desired_mode, | ||
791 | urb->transfer_dma, | ||
792 | qh->segsize); | ||
793 | if (dma_ok) { | ||
794 | load_count = 0; | ||
795 | } else { | ||
796 | dma_controller->channel_release(dma_channel); | ||
797 | if (is_out) | ||
798 | hw_ep->tx_channel = NULL; | ||
799 | else | ||
800 | hw_ep->rx_channel = NULL; | ||
801 | dma_channel = NULL; | ||
802 | |||
803 | /* | ||
804 | * The programming guide says that we must | ||
805 | * clear the DMAENAB bit before DMAMODE... | ||
806 | */ | ||
807 | csr = musb_readw(epio, MUSB_TXCSR); | ||
808 | csr &= ~(MUSB_TXCSR_DMAENAB | ||
809 | | MUSB_TXCSR_AUTOSET); | ||
810 | musb_writew(epio, MUSB_TXCSR, csr); | ||
811 | csr &= ~MUSB_TXCSR_DMAMODE; | ||
812 | musb_writew(epio, MUSB_TXCSR, csr); | ||
813 | } | ||
814 | } | ||
815 | #endif | ||
816 | |||
817 | /* candidate for DMA */ | ||
818 | if ((is_cppi_enabled() || tusb_dma_omap()) && dma_channel) { | ||
819 | |||
820 | /* Defer enabling DMA */ | ||
821 | dma_channel->actual_len = 0L; | ||
822 | qh->segsize = len; | ||
823 | |||
824 | /* TX uses "rndis" mode automatically, but needs help | ||
825 | * to identify the zero-length-final-packet case. | ||
826 | */ | ||
827 | dma_ok = dma_controller->channel_program( | ||
828 | dma_channel, packet_sz, | ||
829 | (urb->transfer_flags | ||
830 | & URB_ZERO_PACKET) | ||
831 | == URB_ZERO_PACKET, | ||
832 | urb->transfer_dma, | ||
833 | qh->segsize); | ||
834 | if (dma_ok) { | ||
835 | load_count = 0; | ||
836 | } else { | ||
837 | dma_controller->channel_release(dma_channel); | ||
838 | hw_ep->tx_channel = NULL; | ||
839 | dma_channel = NULL; | ||
840 | |||
841 | /* REVISIT there's an error path here that | ||
842 | * needs handling: can't do dma, but | ||
843 | * there's no pio buffer address... | ||
844 | */ | ||
845 | } | ||
846 | } | ||
847 | 828 | ||
848 | if (load_count) { | 829 | if (load_count) { |
849 | /* PIO to load FIFO */ | 830 | /* PIO to load FIFO */ |
@@ -903,7 +884,7 @@ static void musb_ep_program(struct musb *musb, u8 epnum, | |||
903 | dma_channel, packet_sz, | 884 | dma_channel, packet_sz, |
904 | !(urb->transfer_flags | 885 | !(urb->transfer_flags |
905 | & URB_SHORT_NOT_OK), | 886 | & URB_SHORT_NOT_OK), |
906 | urb->transfer_dma, | 887 | urb->transfer_dma + offset, |
907 | qh->segsize); | 888 | qh->segsize); |
908 | if (!dma_ok) { | 889 | if (!dma_ok) { |
909 | dma_controller->channel_release( | 890 | dma_controller->channel_release( |
@@ -1146,8 +1127,8 @@ void musb_host_tx(struct musb *musb, u8 epnum) | |||
1146 | int pipe; | 1127 | int pipe; |
1147 | bool done = false; | 1128 | bool done = false; |
1148 | u16 tx_csr; | 1129 | u16 tx_csr; |
1149 | size_t wLength = 0; | 1130 | size_t length = 0; |
1150 | u8 *buf = NULL; | 1131 | size_t offset = 0; |
1151 | struct urb *urb; | 1132 | struct urb *urb; |
1152 | struct musb_hw_ep *hw_ep = musb->endpoints + epnum; | 1133 | struct musb_hw_ep *hw_ep = musb->endpoints + epnum; |
1153 | void __iomem *epio = hw_ep->regs; | 1134 | void __iomem *epio = hw_ep->regs; |
@@ -1165,7 +1146,7 @@ void musb_host_tx(struct musb *musb, u8 epnum) | |||
1165 | /* with CPPI, DMA sometimes triggers "extra" irqs */ | 1146 | /* with CPPI, DMA sometimes triggers "extra" irqs */ |
1166 | if (!urb) { | 1147 | if (!urb) { |
1167 | DBG(4, "extra TX%d ready, csr %04x\n", epnum, tx_csr); | 1148 | DBG(4, "extra TX%d ready, csr %04x\n", epnum, tx_csr); |
1168 | goto finish; | 1149 | return; |
1169 | } | 1150 | } |
1170 | 1151 | ||
1171 | pipe = urb->pipe; | 1152 | pipe = urb->pipe; |
@@ -1202,7 +1183,7 @@ void musb_host_tx(struct musb *musb, u8 epnum) | |||
1202 | musb_writew(epio, MUSB_TXCSR, | 1183 | musb_writew(epio, MUSB_TXCSR, |
1203 | MUSB_TXCSR_H_WZC_BITS | 1184 | MUSB_TXCSR_H_WZC_BITS |
1204 | | MUSB_TXCSR_TXPKTRDY); | 1185 | | MUSB_TXCSR_TXPKTRDY); |
1205 | goto finish; | 1186 | return; |
1206 | } | 1187 | } |
1207 | 1188 | ||
1208 | if (status) { | 1189 | if (status) { |
@@ -1234,8 +1215,7 @@ void musb_host_tx(struct musb *musb, u8 epnum) | |||
1234 | /* second cppi case */ | 1215 | /* second cppi case */ |
1235 | if (dma_channel_status(dma) == MUSB_DMA_STATUS_BUSY) { | 1216 | if (dma_channel_status(dma) == MUSB_DMA_STATUS_BUSY) { |
1236 | DBG(4, "extra TX%d ready, csr %04x\n", epnum, tx_csr); | 1217 | DBG(4, "extra TX%d ready, csr %04x\n", epnum, tx_csr); |
1237 | goto finish; | 1218 | return; |
1238 | |||
1239 | } | 1219 | } |
1240 | 1220 | ||
1241 | if (is_dma_capable() && dma && !status) { | 1221 | if (is_dma_capable() && dma && !status) { |
@@ -1299,25 +1279,25 @@ void musb_host_tx(struct musb *musb, u8 epnum) | |||
1299 | } | 1279 | } |
1300 | } | 1280 | } |
1301 | 1281 | ||
1302 | /* REVISIT this looks wrong... */ | ||
1303 | if (!status || dma || usb_pipeisoc(pipe)) { | 1282 | if (!status || dma || usb_pipeisoc(pipe)) { |
1304 | if (dma) | 1283 | if (dma) |
1305 | wLength = dma->actual_len; | 1284 | length = dma->actual_len; |
1306 | else | 1285 | else |
1307 | wLength = qh->segsize; | 1286 | length = qh->segsize; |
1308 | qh->offset += wLength; | 1287 | qh->offset += length; |
1309 | 1288 | ||
1310 | if (usb_pipeisoc(pipe)) { | 1289 | if (usb_pipeisoc(pipe)) { |
1311 | struct usb_iso_packet_descriptor *d; | 1290 | struct usb_iso_packet_descriptor *d; |
1312 | 1291 | ||
1313 | d = urb->iso_frame_desc + qh->iso_idx; | 1292 | d = urb->iso_frame_desc + qh->iso_idx; |
1314 | d->actual_length = qh->segsize; | 1293 | d->actual_length = length; |
1294 | d->status = status; | ||
1315 | if (++qh->iso_idx >= urb->number_of_packets) { | 1295 | if (++qh->iso_idx >= urb->number_of_packets) { |
1316 | done = true; | 1296 | done = true; |
1317 | } else { | 1297 | } else { |
1318 | d++; | 1298 | d++; |
1319 | buf = urb->transfer_buffer + d->offset; | 1299 | offset = d->offset; |
1320 | wLength = d->length; | 1300 | length = d->length; |
1321 | } | 1301 | } |
1322 | } else if (dma) { | 1302 | } else if (dma) { |
1323 | done = true; | 1303 | done = true; |
@@ -1330,10 +1310,8 @@ void musb_host_tx(struct musb *musb, u8 epnum) | |||
1330 | & URB_ZERO_PACKET)) | 1310 | & URB_ZERO_PACKET)) |
1331 | done = true; | 1311 | done = true; |
1332 | if (!done) { | 1312 | if (!done) { |
1333 | buf = urb->transfer_buffer | 1313 | offset = qh->offset; |
1334 | + qh->offset; | 1314 | length = urb->transfer_buffer_length - offset; |
1335 | wLength = urb->transfer_buffer_length | ||
1336 | - qh->offset; | ||
1337 | } | 1315 | } |
1338 | } | 1316 | } |
1339 | } | 1317 | } |
@@ -1352,28 +1330,31 @@ void musb_host_tx(struct musb *musb, u8 epnum) | |||
1352 | urb->status = status; | 1330 | urb->status = status; |
1353 | urb->actual_length = qh->offset; | 1331 | urb->actual_length = qh->offset; |
1354 | musb_advance_schedule(musb, urb, hw_ep, USB_DIR_OUT); | 1332 | musb_advance_schedule(musb, urb, hw_ep, USB_DIR_OUT); |
1333 | return; | ||
1334 | } else if (usb_pipeisoc(pipe) && dma) { | ||
1335 | if (musb_tx_dma_program(musb->dma_controller, hw_ep, qh, urb, | ||
1336 | offset, length)) | ||
1337 | return; | ||
1338 | } else if (tx_csr & MUSB_TXCSR_DMAENAB) { | ||
1339 | DBG(1, "not complete, but DMA enabled?\n"); | ||
1340 | return; | ||
1341 | } | ||
1355 | 1342 | ||
1356 | } else if (!(tx_csr & MUSB_TXCSR_DMAENAB)) { | 1343 | /* |
1357 | /* WARN_ON(!buf); */ | 1344 | * PIO: start next packet in this URB. |
1358 | 1345 | * | |
1359 | /* REVISIT: some docs say that when hw_ep->tx_double_buffered, | 1346 | * REVISIT: some docs say that when hw_ep->tx_double_buffered, |
1360 | * (and presumably, fifo is not half-full) we should write TWO | 1347 | * (and presumably, FIFO is not half-full) we should write *two* |
1361 | * packets before updating TXCSR ... other docs disagree ... | 1348 | * packets before updating TXCSR; other docs disagree... |
1362 | */ | 1349 | */ |
1363 | /* PIO: start next packet in this URB */ | 1350 | if (length > qh->maxpacket) |
1364 | if (wLength > qh->maxpacket) | 1351 | length = qh->maxpacket; |
1365 | wLength = qh->maxpacket; | 1352 | musb_write_fifo(hw_ep, length, urb->transfer_buffer + offset); |
1366 | musb_write_fifo(hw_ep, wLength, buf); | 1353 | qh->segsize = length; |
1367 | qh->segsize = wLength; | ||
1368 | |||
1369 | musb_ep_select(mbase, epnum); | ||
1370 | musb_writew(epio, MUSB_TXCSR, | ||
1371 | MUSB_TXCSR_H_WZC_BITS | MUSB_TXCSR_TXPKTRDY); | ||
1372 | } else | ||
1373 | DBG(1, "not complete, but dma enabled?\n"); | ||
1374 | 1354 | ||
1375 | finish: | 1355 | musb_ep_select(mbase, epnum); |
1376 | return; | 1356 | musb_writew(epio, MUSB_TXCSR, |
1357 | MUSB_TXCSR_H_WZC_BITS | MUSB_TXCSR_TXPKTRDY); | ||
1377 | } | 1358 | } |
1378 | 1359 | ||
1379 | 1360 | ||