プラットフォーム設備登録プロセスplotform_add_devices()plotform_driver_レジスター

8289 ワード

来た:http://www.diybl.com/course/6_system/linux/Linuxjs/200871/129585.
から Linux 2.6 新しいドライバ管理と登録メカニズムを導入しました。 :Platform_device 和 Platform_driver 。
     Linux のほとんどのデバイスドライバは、このメカニズムを使用することができます。 , デバイス Platform_device 表示する Platform_driver 登録します
    Linux plotform driver 構造と伝統の device driver 構造 ( 通過する driverage gister 関数を登録します ) 対照的に、非常に明確な利点は plotform メカニズムは、デバイス自身のリソースをカーネルに登録し、カーネルによって統一的に管理され、ドライバでこれらのリソースを使用するときに、 plotform device 提供された標準インターフェースは申請されて使用されます。これにより駆動と資源管理の独立性が向上し、より良い移植性と安全性が得られます。 ( これらの標準インターフェースは安全です。 ) 。
    Platform メカニズム自体の使用は複雑ではなく、二つの部分から構成されています。 プラットフォーム 和 プラットフロム 。
    通過する Platform メカニズム開発の下側駆動の大まかな流れは : 定義 プラットフォーム -> 登録する プラットフォーム-> 定義 プラットフォーム 登録する プラットフォーム 。
    まず確認するのは、デバイスのリソース情報、例えば、デバイスのアドレス、中断番号などです。
はい、 2.6 カーネル中 plotform デバイス用構造体 プラットフォーム を選択して説明します。 ケネル\include\linux\plotformu.h にあります
struct plot formudevice{
const char*name;
u 32 id;
struct device dev;
u 32 num ture sources
struct resource*resource;

    この構造の重要な要素は resource ,この要素は最も重要な設備資源情報を保存しています。 ケネル\include\linux\ioport.h にあります
struct resource{
const char*name;
unsigned long start,end;
unsigned long flags;
struct resource*parent、*sibling、*child;

下に挙げます s 3 c 2410 プラットフォームの i 2 c ドライバを例として説明します。/*arch/arm/mach-s 3 c 2410/devs.c*/  /* I 2 C*/  static struct resource[ ] = {           [ 0) = {                     . start = S 3 C 24 xxxuPA IIC、                     . end = S 3 C 24 xxxxuPA IIC + S 3 C 24 xxxuSZuIIC - 1,                     . flags = IORESOURCEM           } ,           [ 1) = {                     . start = IRQUIIC、 //S 3 C 2410_IRQ(27)                     . end = IRQUIIC、                     . flags = IORESOURCEUIRQ           }  } ;
ここで二つのグループを定義します。 resource ,それは一つのことを述べています I 2 C 設備の資源,第 1 グループはこれを記述しています I 2 C デバイスが占有するバスアドレス範囲、 IORESOURCEM 表示第 1 グループはメモリタイプのリソース情報を記述しています。 2 グループはこれを記述しています I 2 C 設備の中断番号、 IORESOURCEIRQ 表示第 2 グループはリソース情報を中断します。デバイスドライバは、 flags を選択します。
あります resource 情報を定義することができます。 プラットフォーム 終了:
struct plotformudevice s 3 cudviceu 2 c = {           . name = “s 3 c 2410-i 2 c” ,           . id。 = - 1,           . num ture sources = ARRAYUSIZE( s 3 cui 2 ccuurce) ,           . resource = s 3 cui 2 ccuurce、  } ;
 定義しました プラットフォーム 構造体の後で関数を呼び出すことができます。 プラットフォーム システムにこのデバイスを追加しました。その後、起動できます。 プラットフォーム デバイス登録を行います。注意することは、ここの プラットフォーム デバイスの登録プロセスは、それぞれのデバイスの駆動ローディングの前に呼び出しられ、すなわち実行されなければならない。 プラットフォーム 前に , ドライバ登録時にカーネルにマッチする必要があるため、登録済みのデバイス名が必要です。
    s 3 c 2410-i 2 c の プラットフォーム システム起動時に、 cpu.c の中の s 3 ccusurhuinit() 関数に登録されていますが、この関数は アルchuinit call(s 3 ccarhuinit); システム初期化段階で呼び出されます。 。
    アーchuinit call の優先度が高い module init 。だからここにいます Platform ドライバ登録前に呼び出します。 ( 詳細な参照 include/linux/init.h)
s 3 ccurhuinit 関数は以下の通りです
*arch/arm/mach-3 sc 2410/cpu.c*/  static 要点 __init s 3 ccurhuinit( void )  {      要点 ret;       …… /* ここでboardポインタは、mach-smdk 2410 cで定義されているsdk 2410 ubroardを指し、予め定義されているI 2 C Platformudviceなどが含まれています。      if ( board ! = NULL ) {          struct プラットフォーム * * ptr = board- > devices;          要点 i;          for ( i = 0; i < board- > devices ucount; i+ + , ptr+ + ) {               ret = プラットフォーム * ptr) ;      //ここで登録します。            if ( ret) {                   printk KERNuERR 「s 3 c 24 xx:failed to add board device%s(%d)@%p」 , ( * ptr) - > name  レイト、 * ptr) ;              }          }           /* mask any error,we may not need all these board         * devices*/           ret = 0;      }      return ret;  } 
同時に登録されて他のプラットフォームもたくさんあります。 プラットフォーム ,詳細を見る arch/arm/mach-s 3 c 2410/mach-sdk 2410.c の中の smdk 2410. 構造体
ドライバは構造体を実現する必要があります。 struct plot formudiver ,参照 drivers/i 2 c/busses/* device driver for platform bus bits */
static struct platform_driver s3c2410_i2c_driver = { 
         . probe = s3c24xx_i2c_probe, 
         . remove = s3c24xx_i2c_remove, 
         . resume = s3c24xx_i2c_resume, 
         . driver = { 
                   . owner = THIS_MODULE, 
                   . name = "s3c2410-i2c" , 
         } , 
} ;
ドライバ初期化関数で関数を呼び出します。 プラットフォーム 登録する プラットフォーム ,注意したいのは s 3 cudviceu 2 c 構造中 name 元素と s 3 c 2410クラウド 構造中 driver.name 同じものでなければなりません。 このように プラットフォーム 登録するときは登録済みのすべてのものに対して プラットフォーム 的に命中する nameと現在登録されている プラットフォーム の driver.name 比較すると、同じ名前を見つけたのは plotfomrudevice 登録が成功しました。登録が成功したら呼び出します。 プラットフォーム 構造要素 probe 関数ポインタ、 ここです s 3 c 24 xui 2 cuprobe、 に入る probe 関数を使用すると、デバイスのリソース情報を取得する必要があります。 ,よく使われるリソースの関数は主に以下の通りです。
struct reource*plot formurce(struct plot formudev、unsigned int type、unsigned int num);
パラメータによる タイプ 指定されたタイプ、例えば IORESOURCEM ,を選択します。
struct int plot form(struct plot form*dev、unsigned int num)
リソースの中断番号を取得します。
下に挙げます s 3 c 24 xui 2 cuprobe 関数解析 , これらのインターフェースはどうやって使いますか?
前にもう話しました。 s 3 c 2410クラウド 登録が成功したら呼び出します。 s 3 c 24 xui 2 cuprobe 実行します。コードを見ます。
//s 3 c 24 xui 2 cuprobe*caled by the bus driver when a suitable device is found*//* drivers/i2c/busses/i2c-s3c2410.c */ 

static int s3c24xx_i2c_probe( struct platform_device * pdev) 

    struct s3c24xx_i2c * i2c = & s3c24xx_i2c; 
    struct resource * res; 
    int ret; 

    /* find the clock and enable it */ 

     i2c- > dev = & pdev- > dev; 
     i2c- > clk = clk_get( & pdev- > dev, "i2c" ) ; 
    if ( IS_ERR( i2c- > clk) ) { 
     dev_err( & pdev- > dev, "cannot get clock
" ) ; 
     ret = - ENOENT; 
     goto out; 
    } 

     dev_dbg( & pdev- > dev, "clock source %p
" , i2c- > clk) ; 
     clk_enable( i2c- > clk) ;

    /* map the registers */ 
     res = platform_get_resource( pdev, IORESOURCE_MEM, 0) ; /* IO */ 
    if ( res = = NULL ) { 
     dev_err( & pdev- > dev, "cannot find IO resource
" ) ; 
     ret = - ENOENT; 
     goto out; 
    } 
    
     i2c- > ioarea = request_mem_region( res- > start, ( res- > end- res- > start) + 1, pdev- > name) ; /* IO Region */ 
    
    if ( i2c- > ioarea = = NULL ) { 
     dev_err( & pdev- > dev, "cannot request IO
" ) ; 
     ret = - ENXIO; 
     goto out; 
    } 
    
     i2c- > regs = ioremap( res- > start, ( res- > end- res- > start) + 1) ; /* */ 
    
    if ( i2c- > regs = = NULL ) { 
     dev_err( & pdev- > dev, "cannot map IO
" ) ; 
     ret = - ENXIO; 
     goto out; 
    } 
    
     dev_dbg( & pdev- > dev, "registers %p (%p, %p)
" , i2c- > regs, i2c- > ioarea, res) ; 
    
    /* setup info block for the i2c core */ 
     i2c- > adap. algo_data = i2c; 
     i2c- > adap. dev. parent = & pdev- > dev; 
    
    /* initialise the i2c controller */ 
     ret = s3c24xx_i2c_init( i2c) ; 
    if ( ret ! = 0) 
     goto out; 

    /* find the IRQ for this unit (note, this relies on the init call to ensure no current IRQs pending */ 
    
     res = platform_get_resource( pdev, IORESOURCE_IRQ, 0) ; /* IRQ */ 

    if ( res = = NULL ) { 
     dev_err( & pdev- > dev, "cannot find IRQ
" ) ; 
     ret = - ENOENT; 
     goto out; 
    } 
    
     ret = request_irq( res- > start, s3c24xx_i2c_irq, IRQF_DISABLED, /* IRQ */ 
     pdev- > name, i2c) ; 
    
     ……

    return ret; 
    
}
小さな思考:
どんな場合に使えますか? plotform driver メカニズムドライブは?
       カーネル自体と動作依存性が大きくない周辺機器だけが理解できます。 ( つまり、カーネル運行に必要な最小システム内の設備でない限り ), 独立した , それぞれ独自の資源を持つ (address and IRQs) , 全部使えます プラットフォーム 実現する lcd、usb、アート など、全部使えます プラットフロム 書きます timer,irq 最小システム内の設備は使わないほうがいいです。 プラットフロム メカニズムは、実際にはカーネル実装も同様である。
参考資料:
linux-2.64/Dcumentation/driver-model/playtform.txt
『plotform_device』 和 プラットフォーム 登録プロセス」
http://blog.chinaunix.net/u2/60011/showart.php?id=1018999
http://www.eetop.cn/blog/html/45/11145-676.html