1.1 platform匯流排、裝置與驅動
在Linux 2.6的裝置驅動模型中,關心匯流排、裝置和驅動這3個實體,匯流排將裝置和驅動綁定。在系統每註冊一個裝置的時候,會尋找與之匹配的驅動;相反的,在系統每註冊一個驅動的時候,會尋找與之匹配的裝置,而匹配由匯流排完成。
一個現實的Linux裝置和驅動通常都需要掛接在一種匯流排上,對於本身依附於PCI、USB、I2C、SPI等的裝置而言,這自然不是問題,但是在嵌入式系統裡面,SoC系統中整合的獨立的外設控制器、掛接在SoC記憶體空間的外設等確不依附於此類匯流排。基於這一背景,Linux發明了一種虛擬匯流排,稱為platform匯流排,相應的裝置稱為platform_device,而驅動成為platform_driver。
注意,所謂的platform_device並不是與字元裝置、塊裝置和網路裝置並列的概念,而是Linux系統提供的一種附加手段,例如,在S3C6410處理器中,把內部整合的I2C、RTC、SPI、LCD、看門狗等控制器都歸納為platform_device,而它們本身就是字元裝置。platform_device結構體的定義如代碼清單1所示。
代碼清單1 platform_device結構體
1 struct platform_device {
2 const char * name;/* 裝置名稱 */
3 u32 id;
4 struct device dev;
5 u32 num_resources;/* 裝置所使用各類資源數量 */
6 struct resource * resource;/* 資源 */
7 };
platform_driver這個結構體中包含probe()、remove()、shutdown()、suspend()、resume()函數,通常也需要由驅動實現,如代碼清單2。
代碼清單2 platform_driver結構體
1 struct platform_driver {
2 int (*probe)(struct platform_device *);
3 int (*remove)(struct platform_device *);
4 void (*shutdown)(struct platform_device *);
5 int (*suspend)(struct platform_device *, pm_message_t state);
6 int (*suspend_late)(struct platform_device *, pm_message_t state);
7 int (*resume_early)(struct platform_device *);
8 int (*resume)(struct platform_device *);
9 struct pm_ext_ops *pm;
10 struct device_driver driver;
11};
系統中為platform匯流排定義了一個bus_type的執行個體platform_bus_type,其定義如代碼清單15.3。
代碼清單15.3 platform匯流排的bus_type 執行個體platform_bus_type
1 struct bus_type platform_bus_type = {
2 .name = "platform",
3 .dev_attrs = platform_dev_attrs,
4 .match = platform_match,
5 .uevent = platform_uevent,
6 .pm = PLATFORM_PM_OPS_PTR,
7 };
8 EXPORT_SYMBOL_GPL(platform_bus_type);
這裡要重點關注其match()成員函數,正是此成員表明了platform_device和platform_driver之間如何匹配,如代碼清單4所示。
代碼清單4 platform_bus_type的match()成員函數
1 static int platform_match(struct device *dev, struct device_driver *drv)
2 {
3 struct platform_device *pdev;
4
5 pdev = container_of(dev, struct platform_device, dev);
6 return (strncmp(pdev->name, drv->name, BUS_ID_SIZE) == 0);
7 }
從代碼清單4的第6行可以看出,匹配platform_device和platform_driver主要看二者的name欄位是否相同。
對platform_device的定義通常在BSP的板檔案中實現,在板檔案中,將platform_device歸納為一個數組,最終通過platform_add_devices()函數統一註冊。platform_add_devices()函數可以將平台裝置添加到系統中,這個函數的原型為:
int platform_add_devices(struct platform_device **devs, int num);
該函數的第一個參數為平台裝置數組的指標,第二個參數為平台裝置的數量,它內部調用了platform_device_register()函數用於註冊單個的平台裝置。