[PATCH 3/4] drm/amdgpu: Add PSP v15.0.8 interrupt handler

Alex Deucher <[email protected]>
Newsgroups org.freedesktop.lists.amd-gfx
Message-ID <[email protected]>
From: Lijo Lazar <[email protected]>

Register and add interrupt handler in PSP v15.0.8.

Signed-off-by: Lijo Lazar <[email protected]>
Reviewed-by: Felix Kuehling <[email protected]>
Signed-off-by: Alex Deucher <[email protected]>
---
 drivers/gpu/drm/amd/amdgpu/ih_v7_0.c     | 13 +++-
 drivers/gpu/drm/amd/amdgpu/psp_v15_0_8.c | 90 ++++++++++++++++++++++++
 2 files changed, 102 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/ih_v7_0.c b/drivers/gpu/drm/amd/amdgpu/ih_v7_0.c
index b51dacf9e1266..6265ee4b0ff1e 100644
--- a/drivers/gpu/drm/amd/amdgpu/ih_v7_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/ih_v7_0.c
@@ -420,6 +420,9 @@ static int ih_v7_0_irq_init(struct amdgpu_device *adev)
 	if (adev->irq.ih_soft.ring_size)
 		adev->irq.ih_soft.enabled = true;
 
+	if (adev->irq.ih_psp.ring_size)
+		adev->irq.ih_psp.enabled = true;
+
 	return 0;
 }
 
@@ -627,6 +630,10 @@ static int ih_v7_0_sw_init(struct amdgpu_ip_block *ip_block)
 	if (r)
 		return r;
 
+	r = amdgpu_ih_ring_init(adev, &adev->irq.ih_psp, IH_PSP_RING_SIZE, true);
+	if (r)
+		return r;
+
 	r = amdgpu_irq_init(adev);
 
 	return r;
@@ -655,7 +662,11 @@ static int ih_v7_0_hw_init(struct amdgpu_ip_block *ip_block)
 
 static int ih_v7_0_hw_fini(struct amdgpu_ip_block *ip_block)
 {
-	ih_v7_0_irq_disable(ip_block->adev);
+	struct amdgpu_device *adev = ip_block->adev;
+
+	ih_v7_0_irq_disable(adev);
+
+	cancel_work_sync(&adev->irq.ih_psp_work);
 
 	return 0;
 }
diff --git a/drivers/gpu/drm/amd/amdgpu/psp_v15_0_8.c b/drivers/gpu/drm/amd/amdgpu/psp_v15_0_8.c
index f159efd585c32..85857b747bd46 100644
--- a/drivers/gpu/drm/amd/amdgpu/psp_v15_0_8.c
+++ b/drivers/gpu/drm/amd/amdgpu/psp_v15_0_8.c
@@ -357,6 +357,95 @@ static int psp_v15_0_8_get_fw_type(struct amdgpu_firmware_info *ucode,
 	return 0;
 }
 
+/* TBD: These should be in psp_gfx_if.h */
+#define IH_INTERRUPT_ID_TO_DRIVER 0xFF
+
+static int psp_v15_0_8_irq_process(struct amdgpu_device *adev,
+				   struct amdgpu_irq_src *source,
+				   struct amdgpu_iv_entry *entry)
+{
+	struct psp_context *psp = &adev->psp;
+	uint32_t data;
+
+	/* Replayed from the PSP soft ring: run the registered handler. */
+	if (entry->ih == &adev->irq.ih_psp) {
+		amdgpu_psp_irq_mgr_dispatch(&psp->irq_mgr, entry);
+		return 1;
+	}
+
+	/* ACK ASP interrupt */
+	if (!amdgpu_sriov_vf(adev)) {
+		data = RREG32_SOC15(MP0, 0, regMPASP_SMN_IH_SW_INT_CTRL);
+		data = REG_SET_FIELD(data, MPASP_SMN_IH_SW_INT_CTRL, INT_ACK, 1);
+		WREG32_SOC15(MP0, 0, regMPASP_SMN_IH_SW_INT_CTRL, data);
+	}
+
+	dev_dbg(adev->dev,
+		"psp_v15_0_8_irq_process: ctxid[0] = %d, ctxid[1] = %d\n",
+		entry->src_data[0], entry->src_data[1]);
+
+	/* Delegate to the PSP soft ring for process-context handling. */
+	amdgpu_irq_psp_delegate(adev, entry, 8);
+
+	return 1;
+}
+
+static int psp_v15_0_8_set_irq_state(struct amdgpu_device *adev,
+				     struct amdgpu_irq_src *source,
+				     unsigned int type,
+				     enum amdgpu_interrupt_state state)
+{
+	uint32_t val = 0;
+
+	if (amdgpu_sriov_vf(adev))
+		return 0;
+
+	switch (state) {
+	case AMDGPU_IRQ_STATE_DISABLE:
+		val = RREG32_SOC15(MP0, 0, regMPASP_SMN_IH_SW_INT_CTRL);
+		val = REG_SET_FIELD(val, MPASP_SMN_IH_SW_INT_CTRL, INT_MASK, 1);
+		WREG32_SOC15(MP0, 0, regMPASP_SMN_IH_SW_INT_CTRL, val);
+		break;
+	case AMDGPU_IRQ_STATE_ENABLE:
+		val = RREG32_SOC15(MP0, 0, regMPASP_SMN_IH_SW_INT);
+		val = REG_SET_FIELD(val, MPASP_SMN_IH_SW_INT, ID, 0xFE);
+		val = REG_SET_FIELD(val, MPASP_SMN_IH_SW_INT, VALID, 0);
+		WREG32_SOC15(MP0, 0, regMPASP_SMN_IH_SW_INT, val);
+
+		val = RREG32_SOC15(MP0, 0, regMPASP_SMN_IH_SW_INT_CTRL);
+		val = REG_SET_FIELD(val, MPASP_SMN_IH_SW_INT_CTRL, INT_MASK, 0);
+		WREG32_SOC15(MP0, 0, regMPASP_SMN_IH_SW_INT_CTRL, val);
+		break;
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+static const struct amdgpu_irq_src_funcs psp_v15_0_8_irq_funcs = {
+	.set = psp_v15_0_8_set_irq_state,
+	.process = psp_v15_0_8_irq_process,
+};
+
+static int psp_v15_0_8_register_irq_handler(struct amdgpu_psp_irq_mgr *mgr,
+					    struct amdgpu_irq_src *irq_src)
+{
+	struct psp_context *psp = mgr->psp;
+	struct amdgpu_device *adev = psp->adev;
+	int ret;
+
+	irq_src->num_types = 1;
+	irq_src->funcs = &psp_v15_0_8_irq_funcs;
+
+	ret = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_MP0,
+				IH_INTERRUPT_ID_TO_DRIVER, irq_src);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
 static const struct psp_funcs psp_v15_0_8_funcs = {
 	.init_microcode = psp_v15_0_8_init_microcode,
 	.ring_create = psp_v15_0_8_ring_create,
@@ -366,6 +455,7 @@ static const struct psp_funcs psp_v15_0_8_funcs = {
 	.ring_set_wptr = psp_v15_0_8_ring_set_wptr,
 	.get_fw_type = psp_v15_0_8_get_fw_type,
 	.get_ras_capability = psp_v15_0_8_get_ras_capability,
+	.register_irq_handler = psp_v15_0_8_register_irq_handler,
 };
 
 void psp_v15_0_8_set_psp_funcs(struct psp_context *psp)
-- 
2.55.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.