• 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. }  



  • 相关阅读:
    重写Nacos服务发现逻辑动态修改远程服务IP地址
    手撸一个SpringBoot配置中心实现配置动态刷新
    使用CompletableFuture实现多个异步任务并行完成后合并结果
    SpringBoot实现Flyway的Callback回调钩子
    Java实现相似结构表算法
    使用Druid解析SQL实现血缘关系计算
    记一次解决RestTemplate和HttpClient请求结果乱码的问题
    double转json格式化添加自定义注解
    了解23种设计模式
    BigDecimal四舍五入
  • 原文地址:https://www.cnblogs.com/Ph-one/p/5785054.html
Copyright © 2020-2023  润新知