一、SPI总线驱动介绍 | ||||
SPI总线总共需要四根线,包括MOSI、MISO、CLK和CS。本文首先从SPI设备注册开始来讲述SPI总线驱动。 | ||||
二、设备注册 | ||||
在系统启动的时候,会按照顺序执行一些初始化程序,比如device_initcall和module_init等宏。这些宏是按照顺序执行的,比如device_initcall的优先级高于module_init,现在我们看下在系统启动的时候注册的spi设备信息。 对于此处,n为1,在程序中首先创建相应的内存,在for循环中,将信息保存到内存中,然后插入board_list链表,接着遍历spi_master_list链表,注意此处,由于device_initcall的优先级高于module_init,所以此时spi_master_list链表为空,那么还不能调用spi_match_master_to_boardinfo函数创建spi设备,具体的创建设备将在spi总线驱动的探测函数中,使用spi_register_master()函数创建设备。 | ||||
三、总线驱动探测、退出和电源管理函数 | ||||
3.1、探测函数gsc3280_spi_probe | ||||
程序如下: 1. static int __init gsc3280_spi_probe(struct platform_device *pdev) 2. { 3. int ret = 0; 4. struct gsc3280_spi *gscs; 5. struct spi_master *master; 6. struct resource *mem, *ioarea; 7. 8. DBG("############\n"); 9. DBG("gsc3280 spi probe start\n"); 10. master = spi_alloc_master(&pdev->dev, sizeof(struct gsc3280_spi)); 11. if (!master) { 12. ret = -ENOMEM; 13. DBG("!!!!spi_alloc_master error\n"); 14. goto exit; 15. } 16. gscs = spi_master_get_devdata(master); 17. memset(gscs, 0, sizeof(struct gsc3280_spi)); 18. gscs->master = spi_master_get(master); 19. mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); 20. if (!mem) { 21. DBG("!!!!no mem resource!\n"); 22. ret = -EINVAL; 23. goto err_kfree; 24. } 25. ioarea = request_mem_region(mem->start, resource_size(mem), pdev->name); 26. if (!ioarea) { 27. DBG("!!!!SPI region already claimed!\n"); 28. ret = -EBUSY; 29. goto err_kfree; 30. } 31. gscs->regs = ioremap_nocache(mem->start, resource_size(mem)); 32. if (!gscs->regs) { 33. DBG("!!!!SPI ioremap error!\n"); 34. ret = -ENOMEM; 35. goto err_release_reg; 36. } 37. DBG("gscs->regs = 0x%p\n", gscs->regs); 38. gscs->irq = platform_get_irq(pdev, 0); 39. if (gscs->irq < 0) { 40. DBG("!!!!no irq resource!\n"); 41. ret = gscs->irq; 42. goto err_unmap; 43. } 44. ret = request_irq(gscs->irq, gsc3280_spi_irq, IRQF_DISABLED, dev_name(&pdev->dev), gscs); 45. if (ret < 0) { 46. DBG("!!!!can not get IRQ!\n"); 47. goto err_irq; 48. } 49. gscs->clk = clk_get(NULL, "spi1"); 50. if (IS_ERR(gscs->clk)) { 51. DBG("!!!!failed to find spi1 clock source!\n"); 52. ret = PTR_ERR(gscs->clk); 53. goto err_irq; 54. } 55. gscs->max_freq = clk_get_rate(gscs->clk); 56. DBG("rate is %d\n", gscs->max_freq); 57. clk_enable(gscs->clk); 58. gscs->bus_num = pdev->id; 59. gscs->num_cs = 4; 60. gscs->prev_chip = NULL; 61. INIT_LIST_HEAD(&gscs->queue); 62. spin_lock_init(&gscs->slock); 63. 64.#ifdef CONFIG_GSC3280_SPI_DMA 65. gscs->dma_priv = pdev->dev.platform_data = &spi_platform_data; 66. if (!gscs->dma_priv) 67. goto err_clk; //return -ENOMEM; 68. gscs->dma_ops = &gscs_dma_ops; 69. gscs->dma_inited = 0; 70. gscs->dma_addr = (dma_addr_t)(gscs->regs + 0x24) & 0x1fffffff; 71.#endif 72. 73. platform_set_drvdata(pdev, master); 74. master->mode_bits = SPI_CPOL | SPI_CPHA; 75. master->bus_num = gscs->bus_num; 76. master->num_chipselect = gscs->num_cs; 77. master->cleanup = gsc3280_spi_cleanup; 78. master->setup = gsc3280_spi_setup; 79. master->transfer = gsc3280_spi_transfer; 80. gsc3280_spi_hw_init(gscs); 81. 82.#ifdef CONFIG_SPI_GSC3280_DMA 83. if (gscs->dma_ops && gscs->dma_ops->dma_init) { 84. ret = gscs->dma_ops->dma_init(gscs); 85. if (ret) { 86. dev_warn(&master->dev, "DMA init failed\n"); 87. gscs->dma_inited = 0; 88. } 89. } 90.#endif 91. 92. ret = gsc3280_init_queue(gscs); 93. if (ret != 0) { 94. DBG("!!!!problem initializing queue!\n"); 95. goto err_diable_hw; 96. } 97. ret = gsc3280_start_queue(gscs); 98. if (ret != 0) { 99. DBG("!!!!problem starting queue!\n"); 100. goto err_queue_alloc; 101. } 102. ret = spi_register_master(master); 103. if (ret != 0) { 104. DBG("!!!!register spi master error!\n"); 105. goto err_queue_alloc; 106. } 107. DBG("gsc3280 spi probe success\n"); 108. DBG("############\n"); 109. return 0; 110. 111. //err_free_master: 112. //spi_master_put(master); 113. err_queue_alloc: 114. gsc3280_spi_destroy_queue(gscs); 115. #ifdef CONFIG_SPI_GSC3280_DMA 116. if (gscs->dma_ops && gscs->dma_ops->dma_exit) 117. gscs->dma_ops->dma_exit(gscs); 118. #endif 119. err_diable_hw: 120. gsc3280_enable_spi(gscs, GSC_SPI_DISABLE); 121. //err_clk: 122. clk_disable(gscs->clk); 123. clk_put(gscs->clk); 124. err_irq: 125. free_irq(gscs->irq, gscs); 126. err_unmap: 127. iounmap(gscs->regs); 128. err_release_reg: 129. release_mem_region(mem->start, resource_size(mem)); 130. err_kfree: 131. kfree(gscs); 132. kfree(master); 133. exit: 134. printk(KERN_ERR "!!!!!!gsc3280 probe error!!!!!!\n"); 135. return ret; 136. }
1) 首先是总线资源的注册,包括申请IO空间和中断。 2) 接下来注册了中断函数。 3) 然后注册了spi_master所需要的函数,包括清除、设置和传输等函数,在四中会讲述。 4) gsc3280_spi_hw_init函数初始化了SPI总线寄存器,接下来讲述。 5) 总线驱动采用queue机制实现多设备SPI读写,接下来初始化和启动了queue,接下来讲述。 6) 使用spi_register_master函数注册master,此函数即实现创建了SPI设备结构体,接下来讲述。 SPI总线寄存器初始化函数gsc3280_spi_hw_init: 1. /* Restart the controller, disable all interrupts, clean fifo */ 2. static void gsc3280_spi_hw_init(struct gsc3280_spi *gscs) 3. { 4. gsc3280_enable_spi(gscs, GSC_SPI_DISABLE); 5. gsc3280_spi_mask_intr(gscs, GSC_SPI_SR_MASK); 6. if (!gscs->fifo_len) { 7. gscs->fifo_len = 0x10; 8. __raw_writew(0x00, gscs->regs + GSC_SPI_TXFTLR); 9. __raw_writew(0x00, gscs->regs + GSC_SPI_RXFTLR); 10. } 11. gsc3280_enable_spi(gscs, GSC_SPI_ENABLE); 12.}
初始化queue函数gsc3280_init_queue: 1. static int __devinit gsc3280_init_queue(struct gsc3280_spi *gscs) 2. { 3. gscs->queue_state = GSC_SPI_QUEUE_STOP; 4. gscs->busy = 0; 5. tasklet_init(&gscs->pump_transfers, gsc3280_spi_pump_transfers, (unsigned long)gscs); 6. INIT_WORK(&gscs->pump_messages, gsc3280_spi_pump_messages); 7. gscs->workqueue = create_singlethread_workqueue(dev_name(gscs->master->dev.parent)); 8. if (gscs->workqueue == NULL) { 9. DBG("!!!!create_singlethread_workqueue error!\n"); 10. return -EBUSY; 11. } 12. else 13. return 0; 14.}
1. static int gsc3280_start_queue(struct gsc3280_spi *gscs) 2. { 3. unsigned long flags; 4. 5. spin_lock_irqsave(&gscs->lock, flags); 6. if ((gscs->run == GSC_SPI_QUEUE_RUN) || gscs->busy) { 7. spin_unlock_irqrestore(&gscs->lock, flags); 8. return -EBUSY; 9. } 10. gscs->run = GSC_SPI_QUEUE_RUN; 11. gscs->cur_msg = NULL; 12. gscs->cur_transfer = NULL; 13. gscs->cur_chip = NULL; 14. gscs->prev_chip = NULL; 15. spin_unlock_irqrestore(&gscs->lock, flags); 16. queue_work(gscs->workqueue, &gscs->pump_messages); 17. return 0; 18.} 此函数首先对queue的状态进行判断,然后初始化相关成员变量,最后调度queue。
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. struct boardinfo *bi; 6. int status = -ENODEV; 7. int dynamic = 0; 8. 9. if (!dev) 10. return -ENODEV; 11. 12. /* even if it's just one always-selected device, there must 13. * be at least one chipselect 14. */ 15. if (master->num_chipselect == 0) 16. return -EINVAL; 17. 18. /* convention: dynamically assigned bus IDs count down from the max */ 19. if (master->bus_num < 0) { 20. /* FIXME switch to an IDR based scheme, something like 21. * I2C now uses, so we can't run out of "dynamic" IDs 22. */ 23. master->bus_num = atomic_dec_return(&dyn_bus_id); 24. dynamic = 1; 25. } 26. 27. spin_lock_init(&master->bus_lock_spinlock); 28. mutex_init(&master->bus_lock_mutex); 29. master->bus_lock_flag = 0; 30. 31. /* register the device, then userspace will see it. 32. * registration fails if the bus ID is in use. 33. */ 34. dev_set_name(&master->dev, "spi%u", master->bus_num); 35. status = device_add(&master->dev); 36. if (status < 0) 37. goto done; 38. dev_dbg(dev, "registered master %s%s\n", dev_name(&master->dev), 39. dynamic ? " (dynamic)" : ""); 40. 41. mutex_lock(&board_lock); 42. list_add_tail(&master->list, &spi_master_list); 43. list_for_each_entry(bi, &board_list, list) 44. spi_match_master_to_boardinfo(master, &bi->board_info); 45. mutex_unlock(&board_lock); 46. 47. status = 0; 48. 49. /* Register devices from the device tree */ 50. of_register_spi_devices(master); 51.done: 52. return status; 53.} 54.EXPORT_SYMBOL_GPL(spi_register_master);
1) 首先对master成员变量进行检查。 2) 初始化成员变量。 3) 将master->list插入到spi_master_list链表中。 4) 语句list_for_each_entry(bi, &board_list, list)实现遍历board_list链表,在二设备注册中已经讲述了将设备插入到board_list链表中。此时的board_list链表不为空,已经有相应设备结构体信息了。 5) 语句spi_match_master_to_boardinfo(master, &bi->board_info);实现设备的创建,函数程序如下: 1. static void spi_match_master_to_boardinfo(struct spi_master *master, 2. struct spi_board_info *bi) 3. { 4. struct spi_device *dev; 5. 6. if (master->bus_num != bi->bus_num) 7. return; 8. 9. dev = spi_new_device(master, bi); 10. if (!dev) 11. dev_err(master->dev.parent, "can't create new device for %s\n", 12. bi->modalias); 13.}
1) 函数首先判断master的总线号和设备的总线号是否相等,如果不等直接返回。 2) 函数spi_new_device(master, bi);实现设备创建,如下: 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. proxy = spi_alloc_device(master); 15. if (!proxy) 16. return NULL; 17. 18. WARN_ON(strlen(chip->modalias) >= sizeof(proxy->modalias)); 19. 20. proxy->chip_select = chip->chip_select; 21. proxy->max_speed_hz = chip->max_speed_hz; 22. proxy->mode = chip->mode; 23. proxy->irq = chip->irq; 24. strlcpy(proxy->modalias, chip->modalias, sizeof(proxy->modalias)); 25. proxy->dev.platform_data = (void *) chip->platform_data; 26. proxy->controller_data = chip->controller_data; 27. proxy->controller_state = NULL; 28. 29. status = spi_add_device(proxy); 30. if (status < 0) { 31. spi_dev_put(proxy); 32. return NULL; 33. } 34. 35. return proxy; 36.} 37.EXPORT_SYMBOL_GPL(spi_new_device); 38. 39.struct spi_device *spi_alloc_device(struct spi_master *master) 40.{ 41. struct spi_device *spi; 42. struct device *dev = master->dev.parent; 43. 44. if (!spi_master_get(master)) 45. return NULL; 46. 47. spi = kzalloc(sizeof *spi, GFP_KERNEL); 48. if (!spi) { 49. dev_err(dev, "cannot alloc spi_device\n"); 50. spi_master_put(master); 51. return NULL; 52. } 53. 54. spi->master = master; 55. spi->dev.parent = dev; 56. spi->dev.bus = &spi_bus_type; 57. spi->dev.release = spidev_release; 58. device_initialize(&spi->dev); 59. return spi; 60.} 61.EXPORT_SYMBOL_GPL(spi_alloc_device);
1) 首先调用spi_alloc_device函数创建设备内存,从spi_alloc_device函数中可以看到,首先申请内存,然后对设备程序进行赋值。 2) 接下来将芯片的信息赋值给设备结构体,包括片选、最大速率、模式、中断和名称等。此处名称尤为重要,在spi设备的注册函数 spi_register_driver中,就是通过名称找到相应的设备信息结构体的。 3) 程序status = spi_add_device(proxy);实现添加spi设备信息。此函数在--Linux spi驱动分析(二)----spi内核中讲述。 | ||||
3.2、移除函数gsc3280_spi_remove | ||||
程序如下: 1. void __exit gsc3280_spi_remove(struct platform_device *pdev) 2. { 3. int status = 0; 4. struct spi_master *master = platform_get_drvdata(pdev); 5. struct gsc3280_spi *gscs = spi_master_get_devdata(master); 6. 7. if (!gscs) 8. return; 9. status = gsc3280_spi_destroy_queue(gscs); 10. if (status != 0) 11. dev_err(&gscs->master->dev, "gsc3280_spi_remove: workqueue will not " 12. "complete, message memory not freed\n"); 13. 14.#ifdef CONFIG_SPI_GSC3280_DMA 15. if (gscs->dma_ops && gscs->dma_ops->dma_exit) 16. gscs->dma_ops->dma_exit(gscs); 17.#endif 18. 19. gsc3280_enable_spi(gscs, GSC_SPI_DISABLE); 20. free_irq(gscs->irq, gscs); 21. iounmap(gscs->regs); 22. spi_unregister_master(gscs->master); 23.}
1) 首先获得总线结构体 2) 然后删除queue 3) 最后禁止SPI,释放中断和IO,最后注销master。 | ||||
3.3、挂起函数gsc3280_spi_suspend | ||||
程序如下: 1. static int gsc3280_spi_suspend(struct platform_device *pdev, pm_message_t mesg) 2. { 3. int ret = 0; 4. struct spi_master *master = platform_get_drvdata(pdev); 5. struct gsc3280_spi *gscs = spi_master_get_devdata(master); 6. 7. ret = gsc3280_spi_stop_queue(gscs); 8. if (ret) 9. return ret; 10. gsc3280_enable_spi(gscs, GSC_SPI_DISABLE); 11. return ret; 12.}
停止queue函数内容如下: 1. static int gsc3280_spi_stop_queue(struct gsc3280_spi *gscs) 2. { 3. int status = 0; 4. unsigned long flags; 5. unsigned limit = 50; 6. 7. spin_lock_irqsave(&gscs->lock, flags); 8. while ((!list_empty(&gscs->queue) || gscs->busy) && limit--) { 9. spin_unlock_irqrestore(&gscs->lock, flags); 10. msleep(10); 11. spin_lock_irqsave(&gscs->lock, flags); 12. } 13. if (!list_empty(&gscs->queue) || gscs->busy) 14. status = -EBUSY; 15. else 16. gscs->queue_state = GSC_SPI_QUEUE_STOP; 17. spin_unlock_irqrestore(&gscs->lock, flags); 18. return status; 19.}
| ||||
3.4、恢复函数gsc3280_spi_resume | ||||
程序如下: 1. static int gsc3280_spi_resume(struct platform_device *pdev) 2. { 3. int ret = 0; 4. struct spi_master *master = platform_get_drvdata(pdev); 5. struct gsc3280_spi *gscs = spi_master_get_devdata(master); 6. 7. gsc3280_spi_hw_init(gscs); 8. ret = gsc3280_start_queue(gscs); 9. if (ret) 10. dev_err(&gscs->master->dev, "fail to start queue (%d)\n", ret); 11. return ret; 12.} 程序主要初始化SPI寄存器,然后开始运行queue。 | ||||
四、spi master支持函数 | ||||
4.1、清除函数gsc3280_spi_cleanup | ||||
1. static void gsc3280_spi_cleanup(struct spi_device *spi) 2. { 3. struct chip_data *chip = spi_get_ctldata(spi); 4. kfree(chip); 5. } 程序首先获取设备指针,然后释放内存。 | ||||
4.2、设置函数gsc3280_spi_setup | ||||
此函数是一个回调函数,spi核心中的spi_setup()函数会调用此函数,程序如下: 1. /* This may be called twice for each spi dev */ 2. static int gsc3280_spi_setup(struct spi_device *spi) 3. { 4. int ret = 0; 5. struct chip_data *chip = NULL; 6. struct gsc3280_spi_info *chip_info = NULL; 7. 8. DBG("######gsc3280 spi bus setup start######\n"); 9. chip = spi_get_ctldata(spi); /* Only alloc on first setup */ 10. if (!chip) { 11. chip = kzalloc(sizeof(struct chip_data), GFP_KERNEL); 12. if (!chip) { 13. DBG("!!!!kzalloc error!\n"); 14. ret = -ENOMEM; 15. goto exit; 16. } 17. } 18. chip_info = spi->controller_data; 19. /* chip_info doesn't always exist */ 20. if (chip_info) { 21.#ifdef CONFIG_GSC3280_SPI_DMA 22. chip->poll_mode = chip_info->poll_mode; 23. chip->enable_dma = chip_info->enable_dma; 24.#endif 25. chip->pin_cs = chip_info->pin_cs; 26. chip->cs_value = chip_info->cs_value; 27. chip->bits_per_word = chip_info->bits_per_word; 28. chip->lsb_flg = chip_info->lsb_flg; 29. gpio_request(chip->pin_cs, spi->modalias); 30. if (chip->cs_value == 0) 31. gpio_direction_output(chip->pin_cs, 1); 32. else 33. gpio_direction_output(chip->pin_cs, 0); 34. } 35. if (spi->bits_per_word == 8) { 36. chip->n_bytes = 1; 37.#ifdef CONFIG_GSC3280_SPI_DMA 38. chip->dma_width = 1; 39.#endif 40. } else if (spi->bits_per_word == 16) { 41. chip->n_bytes = 2; 42.#ifdef CONFIG_GSC3280_SPI_DMA 43. chip->dma_width = 2; 44.#endif 45. } else { 46. DBG("!!!!spi->bits_per_word = %d error!\n", spi->bits_per_word); 47. ret = -EINVAL; 48. goto exit; 49. } 50. if (!spi->max_speed_hz) { 51. DBG("!!!!spi->max_speed_hz = %d, error!\n", spi->max_speed_hz); 52. ret = -EINVAL; 53. goto exit; 54. } 55. chip->speed_hz = spi->max_speed_hz; 56. chip->cr = (chip->lsb_flg << GSC_SPI_CTL_BITS_NUM) | (spi->mode << GSC_SPI_CTL_MOD) 57. | ((chip->bits_per_word - 1) << GSC_SPI_CTL_DSS); 58. spi_set_ctldata(spi, chip); 59. 60.exit: 61. if (ret != 0) 62. DBG("!!!!gsc3280 spi bus setup error!\n"); 63. else 64. DBG("######gsc3280 spi bus setup success######\n"); 65. return ret; 66.}
1) 首先判断参数,如果参数错误,直接返回。 2) 获取spi控制数据,如果没有,则申请内存创建设备。 3) 接下来根据实际情况对设备结构体赋值。 | ||||
4.3、传输函数gsc3280_spi_transfer | ||||
此函数尤为重要,SPI设备传输数据时,就是调用此函数实现数据传输的,此函数主要完成结构体成员变量的初始化,具体的传输在中断中进行。 2. static int gsc3280_spi_transfer(struct spi_device *spi, struct spi_message *msg) 3. { 4. unsigned long flags = 0; 5. struct gsc3280_spi *gscs = spi_master_get_devdata(spi->master); 6. 7. DBG("####gsc3280 spi transfer start####\n"); 8. if (gscs->queue_state == GSC_SPI_QUEUE_STOP) { 9. DBG("!!!!queue is stop!\n"); 10. return -ESHUTDOWN; 11. } 12. msg->actual_length = 0; 13. msg->status = -EINPROGRESS; 14. msg->state = START_STATE; 15. spin_lock_irqsave(&gscs->slock, flags); 16. list_add_tail(&msg->queue, &gscs->queue); 17. spin_unlock_irqrestore(&gscs->slock, flags); 18. //writel(0x3f, (volatile unsigned int *)(0xbc04a000 + 0x38)); //max divid freq 19. if (gscs->cur_transfer || gscs->cur_msg) { 20. //DBG("gsc3280_spi_transfer: cur transfer or msg not empty\n"); 21. } else { 22. //DBG("gsc3280_spi_transfer: no cur transfer and msg\n"); 23. queue_work(gscs->workqueue, &gscs->pump_messages); 24. } 25. DBG("####gsc3280 spi transfer success####\n"); 26. return 0; 27.} 1) 首先判断queue状态,如果是停止状态,则退出。 2) 对传送结构体成员变量赋值。 3) 判断当前是否有数据在收发,如果有,就先直接返回。 4) 如果没有,则调用queue_work()函数,调度函数gsc3280_spi_pump_messages()。程序如下: 1. /* 2. * when call this function, no msg transfering 3. * deal one msg when call this funciton once. 4. * 5. */ 6. static void gsc3280_spi_pump_messages(struct work_struct *work) 7. { 8. unsigned long flags = 0; 9. struct gsc3280_spi *gscs = container_of(work, struct gsc3280_spi, pump_messages); 10. 11. DBG("####gsc3280_spi_pump_messages####\n"); 12. if (list_empty(&gscs->queue) || (gscs->queue_state == GSC_SPI_QUEUE_STOP)) { 13. if (gscs->queue_state == GSC_SPI_QUEUE_STOP) 14. DBG("!!!!queue is stop!\n"); 15. else 16. DBG("msg is finished!\n"); 17. gscs->busy = 0; 18. return; 19. } 20. 21. spin_lock_irqsave(&gscs->slock, flags); 22. gscs->cur_msg = list_entry(gscs->queue.next, struct spi_message, queue); 23. if (!gscs->cur_msg) { 24. spin_unlock_irqrestore(&gscs->slock, flags); 25. DBG("!!!!gsc3280_spi_pump_messages: current no msg!\n"); 26. return; 27. } 28. list_del_init(&gscs->cur_msg->queue); 29. gscs->cur_msg->state = RUNNING_STATE; 30. gscs->cur_chip = spi_get_ctldata(gscs->cur_msg->spi); 31. gscs->n_bytes = gscs->cur_chip->n_bytes; 32. gscs->busy = 1; 33. spin_unlock_irqrestore(&gscs->slock, flags); 34. 35. DBG("cs select enable\n"); 36. if (gscs->cur_chip->cs_value == 0) { 37. gpio_set_value(gscs->cur_chip->pin_cs, 0); 38. } 39. else 40. gpio_set_value(gscs->cur_chip->pin_cs, 1); 41. /* get first transfer */ 42. gscs->cur_transfer = list_entry(gscs->cur_msg->transfers.next, struct spi_transfer, transfer_list); 43. if (!gscs->cur_transfer) { 44. DBG("!!!!gsc3280_spi_pump_transfers: current no transfer!\n"); 45. return; 46. } 47. tasklet_schedule(&gscs->pump_transfers); 48. return; 49.}
1) 此函数在两种情况下会被调用: a) 当第一次开始SPI传输时,会调用此函数,设置message结构体变量。 b) 当传输完一个message后,如果判断还有message没有被传输,则调用此函数获取新的message。 2) 程序首先对变量进行检查,有两种退出情况,第一种是队列已经处于停止状态,第二种是传输msg链表为空。 3) 上锁,获取新的传输message,如果获取失败,直接解锁退出。 4) 如果获取msg成功,先删除获取成功msg的链表,然后对SPI总线驱动结构体变量赋初值。 5) 解锁,使能片选信号CS。 6) 获取传输的第一个transfer。 7) 调度gsc3280_spi_pump_transfers函数,函数如下: 2. static void gsc3280_spi_pump_transfers(unsigned long data) 3. { 4. int clk_div = 0; 5. u32 imask = 0, cr = 0; 6. unsigned long flags = 0; 7. struct spi_transfer *previous = NULL; 8. struct gsc3280_spi *gscs = (struct gsc3280_spi *)data; 9. 10. //DBG("gsc3280_spi_pump_transfers\n"); 11. if (gscs->cur_msg->state == ERROR_STATE) { 12. DBG("!!!!pump_transfers:cur msg state error!\n"); 13. gscs->cur_msg->status = -EIO; 14. goto early_exit; 15. } 16. /* Handle end of message */ 17. if (gscs->cur_msg->state == DONE_STATE) { 18. gscs->cur_msg->status = 0; 19. goto early_exit; 20. } 21. /* Delay if requested at end of transfer*/ 22. if (gscs->cur_msg->state == RUNNING_STATE) { 23. previous = list_entry(gscs->cur_transfer->transfer_list.prev, struct spi_transfer, transfer_list); 24. if (previous->delay_usecs) 25. udelay(previous->delay_usecs); 26. } 27. 28.#ifdef CONFIG_SPI_GSC3280_DMA 29. gscs->dma_width = gscs->cur_chip->dma_width; 30. gscs->rx_dma = gscs->cur_transfer->rx_dma; 31. gscs->tx_dma = gscs->cur_transfer->tx_dma; 32.#endif 33. 34. /* Handle per transfer options for bpw and speed */ 35. if (gscs->cur_transfer->speed_hz) { 36. if (gscs->cur_transfer->speed_hz != gscs->cur_chip->speed_hz) { 37. if (gscs->cur_transfer->speed_hz > gscs->max_freq) { 38. printk(KERN_ERR "SPI1: unsupported freq: %dHz\n", gscs->cur_transfer->speed_hz); 39. gscs->cur_msg->status = -EIO; 40. return; 41. } else 42. gscs->cur_chip->speed_hz = gscs->cur_transfer->speed_hz; 43. } 44. } 45. if (gscs->cur_transfer->bits_per_word) { 46. switch (gscs->cur_transfer->bits_per_word) { 47. case 8: 48. case 16: 49. gscs->n_bytes = gscs->cur_transfer->bits_per_word >> 3; 50.#ifdef CONFIG_SPI_GSC3280_DMA 51. gscs->dma_width = gscs->n_bytes; 52.#endif 53. break; 54. default: 55. printk(KERN_ERR "SPI1: unsupported bits:" "%db\n", gscs->cur_transfer->bits_per_word); 56. gscs->cur_msg->status = -EIO; 57. return; 58. } 59. } 60. 61. clk_div = gscs->max_freq / gscs->cur_transfer->speed_hz; 62. clk_div = clk_div / 2 - 1; 63. if (clk_div < 0) 64. clk_div = 0; 65. gscs->cur_chip->clk_div = (u16)clk_div; 66. 67. cr = gscs->cur_chip->cr | GSC_SPI_CTL_EN; 68. writel(cr, gscs->regs + GSC_SPI_CTRL); /* enable spi */ 69. writel(gscs->cur_chip->clk_div, gscs->regs + GSC_SPI_SEABAUR); 70. 71. spin_lock_irqsave(&gscs->slock, flags); 72. //gscs->n_bytes = gscs->cur_chip->n_bytes; 73. gscs->tx = (void *)gscs->cur_transfer->tx_buf; 74. gscs->tx_end = gscs->tx + gscs->cur_transfer->len; 75. gscs->rx = gscs->cur_transfer->rx_buf; 76. gscs->rx_end = gscs->rx + gscs->cur_transfer->len; 77. gscs->cs_change = gscs->cur_transfer->cs_change; 78. gscs->len = gscs->cur_transfer->len; 79. spin_unlock_irqrestore(&gscs->slock, flags); 80. 81. imask |= SPI_INT_TX_H_OVER | SPI_INT_RX_L_OVER | SPI_INT_RX_H_OVER | SPI_INT_RX_FULL; 82. if (gscs->tx != NULL) { 83. imask |= SPI_INT_TX_EMPTY; 84. } 85. gsc3280_spi_umask_intr(gscs, imask); 86. 87.#ifdef CONFIG_GSC3280_SPI_DMA 88. /* Check if current transfer is a DMA transaction */ 89. gscs->dma_mapped = map_dma_buffers(gscs); 90. /* Interrupt mode we only need set the TXEI IRQ, as TX/RX always happen syncronizely */ 91. if (!gscs->dma_mapped && !gscs->cur_chip->poll_mode) { 92. //int templen = gscs->len / gscs->n_bytes; 93. //txint_level = gscs->fifo_len / 2; 94. //txint_level = (templen > txint_level) ? txint_level : templen; 95. } 96. if (gscs->dma_mapped) 97. gscs->dma_ops->dma_transfer(gscs, cs_change); 98. if (gscs->cur_chip->poll_mode) 99. gsc3280_spi_poll_transfer(gscs); 100. #endif 101. 102. return; 103. 104. early_exit: 105. gsc3280_spi_giveback(gscs); 106. return; 107. }
1) 首先对msg变量进行检测。 2) 如果变量正确,获取此次传输的分频系数和每次传输几个字节。 3) 设置SPI控制寄存器和分频寄存器 4) 设置SPI总线驱动结构体中的传输或者接收数据指针,打开中断,开始数据传输。 5) 每传输一个transfer,都会调用此函数一次。 实际的传输数据在中断中进行,程序如下: 2. static irqreturn_t gsc3280_spi_irq(int irq, void *dev_id) 3. { 4. struct gsc3280_spi *gscs = dev_id; 5. u32 irq_status = __raw_readw(gscs->regs + GSC_SPI_ISR); 6. 7. //DBG("gsc3280_spi_irq\n"); 8. //DBG("sys_ctl0 = 0x%x\n", readl((volatile unsigned int *)(0xbc04a000 + 0x08))); 9. //DBG("clddiv_spi1 = 0x%x\n", readl((volatile unsigned int *)(0xbc04a000 + 0x38))); 10. //DBG("imux_cfg0 = 0x%x\n", readl((volatile unsigned int *)(0xbc04a000 + 0xb0))); 11. DBG("cr = 0x%x\n", __raw_readw(gscs->regs + GSC_SPI_CTRL)); 12. DBG("imsr = 0x%x, irq_status = 0x%x\n", __raw_readl(gscs->regs + GSC_SPI_IMSR), irq_status); 13. 14. if (!irq_status ) { 15. DBG("!!!!gsc3280_spi_irq: no irq!\n"); 16. return IRQ_NONE; 17. } 18. if (!gscs->cur_msg) { 19. DBG("!!!!gsc3280_spi_irq: no msg!\n"); 20. gsc3280_spi_mask_intr(gscs, SPI_INT_TX_EMPTY | SPI_INT_RX_FULL); 21. return IRQ_HANDLED; 22. } 23. if (irq_status & (SPI_INT_TX_H_OVER | SPI_INT_RX_L_OVER | SPI_INT_RX_H_OVER)) { 24. DBG("!!!!gsc3280_spi_irq: fifo overrun/underrun!\n"); 25. __raw_writew(0x0e, gscs->regs + GSC_SPI_ISR); 26. gscs->cur_msg->state = ERROR_STATE; 27. gscs->cur_msg->status = -EIO; 28. queue_work(gscs->workqueue, &gscs->pump_messages); 29. return IRQ_HANDLED; 30. } 31. if (irq_status & SPI_INT_RX_FULL) { 32. spi_gsc_read(gscs); 33. return IRQ_HANDLED; 34. } 35. if (irq_status & SPI_INT_TX_EMPTY) { 36. spi_gsc_write(gscs); 37. } 38. return IRQ_HANDLED; 39.} 1) 首先读取中断状态,如果是空中断,退出中断。 2) 判断当前是否有msg在传输,如果没有,退出中断。 3) 判断是否是错误中断,包括溢出等,如果是,屏蔽中断,退出中断。 4) 如果是接收满中断,则首先接收数据。然后退出中断。 5) 如果是发送空中断,则发送数据,发送完成后,退出中断。 现在看下发送数据函数spi_gsc_write(): 1. static void gsc3280_writer(struct gsc3280_spi *gscs) 2. { 3. u16 txw = 0; 4. unsigned long flags = 0; 5. u32 max = gsc3280_spi_tx_max(gscs); 6. 7. //DBG("max = %d, gscs->n_bytes = 0x%x", max, gscs->n_bytes); 8. spin_lock_irqsave(&gscs->slock, flags); 9. while (max--) { 10. if (gscs->n_bytes == 1) 11. txw = *(u8 *)(gscs->tx); 12. else 13. txw = *(u16 *)(gscs->tx); 14. DBG("txw = 0x%x\n", txw); 15. writel(txw, gscs->regs + GSC_SPI_DA_S); 16. gscs->tx += gscs->n_bytes; 17. } 18. spin_unlock_irqrestore(&gscs->slock, flags); 19.} 20.static void spi_gsc_write(struct gsc3280_spi *gscs) 21.{ 22. //DBG("spi_gsc_write\n"); 23. gsc3280_spi_mask_intr(gscs, GSC_SPI_SR_MASK); 24. gsc3280_writer(gscs); 25. if (gscs->tx_end == gscs->tx) { 26. gsc3280_spi_xfer_done(gscs); 27. } 28. else { 29. gsc3280_spi_umask_intr(gscs, GSC_SPI_SR_MASK); 30. } 31.}
1) 首先屏蔽中断。 2) 发送数据。 3) 如果发送完成,执行gsc3280_spi_xfer_done(gscs)函数。 4) 如果没有完成,打开中断,继续发数据。 对于gsc3280_spi_xfer_done()函数,如下: 1. static void *gsc3280_spi_next_transfer(struct gsc3280_spi *gscs) 2. { 3. struct spi_message *msg = gscs->cur_msg; 4. struct spi_transfer *trans = gscs->cur_transfer; 5. 6. if (trans->transfer_list.next != &msg->transfers) { 7. gscs->cur_transfer = list_entry(trans->transfer_list.next, struct spi_transfer, transfer_list); 8. return RUNNING_STATE; 9. } else 10. return DONE_STATE; 11.} 12.static void gsc3280_spi_xfer_done(struct gsc3280_spi *gscs) 13.{ 14. //DBG("gsc3280_spi_xfer_done\n"); 15. //DBG("irq_status = 0x%x\n", __raw_readw(gscs->regs + GSC_SPI_ISR)); 16. //DBG("imsr = 0x%x\n", __raw_readl(gscs->regs + GSC_SPI_IMSR)); 17. /* Update total byte transferred return count actual bytes read */ 18. gscs->cur_msg->actual_length += gscs->len; 19. /* Move to next transfer */ 20. gscs->cur_msg->state = gsc3280_spi_next_transfer(gscs); 21. if (gscs->cur_msg->state == DONE_STATE) { 22. /* Handle end of message */ 23. gscs->cur_msg->status = 0; 24. gsc3280_spi_giveback(gscs); 25. } else { 26. tasklet_schedule(&gscs->pump_transfers); 27. } 28.}
1) 获取下一个transfer,如果还有,则调度gsc3280_spi_pump_transfers()函数准备开始传输。 2) 如果没有transfer需要传输,调用函数gsc3280_spi_giveback(gscs),说明此时已经处理完成了一个msg。 gsc3280_spi_giveback(gscs)函数如下: 1. /* Caller already set message->status; dma and pio irqs are blocked */ 2. static void gsc3280_spi_giveback(struct gsc3280_spi *gscs) 3. { 4. unsigned long flags = 0; 5. 6. DBG("gsc3280_spi_giveback\n"); 7. //DBG("irq_status = 0x%x\n", readl(gscs->regs + GSC_SPI_ISR)); 8. gsc3280_spi_mask_intr(gscs, GSC_SPI_SR_MASK); 9. DBG("cs select disable\n"); 10. if (gscs->cur_chip->cs_value == 0) { 11. gpio_set_value(gscs->cur_chip->pin_cs, 1); 12. } 13. else 14. gpio_set_value(gscs->cur_chip->pin_cs, 0); 15. gscs->cur_msg->state = NULL; 16. if (gscs->cur_msg->complete) 17. gscs->cur_msg->complete(gscs->cur_msg->context); 18. 19. spin_lock_irqsave(&gscs->slock, flags); 20. gscs->cur_msg = NULL; 21. gscs->cur_transfer = NULL; 22. gscs->prev_chip = gscs->cur_chip; 23. gscs->cur_chip = NULL; 24. gscs->busy = 0; 25.#ifdef CONFIG_SPI_GSC3280_DMA 26. gscs->dma_mapped = 0; 27.#endif 28. spin_unlock_irqrestore(&gscs->slock, flags); 29. queue_work(gscs->workqueue, &gscs->pump_messages); 30.}
1) 首先屏蔽中断。 2) 禁止片选。 3) 设置完成msg。 4) 上锁,初始化SPI总线结构体变量。 5) 调用gsc3280_spi_pump_messages()函数,处理下一个msg。 中断接收数据函数spi_gsc_read(gscs)如下: 1. static void gsc3280_reader(struct gsc3280_spi *gscs) 2. { 3. u16 rxw = 0; 4. unsigned long flags = 0; 5. u32 max = gsc3280_spi_rx_max(gscs); 6. 7. //DBG("max = %d, gscs->n_bytes = 0x%x", max, gscs->n_bytes); 8. spin_lock_irqsave(&gscs->slock, flags); 9. while (max--) { 10. rxw = readl(gscs->regs + GSC_SPI_DA_S); 11. DBG("rxw = 0x%x\n", rxw); 12. if (gscs->n_bytes == 1) 13. *(u8 *)(gscs->rx) = (u8)rxw; 14. else 15. *(u16 *)(gscs->rx) = rxw; 16. gscs->rx += gscs->n_bytes; 17. } 18. spin_unlock_irqrestore(&gscs->slock, flags); 19.} 20.static void spi_gsc_read(struct gsc3280_spi *gscs) 21.{ 22. //DBG("spi_gsc_read\n"); 23. gsc3280_reader(gscs); 24. if (gscs->rx_end == gscs->rx) { 25. gsc3280_spi_xfer_done(gscs); 26. } 27.} 说明: 1) 首先接收数据,如果接收成功,调用gsc3280_spi_xfer_done(gscs);。 到此,SPI总线驱动就全部讲述完成了,在总线驱动中,使用了queue和tasklet两种机制,queue实现了不同msg的传输,tasklet实现了msg中不同transfer的传输。 | ||||
原文参见:http://blog.chinaunix.net/uid-25445243-id-3987576.html | ||||