diff --git a/sound/soc/intel/skylake/bxt-sst.c b/sound/soc/intel/skylake/bxt-sst.c
index 9d36440c802a..c3dc1c4f1fad 100644
--- a/sound/soc/intel/skylake/bxt-sst.c
+++ b/sound/soc/intel/skylake/bxt-sst.c
@@ -58,7 +58,7 @@ static int sst_bxt_prepare_fw(struct sst_dsp *ctx,
 	ctx->dsp_ops.stream_tag = stream_tag;
 	memcpy(ctx->dmab.area, fwdata, fwsize);
 
-	ret = skl_dsp_core_power_up(ctx);
+	ret = skl_dsp_core_power_up(ctx, SKL_DSP_CORE0_MASK);
 	if (ret < 0) {
 		dev_err(ctx->dev, "Boot dsp core failed ret: %d\n", ret);
 		goto base_fw_load_failed;
@@ -68,7 +68,7 @@ static int sst_bxt_prepare_fw(struct sst_dsp *ctx,
 	sst_dsp_shim_write(ctx, SKL_ADSP_REG_HIPCI, SKL_ADSP_REG_HIPCI_BUSY |
 				(BXT_IPC_PURGE_FW | ((stream_tag - 1) << 9)));
 
-	ret = skl_dsp_start_core(ctx);
+	ret = skl_dsp_start_core(ctx, SKL_DSP_CORE0_MASK);
 	if (ret < 0) {
 		dev_err(ctx->dev, "Start dsp core failed ret: %d\n", ret);
 		ret = -EIO;
@@ -118,7 +118,8 @@ static int sst_bxt_prepare_fw(struct sst_dsp *ctx,
 
 base_fw_load_failed:
 	ctx->dsp_ops.cleanup(ctx->dev, &ctx->dmab, stream_tag);
-	skl_dsp_disable_core(ctx);
+	skl_dsp_core_power_down(ctx, SKL_DSP_CORE_MASK(1));
+	skl_dsp_disable_core(ctx, SKL_DSP_CORE_MASK(1));
 	return ret;
 }
 
@@ -183,14 +184,14 @@ static int bxt_load_base_firmware(struct sst_dsp *ctx)
 			sst_dsp_shim_read(ctx, BXT_ADSP_ERROR_CODE),
 			sst_dsp_shim_read(ctx, BXT_ADSP_FW_STATUS));
 
-		skl_dsp_disable_core(ctx);
+		skl_dsp_disable_core(ctx, SKL_DSP_CORE0_MASK);
 	} else {
 		dev_dbg(ctx->dev, "Firmware download successful\n");
 		ret = wait_event_timeout(skl->boot_wait, skl->boot_complete,
 					msecs_to_jiffies(SKL_IPC_BOOT_MSECS));
 		if (ret == 0) {
 			dev_err(ctx->dev, "DSP boot fail, FW Ready timeout\n");
-			skl_dsp_disable_core(ctx);
+			skl_dsp_disable_core(ctx, SKL_DSP_CORE0_MASK);
 			ret = -EIO;
 		} else {
 			skl_dsp_set_state_locked(ctx, SKL_DSP_RUNNING);
@@ -204,7 +205,7 @@ sst_load_base_firmware_failed:
 	return ret;
 }
 
-static int bxt_set_dsp_D0(struct sst_dsp *ctx)
+static int bxt_set_dsp_D0(struct sst_dsp *ctx, unsigned int core_id)
 {
 	struct skl_sst *skl = ctx->thread_context;
 	int ret;
@@ -219,7 +220,7 @@ static int bxt_set_dsp_D0(struct sst_dsp *ctx)
 		return ret;
 	}
 
-	ret = skl_dsp_enable_core(ctx);
+	ret = skl_dsp_enable_core(ctx, SKL_DSP_CORE0_MASK);
 	if (ret < 0) {
 		dev_err(ctx->dev, "enable dsp core failed ret: %d\n", ret);
 		return ret;
@@ -243,7 +244,7 @@ static int bxt_set_dsp_D0(struct sst_dsp *ctx)
 	return 0;
 }
 
-static int bxt_set_dsp_D3(struct sst_dsp *ctx)
+static int bxt_set_dsp_D3(struct sst_dsp *ctx, unsigned int core_id)
 {
 	struct skl_ipc_dxstate_info dx;
 	struct skl_sst *skl = ctx->thread_context;
@@ -262,7 +263,7 @@ static int bxt_set_dsp_D3(struct sst_dsp *ctx)
 		return ret;
 	}
 
-	ret = skl_dsp_disable_core(ctx);
+	ret = skl_dsp_disable_core(ctx, SKL_DSP_CORE0_MASK);
 	if (ret < 0) {
 		dev_err(ctx->dev, "disbale dsp core failed: %d\n", ret);
 		ret = -EIO;
@@ -330,6 +331,7 @@ int bxt_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq,
 	if (ret)
 		return ret;
 
+	skl->cores.count = 2;
 	skl->boot_complete = false;
 	init_waitqueue_head(&skl->boot_wait);
 
@@ -339,6 +341,8 @@ int bxt_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq,
 		return ret;
 	}
 
+	skl_dsp_init_core_state(sst);
+
 	if (dsp)
 		*dsp = skl;
 
diff --git a/sound/soc/intel/skylake/skl-sst-dsp.c b/sound/soc/intel/skylake/skl-sst-dsp.c
index 33c45aa53532..5da9272707db 100644
--- a/sound/soc/intel/skylake/skl-sst-dsp.c
+++ b/sound/soc/intel/skylake/skl-sst-dsp.c
@@ -34,33 +34,84 @@ void skl_dsp_set_state_locked(struct sst_dsp *ctx, int state)
 	mutex_unlock(&ctx->mutex);
 }
 
-static int skl_dsp_core_set_reset_state(struct sst_dsp *ctx)
+/*
+ * Initialize core power state and usage count. To be called after
+ * successful first boot. Hence core 0 will be running and other cores
+ * will be reset
+ */
+void skl_dsp_init_core_state(struct sst_dsp *ctx)
+{
+	struct skl_sst *skl = ctx->thread_context;
+	int i;
+
+	skl->cores.state[SKL_DSP_CORE0_ID] = SKL_DSP_RUNNING;
+	skl->cores.usage_count[SKL_DSP_CORE0_ID] = 1;
+
+	for (i = SKL_DSP_CORE0_ID + 1; i < SKL_DSP_CORES_MAX; i++) {
+		skl->cores.state[i] = SKL_DSP_RESET;
+		skl->cores.usage_count[i] = 0;
+	}
+}
+
+/* Get the mask for all enabled cores */
+unsigned int skl_dsp_get_enabled_cores(struct sst_dsp *ctx)
+{
+	struct skl_sst *skl = ctx->thread_context;
+	unsigned int core_mask, en_cores_mask;
+	u32 val;
+
+	core_mask = SKL_DSP_CORES_MASK(skl->cores.count);
+
+	val = sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPCS);
+
+	/* Cores having CPA bit set */
+	en_cores_mask = (val & SKL_ADSPCS_CPA_MASK(core_mask)) >>
+			SKL_ADSPCS_CPA_SHIFT;
+
+	/* And cores having CRST bit cleared */
+	en_cores_mask &= (~val & SKL_ADSPCS_CRST_MASK(core_mask)) >>
+			SKL_ADSPCS_CRST_SHIFT;
+
+	/* And cores having CSTALL bit cleared */
+	en_cores_mask &= (~val & SKL_ADSPCS_CSTALL_MASK(core_mask)) >>
+			SKL_ADSPCS_CSTALL_SHIFT;
+	en_cores_mask &= core_mask;
+
+	dev_dbg(ctx->dev, "DSP enabled cores mask = %x\n", en_cores_mask);
+
+	return en_cores_mask;
+}
+
+static int
+skl_dsp_core_set_reset_state(struct sst_dsp *ctx, unsigned int core_mask)
 {
 	int ret;
 
 	/* update bits */
 	sst_dsp_shim_update_bits_unlocked(ctx,
-			SKL_ADSP_REG_ADSPCS, SKL_ADSPCS_CRST_MASK,
-			SKL_ADSPCS_CRST(SKL_DSP_CORES_MASK));
+			SKL_ADSP_REG_ADSPCS, SKL_ADSPCS_CRST_MASK(core_mask),
+			SKL_ADSPCS_CRST_MASK(core_mask));
 
 	/* poll with timeout to check if operation successful */
 	ret = sst_dsp_register_poll(ctx,
 			SKL_ADSP_REG_ADSPCS,
-			SKL_ADSPCS_CRST_MASK,
-			SKL_ADSPCS_CRST(SKL_DSP_CORES_MASK),
+			SKL_ADSPCS_CRST_MASK(core_mask),
+			SKL_ADSPCS_CRST_MASK(core_mask),
 			SKL_DSP_RESET_TO,
 			"Set reset");
 	if ((sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPCS) &
-				SKL_ADSPCS_CRST(SKL_DSP_CORES_MASK)) !=
-				SKL_ADSPCS_CRST(SKL_DSP_CORES_MASK)) {
-		dev_err(ctx->dev, "Set reset state failed\n");
+				SKL_ADSPCS_CRST_MASK(core_mask)) !=
+				SKL_ADSPCS_CRST_MASK(core_mask)) {
+		dev_err(ctx->dev, "Set reset state failed: core_mask %x\n",
+							core_mask);
 		ret = -EIO;
 	}
 
 	return ret;
 }
 
-static int skl_dsp_core_unset_reset_state(struct sst_dsp *ctx)
+int skl_dsp_core_unset_reset_state(
+		struct sst_dsp *ctx, unsigned int core_mask)
 {
 	int ret;
 
@@ -68,151 +119,160 @@ static int skl_dsp_core_unset_reset_state(struct sst_dsp *ctx)
 
 	/* update bits */
 	sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_ADSPCS,
-					SKL_ADSPCS_CRST_MASK, 0);
+				SKL_ADSPCS_CRST_MASK(core_mask), 0);
 
 	/* poll with timeout to check if operation successful */
 	ret = sst_dsp_register_poll(ctx,
 			SKL_ADSP_REG_ADSPCS,
-			SKL_ADSPCS_CRST_MASK,
+			SKL_ADSPCS_CRST_MASK(core_mask),
 			0,
 			SKL_DSP_RESET_TO,
 			"Unset reset");
 
 	if ((sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPCS) &
-				 SKL_ADSPCS_CRST(SKL_DSP_CORES_MASK)) != 0) {
-		dev_err(ctx->dev, "Unset reset state failed\n");
+				SKL_ADSPCS_CRST_MASK(core_mask)) != 0) {
+		dev_err(ctx->dev, "Unset reset state failed: core_mask %x\n",
+				core_mask);
 		ret = -EIO;
 	}
 
 	return ret;
 }
 
-static bool is_skl_dsp_core_enable(struct sst_dsp *ctx)
+static bool
+is_skl_dsp_core_enable(struct sst_dsp *ctx, unsigned int core_mask)
 {
 	int val;
 	bool is_enable;
 
 	val = sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPCS);
 
-	is_enable = ((val & SKL_ADSPCS_CPA(SKL_DSP_CORES_MASK)) &&
-			(val & SKL_ADSPCS_SPA(SKL_DSP_CORES_MASK)) &&
-			!(val & SKL_ADSPCS_CRST(SKL_DSP_CORES_MASK)) &&
-			!(val & SKL_ADSPCS_CSTALL(SKL_DSP_CORES_MASK)));
+	is_enable = ((val & SKL_ADSPCS_CPA_MASK(core_mask)) &&
+			(val & SKL_ADSPCS_SPA_MASK(core_mask)) &&
+			!(val & SKL_ADSPCS_CRST_MASK(core_mask)) &&
+			!(val & SKL_ADSPCS_CSTALL_MASK(core_mask)));
+
+	dev_dbg(ctx->dev, "DSP core(s) enabled? %d : core_mask %x\n",
+						is_enable, core_mask);
 
-	dev_dbg(ctx->dev, "DSP core is enabled=%d\n", is_enable);
 	return is_enable;
 }
 
-static int skl_dsp_reset_core(struct sst_dsp *ctx)
+static int skl_dsp_reset_core(struct sst_dsp *ctx, unsigned int core_mask)
 {
 	/* stall core */
 	sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_ADSPCS,
-			SKL_ADSPCS_CSTALL_MASK,
-			SKL_ADSPCS_CSTALL(SKL_DSP_CORES_MASK));
+			SKL_ADSPCS_CSTALL_MASK(core_mask),
+			SKL_ADSPCS_CSTALL_MASK(core_mask));
 
 	/* set reset state */
-	return skl_dsp_core_set_reset_state(ctx);
+	return skl_dsp_core_set_reset_state(ctx, core_mask);
 }
 
-int skl_dsp_start_core(struct sst_dsp *ctx)
+int skl_dsp_start_core(struct sst_dsp *ctx, unsigned int core_mask)
 {
 	int ret;
 
 	/* unset reset state */
-	ret = skl_dsp_core_unset_reset_state(ctx);
-	if (ret < 0) {
-		dev_dbg(ctx->dev, "dsp unset reset fails\n");
+	ret = skl_dsp_core_unset_reset_state(ctx, core_mask);
+	if (ret < 0)
 		return ret;
-	}
 
 	/* run core */
-	dev_dbg(ctx->dev, "run core...\n");
+	dev_dbg(ctx->dev, "unstall/run core: core_mask = %x\n", core_mask);
 	sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_ADSPCS,
-			SKL_ADSPCS_CSTALL_MASK, 0);
+			SKL_ADSPCS_CSTALL_MASK(core_mask), 0);
 
-	if (!is_skl_dsp_core_enable(ctx)) {
-		skl_dsp_reset_core(ctx);
-		dev_err(ctx->dev, "DSP core enable failed\n");
+	if (!is_skl_dsp_core_enable(ctx, core_mask)) {
+		skl_dsp_reset_core(ctx, core_mask);
+		dev_err(ctx->dev, "DSP start core failed: core_mask %x\n",
+							core_mask);
 		ret = -EIO;
 	}
 
 	return ret;
 }
 
-int skl_dsp_core_power_up(struct sst_dsp *ctx)
+int skl_dsp_core_power_up(struct sst_dsp *ctx, unsigned int core_mask)
 {
 	int ret;
 
 	/* update bits */
 	sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_ADSPCS,
-			SKL_ADSPCS_SPA_MASK, SKL_ADSPCS_SPA(SKL_DSP_CORES_MASK));
+			SKL_ADSPCS_SPA_MASK(core_mask),
+			SKL_ADSPCS_SPA_MASK(core_mask));
 
 	/* poll with timeout to check if operation successful */
 	ret = sst_dsp_register_poll(ctx,
 			SKL_ADSP_REG_ADSPCS,
-			SKL_ADSPCS_CPA_MASK,
-			SKL_ADSPCS_CPA(SKL_DSP_CORES_MASK),
+			SKL_ADSPCS_CPA_MASK(core_mask),
+			SKL_ADSPCS_CPA_MASK(core_mask),
 			SKL_DSP_PU_TO,
 			"Power up");
 
 	if ((sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPCS) &
-			SKL_ADSPCS_CPA(SKL_DSP_CORES_MASK)) !=
-			SKL_ADSPCS_CPA(SKL_DSP_CORES_MASK)) {
-		dev_err(ctx->dev, "DSP core power up failed\n");
+			SKL_ADSPCS_CPA_MASK(core_mask)) !=
+			SKL_ADSPCS_CPA_MASK(core_mask)) {
+		dev_err(ctx->dev, "DSP core power up failed: core_mask %x\n",
+				core_mask);
 		ret = -EIO;
 	}
 
 	return ret;
 }
 
-static int skl_dsp_core_power_down(struct sst_dsp *ctx)
+int skl_dsp_core_power_down(struct sst_dsp  *ctx, unsigned int core_mask)
 {
 	/* update bits */
 	sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_ADSPCS,
-					SKL_ADSPCS_SPA_MASK, 0);
+				SKL_ADSPCS_SPA_MASK(core_mask), 0);
 
 	/* poll with timeout to check if operation successful */
 	return sst_dsp_register_poll(ctx,
 			SKL_ADSP_REG_ADSPCS,
-			SKL_ADSPCS_CPA_MASK,
+			SKL_ADSPCS_CPA_MASK(core_mask),
 			0,
 			SKL_DSP_PD_TO,
 			"Power down");
 }
 
-int skl_dsp_enable_core(struct sst_dsp *ctx)
+int skl_dsp_enable_core(struct sst_dsp  *ctx, unsigned int core_mask)
 {
 	int ret;
 
 	/* power up */
-	ret = skl_dsp_core_power_up(ctx);
+	ret = skl_dsp_core_power_up(ctx, core_mask);
 	if (ret < 0) {
-		dev_dbg(ctx->dev, "dsp core power up failed\n");
+		dev_err(ctx->dev, "dsp core power up failed: core_mask %x\n",
+							core_mask);
 		return ret;
 	}
 
-	return skl_dsp_start_core(ctx);
+	return skl_dsp_start_core(ctx, core_mask);
 }
 
-int skl_dsp_disable_core(struct sst_dsp *ctx)
+int skl_dsp_disable_core(struct sst_dsp *ctx, unsigned int core_mask)
 {
 	int ret;
 
-	ret = skl_dsp_reset_core(ctx);
+	ret = skl_dsp_reset_core(ctx, core_mask);
 	if (ret < 0) {
-		dev_err(ctx->dev, "dsp core reset failed\n");
+		dev_err(ctx->dev, "dsp core reset failed: core_mask %x\n",
+							core_mask);
 		return ret;
 	}
 
 	/* power down core*/
-	ret = skl_dsp_core_power_down(ctx);
+	ret = skl_dsp_core_power_down(ctx, core_mask);
 	if (ret < 0) {
-		dev_err(ctx->dev, "dsp core power down failed\n");
+		dev_err(ctx->dev, "dsp core power down fail mask %x: %d\n",
+							core_mask, ret);
 		return ret;
 	}
 
-	if (is_skl_dsp_core_enable(ctx)) {
-		dev_err(ctx->dev, "DSP core disable failed\n");
+	if (is_skl_dsp_core_enable(ctx, core_mask)) {
+		dev_err(ctx->dev, "dsp core disable fail mask %x: %d\n",
+							core_mask, ret);
 		ret = -EIO;
 	}
 
@@ -223,28 +283,25 @@ int skl_dsp_boot(struct sst_dsp *ctx)
 {
 	int ret;
 
-	if (is_skl_dsp_core_enable(ctx)) {
-		dev_dbg(ctx->dev, "dsp core is already enabled, so reset the dap core\n");
-		ret = skl_dsp_reset_core(ctx);
+	if (is_skl_dsp_core_enable(ctx, SKL_DSP_CORE0_MASK)) {
+		ret = skl_dsp_reset_core(ctx, SKL_DSP_CORE0_MASK);
 		if (ret < 0) {
-			dev_err(ctx->dev, "dsp reset failed\n");
+			dev_err(ctx->dev, "dsp core0 reset fail: %d\n", ret);
 			return ret;
 		}
 
-		ret = skl_dsp_start_core(ctx);
+		ret = skl_dsp_start_core(ctx, SKL_DSP_CORE0_MASK);
 		if (ret < 0) {
-			dev_err(ctx->dev, "dsp start failed\n");
+			dev_err(ctx->dev, "dsp core0 start fail: %d\n", ret);
 			return ret;
 		}
 	} else {
-		dev_dbg(ctx->dev, "disable and enable to make sure DSP is invalid state\n");
-		ret = skl_dsp_disable_core(ctx);
-
+		ret = skl_dsp_disable_core(ctx, SKL_DSP_CORE0_MASK);
 		if (ret < 0) {
-			dev_err(ctx->dev, "dsp disable core failes\n");
+			dev_err(ctx->dev, "dsp core0 disable fail: %d\n", ret);
 			return ret;
 		}
-		ret = skl_dsp_enable_core(ctx);
+		ret = skl_dsp_enable_core(ctx, SKL_DSP_CORE0_MASK);
 	}
 
 	return ret;
@@ -280,16 +337,73 @@ irqreturn_t skl_dsp_sst_interrupt(int irq, void *dev_id)
 
 	return result;
 }
+/*
+ * skl_dsp_get_core/skl_dsp_put_core will be called inside DAPM context
+ * within the dapm mutex. Hence no separate lock is used.
+ */
+int skl_dsp_get_core(struct sst_dsp *ctx, unsigned int core_id)
+{
+	struct skl_sst *skl = ctx->thread_context;
+	int ret = 0;
+
+	if (core_id >= skl->cores.count) {
+		dev_err(ctx->dev, "invalid core id: %d\n", core_id);
+		return -EINVAL;
+	}
+
+	if (skl->cores.state[core_id] == SKL_DSP_RESET) {
+		ret = ctx->fw_ops.set_state_D0(ctx, core_id);
+		if (ret < 0) {
+			dev_err(ctx->dev, "unable to get core%d\n", core_id);
+			return ret;
+		}
+	}
+
+	skl->cores.usage_count[core_id]++;
+
+	dev_dbg(ctx->dev, "core id %d state %d usage_count %d\n",
+			core_id, skl->cores.state[core_id],
+			skl->cores.usage_count[core_id]);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(skl_dsp_get_core);
+
+int skl_dsp_put_core(struct sst_dsp *ctx, unsigned int core_id)
+{
+	struct skl_sst *skl = ctx->thread_context;
+	int ret = 0;
+
+	if (core_id >= skl->cores.count) {
+		dev_err(ctx->dev, "invalid core id: %d\n", core_id);
+		return -EINVAL;
+	}
+
+	if (--skl->cores.usage_count[core_id] == 0)
+		ret = ctx->fw_ops.set_state_D3(ctx, core_id);
+		if (ret < 0) {
+			dev_err(ctx->dev, "unable to put core %d: %d\n",
+					core_id, ret);
+			skl->cores.usage_count[core_id]++;
+	}
+
+	dev_dbg(ctx->dev, "core id %d state %d usage_count %d\n",
+			core_id, skl->cores.state[core_id],
+			skl->cores.usage_count[core_id]);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(skl_dsp_put_core);
 
 int skl_dsp_wake(struct sst_dsp *ctx)
 {
-	return ctx->fw_ops.set_state_D0(ctx);
+	return skl_dsp_get_core(ctx, SKL_DSP_CORE0_ID);
 }
 EXPORT_SYMBOL_GPL(skl_dsp_wake);
 
 int skl_dsp_sleep(struct sst_dsp *ctx)
 {
-	return ctx->fw_ops.set_state_D3(ctx);
+	return skl_dsp_put_core(ctx, SKL_DSP_CORE0_ID);
 }
 EXPORT_SYMBOL_GPL(skl_dsp_sleep);
 
@@ -336,9 +450,7 @@ void skl_dsp_free(struct sst_dsp *dsp)
 
 	free_irq(dsp->irq, dsp);
 	skl_ipc_op_int_disable(dsp);
-	skl_ipc_int_disable(dsp);
-
-	skl_dsp_disable_core(dsp);
+	skl_dsp_disable_core(dsp, SKL_DSP_CORE0_MASK);
 }
 EXPORT_SYMBOL_GPL(skl_dsp_free);
 
diff --git a/sound/soc/intel/skylake/skl-sst-dsp.h b/sound/soc/intel/skylake/skl-sst-dsp.h
index 22fbe1075cb5..0f8629ef79ac 100644
--- a/sound/soc/intel/skylake/skl-sst-dsp.h
+++ b/sound/soc/intel/skylake/skl-sst-dsp.h
@@ -77,35 +77,53 @@ struct sst_dsp_device;
 #define SKL_ADSPIC_IPC			1
 #define SKL_ADSPIS_IPC			1
 
+/* Core ID of core0 */
+#define SKL_DSP_CORE0_ID		0
+
+/* Mask for a given core index, c = 0.. number of supported cores - 1 */
+#define SKL_DSP_CORE_MASK(c)		BIT(c)
+
+/*
+ * Core 0 mask = SKL_DSP_CORE_MASK(0); Defined separately
+ * since Core0 is primary core and it is used often
+ */
+#define SKL_DSP_CORE0_MASK		BIT(0)
+
+/*
+ * Mask for a given number of cores
+ * nc = number of supported cores
+ */
+#define SKL_DSP_CORES_MASK(nc)	GENMASK((nc - 1), 0)
+
 /* ADSPCS - Audio DSP Control & Status */
-#define SKL_DSP_CORES		1
-#define SKL_DSP_CORE0_MASK	1
-#define SKL_DSP_CORES_MASK	((1 << SKL_DSP_CORES) - 1)
-
-/* Core Reset - asserted high */
-#define SKL_ADSPCS_CRST_SHIFT	0
-#define SKL_ADSPCS_CRST_MASK	(SKL_DSP_CORES_MASK << SKL_ADSPCS_CRST_SHIFT)
-#define SKL_ADSPCS_CRST(x)	((x << SKL_ADSPCS_CRST_SHIFT) & SKL_ADSPCS_CRST_MASK)
-
-/* Core run/stall - when set to '1' core is stalled */
-#define SKL_ADSPCS_CSTALL_SHIFT	8
-#define SKL_ADSPCS_CSTALL_MASK	(SKL_DSP_CORES_MASK <<	\
-					SKL_ADSPCS_CSTALL_SHIFT)
-#define SKL_ADSPCS_CSTALL(x)	((x << SKL_ADSPCS_CSTALL_SHIFT) &	\
-				SKL_ADSPCS_CSTALL_MASK)
-
-/* Set Power Active - when set to '1' turn cores on */
-#define SKL_ADSPCS_SPA_SHIFT	16
-#define SKL_ADSPCS_SPA_MASK	(SKL_DSP_CORES_MASK << SKL_ADSPCS_SPA_SHIFT)
-#define SKL_ADSPCS_SPA(x)	((x << SKL_ADSPCS_SPA_SHIFT) & SKL_ADSPCS_SPA_MASK)
-
-/* Current Power Active - power status of cores, set by hardware */
-#define SKL_ADSPCS_CPA_SHIFT	24
-#define SKL_ADSPCS_CPA_MASK	(SKL_DSP_CORES_MASK << SKL_ADSPCS_CPA_SHIFT)
-#define SKL_ADSPCS_CPA(x)	((x << SKL_ADSPCS_CPA_SHIFT) & SKL_ADSPCS_CPA_MASK)
-
-#define SST_DSP_POWER_D0	0x0  /* full On */
-#define SST_DSP_POWER_D3	0x3  /* Off */
+
+/*
+ * Core Reset - asserted high
+ * CRST Mask for a given core mask pattern, cm
+ */
+#define SKL_ADSPCS_CRST_SHIFT		0
+#define SKL_ADSPCS_CRST_MASK(cm)	((cm) << SKL_ADSPCS_CRST_SHIFT)
+
+/*
+ * Core run/stall - when set to '1' core is stalled
+ * CSTALL Mask for a given core mask pattern, cm
+ */
+#define SKL_ADSPCS_CSTALL_SHIFT		8
+#define SKL_ADSPCS_CSTALL_MASK(cm)	((cm) << SKL_ADSPCS_CSTALL_SHIFT)
+
+/*
+ * Set Power Active - when set to '1' turn cores on
+ * SPA Mask for a given core mask pattern, cm
+ */
+#define SKL_ADSPCS_SPA_SHIFT		16
+#define SKL_ADSPCS_SPA_MASK(cm)		((cm) << SKL_ADSPCS_SPA_SHIFT)
+
+/*
+ * Current Power Active - power status of cores, set by hardware
+ * CPA Mask for a given core mask pattern, cm
+ */
+#define SKL_ADSPCS_CPA_SHIFT		24
+#define SKL_ADSPCS_CPA_MASK(cm)		((cm) << SKL_ADSPCS_CPA_SHIFT)
 
 enum skl_dsp_states {
 	SKL_DSP_RUNNING = 1,
@@ -116,8 +134,8 @@ struct skl_dsp_fw_ops {
 	int (*load_fw)(struct sst_dsp  *ctx);
 	/* FW module parser/loader */
 	int (*parse_fw)(struct sst_dsp *ctx);
-	int (*set_state_D0)(struct sst_dsp *ctx);
-	int (*set_state_D3)(struct sst_dsp *ctx);
+	int (*set_state_D0)(struct sst_dsp *ctx, unsigned int core_id);
+	int (*set_state_D3)(struct sst_dsp *ctx, unsigned int core_id);
 	unsigned int (*get_fw_errcode)(struct sst_dsp *ctx);
 	int (*load_mod)(struct sst_dsp *ctx, u16 mod_id, u8 *mod_name);
 	int (*unload_mod)(struct sst_dsp *ctx, u16 mod_id);
@@ -158,14 +176,26 @@ int skl_cldma_prepare(struct sst_dsp *ctx);
 void skl_dsp_set_state_locked(struct sst_dsp *ctx, int state);
 struct sst_dsp *skl_dsp_ctx_init(struct device *dev,
 		struct sst_dsp_device *sst_dev, int irq);
-int skl_dsp_enable_core(struct sst_dsp *ctx);
-int skl_dsp_disable_core(struct sst_dsp *ctx);
 bool is_skl_dsp_running(struct sst_dsp *ctx);
+
+unsigned int skl_dsp_get_enabled_cores(struct sst_dsp *ctx);
+void skl_dsp_init_core_state(struct sst_dsp *ctx);
+int skl_dsp_enable_core(struct sst_dsp *ctx, unsigned int core_mask);
+int skl_dsp_disable_core(struct sst_dsp *ctx, unsigned int core_mask);
+int skl_dsp_core_power_up(struct sst_dsp *ctx, unsigned int core_mask);
+int skl_dsp_core_power_down(struct sst_dsp *ctx, unsigned int core_mask);
+int skl_dsp_core_unset_reset_state(struct sst_dsp *ctx,
+					unsigned int core_mask);
+int skl_dsp_start_core(struct sst_dsp *ctx, unsigned int core_mask);
+
 irqreturn_t skl_dsp_sst_interrupt(int irq, void *dev_id);
 int skl_dsp_wake(struct sst_dsp *ctx);
 int skl_dsp_sleep(struct sst_dsp *ctx);
 void skl_dsp_free(struct sst_dsp *dsp);
 
+int skl_dsp_get_core(struct sst_dsp *ctx, unsigned int core_id);
+int skl_dsp_put_core(struct sst_dsp *ctx, unsigned int core_id);
+
 int skl_dsp_boot(struct sst_dsp *ctx);
 int skl_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq,
 		const char *fw_name, struct skl_dsp_loader_ops dsp_ops,
@@ -182,7 +212,5 @@ int snd_skl_parse_uuids(struct sst_dsp *ctx, unsigned int offset);
 void skl_freeup_uuid_list(struct skl_sst *ctx);
 
 int skl_dsp_strip_extended_manifest(struct firmware *fw);
-int skl_dsp_start_core(struct sst_dsp *ctx);
-int skl_dsp_core_power_up(struct sst_dsp *ctx);
 
 #endif /*__SKL_SST_DSP_H__*/
diff --git a/sound/soc/intel/skylake/skl-sst-ipc.h b/sound/soc/intel/skylake/skl-sst-ipc.h
index 5102c7b415fe..2e3d4e80ef97 100644
--- a/sound/soc/intel/skylake/skl-sst-ipc.h
+++ b/sound/soc/intel/skylake/skl-sst-ipc.h
@@ -45,6 +45,14 @@ struct skl_ipc_header {
 	u32 extension;
 };
 
+#define SKL_DSP_CORES_MAX  2
+
+struct skl_dsp_cores {
+	unsigned int count;
+	enum skl_dsp_states state[SKL_DSP_CORES_MAX];
+	int usage_count[SKL_DSP_CORES_MAX];
+};
+
 struct skl_sst {
 	struct device *dev;
 	struct sst_dsp *dsp;
@@ -66,6 +74,9 @@ struct skl_sst {
 
 	/* Is firmware loaded */
 	bool fw_loaded;
+
+	/* multi-core */
+	struct skl_dsp_cores cores;
 };
 
 struct skl_ipc_init_instance_msg {
diff --git a/sound/soc/intel/skylake/skl-sst.c b/sound/soc/intel/skylake/skl-sst.c
index eaf0c9d19782..ecaca94d2a96 100644
--- a/sound/soc/intel/skylake/skl-sst.c
+++ b/sound/soc/intel/skylake/skl-sst.c
@@ -84,10 +84,8 @@ static int skl_load_base_firmware(struct sst_dsp *ctx)
 		ret = request_firmware(&ctx->fw, ctx->fw_name, ctx->dev);
 		if (ret < 0) {
 			dev_err(ctx->dev, "Request firmware failed %d\n", ret);
-			skl_dsp_disable_core(ctx);
 			return -EIO;
 		}
-
 	}
 
 	ret = snd_skl_parse_uuids(ctx, SKL_ADSP_FW_BIN_HDR_OFFSET);
@@ -95,7 +93,7 @@ static int skl_load_base_firmware(struct sst_dsp *ctx)
 		dev_err(ctx->dev,
 				"UUID parsing err: %d\n", ret);
 		release_firmware(ctx->fw);
-		skl_dsp_disable_core(ctx);
+		skl_dsp_disable_core(ctx, SKL_DSP_CORE0_MASK);
 		return ret;
 	}
 
@@ -159,13 +157,13 @@ static int skl_load_base_firmware(struct sst_dsp *ctx)
 transfer_firmware_failed:
 	ctx->cl_dev.ops.cl_cleanup_controller(ctx);
 skl_load_base_firmware_failed:
-	skl_dsp_disable_core(ctx);
+	skl_dsp_disable_core(ctx, SKL_DSP_CORE0_MASK);
 	release_firmware(ctx->fw);
 	ctx->fw = NULL;
 	return ret;
 }
 
-static int skl_set_dsp_D0(struct sst_dsp *ctx)
+static int skl_set_dsp_D0(struct sst_dsp *ctx, unsigned int core_id)
 {
 	int ret;
 
@@ -180,7 +178,7 @@ static int skl_set_dsp_D0(struct sst_dsp *ctx)
 	return ret;
 }
 
-static int skl_set_dsp_D3(struct sst_dsp *ctx)
+static int skl_set_dsp_D3(struct sst_dsp *ctx, unsigned int core_id)
 {
 	int ret;
 	struct skl_ipc_dxstate_info dx;
@@ -207,7 +205,7 @@ static int skl_set_dsp_D3(struct sst_dsp *ctx)
 	skl_ipc_op_int_disable(ctx);
 	skl_ipc_int_disable(ctx);
 
-	ret = skl_dsp_disable_core(ctx);
+	ret = skl_dsp_disable_core(ctx, core_id);
 	if (ret < 0) {
 		dev_err(ctx->dev, "disable dsp core failed ret: %d\n", ret);
 		ret = -EIO;
@@ -466,12 +464,16 @@ int skl_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq,
 	if (ret)
 		return ret;
 
+	skl->cores.count = 2;
+
 	ret = sst->fw_ops.load_fw(sst);
 	if (ret < 0) {
 		dev_err(dev, "Load base fw failed : %d", ret);
 		goto cleanup;
 	}
 
+	skl_dsp_init_core_state(sst);
+
 	if (dsp)
 		*dsp = skl;
 
