Skip to content
  • Peter Ujfalusi's avatar
    dmaengine: core: Introduce new, universal API to request a channel · a8135d0d
    Peter Ujfalusi authored
    
    
    The two API function can cover most, if not all current APIs used to
    request a channel. With minimal effort dmaengine drivers, platforms and
    dmaengine user drivers can be converted to use the two function.
    
    struct dma_chan *dma_request_chan_by_mask(const dma_cap_mask_t *mask);
    
    To request any channel matching with the requested capabilities, can be
    used to request channel for memcpy, memset, xor, etc where no hardware
    synchronization is needed.
    
    struct dma_chan *dma_request_chan(struct device *dev, const char *name);
    To request a slave channel. The dma_request_chan() will try to find the
    channel via DT, ACPI or in case if the kernel booted in non DT/ACPI mode
    it will use a filter lookup table and retrieves the needed information from
    the dma_slave_map provided by the DMA drivers.
    This legacy mode needs changes in platform code, in dmaengine drivers and
    finally the dmaengine user drivers can be converted:
    
    For each dmaengine driver an array of DMA device, slave and the parameter
    for the filter function needs to be added:
    
    static const struct dma_slave_map da830_edma_map[] = {
    	{ "davinci-mcasp.0", "rx", EDMA_FILTER_PARAM(0, 0) },
    	{ "davinci-mcasp.0", "tx", EDMA_FILTER_PARAM(0, 1) },
    	{ "davinci-mcasp.1", "rx", EDMA_FILTER_PARAM(0, 2) },
    	{ "davinci-mcasp.1", "tx", EDMA_FILTER_PARAM(0, 3) },
    	{ "davinci-mcasp.2", "rx", EDMA_FILTER_PARAM(0, 4) },
    	{ "davinci-mcasp.2", "tx", EDMA_FILTER_PARAM(0, 5) },
    	{ "spi_davinci.0", "rx", EDMA_FILTER_PARAM(0, 14) },
    	{ "spi_davinci.0", "tx", EDMA_FILTER_PARAM(0, 15) },
    	{ "da830-mmc.0", "rx", EDMA_FILTER_PARAM(0, 16) },
    	{ "da830-mmc.0", "tx", EDMA_FILTER_PARAM(0, 17) },
    	{ "spi_davinci.1", "rx", EDMA_FILTER_PARAM(0, 18) },
    	{ "spi_davinci.1", "tx", EDMA_FILTER_PARAM(0, 19) },
    };
    
    This information is going to be needed by the dmaengine driver, so
    modification to the platform_data is needed, and the driver map should be
    added to the pdata of the DMA driver:
    
    da8xx_edma0_pdata.slave_map = da830_edma_map;
    da8xx_edma0_pdata.slavecnt = ARRAY_SIZE(da830_edma_map);
    
    The DMA driver then needs to configure the needed device -> filter_fn
    mapping before it registers with dma_async_device_register() :
    
    ecc->dma_slave.filter_map.map = info->slave_map;
    ecc->dma_slave.filter_map.mapcnt = info->slavecnt;
    ecc->dma_slave.filter_map.fn = edma_filter_fn;
    
    When neither DT or ACPI lookup is available the dma_request_chan() will
    try to match the requester's device name with the filter_map's list of
    device names, when a match found it will use the information from the
    dma_slave_map to get the channel with the dma_get_channel() internal
    function.
    
    Signed-off-by: default avatarPeter Ujfalusi <peter.ujfalusi@ti.com>
    Reviewed-by: default avatarArnd Bergmann <arnd@arndb.de>
    Signed-off-by: default avatarVinod Koul <vinod.koul@intel.com>
    a8135d0d