Commit 42989359 authored by Hawking Zhang's avatar Hawking Zhang Committed by Alex Deucher
Browse files

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: default avatarJohn Clements <John.Clements@amd.com>
Signed-off-by: default avatarHawking Zhang <Hawking.Zhang@amd.com>
Reviewed-by: default avatarXiaojie Yuan <xiaojie.yuan@amd.com>
Reviewed-by: default avatarAlex Deucher <alexander.deucher@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 3840fe25
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -769,6 +769,15 @@ static int psp_hw_start(struct psp_context *psp)
	int ret;

	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);
		if (ret) {
			DRM_ERROR("PSP load sysdrv failed!\n");
+5 −0
Original line number Diff line number Diff line
@@ -79,6 +79,7 @@ enum psp_reg_prog_id {
struct psp_funcs
{
	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_sos)(struct psp_context *psp);
	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			sos_bin_size;
	uint32_t			toc_bin_size;
	uint32_t			kdb_bin_size;
	uint8_t				*sys_start_addr;
	uint8_t				*sos_start_addr;
	uint8_t				*toc_start_addr;
	uint8_t				*kdb_start_addr;

	/* tmr buffer */
	struct amdgpu_bo		*tmr_bo;
@@ -226,6 +229,8 @@ struct amdgpu_psp_funcs {
		(psp)->funcs->compare_sram_data((psp), (ucode), (type))
#define psp_init_microcode(psp) \
		((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) \
		((psp)->funcs->bootloader_load_sysdrv ? (psp)->funcs->bootloader_load_sysdrv((psp)) : 0)
#define psp_bootloader_load_sos(psp) \
+6 −0
Original line number Diff line number Diff line
@@ -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));
			DRM_DEBUG("toc_size_bytes: %u\n",
				  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 {
		DRM_ERROR("Unknown PSP ucode version: %u.%u\n",
+3 −0
Original line number Diff line number Diff line
@@ -85,6 +85,9 @@ struct psp_firmware_header_v1_1 {
	uint32_t toc_header_version;
	uint32_t toc_offset_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 */
+47 −1
Original line number Diff line number Diff line
@@ -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_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);
		}
		break;
	default:
@@ -177,6 +180,48 @@ out:
	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)
{
	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);
	if (sol_reg) {
		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;
	}

@@ -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 = {
	.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_sos = psp_v11_0_bootloader_load_sos,
	.ring_init = psp_v11_0_ring_init,