Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1159636
  • 博文数量: 241
  • 博客积分: 10
  • 博客等级: 民兵
  • 技术积分: 2279
  • 用 户 组: 普通用户
  • 注册时间: 2012-11-27 19:53
个人简介

JustForFun

文章分类

全部博文(241)

文章存档

2023年(8)

2022年(2)

2021年(3)

2020年(30)

2019年(11)

2018年(27)

2017年(54)

2016年(83)

2015年(23)

我的朋友
最近访客

分类: LINUX

2016-11-07 15:12:21

参考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 *);
};
///////////////////////////////////////////////////////


















阅读(1370) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~