diff options
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu')
| -rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c | 70 | ||||
| -rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h | 2 | 
2 files changed, 72 insertions, 0 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c index 3656068976d8..730f98aab11b 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c @@ -1876,6 +1876,76 @@ out:  	return err;  } +int psp_init_sos_microcode(struct psp_context *psp, +			   const char *chip_name) +{ +	struct amdgpu_device *adev = psp->adev; +	char fw_name[30]; +	const struct psp_firmware_header_v1_0 *sos_hdr; +	const struct psp_firmware_header_v1_1 *sos_hdr_v1_1; +	const struct psp_firmware_header_v1_2 *sos_hdr_v1_2; +	int err = 0; + +	if (!chip_name) { +		dev_err(adev->dev, "invalid chip name for sos microcode\n"); +		return -EINVAL; +	} + +	snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_sos.bin", chip_name); +	err = request_firmware(&adev->psp.sos_fw, fw_name, adev->dev); +	if (err) +		goto out; + +	err = amdgpu_ucode_validate(adev->psp.sos_fw); +	if (err) +		goto out; + +	sos_hdr = (const struct psp_firmware_header_v1_0 *)adev->psp.sos_fw->data; +	amdgpu_ucode_print_psp_hdr(&sos_hdr->header); + +	switch (sos_hdr->header.header_version_major) { +	case 1: +		adev->psp.sos_fw_version = le32_to_cpu(sos_hdr->header.ucode_version); +		adev->psp.sos_feature_version = le32_to_cpu(sos_hdr->ucode_feature_version); +		adev->psp.sos_bin_size = le32_to_cpu(sos_hdr->sos_size_bytes); +		adev->psp.sys_bin_size = le32_to_cpu(sos_hdr->sos_offset_bytes); +		adev->psp.sys_start_addr = (uint8_t *)sos_hdr + +				le32_to_cpu(sos_hdr->header.ucode_array_offset_bytes); +		adev->psp.sos_start_addr = (uint8_t *)adev->psp.sys_start_addr + +				le32_to_cpu(sos_hdr->sos_offset_bytes); +		if (sos_hdr->header.header_version_minor == 1) { +			sos_hdr_v1_1 = (const struct psp_firmware_header_v1_1 *)adev->psp.sos_fw->data; +			adev->psp.toc_bin_size = le32_to_cpu(sos_hdr_v1_1->toc_size_bytes); +			adev->psp.toc_start_addr = (uint8_t *)adev->psp.sys_start_addr + +					le32_to_cpu(sos_hdr_v1_1->toc_offset_bytes); +			adev->psp.kdb_bin_size = le32_to_cpu(sos_hdr_v1_1->kdb_size_bytes); +			adev->psp.kdb_start_addr = (uint8_t *)adev->psp.sys_start_addr + +					le32_to_cpu(sos_hdr_v1_1->kdb_offset_bytes); +		} +		if (sos_hdr->header.header_version_minor == 2) { +			sos_hdr_v1_2 = (const struct psp_firmware_header_v1_2 *)adev->psp.sos_fw->data; +			adev->psp.kdb_bin_size = le32_to_cpu(sos_hdr_v1_2->kdb_size_bytes); +			adev->psp.kdb_start_addr = (uint8_t *)adev->psp.sys_start_addr + +						    le32_to_cpu(sos_hdr_v1_2->kdb_offset_bytes); +		} +		break; +	default: +		dev_err(adev->dev, +			"unsupported psp sos firmware\n"); +		err = -EINVAL; +		goto out; +	} + +	return 0; +out: +	dev_err(adev->dev, +		"failed to init sos firmware\n"); +	release_firmware(adev->psp.sos_fw); +	adev->psp.sos_fw = NULL; + +	return err; +} +  static int psp_set_clockgating_state(void *handle,  				     enum amd_clockgating_state state)  { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h index a763148aecbc..7fcd63d5432c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h @@ -387,4 +387,6 @@ int psp_ring_cmd_submit(struct psp_context *psp,  			int index);  int psp_init_asd_microcode(struct psp_context *psp,  			   const char *chip_name); +int psp_init_sos_microcode(struct psp_context *psp, +			   const char *chip_name);  #endif  | 
