[PATCH] drm/amdgpu:common ta binary handling
Mangesh Gadre
Mangesh.Gadre at amd.com
Fri Oct 6 09:33:42 UTC 2023
Support handling common TA binary for dGPUs and APUs
Signed-off-by: Mangesh Gadre <Mangesh.Gadre at amd.com>
Reviewed-by: Lijo Lazar <lijo.lazar at amd.com>
---
drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c | 85 ++++++++++++++++++++---
drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h | 16 +++++
2 files changed, 90 insertions(+), 11 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
index 72ee66db182c..72796671dd2a 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
@@ -3279,17 +3279,12 @@ int psp_init_sos_microcode(struct psp_context *psp, const char *chip_name)
static int parse_ta_bin_descriptor(struct psp_context *psp,
const struct psp_fw_bin_desc *desc,
- const struct ta_firmware_header_v2_0 *ta_hdr)
+ uint8_t *ucode_start_addr)
{
- uint8_t *ucode_start_addr = NULL;
- if (!psp || !desc || !ta_hdr)
+ if (!psp || !desc || !ucode_start_addr)
return -EINVAL;
- ucode_start_addr = (uint8_t *)ta_hdr +
- le32_to_cpu(desc->offset_bytes) +
- le32_to_cpu(ta_hdr->header.ucode_array_offset_bytes);
-
switch (desc->fw_type) {
case TA_FW_TYPE_PSP_ASD:
psp->asd_context.bin_desc.fw_version = le32_to_cpu(desc->fw_version);
@@ -3397,11 +3392,17 @@ static int parse_ta_v2_microcode(struct psp_context *psp)
{
const struct ta_firmware_header_v2_0 *ta_hdr;
struct amdgpu_device *adev = psp->adev;
+ struct psp_fw_bin_desc *desc = NULL;
int err = 0;
int ta_index = 0;
+ uint8_t *ucode_array_start = NULL;
+ uint8_t *ucode_start_addr = NULL;
ta_hdr = (const struct ta_firmware_header_v2_0 *)adev->psp.ta_fw->data;
+ ucode_array_start = (uint8_t *)ta_hdr +
+ le32_to_cpu(ta_hdr->header.ucode_array_offset_bytes);
+
if (le16_to_cpu(ta_hdr->header.header_version_major) != 2)
return -EINVAL;
@@ -3411,9 +3412,13 @@ static int parse_ta_v2_microcode(struct psp_context *psp)
}
for (ta_index = 0; ta_index < le32_to_cpu(ta_hdr->ta_fw_bin_count); ta_index++) {
- err = parse_ta_bin_descriptor(psp,
- &ta_hdr->ta_fw_bin[ta_index],
- ta_hdr);
+
+ desc = (struct psp_fw_bin_desc *)&ta_hdr->ta_fw_bin[ta_index];
+
+ ucode_start_addr = ucode_array_start +
+ le32_to_cpu(desc->offset_bytes);
+
+ err = parse_ta_bin_descriptor(psp, desc, ucode_start_addr);
if (err)
return err;
}
@@ -3421,6 +3426,61 @@ static int parse_ta_v2_microcode(struct psp_context *psp)
return 0;
}
+#define FW_VALID_DGPU 0x00000002
+#define FW_VALID_APU 0x00000001
+
+static int parse_ta_v2_1_microcode(struct psp_context *psp)
+{
+ const struct ta_firmware_header_v2_1 *ta_hdr;
+ struct amdgpu_device *adev = psp->adev;
+ struct ta_fw_bin_desc_v1_1 *desc = NULL;
+ struct psp_fw_bin_desc psp_fw_bin_descriptor;
+ int err = 0;
+ int ta_index = 0;
+ uint8_t *ucode_array_start = NULL;
+ uint8_t *ucode_start_addr = NULL;
+
+ ta_hdr = (const struct ta_firmware_header_v2_1 *)adev->psp.ta_fw->data;
+
+ ucode_array_start = (uint8_t *)ta_hdr +
+ le32_to_cpu(ta_hdr->header.ucode_array_offset_bytes);
+
+ if ((le16_to_cpu(ta_hdr->header.header_version_major) != 2) &&
+ (le16_to_cpu(ta_hdr->header.header_version_minor) != 1))
+ return -EINVAL;
+
+ if (le32_to_cpu(ta_hdr->ta_fw_bin_count) >= UCODE_MAX_PSP_PACKAGING) {
+ dev_err(adev->dev, "packed TA count exceeds maximum limit\n");
+ return -EINVAL;
+ }
+
+ for (ta_index = 0; ta_index < le32_to_cpu(ta_hdr->ta_fw_bin_count); ta_index++) {
+
+ desc = (struct ta_fw_bin_desc_v1_1 *)&ta_hdr->ta_fw_bin[ta_index];
+
+ if (((adev->flags & AMD_IS_APU) &&
+ (le32_to_cpu((desc->fw_valid_flags)) & FW_VALID_APU)) ||
+ (!(adev->flags & AMD_IS_APU) &&
+ (le32_to_cpu((desc->fw_valid_flags)) & FW_VALID_DGPU))) {
+
+ ucode_start_addr = ucode_array_start +
+ le32_to_cpu(desc->offset_bytes);
+
+ psp_fw_bin_descriptor.fw_type = desc->fw_type;
+ psp_fw_bin_descriptor.fw_version = desc->fw_version;
+ psp_fw_bin_descriptor.offset_bytes = desc->offset_bytes;
+ psp_fw_bin_descriptor.size_bytes = desc->size_bytes;
+
+ err = parse_ta_bin_descriptor(psp,
+ &psp_fw_bin_descriptor,
+ ucode_start_addr);
+ if (err)
+ return err;
+ }
+ }
+ return 0;
+}
+
int psp_init_ta_microcode(struct psp_context *psp, const char *chip_name)
{
const struct common_firmware_header *hdr;
@@ -3439,7 +3499,10 @@ int psp_init_ta_microcode(struct psp_context *psp, const char *chip_name)
err = parse_ta_v1_microcode(psp);
break;
case 2:
- err = parse_ta_v2_microcode(psp);
+ if (le16_to_cpu(hdr->header_version_minor) == 1)
+ err = parse_ta_v2_1_microcode(psp);
+ else
+ err = parse_ta_v2_microcode(psp);
break;
default:
dev_err(adev->dev, "unsupported TA header version\n");
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h
index ae5fa61d2890..8c6094ee60c0 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h
@@ -157,6 +157,14 @@ enum ta_fw_type {
TA_FW_TYPE_MAX_INDEX,
};
+struct ta_fw_bin_desc_v1_1 {
+ uint32_t fw_type;
+ uint32_t fw_valid_flags;
+ uint32_t fw_version;
+ uint32_t offset_bytes;
+ uint32_t size_bytes;
+};
+
/* version_major=2, version_minor=0 */
struct ta_firmware_header_v2_0 {
struct common_firmware_header header;
@@ -164,6 +172,13 @@ struct ta_firmware_header_v2_0 {
struct psp_fw_bin_desc ta_fw_bin[];
};
+/* version_major=2, version_minor=1 */
+struct ta_firmware_header_v2_1 {
+ struct common_firmware_header header;
+ uint32_t ta_fw_bin_count;
+ struct ta_fw_bin_desc_v1_1 ta_fw_bin[];
+};
+
/* version_major=1, version_minor=0 */
struct gfx_firmware_header_v1_0 {
struct common_firmware_header header;
@@ -419,6 +434,7 @@ union amdgpu_firmware_header {
struct psp_firmware_header_v2_0 psp_v2_0;
struct ta_firmware_header_v1_0 ta;
struct ta_firmware_header_v2_0 ta_v2_0;
+ struct ta_firmware_header_v2_1 ta_v2_1;
struct gfx_firmware_header_v1_0 gfx;
struct gfx_firmware_header_v2_0 gfx_v2_0;
struct rlc_firmware_header_v1_0 rlc;
--
2.34.1
More information about the amd-gfx
mailing list