1.SPI子系統框圖詳解:
SPI總線上有兩類設備:一類是主控端,通常作爲SOC系統的一個子模塊出現,比如很多嵌入式MPU中都常常包含SPI模塊。一類是受控端,例如一些SPI接口的Flash、傳感器等等。主控端是SPI總線的控制者,通過使用SPI協議主動發起SPI總線上的會話。而受控端則被動接受SPI主控端的指令,並作出響應的響應。
如圖1所示,linux下的spi子系統主要涉及3個部分:spi核心、spiprotocol驅動和spi主控制器驅動。如圖1.1,spi核心負責抽象出所有控制器都具備的功能代碼,同時向上爲spiprotocol驅動提供接口比如spi_message、spi_transfer,spi_async等,具體可參見linux/spi/spi.h文件,需要自己寫客戶驅動的可以詳細瞭解一下spi.h文件。
spi控制器驅動負責與具體的控制器硬件溝通,進行bit級的數據傳輸。
spi客戶驅動,即protocol驅動負責從控制器端接收數據,然後按照“protocol”將其解釋爲有意義的數據格式。
圖2則顯示了Linux下SPI子系統所涉及的大部分結構和函數調用,其中一些細節可以在這裏找到你想要得。
2. SPI驅動移植
平臺:mini2440
kernel:linux-2.6.32.2
Master:SPI0
Slave:of
從圖2中我們看出,要進行驅動移植,大致要做的就是完成上面的6個主要結構的註冊,使系統能夠識別他們。
首先:在LinuxSource Code中修改arch/arm/mach-s3c2440/mach-mini2440.c文件,加入頭文件:
#include<linux/spi/spi.h>
#include<../mach-s3c2410/include/mach/spi.h>
接着是各個結構的註冊:
-
s3c_device_spi0:在devs.c中定義,需要在板級文件mach-mini2440.c中mini2440_devices[]平臺數組中添加如下代碼:
&s3c_device_spi0,
s3c2410_spi_info:就是s3c_device_spi0的platform_data,用來初始化master,給出了總線有幾條,和其相連的slave數量,設置片選的函數...也需要在mach-mini2440.c中加入:static structs3c2410_spi_info s3c2410_spi0_platdata = { .pin_cs= S3C2410_GPG(2),//這個得看你的板子具體情形了 .num_cs= 1, //有一個slave .bus_num= 0, //只有一條SPI總線 .gpio_setup =s3c24xx_spi_gpiocfg_bus0_gpe11_12_13, };
接着在mini2440_machine_init中加入:s3c_device_spi0.dev.platform_data=&s3c2410_spi0_platdata;
-
controller的平臺驅動:s3c24xx_spi_driver,在makemenuconfig時打開便好;
-
總線spi_bus_type:spi核心,在makemenuconfig時打開便好;
-
controller驅動:也不需要動;
-
板級設備信息,即你的slave和總線的連接:
spi_board_info:在mach-mini2440.c中加入s3c2410_spi0_board,如下 static structspi_board_info s3c2410_spi0_board[] = { [0] = { .modalias= "adns3080", //需要和你的驅動一致 .bus_num= 0, .platform_data =&adns3080_data, .chip_select= 0, .irq =IRQ_EINT9, .max_speed_hz= 500 * 1000, } };
外加頭文件(有必要的話):adns3080.h
#ifndef __SPI_PLATFORM_ADNS3080_H__ #define __SPI_PLATFORM_ADNS3080_H__ struct adns3080_platform_data{ your_data_0; }; #endif static structadns3080_platform_data adns3080_data = { .your_data_0 =your_data, };
接着在mini2440_machine_init中加入:spi_register_board_info(s3c2410_spi0_board,ARRAY_SIZE(s3c2410_spi0_board));
6. my_driver:其實可以沒有my_driver這一步,這需要你自己寫的,在module_init中會註冊的...也可以使用kernel自帶的spidev.c驅動,這就需要打開SPIDEV的支持:在makemenuconfig時:
Device Drivers
SPI support
User mode SPIdevicedriver support //打開這一項
然後是板級信息:
7.接着就不是結構註冊,上面如果是板級,下面就得是芯片級了。配置文件的改動:
需要修改arch/arm/plat-s3c24xx/KConfig文件
找到如下代碼段:
configS3C24XX_SPI_BUS0_GPE11_GPE12_GPE13
bool
help
SPI GPIOconfiguration code for BUS0 when connected to GPE11, GPE12 andGPE13.
configS3C24XX_SPI_BUS1_GPG5_GPG6_GPG7
bool
help
SPI GPIOconfiguration code for BUS 1 when connected to GPG5, GPG6 andGPG7.
修改爲
configS3C24XX_SPI_BUS0_GPE11_GPE12_GPE13
bool"S3C24XX_SPI_BUS0_GPE11_GPE12_GPE13" // 管腳可以看芯片手冊
help
SPI GPIOconfiguration code for BUS0 when connected to GPE11, GPE12 andGPE13. //spi_bus0
configS3C24XX_SPI_BUS1_GPG5_GPG6_GPG7
bool"S3C24XX_SPI_BUS1_GPG5_GPG6_GPG7"
help
SPI GPIOconfiguration code for BUS 1 when connected to GPG5,GPG6 and GPG7. //spi_bus1
最後的make menuconfig了 ...