diff options
author | Anand Gadiyar <gadiyar@ti.com> | 2009-12-28 06:40:36 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2010-03-02 17:53:42 -0500 |
commit | f933a0c0fe0ea5f49a35bcd45e3e4850e0606cba (patch) | |
tree | 9a8052f7fd2119bd76f7cd94c6db5ae7324c21cd /drivers/usb/musb/musbhsdma.c | |
parent | 452f0394376d2cc882e4c4a593fc290c042799a9 (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/usb/musb/musbhsdma.c')
-rw-r--r-- | drivers/usb/musb/musbhsdma.c | 25 |
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 *) |