drm/amdgpu: support key database loading for navi10

Starting from navi10, driver should send Key Database Load command
to bootloader before loading sys_drv and sos

Signed-off-by: John Clements <John.Clements@amd.com>
Signed-off-by: Hawking Zhang <Hawking.Zhang@amd.com>
Reviewed-by: Xiaojie Yuan <xiaojie.yuan@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
Hawking Zhang 2019-07-11 00:13:54 +08:00 committed by Alex Deucher
parent 3840fe256a
commit 4298935924
5 changed files with 70 additions and 1 deletions

View File

@ -769,6 +769,15 @@ static int psp_hw_start(struct psp_context *psp)
int ret; int ret;
if (!amdgpu_sriov_vf(adev) || !adev->in_gpu_reset) { if (!amdgpu_sriov_vf(adev) || !adev->in_gpu_reset) {
if (psp->kdb_start_addr &&
(psp->funcs->bootloader_load_kdb != NULL)) {
ret = psp_bootloader_load_kdb(psp);
if (ret) {
DRM_ERROR("PSP load kdb failed!\n");
return ret;
}
}
ret = psp_bootloader_load_sysdrv(psp); ret = psp_bootloader_load_sysdrv(psp);
if (ret) { if (ret) {
DRM_ERROR("PSP load sysdrv failed!\n"); DRM_ERROR("PSP load sysdrv failed!\n");

View File

@ -79,6 +79,7 @@ enum psp_reg_prog_id {
struct psp_funcs struct psp_funcs
{ {
int (*init_microcode)(struct psp_context *psp); int (*init_microcode)(struct psp_context *psp);
int (*bootloader_load_kdb)(struct psp_context *psp);
int (*bootloader_load_sysdrv)(struct psp_context *psp); int (*bootloader_load_sysdrv)(struct psp_context *psp);
int (*bootloader_load_sos)(struct psp_context *psp); int (*bootloader_load_sos)(struct psp_context *psp);
int (*ring_init)(struct psp_context *psp, enum psp_ring_type ring_type); int (*ring_init)(struct psp_context *psp, enum psp_ring_type ring_type);
@ -162,9 +163,11 @@ struct psp_context
uint32_t sys_bin_size; uint32_t sys_bin_size;
uint32_t sos_bin_size; uint32_t sos_bin_size;
uint32_t toc_bin_size; uint32_t toc_bin_size;
uint32_t kdb_bin_size;
uint8_t *sys_start_addr; uint8_t *sys_start_addr;
uint8_t *sos_start_addr; uint8_t *sos_start_addr;
uint8_t *toc_start_addr; uint8_t *toc_start_addr;
uint8_t *kdb_start_addr;
/* tmr buffer */ /* tmr buffer */
struct amdgpu_bo *tmr_bo; struct amdgpu_bo *tmr_bo;
@ -226,6 +229,8 @@ struct amdgpu_psp_funcs {
(psp)->funcs->compare_sram_data((psp), (ucode), (type)) (psp)->funcs->compare_sram_data((psp), (ucode), (type))
#define psp_init_microcode(psp) \ #define psp_init_microcode(psp) \
((psp)->funcs->init_microcode ? (psp)->funcs->init_microcode((psp)) : 0) ((psp)->funcs->init_microcode ? (psp)->funcs->init_microcode((psp)) : 0)
#define psp_bootloader_load_kdb(psp) \
((psp)->funcs->bootloader_load_kdb ? (psp)->funcs->bootloader_load_kdb((psp)) : 0)
#define psp_bootloader_load_sysdrv(psp) \ #define psp_bootloader_load_sysdrv(psp) \
((psp)->funcs->bootloader_load_sysdrv ? (psp)->funcs->bootloader_load_sysdrv((psp)) : 0) ((psp)->funcs->bootloader_load_sysdrv ? (psp)->funcs->bootloader_load_sysdrv((psp)) : 0)
#define psp_bootloader_load_sos(psp) \ #define psp_bootloader_load_sos(psp) \

View File

@ -262,6 +262,12 @@ void amdgpu_ucode_print_psp_hdr(const struct common_firmware_header *hdr)
le32_to_cpu(psp_hdr_v1_1->toc_offset_bytes)); le32_to_cpu(psp_hdr_v1_1->toc_offset_bytes));
DRM_DEBUG("toc_size_bytes: %u\n", DRM_DEBUG("toc_size_bytes: %u\n",
le32_to_cpu(psp_hdr_v1_1->toc_size_bytes)); le32_to_cpu(psp_hdr_v1_1->toc_size_bytes));
DRM_DEBUG("kdb_header_version: %u\n",
le32_to_cpu(psp_hdr_v1_1->kdb_header_version));
DRM_DEBUG("kdb_offset_bytes: %u\n",
le32_to_cpu(psp_hdr_v1_1->kdb_offset_bytes));
DRM_DEBUG("kdb_size_bytes: %u\n",
le32_to_cpu(psp_hdr_v1_1->kdb_size_bytes));
} }
} else { } else {
DRM_ERROR("Unknown PSP ucode version: %u.%u\n", DRM_ERROR("Unknown PSP ucode version: %u.%u\n",

View File

@ -85,6 +85,9 @@ struct psp_firmware_header_v1_1 {
uint32_t toc_header_version; uint32_t toc_header_version;
uint32_t toc_offset_bytes; uint32_t toc_offset_bytes;
uint32_t toc_size_bytes; uint32_t toc_size_bytes;
uint32_t kdb_header_version;
uint32_t kdb_offset_bytes;
uint32_t kdb_size_bytes;
}; };
/* version_major=1, version_minor=0 */ /* version_major=1, version_minor=0 */

View File

@ -103,6 +103,9 @@ static int psp_v11_0_init_microcode(struct psp_context *psp)
adev->psp.toc_bin_size = le32_to_cpu(sos_hdr_v1_1->toc_size_bytes); 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 + adev->psp.toc_start_addr = (uint8_t *)adev->psp.sys_start_addr +
le32_to_cpu(sos_hdr_v1_1->toc_offset_bytes); 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);
} }
break; break;
default: default:
@ -177,6 +180,48 @@ out:
return err; return err;
} }
static int psp_v11_0_bootloader_load_kdb(struct psp_context *psp)
{
int ret;
uint32_t psp_gfxdrv_command_reg = 0;
struct amdgpu_device *adev = psp->adev;
uint32_t sol_reg;
/* Check tOS sign of life register to confirm sys driver and sOS
* are already been loaded.
*/
sol_reg = RREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_81);
if (sol_reg) {
psp->sos_fw_version = RREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_58);
dev_info(adev->dev, "sos fw version = 0x%x.\n", psp->sos_fw_version);
return 0;
}
/* Wait for bootloader to signify that is ready having bit 31 of C2PMSG_35 set to 1 */
ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_35),
0x80000000, 0x80000000, false);
if (ret)
return ret;
memset(psp->fw_pri_buf, 0, PSP_1_MEG);
/* Copy PSP KDB binary to memory */
memcpy(psp->fw_pri_buf, psp->kdb_start_addr, psp->kdb_bin_size);
/* Provide the sys driver to bootloader */
WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_36,
(uint32_t)(psp->fw_pri_mc_addr >> 20));
psp_gfxdrv_command_reg = PSP_BL__LOAD_KEY_DATABASE;
WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_35,
psp_gfxdrv_command_reg);
/* Wait for bootloader to signify that is ready having bit 31 of C2PMSG_35 set to 1*/
ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_35),
0x80000000, 0x80000000, false);
return ret;
}
static int psp_v11_0_bootloader_load_sysdrv(struct psp_context *psp) static int psp_v11_0_bootloader_load_sysdrv(struct psp_context *psp)
{ {
int ret; int ret;
@ -190,7 +235,7 @@ static int psp_v11_0_bootloader_load_sysdrv(struct psp_context *psp)
sol_reg = RREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_81); sol_reg = RREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_81);
if (sol_reg) { if (sol_reg) {
psp->sos_fw_version = RREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_58); psp->sos_fw_version = RREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_58);
printk("sos fw version = 0x%x.\n", psp->sos_fw_version); dev_info(adev->dev, "sos fw version = 0x%x.\n", psp->sos_fw_version);
return 0; return 0;
} }
@ -822,6 +867,7 @@ static int psp_v11_0_rlc_autoload_start(struct psp_context *psp)
static const struct psp_funcs psp_v11_0_funcs = { static const struct psp_funcs psp_v11_0_funcs = {
.init_microcode = psp_v11_0_init_microcode, .init_microcode = psp_v11_0_init_microcode,
.bootloader_load_kdb = psp_v11_0_bootloader_load_kdb,
.bootloader_load_sysdrv = psp_v11_0_bootloader_load_sysdrv, .bootloader_load_sysdrv = psp_v11_0_bootloader_load_sysdrv,
.bootloader_load_sos = psp_v11_0_bootloader_load_sos, .bootloader_load_sos = psp_v11_0_bootloader_load_sos,
.ring_init = psp_v11_0_ring_init, .ring_init = psp_v11_0_ring_init,