Linux驱动——mmc概念与框架(一)

2021/10/23 7:10:01

本文主要是介绍Linux驱动——mmc概念与框架(一),对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

Linux驱动——mmc概念与框架(一)

备注:
  1. Kernel版本:5.4
  2. 使用工具:Source Insight 4.0
  3. 参考博客:
Linux MMC framework(1)_软件架构

1. [mmc subsystem] 概念与框架

文章目录

  • Linux驱动——mmc概念与框架(一)
    • 概念
      • mmc的概念
      • mmc设备
      • mmc协议
    • 软件架构
    • sys下的文件节点说明
      • bus节点
      • host的class节点
      • card对应的sys节点
      • debug节点
      • 源码分析

概念

mmc的概念

  mmc有很多种意义,具体如下:

  • mmc
      MultiMedia Card,多媒体存储卡, 但后续泛指一个接口协定(一种卡式),能符合这接口的内存器都可称作mmc储存体。

  

  • 主要特性
      工作电压:高电压为2.7~3.6 V,低电压为1.65~1.95 V,可选。

  

  • mmc总线
      mmc总线是和I2C总线、SPI总线类似的一种总线结构。简化系统结构图如下(也可以理解为硬件框架图):
    在这里插入图片描述

  

  • 硬件特性

  卡与主控制器间串行传送,工作时钟频率范围为0~200 MHz。
  mmc总线上最多可识别64 K个mmc设备,在总线上不超过10个卡时,可运行到最高频率。

mmc设备

  使用mmc接口规范(MCI, Multimedia Card Interface)的设备都可以称之为mmc设备。
  可分成三个种类,如下:

  • mmc type card

(1)标准mmc卡:闪存卡的一种,使用mmc标准。
(2)emmc:Embedded MultiMediaCard,是MMC协会所制定的内嵌式存储器标准规格,带有mmc接口,是具备mmc协议的芯片。

  • sd type card

(1)sd卡:SD卡为Secure Digital Memory Card, 即安全数码卡。它在MMC的基础上发展而来,增加了两个主要特色:SD卡强调数据的安全,可以设定所储存的使用权限,防止数据被他人复制。兼容mmc接口规范。

  • sdio type card

(1)sdio设备:SDIO是在SD标准上定义了一种外设接口,它和SD卡规范间的一个重要区别是增加了低速标准。在SDIO卡只需要SPI和1位SD传输模式。低速卡的目标应用是以最小的硬件开销支持低速IO能力。常见的sdio设备有Wi-Fi card、Bluetooth card等等。

  注意,这几种类型的card统称为mmc card。

mmc协议

  类似i2c协议、spi协议,mmc总线上也有一套自己的通讯规范。通信规范后续在说明。

  而上述mmc设备基于上mmc总线通讯规范上由自身硬件特性设置了自己的一套协议。

  jedec的协议规范可以去jedec的官网上下载。

  • 标准mmc卡协议

<1> mmc4.0
<2> mmc4.1《MultiMediaCard (MMC) Electrical Standard, Standard Capacity (MMCA, 4.1)》

<3>mmc4.2《MultiMediaCard (MMC) Electrical Standard, High Capacity (MMCA, 4.2)》

  • emmc协议(主要区别主要在读写速度上)

<1> emmc4.41《Embedded MultiMediaCard(e•MMC) e•MMC/Card Product Standard, High Capacity, including Reliable Write, Boot, Sleep Modes, Dual Data Rate, Multiple Partitions Supports, Security Enhancement, Background Operation and High Priority Interrupt (MMCA, 4.41)》

<2> emmc4.51《Embedded Multimedia Card (e•MMC), Electrical Standard 4.51》

<3> emmc5.0《Embedded Multi-Media Card (e•MMC) Electrical Standard (5.01)》

<4> emmc5.1《Embedded Multi-Media Card (e•MMC) Electrical Standard (5.1)》

  • sd协议

<1> sd1.0《SD Host Controller Simplified Specification》

<2> sd2.0《SD Host Controller Simplified Specification》

<3> sd3.0《SD Host Controller Simplified Specification》

<4> sdio4.2《SD Host Controller Simplified Specification》

  • sdio协议

<1> sdio1.0《SDIO Simplified Specification》

<2> sdio1.1《SDIO Simplified Specification》

<3> sdio2.0《SDIO Simplified Specification》

<4> sdio3.0《SDIO Simplified Specification》

软件架构

请添加图片描述

  MMC framework分别有“从左到右”和“从下到上”两种层次结构。


  • 1) 从左到右
      MMC协议是一个总线协议,因此包括Host controller、Bus、Card三类实体(从左到右)。相应的,MMC framework抽象出了host、bus、card三个软件实体,以便和硬件一一对应:

  host,负责驱动Host controller,提供诸如访问card的寄存器、检测card的插拔、读写card等操作方法。从设备模型的角度看,host会检测卡的插入,并向bus注册MMC card设备;

  bus,是MMC bus的虚拟抽象,以标准设备模型的方式,收纳MMC card(device)以及对应的MMC driver(driver);

  card,抽象具体的MMC卡,由对应的MMC driver驱动(从这个角度看,可以忽略MMC的技术细节,只需关心一个个具有特定功能的卡设备,如存储卡、WIFI卡、GPS卡等等)。


  • 2)从下到上

  MMC framework从下到上也有3个层次(老生常谈了):

  MMC core位于中间,是MMC framework的核心实现,负责抽象host、bus、card等软件实体,负责向底层提供统一、便利的编写Host controller driver的API;
  MMC host controller driver位于底层,基于MMC core提供的框架,驱动具体的硬件(MMC controller);
  MMC card driver位于最上面,负责驱动MMC core抽象出来的虚拟的card设备,并对接内核其它的framework(例如块设备、TTY、wireless等),实现具体的功能。
  这里补充说明,sdhci并不是实际的host驱动,而是上述说明的sdhc标准的host的驱动部分,如:sdhci-msm和sdhci-s3c都使用了SDHC标准。


  • 3)文件目录结构
      
      Linux kernel把mmc,sd以及sdio三者的驱动代码整合在一起,俗称mmc子系统。源码位于drivers/mmc下。其下有两个子目录,分别是:
    请添加图片描述

core(核心层)
主要子文件:bus.h/.c、core.h/.c、host.h/.c、mmc.c、sdio.c、sd.c、block.c、queue.h、queue.c等。
  作用一:主要是按照 LINUX 块设备驱动程序的框架实现一个卡的块设备驱动;
  作用二:核心层封装了 MMC/SD 卡的命令,例如存储卡的识别,设置,读写;

文件说明:
  block.c: 在 该文件当中我们可以看到写一个块设备驱动程序时需要的 block_device_operations 结构体变量的定义,其中有 open/release/ioctl 函数的实现;

  queue.c :则是对内核提供的请求队列的封装,我们暂时不用深入理解它,只需要知道一个块设备需要一个请求队列就可以了。

  bus:总线相关操作,连接驱动和设备的桥梁;

  core:提供存储卡的相关操作,core.c由 sd.c、mmc.c 两个文件支撑的, core.c 把 MMC 卡、 SD 卡的共性抽象出来,它们的差别由 sd.c 和 sd_ops.c 、 mmc.c 和 mmc_ops.c 来完成。


host(主机控制层)
  主机控制器则是依赖于不同的平台的,例如 s3c2410 的卡控制器和 atmel 的卡控制器必定是不一样的,所以要针对不同的控制器来实现。
  以 s3cmci.c 为例,它首先要进行一些设置,例如中断函数注册,全能控制器等等。然后它会向 core 层注册一个主机( host ),用结构 mmc_host_ops 描述,这样核心层就可以拿着这个 host 来操作 s3c24xx 的卡控制器了,而具体是 s3c24xx 的卡控制器还是 atmel 的卡控制器, core 层是不用知道的。

sys下的文件节点说明

bus节点

mmc bus节点的对应路径为/sys/bus/mmc。在mmc_register_bus中生成。

在devices目录下有如下节点
/sys/bus/mmc/devices/mmc0:5048
其中mmc0:5048就是mmc core抽象出来的card设备,对应于我们板子上的sd。
对应代码参考mmc_alloc_card & mmc_add_card。

在drivers目录下有如下节点
/sys/bus/mmc/drivers/mmcblk
其中mmcblk就是block.c中实现的card driver。
对应代码参考mmc_register_driver。
在devices目录下有如下节点
/sys/bus/sdio/devices/mmc1:0001:1
其中mmc1:0001:1就是mmc core抽象出来的card设备,对应于我们板子上的sdio wifi。
对应代码参考mmc_alloc_card & mmc_add_card。

在drivers目录下有如下节点
/sys/bus/sdio/drivers/rtl8189fs

host的class节点

  mmc core实现了一个class用于维护和管理mmc host。其对应路径为/sys/class/mmc_host。mmc core会为每个注册到mmc core中的mmc host在该class目录下添加一个对应的节点。在mmc_add_host中生成。
示例如下:

创建class的代码参考mmc_register_host_class


在/sys/class/mmc_host下有如下目录:
/sys/class/mmc_host/mmc0 
/sys/class/mmc_host/mmc1
mmc0就是对应alias序号为0的host,而mmc1就是对应alias序号为1的host。 具体代码参考mmc_alloc_host。


/sys/class/mmc_host/mmc0下有如下属性:
device     mmc0:5048  power      subsystem  uevent

/sys/class/mmc_host/mmc1下有如下属性:
device     mmc1:0001  power      subsystem  uevent

card对应的sys节点

mmc core把mmc设备抽象为card设备。
从两个地方可以找到其对应的sys节点。
简单示例如下:

以mmc0:5048设备为例,mmc0表示这个card挂载mmc0这个host上,0001表示card设备地址为5048(也就是RCA,协议的东西,后续会说明)
(1)/sys/bus/mmc/devices/mmc0:5048(因为是挂在mmc bus上)
(2)/sys/class/mmc_host/mmc0/mmc0:5048(因为card的parent device为mmc host的class device)
具体代码参考mmc_alloc_card & mmc_add_card。

其有如下属性:
block                 hwrev                 scr
cid                   manfid                serial
csd                   name                  ssr
date                  ocr                   subsystem
driver                oemid                 type
dsr                   power                 uevent
erase_size            preferred_erase_size
fwrev                 rca

debug节点

  mmc core为每个注册到core中的host创建了对应的debug节点。
  以mmc0这个host为例,其对应节点路径为/sys/kernel/debug/mmc0。

/sys/kernel/debug/mmc0有如下属性:
caps       caps2      clock      ios        mmc0:5048
具体代码参考mmc_add_host——》mmc_add_host_debugfs


mmc0:5048下有如下debug属性: 
state   status

源码分析

源码路径:drivers/mmc/core/core.c

static int __init mmc_init(void)
{
	int ret;

	ret = mmc_register_bus();//注册mmc bus
	if (ret)
		return ret;

	ret = mmc_register_host_class(); //注册mmc_host class
	if (ret)
		goto unregister_bus;

	ret = sdio_register_bus();  //注册sdio bus
	if (ret)
		goto unregister_host_class;

	return 0;

unregister_host_class:
	mmc_unregister_host_class();
unregister_bus:
	mmc_unregister_bus();
	return ret;
}

static void __exit mmc_exit(void)
{
	sdio_unregister_bus();
	mmc_unregister_host_class();
	mmc_unregister_bus();
}

subsys_initcall(mmc_init);
module_exit(mmc_exit);

MODULE_LICENSE("GPL");

mmc bus注册:
源码路径:drivers/mmc/core/bus.c

static struct bus_type mmc_bus_type = {
	.name		= "mmc",
	.dev_groups	= mmc_dev_groups,
	.match		= mmc_bus_match,
	.uevent		= mmc_bus_uevent,
	.probe		= mmc_bus_probe,
	.remove		= mmc_bus_remove,
	.shutdown	= mmc_bus_shutdown,
	.pm		= &mmc_bus_pm_ops,
};

int mmc_register_bus(void)
{
	return bus_register(&mmc_bus_type);
}

sdio bus注册:
源码路径:drivers/mmc/core/sdio_bus.c

static struct bus_type sdio_bus_type = {
	.name		= "sdio",
	.dev_groups	= sdio_dev_groups,
	.match		= sdio_bus_match,
	.uevent		= sdio_bus_uevent,
	.probe		= sdio_bus_probe,
	.remove		= sdio_bus_remove,
	.pm		= &sdio_bus_pm_ops,
};

int sdio_register_bus(void)
{
	return bus_register(&sdio_bus_type);
}

mmc_host class注册:
源码路径:drivers/mmc/core/host.c

static struct class mmc_host_class = {
	.name		= "mmc_host",
	.dev_release	= mmc_host_classdev_release,
};

int mmc_register_host_class(void)
{
	return class_register(&mmc_host_class);
}


这篇关于Linux驱动——mmc概念与框架(一)的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程