图7-8引自《MMC规范》。需要根据这些控制器的属性值正确地操作MMC设备。图7-9MMC信号传输特点图7-9以单一的读操作为例,可见MMC的信号主要通过CMD传送命令,并且需要响应,通过DAT信号传送数据。另外由于MMC连接的设备可能会以卡的形式存在,这就需要能够支持对设备插入的检测,在系统级别也需要能够对设备插拔进行支持。总体上来说,MMC总线驱动的需求就是要能实现总线的各种功能,并且满足总线的各种无关性需求。......
2023-11-22
1.总线相关以及核心框架
MMC总线设备相对于I2C和SPI总线要复杂,但是总线框架的思路是一致的。首先来看看MMC子系统的初始化mmc_init。
从分析可见,注册了两个bus(分别是mmc bus和sdio bus)和一个class(mmc host class),这里有两种类型的bus是由于MMC连接还需要支持SDIO总线类型,而在MMC框架中就需要实现SDIO总线的功能,其中SDIO总线建立在MMC总线的基础上,所以需要注册两种bus。而注册一个class的原因,与SPI设备管理部分的实现是相同的,这样是为了避免总线控制器的设备进行总线相关的操作。
接下来看看两个总线的信息:
关于这两种bus先来了解MMC总线的情况:
match直接返回真,所以只要是MMC总线设备就会直接与MMC总线驱动匹配,这样的情况说明MMC总线驱动只有一个,并由系统框架已经提供,可以支持所有的设备,这与MMC总线设备主要作为存储设备相关,存储设备只要提供统一的块设备驱动(mmc block层的驱动)即可。
现在对MMC总线管理的设备还是不清楚,继续看一下probe接口:
从中可见,MMC总线设备主要就是mmc_card,而总线驱动就是mmc_driver,在mmc_driver的probe接口中会对上层的驱动相关的接口进行初始化,建立上层与MMC总线层的关联,主要就是与块设备驱动层的关联。
这样的设计与实现是合理的,因为MMC的设备(包括SD卡设备)主要用于数据存储,所以块设备是最合适的。
而SDIO则不同,SDIO设备可以借助MMC总线连接实现不同的功能,下面看看SDIO总线的相关接口:
从match中可见,会涉及具体的总线设备与总线驱动的匹配,这是因为SDIO可以有不同的功能,所以需要进行匹配。
SDIO总线管理的设备在内核中主要由sdio_func来表示,而相对应的驱动则由sdio_driv-er来表示。
MMC整体框架如图7-10所示。
图7-10 MMC整体框架
从图7-10可见,MMC主要管理两个总线功能:MMC和SDIO。MMC总线功能对应于块设备,而在SDIO总线之上可以是具体功能的设备。通常一个MMC接口只与一个设备进行连接,但是因为允许插拔,所以需要能支持检测、扫描来支持硬件插拔,以及不同功能设备的切换。
MMC总线整体框架主要实现了这些功能。
2.总线控制器相关
在MMC框架中,无论是MMC总线还是SDIO总线,实际的总线控制器都是相同的硬件,只是协议中命令字和状态机的差别。在介绍MMC框架初始代码时见到其中注册了class,以与MMC总线设备进行区分,相应的class就是为总线控制器提供的,MMC框架中总线控制器由mmc_host来表示和管理,细节如下:
可见主要是对总线控制器的操作能力以及状态进行设置,这些操作能力相关的都是属于相关规范的物理特性,需要通过这些属性标注总线控制器物理能力。另外重要的就是两个操作接口,分别是mmc_host_ops和mmc_bus_ops。
先来看看mmc_host_ops:
这里主要是控制和进行传输操作的接口,是进行实际总线控制器操作的接口,真正的传输也是通过总线控制器来完成的。
mmc_bus_ops接口细节如下:
需要mmc_bus_ops的原因是因为MMC总线可以支持不同协议规范的设备,这些设备相关的操作是不同的,所以在控制器中提供相应的操作接口,这样在总线设备侦测时就可以根据设备的特点加载合适的操作接口。在相应的操作中,detect是检测设备是否存在,其他大多与电源管理相关,通过规范的命令可以完成相应的操作。
MMC总线控制器框架提供了创建的接口mmc_alloc_host,主要内容如下:
主要的操作是分配空间,并初始化与功能相关的work,其中最重要的是探测设备的work,相应的操作是mmc_rescan,后面会进行介绍。
接下来的接口是注册并初始化控制器硬件的接口mmc_add_host,详细内容如下:
在调用mmc_add_host之前,需要将mmc_host_ops初始化,并将控制器的相关属性进行正确设置。其中最重要的操作就是mmc_start_host,会通过mmc_detect_change唤醒控制器的detect work,最终会通过mmc_rescan来进行设备探测,这实现了MMC总线设备发现的重要功能,详细分析如下:
(www.chuimin.cn)
可见主要的工作就是探测设备,并在探测成功后通过mmc_attach_xxx来初始化总线控制器的busops接口,并对总线设备进行初始化操作。
这样总线的主要功能,包括总线传输事务以及总线设备发现,就都在代表MMC总线的MMC总线控制器部分有了完整支持。
3.总线设备相关
前面已经提及,MMC总线设备管理由mmc_card来完成。下面具体介绍:
从中可见,为了支持MMC/SD/SDIO等不同的协议规范,其中的属性都在mmc_card中进行了表示,具体的类型和对应的属性都会在设备发现阶段进行初始化。
MMC设备的管理框架提供了相应的创建和注册接口。首先来了解创建的接口mmc_alloc_card:
主要进行设备模型相关的设置。下面的接口是用于注册的,详细内容如下:
可见主要的工作与设备模型相关,当向设备模型注册了device之后,就会通过总线来进行驱动的probe操作。对MMC驱动,之前已经说明只有MMC block提供的mmcblk驱动,详细内容如下:
主要与块设备层关联的工作是由mmc_blk_probe来完成的,下面来看看细节:
从分析中可见,通过mmcblk驱动就可以将MMC设备与块驱动层建立关联,进而可以被文件系统和应用使用。至于request queue的操作,在MMC block层mmc_init_queue中单独创建了kthread进行相应操作:
在mmc_queue_thread中则从request queue中获得request再通过mmc_queue的issue_fn接口即mmc_blk_issue_rq来真正执行相应的request。这样MMC作为存储设备的功能就完整了。
SDIO总线设备由sdio_func进行管理,其详细内容就不进行分析了,与mmc_card类似,包含一些属性,但是由于SDIO中的data0可以作为中断源,所以其中包含中断的属性,总线控制器与mmc_card没有差别,所以不需要单独关联。MMC框架也提供了创建和注册SDIO设备的接口。先来看看创建的接口sdio_alloc_func:
从分析中可见,SDIO设备并不是修改mmc_card中的dev属性,而是拥有单独设备模型实体,在设备层次中其父设备是mmc_card,这与设备的逻辑层次相符,而mmc_card在sdio_func中起到了中介作用。
再来看看设备注册的接口sdio_add_func:
可见主要的操作也是向设备模型进行注册,注册后就通过总线操作查找匹配的驱动并绑定,就可实现其相关功能。
对不同规范类型的设备,MMC框架通过mmc_xxx_init_card和mmc_attach_xxx等接口封装了以上的操作来实现设备的创建与注册,这些都是在设备发现阶段完成的。
在设备发现阶段MMC主要依靠探测发现的方式进行,当card有插拔的时候同样需要进行设备的重新发现与探测,MMC框架为这种情况提供了接口mmc_detect_change,其中会唤醒总线控制器的detect操作即mmc_rescan来重新detect总线设备的情况,并根据当前设备情况进行相关操作。
4.总线传输接口
MMC框架是通过mmc_re quest管理MMC总线传输,细节如下:
在总线层所有的传输都是通过mmc_request来进行实际操作。具体的接口是mmc_wait_for_req,下面来看看细节:
可见主要是以同步的方式进行总线传输操作的,具体操作的发起是通过mmc_start_re-quest来完成的,细节如下:
总线传输基本操作是先发送命令,然后进行数据操作,接下来结束命令。实际操作中后两步可选,在完整的操作中任何一步有了问题都会导致整个操作失败,相应的mmc_request中同样分为三步,并在三步的实体中都关联到mmc_request来保证正确处理。块设备的传输最终直接调用mmc_wait_for_req来完成。
除了数据等稍微复杂的传输操作之外,MMC框架对简单的命令发送还提供了mmc_wait_for_cmd接口来执行相关操作。细节如下:
可见主要的操作就是对mmc_wait_for_req的简单封装,其中主要是为了命令的操作。
MMC/SD/SDIO规范中都规定了一些特殊的操作和命令,虽然这些操作最终都是通过以上的接口执行的,但是为了方便开发MMC框架分别提供了相应的接口进行相关操作,具体的操作可以参考规范的说明。具体的接口如下:
这样整个命令操作以及传输功能就完整了。
有关深入剖析Linux内核与设备驱动的文章
图7-8引自《MMC规范》。需要根据这些控制器的属性值正确地操作MMC设备。图7-9MMC信号传输特点图7-9以单一的读操作为例,可见MMC的信号主要通过CMD传送命令,并且需要响应,通过DAT信号传送数据。另外由于MMC连接的设备可能会以卡的形式存在,这就需要能够支持对设备插入的检测,在系统级别也需要能够对设备插拔进行支持。总体上来说,MMC总线驱动的需求就是要能实现总线的各种功能,并且满足总线的各种无关性需求。......
2023-11-22
SPI总线框架对这两类设备进行管理,具体的框架如图7-6所示。通常的SPI驱动都是在内核实现并在内核态执行的,所以就不对spidev进行详细的分析。SPI总线框架整体的功能就是这样,接下来看看具体各部分的实现。在SPI总线框架中相应的实体是spi_board_info,内容如下:其中的主要信息是与总线信号相关的属性。......
2023-11-22
VFS的实现是以“一切皆是文件”为需求出发点的。要理解VFS的框架首先看一下VFS和系统的静态关系框图,如图5-1所示。从图5-1可见,VFS是用户层的直接接口,是面向用户的服务。图5-1VFS和系统静态关系图在图5-2中每个节点被使用时都会在VFS层中创建dentry,这样可以快速通过文件名进行查找和定位,Linux内核中对dentry的管理组织形式如图5-3所示。以上是系统运行时VFS对文件名的组织管理,这是VFS管理的一个方面。......
2023-11-22
整体的frame buffer框架如图6-5所示。了解frame buffer的框架还要先从为用户提供的接口开始。图6-7可变参数中硬件信息的含义固定信息是在frame buffer的操作过程中并不发生变化的。从整体分析,frame buffer的框架很直接,主要就是直接管理实际的设备,而相关的操作与应用层直接相关。......
2023-11-22
也正是因为Linux内核的唯一性,各个不同发布版本拥有相同的框架。Linux内核是在整个Linux系统的最底层,它负责管理硬件,运行用户程序,并保持系统整体的安全性和完整性。可以说是Linux系统的根和灵魂。图3-1中看到Linux内核还有另一层面的含义。这对于Linux内核同样适用。所以对Linux内核的剖析、学习和研究也不能独立于系统进行,而是要综合考虑应用、内核和硬件等各方面的信息和内容。这样才能更全面、深刻地理解Linux内核。......
2023-11-22
Linux内核中的内存管理框架考虑到了各个方面的需求,实现得非常精细。1内核对于内存的管理和使用的整体框架Linux内核的内存管理也要满足内核自身的需要。图4-32展示了Linux内核的内存管理框架。仅有好的页分配器是不能满足内核对于内存管理的需要的,前面已经介绍了,内核有很多频繁使用的数据结构,对于它们最好单独分配空间进行管理,这就形成了SLAB分配器。......
2023-11-22
考虑到电源管理的需求涉及处理器和各种设备,一方面是处理器尽可能减少功耗,另一方面是设备尽可能减少功耗。图5-30Linux电源管理各个功能从图5-30可见Linux内核的电源管理功能有与处理器相关的CPUIdle和CPUFreq,也有与设备相关的runtime pm,另外还有与整个系统待机时SLM相关的低功耗电源管理功能。下面分别对这些功能框架进行介绍。具体的驱动同样会在SoC电源管理部分进行讲解。对具体设备的电源管理实现,将在设备驱动中进行详细分析。......
2023-11-22
应用层对输入设备的基本使用主要是集中在读取相应的事件方面,具体事件传给哪个应用则是属于应用框架的范畴,与具体的UI控制紧密关联。对于Android框架来说,输入设备的相关操作是在EventHub中实现的,首先需要检查所有的输入文件,其是通过inotify来实现的。......
2023-11-22
相关推荐