msm: camera: isp: Skip writes to clean IRQ clear registers
If an IRQ status register has not caused the interrupt to be triggered, we can skip writing to the corresponding clear register as long as no previous writes have been made to it that will cause bits of interest to be cleared (i.e. clear register is dirty). For this, we maintain a dirty flag for each clear register. The dirty flag will never cause false negatives (i.e. valid writes to be missed) since hardware cannot set any bits in the clear register to 1 and will only clear the entire register upon resetting the hardware. CRs-Fixed: 3152588 Change-Id: I4f97bae0e3cd983ca66d5b89ffb2c16da7c25200 Signed-off-by: Anand Ravi <quic_ananravi@quicinc.com>
Цей коміт міститься в:

зафіксовано
Camera Software Integration

джерело
96b3f625f0
коміт
340e043307
@@ -69,6 +69,7 @@ struct cam_irq_evt_handler {
|
||||
* after subscribe/unsubscribe calls
|
||||
* @dependent_read_mask: Mask to check if any dependent controllers' read needs to triggered
|
||||
* from independent controller
|
||||
* @dirty_clear: Flag to identify if clear register contains non-zero value
|
||||
*/
|
||||
struct cam_irq_register_obj {
|
||||
uint32_t index;
|
||||
@@ -81,6 +82,7 @@ struct cam_irq_register_obj {
|
||||
uint32_t top_half_enable_mask[CAM_IRQ_PRIORITY_MAX];
|
||||
uint32_t aggr_mask;
|
||||
uint32_t dependent_read_mask[CAM_IRQ_MAX_DEPENDENTS];
|
||||
bool dirty_clear;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -407,6 +409,7 @@ int cam_irq_controller_init(const char *name,
|
||||
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;
|
||||
controller->irq_register_arr[i].dirty_clear = true;
|
||||
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,
|
||||
@@ -487,6 +490,7 @@ static inline void __cam_irq_controller_enable_irq(
|
||||
irq_register = &controller->irq_register_arr[i];
|
||||
irq_register->top_half_enable_mask[priority] |= update_mask[i];
|
||||
irq_register->aggr_mask |= update_mask[i];
|
||||
irq_register->dirty_clear = true;
|
||||
cam_io_w_mb(irq_register->aggr_mask, controller->mem_base +
|
||||
irq_register->mask_reg_offset);
|
||||
}
|
||||
@@ -865,6 +869,32 @@ static void __cam_irq_controller_read_registers(struct cam_irq_controller *contr
|
||||
controller->irq_register_arr[i].status_reg_offset,
|
||||
controller->irq_status_arr[i]);
|
||||
|
||||
/**
|
||||
* If this status register has not caused the interrupt to be
|
||||
* triggered, we can skip writing to the clear register as long
|
||||
* as no previous writes have been made to it that will cause
|
||||
* bits of interest to be cleared (i.e. clear register is
|
||||
* dirty).
|
||||
*
|
||||
* The dirty clear flag will never cause false negatives (i.e.
|
||||
* valid writes to be missed) since hardware cannot set any bits
|
||||
* in the clear register to 1 and will only clear the entire
|
||||
* register upon resetting the hardware.
|
||||
*/
|
||||
if (!(controller->irq_status_arr[i] & irq_register->aggr_mask)) {
|
||||
if (!irq_register->dirty_clear)
|
||||
continue;
|
||||
else
|
||||
irq_register->dirty_clear = false;
|
||||
} else {
|
||||
irq_register->dirty_clear = true;
|
||||
}
|
||||
|
||||
CAM_DBG(CAM_IRQ_CTRL, "(%s) Write irq clear%d (0x%x) = 0x%x (dirty=%s)",
|
||||
controller->name, i, controller->irq_register_arr[i].clear_reg_offset,
|
||||
controller->irq_status_arr[i],
|
||||
CAM_BOOL_TO_YESNO(irq_register->dirty_clear));
|
||||
|
||||
cam_io_w(controller->irq_status_arr[i],
|
||||
controller->mem_base + irq_register->clear_reg_offset);
|
||||
}
|
||||
|
Посилання в новій задачі
Заблокувати користувача