Linux中SPI子系统图解和mini2440下的SPI驱动移植

来源:互联网 发布:淘宝店铺租金 编辑:程序博客网 时间:2024/06/05 06:29

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文件,加入头文件:

  1. #include<linux/spi/spi.h>   
  2. #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中加入:

  1. static structs3c2410_spi_info s3c2410_spi0_platdata = {  
  2.     .pin_cs= S3C2410_GPG(2),//这个得看你的板子具体情形了   
  3.     .num_cs= 1, //有一个slave   
  4.     .bus_num= 0, //只有一条SPI总线   
  5.     .gpio_setup =s3c24xx_spi_gpiocfg_bus0_gpe11_12_13,  
  6. };  

接着在mini2440_machine_init中加入:

  1. s3c_device_spi0.dev.platform_data=&s3c2410_spi0_platdata;  

controller的平台驱动:s3c24xx_spi_driver,在makemenuconfig时打开便好;

总线spi_bus_type:spi核心,在makemenuconfig时打开便好;

controller驱动:也不需要动;

板级设备信息,即你的slave和总线的连接:

  1. spi_board_info:在mach-mini2440.c中加入s3c2410_spi0_board,如下  
  2. static structspi_board_info s3c2410_spi0_board[] = {  
  3.     [0] = {  
  4.         .modalias= "adns3080"//需要和你的驱动一致   
  5.         .bus_num= 0,  
  6.         .platform_data =&adns3080_data,  
  7.         .chip_select= 0,  
  8.         .irq =IRQ_EINT9,  
  9.         .max_speed_hz= 500 * 1000,  
  10.     }  
  11. };  

外加头文件(有必要的话):adns3080.h

  1. #ifndef __SPI_PLATFORM_ADNS3080_H__   
  2. #define __SPI_PLATFORM_ADNS3080_H__   
  3. struct adns3080_platform_data{  
  4.     your_data_0;  
  5. };  
  6. #endif   
  7. static structadns3080_platform_data adns3080_data = {  
  8.     .your_data_0 =your_data,  
  9. };  

接着在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文件

找到如下代码段:

  1. configS3C24XX_SPI_BUS0_GPE11_GPE12_GPE13  
  2.     bool  
  3.     help  
  4.     SPI GPIOconfiguration code for BUS0 when connected to GPE11, GPE12 andGPE13.  
  1. configS3C24XX_SPI_BUS1_GPG5_GPG6_GPG7  
  2.     bool  
  3.     help  
  4.     SPI GPIOconfiguration code for BUS 1 when connected to GPG5, GPG6 andGPG7.  
  1. configS3C24XX_SPI_BUS0_GPE11_GPE12_GPE13  
  2.     bool"S3C24XX_SPI_BUS0_GPE11_GPE12_GPE13" // 管脚可以看芯片手册   
  3.     help  
  4.     SPI GPIOconfiguration code for BUS0 when connected to GPE11, GPE12 andGPE13.  //spi_bus0   
  5.   
  6. configS3C24XX_SPI_BUS1_GPG5_GPG6_GPG7  
  7.     bool"S3C24XX_SPI_BUS1_GPG5_GPG6_GPG7"  
  8.     help  
  9.     SPI GPIOconfiguration code for BUS 1 when connected to GPG5,GPG6 and GPG7. //spi_bus1  

最后的make menuconfig了.