在3.2之前版本的内核里spi驱动要先注册spi_board_info结构体,产生spi主控制器设备(platform device),然后匹配spi_master_driver(platform driver,这个文件是spi-rt2880.c). 匹配上之后就会进入probe函数,注册spi主控制器,再查找spi主控制器下有没有挂设备,如果有就创建spi_device. 创建完设备之后再到spi总线上寻找有没有同名的spi_driver(例如spidev.c). 如果有的话就调用spi_driver的probe函数. 在probe函数里register_chrdev/class_create/device_create, 创建chrdev然后通过fops里的函数来读写spi设备.在新版的内核里推荐使用dts来描述设备信息, 并且先注册spi_master, 然后再创建设备, 最后跟platform总线上的driver的 .of_match_table成员里的元素匹配, 如果匹配成功就调用probe. 所以新版的内核里我们不需要再写spi_baord_info 和spi_register_board_info这样的代码了.
查看文件mt7620a.dtsi
spi@b00 {
compatible = "ralink,mt7620a-spi", "ralink,rt2880-spi";
reg = <0xb00 0x100>;
resets = <&rstctrl 18>;
reset-names = "spi";
#address-cells = <1>;
#size-cells = <1>;
status = "disabled";
pinctrl-names = "default";
pinctrl-0 = <&spi_pins>;
};
spi@b00代表一个spi控制器,是一个platform device,compatible="ralink, rt2880-spi"与 spi-rt2880.c platform driver 中的of_match_table 对应(如果要支持片选1,还得修改num_cs=2,前提是mt7620的spi控制器本来就支持两个片选).相同就会进入到probe函数中,再调用spi_register_master()注册一个spi主控制器.
看看MT7620a.dts
status = "okay";
m25p80@0 {
#address-cells = <1>;
#size-cells = <1>;
compatible = "en25q64";
reg = <0 0>;
linux,modalias = "m25p80", "en25q64";
spi-max-frequency = <10000000>;
spi_register_master注册spi主控制器时就会扫描这些设备,并注册这些设备。 status = “okay”表示选中,否则不能编译进内核. m25p80@0表示在spi片选0下挂了一个m25p80的设备,reg=<0,0>表示片选0,compatible = "en25q64" 与驱动文件drivers/mtd/devices/m25p80.c 中的id_table匹配.如果要在spi控制器的片选1上挂一个设备,就要修改dts文件,修改如下:
spidev@1 {
compatible = "rohm,dh2228fv";
reg = <1 0>;
spi-max-frequency = <1000000>;
};
compatible = "rohm,dh2228fv"与spidev.c文件中的of_match_table 对应,对应成功就会进入到probe,这样一个spidev设备节点就会出现了。