Forráskód Böngészése

msm: camera: isp: Add mechanism to verify IRQ lines

IRQ line verification can now be triggerred from IFE HW manager by
writing to a debugfs file as follows:
    echo 1 > /d/camera/ife/test_irq_line

IRQ line verification can also be done at probe if
CONFIG_CAM_TEST_IRQ_LINE_AT_PROBE is set to true during compilation.
Both debugfs and probe-time verifications are only active if
CONFIG_CAM_TEST_IRQ_LINE is set to true during compilation.

CRs-Fixed: 3071027
Change-Id: I0f756ae76d366c254b4af64adf60fe6be7a1a2ef
Signed-off-by: Anand Ravi <[email protected]>
Anand Ravi 3 éve
szülő
commit
1ff6fd9371
28 módosított fájl, 561 hozzáadás és 150 törlés
  1. 2 0
      drivers/cam_core/cam_hw_intf.h
  2. 99 0
      drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c
  3. 167 16
      drivers/cam_isp/isp_hw_mgr/hw_utils/irq_controller/cam_irq_controller.c
  4. 30 2
      drivers/cam_isp/isp_hw_mgr/hw_utils/irq_controller/cam_irq_controller.h
  5. 8 4
      drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid680.h
  6. 8 4
      drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid780.h
  7. 39 13
      drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_hw_ver2.c
  8. 8 4
      drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_lite680.h
  9. 8 4
      drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_lite780.h
  10. 20 16
      drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/cam_sfe680.h
  11. 18 13
      drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/cam_sfe780.h
  12. 31 0
      drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/cam_sfe_core.c
  13. 1 0
      drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/cam_sfe_core.h
  14. 1 0
      drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/cam_sfe_dev.c
  15. 29 0
      drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c
  16. 1 0
      drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.h
  17. 1 0
      drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_dev.c
  18. 8 8
      drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe170.h
  19. 8 8
      drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe170_150.h
  20. 8 8
      drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175.h
  21. 13 13
      drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175_130.h
  22. 9 9
      drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe480.h
  23. 8 4
      drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe680.h
  24. 8 4
      drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe780.h
  25. 8 8
      drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe_lite17x.h
  26. 4 4
      drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe_lite48x.h
  27. 8 4
      drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe_lite68x.h
  28. 8 4
      drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe_lite78x.h

+ 2 - 0
drivers/cam_core/cam_hw_intf.h

@@ -38,6 +38,7 @@ enum cam_clk_bw_state {
  * @write:                 Function pointer for Write hardware registers
  * @process_cmd:           Function pointer for additional hardware controls
  * @flush_cmd:             Function pointer for flush requests
+ * @test_irq_line:         Function pointer for testing irq line
  *
  */
 struct cam_hw_ops {
@@ -65,6 +66,7 @@ struct cam_hw_ops {
 		uint32_t cmd_type, void *cmd_args, uint32_t arg_size);
 	int (*flush)(void *hw_priv,
 		void *flush_args, uint32_t arg_size);
+	int (*test_irq_line)(void *hw_priv);
 };
 
 /**

+ 99 - 0
drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c

@@ -13058,6 +13058,102 @@ DEFINE_DEBUGFS_ATTRIBUTE(cam_ife_csid_rx_capture_debug,
 	cam_ife_get_csid_rx_pkt_capture_debug,
 	cam_ife_set_csid_rx_pkt_capture_debug, "%16llu");
 
+#ifdef CONFIG_CAM_TEST_IRQ_LINE
+static int __cam_ife_mgr_test_irq_line(struct cam_hw_intf *hw_intf, int *n_intf, int *n_success,
+	const char *hw_name, int idx)
+{
+	int rc = -EINVAL;
+
+	if (!hw_intf) {
+		CAM_ERR(CAM_ISP, "%s:%d hw-intf is null", hw_name, idx);
+		return -EINVAL;
+	}
+
+	(*n_intf)++;
+
+	if (hw_intf->hw_ops.test_irq_line)
+		rc = hw_intf->hw_ops.test_irq_line(hw_intf->hw_priv);
+
+	if (!rc) {
+		(*n_success)++;
+		CAM_INFO(CAM_ISP, "%s:%u IRQ line verified successfully", hw_name, hw_intf->hw_idx);
+	} else {
+		CAM_ERR(CAM_ISP, "%s:%u failed to verify IRQ line", hw_name, hw_intf->hw_idx);
+	}
+
+	return rc;
+}
+
+static int cam_ife_mgr_test_irq_lines(struct cam_ife_hw_mgr *hw_mgr)
+{
+	int i, rc, n_intf = 0, n_success = 0;
+
+	for (i = 0; i < CAM_IFE_CSID_HW_NUM_MAX; i++) {
+		if (hw_mgr->csid_devices[i]) {
+			rc = __cam_ife_mgr_test_irq_line(hw_mgr->csid_devices[i], &n_intf,
+				&n_success, "CSID", i);
+		}
+	}
+
+	for (i = 0; i < CAM_IFE_HW_NUM_MAX; i++) {
+		if (hw_mgr->ife_devices[i] && hw_mgr->ife_devices[i]->hw_intf) {
+			rc = __cam_ife_mgr_test_irq_line(hw_mgr->ife_devices[i]->hw_intf, &n_intf,
+				&n_success, "IFE", i);
+		}
+	}
+
+	for (i = 0; i < CAM_SFE_HW_NUM_MAX; i++) {
+		if (hw_mgr->sfe_devices[i] && hw_mgr->sfe_devices[i]->hw_intf) {
+			rc = __cam_ife_mgr_test_irq_line(hw_mgr->sfe_devices[i]->hw_intf, &n_intf,
+				&n_success, "SFE", i);
+		}
+	}
+
+	if (n_intf) {
+		if (n_intf == n_success)
+			CAM_INFO(CAM_ISP, "verified IRQ lines for all %d hw-intf", n_intf);
+		else
+			CAM_ERR(CAM_ISP, "verified %d/%d IRQ lines", n_success, n_intf);
+	} else {
+		CAM_ERR(CAM_ISP, "no valid hw-intf to test IRQ lines");
+	}
+
+	return 0;
+}
+#else
+static int cam_ife_mgr_test_irq_lines(struct cam_ife_hw_mgr *hw_mgr)
+{
+	return 0;
+}
+#endif
+
+#if (defined(CONFIG_CAM_TEST_IRQ_LINE) && defined(CONFIG_CAM_TEST_IRQ_LINE_AT_PROBE))
+static int cam_ife_mgr_test_irq_lines_at_probe(struct cam_ife_hw_mgr *hw_mgr)
+{
+	return cam_ife_mgr_test_irq_lines(hw_mgr);
+}
+#else
+static int cam_ife_mgr_test_irq_lines_at_probe(struct cam_ife_hw_mgr *hw_mgr)
+{
+	return 0;
+}
+#endif
+
+static int cam_isp_set_test_irq_line(void *data, u64 val)
+{
+	cam_ife_mgr_test_irq_lines(&g_ife_hw_mgr);
+	return 0;
+}
+
+static int cam_isp_get_test_irq_line(void *data, u64 *val)
+{
+	*val = 0;
+	return 0;
+}
+
+DEFINE_DEBUGFS_ATTRIBUTE(cam_isp_test_irq_line, cam_isp_get_test_irq_line,
+	cam_isp_set_test_irq_line, "%16llu");
+
 static int cam_ife_hw_mgr_debug_register(void)
 {
 	int rc = 0;
@@ -13104,6 +13200,8 @@ static int cam_ife_hw_mgr_debug_register(void)
 		&g_ife_hw_mgr.debug_cfg.disable_ife_mmu_prefetch);
 	debugfs_create_file("sfe_cache_debug", 0644,
 		g_ife_hw_mgr.debug_cfg.dentry, NULL, &cam_ife_sfe_cache_debug);
+	dbgfileptr = debugfs_create_file("test_irq_line", 0644,
+		g_ife_hw_mgr.debug_cfg.dentry, NULL, &cam_isp_test_irq_line);
 end:
 	g_ife_hw_mgr.debug_cfg.enable_csid_recovery = 1;
 	return rc;
@@ -13495,6 +13593,7 @@ int cam_ife_hw_mgr_init(struct cam_hw_mgr_intf *hw_mgr_intf, int *iommu_hdl)
 	cam_ife_mgr_count_ife();
 	cam_common_register_mini_dump_cb(cam_ife_hw_mgr_mini_dump_cb,
 		"CAM_ISP");
+	cam_ife_mgr_test_irq_lines_at_probe(&g_ife_hw_mgr);
 
 	CAM_DBG(CAM_ISP, "Exit");
 

+ 167 - 16
drivers/cam_isp/isp_hw_mgr/hw_utils/irq_controller/cam_irq_controller.c

@@ -13,6 +13,8 @@
 #include "cam_debug_util.h"
 #include "cam_common_util.h"
 
+#define CAM_IRQ_LINE_TEST_TIMEOUT_MS 1000
+
 /**
  * struct cam_irq_evt_handler:
  * @Brief:                  Event handler information
@@ -56,6 +58,9 @@ struct cam_irq_evt_handler {
  * @mask_reg_offset:        Offset of IRQ MASK register
  * @clear_reg_offset:       Offset of IRQ CLEAR register
  * @status_reg_offset:      Offset of IRQ STATUS register
+ * @set_reg_offset:         Offset of IRQ SET register
+ * @test_set_val:           Value to write to IRQ SET register to trigger IRQ
+ * @test_sub_val:           Value to write to IRQ MASK register to receive test IRQ
  * @top_half_enable_mask:   Array of enabled bit_mask sorted by priority
  * @aggr_mask:              Aggregate mask to keep track of the overall mask
  *                          after subscribe/unsubscribe calls
@@ -67,6 +72,9 @@ struct cam_irq_register_obj {
 	uint32_t                     mask_reg_offset;
 	uint32_t                     clear_reg_offset;
 	uint32_t                     status_reg_offset;
+	uint32_t                     set_reg_offset;
+	uint32_t                     test_set_val;
+	uint32_t                     test_sub_val;
 	uint32_t                     top_half_enable_mask[CAM_IRQ_PRIORITY_MAX];
 	uint32_t                     aggr_mask;
 	uint32_t                     dependent_read_mask[CAM_IRQ_MAX_DEPENDENTS];
@@ -84,11 +92,13 @@ struct cam_irq_register_obj {
  * @irq_register_arr:       Array of Register object associated with this
  *                          Controller
  * @irq_status_arr:         Array of IRQ Status values
- * @global_clear_offset:    Offset of Global IRQ Clear register. This register
+ * @global_irq_cmd_offset:  Offset of Global IRQ Clear register. This register
  *                          contains the BIT that needs to be set for the CLEAR
  *                          to take effect
- * @global_clear_bitmask:   Bitmask needed to be used in Global Clear register
+ * @global_clear_bitmask:   Bitmask needed to be used in Global IRQ command register
  *                          for Clear IRQ cmd to take effect
+ * @global_set_bitmask:     Bitmask needed to be used in Global IRQ command register
+ *                          for Set IRQ cmd to take effect
  * @clear_all_bitmask:      Bitmask that specifies which bits should be written to clear register
  *                          when it is to be cleared forcefully
  * @evt_handler_list_head:  List of all event handlers
@@ -109,8 +119,9 @@ struct cam_irq_controller {
 	uint32_t                        num_registers;
 	struct cam_irq_register_obj    *irq_register_arr;
 	uint32_t                       *irq_status_arr;
-	uint32_t                        global_clear_offset;
+	uint32_t                        global_irq_cmd_offset;
 	uint32_t                        global_clear_bitmask;
+	uint32_t                        global_set_bitmask;
 	uint32_t                        clear_all_bitmask;
 	struct list_head                evt_handler_list_head;
 	struct list_head                th_list_head[CAM_IRQ_PRIORITY_MAX];
@@ -263,9 +274,9 @@ int cam_irq_controller_register_dependent(void *primary_controller, void *second
 
 	/**
 	 * NOTE: For dependent controllers that should not issue global clear command,
-	 * set their global_clear_offset to 0
+	 * set their global_irq_cmd_offset to 0
 	 */
-	if (!ctrl_secondary->global_clear_offset)
+	if (!ctrl_secondary->global_irq_cmd_offset)
 		ctrl_primary->delayed_global_clear = true;
 
 	CAM_DBG(CAM_IRQ_CTRL, "successfully registered %s as dependent of %s", ctrl_secondary->name,
@@ -293,10 +304,10 @@ static inline void cam_irq_controller_clear_irq(
 				irq_register->clear_reg_offset);
 	}
 
-	if (controller->global_clear_offset)
+	if (controller->global_irq_cmd_offset)
 		cam_io_w_mb(controller->global_clear_bitmask,
 				controller->mem_base +
-				controller->global_clear_offset);
+				controller->global_irq_cmd_offset);
 }
 
 int cam_irq_controller_deinit(void **irq_controller)
@@ -387,24 +398,33 @@ int cam_irq_controller_init(const char       *name,
 			register_info->irq_reg_set[i].clear_reg_offset;
 		controller->irq_register_arr[i].status_reg_offset =
 			register_info->irq_reg_set[i].status_reg_offset;
+		controller->irq_register_arr[i].set_reg_offset =
+			register_info->irq_reg_set[i].set_reg_offset;
+		controller->irq_register_arr[i].test_set_val =
+			register_info->irq_reg_set[i].test_set_val;
+		controller->irq_register_arr[i].test_sub_val =
+			register_info->irq_reg_set[i].test_sub_val;
 		CAM_DBG(CAM_IRQ_CTRL, "i %d mask_reg_offset: 0x%x", i,
 			controller->irq_register_arr[i].mask_reg_offset);
 		CAM_DBG(CAM_IRQ_CTRL, "i %d clear_reg_offset: 0x%x", i,
 			controller->irq_register_arr[i].clear_reg_offset);
 		CAM_DBG(CAM_IRQ_CTRL, "i %d status_reg_offset: 0x%x", i,
 			controller->irq_register_arr[i].status_reg_offset);
+		CAM_DBG(CAM_IRQ_CTRL, "i %d set_reg_offset: 0x%x", i,
+			controller->irq_register_arr[i].set_reg_offset);
 	}
 	controller->num_registers        = register_info->num_registers;
 	controller->global_clear_bitmask = register_info->global_clear_bitmask;
-	controller->global_clear_offset  = register_info->global_clear_offset;
+	controller->global_irq_cmd_offset  = register_info->global_irq_cmd_offset;
+	controller->global_set_bitmask   = register_info->global_set_bitmask;
 	controller->clear_all_bitmask    = register_info->clear_all_bitmask;
 	controller->mem_base             = mem_base;
 	controller->is_dependent         = false;
 
 	CAM_DBG(CAM_IRQ_CTRL, "global_clear_bitmask: 0x%x",
 		controller->global_clear_bitmask);
-	CAM_DBG(CAM_IRQ_CTRL, "global_clear_offset: 0x%x",
-		controller->global_clear_offset);
+	CAM_DBG(CAM_IRQ_CTRL, "global_irq_cmd_offset: 0x%x",
+		controller->global_irq_cmd_offset);
 	CAM_DBG(CAM_IRQ_CTRL, "mem_base: %pK",
 		(void __iomem *)controller->mem_base);
 
@@ -813,9 +833,9 @@ void cam_irq_controller_disable_all(void *priv)
 			irq_register->clear_reg_offset);
 	}
 
-	if (controller->global_clear_offset && !controller->delayed_global_clear) {
+	if (controller->global_irq_cmd_offset && !controller->delayed_global_clear) {
 		cam_io_w_mb(controller->global_clear_bitmask,
-			controller->mem_base + controller->global_clear_offset);
+			controller->mem_base + controller->global_irq_cmd_offset);
 		CAM_DBG(CAM_IRQ_CTRL, "Global Clear done from %s",
 			controller->name);
 	}
@@ -846,9 +866,9 @@ static void __cam_irq_controller_read_registers(struct cam_irq_controller *contr
 			controller->mem_base + irq_register->clear_reg_offset);
 	}
 
-	if (controller->global_clear_offset && !controller->delayed_global_clear) {
+	if (controller->global_irq_cmd_offset && !controller->delayed_global_clear) {
 		cam_io_w_mb(controller->global_clear_bitmask,
-			controller->mem_base + controller->global_clear_offset);
+			controller->mem_base + controller->global_irq_cmd_offset);
 		CAM_DBG(CAM_IRQ_CTRL, "Global Clear done from %s",
 			controller->name);
 	}
@@ -884,9 +904,9 @@ static void cam_irq_controller_read_registers(struct cam_irq_controller *control
 		}
 	}
 
-	if (controller->global_clear_offset && controller->delayed_global_clear) {
+	if (controller->global_irq_cmd_offset && controller->delayed_global_clear) {
 		cam_io_w_mb(controller->global_clear_bitmask,
-			controller->mem_base + controller->global_clear_offset);
+			controller->mem_base + controller->global_irq_cmd_offset);
 		CAM_DBG(CAM_IRQ_CTRL, "Delayed Global Clear done from %s",
 			controller->name);
 	}
@@ -979,3 +999,134 @@ end:
 
 	return rc;
 }
+
+#ifdef CONFIG_CAM_TEST_IRQ_LINE
+
+struct cam_irq_line_test_priv {
+	char msg[256];
+	struct completion complete;
+};
+
+static int cam_irq_controller_test_irq_line_top_half(uint32_t evt_id,
+	struct cam_irq_th_payload *th_payload)
+{
+	struct cam_irq_line_test_priv *test_priv;
+
+	if (!th_payload || !th_payload->handler_priv) {
+		CAM_ERR(CAM_IRQ_CTRL, "invalid payload");
+		return -EINVAL;
+	}
+
+	test_priv = th_payload->handler_priv;
+	complete(&test_priv->complete);
+	CAM_DBG(CAM_IRQ_CTRL, "%s IRQ line verified", test_priv->msg);
+
+	return 0;
+}
+
+
+int cam_irq_controller_test_irq_line(void *irq_controller, const char *fmt, ...)
+{
+	struct cam_irq_controller *controller = irq_controller;
+	struct cam_irq_register_obj *irq_reg;
+	struct cam_irq_line_test_priv *test_priv;
+	uint32_t *mask = NULL;
+	va_list args;
+	bool can_test = false;
+	int rc = 0, i, handle;
+
+	if (!irq_controller) {
+		CAM_ERR(CAM_IRQ_CTRL, "invalid argument");
+		return -EINVAL;
+	}
+
+	for (i = 0; i < controller->num_registers; i++) {
+		irq_reg = &controller->irq_register_arr[i];
+		if (irq_reg->set_reg_offset != 0 && irq_reg->test_set_val != 0 &&
+			irq_reg->test_sub_val)
+			can_test = true;
+		CAM_DBG(CAM_IRQ_CTRL, "[%d] offset:0x%x val:0x%x can-test:%s",
+			i, irq_reg->set_reg_offset, irq_reg->test_set_val,
+			CAM_BOOL_TO_YESNO(can_test));
+	}
+
+	if (controller->global_irq_cmd_offset == 0 || controller->global_set_bitmask == 0)
+		can_test = false;
+
+	CAM_DBG(CAM_IRQ_CTRL, "global offset:0x%x mask:0x%x",
+			controller->global_irq_cmd_offset,
+			controller->global_set_bitmask);
+
+	if (!can_test) {
+		CAM_ERR(CAM_IRQ_CTRL, "%s not configured properly for testing",
+			controller->name);
+		return -EINVAL;
+	}
+
+	mask = kcalloc(controller->num_registers, sizeof(uint32_t), GFP_KERNEL);
+	if (!mask) {
+		CAM_ERR(CAM_IRQ_CTRL, "%s: cannot allocate mask array of length %d",
+			controller->name, controller->num_registers);
+		return -ENOMEM;
+	}
+
+	for (i = 0; i < controller->num_registers; i++)
+		mask[i] = controller->irq_register_arr[i].test_sub_val;
+
+	test_priv = kzalloc(sizeof(struct cam_irq_line_test_priv), GFP_KERNEL);
+	if (!test_priv) {
+		CAM_ERR(CAM_IRQ_CTRL, "%s: cannot allocate test-priv", controller->name);
+		rc = -ENOMEM;
+		goto kfree_exit;
+	}
+
+	va_start(args, fmt);
+	vscnprintf(test_priv->msg, 256, fmt, args);
+	va_end(args);
+
+	init_completion(&test_priv->complete);
+
+	handle = cam_irq_controller_subscribe_irq(controller, CAM_IRQ_PRIORITY_0,
+		mask, test_priv, cam_irq_controller_test_irq_line_top_half,
+		NULL, NULL, NULL, CAM_IRQ_EVT_GROUP_0);
+	if (handle < 0) {
+		CAM_ERR(CAM_IRQ_CTRL, "%s: failed to subscribe to test irq line",
+			controller->name);
+		rc = -EINVAL;
+		goto kfree_exit;
+	}
+
+	for (i = 0; i < controller->num_registers; i++) {
+		irq_reg = &controller->irq_register_arr[i];
+		if (irq_reg->test_set_val && irq_reg->set_reg_offset) {
+			cam_io_w_mb(irq_reg->test_set_val,
+				controller->mem_base + irq_reg->set_reg_offset);
+			CAM_DBG(CAM_IRQ_CTRL, "%s[%d] offset:0x%08x val:0x%08x", controller->name,
+				i, irq_reg->set_reg_offset, irq_reg->test_set_val);
+		}
+	}
+
+	cam_io_w_mb(controller->global_set_bitmask,
+		controller->mem_base + controller->global_irq_cmd_offset);
+	CAM_DBG(CAM_IRQ_CTRL, "%s[SET-CMD] addr:0x%08x value:0x%08x", controller->name,
+		controller->mem_base + controller->global_irq_cmd_offset,
+		controller->global_set_bitmask);
+
+	if (!cam_common_wait_for_completion_timeout(&test_priv->complete,
+		msecs_to_jiffies(CAM_IRQ_LINE_TEST_TIMEOUT_MS))) {
+		CAM_ERR(CAM_IRQ_CTRL, "%s: IRQ line verification timed out", controller->name);
+		rc = -ETIMEDOUT;
+		goto unsub_exit;
+	}
+
+	CAM_DBG(CAM_IRQ_CTRL, "%s: verified IRQ line successfully", controller->name);
+
+unsub_exit:
+	cam_irq_controller_unsubscribe_irq(controller, handle);
+kfree_exit:
+	kfree(mask);
+	kfree(test_priv);
+	return rc;
+}
+
+#endif

+ 30 - 2
drivers/cam_isp/isp_hw_mgr/hw_utils/irq_controller/cam_irq_controller.h

@@ -48,11 +48,17 @@ enum cam_irq_event_group {
  * @mask_reg_offset:        Offset of IRQ MASK register
  * @clear_reg_offset:       Offset of IRQ CLEAR register
  * @status_reg_offset:      Offset of IRQ STATUS register
+ * @set_reg_offset:         Offset of IRQ SET register
+ * @test_set_val:           Value to write to IRQ SET register to trigger IRQ
+ * @test_sub_val:           Value to write to IRQ MASK register to receive test IRQ
  */
 struct cam_irq_register_set {
 	uint32_t                       mask_reg_offset;
 	uint32_t                       clear_reg_offset;
 	uint32_t                       status_reg_offset;
+	uint32_t                       set_reg_offset;
+	uint32_t                       test_set_val;
+	uint32_t                       test_sub_val;
 };
 
 /*
@@ -62,19 +68,22 @@ struct cam_irq_register_set {
  * @num_registers:          Number of sets(mask/clear/status) of IRQ registers
  * @irq_reg_set:            Array of Register Set Offsets.
  *                          Length of array = num_registers
- * @global_clear_offset:    Offset of Global IRQ Clear register. This register
+ * @global_irq_cmd_offset:  Offset of Global IRQ Clear register. This register
  *                          contains the BIT that needs to be set for the CLEAR
  *                          to take effect
  * @global_clear_bitmask:   Bitmask needed to be used in Global Clear register
  *                          for Clear IRQ cmd to take effect
+ * @global_set_bitmask:     Bitmask needed to be used in Global IRQ command register
+ *                          for Set IRQ cmd to take effect
  * @clear_all_bitmask:      Bitmask that specifies which bits should be written
  *                          to clear register when it is to be cleared forcefully
  */
 struct cam_irq_controller_reg_info {
 	uint32_t                      num_registers;
 	struct cam_irq_register_set  *irq_reg_set;
-	uint32_t                      global_clear_offset;
+	uint32_t                      global_irq_cmd_offset;
 	uint32_t                      global_clear_bitmask;
+	uint32_t                      global_set_bitmask;
 	uint32_t                      clear_all_bitmask;
 };
 
@@ -333,4 +342,23 @@ int cam_irq_controller_register_dependent(void *primary_controller, void *second
  */
 int cam_irq_controller_unregister_dependent(void *primary_controller, void *secondary_controller);
 
+/**
+ * cam_irq_controller_test_irq_line()
+ * @brief: Test IRQ line corresponding to IRQ controller
+ *
+ * @irq_controller: IRQ controller under test
+ * @fmt:            Format of the debug message to be printed
+ * @args:           Arguments for the format specifiers corresponding to @fmt
+ *
+ * @return:         0: success, negative: failure
+ */
+#ifdef CONFIG_CAM_TEST_IRQ_LINE
+int cam_irq_controller_test_irq_line(void *irq_controller, const char *fmt, ...);
+#else
+static inline int cam_irq_controller_test_irq_line(void *irq_controller, const char *fmt, ...)
+{
+	return -EPERM;
+}
+#endif
+
 #endif /* _CAM_IRQ_CONTROLLER_H_ */

+ 8 - 4
drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid680.h

@@ -254,6 +254,9 @@ static struct cam_irq_register_set cam_ife_csid_680_irq_reg_set[9] = {
 		.mask_reg_offset   = 0x00000080,
 		.clear_reg_offset  = 0x00000084,
 		.status_reg_offset = 0x0000007C,
+		.set_reg_offset    = 0x00000088,
+		.test_set_val      = BIT(0),
+		.test_sub_val      = BIT(0),
 	},
 	/* RX */
 	{
@@ -308,9 +311,10 @@ static struct cam_irq_register_set cam_ife_csid_680_irq_reg_set[9] = {
 static struct cam_irq_controller_reg_info cam_ife_csid_680_irq_reg_info = {
 	.num_registers = 9,
 	.irq_reg_set = cam_ife_csid_680_irq_reg_set,
-	.global_clear_offset  = 0x00000014,
-	.global_clear_bitmask = 0x00000001,
-	.clear_all_bitmask = 0xFFFFFFFF,
+	.global_irq_cmd_offset = 0x00000014,
+	.global_clear_bitmask  = 0x00000001,
+	.global_set_bitmask    = 0x00000010,
+	.clear_all_bitmask     = 0xFFFFFFFF,
 };
 
 static struct cam_irq_register_set cam_ife_csid_680_buf_done_irq_reg_set[1] = {
@@ -324,7 +328,7 @@ static struct cam_irq_register_set cam_ife_csid_680_buf_done_irq_reg_set[1] = {
 static struct cam_irq_controller_reg_info cam_ife_csid_680_buf_done_irq_reg_info = {
 	.num_registers = 1,
 	.irq_reg_set = cam_ife_csid_680_buf_done_irq_reg_set,
-	.global_clear_offset  = 0, /* intentionally set to zero */
+	.global_irq_cmd_offset  = 0, /* intentionally set to zero */
 };
 
 static struct cam_ife_csid_ver2_path_reg_info

+ 8 - 4
drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid780.h

@@ -284,6 +284,9 @@ static struct cam_irq_register_set cam_ife_csid_780_irq_reg_set[9] = {
 		.mask_reg_offset   = 0x00000080,
 		.clear_reg_offset  = 0x00000084,
 		.status_reg_offset = 0x0000007C,
+		.set_reg_offset    = 0x00000088,
+		.test_set_val      = BIT(0),
+		.test_sub_val      = BIT(0),
 	},
 	/* RX */
 	{
@@ -338,9 +341,10 @@ static struct cam_irq_register_set cam_ife_csid_780_irq_reg_set[9] = {
 static struct cam_irq_controller_reg_info cam_ife_csid_780_irq_reg_info = {
 	.num_registers = 9,
 	.irq_reg_set = cam_ife_csid_780_irq_reg_set,
-	.global_clear_offset  = 0x00000014,
-	.global_clear_bitmask = 0x00000001,
-	.clear_all_bitmask = 0xFFFFFFFF,
+	.global_irq_cmd_offset = 0x00000014,
+	.global_clear_bitmask  = 0x00000001,
+	.global_set_bitmask    = 0x00000010,
+	.clear_all_bitmask     = 0xFFFFFFFF,
 };
 
 static struct cam_irq_register_set cam_ife_csid_780_buf_done_irq_reg_set[1] = {
@@ -355,7 +359,7 @@ static struct cam_irq_controller_reg_info
 	cam_ife_csid_780_buf_done_irq_reg_info = {
 	.num_registers = 1,
 	.irq_reg_set = cam_ife_csid_780_buf_done_irq_reg_set,
-	.global_clear_offset  = 0, /* intentionally set to zero */
+	.global_irq_cmd_offset  = 0, /* intentionally set to zero */
 };
 
 static struct cam_ife_csid_ver2_path_reg_info

+ 39 - 13
drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_hw_ver2.c

@@ -5462,6 +5462,33 @@ static int cam_ife_csid_hw_init_irq(
 	return rc;
 }
 
+int cam_ife_csid_ver2_irq_line_test(void *hw_priv)
+{
+	struct cam_ife_csid_ver2_hw *csid_hw;
+	struct cam_hw_soc_info *soc_info;
+	int rc = 0;
+
+	if (!hw_priv) {
+		CAM_ERR(CAM_ISP, "CSID: Invalid args");
+		return -EINVAL;
+	}
+
+	csid_hw = ((struct cam_hw_info *)hw_priv)->core_info;
+	soc_info = &csid_hw->hw_info->soc_info;
+
+	rc = cam_ife_csid_enable_soc_resources(soc_info, CAM_LOWSVS_VOTE);
+	if (rc) {
+		CAM_ERR(CAM_ISP, "CSID[%d] Enable soc failed", csid_hw->hw_intf->hw_idx);
+		return rc;
+	}
+
+	rc = cam_irq_controller_test_irq_line(csid_hw->csid_irq_controller, "CSID:%d",
+		csid_hw->hw_intf->hw_idx);
+
+	cam_ife_csid_disable_soc_resources(soc_info);
+	return rc;
+}
+
 int cam_ife_csid_hw_ver2_init(struct cam_hw_intf *hw_intf,
 	struct cam_ife_csid_core_info *core_info,
 	bool is_custom)
@@ -5514,19 +5541,18 @@ int cam_ife_csid_hw_ver2_init(struct cam_hw_intf *hw_intf,
 		CAM_CPAS_HW_IDX_ANY, NULL))
 		csid_hw->flags.binning_enabled = true;
 
-	csid_hw->hw_intf->hw_ops.get_hw_caps =
-						cam_ife_csid_ver2_get_hw_caps;
-	csid_hw->hw_intf->hw_ops.init        = cam_ife_csid_ver2_init_hw;
-	csid_hw->hw_intf->hw_ops.deinit      = cam_ife_csid_ver2_deinit_hw;
-	csid_hw->hw_intf->hw_ops.reset       = cam_ife_csid_ver2_reset;
-	csid_hw->hw_intf->hw_ops.reserve     = cam_ife_csid_ver2_reserve;
-	csid_hw->hw_intf->hw_ops.release     = cam_ife_csid_ver2_release;
-	csid_hw->hw_intf->hw_ops.start       = cam_ife_csid_ver2_start;
-	csid_hw->hw_intf->hw_ops.stop        = cam_ife_csid_ver2_stop;
-	csid_hw->hw_intf->hw_ops.read        = cam_ife_csid_ver2_read;
-	csid_hw->hw_intf->hw_ops.write       = cam_ife_csid_ver2_write;
-	csid_hw->hw_intf->hw_ops.process_cmd =
-						cam_ife_csid_ver2_process_cmd;
+	csid_hw->hw_intf->hw_ops.get_hw_caps   = cam_ife_csid_ver2_get_hw_caps;
+	csid_hw->hw_intf->hw_ops.init          = cam_ife_csid_ver2_init_hw;
+	csid_hw->hw_intf->hw_ops.deinit        = cam_ife_csid_ver2_deinit_hw;
+	csid_hw->hw_intf->hw_ops.reset         = cam_ife_csid_ver2_reset;
+	csid_hw->hw_intf->hw_ops.reserve       = cam_ife_csid_ver2_reserve;
+	csid_hw->hw_intf->hw_ops.release       = cam_ife_csid_ver2_release;
+	csid_hw->hw_intf->hw_ops.start         = cam_ife_csid_ver2_start;
+	csid_hw->hw_intf->hw_ops.stop          = cam_ife_csid_ver2_stop;
+	csid_hw->hw_intf->hw_ops.read          = cam_ife_csid_ver2_read;
+	csid_hw->hw_intf->hw_ops.write         = cam_ife_csid_ver2_write;
+	csid_hw->hw_intf->hw_ops.process_cmd   = cam_ife_csid_ver2_process_cmd;
+	csid_hw->hw_intf->hw_ops.test_irq_line = cam_ife_csid_ver2_irq_line_test;
 
 	rc = cam_ife_csid_hw_init_irq(csid_hw);
 

+ 8 - 4
drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_lite680.h

@@ -249,6 +249,9 @@ static struct cam_irq_register_set cam_ife_csid_lite_680_irq_reg_set[7] = {
 		.mask_reg_offset   = 0x00000080,
 		.clear_reg_offset  = 0x00000084,
 		.status_reg_offset = 0x0000007C,
+		.set_reg_offset    = 0x00000088,
+		.test_set_val      = BIT(0),
+		.test_sub_val      = BIT(0),
 	},
 	/* RX */
 	{
@@ -291,9 +294,10 @@ static struct cam_irq_register_set cam_ife_csid_lite_680_irq_reg_set[7] = {
 static struct cam_irq_controller_reg_info cam_ife_csid_lite_680_irq_reg_info = {
 	.num_registers = 7,
 	.irq_reg_set = cam_ife_csid_lite_680_irq_reg_set,
-	.global_clear_offset  = 0x00000014,
-	.global_clear_bitmask = 0x00000001,
-	.clear_all_bitmask = 0xFFFFFFFF,
+	.global_irq_cmd_offset = 0x00000014,
+	.global_clear_bitmask  = 0x00000001,
+	.global_set_bitmask    = 0x00000010,
+	.clear_all_bitmask     = 0xFFFFFFFF,
 };
 
 static struct cam_irq_register_set cam_ife_csid_lite_680_buf_done_irq_reg_set[1] = {
@@ -308,7 +312,7 @@ static struct cam_irq_controller_reg_info
 	cam_ife_csid_lite_680_buf_done_irq_reg_info = {
 	.num_registers = 1,
 	.irq_reg_set = cam_ife_csid_lite_680_buf_done_irq_reg_set,
-	.global_clear_offset  = 0, /* intentionally set to zero */
+	.global_irq_cmd_offset  = 0, /* intentionally set to zero */
 };
 
 static struct cam_ife_csid_ver2_common_reg_info

+ 8 - 4
drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_lite780.h

@@ -280,6 +280,9 @@ static struct cam_irq_register_set cam_ife_csid_lite_780_irq_reg_set[7] = {
 		.mask_reg_offset   = 0x00000080,
 		.clear_reg_offset  = 0x00000084,
 		.status_reg_offset = 0x0000007C,
+		.set_reg_offset    = 0x00000088,
+		.test_set_val      = BIT(0),
+		.test_sub_val      = BIT(0),
 	},
 	/* RX */
 	{
@@ -322,9 +325,10 @@ static struct cam_irq_register_set cam_ife_csid_lite_780_irq_reg_set[7] = {
 static struct cam_irq_controller_reg_info cam_ife_csid_lite_780_irq_reg_info = {
 	.num_registers = 7,
 	.irq_reg_set = cam_ife_csid_lite_780_irq_reg_set,
-	.global_clear_offset  = 0x00000014,
-	.global_clear_bitmask = 0x00000001,
-	.clear_all_bitmask = 0xFFFFFFFF,
+	.global_irq_cmd_offset = 0x00000014,
+	.global_clear_bitmask  = 0x00000001,
+	.global_set_bitmask    = 0x00000010,
+	.clear_all_bitmask     = 0xFFFFFFFF,
 };
 
 static struct cam_irq_register_set cam_ife_csid_lite_780_buf_done_irq_reg_set[1] = {
@@ -339,7 +343,7 @@ static struct cam_irq_controller_reg_info
 	cam_ife_csid_lite_780_buf_done_irq_reg_info = {
 	.num_registers = 1,
 	.irq_reg_set = cam_ife_csid_lite_780_buf_done_irq_reg_set,
-	.global_clear_offset  = 0, /* intentionally set to zero */
+	.global_irq_cmd_offset  = 0, /* intentionally set to zero */
 };
 
 static struct cam_ife_csid_ver2_common_reg_info

+ 20 - 16
drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/cam_sfe680.h

@@ -434,11 +434,11 @@ static struct cam_sfe_bus_rd_hw_info sfe680_bus_rd_hw_info = {
 		.security_cfg                 = 0x00000420,
 		.cons_violation_status        = 0x00000434,
 		.irq_reg_info = {
-			.num_registers     = 1,
-			.irq_reg_set          = sfe680_bus_rd_irq_reg,
-			.global_clear_offset  = 0x0000040C,
-			.global_clear_bitmask = 0x00000001,
-			.clear_all_bitmask = 0xFFFFFFFF,
+			.num_registers = 1,
+			.irq_reg_set = sfe680_bus_rd_irq_reg,
+			.global_irq_cmd_offset = 0x0000040C,
+			.global_clear_bitmask  = 0x00000001,
+			.clear_all_bitmask     = 0xFFFFFFFF,
 		},
 	},
 	.num_client = 3,
@@ -538,11 +538,11 @@ static struct cam_sfe_bus_wr_hw_info sfe680_bus_wr_hw_info = {
 		.test_bus_ctrl                    = 0x000008DC,
 		.top_irq_mask_0                   = 0x00000020,
 		.irq_reg_info = {
-			.num_registers     = 1,
-			.irq_reg_set          = sfe680_bus_wr_irq_reg,
-			.global_clear_offset  = 0x00000830,
-			.global_clear_bitmask = 0x00000001,
-			.clear_all_bitmask = 0xFFFFFFFF,
+			.num_registers = 1,
+			.irq_reg_set = sfe680_bus_wr_irq_reg,
+			.global_irq_cmd_offset = 0x00000830,
+			.global_clear_bitmask  = 0x00000001,
+			.clear_all_bitmask     = 0xFFFFFFFF,
 		},
 	},
 	.num_client = 13,
@@ -1216,18 +1216,22 @@ static struct cam_sfe_bus_wr_hw_info sfe680_bus_wr_hw_info = {
 
 static struct cam_irq_register_set sfe680_top_irq_reg_set[1] = {
 	{
-	.mask_reg_offset   = 0x00000020,
-	.clear_reg_offset  = 0x00000024,
-	.status_reg_offset = 0x00000028,
+		.mask_reg_offset   = 0x00000020,
+		.clear_reg_offset  = 0x00000024,
+		.status_reg_offset = 0x00000028,
+		.set_reg_offset    = 0x0000002C,
+		.test_set_val      = BIT(0),
+		.test_sub_val      = BIT(0),
 	},
 };
 
 static struct cam_irq_controller_reg_info sfe680_top_irq_reg_info = {
 	.num_registers = 1,
 	.irq_reg_set = sfe680_top_irq_reg_set,
-	.global_clear_offset  = 0x0000001C,
-	.global_clear_bitmask = 0x00000001,
-	.clear_all_bitmask = 0xFFFFFFFF,
+	.global_irq_cmd_offset = 0x0000001C,
+	.global_clear_bitmask  = 0x00000001,
+	.global_set_bitmask    = 0x00000010,
+	.clear_all_bitmask     = 0xFFFFFFFF,
 };
 
 struct cam_sfe_hw_info cam_sfe680_hw_info = {

+ 18 - 13
drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/cam_sfe780.h

@@ -680,10 +680,10 @@ static struct cam_sfe_bus_rd_hw_info sfe780_bus_rd_hw_info = {
 		.security_cfg                 = 0x00000420,
 		.cons_violation_status        = 0x00000434,
 		.irq_reg_info = {
-			.num_registers     = 1,
-			.irq_reg_set          = sfe780_bus_rd_irq_reg,
-			.global_clear_offset  = 0x0000040C,
-			.global_clear_bitmask = 0x00000001,
+			.num_registers = 1,
+			.irq_reg_set = sfe780_bus_rd_irq_reg,
+			.global_irq_cmd_offset = 0x0000040C,
+			.global_clear_bitmask  = 0x00000001,
 		},
 	},
 	.num_client = 3,
@@ -780,10 +780,10 @@ static struct cam_sfe_bus_wr_hw_info sfe780_bus_wr_hw_info = {
 		.test_bus_ctrl                    = 0x000008DC,
 		.top_irq_mask_0                   = 0x00000020,
 		.irq_reg_info = {
-			.num_registers     = 1,
-			.irq_reg_set          = sfe780_bus_wr_irq_reg,
-			.global_clear_offset  = 0x00000830,
-			.global_clear_bitmask = 0x00000001,
+			.num_registers = 1,
+			.irq_reg_set = sfe780_bus_wr_irq_reg,
+			.global_irq_cmd_offset = 0x00000830,
+			.global_clear_bitmask  = 0x00000001,
 		},
 	},
 	.num_client = 16,
@@ -1596,17 +1596,22 @@ static struct cam_sfe_bus_wr_hw_info sfe780_bus_wr_hw_info = {
 
 static struct cam_irq_register_set sfe780_top_irq_reg_set[1] = {
 	{
-	.mask_reg_offset   = 0x00000020,
-	.clear_reg_offset  = 0x00000024,
-	.status_reg_offset = 0x00000028,
+		.mask_reg_offset   = 0x00000020,
+		.clear_reg_offset  = 0x00000024,
+		.status_reg_offset = 0x00000028,
+		.set_reg_offset    = 0x0000002C,
+		.test_set_val      = BIT(0),
+		.test_sub_val      = BIT(0),
 	},
 };
 
 static struct cam_irq_controller_reg_info sfe780_top_irq_reg_info = {
 	.num_registers = 1,
 	.irq_reg_set = sfe780_top_irq_reg_set,
-	.global_clear_offset  = 0x0000001C,
-	.global_clear_bitmask = 0x00000001,
+	.global_irq_cmd_offset = 0x0000001C,
+	.global_clear_bitmask  = 0x00000001,
+	.global_set_bitmask    = 0x00000010,
+	.clear_all_bitmask     = 0xFFFFFFFF,
 };
 
 struct cam_sfe_hw_info cam_sfe780_hw_info = {

+ 31 - 0
drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/cam_sfe_core.c

@@ -130,6 +130,37 @@ int cam_sfe_deinit_hw(void *hw_priv, void *deinit_hw_args, uint32_t arg_size)
 	return rc;
 }
 
+int cam_sfe_test_irq_line(void *hw_priv)
+{
+	struct cam_hw_info *sfe_hw = hw_priv;
+	struct cam_sfe_hw_core_info *core_info;
+	int rc;
+
+	if (!hw_priv) {
+		CAM_ERR(CAM_SFE, "Invalid arguments");
+		return -EINVAL;
+	}
+
+	core_info = sfe_hw->core_info;
+
+	rc = cam_sfe_init_hw(sfe_hw, NULL, 0);
+	if (rc) {
+		CAM_ERR(CAM_SFE, "SFE:%d failed to init hw", sfe_hw->soc_info.index);
+		return rc;
+	}
+
+	rc = cam_irq_controller_test_irq_line(core_info->sfe_irq_controller, "SFE:%d",
+		sfe_hw->soc_info.index);
+	if (rc)
+		CAM_ERR(CAM_SFE, "failed to test SFE:%d", sfe_hw->soc_info.index);
+
+	rc = cam_sfe_deinit_hw(sfe_hw, NULL, 0);
+	if (rc)
+		CAM_ERR(CAM_SFE, "SFE:%d failed to deinit hw", sfe_hw->soc_info.index);
+
+	return rc;
+}
+
 int cam_sfe_reserve(void *hw_priv, void *reserve_args, uint32_t arg_size)
 {
 	struct cam_sfe_hw_core_info       *core_info = NULL;

+ 1 - 0
drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/cam_sfe_core.h

@@ -76,6 +76,7 @@ int cam_sfe_stop(void *device_priv,
 	void *stop_args, uint32_t arg_size);
 int cam_sfe_process_cmd(void *device_priv, uint32_t cmd_type,
 	void *cmd_args, uint32_t arg_size);
+int cam_sfe_test_irq_line(void *hw_priv);
 
 irqreturn_t cam_sfe_irq(int irq_num, void *data);
 

+ 1 - 0
drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/cam_sfe_dev.c

@@ -61,6 +61,7 @@ static int cam_sfe_component_bind(struct device *dev,
 	sfe_hw_intf->hw_ops.read = cam_sfe_read;
 	sfe_hw_intf->hw_ops.write = cam_sfe_write;
 	sfe_hw_intf->hw_ops.process_cmd = cam_sfe_process_cmd;
+	sfe_hw_intf->hw_ops.test_irq_line = cam_sfe_test_irq_line;
 	sfe_hw_intf->hw_type = CAM_ISP_HW_TYPE_SFE;
 
 	CAM_DBG(CAM_SFE, "SFE component bind type %d index %d",

+ 29 - 0
drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c

@@ -577,6 +577,35 @@ irqreturn_t cam_vfe_irq(int irq_num, void *data)
 		core_info->vfe_irq_controller, CAM_IRQ_EVT_GROUP_0);
 }
 
+int cam_vfe_test_irq_line(void *hw_priv)
+{
+	struct cam_hw_info *vfe_hw = hw_priv;
+	void *vfe_irq_ctrl;
+	int rc;
+
+	if (!hw_priv) {
+		CAM_ERR(CAM_ISP, "invalid argument");
+		return -EINVAL;
+	}
+
+	vfe_irq_ctrl = ((struct cam_vfe_hw_core_info *)vfe_hw->core_info)->vfe_irq_controller;
+	rc = cam_vfe_init_hw(vfe_hw, NULL, 0);
+	if (rc) {
+		CAM_ERR(CAM_ISP, "VFE:%d failed to init hw", vfe_hw->soc_info.index);
+		return rc;
+	}
+
+	rc = cam_irq_controller_test_irq_line(vfe_irq_ctrl, "VFE:%d", vfe_hw->soc_info.index);
+	if (rc)
+		CAM_ERR(CAM_ISP, "VFE:%d IRQ line test failed", vfe_hw->soc_info.index);
+
+	rc = cam_vfe_deinit_hw(vfe_hw, NULL, 0);
+	if (rc)
+		CAM_ERR(CAM_ISP, "VFE:%d failed to deinit hw", vfe_hw->soc_info.index);
+
+	return rc;
+}
+
 int cam_vfe_core_init(struct cam_vfe_hw_core_info  *core_info,
 	struct cam_hw_soc_info                     *soc_info,
 	struct cam_hw_intf                         *hw_intf,

+ 1 - 0
drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.h

@@ -84,6 +84,7 @@ int cam_vfe_write(void *device_priv,
 	void *write_args, uint32_t arg_size);
 int cam_vfe_process_cmd(void *device_priv, uint32_t cmd_type,
 	void *cmd_args, uint32_t arg_size);
+int cam_vfe_test_irq_line(void *hw_priv);
 
 irqreturn_t cam_vfe_irq(int irq_num, void *data);
 

+ 1 - 0
drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_dev.c

@@ -69,6 +69,7 @@ static int cam_vfe_component_bind(struct device *dev,
 	vfe_hw_intf->hw_ops.read = cam_vfe_read;
 	vfe_hw_intf->hw_ops.write = cam_vfe_write;
 	vfe_hw_intf->hw_ops.process_cmd = cam_vfe_process_cmd;
+	vfe_hw_intf->hw_ops.test_irq_line = cam_vfe_test_irq_line;
 	vfe_hw_intf->hw_type = CAM_ISP_HW_TYPE_VFE;
 
 	CAM_DBG(CAM_ISP, "VFE component bind, type %d index %d",

+ 8 - 8
drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe170.h

@@ -28,9 +28,9 @@ static struct cam_irq_register_set vfe170_top_irq_reg_set[2] = {
 static struct cam_irq_controller_reg_info vfe170_top_irq_reg_info = {
 	.num_registers = 2,
 	.irq_reg_set = vfe170_top_irq_reg_set,
-	.global_clear_offset  = 0x00000058,
-	.global_clear_bitmask = 0x00000001,
-	.clear_all_bitmask = 0xFFFFFFFF,
+	.global_irq_cmd_offset = 0x00000058,
+	.global_clear_bitmask  = 0x00000001,
+	.clear_all_bitmask     = 0xFFFFFFFF,
 };
 
 static struct cam_vfe_camif_ver2_reg vfe170_camif_reg = {
@@ -263,11 +263,11 @@ static struct cam_vfe_bus_ver2_hw_info vfe170_bus_hw_info = {
 		.pwr_iso_cfg                  = 0x000020CC,
 		.dual_master_comp_cfg         = 0x00002028,
 		.irq_reg_info = {
-			.num_registers        = 3,
-			.irq_reg_set          = vfe170_bus_irq_reg,
-			.global_clear_offset  = 0x00002068,
-			.global_clear_bitmask = 0x00000001,
-			.clear_all_bitmask = 0xFFFFFFFF,
+			.num_registers         = 3,
+			.irq_reg_set           = vfe170_bus_irq_reg,
+			.global_irq_cmd_offset = 0x00002068,
+			.global_clear_bitmask  = 0x00000001,
+			.clear_all_bitmask     = 0xFFFFFFFF,
 		},
 		.comp_error_status            = 0x0000206C,
 		.comp_ovrwr_status            = 0x00002070,

+ 8 - 8
drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe170_150.h

@@ -28,9 +28,9 @@ static struct cam_irq_register_set vfe170_150_top_irq_reg_set[2] = {
 static struct cam_irq_controller_reg_info vfe170_150_top_irq_reg_info = {
 	.num_registers = 2,
 	.irq_reg_set = vfe170_150_top_irq_reg_set,
-	.global_clear_offset  = 0x00000058,
-	.global_clear_bitmask = 0x00000001,
-	.clear_all_bitmask = 0xFFFFFFFF,
+	.global_irq_cmd_offset = 0x00000058,
+	.global_clear_bitmask  = 0x00000001,
+	.clear_all_bitmask     = 0xFFFFFFFF,
 };
 
 static struct cam_vfe_camif_ver2_reg vfe170_150_camif_reg = {
@@ -231,11 +231,11 @@ static struct cam_vfe_bus_ver2_hw_info vfe170_150_bus_hw_info = {
 		.pwr_iso_cfg                  = 0x000020CC,
 		.dual_master_comp_cfg         = 0x00002028,
 		.irq_reg_info = {
-			.num_registers        = 3,
-			.irq_reg_set          = vfe170_150_bus_irq_reg,
-			.global_clear_offset  = 0x00002068,
-			.global_clear_bitmask = 0x00000001,
-			.clear_all_bitmask = 0xFFFFFFFF,
+			.num_registers         = 3,
+			.irq_reg_set           = vfe170_150_bus_irq_reg,
+			.global_irq_cmd_offset = 0x00002068,
+			.global_clear_bitmask  = 0x00000001,
+			.clear_all_bitmask     = 0xFFFFFFFF,
 		},
 		.comp_error_status            = 0x0000206C,
 		.comp_ovrwr_status            = 0x00002070,

+ 8 - 8
drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175.h

@@ -29,9 +29,9 @@ static struct cam_irq_register_set vfe175_top_irq_reg_set[2] = {
 static struct cam_irq_controller_reg_info vfe175_top_irq_reg_info = {
 	.num_registers = 2,
 	.irq_reg_set = vfe175_top_irq_reg_set,
-	.global_clear_offset  = 0x00000058,
-	.global_clear_bitmask = 0x00000001,
-	.clear_all_bitmask = 0xFFFFFFFF,
+	.global_irq_cmd_offset = 0x00000058,
+	.global_clear_bitmask  = 0x00000001,
+	.clear_all_bitmask     = 0xFFFFFFFF,
 };
 
 static struct cam_vfe_camif_ver2_reg vfe175_camif_reg = {
@@ -322,11 +322,11 @@ static struct cam_vfe_bus_ver2_hw_info vfe175_bus_hw_info = {
 		.pwr_iso_cfg                  = 0x000020CC,
 		.dual_master_comp_cfg         = 0x00002028,
 		.irq_reg_info = {
-			.num_registers        = 3,
-			.irq_reg_set          = vfe175_bus_irq_reg,
-			.global_clear_offset  = 0x00002068,
-			.global_clear_bitmask = 0x00000001,
-			.clear_all_bitmask = 0xFFFFFFFF,
+			.num_registers         = 3,
+			.irq_reg_set           = vfe175_bus_irq_reg,
+			.global_irq_cmd_offset = 0x00002068,
+			.global_clear_bitmask  = 0x00000001,
+			.clear_all_bitmask     = 0xFFFFFFFF,
 		},
 		.comp_error_status            = 0x0000206C,
 		.comp_ovrwr_status            = 0x00002070,

+ 13 - 13
drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175_130.h

@@ -38,9 +38,9 @@ static struct cam_vfe_rdi_overflow_status vfe175_130_rdi_irq_status = {
 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,
-	.global_clear_offset  = 0x00000058,
-	.global_clear_bitmask = 0x00000001,
-	.clear_all_bitmask = 0xFFFFFFFF,
+	.global_irq_cmd_offset = 0x00000058,
+	.global_clear_bitmask  = 0x00000001,
+	.clear_all_bitmask     = 0xFFFFFFFF,
 };
 
 static struct cam_vfe_camif_ver2_reg vfe175_130_camif_reg = {
@@ -394,11 +394,11 @@ static struct cam_vfe_bus_rd_ver1_hw_info vfe175_130_bus_rd_hw_info = {
 		.input_if_cmd                 = 0x00005020,
 		.test_bus_ctrl                = 0x00005048,
 		.irq_reg_info = {
-			.num_registers        = 1,
-			.irq_reg_set          = vfe175_130_bus_rd_irq_reg,
-			.global_clear_offset  = 0x00005018,
-			.global_clear_bitmask = 0x00000001,
-			.clear_all_bitmask = 0xFFFFFFFF,
+			.num_registers         = 1,
+			.irq_reg_set           = vfe175_130_bus_rd_irq_reg,
+			.global_irq_cmd_offset = 0x00005018,
+			.global_clear_bitmask  = 0x00000001,
+			.clear_all_bitmask     = 0xFFFFFFFF,
 		},
 	},
 	.num_client = 1,
@@ -434,11 +434,11 @@ static struct cam_vfe_bus_ver2_hw_info vfe175_130_bus_hw_info = {
 		.pwr_iso_cfg                  = 0x000020CC,
 		.dual_master_comp_cfg         = 0x00002028,
 		.irq_reg_info = {
-			.num_registers        = 3,
-			.irq_reg_set          = vfe175_130_bus_irq_reg,
-			.global_clear_offset  = 0x00002068,
-			.global_clear_bitmask = 0x00000001,
-			.clear_all_bitmask = 0xFFFFFFFF,
+			.num_registers         = 3,
+			.irq_reg_set           = vfe175_130_bus_irq_reg,
+			.global_irq_cmd_offset = 0x00002068,
+			.global_clear_bitmask  = 0x00000001,
+			.clear_all_bitmask     = 0xFFFFFFFF,
 		},
 		.comp_error_status            = 0x0000206C,
 		.comp_ovrwr_status            = 0x00002070,

+ 9 - 9
drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe480.h

@@ -35,9 +35,9 @@ static struct cam_irq_register_set vfe480_top_irq_reg_set[3] = {
 static struct cam_irq_controller_reg_info vfe480_top_irq_reg_info = {
 	.num_registers = 3,
 	.irq_reg_set = vfe480_top_irq_reg_set,
-	.global_clear_offset  = 0x00000038,
-	.global_clear_bitmask = 0x00000001,
-	.clear_all_bitmask = 0xFFFFFFFF,
+	.global_irq_cmd_offset = 0x00000038,
+	.global_clear_bitmask  = 0x00000001,
+	.clear_all_bitmask     = 0xFFFFFFFF,
 };
 
 static struct cam_vfe_camif_ver3_pp_clc_reg vfe480_camif_reg = {
@@ -420,7 +420,7 @@ static struct cam_vfe_bus_ver3_hw_info vfe480_bus_hw_info = {
 		.irq_reg_info = {
 			.num_registers            = 2,
 			.irq_reg_set              = vfe480_bus_irq_reg,
-			.global_clear_offset      = 0x0000AA30,
+			.global_irq_cmd_offset    = 0x0000AA30,
 			.global_clear_bitmask     = 0x00000001,
 		},
 	},
@@ -1627,11 +1627,11 @@ static struct cam_vfe_bus_rd_ver1_hw_info vfe480_bus_rd_hw_info = {
 		.input_if_cmd                 = 0x0000A820,
 		.test_bus_ctrl                = 0x0000A848,
 		.irq_reg_info = {
-			.num_registers        = 1,
-			.irq_reg_set          = vfe480_bus_rd_irq_reg,
-			.global_clear_offset  = 0x0000A818,
-			.global_clear_bitmask = 0x00000001,
-			.clear_all_bitmask = 0xFFFFFFFF,
+			.num_registers         = 1,
+			.irq_reg_set           = vfe480_bus_rd_irq_reg,
+			.global_irq_cmd_offset = 0x0000A818,
+			.global_clear_bitmask  = 0x00000001,
+			.clear_all_bitmask     = 0xFFFFFFFF,
 		},
 	},
 	.num_client = 1,

+ 8 - 4
drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe680.h

@@ -451,6 +451,9 @@ static struct cam_irq_register_set vfe680_top_irq_reg_set[2] = {
 		.mask_reg_offset   = 0x00000034,
 		.clear_reg_offset  = 0x0000003c,
 		.status_reg_offset = 0x00000044,
+		.set_reg_offset    = 0x0000004C,
+		.test_set_val      = BIT(1),
+		.test_sub_val      = BIT(0),
 	},
 	{
 		.mask_reg_offset   = 0x00000038,
@@ -462,9 +465,10 @@ static struct cam_irq_register_set vfe680_top_irq_reg_set[2] = {
 static struct cam_irq_controller_reg_info vfe680_top_irq_reg_info = {
 	.num_registers = 2,
 	.irq_reg_set = vfe680_top_irq_reg_set,
-	.global_clear_offset  = 0x00000030,
-	.global_clear_bitmask = 0x00000001,
-	.clear_all_bitmask = 0xFFFFFFFF,
+	.global_irq_cmd_offset = 0x00000030,
+	.global_clear_bitmask  = 0x00000001,
+	.global_set_bitmask    = 0x00000010,
+	.clear_all_bitmask     = 0xFFFFFFFF,
 };
 
 static struct cam_vfe_top_ver4_reg_offset_common vfe680_top_common_reg = {
@@ -885,7 +889,7 @@ static struct cam_vfe_bus_ver3_hw_info vfe680_bus_hw_info = {
 		.irq_reg_info = {
 			.num_registers            = 2,
 			.irq_reg_set              = vfe680_bus_irq_reg,
-			.global_clear_offset      = 0x00000C30,
+			.global_irq_cmd_offset    = 0x00000C30,
 			.global_clear_bitmask     = 0x00000001,
 		},
 	},

+ 8 - 4
drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe780.h

@@ -492,6 +492,9 @@ static struct cam_irq_register_set vfe780_top_irq_reg_set[2] = {
 		.mask_reg_offset   = 0x00000034,
 		.clear_reg_offset  = 0x0000003C,
 		.status_reg_offset = 0x00000044,
+		.set_reg_offset    = 0x0000004C,
+		.test_set_val      = BIT(1),
+		.test_sub_val      = BIT(0),
 	},
 	{
 		.mask_reg_offset   = 0x00000038,
@@ -503,9 +506,10 @@ static struct cam_irq_register_set vfe780_top_irq_reg_set[2] = {
 static struct cam_irq_controller_reg_info vfe780_top_irq_reg_info = {
 	.num_registers = 2,
 	.irq_reg_set = vfe780_top_irq_reg_set,
-	.global_clear_offset  = 0x00000030,
-	.global_clear_bitmask = 0x00000001,
-	.clear_all_bitmask = 0xFFFFFFFF,
+	.global_irq_cmd_offset = 0x00000030,
+	.global_clear_bitmask  = 0x00000001,
+	.global_set_bitmask    = 0x00000010,
+	.clear_all_bitmask     = 0xFFFFFFFF,
 };
 
 static struct cam_vfe_top_ver4_reg_offset_common vfe780_top_common_reg = {
@@ -931,7 +935,7 @@ static struct cam_vfe_bus_ver3_hw_info vfe780_bus_hw_info = {
 		.irq_reg_info = {
 			.num_registers            = 2,
 			.irq_reg_set              = vfe780_bus_irq_reg,
-			.global_clear_offset      = 0x00000C30,
+			.global_irq_cmd_offset    = 0x00000C30,
 			.global_clear_bitmask     = 0x00000001,
 		},
 	},

+ 8 - 8
drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe_lite17x.h

@@ -27,9 +27,9 @@ static struct cam_irq_register_set vfe17x_top_irq_reg_set[2] = {
 static struct cam_irq_controller_reg_info vfe17x_top_irq_reg_info = {
 	.num_registers = 2,
 	.irq_reg_set = vfe17x_top_irq_reg_set,
-	.global_clear_offset  = 0x00000058,
-	.global_clear_bitmask = 0x00000001,
-	.clear_all_bitmask = 0xFFFFFFFF,
+	.global_irq_cmd_offset = 0x00000058,
+	.global_clear_bitmask  = 0x00000001,
+	.clear_all_bitmask     = 0xFFFFFFFF,
 };
 
 static struct cam_vfe_top_ver2_reg_offset_common vfe17x_top_common_reg = {
@@ -151,11 +151,11 @@ static struct cam_vfe_bus_ver2_hw_info vfe17x_bus_hw_info = {
 		.pwr_iso_cfg                  = 0x000020CC,
 		.dual_master_comp_cfg         = 0x00002028,
 		.irq_reg_info = {
-			.num_registers        = 3,
-			.irq_reg_set          = vfe17x_bus_irq_reg,
-			.global_clear_offset  = 0x00002068,
-			.global_clear_bitmask = 0x00000001,
-			.clear_all_bitmask = 0xFFFFFFFF,
+			.num_registers         = 3,
+			.irq_reg_set           = vfe17x_bus_irq_reg,
+			.global_irq_cmd_offset = 0x00002068,
+			.global_clear_bitmask  = 0x00000001,
+			.clear_all_bitmask     = 0xFFFFFFFF,
 		},
 		.comp_error_status            = 0x0000206C,
 		.comp_ovrwr_status            = 0x00002070,

+ 4 - 4
drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe_lite48x.h

@@ -32,9 +32,9 @@ static struct cam_irq_register_set vfe48x_top_irq_reg_set[3] = {
 static struct cam_irq_controller_reg_info vfe48x_top_irq_reg_info = {
 	.num_registers = 3,
 	.irq_reg_set = vfe48x_top_irq_reg_set,
-	.global_clear_offset  = 0x00000024,
-	.global_clear_bitmask = 0x00000001,
-	.clear_all_bitmask = 0xFFFFFFFF,
+	.global_irq_cmd_offset = 0x00000024,
+	.global_clear_bitmask  = 0x00000001,
+	.clear_all_bitmask     = 0xFFFFFFFF,
 };
 
 static struct cam_vfe_top_ver3_reg_offset_common vfe48x_top_common_reg = {
@@ -244,7 +244,7 @@ static struct cam_vfe_bus_ver3_hw_info vfe48x_bus_hw_info = {
 		.irq_reg_info = {
 			.num_registers            = 2,
 			.irq_reg_set              = vfe48x_bus_irq_reg,
-			.global_clear_offset      = 0x00001A30,
+			.global_irq_cmd_offset    = 0x00001A30,
 			.global_clear_bitmask     = 0x00000001,
 		},
 	},

+ 8 - 4
drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe_lite68x.h

@@ -61,6 +61,9 @@ static struct cam_irq_register_set vfe68x_top_irq_reg_set[3] = {
 		.mask_reg_offset   = 0x00001024,
 		.clear_reg_offset  = 0x0000102C,
 		.status_reg_offset = 0x0000101C,
+		.set_reg_offset    = 0x00001034,
+		.test_set_val      = BIT(0),
+		.test_sub_val      = BIT(0),
 	},
 	{
 		.mask_reg_offset   = 0x00001028,
@@ -72,9 +75,10 @@ static struct cam_irq_register_set vfe68x_top_irq_reg_set[3] = {
 static struct cam_irq_controller_reg_info vfe68x_top_irq_reg_info = {
 	.num_registers = 2,
 	.irq_reg_set = vfe68x_top_irq_reg_set,
-	.global_clear_offset  = 0x00001038,
-	.global_clear_bitmask = 0x00000001,
-	.clear_all_bitmask = 0xFFFFFFFF,
+	.global_irq_cmd_offset = 0x00001038,
+	.global_clear_bitmask  = 0x00000001,
+	.global_set_bitmask    = 0x00000010,
+	.clear_all_bitmask     = 0xFFFFFFFF,
 };
 
 static struct cam_vfe_top_ver4_reg_offset_common vfe68x_top_common_reg = {
@@ -273,7 +277,7 @@ static struct cam_vfe_bus_ver3_hw_info vfe680x_bus_hw_info = {
 		.irq_reg_info = {
 			.num_registers            = 2,
 			.irq_reg_set              = vfe680x_bus_irq_reg,
-			.global_clear_offset      = 0x00001230,
+			.global_irq_cmd_offset    = 0x00001230,
 			.global_clear_bitmask     = 0x00000001,
 		},
 	},

+ 8 - 4
drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe_lite78x.h

@@ -61,6 +61,9 @@ static struct cam_irq_register_set vfe_lite78x_top_irq_reg_set[2] = {
 		.mask_reg_offset   = 0x00001024,
 		.clear_reg_offset  = 0x0000102C,
 		.status_reg_offset = 0x0000101C,
+		.set_reg_offset    = 0x00001034,
+		.test_set_val      = BIT(0),
+		.test_sub_val      = BIT(0),
 	},
 	{
 		.mask_reg_offset   = 0x00001028,
@@ -72,9 +75,10 @@ static struct cam_irq_register_set vfe_lite78x_top_irq_reg_set[2] = {
 static struct cam_irq_controller_reg_info vfe_lite78x_top_irq_reg_info = {
 	.num_registers = 2,
 	.irq_reg_set = vfe_lite78x_top_irq_reg_set,
-	.global_clear_offset  = 0x00001038,
-	.global_clear_bitmask = 0x00000001,
-	.clear_all_bitmask = 0xFFFFFFFF,
+	.global_irq_cmd_offset = 0x00001038,
+	.global_clear_bitmask  = 0x00000001,
+	.global_set_bitmask    = 0x00000010,
+	.clear_all_bitmask     = 0xFFFFFFFF,
 };
 
 static struct cam_vfe_top_ver4_reg_offset_common vfe_lite78x_top_common_reg = {
@@ -268,7 +272,7 @@ static struct cam_vfe_bus_ver3_hw_info vfe_lite78x_bus_hw_info = {
 		.irq_reg_info = {
 			.num_registers            = 1,
 			.irq_reg_set              = vfe_lite78x_bus_irq_reg,
-			.global_clear_offset      = 0x00001230,
+			.global_irq_cmd_offset    = 0x00001230,
 			.global_clear_bitmask     = 0x00000001,
 		},
 	},