Commit f2c6b0f4 authored by Alex Deucher's avatar Alex Deucher

drm/radeon/cik: Add support for new ucode format (v5)

This adds CIK support for the new ucode format.

v2: add size validation, integrate debug info
v3: add support for MEC2 on KV
v4: fix typos
v4: update to latest format
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 629bd33c
...@@ -213,24 +213,37 @@ int ci_load_smc_ucode(struct radeon_device *rdev, u32 limit) ...@@ -213,24 +213,37 @@ int ci_load_smc_ucode(struct radeon_device *rdev, u32 limit)
if (!rdev->smc_fw) if (!rdev->smc_fw)
return -EINVAL; return -EINVAL;
switch (rdev->family) { if (rdev->new_fw) {
case CHIP_BONAIRE: const struct smc_firmware_header_v1_0 *hdr =
ucode_start_address = BONAIRE_SMC_UCODE_START; (const struct smc_firmware_header_v1_0 *)rdev->smc_fw->data;
ucode_size = BONAIRE_SMC_UCODE_SIZE;
break; radeon_ucode_print_smc_hdr(&hdr->header);
case CHIP_HAWAII:
ucode_start_address = HAWAII_SMC_UCODE_START; ucode_start_address = le32_to_cpu(hdr->ucode_start_addr);
ucode_size = HAWAII_SMC_UCODE_SIZE; ucode_size = le32_to_cpu(hdr->header.ucode_size_bytes);
break; src = (const u8 *)
default: (rdev->smc_fw->data + le32_to_cpu(hdr->header.ucode_array_offset_bytes));
DRM_ERROR("unknown asic in smc ucode loader\n"); } else {
BUG(); switch (rdev->family) {
case CHIP_BONAIRE:
ucode_start_address = BONAIRE_SMC_UCODE_START;
ucode_size = BONAIRE_SMC_UCODE_SIZE;
break;
case CHIP_HAWAII:
ucode_start_address = HAWAII_SMC_UCODE_START;
ucode_size = HAWAII_SMC_UCODE_SIZE;
break;
default:
DRM_ERROR("unknown asic in smc ucode loader\n");
BUG();
}
src = (const u8 *)rdev->smc_fw->data;
} }
if (ucode_size & 3) if (ucode_size & 3)
return -EINVAL; return -EINVAL;
src = (const u8 *)rdev->smc_fw->data;
spin_lock_irqsave(&rdev->smc_idx_lock, flags); spin_lock_irqsave(&rdev->smc_idx_lock, flags);
WREG32(SMC_IND_INDEX_0, ucode_start_address); WREG32(SMC_IND_INDEX_0, ucode_start_address);
WREG32_P(SMC_IND_ACCESS_CNTL, AUTO_INCREMENT_IND_0, ~AUTO_INCREMENT_IND_0); WREG32_P(SMC_IND_ACCESS_CNTL, AUTO_INCREMENT_IND_0, ~AUTO_INCREMENT_IND_0);
......
...@@ -42,6 +42,16 @@ MODULE_FIRMWARE("radeon/BONAIRE_mc2.bin"); ...@@ -42,6 +42,16 @@ MODULE_FIRMWARE("radeon/BONAIRE_mc2.bin");
MODULE_FIRMWARE("radeon/BONAIRE_rlc.bin"); MODULE_FIRMWARE("radeon/BONAIRE_rlc.bin");
MODULE_FIRMWARE("radeon/BONAIRE_sdma.bin"); MODULE_FIRMWARE("radeon/BONAIRE_sdma.bin");
MODULE_FIRMWARE("radeon/BONAIRE_smc.bin"); MODULE_FIRMWARE("radeon/BONAIRE_smc.bin");
MODULE_FIRMWARE("radeon/bonaire_pfp.bin");
MODULE_FIRMWARE("radeon/bonaire_me.bin");
MODULE_FIRMWARE("radeon/bonaire_ce.bin");
MODULE_FIRMWARE("radeon/bonaire_mec.bin");
MODULE_FIRMWARE("radeon/bonaire_mc.bin");
MODULE_FIRMWARE("radeon/bonaire_rlc.bin");
MODULE_FIRMWARE("radeon/bonaire_sdma.bin");
MODULE_FIRMWARE("radeon/bonaire_smc.bin");
MODULE_FIRMWARE("radeon/HAWAII_pfp.bin"); MODULE_FIRMWARE("radeon/HAWAII_pfp.bin");
MODULE_FIRMWARE("radeon/HAWAII_me.bin"); MODULE_FIRMWARE("radeon/HAWAII_me.bin");
MODULE_FIRMWARE("radeon/HAWAII_ce.bin"); MODULE_FIRMWARE("radeon/HAWAII_ce.bin");
...@@ -51,18 +61,45 @@ MODULE_FIRMWARE("radeon/HAWAII_mc2.bin"); ...@@ -51,18 +61,45 @@ MODULE_FIRMWARE("radeon/HAWAII_mc2.bin");
MODULE_FIRMWARE("radeon/HAWAII_rlc.bin"); MODULE_FIRMWARE("radeon/HAWAII_rlc.bin");
MODULE_FIRMWARE("radeon/HAWAII_sdma.bin"); MODULE_FIRMWARE("radeon/HAWAII_sdma.bin");
MODULE_FIRMWARE("radeon/HAWAII_smc.bin"); MODULE_FIRMWARE("radeon/HAWAII_smc.bin");
MODULE_FIRMWARE("radeon/hawaii_pfp.bin");
MODULE_FIRMWARE("radeon/hawaii_me.bin");
MODULE_FIRMWARE("radeon/hawaii_ce.bin");
MODULE_FIRMWARE("radeon/hawaii_mec.bin");
MODULE_FIRMWARE("radeon/hawaii_mc.bin");
MODULE_FIRMWARE("radeon/hawaii_rlc.bin");
MODULE_FIRMWARE("radeon/hawaii_sdma.bin");
MODULE_FIRMWARE("radeon/hawaii_smc.bin");
MODULE_FIRMWARE("radeon/KAVERI_pfp.bin"); MODULE_FIRMWARE("radeon/KAVERI_pfp.bin");
MODULE_FIRMWARE("radeon/KAVERI_me.bin"); MODULE_FIRMWARE("radeon/KAVERI_me.bin");
MODULE_FIRMWARE("radeon/KAVERI_ce.bin"); MODULE_FIRMWARE("radeon/KAVERI_ce.bin");
MODULE_FIRMWARE("radeon/KAVERI_mec.bin"); MODULE_FIRMWARE("radeon/KAVERI_mec.bin");
MODULE_FIRMWARE("radeon/KAVERI_rlc.bin"); MODULE_FIRMWARE("radeon/KAVERI_rlc.bin");
MODULE_FIRMWARE("radeon/KAVERI_sdma.bin"); MODULE_FIRMWARE("radeon/KAVERI_sdma.bin");
MODULE_FIRMWARE("radeon/kaveri_pfp.bin");
MODULE_FIRMWARE("radeon/kaveri_me.bin");
MODULE_FIRMWARE("radeon/kaveri_ce.bin");
MODULE_FIRMWARE("radeon/kaveri_mec.bin");
MODULE_FIRMWARE("radeon/kaveri_mec2.bin");
MODULE_FIRMWARE("radeon/kaveri_rlc.bin");
MODULE_FIRMWARE("radeon/kaveri_sdma.bin");
MODULE_FIRMWARE("radeon/KABINI_pfp.bin"); MODULE_FIRMWARE("radeon/KABINI_pfp.bin");
MODULE_FIRMWARE("radeon/KABINI_me.bin"); MODULE_FIRMWARE("radeon/KABINI_me.bin");
MODULE_FIRMWARE("radeon/KABINI_ce.bin"); MODULE_FIRMWARE("radeon/KABINI_ce.bin");
MODULE_FIRMWARE("radeon/KABINI_mec.bin"); MODULE_FIRMWARE("radeon/KABINI_mec.bin");
MODULE_FIRMWARE("radeon/KABINI_rlc.bin"); MODULE_FIRMWARE("radeon/KABINI_rlc.bin");
MODULE_FIRMWARE("radeon/KABINI_sdma.bin"); MODULE_FIRMWARE("radeon/KABINI_sdma.bin");
MODULE_FIRMWARE("radeon/kabini_pfp.bin");
MODULE_FIRMWARE("radeon/kabini_me.bin");
MODULE_FIRMWARE("radeon/kabini_ce.bin");
MODULE_FIRMWARE("radeon/kabini_mec.bin");
MODULE_FIRMWARE("radeon/kabini_rlc.bin");
MODULE_FIRMWARE("radeon/kabini_sdma.bin");
MODULE_FIRMWARE("radeon/MULLINS_pfp.bin"); MODULE_FIRMWARE("radeon/MULLINS_pfp.bin");
MODULE_FIRMWARE("radeon/MULLINS_me.bin"); MODULE_FIRMWARE("radeon/MULLINS_me.bin");
MODULE_FIRMWARE("radeon/MULLINS_ce.bin"); MODULE_FIRMWARE("radeon/MULLINS_ce.bin");
...@@ -70,6 +107,13 @@ MODULE_FIRMWARE("radeon/MULLINS_mec.bin"); ...@@ -70,6 +107,13 @@ MODULE_FIRMWARE("radeon/MULLINS_mec.bin");
MODULE_FIRMWARE("radeon/MULLINS_rlc.bin"); MODULE_FIRMWARE("radeon/MULLINS_rlc.bin");
MODULE_FIRMWARE("radeon/MULLINS_sdma.bin"); MODULE_FIRMWARE("radeon/MULLINS_sdma.bin");
MODULE_FIRMWARE("radeon/mullins_pfp.bin");
MODULE_FIRMWARE("radeon/mullins_me.bin");
MODULE_FIRMWARE("radeon/mullins_ce.bin");
MODULE_FIRMWARE("radeon/mullins_mec.bin");
MODULE_FIRMWARE("radeon/mullins_rlc.bin");
MODULE_FIRMWARE("radeon/mullins_sdma.bin");
extern int r600_ih_ring_alloc(struct radeon_device *rdev); extern int r600_ih_ring_alloc(struct radeon_device *rdev);
extern void r600_ih_ring_fini(struct radeon_device *rdev); extern void r600_ih_ring_fini(struct radeon_device *rdev);
extern void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_save *save); extern void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_save *save);
...@@ -1760,27 +1804,44 @@ static void cik_srbm_select(struct radeon_device *rdev, ...@@ -1760,27 +1804,44 @@ static void cik_srbm_select(struct radeon_device *rdev,
*/ */
int ci_mc_load_microcode(struct radeon_device *rdev) int ci_mc_load_microcode(struct radeon_device *rdev)
{ {
const __be32 *fw_data; const __be32 *fw_data = NULL;
const __le32 *new_fw_data = NULL;
u32 running, blackout = 0; u32 running, blackout = 0;
u32 *io_mc_regs; u32 *io_mc_regs = NULL;
const __le32 *new_io_mc_regs = NULL;
int i, regs_size, ucode_size; int i, regs_size, ucode_size;
if (!rdev->mc_fw) if (!rdev->mc_fw)
return -EINVAL; return -EINVAL;
ucode_size = rdev->mc_fw->size / 4; if (rdev->new_fw) {
const struct mc_firmware_header_v1_0 *hdr =
(const struct mc_firmware_header_v1_0 *)rdev->mc_fw->data;
switch (rdev->family) { radeon_ucode_print_mc_hdr(&hdr->header);
case CHIP_BONAIRE:
io_mc_regs = (u32 *)&bonaire_io_mc_regs; regs_size = le32_to_cpu(hdr->io_debug_size_bytes) / (4 * 2);
regs_size = BONAIRE_IO_MC_REGS_SIZE; new_io_mc_regs = (const __le32 *)
break; (rdev->mc_fw->data + le32_to_cpu(hdr->io_debug_array_offset_bytes));
case CHIP_HAWAII: ucode_size = le32_to_cpu(hdr->header.ucode_size_bytes) / 4;
io_mc_regs = (u32 *)&hawaii_io_mc_regs; new_fw_data = (const __le32 *)
regs_size = HAWAII_IO_MC_REGS_SIZE; (rdev->mc_fw->data + le32_to_cpu(hdr->header.ucode_array_offset_bytes));
break; } else {
default: ucode_size = rdev->mc_fw->size / 4;
return -EINVAL;
switch (rdev->family) {
case CHIP_BONAIRE:
io_mc_regs = (u32 *)&bonaire_io_mc_regs;
regs_size = BONAIRE_IO_MC_REGS_SIZE;
break;
case CHIP_HAWAII:
io_mc_regs = (u32 *)&hawaii_io_mc_regs;
regs_size = HAWAII_IO_MC_REGS_SIZE;
break;
default:
return -EINVAL;
}
fw_data = (const __be32 *)rdev->mc_fw->data;
} }
running = RREG32(MC_SEQ_SUP_CNTL) & RUN_MASK; running = RREG32(MC_SEQ_SUP_CNTL) & RUN_MASK;
...@@ -1797,13 +1858,21 @@ int ci_mc_load_microcode(struct radeon_device *rdev) ...@@ -1797,13 +1858,21 @@ int ci_mc_load_microcode(struct radeon_device *rdev)
/* load mc io regs */ /* load mc io regs */
for (i = 0; i < regs_size; i++) { for (i = 0; i < regs_size; i++) {
WREG32(MC_SEQ_IO_DEBUG_INDEX, io_mc_regs[(i << 1)]); if (rdev->new_fw) {
WREG32(MC_SEQ_IO_DEBUG_DATA, io_mc_regs[(i << 1) + 1]); WREG32(MC_SEQ_IO_DEBUG_INDEX, le32_to_cpup(new_io_mc_regs++));
WREG32(MC_SEQ_IO_DEBUG_DATA, le32_to_cpup(new_io_mc_regs++));
} else {
WREG32(MC_SEQ_IO_DEBUG_INDEX, io_mc_regs[(i << 1)]);
WREG32(MC_SEQ_IO_DEBUG_DATA, io_mc_regs[(i << 1) + 1]);
}
} }
/* load the MC ucode */ /* load the MC ucode */
fw_data = (const __be32 *)rdev->mc_fw->data; for (i = 0; i < ucode_size; i++) {
for (i = 0; i < ucode_size; i++) if (rdev->new_fw)
WREG32(MC_SEQ_SUP_PGM, be32_to_cpup(fw_data++)); WREG32(MC_SEQ_SUP_PGM, le32_to_cpup(new_fw_data++));
else
WREG32(MC_SEQ_SUP_PGM, be32_to_cpup(fw_data++));
}
/* put the engine back into the active state */ /* put the engine back into the active state */
WREG32(MC_SEQ_SUP_CNTL, 0x00000008); WREG32(MC_SEQ_SUP_CNTL, 0x00000008);
...@@ -1841,17 +1910,21 @@ int ci_mc_load_microcode(struct radeon_device *rdev) ...@@ -1841,17 +1910,21 @@ int ci_mc_load_microcode(struct radeon_device *rdev)
static int cik_init_microcode(struct radeon_device *rdev) static int cik_init_microcode(struct radeon_device *rdev)
{ {
const char *chip_name; const char *chip_name;
const char *new_chip_name;
size_t pfp_req_size, me_req_size, ce_req_size, size_t pfp_req_size, me_req_size, ce_req_size,
mec_req_size, rlc_req_size, mc_req_size = 0, mec_req_size, rlc_req_size, mc_req_size = 0,
sdma_req_size, smc_req_size = 0, mc2_req_size = 0; sdma_req_size, smc_req_size = 0, mc2_req_size = 0;
char fw_name[30]; char fw_name[30];
int new_fw = 0;
int err; int err;
int num_fw;
DRM_DEBUG("\n"); DRM_DEBUG("\n");
switch (rdev->family) { switch (rdev->family) {
case CHIP_BONAIRE: case CHIP_BONAIRE:
chip_name = "BONAIRE"; chip_name = "BONAIRE";
new_chip_name = "bonaire";
pfp_req_size = CIK_PFP_UCODE_SIZE * 4; pfp_req_size = CIK_PFP_UCODE_SIZE * 4;
me_req_size = CIK_ME_UCODE_SIZE * 4; me_req_size = CIK_ME_UCODE_SIZE * 4;
ce_req_size = CIK_CE_UCODE_SIZE * 4; ce_req_size = CIK_CE_UCODE_SIZE * 4;
...@@ -1861,9 +1934,11 @@ static int cik_init_microcode(struct radeon_device *rdev) ...@@ -1861,9 +1934,11 @@ static int cik_init_microcode(struct radeon_device *rdev)
mc2_req_size = BONAIRE_MC2_UCODE_SIZE * 4; mc2_req_size = BONAIRE_MC2_UCODE_SIZE * 4;
sdma_req_size = CIK_SDMA_UCODE_SIZE * 4; sdma_req_size = CIK_SDMA_UCODE_SIZE * 4;
smc_req_size = ALIGN(BONAIRE_SMC_UCODE_SIZE, 4); smc_req_size = ALIGN(BONAIRE_SMC_UCODE_SIZE, 4);
num_fw = 8;
break; break;
case CHIP_HAWAII: case CHIP_HAWAII:
chip_name = "HAWAII"; chip_name = "HAWAII";
new_chip_name = "hawaii";
pfp_req_size = CIK_PFP_UCODE_SIZE * 4; pfp_req_size = CIK_PFP_UCODE_SIZE * 4;
me_req_size = CIK_ME_UCODE_SIZE * 4; me_req_size = CIK_ME_UCODE_SIZE * 4;
ce_req_size = CIK_CE_UCODE_SIZE * 4; ce_req_size = CIK_CE_UCODE_SIZE * 4;
...@@ -1873,142 +1948,285 @@ static int cik_init_microcode(struct radeon_device *rdev) ...@@ -1873,142 +1948,285 @@ static int cik_init_microcode(struct radeon_device *rdev)
mc2_req_size = HAWAII_MC2_UCODE_SIZE * 4; mc2_req_size = HAWAII_MC2_UCODE_SIZE * 4;
sdma_req_size = CIK_SDMA_UCODE_SIZE * 4; sdma_req_size = CIK_SDMA_UCODE_SIZE * 4;
smc_req_size = ALIGN(HAWAII_SMC_UCODE_SIZE, 4); smc_req_size = ALIGN(HAWAII_SMC_UCODE_SIZE, 4);
num_fw = 8;
break; break;
case CHIP_KAVERI: case CHIP_KAVERI:
chip_name = "KAVERI"; chip_name = "KAVERI";
new_chip_name = "kaveri";
pfp_req_size = CIK_PFP_UCODE_SIZE * 4; pfp_req_size = CIK_PFP_UCODE_SIZE * 4;
me_req_size = CIK_ME_UCODE_SIZE * 4; me_req_size = CIK_ME_UCODE_SIZE * 4;
ce_req_size = CIK_CE_UCODE_SIZE * 4; ce_req_size = CIK_CE_UCODE_SIZE * 4;
mec_req_size = CIK_MEC_UCODE_SIZE * 4; mec_req_size = CIK_MEC_UCODE_SIZE * 4;
rlc_req_size = KV_RLC_UCODE_SIZE * 4; rlc_req_size = KV_RLC_UCODE_SIZE * 4;
sdma_req_size = CIK_SDMA_UCODE_SIZE * 4; sdma_req_size = CIK_SDMA_UCODE_SIZE * 4;
num_fw = 7;
break; break;
case CHIP_KABINI: case CHIP_KABINI:
chip_name = "KABINI"; chip_name = "KABINI";
new_chip_name = "kabini";
pfp_req_size = CIK_PFP_UCODE_SIZE * 4; pfp_req_size = CIK_PFP_UCODE_SIZE * 4;
me_req_size = CIK_ME_UCODE_SIZE * 4; me_req_size = CIK_ME_UCODE_SIZE * 4;
ce_req_size = CIK_CE_UCODE_SIZE * 4; ce_req_size = CIK_CE_UCODE_SIZE * 4;
mec_req_size = CIK_MEC_UCODE_SIZE * 4; mec_req_size = CIK_MEC_UCODE_SIZE * 4;
rlc_req_size = KB_RLC_UCODE_SIZE * 4; rlc_req_size = KB_RLC_UCODE_SIZE * 4;
sdma_req_size = CIK_SDMA_UCODE_SIZE * 4; sdma_req_size = CIK_SDMA_UCODE_SIZE * 4;
num_fw = 6;
break; break;
case CHIP_MULLINS: case CHIP_MULLINS:
chip_name = "MULLINS"; chip_name = "MULLINS";
new_chip_name = "mullins";
pfp_req_size = CIK_PFP_UCODE_SIZE * 4; pfp_req_size = CIK_PFP_UCODE_SIZE * 4;
me_req_size = CIK_ME_UCODE_SIZE * 4; me_req_size = CIK_ME_UCODE_SIZE * 4;
ce_req_size = CIK_CE_UCODE_SIZE * 4; ce_req_size = CIK_CE_UCODE_SIZE * 4;
mec_req_size = CIK_MEC_UCODE_SIZE * 4; mec_req_size = CIK_MEC_UCODE_SIZE * 4;
rlc_req_size = ML_RLC_UCODE_SIZE * 4; rlc_req_size = ML_RLC_UCODE_SIZE * 4;
sdma_req_size = CIK_SDMA_UCODE_SIZE * 4; sdma_req_size = CIK_SDMA_UCODE_SIZE * 4;
num_fw = 6;
break; break;
default: BUG(); default: BUG();
} }
DRM_INFO("Loading %s Microcode\n", chip_name); DRM_INFO("Loading %s Microcode\n", new_chip_name);
snprintf(fw_name, sizeof(fw_name), "radeon/%s_pfp.bin", chip_name); snprintf(fw_name, sizeof(fw_name), "radeon/%s_pfp.bin", new_chip_name);
err = request_firmware(&rdev->pfp_fw, fw_name, rdev->dev); err = request_firmware(&rdev->pfp_fw, fw_name, rdev->dev);
if (err) if (err) {
goto out; snprintf(fw_name, sizeof(fw_name), "radeon/%s_pfp.bin", chip_name);
if (rdev->pfp_fw->size != pfp_req_size) { err = request_firmware(&rdev->pfp_fw, fw_name, rdev->dev);
printk(KERN_ERR if (err)
"cik_cp: Bogus length %zu in firmware \"%s\"\n", goto out;
rdev->pfp_fw->size, fw_name); if (rdev->pfp_fw->size != pfp_req_size) {
err = -EINVAL; printk(KERN_ERR
goto out; "cik_cp: Bogus length %zu in firmware \"%s\"\n",
rdev->pfp_fw->size, fw_name);
err = -EINVAL;
goto out;
}
} else {
err = radeon_ucode_validate(rdev->pfp_fw);
if (err) {
printk(KERN_ERR
"cik_fw: validation failed for firmware \"%s\"\n",
fw_name);
goto out;
} else {
new_fw++;
}
} }
snprintf(fw_name, sizeof(fw_name), "radeon/%s_me.bin", chip_name); snprintf(fw_name, sizeof(fw_name), "radeon/%s_me.bin", new_chip_name);
err = request_firmware(&rdev->me_fw, fw_name, rdev->dev); err = request_firmware(&rdev->me_fw, fw_name, rdev->dev);
if (err) if (err) {
goto out; snprintf(fw_name, sizeof(fw_name), "radeon/%s_me.bin", chip_name);
if (rdev->me_fw->size != me_req_size) { err = request_firmware(&rdev->me_fw, fw_name, rdev->dev);
printk(KERN_ERR if (err)
"cik_cp: Bogus length %zu in firmware \"%s\"\n", goto out;
rdev->me_fw->size, fw_name); if (rdev->me_fw->size != me_req_size) {
err = -EINVAL; printk(KERN_ERR
"cik_cp: Bogus length %zu in firmware \"%s\"\n",
rdev->me_fw->size, fw_name);
err = -EINVAL;
}
} else {
err = radeon_ucode_validate(rdev->me_fw);
if (err) {
printk(KERN_ERR
"cik_fw: validation failed for firmware \"%s\"\n",
fw_name);
goto out;
} else {
new_fw++;
}
} }
snprintf(fw_name, sizeof(fw_name), "radeon/%s_ce.bin", chip_name); snprintf(fw_name, sizeof(fw_name), "radeon/%s_ce.bin", new_chip_name);
err = request_firmware(&rdev->ce_fw, fw_name, rdev->dev); err = request_firmware(&rdev->ce_fw, fw_name, rdev->dev);
if (err) if (err) {
goto out; snprintf(fw_name, sizeof(fw_name), "radeon/%s_ce.bin", chip_name);
if (rdev->ce_fw->size != ce_req_size) { err = request_firmware(&rdev->ce_fw, fw_name, rdev->dev);
printk(KERN_ERR if (err)
"cik_cp: Bogus length %zu in firmware \"%s\"\n", goto out;
rdev->ce_fw->size, fw_name); if (rdev->ce_fw->size != ce_req_size) {
err = -EINVAL; printk(KERN_ERR
"cik_cp: Bogus length %zu in firmware \"%s\"\n",
rdev->ce_fw->size, fw_name);
err = -EINVAL;
}
} else {
err = radeon_ucode_validate(rdev->ce_fw);
if (err) {
printk(KERN_ERR
"cik_fw: validation failed for firmware \"%s\"\n",
fw_name);
goto out;
} else {
new_fw++;
}
} }
snprintf(fw_name, sizeof(fw_name), "radeon/%s_mec.bin", chip_name); snprintf(fw_name, sizeof(fw_name), "radeon/%s_mec.bin", new_chip_name);
err = request_firmware(&rdev->mec_fw, fw_name, rdev->dev); err = request_firmware(&rdev->mec_fw, fw_name, rdev->dev);
if (err) if (err) {
goto out; snprintf(fw_name, sizeof(fw_name), "radeon/%s_mec.bin", chip_name);
if (rdev->mec_fw->size != mec_req_size) { err = request_firmware(&rdev->mec_fw, fw_name, rdev->dev);
printk(KERN_ERR if (err)
"cik_cp: Bogus length %zu in firmware \"%s\"\n", goto out;
rdev->mec_fw->size, fw_name); if (rdev->mec_fw->size != mec_req_size) {
err = -EINVAL; printk(KERN_ERR
"cik_cp: Bogus length %zu in firmware \"%s\"\n",
rdev->mec_fw->size, fw_name);
err = -EINVAL;
}
} else {
err = radeon_ucode_validate(rdev->mec_fw);
if (err) {
printk(KERN_ERR
"cik_fw: validation failed for firmware \"%s\"\n",
fw_name);
goto out;
} else {
new_fw++;
}
} }
snprintf(fw_name, sizeof(fw_name), "radeon/%s_rlc.bin", chip_name); if (rdev->family == CHIP_KAVERI) {
snprintf(fw_name, sizeof(fw_name), "radeon/%s_mec2.bin", new_chip_name);
err = request_firmware(&rdev->mec2_fw, fw_name, rdev->dev);
if (err) {
goto out;
} else {
err = radeon_ucode_validate(rdev->mec2_fw);
if (err) {
goto out;
} else {
new_fw++;
}
}
}
snprintf(fw_name, sizeof(fw_name), "radeon/%s_rlc.bin", new_chip_name);
err = request_firmware(&rdev->rlc_fw, fw_name, rdev->dev); err = request_firmware(&rdev->rlc_fw, fw_name, rdev->dev);
if (err) if (err) {
goto out; snprintf(fw_name, sizeof(fw_name), "radeon/%s_rlc.bin", chip_name);
if (rdev->rlc_fw->size != rlc_req_size) { err = request_firmware(&rdev->rlc_fw, fw_name, rdev->dev);
printk(KERN_ERR if (err)
"cik_rlc: Bogus length %zu in firmware \"%s\"\n", goto out;
rdev->rlc_fw->size, fw_name); if (rdev->rlc_fw->size != rlc_req_size) {
err = -EINVAL; printk(KERN_ERR
"cik_rlc: Bogus length %zu in firmware \"%s\"\n",
rdev->rlc_fw->size, fw_name);
err = -EINVAL;
}
} else {
err = radeon_ucode_validate(rdev->rlc_fw);
if (err) {
printk(KERN_ERR
"cik_fw: validation failed for firmware \"%s\"\n",
fw_name);
goto out;
} else {
new_fw++;
}
} }
snprintf(fw_name, sizeof(fw_name), "radeon/%s_sdma.bin", chip_name); snprintf(fw_name, sizeof(fw_name), "radeon/%s_sdma.bin", new_chip_name);
err = request_firmware(&rdev->sdma_fw, fw_name, rdev->dev); err = request_firmware(&rdev->sdma_fw, fw_name, rdev->dev);
if (err) if (err) {
goto out; snprintf(fw_name, sizeof(fw_name), "radeon/%s_sdma.bin", chip_name);
if (rdev->sdma_fw->size != sdma_req_size) { err = request_firmware(&rdev->sdma_fw, fw_name, rdev->dev);
printk(KERN_ERR if (err)
"cik_sdma: Bogus length %zu in firmware \"%s\"\n", goto out;
rdev->sdma_fw->size, fw_name); if (rdev->sdma_fw->size != sdma_req_size) {
err = -EINVAL; printk(KERN_ERR
"cik_sdma: Bogus length %zu in firmware \"%s\"\n",
rdev->sdma_fw->size, fw_name);
err = -EINVAL;
}
} else {
err = radeon_ucode_validate(rdev->sdma_fw);
if (err) {
printk(KERN_ERR
"cik_fw: validation failed for firmware \"%s\"\n",
fw_name);
goto out;
} else {
new_fw++;
}
} }
/* No SMC, MC ucode on APUs */ /* No SMC, MC ucode on APUs */
if (!(rdev->flags & RADEON_IS_IGP)) { if (!(rdev->flags & RADEON_IS_IGP)) {
snprintf(fw_name, sizeof(fw_name), "radeon/%s_mc2.bin", chip_name); snprintf(fw_name, sizeof(fw_name), "radeon/%s_mc.bin", new_chip_name);
err = request_firmware(&rdev->mc_fw, fw_name, rdev->dev); err = request_firmware(&rdev->mc_fw, fw_name, rdev->dev);
if (err) { if (err) {
snprintf(fw_name, sizeof(fw_name), "radeon/%s_mc.bin", chip_name); snprintf(fw_name, sizeof(fw_name), "radeon/%s_mc2.bin", chip_name);
err = request_firmware(&rdev->mc_fw, fw_name, rdev->dev); err = request_firmware(&rdev->mc_fw, fw_name, rdev->dev);
if (err) if (err) {
snprintf(fw_name, sizeof(fw_name), "radeon/%s_mc.bin", chip_name);
err = request_firmware(&rdev->mc_fw, fw_name, rdev->dev);
if (err)
goto out;
}
if ((rdev->mc_fw->size != mc_req_size) &&
(rdev->mc_fw->size != mc2_req_size)){
printk(KERN_ERR
"cik_mc: Bogus length %zu in firmware \"%s\"\n",
rdev->mc_fw->size, fw_name);
err = -EINVAL;
}
DRM_INFO("%s: %zu bytes\n", fw_name, rdev->mc_fw->size);
} else {
err = radeon_ucode_validate(rdev->mc_fw);
if (err) {
printk(KERN_ERR
"cik_fw: validation failed for firmware \"%s\"\n",
fw_name);
goto out; goto out;
} else {
new_fw++;
}
} }
if ((rdev->mc_fw->size != mc_req_size) &&
(rdev->mc_fw->size != mc2_req_size)){
printk(KERN_ERR
"cik_mc: Bogus length %zu in firmware \"%s\"\n",
rdev->mc_fw->size, fw_name);
err = -EINVAL;
}
DRM_INFO("%s: %zu bytes\n", fw_name, rdev->mc_fw->size);
snprintf(fw_name, sizeof(fw_name), "radeon/%s_smc.bin", chip_name); snprintf(fw_name, sizeof(fw_name), "radeon/%s_smc.bin", new_chip_name);
err = request_firmware(&rdev->smc_fw, fw_name, rdev->dev); err = request_firmware(&rdev->smc_fw, fw_name, rdev->dev);
if (err) { if (err) {
printk(KERN_ERR snprintf(fw_name, sizeof(fw_name), "radeon/%s_smc.bin", chip_name);
"smc: error loading firmware \"%s\"\n", err = request_firmware(&rdev->smc_fw, fw_name, rdev->dev);
fw_name); if (err) {
release_firmware(rdev->smc_fw); printk(KERN_ERR
rdev->smc_fw = NULL; "smc: error loading firmware \"%s\"\n",
err = 0; fw_name);
} else if (rdev->smc_fw->size != smc_req_size) { release_firmware(rdev->smc_fw);
printk(KERN_ERR rdev->smc_fw = NULL;
"cik_smc: Bogus length %zu in firmware \"%s\"\n", err = 0;
rdev->smc_fw->size, fw_name); } else if (rdev->smc_fw->size != smc_req_size) {
err = -EINVAL; printk(KERN_ERR
"cik_smc: Bogus length %zu in firmware \"%s\"\n",
rdev->smc_fw->size, fw_name);
err = -EINVAL;
}
} else {
err = radeon_ucode_validate(rdev->smc_fw);
if (err) {
printk(KERN_ERR
"cik_fw: validation failed for firmware \"%s\"\n",
fw_name);
goto out;
} else {
new_fw++;
}
} }
} }
if (new_fw == 0) {
rdev->new_fw = false;
} else if (new_fw < num_fw) {
printk(KERN_ERR "ci_fw: mixing new and old firmware!\n");
err = -EINVAL;
} else {
rdev->new_fw = true;
}
out: out:
if (err) { if (err) {
if (err != -EINVAL) if (err != -EINVAL)
...@@ -2021,8 +2239,14 @@ static int cik_init_microcode(struct radeon_device *rdev) ...@@ -2021,8 +2239,14 @@ static int cik_init_microcode(struct radeon_device *rdev)
rdev->me_fw = NULL; rdev->me_fw = NULL;
release_firmware(rdev->ce_fw); release_firmware(rdev->ce_fw);
rdev->ce_fw = NULL; rdev->ce_fw = NULL;
release_firmware(rdev->mec_fw);
rdev->mec_fw = NULL;
release_firmware(rdev->mec2_fw);
rdev->mec2_fw = NULL;
release_firmware(rdev->rlc_fw); release_firmware(rdev->rlc_fw);
rdev->rlc_fw = NULL; rdev->rlc_fw = NULL;
release_firmware(rdev->sdma_fw);
rdev->sdma_fw = NULL;
release_firmware(rdev->mc_fw); release_firmware(rdev->mc_fw);
rdev->mc_fw = NULL; rdev->mc_fw = NULL;
release_firmware(rdev->smc_fw); release_firmware(rdev->smc_fw);
...@@ -3969,7 +4193,6 @@ static void cik_cp_gfx_enable(struct radeon_device *rdev, bool enable) ...@@ -3969,7 +4193,6 @@ static void cik_cp_gfx_enable(struct radeon_device *rdev, bool enable)
*/ */
static int cik_cp_gfx_load_microcode(struct radeon_device *rdev) static int cik_cp_gfx_load_microcode(struct radeon_device *rdev)
{ {
const __be32 *fw_data;
int i; int i;
if (!rdev->me_fw || !rdev->pfp_fw || !rdev->ce_fw) if (!rdev->me_fw || !rdev->pfp_fw || !rdev->ce_fw)
...@@ -3977,26 +4200,70 @@ static int cik_cp_gfx_load_microcode(struct radeon_device *rdev) ...@@ -3977,26 +4200,70 @@ static int cik_cp_gfx_load_microcode(struct radeon_device *rdev)
cik_cp_gfx_enable(rdev, false); cik_cp_gfx_enable(rdev, false);
/* PFP */ if (rdev->new_fw) {
fw_data = (const __be32 *)rdev->pfp_fw->data; const struct gfx_firmware_header_v1_0 *pfp_hdr =
WREG32(CP_PFP_UCODE_ADDR, 0); (const struct gfx_firmware_header_v1_0 *)rdev->pfp_fw->data;
for (i = 0; i < CIK_PFP_UCODE_SIZE; i++) const struct gfx_firmware_header_v1_0 *ce_hdr =
WREG32(CP_PFP_UCODE_DATA, be32_to_cpup(fw_data++)); (const struct gfx_firmware_header_v1_0 *)rdev->ce_fw->data;
WREG32(CP_PFP_UCODE_ADDR, 0); const struct gfx_firmware_header_v1_0 *me_hdr =
(const struct gfx_firmware_header_v1_0 *)rdev->me_fw->data;
/* CE */ const __le32 *fw_data;
fw_data = (const __be32 *)rdev->ce_fw->data; u32 fw_size;
WREG32(CP_CE_UCODE_ADDR, 0);
for (i = 0; i < CIK_CE_UCODE_SIZE; i++) radeon_ucode_print_gfx_hdr(&pfp_hdr->header);
WREG32(CP_CE_UCODE_DATA, be32_to_cpup(fw_data++)); radeon_ucode_print_gfx_hdr(&ce_hdr->header);
WREG32(CP_CE_UCODE_ADDR, 0); radeon_ucode_print_gfx_hdr(&me_hdr->header);
/* ME */ /* PFP */
fw_data = (const __be32 *)rdev->me_fw->data; fw_data = (const __le32 *)
WREG32(CP_ME_RAM_WADDR, 0); (rdev->pfp_fw->data + le32_to_cpu(pfp_hdr->header.ucode_array_offset_bytes));
for (i = 0; i < CIK_ME_UCODE_SIZE; i++) fw_size = le32_to_cpu(pfp_hdr->header.ucode_size_bytes) / 4;
WREG32(CP_ME_RAM_DATA, be32_to_cpup(fw_data++)); WREG32(CP_PFP_UCODE_ADDR, 0);
WREG32(CP_ME_RAM_WADDR, 0); for (i = 0; i < fw_size; i++)
WREG32(CP_PFP_UCODE_DATA, le32_to_cpup(fw_data++));
WREG32(CP_PFP_UCODE_ADDR, 0);
/* CE */
fw_data = (const __le32 *)
(rdev->ce_fw->data + le32_to_cpu(ce_hdr->header.ucode_array_offset_bytes));
fw_size = le32_to_cpu(ce_hdr->header.ucode_size_bytes) / 4;
WREG32(CP_CE_UCODE_ADDR, 0);
for (i = 0; i < fw_size; i++)
WREG32(CP_CE_UCODE_DATA, le32_to_cpup(fw_data++));
WREG32(CP_CE_UCODE_ADDR, 0);
/* ME */
fw_data = (const __be32 *)
(rdev->me_fw->data + le32_to_cpu(me_hdr->header.ucode_array_offset_bytes));
fw_size = le32_to_cpu(me_hdr->header.ucode_size_bytes) / 4;
WREG32(CP_ME_RAM_WADDR, 0);
for (i = 0; i < fw_size; i++)
WREG32(CP_ME_RAM_DATA, le32_to_cpup(fw_data++));
WREG32(CP_ME_RAM_WADDR, 0);
} else {
const __be32 *fw_data;
/* PFP */
fw_data = (const __be32 *)rdev->pfp_fw->data;
WREG32(CP_PFP_UCODE_ADDR, 0);
for (i = 0; i < CIK_PFP_UCODE_SIZE; i++)
WREG32(CP_PFP_UCODE_DATA, be32_to_cpup(fw_data++));
WREG32(CP_PFP_UCODE_ADDR, 0);
/* CE */
fw_data = (const __be32 *)rdev->ce_fw->data;
WREG32(CP_CE_UCODE_ADDR, 0);
for (i = 0; i < CIK_CE_UCODE_SIZE; i++)
WREG32(CP_CE_UCODE_DATA, be32_to_cpup(fw_data++));
WREG32(CP_CE_UCODE_ADDR, 0);
/* ME */
fw_data = (const __be32 *)rdev->me_fw->data;
WREG32(CP_ME_RAM_WADDR, 0);
for (i = 0; i < CIK_ME_UCODE_SIZE; i++)
WREG32(CP_ME_RAM_DATA, be32_to_cpup(fw_data++));
WREG32(CP_ME_RAM_WADDR, 0);
}
WREG32(CP_PFP_UCODE_ADDR, 0); WREG32(CP_PFP_UCODE_ADDR, 0);
WREG32(CP_CE_UCODE_ADDR, 0); WREG32(CP_CE_UCODE_ADDR, 0);
...@@ -4261,7 +4528,6 @@ static void cik_cp_compute_enable(struct radeon_device *rdev, bool enable) ...@@ -4261,7 +4528,6 @@ static void cik_cp_compute_enable(struct radeon_device *rdev, bool enable)
*/ */
static int cik_cp_compute_load_microcode(struct radeon_device *rdev) static int cik_cp_compute_load_microcode(struct radeon_device *rdev)
{ {
const __be32 *fw_data;
int i; int i;
if (!rdev->mec_fw) if (!rdev->mec_fw)
...@@ -4269,20 +4535,55 @@ static int cik_cp_compute_load_microcode(struct radeon_device *rdev) ...@@ -4269,20 +4535,55 @@ static int cik_cp_compute_load_microcode(struct radeon_device *rdev)
cik_cp_compute_enable(rdev, false); cik_cp_compute_enable(rdev, false);
/* MEC1 */ if (rdev->new_fw) {
fw_data = (const __be32 *)rdev->mec_fw->data; const struct gfx_firmware_header_v1_0 *mec_hdr =
WREG32(CP_MEC_ME1_UCODE_ADDR, 0); (const struct gfx_firmware_header_v1_0 *)rdev->mec_fw->data;
for (i = 0; i < CIK_MEC_UCODE_SIZE; i++) const __le32 *fw_data;
WREG32(CP_MEC_ME1_UCODE_DATA, be32_to_cpup(fw_data++)); u32 fw_size;
WREG32(CP_MEC_ME1_UCODE_ADDR, 0);
radeon_ucode_print_gfx_hdr(&mec_hdr->header);
/* MEC1 */
fw_data = (const __le32 *)
(rdev->mec_fw->data + le32_to_cpu(mec_hdr->header.ucode_array_offset_bytes));
fw_size = le32_to_cpu(mec_hdr->header.ucode_size_bytes) / 4;
WREG32(CP_MEC_ME1_UCODE_ADDR, 0);
for (i = 0; i < fw_size; i++)
WREG32(CP_MEC_ME1_UCODE_DATA, le32_to_cpup(fw_data++));
WREG32(CP_MEC_ME1_UCODE_ADDR, 0);
if (rdev->family == CHIP_KAVERI) {
/* MEC2 */ /* MEC2 */
if (rdev->family == CHIP_KAVERI) {
const struct gfx_firmware_header_v1_0 *mec2_hdr =
(const struct gfx_firmware_header_v1_0 *)rdev->mec2_fw->data;
fw_data = (const __le32 *)
(rdev->mec2_fw->data +
le32_to_cpu(mec2_hdr->header.ucode_array_offset_bytes));
fw_size = le32_to_cpu(mec2_hdr->header.ucode_size_bytes) / 4;
WREG32(CP_MEC_ME2_UCODE_ADDR, 0);
for (i = 0; i < fw_size; i++)
WREG32(CP_MEC_ME2_UCODE_DATA, le32_to_cpup(fw_data++));
WREG32(CP_MEC_ME2_UCODE_ADDR, 0);
}
} else {
const __be32 *fw_data;
/* MEC1 */
fw_data = (const __be32 *)rdev->mec_fw->data; fw_data = (const __be32 *)rdev->mec_fw->data;
WREG32(CP_MEC_ME2_UCODE_ADDR, 0); WREG32(CP_MEC_ME1_UCODE_ADDR, 0);
for (i = 0; i < CIK_MEC_UCODE_SIZE; i++) for (i = 0; i < CIK_MEC_UCODE_SIZE; i++)
WREG32(CP_MEC_ME2_UCODE_DATA, be32_to_cpup(fw_data++)); WREG32(CP_MEC_ME1_UCODE_DATA, be32_to_cpup(fw_data++));
WREG32(CP_MEC_ME2_UCODE_ADDR, 0); WREG32(CP_MEC_ME1_UCODE_ADDR, 0);
if (rdev->family == CHIP_KAVERI) {
/* MEC2 */
fw_data = (const __be32 *)rdev->mec_fw->data;
WREG32(CP_MEC_ME2_UCODE_ADDR, 0);
for (i = 0; i < CIK_MEC_UCODE_SIZE; i++)
WREG32(CP_MEC_ME2_UCODE_DATA, be32_to_cpup(fw_data++));
WREG32(CP_MEC_ME2_UCODE_ADDR, 0);
}
} }
return 0; return 0;
...@@ -5865,28 +6166,10 @@ static void cik_rlc_start(struct radeon_device *rdev) ...@@ -5865,28 +6166,10 @@ static void cik_rlc_start(struct radeon_device *rdev)
static int cik_rlc_resume(struct radeon_device *rdev) static int cik_rlc_resume(struct radeon_device *rdev)
{ {
u32 i, size, tmp; u32 i, size, tmp;
const __be32 *fw_data;
if (!rdev->rlc_fw) if (!rdev->rlc_fw)
return -EINVAL; return -EINVAL;
switch (rdev->family) {
case CHIP_BONAIRE:
case CHIP_HAWAII:
default:
size = BONAIRE_RLC_UCODE_SIZE;
break;
case CHIP_KAVERI:
size = KV_RLC_UCODE_SIZE;
break;
case CHIP_KABINI:
size = KB_RLC_UCODE_SIZE;
break;
case CHIP_MULLINS:
size = ML_RLC_UCODE_SIZE;
break;
}
cik_rlc_stop(rdev); cik_rlc_stop(rdev);
/* disable CG */ /* disable CG */
...@@ -5910,11 +6193,45 @@ static int cik_rlc_resume(struct radeon_device *rdev) ...@@ -5910,11 +6193,45 @@ static int cik_rlc_resume(struct radeon_device *rdev)
WREG32(RLC_MC_CNTL, 0); WREG32(RLC_MC_CNTL, 0);
WREG32(RLC_UCODE_CNTL, 0); WREG32(RLC_UCODE_CNTL, 0);
fw_data = (const __be32 *)rdev->rlc_fw->data; if (rdev->new_fw) {
const struct rlc_firmware_header_v1_0 *hdr =
(const struct rlc_firmware_header_v1_0 *)rdev->rlc_fw->data;
const __le32 *fw_data = (const __le32 *)
(rdev->rlc_fw->data + le32_to_cpu(hdr->header.ucode_array_offset_bytes));
radeon_ucode_print_rlc_hdr(&hdr->header);
size = le32_to_cpu(hdr->header.ucode_size_bytes) / 4;
WREG32(RLC_GPM_UCODE_ADDR, 0);
for (i = 0; i < size; i++)
WREG32(RLC_GPM_UCODE_DATA, le32_to_cpup(fw_data++));
WREG32(RLC_GPM_UCODE_ADDR, 0); WREG32(RLC_GPM_UCODE_ADDR, 0);
for (i = 0; i < size; i++) } else {
WREG32(RLC_GPM_UCODE_DATA, be32_to_cpup(fw_data++)); const __be32 *fw_data;
WREG32(RLC_GPM_UCODE_ADDR, 0);
switch (rdev->family) {
case CHIP_BONAIRE:
case CHIP_HAWAII:
default:
size = BONAIRE_RLC_UCODE_SIZE;
break;
case CHIP_KAVERI:
size = KV_RLC_UCODE_SIZE;
break;
case CHIP_KABINI:
size = KB_RLC_UCODE_SIZE;
break;
case CHIP_MULLINS:
size = ML_RLC_UCODE_SIZE;
break;
}
fw_data = (const __be32 *)rdev->rlc_fw->data;
WREG32(RLC_GPM_UCODE_ADDR, 0);
for (i = 0; i < size; i++)
WREG32(RLC_GPM_UCODE_DATA, be32_to_cpup(fw_data++));
WREG32(RLC_GPM_UCODE_ADDR, 0);
}
/* XXX - find out what chips support lbpw */ /* XXX - find out what chips support lbpw */
cik_enable_lbpw(rdev, false); cik_enable_lbpw(rdev, false);
...@@ -6348,11 +6665,10 @@ static void cik_enable_gds_pg(struct radeon_device *rdev, bool enable) ...@@ -6348,11 +6665,10 @@ static void cik_enable_gds_pg(struct radeon_device *rdev, bool enable)
void cik_init_cp_pg_table(struct radeon_device *rdev) void cik_init_cp_pg_table(struct radeon_device *rdev)
{ {
const __be32 *fw_data;
volatile u32 *dst_ptr; volatile u32 *dst_ptr;
int me, i, max_me = 4; int me, i, max_me = 4;
u32 bo_offset = 0; u32 bo_offset = 0;
u32 table_offset; u32 table_offset, table_size;
if (rdev->family == CHIP_KAVERI) if (rdev->family == CHIP_KAVERI)
max_me = 5; max_me = 5;
...@@ -6363,24 +6679,71 @@ void cik_init_cp_pg_table(struct radeon_device *rdev) ...@@ -6363,24 +6679,71 @@ void cik_init_cp_pg_table(struct radeon_device *rdev)
/* write the cp table buffer */ /* write the cp table buffer */
dst_ptr = rdev->rlc.cp_table_ptr; dst_ptr = rdev->rlc.cp_table_ptr;
for (me = 0; me < max_me; me++) { for (me = 0; me < max_me; me++) {
if (me == 0) { if (rdev->new_fw) {
fw_data = (const __be32 *)rdev->ce_fw->data; const __le32 *fw_data;
table_offset = CP_ME_TABLE_OFFSET; const struct gfx_firmware_header_v1_0 *hdr;
} else if (me == 1) {
fw_data = (const __be32 *)rdev->pfp_fw->data; if (me == 0) {
table_offset = CP_ME_TABLE_OFFSET; hdr = (const struct gfx_firmware_header_v1_0 *)rdev->ce_fw->data;
} else if (me == 2) { fw_data = (const __le32 *)
fw_data = (const __be32 *)rdev->me_fw->data; (rdev->ce_fw->data + le32_to_cpu(hdr->header.ucode_array_offset_bytes));
table_offset = CP_ME_TABLE_OFFSET; table_offset = le32_to_cpu(hdr->jt_offset);
table_size = le32_to_cpu(hdr->jt_size);
} else if (me == 1) {
hdr = (const struct gfx_firmware_header_v1_0 *)rdev->pfp_fw->data;
fw_data = (const __le32 *)
(rdev->pfp_fw->data + le32_to_cpu(hdr->header.ucode_array_offset_bytes));
table_offset = le32_to_cpu(hdr->jt_offset);
table_size = le32_to_cpu(hdr->jt_size);
} else if (me == 2) {
hdr = (const struct gfx_firmware_header_v1_0 *)rdev->me_fw->data;
fw_data = (const __le32 *)
(rdev->me_fw->data + le32_to_cpu(hdr->header.ucode_array_offset_bytes));
table_offset = le32_to_cpu(hdr->jt_offset);
table_size = le32_to_cpu(hdr->jt_size);
} else if (me == 3) {
hdr = (const struct gfx_firmware_header_v1_0 *)rdev->mec_fw->data;
fw_data = (const __le32 *)
(rdev->mec_fw->data + le32_to_cpu(hdr->header.ucode_array_offset_bytes));
table_offset = le32_to_cpu(hdr->jt_offset);
table_size = le32_to_cpu(hdr->jt_size);
} else {
hdr = (const struct gfx_firmware_header_v1_0 *)rdev->mec2_fw->data;
fw_data = (const __le32 *)
(rdev->mec2_fw->data + le32_to_cpu(hdr->header.ucode_array_offset_bytes));
table_offset = le32_to_cpu(hdr->jt_offset);
table_size = le32_to_cpu(hdr->jt_size);
}
for (i = 0; i < table_size; i ++) {
dst_ptr[bo_offset + i] =
cpu_to_le32(le32_to_cpu(fw_data[table_offset + i]));
}
bo_offset += table_size;
} else { } else {
fw_data = (const __be32 *)rdev->mec_fw->data; const __be32 *fw_data;
table_offset = CP_MEC_TABLE_OFFSET; table_size = CP_ME_TABLE_SIZE;
}
if (me == 0) {
fw_data = (const __be32 *)rdev->ce_fw->data;
table_offset = CP_ME_TABLE_OFFSET;
} else if (me == 1) {
fw_data = (const __be32 *)rdev->pfp_fw->data;
table_offset = CP_ME_TABLE_OFFSET;
} else if (me == 2) {
fw_data = (const __be32 *)rdev->me_fw->data;
table_offset = CP_ME_TABLE_OFFSET;
} else {
fw_data = (const __be32 *)rdev->mec_fw->data;
table_offset = CP_MEC_TABLE_OFFSET;
}
for (i = 0; i < CP_ME_TABLE_SIZE; i ++) { for (i = 0; i < table_size; i ++) {
dst_ptr[bo_offset + i] = cpu_to_le32(be32_to_cpu(fw_data[table_offset + i])); dst_ptr[bo_offset + i] =
cpu_to_le32(be32_to_cpu(fw_data[table_offset + i]));
}
bo_offset += table_size;
} }
bo_offset += CP_ME_TABLE_SIZE;
} }
} }
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include <linux/firmware.h> #include <linux/firmware.h>
#include <drm/drmP.h> #include <drm/drmP.h>
#include "radeon.h" #include "radeon.h"
#include "radeon_ucode.h"
#include "radeon_asic.h" #include "radeon_asic.h"
#include "radeon_trace.h" #include "radeon_trace.h"
#include "cikd.h" #include "cikd.h"
...@@ -419,7 +420,6 @@ static int cik_sdma_rlc_resume(struct radeon_device *rdev) ...@@ -419,7 +420,6 @@ static int cik_sdma_rlc_resume(struct radeon_device *rdev)
*/ */
static int cik_sdma_load_microcode(struct radeon_device *rdev) static int cik_sdma_load_microcode(struct radeon_device *rdev)
{ {
const __be32 *fw_data;
int i; int i;
if (!rdev->sdma_fw) if (!rdev->sdma_fw)
...@@ -428,19 +428,48 @@ static int cik_sdma_load_microcode(struct radeon_device *rdev) ...@@ -428,19 +428,48 @@ static int cik_sdma_load_microcode(struct radeon_device *rdev)
/* halt the MEs */ /* halt the MEs */
cik_sdma_enable(rdev, false); cik_sdma_enable(rdev, false);
/* sdma0 */ if (rdev->new_fw) {
fw_data = (const __be32 *)rdev->sdma_fw->data; const struct sdma_firmware_header_v1_0 *hdr =
WREG32(SDMA0_UCODE_ADDR + SDMA0_REGISTER_OFFSET, 0); (const struct sdma_firmware_header_v1_0 *)rdev->sdma_fw->data;
for (i = 0; i < CIK_SDMA_UCODE_SIZE; i++) const __le32 *fw_data;
WREG32(SDMA0_UCODE_DATA + SDMA0_REGISTER_OFFSET, be32_to_cpup(fw_data++)); u32 fw_size;
WREG32(SDMA0_UCODE_DATA + SDMA0_REGISTER_OFFSET, CIK_SDMA_UCODE_VERSION);
radeon_ucode_print_sdma_hdr(&hdr->header);
/* sdma1 */
fw_data = (const __be32 *)rdev->sdma_fw->data; /* sdma0 */
WREG32(SDMA0_UCODE_ADDR + SDMA1_REGISTER_OFFSET, 0); fw_data = (const __le32 *)
for (i = 0; i < CIK_SDMA_UCODE_SIZE; i++) (rdev->sdma_fw->data + le32_to_cpu(hdr->header.ucode_array_offset_bytes));
WREG32(SDMA0_UCODE_DATA + SDMA1_REGISTER_OFFSET, be32_to_cpup(fw_data++)); fw_size = le32_to_cpu(hdr->header.ucode_size_bytes) / 4;
WREG32(SDMA0_UCODE_DATA + SDMA1_REGISTER_OFFSET, CIK_SDMA_UCODE_VERSION); WREG32(SDMA0_UCODE_ADDR + SDMA0_REGISTER_OFFSET, 0);
for (i = 0; i < fw_size; i++)
WREG32(SDMA0_UCODE_DATA + SDMA0_REGISTER_OFFSET, le32_to_cpup(fw_data++));
WREG32(SDMA0_UCODE_DATA + SDMA0_REGISTER_OFFSET, CIK_SDMA_UCODE_VERSION);
/* sdma1 */
fw_data = (const __le32 *)
(rdev->sdma_fw->data + le32_to_cpu(hdr->header.ucode_array_offset_bytes));
fw_size = le32_to_cpu(hdr->header.ucode_size_bytes) / 4;
WREG32(SDMA0_UCODE_ADDR + SDMA1_REGISTER_OFFSET, 0);
for (i = 0; i < fw_size; i++)
WREG32(SDMA0_UCODE_DATA + SDMA1_REGISTER_OFFSET, le32_to_cpup(fw_data++));
WREG32(SDMA0_UCODE_DATA + SDMA1_REGISTER_OFFSET, CIK_SDMA_UCODE_VERSION);
} else {
const __be32 *fw_data;
/* sdma0 */
fw_data = (const __be32 *)rdev->sdma_fw->data;
WREG32(SDMA0_UCODE_ADDR + SDMA0_REGISTER_OFFSET, 0);
for (i = 0; i < CIK_SDMA_UCODE_SIZE; i++)
WREG32(SDMA0_UCODE_DATA + SDMA0_REGISTER_OFFSET, be32_to_cpup(fw_data++));
WREG32(SDMA0_UCODE_DATA + SDMA0_REGISTER_OFFSET, CIK_SDMA_UCODE_VERSION);
/* sdma1 */
fw_data = (const __be32 *)rdev->sdma_fw->data;
WREG32(SDMA0_UCODE_ADDR + SDMA1_REGISTER_OFFSET, 0);
for (i = 0; i < CIK_SDMA_UCODE_SIZE; i++)
WREG32(SDMA0_UCODE_DATA + SDMA1_REGISTER_OFFSET, be32_to_cpup(fw_data++));
WREG32(SDMA0_UCODE_DATA + SDMA1_REGISTER_OFFSET, CIK_SDMA_UCODE_VERSION);
}
WREG32(SDMA0_UCODE_ADDR + SDMA0_REGISTER_OFFSET, 0); WREG32(SDMA0_UCODE_ADDR + SDMA0_REGISTER_OFFSET, 0);
WREG32(SDMA0_UCODE_ADDR + SDMA1_REGISTER_OFFSET, 0); WREG32(SDMA0_UCODE_ADDR + SDMA1_REGISTER_OFFSET, 0);
......
...@@ -2302,6 +2302,7 @@ struct radeon_device { ...@@ -2302,6 +2302,7 @@ struct radeon_device {
const struct firmware *mc_fw; /* NI MC firmware */ const struct firmware *mc_fw; /* NI MC firmware */
const struct firmware *ce_fw; /* SI CE firmware */ const struct firmware *ce_fw; /* SI CE firmware */
const struct firmware *mec_fw; /* CIK MEC firmware */ const struct firmware *mec_fw; /* CIK MEC firmware */
const struct firmware *mec2_fw; /* KV MEC2 firmware */
const struct firmware *sdma_fw; /* CIK SDMA firmware */ const struct firmware *sdma_fw; /* CIK SDMA firmware */
const struct firmware *smc_fw; /* SMC firmware */ const struct firmware *smc_fw; /* SMC firmware */
const struct firmware *uvd_fw; /* UVD firmware */ const struct firmware *uvd_fw; /* UVD firmware */
......
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