Пример #1
0
/* extensions for test DMA to FIOPIN */
int32_t dma_start_m2pin(int32_t ch,
                     void *src,
                     void *dest,
                     DMAC_LL_T *plli,
                     int32_t trans)
{
	int32_t sts = _ERROR;

	/* Verify that the selected channel has been allocated */
	if (dmadrv_dat.alloc_ch [ch] == TRUE)
	{
		/* Setup source and destination and clear LLI */
		dmadrv_dat.pdma->dma_chan [ch].src_addr = (uint32_t) src;
		dmadrv_dat.pdma->dma_chan [ch].dest_addr = (uint32_t) dest;
		dmadrv_dat.pdma->dma_chan [ch].lli = (uint32_t) plli;

		/* Use linked list control word if available */
		if (plli != NULL)
		{
			dmadrv_dat.pdma->dma_chan [ch].control = plli->next_ctrl;
		}
		else 
		{
			/* Setup channel configuration */
			dmadrv_dat.pdma->dma_chan [ch].control =
			    (DMAC_CHAN_INT_TC_EN | 	
		    	DMAC_CHAN_SRC_AUTOINC | DMAC_CHAN_DEST_WIDTH_8 |
			    DMAC_CHAN_SRC_WIDTH_8 | DMAC_CHAN_DEST_BURST_1 |
			    DMAC_CHAN_SRC_BURST_1 |
			    DMAC_CHAN_TRANSFER_SIZE(trans));
		}

		/* Start channel transfer */
		dmadrv_dat.pdma->dma_chan [ch].config_ch =
			(DMAC_CHAN_FLOW_D_P2M | DMAC_CHAN_ENABLE | DMAC_SRC_PERIP(9) );
		
		sts = _NO_ERROR;
	}

	return sts;
}
Пример #2
0
/*
 * Configure DMA descriptors and enable DMA channel for data and ECC reads
 */
static void lpc32xx_nand_dma_configure(struct mtd_info *mtd,
	dma_addr_t databuf, int eccsubpages, int read)
{
	struct nand_chip *chip = mtd->priv;
	struct lpc32xx_nand_host *host = chip->priv;
	uint32_t ecc_ctrl, *ecc_buf;
	uint32_t dataaddr, data_ctrl;
	int i;

	/* DMA buffer pointer for calculated ECC values */
	ecc_buf = (uint32_t *)host->ecc_buf_dma;

	/*
	 * ctrl descriptor entry for reading ECC
	 */
	ecc_ctrl = DMAC_CHAN_SRC_BURST_1 |
		DMAC_CHAN_DEST_BURST_1 |
		DMAC_CHAN_SRC_WIDTH_32 |
		DMAC_CHAN_DEST_WIDTH_32 |
		DMAC_CHAN_DEST_AHB1;

	/* data descriptor entry for reading/writing data */
	data_ctrl = ((mtd->writesize / eccsubpages) / 4) |
		DMAC_CHAN_SRC_BURST_4 |
		DMAC_CHAN_DEST_BURST_4 |
		DMAC_CHAN_SRC_WIDTH_32 |
		DMAC_CHAN_DEST_WIDTH_32 |
		DMAC_CHAN_DEST_AHB1;

	if (read) {
		data_ctrl |= DMAC_CHAN_DEST_AUTOINC;
		ecc_ctrl |= DMAC_CHAN_TRANSFER_SIZE(1);
	} else {
		data_ctrl |= DMAC_CHAN_SRC_AUTOINC;
		ecc_ctrl |= DMAC_CHAN_TRANSFER_SIZE(LPC32XX_DMA_ECC_REP_READ);
	}

	/*
	 * Only transfer the data areas plus ECC from hardware. The last ECC
	 * from hardware and OOB area will be transferred later.
	 */
	dataaddr = (uint32_t)databuf;

	for (i = 0; i < eccsubpages; i++) {
		if ((i == (eccsubpages - 1)) &&
			(!host->ncfg->polled_completion))
			data_ctrl |= DMAC_CHAN_INT_TC_EN;

		if (read)
			lpc32xx_dma_queue_llist(host->dmach,
				(void *)SLC_DMA_DATA(host->io_base_dma),
				(void *)dataaddr, -1, data_ctrl);
		else
			lpc32xx_dma_queue_llist(host->dmach, (void *)dataaddr,
				(void *)SLC_DMA_DATA(host->io_base_dma), -1,
				data_ctrl);

		dataaddr += (uint32_t)chip->ecc.size;;

		if (i != (eccsubpages - 1)) {
			lpc32xx_dma_queue_llist(host->dmach,
				(void *)SLC_ECC(host->io_base_dma),
				(void *)ecc_buf, -1, ecc_ctrl);
			ecc_buf++;;
		}
	}
}
/***********************************************************************
 *
 * Function: i2s_dma_init_dev
 *
 * Purpose: Initialize DMA for I2S
 *
 * Processing:
 *     See function
 *
 * Parameters:
 *          dmach:  DMA Channel number
 *          p_i2s_dma_prms: dma parameters
 *
 *
 * Outputs: None
 *
 * Returns:	if ok returns TRUE
 *
 *
 **********************************************************************/
INT_32 i2s_dma_init_dev(INT_32 devid, I2S_DMA_PRMS_T *p_i2s_dma_prms)

{

  INT_32 DMAC_CHAN_DEST_WIDTH;
  INT_32 DMAC_CHAN_SRC_WIDTH ;
  INT_32 i2s_ww, i2sch;
  INT_32 dmach, dir, mem, sz;

  I2S_CFG_T *pi2s = (I2S_CFG_T *) devid;
  i2sch = pi2s->i2snum;
  i2s_ww = pi2s->i2s_w_sz ;

 
  dmach = p_i2s_dma_prms->dmach;
  dir   = p_i2s_dma_prms->dir;
  mem   = p_i2s_dma_prms->mem;
  sz    = p_i2s_dma_prms->sz;

  /* clear TC for the  selected dma channel */
  DMAC->int_tc_clear |= _SBF(0, dmach);

  /* Set the DMA src and dst word width based on I2S Word 
  width setting */
  if (i2s_ww == I2S_WW8)
  {
    DMAC_CHAN_DEST_WIDTH = DMAC_CHAN_DEST_WIDTH_8;
    DMAC_CHAN_SRC_WIDTH = DMAC_CHAN_SRC_WIDTH_8;
  }
  else if (i2s_ww == I2S_WW16)
  {
    DMAC_CHAN_DEST_WIDTH = DMAC_CHAN_DEST_WIDTH_16;
    DMAC_CHAN_SRC_WIDTH = DMAC_CHAN_SRC_WIDTH_16;
  }
  else
  {
    DMAC_CHAN_DEST_WIDTH = DMAC_CHAN_DEST_WIDTH_32;
    DMAC_CHAN_SRC_WIDTH = DMAC_CHAN_SRC_WIDTH_32;
  }

  /* Setup DMA for I2S Channel 0, DEST uses AHB1, SRC uses AHB0 */
  if (i2sch == I2S_CH0)
  {
    /* dma is flow controller */
    if (dir == DMAC_CHAN_FLOW_D_M2P)
    {
      DMAC->dma_chan[dmach].src_addr = mem;
      DMAC->dma_chan[dmach].dest_addr = (UNS_32) & I2S0->i2s_tx_fifo;
      DMAC->dma_chan[dmach].control = DMAC_CHAN_TRANSFER_SIZE(sz) 
                                      | DMAC_CHAN_SRC_BURST_4
                                      | DMAC_CHAN_DEST_BURST_4 
                                      | DMAC_CHAN_DEST_AHB1
                                      | DMAC_CHAN_SRC_AUTOINC 
                                      | DMAC_CHAN_INT_TC_EN
                                      | DMAC_CHAN_SRC_WIDTH 
                                      | DMAC_CHAN_DEST_WIDTH;

      DMAC->dma_chan[dmach].config_ch |= DMAC_CHAN_ENABLE 
                              | DMAC_DEST_PERIP(DMA_PERID_I2S0_DMA0)
                              | DMAC_CHAN_FLOW_D_M2P | DMAC_CHAN_IE 
                              | DMAC_CHAN_ITC;

    }
    /* peripheral is flow controller */
    else if (dir == DMAC_CHAN_FLOW_P_M2P)
    {
      DMAC->dma_chan[dmach].src_addr = mem;
      DMAC->dma_chan[dmach].dest_addr = (UNS_32) & I2S0->i2s_tx_fifo;
      DMAC->dma_chan[dmach].control =  DMAC_CHAN_SRC_BURST_4
                                       | DMAC_CHAN_DEST_BURST_4 
                                       | DMAC_CHAN_DEST_AHB1
                                       | DMAC_CHAN_SRC_AUTOINC 
                                       | DMAC_CHAN_INT_TC_EN
                                       | DMAC_CHAN_SRC_WIDTH 
                                       | DMAC_CHAN_DEST_WIDTH;

      DMAC->dma_chan[dmach].config_ch |= DMAC_CHAN_ENABLE 
                              | DMAC_DEST_PERIP(DMA_PERID_I2S0_DMA0)
                              | DMAC_CHAN_FLOW_P_M2P | DMAC_CHAN_IE 
                              | DMAC_CHAN_ITC;

    }
    /* dma is flow controller */
    else if (dir == DMAC_CHAN_FLOW_D_P2M)
    {
      DMAC->dma_chan[dmach].src_addr = (UNS_32) & I2S0->i2s_rx_fifo;
      DMAC->dma_chan[dmach].dest_addr = mem;
      DMAC->dma_chan[dmach].control = DMAC_CHAN_TRANSFER_SIZE(sz) 
                                      | DMAC_CHAN_SRC_BURST_4
                                      | DMAC_CHAN_DEST_BURST_4 
                                      | DMAC_CHAN_SRC_AHB1
                                      | DMAC_CHAN_DEST_AUTOINC 
                                      | DMAC_CHAN_INT_TC_EN
                                      | DMAC_CHAN_SRC_WIDTH 
                                      | DMAC_CHAN_DEST_WIDTH;

      DMAC->dma_chan[dmach].config_ch |= DMAC_CHAN_ENABLE 
                              | DMAC_SRC_PERIP(DMA_PERID_I2S0_DMA1)
                              | DMAC_CHAN_FLOW_D_P2M | DMAC_CHAN_IE 
                              | DMAC_CHAN_ITC;
    }
    /* peripheral is flow controller */
    else if (dir == DMAC_CHAN_FLOW_P_P2M)
    {
      DMAC->dma_chan[dmach].src_addr = (UNS_32) & I2S0->i2s_rx_fifo;
      DMAC->dma_chan[dmach].dest_addr = mem;
      DMAC->dma_chan[dmach].control = DMAC_CHAN_SRC_BURST_4
                                      | DMAC_CHAN_DEST_BURST_4 
                                      | DMAC_CHAN_SRC_AHB1
                                      | DMAC_CHAN_DEST_AUTOINC 
                                      | DMAC_CHAN_INT_TC_EN
                                      | DMAC_CHAN_SRC_WIDTH 
                                      | DMAC_CHAN_DEST_WIDTH;

      DMAC->dma_chan[dmach].config_ch |= DMAC_CHAN_ENABLE 
                              | DMAC_SRC_PERIP(DMA_PERID_I2S0_DMA1)
                              | DMAC_CHAN_FLOW_P_P2M | DMAC_CHAN_IE 
                              | DMAC_CHAN_ITC;
    }
  }
  /* Setup DMA for I2S Channel 1 */
  else if (i2sch == I2S_CH1)
  {
    /* dma is flow controller */
    if (dir == DMAC_CHAN_FLOW_D_M2P)
    {
      DMAC->dma_chan[dmach].src_addr = mem;
      DMAC->dma_chan[dmach].dest_addr = (UNS_32) & I2S1->i2s_tx_fifo;
      DMAC->dma_chan[dmach].control = DMAC_CHAN_TRANSFER_SIZE(sz) 
                                      | DMAC_CHAN_SRC_BURST_4
                                      | DMAC_CHAN_DEST_BURST_4 
                                      | DMAC_CHAN_DEST_AHB1
                                      | DMAC_CHAN_SRC_AUTOINC 
                                      | DMAC_CHAN_INT_TC_EN
                                      | DMAC_CHAN_SRC_WIDTH 
                                      | DMAC_CHAN_DEST_WIDTH;

      DMAC->dma_chan[dmach].config_ch |= DMAC_CHAN_ENABLE 
                              | DMAC_DEST_PERIP(DMA_PERID_I2S1_DMA0)
                              | DMAC_CHAN_FLOW_D_M2P | DMAC_CHAN_IE 
                              | DMAC_CHAN_ITC;
    }
    /* peripheral is flow controller */
    else if (dir == DMAC_CHAN_FLOW_P_M2P)
    {
      DMAC->dma_chan[dmach].src_addr = mem;
      DMAC->dma_chan[dmach].dest_addr = (UNS_32) & I2S1->i2s_tx_fifo;
      DMAC->dma_chan[dmach].control = DMAC_CHAN_SRC_BURST_4
                                      | DMAC_CHAN_DEST_BURST_4 
                                      | DMAC_CHAN_DEST_AHB1
                                      | DMAC_CHAN_SRC_AUTOINC 
                                      | DMAC_CHAN_INT_TC_EN
                                      | DMAC_CHAN_SRC_WIDTH 
                                      | DMAC_CHAN_DEST_WIDTH;

      DMAC->dma_chan[dmach].config_ch |= DMAC_CHAN_ENABLE 
                              | DMAC_DEST_PERIP(DMA_PERID_I2S1_DMA0)
                              | DMAC_CHAN_FLOW_P_M2P | DMAC_CHAN_IE 
                              | DMAC_CHAN_ITC;
    }
    /* dma is flow controller */
    else if (dir == DMAC_CHAN_FLOW_D_P2M)
    {
      DMAC->dma_chan[dmach].src_addr = (UNS_32) & I2S1->i2s_rx_fifo;
      DMAC->dma_chan[dmach].dest_addr = mem;
      DMAC->dma_chan[dmach].control = DMAC_CHAN_TRANSFER_SIZE(sz) 
                                      | DMAC_CHAN_SRC_BURST_4
                                      | DMAC_CHAN_DEST_BURST_4 
                                      | DMAC_CHAN_SRC_AHB1
                                      | DMAC_CHAN_DEST_AUTOINC 
                                      | DMAC_CHAN_INT_TC_EN
                                      | DMAC_CHAN_SRC_WIDTH 
                                      | DMAC_CHAN_DEST_WIDTH;

      DMAC->dma_chan[dmach].config_ch |= DMAC_CHAN_ENABLE 
                              | DMAC_SRC_PERIP(DMA_PERID_I2S1_DMA1)
                              | DMAC_CHAN_FLOW_D_P2M 
                              | DMAC_CHAN_IE
                              | DMAC_CHAN_ITC;
    }
    /* peripheral is flow controller */
    else if (dir == DMAC_CHAN_FLOW_P_P2M)
    {
      DMAC->dma_chan[dmach].src_addr = (UNS_32) & I2S1->i2s_rx_fifo;
      DMAC->dma_chan[dmach].dest_addr = mem;
      DMAC->dma_chan[dmach].control = DMAC_CHAN_SRC_BURST_4
                                      | DMAC_CHAN_DEST_BURST_4 
                                      | DMAC_CHAN_SRC_AHB1
                                      | DMAC_CHAN_DEST_AUTOINC 
                                      | DMAC_CHAN_INT_TC_EN
                                      | DMAC_CHAN_SRC_WIDTH 
                                      | DMAC_CHAN_DEST_WIDTH;

      DMAC->dma_chan[dmach].config_ch |= DMAC_CHAN_ENABLE 
                              | DMAC_SRC_PERIP(DMA_PERID_I2S1_DMA1)
                              | DMAC_CHAN_FLOW_P_P2M 
                              | DMAC_CHAN_IE 
                              | DMAC_CHAN_ITC;
    }
  }

  else
  {
    return (FALSE);
  }

  return(TRUE);
}