From 815ffdf422e67521e19c5f998b975b25cacf4b66 Mon Sep 17 00:00:00 2001 From: George Shen Date: Fri, 31 Mar 2023 14:51:48 -0700 Subject: [PATCH] msm: eva: Fix NoC Hang When accessing NoC Acquire xo_reset before accessing CVP NoC. There is a chance the NoC clock, XO clock is disabled during XO reset. Acquiring xo_reset will block the XO clock reset. Change-Id: I51ab201beafbd1a4b998ee33a9d23c1efa3e2a14 Signed-off-by: George Shen --- msm/eva/cvp.c | 1 - msm/eva/cvp_hfi.c | 195 ++++++++++++++++++------------------ msm/eva/cvp_hfi_io.h | 10 ++ msm/eva/msm_cvp_common.c | 40 +------- msm/eva/msm_cvp_internal.h | 1 - msm/eva/msm_cvp_res_parse.c | 2 - msm/eva/msm_cvp_resources.h | 1 - 7 files changed, 109 insertions(+), 141 deletions(-) diff --git a/msm/eva/cvp.c b/msm/eva/cvp.c index aef273fb8e..b21c8fed4f 100644 --- a/msm/eva/cvp.c +++ b/msm/eva/cvp.c @@ -146,7 +146,6 @@ static int msm_cvp_initialize_core(struct platform_device *pdev, init_completion(&core->completions[i]); } - INIT_DELAYED_WORK(&core->fw_unload_work, msm_cvp_fw_unload_handler); INIT_WORK(&core->ssr_work, msm_cvp_ssr_handler); init_cycle_info(&core->dyn_clk); core->ssr_count = 0; diff --git a/msm/eva/cvp_hfi.c b/msm/eva/cvp_hfi.c index 39aabf4f02..aa54362383 100644 --- a/msm/eva/cvp_hfi.c +++ b/msm/eva/cvp_hfi.c @@ -100,6 +100,7 @@ static void power_off_iris2(struct iris_hfi_device *device); static int __set_ubwc_config(struct iris_hfi_device *device); static void __noc_error_info_iris2(struct iris_hfi_device *device); static int __enable_hw_power_collapse(struct iris_hfi_device *device); +static int __disable_hw_power_collapse(struct iris_hfi_device *device); static int __power_off_controller(struct iris_hfi_device *device); static int __hwfence_regs_map(struct iris_hfi_device *device); @@ -386,6 +387,25 @@ err_reg_handoff_failed: return rc; } +static int __take_back_regulators(struct iris_hfi_device *device) +{ + struct regulator_info *rinfo; + int rc = 0; + + iris_hfi_for_each_regulator(device, rinfo) { + rc = __acquire_regulator(rinfo, device); + /* + * if one regulator hand off failed, driver should take + * the control for other regulators back. + */ + if (rc) + return rc; + } + + return rc; +} + + static int __write_queue(struct cvp_iface_q_info *qinfo, u8 *packet, bool *rx_req_is_set) { @@ -772,38 +792,6 @@ static int __read_register(struct iris_hfi_device *device, u32 reg) return rc; } -static bool __noc_access_ok(struct iris_hfi_device *device) -{ - int ret; - - ret = __read_register(device, CVP_CC_MVS1C_CBCR); - if (ret & 0x80000000) { - dprintk(CVP_ERR, "%s MVS1C off\n", __func__); - return false; - } - ret = __read_register(device, CVP_CC_MVS1_CBCR); - if (ret & 0x80000000) { - dprintk(CVP_ERR, "%s MVS1 off\n", __func__); - return false; - } - ret = __read_register(device, CVP_CC_AHB_CBCR); - if (ret & 0x80000000) { - dprintk(CVP_ERR, "%s AHB off\n", __func__); - return false; - } - ret = __read_register(device, CVP_CC_XO_CBCR); - if (ret & 0x80000000) { - dprintk(CVP_ERR, "%s XO off\n", __func__); - return false; - } - ret = __read_register(device, CVP_CC_SLEEP_CBCR); - if (ret & 0x80000000) { - dprintk(CVP_ERR, "%s SLEEP off\n", __func__); - return false; - } - return true; -} - static int __set_registers(struct iris_hfi_device *device) { struct msm_cvp_core *core; @@ -829,8 +817,11 @@ static int __set_registers(struct iris_hfi_device *device) reg_set->reg_tbl[i].value); } - if (!__noc_access_ok(device)) + i = call_iris_op(device, reset_control_acquire_name, device, "cvp_xo_reset"); + if (i) { + dprintk(CVP_WARN, "%s Fail acquire xo_reset\n", __func__); return -EINVAL; + } __write_register(device, CVP_CPU_CS_AXI4_QOS, pdata->noc_qos->axi_qos); @@ -854,6 +845,22 @@ static int __set_registers(struct iris_hfi_device *device) pdata->noc_qos->dangerlut_low); __write_register(device, CVP_NOC_CDM_SAFELUT_LOW, pdata->noc_qos->safelut_low); + + /* Below registers write moved from FW to SW to enable UBWC */ + __write_register(device, CVP_NOC_RGE_NIU_DECCTL_LOW, + 0x1); + __write_register(device, CVP_NOC_RGE_NIU_ENCCTL_LOW, + 0x1); + __write_register(device, CVP_NOC_GCE_VADL_TOF_NIU_DECCTL_LOW, + 0x1); + __write_register(device, CVP_NOC_GCE_VADL_TOF_NIU_ENCCTL_LOW, + 0x1); + __write_register(device, CVP_NOC_CORE_ERR_MAINCTL_LOW_OFFS, + 0x3); + __write_register(device, CVP_NOC_MAIN_SIDEBANDMANAGER_FAULTINEN0_LOW, + 0x1); + + call_iris_op(device, reset_control_release_name, device, "cvp_xo_reset"); return 0; } @@ -2269,6 +2276,9 @@ static int iris_hfi_core_release(void *dev) __resume(device); __set_state(device, IRIS_STATE_DEINIT); + rc = __tzbsp_set_cvp_state(TZ_SUBSYS_STATE_SUSPEND); + if (rc) + dprintk(CVP_WARN, "Failed to suspend cvp FW%d\n", rc); __dsp_shutdown(device); @@ -3896,6 +3906,23 @@ disable_regulator_failed: return rc; } +static int __disable_hw_power_collapse(struct iris_hfi_device *device) +{ + int rc = 0; + + if (!msm_cvp_fw_low_power_mode) { + dprintk(CVP_PWR, "Not enabling hardware power collapse\n"); + return 0; + } + + rc = __take_back_regulators(device); + if (rc) + dprintk(CVP_WARN, + "%s : Failed to disable HW power collapse %d\n", + __func__, rc); + return rc; +} + static int __enable_hw_power_collapse(struct iris_hfi_device *device) { int rc = 0; @@ -4317,6 +4344,7 @@ static int __iris_power_on(struct iris_hfi_device *device) /* * Re-program all of the registers that get reset as a result of * regulator_disable() and _enable() + * calling below function requires CORE powered on */ rc = __set_registers(device); if (rc) @@ -4379,6 +4407,7 @@ static void __print_sidebandmanager_regs(struct iris_hfi_device *device) u32 sbm_ln0_low, axi_cbcr; u32 main_sbm_ln0_low = 0xdeadbeef, main_sbm_ln0_high = 0xdeadbeef; u32 main_sbm_ln1_high = 0xdeadbeef, cpu_cs_x2rpmh; + int rc; sbm_ln0_low = __read_register(device, CVP_NOC_SBM_SENSELN0_LOW); @@ -4403,12 +4432,18 @@ static void __print_sidebandmanager_regs(struct iris_hfi_device *device) goto exit; } + rc = call_iris_op(device, reset_control_acquire_name, device, "cvp_xo_reset"); + if (rc) { + dprintk(CVP_WARN, "%s Fail acquire xo_reset\n", __func__); + goto exit; + } main_sbm_ln0_low = __read_register(device, CVP_NOC_MAIN_SIDEBANDMANAGER_SENSELN0_LOW); main_sbm_ln0_high = __read_register(device, CVP_NOC_MAIN_SIDEBANDMANAGER_SENSELN0_HIGH); main_sbm_ln1_high = __read_register(device, CVP_NOC_MAIN_SIDEBANDMANAGER_SENSELN1_HIGH); + call_iris_op(device, reset_control_release_name, device, "cvp_xo_reset"); exit: cpu_cs_x2rpmh = cpu_cs_x2rpmh & (~CVP_CPU_CS_X2RPMh_SWOVERRIDE_BMSK); @@ -4431,33 +4466,6 @@ static int __power_off_controller(struct iris_hfi_device *device) __write_register(device, CVP_CPU_CS_X2RPMh, 0x3); /* HPG 6.2.2 Step 2, noc to low power */ -#ifndef CONFIG_EVA_PINEAPPLE - __write_register(device, CVP_AON_WRAPPER_CVP_NOC_LPI_CONTROL, 0x1); - while (!reg_status && count < max_count) { - lpi_status = - __read_register(device, - CVP_AON_WRAPPER_CVP_NOC_LPI_STATUS); - reg_status = lpi_status & BIT(0); - /* Wait for Core noc lpi status to be set */ - usleep_range(50, 100); - count++; - } - dprintk(CVP_PWR, - "Core Noc: lpi_status %x noc_status %x (count %d)\n", - lpi_status, reg_status, count); - if (count == max_count) { - u32 pc_ready, wfi_status; - - wfi_status = __read_register(device, CVP_WRAPPER_CPU_STATUS); - pc_ready = __read_register(device, CVP_CTRL_STATUS); - - dprintk(CVP_WARN, - "Core NOC not in qaccept status %x %x %x %x\n", - reg_status, lpi_status, wfi_status, pc_ready); - - __print_sidebandmanager_regs(device); - } -#endif /* New addition to put CPU/Tensilica to low power */ reg_status = 0; @@ -4623,6 +4631,15 @@ static int __power_off_core(struct iris_hfi_device *device) msm_cvp_disable_unprepare_clk(device, "core_clk"); msm_cvp_disable_unprepare_clk(device, "video_cc_mvs1_clk_src"); return 0; + } else if (!(value & 0x2)) { + /* + * HW_CONTROL PC disabled, then core is powered on for + * CVP NoC access + */ + __disable_regulator(device, "cvp-core"); + msm_cvp_disable_unprepare_clk(device, "core_clk"); + msm_cvp_disable_unprepare_clk(device, "video_cc_mvs1_clk_src"); + return 0; } dprintk(CVP_PWR, "Driver controls Core power off now\n"); @@ -4656,41 +4673,6 @@ static int __power_off_core(struct iris_hfi_device *device) warn_flag = 1; } -#ifndef CONFIG_EVA_PINEAPPLE - /* Apply partial reset on MSF interface and wait for ACK */ - __write_register(device, CVP_NOC_RESET_REQ, 0x7); - count = 0; - do { - value = __read_register(device, CVP_NOC_RESET_ACK); - if ((value & 0x7) == 0x7) - break; - else - usleep_range(100, 200); - count++; - } while (count < max_count); - - if (count == max_count) { - dprintk(CVP_WARN, "Core NoC reset assert failed %x\n", value); - warn_flag = 1; - } - - /* De-assert partial reset on MSF interface and wait for ACK */ - __write_register(device, CVP_NOC_RESET_REQ, 0x0); - count = 0; - do { - value = __read_register(device, CVP_NOC_RESET_ACK); - if ((value & 0x1) == 0x0) - break; - else - usleep_range(100, 200); - count++; - } while (count < max_count); - - if (count == max_count) { - dprintk(CVP_WARN, "Core NoC reset de-assert failed\n"); - warn_flag = 1; - } -#else count = 0; max_count = 1000; __write_register(device, CVP_AON_WRAPPER_CVP_NOC_LPI_CONTROL, 0x1); @@ -4720,7 +4702,6 @@ static int __power_off_core(struct iris_hfi_device *device) } __write_register(device, CVP_AON_WRAPPER_CVP_NOC_LPI_CONTROL, 0x0); -#endif if (warn_flag) __print_sidebandmanager_regs(device); @@ -4732,6 +4713,8 @@ static int __power_off_core(struct iris_hfi_device *device) __write_register(device, CVP_WRAPPER_CORE_CLOCK_CONFIG, config); + __disable_hw_power_collapse(device); + usleep_range(100, 200); __disable_regulator(device, "cvp-core"); msm_cvp_disable_unprepare_clk(device, "core_clk"); msm_cvp_disable_unprepare_clk(device, "video_cc_mvs1_clk_src"); @@ -4982,8 +4965,9 @@ static void __noc_error_info_iris2(struct iris_hfi_device *device) { struct msm_cvp_core *core; struct cvp_noc_log *noc_log; - u32 val = 0, regi, i; + u32 val = 0, regi, regii, regiii, i; bool log_required = false; + int rc; core = list_first_entry(&cvp_driver->cores, struct msm_cvp_core, list); @@ -4998,6 +4982,15 @@ static void __noc_error_info_iris2(struct iris_hfi_device *device) } noc_log->used = 1; + __disable_hw_power_collapse(device); + + val = __read_register(device, CVP_CC_MVS1_GDSCR); + regi = __read_register(device, CVP_AON_WRAPPER_CVP_NOC_CORE_CLK_CONTROL); + regii = __read_register(device, CVP_CC_MVS1_CBCR); + regiii = __read_register(device, CVP_WRAPPER_CORE_CLOCK_CONFIG); + dprintk(CVP_ERR, "noc reg check: %#x %#x %#x %#x\n", + val, regi, regii, regiii); + val = __read_register(device, CVP_NOC_ERR_SWID_LOW_OFFS); __err_log(log_required, &noc_log->err_ctrl_swid_low, "CVP_NOC_ERL_MAIN_SWID_LOW", val); @@ -5038,6 +5031,12 @@ static void __noc_error_info_iris2(struct iris_hfi_device *device) __err_log(log_required, &noc_log->err_ctrl_errlog3_high, "CVP_NOC_ERL_MAIN_ERRLOG3_HIGH", val); + rc = call_iris_op(device, reset_control_acquire_name, device, "cvp_xo_reset"); + if (rc) { + dprintk(CVP_WARN, "%s Fail acquire xo_reset\n", __func__); + return; + } + val = __read_register(device, CVP_NOC_CORE_ERR_SWID_LOW_OFFS); __err_log(log_required, &noc_log->err_core_swid_low, "CVP_NOC__CORE_ERL_MAIN_SWID_LOW", val); @@ -5078,6 +5077,8 @@ static void __noc_error_info_iris2(struct iris_hfi_device *device) val = __read_register(device, CVP_NOC_CORE_ERR_ERRLOG3_HIGH_OFFS); __err_log(log_required, &noc_log->err_core_errlog3_high, "CVP_NOC_CORE_ERL_MAIN_ERRLOG3_HIGH", val); + __write_register(device, CVP_NOC_CORE_ERR_ERRCLR_LOW_OFFS, 0x1); + call_iris_op(device, reset_control_release_name, device, "cvp_xo_reset"); #define CVP_SS_CLK_HALT 0x8 #define CVP_SS_CLK_EN 0xC #define CVP_SS_ARP_TEST_BUS_CONTROL 0x700 diff --git a/msm/eva/cvp_hfi_io.h b/msm/eva/cvp_hfi_io.h index bbd3b605c7..0f9bd0223b 100644 --- a/msm/eva/cvp_hfi_io.h +++ b/msm/eva/cvp_hfi_io.h @@ -195,6 +195,16 @@ #define CVP_NOC_SBM_SENSELN0_LOW (CVP_NOC_BASE_OFFS + 0x300) #define CVP_NOC_CORE_BASE_OFFS 0x00010000 +#define CVP_NOC_RGE_NIU_DECCTL_LOW \ + (CVP_NOC_CORE_BASE_OFFS + 0x3108) +#define CVP_NOC_RGE_NIU_ENCCTL_LOW \ + (CVP_NOC_CORE_BASE_OFFS + 0x3188) +#define CVP_NOC_GCE_VADL_TOF_NIU_DECCTL_LOW \ + (CVP_NOC_CORE_BASE_OFFS + 0x3508) +#define CVP_NOC_GCE_VADL_TOF_NIU_ENCCTL_LOW \ + (CVP_NOC_CORE_BASE_OFFS + 0x3588) +#define CVP_NOC_MAIN_SIDEBANDMANAGER_FAULTINEN0_LOW \ + (CVP_NOC_CORE_BASE_OFFS + 0x7040) #define CVP_NOC_MAIN_SIDEBANDMANAGER_SENSELN0_LOW \ (CVP_NOC_CORE_BASE_OFFS + 0x7100) #define CVP_NOC_MAIN_SIDEBANDMANAGER_SENSELN0_HIGH \ diff --git a/msm/eva/msm_cvp_common.c b/msm/eva/msm_cvp_common.c index a3438d89c1..d98431ed57 100644 --- a/msm/eva/msm_cvp_common.c +++ b/msm/eva/msm_cvp_common.c @@ -632,8 +632,6 @@ static void handle_sys_error(enum hal_command_response cmd, void *data) if (hfi_device->error == CVP_ERR_NOC_ERROR) { dprintk(CVP_WARN, "Got NOC error"); msm_cvp_noc_error_info(core); - hfi_device->error = 0xdead; - MSM_CVP_ERROR(true); } call_hfi_op(hdev, flush_debug_queue, hdev->hfi_device_data); list_for_each_entry(inst, &core->instances, list) { @@ -653,6 +651,7 @@ static void handle_sys_error(enum hal_command_response cmd, void *data) if (!core->trigger_ssr) { cvp_print_inst(CVP_WARN, inst); + if (hfi_device->error != CVP_ERR_NOC_ERROR) msm_cvp_print_inst_bufs(inst, false); } } @@ -1446,43 +1445,6 @@ int msm_cvp_comm_kill_session(struct msm_cvp_inst *inst) return rc; } -void msm_cvp_fw_unload_handler(struct work_struct *work) -{ - struct msm_cvp_core *core = NULL; - struct cvp_hfi_device *hdev = NULL; - int rc = 0; - - core = container_of(work, struct msm_cvp_core, fw_unload_work.work); - if (!core || !core->device) { - dprintk(CVP_ERR, "%s - invalid work or core handle\n", - __func__); - return; - } - - hdev = core->device; - - mutex_lock(&core->lock); - if (list_empty(&core->instances) && - core->state != CVP_CORE_UNINIT) { - if (core->state > CVP_CORE_INIT) { - dprintk(CVP_CORE, "Calling cvp_hal_core_release\n"); - rc = call_hfi_op(hdev, core_release, - hdev->hfi_device_data); - if (rc) { - dprintk(CVP_ERR, - "Failed to release core, id = %d\n", - core->id); - mutex_unlock(&core->lock); - return; - } - } - core->state = CVP_CORE_UNINIT; - kfree(core->capabilities); - core->capabilities = NULL; - } - mutex_unlock(&core->lock); -} - static int set_internal_buf_on_fw(struct msm_cvp_inst *inst, struct msm_cvp_smem *handle) { diff --git a/msm/eva/msm_cvp_internal.h b/msm/eva/msm_cvp_internal.h index a599e1d4ce..0bb6b56130 100644 --- a/msm/eva/msm_cvp_internal.h +++ b/msm/eva/msm_cvp_internal.h @@ -412,7 +412,6 @@ int msm_cvp_trigger_ssr(struct msm_cvp_core *core, int msm_cvp_noc_error_info(struct msm_cvp_core *core); void msm_cvp_comm_handle_thermal_event(void); -void msm_cvp_fw_unload_handler(struct work_struct *work); void msm_cvp_ssr_handler(struct work_struct *work); /* * XXX: normally should be in msm_cvp_core.h, but that's meant for public APIs, diff --git a/msm/eva/msm_cvp_res_parse.c b/msm/eva/msm_cvp_res_parse.c index 054eb25cff..aac7c27c94 100644 --- a/msm/eva/msm_cvp_res_parse.c +++ b/msm/eva/msm_cvp_res_parse.c @@ -860,8 +860,6 @@ int cvp_read_platform_resources_from_drv_data( "qcom,enable-thermal-mitigation"); res->msm_cvp_pwr_collapse_delay = find_key_value(platform_data, "qcom,power-collapse-delay"); - res->msm_cvp_firmware_unload_delay = find_key_value(platform_data, - "qcom,fw-unload-delay"); res->msm_cvp_hw_rsp_timeout = find_key_value(platform_data, "qcom,hw-resp-timeout"); res->msm_cvp_dsp_rsp_timeout = find_key_value(platform_data, diff --git a/msm/eva/msm_cvp_resources.h b/msm/eva/msm_cvp_resources.h index c6fe037ea8..5f9ccb10ef 100644 --- a/msm/eva/msm_cvp_resources.h +++ b/msm/eva/msm_cvp_resources.h @@ -206,7 +206,6 @@ struct msm_cvp_platform_resources { uint32_t max_secure_inst_count; int msm_cvp_hw_rsp_timeout; int msm_cvp_dsp_rsp_timeout; - int msm_cvp_firmware_unload_delay; uint32_t msm_cvp_pwr_collapse_delay; bool non_fatal_pagefaults; bool fatal_ssr;