diff options
author | Mian Yousaf Kaukab <mian.yousaf.kaukab@stericsson.com> | 2011-03-11 14:57:36 +0100 |
---|---|---|
committer | Robert Marklund <robert.marklund@stericsson.com> | 2011-10-05 11:16:23 +0200 |
commit | 6bf61d5e56bc1bc2c94e9bfb24dd5e03dc20ba5f (patch) | |
tree | 8c9b39716079662b8109dd840d61e8ef0cf7ba33 /drivers/usb/musb/musb_host.c | |
parent | 2c804919b0c02e746b82a4bc0af646b4cec21f5b (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.c | 25 |
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 */ |