diff options
Diffstat (limited to 'drivers/accel/ivpu/ivpu_hw_ip.c')
| -rw-r--r-- | drivers/accel/ivpu/ivpu_hw_ip.c | 74 |
1 files changed, 51 insertions, 23 deletions
diff --git a/drivers/accel/ivpu/ivpu_hw_ip.c b/drivers/accel/ivpu/ivpu_hw_ip.c index 06aa1e7dc50b..959984c54341 100644 --- a/drivers/accel/ivpu/ivpu_hw_ip.c +++ b/drivers/accel/ivpu/ivpu_hw_ip.c @@ -5,6 +5,7 @@ #include "ivpu_drv.h" #include "ivpu_fw.h" +#include "ivpu_gem.h" #include "ivpu_hw.h" #include "ivpu_hw_37xx_reg.h" #include "ivpu_hw_40xx_reg.h" @@ -816,6 +817,14 @@ void ivpu_hw_ip_tbu_mmu_enable(struct ivpu_device *vdev) return ivpu_hw_ip_tbu_mmu_enable_40xx(vdev); } +static inline u64 get_entry_point_addr(struct ivpu_device *vdev) +{ + if (ivpu_fw_is_warm_boot(vdev)) + return vdev->fw->warm_boot_entry_point; + else + return vdev->fw->cold_boot_entry_point; +} + static int soc_cpu_boot_37xx(struct ivpu_device *vdev) { u32 val; @@ -832,15 +841,12 @@ static int soc_cpu_boot_37xx(struct ivpu_device *vdev) val = REG_CLR_FLD(VPU_37XX_CPU_SS_MSSCPU_CPR_LEON_RT_VEC, IRQI_RESUME0, val); REGV_WR32(VPU_37XX_CPU_SS_MSSCPU_CPR_LEON_RT_VEC, val); - val = vdev->fw->entry_point >> 9; + val = get_entry_point_addr(vdev) >> 9; REGV_WR32(VPU_37XX_HOST_SS_LOADING_ADDRESS_LO, val); val = REG_SET_FLD(VPU_37XX_HOST_SS_LOADING_ADDRESS_LO, DONE, val); REGV_WR32(VPU_37XX_HOST_SS_LOADING_ADDRESS_LO, val); - ivpu_dbg(vdev, PM, "Booting firmware, mode: %s\n", - vdev->fw->entry_point == vdev->fw->cold_boot_entry_point ? "cold boot" : "resume"); - return 0; } @@ -894,46 +900,68 @@ static int soc_cpu_drive_40xx(struct ivpu_device *vdev, bool enable) return ret; } -static int soc_cpu_enable(struct ivpu_device *vdev) +static void soc_cpu_set_entry_point_40xx(struct ivpu_device *vdev, u64 entry_point) { - if (ivpu_hw_ip_gen(vdev) >= IVPU_HW_IP_60XX) - return 0; + u64 val64; + u32 val; + + val64 = entry_point; + val64 <<= ffs(VPU_40XX_HOST_SS_VERIFICATION_ADDRESS_LO_IMAGE_LOCATION_MASK) - 1; + REGV_WR64(VPU_40XX_HOST_SS_VERIFICATION_ADDRESS_LO, val64); - return soc_cpu_drive_40xx(vdev, true); + val = REGV_RD32(VPU_40XX_HOST_SS_VERIFICATION_ADDRESS_LO); + val = REG_SET_FLD(VPU_40XX_HOST_SS_VERIFICATION_ADDRESS_LO, DONE, val); + REGV_WR32(VPU_40XX_HOST_SS_VERIFICATION_ADDRESS_LO, val); } static int soc_cpu_boot_40xx(struct ivpu_device *vdev) { int ret; - u32 val; - u64 val64; - ret = soc_cpu_enable(vdev); + ret = soc_cpu_drive_40xx(vdev, true); if (ret) { ivpu_err(vdev, "Failed to enable SOC CPU: %d\n", ret); return ret; } - val64 = vdev->fw->entry_point; - val64 <<= ffs(VPU_40XX_HOST_SS_VERIFICATION_ADDRESS_LO_IMAGE_LOCATION_MASK) - 1; - REGV_WR64(VPU_40XX_HOST_SS_VERIFICATION_ADDRESS_LO, val64); + soc_cpu_set_entry_point_40xx(vdev, get_entry_point_addr(vdev)); - val = REGV_RD32(VPU_40XX_HOST_SS_VERIFICATION_ADDRESS_LO); - val = REG_SET_FLD(VPU_40XX_HOST_SS_VERIFICATION_ADDRESS_LO, DONE, val); - REGV_WR32(VPU_40XX_HOST_SS_VERIFICATION_ADDRESS_LO, val); + return 0; +} - ivpu_dbg(vdev, PM, "Booting firmware, mode: %s\n", - ivpu_fw_is_cold_boot(vdev) ? "cold boot" : "resume"); +static int soc_cpu_boot_60xx(struct ivpu_device *vdev) +{ + REGV_WR64(VPU_40XX_HOST_SS_AON_RETENTION1, vdev->fw->mem_bp->vpu_addr); + soc_cpu_set_entry_point_40xx(vdev, vdev->fw->cold_boot_entry_point); return 0; } int ivpu_hw_ip_soc_cpu_boot(struct ivpu_device *vdev) { - if (ivpu_hw_ip_gen(vdev) == IVPU_HW_IP_37XX) - return soc_cpu_boot_37xx(vdev); - else - return soc_cpu_boot_40xx(vdev); + int ret; + + switch (ivpu_hw_ip_gen(vdev)) { + case IVPU_HW_IP_37XX: + ret = soc_cpu_boot_37xx(vdev); + break; + + case IVPU_HW_IP_40XX: + case IVPU_HW_IP_50XX: + ret = soc_cpu_boot_40xx(vdev); + break; + + default: + ret = soc_cpu_boot_60xx(vdev); + } + + if (ret) + return ret; + + ivpu_dbg(vdev, PM, "Booting firmware, mode: %s\n", + ivpu_fw_is_warm_boot(vdev) ? "warm boot" : "cold boot"); + + return 0; } static void wdt_disable_37xx(struct ivpu_device *vdev) |
