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

Commit 1fca0a1e authored by Camera Software Integration's avatar Camera Software Integration Committed by Gerrit - the friendly Code Review server
Browse files

Merge "msm: camera: common: Merge camera-kernel.4.0 changes in...

Merge "msm: camera: common: Merge camera-kernel.4.0 changes in camera-kernel.3.1" into camera-kernel.lnx.3.1
parents f618a067 cedd2aa5
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -83,6 +83,7 @@
#define CAM_CDM_RESET_HW_STATUS 0x4
#define CAM_CDM_ERROR_HW_STATUS 0x5
#define CAM_CDM_FLUSH_HW_STATUS 0x6
#define CAM_CDM_RESET_ERR_STATUS 0x7

/* Curent BL command masks and shifts */
#define CAM_CDM_CURRENT_BL_LEN   0xFFFFF
@@ -376,6 +377,7 @@ enum cam_cdm_hw_process_intf_cmd {
	CAM_CDM_HW_INTF_CMD_FLUSH_HW,
	CAM_CDM_HW_INTF_CMD_HANDLE_ERROR,
	CAM_CDM_HW_INTF_CMD_HANG_DETECT,
	CAM_CDM_HW_INTF_DUMP_DBG_REGS,
	CAM_CDM_HW_INTF_CMD_INVALID,
};

+16 −0
Original line number Diff line number Diff line
@@ -823,6 +823,22 @@ int cam_cdm_process_cmd(void *hw_priv,
		rc = cam_hw_cdm_hang_detect(cdm_hw, *handle);
		break;
	}
	case CAM_CDM_HW_INTF_DUMP_DBG_REGS:
	{
		uint32_t *handle = cmd_args;

		if (sizeof(uint32_t) != arg_size) {
			CAM_ERR(CAM_CDM,
				"Invalid CDM cmd %d size=%x for handle=0x%x",
				cmd, arg_size, *handle);
				return -EINVAL;
		}

		mutex_lock(&cdm_hw->hw_mutex);
		cam_hw_cdm_dump_core_debug_registers(cdm_hw, true);
		mutex_unlock(&cdm_hw->hw_mutex);
		break;
	}
	default:
		CAM_ERR(CAM_CDM, "CDM HW intf command not valid =%d", cmd);
		break;
+2 −0
Original line number Diff line number Diff line
@@ -56,5 +56,7 @@ struct cam_cdm_bl_cb_request_entry *cam_cdm_find_request_by_bl_tag(
	uint32_t tag, struct list_head *bl_list);
void cam_cdm_notify_clients(struct cam_hw_info *cdm_hw,
	enum cam_cdm_cb_status status, void *data);
void cam_hw_cdm_dump_core_debug_registers(
	struct cam_hw_info *cdm_hw, bool pause_core);

#endif /* _CAM_CDM_CORE_COMMON_H_ */
+132 −86
Original line number Diff line number Diff line
@@ -170,14 +170,14 @@ static int cam_hw_cdm_pause_core(struct cam_hw_info *cdm_hw, bool pause)
	return rc;
}

int cam_hw_cdm_enable_core_dbg(struct cam_hw_info *cdm_hw)
int cam_hw_cdm_enable_core_dbg(struct cam_hw_info *cdm_hw, uint32_t value)
{
	int rc = 0;
	struct cam_cdm *core = (struct cam_cdm *)cdm_hw->core_info;

	if (cam_cdm_write_hw_reg(cdm_hw,
			core->offsets->cmn_reg->core_debug,
			0x10100)) {
			value)) {
		CAM_ERR(CAM_CDM, "Failed to Write CDM HW core debug");
		rc = -EIO;
	}
@@ -264,24 +264,7 @@ int cam_hw_cdm_bl_fifo_pending_bl_rb_in_fifo(
	return rc;
}

int cam_hw_cdm_enable_core_dbg_per_fifo(
		struct cam_hw_info *cdm_hw,
		uint32_t            fifo_idx)
{
	int rc = 0;
	struct cam_cdm *core = (struct cam_cdm *)cdm_hw->core_info;

	if (cam_cdm_write_hw_reg(cdm_hw,
			core->offsets->cmn_reg->core_debug,
			(0x10100 | fifo_idx << 20))) {
		CAM_ERR(CAM_CDM, "Failed to Write CDM HW core debug");
		rc = -EIO;
	}

	return rc;
}

void cam_hw_cdm_dump_bl_fifo_data(struct cam_hw_info *cdm_hw)
static void cam_hw_cdm_dump_bl_fifo_data(struct cam_hw_info *cdm_hw)
{
	struct cam_cdm *core = (struct cam_cdm *)cdm_hw->core_info;
	int i, j;
@@ -290,12 +273,6 @@ void cam_hw_cdm_dump_bl_fifo_data(struct cam_hw_info *cdm_hw)
	for (i = 0; i < core->offsets->reg_data->num_bl_fifo; i++) {
		cam_hw_cdm_bl_fifo_pending_bl_rb_in_fifo(cdm_hw,
			i, &num_pending_req);

		if (cam_hw_cdm_enable_core_dbg_per_fifo(cdm_hw, i)) {
			CAM_ERR(CAM_CDM,
				"Problem in selecting the fifo for readback");
			continue;
		}
		for (j = 0; j < num_pending_req ; j++) {
			cam_cdm_write_hw_reg(cdm_hw,
				core->offsets->cmn_reg->bl_fifo_rb, j);
@@ -317,89 +294,152 @@ void cam_hw_cdm_dump_bl_fifo_data(struct cam_hw_info *cdm_hw)
	}
}

void cam_hw_cdm_dump_core_debug_registers(
	struct cam_hw_info *cdm_hw)
void cam_hw_cdm_dump_core_debug_registers(struct cam_hw_info *cdm_hw,
	bool pause_core)
{
	uint32_t dump_reg, core_dbg;
	uint32_t dump_reg[4], core_dbg = 0x100;
	int i;
	bool is_core_paused_already;
	struct cam_cdm *core = (struct cam_cdm *)cdm_hw->core_info;
	const struct cam_cdm_icl_regs *inv_cmd_log =
		core->offsets->cmn_reg->icl_reg;

	cam_cdm_read_hw_reg(cdm_hw, core->offsets->cmn_reg->core_en, &dump_reg);
	CAM_INFO(CAM_CDM, "CDM HW core status=%x", dump_reg);

	cam_cdm_read_hw_reg(cdm_hw, core->offsets->cmn_reg->usr_data,
		&dump_reg);
	CAM_INFO(CAM_CDM, "CDM HW core userdata=0x%x", dump_reg);
	cam_cdm_read_hw_reg(cdm_hw, core->offsets->cmn_reg->core_en,
		&dump_reg[0]);

	if (pause_core) {
		cam_hw_cdm_pause_core(cdm_hw, true);
		usleep_range(1000, 1010);
	}
	cam_hw_cdm_enable_core_dbg(cdm_hw, core_dbg);

	cam_cdm_read_hw_reg(cdm_hw, core->offsets->cmn_reg->usr_data,
		&dump_reg[1]);

	cam_cdm_read_hw_reg(cdm_hw,
		core->offsets->cmn_reg->debug_status,
		&dump_reg);
	CAM_INFO(CAM_CDM, "CDM HW Debug status reg=%x", dump_reg);
	cam_cdm_read_hw_reg(cdm_hw,
		core->offsets->cmn_reg->core_debug,
		&core_dbg);
		&dump_reg[2]);

	CAM_INFO(CAM_CDM, "Core stat 0x%x udata 0x%x dbg_stat 0x%x",
			dump_reg[0], dump_reg[1], dump_reg[2]);

	if (core_dbg & 0x100) {
		cam_cdm_read_hw_reg(cdm_hw,
			core->offsets->cmn_reg->last_ahb_addr,
			&dump_reg);
		CAM_INFO(CAM_CDM, "AHB dump reglastaddr=%x", dump_reg);
			&dump_reg[0]);
		cam_cdm_read_hw_reg(cdm_hw,
			core->offsets->cmn_reg->last_ahb_data,
			&dump_reg);
		CAM_INFO(CAM_CDM, "AHB dump reglastdata=%x", dump_reg);
			&dump_reg[1]);
		CAM_INFO(CAM_CDM, "AHB dump lastaddr=0x%x lastdata=0x%x",
			dump_reg[0], dump_reg[1]);
	} else {
		CAM_INFO(CAM_CDM, "CDM HW AHB dump not enable");
	}

	if (inv_cmd_log) {
		if (inv_cmd_log->misc_regs) {
			cam_cdm_read_hw_reg(cdm_hw,
				inv_cmd_log->misc_regs->icl_status,
				&dump_reg[0]);
			cam_cdm_read_hw_reg(cdm_hw,
				inv_cmd_log->misc_regs->icl_inv_bl_addr,
				&dump_reg[1]);
			CAM_INFO(CAM_CDM,
				"Last Inv Cmd Log(ICL)Status: 0x%x bl_addr: 0x%x",
				dump_reg[0], dump_reg[1]);
		}
		if (inv_cmd_log->data_regs) {
			cam_cdm_read_hw_reg(cdm_hw,
				inv_cmd_log->data_regs->icl_inv_data,
				&dump_reg[0]);
			CAM_INFO(CAM_CDM, "First word of Last Inv cmd: 0x%x",
				dump_reg[0]);

			cam_cdm_read_hw_reg(cdm_hw,
				inv_cmd_log->data_regs->icl_last_data_0,
				&dump_reg[0]);
			cam_cdm_read_hw_reg(cdm_hw,
				inv_cmd_log->data_regs->icl_last_data_1,
				&dump_reg[1]);
			cam_cdm_read_hw_reg(cdm_hw,
				inv_cmd_log->data_regs->icl_last_data_2,
				&dump_reg[2]);


			CAM_INFO(CAM_CDM, "Last good cmd word 0x%x 0x%x 0x%x",
					dump_reg[0], dump_reg[1], dump_reg[2]);
		}
	}

	if (core_dbg & 0x10000) {
		cam_cdm_read_hw_reg(cdm_hw,
			core->offsets->cmn_reg->core_en, &dump_reg[0]);
		is_core_paused_already = (bool)(dump_reg[0] & 0x20);
		if (!is_core_paused_already) {
			cam_hw_cdm_pause_core(cdm_hw, true);
			usleep_range(1000, 1010);
		}

		cam_hw_cdm_dump_bl_fifo_data(cdm_hw);

	CAM_INFO(CAM_CDM, "CDM HW default dump");
		if (!is_core_paused_already)
			cam_hw_cdm_pause_core(cdm_hw, false);
	}

	cam_cdm_read_hw_reg(cdm_hw,
		core->offsets->cmn_reg->core_cfg, &dump_reg);
	CAM_INFO(CAM_CDM, "CDM HW core cfg=%x", dump_reg);
		core->offsets->cmn_reg->core_cfg, &dump_reg[0]);
	CAM_INFO(CAM_CDM, "CDM HW core cfg=0x%x", dump_reg[0]);

	for (i = 0; i <
		core->offsets->reg_data->num_bl_fifo_irq;
		i++) {
		cam_cdm_read_hw_reg(cdm_hw,
			core->offsets->irq_reg[i]->irq_status, &dump_reg);
		CAM_INFO(CAM_CDM, "CDM HW irq status%d=%x", i, dump_reg);

			core->offsets->irq_reg[i]->irq_status, &dump_reg[0]);
		cam_cdm_read_hw_reg(cdm_hw,
			core->offsets->irq_reg[i]->irq_set, &dump_reg);
		CAM_INFO(CAM_CDM, "CDM HW irq set%d=%x", i, dump_reg);

			core->offsets->irq_reg[i]->irq_set, &dump_reg[1]);
		cam_cdm_read_hw_reg(cdm_hw,
			core->offsets->irq_reg[i]->irq_mask, &dump_reg);
		CAM_INFO(CAM_CDM, "CDM HW irq mask%d=%x", i, dump_reg);

			core->offsets->irq_reg[i]->irq_mask, &dump_reg[2]);
		cam_cdm_read_hw_reg(cdm_hw,
			core->offsets->irq_reg[i]->irq_clear, &dump_reg);
		CAM_INFO(CAM_CDM, "CDM HW irq clear%d=%x", i, dump_reg);
			core->offsets->irq_reg[i]->irq_clear, &dump_reg[3]);

		CAM_INFO(CAM_CDM,
			"cnt %d irq status 0x%x set 0x%x mask 0x%x clear 0x%x",
			i, dump_reg[0], dump_reg[1], dump_reg[2], dump_reg[3]);
	}

	cam_cdm_read_hw_reg(cdm_hw,
		core->offsets->cmn_reg->current_bl_base, &dump_reg);
	CAM_INFO(CAM_CDM, "CDM HW current BL base=%x", dump_reg);
		core->offsets->cmn_reg->current_bl_base, &dump_reg[0]);
	cam_cdm_read_hw_reg(cdm_hw,
		core->offsets->cmn_reg->current_used_ahb_base, &dump_reg[1]);
	CAM_INFO(CAM_CDM, "curr BL base 0x%x AHB base 0x%x",
		dump_reg[0], dump_reg[1]);

	cam_cdm_read_hw_reg(cdm_hw,
		core->offsets->cmn_reg->current_bl_len, &dump_reg);
		core->offsets->cmn_reg->wait_status, &dump_reg[0]);
	cam_cdm_read_hw_reg(cdm_hw,
		core->offsets->cmn_reg->comp_wait[0]->comp_wait_status,
		&dump_reg[1]);
	cam_cdm_read_hw_reg(cdm_hw,
		core->offsets->cmn_reg->comp_wait[1]->comp_wait_status,
		&dump_reg[2]);
	CAM_INFO(CAM_CDM, "wait status 0x%x comp wait status 0x%x: 0x%x",
		dump_reg[0], dump_reg[1], dump_reg[2]);

	cam_cdm_read_hw_reg(cdm_hw,
		core->offsets->cmn_reg->current_bl_len, &dump_reg[0]);
	CAM_INFO(CAM_CDM,
		"CDM HW current BL len=%d ARB %d FIFO %d tag=%d, ",
		(dump_reg & CAM_CDM_CURRENT_BL_LEN),
		(dump_reg & CAM_CDM_CURRENT_BL_ARB) >>
		(dump_reg[0] & CAM_CDM_CURRENT_BL_LEN),
		(dump_reg[0] & CAM_CDM_CURRENT_BL_ARB) >>
			CAM_CDM_CURRENT_BL_ARB_SHIFT,
		(dump_reg & CAM_CDM_CURRENT_BL_FIFO) >>
		(dump_reg[0] & CAM_CDM_CURRENT_BL_FIFO) >>
			CAM_CDM_CURRENT_BL_FIFO_SHIFT,
		(dump_reg & CAM_CDM_CURRENT_BL_TAG) >>
		(dump_reg[0] & CAM_CDM_CURRENT_BL_TAG) >>
			CAM_CDM_CURRENT_BL_TAG_SHIFT);

	cam_cdm_read_hw_reg(cdm_hw,
		core->offsets->cmn_reg->current_used_ahb_base, &dump_reg);
	CAM_INFO(CAM_CDM, "CDM HW current AHB base=%x", dump_reg);

	cam_hw_cdm_disable_core_dbg(cdm_hw);
	if (pause_core)
		cam_hw_cdm_pause_core(cdm_hw, false);
}

enum cam_cdm_arbitration cam_cdm_get_arbitration_type(
@@ -1107,11 +1147,15 @@ static void cam_hw_cdm_reset_cleanup(
	int i;
	struct cam_cdm_bl_cb_request_entry *node, *tnode;
	bool flush_hw = false;
	bool reset_err = false;

	if (test_bit(CAM_CDM_ERROR_HW_STATUS, &core->cdm_status) ||
		test_bit(CAM_CDM_FLUSH_HW_STATUS, &core->cdm_status))
		flush_hw = true;

	if (test_bit(CAM_CDM_ERROR_HW_STATUS, &core->cdm_status))
		reset_err = true;

	for (i = 0; i < core->offsets->reg_data->num_bl_fifo; i++) {
		list_for_each_entry_safe(node, tnode,
			&core->bl_fifo[i].bl_request_list, entry) {
@@ -1120,12 +1164,19 @@ static void cam_hw_cdm_reset_cleanup(
				CAM_DBG(CAM_CDM,
					"Notifying client %d for tag %d",
					node->client_hdl, node->bl_tag);
				if (flush_hw)
				if (flush_hw) {
					enum cam_cdm_cb_status status;

					status = reset_err ?
						CAM_CDM_CB_STATUS_HW_ERROR :
						CAM_CDM_CB_STATUS_HW_RESUBMIT;

					cam_cdm_notify_clients(cdm_hw,
						(node->client_hdl == handle) ?
						CAM_CDM_CB_STATUS_HW_FLUSH :
						CAM_CDM_CB_STATUS_HW_RESUBMIT,
						status,
						(void *)node);
				}
				else
					cam_cdm_notify_clients(cdm_hw,
						CAM_CDM_CB_STATUS_HW_RESET_DONE,
@@ -1268,7 +1319,7 @@ static void cam_hw_cdm_work(struct work_struct *work)
		 * to dump debug info
		 */
		cam_hw_cdm_pause_core(cdm_hw, true);
		cam_hw_cdm_dump_core_debug_registers(cdm_hw);
		cam_hw_cdm_dump_core_debug_registers(cdm_hw, true);

		if (payload->irq_status &
		CAM_CDM_IRQ_STATUS_ERROR_INV_CMD_MASK) {
@@ -1307,6 +1358,8 @@ static void cam_hw_cdm_work(struct work_struct *work)
				CAM_CDM_IRQ_STATUS_ERROR_INV_CMD_MASK))
			clear_bit(CAM_CDM_ERROR_HW_STATUS,
				&core->cdm_status);
	} else {
		CAM_ERR(CAM_CDM, "NULL payload");
	}
	kfree(payload);
	payload = NULL;
@@ -1329,16 +1382,8 @@ static void cam_hw_cdm_iommu_fault_handler(struct iommu_domain *domain,
		for (i = 0; i < core->offsets->reg_data->num_bl_fifo; i++)
			mutex_lock(&core->bl_fifo[i].fifo_lock);
		if (cdm_hw->hw_state == CAM_HW_STATE_POWER_UP) {
			/*
			 * First pause CDM, If it fails still proceed
			 * to dump debug info
			 */
			cam_hw_cdm_pause_core(cdm_hw, true);
			cam_hw_cdm_dump_core_debug_registers(cdm_hw);
			/* Resume CDM back */
			cam_hw_cdm_pause_core(cdm_hw, false);
		}
		else
			cam_hw_cdm_dump_core_debug_registers(cdm_hw, true);
		} else
			CAM_INFO(CAM_CDM, "CDM hw is power in off state");
		for (i = 0; i < core->offsets->reg_data->num_bl_fifo; i++)
			mutex_unlock(&core->bl_fifo[i].fifo_lock);
@@ -1647,7 +1692,7 @@ int cam_hw_cdm_handle_error_info(
		current_fifo, current_tag);

	/* dump cdm registers for further debug */
	cam_hw_cdm_dump_core_debug_registers(cdm_hw);
	cam_hw_cdm_dump_core_debug_registers(cdm_hw, false);

	for (i = 0; i < cdm_core->offsets->reg_data->num_bl_fifo; i++) {
		reset_val = reset_val |
@@ -1673,7 +1718,7 @@ int cam_hw_cdm_handle_error_info(
	if (time_left <= 0) {
		rc = -ETIMEDOUT;
		CAM_ERR(CAM_CDM, "CDM HW reset Wait failed rc=%d", rc);
		goto end;
		set_bit(CAM_CDM_RESET_ERR_STATUS, &cdm_core->cdm_status);
	}

	rc = cam_hw_cdm_set_cdm_core_cfg(cdm_hw);
@@ -1712,6 +1757,7 @@ int cam_hw_cdm_handle_error_info(
end:
	clear_bit(CAM_CDM_FLUSH_HW_STATUS, &cdm_core->cdm_status);
	clear_bit(CAM_CDM_RESET_HW_STATUS, &cdm_core->cdm_status);
	clear_bit(CAM_CDM_RESET_ERR_STATUS, &cdm_core->cdm_status);
	for (i = 0; i < cdm_core->offsets->reg_data->num_bl_fifo; i++)
		mutex_unlock(&cdm_core->bl_fifo[i].fifo_lock);

+27 −1
Original line number Diff line number Diff line
// 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/delay.h>
@@ -506,6 +506,32 @@ int cam_cdm_detect_hang_error(uint32_t handle)
}
EXPORT_SYMBOL(cam_cdm_detect_hang_error);

int cam_cdm_dump_debug_registers(uint32_t handle)
{
	uint32_t hw_index;
	int rc = -EINVAL;
	struct cam_hw_intf *hw;

	if (get_cdm_mgr_refcount()) {
		CAM_ERR(CAM_CDM, "CDM intf mgr get refcount failed");
		rc = -EPERM;
		return rc;
	}

	hw_index = CAM_CDM_GET_HW_IDX(handle);
	if (hw_index < CAM_CDM_INTF_MGR_MAX_SUPPORTED_CDM) {
		hw = cdm_mgr.nodes[hw_index].device;
		if (hw && hw->hw_ops.process_cmd)
			rc = hw->hw_ops.process_cmd(hw->hw_priv,
				CAM_CDM_HW_INTF_DUMP_DBG_REGS,
				&handle,
				sizeof(handle));
	}
	put_cdm_mgr_refcount();

	return rc;
}

int cam_cdm_intf_register_hw_cdm(struct cam_hw_intf *hw,
	struct cam_cdm_private_dt_data *data, enum cam_cdm_type type,
	uint32_t *index)
Loading