<form id="bpvnp"></form>

            <address id="bpvnp"><listing id="bpvnp"><meter id="bpvnp"></meter></listing></address>

                <address id="bpvnp"><nobr id="bpvnp"><menuitem id="bpvnp"></menuitem></nobr></address>

                    技术文摘

                    Linux spi驱动分析(一)——GSC3280总线驱动












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


                    由程序可以看出,此函数首先禁止SPI,屏蔽中断,然后设置fifo深度,最后使能SPI。

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


                    由程序看出,此函数主要完成初始化队列的作用,包括对queue函数的初始化,最后创建了queue。 开始queue函数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.}

                    此函数首先对queue的状态进行判断,然后初始化相关成员变量,最后调度queue。


                    最后看下master注册函数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成员变量进行检查。

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

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


                    程序首先遍历queue链表,查看是否还有queue没有执行,总共尝试50次,如果还有queue没有执行或者设备忙,则错误返回,否则置正确queue状态。



                    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设备传输数据时,就是调用此函数实现数据传输的,此函数主要完成结构体成员变量的初始化,具体的传输在中断中进行。
                    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状态,如果是停止状态,则退出。

                    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函数,函数如下:
                    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变量进行检测。

                    2) 如果变量正确,获取此次传输的分频系数和每次传输几个字节。

                    3) 设置SPI控制寄存器和分频寄存器

                    4) 设置SPI总线驱动结构体中的传输或者接收数据指针,打开中断,开始数据传输。

                    5) 每传输一个transfer,都会调用此函数一次。

                    实际的传输数据在中断中进行,程序如下:
                    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) 首先读取中断状态,如果是空中断,退出中断。

                    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




















                     
                    彩神ll【中国】股份有限公司