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.