Linux内核中,SPI和I2C两个子系统的软件架构是一致的,且Linux内核的驱动模型都以bus,driver,device三种抽象对象为基本元素构建起来。下文的分析将主要用这三种抽象对象的创建过程及其相互调用关系和作用来进行说明。
1. SPI各对象的初始流程
1.1 创建spi_bus_type总线
postcore_initcall(抽象层spi.c中)
bus_register(&spi_bus_type);
class_register(&spi_master_class);
1.2 把板级信息注册到全局链表中
embedsky_evm_dev_cfg(arch_initcall(customize_machine) -->init_machine()中)
spi1_init
spi_register_board_info(am335x_spi1_slave_info, ..)
static struct spi_board_info am335x_spi1_slave_info[] = {
{
.modalias = "smb380",
.platform_data = &Acceleration_sensor,
.irq = -1,
.mode =SPI_MODE_0,
.max_speed_hz = 120000,
.bus_num = 2,
.chip_select = 0,
},
};
list_add_tail(&bi->list, &board_list);//把当前boardinfo放到全局board_list中
list_for_each_entry(master, &spi_master_list, list)//此时spi_master_list中没有内容,故下面两条语句不执行
spi_match_master_to_boardinfo(master, &bi->board_info)
spi_new_device(master, bi);// =spi_alloc_device() + spi_add_device
1.3 创建platform总线上的平台特定spi device
arch_initcall(omap2_init_devices);//创建特定spi device
omap_init_mcspi();// device name: "omap2_mcspi"
omap_mcspi_init
omap_device_build
omap_device_build_ss
omap_device_alloc
omap_device_register
1.4 创建platform总线上的平台特定spi driver
subsys_initcall(具体spi设备驱动文件spi-omap2-mcspi.c中)
platform_driver_probe(&omap2_mcspi_driver, omap2_mcspi_probe);//drive name: "omap2_mcspi",使用name在platform虚拟总线上进行匹配
spi_alloc_master
INIT_WORK(&mcspi->work,omap2_mcspi_work);
spi_register_master
list_for_each_entry(bi, &board_list, list)//根据bi,一个master可以对应多个slave
spi_match_master_to_boardinfo(master, &bi->board_info);
spi_new_device(master, bi);
spi_alloc_device(master)
spi_setup(spi)// spi->master->setup(spi);
spi_add_device ()
1.5 用户创建spi_bus_type上的driver(名字匹配spi master)
module_init(spidev_init);
spi_register_driver(&spidev_spi_driver);//spi device & spi driver匹配(device modalias和driver name相同)后,执行该driver的probe函数
spidev_probe
device_create(..."spidev%d.%d" ..)//spi_driver创建设备:spidevX.Y,让该device的->p->driver_data为spi_device,换言之,spi_driver只是一个桥梁,应用层open spi driver时候获得该device,继而在别的操作如release、read/write时通过该device获取spi_device,即实际让spi工作的只是spi_device,而spi_device也是通过其对应的spi_master进行的,如spi_setup,transfer等。另,spi_master和这里创建的spidevX.Y是放在sys/class/spi_master及sys/class/spidev目录下的,并没有对应的bus和driver。
2. I2C子系统启动流程
2.1 板级相关的初始化:
包括1)板级信息注册到全局链表__i2c_board_list;
2)注册i2c device到platform总线上。
embedsky_evm_dev_cfg(arch_initcall(customize_machine) -->init_machine()中)
i2c2_init
omap_register_i2c_bus(3, 100, am335x_i2c_boardinfo2。。
i2c_register_board_info//注册板级i2c信息到__i2c_board_list
omap_i2c_add_bus(bus_id);
omap2_i2c_add_bus(bus_id);
omap_device_build// 创建platform device:"omap_i2c"
omap_device_build_ss
2.2 platform总线上i2c相关driver和device的注册
I2c driver 到platform总线上,该总线上的i2c driver & i2c device匹配后:
I2c adapter device注册到i2c_bus_type总线,i2c client device注册到i2c_bus_type总线
subsys_initcall(omap_i2c_init_driver);
platform_driver_register(&omap_i2c_driver);//以"omap_i2c"名字匹配后调用相关probe
omap_i2c_probe
//omap i2c 本身的一些初始化
//设置i2c板级特定信息到该driver对应的device上,比如slave对应的adapter(master),设置该adapter的algo
i2c_add_numbered_adapter
i2c_add_adapter(adap);
i2c_register_adapter(adap);//把adapter device(device类型为i2c_adapter_type)注册到i2c_bus_type上,该总线以id进行匹配
__process_new_adapter
i2c_do_add_adapter
i2c_detect(adap, driver);
i2c_detect_address(temp_client, driver);
i2c_new_device(adapter, &info);//把client(device类型为i2c_client_type)注册到i2c_bus_type上
2.3 i2c使用者
用户新建并注册i2c driver到i2c_bus_type上,通过id和i2c client device(板级信息中的type字段)匹配后调用用户新建driver的probe函数。
同样的,作为master的adapter抽象为一个device,挂载到i2c_bus_type总线上,但是没有相应的driver与之匹配,因为数据流是上层用户如这里的i2c使用者创建的driver call对应的client device,该client device有与之匹配的adapter device。一般情况下,driver的目的是让上层用户调用对应device拥有的接口,这里的i2c adapter和i2c client是同级,只需要client有对应adapter的连接通路,adapter自己就不需要自己的driver。这种方式和spi子系统是一样的:
1) driver的作用是作为暴露在外部的接口,内部的实际操作放置于device中;
2) 对于硬件上存在master和slave概念的驱动,device中也会包括master和slave两个device,且这两个device之间互相联系(使用结构体中的指针)。
3. 从文件角度看spi/i2c子系统的地位及其构成
Linux内核中SPI总线驱动分析
本文主要有两个大的模块:一个是SPI总线驱动的分析 (研究了具体实现的过程): 另一个是SPI总线驱动的编写(不用研究具体的实现过程). 1 SPI概述 SPI是英语Serial Peripheral ...
linux内核中的MFD子系统
分析用的内核版本为5.1.3 1.MFD全称 Multi-function Device,多功能设备 2. 为何会出现MFD子系统 由于出现了一类具有多种功能的外围设备或cpu内部集成的硬件模块 3. ...
KSM剖析——Linux 内核中的内存去耦合
简介: 作为一个系统管理程序(hypervisor),Linux® 有几个创新,2.6.32 内核中一个有趣的变化是 KSM(Kernel Samepage Merging) 允许这个系统管理程序通 ...
剖析linux内核中的宏---------container_of
#define container_of(ptr, type, member) ({ \ const typeof(((type *)0)->member) * __mptr = (ptr); ...
Linux内核中的GPIO系统之(3):pin controller driver代码分析
一.前言 对于一个嵌入式软件工程师,我们的软件模块经常和硬件打交道,pin control subsystem也不例外,被它驱动的硬件叫做pin controller(一般ARM soc的datash ...
Linux内核中的GPIO系统之(3):pin controller driver代码分析--devm_kzalloc使用【转】
转自:http://www.wowotech.net/linux_kenrel/pin-controller-driver.html 一.前言 对于一个嵌入式软件工程师,我们的软件模块经常和硬件打交道 ...
Linux内核调用SPI平台级驱动_实现OLED的显示功能
Linux内核调用SPI驱动_实现OLED显示功能 0. 导语 进入Linux的世界,发现真的是无比的有趣,也发现搞Linux驱动从底层嵌入式搞起真的是很有益处.我们在单片机.DSP这些无操作系统的裸 ...
Linux 内核中的 Device Mapper 机制
本文结合具体代码对 Linux 内核中的 device mapper 映射机制进行了介绍.Device mapper 是 Linux 2.6 内核中提供的一种从逻辑设备到物理设备的映射框架机制,在该机 ...
[转] Linux 内核中的 Device Mapper 机制
本文结合具体代码对 Linux 内核中的 device mapper 映射机制进行了介绍.Device mapper 是 Linux 2.6 内核中提供的一种从逻辑设备到物理设备的映射框架机制,在该机 ...
随机推荐
Codeforces Round #257 (Div. 2)
A - Jzzhu and Children 找到最大的ceil(ai/m)即可 #include #include using name ...
[设计模式]<;<;设计模式之禅>;>;关于接口隔离原则
在讲接口隔离原则之前,先明确一下我们的主角——接口.接口分为两种: ● 实例接口(Object Interface),在Java中声明一个类,然后用new关键字产生一个实例,它是对一个类型的事物的描述 ...
VI一个终端编辑多个文件的命令
可分两种情况: 在不同窗口中打开多个文件: 如果已经打开一个了一个文件, 则在vi的命令输入状态下输入 :sp 另外一个文件的路径及文件名, 如此就可以在一个窗口打开多个文件了. 可以使用 ...
BrainTree信用卡包
BrainTree是一个国外集成信用卡支付的卡包. 沙盒登陆地址: https://sandbox.braintreegateway.com/login 登陆沙盒得到商户ID.公钥.私钥. 1.配置w ...
使用oracle的SQL Developer创建用户的方法
这里针对的是Oracle11g,其它版本的没测试过不知道. 首先,使用system建立连接,密码是你安装时指定的那个密码,然后在最下面的“其它用户”中创建一个新用户. 注意1:创建完毕后一定要注意要在 ...
MySQL mysqlbinlog解析出的SQL语句被注释是怎么回事
MySQL mysqlbinlog解析出的SQL语句被注释是怎么回事 一网友反馈使用mysqlbinlog解析出的二进制日志中的内容中,有些SQL语句有#注释的情况,这个是怎么回事呢?我们通过实验 ...
TCP详解——连接建立与断开
一.报文结构介绍 在开始讲TCP连接过程时,还是先看看TCP报文的格式如图1所示.IP数据报此时由IP头部+TCP头部+TCP数据组成.不带选项的TCP头部是20字节长,而带选项的,TCP头部最长可达 ...
Windows 64位系统安装Apache2.4
Windows 64位系统安装Apache2.4 来自:百度经验:jingyan.baidu.com 现在大部分一键安装包多是32位的,并不支持64位,直接在64位的系统上使用会报错的,所以我这里就来 ...
vim文本删除方法 Linux
1,先打开某个文件: vim filename 2,转到文件结尾 在命令模式输入 G 3,转到10行 在命令模式输入 10G 4,删除所有内容:先用G 转到文件尾,然后使用下面命令: :1, .d ...