linux2.6.28块设备mmc_sd卡mmc子系统核心初始化

参考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 *);
    };
    ///
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

xx-xx-xxx-xxx

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值