msm: camera: isp: Add dynamic enabling of IRQ in controller
CSID SOFs are needed to do a health check of sensors once the sensor freeze is observed. Since the 680 CSID driver has controller based mechanism, there is a need to enable the IRQ on controller dynamically. This commit adds support for dynamic enable/disable of IRQ on controller. Minor clean ups to remove unused code. CRs-Fixed: 2830502 Change-Id: Ic4985555a5726264606a8e60c725eb8d1ce81364 Signed-off-by: Gaurav Jindal <gjindal@codeaurora.org>
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
@@ -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_ */
|
||||
|
@@ -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++) {
|
||||
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);
|
||||
|
||||
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 = 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;
|
||||
@@ -2146,7 +2128,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(
|
||||
@@ -2220,11 +2202,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:
|
||||
|
Reference in New Issue
Block a user