static void davinci_spi_dma_tx_callback(unsigned lch, u16 ch_status, void *data) { struct spi_device *spi = (struct spi_device *)data; struct davinci_spi *davinci_spi; struct davinci_spi_dma *davinci_spi_dma; struct davinci_spi_platform_data *pdata; davinci_spi = spi_master_get_devdata(spi->master); davinci_spi_dma = &(davinci_spi->dma_channels[spi->chip_select]); pdata = davinci_spi->pdata; if (ch_status == DMA_COMPLETE) edma_stop(davinci_spi_dma->dma_tx_channel); else edma_clean_channel(davinci_spi_dma->dma_tx_channel); complete(&davinci_spi_dma->dma_tx_completion); /* We must disable the DMA TX request */ davinci_spi_set_dma_req(spi, 0); }
/* release_channel() must be called with the edma_mutex held */ static void release_channel(int chan) { int localChan; int i; /* * The non-LSP_210 EDMA interface returns a "magic" value that represents * the controller number and channel number muxed together in one UInt32. * This module doesn't yet support a controller other than 0, however, this * function needs to accommodate being called with a controller > 0 since * it's called to release a channel on a controller > 0 when the * REQUESTDMA ioctl() receives a controller > 0 that it can't handle and * needs to clean up after itself. */ /* * In order to not be dependent on the LSP #defines, we need to * translate our EDMA interface's #defines to the LSP ones. */ #if defined(LSP_210) localChan = chan; if (chan >= EDMA_QDMA0 && chan <= EDMA_QDMA7) { __D(" release_channel: translating QDMA channel %d to LSP namespace ...\n", chan); localChan = EDMA_QDMA_CHANNEL_0 + (chan - EDMA_QDMA0); } for (i = 0; i < channels[localChan].nParam; i++) { __D(" release_channel: freeing channel %d...\n", localChan + i); davinci_free_dma(localChan + i); } INIT_LIST_HEAD(&channels[localChan].users); channels[localChan].nParam = 0; channels[localChan].isParam = 0; #else /* defined(LSP_210) */ localChan = EDMA_CHAN_SLOT(chan); if (localChan >= EDMA_QDMA0 && localChan <= EDMA_QDMA7) { __E(" release_channel: QDMA is not supported: chan %d\n", chan); return; } for (i = 0; i < channels[localChan].nParam; i++) { if (channels[localChan].isParam) { __D(" release_channel: calling edma_free_slot(%d)...\n", chan + i); edma_free_slot(chan + i); } else { __D(" release_channel: calling edma_free_channel(%d)...\n", chan + i); edma_clean_channel(chan + i); edma_free_channel(chan + i); } } if (EDMA_CTLR(chan) == 0) { INIT_LIST_HEAD(&channels[localChan].users); channels[localChan].nParam = 0; channels[localChan].isParam = 0; } #endif /* defined(LSP_210) */ }