您的位置:首页 > 运维架构 > 网站架构

Linux设备驱动程序架构分析之I2C架构(基于3.10.1内核)

2013-12-09 15:48 507 查看
作者:刘昊昱

博客:http://blog.csdn.net/liuhaoyutz

内核版本:3.10.1


I2C体系架构的硬件实体包括两部分:

硬件I2CAdapter:硬件I2CAdapter表示一个硬件I2C适配器,也就是I2C控制器。一般是SOC中的一个接口,也可以用GPIO模拟。硬件I2CAdapter主要用来在I2C接口上产生I2C时钟信号和数据信号。
硬件I2CDevice:表示一个I2C从设备,I2C从设备并行的挂接在I2C总线上,通过I2C接口与I2C主控制器通信。

Linux的I2C体系架构包括6个部分:

I2CCore,定义了一些函数和数据结构,用于支持I2C控制器驱动(I2CAdapterdrvier)和I2C设备驱动(I2Cclientdriver)。I2CCore的存在使I2C控制器驱动和I2C设备驱动独立开来,具有更好的可移置性,同时简化了驱动开发的工作量。但是,I2CCore的存在也使LinuxI2C体系结构理解起来更有难度。
I2CAdapter,代表一个I2C控制器,用structi2c_adapter来表示。
Algorithm,访问I2C控制器的接口,Algorithm直接操作I2C控制器的硬件寄存器来执行数据的发送和接收。它提供操作I2C控制器的最底层操作函数。每个I2CAdapter都有自己的Algorithm,每个I2CAdapter通过自己的Algorithm与挂接在该控制器上的I2C从设备进行通信。
I2CClient,代表一个挂接在I2C总线上的I2C设备。
I2C设备驱动(I2Cclientdriver)
I2C-dev,I2C控制器的设备文件,通常命名为i2c-0、i2c-1等等,是I2C控制器的应用层访问接口。


一、I2C相关数据结构

I2C控制器(例如S3C2440I2C控制器)对应的数据结构是i2c_adapter,i2c_adapter结构定义在include/linux/i2c.h文件中,从注释可以看出,i2c_adapter代表一条物理的I2C总线,同时还包括访问该I2C总线的方法。其内容如下:

409/*
410*i2c_adapteristhestructureusedtoidentifyaphysicali2cbusalong
411*withtheaccessalgorithmsnecessarytoaccessit.
412*/
413structi2c_adapter{
414structmodule*owner;
415unsignedintclass;/*classestoallowprobingfor*/
416conststructi2c_algorithm*algo;/*thealgorithmtoaccessthebus*/
417void*algo_data;
418
419/*datafieldsthatarevalidforalldevices*/
420structrt_mutexbus_lock;
421
422inttimeout;/*injiffies*/
423intretries;
424structdevicedev;/*theadapterdevice*/
425
426intnr;
427charname[48];
428structcompletiondev_released;
429
430structmutexuserspace_clients_lock;
431structlist_headuserspace_clients;
432
433structi2c_bus_recovery_info*bus_recovery_info;
434};


[/code]
i2c_algorithm定义在include/linux/i2c.h文件中,其内容如下:

347/*
348*Thefollowingstructsareforthosewholiketoimplementnewbusdrivers:
349*i2c_algorithmistheinterfacetoaclassofhardwaresolutionswhichcan
350*beaddressedusingthesamebusalgorithms-i.e.bit-bangingorthePCF8584
351*tonametwoofthemostcommon.
352*/
353structi2c_algorithm{
354/*Ifanadapteralgorithmcan'tdoI2C-levelaccess,setmaster_xfer
355toNULL.IfanadapteralgorithmcandoSMBusaccess,set
356smbus_xfer.IfsettoNULL,theSMBusprotocolissimulated
357usingcommonI2Cmessages*/
358/*master_xfershouldreturnthenumberofmessagessuccessfully
359processed,oranegativevalueonerror*/
360int(*master_xfer)(structi2c_adapter*adap,structi2c_msg*msgs,
361intnum);
362int(*smbus_xfer)(structi2c_adapter*adap,u16addr,
363unsignedshortflags,charread_write,
364u8command,intsize,unioni2c_smbus_data*data);
365
366/*Todeterminewhattheadaptersupports*/
367u32(*functionality)(structi2c_adapter*);
368};


[/code]
structi2c_client代表一个I2C设备,该结构体定义在include/linux/i2c.h文件中,其内容如下:

200/**
201*structi2c_client-representanI2Cslavedevice
202*@flags:I2C_CLIENT_TENindicatesthedeviceusesatenbitchipaddress;
203*I2C_CLIENT_PECindicatesitusesSMBusPacketErrorChecking
204*@addr:AddressusedontheI2Cbusconnectedtotheparentadapter.
205*@name:Indicatesthetypeofthedevice,usuallyachipnamethat's
206*genericenoughtohidesecond-sourcingandcompatiblerevisions.
207*@adapter:managesthebussegmenthostingthisI2Cdevice
208*@driver:device'sdriver,hencepointertoaccessroutines
209*@dev:Drivermodeldevicenodefortheslave.
210*@irq:indicatestheIRQgeneratedbythisdevice(ifany)
211*@detected:memberofani2c_driver.clientslistori2c-core's
212*userspace_deviceslist
213*
214*Ani2c_clientidentifiesasingledevice(i.e.chip)connectedtoan
215*i2cbus.ThebehaviourexposedtoLinuxisdefinedbythedriver
216*managingthedevice.
217*/
218structi2c_client{
219unsignedshortflags;/*div.,seebelow*/
220unsignedshortaddr;/*chipaddress-NOTE:7bit*/
221/*addressesarestoredinthe*/
222/*_LOWER_7bits*/
223charname[I2C_NAME_SIZE];
224structi2c_adapter*adapter;/*theadapterwesiton*/
225structi2c_driver*driver;/*andouraccessroutines*/
226structdevicedev;/*thedevicestructure*/
227intirq;/*irqissuedbydevice*/
228structlist_headdetected;
229};


[/code]
structi2c_driver代表一个I2C设备驱动程序,该结构体定义在include/linux/i2c.h文件中,其内容如下:

124/**
125*structi2c_driver-representanI2Cdevicedriver
126*@class:Whatkindofi2cdeviceweinstantiate(fordetect)
127*@attach_adapter:Callbackforbusaddition(deprecated)
128*@probe:Callbackfordevicebinding
129*@remove:Callbackfordeviceunbinding
130*@shutdown:Callbackfordeviceshutdown
131*@suspend:Callbackfordevicesuspend
132*@resume:Callbackfordeviceresume
133*@alert:Alertcallback,forexamplefortheSMBusalertprotocol
134*@command:Callbackforbus-widesignaling(optional)
135*@driver:Devicedrivermodeldriver
136*@id_table:ListofI2Cdevicessupportedbythisdriver
137*@detect:Callbackfordevicedetection
138*@address_list:TheI2Caddressestoprobe(fordetect)
139*@clients:Listofdetectedclientswecreated(fori2c-coreuseonly)
140*
141*Thedriver.ownerfieldshouldbesettothemoduleownerofthisdriver.
142*Thedriver.namefieldshouldbesettothenameofthisdriver.
143*
144*Forautomaticdevicedetection,both@detectand@address_listmust
145*bedefined.@classshouldalsobeset,otherwiseonlydevicesforced
146*withmoduleparameterswillbecreated.Thedetectfunctionmust
147*fillatleastthenamefieldofthei2c_board_infostructureitis
148*handeduponsuccessfuldetection,andpossiblyalsotheflagsfield.
149*
150*If@detectismissing,thedriverwillstillworkfineforenumerated
151*devices.Detecteddevicessimplywon'tbesupported.Thisisexpected
152*forthemanyI2C/SMBusdeviceswhichcan'tbedetectedreliably,and
153*theoneswhichcanalwaysbeenumeratedinpractice.
154*
155*Thei2c_clientstructurewhichishandedtothe@detectcallbackis
156*notareali2c_client.Itisinitializedjustenoughsothatyoucan
157*calli2c_smbus_read_byte_dataandfriendsonit.Don'tdoanything
158*elsewithit.Inparticular,callingdev_dbgandfriendsonitis
159*notallowed.
160*/
161structi2c_driver{
162unsignedintclass;
163
164/*Notifiesthedriverthatanewbushasappeared.Youshouldavoid
165*usingthis,itwillberemovedinanearfuture.
166*/
167int(*attach_adapter)(structi2c_adapter*)__deprecated;
168
169/*Standarddrivermodelinterfaces*/
170int(*probe)(structi2c_client*,conststructi2c_device_id*);
171int(*remove)(structi2c_client*);
172
173/*drivermodelinterfacesthatdon'trelatetoenumeration*/
174void(*shutdown)(structi2c_client*);
175int(*suspend)(structi2c_client*,pm_message_tmesg);
176int(*resume)(structi2c_client*);
177
178/*Alertcallback,forexamplefortheSMBusalertprotocol.
179*Theformatandmeaningofthedatavaluedependsontheprotocol.
180*FortheSMBusalertprotocol,thereisasinglebitofdatapassed
181*asthealertresponse'slowbit("eventflag").
182*/
183void(*alert)(structi2c_client*,unsignedintdata);
184
185/*aioctllikecommandthatcanbeusedtoperformspecificfunctions
186*withthedevice.
187*/
188int(*command)(structi2c_client*client,unsignedintcmd,void*arg);
189
190structdevice_driverdriver;
191conststructi2c_device_id*id_table;
192
193/*Devicedetectioncallbackforautomaticdevicecreation*/
194int(*detect)(structi2c_client*,structi2c_board_info*);
195constunsignedshort*address_list;
196structlist_headclients;
197};


[/code]

二、i2c_adapter的注册

i2c_add_adapter和i2c_add_numbered_adapter函数都可以注册I2Cadapter,这两个函数的区别是,i2c_add_adapter动态分配一个busnumber,而i2c_add_numbered_adapter使用i2c_adapter.nr指定的busnumber。

下面是i2c_add_adapter函数的定义,它定义在drivers/i2c/i2c-core.c文件中,其内容如下:

1099/**
1100*i2c_add_adapter-declarei2cadapter,usedynamicbusnumber
1101*@adapter:theadaptertoadd
1102*Context:cansleep
1103*
1104*ThisroutineisusedtodeclareanI2Cadapterwhenitsbusnumber
1105*doesn'tmatterorwhenitsbusnumberisspecifiedbyandtalias.
1106*Examplesofbaseswhenthebusnumberdoesn'tmatter:I2Cadapters
1107*dynamicallyaddedbyUSBlinksorPCIplugincards.
1108*
1109*Whenthisreturnszero,anewbusnumberwasallocatedandstored
1110*inadap->nr,andthespecifiedadapterbecameavailableforclients.
1111*Otherwise,anegativeerrnovalueisreturned.
1112*/
1113inti2c_add_adapter(structi2c_adapter*adapter)
1114{
1115structdevice*dev=&adapter->dev;
1116intid;
1117
1118if(dev->of_node){
1119id=of_alias_get_id(dev->of_node,"i2c");
1120if(id>=0){
1121adapter->nr=id;
1122return__i2c_add_numbered_adapter(adapter);
1123}
1124}
1125
1126mutex_lock(&core_lock);
1127id=idr_alloc(&i2c_adapter_idr,adapter,
1128__i2c_first_dynamic_bus_num,0,GFP_KERNEL);
1129mutex_unlock(&core_lock);
1130if(id<0)
1131returnid;
1132
1133adapter->nr=id;
1134
1135returni2c_register_adapter(adapter);
1136}


[/code]
1118-1124行,跳过。

1127-1128行,调用idr_alloc动态分配一个idrentry,并用返回的id作为busnumber。

1135行,调用i2c_register_adapter函数。这个函数我们后面再分析。

下面是i2c_add_numbered_adapter函数的定义,它同样定义在drivers/i2c/i2c-core.c文件中,其内容如下:

1139/**
1140*i2c_add_numbered_adapter-declarei2cadapter,usestaticbusnumber
1141*@adap:theadaptertoregister(withadap->nrinitialized)
1142*Context:cansleep
1143*
1144*ThisroutineisusedtodeclareanI2Cadapterwhenitsbusnumber
1145*matters.Forexample,useitforI2Cadaptersfromsystem-on-chipCPUs,
1146*orotherwisebuiltintothesystem'smainboard,andwherei2c_board_info
1147*isusedtoproperlyconfigureI2Cdevices.
1148*
1149*Iftherequestedbusnumberissetto-1,thenthisfunctionwillbehave
1150*identicallytoi2c_add_adapter,andwilldynamicallyassignabusnumber.
1151*
1152*Ifnodeviceshavepre-beendeclaredforthisbus,thenbesureto
1153*registertheadapterbeforeanydynamicallyallocatedones.Otherwise
1154*therequiredbusIDmaynotbeavailable.
1155*
1156*Whenthisreturnszero,thespecifiedadapterbecameavailablefor
1157*clientsusingthebusnumberprovidedinadap->nr.Also,thetable
1158*ofI2Cdevicespre-declaredusingi2c_register_board_info()isscanned,
1159*andtheappropriatedrivermodeldevicenodesarecreated.Otherwise,a
1160*negativeerrnovalueisreturned.
1161*/
1162inti2c_add_numbered_adapter(structi2c_adapter*adap)
1163{
1164if(adap->nr==-1)/*-1meansdynamicallyassignbusid*/
1165returni2c_add_adapter(adap);
1166
1167return__i2c_add_numbered_adapter(adap);
1168}


[/code]
可以看到如果adap->nr的值为-1,则调用i2c_add_adapter动态分配一个busnumber并注册。否则,调用__i2c_add_numbered_adapter函数,该函数定义在drivers/i2c/i2c-core.c文件中,其内容如下:

1078/**
1079*__i2c_add_numbered_adapter-i2c_add_numbered_adapterwherenrisnever-1
1080*@adap:theadaptertoregister(withadap->nrinitialized)
1081*Context:cansleep
1082*
1083*Seei2c_add_numbered_adapter()fordetails.
1084*/
1085staticint__i2c_add_numbered_adapter(structi2c_adapter*adap)
1086{
1087intid;
1088
1089mutex_lock(&core_lock);
1090id=idr_alloc(&i2c_adapter_idr,adap,adap->nr,adap->nr+1,
1091GFP_KERNEL);
1092mutex_unlock(&core_lock);
1093if(id<0)
1094returnid==-ENOSPC?-EBUSY:id;
1095
1096returni2c_register_adapter(adap);
1097}


[/code]
1090行,调用idr_alloc函数用指定的daap->nr作为busnumber分配一个idrentry。

1096行,调用i2c_register_adapter函数。

所以,不论是用i2c_add_adapter还是用i2c_add_numbered_adapter函数注册i2c_adapter,最终都会调用i2c_register_adapter函数完成注册。

i2c_register_adapter函数定义在drivers/i2c/i2c-core.c文件中,其内容如下:

980staticinti2c_register_adapter(structi2c_adapter*adap)
981{
982intres=0;
983
984/*Can'tregisteruntilafterdrivermodelinit*/
985if(unlikely(WARN_ON(!i2c_bus_type.p))){
986res=-EAGAIN;
987gotoout_list;
988}
989
990/*Sanitychecks*/
991if(unlikely(adap->name[0]=='\0')){
992pr_err("i2c-core:Attempttoregisteranadapterwith"
993"noname!\n");
994return-EINVAL;
995}
996if(unlikely(!adap->algo)){
997pr_err("i2c-core:Attempttoregisteradapter'%s'with"
998"noalgo!\n",adap->name);
999return-EINVAL;
1000}
1001
1002rt_mutex_init(&adap->bus_lock);
1003mutex_init(&adap->userspace_clients_lock);
1004INIT_LIST_HEAD(&adap->userspace_clients);
1005
1006/*Setdefaulttimeoutto1secondifnotalreadyset*/
1007if(adap->timeout==0)
1008adap->timeout=HZ;
1009
1010dev_set_name(&adap->dev,"i2c-%d",adap->nr);
1011adap->dev.bus=&i2c_bus_type;
1012adap->dev.type=&i2c_adapter_type;
1013res=device_register(&adap->dev);
1014if(res)
1015gotoout_list;
1016
1017dev_dbg(&adap->dev,"adapter[%s]registered\n",adap->name);
1018
1019#ifdefCONFIG_I2C_COMPAT
1020res=class_compat_create_link(i2c_adapter_compat_class,&adap->dev,
1021adap->dev.parent);
1022if(res)
1023dev_warn(&adap->dev,
1024"Failedtocreatecompatibilityclasslink\n");
1025#endif
1026
1027/*busrecoveryspecificinitialization*/
1028if(adap->bus_recovery_info){
1029structi2c_bus_recovery_info*bri=adap->bus_recovery_info;
1030
1031if(!bri->recover_bus){
1032dev_err(&adap->dev,"Norecover_bus()found,notusingrecovery\n");
1033adap->bus_recovery_info=NULL;
1034gotoexit_recovery;
1035}
1036
1037/*GenericGPIOrecovery*/
1038if(bri->recover_bus==i2c_generic_gpio_recovery){
1039if(!gpio_is_valid(bri->scl_gpio)){
1040dev_err(&adap->dev,"InvalidSCLgpio,notusingrecovery\n");
1041adap->bus_recovery_info=NULL;
1042gotoexit_recovery;
1043}
1044
1045if(gpio_is_valid(bri->sda_gpio))
1046bri->get_sda=get_sda_gpio_value;
1047else
1048bri->get_sda=NULL;
1049
1050bri->get_scl=get_scl_gpio_value;
1051bri->set_scl=set_scl_gpio_value;
1052}elseif(!bri->set_scl||!bri->get_scl){
1053/*GenericSCLrecovery*/
1054dev_err(&adap->dev,"No{get|set}_gpio()found,notusingrecovery\n");
1055adap->bus_recovery_info=NULL;
1056}
1057}
1058
1059exit_recovery:
1060/*createpre-declareddevicenodes*/
1061if(adap->nr<__i2c_first_dynamic_bus_num)
1062i2c_scan_static_board_info(adap);
1063
1064/*Notifydrivers*/
1065mutex_lock(&core_lock);
1066bus_for_each_drv(&i2c_bus_type,NULL,adap,__process_new_adapter);
1067mutex_unlock(&core_lock);
1068
1069return0;
1070
1071out_list:
1072mutex_lock(&core_lock);
1073idr_remove(&i2c_adapter_idr,adap->nr);
1074mutex_unlock(&core_lock);
1075returnres;
1076}


[/code]
984-1013行,完成基本的检查和初始化工作后,注册i2c_adapter.dev。

1027-1059行,如果有必要,为busrecovery作一些准备工作。

1060-1062行,如果有预先声明的i2c设备,则注册对应的i2c_client。

先看1061行,判断adap->nr是否小于__i2c_first_dynamic_bus_num,只有是使用i2c_add_numbered_adapter注册i2c_adapter时,该判断才会成立。用i2c_add_adapter函数注册i2c_adapter时,动态分配的busnumber一定是大于或等于__i2c_first_dynamic_bus_num的。

如果1061行的判断成立,说明是使用预先定义的busnumber,因此,就可能会有预置的I2C设备信息。所以1062行,调用i2c_scan_static_board_info函数,遍历预置I2C设备信息列表,创建对应的i2c_client。

i2c_scan_static_board_info函数定义在drivers/i2c/i2c-core.c文件中,其内容如下:

941staticvoidi2c_scan_static_board_info(structi2c_adapter*adapter)
942{
943structi2c_devinfo*devinfo;
944
945down_read(&__i2c_board_lock);
946list_for_each_entry(devinfo,&__i2c_board_list,list){
947if(devinfo->busnum==adapter->nr
948&&!i2c_new_device(adapter,
949&devinfo->board_info))
950dev_err(&adapter->dev,
951"Can'tcreatedeviceat0x%02x\n",
952devinfo->board_info.addr);
953}
954up_read(&__i2c_board_lock);
955}


[/code]
该函数遍历__i2c_board_list链表,如果某个节点的devinfo->busnum等于adapter->nr,即该I2C设备属于这个注册的I2Cadapter,则调用i2c_new_device创建并注册该I2C设备对应的i2c_client。

i2c_new_device定义在drivers/i2c/i2c-core.c文件中,其内容如下:

612/**
613*i2c_new_device-instantiateani2cdevice
614*@adap:theadaptermanagingthedevice
615*@info:describesoneI2Cdevice;bus_numisignored
616*Context:cansleep
617*
618*Createani2cdevice.Bindingishandledthroughdrivermodel
619*probe()/remove()methods.Adrivermaybeboundtothisdevicewhenwe
620*returnfromthisfunction,oranylatermoment(e.g.maybehotpluggingwill
621*loadthedrivermodule).Thiscallisnotappropriateforusebymainboard
622*initializationlogic,whichusuallyrunsduringanarch_initcall()long
623*beforeanyi2c_adaptercouldexist.
624*
625*Thisreturnsthenewi2cclient,whichmaybesavedforlaterusewith
626*i2c_unregister_device();orNULLtoindicateanerror.
627*/
628structi2c_client*
629i2c_new_device(structi2c_adapter*adap,structi2c_board_infoconst*info)
630{
631structi2c_client*client;
632intstatus;
633
634client=kzalloc(sizeof*client,GFP_KERNEL);
635if(!client)
636returnNULL;
637
638client->adapter=adap;
639
640client->dev.platform_data=info->platform_data;
641
642if(info->archdata)
643client->dev.archdata=*info->archdata;
644
645client->flags=info->flags;
646client->addr=info->addr;
647client->irq=info->irq;
648
649strlcpy(client->name,info->type,sizeof(client->name));
650
651/*Checkforaddressvalidity*/
652status=i2c_check_client_addr_validity(client);
653if(status){
654dev_err(&adap->dev,"Invalid%d-bitI2Caddress0x%02hx\n",
655client->flags&I2C_CLIENT_TEN?10:7,client->addr);
656gotoout_err_silent;
657}
658
659/*Checkforaddressbusiness*/
660status=i2c_check_addr_busy(adap,client->addr);
661if(status)
662gotoout_err;
663
664client->dev.parent=&client->adapter->dev;
665client->dev.bus=&i2c_bus_type;
666client->dev.type=&i2c_client_type;
667client->dev.of_node=info->of_node;
668ACPI_HANDLE_SET(&client->dev,info->acpi_node.handle);
669
670/*For10-bitclients,addanarbitraryoffsettoavoidcollisions*/
671dev_set_name(&client->dev,"%d-%04x",i2c_adapter_id(adap),
672client->addr|((client->flags&I2C_CLIENT_TEN)
673?0xa000:0));
674status=device_register(&client->dev);
675if(status)
676gotoout_err;
677
678dev_dbg(&adap->dev,"client[%s]registeredwithbusid%s\n",
679client->name,dev_name(&client->dev));
680
681returnclient;
682
683out_err:
684dev_err(&adap->dev,"Failedtoregisteri2cclient%sat0x%02x"
685"(%d)\n",client->name,client->addr,status);
686out_err_silent:
687kfree(client);
688returnNULL;
689}


[/code]
这个函数很直接,就是初始化i2c_client的各个成员,并最终注册client->dev,从而完成对i2c设备的注册。

这里要说明一下,预置的i2c设备信息是通过调用i2c_register_board_info函数完成的,该函数定义在drivers/i2c/i2c-boardinfo.c文件中,其内容如下:

42/**
43*i2c_register_board_info-staticallydeclareI2Cdevices
44*@busnum:identifiesthebustowhichthesedevicesbelong
45*@info:vectorofi2cdevicedescriptors
46*@len:howmanydescriptorsinthevector;maybezerotoreserve
47*thespecifiedbusnumber.
48*
49*SystemsusingtheLinuxI2Cdriverstackcandeclaretablesofboardinfo
50*whiletheyinitialize.Thisshouldbedoneinboard-specificinitcode
51*neararch_initcall()time,orequivalent,beforeanyI2Cadapterdriveris
52*registered.Forexample,mainboardinitcodecoulddefineseveraldevices,
53*ascouldtheinitcodeforeachdaughtercardinaboardstack.
54*
55*TheI2Cdeviceswillbecreatedlater,aftertheadapterfortherelevant
56*bushasbeenregistered.Afterthatmoment,standarddrivermodeltools
57*areusedtobind"newstyle"I2Cdriverstothedevices.Thebusnumber
58*foranydevicedeclaredusingthisroutineisnotavailablefordynamic
59*allocation.
60*
61*Theboardinfopassedcansafelybe__initdata,butbecarefulofembedded
62*pointers(forplatform_data,functions,etc)sincethatwon'tbecopied.
63*/
64int__init
65i2c_register_board_info(intbusnum,
66structi2c_board_infoconst*info,unsignedlen)
67{
68intstatus;
69
70down_write(&__i2c_board_lock);
71
72/*dynamicbusnumberswillbeassignedafterthelaststaticone*/
73if(busnum>=__i2c_first_dynamic_bus_num)
74__i2c_first_dynamic_bus_num=busnum+1;
75
76for(status=0;len;len--,info++){
77structi2c_devinfo*devinfo;
78
79devinfo=kzalloc(sizeof(*devinfo),GFP_KERNEL);
80if(!devinfo){
81pr_debug("i2c-core:can'tregisterboardinfo!\n");
82status=-ENOMEM;
83break;
84}
85
86devinfo->busnum=busnum;
87devinfo->board_info=*info;
88list_add_tail(&devinfo->list,&__i2c_board_list);
89}
90
91up_write(&__i2c_board_lock);
92
93returnstatus;
94}


[/code]
可以看到,该函数将预置的i2c设备信息保存在__i2c_board_list链表中。

回到i2c_register_adapter函数:

1066行,调用bus_for_each_drv函数,该函数定义在drivers/base/bus.c文件中,其内容如下:

417/**
418*bus_for_each_drv-driveriterator
419*@bus:buswe'redealingwith.
420*@start:drivertostartiteratingon.
421*@data:datatopasstothecallback.
422*@fn:functiontocallforeachdriver.
423*
424*Thisisnearlyidenticaltothedeviceiteratorabove.
425*Weiterateovereachdriverthatbelongsto@bus,andcall
426*@fnforeach.If@fnreturnsanythingbut0,webreakout
427*andreturnit.If@startisnotNULL,weuseitasthehead
428*ofthelist.
429*
430*NOTE:wedon'treturnthedriverthatreturnsanon-zero
431*value,nordoweleavethereferencecountincrementedforthat
432*driver.Ifthecallerneedstoknowthatinfo,itmustsetit
433*inthecallback.Itmustalsobesuretoincrementtherefcount
434*soitdoesn'tdisappearbeforereturningtothecaller.
435*/
436intbus_for_each_drv(structbus_type*bus,structdevice_driver*start,
437void*data,int(*fn)(structdevice_driver*,void*))
438{
439structklist_iteri;
440structdevice_driver*drv;
441interror=0;
442
443if(!bus)
444return-EINVAL;
445
446klist_iter_init_node(&bus->p->klist_drivers,&i,
447start?&start->p->knode_bus:NULL);
448while((drv=next_driver(&i))&&!error)
449error=fn(drv,data);
450klist_iter_exit(&i);
451returnerror;
452}


[/code]
这个函数我们在《Linux设备模型分析之device(基于3.10.1内核)》一文中已经分析过了。448-449行,这个while循环依次遍历bus->p->klist_drivers中的所有device_driver,对于每个device_driver,调用fn(drv,data)函数。这里,传递过来的fn参数是__process_new_adapter,data参数是adap。这个循环是一个关键点,注册一个新的i2c_adapter后,要为该i2c_adapter上的i2c设备匹配驱动程序,这个匹配过程就是通过这个循环调用__process_new_adapter函数完成的。

__process_new_adapter函数定义在drivers/i2c/i2c-core.c文件中,其内容如下:

975staticint__process_new_adapter(structdevice_driver*d,void*data)
976{
977returni2c_do_add_adapter(to_i2c_driver(d),data);
978}


[/code]
注意i2c_do_add_adapter函数的第一个参数,从device_driver转换为i2c_driver。

i2c_do_add_adapter函数定义在drivers/i2c/i2c-core.c文件中,其内容如下:

957staticinti2c_do_add_adapter(structi2c_driver*driver,
958structi2c_adapter*adap)
959{
960/*Detectsupporteddevicesonthatbus,andinstantiatethem*/
961i2c_detect(adap,driver);
962
963/*Letlegacydriversscanthisbusformatchingdevices*/
964if(driver->attach_adapter){
965dev_warn(&adap->dev,"%s:attach_adaptermethodisdeprecated\n",
966driver->driver.name);
967dev_warn(&adap->dev,"Pleaseuseanotherwaytoinstantiate"
968"youri2c_client\n");
969/*Weignorethereturncode;ifitfails,toobad*/
970driver->attach_adapter(adap);
971}
972return0;
973}


[/code]
961行,调用i2c_detect函数,探测并初始化该i2c总线上的i2c设备。该函数定义在drivers/i2c/i2c-core.c文件中,其内容如下:

1730staticinti2c_detect(structi2c_adapter*adapter,structi2c_driver*driver)
1731{
1732constunsignedshort*address_list;
1733structi2c_client*temp_client;
1734inti,err=0;
1735intadap_id=i2c_adapter_id(adapter);
1736
1737address_list=driver->address_list;
1738if(!driver->detect||!address_list)
1739return0;
1740
1741/*Stophereiftheclassesdonotmatch*/
1742if(!(adapter->class&driver->class))
1743return0;
1744
1745/*Setupatemporaryclienttohelpdetectcallback*/
1746temp_client=kzalloc(sizeof(structi2c_client),GFP_KERNEL);
1747if(!temp_client)
1748return-ENOMEM;
1749temp_client->adapter=adapter;
1750
1751for(i=0;address_list[i]!=I2C_CLIENT_END;i+=1){
1752dev_dbg(&adapter->dev,"foundnormalentryforadapter%d,"
1753"addr0x%02x\n",adap_id,address_list[i]);
1754temp_client->addr=address_list[i];
1755err=i2c_detect_address(temp_client,driver);
1756if(unlikely(err))
1757break;
1758}
1759
1760kfree(temp_client);
1761returnerr;
1762}


[/code]
1755行,调用i2c_detect_address,探测指定的地址上的I2C设备是否存在,如果存在,注册该i2c设备。i2c_detect_address函数定义在drivers/i2c/i2c-core.c文件中,其内容如下:

1675staticinti2c_detect_address(structi2c_client*temp_client,
1676structi2c_driver*driver)
1677{
1678structi2c_board_infoinfo;
1679structi2c_adapter*adapter=temp_client->adapter;
1680intaddr=temp_client->addr;
1681interr;
1682
1683/*Makesuretheaddressisvalid*/
1684err=i2c_check_addr_validity(addr);
1685if(err){
1686dev_warn(&adapter->dev,"Invalidprobeaddress0x%02x\n",
1687addr);
1688returnerr;
1689}
1690
1691/*Skipifalreadyinuse*/
1692if(i2c_check_addr_busy(adapter,addr))
1693return0;
1694
1695/*Makesurethereissomethingatthisaddress*/
1696if(!i2c_default_probe(adapter,addr))
1697return0;
1698
1699/*Finallycallthecustomdetectionfunction*/
1700memset(&info,0,sizeof(structi2c_board_info));
1701info.addr=addr;
1702err=driver->detect(temp_client,&info);
1703if(err){
1704/*-ENODEVisreturnedifthedetectionfails.Wecatchit
1705hereasthisisn'tanerror.*/
1706returnerr==-ENODEV?0:err;
1707}
1708
1709/*Consistencycheck*/
1710if(info.type[0]=='\0'){
1711dev_err(&adapter->dev,"%sdetectionfunctionprovided"
1712"nonamefor0x%x\n",driver->driver.name,
1713addr);
1714}else{
1715structi2c_client*client;
1716
1717/*Detectionsucceeded,instantiatethedevice*/
1718dev_dbg(&adapter->dev,"Creating%sat0x%02x\n",
1719info.type,info.addr);
1720client=i2c_new_device(adapter,&info);
1721if(client)
1722list_add_tail(&client->detected,&driver->clients);
1723else
1724dev_err(&adapter->dev,"Failedcreating%sat0x%02x\n",
1725info.type,info.addr);
1726}
1727return0;
1728}


[/code]
1702行,调用driver->detect。

1720行,如果探测到i2c设备确实存在,调用i2c_new_device函数初始化对应的i2c_client结构体并注册。i2c_new_device函数我们在前面已经分析过。

至此,i2c_adapter的注册过程我们就清楚了。


三、i2c_driver的注册

i2c_driver的注册是通过调用i2c_add_driver宏完成的,该宏定义在include/linux/i2c.h文件中:

497/*useadefinetoavoidincludechainingtogetTHIS_MODULE*/
498#definei2c_add_driver(driver)\
499i2c_register_driver(THIS_MODULE,driver)


[/code]
i2c_register_driver函数定义在drivers/i2c/i2c-core.c文件中,其内容如下:

1307/*
1308*Ani2c_driverisusedwithoneormorei2c_client(device)nodestoaccess
1309*i2cslavechips,onabusinstanceassociatedwithsomei2c_adapter.
1310*/
1311
1312inti2c_register_driver(structmodule*owner,structi2c_driver*driver)
1313{
1314intres;
1315
1316/*Can'tregisteruntilafterdrivermodelinit*/
1317if(unlikely(WARN_ON(!i2c_bus_type.p)))
1318return-EAGAIN;
1319
1320/*addthedrivertothelistofi2cdriversinthedrivercore*/
1321driver->driver.owner=owner;
1322driver->driver.bus=&i2c_bus_type;
1323
1324/*Whenregistrationreturns,thedrivercore
1325*willhavecalledprobe()forallmatching-but-unbounddevices.
1326*/
1327res=driver_register(&driver->driver);
1328if(res)
1329returnres;
1330
1331/*Driversshouldswitchtodev_pm_opsinstead.*/
1332if(driver->suspend)
1333pr_warn("i2c-core:driver[%s]usinglegacysuspendmethod\n",
1334driver->driver.name);
1335if(driver->resume)
1336pr_warn("i2c-core:driver[%s]usinglegacyresumemethod\n",
1337driver->driver.name);
1338
1339pr_debug("i2c-core:driver[%s]registered\n",driver->driver.name);
1340
1341INIT_LIST_HEAD(&driver->clients);
1342/*Walktheadaptersthatarealreadypresent*/
1343i2c_for_each_dev(driver,__process_new_driver);
1344
1345return0;
1346}


[/code]
1327行,调用driver_register注册i2c_driver.driver。参考《Linux设备模型分析之device_driver(基于3.10.1内核)》对Linux设备模型的分析,在driver_register执行过程中,如果I2C总线上找到了与该驱动匹配的I2C设备,则i2c_driver.probe函数会被调用执行。

1343行,调用i2c_for_each_dev遍历所有已存在的i2c_adapter。该函数定义在drivers/i2c/i2c-core.c文件中,其内容如下:

1288inti2c_for_each_dev(void*data,int(*fn)(structdevice*,void*))
1289{
1290intres;
1291
1292mutex_lock(&core_lock);
1293res=bus_for_each_dev(&i2c_bus_type,NULL,data,fn);
1294mutex_unlock(&core_lock);
1295
1296returnres;
1297}


[/code]
1293行,调用bus_for_each_dev,这个函数定义在drivers/base/bus.c文件中,其内容如下:

286intbus_for_each_dev(structbus_type*bus,structdevice*start,
287void*data,int(*fn)(structdevice*,void*))
288{
289structklist_iteri;
290structdevice*dev;
291interror=0;
292
293if(!bus||!bus->p)
294return-EINVAL;
295
296klist_iter_init_node(&bus->p->klist_devices,&i,
297(start?&start->p->knode_bus:NULL));
298while((dev=next_device(&i))&&!error)
299error=fn(dev,data);
300klist_iter_exit(&i);
301returnerror;
302}


我们在《Linux设备模型分析之device_driver(基于3.10.1内核)》一文中已经分析过这个函数。这里,传递过来的data参数是要注册的i2c_driver,fn参数是__process_new_driver函数,所以我们来看__process_new_driver函数,该函数定义在drivers/i2c/i2c-core.c文件中,其内容如下:

1300staticint__process_new_driver(structdevice*dev,void*data)
1301{
1302if(dev->type!=&i2c_adapter_type)
1303return0;
1304returni2c_do_add_adapter(data,to_i2c_adapter(dev));
1305}


i2c_do_add_adapter函数定义在drivers/i2c/i2c-core.c文件中,其内容如下:

957staticinti2c_do_add_adapter(structi2c_driver*driver,
958structi2c_adapter*adap)
959{
960/*Detectsupporteddevicesonthatbus,andinstantiatethem*/
961i2c_detect(adap,driver);
962
963/*Letlegacydriversscanthisbusformatchingdevices*/
964if(driver->attach_adapter){
965dev_warn(&adap->dev,"%s:attach_adaptermethodisdeprecated\n",
966driver->driver.name);
967dev_warn(&adap->dev,"Pleaseuseanotherwaytoinstantiate"
968"youri2c_client\n");
969/*Weignorethereturncode;ifitfails,toobad*/
970driver->attach_adapter(adap);
971}
972return0;
973}


这个函数我们在分析i2c_adapter的注册过程时已经分析过了,它主要完成i2c_driver与i2c_adapter上的i2c设备的匹配工作,如果匹配成功,初始化并注册对应的i2c_client。

至此,i2c_driver的注册过程我们就清楚了。



四、i2c_bus_type分析

i2c_init函数完成Linuxi2c框架的初始化工作,该函数定义在drivers/i2c/i2c-core.c文件中,其内容如下:

1429staticint__initi2c_init(void)
1430{
1431intretval;
1432
1433retval=bus_register(&i2c_bus_type);
1434if(retval)
1435returnretval;
1436#ifdefCONFIG_I2C_COMPAT
1437i2c_adapter_compat_class=class_compat_register("i2c-adapter");
1438if(!i2c_adapter_compat_class){
1439retval=-ENOMEM;
1440gotobus_err;
1441}
1442#endif
1443retval=i2c_add_driver(&dummy_driver);
1444if(retval)
1445gotoclass_err;
1446return0;
1447
1448class_err:
1449#ifdefCONFIG_I2C_COMPAT
1450class_compat_unregister(i2c_adapter_compat_class);
1451bus_err:
1452#endif
1453bus_unregister(&i2c_bus_type);
1454returnretval;
1455}


1433行,调用bus_register注册了i2c_bus_type。i2c_bus_tpye定义在drivers/i2c/i2c-core.c文件中,其内容如下:

442structbus_typei2c_bus_type={
443.name="i2c",
444.match=i2c_device_match,
445.probe=i2c_device_probe,
446.remove=i2c_device_remove,
447.shutdown=i2c_device_shutdown,
448.pm=&i2c_device_pm_ops,
449};


其类型是bus_type,所以它代表i2c总线。我们来关注一下i2c_device_match和i2c_device_probe函数。

i2c_device_match函数定义在drivers/i2c/i2c-core.c文件中,其内容如下:

72staticinti2c_device_match(structdevice*dev,structdevice_driver*drv)
73{
74structi2c_client*client=i2c_verify_client(dev);
75structi2c_driver*driver;
76
77if(!client)
78return0;
79
80/*AttemptanOFstylematch*/
81if(of_driver_match_device(dev,drv))
82return1;
83
84/*ThenACPIstylematch*/
85if(acpi_driver_match_device(dev,drv))
86return1;
87
88driver=to_i2c_driver(drv);
89/*matchonanidtableifthereisone*/
90if(driver->id_table)
91returni2c_match_id(driver->id_table,client)!=NULL;
92
93return0;
94}


88行,将device_driver转换为i2c_driver。

90-91行,如果driver->id_table不为空,则调用i2c_match_id函数,该函数定义在drivers/i2c/i2c-core.c文件中,其内容如下:

61staticconststructi2c_device_id*i2c_match_id(conststructi2c_device_id*id,
62conststructi2c_client*client)
63{
64while(id->name[0]){
65if(strcmp(client->name,id->name)==0)
66returnid;
67id++;
68}
69returnNULL;
70}


可以看到,如果client->name和id->name相同,则匹配成功,返回id。如果返回NULL,则表示匹配失败。

分析到这里,我们要回顾一下分析Linux设备模型时涉及到的一个函数driver_match_device,该函数定义在drivers/base/base.h文件中,其内容如下:

116staticinlineintdriver_match_device(structdevice_driver*drv,
117structdevice*dev)
118{
119returndrv->bus->match?drv->bus->match(dev,drv):1;
120}


当进行device和device_driver的匹配时,会调用这个函数,该函数返回值为0,表示match失败。只有match成功时,才会进一步进行probe。

可以看到,如果drv->bus->match存在,会调用drv->bus->match(dev,drv)。所以,当i2c设备(i2c_client)和i2c驱动(i2c_driver)进行匹配操作时,就会调用i2c_device_match函数。

在分析i2c_device_probe函数之前,我们要回顾一下分析Linux设备模型时涉及到的一个函数driver_probe_device,device_driver探测支持的device时,会调用到这个函数,它又会进一步调用really_probe函数,really_probe函数定义在drivers/base/dd.c文件中,其内容如下:

265staticintreally_probe(structdevice*dev,structdevice_driver*drv)
266{
267intret=0;
268
269atomic_inc(&probe_count);
270pr_debug("bus:'%s':%s:probingdriver%swithdevice%s\n",
271drv->bus->name,__func__,drv->name,dev_name(dev));
272WARN_ON(!list_empty(&dev->devres_head));
273
274dev->driver=drv;
275
276/*Ifusingpinctrl,bindpinsnowbeforeprobing*/
277ret=pinctrl_bind_pins(dev);
278if(ret)
279gotoprobe_failed;
280
281if(driver_sysfs_add(dev)){
282printk(KERN_ERR"%s:driver_sysfs_add(%s)failed\n",
283__func__,dev_name(dev));
284gotoprobe_failed;
285}
286
287if(dev->bus->probe){
288ret=dev->bus->probe(dev);
289if(ret)
290gotoprobe_failed;
291}elseif(drv->probe){
292ret=drv->probe(dev);
293if(ret)
294gotoprobe_failed;
295}
296
297driver_bound(dev);
298ret=1;
299pr_debug("bus:'%s':%s:bounddevice%stodriver%s\n",
300drv->bus->name,__func__,dev_name(dev),drv->name);
301gotodone;
302
303probe_failed:
304devres_release_all(dev);
305driver_sysfs_remove(dev);
306dev->driver=NULL;
307dev_set_drvdata(dev,NULL);
308
309if(ret==-EPROBE_DEFER){
310/*Driverrequesteddeferredprobing*/
311dev_info(dev,"Driver%srequestsprobedeferral\n",drv->name);
312driver_deferred_probe_add(dev);
313}elseif(ret!=-ENODEV&&ret!=-ENXIO){
314/*drivermatchedbuttheprobefailed*/
315printk(KERN_WARNING
316"%s:probeof%sfailedwitherror%d\n",
317drv->name,dev_name(dev),ret);
318}else{
319pr_debug("%s:probeof%srejectsmatch%d\n",
320drv->name,dev_name(dev),ret);
321}
322/*
323*Ignoreerrorsreturnedby->probesothatthenextdrivercantry
324*itsluck.
325*/
326ret=0;
327done:
328atomic_dec(&probe_count);
329wake_up(&probe_waitqueue);
330returnret;
331}


这个函数我们现在需要关注的是287-295行,如果dev->bus->probe存在,则调用dev->bus->probe(dev),如果dev->bus->probe不存在,并且drv->probe存在,才会调用drv->probe(dev)。所以,对于i2c设备和i2c驱动,探测设备时会优先调用i2c_bus_type.probe函数。而i2c_bus_type.probe即i2c_device_probe会转而调用i2c_driver.probe函数。

现在我们可以来看i2c_device_probe函数了,它定义在drivers/i2c/i2c-core.c文件中,其内容如下:

233staticinti2c_device_probe(structdevice*dev)
234{
235structi2c_client*client=i2c_verify_client(dev);
236structi2c_driver*driver;
237intstatus;
238
239if(!client)
240return0;
241
242driver=to_i2c_driver(dev->driver);
243if(!driver->probe||!driver->id_table)
244return-ENODEV;
245client->driver=driver;
246if(!device_can_wakeup(&client->dev))
247device_init_wakeup(&client->dev,
248client->flags&I2C_CLIENT_WAKE);
249dev_dbg(dev,"probe\n");
250
251status=driver->probe(client,i2c_match_id(driver->id_table,client));
252if(status){
253client->driver=NULL;
254i2c_set_clientdata(client,NULL);
255}
256returnstatus;
257}


242行,取得i2c_driver。

243行,如果i2c_driver没有定义probe或者i2c_driver没有定义id_table,则直接退出。所以我们在写i2c驱动时,必须定义i2c_driver.probe和i2c_driver.id_table。

251行,调用i2c_driver.probe。这时,我们的i2c驱动程序定义的probe函数就会执行。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: