18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * skl-sst-dsp.c - SKL SST library generic function 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 2014-15, Intel Corporation. 68c2ecf20Sopenharmony_ci * Author:Rafal Redzimski <rafal.f.redzimski@intel.com> 78c2ecf20Sopenharmony_ci * Jeeja KP <jeeja.kp@intel.com> 88c2ecf20Sopenharmony_ci * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 98c2ecf20Sopenharmony_ci */ 108c2ecf20Sopenharmony_ci#include <sound/pcm.h> 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_ci#include "../common/sst-dsp.h" 138c2ecf20Sopenharmony_ci#include "../common/sst-ipc.h" 148c2ecf20Sopenharmony_ci#include "../common/sst-dsp-priv.h" 158c2ecf20Sopenharmony_ci#include "skl.h" 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_ci/* various timeout values */ 188c2ecf20Sopenharmony_ci#define SKL_DSP_PU_TO 50 198c2ecf20Sopenharmony_ci#define SKL_DSP_PD_TO 50 208c2ecf20Sopenharmony_ci#define SKL_DSP_RESET_TO 50 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_civoid skl_dsp_set_state_locked(struct sst_dsp *ctx, int state) 238c2ecf20Sopenharmony_ci{ 248c2ecf20Sopenharmony_ci mutex_lock(&ctx->mutex); 258c2ecf20Sopenharmony_ci ctx->sst_state = state; 268c2ecf20Sopenharmony_ci mutex_unlock(&ctx->mutex); 278c2ecf20Sopenharmony_ci} 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_ci/* 308c2ecf20Sopenharmony_ci * Initialize core power state and usage count. To be called after 318c2ecf20Sopenharmony_ci * successful first boot. Hence core 0 will be running and other cores 328c2ecf20Sopenharmony_ci * will be reset 338c2ecf20Sopenharmony_ci */ 348c2ecf20Sopenharmony_civoid skl_dsp_init_core_state(struct sst_dsp *ctx) 358c2ecf20Sopenharmony_ci{ 368c2ecf20Sopenharmony_ci struct skl_dev *skl = ctx->thread_context; 378c2ecf20Sopenharmony_ci int i; 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_ci skl->cores.state[SKL_DSP_CORE0_ID] = SKL_DSP_RUNNING; 408c2ecf20Sopenharmony_ci skl->cores.usage_count[SKL_DSP_CORE0_ID] = 1; 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_ci for (i = SKL_DSP_CORE0_ID + 1; i < skl->cores.count; i++) { 438c2ecf20Sopenharmony_ci skl->cores.state[i] = SKL_DSP_RESET; 448c2ecf20Sopenharmony_ci skl->cores.usage_count[i] = 0; 458c2ecf20Sopenharmony_ci } 468c2ecf20Sopenharmony_ci} 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_ci/* Get the mask for all enabled cores */ 498c2ecf20Sopenharmony_ciunsigned int skl_dsp_get_enabled_cores(struct sst_dsp *ctx) 508c2ecf20Sopenharmony_ci{ 518c2ecf20Sopenharmony_ci struct skl_dev *skl = ctx->thread_context; 528c2ecf20Sopenharmony_ci unsigned int core_mask, en_cores_mask; 538c2ecf20Sopenharmony_ci u32 val; 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_ci core_mask = SKL_DSP_CORES_MASK(skl->cores.count); 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_ci val = sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPCS); 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_ci /* Cores having CPA bit set */ 608c2ecf20Sopenharmony_ci en_cores_mask = (val & SKL_ADSPCS_CPA_MASK(core_mask)) >> 618c2ecf20Sopenharmony_ci SKL_ADSPCS_CPA_SHIFT; 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_ci /* And cores having CRST bit cleared */ 648c2ecf20Sopenharmony_ci en_cores_mask &= (~val & SKL_ADSPCS_CRST_MASK(core_mask)) >> 658c2ecf20Sopenharmony_ci SKL_ADSPCS_CRST_SHIFT; 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_ci /* And cores having CSTALL bit cleared */ 688c2ecf20Sopenharmony_ci en_cores_mask &= (~val & SKL_ADSPCS_CSTALL_MASK(core_mask)) >> 698c2ecf20Sopenharmony_ci SKL_ADSPCS_CSTALL_SHIFT; 708c2ecf20Sopenharmony_ci en_cores_mask &= core_mask; 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_ci dev_dbg(ctx->dev, "DSP enabled cores mask = %x\n", en_cores_mask); 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_ci return en_cores_mask; 758c2ecf20Sopenharmony_ci} 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_cistatic int 788c2ecf20Sopenharmony_ciskl_dsp_core_set_reset_state(struct sst_dsp *ctx, unsigned int core_mask) 798c2ecf20Sopenharmony_ci{ 808c2ecf20Sopenharmony_ci int ret; 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_ci /* update bits */ 838c2ecf20Sopenharmony_ci sst_dsp_shim_update_bits_unlocked(ctx, 848c2ecf20Sopenharmony_ci SKL_ADSP_REG_ADSPCS, SKL_ADSPCS_CRST_MASK(core_mask), 858c2ecf20Sopenharmony_ci SKL_ADSPCS_CRST_MASK(core_mask)); 868c2ecf20Sopenharmony_ci 878c2ecf20Sopenharmony_ci /* poll with timeout to check if operation successful */ 888c2ecf20Sopenharmony_ci ret = sst_dsp_register_poll(ctx, 898c2ecf20Sopenharmony_ci SKL_ADSP_REG_ADSPCS, 908c2ecf20Sopenharmony_ci SKL_ADSPCS_CRST_MASK(core_mask), 918c2ecf20Sopenharmony_ci SKL_ADSPCS_CRST_MASK(core_mask), 928c2ecf20Sopenharmony_ci SKL_DSP_RESET_TO, 938c2ecf20Sopenharmony_ci "Set reset"); 948c2ecf20Sopenharmony_ci if ((sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPCS) & 958c2ecf20Sopenharmony_ci SKL_ADSPCS_CRST_MASK(core_mask)) != 968c2ecf20Sopenharmony_ci SKL_ADSPCS_CRST_MASK(core_mask)) { 978c2ecf20Sopenharmony_ci dev_err(ctx->dev, "Set reset state failed: core_mask %x\n", 988c2ecf20Sopenharmony_ci core_mask); 998c2ecf20Sopenharmony_ci ret = -EIO; 1008c2ecf20Sopenharmony_ci } 1018c2ecf20Sopenharmony_ci 1028c2ecf20Sopenharmony_ci return ret; 1038c2ecf20Sopenharmony_ci} 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_ciint skl_dsp_core_unset_reset_state( 1068c2ecf20Sopenharmony_ci struct sst_dsp *ctx, unsigned int core_mask) 1078c2ecf20Sopenharmony_ci{ 1088c2ecf20Sopenharmony_ci int ret; 1098c2ecf20Sopenharmony_ci 1108c2ecf20Sopenharmony_ci dev_dbg(ctx->dev, "In %s\n", __func__); 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_ci /* update bits */ 1138c2ecf20Sopenharmony_ci sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_ADSPCS, 1148c2ecf20Sopenharmony_ci SKL_ADSPCS_CRST_MASK(core_mask), 0); 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_ci /* poll with timeout to check if operation successful */ 1178c2ecf20Sopenharmony_ci ret = sst_dsp_register_poll(ctx, 1188c2ecf20Sopenharmony_ci SKL_ADSP_REG_ADSPCS, 1198c2ecf20Sopenharmony_ci SKL_ADSPCS_CRST_MASK(core_mask), 1208c2ecf20Sopenharmony_ci 0, 1218c2ecf20Sopenharmony_ci SKL_DSP_RESET_TO, 1228c2ecf20Sopenharmony_ci "Unset reset"); 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_ci if ((sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPCS) & 1258c2ecf20Sopenharmony_ci SKL_ADSPCS_CRST_MASK(core_mask)) != 0) { 1268c2ecf20Sopenharmony_ci dev_err(ctx->dev, "Unset reset state failed: core_mask %x\n", 1278c2ecf20Sopenharmony_ci core_mask); 1288c2ecf20Sopenharmony_ci ret = -EIO; 1298c2ecf20Sopenharmony_ci } 1308c2ecf20Sopenharmony_ci 1318c2ecf20Sopenharmony_ci return ret; 1328c2ecf20Sopenharmony_ci} 1338c2ecf20Sopenharmony_ci 1348c2ecf20Sopenharmony_cistatic bool 1358c2ecf20Sopenharmony_ciis_skl_dsp_core_enable(struct sst_dsp *ctx, unsigned int core_mask) 1368c2ecf20Sopenharmony_ci{ 1378c2ecf20Sopenharmony_ci int val; 1388c2ecf20Sopenharmony_ci bool is_enable; 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_ci val = sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPCS); 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_ci is_enable = ((val & SKL_ADSPCS_CPA_MASK(core_mask)) && 1438c2ecf20Sopenharmony_ci (val & SKL_ADSPCS_SPA_MASK(core_mask)) && 1448c2ecf20Sopenharmony_ci !(val & SKL_ADSPCS_CRST_MASK(core_mask)) && 1458c2ecf20Sopenharmony_ci !(val & SKL_ADSPCS_CSTALL_MASK(core_mask))); 1468c2ecf20Sopenharmony_ci 1478c2ecf20Sopenharmony_ci dev_dbg(ctx->dev, "DSP core(s) enabled? %d : core_mask %x\n", 1488c2ecf20Sopenharmony_ci is_enable, core_mask); 1498c2ecf20Sopenharmony_ci 1508c2ecf20Sopenharmony_ci return is_enable; 1518c2ecf20Sopenharmony_ci} 1528c2ecf20Sopenharmony_ci 1538c2ecf20Sopenharmony_cistatic int skl_dsp_reset_core(struct sst_dsp *ctx, unsigned int core_mask) 1548c2ecf20Sopenharmony_ci{ 1558c2ecf20Sopenharmony_ci /* stall core */ 1568c2ecf20Sopenharmony_ci sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_ADSPCS, 1578c2ecf20Sopenharmony_ci SKL_ADSPCS_CSTALL_MASK(core_mask), 1588c2ecf20Sopenharmony_ci SKL_ADSPCS_CSTALL_MASK(core_mask)); 1598c2ecf20Sopenharmony_ci 1608c2ecf20Sopenharmony_ci /* set reset state */ 1618c2ecf20Sopenharmony_ci return skl_dsp_core_set_reset_state(ctx, core_mask); 1628c2ecf20Sopenharmony_ci} 1638c2ecf20Sopenharmony_ci 1648c2ecf20Sopenharmony_ciint skl_dsp_start_core(struct sst_dsp *ctx, unsigned int core_mask) 1658c2ecf20Sopenharmony_ci{ 1668c2ecf20Sopenharmony_ci int ret; 1678c2ecf20Sopenharmony_ci 1688c2ecf20Sopenharmony_ci /* unset reset state */ 1698c2ecf20Sopenharmony_ci ret = skl_dsp_core_unset_reset_state(ctx, core_mask); 1708c2ecf20Sopenharmony_ci if (ret < 0) 1718c2ecf20Sopenharmony_ci return ret; 1728c2ecf20Sopenharmony_ci 1738c2ecf20Sopenharmony_ci /* run core */ 1748c2ecf20Sopenharmony_ci dev_dbg(ctx->dev, "unstall/run core: core_mask = %x\n", core_mask); 1758c2ecf20Sopenharmony_ci sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_ADSPCS, 1768c2ecf20Sopenharmony_ci SKL_ADSPCS_CSTALL_MASK(core_mask), 0); 1778c2ecf20Sopenharmony_ci 1788c2ecf20Sopenharmony_ci if (!is_skl_dsp_core_enable(ctx, core_mask)) { 1798c2ecf20Sopenharmony_ci skl_dsp_reset_core(ctx, core_mask); 1808c2ecf20Sopenharmony_ci dev_err(ctx->dev, "DSP start core failed: core_mask %x\n", 1818c2ecf20Sopenharmony_ci core_mask); 1828c2ecf20Sopenharmony_ci ret = -EIO; 1838c2ecf20Sopenharmony_ci } 1848c2ecf20Sopenharmony_ci 1858c2ecf20Sopenharmony_ci return ret; 1868c2ecf20Sopenharmony_ci} 1878c2ecf20Sopenharmony_ci 1888c2ecf20Sopenharmony_ciint skl_dsp_core_power_up(struct sst_dsp *ctx, unsigned int core_mask) 1898c2ecf20Sopenharmony_ci{ 1908c2ecf20Sopenharmony_ci int ret; 1918c2ecf20Sopenharmony_ci 1928c2ecf20Sopenharmony_ci /* update bits */ 1938c2ecf20Sopenharmony_ci sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_ADSPCS, 1948c2ecf20Sopenharmony_ci SKL_ADSPCS_SPA_MASK(core_mask), 1958c2ecf20Sopenharmony_ci SKL_ADSPCS_SPA_MASK(core_mask)); 1968c2ecf20Sopenharmony_ci 1978c2ecf20Sopenharmony_ci /* poll with timeout to check if operation successful */ 1988c2ecf20Sopenharmony_ci ret = sst_dsp_register_poll(ctx, 1998c2ecf20Sopenharmony_ci SKL_ADSP_REG_ADSPCS, 2008c2ecf20Sopenharmony_ci SKL_ADSPCS_CPA_MASK(core_mask), 2018c2ecf20Sopenharmony_ci SKL_ADSPCS_CPA_MASK(core_mask), 2028c2ecf20Sopenharmony_ci SKL_DSP_PU_TO, 2038c2ecf20Sopenharmony_ci "Power up"); 2048c2ecf20Sopenharmony_ci 2058c2ecf20Sopenharmony_ci if ((sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPCS) & 2068c2ecf20Sopenharmony_ci SKL_ADSPCS_CPA_MASK(core_mask)) != 2078c2ecf20Sopenharmony_ci SKL_ADSPCS_CPA_MASK(core_mask)) { 2088c2ecf20Sopenharmony_ci dev_err(ctx->dev, "DSP core power up failed: core_mask %x\n", 2098c2ecf20Sopenharmony_ci core_mask); 2108c2ecf20Sopenharmony_ci ret = -EIO; 2118c2ecf20Sopenharmony_ci } 2128c2ecf20Sopenharmony_ci 2138c2ecf20Sopenharmony_ci return ret; 2148c2ecf20Sopenharmony_ci} 2158c2ecf20Sopenharmony_ci 2168c2ecf20Sopenharmony_ciint skl_dsp_core_power_down(struct sst_dsp *ctx, unsigned int core_mask) 2178c2ecf20Sopenharmony_ci{ 2188c2ecf20Sopenharmony_ci /* update bits */ 2198c2ecf20Sopenharmony_ci sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_ADSPCS, 2208c2ecf20Sopenharmony_ci SKL_ADSPCS_SPA_MASK(core_mask), 0); 2218c2ecf20Sopenharmony_ci 2228c2ecf20Sopenharmony_ci /* poll with timeout to check if operation successful */ 2238c2ecf20Sopenharmony_ci return sst_dsp_register_poll(ctx, 2248c2ecf20Sopenharmony_ci SKL_ADSP_REG_ADSPCS, 2258c2ecf20Sopenharmony_ci SKL_ADSPCS_CPA_MASK(core_mask), 2268c2ecf20Sopenharmony_ci 0, 2278c2ecf20Sopenharmony_ci SKL_DSP_PD_TO, 2288c2ecf20Sopenharmony_ci "Power down"); 2298c2ecf20Sopenharmony_ci} 2308c2ecf20Sopenharmony_ci 2318c2ecf20Sopenharmony_ciint skl_dsp_enable_core(struct sst_dsp *ctx, unsigned int core_mask) 2328c2ecf20Sopenharmony_ci{ 2338c2ecf20Sopenharmony_ci int ret; 2348c2ecf20Sopenharmony_ci 2358c2ecf20Sopenharmony_ci /* power up */ 2368c2ecf20Sopenharmony_ci ret = skl_dsp_core_power_up(ctx, core_mask); 2378c2ecf20Sopenharmony_ci if (ret < 0) { 2388c2ecf20Sopenharmony_ci dev_err(ctx->dev, "dsp core power up failed: core_mask %x\n", 2398c2ecf20Sopenharmony_ci core_mask); 2408c2ecf20Sopenharmony_ci return ret; 2418c2ecf20Sopenharmony_ci } 2428c2ecf20Sopenharmony_ci 2438c2ecf20Sopenharmony_ci return skl_dsp_start_core(ctx, core_mask); 2448c2ecf20Sopenharmony_ci} 2458c2ecf20Sopenharmony_ci 2468c2ecf20Sopenharmony_ciint skl_dsp_disable_core(struct sst_dsp *ctx, unsigned int core_mask) 2478c2ecf20Sopenharmony_ci{ 2488c2ecf20Sopenharmony_ci int ret; 2498c2ecf20Sopenharmony_ci 2508c2ecf20Sopenharmony_ci ret = skl_dsp_reset_core(ctx, core_mask); 2518c2ecf20Sopenharmony_ci if (ret < 0) { 2528c2ecf20Sopenharmony_ci dev_err(ctx->dev, "dsp core reset failed: core_mask %x\n", 2538c2ecf20Sopenharmony_ci core_mask); 2548c2ecf20Sopenharmony_ci return ret; 2558c2ecf20Sopenharmony_ci } 2568c2ecf20Sopenharmony_ci 2578c2ecf20Sopenharmony_ci /* power down core*/ 2588c2ecf20Sopenharmony_ci ret = skl_dsp_core_power_down(ctx, core_mask); 2598c2ecf20Sopenharmony_ci if (ret < 0) { 2608c2ecf20Sopenharmony_ci dev_err(ctx->dev, "dsp core power down fail mask %x: %d\n", 2618c2ecf20Sopenharmony_ci core_mask, ret); 2628c2ecf20Sopenharmony_ci return ret; 2638c2ecf20Sopenharmony_ci } 2648c2ecf20Sopenharmony_ci 2658c2ecf20Sopenharmony_ci if (is_skl_dsp_core_enable(ctx, core_mask)) { 2668c2ecf20Sopenharmony_ci dev_err(ctx->dev, "dsp core disable fail mask %x: %d\n", 2678c2ecf20Sopenharmony_ci core_mask, ret); 2688c2ecf20Sopenharmony_ci ret = -EIO; 2698c2ecf20Sopenharmony_ci } 2708c2ecf20Sopenharmony_ci 2718c2ecf20Sopenharmony_ci return ret; 2728c2ecf20Sopenharmony_ci} 2738c2ecf20Sopenharmony_ci 2748c2ecf20Sopenharmony_ciint skl_dsp_boot(struct sst_dsp *ctx) 2758c2ecf20Sopenharmony_ci{ 2768c2ecf20Sopenharmony_ci int ret; 2778c2ecf20Sopenharmony_ci 2788c2ecf20Sopenharmony_ci if (is_skl_dsp_core_enable(ctx, SKL_DSP_CORE0_MASK)) { 2798c2ecf20Sopenharmony_ci ret = skl_dsp_reset_core(ctx, SKL_DSP_CORE0_MASK); 2808c2ecf20Sopenharmony_ci if (ret < 0) { 2818c2ecf20Sopenharmony_ci dev_err(ctx->dev, "dsp core0 reset fail: %d\n", ret); 2828c2ecf20Sopenharmony_ci return ret; 2838c2ecf20Sopenharmony_ci } 2848c2ecf20Sopenharmony_ci 2858c2ecf20Sopenharmony_ci ret = skl_dsp_start_core(ctx, SKL_DSP_CORE0_MASK); 2868c2ecf20Sopenharmony_ci if (ret < 0) { 2878c2ecf20Sopenharmony_ci dev_err(ctx->dev, "dsp core0 start fail: %d\n", ret); 2888c2ecf20Sopenharmony_ci return ret; 2898c2ecf20Sopenharmony_ci } 2908c2ecf20Sopenharmony_ci } else { 2918c2ecf20Sopenharmony_ci ret = skl_dsp_disable_core(ctx, SKL_DSP_CORE0_MASK); 2928c2ecf20Sopenharmony_ci if (ret < 0) { 2938c2ecf20Sopenharmony_ci dev_err(ctx->dev, "dsp core0 disable fail: %d\n", ret); 2948c2ecf20Sopenharmony_ci return ret; 2958c2ecf20Sopenharmony_ci } 2968c2ecf20Sopenharmony_ci ret = skl_dsp_enable_core(ctx, SKL_DSP_CORE0_MASK); 2978c2ecf20Sopenharmony_ci } 2988c2ecf20Sopenharmony_ci 2998c2ecf20Sopenharmony_ci return ret; 3008c2ecf20Sopenharmony_ci} 3018c2ecf20Sopenharmony_ci 3028c2ecf20Sopenharmony_ciirqreturn_t skl_dsp_sst_interrupt(int irq, void *dev_id) 3038c2ecf20Sopenharmony_ci{ 3048c2ecf20Sopenharmony_ci struct sst_dsp *ctx = dev_id; 3058c2ecf20Sopenharmony_ci u32 val; 3068c2ecf20Sopenharmony_ci irqreturn_t result = IRQ_NONE; 3078c2ecf20Sopenharmony_ci 3088c2ecf20Sopenharmony_ci spin_lock(&ctx->spinlock); 3098c2ecf20Sopenharmony_ci 3108c2ecf20Sopenharmony_ci val = sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPIS); 3118c2ecf20Sopenharmony_ci ctx->intr_status = val; 3128c2ecf20Sopenharmony_ci 3138c2ecf20Sopenharmony_ci if (val == 0xffffffff) { 3148c2ecf20Sopenharmony_ci spin_unlock(&ctx->spinlock); 3158c2ecf20Sopenharmony_ci return IRQ_NONE; 3168c2ecf20Sopenharmony_ci } 3178c2ecf20Sopenharmony_ci 3188c2ecf20Sopenharmony_ci if (val & SKL_ADSPIS_IPC) { 3198c2ecf20Sopenharmony_ci skl_ipc_int_disable(ctx); 3208c2ecf20Sopenharmony_ci result = IRQ_WAKE_THREAD; 3218c2ecf20Sopenharmony_ci } 3228c2ecf20Sopenharmony_ci 3238c2ecf20Sopenharmony_ci if (val & SKL_ADSPIS_CL_DMA) { 3248c2ecf20Sopenharmony_ci skl_cldma_int_disable(ctx); 3258c2ecf20Sopenharmony_ci result = IRQ_WAKE_THREAD; 3268c2ecf20Sopenharmony_ci } 3278c2ecf20Sopenharmony_ci 3288c2ecf20Sopenharmony_ci spin_unlock(&ctx->spinlock); 3298c2ecf20Sopenharmony_ci 3308c2ecf20Sopenharmony_ci return result; 3318c2ecf20Sopenharmony_ci} 3328c2ecf20Sopenharmony_ci/* 3338c2ecf20Sopenharmony_ci * skl_dsp_get_core/skl_dsp_put_core will be called inside DAPM context 3348c2ecf20Sopenharmony_ci * within the dapm mutex. Hence no separate lock is used. 3358c2ecf20Sopenharmony_ci */ 3368c2ecf20Sopenharmony_ciint skl_dsp_get_core(struct sst_dsp *ctx, unsigned int core_id) 3378c2ecf20Sopenharmony_ci{ 3388c2ecf20Sopenharmony_ci struct skl_dev *skl = ctx->thread_context; 3398c2ecf20Sopenharmony_ci int ret = 0; 3408c2ecf20Sopenharmony_ci 3418c2ecf20Sopenharmony_ci if (core_id >= skl->cores.count) { 3428c2ecf20Sopenharmony_ci dev_err(ctx->dev, "invalid core id: %d\n", core_id); 3438c2ecf20Sopenharmony_ci return -EINVAL; 3448c2ecf20Sopenharmony_ci } 3458c2ecf20Sopenharmony_ci 3468c2ecf20Sopenharmony_ci skl->cores.usage_count[core_id]++; 3478c2ecf20Sopenharmony_ci 3488c2ecf20Sopenharmony_ci if (skl->cores.state[core_id] == SKL_DSP_RESET) { 3498c2ecf20Sopenharmony_ci ret = ctx->fw_ops.set_state_D0(ctx, core_id); 3508c2ecf20Sopenharmony_ci if (ret < 0) { 3518c2ecf20Sopenharmony_ci dev_err(ctx->dev, "unable to get core%d\n", core_id); 3528c2ecf20Sopenharmony_ci goto out; 3538c2ecf20Sopenharmony_ci } 3548c2ecf20Sopenharmony_ci } 3558c2ecf20Sopenharmony_ci 3568c2ecf20Sopenharmony_ciout: 3578c2ecf20Sopenharmony_ci dev_dbg(ctx->dev, "core id %d state %d usage_count %d\n", 3588c2ecf20Sopenharmony_ci core_id, skl->cores.state[core_id], 3598c2ecf20Sopenharmony_ci skl->cores.usage_count[core_id]); 3608c2ecf20Sopenharmony_ci 3618c2ecf20Sopenharmony_ci return ret; 3628c2ecf20Sopenharmony_ci} 3638c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(skl_dsp_get_core); 3648c2ecf20Sopenharmony_ci 3658c2ecf20Sopenharmony_ciint skl_dsp_put_core(struct sst_dsp *ctx, unsigned int core_id) 3668c2ecf20Sopenharmony_ci{ 3678c2ecf20Sopenharmony_ci struct skl_dev *skl = ctx->thread_context; 3688c2ecf20Sopenharmony_ci int ret = 0; 3698c2ecf20Sopenharmony_ci 3708c2ecf20Sopenharmony_ci if (core_id >= skl->cores.count) { 3718c2ecf20Sopenharmony_ci dev_err(ctx->dev, "invalid core id: %d\n", core_id); 3728c2ecf20Sopenharmony_ci return -EINVAL; 3738c2ecf20Sopenharmony_ci } 3748c2ecf20Sopenharmony_ci 3758c2ecf20Sopenharmony_ci if ((--skl->cores.usage_count[core_id] == 0) && 3768c2ecf20Sopenharmony_ci (skl->cores.state[core_id] != SKL_DSP_RESET)) { 3778c2ecf20Sopenharmony_ci ret = ctx->fw_ops.set_state_D3(ctx, core_id); 3788c2ecf20Sopenharmony_ci if (ret < 0) { 3798c2ecf20Sopenharmony_ci dev_err(ctx->dev, "unable to put core %d: %d\n", 3808c2ecf20Sopenharmony_ci core_id, ret); 3818c2ecf20Sopenharmony_ci skl->cores.usage_count[core_id]++; 3828c2ecf20Sopenharmony_ci } 3838c2ecf20Sopenharmony_ci } 3848c2ecf20Sopenharmony_ci 3858c2ecf20Sopenharmony_ci dev_dbg(ctx->dev, "core id %d state %d usage_count %d\n", 3868c2ecf20Sopenharmony_ci core_id, skl->cores.state[core_id], 3878c2ecf20Sopenharmony_ci skl->cores.usage_count[core_id]); 3888c2ecf20Sopenharmony_ci 3898c2ecf20Sopenharmony_ci return ret; 3908c2ecf20Sopenharmony_ci} 3918c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(skl_dsp_put_core); 3928c2ecf20Sopenharmony_ci 3938c2ecf20Sopenharmony_ciint skl_dsp_wake(struct sst_dsp *ctx) 3948c2ecf20Sopenharmony_ci{ 3958c2ecf20Sopenharmony_ci return skl_dsp_get_core(ctx, SKL_DSP_CORE0_ID); 3968c2ecf20Sopenharmony_ci} 3978c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(skl_dsp_wake); 3988c2ecf20Sopenharmony_ci 3998c2ecf20Sopenharmony_ciint skl_dsp_sleep(struct sst_dsp *ctx) 4008c2ecf20Sopenharmony_ci{ 4018c2ecf20Sopenharmony_ci return skl_dsp_put_core(ctx, SKL_DSP_CORE0_ID); 4028c2ecf20Sopenharmony_ci} 4038c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(skl_dsp_sleep); 4048c2ecf20Sopenharmony_ci 4058c2ecf20Sopenharmony_cistruct sst_dsp *skl_dsp_ctx_init(struct device *dev, 4068c2ecf20Sopenharmony_ci struct sst_dsp_device *sst_dev, int irq) 4078c2ecf20Sopenharmony_ci{ 4088c2ecf20Sopenharmony_ci int ret; 4098c2ecf20Sopenharmony_ci struct sst_dsp *sst; 4108c2ecf20Sopenharmony_ci 4118c2ecf20Sopenharmony_ci sst = devm_kzalloc(dev, sizeof(*sst), GFP_KERNEL); 4128c2ecf20Sopenharmony_ci if (sst == NULL) 4138c2ecf20Sopenharmony_ci return NULL; 4148c2ecf20Sopenharmony_ci 4158c2ecf20Sopenharmony_ci spin_lock_init(&sst->spinlock); 4168c2ecf20Sopenharmony_ci mutex_init(&sst->mutex); 4178c2ecf20Sopenharmony_ci sst->dev = dev; 4188c2ecf20Sopenharmony_ci sst->sst_dev = sst_dev; 4198c2ecf20Sopenharmony_ci sst->irq = irq; 4208c2ecf20Sopenharmony_ci sst->ops = sst_dev->ops; 4218c2ecf20Sopenharmony_ci sst->thread_context = sst_dev->thread_context; 4228c2ecf20Sopenharmony_ci 4238c2ecf20Sopenharmony_ci /* Initialise SST Audio DSP */ 4248c2ecf20Sopenharmony_ci if (sst->ops->init) { 4258c2ecf20Sopenharmony_ci ret = sst->ops->init(sst); 4268c2ecf20Sopenharmony_ci if (ret < 0) 4278c2ecf20Sopenharmony_ci return NULL; 4288c2ecf20Sopenharmony_ci } 4298c2ecf20Sopenharmony_ci 4308c2ecf20Sopenharmony_ci return sst; 4318c2ecf20Sopenharmony_ci} 4328c2ecf20Sopenharmony_ci 4338c2ecf20Sopenharmony_ciint skl_dsp_acquire_irq(struct sst_dsp *sst) 4348c2ecf20Sopenharmony_ci{ 4358c2ecf20Sopenharmony_ci struct sst_dsp_device *sst_dev = sst->sst_dev; 4368c2ecf20Sopenharmony_ci int ret; 4378c2ecf20Sopenharmony_ci 4388c2ecf20Sopenharmony_ci /* Register the ISR */ 4398c2ecf20Sopenharmony_ci ret = request_threaded_irq(sst->irq, sst->ops->irq_handler, 4408c2ecf20Sopenharmony_ci sst_dev->thread, IRQF_SHARED, "AudioDSP", sst); 4418c2ecf20Sopenharmony_ci if (ret) 4428c2ecf20Sopenharmony_ci dev_err(sst->dev, "unable to grab threaded IRQ %d, disabling device\n", 4438c2ecf20Sopenharmony_ci sst->irq); 4448c2ecf20Sopenharmony_ci 4458c2ecf20Sopenharmony_ci return ret; 4468c2ecf20Sopenharmony_ci} 4478c2ecf20Sopenharmony_ci 4488c2ecf20Sopenharmony_civoid skl_dsp_free(struct sst_dsp *dsp) 4498c2ecf20Sopenharmony_ci{ 4508c2ecf20Sopenharmony_ci skl_ipc_int_disable(dsp); 4518c2ecf20Sopenharmony_ci 4528c2ecf20Sopenharmony_ci free_irq(dsp->irq, dsp); 4538c2ecf20Sopenharmony_ci skl_ipc_op_int_disable(dsp); 4548c2ecf20Sopenharmony_ci skl_dsp_disable_core(dsp, SKL_DSP_CORE0_MASK); 4558c2ecf20Sopenharmony_ci} 4568c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(skl_dsp_free); 4578c2ecf20Sopenharmony_ci 4588c2ecf20Sopenharmony_cibool is_skl_dsp_running(struct sst_dsp *ctx) 4598c2ecf20Sopenharmony_ci{ 4608c2ecf20Sopenharmony_ci return (ctx->sst_state == SKL_DSP_RUNNING); 4618c2ecf20Sopenharmony_ci} 4628c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(is_skl_dsp_running); 463