Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 143603
b: refs/heads/master
c: b6e434a
h: refs/heads/master
i:
  143601: 996230a
  143599: 829d6db
v: v3
  • Loading branch information
Sergei Shtylyov authored and Greg Kroah-Hartman committed Apr 17, 2009
1 parent 6cf2a83 commit ca13951
Show file tree
Hide file tree
Showing 4 changed files with 91 additions and 82 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: c7bbc056a92476b3b3d70a8df7cc746ac5d56de7
refs/heads/master: b6e434a5404b9ce8c285ea081b6ea5c523b29db4
33 changes: 22 additions & 11 deletions trunk/drivers/usb/musb/musb_gadget.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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 */
Expand All @@ -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)
Expand All @@ -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)
Expand Down
79 changes: 32 additions & 47 deletions trunk/drivers/usb/musb/musb_host.c
Original file line number Diff line number Diff line change
Expand Up @@ -593,10 +593,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 */
Expand Down Expand Up @@ -693,29 +700,33 @@ 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
| MUSB_TXCSR_TXPKTRDY
);
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 {
Expand Down Expand Up @@ -759,34 +770,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(
Expand All @@ -803,25 +799,25 @@ 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

/* 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;

Expand Down Expand Up @@ -850,20 +846,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 */
Expand Down
59 changes: 36 additions & 23 deletions trunk/drivers/usb/musb/musbhsdma.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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);
}
musb_dma_completion(musb, musb_channel->epnum,
musb_channel->transmit);
Expand Down

0 comments on commit ca13951

Please sign in to comment.