Commit a76b2870 authored by Candice Li's avatar Candice Li Committed by Alex Deucher
Browse files

drm/amdgpu: Add RREG64_PCIE_EXT/WREG64_PCIE_EXT functions



Add 64bits register access support on register whose address
is greater than 32bits.

Signed-off-by: default avatarCandice Li <candice.li@amd.com>
Reviewed-by: default avatarTao Zhou <tao.zhou1@amd.com>
Reviewed-by: default avatarHawking Zhang <Hawking.Zhang@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 9b70a1d4
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -626,6 +626,9 @@ typedef void (*amdgpu_wreg_ext_t)(struct amdgpu_device*, uint64_t, uint32_t);
typedef uint64_t (*amdgpu_rreg64_t)(struct amdgpu_device*, uint32_t);
typedef void (*amdgpu_wreg64_t)(struct amdgpu_device*, uint32_t, uint64_t);

typedef uint64_t (*amdgpu_rreg64_ext_t)(struct amdgpu_device*, uint64_t);
typedef void (*amdgpu_wreg64_ext_t)(struct amdgpu_device*, uint64_t, uint64_t);

typedef uint32_t (*amdgpu_block_rreg_t)(struct amdgpu_device*, uint32_t, uint32_t);
typedef void (*amdgpu_block_wreg_t)(struct amdgpu_device*, uint32_t, uint32_t, uint32_t);

@@ -830,6 +833,8 @@ struct amdgpu_device {
	amdgpu_wreg_ext_t		pcie_wreg_ext;
	amdgpu_rreg64_t			pcie_rreg64;
	amdgpu_wreg64_t			pcie_wreg64;
	amdgpu_rreg64_ext_t			pcie_rreg64_ext;
	amdgpu_wreg64_ext_t			pcie_wreg64_ext;
	/* protects concurrent UVD register access */
	spinlock_t uvd_ctx_idx_lock;
	amdgpu_rreg_t			uvd_ctx_rreg;
@@ -1145,10 +1150,14 @@ u32 amdgpu_device_indirect_rreg(struct amdgpu_device *adev,
				u32 reg_addr);
u64 amdgpu_device_indirect_rreg64(struct amdgpu_device *adev,
				  u32 reg_addr);
u64 amdgpu_device_indirect_rreg64_ext(struct amdgpu_device *adev,
				  u64 reg_addr);
void amdgpu_device_indirect_wreg(struct amdgpu_device *adev,
				 u32 reg_addr, u32 reg_data);
void amdgpu_device_indirect_wreg64(struct amdgpu_device *adev,
				   u32 reg_addr, u64 reg_data);
void amdgpu_device_indirect_wreg64_ext(struct amdgpu_device *adev,
				   u64 reg_addr, u64 reg_data);
u32 amdgpu_device_get_rev_id(struct amdgpu_device *adev);
bool amdgpu_device_asic_has_dc_support(enum amd_asic_type asic_type);
bool amdgpu_device_has_dc_support(struct amdgpu_device *adev);
@@ -1191,6 +1200,8 @@ int emu_soc_asic_init(struct amdgpu_device *adev);
#define WREG32_PCIE_EXT(reg, v) adev->pcie_wreg_ext(adev, (reg), (v))
#define RREG64_PCIE(reg) adev->pcie_rreg64(adev, (reg))
#define WREG64_PCIE(reg, v) adev->pcie_wreg64(adev, (reg), (v))
#define RREG64_PCIE_EXT(reg) adev->pcie_rreg64_ext(adev, (reg))
#define WREG64_PCIE_EXT(reg, v) adev->pcie_wreg64_ext(adev, (reg), (v))
#define RREG32_SMC(reg) adev->smc_rreg(adev, (reg))
#define WREG32_SMC(reg, v) adev->smc_wreg(adev, (reg), (v))
#define RREG32_UVD_CTX(reg) adev->uvd_ctx_rreg(adev, (reg))
+115 −0
Original line number Diff line number Diff line
@@ -639,6 +639,56 @@ u64 amdgpu_device_indirect_rreg64(struct amdgpu_device *adev,
	return r;
}

u64 amdgpu_device_indirect_rreg64_ext(struct amdgpu_device *adev,
				  u64 reg_addr)
{
	unsigned long flags, pcie_index, pcie_data;
	unsigned long pcie_index_hi = 0;
	void __iomem *pcie_index_offset;
	void __iomem *pcie_index_hi_offset;
	void __iomem *pcie_data_offset;
	u64 r;

	pcie_index = adev->nbio.funcs->get_pcie_index_offset(adev);
	pcie_data = adev->nbio.funcs->get_pcie_data_offset(adev);
	if ((reg_addr >> 32) && (adev->nbio.funcs->get_pcie_index_hi_offset))
		pcie_index_hi = adev->nbio.funcs->get_pcie_index_hi_offset(adev);

	spin_lock_irqsave(&adev->pcie_idx_lock, flags);
	pcie_index_offset = (void __iomem *)adev->rmmio + pcie_index * 4;
	pcie_data_offset = (void __iomem *)adev->rmmio + pcie_data * 4;
	if (pcie_index_hi != 0)
		pcie_index_hi_offset = (void __iomem *)adev->rmmio +
			pcie_index_hi * 4;

	/* read low 32 bits */
	writel(reg_addr, pcie_index_offset);
	readl(pcie_index_offset);
	if (pcie_index_hi != 0) {
		writel((reg_addr >> 32) & 0xff, pcie_index_hi_offset);
		readl(pcie_index_hi_offset);
	}
	r = readl(pcie_data_offset);
	/* read high 32 bits */
	writel(reg_addr + 4, pcie_index_offset);
	readl(pcie_index_offset);
	if (pcie_index_hi != 0) {
		writel((reg_addr >> 32) & 0xff, pcie_index_hi_offset);
		readl(pcie_index_hi_offset);
	}
	r |= ((u64)readl(pcie_data_offset) << 32);

	/* clear the high bits */
	if (pcie_index_hi != 0) {
		writel(0, pcie_index_hi_offset);
		readl(pcie_index_hi_offset);
	}

	spin_unlock_irqrestore(&adev->pcie_idx_lock, flags);

	return r;
}

/**
 * amdgpu_device_indirect_wreg - write an indirect register address
 *
@@ -743,6 +793,55 @@ void amdgpu_device_indirect_wreg64(struct amdgpu_device *adev,
	spin_unlock_irqrestore(&adev->pcie_idx_lock, flags);
}

void amdgpu_device_indirect_wreg64_ext(struct amdgpu_device *adev,
				   u64 reg_addr, u64 reg_data)
{
	unsigned long flags, pcie_index, pcie_data;
	unsigned long pcie_index_hi = 0;
	void __iomem *pcie_index_offset;
	void __iomem *pcie_index_hi_offset;
	void __iomem *pcie_data_offset;

	pcie_index = adev->nbio.funcs->get_pcie_index_offset(adev);
	pcie_data = adev->nbio.funcs->get_pcie_data_offset(adev);
	if ((reg_addr >> 32) && (adev->nbio.funcs->get_pcie_index_hi_offset))
		pcie_index_hi = adev->nbio.funcs->get_pcie_index_hi_offset(adev);

	spin_lock_irqsave(&adev->pcie_idx_lock, flags);
	pcie_index_offset = (void __iomem *)adev->rmmio + pcie_index * 4;
	pcie_data_offset = (void __iomem *)adev->rmmio + pcie_data * 4;
	if (pcie_index_hi != 0)
		pcie_index_hi_offset = (void __iomem *)adev->rmmio +
				pcie_index_hi * 4;

	/* write low 32 bits */
	writel(reg_addr, pcie_index_offset);
	readl(pcie_index_offset);
	if (pcie_index_hi != 0) {
		writel((reg_addr >> 32) & 0xff, pcie_index_hi_offset);
		readl(pcie_index_hi_offset);
	}
	writel((u32)(reg_data & 0xffffffffULL), pcie_data_offset);
	readl(pcie_data_offset);
	/* write high 32 bits */
	writel(reg_addr + 4, pcie_index_offset);
	readl(pcie_index_offset);
	if (pcie_index_hi != 0) {
		writel((reg_addr >> 32) & 0xff, pcie_index_hi_offset);
		readl(pcie_index_hi_offset);
	}
	writel((u32)(reg_data >> 32), pcie_data_offset);
	readl(pcie_data_offset);

	/* clear the high bits */
	if (pcie_index_hi != 0) {
		writel(0, pcie_index_hi_offset);
		readl(pcie_index_hi_offset);
	}

	spin_unlock_irqrestore(&adev->pcie_idx_lock, flags);
}

/**
 * amdgpu_device_get_rev_id - query device rev_id
 *
@@ -820,6 +919,13 @@ static uint64_t amdgpu_invalid_rreg64(struct amdgpu_device *adev, uint32_t reg)
	return 0;
}

static uint64_t amdgpu_invalid_rreg64_ext(struct amdgpu_device *adev, uint64_t reg)
{
	DRM_ERROR("Invalid callback to read register 0x%llX\n", reg);
	BUG();
	return 0;
}

/**
 * amdgpu_invalid_wreg64 - dummy reg write function
 *
@@ -837,6 +943,13 @@ static void amdgpu_invalid_wreg64(struct amdgpu_device *adev, uint32_t reg, uint
	BUG();
}

static void amdgpu_invalid_wreg64_ext(struct amdgpu_device *adev, uint64_t reg, uint64_t v)
{
	DRM_ERROR("Invalid callback to write 64 bit register 0x%llX with 0x%08llX\n",
		  reg, v);
	BUG();
}

/**
 * amdgpu_block_invalid_rreg - dummy reg read function
 *
@@ -3569,6 +3682,8 @@ int amdgpu_device_init(struct amdgpu_device *adev,
	adev->pciep_wreg = &amdgpu_invalid_wreg;
	adev->pcie_rreg64 = &amdgpu_invalid_rreg64;
	adev->pcie_wreg64 = &amdgpu_invalid_wreg64;
	adev->pcie_rreg64_ext = &amdgpu_invalid_rreg64_ext;
	adev->pcie_wreg64_ext = &amdgpu_invalid_wreg64_ext;
	adev->uvd_ctx_rreg = &amdgpu_invalid_rreg;
	adev->uvd_ctx_wreg = &amdgpu_invalid_wreg;
	adev->didt_rreg = &amdgpu_invalid_rreg;
+2 −0
Original line number Diff line number Diff line
@@ -921,6 +921,8 @@ static int soc15_common_early_init(void *handle)
	adev->pcie_wreg_ext = &amdgpu_device_indirect_wreg_ext;
	adev->pcie_rreg64 = &amdgpu_device_indirect_rreg64;
	adev->pcie_wreg64 = &amdgpu_device_indirect_wreg64;
	adev->pcie_rreg64_ext = &amdgpu_device_indirect_rreg64_ext;
	adev->pcie_wreg64_ext = &amdgpu_device_indirect_wreg64_ext;
	adev->uvd_ctx_rreg = &soc15_uvd_ctx_rreg;
	adev->uvd_ctx_wreg = &soc15_uvd_ctx_wreg;
	adev->didt_rreg = &soc15_didt_rreg;