示例#1
0
static irqreturn_t xdma_tx_intr_handler(int irq, void *data)
{
	struct xdma_chan *chan = data;
	u32 stat;

	stat = DMA_IN(&chan->regs->sr);

	if (!(stat & XDMA_XR_IRQ_ALL_MASK)) {
		return IRQ_NONE;
	}

	/* Ack the interrupts */
	DMA_OUT(&chan->regs->sr, (stat & XDMA_XR_IRQ_ALL_MASK));

	if (stat & XDMA_XR_IRQ_ERROR_MASK) {
		dev_err(chan->dev, "Channel %s has errors %x, cdr %x tdr %x\n",
			chan->name, (unsigned int)stat,
			(unsigned int)DMA_IN(&chan->regs->cdr),
			(unsigned int)DMA_IN(&chan->regs->tdr));

		dump_cur_bd(chan);

		chan->err = 1;
		tasklet_schedule(&chan->dma_err_tasklet);
	}

	if (!(chan->poll_mode) && ((stat & XDMA_XR_IRQ_DELAY_MASK) ||
			(stat & XDMA_XR_IRQ_IOC_MASK)))
		tasklet_schedule(&chan->tasklet);

	return IRQ_HANDLED;
}
示例#2
0
static void dump_cur_bd(struct xdma_chan *chan)
{
	u32 index;

	index = (((u32)DMA_IN(&chan->regs->cdr)) - chan->bd_phys_addr) /
			sizeof(struct xdma_desc_hw);

	dev_err(chan->dev, "cur bd @ %08x\n",   (u32)DMA_IN(&chan->regs->cdr));
	dev_err(chan->dev, "  buf  = 0x%08x\n", chan->bds[index]->src_addr);
	dev_err(chan->dev, "  ctrl = 0x%08x\n", chan->bds[index]->control);
	dev_err(chan->dev, "  sts  = 0x%08x\n", chan->bds[index]->status);
	dev_err(chan->dev, "  next = 0x%08x\n", chan->bds[index]->next_desc);
}
示例#3
0
static void xdma_start_transfer(struct xdma_chan *chan,
				int start_index,
				int end_index)
{
	dma_addr_t cur_phys;
	dma_addr_t tail_phys;
	u32 regval;

	if (chan->err)
		return;

	cur_phys = chan->bd_phys_addr + (start_index *
					sizeof(struct xdma_desc_hw));
	tail_phys = chan->bd_phys_addr + (end_index *
					sizeof(struct xdma_desc_hw));
	/* If hardware is busy, move the tail & return */
	if (dma_is_running(chan) || dma_is_idle(chan)) {
		/* Update tail ptr register and start the transfer */
		DMA_OUT(&chan->regs->tdr, tail_phys);
		return;
	}

	DMA_OUT(&chan->regs->cdr, cur_phys);

	dma_start(chan);

	/* Enable interrupts */
	regval = DMA_IN(&chan->regs->cr);
	regval |= (chan->poll_mode ? XDMA_XR_IRQ_ERROR_MASK
					: XDMA_XR_IRQ_ALL_MASK);
	DMA_OUT(&chan->regs->cr, regval);

	/* Update tail ptr register and start the transfer */
	DMA_OUT(&chan->regs->tdr, tail_phys);
}
示例#4
0
static int dma_init(struct xdma_chan *chan)
{
	int loop = XDMA_RESET_LOOP;

	DMA_OUT(&chan->regs->cr,
		(DMA_IN(&chan->regs->cr) | XDMA_CR_RESET_MASK));

	/* Wait for the hardware to finish reset
	 */
	while (loop) {
		if (!(DMA_IN(&chan->regs->cr) & XDMA_CR_RESET_MASK))
			break;

		loop -= 1;
	}

	if (!loop)
		return 1;

	return 0;
}
示例#5
0
static void dma_start(struct xdma_chan *chan)
{
	DMA_OUT(&chan->regs->cr,
		(DMA_IN(&chan->regs->cr) | XDMA_CR_RUNSTOP_MASK));
}
示例#6
0
static int dma_is_idle(struct xdma_chan *chan)
{
	return DMA_IN(&chan->regs->sr) & XDMA_SR_IDLE_MASK;
}
示例#7
0
static int dma_is_running(struct xdma_chan *chan)
{
	return !(DMA_IN(&chan->regs->sr) & XDMA_SR_HALTED_MASK) &&
		(DMA_IN(&chan->regs->cr) & XDMA_CR_RUNSTOP_MASK);
}
示例#8
0
int ap_dma_wait(int ch)
{
	int i = 0;
	while (DMA_IN(ch+DMA_DMST) & DMA_DMST_AC) i++;
	return i;
}