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

Commit 54070a35 authored by Venkat Chinta's avatar Venkat Chinta Committed by Mukund Madhusudan Atre
Browse files

msm: camera: ife: Add new controller for RUP IRQ



Currently EPOCH IRQ handling is at a higher priority
compared to RUP IRQ as RUP is fired at bus level. If
RUP IRQ is not scheduled for handling by the time we
receive EPOCH IRQ, EPOCH IRQ will be processed first
and this will lead to missed SOF notification as the
active request list might be empty. This change sets
priority of both IRQs to the same by utilizing a new
IRQ controller that is tasked with handling RUP from
BUS. BUF_DONE is also subscribed to the same VFE top
level BUS_WR IRQ but with a lower priority. IRQs for
CAMIF Lite and RDI are subscribed to only if the ctx
is RDI only.

Change-Id: Id844ffe291e21ecfc7f7ed6fc53baf7e79dd2184
Signed-off-by: default avatarVenkat Chinta <vchinta@codeaurora.org>
Signed-off-by: default avatarMukund Madhusudan Atre <matre@codeaurora.org>
parent 3b1e74e5
Loading
Loading
Loading
Loading
+28 −8
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
 * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
 */

#include <linux/slab.h>
@@ -53,6 +53,8 @@ struct cam_irq_evt_handler {
 * @clear_reg_offset:       Offset of IRQ CLEAR register
 * @status_reg_offset:      Offset of IRQ STATUS register
 * @top_half_enable_mask:   Array of enabled bit_mask sorted by priority
 * @pclear_mask:            Partial mask to be cleared in case entire status
 *                          register is not to be cleared
 */
struct cam_irq_register_obj {
	uint32_t                     index;
@@ -60,6 +62,7 @@ struct cam_irq_register_obj {
	uint32_t                     clear_reg_offset;
	uint32_t                     status_reg_offset;
	uint32_t                     top_half_enable_mask[CAM_IRQ_PRIORITY_MAX];
	uint32_t                     pclear_mask;
};

/**
@@ -84,6 +87,8 @@ struct cam_irq_register_obj {
 * @hdl_idx:                Unique identity of handler assigned on Subscribe.
 *                          Used to Unsubscribe.
 * @lock:                   Lock for use by controller
 * @clear_all:              Flag to indicate whether to clear entire status
 *                          register
 */
struct cam_irq_controller {
	const char                     *name;
@@ -98,6 +103,7 @@ struct cam_irq_controller {
	uint32_t                        hdl_idx;
	spinlock_t                      lock;
	struct cam_irq_th_payload       th_payload;
	bool                            clear_all;
};

int cam_irq_controller_deinit(void **irq_controller)
@@ -125,7 +131,8 @@ int cam_irq_controller_deinit(void **irq_controller)
int cam_irq_controller_init(const char       *name,
	void __iomem                         *mem_base,
	struct cam_irq_controller_reg_info   *register_info,
	void                                **irq_controller)
	void                                **irq_controller,
	bool                                  clear_all)
{
	struct cam_irq_controller *controller = NULL;
	int i, rc = 0;
@@ -194,6 +201,7 @@ int cam_irq_controller_init(const char *name,
	controller->global_clear_bitmask = register_info->global_clear_bitmask;
	controller->global_clear_offset  = register_info->global_clear_offset;
	controller->mem_base             = mem_base;
	controller->clear_all            = clear_all;

	CAM_DBG(CAM_IRQ_CTRL, "global_clear_bitmask: 0x%x",
		controller->global_clear_bitmask);
@@ -321,6 +329,9 @@ int cam_irq_controller_subscribe_irq(void *irq_controller,
		controller->irq_register_arr[i].top_half_enable_mask[priority]
			|= evt_bit_mask_arr[i];

		controller->irq_register_arr[i].pclear_mask
			|= 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_bit_mask_arr[i];
@@ -610,7 +621,8 @@ static void cam_irq_controller_th_processing(
				evt_handler->bottom_half, &bh_cmd);
			if (rc || !bh_cmd) {
				CAM_ERR_RATE_LIMIT(CAM_ISP,
					"No payload, IRQ handling frozen");
					"No payload, IRQ handling frozen for %s",
					controller->name);
				continue;
			}
		}
@@ -689,11 +701,19 @@ irqreturn_t cam_irq_controller_handle_irq(int irq_num, void *priv)
	for (i = 0; i < controller->num_registers; i++) {
		irq_register = &controller->irq_register_arr[i];
		controller->irq_status_arr[i] = cam_io_r_mb(
			controller->mem_base +
			controller->irq_register_arr[i].status_reg_offset);
			controller->mem_base + irq_register->status_reg_offset);

		if (controller->clear_all)
			cam_io_w_mb(controller->irq_status_arr[i],
				controller->mem_base +
			controller->irq_register_arr[i].clear_reg_offset);
				irq_register->clear_reg_offset);
		else
			cam_io_w_mb(
				controller->irq_register_arr[i].pclear_mask &
				controller->irq_status_arr[i],
				controller->mem_base +
				irq_register->clear_reg_offset);

		CAM_DBG(CAM_IRQ_CTRL, "Read irq status%d (0x%x) = 0x%x", i,
			controller->irq_register_arr[i].status_reg_offset,
			controller->irq_status_arr[i]);
+4 −2
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
 * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
 */

#ifndef _CAM_IRQ_CONTROLLER_H_
@@ -131,6 +131,7 @@ struct cam_irq_bh_api {
 * @register_info:      Register Info structure associated with this Controller
 * @irq_controller:     Pointer to IRQ Controller that will be filled if
 *                      initialization is successful
 * @clear_all:          Flag to indicate whether to clear entire status register
 *
 * @return:             0: Success
 *                      Negative: Failure
@@ -138,7 +139,8 @@ struct cam_irq_bh_api {
int cam_irq_controller_init(const char       *name,
	void __iomem                         *mem_base,
	struct cam_irq_controller_reg_info   *register_info,
	void                                **irq_controller);
	void                                **irq_controller,
	bool                                  clear_all);

/*
 * cam_irq_controller_subscribe_irq()
+2 −1
Original line number Diff line number Diff line
@@ -669,7 +669,8 @@ int cam_vfe_core_init(struct cam_vfe_hw_core_info *core_info,

	rc = cam_irq_controller_init(drv_name,
		CAM_SOC_GET_REG_MAP_START(soc_info, VFE_CORE_BASE_IDX),
		vfe_hw_info->irq_reg_info, &core_info->vfe_irq_controller);
		vfe_hw_info->irq_reg_info, &core_info->vfe_irq_controller,
		true);
	if (rc) {
		CAM_ERR(CAM_ISP,
			"Error, cam_irq_controller_init failed rc = %d", rc);
+1 −1
Original line number Diff line number Diff line
@@ -1107,7 +1107,7 @@ int cam_vfe_bus_rd_ver1_init(

	rc = cam_irq_controller_init(drv_name, bus_priv->common_data.mem_base,
		&bus_rd_hw_info->common_reg.irq_reg_info,
		&bus_priv->common_data.bus_irq_controller);
		&bus_priv->common_data.bus_irq_controller, true);
	if (rc) {
		CAM_ERR(CAM_ISP, "cam_irq_controller_init failed");
		goto free_bus_priv;
+1 −1
Original line number Diff line number Diff line
@@ -3622,7 +3622,7 @@ int cam_vfe_bus_ver2_init(

	rc = cam_irq_controller_init(drv_name, bus_priv->common_data.mem_base,
		&ver2_hw_info->common_reg.irq_reg_info,
		&bus_priv->common_data.bus_irq_controller);
		&bus_priv->common_data.bus_irq_controller, true);
	if (rc) {
		CAM_ERR(CAM_ISP, "cam_irq_controller_init failed");
		goto free_bus_priv;
Loading