瀏覽代碼

video-driver: Made changes in error recovery sequence

- Add ARES for Core clock.
- After controller power down, re-initiate controller/core power
  on sequence and wait for QACCEPT and then power down the video
  subsystem.

Change-Id: Icec985f33dc6e05adf71bfa40901120ceffea655
Signed-off-by: Manikanta Kanamarlapudi <[email protected]>
Manikanta Kanamarlapudi 1 年之前
父節點
當前提交
f7b9dd6807

+ 5 - 1
driver/platform/pineapple/src/msm_vidc_pineapple.c

@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
  * Copyright (c) 2020-2022, The Linux Foundation. All rights reserved.
- * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
  */
 
 #include <dt-bindings/clock/qcom,gcc-pineapple.h>
@@ -2716,6 +2716,7 @@ static const struct clk_rst_table pineapple_clk_reset_table[] = {
 	{ "video_axi_reset",        0  },
 	{ "video_xo_reset",         1  },
 	{ "video_mvs0c_reset",      0  },
+	{ "video_mvs0_reset",       0  },
 };
 
 /* name, llcc_id */
@@ -2881,6 +2882,9 @@ static const u32 pineapple_vdec_output_properties_av1[] = {
 
 static const u32 pineapple_msm_vidc_ssr_type[] = {
 	HFI_SSR_TYPE_SW_ERR_FATAL,
+	HFI_SSR_TYPE_SW_DIV_BY_ZERO,
+	HFI_SSR_TYPE_CPU_WDOG_IRQ,
+	HFI_SSR_TYPE_NOC_ERROR,
 };
 
 static const struct msm_vidc_platform_data pineapple_data = {

+ 218 - 19
driver/variant/iris33/src/msm_vidc_iris33.c

@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
  * Copyright (c) 2020-2022, The Linux Foundation. All rights reserved.
- * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
  */
 
 #include <linux/reset.h>
@@ -134,6 +134,10 @@ typedef enum {
 #define NOC_ERL_ERRORLOGGER_MAIN_ERRORLOGGER_ERRLOG3_LOW_IRIS33   (NOC_BASE_OFFS + 0xA038)
 #define NOC_ERL_ERRORLOGGER_MAIN_ERRORLOGGER_ERRLOG3_HIGH_IRIS33  (NOC_BASE_OFFS + 0xA03C)
 #define NOC_SIDEBANDMANAGER_MAIN_SIDEBANDMANAGER_FAULTINEN0_LOW_IRIS33 (NOC_BASE_OFFS + 0x7040)
+#define VCODEC_NOC_SidebandManager_main_SidebandManager_SenseIn0_Low  (NOC_BASE_OFFS + 0x7100)
+#define VCODEC_NOC_SIDEBANDMANAGER_MAIN_SIDEBANDMANAGER_SENSEIN0_HIGH (NOC_BASE_OFFS + 0x7104)
+#define VCODEC_NOC_SIDEBANDMANAGER_MAIN_SIDEBANDMANAGER_SENSEIN1_HIGH (NOC_BASE_OFFS + 0x710C)
+#define VCODEC_NOC_SIDEBANDMANAGER_MAIN_SIDEBANDMANAGER_SENSEIN2_LOW  (NOC_BASE_OFFS + 0x7110)
 
 #define NOC_ERL_ERRORLOGGER_MAIN_ERRORLOGGER_MAINCTL_LOW_IRIS33_2P   (NOC_BASE_OFFS + 0x3508)
 #define NOC_ERL_ERRORLOGGER_MAIN_ERRORLOGGER_ERRCLR_LOW_IRIS33_2P    (NOC_BASE_OFFS + 0x3518)
@@ -147,6 +151,8 @@ typedef enum {
 #define NOC_ERL_ERRORLOGGER_MAIN_ERRORLOGGER_ERRLOG3_HIGH_IRIS33_2P  (NOC_BASE_OFFS + 0x353C)
 #define NOC_SIDEBANDMANAGER_MAIN_SIDEBANDMANAGER_FAULTINEN0_LOW_IRIS33_2P (NOC_BASE_OFFS + 0x3240)
 
+#define VCODEC_DMA_SPARE_3 0x87B8
+
 static int __interrupt_init_iris33(struct msm_vidc_core *core)
 {
 	u32 mask_val = 0;
@@ -282,8 +288,9 @@ static bool is_iris33_hw_power_collapsed(struct msm_vidc_core *core)
 static int __power_off_iris33_hardware(struct msm_vidc_core *core)
 {
 	int rc = 0, i;
-	u32 value = 0;
+	u32 value = 0, count = 0;
 	bool pwr_collapsed = false;
+	u32 sense0_low, sense0_high, sense1_high, sense2_low;
 
 	/*
 	 * Incase hw power control is enabled, for any error case
@@ -304,6 +311,10 @@ static int __power_off_iris33_hardware(struct msm_vidc_core *core)
 		}
 	}
 
+	rc = call_res_op(core, gdsc_sw_ctrl, core);
+	if (rc)
+		return rc;
+
 	/*
 	 * check to make sure core clock branch enabled else
 	 * we cannot read vcodec top idle register
@@ -320,6 +331,10 @@ static int __power_off_iris33_hardware(struct msm_vidc_core *core)
 			return rc;
 	}
 
+	rc = __write_register_masked(core, VCODEC_DMA_SPARE_3, 0x1, BIT(0));
+	if (rc)
+		return rc;
+
 	/*
 	 * add MNoC idle check before collapsing MVS0 per HPG update
 	 * poll for NoC DMA idle -> HPG 6.1.1
@@ -338,15 +353,69 @@ static int __power_off_iris33_hardware(struct msm_vidc_core *core)
 	if (rc)
 		return rc;
 
-	rc = __read_register_with_poll_timeout(core, AON_WRAPPER_MVP_NOC_LPI_STATUS,
-					0x1, 0x1, 200, 2000);
-	if (rc)
-		d_vpr_e("%s: AON_WRAPPER_MVP_NOC_LPI_CONTROL failed\n", __func__);
+	rc = __read_register(core, AON_WRAPPER_MVP_NOC_LPI_STATUS, &value);
+		if (rc)
+			return rc;
 
-	rc = __write_register_masked(core, AON_WRAPPER_MVP_NOC_LPI_CONTROL,
-					0x0, BIT(0));
-	if (rc)
-		return rc;
+	while ((!(value & BIT(0))) && (value & BIT(1) || value & BIT(2))) {
+		rc = __write_register_masked(core, AON_WRAPPER_MVP_NOC_LPI_CONTROL,
+					     0x0, BIT(0));
+		if (rc)
+			return rc;
+
+		usleep_range(10, 20);
+
+		rc = __write_register_masked(core, AON_WRAPPER_MVP_NOC_LPI_CONTROL,
+					     0x1, BIT(0));
+		if (rc)
+			return rc;
+
+		usleep_range(10, 20);
+
+		rc = __read_register(core, AON_WRAPPER_MVP_NOC_LPI_STATUS, &value);
+		if (rc)
+			return rc;
+
+		++count;
+		if (count >= 1000) {
+			d_vpr_e("%s: AON_WRAPPER_MVP_NOC_LPI_CONTROL failed\n", __func__);
+			break;
+		}
+	}
+
+	if (count < 1000) {
+		rc = __write_register_masked(core, AON_WRAPPER_MVP_NOC_LPI_CONTROL,
+					     0x0, BIT(0));
+		if (rc)
+			return rc;
+	}
+
+	i = 0;
+	do {
+		value = 0;
+
+		__read_register(core,
+				VCODEC_NOC_SidebandManager_main_SidebandManager_SenseIn0_Low,
+				&sense0_low);
+		__read_register(core,
+				VCODEC_NOC_SIDEBANDMANAGER_MAIN_SIDEBANDMANAGER_SENSEIN0_HIGH,
+				&sense0_high);
+		__read_register(core,
+				VCODEC_NOC_SIDEBANDMANAGER_MAIN_SIDEBANDMANAGER_SENSEIN1_HIGH,
+				&sense1_high);
+		__read_register(core,
+				VCODEC_NOC_SIDEBANDMANAGER_MAIN_SIDEBANDMANAGER_SENSEIN2_LOW,
+				&sense2_low);
+
+		value = ((sense0_low & 0x00008000) ||
+			 (sense0_high & 0x00000800) ||
+			 (sense1_high & 0x00800000) ||
+			 (sense2_low & 0x00002000));
+		usleep_range(10, 20);
+		i++;
+	} while ((value) && (i <= 100));
+
+	d_vpr_h("%s: sideband register value = %d\n", __func__, value);
 
 	/*
 	 * Reset both sides of 2 ahb2ahb_bridges (TZ and non-TZ)
@@ -370,19 +439,13 @@ disable_power:
 		rc = 0;
 	}
 
-	rc = call_res_op(core, clk_disable, core, "video_cc_mvs0_clk");
-	if (rc) {
-		d_vpr_e("%s: disable unprepare video_cc_mvs0_clk failed\n", __func__);
-		rc = 0;
-	}
-
 	return rc;
 }
 
 static int __power_off_iris33_controller(struct msm_vidc_core *core)
 {
-	int rc = 0;
-	int value = 0;
+	int noc_lpi_status = 0, count = 0;
+	int rc = 0, value = 0;
 
 	/*
 	 * mask fal10_veto QLPAC error since fal10_veto can go 1
@@ -434,6 +497,11 @@ static int __power_off_iris33_controller(struct msm_vidc_core *core)
 	rc = call_res_op(core, reset_control_assert, core, "video_axi_reset");
 	if (rc)
 		d_vpr_e("%s: assert video_axi_reset failed\n", __func__);
+
+	rc = call_res_op(core, reset_control_assert, core, "video_mvs0_reset");
+	if (rc)
+		d_vpr_e("%s: assert video_mvs0_reset failed\n", __func__);
+
 	/* set retain mem and peripheral before asset mvs0c reset */
 	rc = call_res_op(core, clk_set_flag, core,
 		"video_cc_mvs0c_clk", MSM_VIDC_CLKFLAG_RETAIN_MEM);
@@ -447,6 +515,9 @@ static int __power_off_iris33_controller(struct msm_vidc_core *core)
 	if (rc)
 		d_vpr_e("%s: assert video_mvs0c_reset failed\n", __func__);
 	usleep_range(400, 500);
+	rc = call_res_op(core, reset_control_deassert, core, "video_mvs0_reset");
+	if (rc)
+		d_vpr_e("%s: de-assert video_mvs0_reset failed\n", __func__);
 	rc = call_res_op(core, reset_control_deassert, core, "video_axi_reset");
 	if (rc)
 		d_vpr_e("%s: de-assert video_axi_reset failed\n", __func__);
@@ -523,6 +594,12 @@ skip_video_xo_reset:
 	if (rc)
 		return rc;
 
+	rc = call_res_op(core, clk_disable, core, "video_cc_mvs0_clk");
+	if (rc) {
+		d_vpr_e("%s: disable unprepare video_cc_mvs0_clk failed\n", __func__);
+		rc = 0;
+	}
+
 	/* remove retain mem and retain peripheral */
 	rc = call_res_op(core, clk_set_flag, core,
 		"video_cc_mvs0c_clk", MSM_VIDC_CLKFLAG_NORETAIN_PERIPH);
@@ -541,6 +618,129 @@ skip_video_xo_reset:
 		rc = 0;
 	}
 
+	if (!is_core_state(core, MSM_VIDC_CORE_ERROR))
+		goto power_down;
+
+	/* power cycle process to recover from NoC error */
+	rc = call_res_op(core, gdsc_off, core, "iris-ctl");
+	if (rc) {
+		d_vpr_e("%s: disable regulator iris-ctl failed\n", __func__);
+		rc = 0;
+	}
+
+	call_res_op(core, gdsc_on, core, "iris-ctl");
+	rc = call_res_op(core, clk_enable, core, "video_cc_mvs0c_clk");
+
+	/* assert and deassert axi and mvs0c resets */
+	rc = call_res_op(core, reset_control_assert, core, "video_axi_reset");
+	if (rc)
+		d_vpr_e("%s: assert video_axi_reset failed\n", __func__);
+
+	/* set retain mem and peripheral before asset mvs0c reset */
+	rc = call_res_op(core, clk_set_flag, core,
+			 "video_cc_mvs0c_clk", MSM_VIDC_CLKFLAG_RETAIN_MEM);
+	if (rc)
+		d_vpr_e("%s: set retain mem failed\n", __func__);
+	rc = call_res_op(core, clk_set_flag, core,
+			 "video_cc_mvs0c_clk", MSM_VIDC_CLKFLAG_RETAIN_PERIPH);
+	if (rc)
+		d_vpr_e("%s: set retain peripheral failed\n", __func__);
+	rc = call_res_op(core, reset_control_assert, core, "video_mvs0c_reset");
+	if (rc)
+		d_vpr_e("%s: assert video_mvs0c_reset failed\n", __func__);
+	usleep_range(400, 500);
+
+	rc = call_res_op(core, reset_control_deassert, core, "video_axi_reset");
+	if (rc)
+		d_vpr_e("%s: de-assert video_axi_reset failed\n", __func__);
+	rc = call_res_op(core, reset_control_deassert, core, "video_mvs0c_reset");
+	if (rc)
+		d_vpr_e("%s: de-assert video_mvs0c_reset failed\n", __func__);
+
+	rc = call_res_op(core, gdsc_on, core, "vcodec");
+	if (rc)
+		return rc;
+
+	rc = call_res_op(core, clk_enable, core, "video_cc_mvs0_clk");
+	if (rc)
+		return rc;
+
+	rc = __write_register_masked(core, AON_WRAPPER_MVP_NOC_LPI_CONTROL,
+				     0x1, BIT(0));
+	if (rc)
+		return rc;
+
+	usleep_range(10, 20);
+
+	rc = __read_register(core, AON_WRAPPER_MVP_NOC_LPI_STATUS, &noc_lpi_status);
+	if (rc)
+		return rc;
+
+	while ((!(noc_lpi_status & BIT(0))) &&
+	       (noc_lpi_status & BIT(1) || noc_lpi_status & BIT(2))) {
+		rc = __write_register_masked(core, AON_WRAPPER_MVP_NOC_LPI_CONTROL,
+					     0x0, BIT(0));
+		if (rc)
+			return rc;
+
+		usleep_range(10, 20);
+
+		rc = __write_register_masked(core, AON_WRAPPER_MVP_NOC_LPI_CONTROL,
+					     0x1, BIT(0));
+		if (rc)
+			return rc;
+
+		usleep_range(10, 20);
+
+		rc = __read_register(core, AON_WRAPPER_MVP_NOC_LPI_STATUS, &noc_lpi_status);
+		if (rc)
+			return rc;
+
+		++count;
+		if (count >= 1000) {
+			d_vpr_e("%s: AON_WRAPPER_MVP_NOC_LPI_CONTROL failed\n", __func__);
+			break;
+		}
+	}
+
+	if (count < 1000) {
+		rc = __write_register_masked(core, AON_WRAPPER_MVP_NOC_LPI_CONTROL,
+					     0x0, BIT(0));
+		if (rc)
+			return rc;
+	}
+
+	rc = call_res_op(core, clk_disable, core, "video_cc_mvs0_clk");
+	if (rc) {
+		d_vpr_e("%s: disable unprepare video_cc_mvs0_clk failed\n", __func__);
+		rc = 0;
+	}
+
+	rc = call_res_op(core, gdsc_off, core, "vcodec");
+	if (rc) {
+		d_vpr_e("%s: disable regulator vcodec failed\n", __func__);
+		rc = 0;
+	}
+
+	/* remove retain mem and retain peripheral */
+	rc = call_res_op(core, clk_set_flag, core,
+			 "video_cc_mvs0c_clk", MSM_VIDC_CLKFLAG_NORETAIN_PERIPH);
+	if (rc)
+		d_vpr_e("%s: set noretain peripheral failed\n", __func__);
+
+	rc = call_res_op(core, clk_set_flag, core,
+			 "video_cc_mvs0c_clk", MSM_VIDC_CLKFLAG_NORETAIN_MEM);
+	if (rc)
+		d_vpr_e("%s: set noretain mem failed\n", __func__);
+
+	/* Turn off MVP MVS0C core clock */
+	rc = call_res_op(core, clk_disable, core, "video_cc_mvs0c_clk");
+	if (rc) {
+		d_vpr_e("%s: disable unprepare video_cc_mvs0c_clk failed\n", __func__);
+		rc = 0;
+	}
+
+power_down:
 	/* power down process */
 	rc = call_res_op(core, gdsc_off, core, "iris-ctl");
 	if (rc) {
@@ -1067,7 +1267,6 @@ static int __noc_error_info_iris33(struct msm_vidc_core *core)
 
 fail_deassert_xo_reset:
 fail_assert_xo_reset:
-	MSM_VIDC_FATAL(true);
 	return rc;
 }
 

+ 5 - 2
driver/vidc/src/venus_hfi_response.c

@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
  * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
- * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
  */
 
 #include <linux/of_address.h>
@@ -402,7 +402,10 @@ int handle_system_error(struct msm_vidc_core *core,
 		}
 	}
 
-	msm_vidc_core_deinit(core, true);
+	core_lock(core, __func__);
+	msm_vidc_change_core_state(core, MSM_VIDC_CORE_ERROR, __func__);
+	msm_vidc_core_deinit_locked(core, true);
+	core_unlock(core, __func__);
 
 	return 0;
 }