192eb4f62SJeeja KP /* 292eb4f62SJeeja KP * bxt-sst.c - DSP library functions for BXT platform 392eb4f62SJeeja KP * 492eb4f62SJeeja KP * Copyright (C) 2015-16 Intel Corp 592eb4f62SJeeja KP * Author:Rafal Redzimski <rafal.f.redzimski@intel.com> 692eb4f62SJeeja KP * Jeeja KP <jeeja.kp@intel.com> 792eb4f62SJeeja KP * 892eb4f62SJeeja KP * This program is free software; you can redistribute it and/or modify 992eb4f62SJeeja KP * it under the terms of the GNU General Public License as published by 1092eb4f62SJeeja KP * the Free Software Foundation; version 2 of the License. 1192eb4f62SJeeja KP * 1292eb4f62SJeeja KP * This program is distributed in the hope that it will be useful, but 1392eb4f62SJeeja KP * WITHOUT ANY WARRANTY; without even the implied warranty of 1492eb4f62SJeeja KP * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 1592eb4f62SJeeja KP * General Public License for more details. 1692eb4f62SJeeja KP */ 1792eb4f62SJeeja KP 1892eb4f62SJeeja KP #include <linux/module.h> 1992eb4f62SJeeja KP #include <linux/delay.h> 2092eb4f62SJeeja KP #include <linux/firmware.h> 2192eb4f62SJeeja KP #include <linux/device.h> 2292eb4f62SJeeja KP 2392eb4f62SJeeja KP #include "../common/sst-dsp.h" 2492eb4f62SJeeja KP #include "../common/sst-dsp-priv.h" 2592eb4f62SJeeja KP #include "skl-sst-ipc.h" 2692eb4f62SJeeja KP 2792eb4f62SJeeja KP #define BXT_BASEFW_TIMEOUT 3000 2892eb4f62SJeeja KP #define BXT_INIT_TIMEOUT 500 2992eb4f62SJeeja KP #define BXT_IPC_PURGE_FW 0x01004000 3092eb4f62SJeeja KP 3192eb4f62SJeeja KP #define BXT_ROM_INIT 0x5 3292eb4f62SJeeja KP #define BXT_ADSP_SRAM0_BASE 0x80000 3392eb4f62SJeeja KP 3492eb4f62SJeeja KP /* Firmware status window */ 3592eb4f62SJeeja KP #define BXT_ADSP_FW_STATUS BXT_ADSP_SRAM0_BASE 3692eb4f62SJeeja KP #define BXT_ADSP_ERROR_CODE (BXT_ADSP_FW_STATUS + 0x4) 3792eb4f62SJeeja KP 3892eb4f62SJeeja KP #define BXT_ADSP_SRAM1_BASE 0xA0000 3992eb4f62SJeeja KP 40e68aca08SJayachandran B #define BXT_INSTANCE_ID 0 41e68aca08SJayachandran B #define BXT_BASE_FW_MODULE_ID 0 42e68aca08SJayachandran B 4392eb4f62SJeeja KP static unsigned int bxt_get_errorcode(struct sst_dsp *ctx) 4492eb4f62SJeeja KP { 4592eb4f62SJeeja KP return sst_dsp_shim_read(ctx, BXT_ADSP_ERROR_CODE); 4692eb4f62SJeeja KP } 4792eb4f62SJeeja KP 48e68aca08SJayachandran B /* 49e68aca08SJayachandran B * First boot sequence has some extra steps. Core 0 waits for power 50e68aca08SJayachandran B * status on core 1, so power up core 1 also momentarily, keep it in 51e68aca08SJayachandran B * reset/stall and then turn it off 52e68aca08SJayachandran B */ 5392eb4f62SJeeja KP static int sst_bxt_prepare_fw(struct sst_dsp *ctx, 5492eb4f62SJeeja KP const void *fwdata, u32 fwsize) 5592eb4f62SJeeja KP { 5692eb4f62SJeeja KP int stream_tag, ret, i; 5792eb4f62SJeeja KP u32 reg; 5892eb4f62SJeeja KP 5992eb4f62SJeeja KP stream_tag = ctx->dsp_ops.prepare(ctx->dev, 0x40, fwsize, &ctx->dmab); 60e68aca08SJayachandran B if (stream_tag <= 0) { 6192eb4f62SJeeja KP dev_err(ctx->dev, "Failed to prepare DMA FW loading err: %x\n", 6292eb4f62SJeeja KP stream_tag); 6392eb4f62SJeeja KP return stream_tag; 6492eb4f62SJeeja KP } 6592eb4f62SJeeja KP 6692eb4f62SJeeja KP ctx->dsp_ops.stream_tag = stream_tag; 6792eb4f62SJeeja KP memcpy(ctx->dmab.area, fwdata, fwsize); 6892eb4f62SJeeja KP 69e68aca08SJayachandran B /* Step 1: Power up core 0 and core1 */ 70e68aca08SJayachandran B ret = skl_dsp_core_power_up(ctx, SKL_DSP_CORE0_MASK | 71e68aca08SJayachandran B SKL_DSP_CORE_MASK(1)); 7292eb4f62SJeeja KP if (ret < 0) { 73e68aca08SJayachandran B dev_err(ctx->dev, "dsp core0/1 power up failed\n"); 742023576dSSenthilnathan Veppur goto base_fw_load_failed; 752023576dSSenthilnathan Veppur } 762023576dSSenthilnathan Veppur 77e68aca08SJayachandran B /* Step 2: Purge FW request */ 782023576dSSenthilnathan Veppur sst_dsp_shim_write(ctx, SKL_ADSP_REG_HIPCI, SKL_ADSP_REG_HIPCI_BUSY | 792023576dSSenthilnathan Veppur (BXT_IPC_PURGE_FW | ((stream_tag - 1) << 9))); 802023576dSSenthilnathan Veppur 81e68aca08SJayachandran B /* Step 3: Unset core0 reset state & unstall/run core0 */ 82052f103cSJayachandran B ret = skl_dsp_start_core(ctx, SKL_DSP_CORE0_MASK); 832023576dSSenthilnathan Veppur if (ret < 0) { 842023576dSSenthilnathan Veppur dev_err(ctx->dev, "Start dsp core failed ret: %d\n", ret); 8592eb4f62SJeeja KP ret = -EIO; 8692eb4f62SJeeja KP goto base_fw_load_failed; 8792eb4f62SJeeja KP } 8892eb4f62SJeeja KP 89e68aca08SJayachandran B /* Step 4: Wait for DONE Bit */ 9092eb4f62SJeeja KP for (i = BXT_INIT_TIMEOUT; i > 0; --i) { 9192eb4f62SJeeja KP reg = sst_dsp_shim_read(ctx, SKL_ADSP_REG_HIPCIE); 9292eb4f62SJeeja KP 9392eb4f62SJeeja KP if (reg & SKL_ADSP_REG_HIPCIE_DONE) { 9492eb4f62SJeeja KP sst_dsp_shim_update_bits_forced(ctx, 9592eb4f62SJeeja KP SKL_ADSP_REG_HIPCIE, 9692eb4f62SJeeja KP SKL_ADSP_REG_HIPCIE_DONE, 9792eb4f62SJeeja KP SKL_ADSP_REG_HIPCIE_DONE); 9892eb4f62SJeeja KP break; 9992eb4f62SJeeja KP } 10092eb4f62SJeeja KP mdelay(1); 10192eb4f62SJeeja KP } 10292eb4f62SJeeja KP if (!i) { 10392eb4f62SJeeja KP dev_info(ctx->dev, "Waiting for HIPCIE done, reg: 0x%x\n", reg); 10492eb4f62SJeeja KP sst_dsp_shim_update_bits(ctx, SKL_ADSP_REG_HIPCIE, 10592eb4f62SJeeja KP SKL_ADSP_REG_HIPCIE_DONE, 10692eb4f62SJeeja KP SKL_ADSP_REG_HIPCIE_DONE); 10792eb4f62SJeeja KP } 10892eb4f62SJeeja KP 109e68aca08SJayachandran B /* Step 5: power down core1 */ 110e68aca08SJayachandran B ret = skl_dsp_core_power_down(ctx, SKL_DSP_CORE_MASK(1)); 111e68aca08SJayachandran B if (ret < 0) { 112e68aca08SJayachandran B dev_err(ctx->dev, "dsp core1 power down failed\n"); 113e68aca08SJayachandran B goto base_fw_load_failed; 114e68aca08SJayachandran B } 115e68aca08SJayachandran B 116e68aca08SJayachandran B /* Step 6: Enable Interrupt */ 11792eb4f62SJeeja KP skl_ipc_int_enable(ctx); 11892eb4f62SJeeja KP skl_ipc_op_int_enable(ctx); 11992eb4f62SJeeja KP 120e68aca08SJayachandran B /* Step 7: Wait for ROM init */ 12192eb4f62SJeeja KP for (i = BXT_INIT_TIMEOUT; i > 0; --i) { 12292eb4f62SJeeja KP if (SKL_FW_INIT == 12392eb4f62SJeeja KP (sst_dsp_shim_read(ctx, BXT_ADSP_FW_STATUS) & 12492eb4f62SJeeja KP SKL_FW_STS_MASK)) { 12592eb4f62SJeeja KP 12692eb4f62SJeeja KP dev_info(ctx->dev, "ROM loaded, continue FW loading\n"); 12792eb4f62SJeeja KP break; 12892eb4f62SJeeja KP } 12992eb4f62SJeeja KP mdelay(1); 13092eb4f62SJeeja KP } 13192eb4f62SJeeja KP if (!i) { 13292eb4f62SJeeja KP dev_err(ctx->dev, "Timeout for ROM init, HIPCIE: 0x%x\n", reg); 13392eb4f62SJeeja KP ret = -EIO; 13492eb4f62SJeeja KP goto base_fw_load_failed; 13592eb4f62SJeeja KP } 13692eb4f62SJeeja KP 13792eb4f62SJeeja KP return ret; 13892eb4f62SJeeja KP 13992eb4f62SJeeja KP base_fw_load_failed: 14092eb4f62SJeeja KP ctx->dsp_ops.cleanup(ctx->dev, &ctx->dmab, stream_tag); 141052f103cSJayachandran B skl_dsp_core_power_down(ctx, SKL_DSP_CORE_MASK(1)); 142c7872267SSenthilnathan Veppur skl_dsp_disable_core(ctx, SKL_DSP_CORE0_MASK); 14392eb4f62SJeeja KP return ret; 14492eb4f62SJeeja KP } 14592eb4f62SJeeja KP 14692eb4f62SJeeja KP static int sst_transfer_fw_host_dma(struct sst_dsp *ctx) 14792eb4f62SJeeja KP { 14892eb4f62SJeeja KP int ret; 14992eb4f62SJeeja KP 15092eb4f62SJeeja KP ctx->dsp_ops.trigger(ctx->dev, true, ctx->dsp_ops.stream_tag); 15192eb4f62SJeeja KP ret = sst_dsp_register_poll(ctx, BXT_ADSP_FW_STATUS, SKL_FW_STS_MASK, 15292eb4f62SJeeja KP BXT_ROM_INIT, BXT_BASEFW_TIMEOUT, "Firmware boot"); 15392eb4f62SJeeja KP 15492eb4f62SJeeja KP ctx->dsp_ops.trigger(ctx->dev, false, ctx->dsp_ops.stream_tag); 15592eb4f62SJeeja KP ctx->dsp_ops.cleanup(ctx->dev, &ctx->dmab, ctx->dsp_ops.stream_tag); 15692eb4f62SJeeja KP 15792eb4f62SJeeja KP return ret; 15892eb4f62SJeeja KP } 15992eb4f62SJeeja KP 1603467a64dSVinod Koul #define BXT_ADSP_FW_BIN_HDR_OFFSET 0x2000 1613467a64dSVinod Koul 16292eb4f62SJeeja KP static int bxt_load_base_firmware(struct sst_dsp *ctx) 16392eb4f62SJeeja KP { 164bf242d19SVinod Koul struct firmware stripped_fw; 16592eb4f62SJeeja KP struct skl_sst *skl = ctx->thread_context; 16692eb4f62SJeeja KP int ret; 16792eb4f62SJeeja KP 168fdfa82eeSVinod Koul ret = request_firmware(&ctx->fw, ctx->fw_name, ctx->dev); 16992eb4f62SJeeja KP if (ret < 0) { 17092eb4f62SJeeja KP dev_err(ctx->dev, "Request firmware failed %d\n", ret); 17192eb4f62SJeeja KP goto sst_load_base_firmware_failed; 17292eb4f62SJeeja KP } 17392eb4f62SJeeja KP 174bf242d19SVinod Koul /* check for extended manifest */ 175bf242d19SVinod Koul if (ctx->fw == NULL) 176bf242d19SVinod Koul goto sst_load_base_firmware_failed; 177bf242d19SVinod Koul 178a8e2c19eSSenthilnathan Veppur ret = snd_skl_parse_uuids(ctx, ctx->fw, BXT_ADSP_FW_BIN_HDR_OFFSET, 0); 1793467a64dSVinod Koul if (ret < 0) 1803467a64dSVinod Koul goto sst_load_base_firmware_failed; 181bf242d19SVinod Koul 182bf242d19SVinod Koul stripped_fw.data = ctx->fw->data; 183bf242d19SVinod Koul stripped_fw.size = ctx->fw->size; 184bf242d19SVinod Koul skl_dsp_strip_extended_manifest(&stripped_fw); 185bf242d19SVinod Koul 186bf242d19SVinod Koul ret = sst_bxt_prepare_fw(ctx, stripped_fw.data, stripped_fw.size); 18792eb4f62SJeeja KP /* Retry Enabling core and ROM load. Retry seemed to help */ 18892eb4f62SJeeja KP if (ret < 0) { 189bf242d19SVinod Koul ret = sst_bxt_prepare_fw(ctx, stripped_fw.data, stripped_fw.size); 19092eb4f62SJeeja KP if (ret < 0) { 1912023576dSSenthilnathan Veppur dev_err(ctx->dev, "Error code=0x%x: FW status=0x%x\n", 1922023576dSSenthilnathan Veppur sst_dsp_shim_read(ctx, BXT_ADSP_ERROR_CODE), 1932023576dSSenthilnathan Veppur sst_dsp_shim_read(ctx, BXT_ADSP_FW_STATUS)); 1942023576dSSenthilnathan Veppur 19592eb4f62SJeeja KP dev_err(ctx->dev, "Core En/ROM load fail:%d\n", ret); 19692eb4f62SJeeja KP goto sst_load_base_firmware_failed; 19792eb4f62SJeeja KP } 19892eb4f62SJeeja KP } 19992eb4f62SJeeja KP 20092eb4f62SJeeja KP ret = sst_transfer_fw_host_dma(ctx); 20192eb4f62SJeeja KP if (ret < 0) { 20292eb4f62SJeeja KP dev_err(ctx->dev, "Transfer firmware failed %d\n", ret); 20392eb4f62SJeeja KP dev_info(ctx->dev, "Error code=0x%x: FW status=0x%x\n", 20492eb4f62SJeeja KP sst_dsp_shim_read(ctx, BXT_ADSP_ERROR_CODE), 20592eb4f62SJeeja KP sst_dsp_shim_read(ctx, BXT_ADSP_FW_STATUS)); 20692eb4f62SJeeja KP 207052f103cSJayachandran B skl_dsp_disable_core(ctx, SKL_DSP_CORE0_MASK); 20892eb4f62SJeeja KP } else { 20992eb4f62SJeeja KP dev_dbg(ctx->dev, "Firmware download successful\n"); 21092eb4f62SJeeja KP ret = wait_event_timeout(skl->boot_wait, skl->boot_complete, 21192eb4f62SJeeja KP msecs_to_jiffies(SKL_IPC_BOOT_MSECS)); 21292eb4f62SJeeja KP if (ret == 0) { 21392eb4f62SJeeja KP dev_err(ctx->dev, "DSP boot fail, FW Ready timeout\n"); 214052f103cSJayachandran B skl_dsp_disable_core(ctx, SKL_DSP_CORE0_MASK); 21592eb4f62SJeeja KP ret = -EIO; 21692eb4f62SJeeja KP } else { 21792eb4f62SJeeja KP ret = 0; 2181665c177SJayachandran B skl->fw_loaded = true; 21992eb4f62SJeeja KP } 22092eb4f62SJeeja KP } 22192eb4f62SJeeja KP 22292eb4f62SJeeja KP sst_load_base_firmware_failed: 223fdfa82eeSVinod Koul release_firmware(ctx->fw); 22492eb4f62SJeeja KP return ret; 22592eb4f62SJeeja KP } 22692eb4f62SJeeja KP 227052f103cSJayachandran B static int bxt_set_dsp_D0(struct sst_dsp *ctx, unsigned int core_id) 22892eb4f62SJeeja KP { 22992eb4f62SJeeja KP struct skl_sst *skl = ctx->thread_context; 23092eb4f62SJeeja KP int ret; 231e68aca08SJayachandran B struct skl_ipc_dxstate_info dx; 232e68aca08SJayachandran B unsigned int core_mask = SKL_DSP_CORE_MASK(core_id); 23392eb4f62SJeeja KP 2341665c177SJayachandran B if (skl->fw_loaded == false) { 23592eb4f62SJeeja KP skl->boot_complete = false; 2361665c177SJayachandran B ret = bxt_load_base_firmware(ctx); 2371665c177SJayachandran B if (ret < 0) 2381665c177SJayachandran B dev_err(ctx->dev, "reload fw failed: %d\n", ret); 23992eb4f62SJeeja KP return ret; 24092eb4f62SJeeja KP } 24192eb4f62SJeeja KP 242e68aca08SJayachandran B /* If core 0 is being turned on, turn on core 1 as well */ 243e68aca08SJayachandran B if (core_id == SKL_DSP_CORE0_ID) 244e68aca08SJayachandran B ret = skl_dsp_core_power_up(ctx, core_mask | 245e68aca08SJayachandran B SKL_DSP_CORE_MASK(1)); 246e68aca08SJayachandran B else 247e68aca08SJayachandran B ret = skl_dsp_core_power_up(ctx, core_mask); 24892eb4f62SJeeja KP 249e68aca08SJayachandran B if (ret < 0) 250e68aca08SJayachandran B goto err; 251e68aca08SJayachandran B 252e68aca08SJayachandran B if (core_id == SKL_DSP_CORE0_ID) { 253e68aca08SJayachandran B 254e68aca08SJayachandran B /* 255e68aca08SJayachandran B * Enable interrupt after SPA is set and before 256e68aca08SJayachandran B * DSP is unstalled 257e68aca08SJayachandran B */ 25892eb4f62SJeeja KP skl_ipc_int_enable(ctx); 25992eb4f62SJeeja KP skl_ipc_op_int_enable(ctx); 260e68aca08SJayachandran B skl->boot_complete = false; 261e68aca08SJayachandran B } 26292eb4f62SJeeja KP 263e68aca08SJayachandran B ret = skl_dsp_start_core(ctx, core_mask); 264e68aca08SJayachandran B if (ret < 0) 265e68aca08SJayachandran B goto err; 266e68aca08SJayachandran B 267e68aca08SJayachandran B if (core_id == SKL_DSP_CORE0_ID) { 268e68aca08SJayachandran B ret = wait_event_timeout(skl->boot_wait, 269e68aca08SJayachandran B skl->boot_complete, 27092eb4f62SJeeja KP msecs_to_jiffies(SKL_IPC_BOOT_MSECS)); 271e68aca08SJayachandran B 272e68aca08SJayachandran B /* If core 1 was turned on for booting core 0, turn it off */ 273e68aca08SJayachandran B skl_dsp_core_power_down(ctx, SKL_DSP_CORE_MASK(1)); 27492eb4f62SJeeja KP if (ret == 0) { 275e68aca08SJayachandran B dev_err(ctx->dev, "%s: DSP boot timeout\n", __func__); 27692eb4f62SJeeja KP dev_err(ctx->dev, "Error code=0x%x: FW status=0x%x\n", 27792eb4f62SJeeja KP sst_dsp_shim_read(ctx, BXT_ADSP_ERROR_CODE), 27892eb4f62SJeeja KP sst_dsp_shim_read(ctx, BXT_ADSP_FW_STATUS)); 279e68aca08SJayachandran B dev_err(ctx->dev, "Failed to set core0 to D0 state\n"); 280e68aca08SJayachandran B ret = -EIO; 281e68aca08SJayachandran B goto err; 282e68aca08SJayachandran B } 28392eb4f62SJeeja KP } 28492eb4f62SJeeja KP 285e68aca08SJayachandran B /* Tell FW if additional core in now On */ 286e68aca08SJayachandran B 287e68aca08SJayachandran B if (core_id != SKL_DSP_CORE0_ID) { 288e68aca08SJayachandran B dx.core_mask = core_mask; 289e68aca08SJayachandran B dx.dx_mask = core_mask; 290e68aca08SJayachandran B 291e68aca08SJayachandran B ret = skl_ipc_set_dx(&skl->ipc, BXT_INSTANCE_ID, 292e68aca08SJayachandran B BXT_BASE_FW_MODULE_ID, &dx); 293e68aca08SJayachandran B if (ret < 0) { 294e68aca08SJayachandran B dev_err(ctx->dev, "IPC set_dx for core %d fail: %d\n", 295e68aca08SJayachandran B core_id, ret); 296e68aca08SJayachandran B goto err; 297e68aca08SJayachandran B } 298e68aca08SJayachandran B } 299e68aca08SJayachandran B 300e68aca08SJayachandran B skl->cores.state[core_id] = SKL_DSP_RUNNING; 30192eb4f62SJeeja KP return 0; 302e68aca08SJayachandran B err: 303e68aca08SJayachandran B if (core_id == SKL_DSP_CORE0_ID) 304e68aca08SJayachandran B core_mask |= SKL_DSP_CORE_MASK(1); 305e68aca08SJayachandran B skl_dsp_disable_core(ctx, core_mask); 306e68aca08SJayachandran B 307e68aca08SJayachandran B return ret; 30892eb4f62SJeeja KP } 30992eb4f62SJeeja KP 310052f103cSJayachandran B static int bxt_set_dsp_D3(struct sst_dsp *ctx, unsigned int core_id) 31192eb4f62SJeeja KP { 312e68aca08SJayachandran B int ret; 31392eb4f62SJeeja KP struct skl_ipc_dxstate_info dx; 31492eb4f62SJeeja KP struct skl_sst *skl = ctx->thread_context; 315e68aca08SJayachandran B unsigned int core_mask = SKL_DSP_CORE_MASK(core_id); 31692eb4f62SJeeja KP 317e68aca08SJayachandran B dx.core_mask = core_mask; 31892eb4f62SJeeja KP dx.dx_mask = SKL_IPC_D3_MASK; 31992eb4f62SJeeja KP 320e68aca08SJayachandran B dev_dbg(ctx->dev, "core mask=%x dx_mask=%x\n", 321e68aca08SJayachandran B dx.core_mask, dx.dx_mask); 322e68aca08SJayachandran B 323e68aca08SJayachandran B ret = skl_ipc_set_dx(&skl->ipc, BXT_INSTANCE_ID, 324e68aca08SJayachandran B BXT_BASE_FW_MODULE_ID, &dx); 325e68aca08SJayachandran B if (ret < 0) 326e68aca08SJayachandran B dev_err(ctx->dev, 327e68aca08SJayachandran B "Failed to set DSP to D3:core id = %d;Continue reset\n", 328e68aca08SJayachandran B core_id); 329e68aca08SJayachandran B 330e68aca08SJayachandran B ret = skl_dsp_disable_core(ctx, core_mask); 33192eb4f62SJeeja KP if (ret < 0) { 332e68aca08SJayachandran B dev_err(ctx->dev, "Failed to disable core %d", ret); 33392eb4f62SJeeja KP return ret; 33492eb4f62SJeeja KP } 335e68aca08SJayachandran B skl->cores.state[core_id] = SKL_DSP_RESET; 33692eb4f62SJeeja KP return 0; 33792eb4f62SJeeja KP } 33892eb4f62SJeeja KP 33992eb4f62SJeeja KP static struct skl_dsp_fw_ops bxt_fw_ops = { 34092eb4f62SJeeja KP .set_state_D0 = bxt_set_dsp_D0, 34192eb4f62SJeeja KP .set_state_D3 = bxt_set_dsp_D3, 34292eb4f62SJeeja KP .load_fw = bxt_load_base_firmware, 34392eb4f62SJeeja KP .get_fw_errcode = bxt_get_errorcode, 34492eb4f62SJeeja KP }; 34592eb4f62SJeeja KP 34692eb4f62SJeeja KP static struct sst_ops skl_ops = { 34792eb4f62SJeeja KP .irq_handler = skl_dsp_sst_interrupt, 34892eb4f62SJeeja KP .write = sst_shim32_write, 34992eb4f62SJeeja KP .read = sst_shim32_read, 35092eb4f62SJeeja KP .ram_read = sst_memcpy_fromio_32, 35192eb4f62SJeeja KP .ram_write = sst_memcpy_toio_32, 35292eb4f62SJeeja KP .free = skl_dsp_free, 35392eb4f62SJeeja KP }; 35492eb4f62SJeeja KP 35592eb4f62SJeeja KP static struct sst_dsp_device skl_dev = { 35692eb4f62SJeeja KP .thread = skl_dsp_irq_thread_handler, 35792eb4f62SJeeja KP .ops = &skl_ops, 35892eb4f62SJeeja KP }; 35992eb4f62SJeeja KP 36092eb4f62SJeeja KP int bxt_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq, 36192eb4f62SJeeja KP const char *fw_name, struct skl_dsp_loader_ops dsp_ops, 36292eb4f62SJeeja KP struct skl_sst **dsp) 36392eb4f62SJeeja KP { 36492eb4f62SJeeja KP struct skl_sst *skl; 36592eb4f62SJeeja KP struct sst_dsp *sst; 36692eb4f62SJeeja KP int ret; 36792eb4f62SJeeja KP 36892eb4f62SJeeja KP skl = devm_kzalloc(dev, sizeof(*skl), GFP_KERNEL); 36992eb4f62SJeeja KP if (skl == NULL) 37092eb4f62SJeeja KP return -ENOMEM; 37192eb4f62SJeeja KP 37292eb4f62SJeeja KP skl->dev = dev; 37392eb4f62SJeeja KP skl_dev.thread_context = skl; 3743467a64dSVinod Koul INIT_LIST_HEAD(&skl->uuid_list); 37592eb4f62SJeeja KP 37692eb4f62SJeeja KP skl->dsp = skl_dsp_ctx_init(dev, &skl_dev, irq); 37792eb4f62SJeeja KP if (!skl->dsp) { 37892eb4f62SJeeja KP dev_err(skl->dev, "skl_dsp_ctx_init failed\n"); 37992eb4f62SJeeja KP return -ENODEV; 38092eb4f62SJeeja KP } 38192eb4f62SJeeja KP 38292eb4f62SJeeja KP sst = skl->dsp; 38392eb4f62SJeeja KP sst->fw_name = fw_name; 38492eb4f62SJeeja KP sst->dsp_ops = dsp_ops; 38592eb4f62SJeeja KP sst->fw_ops = bxt_fw_ops; 38692eb4f62SJeeja KP sst->addr.lpe = mmio_base; 38792eb4f62SJeeja KP sst->addr.shim = mmio_base; 38892eb4f62SJeeja KP 38992eb4f62SJeeja KP sst_dsp_mailbox_init(sst, (BXT_ADSP_SRAM0_BASE + SKL_ADSP_W0_STAT_SZ), 39092eb4f62SJeeja KP SKL_ADSP_W0_UP_SZ, BXT_ADSP_SRAM1_BASE, SKL_ADSP_W1_SZ); 39192eb4f62SJeeja KP 392b914bb55SVinod Koul INIT_LIST_HEAD(&sst->module_list); 39392eb4f62SJeeja KP ret = skl_ipc_init(dev, skl); 39492eb4f62SJeeja KP if (ret) 39592eb4f62SJeeja KP return ret; 39692eb4f62SJeeja KP 397052f103cSJayachandran B skl->cores.count = 2; 39892eb4f62SJeeja KP skl->boot_complete = false; 39992eb4f62SJeeja KP init_waitqueue_head(&skl->boot_wait); 40078cdbbdaSVinod Koul skl->is_first_boot = true; 40178cdbbdaSVinod Koul 40278cdbbdaSVinod Koul if (dsp) 40378cdbbdaSVinod Koul *dsp = skl; 40478cdbbdaSVinod Koul 40578cdbbdaSVinod Koul return 0; 40678cdbbdaSVinod Koul } 40778cdbbdaSVinod Koul EXPORT_SYMBOL_GPL(bxt_sst_dsp_init); 40878cdbbdaSVinod Koul 40978cdbbdaSVinod Koul int bxt_sst_init_fw(struct device *dev, struct skl_sst *ctx) 41078cdbbdaSVinod Koul { 41178cdbbdaSVinod Koul int ret; 41278cdbbdaSVinod Koul struct sst_dsp *sst = ctx->dsp; 41392eb4f62SJeeja KP 41492eb4f62SJeeja KP ret = sst->fw_ops.load_fw(sst); 41592eb4f62SJeeja KP if (ret < 0) { 41692eb4f62SJeeja KP dev_err(dev, "Load base fw failed: %x", ret); 41792eb4f62SJeeja KP return ret; 41892eb4f62SJeeja KP } 41992eb4f62SJeeja KP 420052f103cSJayachandran B skl_dsp_init_core_state(sst); 421052f103cSJayachandran B 42278cdbbdaSVinod Koul ctx->is_first_boot = false; 42392eb4f62SJeeja KP 42492eb4f62SJeeja KP return 0; 42592eb4f62SJeeja KP } 42678cdbbdaSVinod Koul EXPORT_SYMBOL_GPL(bxt_sst_init_fw); 42792eb4f62SJeeja KP 42892eb4f62SJeeja KP void bxt_sst_dsp_cleanup(struct device *dev, struct skl_sst *ctx) 42992eb4f62SJeeja KP { 4303467a64dSVinod Koul skl_freeup_uuid_list(ctx); 43192eb4f62SJeeja KP skl_ipc_free(&ctx->ipc); 43292eb4f62SJeeja KP ctx->dsp->cl_dev.ops.cl_cleanup_controller(ctx->dsp); 43392eb4f62SJeeja KP 43492eb4f62SJeeja KP if (ctx->dsp->addr.lpe) 43592eb4f62SJeeja KP iounmap(ctx->dsp->addr.lpe); 43692eb4f62SJeeja KP 43792eb4f62SJeeja KP ctx->dsp->ops->free(ctx->dsp); 43892eb4f62SJeeja KP } 43992eb4f62SJeeja KP EXPORT_SYMBOL_GPL(bxt_sst_dsp_cleanup); 44092eb4f62SJeeja KP 44192eb4f62SJeeja KP MODULE_LICENSE("GPL v2"); 44292eb4f62SJeeja KP MODULE_DESCRIPTION("Intel Broxton IPC driver"); 443