diff options
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu')
| -rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu.h | 11 | ||||
| -rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 73 | ||||
| -rw-r--r-- | drivers/gpu/drm/amd/amdgpu/soc15.c | 45 | 
3 files changed, 129 insertions, 0 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index c23cffc246e4..61bd7be69a3f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -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)) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 2081649f49ca..6940600ebf0e 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -262,6 +262,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   *   * @adev: amdgpu_device pointer @@ -417,6 +454,40 @@ static void amdgpu_invalid_wreg(struct amdgpu_device *adev, uint32_t reg, uint32  }  /** + * 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   *   * @adev: amdgpu device pointer @@ -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; diff --git a/drivers/gpu/drm/amd/amdgpu/soc15.c b/drivers/gpu/drm/amd/amdgpu/soc15.c index e528122bb7b4..bac232f9c627 100644 --- a/drivers/gpu/drm/amd/amdgpu/soc15.c +++ b/drivers/gpu/drm/amd/amdgpu/soc15.c @@ -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;  | 

