Эх сурвалжийг харах

msm: camera: ife: IFE debug enhancement for overflow debugging

In many error cases it is required to know the
bandwidth applied on axi ports and camnoc axi
clock rate values. Added cpas api to print the
current axi bus votes, camnoc axi clock and ahb
vote level.This api can be called for isp errors
such as bus overflow, pxl overflow cases.
On RDI overflow printing last applied IFE clock,
dumping the CAMNOC fill-level registers to know
the pending and queued transactions, SOF EPOCH
and EOF timing to know exactly at what time the
RDI overflow came, Width and height of specific
Write master.

CRs-Fixed: 2623885
Change-Id: I92a9097efe9f6726748ec27ca39dd51c8c6de1b6
Signed-off-by: Mukund Madhusudan Atre <[email protected]>
Mukund Madhusudan Atre 5 жил өмнө
parent
commit
b7235bc92c
21 өөрчлөгдсөн 732 нэмэгдсэн , 76 устгасан
  1. 65 4
      drivers/cam_cpas/cam_cpas_hw.c
  2. 6 0
      drivers/cam_cpas/cam_cpas_hw.h
  3. 2 1
      drivers/cam_cpas/cam_cpas_hw_intf.h
  4. 24 0
      drivers/cam_cpas/cam_cpas_intf.c
  5. 10 0
      drivers/cam_cpas/include/cam_cpas_api.h
  6. 77 5
      drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c
  7. 2 0
      drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h
  8. 2 0
      drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c
  9. 3 1
      drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.h
  10. 11 2
      drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe170.h
  11. 9 0
      drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175_130.h
  12. 43 0
      drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c
  13. 43 52
      drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c
  14. 71 1
      drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_lite_ver2.c
  15. 65 3
      drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_lite_ver3.c
  16. 66 1
      drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c
  17. 67 1
      drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c
  18. 113 2
      drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_rdi.c
  19. 10 1
      drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_rdi.h
  20. 26 2
      drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c
  21. 17 0
      drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.c

+ 65 - 4
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;

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