Commit f8e487ce authored by John Clements's avatar John Clements Committed by Alex Deucher

drm/amdgpu: Added latest PSP FW header

Improved handling for scalling PSP FW binaries
Signed-off-by: default avatarJohn Clements <john.clements@amd.com>
Reviewed-by: default avatarHawking Zhang <Hawking.Zhang@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent b84d029d
...@@ -3024,6 +3024,64 @@ int psp_init_toc_microcode(struct psp_context *psp, ...@@ -3024,6 +3024,64 @@ int psp_init_toc_microcode(struct psp_context *psp,
return err; return err;
} }
static int parse_sos_bin_descriptor(struct psp_context *psp,
const struct psp_fw_bin_desc *desc,
const struct psp_firmware_header_v2_0 *sos_hdr)
{
uint8_t *ucode_start_addr = NULL;
if (!psp || !desc || !sos_hdr)
return -EINVAL;
ucode_start_addr = (uint8_t *)sos_hdr +
le32_to_cpu(desc->offset_bytes) +
le32_to_cpu(sos_hdr->header.ucode_array_offset_bytes);
switch (desc->fw_type) {
case PSP_FW_TYPE_PSP_SOS:
psp->sos.fw_version = le32_to_cpu(desc->fw_version);
psp->sos.feature_version = le32_to_cpu(desc->fw_version);
psp->sos.size_bytes = le32_to_cpu(desc->size_bytes);
psp->sos.start_addr = ucode_start_addr;
break;
case PSP_FW_TYPE_PSP_SYS_DRV:
psp->sys.fw_version = le32_to_cpu(desc->fw_version);
psp->sys.feature_version = le32_to_cpu(desc->fw_version);
psp->sys.size_bytes = le32_to_cpu(desc->size_bytes);
psp->sys.start_addr = ucode_start_addr;
break;
case PSP_FW_TYPE_PSP_KDB:
psp->kdb.fw_version = le32_to_cpu(desc->fw_version);
psp->kdb.feature_version = le32_to_cpu(desc->fw_version);
psp->kdb.size_bytes = le32_to_cpu(desc->size_bytes);
psp->kdb.start_addr = ucode_start_addr;
break;
case PSP_FW_TYPE_PSP_TOC:
psp->toc.fw_version = le32_to_cpu(desc->fw_version);
psp->toc.feature_version = le32_to_cpu(desc->fw_version);
psp->toc.size_bytes = le32_to_cpu(desc->size_bytes);
psp->toc.start_addr = ucode_start_addr;
break;
case PSP_FW_TYPE_PSP_SPL:
psp->spl.fw_version = le32_to_cpu(desc->fw_version);
psp->spl.feature_version = le32_to_cpu(desc->fw_version);
psp->spl.size_bytes = le32_to_cpu(desc->size_bytes);
psp->spl.start_addr = ucode_start_addr;
break;
case PSP_FW_TYPE_PSP_RL:
psp->rl.fw_version = le32_to_cpu(desc->fw_version);
psp->rl.feature_version = le32_to_cpu(desc->fw_version);
psp->rl.size_bytes = le32_to_cpu(desc->size_bytes);
psp->rl.start_addr = ucode_start_addr;
break;
default:
dev_warn(psp->adev->dev, "Unsupported PSP FW type: %d\n", desc->fw_type);
break;
}
return 0;
}
static int psp_init_sos_base_fw(struct amdgpu_device *adev) static int psp_init_sos_base_fw(struct amdgpu_device *adev)
{ {
const struct psp_firmware_header_v1_0 *sos_hdr; const struct psp_firmware_header_v1_0 *sos_hdr;
...@@ -3077,8 +3135,10 @@ int psp_init_sos_microcode(struct psp_context *psp, ...@@ -3077,8 +3135,10 @@ int psp_init_sos_microcode(struct psp_context *psp,
const struct psp_firmware_header_v1_1 *sos_hdr_v1_1; const struct psp_firmware_header_v1_1 *sos_hdr_v1_1;
const struct psp_firmware_header_v1_2 *sos_hdr_v1_2; const struct psp_firmware_header_v1_2 *sos_hdr_v1_2;
const struct psp_firmware_header_v1_3 *sos_hdr_v1_3; const struct psp_firmware_header_v1_3 *sos_hdr_v1_3;
const struct psp_firmware_header_v2_0 *sos_hdr_v2_0;
int err = 0; int err = 0;
uint8_t *ucode_array_start_addr; uint8_t *ucode_array_start_addr;
int fw_index = 0;
if (!chip_name) { if (!chip_name) {
dev_err(adev->dev, "invalid chip name for sos microcode\n"); dev_err(adev->dev, "invalid chip name for sos microcode\n");
...@@ -3136,6 +3196,23 @@ int psp_init_sos_microcode(struct psp_context *psp, ...@@ -3136,6 +3196,23 @@ int psp_init_sos_microcode(struct psp_context *psp,
le32_to_cpu(sos_hdr_v1_3->rl.offset_bytes); le32_to_cpu(sos_hdr_v1_3->rl.offset_bytes);
} }
break; break;
case 2:
sos_hdr_v2_0 = (const struct psp_firmware_header_v2_0 *)adev->psp.sos_fw->data;
if (le32_to_cpu(sos_hdr_v2_0->psp_fw_bin_count) >= UCODE_MAX_PSP_PACKAGING) {
dev_err(adev->dev, "packed SOS count exceeds maximum limit\n");
err = -EINVAL;
goto out;
}
for (fw_index = 0; fw_index < le32_to_cpu(sos_hdr_v2_0->psp_fw_bin_count); fw_index++) {
err = parse_sos_bin_descriptor(psp,
&sos_hdr_v2_0->psp_fw_bin[fw_index],
sos_hdr_v2_0);
if (err)
goto out;
}
break;
default: default:
dev_err(adev->dev, dev_err(adev->dev,
"unsupported psp sos firmware\n"); "unsupported psp sos firmware\n");
...@@ -3154,7 +3231,7 @@ int psp_init_sos_microcode(struct psp_context *psp, ...@@ -3154,7 +3231,7 @@ int psp_init_sos_microcode(struct psp_context *psp,
} }
static int parse_ta_bin_descriptor(struct psp_context *psp, static int parse_ta_bin_descriptor(struct psp_context *psp,
const struct ta_fw_bin_desc *desc, const struct psp_fw_bin_desc *desc,
const struct ta_firmware_header_v2_0 *ta_hdr) const struct ta_firmware_header_v2_0 *ta_hdr)
{ {
uint8_t *ucode_start_addr = NULL; uint8_t *ucode_start_addr = NULL;
...@@ -3242,7 +3319,7 @@ int psp_init_ta_microcode(struct psp_context *psp, ...@@ -3242,7 +3319,7 @@ int psp_init_ta_microcode(struct psp_context *psp,
goto out; goto out;
} }
if (le32_to_cpu(ta_hdr->ta_fw_bin_count) >= UCODE_MAX_TA_PACKAGING) { 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"); dev_err(adev->dev, "packed TA count exceeds maximum limit\n");
err = -EINVAL; err = -EINVAL;
goto out; goto out;
......
...@@ -71,7 +71,7 @@ struct smc_firmware_header_v2_1 { ...@@ -71,7 +71,7 @@ struct smc_firmware_header_v2_1 {
uint32_t pptable_entry_offset; uint32_t pptable_entry_offset;
}; };
struct psp_fw_bin_desc { struct psp_fw_legacy_bin_desc {
uint32_t fw_version; uint32_t fw_version;
uint32_t offset_bytes; uint32_t offset_bytes;
uint32_t size_bytes; uint32_t size_bytes;
...@@ -80,30 +80,54 @@ struct psp_fw_bin_desc { ...@@ -80,30 +80,54 @@ struct psp_fw_bin_desc {
/* version_major=1, version_minor=0 */ /* version_major=1, version_minor=0 */
struct psp_firmware_header_v1_0 { struct psp_firmware_header_v1_0 {
struct common_firmware_header header; struct common_firmware_header header;
struct psp_fw_bin_desc sos; struct psp_fw_legacy_bin_desc sos;
}; };
/* version_major=1, version_minor=1 */ /* version_major=1, version_minor=1 */
struct psp_firmware_header_v1_1 { struct psp_firmware_header_v1_1 {
struct psp_firmware_header_v1_0 v1_0; struct psp_firmware_header_v1_0 v1_0;
struct psp_fw_bin_desc toc; struct psp_fw_legacy_bin_desc toc;
struct psp_fw_bin_desc kdb; struct psp_fw_legacy_bin_desc kdb;
}; };
/* version_major=1, version_minor=2 */ /* version_major=1, version_minor=2 */
struct psp_firmware_header_v1_2 { struct psp_firmware_header_v1_2 {
struct psp_firmware_header_v1_0 v1_0; struct psp_firmware_header_v1_0 v1_0;
struct psp_fw_bin_desc res; struct psp_fw_legacy_bin_desc res;
struct psp_fw_bin_desc kdb; struct psp_fw_legacy_bin_desc kdb;
}; };
/* version_major=1, version_minor=3 */ /* version_major=1, version_minor=3 */
struct psp_firmware_header_v1_3 { struct psp_firmware_header_v1_3 {
struct psp_firmware_header_v1_1 v1_1; struct psp_firmware_header_v1_1 v1_1;
struct psp_fw_bin_desc spl; struct psp_fw_legacy_bin_desc spl;
struct psp_fw_bin_desc rl; struct psp_fw_legacy_bin_desc rl;
struct psp_fw_bin_desc sys_drv_aux; struct psp_fw_legacy_bin_desc sys_drv_aux;
struct psp_fw_bin_desc sos_aux; struct psp_fw_legacy_bin_desc sos_aux;
};
struct psp_fw_bin_desc {
uint32_t fw_type;
uint32_t fw_version;
uint32_t offset_bytes;
uint32_t size_bytes;
};
enum psp_fw_type {
PSP_FW_TYPE_UNKOWN,
PSP_FW_TYPE_PSP_SOS,
PSP_FW_TYPE_PSP_SYS_DRV,
PSP_FW_TYPE_PSP_KDB,
PSP_FW_TYPE_PSP_TOC,
PSP_FW_TYPE_PSP_SPL,
PSP_FW_TYPE_PSP_RL,
};
/* version_major=2, version_minor=0 */
struct psp_firmware_header_v2_0 {
struct common_firmware_header header;
uint32_t psp_fw_bin_count;
struct psp_fw_bin_desc psp_fw_bin[];
}; };
/* version_major=1, version_minor=0 */ /* version_major=1, version_minor=0 */
...@@ -138,18 +162,11 @@ enum ta_fw_type { ...@@ -138,18 +162,11 @@ enum ta_fw_type {
TA_FW_TYPE_MAX_INDEX, TA_FW_TYPE_MAX_INDEX,
}; };
struct ta_fw_bin_desc {
uint32_t fw_type;
uint32_t fw_version;
uint32_t offset_bytes;
uint32_t size_bytes;
};
/* version_major=2, version_minor=0 */ /* version_major=2, version_minor=0 */
struct ta_firmware_header_v2_0 { struct ta_firmware_header_v2_0 {
struct common_firmware_header header; struct common_firmware_header header;
uint32_t ta_fw_bin_count; uint32_t ta_fw_bin_count;
struct ta_fw_bin_desc ta_fw_bin[]; struct psp_fw_bin_desc ta_fw_bin[];
}; };
/* version_major=1, version_minor=0 */ /* version_major=1, version_minor=0 */
...@@ -312,6 +329,7 @@ union amdgpu_firmware_header { ...@@ -312,6 +329,7 @@ union amdgpu_firmware_header {
struct psp_firmware_header_v1_0 psp; struct psp_firmware_header_v1_0 psp;
struct psp_firmware_header_v1_1 psp_v1_1; struct psp_firmware_header_v1_1 psp_v1_1;
struct psp_firmware_header_v1_3 psp_v1_3; struct psp_firmware_header_v1_3 psp_v1_3;
struct psp_firmware_header_v2_0 psp_v2_0;
struct ta_firmware_header_v1_0 ta; struct ta_firmware_header_v1_0 ta;
struct ta_firmware_header_v2_0 ta_v2_0; struct ta_firmware_header_v2_0 ta_v2_0;
struct gfx_firmware_header_v1_0 gfx; struct gfx_firmware_header_v1_0 gfx;
...@@ -326,7 +344,7 @@ union amdgpu_firmware_header { ...@@ -326,7 +344,7 @@ union amdgpu_firmware_header {
uint8_t raw[0x100]; uint8_t raw[0x100];
}; };
#define UCODE_MAX_TA_PACKAGING ((sizeof(union amdgpu_firmware_header) - sizeof(struct common_firmware_header) - 4) / sizeof(struct ta_fw_bin_desc)) #define UCODE_MAX_PSP_PACKAGING ((sizeof(union amdgpu_firmware_header) - sizeof(struct common_firmware_header) - 4) / sizeof(struct psp_fw_bin_desc))
/* /*
* fw loading support * fw loading support
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment