static int dma_channel_abort(struct dma_channel *channel) { struct musb_dma_channel *musb_channel = channel->private_data; 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) { 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 { 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, offset, csr); } musb_writew(mbase, MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_CONTROL), 0); musb_write_hsdma_addr(mbase, bchannel, 0); musb_write_hsdma_count(mbase, bchannel, 0); channel->status = MUSB_DMA_STATUS_FREE; if (musb_channel->transmit) musb_channel->controller->tx_active &= ~(1 << bchannel); else musb_channel->controller->rx_active &= ~(1 << bchannel); } return 0; }
static void musb_sysdma_completion(int lch, u16 ch_status, void *data) { u32 addr; unsigned long flags; struct dma_channel *channel; struct musb_dma_channel *musb_channel = (struct musb_dma_channel *) data; struct musb_dma_controller *controller = musb_channel->controller; struct musb *musb = controller->private_data; void __iomem *mbase = controller->base; channel = &musb_channel->channel; DBG(2, "lch = 0x%d, ch_status = 0x%x\n", lch, ch_status); spin_lock_irqsave(&musb->lock, flags); if (musb_channel->transmit) addr = (u32) omap_get_dma_src_pos(musb_channel->sysdma_channel); else addr = (u32) omap_get_dma_dst_pos(musb_channel->sysdma_channel); if (musb_channel->len == 0) channel->actual_len = 0; else channel->actual_len = addr - musb_channel->start_addr; DBG(2, "ch %p, 0x%x -> 0x%x (%d / %d) %s\n", channel, musb_channel->start_addr, addr, channel->actual_len, musb_channel->len, (channel->actual_len < musb_channel->len) ? "=> reconfig 0 " : " => complete"); channel->status = MUSB_DMA_STATUS_FREE; /* completed */ if ((musb_channel->transmit) && (channel->desired_mode == 0) && (channel->actual_len == musb_channel->max_packet_sz)) { u8 epnum = musb_channel->epnum; int offset = MUSB_EP_OFFSET(musb, epnum, MUSB_TXCSR); u16 txcsr; /* * The programming guide says that we * must clear DMAENAB before DMAMODE. */ musb_ep_select(musb, mbase, epnum); txcsr = musb_readw(mbase, offset); txcsr |= MUSB_TXCSR_TXPKTRDY; musb_writew(mbase, offset, txcsr); } musb_dma_completion(musb, musb_channel->epnum, musb_channel->transmit); spin_unlock_irqrestore(&musb->lock, flags); return; }
static int dma_channel_abort(struct dma_channel *channel) { struct musb_dma_channel *musb_channel = channel->private_data; void __iomem *mbase = musb_channel->controller->base; u8 bchannel = musb_channel->idx; 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); } else { if (musb_channel->sysdma_channel != -1) omap_stop_dma(musb_channel->sysdma_channel); csr = musb_readw(mbase, MUSB_EP_OFFSET(musb_channel->epnum, MUSB_RXCSR)); 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, MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_CONTROL), 0); musb_write_hsdma_addr(mbase, bchannel, 0); musb_write_hsdma_count(mbase, bchannel, 0); channel->status = MUSB_DMA_STATUS_FREE; } return 0; }
static irqreturn_t dma_controller_irq(int irq, void *private_data) { struct musb_dma_controller *controller = private_data; struct musb *musb = controller->private_data; struct musb_dma_channel *musb_channel; struct dma_channel *channel; void __iomem *mbase = controller->base; irqreturn_t retval = IRQ_NONE; unsigned long flags; u8 bchannel; u8 int_hsdma; u32 addr; u16 csr, count; spin_lock_irqsave(&musb->lock, flags); int_hsdma = musb_readb(mbase, MUSB_HSDMA_INTR); 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_readw(mbase, MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_COUNT)); 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 *) &(controller->channel[bchannel]); channel = &musb_channel->channel; csr = musb_readw(mbase, MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_CONTROL)); if (csr & (1 << MUSB_HSDMA_BUSERROR_SHIFT)) { musb_channel->channel.status = MUSB_DMA_STATUS_BUS_ABORT; } else { u8 devctl; addr = musb_read_hsdma_addr(mbase, bchannel); channel->actual_len = addr - musb_channel->start_addr; DBG(2, "ch %p, 0x%x -> 0x%x (%d / %d) %s\n", channel, musb_channel->start_addr, addr, channel->actual_len, musb_channel->len, (channel->actual_len < musb_channel->len) ? "=> reconfig 0" : "=> complete"); devctl = musb_readb(mbase, MUSB_DEVCTL); channel->status = MUSB_DMA_STATUS_FREE; if (musb_channel->transmit) controller->tx_active &= ~(1 << bchannel); else controller->rx_active &= ~(1 << bchannel); /* completed */ if ((devctl & MUSB_DEVCTL_HM) && (musb_channel->transmit) && ((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 */ txcsr &= ~MUSB_TXCSR_DMAMODE; txcsr |= MUSB_TXCSR_TXPKTRDY; musb_writew(mbase, offset, txcsr); } musb_dma_completion(musb, musb_channel->epnum, musb_channel->transmit); } } } #ifdef CONFIG_BLACKFIN /* Clear DMA interrup flags */ musb_writeb(mbase, MUSB_HSDMA_INTR, int_hsdma); #endif retval = IRQ_HANDLED; done: spin_unlock_irqrestore(&musb->lock, flags); return retval; }
static irqreturn_t dma_controller_irq(int irq, void *private_data) { struct musb_dma_controller *controller = private_data; struct musb *musb = controller->private_data; struct musb_dma_channel *musb_channel; struct dma_channel *channel; void __iomem *mbase = controller->base; irqreturn_t retval = IRQ_NONE; unsigned long flags; u8 bchannel; u8 int_hsdma; u32 addr; u16 csr; spin_lock_irqsave(&musb->lock, flags); int_hsdma = musb_readb(mbase, MUSB_HSDMA_INTR); if (!int_hsdma) goto done; for (bchannel = 0; bchannel < MUSB_HSDMA_CHANNELS; bchannel++) { if (int_hsdma & (1 << bchannel)) { musb_channel = (struct musb_dma_channel *) &(controller->channel[bchannel]); channel = &musb_channel->channel; csr = musb_readw(mbase, MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_CONTROL)); if (csr & (1 << MUSB_HSDMA_BUSERROR_SHIFT)) { musb_channel->channel.status = MUSB_DMA_STATUS_BUS_ABORT; } else { u8 devctl; addr = musb_read_hsdma_addr(mbase, bchannel); channel->actual_len = addr - musb_channel->start_addr; DBG(2, "ch %p, 0x%x -> 0x%x (%d / %d) %s\n", channel, musb_channel->start_addr, addr, channel->actual_len, musb_channel->len, (channel->actual_len < musb_channel->len) ? "=> reconfig 0" : "=> complete"); devctl = musb_readb(mbase, MUSB_DEVCTL); channel->status = MUSB_DMA_STATUS_FREE; /* completed */ if ((devctl & MUSB_DEVCTL_HM) && (musb_channel->transmit) && ((channel->desired_mode == 0) || (channel->actual_len & (musb_channel->max_packet_sz - 1))) ) { /* 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); } else { musb_dma_completion( musb, musb_channel->epnum, musb_channel->transmit); } } } } #ifdef CONFIG_BLACKFIN /* Clear DMA interrup flags */ musb_writeb(mbase, MUSB_HSDMA_INTR, int_hsdma); #endif retval = IRQ_HANDLED; done: spin_unlock_irqrestore(&musb->lock, flags); return retval; }