From c5f8e70b0f3697e04d2f59c0b39ac1c15bfc29a4 Mon Sep 17 00:00:00 2001 From: shiwgupt Date: Mon, 14 Sep 2020 15:55:56 +0530 Subject: [PATCH] msm: camera: cci: Enable compilation for cci dump code CCI register dump is only enable when dump flag is defined. Remove this flag and add control via debugfs entry. This change helps debugfs entry to control cci device individually on the fly for debugging rather than to rebuild. CRs-Fixed: 2692379 Change-Id: Ic13dc903e861e7c49bf3b375a66b96bfbe5d9c70 Signed-off-by: shiwgupt --- .../cam_sensor_module/cam_cci/cam_cci_core.c | 33 ++++---- .../cam_sensor_module/cam_cci/cam_cci_dev.c | 80 +++++++++++++++++++ .../cam_sensor_module/cam_cci/cam_cci_dev.h | 8 ++ 3 files changed, 107 insertions(+), 14 deletions(-) diff --git a/drivers/cam_sensor_module/cam_cci/cam_cci_core.c b/drivers/cam_sensor_module/cam_cci/cam_cci_core.c index af1cd28144ff..0d1b90932eeb 100644 --- a/drivers/cam_sensor_module/cam_cci/cam_cci_core.c +++ b/drivers/cam_sensor_module/cam_cci/cam_cci_core.c @@ -193,17 +193,26 @@ static int32_t cam_cci_lock_queue(struct cci_device *cci_dev, return cam_cci_write_i2c_queue(cci_dev, val, master, queue); } -#ifdef DUMP_CCI_REGISTERS -static void cam_cci_dump_registers(struct cci_device *cci_dev, + +void cam_cci_dump_registers(struct cci_device *cci_dev, enum cci_i2c_master_t master, enum cci_i2c_queue_t queue) { + uint32_t dump_en = 0; uint32_t read_val = 0; uint32_t i = 0; uint32_t reg_offset = 0; void __iomem *base = cci_dev->soc_info.reg_map[0].mem_base; + dump_en = cci_dev->dump_en; + if (!(dump_en & CAM_CCI_NACK_DUMP_EN) && + !(dump_en & CAM_CCI_TIMEOUT_DUMP_EN)) { + CAM_DBG(CAM_CCI, + "Nack and Timeout dump is not enabled"); + return; + } + CAM_INFO(CAM_CCI, "**** CCI:%d register dump ****", - cci_dev->soc_info->index); + cci_dev->soc_info.index); /* CCI Top Registers */ CAM_INFO(CAM_CCI, "****CCI TOP Registers ****"); @@ -247,7 +256,7 @@ static void cam_cci_dump_registers(struct cci_device *cci_dev, reg_offset, read_val); } } -#endif +EXPORT_SYMBOL(cam_cci_dump_registers); static uint32_t cam_cci_wait(struct cci_device *cci_dev, enum cci_i2c_master_t master, @@ -263,9 +272,8 @@ static uint32_t cam_cci_wait(struct cci_device *cci_dev, if (!wait_for_completion_timeout( &cci_dev->cci_master_info[master].report_q[queue], CCI_TIMEOUT)) { -#ifdef DUMP_CCI_REGISTERS cam_cci_dump_registers(cci_dev, master, queue); -#endif + CAM_ERR(CAM_CCI, "wait timeout for cci:%d, Maser:%d, Queue:%d, rc=%d", cci_dev->soc_info.index, master, queue, rc); @@ -1076,9 +1084,8 @@ static int32_t cam_cci_burst_read(struct v4l2_subdev *sd, CAM_ERR(CAM_CCI, "wait timeout for th_complete cci: %d, master: %d, FIFO buf_lvl:0x%x, rc: %d", cci_dev->soc_info.index, master, val, rc); -#ifdef DUMP_CCI_REGISTERS cam_cci_dump_registers(cci_dev, master, queue); -#endif + cam_cci_flush_queue(cci_dev, master); goto rel_mutex_q; } @@ -1167,11 +1174,10 @@ static int32_t cam_cci_burst_read(struct v4l2_subdev *sd, "wait timeout for RD_DONE irq for cci: %d, master: %d, rc = %d FIFO buf_lvl:0x%x, rc: %d", cci_dev->soc_info.index, master, val, rc); - #ifdef DUMP_CCI_REGISTERS - cam_cci_dump_registers(cci_dev, + cam_cci_dump_registers(cci_dev, master, queue); - #endif - cam_cci_flush_queue(cci_dev, master); + + cam_cci_flush_queue(cci_dev, master); goto rel_mutex_q; } @@ -1364,9 +1370,8 @@ static int32_t cam_cci_read(struct v4l2_subdev *sd, if (!wait_for_completion_timeout( &cci_dev->cci_master_info[master].rd_done, CCI_TIMEOUT)) { -#ifdef DUMP_CCI_REGISTERS cam_cci_dump_registers(cci_dev, master, queue); -#endif + rc = -ETIMEDOUT; val = cam_io_r_mb(base + CCI_I2C_M0_READ_BUF_LEVEL_ADDR + master * 0x100); diff --git a/drivers/cam_sensor_module/cam_cci/cam_cci_dev.c b/drivers/cam_sensor_module/cam_cci/cam_cci_dev.c index 68bd320d89a8..8b5ab58539f1 100644 --- a/drivers/cam_sensor_module/cam_cci/cam_cci_dev.c +++ b/drivers/cam_sensor_module/cam_cci/cam_cci_dev.c @@ -12,6 +12,7 @@ #define CCI_MAX_DELAY 1000000 static struct v4l2_subdev *g_cci_subdev[MAX_CCI]; +static struct dentry *debugfs_root; struct v4l2_subdev *cam_cci_get_subdev(int cci_dev_index) { @@ -233,6 +234,8 @@ irqreturn_t cam_cci_irq(int irq_num, void *data) CAM_ERR(CAM_CCI, "Base:%pK,cci: %d, M0_Q0 NACK ERROR: 0x%x", base, cci_dev->soc_info.index, irq_status0); + cam_cci_dump_registers(cci_dev, MASTER_0, + QUEUE_0); complete_all(&cci_dev->cci_master_info[MASTER_0] .report_q[QUEUE_0]); } @@ -240,6 +243,8 @@ irqreturn_t cam_cci_irq(int irq_num, void *data) CAM_ERR(CAM_CCI, "Base:%pK,cci: %d, M0_Q1 NACK ERROR: 0x%x", base, cci_dev->soc_info.index, irq_status0); + cam_cci_dump_registers(cci_dev, MASTER_0, + QUEUE_1); complete_all(&cci_dev->cci_master_info[MASTER_0] .report_q[QUEUE_1]); } @@ -261,6 +266,8 @@ irqreturn_t cam_cci_irq(int irq_num, void *data) CAM_ERR(CAM_CCI, "Base:%pK, cci: %d, M1_Q0 NACK ERROR: 0x%x", base, cci_dev->soc_info.index, irq_status0); + cam_cci_dump_registers(cci_dev, MASTER_1, + QUEUE_0); complete_all(&cci_dev->cci_master_info[MASTER_1] .report_q[QUEUE_0]); } @@ -268,6 +275,8 @@ irqreturn_t cam_cci_irq(int irq_num, void *data) CAM_ERR(CAM_CCI, "Base:%pK, cci: %d, M1_Q1 NACK ERROR: 0x%x", base, cci_dev->soc_info.index, irq_status0); + cam_cci_dump_registers(cci_dev, MASTER_1, + QUEUE_1); complete_all(&cci_dev->cci_master_info[MASTER_1] .report_q[QUEUE_1]); } @@ -372,6 +381,70 @@ static const struct v4l2_subdev_ops cci_subdev_ops = { static const struct v4l2_subdev_internal_ops cci_subdev_intern_ops; +static int cam_cci_get_debug(void *data, u64 *val) +{ + struct cci_device *cci_dev = (struct cci_device *)data; + + *val = cci_dev->dump_en; + + return 0; +} + +static int cam_cci_set_debug(void *data, u64 val) +{ + struct cci_device *cci_dev = (struct cci_device *)data; + + cci_dev->dump_en = val; + + return 0; +} + +DEFINE_DEBUGFS_ATTRIBUTE(cam_cci_debug, + cam_cci_get_debug, + cam_cci_set_debug, "%16llu\n"); + +static int cam_cci_create_debugfs_entry(struct cci_device *cci_dev) +{ + int rc = 0; + struct dentry *dbgfileptr = NULL; + + if (!debugfs_root) { + dbgfileptr = debugfs_create_dir("cam_cci", NULL); + if (!dbgfileptr) { + CAM_ERR(CAM_CCI, "debugfs directory creation fail"); + rc = -ENOENT; + goto end; + } + debugfs_root = dbgfileptr; + } + + if (cci_dev->soc_info.index == 0) { + dbgfileptr = debugfs_create_file("en_dump_cci0", 0644, + debugfs_root, cci_dev, &cam_cci_debug); + if (IS_ERR(dbgfileptr)) { + if (PTR_ERR(dbgfileptr) == -ENODEV) + CAM_WARN(CAM_CCI, "DebugFS not enabled"); + else { + rc = PTR_ERR(dbgfileptr); + goto end; + } + } + } else { + dbgfileptr = debugfs_create_file("en_dump_cci1", 0644, + debugfs_root, cci_dev, &cam_cci_debug); + if (IS_ERR(dbgfileptr)) { + if (PTR_ERR(dbgfileptr) == -ENODEV) + CAM_WARN(CAM_CCI, "DebugFS not enabled"); + else { + rc = PTR_ERR(dbgfileptr); + goto end; + } + } + } +end: + return rc; +} + static int cam_cci_component_bind(struct device *dev, struct device *master_dev, void *data) { @@ -447,6 +520,12 @@ static int cam_cci_component_bind(struct device *dev, CAM_DBG(CAM_CCI, "CPAS registration successful handle=%d", cpas_parms.client_handle); new_cci_dev->cpas_handle = cpas_parms.client_handle; + + rc = cam_cci_create_debugfs_entry(new_cci_dev); + if (rc) { + CAM_WARN(CAM_CCI, "debugfs creation failed"); + rc = 0; + } CAM_DBG(CAM_CCI, "Component bound successfully"); return rc; @@ -468,6 +547,7 @@ static void cam_cci_component_unbind(struct device *dev, v4l2_get_subdevdata(subdev); cam_cpas_unregister_client(cci_dev->cpas_handle); + debugfs_remove_recursive(debugfs_root); cam_cci_soc_remove(pdev, cci_dev); rc = cam_unregister_subdev(&(cci_dev->v4l2_dev_str)); if (rc < 0) diff --git a/drivers/cam_sensor_module/cam_cci/cam_cci_dev.h b/drivers/cam_sensor_module/cam_cci/cam_cci_dev.h index 62652c0397e4..808cf6177fb5 100644 --- a/drivers/cam_sensor_module/cam_cci/cam_cci_dev.h +++ b/drivers/cam_sensor_module/cam_cci/cam_cci_dev.h @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -68,6 +69,9 @@ #define PRIORITY_QUEUE (QUEUE_0) #define SYNC_QUEUE (QUEUE_1) +#define CAM_CCI_NACK_DUMP_EN BIT(1) +#define CAM_CCI_TIMEOUT_DUMP_EN BIT(2) + #define CCI_VERSION_1_2_9 0x10020009 enum cci_i2c_sync { MSM_SYNC_DISABLE, @@ -200,6 +204,7 @@ enum cam_cci_state_t { * @irqs_disabled: Mask for IRQs that are disabled * @init_mutex: Mutex for maintaining refcount for attached * devices to cci during init/deinit. + * @dump_en: To enable the selective dump */ struct cci_device { struct v4l2_subdev subdev; @@ -230,6 +235,7 @@ struct cci_device { bool is_burst_read; uint32_t irqs_disabled; struct mutex init_mutex; + uint64_t dump_en; }; enum cam_cci_i2c_cmd_type { @@ -301,6 +307,8 @@ struct cci_write_async { irqreturn_t cam_cci_irq(int irq_num, void *data); struct v4l2_subdev *cam_cci_get_subdev(int cci_dev_index); +void cam_cci_dump_registers(struct cci_device *cci_dev, + enum cci_i2c_master_t master, enum cci_i2c_queue_t queue); /** * @brief : API to register CCI hw to platform framework.