Commit 052f103c authored by Jayachandran B's avatar Jayachandran B Committed by Mark Brown

ASoC: Intel: Skylake: Add DSP muti-core infrastructure

The DSP can have more than one cores. In that case the secondary
core has to be managed by the driver. This patch adds the changes
to driver infrastructure to support multiple core.

A new object skl_dsp_cores is introduced to support multiple
core. Helpers skl_dsp_get_core() skl_dsp_put_core() help to
managed the cores.

Many of the power_up/down and DSP APIs take additional argument
of core_id. The primary core, 0 is always powered up first and
then on demand second core.
Signed-off-by: default avatarJayachandran B <jayachandran.b@intel.com>
Signed-off-by: default avatarVinod Koul <vinod.koul@intel.com>
Signed-off-by: default avatarMark Brown <broonie@kernel.org>
parent 957427d9
...@@ -58,7 +58,7 @@ static int sst_bxt_prepare_fw(struct sst_dsp *ctx, ...@@ -58,7 +58,7 @@ static int sst_bxt_prepare_fw(struct sst_dsp *ctx,
ctx->dsp_ops.stream_tag = stream_tag; ctx->dsp_ops.stream_tag = stream_tag;
memcpy(ctx->dmab.area, fwdata, fwsize); 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) { if (ret < 0) {
dev_err(ctx->dev, "Boot dsp core failed ret: %d\n", ret); dev_err(ctx->dev, "Boot dsp core failed ret: %d\n", ret);
goto base_fw_load_failed; goto base_fw_load_failed;
...@@ -68,7 +68,7 @@ static int sst_bxt_prepare_fw(struct sst_dsp *ctx, ...@@ -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 | sst_dsp_shim_write(ctx, SKL_ADSP_REG_HIPCI, SKL_ADSP_REG_HIPCI_BUSY |
(BXT_IPC_PURGE_FW | ((stream_tag - 1) << 9))); (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) { if (ret < 0) {
dev_err(ctx->dev, "Start dsp core failed ret: %d\n", ret); dev_err(ctx->dev, "Start dsp core failed ret: %d\n", ret);
ret = -EIO; ret = -EIO;
...@@ -118,7 +118,8 @@ static int sst_bxt_prepare_fw(struct sst_dsp *ctx, ...@@ -118,7 +118,8 @@ static int sst_bxt_prepare_fw(struct sst_dsp *ctx,
base_fw_load_failed: base_fw_load_failed:
ctx->dsp_ops.cleanup(ctx->dev, &ctx->dmab, stream_tag); 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; return ret;
} }
...@@ -183,14 +184,14 @@ static int bxt_load_base_firmware(struct sst_dsp *ctx) ...@@ -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_ERROR_CODE),
sst_dsp_shim_read(ctx, BXT_ADSP_FW_STATUS)); sst_dsp_shim_read(ctx, BXT_ADSP_FW_STATUS));
skl_dsp_disable_core(ctx); skl_dsp_disable_core(ctx, SKL_DSP_CORE0_MASK);
} else { } else {
dev_dbg(ctx->dev, "Firmware download successful\n"); dev_dbg(ctx->dev, "Firmware download successful\n");
ret = wait_event_timeout(skl->boot_wait, skl->boot_complete, ret = wait_event_timeout(skl->boot_wait, skl->boot_complete,
msecs_to_jiffies(SKL_IPC_BOOT_MSECS)); msecs_to_jiffies(SKL_IPC_BOOT_MSECS));
if (ret == 0) { if (ret == 0) {
dev_err(ctx->dev, "DSP boot fail, FW Ready timeout\n"); 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; ret = -EIO;
} else { } else {
skl_dsp_set_state_locked(ctx, SKL_DSP_RUNNING); skl_dsp_set_state_locked(ctx, SKL_DSP_RUNNING);
...@@ -204,7 +205,7 @@ static int bxt_load_base_firmware(struct sst_dsp *ctx) ...@@ -204,7 +205,7 @@ static int bxt_load_base_firmware(struct sst_dsp *ctx)
return ret; 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; struct skl_sst *skl = ctx->thread_context;
int ret; int ret;
...@@ -219,7 +220,7 @@ static int bxt_set_dsp_D0(struct sst_dsp *ctx) ...@@ -219,7 +220,7 @@ static int bxt_set_dsp_D0(struct sst_dsp *ctx)
return ret; return ret;
} }
ret = skl_dsp_enable_core(ctx); ret = skl_dsp_enable_core(ctx, SKL_DSP_CORE0_MASK);
if (ret < 0) { if (ret < 0) {
dev_err(ctx->dev, "enable dsp core failed ret: %d\n", ret); dev_err(ctx->dev, "enable dsp core failed ret: %d\n", ret);
return ret; return ret;
...@@ -243,7 +244,7 @@ static int bxt_set_dsp_D0(struct sst_dsp *ctx) ...@@ -243,7 +244,7 @@ static int bxt_set_dsp_D0(struct sst_dsp *ctx)
return 0; 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_ipc_dxstate_info dx;
struct skl_sst *skl = ctx->thread_context; struct skl_sst *skl = ctx->thread_context;
...@@ -262,7 +263,7 @@ static int bxt_set_dsp_D3(struct sst_dsp *ctx) ...@@ -262,7 +263,7 @@ static int bxt_set_dsp_D3(struct sst_dsp *ctx)
return ret; return ret;
} }
ret = skl_dsp_disable_core(ctx); ret = skl_dsp_disable_core(ctx, SKL_DSP_CORE0_MASK);
if (ret < 0) { if (ret < 0) {
dev_err(ctx->dev, "disbale dsp core failed: %d\n", ret); dev_err(ctx->dev, "disbale dsp core failed: %d\n", ret);
ret = -EIO; ret = -EIO;
...@@ -329,6 +330,7 @@ int bxt_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq, ...@@ -329,6 +330,7 @@ int bxt_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq,
if (ret) if (ret)
return ret; return ret;
skl->cores.count = 2;
skl->boot_complete = false; skl->boot_complete = false;
init_waitqueue_head(&skl->boot_wait); init_waitqueue_head(&skl->boot_wait);
...@@ -338,6 +340,8 @@ int bxt_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq, ...@@ -338,6 +340,8 @@ int bxt_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq,
return ret; return ret;
} }
skl_dsp_init_core_state(sst);
if (dsp) if (dsp)
*dsp = skl; *dsp = skl;
......
This diff is collapsed.
...@@ -77,35 +77,53 @@ struct sst_dsp_device; ...@@ -77,35 +77,53 @@ struct sst_dsp_device;
#define SKL_ADSPIC_IPC 1 #define SKL_ADSPIC_IPC 1
#define SKL_ADSPIS_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 */ /* 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
* CRST Mask for a given core mask pattern, cm
/* Core Reset - asserted high */ */
#define SKL_ADSPCS_CRST_SHIFT 0 #define SKL_ADSPCS_CRST_SHIFT 0
#define SKL_ADSPCS_CRST_MASK (SKL_DSP_CORES_MASK << SKL_ADSPCS_CRST_SHIFT) #define SKL_ADSPCS_CRST_MASK(cm) ((cm) << 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 */ * Core run/stall - when set to '1' core is stalled
#define SKL_ADSPCS_CSTALL_SHIFT 8 * CSTALL Mask for a given core mask pattern, cm
#define SKL_ADSPCS_CSTALL_MASK (SKL_DSP_CORES_MASK << \ */
SKL_ADSPCS_CSTALL_SHIFT) #define SKL_ADSPCS_CSTALL_SHIFT 8
#define SKL_ADSPCS_CSTALL(x) ((x << SKL_ADSPCS_CSTALL_SHIFT) & \ #define SKL_ADSPCS_CSTALL_MASK(cm) ((cm) << SKL_ADSPCS_CSTALL_SHIFT)
SKL_ADSPCS_CSTALL_MASK)
/*
/* Set Power Active - when set to '1' turn cores on */ * Set Power Active - when set to '1' turn cores on
#define SKL_ADSPCS_SPA_SHIFT 16 * SPA Mask for a given core mask pattern, cm
#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) #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 */
#define SKL_ADSPCS_CPA_SHIFT 24 /*
#define SKL_ADSPCS_CPA_MASK (SKL_DSP_CORES_MASK << SKL_ADSPCS_CPA_SHIFT) * Current Power Active - power status of cores, set by hardware
#define SKL_ADSPCS_CPA(x) ((x << SKL_ADSPCS_CPA_SHIFT) & SKL_ADSPCS_CPA_MASK) * CPA Mask for a given core mask pattern, cm
*/
#define SST_DSP_POWER_D0 0x0 /* full On */ #define SKL_ADSPCS_CPA_SHIFT 24
#define SST_DSP_POWER_D3 0x3 /* Off */ #define SKL_ADSPCS_CPA_MASK(cm) ((cm) << SKL_ADSPCS_CPA_SHIFT)
enum skl_dsp_states { enum skl_dsp_states {
SKL_DSP_RUNNING = 1, SKL_DSP_RUNNING = 1,
...@@ -116,8 +134,8 @@ struct skl_dsp_fw_ops { ...@@ -116,8 +134,8 @@ struct skl_dsp_fw_ops {
int (*load_fw)(struct sst_dsp *ctx); int (*load_fw)(struct sst_dsp *ctx);
/* FW module parser/loader */ /* FW module parser/loader */
int (*parse_fw)(struct sst_dsp *ctx); int (*parse_fw)(struct sst_dsp *ctx);
int (*set_state_D0)(struct sst_dsp *ctx); int (*set_state_D0)(struct sst_dsp *ctx, unsigned int core_id);
int (*set_state_D3)(struct sst_dsp *ctx); int (*set_state_D3)(struct sst_dsp *ctx, unsigned int core_id);
unsigned int (*get_fw_errcode)(struct sst_dsp *ctx); unsigned int (*get_fw_errcode)(struct sst_dsp *ctx);
int (*load_mod)(struct sst_dsp *ctx, u16 mod_id, u8 *mod_name); int (*load_mod)(struct sst_dsp *ctx, u16 mod_id, u8 *mod_name);
int (*unload_mod)(struct sst_dsp *ctx, u16 mod_id); int (*unload_mod)(struct sst_dsp *ctx, u16 mod_id);
...@@ -158,14 +176,26 @@ int skl_cldma_prepare(struct sst_dsp *ctx); ...@@ -158,14 +176,26 @@ int skl_cldma_prepare(struct sst_dsp *ctx);
void skl_dsp_set_state_locked(struct sst_dsp *ctx, int state); 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 *skl_dsp_ctx_init(struct device *dev,
struct sst_dsp_device *sst_dev, int irq); 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); 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); irqreturn_t skl_dsp_sst_interrupt(int irq, void *dev_id);
int skl_dsp_wake(struct sst_dsp *ctx); int skl_dsp_wake(struct sst_dsp *ctx);
int skl_dsp_sleep(struct sst_dsp *ctx); int skl_dsp_sleep(struct sst_dsp *ctx);
void skl_dsp_free(struct sst_dsp *dsp); 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_dsp_boot(struct sst_dsp *ctx);
int skl_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq, 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, 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); ...@@ -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); void skl_freeup_uuid_list(struct skl_sst *ctx);
int skl_dsp_strip_extended_manifest(struct firmware *fw); 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__*/ #endif /*__SKL_SST_DSP_H__*/
...@@ -45,6 +45,14 @@ struct skl_ipc_header { ...@@ -45,6 +45,14 @@ struct skl_ipc_header {
u32 extension; 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 skl_sst {
struct device *dev; struct device *dev;
struct sst_dsp *dsp; struct sst_dsp *dsp;
...@@ -66,6 +74,9 @@ struct skl_sst { ...@@ -66,6 +74,9 @@ struct skl_sst {
/* Is firmware loaded */ /* Is firmware loaded */
bool fw_loaded; bool fw_loaded;
/* multi-core */
struct skl_dsp_cores cores;
}; };
struct skl_ipc_init_instance_msg { struct skl_ipc_init_instance_msg {
......
...@@ -84,10 +84,8 @@ static int skl_load_base_firmware(struct sst_dsp *ctx) ...@@ -84,10 +84,8 @@ static int skl_load_base_firmware(struct sst_dsp *ctx)
ret = request_firmware(&ctx->fw, ctx->fw_name, ctx->dev); ret = request_firmware(&ctx->fw, ctx->fw_name, ctx->dev);
if (ret < 0) { if (ret < 0) {
dev_err(ctx->dev, "Request firmware failed %d\n", ret); dev_err(ctx->dev, "Request firmware failed %d\n", ret);
skl_dsp_disable_core(ctx);
return -EIO; return -EIO;
} }
} }
ret = snd_skl_parse_uuids(ctx, SKL_ADSP_FW_BIN_HDR_OFFSET); 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) ...@@ -95,7 +93,7 @@ static int skl_load_base_firmware(struct sst_dsp *ctx)
dev_err(ctx->dev, dev_err(ctx->dev,
"UUID parsing err: %d\n", ret); "UUID parsing err: %d\n", ret);
release_firmware(ctx->fw); release_firmware(ctx->fw);
skl_dsp_disable_core(ctx); skl_dsp_disable_core(ctx, SKL_DSP_CORE0_MASK);
return ret; return ret;
} }
...@@ -159,13 +157,13 @@ static int skl_load_base_firmware(struct sst_dsp *ctx) ...@@ -159,13 +157,13 @@ static int skl_load_base_firmware(struct sst_dsp *ctx)
transfer_firmware_failed: transfer_firmware_failed:
ctx->cl_dev.ops.cl_cleanup_controller(ctx); ctx->cl_dev.ops.cl_cleanup_controller(ctx);
skl_load_base_firmware_failed: skl_load_base_firmware_failed:
skl_dsp_disable_core(ctx); skl_dsp_disable_core(ctx, SKL_DSP_CORE0_MASK);
release_firmware(ctx->fw); release_firmware(ctx->fw);
ctx->fw = NULL; ctx->fw = NULL;
return ret; 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; int ret;
...@@ -180,7 +178,7 @@ static int skl_set_dsp_D0(struct sst_dsp *ctx) ...@@ -180,7 +178,7 @@ static int skl_set_dsp_D0(struct sst_dsp *ctx)
return ret; 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; int ret;
struct skl_ipc_dxstate_info dx; struct skl_ipc_dxstate_info dx;
...@@ -207,7 +205,7 @@ static int skl_set_dsp_D3(struct sst_dsp *ctx) ...@@ -207,7 +205,7 @@ static int skl_set_dsp_D3(struct sst_dsp *ctx)
skl_ipc_op_int_disable(ctx); skl_ipc_op_int_disable(ctx);
skl_ipc_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) { if (ret < 0) {
dev_err(ctx->dev, "disable dsp core failed ret: %d\n", ret); dev_err(ctx->dev, "disable dsp core failed ret: %d\n", ret);
ret = -EIO; ret = -EIO;
...@@ -466,12 +464,16 @@ int skl_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq, ...@@ -466,12 +464,16 @@ int skl_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq,
if (ret) if (ret)
return ret; return ret;
skl->cores.count = 2;
ret = sst->fw_ops.load_fw(sst); ret = sst->fw_ops.load_fw(sst);
if (ret < 0) { if (ret < 0) {
dev_err(dev, "Load base fw failed : %d", ret); dev_err(dev, "Load base fw failed : %d", ret);
goto cleanup; goto cleanup;
} }
skl_dsp_init_core_state(sst);
if (dsp) if (dsp)
*dsp = skl; *dsp = skl;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment