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