Browse Source

Merge "msm: camera: ife: IFE debug enhancement for overflow debugging" into camera-kernel.lnx.4.0

Camera Software Integration 5 years ago
parent
commit
aa71c1c0b7

+ 65 - 4
drivers/cam_cpas/cam_cpas_hw.c

@@ -134,7 +134,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;
@@ -193,6 +193,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:
@@ -311,6 +316,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);
@@ -331,13 +337,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;
@@ -518,6 +526,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;
 		}
 	}
 
@@ -699,6 +709,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);
@@ -739,7 +750,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",
@@ -750,6 +761,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;
 }
@@ -772,6 +785,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) {
@@ -947,13 +961,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);
@@ -1703,6 +1720,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)
@@ -1806,6 +1863,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;

+ 6 - 0
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);

+ 2 - 1
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,
 };
 

+ 24 - 0
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;

+ 10 - 0
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_ */

+ 77 - 5
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:

+ 2 - 0
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,

+ 2 - 0
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);

+ 3 - 1
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;
 };
 
 /*

+ 11 - 2
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,

+ 9 - 0
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,

+ 43 - 0
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;

+ 43 - 52
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;

+ 71 - 1
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 <linux/slab.h>
@@ -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);

+ 65 - 3
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 <linux/slab.h>
@@ -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,

+ 66 - 1
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);

+ 67 - 1
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);

+ 113 - 2
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 <linux/slab.h>
@@ -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:

+ 10 - 1
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];
 };
 

+ 26 - 2
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);

+ 17 - 0
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);