歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> Linux驅動設備模型之Platform

Linux驅動設備模型之Platform

日期:2017/3/1 10:57:32   编辑:Linux編程

[概述]

一個現實的Linux設備和驅動通常都需要掛接在一種總線上,對於本身依附於PCI、USB、IIC、SPI等的設備而言,這自然不是問題,但是在嵌入式系統中,SoC系統中集成的獨立的外設控制器,掛接在SoC內存空間的外設(IIC,RTC,SPI,LCD,看門狗)等卻不依附於此類總線。基於這一背景,Linux發明了一種虛擬的總線,稱為platform總線,相應的設備稱為platformdevice,而驅動稱為platform driver。

注意,所謂的platform device並不是與字符設備,塊設備和網絡設備並列的概念,而是Linux系統提供的一種附加手段。

[Platform的兩大好處]

1、使得設備被掛接在一個總線上,因此,符合Linux2.6的設備模型。其結果是,配套的sysfs節點、設備電源管理都成為可能;

2、 隔離BSP和驅動。在BSP中定義platform設備和設備使用的資源、設備的具體配置信息,而在驅動中,只需要通過通用的API去獲取資源和數據,做到了板相關代碼和驅動代碼的分離,使得驅動具有更好的可擴展性和跨平台性。

[platform_device& platform_driver]

  1. struct platform_device {
  2. constchar * name; /* 設備名www.linuxidc.com */
  3. int id; /* 設備ID */
  4. structdevice dev; /* 內嵌的設備結構體www.linuxidc.com */
  5. u32 num_resources; /* 設備使用各類資源數量 */
  6. structresource * resource; /* 資源 */
  7. structplatform_device_id *id_entry;
  8. /*arch specific additions */
  9. structpdev_archdata archdata;
  10. };

Platform_device通常在BSP的板文件中實現,在板文件中,將platform_device歸納為一個數組,最終調用platform_add_device()函數統一注冊。

  1. struct resource {
  2. resource_size_tstart;
  3. resource_size_tend;
  4. constchar *name;
  5. unsignedlong flags;
  6. structresource *parent, *sibling, *child;
  7. };

Platform_device的資源由resource來描述,通常只要關心start、end、flags,分別表示開始值,結束值和類型。Start和end的含義會隨著flags而變更,當flags為IORESOURCE_MEM時,start和end分別表示該platform_device占據內存的開始地址和結束地址;當flags為IORESOURCE_IRQ時,start和end分別表示該platform_device使用的中斷號的開始值和結束值。

對resource的定義通常也在BSP的板文件中進行,而我們在設備驅動中可以用platform_get_resource()來獲取resource。

  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(*resume)(struct platform_device *);
  7. structdevice_driver driver;
  8. structplatform_device_id *id_table;
  9. };

Platform_driver中包含了probe(),remove(),shutdown(),suspend(),resume()函數,通常是由驅動來實現。如果bus中定義了probe,remove,shutdown函數,會優先調用。

[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_dev_pm_ops,
  7. };

Platform總線並沒有對bus_type進行封裝,總線維護了兩條鏈klist_devices和klist_drivers(這兩條鏈表在成員subsys_private下):

Klist_devices 用來連接所有的platformdevice,調用platform_device_register函數時,會把設備掛接到klist_devices鏈表上;

Klist_drivers 用來連接所有的platformdriver,調用platform_driver_register函數時,會把驅動掛接到klist_drivers鏈表上。

驅動和設備通過match函數來進行匹配

  1. static int platform_match(struct device*dev, struct device_driver *drv)
  2. {
  3. structplatform_device *pdev = to_platform_device(dev);
  4. structplatform_driver *pdrv = to_platform_driver(drv);
  5. /*Attempt an OF style match first */
  6. if(of_driver_match_device(dev, drv))
  7. return1;
  8. /*Then try to match against the id table */
  9. if(pdrv->id_table)
  10. returnplatform_match_id(pdrv->id_table, pdev) != NULL;
  11. /*fall-back to driver name match */
  12. return(strcmp(pdev->name, drv->name) == 0);
  13. }
Copyright © Linux教程網 All Rights Reserved