[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