参考
http://blog.csdn.net/wavemcu/article/details/7366852
//////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////
MMC/SD设备驱动代码在Linux源码中的位置/linux-2.6.35.4/drivers/mmc/,分别有card、core和host三个文件夹,他们都是MMC/SD卡的驱动。在实际驱动开发中,只需要在host文件夹下实现你具体的MMC/SD设备驱动部分代码,也就是控制器(支持对MMC/SD卡的控制,俗称MMC/SD主机控制器)和SDI控制器与MMC/SD卡的硬件接口电路。
四.中SD/MMC设备驱动流程
4.1.MMC子系统的基本框架
4.1.1.MMC子系统的代码在kernel/driver/MMC下面,目前MMC子系统支持一些形式的记忆卡:SD,SDIO,MMC。
4.1.2.HOST:针对不同主机的驱动程序,这一部分需要根据自己的特定平台来完成。
4.1.3.CORE:这是整个MMC的核心层,这部分完成了不同协议和规范的实现,并且为HOST层的驱动提供接口函数。
4.1.4.CARD:因为这些记忆卡都是块设备,当然需要提供块设备的驱动程序,这部分就是实现了将SD卡如何实现为块设备的。
drivers/mmc/core/core.c
//子系统初始化
subsys_initcall(mmc_init);
module_exit(mmc_exit);
//drivers/mmc/core/core.c
static void __exit mmc_exit(void)
{
sdio_unregister_bus();
mmc_unregister_host_class();
mmc_unregister_bus();
destroy_workqueue(workqueue);
}
////drivers/mmc/core/core.c
static int __init
mmc_init(void)
{
int ret;
//用于创建workqueue,只创建一个内核线程的工作队列
workqueue = create_singlethread_workqueue("kmmcd");
if (!workqueue)
return -ENOMEM;
//总线类型 mmc_bus_type注册(SD/MMC)
ret = mmc_register_bus();////注册总线
if (ret)
goto destroy_workqueue;
////为控制器设备注册一个类mmc_host_class
ret = mmc_register_host_class();
if (ret)
goto unregister_bus;
//总线类型 sdio_bus_type注册(SDIO)
ret = sdio_register_bus();
if (ret)
goto unregister_host_class;
return 0;
unregister_host_class:
mmc_unregister_host_class();
unregister_bus:
mmc_unregister_bus();
destroy_workqueue:
destroy_workqueue(workqueue);
return ret;
}
////drivers/mmc/core/bus.c
int mmc_register_bus(void)
{
//总线类型 mmc_bus_type注册(SD/MMC)
return bus_register(&mmc_bus_type);
}
/////
drivers/mmc/core/bus.c
static struct bus_type mmc_bus_type = {
.name = "mmc",
.dev_attrs = mmc_dev_attrs,
.match = mmc_bus_match,
.uevent = mmc_bus_uevent,
.probe = mmc_bus_probe,
.remove = mmc_bus_remove,
.suspend = mmc_bus_suspend,
.resume = mmc_bus_resume,
};
/////////
////////////////////////////////////
static ssize_t mmc_type_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct mmc_card *card = dev_to_mmc_card(dev);
//看看是如何区分出是MMC,SD,SDIO卡的。
switch (card->type) {
case MMC_TYPE_MMC:
return sprintf(buf, "MMC\n");
case MMC_TYPE_SD:
return sprintf(buf, "SD\n");
case MMC_TYPE_SDIO:
return sprintf(buf, "SDIO\n");
default:
return -EFAULT;
}
}
//static struct bus_type mmc_bus_type里的 .dev_attrs = mmc_dev_attrs,
static struct device_attribute mmc_dev_attrs[] = {
__ATTR(type, S_IRUGO, mmc_type_show, NULL),
__ATTR_NULL,
};
//////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
mmc_host_class
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
driver/mmc/core/host.c
int mmc_register_host_class(void)
{
return class_register(&mmc_host_class);
}
//
static struct class mmc_host_class = {
.name = "mmc_host",
.dev_release = mmc_host_classdev_release,
};
//driver/mmc/core/host.c
static void mmc_host_classdev_release(struct device *dev)
{
struct mmc_host *host = cls_dev_to_mmc_host(dev);
kfree(host);
}
//
#define cls_dev_to_mmc_host(d) container_of(d, struct mmc_host, class_dev)
//
include/linux/mmc/host.h
struct mmc_host {
struct device *parent;
struct device class_dev;
int index;
const struct mmc_host_ops *ops;
unsigned int f_min;
unsigned int f_max;
u32 ocr_avail;
#define MMC_VDD_165_195 0x00000080 /* VDD voltage 1.65 - 1.95 */
#define MMC_VDD_20_21 0x00000100 /* VDD voltage 2.0 ~ 2.1 */
#define MMC_VDD_21_22 0x00000200 /* VDD voltage 2.1 ~ 2.2 */
#define MMC_VDD_22_23 0x00000400 /* VDD voltage 2.2 ~ 2.3 */
#define MMC_VDD_23_24 0x00000800 /* VDD voltage 2.3 ~ 2.4 */
#define MMC_VDD_24_25 0x00001000 /* VDD voltage 2.4 ~ 2.5 */
#define MMC_VDD_25_26 0x00002000 /* VDD voltage 2.5 ~ 2.6 */
#define MMC_VDD_26_27 0x00004000 /* VDD voltage 2.6 ~ 2.7 */
#define MMC_VDD_27_28 0x00008000 /* VDD voltage 2.7 ~ 2.8 */
#define MMC_VDD_28_29 0x00010000 /* VDD voltage 2.8 ~ 2.9 */
#define MMC_VDD_29_30 0x00020000 /* VDD voltage 2.9 ~ 3.0 */
#define MMC_VDD_30_31 0x00040000 /* VDD voltage 3.0 ~ 3.1 */
#define MMC_VDD_31_32 0x00080000 /* VDD voltage 3.1 ~ 3.2 */
#define MMC_VDD_32_33 0x00100000 /* VDD voltage 3.2 ~ 3.3 */
#define MMC_VDD_33_34 0x00200000 /* VDD voltage 3.3 ~ 3.4 */
#define MMC_VDD_34_35 0x00400000 /* VDD voltage 3.4 ~ 3.5 */
#define MMC_VDD_35_36 0x00800000 /* VDD voltage 3.5 ~ 3.6 */
unsigned long caps; /* Host capabilities */
#define MMC_CAP_4_BIT_DATA (1 << 0) /* Can the host do 4 bit transfers */
#define MMC_CAP_MMC_HIGHSPEED (1 << 1) /* Can do MMC high-speed timing */
#define MMC_CAP_SD_HIGHSPEED (1 << 2) /* Can do SD high-speed timing */
#define MMC_CAP_SDIO_IRQ (1 << 3) /* Can signal pending SDIO IRQs */
#define MMC_CAP_SPI (1 << 4) /* Talks only SPI protocols */
#define MMC_CAP_NEEDS_POLL (1 << 5) /* Needs polling for card-detection */
#define MMC_CAP_8_BIT_DATA (1 << 6) /* Can the host do 8 bit transfers */
#define MMC_CAP_ON_BOARD (1 << 7) /* Do not need to rescan after bootup */
#define MMC_CAP_BOOT_ONTHEFLY (1 << 8) /* Can detect device at boot time */
/* host specific block data */
unsigned int max_seg_size; /* see blk_queue_max_segment_size */
unsigned short max_hw_segs; /* see blk_queue_max_hw_segments */
unsigned short max_phys_segs; /* see blk_queue_max_phys_segments */
unsigned short unused;
unsigned int max_req_size; /* maximum number of bytes in one req */
unsigned int max_blk_size; /* maximum size of one mmc block */
unsigned int max_blk_count; /* maximum number of blocks in one req */
/* private data */
spinlock_t lock; /* lock for claim and bus ops */
struct mmc_ios ios; /* current io bus settings */
u32 ocr; /* the current OCR setting */
/* group bitfields together to minimize padding */
unsigned int use_spi_crc:1;
unsigned int claimed:1; /* host exclusively claimed */
unsigned int bus_dead:1; /* bus has been released */
#ifdef CONFIG_MMC_DEBUG
unsigned int removed:1; /* host is being removed */
#endif
struct mmc_card *card; /* device attached to this host */
wait_queue_head_t wq;
struct delayed_work detect;
const struct mmc_bus_ops *bus_ops; /* current bus driver */
unsigned int bus_refs; /* reference counter */
unsigned int sdio_irqs;
struct task_struct *sdio_irq_thread;
atomic_t sdio_irq_thread_abort;
#ifdef CONFIG_LEDS_TRIGGERS
struct led_trigger *led; /* activity led */
#endif
struct dentry *debugfs_root;
unsigned long private[0] ____cacheline_aligned;
};
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
end mmc_host_class
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
sdio_bus_type
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
drivers/mmc/core/sdio_bus.c
int sdio_register_bus(void)
{
//总线类型 sdio_bus_type注册(SDIO)
return bus_register(&sdio_bus_type);
}
//drivers/mmc/core/sdio_bus.c
static struct bus_type sdio_bus_type = {
.name = "sdio",
.dev_attrs = sdio_dev_attrs,
.match = sdio_bus_match,
.uevent = sdio_bus_uevent,
.probe = sdio_bus_probe,
.remove = sdio_bus_remove,
};
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
end sdio_bus_type
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
本结构表述一张MMC卡
/*
* MMC device
*/
struct
mmc_card {
//隶属的mmc控制器
struct mmc_host *host; /* the host this device belongs to */
//当前设备
struct device dev; /* the device */
//卡地址
unsigned int rca; /* relative card address of device */
//卡类型
unsigned int type; /* card type */
#define MMC_TYPE_MMC 0 /* MMC card */
#define MMC_TYPE_SD 1 /* SD card */
#define MMC_TYPE_SDIO 2 /* SDIO card */
//卡状态
unsigned int state; /* (our) card state */
#define MMC_STATE_PRESENT (1<<0) /* present in sysfs */
#define MMC_STATE_READONLY (1<<1) /* card is read-only */
#define MMC_STATE_HIGHSPEED (1<<2) /* card is in high speed mode */
#define MMC_STATE_BLOCKADDR (1<<3) /* card uses block-addressing */
//卡CID 未解码
u32 raw_cid[4]; /* raw card CID */
//卡CSD 未解码
u32 raw_csd[4]; /* raw card CSD */
//卡SCR 未解码
u32 raw_scr[2]; /* raw card SCR */
//卡 身份 已解码
struct mmc_cid cid; /* card identification */
//卡的特殊数据 已解码
struct mmc_csd csd; /* card specific */
struct mmc_ext_csd ext_csd; /* mmc v4 extended card specific */
//额外的SD卡数据 已解码
struct sd_scr scr; /* extra SD information */
struct sd_switch_caps sw_caps; /* switch (CMD6) caps */
unsigned int sdio_funcs; /* number of SDIO functions */
struct sdio_cccr cccr; /* common card info */
struct sdio_cis cis; /* common tuple info */
struct sdio_func *sdio_func[SDIO_MAX_FUNCS]; /* SDIO functions (devices) */
unsigned num_info; /* number of info strings */
const char **info; /* info strings */
struct sdio_func_tuple *tuples; /* unknown common tuples */
struct dentry *debugfs_root;
};
/////////////////////////////////////////////////////
/*
* MMC device driver (e.g., Flash card, I/O card...)
*/
struct mmc_driver {
struct device_driver drv;
int (*probe)(struct mmc_card *);
void (*remove)(struct mmc_card *);
int (*suspend)(struct mmc_card *, pm_message_t);
int (*resume)(struct mmc_card *);
};
///////////////////////////////////////////////////////