linux spi驱动分析

spi的驱动框架主要分为:
cpu<—platform bus—>spi master 端 <-----spi bus—>spi slave 端

spi master 指的是spi控制器,spi master device是平台设备,spi master driver是平台驱动,它们都挂载在平台总线上

spi slave指的是spi设备,spi device和spi driver分别挂载在spi bus上

drivers/spi/spi.c是spi的主要框架部分,实现的代码跟平台无关:

  struct bus_type spi_bus_type = {                                                                                                          
      .name       = "spi",
      .dev_groups = spi_dev_groups,
      .match      = spi_match_device,
      .uevent     = spi_uevent,
  };
static int __init spi_init(void)
{
status = bus_register(&spi_bus_type);  //注册spi bus
}

注册spi 控制器设备,跟平台相关,通过解析dts:
platform_device_register(&sprd_spi_controller_device[0]);
注册spi控制器驱动,这里以amlogic的spi控制器为例:

//drivers/amlogic/spicc/spicc.c
  static struct platform_driver spicc_driver = {
      .probe = spicc_probe,                                                                                                                 
      .remove = spicc_remove,
      .suspend = spicc_suspend,
      .resume = spicc_resume,
      .driver = {
              .name = "spicc",
              .of_match_table = spicc_of_match,
              .owner = THIS_MODULE,
          },   
  };
  static int __init spicc_init(void)
  {
      return platform_driver_register(&spicc_driver);
  }
    static int spicc_probe(struct platform_device *pdev)                                                                                      
  { 
  		...
        master = spi_alloc_master(&pdev->dev, sizeof(*spicc)); //spi控制器设备
       master->dev.of_node = pdev->dev.of_node;  //spi控制器设备相关的信息
      master->bus_num = spicc->device_id;
      master->setup = spicc_setup;   //实际调用的是spi具体的控制器驱动
      master->transfer = spicc_transfer;
      master->cleanup = spicc_cleanup;
      master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
     spi_register_master(master); //注册master
   }

每个master都对应一个bus num。
注册spi slave设备,由dts解析得到,dts会指定spi slave 挂载在哪个bus num下,由bus num就可以得到对应的spi master 了:

//1.由dts中描述的slave device挂载的bus_num得到master
struct spi_master * spi_busnum_to_master(u16 bus_num)
//2. 在该master下alloc一个设备
struct spi_device *spi_alloc_device(struct spi_master *master)
//3.注册设备
spi_add_device()
  struct spi_device {
    struct device       dev; 
      struct spi_master   *master;   //该设备在哪个master下
    u32         max_speed_hz;
    u8          chip_select;
    u8          bits_per_word;
    u16         mode;
    ...
  }

注册spi slave驱动:

spi_register_driver(&rv3049_driver);

spi slave设备驱动只是实现了数据的逻辑操作,不实现接口相关,当要进行接口数据传输时,调用struct spi_device中的master进行,这样就能做到驱动和接口解耦,这样驱动更通用,在不同的总线上都可以使用。

发布了85 篇原创文章 · 获赞 26 · 访问量 12万+

猜你喜欢

转载自blog.csdn.net/whuzm08/article/details/88696251