Chinaunix首页 | 论坛 | 博客
  • 博客访问: 119833
  • 博文数量: 35
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 165
  • 用 户 组: 普通用户
  • 注册时间: 2016-10-24 15:06
文章分类

全部博文(35)

文章存档

2017年(5)

2016年(30)

我的朋友

分类: LINUX

2016-11-21 22:34:28

platform总线-------linux2.6内核加入的一种虚拟总线。由两部分组成:

platform_device和platform_driver

platform总线----好处

platform 驱动与传统的设备驱动模型相比,优势在于platform机制将设备本身的资源注册进内核由内核统一管理,在驱动程序使用这些资源的时使用统一的借口,提高了程序的可移植性。

platform机制开发底层设备驱动的流程:

1--定义platform_device

2--注册platform_device

3--定义platform_driver

4--注册platform_driver

平台设备描述-----

struct platform_device {
    const char    * name;设备名

    int        id;设备编号,配合设备名使用
    struct device    dev;
    u32        num_resources;
    struct resource    * resource;设备资源
};


struct device {
    struct klist        klist_children;
    struct klist_node    knode_parent;    /* node in sibling list */
    struct klist_node    knode_driver;
    struct klist_node    knode_bus;
    struct device        *parent;

    struct kobject kobj;
    char    bus_id[BUS_ID_SIZE];    /* position on parent bus */
    unsigned        uevent_suppress:1;
    const char        *init_name; /* initial name of the device */
    struct device_type    *type;

    struct semaphore    sem;    /* semaphore to synchronize calls to
                     * its driver.
                     */

    struct bus_type    *bus;        /* type of bus device is on */
    struct device_driver *driver;    /* which driver has allocated this
                       device */
    void        *driver_data;    /* data private to the driver */
    void        *platform_data;    /* Platform specific data, device
                       core doesn't touch it */
    struct dev_pm_info    power;

#ifdef CONFIG_NUMA
    int        numa_node;    /* NUMA node this device is close to */
#endif
    u64        *dma_mask;    /* dma mask (if dma'able device) */
    u64        coherent_dma_mask;/* Like dma_mask, but for
                         alloc_coherent mappings as
                         not all hardware supports
                         64 bit addresses for consistent
                         allocations such descriptors. */

    struct device_dma_parameters *dma_parms;

    struct list_head    dma_pools;    /* dma pools (if dma'ble) */

    struct dma_coherent_mem    *dma_mem; /* internal for coherent mem
                         override */
    /* arch specific additions */
    struct dev_archdata    archdata;

    dev_t            devt;    /* dev_t, creates the sysfs "dev" */

    spinlock_t        devres_lock;
    struct list_head    devres_head;

    struct klist_node    knode_class;
    struct class        *class;
    struct attribute_group    **groups;    /* optional groups */

    void    (*release)(struct device *dev);
};



struct device
{
    /* The linked-list pointer. */
    struct device *next;

    /* The this device's descriptor, as mapped into the Guest. */
    struct lguest_device_desc *desc;

    /* The name of this device, for --verbose. */
    const char *name;

    /* If handle_input is set, it wants to be called when this file
     * descriptor is ready. */
    int fd;
    bool (*handle_input)(int fd, struct device *me);

    /* Any queues attached to this device */
    struct virtqueue *vq;

    /* Handle status being finalized (ie. feature bits stable). */
    void (*ready)(struct device *me);

    /* Device-specific data. */
    void *priv;
};

平台设备分配-----

struct platform_device *platform_device_alloc(const char *name,int id)

参数---

name---设备名

id--设备id一般为-1

平台设备注册-----

int platform_device_add(struct platform_device *pdev)

设备资源描述

struct resource {
    resource_size_t start;资源的起始物理地址
    resource_size_t end;资源的结束物理地址
    const char *name;资源的名称
    unsigned long flags;资源的类型,比如MEM,IO,IRQ类型
    struct resource *parent, *sibling, *child;资源链表指针
};

设备资源一例

static struct resource s3c_wdt_resource1=

{

.start=0x44100000,

.end=0x44200000,

.flags=IORESOURACE_MEM,设备基地址信息

}

static struct resource s3c_wdt_resource2=

{

.start=20,

.end=20,

.flags=IORESOURACE_IRQ,设备使用的中断号。

}

获取资源

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

参数:

dev--资源所属设备

type--获取的资源类型

num--获取的资源序号

例子

platform_get_resource(pdev,IORESOURACE_IRQ,0)

获取中断号

平台驱动描述---

struct platform_driver

{
    int (*probe)(struct platform_device *);
    int (*remove)(struct platform_device *);
    void (*shutdown)(struct platform_device *);
    int (*suspend)(struct platform_device *, pm_message_t state);
    int (*suspend_late)(struct platform_device *, pm_message_t state);
    int (*resume_early)(struct platform_device *);
    int (*resume)(struct platform_device *);
    struct device_driver driver;
};

struct device_driver {
    const char        *name;
    struct bus_type        *bus;

    struct module        *owner;
    const char         *mod_name;    /* used for built-in modules */

    int (*probe) (struct device *dev);
    int (*remove) (struct device *dev);
    void (*shutdown) (struct device *dev);
    int (*suspend) (struct device *dev, pm_message_t state);
    int (*resume) (struct device *dev);
    struct attribute_group **groups;

    struct dev_pm_ops *pm;

    struct driver_private *p;
};

平台驱动注册----

int platform_driver_register(struct platform_driver *)


重要----在平台驱动注册的时候,因为平台驱动的描述里有struct device_driver driver;

它首先给driver赋值一个内核定义好的总线。然后调用driver的注册函数,在这个注册函数里,它会把这个driver添加到总线上,调用driver_add函数。在这个函数中,调用函数driver_attach,bus_for_each_dev,最终调用总线的match(dev, drv)函数,若match成功,会接着调用driver的probe函数。这就是probe函数的调用时机。


上面提到的内核定义好的总线即平台总线,它也有平台总线的match函数,在这个函数里是通过平台设备的名字和平台驱动的名字来匹配的。

注意----在一般的设备模型中是通过设备的bus_id设备的唯一的编号,和驱动的名字来匹配的。在这个设备模型中,struct device 无name成员。





device----


#include
#include
#include
#include
#include
#include

MODULE_AUTHOR("David Xie");
MODULE_LICENSE("Dual BSD/GPL");

static struct platform_device *my_device;

static int __init my_device_init(void)
{
    int ret = 0;
        
        /* 分配结构 */
    my_device = platform_device_alloc("my_dev", -1);
        
        /*注册设备*/
    ret = platform_device_add(my_device);
    
    /*注册失败,释放相关内存*/
    if (ret)
        platform_device_put(my_device);
    
    return ret;    
}

static void my_device_exit(void)
{
    platform_device_unregister(my_device);
}

module_init(my_device_init);
module_exit(my_device_exit);




driver----


#include
#include
#include
#include
#include
#include

MODULE_AUTHOR("David Xie");
MODULE_LICENSE("Dual BSD/GPL");

static int my_probe(struct device *dev)
{
    printk("Driver found device which my driver can handle!\n");
    return 0;
}

static int my_remove(struct device *dev)
{
    printk("Driver found device unpluged!\n");
    return 0;
}

static struct platform_driver my_driver = {
    .probe        = my_probe,
    .remove        = my_remove,
    .driver        = {
        .owner    = THIS_MODULE,
        .name    = "my_dev",
    },
};

static int __init my_driver_init(void)
{       
        /*注册平台驱动*/
    return platform_driver_register(&my_driver);
}

static void my_driver_exit(void)
{
    platform_driver_unregister(&my_driver);
}

module_init(my_driver_init);
module_exit(my_driver_exit);








总结----------三个重要的

platform_device

platform_driver

resource

阅读(1216) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~