Looks like I have almost done... Issue has been partially solved by allocating memory with CMEM_alloc() and passing addresses to DMA by dma_map_single. So I've constructed a DMA chain using dma_map_single() and dma_unmap_single().
Unfortunately, I've encountered another issue... maybe it has relation to cache, I'm not sure. New problem: sometimes all received data becomes = 0. ARM prefetching issue or something else? Calling flush_cache_all() before mapping and unmapping has no effect.
UPDATE: simplified call order
to start dma: for (all channels in chain) { dat = dma_map_single(NULL,_some_surely_correct_virtual_address_,2048,DMA_FROM_DEVICE); dma_sync_single_for_device(NULL,dat,2048,DMA_FROM_DEVICE); } omap_start_dma(first_channel_in_chain); in dma callback: omap_stop_dma(last_channel_in_chain); for (all channels in chain) { dma_unmap_single(NULL,_stored_from_above_dma_address_,2048,DMA_FROM_DEVICE); dma_sync_single_for_cpu(NULL,dat,2048,DMA_FROM_DEVICE); }