/** * sw_dma_request - request a dma channel * @name: dma channel name * @type: channel type, normal or dedicate * * Returns handle to the channel if success, NULL if failed. */ dma_hdl_t sw_dma_request(char * name, dma_chan_type_e type) { u32 i, num; u32 usign = 0; dma_channel_t *pchan = NULL; DMA_DBG("%s: name %s, chan type %d\n", __func__, name, (u32)type); if((name && strlen(name) >= MAX_NAME_LEN) || (type != CHAN_NORMAL && type != CHAN_DEDICATE)) { DMA_ERR("%s: para err, name %s, type %d\n", __func__, name, (u32)type); return NULL; } mutex_lock(&dma_mutex); /* check if already exist */ if(NULL != name && __dma_channel_already_exist(name)) { usign = __LINE__; goto end; } /* get a free channel */ if(CHAN_NORMAL == type) i = 0; else i = 8; num = i + 8; for(; i < num ; i++) { if(0 == g_dma_mgr.chnl[i].used) { WARN_ON(!__chan_is_free(&g_dma_mgr.chnl[i])); break; } } if(num == i) { usign = __LINE__; goto end; } /* init channel */ pchan = &g_dma_mgr.chnl[i]; pchan->used = 1; dma_request_init(pchan); if(NULL != name) strcpy(pchan->owner, name); end: mutex_unlock(&dma_mutex); if(0 != usign) DMA_ERR("%s err, line %d\n", __func__, usign); else DMA_DBG("%s: success, channel id %d\n", __func__, i); return (dma_hdl_t)pchan; }
/** * sw_dma_getposition - get the src and dst address from the reg * @dma_hdl: dma handle * @psrc: pointed to src addr that will be got * @pdst: pointed to dst addr that will be got * * Returns 0 if sucess, the err line number if failed. */ int sw_dma_getposition(dm_hdl_t dma_hdl, u32 *psrc, u32 *pdst) { dma_channel_t *pchan = (dma_channel_t *)dma_hdl; if(NULL == dma_hdl || NULL == psrc || NULL == pdst) { DMA_ERR("%s err, line %d\n", __func__, __LINE__); return __LINE__; } if(0 == pchan->used) { DMA_ERR("%s err, line %d\n", __func__, __LINE__); return __LINE__; } *psrc = csp_dma_chan_get_cur_srcaddr(pchan); *pdst = csp_dma_chan_get_cur_dstaddr(pchan); DMA_DBG("%s: get *psrc 0x%08x, *pdst 0x%08x\n", __func__, *psrc, *pdst); return 0; }
/** * sw_dma_getposition - get src and dst position * @dma_hdl: dma handle * @psrc: stored the src addr got * @pdst: stored the dst addr got * * Returns 0 if sucess, otherwise failed */ int sw_dma_getposition(dma_hdl_t dma_hdl, u32 *psrc, u32 *pdst) { dma_channel_t *pchan = (dma_channel_t *)dma_hdl; unsigned long flags; u32 saddr, daddr, reamin; BUG_ON(unlikely(!dma_handle_is_valid(dma_hdl))); BUG_ON(unlikely(NULL == psrc || NULL == pdst)); DMA_CHAN_LOCK(&pchan->lock, flags); /* get src/dst start addr */ saddr = csp_dma_get_saddr(pchan); daddr = csp_dma_get_daddr(pchan); /* get remain bytes */ reamin = csp_dma_get_bcnt(pchan); /* note: tha caller use "period - reamin" to get transferred bytes */ *psrc = saddr - reamin; *pdst = daddr - reamin; DMA_CHAN_UNLOCK(&pchan->lock, flags); DMA_DBG("%s: get *psrc 0x%08x, *pdst 0x%08x\n", __func__, *psrc, *pdst); return 0; }
/** * sw_dma_request - request a dma channel * @name: dma channel name * * Returns handle to the channel if success, NULL if failed. */ dm_hdl_t sw_dma_request(char *name, enum dma_work_mode_e work_mode) { u32 i = 0; u32 usign = 0; dma_channel_t *pchan = NULL; DMA_DBG("%s: name %s, work_mode %d\n", __func__, name, (u32)work_mode); if(strlen(name) >= MAX_OWNER_NAME_LEN || (work_mode != DMA_WORK_MODE_CHAIN && work_mode != DMA_WORK_MODE_SINGLE)) { DMA_ERR("%s: para err, name %s, work mode %d\n", __func__, name, (u32)work_mode); return NULL; } mutex_lock(&dma_mutex); /* check if already exist */ if(NULL != name && __dma_channel_already_exist(name)) { usign = __LINE__; goto end; } /* get a free channel */ for(i = 0; i < DMA_CHAN_TOTAL; i++) { pchan = &dma_chnl[i]; if(0 == pchan->used) { #ifdef DBG_DMA if(true != __dma_check_channel_free(pchan)) DMA_ERR("%s(%d) err, channel is not free\n", __func__, __LINE__); #endif /* DBG_DMA */ break; } } /* cannot get a free channel */ if(DMA_CHAN_TOTAL == i) { usign = __LINE__; goto end; } /* init channel */ if(DMA_WORK_MODE_CHAIN == work_mode) { dma_request_init_chain(pchan); } else if(DMA_WORK_MODE_SINGLE == work_mode) { dma_request_init_single(pchan); #ifdef NOT_ALLOC_DES_TEMP v_addr = (u32)dma_alloc_coherent(NULL, TEMP_DES_CNT * sizeof(des_item), (dma_addr_t *)&p_addr, GFP_KERNEL); if(0 == v_addr) printk("%s err, dma_alloc_coherent failed, line %d\n", __func__, __LINE__); else printk("%s: dma_alloc_coherent return v_addr 0x%08x, p_addr 0x%08x\n", __func__, v_addr, p_addr); index_get = 0; index_put = 0; #endif /* NOT_ALLOC_DES_TEMP */ } pchan->used = 1; if(NULL != name) strcpy(pchan->owner, name); pchan->work_mode = work_mode; end: mutex_unlock(&dma_mutex); if(0 != usign) { DMA_ERR("%s err, line %d\n", __func__, usign); return (dm_hdl_t)NULL; } else { DMA_DBG("%s: success, channel id %d\n", __func__, i); return (dm_hdl_t)pchan; } }
/** * __dma_dump_config_para - dump dma_config_t struct * @para: dma_config_t struct to dump */ static void __dma_dump_config_para(struct dma_config_t *para) { if(NULL == para) { DMA_ERR("%s err, line %d\n", __func__, __LINE__); return; } DMA_DBG("+++++++++++%s+++++++++++\n", __func__); DMA_DBG(" xfer_type: %d\n", para->xfer_type); DMA_DBG(" address_type: %d\n", para->address_type); DMA_DBG(" para: 0x%08x\n", para->para); DMA_DBG(" irq_spt: %d\n", para->irq_spt); DMA_DBG(" src_addr: 0x%08x\n", para->src_addr); DMA_DBG(" dst_addr: 0x%08x\n", para->dst_addr); DMA_DBG(" byte_cnt: 0x%08x\n", para->byte_cnt); DMA_DBG(" bconti_mode: %d\n", para->bconti_mode); DMA_DBG(" src_drq_type: %d\n", para->src_drq_type); DMA_DBG(" dst_drq_type: %d\n", para->dst_drq_type); DMA_DBG("-----------%s-----------\n", __func__); }