File Index
Files and directories
Sign in
FILE

amdgpu_cgs.c

File preview with syntax highlighting.

linux-6.19.14/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c C
  1/*
  2 * Copyright 2015 Advanced Micro Devices, Inc.
  3 *
  4 * Permission is hereby granted, free of charge, to any person obtaining a
  5 * copy of this software and associated documentation files (the "Software"),
  6 * to deal in the Software without restriction, including without limitation
  7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  8 * and/or sell copies of the Software, and to permit persons to whom the
  9 * Software is furnished to do so, subject to the following conditions:
 10 *
 11 * The above copyright notice and this permission notice shall be included in
 12 * all copies or substantial portions of the Software.
 13 *
 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
 18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 20 * OTHER DEALINGS IN THE SOFTWARE.
 21 *
 22 *
 23 */
 24#include <linux/list.h>
 25#include <linux/pci.h>
 26#include <linux/slab.h>
 27
 28#include <linux/firmware.h>
 29#include <drm/amdgpu_drm.h>
 30#include "amdgpu.h"
 31#include "atom.h"
 32#include "amdgpu_ucode.h"
 33
 34struct amdgpu_cgs_device {
 35	struct cgs_device base;
 36	struct amdgpu_device *adev;
 37};
 38
 39#define CGS_FUNC_ADEV							\
 40	struct amdgpu_device *adev =					\
 41		((struct amdgpu_cgs_device *)cgs_device)->adev
 42
 43
 44static uint32_t amdgpu_cgs_read_register(struct cgs_device *cgs_device, unsigned int offset)
 45{
 46	CGS_FUNC_ADEV;
 47	return RREG32(offset);
 48}
 49
 50static void amdgpu_cgs_write_register(struct cgs_device *cgs_device, unsigned int offset,
 51				      uint32_t value)
 52{
 53	CGS_FUNC_ADEV;
 54	WREG32(offset, value);
 55}
 56
 57static uint32_t amdgpu_cgs_read_ind_register(struct cgs_device *cgs_device,
 58					     enum cgs_ind_reg space,
 59					     unsigned int index)
 60{
 61	CGS_FUNC_ADEV;
 62	switch (space) {
 63	case CGS_IND_REG__PCIE:
 64		return RREG32_PCIE(index);
 65	case CGS_IND_REG__SMC:
 66		return RREG32_SMC(index);
 67	case CGS_IND_REG__UVD_CTX:
 68		return RREG32_UVD_CTX(index);
 69	case CGS_IND_REG__DIDT:
 70		return RREG32_DIDT(index);
 71	case CGS_IND_REG_GC_CAC:
 72		return RREG32_GC_CAC(index);
 73	case CGS_IND_REG_SE_CAC:
 74		return RREG32_SE_CAC(index);
 75	case CGS_IND_REG__AUDIO_ENDPT:
 76		DRM_ERROR("audio endpt register access not implemented.\n");
 77		return 0;
 78	default:
 79		BUG();
 80	}
 81	WARN(1, "Invalid indirect register space");
 82	return 0;
 83}
 84
 85static void amdgpu_cgs_write_ind_register(struct cgs_device *cgs_device,
 86					  enum cgs_ind_reg space,
 87					  unsigned int index, uint32_t value)
 88{
 89	CGS_FUNC_ADEV;
 90	switch (space) {
 91	case CGS_IND_REG__PCIE:
 92		return WREG32_PCIE(index, value);
 93	case CGS_IND_REG__SMC:
 94		return WREG32_SMC(index, value);
 95	case CGS_IND_REG__UVD_CTX:
 96		return WREG32_UVD_CTX(index, value);
 97	case CGS_IND_REG__DIDT:
 98		return WREG32_DIDT(index, value);
 99	case CGS_IND_REG_GC_CAC:
100		return WREG32_GC_CAC(index, value);
101	case CGS_IND_REG_SE_CAC:
102		return WREG32_SE_CAC(index, value);
103	case CGS_IND_REG__AUDIO_ENDPT:
104		DRM_ERROR("audio endpt register access not implemented.\n");
105		return;
106	default:
107		BUG();
108	}
109	WARN(1, "Invalid indirect register space");
110}
111
112static uint32_t fw_type_convert(struct cgs_device *cgs_device, uint32_t fw_type)
113{
114	CGS_FUNC_ADEV;
115	enum AMDGPU_UCODE_ID result = AMDGPU_UCODE_ID_MAXIMUM;
116
117	switch (fw_type) {
118	case CGS_UCODE_ID_SDMA0:
119		result = AMDGPU_UCODE_ID_SDMA0;
120		break;
121	case CGS_UCODE_ID_SDMA1:
122		result = AMDGPU_UCODE_ID_SDMA1;
123		break;
124	case CGS_UCODE_ID_CP_CE:
125		result = AMDGPU_UCODE_ID_CP_CE;
126		break;
127	case CGS_UCODE_ID_CP_PFP:
128		result = AMDGPU_UCODE_ID_CP_PFP;
129		break;
130	case CGS_UCODE_ID_CP_ME:
131		result = AMDGPU_UCODE_ID_CP_ME;
132		break;
133	case CGS_UCODE_ID_CP_MEC:
134	case CGS_UCODE_ID_CP_MEC_JT1:
135		result = AMDGPU_UCODE_ID_CP_MEC1;
136		break;
137	case CGS_UCODE_ID_CP_MEC_JT2:
138		/* for VI. JT2 should be the same as JT1, because:
139			1, MEC2 and MEC1 use exactly same FW.
140			2, JT2 is not pached but JT1 is.
141		*/
142		if (adev->asic_type >= CHIP_TOPAZ)
143			result = AMDGPU_UCODE_ID_CP_MEC1;
144		else
145			result = AMDGPU_UCODE_ID_CP_MEC2;
146		break;
147	case CGS_UCODE_ID_RLC_G:
148		result = AMDGPU_UCODE_ID_RLC_G;
149		break;
150	case CGS_UCODE_ID_STORAGE:
151		result = AMDGPU_UCODE_ID_STORAGE;
152		break;
153	default:
154		DRM_ERROR("Firmware type not supported\n");
155	}
156	return result;
157}
158
159static uint16_t amdgpu_get_firmware_version(struct cgs_device *cgs_device,
160					enum cgs_ucode_id type)
161{
162	CGS_FUNC_ADEV;
163	uint16_t fw_version = 0;
164
165	switch (type) {
166	case CGS_UCODE_ID_SDMA0:
167		fw_version = adev->sdma.instance[0].fw_version;
168		break;
169	case CGS_UCODE_ID_SDMA1:
170		fw_version = adev->sdma.instance[1].fw_version;
171		break;
172	case CGS_UCODE_ID_CP_CE:
173		fw_version = adev->gfx.ce_fw_version;
174		break;
175	case CGS_UCODE_ID_CP_PFP:
176		fw_version = adev->gfx.pfp_fw_version;
177		break;
178	case CGS_UCODE_ID_CP_ME:
179		fw_version = adev->gfx.me_fw_version;
180		break;
181	case CGS_UCODE_ID_CP_MEC:
182		fw_version = adev->gfx.mec_fw_version;
183		break;
184	case CGS_UCODE_ID_CP_MEC_JT1:
185		fw_version = adev->gfx.mec_fw_version;
186		break;
187	case CGS_UCODE_ID_CP_MEC_JT2:
188		fw_version = adev->gfx.mec_fw_version;
189		break;
190	case CGS_UCODE_ID_RLC_G:
191		fw_version = adev->gfx.rlc_fw_version;
192		break;
193	case CGS_UCODE_ID_STORAGE:
194		break;
195	default:
196		DRM_ERROR("firmware type %d do not have version\n", type);
197		break;
198	}
199	return fw_version;
200}
201
202static int amdgpu_cgs_get_firmware_info(struct cgs_device *cgs_device,
203					enum cgs_ucode_id type,
204					struct cgs_firmware_info *info)
205{
206	CGS_FUNC_ADEV;
207
208	if (type != CGS_UCODE_ID_SMU && type != CGS_UCODE_ID_SMU_SK) {
209		uint64_t gpu_addr;
210		uint32_t data_size;
211		const struct gfx_firmware_header_v1_0 *header;
212		enum AMDGPU_UCODE_ID id;
213		struct amdgpu_firmware_info *ucode;
214
215		id = fw_type_convert(cgs_device, type);
216		if (id >= AMDGPU_UCODE_ID_MAXIMUM)
217			return -EINVAL;
218
219		ucode = &adev->firmware.ucode[id];
220		if (ucode->fw == NULL)
221			return -EINVAL;
222
223		gpu_addr  = ucode->mc_addr;
224		header = (const struct gfx_firmware_header_v1_0 *)ucode->fw->data;
225		data_size = le32_to_cpu(header->header.ucode_size_bytes);
226
227		if ((type == CGS_UCODE_ID_CP_MEC_JT1) ||
228		    (type == CGS_UCODE_ID_CP_MEC_JT2)) {
229			gpu_addr += ALIGN(le32_to_cpu(header->header.ucode_size_bytes), PAGE_SIZE);
230			data_size = le32_to_cpu(header->jt_size) << 2;
231		}
232
233		info->kptr = ucode->kaddr;
234		info->image_size = data_size;
235		info->mc_addr = gpu_addr;
236		info->version = (uint16_t)le32_to_cpu(header->header.ucode_version);
237
238		if (type == CGS_UCODE_ID_CP_MEC)
239			info->image_size = le32_to_cpu(header->jt_offset) << 2;
240
241		info->fw_version = amdgpu_get_firmware_version(cgs_device, type);
242		info->feature_version = (uint16_t)le32_to_cpu(header->ucode_feature_version);
243	} else {
244		char fw_name[30] = {0};
245		int err = 0;
246		uint32_t ucode_size;
247		uint32_t ucode_start_address;
248		const uint8_t *src;
249		const struct smc_firmware_header_v1_0 *hdr;
250		const struct common_firmware_header *header;
251		struct amdgpu_firmware_info *ucode = NULL;
252
253		if (!adev->pm.fw) {
254			switch (adev->asic_type) {
255			case CHIP_BONAIRE:
256				if ((adev->pdev->revision == 0x80) ||
257					(adev->pdev->revision == 0x81) ||
258					(adev->pdev->device == 0x665f)) {
259					info->is_kicker = true;
260					strscpy(fw_name, "amdgpu/bonaire_k_smc.bin");
261				} else {
262					strscpy(fw_name, "amdgpu/bonaire_smc.bin");
263				}
264				break;
265			case CHIP_HAWAII:
266				if (adev->pdev->revision == 0x80) {
267					info->is_kicker = true;
268					strscpy(fw_name, "amdgpu/hawaii_k_smc.bin");
269				} else {
270					strscpy(fw_name, "amdgpu/hawaii_smc.bin");
271				}
272				break;
273			case CHIP_TOPAZ:
274				if (((adev->pdev->device == 0x6900) && (adev->pdev->revision == 0x81)) ||
275				    ((adev->pdev->device == 0x6900) && (adev->pdev->revision == 0x83)) ||
276				    ((adev->pdev->device == 0x6907) && (adev->pdev->revision == 0x87)) ||
277				    ((adev->pdev->device == 0x6900) && (adev->pdev->revision == 0xD1)) ||
278				    ((adev->pdev->device == 0x6900) && (adev->pdev->revision == 0xD3))) {
279					info->is_kicker = true;
280					strscpy(fw_name, "amdgpu/topaz_k_smc.bin");
281				} else
282					strscpy(fw_name, "amdgpu/topaz_smc.bin");
283				break;
284			case CHIP_TONGA:
285				if (((adev->pdev->device == 0x6939) && (adev->pdev->revision == 0xf1)) ||
286				    ((adev->pdev->device == 0x6938) && (adev->pdev->revision == 0xf1))) {
287					info->is_kicker = true;
288					strscpy(fw_name, "amdgpu/tonga_k_smc.bin");
289				} else
290					strscpy(fw_name, "amdgpu/tonga_smc.bin");
291				break;
292			case CHIP_FIJI:
293				strscpy(fw_name, "amdgpu/fiji_smc.bin");
294				break;
295			case CHIP_POLARIS11:
296				if (type == CGS_UCODE_ID_SMU) {
297					if (ASICID_IS_P21(adev->pdev->device, adev->pdev->revision)) {
298						info->is_kicker = true;
299						strscpy(fw_name, "amdgpu/polaris11_k_smc.bin");
300					} else if (ASICID_IS_P31(adev->pdev->device, adev->pdev->revision)) {
301						info->is_kicker = true;
302						strscpy(fw_name, "amdgpu/polaris11_k2_smc.bin");
303					} else {
304						strscpy(fw_name, "amdgpu/polaris11_smc.bin");
305					}
306				} else if (type == CGS_UCODE_ID_SMU_SK) {
307					strscpy(fw_name, "amdgpu/polaris11_smc_sk.bin");
308				}
309				break;
310			case CHIP_POLARIS10:
311				if (type == CGS_UCODE_ID_SMU) {
312					if (ASICID_IS_P20(adev->pdev->device, adev->pdev->revision)) {
313						info->is_kicker = true;
314						strscpy(fw_name, "amdgpu/polaris10_k_smc.bin");
315					} else if (ASICID_IS_P30(adev->pdev->device, adev->pdev->revision)) {
316						info->is_kicker = true;
317						strscpy(fw_name, "amdgpu/polaris10_k2_smc.bin");
318					} else {
319						strscpy(fw_name, "amdgpu/polaris10_smc.bin");
320					}
321				} else if (type == CGS_UCODE_ID_SMU_SK) {
322					strscpy(fw_name, "amdgpu/polaris10_smc_sk.bin");
323				}
324				break;
325			case CHIP_POLARIS12:
326				if (ASICID_IS_P23(adev->pdev->device, adev->pdev->revision)) {
327					info->is_kicker = true;
328					strscpy(fw_name, "amdgpu/polaris12_k_smc.bin");
329				} else {
330					strscpy(fw_name, "amdgpu/polaris12_smc.bin");
331				}
332				break;
333			case CHIP_VEGAM:
334				strscpy(fw_name, "amdgpu/vegam_smc.bin");
335				break;
336			case CHIP_VEGA10:
337				if ((adev->pdev->device == 0x687f) &&
338					((adev->pdev->revision == 0xc0) ||
339					(adev->pdev->revision == 0xc1) ||
340					(adev->pdev->revision == 0xc3)))
341					strscpy(fw_name, "amdgpu/vega10_acg_smc.bin");
342				else
343					strscpy(fw_name, "amdgpu/vega10_smc.bin");
344				break;
345			case CHIP_VEGA12:
346				strscpy(fw_name, "amdgpu/vega12_smc.bin");
347				break;
348			case CHIP_VEGA20:
349				strscpy(fw_name, "amdgpu/vega20_smc.bin");
350				break;
351			default:
352				DRM_ERROR("SMC firmware not supported\n");
353				return -EINVAL;
354			}
355
356			err = amdgpu_ucode_request(adev, &adev->pm.fw,
357						   AMDGPU_UCODE_REQUIRED,
358						   "%s", fw_name);
359			if (err) {
360				DRM_ERROR("Failed to load firmware \"%s\"", fw_name);
361				amdgpu_ucode_release(&adev->pm.fw);
362				return err;
363			}
364
365			if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) {
366				ucode = &adev->firmware.ucode[AMDGPU_UCODE_ID_SMC];
367				ucode->ucode_id = AMDGPU_UCODE_ID_SMC;
368				ucode->fw = adev->pm.fw;
369				header = (const struct common_firmware_header *)ucode->fw->data;
370				adev->firmware.fw_size +=
371					ALIGN(le32_to_cpu(header->ucode_size_bytes), PAGE_SIZE);
372			}
373		}
374
375		hdr = (const struct smc_firmware_header_v1_0 *)	adev->pm.fw->data;
376		amdgpu_ucode_print_smc_hdr(&hdr->header);
377		adev->pm.fw_version = le32_to_cpu(hdr->header.ucode_version);
378		ucode_size = le32_to_cpu(hdr->header.ucode_size_bytes);
379		ucode_start_address = le32_to_cpu(hdr->ucode_start_addr);
380		src = (const uint8_t *)(adev->pm.fw->data +
381		       le32_to_cpu(hdr->header.ucode_array_offset_bytes));
382
383		info->version = adev->pm.fw_version;
384		info->image_size = ucode_size;
385		info->ucode_start_address = ucode_start_address;
386		info->kptr = (void *)src;
387	}
388	return 0;
389}
390
391static const struct cgs_ops amdgpu_cgs_ops = {
392	.read_register = amdgpu_cgs_read_register,
393	.write_register = amdgpu_cgs_write_register,
394	.read_ind_register = amdgpu_cgs_read_ind_register,
395	.write_ind_register = amdgpu_cgs_write_ind_register,
396	.get_firmware_info = amdgpu_cgs_get_firmware_info,
397};
398
399struct cgs_device *amdgpu_cgs_create_device(struct amdgpu_device *adev)
400{
401	struct amdgpu_cgs_device *cgs_device =
402		kmalloc(sizeof(*cgs_device), GFP_KERNEL);
403
404	if (!cgs_device) {
405		DRM_ERROR("Couldn't allocate CGS device structure\n");
406		return NULL;
407	}
408
409	cgs_device->base.ops = &amdgpu_cgs_ops;
410	cgs_device->adev = adev;
411
412	return (struct cgs_device *)cgs_device;
413}
414
415void amdgpu_cgs_destroy_device(struct cgs_device *cgs_device)
416{
417	kfree(cgs_device);
418}
~/ Read-only file preview.