平台设备驱动之平台设备

平台设备驱动模型分为两个部分:平台设备(platform_device)和平台驱动(platform_driver)

设备层的核心数据结构struct platform_device (include\linux\platform_device.h)

 1 struct platform_device {
 2     const char    * name;
 3     int        id;
 4     struct device    dev;//内嵌标准device,一般可以用来传递平台数据
 5     u32        num_resources;
 6     struct resource    * resource;//设备占用资源的首地址
 7 
 8     struct platform_device_id    *id_entry;
 9 
10     /* arch specific additions */
11     struct pdev_archdata    archdata;
12 };

其中struct device用来实现设备模型,其中的*platform_data成员用途很大,一般称为平台数据指针,可以给平台驱动层传递任何需要的信息 

 结构如下:(include\linux\device.h)

 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 semaphore    sem;    /* semaphore 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     struct dev_pm_info    power;
20 
21 #ifdef CONFIG_NUMA
22     int        numa_node;    /* NUMA node this device is close to */
23 #endif
24     u64        *dma_mask;    /* dma mask (if dma'able device) */
25     u64        coherent_dma_mask;/* Like dma_mask, but for
26                          alloc_coherent mappings as
27                          not all hardware supports
28                          64 bit addresses for consistent
29                          allocations such descriptors. */
30 
31     struct device_dma_parameters *dma_parms;
32 
33     struct list_head    dma_pools;    /* dma pools (if dma'ble) */
34 
35     struct dma_coherent_mem    *dma_mem; /* internal for coherent mem
36                          override */
37     /* arch specific additions */
38     struct dev_archdata    archdata;
39 
40     dev_t            devt;    /* dev_t, creates the sysfs "dev" */
41 
42     spinlock_t        devres_lock;
43     struct list_head    devres_head;
44 
45     struct klist_node    knode_class;
46     struct class        *class;
47     const struct attribute_group **groups;    /* optional groups */
48 
49     void    (*release)(struct device *dev);
50 };

 struct resource结构如下:(include\linux\ioport.h)

 1 struct resource {
 2     resource_size_t start;
 3     resource_size_t end;
 4     const char *name;
 5     unsigned long flags;//资源类型,I/O,内存,中断,DMA
 6     struct resource *parent, *sibling, *child;
 7 };
 8 
 9 struct resource_list {
10     struct resource_list *next;
11     struct resource *res;
12     struct pci_dev *dev;
13 };
14 
15 /*
16  * IO resources have these defined flags.       flags资源类型
17  */
18 #define IORESOURCE_BITS        0x000000ff    /* Bus-specific bits */
19 
20 #define IORESOURCE_TYPE_BITS    0x00000f00    /* Resource type */
21 #define IORESOURCE_IO        0x00000100//I/O空间,一般在X86存在,ARM一般没有
22 #define IORESOURCE_MEM        0x00000200//内存空间,占用的是CPU 4G统一编址空间
23 #define IORESOURCE_IRQ        0x00000400//中断资源,中断号
24 #define IORESOURCE_DMA        0x00000800//DMA空间,占用的是CPU 4G统一编址空间
......

 platform设备层API

int platform_device_register(struct platform_device *pdev)注册设备:0成功;负数,失败。(只注册单个平台设备

void platform_device_unregister(struct platform_device *pdev)从内核中注销

int platform_add_devices(struct platform_device **devs, int num)内部还是调用platform_device_register(struct platform_device *pdev), 但是它可以注册多个平台设备结构

 

以LED设备为例,讲述实现设备层的步骤:

1.分析LED设备占用的物理资源,定义struct resource

2.设计LED的平台数据结构,定义平台数据变量并填充

3.定义struct platform_device结构,填充name、resource、num_resources、id,并将2中定义的平台数据指针填充到dev下的platform_data中

4.在模块的初始化函数中,调用platform_device_register(struct platform_device *pdev)注册

5.在模块卸载函数中,调用platform_device_unregister(struct platform_device *pdev)注销

 

 

LED平台设备层程序代码如下:

 

 1 #include<linux/module.h>
 2 #include<linux/kernel.h>
 3 #include<linux/init.h>
 4 
 5 #include<linux/types.h>
 6 #include<linux/interrupt.h>
 7 #include<linux/platform_device.h>
 8 
 9 /*
10  *
11  *
12  */
13 struct led_info
14 {
15     unsigned int pin_bit;//定义的平台数据结构
16 };
17 
18 static struct led_info ledpos={
19     .pin_bit=1<<5|1<<6|1<<7|1<<8,
20 };
21 
22 static struct resource led_resource[]={
23     [0]={
24         .start=0x56000010,
25         .end=0x56000010+16-1,
26         .flags=IORESOURCE_MEM,
27     },
28 };
29 
30 static void led_release(struct device *dev)
31 {
32     printk("remove device\n");
33 }
34 
35 static struct platform_device led_dev={
36     .name="s3c2440leds",
37     .id=-1,
38 //    .num_resources=ARRAY_SIZE(led_resource),
39     .resource=led_resource,
40     .num_resources=ARRAY_SIZE(led_resource),
41     .dev={
42         .release=led_release,
43         .platform_data=&ledpos,
44     },
45 };
46 
47 static int leddev_init(void)
48 {
49     platform_device_register(&led_dev);
50     return 0;
51 }
52 
53 static void leddev_exit(void)
54 {
55     platform_device_unregister(&led_dev);
56 }
57 
58 module_init(leddev_init);
59 module_exit(leddev_exit);
60 
61 MODULE_LICENSE("GPL");

注意:代码中43行的platform_data=&ledpos, 

 

 

 

 

参考文献:《嵌入式Linux高级驱动教程》    电子工业出版社      深圳信盈达电子有限公司   陈志发  周中孝  李志超  编著

posted on 2016-03-25 20:52  tragiccandidate  阅读(359)  评论(0编辑  收藏  举报