/* 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; }
/* * 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); }