欧美亚洲一区二区三区,午夜欧美艳情视频免费看,欧美XXXXX又粗又大,国精品产露脸偷拍视频

技術(shù)文摘

Linux spi驅(qū)動分析(一)——GSC3280總線驅(qū)動












一、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.}


由程序可以看出,此函數(shù)首先禁止SPI,屏蔽中斷,然后設(shè)置fifo深度,最后使能SPI。

初始化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.}


由程序看出,此函數(shù)主要完成初始化隊列的作用,包括對queue函數(shù)的初始化,最后創(chuàng)建了queue。 開始queue函數(shù)gsc3280_start_queue:

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。


最后看下master注冊函數(shù)spi_register_master:

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,然后禁止SPI。

停止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.}


程序首先遍歷queue鏈表,查看是否還有queue沒有執(zhí)行,總共嘗試50次,如果還有queue沒有執(zhí)行或者設(shè)備忙,則錯誤返回,否則置正確queue狀態(tài)。



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)行。
1.  /* spi driver call this function transfer data */

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ù)如下:
1.  /* when call this function,the cur_msg is the new msg */

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)行,程序如下:
1.  /* this is transfer message function */

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