|
|
@@ -253,14 +253,14 @@ out:
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * 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;
|
|
|
@@ -268,9 +268,6 @@ static int gmc_v8_0_mc_load_microcode(struct amdgpu_device *adev)
|
|
|
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
|
|
|
@@ -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);
|
|
|
|
|
|
@@ -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)
|
|
|
{
|
|
|
@@ -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;
|