Re: [PATCH 08/11] accel/ivpu: Pass D0i3 residency time to the VPU firmware

2023-10-27 Thread Jeffrey Hugo

On 10/25/2023 3:43 AM, Stanislaw Gruszka wrote:

From: Andrzej Kacprowski 

The firmware needs to know the time spend in D0i3/D3 to


spent?


calculate telemetry data. The D0i3/D3 residency time is
calculated by the driver and passed to the firmware
in the boot parameters.

The driver also passes VPU perf counter value captured
right before entering D0i3 - this allows the VPU firmware
to generate monotonic timestamps for the logs.

Signed-off-by: Andrzej Kacprowski 
Reviewed-by: Stanislaw Gruszka 
Signed-off-by: Stanislaw Gruszka 


Reviewed-by: Jeffrey Hugo 


[PATCH 08/11] accel/ivpu: Pass D0i3 residency time to the VPU firmware

2023-10-25 Thread Stanislaw Gruszka
From: Andrzej Kacprowski 

The firmware needs to know the time spend in D0i3/D3 to
calculate telemetry data. The D0i3/D3 residency time is
calculated by the driver and passed to the firmware
in the boot parameters.

The driver also passes VPU perf counter value captured
right before entering D0i3 - this allows the VPU firmware
to generate monotonic timestamps for the logs.

Signed-off-by: Andrzej Kacprowski 
Reviewed-by: Stanislaw Gruszka 
Signed-off-by: Stanislaw Gruszka 
---
 drivers/accel/ivpu/ivpu_fw.c  | 17 -
 drivers/accel/ivpu/ivpu_hw.h  |  2 ++
 drivers/accel/ivpu/ivpu_hw_37xx.c |  8 
 drivers/accel/ivpu/ivpu_hw_37xx_reg.h |  2 ++
 4 files changed, 28 insertions(+), 1 deletion(-)

diff --git a/drivers/accel/ivpu/ivpu_fw.c b/drivers/accel/ivpu/ivpu_fw.c
index a4149fc8a1d7..51d976ba5276 100644
--- a/drivers/accel/ivpu/ivpu_fw.c
+++ b/drivers/accel/ivpu/ivpu_fw.c
@@ -426,14 +426,27 @@ static void ivpu_fw_boot_params_print(struct ivpu_device 
*vdev, struct vpu_boot_
 boot_params->vpu_telemetry_enable);
ivpu_dbg(vdev, FW_BOOT, "boot_params.dvfs_mode = %u\n",
 boot_params->dvfs_mode);
+   ivpu_dbg(vdev, FW_BOOT, "boot_params.d0i3_residency_time_us = %lld\n",
+boot_params->d0i3_residency_time_us);
+   ivpu_dbg(vdev, FW_BOOT, "boot_params.d0i3_entry_vpu_ts = %llu\n",
+boot_params->d0i3_entry_vpu_ts);
 }
 
 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 we only have to reset the entrypoint addr */
+   /* In case of warm boot only update variable params */
if (!ivpu_fw_is_cold_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;
+
+   ivpu_dbg(vdev, FW_BOOT, "boot_params.d0i3_residency_time_us = 
%lld\n",
+boot_params->d0i3_residency_time_us);
+   ivpu_dbg(vdev, FW_BOOT, "boot_params.d0i3_entry_vpu_ts = 
%llu\n",
+boot_params->d0i3_entry_vpu_ts);
+
boot_params->save_restore_ret_address = 0;
vdev->pm->is_warmboot = true;
wmb(); /* Flush WC buffers after writing 
save_restore_ret_address */
@@ -498,6 +511,8 @@ void ivpu_fw_boot_params_setup(struct ivpu_device *vdev, 
struct vpu_boot_params
boot_params->punit_telemetry_sram_size = 
ivpu_hw_reg_telemetry_size_get(vdev);
boot_params->vpu_telemetry_enable = 
ivpu_hw_reg_telemetry_enable_get(vdev);
boot_params->dvfs_mode = vdev->fw->dvfs_mode;
+   boot_params->d0i3_residency_time_us = 0;
+   boot_params->d0i3_entry_vpu_ts = 0;
 
wmb(); /* Flush WC buffers after writing bootparams */
 
diff --git a/drivers/accel/ivpu/ivpu_hw.h b/drivers/accel/ivpu/ivpu_hw.h
index 1079e06255ba..bb4368168247 100644
--- a/drivers/accel/ivpu/ivpu_hw.h
+++ b/drivers/accel/ivpu/ivpu_hw.h
@@ -58,6 +58,8 @@ struct ivpu_hw_info {
u32 sku;
u16 config;
int dma_bits;
+   ktime_t d0i3_entry_host_ts;
+   u64 d0i3_entry_vpu_ts;
 };
 
 extern const struct ivpu_hw_ops ivpu_hw_37xx_ops;
diff --git a/drivers/accel/ivpu/ivpu_hw_37xx.c 
b/drivers/accel/ivpu/ivpu_hw_37xx.c
index 0da4e6117d6b..06d7db28448a 100644
--- a/drivers/accel/ivpu/ivpu_hw_37xx.c
+++ b/drivers/accel/ivpu/ivpu_hw_37xx.c
@@ -731,10 +731,18 @@ static bool ivpu_hw_37xx_is_idle(struct ivpu_device *vdev)
   REG_TEST_FLD(VPU_37XX_BUTTRESS_VPU_STATUS, IDLE, val);
 }
 
+static void ivpu_hw_37xx_save_d0i3_entry_timestamp(struct ivpu_device *vdev)
+{
+   vdev->hw->d0i3_entry_host_ts = ktime_get_boottime();
+   vdev->hw->d0i3_entry_vpu_ts = 
REGV_RD64(VPU_37XX_CPU_SS_TIM_PERF_FREE_CNT);
+}
+
 static int ivpu_hw_37xx_power_down(struct ivpu_device *vdev)
 {
int ret = 0;
 
+   ivpu_hw_37xx_save_d0i3_entry_timestamp(vdev);
+
if (!ivpu_hw_37xx_is_idle(vdev) && ivpu_hw_37xx_ip_reset(vdev))
ivpu_err(vdev, "Failed to reset the VPU\n");
 
diff --git a/drivers/accel/ivpu/ivpu_hw_37xx_reg.h 
b/drivers/accel/ivpu/ivpu_hw_37xx_reg.h
index 4083beb5e9db..f6fec1919202 100644
--- a/drivers/accel/ivpu/ivpu_hw_37xx_reg.h
+++ b/drivers/accel/ivpu/ivpu_hw_37xx_reg.h
@@ -240,6 +240,8 @@
 #define VPU_37XX_CPU_SS_TIM_GEN_CONFIG 
0x06021008u
 #define VPU_37XX_CPU_SS_TIM_GEN_CONFIG_WDOG_TO_INT_CLR_MASK
BIT_MASK(9)
 
+#define VPU_37XX_CPU_SS_TIM_PERF_FREE_CNT  
0x06029000u
+
 #define VPU_37XX_CPU_SS_DOORBELL_0 
0x0630u
 #define VPU_37XX_CPU_SS_DOORBELL_0_SET_MASK
BIT_MASK(0)
 
-- 
2.25.1