static int ss_dma_src_config(sunxi_ss_t *sss, void *ctx, ss_aes_req_ctx_t *req_ctx, int len, int cb) { int flow = ((ss_comm_ctx_t *)ctx)->flow; ss_dma_info_t *info = &req_ctx->dma_src; struct dma_slave_config dma_conf = {0}; struct dma_async_tx_descriptor *dma_desc = NULL; info->dir = DMA_MEM_TO_MEM; dma_conf.direction = info->dir; #ifdef SS_CTR_MODE_ENABLE if (req_ctx->mode == SS_AES_MODE_CTR) dma_conf.src_addr_width = dma_conf.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE; else #endif dma_conf.src_addr_width = dma_conf.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; dma_conf.src_maxburst = 1; dma_conf.dst_maxburst = 1; dma_conf.slave_id = sunxi_slave_id(DRQDST_SDRAM, DRQSRC_SDRAM); dmaengine_slave_config(info->chan, &dma_conf); ss_sg_table_init(&info->sgt_for_cp, info->sg, len, sss->flows[flow].buf_src, sss->flows[flow].buf_src_dma); SS_DBG("chan: 0x%p, info->sgt_for_cp.sgl: 0x%p \n", info->chan, info->sgt_for_cp.sgl); info->nents = info->sgt_for_cp.nents; SS_DBG("flow: %d, sg num: %d, total len: %d \n", flow, info->nents, len); dma_map_sg(&sss->pdev->dev, info->sg, info->nents, info->dir); dma_map_sg(&sss->pdev->dev, info->sgt_for_cp.sgl, info->nents, info->dir); if (SS_METHOD_IS_HASH(req_ctx->type)) { /* Total len is to small, so there is no data for DMA. */ if (len < SHA1_BLOCK_SIZE) return 1; ss_hash_padding_sg_prepare(&info->sg[info->nents-1], len); ss_hash_padding_sg_prepare(&info->sgt_for_cp.sgl[info->nents-1], len); } dma_desc = info->chan->device->device_prep_dma_sg(info->chan, info->sgt_for_cp.sgl, info->nents, info->sg, info->nents, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); if (!dma_desc) { SS_ERR("dmaengine_prep_slave_sg() failed!\n"); return -1; } if (cb == 1) { dma_desc->callback = ss_dma_cb; dma_desc->callback_param = (void *)req_ctx; } dmaengine_submit(dma_desc); return 0; }
/* ctx - only used for HASH. */ static int ss_dma_src_config(sunxi_ss_t *sss, void *ctx, ss_aes_req_ctx_t *req_ctx, int len, int cb) { int nents = 0; int npages = 0; ss_dma_info_t *info = &req_ctx->dma_src; struct dma_slave_config dma_conf = {0}; struct dma_async_tx_descriptor *dma_desc = NULL; info->dir = DMA_MEM_TO_DEV; dma_conf.direction = info->dir; dma_conf.dst_addr = sss->base_addr_phy + SS_REG_RXFIFO; dma_conf.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; dma_conf.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; dma_conf.src_maxburst = 1; dma_conf.dst_maxburst = 1; dma_conf.slave_id = sunxi_slave_id(DRQDST_SS, DRQSRC_SDRAM); dmaengine_slave_config(info->chan, &dma_conf); npages = ss_sg_cnt(info->sg, len); WARN_ON(npages == 0); nents = dma_map_sg(&sss->pdev->dev, info->sg, npages, info->dir); SS_DBG("npages = %d, nents = %d, len = %d, sg.len = %d \n", npages, nents, len, sg_dma_len(info->sg)); if (!nents) { SS_ERR("dma_map_sg() error\n"); return -EINVAL; } info->nents = nents; if (SS_METHOD_IS_HASH(req_ctx->type)) { ss_hash_padding_sg_prepare(&info->sg[nents-1], len); /* Total len is too small, so there is no data for DMA. */ if (len < SHA1_BLOCK_SIZE) return 1; } dma_desc = dmaengine_prep_slave_sg(info->chan, info->sg, nents, info->dir, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); if (!dma_desc) { SS_ERR("dmaengine_prep_slave_sg() failed!\n"); return -1; } if (cb == 1) { dma_desc->callback = ss_dma_cb; dma_desc->callback_param = (void *)req_ctx; } dmaengine_submit(dma_desc); return 0; }