一、SPI總線驅(qū)動介紹 | ||||
SPI總線總共需要四根線,包括MOSI、MISO、CLK和CS。本文首先從SPI設(shè)備注冊開始來講述SPI總線驅(qū)動。 | ||||
二、設(shè)備注冊 | ||||
在系統(tǒng)啟動的時候,會按照順序執(zhí)行一些初始化程序,比如device_initcall和module_init等宏。這些宏是按照順序執(zhí)行的,比如device_initcall的優(yōu)先級高于module_init,現(xiàn)在我們看下在系統(tǒng)啟動的時候注冊的spi設(shè)備信息。 對于此處,n為1,在程序中首先創(chuàng)建相應(yīng)的內(nèi)存,在for循環(huán)中,將信息保存到內(nèi)存中,然后插入board_list鏈表,接著遍歷spi_master_list鏈表,注意此處,由于device_initcall的優(yōu)先級高于module_init,所以此時spi_master_list鏈表為空,那么還不能調(diào)用spi_match_master_to_boardinfo函數(shù)創(chuàng)建spi設(shè)備,具體的創(chuàng)建設(shè)備將在spi總線驅(qū)動的探測函數(shù)中,使用spi_register_master()函數(shù)創(chuàng)建設(shè)備。 | ||||
三、總線驅(qū)動探測、退出和電源管理函數(shù) | ||||
3.1、探測函數(shù)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) 接下來注冊了中斷函數(shù)。 3) 然后注冊了spi_master所需要的函數(shù),包括清除、設(shè)置和傳輸?shù)群瘮?shù),在四中會講述。 4) gsc3280_spi_hw_init函數(shù)初始化了SPI總線寄存器,接下來講述。 5) 總線驅(qū)動采用queue機(jī)制實現(xiàn)多設(shè)備SPI讀寫,接下來初始化和啟動了queue,接下來講述。 6) 使用spi_register_master函數(shù)注冊master,此函數(shù)即實現(xiàn)創(chuàng)建了SPI設(shè)備結(jié)構(gòu)體,接下來講述。 SPI總線寄存器初始化函數(shù)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函數(shù)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.} 此函數(shù)首先對queue的狀態(tài)進(jìn)行判斷,然后初始化相關(guān)成員變量,最后調(diào)度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成員變量進(jìn)行檢查。 2) 初始化成員變量。 3) 將master->list插入到spi_master_list鏈表中。 4) 語句list_for_each_entry(bi, &board_list, list)實現(xiàn)遍歷board_list鏈表,在二設(shè)備注冊中已經(jīng)講述了將設(shè)備插入到board_list鏈表中。此時的board_list鏈表不為空,已經(jīng)有相應(yīng)設(shè)備結(jié)構(gòu)體信息了。 5) 語句spi_match_master_to_boardinfo(master, &bi->board_info);實現(xiàn)設(shè)備的創(chuàng)建,函數(shù)程序如下: 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) 函數(shù)首先判斷master的總線號和設(shè)備的總線號是否相等,如果不等直接返回。 2) 函數(shù)spi_new_device(master, bi);實現(xiàn)設(shè)備創(chuàng)建,如下: 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) 首先調(diào)用spi_alloc_device函數(shù)創(chuàng)建設(shè)備內(nèi)存,從spi_alloc_device函數(shù)中可以看到,首先申請內(nèi)存,然后對設(shè)備程序進(jìn)行賦值。 2) 接下來將芯片的信息賦值給設(shè)備結(jié)構(gòu)體,包括片選、最大速率、模式、中斷和名稱等。此處名稱尤為重要,在spi設(shè)備的注冊函數(shù) spi_register_driver中,就是通過名稱找到相應(yīng)的設(shè)備信息結(jié)構(gòu)體的。 3) 程序status = spi_add_device(proxy);實現(xiàn)添加spi設(shè)備信息。此函數(shù)在--Linux spi驅(qū)動分析(二)----spi內(nèi)核中講述。 | ||||
3.2、移除函數(shù)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) 首先獲得總線結(jié)構(gòu)體 2) 然后刪除queue 3) 最后禁止SPI,釋放中斷和IO,最后注銷master。 | ||||
3.3、掛起函數(shù)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函數(shù)內(nèi)容如下: 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、恢復(fù)函數(shù)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支持函數(shù) | ||||
4.1、清除函數(shù)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. } 程序首先獲取設(shè)備指針,然后釋放內(nèi)存。 | ||||
4.2、設(shè)置函數(shù)gsc3280_spi_setup | ||||
此函數(shù)是一個回調(diào)函數(shù),spi核心中的spi_setup()函數(shù)會調(diào)用此函數(shù),程序如下: 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) 首先判斷參數(shù),如果參數(shù)錯誤,直接返回。 2) 獲取spi控制數(shù)據(jù),如果沒有,則申請內(nèi)存創(chuàng)建設(shè)備。 3) 接下來根據(jù)實際情況對設(shè)備結(jié)構(gòu)體賦值。 | ||||
4.3、傳輸函數(shù)gsc3280_spi_transfer | ||||
此函數(shù)尤為重要,SPI設(shè)備傳輸數(shù)據(jù)時,就是調(diào)用此函數(shù)實現(xiàn)數(shù)據(jù)傳輸?shù)?,此函?shù)主要完成結(jié)構(gòu)體成員變量的初始化,具體的傳輸在中斷中進(jìn)行。 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狀態(tài),如果是停止?fàn)顟B(tài),則退出。 2) 對傳送結(jié)構(gòu)體成員變量賦值。 3) 判斷當(dāng)前是否有數(shù)據(jù)在收發(fā),如果有,就先直接返回。 4) 如果沒有,則調(diào)用queue_work()函數(shù),調(diào)度函數(shù)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) 此函數(shù)在兩種情況下會被調(diào)用: a) 當(dāng)?shù)谝淮伍_始SPI傳輸時,會調(diào)用此函數(shù),設(shè)置message結(jié)構(gòu)體變量。 b) 當(dāng)傳輸完一個message后,如果判斷還有message沒有被傳輸,則調(diào)用此函數(shù)獲取新的message。 2) 程序首先對變量進(jìn)行檢查,有兩種退出情況,第一種是隊列已經(jīng)處于停止?fàn)顟B(tài),第二種是傳輸msg鏈表為空。 3) 上鎖,獲取新的傳輸message,如果獲取失敗,直接解鎖退出。 4) 如果獲取msg成功,先刪除獲取成功msg的鏈表,然后對SPI總線驅(qū)動結(jié)構(gòu)體變量賦初值。 5) 解鎖,使能片選信號CS。 6) 獲取傳輸?shù)牡谝粋€transfer。 7) 調(diào)度gsc3280_spi_pump_transfers函數(shù),函數(shù)如下: 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變量進(jìn)行檢測。 2) 如果變量正確,獲取此次傳輸?shù)姆诸l系數(shù)和每次傳輸幾個字節(jié)。 3) 設(shè)置SPI控制寄存器和分頻寄存器 4) 設(shè)置SPI總線驅(qū)動結(jié)構(gòu)體中的傳輸或者接收數(shù)據(jù)指針,打開中斷,開始數(shù)據(jù)傳輸。 5) 每傳輸一個transfer,都會調(diào)用此函數(shù)一次。 實際的傳輸數(shù)據(jù)在中斷中進(jìn)行,程序如下: 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) 首先讀取中斷狀態(tài),如果是空中斷,退出中斷。 2) 判斷當(dāng)前是否有msg在傳輸,如果沒有,退出中斷。 3) 判斷是否是錯誤中斷,包括溢出等,如果是,屏蔽中斷,退出中斷。 4) 如果是接收滿中斷,則首先接收數(shù)據(jù)。然后退出中斷。 5) 如果是發(fā)送空中斷,則發(fā)送數(shù)據(jù),發(fā)送完成后,退出中斷。 現(xiàn)在看下發(fā)送數(shù)據(jù)函數(shù)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) 發(fā)送數(shù)據(jù)。 3) 如果發(fā)送完成,執(zhí)行g(shù)sc3280_spi_xfer_done(gscs)函數(shù)。 4) 如果沒有完成,打開中斷,繼續(xù)發(fā)數(shù)據(jù)。 對于gsc3280_spi_xfer_done()函數(shù),如下: 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,如果還有,則調(diào)度gsc3280_spi_pump_transfers()函數(shù)準(zhǔn)備開始傳輸。 2) 如果沒有transfer需要傳輸,調(diào)用函數(shù)gsc3280_spi_giveback(gscs),說明此時已經(jīng)處理完成了一個msg。 gsc3280_spi_giveback(gscs)函數(shù)如下: 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) 設(shè)置完成msg。 4) 上鎖,初始化SPI總線結(jié)構(gòu)體變量。 5) 調(diào)用gsc3280_spi_pump_messages()函數(shù),處理下一個msg。 中斷接收數(shù)據(jù)函數(shù)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) 首先接收數(shù)據(jù),如果接收成功,調(diào)用gsc3280_spi_xfer_done(gscs);。 到此,SPI總線驅(qū)動就全部講述完成了,在總線驅(qū)動中,使用了queue和tasklet兩種機(jī)制,queue實現(xiàn)了不同msg的傳輸,tasklet實現(xiàn)了msg中不同transfer的傳輸。 | ||||
原文參見:http://blog.chinaunix.net/uid-25445243-id-3987576.html | ||||