SDIO驱动的命令从何玩起?
2016-01-26 19:01
309 查看
SDIO 卡
SDIO 卡是在 SD 内存卡接口的基础上发展起来的接口, SDIO 接口兼容以前的 SD 内存卡,并且可以连接 SDIO 接口的设备,目前根据 SDIO 协议的 SPEC , SDIO 接口支持的设备总类有蓝牙,网卡,电视卡等。
SDIO 协议是由 SD 卡的协议演化升级而来的,很多地方保留了 SD 卡的读写协议,同时 SDIO 协议又在 SD 卡协议之上添加了 CMD52 和 CMD53 命令。由于这个, SDIO 和 SD 卡规范间的一个重要区别是增加了低速标准,低速卡的目标应用是以最小的硬件开始来支持低速 I/O 能力。低速卡支持类似调制解调器 , 条形码扫描仪和 GPS 接收器等应用。高速卡支持网卡,电视卡还有“组合”卡等,组合卡指的是存储器 +SDIO 。
SDIO 和 SD 卡的 SPEC 间的又一个重要区别是增加了低速标准。 SDIO 卡只需要 SPI 和 1 位 SD 传输模式。低速卡的目标应用是以最小的硬件开支来支持低速 I/O 能力,低速卡支持类似 MODEM ,条形扫描仪和 GPS 接收器等应用。对组合卡来说,全速和 4BIT 操作对卡内存储器和 SDIO 部分都是强制要求的。
在非组合卡的 SDIO 设备里,其最高速度要只有达到 25M ,而组合卡的最高速度同 SD 卡的最高速度一样,要高于25M 。
SDIO 总线
SDIO 总线和 USB 总线类似, SDIO 总线也有两端,其中一端是主机( HOST )端,另一端是设备端( DEVICE ),采用 HOST-
DEVICE 这样的设计是为了简化 DEVICE 的设计,所有的通信都是由 HOST 端发出命令开始的。在 DEVICE 端只要能解溪 HOST 的命令,就可以同 HOST 进行通信了。
SDIO 的 HOST 可以连接多个 DEVICE ,如下图所示 :
这个是同 SD 的总线一样的 , 其中有如下的几种信号
1. CLK 信号 :HOST 给 DEVICE 的时钟信号 .
2. CMD 信号:双向的信号,用于传送命令和反应。
3. DAT0-DAT3 信号 : 四条用于传送的数据线。
4. VDD 信号 : 电源信号。
5. VSS1 , VSS2: 电源地信号。
在 SDIO 总线定义中 ,DAT1 信号线复用为中断线。在 SDIO 的 1BIT 模式下 DAT0 用来传输数据, DAT1 用作中断线。在 SDIO 的 4BIT 模式下 DAT0-DAT3 用来传输数据,其中 DAT1 复用作中断线。
SDIO 命令:
SDIO 总线上都是 HOST 端发起请求,然后 DEVICE 端回应请求。其中请求和回应中会数据信息。
1. Command: 用于开始传输的命令,是由 HOST 端发往 DEVICE 端的。其中命令是通过 CMD 信号线传送的。
2. Response: 回应是 DEVICE 返回的 HOST 的命令,作为 Command 的回应。也是通过
CMD 线传送的。
3. Data: 数据是双向的传送的。可以设置为 1 线模式,也可以设置为 4 线模式。数据是通过 DAT0-DAT3 信号线传输的。
SDIO 的每次操作都是由 HOST 在 CMD 线上发起一个 CMD ,对于有的 CMD , DEVICE 需要返回 Response ,有的则不需要。
对于读命令,首先 HOST 会向 DEVICE 发送命令,紧接着 DEVICE 会返回一个握手信号,此时,当 HOST 收到回应的握手信号后,会将数据放在 4 位的数据线上,在传送数据的同时会跟随着 CRC 校验码。当整个读传送完毕后, HOST 会再次发送一个命令,通知 DEVICE 操作完毕, DEVICE 同时会返回一个响应。
对于写命令,首先 HOST 会向 DEVICE 发送命令,紧接着 DEVICE 会返回一个握手信号,此时,当 HOST 收到回应的握手信号后,会将数据放在 4 位的数据线上,在传送数据的同时会跟随着 CRC 校验码。当整个写传送完毕后, HOST 会再次发送一个命令,通知 DEVICE 操作完毕, DEVICE 同时会返回一个响应。
SDIO 的寄存器:
SDIO 卡的设备驱动 80% 的任务就是操作 SDIO 卡上的有关寄存器。 SDIO 卡最多允许有 7 个功能( function ) ,这个同其功能号是对应的( 0 ~ 7 ) , 每个功能都对应一个 128K 字节大小的寄存器,这个见下面的图。功能号之所以取值范围是 1~7 ,而没有包含 0 ,是因为功能 0 并不代表真正的功能,而代表 CIA 寄存器,即 Common
I/O Area ,这个纪录着 SDIO 卡的一些基本信息和特性,并且可以改写这些寄存器。其中地址 0x1000~0x17fff 是 SDIO 卡的 CIS 区域,就是基本信息区域, Common
Information Structure 。初始化的时候读取并配对 SDIO 设备。
这些寄存器的详细分区已经其对应的功能,在开发过程中都是需要仔细研读的,这些都在协议的 SPEC 中都有详细说明,这里就不在罗索了。
CMD52 命令:
SDIO 设备为了和 SD 内存卡兼容, SD 卡所有 Command 和 Response 完全兼容,同时加入了一些新的 Command 和Response 。例如,初始化 SD 内存卡使用 ACMD41 ,而 SDIO 卡设备则用 CMD5 通知 DEVICE 进行初始化。
但二者最重要的区别是, SDIO 卡比 SD 内存卡多了 CMD52 和 CMD53 命令,这两个命令可以方便的访问某个功能的某个地址寄存器。
CMD52 命令是 IO_RW_DIRECT 命令的简称,其命令格式如下
首先第一位为 0, 表明是起始位,第二位为传输方向,这里为 1 ,代表方向为 HOST 向 DEVICE 设备传送,其后 6 位为命令号,这里是 110100b ,用十进制表示为 52 , CMD52 的名字也由此而来。紧接着是读写标志位。
然后是操作的功能号。也就是 function number 。如果为 0 则指示为 CCCR 寄存器组。
紧接着是寄存器地址,用 17 指示,由于功能寄存器有 128K 地址, 17 位正好能寻址。
再下来 8 位 Write
data or Staff Bits 的意思是说,如果当前为写操作,则为数据,否则 8 位为填充位。无意义。
最后 7 位为 CRC 校验码。最后一位为结束位 0 。
对于 CMD52 的 Response 是 48 位,命令格式如下:
总结下, CMD52 是由 HOST 发往 DEVICE 的,它必须有 DEVICE 返回来的 Response 。 CMD52 不需要占用DAT 线,读写的数据是通过 CMD52 或者 Response 来传送。每次 CMD52 只能读或者写一个 byte .
CMD53 命令:
CMD52 每次只能读写一个字节,因为有了 CMD53 对读写进行了扩展, CMD53 允许每次读写多个字节或者多个块(BLOCK) 。 CMD53 的命令格式如下:
第一位是 1, 为开始位,然后是一位方向位,总是 1 ,代表方向为 HOST 向 DEVICE 设备传送,其后 6 位为命令号,这里是 110101b ,用十进制表示为 53 , CMD53 的名字也由此而来。
然后是 1 位的读写标志。接着是 3 位功能号,这个同 CMD52 都是相同的。 Block Mode 如果 1 代表是块传输模式,否则为字节传输模式。
OP
Code 为操作位,如果是 0 ,代表数据往固定的位置读写,如果 1 代表是地质增量读写。例如,对地址 0 固定读写16 个字节,相当于 16 次读写的地址 0 ,而对地址 0 增量读写 16 个字节,相当于读写 0~15 地址的数据。
然后是 17 位的地址寄存器,可以寻址到 128K 字节的地址,然后是 9 位的读写的计数,对于字节读取,读写大小就是这个计数,而对于块读写,读写的大小是计数乘以块的大小。
随后的 7 位为 CRC 校验码。最后一位为 1 。
当读写操作是块操作的时候,块的大小是可以通过设置 FBR 中的相关寄存器来设置。
同 CMD52 命令不同的是, CMD53 没有返回的命令的,这里判断是否 DEVICE 设备读写完毕是需要驱动里面自己判断的,一般有 2 个方法, 1. 设置相应的读写完毕中断。如果 DEVICE 设备读写完毕,则对 HOST 设备发送中断。 2.HOST 设备主动查询 DEVICE 设备是否读写完毕,可以通过 CMD 命令是否有返回来判断是否 DEVICE 是否读写完毕。
——————————————————————————————————————
了解了SDIO总线命令的基础知识,下面看一个具体的基于s3c2440平台的mmc/sd卡驱动实例,会用到sd卡的命令字,对sdio的命令字道理也是差不多的:
发现了两篇讲SD/MMC卡驱动的文章,觉得不错,转了过来,谢谢原作者
文一:FROM:http://blog.chinaunix.net/u2/69999/showart_734099.html
关于linux 2.6 mmc/sd驱动
linux 2.6 中的mmc/sd驱动分为以下几方面的内容
1. sysfs 层的总线类型处理: 注册一组 mmc 类型处理函数, 标志为 "mmc"
具体在mmc_sysfs.c文件中实现
2. mmc/sd 快设备管理:注册一个块设备和一组 mmc 总线类型的 driver 子函数, 实现块设备的队列管理等
drivers/mmc/mmc_block.c
3. mmc/sd host管理: 实现 host 的管理
. drivers/mmc/mmc.c:主要的 MMC command 與 protocol
實作。
4. 针对特定的mcu实现一个host驱动实例:主要是注册一个 host实体,中断处理函数,io设置函数,请求处理函数等
以上1.2.3基本是不需要修改的,需要处理的就是 4.要做的工作.当有卡插入时,由4中实现的插卡中断激活卡初始化程序和总线探测函数. 由mmc总线探测函数会调用块设备的探测函数,在卡设备探测函数中会初始化块设备的请求队列和注册一个gendisk实体(以后文件系统会通过 gendisk实体访问 mmc 块设备),同时在sysfs中建立真正的 mmc/sd 设备.块设备通过具体的 host 注册的io设置函数和请求函数与具体的host通讯.
后面的文章将具体对几个部分进行分析
-----------------------------------------------------------------------------
文二:
FROM:http://blog.chinaunix.net/u1/42456/showart_516030.html
最近要让s3c2440在linux2.6.18上 支持4G的SD卡.
原文地址:http://linux4u.wikidot.com/mmc-controller-driver
==============================================================
linux-2.6.2x的mmc驱动与linux-2.6.1x的mmc驱动的区别
在linux-2.6.2x中,mmc驱动用到的block_device_operations结构已重新定义,请看:
linux-2.6.1x:
[/code]
linux-2.6.2x
[/code]
注意到新版本的block驱动接口结构增加了gntgeo成员,使调用者可以直接调用此函数获得设备的几何结构。
工作流程:
mmc驱动主要文件包括
drivers/mmc/card/block.c
drivers/mmc/card/queue.c
drivers/mmc/core/core.c
drivers/mmc/core/host.c
drivers/mmc/core/
内核启动时,首先执行core/core.c的mmc_init,注册mmc、sd总线,以及一个host class设备。接着执行card/block.c中,申请一个块设备。
数据结构:
mmc总线操作相关函数,由于mmc卡支持多种总数据线,如SPI、SDIO、8LineMMC,而不同的总线的操作控制方式不尽相同,所以通过此结构与相应的总线回调函数相关联。
[/code]
关于总线操作的函数:
.detect,驱动程序经常需要调用此函数去检测mmc卡的状态,具体实现是发送CMD13命令,并读回响应,如果响应错误,则依次调用.remove、detach_bus来移除卡及释放总线。
总体架构:
kernel启动时,先后执行mmc_init()及mmc_blk_init(),以对mmc设备及mmc块模块进行初始化。
然后在挂载mmc设备驱动时,执行驱动程序中的xx_mmc_probe(),检测host设备中挂载的sd设备。此时probe函数会创建一个host设备,然后开启一个延时任务mmc_rescan()。
驱动挂载成功后,mmc_rescan()函数被执行,然后对卡进行初始化(步骤后面详细讲述)。
假如扫描到总线上挂有有效的设备,就调用相对应的函数把设备装到系统中,mmc_attach_sdio()、mmc_attach_sd()、mmc_attach_mmc()这三个函数分别是装载sdio设备,sd卡和mmc卡的。
在 sd卡中,驱动循环发送ACMD41、CMD55给卡,读取OCR寄存器,成功后,依次发送CMD2(读CID)、CMD3(得到RCA)、CMD9(读 CSD)、CMD7(选择卡)。后面还有几个命令分别是ACMD41&CMD51,使用CMD6切换一些功能,如切换到高速模式。
经过上述步骤,已经确定当前插入的卡是一张有效、可识别的存储卡。然后调用mmc_add_card()把存储卡加到系统中。正式与系统驱动连接在一起。
卡设备加到系统中后,通知mmc块设备驱动。块设备驱动此时调用probe函数,即mmc_blk_probe()函数,mmc_blk_probe()首先分配一个新的mmc_blk_data结构变量,然后调用mmc_init_queue,初始化blk队列。然后建立一个线程 mmc_queue_thread()。
mmc_rescan:mmc_rescan()函数是在驱动装载的时候,由驱动xx_mmc_probe()调用 mmc_alloc_host()时启动的一个延时任务。 xx_mmc_probe()->mmc_alloc_host()->INIT_DELAYED_WORK(&host->detect, mmc_rescan);
当
core部分
1、取得总线
2、检查总线操作结构指针bus_ops,如果为空,则重新利用各总线对端口进行扫描,检测顺序依次为:SDIO、Normal SD、MMC。当检测到相应的卡类型后,就使用mmc_attach_bus()把相对应的总线操作与host连接起来。
[/code]
3、初始化卡接以下流程初始化:
a、发送CMD0使卡进入IDLE状态
b、发送CMD8,检查卡是否SD2.0。SD1.1是不支持CMD8的,因此在SD2.0 Spec中提出了先发送CMD8,如响应为无效命令,则卡为SD1.1,否则就是SD2.0(请参考SD2.0 Spec)。
c、发送CMD5读取OCR寄存器。
d、发送ACMD55、CMD41,使卡进入工作状态。MMC卡并不支持ACMD55、CMD41,如果这步通过了,则证明这张卡是SD卡。
e、如果d步骤错误,则发送CMD1判断卡是否为MMC。SD卡不支持CMD1,而MMC卡支持,这就是SD和MMC类型的判断依据。
f、如果ACMD41和CMD1都不能通过,那这张卡恐怕就是无效卡了,初始化失败。
SDIO 卡是在 SD 内存卡接口的基础上发展起来的接口, SDIO 接口兼容以前的 SD 内存卡,并且可以连接 SDIO 接口的设备,目前根据 SDIO 协议的 SPEC , SDIO 接口支持的设备总类有蓝牙,网卡,电视卡等。
SDIO 协议是由 SD 卡的协议演化升级而来的,很多地方保留了 SD 卡的读写协议,同时 SDIO 协议又在 SD 卡协议之上添加了 CMD52 和 CMD53 命令。由于这个, SDIO 和 SD 卡规范间的一个重要区别是增加了低速标准,低速卡的目标应用是以最小的硬件开始来支持低速 I/O 能力。低速卡支持类似调制解调器 , 条形码扫描仪和 GPS 接收器等应用。高速卡支持网卡,电视卡还有“组合”卡等,组合卡指的是存储器 +SDIO 。
SDIO 和 SD 卡的 SPEC 间的又一个重要区别是增加了低速标准。 SDIO 卡只需要 SPI 和 1 位 SD 传输模式。低速卡的目标应用是以最小的硬件开支来支持低速 I/O 能力,低速卡支持类似 MODEM ,条形扫描仪和 GPS 接收器等应用。对组合卡来说,全速和 4BIT 操作对卡内存储器和 SDIO 部分都是强制要求的。
在非组合卡的 SDIO 设备里,其最高速度要只有达到 25M ,而组合卡的最高速度同 SD 卡的最高速度一样,要高于25M 。
SDIO 总线
SDIO 总线和 USB 总线类似, SDIO 总线也有两端,其中一端是主机( HOST )端,另一端是设备端( DEVICE ),采用 HOST-
DEVICE 这样的设计是为了简化 DEVICE 的设计,所有的通信都是由 HOST 端发出命令开始的。在 DEVICE 端只要能解溪 HOST 的命令,就可以同 HOST 进行通信了。
SDIO 的 HOST 可以连接多个 DEVICE ,如下图所示 :
这个是同 SD 的总线一样的 , 其中有如下的几种信号
1. CLK 信号 :HOST 给 DEVICE 的时钟信号 .
2. CMD 信号:双向的信号,用于传送命令和反应。
3. DAT0-DAT3 信号 : 四条用于传送的数据线。
4. VDD 信号 : 电源信号。
5. VSS1 , VSS2: 电源地信号。
在 SDIO 总线定义中 ,DAT1 信号线复用为中断线。在 SDIO 的 1BIT 模式下 DAT0 用来传输数据, DAT1 用作中断线。在 SDIO 的 4BIT 模式下 DAT0-DAT3 用来传输数据,其中 DAT1 复用作中断线。
SDIO 命令:
SDIO 总线上都是 HOST 端发起请求,然后 DEVICE 端回应请求。其中请求和回应中会数据信息。
1. Command: 用于开始传输的命令,是由 HOST 端发往 DEVICE 端的。其中命令是通过 CMD 信号线传送的。
2. Response: 回应是 DEVICE 返回的 HOST 的命令,作为 Command 的回应。也是通过
CMD 线传送的。
3. Data: 数据是双向的传送的。可以设置为 1 线模式,也可以设置为 4 线模式。数据是通过 DAT0-DAT3 信号线传输的。
SDIO 的每次操作都是由 HOST 在 CMD 线上发起一个 CMD ,对于有的 CMD , DEVICE 需要返回 Response ,有的则不需要。
对于读命令,首先 HOST 会向 DEVICE 发送命令,紧接着 DEVICE 会返回一个握手信号,此时,当 HOST 收到回应的握手信号后,会将数据放在 4 位的数据线上,在传送数据的同时会跟随着 CRC 校验码。当整个读传送完毕后, HOST 会再次发送一个命令,通知 DEVICE 操作完毕, DEVICE 同时会返回一个响应。
对于写命令,首先 HOST 会向 DEVICE 发送命令,紧接着 DEVICE 会返回一个握手信号,此时,当 HOST 收到回应的握手信号后,会将数据放在 4 位的数据线上,在传送数据的同时会跟随着 CRC 校验码。当整个写传送完毕后, HOST 会再次发送一个命令,通知 DEVICE 操作完毕, DEVICE 同时会返回一个响应。
SDIO 的寄存器:
SDIO 卡的设备驱动 80% 的任务就是操作 SDIO 卡上的有关寄存器。 SDIO 卡最多允许有 7 个功能( function ) ,这个同其功能号是对应的( 0 ~ 7 ) , 每个功能都对应一个 128K 字节大小的寄存器,这个见下面的图。功能号之所以取值范围是 1~7 ,而没有包含 0 ,是因为功能 0 并不代表真正的功能,而代表 CIA 寄存器,即 Common
I/O Area ,这个纪录着 SDIO 卡的一些基本信息和特性,并且可以改写这些寄存器。其中地址 0x1000~0x17fff 是 SDIO 卡的 CIS 区域,就是基本信息区域, Common
Information Structure 。初始化的时候读取并配对 SDIO 设备。
这些寄存器的详细分区已经其对应的功能,在开发过程中都是需要仔细研读的,这些都在协议的 SPEC 中都有详细说明,这里就不在罗索了。
CMD52 命令:
SDIO 设备为了和 SD 内存卡兼容, SD 卡所有 Command 和 Response 完全兼容,同时加入了一些新的 Command 和Response 。例如,初始化 SD 内存卡使用 ACMD41 ,而 SDIO 卡设备则用 CMD5 通知 DEVICE 进行初始化。
但二者最重要的区别是, SDIO 卡比 SD 内存卡多了 CMD52 和 CMD53 命令,这两个命令可以方便的访问某个功能的某个地址寄存器。
CMD52 命令是 IO_RW_DIRECT 命令的简称,其命令格式如下
首先第一位为 0, 表明是起始位,第二位为传输方向,这里为 1 ,代表方向为 HOST 向 DEVICE 设备传送,其后 6 位为命令号,这里是 110100b ,用十进制表示为 52 , CMD52 的名字也由此而来。紧接着是读写标志位。
然后是操作的功能号。也就是 function number 。如果为 0 则指示为 CCCR 寄存器组。
紧接着是寄存器地址,用 17 指示,由于功能寄存器有 128K 地址, 17 位正好能寻址。
再下来 8 位 Write
data or Staff Bits 的意思是说,如果当前为写操作,则为数据,否则 8 位为填充位。无意义。
最后 7 位为 CRC 校验码。最后一位为结束位 0 。
对于 CMD52 的 Response 是 48 位,命令格式如下:
总结下, CMD52 是由 HOST 发往 DEVICE 的,它必须有 DEVICE 返回来的 Response 。 CMD52 不需要占用DAT 线,读写的数据是通过 CMD52 或者 Response 来传送。每次 CMD52 只能读或者写一个 byte .
CMD53 命令:
CMD52 每次只能读写一个字节,因为有了 CMD53 对读写进行了扩展, CMD53 允许每次读写多个字节或者多个块(BLOCK) 。 CMD53 的命令格式如下:
第一位是 1, 为开始位,然后是一位方向位,总是 1 ,代表方向为 HOST 向 DEVICE 设备传送,其后 6 位为命令号,这里是 110101b ,用十进制表示为 53 , CMD53 的名字也由此而来。
然后是 1 位的读写标志。接着是 3 位功能号,这个同 CMD52 都是相同的。 Block Mode 如果 1 代表是块传输模式,否则为字节传输模式。
OP
Code 为操作位,如果是 0 ,代表数据往固定的位置读写,如果 1 代表是地质增量读写。例如,对地址 0 固定读写16 个字节,相当于 16 次读写的地址 0 ,而对地址 0 增量读写 16 个字节,相当于读写 0~15 地址的数据。
然后是 17 位的地址寄存器,可以寻址到 128K 字节的地址,然后是 9 位的读写的计数,对于字节读取,读写大小就是这个计数,而对于块读写,读写的大小是计数乘以块的大小。
随后的 7 位为 CRC 校验码。最后一位为 1 。
当读写操作是块操作的时候,块的大小是可以通过设置 FBR 中的相关寄存器来设置。
同 CMD52 命令不同的是, CMD53 没有返回的命令的,这里判断是否 DEVICE 设备读写完毕是需要驱动里面自己判断的,一般有 2 个方法, 1. 设置相应的读写完毕中断。如果 DEVICE 设备读写完毕,则对 HOST 设备发送中断。 2.HOST 设备主动查询 DEVICE 设备是否读写完毕,可以通过 CMD 命令是否有返回来判断是否 DEVICE 是否读写完毕。
——————————————————————————————————————
了解了SDIO总线命令的基础知识,下面看一个具体的基于s3c2440平台的mmc/sd卡驱动实例,会用到sd卡的命令字,对sdio的命令字道理也是差不多的:
发现了两篇讲SD/MMC卡驱动的文章,觉得不错,转了过来,谢谢原作者
文一:FROM:http://blog.chinaunix.net/u2/69999/showart_734099.html
关于linux 2.6 mmc/sd驱动
linux 2.6 中的mmc/sd驱动分为以下几方面的内容
1. sysfs 层的总线类型处理: 注册一组 mmc 类型处理函数, 标志为 "mmc"
具体在mmc_sysfs.c文件中实现
2. mmc/sd 快设备管理:注册一个块设备和一组 mmc 总线类型的 driver 子函数, 实现块设备的队列管理等
drivers/mmc/mmc_block.c
3. mmc/sd host管理: 实现 host 的管理
. drivers/mmc/mmc.c:主要的 MMC command 與 protocol
實作。
4. 针对特定的mcu实现一个host驱动实例:主要是注册一个 host实体,中断处理函数,io设置函数,请求处理函数等
以上1.2.3基本是不需要修改的,需要处理的就是 4.要做的工作.当有卡插入时,由4中实现的插卡中断激活卡初始化程序和总线探测函数. 由mmc总线探测函数会调用块设备的探测函数,在卡设备探测函数中会初始化块设备的请求队列和注册一个gendisk实体(以后文件系统会通过 gendisk实体访问 mmc 块设备),同时在sysfs中建立真正的 mmc/sd 设备.块设备通过具体的 host 注册的io设置函数和请求函数与具体的host通讯.
后面的文章将具体对几个部分进行分析
-----------------------------------------------------------------------------
文二:
FROM:http://blog.chinaunix.net/u1/42456/showart_516030.html
最近要让s3c2440在linux2.6.18上 支持4G的SD卡.
原文地址:http://linux4u.wikidot.com/mmc-controller-driver
==============================================================
linux-2.6.2x的mmc驱动与linux-2.6.1x的mmc驱动的区别
在linux-2.6.2x中,mmc驱动用到的block_device_operations结构已重新定义,请看:
linux-2.6.1x:
struct block_device_operations { int (*open) (struct inode *, struct file *); int (*release) (struct inode *, struct file *); int (*ioctl) (struct inode *, struct file *, unsigned, unsigned long); int (*media_changed) (struct gendisk *); int (*revalidate_disk) (struct gendisk *); struct module *owner; };
[/code]
linux-2.6.2x
struct block_device_operations { int (*open) (struct inode *, struct file *); int (*release) (struct inode *, struct file *); int (*ioctl) (struct inode *, struct file *, unsigned, unsigned long); long (*unlocked_ioctl) (struct file *, unsigned, unsigned long); long (*compat_ioctl) (struct file *, unsigned, unsigned long); int (*direct_access) (struct block_device *, sector_t, unsigned long *); int (*media_changed) (struct gendisk *); int (*revalidate_disk) (struct gendisk *); int (*getgeo)(struct block_device *, struct hd_geometry *); struct module *owner; };
[/code]
注意到新版本的block驱动接口结构增加了gntgeo成员,使调用者可以直接调用此函数获得设备的几何结构。
工作流程:
mmc驱动主要文件包括
drivers/mmc/card/block.c
drivers/mmc/card/queue.c
drivers/mmc/core/core.c
drivers/mmc/core/host.c
drivers/mmc/core/
内核启动时,首先执行core/core.c的mmc_init,注册mmc、sd总线,以及一个host class设备。接着执行card/block.c中,申请一个块设备。
数据结构:
mmc总线操作相关函数,由于mmc卡支持多种总数据线,如SPI、SDIO、8LineMMC,而不同的总线的操作控制方式不尽相同,所以通过此结构与相应的总线回调函数相关联。
//总线操作结构 struct mmc_bus_ops { void (*remove)(struct mmc_host *); void (*detect)(struct mmc_host *); int (*sysfs_add)(struct mmc_host *, struct mmc_card *card); void (*sysfs_remove)(struct mmc_host *, struct mmc_card *card); void (*suspend)(struct mmc_host *); void (*resume)(struct mmc_host *); }; // mmc卡的总线操作 core/mmc.c static const struct mmc_bus_ops mmc_ops = { .remove = mmc_remove, .detect = mmc_detect, .sysfs_add = mmc_sysfs_add, .sysfs_remove = mmc_sysfs_remove, .suspend = mmc_suspend, .resume = mmc_resume, }; // sd卡的总线操作 core/sd.c static const struct mmc_bus_ops mmc_sd_ops = { .remove = mmc_sd_remove, .detect = mmc_sd_detect, .sysfs_add = mmc_sd_sysfs_add, .sysfs_remove = mmc_sd_sysfs_remove, .suspend = mmc_sd_suspend, .resume = mmc_sd_resume, }; // sdio的总线操作 core/sdio.c static const struct mmc_bus_ops mmc_sdio_ops = { .remove = mmc_sdio_remove, .detect = mmc_sdio_detect, };
[/code]
关于总线操作的函数:
.detect,驱动程序经常需要调用此函数去检测mmc卡的状态,具体实现是发送CMD13命令,并读回响应,如果响应错误,则依次调用.remove、detach_bus来移除卡及释放总线。
总体架构:
kernel启动时,先后执行mmc_init()及mmc_blk_init(),以对mmc设备及mmc块模块进行初始化。
然后在挂载mmc设备驱动时,执行驱动程序中的xx_mmc_probe(),检测host设备中挂载的sd设备。此时probe函数会创建一个host设备,然后开启一个延时任务mmc_rescan()。
驱动挂载成功后,mmc_rescan()函数被执行,然后对卡进行初始化(步骤后面详细讲述)。
假如扫描到总线上挂有有效的设备,就调用相对应的函数把设备装到系统中,mmc_attach_sdio()、mmc_attach_sd()、mmc_attach_mmc()这三个函数分别是装载sdio设备,sd卡和mmc卡的。
在 sd卡中,驱动循环发送ACMD41、CMD55给卡,读取OCR寄存器,成功后,依次发送CMD2(读CID)、CMD3(得到RCA)、CMD9(读 CSD)、CMD7(选择卡)。后面还有几个命令分别是ACMD41&CMD51,使用CMD6切换一些功能,如切换到高速模式。
经过上述步骤,已经确定当前插入的卡是一张有效、可识别的存储卡。然后调用mmc_add_card()把存储卡加到系统中。正式与系统驱动连接在一起。
卡设备加到系统中后,通知mmc块设备驱动。块设备驱动此时调用probe函数,即mmc_blk_probe()函数,mmc_blk_probe()首先分配一个新的mmc_blk_data结构变量,然后调用mmc_init_queue,初始化blk队列。然后建立一个线程 mmc_queue_thread()。
mmc_rescan:mmc_rescan()函数是在驱动装载的时候,由驱动xx_mmc_probe()调用 mmc_alloc_host()时启动的一个延时任务。 xx_mmc_probe()->mmc_alloc_host()->INIT_DELAYED_WORK(&host->detect, mmc_rescan);
当
core部分
1、取得总线
2、检查总线操作结构指针bus_ops,如果为空,则重新利用各总线对端口进行扫描,检测顺序依次为:SDIO、Normal SD、MMC。当检测到相应的卡类型后,就使用mmc_attach_bus()把相对应的总线操作与host连接起来。
void mmc_attach_bus(struct mmc_host *host, const struct mmc_bus_ops *ops) { ... host->bus_ops = ops; ... }
[/code]
3、初始化卡接以下流程初始化:
a、发送CMD0使卡进入IDLE状态
b、发送CMD8,检查卡是否SD2.0。SD1.1是不支持CMD8的,因此在SD2.0 Spec中提出了先发送CMD8,如响应为无效命令,则卡为SD1.1,否则就是SD2.0(请参考SD2.0 Spec)。
c、发送CMD5读取OCR寄存器。
d、发送ACMD55、CMD41,使卡进入工作状态。MMC卡并不支持ACMD55、CMD41,如果这步通过了,则证明这张卡是SD卡。
e、如果d步骤错误,则发送CMD1判断卡是否为MMC。SD卡不支持CMD1,而MMC卡支持,这就是SD和MMC类型的判断依据。
f、如果ACMD41和CMD1都不能通过,那这张卡恐怕就是无效卡了,初始化失败。
相关文章推荐
- MR-2.输入格式(InputFormat)基本介绍
- 操作注册表的API函数介绍(RegCreateKeyEx:该函数用来创建注册表键,如果该键已经存在,则打开它)
- android多线程断点续传下载
- Codeforces Round #326 (Div. 2) E. Duff in the Army(LCA+倍增法)
- 关于SQL语句的使用心得
- linux下查看路由表、默认路由器
- 数据结构---无重复元素链表的实现
- JavaScript基础
- linux命令(2):df 磁盘占用
- Android的底层库libutils介绍
- 使用lua代码创建文件夹,解压zip文件到指定目录(亲测可用)
- 大话重构连载6:一个真实的谎言
- 学习Slim Framework for PHP v3 (三)
- web项目中文乱码问题实践经验(springmvc +hibernate)
- Spy++的使用方法
- Postgresql通过批处理命令执行sql文件
- 23岁产妇坐月子双腿险被截肢,产后绝对不能做这八件事!
- Use of undeclared identifier 'BMKMapPointMake'错误 (百度地图)
- MR-2.MapReduce序列化&反序列化&MapReduce函数
- Qt之进程间通信(IPC)