20230414将CV1826平台的硬件I2C2配置成为模拟I2C6

20230414将CV1826平台的硬件I2C2配置成为模拟I2C6
2023/4/14 15:58


在公司的点读笔项目S6中,TP使用了I2C2(GPIOB13/B14),摄像头也占用了I2C2(GPIOC15/14)。但是linux的内核中只能有一个I2C总线!
由于摄像头对I2C2的使用率偏低:打开之后就不用管了!
因此公司决定让TP使用硬件I2C2,摄像头使用GPIO口模拟的I2C6。


1、【已经默认打开了】
Z:\cv1823\smartpen\build\boards\cv1826_wevb_0005a\linux\cvitek_cv1826_wevb_0005a_defconfig
#
# I2C system bus drivers (mostly embedded / system-on-chip)
#
# CONFIG_I2C_CBUS_GPIO is not set
CONFIG_I2C_DESIGNWARE_CORE=y
CONFIG_I2C_DESIGNWARE_PLATFORM=y
# CONFIG_I2C_DESIGNWARE_SLAVE is not set
# CONFIG_I2C_EMEV2 is not set
CONFIG_I2C_GPIO=y
# CONFIG_I2C_GPIO_FAULT_INJECTOR is not set
# CONFIG_I2C_NOMADIK is not set
# CONFIG_I2C_OCORES is not set
# CONFIG_I2C_PCA_PLATFORM is not set
# CONFIG_I2C_RK3X is not set
# CONFIG_I2C_SIMTEC is not set
# CONFIG_I2C_XILINX is not set


2、
Z:\cv1823\smartpen\build\boards\cv1826_wevb_0005a\u-boot\cvi_board_init.c
    // set tp, i2c2 and reset irq
    //PINMUX_CONFIG(VIVO_D8, IIC2_SCL);
    //PINMUX_CONFIG(VIVO_D7, IIC2_SDA);

    PINMUX_CONFIG(PAD_MIPI_TXP1, IIC2_SCL);
    PINMUX_CONFIG(PAD_MIPI_TXM1, IIC2_SDA);
修改为:(在uboot阶段将GPIOC15/14配置为GPIO口)
    // set tp, i2c2 and reset irq
    //PINMUX_CONFIG(VIVO_D8, IIC2_SCL);
    //PINMUX_CONFIG(VIVO_D7, IIC2_SDA);
    //PINMUX_CONFIG(PAD_MIPI_TXP1, IIC2_SCL);
    //PINMUX_CONFIG(PAD_MIPI_TXM1, IIC2_SDA);
    
    //PINMUX_CONFIG(SD0_CLK, XGPIOA_7);
    PINMUX_CONFIG(PAD_MIPI_TXP1, XGPIOC_15);
    PINMUX_CONFIG(PAD_MIPI_TXM1, XGPIOC_14);

    printf("-------------------1----------------------\n");


    //sc7a20
    PINMUX_CONFIG(IIC2_SDA, PWR_GPIO_13);

修改为:【可选】
    //sc7a20
    //PINMUX_CONFIG(IIC2_SDA, PWR_GPIO_13);


    mmio_write_32(0x03001C84, 0x08);  // set MIPI_TXP0 Driving Strength to 0
    mmio_write_32(0x03001C80, 0x08);  // set MIPI_TXM0 Driving Strength to 0
    mmio_write_32(0x03001C7c, 0x08);  // set MIPI_TXP1 Driving Strength to 0
    mmio_write_32(0x03001C78, 0x08);  // set MIPI_TXM1 Driving Strength to 0

    mmio_write_32(0x03001C74, 0x08);  // set MIPI_TXP2 Driving Strength to 0
    mmio_write_32(0x03001C70, 0x08);  // set MIPI_TXM2 Driving Strength to 0
修改为:
    mmio_write_32(0x03001C84, 0x08);  // set MIPI_TXP0 Driving Strength to 0
    mmio_write_32(0x03001C80, 0x08);  // set MIPI_TXM0 Driving Strength to 0
    //mmio_write_32(0x03001C7c, 0x08);  // set MIPI_TXP1 Driving Strength to 0
    //mmio_write_32(0x03001C78, 0x08);  // set MIPI_TXM1 Driving Strength to 0

    mmio_write_32(0x03001C74, 0x08);  // set MIPI_TXP2 Driving Strength to 0
    mmio_write_32(0x03001C70, 0x08);  // set MIPI_TXM2 Driving Strength to 0


3、
Z:\cv1823\smartpen\build\boards\cv1826_wevb_0005a_3\linux\cv1826_wevb_0005a_3.dts
    /delete-node/ ethernet@4070000;
    /delete-node/ cv-spinf@4060000;
    /delete-node/ cvi-spif@10000000;
    /delete-node/ sound_PDM;
    /delete-node/ cv-sd@4310000;

    // i2c5:i2c_gpio {
    //     compatible = "i2c-gpio";
    //     gpios = <&porte 2 GPIO_ACTIVE_HIGH>, /* sda PWR_GPIO2*/
    //             <&porte 1 GPIO_ACTIVE_HIGH>; /* scl PWR_GPIO1*/
    //     i2c-gpio,delay-us = <5>;    /* ~100 kHz */
    // };
    aliases {
        i2c0 = &i2c0;
        i2c1 = &i2c1;
        i2c2 = &i2c2;
        i2c3 = &i2c3;
        i2c4 = &i2c4;
        i2c5 = &pwr_i2c;

#if 0
        ethernet0 = &ethernet0;
#endif
    };
};

&uart1 {
        status = "okay";
};
修改为:
    /delete-node/ ethernet@4070000;
    /delete-node/ cv-spinf@4060000;
    /delete-node/ cvi-spif@10000000;
    /delete-node/ sound_PDM;
    /delete-node/ cv-sd@4310000;

    //i2c_camera:i2c6 {
    //i2c-gpio:i2c6 {
    i2c_gpio:i2c6 {
            
             compatible = "i2c-gpio";
             gpios = <&portc 14 GPIO_ACTIVE_HIGH>, /*SDA*/
                 <&portc 15 GPIO_ACTIVE_HIGH>; /*SCL*/

            //i2c-gpio,sda-open-drain;
            //i2c-gpio,scl-open-drain;
             //i2c-gpio,delay-us = <5>;    /* ~100 kHz */
            //i2c-gpio,delay-us = <2>;    /* ~100 kHz */
            //# [  138.687847] i2c i2c-6: sendbytes: NAK bailout.
            //i2c-gpio,delay-us = <20>;
            i2c-gpio,delay-us = <50>;
            //i2c-gpio,delay-us = <200>;
            #address-cells = <1>;
            #size-cells = <0>;

            //status = "okay";
    };
         
    aliases {
        i2c0 = &i2c0;
        i2c1 = &i2c1;
        i2c2 = &i2c2;
        i2c3 = &i2c3;
        i2c4 = &i2c4;
        i2c5 = &pwr_i2c;
        //i2c6 = &i2c_camera;
        //i2c6 = &i2c6;
        //i2c6 = &i2c-gpio;
        i2c6 = &i2c_gpio;
#if 0
        ethernet0 = &ethernet0;
#endif
    };
};

&uart1 {
        status = "okay";
};


4、【请严重注意:本处内核里面的printk打印可能会被清除掉,但是本处必须修改!】
另:I2C0拿掉还是会显示/dev/i2c-0,但是不加上I2C6,肯定不会显示/dev/i2c-6!^_
Z:\cv1823\smartpen\linux\drivers\i2c\i2c-dev.c
static int i2cdev_attach_adapter(struct device *dev, void *dummy)
{
    struct i2c_adapter *adap;
    struct i2c_dev *i2c_dev;
    int res;

    if (dev->type != &i2c_adapter_type)
        return 0;
    adap = to_i2c_adapter(dev);

    i2c_dev = get_free_i2c_dev(adap);
    if (IS_ERR(i2c_dev))
        return PTR_ERR(i2c_dev);

    cdev_init(&i2c_dev->cdev, &i2cdev_fops);
    i2c_dev->cdev.owner = THIS_MODULE;

    device_initialize(&i2c_dev->dev);
    i2c_dev->dev.devt = MKDEV(I2C_MAJOR, adap->nr);
    i2c_dev->dev.class = i2c_dev_class;
    i2c_dev->dev.parent = &adap->dev;
    i2c_dev->dev.release = i2cdev_dev_release;

#if defined(CONFIG_ARCH_CVITEK)
    if (!strcmp(adap->dev.of_node->full_name, I2C0))
        adap->i2c_idx = 0;
    if (!strcmp(adap->dev.of_node->full_name, I2C1))
        adap->i2c_idx = 1;
    if (!strcmp(adap->dev.of_node->full_name, I2C2))
        adap->i2c_idx = 2;
    if (!strcmp(adap->dev.of_node->full_name, I2C3))
        adap->i2c_idx = 3;
    if (!strcmp(adap->dev.of_node->full_name, I2C4))
        adap->i2c_idx = 4;
    if (!strcmp(adap->dev.of_node->full_name, PWRI2C))
        adap->i2c_idx = 5;

    dev_set_name(&i2c_dev->dev, "i2c-%d", adap->i2c_idx);
#else
    dev_set_name(&i2c_dev->dev, "i2c-%d", adap->nr);
#endif


    res = cdev_device_add(&i2c_dev->cdev, &i2c_dev->dev);
    if (res) {
        put_i2c_dev(i2c_dev, false);
        return res;
    }

    pr_debug("i2c-dev: adapter [%s] registered as minor %d\n",
         adap->name, adap->nr);
    return 0;
}
修改为:
static int i2cdev_attach_adapter(struct device *dev, void *dummy)
{
    struct i2c_adapter *adap;
    struct i2c_dev *i2c_dev;
    int res;
    
    printk("***wyb %s:%d %s\n",__FILE__,__LINE__,__FUNCTION__);

    if (dev->type != &i2c_adapter_type)
        return 0;
    adap = to_i2c_adapter(dev);

    i2c_dev = get_free_i2c_dev(adap);
    if (IS_ERR(i2c_dev))
        return PTR_ERR(i2c_dev);

    cdev_init(&i2c_dev->cdev, &i2cdev_fops);
    i2c_dev->cdev.owner = THIS_MODULE;

    device_initialize(&i2c_dev->dev);
    i2c_dev->dev.devt = MKDEV(I2C_MAJOR, adap->nr);
    i2c_dev->dev.class = i2c_dev_class;
    i2c_dev->dev.parent = &adap->dev;
    i2c_dev->dev.release = i2cdev_dev_release;

#if defined(CONFIG_ARCH_CVITEK)
    //if (!strcmp(adap->dev.of_node->full_name, I2C0))
    //    adap->i2c_idx = 0;

    if (!strcmp(adap->dev.of_node->full_name, I2C1))
        adap->i2c_idx = 1;
    if (!strcmp(adap->dev.of_node->full_name, I2C2))
        adap->i2c_idx = 2;
    if (!strcmp(adap->dev.of_node->full_name, I2C3))
        adap->i2c_idx = 3;
    if (!strcmp(adap->dev.of_node->full_name, I2C4))
        adap->i2c_idx = 4;
    if (!strcmp(adap->dev.of_node->full_name, PWRI2C))
        adap->i2c_idx = 5;

    if (!strcmp(adap->dev.of_node->full_name, "i2c6"))
        adap->i2c_idx = 6;

        
    //if (!strcmp(adap->dev.of_node->full_name, i2c_gpio))
    //    adap->i2c_idx = 6;        
    dev_set_name(&i2c_dev->dev, "i2c-%d", adap->i2c_idx);
    
    printk("***wyb %s:%d %s\n",__FILE__,__LINE__,__FUNCTION__);
#else
    dev_set_name(&i2c_dev->dev, "i2c-%d", adap->nr);
    
    printk("***wyb %s:%d %s\n",__FILE__,__LINE__,__FUNCTION__);
#endif


    res = cdev_device_add(&i2c_dev->cdev, &i2c_dev->dev);
    if (res) {
        put_i2c_dev(i2c_dev, false);
        return res;
    }

    pr_debug("i2c-dev: adapter [%s] registered as minor %d\n",
         adap->name, adap->nr);
    
    printk("***wyb %s:%d %s\n",__FILE__,__LINE__,__FUNCTION__);
    
    return 0;
}


5、【可选】加的printk会被打印,在SourceInsight中搜索:"i2c-"找到这里了!
有兴趣的可以了解一下!
Z:\cv1823\smartpen\linux\drivers\i2c\i2c-core-base.c
static int i2c_register_adapter(struct i2c_adapter *adap)
{
    int res = -EINVAL;
    
    printk("***wyb %s:%d %s\n",__FILE__,__LINE__,__FUNCTION__);

    /* Can't register until after driver model init */
    if (WARN_ON(!is_registered)) {
        res = -EAGAIN;
        goto out_list;
    }

    /* Sanity checks */
    if (WARN(!adap->name[0], "i2c adapter has no name"))
        goto out_list;

    if (!adap->algo) {
        pr_err("adapter '%s': no algo supplied!\n", adap->name);
        goto out_list;
    }

    if (!adap->lock_ops)
        adap->lock_ops = &i2c_adapter_lock_ops;

    rt_mutex_init(&adap->bus_lock);
    rt_mutex_init(&adap->mux_lock);
    mutex_init(&adap->userspace_clients_lock);
    INIT_LIST_HEAD(&adap->userspace_clients);

    /* Set default timeout to 1 second if not already set */
    if (adap->timeout == 0)
        adap->timeout = HZ;

    /* register soft irqs for Host Notify */
    res = i2c_setup_host_notify_irq_domain(adap);
    if (res) {
        pr_err("adapter '%s': can't create Host Notify IRQs (%d)\n",
               adap->name, res);
        goto out_list;
    }
    
    printk("***wyb %s:%d %s i2c-%d\n",__FILE__,__LINE__,__FUNCTION__, adap->nr);
    dev_set_name(&adap->dev, "i2c-%d", adap->nr);

    
    adap->dev.bus = &i2c_bus_type;
    adap->dev.type = &i2c_adapter_type;
    res = device_register(&adap->dev);
    if (res) {
        pr_err("adapter '%s': can't register device (%d)\n", adap->name, res);
        goto out_list;
    }

    res = of_i2c_setup_smbus_alert(adap);
    if (res)
        goto out_reg;

    printk("***wyb %s:%d %s adapter [%s] registered\n",__FILE__,__LINE__,__FUNCTION__, adap->name);
    dev_dbg(&adap->dev, "adapter [%s] registered\n", adap->name);

    pm_runtime_no_callbacks(&adap->dev);
    pm_suspend_ignore_children(&adap->dev, true);
    pm_runtime_enable(&adap->dev);

#ifdef CONFIG_I2C_COMPAT
    res = class_compat_create_link(i2c_adapter_compat_class, &adap->dev,
                       adap->dev.parent);
    if (res)
        dev_warn(&adap->dev,
             "Failed to create compatibility class link\n");
#endif

    i2c_init_recovery(adap);

    /* create pre-declared device nodes */
    of_i2c_register_devices(adap);
    i2c_acpi_install_space_handler(adap);
    i2c_acpi_register_devices(adap);

    if (adap->nr < __i2c_first_dynamic_bus_num)
        i2c_scan_static_board_info(adap);

    /* Notify drivers */
    mutex_lock(&core_lock);
    bus_for_each_drv(&i2c_bus_type, NULL, adap, __process_new_adapter);
    mutex_unlock(&core_lock);
    
    printk("***wyb %s:%d %s\n",__FILE__,__LINE__,__FUNCTION__);

    return 0;

out_reg:
    init_completion(&adap->dev_released);
    device_unregister(&adap->dev);
    wait_for_completion(&adap->dev_released);
out_list:
    mutex_lock(&core_lock);
    idr_remove(&i2c_adapter_idr, adap->nr);
    mutex_unlock(&core_lock);
    return res;
}


6、确认生成/dev/i2c-6:



# cd /sys/class/i2c-adapter/

# ls -l
total 0
lrwxrwxrwx    1 root     root             0 Jan  1 00:00 i2c-0 -> ../../devices/platform/4000000.i2c/i2c-0
lrwxrwxrwx    1 root     root             0 Jan  1 00:00 i2c-1 -> ../../devices/platform/4010000.i2c/i2c-1
lrwxrwxrwx    1 root     root             0 Jan  1 00:00 i2c-2 -> ../../devices/platform/4020000.i2c/i2c-2
lrwxrwxrwx    1 root     root             0 Jan  1 00:00 i2c-3 -> ../../devices/platform/4030000.i2c/i2c-3
lrwxrwxrwx    1 root     root             0 Jan  1 00:00 i2c-4 -> ../../devices/platform/4040000.i2c/i2c-4
lrwxrwxrwx    1 root     root             0 Jan  1 00:00 i2c-5 -> ../../devices/platform/502b000.i2c/i2c-5

lrwxrwxrwx    1 root     root             0 Jan  1 00:00 i2c-6 -> ../../devices/platform/i2c6/i2c-6

# cd /sys/bus/i2c/devices/

# ls -l
total 0
lrwxrwxrwx    1 root     root             0 Jan  1 00:00 0-003d -> ../../../devices/platform/4000000.i2c/i2c-0/0-003d
lrwxrwxrwx    1 root     root             0 Jan  1 00:00 1-003d -> ../../../devices/platform/4010000.i2c/i2c-1/1-003d
lrwxrwxrwx    1 root     root             0 Jan  1 00:00 2-0020 -> ../../../devices/platform/4020000.i2c/i2c-2/2-0020
lrwxrwxrwx    1 root     root             0 Jan  1 00:00 2-003d -> ../../../devices/platform/4020000.i2c/i2c-2/2-003d
lrwxrwxrwx    1 root     root             0 Jan  1 00:00 2-0055 -> ../../../devices/platform/4020000.i2c/i2c-2/2-0055
lrwxrwxrwx    1 root     root             0 Jan  1 00:00 3-0034 -> ../../../devices/platform/4030000.i2c/i2c-3/3-0034
lrwxrwxrwx    1 root     root             0 Jan  1 00:00 3-0035 -> ../../../devices/platform/4030000.i2c/i2c-3/3-0035
lrwxrwxrwx    1 root     root             0 Jan  1 00:00 3-003d -> ../../../devices/platform/4030000.i2c/i2c-3/3-003d
lrwxrwxrwx    1 root     root             0 Jan  1 00:00 3-0062 -> ../../../devices/platform/4030000.i2c/i2c-3/3-0062
lrwxrwxrwx    1 root     root             0 Jan  1 00:00 4-003d -> ../../../devices/platform/4040000.i2c/i2c-4/4-003d
lrwxrwxrwx    1 root     root             0 Jan  1 00:00 4-004e -> ../../../devices/platform/4040000.i2c/i2c-4/4-004e
lrwxrwxrwx    1 root     root             0 Jan  1 00:00 5-0018 -> ../../../devices/platform/502b000.i2c/i2c-5/5-0018
lrwxrwxrwx    1 root     root             0 Jan  1 00:00 5-0019 -> ../../../devices/platform/502b000.i2c/i2c-5/5-0019
lrwxrwxrwx    1 root     root             0 Jan  1 00:00 5-0034 -> ../../../devices/platform/502b000.i2c/i2c-5/5-0034
lrwxrwxrwx    1 root     root             0 Jan  1 00:00 i2c-0 -> ../../../devices/platform/4000000.i2c/i2c-0
lrwxrwxrwx    1 root     root             0 Jan  1 00:00 i2c-1 -> ../../../devices/platform/4010000.i2c/i2c-1
lrwxrwxrwx    1 root     root             0 Jan  1 00:00 i2c-2 -> ../../../devices/platform/4020000.i2c/i2c-2
lrwxrwxrwx    1 root     root             0 Jan  1 00:00 i2c-3 -> ../../../devices/platform/4030000.i2c/i2c-3
lrwxrwxrwx    1 root     root             0 Jan  1 00:00 i2c-4 -> ../../../devices/platform/4040000.i2c/i2c-4
lrwxrwxrwx    1 root     root             0 Jan  1 00:00 i2c-5 -> ../../../devices/platform/502b000.i2c/i2c-5
lrwxrwxrwx    1 root     root             0 Jan  1 00:00 i2c-6 -> ../../../devices/platform/i2c6/i2c-6



# cd /dev

# ls -l 
total 0
drwxr-xr-x    2 root     root           400 Jan  1 00:00 block
drwxr-xr-x    3 root     root            60 Jan  1 00:00 bus
drwxr-xr-x    2 root     root         13080 Jan  1 00:00 char
crw-------    1 root     root        5,   1 Jan  1 00:03 console
crw-------    1 root     root       10,  60 Jan  1 00:00 cpu_dma_latency
crw-------    1 root     root       10,  62 Jan  1 00:00 cv182xadc
crw-------    1 root     root       10,  61 Jan  1 00:00 cv182xdac
crw-------    1 root     root       10,  55 Jan  1 00:00 cvi-base
crw-------    1 root     root       10,  54 Jan  1 00:00 cvi-mipi-rx
crw-------    1 root     root       10,  53 Jan  1 00:00 cvi-mipi-tx
crw-------    1 root     root      243,   0 Jan  1 00:00 cvi-saradc0
crw-------    1 root     root      242,   0 Jan  1 00:00 cvi-tpu0
crw-------    1 root     root       10,  52 Jan  1 00:00 cvi-vcodec
drwxr-xr-x    8 root     root           160 Jan  1 00:00 disk
crw-rw----    1 root     video      29,   0 Jan  1 00:00 fb0
lrwxrwxrwx    1 root     root            13 Jan  1 00:00 fd -> /proc/self/fd
crw-rw-rw-    1 root     root        1,   7 Jan  1 00:00 full
crw-------    1 root     root      254,   0 Jan  1 00:00 gpiochip0
crw-------    1 root     root      254,   1 Jan  1 00:00 gpiochip1
crw-------    1 root     root      254,   2 Jan  1 00:00 gpiochip2
crw-------    1 root     root      254,   3 Jan  1 00:00 gpiochip3
crw-------    1 root     root      254,   4 Jan  1 00:00 gpiochip4
crw-------    1 root     root       10, 183 Jan  1 00:00 hwrng
crw-------    1 root     root       89,   0 Jan  1 00:00 i2c-0
crw-------    1 root     root       89,   1 Jan  1 00:00 i2c-1
crw-------    1 root     root       89,   2 Jan  1 00:00 i2c-2
crw-------    1 root     root       89,   3 Jan  1 00:00 i2c-3
crw-------    1 root     root       89,   4 Jan  1 00:00 i2c-4
crw-------    1 root     root       89,   5 Jan  1 00:00 i2c-5

crw-------    1 root     root       89,   6 Jan  1 00:00 i2c-6
drwxr-xr-x    3 root     root           120 Jan  1 00:00 input
crw-------    1 root     root       10,  63 Jan  1 00:00 ion


【后记:模拟I2C的传输速度实测】


1、i2c-gpio,delay-us = <50>;
Microsoft Windows [版本 10.0.19045.2728]
(c) Microsoft Corporation。保留所有权利。

C:\Users\Sun>adb shell
/ #
/ # i2cdetect -y -r 6
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- 35 -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: 60 -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --
/ #

# [  349.189520] i2c i2c-6: sendbytes: NAK bailout.


参考资料:
https://blog.csdn.net/lutao614/article/details/14452539
gslX680驱动中出现“i2c i2c-0: sendbytes: NAK bailout.”错误


https://blog.csdn.net/ch122633/article/details/120144785
使用GPIO模拟I2C的驱动程序分析


https://cloud.tencent.com/developer/article/1914841
14——使用GPIO操作I2C设备_IMX6ULL
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值