781行之前没什么好说的,直接看783行,将work投入到工作队列里,然后就返回,在这里就可以回答之前为什么是异步的问题。以后在某个合适的时间里CPU会执行这个work指定的函数,这里是s3c64xx_spi_work函数,看它的定义:
00000723 static void s3c64xx_spi_work(struct work_struct *work) 00000724 { 00000725 struct s3c64xx_spi_driver_data *sdd = container_of(work, 00000726 struct s3c64xx_spi_driver_data, work); 00000727 unsigned long flags; 00000728 00000729 /* Acquire DMA channels */ 00000730 while (!acquire_dma(sdd)) 00000731 msleep(10); 00000732 00000733 spin_lock_irqsave(&sdd->lock, flags); 00000734 00000735 while (!list_empty(&sdd->queue) 00000736 && !(sdd->state & SUSPND)) { 00000737 00000738 struct spi_message *msg; 00000739 00000740 msg = container_of(sdd->queue.next, struct spi_message, queue); 00000741 00000742 list_del_init(&msg->queue); 00000743 00000744 /* Set Xfer busy flag */ 00000745 sdd->state |= SPIBUSY; 00000746 00000747 spin_unlock_irqrestore(&sdd->lock, flags); 00000748 00000749 handle_msg(sdd, msg); 00000750 00000751 spin_lock_irqsave(&sdd->lock, flags); 00000752 00000753 sdd->state &= ~SPIBUSY; 00000754 } 00000755 00000756 spin_unlock_irqrestore(&sdd->lock, flags); 00000757 00000758 /* Free DMA channels */ 00000759 s3c2410_dma_free(sdd->tx_dmach, &s3c64xx_spi_dma_client); 00000760 s3c2410_dma_free(sdd->rx_dmach, &s3c64xx_spi_dma_client); 00000761 }
730行,申请DMA,关于DMA的就不说,一是我对DMA没什么了解,二是这里基本上用不到,后面就知道什么时候才会用到DMA。
735至754行,循环取出队列里的message并调用749行的handle_msg函数进行处理,handle_msg函数的定义如下:
00000568 static void handle_msg(struct s3c64xx_spi_driver_data *sdd, 00000569 struct spi_message *msg) 00000570 { 00000571 struct s3c64xx_spi_info *sci = sdd->cntrlr_info; 00000572 struct spi_device *spi = msg->spi; 00000573 struct s3c64xx_spi_csinfo *cs = spi->controller_data; 00000574 struct spi_transfer *xfer; 00000575 int status = 0, cs_toggle = 0; 00000576 u32 speed; 00000577 u8 bpw; 00000578 00000579 /* If Master's(controller) state differs from that needed by Slave */ 00000580 if (sdd->cur_speed != spi->max_speed_hz 00000581 || sdd->cur_mode != spi->mode 00000582 || sdd->cur_bpw != spi->bits_per_word) { 00000583 sdd->cur_bpw = spi->bits_per_word; 00000584 sdd->cur_speed = spi->max_speed_hz; 00000585 sdd->cur_mode = spi->mode; 00000586 s3c64xx_spi_config(sdd); 00000587 } 00000588 00000589 /* Map all the transfers if needed */ 00000590 if (s3c64xx_spi_map_mssg(sdd, msg)) { 00000591 dev_err(&spi->dev, 00000592 "Xfer: Unable to map message buffers! "); 00000593 status = -ENOMEM; 00000594 goto out; 00000595 } 00000596 00000597 /* Configure feedback delay */ 00000598 writel(cs->fb_delay & 0x3, sdd->regs + S3C64XX_SPI_FB_CLK); 00000599 00000600 list_for_each_entry(xfer, &msg->transfers, transfer_list) { 00000601 00000602 unsigned long flags; 00000603 int use_dma; 00000604 00000605 INIT_COMPLETION(sdd->xfer_completion); 00000606 00000607 /* Only BPW and Speed may change across transfers */ 00000608 bpw = xfer->bits_per_word ? : spi->bits_per_word; 00000609 speed = xfer->speed_hz ? : spi->max_speed_hz; 00000610 00000611 if (bpw != sdd->cur_bpw || speed != sdd->cur_speed) { 00000612 sdd->cur_bpw = bpw; 00000613 sdd->cur_speed = speed; 00000614 s3c64xx_spi_config(sdd); 00000615 } 00000616 00000617 /* Polling method for xfers not bigger than FIFO capacity */ 00000618 00000619 if (xfer->len <= ((sci->fifo_lvl_mask >> 1) + 1)) 00000620 use_dma = 0; 00000621 else 00000622 use_dma = 1; 00000623 00000624 spin_lock_irqsave(&sdd->lock, flags); 00000625 00000626 /* Pending only which is to be done */ 00000627 sdd->state &= ~RXBUSY; 00000628 sdd->state &= ~TXBUSY; 00000629 00000630 enable_datapath(sdd, spi, xfer, use_dma); 00000631 00000632 /* Slave Select */ 00000633 enable_cs(sdd, spi); 00000634 00000635 /* Start the signals */ 00000636 S3C64XX_SPI_ACT(sdd); 00000637 00000638 spin_unlock_irqrestore(&sdd->lock, flags); 00000639 00000640 status = wait_for_xfer(sdd, xfer, use_dma); 00000641 00000642 /* Quiese the signals */ 00000643 S3C64XX_SPI_DEACT(sdd); 00000644 00000645 if (status) { 00000646 dev_err(&spi->dev, "I/O Error: " 00000647 "rx-%d tx-%d res:rx-%c tx-%c len-%d ", 00000648 xfer->rx_buf ? 1 : 0, xfer->tx_buf ? 1 : 0, 00000649 (sdd->state & RXBUSY) ? 'f' : 'p', 00000650 (sdd->state & TXBUSY) ? 'f' : 'p', 00000651 xfer->len); 00000652 00000653 if (use_dma) { 00000654 if (xfer->tx_buf != NULL 00000655 && (sdd->state & TXBUSY)) 00000656 s3c2410_dma_ctrl(sdd->tx_dmach, 00000657 S3C2410_DMAOP_FLUSH); 00000658 if (xfer->rx_buf != NULL 00000659 && (sdd->state & RXBUSY)) 00000660 s3c2410_dma_ctrl(sdd->rx_dmach, 00000661 S3C2410_DMAOP_FLUSH); 00000662 } 00000663 00000664 goto out; 00000665 } 00000666 00000667 if (xfer->delay_usecs) 00000668 udelay(xfer->delay_usecs); 00000669 00000670 if (xfer->cs_change) { 00000671 /* Hint that the next mssg is gonna be 00000672 for the same device */ 00000673 if (list_is_last(&xfer->transfer_list, 00000674 &msg->transfers)) 00000675 cs_toggle = 1; 00000676 else 00000677 disable_cs(sdd, spi); 00000678 } 00000679 00000680 msg->actual_length += xfer->len; 00000681 00000682 flush_fifo(sdd); 00000683 } 00000684 00000685 out: 00000686 if (!cs_toggle || status) 00000687 disable_cs(sdd, spi); 00000688 else 00000689 sdd->tgl_spi = spi; 00000690 00000691 s3c64xx_spi_unmap_mssg(sdd, msg); 00000692 00000693 msg->status = status; 00000694 00000695 if (msg->complete) 00000696 msg->complete(msg->context); 00000697 }
函数很长,580至587行,如果一路走来speed、bpw和mode的值与spi设备的不一致就调用s3c64xx_spi_config函数重新配置,s3c64xx_spi_config函数里面就是对SPI寄存器进行设置的。
590至595行,关于DMA映射的,略过。
598行,设置feedback寄存器。
600行,遍历每一个transfer。605行,又初始化一个完成量,注意这里与之前的那个完成量是不一样的,这里的完成量只有使用DMA传输时才会用得到,接下来很快就可以看到。
608至615行,也是一些关于设置值的检查。
619至622行,只有发送或者接收的数据长度大于fifo的深度(这里是64个字节)设置use_dma为1,也即使用DMA进行传输,否则不使用DMA。
630行,enable_datapath函数的定义为:
00000232 static void enable_datapath(struct s3c64xx_spi_driver_data *sdd, 00000233 struct spi_device *spi, 00000234 struct spi_transfer *xfer, int dma_mode) 00000235 { 00000236 struct s3c64xx_spi_info *sci = sdd->cntrlr_info; 00000237 void __iomem *regs = sdd->regs; 00000238 u32 modecfg, chcfg; 00000239 00000240 modecfg = readl(regs + S3C64XX_SPI_MODE_CFG); 00000241 modecfg&=~(S3C64XX_SPI_MODE_TXDMA_ON|S3C64XX_SPI_MODE_RXDMA_ON); 00000242 00000243 chcfg = readl(regs + S3C64XX_SPI_CH_CFG); 00000244 chcfg &= ~S3C64XX_SPI_CH_TXCH_ON; 00000245 00000246 if (dma_mode) { 00000247 chcfg &= ~S3C64XX_SPI_CH_RXCH_ON; 00000248 } else { 00000249 /* Always shift in data in FIFO, even if xfer is Tx only, 00000250 * this helps setting PCKT_CNT value for generating clocks 00000251 * as exactly needed. 00000252 */ 00000253 chcfg |= S3C64XX_SPI_CH_RXCH_ON; 00000254 writel(((xfer->len * 8 / sdd->cur_bpw) & 0xffff) 00000255 | S3C64XX_SPI_PACKET_CNT_EN, 00000256 regs + S3C64XX_SPI_PACKET_CNT); 00000257 } 00000258 00000259 if (xfer->tx_buf != NULL) { 00000260 sdd->state |= TXBUSY; 00000261 chcfg |= S3C64XX_SPI_CH_TXCH_ON; 00000262 if (dma_mode) { 00000263 modecfg |= S3C64XX_SPI_MODE_TXDMA_ON; 00000264 s3c2410_dma_config(sdd->tx_dmach, 1); 00000265 s3c2410_dma_enqueue(sdd->tx_dmach, (void *)sdd, 00000266 xfer->tx_dma, xfer->len); 00000267 s3c2410_dma_ctrl(sdd->tx_dmach, S3C2410_DMAOP_START); 00000268 } else { 00000269 unsigned char *buf = (unsigned char *) xfer->tx_buf; 00000270 int i = 0; 00000271 while (i < xfer->len) 00000272 writeb(buf[i++], regs + S3C64XX_SPI_TX_DATA); 00000273 } 00000274 } 00000275 00000276 if (xfer->rx_buf != NULL) { 00000277 sdd->state |= RXBUSY; 00000278 00000279 if (sci->high_speed && sdd->cur_speed >= 30000000UL 00000280 && !(sdd->cur_mode & SPI_CPHA)) 00000281 chcfg |= S3C64XX_SPI_CH_HS_EN; 00000282 00000283 if (dma_mode) { 00000284 modecfg |= S3C64XX_SPI_MODE_RXDMA_ON; 00000285 chcfg |= S3C64XX_SPI_CH_RXCH_ON; 00000286 writel(((xfer->len * 8 / sdd->cur_bpw) & 0xffff) 00000287 | S3C64XX_SPI_PACKET_CNT_EN, 00000288 regs + S3C64XX_SPI_PACKET_CNT); 00000289 s3c2410_dma_config(sdd->rx_dmach, 1); 00000290 s3c2410_dma_enqueue(sdd->rx_dmach, (void *)sdd, 00000291 xfer->rx_dma, xfer->len); 00000292 s3c2410_dma_ctrl(sdd->rx_dmach, S3C2410_DMAOP_START); 00000293 } 00000294 } 00000295 00000296 writel(modecfg, regs + S3C64XX_SPI_MODE_CFG); 00000297 writel(chcfg, regs + S3C64XX_SPI_CH_CFG); 00000298 }
240至244行,读取模式配置和通道配置寄存器。
246至257行,根据是否采用DMA模式设置接收计数寄存器。
259行,很早就为tx_buf分配内存,因此条件成立。因为不考虑DMA模式,因此略过262至268行。
269至272行,循环将发送数据写入到发送寄存器。
276至294行,由于rx_buf为NULL,因此直接略过277至294行。
296、297行,将之前的值写入到寄存器中。
回到handle_msg函数,633行,选中从设备。636行,设置寄存器,开始数据传输。
640行,wait_for_xfer函数的定义:
00000319 static int wait_for_xfer(struct s3c64xx_spi_driver_data *sdd, 00000320 struct spi_transfer *xfer, int dma_mode) 00000321 { 00000322 struct s3c64xx_spi_info *sci = sdd->cntrlr_info; 00000323 void __iomem *regs = sdd->regs; 00000324 unsigned long val; 00000325 int ms; 00000326 00000327 /* millisecs to xfer 'len' bytes @ 'cur_speed' */ 00000328 ms = xfer->len * 8 * 1000 / sdd->cur_speed; 00000329 ms += 10; /* some tolerance */ 00000330 00000331 if (dma_mode) { 00000332 val = msecs_to_jiffies(ms) + 10; 00000333 val = wait_for_completion_timeout(&sdd->xfer_completion, val); 00000334 } else { 00000335 u32 status; 00000336 val = msecs_to_loops(ms); 00000337 do { 00000338 status = readl(regs + S3C64XX_SPI_STATUS); 00000339 } while (RX_FIFO_LVL(status, sci) < xfer->len && --val); 00000340 } 00000341 00000342 if (!val) 00000343 return -EIO; 00000344 00000345 if (dma_mode) { 00000346 u32 status; 00000347 00000348 /* 00000349 * DmaTx returns after simply writing data in the FIFO, 00000350 * w/o waiting for real transmission on the bus to finish. 00000351 * DmaRx returns only after Dma read data from FIFO which 00000352 * needs bus transmission to finish, so we don't worry if 00000353 * Xfer involved Rx(with or without Tx). 00000354 */ 00000355 if (xfer->rx_buf == NULL) { 00000356 val = msecs_to_loops(10); 00000357 status = readl(regs + S3C64XX_SPI_STATUS); 00000358 while ((TX_FIFO_LVL(status, sci) 00000359 || !S3C64XX_SPI_ST_TX_DONE(status, sci)) 00000360 && --val) { 00000361 cpu_relax(); 00000362 status = readl(regs + S3C64XX_SPI_STATUS); 00000363 } 00000364 00000365 if (!val) 00000366 return -EIO; 00000367 } 00000368 } else { 00000369 unsigned char *buf; 00000370 int i; 00000371 00000372 /* If it was only Tx */ 00000373 if (xfer->rx_buf == NULL) { 00000374 sdd->state &= ~TXBUSY; 00000375 return 0; 00000376 } 00000377 00000378 i = 0; 00000379 buf = xfer->rx_buf; 00000380 while (i < xfer->len) 00000381 buf[i++] = readb(regs + S3C64XX_SPI_RX_DATA); 00000382 00000383 sdd->state &= ~RXBUSY; 00000384 } 00000385 00000386 return 0; 00000387 }
328行,根据发送速率计算需要等待的时间。331至334行,与DMA相关的,略过。
335至339行,不断地读状态寄存器,如果接收到的数据长度等于发送数据的长度或超时则退出循环。
342、343行,如果是超时退出循环的,则返回出错。
345至368行,DMA相关的,略过。
369至383行,如果只是发送数据,则直接返回0。否则从接收寄存器里将接收到的数据读出来。
回到handle_msg函数,643行,停止传输。645至665行,如果之前wait_for_xfer函数返回大于0的值,则表示出错,这里就打印一些信息。
667、668行,之前如果有设置延时的话这里就延时。
670至678行,是否需要每个transfer完成都改变片选信号。
680行,累加所有transfer成功发送的数据。
682行,清发送和接收寄存器。
691行,取消DMA映射。
693行,记录状态信息。
695、696行,唤醒之前等待的完成量。
到这里,已经说了整个write过程,不容易啊!。其他的read/ioctl过程是大同小异的。
总结
spidev.c是一个通用的SPI驱动,因此它不处理任何有关具体驱动的逻辑,这就需要在用户空间来完成具体的逻辑。其实这符合了Android驱动的思想,这也是Android HAL层存在的目的:内核驱动只完成硬件操作,具体逻辑放在HAL层,这样就有利于保护厂家、开发者的知识产权。
在用户空间使用ioctl就可以完成write、read操作。