基于Linux-3.10.0-229内核的Baytrail eMMC驱动分析之一概述

来源:互联网 发布:淘宝海报怎么放 编辑:程序博客网 时间:2024/06/05 19:32

一、硬件环境

  • Intel Baytrail处理器,自带eMMC-4.5控制器
  • CentOS-7.1-1503-X86_64.iso
  • linux-3.10.0-229.el7.x86_64
  • eMMC存储芯片——KLMxGxGEND-B031(支持eMMC-5.0协议标准)

二、软件环境

1、MMC子系统框架


2、子系统代码结构
  Linux MMC子系统主要分成三个部分:

  • Card:存放闪存卡(块设备)的相关驱动,如MMC/SD卡设备驱动,SDIOUART;
  • Host:针对不同主机端的SDHC、MMC控制器的驱动,这部分需要由驱动工程师来完成;
  • Core:整个MMC的核心层,这部分完成不同协议和规范的实现,为host层和设备驱动层提供接口函数。

 (1)、区块层(Card)
   主要是按照 LINUX 块设备驱动程序的框架实现一个卡的块设备驱动,这block.c当中我们可以看到写一个块 设备驱动程序时需要的block_device_operations结构体变量的定义,其中有open/release/request函数的实现,而queue.c则是对内核提供的请求队列的封装,我们暂时不用深入理解它,只需要知道一个块设备需要一个请求队列就可以了。
 (2)、核心层(Core)
   核心层封装了MMC/SD卡的命令,例如存储卡的识别,设置,读写。例如不管什么卡都应该有一些识别,设置,和读写的命令,这些流程都是必须要有的,只是具体对于不同的卡会有一些各自特有的操作。Core.c文件是由sd.c、 mmc.c两个文件支撑的,core.c把MMC卡、SD卡的共性抽象出来,它们的差别由sd.c和sd_ops.c、mmc.c和mmc_ops.c 来完成。
 (3)、主机控制器层(Host)
   主机控制器则是依赖于不同的平台的,例如Baytrail处理器的eMMC卡控制器和三星的s3c24xx系列的卡控制器必定是不一样的,所以要针对不同的控制器来实现。以s3cmci.c为例,它首先要进行一些设置,例如中断函数注册,全能控制器等等。然后它会向core层注册一个主机(host),用结构mmc_host_ops描述,这样核心层就可以拿着这个host来操作s3c24xx的卡控制器了,而具体是s3c24xx的卡控制器还是Baytrail的卡控制器,core层是不用知道的。

3、结构体描述
   主要包括如下:
  • struct mmc_host 用来描述卡控制器、
  • struct mmc_card 用来描述卡
  • struct mmc_driver 用来描述 mmc 卡驱动
  • struct mmc_host_ops 用来描述卡控制器操作集,用于从主机控制器层向core层注册操作函数,从而将core层与具体的主机控制器隔离。也就是说core要操作主机控制器,就用这个ops当中给的函数指针操作,不能直接调用具体主控制器的函数。
struct mmc_host {
   const struct mmc_host_ops *ops;     // SD卡主控制器的操作函数,即该控制器所具备的驱动能力
   const struct mmc_bus_ops *bus_ops; // SD总线驱动的操作函数,即SD总线所具备的驱动能力
   struct mmc_ios  ios;  // 配置时钟、总线、电源、片选、时序等
   struct mmc_card  *card;  // 连接到此主控制器的SD卡设备
   ... ...
};

struct mmc_host_ops {
    void (*request)(struct mmc_host *host, struct mmc_request *req);  // 核心函数,完成主控制器与SD卡设备之间的数据通信
    void (*set_ios)(struct mmc_host *host, struct mmc_ios *ios);  // 配置时钟、总线、电源、片选、时序等
    int (*get_ro)(struct mmc_host *host); //获取gpio管脚,判断是否是写保护
    void (*enable_sdio_irq)(struct mmc_host *host, int enable); //卡插入与拔出中断
};

struct mmc_bus_ops {
 void (*remove)(struct mmc_host *);    // 拔出SD卡的回调函数
 void (*detect)(struct mmc_host *);      // 探测SD卡是否还在SD总线上的回调函数
 void (*suspend)(struct mmc_host *);
 void (*resume)(struct mmc_host *);
};

struct mmc_card {
 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 */
 unsigned int  state;  /* (our) card state */
 unsigned int  quirks;  /* card quirks */
 u32   raw_cid[4]; /* raw card CID */
 u32   raw_csd[4]; /* raw card CSD */
 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 */
 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 */
   ... ...
};

原创粉丝点击