Loading drivers/media/platform/msm/camera/cam_sensor_module/cam_cci/cam_cci_core.c +11 −5 Original line number Original line Diff line number Diff line /* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. /* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. * * * This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -1094,7 +1094,7 @@ static int32_t cam_cci_burst_read(struct v4l2_subdev *sd, * RD_DONE exclusively. * RD_DONE exclusively. */ */ rem_jiffies = wait_for_completion_timeout( rem_jiffies = wait_for_completion_timeout( &cci_dev->cci_master_info[master].reset_complete, &cci_dev->cci_master_info[master].rd_done, CCI_TIMEOUT); CCI_TIMEOUT); if (!rem_jiffies) { if (!rem_jiffies) { rc = -ETIMEDOUT; rc = -ETIMEDOUT; Loading Loading @@ -1275,10 +1275,11 @@ static int32_t cam_cci_read(struct v4l2_subdev *sd, val = 1 << ((master * 2) + queue); val = 1 << ((master * 2) + queue); cam_io_w_mb(val, base + CCI_QUEUE_START_ADDR); cam_io_w_mb(val, base + CCI_QUEUE_START_ADDR); CAM_DBG(CAM_CCI, CAM_DBG(CAM_CCI, "waiting_for_rd_done [exp_words: %d]", exp_words); "waiting_for_rd_done [exp_words: %d]", ((read_cfg->num_byte / 4) + 1)); rc = wait_for_completion_timeout( rc = wait_for_completion_timeout( &cci_dev->cci_master_info[master].reset_complete, CCI_TIMEOUT); &cci_dev->cci_master_info[master].rd_done, CCI_TIMEOUT); if (rc <= 0) { if (rc <= 0) { #ifdef DUMP_CCI_REGISTERS #ifdef DUMP_CCI_REGISTERS cam_cci_dump_registers(cci_dev, master, queue); cam_cci_dump_registers(cci_dev, master, queue); Loading Loading @@ -1692,14 +1693,19 @@ int32_t cam_cci_core_cfg(struct v4l2_subdev *sd, struct cam_cci_ctrl *cci_ctrl) struct cam_cci_ctrl *cci_ctrl) { { int32_t rc = 0; int32_t rc = 0; struct cci_device *cci_dev = v4l2_get_subdevdata(sd); CAM_DBG(CAM_CCI, "cmd %d", cci_ctrl->cmd); CAM_DBG(CAM_CCI, "cmd %d", cci_ctrl->cmd); switch (cci_ctrl->cmd) { switch (cci_ctrl->cmd) { case MSM_CCI_INIT: case MSM_CCI_INIT: mutex_lock(&cci_dev->init_mutex); rc = cam_cci_init(sd, cci_ctrl); rc = cam_cci_init(sd, cci_ctrl); mutex_unlock(&cci_dev->init_mutex); break; break; case MSM_CCI_RELEASE: case MSM_CCI_RELEASE: mutex_lock(&cci_dev->init_mutex); rc = cam_cci_release(sd); rc = cam_cci_release(sd); mutex_unlock(&cci_dev->init_mutex); break; break; case MSM_CCI_I2C_READ: case MSM_CCI_I2C_READ: rc = cam_cci_read_bytes(sd, cci_ctrl); rc = cam_cci_read_bytes(sd, cci_ctrl); Loading drivers/media/platform/msm/camera/cam_sensor_module/cam_cci/cam_cci_dev.c +41 −17 Original line number Original line Diff line number Diff line /* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. /* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. * * * This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -71,20 +71,26 @@ irqreturn_t cam_cci_irq(int irq_num, void *data) irq_status0 = cam_io_r_mb(base + CCI_IRQ_STATUS_0_ADDR); irq_status0 = cam_io_r_mb(base + CCI_IRQ_STATUS_0_ADDR); irq_status1 = cam_io_r_mb(base + CCI_IRQ_STATUS_1_ADDR); irq_status1 = cam_io_r_mb(base + CCI_IRQ_STATUS_1_ADDR); CAM_DBG(CAM_CCI, "BASE: %pK", base); CAM_DBG(CAM_CCI, "irq0:%x irq1:%x", irq_status0, irq_status1); CAM_DBG(CAM_CCI, "irq0:%x irq1:%x", irq_status0, irq_status1); if (irq_status0 & CCI_IRQ_STATUS_0_RST_DONE_ACK_BMSK) { if (irq_status0 & CCI_IRQ_STATUS_0_RST_DONE_ACK_BMSK) { struct cam_cci_master_info *cci_master_info; if (cci_dev->cci_master_info[MASTER_0].reset_pending == TRUE) { if (cci_dev->cci_master_info[MASTER_0].reset_pending == TRUE) { cci_master_info = &cci_dev->cci_master_info[MASTER_0]; cci_dev->cci_master_info[MASTER_0].reset_pending = cci_dev->cci_master_info[MASTER_0].reset_pending = FALSE; FALSE; complete( if (!cci_master_info->status) &cci_dev->cci_master_info[MASTER_0].reset_complete); complete(&cci_master_info->reset_complete); cci_master_info->status = 0; } } if (cci_dev->cci_master_info[MASTER_1].reset_pending == TRUE) { if (cci_dev->cci_master_info[MASTER_1].reset_pending == TRUE) { cci_master_info = &cci_dev->cci_master_info[MASTER_1]; cci_dev->cci_master_info[MASTER_1].reset_pending = cci_dev->cci_master_info[MASTER_1].reset_pending = FALSE; FALSE; complete( if (!cci_master_info->status) &cci_dev->cci_master_info[MASTER_1].reset_complete); complete(&cci_master_info->reset_complete); cci_master_info->status = 0; } } } } Loading @@ -93,7 +99,7 @@ irqreturn_t cam_cci_irq(int irq_num, void *data) cci_dev->cci_master_info[MASTER_0].status = 0; cci_dev->cci_master_info[MASTER_0].status = 0; rd_done_th_assert = true; rd_done_th_assert = true; complete(&cci_dev->cci_master_info[MASTER_0].th_complete); complete(&cci_dev->cci_master_info[MASTER_0].th_complete); complete(&cci_dev->cci_master_info[MASTER_0].reset_complete); complete(&cci_dev->cci_master_info[MASTER_0].rd_done); } } if ((irq_status0 & CCI_IRQ_STATUS_0_I2C_M0_RD_DONE_BMSK) && if ((irq_status0 & CCI_IRQ_STATUS_0_I2C_M0_RD_DONE_BMSK) && (!rd_done_th_assert)) { (!rd_done_th_assert)) { Loading @@ -102,7 +108,7 @@ irqreturn_t cam_cci_irq(int irq_num, void *data) if (cci_dev->is_burst_read) if (cci_dev->is_burst_read) complete( complete( &cci_dev->cci_master_info[MASTER_0].th_complete); &cci_dev->cci_master_info[MASTER_0].th_complete); complete(&cci_dev->cci_master_info[MASTER_0].reset_complete); complete(&cci_dev->cci_master_info[MASTER_0].rd_done); } } if ((irq_status1 & CCI_IRQ_STATUS_1_I2C_M0_RD_THRESHOLD) && if ((irq_status1 & CCI_IRQ_STATUS_1_I2C_M0_RD_THRESHOLD) && (!rd_done_th_assert)) { (!rd_done_th_assert)) { Loading Loading @@ -149,7 +155,7 @@ irqreturn_t cam_cci_irq(int irq_num, void *data) cci_dev->cci_master_info[MASTER_1].status = 0; cci_dev->cci_master_info[MASTER_1].status = 0; rd_done_th_assert = true; rd_done_th_assert = true; complete(&cci_dev->cci_master_info[MASTER_1].th_complete); complete(&cci_dev->cci_master_info[MASTER_1].th_complete); complete(&cci_dev->cci_master_info[MASTER_1].reset_complete); complete(&cci_dev->cci_master_info[MASTER_1].rd_done); } } if ((irq_status0 & CCI_IRQ_STATUS_0_I2C_M1_RD_DONE_BMSK) && if ((irq_status0 & CCI_IRQ_STATUS_0_I2C_M1_RD_DONE_BMSK) && (!rd_done_th_assert)) { (!rd_done_th_assert)) { Loading @@ -158,7 +164,7 @@ irqreturn_t cam_cci_irq(int irq_num, void *data) if (cci_dev->is_burst_read) if (cci_dev->is_burst_read) complete( complete( &cci_dev->cci_master_info[MASTER_1].th_complete); &cci_dev->cci_master_info[MASTER_1].th_complete); complete(&cci_dev->cci_master_info[MASTER_1].reset_complete); complete(&cci_dev->cci_master_info[MASTER_1].rd_done); } } if ((irq_status1 & CCI_IRQ_STATUS_1_I2C_M1_RD_THRESHOLD) && if ((irq_status1 & CCI_IRQ_STATUS_1_I2C_M1_RD_THRESHOLD) && (!rd_done_th_assert)) { (!rd_done_th_assert)) { Loading Loading @@ -217,16 +223,33 @@ irqreturn_t cam_cci_irq(int irq_num, void *data) } } if (irq_status0 & CCI_IRQ_STATUS_0_I2C_M0_ERROR_BMSK) { if (irq_status0 & CCI_IRQ_STATUS_0_I2C_M0_ERROR_BMSK) { cci_dev->cci_master_info[MASTER_0].status = -EINVAL; cci_dev->cci_master_info[MASTER_0].status = -EINVAL; cam_io_w_mb(CCI_M0_HALT_REQ_RMSK, if (irq_status0 & CCI_IRQ_STATUS_0_I2C_M0_NACK_ERROR_BMSK) base + CCI_HALT_REQ_ADDR); CAM_ERR(CAM_CCI, "Base:%pK, M0 NACK ERROR: 0x%x", CAM_DBG(CAM_CCI, "MASTER_0 error 0x%x", irq_status0); base, irq_status0); if (irq_status0 & CCI_IRQ_STATUS_0_I2C_M0_Q0Q1_ERROR_BMSK) CAM_ERR(CAM_CCI, "Base:%pK, M0 QUEUE_OVER/UNDER_FLOW OR CMD ERR: 0x%x", base, irq_status0); if (irq_status0 & CCI_IRQ_STATUS_0_I2C_M0_RD_ERROR_BMSK) CAM_ERR(CAM_CCI, "Base: %pK, M0 RD_OVER/UNDER_FLOW ERROR: 0x%x", base, irq_status0); cam_io_w_mb(CCI_M0_HALT_REQ_RMSK, base + CCI_HALT_REQ_ADDR); } } if (irq_status0 & CCI_IRQ_STATUS_0_I2C_M1_ERROR_BMSK) { if (irq_status0 & CCI_IRQ_STATUS_0_I2C_M1_ERROR_BMSK) { cci_dev->cci_master_info[MASTER_1].status = -EINVAL; cci_dev->cci_master_info[MASTER_1].status = -EINVAL; cam_io_w_mb(CCI_M1_HALT_REQ_RMSK, if (irq_status0 & CCI_IRQ_STATUS_0_I2C_M0_NACK_ERROR_BMSK) base + CCI_HALT_REQ_ADDR); CAM_ERR(CAM_CCI, "Base:%pK, M1 NACK ERROR: 0x%x", CAM_DBG(CAM_CCI, "MASTER_1 error 0x%x", irq_status0); base, irq_status0); if (irq_status0 & CCI_IRQ_STATUS_0_I2C_M0_Q0Q1_ERROR_BMSK) CAM_ERR(CAM_CCI, "Base:%pK, M1 QUEUE_OVER_UNDER_FLOW OR CMD ERROR:0x%x", base, irq_status0); if (irq_status0 & CCI_IRQ_STATUS_0_I2C_M0_RD_ERROR_BMSK) CAM_ERR(CAM_CCI, "Base:%pK, M1 RD_OVER/UNDER_FLOW ERROR: 0x%x", base, irq_status0); cam_io_w_mb(CCI_M1_HALT_REQ_RMSK, base + CCI_HALT_REQ_ADDR); } } cam_io_w_mb(irq_status0, base + CCI_IRQ_CLEAR_0_ADDR); cam_io_w_mb(irq_status0, base + CCI_IRQ_CLEAR_0_ADDR); Loading Loading @@ -402,7 +425,8 @@ static int cam_cci_platform_probe(struct platform_device *pdev) } } g_cci_subdev[soc_info->index] = &new_cci_dev->v4l2_dev_str.sd; g_cci_subdev[soc_info->index] = &new_cci_dev->v4l2_dev_str.sd; CAM_ERR(CAM_CCI, "Device Type :%d", soc_info->index); mutex_init(&(new_cci_dev->init_mutex)); CAM_INFO(CAM_CCI, "Device Type :%d", soc_info->index); cam_register_subdev_fops(&cci_v4l2_subdev_fops); cam_register_subdev_fops(&cci_v4l2_subdev_fops); cci_v4l2_subdev_fops.unlocked_ioctl = cam_cci_subdev_fops_ioctl; cci_v4l2_subdev_fops.unlocked_ioctl = cam_cci_subdev_fops_ioctl; Loading drivers/media/platform/msm/camera/cam_sensor_module/cam_cci/cam_cci_dev.h +38 −35 Original line number Original line Diff line number Diff line /* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. /* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. * * * This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -140,6 +140,7 @@ struct cam_cci_master_info { uint8_t reset_pending; uint8_t reset_pending; struct mutex mutex; struct mutex mutex; struct completion reset_complete; struct completion reset_complete; struct completion rd_done; struct completion th_complete; struct completion th_complete; struct mutex mutex_q[NUM_QUEUES]; struct mutex mutex_q[NUM_QUEUES]; struct completion report_q[NUM_QUEUES]; struct completion report_q[NUM_QUEUES]; Loading Loading @@ -192,8 +193,7 @@ enum cam_cci_state_t { * @cci_vreg: CCI regulator structure * @cci_vreg: CCI regulator structure * @cci_reg_ptr: CCI individual regulator structure * @cci_reg_ptr: CCI individual regulator structure * @regulator_count: Regulator count * @regulator_count: Regulator count * @support_seq_write: * @support_seq_write: Set this flag when sequential write is enabled * Set this flag when sequential write is enabled * @write_wq: Work queue structure * @write_wq: Work queue structure * @valid_sync: Is it a valid sync with CSID * @valid_sync: Is it a valid sync with CSID * @v4l2_dev_str: V4L2 device structure * @v4l2_dev_str: V4L2 device structure Loading @@ -206,6 +206,8 @@ enum cam_cci_state_t { * @is_burst_read: Flag to determine if we are performing * @is_burst_read: Flag to determine if we are performing * a burst read operation or not * a burst read operation or not * @irqs_disabled: Mask for IRQs that are disabled * @irqs_disabled: Mask for IRQs that are disabled * @init_mutex: Mutex for maintaining refcount for attached * devices to cci during init/deinit. */ */ struct cci_device { struct cci_device { struct v4l2_subdev subdev; struct v4l2_subdev subdev; Loading Loading @@ -234,6 +236,7 @@ struct cci_device { spinlock_t lock_status; spinlock_t lock_status; bool is_burst_read; bool is_burst_read; uint32_t irqs_disabled; uint32_t irqs_disabled; struct mutex init_mutex; }; }; enum cam_cci_i2c_cmd_type { enum cam_cci_i2c_cmd_type { Loading drivers/media/platform/msm/camera/cam_sensor_module/cam_cci/cam_cci_hwreg.h +7 −1 Original line number Original line Diff line number Diff line /* Copyright (c) 2012-2015, 2017-2018, The Linux Foundation. All rights reserved. /* Copyright (c) 2012-2015, 2017-2019, The Linux Foundation. All rights reserved. * * * This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -61,6 +61,12 @@ #define CCI_IRQ_STATUS_0_I2C_M0_Q0_REPORT_BMSK 0x10 #define CCI_IRQ_STATUS_0_I2C_M0_Q0_REPORT_BMSK 0x10 #define CCI_IRQ_STATUS_0_I2C_M0_ERROR_BMSK 0x18000EE6 #define CCI_IRQ_STATUS_0_I2C_M0_ERROR_BMSK 0x18000EE6 #define CCI_IRQ_STATUS_0_I2C_M1_ERROR_BMSK 0x60EE6000 #define CCI_IRQ_STATUS_0_I2C_M1_ERROR_BMSK 0x60EE6000 #define CCI_IRQ_STATUS_0_I2C_M0_NACK_ERROR_BMSK 0x18000000 #define CCI_IRQ_STATUS_0_I2C_M1_NACK_ERROR_BMSK 0x60000000 #define CCI_IRQ_STATUS_0_I2C_M0_Q0Q1_ERROR_BMSK 0xEE0 #define CCI_IRQ_STATUS_0_I2C_M1_Q0Q1_ERROR_BMSK 0xEE0000 #define CCI_IRQ_STATUS_0_I2C_M0_RD_ERROR_BMSK 0x6 #define CCI_IRQ_STATUS_0_I2C_M1_RD_ERROR_BMSK 0x6000 #define CCI_IRQ_STATUS_0_I2C_M0_RD_DONE_BMSK 0x1 #define CCI_IRQ_STATUS_0_I2C_M0_RD_DONE_BMSK 0x1 #define CCI_IRQ_STATUS_1_I2C_M0_RD_THRESHOLD 0x10000 #define CCI_IRQ_STATUS_1_I2C_M0_RD_THRESHOLD 0x10000 #define CCI_IRQ_STATUS_1_I2C_M0_RD_PAUSE 0x20000 #define CCI_IRQ_STATUS_1_I2C_M0_RD_PAUSE 0x20000 Loading drivers/media/platform/msm/camera/cam_sensor_module/cam_cci/cam_cci_soc.c +8 −4 Original line number Original line Diff line number Diff line Loading @@ -19,7 +19,7 @@ int cam_cci_init(struct v4l2_subdev *sd, uint8_t i = 0, j = 0; uint8_t i = 0, j = 0; int32_t rc = 0; int32_t rc = 0; struct cci_device *cci_dev; struct cci_device *cci_dev; enum cci_i2c_master_t master = MASTER_0; enum cci_i2c_master_t master = c_ctrl->cci_info->cci_i2c_master; struct cam_ahb_vote ahb_vote; struct cam_ahb_vote ahb_vote; struct cam_axi_vote axi_vote; struct cam_axi_vote axi_vote; struct cam_hw_soc_info *soc_info = NULL; struct cam_hw_soc_info *soc_info = NULL; Loading Loading @@ -47,7 +47,6 @@ int cam_cci_init(struct v4l2_subdev *sd, if (cci_dev->ref_count++) { if (cci_dev->ref_count++) { CAM_DBG(CAM_CCI, "ref_count %d", cci_dev->ref_count); CAM_DBG(CAM_CCI, "ref_count %d", cci_dev->ref_count); master = c_ctrl->cci_info->cci_i2c_master; CAM_DBG(CAM_CCI, "master %d", master); CAM_DBG(CAM_CCI, "master %d", master); if (master < MASTER_MAX && master >= 0) { if (master < MASTER_MAX && master >= 0) { mutex_lock(&cci_dev->cci_master_info[master].mutex); mutex_lock(&cci_dev->cci_master_info[master].mutex); Loading @@ -55,6 +54,8 @@ int cam_cci_init(struct v4l2_subdev *sd, /* Re-initialize the completion */ /* Re-initialize the completion */ reinit_completion( reinit_completion( &cci_dev->cci_master_info[master].reset_complete); &cci_dev->cci_master_info[master].reset_complete); reinit_completion( &cci_dev->cci_master_info[master].rd_done); for (i = 0; i < NUM_QUEUES; i++) for (i = 0; i < NUM_QUEUES; i++) reinit_completion( reinit_completion( &cci_dev->cci_master_info[master].report_q[i]); &cci_dev->cci_master_info[master].report_q[i]); Loading Loading @@ -93,6 +94,7 @@ int cam_cci_init(struct v4l2_subdev *sd, /* Re-initialize the completion */ /* Re-initialize the completion */ reinit_completion(&cci_dev->cci_master_info[master].reset_complete); reinit_completion(&cci_dev->cci_master_info[master].reset_complete); reinit_completion(&cci_dev->cci_master_info[master].rd_done); for (i = 0; i < NUM_QUEUES; i++) for (i = 0; i < NUM_QUEUES; i++) reinit_completion( reinit_completion( &cci_dev->cci_master_info[master].report_q[i]); &cci_dev->cci_master_info[master].report_q[i]); Loading Loading @@ -128,12 +130,12 @@ int cam_cci_init(struct v4l2_subdev *sd, } } } } cci_dev->cci_master_info[MASTER_0].reset_pending = TRUE; cci_dev->cci_master_info[master].reset_pending = TRUE; cam_io_w_mb(CCI_RESET_CMD_RMSK, base + cam_io_w_mb(CCI_RESET_CMD_RMSK, base + CCI_RESET_CMD_ADDR); CCI_RESET_CMD_ADDR); cam_io_w_mb(0x1, base + CCI_RESET_CMD_ADDR); cam_io_w_mb(0x1, base + CCI_RESET_CMD_ADDR); rc = wait_for_completion_timeout( rc = wait_for_completion_timeout( &cci_dev->cci_master_info[MASTER_0].reset_complete, &cci_dev->cci_master_info[master].reset_complete, CCI_TIMEOUT); CCI_TIMEOUT); if (rc <= 0) { if (rc <= 0) { CAM_ERR(CAM_CCI, "wait_for_completion_timeout"); CAM_ERR(CAM_CCI, "wait_for_completion_timeout"); Loading Loading @@ -205,6 +207,8 @@ static void cam_cci_init_cci_params(struct cci_device *new_cci_dev) &new_cci_dev->cci_master_info[i].reset_complete); &new_cci_dev->cci_master_info[i].reset_complete); init_completion( init_completion( &new_cci_dev->cci_master_info[i].th_complete); &new_cci_dev->cci_master_info[i].th_complete); init_completion( &new_cci_dev->cci_master_info[i].rd_done); for (j = 0; j < NUM_QUEUES; j++) { for (j = 0; j < NUM_QUEUES; j++) { mutex_init(&new_cci_dev->cci_master_info[i].mutex_q[j]); mutex_init(&new_cci_dev->cci_master_info[i].mutex_q[j]); Loading Loading
drivers/media/platform/msm/camera/cam_sensor_module/cam_cci/cam_cci_core.c +11 −5 Original line number Original line Diff line number Diff line /* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. /* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. * * * This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -1094,7 +1094,7 @@ static int32_t cam_cci_burst_read(struct v4l2_subdev *sd, * RD_DONE exclusively. * RD_DONE exclusively. */ */ rem_jiffies = wait_for_completion_timeout( rem_jiffies = wait_for_completion_timeout( &cci_dev->cci_master_info[master].reset_complete, &cci_dev->cci_master_info[master].rd_done, CCI_TIMEOUT); CCI_TIMEOUT); if (!rem_jiffies) { if (!rem_jiffies) { rc = -ETIMEDOUT; rc = -ETIMEDOUT; Loading Loading @@ -1275,10 +1275,11 @@ static int32_t cam_cci_read(struct v4l2_subdev *sd, val = 1 << ((master * 2) + queue); val = 1 << ((master * 2) + queue); cam_io_w_mb(val, base + CCI_QUEUE_START_ADDR); cam_io_w_mb(val, base + CCI_QUEUE_START_ADDR); CAM_DBG(CAM_CCI, CAM_DBG(CAM_CCI, "waiting_for_rd_done [exp_words: %d]", exp_words); "waiting_for_rd_done [exp_words: %d]", ((read_cfg->num_byte / 4) + 1)); rc = wait_for_completion_timeout( rc = wait_for_completion_timeout( &cci_dev->cci_master_info[master].reset_complete, CCI_TIMEOUT); &cci_dev->cci_master_info[master].rd_done, CCI_TIMEOUT); if (rc <= 0) { if (rc <= 0) { #ifdef DUMP_CCI_REGISTERS #ifdef DUMP_CCI_REGISTERS cam_cci_dump_registers(cci_dev, master, queue); cam_cci_dump_registers(cci_dev, master, queue); Loading Loading @@ -1692,14 +1693,19 @@ int32_t cam_cci_core_cfg(struct v4l2_subdev *sd, struct cam_cci_ctrl *cci_ctrl) struct cam_cci_ctrl *cci_ctrl) { { int32_t rc = 0; int32_t rc = 0; struct cci_device *cci_dev = v4l2_get_subdevdata(sd); CAM_DBG(CAM_CCI, "cmd %d", cci_ctrl->cmd); CAM_DBG(CAM_CCI, "cmd %d", cci_ctrl->cmd); switch (cci_ctrl->cmd) { switch (cci_ctrl->cmd) { case MSM_CCI_INIT: case MSM_CCI_INIT: mutex_lock(&cci_dev->init_mutex); rc = cam_cci_init(sd, cci_ctrl); rc = cam_cci_init(sd, cci_ctrl); mutex_unlock(&cci_dev->init_mutex); break; break; case MSM_CCI_RELEASE: case MSM_CCI_RELEASE: mutex_lock(&cci_dev->init_mutex); rc = cam_cci_release(sd); rc = cam_cci_release(sd); mutex_unlock(&cci_dev->init_mutex); break; break; case MSM_CCI_I2C_READ: case MSM_CCI_I2C_READ: rc = cam_cci_read_bytes(sd, cci_ctrl); rc = cam_cci_read_bytes(sd, cci_ctrl); Loading
drivers/media/platform/msm/camera/cam_sensor_module/cam_cci/cam_cci_dev.c +41 −17 Original line number Original line Diff line number Diff line /* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. /* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. * * * This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -71,20 +71,26 @@ irqreturn_t cam_cci_irq(int irq_num, void *data) irq_status0 = cam_io_r_mb(base + CCI_IRQ_STATUS_0_ADDR); irq_status0 = cam_io_r_mb(base + CCI_IRQ_STATUS_0_ADDR); irq_status1 = cam_io_r_mb(base + CCI_IRQ_STATUS_1_ADDR); irq_status1 = cam_io_r_mb(base + CCI_IRQ_STATUS_1_ADDR); CAM_DBG(CAM_CCI, "BASE: %pK", base); CAM_DBG(CAM_CCI, "irq0:%x irq1:%x", irq_status0, irq_status1); CAM_DBG(CAM_CCI, "irq0:%x irq1:%x", irq_status0, irq_status1); if (irq_status0 & CCI_IRQ_STATUS_0_RST_DONE_ACK_BMSK) { if (irq_status0 & CCI_IRQ_STATUS_0_RST_DONE_ACK_BMSK) { struct cam_cci_master_info *cci_master_info; if (cci_dev->cci_master_info[MASTER_0].reset_pending == TRUE) { if (cci_dev->cci_master_info[MASTER_0].reset_pending == TRUE) { cci_master_info = &cci_dev->cci_master_info[MASTER_0]; cci_dev->cci_master_info[MASTER_0].reset_pending = cci_dev->cci_master_info[MASTER_0].reset_pending = FALSE; FALSE; complete( if (!cci_master_info->status) &cci_dev->cci_master_info[MASTER_0].reset_complete); complete(&cci_master_info->reset_complete); cci_master_info->status = 0; } } if (cci_dev->cci_master_info[MASTER_1].reset_pending == TRUE) { if (cci_dev->cci_master_info[MASTER_1].reset_pending == TRUE) { cci_master_info = &cci_dev->cci_master_info[MASTER_1]; cci_dev->cci_master_info[MASTER_1].reset_pending = cci_dev->cci_master_info[MASTER_1].reset_pending = FALSE; FALSE; complete( if (!cci_master_info->status) &cci_dev->cci_master_info[MASTER_1].reset_complete); complete(&cci_master_info->reset_complete); cci_master_info->status = 0; } } } } Loading @@ -93,7 +99,7 @@ irqreturn_t cam_cci_irq(int irq_num, void *data) cci_dev->cci_master_info[MASTER_0].status = 0; cci_dev->cci_master_info[MASTER_0].status = 0; rd_done_th_assert = true; rd_done_th_assert = true; complete(&cci_dev->cci_master_info[MASTER_0].th_complete); complete(&cci_dev->cci_master_info[MASTER_0].th_complete); complete(&cci_dev->cci_master_info[MASTER_0].reset_complete); complete(&cci_dev->cci_master_info[MASTER_0].rd_done); } } if ((irq_status0 & CCI_IRQ_STATUS_0_I2C_M0_RD_DONE_BMSK) && if ((irq_status0 & CCI_IRQ_STATUS_0_I2C_M0_RD_DONE_BMSK) && (!rd_done_th_assert)) { (!rd_done_th_assert)) { Loading @@ -102,7 +108,7 @@ irqreturn_t cam_cci_irq(int irq_num, void *data) if (cci_dev->is_burst_read) if (cci_dev->is_burst_read) complete( complete( &cci_dev->cci_master_info[MASTER_0].th_complete); &cci_dev->cci_master_info[MASTER_0].th_complete); complete(&cci_dev->cci_master_info[MASTER_0].reset_complete); complete(&cci_dev->cci_master_info[MASTER_0].rd_done); } } if ((irq_status1 & CCI_IRQ_STATUS_1_I2C_M0_RD_THRESHOLD) && if ((irq_status1 & CCI_IRQ_STATUS_1_I2C_M0_RD_THRESHOLD) && (!rd_done_th_assert)) { (!rd_done_th_assert)) { Loading Loading @@ -149,7 +155,7 @@ irqreturn_t cam_cci_irq(int irq_num, void *data) cci_dev->cci_master_info[MASTER_1].status = 0; cci_dev->cci_master_info[MASTER_1].status = 0; rd_done_th_assert = true; rd_done_th_assert = true; complete(&cci_dev->cci_master_info[MASTER_1].th_complete); complete(&cci_dev->cci_master_info[MASTER_1].th_complete); complete(&cci_dev->cci_master_info[MASTER_1].reset_complete); complete(&cci_dev->cci_master_info[MASTER_1].rd_done); } } if ((irq_status0 & CCI_IRQ_STATUS_0_I2C_M1_RD_DONE_BMSK) && if ((irq_status0 & CCI_IRQ_STATUS_0_I2C_M1_RD_DONE_BMSK) && (!rd_done_th_assert)) { (!rd_done_th_assert)) { Loading @@ -158,7 +164,7 @@ irqreturn_t cam_cci_irq(int irq_num, void *data) if (cci_dev->is_burst_read) if (cci_dev->is_burst_read) complete( complete( &cci_dev->cci_master_info[MASTER_1].th_complete); &cci_dev->cci_master_info[MASTER_1].th_complete); complete(&cci_dev->cci_master_info[MASTER_1].reset_complete); complete(&cci_dev->cci_master_info[MASTER_1].rd_done); } } if ((irq_status1 & CCI_IRQ_STATUS_1_I2C_M1_RD_THRESHOLD) && if ((irq_status1 & CCI_IRQ_STATUS_1_I2C_M1_RD_THRESHOLD) && (!rd_done_th_assert)) { (!rd_done_th_assert)) { Loading Loading @@ -217,16 +223,33 @@ irqreturn_t cam_cci_irq(int irq_num, void *data) } } if (irq_status0 & CCI_IRQ_STATUS_0_I2C_M0_ERROR_BMSK) { if (irq_status0 & CCI_IRQ_STATUS_0_I2C_M0_ERROR_BMSK) { cci_dev->cci_master_info[MASTER_0].status = -EINVAL; cci_dev->cci_master_info[MASTER_0].status = -EINVAL; cam_io_w_mb(CCI_M0_HALT_REQ_RMSK, if (irq_status0 & CCI_IRQ_STATUS_0_I2C_M0_NACK_ERROR_BMSK) base + CCI_HALT_REQ_ADDR); CAM_ERR(CAM_CCI, "Base:%pK, M0 NACK ERROR: 0x%x", CAM_DBG(CAM_CCI, "MASTER_0 error 0x%x", irq_status0); base, irq_status0); if (irq_status0 & CCI_IRQ_STATUS_0_I2C_M0_Q0Q1_ERROR_BMSK) CAM_ERR(CAM_CCI, "Base:%pK, M0 QUEUE_OVER/UNDER_FLOW OR CMD ERR: 0x%x", base, irq_status0); if (irq_status0 & CCI_IRQ_STATUS_0_I2C_M0_RD_ERROR_BMSK) CAM_ERR(CAM_CCI, "Base: %pK, M0 RD_OVER/UNDER_FLOW ERROR: 0x%x", base, irq_status0); cam_io_w_mb(CCI_M0_HALT_REQ_RMSK, base + CCI_HALT_REQ_ADDR); } } if (irq_status0 & CCI_IRQ_STATUS_0_I2C_M1_ERROR_BMSK) { if (irq_status0 & CCI_IRQ_STATUS_0_I2C_M1_ERROR_BMSK) { cci_dev->cci_master_info[MASTER_1].status = -EINVAL; cci_dev->cci_master_info[MASTER_1].status = -EINVAL; cam_io_w_mb(CCI_M1_HALT_REQ_RMSK, if (irq_status0 & CCI_IRQ_STATUS_0_I2C_M0_NACK_ERROR_BMSK) base + CCI_HALT_REQ_ADDR); CAM_ERR(CAM_CCI, "Base:%pK, M1 NACK ERROR: 0x%x", CAM_DBG(CAM_CCI, "MASTER_1 error 0x%x", irq_status0); base, irq_status0); if (irq_status0 & CCI_IRQ_STATUS_0_I2C_M0_Q0Q1_ERROR_BMSK) CAM_ERR(CAM_CCI, "Base:%pK, M1 QUEUE_OVER_UNDER_FLOW OR CMD ERROR:0x%x", base, irq_status0); if (irq_status0 & CCI_IRQ_STATUS_0_I2C_M0_RD_ERROR_BMSK) CAM_ERR(CAM_CCI, "Base:%pK, M1 RD_OVER/UNDER_FLOW ERROR: 0x%x", base, irq_status0); cam_io_w_mb(CCI_M1_HALT_REQ_RMSK, base + CCI_HALT_REQ_ADDR); } } cam_io_w_mb(irq_status0, base + CCI_IRQ_CLEAR_0_ADDR); cam_io_w_mb(irq_status0, base + CCI_IRQ_CLEAR_0_ADDR); Loading Loading @@ -402,7 +425,8 @@ static int cam_cci_platform_probe(struct platform_device *pdev) } } g_cci_subdev[soc_info->index] = &new_cci_dev->v4l2_dev_str.sd; g_cci_subdev[soc_info->index] = &new_cci_dev->v4l2_dev_str.sd; CAM_ERR(CAM_CCI, "Device Type :%d", soc_info->index); mutex_init(&(new_cci_dev->init_mutex)); CAM_INFO(CAM_CCI, "Device Type :%d", soc_info->index); cam_register_subdev_fops(&cci_v4l2_subdev_fops); cam_register_subdev_fops(&cci_v4l2_subdev_fops); cci_v4l2_subdev_fops.unlocked_ioctl = cam_cci_subdev_fops_ioctl; cci_v4l2_subdev_fops.unlocked_ioctl = cam_cci_subdev_fops_ioctl; Loading
drivers/media/platform/msm/camera/cam_sensor_module/cam_cci/cam_cci_dev.h +38 −35 Original line number Original line Diff line number Diff line /* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. /* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. * * * This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -140,6 +140,7 @@ struct cam_cci_master_info { uint8_t reset_pending; uint8_t reset_pending; struct mutex mutex; struct mutex mutex; struct completion reset_complete; struct completion reset_complete; struct completion rd_done; struct completion th_complete; struct completion th_complete; struct mutex mutex_q[NUM_QUEUES]; struct mutex mutex_q[NUM_QUEUES]; struct completion report_q[NUM_QUEUES]; struct completion report_q[NUM_QUEUES]; Loading Loading @@ -192,8 +193,7 @@ enum cam_cci_state_t { * @cci_vreg: CCI regulator structure * @cci_vreg: CCI regulator structure * @cci_reg_ptr: CCI individual regulator structure * @cci_reg_ptr: CCI individual regulator structure * @regulator_count: Regulator count * @regulator_count: Regulator count * @support_seq_write: * @support_seq_write: Set this flag when sequential write is enabled * Set this flag when sequential write is enabled * @write_wq: Work queue structure * @write_wq: Work queue structure * @valid_sync: Is it a valid sync with CSID * @valid_sync: Is it a valid sync with CSID * @v4l2_dev_str: V4L2 device structure * @v4l2_dev_str: V4L2 device structure Loading @@ -206,6 +206,8 @@ enum cam_cci_state_t { * @is_burst_read: Flag to determine if we are performing * @is_burst_read: Flag to determine if we are performing * a burst read operation or not * a burst read operation or not * @irqs_disabled: Mask for IRQs that are disabled * @irqs_disabled: Mask for IRQs that are disabled * @init_mutex: Mutex for maintaining refcount for attached * devices to cci during init/deinit. */ */ struct cci_device { struct cci_device { struct v4l2_subdev subdev; struct v4l2_subdev subdev; Loading Loading @@ -234,6 +236,7 @@ struct cci_device { spinlock_t lock_status; spinlock_t lock_status; bool is_burst_read; bool is_burst_read; uint32_t irqs_disabled; uint32_t irqs_disabled; struct mutex init_mutex; }; }; enum cam_cci_i2c_cmd_type { enum cam_cci_i2c_cmd_type { Loading
drivers/media/platform/msm/camera/cam_sensor_module/cam_cci/cam_cci_hwreg.h +7 −1 Original line number Original line Diff line number Diff line /* Copyright (c) 2012-2015, 2017-2018, The Linux Foundation. All rights reserved. /* Copyright (c) 2012-2015, 2017-2019, The Linux Foundation. All rights reserved. * * * This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -61,6 +61,12 @@ #define CCI_IRQ_STATUS_0_I2C_M0_Q0_REPORT_BMSK 0x10 #define CCI_IRQ_STATUS_0_I2C_M0_Q0_REPORT_BMSK 0x10 #define CCI_IRQ_STATUS_0_I2C_M0_ERROR_BMSK 0x18000EE6 #define CCI_IRQ_STATUS_0_I2C_M0_ERROR_BMSK 0x18000EE6 #define CCI_IRQ_STATUS_0_I2C_M1_ERROR_BMSK 0x60EE6000 #define CCI_IRQ_STATUS_0_I2C_M1_ERROR_BMSK 0x60EE6000 #define CCI_IRQ_STATUS_0_I2C_M0_NACK_ERROR_BMSK 0x18000000 #define CCI_IRQ_STATUS_0_I2C_M1_NACK_ERROR_BMSK 0x60000000 #define CCI_IRQ_STATUS_0_I2C_M0_Q0Q1_ERROR_BMSK 0xEE0 #define CCI_IRQ_STATUS_0_I2C_M1_Q0Q1_ERROR_BMSK 0xEE0000 #define CCI_IRQ_STATUS_0_I2C_M0_RD_ERROR_BMSK 0x6 #define CCI_IRQ_STATUS_0_I2C_M1_RD_ERROR_BMSK 0x6000 #define CCI_IRQ_STATUS_0_I2C_M0_RD_DONE_BMSK 0x1 #define CCI_IRQ_STATUS_0_I2C_M0_RD_DONE_BMSK 0x1 #define CCI_IRQ_STATUS_1_I2C_M0_RD_THRESHOLD 0x10000 #define CCI_IRQ_STATUS_1_I2C_M0_RD_THRESHOLD 0x10000 #define CCI_IRQ_STATUS_1_I2C_M0_RD_PAUSE 0x20000 #define CCI_IRQ_STATUS_1_I2C_M0_RD_PAUSE 0x20000 Loading
drivers/media/platform/msm/camera/cam_sensor_module/cam_cci/cam_cci_soc.c +8 −4 Original line number Original line Diff line number Diff line Loading @@ -19,7 +19,7 @@ int cam_cci_init(struct v4l2_subdev *sd, uint8_t i = 0, j = 0; uint8_t i = 0, j = 0; int32_t rc = 0; int32_t rc = 0; struct cci_device *cci_dev; struct cci_device *cci_dev; enum cci_i2c_master_t master = MASTER_0; enum cci_i2c_master_t master = c_ctrl->cci_info->cci_i2c_master; struct cam_ahb_vote ahb_vote; struct cam_ahb_vote ahb_vote; struct cam_axi_vote axi_vote; struct cam_axi_vote axi_vote; struct cam_hw_soc_info *soc_info = NULL; struct cam_hw_soc_info *soc_info = NULL; Loading Loading @@ -47,7 +47,6 @@ int cam_cci_init(struct v4l2_subdev *sd, if (cci_dev->ref_count++) { if (cci_dev->ref_count++) { CAM_DBG(CAM_CCI, "ref_count %d", cci_dev->ref_count); CAM_DBG(CAM_CCI, "ref_count %d", cci_dev->ref_count); master = c_ctrl->cci_info->cci_i2c_master; CAM_DBG(CAM_CCI, "master %d", master); CAM_DBG(CAM_CCI, "master %d", master); if (master < MASTER_MAX && master >= 0) { if (master < MASTER_MAX && master >= 0) { mutex_lock(&cci_dev->cci_master_info[master].mutex); mutex_lock(&cci_dev->cci_master_info[master].mutex); Loading @@ -55,6 +54,8 @@ int cam_cci_init(struct v4l2_subdev *sd, /* Re-initialize the completion */ /* Re-initialize the completion */ reinit_completion( reinit_completion( &cci_dev->cci_master_info[master].reset_complete); &cci_dev->cci_master_info[master].reset_complete); reinit_completion( &cci_dev->cci_master_info[master].rd_done); for (i = 0; i < NUM_QUEUES; i++) for (i = 0; i < NUM_QUEUES; i++) reinit_completion( reinit_completion( &cci_dev->cci_master_info[master].report_q[i]); &cci_dev->cci_master_info[master].report_q[i]); Loading Loading @@ -93,6 +94,7 @@ int cam_cci_init(struct v4l2_subdev *sd, /* Re-initialize the completion */ /* Re-initialize the completion */ reinit_completion(&cci_dev->cci_master_info[master].reset_complete); reinit_completion(&cci_dev->cci_master_info[master].reset_complete); reinit_completion(&cci_dev->cci_master_info[master].rd_done); for (i = 0; i < NUM_QUEUES; i++) for (i = 0; i < NUM_QUEUES; i++) reinit_completion( reinit_completion( &cci_dev->cci_master_info[master].report_q[i]); &cci_dev->cci_master_info[master].report_q[i]); Loading Loading @@ -128,12 +130,12 @@ int cam_cci_init(struct v4l2_subdev *sd, } } } } cci_dev->cci_master_info[MASTER_0].reset_pending = TRUE; cci_dev->cci_master_info[master].reset_pending = TRUE; cam_io_w_mb(CCI_RESET_CMD_RMSK, base + cam_io_w_mb(CCI_RESET_CMD_RMSK, base + CCI_RESET_CMD_ADDR); CCI_RESET_CMD_ADDR); cam_io_w_mb(0x1, base + CCI_RESET_CMD_ADDR); cam_io_w_mb(0x1, base + CCI_RESET_CMD_ADDR); rc = wait_for_completion_timeout( rc = wait_for_completion_timeout( &cci_dev->cci_master_info[MASTER_0].reset_complete, &cci_dev->cci_master_info[master].reset_complete, CCI_TIMEOUT); CCI_TIMEOUT); if (rc <= 0) { if (rc <= 0) { CAM_ERR(CAM_CCI, "wait_for_completion_timeout"); CAM_ERR(CAM_CCI, "wait_for_completion_timeout"); Loading Loading @@ -205,6 +207,8 @@ static void cam_cci_init_cci_params(struct cci_device *new_cci_dev) &new_cci_dev->cci_master_info[i].reset_complete); &new_cci_dev->cci_master_info[i].reset_complete); init_completion( init_completion( &new_cci_dev->cci_master_info[i].th_complete); &new_cci_dev->cci_master_info[i].th_complete); init_completion( &new_cci_dev->cci_master_info[i].rd_done); for (j = 0; j < NUM_QUEUES; j++) { for (j = 0; j < NUM_QUEUES; j++) { mutex_init(&new_cci_dev->cci_master_info[i].mutex_q[j]); mutex_init(&new_cci_dev->cci_master_info[i].mutex_q[j]); Loading