Rockchip平台TP驱动详解

更新时间:2023-03-16 00:53:01 阅读量: 教育文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

本文描述在RK3126平台上添加一个新的TP驱动(gslx680驱动)以及详细的驱动代码信息。如有不足之处,敬请指出。 1、修改dts,添加新的i2c设备。 在 arch/arm/boot/dts/rk312x-sdk-v2.2.dtsi中添加i2c设备的相关信息: ts@40 { compatible = \ reg = <0x40>; wake-gpio = <&gpio0 GPIO_D3 GPIO_ACTIVE_LOW>; irp-gpio = <&gpio0 GPIO_A2 IRQ_TYPE_LEVEL_HIGH>; revert_x = <0>; revert_y = <0>; }; ? ? ? ? ? ? ? ? 1 2 3 4 5 6 7 8 &i2c2 { status = \ /* ts@55 { compatible = \ reg = <0x55>; touch-gpio = <&gpio1 GPIO_B0 IRQ_TYPE_LEVEL_LOW>; reset-gpio = <&gpio2 GPIO_C1 GPIO_ACTIVE_LOW>; //power-gpio = <&gpio0 GPIO_C5 GPIO_ACTIVE_LOW>; max-x = <1280>; max-y = <800>; };*/ ts@40 { compatible = \ reg = <0x40>; //wake-gpio = <&gpio0 GPIO_D3 GPIO_ACTIVE_LOW>; irp-gpio = <&gpio0 GPIO_A2 IRQ_TYPE_LEVEL_HIGH>; revert_x = <0>; revert_y = <0>; }; /* ... */ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22

表示i2c2总线上下挂在了多个i2c设备。

其中ts@40是表示此i2c设备的设备类型为触摸屏,设备地址为0x40(7位地址,

注意:在i2c的传输函数中,会将此地址左移一位,因此实际上gslx680的i2c设备地址为0x80)。该节点下有多个属性:

1、compatible = \属性用于驱动和设备的绑定。表示特定的设备名称,此处为gslX680;

2、reg = <0x40>;属性表示此设备的i2c地址为0x40,等同于@40; 3、wake-gpio = <&gpio0 GPIO_D3 GPIO_ACTIVE_LOW>;表示复位引脚使用的是GPIO0 中的GPIO_D3这个引脚,低电平有效。

irp-gpio = <&gpio0 GPIO_A2 IRQ_TYPE_LEVEL_HIGH>;表示中断引脚使用的是

GPIO0中的GPIO_A2这个引脚,高电平触发。

很奇怪,为什么这里没有上电的信息,以及在整个驱动程序中都没有给ic上电的操作。在前面的MTK平台上的tp驱动都有上电的动作,暂时还搞不懂在RK平台上为什么没有。

4、revert_x = <0>; revert_y = <0>;标记x和y是否需要翻转。

在上述的信息中,可以通过of接口获取到属性对应的值。在后面的probe()函数中就会使用到。

注:关于dts的详细信息可以查看ARM Linux 3.x的设备树(Device Tree)和Device Tree Usage

2、修改Makefile、Kconfig、defconfig (1)、修改Makefile添加gslx680驱动

在 drivers/input/touchscreen/Makefile中添加驱动:

obj-$(CONFIG_TOUCHSCREEN_GSLX680) += gslx680/。

只要当配置了CONFIG_TOUCHSCREEN_GSLX680的选项才会去编译gslx680目录下

的内容。在配置内核的时候会通过make menuconfig来配置对应的选项。或者是直接在defconfig文件中强制设置该选项。 注:如果不想要这么复杂,可以将该语句写成obj-y += gslx680/来强制编译该驱动。 (2)、修改Kconfig添加驱动配置描述 在 drivers/input/touchscreen/Kconfig中添加驱动配置描述: config TOUCHSCREEN_GSLX680 tristate \ help gslX680 touchscreen driver ? ? ? ? 1 2 3 4 (3)、配置defconfig设置编译驱动 一般在内核中会有配置好的默认的config文件供参考,可以直接修改defconfig来选择编译某个驱动。此处在arch/arm/configs/rockchip_defconfig文件中添加CONFIG_TOUCHSCREEN_GSLX680=y并将该文件拷贝到kernel目录下命名为.config即可。 2、添加i2c驱动 #define GSLX680_I2C_NAME \#define GSLX680_I2C_ADDR 0x40 static const struct i2c_device_id gsl_ts_id[] = { {GSLX680_I2C_NAME, 0}, {} }; MODULE_DEVICE_TABLE(i2c, gsl_ts_id); static struct i2c_driver gsl_ts_driver = { .driver = { .name = GSLX680_I2C_NAME, .owner = THIS_MODULE, }, #ifndef CONFIG_HAS_EARLYSUSPEND // .suspend = gsl_ts_suspend, // .resume = gsl_ts_resume, #endif .probe = gsl_ts_probe, .remove = gsl_ts_remove, .id_table = gsl_ts_id, }; static int __init gsl_ts_init(void) { int ret; printk(\ ret = i2c_add_driver(&gsl_ts_driver); printk(\ return ret; } static void __exit gsl_ts_exit(void) { printk(\ i2c_del_driver(&gsl_ts_driver);

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

本文来源:https://www.bwwdw.com/article/g76v.html

Top