http://my.oschina.net/yuyang/blog/85888
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);
}
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);
}