Просмотр исходного кода

msm: camera: icp: Improve ICP debug infrastructure

On FW timeouts, dump ICP status registers and HFI queue indices.

CRs-Fixed: 3110947
Change-Id: I74561ce943c027e51b6f8b61e7ebb68d2a89982d
Signed-off-by: Karthik Anantha Ram <[email protected]>
Karthik Anantha Ram 3 лет назад
Родитель
Сommit
1df78bed63

+ 4 - 1
drivers/cam_icp/fw_inc/hfi_intf.h

@@ -1,6 +1,7 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 /* SPDX-License-Identifier: GPL-2.0-only */
 /*
 /*
  * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
  * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
  */
  */
 
 
 #ifndef _HFI_INTF_H_
 #ifndef _HFI_INTF_H_
@@ -182,8 +183,10 @@ int cam_hfi_resume(struct hfi_mem_info *hfi_mem);
 
 
 /**
 /**
  * cam_hfi_queue_dump() - utility function to dump hfi queues
  * cam_hfi_queue_dump() - utility function to dump hfi queues
+ * @dump_queue_data: if set dumps queue contents
+ *
  */
  */
-void cam_hfi_queue_dump(void);
+void cam_hfi_queue_dump(bool dump_queue_data);
 
 
 /**
 /**
  * cam_hfi_mini_dump() - utility function for mini dump
  * cam_hfi_mini_dump() - utility function for mini dump

+ 9 - 6
drivers/cam_icp/hfi.c

@@ -1,6 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0-only
 // SPDX-License-Identifier: GPL-2.0-only
 /*
 /*
  * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
  * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
  */
  */
 
 
 #include <linux/io.h>
 #include <linux/io.h>
@@ -121,7 +122,7 @@ void cam_hfi_mini_dump(struct hfi_mini_dump_info *dst)
 	dst->cmd_q_state = g_hfi->cmd_q_state;
 	dst->cmd_q_state = g_hfi->cmd_q_state;
 }
 }
 
 
-void cam_hfi_queue_dump(void)
+void cam_hfi_queue_dump(bool dump_queue_data)
 {
 {
 	struct hfi_mem_info *hfi_mem = &g_hfi->map;
 	struct hfi_mem_info *hfi_mem = &g_hfi->map;
 	struct hfi_qtbl *qtbl;
 	struct hfi_qtbl *qtbl;
@@ -135,7 +136,7 @@ void cam_hfi_queue_dump(void)
 	}
 	}
 
 
 	qtbl = (struct hfi_qtbl *)hfi_mem->qtbl.kva;
 	qtbl = (struct hfi_qtbl *)hfi_mem->qtbl.kva;
-	CAM_DBG(CAM_HFI,
+	CAM_INFO(CAM_HFI,
 		"qtbl header: version=0x%08x tbl_size=%u numq=%u qhdr_size=%u",
 		"qtbl header: version=0x%08x tbl_size=%u numq=%u qhdr_size=%u",
 		qtbl->q_tbl_hdr.qtbl_version,
 		qtbl->q_tbl_hdr.qtbl_version,
 		qtbl->q_tbl_hdr.qtbl_size,
 		qtbl->q_tbl_hdr.qtbl_size,
@@ -143,7 +144,7 @@ void cam_hfi_queue_dump(void)
 		qtbl->q_tbl_hdr.qtbl_qhdr_size);
 		qtbl->q_tbl_hdr.qtbl_qhdr_size);
 
 
 	q_hdr = &qtbl->q_hdr[Q_CMD];
 	q_hdr = &qtbl->q_hdr[Q_CMD];
-	CAM_DBG(CAM_HFI,
+	CAM_INFO(CAM_HFI,
 		"cmd_q: addr=0x%08x size=%u read_idx=%u write_idx=%u",
 		"cmd_q: addr=0x%08x size=%u read_idx=%u write_idx=%u",
 		hfi_mem->cmd_q.iova,
 		hfi_mem->cmd_q.iova,
 		q_hdr->qhdr_q_size,
 		q_hdr->qhdr_q_size,
@@ -153,10 +154,11 @@ void cam_hfi_queue_dump(void)
 	dwords = (uint32_t *)hfi_mem->cmd_q.kva;
 	dwords = (uint32_t *)hfi_mem->cmd_q.kva;
 	num_dwords = ICP_CMD_Q_SIZE_IN_BYTES >> BYTE_WORD_SHIFT;
 	num_dwords = ICP_CMD_Q_SIZE_IN_BYTES >> BYTE_WORD_SHIFT;
 
 
-	hfi_queue_dump(dwords, num_dwords);
+	if (dump_queue_data)
+		hfi_queue_dump(dwords, num_dwords);
 
 
 	q_hdr = &qtbl->q_hdr[Q_MSG];
 	q_hdr = &qtbl->q_hdr[Q_MSG];
-	CAM_DBG(CAM_HFI,
+	CAM_INFO(CAM_HFI,
 		"msg_q: addr=0x%08x size=%u read_idx=%u write_idx=%u",
 		"msg_q: addr=0x%08x size=%u read_idx=%u write_idx=%u",
 		hfi_mem->msg_q.iova,
 		hfi_mem->msg_q.iova,
 		q_hdr->qhdr_q_size,
 		q_hdr->qhdr_q_size,
@@ -166,7 +168,8 @@ void cam_hfi_queue_dump(void)
 	dwords = (uint32_t *)hfi_mem->msg_q.kva;
 	dwords = (uint32_t *)hfi_mem->msg_q.kva;
 	num_dwords = ICP_MSG_Q_SIZE_IN_BYTES >> BYTE_WORD_SHIFT;
 	num_dwords = ICP_MSG_Q_SIZE_IN_BYTES >> BYTE_WORD_SHIFT;
 
 
-	hfi_queue_dump(dwords, num_dwords);
+	if (dump_queue_data)
+		hfi_queue_dump(dwords, num_dwords);
 }
 }
 
 
 #ifndef CONFIG_CAM_PRESIL
 #ifndef CONFIG_CAM_PRESIL

+ 5 - 0
drivers/cam_icp/icp_hw/a5_hw/a5_core.c

@@ -1,6 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0-only
 // SPDX-License-Identifier: GPL-2.0-only
 /*
 /*
  * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
  * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
  */
  */
 
 
 #include <linux/slab.h>
 #include <linux/slab.h>
@@ -746,6 +747,10 @@ int cam_a5_process_cmd(void *device_priv, uint32_t cmd_type,
 		rc = cam_a5_fw_mini_dump(dump_args, core_info);
 		rc = cam_a5_fw_mini_dump(dump_args, core_info);
 		break;
 		break;
 	}
 	}
+	case CAM_ICP_CMD_HW_REG_DUMP: {
+		/* reg dump not supported */
+		break;
+	}
 	default:
 	default:
 		break;
 		break;
 	}
 	}

+ 25 - 16
drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c

@@ -126,6 +126,19 @@ static const char *cam_icp_dev_type_to_name(
 	}
 	}
 }
 }
 
 
+static inline void cam_icp_dump_debug_info(bool skip_dump)
+{
+	struct cam_hw_intf *icp_dev_intf = icp_hw_mgr.icp_dev_intf;
+
+	if (skip_dump)
+		return;
+
+	cam_icp_mgr_process_dbg_buf(icp_hw_mgr.icp_dbg_lvl);
+	cam_hfi_queue_dump(false);
+	icp_dev_intf->hw_ops.process_cmd(
+		icp_dev_intf->hw_priv, CAM_ICP_CMD_HW_REG_DUMP, NULL, 0x0);
+}
+
 static int cam_icp_send_ubwc_cfg(struct cam_icp_hw_mgr *hw_mgr)
 static int cam_icp_send_ubwc_cfg(struct cam_icp_hw_mgr *hw_mgr)
 {
 {
 	struct cam_hw_intf *icp_dev_intf = hw_mgr->icp_dev_intf;
 	struct cam_hw_intf *icp_dev_intf = hw_mgr->icp_dev_intf;
@@ -2122,6 +2135,7 @@ static int cam_icp_mgr_cleanup_ctx(struct cam_icp_hw_ctx_data *ctx_data)
 		ctx_data->hfi_frame_process.in_free_resource[i] = 0;
 		ctx_data->hfi_frame_process.in_free_resource[i] = 0;
 	}
 	}
 
 
+	ctx_data->abort_timed_out = false;
 	return 0;
 	return 0;
 }
 }
 
 
@@ -2605,6 +2619,7 @@ static int cam_icp_mgr_trigger_recovery(struct cam_icp_hw_mgr *hw_mgr)
 
 
 	sfr_buffer = (struct sfr_buf *)icp_hw_mgr.hfi_mem.sfr_buf.kva;
 	sfr_buffer = (struct sfr_buf *)icp_hw_mgr.hfi_mem.sfr_buf.kva;
 	CAM_WARN(CAM_ICP, "SFR:%s", sfr_buffer->msg);
 	CAM_WARN(CAM_ICP, "SFR:%s", sfr_buffer->msg);
+	cam_icp_dump_debug_info(false);
 
 
 	cam_icp_mgr_ipe_bps_get_gdsc_control(hw_mgr);
 	cam_icp_mgr_ipe_bps_get_gdsc_control(hw_mgr);
 	cam_icp_ipebps_reset(hw_mgr);
 	cam_icp_ipebps_reset(hw_mgr);
@@ -2639,7 +2654,6 @@ static int cam_icp_mgr_process_fatal_error(
 			BUG();
 			BUG();
 		}
 		}
 		rc = cam_icp_mgr_trigger_recovery(hw_mgr);
 		rc = cam_icp_mgr_trigger_recovery(hw_mgr);
-		cam_icp_mgr_process_dbg_buf(icp_hw_mgr.icp_dbg_lvl);
 	}
 	}
 
 
 	return rc;
 	return rc;
@@ -3743,8 +3757,8 @@ static int cam_icp_mgr_abort_handle(
 			CAM_ERR(CAM_ICP,
 			CAM_ERR(CAM_ICP,
 				"FW timeout/err in abort handle command ctx: %u",
 				"FW timeout/err in abort handle command ctx: %u",
 				ctx_data->ctx_id);
 				ctx_data->ctx_id);
-			cam_icp_mgr_process_dbg_buf(icp_hw_mgr.icp_dbg_lvl);
-			cam_hfi_queue_dump();
+			cam_icp_dump_debug_info(false);
+			ctx_data->abort_timed_out = true;
 		}
 		}
 	}
 	}
 
 
@@ -3800,8 +3814,7 @@ static int cam_icp_mgr_destroy_handle(
 		rc = -ETIMEDOUT;
 		rc = -ETIMEDOUT;
 		CAM_ERR(CAM_ICP, "FW response timeout: %d for %u",
 		CAM_ERR(CAM_ICP, "FW response timeout: %d for %u",
 			rc, ctx_data->ctx_id);
 			rc, ctx_data->ctx_id);
-		cam_icp_mgr_process_dbg_buf(icp_hw_mgr.icp_dbg_lvl);
-		cam_hfi_queue_dump();
+		cam_icp_dump_debug_info(ctx_data->abort_timed_out);
 	}
 	}
 	kfree(destroy_cmd);
 	kfree(destroy_cmd);
 	return rc;
 	return rc;
@@ -4206,8 +4219,7 @@ static int cam_icp_mgr_send_fw_init(struct cam_icp_hw_mgr *hw_mgr)
 	if (!rem_jiffies) {
 	if (!rem_jiffies) {
 		rc = -ETIMEDOUT;
 		rc = -ETIMEDOUT;
 		CAM_ERR(CAM_ICP, "FW response timed out %d", rc);
 		CAM_ERR(CAM_ICP, "FW response timed out %d", rc);
-		cam_icp_mgr_process_dbg_buf(icp_hw_mgr.icp_dbg_lvl);
-		cam_hfi_queue_dump();
+		cam_icp_dump_debug_info(false);
 	}
 	}
 	CAM_DBG(CAM_ICP, "Done Waiting for INIT DONE Message");
 	CAM_DBG(CAM_ICP, "Done Waiting for INIT DONE Message");
 
 
@@ -4512,8 +4524,7 @@ static int cam_icp_mgr_send_config_io(struct cam_icp_hw_ctx_data *ctx_data,
 			ctx_data->ctx_id, ctx_data->acquire_dev_cmd.dev_handle,
 			ctx_data->ctx_id, ctx_data->acquire_dev_cmd.dev_handle,
 			ctx_data->acquire_dev_cmd.session_handle,
 			ctx_data->acquire_dev_cmd.session_handle,
 			ctx_data->icp_dev_acquire_info->dev_type);
 			ctx_data->icp_dev_acquire_info->dev_type);
-		cam_icp_mgr_process_dbg_buf(icp_hw_mgr.icp_dbg_lvl);
-		cam_hfi_queue_dump();
+		cam_icp_dump_debug_info(false);
 	}
 	}
 
 
 	return rc;
 	return rc;
@@ -4977,7 +4988,7 @@ static int cam_icp_process_stream_settings(
 	if (!rem_jiffies) {
 	if (!rem_jiffies) {
 		rc = -ETIMEDOUT;
 		rc = -ETIMEDOUT;
 		CAM_ERR(CAM_ICP, "FW response timed out %d", rc);
 		CAM_ERR(CAM_ICP, "FW response timed out %d", rc);
-		cam_hfi_queue_dump();
+		cam_icp_dump_debug_info(false);
 	}
 	}
 
 
 end:
 end:
@@ -5750,8 +5761,8 @@ static int cam_icp_mgr_enqueue_abort(
 			CAM_ERR(CAM_ICP,
 			CAM_ERR(CAM_ICP,
 				"FW timeout/err in abort handle command ctx: %u",
 				"FW timeout/err in abort handle command ctx: %u",
 				ctx_data->ctx_id);
 				ctx_data->ctx_id);
-			cam_icp_mgr_process_dbg_buf(icp_hw_mgr.icp_dbg_lvl);
-			cam_hfi_queue_dump();
+			cam_icp_dump_debug_info(false);
+			ctx_data->abort_timed_out = true;
 			return rc;
 			return rc;
 		}
 		}
 	}
 	}
@@ -6078,8 +6089,7 @@ static int cam_icp_mgr_create_handle(uint32_t dev_type,
 	if (!rem_jiffies) {
 	if (!rem_jiffies) {
 		rc = -ETIMEDOUT;
 		rc = -ETIMEDOUT;
 		CAM_ERR(CAM_ICP, "FW response timed out %d", rc);
 		CAM_ERR(CAM_ICP, "FW response timed out %d", rc);
-		cam_icp_mgr_process_dbg_buf(icp_hw_mgr.icp_dbg_lvl);
-		cam_hfi_queue_dump();
+		cam_icp_dump_debug_info(false);
 	}
 	}
 
 
 	if (ctx_data->fw_handle == 0) {
 	if (ctx_data->fw_handle == 0) {
@@ -6126,8 +6136,7 @@ static int cam_icp_mgr_send_ping(struct cam_icp_hw_ctx_data *ctx_data)
 	if (!rem_jiffies) {
 	if (!rem_jiffies) {
 		rc = -ETIMEDOUT;
 		rc = -ETIMEDOUT;
 		CAM_ERR(CAM_ICP, "FW response timed out %d", rc);
 		CAM_ERR(CAM_ICP, "FW response timed out %d", rc);
-		cam_icp_mgr_process_dbg_buf(icp_hw_mgr.icp_dbg_lvl);
-		cam_hfi_queue_dump();
+		cam_icp_dump_debug_info(false);
 	}
 	}
 
 
 	return rc;
 	return rc;

+ 3 - 0
drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h

@@ -1,6 +1,7 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 /* SPDX-License-Identifier: GPL-2.0-only */
 /*
 /*
  * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
  * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
  */
  */
 
 
 #ifndef CAM_ICP_HW_MGR_H
 #ifndef CAM_ICP_HW_MGR_H
@@ -270,6 +271,7 @@ struct cam_ctx_clk_info {
  * @watch_dog_reset_counter: Counter for watch dog reset
  * @watch_dog_reset_counter: Counter for watch dog reset
  * @icp_dev_io_info: io config resource
  * @icp_dev_io_info: io config resource
  * @last_flush_req: last flush req for this ctx
  * @last_flush_req: last flush req for this ctx
+ * @abort_timed_out: Indicates if abort timed out
  */
  */
 struct cam_icp_hw_ctx_data {
 struct cam_icp_hw_ctx_data {
 	void *context_priv;
 	void *context_priv;
@@ -293,6 +295,7 @@ struct cam_icp_hw_ctx_data {
 	struct cam_icp_acquire_dev_info icp_dev_io_info;
 	struct cam_icp_acquire_dev_info icp_dev_io_info;
 	uint64_t last_flush_req;
 	uint64_t last_flush_req;
 	char ctx_id_string[128];
 	char ctx_id_string[128];
+	bool abort_timed_out;
 };
 };
 
 
 /**
 /**

+ 2 - 0
drivers/cam_icp/icp_hw/icp_hw_mgr/include/cam_icp_hw_intf.h

@@ -1,6 +1,7 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 /* SPDX-License-Identifier: GPL-2.0-only */
 /*
 /*
  * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
  * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
  */
  */
 
 
 #ifndef CAM_ICP_HW_INTF_H
 #ifndef CAM_ICP_HW_INTF_H
@@ -43,6 +44,7 @@ enum cam_icp_cmd_type {
 	CAM_ICP_CMD_CLK_UPDATE,
 	CAM_ICP_CMD_CLK_UPDATE,
 	CAM_ICP_CMD_HW_DUMP,
 	CAM_ICP_CMD_HW_DUMP,
 	CAM_ICP_CMD_HW_MINI_DUMP,
 	CAM_ICP_CMD_HW_MINI_DUMP,
+	CAM_ICP_CMD_HW_REG_DUMP,
 	CAM_ICP_CMD_MAX,
 	CAM_ICP_CMD_MAX,
 };
 };
 
 

+ 25 - 11
drivers/cam_icp/icp_hw/lx7_hw/lx7_core.c

@@ -27,8 +27,6 @@
 #define TZ_STATE_SUSPEND 0
 #define TZ_STATE_SUSPEND 0
 #define TZ_STATE_RESUME  1
 #define TZ_STATE_RESUME  1
 
 
-#define LX7_GEN_PURPOSE_REG_OFFSET 0x20
-
 #define ICP_FW_NAME_MAX_SIZE    32
 #define ICP_FW_NAME_MAX_SIZE    32
 
 
 #define PC_POLL_DELAY_US 100
 #define PC_POLL_DELAY_US 100
@@ -702,6 +700,21 @@ static int cam_lx7_shutdown(struct cam_hw_info *lx7_info)
 	return rc;
 	return rc;
 }
 }
 
 
+static inline void __cam_lx7_core_reg_dump(
+	struct cam_hw_info *lx7_info)
+{
+	void __iomem *cirq_base = lx7_info->soc_info.reg_map[LX7_CIRQ_BASE].mem_base;
+	void __iomem *csr_base = lx7_info->soc_info.reg_map[LX7_CSR_BASE].mem_base;
+
+	CAM_INFO(CAM_ICP,
+		"CIRQ IB_status0:0x%x IB_Status1:0x%x PFault:0x%x CSR debug_status:0x%x debug_ctrl:0x%x",
+		cam_io_r_mb(cirq_base + ICP_LX7_CIRQ_IB_STATUS0),
+		cam_io_r_mb(cirq_base + ICP_LX7_CIRQ_IB_STATUS1),
+		cam_io_r_mb(cirq_base + ICP_LX7_CIRQ_PFAULT_INFO),
+		cam_io_r_mb(csr_base + LX7_CSR_DBG_STATUS_REG_OFFSET),
+		cam_io_r_mb(csr_base + LX7_CSR_DBG_CTRL_REG_OFFSET));
+}
+
 /* API controls collapse/resume of ICP */
 /* API controls collapse/resume of ICP */
 static int cam_lx7_core_control(
 static int cam_lx7_core_control(
 	struct cam_hw_info *lx7_info,
 	struct cam_hw_info *lx7_info,
@@ -713,16 +726,12 @@ static int cam_lx7_core_control(
 
 
 	if (core_info->use_sec_pil) {
 	if (core_info->use_sec_pil) {
 		rc = qcom_scm_set_remote_state(state, CAM_FW_PAS_ID);
 		rc = qcom_scm_set_remote_state(state, CAM_FW_PAS_ID);
-		if (rc)
+		if (rc) {
 			CAM_ERR(CAM_ICP,
 			CAM_ERR(CAM_ICP,
-				"remote state set to %s failed rc=%d IB_status0=0x%x IB_Status1=0x%x PFault=0x%x",
-				state == TZ_STATE_RESUME ? "resume" : "suspend", rc,
-				cam_io_r_mb(lx7_info->soc_info.reg_map[LX7_CIRQ_BASE].mem_base +
-					ICP_LX7_CIRQ_IB_STATUS0),
-				cam_io_r_mb(lx7_info->soc_info.reg_map[LX7_CIRQ_BASE].mem_base +
-					ICP_LX7_CIRQ_IB_STATUS1),
-				cam_io_r_mb(lx7_info->soc_info.reg_map[LX7_CIRQ_BASE].mem_base +
-					ICP_LX7_CIRQ_PFAULT_INFO));
+				"remote state set to %s failed rc=%d",
+				(state == TZ_STATE_RESUME ? "resume" : "suspend"), rc);
+			__cam_lx7_core_reg_dump(lx7_info);
+		}
 	} else {
 	} else {
 		if (state == TZ_STATE_RESUME) {
 		if (state == TZ_STATE_RESUME) {
 			rc = __cam_lx7_power_resume(lx7_info);
 			rc = __cam_lx7_power_resume(lx7_info);
@@ -886,6 +895,11 @@ int cam_lx7_process_cmd(void *priv, uint32_t cmd_type,
 		rc = __cam_lx7_fw_mini_dump(lx7_info->core_info, args);
 		rc = __cam_lx7_fw_mini_dump(lx7_info->core_info, args);
 		break;
 		break;
 	}
 	}
+	case CAM_ICP_CMD_HW_REG_DUMP: {
+		__cam_lx7_core_reg_dump(lx7_info);
+		rc = 0;
+		break;
+	}
 	default:
 	default:
 		CAM_ERR(CAM_ICP, "invalid command type=%u", cmd_type);
 		CAM_ERR(CAM_ICP, "invalid command type=%u", cmd_type);
 		break;
 		break;

+ 5 - 0
drivers/cam_icp/icp_hw/lx7_hw/lx7_reg.h

@@ -7,6 +7,11 @@
 #ifndef _CAM_LX7_REG_H_
 #ifndef _CAM_LX7_REG_H_
 #define _CAM_LX7_REG_H_
 #define _CAM_LX7_REG_H_
 
 
+/* ICP CSR info */
+#define LX7_GEN_PURPOSE_REG_OFFSET     0x20
+#define LX7_CSR_DBG_STATUS_REG_OFFSET  0xC0
+#define LX7_CSR_DBG_CTRL_REG_OFFSET    0xC4
+
 /* ICP_SYS - Protected reg space defined in AC policy */
 /* ICP_SYS - Protected reg space defined in AC policy */
 #define ICP_LX7_SYS_RESET      0x0
 #define ICP_LX7_SYS_RESET      0x0
 #define ICP_LX7_SYS_CONTROL    0x4
 #define ICP_LX7_SYS_CONTROL    0x4