platform_device驱动模型详解

linux  platform_device驱动模型详解

platform在linux模型结构中,其实就是一种虚拟总线,没有对应的硬件结构。
其主要用来管理系统的外设资源,比如IO 内存  中断信号......
这样内核就可以假设所有设备都是挂在platform总线上,从而进行整体管理。

linux2.6的设备模型:设备、总线、类和驱动彼此相关的模型结构

首先是总线,bus_type
include/linux/device.h
struct bus_type {
    const char      *name;
    struct bus_attribute    *bus_attrs;
    struct device_attribute *dev_attrs;
    struct driver_attribute *drv_attrs;

    int (*match)(struct device *dev, struct device_driver *drv);
    int (*uevent)(struct device *dev, struct kobj_uevent_env *env);
    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);

    const struct dev_pm_ops *pm;

    struct subsys_private *p;
};
platform的总线定义如下:
struct bus_type platform_bus_type = {
    .name       = "platform",
    .dev_attrs  = platform_dev_attrs,  //设备属性
    .match      = platform_match,       //match函数这个函数在当属于platform的设备或者驱动注册到内核时就会调用完成设备与驱动的匹配工作
    .uevent     = platform_uevent,      //热插拔操作函数
    .pm     = &platform_dev_pm_ops,
};
platform_bus_type不是以模块的形势注册到内核中的,它是由init/main.c中的
do_base_setup  ---->drivers/base/init.c中driver_init---->
drivers/base/platform.c下的
int __init platform_bus_init(void)
{
    int error;

    early_platform_cleanup();

    error = device_register(&platform_bus);
    if (error)
        return error;
    error =  bus_register(&platform_bus_type);
    if (error)
        device_unregister(&platform_bus);
    return error;
}


设备
系统中每个设备都有一个device对象(C语言也可以进行面向对象编程,参考“Linux设备模型理解”)描述,如下
include/linux/device.h
struct device {
    struct device       *parent;

    struct device_private   *p;

    struct kobject kobj;
    const char      *init_name; /* initial name of the device */
    const struct device_type *type;

    struct mutex        mutex;  /* mutex 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        *platform_data; /* Platform specific data, device
                       core doesn't touch it */
    struct dev_pm_info  power;
    struct dev_power_domain *pwr_domain;

#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;

    struct device_node  *of_node; /* associated device tree node */

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

    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;
    const struct attribute_group **groups;  /* optional groups */

    void    (*release)(struct device *dev);
};
include/linux/platform_device.h中platform_device
struct platform_device {
    const char  * name;
    int     id;
    struct device   dev;
    u32     num_resources;
    struct resource * resource;

    const struct platform_device_id *id_entry;

    /* MFD cell pointer */
    struct mfd_cell *mfd_cell;

    /* arch specific additions */
    struct pdev_archdata    archdata;
};
resource定义在include/linux/ioport.h下
struct resource {
    resource_size_t start;
    resource_size_t end;
    const char *name;
    unsigned long flags;
    struct resource *parent, *sibling, *child;
};

设备的注册:
register_device(dev);
int device_register(struct device *dev)
{
device_initialize(dev);
return device_add(dev);
}
对应的platform_device的注册函数为:drivers/base/platform.c下platform_device_register
int platform_device_register(struct device *dev)
{
   device_initialize(&pdev->dev);
   returnplatform_device_add(pdev);
}
就是mini2440的所有外设资源了,外设的具体定义在
/arch/arm/plat-s3c24xx/devs.c下

驱动
下面是设备驱动定义:
include/linux/device.h
struct device_driver {
const char  * name;
struct bus_type  * bus;//所属总线
struct completion unloaded;
struct kobject  kobj;//代表自身
struct klist  klist_devices;//设备列表
struct klist_node knode_bus;
struct module  * owner;
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);
};
platform_driver的结构如下:
include/linux/platform_device.h
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 (*resume)(struct platform_device *);
    struct device_driver driver;
    const struct platform_device_id *id_table;
};

驱动注册函数:
drivers/base/driver.c下int driver_register(struct device_driver *drv)

platform_driver的注册函数在drivers/base/platform.c下
int platform_driver_register(struct platform_driver *drv)                                                         {
    drv->driver.bus = &platform_bus_type;
    if (drv->probe)
        drv->driver.probe = platform_drv_probe;
    if (drv->remove)
        drv->driver.remove = platform_drv_remove;
    if (drv->shutdown)
        drv->driver.shutdown = platform_drv_shutdown;

    return driver_register(&drv->driver);
}
 

你可能感兴趣的:(linux,详解,驱动,模型,platform_device)