Browse Source

Linux_SDK_V1.0.2

thead_admin 1 year ago
parent
commit
34b5899c3c

+ 1 - 1
driver/common/bm_printk.h

@@ -37,7 +37,7 @@
 #define bm_notice(fmt, ...) \
 	printk(KERN_NOTICE pr_fmt(fmt), ##__VA_ARGS__)
 #define bm_info(fmt, ...) \
-	printk(KERN_INFO pr_fmt(fmt), ##__VA_ARGS__)
+    printk(KERN_DEBUG   pr_fmt(fmt), ##__VA_ARGS__)
 #else
 #define bm_notice(fmt, ...)
 #define bm_info(fmt, ...)

+ 60 - 12
driver/csi/bm_csi_driver.c

@@ -32,6 +32,7 @@
 #include <linux/pm_runtime.h>
 
 #include <linux/of.h>
+#include <linux/mfd/syscon.h>
 
 #include "bm_printk.h"
 #include "bm_csi_ioctl.h"
@@ -52,9 +53,10 @@ static unsigned int device_register_index = 0;
 			return -EIO;\
 	} while (0)
 
-static unsigned int bm_csi_poll(struct file * filp, poll_table *wait)
+extern unsigned csi_poll(struct file *file, struct poll_table_struct *wait);
+static unsigned int bm_csi_poll(struct file * filp, struct poll_table_struct *wait)
 {
-	return 0;
+	return csi_poll(filp, wait);
 }
 
 void bm_csi_work(struct work_struct *work)
@@ -70,7 +72,7 @@ irqreturn_t bm_csi_irq(int irq, void *dev_id)
 static int bm_csi_runtime_suspend(struct device *dev)
 {
 	struct bm_csi_drvdata *pdriver_dev = dev_get_drvdata(dev);
-	dev_info(dev, "enter %s\n", __func__);
+	bm_info("enter %s\n", __func__);
 
     if (pdriver_dev->pclk != NULL) {
 	    clk_disable_unprepare(pdriver_dev->pclk);
@@ -99,7 +101,7 @@ static int bm_csi_runtime_resume(struct device *dev)
 {
 	int ret = 0;
 	struct bm_csi_drvdata *pdriver_dev = dev_get_drvdata(dev);
-	dev_info(dev, "enter %s\n", __func__);
+	bm_info("enter %s\n", __func__);
 
     if (pdriver_dev->pclk != NULL) {
 	    ret = clk_prepare_enable(pdriver_dev->pclk);
@@ -161,12 +163,19 @@ static int bm_csi_open(struct inode * inode, struct file * file)
     struct device *dev;
 
 	bm_info("enter %s\n",  __func__);
-	dev_info(dev, "open mipi-csi dev\n");
+	bm_info("open mipi-csi dev\n");
 
 	drvdata = container_of(inode->i_cdev, struct bm_csi_drvdata, cdev);
 	file->private_data = drvdata;
     dev = &drvdata->pdev->dev;
-	dev_info(dev, "open mipi-csi dev\n");
+    drvdata->csi_power_on_sta = 0;
+    memset(&drvdata->csi_dev.hw, 0, sizeof(drvdata->csi_dev.hw));
+	drvdata->csi_dev.hw.ipi_mode = CAMERA_TIMING;
+    drvdata->csi_dev.hw.ipi_color_mode = COLOR16;
+
+    memset(&drvdata->csi_dev.error_mask, 0, sizeof(drvdata->csi_dev.error_mask));
+
+	bm_info("open mipi-csi dev\n");
     if (pm_runtime_get_sync(dev)) {
 		ret = bm_csi_runtime_resume(dev);
 		if (ret)
@@ -196,6 +205,9 @@ static long bm_csi_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 	case BMCSI_IOC_READ_REG:
 		ret = bm_csi_read_reg(drvdata, (void *)arg);
 		break;
+	case BMCSI_IOC_READ_ARRAY:
+        ret = bm_csi_read_array(drvdata, (void *)arg);
+        break;
     case BMCSI_IOC_S_RESET:
         ret = bm_csi_reset(drvdata, (void *)arg);
 		break;
@@ -253,6 +265,9 @@ static long bm_csi_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
     case BMCSI_IOC_GET_PIXCLK:
         ret = bm_csi_get_pixclk(drvdata, (void *)arg);
 		break;
+    case BMCSI_IOC_GET_ERROR:
+        ret = bm_csi_get_error(drvdata, (void *)arg);
+		break;
     case BMCSI_IOC_MAX:
 		break;
 	default:
@@ -275,7 +290,7 @@ static int bm_csi_release(struct inode * inode, struct file * file)
 	drvdata = container_of(inode->i_cdev, struct bm_csi_drvdata, cdev);
 	file->private_data = drvdata;
     dev = &drvdata->pdev->dev;
-	dev_info(dev, "release mipi-csi dev\n");
+	bm_info("release mipi-csi dev\n");
     ret = bm_csi_dis_power(drvdata);
     if (ret) {
 		pr_info("fail to disable csi power, %s %d\n", __func__, __LINE__);
@@ -311,6 +326,7 @@ static int bm_csi_probe(struct platform_device *pdev)
 	struct resource *iores_mem;
     unsigned int dphyglueiftester= 0;
     unsigned int sysreg_mipi_csi_ctrl = 0;
+    struct device_node *np = pdev->dev.of_node;
 	u32 value;
 
 	bm_info("enter %s\n", __func__);
@@ -326,11 +342,43 @@ static int bm_csi_probe(struct platform_device *pdev)
 		return  -ENOMEM;
 	}
 
+    memset(drvdata, 0, sizeof(*drvdata));
+
 	iores_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	drvdata->base = devm_ioremap_resource(&pdev->dev, iores_mem);
+
 	bm_info("%s: [%s%d]: drvdata->base=0x%px, phy_addr base=0x%llx\n", __func__,
 		BM_DRIVER_NAME, pdev->id, drvdata->base, iores_mem->start);
 
+    /*
+    if (iores_mem->start == 0xffe4010000) {
+        drvdata->visys_clk_reg = syscon_regmap_lookup_by_phandle(np, "visys-regmap");
+        if (IS_ERR(drvdata->visys_clk_reg)) {
+            drvdata->visys_clk_reg = NULL;
+            dev_err(&pdev->dev, "cannot find regmap for visys clk register\n");
+        }
+
+        drvdata->csia_reg = syscon_regmap_lookup_by_phandle(np, "csia-regmap");
+        if (IS_ERR(drvdata->csia_reg)) {
+            drvdata->csia_reg = NULL;
+            dev_err(&pdev->dev, "cannot find regmap for csia register\n");
+        }
+    }
+    */
+
+    const char *phy_name;
+    ret = of_property_read_string(np, "phy_name", &phy_name);
+    if (strcmp(phy_name, "CSI_B") == 0) {
+	    bm_info("mipi is b phy\n");
+        drvdata->phy_id = MIPI_B_PHY;
+    } else if(strcmp(phy_name, "CSI_A") == 0) {
+	    bm_info("mipi is a phy\n");
+        drvdata->phy_id = MIPI_A_PHY;
+    } else if(strcmp(phy_name, "CSI_4LANE") == 0) {
+	    bm_info("mipi is 4lane phy\n");
+        drvdata->phy_id = MIPI_4LANE_PHY;
+    }
+
 	drvdata->reset = NULL;
 	drvdata->device_idx = pdev->id;
 	mutex_init(&drvdata->mutex);
@@ -420,16 +468,16 @@ static int bm_csi_probe(struct platform_device *pdev)
     device_property_read_u32(&pdev->dev, "sysreg_mipi_csi_ctrl", &sysreg_mipi_csi_ctrl);
 	bm_info("sysreg_mipi_csi_ctrl is:0x%x\n", sysreg_mipi_csi_ctrl);
 
-    dw_dphy_rx_probe(pdev, dphyglueiftester, sysreg_mipi_csi_ctrl);
-    dw_csi_probe(pdev);
-
     pm_runtime_enable(&pdev->dev);
-	ret = bm_csi_runtime_resume(&pdev->dev);
+    ret = pm_runtime_get_sync(&pdev->dev);
 	if (ret < 0) {
 		dev_err(&pdev->dev, "fail to resume csi\n");
 	}
 
-	ret = bm_csi_runtime_suspend(&pdev->dev);
+    dw_dphy_rx_probe(pdev, dphyglueiftester, sysreg_mipi_csi_ctrl);
+    dw_csi_probe(pdev);
+
+    ret = pm_runtime_put_sync(&pdev->dev);
 	if (ret < 0) {
 		dev_err(&pdev->dev, "fail to suspend csi\n");
 	}

+ 69 - 13
driver/csi/bm_csi_hw.c

@@ -31,6 +31,7 @@
 #include <linux/interrupt.h>
 
 #include <linux/of.h>
+#include <linux/regmap.h>
 
 #include "bm_printk.h"
 #include "bm_csi_ioctl.h"
@@ -70,6 +71,24 @@ int bm_csi_read_reg(struct bm_csi_drvdata *drvdata, void *__user args)
 	return 0;
 }
 
+int bm_csi_read_array(struct bm_csi_drvdata *drvdata, void *__user args)
+{
+	int index = 0;
+	int cnt = 0;
+    uint32_t value = 0;
+    struct bm_csi_reg_arry_t array;
+
+	check_retval(copy_from_user(&array, args, sizeof(struct bm_csi_reg_arry_t)));
+    cnt = array.words;
+
+	for (index = 0; index < cnt; index++) {
+	    value = readl(drvdata->base + array.start_addr + index * 4);
+		check_retval(copy_to_user(&(array.buf[index]), &value, sizeof(value)));
+	}
+
+	return 0;
+}
+
 int bm_csi_reset(struct bm_csi_drvdata *drvdata, void *__user args)
 {
 	bm_info("%s: csi reset success\n", __func__);
@@ -79,36 +98,62 @@ int bm_csi_reset(struct bm_csi_drvdata *drvdata, void *__user args)
 	return 0;
 }
 
-static uint32_t csi_power_on_sta = 0;
-
 int bm_csi_en_power(struct bm_csi_drvdata *drvdata)
 {
 	bm_info("%s: csi set power\n", __func__);
-	csi_power_on_sta = 1;
-    dw_mipi_csi_s_power(&drvdata->csi_dev, csi_power_on_sta);
+	drvdata->csi_power_on_sta = 1;
+    dw_mipi_csi_s_power(&drvdata->csi_dev, drvdata->csi_power_on_sta);
 	return 0;
 }
 
 int bm_csi_dis_power(struct bm_csi_drvdata *drvdata)
 {
 	bm_info("%s: csi set power\n", __func__);
-	csi_power_on_sta = 0;
-    dw_mipi_csi_s_power(&drvdata->csi_dev, csi_power_on_sta);
+	drvdata->csi_power_on_sta = 0;
+    dw_mipi_csi_s_power(&drvdata->csi_dev, drvdata->csi_power_on_sta);
 	return 0;
 }
 
+static int bm_csi_can_enable(struct bm_csi_drvdata *drvdata)
+{
+    return 1;
+    u32 csia_pixclk = 0;
+    u32 csia_rst = 0;
+    u32 csia_shutdown = 0;
+
+    if (drvdata->csia_reg == NULL || drvdata->visys_clk_reg == NULL) {
+        return 1;
+    }
+
+    regmap_read(drvdata->visys_clk_reg, 0xa0, &csia_pixclk);
+    regmap_read(drvdata->csia_reg, 0x40 + R_CSI2_DPHY_RSTZ, &csia_rst);
+    regmap_read(drvdata->csia_reg, 0x40 + R_CSI2_DPHY_SHUTDOWNZ, &csia_shutdown);
+
+    if (csia_pixclk & (1 << 9) && (csia_rst | csia_shutdown)) {
+        return 0;
+    }
+
+    return 1;
+}
+
 int bm_csi_set_power(struct bm_csi_drvdata *drvdata, void *__user args)
 {
 	bm_info("%s: csi set power\n", __func__);
-	check_retval(copy_from_user(&csi_power_on_sta, args, sizeof(csi_power_on_sta)));
-    dw_mipi_csi_s_power(&drvdata->csi_dev, csi_power_on_sta);
+	check_retval(copy_from_user(&drvdata->csi_power_on_sta, args, sizeof(drvdata->csi_power_on_sta)));
+
+    if (!bm_csi_can_enable(drvdata)) {
+        printk("can't enable csi power!!!!!!!!!!!!!\n");
+        return -1;
+    }
+
+    dw_mipi_csi_s_power(&drvdata->csi_dev, drvdata->csi_power_on_sta);
 	return 0;
 }
 
 int bm_csi_get_power(struct bm_csi_drvdata *drvdata, void *__user args)
 {
 	bm_info("%s: csi get power\n", __func__);
-	check_retval(copy_to_user(args, &csi_power_on_sta, sizeof(csi_power_on_sta)));
+	check_retval(copy_to_user(args, &drvdata->csi_power_on_sta, sizeof(drvdata->csi_power_on_sta)));
 	return 0;
 }
 
@@ -146,6 +191,14 @@ int bm_csi_get_pixclk(struct bm_csi_drvdata *drvdata, void *__user args)
     return 0;
 }
 
+int bm_csi_get_error(struct bm_csi_drvdata *drvdata, void *__user args)
+{
+	bm_info("%s: \n", __func__);
+    struct dw_csi_err_mask *error_mask = &drvdata->csi_dev.error_mask;
+	check_retval(copy_to_user(args, error_mask, sizeof(struct dw_csi_err_mask)));
+    return 0;
+}
+
 int bm_csi_set_stream(struct bm_csi_drvdata *drvdata, void *__user args)
 {
 	bm_info("%s: \n", __func__);
@@ -155,7 +208,7 @@ int bm_csi_set_stream(struct bm_csi_drvdata *drvdata, void *__user args)
 int bm_csi_get_stream(struct bm_csi_drvdata *drvdata, void *__user args)
 {
 	bm_info("%s: \n", __func__);
-	check_retval(copy_to_user(args, &csi_power_on_sta, sizeof(csi_power_on_sta)));
+	check_retval(copy_to_user(args, &drvdata->csi_power_on_sta, sizeof(drvdata->csi_power_on_sta)));
 	return 0;
 }
 
@@ -209,13 +262,10 @@ int bm_csi_set_vc_select(struct bm_csi_drvdata *drvdata, void *__user args)
 	check_retval(copy_from_user(&vc, args, sizeof(vc)));
 
     if (vc.ipi_idx == 1) {
-        csi_dev->hw.ipi1_en = true;
         csi_dev->hw.virtual_ch = vc.vc_ch;
     } else if (vc.ipi_idx == 2) {
-        csi_dev->hw.ipi2_en = true;
         csi_dev->hw.ipi2_virtual_ch = vc.vc_ch;
     } else if (vc.ipi_idx == 3) {
-        csi_dev->hw.ipi3_en = true;
         csi_dev->hw.ipi3_virtual_ch = vc.vc_ch;
     }
 
@@ -227,6 +277,12 @@ int bm_csi_ipi_enable(struct bm_csi_drvdata *drvdata, void *__user args)
     int ipi_idx;
     struct dw_csi *csi_dev = &drvdata->csi_dev;
 	bm_info("%s: \n", __func__);
+
+    if (!bm_csi_can_enable(drvdata)) {
+        printk("can't enable csi ipi!!!!!!!!!!!!!\n");
+        return -1;
+    }
+
 	check_retval(copy_from_user(&ipi_idx, args, sizeof(ipi_idx)));
 
     if (ipi_idx == 1) {

+ 7 - 0
driver/csi/bm_csi_hw.h

@@ -23,7 +23,10 @@ struct bm_csi_drvdata {
 	struct mutex mutex;
 	unsigned int device_idx;
 	void __iomem *base;
+    struct regmap *csia_reg;
+    struct regmap *visys_clk_reg;
 	void __iomem *reset;
+    phy_id_e phy_id;
     struct dw_dphy_rx *dphy;
     struct dw_csi csi_dev;
 	struct dw_csih_pdata csi_pdata;
@@ -35,6 +38,8 @@ struct bm_csi_drvdata {
 	struct clk *cfg_clk1;
 	struct clk *cfg_clk2;
 	struct platform_device *pdev;
+    uint32_t csi_power_on_sta;
+    wait_queue_head_t irq_wait;
 	void *private;	// can be bm_csi_drvdata_private, but not use now
 };
 
@@ -44,6 +49,7 @@ struct bm_csi_drvdata_private {
 
 int bm_csi_write_reg(struct bm_csi_drvdata *drvdata, void *__user args);
 int bm_csi_read_reg(struct bm_csi_drvdata *drvdata, void *__user args);
+int bm_csi_read_array(struct bm_csi_drvdata *drvdata, void *__user args);
 int bm_csi_init(struct bm_csi_drvdata *drvdata, void *__user args);
 int bm_csi_exit(struct bm_csi_drvdata *drvdata, void *__user args);
 int bm_csi_reset(struct bm_csi_drvdata *drvdata, void *__user args);
@@ -57,6 +63,7 @@ int bm_csi_set_pixclk(struct bm_csi_drvdata *drvdata, void *__user args);
 int bm_csi_get_pixclk(struct bm_csi_drvdata *drvdata, void *__user args);
 int bm_csi_set_stream(struct bm_csi_drvdata *drvdata, void *__user args);
 int bm_csi_get_stream(struct bm_csi_drvdata *drvdata, void *__user args);
+int bm_csi_get_error(struct bm_csi_drvdata *drvdata, void *__user args);
 int bm_csi_set_fmt(struct bm_csi_drvdata *drvdata, void *__user args);
 int bm_csi_get_fmt(struct bm_csi_drvdata *drvdata, void *__user args);
 int bm_csi_set_vc_select(struct bm_csi_drvdata *drvdata, void *__user args);

+ 28 - 0
driver/csi/bm_csi_ioctl.h

@@ -31,8 +31,10 @@ enum {
     BMCSI_IOC_S_HSD_CFG,
 	BMCSI_IOC_WRITE_REG,
 	BMCSI_IOC_READ_REG,
+	BMCSI_IOC_READ_ARRAY,
 	BMCSI_IOC_SET_PIXCLK,
     BMCSI_IOC_GET_PIXCLK,
+    BMCSI_IOC_GET_ERROR,
     BMCSI_IOC_MAX,
 };
 
@@ -41,9 +43,35 @@ struct bm_csi_reg_t {
 	unsigned int value;
 };
 
+struct bm_csi_reg_arry_t {
+	unsigned int start_addr;
+	unsigned int words;
+    unsigned int *buf;
+};
+
 struct csi_vc_select_context {
     unsigned int ipi_idx;
     unsigned int vc_ch;
 };
 
+struct dw_csi_err_mask {
+    unsigned int src;
+    unsigned int ipi1_phy_fatal_mask;
+    unsigned int ipi2_phy_fatal_mask;
+    unsigned int ipi3_phy_fatal_mask;
+    unsigned int pkt_fatal;
+    unsigned int frame_fatal;
+    unsigned int phy;
+    unsigned int line;
+    unsigned int ipi;
+    unsigned int ipi2;
+    unsigned int ipi3;
+    unsigned int bndry_frame_fatal;
+    unsigned int seq_frame_fatal;
+    unsigned int crc_frame_fatal;
+    unsigned int pld_crc_fatal;
+    unsigned int data_id;
+    unsigned int ecc_corrected;
+};
+
 #endif /* _BM_CSI_IOCTL_H_*/

+ 38 - 16
driver/csi/dw-csi-plat.c

@@ -114,13 +114,13 @@ dw_mipi_csi_try_format(uint32_t mbus_code)
 struct mipi_fmt *
 dw_mipi_csi_get_format(struct dw_csi *dev)
 {
-	dev_info(dev->dev,
+	dev_vdbg(dev->dev,
 		"%s got v4l2_mbus_pixelcode. 0x%x\n", __func__,
 		dev->fmt->mbus_code);
-	dev_info(dev->dev,
+	dev_vdbg(dev->dev,
 		"%s got width. 0x%x\n", __func__,
 		dev->fmt->width);
-	dev_info(dev->dev,
+	dev_vdbg(dev->dev,
 		"%s got height. 0x%x\n", __func__,
 		dev->fmt->height);
     return dev->fmt;
@@ -135,13 +135,13 @@ dw_mipi_csi_set_fmt(struct platform_device *pdev,
 
 	struct mipi_fmt *dev_fmt = NULL;
 	int i;
-	dev_info(dev->dev,
+	dev_vdbg(dev->dev,
 		"%s got mbus_pixelcode. 0x%x\n", __func__,
 		mbus_code);
 
 	dev_fmt = dw_mipi_csi_try_format(mbus_code);
 
-	dev_info(dev->dev,
+	dev_vdbg(dev->dev,
 		"%s got v4l2_mbus_pixelcode. 0x%x\n", __func__,
 		dev_fmt->mbus_code);
 	if (!dev_fmt)
@@ -153,7 +153,7 @@ dw_mipi_csi_set_fmt(struct platform_device *pdev,
         dev->fmt->height = height;
 		dw_mipi_csi_set_ipi_fmt(dev);
 	}
-	dev_info(dev->dev, "Width: %d, Height: %d of Demo\n", width, height);
+	dev_vdbg(dev->dev, "Width: %d, Height: %d of Demo\n", width, height);
 	if (width > 0 && height > 0) {
         dw_mipi_csi_fill_timings(dev, width, height);
 /*
@@ -170,7 +170,7 @@ dw_mipi_csi_set_fmt(struct platform_device *pdev,
 			 width,
 			 dev->hw.vactive,
 			 height);
-		dev_info(dev->dev,
+		dev_vdbg(dev->dev,
 			 "(core/demosaic) : width=%d/%d, height=%d/%d\n",
 			 dev->hw.htotal - (dev->hw.hbp
 					   + dev->hw.hsd
@@ -184,9 +184,9 @@ dw_mipi_csi_set_fmt(struct platform_device *pdev,
 		       __func__, width);
 		dev_vdbg(dev->dev, "%s unacceptable values 0x%x.\n",
 		       __func__, height);
-		dev_info(dev->dev, "%s unacceptable values 0x%x.\n",
+		dev_vdbg(dev->dev, "%s unacceptable values 0x%x.\n",
 		       __func__, width);
-		dev_info(dev->dev, "%s unacceptable values 0x%x.\n",
+		dev_vdbg(dev->dev, "%s unacceptable values 0x%x.\n",
 		       __func__, height);
 		return -EINVAL;
 	}
@@ -195,7 +195,7 @@ dw_mipi_csi_set_fmt(struct platform_device *pdev,
 		if (csi_dt[i].hex == dev->ipi_dt) {
 			dev_vdbg(dev->dev, "Using data type %s\n",
 				 csi_dt[i].name);
-			dev_info(dev->dev, "Using data type %s\n",
+			dev_vdbg(dev->dev, "Using data type %s\n",
 				 csi_dt[i].name);
 		}
 	return 0;
@@ -221,14 +221,14 @@ dw_mipi_csi_get_fmt(struct platform_device *pdev,
 
 int dw_mipi_csi_s_power(struct dw_csi *dev, int on)
 {
-	dev_info(dev->dev, "%s: on=%d\n", __func__, on);
+	dev_vdbg(dev->dev, "%s: on=%d\n", __func__, on);
 
 	if (on) {
         dw_dphy_power_on(dev->phy);
 		dw_mipi_csi_hw_stdby(dev);
 		dw_mipi_csi_start(dev);
 	} else {
-		phy_power_off(dev->phy);
+        dw_dphy_power_off(dev->phy);
 		dw_mipi_csi_mask_irq_power_off(dev);
 		/* reset data type */
 		dev->ipi_dt = 0x0;
@@ -272,11 +272,32 @@ static int dw_mipi_csi_init_cfg(struct v4l2_subdev *sd,
 }
 #endif
 
+unsigned csi_poll(struct file *file, struct poll_table_struct *wait)
+{
+    unsigned int mask = 0;
+	struct bm_csi_drvdata *drvdata = file->private_data;
+	struct dw_csi *csi_dev = &drvdata->csi_dev;
+    struct dw_csi_err_mask *err_mask = &csi_dev->error_mask;
+
+    poll_wait(file, &drvdata->irq_wait, wait);
+
+    if (csi_dev->has_error) {
+        csi_dev->has_error = 0;
+        mask |= POLLIN | POLLRDNORM;
+    }
+
+    return mask;
+}
+
+
 static irqreturn_t dw_mipi_csi_irq1(int irq, void *dev_id)
 {
-	struct dw_csi *csi_dev = dev_id;
+
+	struct bm_csi_drvdata *drvdata = dev_id;
+	struct dw_csi *csi_dev = &drvdata->csi_dev;
 
 	dw_mipi_csi_irq_handler(csi_dev);
+    wake_up_interruptible(&drvdata->irq_wait);
 
 	return IRQ_HANDLED;
 }
@@ -369,7 +390,7 @@ int dw_csi_probe(struct platform_device *pdev)
 
 	ret = devm_request_irq(dev, csi->ctrl_irq_number,
 			       dw_mipi_csi_irq1, IRQF_SHARED,
-			       dev_name(dev), csi);
+			       dev_name(dev), drvdata);
 	if (ret) {
 		dev_err(dev, "irq csi %d failed\n", pdata->id);
 		goto end;
@@ -387,6 +408,7 @@ int dw_csi_probe(struct platform_device *pdev)
 	csi->hw.ipi_mode = CAMERA_TIMING;
     csi->hw.ipi_color_mode = COLOR16;
 
+    init_waitqueue_head(&drvdata->irq_wait);
     //csi soc reset
     dw_csi_soc_reset();
 	dw_csi_create_capabilities_sysfs(pdev);
@@ -394,7 +416,7 @@ int dw_csi_probe(struct platform_device *pdev)
 	dw_mipi_csi_specific_mappings(csi);
 	dw_mipi_csi_mask_irq_power_off(csi);
 
-	dev_info(dev, "DW MIPI CSI-2 Host registered successfully HW v%u.%u\n",
+	dev_vdbg(dev, "DW MIPI CSI-2 Host registered successfully HW v%u.%u\n",
 		 csi->hw_version_major, csi->hw_version_minor);
 
 	ret = phy_reset(csi->phy);
@@ -421,7 +443,7 @@ int dw_csi_remove(struct platform_device *pdev)
 	//struct dw_csi *mipi_csi = &drvdata->csi_dev;
     //csi soc reset
     dw_csi_soc_reset();
-    dev_info(&pdev->dev, "DW MIPI CSI-2 Host module removed\n");
+    dev_vdbg(&pdev->dev, "DW MIPI CSI-2 Host module removed\n");
 
 	return 0;
 }

+ 24 - 24
driver/csi/dw-csi-sysfs.c

@@ -46,7 +46,7 @@ static ssize_t n_lanes_store(struct device *dev, struct device_attribute *attr,
 		return count;
 	}
 
-	dev_info(dev, "Lanes %lu\n", lanes);
+	dev_vdbg(dev, "Lanes %lu\n", lanes);
 	csi_dev->hw.num_lanes = lanes;
 
 	return count;
@@ -81,7 +81,7 @@ static ssize_t width_store(struct device *dev, struct device_attribute *attr,
 	if (ret < 0)
 		return ret;
 
-	dev_info(dev, "width %lu\n", width);
+	dev_vdbg(dev, "width %lu\n", width);
 	csi_dev->hw.htotal = width;
 
 	return count;
@@ -116,7 +116,7 @@ static ssize_t height_store(struct device *dev, struct device_attribute *attr,
 	if (ret < 0)
 		return ret;
 
-	dev_info(dev, "hight %lu\n", height);
+	dev_vdbg(dev, "hight %lu\n", height);
 	csi_dev->hw.vactive = height;
 
 	return count;
@@ -178,7 +178,7 @@ static ssize_t data_type_store(struct device *dev,
 		return count;
 	}
 
-	dev_info(dev, "Data type 0x%lx\n", dt);
+	dev_vdbg(dev, "Data type 0x%lx\n", dt);
 	csi_dev->ipi_dt = dt;
 
     dw_mipi_csi_set_ipi_fmt(csi_dev);
@@ -222,7 +222,7 @@ static ssize_t hsa_store(struct device *dev,
 		return count;
 	}
 
-	dev_info(dev, "HSA time 0x%lx\n", hsa);
+	dev_vdbg(dev, "HSA time 0x%lx\n", hsa);
 	csi_dev->hw.hsa = hsa;
 
 	return count;
@@ -263,7 +263,7 @@ static ssize_t hbp_store(struct device *dev,
 		return count;
 	}
 
-	dev_info(dev, "HBP time 0x%lx\n", hbp);
+	dev_vdbg(dev, "HBP time 0x%lx\n", hbp);
 	csi_dev->hw.hbp = hbp;
 
 	return count;
@@ -304,7 +304,7 @@ static ssize_t hsd_store(struct device *dev,
 		return count;
 	}
 
-	dev_info(dev, "HSD time 0x%lx\n", hsd);
+	dev_vdbg(dev, "HSD time 0x%lx\n", hsd);
 	csi_dev->hw.hsd = hsd;
 
 	return count;
@@ -345,7 +345,7 @@ static ssize_t ipi2_hsa_store(struct device *dev,
 		return count;
 	}
 
-	dev_info(dev, "HSA time 0x%lx\n", hsa);
+	dev_vdbg(dev, "HSA time 0x%lx\n", hsa);
 	csi_dev->hw.ipi2_hsa = hsa;
 
 	return count;
@@ -386,7 +386,7 @@ static ssize_t ipi2_hbp_store(struct device *dev,
 		return count;
 	}
 
-	dev_info(dev, "HBP time 0x%lx\n", hbp);
+	dev_vdbg(dev, "HBP time 0x%lx\n", hbp);
 	csi_dev->hw.ipi2_hbp = hbp;
 
 	return count;
@@ -427,7 +427,7 @@ static ssize_t ipi2_hsd_store(struct device *dev,
 		return count;
 	}
 
-	dev_info(dev, "HSD time 0x%lx\n", hsd);
+	dev_vdbg(dev, "HSD time 0x%lx\n", hsd);
 	csi_dev->hw.ipi2_hsd = hsd;
 
 	return count;
@@ -468,7 +468,7 @@ static ssize_t ipi3_hsa_store(struct device *dev,
 		return count;
 	}
 
-	dev_info(dev, "HSA time 0x%lx\n", hsa);
+	dev_vdbg(dev, "HSA time 0x%lx\n", hsa);
 	csi_dev->hw.ipi3_hsa = hsa;
 
 	return count;
@@ -509,7 +509,7 @@ static ssize_t ipi3_hbp_store(struct device *dev,
 		return count;
 	}
 
-	dev_info(dev, "HBP time 0x%lx\n", hbp);
+	dev_vdbg(dev, "HBP time 0x%lx\n", hbp);
 	csi_dev->hw.ipi3_hbp = hbp;
 
 	return count;
@@ -550,7 +550,7 @@ static ssize_t ipi3_hsd_store(struct device *dev,
 		return count;
 	}
 
-	dev_info(dev, "HSD time 0x%lx\n", hsd);
+	dev_vdbg(dev, "HSD time 0x%lx\n", hsd);
 	csi_dev->hw.ipi3_hsd = hsd;
 
 	return count;
@@ -591,7 +591,7 @@ static ssize_t vsa_store(struct device *dev,
 		return count;
 	}
 
-	dev_info(dev, "VSA period 0x%lx\n", vsa);
+	dev_vdbg(dev, "VSA period 0x%lx\n", vsa);
 	csi_dev->hw.vsa = vsa;
 
 	return count;
@@ -632,7 +632,7 @@ static ssize_t vbp_store(struct device *dev,
 		return count;
 	}
 
-	dev_info(dev, "VBP period 0x%lx\n", vbp);
+	dev_vdbg(dev, "VBP period 0x%lx\n", vbp);
 	csi_dev->hw.vbp = vbp;
 
 	return count;
@@ -673,7 +673,7 @@ static ssize_t vfp_store(struct device *dev,
 		return count;
 	}
 
-	dev_info(dev, "VFP period 0x%lx\n", vfp);
+	dev_vdbg(dev, "VFP period 0x%lx\n", vfp);
 	csi_dev->hw.vfp = vfp;
 
 	return count;
@@ -709,7 +709,7 @@ static ssize_t ipi_enable_mask_store(struct device *dev,
 	if (ret < 0)
 		return ret;
 
-	dev_info(dev, "enable_mask 0x%lx\n", enable_mask);
+	dev_vdbg(dev, "enable_mask 0x%lx\n", enable_mask);
 
     if (enable_mask & 1) {
 	    csi_dev->hw.ipi1_en = true;
@@ -783,7 +783,7 @@ static ssize_t virtual_channel_store(struct device *dev,
 		return count;
 	}
 
-	dev_info(dev, "Virtual Channel %lu\n", virtual_ch);
+	dev_vdbg(dev, "Virtual Channel %lu\n", virtual_ch);
 	csi_dev->hw.virtual_ch = virtual_ch;
 
 	return count;
@@ -824,7 +824,7 @@ static ssize_t ipi2_virtual_channel_store(struct device *dev,
 		return count;
 	}
 
-	dev_info(dev, "Virtual Channel %lu\n", virtual_ch);
+	dev_vdbg(dev, "Virtual Channel %lu\n", virtual_ch);
 	csi_dev->hw.ipi2_virtual_ch = virtual_ch;
 
 	return count;
@@ -865,7 +865,7 @@ static ssize_t ipi3_virtual_channel_store(struct device *dev,
 		return count;
 	}
 
-	dev_info(dev, "Virtual Channel %lu\n", virtual_ch);
+	dev_vdbg(dev, "Virtual Channel %lu\n", virtual_ch);
 	csi_dev->hw.ipi3_virtual_ch = virtual_ch;
 
 	return count;
@@ -908,7 +908,7 @@ static ssize_t ipi_color_mode_store(struct device *dev,
 		return count;
 	}
 
-	dev_info(dev, "IPI Color mode %lu\n", ipi_color_mode);
+	dev_vdbg(dev, "IPI Color mode %lu\n", ipi_color_mode);
 	csi_dev->hw.ipi_color_mode = ipi_color_mode;
 
 	return count;
@@ -951,7 +951,7 @@ static ssize_t ipi_auto_flush_store(struct device *dev,
 		return count;
 	}
 
-	dev_info(dev, "IPI Auto Flush %lu\n", ipi_auto_flush);
+	dev_vdbg(dev, "IPI Auto Flush %lu\n", ipi_auto_flush);
 	csi_dev->hw.ipi_auto_flush = ipi_auto_flush;
 
 	return count;
@@ -994,7 +994,7 @@ static ssize_t ipi_timings_mode_store(struct device *dev,
 		return count;
 	}
 
-	dev_info(dev, "IPI Color mode %lu\n", ipi_mode);
+	dev_vdbg(dev, "IPI Color mode %lu\n", ipi_mode);
 	csi_dev->hw.ipi_mode = ipi_mode;
 
 	return count;
@@ -1038,7 +1038,7 @@ static ssize_t output_type_store(struct device *dev,
 		return count;
 	}
 
-	dev_info(dev, "IPI Color mode %lu\n", output);
+	dev_vdbg(dev, "IPI Color mode %lu\n", output);
 	csi_dev->hw.output = output;
 
 	return count;

+ 5 - 3
driver/csi/dw-dphy-plat.c

@@ -92,8 +92,10 @@ int dw_dphy_rx_probe(struct platform_device *pdev, unsigned int dphyglueiftester
 		return -ENOMEM;
 
 	drvdata = platform_get_drvdata(pdev);
-	dphy->base_address = drvdata->base + REG_DPHY_OFFSET;
     drvdata->dphy= dphy;
+
+    dphy->phy_id = drvdata->phy_id;
+	dphy->base_address = drvdata->base + REG_DPHY_OFFSET;
 	dphy->dphyglueiftester = dphyglueiftester;
 	dphy->sysreg_mipi_csi_ctrl = sysreg_mipi_csi_ctrl;
 
@@ -123,7 +125,7 @@ int dw_dphy_rx_probe(struct platform_device *pdev, unsigned int dphyglueiftester
 	dphy->lp_time = 1000; /* 1000 ns */
 	dphy->lanes_config = dw_dphy_setup_config(dphy);
 
-	dev_info(&dphy->phy->dev, "Probing dphy finished\n");
+	dev_vdbg(&dphy->phy->dev, "Probing dphy finished\n");
 
 	dw_dphy_create_capabilities_sysfs(pdev);
 
@@ -135,7 +137,7 @@ int dw_dphy_rx_remove(struct platform_device *pdev)
     struct bm_csi_drvdata *drvdata = platform_get_drvdata(pdev);
     struct dw_dphy_rx *dphy = drvdata->dphy;
 
-	dev_info(&dphy->phy->dev, "phy removed\n");
+	dev_vdbg(&dphy->phy->dev, "phy removed\n");
 
 	phy_reset(dphy->phy);
 	phy_unregister(&pdev->dev);

+ 16 - 2
driver/csi/dw-dphy-rx.c

@@ -439,6 +439,14 @@ static int dw_dphy_gen3_12bit_configure(struct dw_dphy_rx *dphy, int abphy_flag)
 
 	dw_dphy_write(dphy, R_CSI2_DPHY_RSTZ, 0);
 	dw_dphy_write(dphy, R_CSI2_DPHY_SHUTDOWNZ, 0);
+
+
+    if (dphy->phy_id == MIPI_A_PHY) {
+        reg_val = dw_dphy_te_read(dphy, RX_RX_CLKLANE_LANE_6);
+        reg_val &= ~(3 << 4);
+	    dw_dphy_te_write(dphy, RX_RX_CLKLANE_LANE_6, reg_val);
+    }
+
 	dw_dphy_write_msk(dphy, R_CSI2_DPHY_TST_CTRL0, 1, PHY_TESTCLR, 1);
     udelay(1);
 	dw_dphy_write_msk(dphy, R_CSI2_DPHY_TST_CTRL0, 0, PHY_TESTCLR, 1);
@@ -546,6 +554,12 @@ static int dw_dphy_gen3_12bit_configure(struct dw_dphy_rx *dphy, int abphy_flag)
 		dw_dphy_te_write(dphy, RX_SYS_7, reg_val);
     }
 
+    if (dphy->phy_id == MIPI_A_PHY) {
+        reg_val = dw_dphy_te_read(dphy, RX_RX_CLKLANE_LANE_6);
+        reg_val |= (1 << 5);
+	    dw_dphy_te_write(dphy, RX_RX_CLKLANE_LANE_6, reg_val);
+    }
+
 	dw_dphy_write(dphy, R_CSI2_DPHY_RSTZ, 1);
     udelay(1);
 	dw_dphy_write(dphy, R_CSI2_DPHY_SHUTDOWNZ, 1);
@@ -926,7 +940,7 @@ static int dw_dphy_set_phy_state(struct dw_dphy_rx *dphy, u32 on)
 
 	if (on) {
 		dw_dphy_configure(dphy);
-		dev_info(&dphy->phy->dev,
+		dev_vdbg(&dphy->phy->dev,
 			 "HS Code: 0X%x\n", dw_dphy_te_read(dphy, hs_freq));
 	} else {
 		dw_dphy_write(dphy, R_CSI2_DPHY_SHUTDOWNZ, 0);
@@ -940,7 +954,7 @@ int dw_dphy_power_on(struct phy *phy)
 {
 	struct dw_dphy_rx *dphy = phy_get_drvdata(phy);
 
-	dev_info(&dphy->phy->dev, "DPHY Power ON\n");
+	dev_vdbg(&dphy->phy->dev, "DPHY Power ON\n");
     bm_info("enter %s\n", __func__);
 
     dphy->phy_type = 1;

+ 7 - 0
driver/csi/dw-dphy-rx.h

@@ -145,6 +145,12 @@ enum glueiftester {
 };
 //#endif
 
+typedef enum {
+    MIPI_4LANE_PHY,
+    MIPI_A_PHY,
+    MIPI_B_PHY,
+} phy_id_e;
+
 /**
  * struct phy		specifies associated phy component
  * struct cfg		to pass mipi dphy specific configurations
@@ -167,6 +173,7 @@ struct dw_dphy_rx {
 	u32 lanes_config;
 	u32 dphy_freq;  //MBPS
 	u32 phy_type;
+    phy_id_e phy_id;    //csi2_phy, a phy, b phy
 	u32 dphy_gen;
 	u32 dphy_te_len;
 	u32 max_lanes;

+ 2 - 2
driver/csi/dw-dphy-sysfs.c

@@ -44,11 +44,11 @@ static ssize_t dphy_freq_store(struct device *dev,
 		return ret;
 
 	if (freq > 2500) {
-		dev_info(dev, "Freq must be under 2500 Mhz\n");
+		dev_vdbg(dev, "Freq must be under 2500 Mhz\n");
 		return count;
 	}
 	if (freq < 80) {
-		dev_info(dev, "Freq must be over 80 Mhz\n");
+		dev_vdbg(dev, "Freq must be over 80 Mhz\n");
 		return count;
 	}
 

+ 61 - 24
driver/csi/dw-mipi-csi.c

@@ -75,7 +75,7 @@ struct interrupt_type csi_int = {
 };
 
 #define dw_print(VAR) \
-	dev_info(csi_dev->dev, "%s: 0x%x: %X\n", "##VAR##",\
+	dev_vdbg(csi_dev->dev, "%s: 0x%x: %X\n", "##VAR##",\
 	VAR, dw_mipi_csi_read(csi_dev, VAR))
 
 void dw_mipi_csi_write_part(struct dw_csi *dev, u32 address, u32 data,
@@ -151,11 +151,15 @@ int dw_mipi_csi_hw_stdby(struct dw_csi *csi_dev)
 		dw_mipi_csi_write(csi_dev, reg.MASK_INT_PHY_FATAL,
 				  GENMASK(8, 0));
 
-		dw_mipi_csi_write(csi_dev, reg.IPI2_MASK_INT_PHY_FATAL,
-				  GENMASK(8, 0));
+        if (csi_dev->hw.ipi2_en) {
+		    dw_mipi_csi_write(csi_dev, reg.IPI2_MASK_INT_PHY_FATAL,
+				    GENMASK(8, 0));
+        }
 
-		dw_mipi_csi_write(csi_dev, reg.IPI3_MASK_INT_PHY_FATAL,
-				  GENMASK(8, 0));
+        if (csi_dev->hw.ipi3_en) {
+		    dw_mipi_csi_write(csi_dev, reg.IPI3_MASK_INT_PHY_FATAL,
+				    GENMASK(8, 0));
+        }
 
 		dw_mipi_csi_write(csi_dev, reg.MASK_INT_PKT_FATAL,
 				  GENMASK(1, 0));
@@ -300,7 +304,7 @@ void dw_mipi_csi_set_ipi_fmt(struct dw_csi *csi_dev)
 		dw_mipi_csi_write(csi_dev, reg.IPI2_DATA_TYPE, csi_dev->ipi_dt);
 		dw_mipi_csi_write(csi_dev, reg.IPI3_DATA_TYPE, csi_dev->ipi_dt);
 	}
-	dev_info(dev, "Selected IPI Data Type 0x%X\n", csi_dev->ipi_dt);
+	dev_vdbg(dev, "Selected IPI Data Type 0x%X\n", csi_dev->ipi_dt);
 }
 
 void dw_mipi_csi_fill_timings(struct dw_csi *dev, uint32_t width, uint32_t height)
@@ -349,7 +353,7 @@ void dw_mipi_csi_start(struct dw_csi *csi_dev)
 	struct device *dev = csi_dev->dev;
 
 	dw_mipi_csi_write(csi_dev, reg.N_LANES, (csi_dev->hw.num_lanes - 1));
-	dev_info(dev, "number of lanes: %d\n", csi_dev->hw.num_lanes);
+	dev_vdbg(dev, "number of lanes: %d\n", csi_dev->hw.num_lanes);
 
 	/* IPI Related Configuration */
 	if (csi_dev->hw.output == IPI_OUT || csi_dev->hw.output == BOTH_OUT) {
@@ -545,28 +549,35 @@ int dw_mipi_csi_irq_handler(struct dw_csi *csi_dev)
 	struct device *dev = csi_dev->dev;
 	u32 global_int_status, i_sts;
 	unsigned long flags;
+    struct dw_csi_err_mask *err_mask = &csi_dev->error_mask;
 
+    csi_dev->has_error = 1;
 	spin_lock_irqsave(&csi_dev->slock, flags);
 	global_int_status = dw_mipi_csi_read(csi_dev, reg.INTERRUPT);
+    err_mask->src = global_int_status;
 
 	if (global_int_status & csi_int.PHY_FATAL) {
 		i_sts = dw_mipi_csi_read(csi_dev, reg.INT_PHY_FATAL);
-		dev_err_ratelimited(dev, "int %08X: PHY FATAL: %08X\n",
+        err_mask->ipi1_phy_fatal_mask = i_sts;
+		pr_err( "int %08X: PHY FATAL: %08X\n",
 				    reg.INT_PHY_FATAL, i_sts);
 
         i_sts = dw_mipi_csi_read(csi_dev, reg.IPI2_INT_PHY_FATAL);
-		dev_err_ratelimited(dev, "int %08X: IPI2 PHY FATAL: %08X\n",
+        err_mask->ipi2_phy_fatal_mask = i_sts;
+		pr_err( "int %08X: IPI2 PHY FATAL: %08X\n",
 				    reg.IPI2_INT_PHY_FATAL, i_sts);
 
         i_sts = dw_mipi_csi_read(csi_dev, reg.IPI3_INT_PHY_FATAL);
-		dev_err_ratelimited(dev, "int %08X: IPI2 PHY FATAL: %08X\n",
+        err_mask->ipi3_phy_fatal_mask = i_sts;
+		pr_err( "int %08X: IPI3 PHY FATAL: %08X\n",
 				    reg.IPI3_INT_PHY_FATAL, i_sts);
 
 	}
 
 	if (global_int_status & csi_int.PKT_FATAL) {
 		i_sts = dw_mipi_csi_read(csi_dev, reg.INT_PKT_FATAL);
-		dev_err_ratelimited(dev, "int %08X: PKT FATAL: %08X\n",
+        err_mask->pkt_fatal = i_sts;
+		pr_err( "int %08X: PKT FATAL: %08X\n",
 				    reg.INT_PKT_FATAL, i_sts);
 	}
 
@@ -574,13 +585,15 @@ int dw_mipi_csi_irq_handler(struct dw_csi *csi_dev)
 	    csi_dev->hw_version_major == 1 &&
 	    csi_dev->hw_version_minor == 30) {
 		i_sts = dw_mipi_csi_read(csi_dev, reg.INT_FRAME_FATAL);
-		dev_err_ratelimited(dev, "int %08X: FRAME FATAL: %08X\n",
+        err_mask->frame_fatal = i_sts;
+		pr_err( "int %08X: FRAME FATAL: %08X\n",
 				    reg.INT_FRAME_FATAL, i_sts);
 	}
 
 	if (global_int_status & csi_int.PHY) {
 		i_sts = dw_mipi_csi_read(csi_dev, reg.INT_PHY);
-		dev_err_ratelimited(dev, "int %08X: PHY: %08X\n",
+        err_mask->phy = i_sts;
+		pr_err( "int %08X: PHY: %08X\n",
 				    reg.INT_PHY, i_sts);
 	}
 
@@ -588,59 +601,81 @@ int dw_mipi_csi_irq_handler(struct dw_csi *csi_dev)
 	    csi_dev->hw_version_major == 1 &&
 	    csi_dev->hw_version_minor <= 30) {
 		i_sts = dw_mipi_csi_read(csi_dev, reg.INT_PKT);
-		dev_err_ratelimited(dev, "int %08X: PKT: %08X\n",
+		pr_err( "int %08X: PKT: %08X\n",
 				    reg.INT_PKT, i_sts);
 	}
 
 	if (global_int_status & csi_int.LINE) {
 		i_sts = dw_mipi_csi_read(csi_dev, reg.INT_LINE);
-		dev_err_ratelimited(dev, "int %08X: LINE: %08X\n",
+        err_mask->line = i_sts;
+		pr_err( "int %08X: LINE: %08X\n",
 				    reg.INT_LINE, i_sts);
 	}
 
 	if (global_int_status & csi_int.IPI) {
 		i_sts = dw_mipi_csi_read(csi_dev, reg.INT_IPI);
-		dev_err_ratelimited(dev, "int %08X: IPI: %08X\n",
+        err_mask->ipi = i_sts;
+		pr_err( "int %08X: IPI: %08X\n",
+				    reg.INT_IPI, i_sts);
+	}
+
+    if (global_int_status & csi_int.IPI2) {
+		i_sts = dw_mipi_csi_read(csi_dev, reg.IPI2_INT_PHY_FATAL);
+        err_mask->ipi2 = i_sts;
+		pr_err( "int %08X: IPI2: %08X\n",
+				    reg.IPI2_INT_PHY_FATAL, i_sts);
+	}
+
+    if (global_int_status & csi_int.IPI3) {
+		i_sts = dw_mipi_csi_read(csi_dev, reg.IPI2_INT_PHY_FATAL);
+        err_mask->ipi3 = i_sts;
+		pr_err( "int %08X: IPI3: %08X\n",
 				    reg.INT_IPI, i_sts);
 	}
 
 	if (global_int_status & csi_int.BNDRY_FRAME_FATAL) {
 		i_sts = dw_mipi_csi_read(csi_dev, reg.ST_BNDRY_FRAME_FATAL);
-		dev_err_ratelimited(dev,
+        err_mask->bndry_frame_fatal = i_sts;
+		pr_err(
 				    "int %08X: ST_BNDRY_FRAME_FATAL: %08X\n",
 				    reg.ST_BNDRY_FRAME_FATAL, i_sts);
 	}
 
 	if (global_int_status & csi_int.SEQ_FRAME_FATAL) {
 		i_sts = dw_mipi_csi_read(csi_dev, reg.ST_SEQ_FRAME_FATAL);
-		dev_err_ratelimited(dev,
+        err_mask->seq_frame_fatal = i_sts;
+		pr_err(
 				    "int %08X: ST_SEQ_FRAME_FATAL: %08X\n",
 				    reg.ST_SEQ_FRAME_FATAL, i_sts);
 	}
 
 	if (global_int_status & csi_int.CRC_FRAME_FATAL) {
 		i_sts = dw_mipi_csi_read(csi_dev, reg.ST_CRC_FRAME_FATAL);
-		dev_err_ratelimited(dev,
+        err_mask->crc_frame_fatal = i_sts;
+		pr_err(
 				    "int %08X: ST_CRC_FRAME_FATAL: %08X\n",
 				    reg.ST_CRC_FRAME_FATAL, i_sts);
 	}
 
 	if (global_int_status & csi_int.PLD_CRC_FATAL) {
 		i_sts = dw_mipi_csi_read(csi_dev, reg.ST_PLD_CRC_FATAL);
-		dev_err_ratelimited(dev,
+        err_mask->pld_crc_fatal = i_sts;
+		pr_err(
 				    "int %08X: ST_PLD_CRC_FATAL: %08X\n",
 				    reg.ST_PLD_CRC_FATAL, i_sts);
 	}
 
 	if (global_int_status & csi_int.DATA_ID) {
 		i_sts = dw_mipi_csi_read(csi_dev, reg.ST_DATA_ID);
-		dev_err_ratelimited(dev, "int %08X: ST_DATA_ID: %08X\n",
+        err_mask->data_id = i_sts;
+		pr_err( "int %08X: ST_DATA_ID: %08X\n",
 				    reg.ST_DATA_ID, i_sts);
 	}
 
 	if (global_int_status & csi_int.ECC_CORRECTED) {
 		i_sts = dw_mipi_csi_read(csi_dev, reg.ST_ECC_CORRECT);
-		dev_err_ratelimited(dev, "int %08X: ST_ECC_CORRECT: %08X\n",
+        err_mask->ecc_corrected = i_sts;
+		pr_err( "int %08X: ST_ECC_CORRECT: %08X\n",
 				    reg.ST_ECC_CORRECT, i_sts);
 	}
 
@@ -713,6 +748,8 @@ int dw_mipi_csi_specific_mappings(struct dw_csi *csi_dev)
 			/* interrupts map were changed */
 			csi_int.LINE = BIT(17);
 			csi_int.IPI = BIT(18);
+			csi_int.IPI2 = BIT(19);
+			csi_int.IPI3 = BIT(20);
 			csi_int.BNDRY_FRAME_FATAL = BIT(2);
 			csi_int.SEQ_FRAME_FATAL	= BIT(3);
 			csi_int.CRC_FRAME_FATAL = BIT(4);
@@ -721,10 +758,10 @@ int dw_mipi_csi_specific_mappings(struct dw_csi *csi_dev)
 			csi_int.ECC_CORRECTED = BIT(7);
 
 		} else {
-			dev_info(dev, "Version minor not supported.");
+			dev_vdbg(dev, "Version minor not supported.");
 		}
 	} else {
-		dev_info(dev, "Version major not supported.");
+		dev_vdbg(dev, "Version major not supported.");
 	}
 	return 0;
 }

+ 6 - 0
driver/csi/dw-mipi-csi.h

@@ -25,6 +25,7 @@
 #include <linux/videodev2.h>
 #include <linux/wait.h>
 #include <dw-mipi-csi-pltfrm.h>
+#include <bm_csi_ioctl.h>
 
 /* Advanced features */
 #define IPI_DT_OVERWRITE BIT(0)
@@ -144,6 +145,8 @@ struct interrupt_type {
 	u32 PKT;
 	u32 LINE;
 	u32 IPI;
+	u32 IPI2;
+	u32 IPI3;
 	u32 BNDRY_FRAME_FATAL;
 	u32 SEQ_FRAME_FATAL;
 	u32 CRC_FRAME_FATAL;
@@ -258,6 +261,7 @@ struct csi_data {
 };
 
 /* Structure to embed device driver information */
+
 struct dw_csi {
 	//struct v4l2_subdev sd;
 	//struct video_device vdev;
@@ -281,6 +285,8 @@ struct dw_csi {
 	u8 index;
 	u8 hw_version_major;
 	u16 hw_version_minor;
+    int has_error;
+    struct dw_csi_err_mask error_mask;
 };
 
 void dw_mipi_csi_reset(struct dw_csi *csi_dev);