diff --git a/drivers/media/platform/rockchip/cif/mipi-csi2.c b/drivers/media/platform/rockchip/cif/mipi-csi2.c index bc74726c94c1..8258dfd669a2 100644 --- a/drivers/media/platform/rockchip/cif/mipi-csi2.c +++ b/drivers/media/platform/rockchip/cif/mipi-csi2.c @@ -282,6 +282,8 @@ static int csi2_start(struct csi2_dev *csi2) else host_type = RK_CSI_RXHOST; + csi2->irq1_timestamp = 0; + csi2->irq2_timestamp = 0; for (i = 0; i < csi2->csi_info.csi_num; i++) { csi_idx = csi2->csi_info.csi_idx[i]; ret |= csi2_hw_start(csi2->csi2_hw[csi_idx], host_type); @@ -840,6 +842,7 @@ static irqreturn_t rk_csirx_irq1_handler(int irq, void *ctx) char cur_str[CSI_ERRSTR_LEN] = {0}; char vc_info[CSI_VCINFO_LEN] = {0}; bool is_add_cnt = false; + u64 cur_timestamp = ktime_get_ns(); if (!csi2_hw) { disable_irq_nosync(irq); @@ -912,7 +915,7 @@ static irqreturn_t rk_csirx_irq1_handler(int irq, void *ctx) } if (val & CSIHOST_ERR1_ERR_ECC2) { - err_list = &csi2->err_list[RK_CSI2_ERR_CRC]; + err_list = &csi2->err_list[RK_CSI2_ERR_ECC2]; err_list->cnt++; is_add_cnt = true; snprintf(cur_str, CSI_ERRSTR_LEN, "(ecc2) "); @@ -920,12 +923,17 @@ static irqreturn_t rk_csirx_irq1_handler(int irq, void *ctx) } if (val & CSIHOST_ERR1_ERR_CTRL) { + err_list = &csi2->err_list[RK_CSI2_ERR_CTRL]; + err_list->cnt++; csi2_find_err_vc((val >> 16) & 0xf, vc_info); snprintf(cur_str, CSI_ERRSTR_LEN, "(ctrl,vc:%s) ", vc_info); csi2_err_strncat(err_str, cur_str); } - pr_err("(0x%x)MIPI_CSI2 ERR1:0x%x %s\n", (u32)csi2_hw->res->start, val, err_str); + if (csi2->irq1_timestamp == 0 || cur_timestamp - csi2->irq1_timestamp > 1000000000) { + csi2->irq1_timestamp = cur_timestamp; + pr_err("(0x%x)MIPI_CSI2 ERR1:0x%x %s\n", (u32)csi2_hw->res->start, val, err_str); + } if (is_add_cnt) { csi2->err_list[RK_CSI2_ERR_ALL].cnt++; @@ -946,16 +954,24 @@ static irqreturn_t rk_csirx_irq2_handler(int irq, void *ctx) { struct device *dev = ctx; struct csi2_hw *csi2_hw = dev_get_drvdata(dev); + struct csi2_dev *csi2 = NULL; u32 val; char cur_str[CSI_ERRSTR_LEN] = {0}; char err_str[CSI_ERRSTR_LEN] = {0}; char vc_info[CSI_VCINFO_LEN] = {0}; + u64 cur_timestamp = ktime_get_ns(); if (!csi2_hw) { disable_irq_nosync(irq); return IRQ_HANDLED; } + csi2 = csi2_hw->csi2; + if (!csi2) { + disable_irq_nosync(irq); + return IRQ_HANDLED; + } + val = read_csihost_reg(csi2_hw->base, CSIHOST_ERR2); if (val) { if (val & CSIHOST_ERR2_PHYERR_ESC) { @@ -983,7 +999,10 @@ static irqreturn_t rk_csirx_irq2_handler(int irq, void *ctx) csi2_err_strncat(err_str, cur_str); } - pr_err("(0x%x)MIPI_CSI2 ERR2:0x%x %s\n", (u32)csi2_hw->res->start, val, err_str); + if (csi2->irq2_timestamp == 0 || cur_timestamp - csi2->irq2_timestamp > 1000000000) { + csi2->irq2_timestamp = cur_timestamp; + pr_err("(0x%x)MIPI_CSI2 ERR2:0x%x %s\n", (u32)csi2_hw->res->start, val, err_str); + } } return IRQ_HANDLED; diff --git a/drivers/media/platform/rockchip/cif/mipi-csi2.h b/drivers/media/platform/rockchip/cif/mipi-csi2.h index 026b48ff552f..93c4bc3fbc9b 100644 --- a/drivers/media/platform/rockchip/cif/mipi-csi2.h +++ b/drivers/media/platform/rockchip/cif/mipi-csi2.h @@ -113,6 +113,8 @@ enum csi2_err { RK_CSI2_ERR_FRM_SEQ_ERR, RK_CSI2_ERR_CRC_ONCE, RK_CSI2_ERR_CRC, + RK_CSI2_ERR_ECC2, + RK_CSI2_ERR_CTRL, RK_CSI2_ERR_ALL, RK_CSI2_ERR_MAX }; @@ -176,6 +178,8 @@ struct csi2_dev { struct rkcif_csi_info csi_info; const char *dev_name; int sw_dbg; + u64 irq1_timestamp; + u64 irq2_timestamp; }; struct csi2_hw { diff --git a/drivers/media/platform/rockchip/cif/procfs.c b/drivers/media/platform/rockchip/cif/procfs.c index 1956020b1f75..6122ab4ff2c8 100644 --- a/drivers/media/platform/rockchip/cif/procfs.c +++ b/drivers/media/platform/rockchip/cif/procfs.c @@ -526,6 +526,27 @@ static void rkcif_show_reg_dbg(struct rkcif_device *dev, struct seq_file *f) } } +static void rkcif_show_mipi_csi2_error_info(struct rkcif_device *dev, struct seq_file *f) +{ + struct csi2_dev *csi2 = container_of(dev->active_sensor->sd, struct csi2_dev, sd); + + seq_puts(f, "\nMipi error info:\n"); + seq_printf(f, "\terr sot sync:%u\n", + csi2->err_list[RK_CSI2_ERR_SOTSYN].cnt); + seq_printf(f, "\terr fs/fe not match:%u\n", + csi2->err_list[RK_CSI2_ERR_FS_FE_MIS].cnt); + seq_printf(f, "\terr frm seq:%u\n", + csi2->err_list[RK_CSI2_ERR_FRM_SEQ_ERR].cnt); + seq_printf(f, "\terr crc once:%u\n", + csi2->err_list[RK_CSI2_ERR_CRC_ONCE].cnt); + seq_printf(f, "\terr crc:%u\n", + csi2->err_list[RK_CSI2_ERR_CRC].cnt); + seq_printf(f, "\terr ecc2:%u\n", + csi2->err_list[RK_CSI2_ERR_ECC2].cnt); + seq_printf(f, "\terr ctrl:%u\n", + csi2->err_list[RK_CSI2_ERR_CTRL].cnt); +} + static void rkcif_show_format(struct rkcif_device *dev, struct seq_file *f) { struct rkcif_stream *stream = &dev->stream[0]; @@ -676,6 +697,9 @@ static void rkcif_show_format(struct rkcif_device *dev, struct seq_file *f) rkcif_show_toisp_info(dev, f); if (dev->reg_dbg) rkcif_show_reg_dbg(dev, f); + if (sensor->mbus.type == V4L2_MBUS_CSI2_DPHY || + sensor->mbus.type == V4L2_MBUS_CSI2_CPHY) + rkcif_show_mipi_csi2_error_info(dev, f); } }