linux内核静态添加sdio设备,嵌入式 linux下MMC/SD/SDIO识别与操作

我们知道host在扫描卡的过程中,其识别的顺序为SDIO  SD MMC,并且从它的注释可以看出,这个顺序是很重要的。那这篇文章,我们就看看SDIO的识别过程,它对应的函数就是mmc_attach_sdio(host) (函数位于文件drivers/mmc/core/sdio.c)

这个函数大概来说做了如下的工作

1、向卡发送CMD5命令,该命令有两个作用:第一,通过判断卡是否有反馈信息来判断是否为SDIO设备(只有SDIO设备才对CMD5命令有反馈,其他卡是没有回馈的);第二,如果是SDIO设备,就会给host反馈电压信息,就是说告诉host,本卡所能支持的电压是多少多少。

2、host根据SDIO卡反馈回来的电压要求,给其提供合适的电压。

3、初始化该SDIO卡

4、注册SDIO的各个功能模块

5、注册SDIO卡

对于以上功能的具体解释,下面将结合程序娓娓道来

1、CMD5命令的发送

3f288ee285423cc6e29fa526842ca321.png

第789行的函数就是发送的CMD5命令,如果卡对该命令有回馈的话,err就是0,否则,err为非0,直接退出了;并且需要重点说明的一点就是,该函数的最后一个参数ocr,它是存储反馈命令的,SDIO设备对CMD5的反馈命令为R4,下面来仔细分析一下这个R4,因为后面要用到这个R4命令。从SDIO

spec文档里面,我们能得到R4命令的格式

05e962f94abc9c56c1dd837c64e72a06.png

从上图可以看出,该命令有48位,但我们的ocr变量是32位的,那怎么存储呢?系统就去掉原命令的开头8位以及结尾的8位,只保留中间的32为,也就是截短后的命令格式是如下:

1c6edeed51b25ee542e709d94acfe806.png

具体各位的描述如下:

C --   我还不知道

Number 0f IO functions   -- 每个SDIO设备都有功能块,这三位就记录了该设备有多少个功能块,最多7个

Memory Present – 指明该设备是纯粹只有功能块的设备,还是同时包含了存储空间,如果为0就是前者,如果是1就是后者

Stuff Bits  -- 没有实际用途一般为0

I/O OCR – 该设备所能支持的电压范围(具体描述见sdio spec)

2、配置电压

abba6e53647ad0a618a9a6f0342a9579.png

ocr就是我们上面讲的反馈命令R4(截短之后的32位),那么ocr&0x7f的意义是什么呢?从R4的格式就可以看出来,其低24位就代表了所能支持的电压范围,我们再来详细的看一下这24位的OCR格式

0c6aea3771b14bf3751ffe1765bbefdb.png

现在应该可以知道ocr&0x7f的意义了吧,就是摈弃那些保留的电压范围。

重点关注mmc_select_voltage

55d99832da95a6e4922d86a8afdef8bb.png

第1080行的相与 过程就是判断host实际所支持的电压与card所需要的电压是否匹配,如果匹配,那么ocr的值就非0,否则就为0

简单介绍下第1082行的ffs函数,它的作用就是返回参数中第一个为1的bit的位置(ffs(0)=0,ffs(1)=1,ffs(8)=4),那么该函数用在这里的作用就是取出card需要的实际电压是多少;

第1090行的mmc_set_ios函数里面通过调用sdhci_set_power将host->ios.vdd所代表的电压写入寄存器PWRCONn中 完成那个对电压的重新配置(想要了解更详细的过程,请跟踪源代码)

3、初始化SDIO卡

6930d18e367ec6ea27540d63e6ab74ef.png

第821行就是初始化SDIO卡的函数  这个函数很长,也很重要,这里笔者就不列出其程序代码了,只是列出其中最重要的几条:

1、通过函数mmc_alloc_card分配一个mmc_card的变量card

2、通过读取R4命令中的bit27(也就是Memory Present)来判断此卡是纯IO卡 ,还是同时包含存储功能。笔者使用的WIFI模块为纯IO功能,所以card->type = MMC_TYPE_SDIO(这个很重要,以后会用到)

(接下来重点分析MMC_TYPE_SDIO的情况)

3、通过发送CMD3命令获取设备的从地址(relative addr),并且存放在变量card->rca中。笔者使用的WIFI模块的card->rca = 1

4、通过发送CMD7,选中相应从地址的卡

5、通过调用函数mmc_set_clock设置卡工作的时钟频率

6、通过发送CMD52命令,设置4位数据传输模式

4、注册SDIO功能模块

8cef2a697a56a9ef9d7dc5a14eb8e24b.png

847行的变量funcs存储该SDIO卡所包含的IO功能块的个数,851行到857行就是逐一初始化各个IO功能块,下面来重点看一下该函数的内容:

a93abba9a10732694050d5bdb58a10fb.png

第71行就是分配sdio_func结构体变量,该结构体存储了功能块的参数。

第75行就是给功能块编号,编号是从1到7(因为一个SDIO设备最多只有7个功能块),存储在变量func->num中

第78行就是读取SDIO卡中的FBR寄存器中关于该卡的功能类型的数据,存储在func->class变量中(具体关于FBR寄存器内容,可以参考SDIO spec文档)

第82行就是读取SDIO卡中的CIS寄存器的内容

b4f27c78dd6d96de0b8eb3907bc2c07d.png

上面的程序就是将功能模块逐个的注册进设备模型,这里想重点说明一下注册的名称(name),它是由三部分组成的,每部分之间用冒号隔开,(即 host的名称:rca:功能块编号) 。具体到笔者使用的WIFI模块,因为其host名称是mmc2  ,rca = 1,并且有两个功能模块(功能模块编号分别是1和2),所以在/sys/bus/sdio/devices目录下能见到如下两个设备名

mmc2:0001:1

mmc2:0001:2

5、注册SDIO卡

b2c63ebc68eb340eafc22e9373ddda3f.png

上面的mmc_add_card函数就是注册card了(这个card是在第3部分,初始化SDIO卡 里面分配和定义的)

5924dc50bc09c8ecae421463abc18c7c.png

第259行就是给card命名,格式为host名字:从地址,对于笔者的WIFI模块 就是mmc2:0001

第261到273行就是根据card->type来分辨出card的类型,给赋予相应的字符串,笔者的WIFI模块就是"SDIO"

第275行就是打印信息,具体不解释 笔者的打印信息为  mmc2:new high speed SDIO card at address 0001(通常可以通过查看内核启动信息中是否有该语句来判断card是否被正确识别)

第283行 就是将card注册进linux设备模型  注册结果就是可以在/sys/bus/mmc/devices目录下见到card 的名字,笔者的就是mmc2:0001

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
SDIO (Secure Digital Input/Output) 是一种用于将外部设备连接到计算机系统的接口标准。Linux提供了SDIO设备驱动程序,用于管理和控制与系统连接的SDIO设备SDIO设备驱动在Linux内核中的实现基于统一的设备模型,以提供设备发现、配置和控制功能。驱动程序负责与硬件通信,并且为用户空间程序提供与SDIO设备交互的接口。 SDIO设备驱动程序的核心功能包括: 1. 设备识别和初始化:驱动程序通过检测SDIO设备的插入和拔出事件来进行设备识别。在插入新的SDIO设备时,驱动程序会通过与设备通信来获取设备识别信息,并进行必要的初始化设置。 2. 数据传输:驱动程序负责管理和控制从SDIO设备读取数据或向设备写入数据。它处理数据传输的请求和缓冲区管理,以确保数据的正确传输和处理。驱动程序还为用户空间程序提供接口,以便它们可以通过系统调用与SDIO设备进行数据交互。 3. 中断处理:SDIO设备可能会产生中断信号,以通知系统有新的数据可用或发生了特定事件。驱动程序负责处理这些中断,并触发适当的操作或通知用户空间程序。 4. 功耗管理:SDIO设备驱动程序还可以实现功耗管理功能,以控制和优化设备的功耗消耗。它可以根据系统的需求来控制设备的电源状态,例如睡眠模式和唤醒模式之间的切换。 5. 错误处理和调试:驱动程序应具备可靠的错误处理和调试功能,以便在发生错误或异常情况时能够及时识别和处理问题。例如,驱动程序可能需要处理数据传输错误、设备通信失败或设备故障等情况。 总之,LinuxSDIO设备驱动程序提供了一个统一的接口和框架,以便方便地管理和控制与系统连接的SDIO设备。它允许用户空间程序与SDIO设备进行数据交互,并负责处理设备的初始化、数据传输、中断处理、功耗管理和错误处理等功能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值