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

Merge "msm: camera: isp: Add dynamic enabling of IRQ in controller" into camera-kernel.lnx.5.0

Haritha Chintalapati 4 жил өмнө
parent
commit
1cb2a58c04

+ 69 - 1
drivers/cam_isp/isp_hw_mgr/hw_utils/irq_controller/cam_irq_controller.c

@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
- * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
  */
 
 #include <linux/slab.h>
@@ -759,3 +759,71 @@ irqreturn_t cam_irq_controller_handle_irq(int irq_num, void *priv)
 
 	return IRQ_HANDLED;
 }
+
+int cam_irq_controller_update_irq(void *irq_controller, uint32_t handle,
+	bool enable, uint32_t *irq_mask)
+{
+	struct cam_irq_controller   *controller  = irq_controller;
+	struct cam_irq_evt_handler  *evt_handler = NULL;
+	struct cam_irq_evt_handler  *evt_handler_temp;
+	struct cam_irq_register_obj *irq_register = NULL;
+	enum cam_irq_priority_level priority;
+	unsigned long               flags = 0;
+	unsigned int                i;
+	uint32_t                    found = 0;
+	int                         rc = -EINVAL;
+	bool                        need_lock;
+
+	if (!controller)
+		return rc;
+
+	need_lock = !in_irq();
+	if (need_lock)
+		spin_lock_irqsave(&controller->lock, flags);
+
+	list_for_each_entry_safe(evt_handler, evt_handler_temp,
+		&controller->evt_handler_list_head, list_node) {
+		if (evt_handler->index == handle) {
+			CAM_DBG(CAM_IRQ_CTRL, "enable item %d", handle);
+			found = 1;
+			rc = 0;
+			break;
+		}
+	}
+
+	if (!found) {
+		if (need_lock)
+			spin_unlock_irqrestore(&controller->lock, flags);
+		return rc;
+	}
+
+	priority = evt_handler->priority;
+	for (i = 0; i < controller->num_registers; i++) {
+
+		irq_register = &controller->irq_register_arr[i];
+
+		if (enable) {
+			irq_register->top_half_enable_mask[priority] |=
+								irq_mask[i];
+			evt_handler->evt_bit_mask_arr[i] |= irq_mask[i];
+		} else {
+			irq_register->top_half_enable_mask[priority] &=
+								~irq_mask[i];
+			evt_handler->evt_bit_mask_arr[i] &= ~irq_mask[i];
+
+			if (controller->global_clear_offset)
+				cam_io_w_mb(controller->global_clear_bitmask,
+					controller->mem_base +
+					controller->global_clear_offset);
+		}
+
+		cam_io_w_mb(evt_handler->evt_bit_mask_arr[i],
+			controller->mem_base +
+			controller->irq_register_arr[i].mask_reg_offset);
+	}
+
+	if (need_lock)
+		spin_unlock_irqrestore(&controller->lock, flags);
+
+	return rc;
+}

+ 22 - 1
drivers/cam_isp/isp_hw_mgr/hw_utils/irq_controller/cam_irq_controller.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-2021, The Linux Foundation. All rights reserved.
  */
 
 #ifndef _CAM_IRQ_CONTROLLER_H_
@@ -271,4 +271,25 @@ int cam_irq_controller_enable_irq(void *irq_controller, uint32_t handle);
  * @return:             IRQ_HANDLED/IRQ_NONE
  */
 irqreturn_t cam_irq_controller_clear_and_mask(int irq_num, void *priv);
+
+/*
+ * cam_irq_controller_update_irq()
+ *
+ * @brief:              Enable/Disable the interrupts on given controller.
+ *                      Dynamically any irq can be disabled or enabled.
+ *
+ * @irq_controller:     Pointer to IRQ Controller that controls the registered
+ *                      events to it.
+ * @handle:             Handle returned on successful subscribe, used to
+ *                      identify the handler object
+ *
+ * @enable:             Flag to indicate if disable or enable the irq.
+ *
+ * @irq_mask:           IRQ mask to be enabled or disabled.
+ *
+ * @return:             0: events found and enabled
+ *                      Negative: events not registered on this controller
+ */
+int cam_irq_controller_update_irq(void *irq_controller, uint32_t handle,
+	bool enable, uint32_t *irq_mask);
 #endif /* _CAM_IRQ_CONTROLLER_H_ */

+ 27 - 50
drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_hw_ver2.c

@@ -291,10 +291,10 @@ static int cam_ife_csid_ver2_sof_irq_debug(
 	void *cmd_args)
 {
 	int i = 0;
-	uint32_t val = 0;
+	uint32_t irq_idx = 0;
 	bool sof_irq_enable = false;
-	struct cam_hw_soc_info                  *soc_info;
 	struct cam_ife_csid_ver2_reg_info *csid_reg;
+	uint32_t irq_mask[CAM_IFE_CSID_IRQ_REG_MAX] = {0};
 
 	if (*((uint32_t *)cmd_args) == 1)
 		sof_irq_enable = true;
@@ -307,53 +307,32 @@ static int cam_ife_csid_ver2_sof_irq_debug(
 		return 0;
 	}
 
-	soc_info = &csid_hw->hw_info->soc_info;
 	csid_reg = (struct cam_ife_csid_ver2_reg_info *)
 			csid_hw->core_info->csid_reg;
 
-	for (i = 0; i < csid_reg->cmn_reg->num_pix; i++) {
-
-		val = cam_io_r_mb(soc_info->reg_map[0].mem_base +
-			csid_reg->ipp_reg->irq_mask_addr);
-
-		if (!val)
-			continue;
-
-		if (sof_irq_enable)
-			val |= IFE_CSID_VER2_PATH_INFO_INPUT_SOF;
-		else
-			val &= ~IFE_CSID_VER2_PATH_INFO_INPUT_SOF;
-
-		cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
-			csid_reg->ipp_reg->irq_mask_addr);
-	}
+	for (i = CAM_IFE_CSID_IRQ_REG_RDI_0; i <= CAM_IFE_CSID_IRQ_REG_IPP;
+		i++) {
+		irq_idx = cam_ife_csid_get_rt_irq_idx(i,
+				csid_reg->cmn_reg->num_pix,
+				csid_reg->cmn_reg->num_ppp,
+				csid_reg->cmn_reg->num_rdis);
 
-	for (i = 0; i < csid_reg->cmn_reg->num_rdis; i++) {
-		val = cam_io_r_mb(soc_info->reg_map[0].mem_base +
-			csid_reg->rdi_reg[i]->irq_mask_addr);
-		if (!val)
-			continue;
-
-		if (sof_irq_enable)
-			val |= IFE_CSID_VER2_PATH_INFO_INPUT_SOF;
-		else
-			val &= ~IFE_CSID_VER2_PATH_INFO_INPUT_SOF;
-
-		cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
-			csid_reg->rdi_reg[i]->irq_mask_addr);
+		if (csid_hw->irq_handle[irq_idx]) {
+			irq_mask[irq_idx] =  IFE_CSID_VER2_PATH_INFO_INPUT_SOF;
+			cam_irq_controller_update_irq(
+				csid_hw->csid_irq_controller,
+				csid_hw->irq_handle[i],
+				sof_irq_enable, irq_mask);
+		}
 	}
 
 	if (sof_irq_enable) {
 		csid_hw->debug_info.path_mask |=
 			IFE_CSID_VER2_PATH_INFO_INPUT_SOF;
-		csid_hw->debug_info.debug_val |=
-			CAM_IFE_CSID_DEBUG_ENABLE_SOF_IRQ;
 		csid_hw->flags.sof_irq_triggered = true;
 	} else {
 		csid_hw->debug_info.path_mask &=
 			~IFE_CSID_VER2_PATH_INFO_INPUT_SOF;
-		csid_hw->debug_info.debug_val &=
-			~CAM_IFE_CSID_DEBUG_ENABLE_SOF_IRQ;
 		csid_hw->flags.sof_irq_triggered = false;
 	}
 
@@ -794,11 +773,6 @@ static int cam_ife_csid_ver2_parse_path_irq_status(
 	irq_reg_tag = cam_ife_csid_get_irq_reg_tag_ptr();
 	temp_status = irq_status & err_mask;
 
-	if (csid_hw->flags.sof_irq_triggered &&
-		(irq_status & IFE_CSID_VER2_PATH_INFO_INPUT_SOF)) {
-		csid_hw->counters.irq_debug_cnt++;
-	}
-
 	while (temp_status) {
 
 		if (temp_status & 0x1)
@@ -826,9 +800,17 @@ static int cam_ife_csid_ver2_parse_path_irq_status(
 		temp_status >>= 1;
 	}
 
-	if (csid_hw->counters.irq_debug_cnt >= CAM_CSID_IRQ_SOF_DEBUG_CNT_MAX) {
-		cam_ife_csid_ver2_sof_irq_debug(csid_hw, &sof_irq_debug_en);
-		csid_hw->counters.irq_debug_cnt = 0;
+	if (csid_hw->flags.sof_irq_triggered) {
+
+		if (irq_status & IFE_CSID_VER2_PATH_INFO_INPUT_SOF)
+			csid_hw->counters.irq_debug_cnt++;
+
+		if (csid_hw->counters.irq_debug_cnt >=
+			CAM_CSID_IRQ_SOF_DEBUG_CNT_MAX) {
+			cam_ife_csid_ver2_sof_irq_debug(csid_hw,
+				&sof_irq_debug_en);
+			csid_hw->counters.irq_debug_cnt = 0;
+		}
 	}
 
 	return 0;
@@ -2150,7 +2132,7 @@ static int cam_ife_csid_ver2_start_rdi_path(
 	void __iomem *mem_base;
 	uint32_t val = 0;
 	uint32_t irq_mask[CAM_IFE_CSID_IRQ_REG_MAX] = {0};
-	uint32_t top_irq_mask = 0, irq_idx = 0, rt_irq_idx;
+	uint32_t top_irq_mask = 0, irq_idx = 0;
 	struct cam_ife_csid_ver2_path_cfg *path_cfg;
 
 	rc = cam_ife_csid_ver2_init_config_rdi_path(
@@ -2224,11 +2206,6 @@ static int cam_ife_csid_ver2_start_rdi_path(
 	res->res_state = CAM_ISP_RESOURCE_STATE_STREAMING;
 
 	irq_idx = cam_ife_csid_convert_res_to_irq_reg(res->res_id);
-	rt_irq_idx = cam_ife_csid_get_rt_irq_idx(
-			irq_idx,
-			csid_reg->cmn_reg->num_pix,
-			csid_reg->cmn_reg->num_ppp,
-			csid_reg->cmn_reg->num_rdis);
 
 	switch (res->res_id) {
 	case CAM_IFE_PIX_PATH_RES_RDI_0: