内容来自以下博客:
http://blog.csdn.net/qianjin0703/article/details/5918041 Linux设备驱动子系统第二弹 - SD卡 (有介绍SD卡硬件)http://blog.csdn.net/wavemcu/article/details/7366852 linux2.6内核SD Card Driver详细解析之一
http://blog.chinaunix.net/uid-147915-id-3063162.html 基于S3C2410的SD卡linux驱动工作原理
http://www.cnblogs.com/autum/archive/2012/08/16/SD.html SD卡驱动分析(一)(系列关于 SD 卡文章)
http://blog.163.com/fenglang_2006/blog/static/133662318201011183912576/ linux sd卡驱动分析,基于mini2440,sdio mmc sd卡驱动编4
一、先来一些简单硬件知识:
MMC:MMC就是 MultiMediaCard 的缩写,即多媒体卡
SD:SD卡为Secure Digital Memory Card, 即安全数码卡,(另TF卡又称microSD)
SDIO:SDIO是在SD标准上定义了一种外设接口
MCI:MCI是Multimedia Card Interface的简称,即多媒体卡接口。上述的MMC,SD,SDI卡定义的接口都属于MCI接口
SD卡引脚:
一根指令线CMD,4根数据线DAT0~DAT3,一个 SDCARD_DET_N 检测引脚
SD卡内部有7个寄存器
OCR,CID,CSD和SCR寄存器保存卡的配置信息
RCA寄存器保存着通信过程中卡当前暂时分配的地址(只适合SD模式)
卡状态(Card Status)和SD状态(SD Status)寄存器保存着卡的状态
OCR寄存器保存着SD/MMC卡的供电电允许范围
CID为一个16个字节的寄存器,该寄存器包含一个独特的卡标识号
CSD寄存器(卡特殊数据寄存器)包含访问卡存储时需要的相关信息
SD卡命令共分为12类,分别为class0到Class11
CMD0:复位SD 卡
CMD1:读OCR寄存器
...
二、好,开始软件部分了。
Linux相关MMC的代码分布,主要有两个目录,一个头文件目录和一个源代码目录
头文件目录:include/linux/mmc
源代码目录:drivers/mmc
mmc驱动共分为三个目录:card/、core/、host/
card:块设备的驱动程序。这部分就是实现了将SD卡如何实现为块设备的
core:总线驱动程序。这是整个MMC的核心层,这部分完成了不同协议和规范的实现,并且为HOST层的驱动提供接口函数
host:通讯接口驱动。针对不同主机的驱动程序,这一部分需要根据自己的特定平台来完成
MMC/SD卡的驱动被分为:卡识别阶段和数据传输阶段
卡识别阶段:空闲(idle)、准备(ready)、识别(ident)、等待(stby)、不活动(ina)
数据传输阶段:发送(data)、传输(tran)、接收(rcv)、程序(prg)、断开连接(dis)
在实际驱动开发中,只需要在host文件夹下实现你具体的MMC/SD设备驱动部分代码,
也就是控制器(支持对MMC/SD卡的控制,俗称MMC/SD主机控制器)和SDI控制器与MMC/SD卡的硬件接口电路
其实SD驱动一共就做了两件事件:
1).卡的检测。(初始化sd卡)
2).卡数据的读取:
写sd卡:POLL、中断、DMA
读sd卡:POLL、中断、DMA
可以从以下几个方面理解驱动:
1、 msm_sdcc.c代码初始化过程;
2、 SD卡块设备注册过程;
3、 request及数据传输的实现
SD 传输模式有以下 3 种:
SPI mode (required )
1-bit mode
4-bit mode
开始上代码
三、重要的结构体
卡控制器
kernel/include/linux/mmc/host.h
struct mmc_host {
const struct mmc_host_ops *ops; // SD卡主控制器的操作函数,即该控制器所具备的驱动能力
struct mmc_ios ios; // 配置时钟、总线、电源、片选、时序等
truct mmc_card *card; // 连接到此主控制器的SD卡设备
const struct mmc_bus_ops *bus_ops; // SD总线驱动的操作函数,即SD总线所具备的驱动能力
...
}
卡控制器操作集
用于从主机控制器向 core 层注册操作函数,从而将core层与具体的主机控制器隔离
也就是说 core 要操作主机控制器,就是这个 ops 当中给的函数指针操作,不能直接调用具体主控制器的函数
struct mmc_host_ops { -----------------非常重要
int (*enable)(struct mmc_host *host); //使能和禁止HOST控制器
int (*disable)(struct mmc_host *host);
void (*request)(struct mmc_host *host, struct mmc_request *req); //核心函数,用于SD卡命令的传输,比如发送和接收命令,CMD0,CMD8,ACMD41诸如此类的都是在这个函数去实现
void (*set_ios)(struct mmc_host *host, struct mmc_ios *ios); //配置时钟、总线、电源、片选、时序等
int (*get_ro)(struct mmc_host *host); //用于检测SD卡的写保护是否打开
int (*get_cd)(struct mmc_host *host); //用于SD卡的检测,是否有卡插入和弹出
void (*enable_sdio_irq)(struct mmc_host *host, int enable); //开启sdio中断
...
}
控制器对卡的I/O状态
struct mmc_ios {
}
描述卡
kernel/include/linux/mmc/card.h
struct mmc_card {
}
读写MMC卡的请求
包括命令,数据以及请求完成后的回调函数
struct mmc_request {
struct mmc_command *sbc; /* SET_BLOCK_COUNT for multiblock */
struct mmc_command *cmd;
struct mmc_data *data;
struct mmc_command *stop;
struct completion completion;
void (*done)(struct mmc_request *);/* completion function */
struct mmc_host *host;
};
MMC卡读写的数据相关信息
如:请求,操作命令,数据以及状态等
struct mmc_data {
}
MMC卡操作相关命令及数据,状态信息等
一条指令command共48位,其中command index指代这条具体的指令名称,argument为该指令的参数
struct mmc_command {
u32 opcode; //对应command index
u32 arg; // 对应argument
u32 resp[4]; // 对应response
...
}
描述mmc卡驱动
struct mmc_driver {
struct device_driver drv;
int (*probe)(struct mmc_card *);
void (*remove)(struct mmc_card *);
int (*su