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

参考http://blog.csdn.net/wavemcu/article/details/7366852

//

ff510e5ad91ee0a8b30985b1cdc4e685.png

/

2bf53f6f8656dffc35b8bf76a86d09a0.png

///

7fa8282455787e1d1e1887015a2b095c.png

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

staticstruct bus_typemmc_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 *);

};

///

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值