Linux SPI设备驱动框架

本文深入探讨了Linux SPI子系统的架构原理,详细介绍了关键数据结构如spi_master、spi_device及spi_driver,并分析了SPI总线注册流程、从设备与驱动匹配机制及数据传输过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

转载出处:http://blog.youkuaiyun.com/vanbreaker/article/details/7733476

      

一 、


       Linux的SPI子系统采用主机驱动和外设驱动分离的思想,首先主机SPI控制器是一种平台设备,因此它以platform的方式注册进内核,外设的信息是以boardinfo形式静态定义的,在创建spi_master时,会根据外设的bus_num和主机的bus_num是否相等,来选择是否将该外设挂接在该SPI主控制器下。先看SPI子系统中几个关键的数据结构:

struct spi_master用来描述一个SPI主控制器

[cpp]  view plain  copy
  1. struct spi_master {  
  2.     struct device    dev;  
  3.     s16    bus_num; /*总线编号*/  
  4.     u16    num_chipselect;/*支持的外设数量*/  
  5.     u16    dma_alignment;  
  6.     int   (*transfer)(struct spi_device *spi, struct spi_message *mesg);/*用于将消息添加到队列*/  
  7.     void  (*cleanup)(struct spi_device *spi);  
  8. };  


struct spi_device用来描述一个SPI从设备

[cpp]  view plain  copy
  1. struct spi_device {  
  2.     struct device       dev;  
  3.     struct spi_master   *master;                 /*从设备所属的SPI主控器*/  
  4.     u32         max_speed_hz;   /*最大传输频率*/  
  5.     u8          chip_select;    /*片选号,用于区别其他从设备*/  
  6.     u8          mode;           /*传输模式*/  
  7. /*各个mode的定义*/  
  8. #define SPI_CPHA    0x01             /* clock phase */  
  9. #define SPI_CPOL    0x02             /* clock polarity */  
  10. #define SPI_MODE_0  (0|0)        /* (original MicroWire) */  
  11. #define SPI_MODE_1  (0|SPI_CPHA)  
  12. #define SPI_MODE_2  (SPI_CPOL|0)  
  13. #define SPI_MODE_3  (SPI_CPOL|SPI_CPHA)  
  14. #define SPI_CS_HIGH 0x04         /* chipselect active high? */  
  15. #define SPI_LSB_FIRST   0x08         /* per-word bits-on-wire */  
  16. #define SPI_3WIRE   0x10             /* SI/SO signals shared */  
  17. #define SPI_LOOP    0x20             /* loopback mode */  
  18.     u8          bits_per_word; /*每个字的比特数*/  
  19.     int         irq;           /*所使用的中断*/  
  20.     void            *controller_state;  
  21.     void            *controller_data;  
  22.     char            modalias[32];  /*设备名,在和从设备驱动匹配时会用到*/  
  23.   
  24. };  


struct spi_driver用来描述一个SPI从设备的驱动,它的形式和struct platform_driver是一致的

[cpp]  view plain  copy
  1. struct spi_driver {  
  2.     int         (*probe)(struct spi_device *spi);  
  3.     int         (*remove)(struct spi_device *spi);  
  4.     void            (*shutdown)(struct spi_device *spi);  
  5.     int         (*suspend)(struct spi_device *spi, pm_message_t mesg);  
  6.     int         (*resume)(struct spi_device *spi);  
  7.     struct device_driver    driver;  
  8. };  


SPI子系统初始化的第一步就是将SPI总线注册进内核,并且在/sys下创建一个spi_master的类,以后注册的从设备都将挂接在该总线下

[cpp]  view plain  copy
  1. static int __init spi_init(void)  
  2. {  
  3.     int status;  
  4.   
  5.     buf = kmalloc(SPI_BUFSIZ, GFP_KERNEL);  
  6.     if (!buf) {  
  7.         status = -ENOMEM;  
  8.         goto err0;  
  9.     }  
  10.   
  11.     status = bus_register(&spi_bus_type);//注册SPI总线  
  12.     if (status < 0)  
  13.         goto err1;  
  14.   
  15.     status = class_register(&spi_master_class);//注册spi_master类  
  16.     if (status < 0)  
  17.         goto err2;  
  18.     return 0;  
  19.   
  20. err2:  
  21.     bus_unregister(&spi_bus_type);  
  22. err1:  
  23.     kfree(buf);  
  24.     buf = NULL;  
  25. err0:  
  26.     return status;  
  27. }  


我们来看spi_bus_type的定义

[cpp]  view plain  copy
  1. struct bus_type spi_bus_type = {  
  2.     .name       = "spi",  
  3.     .dev_attrs  = spi_dev_attrs,  
  4.     .match      = spi_match_device,  
  5.     .uevent     = spi_uevent,  
  6.     .suspend    = spi_suspend,  
  7.     .resume     = spi_resume,  
  8. };  

来看挂接在SPI总线下的从设备和从设备驱动是如何匹配的,也就是spi_match_device函数

[cpp]  view plain  copy
  1. static int spi_match_device(struct device *dev, struct device_driver *drv)  
  2. {  
  3.     const struct spi_device *spi = to_spi_device(dev);  
  4.   
  5.     return strcmp(spi->modalias, drv->name) == 0;  
  6. }  


这里可以看到是将struct device_driver中的name字段与struct spi_device中的modalias字段进行匹配

 

这里已经完成了SPI子系统初始化的第一步,也就是注册SPI总线,这一步是和平台无关的,第二步是和平台相关的初始化。


二、


       上面介绍了SPI子系统中的一些重要数据结构和SPI子系统初始化的第一步,也就是注册SPI总线。这节介绍针对于s3c24xx平台的SPI子系统初始化,在看具体的代码之前,先上一张自己画的图,帮助理清初始化的主要步骤

 

显然,SPI是一种平台特定的资源,所以它是以platform平台设备的方式注册进内核的,因此它的struct platform_device结构是已经静态定义好了的,现在只待它的struct platform_driver注册,然后和platform_device匹配。

 

初始化的入口:

[html]  view plain  copy
  1. static int __init s3c24xx_spi_init(void)  
  2. {  
  3.         return platform_driver_probe(&s3c24xx_spi_driver, s3c24xx_spi_probe);  
  4. }  


platform_driver_probe()会调用platform_driver_register()来注册驱动,然后在注册的过程中寻求匹配的platform_device,一旦匹配成功,便会调用probe函数,也就是s3c24xx_spi_probe(),在看这个函数之前,还得介绍几个相关的数据结构。

struct s3c2410_spi_info是一个板级结构,也是在移植时就定义好的,在初始化spi_master时用到,platform_device-->dev-->platform_data会指向这个结构。

[cpp]  view plain  copy
  1. struct s3c2410_spi_info {  
  2.     int          pin_cs;    /* simple gpio cs */  
  3.     unsigned int         num_cs;    /* total chipselects */  
  4.     int          bus_num;/* bus number to use. */  
  5.   
  6.     void (*gpio_setup)(struct s3c2410_spi_info *spi, int enable);  
  7.     void (*set_cs)(struct s3c2410_spi_info *spi, int cs, int pol);  
  8. };  

 

struct s3c24xx_spi用来具体描述s3c24xx平台上一个SPI控制器

[cpp]  view plain  copy
  1. struct s3c24xx_spi {  
  2.     /* bitbang has to be first */  
  3.     struct spi_bitbang   bitbang;  
  4.     struct completion    done;  
  5.   
  6.     void __iomem        *regs;  
  7.     int          irq;  
  8.     int          len;  
  9.     int          count;  
  10.   
  11.     void            (*set_cs)(struct s3c2410_spi_info *spi,  
  12.                       int cs, int pol);  
  13.   
  14.     /* data buffers */  
  15.     const unsigned char *tx;  
  16.     unsigned char       *rx;  
  17.   
  18.     struct clk      *clk;  
  19.     struct resource     *ioarea;  
  20.     struct spi_master   *master;  
  21.     struct spi_device   *curdev;  
  22.     struct device       *dev;  
  23.     struct s3c2410_spi_info *pdata;  
  24. };  


struct spi_bitbang用于控制实际的数据传输

[cpp]  view plain  copy
  1. struct spi_bitbang {  
  2.     struct workqueue_struct *workqueue;  /*工作队列*/  
  3.     struct work_struct  work;  
  4.   
  5.     spinlock_t      lock;  
  6.     struct list_head    queue;  
  7.     u8          busy;  
  8.     u8          use_dma;  
  9.     u8          flags;      /* extra spi->mode support */  
  10.   
  11.     struct spi_master   *master;         /*bitbang所属的master*/  
  12.   
  13.      /*用于设置设备传输时的时钟,字长等*/  
  14.     int (*setup_transfer)(struct spi_device *spi,  
  15.             struct spi_transfer *t);  
  16.   
  17.     void    (*chipselect)(struct spi_device *spi, int is_on);  
  18. #define BITBANG_CS_ACTIVE   1   /* normally nCS, active low */  
  19. #define BITBANG_CS_INACTIVE 0  
  20.   
  21.     /*针对于平台的传输控制函数*/  
  22.     int (*txrx_bufs)(struct spi_device *spi, struct spi_transfer *t);  
  23.   
  24.     /* txrx_word[SPI_MODE_*]() just looks like a shift register */  
  25.     u32 (*txrx_word[4])(struct spi_device *spi,  
  26.             unsigned nsecs,  
  27.             u32 word, u8 bits);  
  28. };  

 

下面来看s3c24xx_spi_probe()函数的实现

[cpp]  view plain  copy
  1. static int __init s3c24xx_spi_probe(struct platform_device *pdev)  
  2. {  
  3.     struct s3c2410_spi_info *pdata;  
  4.     struct s3c24xx_spi *hw;  
  5.     struct spi_master *master;  
  6.     struct resource *res;  
  7.     int err = 0;  
  8.   
  9.     /*创建spi_master,并将spi_master->private_data指向s3c24xx_spi*/  
  10.     master = spi_alloc_master(&pdev->dev, sizeof(struct s3c24xx_spi));  
  11.     if (master == NULL) {  
  12.         dev_err(&pdev->dev, "No memory for spi_master\n");  
  13.         err = -ENOMEM;  
  14.         goto err_nomem;  
  15.     }  
  16.   
  17.     hw = spi_master_get_devdata(master);//获取s3c24xx_spi  
  18.     memset(hw, 0, sizeof(struct s3c24xx_spi));  
  19.   
  20.     hw->master = spi_master_get(master);  
  21.     hw->pdata = pdata = pdev->dev.platform_data;  
  22.     hw->dev = &pdev->dev;  
  23.   
  24.     if (pdata == NULL) {  
  25.         dev_err(&pdev->dev, "No platform data supplied\n");  
  26.         err = -ENOENT;  
  27.         goto err_no_pdata;  
  28.     }  
  29.   
  30.     platform_set_drvdata(pdev, hw);  
  31.     init_completion(&hw->done);  
  32.   
  33.     /* setup the master state. */  
  34.          /*片选数和SPI主控制器编号是在platform_data中已经定义好了的*/  
  35.     master->num_chipselect = hw->pdata->num_cs;  
  36.     master->bus_num = pdata->bus_num;  
  37.   
  38.     /* setup the state for the bitbang driver */  
  39.   
  40.     /*设置bitbang的所属master和控制传输的相关函数*/  
  41.     hw->bitbang.master         = hw->master;  
  42.     hw->bitbang.setup_transfer = s3c24xx_spi_setupxfer;  
  43.     hw->bitbang.chipselect     = s3c24xx_spi_chipsel;  
  44.     hw->bitbang.txrx_bufs      = s3c24xx_spi_txrx;  
  45.     hw->bitbang.master->setup  = s3c24xx_spi_setup;  
  46.   
  47.     dev_dbg(hw->dev, "bitbang at %p\n", &hw->bitbang);  
  48.   
  49.     /* find and map our resources */  
  50.   
  51.     res = platform_get_resource(pdev, IORESOURCE_MEM, 0);  
  52.     if (res == NULL) {  
  53.         dev_err(&pdev->dev, "Cannot get IORESOURCE_MEM\n");  
  54.         err = -ENOENT;  
  55.         goto err_no_iores;  
  56.     }  
  57.   
  58.     hw->ioarea = request_mem_region(res->start, (res->end - res->start)+1,  
  59.                     pdev->name);  
  60.   
  61.     if (hw->ioarea == NULL) {  
  62.         dev_err(&pdev->dev, "Cannot reserve region\n");  
  63.         err = -ENXIO;  
  64.         goto err_no_iores;  
  65.     }  
  66.   
  67.     /*映射SPI控制寄存器*/  
  68.     hw->regs = ioremap(res->start, (res->end - res->start)+1);  
  69.     if (hw->regs == NULL) {  
  70.         dev_err(&pdev->dev, "Cannot map IO\n");  
  71.         err = -ENXIO;  
  72.         goto err_no_iomap;  
  73.     }  
  74.   
  75.     /*获取中断号*/  
  76.     hw->irq = platform_get_irq(pdev, 0);  
  77.     if (hw->irq < 0) {  
  78.         dev_err(&pdev->dev, "No IRQ specified\n");  
  79.         err = -ENOENT;  
  80.         goto err_no_irq;  
  81.     }  
  82.   
  83.     /*注册中断*/  
  84.     err = request_irq(hw->irq, s3c24xx_spi_irq, 0, pdev->name, hw);  
  85.     if (err) {  
  86.         dev_err(&pdev->dev, "Cannot claim IRQ\n");  
  87.         goto err_no_irq;  
  88.     }  
  89.   
  90.     hw->clk = clk_get(&pdev->dev, "spi");  
  91.     if (IS_ERR(hw->clk)) {  
  92.         dev_err(&pdev->dev, "No clock for device\n");  
  93.         err = PTR_ERR(hw->clk);  
  94.         goto err_no_clk;  
  95.     }  
  96.   
  97.     /* setup any gpio we can */  
  98.   
  99.     if (!pdata->set_cs) {  
  100.         if (pdata->pin_cs < 0) {  
  101.             dev_err(&pdev->dev, "No chipselect pin\n");  
  102.             goto err_register;  
  103.         }  
  104.   
  105.         err = gpio_request(pdata->pin_cs, dev_name(&pdev->dev));  
  106.         if (err) {  
  107.             dev_err(&pdev->dev, "Failed to get gpio for cs\n");  
  108.             goto err_register;  
  109.         }  
  110.           
  111.         hw->set_cs = s3c24xx_spi_gpiocs;//设定片选函数  
  112.         gpio_direction_output(pdata->pin_cs, 1);  
  113.     } else  
  114.         hw->set_cs = pdata->set_cs;  
  115.   
  116.     s3c24xx_spi_initialsetup(hw);  
  117.   
  118.     /* register our spi controller */  
  119.          /* 注册主机SPI控制器 */  
  120.     err = spi_bitbang_start(&hw->bitbang);  
  121.     if (err) {  
  122.         dev_err(&pdev->dev, "Failed to register SPI master\n");  
  123.         goto err_register;  
  124.     }  
  125.   
  126.     return 0;  
  127.   
  128.  err_register:  
  129.     if (hw->set_cs == s3c24xx_spi_gpiocs)  
  130.         gpio_free(pdata->pin_cs);  
  131.   
  132.     clk_disable(hw->clk);  
  133.     clk_put(hw->clk);  
  134.   
  135.  err_no_clk:  
  136.     free_irq(hw->irq, hw);  
  137.   
  138.  err_no_irq:  
  139.     iounmap(hw->regs);  

[cpp]  view plain  copy
  1. int spi_bitbang_start(struct spi_bitbang *bitbang)  
  2. {  
  3.     int status;  
  4.   
  5.     if (!bitbang->master || !bitbang->chipselect)  
  6.         return -EINVAL;  
  7.   
  8.     /*初始化一个struct work,处理函数为bitbang_work*/  
  9.     INIT_WORK(&bitbang->work, bitbang_work);  
  10.     spin_lock_init(&bitbang->lock);  
  11.     INIT_LIST_HEAD(&bitbang->queue);  
  12.   
  13.     /*检测bitbang中的函数是否都定义了,如果没定义,则默认使用spi_bitbang_xxx*/  
  14.     if (!bitbang->master->transfer)  
  15.         bitbang->master->transfer = spi_bitbang_transfer;  
  16.     if (!bitbang->txrx_bufs) {  
  17.         bitbang->use_dma = 0;  
  18.         bitbang->txrx_bufs = spi_bitbang_bufs;  
  19.         if (!bitbang->master->setup) {  
  20.             if (!bitbang->setup_transfer)  
  21.                 bitbang->setup_transfer =  
  22.                      spi_bitbang_setup_transfer;  
  23.             bitbang->master->setup = spi_bitbang_setup;  
  24.             bitbang->master->cleanup = spi_bitbang_cleanup;  
  25.         }  
  26.     } else if (!bitbang->master->setup)  
  27.         return -EINVAL;  
  28.   
  29.     /* this task is the only thing to touch the SPI bits */  
  30.     bitbang->busy = 0;  
  31.     /*创建bitbang的工作队列*/  
  32.     bitbang->workqueue = create_singlethread_workqueue(  
  33.             dev_name(bitbang->master->dev.parent));  
  34.     if (bitbang->workqueue == NULL) {  
  35.         status = -EBUSY;  
  36.         goto err1;  
  37.     }  
  38.   
  39.     /* driver may get busy before register() returns, especially 
  40.      * if someone registered boardinfo for devices 
  41.      */  
  42.      /*注册spi_master*/  
  43.     status = spi_register_master(bitbang->master);  
  44.     if (status < 0)  
  45.         goto err2;  
  46.   
  47.     return status;  
  48.   
  49. err2:  
  50.     destroy_workqueue(bitbang->workqueue);  
  51. err1:  
  52.     return status;  
  53. }  

 

下一个关键函数就是spi_register_master(),用于注册spi_master

[cpp]  view plain  copy
  1. int spi_register_master(struct spi_master *master)  
  2. {  
  3.     static atomic_t     dyn_bus_id = ATOMIC_INIT((1<<15) - 1);  
  4.     struct device       *dev = master->dev.parent;  
  5.     int         status = -ENODEV;  
  6.     int         dynamic = 0;  
  7.   
  8.     if (!dev)  
  9.         return -ENODEV;  
  10.   
  11.     /* even if it's just one always-selected device, there must 
  12.      * be at least one chipselect 
  13.      */  
  14.     if (master->num_chipselect == 0)//片选数不能为0  
  15.         return -EINVAL;  
  16.   
  17.     /* convention:  dynamically assigned bus IDs count down from the max */  
  18.     if (master->bus_num < 0) {  
  19.         /* FIXME switch to an IDR based scheme, something like 
  20.          * I2C now uses, so we can't run out of "dynamic" IDs 
  21.          */  
  22.         master->bus_num = atomic_dec_return(&dyn_bus_id);  
  23.         dynamic = 1;  
  24.     }  
  25.   
  26.     /* register the device, then userspace will see it. 
  27.      * registration fails if the bus ID is in use. 
  28.      */  
  29.     dev_set_name(&master->dev, "spi%u", master->bus_num);  
  30.     status = device_add(&master->dev);//添加spi_master设备  
  31.     if (status < 0)  
  32.         goto done;  
  33.     dev_dbg(dev, "registered master %s%s\n", dev_name(&master->dev),  
  34.             dynamic ? " (dynamic)" : "");  
  35.   
  36.     /* populate children from any spi device tables */  
  37.     scan_boardinfo(master);//遍历板级信息,寻找可以挂接在该spi_master下的从设备  
  38.     status = 0;  
  39. done:  
  40.     return status;  
  41. }  


 

[cpp]  view plain  copy
  1. static void scan_boardinfo(struct spi_master *master)  
  2. {  
  3.     struct boardinfo    *bi;  
  4.   
  5.     mutex_lock(&board_lock);  
  6.     list_for_each_entry(bi, &board_list, list) {  
  7.         struct spi_board_info   *chip = bi->board_info;  
  8.         unsigned        n;  
  9.   
  10.         for (n = bi->n_board_info; n > 0; n--, chip++) {  
  11.             if (chip->bus_num != master->bus_num)  
  12.                 continue;  
  13.             /* NOTE: this relies on spi_new_device to 
  14.              * issue diagnostics when given bogus inputs 
  15.              */  
  16.              /*bus_num相等则创建新设备*/  
  17.             (void) spi_new_device(master, chip);  
  18.         }  
  19.     }  
  20.     mutex_unlock(&board_lock);  
  21. }  


spi_board_info是板级信息,是在移植时就写好的,并且要将其注册

[cpp]  view plain  copy
  1. struct spi_board_info {  
  2.     char        modalias[32];  /*名字*/  
  3.     const void  *platform_data;  
  4.     void        *controller_data;  
  5.     int     irq;          /*中断号*/  
  6.     u32     max_speed_hz; /*最高传输速率*/  
  7.     u16     bus_num;      /*所属的spi_master编号*/  
  8.     u16     chip_select;  /*片选号*/  
  9.   
  10.     u8      mode;         /*传输模式*/  
  11.   
  12. };  

 

最后一步就是将相应的从设备注册进内核

[cpp]  view plain  copy
  1. struct spi_device *spi_new_device(struct spi_master *master,  
  2.                   struct spi_board_info *chip)  
  3. {  
  4.     struct spi_device   *proxy;  
  5.     int         status;  
  6.   
  7.     /* NOTE:  caller did any chip->bus_num checks necessary. 
  8.      * 
  9.      * Also, unless we change the return value convention to use 
  10.      * error-or-pointer (not NULL-or-pointer), troubleshootability 
  11.      * suggests syslogged diagnostics are best here (ugh). 
  12.      */  
  13.   
  14.     /*创建SPI_device*/  
  15.     proxy = spi_alloc_device(master);  
  16.     if (!proxy)  
  17.         return NULL;  
  18.   
  19.     WARN_ON(strlen(chip->modalias) >= sizeof(proxy->modalias));  
  20.   
  21.     /*初始化*/  
  22.     proxy->chip_select = chip->chip_select;  
  23.     proxy->max_speed_hz = chip->max_speed_hz;  
  24.     proxy->mode = chip->mode;  
  25.     proxy->irq = chip->irq;  
  26.     strlcpy(proxy->modalias, chip->modalias, sizeof(proxy->modalias));  
  27.     proxy->dev.platform_data = (void *) chip->platform_data;  
  28.     proxy->controller_data = chip->controller_data;  
  29.     proxy->controller_state = NULL;  
  30.   
  31.     /*将新设备添加进内核*/  
  32.     status = spi_add_device(proxy);  
  33.     if (status < 0) {  
  34.         spi_dev_put(proxy);  
  35.         return NULL;  
  36.     }  
  37.   
  38.     return proxy;  
  39. }  

三、


最后以spidev设备驱动为例,来阐述SPI数据传输的过程。spidev是内核中一个通用的设备驱动,我们注册的从设备都可以使用该驱动,只需在注册时将从设备的modalias字段设置为"spidev",这样才能和spidev驱动匹配成功。我们要传输的数据有时需要分为一段一段的(比如先发送,后读取,就需要两个字段),每个字段都被封装成一个transfer,N个transfer可以被添加到message中,作为一个消息包进行传输。当用户发出传输数据的请求时,message并不会立刻传输到从设备,而是由之前定义的transfer()函数将message放入一个等待队列中,这些message会以FIFO的方式有workqueue调度进行传输,这样能够避免SPI从设备同一时间对主SPI控制器的竞争。和之前一样,还是习惯先画一张图来描述数据传输的主要过程。

 

         在使用spidev设备驱动时,需要先初始化spidev. spidev是以字符设备的形式注册进内核的。

[cpp]  view plain  copy
  1. static int __init spidev_init(void)  
  2. {  
  3.     int status;  
  4.   
  5.     /* Claim our 256 reserved device numbers.  Then register a class 
  6.      * that will key udev/mdev to add/remove /dev nodes.  Last, register 
  7.      * the driver which manages those device numbers. 
  8.      */  
  9.     BUILD_BUG_ON(N_SPI_MINORS > 256);  
  10.     /*将spidev作为字符设备注册*/  
  11.     status = register_chrdev(SPIDEV_MAJOR, "spi", &spidev_fops);  
  12.     if (status < 0)  
  13.         return status;  
  14.   
  15.     /*创建spidev类*/  
  16.     spidev_class = class_create(THIS_MODULE, "spidev");  
  17.     if (IS_ERR(spidev_class)) {  
  18.         unregister_chrdev(SPIDEV_MAJOR, spidev_spi.driver.name);  
  19.         return PTR_ERR(spidev_class);  
  20.     }  
  21.   
  22.     /*注册spidev的driver,可与modalias字段为"spidev"的spi_device匹配*/  
  23.     status = spi_register_driver(&spidev_spi);  
  24.     if (status < 0) {  
  25.         class_destroy(spidev_class);  
  26.         unregister_chrdev(SPIDEV_MAJOR, spidev_spi.driver.name);  
  27.     }  
  28.     return status;  
  29. }  


与相应的从设备匹配成功后,则调用spidev中的probe函数

[cpp]  view plain  copy
  1. static int spidev_probe(struct spi_device *spi)  
  2. {  
  3.     struct spidev_data  *spidev;  
  4.     int         status;  
  5.     unsigned long       minor;  
  6.   
  7.     /* Allocate driver data */  
  8.     spidev = kzalloc(sizeof(*spidev), GFP_KERNEL);  
  9.     if (!spidev)  
  10.         return -ENOMEM;  
  11.   
  12.     /* Initialize the driver data */  
  13.     spidev->spi = spi;//设定spi  
  14.     spin_lock_init(&spidev->spi_lock);  
  15.     mutex_init(&spidev->buf_lock);  
  16.   
  17.     INIT_LIST_HEAD(&spidev->device_entry);  
  18.   
  19.     /* If we can allocate a minor number, hook up this device. 
  20.      * Reusing minors is fine so long as udev or mdev is working. 
  21.      */  
  22.     mutex_lock(&device_list_lock);  
  23.     minor = find_first_zero_bit(minors, N_SPI_MINORS);//寻找没被占用的次设备号  
  24.     if (minor < N_SPI_MINORS) {  
  25.         struct device *dev;  
  26.         /*计算设备号*/  
  27.         spidev->devt = MKDEV(SPIDEV_MAJOR, minor);  
  28.         /*在spidev_class下创建设备*/  
  29.         dev = device_create(spidev_class, &spi->dev, spidev->devt,  
  30.                     spidev, "spidev%d.%d",  
  31.                     spi->master->bus_num, spi->chip_select);  
  32.         status = IS_ERR(dev) ? PTR_ERR(dev) : 0;  
  33.     } else {  
  34.         dev_dbg(&spi->dev, "no minor number available!\n");  
  35.         status = -ENODEV;  
  36.     }  
  37.     if (status == 0) {  
  38.         set_bit(minor, minors);//将minors的相应位置位,表示该位对应的次设备号已被占用  
  39.         list_add(&spidev->device_entry, &device_list);//将创建的spidev添加到device_list  
  40.     }  
  41.     mutex_unlock(&device_list_lock);  
  42.   
  43.     if (status == 0)  
  44.         spi_set_drvdata(spi, spidev);  
  45.     else  
  46.         kfree(spidev);  
  47.   
  48.     return status;  
  49. }  


然后就可以利用spidev模块提供的接口来实现主从设备之间的数据传输了。我们以spidev_write()函数为例来分析数据传输的过程,实际上spidev_read()和其是差不多的,只是前面的一些步骤不一样,可以参照上图。

[cpp]  view plain  copy
  1. static ssize_t  
  2. spidev_write(struct file *filp, const char __user *buf,  
  3.         size_t count, loff_t *f_pos)  
  4. {  
  5.     struct spidev_data  *spidev;  
  6.     ssize_t         status = 0;  
  7.     unsigned long       missing;  
  8.   
  9.     /* chipselect only toggles at start or end of operation */  
  10.     if (count > bufsiz)  
  11.         return -EMSGSIZE;  
  12.   
  13.     spidev = filp->private_data;  
  14.   
  15.     mutex_lock(&spidev->buf_lock);  
  16.     //将用户要发送的数据拷贝到spidev->buffer  
  17.     missing = copy_from_user(spidev->buffer, buf, count);  
  18.     if (missing == 0) {//全部拷贝成功,则调用spidev_sysn_write()  
  19.         status = spidev_sync_write(spidev, count);  
  20.     } else  
  21.         status = -EFAULT;  
  22.     mutex_unlock(&spidev->buf_lock);  
  23.   
  24.     return status;  
  25. }  


 

[cpp]  view plain  copy
  1. static inline ssize_t  
  2. spidev_sync_write(struct spidev_data *spidev, size_t len)  
  3. {  
  4.     struct spi_transfer t = {//设置传输字段  
  5.             .tx_buf     = spidev->buffer,  
  6.             .len        = len,  
  7.         };  
  8.     struct spi_message   m;//创建message  
  9.   
  10.     spi_message_init(&m);  
  11.     spi_message_add_tail(&t, &m);//将transfer添加到message中  
  12.     return spidev_sync(spidev, &m);  
  13. }  


我们来看看struct spi_transfer和struct spi_message是如何定义的

[cpp]  view plain  copy
  1. struct spi_transfer {  
  2.     /* it's ok if tx_buf == rx_buf (right?) 
  3.      * for MicroWire, one buffer must be null 
  4.      * buffers must work with dma_*map_single() calls, unless 
  5.      *   spi_message.is_dma_mapped reports a pre-existing mapping 
  6.      */  
  7.     const void  *tx_buf;//发送缓冲区  
  8.     void        *rx_buf;//接收缓冲区  
  9.     unsigned    len;    //传输数据的长度  
  10.   
  11.     dma_addr_t  tx_dma;  
  12.     dma_addr_t  rx_dma;  
  13.   
  14.     unsigned    cs_change:1; //该位如果为1,则表示当该transfer传输完后,改变片选信号  
  15.     u8      bits_per_word;//字比特数  
  16.     u16     delay_usecs;  //传输后的延时   
  17.     u32     speed_hz;  //指定的时钟  
  18.   
  19.     struct list_head transfer_list;//用于将该transfer链入message  
  20. };  


 

[cpp]  view plain  copy
  1. struct spi_message {  
  2.     struct list_head    transfers;//用于链接spi_transfer  
  3.   
  4.     struct spi_device   *spi;      //指向目的从设备  
  5.   
  6.     unsigned        is_dma_mapped:1;  
  7.   
  8.     /* REVISIT:  we might want a flag affecting the behavior of the 
  9.      * last transfer ... allowing things like "read 16 bit length L" 
  10.      * immediately followed by "read L bytes".  Basically imposing 
  11.      * a specific message scheduling algorithm. 
  12.      * 
  13.      * Some controller drivers (message-at-a-time queue processing) 
  14.      * could provide that as their default scheduling algorithm.  But 
  15.      * others (with multi-message pipelines) could need a flag to 
  16.      * tell them about such special cases. 
  17.      */  
  18.   
  19.     /* completion is reported through a callback */  
  20.     void            (*complete)(void *context);//用于异步传输完成时调用的回调函数  
  21.     void            *context;                  //回调函数的参数  
  22.     unsigned        actual_length;            //实际传输的长度  
  23.     int         status;  
  24.   
  25.     /* for optional use by whatever driver currently owns the 
  26.      * spi_message ...  between calls to spi_async and then later 
  27.      * complete(), that's the spi_master controller driver. 
  28.      */  
  29.     struct list_head    queue; //用于将该message链入bitbang等待队列  
  30.     void            *state;  
  31. };  


继续跟踪源码,进入spidev_sync(),从这一步开始,read和write就完全一样了

[cpp]  view plain  copy
  1. <span style="font-size:12px;">static ssize_t  
  2. spidev_sync(struct spidev_data *spidev, struct spi_message *message)  
  3. {  
  4.     DECLARE_COMPLETION_ONSTACK(done);  
  5.     int status;  
  6.   
  7.     message->complete = spidev_complete;//设置回调函数  
  8.     message->context = &done;              
  9.   
  10.     spin_lock_irq(&spidev->spi_lock);  
  11.     if (spidev->spi == NULL)  
  12.         status = -ESHUTDOWN;  
  13.     else  
  14.         status = spi_async(spidev->spi, message);//调用spi核心层的函数spi_async()  
  15.     spin_unlock_irq(&spidev->spi_lock);  
  16.   
  17.     if (status == 0) {  
  18.         wait_for_completion(&done);  
  19.         status = message->status;  
  20.         if (status == 0)  
  21.             status = message->actual_length;  
  22.     }  
  23.     return status;  
  24. }</span>  


 

[cpp]  view plain  copy
  1. static inline int  
  2. spi_async(struct spi_device *spi, struct spi_message *message)  
  3. {  
  4.     message->spi = spi;  
  5.     /*调用master的transfer函数将message放入等待队列*/  
  6.     return spi->master->transfer(spi, message);  
  7. }  


 

s3c24xx平台下的transfer函数是在bitbang_start()函数中定义的,为bitbang_transfer()

[cpp]  view plain  copy
  1. int spi_bitbang_transfer(struct spi_device *spi, struct spi_message *m)  
  2. {  
  3.     struct spi_bitbang  *bitbang;  
  4.     unsigned long       flags;  
  5.     int         status = 0;  
  6.   
  7.     m->actual_length = 0;  
  8.     m->status = -EINPROGRESS;  
  9.   
  10.     bitbang = spi_master_get_devdata(spi->master);  
  11.   
  12.     spin_lock_irqsave(&bitbang->lock, flags);  
  13.     if (!spi->max_speed_hz)  
  14.         status = -ENETDOWN;  
  15.     else {  
  16.         list_add_tail(&m->queue, &bitbang->queue);//将message添加到bitbang的等待队列  
  17.         queue_work(bitbang->workqueue, &bitbang->work);//调度运行work  
  18.     }  
  19.     spin_unlock_irqrestore(&bitbang->lock, flags);  
  20.   
  21.     return status;  
  22. }  

这里可以看到transfer函数不负责实际的数据传输,而是将message添加到等待队列中。同样在spi_bitbang_start()中,有这样一个定义INIT_WORK(&bitbang->work, bitbang_work);因此bitbang_work()函数会被调度运行,类似于底半部机制

[cpp]  view plain  copy
  1. static void bitbang_work(struct work_struct *work)  
  2. {  
  3.     struct spi_bitbang  *bitbang =  
  4.         container_of(work, struct spi_bitbang, work);//获取bitbang  
  5.     unsigned long       flags;  
  6.   
  7.     spin_lock_irqsave(&bitbang->lock, flags);  
  8.     bitbang->busy = 1;  
  9.     while (!list_empty(&bitbang->queue)) {//等待队列不为空  
  10.         struct spi_message  *m;  
  11.         struct spi_device   *spi;  
  12.         unsigned        nsecs;  
  13.         struct spi_transfer *t = NULL;  
  14.         unsigned        tmp;  
  15.         unsigned        cs_change;  
  16.         int         status;  
  17.         int         (*setup_transfer)(struct spi_device *,  
  18.                         struct spi_transfer *);  
  19.         /*取出等待队列中的的第一个message*/  
  20.         m = container_of(bitbang->queue.next, struct spi_message,  
  21.                 queue);  
  22.         list_del_init(&m->queue);//将message从队列中删除  
  23.         spin_unlock_irqrestore(&bitbang->lock, flags);  
  24.   
  25.         /* FIXME this is made-up ... the correct value is known to 
  26.          * word-at-a-time bitbang code, and presumably chipselect() 
  27.          * should enforce these requirements too? 
  28.          */  
  29.         nsecs = 100;  
  30.   
  31.         spi = m->spi;  
  32.         tmp = 0;  
  33.         cs_change = 1;  
  34.         status = 0;  
  35.         setup_transfer = NULL;  
  36.   
  37.         /*遍历message中的所有传输字段,逐一进行传输*/  
  38.         list_for_each_entry (t, &m->transfers, transfer_list) {  
  39.   
  40.             /* override or restore speed and wordsize */  
  41.             if (t->speed_hz || t->bits_per_word) {  
  42.                 setup_transfer = bitbang->setup_transfer;  
  43.                 if (!setup_transfer) {  
  44.                     status = -ENOPROTOOPT;  
  45.                     break;  
  46.                 }  
  47.             }  
  48.             /*调用setup_transfer根据transfer中的信息进行时钟、字比特数的设定*/  
  49.             if (setup_transfer) {  
  50.                 status = setup_transfer(spi, t);  
  51.                 if (status < 0)  
  52.                     break;  
  53.             }  
  54.   
  55.             /* set up default clock polarity, and activate chip; 
  56.              * this implicitly updates clock and spi modes as 
  57.              * previously recorded for this device via setup(). 
  58.              * (and also deselects any other chip that might be 
  59.              * selected ...) 
  60.              */  
  61.             if (cs_change) {//使能外设的片选  
  62.                 bitbang->chipselect(spi, BITBANG_CS_ACTIVE);  
  63.                 ndelay(nsecs);  
  64.             }  
  65.             cs_change = t->cs_change;//这里确定进行了这个字段的传输后是否要改变片选状态  
  66.             if (!t->tx_buf && !t->rx_buf && t->len) {  
  67.                 status = -EINVAL;  
  68.                 break;  
  69.             }  
  70.   
  71.             /* transfer data.  the lower level code handles any 
  72.              * new dma mappings it needs. our caller always gave 
  73.              * us dma-safe buffers. 
  74.              */  
  75.             if (t->len) {  
  76.                 /* REVISIT dma API still needs a designated 
  77.                  * DMA_ADDR_INVALID; ~0 might be better. 
  78.                  */  
  79.                 if (!m->is_dma_mapped)  
  80.                     t->rx_dma = t->tx_dma = 0;  
  81.                 /*调用针对于平台的传输函数txrx_bufs*/  
  82.                 status = bitbang->txrx_bufs(spi, t);  
  83.             }  
  84.             if (status > 0)  
  85.                 m->actual_length += status;  
  86.             if (status != t->len) {  
  87.                 /* always report some kind of error */  
  88.                 if (status >= 0)  
  89.                     status = -EREMOTEIO;  
  90.                 break;  
  91.             }  
  92.             status = 0;  
  93.   
  94.             /* protocol tweaks before next transfer */  
  95.             /*如果要求在传输完一个字段后进行delay,则进行delay*/  
  96.             if (t->delay_usecs)  
  97.                 udelay(t->delay_usecs);  
  98.   
  99.             if (!cs_change)  
  100.                 continue;  
  101.               
  102.             /*最后一个字段传输完毕了,则跳出循环*/  
  103.             if (t->transfer_list.next == &m->transfers)  
  104.                 break;  
  105.   
  106.             /* sometimes a short mid-message deselect of the chip 
  107.              * may be needed to terminate a mode or command 
  108.              */  
  109.             ndelay(nsecs);  
  110.             bitbang->chipselect(spi, BITBANG_CS_INACTIVE);  
  111.             ndelay(nsecs);  
  112.         }  
  113.   
  114.         m->status = status;  
  115.         m->complete(m->context);  
  116.   
  117.         /* restore speed and wordsize */  
  118.         if (setup_transfer)  
  119.             setup_transfer(spi, NULL);  
  120.   
  121.         /* normally deactivate chipselect ... unless no error and 
  122.          * cs_change has hinted that the next message will probably 
  123.          * be for this chip too. 
  124.          */  
  125.         if (!(status == 0 && cs_change)) {  
  126.             ndelay(nsecs);  
  127.             bitbang->chipselect(spi, BITBANG_CS_INACTIVE);  
  128.             ndelay(nsecs);  
  129.         }  
  130.   
  131.         spin_lock_irqsave(&bitbang->lock, flags);  
  132.     }  
  133.     bitbang->busy = 0;  
  134.     spin_unlock_irqrestore(&bitbang->lock, flags);  
  135. }  


只要bitbang->queue等待队列不为空,就表示相应的SPI主控制器上还有传输任务没有完成,因此bitbang_work()会被不断地调度执行。 bitbang_work()中的工作主要是两个循环,外循环遍历等待队列中的message,内循环遍历message中的transfer,在bitbang_work()中,传输总是以transfer为单位的。当选定了一个transfer后,便会调用transfer_txrx()函数,进行实际的数据传输,显然这个函数是针对于平台的SPI控制器而实现的,在s3c24xx平台中,该函数为s3c24xx_spi_txrx();

[cpp]  view plain  copy
  1. static int s3c24xx_spi_txrx(struct spi_device *spi, struct spi_transfer *t)  
  2. {  
  3.     struct s3c24xx_spi *hw = to_hw(spi);  
  4.   
  5.     dev_dbg(&spi->dev, "txrx: tx %p, rx %p, len %d\n",  
  6.         t->tx_buf, t->rx_buf, t->len);  
  7.   
  8.     hw->tx = t->tx_buf;//获取发送缓冲区  
  9.     hw->rx = t->rx_buf;//获取读取缓存区  
  10.     hw->len = t->len;  //获取数据长度  
  11.     hw->count = 0;  
  12.   
  13.     init_completion(&hw->done);//初始化完成量  
  14.   
  15.     /* send the first byte */  
  16.     /*只发送第一个字节,其他的在中断中发送(读取)*/  
  17.     writeb(hw_txbyte(hw, 0), hw->regs + S3C2410_SPTDAT);  
  18.   
  19.     wait_for_completion(&hw->done);  
  20.   
  21.     return hw->count;  
  22. }  


 

[cpp]  view plain  copy
  1. static inline unsigned int hw_txbyte(struct s3c24xx_spi *hw, int count)  
  2. {  
  3.     /*如果tx不为空,也就是说当前是从主机向从机发送数据,则直接将tx[count]发送过去, 
  4.       如果tx为空,也就是说当前是从从机向主机发送数据,则向从机写入0*/  
  5.     return hw->tx ? hw->tx[count] : 0;  
  6. }  


负责SPI数据传输的中断函数:

[cpp]  view plain  copy
  1. static irqreturn_t s3c24xx_spi_irq(int irq, void *dev)  
  2. {  
  3.     struct s3c24xx_spi *hw = dev;  
  4.     unsigned int spsta = readb(hw->regs + S3C2410_SPSTA);  
  5.     unsigned int count = hw->count;  
  6.   
  7.     /*冲突检测*/  
  8.     if (spsta & S3C2410_SPSTA_DCOL) {  
  9.         dev_dbg(hw->dev, "data-collision\n");  
  10.         complete(&hw->done);  
  11.         goto irq_done;  
  12.     }  
  13.   
  14.     /*设备忙检测*/  
  15.     if (!(spsta & S3C2410_SPSTA_READY)) {  
  16.         dev_dbg(hw->dev, "spi not ready for tx?\n");  
  17.         complete(&hw->done);  
  18.         goto irq_done;  
  19.     }  
  20.   
  21.     hw->count++;  
  22.   
  23.     if (hw->rx)//读取数据到缓冲区  
  24.         hw->rx[count] = readb(hw->regs + S3C2410_SPRDAT);  
  25.   
  26.     count++;  
  27.   
  28.     if (count < hw->len)//向从机写入数据  
  29.         writeb(hw_txbyte(hw, count), hw->regs + S3C2410_SPTDAT);  
  30.     else//count == len,一个字段发送完成,唤醒完成量  
  31.         complete(&hw->done);  
  32.   
  33.  irq_done:  
  34.     return IRQ_HANDLED;  
  35. }  

这里可以看到一点,即使tx为空,也就是说用户申请的是从从设备读取数据,也要不断地向从设备写入数据,只不过写入从设备的是无效数据(0),这样做得目的是为了维持SPI总线上的时钟。至此,SPI框架已分析完毕。






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值