#include "ivpu_hw.h"
#include "ivpu_jsm_msg.h"
#include "ivpu_pm.h"
+#include "vpu_boot_api.h"
static inline struct ivpu_device *seq_to_ivpu(struct seq_file *s)
{
{
struct ivpu_device *vdev = seq_to_ivpu(s);
- seq_printf(s, "%s\n", (vdev->pm->is_warmboot) ? "warmboot" : "coldboot");
+ seq_printf(s, "%s\n", (vdev->fw->last_boot_mode == VPU_BOOT_TYPE_WARMBOOT) ?
+ "warm boot" : "cold boot");
return 0;
}
drm_WARN_ON(&vdev->drm, !xa_empty(&vdev->submitted_jobs_xa));
ivpu_fw_boot_params_setup(vdev, ivpu_bo_vaddr(vdev->fw->mem_bp));
+ vdev->fw->last_boot_mode = vdev->fw->next_boot_mode;
ret = ivpu_hw_boot_fw(vdev);
if (ret) {
ivpu_err(vdev, "Failed to boot the firmware: %d\n", ret);
goto err_diagnose_failure;
}
-
ivpu_hw_irq_clear(vdev);
enable_irq(vdev->irq);
ivpu_hw_irq_enable(vdev);
ivpu_ipc_enable(vdev);
- if (ivpu_fw_is_cold_boot(vdev)) {
+ if (!ivpu_fw_is_warm_boot(vdev)) {
ret = ivpu_pm_dct_init(vdev);
if (ret)
goto err_disable_ipc;
fw->image_load_offset = image_load_addr - runtime_addr;
fw->image_size = image_size;
fw->shave_nn_size = PAGE_ALIGN(fw_hdr->shave_nn_fw_size);
-
fw->cold_boot_entry_point = fw_hdr->entry_point;
- fw->entry_point = fw->cold_boot_entry_point;
fw->trace_level = min_t(u32, ivpu_fw_log_level, IVPU_FW_LOG_FATAL);
fw->trace_destination_mask = VPU_TRACE_DESTINATION_VERBOSE_TRACING;
fw->image_load_offset, fw->image_size);
ivpu_dbg(vdev, FW_BOOT, "Read-only section: address 0x%llx, size %u\n",
fw->read_only_addr, fw->read_only_size);
- ivpu_dbg(vdev, FW_BOOT, "FW entry point: 0x%llx\n", fw->entry_point);
+ ivpu_dbg(vdev, FW_BOOT, "FW cold boot entry point: 0x%llx\n", fw->cold_boot_entry_point);
ivpu_dbg(vdev, FW_BOOT, "SHAVE NN size: %u\n", fw->shave_nn_size);
return 0;
boot_params->power_profile);
ivpu_dbg(vdev, FW_BOOT, "boot_params.vpu_uses_ecc_mca_signal = 0x%x\n",
boot_params->vpu_uses_ecc_mca_signal);
+ ivpu_dbg(vdev, FW_BOOT, "boot_params.boot_type = 0x%x\n", boot_params->boot_type);
}
void ivpu_fw_boot_params_setup(struct ivpu_device *vdev, struct vpu_boot_params *boot_params)
struct ivpu_bo *ipc_mem_rx = vdev->ipc->mem_rx;
/* In case of warm boot only update variable params */
- if (!ivpu_fw_is_cold_boot(vdev)) {
+ if (ivpu_fw_is_warm_boot(vdev)) {
boot_params->d0i3_residency_time_us =
ktime_us_delta(ktime_get_boottime(), vdev->hw->d0i3_entry_host_ts);
boot_params->d0i3_entry_vpu_ts = vdev->hw->d0i3_entry_vpu_ts;
boot_params->d0i3_entry_vpu_ts);
ivpu_dbg(vdev, FW_BOOT, "boot_params.system_time_us = %llu\n",
boot_params->system_time_us);
+ ivpu_dbg(vdev, FW_BOOT, "boot_params.boot_type = 0x%x\n", boot_params->boot_type);
boot_params->save_restore_ret_address = 0;
- vdev->pm->is_warmboot = true;
+ boot_params->boot_type = VPU_BOOT_TYPE_WARMBOOT;
wmb(); /* Flush WC buffers after writing save_restore_ret_address */
return;
}
memset(boot_params, 0, sizeof(*boot_params));
- vdev->pm->is_warmboot = false;
-
+ boot_params->boot_type = VPU_BOOT_TYPE_COLDBOOT;
boot_params->magic = VPU_BOOT_PARAMS_MAGIC;
boot_params->vpu_id = to_pci_dev(vdev->drm.dev)->bus->number;
#ifndef __IVPU_FW_H__
#define __IVPU_FW_H__
+#include "vpu_boot_api.h"
#include "vpu_jsm_api.h"
#define FW_VERSION_HEADER_SIZE SZ_4K
u64 image_load_offset;
u32 image_size;
u32 shave_nn_size;
- u64 entry_point; /* Cold or warm boot entry point for next boot */
+ u64 warm_boot_entry_point;
u64 cold_boot_entry_point;
+ u8 last_boot_mode;
+ u8 next_boot_mode;
u32 trace_level;
u32 trace_destination_mask;
u64 trace_hw_component_mask;
void ivpu_fw_load(struct ivpu_device *vdev);
void ivpu_fw_boot_params_setup(struct ivpu_device *vdev, struct vpu_boot_params *boot_params);
-static inline bool ivpu_fw_is_cold_boot(struct ivpu_device *vdev)
+static inline bool ivpu_fw_is_warm_boot(struct ivpu_device *vdev)
{
- return vdev->fw->entry_point == vdev->fw->cold_boot_entry_point;
+ return vdev->fw->next_boot_mode == VPU_BOOT_TYPE_WARMBOOT;
}
static inline u32 ivpu_fw_preempt_buf_size(struct ivpu_device *vdev)
#define VPU_50XX_HOST_SS_AON_PWR_ISLAND_STATUS_DLY 0x0003006cu
#define VPU_50XX_HOST_SS_AON_PWR_ISLAND_STATUS_DLY_STATUS_DLY_MASK GENMASK(7, 0)
+#define VPU_40XX_HOST_SS_AON_RETENTION0 0x0003000cu
+#define VPU_40XX_HOST_SS_AON_RETENTION1 0x00030010u
+#define VPU_40XX_HOST_SS_AON_RETENTION2 0x00030014u
+#define VPU_40XX_HOST_SS_AON_RETENTION3 0x00030018u
+#define VPU_40XX_HOST_SS_AON_RETENTION4 0x0003001cu
+
#define VPU_40XX_HOST_SS_AON_IDLE_GEN 0x00030200u
#define VPU_40XX_HOST_SS_AON_IDLE_GEN_EN_MASK BIT_MASK(0)
#define VPU_40XX_HOST_SS_AON_IDLE_GEN_HW_PG_EN_MASK BIT_MASK(1)
#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"
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;
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;
}
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)
void ivpu_hw_ip_ipc_tx_set(struct ivpu_device *vdev, u32 vpu_addr);
void ivpu_hw_ip_irq_enable(struct ivpu_device *vdev);
void ivpu_hw_ip_irq_disable(struct ivpu_device *vdev);
-void ivpu_hw_ip_diagnose_failure(struct ivpu_device *vdev);
void ivpu_hw_ip_fabric_req_override_enable_50xx(struct ivpu_device *vdev);
void ivpu_hw_ip_fabric_req_override_disable_50xx(struct ivpu_device *vdev);
ivpu_ipc_reset(vdev);
ivpu_fw_log_reset(vdev);
ivpu_fw_load(vdev);
- fw->entry_point = fw->cold_boot_entry_point;
fw->last_heartbeat = 0;
+
+ ivpu_dbg(vdev, FW_BOOT, "Cold boot entry point 0x%llx", vdev->fw->cold_boot_entry_point);
+ fw->next_boot_mode = VPU_BOOT_TYPE_COLDBOOT;
}
static void ivpu_pm_prepare_warm_boot(struct ivpu_device *vdev)
struct ivpu_fw_info *fw = vdev->fw;
struct vpu_boot_params *bp = ivpu_bo_vaddr(fw->mem_bp);
- if (!bp->save_restore_ret_address) {
+ fw->warm_boot_entry_point = bp->save_restore_ret_address;
+ if (!fw->warm_boot_entry_point) {
ivpu_pm_prepare_cold_boot(vdev);
return;
}
- ivpu_dbg(vdev, FW_BOOT, "Save/restore entry point %llx", bp->save_restore_ret_address);
- fw->entry_point = bp->save_restore_ret_address;
+ ivpu_dbg(vdev, FW_BOOT, "Warm boot entry point 0x%llx", fw->warm_boot_entry_point);
+ fw->next_boot_mode = VPU_BOOT_TYPE_WARMBOOT;
}
static int ivpu_suspend(struct ivpu_device *vdev)
ivpu_hw_power_down(vdev);
pci_set_power_state(to_pci_dev(vdev->drm.dev), PCI_D3hot);
- if (!ivpu_fw_is_cold_boot(vdev)) {
+ if (ivpu_fw_is_warm_boot(vdev)) {
ivpu_pm_prepare_cold_boot(vdev);
goto retry;
} else {
struct rw_semaphore reset_lock;
atomic_t reset_counter;
atomic_t reset_pending;
- bool is_warmboot;
u8 dct_active_percent;
};