All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/8] drm/amdgpu: add mask bit for IH_CLK_CTRL on oss v5.0
@ 2020-03-18 22:51 Alex Sierra
  2020-03-18 22:51 ` [PATCH 2/8] drm/amdgpu: create new files for arcturus ih Alex Sierra
                   ` (6 more replies)
  0 siblings, 7 replies; 12+ messages in thread
From: Alex Sierra @ 2020-03-18 22:51 UTC (permalink / raw)
  To: amd-gfx; +Cc: Alex Sierra

[Why]
Mask bit IH_RETRY_INT_CAM_MEM_CLK_SOFT_OVERRIDE was missing for osssys v5.0.

[How]
IH_RETRY_INT_CAM_MEM_CLK_SOFT_OVERRIDE bit mask added for IH_CLK_CTRL register
on osssys v5_0_0 mask header file.

Change-Id: I71e5ea3a8e5b5077b21906c730bcf30faa678f10
Signed-off-by: Alex Sierra <alex.sierra@amd.com>
---
 drivers/gpu/drm/amd/include/asic_reg/oss/osssys_5_0_0_sh_mask.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/gpu/drm/amd/include/asic_reg/oss/osssys_5_0_0_sh_mask.h b/drivers/gpu/drm/amd/include/asic_reg/oss/osssys_5_0_0_sh_mask.h
index 05543bde3444..7555ccb667eb 100644
--- a/drivers/gpu/drm/amd/include/asic_reg/oss/osssys_5_0_0_sh_mask.h
+++ b/drivers/gpu/drm/amd/include/asic_reg/oss/osssys_5_0_0_sh_mask.h
@@ -586,12 +586,14 @@
 #define IH_STORM_CLIENT_LIST_CNTL__CLIENT30_IS_STORM_CLIENT_MASK                                              0x40000000L
 #define IH_STORM_CLIENT_LIST_CNTL__CLIENT31_IS_STORM_CLIENT_MASK                                              0x80000000L
 //IH_CLK_CTRL
+#define IH_CLK_CTRL__IH_RETRY_INT_CAM_MEM_CLK_SOFT_OVERRIDE__SHIFT                                             0x19
 #define IH_CLK_CTRL__IH_BUFFER_MEM_CLK_SOFT_OVERRIDE__SHIFT                                                   0x1a
 #define IH_CLK_CTRL__DBUS_MUX_CLK_SOFT_OVERRIDE__SHIFT                                                        0x1b
 #define IH_CLK_CTRL__OSSSYS_SHARE_CLK_SOFT_OVERRIDE__SHIFT                                                    0x1c
 #define IH_CLK_CTRL__LIMIT_SMN_CLK_SOFT_OVERRIDE__SHIFT                                                       0x1d
 #define IH_CLK_CTRL__DYN_CLK_SOFT_OVERRIDE__SHIFT                                                             0x1e
 #define IH_CLK_CTRL__REG_CLK_SOFT_OVERRIDE__SHIFT                                                             0x1f
+#define IH_CLK_CTRL__IH_RETRY_INT_CAM_MEM_CLK_SOFT_OVERRIDE_MASK                                              0x02000000L
 #define IH_CLK_CTRL__IH_BUFFER_MEM_CLK_SOFT_OVERRIDE_MASK                                                     0x04000000L
 #define IH_CLK_CTRL__DBUS_MUX_CLK_SOFT_OVERRIDE_MASK                                                          0x08000000L
 #define IH_CLK_CTRL__OSSSYS_SHARE_CLK_SOFT_OVERRIDE_MASK                                                      0x10000000L
-- 
2.17.1

_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 2/8] drm/amdgpu: create new files for arcturus ih
  2020-03-18 22:51 [PATCH 1/8] drm/amdgpu: add mask bit for IH_CLK_CTRL on oss v5.0 Alex Sierra
@ 2020-03-18 22:51 ` Alex Sierra
  2020-03-18 23:33   ` Felix Kuehling
  2020-03-18 22:51 ` [PATCH 3/8] drm/amdgpu: remove non Arcturus references from arcturus_ih Alex Sierra
                   ` (5 subsequent siblings)
  6 siblings, 1 reply; 12+ messages in thread
From: Alex Sierra @ 2020-03-18 22:51 UTC (permalink / raw)
  To: amd-gfx; +Cc: Alex Sierra

[Why]
Arcturus uses osssys v4.2. This shares the same register map as
osssys v5.0.

[How]
Copy vega10_ih into new arcturus_ih source and header files.
Replace osssys include file with v5.0.0 on arcturus_ih.c source.

Change-Id: I5215f32f477adb6a30acef6e8add9f8e5bb041ef
Signed-off-by: Alex Sierra <alex.sierra@amd.com>
---
 drivers/gpu/drm/amd/amdgpu/arcturus_ih.c | 766 +++++++++++++++++++++++
 drivers/gpu/drm/amd/amdgpu/arcturus_ih.h |  30 +
 2 files changed, 796 insertions(+)
 create mode 100644 drivers/gpu/drm/amd/amdgpu/arcturus_ih.c
 create mode 100644 drivers/gpu/drm/amd/amdgpu/arcturus_ih.h

diff --git a/drivers/gpu/drm/amd/amdgpu/arcturus_ih.c b/drivers/gpu/drm/amd/amdgpu/arcturus_ih.c
new file mode 100644
index 000000000000..21bb5be40921
--- /dev/null
+++ b/drivers/gpu/drm/amd/amdgpu/arcturus_ih.c
@@ -0,0 +1,766 @@
+/*
+ * Copyright 2020 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include <linux/pci.h>
+
+#include "amdgpu.h"
+#include "amdgpu_ih.h"
+#include "soc15.h"
+
+#include "oss/osssys_5_0_0_offset.h"
+#include "oss/osssys_5_0_0_sh_mask.h"
+
+#include "soc15_common.h"
+#include "arcturus_ih.h"
+
+#define MAX_REARM_RETRY 10
+
+static void vega10_ih_set_interrupt_funcs(struct amdgpu_device *adev);
+
+/**
+ * vega10_ih_enable_interrupts - Enable the interrupt ring buffer
+ *
+ * @adev: amdgpu_device pointer
+ *
+ * Enable the interrupt ring buffer (VEGA10).
+ */
+static void vega10_ih_enable_interrupts(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);
+	}
+	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;
+	}
+
+	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;
+	}
+}
+
+/**
+ * vega10_ih_disable_interrupts - Disable the interrupt ring buffer
+ *
+ * @adev: amdgpu_device pointer
+ *
+ * Disable the interrupt ring buffer (VEGA10).
+ */
+static void vega10_ih_disable_interrupts(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, 0);
+	ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, ENABLE_INTR, 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;
+		}
+	} else {
+		WREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL, ih_rb_cntl);
+	}
+
+	/* 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);
+		}
+		/* 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;
+	}
+
+	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);
+		}
+
+		/* 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;
+	}
+}
+
+static uint32_t vega10_ih_rb_cntl(struct amdgpu_ih_ring *ih, uint32_t ih_rb_cntl)
+{
+	int rb_bufsz = order_base_2(ih->ring_size / 4);
+
+	ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL,
+				   MC_SPACE, ih->use_bus_addr ? 1 : 4);
+	ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL,
+				   WPTR_OVERFLOW_CLEAR, 1);
+	ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL,
+				   WPTR_OVERFLOW_ENABLE, 1);
+	ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, RB_SIZE, rb_bufsz);
+	/* Ring Buffer write pointer writeback. If enabled, IH_RB_WPTR register
+	 * value is written to memory
+	 */
+	ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL,
+				   WPTR_WRITEBACK_ENABLE, 1);
+	ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, MC_SNOOP, 1);
+	ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, MC_RO, 0);
+	ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, MC_VMID, 0);
+
+	return ih_rb_cntl;
+}
+
+static uint32_t vega10_ih_doorbell_rptr(struct amdgpu_ih_ring *ih)
+{
+	u32 ih_doorbell_rtpr = 0;
+
+	if (ih->use_doorbell) {
+		ih_doorbell_rtpr = REG_SET_FIELD(ih_doorbell_rtpr,
+						 IH_DOORBELL_RPTR, OFFSET,
+						 ih->doorbell_index);
+		ih_doorbell_rtpr = REG_SET_FIELD(ih_doorbell_rtpr,
+						 IH_DOORBELL_RPTR,
+						 ENABLE, 1);
+	} else {
+		ih_doorbell_rtpr = REG_SET_FIELD(ih_doorbell_rtpr,
+						 IH_DOORBELL_RPTR,
+						 ENABLE, 0);
+	}
+	return ih_doorbell_rtpr;
+}
+
+/**
+ * vega10_ih_irq_init - init and enable the interrupt ring
+ *
+ * @adev: amdgpu_device pointer
+ *
+ * Allocate a ring buffer for the interrupt controller,
+ * enable the RLC, disable interrupts, enable the IH
+ * ring buffer and enable it (VI).
+ * Called at device load and reume.
+ * Returns 0 for success, errors for failure.
+ */
+static int vega10_ih_irq_init(struct amdgpu_device *adev)
+{
+	struct amdgpu_ih_ring *ih;
+	u32 ih_rb_cntl, ih_chicken;
+	int ret = 0;
+	u32 tmp;
+
+	/* disable irqs */
+	vega10_ih_disable_interrupts(adev);
+
+	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) {
+		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);
+		}
+
+		/* 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);
+	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 */
+	vega10_ih_enable_interrupts(adev);
+
+	return ret;
+}
+
+/**
+ * vega10_ih_irq_disable - disable interrupts
+ *
+ * @adev: amdgpu_device pointer
+ *
+ * Disable interrupts on the hw (VEGA10).
+ */
+static void vega10_ih_irq_disable(struct amdgpu_device *adev)
+{
+	vega10_ih_disable_interrupts(adev);
+
+	/* Wait and acknowledge irq */
+	mdelay(1);
+}
+
+/**
+ * vega10_ih_get_wptr - get the IH ring buffer wptr
+ *
+ * @adev: amdgpu_device pointer
+ *
+ * Get the IH ring buffer wptr from either the register
+ * or the writeback memory buffer (VEGA10).  Also check for
+ * ring buffer overflow and deal with it.
+ * Returns the value of the wptr.
+ */
+static u32 vega10_ih_get_wptr(struct amdgpu_device *adev,
+			      struct amdgpu_ih_ring *ih)
+{
+	u32 wptr, reg, tmp;
+
+	wptr = le32_to_cpu(*ih->wptr_cpu);
+
+	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);
+	if (!REG_GET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW))
+		goto out;
+
+	wptr = REG_SET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW, 0);
+
+	/* When a ring buffer overflow happen start parsing interrupt
+	 * from the last not overwritten vector (wptr + 32). Hopefully
+	 * this should allow us to catchup.
+	 */
+	tmp = (wptr + 32) & ih->ptr_mask;
+	dev_warn(adev->dev, "IH ring buffer overflow "
+		 "(0x%08X, 0x%08X, 0x%08X)\n",
+		 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 = REG_SET_FIELD(tmp, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 1);
+	WREG32_NO_KIQ(reg, tmp);
+
+out:
+	return (wptr & ih->ptr_mask);
+}
+
+/**
+ * vega10_ih_decode_iv - decode an interrupt vector
+ *
+ * @adev: amdgpu_device pointer
+ *
+ * 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
+ *
+ */
+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;
+
+	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;
+
+	/* Rearm IRQ / re-wwrite doorbell if doorbell write is lost */
+	for (i = 0; i < MAX_REARM_RETRY; i++) {
+		v = RREG32_NO_KIQ(reg_rptr);
+		if ((v < ih->ring_size) && (v != ih->rptr))
+			WDOORBELL32(ih->doorbell_index, ih->rptr);
+		else
+			break;
+	}
+}
+
+/**
+ * vega10_ih_set_rptr - set the IH ring buffer rptr
+ *
+ * @adev: amdgpu_device pointer
+ *
+ * Set the IH ring buffer rptr.
+ */
+static void vega10_ih_set_rptr(struct amdgpu_device *adev,
+			       struct amdgpu_ih_ring *ih)
+{
+	if (ih->use_doorbell) {
+		/* XXX check if swapping is necessary on BE */
+		*ih->rptr_cpu = ih->rptr;
+		WDOORBELL32(ih->doorbell_index, ih->rptr);
+
+		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);
+	}
+}
+
+/**
+ * vega10_ih_self_irq - dispatch work for ring 1 and 2
+ *
+ * @adev: amdgpu_device pointer
+ * @source: irq source
+ * @entry: IV with WPTR update
+ *
+ * Update the WPTR from the IV and schedule work to handle the entries.
+ */
+static int vega10_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;
+	}
+	return 0;
+}
+
+static const struct amdgpu_irq_src_funcs vega10_ih_self_irq_funcs = {
+	.process = vega10_ih_self_irq,
+};
+
+static void vega10_ih_set_self_irq_funcs(struct amdgpu_device *adev)
+{
+	adev->irq.self_irq.num_types = 0;
+	adev->irq.self_irq.funcs = &vega10_ih_self_irq_funcs;
+}
+
+static int vega10_ih_early_init(void *handle)
+{
+	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+
+	vega10_ih_set_interrupt_funcs(adev);
+	vega10_ih_set_self_irq_funcs(adev);
+	return 0;
+}
+
+static int vega10_ih_sw_init(void *handle)
+{
+	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+	int r;
+
+	r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_IH, 0,
+			      &adev->irq.self_irq);
+	if (r)
+		return r;
+
+	r = amdgpu_ih_ring_init(adev, &adev->irq.ih, 256 * 1024, true);
+	if (r)
+		return r;
+
+	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;
+
+	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;
+
+	adev->irq.ih2.use_doorbell = true;
+	adev->irq.ih2.doorbell_index = (adev->doorbell_index.ih + 2) << 1;
+
+	r = amdgpu_irq_init(adev);
+
+	return r;
+}
+
+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.ih2);
+	amdgpu_ih_ring_fini(adev, &adev->irq.ih1);
+	amdgpu_ih_ring_fini(adev, &adev->irq.ih);
+
+	return 0;
+}
+
+static int vega10_ih_hw_init(void *handle)
+{
+	int r;
+	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+
+	r = vega10_ih_irq_init(adev);
+	if (r)
+		return r;
+
+	return 0;
+}
+
+static int vega10_ih_hw_fini(void *handle)
+{
+	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+
+	vega10_ih_irq_disable(adev);
+
+	return 0;
+}
+
+static int vega10_ih_suspend(void *handle)
+{
+	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+
+	return vega10_ih_hw_fini(adev);
+}
+
+static int vega10_ih_resume(void *handle)
+{
+	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+
+	return vega10_ih_hw_init(adev);
+}
+
+static bool vega10_ih_is_idle(void *handle)
+{
+	/* todo */
+	return true;
+}
+
+static int vega10_ih_wait_for_idle(void *handle)
+{
+	/* todo */
+	return -ETIMEDOUT;
+}
+
+static int vega10_ih_soft_reset(void *handle)
+{
+	/* todo */
+
+	return 0;
+}
+
+static void vega10_ih_update_clockgating_state(struct amdgpu_device *adev,
+					       bool enable)
+{
+	uint32_t data, def, field_val;
+
+	if (adev->cg_flags & AMD_CG_SUPPORT_IH_CG) {
+		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.
+		 */
+		if (adev->asic_type > CHIP_VEGA10) {
+			data = REG_SET_FIELD(data, IH_CLK_CTRL,
+				     IH_RETRY_INT_CAM_MEM_CLK_SOFT_OVERRIDE, field_val);
+			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);
+		data = REG_SET_FIELD(data, IH_CLK_CTRL,
+				     OSSSYS_SHARE_CLK_SOFT_OVERRIDE, field_val);
+		data = REG_SET_FIELD(data, IH_CLK_CTRL,
+				     LIMIT_SMN_CLK_SOFT_OVERRIDE, field_val);
+		data = REG_SET_FIELD(data, IH_CLK_CTRL,
+				     DYN_CLK_SOFT_OVERRIDE, field_val);
+		data = REG_SET_FIELD(data, IH_CLK_CTRL,
+				     REG_CLK_SOFT_OVERRIDE, field_val);
+		if (def != data)
+			WREG32_SOC15(OSSSYS, 0, mmIH_CLK_CTRL, data);
+	}
+}
+
+static int vega10_ih_set_clockgating_state(void *handle,
+					  enum amd_clockgating_state state)
+{
+	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+
+	vega10_ih_update_clockgating_state(adev,
+				state == AMD_CG_STATE_GATE);
+	return 0;
+
+}
+
+static int vega10_ih_set_powergating_state(void *handle,
+					  enum amd_powergating_state state)
+{
+	return 0;
+}
+
+const struct amd_ip_funcs vega10_ih_ip_funcs = {
+	.name = "vega10_ih",
+	.early_init = vega10_ih_early_init,
+	.late_init = NULL,
+	.sw_init = vega10_ih_sw_init,
+	.sw_fini = vega10_ih_sw_fini,
+	.hw_init = vega10_ih_hw_init,
+	.hw_fini = vega10_ih_hw_fini,
+	.suspend = vega10_ih_suspend,
+	.resume = vega10_ih_resume,
+	.is_idle = vega10_ih_is_idle,
+	.wait_for_idle = vega10_ih_wait_for_idle,
+	.soft_reset = vega10_ih_soft_reset,
+	.set_clockgating_state = vega10_ih_set_clockgating_state,
+	.set_powergating_state = vega10_ih_set_powergating_state,
+};
+
+static const struct amdgpu_ih_funcs vega10_ih_funcs = {
+	.get_wptr = vega10_ih_get_wptr,
+	.decode_iv = vega10_ih_decode_iv,
+	.set_rptr = vega10_ih_set_rptr
+};
+
+static void vega10_ih_set_interrupt_funcs(struct amdgpu_device *adev)
+{
+	adev->irq.ih_funcs = &vega10_ih_funcs;
+}
+
+const struct amdgpu_ip_block_version vega10_ih_ip_block = {
+	.type = AMD_IP_BLOCK_TYPE_IH,
+	.major = 4,
+	.minor = 0,
+	.rev = 0,
+	.funcs = &vega10_ih_ip_funcs,
+};
diff --git a/drivers/gpu/drm/amd/amdgpu/arcturus_ih.h b/drivers/gpu/drm/amd/amdgpu/arcturus_ih.h
new file mode 100644
index 000000000000..54daf8cf6ff3
--- /dev/null
+++ b/drivers/gpu/drm/amd/amdgpu/arcturus_ih.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2020 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef __VEGA10_IH_H__
+#define __VEGA10_IH_H__
+
+extern const struct amd_ip_funcs vega10_ih_ip_funcs;
+extern const struct amdgpu_ip_block_version vega10_ih_ip_block;
+
+#endif
-- 
2.17.1

_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 3/8] drm/amdgpu: remove non Arcturus references from arcturus_ih
  2020-03-18 22:51 [PATCH 1/8] drm/amdgpu: add mask bit for IH_CLK_CTRL on oss v5.0 Alex Sierra
  2020-03-18 22:51 ` [PATCH 2/8] drm/amdgpu: create new files for arcturus ih Alex Sierra
@ 2020-03-18 22:51 ` Alex Sierra
  2020-03-18 22:51 ` [PATCH 4/8] drm/amdgpu: replace function prefix names Alex Sierra
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 12+ messages in thread
From: Alex Sierra @ 2020-03-18 22:51 UTC (permalink / raw)
  To: amd-gfx; +Cc: Alex Sierra

Renoir and Vega10 references removed. Both have their implementation
under vega10_ih

Change-Id: Id12a0228ea75dd7122c5ec264e5b38a00a79b45d
Signed-off-by: Alex Sierra <alex.sierra@amd.com>
---
 drivers/gpu/drm/amd/amdgpu/arcturus_ih.c | 15 +++------------
 1 file changed, 3 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/arcturus_ih.c b/drivers/gpu/drm/amd/amdgpu/arcturus_ih.c
index 21bb5be40921..b8cd5c3c8a36 100644
--- a/drivers/gpu/drm/amd/amdgpu/arcturus_ih.c
+++ b/drivers/gpu/drm/amd/amdgpu/arcturus_ih.c
@@ -246,9 +246,7 @@ static int vega10_ih_irq_init(struct amdgpu_device *adev)
 		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->firmware.load_type == AMDGPU_FW_LOAD_DIRECT) {
 		ih_chicken = RREG32_SOC15(OSSSYS, 0, mmIH_CHICKEN);
 		if (adev->irq.ih.use_bus_addr) {
 			ih_chicken = REG_SET_FIELD(ih_chicken, IH_CHICKEN,
@@ -686,17 +684,10 @@ static void vega10_ih_update_clockgating_state(struct amdgpu_device *adev,
 	if (adev->cg_flags & AMD_CG_SUPPORT_IH_CG) {
 		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.
-		 */
-		if (adev->asic_type > CHIP_VEGA10) {
-			data = REG_SET_FIELD(data, IH_CLK_CTRL,
+		data = REG_SET_FIELD(data, IH_CLK_CTRL,
 				     IH_RETRY_INT_CAM_MEM_CLK_SOFT_OVERRIDE, field_val);
-			data = REG_SET_FIELD(data, IH_CLK_CTRL,
+		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);
 		data = REG_SET_FIELD(data, IH_CLK_CTRL,
-- 
2.17.1

_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 4/8] drm/amdgpu: replace function prefix names
  2020-03-18 22:51 [PATCH 1/8] drm/amdgpu: add mask bit for IH_CLK_CTRL on oss v5.0 Alex Sierra
  2020-03-18 22:51 ` [PATCH 2/8] drm/amdgpu: create new files for arcturus ih Alex Sierra
  2020-03-18 22:51 ` [PATCH 3/8] drm/amdgpu: remove non Arcturus references from arcturus_ih Alex Sierra
@ 2020-03-18 22:51 ` Alex Sierra
  2020-03-18 22:51 ` [PATCH 5/8] drm/amdgpu: reroute VMC and UMD to IH ring 1 for arcturus Alex Sierra
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 12+ messages in thread
From: Alex Sierra @ 2020-03-18 22:51 UTC (permalink / raw)
  To: amd-gfx; +Cc: Alex Sierra

Replace function prefix name from vega10 to arcturus

Change-Id: Ic21713f2dda30a0bc28c7b525e20d5f1fcde96dd
Signed-off-by: Alex Sierra <alex.sierra@amd.com>
---
 drivers/gpu/drm/amd/amdgpu/arcturus_ih.c | 162 +++++++++++------------
 drivers/gpu/drm/amd/amdgpu/arcturus_ih.h |   8 +-
 2 files changed, 85 insertions(+), 85 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/arcturus_ih.c b/drivers/gpu/drm/amd/amdgpu/arcturus_ih.c
index b8cd5c3c8a36..b687fcc4c9b6 100644
--- a/drivers/gpu/drm/amd/amdgpu/arcturus_ih.c
+++ b/drivers/gpu/drm/amd/amdgpu/arcturus_ih.c
@@ -35,16 +35,16 @@
 
 #define MAX_REARM_RETRY 10
 
-static void vega10_ih_set_interrupt_funcs(struct amdgpu_device *adev);
+static void arcturus_ih_set_interrupt_funcs(struct amdgpu_device *adev);
 
 /**
- * vega10_ih_enable_interrupts - Enable the interrupt ring buffer
+ * arcturus_ih_enable_interrupts - Enable the interrupt ring buffer
  *
  * @adev: amdgpu_device pointer
  *
- * Enable the interrupt ring buffer (VEGA10).
+ * Enable the interrupt ring buffer (ARCTURUS).
  */
-static void vega10_ih_enable_interrupts(struct amdgpu_device *adev)
+static void arcturus_ih_enable_interrupts(struct amdgpu_device *adev)
 {
 	u32 ih_rb_cntl = RREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL);
 
@@ -94,13 +94,13 @@ static void vega10_ih_enable_interrupts(struct amdgpu_device *adev)
 }
 
 /**
- * vega10_ih_disable_interrupts - Disable the interrupt ring buffer
+ * arcturus_ih_disable_interrupts - Disable the interrupt ring buffer
  *
  * @adev: amdgpu_device pointer
  *
- * Disable the interrupt ring buffer (VEGA10).
+ * Disable the interrupt ring buffer (ARCTURUS).
  */
-static void vega10_ih_disable_interrupts(struct amdgpu_device *adev)
+static void arcturus_ih_disable_interrupts(struct amdgpu_device *adev)
 {
 	u32 ih_rb_cntl = RREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL);
 
@@ -163,7 +163,7 @@ static void vega10_ih_disable_interrupts(struct amdgpu_device *adev)
 	}
 }
 
-static uint32_t vega10_ih_rb_cntl(struct amdgpu_ih_ring *ih, uint32_t ih_rb_cntl)
+static uint32_t arcturus_ih_rb_cntl(struct amdgpu_ih_ring *ih, uint32_t ih_rb_cntl)
 {
 	int rb_bufsz = order_base_2(ih->ring_size / 4);
 
@@ -186,7 +186,7 @@ static uint32_t vega10_ih_rb_cntl(struct amdgpu_ih_ring *ih, uint32_t ih_rb_cntl
 	return ih_rb_cntl;
 }
 
-static uint32_t vega10_ih_doorbell_rptr(struct amdgpu_ih_ring *ih)
+static uint32_t arcturus_ih_doorbell_rptr(struct amdgpu_ih_ring *ih)
 {
 	u32 ih_doorbell_rtpr = 0;
 
@@ -206,7 +206,7 @@ static uint32_t vega10_ih_doorbell_rptr(struct amdgpu_ih_ring *ih)
 }
 
 /**
- * vega10_ih_irq_init - init and enable the interrupt ring
+ * arcturus_ih_irq_init - init and enable the interrupt ring
  *
  * @adev: amdgpu_device pointer
  *
@@ -216,7 +216,7 @@ static uint32_t vega10_ih_doorbell_rptr(struct amdgpu_ih_ring *ih)
  * Called at device load and reume.
  * Returns 0 for success, errors for failure.
  */
-static int vega10_ih_irq_init(struct amdgpu_device *adev)
+static int arcturus_ih_irq_init(struct amdgpu_device *adev)
 {
 	struct amdgpu_ih_ring *ih;
 	u32 ih_rb_cntl, ih_chicken;
@@ -224,7 +224,7 @@ static int vega10_ih_irq_init(struct amdgpu_device *adev)
 	u32 tmp;
 
 	/* disable irqs */
-	vega10_ih_disable_interrupts(adev);
+	arcturus_ih_disable_interrupts(adev);
 
 	adev->nbio.funcs->ih_control(adev);
 
@@ -234,7 +234,7 @@ static int vega10_ih_irq_init(struct amdgpu_device *adev)
 	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 = arcturus_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)) {
@@ -269,7 +269,7 @@ static int vega10_ih_irq_init(struct amdgpu_device *adev)
 	WREG32_SOC15(OSSSYS, 0, mmIH_RB_RPTR, 0);
 
 	WREG32_SOC15(OSSSYS, 0, mmIH_DOORBELL_RPTR,
-		     vega10_ih_doorbell_rptr(ih));
+		     arcturus_ih_doorbell_rptr(ih));
 
 	ih = &adev->irq.ih1;
 	if (ih->ring_size) {
@@ -278,7 +278,7 @@ static int vega10_ih_irq_init(struct amdgpu_device *adev)
 			     (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 = arcturus_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,
@@ -298,7 +298,7 @@ static int vega10_ih_irq_init(struct amdgpu_device *adev)
 		WREG32_SOC15(OSSSYS, 0, mmIH_RB_RPTR_RING1, 0);
 
 		WREG32_SOC15(OSSSYS, 0, mmIH_DOORBELL_RPTR_RING1,
-			     vega10_ih_doorbell_rptr(ih));
+			     arcturus_ih_doorbell_rptr(ih));
 	}
 
 	ih = &adev->irq.ih2;
@@ -308,7 +308,7 @@ static int vega10_ih_irq_init(struct amdgpu_device *adev)
 			     (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);
+		ih_rb_cntl = arcturus_ih_rb_cntl(ih, ih_rb_cntl);
 
 		if (amdgpu_sriov_vf(adev)) {
 			if (psp_reg_program(&adev->psp, PSP_REG_IH_RB_CNTL_RING2,
@@ -325,7 +325,7 @@ static int vega10_ih_irq_init(struct amdgpu_device *adev)
 		WREG32_SOC15(OSSSYS, 0, mmIH_RB_RPTR_RING2, 0);
 
 		WREG32_SOC15(OSSSYS, 0, mmIH_DOORBELL_RPTR_RING2,
-			     vega10_ih_doorbell_rptr(ih));
+			     arcturus_ih_doorbell_rptr(ih));
 	}
 
 	tmp = RREG32_SOC15(OSSSYS, 0, mmIH_STORM_CLIENT_LIST_CNTL);
@@ -340,37 +340,37 @@ static int vega10_ih_irq_init(struct amdgpu_device *adev)
 	pci_set_master(adev->pdev);
 
 	/* enable interrupts */
-	vega10_ih_enable_interrupts(adev);
+	arcturus_ih_enable_interrupts(adev);
 
 	return ret;
 }
 
 /**
- * vega10_ih_irq_disable - disable interrupts
+ * arcturus_ih_irq_disable - disable interrupts
  *
  * @adev: amdgpu_device pointer
  *
- * Disable interrupts on the hw (VEGA10).
+ * Disable interrupts on the hw (ARCTURUS).
  */
-static void vega10_ih_irq_disable(struct amdgpu_device *adev)
+static void arcturus_ih_irq_disable(struct amdgpu_device *adev)
 {
-	vega10_ih_disable_interrupts(adev);
+	arcturus_ih_disable_interrupts(adev);
 
 	/* Wait and acknowledge irq */
 	mdelay(1);
 }
 
 /**
- * vega10_ih_get_wptr - get the IH ring buffer wptr
+ * arcturus_ih_get_wptr - get the IH ring buffer wptr
  *
  * @adev: amdgpu_device pointer
  *
  * Get the IH ring buffer wptr from either the register
- * or the writeback memory buffer (VEGA10).  Also check for
+ * or the writeback memory buffer (ARCTURUS).  Also check for
  * ring buffer overflow and deal with it.
  * Returns the value of the wptr.
  */
-static u32 vega10_ih_get_wptr(struct amdgpu_device *adev,
+static u32 arcturus_ih_get_wptr(struct amdgpu_device *adev,
 			      struct amdgpu_ih_ring *ih)
 {
 	u32 wptr, reg, tmp;
@@ -425,14 +425,14 @@ static u32 vega10_ih_get_wptr(struct amdgpu_device *adev,
 }
 
 /**
- * vega10_ih_decode_iv - decode an interrupt vector
+ * arcturus_ih_decode_iv - decode an interrupt vector
  *
  * @adev: amdgpu_device pointer
  *
  * Decodes the interrupt vector at the current rptr
  * position and also advance the position.
  */
-static void vega10_ih_decode_iv(struct amdgpu_device *adev,
+static void arcturus_ih_decode_iv(struct amdgpu_device *adev,
 				struct amdgpu_ih_ring *ih,
 				struct amdgpu_iv_entry *entry)
 {
@@ -468,12 +468,12 @@ static void vega10_ih_decode_iv(struct amdgpu_device *adev,
 }
 
 /**
- * vega10_ih_irq_rearm - rearm IRQ if lost
+ * arcturus_ih_irq_rearm - rearm IRQ if lost
  *
  * @adev: amdgpu_device pointer
  *
  */
-static void vega10_ih_irq_rearm(struct amdgpu_device *adev,
+static void arcturus_ih_irq_rearm(struct amdgpu_device *adev,
 			       struct amdgpu_ih_ring *ih)
 {
 	uint32_t reg_rptr = 0;
@@ -500,13 +500,13 @@ static void vega10_ih_irq_rearm(struct amdgpu_device *adev,
 }
 
 /**
- * vega10_ih_set_rptr - set the IH ring buffer rptr
+ * arcturus_ih_set_rptr - set the IH ring buffer rptr
  *
  * @adev: amdgpu_device pointer
  *
  * Set the IH ring buffer rptr.
  */
-static void vega10_ih_set_rptr(struct amdgpu_device *adev,
+static void arcturus_ih_set_rptr(struct amdgpu_device *adev,
 			       struct amdgpu_ih_ring *ih)
 {
 	if (ih->use_doorbell) {
@@ -515,7 +515,7 @@ static void vega10_ih_set_rptr(struct amdgpu_device *adev,
 		WDOORBELL32(ih->doorbell_index, ih->rptr);
 
 		if (amdgpu_sriov_vf(adev))
-			vega10_ih_irq_rearm(adev, ih);
+			arcturus_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) {
@@ -526,7 +526,7 @@ static void vega10_ih_set_rptr(struct amdgpu_device *adev,
 }
 
 /**
- * vega10_ih_self_irq - dispatch work for ring 1 and 2
+ * arcturus_ih_self_irq - dispatch work for ring 1 and 2
  *
  * @adev: amdgpu_device pointer
  * @source: irq source
@@ -534,7 +534,7 @@ static void vega10_ih_set_rptr(struct amdgpu_device *adev,
  *
  * Update the WPTR from the IV and schedule work to handle the entries.
  */
-static int vega10_ih_self_irq(struct amdgpu_device *adev,
+static int arcturus_ih_self_irq(struct amdgpu_device *adev,
 			      struct amdgpu_irq_src *source,
 			      struct amdgpu_iv_entry *entry)
 {
@@ -555,26 +555,26 @@ static int vega10_ih_self_irq(struct amdgpu_device *adev,
 	return 0;
 }
 
-static const struct amdgpu_irq_src_funcs vega10_ih_self_irq_funcs = {
-	.process = vega10_ih_self_irq,
+static const struct amdgpu_irq_src_funcs arcturus_ih_self_irq_funcs = {
+	.process = arcturus_ih_self_irq,
 };
 
-static void vega10_ih_set_self_irq_funcs(struct amdgpu_device *adev)
+static void arcturus_ih_set_self_irq_funcs(struct amdgpu_device *adev)
 {
 	adev->irq.self_irq.num_types = 0;
-	adev->irq.self_irq.funcs = &vega10_ih_self_irq_funcs;
+	adev->irq.self_irq.funcs = &arcturus_ih_self_irq_funcs;
 }
 
-static int vega10_ih_early_init(void *handle)
+static int arcturus_ih_early_init(void *handle)
 {
 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 
-	vega10_ih_set_interrupt_funcs(adev);
-	vega10_ih_set_self_irq_funcs(adev);
+	arcturus_ih_set_interrupt_funcs(adev);
+	arcturus_ih_set_self_irq_funcs(adev);
 	return 0;
 }
 
-static int vega10_ih_sw_init(void *handle)
+static int arcturus_ih_sw_init(void *handle)
 {
 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 	int r;
@@ -610,7 +610,7 @@ static int vega10_ih_sw_init(void *handle)
 	return r;
 }
 
-static int vega10_ih_sw_fini(void *handle)
+static int arcturus_ih_sw_fini(void *handle)
 {
 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 
@@ -622,61 +622,61 @@ static int vega10_ih_sw_fini(void *handle)
 	return 0;
 }
 
-static int vega10_ih_hw_init(void *handle)
+static int arcturus_ih_hw_init(void *handle)
 {
 	int r;
 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 
-	r = vega10_ih_irq_init(adev);
+	r = arcturus_ih_irq_init(adev);
 	if (r)
 		return r;
 
 	return 0;
 }
 
-static int vega10_ih_hw_fini(void *handle)
+static int arcturus_ih_hw_fini(void *handle)
 {
 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 
-	vega10_ih_irq_disable(adev);
+	arcturus_ih_irq_disable(adev);
 
 	return 0;
 }
 
-static int vega10_ih_suspend(void *handle)
+static int arcturus_ih_suspend(void *handle)
 {
 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 
-	return vega10_ih_hw_fini(adev);
+	return arcturus_ih_hw_fini(adev);
 }
 
-static int vega10_ih_resume(void *handle)
+static int arcturus_ih_resume(void *handle)
 {
 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 
-	return vega10_ih_hw_init(adev);
+	return arcturus_ih_hw_init(adev);
 }
 
-static bool vega10_ih_is_idle(void *handle)
+static bool arcturus_ih_is_idle(void *handle)
 {
 	/* todo */
 	return true;
 }
 
-static int vega10_ih_wait_for_idle(void *handle)
+static int arcturus_ih_wait_for_idle(void *handle)
 {
 	/* todo */
 	return -ETIMEDOUT;
 }
 
-static int vega10_ih_soft_reset(void *handle)
+static int arcturus_ih_soft_reset(void *handle)
 {
 	/* todo */
 
 	return 0;
 }
 
-static void vega10_ih_update_clockgating_state(struct amdgpu_device *adev,
+static void arcturus_ih_update_clockgating_state(struct amdgpu_device *adev,
 					       bool enable)
 {
 	uint32_t data, def, field_val;
@@ -703,55 +703,55 @@ static void vega10_ih_update_clockgating_state(struct amdgpu_device *adev,
 	}
 }
 
-static int vega10_ih_set_clockgating_state(void *handle,
+static int arcturus_ih_set_clockgating_state(void *handle,
 					  enum amd_clockgating_state state)
 {
 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 
-	vega10_ih_update_clockgating_state(adev,
+	arcturus_ih_update_clockgating_state(adev,
 				state == AMD_CG_STATE_GATE);
 	return 0;
 
 }
 
-static int vega10_ih_set_powergating_state(void *handle,
+static int arcturus_ih_set_powergating_state(void *handle,
 					  enum amd_powergating_state state)
 {
 	return 0;
 }
 
-const struct amd_ip_funcs vega10_ih_ip_funcs = {
-	.name = "vega10_ih",
-	.early_init = vega10_ih_early_init,
+const struct amd_ip_funcs arcturus_ih_ip_funcs = {
+	.name = "arcturus_ih",
+	.early_init = arcturus_ih_early_init,
 	.late_init = NULL,
-	.sw_init = vega10_ih_sw_init,
-	.sw_fini = vega10_ih_sw_fini,
-	.hw_init = vega10_ih_hw_init,
-	.hw_fini = vega10_ih_hw_fini,
-	.suspend = vega10_ih_suspend,
-	.resume = vega10_ih_resume,
-	.is_idle = vega10_ih_is_idle,
-	.wait_for_idle = vega10_ih_wait_for_idle,
-	.soft_reset = vega10_ih_soft_reset,
-	.set_clockgating_state = vega10_ih_set_clockgating_state,
-	.set_powergating_state = vega10_ih_set_powergating_state,
+	.sw_init = arcturus_ih_sw_init,
+	.sw_fini = arcturus_ih_sw_fini,
+	.hw_init = arcturus_ih_hw_init,
+	.hw_fini = arcturus_ih_hw_fini,
+	.suspend = arcturus_ih_suspend,
+	.resume = arcturus_ih_resume,
+	.is_idle = arcturus_ih_is_idle,
+	.wait_for_idle = arcturus_ih_wait_for_idle,
+	.soft_reset = arcturus_ih_soft_reset,
+	.set_clockgating_state = arcturus_ih_set_clockgating_state,
+	.set_powergating_state = arcturus_ih_set_powergating_state,
 };
 
-static const struct amdgpu_ih_funcs vega10_ih_funcs = {
-	.get_wptr = vega10_ih_get_wptr,
-	.decode_iv = vega10_ih_decode_iv,
-	.set_rptr = vega10_ih_set_rptr
+static const struct amdgpu_ih_funcs arcturus_ih_funcs = {
+	.get_wptr = arcturus_ih_get_wptr,
+	.decode_iv = arcturus_ih_decode_iv,
+	.set_rptr = arcturus_ih_set_rptr
 };
 
-static void vega10_ih_set_interrupt_funcs(struct amdgpu_device *adev)
+static void arcturus_ih_set_interrupt_funcs(struct amdgpu_device *adev)
 {
-	adev->irq.ih_funcs = &vega10_ih_funcs;
+	adev->irq.ih_funcs = &arcturus_ih_funcs;
 }
 
-const struct amdgpu_ip_block_version vega10_ih_ip_block = {
+const struct amdgpu_ip_block_version arcturus_ih_ip_block = {
 	.type = AMD_IP_BLOCK_TYPE_IH,
 	.major = 4,
 	.minor = 0,
 	.rev = 0,
-	.funcs = &vega10_ih_ip_funcs,
+	.funcs = &arcturus_ih_ip_funcs,
 };
diff --git a/drivers/gpu/drm/amd/amdgpu/arcturus_ih.h b/drivers/gpu/drm/amd/amdgpu/arcturus_ih.h
index 54daf8cf6ff3..56da58ac0e97 100644
--- a/drivers/gpu/drm/amd/amdgpu/arcturus_ih.h
+++ b/drivers/gpu/drm/amd/amdgpu/arcturus_ih.h
@@ -21,10 +21,10 @@
  *
  */
 
-#ifndef __VEGA10_IH_H__
-#define __VEGA10_IH_H__
+#ifndef __ARCTURUS_IH_H__
+#define __ARCTURUS_IH_H__
 
-extern const struct amd_ip_funcs vega10_ih_ip_funcs;
-extern const struct amdgpu_ip_block_version vega10_ih_ip_block;
+extern const struct amd_ip_funcs arcturus_ih_ip_funcs;
+extern const struct amdgpu_ip_block_version arcturus_ih_ip_block;
 
 #endif
-- 
2.17.1

_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 5/8] drm/amdgpu: reroute VMC and UMD to IH ring 1 for arcturus
  2020-03-18 22:51 [PATCH 1/8] drm/amdgpu: add mask bit for IH_CLK_CTRL on oss v5.0 Alex Sierra
                   ` (2 preceding siblings ...)
  2020-03-18 22:51 ` [PATCH 4/8] drm/amdgpu: replace function prefix names Alex Sierra
@ 2020-03-18 22:51 ` Alex Sierra
  2020-03-18 22:51 ` [PATCH 6/8] drm/amdgpu: remove Arcturus references from vega10 ih Alex Sierra
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 12+ messages in thread
From: Alex Sierra @ 2020-03-18 22:51 UTC (permalink / raw)
  To: amd-gfx; +Cc: Alex Sierra

[Why]
Same reason as commit "reroute VMC and UMD to IH ring 1" for vega10.
Due Page faults can easily overwhelm the interrupt handler.
So to make sure that we never lose valuable interrupts on the primary ring
we re-route page faults to IH ring 1.
It also facilitates the recovery page process, since it's already
running from a process context.

[How]
Setting IH_CLIENT_CFG_DATA for VMC and UMD IH clients.

Change-Id: I189a6b35c9f5bd55d001fa9672d7d08ba4e8591e
Signed-off-by: Alex Sierra <alex.sierra@amd.com>
---
 drivers/gpu/drm/amd/amdgpu/arcturus_ih.c | 20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)

diff --git a/drivers/gpu/drm/amd/amdgpu/arcturus_ih.c b/drivers/gpu/drm/amd/amdgpu/arcturus_ih.c
index b687fcc4c9b6..73a00e752ead 100644
--- a/drivers/gpu/drm/amd/amdgpu/arcturus_ih.c
+++ b/drivers/gpu/drm/amd/amdgpu/arcturus_ih.c
@@ -205,6 +205,24 @@ static uint32_t arcturus_ih_doorbell_rptr(struct amdgpu_ih_ring *ih)
 	return ih_doorbell_rtpr;
 }
 
+static void arcturus_ih_reroute_ih(struct amdgpu_device *adev)
+{
+	uint32_t tmp;
+
+	/* 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);
+	tmp = REG_SET_FIELD(tmp, IH_CLIENT_CFG_DATA, CLIENT_TYPE, 1);
+	tmp = REG_SET_FIELD(tmp, IH_CLIENT_CFG_DATA, RING_ID, 1);
+	WREG32_SOC15(OSSSYS, 0, mmIH_CLIENT_CFG_DATA, tmp);
+
+	/* Reroute IH ring 1 for UMC */
+	WREG32_SOC15(OSSSYS, 0, mmIH_CLIENT_CFG_INDEX, 0x1B);
+	tmp = RREG32_SOC15(OSSSYS, 0, mmIH_CLIENT_CFG_DATA);
+	tmp = REG_SET_FIELD(tmp, IH_CLIENT_CFG_DATA, RING_ID, 1);
+	WREG32_SOC15(OSSSYS, 0, mmIH_CLIENT_CFG_DATA, tmp);
+}
+
 /**
  * arcturus_ih_irq_init - init and enable the interrupt ring
  *
@@ -246,6 +264,8 @@ static int arcturus_ih_irq_init(struct amdgpu_device *adev)
 		WREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL, ih_rb_cntl);
 	}
 
+	arcturus_ih_reroute_ih(adev);
+
 	if (adev->firmware.load_type == AMDGPU_FW_LOAD_DIRECT) {
 		ih_chicken = RREG32_SOC15(OSSSYS, 0, mmIH_CHICKEN);
 		if (adev->irq.ih.use_bus_addr) {
-- 
2.17.1

_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 6/8] drm/amdgpu: remove Arcturus references from vega10 ih
  2020-03-18 22:51 [PATCH 1/8] drm/amdgpu: add mask bit for IH_CLK_CTRL on oss v5.0 Alex Sierra
                   ` (3 preceding siblings ...)
  2020-03-18 22:51 ` [PATCH 5/8] drm/amdgpu: reroute VMC and UMD to IH ring 1 for arcturus Alex Sierra
@ 2020-03-18 22:51 ` Alex Sierra
  2020-03-18 23:26   ` Felix Kuehling
  2020-03-18 22:51 ` [PATCH 7/8] drm/amdgpu: add arcturus_ih.o into Makefile Alex Sierra
  2020-03-18 22:51 ` [PATCH 8/8] drm/amdgpu: replace ih ip reference for arcturus Alex Sierra
  6 siblings, 1 reply; 12+ messages in thread
From: Alex Sierra @ 2020-03-18 22:51 UTC (permalink / raw)
  To: amd-gfx; +Cc: Alex Sierra

Arcturus has its own ih implementation. There's no need to support
this on vega10 ih anymore.

Change-Id: I29c843e0b12a458d2915129503c0ad852bcebc48
Signed-off-by: Alex Sierra <alex.sierra@amd.com>
---
 drivers/gpu/drm/amd/amdgpu/vega10_ih.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/vega10_ih.c b/drivers/gpu/drm/amd/amdgpu/vega10_ih.c
index 407c6093c2ec..608e8da9b962 100644
--- a/drivers/gpu/drm/amd/amdgpu/vega10_ih.c
+++ b/drivers/gpu/drm/amd/amdgpu/vega10_ih.c
@@ -246,9 +246,7 @@ static int vega10_ih_irq_init(struct amdgpu_device *adev)
 		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,
-- 
2.17.1

_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 7/8] drm/amdgpu: add arcturus_ih.o into Makefile
  2020-03-18 22:51 [PATCH 1/8] drm/amdgpu: add mask bit for IH_CLK_CTRL on oss v5.0 Alex Sierra
                   ` (4 preceding siblings ...)
  2020-03-18 22:51 ` [PATCH 6/8] drm/amdgpu: remove Arcturus references from vega10 ih Alex Sierra
@ 2020-03-18 22:51 ` Alex Sierra
  2020-03-18 22:51 ` [PATCH 8/8] drm/amdgpu: replace ih ip reference for arcturus Alex Sierra
  6 siblings, 0 replies; 12+ messages in thread
From: Alex Sierra @ 2020-03-18 22:51 UTC (permalink / raw)
  To: amd-gfx; +Cc: Alex Sierra

Change-Id: I4701d12bff12052774562e666f95b5978097b5e4
Signed-off-by: Alex Sierra <alex.sierra@amd.com>
---
 drivers/gpu/drm/amd/amdgpu/Makefile | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/Makefile b/drivers/gpu/drm/amd/amdgpu/Makefile
index c2bbcdd9c875..2da7922c166d 100644
--- a/drivers/gpu/drm/amd/amdgpu/Makefile
+++ b/drivers/gpu/drm/amd/amdgpu/Makefile
@@ -94,7 +94,8 @@ amdgpu-y += \
 	tonga_ih.o \
 	cz_ih.o \
 	vega10_ih.o \
-	navi10_ih.o
+	navi10_ih.o \
+	arcturus_ih.o
 
 # add PSP block
 amdgpu-y += \
-- 
2.17.1

_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 8/8] drm/amdgpu: replace ih ip reference for arcturus
  2020-03-18 22:51 [PATCH 1/8] drm/amdgpu: add mask bit for IH_CLK_CTRL on oss v5.0 Alex Sierra
                   ` (5 preceding siblings ...)
  2020-03-18 22:51 ` [PATCH 7/8] drm/amdgpu: add arcturus_ih.o into Makefile Alex Sierra
@ 2020-03-18 22:51 ` Alex Sierra
  6 siblings, 0 replies; 12+ messages in thread
From: Alex Sierra @ 2020-03-18 22:51 UTC (permalink / raw)
  To: amd-gfx; +Cc: Alex Sierra

[Why]
IH implementation for arcturus has been added.
This reference has to be replace it for Arcutus ih ip.

[How]
Replace arcturus ih ip reference.

Change-Id: I5a12b329146fa7883586bb10d22077046a977701
Signed-off-by: Alex Sierra <alex.sierra@amd.com>
---
 drivers/gpu/drm/amd/amdgpu/soc15.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/soc15.c b/drivers/gpu/drm/amd/amdgpu/soc15.c
index a40499d51c93..c27760713aa8 100644
--- a/drivers/gpu/drm/amd/amdgpu/soc15.c
+++ b/drivers/gpu/drm/amd/amdgpu/soc15.c
@@ -62,6 +62,7 @@
 #include "nbio_v7_0.h"
 #include "nbio_v7_4.h"
 #include "vega10_ih.h"
+#include "arcturus_ih.h"
 #include "sdma_v4_0.h"
 #include "uvd_v7_0.h"
 #include "vce_v4_0.h"
@@ -785,9 +786,9 @@ int soc15_set_ip_blocks(struct amdgpu_device *adev)
 		if (amdgpu_sriov_vf(adev)) {
 			if (likely(adev->firmware.load_type == AMDGPU_FW_LOAD_PSP))
 				amdgpu_device_ip_block_add(adev, &psp_v11_0_ip_block);
-			amdgpu_device_ip_block_add(adev, &vega10_ih_ip_block);
+			amdgpu_device_ip_block_add(adev, &arcturus_ih_ip_block);
 		} else {
-			amdgpu_device_ip_block_add(adev, &vega10_ih_ip_block);
+			amdgpu_device_ip_block_add(adev, &arcturus_ih_ip_block);
 			if (likely(adev->firmware.load_type == AMDGPU_FW_LOAD_PSP))
 				amdgpu_device_ip_block_add(adev, &psp_v11_0_ip_block);
 		}
-- 
2.17.1

_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* Re: [PATCH 6/8] drm/amdgpu: remove Arcturus references from vega10 ih
  2020-03-18 22:51 ` [PATCH 6/8] drm/amdgpu: remove Arcturus references from vega10 ih Alex Sierra
@ 2020-03-18 23:26   ` Felix Kuehling
  0 siblings, 0 replies; 12+ messages in thread
From: Felix Kuehling @ 2020-03-18 23:26 UTC (permalink / raw)
  To: amd-gfx, Sierra Guiza, Alejandro (Alex)

I believe this should be squashed into Patch #8 or applied after patch 
#8. Otherwise it creates a broken intermediate state where Arcturus 
doesn't have any valid IH support. That said, it's probably less 
critical because it only affects the case of direct (backdoor) firmware 
loading.

Regards,
   Felix

On 2020-03-18 18:51, Alex Sierra wrote:
> Arcturus has its own ih implementation. There's no need to support
> this on vega10 ih anymore.
>
> Change-Id: I29c843e0b12a458d2915129503c0ad852bcebc48
> Signed-off-by: Alex Sierra <alex.sierra@amd.com>
> ---
>   drivers/gpu/drm/amd/amdgpu/vega10_ih.c | 4 +---
>   1 file changed, 1 insertion(+), 3 deletions(-)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/vega10_ih.c b/drivers/gpu/drm/amd/amdgpu/vega10_ih.c
> index 407c6093c2ec..608e8da9b962 100644
> --- a/drivers/gpu/drm/amd/amdgpu/vega10_ih.c
> +++ b/drivers/gpu/drm/amd/amdgpu/vega10_ih.c
> @@ -246,9 +246,7 @@ static int vega10_ih_irq_init(struct amdgpu_device *adev)
>   		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,
_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH 2/8] drm/amdgpu: create new files for arcturus ih
  2020-03-18 22:51 ` [PATCH 2/8] drm/amdgpu: create new files for arcturus ih Alex Sierra
@ 2020-03-18 23:33   ` Felix Kuehling
  2020-03-19  1:34     ` Deucher, Alexander
  0 siblings, 1 reply; 12+ messages in thread
From: Felix Kuehling @ 2020-03-18 23:33 UTC (permalink / raw)
  To: Alex Sierra, amd-gfx

How much overlap is there between arcturus_ih and nave10_ih? Given that 
they both use the same register map, could they share the same driver 
code with only minor differences?

If they're almost the same, maybe you could rename navi10_ih.[ch] to 
osssys_v5_0.[ch] and use it for both navi10 and arcturus.

Regards,
   Felix

On 2020-03-18 18:51, Alex Sierra wrote:
> [Why]
> Arcturus uses osssys v4.2. This shares the same register map as
> osssys v5.0.
>
> [How]
> Copy vega10_ih into new arcturus_ih source and header files.
> Replace osssys include file with v5.0.0 on arcturus_ih.c source.
>
> Change-Id: I5215f32f477adb6a30acef6e8add9f8e5bb041ef
> Signed-off-by: Alex Sierra <alex.sierra@amd.com>
> ---
>   drivers/gpu/drm/amd/amdgpu/arcturus_ih.c | 766 +++++++++++++++++++++++
>   drivers/gpu/drm/amd/amdgpu/arcturus_ih.h |  30 +
>   2 files changed, 796 insertions(+)
>   create mode 100644 drivers/gpu/drm/amd/amdgpu/arcturus_ih.c
>   create mode 100644 drivers/gpu/drm/amd/amdgpu/arcturus_ih.h
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/arcturus_ih.c b/drivers/gpu/drm/amd/amdgpu/arcturus_ih.c
> new file mode 100644
> index 000000000000..21bb5be40921
> --- /dev/null
> +++ b/drivers/gpu/drm/amd/amdgpu/arcturus_ih.c
> @@ -0,0 +1,766 @@
> +/*
> + * Copyright 2020 Advanced Micro Devices, Inc.
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a
> + * copy of this software and associated documentation files (the "Software"),
> + * to deal in the Software without restriction, including without limitation
> + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
> + * and/or sell copies of the Software, and to permit persons to whom the
> + * Software is furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice shall be included in
> + * all copies or substantial portions of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
> + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
> + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
> + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
> + * OTHER DEALINGS IN THE SOFTWARE.
> + *
> + */
> +
> +#include <linux/pci.h>
> +
> +#include "amdgpu.h"
> +#include "amdgpu_ih.h"
> +#include "soc15.h"
> +
> +#include "oss/osssys_5_0_0_offset.h"
> +#include "oss/osssys_5_0_0_sh_mask.h"
> +
> +#include "soc15_common.h"
> +#include "arcturus_ih.h"
> +
> +#define MAX_REARM_RETRY 10
> +
> +static void vega10_ih_set_interrupt_funcs(struct amdgpu_device *adev);
> +
> +/**
> + * vega10_ih_enable_interrupts - Enable the interrupt ring buffer
> + *
> + * @adev: amdgpu_device pointer
> + *
> + * Enable the interrupt ring buffer (VEGA10).
> + */
> +static void vega10_ih_enable_interrupts(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);
> +	}
> +	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;
> +	}
> +
> +	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;
> +	}
> +}
> +
> +/**
> + * vega10_ih_disable_interrupts - Disable the interrupt ring buffer
> + *
> + * @adev: amdgpu_device pointer
> + *
> + * Disable the interrupt ring buffer (VEGA10).
> + */
> +static void vega10_ih_disable_interrupts(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, 0);
> +	ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, ENABLE_INTR, 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;
> +		}
> +	} else {
> +		WREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL, ih_rb_cntl);
> +	}
> +
> +	/* 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);
> +		}
> +		/* 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;
> +	}
> +
> +	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);
> +		}
> +
> +		/* 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;
> +	}
> +}
> +
> +static uint32_t vega10_ih_rb_cntl(struct amdgpu_ih_ring *ih, uint32_t ih_rb_cntl)
> +{
> +	int rb_bufsz = order_base_2(ih->ring_size / 4);
> +
> +	ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL,
> +				   MC_SPACE, ih->use_bus_addr ? 1 : 4);
> +	ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL,
> +				   WPTR_OVERFLOW_CLEAR, 1);
> +	ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL,
> +				   WPTR_OVERFLOW_ENABLE, 1);
> +	ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, RB_SIZE, rb_bufsz);
> +	/* Ring Buffer write pointer writeback. If enabled, IH_RB_WPTR register
> +	 * value is written to memory
> +	 */
> +	ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL,
> +				   WPTR_WRITEBACK_ENABLE, 1);
> +	ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, MC_SNOOP, 1);
> +	ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, MC_RO, 0);
> +	ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, MC_VMID, 0);
> +
> +	return ih_rb_cntl;
> +}
> +
> +static uint32_t vega10_ih_doorbell_rptr(struct amdgpu_ih_ring *ih)
> +{
> +	u32 ih_doorbell_rtpr = 0;
> +
> +	if (ih->use_doorbell) {
> +		ih_doorbell_rtpr = REG_SET_FIELD(ih_doorbell_rtpr,
> +						 IH_DOORBELL_RPTR, OFFSET,
> +						 ih->doorbell_index);
> +		ih_doorbell_rtpr = REG_SET_FIELD(ih_doorbell_rtpr,
> +						 IH_DOORBELL_RPTR,
> +						 ENABLE, 1);
> +	} else {
> +		ih_doorbell_rtpr = REG_SET_FIELD(ih_doorbell_rtpr,
> +						 IH_DOORBELL_RPTR,
> +						 ENABLE, 0);
> +	}
> +	return ih_doorbell_rtpr;
> +}
> +
> +/**
> + * vega10_ih_irq_init - init and enable the interrupt ring
> + *
> + * @adev: amdgpu_device pointer
> + *
> + * Allocate a ring buffer for the interrupt controller,
> + * enable the RLC, disable interrupts, enable the IH
> + * ring buffer and enable it (VI).
> + * Called at device load and reume.
> + * Returns 0 for success, errors for failure.
> + */
> +static int vega10_ih_irq_init(struct amdgpu_device *adev)
> +{
> +	struct amdgpu_ih_ring *ih;
> +	u32 ih_rb_cntl, ih_chicken;
> +	int ret = 0;
> +	u32 tmp;
> +
> +	/* disable irqs */
> +	vega10_ih_disable_interrupts(adev);
> +
> +	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) {
> +		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);
> +		}
> +
> +		/* 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);
> +	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 */
> +	vega10_ih_enable_interrupts(adev);
> +
> +	return ret;
> +}
> +
> +/**
> + * vega10_ih_irq_disable - disable interrupts
> + *
> + * @adev: amdgpu_device pointer
> + *
> + * Disable interrupts on the hw (VEGA10).
> + */
> +static void vega10_ih_irq_disable(struct amdgpu_device *adev)
> +{
> +	vega10_ih_disable_interrupts(adev);
> +
> +	/* Wait and acknowledge irq */
> +	mdelay(1);
> +}
> +
> +/**
> + * vega10_ih_get_wptr - get the IH ring buffer wptr
> + *
> + * @adev: amdgpu_device pointer
> + *
> + * Get the IH ring buffer wptr from either the register
> + * or the writeback memory buffer (VEGA10).  Also check for
> + * ring buffer overflow and deal with it.
> + * Returns the value of the wptr.
> + */
> +static u32 vega10_ih_get_wptr(struct amdgpu_device *adev,
> +			      struct amdgpu_ih_ring *ih)
> +{
> +	u32 wptr, reg, tmp;
> +
> +	wptr = le32_to_cpu(*ih->wptr_cpu);
> +
> +	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);
> +	if (!REG_GET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW))
> +		goto out;
> +
> +	wptr = REG_SET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW, 0);
> +
> +	/* When a ring buffer overflow happen start parsing interrupt
> +	 * from the last not overwritten vector (wptr + 32). Hopefully
> +	 * this should allow us to catchup.
> +	 */
> +	tmp = (wptr + 32) & ih->ptr_mask;
> +	dev_warn(adev->dev, "IH ring buffer overflow "
> +		 "(0x%08X, 0x%08X, 0x%08X)\n",
> +		 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 = REG_SET_FIELD(tmp, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 1);
> +	WREG32_NO_KIQ(reg, tmp);
> +
> +out:
> +	return (wptr & ih->ptr_mask);
> +}
> +
> +/**
> + * vega10_ih_decode_iv - decode an interrupt vector
> + *
> + * @adev: amdgpu_device pointer
> + *
> + * 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
> + *
> + */
> +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;
> +
> +	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;
> +
> +	/* Rearm IRQ / re-wwrite doorbell if doorbell write is lost */
> +	for (i = 0; i < MAX_REARM_RETRY; i++) {
> +		v = RREG32_NO_KIQ(reg_rptr);
> +		if ((v < ih->ring_size) && (v != ih->rptr))
> +			WDOORBELL32(ih->doorbell_index, ih->rptr);
> +		else
> +			break;
> +	}
> +}
> +
> +/**
> + * vega10_ih_set_rptr - set the IH ring buffer rptr
> + *
> + * @adev: amdgpu_device pointer
> + *
> + * Set the IH ring buffer rptr.
> + */
> +static void vega10_ih_set_rptr(struct amdgpu_device *adev,
> +			       struct amdgpu_ih_ring *ih)
> +{
> +	if (ih->use_doorbell) {
> +		/* XXX check if swapping is necessary on BE */
> +		*ih->rptr_cpu = ih->rptr;
> +		WDOORBELL32(ih->doorbell_index, ih->rptr);
> +
> +		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);
> +	}
> +}
> +
> +/**
> + * vega10_ih_self_irq - dispatch work for ring 1 and 2
> + *
> + * @adev: amdgpu_device pointer
> + * @source: irq source
> + * @entry: IV with WPTR update
> + *
> + * Update the WPTR from the IV and schedule work to handle the entries.
> + */
> +static int vega10_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;
> +	}
> +	return 0;
> +}
> +
> +static const struct amdgpu_irq_src_funcs vega10_ih_self_irq_funcs = {
> +	.process = vega10_ih_self_irq,
> +};
> +
> +static void vega10_ih_set_self_irq_funcs(struct amdgpu_device *adev)
> +{
> +	adev->irq.self_irq.num_types = 0;
> +	adev->irq.self_irq.funcs = &vega10_ih_self_irq_funcs;
> +}
> +
> +static int vega10_ih_early_init(void *handle)
> +{
> +	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
> +
> +	vega10_ih_set_interrupt_funcs(adev);
> +	vega10_ih_set_self_irq_funcs(adev);
> +	return 0;
> +}
> +
> +static int vega10_ih_sw_init(void *handle)
> +{
> +	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
> +	int r;
> +
> +	r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_IH, 0,
> +			      &adev->irq.self_irq);
> +	if (r)
> +		return r;
> +
> +	r = amdgpu_ih_ring_init(adev, &adev->irq.ih, 256 * 1024, true);
> +	if (r)
> +		return r;
> +
> +	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;
> +
> +	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;
> +
> +	adev->irq.ih2.use_doorbell = true;
> +	adev->irq.ih2.doorbell_index = (adev->doorbell_index.ih + 2) << 1;
> +
> +	r = amdgpu_irq_init(adev);
> +
> +	return r;
> +}
> +
> +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.ih2);
> +	amdgpu_ih_ring_fini(adev, &adev->irq.ih1);
> +	amdgpu_ih_ring_fini(adev, &adev->irq.ih);
> +
> +	return 0;
> +}
> +
> +static int vega10_ih_hw_init(void *handle)
> +{
> +	int r;
> +	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
> +
> +	r = vega10_ih_irq_init(adev);
> +	if (r)
> +		return r;
> +
> +	return 0;
> +}
> +
> +static int vega10_ih_hw_fini(void *handle)
> +{
> +	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
> +
> +	vega10_ih_irq_disable(adev);
> +
> +	return 0;
> +}
> +
> +static int vega10_ih_suspend(void *handle)
> +{
> +	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
> +
> +	return vega10_ih_hw_fini(adev);
> +}
> +
> +static int vega10_ih_resume(void *handle)
> +{
> +	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
> +
> +	return vega10_ih_hw_init(adev);
> +}
> +
> +static bool vega10_ih_is_idle(void *handle)
> +{
> +	/* todo */
> +	return true;
> +}
> +
> +static int vega10_ih_wait_for_idle(void *handle)
> +{
> +	/* todo */
> +	return -ETIMEDOUT;
> +}
> +
> +static int vega10_ih_soft_reset(void *handle)
> +{
> +	/* todo */
> +
> +	return 0;
> +}
> +
> +static void vega10_ih_update_clockgating_state(struct amdgpu_device *adev,
> +					       bool enable)
> +{
> +	uint32_t data, def, field_val;
> +
> +	if (adev->cg_flags & AMD_CG_SUPPORT_IH_CG) {
> +		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.
> +		 */
> +		if (adev->asic_type > CHIP_VEGA10) {
> +			data = REG_SET_FIELD(data, IH_CLK_CTRL,
> +				     IH_RETRY_INT_CAM_MEM_CLK_SOFT_OVERRIDE, field_val);
> +			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);
> +		data = REG_SET_FIELD(data, IH_CLK_CTRL,
> +				     OSSSYS_SHARE_CLK_SOFT_OVERRIDE, field_val);
> +		data = REG_SET_FIELD(data, IH_CLK_CTRL,
> +				     LIMIT_SMN_CLK_SOFT_OVERRIDE, field_val);
> +		data = REG_SET_FIELD(data, IH_CLK_CTRL,
> +				     DYN_CLK_SOFT_OVERRIDE, field_val);
> +		data = REG_SET_FIELD(data, IH_CLK_CTRL,
> +				     REG_CLK_SOFT_OVERRIDE, field_val);
> +		if (def != data)
> +			WREG32_SOC15(OSSSYS, 0, mmIH_CLK_CTRL, data);
> +	}
> +}
> +
> +static int vega10_ih_set_clockgating_state(void *handle,
> +					  enum amd_clockgating_state state)
> +{
> +	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
> +
> +	vega10_ih_update_clockgating_state(adev,
> +				state == AMD_CG_STATE_GATE);
> +	return 0;
> +
> +}
> +
> +static int vega10_ih_set_powergating_state(void *handle,
> +					  enum amd_powergating_state state)
> +{
> +	return 0;
> +}
> +
> +const struct amd_ip_funcs vega10_ih_ip_funcs = {
> +	.name = "vega10_ih",
> +	.early_init = vega10_ih_early_init,
> +	.late_init = NULL,
> +	.sw_init = vega10_ih_sw_init,
> +	.sw_fini = vega10_ih_sw_fini,
> +	.hw_init = vega10_ih_hw_init,
> +	.hw_fini = vega10_ih_hw_fini,
> +	.suspend = vega10_ih_suspend,
> +	.resume = vega10_ih_resume,
> +	.is_idle = vega10_ih_is_idle,
> +	.wait_for_idle = vega10_ih_wait_for_idle,
> +	.soft_reset = vega10_ih_soft_reset,
> +	.set_clockgating_state = vega10_ih_set_clockgating_state,
> +	.set_powergating_state = vega10_ih_set_powergating_state,
> +};
> +
> +static const struct amdgpu_ih_funcs vega10_ih_funcs = {
> +	.get_wptr = vega10_ih_get_wptr,
> +	.decode_iv = vega10_ih_decode_iv,
> +	.set_rptr = vega10_ih_set_rptr
> +};
> +
> +static void vega10_ih_set_interrupt_funcs(struct amdgpu_device *adev)
> +{
> +	adev->irq.ih_funcs = &vega10_ih_funcs;
> +}
> +
> +const struct amdgpu_ip_block_version vega10_ih_ip_block = {
> +	.type = AMD_IP_BLOCK_TYPE_IH,
> +	.major = 4,
> +	.minor = 0,
> +	.rev = 0,
> +	.funcs = &vega10_ih_ip_funcs,
> +};
> diff --git a/drivers/gpu/drm/amd/amdgpu/arcturus_ih.h b/drivers/gpu/drm/amd/amdgpu/arcturus_ih.h
> new file mode 100644
> index 000000000000..54daf8cf6ff3
> --- /dev/null
> +++ b/drivers/gpu/drm/amd/amdgpu/arcturus_ih.h
> @@ -0,0 +1,30 @@
> +/*
> + * Copyright 2020 Advanced Micro Devices, Inc.
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a
> + * copy of this software and associated documentation files (the "Software"),
> + * to deal in the Software without restriction, including without limitation
> + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
> + * and/or sell copies of the Software, and to permit persons to whom the
> + * Software is furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice shall be included in
> + * all copies or substantial portions of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
> + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
> + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
> + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
> + * OTHER DEALINGS IN THE SOFTWARE.
> + *
> + */
> +
> +#ifndef __VEGA10_IH_H__
> +#define __VEGA10_IH_H__
> +
> +extern const struct amd_ip_funcs vega10_ih_ip_funcs;
> +extern const struct amdgpu_ip_block_version vega10_ih_ip_block;
> +
> +#endif
_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH 2/8] drm/amdgpu: create new files for arcturus ih
  2020-03-18 23:33   ` Felix Kuehling
@ 2020-03-19  1:34     ` Deucher, Alexander
  2020-03-19  7:43       ` Zhang, Hawking
  0 siblings, 1 reply; 12+ messages in thread
From: Deucher, Alexander @ 2020-03-19  1:34 UTC (permalink / raw)
  To: Kuehling, Felix, Sierra Guiza, Alejandro (Alex), amd-gfx


[-- Attachment #1.1: Type: text/plain, Size: 33173 bytes --]

[AMD Public Use]

if we have been using vega10_ih all along for arcturus, presumably the register map is close enough.  I'd suggest either adding whatever new stuff you need to vega10_ih.c or navi10_ih.c.  No need to add a completely new one for a small change like this.

Alex
________________________________
From: amd-gfx <amd-gfx-bounces@lists.freedesktop.org> on behalf of Felix Kuehling <felix.kuehling@amd.com>
Sent: Wednesday, March 18, 2020 7:33 PM
To: Sierra Guiza, Alejandro (Alex) <Alex.Sierra@amd.com>; amd-gfx@lists.freedesktop.org <amd-gfx@lists.freedesktop.org>
Subject: Re: [PATCH 2/8] drm/amdgpu: create new files for arcturus ih

How much overlap is there between arcturus_ih and nave10_ih? Given that
they both use the same register map, could they share the same driver
code with only minor differences?

If they're almost the same, maybe you could rename navi10_ih.[ch] to
osssys_v5_0.[ch] and use it for both navi10 and arcturus.

Regards,
   Felix

On 2020-03-18 18:51, Alex Sierra wrote:
> [Why]
> Arcturus uses osssys v4.2. This shares the same register map as
> osssys v5.0.
>
> [How]
> Copy vega10_ih into new arcturus_ih source and header files.
> Replace osssys include file with v5.0.0 on arcturus_ih.c source.
>
> Change-Id: I5215f32f477adb6a30acef6e8add9f8e5bb041ef
> Signed-off-by: Alex Sierra <alex.sierra@amd.com>
> ---
>   drivers/gpu/drm/amd/amdgpu/arcturus_ih.c | 766 +++++++++++++++++++++++
>   drivers/gpu/drm/amd/amdgpu/arcturus_ih.h |  30 +
>   2 files changed, 796 insertions(+)
>   create mode 100644 drivers/gpu/drm/amd/amdgpu/arcturus_ih.c
>   create mode 100644 drivers/gpu/drm/amd/amdgpu/arcturus_ih.h
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/arcturus_ih.c b/drivers/gpu/drm/amd/amdgpu/arcturus_ih.c
> new file mode 100644
> index 000000000000..21bb5be40921
> --- /dev/null
> +++ b/drivers/gpu/drm/amd/amdgpu/arcturus_ih.c
> @@ -0,0 +1,766 @@
> +/*
> + * Copyright 2020 Advanced Micro Devices, Inc.
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a
> + * copy of this software and associated documentation files (the "Software"),
> + * to deal in the Software without restriction, including without limitation
> + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
> + * and/or sell copies of the Software, and to permit persons to whom the
> + * Software is furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice shall be included in
> + * all copies or substantial portions of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
> + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
> + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
> + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
> + * OTHER DEALINGS IN THE SOFTWARE.
> + *
> + */
> +
> +#include <linux/pci.h>
> +
> +#include "amdgpu.h"
> +#include "amdgpu_ih.h"
> +#include "soc15.h"
> +
> +#include "oss/osssys_5_0_0_offset.h"
> +#include "oss/osssys_5_0_0_sh_mask.h"
> +
> +#include "soc15_common.h"
> +#include "arcturus_ih.h"
> +
> +#define MAX_REARM_RETRY 10
> +
> +static void vega10_ih_set_interrupt_funcs(struct amdgpu_device *adev);
> +
> +/**
> + * vega10_ih_enable_interrupts - Enable the interrupt ring buffer
> + *
> + * @adev: amdgpu_device pointer
> + *
> + * Enable the interrupt ring buffer (VEGA10).
> + */
> +static void vega10_ih_enable_interrupts(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);
> +     }
> +     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;
> +     }
> +
> +     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;
> +     }
> +}
> +
> +/**
> + * vega10_ih_disable_interrupts - Disable the interrupt ring buffer
> + *
> + * @adev: amdgpu_device pointer
> + *
> + * Disable the interrupt ring buffer (VEGA10).
> + */
> +static void vega10_ih_disable_interrupts(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, 0);
> +     ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, ENABLE_INTR, 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;
> +             }
> +     } else {
> +             WREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL, ih_rb_cntl);
> +     }
> +
> +     /* 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);
> +             }
> +             /* 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;
> +     }
> +
> +     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);
> +             }
> +
> +             /* 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;
> +     }
> +}
> +
> +static uint32_t vega10_ih_rb_cntl(struct amdgpu_ih_ring *ih, uint32_t ih_rb_cntl)
> +{
> +     int rb_bufsz = order_base_2(ih->ring_size / 4);
> +
> +     ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL,
> +                                MC_SPACE, ih->use_bus_addr ? 1 : 4);
> +     ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL,
> +                                WPTR_OVERFLOW_CLEAR, 1);
> +     ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL,
> +                                WPTR_OVERFLOW_ENABLE, 1);
> +     ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, RB_SIZE, rb_bufsz);
> +     /* Ring Buffer write pointer writeback. If enabled, IH_RB_WPTR register
> +      * value is written to memory
> +      */
> +     ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL,
> +                                WPTR_WRITEBACK_ENABLE, 1);
> +     ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, MC_SNOOP, 1);
> +     ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, MC_RO, 0);
> +     ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, MC_VMID, 0);
> +
> +     return ih_rb_cntl;
> +}
> +
> +static uint32_t vega10_ih_doorbell_rptr(struct amdgpu_ih_ring *ih)
> +{
> +     u32 ih_doorbell_rtpr = 0;
> +
> +     if (ih->use_doorbell) {
> +             ih_doorbell_rtpr = REG_SET_FIELD(ih_doorbell_rtpr,
> +                                              IH_DOORBELL_RPTR, OFFSET,
> +                                              ih->doorbell_index);
> +             ih_doorbell_rtpr = REG_SET_FIELD(ih_doorbell_rtpr,
> +                                              IH_DOORBELL_RPTR,
> +                                              ENABLE, 1);
> +     } else {
> +             ih_doorbell_rtpr = REG_SET_FIELD(ih_doorbell_rtpr,
> +                                              IH_DOORBELL_RPTR,
> +                                              ENABLE, 0);
> +     }
> +     return ih_doorbell_rtpr;
> +}
> +
> +/**
> + * vega10_ih_irq_init - init and enable the interrupt ring
> + *
> + * @adev: amdgpu_device pointer
> + *
> + * Allocate a ring buffer for the interrupt controller,
> + * enable the RLC, disable interrupts, enable the IH
> + * ring buffer and enable it (VI).
> + * Called at device load and reume.
> + * Returns 0 for success, errors for failure.
> + */
> +static int vega10_ih_irq_init(struct amdgpu_device *adev)
> +{
> +     struct amdgpu_ih_ring *ih;
> +     u32 ih_rb_cntl, ih_chicken;
> +     int ret = 0;
> +     u32 tmp;
> +
> +     /* disable irqs */
> +     vega10_ih_disable_interrupts(adev);
> +
> +     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) {
> +             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);
> +             }
> +
> +             /* 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);
> +     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 */
> +     vega10_ih_enable_interrupts(adev);
> +
> +     return ret;
> +}
> +
> +/**
> + * vega10_ih_irq_disable - disable interrupts
> + *
> + * @adev: amdgpu_device pointer
> + *
> + * Disable interrupts on the hw (VEGA10).
> + */
> +static void vega10_ih_irq_disable(struct amdgpu_device *adev)
> +{
> +     vega10_ih_disable_interrupts(adev);
> +
> +     /* Wait and acknowledge irq */
> +     mdelay(1);
> +}
> +
> +/**
> + * vega10_ih_get_wptr - get the IH ring buffer wptr
> + *
> + * @adev: amdgpu_device pointer
> + *
> + * Get the IH ring buffer wptr from either the register
> + * or the writeback memory buffer (VEGA10).  Also check for
> + * ring buffer overflow and deal with it.
> + * Returns the value of the wptr.
> + */
> +static u32 vega10_ih_get_wptr(struct amdgpu_device *adev,
> +                           struct amdgpu_ih_ring *ih)
> +{
> +     u32 wptr, reg, tmp;
> +
> +     wptr = le32_to_cpu(*ih->wptr_cpu);
> +
> +     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);
> +     if (!REG_GET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW))
> +             goto out;
> +
> +     wptr = REG_SET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW, 0);
> +
> +     /* When a ring buffer overflow happen start parsing interrupt
> +      * from the last not overwritten vector (wptr + 32). Hopefully
> +      * this should allow us to catchup.
> +      */
> +     tmp = (wptr + 32) & ih->ptr_mask;
> +     dev_warn(adev->dev, "IH ring buffer overflow "
> +              "(0x%08X, 0x%08X, 0x%08X)\n",
> +              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 = REG_SET_FIELD(tmp, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 1);
> +     WREG32_NO_KIQ(reg, tmp);
> +
> +out:
> +     return (wptr & ih->ptr_mask);
> +}
> +
> +/**
> + * vega10_ih_decode_iv - decode an interrupt vector
> + *
> + * @adev: amdgpu_device pointer
> + *
> + * 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
> + *
> + */
> +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;
> +
> +     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;
> +
> +     /* Rearm IRQ / re-wwrite doorbell if doorbell write is lost */
> +     for (i = 0; i < MAX_REARM_RETRY; i++) {
> +             v = RREG32_NO_KIQ(reg_rptr);
> +             if ((v < ih->ring_size) && (v != ih->rptr))
> +                     WDOORBELL32(ih->doorbell_index, ih->rptr);
> +             else
> +                     break;
> +     }
> +}
> +
> +/**
> + * vega10_ih_set_rptr - set the IH ring buffer rptr
> + *
> + * @adev: amdgpu_device pointer
> + *
> + * Set the IH ring buffer rptr.
> + */
> +static void vega10_ih_set_rptr(struct amdgpu_device *adev,
> +                            struct amdgpu_ih_ring *ih)
> +{
> +     if (ih->use_doorbell) {
> +             /* XXX check if swapping is necessary on BE */
> +             *ih->rptr_cpu = ih->rptr;
> +             WDOORBELL32(ih->doorbell_index, ih->rptr);
> +
> +             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);
> +     }
> +}
> +
> +/**
> + * vega10_ih_self_irq - dispatch work for ring 1 and 2
> + *
> + * @adev: amdgpu_device pointer
> + * @source: irq source
> + * @entry: IV with WPTR update
> + *
> + * Update the WPTR from the IV and schedule work to handle the entries.
> + */
> +static int vega10_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;
> +     }
> +     return 0;
> +}
> +
> +static const struct amdgpu_irq_src_funcs vega10_ih_self_irq_funcs = {
> +     .process = vega10_ih_self_irq,
> +};
> +
> +static void vega10_ih_set_self_irq_funcs(struct amdgpu_device *adev)
> +{
> +     adev->irq.self_irq.num_types = 0;
> +     adev->irq.self_irq.funcs = &vega10_ih_self_irq_funcs;
> +}
> +
> +static int vega10_ih_early_init(void *handle)
> +{
> +     struct amdgpu_device *adev = (struct amdgpu_device *)handle;
> +
> +     vega10_ih_set_interrupt_funcs(adev);
> +     vega10_ih_set_self_irq_funcs(adev);
> +     return 0;
> +}
> +
> +static int vega10_ih_sw_init(void *handle)
> +{
> +     struct amdgpu_device *adev = (struct amdgpu_device *)handle;
> +     int r;
> +
> +     r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_IH, 0,
> +                           &adev->irq.self_irq);
> +     if (r)
> +             return r;
> +
> +     r = amdgpu_ih_ring_init(adev, &adev->irq.ih, 256 * 1024, true);
> +     if (r)
> +             return r;
> +
> +     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;
> +
> +     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;
> +
> +     adev->irq.ih2.use_doorbell = true;
> +     adev->irq.ih2.doorbell_index = (adev->doorbell_index.ih + 2) << 1;
> +
> +     r = amdgpu_irq_init(adev);
> +
> +     return r;
> +}
> +
> +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.ih2);
> +     amdgpu_ih_ring_fini(adev, &adev->irq.ih1);
> +     amdgpu_ih_ring_fini(adev, &adev->irq.ih);
> +
> +     return 0;
> +}
> +
> +static int vega10_ih_hw_init(void *handle)
> +{
> +     int r;
> +     struct amdgpu_device *adev = (struct amdgpu_device *)handle;
> +
> +     r = vega10_ih_irq_init(adev);
> +     if (r)
> +             return r;
> +
> +     return 0;
> +}
> +
> +static int vega10_ih_hw_fini(void *handle)
> +{
> +     struct amdgpu_device *adev = (struct amdgpu_device *)handle;
> +
> +     vega10_ih_irq_disable(adev);
> +
> +     return 0;
> +}
> +
> +static int vega10_ih_suspend(void *handle)
> +{
> +     struct amdgpu_device *adev = (struct amdgpu_device *)handle;
> +
> +     return vega10_ih_hw_fini(adev);
> +}
> +
> +static int vega10_ih_resume(void *handle)
> +{
> +     struct amdgpu_device *adev = (struct amdgpu_device *)handle;
> +
> +     return vega10_ih_hw_init(adev);
> +}
> +
> +static bool vega10_ih_is_idle(void *handle)
> +{
> +     /* todo */
> +     return true;
> +}
> +
> +static int vega10_ih_wait_for_idle(void *handle)
> +{
> +     /* todo */
> +     return -ETIMEDOUT;
> +}
> +
> +static int vega10_ih_soft_reset(void *handle)
> +{
> +     /* todo */
> +
> +     return 0;
> +}
> +
> +static void vega10_ih_update_clockgating_state(struct amdgpu_device *adev,
> +                                            bool enable)
> +{
> +     uint32_t data, def, field_val;
> +
> +     if (adev->cg_flags & AMD_CG_SUPPORT_IH_CG) {
> +             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.
> +              */
> +             if (adev->asic_type > CHIP_VEGA10) {
> +                     data = REG_SET_FIELD(data, IH_CLK_CTRL,
> +                                  IH_RETRY_INT_CAM_MEM_CLK_SOFT_OVERRIDE, field_val);
> +                     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);
> +             data = REG_SET_FIELD(data, IH_CLK_CTRL,
> +                                  OSSSYS_SHARE_CLK_SOFT_OVERRIDE, field_val);
> +             data = REG_SET_FIELD(data, IH_CLK_CTRL,
> +                                  LIMIT_SMN_CLK_SOFT_OVERRIDE, field_val);
> +             data = REG_SET_FIELD(data, IH_CLK_CTRL,
> +                                  DYN_CLK_SOFT_OVERRIDE, field_val);
> +             data = REG_SET_FIELD(data, IH_CLK_CTRL,
> +                                  REG_CLK_SOFT_OVERRIDE, field_val);
> +             if (def != data)
> +                     WREG32_SOC15(OSSSYS, 0, mmIH_CLK_CTRL, data);
> +     }
> +}
> +
> +static int vega10_ih_set_clockgating_state(void *handle,
> +                                       enum amd_clockgating_state state)
> +{
> +     struct amdgpu_device *adev = (struct amdgpu_device *)handle;
> +
> +     vega10_ih_update_clockgating_state(adev,
> +                             state == AMD_CG_STATE_GATE);
> +     return 0;
> +
> +}
> +
> +static int vega10_ih_set_powergating_state(void *handle,
> +                                       enum amd_powergating_state state)
> +{
> +     return 0;
> +}
> +
> +const struct amd_ip_funcs vega10_ih_ip_funcs = {
> +     .name = "vega10_ih",
> +     .early_init = vega10_ih_early_init,
> +     .late_init = NULL,
> +     .sw_init = vega10_ih_sw_init,
> +     .sw_fini = vega10_ih_sw_fini,
> +     .hw_init = vega10_ih_hw_init,
> +     .hw_fini = vega10_ih_hw_fini,
> +     .suspend = vega10_ih_suspend,
> +     .resume = vega10_ih_resume,
> +     .is_idle = vega10_ih_is_idle,
> +     .wait_for_idle = vega10_ih_wait_for_idle,
> +     .soft_reset = vega10_ih_soft_reset,
> +     .set_clockgating_state = vega10_ih_set_clockgating_state,
> +     .set_powergating_state = vega10_ih_set_powergating_state,
> +};
> +
> +static const struct amdgpu_ih_funcs vega10_ih_funcs = {
> +     .get_wptr = vega10_ih_get_wptr,
> +     .decode_iv = vega10_ih_decode_iv,
> +     .set_rptr = vega10_ih_set_rptr
> +};
> +
> +static void vega10_ih_set_interrupt_funcs(struct amdgpu_device *adev)
> +{
> +     adev->irq.ih_funcs = &vega10_ih_funcs;
> +}
> +
> +const struct amdgpu_ip_block_version vega10_ih_ip_block = {
> +     .type = AMD_IP_BLOCK_TYPE_IH,
> +     .major = 4,
> +     .minor = 0,
> +     .rev = 0,
> +     .funcs = &vega10_ih_ip_funcs,
> +};
> diff --git a/drivers/gpu/drm/amd/amdgpu/arcturus_ih.h b/drivers/gpu/drm/amd/amdgpu/arcturus_ih.h
> new file mode 100644
> index 000000000000..54daf8cf6ff3
> --- /dev/null
> +++ b/drivers/gpu/drm/amd/amdgpu/arcturus_ih.h
> @@ -0,0 +1,30 @@
> +/*
> + * Copyright 2020 Advanced Micro Devices, Inc.
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a
> + * copy of this software and associated documentation files (the "Software"),
> + * to deal in the Software without restriction, including without limitation
> + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
> + * and/or sell copies of the Software, and to permit persons to whom the
> + * Software is furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice shall be included in
> + * all copies or substantial portions of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
> + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
> + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
> + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
> + * OTHER DEALINGS IN THE SOFTWARE.
> + *
> + */
> +
> +#ifndef __VEGA10_IH_H__
> +#define __VEGA10_IH_H__
> +
> +extern const struct amd_ip_funcs vega10_ih_ip_funcs;
> +extern const struct amdgpu_ip_block_version vega10_ih_ip_block;
> +
> +#endif
_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Flists.freedesktop.org%2Fmailman%2Flistinfo%2Famd-gfx&amp;data=02%7C01%7Calexander.deucher%40amd.com%7Ca1fe681c257644a9727c08d7cb94d5f5%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637201712448085102&amp;sdata=M8SSL1wFhDgmkyFd36kMHmuPzAqp%2BU0QHwttrz0rOzo%3D&amp;reserved=0

[-- Attachment #1.2: Type: text/html, Size: 71143 bytes --]

[-- Attachment #2: Type: text/plain, Size: 154 bytes --]

_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

^ permalink raw reply	[flat|nested] 12+ messages in thread

* RE: [PATCH 2/8] drm/amdgpu: create new files for arcturus ih
  2020-03-19  1:34     ` Deucher, Alexander
@ 2020-03-19  7:43       ` Zhang, Hawking
  0 siblings, 0 replies; 12+ messages in thread
From: Zhang, Hawking @ 2020-03-19  7:43 UTC (permalink / raw)
  To: Deucher, Alexander, Kuehling, Felix, Sierra Guiza,
	Alejandro (Alex),
	amd-gfx


[-- Attachment #1.1: Type: text/plain, Size: 34450 bytes --]

[AMD Public Use]

The register offset of IH_RB_RING1|RING2 register group is the major differences between osssys 4.0 and osssys 4.2. Other than that, 4.2 share the same registers as 4.0. So just centralize ih ring1 and ring2 related functions into a separated file, and invoke ih ring1 and ring2 function from vega10_ih function call for Arcturus.

Regards,
Hawking
From: amd-gfx <amd-gfx-bounces@lists.freedesktop.org> On Behalf Of Deucher, Alexander
Sent: Thursday, March 19, 2020 09:35
To: Kuehling, Felix <Felix.Kuehling@amd.com>; Sierra Guiza, Alejandro (Alex) <Alex.Sierra@amd.com>; amd-gfx@lists.freedesktop.org
Subject: Re: [PATCH 2/8] drm/amdgpu: create new files for arcturus ih


[AMD Public Use]

if we have been using vega10_ih all along for arcturus, presumably the register map is close enough.  I'd suggest either adding whatever new stuff you need to vega10_ih.c or navi10_ih.c.  No need to add a completely new one for a small change like this.

Alex
________________________________
From: amd-gfx <amd-gfx-bounces@lists.freedesktop.org<mailto:amd-gfx-bounces@lists.freedesktop.org>> on behalf of Felix Kuehling <felix.kuehling@amd.com<mailto:felix.kuehling@amd.com>>
Sent: Wednesday, March 18, 2020 7:33 PM
To: Sierra Guiza, Alejandro (Alex) <Alex.Sierra@amd.com<mailto:Alex.Sierra@amd.com>>; amd-gfx@lists.freedesktop.org<mailto:amd-gfx@lists.freedesktop.org> <amd-gfx@lists.freedesktop.org<mailto:amd-gfx@lists.freedesktop.org>>
Subject: Re: [PATCH 2/8] drm/amdgpu: create new files for arcturus ih

How much overlap is there between arcturus_ih and nave10_ih? Given that
they both use the same register map, could they share the same driver
code with only minor differences?

If they're almost the same, maybe you could rename navi10_ih.[ch] to
osssys_v5_0.[ch] and use it for both navi10 and arcturus.

Regards,
   Felix

On 2020-03-18 18:51, Alex Sierra wrote:
> [Why]
> Arcturus uses osssys v4.2. This shares the same register map as
> osssys v5.0.
>
> [How]
> Copy vega10_ih into new arcturus_ih source and header files.
> Replace osssys include file with v5.0.0 on arcturus_ih.c source.
>
> Change-Id: I5215f32f477adb6a30acef6e8add9f8e5bb041ef
> Signed-off-by: Alex Sierra <alex.sierra@amd.com<mailto:alex.sierra@amd.com>>
> ---
>   drivers/gpu/drm/amd/amdgpu/arcturus_ih.c | 766 +++++++++++++++++++++++
>   drivers/gpu/drm/amd/amdgpu/arcturus_ih.h |  30 +
>   2 files changed, 796 insertions(+)
>   create mode 100644 drivers/gpu/drm/amd/amdgpu/arcturus_ih.c
>   create mode 100644 drivers/gpu/drm/amd/amdgpu/arcturus_ih.h
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/arcturus_ih.c b/drivers/gpu/drm/amd/amdgpu/arcturus_ih.c
> new file mode 100644
> index 000000000000..21bb5be40921
> --- /dev/null
> +++ b/drivers/gpu/drm/amd/amdgpu/arcturus_ih.c
> @@ -0,0 +1,766 @@
> +/*
> + * Copyright 2020 Advanced Micro Devices, Inc.
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a
> + * copy of this software and associated documentation files (the "Software"),
> + * to deal in the Software without restriction, including without limitation
> + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
> + * and/or sell copies of the Software, and to permit persons to whom the
> + * Software is furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice shall be included in
> + * all copies or substantial portions of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
> + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
> + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
> + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
> + * OTHER DEALINGS IN THE SOFTWARE.
> + *
> + */
> +
> +#include <linux/pci.h>
> +
> +#include "amdgpu.h"
> +#include "amdgpu_ih.h"
> +#include "soc15.h"
> +
> +#include "oss/osssys_5_0_0_offset.h"
> +#include "oss/osssys_5_0_0_sh_mask.h"
> +
> +#include "soc15_common.h"
> +#include "arcturus_ih.h"
> +
> +#define MAX_REARM_RETRY 10
> +
> +static void vega10_ih_set_interrupt_funcs(struct amdgpu_device *adev);
> +
> +/**
> + * vega10_ih_enable_interrupts - Enable the interrupt ring buffer
> + *
> + * @adev: amdgpu_device pointer
> + *
> + * Enable the interrupt ring buffer (VEGA10).
> + */
> +static void vega10_ih_enable_interrupts(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);
> +     }
> +     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;
> +     }
> +
> +     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;
> +     }
> +}
> +
> +/**
> + * vega10_ih_disable_interrupts - Disable the interrupt ring buffer
> + *
> + * @adev: amdgpu_device pointer
> + *
> + * Disable the interrupt ring buffer (VEGA10).
> + */
> +static void vega10_ih_disable_interrupts(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, 0);
> +     ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, ENABLE_INTR, 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;
> +             }
> +     } else {
> +             WREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL, ih_rb_cntl);
> +     }
> +
> +     /* 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);
> +             }
> +             /* 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;
> +     }
> +
> +     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);
> +             }
> +
> +             /* 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;
> +     }
> +}
> +
> +static uint32_t vega10_ih_rb_cntl(struct amdgpu_ih_ring *ih, uint32_t ih_rb_cntl)
> +{
> +     int rb_bufsz = order_base_2(ih->ring_size / 4);
> +
> +     ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL,
> +                                MC_SPACE, ih->use_bus_addr ? 1 : 4);
> +     ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL,
> +                                WPTR_OVERFLOW_CLEAR, 1);
> +     ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL,
> +                                WPTR_OVERFLOW_ENABLE, 1);
> +     ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, RB_SIZE, rb_bufsz);
> +     /* Ring Buffer write pointer writeback. If enabled, IH_RB_WPTR register
> +      * value is written to memory
> +      */
> +     ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL,
> +                                WPTR_WRITEBACK_ENABLE, 1);
> +     ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, MC_SNOOP, 1);
> +     ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, MC_RO, 0);
> +     ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, MC_VMID, 0);
> +
> +     return ih_rb_cntl;
> +}
> +
> +static uint32_t vega10_ih_doorbell_rptr(struct amdgpu_ih_ring *ih)
> +{
> +     u32 ih_doorbell_rtpr = 0;
> +
> +     if (ih->use_doorbell) {
> +             ih_doorbell_rtpr = REG_SET_FIELD(ih_doorbell_rtpr,
> +                                              IH_DOORBELL_RPTR, OFFSET,
> +                                              ih->doorbell_index);
> +             ih_doorbell_rtpr = REG_SET_FIELD(ih_doorbell_rtpr,
> +                                              IH_DOORBELL_RPTR,
> +                                              ENABLE, 1);
> +     } else {
> +             ih_doorbell_rtpr = REG_SET_FIELD(ih_doorbell_rtpr,
> +                                              IH_DOORBELL_RPTR,
> +                                              ENABLE, 0);
> +     }
> +     return ih_doorbell_rtpr;
> +}
> +
> +/**
> + * vega10_ih_irq_init - init and enable the interrupt ring
> + *
> + * @adev: amdgpu_device pointer
> + *
> + * Allocate a ring buffer for the interrupt controller,
> + * enable the RLC, disable interrupts, enable the IH
> + * ring buffer and enable it (VI).
> + * Called at device load and reume.
> + * Returns 0 for success, errors for failure.
> + */
> +static int vega10_ih_irq_init(struct amdgpu_device *adev)
> +{
> +     struct amdgpu_ih_ring *ih;
> +     u32 ih_rb_cntl, ih_chicken;
> +     int ret = 0;
> +     u32 tmp;
> +
> +     /* disable irqs */
> +     vega10_ih_disable_interrupts(adev);
> +
> +     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) {
> +             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);
> +             }
> +
> +             /* 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);
> +     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 */
> +     vega10_ih_enable_interrupts(adev);
> +
> +     return ret;
> +}
> +
> +/**
> + * vega10_ih_irq_disable - disable interrupts
> + *
> + * @adev: amdgpu_device pointer
> + *
> + * Disable interrupts on the hw (VEGA10).
> + */
> +static void vega10_ih_irq_disable(struct amdgpu_device *adev)
> +{
> +     vega10_ih_disable_interrupts(adev);
> +
> +     /* Wait and acknowledge irq */
> +     mdelay(1);
> +}
> +
> +/**
> + * vega10_ih_get_wptr - get the IH ring buffer wptr
> + *
> + * @adev: amdgpu_device pointer
> + *
> + * Get the IH ring buffer wptr from either the register
> + * or the writeback memory buffer (VEGA10).  Also check for
> + * ring buffer overflow and deal with it.
> + * Returns the value of the wptr.
> + */
> +static u32 vega10_ih_get_wptr(struct amdgpu_device *adev,
> +                           struct amdgpu_ih_ring *ih)
> +{
> +     u32 wptr, reg, tmp;
> +
> +     wptr = le32_to_cpu(*ih->wptr_cpu);
> +
> +     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);
> +     if (!REG_GET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW))
> +             goto out;
> +
> +     wptr = REG_SET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW, 0);
> +
> +     /* When a ring buffer overflow happen start parsing interrupt
> +      * from the last not overwritten vector (wptr + 32). Hopefully
> +      * this should allow us to catchup.
> +      */
> +     tmp = (wptr + 32) & ih->ptr_mask;
> +     dev_warn(adev->dev, "IH ring buffer overflow "
> +              "(0x%08X, 0x%08X, 0x%08X)\n",
> +              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 = REG_SET_FIELD(tmp, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 1);
> +     WREG32_NO_KIQ(reg, tmp);
> +
> +out:
> +     return (wptr & ih->ptr_mask);
> +}
> +
> +/**
> + * vega10_ih_decode_iv - decode an interrupt vector
> + *
> + * @adev: amdgpu_device pointer
> + *
> + * 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
> + *
> + */
> +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;
> +
> +     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;
> +
> +     /* Rearm IRQ / re-wwrite doorbell if doorbell write is lost */
> +     for (i = 0; i < MAX_REARM_RETRY; i++) {
> +             v = RREG32_NO_KIQ(reg_rptr);
> +             if ((v < ih->ring_size) && (v != ih->rptr))
> +                     WDOORBELL32(ih->doorbell_index, ih->rptr);
> +             else
> +                     break;
> +     }
> +}
> +
> +/**
> + * vega10_ih_set_rptr - set the IH ring buffer rptr
> + *
> + * @adev: amdgpu_device pointer
> + *
> + * Set the IH ring buffer rptr.
> + */
> +static void vega10_ih_set_rptr(struct amdgpu_device *adev,
> +                            struct amdgpu_ih_ring *ih)
> +{
> +     if (ih->use_doorbell) {
> +             /* XXX check if swapping is necessary on BE */
> +             *ih->rptr_cpu = ih->rptr;
> +             WDOORBELL32(ih->doorbell_index, ih->rptr);
> +
> +             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);
> +     }
> +}
> +
> +/**
> + * vega10_ih_self_irq - dispatch work for ring 1 and 2
> + *
> + * @adev: amdgpu_device pointer
> + * @source: irq source
> + * @entry: IV with WPTR update
> + *
> + * Update the WPTR from the IV and schedule work to handle the entries.
> + */
> +static int vega10_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;
> +     }
> +     return 0;
> +}
> +
> +static const struct amdgpu_irq_src_funcs vega10_ih_self_irq_funcs = {
> +     .process = vega10_ih_self_irq,
> +};
> +
> +static void vega10_ih_set_self_irq_funcs(struct amdgpu_device *adev)
> +{
> +     adev->irq.self_irq.num_types = 0;
> +     adev->irq.self_irq.funcs = &vega10_ih_self_irq_funcs;
> +}
> +
> +static int vega10_ih_early_init(void *handle)
> +{
> +     struct amdgpu_device *adev = (struct amdgpu_device *)handle;
> +
> +     vega10_ih_set_interrupt_funcs(adev);
> +     vega10_ih_set_self_irq_funcs(adev);
> +     return 0;
> +}
> +
> +static int vega10_ih_sw_init(void *handle)
> +{
> +     struct amdgpu_device *adev = (struct amdgpu_device *)handle;
> +     int r;
> +
> +     r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_IH, 0,
> +                           &adev->irq.self_irq);
> +     if (r)
> +             return r;
> +
> +     r = amdgpu_ih_ring_init(adev, &adev->irq.ih, 256 * 1024, true);
> +     if (r)
> +             return r;
> +
> +     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;
> +
> +     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;
> +
> +     adev->irq.ih2.use_doorbell = true;
> +     adev->irq.ih2.doorbell_index = (adev->doorbell_index.ih + 2) << 1;
> +
> +     r = amdgpu_irq_init(adev);
> +
> +     return r;
> +}
> +
> +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.ih2);
> +     amdgpu_ih_ring_fini(adev, &adev->irq.ih1);
> +     amdgpu_ih_ring_fini(adev, &adev->irq.ih);
> +
> +     return 0;
> +}
> +
> +static int vega10_ih_hw_init(void *handle)
> +{
> +     int r;
> +     struct amdgpu_device *adev = (struct amdgpu_device *)handle;
> +
> +     r = vega10_ih_irq_init(adev);
> +     if (r)
> +             return r;
> +
> +     return 0;
> +}
> +
> +static int vega10_ih_hw_fini(void *handle)
> +{
> +     struct amdgpu_device *adev = (struct amdgpu_device *)handle;
> +
> +     vega10_ih_irq_disable(adev);
> +
> +     return 0;
> +}
> +
> +static int vega10_ih_suspend(void *handle)
> +{
> +     struct amdgpu_device *adev = (struct amdgpu_device *)handle;
> +
> +     return vega10_ih_hw_fini(adev);
> +}
> +
> +static int vega10_ih_resume(void *handle)
> +{
> +     struct amdgpu_device *adev = (struct amdgpu_device *)handle;
> +
> +     return vega10_ih_hw_init(adev);
> +}
> +
> +static bool vega10_ih_is_idle(void *handle)
> +{
> +     /* todo */
> +     return true;
> +}
> +
> +static int vega10_ih_wait_for_idle(void *handle)
> +{
> +     /* todo */
> +     return -ETIMEDOUT;
> +}
> +
> +static int vega10_ih_soft_reset(void *handle)
> +{
> +     /* todo */
> +
> +     return 0;
> +}
> +
> +static void vega10_ih_update_clockgating_state(struct amdgpu_device *adev,
> +                                            bool enable)
> +{
> +     uint32_t data, def, field_val;
> +
> +     if (adev->cg_flags & AMD_CG_SUPPORT_IH_CG) {
> +             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.
> +              */
> +             if (adev->asic_type > CHIP_VEGA10) {
> +                     data = REG_SET_FIELD(data, IH_CLK_CTRL,
> +                                  IH_RETRY_INT_CAM_MEM_CLK_SOFT_OVERRIDE, field_val);
> +                     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);
> +             data = REG_SET_FIELD(data, IH_CLK_CTRL,
> +                                  OSSSYS_SHARE_CLK_SOFT_OVERRIDE, field_val);
> +             data = REG_SET_FIELD(data, IH_CLK_CTRL,
> +                                  LIMIT_SMN_CLK_SOFT_OVERRIDE, field_val);
> +             data = REG_SET_FIELD(data, IH_CLK_CTRL,
> +                                  DYN_CLK_SOFT_OVERRIDE, field_val);
> +             data = REG_SET_FIELD(data, IH_CLK_CTRL,
> +                                  REG_CLK_SOFT_OVERRIDE, field_val);
> +             if (def != data)
> +                     WREG32_SOC15(OSSSYS, 0, mmIH_CLK_CTRL, data);
> +     }
> +}
> +
> +static int vega10_ih_set_clockgating_state(void *handle,
> +                                       enum amd_clockgating_state state)
> +{
> +     struct amdgpu_device *adev = (struct amdgpu_device *)handle;
> +
> +     vega10_ih_update_clockgating_state(adev,
> +                             state == AMD_CG_STATE_GATE);
> +     return 0;
> +
> +}
> +
> +static int vega10_ih_set_powergating_state(void *handle,
> +                                       enum amd_powergating_state state)
> +{
> +     return 0;
> +}
> +
> +const struct amd_ip_funcs vega10_ih_ip_funcs = {
> +     .name = "vega10_ih",
> +     .early_init = vega10_ih_early_init,
> +     .late_init = NULL,
> +     .sw_init = vega10_ih_sw_init,
> +     .sw_fini = vega10_ih_sw_fini,
> +     .hw_init = vega10_ih_hw_init,
> +     .hw_fini = vega10_ih_hw_fini,
> +     .suspend = vega10_ih_suspend,
> +     .resume = vega10_ih_resume,
> +     .is_idle = vega10_ih_is_idle,
> +     .wait_for_idle = vega10_ih_wait_for_idle,
> +     .soft_reset = vega10_ih_soft_reset,
> +     .set_clockgating_state = vega10_ih_set_clockgating_state,
> +     .set_powergating_state = vega10_ih_set_powergating_state,
> +};
> +
> +static const struct amdgpu_ih_funcs vega10_ih_funcs = {
> +     .get_wptr = vega10_ih_get_wptr,
> +     .decode_iv = vega10_ih_decode_iv,
> +     .set_rptr = vega10_ih_set_rptr
> +};
> +
> +static void vega10_ih_set_interrupt_funcs(struct amdgpu_device *adev)
> +{
> +     adev->irq.ih_funcs = &vega10_ih_funcs;
> +}
> +
> +const struct amdgpu_ip_block_version vega10_ih_ip_block = {
> +     .type = AMD_IP_BLOCK_TYPE_IH,
> +     .major = 4,
> +     .minor = 0,
> +     .rev = 0,
> +     .funcs = &vega10_ih_ip_funcs,
> +};
> diff --git a/drivers/gpu/drm/amd/amdgpu/arcturus_ih.h b/drivers/gpu/drm/amd/amdgpu/arcturus_ih.h
> new file mode 100644
> index 000000000000..54daf8cf6ff3
> --- /dev/null
> +++ b/drivers/gpu/drm/amd/amdgpu/arcturus_ih.h
> @@ -0,0 +1,30 @@
> +/*
> + * Copyright 2020 Advanced Micro Devices, Inc.
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a
> + * copy of this software and associated documentation files (the "Software"),
> + * to deal in the Software without restriction, including without limitation
> + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
> + * and/or sell copies of the Software, and to permit persons to whom the
> + * Software is furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice shall be included in
> + * all copies or substantial portions of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
> + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
> + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
> + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
> + * OTHER DEALINGS IN THE SOFTWARE.
> + *
> + */
> +
> +#ifndef __VEGA10_IH_H__
> +#define __VEGA10_IH_H__
> +
> +extern const struct amd_ip_funcs vega10_ih_ip_funcs;
> +extern const struct amdgpu_ip_block_version vega10_ih_ip_block;
> +
> +#endif
_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org<mailto:amd-gfx@lists.freedesktop.org>
https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Flists.freedesktop.org%2Fmailman%2Flistinfo%2Famd-gfx&amp;data=02%7C01%7Calexander.deucher%40amd.com%7Ca1fe681c257644a9727c08d7cb94d5f5%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637201712448085102&amp;sdata=M8SSL1wFhDgmkyFd36kMHmuPzAqp%2BU0QHwttrz0rOzo%3D&amp;reserved=0<https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Flists.freedesktop.org%2Fmailman%2Flistinfo%2Famd-gfx&data=02%7C01%7Chawking.zhang%40amd.com%7Cd2c1351802c1460154ae08d7cba5bfe3%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637201785086924150&sdata=Zvu33NFtbbE%2FtMRqll%2BeaayRdTAx6MYEysSdMPrIEgU%3D&reserved=0>

[-- Attachment #1.2: Type: text/html, Size: 74697 bytes --]

[-- Attachment #2: Type: text/plain, Size: 154 bytes --]

_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2020-03-19  7:43 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-03-18 22:51 [PATCH 1/8] drm/amdgpu: add mask bit for IH_CLK_CTRL on oss v5.0 Alex Sierra
2020-03-18 22:51 ` [PATCH 2/8] drm/amdgpu: create new files for arcturus ih Alex Sierra
2020-03-18 23:33   ` Felix Kuehling
2020-03-19  1:34     ` Deucher, Alexander
2020-03-19  7:43       ` Zhang, Hawking
2020-03-18 22:51 ` [PATCH 3/8] drm/amdgpu: remove non Arcturus references from arcturus_ih Alex Sierra
2020-03-18 22:51 ` [PATCH 4/8] drm/amdgpu: replace function prefix names Alex Sierra
2020-03-18 22:51 ` [PATCH 5/8] drm/amdgpu: reroute VMC and UMD to IH ring 1 for arcturus Alex Sierra
2020-03-18 22:51 ` [PATCH 6/8] drm/amdgpu: remove Arcturus references from vega10 ih Alex Sierra
2020-03-18 23:26   ` Felix Kuehling
2020-03-18 22:51 ` [PATCH 7/8] drm/amdgpu: add arcturus_ih.o into Makefile Alex Sierra
2020-03-18 22:51 ` [PATCH 8/8] drm/amdgpu: replace ih ip reference for arcturus Alex Sierra

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.