Linux下SPI驱动分析

shipinsky 2011-03-07

Linux下SPI总线驱动有通用接口,一般的SPI设备驱动使用这个驱动接口实现设备驱动。分析驱动最好是先了解核心代码,然后从具体设备分析入手,然后从下至上,了解整个框架,再从上到下分析,理解透彻。

以下分析内核根目录均以"src"代替。内核代码http://lxr.linux.no/,版本2.6.37.2。

SPI的核心代码即

"src/drivers/spi/spi.c"——SPI 初始化和核心代码

"src/drivers/spi/spi_gpio.c"——IO模拟SPI接口代码

头文件:

"src/include/linux/spi/spi.h"

"src/include/linux/spi/spi_gpio.h"

"src/include/linux/spi/spi_bitbang.h"

 首先,先看核心代码。

 一步步来,先分析代码,然后看了具体驱动再回过头来看这个核心代码。

 spi.c


--------------------------------------------------------------------------------

       /* 这个函数是驱动模块卸载时使用 */
  32static void spidev_release(struct device *dev)
  33{
            /* 标准设备结构体转换成SPI设备结构体
             * 调用container_of函数获取dev设备所在的SPI设备结构体指针
             */
  34        struct spi_device       *spi = to_spi_device(dev);
  35
  36        /* spi masters may cleanup for released devices */
            /* 清空SPI主机申请的内存 */
  37        if (spi->master->cleanup)
  38                spi->master->cleanup(spi);
  39
            /* 减调用次数 */
  40        spi_master_put(spi->master);
            /* 释放SPI设备节点内存 */
  41        kfree(spi);
  42}

  43

      /* 打印模块别名 */
  44static ssize_t
  45modalias_show(struct device *dev, struct device_attribute *a, char *buf)
  46{
  47        const struct spi_device *spi = to_spi_device(dev);
  48
  49        return sprintf(buf, "%s\n", spi->modalias);
  50}

  51


/* 设置SPI总线属性——名称/显示 */

  52static struct device_attribute spi_dev_attrs[] = {

  53        __ATTR_RO(modalias),

  54        __ATTR_NULL,

  55};

56

      /* 获取设备ID */
  57/* modalias support makes "modprobe $MODALIAS" new-style hotplug work,
  58 * and the sysfs version makes coldplug work too.
  59 */
  60
  61static const struct spi_device_id *spi_match_id(const struct spi_device_id *id,
  62                                                const struct spi_device *sdev)
  63{
            /* 判断设备中名称与模块别名相同,则返回该设备ID */
  64        while (id->name[0]) {
  65                if (!strcmp(sdev->modalias, id->name))
  66                        return id;
  67                id++;
  68        }
  69        return NULL;
  70}
  71
    /* 返回设备ID */
  72const struct spi_device_id *spi_get_device_id(const struct spi_device *sdev)
  73{
  74        const struct spi_driver *sdrv = to_spi_driver(sdev->dev.driver);
  75
  76        return spi_match_id(sdrv->id_table, sdev);
  77}
  78EXPORT_SYMBOL_GPL(spi_get_device_id);

相关推荐