今天花了时间简单看了mmc/sd部门内容和代码,我觉得形式上,这个部分和i2c非常相似系统也是分成core层,host层(对应i2c的adapter),设备层如果这样讲,那么core层主要功能应该是提供host注册,总线注册,设备注册的几个方法以及所谓sdio总线接口的算法了。host层已经是注册一个platform设备,其中应该提供主要sdio接口算法的实现。设备层,应该是提供几个公司1)注册块设备,映射到/dev下面的设备节点 2)应该还有设备其他信息。当然,也有很多和i2c不一样的地方,就是必须支持动态扫描卡设备的方法,而i2c是靠i2c地址制定的。
有关MMC/SD/SDIO相关的知识这里就不多讲了,请参考相关资料。这里主要涉及Linux下MMC相关内容。
内核版本(2.6.36)
首先说一下Linux相关MMC的代码分布,主要有两个目录,一个头文件目录和一个源代码目录。
分别位置如下:
include/linux/mmc
drivers/mmc
要阅读MMC相关代码就必须要看这两个目录。在drivers/mmc目录下分别有三个子目录,其将对应接下来要讲的MMC的体系结构。这三个子目录分别为:
card
core
host
它们的内容后面讲到体系结构时自然就明了了。
现在来说说MMC的体系结构,其分为三层
/dev下设备文件访问MMC/SD/SDIO
用户空间 |
---------------------|-----------------------------------------------------
内核空间 \ /
MMC Card层(对应具体的设备驱动,如MMC/SD卡块设备驱动,SDIO UART)
|
\ /
MMC core层(为上次设备驱动实现提供操作接口,和下层host注册提供机制)
|
\ /
Host层(具体MMC/SD/SDIO控制器驱动层。如S3C2440 MMC/SD控制器驱动)
|
\ /
-----------------------------------------------------------------------------
硬件层
对于我们来说,编写MMC/SD卡相关驱动主要涉及的就是Host层,其余层不用考虑。对于SDIO设备除了Host层以外,还有可能要编写MMC Card层的设备驱动。
编写Host层驱动,主要是填充mmc_host结构体相关内容和实现mmc_host_ops结构体中的函数。最后调用mmc_add_host向MMC core注册host驱动。可以参考S3C24XX的HOST驱动程序(drivers/mmc/host/s3cmci.c,s3cmci.h),上层MMC Core主要调用mmc_host_ops中的函数来实现与硬件交互。如下是mmc_host_ops结构体里面的函数:
struct mmc_host_ops {
/*使能和禁止HOST控制器*/
int (*enable)(struct mmc_host *host);
int (*disable)(struct mmc_host *host, int lazy);
/*这个是关键的函数,所有对MMC/SD的操作,包括发命令和读数据,都通过该接口来实现,所以实现该接口时要处理是命令还是数据操作,另外要考虑是否使用DMA来进行数据传输。*/
void (*request)(struct mmc_host *host, struct mmc_request *req);
/*用来设置MMC/SD的时钟,电压等操作*/
void (*set_ios)(struct mmc_host *host, struct mmc_ios *ios);
/*检查MMC/SD是否写保护了*/
int (*get_ro)(struct mmc_host *host);
/*检查mmc/sd的插入和拔出*/
int (*get_cd)(struct mmc_host *host);
void (*enable_sdio_irq)(struct mmc_host *host, int enable);
/* optional callback for HC quirks */
void (*init_card)(struct mmc_host *host, struct mmc_card *card);
};
接下来说说MMC Core层。
该层主要实现了几个结构体函数指针,用来构建整个MMC设备驱动模型。它们是:
struct bus_type mmc_bus_type /*mmc总线,用来管理sd/mmc卡设备和驱动*/
struct mmc_bus_ops mmc_ops /*MMC卡总线操作函数,主要是在电源管理方面*/
struct mmc_bus_ops mmc_sd_op /*SD卡总线操作函数,主要是在电源管理方面*/
struct mmc_bus_ops mmc_sdio_ops /*SDIO总线操作函数,主要是在电源管理方面*/
struct bus_type sdio_bus_type /*SDIO另外定义了一条总线*/
core.c文件中实现了几个关键的函数,用来提供给上层MMC Card调用和对SD/MMC卡的侦测函数以及初始化。
供给上层MMC Card调用主要有:
void mmc_wait_for_req(struct mmc_host *host, struct mmc_request *mrq);
int mmc_wait_for_cmd(struct mmc_host *host, struct mmc_command *cmd, int retries);
mmc card层就是通过这些函数来操作mmc/sd卡。而这些函数最终调用的是mmc_host_ops 结构体中的request函数来进行具体的操作。
对SD/MMC卡的侦测函数以及初始化,主要实现在
void mmc_rescan(struct work_struct *work);
函数中。
host层在调用mmc_add_host时会引发该函数的调用,侦测/初始化顺序为:
先SDIO接口
/*
* First we search for SDIO...
*/
err = mmc_send_io_op_cond(host, 0, &ocr);
if (!err) {
if (mmc_attach_sdio(host, ocr)) {
...
在SD:
/*
* ...then normal SD...
*/
err = mmc_send_app_op_cond(host, 0, &ocr);
if (!err) {
if (mmc_attach_sd(host, ocr))
最后是MMC:
/*
* ...and finally MMC.
*/
err = mmc_send_op_cond(host, 0, &ocr);
if (!err) {
if (mmc_attach_mmc(host, ocr))
其中mmc_attach_xxx函数就是用来完成侦测和初始化的,选择相应的总线操作函数,并产生struct mmc_card结构体,并填充其内容,最后注册一个mmc_card(代表着一个设备),并在注册中由mmc_bus_type结构体的match和probe函数来查找到适合该设备的驱动(这个又牵涉到设备驱动模型,可以查看设备驱动模型相关内容,了解设备和驱动匹配的过程),这里将匹配到mmc card层的MMC_Block(MMC块设备驱动程序,由 struct mmc_driver代表)。在完成设备侦测和初始化以后,以后的操作就是mmc card层中相关的设备驱动程序发出的了。
再说说MMC card层,该层主要实现具体的设备驱动程序,如MMC块设备驱动程序,通过mmc_register_driver注册。如果是SDIO就有可能是其它字符设备驱动程序了,其通过调用sdio_register_driver来注册设备驱动。
总体概括来说:
host层提供驱动相关MMC/SD/SDIO控制器的功能。
Core层提供了具体MMC/SD/SDIO设备侦测和初始化功能,以及电源管理方面的内容和通用的操作功能。
Card为实现具体的设备驱动层。
这样的分层结构在Linux设备驱动中非常常见,如I2C,SPI等都提供了这样的驱动模型。
最后简单说说SDIO相关部分。在core层注册了新的sdio_bus_type总线,并且定义了新的sdio_driver来代表sdio设备驱动,并定义了struct sdio_func来代表设备。所以在SDIO设备除了struct mmc_card来代表设备以外,还有struct sdio_func来代表具体功能设备。所以在mmc_attach_sdio函数中除了注册mmc_card以外,还注册了sdio_func。具体代码如下:
int mmc_attach_sdio(struct mmc_host *host, u32 ocr)
{
....
/*
* First add the card to the driver model...
*/
err = mmc_add_card(host->card);
if (err)
goto remove_added;
/*
* ...then the SDIO functions.
*/
for (i = 0;i < funcs;i++) {
err = sdio_add_func(host->card->sdio_func[i]);
if (err)
goto remove_added;
}
....
}
所以它除了调用mmc_bus_type结构体的match和probe函数来查找到适合该设备的驱动外,也调用sdio_bus_type结构体的match和probe函数来查找到适合该设备的驱动。
关于linux mmc/sd驱动程序架构,你了解多少?
- 驱动(84267)
- Linux(206513)
- MMC(30332)
- 架构(25184)
相关推荐
了解和使用no-OS及平台驱动程序
快速发展的技术需要软件支持(固件驱动程序和代码示例)来简化设计导入过程。本文介绍如何利用no-OS(无操作系统)驱动程序和平台驱动程序来构建ADI公司精密模数转换器和数模转换器的应用固件,这些器件
2022-04-11 15:55:48
4097


基于eCos系统的SPCE3200中SD卡驱动程序的开发
基于eCos系统的SPCE3200中SD卡驱动程序的开发
设备驱动程序是介于硬件和嵌入式系统eCos内核之间的软件接口,是一种底层的、专用于某一硬件的软件组件。在eCos系统[1]中,设
2009-11-05 16:03:26
1157


linux驱动程序的主要流程和功能
驱动程序是用于控制和管理硬件设备的软件模块,它主要负责与设备进行交互,通过操作设备的寄存器和接口,实现对硬件的控制和访问。在Linux系统中,驱动程序是实现与硬件设备交互的一个关键部分。本文将详细
2023-12-08 14:56:02
668

LINUX音频驱动架构相关资料分享
1、LINUX音频驱动架构 LINUX下音频驱动开发,要遵循标准的ALSA架构, 下面分别从硬件架构、软件架构、驱动程序,3个方面分析。 硬件架构 硬件上音频总线接口有很多,如I2S、PCM、TDM、SLIMBUS等,以I2S为例分析:原作者:DMCF
2022-11-04 15:57:35
Linux的32位驱动程序
你好,我已经下载了网格驱动程序2.1但它只带有64位驱动程序的Linux。我如何获得Linux的32位驱动程序。谢谢,赛义德以上来自于谷歌翻译以下为原文Hello there,I've
2018-09-07 16:42:51
Linux设备驱动程序开发 - Linux设备驱动类型
驱动程序在Linux的内核源代码中占有很大的比例,源代码的长度日益增加,主要是驱动程序的增加。在Linux内核的不断升级过程中,驱动程序的结构还是相对稳定。Linux设备驱动架构的不断发展中始终坚持
2016-04-16 14:31:57
stm32 sd卡驱动程序。
程序是基于keil4开发的,是关于的SD卡的驱动程序。本人写了部分其他处理器的sd卡的驱动程序。codefire, k10,xs128等。有需要的可以跟我联系哈。qq:490690385.
2013-06-24 15:22:06
嵌入式Linux驱动程序开发大概了解
1.嵌入式Linux驱动程序开发嵌入式Linux驱动程序开发包罗万象,基本上每个点都要大概了解一下。1.1软件工具Makefile必须要掌握一些,至于Kconfig太简单了只是个配置文件算不上程序
2021-11-02 10:17:37
嵌入式系统驱动程序的开发
嵌入式系统驱动程序的开发有别于WIndows或Linux。后者除了必须了解新设备的硬件特性,把控制硬件的程序尽快完成之外,还需要设法让驱动程序符合Windows或Linux的规定(大且复杂的架构
2021-11-08 06:21:19
请问VC707板上有设备驱动程序吗?
驱动程序使用监视器或其他I / O驱动程序。现在,我有一些问题。在VC707板上,有hdmi端口。我是否必须为显示器制作设备驱动程序?如果没有,我认为VC707板上有很多设备驱动程序。我在哪里可以查看所有这些?另外,如果您有关于板载Linux移植的任何信息,请与我分享。永远谢谢YoungWook
2019-09-30 06:56:37
评论