From: Andrey Grodzovsky <[email protected]>

Add psp vbflash function for psp v13.

v2: fix warnings

Signed-off-by: Andrey Grodzovsky <[email protected]>
Signed-off-by: Likun Gao <[email protected]>
Reviewed-by: Hawking Zhang <[email protected]>
Signed-off-by: Alex Deucher <[email protected]>
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h |  5 ++
 drivers/gpu/drm/amd/amdgpu/psp_v13_0.c  | 74 ++++++++++++++++++++++++-
 2 files changed, 78 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h
index a9fe05c38715..81ecbdeb1ddb 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h
@@ -129,6 +129,7 @@ struct psp_funcs
        void (*ring_set_wptr)(struct psp_context *psp, uint32_t value);
        int (*load_usbc_pd_fw)(struct psp_context *psp, uint64_t 
fw_pri_mc_addr);
        int (*read_usbc_pd_fw)(struct psp_context *psp, uint32_t *fw_ver);
+       int (*update_spirom)(struct psp_context *psp, uint64_t fw_pri_mc_addr);
 };
 
 #define AMDGPU_XGMI_MAX_CONNECTED_NODES                64
@@ -417,6 +418,10 @@ struct amdgpu_psp_funcs {
        ((psp)->funcs->read_usbc_pd_fw ? \
        (psp)->funcs->read_usbc_pd_fw((psp), fw_ver) : -EINVAL)
 
+#define psp_update_spirom(psp, fw_pri_mc_addr) \
+       ((psp)->funcs->update_spirom ? \
+       (psp)->funcs->update_spirom((psp), fw_pri_mc_addr) : -EINVAL)
+
 extern const struct amd_ip_funcs psp_ip_funcs;
 
 extern const struct amdgpu_ip_block_version psp_v3_1_ip_block;
diff --git a/drivers/gpu/drm/amd/amdgpu/psp_v13_0.c 
b/drivers/gpu/drm/amd/amdgpu/psp_v13_0.c
index 9beb94681dd2..894ac0c64bf6 100644
--- a/drivers/gpu/drm/amd/amdgpu/psp_v13_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/psp_v13_0.c
@@ -50,6 +50,15 @@ MODULE_FIRMWARE("amdgpu/psp_13_0_7_sos.bin");
 /* Read USB-PD from LFB */
 #define GFX_CMD_USB_PD_USE_LFB 0x480
 
+/* VBIOS gfl defines */
+#define MBOX_READY_MASK 0x80000000
+#define MBOX_STATUS_MASK 0x0000FFFF
+#define MBOX_COMMAND_MASK 0x00FF0000
+#define MBOX_READY_FLAG 0x80000000
+#define C2PMSG_CMD_SPI_UPDATE_ROM_IMAGE_ADDR_LO 0x2
+#define C2PMSG_CMD_SPI_UPDATE_ROM_IMAGE_ADDR_HI 0x3
+#define C2PMSG_CMD_SPI_UPDATE_FLASH_IMAGE 0x4
+
 static int psp_v13_0_init_microcode(struct psp_context *psp)
 {
        struct amdgpu_device *adev = psp->adev;
@@ -465,6 +474,68 @@ static int psp_v13_0_read_usbc_pd_fw(struct psp_context 
*psp, uint32_t *fw_ver)
        return ret;
 }
 
+static int psp_v13_0_exec_spi_cmd(struct psp_context *psp, int cmd)
+{
+       uint32_t reg_status = 0, reg_val = 0;
+       struct amdgpu_device *adev = psp->adev;
+       int ret;
+
+       /* clear MBX ready (MBOX_READY_MASK bit is 0) and set update command */
+       reg_val |= (cmd << 16);
+       WREG32_SOC15(MP0, 0, regMP0_SMN_C2PMSG_115,  reg_val);
+
+       /* Ring the doorbell */
+       WREG32_SOC15(MP0, 0, regMP0_SMN_C2PMSG_73, 1);
+
+       ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, regMP0_SMN_C2PMSG_115),
+                               MBOX_READY_FLAG, MBOX_READY_MASK, false);
+       if (ret) {
+               dev_err(adev->dev, "SPI cmd %x timed out, ret = %d", cmd, ret);
+               return ret;
+       }
+
+       reg_status = RREG32_SOC15(MP0, 0, regMP0_SMN_C2PMSG_115);
+       if ((reg_status & 0xFFFF) != 0) {
+               dev_err(adev->dev, "SPI cmd %x failed, fail status = %04x\n",
+                               cmd, reg_status & 0xFFFF);
+               return -EIO;
+       }
+
+       return 0;
+}
+
+int psp_v13_0_update_spirom(struct psp_context *psp, uint64_t fw_pri_mc_addr)
+{
+       struct amdgpu_device *adev = psp->adev;
+       int ret;
+
+       /* Confirm PSP is ready to start */
+       ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, regMP0_SMN_C2PMSG_115),
+                          MBOX_READY_FLAG, MBOX_READY_MASK, false);
+       if (ret) {
+               dev_err(adev->dev, "PSP Not ready to start processing, ret = 
%d", ret);
+               return ret;
+       }
+
+       WREG32_SOC15(MP0, 0, regMP0_SMN_C2PMSG_116, 
lower_32_bits(fw_pri_mc_addr));
+
+       ret = psp_v13_0_exec_spi_cmd(psp, 
C2PMSG_CMD_SPI_UPDATE_ROM_IMAGE_ADDR_LO);
+       if (ret)
+               return ret;
+
+       WREG32_SOC15(MP0, 0, regMP0_SMN_C2PMSG_116, 
upper_32_bits(fw_pri_mc_addr));
+
+       ret = psp_v13_0_exec_spi_cmd(psp, 
C2PMSG_CMD_SPI_UPDATE_ROM_IMAGE_ADDR_HI);
+       if (ret)
+               return ret;
+
+       ret = psp_v13_0_exec_spi_cmd(psp, C2PMSG_CMD_SPI_UPDATE_FLASH_IMAGE);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
 static const struct psp_funcs psp_v13_0_funcs = {
        .init_microcode = psp_v13_0_init_microcode,
        .bootloader_load_kdb = psp_v13_0_bootloader_load_kdb,
@@ -481,7 +552,8 @@ static const struct psp_funcs psp_v13_0_funcs = {
        .ring_get_wptr = psp_v13_0_ring_get_wptr,
        .ring_set_wptr = psp_v13_0_ring_set_wptr,
        .load_usbc_pd_fw = psp_v13_0_load_usbc_pd_fw,
-       .read_usbc_pd_fw = psp_v13_0_read_usbc_pd_fw
+       .read_usbc_pd_fw = psp_v13_0_read_usbc_pd_fw,
+       .update_spirom = psp_v13_0_update_spirom
 };
 
 void psp_v13_0_set_psp_funcs(struct psp_context *psp)
-- 
2.35.1

Reply via email to