内核版本: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的终身幸福,她们能不能彼此走在一起.
到这里,我觉得已经不可避免的要牵扯出控制器和驱动的注册了,这部分是平台相关的,留待下一节再讲.