root/sound/soc/sof/intel/hda-loader-skl.c
// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
//
// This file is provided under a dual BSD/GPLv2 license.  When using or
// redistributing this file, you may do so under either license.
//
// Copyright(c) 2018-2022 Intel Corporation
//

#include <linux/delay.h>
#include <linux/device.h>
#include <linux/dma-mapping.h>
#include <linux/firmware.h>
#include <linux/fs.h>
#include <linux/interrupt.h>
#include <linux/mm.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/slab.h>
#include <sound/hdaudio_ext.h>
#include <sound/sof.h>
#include <sound/pcm_params.h>

#include "../sof-priv.h"
#include "../ops.h"
#include "hda.h"

#define HDA_SKL_WAIT_TIMEOUT            500     /* 500 msec */
#define HDA_SKL_CLDMA_MAX_BUFFER_SIZE   (32 * PAGE_SIZE)

/* Stream Reset */
#define HDA_CL_SD_CTL_SRST_SHIFT        0
#define HDA_CL_SD_CTL_SRST(x)           (((x) & 0x1) << \
                                        HDA_CL_SD_CTL_SRST_SHIFT)

/* Stream Run */
#define HDA_CL_SD_CTL_RUN_SHIFT         1
#define HDA_CL_SD_CTL_RUN(x)            (((x) & 0x1) << \
                                        HDA_CL_SD_CTL_RUN_SHIFT)

/* Interrupt On Completion Enable */
#define HDA_CL_SD_CTL_IOCE_SHIFT        2
#define HDA_CL_SD_CTL_IOCE(x)           (((x) & 0x1) << \
                                        HDA_CL_SD_CTL_IOCE_SHIFT)

/* FIFO Error Interrupt Enable */
#define HDA_CL_SD_CTL_FEIE_SHIFT        3
#define HDA_CL_SD_CTL_FEIE(x)           (((x) & 0x1) << \
                                        HDA_CL_SD_CTL_FEIE_SHIFT)

/* Descriptor Error Interrupt Enable */
#define HDA_CL_SD_CTL_DEIE_SHIFT        4
#define HDA_CL_SD_CTL_DEIE(x)           (((x) & 0x1) << \
                                        HDA_CL_SD_CTL_DEIE_SHIFT)

/* FIFO Limit Change */
#define HDA_CL_SD_CTL_FIFOLC_SHIFT      5
#define HDA_CL_SD_CTL_FIFOLC(x)         (((x) & 0x1) << \
                                        HDA_CL_SD_CTL_FIFOLC_SHIFT)

/* Stripe Control */
#define HDA_CL_SD_CTL_STRIPE_SHIFT      16
#define HDA_CL_SD_CTL_STRIPE(x)         (((x) & 0x3) << \
                                        HDA_CL_SD_CTL_STRIPE_SHIFT)

/* Traffic Priority */
#define HDA_CL_SD_CTL_TP_SHIFT          18
#define HDA_CL_SD_CTL_TP(x)             (((x) & 0x1) << \
                                        HDA_CL_SD_CTL_TP_SHIFT)

/* Bidirectional Direction Control */
#define HDA_CL_SD_CTL_DIR_SHIFT         19
#define HDA_CL_SD_CTL_DIR(x)            (((x) & 0x1) << \
                                        HDA_CL_SD_CTL_DIR_SHIFT)

/* Stream Number */
#define HDA_CL_SD_CTL_STRM_SHIFT        20
#define HDA_CL_SD_CTL_STRM(x)           (((x) & 0xf) << \
                                        HDA_CL_SD_CTL_STRM_SHIFT)

#define HDA_CL_SD_CTL_INT(x)    \
                (HDA_CL_SD_CTL_IOCE(x) | \
                HDA_CL_SD_CTL_FEIE(x) | \
                HDA_CL_SD_CTL_DEIE(x))

#define HDA_CL_SD_CTL_INT_MASK  \
                (HDA_CL_SD_CTL_IOCE(1) | \
                HDA_CL_SD_CTL_FEIE(1) | \
                HDA_CL_SD_CTL_DEIE(1))

#define DMA_ADDRESS_128_BITS_ALIGNMENT  7
#define BDL_ALIGN(x)                    ((x) >> DMA_ADDRESS_128_BITS_ALIGNMENT)

/* Buffer Descriptor List Lower Base Address */
#define HDA_CL_SD_BDLPLBA_SHIFT         7
#define HDA_CL_SD_BDLPLBA_MASK          GENMASK(31, 7)
#define HDA_CL_SD_BDLPLBA(x)            \
        ((BDL_ALIGN(lower_32_bits(x)) << HDA_CL_SD_BDLPLBA_SHIFT) & \
         HDA_CL_SD_BDLPLBA_MASK)

/* Buffer Descriptor List Upper Base Address */
#define HDA_CL_SD_BDLPUBA(x)            \
                        (upper_32_bits(x))

/* Software Position in Buffer Enable */
#define HDA_CL_SPBFIFO_SPBFCCTL_SPIBE_SHIFT     0
#define HDA_CL_SPBFIFO_SPBFCCTL_SPIBE_MASK      \
                        (1 << HDA_CL_SPBFIFO_SPBFCCTL_SPIBE_SHIFT)

#define HDA_CL_SPBFIFO_SPBFCCTL_SPIBE(x)        \
                        (((x) << HDA_CL_SPBFIFO_SPBFCCTL_SPIBE_SHIFT) & \
                         HDA_CL_SPBFIFO_SPBFCCTL_SPIBE_MASK)

#define HDA_CL_DMA_SD_INT_COMPLETE              0x4

static int cl_skl_cldma_setup_bdle(struct snd_sof_dev *sdev,
                                   struct snd_dma_buffer *dmab_data,
                                   __le32 **bdlp, int size, int with_ioc)
{
        phys_addr_t addr = virt_to_phys(dmab_data->area);
        __le32 *bdl = *bdlp;

        /*
         * This code is simplified by using one fragment of physical memory and assuming
         * all the code fits. This could be improved with scatter-gather but the firmware
         * size is limited by DSP memory anyways
         */
        bdl[0] = cpu_to_le32(lower_32_bits(addr));
        bdl[1] = cpu_to_le32(upper_32_bits(addr));
        bdl[2] = cpu_to_le32(size);
        bdl[3] = (!with_ioc) ? 0 : cpu_to_le32(0x01);

        return 1; /* one fragment */
}

static void cl_skl_cldma_stream_run(struct snd_sof_dev *sdev, bool enable)
{
        int sd_offset = SOF_HDA_ADSP_LOADER_BASE;
        unsigned char val;
        int retries;
        u32 run = enable ? 0x1 : 0;

        snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR,
                                sd_offset + SOF_HDA_ADSP_REG_SD_CTL,
                                HDA_CL_SD_CTL_RUN(1), HDA_CL_SD_CTL_RUN(run));

        retries = 300;
        do {
                udelay(3);

                /* waiting for hardware to report the stream Run bit set */
                val = snd_sof_dsp_read(sdev, HDA_DSP_BAR,
                                       sd_offset + SOF_HDA_ADSP_REG_SD_CTL);
                val &= HDA_CL_SD_CTL_RUN(1);
                if (enable && val)
                        break;
                else if (!enable && !val)
                        break;
        } while (--retries);

        if (retries == 0)
                dev_err(sdev->dev, "%s: failed to set Run bit=%d enable=%d\n",
                        __func__, val, enable);
}

static void cl_skl_cldma_stream_clear(struct snd_sof_dev *sdev)
{
        int sd_offset = SOF_HDA_ADSP_LOADER_BASE;

        /* make sure Run bit is cleared before setting stream register */
        cl_skl_cldma_stream_run(sdev, 0);

        /* Disable the Interrupt On Completion, FIFO Error Interrupt,
         * Descriptor Error Interrupt and set the cldma stream number to 0.
         */
        snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR,
                                sd_offset + SOF_HDA_ADSP_REG_SD_CTL,
                                HDA_CL_SD_CTL_INT_MASK, HDA_CL_SD_CTL_INT(0));
        snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR,
                                sd_offset + SOF_HDA_ADSP_REG_SD_CTL,
                                HDA_CL_SD_CTL_STRM(0xf), HDA_CL_SD_CTL_STRM(0));

        snd_sof_dsp_write(sdev, HDA_DSP_BAR,
                          sd_offset + SOF_HDA_ADSP_REG_SD_BDLPL, HDA_CL_SD_BDLPLBA(0));
        snd_sof_dsp_write(sdev, HDA_DSP_BAR,
                          sd_offset + SOF_HDA_ADSP_REG_SD_BDLPU, 0);

        /* Set the Cyclic Buffer Length to 0. */
        snd_sof_dsp_write(sdev, HDA_DSP_BAR,
                          sd_offset + SOF_HDA_ADSP_REG_SD_CBL, 0);
        /* Set the Last Valid Index. */
        snd_sof_dsp_write(sdev, HDA_DSP_BAR,
                          sd_offset + SOF_HDA_ADSP_REG_SD_LVI, 0);
}

static void cl_skl_cldma_setup_spb(struct snd_sof_dev *sdev,
                                   unsigned int size, bool enable)
{
        int sd_offset = SOF_DSP_REG_CL_SPBFIFO;

        if (enable)
                snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR,
                                        sd_offset + SOF_HDA_ADSP_REG_CL_SPBFIFO_SPBFCCTL,
                                        HDA_CL_SPBFIFO_SPBFCCTL_SPIBE_MASK,
                                        HDA_CL_SPBFIFO_SPBFCCTL_SPIBE(1));

        snd_sof_dsp_write(sdev, HDA_DSP_BAR,
                          sd_offset + SOF_HDA_ADSP_REG_CL_SPBFIFO_SPIB, size);
}

static void cl_skl_cldma_set_intr(struct snd_sof_dev *sdev, bool enable)
{
        u32 val = enable ? HDA_DSP_ADSPIC_CL_DMA : 0;

        snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, HDA_DSP_REG_ADSPIC,
                                HDA_DSP_ADSPIC_CL_DMA, val);
}

static void cl_skl_cldma_cleanup_spb(struct snd_sof_dev *sdev)
{
        int sd_offset = SOF_DSP_REG_CL_SPBFIFO;

        snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR,
                                sd_offset + SOF_HDA_ADSP_REG_CL_SPBFIFO_SPBFCCTL,
                                HDA_CL_SPBFIFO_SPBFCCTL_SPIBE_MASK,
                                HDA_CL_SPBFIFO_SPBFCCTL_SPIBE(0));

        snd_sof_dsp_write(sdev, HDA_DSP_BAR,
                          sd_offset + SOF_HDA_ADSP_REG_CL_SPBFIFO_SPIB, 0);
}

static void cl_skl_cldma_setup_controller(struct snd_sof_dev *sdev,
                                          struct snd_dma_buffer *dmab_bdl,
                                          unsigned int max_size, u32 count)
{
        int sd_offset = SOF_HDA_ADSP_LOADER_BASE;

        /* Clear the stream first and then set it. */
        cl_skl_cldma_stream_clear(sdev);

        /* setting the stream register */
        snd_sof_dsp_write(sdev, HDA_DSP_BAR,
                          sd_offset + SOF_HDA_ADSP_REG_SD_BDLPL,
                          HDA_CL_SD_BDLPLBA(dmab_bdl->addr));
        snd_sof_dsp_write(sdev, HDA_DSP_BAR,
                          sd_offset + SOF_HDA_ADSP_REG_SD_BDLPU,
                          HDA_CL_SD_BDLPUBA(dmab_bdl->addr));

        /* Set the Cyclic Buffer Length. */
        snd_sof_dsp_write(sdev, HDA_DSP_BAR,
                          sd_offset + SOF_HDA_ADSP_REG_SD_CBL, max_size);
        /* Set the Last Valid Index. */
        snd_sof_dsp_write(sdev, HDA_DSP_BAR,
                          sd_offset + SOF_HDA_ADSP_REG_SD_LVI, count - 1);

        /* Set the Interrupt On Completion, FIFO Error Interrupt,
         * Descriptor Error Interrupt and the cldma stream number.
         */
        snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR,
                                sd_offset + SOF_HDA_ADSP_REG_SD_CTL,
                                HDA_CL_SD_CTL_INT_MASK, HDA_CL_SD_CTL_INT(1));
        snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR,
                                sd_offset + SOF_HDA_ADSP_REG_SD_CTL,
                                HDA_CL_SD_CTL_STRM(0xf),
                                HDA_CL_SD_CTL_STRM(1));
}

static int cl_stream_prepare_skl(struct snd_sof_dev *sdev,
                                 struct snd_dma_buffer *dmab,
                                 struct snd_dma_buffer *dmab_bdl)

{
        unsigned int bufsize = HDA_SKL_CLDMA_MAX_BUFFER_SIZE;
        __le32 *bdl;
        int frags;
        int ret;

        ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, sdev->dev, bufsize, dmab);
        if (ret < 0) {
                dev_err(sdev->dev, "%s: failed to alloc fw buffer: %x\n", __func__, ret);
                return ret;
        }

        ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, sdev->dev, bufsize, dmab_bdl);
        if (ret < 0) {
                dev_err(sdev->dev, "%s: failed to alloc blde: %x\n", __func__, ret);
                snd_dma_free_pages(dmab);
                return ret;
        }

        bdl = (__le32 *)dmab_bdl->area;
        frags = cl_skl_cldma_setup_bdle(sdev, dmab, &bdl, bufsize, 1);
        cl_skl_cldma_setup_controller(sdev, dmab_bdl, bufsize, frags);

        return ret;
}

static void cl_cleanup_skl(struct snd_sof_dev *sdev,
                           struct snd_dma_buffer *dmab,
                           struct snd_dma_buffer *dmab_bdl)
{
        cl_skl_cldma_cleanup_spb(sdev);
        cl_skl_cldma_stream_clear(sdev);
        snd_dma_free_pages(dmab);
        snd_dma_free_pages(dmab_bdl);
}

static int cl_dsp_init_skl(struct snd_sof_dev *sdev,
                           struct snd_dma_buffer *dmab,
                           struct snd_dma_buffer *dmab_bdl)
{
        struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata;
        const struct sof_intel_dsp_desc *chip = hda->desc;
        unsigned int status;
        u32 flags;
        int ret;

        /* check if the init_core is already enabled, if yes, reset and make it run,
         * if not, powerdown and enable it again.
         */
        if (hda_dsp_core_is_enabled(sdev, chip->init_core_mask)) {
                /* if enabled, reset it, and run the init_core. */
                ret = hda_dsp_core_stall_reset(sdev, chip->init_core_mask);
                if (ret < 0)
                        goto err;

                ret = hda_dsp_core_run(sdev, chip->init_core_mask);
                if (ret < 0) {
                        dev_err(sdev->dev, "%s: dsp core start failed %d\n", __func__, ret);
                        goto err;
                }
        } else {
                /* if not enabled, power down it first and then powerup and run
                 * the init_core.
                 */
                ret = hda_dsp_core_reset_power_down(sdev, chip->init_core_mask);
                if (ret < 0) {
                        dev_err(sdev->dev, "%s: dsp core0 disable fail: %d\n", __func__, ret);
                        goto err;
                }
                ret = hda_dsp_enable_core(sdev, chip->init_core_mask);
                if (ret < 0) {
                        dev_err(sdev->dev, "%s: dsp core0 enable fail: %d\n", __func__, ret);
                        goto err;
                }
        }

        /* prepare DMA for code loader stream */
        ret = cl_stream_prepare_skl(sdev, dmab, dmab_bdl);
        if (ret < 0) {
                dev_err(sdev->dev, "%s: dma prepare fw loading err: %x\n", __func__, ret);
                return ret;
        }

        /* enable the interrupt */
        snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, HDA_DSP_REG_ADSPIC,
                                HDA_DSP_ADSPIC_IPC, HDA_DSP_ADSPIC_IPC);

        /* enable IPC DONE interrupt */
        snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, chip->ipc_ctl,
                                HDA_DSP_REG_HIPCCTL_DONE,
                                HDA_DSP_REG_HIPCCTL_DONE);

        /* enable IPC BUSY interrupt */
        snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, chip->ipc_ctl,
                                HDA_DSP_REG_HIPCCTL_BUSY,
                                HDA_DSP_REG_HIPCCTL_BUSY);

        /* polling the ROM init status information. */
        ret = snd_sof_dsp_read_poll_timeout(sdev, HDA_DSP_BAR,
                                            chip->rom_status_reg, status,
                                            (FSR_TO_STATE_CODE(status)
                                             == FSR_STATE_INIT_DONE),
                                            HDA_DSP_REG_POLL_INTERVAL_US,
                                            chip->rom_init_timeout *
                                            USEC_PER_MSEC);
        if (ret < 0)
                goto err;

        return ret;

err:
        flags = SOF_DBG_DUMP_PCI | SOF_DBG_DUMP_MBOX;

        snd_sof_dsp_dbg_dump(sdev, "Boot failed\n", flags);
        cl_cleanup_skl(sdev, dmab, dmab_bdl);
        hda_dsp_core_reset_power_down(sdev, chip->init_core_mask);
        return ret;
}

static void cl_skl_cldma_fill_buffer(struct snd_sof_dev *sdev,
                                     struct snd_dma_buffer *dmab,
                                     unsigned int bufsize,
                                     unsigned int copysize,
                                     const void *curr_pos,
                                     bool intr_enable)
{
        struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata;

        /* copy the image into the buffer with the maximum buffer size. */
        unsigned int size = (bufsize == copysize) ? bufsize : copysize;

        memcpy(dmab->area, curr_pos, size);

        /* Set the wait condition for every load. */
        hda->code_loading = 1;

        /* Set the interrupt. */
        if (intr_enable)
                cl_skl_cldma_set_intr(sdev, true);

        /* Set the SPB. */
        cl_skl_cldma_setup_spb(sdev, size, true);

        /* Trigger the code loading stream. */
        cl_skl_cldma_stream_run(sdev, true);
}

static int cl_skl_cldma_wait_interruptible(struct snd_sof_dev *sdev,
                                           bool intr_wait)
{
        struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata;
        const struct sof_intel_dsp_desc *chip = hda->desc;
        int sd_offset = SOF_HDA_ADSP_LOADER_BASE;
        u8 cl_dma_intr_status;

        /*
         * Wait for CLDMA interrupt to inform the binary segment transfer is
         * complete.
         */
        if (!wait_event_timeout(hda->waitq, !hda->code_loading,
                                msecs_to_jiffies(HDA_SKL_WAIT_TIMEOUT))) {
                dev_err(sdev->dev, "cldma copy timeout\n");
                dev_err(sdev->dev, "ROM code=%#x: FW status=%#x\n",
                        snd_sof_dsp_read(sdev, HDA_DSP_BAR, HDA_DSP_SRAM_REG_ROM_ERROR),
                        snd_sof_dsp_read(sdev, HDA_DSP_BAR, chip->rom_status_reg));
                return -EIO;
        }

        /* now check DMA interrupt status */
        cl_dma_intr_status = snd_sof_dsp_read(sdev, HDA_DSP_BAR,
                                              sd_offset + SOF_HDA_ADSP_REG_SD_STS);

        if (!(cl_dma_intr_status & HDA_CL_DMA_SD_INT_COMPLETE)) {
                dev_err(sdev->dev, "cldma copy failed\n");
                return -EIO;
        }

        dev_dbg(sdev->dev, "cldma buffer copy complete\n");
        return 0;
}

static int
cl_skl_cldma_copy_to_buf(struct snd_sof_dev *sdev,
                         struct snd_dma_buffer *dmab,
                         const void *bin,
                         u32 total_size, u32 bufsize)
{
        unsigned int bytes_left = total_size;
        const void *curr_pos = bin;
        int ret;

        if (total_size <= 0)
                return -EINVAL;

        while (bytes_left > 0) {
                if (bytes_left > bufsize) {
                        dev_dbg(sdev->dev, "cldma copy %#x bytes\n", bufsize);

                        cl_skl_cldma_fill_buffer(sdev, dmab, bufsize, bufsize, curr_pos, true);

                        ret = cl_skl_cldma_wait_interruptible(sdev, false);
                        if (ret < 0) {
                                dev_err(sdev->dev, "%s: fw failed to load. %#x bytes remaining\n",
                                        __func__, bytes_left);
                                return ret;
                        }

                        bytes_left -= bufsize;
                        curr_pos += bufsize;
                } else {
                        dev_dbg(sdev->dev, "cldma copy %#x bytes\n", bytes_left);

                        cl_skl_cldma_set_intr(sdev, false);
                        cl_skl_cldma_fill_buffer(sdev, dmab, bufsize, bytes_left, curr_pos, false);
                        return 0;
                }
        }

        return bytes_left;
}

static int cl_copy_fw_skl(struct snd_sof_dev *sdev,
                          struct snd_dma_buffer *dmab)

{
        const struct firmware *fw =  sdev->basefw.fw;
        struct firmware stripped_firmware;
        unsigned int bufsize = HDA_SKL_CLDMA_MAX_BUFFER_SIZE;
        int ret;

        stripped_firmware.data = fw->data + sdev->basefw.payload_offset;
        stripped_firmware.size = fw->size - sdev->basefw.payload_offset;

        dev_dbg(sdev->dev, "firmware size: %#zx buffer size %#x\n", fw->size, bufsize);

        ret = cl_skl_cldma_copy_to_buf(sdev, dmab, stripped_firmware.data,
                                       stripped_firmware.size, bufsize);
        if (ret < 0)
                dev_err(sdev->dev, "%s: fw copy failed %d\n", __func__, ret);

        return ret;
}

int hda_dsp_cl_boot_firmware_skl(struct snd_sof_dev *sdev)
{
        struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata;
        const struct sof_intel_dsp_desc *chip = hda->desc;
        struct snd_dma_buffer dmab_bdl;
        struct snd_dma_buffer dmab;
        unsigned int reg;
        u32 flags;
        int ret;

        ret = cl_dsp_init_skl(sdev, &dmab, &dmab_bdl);

        /* retry enabling core and ROM load. seemed to help */
        if (ret < 0) {
                ret = cl_dsp_init_skl(sdev, &dmab, &dmab_bdl);
                if (ret < 0) {
                        dev_err(sdev->dev, "Error code=%#x: FW status=%#x\n",
                                snd_sof_dsp_read(sdev, HDA_DSP_BAR, HDA_DSP_SRAM_REG_ROM_ERROR),
                                snd_sof_dsp_read(sdev, HDA_DSP_BAR, chip->rom_status_reg));
                        dev_err(sdev->dev, "Core En/ROM load fail:%d\n", ret);
                        return ret;
                }
        }

        dev_dbg(sdev->dev, "ROM init successful\n");

        /* at this point DSP ROM has been initialized and should be ready for
         * code loading and firmware boot
         */
        ret = cl_copy_fw_skl(sdev, &dmab);
        if (ret < 0) {
                dev_err(sdev->dev, "%s: load firmware failed : %d\n", __func__, ret);
                goto err;
        }

        ret = snd_sof_dsp_read_poll_timeout(sdev, HDA_DSP_BAR,
                                            chip->rom_status_reg, reg,
                                            (FSR_TO_STATE_CODE(reg)
                                             == FSR_STATE_ROM_BASEFW_ENTERED),
                                            HDA_DSP_REG_POLL_INTERVAL_US,
                                            HDA_DSP_BASEFW_TIMEOUT_US);

        dev_dbg(sdev->dev, "Firmware download successful, booting...\n");

        cl_skl_cldma_stream_run(sdev, false);
        cl_cleanup_skl(sdev, &dmab, &dmab_bdl);

        if (!ret)
                return chip->init_core_mask;

        return ret;

err:
        flags = SOF_DBG_DUMP_PCI | SOF_DBG_DUMP_MBOX;

        snd_sof_dsp_dbg_dump(sdev, "Boot failed\n", flags);

        /* power down DSP */
        hda_dsp_core_reset_power_down(sdev, chip->init_core_mask);
        cl_skl_cldma_stream_run(sdev, false);
        cl_cleanup_skl(sdev, &dmab, &dmab_bdl);

        dev_err(sdev->dev, "%s: load fw failed err: %d\n", __func__, ret);
        return ret;
}