1 // SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
3 // Copyright(c) 2020 Intel Corporation
5 // Author: Fred Oh <fred.oh@linux.intel.com>
9 * Hardware interface for audio DSP on IceLake.
12 #include <linux/kernel.h>
13 #include <linux/kconfig.h>
14 #include <linux/export.h>
15 #include <linux/bits.h>
16 #include "../ipc4-priv.h"
20 #include "../sof-audio.h"
22 #define ICL_DSP_HPRO_CORE_ID 3
24 static const struct snd_sof_debugfs_map icl_dsp_debugfs
[] = {
25 {"hda", HDA_DSP_HDA_BAR
, 0, 0x4000, SOF_DEBUGFS_ACCESS_ALWAYS
},
26 {"pp", HDA_DSP_PP_BAR
, 0, 0x1000, SOF_DEBUGFS_ACCESS_ALWAYS
},
27 {"dsp", HDA_DSP_BAR
, 0, 0x10000, SOF_DEBUGFS_ACCESS_ALWAYS
},
30 static int icl_dsp_core_stall(struct snd_sof_dev
*sdev
, unsigned int core_mask
)
32 struct sof_intel_hda_dev
*hda
= sdev
->pdata
->hw_pdata
;
33 const struct sof_intel_dsp_desc
*chip
= hda
->desc
;
35 /* make sure core_mask in host managed cores */
36 core_mask
&= chip
->host_managed_cores_mask
;
38 dev_err(sdev
->dev
, "error: core_mask is not in host managed cores\n");
43 snd_sof_dsp_update_bits_unlocked(sdev
, HDA_DSP_BAR
, HDA_DSP_REG_ADSPCS
,
44 HDA_DSP_ADSPCS_CSTALL_MASK(core_mask
),
45 HDA_DSP_ADSPCS_CSTALL_MASK(core_mask
));
51 * post fw run operation for ICL.
52 * Core 3 will be powered up and in stall when HPRO is enabled
54 static int icl_dsp_post_fw_run(struct snd_sof_dev
*sdev
)
56 struct sof_intel_hda_dev
*hda
= sdev
->pdata
->hw_pdata
;
59 if (sdev
->first_boot
) {
60 struct sof_intel_hda_dev
*hdev
= sdev
->pdata
->hw_pdata
;
62 ret
= hda_sdw_startup(sdev
);
64 dev_err(sdev
->dev
, "error: could not startup SoundWire links\n");
68 /* Check if IMR boot is usable */
69 if (!sof_debug_check_flag(SOF_DBG_IGNORE_D3_PERSISTENT
) &&
70 sdev
->fw_ready
.flags
& SOF_IPC_INFO_D3_PERSISTENT
)
71 hdev
->imrboot_supported
= true;
74 hda_sdw_int_enable(sdev
, true);
77 * The recommended HW programming sequence for ICL is to
78 * power up core 3 and keep it in stall if HPRO is enabled.
80 if (!hda
->clk_config_lpro
) {
81 ret
= hda_dsp_enable_core(sdev
, BIT(ICL_DSP_HPRO_CORE_ID
));
83 dev_err(sdev
->dev
, "error: dsp core power up failed on core %d\n",
84 ICL_DSP_HPRO_CORE_ID
);
88 sdev
->enabled_cores_mask
|= BIT(ICL_DSP_HPRO_CORE_ID
);
89 sdev
->dsp_core_ref_count
[ICL_DSP_HPRO_CORE_ID
]++;
91 snd_sof_dsp_stall(sdev
, BIT(ICL_DSP_HPRO_CORE_ID
));
94 /* re-enable clock gating and power gating */
95 return hda_dsp_ctrl_clock_power_gating(sdev
, true);
99 struct snd_sof_dsp_ops sof_icl_ops
;
101 int sof_icl_ops_init(struct snd_sof_dev
*sdev
)
103 /* common defaults */
104 memcpy(&sof_icl_ops
, &sof_hda_common_ops
, sizeof(struct snd_sof_dsp_ops
));
106 /* probe/remove/shutdown */
107 sof_icl_ops
.shutdown
= hda_dsp_shutdown
;
109 if (sdev
->pdata
->ipc_type
== SOF_IPC_TYPE_3
) {
111 sof_icl_ops
.irq_thread
= cnl_ipc_irq_thread
;
114 sof_icl_ops
.send_msg
= cnl_ipc_send_msg
;
117 sof_icl_ops
.ipc_dump
= cnl_ipc_dump
;
119 sof_icl_ops
.set_power_state
= hda_dsp_set_power_state_ipc3
;
122 if (sdev
->pdata
->ipc_type
== SOF_IPC_TYPE_4
) {
123 struct sof_ipc4_fw_data
*ipc4_data
;
125 sdev
->private = kzalloc(sizeof(*ipc4_data
), GFP_KERNEL
);
129 ipc4_data
= sdev
->private;
130 ipc4_data
->manifest_fw_hdr_offset
= SOF_MAN4_FW_HDR_OFFSET
;
132 ipc4_data
->mtrace_type
= SOF_IPC4_MTRACE_INTEL_CAVS_2
;
134 /* External library loading support */
135 ipc4_data
->load_library
= hda_dsp_ipc4_load_library
;
138 sof_icl_ops
.irq_thread
= cnl_ipc4_irq_thread
;
141 sof_icl_ops
.send_msg
= cnl_ipc4_send_msg
;
144 sof_icl_ops
.ipc_dump
= cnl_ipc4_dump
;
146 sof_icl_ops
.set_power_state
= hda_dsp_set_power_state_ipc4
;
150 sof_icl_ops
.debug_map
= icl_dsp_debugfs
;
151 sof_icl_ops
.debug_map_count
= ARRAY_SIZE(icl_dsp_debugfs
);
153 /* pre/post fw run */
154 sof_icl_ops
.post_fw_run
= icl_dsp_post_fw_run
;
157 sof_icl_ops
.run
= hda_dsp_cl_boot_firmware_iccmax
;
158 sof_icl_ops
.stall
= icl_dsp_core_stall
;
160 /* dsp core get/put */
161 sof_icl_ops
.core_get
= hda_dsp_core_get
;
163 /* set DAI driver ops */
164 hda_set_dai_drv_ops(sdev
, &sof_icl_ops
);
169 const struct sof_intel_dsp_desc icl_chip_info
= {
173 .host_managed_cores_mask
= GENMASK(3, 0),
174 .ipc_req
= CNL_DSP_REG_HIPCIDR
,
175 .ipc_req_mask
= CNL_DSP_REG_HIPCIDR_BUSY
,
176 .ipc_ack
= CNL_DSP_REG_HIPCIDA
,
177 .ipc_ack_mask
= CNL_DSP_REG_HIPCIDA_DONE
,
178 .ipc_ctl
= CNL_DSP_REG_HIPCCTL
,
179 .rom_status_reg
= HDA_DSP_SRAM_REG_ROM_STATUS
,
180 .rom_init_timeout
= 300,
181 .ssp_count
= ICL_SSP_COUNT
,
182 .ssp_base_offset
= CNL_SSP_BASE_OFFSET
,
183 .sdw_shim_base
= SDW_SHIM_BASE
,
184 .sdw_alh_base
= SDW_ALH_BASE
,
185 .d0i3_offset
= SOF_HDA_VS_D0I3C
,
186 .read_sdw_lcount
= hda_sdw_check_lcount_common
,
187 .enable_sdw_irq
= hda_common_enable_sdw_irq
,
188 .check_sdw_irq
= hda_common_check_sdw_irq
,
189 .check_sdw_wakeen_irq
= hda_sdw_check_wakeen_irq_common
,
190 .sdw_process_wakeen
= hda_sdw_process_wakeen_common
,
191 .check_ipc_irq
= hda_dsp_check_ipc_irq
,
192 .cl_init
= cl_dsp_init
,
193 .power_down_dsp
= hda_power_down_dsp
,
194 .disable_interrupts
= hda_dsp_disable_interrupts
,
195 .hw_ip_version
= SOF_INTEL_CAVS_2_0
,