Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2675718
  • 博文数量: 877
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 5921
  • 用 户 组: 普通用户
  • 注册时间: 2013-12-05 12:25
个人简介

技术的乐趣在于分享,欢迎多多交流,多多沟通。

文章分类

全部博文(877)

文章存档

2021年(2)

2016年(20)

2015年(471)

2014年(358)

2013年(26)

分类: LINUX

2014-08-15 15:44:46

原文地址:spi子系统分析 作者:wangchenxicool

上文从下到上的介绍了spi子系统,现在反过来从上到下的来介绍spi子系统的使用:
  1. int spi_register_driver(struct spi_driver *sdrv)
  2. {
  3.         sdrv->driver.bus = &spi_bus_type;
  4.         if (sdrv->probe)
  5.                 sdrv->driver.probe = spi_drv_probe;
  6.         if (sdrv->remove)
  7.                 sdrv->driver.remove = spi_drv_remove;
  8.         if (sdrv->shutdown)
  9.                 sdrv->driver.shutdown = spi_drv_shutdown;
  10.         return driver_register(&sdrv->driver);
  11. }
2.6内核的典型做法,不直接使用原始设备驱动,而是使用包装后的抽象设备驱动spi_driver, 间接与原始设备驱动建立联系,并最终通过调用driver_register来注册原始设备驱动(要充分理解2.6内核的抽象化思想)。
注:
    以后我们也不会直接与原始设备打交道了,而是通过spi_device来间接操作spi设备了^_^

 
  1. /**
  2. * spi_write_then_read - SPI synchronous write followed by read
  3. * @spi: device with which data will be exchanged
  4. * @txbuf: data to be written (need not be dma-safe)
  5. * @n_tx: size of txbuf, in bytes
  6. * @rxbuf: buffer into which data will be read
  7. * @n_rx: size of rxbuf, in bytes (need not be dma-safe)
  8. *
  9. * This performs a half duplex MicroWire style transaction with the
  10. * device, sending txbuf and then reading rxbuf. The return value
  11. * is zero for success, else a negative errno status code.
  12. * This call may only be used from a context that may sleep.
  13. *
  14. * Parameters to this routine are always copied using a small buffer;
  15. * performance-sensitive or bulk transfer code should instead use
  16. * spi_{async,sync}() calls with dma-safe buffers.
  17. */
  18. /*
  19. * spi_write_then_read比较简单,容易说明spi的使用,用它来作例子比较合适
  20. */
  21. int spi_write_then_read(struct spi_device *spi,
  22.                 const u8 *txbuf, unsigned n_tx,
  23.                 u8 *rxbuf, unsigned n_rx)
  24. {
  25.         static DECLARE_MUTEX(lock);
  26.         int status;
  27.         struct spi_message message;
  28.         struct spi_transfer x[2];
  29.         u8 *local_buf;
  30.         /* Use preallocated DMA-safe buffer. We can't avoid copying here,
  31.          * (as a pure convenience thing), but we can keep heap costs
  32.          * out of the hot path ...
  33.          */
  34.         if ((n_tx + n_rx) > SPI_BUFSIZ)//SPI_BUFSIZ == 32

  35.                 return -EINVAL;
  36.      /* 这里初始化message结构里面用于存放struct spi_transfer指针的链表头 */
  37.         spi_message_init(&message);//INIT_LIST_HEAD(&message->transfers);

  38.         memset(x, 0, sizeof x);
  39.      /* 留意到没有:tx和rx个占一个工作添加到message的struct spi_transfer链表里,稍后被bitbang_work从链表里提出来处理(后面会讲到) */
  40.         if (n_tx) {
  41.                 x[0].len = n_tx;
  42.                 spi_message_add_tail(&x[0], &message);//list_add_tail(&t->transfer_list, &m->transfers);

  43.         }
  44.         if (n_rx) {
  45.                 x[1].len = n_rx;
  46.                 spi_message_add_tail(&x[1], &message);
  47.         }
  48.         /* ... unless someone else is using the pre-allocated buffer */
  49.         /* 如果有人在用这个预分配的缓存,那没办法了,只能再分配一个临时的,用完再释放掉 */
  50.         if (down_trylock(&lock)) {
  51.                 local_buf = kmalloc(SPI_BUFSIZ, GFP_KERNEL);
  52.                 if (!local_buf)
  53.                         return -ENOMEM;
  54.         } else
  55.                 local_buf = buf;//否则就采用预分配的缓存吧

  56.         /* local_buf的前部分用来存放要发送的数据,后部分用来存放接收到的数据 */
  57.         memcpy(local_buf, txbuf, n_tx);
  58.         x[0].tx_buf = local_buf;
  59.         x[1].rx_buf = local_buf + n_tx;
  60.         /* do the i/o */
  61.         status = spi_sync(spi, &message);//同步io,等待spi传输完成,然后返回用户所接收的数据和状态

  62.         if (status == 0) {
  63.                 memcpy(rxbuf, x[1].rx_buf, n_rx);
  64.                 status = message.status;
  65.         }
  66.         if (x[0].tx_buf == buf)//如果使用的是预分配的缓存,释放锁好让其它人使用

  67.                 up(&lock);
  68.         else
  69.                 kfree(local_buf);//如果使用的是临时申请的缓存,释放之

  70.         return status;
  71. }
  72. /*
  73. * spi_sync - blocking/synchronous SPI data transfers
  74. * @spi: device with which data will be exchanged
  75. * @message: describes the data transfers
  76. *
  77. * This call may only be used from a context that may sleep. The sleep
  78. * is non-interruptible, and has no timeout. Low-overhead controller
  79. * drivers may DMA directly into and out of the message buffers.
  80. *
  81. * Note that the SPI device's chip select is active during the message,
  82. * and then is normally disabled between messages. Drivers for some
  83. * frequently-used devices may want to minimize costs of selecting a chip,
  84. * by leaving it selected in anticipation that the next message will go
  85. * to the same chip. (That may increase power usage.)
  86. *
  87. * Also, the caller is guaranteeing that the memory associated with the
  88. * message will not be freed before this call returns.
  89. *
  90. * The return value is a negative error code if the message could not be
  91. * submitted, else zero. When the value is zero, then message->status is
  92. * also defined: it's the completion code for the transfer, either zero
  93. * or a negative error code from the controller driver.
  94. */
  95. int spi_sync(struct spi_device *spi, struct spi_message *message)
  96. {
  97.         DECLARE_COMPLETION_ONSTACK(done);//声明一个完成变量

  98.         int status;
  99.         message->complete = spi_complete;//spi传输完成后的回调函数

  100.         message->context = &done;
  101.         status = spi_async(spi, message);
  102.         if (status == 0)
  103.                 wait_for_completion(&done);//等待spi传输,调用spi_complete后返回

  104.         message->context = NULL;
  105.         return status;
  106. }
  107. /*
  108. * spi_async -- asynchronous SPI transfer
  109. * @spi: device with which data will be exchanged
  110. * @message: describes the data transfers, including completion callback
  111. *
  112. * This call may be used in_irq and other contexts which can't sleep,
  113. * as well as from task contexts which can sleep.
  114. *
  115. * The completion callback is invoked in a context which can't sleep.
  116. * Before that invocation, the value of message->status is undefined.
  117. * When the callback is issued, message->status holds either zero (to
  118. * indicate complete success) or a negative error code. After that
  119. * callback returns, the driver which issued the transfer request may
  120. * deallocate the associated memory; it's no longer in use by any SPI
  121. * core or controller driver code.
  122. *
  123. * Note that although all messages to a spi_device are handled in
  124. * FIFO order, messages may go to different devices in other orders.
  125. * Some device might be higher priority, or have various "hard" access
  126. * time requirements, for example.
  127. *
  128. * On detection of any fault during the transfer, processing of
  129. * the entire message is aborted, and the device is deselected.
  130. * Until returning from the associated message completion callback,
  131. * no other spi_message queued to that device will be processed.
  132. * (This rule applies equally to all the synchronous transfer calls,
  133. * which are wrappers around this core asynchronous primitive.)
  134. */
  135. static inline int
  136. spi_async(struct spi_device *spi, struct spi_message *message)
  137. {
  138.         printk("spi_async\n");
  139.         message->spi = spi;
  140.         return spi->master->transfer(spi, message);//调用spi_bitbang_transfer传输数据

  141. }
  142. /*
  143. * spi_bitbang_transfer - default submit to transfer queue
  144. */
  145. int spi_bitbang_transfer(struct spi_device *spi, struct spi_message *m)
  146. {
  147.         struct spi_bitbang *bitbang;
  148.         unsigned long flags;
  149.         int status = 0;
  150.         m->actual_length = 0;
  151.         m->status = -EINPROGRESS;
  152.         bitbang = spi_master_get_devdata(spi->master);
  153.      /*
  154.       * 还记得spi_alloc_master函数中调用spi_master_set_devdata把struct s3c24xx_spi结构存放起来吧?
  155.       * 而struct spi_bitbang结构正是struct s3c24xx_spi结构所包含的第一个结构
  156.       */
  157.         if (bitbang->shutdown)
  158.                 return -ESHUTDOWN;
  159.         spin_lock_irqsave(&bitbang->lock, flags);
  160.         if (!spi->max_speed_hz)
  161.                 status = -ENETDOWN;
  162.         else {
  163.                 list_add_tail(&m->queue, &bitbang->queue);//把message加入到bitang的等待队列中

  164.                 queue_work(bitbang->workqueue, &bitbang->work);//把bitbang-work加入bitbang->workqueue中,调度运行

  165.         }
  166.         spin_unlock_irqrestore(&bitbang->lock, flags);
  167.         return status;
  168. }
好了,稍微总结一下:
spi的读写请求通过:spi_transfer->spi_message->spi_bitbang添加都bitbang->queue中,被bitbang->work反方向提取出来执行(后面会提到)。
通 过queue_work(bitbang->workqueue, &bitbang->work)把bitbang-work加入bitbang->workqueue后,在某个合适的时间, bitbang->work将被调度运行,bitbang_work函数将被调用:
  1. /*
  2. * SECOND PART ... simple transfer queue runner.
  3. *
  4. * This costs a task context per controller, running the queue by
  5. * performing each transfer in sequence. Smarter hardware can queue
  6. * several DMA transfers at once, and process several controller queues
  7. * in parallel; this driver doesn't match such hardware very well.
  8. *
  9. * Drivers can provide word-at-a-time i/o primitives, or provide
  10. * transfer-at-a-time ones to leverage dma or fifo hardware.
  11. */
  12. static void bitbang_work(void *_bitbang)
  13. {
  14.         struct spi_bitbang *bitbang = _bitbang;
  15.         unsigned long flags;
  16.         spin_lock_irqsave(&bitbang->lock, flags);
  17.         bitbang->busy = 1;//置忙标志

  18.         while (!list_empty(&bitbang->queue)) { //遍历bitbang->queue链表

  19.                 struct spi_message *m;
  20.                 struct spi_device *spi;
  21.                 unsigned nsecs;
  22.                 struct spi_transfer *t = NULL;
  23.                 unsigned tmp;
  24.                 unsigned cs_change;
  25.                 int status;
  26.                 int (*setup_transfer)(struct spi_device *,
  27.                                                 struct spi_transfer *);
  28.                 m = container_of(bitbang->queue.next, struct spi_message, queue);//获取spi_message结构

  29.                 list_del_init(&m->queue);//把spi_messae从queue里删除

  30.                 spin_unlock_irqrestore(&bitbang->lock, flags);
  31.                 /* FIXME this is made-up ... the correct value is known to
  32.                  * word-at-a-time bitbang code, and presumably chipselect()
  33.                  * should enforce these requirements too?
  34.                  */
  35.                 nsecs = 100;
  36.                 spi = m->spi;
  37.                 tmp = 0;
  38.                 cs_change = 1;
  39.                 status = 0;
  40.                 setup_transfer = NULL;
  41.                 list_for_each_entry (t, &m->transfers, transfer_list) {//从spi_message结构的transfers链表中获取spi_transfer结构

  42.                         if (bitbang->shutdown) {
  43.                                 status = -ESHUTDOWN;
  44.                                 break;
  45.                            }
  46.                         /* override or restore speed and wordsize */
  47.                 /* 本messae传输中,需要重设条件,调用setup_transfer函数 */
  48.                         if (t->speed_hz || t->bits_per_word) {
  49.                                 setup_transfer = bitbang->setup_transfer;
  50.                                 if (!setup_transfer) {
  51.                                         status = -ENOPROTOOPT;
  52.                                         break;
  53.                                 }
  54.                            }
  55.                         if (setup_transfer) {
  56.                                 status = setup_transfer(spi, t);
  57.                                 if (status //片选激活spi

  58.                                 bitbang->chipselect(spi, BITBANG_CS_ACTIVE);
  59.                                 ndelay(nsecs);
  60.                          }
  61.                       cs_change = t->cs_change;
  62.                       if (!t->tx_buf && !t->rx_buf && t->len) {
  63.                                 status = -EINVAL;
  64.                                 break;
  65.                          }
  66.                         /* transfer data. the lower level code handles any
  67.                          * new dma mappings it needs. our caller always gave
  68.                          * us dma-safe buffers.
  69.                          */
  70.                         if (t->len) {
  71.                                 /* REVISIT dma API still needs a designated
  72.                                  * DMA_ADDR_INVALID; ~0 might be better.
  73.                                  */
  74.                                 if (!m->is_dma_mapped)
  75.                                         t->rx_dma = t->tx_dma = 0;
  76.                                 status = bitbang->txrx_bufs(spi, t);//调用s3c24xx_spi_txrx开始传输数据

  77.                            }
  78.                         if (status != t->len) {
  79.                                 if (status > 0)
  80.                                         status = -EMSGSIZE;
  81.                                 break;
  82.                            }
  83.                         m->actual_length += status;
  84.                         status = 0;
  85.                         /* protocol tweaks before next transfer */
  86.                         if (t->delay_usecs)
  87.                                 udelay(t->delay_usecs);
  88.                         if (!cs_change)
  89.                                 continue;//不用重新片选,继续下一个message的传输

  90.                         if (t->transfer_list.next == &m->transfers)//链表遍历完毕,退出循环

  91.                                 break;
  92.                         /* sometimes a short mid-message deselect of the chip
  93.                          * may be needed to terminate a mode or command
  94.                          */
  95.                         ndelay(nsecs);
  96.                         bitbang->chipselect(spi, BITBANG_CS_INACTIVE);//需要重新片选的话...

  97.                         ndelay(nsecs);
  98.                 }
  99.                 m->status = status;//所用spi_message传输完毕

  100.                 m->complete(m->context);//应答返回变量,通知等待spi传输完毕的进程(具体来说就是spi_sync函数了)

  101.                 /* restore speed and wordsize */
  102.           /* 前面重设过条件的,在这恢复之 */
  103.                 if (setup_transfer)
  104.                         setup_transfer(spi, NULL);
  105.                 /* normally deactivate chipselect ... unless no error and
  106.                  * cs_change has hinted that the next message will probably
  107.                  * be for this chip too.
  108.                  */
  109.                 if (!(status == 0 && cs_change)) {
  110.                         ndelay(nsecs);
  111.                         bitbang->chipselect(spi, BITBANG_CS_INACTIVE);
  112.                         ndelay(nsecs);
  113.                 }
  114.                 spin_lock_irqsave(&bitbang->lock, flags);//重新获取自旋锁,遍历工作者队列的下一个工作

  115.         }
  116.         bitbang->busy = 0;//处理完毕,清除忙标志

  117.         spin_unlock_irqrestore(&bitbang->lock, flags);
  118. }
  119. static int s3c24xx_spi_txrx(struct spi_device *spi, struct spi_transfer *t)
  120. {
  121.         struct s3c24xx_spi *hw = to_hw(spi);
  122.         dev_dbg(&spi->dev, "txrx: tx %p, rx %p, len %d\n",
  123.                 t->tx_buf, t->rx_buf, t->len);
  124.         hw->tx = t->tx_buf;//发送指针

  125.         hw->rx = t->rx_buf;//接收指针

  126.         hw->len = t->len;//需要发送/接收的数据数目

  127.         hw->count = 0;//存放实际spi传输的数据数目

  128.         /* send the first byte */
  129.         writeb(hw_txbyte(hw, 0), hw->regs + S3C2410_SPTDAT);
  130.         wait_for_completion(&hw->done);
  131.         /*
  132.          * 非常有意思,这里虽然只发送第一字节,可是中断里会帮你发送完其它的字节(并接收数据),
  133.          * 直到所有的数据发送完毕且所要接收的数据接收完毕(首要)才返回
  134.          */
  135.         return hw->count;
  136. }
  137. static irqreturn_t s3c24xx_spi_irq(int irq, void *dev, struct pt_regs *regs)
  138. {
  139.         struct s3c24xx_spi *hw = dev;
  140.         unsigned int spsta = readb(hw->regs + S3C2410_SPSTA);
  141.         unsigned int count = hw->count;
  142.         if (hw->len){
  143.                 if (spsta & S3C2410_SPSTA_DCOL) {
  144.                         dev_dbg(hw->dev, "data-collision\n");//检测冲突

  145.                         complete(&hw->done);
  146.                         goto irq_done;
  147.                 }
  148.                 if (!(spsta & S3C2410_SPSTA_READY)) {
  149.                         dev_dbg(hw->dev, "spi not ready for tx?\n");//设备忙

  150.                         complete(&hw->done);
  151.                         goto irq_done;
  152.                 }
  153.                 hw->count++;
  154.                 if (hw->rx)
  155.                         hw->rx[count] = readb(hw->regs + S3C2410_SPRDAT);//接收数据

  156.                 count++;
  157.                 if (count len)
  158.                         writeb(hw_txbyte(hw, count), hw->regs + S3C2410_SPTDAT);//发送其它数据(或空数据0xFF)

  159.                 else
  160.                         complete(&hw->done);//发送接收完毕,通知s3c24xx_spi_txrx函数

  161.         }
  162. irq_done:
  163.         return IRQ_HANDLED;
  164. }

  165. static inline unsigned int hw_txbyte(struct s3c24xx_spi *hw, int count)
  166. {
  167.         return hw->tx ? hw->tx[count] : 0xff;
  168.         //如果还有数据没接收完且要发送的数据经已发送完毕,发送空数据0xFF

  169. }
注:
    这里要注意的是:在spi提供的write_then_read函数中,写和读数据是分开两个阶段来进行的(写数据的时候不读数据;读数据的时候发送空数据0xff)。
总结:
    简单的spi子系统大致就是这样, 相对比较简单易懂, 具体的应用可以参考一下代spi接口的触摸屏控制芯片驱动:
driver/input/touchscreen/ads7846.c
不过看明白它需要多花些时间了,因为毕竟这个驱动不仅和spi子系统打交道而且还和input子系统打交道,可不是那么容易应付的哦!

阅读(486) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~