drivers/mfd/Mfd-core.c

mfd: multifunction device drivers---多功能设备驱动开发;
A product or device that has multiple functions. An example of this might be a printer that also makes copies, faxes, and scans. Another example is a CD or DVD that might contain multiple applications on the same disk; this may be a Mac and PC version of the same software or media meant to be played on more than one platform. Also called multi function product (MFP), all-in-one.

源码主要是做了一些platform_device的注册和添加删除工作。

 

[cpp] view plain copy
 
 在CODE上查看代码片派生到我的代码片
  1. int mfd_add_devices(struct device *parent, int id,  
  2.             struct mfd_cell *cells, int n_devs,  
  3.             struct resource *mem_base,  
  4.             int irq_base)  
  5. {  
  6.     int i;  
  7.     int ret = 0;  
  8.     atomic_t *cnts;  
  9.   
  10.     /* initialize reference counting for all cells */  
  11.     cnts = kcalloc(n_devs, sizeof(*cnts), GFP_KERNEL);  
  12.     if (!cnts)  
  13.         return -ENOMEM;  
  14.   
  15.     for (i = 0; i < n_devs; i++) {  
  16.         atomic_set(&cnts[i], 0);  
  17.         cells[i].usage_count = &cnts[i];  
  18.         ret = mfd_add_device(parent, id, cells + i, mem_base, irq_base); 调用mfd_add_device()  
  19.         if (ret)  
  20.             break;  
  21.     }  
  22.   
  23.     if (ret)  
  24.         mfd_remove_devices(parent);  
  25.   
  26.     return ret;  
  27. }  
  28. EXPORT_SYMBOL(mfd_add_devices);  

在这个函数中,参数cells是数组,个数为参数n_devs。用户调用此函数前初始化了cells部分内容,但其中成员由本函数初始化:

 

 

[cpp] view plain copy
 
 在CODE上查看代码片派生到我的代码片
  1. /* 
  2.  * This struct describes the MFD part ("cell"). 
  3.  * After registration the copy of this structure will become the platform data 
  4.  * of the resulting platform_device 
  5.  */  
  6. struct mfd_cell {  //个人理解:注册mfd_cell后等效为platform_device
  7.     const char      *name;       
  8.     int         id;                    
  9.   
  10.     /* refcounting for multiple drivers to use a single cell */  
  11.     atomic_t        *usage_count;    //本函数初始化  
  12.     int         (*enable)(struct platform_device *dev);  
  13.     int         (*disable)(struct platform_device *dev);  
  14.   
  15.     int         (*suspend)(struct platform_device *dev);  
  16.     int         (*resume)(struct platform_device *dev);  
  17.   
  18.     /* platform data passed to the sub devices drivers */  
  19.     void            *platform_data;  
  20.     size_t          pdata_size;  
  21.   
  22.     /* 
  23.      * These resources can be specified relative to the parent device. 
  24.      * For accessing hardware you should use resources from the platform dev 
  25.      */  
  26.     int         num_resources;  
  27.     const struct resource   *resources;  
  28.   
  29.     /* don't check for resource conflicts */  
  30.     bool            ignore_resource_conflicts;  
  31.   
  32.     /* 
  33.      * Disable runtime PM callbacks for this subdevice - see 
  34.      * pm_runtime_no_callbacks(). 
  35.      */  
  36.     bool            pm_runtime_no_callbacks;  
  37. };  

再来看mfd_add_device()

 

 

[cpp] view plain copy
 
 在CODE上查看代码片派生到我的代码片
  1. static int mfd_add_device(struct device *parent, int id,  
  2.               const struct mfd_cell *cell,  
  3.               struct resource *mem_base,  
  4.               int irq_base)  
  5. {  
  6.     struct resource *res;  
  7.     struct platform_device *pdev;  
  8.     int ret = -ENOMEM;  
  9.     int r;  
  10.   
  11.     pdev = platform_device_alloc(cell->name, id + cell->id); //申请pdev内存并初始化name和id  
  12.     if (!pdev)  
  13.         goto fail_alloc;  
  14.   
  15.     res = kzalloc(sizeof(*res) * cell->num_resources, GFP_KERNEL);  
  16.     if (!res)  
  17.         goto fail_device;  
  18.   
  19.     pdev->dev.parent = parent;  
  20.     pdev->dev.type = &mfd_dev_type;  
  21.   
  22.     if (cell->pdata_size) {  //重新分配pdev->dev. platform_data内存并将cell->platform_data赋给它。  
  23.         ret = platform_device_add_data(pdev,  
  24.                     cell->platform_data, cell->pdata_size);  
  25.         if (ret)  
  26.             goto fail_res;  
  27.     }  
  28.   
  29.     ret = mfd_platform_add_cell(pdev, cell); //重新分配pdev->mfd_cell内存并将cell赋给它。  
  30.     if (ret)  
  31.         goto fail_res;  
  32.   
  33. //初始化cell->num_resources 个数量的res将它赋给pdev->resource  
  34.     for (r = 0; r < cell->num_resources; r++) {  
  35.         res[r].name = cell->resources[r].name;  
  36.         res[r].flags = cell->resources[r].flags;  
  37.   
  38.         /* Find out base to use */  
  39.         if ((cell->resources[r].flags & IORESOURCE_MEM) && mem_base) {  
  40.             res[r].parent = mem_base;  
  41.             res[r].start = mem_base->start +    //cell中的每个内存start都要加上mem_base->start  
  42.                 cell->resources[r].start;  
  43.             res[r].end = mem_base->start +  
  44.                 cell->resources[r].end;  
  45.         } else if (cell->resources[r].flags & IORESOURCE_IRQ) {  
  46.             res[r].start = irq_base +           //每个cell中的irq都要加上irq_base。  
  47.                 cell->resources[r].start;  
  48.             res[r].end   = irq_base +  
  49.                 cell->resources[r].end;  
  50.         } else {  
  51.             res[r].parent = cell->resources[r].parent;  
  52.             res[r].start = cell->resources[r].start;  
  53.             res[r].end   = cell->resources[r].end;  
  54.         }  
  55.   
  56.         if (!cell->ignore_resource_conflicts) {  
  57.             ret = acpi_check_resource_conflict(&res[r]);  
  58.             if (ret)  
  59.                 goto fail_res;  
  60.         }  
  61.     }  
  62.   
  63.     ret = platform_device_add_resources(pdev, res, cell->num_resources);//将多个res赋给pdev  
  64.     if (ret)  
  65.         goto fail_res;  
  66.   
  67.     ret = platform_device_add(pdev); //添加一个platform_device到系统,这时在dev的驱动中会使用这些res数据。  
  68.     if (ret)  
  69.         goto fail_res;  
  70.   
  71.     if (cell->pm_runtime_no_callbacks)  
  72.         pm_runtime_no_callbacks(&pdev->dev);  
  73.   
  74.     kfree(res);  
  75.   
  76.     return 0;  
  77.   
  78. fail_res:  
  79.     kfree(res);  
  80. fail_device:  
  81.     platform_device_put(pdev);  
  82. fail_alloc:  
  83.     return ret;  
  84. }  



posted @ 2016-08-18 18:48  瘋耔  阅读(397)  评论(0编辑  收藏  举报
跳至侧栏