コード例 #1
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);
}
コード例 #2
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;
}
コード例 #3
0
ファイル: dma.c プロジェクト: chinnyannieb/empeg-hijack
/* send some data out a dma channel */
int ap_dma_go(unsigned long ch,unsigned int p,int size,unsigned long cmd)
{
  int rest;

  p = mmu_v2p(p);

  cmd |= DMA_DCMD_ST | DMA_DCMD_TYP_AUTO;

#if 0
  if (ap_dma_wait(ch)) {
	  printk("WARNING: dma started when not complete\n");
  }

  if (cmd == DMA_DCMD_TD_MD && !(BIF_IN(BIF_SDCSR) & BIF_SDCSR_BG)) {
	  ap_led(0xAA);
	  printk("attempt to dma without holding the bus\n");
	  return -1;
  }
#endif

  /* reset the dma system */
  DMA_OUT(ch + DMA_DMST,DMA_DMST_RST);

  if (size <= DMA_MAX_TRANS_SIZE) {
    DMA_OUT(ch + DMA_MADDR,(unsigned long)p);
    DMA_OUT(ch + DMA_HSKIP,1);
    DMA_OUT(ch + DMA_VSKIP,1);
    DMA_OUT(ch + DMA_DCMD,cmd | B2W(size));
    return 0;
  } 

  if (size <= DMA_MAX_TRANS_SIZE2) {
    if(size & 0x3) size += 4;
    rest = (size & (DMA_TRANS_BLOCK_SIZE - 1)) >> 2;
    if (rest) {
      DMA_OUT(ch + DMA_HDRP,(unsigned)p);
      p += rest << 2;
    }
    DMA_OUT(ch + DMA_MADDR,(unsigned)p);
    DMA_OUT(ch + DMA_HSKIP,size >> (2 + 6));
    DMA_OUT(ch + DMA_VSKIP,1);
    DMA_OUT(ch + DMA_DCMD,cmd | (rest << 16) | 64);
    return 0;
  }

  printk("AP1000 DMA operation too big (%d bytes) - aborting\n",size);
  return(-1);
}
コード例 #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));
}