第一次写这方面的文章,也不怎么会写吧!之前一直在学习uboot代码,其实提到设备驱动就不得不提到内核机制,所以学习驱动必须学习内核机制,希望和所有初学者一起学习、交流!
我主要从事eMMC/SD卡设备驱动的开发,提起SD卡大家都知道就是手机里面的那张小存储卡,而emmc可能就不太清楚了,其实用过手机或平板的都知道,厂商经常会说自己的ROM 16G、32G等,其实这个ROM已经不是当初的概念了,现在这个ROM是用nandflash或者emmc代替,emmc比nandflash的传输速度更快,底层的开发更加方便,不用考虑nandflash的坏块处理。所以大家买手机或者平板是可关注下ROM用的是什么芯片。
SD卡和emmc的接口和传输协议都类似,所以它们代码都放在/common/drive/mmc/文件夹下,按照驱动的架构分为三层分别存放在三个文件夹下面/mmc/card,/mmc/core,/mmc/host 三个文件夹下,接下来我主要分析下emmc/sd卡的驱动框架结构,具体代码有待继续学习。
emmc/sd都属于块设备驱动,而块设备驱动是内核驱动中最难的一种,下面是一个典型的块设备驱动的架构,它包括了应用层、内核驱动、硬件三层。
按照这个框架来实现emmc/sd卡的驱动模型,主要是实现其中的内核空间和硬件层。
其实理解驱动框架,主要是理解各个层之间是如何进行通讯的。下面就此分析其中的通讯机制。
(1)Host层
Host层主要是对主机控制器进行描述, 这里以我们公司的xxx_sdio.c为例子进行分析,我们先采用 static int xxx_sdio_probe(struct platform_device *pdev)注册了一个平台设备,接下来重点关注probe函 数。在这个函数中,host层与core层的联系是通过下面三句实现的。首先分配一个mmc_host结构体,接下来对操作该结构体的函数赋值mmc->ops,待会我一一介绍。中间还对mmc结构的很多成员进行了赋值,最后将mmc结构加入到mmc子系统,mmc_alloc_host,以及mmc_add_host 的具体做了什么事情,以后我们具体分析,这三句是些mmc层驱动必须包含的。
mmc = mmc_alloc_host(sizeof(struct xxxsd_platform), &pdev->dev);
mmc->ops = &xxx_sdio_ops;
……………
xxxmci_ops 中包含了四个函数:
static struct mmc_host_ops xxxmci_ops = {
.request = xxxmci_request,
.set_ios = xxxmci_set_ios,
.get_ro = xxxmci_get_ro,
.get_cd = xxxmci_card_present,
};
我们 从简单的开始分析,这些函数都会在core部分被调用:
xxxmci_get_ro:这个函数通过从GPIO读取,来判断我们的卡是否是写保护的
xxxmci_card_present: 这个函数通过从GPIO读取来判断卡是否存在
xxxmci_set_ios:s3cmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
依据核心层传递过来的ios,来设置硬件IO,包括引脚配置,使能时钟,和配置总线带宽。
xxxmci_request: 这个函数是最主要,也最复杂的函数,实现了命令和数据的发送和接收,
当core部分需要发送命令或者传输数据时,都会调用这个函数,并传递mrq 请求。
void xxx_sdio_request(struct mmc_host *mmc, struct mmc_request *mrq);
(2)core层
CORE层完成了不同协议和规范的实现,并为HOST层的驱动提供了接口函数,在HOST层我们曾经调用的两个函数:
mmc_alloc_host(sizeof(struct xxxmci_host), &pdev->dev);
mmc_add_host(mmc );
我 们就从这两个函数入手,来分析CORE层与HOST层是如何交互的。
它们的作用主要是扫描和初始化SD卡和emmc,并将其添加到系统设备模型中。其具体的代码将在以后的文章中具体分析。
(3)CARD层
因为SD卡和emmc都是块设备,当然需要提供块设备的驱动程序,这部分就是实现了将SD卡和emmc如何实现为块设备的。这些代码都在CARD文件夹下的block.c文件中。它主要实现了建立设备节点,通过请求队列机制进行数据传输。
每层都会涉及到内核机制中的很多东西,在以后的文章中会对每一个函数进行分析。理解的东西不多,还需继续努力!