return; } ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
注册名字为GSLX680_I2C_NAME的i2c驱动,即gslx680,该驱动支持的设备名为字gsl_ts_id[]里的设备名称。因为我们在dts中已注册了一个名字为gslx680的i2c设备。因此,设备与驱动可以匹配成功并正确执行probe()函数。 至于设备与驱动是如何匹配的,可以参照Linux i2c子系统 3、gsl_ts_probe() static int gsl_ts_probe(struct i2c_client *client,const struct i2c_device_id *id) { struct gsl_ts *ts; int rc; struct device_node *np = client->dev.of_node; enum of_gpio_flags wake_flags; unsigned long irq_flags; // 检查i2c适配器的能力 printk(\ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { dev_err(&client->dev, \\ return -ENODEV; } // 为ts申请内核空间 ts = kzalloc(sizeof(*ts), GFP_KERNEL); if(!ts) return -ENOMEM; printk(\ ts->client = client; i2c_set_clientdata(client, ts); ts->device_id = id->driver_data; // 从设备节点np中获取到irq和wake 的gpio的信息 ts->irq_pin=of_get_named_gpio_flags(np, \m of_gpio_flags *)&irq_flags); ts->wake_pin=of_get_named_gpio_flags(np, \ake_flags); // 为设备申请gpio,并设置默认电平 if(gpio_is_valid(ts->wake_pin)) { rc = devm_gpio_request_one(&client->dev, ts->wake_pin, (wake_flags & OF_GPIO_ACTIVE_LOW) ? GPIOF_OUT_INIT_LOW : GPIOF_OUT_INIT_HIGH, \ if(rc != 0) { dev_err(&client->dev, \ return -EIO; } g_wake_pin = ts->wake_pin; //msleep(100); } else { dev_info(&client->dev, \ } if(gpio_is_valid(ts->irq_pin)) { rc = devm_gpio_request_one(&client->dev, ts->irq_pin, (irq_flags & OF_GPIO_ACTIVE_LOW) ? GPIOF_OUT_INIT_LOW : GPIOF_OUT_INIT_HIGH, \ if (rc != 0) { dev_err(&client->dev, \ return -EIO; } } else { dev_info(&client->dev, \ } // 创建工作队列,申请input设备 rc = gslX680_ts_init(client, ts); if(rc < 0) { dev_err(&client->dev, \ goto error_mutex_destroy; } gsl_client = client; // 从设备节点中获取属性信息 of_property_read_u32(np,\ of_property_read_u32(np,\ // 初始化IC,包括复位,测试i2c以及加载ic配置信息 init_chip(ts->client); check_mem_data(ts->client); // 申请中断号 ts->irq=gpio_to_irq(ts->irq_pin); //If not defined in client if (ts->irq) { // 为client->dev设备的中断号ts->irq申请irq_flags触发的中断,中断服务子程序为gsl_ts_irq rc = devm_request_threaded_irq(&client->dev, ts->irq, NULL, gsl_ts_irq, irq_flags | IRQF_ONESHOT, client->name, ts); if(rc != 0) { printk(KERN_ALERT \\ goto error_req_irq_fail; } //disable_irq(ts->irq); } else { printk(\ goto error_req_irq_fail; } ts->tp.tp_resume = gsl_ts_late_resume; ts->tp.tp_suspend = gsl_ts_early_suspend; tp_register_fb(&ts->tp); #ifdef CONFIG_HAS_EARLYSUSPEND