161f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij/* 261f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij * driver/dma/coh901318_lli.c 361f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij * 461f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij * Copyright (C) 2007-2009 ST-Ericsson 561f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij * License terms: GNU General Public License (GPL) version 2 661f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij * Support functions for handling lli for dma 761f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij * Author: Per Friden <per.friden@stericsson.com> 861f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij */ 961f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij 1061f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij#include <linux/spinlock.h> 1161f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij#include <linux/memory.h> 125a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/gfp.h> 13db8196df4bb6f117caa163aa73b0f16fd62290bdVinod Koul#include <linux/dmapool.h> 1461f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij#include <mach/coh901318.h> 1561f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij 1661f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij#include "coh901318_lli.h" 1761f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij 1861f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij#if (defined(CONFIG_DEBUG_FS) && defined(CONFIG_U300_DEBUG)) 1961f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij#define DEBUGFS_POOL_COUNTER_RESET(pool) (pool->debugfs_pool_counter = 0) 2061f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij#define DEBUGFS_POOL_COUNTER_ADD(pool, add) (pool->debugfs_pool_counter += add) 2161f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij#else 2261f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij#define DEBUGFS_POOL_COUNTER_RESET(pool) 2361f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij#define DEBUGFS_POOL_COUNTER_ADD(pool, add) 2461f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij#endif 2561f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij 2661f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleijstatic struct coh901318_lli * 2761f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleijcoh901318_lli_next(struct coh901318_lli *data) 2861f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij{ 2961f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij if (data == NULL || data->link_addr == 0) 3061f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij return NULL; 3161f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij 3261f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij return (struct coh901318_lli *) data->virt_link_addr; 3361f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij} 3461f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij 3561f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleijint coh901318_pool_create(struct coh901318_pool *pool, 3661f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij struct device *dev, 3761f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij size_t size, size_t align) 3861f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij{ 3961f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij spin_lock_init(&pool->lock); 4061f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij pool->dev = dev; 4161f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij pool->dmapool = dma_pool_create("lli_pool", dev, size, align, 0); 4261f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij 4361f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij DEBUGFS_POOL_COUNTER_RESET(pool); 4461f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij return 0; 4561f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij} 4661f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij 4761f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleijint coh901318_pool_destroy(struct coh901318_pool *pool) 4861f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij{ 4961f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij 5061f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij dma_pool_destroy(pool->dmapool); 5161f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij return 0; 5261f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij} 5361f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij 5461f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleijstruct coh901318_lli * 5561f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleijcoh901318_lli_alloc(struct coh901318_pool *pool, unsigned int len) 5661f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij{ 5761f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij int i; 5861f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij struct coh901318_lli *head; 5961f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij struct coh901318_lli *lli; 6061f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij struct coh901318_lli *lli_prev; 6161f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij dma_addr_t phy; 6261f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij 6361f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij if (len == 0) 6461f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij goto err; 6561f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij 6661f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij spin_lock(&pool->lock); 6761f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij 6861f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij head = dma_pool_alloc(pool->dmapool, GFP_NOWAIT, &phy); 6961f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij 7061f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij if (head == NULL) 7161f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij goto err; 7261f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij 7361f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij DEBUGFS_POOL_COUNTER_ADD(pool, 1); 7461f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij 7561f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij lli = head; 7661f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij lli->phy_this = phy; 7756a5d3cf21c71963c8fc506e9b9d3f71641d9c71Linus Walleij lli->link_addr = 0x00000000; 7856a5d3cf21c71963c8fc506e9b9d3f71641d9c71Linus Walleij lli->virt_link_addr = 0x00000000U; 7961f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij 8061f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij for (i = 1; i < len; i++) { 8161f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij lli_prev = lli; 8261f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij 8361f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij lli = dma_pool_alloc(pool->dmapool, GFP_NOWAIT, &phy); 8461f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij 8561f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij if (lli == NULL) 8661f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij goto err_clean_up; 8761f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij 8861f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij DEBUGFS_POOL_COUNTER_ADD(pool, 1); 8961f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij lli->phy_this = phy; 9056a5d3cf21c71963c8fc506e9b9d3f71641d9c71Linus Walleij lli->link_addr = 0x00000000; 9156a5d3cf21c71963c8fc506e9b9d3f71641d9c71Linus Walleij lli->virt_link_addr = 0x00000000U; 9261f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij 9361f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij lli_prev->link_addr = phy; 9461f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij lli_prev->virt_link_addr = lli; 9561f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij } 9661f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij 9761f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij spin_unlock(&pool->lock); 9861f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij 9961f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij return head; 10061f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij 10161f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij err: 10261f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij spin_unlock(&pool->lock); 10361f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij return NULL; 10461f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij 10561f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij err_clean_up: 10661f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij lli_prev->link_addr = 0x00000000U; 10761f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij spin_unlock(&pool->lock); 10861f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij coh901318_lli_free(pool, &head); 10961f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij return NULL; 11061f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij} 11161f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij 11261f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleijvoid coh901318_lli_free(struct coh901318_pool *pool, 11361f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij struct coh901318_lli **lli) 11461f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij{ 11561f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij struct coh901318_lli *l; 11661f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij struct coh901318_lli *next; 11761f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij 11861f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij if (lli == NULL) 11961f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij return; 12061f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij 12161f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij l = *lli; 12261f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij 12361f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij if (l == NULL) 12461f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij return; 12561f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij 12661f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij spin_lock(&pool->lock); 12761f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij 12861f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij while (l->link_addr) { 12961f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij next = l->virt_link_addr; 13061f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij dma_pool_free(pool->dmapool, l, l->phy_this); 13161f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij DEBUGFS_POOL_COUNTER_ADD(pool, -1); 13261f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij l = next; 13361f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij } 13461f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij dma_pool_free(pool->dmapool, l, l->phy_this); 13561f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij DEBUGFS_POOL_COUNTER_ADD(pool, -1); 13661f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij 13761f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij spin_unlock(&pool->lock); 13861f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij *lli = NULL; 13961f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij} 14061f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij 14161f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleijint 14261f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleijcoh901318_lli_fill_memcpy(struct coh901318_pool *pool, 14361f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij struct coh901318_lli *lli, 14461f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij dma_addr_t source, unsigned int size, 14561f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij dma_addr_t destination, u32 ctrl_chained, 14661f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij u32 ctrl_eom) 14761f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij{ 14861f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij int s = size; 14961f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij dma_addr_t src = source; 15061f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij dma_addr_t dst = destination; 15161f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij 15261f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij lli->src_addr = src; 15361f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij lli->dst_addr = dst; 15461f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij 15561f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij while (lli->link_addr) { 15661f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij lli->control = ctrl_chained | MAX_DMA_PACKET_SIZE; 15761f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij lli->src_addr = src; 15861f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij lli->dst_addr = dst; 15961f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij 16061f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij s -= MAX_DMA_PACKET_SIZE; 16161f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij lli = coh901318_lli_next(lli); 16261f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij 16361f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij src += MAX_DMA_PACKET_SIZE; 16461f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij dst += MAX_DMA_PACKET_SIZE; 16561f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij } 16661f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij 16761f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij lli->control = ctrl_eom | s; 16861f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij lli->src_addr = src; 16961f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij lli->dst_addr = dst; 17061f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij 1710b58828c923e57f1bfbbd2c4277ceb60666314faLinus Walleij return 0; 17261f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij} 17361f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij 17461f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleijint 17561f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleijcoh901318_lli_fill_single(struct coh901318_pool *pool, 17661f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij struct coh901318_lli *lli, 17761f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij dma_addr_t buf, unsigned int size, 17861f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij dma_addr_t dev_addr, u32 ctrl_chained, u32 ctrl_eom, 179db8196df4bb6f117caa163aa73b0f16fd62290bdVinod Koul enum dma_transfer_direction dir) 18061f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij{ 18161f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij int s = size; 18261f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij dma_addr_t src; 18361f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij dma_addr_t dst; 18461f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij 18561f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij 186db8196df4bb6f117caa163aa73b0f16fd62290bdVinod Koul if (dir == DMA_MEM_TO_DEV) { 18761f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij src = buf; 18861f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij dst = dev_addr; 18961f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij 190db8196df4bb6f117caa163aa73b0f16fd62290bdVinod Koul } else if (dir == DMA_DEV_TO_MEM) { 19161f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij 19261f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij src = dev_addr; 19361f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij dst = buf; 19461f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij } else { 19561f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij return -EINVAL; 19661f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij } 19761f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij 19861f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij while (lli->link_addr) { 19961f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij size_t block_size = MAX_DMA_PACKET_SIZE; 20061f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij lli->control = ctrl_chained | MAX_DMA_PACKET_SIZE; 20161f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij 20261f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij /* If we are on the next-to-final block and there will 20361f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij * be less than half a DMA packet left for the last 20461f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij * block, then we want to make this block a little 20561f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij * smaller to balance the sizes. This is meant to 20661f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij * avoid too small transfers if the buffer size is 20761f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij * (MAX_DMA_PACKET_SIZE*N + 1) */ 20861f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij if (s < (MAX_DMA_PACKET_SIZE + MAX_DMA_PACKET_SIZE/2)) 20961f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij block_size = MAX_DMA_PACKET_SIZE/2; 21061f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij 21161f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij s -= block_size; 21261f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij lli->src_addr = src; 21361f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij lli->dst_addr = dst; 21461f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij 21561f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij lli = coh901318_lli_next(lli); 21661f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij 217db8196df4bb6f117caa163aa73b0f16fd62290bdVinod Koul if (dir == DMA_MEM_TO_DEV) 21861f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij src += block_size; 219db8196df4bb6f117caa163aa73b0f16fd62290bdVinod Koul else if (dir == DMA_DEV_TO_MEM) 22061f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij dst += block_size; 22161f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij } 22261f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij 22361f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij lli->control = ctrl_eom | s; 22461f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij lli->src_addr = src; 22561f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij lli->dst_addr = dst; 22661f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij 2270b58828c923e57f1bfbbd2c4277ceb60666314faLinus Walleij return 0; 22861f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij} 22961f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij 23061f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleijint 23161f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleijcoh901318_lli_fill_sg(struct coh901318_pool *pool, 23261f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij struct coh901318_lli *lli, 23361f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij struct scatterlist *sgl, unsigned int nents, 23461f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij dma_addr_t dev_addr, u32 ctrl_chained, u32 ctrl, 23561f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij u32 ctrl_last, 236db8196df4bb6f117caa163aa73b0f16fd62290bdVinod Koul enum dma_transfer_direction dir, u32 ctrl_irq_mask) 23761f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij{ 23861f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij int i; 23961f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij struct scatterlist *sg; 24061f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij u32 ctrl_sg; 24161f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij dma_addr_t src = 0; 24261f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij dma_addr_t dst = 0; 24361f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij u32 bytes_to_transfer; 24461f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij u32 elem_size; 24561f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij 24661f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij if (lli == NULL) 24761f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij goto err; 24861f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij 24961f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij spin_lock(&pool->lock); 25061f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij 251db8196df4bb6f117caa163aa73b0f16fd62290bdVinod Koul if (dir == DMA_MEM_TO_DEV) 25261f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij dst = dev_addr; 253db8196df4bb6f117caa163aa73b0f16fd62290bdVinod Koul else if (dir == DMA_DEV_TO_MEM) 25461f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij src = dev_addr; 25561f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij else 25661f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij goto err; 25761f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij 25861f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij for_each_sg(sgl, sg, nents, i) { 25961f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij if (sg_is_chain(sg)) { 26061f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij /* sg continues to the next sg-element don't 26161f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij * send ctrl_finish until the last 26261f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij * sg-element in the chain 26361f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij */ 26461f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij ctrl_sg = ctrl_chained; 26561f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij } else if (i == nents - 1) 26661f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij ctrl_sg = ctrl_last; 26761f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij else 26861f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij ctrl_sg = ctrl ? ctrl : ctrl_last; 26961f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij 27061f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij 271db8196df4bb6f117caa163aa73b0f16fd62290bdVinod Koul if (dir == DMA_MEM_TO_DEV) 27261f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij /* increment source address */ 27356a5d3cf21c71963c8fc506e9b9d3f71641d9c71Linus Walleij src = sg_phys(sg); 27461f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij else 27561f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij /* increment destination address */ 27656a5d3cf21c71963c8fc506e9b9d3f71641d9c71Linus Walleij dst = sg_phys(sg); 27761f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij 27861f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij bytes_to_transfer = sg_dma_len(sg); 27961f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij 28061f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij while (bytes_to_transfer) { 28161f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij u32 val; 28261f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij 28361f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij if (bytes_to_transfer > MAX_DMA_PACKET_SIZE) { 28461f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij elem_size = MAX_DMA_PACKET_SIZE; 28561f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij val = ctrl_chained; 28661f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij } else { 28761f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij elem_size = bytes_to_transfer; 28861f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij val = ctrl_sg; 28961f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij } 29061f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij 29161f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij lli->control = val | elem_size; 29261f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij lli->src_addr = src; 29361f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij lli->dst_addr = dst; 29461f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij 295db8196df4bb6f117caa163aa73b0f16fd62290bdVinod Koul if (dir == DMA_DEV_TO_MEM) 29661f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij dst += elem_size; 29761f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij else 29861f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij src += elem_size; 29961f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij 30061f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij BUG_ON(lli->link_addr & 3); 30161f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij 30261f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij bytes_to_transfer -= elem_size; 30361f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij lli = coh901318_lli_next(lli); 30461f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij } 30561f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij 30661f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij } 30761f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij spin_unlock(&pool->lock); 30861f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij 3090b58828c923e57f1bfbbd2c4277ceb60666314faLinus Walleij return 0; 31061f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij err: 31161f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij spin_unlock(&pool->lock); 31261f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij return -EINVAL; 31361f135b92f4758bc4d4767cd0a5d2da954e27f14Linus Walleij} 314