diff --git a/drivers/cam_cpas/cam_cpas_hw.c b/drivers/cam_cpas/cam_cpas_hw.c index 8fd153169d89..e45145090bd9 100644 --- a/drivers/cam_cpas/cam_cpas_hw.c +++ b/drivers/cam_cpas/cam_cpas_hw.c @@ -81,7 +81,7 @@ end: static int cam_cpas_util_vote_bus_client_bw( struct cam_cpas_bus_client *bus_client, uint64_t ab, uint64_t ib, - bool camnoc_bw) + bool camnoc_bw, uint64_t *applied_ab, uint64_t *applied_ib) { int rc = 0; uint64_t min_camnoc_ib_bw = CAM_CPAS_AXI_MIN_CAMNOC_IB_BW; @@ -124,6 +124,11 @@ static int cam_cpas_util_vote_bus_client_bw( goto unlock_client; } + if (applied_ab) + *applied_ab = ab; + if (applied_ib) + *applied_ib = ib; + unlock_client: mutex_unlock(&bus_client->lock); end: @@ -242,6 +247,7 @@ static int cam_cpas_util_vote_default_ahb_axi(struct cam_hw_info *cpas_hw, int rc, i = 0; struct cam_cpas *cpas_core = (struct cam_cpas *)cpas_hw->core_info; uint64_t ab_bw, ib_bw; + uint64_t applied_ab_bw = 0, applied_ib_bw = 0; rc = cam_cpas_util_vote_bus_client_level(&cpas_core->ahb_bus_client, (enable == true) ? CAM_SVS_VOTE : CAM_SUSPEND_VOTE); @@ -262,13 +268,15 @@ static int cam_cpas_util_vote_default_ahb_axi(struct cam_hw_info *cpas_hw, for (i = 0; i < cpas_core->num_axi_ports; i++) { rc = cam_cpas_util_vote_bus_client_bw( &cpas_core->axi_port[i].bus_client, - ab_bw, ib_bw, false); + ab_bw, ib_bw, false, &applied_ab_bw, &applied_ib_bw); if (rc) { CAM_ERR(CAM_CPAS, "Failed in mnoc vote, enable=%d, rc=%d", enable, rc); goto remove_ahb_vote; } + cpas_core->axi_port[i].applied_ab_bw = applied_ab_bw; + cpas_core->axi_port[i].applied_ib_bw = applied_ib_bw; } return 0; @@ -434,6 +442,8 @@ static int cam_cpas_util_set_camnoc_axi_clk_rate( CAM_ERR(CAM_CPAS, "Failed in setting camnoc axi clk %llu %d %d", required_camnoc_bw, clk_rate, rc); + + cpas_core->applied_camnoc_axi_rate = clk_rate; } } @@ -615,6 +625,7 @@ static int cam_cpas_camnoc_set_vote_axi_clk_rate( int rc = 0; struct cam_cpas_axi_port *camnoc_axi_port = NULL; uint64_t camnoc_bw; + uint64_t applied_ab = 0, applied_ib = 0; if (soc_private->control_camnoc_axi_clk) { rc = cam_cpas_util_set_camnoc_axi_clk_rate(cpas_hw); @@ -655,7 +666,7 @@ static int cam_cpas_camnoc_set_vote_axi_clk_rate( rc = cam_cpas_util_vote_bus_client_bw( &camnoc_axi_port->bus_client, - 0, camnoc_bw, true); + 0, camnoc_bw, true, &applied_ab, &applied_ib); CAM_DBG(CAM_CPAS, "camnoc vote camnoc_bw[%llu] rc=%d %s", @@ -666,6 +677,8 @@ static int cam_cpas_camnoc_set_vote_axi_clk_rate( camnoc_bw, rc); break; } + camnoc_axi_port->applied_ab_bw = applied_ab; + camnoc_axi_port->applied_ib_bw = applied_ib; } return rc; } @@ -688,6 +701,7 @@ static int cam_cpas_util_apply_client_axi_vote( curr_camnoc_old = 0, curr_mnoc_ab_old = 0, curr_mnoc_ib_old = 0, par_camnoc_old = 0, par_mnoc_ab_old = 0, par_mnoc_ib_old = 0; int rc = 0, i = 0; + uint64_t applied_ab = 0, applied_ib = 0; mutex_lock(&cpas_core->tree_lock); if (!cpas_client->tree_node_valid) { @@ -863,13 +877,16 @@ vote_start_clients: rc = cam_cpas_util_vote_bus_client_bw( &mnoc_axi_port->bus_client, - mnoc_ab_bw, mnoc_ib_bw, false); + mnoc_ab_bw, mnoc_ib_bw, false, &applied_ab, + &applied_ib); if (rc) { CAM_ERR(CAM_CPAS, "Failed in mnoc vote ab[%llu] ib[%llu] rc=%d", mnoc_ab_bw, mnoc_ib_bw, rc); goto unlock_tree; } + mnoc_axi_port->applied_ab_bw = applied_ab; + mnoc_axi_port->applied_ib_bw = applied_ib; } rc = cam_cpas_camnoc_set_vote_axi_clk_rate( cpas_hw, camnoc_axi_port_updated); @@ -1616,6 +1633,46 @@ static int cam_cpas_hw_get_hw_info(void *hw_priv, return 0; } +static int cam_cpas_log_vote(struct cam_hw_info *cpas_hw) +{ + struct cam_cpas *cpas_core = (struct cam_cpas *) cpas_hw->core_info; + struct cam_cpas_private_soc *soc_private = + (struct cam_cpas_private_soc *) cpas_hw->soc_info.soc_private; + int rc = 0; + uint32_t i; + + for (i = 0; i < cpas_core->num_axi_ports; i++) { + CAM_INFO(CAM_CPAS, + "[%s] ab_bw[%lld] ib_bw[%lld] additional_bw[%lld] applied_ab[%lld] applied_ib[%lld]", + cpas_core->axi_port[i].axi_port_name, + cpas_core->axi_port[i].ab_bw, + cpas_core->axi_port[i].ib_bw, + cpas_core->axi_port[i].additional_bw, + cpas_core->axi_port[i].applied_ab_bw, + cpas_core->axi_port[i].applied_ib_bw); + } + + if (soc_private->control_camnoc_axi_clk) { + CAM_INFO(CAM_CPAS, "applied camnoc axi clk[%lld]", + cpas_core->applied_camnoc_axi_rate); + } else { + for (i = 0; i < cpas_core->num_camnoc_axi_ports; i++) { + CAM_INFO(CAM_CPAS, + "[%s] ab_bw[%lld] ib_bw[%lld] additional_bw[%lld] applied_ab[%lld] applied_ib[%lld]", + cpas_core->camnoc_axi_port[i].axi_port_name, + cpas_core->camnoc_axi_port[i].ab_bw, + cpas_core->camnoc_axi_port[i].ib_bw, + cpas_core->camnoc_axi_port[i].additional_bw, + cpas_core->camnoc_axi_port[i].applied_ab_bw, + cpas_core->camnoc_axi_port[i].applied_ib_bw); + } + } + + CAM_INFO(CAM_CPAS, "ahb client curr vote level[%d]", + cpas_core->ahb_bus_client.curr_vote_level); + + return rc; +} static int cam_cpas_hw_process_cmd(void *hw_priv, uint32_t cmd_type, void *cmd_args, uint32_t arg_size) @@ -1719,6 +1776,10 @@ static int cam_cpas_hw_process_cmd(void *hw_priv, cmd_axi_vote->client_handle, cmd_axi_vote->axi_vote); break; } + case CAM_CPAS_HW_CMD_LOG_VOTE: { + rc = cam_cpas_log_vote(hw_priv); + break; + } default: CAM_ERR(CAM_CPAS, "CPAS HW command not valid =%d", cmd_type); break; diff --git a/drivers/cam_cpas/cam_cpas_hw.h b/drivers/cam_cpas/cam_cpas_hw.h index ac692d9ff559..ca44666dd40f 100644 --- a/drivers/cam_cpas/cam_cpas_hw.h +++ b/drivers/cam_cpas/cam_cpas_hw.h @@ -144,6 +144,8 @@ struct cam_cpas_bus_client { * @ib_bw: IB bw value for this port * @camnoc_bw: CAMNOC bw value for this port * @additional_bw: Additional bandwidth to cover non-hw cpas clients + * @applied_ab_bw: applied ab bw for this port + * @applied_ib_bw: applied ib bw for this port */ struct cam_cpas_axi_port { const char *axi_port_name; @@ -154,6 +156,8 @@ struct cam_cpas_axi_port { uint64_t ib_bw; uint64_t camnoc_bw; uint64_t additional_bw; + uint64_t applied_ab_bw; + uint64_t applied_ib_bw; }; /** @@ -178,6 +182,7 @@ struct cam_cpas_axi_port { * @irq_count_wq: wait variable to ensure all irq's are handled * @dentry: debugfs file entry * @ahb_bus_scaling_disable: ahb scaling based on src clk corner for bus + * @applied_camnoc_axi_rate: applied camnoc axi clock rate */ struct cam_cpas { struct cam_cpas_hw_caps hw_caps; @@ -199,6 +204,7 @@ struct cam_cpas { wait_queue_head_t irq_count_wq; struct dentry *dentry; bool ahb_bus_scaling_disable; + uint64_t applied_camnoc_axi_rate; }; int cam_camsstop_get_internal_ops(struct cam_cpas_internal_ops *internal_ops); diff --git a/drivers/cam_cpas/cam_cpas_hw_intf.h b/drivers/cam_cpas/cam_cpas_hw_intf.h index 1c3c146e24e7..3e6ac167f478 100644 --- a/drivers/cam_cpas/cam_cpas_hw_intf.h +++ b/drivers/cam_cpas/cam_cpas_hw_intf.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #ifndef _CAM_CPAS_HW_INTF_H_ @@ -38,6 +38,7 @@ enum cam_cpas_hw_cmd_process { CAM_CPAS_HW_CMD_REG_READ, CAM_CPAS_HW_CMD_AHB_VOTE, CAM_CPAS_HW_CMD_AXI_VOTE, + CAM_CPAS_HW_CMD_LOG_VOTE, CAM_CPAS_HW_CMD_INVALID, }; diff --git a/drivers/cam_cpas/cam_cpas_intf.c b/drivers/cam_cpas/cam_cpas_intf.c index f96da1779c2a..cc72cbf985b1 100644 --- a/drivers/cam_cpas/cam_cpas_intf.c +++ b/drivers/cam_cpas/cam_cpas_intf.c @@ -405,6 +405,30 @@ int cam_cpas_start(uint32_t client_handle, } EXPORT_SYMBOL(cam_cpas_start); +void cam_cpas_log_votes(void) +{ + uint32_t dummy_args; + int rc; + + if (!CAM_CPAS_INTF_INITIALIZED()) { + CAM_ERR(CAM_CPAS, "cpas intf not initialized"); + return; + } + + if (g_cpas_intf->hw_intf->hw_ops.process_cmd) { + rc = g_cpas_intf->hw_intf->hw_ops.process_cmd( + g_cpas_intf->hw_intf->hw_priv, + CAM_CPAS_HW_CMD_LOG_VOTE, &dummy_args, + sizeof(dummy_args)); + if (rc) + CAM_ERR(CAM_CPAS, "Failed in process_cmd, rc=%d", rc); + } else { + CAM_ERR(CAM_CPAS, "Invalid process_cmd ops"); + } + +} +EXPORT_SYMBOL(cam_cpas_log_votes); + int cam_cpas_unregister_client(uint32_t client_handle) { int rc; diff --git a/drivers/cam_cpas/include/cam_cpas_api.h b/drivers/cam_cpas/include/cam_cpas_api.h index 8423bc511d31..c13ac20e7b7b 100644 --- a/drivers/cam_cpas/include/cam_cpas_api.h +++ b/drivers/cam_cpas/include/cam_cpas_api.h @@ -622,5 +622,15 @@ const char *cam_cpas_axi_util_path_type_to_string( const char *cam_cpas_axi_util_trans_type_to_string( uint32_t path_data_type); +/** + * cam_cpas_log_votes() + * + * @brief: API to print the all bw votes of axi client. It also print the + * applied camnoc axi clock vote value and ahb vote value + * + * @return 0 on success. + * + */ +void cam_cpas_log_votes(void); #endif /* _CAM_CPAS_API_H_ */ diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index d1cf9fd3eb50..045097aa2a7e 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -7118,14 +7118,86 @@ static int cam_ife_hw_mgr_find_affected_ctx( return 0; } +static int cam_ife_hw_mgr_handle_hw_dump_info( + void *ctx, + void *evt_info) +{ + struct cam_ife_hw_mgr_ctx *ife_hw_mgr_ctx = + (struct cam_ife_hw_mgr_ctx *)ctx; + struct cam_isp_hw_event_info *event_info = + (struct cam_isp_hw_event_info *)evt_info; + struct cam_isp_hw_mgr_res *hw_mgr_res = NULL; + struct cam_isp_resource_node *rsrc_node = NULL; + struct cam_hw_intf *hw_intf; + uint32_t i, out_port_id; + int rc = 0; + + list_for_each_entry(hw_mgr_res, + &ife_hw_mgr_ctx->res_list_ife_src, list) { + for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) { + if (!hw_mgr_res->hw_res[i]) + continue; + + rsrc_node = hw_mgr_res->hw_res[i]; + if (rsrc_node->res_id == + CAM_ISP_HW_VFE_IN_CAMIF) { + hw_intf = rsrc_node->hw_intf; + if (hw_intf && + hw_intf->hw_ops.process_cmd) + rc = + hw_intf->hw_ops.process_cmd( + hw_intf->hw_priv, + CAM_ISP_HW_CMD_CAMIF_DATA, + rsrc_node, + sizeof( + struct + cam_isp_resource_node)); + } + } + } + + + out_port_id = event_info->res_id & 0xFF; + hw_mgr_res = + &ife_hw_mgr_ctx->res_list_ife_out[out_port_id]; + for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) { + if (!hw_mgr_res->hw_res[i]) + continue; + hw_intf = hw_mgr_res->hw_res[i]->hw_intf; + if (hw_intf->hw_ops.process_cmd) { + rc = hw_intf->hw_ops.process_cmd( + hw_intf->hw_priv, + CAM_ISP_HW_CMD_DUMP_BUS_INFO, + (void *)event_info, + sizeof(struct cam_isp_hw_event_info)); + } + } + + return rc; +} + static int cam_ife_hw_mgr_handle_hw_err( + void *ctx, void *evt_info) { - struct cam_isp_hw_event_info *event_info = evt_info; - uint32_t core_idx; - struct cam_isp_hw_error_event_data error_event_data = {0}; + struct cam_ife_hw_mgr_ctx *ife_hw_mgr_ctx; + struct cam_isp_hw_event_info *event_info = evt_info; + uint32_t core_idx; + struct cam_isp_hw_error_event_data error_event_data = {0}; struct cam_ife_hw_event_recovery_data recovery_data = {0}; - int rc = -EINVAL; + int rc = -EINVAL; + + if (ctx) { + ife_hw_mgr_ctx = + (struct cam_ife_hw_mgr_ctx *)ctx; + if (event_info->res_type == + CAM_ISP_RESOURCE_VFE_IN && + !ife_hw_mgr_ctx->is_rdi_only_context && + event_info->res_id != + CAM_ISP_HW_VFE_IN_CAMIF) + cam_ife_hw_mgr_handle_hw_dump_info( + ife_hw_mgr_ctx, event_info); + } if (event_info->err_type == CAM_VFE_IRQ_STATUS_VIOLATION) error_event_data.error_type = CAM_ISP_HW_ERROR_VIOLATION; @@ -7431,7 +7503,7 @@ static int cam_ife_hw_mgr_event_handler( break; case CAM_ISP_HW_EVENT_ERROR: - rc = cam_ife_hw_mgr_handle_hw_err(evt_info); + rc = cam_ife_hw_mgr_handle_hw_err(priv, evt_info); break; default: diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h index b48416c35587..25697c9d64f3 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h @@ -101,8 +101,10 @@ enum cam_isp_hw_cmd_type { CAM_ISP_HW_CMD_STOP_BUS_ERR_IRQ, CAM_ISP_HW_CMD_GET_REG_DUMP, CAM_ISP_HW_CMD_UBWC_UPDATE, + CAM_ISP_HW_CMD_DUMP_BUS_INFO, CAM_ISP_HW_CMD_SOF_IRQ_DEBUG, CAM_ISP_HW_CMD_SET_CAMIF_DEBUG, + CAM_ISP_HW_CMD_CAMIF_DATA, CAM_ISP_HW_CMD_CSID_CLOCK_UPDATE, CAM_ISP_HW_CMD_FE_UPDATE_IN_RD, CAM_ISP_HW_CMD_FE_UPDATE_BUS_RD, diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c index 7b991a316824..bd1a84e86042 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c @@ -598,6 +598,7 @@ int cam_vfe_process_cmd(void *hw_priv, uint32_t cmd_type, case CAM_ISP_HW_CMD_DUMP_HW: case CAM_ISP_HW_CMD_ADD_WAIT: case CAM_ISP_HW_CMD_ADD_WAIT_TRIGGER: + case CAM_ISP_HW_CMD_CAMIF_DATA: rc = core_info->vfe_top->hw_ops.process_cmd( core_info->vfe_top->top_priv, cmd_type, cmd_args, arg_size); @@ -611,6 +612,7 @@ int cam_vfe_process_cmd(void *hw_priv, uint32_t cmd_type, case CAM_ISP_HW_CMD_WM_CONFIG_UPDATE: case CAM_ISP_HW_CMD_GET_SECURE_MODE: case CAM_ISP_HW_CMD_UNMASK_BUS_WR_IRQ: + case CAM_ISP_HW_CMD_DUMP_BUS_INFO: rc = core_info->vfe_bus->hw_ops.process_cmd( core_info->vfe_bus->bus_priv, cmd_type, cmd_args, arg_size); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.h index 64d9de084ec1..eef02079628a 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #ifndef _CAM_VFE_SOC_H_ @@ -24,6 +24,7 @@ * @cpas_version: Has cpas version read from Hardware * @ubwc_static_ctrl: UBWC static control configuration * @is_ife_lite: Flag to indicate full vs lite IFE + * @ife_clk_src: IFE source clock */ struct cam_vfe_soc_private { uint32_t cpas_handle; @@ -33,6 +34,7 @@ struct cam_vfe_soc_private { int32_t dsp_clk_rate; uint32_t ubwc_static_ctrl[UBWC_STATIC_CONFIG_MAX]; bool is_ife_lite; + uint64_t ife_clk_src; }; /* diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe170.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe170.h index a16c9d510f40..d0f85565a968 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe170.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe170.h @@ -170,6 +170,14 @@ struct cam_vfe_top_dump_data vfe170_dump_data = { }, }; +static struct cam_vfe_rdi_overflow_status vfe170_rdi_irq_status = { + .rdi0_overflow_mask = 0x8, + .rdi1_overflow_mask = 0x10, + .rdi2_overflow_mask = 0x18, + .rdi3_overflow_mask = 0x20, + .rdi_overflow_mask = 0x3c, +}; + static struct cam_vfe_top_ver2_hw_info vfe170_top_hw_info = { .common_reg = &vfe170_top_common_reg, .camif_hw_info = { @@ -183,8 +191,9 @@ static struct cam_vfe_top_ver2_hw_info vfe170_top_hw_info = { .reg_data = NULL, }, .rdi_hw_info = { - .common_reg = &vfe170_top_common_reg, - .rdi_reg = &vfe170_rdi_reg, + .common_reg = &vfe170_top_common_reg, + .rdi_reg = &vfe170_rdi_reg, + .rdi_irq_status = &vfe170_rdi_irq_status, .reg_data = { &vfe_170_rdi_0_data, &vfe_170_rdi_1_data, diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175_130.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175_130.h index a1df85c12388..ce0739d386cd 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175_130.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175_130.h @@ -27,6 +27,14 @@ static struct cam_irq_register_set vfe175_130_top_irq_reg_set[2] = { }, }; +static struct cam_vfe_rdi_overflow_status vfe175_130_rdi_irq_status = { + .rdi0_overflow_mask = 0x8, + .rdi1_overflow_mask = 0x10, + .rdi2_overflow_mask = 0x18, + .rdi3_overflow_mask = 0x20, + .rdi_overflow_mask = 0x3c, +}; + static struct cam_irq_controller_reg_info vfe175_130_top_irq_reg_info = { .num_registers = 2, .irq_reg_set = vfe175_130_top_irq_reg_set, @@ -268,6 +276,7 @@ static struct cam_vfe_top_ver2_hw_info vfe175_130_top_hw_info = { .common_reg = &vfe175_130_top_common_reg, .rdi_reg = &vfe175_130_rdi_reg, .common_reg_data = &vfe175_130_rdi_reg_data, + .rdi_irq_status = &vfe175_130_rdi_irq_status, .reg_data = { &vfe_175_130_rdi_0_data, &vfe_175_130_rdi_1_data, diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c index ae705f265af1..1771ed7d529b 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c @@ -140,6 +140,8 @@ struct cam_vfe_bus_ver2_wm_resource_data { uint32_t ubwc_lossy_threshold_0; uint32_t ubwc_lossy_threshold_1; uint32_t ubwc_bandwidth_limit; + uint32_t acquired_width; + uint32_t acquired_height; }; struct cam_vfe_bus_ver2_comp_grp_data { @@ -984,6 +986,8 @@ static int cam_vfe_bus_acquire_wm( rsrc_data->width = out_port_info->width; rsrc_data->height = out_port_info->height; + rsrc_data->acquired_width = out_port_info->width; + rsrc_data->acquired_height = out_port_info->height; rsrc_data->is_dual = is_dual; /* Set WM offset value to default */ rsrc_data->offset = 0; @@ -3536,6 +3540,42 @@ static int __cam_vfe_bus_process_cmd(void *priv, return cam_vfe_bus_process_cmd(priv, cmd_type, cmd_args, arg_size); } +int cam_vfe_bus_dump_wm_data(void *priv, void *cmd_args, uint32_t arg_size) +{ + struct cam_vfe_bus_ver2_priv *bus_priv = + (struct cam_vfe_bus_ver2_priv *) priv; + struct cam_isp_hw_event_info *event_info = + (struct cam_isp_hw_event_info *)cmd_args; + struct cam_isp_resource_node *rsrc_node = NULL; + struct cam_vfe_bus_ver2_vfe_out_data *rsrc_data = NULL; + struct cam_vfe_bus_ver2_wm_resource_data *wm_data = NULL; + int i, wm_idx; + enum cam_vfe_bus_ver2_vfe_out_type vfe_out_res_id; + + vfe_out_res_id = cam_vfe_bus_get_out_res_id(event_info->res_id); + rsrc_node = &bus_priv->vfe_out[vfe_out_res_id]; + rsrc_data = rsrc_node->res_priv; + for (i = 0; i < rsrc_data->num_wm; i++) { + wm_idx = cam_vfe_bus_get_wm_idx(vfe_out_res_id, i); + if (wm_idx < 0 || wm_idx >= bus_priv->num_client) { + CAM_ERR(CAM_ISP, "Unsupported VFE out %d", + vfe_out_res_id); + return -EINVAL; + } + wm_data = bus_priv->bus_client[wm_idx].res_priv; + CAM_INFO(CAM_ISP, + "VFE:%d WM:%d width:%u height:%u stride:%u x_init:%u en_cfg:%u acquired width:%u height:%u", + wm_data->common_data->core_index, wm_idx, + wm_data->width, + wm_data->height, + wm_data->stride, wm_data->h_init, + wm_data->en_cfg, + wm_data->acquired_width, + wm_data->acquired_height); + } + return 0; +} + static int cam_vfe_bus_process_cmd( struct cam_isp_resource_node *priv, uint32_t cmd_type, void *cmd_args, uint32_t arg_size) @@ -3575,6 +3615,9 @@ static int cam_vfe_bus_process_cmd( case CAM_ISP_HW_CMD_UBWC_UPDATE: rc = cam_vfe_bus_update_ubwc_config(cmd_args); break; + case CAM_ISP_HW_CMD_DUMP_BUS_INFO: + rc = cam_vfe_bus_dump_wm_data(priv, cmd_args, arg_size); + break; case CAM_ISP_HW_CMD_UBWC_UPDATE_V2: rc = cam_vfe_bus_update_ubwc_config_v2(cmd_args); break; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c index 67c59bc0e205..425a041ba912 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c @@ -128,6 +128,8 @@ struct cam_vfe_bus_ver3_wm_resource_data { uint32_t ubwc_lossy_threshold_1; uint32_t ubwc_offset_lossy_variance; uint32_t ubwc_bandwidth_limit; + uint32_t acquired_width; + uint32_t acquired_height; }; struct cam_vfe_bus_ver3_comp_grp_data { @@ -1079,6 +1081,8 @@ static int cam_vfe_bus_ver3_acquire_wm( rsrc_data->width = out_port_info->width; rsrc_data->height = out_port_info->height; + rsrc_data->acquired_width = out_port_info->width; + rsrc_data->acquired_height = out_port_info->height; rsrc_data->is_dual = is_dual; /* Set WM offset value to default */ rsrc_data->offset = 0; @@ -2383,34 +2387,37 @@ static int cam_vfe_bus_ver3_deinit_vfe_out_resource( return 0; } -static void cam_vfe_bus_ver3_print_dimensions( +static int cam_vfe_bus_ver3_print_dimensions( enum cam_vfe_bus_ver3_vfe_out_type vfe_out_res_id, - enum cam_vfe_bus_plane_type plane, struct cam_vfe_bus_ver3_priv *bus_priv) { - struct cam_isp_resource_node *wm_res = NULL; - struct cam_vfe_bus_ver3_wm_resource_data *wm_data = NULL; - int wm_idx = 0; + struct cam_isp_resource_node *rsrc_node = NULL; + struct cam_vfe_bus_ver3_vfe_out_data *rsrc_data = NULL; + struct cam_vfe_bus_ver3_wm_resource_data *wm_data = NULL; + int i, wm_idx; - wm_idx = cam_vfe_bus_ver3_get_wm_idx(vfe_out_res_id, plane, - bus_priv->common_data.is_lite); - - if (wm_idx < 0 || wm_idx >= bus_priv->num_client || plane > PLANE_C) { - CAM_ERR(CAM_ISP, - "Unsupported VFE out_type:0x%X plane:%d wm_idx:%d max_idx:%d", - vfe_out_res_id, plane, wm_idx, - bus_priv->num_client - 1); - return; + rsrc_node = &bus_priv->vfe_out[vfe_out_res_id]; + rsrc_data = rsrc_node->res_priv; + for (i = 0; i < rsrc_data->num_wm; i++) { + wm_idx = cam_vfe_bus_ver3_get_wm_idx(vfe_out_res_id, i, + bus_priv->common_data.is_lite); + if (wm_idx < 0 || wm_idx >= bus_priv->num_client) { + CAM_ERR(CAM_ISP, "Unsupported VFE out %d", + vfe_out_res_id); + return -EINVAL; + } + wm_data = bus_priv->bus_client[wm_idx].res_priv; + CAM_INFO(CAM_ISP, + "VFE:%d WM:%d width:%u height:%u stride:%u x_init:%u en_cfg:%u acquired width:%u height:%u", + wm_data->common_data->core_index, wm_idx, + wm_data->width, + wm_data->height, + wm_data->stride, wm_data->h_init, + wm_data->en_cfg, + wm_data->acquired_width, + wm_data->acquired_height); } - - wm_res = &bus_priv->bus_client[wm_idx]; - wm_data = wm_res->res_priv; - - CAM_INFO(CAM_ISP, - "VFE:%d WM:%d width:%u height:%u stride:%u x_init:%u en_cfg:%u", - wm_data->common_data->core_index, wm_idx, wm_data->width, - wm_data->height, wm_data->stride, wm_data->h_init, - wm_data->en_cfg); + return 0; } static int cam_vfe_bus_ver3_handle_bus_irq(uint32_t evt_id, @@ -2516,7 +2523,6 @@ static int cam_vfe_bus_ver3_err_irq_bottom_half( "RDI 0 image size violation"); cam_vfe_bus_ver3_print_dimensions( CAM_VFE_BUS_VER3_VFE_OUT_RDI0, - PLANE_Y, bus_priv); } @@ -2525,7 +2531,6 @@ static int cam_vfe_bus_ver3_err_irq_bottom_half( "RDI 1 image size violation"); cam_vfe_bus_ver3_print_dimensions( CAM_VFE_BUS_VER3_VFE_OUT_RDI1, - PLANE_Y, bus_priv); } @@ -2534,7 +2539,6 @@ static int cam_vfe_bus_ver3_err_irq_bottom_half( "RDI 2 image size violation"); cam_vfe_bus_ver3_print_dimensions( CAM_VFE_BUS_VER3_VFE_OUT_RDI2, - PLANE_Y, bus_priv); } @@ -2543,7 +2547,6 @@ static int cam_vfe_bus_ver3_err_irq_bottom_half( "RDI 3 image size violation"); cam_vfe_bus_ver3_print_dimensions( CAM_VFE_BUS_VER3_VFE_OUT_RDI3, - PLANE_Y, bus_priv); } } @@ -2578,7 +2581,6 @@ static int cam_vfe_bus_ver3_err_irq_bottom_half( CAM_INFO(CAM_ISP, "VID Y 1:1 image size violation"); cam_vfe_bus_ver3_print_dimensions( CAM_VFE_BUS_VER3_VFE_OUT_FULL, - PLANE_Y, bus_priv); } @@ -2586,7 +2588,6 @@ static int cam_vfe_bus_ver3_err_irq_bottom_half( CAM_INFO(CAM_ISP, "VID C 1:1 image size violation"); cam_vfe_bus_ver3_print_dimensions( CAM_VFE_BUS_VER3_VFE_OUT_FULL, - PLANE_C, bus_priv); } @@ -2594,7 +2595,6 @@ static int cam_vfe_bus_ver3_err_irq_bottom_half( CAM_INFO(CAM_ISP, "VID YC 4:1 image size violation"); cam_vfe_bus_ver3_print_dimensions( CAM_VFE_BUS_VER3_VFE_OUT_DS4, - PLANE_Y, bus_priv); } @@ -2602,7 +2602,6 @@ static int cam_vfe_bus_ver3_err_irq_bottom_half( CAM_INFO(CAM_ISP, "VID YC 16:1 image size violation"); cam_vfe_bus_ver3_print_dimensions( CAM_VFE_BUS_VER3_VFE_OUT_DS16, - PLANE_Y, bus_priv); } @@ -2610,7 +2609,6 @@ static int cam_vfe_bus_ver3_err_irq_bottom_half( CAM_INFO(CAM_ISP, "DISP Y 1:1 image size violation"); cam_vfe_bus_ver3_print_dimensions( CAM_VFE_BUS_VER3_VFE_OUT_FULL_DISP, - PLANE_Y, bus_priv); } @@ -2618,7 +2616,6 @@ static int cam_vfe_bus_ver3_err_irq_bottom_half( CAM_INFO(CAM_ISP, "DISP C 1:1 image size violation"); cam_vfe_bus_ver3_print_dimensions( CAM_VFE_BUS_VER3_VFE_OUT_FULL_DISP, - PLANE_C, bus_priv); } @@ -2626,7 +2623,6 @@ static int cam_vfe_bus_ver3_err_irq_bottom_half( CAM_INFO(CAM_ISP, "DISP YC 4:1 image size violation"); cam_vfe_bus_ver3_print_dimensions( CAM_VFE_BUS_VER3_VFE_OUT_DS4_DISP, - PLANE_Y, bus_priv); } @@ -2634,7 +2630,6 @@ static int cam_vfe_bus_ver3_err_irq_bottom_half( CAM_INFO(CAM_ISP, "DISP YC 16:1 image size violation"); cam_vfe_bus_ver3_print_dimensions( CAM_VFE_BUS_VER3_VFE_OUT_DS16_DISP, - PLANE_Y, bus_priv); } @@ -2642,7 +2637,6 @@ static int cam_vfe_bus_ver3_err_irq_bottom_half( CAM_INFO(CAM_ISP, "FD Y image size violation"); cam_vfe_bus_ver3_print_dimensions( CAM_VFE_BUS_VER3_VFE_OUT_FD, - PLANE_Y, bus_priv); } @@ -2650,7 +2644,6 @@ static int cam_vfe_bus_ver3_err_irq_bottom_half( CAM_INFO(CAM_ISP, "FD C image size violation"); cam_vfe_bus_ver3_print_dimensions( CAM_VFE_BUS_VER3_VFE_OUT_FD, - PLANE_C, bus_priv); } @@ -2659,7 +2652,6 @@ static int cam_vfe_bus_ver3_err_irq_bottom_half( "PIXEL RAW DUMP image size violation"); cam_vfe_bus_ver3_print_dimensions( CAM_VFE_BUS_VER3_VFE_OUT_RAW_DUMP, - PLANE_Y, bus_priv); } @@ -2667,7 +2659,6 @@ static int cam_vfe_bus_ver3_err_irq_bottom_half( CAM_INFO(CAM_ISP, "STATS HDR BE image size violation"); cam_vfe_bus_ver3_print_dimensions( CAM_VFE_BUS_VER3_VFE_OUT_STATS_HDR_BE, - PLANE_Y, bus_priv); } @@ -2676,7 +2667,6 @@ static int cam_vfe_bus_ver3_err_irq_bottom_half( "STATS HDR BHIST image size violation"); cam_vfe_bus_ver3_print_dimensions( CAM_VFE_BUS_VER3_VFE_OUT_STATS_HDR_BHIST, - PLANE_Y, bus_priv); } @@ -2685,7 +2675,6 @@ static int cam_vfe_bus_ver3_err_irq_bottom_half( "STATS TINTLESS BG image size violation"); cam_vfe_bus_ver3_print_dimensions( CAM_VFE_BUS_VER3_VFE_OUT_STATS_TL_BG, - PLANE_Y, bus_priv); } @@ -2693,7 +2682,6 @@ static int cam_vfe_bus_ver3_err_irq_bottom_half( CAM_INFO(CAM_ISP, "STATS AWB BG image size violation"); cam_vfe_bus_ver3_print_dimensions( CAM_VFE_BUS_VER3_VFE_OUT_STATS_AWB_BG, - PLANE_Y, bus_priv); } @@ -2701,7 +2689,6 @@ static int cam_vfe_bus_ver3_err_irq_bottom_half( CAM_INFO(CAM_ISP, "STATS BHIST image size violation"); cam_vfe_bus_ver3_print_dimensions( CAM_VFE_BUS_VER3_VFE_OUT_STATS_BHIST, - PLANE_Y, bus_priv); } @@ -2709,7 +2696,6 @@ static int cam_vfe_bus_ver3_err_irq_bottom_half( CAM_INFO(CAM_ISP, "STATS RS image size violation"); cam_vfe_bus_ver3_print_dimensions( CAM_VFE_BUS_VER3_VFE_OUT_STATS_RS, - PLANE_Y, bus_priv); } @@ -2717,7 +2703,6 @@ static int cam_vfe_bus_ver3_err_irq_bottom_half( CAM_INFO(CAM_ISP, "STATS CS image size violation"); cam_vfe_bus_ver3_print_dimensions( CAM_VFE_BUS_VER3_VFE_OUT_STATS_CS, - PLANE_Y, bus_priv); } @@ -2725,7 +2710,6 @@ static int cam_vfe_bus_ver3_err_irq_bottom_half( CAM_INFO(CAM_ISP, "STATS IHIST image size violation"); cam_vfe_bus_ver3_print_dimensions( CAM_VFE_BUS_VER3_VFE_OUT_STATS_IHIST, - PLANE_Y, bus_priv); } @@ -2733,7 +2717,6 @@ static int cam_vfe_bus_ver3_err_irq_bottom_half( CAM_INFO(CAM_ISP, "STATS BAF image size violation"); cam_vfe_bus_ver3_print_dimensions( CAM_VFE_BUS_VER3_VFE_OUT_STATS_BF, - PLANE_Y, bus_priv); } @@ -2741,7 +2724,6 @@ static int cam_vfe_bus_ver3_err_irq_bottom_half( CAM_INFO(CAM_ISP, "PD image size violation"); cam_vfe_bus_ver3_print_dimensions( CAM_VFE_BUS_VER3_VFE_OUT_2PD, - PLANE_Y, bus_priv); } @@ -2749,7 +2731,6 @@ static int cam_vfe_bus_ver3_err_irq_bottom_half( CAM_INFO(CAM_ISP, "LCR image size violation"); cam_vfe_bus_ver3_print_dimensions( CAM_VFE_BUS_VER3_VFE_OUT_LCR, - PLANE_Y, bus_priv); } @@ -2757,7 +2738,6 @@ static int cam_vfe_bus_ver3_err_irq_bottom_half( CAM_INFO(CAM_ISP, "RDI 0 image size violation"); cam_vfe_bus_ver3_print_dimensions( CAM_VFE_BUS_VER3_VFE_OUT_RDI0, - PLANE_Y, bus_priv); } @@ -2765,7 +2745,6 @@ static int cam_vfe_bus_ver3_err_irq_bottom_half( CAM_INFO(CAM_ISP, "RDI 1 image size violation"); cam_vfe_bus_ver3_print_dimensions( CAM_VFE_BUS_VER3_VFE_OUT_RDI1, - PLANE_Y, bus_priv); } @@ -2773,7 +2752,6 @@ static int cam_vfe_bus_ver3_err_irq_bottom_half( CAM_INFO(CAM_ISP, "RDI 2 image size violation"); cam_vfe_bus_ver3_print_dimensions( CAM_VFE_BUS_VER3_VFE_OUT_RDI2, - PLANE_Y, bus_priv); } @@ -3686,6 +3664,19 @@ static int cam_vfe_bus_ver3_process_cmd( bus_priv->error_irq_handle = 0; } break; + case CAM_ISP_HW_CMD_DUMP_BUS_INFO: { + struct cam_isp_hw_event_info *event_info; + enum cam_vfe_bus_ver3_vfe_out_type vfe_out_res_id; + + event_info = + (struct cam_isp_hw_event_info *)cmd_args; + bus_priv = (struct cam_vfe_bus_ver3_priv *) priv; + vfe_out_res_id = + cam_vfe_bus_ver3_get_out_res_id(event_info->res_id); + rc = cam_vfe_bus_ver3_print_dimensions( + vfe_out_res_id, bus_priv); + break; + } case CAM_ISP_HW_CMD_UBWC_UPDATE_V2: rc = cam_vfe_bus_ver3_update_ubwc_config_v2(cmd_args); break; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_lite_ver2.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_lite_ver2.c index 9ea8d74a35ca..e4ff7255df5b 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_lite_ver2.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_lite_ver2.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. */ #include @@ -36,6 +36,7 @@ struct cam_vfe_mux_camif_lite_data { evt_payload[CAM_VFE_CAMIF_LITE_EVT_MAX]; struct list_head free_payload_list; spinlock_t spin_lock; + struct timeval error_ts; }; static int cam_vfe_camif_lite_get_evt_payload( @@ -133,6 +134,12 @@ static int cam_vfe_camif_lite_err_irq_top_half( } cam_isp_hw_get_timestamp(&evt_payload->ts); + if (error_flag) { + camif_lite_priv->error_ts.tv_sec = + evt_payload->ts.mono_time.tv_sec; + camif_lite_priv->error_ts.tv_usec = + evt_payload->ts.mono_time.tv_usec; + } for (i = 0; i < th_payload->num_registers; i++) evt_payload->irq_reg_val[i] = th_payload->evt_status_arr[i]; @@ -301,6 +308,9 @@ static int cam_vfe_camif_lite_resource_start( } } + rsrc_data->error_ts.tv_sec = 0; + rsrc_data->error_ts.tv_usec = 0; + CAM_DBG(CAM_ISP, "Start Camif Lite IFE %d Done", camif_lite_res->hw_intf->hw_idx); return rc; @@ -405,6 +415,44 @@ static int cam_vfe_camif_lite_handle_irq_top_half(uint32_t evt_id, return rc; } +static int cam_vfe_camif_lite_cpas_fifo_levels_reg_dump( + struct cam_vfe_mux_camif_lite_data *camif_lite_priv) +{ + struct cam_vfe_soc_private *soc_private = + camif_lite_priv->soc_info->soc_private; + uint32_t val; + + if (soc_private->cpas_version == CAM_CPAS_TITAN_175_V120 || + soc_private->cpas_version == CAM_CPAS_TITAN_175_V130) { + cam_cpas_reg_read(soc_private->cpas_handle, + CAM_CPAS_REG_CAMNOC, 0x3A20, true, &val); + CAM_INFO(CAM_ISP, "IFE0_nRDI_MAXWR_LOW offset 0x3A20 val 0x%x", + val); + + cam_cpas_reg_read(soc_private->cpas_handle, + CAM_CPAS_REG_CAMNOC, 0x5420, true, &val); + CAM_INFO(CAM_ISP, "IFE1_nRDI_MAXWR_LOW offset 0x5420 val 0x%x", + val); + + cam_cpas_reg_read(soc_private->cpas_handle, + CAM_CPAS_REG_CAMNOC, 0x3620, true, &val); + CAM_INFO(CAM_ISP, + "IFE0123_RDI_WR_MAXWR_LOW offset 0x3620 val 0x%x", val); + + } else if (soc_private->cpas_version < CAM_CPAS_TITAN_175_V120) { + cam_cpas_reg_read(soc_private->cpas_handle, + CAM_CPAS_REG_CAMNOC, 0x420, true, &val); + CAM_INFO(CAM_ISP, "IFE02_MAXWR_LOW offset 0x420 val 0x%x", val); + + cam_cpas_reg_read(soc_private->cpas_handle, + CAM_CPAS_REG_CAMNOC, 0x820, true, &val); + CAM_INFO(CAM_ISP, "IFE13_MAXWR_LOW offset 0x820 val 0x%x", val); + } + + return 0; + +} + static int cam_vfe_camif_lite_handle_irq_bottom_half( void *handler_priv, void *evt_payload_priv) @@ -416,6 +464,9 @@ static int cam_vfe_camif_lite_handle_irq_bottom_half( struct cam_isp_hw_event_info evt_info; uint32_t irq_status0; uint32_t irq_status1; + struct cam_hw_soc_info *soc_info = NULL; + struct cam_vfe_soc_private *soc_private = NULL; + struct timespec64 ts; if (!handler_priv || !evt_payload_priv) { CAM_ERR(CAM_ISP, "Invalid params"); @@ -427,6 +478,9 @@ static int cam_vfe_camif_lite_handle_irq_bottom_half( payload = evt_payload_priv; irq_status0 = payload->irq_reg_val[CAM_IFE_IRQ_CAMIF_REG_STATUS0]; irq_status1 = payload->irq_reg_val[CAM_IFE_IRQ_CAMIF_REG_STATUS1]; + soc_info = camif_lite_priv->soc_info; + soc_private = + (struct cam_vfe_soc_private *)soc_info->soc_private; evt_info.hw_idx = camif_lite_node->hw_intf->hw_idx; evt_info.res_id = camif_lite_node->res_id; @@ -464,11 +518,27 @@ static int cam_vfe_camif_lite_handle_irq_bottom_half( CAM_DBG(CAM_ISP, "VFE:%d CAMIF LITE Received ERROR", evt_info.hw_idx); + cam_vfe_camif_lite_cpas_fifo_levels_reg_dump(camif_lite_priv); + + ktime_get_boottime_ts64(&ts); + CAM_INFO(CAM_ISP, + "current monotonic time stamp seconds %lld:%lld", + ts.tv_sec, ts.tv_nsec/1000); + CAM_INFO(CAM_ISP, + "ERROR time %lld:%lld", + camif_lite_priv->error_ts.tv_sec, + camif_lite_priv->error_ts.tv_usec); + CAM_INFO(CAM_ISP, "ife_clk_src:%lld", + soc_private->ife_clk_src); + if (camif_lite_priv->event_cb) camif_lite_priv->event_cb(camif_lite_priv->priv, CAM_ISP_HW_EVENT_ERROR, (void *)&evt_info); ret = CAM_VFE_IRQ_STATUS_OVERFLOW; + + cam_cpas_log_votes(); + } cam_vfe_camif_lite_put_evt_payload(camif_lite_priv, &payload); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_lite_ver3.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_lite_ver3.c index bfb17d2145f8..b54c43a145bc 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_lite_ver3.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_lite_ver3.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. */ #include @@ -40,6 +40,10 @@ struct cam_vfe_mux_camif_lite_data { uint32_t camif_debug; struct cam_vfe_top_irq_evt_payload evt_payload[CAM_VFE_CAMIF_LITE_EVT_MAX]; + struct timeval sof_ts; + struct timeval epoch_ts; + struct timeval eof_ts; + struct timeval error_ts; }; static int cam_vfe_camif_lite_get_evt_payload( @@ -137,6 +141,12 @@ static int cam_vfe_camif_lite_err_irq_top_half( return rc; cam_isp_hw_get_timestamp(&evt_payload->ts); + if (error_flag) { + camif_lite_priv->error_ts.tv_sec = + evt_payload->ts.mono_time.tv_sec; + camif_lite_priv->error_ts.tv_usec = + evt_payload->ts.mono_time.tv_usec; + } for (i = 0; i < th_payload->num_registers; i++) evt_payload->irq_reg_val[i] = th_payload->evt_status_arr[i]; @@ -293,6 +303,15 @@ static int cam_vfe_camif_lite_resource_start( rsrc_data->mem_base + rsrc_data->camif_lite_reg->lite_epoch_irq); + rsrc_data->error_ts.tv_sec = 0; + rsrc_data->error_ts.tv_usec = 0; + rsrc_data->sof_ts.tv_sec = 0; + rsrc_data->sof_ts.tv_usec = 0; + rsrc_data->epoch_ts.tv_sec = 0; + rsrc_data->epoch_ts.tv_usec = 0; + rsrc_data->eof_ts.tv_sec = 0; + rsrc_data->eof_ts.tv_usec = 0; + skip_core_cfg: camif_lite_res->res_state = CAM_ISP_RESOURCE_STATE_STREAMING; @@ -888,6 +907,7 @@ static void cam_vfe_camif_lite_print_status(uint32_t *status, CAM_INFO(CAM_ISP, "CAMNOC REG ife_linear: 0x%X ife_rdi_wr: 0x%X ife_ubwc_stats: 0x%X", val0, val1, val2); + cam_cpas_log_votes(); } if (err_type == CAM_VFE_IRQ_STATUS_OVERFLOW && !bus_overflow_status) { @@ -1062,6 +1082,8 @@ static int cam_vfe_camif_lite_handle_irq_bottom_half( struct cam_vfe_soc_private *soc_private = NULL; uint32_t irq_status[CAM_IFE_IRQ_REGISTERS_MAX] = {0}; int i = 0; + uint32_t status_0 = 0; + struct timespec64 ts; if (!handler_priv || !evt_payload_priv) { CAM_ERR(CAM_ISP, "Invalid params"); @@ -1097,6 +1119,10 @@ static int cam_vfe_camif_lite_handle_irq_bottom_half( CAM_DBG(CAM_ISP, "VFE:%d CAMIF LITE:%d Received SOF", evt_info.hw_idx, evt_info.res_id); ret = CAM_VFE_IRQ_STATUS_SUCCESS; + camif_lite_priv->sof_ts.tv_sec = + payload->ts.mono_time.tv_sec; + camif_lite_priv->sof_ts.tv_usec = + payload->ts.mono_time.tv_usec; if (camif_lite_priv->event_cb) camif_lite_priv->event_cb(camif_lite_priv->priv, @@ -1108,6 +1134,10 @@ static int cam_vfe_camif_lite_handle_irq_bottom_half( CAM_DBG(CAM_ISP, "VFE:%d CAMIF LITE:%d Received EPOCH", evt_info.hw_idx, evt_info.res_id); ret = CAM_VFE_IRQ_STATUS_SUCCESS; + camif_lite_priv->epoch_ts.tv_sec = + payload->ts.mono_time.tv_sec; + camif_lite_priv->epoch_ts.tv_usec = + payload->ts.mono_time.tv_usec; if (camif_lite_priv->event_cb) camif_lite_priv->event_cb(camif_lite_priv->priv, @@ -1119,18 +1149,50 @@ static int cam_vfe_camif_lite_handle_irq_bottom_half( CAM_DBG(CAM_ISP, "VFE:%d CAMIF LITE:%d Received EOF", evt_info.hw_idx, evt_info.res_id); ret = CAM_VFE_IRQ_STATUS_SUCCESS; + camif_lite_priv->eof_ts.tv_sec = + payload->ts.mono_time.tv_sec; + camif_lite_priv->eof_ts.tv_usec = + payload->ts.mono_time.tv_usec; if (camif_lite_priv->event_cb) camif_lite_priv->event_cb(camif_lite_priv->priv, CAM_ISP_HW_EVENT_EOF, (void *)&evt_info); } - if (irq_status[CAM_IFE_IRQ_CAMIF_REG_STATUS0] - & camif_lite_priv->reg_data->error_irq_mask0) { + status_0 = irq_status[CAM_IFE_IRQ_CAMIF_REG_STATUS0] + & camif_lite_priv->reg_data->error_irq_mask0; + if (status_0) { CAM_ERR(CAM_ISP, "VFE:%d Overflow", camif_lite_node->hw_intf->hw_idx); evt_info.err_type = CAM_VFE_IRQ_STATUS_OVERFLOW; + ktime_get_boottime_ts64(&ts); + CAM_INFO(CAM_ISP, + "current monotonic time stamp seconds %lld:%lld", + ts.tv_sec, ts.tv_nsec/1000); + CAM_INFO(CAM_ISP, + "ERROR time %lld:%lld", + camif_lite_priv->error_ts.tv_sec, + camif_lite_priv->error_ts.tv_usec); + + if (camif_lite_node->rdi_only_ctx) + CAM_INFO(CAM_ISP, + "SOF %lld:%lld EPOCH %lld:%lld EOF %lld:%lld", + camif_lite_priv->sof_ts.tv_sec, + camif_lite_priv->sof_ts.tv_usec, + camif_lite_priv->epoch_ts.tv_sec, + camif_lite_priv->epoch_ts.tv_usec, + camif_lite_priv->eof_ts.tv_sec, + camif_lite_priv->eof_ts.tv_usec); + + if (status_0 & 0x8000000) + evt_info.res_id = CAM_ISP_IFE_OUT_RES_RDI_2; + + if (status_0 & 0x10000000) + evt_info.res_id = CAM_ISP_IFE_OUT_RES_RDI_1; + + if (status_0 & 0x20000000) + evt_info.res_id = CAM_ISP_IFE_OUT_RES_RDI_0; if (camif_lite_priv->event_cb) camif_lite_priv->event_cb(camif_lite_priv->priv, diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c index 55a94c843dfb..1f7824763cfe 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c @@ -50,6 +50,10 @@ struct cam_vfe_mux_camif_data { uint32_t camif_debug; uint32_t dual_hw_idx; uint32_t is_dual; + struct timeval sof_ts; + struct timeval epoch_ts; + struct timeval eof_ts; + struct timeval error_ts; }; static int cam_vfe_camif_get_evt_payload( @@ -144,6 +148,12 @@ static int cam_vfe_camif_err_irq_top_half( } cam_isp_hw_get_timestamp(&evt_payload->ts); + if (error_flag) { + camif_priv->error_ts.tv_sec = + evt_payload->ts.mono_time.tv_sec; + camif_priv->error_ts.tv_usec = + evt_payload->ts.mono_time.tv_usec; + } for (i = 0; i < th_payload->num_registers; i++) evt_payload->irq_reg_val[i] = th_payload->evt_status_arr[i]; @@ -293,6 +303,14 @@ static int cam_vfe_camif_resource_init( if (rc) CAM_ERR(CAM_ISP, "failed to enable dsp clk"); } + camif_data->sof_ts.tv_sec = 0; + camif_data->sof_ts.tv_usec = 0; + camif_data->epoch_ts.tv_sec = 0; + camif_data->epoch_ts.tv_usec = 0; + camif_data->eof_ts.tv_sec = 0; + camif_data->eof_ts.tv_usec = 0; + camif_data->error_ts.tv_sec = 0; + camif_data->error_ts.tv_usec = 0; return rc; } @@ -631,6 +649,26 @@ static int cam_vfe_camif_sof_irq_debug( return 0; } +int cam_vfe_camif_dump_timestamps( + struct cam_isp_resource_node *rsrc_node, void *cmd_args) +{ + struct cam_vfe_mux_camif_data *camif_priv = + (struct cam_vfe_mux_camif_data *)rsrc_node->res_priv; + + CAM_INFO(CAM_ISP, + "CAMIF ERROR time %lld:%lld SOF %lld:%lld EPOCH %lld:%lld EOF %lld:%lld", + camif_priv->error_ts.tv_sec, + camif_priv->error_ts.tv_usec, + camif_priv->sof_ts.tv_sec, + camif_priv->sof_ts.tv_usec, + camif_priv->epoch_ts.tv_sec, + camif_priv->epoch_ts.tv_usec, + camif_priv->eof_ts.tv_sec, + camif_priv->eof_ts.tv_usec); + + return 0; +} + static int cam_vfe_camif_process_cmd(struct cam_isp_resource_node *rsrc_node, uint32_t cmd_type, void *cmd_args, uint32_t arg_size) { @@ -655,6 +693,9 @@ static int cam_vfe_camif_process_cmd(struct cam_isp_resource_node *rsrc_node, (struct cam_vfe_mux_camif_data *)rsrc_node->res_priv; camif_priv->camif_debug = *((uint32_t *)cmd_args); break; + case CAM_ISP_HW_CMD_CAMIF_DATA: + rc = cam_vfe_camif_dump_timestamps(rsrc_node, cmd_args); + break; default: CAM_ERR(CAM_ISP, "unsupported process command:%d", cmd_type); @@ -710,6 +751,7 @@ static int cam_vfe_camif_handle_irq_bottom_half(void *handler_priv, uint32_t irq_status0; uint32_t irq_status1; uint32_t val; + struct timespec64 ts; if (!handler_priv || !evt_payload_priv) { CAM_ERR(CAM_ISP, "Invalid params"); @@ -731,6 +773,10 @@ static int cam_vfe_camif_handle_irq_bottom_half(void *handler_priv, if (irq_status0 & camif_priv->reg_data->eof_irq_mask) { CAM_DBG(CAM_ISP, "Received EOF"); + camif_priv->eof_ts.tv_sec = + payload->ts.mono_time.tv_sec; + camif_priv->eof_ts.tv_usec = + payload->ts.mono_time.tv_usec; if (camif_priv->event_cb) camif_priv->event_cb(camif_priv->priv, @@ -752,8 +798,13 @@ static int cam_vfe_camif_handle_irq_bottom_half(void *handler_priv, false; camif_priv->irq_debug_cnt = 0; } - } else + } else { CAM_DBG(CAM_ISP, "Received SOF"); + camif_priv->sof_ts.tv_sec = + payload->ts.mono_time.tv_sec; + camif_priv->sof_ts.tv_usec = + payload->ts.mono_time.tv_usec; + } if (camif_priv->event_cb) camif_priv->event_cb(camif_priv->priv, @@ -774,6 +825,10 @@ static int cam_vfe_camif_handle_irq_bottom_half(void *handler_priv, if (irq_status0 & camif_priv->reg_data->epoch0_irq_mask) { CAM_DBG(CAM_ISP, "Received EPOCH"); + camif_priv->epoch_ts.tv_sec = + payload->ts.mono_time.tv_sec; + camif_priv->epoch_ts.tv_usec = + payload->ts.mono_time.tv_usec; if (camif_priv->event_cb) camif_priv->event_cb(camif_priv->priv, @@ -785,6 +840,11 @@ static int cam_vfe_camif_handle_irq_bottom_half(void *handler_priv, if (irq_status0 & camif_priv->reg_data->error_irq_mask0) { CAM_DBG(CAM_ISP, "Received ERROR"); + ktime_get_boottime_ts64(&ts); + CAM_INFO(CAM_ISP, + "current monotonic time stamp seconds %lld:%lld", + ts.tv_sec, ts.tv_nsec/1000); + if (camif_priv->event_cb) camif_priv->event_cb(camif_priv->priv, CAM_ISP_HW_EVENT_ERROR, (void *)&evt_info); @@ -800,6 +860,11 @@ static int cam_vfe_camif_handle_irq_bottom_half(void *handler_priv, if (irq_status1 & camif_priv->reg_data->error_irq_mask1) { CAM_DBG(CAM_ISP, "Received ERROR"); + ktime_get_boottime_ts64(&ts); + CAM_INFO(CAM_ISP, + "current monotonic time stamp seconds %lld:%lld", + ts.tv_sec, ts.tv_nsec/1000); + if (camif_priv->event_cb) camif_priv->event_cb(camif_priv->priv, CAM_ISP_HW_EVENT_ERROR, (void *)&evt_info); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c index b5e2a429dab1..543dcbb358bf 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c @@ -57,6 +57,10 @@ struct cam_vfe_mux_camif_ver3_data { uint32_t is_dual; bool is_fe_enabled; bool is_offline; + struct timeval sof_ts; + struct timeval epoch_ts; + struct timeval eof_ts; + struct timeval error_ts; }; static int cam_vfe_camif_ver3_get_evt_payload( @@ -142,6 +146,12 @@ static int cam_vfe_camif_ver3_err_irq_top_half( return rc; cam_isp_hw_get_timestamp(&evt_payload->ts); + if (error_flag) { + camif_priv->error_ts.tv_sec = + evt_payload->ts.mono_time.tv_sec; + camif_priv->error_ts.tv_usec = + evt_payload->ts.mono_time.tv_usec; + } for (i = 0; i < th_payload->num_registers; i++) evt_payload->irq_reg_val[i] = th_payload->evt_status_arr[i]; @@ -304,6 +314,14 @@ static int cam_vfe_camif_ver3_resource_init( CAM_ERR(CAM_ISP, "failed to enable dsp clk, rc = %d", rc); } + camif_data->sof_ts.tv_sec = 0; + camif_data->sof_ts.tv_usec = 0; + camif_data->epoch_ts.tv_sec = 0; + camif_data->epoch_ts.tv_usec = 0; + camif_data->eof_ts.tv_sec = 0; + camif_data->eof_ts.tv_usec = 0; + camif_data->error_ts.tv_sec = 0; + camif_data->error_ts.tv_usec = 0; return rc; } @@ -772,6 +790,26 @@ static int cam_vfe_camif_ver3_sof_irq_debug( return 0; } +int cam_vfe_camif_ver3_dump_timestamps( + struct cam_isp_resource_node *rsrc_node, void *cmd_args) +{ + struct cam_vfe_mux_camif_ver3_data *camif_priv = + (struct cam_vfe_mux_camif_ver3_data *)rsrc_node->res_priv; + + CAM_INFO(CAM_ISP, + "CAMIF ERROR time %lld:%lld SOF %lld:%lld EPOCH %lld:%lld EOF %lld:%lld", + camif_priv->error_ts.tv_sec, + camif_priv->error_ts.tv_usec, + camif_priv->sof_ts.tv_sec, + camif_priv->sof_ts.tv_usec, + camif_priv->epoch_ts.tv_sec, + camif_priv->epoch_ts.tv_usec, + camif_priv->eof_ts.tv_sec, + camif_priv->eof_ts.tv_usec); + + return 0; +} + static int cam_vfe_camif_ver3_process_cmd( struct cam_isp_resource_node *rsrc_node, uint32_t cmd_type, void *cmd_args, uint32_t arg_size) @@ -808,6 +846,9 @@ static int cam_vfe_camif_ver3_process_cmd( *((struct cam_hw_soc_info **)cmd_args) = camif_priv->soc_info; rc = 0; break; + case CAM_ISP_HW_CMD_CAMIF_DATA: + rc = cam_vfe_camif_ver3_dump_timestamps(rsrc_node, cmd_args); + break; default: CAM_ERR(CAM_ISP, "unsupported process command:%d", cmd_type); @@ -969,6 +1010,7 @@ static void cam_vfe_camif_ver3_print_status(uint32_t *status, CAM_INFO(CAM_ISP, "CAMNOC REG ife_linear: 0x%X ife_rdi_wr: 0x%X ife_ubwc_stats: 0x%X", val0, val1, val2); + cam_cpas_log_votes(); return; } @@ -1280,6 +1322,7 @@ static int cam_vfe_camif_ver3_handle_irq_bottom_half(void *handler_priv, struct cam_vfe_top_irq_evt_payload *payload; struct cam_isp_hw_event_info evt_info; uint32_t irq_status[CAM_IFE_IRQ_REGISTERS_MAX] = {0}; + struct timespec64 ts; uint32_t val = 0; int i = 0; @@ -1317,9 +1360,14 @@ static int cam_vfe_camif_ver3_handle_irq_bottom_half(void *handler_priv, false; camif_priv->irq_debug_cnt = 0; } - } else + } else { CAM_DBG(CAM_ISP, "VFE:%d Received SOF", evt_info.hw_idx); + camif_priv->sof_ts.tv_sec = + payload->ts.mono_time.tv_sec; + camif_priv->sof_ts.tv_usec = + payload->ts.mono_time.tv_usec; + } if (camif_priv->event_cb) camif_priv->event_cb(camif_priv->priv, @@ -1332,6 +1380,10 @@ static int cam_vfe_camif_ver3_handle_irq_bottom_half(void *handler_priv, & camif_priv->reg_data->epoch0_irq_mask) { CAM_DBG(CAM_ISP, "VFE:%d Received EPOCH", evt_info.hw_idx); evt_info.th_reg_val = payload->th_reg_val; + camif_priv->epoch_ts.tv_sec = + payload->ts.mono_time.tv_sec; + camif_priv->epoch_ts.tv_usec = + payload->ts.mono_time.tv_usec; if (camif_priv->event_cb) camif_priv->event_cb(camif_priv->priv, @@ -1343,6 +1395,10 @@ static int cam_vfe_camif_ver3_handle_irq_bottom_half(void *handler_priv, if (irq_status[CAM_IFE_IRQ_CAMIF_REG_STATUS1] & camif_priv->reg_data->eof_irq_mask) { CAM_DBG(CAM_ISP, "VFE:%d Received EOF", evt_info.hw_idx); + camif_priv->eof_ts.tv_sec = + payload->ts.mono_time.tv_sec; + camif_priv->eof_ts.tv_usec = + payload->ts.mono_time.tv_usec; if (camif_priv->event_cb) camif_priv->event_cb(camif_priv->priv, @@ -1355,6 +1411,11 @@ static int cam_vfe_camif_ver3_handle_irq_bottom_half(void *handler_priv, & camif_priv->reg_data->error_irq_mask0) { CAM_ERR(CAM_ISP, "VFE:%d Overflow", evt_info.hw_idx); + ktime_get_boottime_ts64(&ts); + CAM_INFO(CAM_ISP, + "current monotonic time stamp seconds %lld:%lld", + ts.tv_sec, ts.tv_nsec/1000); + if (camif_priv->event_cb) camif_priv->event_cb(camif_priv->priv, CAM_ISP_HW_EVENT_ERROR, (void *)&evt_info); @@ -1379,6 +1440,11 @@ static int cam_vfe_camif_ver3_handle_irq_bottom_half(void *handler_priv, if (irq_status[CAM_IFE_IRQ_CAMIF_REG_STATUS2]) { CAM_ERR(CAM_ISP, "VFE:%d Violation", evt_info.hw_idx); + ktime_get_boottime_ts64(&ts); + CAM_INFO(CAM_ISP, + "current monotonic time stamp seconds %lld:%lld", + ts.tv_sec, ts.tv_nsec/1000); + if (camif_priv->event_cb) camif_priv->event_cb(camif_priv->priv, CAM_ISP_HW_EVENT_ERROR, (void *)&evt_info); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_rdi.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_rdi.c index a0e7741e5505..b766c1ee844b 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_rdi.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_rdi.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #include @@ -21,7 +21,9 @@ struct cam_vfe_mux_rdi_data { struct cam_vfe_top_ver2_reg_offset_common *common_reg; struct cam_vfe_rdi_ver2_reg *rdi_reg; struct cam_vfe_rdi_common_reg_data *rdi_common_reg_data; + struct cam_vfe_rdi_overflow_status *rdi_irq_status; struct cam_vfe_rdi_reg_data *reg_data; + struct cam_hw_soc_info *soc_info; cam_hw_mgr_event_cb_func event_cb; void *priv; @@ -33,6 +35,8 @@ struct cam_vfe_mux_rdi_data { spinlock_t spin_lock; enum cam_isp_hw_sync_mode sync_mode; + struct timeval sof_ts; + struct timeval error_ts; }; static int cam_vfe_rdi_get_evt_payload( @@ -81,6 +85,44 @@ static int cam_vfe_rdi_put_evt_payload( return 0; } +static int cam_vfe_rdi_cpas_reg_dump( +struct cam_vfe_mux_rdi_data *rdi_priv) +{ + struct cam_vfe_soc_private *soc_private = + rdi_priv->soc_info->soc_private; + uint32_t val; + + if (soc_private->cpas_version == CAM_CPAS_TITAN_175_V120 || + soc_private->cpas_version == CAM_CPAS_TITAN_175_V130) { + cam_cpas_reg_read(soc_private->cpas_handle, + CAM_CPAS_REG_CAMNOC, 0x3A20, true, &val); + CAM_INFO(CAM_ISP, "IFE0_nRDI_MAXWR_LOW offset 0x3A20 val 0x%x", + val); + + cam_cpas_reg_read(soc_private->cpas_handle, + CAM_CPAS_REG_CAMNOC, 0x5420, true, &val); + CAM_INFO(CAM_ISP, "IFE1_nRDI_MAXWR_LOW offset 0x5420 val 0x%x", + val); + + cam_cpas_reg_read(soc_private->cpas_handle, + CAM_CPAS_REG_CAMNOC, 0x3620, true, &val); + CAM_INFO(CAM_ISP, + "IFE0123_RDI_WR_MAXWR_LOW offset 0x3620 val 0x%x", val); + + } else if (soc_private->cpas_version < CAM_CPAS_TITAN_175_V120) { + cam_cpas_reg_read(soc_private->cpas_handle, + CAM_CPAS_REG_CAMNOC, 0x420, true, &val); + CAM_INFO(CAM_ISP, "IFE02_MAXWR_LOW offset 0x420 val 0x%x", val); + + cam_cpas_reg_read(soc_private->cpas_handle, + CAM_CPAS_REG_CAMNOC, 0x820, true, &val); + CAM_INFO(CAM_ISP, "IFE13_MAXWR_LOW offset 0x820 val 0x%x", val); + } + + return 0; + +} + static int cam_vfe_rdi_err_irq_top_half( uint32_t evt_id, struct cam_irq_th_payload *th_payload) @@ -124,6 +166,12 @@ static int cam_vfe_rdi_err_irq_top_half( } cam_isp_hw_get_timestamp(&evt_payload->ts); + if (error_flag) { + rdi_priv->error_ts.tv_sec = + evt_payload->ts.mono_time.tv_sec; + rdi_priv->error_ts.tv_usec = + evt_payload->ts.mono_time.tv_usec; + } for (i = 0; i < th_payload->num_registers; i++) evt_payload->irq_reg_val[i] = th_payload->evt_status_arr[i]; @@ -282,6 +330,11 @@ static int cam_vfe_rdi_resource_start( } } + rsrc_data->sof_ts.tv_sec = 0; + rsrc_data->sof_ts.tv_usec = 0; + rsrc_data->error_ts.tv_sec = 0; + rsrc_data->error_ts.tv_usec = 0; + CAM_DBG(CAM_ISP, "Start RDI %d", rdi_res->res_id - CAM_ISP_HW_VFE_IN_RDI0); end: @@ -392,6 +445,11 @@ static int cam_vfe_rdi_handle_irq_bottom_half(void *handler_priv, struct cam_vfe_top_irq_evt_payload *payload; struct cam_isp_hw_event_info evt_info; uint32_t irq_status0; + uint32_t irq_status1; + uint32_t irq_rdi_status; + struct cam_hw_soc_info *soc_info = NULL; + struct cam_vfe_soc_private *soc_private = NULL; + struct timespec64 ts; if (!handler_priv || !evt_payload_priv) { CAM_ERR(CAM_ISP, "Invalid params"); @@ -401,8 +459,12 @@ static int cam_vfe_rdi_handle_irq_bottom_half(void *handler_priv, rdi_node = handler_priv; rdi_priv = rdi_node->res_priv; payload = evt_payload_priv; + soc_info = rdi_priv->soc_info; + soc_private = + (struct cam_vfe_soc_private *)soc_info->soc_private; irq_status0 = payload->irq_reg_val[CAM_IFE_IRQ_CAMIF_REG_STATUS0]; + irq_status1 = payload->irq_reg_val[CAM_IFE_IRQ_CAMIF_REG_STATUS1]; evt_info.hw_idx = rdi_node->hw_intf->hw_idx; evt_info.res_id = rdi_node->res_id; @@ -412,7 +474,10 @@ static int cam_vfe_rdi_handle_irq_bottom_half(void *handler_priv, if (irq_status0 & rdi_priv->reg_data->sof_irq_mask) { CAM_DBG(CAM_ISP, "Received SOF"); - + rdi_priv->sof_ts.tv_sec = + payload->ts.mono_time.tv_sec; + rdi_priv->sof_ts.tv_usec = + payload->ts.mono_time.tv_usec; if (rdi_priv->event_cb) rdi_priv->event_cb(rdi_priv->priv, CAM_ISP_HW_EVENT_SOF, (void *)&evt_info); @@ -430,6 +495,50 @@ static int cam_vfe_rdi_handle_irq_bottom_half(void *handler_priv, ret = CAM_VFE_IRQ_STATUS_SUCCESS; } + irq_rdi_status = + (irq_status1 & + rdi_priv->rdi_irq_status->rdi_overflow_mask); + if (irq_rdi_status) { + ktime_get_boottime_ts64(&ts); + CAM_INFO(CAM_ISP, + "current monotonic time stamp seconds %lld:%lld", + ts.tv_sec, ts.tv_nsec/1000); + + cam_vfe_rdi_cpas_reg_dump(rdi_priv); + + CAM_INFO(CAM_ISP, "ife_clk_src:%lld", + soc_private->ife_clk_src); + CAM_INFO(CAM_ISP, + "ERROR time %lld:%lld SOF %lld:%lld", + rdi_priv->error_ts.tv_sec, + rdi_priv->error_ts.tv_usec, + rdi_priv->sof_ts.tv_sec, + rdi_priv->sof_ts.tv_usec); + + if (irq_rdi_status & + rdi_priv->rdi_irq_status->rdi0_overflow_mask) { + evt_info.res_id = CAM_ISP_IFE_OUT_RES_RDI_0; + } + else if (irq_rdi_status & + rdi_priv->rdi_irq_status->rdi1_overflow_mask) { + evt_info.res_id = CAM_ISP_IFE_OUT_RES_RDI_1; + } + else if (irq_rdi_status & + rdi_priv->rdi_irq_status->rdi2_overflow_mask) { + evt_info.res_id = CAM_ISP_IFE_OUT_RES_RDI_2; + } + else if (irq_rdi_status & + rdi_priv->rdi_irq_status->rdi3_overflow_mask) { + evt_info.res_id = CAM_ISP_IFE_OUT_RES_RDI_3; + } + + if (rdi_priv->event_cb) + rdi_priv->event_cb(rdi_priv->priv, + CAM_ISP_HW_EVENT_ERROR, + (void *)&evt_info); + cam_cpas_log_votes(); + } + cam_vfe_rdi_put_evt_payload(rdi_priv, &payload); CAM_DBG(CAM_ISP, "returing status = %d", ret); return ret; @@ -461,6 +570,8 @@ int cam_vfe_rdi_ver2_init( rdi_priv->rdi_reg = rdi_info->rdi_reg; rdi_priv->vfe_irq_controller = vfe_irq_controller; rdi_priv->rdi_common_reg_data = rdi_info->common_reg_data; + rdi_priv->soc_info = soc_info; + rdi_priv->rdi_irq_status = rdi_info->rdi_irq_status; switch (rdi_node->res_id) { case CAM_ISP_HW_VFE_IN_RDI0: diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_rdi.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_rdi.h index c570e84a011c..70a2cb756cea 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_rdi.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_rdi.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #ifndef _CAM_VFE_RDI_H_ @@ -17,6 +17,14 @@ struct cam_vfe_rdi_ver2_reg { uint32_t reg_update_cmd; }; +struct cam_vfe_rdi_overflow_status { + uint32_t rdi0_overflow_mask; + uint32_t rdi1_overflow_mask; + uint32_t rdi2_overflow_mask; + uint32_t rdi3_overflow_mask; + uint32_t rdi_overflow_mask; +}; + struct cam_vfe_rdi_common_reg_data { uint32_t subscribe_irq_mask0; uint32_t subscribe_irq_mask1; @@ -35,6 +43,7 @@ struct cam_vfe_rdi_ver2_hw_info { struct cam_vfe_top_ver2_reg_offset_common *common_reg; struct cam_vfe_rdi_ver2_reg *rdi_reg; struct cam_vfe_rdi_common_reg_data *common_reg_data; + struct cam_vfe_rdi_overflow_status *rdi_irq_status; struct cam_vfe_rdi_reg_data *reg_data[CAM_VFE_RDI_VER2_MAX]; }; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c index b174c21d8bf2..044a02468072 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c @@ -83,8 +83,11 @@ static int cam_vfe_top_set_hw_clk_rate( struct cam_hw_soc_info *soc_info = NULL; int i, rc = 0; unsigned long max_clk_rate = 0; + struct cam_vfe_soc_private *soc_private = NULL; soc_info = top_priv->common_data.soc_info; + soc_private = + (struct cam_vfe_soc_private *)soc_info->soc_private; for (i = 0; i < top_priv->top_common.num_mux; i++) { if (top_priv->req_clk_rate[i] > max_clk_rate) @@ -96,7 +99,7 @@ static int cam_vfe_top_set_hw_clk_rate( CAM_DBG(CAM_PERF, "VFE: Clock name=%s idx=%d clk=%llu", soc_info->clk_name[soc_info->src_clk_idx], soc_info->src_clk_idx, max_clk_rate); - + soc_private->ife_clk_src = max_clk_rate; rc = cam_soc_util_set_src_clk_rate(soc_info, max_clk_rate); if (!rc) @@ -265,6 +268,19 @@ static int cam_vfe_top_add_wait_trigger(struct cam_vfe_top_ver2_priv *top_priv, return 0; } +static int cam_vfe_top_get_data( + struct cam_vfe_top_ver2_priv *top_priv, + void *cmd_args, uint32_t arg_size) +{ + struct cam_isp_resource_node *res = cmd_args; + + if (res->process_cmd) + return res->process_cmd(res, + CAM_ISP_HW_CMD_CAMIF_DATA, cmd_args, arg_size); + + return -EINVAL; +} + int cam_vfe_top_get_hw_caps(void *device_priv, void *get_hw_cap_args, uint32_t arg_size) { @@ -622,6 +638,8 @@ int cam_vfe_top_stop(void *device_priv, struct cam_vfe_top_ver2_priv *top_priv; struct cam_isp_resource_node *mux_res; struct cam_hw_info *hw_info = NULL; + struct cam_hw_soc_info *soc_info = NULL; + struct cam_vfe_soc_private *soc_private = NULL; int i, rc = 0; if (!device_priv || !stop_args) { @@ -632,6 +650,8 @@ int cam_vfe_top_stop(void *device_priv, top_priv = (struct cam_vfe_top_ver2_priv *)device_priv; mux_res = (struct cam_isp_resource_node *)stop_args; hw_info = (struct cam_hw_info *)mux_res->hw_intf->hw_priv; + soc_info = top_priv->common_data.soc_info; + soc_private = soc_info->soc_private; if ((mux_res->res_id == CAM_ISP_HW_VFE_IN_CAMIF) || (mux_res->res_id == CAM_ISP_HW_VFE_IN_PDLIB) || @@ -662,7 +682,7 @@ int cam_vfe_top_stop(void *device_priv, } } } - + soc_private->ife_clk_src = 0; return rc; } @@ -706,6 +726,10 @@ int cam_vfe_top_process_cmd(void *device_priv, uint32_t cmd_type, rc = cam_vfe_top_mux_get_reg_update(top_priv, cmd_args, arg_size); break; + case CAM_ISP_HW_CMD_CAMIF_DATA: + rc = cam_vfe_top_get_data(top_priv, cmd_args, + arg_size); + break; case CAM_ISP_HW_CMD_CLOCK_UPDATE: rc = cam_vfe_top_clock_update(top_priv, cmd_args, arg_size); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.c index e632596991bb..763b8f4afdaa 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.c @@ -309,6 +309,19 @@ static int cam_vfe_top_add_wait_trigger(struct cam_vfe_top_ver3_priv *top_priv, return 0; } +static int cam_vfe_top_ver3_get_data( + struct cam_vfe_top_ver3_priv *top_priv, + void *cmd_args, uint32_t arg_size) +{ + struct cam_isp_resource_node *res = cmd_args; + + if (res->process_cmd) + return res->process_cmd(res, + CAM_ISP_HW_CMD_CAMIF_DATA, cmd_args, arg_size); + + return -EINVAL; +} + int cam_vfe_top_ver3_get_hw_caps(void *device_priv, void *get_hw_cap_args, uint32_t arg_size) { @@ -639,6 +652,10 @@ int cam_vfe_top_ver3_process_cmd(void *device_priv, uint32_t cmd_type, rc = cam_vfe_top_ver3_mux_get_reg_update(top_priv, cmd_args, arg_size); break; + case CAM_ISP_HW_CMD_CAMIF_DATA: + rc = cam_vfe_top_ver3_get_data(top_priv, cmd_args, + arg_size); + break; case CAM_ISP_HW_CMD_CLOCK_UPDATE: rc = cam_vfe_top_ver3_clock_update(top_priv, cmd_args, arg_size);