diff options
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu/vega20_ih.c')
| -rw-r--r-- | drivers/gpu/drm/amd/amdgpu/vega20_ih.c | 55 | 
1 files changed, 31 insertions, 24 deletions
| diff --git a/drivers/gpu/drm/amd/amdgpu/vega20_ih.c b/drivers/gpu/drm/amd/amdgpu/vega20_ih.c index 5a3c867d5881..8a122b413bf5 100644 --- a/drivers/gpu/drm/amd/amdgpu/vega20_ih.c +++ b/drivers/gpu/drm/amd/amdgpu/vega20_ih.c @@ -35,6 +35,9 @@  #define MAX_REARM_RETRY 10 +#define mmIH_CHICKEN_ALDEBARAN			0x18d +#define mmIH_CHICKEN_ALDEBARAN_BASE_IDX		0 +  static void vega20_ih_set_interrupt_funcs(struct amdgpu_device *adev);  /** @@ -104,6 +107,8 @@ static int vega20_ih_toggle_ring_interrupts(struct amdgpu_device *adev,  	tmp = RREG32(ih_regs->ih_rb_cntl);  	tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, RB_ENABLE, (enable ? 1 : 0)); +	tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, RB_GPU_TS_ENABLE, 1); +  	/* enable_intr field is only valid in ring0 */  	if (ih == &adev->irq.ih)  		tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, ENABLE_INTR, (enable ? 1 : 0)); @@ -220,10 +225,8 @@ static int vega20_ih_enable_ring(struct amdgpu_device *adev,  	tmp = vega20_ih_rb_cntl(ih, tmp);  	if (ih == &adev->irq.ih)  		tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, RPTR_REARM, !!adev->irq.msi_enabled); -	if (ih == &adev->irq.ih1) { -		tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, WPTR_OVERFLOW_ENABLE, 0); +	if (ih == &adev->irq.ih1)  		tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, RB_FULL_DRAIN_ENABLE, 1); -	}  	if (amdgpu_sriov_vf(adev)) {  		if (psp_reg_program(&adev->psp, ih_regs->psp_reg_id, tmp)) {  			dev_err(adev->dev, "PSP program IH_RB_CNTL failed!\n"); @@ -261,10 +264,10 @@ static void vega20_ih_reroute_ih(struct amdgpu_device *adev)  {  	uint32_t tmp; -	/* vega20 ih reroute will go through psp -	 * this function is only used for arcturus +	/* vega20 ih reroute will go through psp this +	 * function is used for newer asics starting arcturus  	 */ -	if (adev->asic_type == CHIP_ARCTURUS) { +	if (adev->asic_type >= CHIP_ARCTURUS) {  		/* Reroute to IH ring 1 for VMC */  		WREG32_SOC15(OSSSYS, 0, mmIH_CLIENT_CFG_INDEX, 0x12);  		tmp = RREG32_SOC15(OSSSYS, 0, mmIH_CLIENT_CFG_DATA); @@ -297,7 +300,6 @@ static int vega20_ih_irq_init(struct amdgpu_device *adev)  	u32 ih_chicken;  	int ret;  	int i; -	u32 tmp;  	/* disable irqs */  	ret = vega20_ih_toggle_interrupts(adev, false); @@ -316,6 +318,18 @@ static int vega20_ih_irq_init(struct amdgpu_device *adev)  		WREG32_SOC15(OSSSYS, 0, mmIH_CHICKEN, ih_chicken);  	} +	/* psp firmware won't program IH_CHICKEN for aldebaran +	 * driver needs to program it properly according to +	 * MC_SPACE type in IH_RB_CNTL */ +	if (adev->asic_type == CHIP_ALDEBARAN) { +		ih_chicken = RREG32_SOC15(OSSSYS, 0, mmIH_CHICKEN_ALDEBARAN); +		if (adev->irq.ih.use_bus_addr) { +			ih_chicken = REG_SET_FIELD(ih_chicken, IH_CHICKEN, +						   MC_SPACE_GPA_ENABLE, 1); +		} +		WREG32_SOC15(OSSSYS, 0, mmIH_CHICKEN_ALDEBARAN, ih_chicken); +	} +  	for (i = 0; i < ARRAY_SIZE(ih); i++) {  		if (ih[i]->ring_size) {  			if (i == 1) @@ -326,15 +340,6 @@ static int vega20_ih_irq_init(struct amdgpu_device *adev)  		}  	} -	tmp = RREG32_SOC15(OSSSYS, 0, mmIH_STORM_CLIENT_LIST_CNTL); -	tmp = REG_SET_FIELD(tmp, IH_STORM_CLIENT_LIST_CNTL, -			    CLIENT18_IS_STORM_CLIENT, 1); -	WREG32_SOC15(OSSSYS, 0, mmIH_STORM_CLIENT_LIST_CNTL, tmp); - -	tmp = RREG32_SOC15(OSSSYS, 0, mmIH_INT_FLOOD_CNTL); -	tmp = REG_SET_FIELD(tmp, IH_INT_FLOOD_CNTL, FLOOD_CNTL_ENABLE, 1); -	WREG32_SOC15(OSSSYS, 0, mmIH_INT_FLOOD_CNTL, tmp); -  	pci_set_master(adev->pdev);  	/* enable interrupts */ @@ -380,11 +385,17 @@ static u32 vega20_ih_get_wptr(struct amdgpu_device *adev,  	u32 wptr, tmp;  	struct amdgpu_ih_regs *ih_regs; -	wptr = le32_to_cpu(*ih->wptr_cpu); -	ih_regs = &ih->ih_regs; +	if (ih == &adev->irq.ih) { +		/* Only ring0 supports writeback. On other rings fall back +		 * to register-based code with overflow checking below. +		 */ +		wptr = le32_to_cpu(*ih->wptr_cpu); -	if (!REG_GET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW)) -		goto out; +		if (!REG_GET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW)) +			goto out; +	} + +	ih_regs = &ih->ih_regs;  	/* Double check that the overflow wasn't already cleared. */  	wptr = RREG32_NO_KIQ(ih_regs->ih_rb_wptr); @@ -476,15 +487,11 @@ static int vega20_ih_self_irq(struct amdgpu_device *adev,  			      struct amdgpu_irq_src *source,  			      struct amdgpu_iv_entry *entry)  { -	uint32_t wptr = cpu_to_le32(entry->src_data[0]); -  	switch (entry->ring_id) {  	case 1: -		*adev->irq.ih1.wptr_cpu = wptr;  		schedule_work(&adev->irq.ih1_work);  		break;  	case 2: -		*adev->irq.ih2.wptr_cpu = wptr;  		schedule_work(&adev->irq.ih2_work);  		break;  	default: break; | 
