Linux platform设备和驱动


platform 设备与驱动

一. 概述

    platform设备和驱动与linux设备模型密切相关。platform在linux设备模型中,其实就是一种虚拟总线没有对应的硬件结构。它的主要作用就是管理系统的外设资源,比如io内存,中断信号线。现在大多数处理器芯片都是soc,如s3c2440,它包括处理器内核(arm920t)和系统的外设(lcd接口,nandflash接口等)。linux在引入了platform机制之后,内核假设所有的这些外设都挂载在platform虚拟总线上,以便进行统一管理。

二. platform 总线
   1. 在系统中platform对应的文件drivers/base/platform.c,它不是作为一个模块注册到内核的,关键的注册总线的函数由系统初始化部分,对应/init/main.c中的do_basic_setup函数间接调用。这里可以看出platform非常重要,要在系统其他驱动加载之前注册。下面分析platform总线注册函数  
  1. int __init platform_bus_init(void)  
  2. {  
  3.     int error;  
  4.   
  5.   
  6.     early_platform_cleanup();  
  7.   
  8.   
  9.     error = device_register(&platform_bus);  
  10.         //总线也是设备,所以也要进行设备的注册   
  11.     if (error)  
  12.         return error;  
  13.     error =  bus_register(&platform_bus_type);  
  14.         //注册platform_bus_type总线到内核   
  15.     if (error)  
  16.         device_unregister(&platform_bus);  
  17.     return error;  
  18. }  
    这个函数向内核注册了一种总线。他首先由/drivers/base/init.c中的driver_init函数调用,driver_init函数由/init/main.c中的do_basic_setup函数调用,do_basic_setup这个函数由kernel_init调用,所以platform总线是在内核初始化的时候就注册进了内核。
   2. platform_bus_type 总线结构与设备结构
    (1) platform总线 设备结构
 
  1. struct device platform_bus = {  
  2.     .init_name  = "platform",  
  3. };  
    platform总线也是一种设备,这里初始化一个device结构,设备名称platform,因为没有指定父设备,所以注册后将会在/sys/device/下出现platform目录。
    (2) platform总线 总线结构
 
  1. struct bus_type platform_bus_type = {  
  2.     .name       = "platform",  
  3.     .dev_attrs  = platform_dev_attrs,   
  4.     .match      = platform_match,  
  5.     .uevent     = platform_uevent,  
  6.     .pm     = &platform_dev_pm_ops,  
  7. };  
    platform_dev_attrs    设备属性
    platform_match        match函数,这个函数在当属于platform的设备或者驱动注册到内核时就会调用,完成设备与驱动的匹配工作。
    platform_uevent       热插拔操作函数
三. platform 设备
   1. platform_device 结构
 
  1. struct platform_device {  
  2.     const char  * name;  
  3.     int     id;  
  4.     struct device   dev;  
  5.     u32     num_resources;  
  6.     struct resource * resource;  
  7.     struct platform_device_id   *id_entry;  
  8.     /* arch specific additions */  
  9.     struct pdev_archdata    archdata;  
  10. };  
    (1)platform_device结构体中有一个struct resource结构,是设备占用系统的资源,定义在ioport.h中,如下
 
  1. struct resource {  
  2.     resource_size_t start;  
  3.     resource_size_t end;  
  4.     const char *name;  
  5.     unsigned long flags;  
  6.     struct resource *parent, *sibling, *child;  
  7. };  
    (2) num_resources 占用系统资源的数目,一般设备都占用两种资源,io内存和中断信号线。这个为两种资源的总和。
   2. 设备注册函数 platform_device_register
 
  1. int platform_device_register(struct platform_device *pdev)  
  2. {  
  3.     device_initialize(&pdev->dev);  
  4.     return platform_device_add(pdev);  
  5. }  
    这个函数首先初始化了platform_device的device结构,然后调用platform_device_add,这个是注册函数的关键,下面分析platform_device_add:  
  1. int platform_device_add(struct platform_device *pdev)  
  2. {  
  3.     int i, ret = 0;  
  4.   
  5.   
  6.     if (!pdev)  
  7.         return -EINVAL;  
  8.   
  9.   
  10.     if (!pdev->dev.parent)  
  11.         pdev->dev.parent = &platform_bus;  
  12.         //可以看出,platform设备的父设备一般都是platform_bus,所以注册后的platform设备都出现在/sys/devices/platform_bus下  
  13.     pdev->dev.bus = &platform_bus_type;  
  14.         //挂到platform总线上  
  15.     if (pdev->id != -1)  
  16.         dev_set_name(&pdev->dev, "%s.%d", pdev->name,  pdev->id);  
  17.     else  
  18.         dev_set_name(&pdev->dev, "%s", pdev->name);  
  19.         //设置设备名字,这个名字与/sys/devices/platform_bus下的名字对应  
  20.     for (i = 0; i < pdev->num_resources; i++) { //下面操作设备所占用的系统资源  
  21.         struct resource *p, *r = &pdev->resource[i];  
  22.   
  23.         if (r->name == NULL)  
  24.             r->name = dev_name(&pdev->dev);  
  25.   
  26.         p = r->parent;  
  27.         if (!p) {  
  28.             if (resource_type(r) == IORESOURCE_MEM)  
  29.                 p = &iomem_resource;  
  30.             else if (resource_type(r) == IORESOURCE_IO)  
  31.                 p = &ioport_resource;  
  32.         }  
  33.   
  34.         if (p && insert_resource(p, r)) {  
  35.             printk(KERN_ERR  
  36.                    "%s: failed to claim resource %d\n",  
  37.                    dev_name(&pdev->dev), i);  
  38.             ret = -EBUSY;  
  39.             goto failed;  
  40.         }  
  41.     }  
  42.        //上面主要是遍历设备所占用的资源,找到对应的父资源,如果没有定义,那么根据资源的类型,分别赋予iomem_resource和ioport_resource,然后调用insert_resource插入资源。  
  43.        //这样系统的资源就形成了一个树形的数据结构,便于系统的管理  
  44.     pr_debug("Registering platform device '%s'. Parent at %s\n",  
  45.          dev_name(&pdev->dev), dev_name(pdev->dev.parent));  
  46.   
  47.   
  48.     ret = device_add(&pdev->dev);  
  49.         //注册到设备模型中  
  50.     if (ret == 0)  
  51.         return ret;  
  52.  failed:  
  53.     while (--i >= 0) {  
  54.         struct resource *r = &pdev->resource[i];  
  55.         unsigned long type = resource_type(r);  
  56.   
  57.   
  58.         if (type == IORESOURCE_MEM || type == IORESOURCE_IO)  
  59.             release_resource(r);  
  60.     }  
  61.     return ret;  
  62. }  
  • 1
  • 2
  • 下一页

相关内容