aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorAnand Gadiyar <gadiyar@ti.com>2009-12-28 06:40:36 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2010-03-02 17:53:42 -0500
commitf933a0c0fe0ea5f49a35bcd45e3e4850e0606cba (patch)
tree9a8052f7fd2119bd76f7cd94c6db5ae7324c21cd /drivers
parent452f0394376d2cc882e4c4a593fc290c042799a9 (diff)
usb: musb: workaround MUSB DMA_INTR sometimes reads zero
MUSB DMA_INTR register may sometimes read zero when infact there was a pending interrupt. Workaround this by reading the DMA_COUNT values for all enabled channels when this condition occurs. Flag these channels as the ones needing to be serviced. Additionally, the absence of a debug print meant we would never catch a spurious DMA interrupt in MUSB. So this patch adds a debug print in the IRQ handler. Signed-off-by: Anand Gadiyar <gadiyar@ti.com> Cc: Ajay Kumar Gupta <ajay.gupta@ti.com> Cc: David Brownell <dbrownell@users.sourceforge.net> Cc: Sergei Shtylyov <sshtylyov@ru.mvista.com> Cc: Vikram Pandita <vikram.pandita@ti.com> Signed-off-by: Felipe Balbi <felipe.balbi@nokia.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/usb/musb/musbhsdma.c25
1 files changed, 22 insertions, 3 deletions
diff --git a/drivers/usb/musb/musbhsdma.c b/drivers/usb/musb/musbhsdma.c
index a237550f91bf..2fa7d5c00f31 100644
--- a/drivers/usb/musb/musbhsdma.c
+++ b/drivers/usb/musb/musbhsdma.c
@@ -250,20 +250,39 @@ static irqreturn_t dma_controller_irq(int irq, void *private_data)
250 u8 bchannel; 250 u8 bchannel;
251 u8 int_hsdma; 251 u8 int_hsdma;
252 252
253 u32 addr; 253 u32 addr, count;
254 u16 csr; 254 u16 csr;
255 255
256 spin_lock_irqsave(&musb->lock, flags); 256 spin_lock_irqsave(&musb->lock, flags);
257 257
258 int_hsdma = musb_readb(mbase, MUSB_HSDMA_INTR); 258 int_hsdma = musb_readb(mbase, MUSB_HSDMA_INTR);
259 if (!int_hsdma)
260 goto done;
261 259
262#ifdef CONFIG_BLACKFIN 260#ifdef CONFIG_BLACKFIN
263 /* Clear DMA interrupt flags */ 261 /* Clear DMA interrupt flags */
264 musb_writeb(mbase, MUSB_HSDMA_INTR, int_hsdma); 262 musb_writeb(mbase, MUSB_HSDMA_INTR, int_hsdma);
265#endif 263#endif
266 264
265 if (!int_hsdma) {
266 DBG(2, "spurious DMA irq\n");
267
268 for (bchannel = 0; bchannel < MUSB_HSDMA_CHANNELS; bchannel++) {
269 musb_channel = (struct musb_dma_channel *)
270 &(controller->channel[bchannel]);
271 channel = &musb_channel->channel;
272 if (channel->status == MUSB_DMA_STATUS_BUSY) {
273 count = musb_read_hsdma_count(mbase, bchannel);
274
275 if (count == 0)
276 int_hsdma |= (1 << bchannel);
277 }
278 }
279
280 DBG(2, "int_hsdma = 0x%x\n", int_hsdma);
281
282 if (!int_hsdma)
283 goto done;
284 }
285
267 for (bchannel = 0; bchannel < MUSB_HSDMA_CHANNELS; bchannel++) { 286 for (bchannel = 0; bchannel < MUSB_HSDMA_CHANNELS; bchannel++) {
268 if (int_hsdma & (1 << bchannel)) { 287 if (int_hsdma & (1 << bchannel)) {
269 musb_channel = (struct musb_dma_channel *) 288 musb_channel = (struct musb_dma_channel *)