SDIO驱动的命令从何玩起?

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:

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;
};

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;
};

注意到新版本的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,
};

关于总线操作的函数:
.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;
    ...
}

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都不能通过,那这张卡恐怕就是无效卡了,初始化失败。

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值