Skip to content

Commit

Permalink
drm/amdgpu: load mc firware in driver for Polaris.
Browse files Browse the repository at this point in the history
load mc ucode in driver if VBIOS not loaded
a full version of MC ucode,

Signed-off-by: Rex Zhu <[email protected]>
Reviewed-by: Alex Deucher <[email protected]>
Reviewed-by: jimqu <[email protected]>
Signed-off-by: Alex Deucher <[email protected]>
  • Loading branch information
Rex Zhu authored and alexdeucher committed Mar 30, 2017
1 parent aacbbc8 commit 0d52c6a
Showing 1 changed file with 84 additions and 6 deletions.
90 changes: 84 additions & 6 deletions drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c
Original file line number Diff line number Diff line change
Expand Up @@ -253,24 +253,21 @@ 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
*
* Load the GDDR MC ucode into the hw (CIK).
* 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 __le32 *fw_data = NULL;
const __le32 *io_mc_regs = NULL;
u32 running;
int i, ucode_size, regs_size;

if (!adev->mc.fw)
return -EINVAL;

/* 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
Expand All @@ -279,6 +276,9 @@ static int gmc_v8_0_mc_load_microcode(struct amdgpu_device *adev)
if (amdgpu_sriov_bios(adev))
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);

Expand Down Expand Up @@ -329,6 +329,76 @@ static int gmc_v8_0_mc_load_microcode(struct amdgpu_device *adev)
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,
struct amdgpu_mc *mc)
{
Expand Down Expand Up @@ -1095,7 +1165,15 @@ static int gmc_v8_0_hw_init(void *handle)
gmc_v8_0_mc_program(adev);

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) {
DRM_ERROR("Failed to load MC firmware!\n");
return r;
Expand Down

0 comments on commit 0d52c6a

Please sign in to comment.