写在前面
初次接触SPI是因为几年前玩单片机的时候,由于普通的51单片机没有SPI控制器,所以只好用IO口去模拟。最近一次接触SPI是大三时参加的校内选拔赛,当时需要用2440去控制nrf24L01,从而实现数据的无线传输。nrf24L01是一种典型的SPI接口的2.4GHz无线收发器,当时搞了很久,由于时间比较紧,而且当时根本不熟悉Linux的SPI子系统,最后虽然采用IO口模拟SPI的方式勉强实现了,但是这根本就不符合Linux驱动的编程规范,或者说是在破坏Linux、污染kernel。
根据我个人所知道的,Linux SPI一直是处于被“忽略”的角色,市场上大部分板子在板级文件里都没有关于SPI的相关代码,而大部分讲驱动的书籍也没有专门的一章来讲述关于Linux SPI方面的内容,与IIC相比,SPI就是一个不被重视的“家伙”,为什么?我也不知道。为了帮SPI抱打不平,我决定基于Linux-2.6.36,说说Linux中SPI子系统。
先给出Linux SPI子系统的体系结构图:
SPI子系统体系结构
下面开始分析SPI子系统。
Linux中SPI子系统的初始化是从drivers/spi/spi.c文件中的spi_init函数开始的,看看它的定义:
00001025 static int __init spi_init(void)
00001026 {
00001027 int status;
00001028
00001029 buf = kmalloc(SPI_BUFSIZ, GFP_KERNEL);
00001030 if (!buf) {
00001031 status = -ENOMEM;
00001032 goto err0;
00001033 }
00001034
00001035 status = bus_register(&spi_bus_type);
00001036 if (status < 0)
00001037 goto err1;
00001038
00001039 status = class_register(&spi_master_class);
00001040 if (status < 0)
00001041 goto err2;
00001042 return 0;
00001043
00001044 err2:
00001045 bus_unregister(&spi_bus_type);
00001046 err1:
00001047 kfree(buf);
00001048 buf = NULL;
00001049 err0:
00001050 return status;
00001051 }
1029行,分配spi buf内存,其中buf和SPI_BUFSIZ都在spi.c文件中定义:
00000945 #define SPI_BUFSIZ max(32,SMP_CACHE_BYTES)
00000946
00000947 static u8 *buf;
1035行,注册spi总线,同样是在spi.c文件中:
00000145 struct bus_type spi_bus_type = {
00000146 .name = "spi",
00000147 .dev_attrs = spi_dev_attrs,
00000148 .match = spi_match_device,
00000149 .uevent = spi_uevent,
00000150 .suspend = spi_suspend,
00000151 .resume = spi_resume,
00000152 };
146行,总线的名字就叫spi。
148行,比较重要的,spi_match_device是spi总线上匹配设备和设备驱动的函数,同样是在spi.c文件中:
00000085 static int spi_match_device(struct device *dev, struct device_driver *drv)
00000086 {
00000087 const struct spi_device *spi = to_spi_device(dev);
00000088 const struct spi_driver *sdrv = to_spi_driver(drv);
00000089
00000090 /* Attempt an OF style match */
00000091 if (of_driver_match_device(dev, drv))
00000092 return 1;
00000093
00000094 if (sdrv->id_table)
00000095 return !!spi_match_id(sdrv->id_table, spi);
00000096
00000097 return strcmp(spi->modalias, drv->name) == 0;
00000098 }
写过驱动的都应该知道platform总线有struct platform_device和struct platform_driver,到了SPI总线,当然也有对应的struct spi_device和struct spi_driver,如87、88行所示。87行,关于struct spi_device的定义是在include/linux/spi/spi.h中:
00000069 struct spi_device {
00000070 struct device dev;
00000071 struct spi_master *master;
00000072 u32 max_speed_hz;
00000073 u8 chip_select;
00000074 u8 mode;
00000075 #