转自:http://blog.csdn.net/skdkjzz/article/details/38927943

我们知道host在扫描卡的过程中,其识别的顺序为SDIO  SD MMC,并且从它的注释可以看出,这个顺序是很重要的。那这篇文章,我们就看看SDIO的识别过程,它对应的函数就是mmc_attach_sdio(host) (函数位于文件drivers/mmc/core/sdio.c), 那么同一个控制器是如何区分mmc/sd/sdio设备的,软件会不停的轮训设备,发不同的指令,然后不同的设备会做出不同的反应。

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

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

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

               3、初始化该SDIO卡

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

               5、注册SDIO卡

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

 1、CMD5命令的发送

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

            

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

            

        

           具体各位的描述如下:

C --   我还不知道

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

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

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

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

         2、配置电压

         

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

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

重点关注mmc_select_voltage

                  

            第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卡

               

             第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功能模块

             

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

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

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

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

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

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

mmc2:0001:1

mmc2:0001:2

5、注册SDIO卡

       

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

第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

[mmc]Linux下MMC/SD/SDIO的识别与操作的更多相关文章

  1. (原创)Linux下一定要4字节地址对齐操作

    Linux下一定要4字节地址对齐操作:“血”的教训,一定不要忘记!!! 当然不仅仅是Linux下,所有的32位机都应该如此!!!

  2. Linux下记录所有用户的登录和操作日志

    Linux下记录所有用户的登录和操作日志   一般我们可以用history命令来查看用户的操作记录,但是这个命令不能记录是哪个用户登录操作的,也不能记录详细的操作时间,且不完整:所以误操作而造成重要的 ...

  3. Linux下磁盘分区、挂载、卸载操作记录

    Linux下磁盘分区.挂载.卸载操作记录. 操作环境:CentOS release 6.5 (Final) Last :: from 118.230.194.76 [root@CentOS ~]# [ ...

  4. linux下vi编辑某文件时,操作出现 错误提示: E325: ATTENTION 2, Found a swap file by the name ".p1.c.swp"

    当我在linux下用vi打开p1.c文件时 root@iZ2zeeailqvwws5dcuivdbZ:~/1/01/指针# vi p1.c 会出现如下信息: E325: ATTENTION Found ...

  5. 归纳整理Linux下C语言常用的库函数----文件操作

    在没有IDE的时候,记住一些常用的库函数的函数名.参数.基本用法及注意事项是很有必要的. 参照Linux_C_HS.chm的目录,我大致将常用的函数分为一下几类: 1. 内存及字符串控制及操作 2. ...

  6. 2017.7.18 linux下用户、组和文件的操作

    参考来自:<鸟叔的linux私房菜(基础学习篇)-第14章> 0 目的 在linux下搭建ELK环境时,因为elasticsearch不能在root下操作,所以要为其新增一个用户,以及随之 ...

  7. Linux下Maven私服Nexus3.x环境构建操作记录

    原文地址:https://blog.csdn.net/liupeifeng3514/article/details/79553747 私服介绍 私服是指私有服务器,是架设在局域网的一种特殊的远程仓库, ...

  8. Ubuntu/Linux 下pdf阅读器Zathura(类vim操作)

    Ubuntu下源安装: sudo apt-get install zathura 操作总结: 基本操作与vim一致,对于熟悉vim快捷键的十分方便: 向下移动一页是J(Ctrl+f),向上移动一页是K ...

  9. linux下MMC/SD/SDIO驱动系列之二 ---- host注册过程(一)

    参考了 http://blog.csdn.net/xieweihua2012/article/details/12844733 在他的基础上更详细的解析源 ...................... ...

随机推荐

  1. 判断是否为SIM卡联系人

    判断是否为SIM卡联系人 在AsyncQueryContacts类中. private List<TxrjAccount> accounts = new ArrayList<Txrj ...

  2. 【laravel54】详解中间件

    1.中间件定义:对http请求进行一层过滤,通过过滤才能继续执行请求 2.中间件方法handle方法参数详解: 其中参数的形式可以有多个,使用[,]进行分割. 3.路由中使用中间件: 3.1 中间件使 ...

  3. leetcode185 Department Top Three Salaries

    Employee表存储员工姓名.员工所在公寓.员工工资 Department表存储公寓id 评选出各个公寓的工资前三名的员工. 遇到的问题如下: limit,in等语句不能用在嵌套select语句中, ...

  4. 直线的中点Bresenham算法的实现

    一.实验目的 1.掌握在MFC中搭建图形绘制的基本框架的方法: 2.将直线的中点Bresenham算法转化成可执行代码. 二.实验内容 1. 通过分析具体数据在中点Bresenham算法上的执行过程, ...

  5. 百度UEditor富文本编辑器去除过滤div等标签

    将设计排版好的页面html代码上传到数据库,再读取出来的时候发现所有的div都被替换成了p标签. 解决方法: 首先在ueditor.all.js文件内搜索allowDivTransToP,找到如下的代 ...

  6. python练习笔记——丑数的计算

    只包含因子2,3,5的正整数被称作丑数,比如4,10,12都是丑数,而7,23,111则不是丑数,另外1也不是丑数.——摘自百度百科 get_num = int(input("请您输入丑数的 ...

  7. PO_PO接受入库时的接受方式详解(概念)

    2014-06-03 Created By BaoXinjian

  8. PLSQL_统计信息系列03_统计信息的收集

    20150506 Created By Baoxinjian

  9. struts2 ValueStack详解,页面获取值el表达式、ognl表达式

    http://www.blogjava.net/max/archive/2007/04/28/114417.html 我想用的是el表达式! http://www.cnblogs.com/belief ...

  10. js下拉框二级关联菜单效果代码具体实现

    这篇文章介绍了js下拉框二级关联菜单效果代码具体实现,有需要的朋友可以参考一下 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transit ...