aboutsummaryrefslogtreecommitdiffstats
path: root/meta/recipes-kernel/linux/linux-omap-2.6.29/musb/0010-musb-sanitize-clearing-TXCSR-DMA-bits-take-2.patch
diff options
context:
space:
mode:
authorRichard Purdie <rpurdie@linux.intel.com>2010-08-27 15:14:24 +0100
committerRichard Purdie <rpurdie@linux.intel.com>2010-08-27 15:29:45 +0100
commit29d6678fd546377459ef75cf54abeef5b969b5cf (patch)
tree8edd65790e37a00d01c3f203f773fe4b5012db18 /meta/recipes-kernel/linux/linux-omap-2.6.29/musb/0010-musb-sanitize-clearing-TXCSR-DMA-bits-take-2.patch
parentda49de6885ee1bc424e70bc02f21f6ab920efb55 (diff)
downloadopenembedded-core-contrib-29d6678fd546377459ef75cf54abeef5b969b5cf.tar.gz
Major layout change to the packages directory
Having one monolithic packages directory makes it hard to find things and is generally overwhelming. This commit splits it into several logical sections roughly based on function, recipes.txt gives more information about the classifications used. The opportunity is also used to switch from "packages" to "recipes" as used in OpenEmbedded as the term "packages" can be confusing to people and has many different meanings. Not all recipes have been classified yet, this is just a first pass at separating things out. Some packages are moved to meta-extras as they're no longer actively used or maintained. Signed-off-by: Richard Purdie <rpurdie@linux.intel.com>
Diffstat (limited to 'meta/recipes-kernel/linux/linux-omap-2.6.29/musb/0010-musb-sanitize-clearing-TXCSR-DMA-bits-take-2.patch')
-rw-r--r--meta/recipes-kernel/linux/linux-omap-2.6.29/musb/0010-musb-sanitize-clearing-TXCSR-DMA-bits-take-2.patch361
1 files changed, 361 insertions, 0 deletions
diff --git a/meta/recipes-kernel/linux/linux-omap-2.6.29/musb/0010-musb-sanitize-clearing-TXCSR-DMA-bits-take-2.patch b/meta/recipes-kernel/linux/linux-omap-2.6.29/musb/0010-musb-sanitize-clearing-TXCSR-DMA-bits-take-2.patch
new file mode 100644
index 0000000000..bcbe3bbe39
--- /dev/null
+++ b/meta/recipes-kernel/linux/linux-omap-2.6.29/musb/0010-musb-sanitize-clearing-TXCSR-DMA-bits-take-2.patch
@@ -0,0 +1,361 @@
+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
+