Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f933a0c0 authored by Anand Gadiyar's avatar Anand Gadiyar Committed by Greg Kroah-Hartman
Browse files

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: default avatarAnand 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: default avatarFelipe Balbi <felipe.balbi@nokia.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent 452f0394
Loading
Loading
Loading
Loading
+22 −3
Original line number Diff line number Diff line
@@ -250,20 +250,39 @@ static irqreturn_t dma_controller_irq(int irq, void *private_data)
	u8 bchannel;
	u8 int_hsdma;

	u32 addr;
	u32 addr, count;
	u16 csr;

	spin_lock_irqsave(&musb->lock, flags);

	int_hsdma = musb_readb(mbase, MUSB_HSDMA_INTR);
	if (!int_hsdma)
		goto done;

#ifdef CONFIG_BLACKFIN
	/* Clear DMA interrupt flags */
	musb_writeb(mbase, MUSB_HSDMA_INTR, int_hsdma);
#endif

	if (!int_hsdma) {
		DBG(2, "spurious DMA irq\n");

		for (bchannel = 0; bchannel < MUSB_HSDMA_CHANNELS; bchannel++) {
			musb_channel = (struct musb_dma_channel *)
					&(controller->channel[bchannel]);
			channel = &musb_channel->channel;
			if (channel->status == MUSB_DMA_STATUS_BUSY) {
				count = musb_read_hsdma_count(mbase, bchannel);

				if (count == 0)
					int_hsdma |= (1 << bchannel);
			}
		}

		DBG(2, "int_hsdma = 0x%x\n", int_hsdma);

		if (!int_hsdma)
			goto done;
	}

	for (bchannel = 0; bchannel < MUSB_HSDMA_CHANNELS; bchannel++) {
		if (int_hsdma & (1 << bchannel)) {
			musb_channel = (struct musb_dma_channel *)