Linux设备驱动剖析之SPI(一)

本文介绍了Linux SPI子系统,分析了SPI的初始化过程、设备驱动与SPI控制器的匹配方式,并以S3c6410为例展示了SPI控制器的平台设备注册。SPI在Linux中的应用相对较少,但通过理解其工作原理,可以更好地实现设备驱动编程。
摘要由CSDN通过智能技术生成

写在前面

初次接触SPI是因为几年前玩单片机的时候,由于普通的51单片机没有SPI控制器,所以只好用IO口去模拟。最近一次接触SPI是大三时参加的校内选拔赛,当时需要用2440去控制nrf24L01,从而实现数据的无线传输。nrf24L01是一种典型的SPI接口的2.4GHz无线收发器,当时搞了很久,由于时间比较紧,而且当时根本不熟悉Linux的SPI子系统,最后虽然采用IO口模拟SPI的方式勉强实现了,但是这根本就不符合Linux驱动的编程规范,或者说是在破坏Linux、污染kernel。

根据我个人所知道的,Linux SPI一直是处于被“忽略”的角色,市场上大部分板子在板级文件里都没有关于SPI的相关代码,而大部分讲驱动的书籍也没有专门的一章来讲述关于Linux SPI方面的内容,与IIC相比,SPI就是一个不被重视的“家伙”,为什么?我也不知道。为了帮SPI抱打不平,我决定基于Linux-2.6.36,说说Linux中SPI子系统。

先给出Linux SPI子系统的体系结构图:

SPI子系统体系结构

下面开始分析SPI子系统。

Linux中SPI子系统的初始化是从drivers/spi/spi.c文件中的spi_init函数开始的,看看它的定义:

00001025 static int __init spi_init(void)
00001026 {
00001027     int    status;
00001028 
00001029     buf = kmalloc(SPI_BUFSIZ, GFP_KERNEL);
00001030     if (!buf) {
00001031         status = -ENOMEM;
00001032         goto err0;
00001033     }
00001034 
00001035     status = bus_register(&spi_bus_type);
00001036     if (status < 0)
00001037         goto err1;
00001038 
00001039     status = class_register(&spi_master_class);
00001040     if (status < 0)
00001041         goto err2;
00001042     return 0;
00001043 
00001044 err2:
00001045     bus_unregister(&spi_bus_type);
00001046 err1:
00001047     kfree(buf);
00001048     buf = NULL;
00001049 err0:
00001050     return status;
00001051 }

1029行,分配spi buf内存,其中buf和SPI_BUFSIZ都在spi.c文件中定义:

00000945 #define    SPI_BUFSIZ    max(32,SMP_CACHE_BYTES)
00000946 
00000947 static u8    *buf;

1035行,注册spi总线,同样是在spi.c文件中:

00000145 struct bus_type spi_bus_type = {
00000146     .name        = "spi",
00000147     .dev_attrs    = spi_dev_attrs,
00000148     .match        = spi_match_device,
00000149     .uevent        = spi_uevent,
00000150     .suspend        = spi_suspend,
00000151     .resume        = spi_resume,
00000152 };

146行,总线的名字就叫spi。

148行,比较重要的,spi_match_device是spi总线上匹配设备和设备驱动的函数,同样是在spi.c文件中:

00000085 static int spi_match_device(struct device *dev, struct device_driver *drv)
00000086 {
00000087     const struct spi_device    *spi = to_spi_device(dev);
00000088     const struct spi_driver    *sdrv = to_spi_driver(drv);
00000089 
00000090     /* Attempt an OF style match */
00000091     if (of_driver_match_device(dev, drv))
00000092         return 1;
00000093 
00000094     if (sdrv->id_table)
00000095         return !!spi_match_id(sdrv->id_table, spi);
00000096 
00000097     return strcmp(spi->modalias, drv->name) == 0;
00000098 }

写过驱动的都应该知道platform总线有struct platform_device和struct platform_driver,到了SPI总线,当然也有对应的struct spi_device和struct spi_driver,如87、88行所示。87行,关于struct spi_device的定义是在include/linux/spi/spi.h中:

00000069 struct spi_device {
00000070     struct device        dev;
00000071     struct spi_master    *master;
00000072     u32            max_speed_hz;
00000073     u8            chip_select;
00000074     u8            mode;
00000075 #
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值