projects/linux·blob master · refs

839 lines · 24.2 KiB

1// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
2//
3// Copyright(c) 2022 Intel Corporation
4//
5// Authors: Ranjani Sridharan <[email protected]>
6//
7
8/*
9 * Hardware interface for audio DSP on Meteorlake.
10 */
11
12#include <linux/debugfs.h>
13#include <linux/firmware.h>
14#include <linux/string_choices.h>
15#include <sound/sof/ipc4/header.h>
16#include <trace/events/sof_intel.h>
17#include "../ipc4-priv.h"
18#include "../ops.h"
19#include "hda.h"
20#include "hda-ipc.h"
21#include "../sof-audio.h"
22#include "mtl.h"
23#include "telemetry.h"
24
25static const struct snd_sof_debugfs_map mtl_dsp_debugfs[] = {
26 {"hda", HDA_DSP_HDA_BAR, 0, 0x4000, SOF_DEBUGFS_ACCESS_ALWAYS},
27 {"pp", HDA_DSP_PP_BAR, 0, 0x1000, SOF_DEBUGFS_ACCESS_ALWAYS},
28 {"dsp", HDA_DSP_BAR, 0, 0x10000, SOF_DEBUGFS_ACCESS_ALWAYS},
29 {"fw_regs", HDA_DSP_BAR, MTL_SRAM_WINDOW_OFFSET(0), 0x1000, SOF_DEBUGFS_ACCESS_D0_ONLY},
30};
31
32static void mtl_ipc_host_done(struct snd_sof_dev *sdev)
33{
34 /*
35 * clear busy interrupt to tell dsp controller this interrupt has been accepted,
36 * not trigger it again
37 */
38 snd_sof_dsp_update_bits_forced(sdev, HDA_DSP_BAR, MTL_DSP_REG_HFIPCXTDR,
39 MTL_DSP_REG_HFIPCXTDR_BUSY, MTL_DSP_REG_HFIPCXTDR_BUSY);
40 /*
41 * clear busy bit to ack dsp the msg has been processed and send reply msg to dsp
42 */
43 snd_sof_dsp_update_bits_forced(sdev, HDA_DSP_BAR, MTL_DSP_REG_HFIPCXTDA,
44 MTL_DSP_REG_HFIPCXTDA_BUSY, 0);
45}
46
47static void mtl_ipc_dsp_done(struct snd_sof_dev *sdev)
48{
49 /*
50 * set DONE bit - tell DSP we have received the reply msg from DSP, and processed it,
51 * don't send more reply to host
52 */
53 snd_sof_dsp_update_bits_forced(sdev, HDA_DSP_BAR, MTL_DSP_REG_HFIPCXIDA,
54 MTL_DSP_REG_HFIPCXIDA_DONE, MTL_DSP_REG_HFIPCXIDA_DONE);
55
56 /* unmask Done interrupt */
57 snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, MTL_DSP_REG_HFIPCXCTL,
58 MTL_DSP_REG_HFIPCXCTL_DONE, MTL_DSP_REG_HFIPCXCTL_DONE);
59}
60
61/* Check if an IPC IRQ occurred */
62bool mtl_dsp_check_ipc_irq(struct snd_sof_dev *sdev)
63{
64 u32 irq_status;
65 u32 hfintipptr;
66
67 if (sdev->dspless_mode_selected)
68 return false;
69
70 /* read Interrupt IP Pointer */
71 hfintipptr = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_HFINTIPPTR) & MTL_HFINTIPPTR_PTR_MASK;
72 irq_status = snd_sof_dsp_read(sdev, HDA_DSP_BAR, hfintipptr + MTL_DSP_IRQSTS);
73
74 trace_sof_intel_hda_irq_ipc_check(sdev, irq_status);
75
76 if (irq_status != U32_MAX && (irq_status & MTL_DSP_IRQSTS_IPC))
77 return true;
78
79 return false;
80}
81EXPORT_SYMBOL_NS(mtl_dsp_check_ipc_irq, "SND_SOC_SOF_INTEL_MTL");
82
83/* Check if an SDW IRQ occurred */
84static bool mtl_dsp_check_sdw_irq(struct snd_sof_dev *sdev)
85{
86 u32 irq_status;
87 u32 hfintipptr;
88
89 /* read Interrupt IP Pointer */
90 hfintipptr = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_HFINTIPPTR) & MTL_HFINTIPPTR_PTR_MASK;
91 irq_status = snd_sof_dsp_read(sdev, HDA_DSP_BAR, hfintipptr + MTL_DSP_IRQSTS);
92
93 if (irq_status != U32_MAX && (irq_status & MTL_DSP_IRQSTS_SDW))
94 return true;
95
96 return false;
97}
98
99static int mtl_ipc_send_msg(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg)
100{
101 struct sof_intel_hda_dev *hdev = sdev->pdata->hw_pdata;
102 struct sof_ipc4_msg *msg_data = msg->msg_data;
103
104 if (hda_ipc4_tx_is_busy(sdev)) {
105 hdev->delayed_ipc_tx_msg = msg;
106 return 0;
107 }
108
109 hdev->delayed_ipc_tx_msg = NULL;
110
111 /* send the message via mailbox */
112 if (msg_data->data_size)
113 sof_mailbox_write(sdev, sdev->host_box.offset, msg_data->data_ptr,
114 msg_data->data_size);
115
116 snd_sof_dsp_write(sdev, HDA_DSP_BAR, MTL_DSP_REG_HFIPCXIDDY,
117 msg_data->extension);
118 snd_sof_dsp_write(sdev, HDA_DSP_BAR, MTL_DSP_REG_HFIPCXIDR,
119 msg_data->primary | MTL_DSP_REG_HFIPCXIDR_BUSY);
120
121 hda_dsp_ipc4_schedule_d0i3_work(hdev, msg);
122
123 return 0;
124}
125
126void mtl_enable_ipc_interrupts(struct snd_sof_dev *sdev)
127{
128 struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata;
129 const struct sof_intel_dsp_desc *chip = hda->desc;
130
131 if (sdev->dspless_mode_selected)
132 return;
133
134 /* enable IPC DONE and BUSY interrupts */
135 snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, chip->ipc_ctl,
136 MTL_DSP_REG_HFIPCXCTL_BUSY | MTL_DSP_REG_HFIPCXCTL_DONE,
137 MTL_DSP_REG_HFIPCXCTL_BUSY | MTL_DSP_REG_HFIPCXCTL_DONE);
138}
139
140void mtl_disable_ipc_interrupts(struct snd_sof_dev *sdev)
141{
142 struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata;
143 const struct sof_intel_dsp_desc *chip = hda->desc;
144
145 if (sdev->dspless_mode_selected)
146 return;
147
148 /* disable IPC DONE and BUSY interrupts */
149 snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, chip->ipc_ctl,
150 MTL_DSP_REG_HFIPCXCTL_BUSY | MTL_DSP_REG_HFIPCXCTL_DONE, 0);
151}
152EXPORT_SYMBOL_NS(mtl_disable_ipc_interrupts, "SND_SOC_SOF_INTEL_MTL");
153
154static void mtl_enable_sdw_irq(struct snd_sof_dev *sdev, bool enable)
155{
156 u32 hipcie;
157 u32 mask;
158 u32 val;
159 int ret;
160
161 if (sdev->dspless_mode_selected)
162 return;
163
164 /* Enable/Disable SoundWire interrupt */
165 mask = MTL_DSP_REG_HfSNDWIE_IE_MASK;
166 if (enable)
167 val = mask;
168 else
169 val = 0;
170
171 snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, MTL_DSP_REG_HfSNDWIE, mask, val);
172
173 /* check if operation was successful */
174 ret = snd_sof_dsp_read_poll_timeout(sdev, HDA_DSP_BAR, MTL_DSP_REG_HfSNDWIE, hipcie,
175 (hipcie & mask) == val,
176 HDA_DSP_REG_POLL_INTERVAL_US, HDA_DSP_RESET_TIMEOUT_US);
177 if (ret < 0)
178 dev_err(sdev->dev, "failed to set SoundWire IPC interrupt %s\n",
179 str_enable_disable(enable));
180}
181
182int mtl_enable_interrupts(struct snd_sof_dev *sdev, bool enable)
183{
184 u32 hfintipptr;
185 u32 irqinten;
186 u32 hipcie;
187 u32 mask;
188 u32 val;
189 int ret;
190
191 if (sdev->dspless_mode_selected)
192 return 0;
193
194 /* read Interrupt IP Pointer */
195 hfintipptr = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_HFINTIPPTR) & MTL_HFINTIPPTR_PTR_MASK;
196
197 /* Enable/Disable Host IPC and SOUNDWIRE */
198 mask = MTL_IRQ_INTEN_L_HOST_IPC_MASK | MTL_IRQ_INTEN_L_SOUNDWIRE_MASK;
199 if (enable)
200 val = mask;
201 else
202 val = 0;
203
204 snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, hfintipptr, mask, val);
205
206 /* check if operation was successful */
207 ret = snd_sof_dsp_read_poll_timeout(sdev, HDA_DSP_BAR, hfintipptr, irqinten,
208 (irqinten & mask) == val,
209 HDA_DSP_REG_POLL_INTERVAL_US, HDA_DSP_RESET_TIMEOUT_US);
210 if (ret < 0) {
211 dev_err(sdev->dev, "failed to %s Host IPC and/or SOUNDWIRE\n",
212 str_enable_disable(enable));
213 return ret;
214 }
215
216 /* Enable/Disable Host IPC interrupt*/
217 mask = MTL_DSP_REG_HfHIPCIE_IE_MASK;
218 if (enable)
219 val = mask;
220 else
221 val = 0;
222
223 snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, MTL_DSP_REG_HfHIPCIE, mask, val);
224
225 /* check if operation was successful */
226 ret = snd_sof_dsp_read_poll_timeout(sdev, HDA_DSP_BAR, MTL_DSP_REG_HfHIPCIE, hipcie,
227 (hipcie & mask) == val,
228 HDA_DSP_REG_POLL_INTERVAL_US, HDA_DSP_RESET_TIMEOUT_US);
229 if (ret < 0) {
230 dev_err(sdev->dev, "failed to set Host IPC interrupt %s\n",
231 str_enable_disable(enable));
232 return ret;
233 }
234
235 return ret;
236}
237EXPORT_SYMBOL_NS(mtl_enable_interrupts, "SND_SOC_SOF_INTEL_MTL");
238
239static bool mtl_dsp_is_enabled(struct snd_sof_dev *sdev)
240{
241 int val;
242
243 val = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_HFDSSCS);
244 if (val & MTL_HFDSSCS_CPA_MASK)
245 return true;
246
247 return false;
248}
249
250/* pre fw run operations */
251static int mtl_dsp_pre_fw_run(struct snd_sof_dev *sdev)
252{
253 struct sof_intel_hda_dev *hdev = sdev->pdata->hw_pdata;
254 u32 dsphfpwrsts;
255 u32 dsphfdsscs;
256 u32 cpa;
257 u32 pgs;
258 int ret;
259 u32 dsppwrctl;
260 u32 dsppwrsts;
261 const struct sof_intel_dsp_desc *chip;
262
263 /* Power down the DSP if it is left enabled to ensure clean boot state */
264 if (mtl_dsp_is_enabled(sdev)) {
265 dev_dbg(sdev->dev, "powering down DSP first\n");
266
267 ret = mtl_power_down_dsp(sdev);
268 if (ret < 0) {
269 dev_warn(sdev->dev,
270 "%s: failed to power down already-enabled DSP\n", __func__);
271 /* Continue anyway to attempt recovery */
272 }
273 }
274
275 chip = get_chip_info(sdev->pdata);
276 if (chip->hw_ip_version > SOF_INTEL_ACE_2_0) {
277 dsppwrctl = PTL_HFPWRCTL2;
278 dsppwrsts = PTL_HFPWRSTS2;
279 } else {
280 dsppwrctl = MTL_HFPWRCTL;
281 dsppwrsts = MTL_HFPWRSTS;
282 }
283
284 /* Set the DSP subsystem power on */
285 snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, MTL_HFDSSCS,
286 MTL_HFDSSCS_SPA_MASK, MTL_HFDSSCS_SPA_MASK);
287
288 /* Wait for unstable CPA read (1 then 0 then 1) just after setting SPA bit */
289 usleep_range(1000, 1010);
290
291 /* poll with timeout to check if operation successful */
292 cpa = MTL_HFDSSCS_CPA_MASK;
293 ret = snd_sof_dsp_read_poll_timeout(sdev, HDA_DSP_BAR, MTL_HFDSSCS, dsphfdsscs,
294 (dsphfdsscs & cpa) == cpa, HDA_DSP_REG_POLL_INTERVAL_US,
295 HDA_DSP_RESET_TIMEOUT_US);
296 if (ret < 0) {
297 dev_err(sdev->dev, "failed to enable DSP subsystem\n");
298 return ret;
299 }
300
301 /* Power up gated-DSP-0 domain in order to access the DSP shim register block. */
302 snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, dsppwrctl,
303 MTL_HFPWRCTL_WPDSPHPXPG, MTL_HFPWRCTL_WPDSPHPXPG);
304
305 usleep_range(1000, 1010);
306
307 /* poll with timeout to check if operation successful */
308 pgs = MTL_HFPWRSTS_DSPHPXPGS_MASK;
309 ret = snd_sof_dsp_read_poll_timeout(sdev, HDA_DSP_BAR, dsppwrsts, dsphfpwrsts,
310 (dsphfpwrsts & pgs) == pgs,
311 HDA_DSP_REG_POLL_INTERVAL_US,
312 HDA_DSP_RESET_TIMEOUT_US);
313 if (ret < 0)
314 dev_err(sdev->dev, "failed to power up gated DSP domain\n");
315
316 /* if SoundWire is used, make sure it is not power-gated */
317 if (hdev->info.handle && hdev->info.link_mask > 0)
318 snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, MTL_HFPWRCTL,
319 MTL_HfPWRCTL_WPIOXPG(1), MTL_HfPWRCTL_WPIOXPG(1));
320
321 return ret;
322}
323
324static int mtl_dsp_post_fw_run(struct snd_sof_dev *sdev)
325{
326 int ret;
327
328 if (sdev->first_boot) {
329 struct sof_intel_hda_dev *hdev = sdev->pdata->hw_pdata;
330
331 ret = hda_sdw_startup(sdev);
332 if (ret < 0) {
333 dev_err(sdev->dev, "could not startup SoundWire links\n");
334 return ret;
335 }
336
337 /* Check if IMR boot is usable */
338 if (!sof_debug_check_flag(SOF_DBG_IGNORE_D3_PERSISTENT)) {
339 hdev->imrboot_supported = true;
340 debugfs_create_bool("skip_imr_boot",
341 0644, sdev->debugfs_root,
342 &hdev->skip_imr_boot);
343 }
344 }
345
346 hda_sdw_int_enable(sdev, true);
347 return 0;
348}
349
350static void mtl_dsp_dump(struct snd_sof_dev *sdev, u32 flags)
351{
352 char *level = (flags & SOF_DBG_DUMP_OPTIONAL) ? KERN_DEBUG : KERN_ERR;
353 u32 fwsts;
354 u32 fwlec;
355
356 hda_dsp_get_state(sdev, level);
357 fwsts = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_DSP_ROM_STS);
358 fwlec = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_DSP_ROM_ERROR);
359
360 if (fwsts != 0xffffffff)
361 dev_err(sdev->dev, "Firmware state: %#x, status/error code: %#x\n",
362 fwsts, fwlec);
363
364 sof_ipc4_intel_dump_telemetry_state(sdev, flags);
365}
366
367static bool mtl_dsp_primary_core_is_enabled(struct snd_sof_dev *sdev)
368{
369 int val;
370
371 val = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_DSP2CXCTL_PRIMARY_CORE);
372 if (val != U32_MAX && val & MTL_DSP2CXCTL_PRIMARY_CORE_CPA_MASK)
373 return true;
374
375 return false;
376}
377
378static int mtl_dsp_core_power_up(struct snd_sof_dev *sdev, int core)
379{
380 unsigned int cpa;
381 u32 dspcxctl;
382 int ret;
383
384 /* Only the primary core can be powered up by the host */
385 if (core != SOF_DSP_PRIMARY_CORE || mtl_dsp_primary_core_is_enabled(sdev))
386 return 0;
387
388 /* Program the owner of the IP & shim registers (10: Host CPU) */
389 snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, MTL_DSP2CXCTL_PRIMARY_CORE,
390 MTL_DSP2CXCTL_PRIMARY_CORE_OSEL,
391 0x2 << MTL_DSP2CXCTL_PRIMARY_CORE_OSEL_SHIFT);
392
393 /* enable SPA bit */
394 snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, MTL_DSP2CXCTL_PRIMARY_CORE,
395 MTL_DSP2CXCTL_PRIMARY_CORE_SPA_MASK,
396 MTL_DSP2CXCTL_PRIMARY_CORE_SPA_MASK);
397
398 /* Wait for unstable CPA read (1 then 0 then 1) just after setting SPA bit */
399 usleep_range(1000, 1010);
400
401 /* poll with timeout to check if operation successful */
402 cpa = MTL_DSP2CXCTL_PRIMARY_CORE_CPA_MASK;
403 ret = snd_sof_dsp_read_poll_timeout(sdev, HDA_DSP_BAR, MTL_DSP2CXCTL_PRIMARY_CORE, dspcxctl,
404 (dspcxctl & cpa) == cpa, HDA_DSP_REG_POLL_INTERVAL_US,
405 HDA_DSP_RESET_TIMEOUT_US);
406 if (ret < 0) {
407 dev_err(sdev->dev, "%s: timeout on MTL_DSP2CXCTL_PRIMARY_CORE read\n",
408 __func__);
409 return ret;
410 }
411
412 /* set primary core mask and refcount to 1 */
413 sdev->enabled_cores_mask = BIT(SOF_DSP_PRIMARY_CORE);
414 sdev->dsp_core_ref_count[SOF_DSP_PRIMARY_CORE] = 1;
415
416 return 0;
417}
418
419static int mtl_dsp_core_power_down(struct snd_sof_dev *sdev, int core)
420{
421 u32 dspcxctl;
422 int ret;
423
424 /* Only the primary core can be powered down by the host */
425 if (core != SOF_DSP_PRIMARY_CORE || !mtl_dsp_primary_core_is_enabled(sdev))
426 return 0;
427
428 /* disable SPA bit */
429 snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, MTL_DSP2CXCTL_PRIMARY_CORE,
430 MTL_DSP2CXCTL_PRIMARY_CORE_SPA_MASK, 0);
431
432 /* Wait for unstable CPA read (0 then 1 then 0) just after setting SPA bit */
433 usleep_range(1000, 1010);
434
435 ret = snd_sof_dsp_read_poll_timeout(sdev, HDA_DSP_BAR, MTL_DSP2CXCTL_PRIMARY_CORE, dspcxctl,
436 !(dspcxctl & MTL_DSP2CXCTL_PRIMARY_CORE_CPA_MASK),
437 HDA_DSP_REG_POLL_INTERVAL_US,
438 HDA_DSP_PD_TIMEOUT * USEC_PER_MSEC);
439 if (ret < 0) {
440 dev_err(sdev->dev, "failed to power down primary core\n");
441 return ret;
442 }
443
444 sdev->enabled_cores_mask = 0;
445 sdev->dsp_core_ref_count[SOF_DSP_PRIMARY_CORE] = 0;
446
447 return 0;
448}
449
450int mtl_power_down_dsp(struct snd_sof_dev *sdev)
451{
452 u32 dsphfdsscs, cpa;
453 int ret;
454
455 /* first power down core */
456 ret = mtl_dsp_core_power_down(sdev, SOF_DSP_PRIMARY_CORE);
457 if (ret) {
458 dev_err(sdev->dev, "mtl dsp power down error, %d\n", ret);
459 return ret;
460 }
461
462 /* Set the DSP subsystem power down */
463 snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, MTL_HFDSSCS,
464 MTL_HFDSSCS_SPA_MASK, 0);
465
466 /* Wait for unstable CPA read (0 then 1 then 0) just after setting SPA bit */
467 usleep_range(1000, 1010);
468
469 /* poll with timeout to check if operation successful */
470 cpa = MTL_HFDSSCS_CPA_MASK;
471 dsphfdsscs = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_HFDSSCS);
472 return snd_sof_dsp_read_poll_timeout(sdev, HDA_DSP_BAR, MTL_HFDSSCS, dsphfdsscs,
473 (dsphfdsscs & cpa) == 0, HDA_DSP_REG_POLL_INTERVAL_US,
474 HDA_DSP_RESET_TIMEOUT_US);
475}
476EXPORT_SYMBOL_NS(mtl_power_down_dsp, "SND_SOC_SOF_INTEL_MTL");
477
478int mtl_dsp_cl_init(struct snd_sof_dev *sdev, int stream_tag, bool imr_boot)
479{
480 struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata;
481 const struct sof_intel_dsp_desc *chip = hda->desc;
482 unsigned int status, target_status;
483 u32 ipc_hdr, flags;
484 char *dump_msg;
485 int ret;
486
487 /* step 1: purge FW request */
488 ipc_hdr = chip->ipc_req_mask | HDA_DSP_ROM_IPC_CONTROL;
489 if (!imr_boot)
490 ipc_hdr |= HDA_DSP_ROM_IPC_PURGE_FW | ((stream_tag - 1) << 9);
491
492 snd_sof_dsp_write(sdev, HDA_DSP_BAR, chip->ipc_req, ipc_hdr);
493
494 /* step 2: power up primary core */
495 ret = mtl_dsp_core_power_up(sdev, SOF_DSP_PRIMARY_CORE);
496 if (ret < 0) {
497 if (hda->boot_iteration == HDA_FW_BOOT_ATTEMPTS)
498 dev_err(sdev->dev, "dsp core 0/1 power up failed\n");
499 goto err;
500 }
501
502 dev_dbg(sdev->dev, "Primary core power up successful\n");
503
504 /* step 3: wait for IPC DONE bit from ROM */
505 ret = snd_sof_dsp_read_poll_timeout(sdev, HDA_DSP_BAR, chip->ipc_ack, status,
506 ((status & chip->ipc_ack_mask) == chip->ipc_ack_mask),
507 HDA_DSP_REG_POLL_INTERVAL_US, HDA_DSP_INIT_TIMEOUT_US);
508 if (ret < 0) {
509 if (hda->boot_iteration == HDA_FW_BOOT_ATTEMPTS)
510 dev_err(sdev->dev, "timeout waiting for purge IPC done\n");
511 goto err;
512 }
513
514 /* set DONE bit to clear the reply IPC message */
515 snd_sof_dsp_update_bits_forced(sdev, HDA_DSP_BAR, chip->ipc_ack, chip->ipc_ack_mask,
516 chip->ipc_ack_mask);
517
518 /* step 4: enable interrupts */
519 ret = mtl_enable_interrupts(sdev, true);
520 if (ret < 0) {
521 if (hda->boot_iteration == HDA_FW_BOOT_ATTEMPTS)
522 dev_err(sdev->dev, "%s: failed to enable interrupts\n", __func__);
523 goto err;
524 }
525
526 mtl_enable_ipc_interrupts(sdev);
527
528 if (chip->rom_status_reg == MTL_DSP_ROM_STS) {
529 /*
530 * Workaround: when the ROM status register is pointing to
531 * the SRAM window (MTL_DSP_ROM_STS) the platform cannot catch
532 * ROM_INIT_DONE because of a very short timing window.
533 * Follow the recommendations and skip target state waiting.
534 */
535 return 0;
536 }
537
538 /*
539 * step 7:
540 * - Cold/Full boot: wait for ROM init to proceed to download the firmware
541 * - IMR boot: wait for ROM firmware entered (firmware booted up from IMR)
542 */
543 if (imr_boot)
544 target_status = FSR_STATE_FW_ENTERED;
545 else
546 target_status = FSR_STATE_INIT_DONE;
547
548 ret = snd_sof_dsp_read_poll_timeout(sdev, HDA_DSP_BAR,
549 chip->rom_status_reg, status,
550 (FSR_TO_STATE_CODE(status) == target_status),
551 HDA_DSP_REG_POLL_INTERVAL_US,
552 chip->rom_init_timeout *
553 USEC_PER_MSEC);
554
555 if (!ret)
556 return 0;
557
558 if (hda->boot_iteration == HDA_FW_BOOT_ATTEMPTS)
559 dev_err(sdev->dev,
560 "%s: timeout with rom_status_reg (%#x) read\n",
561 __func__, chip->rom_status_reg);
562
563err:
564 flags = SOF_DBG_DUMP_PCI | SOF_DBG_DUMP_MBOX | SOF_DBG_DUMP_OPTIONAL;
565
566 /* after max boot attempts make sure that the dump is printed */
567 if (hda->boot_iteration == HDA_FW_BOOT_ATTEMPTS)
568 flags &= ~SOF_DBG_DUMP_OPTIONAL;
569
570 dump_msg = kasprintf(GFP_KERNEL, "Boot iteration failed: %d/%d",
571 hda->boot_iteration, HDA_FW_BOOT_ATTEMPTS);
572 snd_sof_dsp_dbg_dump(sdev, dump_msg, flags);
573 mtl_enable_interrupts(sdev, false);
574 mtl_dsp_core_power_down(sdev, SOF_DSP_PRIMARY_CORE);
575
576 kfree(dump_msg);
577 return ret;
578}
579EXPORT_SYMBOL_NS(mtl_dsp_cl_init, "SND_SOC_SOF_INTEL_MTL");
580
581static irqreturn_t mtl_ipc_irq_thread(int irq, void *context)
582{
583 struct sof_ipc4_msg notification_data = {{ 0 }};
584 struct snd_sof_dev *sdev = context;
585 bool ack_received = false;
586 bool ipc_irq = false;
587 u32 hipcida;
588 u32 hipctdr;
589
590 hipcida = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_DSP_REG_HFIPCXIDA);
591 hipctdr = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_DSP_REG_HFIPCXTDR);
592
593 /* reply message from DSP */
594 if (hipcida & MTL_DSP_REG_HFIPCXIDA_DONE) {
595 /* DSP received the message */
596 snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, MTL_DSP_REG_HFIPCXCTL,
597 MTL_DSP_REG_HFIPCXCTL_DONE, 0);
598
599 mtl_ipc_dsp_done(sdev);
600
601 ipc_irq = true;
602 ack_received = true;
603 }
604
605 if (hipctdr & MTL_DSP_REG_HFIPCXTDR_BUSY) {
606 /* Message from DSP (reply or notification) */
607 u32 extension = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_DSP_REG_HFIPCXTDDY);
608 u32 primary = hipctdr & MTL_DSP_REG_HFIPCXTDR_MSG_MASK;
609
610 /*
611 * ACE fw sends a new fw ipc message to host to
612 * notify the status of the last host ipc message
613 */
614 if (primary & SOF_IPC4_MSG_DIR_MASK) {
615 /* Reply received */
616 if (likely(sdev->fw_state == SOF_FW_BOOT_COMPLETE)) {
617 struct sof_ipc4_msg *data = sdev->ipc->msg.reply_data;
618
619 data->primary = primary;
620 data->extension = extension;
621
622 guard(spinlock_irq)(&sdev->ipc_lock);
623 snd_sof_ipc_get_reply(sdev);
624 mtl_ipc_host_done(sdev);
625 snd_sof_ipc_reply(sdev, data->primary);
626 } else {
627 dev_dbg_ratelimited(sdev->dev,
628 "IPC reply before FW_READY: %#x|%#x\n",
629 primary, extension);
630 }
631 } else {
632 /* Notification received */
633 notification_data.primary = primary;
634 notification_data.extension = extension;
635
636 sdev->ipc->msg.rx_data = &notification_data;
637 snd_sof_ipc_msgs_rx(sdev);
638 sdev->ipc->msg.rx_data = NULL;
639
640 mtl_ipc_host_done(sdev);
641 }
642
643 ipc_irq = true;
644 }
645
646 if (!ipc_irq) {
647 /* This interrupt is not shared so no need to return IRQ_NONE. */
648 dev_dbg_ratelimited(sdev->dev, "nothing to do in IPC IRQ thread\n");
649 }
650
651 if (ack_received) {
652 struct sof_intel_hda_dev *hdev = sdev->pdata->hw_pdata;
653
654 if (hdev->delayed_ipc_tx_msg)
655 mtl_ipc_send_msg(sdev, hdev->delayed_ipc_tx_msg);
656 }
657
658 return IRQ_HANDLED;
659}
660
661static int mtl_dsp_ipc_get_mailbox_offset(struct snd_sof_dev *sdev)
662{
663 return MTL_DSP_MBOX_UPLINK_OFFSET;
664}
665
666static int mtl_dsp_ipc_get_window_offset(struct snd_sof_dev *sdev, u32 id)
667{
668 return MTL_SRAM_WINDOW_OFFSET(id);
669}
670
671static void mtl_ipc_dump(struct snd_sof_dev *sdev)
672{
673 u32 hipcidr, hipcidd, hipcida, hipctdr, hipctdd, hipctda, hipcctl;
674
675 hipcidr = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_DSP_REG_HFIPCXIDR);
676 hipcidd = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_DSP_REG_HFIPCXIDDY);
677 hipcida = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_DSP_REG_HFIPCXIDA);
678 hipctdr = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_DSP_REG_HFIPCXTDR);
679 hipctdd = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_DSP_REG_HFIPCXTDDY);
680 hipctda = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_DSP_REG_HFIPCXTDA);
681 hipcctl = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_DSP_REG_HFIPCXCTL);
682
683 dev_err(sdev->dev,
684 "Host IPC initiator: %#x|%#x|%#x, target: %#x|%#x|%#x, ctl: %#x\n",
685 hipcidr, hipcidd, hipcida, hipctdr, hipctdd, hipctda, hipcctl);
686}
687
688static int mtl_dsp_disable_interrupts(struct snd_sof_dev *sdev)
689{
690 mtl_enable_sdw_irq(sdev, false);
691 mtl_disable_ipc_interrupts(sdev);
692 return mtl_enable_interrupts(sdev, false);
693}
694
695static int mtl_dsp_core_get(struct snd_sof_dev *sdev, int core)
696{
697 const struct sof_ipc_pm_ops *pm_ops = sdev->ipc->ops->pm;
698
699 if (core == SOF_DSP_PRIMARY_CORE)
700 return mtl_dsp_core_power_up(sdev, SOF_DSP_PRIMARY_CORE);
701
702 if (pm_ops->set_core_state)
703 return pm_ops->set_core_state(sdev, core, true);
704
705 return 0;
706}
707
708static int mtl_dsp_core_put(struct snd_sof_dev *sdev, int core)
709{
710 const struct sof_ipc_pm_ops *pm_ops = sdev->ipc->ops->pm;
711 int ret;
712
713 if (pm_ops->set_core_state) {
714 ret = pm_ops->set_core_state(sdev, core, false);
715 if (ret < 0)
716 return ret;
717 }
718
719 if (core == SOF_DSP_PRIMARY_CORE)
720 return mtl_dsp_core_power_down(sdev, SOF_DSP_PRIMARY_CORE);
721
722 return 0;
723}
724
725int sof_mtl_set_ops(struct snd_sof_dev *sdev, struct snd_sof_dsp_ops *dsp_ops)
726{
727 struct sof_ipc4_fw_data *ipc4_data;
728
729 /* common defaults */
730 memcpy(dsp_ops, &sof_hda_common_ops, sizeof(struct snd_sof_dsp_ops));
731
732 /* shutdown */
733 dsp_ops->shutdown = hda_dsp_shutdown;
734
735 /* doorbell */
736 dsp_ops->irq_thread = mtl_ipc_irq_thread;
737
738 /* ipc */
739 dsp_ops->send_msg = mtl_ipc_send_msg;
740 dsp_ops->get_mailbox_offset = mtl_dsp_ipc_get_mailbox_offset;
741 dsp_ops->get_window_offset = mtl_dsp_ipc_get_window_offset;
742
743 /* debug */
744 dsp_ops->debug_map = mtl_dsp_debugfs;
745 dsp_ops->debug_map_count = ARRAY_SIZE(mtl_dsp_debugfs);
746 dsp_ops->dbg_dump = mtl_dsp_dump;
747 dsp_ops->ipc_dump = mtl_ipc_dump;
748
749 /* pre/post fw run */
750 dsp_ops->pre_fw_run = mtl_dsp_pre_fw_run;
751 dsp_ops->post_fw_run = mtl_dsp_post_fw_run;
752
753 /* parse platform specific extended manifest */
754 dsp_ops->parse_platform_ext_manifest = NULL;
755
756 /* dsp core get/put */
757 dsp_ops->core_get = mtl_dsp_core_get;
758 dsp_ops->core_put = mtl_dsp_core_put;
759
760 sdev->private = kzalloc_obj(struct sof_ipc4_fw_data);
761 if (!sdev->private)
762 return -ENOMEM;
763
764 ipc4_data = sdev->private;
765 ipc4_data->manifest_fw_hdr_offset = SOF_MAN4_FW_HDR_OFFSET;
766
767 ipc4_data->mtrace_type = SOF_IPC4_MTRACE_INTEL_CAVS_2;
768
769 ipc4_data->fw_context_save = true;
770
771 /* External library loading support */
772 ipc4_data->load_library = hda_dsp_ipc4_load_library;
773
774 dsp_ops->set_power_state = hda_dsp_set_power_state_ipc4;
775
776 /* set DAI ops */
777 hda_set_dai_drv_ops(sdev, dsp_ops);
778
779 return 0;
780}
781EXPORT_SYMBOL_NS(sof_mtl_set_ops, "SND_SOC_SOF_INTEL_MTL");
782
783const struct sof_intel_dsp_desc mtl_chip_info = {
784 .cores_num = 3,
785 .init_core_mask = BIT(0),
786 .host_managed_cores_mask = BIT(0),
787 .ipc_req = MTL_DSP_REG_HFIPCXIDR,
788 .ipc_req_mask = MTL_DSP_REG_HFIPCXIDR_BUSY,
789 .ipc_ack = MTL_DSP_REG_HFIPCXIDA,
790 .ipc_ack_mask = MTL_DSP_REG_HFIPCXIDA_DONE,
791 .ipc_ctl = MTL_DSP_REG_HFIPCXCTL,
792 .rom_status_reg = MTL_DSP_REG_HFFLGPXQWY,
793 .rom_init_timeout = 300,
794 .ssp_count = MTL_SSP_COUNT,
795 .ssp_base_offset = CNL_SSP_BASE_OFFSET,
796 .sdw_shim_base = SDW_SHIM_BASE_ACE,
797 .sdw_alh_base = SDW_ALH_BASE_ACE,
798 .d0i3_offset = MTL_HDA_VS_D0I3C,
799 .read_sdw_lcount = hda_sdw_check_lcount_common,
800 .enable_sdw_irq = mtl_enable_sdw_irq,
801 .check_sdw_irq = mtl_dsp_check_sdw_irq,
802 .check_sdw_wakeen_irq = hda_sdw_check_wakeen_irq_common,
803 .sdw_process_wakeen = hda_sdw_process_wakeen_common,
804 .check_ipc_irq = mtl_dsp_check_ipc_irq,
805 .cl_init = mtl_dsp_cl_init,
806 .power_down_dsp = mtl_power_down_dsp,
807 .disable_interrupts = mtl_dsp_disable_interrupts,
808 .hw_ip_version = SOF_INTEL_ACE_1_0,
809 .platform = "mtl",
810};
811
812const struct sof_intel_dsp_desc arl_s_chip_info = {
813 .cores_num = 2,
814 .init_core_mask = BIT(0),
815 .host_managed_cores_mask = BIT(0),
816 .ipc_req = MTL_DSP_REG_HFIPCXIDR,
817 .ipc_req_mask = MTL_DSP_REG_HFIPCXIDR_BUSY,
818 .ipc_ack = MTL_DSP_REG_HFIPCXIDA,
819 .ipc_ack_mask = MTL_DSP_REG_HFIPCXIDA_DONE,
820 .ipc_ctl = MTL_DSP_REG_HFIPCXCTL,
821 .rom_status_reg = MTL_DSP_REG_HFFLGPXQWY,
822 .rom_init_timeout = 300,
823 .ssp_count = MTL_SSP_COUNT,
824 .ssp_base_offset = CNL_SSP_BASE_OFFSET,
825 .sdw_shim_base = SDW_SHIM_BASE_ACE,
826 .sdw_alh_base = SDW_ALH_BASE_ACE,
827 .d0i3_offset = MTL_HDA_VS_D0I3C,
828 .read_sdw_lcount = hda_sdw_check_lcount_common,
829 .enable_sdw_irq = mtl_enable_sdw_irq,
830 .check_sdw_irq = mtl_dsp_check_sdw_irq,
831 .check_sdw_wakeen_irq = hda_sdw_check_wakeen_irq_common,
832 .sdw_process_wakeen = hda_sdw_process_wakeen_common,
833 .check_ipc_irq = mtl_dsp_check_ipc_irq,
834 .cl_init = mtl_dsp_cl_init,
835 .power_down_dsp = mtl_power_down_dsp,
836 .disable_interrupts = mtl_dsp_disable_interrupts,
837 .hw_ip_version = SOF_INTEL_ACE_1_0,
838 .platform = "arl",
839};