Linux: Platform device

Platform device是在Linux 2.6引入的driver管理和註冊機制,在我porting過的driver中,許多裝置都可以以Platform device來做註冊,其中可能還會包含了介面的註冊(例如I2C,SPI),因為有些裝置在傳輸command和傳輸data的時候所用的介面會不同。好比Display device的時候,假若command是使用I2C介面傳輸,而RGB data是使用MDDI介面傳輸,那麼在註冊MDDI的Platform device時會一併註冊傳輸command的I2C介面,接著才能使用I2C傳輸command到裝置上去控制暫存器來完成初始化的動作(當然這並不是初始化一個device的完整流程)。

在Linux中大部分的device都可以包成Platform device來做註冊。Platform device是掛在虛擬的bus 上(Platform bus)。

Platform driver的移植,就軟體來說主要是driver和device兩個部分。
在board-xxx.c中可以看到所有platform device的註冊。

static void __init Board_init(void) {

...
//platform_add_devices註冊,devices struct中所帶的platform device,第二個參數表示該struct的大小
platform_add_devices(devices, ARRAY_SIZE(devices));

...

}

回頭去找devices這個struct如下:

static struct platform_device *devices[] __initdata = {
...

&aaa_device,
&bbb_device,

...

};
可以看到該struct的內容是蒐集了所有要註冊的platform device的資訊。每個device的型別仍然是platform_device,platform_device struct如下所示:

struct platform_device {
const char * name;
int id;
struct device dev;
u32 num_resources;
struct resource * resource;

const struct platform_device_id *id_entry;

/* arch specific additions */
struct pdev_archdata archdata;
};
一般常用到的包含了name, id, dev, resource,dev可以帶platform_data,提供在probe的時候使用。

以上是device的註冊,要完成driver的porting,還需要driver的register。

關於device register和driver register,常見的順序都是先register device再register driver,因為board_xxx.c中的xxx_init通常會比之後採用module_init而掛載的driver來的早執行到,因此一般來說都是device先註冊。

以下是之前的誤解。
因為這樣的機制,所以認為driver在註冊的時候,都必須先是device先註冊才可以註冊driver。
後來發現反過來也是可以的,所以稍微在網路上搜尋了一下兩者的關聯性,因為過去單從platform_register_driver()來往下trace,看到內部的code有去做match來配對device和driver,match的話就會做really_probe()來執行driver probe函示。其實在platform_device_register()也會做同樣的動作去媒合device和driver。之前沒有注意到platform_device_register()的部分,因為他被包在platform_add_device()裡面。因此platform_device_register()和platform_driver_register()誰先做並不會影響結果。

從網路上找到關於兩者的關係:

                                                  1.  platform_device_register()
                                                                      |
                                                                      |
---------------------------------------------------------------------------------------------------------
bus type (Platform, I2C, SPI)  在bus driver中會作match()和呼叫driver probe()的動作,若有match的話
---------------------------------------------------------------------------------------------------------
                                                                      |
                                                                      |
                                                   2. platform_driver_register()

這邊分成兩個部分解釋:
1. 當device透過platform_device_register()時,會透過.match提供的API在bus上找尋name相同的driver是否已經被掛載了,若成立,則會call bus或driver所提供的probe函式來做driver的初始化動作。若不成立,則只是將該device掛到bus上就return。

2. 相同的,當driver透過platform_driver_register()註冊時,也是利用.match的方式在bus上尋找name相同的device是否已經掛接在bus上,若是,則啟動probe的函式完成driver的初始化。若否,則將drvier掛接在bus上就return。

綜合以上,可以得知device和driver的掛接沒有誰先誰後的副作用,唯一的先決條件就是bus driver已經被註冊好。故platform bus是第一個要備系統給註冊起來,接著的device和driver就是透過platform_device_register()和platform_driver_register()將三者牽上關係。

platform bus的註冊,從code中去搜尋一下可以發現在platform.c中的platform_bus_init(),那麼誰會call這個API,稍微找一下可以發現是從init.c中的driver_init(),在往上串應該就會跟開機的部分有關了,這邊就先不往上trace了。

以上

留言

熱門文章