From 1435a8a68b24fe0c45f23a44ac1fce10fc463957 Mon Sep 17 00:00:00 2001 From: Vishal Verma Date: Thu, 2 Apr 2020 20:43:26 +0530 Subject: [PATCH] msm: camera: sensor: Dump phy registers on error Dump csiphy registers on following fatal errors: 1. lane overflow error 2. unbounded frame error 3. SOT ans EOT reception error 4. stream underflow error These errors irqs are set at csid end, Currently there is no interface to send message from one subdevice to other if the subdev is not a real time device. This change adds an interface to notify the no real time subdev. CRs-Fixed: 2696744 Change-Id: I522167d1639ac298bc739a8a5a380a01356f0776 Signed-off-by: Vishal Verma Signed-off-by: Jigar Agrawal --- .../isp_hw/ife_csid_hw/cam_ife_csid_core.c | 5 ++ .../isp_hw/tfe_csid_hw/cam_tfe_csid_core.c | 8 ++++ drivers/cam_req_mgr/cam_req_mgr_dev.c | 20 +++++++- drivers/cam_req_mgr/cam_subdev.h | 22 +++++++++ .../cam_csiphy/cam_csiphy_dev.c | 21 ++++++++ .../cam_csiphy/cam_csiphy_dev.h | 1 + .../cam_csiphy/cam_csiphy_soc.c | 48 +++++++++++++++++++ .../cam_csiphy/cam_csiphy_soc.h | 6 +++ .../cam_csiphy/include/cam_csiphy_1_0_hwreg.h | 3 +- .../cam_csiphy/include/cam_csiphy_1_1_hwreg.h | 3 +- .../include/cam_csiphy_1_2_1_hwreg.h | 1 + .../include/cam_csiphy_1_2_2_hwreg.h | 1 + .../cam_csiphy/include/cam_csiphy_1_2_hwreg.h | 3 +- .../cam_csiphy/include/cam_csiphy_2_0_hwreg.h | 1 + 14 files changed, 139 insertions(+), 4 deletions(-) diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c index 54b441424c..ac6c2a5d54 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c @@ -9,6 +9,7 @@ #include #include +#include #include #include "cam_ife_csid_core.h" @@ -17,6 +18,7 @@ #include "cam_io_util.h" #include "cam_debug_util.h" #include "cam_cpas_api.h" +#include "cam_subdev.h" /* Timeout value in msec */ #define IFE_CSID_TIMEOUT 1000 @@ -1708,6 +1710,9 @@ static void cam_ife_csid_halt_csi2( csid_reg->csi2_reg->csid_csi2_rx_cfg0_addr); cam_io_w_mb(0, soc_info->reg_map[0].mem_base + csid_reg->csi2_reg->csid_csi2_rx_cfg1_addr); + cam_subdev_notify_message(CAM_CSIPHY_DEVICE_TYPE, + CAM_SUBDEV_MESSAGE_IRQ_ERR, + csid_hw->csi2_rx_cfg.phy_sel); } static int cam_ife_csid_init_config_pxl_path( diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.c index ddad24cd23..6b896a0beb 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.c @@ -7,6 +7,7 @@ #include #include #include +#include #include "cam_tfe_csid_core.h" #include "cam_isp_hw.h" @@ -15,6 +16,7 @@ #include "cam_debug_util.h" #include "cam_cpas_api.h" #include "cam_isp_hw_mgr_intf.h" +#include "cam_subdev.h" /* Timeout value in msec */ #define TFE_CSID_TIMEOUT 1000 @@ -2585,6 +2587,12 @@ irqreturn_t cam_tfe_csid_irq(int irq_num, void *data) csid_reg->csi2_reg->csid_csi2_rx_cfg1_addr); cam_io_w_mb(0, soc_info->reg_map[0].mem_base + csid_reg->csi2_reg->csid_csi2_rx_irq_mask_addr); + /* phy_sel starts from 1 and should never be zero*/ + if (csid_hw->csi2_rx_cfg.phy_sel > 0) { + cam_subdev_notify_message(CAM_CSIPHY_DEVICE_TYPE, + CAM_SUBDEV_MESSAGE_IRQ_ERR, + (csid_hw->csi2_rx_cfg.phy_sel - 1)); + } } if (csid_hw->csid_debug & TFE_CSID_DEBUG_ENABLE_EOT_IRQ) { diff --git a/drivers/cam_req_mgr/cam_req_mgr_dev.c b/drivers/cam_req_mgr/cam_req_mgr_dev.c index 555ad537b8..cc9139e289 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_dev.c +++ b/drivers/cam_req_mgr/cam_req_mgr_dev.c @@ -640,6 +640,24 @@ void cam_video_device_cleanup(void) g_dev.video = NULL; } +void cam_subdev_notify_message(u32 subdev_type, + enum cam_subdev_message_type_t message_type, + uint32_t data) +{ + struct v4l2_subdev *sd = NULL; + struct cam_subdev *csd = NULL; + + list_for_each_entry(sd, &g_dev.v4l2_dev->subdevs, list) { + sd->entity.name = video_device_node_name(sd->devnode); + if (sd->entity.function == subdev_type) { + csd = container_of(sd, struct cam_subdev, sd); + if (csd->msg_cb != NULL) + csd->msg_cb(sd, message_type, data); + } + } +} +EXPORT_SYMBOL(cam_subdev_notify_message); + int cam_register_subdev(struct cam_subdev *csd) { struct v4l2_subdev *sd; @@ -660,7 +678,7 @@ int cam_register_subdev(struct cam_subdev *csd) sd = &csd->sd; v4l2_subdev_init(sd, csd->ops); sd->internal_ops = csd->internal_ops; - snprintf(sd->name, ARRAY_SIZE(sd->name), csd->name); + snprintf(sd->name, V4L2_SUBDEV_NAME_SIZE, "%s", csd->name); v4l2_set_subdevdata(sd, csd->token); sd->flags = csd->sd_flags; diff --git a/drivers/cam_req_mgr/cam_subdev.h b/drivers/cam_req_mgr/cam_subdev.h index 1b2d146fa2..c2ded0c910 100644 --- a/drivers/cam_req_mgr/cam_subdev.h +++ b/drivers/cam_req_mgr/cam_subdev.h @@ -16,6 +16,10 @@ #define CAM_SUBDEVICE_EVENT_MAX 30 +enum cam_subdev_message_type_t { + CAM_SUBDEV_MESSAGE_IRQ_ERR = 0x1 +}; + /** * struct cam_subdev - describes a camera sub-device * @@ -49,8 +53,26 @@ struct cam_subdev { u32 sd_flags; void *token; u32 ent_function; + void (*msg_cb)( + struct v4l2_subdev *sd, + enum cam_subdev_message_type_t msg_type, + uint32_t data); }; +/** + * cam_subdev_notify_message() + * + * @brief: Notify message to a subdevs of specific type + * + * @subdev_type: Subdev type + * @message_type: message type + * @data: data to be delivered. + * + */ +void cam_subdev_notify_message(u32 subdev_type, + enum cam_subdev_message_type_t message_type, + uint32_t data); + /** * cam_subdev_probe() * diff --git a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.c b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.c index 2a6abfc306..ebfd041d13 100644 --- a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.c +++ b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.c @@ -10,6 +10,25 @@ #include #include "camera_main.h" +static void cam_csiphy_subdev_handle_message( + struct v4l2_subdev *sd, + enum cam_subdev_message_type_t message_type, + uint32_t data) +{ + struct csiphy_device *csiphy_dev = v4l2_get_subdevdata(sd); + + switch (message_type) { + case CAM_SUBDEV_MESSAGE_IRQ_ERR: + CAM_INFO(CAM_CSIPHY, "subdev index : %d CSIPHY index: %d", + csiphy_dev->soc_info.index, data); + if (data == csiphy_dev->soc_info.index) + cam_csiphy_status_dmp(csiphy_dev); + break; + default: + break; + } +} + static long cam_csiphy_subdev_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) { @@ -151,6 +170,8 @@ static int cam_csiphy_component_bind(struct device *dev, (V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS); new_csiphy_dev->v4l2_dev_str.ent_function = CAM_CSIPHY_DEVICE_TYPE; + new_csiphy_dev->v4l2_dev_str.msg_cb = + cam_csiphy_subdev_handle_message; new_csiphy_dev->v4l2_dev_str.token = new_csiphy_dev; diff --git a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.h b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.h index c88b109a5d..ac5a017b15 100644 --- a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.h +++ b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.h @@ -106,6 +106,7 @@ struct csiphy_reg_parms_t { uint32_t mipi_csiphy_interrupt_mask_addr; uint32_t mipi_csiphy_interrupt_clear0_addr; uint32_t csiphy_version; + uint32_t csiphy_interrupt_status_size; uint32_t csiphy_common_array_size; uint32_t csiphy_reset_array_size; uint32_t csiphy_2ph_config_array_size; diff --git a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c index 89686a3b00..bedd0570b4 100644 --- a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c +++ b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c @@ -78,6 +78,54 @@ int32_t cam_csiphy_mem_dmp(struct cam_hw_soc_info *soc_info) return rc; } +int32_t cam_csiphy_status_dmp(struct csiphy_device *csiphy_dev) +{ + struct csiphy_reg_parms_t *csiphy_reg = NULL; + int32_t rc = 0; + resource_size_t size = 0; + void __iomem *phy_base = NULL; + int reg_id = 0; + uint32_t irq, status_reg, clear_reg; + + if (!csiphy_dev) { + rc = -EINVAL; + CAM_ERR(CAM_CSIPHY, "invalid input %d", rc); + return rc; + } + + csiphy_reg = &csiphy_dev->ctrl_reg->csiphy_reg; + phy_base = csiphy_dev->soc_info.reg_map[0].mem_base; + status_reg = csiphy_reg->mipi_csiphy_interrupt_status0_addr; + clear_reg = csiphy_reg->mipi_csiphy_interrupt_clear0_addr; + size = csiphy_reg->csiphy_interrupt_status_size; + + CAM_INFO(CAM_CSIPHY, "PHY base addr=%pK offset=0x%x size=%d", + phy_base, status_reg, size); + + if (phy_base != NULL) { + for (reg_id = 0; reg_id < size; reg_id++) { + uint32_t offset; + + offset = status_reg + (0x4 * reg_id); + irq = cam_io_r(phy_base + offset); + offset = clear_reg + (0x4 * reg_id); + cam_io_w_mb(irq, phy_base + offset); + cam_io_w_mb(0, phy_base + offset); + + CAM_INFO(CAM_CSIPHY, + "CSIPHY%d_IRQ_STATUS_ADDR%d = 0x%x", + csiphy_dev->soc_info.index, reg_id, irq); + } + } else { + rc = -EINVAL; + CAM_ERR(CAM_CSIPHY, "phy base is NULL %d", rc); + return rc; + } + return rc; +} + + + enum cam_vote_level get_clk_vote_default(struct csiphy_device *csiphy_dev) { CAM_DBG(CAM_CSIPHY, "voting for SVS"); diff --git a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.h b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.h index 1f08193de2..0416d8cda6 100644 --- a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.h +++ b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.h @@ -72,4 +72,10 @@ int cam_csiphy_disable_hw(struct csiphy_device *csiphy_dev); */ int cam_csiphy_mem_dmp(struct cam_hw_soc_info *soc_info); +/** + * @csiphy_dev: CSIPhy device structure + * + * This API dumps memory for the entire status region + */ +int32_t cam_csiphy_status_dmp(struct csiphy_device *csiphy_dev); #endif /* _CAM_CSIPHY_SOC_H_ */ diff --git a/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_0_hwreg.h b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_0_hwreg.h index e910162858..eaedc7b672 100644 --- a/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_0_hwreg.h +++ b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_0_hwreg.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #ifndef _CAM_CSIPHY_1_0_HWREG_H_ @@ -12,6 +12,7 @@ struct csiphy_reg_parms_t csiphy_v1_0 = { .mipi_csiphy_interrupt_status0_addr = 0x8B0, .mipi_csiphy_interrupt_clear0_addr = 0x858, .mipi_csiphy_glbl_irq_cmd_addr = 0x828, + .csiphy_interrupt_status_size = 11, .csiphy_common_array_size = 5, .csiphy_reset_array_size = 5, .csiphy_2ph_config_array_size = 14, diff --git a/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_1_hwreg.h b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_1_hwreg.h index 30b61067a7..e1db638da5 100644 --- a/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_1_hwreg.h +++ b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_1_hwreg.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. */ #ifndef _CAM_CSIPHY_1_1_HWREG_H_ @@ -12,6 +12,7 @@ struct csiphy_reg_parms_t csiphy_v1_1 = { .mipi_csiphy_interrupt_status0_addr = 0x8B0, .mipi_csiphy_interrupt_clear0_addr = 0x858, .mipi_csiphy_glbl_irq_cmd_addr = 0x828, + .csiphy_interrupt_status_size = 11, .csiphy_common_array_size = 5, .csiphy_reset_array_size = 5, .csiphy_2ph_config_array_size = 14, diff --git a/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_1_hwreg.h b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_1_hwreg.h index c9fb93f7e9..8bf373677a 100644 --- a/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_1_hwreg.h +++ b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_1_hwreg.h @@ -12,6 +12,7 @@ struct csiphy_reg_parms_t csiphy_v1_2_1 = { .mipi_csiphy_interrupt_status0_addr = 0x8B0, .mipi_csiphy_interrupt_clear0_addr = 0x858, .mipi_csiphy_glbl_irq_cmd_addr = 0x828, + .csiphy_interrupt_status_size = 11, .csiphy_common_array_size = 7, .csiphy_reset_array_size = 5, .csiphy_2ph_config_array_size = 20, diff --git a/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_2_hwreg.h b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_2_hwreg.h index 119b6b575b..00e6bb3039 100644 --- a/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_2_hwreg.h +++ b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_2_hwreg.h @@ -12,6 +12,7 @@ struct csiphy_reg_parms_t csiphy_v1_2_2 = { .mipi_csiphy_interrupt_status0_addr = 0x8B0, .mipi_csiphy_interrupt_clear0_addr = 0x858, .mipi_csiphy_glbl_irq_cmd_addr = 0x828, + .csiphy_interrupt_status_size = 11, .csiphy_common_array_size = 8, .csiphy_reset_array_size = 5, .csiphy_2ph_config_array_size = 18, diff --git a/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_hwreg.h b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_hwreg.h index 179ccebddc..446c8197df 100644 --- a/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_hwreg.h +++ b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_hwreg.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. */ #ifndef _CAM_CSIPHY_1_2_HWREG_H_ @@ -12,6 +12,7 @@ struct csiphy_reg_parms_t csiphy_v1_2 = { .mipi_csiphy_interrupt_status0_addr = 0x8B0, .mipi_csiphy_interrupt_clear0_addr = 0x858, .mipi_csiphy_glbl_irq_cmd_addr = 0x828, + .csiphy_interrupt_status_size = 11, .csiphy_common_array_size = 7, .csiphy_reset_array_size = 5, .csiphy_2ph_config_array_size = 18, diff --git a/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_2_0_hwreg.h b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_2_0_hwreg.h index 9549919e2e..f7be2b60a4 100644 --- a/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_2_0_hwreg.h +++ b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_2_0_hwreg.h @@ -12,6 +12,7 @@ struct csiphy_reg_parms_t csiphy_v2_0 = { .mipi_csiphy_interrupt_status0_addr = 0x8B0, .mipi_csiphy_interrupt_clear0_addr = 0x858, .mipi_csiphy_glbl_irq_cmd_addr = 0x828, + .csiphy_interrupt_status_size = 11, .csiphy_common_array_size = 8, .csiphy_reset_array_size = 5, .csiphy_2ph_config_array_size = 15,