Commit 44e4c889 authored by Karol Wachowski's avatar Karol Wachowski Committed by Maciej Falkowski
Browse files

accel/ivpu: Implement warm boot flow for NPU6 and unify boot handling



Starting from NPU6, the driver can pass boot parameters address through
the AON retention register and toggle between cold/warm boot types using
the boot_type parameter, while setting the cold boot entry point in both
cases.

Refactor the existing cold/warm boot handling to be consistent with the
new NPU6 boot flow requirements and still maintain compatibility with
older boot flows.

This will allow firmware to remove support for legacy warm boot starting
from NPU6.

Fixes: 550f4dd2 ("accel/ivpu: Add support for Nova Lake's NPU")
Signed-off-by: default avatarKarol Wachowski <karol.wachowski@linux.intel.com>
Reviewed-by: default avatarJeff Hugo <jeff.hugo@oss.qualcomm.com>
Reviewed-by: default avatarAndrzej Kacprowski <andrzej.kacprowski@linux.intel.com>
Signed-off-by: default avatarMaciej Falkowski <maciej.falkowski@linux.intel.com>
Link: https://patch.msgid.link/20251230142116.540026-1-maciej.falkowski@linux.intel.com
parent d42d701e
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@
#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)
{
@@ -96,7 +97,8 @@ static int last_bootmode_show(struct seq_file *s, void *v)
{
	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;
}
+2 −2
Original line number Diff line number Diff line
@@ -384,6 +384,7 @@ int ivpu_boot(struct ivpu_device *vdev)
	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) {
@@ -396,13 +397,12 @@ int ivpu_boot(struct ivpu_device *vdev)
		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;
+6 −7
Original line number Diff line number Diff line
@@ -300,9 +300,7 @@ static int ivpu_fw_parse(struct ivpu_device *vdev)
	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;
@@ -338,7 +336,7 @@ static int ivpu_fw_parse(struct ivpu_device *vdev)
		 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;
@@ -616,6 +614,7 @@ static void ivpu_fw_boot_params_print(struct ivpu_device *vdev, struct vpu_boot_
		 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)
@@ -623,7 +622,7 @@ void ivpu_fw_boot_params_setup(struct ivpu_device *vdev, struct vpu_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;
@@ -635,16 +634,16 @@ void ivpu_fw_boot_params_setup(struct ivpu_device *vdev, struct vpu_boot_params
			 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;

+6 −3
Original line number Diff line number Diff line
@@ -6,6 +6,7 @@
#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
@@ -34,8 +35,10 @@ struct ivpu_fw_info {
	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;
@@ -54,9 +57,9 @@ void ivpu_fw_fini(struct ivpu_device *vdev);
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)
+6 −0
Original line number Diff line number Diff line
@@ -121,6 +121,12 @@
#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)
Loading