zoukankan      html  css  js  c++  java
  • SPI子系统分析之三:驱动模块

    内核版本:3.9.5

    SPI核心层(平台无关)

    SPI子系统初始化的第一步就是将SPI总线注册进内核,并且在/sys下创建一个spi_master的类,以后注册的从设备都将挂接在该总线下. 下列函数位于drivers/spi/spi.c中:

     1 static int __init spi_init(void)
     2 {
     3     int    status;
     4 
     5     buf = kmalloc(SPI_BUFSIZ, GFP_KERNEL);/*初始化缓存*/
     6     if (!buf) {
     7         status = -ENOMEM;
     8         goto err0;
     9     }
    10 
    11     status = bus_register(&spi_bus_type);/*注册spi总线,此步骤之后就会在/sys/bus目录下生成spi子目录*/
    12     if (status < 0)
    13         goto err1;
    14 
    15     status = class_register(&spi_master_class);/*注册spi类,此步骤之后就会在/sys/class目录下生成spi_master子目录*/
    16     if (status < 0)
    17         goto err2;
    18     return 0;
    19 
    20 err2:
    21     bus_unregister(&spi_bus_type);
    22 err1:
    23     kfree(buf);
    24     buf = NULL;
    25 err0:
    26     return status;
    27 }
    28 
    29 /* board_info is normally registered in arch_initcall(),
    30  * but even essential drivers wait till later
    31  *
    32  * REVISIT only boardinfo really needs static linking. the rest (device and
    33  * driver registration) _could_ be dynamically linked (modular) ... costs
    34  * include needing to have boardinfo data structures be much more public.
    35  */
    36 postcore_initcall(spi_init);

    我们来看spi_bus_type的定义:

     1 /*和电源管理相关的结构*/
     2 static const struct dev_pm_ops spi_pm = {
     3     .suspend = spi_pm_suspend,
     4     .resume = spi_pm_resume,
     5     .freeze = spi_pm_freeze,
     6     .thaw = spi_pm_thaw,
     7     .poweroff = spi_pm_poweroff,
     8     .restore = spi_pm_restore,
     9     SET_RUNTIME_PM_OPS(
    10         pm_generic_runtime_suspend,
    11         pm_generic_runtime_resume,
    12         pm_generic_runtime_idle
    13     )
    14 };
    15 
    16 struct bus_type spi_bus_type = {
    17     .name        = "spi",
    18     .dev_attrs    = spi_dev_attrs,
    19     .match        = spi_match_device,
    20     .uevent        = spi_uevent,
    21     .pm        = &spi_pm,/*和电源管理相关的一些函数的结构封装*/
    22 };

    来看看spi_match_device函数都做了什么:

     1 /* 名词解释of: OpenFirmware
     2  * 调用层次spi_match_device-->of_driver_match_device-->of_match_device-->
     3  * of_match_node
     4  * 用于驱动程序检查platform_device是否在其支持列表里
     5  */
     6 static int spi_match_device(struct device *dev, struct device_driver *drv)
     7 {
     8     const struct spi_device    *spi = to_spi_device(dev);
     9     const struct spi_driver    *sdrv = to_spi_driver(drv);
    10 
    11     /* Attempt an OF style match */
    12     /* 不匹配返回0;匹配返回非0,指向struct of_device_id类型的指针
    13      * dev:需要查找的设备; drv:驱动程序结构体
    14      */
    15     if (of_driver_match_device(dev, drv))
    16         return 1;
    17 
    18     /* Then try ACPI */
    19     if (acpi_driver_match_device(dev, drv))
    20         return 1;
    21 
    22     /*在驱动查找设备ID,找到返回真,否则假*/
    23     if (sdrv->id_table)
    24         return !!spi_match_id(sdrv->id_table, spi);
    25 
    26     return strcmp(spi->modalias, drv->name) == 0;/*比较设备别名和驱动名称,匹配返回真*/
    27 }

    这个函数比我还单纯,没有啥看的,但是其透露出的消息是重要的.这关系到spi_device和spi_driver的终身幸福,她们能不能彼此走在一起.
    到这里,我觉得已经不可避免的要牵扯出控制器和驱动的注册了,这部分是平台相关的,留待下一节再讲.

  • 相关阅读:
    第二章 1.绘制文本
    在Windows Mobile 5中使用DirectShow控制摄像头转
    写会议纪要也是需要水平滴
    注重实效的程序员(The Pragmatic Programmer)[转载]
    项目经理面试指南(上)[转载]
    上海西门子培训序
    周末桂林游
    我们应该如何面试程序员/技术人员?
    Erlang Code Auto Reloader
    新车落地几种常见的配件加装建议
  • 原文地址:https://www.cnblogs.com/jason-lu/p/3164949.html
Copyright © 2011-2022 走看看