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 <quic_sqiao@quicinc.com>
这个提交包含在:
George Shen
2023-03-31 14:51:48 -07:00
父节点 cde58caa65
当前提交 815ffdf422
修改 7 个文件,包含 109 行新增141 行删除

查看文件

@@ -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;

查看文件

@@ -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

查看文件

@@ -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 \

查看文件

@@ -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)
{

查看文件

@@ -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,

查看文件

@@ -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,

查看文件

@@ -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;