Rockchip平台TP驱动详解Word下载.docx

上传人:b****6 文档编号:16621017 上传时间:2022-11-24 格式:DOCX 页数:25 大小:23.57KB
下载 相关 举报
Rockchip平台TP驱动详解Word下载.docx_第1页
第1页 / 共25页
Rockchip平台TP驱动详解Word下载.docx_第2页
第2页 / 共25页
Rockchip平台TP驱动详解Word下载.docx_第3页
第3页 / 共25页
Rockchip平台TP驱动详解Word下载.docx_第4页
第4页 / 共25页
Rockchip平台TP驱动详解Word下载.docx_第5页
第5页 / 共25页
点击查看更多>>
下载资源
资源描述

Rockchip平台TP驱动详解Word下载.docx

《Rockchip平台TP驱动详解Word下载.docx》由会员分享,可在线阅读,更多相关《Rockchip平台TP驱动详解Word下载.docx(25页珍藏版)》请在冰豆网上搜索。

Rockchip平台TP驱动详解Word下载.docx

ts@40{

//wake-gpio=<

/*...*/

∙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=<

属性表示此设备的i2c地址为0x40,等同于@40;

3、wake-gpio=<

表示复位引脚使用的是GPIO0中的GPIO_D3这个引脚,低电平有效。

irp-gpio=<

表示中断引脚使用的是GPIO0中的GPIO_A2这个引脚,高电平触发。

很奇怪,为什么这里没有上电的信息,以及在整个驱动程序中都没有给ic上电的操作。

在前面的MTK平台上的tp驱动都有上电的动作,暂时还搞不懂在RK平台上为什么没有。

4、revert_x=<

标记x和y是否需要翻转。

在上述的信息中,可以通过of接口获取到属性对应的值。

在后面的probe()函数中就会使用到。

注:

关于dts的详细信息可以查看ARMLinux3.x的设备树(DeviceTree)和DeviceTreeUsage

2、修改Makefile、Kconfig、defconfig

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

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

obj-$(CONFIG_TOUCHSCREEN_GSLX680)+=gslx680/。

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

在配置内核的时候会通过makemenuconfig来配置对应的选项。

或者是直接在defconfig文件中强制设置该选项。

如果不想要这么复杂,可以将该语句写成obj-y+=gslx680/来强制编译该驱动。

(2)、修改Kconfig添加驱动配置描述

drivers/input/touchscreen/Kconfig中添加驱动配置描述:

configTOUCHSCREEN_GSLX680

tristate"

gslX680touchscreendriver"

help

gslX680touchscreendriver

(3)、配置defconfig设置编译驱动

一般在内核中会有配置好的默认的config文件供参考,可以直接修改defconfig来选择编译某个驱动。

此处在arch/arm/configs/rockchip_defconfig文件中添加CONFIG_TOUCHSCREEN_GSLX680=y并将该文件拷贝到kernel目录下命名为.config即可。

2、添加i2c驱动

#defineGSLX680_I2C_NAME"

#defineGSLX680_I2C_ADDR0x40

staticconststructi2c_device_idgsl_ts_id[]={

{GSLX680_I2C_NAME,0},

{}

};

MODULE_DEVICE_TABLE(i2c,gsl_ts_id);

staticstructi2c_drivergsl_ts_driver={

.driver={

.name=GSLX680_I2C_NAME,

.owner=THIS_MODULE,

},

#ifndefCONFIG_HAS_EARLYSUSPEND

//.suspend=gsl_ts_suspend,

//.resume=gsl_ts_resume,

#endif

.probe=gsl_ts_probe,

.remove=gsl_ts_remove,

.id_table=gsl_ts_id,

staticint__initgsl_ts_init(void)

{

intret;

printk("

==gsl_ts_init==\n"

);

ret=i2c_add_driver(&

gsl_ts_driver);

ret=%d\n"

ret);

returnret;

}

staticvoid__exitgsl_ts_exit(void)

==gsl_ts_exit==\n"

i2c_del_driver(&

return;

∙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()函数。

至于设备与驱动是如何匹配的,可以参照Linuxi2c子系统

3、gsl_ts_probe()

staticintgsl_ts_probe(structi2c_client*client,conststructi2c_device_id*id)

structgsl_ts*ts;

intrc;

structdevice_node*np=client->

dev.of_node;

enumof_gpio_flagswake_flags;

unsignedlongirq_flags;

//检查i2c适配器的能力

GSLX680Enter%s\n"

__func__);

if(!

i2c_check_functionality(client->

adapter,I2C_FUNC_I2C))

{

dev_err(&

client->

dev,"

I2Cfunctionalitynotsupported\n"

return-ENODEV;

}

//为ts申请内核空间

ts=kzalloc(sizeof(*ts),GFP_KERNEL);

if(!

ts)

return-ENOMEM;

==kzallocsuccess=\n"

ts->

client=client;

i2c_set_clientdata(client,ts);

device_id=id->

driver_data;

//从设备节点np中获取到irq和wake的gpio的信息

irq_pin=of_get_named_gpio_flags(np,"

irp-gpio"

0,(enumof_gpio_flags*)&

irq_flags);

wake_pin=of_get_named_gpio_flags(np,"

wake-gpio"

0,&

wake_flags);

//为设备申请gpio,并设置默认电平

if(gpio_is_valid(ts->

wake_pin))

rc=devm_gpio_request_one(&

dev,ts->

wake_pin,(wake_flags&

OF_GPIO_ACTIVE_LOW)?

GPIOF_OUT_INIT_LOW:

GPIOF_OUT_INIT_HIGH,"

gslX680wakepin"

if(rc!

=0)

gslX680wakepinerror\n"

return-EIO;

g_wake_pin=ts->

wake_pin;

//msleep(100);

else

dev_info(&

wakepininvalid\n"

irq_pin))

irq_pin,(irq_flags&

gslX680irqpin"

if(rc!

gslX680irqpinerror\n"

irqpininvalid\n"

//创建工作队列,申请input设备

rc=gslX680_ts_init(client,ts);

if(rc<

0)

GSLX680initfailed\n"

gotoerror_mutex_destroy;

}

gsl_client=client;

//从设备节点中获取属性信息

of_property_read_u32(np,"

revert_x"

&

revert_x);

//sss

revert_y"

revert_y);

//初始化IC,包括复位,测试i2c以及加载ic配置信息

init_chip(ts->

client);

check_mem_data(ts->

//申请中断号

irq=gpio_to_irq(ts->

irq_pin);

//Ifnotdefinedinclient

if(ts->

irq)

//为client->

dev设备的中断号ts->

irq申请irq_flags触发的中断,中断服务子程序为gsl_ts_irq

rc=devm_request_threaded_irq(&

irq,NULL,gsl_ts_irq,irq_flags|IRQF_ONESHOT,client->

name,ts);

printk(KERN_ALERT"

CannotallocatetsINT!

ERRNO:

%d\n"

rc);

gotoerror_req_irq_fail;

//disable_irq(ts->

irq);

gslx680irqreqfail\n"

tp.tp_resume=gsl_ts_late_resume;

tp.tp_suspend=gsl_ts_early_suspend;

tp_register_fb(&

ts->

tp);

#ifdefCONFIG_HAS_EARLYSUSPEND

early_suspend.level=EARLY_SUSPEND_LEVEL_BLANK_SCREEN+1;

//ts->

early_suspend.level=EARLY_SUSPEND_LEVEL_DISABLE_FB+1;

early_suspend.suspend=gsl_ts_early_suspend;

early_suspend.resume=gsl_ts_late_resume;

register_early_suspend(&

early_suspend);

#ifdefGSL_MONITOR

printk("

gsl_ts_probe():

queuegsl_monitor_workqueue\n"

INIT_DELAYED_WORK(&

gsl_monitor_work,gsl_monitor_worker);

gsl_monitor_workqueue=create_singlethread_workqueue("

gsl_monitor_workqueue"

queue_delayed_work(gsl_monitor_workqueue,&

gsl_monitor_work,1000);

[GSLX680]End%s\n"

return0;

//exit_set_irq_mode:

error_req_irq_fail:

free_irq(ts->

irq,ts);

error_mutex_destroy:

input_free_device(ts->

input);

kfree(ts);

returnrc;

∙39

∙40

∙41

∙42

∙43

∙44

∙45

∙46

∙47

∙48

∙49

∙50

∙51

∙52

∙53

∙54

∙55

∙56

∙57

∙58

∙59

∙60

∙61

∙62

∙63

∙64

∙65

∙66

∙67

∙68

∙69

∙70

∙71

∙72

∙73

∙74

∙75

∙76

∙77

∙78

∙79

∙80

∙81

∙82

∙83

∙84

∙85

∙86

∙87

∙88

∙89

∙90

∙91

∙92

∙93

∙94

∙95

∙96

∙97

∙98

∙99

∙100

∙101

∙102

∙103

∙104

∙105

∙106

∙107

∙108

∙109

∙110

∙111

∙112

∙113

∙114

∙115

∙116

∙117

∙118

∙119

∙120

∙121

∙122

∙123

∙124

∙125

∙126

∙127

∙128

∙129

∙130

∙131

(1)、自定义的数据结构gsl_ts

一般在自己的驱动程序中,都会为该驱动程序封装一个数据结构,这里的gsl_ts就充当这种角色。

在该驱动程序中自定义了一个数据结构:

structgsl_ts{

structi2c_client*client;

structinput_dev*input;

structwork_structwork;

structworkqueue_struct*wq;

structgsl_ts_data*dd;

u8*touch_data;

u8device_id;

intirq;

intirq_pin;

intwake_pin;

structtp_devicetp;

#ifdefined(CONFIG_HAS_EARLYSUSPEND)

structearly_suspendearly_suspend;

client表示一个i2c的设备;

input表示一个输入设备;

work表示一个工作,用于处理中断到来之后获取坐标等信息;

wq表示一个工作队列,将上面的work加入到该工作队列中;

dd和touch_data用来存储坐标的相关信息;

device_id表示i2c设备的设备号;

irq申请的中断号;

irq_pin中断引脚;

wake_pin复位引脚;

这两个引脚信息可以通过dts获取到. 

tp创建一个为tp_device的数据结构,里面有个成员notifier_block用来接收LCD背光灯的亮暗的通知进而调用suspend()和resume()。

主要的实现在tp_suspend.h中。

至于这里面的详细机制还不是很明白。

(2)、检查i2c适配器的能力

在很多i2c设备驱动程序中,一进入probe()就要检查i2c适配器的能力。

现在还不清楚这么做的目的是什么。

后面会仔细的学习一下linux的i2c子系统。

(3)、获取wake和irq的引脚信息

在前面配置dts说过:

dts中设备节点的属性的值可以通过of_接口获取到。

//从设备节点np中获取到irq和wake的gpio的信息

可以通过设备节点np获取到它irq-gpio这一个属性的值存放在ts->

irq_pin中,以及将其flag刚到变量irq_flags中。

因此我们可以知道:

irq_pin=GPIO_A2

irq_flag=IRQ_TYPE_LEVEL_HIGH

同理,wake_pin也是一样。

(4)、申请gpio并设置输出电平

将irq和wake引脚电平都设置输出低电平。

(5)、gslX680_ts_init

staticintgslX680_ts_init(structi2c_client*client,structgsl_ts*ts)

structinput_dev*input_device;

intrc=0;

[GSLX680]Enter%s\n"

//配置获取坐标信息

dd=&

devices[ts->

device_id];

if(ts->

device_id==0)

dd->

data_size=MAX_FINGERS*ts->

touch_bytes+ts->

touch_meta_data;

touch_index=0;

//申请空间存放坐标信息

touch_data=kzalloc(ts->

data_size,GFP_KERNEL);

touch_data)

pr_err("

%s:

Unabletoallocatememory\n"

//申请一个input_dev设备

input_device=input_allocate_device();

input_device){

rc=-ENOMEM;

gotoerror_alloc_dev;

//初始化input_device

input=input_device;

input_device->

name=GSLX680_I2C_NAME;

input_devi

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > PPT模板 > 动态背景

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1