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

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

Merge "msm: camera: tfe: LDAR dump for TFE" into camera-kernel.lnx.3.1

parents 812586fe 3a9861ae
Loading
Loading
Loading
Loading
+166 −7
Original line number Diff line number Diff line
@@ -118,7 +118,9 @@ static int cam_tfe_mgr_regspace_data_cb(uint32_t reg_base_type,

static int cam_tfe_mgr_handle_reg_dump(struct cam_tfe_hw_mgr_ctx *ctx,
	struct cam_cmd_buf_desc *reg_dump_buf_desc, uint32_t num_reg_dump_buf,
	uint32_t meta_type)
	uint32_t meta_type,
	void *soc_dump_args,
	bool user_triggered_dump)
{
	int rc = -EINVAL, i;

@@ -142,8 +144,8 @@ static int cam_tfe_mgr_handle_reg_dump(struct cam_tfe_hw_mgr_ctx *ctx,
				&reg_dump_buf_desc[i],
				ctx->applied_req_id,
				cam_tfe_mgr_regspace_data_cb,
				NULL,
				false);
				soc_dump_args,
				user_triggered_dump);
			if (rc) {
				CAM_ERR(CAM_ISP,
					"Reg dump failed at idx: %d, rc: %d req_id: %llu meta type: %u",
@@ -153,7 +155,7 @@ static int cam_tfe_mgr_handle_reg_dump(struct cam_tfe_hw_mgr_ctx *ctx,
		}
	}

	return 0;
	return rc;
}

static int cam_tfe_mgr_get_hw_caps(void *hw_mgr_priv,
@@ -1719,7 +1721,8 @@ void cam_tfe_cam_cdm_callback(uint32_t handle, void *userdata,
			cam_tfe_mgr_handle_reg_dump(ctx,
				hw_update_data->reg_dump_buf_desc,
				hw_update_data->num_reg_dump_buf,
				CAM_ISP_TFE_PACKET_META_REG_DUMP_PER_REQUEST);
				CAM_ISP_TFE_PACKET_META_REG_DUMP_PER_REQUEST,
				NULL, false);
		CAM_DBG(CAM_ISP,
			"Called by CDM hdl=%x, udata=%pK, status=%d, cookie=%llu ctx_index=%d",
			 handle, userdata, status, cookie, ctx->ctx_index);
@@ -2979,6 +2982,159 @@ static int cam_tfe_mgr_write(void *hw_mgr_priv, void *write_args)
	return -EPERM;
}

static int cam_tfe_mgr_user_dump_hw(
		struct cam_tfe_hw_mgr_ctx *tfe_ctx,
		struct cam_hw_dump_args *dump_args)
{
	int rc = 0;
	struct cam_hw_soc_dump_args soc_dump_args;

	if (!tfe_ctx || !dump_args) {
		CAM_ERR(CAM_ISP, "Invalid parameters %pK %pK",
			tfe_ctx, dump_args);
		return -EINVAL;
	}
	soc_dump_args.buf_handle = dump_args->buf_handle;
	soc_dump_args.request_id = dump_args->request_id;
	soc_dump_args.offset = dump_args->offset;

	rc = cam_tfe_mgr_handle_reg_dump(tfe_ctx,
		tfe_ctx->reg_dump_buf_desc,
		tfe_ctx->num_reg_dump_buf,
		CAM_ISP_PACKET_META_REG_DUMP_ON_ERROR,
		&soc_dump_args,
		true);
	if (rc) {
		CAM_DBG(CAM_ISP,
			"Dump failed req: %lld handle %u offset %u rc %d",
			dump_args->request_id,
			dump_args->buf_handle,
			dump_args->offset,
			rc);
		return rc;
	}
	dump_args->offset = soc_dump_args.offset;
	return rc;
}

static int cam_tfe_mgr_dump(void *hw_mgr_priv, void *args)
{

	struct cam_isp_hw_dump_args isp_hw_dump_args;
	struct cam_hw_dump_args *dump_args = (struct cam_hw_dump_args *)args;
	struct cam_isp_hw_mgr_res            *hw_mgr_res;
	struct cam_hw_intf                   *hw_intf;
	struct cam_tfe_hw_mgr_ctx *tfe_ctx = (struct cam_tfe_hw_mgr_ctx *)
						dump_args->ctxt_to_hw_map;
	int i;
	int rc = 0;

	/* for some targets, information about the TFE registers to be dumped
	 * is already submitted with the hw manager. In this case, we
	 * can dump just the related registers and skip going to core files.
	 * If dump to this buffer falis due to any reason, fallback to dump
	 * to the LDAR buffer
	 */
	isp_hw_dump_args.is_dump_all = true;
	if (tfe_ctx->num_reg_dump_buf) {
		rc = cam_tfe_mgr_user_dump_hw(tfe_ctx, dump_args);
		if (!rc)
			isp_hw_dump_args.is_dump_all = false;
	}

	rc  = cam_mem_get_cpu_buf(dump_args->buf_handle,
		&isp_hw_dump_args.cpu_addr,
		&isp_hw_dump_args.buf_len);

	if (rc) {
		CAM_ERR(CAM_ISP, "Invalid handle %u rc %d",
			dump_args->buf_handle, rc);
		return rc;
	}

	isp_hw_dump_args.offset = dump_args->offset;
	isp_hw_dump_args.req_id = dump_args->request_id;

	list_for_each_entry(hw_mgr_res, &tfe_ctx->res_list_tfe_csid, list) {
		for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) {
			if (!hw_mgr_res->hw_res[i])
				continue;
			hw_intf = hw_mgr_res->hw_res[i]->hw_intf;
			switch (hw_mgr_res->hw_res[i]->res_id) {
			case CAM_TFE_CSID_PATH_RES_RDI_0:
			case CAM_TFE_CSID_PATH_RES_RDI_1:
			case CAM_TFE_CSID_PATH_RES_RDI_2:
				if (tfe_ctx->is_rdi_only_context &&
					hw_intf->hw_ops.process_cmd) {
					rc = hw_intf->hw_ops.process_cmd(
						hw_intf->hw_priv,
						CAM_ISP_HW_CMD_DUMP_HW,
						&isp_hw_dump_args,
						sizeof(struct
						    cam_isp_hw_dump_args));
				}
				break;

			case CAM_TFE_CSID_PATH_RES_IPP:
				if (hw_intf->hw_ops.process_cmd) {
					rc = hw_intf->hw_ops.process_cmd(
						hw_intf->hw_priv,
						CAM_ISP_HW_CMD_DUMP_HW,
						&isp_hw_dump_args,
						sizeof(struct
						    cam_isp_hw_dump_args));
				}
				break;
			default:
				CAM_DBG(CAM_ISP, "not a valid res %d",
				hw_mgr_res->res_id);
				break;
			}
		}
	}

	list_for_each_entry(hw_mgr_res, &tfe_ctx->res_list_tfe_in, list) {
		for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) {
			if (!hw_mgr_res->hw_res[i])
				continue;
			hw_intf = hw_mgr_res->hw_res[i]->hw_intf;
			switch (hw_mgr_res->hw_res[i]->res_id) {
			case CAM_ISP_HW_TFE_IN_RDI0:
			case CAM_ISP_HW_TFE_IN_RDI1:
			case CAM_ISP_HW_TFE_IN_RDI2:
				if (tfe_ctx->is_rdi_only_context &&
					hw_intf->hw_ops.process_cmd) {
					rc = hw_intf->hw_ops.process_cmd(
						hw_intf->hw_priv,
						CAM_ISP_HW_CMD_DUMP_HW,
						&isp_hw_dump_args,
						sizeof(struct
						    cam_isp_hw_dump_args));
				}
				break;

			case CAM_ISP_HW_TFE_IN_CAMIF:
				if (hw_intf->hw_ops.process_cmd) {
					rc = hw_intf->hw_ops.process_cmd(
						hw_intf->hw_priv,
						CAM_ISP_HW_CMD_DUMP_HW,
						&isp_hw_dump_args,
						sizeof(struct
						    cam_isp_hw_dump_args));
				}
				break;
			default:
				CAM_DBG(CAM_ISP, "not a valid res %d",
				hw_mgr_res->res_id);
				break;
			}
		}
	}
	dump_args->offset = isp_hw_dump_args.offset;
	CAM_DBG(CAM_ISP, "offset %u", dump_args->offset);
	return rc;
}

static int cam_tfe_mgr_reset(void *hw_mgr_priv, void *hw_reset_args)
{
	struct cam_tfe_hw_mgr            *hw_mgr = hw_mgr_priv;
@@ -4226,7 +4382,8 @@ static int cam_tfe_mgr_cmd(void *hw_mgr_priv, void *cmd_args)

		rc = cam_tfe_mgr_handle_reg_dump(ctx, ctx->reg_dump_buf_desc,
			ctx->num_reg_dump_buf,
			CAM_ISP_TFE_PACKET_META_REG_DUMP_ON_FLUSH);
			CAM_ISP_TFE_PACKET_META_REG_DUMP_ON_FLUSH,
			NULL, false);
		if (rc) {
			CAM_ERR(CAM_ISP,
				"Reg dump on flush failed req id: %llu num_reg_dump:0x%x rc: %d",
@@ -4242,7 +4399,8 @@ static int cam_tfe_mgr_cmd(void *hw_mgr_priv, void *cmd_args)
		ctx->last_dump_err_req_id = ctx->applied_req_id;
		rc = cam_tfe_mgr_handle_reg_dump(ctx, ctx->reg_dump_buf_desc,
			ctx->num_reg_dump_buf,
			CAM_ISP_TFE_PACKET_META_REG_DUMP_ON_ERROR);
			CAM_ISP_TFE_PACKET_META_REG_DUMP_ON_ERROR,
			NULL, false);
		if (rc) {
			CAM_ERR(CAM_ISP,
				"Reg dump on error failed req id:%llu num_reg_dump:0x%x rc: %d",
@@ -5309,6 +5467,7 @@ int cam_tfe_hw_mgr_init(struct cam_hw_mgr_intf *hw_mgr_intf, int *iommu_hdl)
	hw_mgr_intf->hw_config = cam_tfe_mgr_config_hw;
	hw_mgr_intf->hw_cmd = cam_tfe_mgr_cmd;
	hw_mgr_intf->hw_reset = cam_tfe_mgr_reset;
	hw_mgr_intf->hw_dump = cam_tfe_mgr_dump;

	if (iommu_hdl)
		*iommu_hdl = g_tfe_hw_mgr.mgr_common.img_iommu_hdl;
+2 −0
Original line number Diff line number Diff line
@@ -267,6 +267,7 @@ struct cam_isp_hw_dual_isp_update_args {
 * @ buf_len:        buf len
 * @ offset:         offset of buffer
 * @ ctxt_to_hw_map: ctx to hw map
 * @ is_dump_all:    flag to indicate if all information or just bw/clk rate
 */
struct cam_isp_hw_dump_args {
	uint64_t                req_id;
@@ -274,6 +275,7 @@ struct cam_isp_hw_dump_args {
	size_t                  buf_len;
	size_t                  offset;
	void                   *ctxt_to_hw_map;
	bool                    is_dump_all;
};

/**
+103 −0
Original line number Diff line number Diff line
@@ -2301,6 +2301,106 @@ static int cam_tfe_csid_get_regdump(struct cam_tfe_csid_hw *csid_hw,
	return 0;
}

static int cam_tfe_csid_dump_hw(
	struct cam_tfe_csid_hw *csid_hw, void *cmd_args)
{
	int                             i;
	uint8_t                        *dst;
	uint32_t                       *addr, *start;
	uint64_t                       *clk_addr, *clk_start;
	uint32_t                        min_len;
	uint32_t                        num_reg;
	uint32_t                        reg_size = 0;
	size_t                          remain_len;
	struct cam_isp_hw_dump_header  *hdr;
	struct cam_isp_hw_dump_args    *dump_args =
		(struct cam_isp_hw_dump_args *)cmd_args;
	struct cam_hw_soc_info         *soc_info;

	if (!dump_args) {
		CAM_ERR(CAM_ISP, "Invalid args");
		return -EINVAL;
	}

	if (!dump_args->cpu_addr || !dump_args->buf_len) {
		CAM_ERR(CAM_ISP,
			"Invalid params %pK %zu",
			(void *)dump_args->cpu_addr,
			dump_args->buf_len);
		return -EINVAL;
	}

	if (dump_args->buf_len <= dump_args->offset) {
		CAM_WARN(CAM_ISP,
			"Dump offset overshoot offset %zu buf_len %zu",
			dump_args->offset, dump_args->buf_len);
		return -ENOSPC;
	}

	soc_info = &csid_hw->hw_info->soc_info;
	if (dump_args->is_dump_all)
		reg_size = soc_info->reg_map[0].size;

	min_len = reg_size +
		sizeof(struct cam_isp_hw_dump_header) +
		(sizeof(uint32_t) * CAM_TFE_CSID_DUMP_MISC_NUM_WORDS);
	remain_len = dump_args->buf_len - dump_args->offset;

	if (remain_len < min_len) {
		CAM_WARN(CAM_ISP, "Dump buffer exhaust remain %zu, min %u",
			remain_len, min_len);
		return -ENOSPC;
	}

	mutex_lock(&csid_hw->hw_info->hw_mutex);
	if (csid_hw->hw_info->hw_state != CAM_HW_STATE_POWER_UP) {
		CAM_ERR(CAM_ISP, "CSID:%d Invalid HW State:%d",
			csid_hw->hw_intf->hw_idx,
			csid_hw->hw_info->hw_state);
		mutex_unlock(&csid_hw->hw_info->hw_mutex);
		return -EINVAL;
	}

	if (!dump_args->is_dump_all)
		goto dump_bw;

	dst = (uint8_t *)dump_args->cpu_addr + dump_args->offset;
	hdr = (struct cam_isp_hw_dump_header *)dst;
	scnprintf(hdr->tag, CAM_ISP_HW_DUMP_TAG_MAX_LEN, "CSID_REG:");
	addr = (uint32_t *)(dst + sizeof(struct cam_isp_hw_dump_header));
	start = addr;
	num_reg = soc_info->reg_map[0].size/4;
	hdr->word_size = sizeof(uint32_t);
	*addr = soc_info->index;
	addr++;

	for (i = 0; i < num_reg; i++) {
		addr[0] = soc_info->mem_block[0]->start + (i*4);
		addr[1] = cam_io_r(soc_info->reg_map[0].mem_base
			+ (i*4));
		addr += 2;
	}

	hdr->size = hdr->word_size * (addr - start);
	dump_args->offset +=  hdr->size +
		sizeof(struct cam_isp_hw_dump_header);
dump_bw:
	dst = (char *)dump_args->cpu_addr + dump_args->offset;
	hdr = (struct cam_isp_hw_dump_header *)dst;
	scnprintf(hdr->tag, CAM_ISP_HW_DUMP_TAG_MAX_LEN, "CSID_CLK_RATE:");
	clk_addr = (uint64_t *)(dst +
		sizeof(struct cam_isp_hw_dump_header));
	clk_start = clk_addr;
	hdr->word_size = sizeof(uint64_t);
	*clk_addr++ = csid_hw->clk_rate;
	hdr->size = hdr->word_size * (clk_addr - clk_start);
	dump_args->offset +=  hdr->size +
		sizeof(struct cam_isp_hw_dump_header);
	CAM_DBG(CAM_ISP, "offset %zu", dump_args->offset);
	mutex_unlock(&csid_hw->hw_info->hw_mutex);
	return 0;
}

static int cam_tfe_csid_process_cmd(void *hw_priv,
	uint32_t cmd_type, void *cmd_args, uint32_t arg_size)
{
@@ -2332,6 +2432,9 @@ static int cam_tfe_csid_process_cmd(void *hw_priv,
	case CAM_TFE_CSID_CMD_GET_REG_DUMP:
		rc = cam_tfe_csid_get_regdump(csid_hw, cmd_args);
		break;
	case CAM_ISP_HW_CMD_DUMP_HW:
		rc = cam_tfe_csid_dump_hw(csid_hw, cmd_args);
		break;
	default:
		CAM_ERR(CAM_ISP, "CSID:%d unsupported cmd:%d",
			csid_hw->hw_intf->hw_idx, cmd_type);
+6 −0
Original line number Diff line number Diff line
@@ -12,6 +12,12 @@

#define CAM_TFE_CSID_CID_MAX                          4

/* Each word is taken as uint32_t, for dumping uint64_t count as 2 words
 * 1. soc_index
 * 2. clk_rate --> uint64_t -> 2 words
 */
#define CAM_TFE_CSID_DUMP_MISC_NUM_WORDS              3

#define TFE_CSID_CSI2_RX_INFO_PHY_DL0_EOT_CAPTURED    BIT(0)
#define TFE_CSID_CSI2_RX_INFO_PHY_DL1_EOT_CAPTURED    BIT(1)
#define TFE_CSID_CSI2_RX_INFO_PHY_DL2_EOT_CAPTURED    BIT(2)
+232 −0
Original line number Diff line number Diff line
@@ -1490,6 +1490,234 @@ static int cam_tfe_top_get_reg_dump(
	return 0;
}

static int cam_tfe_hw_dump(
	struct cam_tfe_hw_core_info *core_info,
	void                        *cmd_args,
	uint32_t                     arg_size)
{
	int                                i, j;
	uint8_t                           *dst;
	uint32_t                           reg_start_offset;
	uint32_t                           reg_dump_size = 0;
	uint32_t                           lut_dump_size = 0;
	uint32_t                           num_lut_dump_entries = 0;
	uint32_t                           num_reg;
	uint32_t                           lut_word_size, lut_size;
	uint32_t                           lut_bank_sel, lut_dmi_reg;
	uint32_t                           val;
	void __iomem                      *reg_base;
	void __iomem                      *mem_base;
	uint32_t                          *addr, *start;
	uint64_t                          *clk_waddr, *clk_wstart;
	size_t                             remain_len;
	uint32_t                           min_len;
	struct cam_hw_info                *tfe_hw_info;
	struct cam_hw_soc_info            *soc_info;
	struct cam_tfe_top_priv           *top_priv;
	struct cam_tfe_soc_private        *soc_private;
	struct cam_tfe_reg_dump_data      *reg_dump_data;
	struct cam_isp_hw_dump_header     *hdr;
	struct cam_isp_hw_dump_args       *dump_args =
		(struct cam_isp_hw_dump_args *)cmd_args;

	if (!dump_args || !core_info) {
		CAM_ERR(CAM_ISP, "Invalid args");
		return -EINVAL;
	}

	if (!dump_args->cpu_addr || !dump_args->buf_len) {
		CAM_ERR(CAM_ISP,
			"Invalid params %pK %zu",
			(void *)dump_args->cpu_addr,
			dump_args->buf_len);
		return -EINVAL;
	}

	if (dump_args->buf_len <= dump_args->offset) {
		CAM_WARN(CAM_ISP,
			"Dump offset overshoot offset %zu buf_len %zu",
			dump_args->offset, dump_args->buf_len);
		return -ENOSPC;
	}

	top_priv = (struct cam_tfe_top_priv  *)core_info->top_priv;
	tfe_hw_info =
		(struct cam_hw_info *)(top_priv->common_data.hw_intf->hw_priv);
	reg_dump_data = top_priv->common_data.reg_dump_data;
	soc_info = top_priv->common_data.soc_info;
	soc_private = top_priv->common_data.soc_info->soc_private;
	mem_base = soc_info->reg_map[TFE_CORE_BASE_IDX].mem_base;

	if (dump_args->is_dump_all) {

		/*Dump registers size*/
		for (i = 0; i < reg_dump_data->num_reg_dump_entries; i++)
			reg_dump_size +=
				(reg_dump_data->reg_entry[i].end_offset -
				reg_dump_data->reg_entry[i].start_offset);

		/*
		 * We dump the offset as well, so the total size dumped becomes
		 * multiplied by 2
		 */
		reg_dump_size *= 2;

		/* LUT dump size */
		for (i = 0; i < reg_dump_data->num_lut_dump_entries; i++)
			lut_dump_size +=
				((reg_dump_data->lut_entry[i].lut_addr_size) *
				(reg_dump_data->lut_entry[i].lut_word_size/8));

		num_lut_dump_entries = reg_dump_data->num_lut_dump_entries;
	}

	/*Minimum len comprises of:
	 * lut_dump_size + reg_dump_size + sizeof dump_header +
	 * (num_lut_dump_entries--> represents number of banks) +
	 *  (misc number of words) * sizeof(uint32_t)
	 */
	min_len = lut_dump_size + reg_dump_size +
		sizeof(struct cam_isp_hw_dump_header) +
		(num_lut_dump_entries * sizeof(uint32_t)) +
		(sizeof(uint32_t) * CAM_TFE_CORE_DUMP_MISC_NUM_WORDS);

	remain_len = dump_args->buf_len - dump_args->offset;
	if (remain_len < min_len) {
		CAM_WARN(CAM_ISP, "Dump buffer exhaust remain %zu, min %u",
			remain_len, min_len);
		return -ENOSPC;
	}

	mutex_lock(&tfe_hw_info->hw_mutex);
	if (tfe_hw_info->hw_state != CAM_HW_STATE_POWER_UP) {
		CAM_ERR(CAM_ISP, "TFE:%d HW not powered up",
			core_info->core_index);
		mutex_unlock(&tfe_hw_info->hw_mutex);
		return -EPERM;
	}

	if (!dump_args->is_dump_all)
		goto dump_bw;

	dst = (uint8_t *)dump_args->cpu_addr + dump_args->offset;
	hdr = (struct cam_isp_hw_dump_header *)dst;
	hdr->word_size = sizeof(uint32_t);
	scnprintf(hdr->tag, CAM_ISP_HW_DUMP_TAG_MAX_LEN, "TFE_REG:");
	addr = (uint32_t *)(dst + sizeof(struct cam_isp_hw_dump_header));
	start = addr;
	*addr++ = soc_info->index;
	for (i = 0; i < reg_dump_data->num_reg_dump_entries; i++) {
		num_reg  = (reg_dump_data->reg_entry[i].end_offset -
			reg_dump_data->reg_entry[i].start_offset)/4;
		reg_start_offset = reg_dump_data->reg_entry[i].start_offset;
		reg_base = mem_base + reg_start_offset;
		for (j = 0; j < num_reg; j++) {
			addr[0] =
				soc_info->mem_block[TFE_CORE_BASE_IDX]->start +
				reg_start_offset + (j*4);
			addr[1] = cam_io_r(reg_base + (j*4));
			addr += 2;
		}
	}

	/*Dump bus top registers*/
	num_reg  = (reg_dump_data->bus_write_top_end_addr -
			reg_dump_data->bus_start_addr)/4;
	reg_base = mem_base + reg_dump_data->bus_start_addr;
	reg_start_offset = soc_info->mem_block[TFE_CORE_BASE_IDX]->start +
		reg_dump_data->bus_start_addr;
	for (i = 0; i < num_reg; i++) {
		addr[0] = reg_start_offset + (i*4);
		addr[1] = cam_io_r(reg_base + (i*4));
		addr += 2;
	}

	/* Dump bus clients */
	reg_base = mem_base + reg_dump_data->bus_client_start_addr;
	reg_start_offset = soc_info->mem_block[TFE_CORE_BASE_IDX]->start +
		reg_dump_data->bus_client_start_addr;
	for (j = 0; j < reg_dump_data->num_bus_clients; j++) {

		for (i = 0; i <= 0x3c; i += 4) {
			addr[0] = reg_start_offset + i;
			addr[1] = cam_io_r(reg_base + i);
			addr += 2;
		}
		for (i = 0x60; i <= 0x80; i += 4) {
			addr[0] = reg_start_offset + (i*4);
			addr[1] = cam_io_r(reg_base + (i*4));
			addr += 2;
		}
		reg_base += reg_dump_data->bus_client_offset;
		reg_start_offset += reg_dump_data->bus_client_offset;
	}

	hdr->size = hdr->word_size * (addr - start);
	dump_args->offset +=  hdr->size +
		sizeof(struct cam_isp_hw_dump_header);

	/* Dump LUT entries */
	for (i = 0; i < reg_dump_data->num_lut_dump_entries; i++) {

		lut_bank_sel = reg_dump_data->lut_entry[i].lut_bank_sel;
		lut_size = reg_dump_data->lut_entry[i].lut_addr_size;
		lut_word_size = reg_dump_data->lut_entry[i].lut_word_size;
		lut_dmi_reg = reg_dump_data->lut_entry[i].dmi_reg_offset;
		dst = (char *)dump_args->cpu_addr + dump_args->offset;
		hdr = (struct cam_isp_hw_dump_header *)dst;
		scnprintf(hdr->tag, CAM_ISP_HW_DUMP_TAG_MAX_LEN, "LUT_REG:");
		hdr->word_size = lut_word_size/8;
		addr = (uint32_t *)(dst +
			sizeof(struct cam_isp_hw_dump_header));
		start = addr;
		*addr++ = lut_bank_sel;
		cam_io_w_mb(lut_bank_sel, mem_base + lut_dmi_reg + 4);
		cam_io_w_mb(0, mem_base + 0xC28);
		for (j = 0; j < lut_size; j++) {
			*addr = cam_io_r_mb(mem_base + 0xc30);
			addr++;
		}
		hdr->size = hdr->word_size * (addr - start);
		dump_args->offset +=  hdr->size +
			sizeof(struct cam_isp_hw_dump_header);
	}
	cam_io_w_mb(0, mem_base + 0xC24);
	cam_io_w_mb(0, mem_base + 0xC28);

dump_bw:
	dst = (char *)dump_args->cpu_addr + dump_args->offset;
	hdr = (struct cam_isp_hw_dump_header *)dst;
	scnprintf(hdr->tag, CAM_ISP_HW_DUMP_TAG_MAX_LEN, "TFE_CLK_RATE_BW:");
	clk_waddr = (uint64_t *)(dst +
		sizeof(struct cam_isp_hw_dump_header));
	clk_wstart = clk_waddr;
	hdr->word_size = sizeof(uint64_t);
	*clk_waddr++ = top_priv->hw_clk_rate;
	*clk_waddr++ = top_priv->total_bw_applied;

	hdr->size = hdr->word_size * (clk_waddr - clk_wstart);
	dump_args->offset +=  hdr->size +
		sizeof(struct cam_isp_hw_dump_header);

	dst = (char *)dump_args->cpu_addr + dump_args->offset;
	hdr = (struct cam_isp_hw_dump_header *)dst;
	scnprintf(hdr->tag, CAM_ISP_HW_DUMP_TAG_MAX_LEN, "TFE_NIU_MAXWR:");
	addr = (uint32_t *)(dst +
		sizeof(struct cam_isp_hw_dump_header));
	start = addr;
	hdr->word_size = sizeof(uint32_t);
	cam_cpas_reg_read(soc_private->cpas_handle,
		CAM_CPAS_REG_CAMNOC, 0x20, true, &val);
	*addr++ = val;
	hdr->size = hdr->word_size * (addr - start);
	dump_args->offset +=  hdr->size +
		sizeof(struct cam_isp_hw_dump_header);
	mutex_unlock(&tfe_hw_info->hw_mutex);

	CAM_DBG(CAM_ISP, "offset %zu", dump_args->offset);
	return 0;
}

static int cam_tfe_camif_irq_reg_dump(
	struct cam_tfe_hw_core_info    *core_info,
	void *cmd_args, uint32_t arg_size)
@@ -2570,6 +2798,10 @@ int cam_tfe_process_cmd(void *hw_priv, uint32_t cmd_type,
	case CAM_ISP_HW_CMD_QUERY_REGSPACE_DATA:
		*((struct cam_hw_soc_info **)cmd_args) = soc_info;
		break;
	case CAM_ISP_HW_CMD_DUMP_HW:
		rc = cam_tfe_hw_dump(core_info,
			cmd_args, arg_size);
		break;
	case CAM_ISP_HW_CMD_GET_BUF_UPDATE:
	case CAM_ISP_HW_CMD_GET_HFR_UPDATE:
	case CAM_ISP_HW_CMD_STRIPE_UPDATE:
Loading