xref: /linux/sound/soc/sof/amd/acp-loader.c (revision 59e6295fac26b8e85c1ea859cdd89fa1e47519d7)
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 /*
11  * Hardware interface for ACP DSP Firmware binaries loader
12  */
13 
14 #include <linux/firmware.h>
15 #include <linux/module.h>
16 #include <linux/pci.h>
17 #include <linux/unaligned.h>
18 
19 #include "../ops.h"
20 #include "acp-dsp-offset.h"
21 #include "acp.h"
22 
23 #define FW_BIN			0
24 #define FW_DATA_BIN		1
25 #define FW_SRAM_DATA_BIN	2
26 
27 #define FW_BIN_PTE_OFFSET	0x00
28 #define FW_DATA_BIN_PTE_OFFSET	0x08
29 
30 #define ACP_DSP_RUN	0x00
31 
32 int acp_dsp_block_read(struct snd_sof_dev *sdev, enum snd_sof_fw_blk_type blk_type,
33 		       u32 offset, void *dest, size_t size)
34 {
35 	const struct sof_amd_acp_desc *desc = get_chip_info(sdev->pdata);
36 	switch (blk_type) {
37 	case SOF_FW_BLK_TYPE_SRAM:
38 		offset = offset - desc->sram_pte_offset;
39 		memcpy_from_scratch(sdev, offset, dest, size);
40 		break;
41 	default:
42 		dev_err(sdev->dev, "bad blk type 0x%x\n", blk_type);
43 		return -EINVAL;
44 	}
45 
46 	return 0;
47 }
48 EXPORT_SYMBOL_NS(acp_dsp_block_read, "SND_SOC_SOF_AMD_COMMON");
49 
50 int acp_dsp_block_write(struct snd_sof_dev *sdev, enum snd_sof_fw_blk_type blk_type,
51 			u32 offset, void *src, size_t size)
52 {
53 	struct pci_dev *pci = to_pci_dev(sdev->dev);
54 	struct acp_dev_data *adata;
55 	void *dest;
56 	u32 dma_size, page_count;
57 	unsigned int size_fw;
58 
59 	adata = sdev->pdata->hw_pdata;
60 
61 	switch (blk_type) {
62 	case SOF_FW_BLK_TYPE_IRAM:
63 		if (!adata->bin_buf) {
64 			size_fw = sdev->basefw.fw->size;
65 			page_count = PAGE_ALIGN(size_fw) >> PAGE_SHIFT;
66 			dma_size = page_count * ACP_PAGE_SIZE;
67 			adata->bin_buf = dma_alloc_coherent(&pci->dev, dma_size,
68 							    &adata->sha_dma_addr,
69 							    GFP_KERNEL);
70 			if (!adata->bin_buf)
71 				return -ENOMEM;
72 		}
73 		adata->fw_bin_size = size + offset;
74 		dest = adata->bin_buf + offset;
75 		break;
76 	case SOF_FW_BLK_TYPE_DRAM:
77 		if (!adata->data_buf) {
78 			adata->data_buf = dma_alloc_coherent(&pci->dev,
79 							     ACP_DEFAULT_DRAM_LENGTH,
80 							     &adata->dma_addr,
81 							     GFP_KERNEL);
82 			if (!adata->data_buf)
83 				return -ENOMEM;
84 		}
85 		dest = adata->data_buf + offset;
86 		adata->fw_data_bin_size = size + offset;
87 		adata->is_dram_in_use = true;
88 		break;
89 	case SOF_FW_BLK_TYPE_SRAM:
90 		if (!adata->sram_data_buf) {
91 			adata->sram_data_buf = dma_alloc_coherent(&pci->dev,
92 								  ACP_DEFAULT_SRAM_LENGTH,
93 								  &adata->sram_dma_addr,
94 								  GFP_KERNEL);
95 			if (!adata->sram_data_buf)
96 				return -ENOMEM;
97 		}
98 		adata->fw_sram_data_bin_size = size + offset;
99 		dest = adata->sram_data_buf + offset;
100 		adata->is_sram_in_use = true;
101 		break;
102 	default:
103 		dev_err(sdev->dev, "bad blk type 0x%x\n", blk_type);
104 		return -EINVAL;
105 	}
106 
107 	memcpy(dest, src, size);
108 	return 0;
109 }
110 EXPORT_SYMBOL_NS(acp_dsp_block_write, "SND_SOC_SOF_AMD_COMMON");
111 
112 int acp_get_bar_index(struct snd_sof_dev *sdev, u32 type)
113 {
114 	return type;
115 }
116 EXPORT_SYMBOL_NS(acp_get_bar_index, "SND_SOC_SOF_AMD_COMMON");
117 
118 static void configure_pte_for_fw_loading(int type, int num_pages, struct acp_dev_data *adata)
119 {
120 	struct snd_sof_dev *sdev = adata->dev;
121 	const struct sof_amd_acp_desc *desc = get_chip_info(sdev->pdata);
122 	unsigned int low, high;
123 	dma_addr_t addr;
124 	u16 page_idx;
125 	u32 offset;
126 
127 	switch (type) {
128 	case FW_BIN:
129 		offset = FW_BIN_PTE_OFFSET;
130 		addr = adata->sha_dma_addr;
131 		break;
132 	case FW_DATA_BIN:
133 		offset = adata->fw_bin_page_count * 8;
134 		addr = adata->dma_addr;
135 		break;
136 	case FW_SRAM_DATA_BIN:
137 		offset = (adata->fw_bin_page_count + ACP_DRAM_PAGE_COUNT) * 8;
138 		addr = adata->sram_dma_addr;
139 		break;
140 	default:
141 		dev_err(sdev->dev, "Invalid data type %x\n", type);
142 		return;
143 	}
144 
145 	/* Group Enable */
146 	snd_sof_dsp_write(sdev, ACP_DSP_BAR, ACPAXI2AXI_ATU_BASE_ADDR_GRP_1,
147 			  desc->sram_pte_offset | BIT(31));
148 	snd_sof_dsp_write(sdev, ACP_DSP_BAR, ACPAXI2AXI_ATU_PAGE_SIZE_GRP_1,
149 			  PAGE_SIZE_4K_ENABLE);
150 
151 	for (page_idx = 0; page_idx < num_pages; page_idx++) {
152 		low = lower_32_bits(addr);
153 		high = upper_32_bits(addr);
154 		snd_sof_dsp_write(sdev, ACP_DSP_BAR, ACP_SCRATCH_REG_0 + offset, low);
155 		high |= BIT(31);
156 		snd_sof_dsp_write(sdev, ACP_DSP_BAR, ACP_SCRATCH_REG_0 + offset + 4, high);
157 		offset += 8;
158 		addr += PAGE_SIZE;
159 	}
160 
161 	/* Flush ATU Cache after PTE Update */
162 	snd_sof_dsp_write(sdev, ACP_DSP_BAR, ACPAXI2AXI_ATU_CTRL, ACP_ATU_CACHE_INVALID);
163 }
164 
165 /* pre fw run operations */
166 int acp_dsp_pre_fw_run(struct snd_sof_dev *sdev)
167 {
168 	struct pci_dev *pci = to_pci_dev(sdev->dev);
169 	const struct sof_amd_acp_desc *desc = get_chip_info(sdev->pdata);
170 	struct acp_dev_data *adata;
171 	unsigned int src_addr, size_fw, dest_addr;
172 	u32 page_count, dma_size;
173 	int ret;
174 
175 	adata = sdev->pdata->hw_pdata;
176 
177 	if (adata->pci_rev >= ACP7B_PCI_ID) {
178 		if (adata->acp_sof_signed_firmware_image) {
179 			if (adata->fw_bin_size <= ACP_IMAGE_HEADER_SIZE) {
180 				dev_err(sdev->dev, "Invalid signed firmware size %u\n",
181 					adata->fw_bin_size);
182 				return -EINVAL;
183 			}
184 			size_fw = get_unaligned_le32(adata->bin_buf +
185 						     ACP_IMAGE_HDR_SIZE_FW_SIGNED_OFF);
186 			if (!size_fw ||
187 			    size_fw > adata->fw_bin_size - ACP_IMAGE_HEADER_SIZE) {
188 				dev_err(sdev->dev,
189 					"Invalid signed firmware payload size %u (max %u)\n",
190 					size_fw, adata->fw_bin_size - ACP_IMAGE_HEADER_SIZE);
191 				return -EINVAL;
192 			}
193 			size_fw += ACP_IMAGE_HEADER_SIZE;
194 		} else {
195 			size_fw = adata->fw_bin_size;
196 		}
197 	} else if (adata->quirks && adata->quirks->signed_fw_image) {
198 		size_fw = adata->fw_bin_size - ACP_FIRMWARE_SIGNATURE;
199 	} else {
200 		size_fw = adata->fw_bin_size;
201 	}
202 
203 	page_count = PAGE_ALIGN(size_fw) >> PAGE_SHIFT;
204 	adata->fw_bin_page_count = page_count;
205 
206 	configure_pte_for_fw_loading(FW_BIN, page_count, adata);
207 	ret = configure_and_run_sha_dma(adata, adata->bin_buf, ACP_SYSTEM_MEMORY_WINDOW,
208 					ACP_IRAM_BASE_ADDRESS, size_fw);
209 	if (ret < 0) {
210 		dev_err(sdev->dev, "SHA DMA transfer failed status: %d\n", ret);
211 		return ret;
212 	}
213 	if (adata->is_dram_in_use) {
214 		configure_pte_for_fw_loading(FW_DATA_BIN, ACP_DRAM_PAGE_COUNT, adata);
215 		src_addr = ACP_SYSTEM_MEMORY_WINDOW + (page_count * ACP_PAGE_SIZE);
216 		dest_addr = ACP_DRAM_BASE_ADDRESS;
217 
218 		ret = configure_and_run_dma(adata, src_addr, dest_addr, adata->fw_data_bin_size);
219 		if (ret < 0) {
220 			dev_err(sdev->dev, "acp dma configuration failed: %d\n", ret);
221 			return ret;
222 		}
223 		ret = acp_dma_status(adata, 0);
224 		if (ret < 0)
225 			dev_err(sdev->dev, "acp dma transfer status: %d\n", ret);
226 	}
227 	if (adata->is_sram_in_use) {
228 		configure_pte_for_fw_loading(FW_SRAM_DATA_BIN, ACP_SRAM_PAGE_COUNT, adata);
229 		src_addr = ACP_SYSTEM_MEMORY_WINDOW + ACP_DEFAULT_SRAM_LENGTH +
230 			   (page_count * ACP_PAGE_SIZE);
231 		if (adata->pci_rev > ACP63_PCI_ID)
232 			dest_addr = ACP7X_SRAM_BASE_ADDRESS;
233 		else
234 			dest_addr = ACP_SRAM_BASE_ADDRESS;
235 
236 		ret = configure_and_run_dma(adata, src_addr, dest_addr,
237 					    adata->fw_sram_data_bin_size);
238 		if (ret < 0) {
239 			dev_err(sdev->dev, "acp dma configuration failed: %d\n", ret);
240 			return ret;
241 		}
242 		ret = acp_dma_status(adata, 0);
243 		if (ret < 0)
244 			dev_err(sdev->dev, "acp dma transfer status: %d\n", ret);
245 	}
246 
247 	if (adata->pci_rev > ACP_RN_PCI_ID) {
248 		/* Cache Window enable */
249 		snd_sof_dsp_write(sdev, ACP_DSP_BAR, ACP_DSP0_CACHE_OFFSET0, desc->sram_pte_offset);
250 		snd_sof_dsp_write(sdev, ACP_DSP_BAR, ACP_DSP0_CACHE_SIZE0, SRAM1_SIZE | BIT(31));
251 	}
252 
253 	/* Free memory once DMA is complete */
254 	dma_size =  (PAGE_ALIGN(sdev->basefw.fw->size) >> PAGE_SHIFT) * ACP_PAGE_SIZE;
255 	dma_free_coherent(&pci->dev, dma_size, adata->bin_buf, adata->sha_dma_addr);
256 	adata->bin_buf = NULL;
257 	if (adata->is_dram_in_use) {
258 		dma_free_coherent(&pci->dev, ACP_DEFAULT_DRAM_LENGTH, adata->data_buf,
259 				  adata->dma_addr);
260 		adata->data_buf = NULL;
261 	}
262 	if (adata->is_sram_in_use) {
263 		dma_free_coherent(&pci->dev, ACP_DEFAULT_SRAM_LENGTH, adata->sram_data_buf,
264 				  adata->sram_dma_addr);
265 		adata->sram_data_buf = NULL;
266 	}
267 	return ret;
268 }
269 EXPORT_SYMBOL_NS(acp_dsp_pre_fw_run, "SND_SOC_SOF_AMD_COMMON");
270 
271 int acp_sof_dsp_run(struct snd_sof_dev *sdev)
272 {
273 	struct acp_dev_data *adata = sdev->pdata->hw_pdata;
274 	const struct sof_amd_acp_desc *desc = get_chip_info(sdev->pdata);
275 	int val;
276 
277 	snd_sof_dsp_write(sdev, ACP_DSP_BAR, ACP_DSP0_RUNSTALL, ACP_DSP_RUN);
278 	val = snd_sof_dsp_read(sdev, ACP_DSP_BAR, ACP_DSP0_RUNSTALL);
279 	dev_dbg(sdev->dev, "ACP_DSP0_RUNSTALL : 0x%0x\n", val);
280 
281 	/* Some platforms won't support fusion DSP,keep offset zero for no support */
282 	if (desc->fusion_dsp_offset && adata->enable_fw_debug) {
283 		snd_sof_dsp_write(sdev, ACP_DSP_BAR, desc->fusion_dsp_offset, ACP_DSP_RUN);
284 		val = snd_sof_dsp_read(sdev, ACP_DSP_BAR, desc->fusion_dsp_offset);
285 		dev_dbg(sdev->dev, "ACP_DSP0_FUSION_RUNSTALL : 0x%0x\n", val);
286 	}
287 	return 0;
288 }
289 EXPORT_SYMBOL_NS(acp_sof_dsp_run, "SND_SOC_SOF_AMD_COMMON");
290 
291 int acp_sof_load_signed_firmware(struct snd_sof_dev *sdev)
292 {
293 	struct snd_sof_pdata *plat_data = sdev->pdata;
294 	struct acp_dev_data *adata = plat_data->hw_pdata;
295 	const char *fw_filename;
296 	int ret;
297 
298 	fw_filename = kasprintf(GFP_KERNEL, "%s/%s",
299 				plat_data->fw_filename_prefix,
300 				adata->fw_code_bin);
301 	if (!fw_filename)
302 		return -ENOMEM;
303 
304 	ret = request_firmware(&sdev->basefw.fw, fw_filename, sdev->dev);
305 	if (ret < 0) {
306 		kfree(fw_filename);
307 		dev_err(sdev->dev, "sof signed firmware code bin is missing\n");
308 		return ret;
309 	} else {
310 		dev_dbg(sdev->dev, "request_firmware %s successful\n", fw_filename);
311 	}
312 	kfree(fw_filename);
313 
314 	ret = snd_sof_dsp_block_write(sdev, SOF_FW_BLK_TYPE_IRAM, 0,
315 				      (void *)sdev->basefw.fw->data,
316 				      sdev->basefw.fw->size);
317 	if (ret < 0)
318 		return ret;
319 
320 	fw_filename = kasprintf(GFP_KERNEL, "%s/%s",
321 				plat_data->fw_filename_prefix,
322 				adata->fw_data_bin);
323 	if (!fw_filename)
324 		return -ENOMEM;
325 
326 	ret = request_firmware(&adata->fw_dbin, fw_filename, sdev->dev);
327 	if (ret < 0) {
328 		kfree(fw_filename);
329 		dev_err(sdev->dev, "sof signed firmware data bin is missing\n");
330 		return ret;
331 
332 	} else {
333 		dev_dbg(sdev->dev, "request_firmware %s successful\n", fw_filename);
334 	}
335 	kfree(fw_filename);
336 
337 	if (adata->pci_rev >= ACP7B_PCI_ID)
338 		ret = snd_sof_dsp_block_write(sdev, SOF_FW_BLK_TYPE_SRAM, 0,
339 					      (void *)adata->fw_dbin->data,
340 					      adata->fw_dbin->size);
341 	else
342 		ret = snd_sof_dsp_block_write(sdev, SOF_FW_BLK_TYPE_DRAM, 0,
343 					      (void *)adata->fw_dbin->data,
344 					      adata->fw_dbin->size);
345 	return ret;
346 }
347 EXPORT_SYMBOL_NS(acp_sof_load_signed_firmware, "SND_SOC_SOF_AMD_COMMON");
348