sd卡驱动在linux 2.6.24上的实现简易心得 及 好的url地址

89 篇文章 0 订阅
51 篇文章 0 订阅

整理sd卡驱动在linux 2.6.24上的实现简易心得

1.mmc_rescan    当GPIO8发生sd卡插入动作后,进入pxamci_detect_irq()中断,进而触发mmc_rescan检卡work queue工作队列

2.对于sdio设备  host->bus_ops = mmc_sdio_ops;
  对于sd设备    host->bus_ops = mmc_sd_ops;
  对于mmc设备   host->bus_ops = mmc_ops;
  如果检测到插入sd口的设备不是上述3种设备,那么这次mmc_rescan将不能建立任何设备,关闭sd口电源,之后退出.

如果检测到的是sdio设备,那么card将被放到mmc_bus_type总线,同时sdio_funcs会被放到sdio_bus_type总线上,去匹配sido_func驱动
如果检测到的是sd设备,那么card将被放到mmc_bus_type总线,去匹配mmc_bus_type总线上的mmc驱动
如果检测到的是mmc设备,那么card也和sd设备一样将被放到mmc_bus_type总线上.

只有host不会挂载到总线上,插入的sd设备是一定会被登记到mmc_bus_type总线上,如果是sdio设备,那么同时sdio设备的sdio_funcs会被放到sdio_bus_type总线上,去匹配sido_func驱动

3.当host发送完数据之后,命令完成之后,以及sdio_int中断上来之后,cpu会触发pxamci_irq,去集中处理

4.对于主host控制器的同一读写函数为
  mmc_host->ops = pxamci_ops
 
  static const struct mmc_host_ops pxamci_ops = {
    .request        = pxamci_request,
    .get_ro            = pxamci_get_ro,
    .set_ios        = pxamci_set_ios,
    .enable_sdio_irq= pxamci_enable_sdio_irq,
  };

ps:
因为mmc主控制器只有一个,被众多驱动和设备共享,同时对于同一设备,因为数据发送是异步进行的,所以当前如果需要发送数据,那么之前的数据可能因为还没有发送完成,而仍然占用着mmc主控制器的物理寄存器,所以为了保证对物理设备的唯一共享,不扰乱物理通道上的数据序列,驱动中使用 mmc_claim_host(host);来得知,当前mmc控制器是否被占用,当前mmc控制器如果被占用,那么host->claimed = 1;否则为0,如果为1,那么会在for(;;)循环中调用schedule切换出自己,当占用mmc控制器的操作完成之后,执行 mmc_release_host()的时候,会激活登记到等待队列&host->wq中的其他程序获得mmc主控制器的物理使用权 [gliethttp_20080630].
ps1:
不过在pxamci_irq实际中断处理过程中,也就是cmd,data等传输完毕之后,都是会调用pxamci_finish_request()来wake_up唤醒阻塞等待的mmc_wait_done()回调函数,这也是命令执行函数mmc_wait_for_cmd()使用的阻塞等待当前命令结束的方法,之所以这样,是因为有些操作需要驱动去直接操作mmc控制器的寄存器,如果不这样作,就有可能和正在传输中的data中断发生数据和cmd等的命令冲突,这样就使得mmc主控制器上的数据发生混乱,这是绝对不允许的,所以就只能使用这种阻塞方式,来一个一个的完成操作,肯定是不能并行的搞[gliethttp_20080630].

 

 

/

发现了两篇讲SD/MMC卡驱动的文章,觉得不错,转了过来,谢谢原作者
文一:FROM:http://blog.chinaunix.net/u2/69999/showart_734099.html

 关于linux 2.6 mmc/sd驱动   

 linux 2.6 中的mmc/sd驱动分为以下几方面的内容       

1. sysfs 层的总线类型处理: 注册一组 mmc 类型处理函数, 标志为 "mmc"   

   具体在mmc_sysfs.c文件中实现
 

2. mmc/sd 快设备管理:注册一个块设备和一组 mmc 总线类型的 driver 子函数, 实现块设备的队列管理等     

drivers/mmc/mmc_block.c

3. mmc/sd host管理: 实现 host 的管理

. drivers/mmc/mmc.c:主要的 MMC command 與 protocol 實作。
4. 针对特定的mcu实现一个host驱动实例:主要是注册一个 host实体,中断处理函数,io设置函数,请求处理函数等   

       以上1.2.3基本是不需要修改的,需要处理的就是 4.要做的工作.当有卡插入时,由4中实现的插卡中断激活卡初始化程序和总线探测函数. 由mmc总线探测函数会调用块设备的探测函数,在卡设备探测函数中会初始化块设备的请求队列和注册一个gendisk实体(以后文件系统会通过 gendisk实体访问 mmc 块设备),同时在sysfs中建立真正的 mmc/sd 设备.块设备通过具体的 host 注册的io设置函数和请求函数与具体的host通讯.

后面的文章将具体对几个部分进行分析
-----------------------------------------------------------------------------
文二:
FROM:http://blog.chinaunix.net/u1/42456/showart_516030.html


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

原文地址:http://linux4u.wikidot.com/mmc-controller-driver

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

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.cstatic 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.cstatic 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.cstatic 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都不能通过,那这张卡恐怕就是无效卡了,初始化失败。

 

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/unbutun/archive/2009/03/26/4027289.aspx

 

 

 

 

好的url:

http://apps.hi.baidu.com/share/detail/5738180
http://edu.codepub.com/2010/0611/23407_7.php
http://blog.chinaunix.net/u3/110130/showart_2147127.html
http://www.china-cto.cn/cu/44438s.html
http://cjc.javaeye.com/blog/404754
http://herbertbt.blog.163.com/blog/static/5726658220097113421582/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值