天天看點

platform_get_resource的分析

閱讀platformdriver的代碼時,發現在probe函數直接調用platform_get_resource從pdev中擷取io記憶體,但卻沒有判斷傳給probe的pdev是否屬于這個驅動 !

後來發現原來在arch目錄下的對應目錄裡面有個devs.c檔案(這個檔案可能因不同的架構而不一樣),這個檔案裡面聲明了一個platform裝置的資源數組foo_devices,原型如下:

static struct platform_device* foo_devices[] __initdata;

這個數組裡面包含了所有platform裝置的資源資訊。例如:一個裝置的資源聲明如下:

static struct resource foo_resource[] =

{

[0] =

.start = (FOO_BASE_PA),

.end = (FOO_BASE_PA) + (0x0008000),

.flags = IORESOURCE_MEM,

},

[1] =

.start = (IRQ_FOO),

.end = (IRQ_FOO),

.flags = IORESOURCE_IRQ,

};

static struct platform_device device_foo =

.name = "device_foo",

.id = 0,

.resource = foo_resource,

.num_resources = ARRAY_SIZE(foo_resource),

.dev =

//根據源代碼,這兩個成員置成0表示不起作用

.dma_mask = 0x0,

.coherent_dma_mask = 0x0,

那麼将這個device_foo加入foo_devices數組,就能直接在probe函數中用platform_get_resource擷取資源了,但是要注意驅動的name成員必須和platform_device結構中的name成員完全相同。

那為什麼加入foo_devices數組後就能直接通路了呢?

在 相關體系的machine_desc結構體中(對于每個特定平台都有一個MACHINE_START宏用來定義machine_desc結構體),有一個 接口init_machine,這個接口中會調用platform_add_devices添加foo_devices。例如:

platform_add_devices(foo_devices);

platform_get_resource函數源碼如下:

struct resource *platform_get_resource(struct platform_device *dev,

                                   unsigned int type, unsigned int num)

       int i;

       for (i = 0; i < dev->num_resources; i++) {

              struct resource *r = &dev->resource[i];

              if (type == resource_type(r) && num-- == 0)

                     return r;

       }

       return NULL;

}

函數分析:

struct resource *r = &dev->resource[i];

這行代碼使得不管你是想擷取哪一份資源都從第一份資源開始搜尋。

if (type == resource_type(r) && num-- == 0)

這行代碼首先通過type == resource_type(r)判斷目前這份資源的類型是否比對,如果比對則再通過num-- == 0判斷是否是你要的,如果不比對重新提取下一份資源而不會執行num-- == 0這一句代碼。

通過以上兩步就能定位到你要找的資源了,接着把資源傳回即可。如果都不比對就傳回NULL。

執行個體分析:

下面通過一個例子來看看它是如何拿到裝置資源的。

裝置資源如下:

static struct resource s3c_buttons_resource[] = {

       [0]={

              .start = S3C24XX_PA_GPIO,

              .end   = S3C24XX_PA_GPIO + S3C24XX_SZ_GPIO - 1,

              .flags = IORESOURCE_MEM,

       },

       [1]={

              .start = IRQ_EINT8,

              .end   = IRQ_EINT8,

              .flags = IORESOURCE_IRQ,

       [2]={

              .start = IRQ_EINT11,

              .end   = IRQ_EINT11,

       [3]={

              .start = IRQ_EINT13,

              .end   = IRQ_EINT13,

       [4]={

              .start = IRQ_EINT14,

              .end   = IRQ_EINT14,

       [5]={

              .start = IRQ_EINT15,

              .end   = IRQ_EINT15,

       [6]={

              .start = IRQ_EINT19,

              .end   = IRQ_EINT19,

驅動中通過下面代碼拿到第一份資源:

struct resource *res;

res = platform_get_resource(pdev, IORESOURCE_MEM, 0);

函數進入for裡面,i=0,num_resources=7,拿出resource[0]資源。resource_type(r)提取出該份資源 的資源類型并與函數傳遞下來的資源類型進行比較,比對。Num=0(這裡先判斷是否等于0再自減1)符合要求,進而傳回該資源。

擷取剩下資源的代碼如下:

for(i=0; i<6; i++){

              buttons_irq = platform_get_resource(pdev,IORESOURCE_IRQ,i);

             if(buttons_irq == NULL){

                  dev_err(dev,"no irq resource specified\n");

                   ret = -ENOENT;

                   goto err_map;

              }

              button_irqs[i] = buttons_irq->start; 

分析如下:

For第一次循環:

buttons_irq = platform_get_resource(pdev,IORESOURCE_IRQ,0);

在拿出第一份資源進行resource_type(r)判斷資源類型時不符合(此時num-- == 0這句沒有執行),進而拿出第二份資源,此時i=1,num_resources=7,num傳遞下來為0,資源類型判斷時候比對,num也等于0,進而确定資源并傳回。

For第二次循環:

buttons_irq = platform_get_resource(pdev,IORESOURCE_IRQ,1);

拿出第二份資源的時候resource_type(r)資源類型比對,但是num傳遞下來時候為1,執行num-- == 0時不符合(但num開始自減1,這導緻拿出第三份資源時num==0),隻好拿出第三份資源。剩下的以此類推。

總結:

unsigned int type決定資源的類型,unsigned int num決定type類型的第幾份資源(從0開始)。即使同類型資源在資源數組中不是連續排放也可以定位得到該資源。

比如第一份IORESOURCE_IRQ類型資源在resource[2],而第二份在resource[5],那

platform_get_resource(pdev,IORESOURCE_IRQ,0);

可以定位第一份IORESOURCE_IRQ資源;

platform_get_resource(pdev,IORESOURCE_IRQ,1);

可以定位第二份IORESOURCE_IRQ資源。

       之是以能定位到資源,在于函數實作中的這一行代碼:

該行代碼,如果沒有比對資源類型,num-- == 0不會執行而重新提取下一份資源,隻有資源比對了才會尋找該類型的第幾份資源,即使這些資源排放不連續。

【作者】sky

【出處】http://www.cnblogs.com/sky-heaven/

【部落格園】 http://www.cnblogs.com/sky-heaven/

【知乎】 http://www.zhihu.com/people/zhang-bing-hua

【我的作品---旋轉倒立擺】 http://v.youku.com/v_show/id_XODM5NDAzNjQw.html?spm=a2hzp.8253869.0.0&from=y1.7-2

【我的作品---自平衡自動循迹車】 http://v.youku.com/v_show/id_XODM5MzYyNTIw.html?spm=a2hzp.8253869.0.0&from=y1.7-2

【大餅教你學系列】https://edu.csdn.net/course/detail/10393

本文版權歸作者和部落格園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接配接,否則保留追究法律責任的權利.