Commit 4fa1c6a6 authored by Tao Zhou's avatar Tao Zhou Committed by Alex Deucher
Browse files

drm/amdgpu: add RREG64/WREG64(_PCIE) operations



add 64 bits register access functions

v2: implement 64 bit functions in low level

Signed-off-by: default avatarTao Zhou <tao.zhou1@amd.com>
Reviewed-by: default avatarDennis Li <dennis.li@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 05a58345
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -637,6 +637,9 @@ void amdgpu_cgs_destroy_device(struct cgs_device *cgs_device);
typedef uint32_t (*amdgpu_rreg_t)(struct amdgpu_device*, uint32_t);
typedef void (*amdgpu_wreg_t)(struct amdgpu_device*, uint32_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 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_t			pcie_wreg;
	amdgpu_rreg_t			pciep_rreg;
	amdgpu_wreg_t			pciep_wreg;
	amdgpu_rreg64_t			pcie_rreg64;
	amdgpu_wreg64_t			pcie_wreg64;
	/* protects concurrent UVD register access */
	spinlock_t uvd_ctx_idx_lock;
	amdgpu_rreg_t			uvd_ctx_rreg;
@@ -1030,6 +1035,8 @@ void amdgpu_mm_wreg(struct amdgpu_device *adev, uint32_t reg, uint32_t v,
		    uint32_t acc_flags);
void amdgpu_mm_wreg8(struct amdgpu_device *adev, uint32_t offset, uint8_t value);
uint8_t amdgpu_mm_rreg8(struct amdgpu_device *adev, uint32_t offset);
uint64_t amdgpu_mm_rreg64(struct amdgpu_device *adev, uint32_t reg);
void amdgpu_mm_wreg64(struct amdgpu_device *adev, uint32_t reg, uint64_t v);

u32 amdgpu_io_rreg(struct amdgpu_device *adev, u32 reg);
void amdgpu_io_wreg(struct amdgpu_device *adev, u32 reg, u32 v);
@@ -1057,12 +1064,16 @@ int emu_soc_asic_init(struct amdgpu_device *adev);
#define DREG32(reg) printk(KERN_INFO "REGISTER: " #reg " : 0x%08X\n", amdgpu_mm_rreg(adev, (reg), 0))
#define WREG32(reg, v) amdgpu_mm_wreg(adev, (reg), (v), 0)
#define WREG32_IDX(reg, v) amdgpu_mm_wreg(adev, (reg), (v), AMDGPU_REGS_IDX)
#define RREG64(reg) amdgpu_mm_rreg64(adev, (reg))
#define WREG64(reg, v) amdgpu_mm_wreg64(adev, (reg), (v))
#define REG_SET(FIELD, v) (((v) << FIELD##_SHIFT) & FIELD##_MASK)
#define REG_GET(FIELD, v) (((v) << FIELD##_SHIFT) & FIELD##_MASK)
#define RREG32_PCIE(reg) adev->pcie_rreg(adev, (reg))
#define WREG32_PCIE(reg, v) adev->pcie_wreg(adev, (reg), (v))
#define RREG32_PCIE_PORT(reg) adev->pciep_rreg(adev, (reg))
#define WREG32_PCIE_PORT(reg, v) adev->pciep_wreg(adev, (reg), (v))
#define RREG64_PCIE(reg) adev->pcie_rreg64(adev, (reg))
#define WREG64_PCIE(reg, v) adev->pcie_wreg64(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))
+73 −0
Original line number Diff line number Diff line
@@ -261,6 +261,43 @@ void amdgpu_mm_wreg(struct amdgpu_device *adev, uint32_t reg, uint32_t v,
	}
}

/**
 * amdgpu_mm_rreg64 - read a 64 bit memory mapped IO register
 *
 * @adev: amdgpu_device pointer
 * @reg: dword aligned register offset
 *
 * Returns the 64 bit value from the offset specified.
 */
uint64_t amdgpu_mm_rreg64(struct amdgpu_device *adev, uint32_t reg)
{
	uint64_t ret;

	if ((reg * 4) < adev->rmmio_size)
		ret = readq(((void __iomem *)adev->rmmio) + (reg * 4));
	else
		BUG();

	return ret;
}

/**
 * amdgpu_mm_wreg64 - write to a 64 bit memory mapped IO register
 *
 * @adev: amdgpu_device pointer
 * @reg: dword aligned register offset
 * @v: 64 bit value to write to the register
 *
 * Writes the value specified to the offset specified.
 */
void amdgpu_mm_wreg64(struct amdgpu_device *adev, uint32_t reg, uint64_t v)
{
	if ((reg * 4) < adev->rmmio_size)
		writeq(v, ((void __iomem *)adev->rmmio) + (reg * 4));
	else
		BUG();
}

/**
 * amdgpu_io_rreg - read an IO register
 *
@@ -416,6 +453,40 @@ static void amdgpu_invalid_wreg(struct amdgpu_device *adev, uint32_t reg, uint32
	BUG();
}

/**
 * amdgpu_invalid_rreg64 - dummy 64 bit reg read function
 *
 * @adev: amdgpu device pointer
 * @reg: offset of register
 *
 * Dummy register read function.  Used for register blocks
 * that certain asics don't have (all asics).
 * Returns the value in the register.
 */
static uint64_t amdgpu_invalid_rreg64(struct amdgpu_device *adev, uint32_t reg)
{
	DRM_ERROR("Invalid callback to read 64 bit register 0x%04X\n", reg);
	BUG();
	return 0;
}

/**
 * amdgpu_invalid_wreg64 - dummy reg write function
 *
 * @adev: amdgpu device pointer
 * @reg: offset of register
 * @v: value to write to the register
 *
 * Dummy register read function.  Used for register blocks
 * that certain asics don't have (all asics).
 */
static void amdgpu_invalid_wreg64(struct amdgpu_device *adev, uint32_t reg, uint64_t v)
{
	DRM_ERROR("Invalid callback to write 64 bit register 0x%04X with 0x%08llX\n",
		  reg, v);
	BUG();
}

/**
 * amdgpu_block_invalid_rreg - dummy reg read function
 *
@@ -2537,6 +2608,8 @@ int amdgpu_device_init(struct amdgpu_device *adev,
	adev->pcie_wreg = &amdgpu_invalid_wreg;
	adev->pciep_rreg = &amdgpu_invalid_rreg;
	adev->pciep_wreg = &amdgpu_invalid_wreg;
	adev->pcie_rreg64 = &amdgpu_invalid_rreg64;
	adev->pcie_wreg64 = &amdgpu_invalid_wreg64;
	adev->uvd_ctx_rreg = &amdgpu_invalid_rreg;
	adev->uvd_ctx_wreg = &amdgpu_invalid_wreg;
	adev->didt_rreg = &amdgpu_invalid_rreg;
+45 −0
Original line number Diff line number Diff line
@@ -116,6 +116,49 @@ static void soc15_pcie_wreg(struct amdgpu_device *adev, u32 reg, u32 v)
	spin_unlock_irqrestore(&adev->pcie_idx_lock, flags);
}

static u64 soc15_pcie_rreg64(struct amdgpu_device *adev, u32 reg)
{
	unsigned long flags, address, data;
	u64 r;
	address = adev->nbio_funcs->get_pcie_index_offset(adev);
	data = adev->nbio_funcs->get_pcie_data_offset(adev);

	spin_lock_irqsave(&adev->pcie_idx_lock, flags);
	/* read low 32 bit */
	WREG32(address, reg);
	(void)RREG32(address);
	r = RREG32(data);

	/* read high 32 bit*/
	WREG32(address, reg + 4);
	(void)RREG32(address);
	r |= ((u64)RREG32(data) << 32);
	spin_unlock_irqrestore(&adev->pcie_idx_lock, flags);
	return r;
}

static void soc15_pcie_wreg64(struct amdgpu_device *adev, u32 reg, u64 v)
{
	unsigned long flags, address, data;

	address = adev->nbio_funcs->get_pcie_index_offset(adev);
	data = adev->nbio_funcs->get_pcie_data_offset(adev);

	spin_lock_irqsave(&adev->pcie_idx_lock, flags);
	/* write low 32 bit */
	WREG32(address, reg);
	(void)RREG32(address);
	WREG32(data, (u32)(v & 0xffffffffULL));
	(void)RREG32(data);

	/* write high 32 bit */
	WREG32(address, reg + 4);
	(void)RREG32(address);
	WREG32(data, (u32)(v >> 32));
	(void)RREG32(data);
	spin_unlock_irqrestore(&adev->pcie_idx_lock, flags);
}

static u32 soc15_uvd_ctx_rreg(struct amdgpu_device *adev, u32 reg)
{
	unsigned long flags, address, data;
@@ -866,6 +909,8 @@ static int soc15_common_early_init(void *handle)
	adev->smc_wreg = NULL;
	adev->pcie_rreg = &soc15_pcie_rreg;
	adev->pcie_wreg = &soc15_pcie_wreg;
	adev->pcie_rreg64 = &soc15_pcie_rreg64;
	adev->pcie_wreg64 = &soc15_pcie_wreg64;
	adev->uvd_ctx_rreg = &soc15_uvd_ctx_rreg;
	adev->uvd_ctx_wreg = &soc15_uvd_ctx_wreg;
	adev->didt_rreg = &soc15_didt_rreg;