From patchwork Tue Jun 21 04:47:43 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vinod Koul X-Patchwork-Id: 9189425 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 45C0760756 for ; Tue, 21 Jun 2016 04:42:40 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 3271623B23 for ; Tue, 21 Jun 2016 04:42:40 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 2704727F9A; Tue, 21 Jun 2016 04:42:40 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-1.9 required=2.0 tests=BAYES_00, RCVD_IN_DNSWL_NONE autolearn=ham version=3.3.1 Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 345C923B23 for ; Tue, 21 Jun 2016 04:42:39 +0000 (UTC) Received: by alsa0.perex.cz (Postfix, from userid 1000) id 148AE266920; Tue, 21 Jun 2016 06:42:38 +0200 (CEST) Received: from alsa0.perex.cz (localhost [127.0.0.1]) by alsa0.perex.cz (Postfix) with ESMTP id D060126686F; Tue, 21 Jun 2016 06:41:12 +0200 (CEST) X-Original-To: alsa-devel@alsa-project.org Delivered-To: alsa-devel@alsa-project.org Received: by alsa0.perex.cz (Postfix, from userid 1000) id 7199C266867; Tue, 21 Jun 2016 06:41:11 +0200 (CEST) Received: from mga03.intel.com (mga03.intel.com [134.134.136.65]) by alsa0.perex.cz (Postfix) with ESMTP id EE72526584E for ; Tue, 21 Jun 2016 06:41:05 +0200 (CEST) Received: from orsmga001.jf.intel.com ([10.7.209.18]) by orsmga103.jf.intel.com with ESMTP; 20 Jun 2016 21:41:05 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.26,501,1459839600"; d="scan'208";a="980116560" Received: from vkoul-udesk7.iind.intel.com ([10.223.84.143]) by orsmga001.jf.intel.com with ESMTP; 20 Jun 2016 21:41:03 -0700 From: Vinod Koul To: alsa-devel@alsa-project.org Date: Tue, 21 Jun 2016 10:17:43 +0530 Message-Id: <1466484463-9129-4-git-send-email-vinod.koul@intel.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1466484463-9129-1-git-send-email-vinod.koul@intel.com> References: <1466484463-9129-1-git-send-email-vinod.koul@intel.com> Cc: liam.r.girdwood@linux.intel.com, patches.audio@intel.com, broonie@kernel.org, Vinod Koul , Jayachandran B Subject: [alsa-devel] [PATCH v2 3/3] ASoC: Intel: Skylake: Support multi-core in Broxton X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: alsa-devel-bounces@alsa-project.org Sender: alsa-devel-bounces@alsa-project.org X-Virus-Scanned: ClamAV using ClamSMTP From: Jayachandran B Add multicore DSP support in Broxton DSP operations. Signed-off-by: Jayachandran B Signed-off-by: Vinod Koul --- sound/soc/intel/skylake/bxt-sst.c | 144 +++++++++++++++++++++++++++----------- 1 file changed, 103 insertions(+), 41 deletions(-) diff --git a/sound/soc/intel/skylake/bxt-sst.c b/sound/soc/intel/skylake/bxt-sst.c index c3dc1c4f1fad..f53868956f39 100644 --- a/sound/soc/intel/skylake/bxt-sst.c +++ b/sound/soc/intel/skylake/bxt-sst.c @@ -37,11 +37,19 @@ #define BXT_ADSP_SRAM1_BASE 0xA0000 +#define BXT_INSTANCE_ID 0 +#define BXT_BASE_FW_MODULE_ID 0 + static unsigned int bxt_get_errorcode(struct sst_dsp *ctx) { return sst_dsp_shim_read(ctx, BXT_ADSP_ERROR_CODE); } +/* + * First boot sequence has some extra steps. Core 0 waits for power + * status on core 1, so power up core 1 also momentarily, keep it in + * reset/stall and then turn it off + */ static int sst_bxt_prepare_fw(struct sst_dsp *ctx, const void *fwdata, u32 fwsize) { @@ -49,7 +57,7 @@ static int sst_bxt_prepare_fw(struct sst_dsp *ctx, u32 reg; stream_tag = ctx->dsp_ops.prepare(ctx->dev, 0x40, fwsize, &ctx->dmab); - if (stream_tag < 0) { + if (stream_tag <= 0) { dev_err(ctx->dev, "Failed to prepare DMA FW loading err: %x\n", stream_tag); return stream_tag; @@ -58,16 +66,19 @@ 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, SKL_DSP_CORE0_MASK); + /* Step 1: Power up core 0 and core1 */ + ret = skl_dsp_core_power_up(ctx, SKL_DSP_CORE0_MASK | + SKL_DSP_CORE_MASK(1)); if (ret < 0) { - dev_err(ctx->dev, "Boot dsp core failed ret: %d\n", ret); + dev_err(ctx->dev, "dsp core0/1 power up failed\n"); goto base_fw_load_failed; } - /* Purge FW request */ + /* Step 2: Purge FW request */ sst_dsp_shim_write(ctx, SKL_ADSP_REG_HIPCI, SKL_ADSP_REG_HIPCI_BUSY | (BXT_IPC_PURGE_FW | ((stream_tag - 1) << 9))); + /* Step 3: Unset core0 reset state & unstall/run core0 */ 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); @@ -75,6 +86,7 @@ static int sst_bxt_prepare_fw(struct sst_dsp *ctx, goto base_fw_load_failed; } + /* Step 4: Wait for DONE Bit */ for (i = BXT_INIT_TIMEOUT; i > 0; --i) { reg = sst_dsp_shim_read(ctx, SKL_ADSP_REG_HIPCIE); @@ -94,10 +106,18 @@ static int sst_bxt_prepare_fw(struct sst_dsp *ctx, SKL_ADSP_REG_HIPCIE_DONE); } - /* enable Interrupt */ + /* Step 5: power down core1 */ + ret = skl_dsp_core_power_down(ctx, SKL_DSP_CORE_MASK(1)); + if (ret < 0) { + dev_err(ctx->dev, "dsp core1 power down failed\n"); + goto base_fw_load_failed; + } + + /* Step 6: Enable Interrupt */ skl_ipc_int_enable(ctx); skl_ipc_op_int_enable(ctx); + /* Step 7: Wait for ROM init */ for (i = BXT_INIT_TIMEOUT; i > 0; --i) { if (SKL_FW_INIT == (sst_dsp_shim_read(ctx, BXT_ADSP_FW_STATUS) & @@ -194,7 +214,6 @@ static int bxt_load_base_firmware(struct sst_dsp *ctx) skl_dsp_disable_core(ctx, SKL_DSP_CORE0_MASK); ret = -EIO; } else { - skl_dsp_set_state_locked(ctx, SKL_DSP_RUNNING); ret = 0; skl->fw_loaded = true; } @@ -209,67 +228,110 @@ static int bxt_set_dsp_D0(struct sst_dsp *ctx, unsigned int core_id) { struct skl_sst *skl = ctx->thread_context; int ret; - - skl->boot_complete = false; + struct skl_ipc_dxstate_info dx; + unsigned int core_mask = SKL_DSP_CORE_MASK(core_id); if (skl->fw_loaded == false) { - dev_dbg(ctx->dev, "Re-loading fw\n"); ret = bxt_load_base_firmware(ctx); if (ret < 0) dev_err(ctx->dev, "reload fw failed: %d\n", ret); return ret; } - 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; + /* If core 0 is being turned on, turn on core 1 as well */ + if (core_id == SKL_DSP_CORE0_ID) + ret = skl_dsp_core_power_up(ctx, core_mask | + SKL_DSP_CORE_MASK(1)); + else + ret = skl_dsp_core_power_up(ctx, core_mask); + + if (ret < 0) + goto err; + + if (core_id == SKL_DSP_CORE0_ID) { + + /* + * Enable interrupt after SPA is set and before + * DSP is unstalled + */ + skl_ipc_int_enable(ctx); + skl_ipc_op_int_enable(ctx); + skl->boot_complete = false; } - /* enable interrupt */ - skl_ipc_int_enable(ctx); - skl_ipc_op_int_enable(ctx); + ret = skl_dsp_start_core(ctx, core_mask); + if (ret < 0) + goto err; - ret = wait_event_timeout(skl->boot_wait, skl->boot_complete, - msecs_to_jiffies(SKL_IPC_BOOT_MSECS)); - if (ret == 0) { - dev_err(ctx->dev, "ipc: error DSP boot timeout\n"); - dev_err(ctx->dev, "Error code=0x%x: FW status=0x%x\n", - sst_dsp_shim_read(ctx, BXT_ADSP_ERROR_CODE), - sst_dsp_shim_read(ctx, BXT_ADSP_FW_STATUS)); - return -EIO; + if (core_id == SKL_DSP_CORE0_ID) { + ret = wait_event_timeout(skl->boot_wait, + skl->boot_complete, + msecs_to_jiffies(SKL_IPC_BOOT_MSECS)); + + /* If core 1 was turned on for booting core 0, turn it off */ + skl_dsp_core_power_down(ctx, SKL_DSP_CORE_MASK(1)); + if (ret == 0) { + dev_err(ctx->dev, "%s: DSP boot timeout\n", __func__); + dev_err(ctx->dev, "Error code=0x%x: FW status=0x%x\n", + sst_dsp_shim_read(ctx, BXT_ADSP_ERROR_CODE), + sst_dsp_shim_read(ctx, BXT_ADSP_FW_STATUS)); + dev_err(ctx->dev, "Failed to set core0 to D0 state\n"); + ret = -EIO; + goto err; + } + } + + /* Tell FW if additional core in now On */ + + if (core_id != SKL_DSP_CORE0_ID) { + dx.core_mask = core_mask; + dx.dx_mask = core_mask; + + ret = skl_ipc_set_dx(&skl->ipc, BXT_INSTANCE_ID, + BXT_BASE_FW_MODULE_ID, &dx); + if (ret < 0) { + dev_err(ctx->dev, "IPC set_dx for core %d fail: %d\n", + core_id, ret); + goto err; + } } - skl_dsp_set_state_locked(ctx, SKL_DSP_RUNNING); + skl->cores.state[core_id] = SKL_DSP_RUNNING; return 0; +err: + if (core_id == SKL_DSP_CORE0_ID) + core_mask |= SKL_DSP_CORE_MASK(1); + skl_dsp_disable_core(ctx, core_mask); + + return ret; } static int bxt_set_dsp_D3(struct sst_dsp *ctx, unsigned int core_id) { + int ret; struct skl_ipc_dxstate_info dx; struct skl_sst *skl = ctx->thread_context; - int ret = 0; - - if (!is_skl_dsp_running(ctx)) - return ret; + unsigned int core_mask = SKL_DSP_CORE_MASK(core_id); - dx.core_mask = SKL_DSP_CORE0_MASK; + dx.core_mask = core_mask; dx.dx_mask = SKL_IPC_D3_MASK; - ret = skl_ipc_set_dx(&skl->ipc, SKL_INSTANCE_ID, - SKL_BASE_FW_MODULE_ID, &dx); - if (ret < 0) { - dev_err(ctx->dev, "Failed to set DSP to D3 state: %d\n", ret); - return ret; - } + dev_dbg(ctx->dev, "core mask=%x dx_mask=%x\n", + dx.core_mask, dx.dx_mask); - ret = skl_dsp_disable_core(ctx, SKL_DSP_CORE0_MASK); + ret = skl_ipc_set_dx(&skl->ipc, BXT_INSTANCE_ID, + BXT_BASE_FW_MODULE_ID, &dx); + if (ret < 0) + dev_err(ctx->dev, + "Failed to set DSP to D3:core id = %d;Continue reset\n", + core_id); + + ret = skl_dsp_disable_core(ctx, core_mask); if (ret < 0) { - dev_err(ctx->dev, "disbale dsp core failed: %d\n", ret); - ret = -EIO; + dev_err(ctx->dev, "Failed to disable core %d", ret); + return ret; } - - skl_dsp_set_state_locked(ctx, SKL_DSP_RESET); + skl->cores.state[core_id] = SKL_DSP_RESET; return 0; }