Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c420c745 authored by Alex Deucher's avatar Alex Deucher Committed by Dave Airlie
Browse files

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



v2: fix check for MC ucode from Tom.

Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
parent e71270fd
Loading
Loading
Loading
Loading
+64 −18
Original line number Diff line number Diff line
@@ -42,6 +42,8 @@ extern void evergreen_irq_suspend(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_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_PM4_UCODE_SIZE 1376
@@ -53,6 +55,8 @@ extern void evergreen_pcie_gen2_enable(struct radeon_device *rdev);
#define CAYMAN_RLC_UCODE_SIZE 1024
#define CAYMAN_MC_UCODE_SIZE 6037

#define ARUBA_RLC_UCODE_SIZE 1536

/* Firmware Names */
MODULE_FIRMWARE("radeon/BARTS_pfp.bin");
MODULE_FIRMWARE("radeon/BARTS_me.bin");
@@ -68,6 +72,9 @@ MODULE_FIRMWARE("radeon/CAYMAN_pfp.bin");
MODULE_FIRMWARE("radeon/CAYMAN_me.bin");
MODULE_FIRMWARE("radeon/CAYMAN_mc.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

@@ -326,6 +333,15 @@ int ni_init_microcode(struct radeon_device *rdev)
		rlc_req_size = CAYMAN_RLC_UCODE_SIZE * 4;
		mc_req_size = CAYMAN_MC_UCODE_SIZE * 4;
		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();
	}

@@ -365,6 +381,8 @@ int ni_init_microcode(struct radeon_device *rdev)
		err = -EINVAL;
	}

	/* no MC ucode on TN */
	if (!(rdev->flags & RADEON_IS_IGP)) {
		snprintf(fw_name, sizeof(fw_name), "radeon/%s_mc.bin", chip_name);
		err = request_firmware(&rdev->mc_fw, fw_name, &pdev->dev);
		if (err)
@@ -375,6 +393,7 @@ int ni_init_microcode(struct radeon_device *rdev)
			       rdev->mc_fw->size, fw_name);
			err = -EINVAL;
		}
	}
out:
	platform_device_unregister(pdev);

@@ -1484,6 +1503,15 @@ static int cayman_startup(struct radeon_device *rdev)
	/* enable pcie gen2 link */
	evergreen_pcie_gen2_enable(rdev);

	if (rdev->flags & RADEON_IS_IGP) {
		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) {
@@ -1491,11 +1519,13 @@ static int cayman_startup(struct radeon_device *rdev)
				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);
	if (r)
@@ -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);
	}

	/* 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 */
	r = radeon_wb_init(rdev);
	if (r)
@@ -1698,6 +1737,8 @@ int cayman_init(struct radeon_device *rdev)
		dev_err(rdev->dev, "disabling GPU acceleration\n");
		cayman_cp_fini(rdev);
		r600_irq_fini(rdev);
		if (rdev->flags & RADEON_IS_IGP)
			si_rlc_fini(rdev);
		radeon_wb_fini(rdev);
		r100_ib_fini(rdev);
		radeon_vm_manager_fini(rdev);
@@ -1709,8 +1750,11 @@ int cayman_init(struct radeon_device *rdev)
	/* Don't start up if the MC ucode is missing.
	 * The default clocks and voltages before the MC ucode
	 * 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");
		return -EINVAL;
	}
@@ -1723,6 +1767,8 @@ void cayman_fini(struct radeon_device *rdev)
	r600_blit_fini(rdev);
	cayman_cp_fini(rdev);
	r600_irq_fini(rdev);
	if (rdev->flags & RADEON_IS_IGP)
		si_rlc_fini(rdev);
	radeon_wb_fini(rdev);
	radeon_vm_manager_fini(rdev);
	r100_ib_fini(rdev);
+17 −4
Original line number Diff line number Diff line
@@ -49,6 +49,7 @@
#define EVERGREEN_PM4_UCODE_SIZE 1376
#define EVERGREEN_RLC_UCODE_SIZE 768
#define CAYMAN_RLC_UCODE_SIZE 1024
#define ARUBA_RLC_UCODE_SIZE 1536

/* Firmware Names */
MODULE_FIRMWARE("radeon/R600_pfp.bin");
@@ -2861,10 +2862,17 @@ static int r600_rlc_init(struct radeon_device *rdev)

	r600_rlc_stop(rdev);

	WREG32(RLC_HB_BASE, 0);
	WREG32(RLC_HB_CNTL, 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) {
		WREG32(RLC_HB_WPTR_LSB_ADDR, 0);
		WREG32(RLC_HB_WPTR_MSB_ADDR, 0);
@@ -2873,7 +2881,12 @@ static int r600_rlc_init(struct radeon_device *rdev)
	WREG32(RLC_UCODE_CNTL, 0);

	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++) {
			WREG32(RLC_UCODE_ADDR, i);
			WREG32(RLC_UCODE_DATA, be32_to_cpup(fw_data++));
+4 −0
Original line number Diff line number Diff line
@@ -593,6 +593,10 @@
#define RLC_UCODE_ADDR                                    0x3f2c
#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 SOFT_RESET_RLC                             (1 << 13)

+2 −2
Original line number Diff line number Diff line
@@ -2949,7 +2949,7 @@ void si_vm_tlb_flush(struct radeon_device *rdev, struct radeon_vm *vm)
/*
 * RLC
 */
static void si_rlc_fini(struct radeon_device *rdev)
void si_rlc_fini(struct radeon_device *rdev)
{
	int r;

@@ -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;