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);