Linux設備驅動開發 - 平台設備驅動


Linux2.6的內核中引入了一種新的設備驅動模型-平台(platform)設備驅動,平台設備驅動分為平台設備(platform_device)和平台驅動(platform_driver),平台設備的引入使得Linux設備驅動更加便於移植。

一、平台設備
平台設備結構體:

 1 struct platform_device {
 2     const char    * name;                      /* 設備名 */
 3     int        id;
 4     struct device    dev;                     /* 設備結構體 */
 5     u32        num_resources;                   /* 設備資源數量 */
 6     struct resource    * resource;              /* 設備資源 */
 7 
 8     const struct platform_device_id    *id_entry;
 9 
10     /* arch specific additions */
11     struct pdev_archdata    archdata;
12 };

平台設備主要是提供設備資源和平台數據給平台驅動,resource為設備資源數組,類型有IORESOURCE_IO、IORESOURCE_MEM、IORESOURCE_IRQ、IORESOURCE_DMA、IORESOURCE_DMA。下面是一個網卡芯片DM9000的外設資源:

 1 static struct resource dm9000_resources[] = {
 2     [0] = {
 3         .start        = S3C64XX_PA_DM9000,
 4         .end        = S3C64XX_PA_DM9000 + 3,
 5         .flags        = IORESOURCE_MEM,
 6     },
 7     [1] = {
 8         .start        = S3C64XX_PA_DM9000 + 4,
 9         .end        = S3C64XX_PA_DM9000 + S3C64XX_SZ_DM9000 - 1,
10         .flags        = IORESOURCE_MEM,
11     },
12     [2] = {
13         .start        = IRQ_EINT(7),
14         .end        = IRQ_EINT(7),
15         .flags        = IORESOURCE_IRQ | IRQF_TRIGGER_HIGH,
16     },
17 };

dm9000_resources里面有三個設備資源,第一個為IORESOURCE_MEM類型,指明了第一個資源內存的起始地址為S3C64XX_PA_DM9000結束地址為S3C64XX_PA_DM9000 + 3,第二個同樣為IORESOURCE_MEM類型,指明了第二個資源內存的起始地址為S3C64XX_PA_DM9000 + 4結束地址為S3C64XX_PA_DM9000 + S3C64XX_SZ_DM9000 - 1,第三個為IORESOURCE_IRQ類型,指明了中斷號為IRQ_EINT(7)。

 1 struct device {
 2     struct device        *parent;
 3 
 4     struct device_private    *p;
 5 
 6     struct kobject kobj;
 7     const char        *init_name; /* initial name of the device */
 8     struct device_type    *type;
 9 
10     struct mutex        mutex;    /* mutex to synchronize calls to
11                      * its driver.
12                      */
13 
14     struct bus_type    *bus;        /* type of bus device is on */
15     struct device_driver *driver;    /* which driver has allocated this
16                        device */
17     void        *platform_data;    /* Platform specific data, device
18                        core doesn't touch it */
19     ...
20 };

 

struct device結構體里面有一個重要成員platform_data,它是平台設備和平台驅動進行數據傳遞的重要成員。

 

平台設備注冊:

1 int platform_device_register(struct platform_device *pdev);

platform_device_register()會對平台設備進行相應的初始化之后調用platform_device_register()函數把它添加到子系統中。

 

平台設備注銷:

1 void platform_device_unregister(struct platform_device *pdev);

platform_device_unregister()函數釋放設備資源之后從子系統中將其移除。

 

平台設備模板:

 1 static struct resource xxx_resource = 
 2 {
 3     [0] = 
 4     {
 5         .start = ...,
 6         .end = ...,
 7         .flags = ...,
 8     },
 9     [1] = 
10     {
11         ...
12     }
13     ...
14 };
15 
16 static struct xxx_plat_data xxx_data = 
17 {
18     ...
19 };
20 
21 static struct platform_device xxx_platform_device = 
22 {
23     .name = NAME,
24     .num_resources = ARRAY_SIZE(xxx_resource),
25     .resource = xxx_resource,
26     .dev = 
27     {
28         .platform_data = &xxx_data,
29     }
30 };
31 
32 static int __init xxx_device_init(void)
33 {
34     ...
35     /* 注冊平台設備 */
36     platform_device_register(&xxx_platform_device);
37     ...
38 }
39 
40 static void __exit xxx_device_exit(void)
41 {
42     ...
43     /* 注銷平台設備 */
44     platform_device_unregister(&xxx_platform_device);
45     ...
46 }

 

 

二、平台驅動
平台驅動結構體:

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     struct device_driver driver;
8     const struct platform_device_id *id_table;
9 };

平台驅動結構體driver成員里面的name必須與平台設備結構體里面的name成員一致,在系統注冊一個設備的時候,會通過設備結構體里面的name成員和平台驅動driver里面的name成員匹配,當匹配成功則調用平台驅動的probe函數,
通常在probe函數中獲取平台設備的資源和私有數據並進行設備的初始化。

獲取設備資源:

1 struct resource *platform_get_resource(struct platform_device *dev, unsigned int type, unsigned int num);

platform_get_resource()函數用於獲取平台設備的資源,dev為要平台設備,type為平台設備資源類型,num為平台資源號(比如同一個資源有兩個則資源號為0,1)。

 

平台驅動注冊:

1 int platform_driver_register(struct platform_driver *drv);

platform_driver_register()函數完成平台驅動的注冊,在驅動模塊加載時調用。

 

平台驅動注銷:

1 void platform_driver_unregister(struct platform_driver *drv);

platform_driver_unregister()函數完成平台驅動的注銷,在驅動模塊卸載時調用。

 

平台驅動模板:

 1 static int __devinit xxx_probe(struct platform_device *pdev)
 2 {
 3     struct xxx_plat_data *pdata = pdev->dev.platform_data;    /* 獲取私有數據 */
 4     platform_get_resource(pdev,xxx,x);                        /* 獲取設備資源 */
 5     ...
 6 }
 7 
 8 static struct platform_driver xxx_platform_driver = 
 9 {
10     .probe = xxx_probe,
11     .remove = __devexit_p(xxx_remove),
12     .driver = 
13     {
14         .name = NAME,    /* 跟平台設備名一致 */
15         ...
16     },
17     ...
18 };
19 
20 static int __init xxx_driver_init(void)
21 {
22     ...
23     /* 驅動注冊 */
24     platform_driver_register(&xxx_platform_driver);
25     ...
26 }
27 
28 static void __exit xxx_driver_exit(void)
29 {
30     ...
31     /* 驅動注銷 */
32     platform_driver_unregister(&xxx_platform_driver);
33     ...
34 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM