platform简单总结

来源:互联网 发布:怎么看淘宝价格曲线 编辑:程序博客网 时间:2024/06/08 01:04

1.platform_device结构体
 struct platform_device {
 const char * name;/* 设备名 */
 u32 id;
 struct device dev;
 u32 num_resources;/* 设备所使用各类资源数量 */
 struct resource * resource;/* 资源 */
 };
 设备的分配:
 struct platform_device *platform_device_alloc(const char *name, int id);  //name:设备名,id:设备
id,一般为-1 
设备的注册:
int platform_device_add(struct platform_device *pdev);  
对platform_device的定义通常在BSP的板文件中实现,在板文件中,将platform_device归纳
为一个数组:
static struct platform_device *smdk2410_devices[] __initdata = {
    &s3c_device_usb, 
    &s3c_device_lcd, 
    &s3c_device_wdt, 
    &s3c_device_i2c0, 
    &s3c_device_iis, 
}; 
最终通过 platform_add_devices()函数统一注册:
static void __init smdk2410_init(void) 

    s3c_i2c0_set_platdata(NULL); 
    platform_add_devices(smdk2410_devices, ARRAY_SIZE(smdk2410_devices)); 
    smdk_machine_init(); 

platform_add_devices()函数可以将平台设备添加到系统中,这个函数的 原型为:
int platform_add_devices(struct platform_device **devs, int num);
 该函数的第一个参数为平台设备数组的指针,第二个参数为平台设备的数量,它内部调用了
 platform_device_register()函 数用于注册单个的平台设备。
 2.platform_driver包含具体的操作函数,通常需要由驱动实现:
 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;
 };
看看驱动是怎么注册进去的:
int platform_driver_register(struct platform_driver *drv) 

    。。。
    return driver_register(&drv->driver); 

int driver_register(struct device_driver *drv) 

    。。。。 
    ret = bus_add_driver(drv); 
    。。。 

int bus_add_driver(struct device_driver *drv) 

    。。。
    if (drv->bus->p->drivers_autoprobe) { 
        error = driver_attach(drv); 
        if (error) 
            goto out_unregister; 
    } 
    。。。     

int driver_attach(struct device_driver *drv) 

    return bus_for_each_dev(drv->bus, NULL, drv, __driver_attach); 

来看__driver_attach这个函数,其中分别调用了driver_match_device,driver_probe_device函数。
static int __driver_attach(struct device *dev, void *data) 

    struct device_driver *drv = data; 
    if (!driver_match_device(drv, dev)) 
        return 0; 
    if (dev->parent)
       down(&dev->parent->sem); 
   down(&dev->sem); 
   if (!dev->driver) 
       driver_probe_device(drv, dev)
   up(&dev->sem); 
   if (dev->parent) 
       up(&dev->parent->sem); 
 
   return 0; 
}
匹配的时候调用的bus的match函数。匹配成功后调用驱动的probe函数。
int driver_probe_device(struct device_driver *drv, struct device *dev) 

    。。。 
    ret = really_probe(dev, drv); 
    。。。

static int really_probe(struct device *dev, struct device_driver *drv) 

    。。。
    int driver_probe_device(struct device_driver *drv, struct device *dev) 

    。。。
    ret = really_probe(dev, drv); 
    。。。 

static int really_probe(struct device *dev, struct device_driver *drv) 

    。。。 
       if (dev->bus->probe) { 
       ret = dev->bus->probe(dev); 
       if (ret) 
           goto probe_failed; 
   } else if (drv->probe) { 
       ret = drv->probe(dev); 
       if (ret) 
           goto probe_failed; 
   } 
   。。。

由relly_probe函数可以看出,如果bus定义了probe函数,则调用bus的probe
函数;如果bus,没有定义而driver定义了probe函数,则调用driver的probe
函数。

 3.bus_type类型的platform_bus_type
(1)基本结构
  struct bus_type platform_bus_type = {
   name = “platform”,
   dev_attrs = platform_dev_attrs,
   match = platform_match,
   uevent = platform_uevent,
   pm = PLATFORM_PM_OPS_PTR,
 };
 EXPORT_SYMBOL_GPL(platform_bus_type);
 (2)match()表明了platform_device和platform_driver之间如何匹配
 static int platform_match(struct device *dev, struct device_driver *drv)
 {
   struct platform_device *pdev;                                                                                          
   pdev = container_of(dev, struct platform_device, dev);             
   return (strncmp(pdev->name, drv->name, BUS_ID_SIZE) == 0);          
 }
匹配platform_device和platform_driver主要看二者的name字段是否相同
(3)总线初始化
platform_bus_type是在系统初始化的时候初始化的,不用我们做什么工作:
.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; 

4.设备中的资源
flags可以为IORESOURCE_IO、 IORESOURCE_MEM、IORESOURCE_IRQ、IORESOURCE_DMA等
static struct resource ldd6410_dm9000_resource[] = {
[0] = {
.start = 0×18000000,
.end = 0×18000000 + 3,
.flags = IORESOURCE_MEM
},
[1] = {
.start = IRQ_EINT(7),
.end = IRQ_EINT(7),
.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
}
};
获取资源:
db->addr_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
5.plat_data
对设备的硬件描述除了中断、内存、DMA通道以外,可能还会有一些配置信
息,而 这些配置信息也依赖于板,不适宜直接放置在设备驱动本身,因此,
platform也提供了platform_data的支持。例如:
static struct dm9000_plat_data ldd6410_dm9000_platdata = {
.flags = DM9000_PLATF_16BITONLY | DM9000_PLATF_NO_EEPROM,
.dev_addr = { 0×0, 0×16, 0xd4, 0×9f, 0xed, 0xa4 },
};
static struct platform_device ldd6410_dm9000 = {
.name = “dm9000″,
.id = 0,
.num_resources = ARRAY_SIZE(ldd6410_dm9000_resource),
.resource = ldd6410_dm9000_resource,
.dev = {
.platform_data = &ldd6410_dm9000_platdata,
}
};
获取plat_data:
struct dm9000_plat_data *pdata = pdev->dev.platform_data;
其中,pdev为platform_device的指针。