Chinaunix首页 | 论坛 | 博客
  • 博客访问: 971878
  • 博文数量: 192
  • 博客积分: 3070
  • 博客等级: 中校
  • 技术积分: 1861
  • 用 户 组: 普通用户
  • 注册时间: 2007-06-27 23:44
个人简介

Start Linux Leave Linux a while Back to Linux

文章分类

全部博文(192)

文章存档

2023年(18)

2022年(11)

2021年(8)

2020年(14)

2019年(7)

2018年(13)

2017年(16)

2016年(4)

2012年(2)

2011年(13)

2010年(26)

2009年(13)

2008年(27)

2007年(20)

我的朋友

分类: LINUX

2008-04-03 10:28:04

最近要让s3c2440在linux2.6.18上 支持4G的SD卡.

原文地址:

==============================================================

linux-2.6.2x的mmc驱动与linux-2.6.1x的mmc驱动的区别
在linux-2.6.2x中,mmc驱动用到的block_device_operations结构已重新定义,请看:
linux-2.6.1x:

struct block_device_operations {
    int (*open) (struct inode *, struct file *);
    int (*release) (struct inode *, struct file *);
    int (*ioctl) (struct inode *, struct file *, unsigned, unsigned long);
    int (*media_changed) (struct gendisk *);
    int (*revalidate_disk) (struct gendisk *);
    struct module *owner;
};

linux-2.6.2x

struct block_device_operations {
    int (*open) (struct inode *, struct file *);
    int (*release) (struct inode *, struct file *);
    int (*ioctl) (struct inode *, struct file *, unsigned, unsigned long);
    long (*unlocked_ioctl) (struct file *, unsigned, unsigned long);
    long (*compat_ioctl) (struct file *, unsigned, unsigned long);
    int (*direct_access) (struct block_device *, sector_t, unsigned long *);
    int (*media_changed) (struct gendisk *);
    int (*revalidate_disk) (struct gendisk *);
    int (*getgeo)(struct block_device *, struct hd_geometry *);
    struct module *owner;
};

注意到新版本的block驱动接口结构增加了gntgeo成员,使调用者可以直接调用此函数获得设备的几何结构。

工作流程:
mmc驱动主要文件包括
drivers/mmc/card/block.c
drivers/mmc/card/queue.c
drivers/mmc/core/core.c
drivers/mmc/core/host.c
drivers/mmc/core/
内核启动时,首先执行core/core.c的mmc_init,注册mmc、sd总线,以及一个host class设备。接着执行card/block.c中,申请一个块设备。

数据结构:
mmc总线操作相关函数,由于mmc卡支持多种总数据线,如SPI、SDIO、8LineMMC,而不同的总线的操作控制方式不尽相同,所以通过此结构与相应的总线回调函数相关联。

//总线操作结构
struct mmc_bus_ops {
    void (*remove)(struct mmc_host *);
    void (*detect)(struct mmc_host *);
    int (*sysfs_add)(struct mmc_host *, struct mmc_card *card);
    void (*sysfs_remove)(struct mmc_host *, struct mmc_card *card);
    void (*suspend)(struct mmc_host *);
    void (*resume)(struct mmc_host *);
};
//  mmc卡的总线操作 core/mmc.c
static const struct mmc_bus_ops mmc_ops = {
    .remove = mmc_remove,
    .detect = mmc_detect,
    .sysfs_add = mmc_sysfs_add,
    .sysfs_remove = mmc_sysfs_remove,
    .suspend = mmc_suspend,
    .resume = mmc_resume,
};
// sd卡的总线操作 core/sd.c
static const struct mmc_bus_ops mmc_sd_ops = {
    .remove = mmc_sd_remove,
    .detect = mmc_sd_detect,
    .sysfs_add = mmc_sd_sysfs_add,
    .sysfs_remove = mmc_sd_sysfs_remove,
    .suspend = mmc_sd_suspend,
    .resume = mmc_sd_resume,
};
// sdio的总线操作 core/sdio.c
static const struct mmc_bus_ops mmc_sdio_ops = {
    .remove = mmc_sdio_remove,
    .detect = mmc_sdio_detect,
};

关于总线操作的函数:
.detect,驱动程序经常需要调用此函数去检测mmc卡的状态,具体实现是发送CMD13命令,并读回响应,如果响应错误,则依次调用.remove、detach_bus来移除卡及释放总线。

总体架构:
kernel启动时,先后执行mmc_init()及mmc_blk_init(),以对mmc设备及mmc块模块进行初始化。
然后在挂载mmc设备驱动时,执行驱动程序中的xx_mmc_probe(),检测host设备中挂载的sd设备。此时probe函数会创建一个host设备,然后开启一个延时任务mmc_rescan()。
驱动挂载成功后,mmc_rescan()函数被执行,然后对卡进行初始化(步骤后面详细讲述)。
假如扫描到总线上挂有有效的设备,就调用相对应的函数把设备装到系统中,mmc_attach_sdio()、mmc_attach_sd()、mmc_attach_mmc()这三个函数分别是装载sdio设备,sd卡和mmc卡的。
在sd卡中,驱动循环发送ACMD41、CMD55给卡,读取OCR寄存器,成功后,依次发送CMD2(读CID)、CMD3(得到RCA)、CMD9(读CSD)、CMD7(选择卡)。后面还有几个命令分别是ACMD41&CMD51,使用CMD6切换一些功能,如切换到高速模式。
经过上述步骤,已经确定当前插入的卡是一张有效、可识别的存储卡。然后调用mmc_add_card()把存储卡加到系统中。正式与系统驱动连接在一起。
卡设备加到系统中后,通知mmc块设备驱动。块设备驱动此时调用probe函数,即mmc_blk_probe()函数,mmc_blk_probe()首先分配一个新的mmc_blk_data结构变量,然后调用mmc_init_queue,初始化blk队列。然后建立一个线程mmc_queue_thread()。
  

mmc_rescan:mmc_rescan()函数是在驱动装载的时候,由驱动xx_mmc_probe()调用mmc_alloc_host()时启动的一个延时任务。xx_mmc_probe()->mmc_alloc_host()->INIT_DELAYED_WORK(&host->detect, mmc_rescan);

core部分
1、取得总线
2、检查总线操作结构指针bus_ops,如果为空,则重新利用各总线对端口进行扫描,检测顺序依次为:SDIO、Normal SD、MMC。当检测到相应的卡类型后,就使用mmc_attach_bus()把相对应的总线操作与host连接起来。

void mmc_attach_bus(struct mmc_host *host, const struct mmc_bus_ops *ops)
{
    ...
    host->bus_ops = ops;
    ...
}

3、初始化卡接以下流程初始化:
a、发送CMD0使卡进入IDLE状态
b、发送CMD8,检查卡是否SD2.0。SD1.1是不支持CMD8的,因此在SD2.0 Spec中提出了先发送CMD8,如响应为无效命令,则卡为SD1.1,否则就是SD2.0(请参考SD2.0 Spec)。
c、发送CMD5读取OCR寄存器。
d、发送ACMD55、CMD41,使卡进入工作状态。MMC卡并不支持ACMD55、CMD41,如果这步通过了,则证明这张卡是SD卡。
e、如果d步骤错误,则发送CMD1判断卡是否为MMC。SD卡不支持CMD1,而MMC卡支持,这就是SD和MMC类型的判断依据。
f、如果ACMD41和CMD1都不能通过,那这张卡恐怕就是无效卡了,初始化失败。

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