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);
先到这,且见下回分解,累了,睡觉~~