mtl.c 24 KB

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