18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * skl-sst-cldma.c - Code Loader DMA handler 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 2015, Intel Corporation. 68c2ecf20Sopenharmony_ci * Author: Subhransu S. Prusty <subhransu.s.prusty@intel.com> 78c2ecf20Sopenharmony_ci * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 88c2ecf20Sopenharmony_ci */ 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci#include <linux/device.h> 118c2ecf20Sopenharmony_ci#include <linux/io.h> 128c2ecf20Sopenharmony_ci#include <linux/mm.h> 138c2ecf20Sopenharmony_ci#include <linux/delay.h> 148c2ecf20Sopenharmony_ci#include "../common/sst-dsp.h" 158c2ecf20Sopenharmony_ci#include "../common/sst-dsp-priv.h" 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_cistatic void skl_cldma_int_enable(struct sst_dsp *ctx) 188c2ecf20Sopenharmony_ci{ 198c2ecf20Sopenharmony_ci sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_ADSPIC, 208c2ecf20Sopenharmony_ci SKL_ADSPIC_CL_DMA, SKL_ADSPIC_CL_DMA); 218c2ecf20Sopenharmony_ci} 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_civoid skl_cldma_int_disable(struct sst_dsp *ctx) 248c2ecf20Sopenharmony_ci{ 258c2ecf20Sopenharmony_ci sst_dsp_shim_update_bits_unlocked(ctx, 268c2ecf20Sopenharmony_ci SKL_ADSP_REG_ADSPIC, SKL_ADSPIC_CL_DMA, 0); 278c2ecf20Sopenharmony_ci} 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_cistatic void skl_cldma_stream_run(struct sst_dsp *ctx, bool enable) 308c2ecf20Sopenharmony_ci{ 318c2ecf20Sopenharmony_ci unsigned char val; 328c2ecf20Sopenharmony_ci int timeout; 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_ci sst_dsp_shim_update_bits_unlocked(ctx, 358c2ecf20Sopenharmony_ci SKL_ADSP_REG_CL_SD_CTL, 368c2ecf20Sopenharmony_ci CL_SD_CTL_RUN_MASK, CL_SD_CTL_RUN(enable)); 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_ci udelay(3); 398c2ecf20Sopenharmony_ci timeout = 300; 408c2ecf20Sopenharmony_ci do { 418c2ecf20Sopenharmony_ci /* waiting for hardware to report that the stream Run bit set */ 428c2ecf20Sopenharmony_ci val = sst_dsp_shim_read(ctx, SKL_ADSP_REG_CL_SD_CTL) & 438c2ecf20Sopenharmony_ci CL_SD_CTL_RUN_MASK; 448c2ecf20Sopenharmony_ci if (enable && val) 458c2ecf20Sopenharmony_ci break; 468c2ecf20Sopenharmony_ci else if (!enable && !val) 478c2ecf20Sopenharmony_ci break; 488c2ecf20Sopenharmony_ci udelay(3); 498c2ecf20Sopenharmony_ci } while (--timeout); 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_ci if (timeout == 0) 528c2ecf20Sopenharmony_ci dev_err(ctx->dev, "Failed to set Run bit=%d enable=%d\n", val, enable); 538c2ecf20Sopenharmony_ci} 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_cistatic void skl_cldma_stream_clear(struct sst_dsp *ctx) 568c2ecf20Sopenharmony_ci{ 578c2ecf20Sopenharmony_ci /* make sure Run bit is cleared before setting stream register */ 588c2ecf20Sopenharmony_ci skl_cldma_stream_run(ctx, 0); 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_ci sst_dsp_shim_update_bits(ctx, SKL_ADSP_REG_CL_SD_CTL, 618c2ecf20Sopenharmony_ci CL_SD_CTL_IOCE_MASK, CL_SD_CTL_IOCE(0)); 628c2ecf20Sopenharmony_ci sst_dsp_shim_update_bits(ctx, SKL_ADSP_REG_CL_SD_CTL, 638c2ecf20Sopenharmony_ci CL_SD_CTL_FEIE_MASK, CL_SD_CTL_FEIE(0)); 648c2ecf20Sopenharmony_ci sst_dsp_shim_update_bits(ctx, SKL_ADSP_REG_CL_SD_CTL, 658c2ecf20Sopenharmony_ci CL_SD_CTL_DEIE_MASK, CL_SD_CTL_DEIE(0)); 668c2ecf20Sopenharmony_ci sst_dsp_shim_update_bits(ctx, SKL_ADSP_REG_CL_SD_CTL, 678c2ecf20Sopenharmony_ci CL_SD_CTL_STRM_MASK, CL_SD_CTL_STRM(0)); 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_ci sst_dsp_shim_write(ctx, SKL_ADSP_REG_CL_SD_BDLPL, CL_SD_BDLPLBA(0)); 708c2ecf20Sopenharmony_ci sst_dsp_shim_write(ctx, SKL_ADSP_REG_CL_SD_BDLPU, 0); 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_ci sst_dsp_shim_write(ctx, SKL_ADSP_REG_CL_SD_CBL, 0); 738c2ecf20Sopenharmony_ci sst_dsp_shim_write(ctx, SKL_ADSP_REG_CL_SD_LVI, 0); 748c2ecf20Sopenharmony_ci} 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_ci/* Code loader helper APIs */ 778c2ecf20Sopenharmony_cistatic void skl_cldma_setup_bdle(struct sst_dsp *ctx, 788c2ecf20Sopenharmony_ci struct snd_dma_buffer *dmab_data, 798c2ecf20Sopenharmony_ci __le32 **bdlp, int size, int with_ioc) 808c2ecf20Sopenharmony_ci{ 818c2ecf20Sopenharmony_ci __le32 *bdl = *bdlp; 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_ci ctx->cl_dev.frags = 0; 848c2ecf20Sopenharmony_ci while (size > 0) { 858c2ecf20Sopenharmony_ci phys_addr_t addr = virt_to_phys(dmab_data->area + 868c2ecf20Sopenharmony_ci (ctx->cl_dev.frags * ctx->cl_dev.bufsize)); 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_ci bdl[0] = cpu_to_le32(lower_32_bits(addr)); 898c2ecf20Sopenharmony_ci bdl[1] = cpu_to_le32(upper_32_bits(addr)); 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_ci bdl[2] = cpu_to_le32(ctx->cl_dev.bufsize); 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_ci size -= ctx->cl_dev.bufsize; 948c2ecf20Sopenharmony_ci bdl[3] = (size || !with_ioc) ? 0 : cpu_to_le32(0x01); 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_ci bdl += 4; 978c2ecf20Sopenharmony_ci ctx->cl_dev.frags++; 988c2ecf20Sopenharmony_ci } 998c2ecf20Sopenharmony_ci} 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_ci/* 1028c2ecf20Sopenharmony_ci * Setup controller 1038c2ecf20Sopenharmony_ci * Configure the registers to update the dma buffer address and 1048c2ecf20Sopenharmony_ci * enable interrupts. 1058c2ecf20Sopenharmony_ci * Note: Using the channel 1 for transfer 1068c2ecf20Sopenharmony_ci */ 1078c2ecf20Sopenharmony_cistatic void skl_cldma_setup_controller(struct sst_dsp *ctx, 1088c2ecf20Sopenharmony_ci struct snd_dma_buffer *dmab_bdl, unsigned int max_size, 1098c2ecf20Sopenharmony_ci u32 count) 1108c2ecf20Sopenharmony_ci{ 1118c2ecf20Sopenharmony_ci skl_cldma_stream_clear(ctx); 1128c2ecf20Sopenharmony_ci sst_dsp_shim_write(ctx, SKL_ADSP_REG_CL_SD_BDLPL, 1138c2ecf20Sopenharmony_ci CL_SD_BDLPLBA(dmab_bdl->addr)); 1148c2ecf20Sopenharmony_ci sst_dsp_shim_write(ctx, SKL_ADSP_REG_CL_SD_BDLPU, 1158c2ecf20Sopenharmony_ci CL_SD_BDLPUBA(dmab_bdl->addr)); 1168c2ecf20Sopenharmony_ci 1178c2ecf20Sopenharmony_ci sst_dsp_shim_write(ctx, SKL_ADSP_REG_CL_SD_CBL, max_size); 1188c2ecf20Sopenharmony_ci sst_dsp_shim_write(ctx, SKL_ADSP_REG_CL_SD_LVI, count - 1); 1198c2ecf20Sopenharmony_ci sst_dsp_shim_update_bits(ctx, SKL_ADSP_REG_CL_SD_CTL, 1208c2ecf20Sopenharmony_ci CL_SD_CTL_IOCE_MASK, CL_SD_CTL_IOCE(1)); 1218c2ecf20Sopenharmony_ci sst_dsp_shim_update_bits(ctx, SKL_ADSP_REG_CL_SD_CTL, 1228c2ecf20Sopenharmony_ci CL_SD_CTL_FEIE_MASK, CL_SD_CTL_FEIE(1)); 1238c2ecf20Sopenharmony_ci sst_dsp_shim_update_bits(ctx, SKL_ADSP_REG_CL_SD_CTL, 1248c2ecf20Sopenharmony_ci CL_SD_CTL_DEIE_MASK, CL_SD_CTL_DEIE(1)); 1258c2ecf20Sopenharmony_ci sst_dsp_shim_update_bits(ctx, SKL_ADSP_REG_CL_SD_CTL, 1268c2ecf20Sopenharmony_ci CL_SD_CTL_STRM_MASK, CL_SD_CTL_STRM(FW_CL_STREAM_NUMBER)); 1278c2ecf20Sopenharmony_ci} 1288c2ecf20Sopenharmony_ci 1298c2ecf20Sopenharmony_cistatic void skl_cldma_setup_spb(struct sst_dsp *ctx, 1308c2ecf20Sopenharmony_ci unsigned int size, bool enable) 1318c2ecf20Sopenharmony_ci{ 1328c2ecf20Sopenharmony_ci if (enable) 1338c2ecf20Sopenharmony_ci sst_dsp_shim_update_bits_unlocked(ctx, 1348c2ecf20Sopenharmony_ci SKL_ADSP_REG_CL_SPBFIFO_SPBFCCTL, 1358c2ecf20Sopenharmony_ci CL_SPBFIFO_SPBFCCTL_SPIBE_MASK, 1368c2ecf20Sopenharmony_ci CL_SPBFIFO_SPBFCCTL_SPIBE(1)); 1378c2ecf20Sopenharmony_ci 1388c2ecf20Sopenharmony_ci sst_dsp_shim_write_unlocked(ctx, SKL_ADSP_REG_CL_SPBFIFO_SPIB, size); 1398c2ecf20Sopenharmony_ci} 1408c2ecf20Sopenharmony_ci 1418c2ecf20Sopenharmony_cistatic void skl_cldma_cleanup_spb(struct sst_dsp *ctx) 1428c2ecf20Sopenharmony_ci{ 1438c2ecf20Sopenharmony_ci sst_dsp_shim_update_bits_unlocked(ctx, 1448c2ecf20Sopenharmony_ci SKL_ADSP_REG_CL_SPBFIFO_SPBFCCTL, 1458c2ecf20Sopenharmony_ci CL_SPBFIFO_SPBFCCTL_SPIBE_MASK, 1468c2ecf20Sopenharmony_ci CL_SPBFIFO_SPBFCCTL_SPIBE(0)); 1478c2ecf20Sopenharmony_ci 1488c2ecf20Sopenharmony_ci sst_dsp_shim_write_unlocked(ctx, SKL_ADSP_REG_CL_SPBFIFO_SPIB, 0); 1498c2ecf20Sopenharmony_ci} 1508c2ecf20Sopenharmony_ci 1518c2ecf20Sopenharmony_cistatic void skl_cldma_cleanup(struct sst_dsp *ctx) 1528c2ecf20Sopenharmony_ci{ 1538c2ecf20Sopenharmony_ci skl_cldma_cleanup_spb(ctx); 1548c2ecf20Sopenharmony_ci skl_cldma_stream_clear(ctx); 1558c2ecf20Sopenharmony_ci 1568c2ecf20Sopenharmony_ci ctx->dsp_ops.free_dma_buf(ctx->dev, &ctx->cl_dev.dmab_data); 1578c2ecf20Sopenharmony_ci ctx->dsp_ops.free_dma_buf(ctx->dev, &ctx->cl_dev.dmab_bdl); 1588c2ecf20Sopenharmony_ci} 1598c2ecf20Sopenharmony_ci 1608c2ecf20Sopenharmony_ciint skl_cldma_wait_interruptible(struct sst_dsp *ctx) 1618c2ecf20Sopenharmony_ci{ 1628c2ecf20Sopenharmony_ci int ret = 0; 1638c2ecf20Sopenharmony_ci 1648c2ecf20Sopenharmony_ci if (!wait_event_timeout(ctx->cl_dev.wait_queue, 1658c2ecf20Sopenharmony_ci ctx->cl_dev.wait_condition, 1668c2ecf20Sopenharmony_ci msecs_to_jiffies(SKL_WAIT_TIMEOUT))) { 1678c2ecf20Sopenharmony_ci dev_err(ctx->dev, "%s: Wait timeout\n", __func__); 1688c2ecf20Sopenharmony_ci ret = -EIO; 1698c2ecf20Sopenharmony_ci goto cleanup; 1708c2ecf20Sopenharmony_ci } 1718c2ecf20Sopenharmony_ci 1728c2ecf20Sopenharmony_ci dev_dbg(ctx->dev, "%s: Event wake\n", __func__); 1738c2ecf20Sopenharmony_ci if (ctx->cl_dev.wake_status != SKL_CL_DMA_BUF_COMPLETE) { 1748c2ecf20Sopenharmony_ci dev_err(ctx->dev, "%s: DMA Error\n", __func__); 1758c2ecf20Sopenharmony_ci ret = -EIO; 1768c2ecf20Sopenharmony_ci } 1778c2ecf20Sopenharmony_ci 1788c2ecf20Sopenharmony_cicleanup: 1798c2ecf20Sopenharmony_ci ctx->cl_dev.wake_status = SKL_CL_DMA_STATUS_NONE; 1808c2ecf20Sopenharmony_ci return ret; 1818c2ecf20Sopenharmony_ci} 1828c2ecf20Sopenharmony_ci 1838c2ecf20Sopenharmony_cistatic void skl_cldma_stop(struct sst_dsp *ctx) 1848c2ecf20Sopenharmony_ci{ 1858c2ecf20Sopenharmony_ci skl_cldma_stream_run(ctx, false); 1868c2ecf20Sopenharmony_ci} 1878c2ecf20Sopenharmony_ci 1888c2ecf20Sopenharmony_cistatic void skl_cldma_fill_buffer(struct sst_dsp *ctx, unsigned int size, 1898c2ecf20Sopenharmony_ci const void *curr_pos, bool intr_enable, bool trigger) 1908c2ecf20Sopenharmony_ci{ 1918c2ecf20Sopenharmony_ci dev_dbg(ctx->dev, "Size: %x, intr_enable: %d\n", size, intr_enable); 1928c2ecf20Sopenharmony_ci dev_dbg(ctx->dev, "buf_pos_index:%d, trigger:%d\n", 1938c2ecf20Sopenharmony_ci ctx->cl_dev.dma_buffer_offset, trigger); 1948c2ecf20Sopenharmony_ci dev_dbg(ctx->dev, "spib position: %d\n", ctx->cl_dev.curr_spib_pos); 1958c2ecf20Sopenharmony_ci 1968c2ecf20Sopenharmony_ci /* 1978c2ecf20Sopenharmony_ci * Check if the size exceeds buffer boundary. If it exceeds 1988c2ecf20Sopenharmony_ci * max_buffer size, then copy till buffer size and then copy 1998c2ecf20Sopenharmony_ci * remaining buffer from the start of ring buffer. 2008c2ecf20Sopenharmony_ci */ 2018c2ecf20Sopenharmony_ci if (ctx->cl_dev.dma_buffer_offset + size > ctx->cl_dev.bufsize) { 2028c2ecf20Sopenharmony_ci unsigned int size_b = ctx->cl_dev.bufsize - 2038c2ecf20Sopenharmony_ci ctx->cl_dev.dma_buffer_offset; 2048c2ecf20Sopenharmony_ci memcpy(ctx->cl_dev.dmab_data.area + ctx->cl_dev.dma_buffer_offset, 2058c2ecf20Sopenharmony_ci curr_pos, size_b); 2068c2ecf20Sopenharmony_ci size -= size_b; 2078c2ecf20Sopenharmony_ci curr_pos += size_b; 2088c2ecf20Sopenharmony_ci ctx->cl_dev.dma_buffer_offset = 0; 2098c2ecf20Sopenharmony_ci } 2108c2ecf20Sopenharmony_ci 2118c2ecf20Sopenharmony_ci memcpy(ctx->cl_dev.dmab_data.area + ctx->cl_dev.dma_buffer_offset, 2128c2ecf20Sopenharmony_ci curr_pos, size); 2138c2ecf20Sopenharmony_ci 2148c2ecf20Sopenharmony_ci if (ctx->cl_dev.curr_spib_pos == ctx->cl_dev.bufsize) 2158c2ecf20Sopenharmony_ci ctx->cl_dev.dma_buffer_offset = 0; 2168c2ecf20Sopenharmony_ci else 2178c2ecf20Sopenharmony_ci ctx->cl_dev.dma_buffer_offset = ctx->cl_dev.curr_spib_pos; 2188c2ecf20Sopenharmony_ci 2198c2ecf20Sopenharmony_ci ctx->cl_dev.wait_condition = false; 2208c2ecf20Sopenharmony_ci 2218c2ecf20Sopenharmony_ci if (intr_enable) 2228c2ecf20Sopenharmony_ci skl_cldma_int_enable(ctx); 2238c2ecf20Sopenharmony_ci 2248c2ecf20Sopenharmony_ci ctx->cl_dev.ops.cl_setup_spb(ctx, ctx->cl_dev.curr_spib_pos, trigger); 2258c2ecf20Sopenharmony_ci if (trigger) 2268c2ecf20Sopenharmony_ci ctx->cl_dev.ops.cl_trigger(ctx, true); 2278c2ecf20Sopenharmony_ci} 2288c2ecf20Sopenharmony_ci 2298c2ecf20Sopenharmony_ci/* 2308c2ecf20Sopenharmony_ci * The CL dma doesn't have any way to update the transfer status until a BDL 2318c2ecf20Sopenharmony_ci * buffer is fully transferred 2328c2ecf20Sopenharmony_ci * 2338c2ecf20Sopenharmony_ci * So Copying is divided in two parts. 2348c2ecf20Sopenharmony_ci * 1. Interrupt on buffer done where the size to be transferred is more than 2358c2ecf20Sopenharmony_ci * ring buffer size. 2368c2ecf20Sopenharmony_ci * 2. Polling on fw register to identify if data left to transferred doesn't 2378c2ecf20Sopenharmony_ci * fill the ring buffer. Caller takes care of polling the required status 2388c2ecf20Sopenharmony_ci * register to identify the transfer status. 2398c2ecf20Sopenharmony_ci * 3. if wait flag is set, waits for DBL interrupt to copy the next chunk till 2408c2ecf20Sopenharmony_ci * bytes_left is 0. 2418c2ecf20Sopenharmony_ci * if wait flag is not set, doesn't wait for BDL interrupt. after ccopying 2428c2ecf20Sopenharmony_ci * the first chunk return the no of bytes_left to be copied. 2438c2ecf20Sopenharmony_ci */ 2448c2ecf20Sopenharmony_cistatic int 2458c2ecf20Sopenharmony_ciskl_cldma_copy_to_buf(struct sst_dsp *ctx, const void *bin, 2468c2ecf20Sopenharmony_ci u32 total_size, bool wait) 2478c2ecf20Sopenharmony_ci{ 2488c2ecf20Sopenharmony_ci int ret; 2498c2ecf20Sopenharmony_ci bool start = true; 2508c2ecf20Sopenharmony_ci unsigned int excess_bytes; 2518c2ecf20Sopenharmony_ci u32 size; 2528c2ecf20Sopenharmony_ci unsigned int bytes_left = total_size; 2538c2ecf20Sopenharmony_ci const void *curr_pos = bin; 2548c2ecf20Sopenharmony_ci 2558c2ecf20Sopenharmony_ci if (total_size <= 0) 2568c2ecf20Sopenharmony_ci return -EINVAL; 2578c2ecf20Sopenharmony_ci 2588c2ecf20Sopenharmony_ci dev_dbg(ctx->dev, "%s: Total binary size: %u\n", __func__, bytes_left); 2598c2ecf20Sopenharmony_ci 2608c2ecf20Sopenharmony_ci while (bytes_left) { 2618c2ecf20Sopenharmony_ci if (bytes_left > ctx->cl_dev.bufsize) { 2628c2ecf20Sopenharmony_ci 2638c2ecf20Sopenharmony_ci /* 2648c2ecf20Sopenharmony_ci * dma transfers only till the write pointer as 2658c2ecf20Sopenharmony_ci * updated in spib 2668c2ecf20Sopenharmony_ci */ 2678c2ecf20Sopenharmony_ci if (ctx->cl_dev.curr_spib_pos == 0) 2688c2ecf20Sopenharmony_ci ctx->cl_dev.curr_spib_pos = ctx->cl_dev.bufsize; 2698c2ecf20Sopenharmony_ci 2708c2ecf20Sopenharmony_ci size = ctx->cl_dev.bufsize; 2718c2ecf20Sopenharmony_ci skl_cldma_fill_buffer(ctx, size, curr_pos, true, start); 2728c2ecf20Sopenharmony_ci 2738c2ecf20Sopenharmony_ci if (wait) { 2748c2ecf20Sopenharmony_ci start = false; 2758c2ecf20Sopenharmony_ci ret = skl_cldma_wait_interruptible(ctx); 2768c2ecf20Sopenharmony_ci if (ret < 0) { 2778c2ecf20Sopenharmony_ci skl_cldma_stop(ctx); 2788c2ecf20Sopenharmony_ci return ret; 2798c2ecf20Sopenharmony_ci } 2808c2ecf20Sopenharmony_ci } 2818c2ecf20Sopenharmony_ci } else { 2828c2ecf20Sopenharmony_ci skl_cldma_int_disable(ctx); 2838c2ecf20Sopenharmony_ci 2848c2ecf20Sopenharmony_ci if ((ctx->cl_dev.curr_spib_pos + bytes_left) 2858c2ecf20Sopenharmony_ci <= ctx->cl_dev.bufsize) { 2868c2ecf20Sopenharmony_ci ctx->cl_dev.curr_spib_pos += bytes_left; 2878c2ecf20Sopenharmony_ci } else { 2888c2ecf20Sopenharmony_ci excess_bytes = bytes_left - 2898c2ecf20Sopenharmony_ci (ctx->cl_dev.bufsize - 2908c2ecf20Sopenharmony_ci ctx->cl_dev.curr_spib_pos); 2918c2ecf20Sopenharmony_ci ctx->cl_dev.curr_spib_pos = excess_bytes; 2928c2ecf20Sopenharmony_ci } 2938c2ecf20Sopenharmony_ci 2948c2ecf20Sopenharmony_ci size = bytes_left; 2958c2ecf20Sopenharmony_ci skl_cldma_fill_buffer(ctx, size, 2968c2ecf20Sopenharmony_ci curr_pos, false, start); 2978c2ecf20Sopenharmony_ci } 2988c2ecf20Sopenharmony_ci bytes_left -= size; 2998c2ecf20Sopenharmony_ci curr_pos = curr_pos + size; 3008c2ecf20Sopenharmony_ci if (!wait) 3018c2ecf20Sopenharmony_ci return bytes_left; 3028c2ecf20Sopenharmony_ci } 3038c2ecf20Sopenharmony_ci 3048c2ecf20Sopenharmony_ci return bytes_left; 3058c2ecf20Sopenharmony_ci} 3068c2ecf20Sopenharmony_ci 3078c2ecf20Sopenharmony_civoid skl_cldma_process_intr(struct sst_dsp *ctx) 3088c2ecf20Sopenharmony_ci{ 3098c2ecf20Sopenharmony_ci u8 cl_dma_intr_status; 3108c2ecf20Sopenharmony_ci 3118c2ecf20Sopenharmony_ci cl_dma_intr_status = 3128c2ecf20Sopenharmony_ci sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_CL_SD_STS); 3138c2ecf20Sopenharmony_ci 3148c2ecf20Sopenharmony_ci if (!(cl_dma_intr_status & SKL_CL_DMA_SD_INT_COMPLETE)) 3158c2ecf20Sopenharmony_ci ctx->cl_dev.wake_status = SKL_CL_DMA_ERR; 3168c2ecf20Sopenharmony_ci else 3178c2ecf20Sopenharmony_ci ctx->cl_dev.wake_status = SKL_CL_DMA_BUF_COMPLETE; 3188c2ecf20Sopenharmony_ci 3198c2ecf20Sopenharmony_ci ctx->cl_dev.wait_condition = true; 3208c2ecf20Sopenharmony_ci wake_up(&ctx->cl_dev.wait_queue); 3218c2ecf20Sopenharmony_ci} 3228c2ecf20Sopenharmony_ci 3238c2ecf20Sopenharmony_ciint skl_cldma_prepare(struct sst_dsp *ctx) 3248c2ecf20Sopenharmony_ci{ 3258c2ecf20Sopenharmony_ci int ret; 3268c2ecf20Sopenharmony_ci __le32 *bdl; 3278c2ecf20Sopenharmony_ci 3288c2ecf20Sopenharmony_ci ctx->cl_dev.bufsize = SKL_MAX_BUFFER_SIZE; 3298c2ecf20Sopenharmony_ci 3308c2ecf20Sopenharmony_ci /* Allocate cl ops */ 3318c2ecf20Sopenharmony_ci ctx->cl_dev.ops.cl_setup_bdle = skl_cldma_setup_bdle; 3328c2ecf20Sopenharmony_ci ctx->cl_dev.ops.cl_setup_controller = skl_cldma_setup_controller; 3338c2ecf20Sopenharmony_ci ctx->cl_dev.ops.cl_setup_spb = skl_cldma_setup_spb; 3348c2ecf20Sopenharmony_ci ctx->cl_dev.ops.cl_cleanup_spb = skl_cldma_cleanup_spb; 3358c2ecf20Sopenharmony_ci ctx->cl_dev.ops.cl_trigger = skl_cldma_stream_run; 3368c2ecf20Sopenharmony_ci ctx->cl_dev.ops.cl_cleanup_controller = skl_cldma_cleanup; 3378c2ecf20Sopenharmony_ci ctx->cl_dev.ops.cl_copy_to_dmabuf = skl_cldma_copy_to_buf; 3388c2ecf20Sopenharmony_ci ctx->cl_dev.ops.cl_stop_dma = skl_cldma_stop; 3398c2ecf20Sopenharmony_ci 3408c2ecf20Sopenharmony_ci /* Allocate buffer*/ 3418c2ecf20Sopenharmony_ci ret = ctx->dsp_ops.alloc_dma_buf(ctx->dev, 3428c2ecf20Sopenharmony_ci &ctx->cl_dev.dmab_data, ctx->cl_dev.bufsize); 3438c2ecf20Sopenharmony_ci if (ret < 0) { 3448c2ecf20Sopenharmony_ci dev_err(ctx->dev, "Alloc buffer for base fw failed: %x\n", ret); 3458c2ecf20Sopenharmony_ci return ret; 3468c2ecf20Sopenharmony_ci } 3478c2ecf20Sopenharmony_ci /* Setup Code loader BDL */ 3488c2ecf20Sopenharmony_ci ret = ctx->dsp_ops.alloc_dma_buf(ctx->dev, 3498c2ecf20Sopenharmony_ci &ctx->cl_dev.dmab_bdl, PAGE_SIZE); 3508c2ecf20Sopenharmony_ci if (ret < 0) { 3518c2ecf20Sopenharmony_ci dev_err(ctx->dev, "Alloc buffer for blde failed: %x\n", ret); 3528c2ecf20Sopenharmony_ci ctx->dsp_ops.free_dma_buf(ctx->dev, &ctx->cl_dev.dmab_data); 3538c2ecf20Sopenharmony_ci return ret; 3548c2ecf20Sopenharmony_ci } 3558c2ecf20Sopenharmony_ci bdl = (__le32 *)ctx->cl_dev.dmab_bdl.area; 3568c2ecf20Sopenharmony_ci 3578c2ecf20Sopenharmony_ci /* Allocate BDLs */ 3588c2ecf20Sopenharmony_ci ctx->cl_dev.ops.cl_setup_bdle(ctx, &ctx->cl_dev.dmab_data, 3598c2ecf20Sopenharmony_ci &bdl, ctx->cl_dev.bufsize, 1); 3608c2ecf20Sopenharmony_ci ctx->cl_dev.ops.cl_setup_controller(ctx, &ctx->cl_dev.dmab_bdl, 3618c2ecf20Sopenharmony_ci ctx->cl_dev.bufsize, ctx->cl_dev.frags); 3628c2ecf20Sopenharmony_ci 3638c2ecf20Sopenharmony_ci ctx->cl_dev.curr_spib_pos = 0; 3648c2ecf20Sopenharmony_ci ctx->cl_dev.dma_buffer_offset = 0; 3658c2ecf20Sopenharmony_ci init_waitqueue_head(&ctx->cl_dev.wait_queue); 3668c2ecf20Sopenharmony_ci 3678c2ecf20Sopenharmony_ci return ret; 3688c2ecf20Sopenharmony_ci} 369