提交 c420c745 编写于 作者: A Alex Deucher 提交者: Dave Airlie

drm/radeon/kms: add support for ucode loading on trinity (v2)

v2: fix check for MC ucode from Tom.
Signed-off-by: NAlex Deucher <alexander.deucher@amd.com>
Signed-off-by: NDave Airlie <airlied@redhat.com>
上级 e71270fd
...@@ -42,6 +42,8 @@ extern void evergreen_irq_suspend(struct radeon_device *rdev); ...@@ -42,6 +42,8 @@ extern void evergreen_irq_suspend(struct radeon_device *rdev);
extern int evergreen_mc_init(struct radeon_device *rdev); extern int evergreen_mc_init(struct radeon_device *rdev);
extern void evergreen_fix_pci_max_read_req_size(struct radeon_device *rdev); extern void evergreen_fix_pci_max_read_req_size(struct radeon_device *rdev);
extern void evergreen_pcie_gen2_enable(struct radeon_device *rdev); extern void evergreen_pcie_gen2_enable(struct radeon_device *rdev);
extern void si_rlc_fini(struct radeon_device *rdev);
extern int si_rlc_init(struct radeon_device *rdev);
#define EVERGREEN_PFP_UCODE_SIZE 1120 #define EVERGREEN_PFP_UCODE_SIZE 1120
#define EVERGREEN_PM4_UCODE_SIZE 1376 #define EVERGREEN_PM4_UCODE_SIZE 1376
...@@ -53,6 +55,8 @@ extern void evergreen_pcie_gen2_enable(struct radeon_device *rdev); ...@@ -53,6 +55,8 @@ extern void evergreen_pcie_gen2_enable(struct radeon_device *rdev);
#define CAYMAN_RLC_UCODE_SIZE 1024 #define CAYMAN_RLC_UCODE_SIZE 1024
#define CAYMAN_MC_UCODE_SIZE 6037 #define CAYMAN_MC_UCODE_SIZE 6037
#define ARUBA_RLC_UCODE_SIZE 1536
/* Firmware Names */ /* Firmware Names */
MODULE_FIRMWARE("radeon/BARTS_pfp.bin"); MODULE_FIRMWARE("radeon/BARTS_pfp.bin");
MODULE_FIRMWARE("radeon/BARTS_me.bin"); MODULE_FIRMWARE("radeon/BARTS_me.bin");
...@@ -68,6 +72,9 @@ MODULE_FIRMWARE("radeon/CAYMAN_pfp.bin"); ...@@ -68,6 +72,9 @@ MODULE_FIRMWARE("radeon/CAYMAN_pfp.bin");
MODULE_FIRMWARE("radeon/CAYMAN_me.bin"); MODULE_FIRMWARE("radeon/CAYMAN_me.bin");
MODULE_FIRMWARE("radeon/CAYMAN_mc.bin"); MODULE_FIRMWARE("radeon/CAYMAN_mc.bin");
MODULE_FIRMWARE("radeon/CAYMAN_rlc.bin"); MODULE_FIRMWARE("radeon/CAYMAN_rlc.bin");
MODULE_FIRMWARE("radeon/ARUBA_pfp.bin");
MODULE_FIRMWARE("radeon/ARUBA_me.bin");
MODULE_FIRMWARE("radeon/ARUBA_rlc.bin");
#define BTC_IO_MC_REGS_SIZE 29 #define BTC_IO_MC_REGS_SIZE 29
...@@ -326,6 +333,15 @@ int ni_init_microcode(struct radeon_device *rdev) ...@@ -326,6 +333,15 @@ int ni_init_microcode(struct radeon_device *rdev)
rlc_req_size = CAYMAN_RLC_UCODE_SIZE * 4; rlc_req_size = CAYMAN_RLC_UCODE_SIZE * 4;
mc_req_size = CAYMAN_MC_UCODE_SIZE * 4; mc_req_size = CAYMAN_MC_UCODE_SIZE * 4;
break; break;
case CHIP_ARUBA:
chip_name = "ARUBA";
rlc_chip_name = "ARUBA";
/* pfp/me same size as CAYMAN */
pfp_req_size = CAYMAN_PFP_UCODE_SIZE * 4;
me_req_size = CAYMAN_PM4_UCODE_SIZE * 4;
rlc_req_size = ARUBA_RLC_UCODE_SIZE * 4;
mc_req_size = 0;
break;
default: BUG(); default: BUG();
} }
...@@ -365,15 +381,18 @@ int ni_init_microcode(struct radeon_device *rdev) ...@@ -365,15 +381,18 @@ int ni_init_microcode(struct radeon_device *rdev)
err = -EINVAL; err = -EINVAL;
} }
snprintf(fw_name, sizeof(fw_name), "radeon/%s_mc.bin", chip_name); /* no MC ucode on TN */
err = request_firmware(&rdev->mc_fw, fw_name, &pdev->dev); if (!(rdev->flags & RADEON_IS_IGP)) {
if (err) snprintf(fw_name, sizeof(fw_name), "radeon/%s_mc.bin", chip_name);
goto out; err = request_firmware(&rdev->mc_fw, fw_name, &pdev->dev);
if (rdev->mc_fw->size != mc_req_size) { if (err)
printk(KERN_ERR goto out;
"ni_mc: Bogus length %zu in firmware \"%s\"\n", if (rdev->mc_fw->size != mc_req_size) {
rdev->mc_fw->size, fw_name); printk(KERN_ERR
err = -EINVAL; "ni_mc: Bogus length %zu in firmware \"%s\"\n",
rdev->mc_fw->size, fw_name);
err = -EINVAL;
}
} }
out: out:
platform_device_unregister(pdev); platform_device_unregister(pdev);
...@@ -1484,18 +1503,29 @@ static int cayman_startup(struct radeon_device *rdev) ...@@ -1484,18 +1503,29 @@ static int cayman_startup(struct radeon_device *rdev)
/* enable pcie gen2 link */ /* enable pcie gen2 link */
evergreen_pcie_gen2_enable(rdev); evergreen_pcie_gen2_enable(rdev);
if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw || !rdev->mc_fw) { if (rdev->flags & RADEON_IS_IGP) {
r = ni_init_microcode(rdev); if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw) {
r = ni_init_microcode(rdev);
if (r) {
DRM_ERROR("Failed to load firmware!\n");
return r;
}
}
} else {
if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw || !rdev->mc_fw) {
r = ni_init_microcode(rdev);
if (r) {
DRM_ERROR("Failed to load firmware!\n");
return r;
}
}
r = ni_mc_load_microcode(rdev);
if (r) { if (r) {
DRM_ERROR("Failed to load firmware!\n"); DRM_ERROR("Failed to load MC firmware!\n");
return r; return r;
} }
} }
r = ni_mc_load_microcode(rdev);
if (r) {
DRM_ERROR("Failed to load MC firmware!\n");
return r;
}
r = r600_vram_scratch_init(rdev); r = r600_vram_scratch_init(rdev);
if (r) if (r)
...@@ -1514,6 +1544,15 @@ static int cayman_startup(struct radeon_device *rdev) ...@@ -1514,6 +1544,15 @@ static int cayman_startup(struct radeon_device *rdev)
dev_warn(rdev->dev, "failed blitter (%d) falling back to memcpy\n", r); dev_warn(rdev->dev, "failed blitter (%d) falling back to memcpy\n", r);
} }
/* allocate rlc buffers */
if (rdev->flags & RADEON_IS_IGP) {
r = si_rlc_init(rdev);
if (r) {
DRM_ERROR("Failed to init rlc BOs!\n");
return r;
}
}
/* allocate wb buffer */ /* allocate wb buffer */
r = radeon_wb_init(rdev); r = radeon_wb_init(rdev);
if (r) if (r)
...@@ -1698,6 +1737,8 @@ int cayman_init(struct radeon_device *rdev) ...@@ -1698,6 +1737,8 @@ int cayman_init(struct radeon_device *rdev)
dev_err(rdev->dev, "disabling GPU acceleration\n"); dev_err(rdev->dev, "disabling GPU acceleration\n");
cayman_cp_fini(rdev); cayman_cp_fini(rdev);
r600_irq_fini(rdev); r600_irq_fini(rdev);
if (rdev->flags & RADEON_IS_IGP)
si_rlc_fini(rdev);
radeon_wb_fini(rdev); radeon_wb_fini(rdev);
r100_ib_fini(rdev); r100_ib_fini(rdev);
radeon_vm_manager_fini(rdev); radeon_vm_manager_fini(rdev);
...@@ -1709,8 +1750,11 @@ int cayman_init(struct radeon_device *rdev) ...@@ -1709,8 +1750,11 @@ int cayman_init(struct radeon_device *rdev)
/* Don't start up if the MC ucode is missing. /* Don't start up if the MC ucode is missing.
* The default clocks and voltages before the MC ucode * The default clocks and voltages before the MC ucode
* is loaded are not suffient for advanced operations. * is loaded are not suffient for advanced operations.
*
* We can skip this check for TN, because there is no MC
* ucode.
*/ */
if (!rdev->mc_fw) { if (!rdev->mc_fw && !(rdev->flags & RADEON_IS_IGP)) {
DRM_ERROR("radeon: MC ucode required for NI+.\n"); DRM_ERROR("radeon: MC ucode required for NI+.\n");
return -EINVAL; return -EINVAL;
} }
...@@ -1723,6 +1767,8 @@ void cayman_fini(struct radeon_device *rdev) ...@@ -1723,6 +1767,8 @@ void cayman_fini(struct radeon_device *rdev)
r600_blit_fini(rdev); r600_blit_fini(rdev);
cayman_cp_fini(rdev); cayman_cp_fini(rdev);
r600_irq_fini(rdev); r600_irq_fini(rdev);
if (rdev->flags & RADEON_IS_IGP)
si_rlc_fini(rdev);
radeon_wb_fini(rdev); radeon_wb_fini(rdev);
radeon_vm_manager_fini(rdev); radeon_vm_manager_fini(rdev);
r100_ib_fini(rdev); r100_ib_fini(rdev);
......
...@@ -49,6 +49,7 @@ ...@@ -49,6 +49,7 @@
#define EVERGREEN_PM4_UCODE_SIZE 1376 #define EVERGREEN_PM4_UCODE_SIZE 1376
#define EVERGREEN_RLC_UCODE_SIZE 768 #define EVERGREEN_RLC_UCODE_SIZE 768
#define CAYMAN_RLC_UCODE_SIZE 1024 #define CAYMAN_RLC_UCODE_SIZE 1024
#define ARUBA_RLC_UCODE_SIZE 1536
/* Firmware Names */ /* Firmware Names */
MODULE_FIRMWARE("radeon/R600_pfp.bin"); MODULE_FIRMWARE("radeon/R600_pfp.bin");
...@@ -2861,10 +2862,17 @@ static int r600_rlc_init(struct radeon_device *rdev) ...@@ -2861,10 +2862,17 @@ static int r600_rlc_init(struct radeon_device *rdev)
r600_rlc_stop(rdev); r600_rlc_stop(rdev);
WREG32(RLC_HB_BASE, 0);
WREG32(RLC_HB_CNTL, 0); WREG32(RLC_HB_CNTL, 0);
WREG32(RLC_HB_RPTR, 0);
WREG32(RLC_HB_WPTR, 0); if (rdev->family == CHIP_ARUBA) {
WREG32(TN_RLC_SAVE_AND_RESTORE_BASE, rdev->rlc.save_restore_gpu_addr >> 8);
WREG32(TN_RLC_CLEAR_STATE_RESTORE_BASE, rdev->rlc.clear_state_gpu_addr >> 8);
}
if (rdev->family <= CHIP_CAYMAN) {
WREG32(RLC_HB_BASE, 0);
WREG32(RLC_HB_RPTR, 0);
WREG32(RLC_HB_WPTR, 0);
}
if (rdev->family <= CHIP_CAICOS) { if (rdev->family <= CHIP_CAICOS) {
WREG32(RLC_HB_WPTR_LSB_ADDR, 0); WREG32(RLC_HB_WPTR_LSB_ADDR, 0);
WREG32(RLC_HB_WPTR_MSB_ADDR, 0); WREG32(RLC_HB_WPTR_MSB_ADDR, 0);
...@@ -2873,7 +2881,12 @@ static int r600_rlc_init(struct radeon_device *rdev) ...@@ -2873,7 +2881,12 @@ static int r600_rlc_init(struct radeon_device *rdev)
WREG32(RLC_UCODE_CNTL, 0); WREG32(RLC_UCODE_CNTL, 0);
fw_data = (const __be32 *)rdev->rlc_fw->data; fw_data = (const __be32 *)rdev->rlc_fw->data;
if (rdev->family >= CHIP_CAYMAN) { if (rdev->family >= CHIP_ARUBA) {
for (i = 0; i < ARUBA_RLC_UCODE_SIZE; i++) {
WREG32(RLC_UCODE_ADDR, i);
WREG32(RLC_UCODE_DATA, be32_to_cpup(fw_data++));
}
} else if (rdev->family >= CHIP_CAYMAN) {
for (i = 0; i < CAYMAN_RLC_UCODE_SIZE; i++) { for (i = 0; i < CAYMAN_RLC_UCODE_SIZE; i++) {
WREG32(RLC_UCODE_ADDR, i); WREG32(RLC_UCODE_ADDR, i);
WREG32(RLC_UCODE_DATA, be32_to_cpup(fw_data++)); WREG32(RLC_UCODE_DATA, be32_to_cpup(fw_data++));
......
...@@ -593,6 +593,10 @@ ...@@ -593,6 +593,10 @@
#define RLC_UCODE_ADDR 0x3f2c #define RLC_UCODE_ADDR 0x3f2c
#define RLC_UCODE_DATA 0x3f30 #define RLC_UCODE_DATA 0x3f30
/* new for TN */
#define TN_RLC_SAVE_AND_RESTORE_BASE 0x3f10
#define TN_RLC_CLEAR_STATE_RESTORE_BASE 0x3f20
#define SRBM_SOFT_RESET 0xe60 #define SRBM_SOFT_RESET 0xe60
# define SOFT_RESET_RLC (1 << 13) # define SOFT_RESET_RLC (1 << 13)
......
...@@ -2949,7 +2949,7 @@ void si_vm_tlb_flush(struct radeon_device *rdev, struct radeon_vm *vm) ...@@ -2949,7 +2949,7 @@ void si_vm_tlb_flush(struct radeon_device *rdev, struct radeon_vm *vm)
/* /*
* RLC * RLC
*/ */
static void si_rlc_fini(struct radeon_device *rdev) void si_rlc_fini(struct radeon_device *rdev)
{ {
int r; int r;
...@@ -2978,7 +2978,7 @@ static void si_rlc_fini(struct radeon_device *rdev) ...@@ -2978,7 +2978,7 @@ static void si_rlc_fini(struct radeon_device *rdev)
} }
} }
static int si_rlc_init(struct radeon_device *rdev) int si_rlc_init(struct radeon_device *rdev)
{ {
int r; int r;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册