声明:本文很多内容和思路参考了http://www.wowotech.net/comm/mmc_host_driver.html,对原作者表示感谢!

1.前言

本文是Linux MMC framework的第二篇,将介绍host对象的基本结构和相应的操作

2.主要数据结构和API

2.1 struct mmc_host

Elemete Name struct mmc_host
Path include/linux/mmc/host.h
Responsiblities

mmc core使用struct mmc_host来抽象mmc host controller

Attributions
  • parent : struct device *类型,指向该mmc host的父设备,一般为注册此mmc_host的platform device
  • class_dev:一个struct device类型的变量,是该MMC host在设备模型中作为一个“设备”的体现。当然,人如其名,该设备从属于某一个class(mmc_host_class)
  • index:该mmc_host的索引号,因为有可能有多个mmc host controller
  • ops:struct mmc_host_ops *类型的指针,包含了此mmc_host所有的操作函数集,见struct mmc_host_ops结构体描述
  • f_min、f_max、f_init,该MMC host支持的时钟频率范围,最小频率、最大频率以及初始频率
  • ocr_avail:通常的OCR电压范围
  • ocr_avail_sdio、ocr_avail_sd、ocr_avail_mmc:sdio sd mmc特定的电压范围
  • pm_notify:struct notifier_block类型,电源管理相关的notify
  • max_current_330/max_current_300/max_current_180:支持的最大电流
  • mmcid:
  • caps:host所具备的能力
  • caps2:host所具备的其它功能
  • pm_caps:mmc_pm_flag_t类型,支持的pm特性
  • clk_requests:
  • clk_delay:
  • clk_gated:clk是否已经开启了
  • clk_gate_work:struct delayed_work类型
  • clk_old:
  • clk_lock:spinlock_t 类型,对clk相关临界资源保护
  • clk_gate_mutex:struct mutex,保护clk gate的排它锁
  • clkgate_delay_attr:struct device_attribute类型
  • clkgate_delay:
  • max_seg_size:一个segment最大为多少字节
  • max_segs:最多支持多少segments
  • unused:
  • max_req_size:一个request的最大字节个数
  • max_blk_size:一个mmc block的最大大小
  • max_blk_count:一个request的最大block数目
  • max_discard_to:最大的discard超时时间(ms)
  • lock:spinlock_t类型mmc的互斥保护
  • ios:struct mmc_ios类型,当前的io总线设置
  • ocr:当前的操作电压设置
  • use_spi_crc:
  • claimed:host排他声明
  • bus_dead:总线是否被释放
  • removed:host是否被移除了
  • rescan_disable:是否禁用卡检测,一般初始时禁用,ready后才使能
  • rescan_entered:用于非可移除式设备
  • card:struct mmc_card *类型,用于连接到这个host的设备
  • wq:wait_queue_head_t类型,work队列
  • claimer:struct task_struct *类型,host声明的task
  • claim_cnt:"claim" nesting count
  • detect:struct delayed_work 类型,用于检测卡的work线程
  • detect_wake_lock:struct wake_lock
  • detect_change:card detect flag
  • slot:struct mmc_slot类型;
  • bus_ops:struct mmc_bus_ops *类型, current bus driver
  • bus_refs:reference counter
  • bus_resume_flags:
  • sdio_irqs:
  • sdio_irq_thread:struct task_struct *类型
  • sdio_irq_pending:
  • sdio_irq_thread_abort:atomic_t类型
  • pm_flags:mmc_pm_flag_t 类型,请求的pm特性
  • led:struct led_trigger *类型
  • regulator_enabled:regulator状态
  • supply:struct mmc_supply类型
  • debugfs_root:struct dentry *类型,用于在debugfs中显示相应节点
  • areq:struct mmc_async_req *类型,  /* active async req */
  • context_info:struct mmc_context_info类型,; /* async synchronization info */
  • fail_mmc_request:struct fault_attr类型
  • actual_clock:Actual HC clock rate
  • slotno:used for sdio acpi binding
  • private:一个0长度的数组,可以在mmc_alloc_host时指定长度,由host controller driver自行支配
Operations
  • struct mmc_host *mmc_alloc_host(int extra, struct device *dev)

分配一个mmc_host结构体,并对其进行初始化

  • int mmc_add_host(struct mmc_host *host)

将host device注册进设备驱动模型,并做host硬件的初始化,向PM core 注册notify, 在本函数完成之前,必须能保证host可以使用

  • void mmc_remove_host(struct mmc_host *host)

将host device从设备驱动模型移除,并将所有的卡与bus切断连接,向pm core注销notify,将mmc bus掉电

  • void mmc_free_host(struct mmc_host *host)

释放mmc_host结构体

  • int mmc_power_save_host(struct mmc_host *host)

对host掉电处理

  • int mmc_power_restore_host(struct mmc_host *host)

恢复host上电

  • void mmc_detect_change(struct mmc_host *host, unsigned long delay)

检测mmc卡的状态

  • void mmc_request_done(struct mmc_host *host, struct mmc_request *mrq)

mmc host在处理完一次request后需要调用此函数来进行后处理

  • static inline void mmc_signal_sdio_irq(struct mmc_host *host)
  • void sdio_run_irqs(struct mmc_host *host);
  • int mmc_regulator_get_ocrmask(struct regulator *supply)

返回支持的操作电压范围

  • int mmc_regulator_set_ocr(struct mmc_host *mmc, struct regulator *supply, unsigned short vdd_bit);

设置regulator以匹配操作电压

  • int mmc_regulator_set_vqmmc(struct mmc_host *mmc, struct mmc_ios *ios)
  • int mmc_regulator_get_supply(struct mmc_host *mmc)

通过device tree获取vcc和vccq

  • int mmc_pm_notify(struct notifier_block *notify_block, unsigned long mode, void *unused)

用于pm在suspend时做卡移除操作

  • static inline int mmc_card_is_removable(struct mmc_host *host)

卡是否被移除

  • static inline int mmc_card_keep_power(struct mmc_host *host)

卡在suspend时是否仍然保持供电

  • static inline int mmc_card_wake_sdio_irq(struct mmc_host *host)

sdio中断来时是否会唤醒休眠的系统

  • static inline int mmc_host_cmd23(struct mmc_host *host)

是否支持CMD23

  • static inline int mmc_boot_partition_access(struct mmc_host *host)

是否支持从boot分区访问

  • static inline int mmc_host_uhs(struct mmc_host *host)

返回host支持的访问速率

  • static inline int mmc_host_packed_wr(struct mmc_host *host)
  • static inline int mmc_card_hs(struct mmc_card *card)
  • static inline int mmc_card_uhs(struct mmc_card *card)
  • static inline bool mmc_card_hs200(struct mmc_card *card)
  • static inline bool mmc_card_ddr52(struct mmc_card *card)
  • static inline bool mmc_card_hs400(struct mmc_card *card)
  • void mmc_retune_timer_stop(struct mmc_host *host)
  • static inline void mmc_retune_needed(struct mmc_host *host)
  • static inline void mmc_retune_recheck(struct mmc_host *host)

2.2 struct mmc_host_ops

Elemete Name struct mmc_host_ops
Path include/linux/mmc/host.h
Responsiblities

主要包含了host contrller 所需要实现的操作

Attributions
  • post_req/pre_req:是为了支持双buffer的请求(一个请求正在处理,同时准备另一个请求)
  • request:用来处理一次transfer request

如下的函数可能会sleep,不能在中断上下文中调用:

  • set_ios:
  • get_ro:获取卡的读写状态,返回0表示可读写卡,返回1表示只读卡,返回-ENOSYS表示不支持,返回其它的负值表示其它错误发生
  • get_cd:返回0表示卡未连接,返回1表示卡有连接,返回-ENOSYS表示不支持,返回其它的负值表示其它错误发生
  • enable_sdio_irq:
  • init_card:
  • start_signal_voltage_switch:
  • card_busy:
  • execute_tuning:根据SD和eMMC卡的不同,调节tuning命令操作码值
  • select_drive_strength:设定驱动能力
  • hw_reset:对device执行reset操作
  • card_event:
  • multi_io_quirk
Operations

2.3 struct mmc_ios

Elemete Name struct mmc_ios
Path include/linux/mmc/host.h
Responsiblities
Attributions

clock:

vdd:

bus_mode:command输出模式,opendrain or pushpull

chip_select:用于SPI片选

power_mode:power supply mode

bus_width:

timing:时序

signal_voltage:信号电压

drv_type:

Operations

3. 主要流程

3.1 mmc_add_host

mmc_add_host->

  mmc_start_host->

    mmc_detect_change->

      mmc_rescan->

        mmc_rescan_try_freq->

          mmc_attach_mmc

  • mmc_add_host
一般在xxx_mmc_probe中执行mmc_add_host来对sd进行注册并完成相应的初始化
  • mmc_start_host
mmc_start_host会调用mmc_detect_change会启动detect的work线程来做mmc检测,对应的线程处理函数为mmc_rescan
  • mmc_rescan
对一些边界情况进行处理:
a)如果卡检测禁用了,则直接退出;
b)如果是不可移除的卡,如贴片的eMMC;,则只检测一次退出;
c)如果定义了总线的bus_ops->detect函数,则执行之; 如果host的bus被移除了,就为用户空间准备一把超时锁,为做相关处理争取时间;
调用mmc_bus_put来尝试释放总线,即将host->bus_ops 标记为 NULL;
如果host->bus_ops 不为NULL,说明卡在线,已经扫描过,直接退出;
通过调用host->ops->get_cd来获取卡在线状态,如果不在线作相应处理:mmc_power_off和mmc_release_host;
除去上面几种特殊情况,说明是首次扫描卡,则通过调用mmc_rescan_try_freq进行卡扫描
  • mmc_rescan_try_freq
将按照如下的几种频率来对卡进行扫描:
static const unsigned freqs[] = { , , , };
mmc_power_up:主要分两阶段MMC_POWER_UP完成给卡的上电,MMC_POWER_ON完成时钟设置以及对模块CLK EN的使能;
mmc_hw_reset_for_init:对卡做reset(主要是对eMMC卡);
sdio_reset:发送CMD52给SDIO卡作reset,SD/eMMC会忽略这个命令;
mmc_go_idle:发送CMD0,命令的flags一般包括了response类型和CMD类型,对于非SPI模式需要将D3设置为高电平,以防进入SPI模式;arg为0,进入IDLE模式。
这里是按照如下的顺序来进行扫描:SDIO SD MMC
以emmc检测为例,因此扫描时会调用回调mmc_attach_mmc()
  • mmc_attach_mmc
主要完成card的初始化(一般是identification mode下),并通过mmc_add_card将mmc_card注册到mmc bus,这样就触发了执行前文所述的mmc_blk_probe函数

TODO

Linux MMC framework2:基本组件之host的更多相关文章

  1. Linux MMC framework2:基本组件之core

    1.前言 本文主要core组件的主要流程,在介绍的过程中,将详细说明和core相关的流程,涉及到其它组件的详细流程再在相关文章中说明. 2.主要数据结构和API TODO 3. 主要流程 3.1 mm ...

  2. Linux mmc framework2:基本组件之block

    1.前言 本文主要block组件的主要流程,在介绍的过程中,将详细说明和block相关的流程,涉及到其它组件的详细流程再在相关文章中说明. 2.主要数据结构和API 2.1 struct mmc_ca ...

  3. Linux mmc framework2:基本组件之queue

    1.前言 本文主要介绍card下queue组件的主要流程,在介绍的过程中,将详细说明和queue相关的流程,涉及到其它组件的详细流程再在相关文章中说明. 2.主要数据结构和API 2.1 struct ...

  4. Linux mmc framework2:基本组件之mmc

    1.前言 本文主要mmc组件的主要流程,在介绍的过程中,将详细说明和mmc相关的流程,涉及到其它组件的详细流程再在相关文章中说明. 2.主要数据结构和API TODO 3. 主要流程 3.1 mmc_ ...

  5. Linux mmc framework1:软件架构

    [部分内容来自] http://www.wowotech.net/comm/mmc_framework_arch.html 1. 前言 由eMMC基础技术1:MMC简介中MMC.SD.SDIO的介绍可 ...

  6. [MMC]Linux MMC/SD/SDIO驱动分析

    转自:http://www.cnblogs.com/cslunatic/p/3678045.html 一.SD/MMC/SDIO概念区分 SD(SecureDigital)与 MMC(Multimed ...

  7. linux驱动基础系列--Linux mmc sd sdio驱动分析

    前言 主要是想对Linux mmc子系统(包含mmc sd sdio)驱动框架有一个整体的把控,因此会忽略某些细节,同时里面涉及到的一些驱动基础,比如平台驱动.块设备驱动.设备模型等也不进行详细说明原 ...

  8. (linux)MMC 卡驱动分析

    最近花时间研究了一下 MMC 卡驱动程序,开始在网上找了很多关于 MMC 卡驱动的分析文章,但大都是在描述各个层,这对于初学者来讲帮助并不大,所以我就打算把自己的理解写下来,希望对大家有用.个人觉得理 ...

  9. Linux MMC 驱动子系统简述(源码剖析)

    1. Linux MMC 驱动子系统 块设备是Linux系统中的基础外设之一,而 MMC/SD 存储设备是一种典型的块设备.Linux内核设计了 MMC子系统,用于管理 MMC/SD 设备. MMC ...

随机推荐

  1. 获取外网出口ip

    curl ifconfig.me 或 curl cip.cc

  2. [luogu5002]专心OI - 找祖先

    [传送门] 我们还是先将一下算法的步骤,待会再解释起来方便一点. 算法步骤 首先我们算出每个子树的\(size\). 我们就设当前访问的节点 然后我们就得到了当前这个节点的答案是这个树整个的\(siz ...

  3. cf379F New Year Tree (树的直径+倍增lca)

    可以证明,如果合并两棵树,新的直径的端点一定是原来两树中直径的端点 可以把新加两个点的操作看成是把两个只有一个点的树合并到原来的树上,然后用其中的一个点去和原来树上的直径两端点更新直径就可以了 #in ...

  4. bzoj1001/luogu4001 狼抓兔子 (最小割/平面图最小割转对偶图最短路)

    平面图转对偶图:先在原图中加一个s->t的边,然后对每个面建一个点,对每条分隔两个面的边加一条连接这两个面对应点的边,边权等于原边权. 然后从刚才加的s->t分割出来的两面对应的两个点跑最 ...

  5. bzoj1597/luogu2900 土地购买 (斜率优化dp)

    首先按x从小到大排序,那么可得: f[i]=min{f[j]+x[i]*maxy[j+1..i]} 然而这样是$O(n^2)$的而且无法做优化. 然后我们考虑:如果对于某一点,存在另一点的x和y都比它 ...

  6. 震惊!1MB == 1000KB??

    稍微对电脑了解一点的同学可能都知道,电脑中的单位换算是: 1KB = 1024B 1MB = 1024KB 1GB = 1024MB ... 以前,我也是这么认为的.... 最近我在Linux解压某个 ...

  7. 【洛谷P1144】最短路计数

    题目大意:给定一个 N 个点,M 条边的无向无权图,求从 1 号点出发到其他每个点最短路的条数. 题解:在跑 dij 时顺便维护 cnt[ ] 数组,用来记录到每个点的最短路条数. 代码如下 #inc ...

  8. java NIO 直接与非直接缓冲区

    ByteBuffer有两个创建缓冲区的方法:static ByteBuffer allocate(int capacity)static ByteBuffer allocateDirect(int c ...

  9. 2018 ACM 网络选拔赛 南京赛区

    A. An Olympian Math Problem #include <cstdio> #include <cstdlib> #include <cmath> ...

  10. 远程升级云服务器系统 CentOS 6.x 至 CentOS 7.x

    由于docker-ce不再支持centos6,所以觉得吧系统升级为centos7,以下是踩坑的过程 1.添加源 /etc/yum.repos.d/upgrade.repo [upgrade] name ...