aboutsummaryrefslogtreecommitdiff
path: root/drivers/usb
diff options
context:
space:
mode:
authorPraveena Nadahally <praveen.nadahally@stericsson.com>2011-01-20 22:41:46 +0530
committerSrinidhi KASAGAR <srinidhi.kasagar@stericsson.com>2011-01-21 12:44:48 +0100
commitcd35a84d17b55796ac16e4acb6930a4a3548e357 (patch)
treeea11824e57e1cf00bc7653651214c924313849ce /drivers/usb
parentc2b6820bb8d3e4cf47b64f6395a6c6e8414e60c5 (diff)
ARM: ux500: USB: Update USB DMA to handle Host mode ACM data
Update the USB DMA to handle the host mode ACM IN data. In this case, the size of the incoming data is unknown. The musb code is updated to handle this scenario. ST-Ericsson ID: 283501 Change-Id: I7ab3b89768fa9a680c26825266d8e24e3e1cdf15 Signed-off-by: Praveena Nadahally <praveen.nadahally@stericsson.com> Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/13086 Reviewed-by: Srinidhi KASAGAR <srinidhi.kasagar@stericsson.com>
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/musb/musb_dma.h4
-rw-r--r--drivers/usb/musb/musb_host.c227
2 files changed, 8 insertions, 223 deletions
diff --git a/drivers/usb/musb/musb_dma.h b/drivers/usb/musb/musb_dma.h
index 916065ba9e7..f6b716ff3de 100644
--- a/drivers/usb/musb/musb_dma.h
+++ b/drivers/usb/musb/musb_dma.h
@@ -91,6 +91,10 @@ struct musb_hw_ep;
# endif
#endif
+#ifdef CONFIG_USB_U8500_DMA
+#undef USE_MODE1
+#endif
+
/*
* DMA channel status ... updated by the dma controller driver whenever that
* status changes, and protected by the overall controller spinlock.
diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c
index 84aa48ed57e..fb63a33aa29 100644
--- a/drivers/usb/musb/musb_host.c
+++ b/drivers/usb/musb/musb_host.c
@@ -910,37 +910,6 @@ static void musb_ep_program(struct musb *musb, u8 epnum,
}
/* kick things off */
-#ifdef CONFIG_USB_U8500_DMA
-
- if ((len >= packet_sz) && dma_channel) {
- if (dma_channel) {
- dma_channel->actual_len = 0L;
- qh->segsize = len;
-
- /* AUTOREQ is in a DMA register */
- musb_writew(hw_ep->regs, MUSB_RXCSR, csr);
- csr = musb_readw(hw_ep->regs,
- MUSB_RXCSR);
-
- /* unless caller treats short rx transfers as
- * errors, we dare not queue multiple transfers.
- */
- dma_ok = dma_controller->channel_program(
- dma_channel, packet_sz,
- !(urb->transfer_flags
- & URB_SHORT_NOT_OK),
- urb->transfer_dma + offset,
- packet_sz);
- if (!dma_ok) {
- dma_controller->channel_release(
- dma_channel);
- hw_ep->rx_channel = NULL;
- dma_channel = NULL;
- } else
- csr |= MUSB_RXCSR_DMAENAB;
- }
- }
-#else
if ((is_cppi_enabled() || tusb_dma_omap()) && dma_channel) {
/* candidate for DMA */
if (dma_channel) {
@@ -970,7 +939,6 @@ static void musb_ep_program(struct musb *musb, u8 epnum,
csr |= MUSB_RXCSR_DMAENAB;
}
}
-#endif
csr |= MUSB_RXCSR_H_REQPKT;
DBG(7, "RXCSR%d := %04x\n", epnum, csr);
musb_writew(hw_ep->regs, MUSB_RXCSR, csr);
@@ -1627,11 +1595,6 @@ void musb_host_rx(struct musb *musb, u8 epnum)
done = true;
goto finish;
}
-#ifdef CONFIG_USB_U8500_DMA
- if (urb->transfer_buffer_length < hw_ep->max_packet_sz_rx)
- goto u8500_no_dma;
-#endif
-
if (unlikely(dma_channel_status(dma) == MUSB_DMA_STATUS_BUSY)) {
/* SHOULD NEVER HAPPEN ... but at least DaVinci has done it */
ERR("RX%d dma busy, csr %04x\n", epnum, rx_csr);
@@ -1645,7 +1608,7 @@ void musb_host_rx(struct musb *musb, u8 epnum)
/* FIXME this is _way_ too much in-line logic for Mentor DMA */
-#ifndef CONFIG_USB_INVENTRA_DMA
+#if !defined(CONFIG_USB_INVENTRA_DMA) && !defined(CONFIG_USB_U8500_DMA)
if (rx_csr & MUSB_RXCSR_H_REQPKT) {
/* REVISIT this happened for a while on some short reads...
* the cleanup still needs investigation... looks bad...
@@ -1669,8 +1632,6 @@ void musb_host_rx(struct musb *musb, u8 epnum)
}
#endif
-#ifdef CONFIG_USB_U8500_DMA
-
if (dma && (rx_csr & MUSB_RXCSR_DMAENAB)) {
xfer_len = dma->actual_len;
@@ -1680,183 +1641,7 @@ void musb_host_rx(struct musb *musb, u8 epnum)
| MUSB_RXCSR_RXPKTRDY);
musb_writew(hw_ep->regs, MUSB_RXCSR, val);
- if (usb_pipeisoc(pipe)) {
- struct usb_iso_packet_descriptor *d;
-
- d = urb->iso_frame_desc + qh->iso_idx;
- d->actual_length = xfer_len;
-
- /* even if there was an error, we did the dma
- * for iso_frame_desc->length
- */
- if (d->status != EILSEQ && d->status != -EOVERFLOW)
- d->status = 0;
-
- if (++qh->iso_idx >= urb->number_of_packets)
- done = true;
- else
- done = false;
-
- } else {
- /* done if urb buffer is full or short packet is recd */
- done = (urb->actual_length + xfer_len >=
- urb->transfer_buffer_length
- || dma->actual_len < qh->maxpacket);
- }
-
- /* send IN token for next packet, without AUTOREQ */
- if (!done) {
- val |= MUSB_RXCSR_H_REQPKT;
- musb_writew(epio, MUSB_RXCSR,
- MUSB_RXCSR_H_WZC_BITS | val);
- }
-
- DBG(4, "ep %d dma %s, rxcsr %04x, rxcount %d\n", epnum,
- done ? "off" : "reset",
- musb_readw(epio, MUSB_RXCSR),
- musb_readw(epio, MUSB_RXCOUNT));
- } else if (urb->status == -EINPROGRESS) {
- /* if no errors, be sure a packet is ready for unloading */
- if (unlikely(!(rx_csr & MUSB_RXCSR_RXPKTRDY))) {
- status = -EPROTO;
- ERR("Rx interrupt with no errors or packet!\n");
-
- /* FIXME this is another "SHOULD NEVER HAPPEN" */
-
-/* SCRUB (RX) */
- /* do the proper sequence to abort the transfer */
- musb_ep_select(mbase, epnum);
- val &= ~MUSB_RXCSR_H_REQPKT;
- musb_writew(epio, MUSB_RXCSR, val);
- goto finish;
- }
-
- /* we are expecting IN packets */
- if (dma) {
- struct dma_controller *c;
- u16 rx_count;
- int ret, length;
- dma_addr_t buf;
-
- rx_count = musb_readw(epio, MUSB_RXCOUNT);
-
- DBG(2, "RX%d count %d, buffer 0x%x len %d/%d\n",
- epnum, rx_count,
- urb->transfer_dma
- + urb->actual_length,
- qh->offset,
- urb->transfer_buffer_length);
-
- c = musb->dma_controller;
-
- if (usb_pipeisoc(pipe)) {
- int d_status = 0;
- struct usb_iso_packet_descriptor *d;
-
- d = urb->iso_frame_desc + qh->iso_idx;
-
- if (iso_err) {
- d_status = -EILSEQ;
- urb->error_count++;
- }
- if (rx_count > d->length) {
- if (d_status == 0) {
- d_status = -EOVERFLOW;
- urb->error_count++;
- }
- DBG(2, "** OVERFLOW %d into %d\n",\
- rx_count, d->length);
-
- length = d->length;
- } else
- length = rx_count;
- d->status = d_status;
- buf = urb->transfer_dma + d->offset;
- } else {
- length = rx_count;
- buf = urb->transfer_dma +
- urb->actual_length;
- }
-
- dma->desired_mode = 0;
-#ifdef USE_MODE1
- /* because of the issue below, mode 1 will
- * only rarely behave with correct semantics.
- */
- if ((urb->transfer_flags &
- URB_SHORT_NOT_OK)
- && (urb->transfer_buffer_length -
- urb->actual_length)
- > qh->maxpacket)
- dma->desired_mode = 1;
- if (rx_count < hw_ep->max_packet_sz_rx) {
- length = rx_count;
- dma->desired_mode = 0;
- } else {
- length = urb->transfer_buffer_length;
- }
-#endif
-
-/* Disadvantage of using mode 1:
- * It's basically usable only for mass storage class; essentially all
- * other protocols also terminate transfers on short packets.
- *
- * Details:
- * An extra IN token is sent at the end of the transfer (due to AUTOREQ)
- * If you try to use mode 1 for (transfer_buffer_length - 512), and try
- * to use the extra IN token to grab the last packet using mode 0, then
- * the problem is that you cannot be sure when the device will send the
- * last packet and RxPktRdy set. Sometimes the packet is recd too soon
- * such that it gets lost when RxCSR is re-set at the end of the mode 1
- * transfer, while sometimes it is recd just a little late so that if you
- * try to configure for mode 0 soon after the mode 1 transfer is
- * completed, you will find rxcount 0. Okay, so you might think why not
- * wait for an interrupt when the pkt is recd. Well, you won't get any!
- */
-
- val = musb_readw(epio, MUSB_RXCSR);
- val &= ~MUSB_RXCSR_H_REQPKT;
-
- if (dma->desired_mode == 0)
- val &= ~MUSB_RXCSR_H_AUTOREQ;
- else
- val |= MUSB_RXCSR_H_AUTOREQ;
- val |= MUSB_RXCSR_DMAENAB;
-
- /* autoclear shouldn't be set in high bandwidth */
- if (qh->hb_mult == 1)
- val |= MUSB_RXCSR_AUTOCLEAR;
-
- musb_writew(epio, MUSB_RXCSR,
- MUSB_RXCSR_H_WZC_BITS | val);
-
- /* REVISIT if when actual_length != 0,
- * transfer_buffer_length needs to be
- * adjusted first...
- */
- ret = c->channel_program(
- dma, qh->maxpacket,
- dma->desired_mode, buf, length);
-
- if (!ret) {
- c->channel_release(dma);
- hw_ep->rx_channel = NULL;
- dma = NULL;
- /* REVISIT reset CSR */
- }
- }
-
-#else
- if (dma && (rx_csr & MUSB_RXCSR_DMAENAB)) {
- xfer_len = dma->actual_len;
-
- val &= ~(MUSB_RXCSR_DMAENAB
- | MUSB_RXCSR_H_AUTOREQ
- | MUSB_RXCSR_AUTOCLEAR
- | MUSB_RXCSR_RXPKTRDY);
- musb_writew(hw_ep->regs, MUSB_RXCSR, val);
-
-#ifdef CONFIG_USB_INVENTRA_DMA
+#if defined(CONFIG_USB_INVENTRA_DMA) || defined(CONFIG_USB_U8500_DMA)
if (usb_pipeisoc(pipe)) {
struct usb_iso_packet_descriptor *d;
@@ -1912,7 +1697,7 @@ void musb_host_rx(struct musb *musb, u8 epnum)
}
/* we are expecting IN packets */
-#ifdef CONFIG_USB_INVENTRA_DMA
+#if defined(CONFIG_USB_INVENTRA_DMA) || defined(CONFIG_USB_U8500_DMA)
if (dma) {
struct dma_controller *c;
u16 rx_count;
@@ -2026,13 +1811,9 @@ void musb_host_rx(struct musb *musb, u8 epnum)
/* REVISIT reset CSR */
}
}
-#endif /* Mentor DMA */
-#endif
+#endif /* Mentor DMA || U8500 DMA */
if (!dma) {
-#ifdef CONFIG_USB_U8500_DMA
-u8500_no_dma:
-#endif
done = musb_host_packet_rx(musb, urb,
epnum, iso_err);
DBG(6, "read %spacket\n", done ? "last " : "");