acp-loader.c 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320
  1. // SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
  2. //
  3. // This file is provided under a dual BSD/GPLv2 license. When using or
  4. // redistributing this file, you may do so under either license.
  5. //
  6. // Copyright(c) 2021, 2023 Advanced Micro Devices, Inc.
  7. //
  8. // Authors: Ajit Kumar Pandey <AjitKumar.Pandey@amd.com>
  9. /*
  10. * Hardware interface for ACP DSP Firmware binaries loader
  11. */
  12. #include <linux/firmware.h>
  13. #include <linux/module.h>
  14. #include <linux/pci.h>
  15. #include "../ops.h"
  16. #include "acp-dsp-offset.h"
  17. #include "acp.h"
  18. #define FW_BIN 0
  19. #define FW_DATA_BIN 1
  20. #define FW_SRAM_DATA_BIN 2
  21. #define FW_BIN_PTE_OFFSET 0x00
  22. #define FW_DATA_BIN_PTE_OFFSET 0x08
  23. #define ACP_DSP_RUN 0x00
  24. int acp_dsp_block_read(struct snd_sof_dev *sdev, enum snd_sof_fw_blk_type blk_type,
  25. u32 offset, void *dest, size_t size)
  26. {
  27. const struct sof_amd_acp_desc *desc = get_chip_info(sdev->pdata);
  28. switch (blk_type) {
  29. case SOF_FW_BLK_TYPE_SRAM:
  30. offset = offset - desc->sram_pte_offset;
  31. memcpy_from_scratch(sdev, offset, dest, size);
  32. break;
  33. default:
  34. dev_err(sdev->dev, "bad blk type 0x%x\n", blk_type);
  35. return -EINVAL;
  36. }
  37. return 0;
  38. }
  39. EXPORT_SYMBOL_NS(acp_dsp_block_read, "SND_SOC_SOF_AMD_COMMON");
  40. int acp_dsp_block_write(struct snd_sof_dev *sdev, enum snd_sof_fw_blk_type blk_type,
  41. u32 offset, void *src, size_t size)
  42. {
  43. struct pci_dev *pci = to_pci_dev(sdev->dev);
  44. struct acp_dev_data *adata;
  45. void *dest;
  46. u32 dma_size, page_count;
  47. unsigned int size_fw;
  48. adata = sdev->pdata->hw_pdata;
  49. switch (blk_type) {
  50. case SOF_FW_BLK_TYPE_IRAM:
  51. if (!adata->bin_buf) {
  52. size_fw = sdev->basefw.fw->size;
  53. page_count = PAGE_ALIGN(size_fw) >> PAGE_SHIFT;
  54. dma_size = page_count * ACP_PAGE_SIZE;
  55. adata->bin_buf = dma_alloc_coherent(&pci->dev, dma_size,
  56. &adata->sha_dma_addr,
  57. GFP_KERNEL);
  58. if (!adata->bin_buf)
  59. return -ENOMEM;
  60. }
  61. adata->fw_bin_size = size + offset;
  62. dest = adata->bin_buf + offset;
  63. break;
  64. case SOF_FW_BLK_TYPE_DRAM:
  65. if (!adata->data_buf) {
  66. adata->data_buf = dma_alloc_coherent(&pci->dev,
  67. ACP_DEFAULT_DRAM_LENGTH,
  68. &adata->dma_addr,
  69. GFP_KERNEL);
  70. if (!adata->data_buf)
  71. return -ENOMEM;
  72. }
  73. dest = adata->data_buf + offset;
  74. adata->fw_data_bin_size = size + offset;
  75. adata->is_dram_in_use = true;
  76. break;
  77. case SOF_FW_BLK_TYPE_SRAM:
  78. if (!adata->sram_data_buf) {
  79. adata->sram_data_buf = dma_alloc_coherent(&pci->dev,
  80. ACP_DEFAULT_SRAM_LENGTH,
  81. &adata->sram_dma_addr,
  82. GFP_KERNEL);
  83. if (!adata->sram_data_buf)
  84. return -ENOMEM;
  85. }
  86. adata->fw_sram_data_bin_size = size + offset;
  87. dest = adata->sram_data_buf + offset;
  88. adata->is_sram_in_use = true;
  89. break;
  90. default:
  91. dev_err(sdev->dev, "bad blk type 0x%x\n", blk_type);
  92. return -EINVAL;
  93. }
  94. memcpy(dest, src, size);
  95. return 0;
  96. }
  97. EXPORT_SYMBOL_NS(acp_dsp_block_write, "SND_SOC_SOF_AMD_COMMON");
  98. int acp_get_bar_index(struct snd_sof_dev *sdev, u32 type)
  99. {
  100. return type;
  101. }
  102. EXPORT_SYMBOL_NS(acp_get_bar_index, "SND_SOC_SOF_AMD_COMMON");
  103. static void configure_pte_for_fw_loading(int type, int num_pages, struct acp_dev_data *adata)
  104. {
  105. struct snd_sof_dev *sdev = adata->dev;
  106. const struct sof_amd_acp_desc *desc = get_chip_info(sdev->pdata);
  107. unsigned int low, high;
  108. dma_addr_t addr;
  109. u16 page_idx;
  110. u32 offset;
  111. switch (type) {
  112. case FW_BIN:
  113. offset = FW_BIN_PTE_OFFSET;
  114. addr = adata->sha_dma_addr;
  115. break;
  116. case FW_DATA_BIN:
  117. offset = adata->fw_bin_page_count * 8;
  118. addr = adata->dma_addr;
  119. break;
  120. case FW_SRAM_DATA_BIN:
  121. offset = (adata->fw_bin_page_count + ACP_DRAM_PAGE_COUNT) * 8;
  122. addr = adata->sram_dma_addr;
  123. break;
  124. default:
  125. dev_err(sdev->dev, "Invalid data type %x\n", type);
  126. return;
  127. }
  128. /* Group Enable */
  129. snd_sof_dsp_write(sdev, ACP_DSP_BAR, ACPAXI2AXI_ATU_BASE_ADDR_GRP_1,
  130. desc->sram_pte_offset | BIT(31));
  131. snd_sof_dsp_write(sdev, ACP_DSP_BAR, ACPAXI2AXI_ATU_PAGE_SIZE_GRP_1,
  132. PAGE_SIZE_4K_ENABLE);
  133. for (page_idx = 0; page_idx < num_pages; page_idx++) {
  134. low = lower_32_bits(addr);
  135. high = upper_32_bits(addr);
  136. snd_sof_dsp_write(sdev, ACP_DSP_BAR, ACP_SCRATCH_REG_0 + offset, low);
  137. high |= BIT(31);
  138. snd_sof_dsp_write(sdev, ACP_DSP_BAR, ACP_SCRATCH_REG_0 + offset + 4, high);
  139. offset += 8;
  140. addr += PAGE_SIZE;
  141. }
  142. /* Flush ATU Cache after PTE Update */
  143. snd_sof_dsp_write(sdev, ACP_DSP_BAR, ACPAXI2AXI_ATU_CTRL, ACP_ATU_CACHE_INVALID);
  144. }
  145. /* pre fw run operations */
  146. int acp_dsp_pre_fw_run(struct snd_sof_dev *sdev)
  147. {
  148. struct pci_dev *pci = to_pci_dev(sdev->dev);
  149. const struct sof_amd_acp_desc *desc = get_chip_info(sdev->pdata);
  150. struct acp_dev_data *adata;
  151. unsigned int src_addr, size_fw, dest_addr;
  152. u32 page_count, dma_size;
  153. int ret;
  154. adata = sdev->pdata->hw_pdata;
  155. if (adata->quirks && adata->quirks->signed_fw_image)
  156. size_fw = adata->fw_bin_size - ACP_FIRMWARE_SIGNATURE;
  157. else
  158. size_fw = adata->fw_bin_size;
  159. page_count = PAGE_ALIGN(size_fw) >> PAGE_SHIFT;
  160. adata->fw_bin_page_count = page_count;
  161. configure_pte_for_fw_loading(FW_BIN, page_count, adata);
  162. ret = configure_and_run_sha_dma(adata, adata->bin_buf, ACP_SYSTEM_MEMORY_WINDOW,
  163. ACP_IRAM_BASE_ADDRESS, size_fw);
  164. if (ret < 0) {
  165. dev_err(sdev->dev, "SHA DMA transfer failed status: %d\n", ret);
  166. return ret;
  167. }
  168. if (adata->is_dram_in_use) {
  169. configure_pte_for_fw_loading(FW_DATA_BIN, ACP_DRAM_PAGE_COUNT, adata);
  170. src_addr = ACP_SYSTEM_MEMORY_WINDOW + (page_count * ACP_PAGE_SIZE);
  171. dest_addr = ACP_DRAM_BASE_ADDRESS;
  172. ret = configure_and_run_dma(adata, src_addr, dest_addr, adata->fw_data_bin_size);
  173. if (ret < 0) {
  174. dev_err(sdev->dev, "acp dma configuration failed: %d\n", ret);
  175. return ret;
  176. }
  177. ret = acp_dma_status(adata, 0);
  178. if (ret < 0)
  179. dev_err(sdev->dev, "acp dma transfer status: %d\n", ret);
  180. }
  181. if (adata->is_sram_in_use) {
  182. configure_pte_for_fw_loading(FW_SRAM_DATA_BIN, ACP_SRAM_PAGE_COUNT, adata);
  183. src_addr = ACP_SYSTEM_MEMORY_WINDOW + ACP_DEFAULT_SRAM_LENGTH +
  184. (page_count * ACP_PAGE_SIZE);
  185. if (adata->pci_rev > ACP63_PCI_ID)
  186. dest_addr = ACP7X_SRAM_BASE_ADDRESS;
  187. else
  188. dest_addr = ACP_SRAM_BASE_ADDRESS;
  189. ret = configure_and_run_dma(adata, src_addr, dest_addr,
  190. adata->fw_sram_data_bin_size);
  191. if (ret < 0) {
  192. dev_err(sdev->dev, "acp dma configuration failed: %d\n", ret);
  193. return ret;
  194. }
  195. ret = acp_dma_status(adata, 0);
  196. if (ret < 0)
  197. dev_err(sdev->dev, "acp dma transfer status: %d\n", ret);
  198. }
  199. if (adata->pci_rev > ACP_RN_PCI_ID) {
  200. /* Cache Window enable */
  201. snd_sof_dsp_write(sdev, ACP_DSP_BAR, ACP_DSP0_CACHE_OFFSET0, desc->sram_pte_offset);
  202. snd_sof_dsp_write(sdev, ACP_DSP_BAR, ACP_DSP0_CACHE_SIZE0, SRAM1_SIZE | BIT(31));
  203. }
  204. /* Free memory once DMA is complete */
  205. dma_size = (PAGE_ALIGN(sdev->basefw.fw->size) >> PAGE_SHIFT) * ACP_PAGE_SIZE;
  206. dma_free_coherent(&pci->dev, dma_size, adata->bin_buf, adata->sha_dma_addr);
  207. adata->bin_buf = NULL;
  208. if (adata->is_dram_in_use) {
  209. dma_free_coherent(&pci->dev, ACP_DEFAULT_DRAM_LENGTH, adata->data_buf,
  210. adata->dma_addr);
  211. adata->data_buf = NULL;
  212. }
  213. if (adata->is_sram_in_use) {
  214. dma_free_coherent(&pci->dev, ACP_DEFAULT_SRAM_LENGTH, adata->sram_data_buf,
  215. adata->sram_dma_addr);
  216. adata->sram_data_buf = NULL;
  217. }
  218. return ret;
  219. }
  220. EXPORT_SYMBOL_NS(acp_dsp_pre_fw_run, "SND_SOC_SOF_AMD_COMMON");
  221. int acp_sof_dsp_run(struct snd_sof_dev *sdev)
  222. {
  223. struct acp_dev_data *adata = sdev->pdata->hw_pdata;
  224. const struct sof_amd_acp_desc *desc = get_chip_info(sdev->pdata);
  225. int val;
  226. snd_sof_dsp_write(sdev, ACP_DSP_BAR, ACP_DSP0_RUNSTALL, ACP_DSP_RUN);
  227. val = snd_sof_dsp_read(sdev, ACP_DSP_BAR, ACP_DSP0_RUNSTALL);
  228. dev_dbg(sdev->dev, "ACP_DSP0_RUNSTALL : 0x%0x\n", val);
  229. /* Some platforms won't support fusion DSP,keep offset zero for no support */
  230. if (desc->fusion_dsp_offset && adata->enable_fw_debug) {
  231. snd_sof_dsp_write(sdev, ACP_DSP_BAR, desc->fusion_dsp_offset, ACP_DSP_RUN);
  232. val = snd_sof_dsp_read(sdev, ACP_DSP_BAR, desc->fusion_dsp_offset);
  233. dev_dbg(sdev->dev, "ACP_DSP0_FUSION_RUNSTALL : 0x%0x\n", val);
  234. }
  235. return 0;
  236. }
  237. EXPORT_SYMBOL_NS(acp_sof_dsp_run, "SND_SOC_SOF_AMD_COMMON");
  238. int acp_sof_load_signed_firmware(struct snd_sof_dev *sdev)
  239. {
  240. struct snd_sof_pdata *plat_data = sdev->pdata;
  241. struct acp_dev_data *adata = plat_data->hw_pdata;
  242. const char *fw_filename;
  243. int ret;
  244. fw_filename = kasprintf(GFP_KERNEL, "%s/%s",
  245. plat_data->fw_filename_prefix,
  246. adata->fw_code_bin);
  247. if (!fw_filename)
  248. return -ENOMEM;
  249. ret = request_firmware(&sdev->basefw.fw, fw_filename, sdev->dev);
  250. if (ret < 0) {
  251. kfree(fw_filename);
  252. dev_err(sdev->dev, "sof signed firmware code bin is missing\n");
  253. return ret;
  254. } else {
  255. dev_dbg(sdev->dev, "request_firmware %s successful\n", fw_filename);
  256. }
  257. kfree(fw_filename);
  258. ret = snd_sof_dsp_block_write(sdev, SOF_FW_BLK_TYPE_IRAM, 0,
  259. (void *)sdev->basefw.fw->data,
  260. sdev->basefw.fw->size);
  261. if (ret < 0)
  262. return ret;
  263. fw_filename = kasprintf(GFP_KERNEL, "%s/%s",
  264. plat_data->fw_filename_prefix,
  265. adata->fw_data_bin);
  266. if (!fw_filename)
  267. return -ENOMEM;
  268. ret = request_firmware(&adata->fw_dbin, fw_filename, sdev->dev);
  269. if (ret < 0) {
  270. kfree(fw_filename);
  271. dev_err(sdev->dev, "sof signed firmware data bin is missing\n");
  272. return ret;
  273. } else {
  274. dev_dbg(sdev->dev, "request_firmware %s successful\n", fw_filename);
  275. }
  276. kfree(fw_filename);
  277. ret = snd_sof_dsp_block_write(sdev, SOF_FW_BLK_TYPE_DRAM, 0,
  278. (void *)adata->fw_dbin->data,
  279. adata->fw_dbin->size);
  280. return ret;
  281. }
  282. EXPORT_SYMBOL_NS(acp_sof_load_signed_firmware, "SND_SOC_SOF_AMD_COMMON");