Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
0002 //
0003 // Copyright(c) 2022 Intel Corporation. All rights reserved.
0004 //
0005 // Authors: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
0006 //
0007 
0008 /*
0009  * Hardware interface for audio DSP on Meteorlake.
0010  */
0011 
0012 #include <linux/firmware.h>
0013 #include <sound/sof/ipc4/header.h>
0014 #include "../ipc4-priv.h"
0015 #include "../ops.h"
0016 #include "hda.h"
0017 #include "hda-ipc.h"
0018 #include "../sof-audio.h"
0019 #include "mtl.h"
0020 
0021 static const struct snd_sof_debugfs_map mtl_dsp_debugfs[] = {
0022     {"hda", HDA_DSP_HDA_BAR, 0, 0x4000, SOF_DEBUGFS_ACCESS_ALWAYS},
0023     {"pp", HDA_DSP_PP_BAR,  0, 0x1000, SOF_DEBUGFS_ACCESS_ALWAYS},
0024     {"dsp", HDA_DSP_BAR,  0, 0x10000, SOF_DEBUGFS_ACCESS_ALWAYS},
0025 };
0026 
0027 static void mtl_ipc_host_done(struct snd_sof_dev *sdev)
0028 {
0029     /*
0030      * clear busy interrupt to tell dsp controller this interrupt has been accepted,
0031      * not trigger it again
0032      */
0033     snd_sof_dsp_update_bits_forced(sdev, HDA_DSP_BAR, MTL_DSP_REG_HFIPCXTDR,
0034                        MTL_DSP_REG_HFIPCXTDR_BUSY, MTL_DSP_REG_HFIPCXTDR_BUSY);
0035     /*
0036      * clear busy bit to ack dsp the msg has been processed and send reply msg to dsp
0037      */
0038     snd_sof_dsp_update_bits_forced(sdev, HDA_DSP_BAR, MTL_DSP_REG_HFIPCXTDA,
0039                        MTL_DSP_REG_HFIPCXTDA_BUSY, 0);
0040 }
0041 
0042 static void mtl_ipc_dsp_done(struct snd_sof_dev *sdev)
0043 {
0044     /*
0045      * set DONE bit - tell DSP we have received the reply msg from DSP, and processed it,
0046      * don't send more reply to host
0047      */
0048     snd_sof_dsp_update_bits_forced(sdev, HDA_DSP_BAR, MTL_DSP_REG_HFIPCXIDA,
0049                        MTL_DSP_REG_HFIPCXIDA_DONE, MTL_DSP_REG_HFIPCXIDA_DONE);
0050 
0051     /* unmask Done interrupt */
0052     snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, MTL_DSP_REG_HFIPCXCTL,
0053                 MTL_DSP_REG_HFIPCXCTL_DONE, MTL_DSP_REG_HFIPCXCTL_DONE);
0054 }
0055 
0056 /* Check if an IPC IRQ occurred */
0057 static bool mtl_dsp_check_ipc_irq(struct snd_sof_dev *sdev)
0058 {
0059     u32 irq_status;
0060     u32 hfintipptr;
0061 
0062     /* read Interrupt IP Pointer */
0063     hfintipptr = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_HFINTIPPTR) & MTL_HFINTIPPTR_PTR_MASK;
0064     irq_status = snd_sof_dsp_read(sdev, HDA_DSP_BAR, hfintipptr + MTL_DSP_IRQSTS);
0065 
0066     dev_vdbg(sdev->dev, "irq handler: irq_status:0x%x\n", irq_status);
0067 
0068     if (irq_status != U32_MAX && (irq_status & MTL_DSP_IRQSTS_IPC))
0069         return true;
0070 
0071     return false;
0072 }
0073 
0074 /* Check if an SDW IRQ occurred */
0075 static bool mtl_dsp_check_sdw_irq(struct snd_sof_dev *sdev)
0076 {
0077     u32 irq_status;
0078     u32 hfintipptr;
0079 
0080     /* read Interrupt IP Pointer */
0081     hfintipptr = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_HFINTIPPTR) & MTL_HFINTIPPTR_PTR_MASK;
0082     irq_status = snd_sof_dsp_read(sdev, HDA_DSP_BAR, hfintipptr + MTL_DSP_IRQSTS);
0083 
0084     if (irq_status != U32_MAX && (irq_status & MTL_DSP_IRQSTS_SDW))
0085         return true;
0086 
0087     return false;
0088 }
0089 
0090 static int mtl_ipc_send_msg(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg)
0091 {
0092     struct sof_ipc4_msg *msg_data = msg->msg_data;
0093 
0094     /* send the message via mailbox */
0095     if (msg_data->data_size)
0096         sof_mailbox_write(sdev, sdev->host_box.offset, msg_data->data_ptr,
0097                   msg_data->data_size);
0098 
0099     snd_sof_dsp_write(sdev, HDA_DSP_BAR, MTL_DSP_REG_HFIPCXIDDY,
0100               msg_data->extension);
0101     snd_sof_dsp_write(sdev, HDA_DSP_BAR, MTL_DSP_REG_HFIPCXIDR,
0102               msg_data->primary | MTL_DSP_REG_HFIPCXIDR_BUSY);
0103 
0104     return 0;
0105 }
0106 
0107 static void mtl_enable_ipc_interrupts(struct snd_sof_dev *sdev)
0108 {
0109     struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata;
0110     const struct sof_intel_dsp_desc *chip = hda->desc;
0111 
0112     /* enable IPC DONE and BUSY interrupts */
0113     snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, chip->ipc_ctl,
0114                 MTL_DSP_REG_HFIPCXCTL_BUSY | MTL_DSP_REG_HFIPCXCTL_DONE,
0115                 MTL_DSP_REG_HFIPCXCTL_BUSY | MTL_DSP_REG_HFIPCXCTL_DONE);
0116 }
0117 
0118 static void mtl_disable_ipc_interrupts(struct snd_sof_dev *sdev)
0119 {
0120     struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata;
0121     const struct sof_intel_dsp_desc *chip = hda->desc;
0122 
0123     /* disable IPC DONE and BUSY interrupts */
0124     snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, chip->ipc_ctl,
0125                 MTL_DSP_REG_HFIPCXCTL_BUSY | MTL_DSP_REG_HFIPCXCTL_DONE, 0);
0126 }
0127 
0128 static int mtl_enable_interrupts(struct snd_sof_dev *sdev)
0129 {
0130     u32 hfintipptr;
0131     u32 irqinten;
0132     u32 host_ipc;
0133     u32 hipcie;
0134     int ret;
0135 
0136     /* read Interrupt IP Pointer */
0137     hfintipptr = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_HFINTIPPTR) & MTL_HFINTIPPTR_PTR_MASK;
0138 
0139     /* Enable Host IPC and SOUNDWIRE */
0140     snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, hfintipptr,
0141                 MTL_IRQ_INTEN_L_HOST_IPC_MASK | MTL_IRQ_INTEN_L_SOUNDWIRE_MASK,
0142                 MTL_IRQ_INTEN_L_HOST_IPC_MASK | MTL_IRQ_INTEN_L_SOUNDWIRE_MASK);
0143 
0144     /* check if operation was successful */
0145     host_ipc = MTL_IRQ_INTEN_L_HOST_IPC_MASK | MTL_IRQ_INTEN_L_SOUNDWIRE_MASK;
0146     irqinten = snd_sof_dsp_read(sdev, HDA_DSP_BAR, hfintipptr);
0147     ret = snd_sof_dsp_read_poll_timeout(sdev, HDA_DSP_BAR, hfintipptr, irqinten,
0148                         (irqinten & host_ipc) == host_ipc,
0149                         HDA_DSP_REG_POLL_INTERVAL_US, HDA_DSP_RESET_TIMEOUT_US);
0150     if (ret < 0) {
0151         dev_err(sdev->dev, "failed to enable Host IPC and/or SOUNDWIRE\n");
0152         return ret;
0153     }
0154 
0155     /* Set Host IPC interrupt enable */
0156     snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, MTL_DSP_REG_HfHIPCIE,
0157                 MTL_DSP_REG_HfHIPCIE_IE_MASK, MTL_DSP_REG_HfHIPCIE_IE_MASK);
0158 
0159     /* check if operation was successful */
0160     host_ipc = MTL_DSP_REG_HfHIPCIE_IE_MASK;
0161     hipcie = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_DSP_REG_HfHIPCIE);
0162     ret = snd_sof_dsp_read_poll_timeout(sdev, HDA_DSP_BAR, MTL_DSP_REG_HfHIPCIE, hipcie,
0163                         (hipcie & host_ipc) == host_ipc,
0164                         HDA_DSP_REG_POLL_INTERVAL_US, HDA_DSP_RESET_TIMEOUT_US);
0165     if (ret < 0) {
0166         dev_err(sdev->dev, "failed to set Host IPC interrupt enable\n");
0167         return ret;
0168     }
0169 
0170     snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, MTL_DSP_REG_HfSNDWIE,
0171                 MTL_DSP_REG_HfSNDWIE_IE_MASK, MTL_DSP_REG_HfSNDWIE_IE_MASK);
0172     host_ipc = MTL_DSP_REG_HfSNDWIE_IE_MASK;
0173     hipcie = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_DSP_REG_HfSNDWIE);
0174     ret = snd_sof_dsp_read_poll_timeout(sdev, HDA_DSP_BAR, MTL_DSP_REG_HfSNDWIE, hipcie,
0175                         (hipcie & host_ipc) == host_ipc,
0176                         HDA_DSP_REG_POLL_INTERVAL_US, HDA_DSP_RESET_TIMEOUT_US);
0177     if (ret < 0)
0178         dev_err(sdev->dev, "failed to set SoundWire IPC interrupt enable\n");
0179 
0180     return ret;
0181 }
0182 
0183 static int mtl_disable_interrupts(struct snd_sof_dev *sdev)
0184 {
0185     u32 hfintipptr;
0186     u32 irqinten;
0187     u32 host_ipc;
0188     u32 hipcie;
0189     int ret1;
0190     int ret;
0191 
0192     /* read Interrupt IP Pointer */
0193     hfintipptr = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_HFINTIPPTR) & MTL_HFINTIPPTR_PTR_MASK;
0194 
0195     /* Disable Host IPC and SOUNDWIRE */
0196     snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, hfintipptr,
0197                 MTL_IRQ_INTEN_L_HOST_IPC_MASK | MTL_IRQ_INTEN_L_SOUNDWIRE_MASK, 0);
0198 
0199     /* check if operation was successful */
0200     host_ipc = MTL_IRQ_INTEN_L_HOST_IPC_MASK | MTL_IRQ_INTEN_L_SOUNDWIRE_MASK;
0201     irqinten = snd_sof_dsp_read(sdev, HDA_DSP_BAR, hfintipptr);
0202     ret = snd_sof_dsp_read_poll_timeout(sdev, HDA_DSP_BAR, hfintipptr, irqinten,
0203                         (irqinten & host_ipc) == 0,
0204                         HDA_DSP_REG_POLL_INTERVAL_US, HDA_DSP_RESET_TIMEOUT_US);
0205     /* Continue to disable other interrupts when error happens */
0206     if (ret < 0)
0207         dev_err(sdev->dev, "failed to disable Host IPC and SoundWire\n");
0208 
0209     /* Set Host IPC interrupt disable */
0210     snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, MTL_DSP_REG_HfHIPCIE,
0211                 MTL_DSP_REG_HfHIPCIE_IE_MASK, 0);
0212 
0213     /* check if operation was successful */
0214     host_ipc = MTL_DSP_REG_HfHIPCIE_IE_MASK;
0215     hipcie = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_DSP_REG_HfHIPCIE);
0216     ret1 = snd_sof_dsp_read_poll_timeout(sdev, HDA_DSP_BAR, MTL_DSP_REG_HfHIPCIE, hipcie,
0217                          (hipcie & host_ipc) == 0,
0218                          HDA_DSP_REG_POLL_INTERVAL_US,
0219                          HDA_DSP_RESET_TIMEOUT_US);
0220     if (ret1 < 0) {
0221         dev_err(sdev->dev, "failed to set Host IPC interrupt disable\n");
0222         if (!ret)
0223             ret = ret1;
0224     }
0225 
0226     /* Set SoundWire IPC interrupt disable */
0227     snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, MTL_DSP_REG_HfSNDWIE,
0228                 MTL_DSP_REG_HfSNDWIE_IE_MASK, 0);
0229     host_ipc = MTL_DSP_REG_HfSNDWIE_IE_MASK;
0230     hipcie = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_DSP_REG_HfSNDWIE);
0231     ret1 = snd_sof_dsp_read_poll_timeout(sdev, HDA_DSP_BAR, MTL_DSP_REG_HfSNDWIE, hipcie,
0232                          (hipcie & host_ipc) == 0,
0233                          HDA_DSP_REG_POLL_INTERVAL_US,
0234                          HDA_DSP_RESET_TIMEOUT_US);
0235     if (ret1 < 0) {
0236         dev_err(sdev->dev, "failed to set SoundWire IPC interrupt disable\n");
0237         if (!ret)
0238             ret = ret1;
0239     }
0240 
0241     return ret;
0242 }
0243 
0244 /* pre fw run operations */
0245 static int mtl_dsp_pre_fw_run(struct snd_sof_dev *sdev)
0246 {
0247     u32 dsphfpwrsts;
0248     u32 dsphfdsscs;
0249     u32 cpa;
0250     u32 pgs;
0251     int ret;
0252 
0253     /* Set the DSP subsystem power on */
0254     snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, MTL_HFDSSCS,
0255                 MTL_HFDSSCS_SPA_MASK, MTL_HFDSSCS_SPA_MASK);
0256 
0257     /* Wait for unstable CPA read (1 then 0 then 1) just after setting SPA bit */
0258     usleep_range(1000, 1010);
0259 
0260     /* poll with timeout to check if operation successful */
0261     cpa = MTL_HFDSSCS_CPA_MASK;
0262     dsphfdsscs = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_HFDSSCS);
0263     ret = snd_sof_dsp_read_poll_timeout(sdev, HDA_DSP_BAR, MTL_HFDSSCS, dsphfdsscs,
0264                         (dsphfdsscs & cpa) == cpa, HDA_DSP_REG_POLL_INTERVAL_US,
0265                         HDA_DSP_RESET_TIMEOUT_US);
0266     if (ret < 0) {
0267         dev_err(sdev->dev, "failed to enable DSP subsystem\n");
0268         return ret;
0269     }
0270 
0271     /* Power up gated-DSP-0 domain in order to access the DSP shim register block. */
0272     snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, MTL_HFPWRCTL,
0273                 MTL_HFPWRCTL_WPDSPHPXPG, MTL_HFPWRCTL_WPDSPHPXPG);
0274 
0275     usleep_range(1000, 1010);
0276 
0277     /* poll with timeout to check if operation successful */
0278     pgs = MTL_HFPWRSTS_DSPHPXPGS_MASK;
0279     dsphfpwrsts = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_HFPWRSTS);
0280     ret = snd_sof_dsp_read_poll_timeout(sdev, HDA_DSP_BAR, MTL_HFPWRSTS, dsphfpwrsts,
0281                         (dsphfpwrsts & pgs) == pgs,
0282                         HDA_DSP_REG_POLL_INTERVAL_US,
0283                         HDA_DSP_RESET_TIMEOUT_US);
0284     if (ret < 0)
0285         dev_err(sdev->dev, "failed to power up gated DSP domain\n");
0286 
0287     /* make sure SoundWire is not power-gated */
0288     snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, MTL_HFPWRCTL,
0289                 MTL_HfPWRCTL_WPIOXPG(1), MTL_HfPWRCTL_WPIOXPG(1));
0290     return ret;
0291 }
0292 
0293 static int mtl_dsp_post_fw_run(struct snd_sof_dev *sdev)
0294 {
0295     int ret;
0296 
0297     if (sdev->first_boot) {
0298         struct sof_intel_hda_dev *hdev = sdev->pdata->hw_pdata;
0299 
0300         ret = hda_sdw_startup(sdev);
0301         if (ret < 0) {
0302             dev_err(sdev->dev, "could not startup SoundWire links\n");
0303             return ret;
0304         }
0305 
0306         /* Check if IMR boot is usable */
0307         if (!sof_debug_check_flag(SOF_DBG_IGNORE_D3_PERSISTENT))
0308             hdev->imrboot_supported = true;
0309     }
0310 
0311     hda_sdw_int_enable(sdev, true);
0312     return 0;
0313 }
0314 
0315 static void mtl_dsp_dump(struct snd_sof_dev *sdev, u32 flags)
0316 {
0317     char *level = (flags & SOF_DBG_DUMP_OPTIONAL) ? KERN_DEBUG : KERN_ERR;
0318     u32 romdbgsts;
0319     u32 romdbgerr;
0320     u32 fwsts;
0321     u32 fwlec;
0322 
0323     fwsts = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_DSP_ROM_STS);
0324     fwlec = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_DSP_ROM_ERROR);
0325     romdbgsts = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_DSP_REG_HFFLGPXQWY);
0326     romdbgerr = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_DSP_REG_HFFLGPXQWY_ERROR);
0327 
0328     dev_err(sdev->dev, "ROM status: %#x, ROM error: %#x\n", fwsts, fwlec);
0329     dev_err(sdev->dev, "ROM debug status: %#x, ROM debug error: %#x\n", romdbgsts,
0330         romdbgerr);
0331     romdbgsts = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_DSP_REG_HFFLGPXQWY + 0x8 * 3);
0332     dev_printk(level, sdev->dev, "ROM feature bit%s enabled\n",
0333            romdbgsts & BIT(24) ? "" : " not");
0334 }
0335 
0336 static bool mtl_dsp_primary_core_is_enabled(struct snd_sof_dev *sdev)
0337 {
0338     int val;
0339 
0340     val = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_DSP2CXCTL_PRIMARY_CORE);
0341     if (val != U32_MAX && val & MTL_DSP2CXCTL_PRIMARY_CORE_CPA_MASK)
0342         return true;
0343 
0344     return false;
0345 }
0346 
0347 static int mtl_dsp_core_power_up(struct snd_sof_dev *sdev, int core)
0348 {
0349     unsigned int cpa;
0350     u32 dspcxctl;
0351     int ret;
0352 
0353     /* Only the primary core can be powered up by the host */
0354     if (core != SOF_DSP_PRIMARY_CORE || mtl_dsp_primary_core_is_enabled(sdev))
0355         return 0;
0356 
0357     /* Program the owner of the IP & shim registers (10: Host CPU) */
0358     snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, MTL_DSP2CXCTL_PRIMARY_CORE,
0359                 MTL_DSP2CXCTL_PRIMARY_CORE_OSEL,
0360                 0x2 << MTL_DSP2CXCTL_PRIMARY_CORE_OSEL_SHIFT);
0361 
0362     /* enable SPA bit */
0363     snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, MTL_DSP2CXCTL_PRIMARY_CORE,
0364                 MTL_DSP2CXCTL_PRIMARY_CORE_SPA_MASK,
0365                 MTL_DSP2CXCTL_PRIMARY_CORE_SPA_MASK);
0366 
0367     /* Wait for unstable CPA read (1 then 0 then 1) just after setting SPA bit */
0368     usleep_range(1000, 1010);
0369 
0370     /* poll with timeout to check if operation successful */
0371     cpa = MTL_DSP2CXCTL_PRIMARY_CORE_CPA_MASK;
0372     ret = snd_sof_dsp_read_poll_timeout(sdev, HDA_DSP_BAR, MTL_DSP2CXCTL_PRIMARY_CORE, dspcxctl,
0373                         (dspcxctl & cpa) == cpa, HDA_DSP_REG_POLL_INTERVAL_US,
0374                         HDA_DSP_RESET_TIMEOUT_US);
0375     if (ret < 0)
0376         dev_err(sdev->dev, "%s: timeout on MTL_DSP2CXCTL_PRIMARY_CORE read\n",
0377             __func__);
0378 
0379     return ret;
0380 }
0381 
0382 static int mtl_dsp_core_power_down(struct snd_sof_dev *sdev, int core)
0383 {
0384     u32 dspcxctl;
0385     int ret;
0386 
0387     /* Only the primary core can be powered down by the host */
0388     if (core != SOF_DSP_PRIMARY_CORE || !mtl_dsp_primary_core_is_enabled(sdev))
0389         return 0;
0390 
0391     /* disable SPA bit */
0392     snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, MTL_DSP2CXCTL_PRIMARY_CORE,
0393                 MTL_DSP2CXCTL_PRIMARY_CORE_SPA_MASK, 0);
0394 
0395     /* Wait for unstable CPA read (1 then 0 then 1) just after setting SPA bit */
0396     usleep_range(1000, 1010);
0397 
0398     ret = snd_sof_dsp_read_poll_timeout(sdev, HDA_DSP_BAR, MTL_DSP2CXCTL_PRIMARY_CORE, dspcxctl,
0399                         !(dspcxctl & MTL_DSP2CXCTL_PRIMARY_CORE_CPA_MASK),
0400                         HDA_DSP_REG_POLL_INTERVAL_US,
0401                         HDA_DSP_PD_TIMEOUT * USEC_PER_MSEC);
0402     if (ret < 0)
0403         dev_err(sdev->dev, "failed to power down primary core\n");
0404 
0405     return ret;
0406 }
0407 
0408 static int mtl_dsp_cl_init(struct snd_sof_dev *sdev, int stream_tag, bool imr_boot)
0409 {
0410     struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata;
0411     const struct sof_intel_dsp_desc *chip = hda->desc;
0412     unsigned int status;
0413     u32 ipc_hdr;
0414     int ret;
0415 
0416     /* step 1: purge FW request */
0417     ipc_hdr = chip->ipc_req_mask | HDA_DSP_ROM_IPC_CONTROL;
0418     if (!imr_boot)
0419         ipc_hdr |= HDA_DSP_ROM_IPC_PURGE_FW | ((stream_tag - 1) << 9);
0420 
0421     snd_sof_dsp_write(sdev, HDA_DSP_BAR, chip->ipc_req, ipc_hdr);
0422 
0423     /* step 2: power up primary core */
0424     ret = mtl_dsp_core_power_up(sdev, SOF_DSP_PRIMARY_CORE);
0425     if (ret < 0) {
0426         if (hda->boot_iteration == HDA_FW_BOOT_ATTEMPTS)
0427             dev_err(sdev->dev, "dsp core 0/1 power up failed\n");
0428         goto err;
0429     }
0430 
0431     dev_dbg(sdev->dev, "Primary core power up successful\n");
0432 
0433     /* step 3: wait for IPC DONE bit from ROM */
0434     ret = snd_sof_dsp_read_poll_timeout(sdev, HDA_DSP_BAR, chip->ipc_ack, status,
0435                         ((status & chip->ipc_ack_mask) == chip->ipc_ack_mask),
0436                         HDA_DSP_REG_POLL_INTERVAL_US, MTL_DSP_PURGE_TIMEOUT_US);
0437     if (ret < 0) {
0438         if (hda->boot_iteration == HDA_FW_BOOT_ATTEMPTS)
0439             dev_err(sdev->dev, "timeout waiting for purge IPC done\n");
0440         goto err;
0441     }
0442 
0443     /* set DONE bit to clear the reply IPC message */
0444     snd_sof_dsp_update_bits_forced(sdev, HDA_DSP_BAR, chip->ipc_ack, chip->ipc_ack_mask,
0445                        chip->ipc_ack_mask);
0446 
0447     /* step 4: enable interrupts */
0448     ret = mtl_enable_interrupts(sdev);
0449     if (ret < 0) {
0450         if (hda->boot_iteration == HDA_FW_BOOT_ATTEMPTS)
0451             dev_err(sdev->dev, "%s: failed to enable interrupts\n", __func__);
0452         goto err;
0453     }
0454 
0455     mtl_enable_ipc_interrupts(sdev);
0456 
0457     /*
0458      * ACE workaround: don't wait for ROM INIT.
0459      * The platform cannot catch ROM_INIT_DONE because of a very short
0460      * timing window. Follow the recommendations and skip this part.
0461      */
0462 
0463     return 0;
0464 
0465 err:
0466     snd_sof_dsp_dbg_dump(sdev, "MTL DSP init fail", 0);
0467     mtl_dsp_core_power_down(sdev, SOF_DSP_PRIMARY_CORE);
0468     return ret;
0469 }
0470 
0471 static irqreturn_t mtl_ipc_irq_thread(int irq, void *context)
0472 {
0473     struct sof_ipc4_msg notification_data = {{ 0 }};
0474     struct snd_sof_dev *sdev = context;
0475     bool ipc_irq = false;
0476     u32 hipcida;
0477     u32 hipctdr;
0478 
0479     hipcida = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_DSP_REG_HFIPCXIDA);
0480 
0481     /* reply message from DSP */
0482     if (hipcida & MTL_DSP_REG_HFIPCXIDA_DONE) {
0483         /* DSP received the message */
0484         snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, MTL_DSP_REG_HFIPCXCTL,
0485                     MTL_DSP_REG_HFIPCXCTL_DONE, 0);
0486 
0487         mtl_ipc_dsp_done(sdev);
0488 
0489         ipc_irq = true;
0490     }
0491 
0492     hipctdr = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_DSP_REG_HFIPCXTDR);
0493     if (hipctdr & MTL_DSP_REG_HFIPCXTDR_BUSY) {
0494         /* Message from DSP (reply or notification) */
0495         u32 extension = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_DSP_REG_HFIPCXTDDY);
0496         u32 primary = hipctdr & MTL_DSP_REG_HFIPCXTDR_MSG_MASK;
0497 
0498         /*
0499          * ACE fw sends a new fw ipc message to host to
0500          * notify the status of the last host ipc message
0501          */
0502         if (primary & SOF_IPC4_MSG_DIR_MASK) {
0503             /* Reply received */
0504             if (likely(sdev->fw_state == SOF_FW_BOOT_COMPLETE)) {
0505                 struct sof_ipc4_msg *data = sdev->ipc->msg.reply_data;
0506 
0507                 data->primary = primary;
0508                 data->extension = extension;
0509 
0510                 spin_lock_irq(&sdev->ipc_lock);
0511 
0512                 snd_sof_ipc_get_reply(sdev);
0513                 snd_sof_ipc_reply(sdev, data->primary);
0514 
0515                 spin_unlock_irq(&sdev->ipc_lock);
0516             } else {
0517                 dev_dbg_ratelimited(sdev->dev,
0518                             "IPC reply before FW_READY: %#x|%#x\n",
0519                             primary, extension);
0520             }
0521         } else {
0522             /* Notification received */
0523             notification_data.primary = primary;
0524             notification_data.extension = extension;
0525 
0526             sdev->ipc->msg.rx_data = &notification_data;
0527             snd_sof_ipc_msgs_rx(sdev);
0528             sdev->ipc->msg.rx_data = NULL;
0529         }
0530 
0531         mtl_ipc_host_done(sdev);
0532 
0533         ipc_irq = true;
0534     }
0535 
0536     if (!ipc_irq) {
0537         /* This interrupt is not shared so no need to return IRQ_NONE. */
0538         dev_dbg_ratelimited(sdev->dev, "nothing to do in IPC IRQ thread\n");
0539     }
0540 
0541     return IRQ_HANDLED;
0542 }
0543 
0544 static int mtl_dsp_ipc_get_mailbox_offset(struct snd_sof_dev *sdev)
0545 {
0546     return MTL_DSP_MBOX_UPLINK_OFFSET;
0547 }
0548 
0549 static int mtl_dsp_ipc_get_window_offset(struct snd_sof_dev *sdev, u32 id)
0550 {
0551     return MTL_SRAM_WINDOW_OFFSET(id);
0552 }
0553 
0554 static int mtl_suspend(struct snd_sof_dev *sdev, bool runtime_suspend)
0555 {
0556     struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata;
0557     const struct sof_intel_dsp_desc *chip = hda->desc;
0558 #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA)
0559     struct hdac_bus *bus = sof_to_bus(sdev);
0560 #endif
0561     u32 dsphfdsscs;
0562     u32 cpa;
0563     int ret;
0564     int i;
0565 
0566     mtl_disable_ipc_interrupts(sdev);
0567     ret = mtl_disable_interrupts(sdev);
0568     if (ret)
0569         return ret;
0570 
0571 #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA)
0572     hda_codec_jack_wake_enable(sdev, runtime_suspend);
0573     /* power down all hda link */
0574     snd_hdac_ext_bus_link_power_down_all(bus);
0575 #endif
0576     snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, MTL_HFPWRCTL,
0577                 MTL_HFPWRCTL_WPDSPHPXPG, 0);
0578 
0579     /* Set the DSP subsystem power down */
0580     snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, MTL_HFDSSCS,
0581                 MTL_HFDSSCS_SPA_MASK, 0);
0582 
0583     /* Wait for unstable CPA read (1 then 0 then 1) just after setting SPA bit */
0584     usleep_range(1000, 1010);
0585 
0586     /* poll with timeout to check if operation successful */
0587     cpa = MTL_HFDSSCS_CPA_MASK;
0588     dsphfdsscs = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_HFDSSCS);
0589     ret = snd_sof_dsp_read_poll_timeout(sdev, HDA_DSP_BAR, MTL_HFDSSCS, dsphfdsscs,
0590                         (dsphfdsscs & cpa) == 0, HDA_DSP_REG_POLL_INTERVAL_US,
0591                     HDA_DSP_RESET_TIMEOUT_US);
0592     if (ret < 0)
0593         dev_err(sdev->dev, "failed to disable DSP subsystem\n");
0594 
0595     /* reset ref counts for all cores */
0596     for (i = 0; i < chip->cores_num; i++)
0597         sdev->dsp_core_ref_count[i] = 0;
0598 
0599     /* TODO: need to reset controller? */
0600 
0601     /* display codec can be powered off after link reset */
0602     hda_codec_i915_display_power(sdev, false);
0603 
0604     return 0;
0605 }
0606 
0607 static int mtl_dsp_suspend(struct snd_sof_dev *sdev, u32 target_state)
0608 {
0609     const struct sof_dsp_power_state target_dsp_state = {
0610         .state = target_state,
0611         .substate = target_state == SOF_DSP_PM_D0 ?
0612                 SOF_HDA_DSP_PM_D0I3 : 0,
0613     };
0614     int ret;
0615 
0616     ret = mtl_suspend(sdev, false);
0617     if (ret < 0)
0618         return ret;
0619 
0620     return snd_sof_dsp_set_power_state(sdev, &target_dsp_state);
0621 }
0622 
0623 static int mtl_dsp_runtime_suspend(struct snd_sof_dev *sdev)
0624 {
0625     const struct sof_dsp_power_state target_state = {
0626         .state = SOF_DSP_PM_D3,
0627     };
0628     int ret;
0629 
0630     ret = mtl_suspend(sdev, true);
0631     if (ret < 0)
0632         return ret;
0633 
0634     return snd_sof_dsp_set_power_state(sdev, &target_state);
0635 }
0636 
0637 static int mtl_resume(struct snd_sof_dev *sdev, bool runtime_resume)
0638 {
0639 #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA)
0640     struct hdac_bus *bus = sof_to_bus(sdev);
0641     struct hdac_ext_link *hlink = NULL;
0642 #endif
0643 
0644     /* display codec must be powered before link reset */
0645     hda_codec_i915_display_power(sdev, true);
0646 
0647 #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA)
0648     /* check jack status */
0649     if (runtime_resume) {
0650         hda_codec_jack_wake_enable(sdev, false);
0651         if (sdev->system_suspend_target == SOF_SUSPEND_NONE)
0652             hda_codec_jack_check(sdev);
0653     }
0654 
0655     /* turn off the links that were off before suspend */
0656     list_for_each_entry(hlink, &bus->hlink_list, list) {
0657         if (!hlink->ref_count)
0658             snd_hdac_ext_bus_link_power_down(hlink);
0659     }
0660 
0661     /* check dma status and clean up CORB/RIRB buffers */
0662     if (!bus->cmd_dma_state)
0663         snd_hdac_bus_stop_cmd_io(bus);
0664 #endif
0665 
0666     return 0;
0667 }
0668 
0669 static int mtl_dsp_resume(struct snd_sof_dev *sdev)
0670 {
0671     const struct sof_dsp_power_state target_state = {
0672         .state = SOF_DSP_PM_D0,
0673         .substate = SOF_HDA_DSP_PM_D0I0,
0674     };
0675     int ret;
0676 
0677     ret = mtl_resume(sdev, false);
0678     if (ret < 0)
0679         return ret;
0680 
0681     return snd_sof_dsp_set_power_state(sdev, &target_state);
0682 }
0683 
0684 static int mtl_dsp_runtime_resume(struct snd_sof_dev *sdev)
0685 {
0686     const struct sof_dsp_power_state target_state = {
0687         .state = SOF_DSP_PM_D0,
0688     };
0689     int ret;
0690 
0691     ret = mtl_resume(sdev, true);
0692     if (ret < 0)
0693         return ret;
0694 
0695     return snd_sof_dsp_set_power_state(sdev, &target_state);
0696 }
0697 
0698 static void mtl_ipc_dump(struct snd_sof_dev *sdev)
0699 {
0700     u32 hipcctl;
0701     u32 hipcida;
0702     u32 hipctdr;
0703 
0704     /* read IPC status */
0705     hipcida = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_DSP_REG_HFIPCXIDA);
0706     hipcctl = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_DSP_REG_HFIPCXCTL);
0707     hipctdr = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_DSP_REG_HFIPCXTDR);
0708 
0709     /* dump the IPC regs */
0710     /* TODO: parse the raw msg */
0711     dev_err(sdev->dev,
0712         "error: host status 0x%8.8x dsp status 0x%8.8x mask 0x%8.8x\n",
0713         hipcida, hipctdr, hipcctl);
0714 }
0715 
0716 /* Meteorlake ops */
0717 struct snd_sof_dsp_ops sof_mtl_ops;
0718 EXPORT_SYMBOL_NS(sof_mtl_ops, SND_SOC_SOF_INTEL_HDA_COMMON);
0719 
0720 int sof_mtl_ops_init(struct snd_sof_dev *sdev)
0721 {
0722     struct sof_ipc4_fw_data *ipc4_data;
0723 
0724     /* common defaults */
0725     memcpy(&sof_mtl_ops, &sof_hda_common_ops, sizeof(struct snd_sof_dsp_ops));
0726 
0727     /* shutdown */
0728     sof_mtl_ops.shutdown = hda_dsp_shutdown;
0729 
0730     /* doorbell */
0731     sof_mtl_ops.irq_thread = mtl_ipc_irq_thread;
0732 
0733     /* ipc */
0734     sof_mtl_ops.send_msg = mtl_ipc_send_msg;
0735     sof_mtl_ops.get_mailbox_offset = mtl_dsp_ipc_get_mailbox_offset;
0736     sof_mtl_ops.get_window_offset = mtl_dsp_ipc_get_window_offset;
0737 
0738     /* debug */
0739     sof_mtl_ops.debug_map = mtl_dsp_debugfs;
0740     sof_mtl_ops.debug_map_count = ARRAY_SIZE(mtl_dsp_debugfs);
0741     sof_mtl_ops.dbg_dump = mtl_dsp_dump;
0742     sof_mtl_ops.ipc_dump = mtl_ipc_dump;
0743 
0744     /* pre/post fw run */
0745     sof_mtl_ops.pre_fw_run = mtl_dsp_pre_fw_run;
0746     sof_mtl_ops.post_fw_run = mtl_dsp_post_fw_run;
0747 
0748     /* parse platform specific extended manifest */
0749     sof_mtl_ops.parse_platform_ext_manifest = NULL;
0750 
0751     /* dsp core get/put */
0752     /* TODO: add core_get and core_put */
0753 
0754     /* PM */
0755     sof_mtl_ops.suspend = mtl_dsp_suspend;
0756     sof_mtl_ops.resume = mtl_dsp_resume;
0757     sof_mtl_ops.runtime_suspend = mtl_dsp_runtime_suspend;
0758     sof_mtl_ops.runtime_resume = mtl_dsp_runtime_resume;
0759 
0760     sdev->private = devm_kzalloc(sdev->dev, sizeof(struct sof_ipc4_fw_data), GFP_KERNEL);
0761     if (!sdev->private)
0762         return -ENOMEM;
0763 
0764     ipc4_data = sdev->private;
0765     ipc4_data->manifest_fw_hdr_offset = SOF_MAN4_FW_HDR_OFFSET;
0766 
0767     /* set DAI ops */
0768     hda_set_dai_drv_ops(sdev, &sof_mtl_ops);
0769 
0770     return 0;
0771 };
0772 EXPORT_SYMBOL_NS(sof_mtl_ops_init, SND_SOC_SOF_INTEL_HDA_COMMON);
0773 
0774 const struct sof_intel_dsp_desc mtl_chip_info = {
0775     .cores_num = 3,
0776     .init_core_mask = BIT(0),
0777     .host_managed_cores_mask = BIT(0),
0778     .ipc_req = MTL_DSP_REG_HFIPCXIDR,
0779     .ipc_req_mask = MTL_DSP_REG_HFIPCXIDR_BUSY,
0780     .ipc_ack = MTL_DSP_REG_HFIPCXIDA,
0781     .ipc_ack_mask = MTL_DSP_REG_HFIPCXIDA_DONE,
0782     .ipc_ctl = MTL_DSP_REG_HFIPCXCTL,
0783     .rom_status_reg = MTL_DSP_ROM_STS,
0784     .rom_init_timeout   = 300,
0785     .ssp_count = ICL_SSP_COUNT,
0786     .ssp_base_offset = CNL_SSP_BASE_OFFSET,
0787     .sdw_shim_base = SDW_SHIM_BASE_ACE,
0788     .sdw_alh_base = SDW_ALH_BASE_ACE,
0789     .check_sdw_irq = mtl_dsp_check_sdw_irq,
0790     .check_ipc_irq = mtl_dsp_check_ipc_irq,
0791     .cl_init = mtl_dsp_cl_init,
0792     .hw_ip_version = SOF_INTEL_ACE_1_0,
0793 };
0794 EXPORT_SYMBOL_NS(mtl_chip_info, SND_SOC_SOF_INTEL_HDA_COMMON);