Chinaunix首页 | 论坛 | 博客
  • 博客访问: 33246
  • 博文数量: 15
  • 博客积分: 351
  • 博客等级: 一等列兵
  • 技术积分: 105
  • 用 户 组: 普通用户
  • 注册时间: 2010-04-22 12:34
文章分类

全部博文(15)

文章存档

2011年(15)

我的朋友

分类: LINUX

2011-02-16 00:04:33

http://blog.csdn.net/yuanyou/archive/2010/11/08/5996227.aspx

Linux MMC/SD/SDIO体系结构
  1. 有关MMC/SD/SDIO相关的知识这里就不多讲了,请参考相关资料。这里主要涉及Linux下MMC相关内容。
  2. 内核版本(2.6.36)
  3. 首先说一下Linux相关MMC的代码分布,主要有两个目录,一个头文件目录和一个源代码目录。
  4. 分别位置如下:
  5. include/linux/mmc
  6. drivers/mmc
  7. 要阅读MMC相关代码就必须要看这两个目录。在drivers/mmc目录下分别有三个子目录,其将对应接下来要讲的MMC的体系结构。这三个子目录分别为:
  8.  card
  9.  core
  10.  host
  11. 它们的内容后面讲到体系结构时自然就明了了。
  12.  现在来说说MMC的体系结构,其分为三层

  13.         /dev下设备文件访问MMC/SD/SDIO
  14. 用户空间              |
  15. ---------------------|-----------------------------------------------------
  16. 内核空间             \ /
  17.          MMC Card层(对应具体的设备驱动,如MMC/SD卡块设备驱动,SDIO UART)
  18.                      |
  19.                     \ /
  20.           MMC core层(为上次设备驱动实现提供操作接口,和下层host注册提供机制)
  21.                      |
  22.                     \ /
  23.            Host层(具体MMC/SD/SDIO控制器驱动层。如S3C2440 MMC/SD控制器驱动)
  24.                      |
  25.                     \ /
  26. -----------------------------------------------------------------------------
  27.                     硬件层

  28. 对于我们来说,编写MMC/SD卡相关驱动主要涉及的就是Host层,其余层不用考虑。对于SDIO设备除了Host层以外,还有可能要编写MMC Card层的设备驱动。

  29. 编写Host层驱动,主要是填充mmc_host结构体相关内容和实现mmc_host_ops结构体中的函数。最后调用mmc_add_host向 MMC core注册host驱动。可以参考S3C24XX的HOST驱动程序(drivers/mmc/host/s3cmci.c,s3cmci.h),上层 MMC Core主要调用mmc_host_ops中的函数来实现与硬件交互。如下是mmc_host_ops结构体里面的函数:
  30.   struct mmc_host_ops {
  31.     /*使能和禁止HOST控制器*/
  32.     int (*enable)(struct mmc_host *host);
  33.     int (*disable)(struct mmc_host *host, int lazy);
  34.    
  35.         /*这个是关键的函数,所有对MMC/SD的操作,包括发命令和读数据,都通过该接口来实现,所以实现该接口时要处理是命令还是数据操作,另外要考虑是否使用DMA来进行数据传输。*/
  36.     void (*request)(struct mmc_host *host, struct mmc_request *req);

  37.         /*用来设置MMC/SD的时钟,电压等操作*/
  38.     void (*set_ios)(struct mmc_host *host, struct mmc_ios *ios);

  39.         /*检查MMC/SD是否写保护了*/
  40.     int (*get_ro)(struct mmc_host *host);

  41.         /*检查mmc/sd的插入和拔出*/
  42.     int (*get_cd)(struct mmc_host *host);

  43.     void (*enable_sdio_irq)(struct mmc_host *host, int enable);

  44.     /* optional callback for HC quirks */
  45.     void (*init_card)(struct mmc_host *host, struct mmc_card *card);
  46. };


  47. 博客http://blog.chinaunix.net/u3/101649/showart.php?id=2232724对S3C2440的HOST驱动进行了详细的分析。

  48. 接下来说说MMC Core层。
  49. 该层主要实现了几个结构体函数指针,用来构建整个MMC设备驱动模型。它们是:
  50. struct bus_type mmc_bus_type /*mmc总线,用来管理sd/mmc卡设备和驱动*/
  51. struct mmc_bus_ops mmc_ops /*MMC卡总线操作函数,主要是在电源管理方面*/
  52. struct mmc_bus_ops mmc_sd_op /*SD卡总线操作函数,主要是在电源管理方面*/
  53. struct mmc_bus_ops mmc_sdio_ops /*SDIO总线操作函数,主要是在电源管理方面*/
  54. struct bus_type sdio_bus_type /*SDIO另外定义了一条总线*/

  55. core.c文件中实现了几个关键的函数,用来提供给上层MMC Card调用和对SD/MMC卡的侦测函数以及初始化。

  56. 供给上层MMC Card调用主要有:
  57. void mmc_wait_for_req(struct mmc_host *host, struct mmc_request *mrq);
  58. int mmc_wait_for_cmd(struct mmc_host *host, struct mmc_command *cmd, int retries);
  59. mmc card层就是通过这些函数来操作mmc/sd卡。而这些函数最终调用的是mmc_host_ops 结构体中的request函数来进行具体的操作。

  60. 对SD/MMC卡的侦测函数以及初始化,主要实现在
  61. void mmc_rescan(struct work_struct *work)
  62. 函数中。
  63. host层在调用mmc_add_host时会引发该函数的调用,侦测/初始化顺序为:
  64.   先SDIO接口
  65.   /*
  66.      * First we search for SDIO...
  67.      */
  68.     err = mmc_send_io_op_cond(host, 0, &ocr);
  69.     if (!err) {
  70.         if (mmc_attach_sdio(host, ocr)) {
  71.    ...

  72. 在SD:
  73.   /*
  74.      * ...then normal SD...
  75.      */
  76.     err = mmc_send_app_op_cond(host, 0, &ocr);
  77.     if (!err) {
  78.         if (mmc_attach_sd(host, ocr))

  79. 最后是MMC:
  80.  /*
  81.      * ...and finally MMC.
  82.      */
  83.     err = mmc_send_op_cond(host, 0, &ocr);
  84.     if (!err) {
  85.         if (mmc_attach_mmc(host, ocr))

  86. 其中mmc_attach_xxx函数就是用来完成侦测和初始化的,选择相应的总线操作函数,并产生struct mmc_card结构体,并填充其内容,最后注册一个mmc_card(代表着一个设备),并在注册中由mmc_bus_type结构体的match和 probe函数来查找到适合该设备的驱动(这个又牵涉到设备驱动模型,可以查看设备驱动模型相关内容,了解设备和驱动匹配的过程),这里将匹配到mmc card层的MMC_Block(MMC块设备驱动程序,由 struct mmc_driver代表)。在完成设备侦测和初始化以后,以后的操作就是mmc card层中相关的设备驱动程序发出的了。


  87. 再说说MMC card层,该层主要实现具体的设备驱动程序,如MMC块设备驱动程序,通过mmc_register_driver注册。如果是SDIO就有可能是其它字符设备驱动程序了,其通过调用sdio_register_driver来注册设备驱动。

  88. 总体概括来说:
  89. host层提供驱动相关MMC/SD/SDIO控制器的功能。
  90. Core层提供了具体MMC/SD/SDIO设备侦测和初始化功能,以及电源管理方面的内容和通用的操作功能。
  91. Card为实现具体的设备驱动层。
  92. 这样的分层结构在Linux设备驱动中非常常见,如I2C,SPI等都提供了这样的驱动模型。


  93. 最后简单说说SDIO相关部分。在core层注册了新的sdio_bus_type总线,并且定义了新的sdio_driver来代表sdio设备驱动,并定义了struct sdio_func来代表设备。所以在SDIO设备除了struct mmc_card来代表设备以外,还有struct sdio_func来代表具体功能设备。所以在mmc_attach_sdio函数中除了注册mmc_card以外,还注册了sdio_func。具体代码如下:
  94. int mmc_attach_sdio(struct mmc_host *host, u32 ocr)
  95. {
  96.    ....
  97.   /*
  98.      * First add the card to the driver model...
  99.      */
  100.     err = mmc_add_card(host->card);
  101.     if (err)
  102.         goto remove_added;

  103.     /*
  104.      * ...then the SDIO functions.
  105.      */
  106.     for (i = 0;i < funcs;i++) {
  107.         err = sdio_add_func(host->card->sdio_func[i]);
  108.         if (err)
  109.             goto remove_added;
  110.     }
  111.     ....
  112. }
  113. 所以它除了调用mmc_bus_type结构体的match和probe函数来查找到适合该设备的驱动外,也调用sdio_bus_type结构体的match和probe函数来查找到适合该设备的驱动。

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