i2c 设备自动探测

来源:互联网 发布:淘宝怎样设置秒杀 编辑:程序博客网 时间:2024/04/27 21:32

最近在做camera和ts的自动识别。因为平台上各种品牌的camera和ts种类繁多,而且有的i2c地址有冲突,通常是在board-device里面配置i2c设备,如果遇到不同机型有相同i2c地址则会造成设备创建失败,只能在编译的时候去改代码,这样调试多种机型就很繁琐,所以有了以下代码。


这里先看下camera的代码:

static int gc0309_lookfor_bus(struct gc0309_info *info){uint8_t val;uint32_t ver;info->i2c_dev->adapter = i2c_get_adapter(i2c_bus);gc0309_i2c_rx_receive(info->i2c_dev, 0x00, &val, 1);ver = val;cam_notice("read ver=%x\n", ver);if (ver == 0xa0) {cam_notice("gc0309 sensor detected...\n");return 0;}cam_notice("gc0309 not found on all i2c bus.\n");return -ENODEV;}static int gc0309_register_i2c_device(struct gc0309_info *info){    struct i2c_board_info board_info;    memset(&board_info, 0, sizeof(struct i2c_board_info));    board_info.addr = info->i2c_dev->addr;    strlcpy(board_info.type, "gc0309", I2C_NAME_SIZE);    info->i2c_dev = i2c_new_device(info->i2c_dev->adapter, &board_info);    if (info->i2c_dev == NULL) {        cam_err("can't add i2c device at 0x%x\n", (unsigned int)board_info.addr);        return -ENODEV;    }    return 0;}static int __init gc0309_init(void){int ret;struct v4l2_subdev *sd;struct gc0309_info *info;info = kzalloc(sizeof(struct gc0309_info), GFP_KERNEL);if (info == NULL)return -ENOMEM;info->i2c_dev = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);if (info->i2c_dev == NULL)return -ENOMEM;/* get CAMERA clock */info->camera = clk_get(&info->i2c_dev->dev, "camera");if (IS_ERR(info->camera)) {cam_err("failed to acquire camera divider\n");ret = -ENODEV;goto exit;}clk_set_rate(info->camera, GC0309_SENSOR_CLOCK);clk_enable(info->camera);/* request gpio */gpio_request(GPIO_CAM_PWDN_B, "cam_pwdn_b");gpio_request(GPIO_CAM_PWDN_F, "cam_pwdn_f");gpio_request(GPIO_CAM_RST_F, "cam_rst_f");/* firstly poweron */gc0309_gpio_preset();gc0309_poweron();gc0309_gpio_reset();info->i2c_dev->addr = 0x21;if(gc0309_lookfor_bus(info)) goto exit_power;if(gc0309_register_i2c_device(info)) goto exit_power;/* after detection finished, poweroff */gc0309_standby_mode();gc0309_poweroff();sd = &info->sd;info->i2c_dev->driver = &gc0309_driver;v4l2_i2c_subdev_init(sd, info->i2c_dev, &gc0309_ops);ret = i2c_add_driver(&gc0309_driver);if (ret) {cam_err("gc0309_dev camera module gc0309 i2c driver add failed\n");return ret;}return 0;exit_power:gc0309_standby_mode();gc0309_poweroff();clk_disable(info->camera);clk_put(info->camera);exit:kfree(info->i2c_dev);kfree(info);return -EFAULT;}static void __exit gc0309_exit(void){i2c_del_driver(&gc0309_driver);}module_param(i2c_bus, int , 0);MODULE_PARM_DESC(i2c_bus, "gc0309 i2c bus number");
刚开始写的时候只管实现这个功能,没有注意优化,感觉很多地方没考虑周全,所以花时间优化了一下,下面就是优化后的ts代码:

static int ft5x0x_add_i2c_device(void){int ret;int reg_value;struct i2c_board_info info;struct i2c_adapter *adapter;adapter = i2c_get_adapter(i2c_bus);if (!adapter) {atxxtp_err("can't get i2c adapter %d\n", i2c_bus);return -ENODEV;}memset(&info, 0, sizeof(struct i2c_board_info));    info.addr = i2c_addr;    strlcpy(info.type, FT5X0X_NAME, I2C_NAME_SIZE);    this_client = i2c_new_device(adapter, &info);i2c_put_adapter(adapter);    if (!this_client) {        atxxtp_err("can't add i2c device at 0x%x\n", i2c_addr);        return -ENODEV;    }reg_value = ft5x0x_read_fw_ver();  //读取ts的版本号  以此判断设备是否存在if(reg_value < 0 ) {atxxtp_err("can't read ft5x06 firmware version\n");ret = -ENODEV;goto exit;}ret = i2c_add_driver(&ft5x0x_ts_driver);if (ret) {atxxtp_err("can't addd ft5x0x_ts i2c driver\n");goto exit;}    return 0;exit:i2c_unregister_device(this_client);return ret;}static int __init ft5x0x_ts_init(void){int ret;ret = gpio_request(GPIO_TP_RESETn, FT5X0X_NAME);if (ret != 0) {atxxtp_err( "can't request GPIO %d!\n", GPIO_TP_RESETn);return -EFAULT;}init_reset_tp();mdelay(100);if(ft5x0x_add_i2c_device())goto exit;return 0;exit:gpio_free(GPIO_TP_RESETn);return -EFAULT;}static void __exit ft5x0x_ts_exit(void){i2c_del_driver(&ft5x0x_ts_driver);i2c_unregister_device(this_client);}module_param(i2c_bus, int, 0);MODULE_PARM_DESC(i2c_bus, "ft5x0x_ts i2c bus number");module_param(i2c_addr, ushort, 0);MODULE_PARM_DESC(i2c_addr, "ft5x0x_ts i2c address");

还好之前看过i2c的核心代码并且总结了一下,不然还真得花些时间才能完成这个。