diff options
Diffstat (limited to 'meta/packages/linux/linux-omap-2.6.29/musb/0010-musb-sanitize-clearing-TXCSR-DMA-bits-take-2.patch')
-rw-r--r-- | meta/packages/linux/linux-omap-2.6.29/musb/0010-musb-sanitize-clearing-TXCSR-DMA-bits-take-2.patch | 361 |
1 files changed, 0 insertions, 361 deletions
diff --git a/meta/packages/linux/linux-omap-2.6.29/musb/0010-musb-sanitize-clearing-TXCSR-DMA-bits-take-2.patch b/meta/packages/linux/linux-omap-2.6.29/musb/0010-musb-sanitize-clearing-TXCSR-DMA-bits-take-2.patch deleted file mode 100644 index bcbe3bbe3..000000000 --- a/meta/packages/linux/linux-omap-2.6.29/musb/0010-musb-sanitize-clearing-TXCSR-DMA-bits-take-2.patch +++ /dev/null @@ -1,361 +0,0 @@ -From c99f4a68268801a2e2ffbef9766c3ac89e4fb22c Mon Sep 17 00:00:00 2001 -From: Sergei Shtylyov <sshtylyov-hkdhdckH98+B+jHODAdFcQ@public.gmane.org> -Date: Thu, 26 Mar 2009 18:27:47 -0700 -Subject: [PATCH] musb: sanitize clearing TXCSR DMA bits (take 2) - -The MUSB code clears TXCSR_DMAMODE incorrectly in several -places, either asserting that TXCSR_DMAENAB is clear (when -sometimes it isn't) or clearing both bits together. Recent -versions of the programmer's guide require DMAENAB to be -cleared first, although some older ones didn't. - -Fix this and while at it: - - - In musb_gadget::txstate(), stop clearing the AUTOSET - and DMAMODE bits for the CPPI case since they never - get set anyway (the former bit is reserved on DaVinci); - but do clear the DMAENAB bit on the DMA error path. - - - In musb_host::musb_ep_program(), remove the duplicate - DMA controller specific code code clearing the TXCSR - previous state, add the code to clear TXCSR DMA bits - on the Inventra DMA error path, to replace such code - (executed late) on the PIO path. - - - In musbhsdma::dma_channel_abort()/dma_controller_irq(), - add/use the 'offset' variable to avoid MUSB_EP_OFFSET() - invocations on every RXCSR/TXCSR access. - -[dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org: don't introduce CamelCase, -shrink diff] - -Signed-off-by: Sergei Shtylyov <sshtylyov-hkdhdckH98+B+jHODAdFcQ@public.gmane.org> -Signed-off-by: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org> ---- - drivers/usb/musb/musb_gadget.c | 33 +++++++++++------ - drivers/usb/musb/musb_host.c | 79 ++++++++++++++++------------------------ - drivers/usb/musb/musbhsdma.c | 59 ++++++++++++++++++------------ - 3 files changed, 90 insertions(+), 81 deletions(-) - -diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c -index c7ebd08..f79440c 100644 ---- a/drivers/usb/musb/musb_gadget.c -+++ b/drivers/usb/musb/musb_gadget.c -@@ -165,9 +165,15 @@ static void nuke(struct musb_ep *ep, const int status) - if (is_dma_capable() && ep->dma) { - struct dma_controller *c = ep->musb->dma_controller; - int value; -+ - if (ep->is_in) { -+ /* -+ * The programming guide says that we must not clear -+ * the DMAMODE bit before DMAENAB, so we only -+ * clear it in the second write... -+ */ - musb_writew(epio, MUSB_TXCSR, -- 0 | MUSB_TXCSR_FLUSHFIFO); -+ MUSB_TXCSR_DMAMODE | MUSB_TXCSR_FLUSHFIFO); - musb_writew(epio, MUSB_TXCSR, - 0 | MUSB_TXCSR_FLUSHFIFO); - } else { -@@ -230,7 +236,7 @@ static inline int max_ep_writesize(struct musb *musb, struct musb_ep *ep) - | IN token(s) are recd from Host. - | -> DMA interrupt on completion - | calls TxAvail. -- | -> stop DMA, ~DmaEenab, -+ | -> stop DMA, ~DMAENAB, - | -> set TxPktRdy for last short pkt or zlp - | -> Complete Request - | -> Continue next request (call txstate) -@@ -315,9 +321,17 @@ static void txstate(struct musb *musb, struct musb_request *req) - request->dma, request_size); - if (use_dma) { - if (musb_ep->dma->desired_mode == 0) { -- /* ASSERT: DMAENAB is clear */ -- csr &= ~(MUSB_TXCSR_AUTOSET | -- MUSB_TXCSR_DMAMODE); -+ /* -+ * We must not clear the DMAMODE bit -+ * before the DMAENAB bit -- and the -+ * latter doesn't always get cleared -+ * before we get here... -+ */ -+ csr &= ~(MUSB_TXCSR_AUTOSET -+ | MUSB_TXCSR_DMAENAB); -+ musb_writew(epio, MUSB_TXCSR, csr -+ | MUSB_TXCSR_P_WZC_BITS); -+ csr &= ~MUSB_TXCSR_DMAMODE; - csr |= (MUSB_TXCSR_DMAENAB | - MUSB_TXCSR_MODE); - /* against programming guide */ -@@ -334,10 +348,7 @@ static void txstate(struct musb *musb, struct musb_request *req) - - #elif defined(CONFIG_USB_TI_CPPI_DMA) - /* program endpoint CSR first, then setup DMA */ -- csr &= ~(MUSB_TXCSR_AUTOSET -- | MUSB_TXCSR_DMAMODE -- | MUSB_TXCSR_P_UNDERRUN -- | MUSB_TXCSR_TXPKTRDY); -+ csr &= ~(MUSB_TXCSR_P_UNDERRUN | MUSB_TXCSR_TXPKTRDY); - csr |= MUSB_TXCSR_MODE | MUSB_TXCSR_DMAENAB; - musb_writew(epio, MUSB_TXCSR, - (MUSB_TXCSR_P_WZC_BITS & ~MUSB_TXCSR_P_UNDERRUN) -@@ -364,8 +375,8 @@ static void txstate(struct musb *musb, struct musb_request *req) - if (!use_dma) { - c->channel_release(musb_ep->dma); - musb_ep->dma = NULL; -- /* ASSERT: DMAENAB clear */ -- csr &= ~(MUSB_TXCSR_DMAMODE | MUSB_TXCSR_MODE); -+ csr &= ~MUSB_TXCSR_DMAENAB; -+ musb_writew(epio, MUSB_TXCSR, csr); - /* invariant: prequest->buf is non-null */ - } - #elif defined(CONFIG_USB_TUSB_OMAP_DMA) -diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c -index a5d75aa..6591282 100644 ---- a/drivers/usb/musb/musb_host.c -+++ b/drivers/usb/musb/musb_host.c -@@ -590,10 +590,17 @@ musb_rx_reinit(struct musb *musb, struct musb_qh *qh, struct musb_hw_ep *ep) - csr = musb_readw(ep->regs, MUSB_TXCSR); - if (csr & MUSB_TXCSR_MODE) { - musb_h_tx_flush_fifo(ep); -+ csr = musb_readw(ep->regs, MUSB_TXCSR); - musb_writew(ep->regs, MUSB_TXCSR, -- MUSB_TXCSR_FRCDATATOG); -+ csr | MUSB_TXCSR_FRCDATATOG); - } -- /* clear mode (and everything else) to enable Rx */ -+ -+ /* -+ * Clear the MODE bit (and everything else) to enable Rx. -+ * NOTE: we mustn't clear the DMAMODE bit before DMAENAB. -+ */ -+ if (csr & MUSB_TXCSR_DMAMODE) -+ musb_writew(ep->regs, MUSB_TXCSR, MUSB_TXCSR_DMAMODE); - musb_writew(ep->regs, MUSB_TXCSR, 0); - - /* scrub all previous state, clearing toggle */ -@@ -690,12 +697,17 @@ static void musb_ep_program(struct musb *musb, u8 epnum, - - /* general endpoint setup */ - if (epnum) { -- /* ASSERT: TXCSR_DMAENAB was already cleared */ -- - /* flush all old state, set default */ - musb_h_tx_flush_fifo(hw_ep); -+ -+ /* -+ * We must not clear the DMAMODE bit before or in -+ * the same cycle with the DMAENAB bit, so we clear -+ * the latter first... -+ */ - csr &= ~(MUSB_TXCSR_H_NAKTIMEOUT -- | MUSB_TXCSR_DMAMODE -+ | MUSB_TXCSR_AUTOSET -+ | MUSB_TXCSR_DMAENAB - | MUSB_TXCSR_FRCDATATOG - | MUSB_TXCSR_H_RXSTALL - | MUSB_TXCSR_H_ERROR -@@ -703,16 +715,15 @@ static void musb_ep_program(struct musb *musb, u8 epnum, - ); - csr |= MUSB_TXCSR_MODE; - -- if (usb_gettoggle(urb->dev, -- qh->epnum, 1)) -+ if (usb_gettoggle(urb->dev, qh->epnum, 1)) - csr |= MUSB_TXCSR_H_WR_DATATOGGLE - | MUSB_TXCSR_H_DATATOGGLE; - else - csr |= MUSB_TXCSR_CLRDATATOG; - -- /* twice in case of double packet buffering */ - musb_writew(epio, MUSB_TXCSR, csr); - /* REVISIT may need to clear FLUSHFIFO ... */ -+ csr &= ~MUSB_TXCSR_DMAMODE; - musb_writew(epio, MUSB_TXCSR, csr); - csr = musb_readw(epio, MUSB_TXCSR); - } else { -@@ -755,34 +766,19 @@ static void musb_ep_program(struct musb *musb, u8 epnum, - - #ifdef CONFIG_USB_INVENTRA_DMA - if (dma_channel) { -- -- /* clear previous state */ -- csr = musb_readw(epio, MUSB_TXCSR); -- csr &= ~(MUSB_TXCSR_AUTOSET -- | MUSB_TXCSR_DMAMODE -- | MUSB_TXCSR_DMAENAB); -- csr |= MUSB_TXCSR_MODE; -- musb_writew(epio, MUSB_TXCSR, -- csr | MUSB_TXCSR_MODE); -- - qh->segsize = min(len, dma_channel->max_len); -- - if (qh->segsize <= packet_sz) - dma_channel->desired_mode = 0; - else - dma_channel->desired_mode = 1; - -- - if (dma_channel->desired_mode == 0) { -- csr &= ~(MUSB_TXCSR_AUTOSET -- | MUSB_TXCSR_DMAMODE); -+ /* Against the programming guide */ - csr |= (MUSB_TXCSR_DMAENAB); -- /* against programming guide */ - } else - csr |= (MUSB_TXCSR_AUTOSET - | MUSB_TXCSR_DMAENAB - | MUSB_TXCSR_DMAMODE); -- - musb_writew(epio, MUSB_TXCSR, csr); - - dma_ok = dma_controller->channel_program( -@@ -799,6 +795,17 @@ static void musb_ep_program(struct musb *musb, u8 epnum, - else - hw_ep->rx_channel = NULL; - dma_channel = NULL; -+ -+ /* -+ * The programming guide says that we must -+ * clear the DMAENAB bit before DMAMODE... -+ */ -+ csr = musb_readw(epio, MUSB_TXCSR); -+ csr &= ~(MUSB_TXCSR_DMAENAB -+ | MUSB_TXCSR_AUTOSET); -+ musb_writew(epio, MUSB_TXCSR, csr); -+ csr &= ~MUSB_TXCSR_DMAMODE; -+ musb_writew(epio, MUSB_TXCSR, csr); - } - } - #endif -@@ -806,18 +813,7 @@ static void musb_ep_program(struct musb *musb, u8 epnum, - /* candidate for DMA */ - if ((is_cppi_enabled() || tusb_dma_omap()) && dma_channel) { - -- /* program endpoint CSRs first, then setup DMA. -- * assume CPPI setup succeeds. -- * defer enabling dma. -- */ -- csr = musb_readw(epio, MUSB_TXCSR); -- csr &= ~(MUSB_TXCSR_AUTOSET -- | MUSB_TXCSR_DMAMODE -- | MUSB_TXCSR_DMAENAB); -- csr |= MUSB_TXCSR_MODE; -- musb_writew(epio, MUSB_TXCSR, -- csr | MUSB_TXCSR_MODE); -- -+ /* Defer enabling DMA */ - dma_channel->actual_len = 0L; - qh->segsize = len; - -@@ -846,20 +842,9 @@ static void musb_ep_program(struct musb *musb, u8 epnum, - } - - if (load_count) { -- /* ASSERT: TXCSR_DMAENAB was already cleared */ -- - /* PIO to load FIFO */ - qh->segsize = load_count; - musb_write_fifo(hw_ep, load_count, buf); -- csr = musb_readw(epio, MUSB_TXCSR); -- csr &= ~(MUSB_TXCSR_DMAENAB -- | MUSB_TXCSR_DMAMODE -- | MUSB_TXCSR_AUTOSET); -- /* write CSR */ -- csr |= MUSB_TXCSR_MODE; -- -- if (epnum) -- musb_writew(epio, MUSB_TXCSR, csr); - } - - /* re-enable interrupt */ -diff --git a/drivers/usb/musb/musbhsdma.c b/drivers/usb/musb/musbhsdma.c -index 8662e9e..40709c3 100644 ---- a/drivers/usb/musb/musbhsdma.c -+++ b/drivers/usb/musb/musbhsdma.c -@@ -195,30 +195,32 @@ static int dma_channel_abort(struct dma_channel *channel) - void __iomem *mbase = musb_channel->controller->base; - - u8 bchannel = musb_channel->idx; -+ int offset; - u16 csr; - - if (channel->status == MUSB_DMA_STATUS_BUSY) { - if (musb_channel->transmit) { -- -- csr = musb_readw(mbase, -- MUSB_EP_OFFSET(musb_channel->epnum, -- MUSB_TXCSR)); -- csr &= ~(MUSB_TXCSR_AUTOSET | -- MUSB_TXCSR_DMAENAB | -- MUSB_TXCSR_DMAMODE); -- musb_writew(mbase, -- MUSB_EP_OFFSET(musb_channel->epnum, MUSB_TXCSR), -- csr); -+ offset = MUSB_EP_OFFSET(musb_channel->epnum, -+ MUSB_TXCSR); -+ -+ /* -+ * The programming guide says that we must clear -+ * the DMAENAB bit before the DMAMODE bit... -+ */ -+ csr = musb_readw(mbase, offset); -+ csr &= ~(MUSB_TXCSR_AUTOSET | MUSB_TXCSR_DMAENAB); -+ musb_writew(mbase, offset, csr); -+ csr &= ~MUSB_TXCSR_DMAMODE; -+ musb_writew(mbase, offset, csr); - } else { -- csr = musb_readw(mbase, -- MUSB_EP_OFFSET(musb_channel->epnum, -- MUSB_RXCSR)); -+ offset = MUSB_EP_OFFSET(musb_channel->epnum, -+ MUSB_RXCSR); -+ -+ csr = musb_readw(mbase, offset); - csr &= ~(MUSB_RXCSR_AUTOCLEAR | - MUSB_RXCSR_DMAENAB | - MUSB_RXCSR_DMAMODE); -- musb_writew(mbase, -- MUSB_EP_OFFSET(musb_channel->epnum, MUSB_RXCSR), -- csr); -+ musb_writew(mbase, offset, csr); - } - - musb_writew(mbase, -@@ -296,14 +298,25 @@ static irqreturn_t dma_controller_irq(int irq, void *private_data) - && ((channel->desired_mode == 0) - || (channel->actual_len & - (musb_channel->max_packet_sz - 1))) -- ) { -+ ) { -+ u8 epnum = musb_channel->epnum; -+ int offset = MUSB_EP_OFFSET(epnum, -+ MUSB_TXCSR); -+ u16 txcsr; -+ -+ /* -+ * The programming guide says that we -+ * must clear DMAENAB before DMAMODE. -+ */ -+ musb_ep_select(mbase, epnum); -+ txcsr = musb_readw(mbase, offset); -+ txcsr &= ~(MUSB_TXCSR_DMAENAB -+ | MUSB_TXCSR_AUTOSET); -+ musb_writew(mbase, offset, txcsr); - /* Send out the packet */ -- musb_ep_select(mbase, -- musb_channel->epnum); -- musb_writew(mbase, MUSB_EP_OFFSET( -- musb_channel->epnum, -- MUSB_TXCSR), -- MUSB_TXCSR_TXPKTRDY); -+ txcsr &= ~MUSB_TXCSR_DMAMODE; -+ txcsr |= MUSB_TXCSR_TXPKTRDY; -+ musb_writew(mbase, offset, txcsr); - } else { - musb_dma_completion( - musb, --- -1.6.0.4 - |