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
#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了.