summaryrefslogtreecommitdiff
path: root/drivers/usb/musb/musb_host.c
diff options
context:
space:
mode:
authorMian Yousaf Kaukab <mian.yousaf.kaukab@stericsson.com>2011-03-11 14:57:36 +0100
committerRobert Marklund <robert.marklund@stericsson.com>2011-10-05 11:16:23 +0200
commit6bf61d5e56bc1bc2c94e9bfb24dd5e03dc20ba5f (patch)
tree8c9b39716079662b8109dd840d61e8ef0cf7ba33 /drivers/usb/musb/musb_host.c
parent2c804919b0c02e746b82a4bc0af646b4cec21f5b (diff)
usb: musb: ux500: add ux500 specific code for gadget side
Although U8500 and U5500 platforms use paltform dma, Inventra dma specific code can work for them for the most part. Only difference is for the Rx path where this patch is making use of request->short_not_ok to select dma mode. usb: musb: ux500: add dma name for ux500 usb: musb: ux500: add dma glue layer for ux500 DMA is mainly intended for mass storage class. Unaligned sizes and buffers are not supported. usb: musb: ux500: add configuration and build options for ux500 dma usb: musb: clear AUTOSET while clearing DMAENAB On the completion of tx dma, dma is disabled by clearing MUSB_TXCSR_DMAENAB in TXCSR. If MUSB_TXCSR_AUTOSET was set in txstate() it will remain set although it is not needed in PIO mode. Clear it as soon as it is not needed. usb: musb: ux500: copy dma mask from platform device to musb device musb code checks dma mask before calling dma hooks. usb: musb: do not release dma channel on channel_program failure Musb hcd releases dma channel (hw_ep->tx_channel / hw_ep->rx_channel ) if ->channel_program() fails. A null hw_ep->tx_channel is then used to continue the transfer in pio mode. Next call to musb_ep_program() will try to allocate the dma channel again. This patch allows the transfer to continue in pio mode if ->channel_program() fails without releasing the dma channel. usb: musb: restore rxcsr on channel_program failure Rxcsr is configured for dma transfer before calling ->channel_program(). Restore rxcsr if ->channel_program() fails. usb: musb: ux500: enable host side dma support Host side dma support for ux500 is enabled by piggybacking on Inventra dma support. Signed-off-by: Mian Yousaf Kaukab <mian.yousaf.kaukab@stericsson.com>
Diffstat (limited to 'drivers/usb/musb/musb_host.c')
-rw-r--r--drivers/usb/musb/musb_host.c25
1 files changed, 11 insertions, 14 deletions
diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c
index 8b2473fa0f4..fbed2b34892 100644
--- a/drivers/usb/musb/musb_host.c
+++ b/drivers/usb/musb/musb_host.c
@@ -290,7 +290,7 @@ start:
dev_dbg(musb->controller, "Start TX%d %s\n", epnum,
hw_ep->tx_channel ? "dma" : "pio");
- if (!hw_ep->tx_channel)
+ if (!hw_ep->tx_channel || hw_ep->do_tx_pio)
musb_h_tx_start(hw_ep);
else if (is_cppi_enabled() || tusb_dma_omap())
musb_h_tx_dma_start(hw_ep);
@@ -615,7 +615,7 @@ static bool musb_tx_dma_program(struct dma_controller *dma,
u16 csr;
u8 mode;
-#ifdef CONFIG_USB_INVENTRA_DMA
+#if defined(CONFIG_USB_INVENTRA_DMA) || defined(CONFIG_USB_UX500_DMA)
if (length > channel->max_len)
length = channel->max_len;
@@ -656,8 +656,6 @@ static bool musb_tx_dma_program(struct dma_controller *dma,
if (!dma->channel_program(channel, pkt_size, mode,
urb->transfer_dma + offset, length)) {
- dma->channel_release(channel);
- hw_ep->tx_channel = NULL;
csr = musb_readw(epio, MUSB_TXCSR);
csr &= ~(MUSB_TXCSR_AUTOSET | MUSB_TXCSR_DMAENAB);
@@ -792,11 +790,11 @@ static void musb_ep_program(struct musb *musb, u8 epnum,
else
load_count = min((u32) packet_sz, len);
- if (dma_channel && musb_tx_dma_program(dma_controller,
+ if (!dma_channel || !musb_tx_dma_program(dma_controller,
hw_ep, qh, urb, offset, len))
- load_count = 0;
+ hw_ep->do_tx_pio = true;
- if (load_count) {
+ if (hw_ep->do_tx_pio) {
/* PIO to load FIFO */
qh->segsize = load_count;
musb_write_fifo(hw_ep, load_count, buf);
@@ -1100,7 +1098,7 @@ void musb_host_tx(struct musb *musb, u8 epnum)
struct urb *urb = next_urb(qh);
u32 status = 0;
void __iomem *mbase = musb->mregs;
- struct dma_channel *dma;
+ struct dma_channel *dma = NULL;
bool transfer_pending = false;
musb_ep_select(mbase, epnum);
@@ -1533,7 +1531,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_UX500_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...
@@ -1565,7 +1563,7 @@ void musb_host_rx(struct musb *musb, u8 epnum)
| 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_UX500_DMA)
if (usb_pipeisoc(pipe)) {
struct usb_iso_packet_descriptor *d;
@@ -1621,7 +1619,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_UX500_DMA)
if (dma) {
struct dma_controller *c;
u16 rx_count;
@@ -1729,10 +1727,9 @@ void musb_host_rx(struct musb *musb, u8 epnum)
dma->desired_mode, buf, length);
if (!ret) {
- c->channel_release(dma);
- hw_ep->rx_channel = NULL;
dma = NULL;
- /* REVISIT reset CSR */
+ /* Restore CSR */
+ musb_writew(epio, MUSB_RXCSR, rx_csr);
}
}
#endif /* Mentor DMA */