summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/amd/amdgpu/vega10_ih.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu/vega10_ih.c')
-rw-r--r--drivers/gpu/drm/amd/amdgpu/vega10_ih.c483
1 files changed, 188 insertions, 295 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/vega10_ih.c b/drivers/gpu/drm/amd/amdgpu/vega10_ih.c
index e5ae31eb744e..88626d83e07b 100644
--- a/drivers/gpu/drm/amd/amdgpu/vega10_ih.c
+++ b/drivers/gpu/drm/amd/amdgpu/vega10_ih.c
@@ -38,132 +38,120 @@
static void vega10_ih_set_interrupt_funcs(struct amdgpu_device *adev);
/**
- * vega10_ih_enable_interrupts - Enable the interrupt ring buffer
+ * vega10_ih_init_register_offset - Initialize register offset for ih rings
*
* @adev: amdgpu_device pointer
*
- * Enable the interrupt ring buffer (VEGA10).
+ * Initialize register offset ih rings (VEGA10).
*/
-static void vega10_ih_enable_interrupts(struct amdgpu_device *adev)
+static void vega10_ih_init_register_offset(struct amdgpu_device *adev)
{
- u32 ih_rb_cntl = RREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL);
-
- ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, RB_ENABLE, 1);
- ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, ENABLE_INTR, 1);
- if (amdgpu_sriov_vf(adev)) {
- if (psp_reg_program(&adev->psp, PSP_REG_IH_RB_CNTL, ih_rb_cntl)) {
- DRM_ERROR("PSP program IH_RB_CNTL failed!\n");
- return;
- }
- } else {
- WREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL, ih_rb_cntl);
+ struct amdgpu_ih_regs *ih_regs;
+
+ if (adev->irq.ih.ring_size) {
+ ih_regs = &adev->irq.ih.ih_regs;
+ ih_regs->ih_rb_base = SOC15_REG_OFFSET(OSSSYS, 0, mmIH_RB_BASE);
+ ih_regs->ih_rb_base_hi = SOC15_REG_OFFSET(OSSSYS, 0, mmIH_RB_BASE_HI);
+ ih_regs->ih_rb_cntl = SOC15_REG_OFFSET(OSSSYS, 0, mmIH_RB_CNTL);
+ ih_regs->ih_rb_wptr = SOC15_REG_OFFSET(OSSSYS, 0, mmIH_RB_WPTR);
+ ih_regs->ih_rb_rptr = SOC15_REG_OFFSET(OSSSYS, 0, mmIH_RB_RPTR);
+ ih_regs->ih_doorbell_rptr = SOC15_REG_OFFSET(OSSSYS, 0, mmIH_DOORBELL_RPTR);
+ ih_regs->ih_rb_wptr_addr_lo = SOC15_REG_OFFSET(OSSSYS, 0, mmIH_RB_WPTR_ADDR_LO);
+ ih_regs->ih_rb_wptr_addr_hi = SOC15_REG_OFFSET(OSSSYS, 0, mmIH_RB_WPTR_ADDR_HI);
+ ih_regs->psp_reg_id = PSP_REG_IH_RB_CNTL;
}
- adev->irq.ih.enabled = true;
if (adev->irq.ih1.ring_size) {
- ih_rb_cntl = RREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING1);
- ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL_RING1,
- RB_ENABLE, 1);
- if (amdgpu_sriov_vf(adev)) {
- if (psp_reg_program(&adev->psp, PSP_REG_IH_RB_CNTL_RING1,
- ih_rb_cntl)) {
- DRM_ERROR("program IH_RB_CNTL_RING1 failed!\n");
- return;
- }
- } else {
- WREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING1, ih_rb_cntl);
- }
- adev->irq.ih1.enabled = true;
+ ih_regs = &adev->irq.ih1.ih_regs;
+ ih_regs->ih_rb_base = SOC15_REG_OFFSET(OSSSYS, 0, mmIH_RB_BASE_RING1);
+ ih_regs->ih_rb_base_hi = SOC15_REG_OFFSET(OSSSYS, 0, mmIH_RB_BASE_HI_RING1);
+ ih_regs->ih_rb_cntl = SOC15_REG_OFFSET(OSSSYS, 0, mmIH_RB_CNTL_RING1);
+ ih_regs->ih_rb_wptr = SOC15_REG_OFFSET(OSSSYS, 0, mmIH_RB_WPTR_RING1);
+ ih_regs->ih_rb_rptr = SOC15_REG_OFFSET(OSSSYS, 0, mmIH_RB_RPTR_RING1);
+ ih_regs->ih_doorbell_rptr = SOC15_REG_OFFSET(OSSSYS, 0, mmIH_DOORBELL_RPTR_RING1);
+ ih_regs->psp_reg_id = PSP_REG_IH_RB_CNTL_RING1;
}
if (adev->irq.ih2.ring_size) {
- ih_rb_cntl = RREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING2);
- ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL_RING2,
- RB_ENABLE, 1);
- if (amdgpu_sriov_vf(adev)) {
- if (psp_reg_program(&adev->psp, PSP_REG_IH_RB_CNTL_RING2,
- ih_rb_cntl)) {
- DRM_ERROR("program IH_RB_CNTL_RING2 failed!\n");
- return;
- }
- } else {
- WREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING2, ih_rb_cntl);
- }
- adev->irq.ih2.enabled = true;
+ ih_regs = &adev->irq.ih2.ih_regs;
+ ih_regs->ih_rb_base = SOC15_REG_OFFSET(OSSSYS, 0, mmIH_RB_BASE_RING2);
+ ih_regs->ih_rb_base_hi = SOC15_REG_OFFSET(OSSSYS, 0, mmIH_RB_BASE_HI_RING2);
+ ih_regs->ih_rb_cntl = SOC15_REG_OFFSET(OSSSYS, 0, mmIH_RB_CNTL_RING2);
+ ih_regs->ih_rb_wptr = SOC15_REG_OFFSET(OSSSYS, 0, mmIH_RB_WPTR_RING2);
+ ih_regs->ih_rb_rptr = SOC15_REG_OFFSET(OSSSYS, 0, mmIH_RB_RPTR_RING2);
+ ih_regs->ih_doorbell_rptr = SOC15_REG_OFFSET(OSSSYS, 0, mmIH_DOORBELL_RPTR_RING2);
+ ih_regs->psp_reg_id = PSP_REG_IH_RB_CNTL_RING2;
}
-
- if (adev->irq.ih_soft.ring_size)
- adev->irq.ih_soft.enabled = true;
}
/**
- * vega10_ih_disable_interrupts - Disable the interrupt ring buffer
+ * vega10_ih_toggle_ring_interrupts - toggle the interrupt ring buffer
*
* @adev: amdgpu_device pointer
+ * @ih: amdgpu_ih_ring pointet
+ * @enable: true - enable the interrupts, false - disable the interrupts
*
- * Disable the interrupt ring buffer (VEGA10).
+ * Toggle the interrupt ring buffer (VEGA10)
*/
-static void vega10_ih_disable_interrupts(struct amdgpu_device *adev)
+static int vega10_ih_toggle_ring_interrupts(struct amdgpu_device *adev,
+ struct amdgpu_ih_ring *ih,
+ bool enable)
{
- u32 ih_rb_cntl = RREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL);
+ struct amdgpu_ih_regs *ih_regs;
+ uint32_t tmp;
- ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, RB_ENABLE, 0);
- ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, ENABLE_INTR, 0);
+ ih_regs = &ih->ih_regs;
+
+ tmp = RREG32(ih_regs->ih_rb_cntl);
+ tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, RB_ENABLE, (enable ? 1 : 0));
+ /* 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));
if (amdgpu_sriov_vf(adev)) {
- if (psp_reg_program(&adev->psp, PSP_REG_IH_RB_CNTL, ih_rb_cntl)) {
- DRM_ERROR("PSP program IH_RB_CNTL failed!\n");
- return;
+ if (psp_reg_program(&adev->psp, ih_regs->psp_reg_id, tmp)) {
+ dev_err(adev->dev, "PSP program IH_RB_CNTL failed!\n");
+ return -ETIMEDOUT;
}
} else {
- WREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL, ih_rb_cntl);
+ WREG32(ih_regs->ih_rb_cntl, tmp);
}
- /* set rptr, wptr to 0 */
- WREG32_SOC15(OSSSYS, 0, mmIH_RB_RPTR, 0);
- WREG32_SOC15(OSSSYS, 0, mmIH_RB_WPTR, 0);
- adev->irq.ih.enabled = false;
- adev->irq.ih.rptr = 0;
-
- if (adev->irq.ih1.ring_size) {
- ih_rb_cntl = RREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING1);
- ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL_RING1,
- RB_ENABLE, 0);
- if (amdgpu_sriov_vf(adev)) {
- if (psp_reg_program(&adev->psp, PSP_REG_IH_RB_CNTL_RING1,
- ih_rb_cntl)) {
- DRM_ERROR("program IH_RB_CNTL_RING1 failed!\n");
- return;
- }
- } else {
- WREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING1, ih_rb_cntl);
- }
+ if (enable) {
+ ih->enabled = true;
+ } else {
/* set rptr, wptr to 0 */
- WREG32_SOC15(OSSSYS, 0, mmIH_RB_RPTR_RING1, 0);
- WREG32_SOC15(OSSSYS, 0, mmIH_RB_WPTR_RING1, 0);
- adev->irq.ih1.enabled = false;
- adev->irq.ih1.rptr = 0;
+ WREG32(ih_regs->ih_rb_rptr, 0);
+ WREG32(ih_regs->ih_rb_wptr, 0);
+ ih->enabled = false;
+ ih->rptr = 0;
}
- if (adev->irq.ih2.ring_size) {
- ih_rb_cntl = RREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING2);
- ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL_RING2,
- RB_ENABLE, 0);
- if (amdgpu_sriov_vf(adev)) {
- if (psp_reg_program(&adev->psp, PSP_REG_IH_RB_CNTL_RING2,
- ih_rb_cntl)) {
- DRM_ERROR("program IH_RB_CNTL_RING2 failed!\n");
- return;
- }
- } else {
- WREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING2, ih_rb_cntl);
- }
+ return 0;
+}
- /* set rptr, wptr to 0 */
- WREG32_SOC15(OSSSYS, 0, mmIH_RB_RPTR_RING2, 0);
- WREG32_SOC15(OSSSYS, 0, mmIH_RB_WPTR_RING2, 0);
- adev->irq.ih2.enabled = false;
- adev->irq.ih2.rptr = 0;
+/**
+ * vega10_ih_toggle_interrupts - Toggle all the available interrupt ring buffers
+ *
+ * @adev: amdgpu_device pointer
+ * @enable: enable or disable interrupt ring buffers
+ *
+ * Toggle all the available interrupt ring buffers (VEGA10).
+ */
+static int vega10_ih_toggle_interrupts(struct amdgpu_device *adev, bool enable)
+{
+ struct amdgpu_ih_ring *ih[] = {&adev->irq.ih, &adev->irq.ih1, &adev->irq.ih2};
+ int i;
+ int r;
+
+ for (i = 0; i < ARRAY_SIZE(ih); i++) {
+ if (ih[i]->ring_size) {
+ r = vega10_ih_toggle_ring_interrupts(adev, ih[i], enable);
+ if (r)
+ return r;
+ }
}
+
+ return 0;
}
static uint32_t vega10_ih_rb_cntl(struct amdgpu_ih_ring *ih, uint32_t ih_rb_cntl)
@@ -209,6 +197,58 @@ static uint32_t vega10_ih_doorbell_rptr(struct amdgpu_ih_ring *ih)
}
/**
+ * vega10_ih_enable_ring - enable an ih ring buffer
+ *
+ * @adev: amdgpu_device pointer
+ * @ih: amdgpu_ih_ring pointer
+ *
+ * Enable an ih ring buffer (VEGA10)
+ */
+static int vega10_ih_enable_ring(struct amdgpu_device *adev,
+ struct amdgpu_ih_ring *ih)
+{
+ struct amdgpu_ih_regs *ih_regs;
+ uint32_t tmp;
+
+ ih_regs = &ih->ih_regs;
+
+ /* Ring Buffer base. [39:8] of 40-bit address of the beginning of the ring buffer*/
+ WREG32(ih_regs->ih_rb_base, ih->gpu_addr >> 8);
+ WREG32(ih_regs->ih_rb_base_hi, (ih->gpu_addr >> 40) & 0xff);
+
+ tmp = RREG32(ih_regs->ih_rb_cntl);
+ tmp = vega10_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);
+ 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");
+ return -ETIMEDOUT;
+ }
+ } else {
+ WREG32(ih_regs->ih_rb_cntl, tmp);
+ }
+
+ if (ih == &adev->irq.ih) {
+ /* set the ih ring 0 writeback address whether it's enabled or not */
+ WREG32(ih_regs->ih_rb_wptr_addr_lo, lower_32_bits(ih->wptr_addr));
+ WREG32(ih_regs->ih_rb_wptr_addr_hi, upper_32_bits(ih->wptr_addr) & 0xFFFF);
+ }
+
+ /* set rptr, wptr to 0 */
+ WREG32(ih_regs->ih_rb_wptr, 0);
+ WREG32(ih_regs->ih_rb_rptr, 0);
+
+ WREG32(ih_regs->ih_doorbell_rptr, vega10_ih_doorbell_rptr(ih));
+
+ return 0;
+}
+
+/**
* vega10_ih_irq_init - init and enable the interrupt ring
*
* @adev: amdgpu_device pointer
@@ -221,116 +261,34 @@ static uint32_t vega10_ih_doorbell_rptr(struct amdgpu_ih_ring *ih)
*/
static int vega10_ih_irq_init(struct amdgpu_device *adev)
{
- struct amdgpu_ih_ring *ih;
- u32 ih_rb_cntl, ih_chicken;
- int ret = 0;
+ struct amdgpu_ih_ring *ih[] = {&adev->irq.ih, &adev->irq.ih1, &adev->irq.ih2};
+ u32 ih_chicken;
+ int ret;
+ int i;
u32 tmp;
/* disable irqs */
- vega10_ih_disable_interrupts(adev);
+ ret = vega10_ih_toggle_interrupts(adev, false);
+ if (ret)
+ return ret;
adev->nbio.funcs->ih_control(adev);
- ih = &adev->irq.ih;
- /* Ring Buffer base. [39:8] of 40-bit address of the beginning of the ring buffer*/
- WREG32_SOC15(OSSSYS, 0, mmIH_RB_BASE, ih->gpu_addr >> 8);
- WREG32_SOC15(OSSSYS, 0, mmIH_RB_BASE_HI, (ih->gpu_addr >> 40) & 0xff);
-
- ih_rb_cntl = RREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL);
- ih_rb_cntl = vega10_ih_rb_cntl(ih, ih_rb_cntl);
- ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, RPTR_REARM,
- !!adev->irq.msi_enabled);
- if (amdgpu_sriov_vf(adev)) {
- if (psp_reg_program(&adev->psp, PSP_REG_IH_RB_CNTL, ih_rb_cntl)) {
- DRM_ERROR("PSP program IH_RB_CNTL failed!\n");
- return -ETIMEDOUT;
- }
- } else {
- WREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL, ih_rb_cntl);
- }
-
- if ((adev->asic_type == CHIP_ARCTURUS &&
- adev->firmware.load_type == AMDGPU_FW_LOAD_DIRECT) ||
- adev->asic_type == CHIP_RENOIR) {
+ if (adev->asic_type == CHIP_RENOIR) {
ih_chicken = RREG32_SOC15(OSSSYS, 0, mmIH_CHICKEN);
if (adev->irq.ih.use_bus_addr) {
ih_chicken = REG_SET_FIELD(ih_chicken, IH_CHICKEN,
MC_SPACE_GPA_ENABLE, 1);
- } else {
- ih_chicken = REG_SET_FIELD(ih_chicken, IH_CHICKEN,
- MC_SPACE_FBPA_ENABLE, 1);
}
WREG32_SOC15(OSSSYS, 0, mmIH_CHICKEN, ih_chicken);
}
- /* set the writeback address whether it's enabled or not */
- WREG32_SOC15(OSSSYS, 0, mmIH_RB_WPTR_ADDR_LO,
- lower_32_bits(ih->wptr_addr));
- WREG32_SOC15(OSSSYS, 0, mmIH_RB_WPTR_ADDR_HI,
- upper_32_bits(ih->wptr_addr) & 0xFFFF);
-
- /* set rptr, wptr to 0 */
- WREG32_SOC15(OSSSYS, 0, mmIH_RB_WPTR, 0);
- WREG32_SOC15(OSSSYS, 0, mmIH_RB_RPTR, 0);
-
- WREG32_SOC15(OSSSYS, 0, mmIH_DOORBELL_RPTR,
- vega10_ih_doorbell_rptr(ih));
-
- ih = &adev->irq.ih1;
- if (ih->ring_size) {
- WREG32_SOC15(OSSSYS, 0, mmIH_RB_BASE_RING1, ih->gpu_addr >> 8);
- WREG32_SOC15(OSSSYS, 0, mmIH_RB_BASE_HI_RING1,
- (ih->gpu_addr >> 40) & 0xff);
-
- ih_rb_cntl = RREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING1);
- ih_rb_cntl = vega10_ih_rb_cntl(ih, ih_rb_cntl);
- ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL,
- WPTR_OVERFLOW_ENABLE, 0);
- ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL,
- RB_FULL_DRAIN_ENABLE, 1);
- if (amdgpu_sriov_vf(adev)) {
- if (psp_reg_program(&adev->psp, PSP_REG_IH_RB_CNTL_RING1,
- ih_rb_cntl)) {
- DRM_ERROR("program IH_RB_CNTL_RING1 failed!\n");
- return -ETIMEDOUT;
- }
- } else {
- WREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING1, ih_rb_cntl);
+ for (i = 0; i < ARRAY_SIZE(ih); i++) {
+ if (ih[i]->ring_size) {
+ ret = vega10_ih_enable_ring(adev, ih[i]);
+ if (ret)
+ return ret;
}
-
- /* set rptr, wptr to 0 */
- WREG32_SOC15(OSSSYS, 0, mmIH_RB_WPTR_RING1, 0);
- WREG32_SOC15(OSSSYS, 0, mmIH_RB_RPTR_RING1, 0);
-
- WREG32_SOC15(OSSSYS, 0, mmIH_DOORBELL_RPTR_RING1,
- vega10_ih_doorbell_rptr(ih));
- }
-
- ih = &adev->irq.ih2;
- if (ih->ring_size) {
- WREG32_SOC15(OSSSYS, 0, mmIH_RB_BASE_RING2, ih->gpu_addr >> 8);
- WREG32_SOC15(OSSSYS, 0, mmIH_RB_BASE_HI_RING2,
- (ih->gpu_addr >> 40) & 0xff);
-
- ih_rb_cntl = RREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING2);
- ih_rb_cntl = vega10_ih_rb_cntl(ih, ih_rb_cntl);
-
- if (amdgpu_sriov_vf(adev)) {
- if (psp_reg_program(&adev->psp, PSP_REG_IH_RB_CNTL_RING2,
- ih_rb_cntl)) {
- DRM_ERROR("program IH_RB_CNTL_RING2 failed!\n");
- return -ETIMEDOUT;
- }
- } else {
- WREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING2, ih_rb_cntl);
- }
-
- /* set rptr, wptr to 0 */
- WREG32_SOC15(OSSSYS, 0, mmIH_RB_WPTR_RING2, 0);
- WREG32_SOC15(OSSSYS, 0, mmIH_RB_RPTR_RING2, 0);
-
- WREG32_SOC15(OSSSYS, 0, mmIH_DOORBELL_RPTR_RING2,
- vega10_ih_doorbell_rptr(ih));
}
tmp = RREG32_SOC15(OSSSYS, 0, mmIH_STORM_CLIENT_LIST_CNTL);
@@ -345,9 +303,14 @@ static int vega10_ih_irq_init(struct amdgpu_device *adev)
pci_set_master(adev->pdev);
/* enable interrupts */
- vega10_ih_enable_interrupts(adev);
+ ret = vega10_ih_toggle_interrupts(adev, true);
+ if (ret)
+ return ret;
- return ret;
+ if (adev->irq.ih_soft.ring_size)
+ adev->irq.ih_soft.enabled = true;
+
+ return 0;
}
/**
@@ -359,7 +322,7 @@ static int vega10_ih_irq_init(struct amdgpu_device *adev)
*/
static void vega10_ih_irq_disable(struct amdgpu_device *adev)
{
- vega10_ih_disable_interrupts(adev);
+ vega10_ih_toggle_interrupts(adev, false);
/* Wait and acknowledge irq */
mdelay(1);
@@ -379,25 +342,17 @@ static void vega10_ih_irq_disable(struct amdgpu_device *adev)
static u32 vega10_ih_get_wptr(struct amdgpu_device *adev,
struct amdgpu_ih_ring *ih)
{
- u32 wptr, reg, tmp;
+ u32 wptr, tmp;
+ struct amdgpu_ih_regs *ih_regs;
wptr = le32_to_cpu(*ih->wptr_cpu);
+ ih_regs = &ih->ih_regs;
if (!REG_GET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW))
goto out;
/* Double check that the overflow wasn't already cleared. */
-
- if (ih == &adev->irq.ih)
- reg = SOC15_REG_OFFSET(OSSSYS, 0, mmIH_RB_WPTR);
- else if (ih == &adev->irq.ih1)
- reg = SOC15_REG_OFFSET(OSSSYS, 0, mmIH_RB_WPTR_RING1);
- else if (ih == &adev->irq.ih2)
- reg = SOC15_REG_OFFSET(OSSSYS, 0, mmIH_RB_WPTR_RING2);
- else
- BUG();
-
- wptr = RREG32_NO_KIQ(reg);
+ wptr = RREG32_NO_KIQ(ih_regs->ih_rb_wptr);
if (!REG_GET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW))
goto out;
@@ -413,69 +368,15 @@ static u32 vega10_ih_get_wptr(struct amdgpu_device *adev,
wptr, ih->rptr, tmp);
ih->rptr = tmp;
- if (ih == &adev->irq.ih)
- reg = SOC15_REG_OFFSET(OSSSYS, 0, mmIH_RB_CNTL);
- else if (ih == &adev->irq.ih1)
- reg = SOC15_REG_OFFSET(OSSSYS, 0, mmIH_RB_CNTL_RING1);
- else if (ih == &adev->irq.ih2)
- reg = SOC15_REG_OFFSET(OSSSYS, 0, mmIH_RB_CNTL_RING2);
- else
- BUG();
-
- tmp = RREG32_NO_KIQ(reg);
+ tmp = RREG32_NO_KIQ(ih_regs->ih_rb_cntl);
tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 1);
- WREG32_NO_KIQ(reg, tmp);
+ WREG32_NO_KIQ(ih_regs->ih_rb_cntl, tmp);
out:
return (wptr & ih->ptr_mask);
}
/**
- * vega10_ih_decode_iv - decode an interrupt vector
- *
- * @adev: amdgpu_device pointer
- * @ih: IH ring buffer to decode
- * @entry: IV entry to place decoded information into
- *
- * Decodes the interrupt vector at the current rptr
- * position and also advance the position.
- */
-static void vega10_ih_decode_iv(struct amdgpu_device *adev,
- struct amdgpu_ih_ring *ih,
- struct amdgpu_iv_entry *entry)
-{
- /* wptr/rptr are in bytes! */
- u32 ring_index = ih->rptr >> 2;
- uint32_t dw[8];
-
- dw[0] = le32_to_cpu(ih->ring[ring_index + 0]);
- dw[1] = le32_to_cpu(ih->ring[ring_index + 1]);
- dw[2] = le32_to_cpu(ih->ring[ring_index + 2]);
- dw[3] = le32_to_cpu(ih->ring[ring_index + 3]);
- dw[4] = le32_to_cpu(ih->ring[ring_index + 4]);
- dw[5] = le32_to_cpu(ih->ring[ring_index + 5]);
- dw[6] = le32_to_cpu(ih->ring[ring_index + 6]);
- dw[7] = le32_to_cpu(ih->ring[ring_index + 7]);
-
- entry->client_id = dw[0] & 0xff;
- entry->src_id = (dw[0] >> 8) & 0xff;
- entry->ring_id = (dw[0] >> 16) & 0xff;
- entry->vmid = (dw[0] >> 24) & 0xf;
- entry->vmid_src = (dw[0] >> 31);
- entry->timestamp = dw[1] | ((u64)(dw[2] & 0xffff) << 32);
- entry->timestamp_src = dw[2] >> 31;
- entry->pasid = dw[3] & 0xffff;
- entry->pasid_src = dw[3] >> 31;
- entry->src_data[0] = dw[4];
- entry->src_data[1] = dw[5];
- entry->src_data[2] = dw[6];
- entry->src_data[3] = dw[7];
-
- /* wptr/rptr are in bytes! */
- ih->rptr += 32;
-}
-
-/**
* vega10_ih_irq_rearm - rearm IRQ if lost
*
* @adev: amdgpu_device pointer
@@ -485,22 +386,14 @@ static void vega10_ih_decode_iv(struct amdgpu_device *adev,
static void vega10_ih_irq_rearm(struct amdgpu_device *adev,
struct amdgpu_ih_ring *ih)
{
- uint32_t reg_rptr = 0;
uint32_t v = 0;
uint32_t i = 0;
+ struct amdgpu_ih_regs *ih_regs;
- if (ih == &adev->irq.ih)
- reg_rptr = SOC15_REG_OFFSET(OSSSYS, 0, mmIH_RB_RPTR);
- else if (ih == &adev->irq.ih1)
- reg_rptr = SOC15_REG_OFFSET(OSSSYS, 0, mmIH_RB_RPTR_RING1);
- else if (ih == &adev->irq.ih2)
- reg_rptr = SOC15_REG_OFFSET(OSSSYS, 0, mmIH_RB_RPTR_RING2);
- else
- return;
-
+ ih_regs = &ih->ih_regs;
/* Rearm IRQ / re-wwrite doorbell if doorbell write is lost */
for (i = 0; i < MAX_REARM_RETRY; i++) {
- v = RREG32_NO_KIQ(reg_rptr);
+ v = RREG32_NO_KIQ(ih_regs->ih_rb_rptr);
if ((v < ih->ring_size) && (v != ih->rptr))
WDOORBELL32(ih->doorbell_index, ih->rptr);
else
@@ -519,6 +412,8 @@ static void vega10_ih_irq_rearm(struct amdgpu_device *adev,
static void vega10_ih_set_rptr(struct amdgpu_device *adev,
struct amdgpu_ih_ring *ih)
{
+ struct amdgpu_ih_regs *ih_regs;
+
if (ih->use_doorbell) {
/* XXX check if swapping is necessary on BE */
*ih->rptr_cpu = ih->rptr;
@@ -526,12 +421,9 @@ static void vega10_ih_set_rptr(struct amdgpu_device *adev,
if (amdgpu_sriov_vf(adev))
vega10_ih_irq_rearm(adev, ih);
- } else if (ih == &adev->irq.ih) {
- WREG32_SOC15(OSSSYS, 0, mmIH_RB_RPTR, ih->rptr);
- } else if (ih == &adev->irq.ih1) {
- WREG32_SOC15(OSSSYS, 0, mmIH_RB_RPTR_RING1, ih->rptr);
- } else if (ih == &adev->irq.ih2) {
- WREG32_SOC15(OSSSYS, 0, mmIH_RB_RPTR_RING2, ih->rptr);
+ } else {
+ ih_regs = &ih->ih_regs;
+ WREG32(ih_regs->ih_rb_rptr, ih->rptr);
}
}
@@ -600,19 +492,23 @@ static int vega10_ih_sw_init(void *handle)
adev->irq.ih.use_doorbell = true;
adev->irq.ih.doorbell_index = adev->doorbell_index.ih << 1;
- r = amdgpu_ih_ring_init(adev, &adev->irq.ih1, PAGE_SIZE, true);
- if (r)
- return r;
+ if (!(adev->flags & AMD_IS_APU)) {
+ r = amdgpu_ih_ring_init(adev, &adev->irq.ih1, PAGE_SIZE, true);
+ if (r)
+ return r;
- adev->irq.ih1.use_doorbell = true;
- adev->irq.ih1.doorbell_index = (adev->doorbell_index.ih + 1) << 1;
+ adev->irq.ih1.use_doorbell = true;
+ adev->irq.ih1.doorbell_index = (adev->doorbell_index.ih + 1) << 1;
- r = amdgpu_ih_ring_init(adev, &adev->irq.ih2, PAGE_SIZE, true);
- if (r)
- return r;
+ r = amdgpu_ih_ring_init(adev, &adev->irq.ih2, PAGE_SIZE, true);
+ if (r)
+ return r;
- adev->irq.ih2.use_doorbell = true;
- adev->irq.ih2.doorbell_index = (adev->doorbell_index.ih + 2) << 1;
+ adev->irq.ih2.use_doorbell = true;
+ adev->irq.ih2.doorbell_index = (adev->doorbell_index.ih + 2) << 1;
+ }
+ /* initialize ih control registers offset */
+ vega10_ih_init_register_offset(adev);
r = amdgpu_ih_ring_init(adev, &adev->irq.ih_soft, PAGE_SIZE, true);
if (r)
@@ -628,6 +524,7 @@ static int vega10_ih_sw_fini(void *handle)
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
amdgpu_irq_fini(adev);
+ amdgpu_ih_ring_fini(adev, &adev->irq.ih_soft);
amdgpu_ih_ring_fini(adev, &adev->irq.ih2);
amdgpu_ih_ring_fini(adev, &adev->irq.ih1);
amdgpu_ih_ring_fini(adev, &adev->irq.ih);
@@ -698,15 +595,11 @@ static void vega10_ih_update_clockgating_state(struct amdgpu_device *adev,
def = data = RREG32_SOC15(OSSSYS, 0, mmIH_CLK_CTRL);
field_val = enable ? 0 : 1;
/**
- * Vega10 does not have IH_RETRY_INT_CAM_MEM_CLK_SOFT_OVERRIDE
- * and IH_BUFFER_MEM_CLK_SOFT_OVERRIDE field.
+ * Vega10/12 and RAVEN don't have IH_BUFFER_MEM_CLK_SOFT_OVERRIDE field.
*/
- if (adev->asic_type > CHIP_VEGA10) {
- data = REG_SET_FIELD(data, IH_CLK_CTRL,
- IH_RETRY_INT_CAM_MEM_CLK_SOFT_OVERRIDE, field_val);
+ if (adev->asic_type == CHIP_RENOIR)
data = REG_SET_FIELD(data, IH_CLK_CTRL,
IH_BUFFER_MEM_CLK_SOFT_OVERRIDE, field_val);
- }
data = REG_SET_FIELD(data, IH_CLK_CTRL,
DBUS_MUX_CLK_SOFT_OVERRIDE, field_val);
@@ -759,7 +652,7 @@ const struct amd_ip_funcs vega10_ih_ip_funcs = {
static const struct amdgpu_ih_funcs vega10_ih_funcs = {
.get_wptr = vega10_ih_get_wptr,
- .decode_iv = vega10_ih_decode_iv,
+ .decode_iv = amdgpu_ih_decode_iv_helper,
.set_rptr = vega10_ih_set_rptr
};