How to disable CSI mipi CRC check on Xavier?

Hi, @ShaneCCC :

We use the FPGA for HDMI video to MIPI CSI, video format YUV422, resolution 1920x1080xP60.
HDMI video 1920x1080xP60 → FPGA → MIPI CSI 4 Lanes / YUV422
The FPGA convert the HDMI video into MIPI CSI format and is connected to MIPI CSI interface 4 Lanes(CSI A, CSI B) of Xavier
As below block diagram:

.

Our CRC of FPGA mipi output doesn’t match Nvidia CSI CRC algorithm, but it is working after disable CRC patch on TX2.
See post:
HDMI FPGA to TX2 MIPI CSI

// csi4_stream_write(chan, port_num, INTR_MASK, 0x0);
// csi4_stream_write(chan, port_num, ERR_INTR_MASK, 0x0);

   csi4_stream_write(chan, port_num, INTR_MASK, PH_ECC_MULTI_BIT_ERR |
                   PD_CRC_ERR_VC0 | PH_ECC_SINGLE_BIT_ERR_VC0);
   csi4_stream_write(chan, port_num, ERR_INTR_MASK, PH_ECC_MULTI_BIT_ERR |
                   PD_CRC_ERR_VC0 | PH_ECC_SINGLE_BIT_ERR_VC0);
   csi4_stream_write(chan, port_num, ERROR_STATUS2VI_MASK,
                   CFG_ERR_STATUS2VI_MASK_VC0 |
                   CFG_ERR_STATUS2VI_MASK_VC1 |
                   CFG_ERR_STATUS2VI_MASK_VC2 |
                   CFG_ERR_STATUS2VI_MASK_VC3);

Now we move this FPGA from TX2 to Xavier, but looks like Xavier VI/CSI driver didn’t programing the REG like TX2.

How to disable CSI mipi CRC check on Xavier?

@SammyChenTw
Just check the csi5_fops.c I think you can try to implement the csi5_stream_write() like csi4_fops to configure the REG to disable it.

Hi, @ShaneCCC :
But I can’t see the csi5_stream_write() in csi5_fpos.c, and only see csi5_phy_write(),
and I also can’t see csi5_stream_init().

Do you mean use csi5_phy_write() to replace csi5_stream_write in csi5_stream_init()?

csi5_fpos.c
csi5_stream_init() {

csi5_phy_write(chan, port_num, INTR_MASK, PH_ECC_MULTI_BIT_ERR |
               PD_CRC_ERR_VC0 | PH_ECC_SINGLE_BIT_ERR_VC0);
csi5_phy_write(chan, port_num, ERR_INTR_MASK, PH_ECC_MULTI_BIT_ERR |
               PD_CRC_ERR_VC0 | PH_ECC_SINGLE_BIT_ERR_VC0);
csi5_phy_write(chan, port_num, ERROR_STATUS2VI_MASK,
               CFG_ERR_STATUS2VI_MASK_VC0 |
               CFG_ERR_STATUS2VI_MASK_VC1 |
               CFG_ERR_STATUS2VI_MASK_VC2 |
               CFG_ERR_STATUS2VI_MASK_VC3);

}

No, I think you can reference to the csi4_fops.c to implement the csi5_stream_write() to program the mask REG to disable it.

What’s difference flow betewwn csi4_fops.c and csi5_fops.c?
Have you any document to introduct it?
Which flow I need to add csi5_stream_write()?

Sorry, there’s no document for it. I think you can trace them to know the detail.

I see the csi4_stream_init() start from csi4_error_recover(),
but how to mapping these csi4 registers to csi5?

#define CSI4_STREAM_OFFSET		        0x800
#define CILA_INTR_STATUS				0x400
#define CILA_INTR_MASK					0x404
#define CILA_ERR_INTR_STATUS			0x408
#define CILA_ERR_INTR_MASK				0x40c
#define CILB_INTR_STATUS				0xc00
#define CILB_INTR_MASK					0xc04
#define CILB_ERR_INTR_STATUS			0xc08
#define CILB_ERR_INTR_MASK				0xc0c
#define INTR_STATUS					    0xa4
#define ERR_INTR_STATUS				    0xac
#define ERR_INTR_MASK				    0xb0
#define ERROR_STATUS2VI_MASK		    0x90
#define PH_ECC_MULTI_BIT_ERR			(0x1 << 16)
#define PD_CRC_ERR_VC0				    (0x1 << 2)
#define PH_ECC_SINGLE_BIT_ERR_VC0		(0x1 << 1)

Have a try below patch.

diff --git a/drivers/media/platform/tegra/camera/nvcsi/csi5_fops.c b/drivers/media/platform/tegra/camera/nvcsi/csi5_fops.c
index d23994d..3530df6 100644
--- a/drivers/media/platform/tegra/camera/nvcsi/csi5_fops.c
+++ b/drivers/media/platform/tegra/camera/nvcsi/csi5_fops.c
@@ -45,6 +45,24 @@
  */
 #define TPG_BLANK 6

+static void csi5_stream_write(struct tegra_csi_channel *chan,
+                unsigned int index, unsigned int addr, u32 val)
+{
+        struct tegra_csi_device *csi = chan->csi;
+        u32 cilb_offset = (index & 0x1) ? CSI5_STREAM_OFFSET : 0x0;
+
+        writel(val, csi->iomem[index >> 1] + cilb_offset + addr);
+}
+
+static u32 csi5_stream_read(struct tegra_csi_channel *chan,
+                unsigned int index, unsigned int addr)
+{
+        struct tegra_csi_device *csi = chan->csi;
+        u32 cilb_offset = (index & 0x1) ? CSI5_STREAM_OFFSET : 0x0;
+
+        return readl(csi->iomem[index >> 1] + cilb_offset + addr);
+}
+
 static void csi5_phy_write(struct tegra_csi_channel *chan,
                unsigned int index, unsigned int addr, u32 val)
 {
@@ -295,6 +313,7 @@ static int csi5_start_streaming(struct tegra_csi_channel *chan, int port_idx)
        if (!chan->pg_mode)
                csi5_stream_set_config(chan, st_id, csi_pt, num_lanes);

+       dev_info(csi->dev, "PH_CHK_CTRL = %d\n", csi5_stream_read(chan, port_idx, CSI5_PH_CHK_CTRL));
        csi5_stream_open(chan, st_id, csi_pt);

        if (chan->pg_mode) {
@@ -302,6 +321,8 @@ static int csi5_start_streaming(struct tegra_csi_channel *chan, int port_idx)
                if (err)
                        return err;
        }
+       csi5_stream_write(chan, port_idx, CSI5_PH_CHK_CTRL, 0x0);
+       dev_info(csi->dev, "PH_CHK_CTRL = %d\n", csi5_stream_read(chan, port_idx, CSI5_PH_CHK_CTRL));

        return err;
 }
diff --git a/include/media/csi5_registers.h b/include/media/csi5_registers.h
index 0d37859..049cf6a 100644
--- a/include/media/csi5_registers.h
+++ b/include/media/csi5_registers.h
@@ -24,11 +24,14 @@

 #define CSI5_BASE_ADDRESS              0x011000
 #define CSI5_PHY_OFFSET                        0x010000
+#define CSI5_STREAM_OFFSET              0x800
 #define CSI5_TEGRA_CSI_STREAM_0_BASE   0x10000
 #define CSI5_TEGRA_CSI_STREAM_2_BASE   0x20000
 #define CSI5_TEGRA_CSI_STREAM_4_BASE   0x30000

+#define CSI5_PH_CHK_CTRL                     0x194
+
 #define CSI5_NVCSI_CIL_A_SW_RESET      0x24
 #define CSI5_NVCSI_CIL_B_SW_RESET      0xb0
 #define CSI5_SW_RESET1_EN              (0x1 << 1)