Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3a980c90 authored by Alok Pandey's avatar Alok Pandey Committed by Gerrit - the friendly Code Review server
Browse files

msm: camera: isp: Add enable/disable IRQ functions to Controller



Add APIs to enable and disable irq events while still subscribed
for the IRQ bits in IRQ controller. This enables the driver to temporary
ignore the IRQs while still keeping the event handler in place. This is
needed when an error occurs and we are trying to recover. After the
error there can be an IRQ storm and we need to disable the IRQ,
then reset the HW and restart the HW after enabling the IRQ again. Since
this disabling of IRQ to avoid IRQ storm needs to happen in top half, we
cannot call unsubscribe which would free the event handler that contains
the top half handling function being executed.

Change-Id: Ic498cf0703db85ae41690374e27e22b1fbd30f2e
Signed-off-by: default avatarAlok Pandey <akumarpa@codeaurora.org>
Signed-off-by: default avatarHarsh Shah <harshs@codeaurora.org>
parent 1e7ed2a9
Loading
Loading
Loading
Loading
+105 −0
Original line number Diff line number Diff line
@@ -329,6 +329,111 @@ int cam_irq_controller_subscribe_irq(void *irq_controller,
	return rc;
}

int cam_irq_controller_enable_irq(void *irq_controller, uint32_t handle)
{
	struct cam_irq_controller  *controller  = irq_controller;
	struct cam_irq_evt_handler *evt_handler = NULL;
	struct cam_irq_evt_handler *evt_handler_temp;
	unsigned long               flags;
	unsigned int                i;
	uint32_t                    irq_mask;
	uint32_t                    found = 0;
	int                         rc = -EINVAL;

	if (!controller)
		return rc;

	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_ISP, "enable item %d", handle);
			found = 1;
			rc = 0;
			break;
		}
	}

	if (!found)
		return rc;

	write_lock_irqsave(&controller->rw_lock, flags);
	for (i = 0; i < controller->num_registers; i++) {
		controller->irq_register_arr[i].
		top_half_enable_mask[evt_handler->priority] |=
			evt_handler->evt_bit_mask_arr[i];

		irq_mask = cam_io_r_mb(controller->mem_base +
			controller->irq_register_arr[i].
			mask_reg_offset);
		irq_mask |= evt_handler->evt_bit_mask_arr[i];

		cam_io_w_mb(irq_mask, controller->mem_base +
		controller->irq_register_arr[i].mask_reg_offset);
	}
	write_unlock_irqrestore(&controller->rw_lock, flags);

	return rc;
}

int cam_irq_controller_disable_irq(void *irq_controller, uint32_t handle)
{
	struct cam_irq_controller  *controller  = irq_controller;
	struct cam_irq_evt_handler *evt_handler = NULL;
	struct cam_irq_evt_handler *evt_handler_temp;
	unsigned long               flags;
	unsigned int                i;
	uint32_t                    irq_mask;
	uint32_t                    found = 0;
	int                         rc = -EINVAL;

	if (!controller)
		return rc;

	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_ISP, "disable item %d", handle);
			found = 1;
			rc = 0;
			break;
		}
	}

	if (!found)
		return rc;

	write_lock_irqsave(&controller->rw_lock, flags);
	for (i = 0; i < controller->num_registers; i++) {
		controller->irq_register_arr[i].
		top_half_enable_mask[evt_handler->priority] &=
			~(evt_handler->evt_bit_mask_arr[i]);

		irq_mask = cam_io_r_mb(controller->mem_base +
			controller->irq_register_arr[i].
			mask_reg_offset);
		irq_mask &= ~(evt_handler->evt_bit_mask_arr[i]);

		cam_io_w_mb(irq_mask, controller->mem_base +
			controller->irq_register_arr[i].
			mask_reg_offset);

		/* Clear the IRQ bits of this handler */
		cam_io_w_mb(evt_handler->evt_bit_mask_arr[i],
			controller->mem_base +
			controller->irq_register_arr[i].
			clear_reg_offset);

		if (controller->global_clear_offset)
			cam_io_w_mb(
				controller->global_clear_bitmask,
				controller->mem_base +
				controller->global_clear_offset);
	}
	write_unlock_irqrestore(&controller->rw_lock, flags);

	return rc;
}

int cam_irq_controller_unsubscribe_irq(void *irq_controller,
	uint32_t handle)
{
+36 −0
Original line number Diff line number Diff line
@@ -214,4 +214,40 @@ int cam_irq_controller_deinit(void **irq_controller);
 */
irqreturn_t cam_irq_controller_handle_irq(int irq_num, void *priv);

/*
 * cam_irq_controller_disable_irq()
 *
 * @brief:              Disable the interrupts on given controller.
 *                      Unsubscribe will disable the IRQ by default, so this is
 *                      only needed if between subscribe/unsubscribe there is
 *                      need to disable IRQ again
 *
 * @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
 *
 * @return:             0: events found and disabled
 *                      Negative: events not registered on this controller
 */
int cam_irq_controller_disable_irq(void *irq_controller, uint32_t handle);

/*
 * cam_irq_controller_enable_irq()
 *
 * @brief:              Enable the interrupts on given controller.
 *                      Subscribe will enable the IRQ by default, so this is
 *                      only needed if between subscribe/unsubscribe there is
 *                      need to enable IRQ again
 *
 * @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
 *
 * @return:             0: events found and enabled
 *                      Negative: events not registered on this controller
 */
int cam_irq_controller_enable_irq(void *irq_controller, uint32_t handle);

#endif /* _CAM_IRQ_CONTROLLER_H_ */