Linux設備驅動剖析之SPI(三)


572至574行,分配內存,注意對象的類型是struct spidev_data,看下它在drivers/spi/spidev.c中的定義:

00000075 struct spidev_data {
00000076     dev_t            devt;
00000077     spinlock_t        spi_lock;
00000078     struct spi_device    *spi;
00000079     struct list_head    device_entry;
00000080 
00000081     /* buffer is NULL unless this device is open (users > 0) */
00000082     struct mutex        buf_lock;
00000083     unsigned        users;
00000084     u8            *buffer;
00000085 };

76行,設備號。79行,設備鏈表,所有采用此驅動的設備將連成一個鏈表。83行,計數,也即是此設備被open的次數。

回到spidev_probe函數,577至586行,一些鎖和鏈表的初始化。588行,從名字上就可以知道,就是找到第一個為0的位,第一個參數minors的定義:

00000054 #define N_SPI_MINORS            32    /* ... up to 256 */
00000055 
00000056 static DECLARE_BITMAP(minors, N_SPI_MINORS);

DECLARE_BITMAP是一個宏,定義如下:

#define DECLARE_BITMAP(name,bits) \
    unsigned long name[BITS_TO_LONGS(bits)]

將宏展開后是這樣的,unsigned long minors[1],其實就是定義一個只有一個元素的無符號長整形數組miniors。

590至593行,如果找到了非0位,就將它作為次設備號與之前注冊的主設備號生成設備號。

595至598行,創建設備,並生成設備節點,設備節點在/dev目錄下,名字的形式為“spidevx.x”。

603至608行,創建設備成功后,將相應的位置1,表示該次設備號已經被使用,同時將該設備加入到設備鏈表。

611至614行,將設備的私有數據指針指向該設備。

      至此,SPI設備驅動的初始化過程也說完了。下面就以應用程序的操作順序來說,假設是從open-->write這個過程。下面先看驅動中open函數的實現,同樣在drivers/spi/spidev.c:

00000477 static int spidev_open(struct inode *inode, struct file *filp)
00000478 {
00000479     struct spidev_data    *spidev;
00000480     int            status = -ENXIO;
00000481 
00000482     mutex_lock(&device_list_lock);
00000483 
00000484     
00000485     list_for_each_entry(spidev, &device_list, device_entry) {
00000486         if (spidev->devt == inode->i_rdev) {
00000487             status = 0;
00000488             break;
00000489         }
00000490     }
00000491     if (status == 0) {
00000492         if (!spidev->buffer) {
00000493             spidev->buffer = kmalloc(bufsiz, GFP_KERNEL);
00000494             if (!spidev->buffer) {
00000495                 dev_dbg(&spidev->spi->dev, "open/ENOMEM\n");
00000496                 status = -ENOMEM;
00000497             }
00000498         }
00000499         if (status == 0) {
00000500             spidev->users++;
00000501             filp->private_data = spidev;
00000502             nonseekable_open(inode, filp);
00000503         }
00000504     } else
00000505         pr_debug("spidev: nothing for minor %d\n", iminor(inode));
00000506 
00000507     mutex_unlock(&device_list_lock);
00000508     return status;
00000509 }

485至490行,遍歷設備鏈表,每找到一個設備就將它的設備號與打開文件的設備號進行比較,相等的話表示查找成功。

491至505行,查找成功后就分配讀寫數據內存,使用計數加1,設置文件私有數據指針指向查找到的設備,以后在驅動的write、read函數里就可以把它取出來。

     接下來是write函數的定義:

00000190 static ssize_t
00000191 spidev_write(struct file *filp, const char __user *buf,
00000192         size_t count, loff_t *f_pos)
00000193 {
00000194     struct spidev_data    *spidev;
00000195     ssize_t            status = 0;
00000196     unsigned long        missing;
00000197 
00000198     /* chipselect only toggles at start or end of operation */
00000199     if (count > bufsiz)
00000200         return -EMSGSIZE;
00000201 
00000202     spidev = filp->private_data;
00000203 
00000204     mutex_lock(&spidev->buf_lock);
00000205     missing = copy_from_user(spidev->buffer, buf, count);
00000206     if (missing == 0) {
00000207         status = spidev_sync_write(spidev, count);
00000208     } else
00000209         status = -EFAULT;
00000210     mutex_unlock(&spidev->buf_lock);
00000211 
00000212     return status;
00000213 }

199至200行,應用程序寫入的數據不能大於驅動中緩沖區的大小,默認為4096個字節。

202行,指向文件的私有數據。

205行,拷貝用戶空間的數據到內核空間。

207行,spidev_sync_write的定義:

00000130 static inline ssize_t
00000131 spidev_sync_write(struct spidev_data *spidev, size_t len)
00000132 {
00000133     struct spi_transfer    t = {
00000134             .tx_buf        = spidev->buffer,
00000135             .len        = len,
00000136         };
00000137     struct spi_message    m;
00000138 
00000139     spi_message_init(&m);
00000140     spi_message_add_tail(&t, &m);
00000141     return spidev_sync(spidev, &m);
00000142 }

133行,struct spi_transfer的定義在include/linux/spi/spi.h:

00000427 struct spi_transfer {
00000428     /* it's ok if tx_buf == rx_buf (right?)
00000429      * for MicroWire, one buffer must be null
00000430      * buffers must work with dma_*map_single() calls, unless
00000431      *   spi_message.is_dma_mapped reports a pre-existing mapping
00000432      */
00000433     const void    *tx_buf;
00000434     void        *rx_buf;
00000435     unsigned    len;
00000436 
00000437     dma_addr_t    tx_dma;
00000438     dma_addr_t    rx_dma;
00000439 
00000440     unsigned    cs_change:1;
00000441     u8        bits_per_word;
00000442     u16        delay_usecs;
00000443     u32        speed_hz;
00000444 
00000445     struct list_head transfer_list;
00000446 };

433至435行,發送、接收緩沖區和長度。437和438行,發送和接收的DMA地址。

440行,傳輸完成后是否改變片選信號。

441行,如果為0則使用驅動的默認值。

442行,傳輸完成后等待多長時間(毫秒)再改變片選信號。

443行,將多個傳輸連成一個鏈表。

     回到spidev_sync_write函數的137行,在spi.h中定義的struct spi_message:

00000476 struct spi_message {
00000477     struct list_head    transfers;
00000478 
00000479     struct spi_device    *spi;
00000480 
00000481     unsigned        is_dma_mapped:1;
00000482 
00000483     /* REVISIT:  we might want a flag affecting the behavior of the
00000484      * last transfer ... allowing things like "read 16 bit length L"
00000485      * immediately followed by "read L bytes".  Basically imposing
00000486      * a specific message scheduling algorithm.
00000487      *
00000488      * Some controller drivers (message-at-a-time queue processing)
00000489      * could provide that as their default scheduling algorithm.  But
00000490      * others (with multi-message pipelines) could need a flag to
00000491      * tell them about such special cases.
00000492      */
00000493 
00000494     /* completion is reported through a callback */
00000495     void            (*complete)(void *context);
00000496     void            *context;
00000497     unsigned        actual_length;
00000498     int            status;
00000499 
00000500     /* for optional use by whatever driver currently owns the
00000501      * spi_message ...  between calls to spi_async and then later
00000502      * complete(), that's the spi_master controller driver.
00000503      */
00000504     struct list_head    queue;
00000505     void            *state;
00000506 };

477行,一個message可能包含多個transfer,因此用鏈表將這些transfer連起來。

479行,這次message所使用的spi設備。

481行,是否采用DMA的標志。

495行,傳輸完成后的回調函數指針。496行,回調函數的參數。

497行,這次message成功傳輸的字節數。

504和505行,當前驅動擁有的message。

      回到spidev_sync_write函數,139行,spi.h中的內聯函數spi_message_init:

00000508 static inline void spi_message_init(struct spi_message *m)
00000509 {
00000510     memset(m, 0, sizeof *m);
00000511     INIT_LIST_HEAD(&m->transfers);
00000512 }

很簡單,清0內存和初始化message的transfer鏈表。

140行,spi_message_add_tail也是spi.h中的內聯函數:

00000514 static inline void
00000515 spi_message_add_tail(struct spi_transfer *t, struct spi_message *m)
00000516 {
00000517     list_add_tail(&t->transfer_list, &m->transfers);
00000518 }

將transfer加入到鏈表尾。

141行,spidev_sync函數是在drivers/spi/spidev.c中定義的:

00000105 static ssize_t
00000106 spidev_sync(struct spidev_data *spidev, struct spi_message *message)
00000107 {
00000108     DECLARE_COMPLETION_ONSTACK(done);
00000109     int status;
00000110 
00000111     message->complete = spidev_complete;
00000112     message->context = &done;
00000113 
00000114     spin_lock_irq(&spidev->spi_lock);
00000115     if (spidev->spi == NULL)
00000116         status = -ESHUTDOWN;
00000117     else
00000118         status = spi_async(spidev->spi, message);
00000119     spin_unlock_irq(&spidev->spi_lock);
00000120 
00000121     if (status == 0) {
00000122         wait_for_completion(&done);
00000123         status = message->status;
00000124         if (status == 0)
00000125             status = message->actual_length;
00000126     }
00000127     return status;
00000128 }

108行,定義並初始化一個完成量,完成量是Linux的一種同步機制。

111行,spidev_complete函數里就用來喚醒等待completion,定義如下:

00000100 static void spidev_complete(void *arg)
00000101 {
00000102     complete(arg);
00000103 }

112行,作為spidev_complete函數的參數。

118行,調用drivers/spi/spi.c里的spi_async函數,從函數名知道,這是異步實現的。為什么是異步的?往下看就知道了。

00000737 int spi_async(struct spi_device *spi, struct spi_message *message)
00000738 {
00000739     struct spi_master *master = spi->master;
00000740     int ret;
00000741     unsigned long flags;
00000742 
00000743     spin_lock_irqsave(&master->bus_lock_spinlock, flags);
00000744 
00000745     if (master->bus_lock_flag)
00000746         ret = -EBUSY;
00000747     else
00000748         ret = __spi_async(spi, message);
00000749 
00000750     spin_unlock_irqrestore(&master->bus_lock_spinlock, flags);
00000751 
00000752     return ret;
00000753 }

745行,如果master所在的總線被鎖住了,那么就返回忙。

748行,看__spi_async函數的定義:

00000679 static int __spi_async(struct spi_device *spi, struct spi_message *message)
00000680 {
00000681     struct spi_master *master = spi->master;
00000682 
00000683     /* Half-duplex links include original MicroWire, and ones with
00000684      * only one data pin like SPI_3WIRE (switches direction) or where
00000685      * either MOSI or MISO is missing.  They can also be caused by
00000686      * software limitations.
00000687      */
00000688     if ((master->flags & SPI_MASTER_HALF_DUPLEX)
00000689             || (spi->mode & SPI_3WIRE)) {
00000690         struct spi_transfer *xfer;
00000691         unsigned flags = master->flags;
00000692 
00000693         list_for_each_entry(xfer, &message->transfers, transfer_list) {
00000694             if (xfer->rx_buf && xfer->tx_buf)
00000695                 return -EINVAL;
00000696             if ((flags & SPI_MASTER_NO_TX) && xfer->tx_buf)
00000697                 return -EINVAL;
00000698             if ((flags & SPI_MASTER_NO_RX) && xfer->rx_buf)
00000699                 return -EINVAL;
00000700         }
00000701     }
00000702 
00000703     message->spi = spi;
00000704     message->status = -EINPROGRESS;
00000705     return master->transfer(spi, message);
00000706 }

688至701行,如果master設置了SPI_MASTER_HALF_DUPLEX標志,或者spi設備使用的是3線模式,那么就對message里的每一個transfer的發送和接收buf做一些檢查。

705行,調用的是具體的SPI控制器驅動里的函數,這里是drivers/spi/spi_s3c64xx.c里的s3c64xx_spi_transfer函數:

00000763 static int s3c64xx_spi_transfer(struct spi_device *spi,
00000764                         struct spi_message *msg)
00000765 {
00000766     struct s3c64xx_spi_driver_data *sdd;
00000767     unsigned long flags;
00000768 
00000769     sdd = spi_master_get_devdata(spi->master);
00000770 
00000771     spin_lock_irqsave(&sdd->lock, flags);
00000772 
00000773     if (sdd->state & SUSPND) {
00000774         spin_unlock_irqrestore(&sdd->lock, flags);
00000775         return -ESHUTDOWN;
00000776     }
00000777 
00000778     msg->status = -EINPROGRESS;
00000779     msg->actual_length = 0;
00000780 
00000781     list_add_tail(&msg->queue, &sdd->queue);
00000782 
00000783     queue_work(sdd->workqueue, &sdd->work);
00000784 
00000785     spin_unlock_irqrestore(&sdd->lock, flags);
00000786 
00000787     return 0;
00000788 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM