Commit 0d52c6a1 authored by Rex Zhu's avatar Rex Zhu Committed by Alex Deucher

drm/amdgpu: load mc firware in driver for Polaris.

load mc ucode in driver if VBIOS not loaded
a full version of MC ucode,
Signed-off-by: default avatarRex Zhu <Rex.Zhu@amd.com>
Reviewed-by: default avatarAlex Deucher <alexander.deucher@amd.com>
Reviewed-by: default avatarjimqu <Jim.Qu@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent aacbbc8b
...@@ -253,14 +253,14 @@ static int gmc_v8_0_init_microcode(struct amdgpu_device *adev) ...@@ -253,14 +253,14 @@ static int gmc_v8_0_init_microcode(struct amdgpu_device *adev)
} }
/** /**
* gmc_v8_0_mc_load_microcode - load MC ucode into the hw * gmc_v8_0_tonga_mc_load_microcode - load tonga MC ucode into the hw
* *
* @adev: amdgpu_device pointer * @adev: amdgpu_device pointer
* *
* Load the GDDR MC ucode into the hw (CIK). * Load the GDDR MC ucode into the hw (CIK).
* Returns 0 on success, error on failure. * Returns 0 on success, error on failure.
*/ */
static int gmc_v8_0_mc_load_microcode(struct amdgpu_device *adev) static int gmc_v8_0_tonga_mc_load_microcode(struct amdgpu_device *adev)
{ {
const struct mc_firmware_header_v1_0 *hdr; const struct mc_firmware_header_v1_0 *hdr;
const __le32 *fw_data = NULL; const __le32 *fw_data = NULL;
...@@ -268,9 +268,6 @@ static int gmc_v8_0_mc_load_microcode(struct amdgpu_device *adev) ...@@ -268,9 +268,6 @@ static int gmc_v8_0_mc_load_microcode(struct amdgpu_device *adev)
u32 running; u32 running;
int i, ucode_size, regs_size; int i, ucode_size, regs_size;
if (!adev->mc.fw)
return -EINVAL;
/* Skip MC ucode loading on SR-IOV capable boards. /* Skip MC ucode loading on SR-IOV capable boards.
* vbios does this for us in asic_init in that case. * vbios does this for us in asic_init in that case.
* Skip MC ucode loading on VF, because hypervisor will do that * Skip MC ucode loading on VF, because hypervisor will do that
...@@ -279,6 +276,9 @@ static int gmc_v8_0_mc_load_microcode(struct amdgpu_device *adev) ...@@ -279,6 +276,9 @@ static int gmc_v8_0_mc_load_microcode(struct amdgpu_device *adev)
if (amdgpu_sriov_bios(adev)) if (amdgpu_sriov_bios(adev))
return 0; return 0;
if (!adev->mc.fw)
return -EINVAL;
hdr = (const struct mc_firmware_header_v1_0 *)adev->mc.fw->data; hdr = (const struct mc_firmware_header_v1_0 *)adev->mc.fw->data;
amdgpu_ucode_print_mc_hdr(&hdr->header); amdgpu_ucode_print_mc_hdr(&hdr->header);
...@@ -329,6 +329,76 @@ static int gmc_v8_0_mc_load_microcode(struct amdgpu_device *adev) ...@@ -329,6 +329,76 @@ static int gmc_v8_0_mc_load_microcode(struct amdgpu_device *adev)
return 0; return 0;
} }
static int gmc_v8_0_polaris_mc_load_microcode(struct amdgpu_device *adev)
{
const struct mc_firmware_header_v1_0 *hdr;
const __le32 *fw_data = NULL;
const __le32 *io_mc_regs = NULL;
u32 data, vbios_version;
int i, ucode_size, regs_size;
/* Skip MC ucode loading on SR-IOV capable boards.
* vbios does this for us in asic_init in that case.
* Skip MC ucode loading on VF, because hypervisor will do that
* for this adaptor.
*/
if (amdgpu_sriov_bios(adev))
return 0;
WREG32(mmMC_SEQ_IO_DEBUG_INDEX, 0x9F);
data = RREG32(mmMC_SEQ_IO_DEBUG_DATA);
vbios_version = data & 0xf;
if (vbios_version == 0)
return 0;
if (!adev->mc.fw)
return -EINVAL;
hdr = (const struct mc_firmware_header_v1_0 *)adev->mc.fw->data;
amdgpu_ucode_print_mc_hdr(&hdr->header);
adev->mc.fw_version = le32_to_cpu(hdr->header.ucode_version);
regs_size = le32_to_cpu(hdr->io_debug_size_bytes) / (4 * 2);
io_mc_regs = (const __le32 *)
(adev->mc.fw->data + le32_to_cpu(hdr->io_debug_array_offset_bytes));
ucode_size = le32_to_cpu(hdr->header.ucode_size_bytes) / 4;
fw_data = (const __le32 *)
(adev->mc.fw->data + le32_to_cpu(hdr->header.ucode_array_offset_bytes));
data = RREG32(mmMC_SEQ_MISC0);
data &= ~(0x40);
WREG32(mmMC_SEQ_MISC0, data);
/* load mc io regs */
for (i = 0; i < regs_size; i++) {
WREG32(mmMC_SEQ_IO_DEBUG_INDEX, le32_to_cpup(io_mc_regs++));
WREG32(mmMC_SEQ_IO_DEBUG_DATA, le32_to_cpup(io_mc_regs++));
}
WREG32(mmMC_SEQ_SUP_CNTL, 0x00000008);
WREG32(mmMC_SEQ_SUP_CNTL, 0x00000010);
/* load the MC ucode */
for (i = 0; i < ucode_size; i++)
WREG32(mmMC_SEQ_SUP_PGM, le32_to_cpup(fw_data++));
/* put the engine back into the active state */
WREG32(mmMC_SEQ_SUP_CNTL, 0x00000008);
WREG32(mmMC_SEQ_SUP_CNTL, 0x00000004);
WREG32(mmMC_SEQ_SUP_CNTL, 0x00000001);
/* wait for training to complete */
for (i = 0; i < adev->usec_timeout; i++) {
data = RREG32(mmMC_SEQ_MISC0);
if (data & 0x80)
break;
udelay(1);
}
return 0;
}
static void gmc_v8_0_vram_gtt_location(struct amdgpu_device *adev, static void gmc_v8_0_vram_gtt_location(struct amdgpu_device *adev,
struct amdgpu_mc *mc) struct amdgpu_mc *mc)
{ {
...@@ -1095,7 +1165,15 @@ static int gmc_v8_0_hw_init(void *handle) ...@@ -1095,7 +1165,15 @@ static int gmc_v8_0_hw_init(void *handle)
gmc_v8_0_mc_program(adev); gmc_v8_0_mc_program(adev);
if (adev->asic_type == CHIP_TONGA) { if (adev->asic_type == CHIP_TONGA) {
r = gmc_v8_0_mc_load_microcode(adev); r = gmc_v8_0_tonga_mc_load_microcode(adev);
if (r) {
DRM_ERROR("Failed to load MC firmware!\n");
return r;
}
} else if (adev->asic_type == CHIP_POLARIS11 ||
adev->asic_type == CHIP_POLARIS10 ||
adev->asic_type == CHIP_POLARIS12) {
r = gmc_v8_0_polaris_mc_load_microcode(adev);
if (r) { if (r) {
DRM_ERROR("Failed to load MC firmware!\n"); DRM_ERROR("Failed to load MC firmware!\n");
return r; return r;
......
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